{"version":3,"sources":["../src/catalog.ts"],"sourcesContent":["// The method catalog (UI_AS_APPS_SPEC §5.5) — the app's own grant-filtered RPC\n// surface, and a generic way to call it. The host advertises exactly the methods\n// this app may invoke (MCP-tool-shaped); `invoke()` calls one by its catalog name.\n// Handing the catalog to an embedded agent as its tool list confines the agent to\n// the app's authority (agent sandboxing falls out of the capability model, §5.9).\nimport { protocolRequest, sendMessage, addListener } from './sandboxUtils';\nimport { throwOnRefusal } from './protocolRefusal';\nimport type { StreamFrame, StreamTransport } from './protocolStream';\nimport { consumeStream } from './protocolStream';\nimport { createPushChannel } from './pushChannel';\nimport { API_CATALOG, REQUEST_API_CATALOG } from './generated/protocol';\n\n/** One advertised method, as the host generated it from its gate table. */\nexport interface ApiMethod {\n  /** Catalog name, `protocol-` stripped — e.g. `spaces:invite`, `contribute:run`. */\n  name: string;\n  /** The capability this method requires (already held — it's in your catalog). */\n  capability: string;\n  /** True when the method STREAMS (use {@link invokeStream}) vs. single-reply. */\n  stream?: boolean;\n  /**\n   * JSON Schema for the method's single object argument, when the host declares one.\n   * Self-describes the call so a catalog-as-tools bridge (an embedded agent) can\n   * advertise the real param shape — e.g. that `authoring:typecheck` takes a nested\n   * `{ files: [{ path, content }] }` array — instead of a permissive \"any object\".\n   * Absent for methods the host advertises without a schema.\n   */\n  paramsSchema?: Record<string, unknown>;\n}\n\n// `scheme:method` → ['scheme', 'method'] (the wire protocol is `protocol-scheme`).\nconst split = (name: string): [string, string] => {\n  const i = name.indexOf(':');\n  if (i <= 0) throw new Error(`invalid catalog method name: ${name}`);\n  return [name.slice(0, i), name.slice(i + 1)];\n};\n\n/**\n * Call a catalog method by name — `invoke('spaces:invite', { spaceId, login, role })`.\n * A thin generic over the host protocol: the host validates params and gates the\n * call (an un-granted method → `forbidden`, even if you name it directly). For a\n * STREAMING method (`ApiMethod.stream`), use {@link invokeStream}.\n */\nexport const invoke = async <T = unknown>(name: string, params: Record<string, unknown> = {}): Promise<T> => {\n  const [scheme, method] = split(name);\n  // The host replies with an `{ ok, data } | { ok:false, code }` envelope; unwrap\n  // it and THROW on refusal (a `.code` like `forbidden` for an off-catalog call)\n  // so callers — and any agent driving `invoke` — see the gate's verdict.\n  const res = (await protocolRequest(scheme, method, [params])) as\n    | { ok: true; data: unknown }\n    | { ok: false; code?: string; message?: string; retryAfter?: unknown }\n    | undefined;\n  // R3-1089: folded onto the shared helper (the last inline unwrap; it stayed out\n  // until the helper learned retryAfter — R3-954's rate-limit wait rides it now).\n  throwOnRefusal(res, `${name} failed`);\n  return res.data as T;\n};\n\n// Stream transport over the resolver (SDK_PACKAGING_SPEC §4) — sendMessage /\n// addListener route through `transport()` (injected bundler messageBus or the §4\n// global), never `bundler.messageBus` directly.\nconst streamTransport: StreamTransport = {\n  send: (msg) => sendMessage(msg.type, msg as unknown as Record<string, unknown>),\n  subscribe: (type, handler) => addListener(type, (msg) => handler(msg as { msgId?: number; stream?: StreamFrame })),\n  // Early-cancel: route a `{type, msgId, cancel:true}` frame back to the host so it\n  // aborts the in-flight generation (and, for `llm:chat`, stops billing) — §3.3.\n  cancel: (msg) => sendMessage(msg.type, msg as unknown as Record<string, unknown>),\n};\n\n/** Call a STREAMING catalog method by name, yielding its events. Pass `signal` to\n *  abort mid-stream: the host stops generating and (for `llm:chat`) stops billing. */\nexport function invokeStream<T = unknown, R = unknown>(\n  name: string,\n  params: Record<string, unknown> = {},\n  signal?: AbortSignal,\n): AsyncGenerator<T, R, void> {\n  const [scheme, method] = split(name);\n  return consumeStream<T, R>(streamTransport, `protocol-${scheme}`, method, [params], undefined, signal);\n}\n\n// The catalog list is read over the transport (§4): the host pushes `api-catalog`\n// and answers `request-api-catalog` with this app's grant-filtered methods (wire\n// format: site-main channelBridge.ts).\nconst channel = createPushChannel<ApiMethod[]>({\n  pushType: API_CATALOG,\n  requestType: REQUEST_API_CATALOG,\n  initial: [],\n  parse: (msg) => (Array.isArray(msg.methods) ? (msg.methods as ApiMethod[]) : undefined),\n});\n\n/** The methods this app may call (grant-filtered, §5.5). Poll for a one-off read;\n *  use {@link onCatalogChange} / {@link useCatalog} to react. */\nexport const getCatalog = (): ApiMethod[] => channel.get();\n\n/** Subscribe to catalog changes (e.g. a grant added/revoked). Invoked immediately\n *  with the current catalog, then on every change. Returns an unsubscribe fn. */\nexport const onCatalogChange = (listener: (catalog: ApiMethod[]) => void): (() => void) => channel.onChange(listener);\n\n/** React hook returning this app's method catalog, re-rendering on change. Hand\n *  it to an embedded agent as its tool list to confine the agent to the app's\n *  authority (§5.9). */\nexport const useCatalog = (): ApiMethod[] => channel.use();\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,0BAA0D;AAC1D,6BAA+B;AAE/B,4BAA8B;AAC9B,yBAAkC;AAClC,sBAAiD;AAqBjD,MAAM,QAAQ,CAAC,SAAmC;AAChD,QAAM,IAAI,KAAK,QAAQ,GAAG;AAC1B,MAAI,KAAK,EAAG,OAAM,IAAI,MAAM,gCAAgC,IAAI,EAAE;AAClE,SAAO,CAAC,KAAK,MAAM,GAAG,CAAC,GAAG,KAAK,MAAM,IAAI,CAAC,CAAC;AAC7C;AAQO,MAAM,SAAS,OAAoB,MAAc,SAAkC,CAAC,MAAkB;AAC3G,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,IAAI;AAInC,QAAM,MAAO,UAAM,qCAAgB,QAAQ,QAAQ,CAAC,MAAM,CAAC;AAM3D,6CAAe,KAAK,GAAG,IAAI,SAAS;AACpC,SAAO,IAAI;AACb;AAKA,MAAM,kBAAmC;AAAA,EACvC,MAAM,CAAC,YAAQ,iCAAY,IAAI,MAAM,GAAyC;AAAA,EAC9E,WAAW,CAAC,MAAM,gBAAY,iCAAY,MAAM,CAAC,QAAQ,QAAQ,GAA+C,CAAC;AAAA;AAAA;AAAA,EAGjH,QAAQ,CAAC,YAAQ,iCAAY,IAAI,MAAM,GAAyC;AAClF;AAIO,SAAS,aACd,MACA,SAAkC,CAAC,GACnC,QAC4B;AAC5B,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,IAAI;AACnC,aAAO,qCAAoB,iBAAiB,YAAY,MAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,QAAW,MAAM;AACvG;AAKA,MAAM,cAAU,sCAA+B;AAAA,EAC7C,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS,CAAC;AAAA,EACV,OAAO,CAAC,QAAS,MAAM,QAAQ,IAAI,OAAO,IAAK,IAAI,UAA0B;AAC/E,CAAC;AAIM,MAAM,aAAa,MAAmB,QAAQ,IAAI;AAIlD,MAAM,kBAAkB,CAAC,aAA2D,QAAQ,SAAS,QAAQ;AAK7G,MAAM,aAAa,MAAmB,QAAQ,IAAI;","names":[]}