/** * Google Docs skill — create / append / read Google Docs from an agent. * * Modelled on notion.js: * - resolveIntegrationToken('google') is the SINGLE auth chokepoint (via * the googleApi() helper below). Don't re-resolve at call sites. The * backend resolver auto-refreshes the ~1h Google access token * server-side, so the skill only ever sees a valid bearer. * - handleToolCall() dispatches the tools and NEVER throws — any HTTP or * parse failure is returned as { ok:false, error } so a missing/broken * Google connection can't crash the run. * * Token shape (GET /integrations/token/google → resolveIntegrationToken): * { provider:'google', token, email, scopes, expiresInSec } * * SCOPE / VISIBILITY (drive.file): * The integration requests ONLY the non-sensitive * https://www.googleapis.com/auth/drive.file scope, which grants per-file * access to files this app CREATED or the user explicitly PICKED (via the * Google Picker). The Docs API's documents.create / documents.get / * documents.batchUpdate all accept drive.file, so create→append→read-back of * our own / picked docs works fully. Reading an arbitrary pre-existing doc * requires the user to PICK it once first (the Picker grants drive.file on * that file). We do NOT request the sensitive documents.readonly scope — * Google's OAuth review rejected it; drive.file + Picker is the sanctioned * path. */ /** * INJECTED-TOKEN fast path (Zibby Copilot per-turn credential injection) + * NON-OWNER SAFETY GATE — the Google twin of linkedin.js injectedPersonalToken. * * The Zibby Copilot is ONE shared chat bot backed by ONE project's * PROJECT_API_TOKEN. resolveIntegrationToken('google') authenticates with that * PAT, so the account is inferred SERVER-SIDE from the PAT — meaning the shared * bot would only ever see the PROJECT OWNER's Google (their readable Docs, their * Drive), never the (different) person who actually sent the chat message. * * Two per-turn env signals, set + restored by the copilot-runtime (a TRUSTED * backend service that already KMS-decrypts tenants' creds directly): * - ZIBBY_INJECTED_GOOGLE_TOKEN (+ _EMAIL): the EMAIL-VERIFIED sender's OWN * `google` integration access token (auto-refreshed server-side). When * present it takes PRECEDENCE over resolveIntegrationToken, so every gdocs * call runs against the SENDER's own Google. * - ZIBBY_SENDER_IS_NON_OWNER=1: the verified sender's account differs from * the PAT/tenant account. With NO injected token this is a HARD REFUSAL * gate: the skill must NEVER fall through to the owner's token on a * colleague's behalf (privacy: the owner's readable docs would be exposed * and created docs would land in the owner's Drive). Every tool returns * { ok:false, error } telling the sender to connect their own Google. * * Absent both (owner/self turns, Fargate workflows, self-host — no * sender-identity context) → the normal PAT chokepoint runs unchanged. */ export declare function injectedGoogleToken(): { token: string; email: string; }; /** True when the runtime flagged this turn's verified sender as NOT the tenant owner. */ export declare function senderIsNonOwner(): boolean; /** * STRICT CHAT-TURN INVARIANT (fail-CLOSED) — ZIBBY_CHAT_STRICT_PERSONAL=1. * * Set UNCONDITIONALLY by the Copilot runtime for EVERY chat turn (Slack + * Lark, owner or not). Under it, personal-tier providers (google here) must * NEVER fall through to the PAT-resolved project-owner token: the ONLY * accepted credential is the per-turn injected sender token * (ZIBBY_INJECTED_GOOGLE_TOKEN — the runtime injects the OWNER's own Google * through the same path, so the owner keeps working). No injected token → * HARD REFUSE, for ANY sender: verified non-owners, same-account colleagues, * UNVERIFIED senders (users.info failure / no email match — the exact class * the old ZIBBY_SENDER_IS_NON_OWNER flag failed OPEN on), and even the owner * when their own Google isn't connected. The non-owner flag stays as * belt-and-braces; this strict flag is the primary gate. * * Absent both flags (Fargate workflows, self-host, direct tool use — no chat * sender context) → the normal PAT chokepoint runs unchanged. */ export declare function chatStrictPersonal(): boolean; export declare const NON_OWNER_REFUSAL = "You haven't connected your own Google account \u2014 connect it at https://studio.zibby.dev/integrations (Google Docs). For privacy, I can't use anyone else's Google (including the project owner's) on your behalf."; /** * Extract a Google Docs document id from a raw id OR a Docs URL * (https://docs.google.com/document/d//edit...). Returns the id string * or null. */ export declare function parseDocId(ref: any): string; export declare function googleApi(url: any, opts?: any): Promise; /** * Parse ONE markdown line's inline marks (bold `**x**`, links `[t](u)`, * inline code `` `x` ``) into { text, styles } where `styles` are ranges * RELATIVE to the returned plain text. */ export declare function parseInlineMarkdown(line: any): { text: string; styles: any[]; }; /** * Convert a small, common subset of markdown (headings #/##/###, bullet * lists -/*, numbered lists `1.`, bold, links, inline code) into Google Docs * batchUpdate requests that insert the content at `startIndex`. * * Strategy: ONE insertText request carrying the whole plain text (every line * newline-terminated → each becomes its own paragraph), followed by * updateParagraphStyle (headings), createParagraphBullets (consecutive list * runs) and updateTextStyle (bold/link/code) requests over the computed * ranges. Indices are UTF-16 code units — JS string .length matches the Docs * API's index space exactly. * * Returns { requests, endIndex }. Plain text (no markdown) passes through as * plain paragraphs — the converter is safe for the `text` input too. */ export declare function markdownToRequests(markdown: any, startIndex: any): { requests: any[]; endIndex: any; }; /** * Flatten a documents.get body into plain text (paragraph text runs joined, * newline-separated — table cells + nested content included via recursion). * Bounded by MAX_TEXT_CHARS. */ export declare function extractPlainText(body: any): string; export declare const googleDocsSkill: any;