@athenaintel/react 0.32.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -9
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +2 -3
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -4
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
- package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
- package/dist/agent-runtime/src/edit-command.js.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +4 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.js +4 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +57 -2
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.js +57 -2
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +24 -3
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js +24 -3
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.cjs +4 -13
- package/dist/agent-runtime/src/statewire-transport.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.js +5 -14
- package/dist/agent-runtime/src/statewire-transport.js.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +12 -1
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +12 -1
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
- package/dist/assets/AthenaAssetEmbed.cjs +3 -1
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +7 -0
- package/dist/assets/AthenaAssetEmbed.js +4 -2
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/use-asset-embed.cjs +71 -71
- package/dist/assets/use-asset-embed.cjs.map +1 -1
- package/dist/assets/use-asset-embed.d.ts +20 -7
- package/dist/assets/use-asset-embed.js +72 -72
- package/dist/assets/use-asset-embed.js.map +1 -1
- package/dist/catalog/agent-mode-menu.cjs +115 -0
- package/dist/catalog/agent-mode-menu.cjs.map +1 -0
- package/dist/catalog/agent-mode-menu.d.ts +101 -0
- package/dist/catalog/agent-mode-menu.js +115 -0
- package/dist/catalog/agent-mode-menu.js.map +1 -0
- package/dist/catalog/agent-model-options.cjs +122 -0
- package/dist/catalog/agent-model-options.cjs.map +1 -0
- package/dist/catalog/agent-model-options.d.ts +115 -0
- package/dist/catalog/agent-model-options.js +122 -0
- package/dist/catalog/agent-model-options.js.map +1 -0
- package/dist/catalog/chat-pickers.cjs +235 -4
- package/dist/catalog/chat-pickers.cjs.map +1 -1
- package/dist/catalog/chat-pickers.d.ts +55 -3
- package/dist/catalog/chat-pickers.js +238 -7
- package/dist/catalog/chat-pickers.js.map +1 -1
- package/dist/catalog/runtime-catalog.cjs +121 -3
- package/dist/catalog/runtime-catalog.cjs.map +1 -1
- package/dist/catalog/runtime-catalog.d.ts +120 -0
- package/dist/catalog/runtime-catalog.js +124 -6
- package/dist/catalog/runtime-catalog.js.map +1 -1
- package/dist/catalog/use-athena-chat-mode.cjs +139 -0
- package/dist/catalog/use-athena-chat-mode.cjs.map +1 -0
- package/dist/catalog/use-athena-chat-mode.d.ts +43 -0
- package/dist/catalog/use-athena-chat-mode.js +139 -0
- package/dist/catalog/use-athena-chat-mode.js.map +1 -0
- package/dist/chat/AthenaChat.cjs +2 -0
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +8 -7
- package/dist/chat/AthenaChat.js +2 -0
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +30 -3
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +12 -9
- package/dist/chat/super-grouping/SuperGroupingCard.js +31 -4
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.d.ts +8 -8
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +4 -4
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +6 -5
- package/dist/chat/super-grouping/toolkit-map.cjs +3 -1
- package/dist/chat/super-grouping/toolkit-map.cjs.map +1 -1
- package/dist/chat/super-grouping/toolkit-map.js +3 -1
- package/dist/chat/super-grouping/toolkit-map.js.map +1 -1
- package/dist/chat-ui/index.cjs +1 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +1 -1
- package/dist/chat-ui/index.js +2 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +33 -2
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +14 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js +33 -2
- package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
- package/dist/chat-ui/statewire.cjs +3 -0
- package/dist/chat-ui/statewire.cjs.map +1 -1
- package/dist/chat-ui/statewire.d.ts +4 -2
- package/dist/chat-ui/statewire.js +3 -0
- package/dist/chat-ui/statewire.js.map +1 -1
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/use-athena-rest-query.cjs +4 -0
- package/dist/lib/use-athena-rest-query.cjs.map +1 -1
- package/dist/lib/use-athena-rest-query.d.ts +6 -0
- package/dist/lib/use-athena-rest-query.js +4 -0
- package/dist/lib/use-athena-rest-query.js.map +1 -1
- package/dist/provider/AthenaProvider.cjs +81 -9
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +25 -5
- package/dist/provider/AthenaProvider.js +83 -11
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/agent-selection-context.cjs +6 -0
- package/dist/provider/agent-selection-context.cjs.map +1 -0
- package/dist/provider/agent-selection-context.d.ts +14 -0
- package/dist/provider/agent-selection-context.js +6 -0
- package/dist/provider/agent-selection-context.js.map +1 -0
- package/dist/provider/chat-mode-context.cjs +6 -0
- package/dist/provider/chat-mode-context.cjs.map +1 -0
- package/dist/provider/chat-mode-context.d.ts +35 -0
- package/dist/provider/chat-mode-context.js +6 -0
- package/dist/provider/chat-mode-context.js.map +1 -0
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs +125 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.d.ts +54 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js +125 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js.map +1 -0
- package/dist/runtime/statewire-model-lane.cjs +0 -12
- package/dist/runtime/statewire-model-lane.cjs.map +1 -1
- package/dist/runtime/statewire-model-lane.d.ts +3 -1
- package/dist/runtime/statewire-model-lane.js +0 -12
- package/dist/runtime/statewire-model-lane.js.map +1 -1
- package/dist/runtime/statewire-run-config.cjs +10 -6
- package/dist/runtime/statewire-run-config.cjs.map +1 -1
- package/dist/runtime/statewire-run-config.d.ts +7 -0
- package/dist/runtime/statewire-run-config.js +10 -6
- package/dist/runtime/statewire-run-config.js.map +1 -1
- package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
- package/dist/runtime/statewire-server-lane-context.d.ts +2 -2
- package/dist/runtime/statewire-server-lane-context.js.map +1 -1
- package/dist/runtime/statewire-thread-config-lane.cjs +84 -0
- package/dist/runtime/statewire-thread-config-lane.cjs.map +1 -0
- package/dist/runtime/statewire-thread-config-lane.d.ts +94 -0
- package/dist/runtime/statewire-thread-config-lane.js +84 -0
- package/dist/runtime/statewire-thread-config-lane.js.map +1 -0
- package/dist/runtime/useAthenaStatewireRuntime.cjs +4 -2
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.js +4 -2
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/threads/use-athena-thread-model.cjs +11 -3
- package/dist/threads/use-athena-thread-model.cjs.map +1 -1
- package/dist/threads/use-athena-thread-model.d.ts +5 -0
- package/dist/threads/use-athena-thread-model.js +12 -4
- package/dist/threads/use-athena-thread-model.js.map +1 -1
- package/package.json +3 -3
- package/dist/runtime/StatewireModelLaneSync.cjs +0 -96
- package/dist/runtime/StatewireModelLaneSync.cjs.map +0 -1
- package/dist/runtime/StatewireModelLaneSync.d.ts +0 -45
- package/dist/runtime/StatewireModelLaneSync.js +0 -96
- package/dist/runtime/StatewireModelLaneSync.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-run-config.js","sources":["../../src/runtime/statewire-run-config.ts"],"sourcesContent":["/** Runtime marker the deep-agent session substrate stamps on sessions. */\nconst DEEP_AGENT_RUNTIME_MARKER = 'athena_deep_agent';\n\n/** Session-origin channel. The backend clamps unknown values to 'web', which\n * is how every SDK-started session has always classified. */\nconst STATEWIRE_START_CHANNEL = 'web';\n\n/** Session label persisted in the thread's panel config (mirrors\n * 'Athena Chrome' / 'Athena mobile' in the sibling statewire hosts). */\nconst STATEWIRE_RUN_LABEL = 'Athena SDK';\n\n/** Deep-agent default model — matches the Olympus and mobile statewire hosts. */\nexport const DEFAULT_STATEWIRE_MODEL = 'claude-sonnet-5-5';\n\n/** Agent-id namespace for collab agents (`collab_agent:<asset_id>`). */\nexport const COLLAB_AGENT_REF_PREFIX = 'collab_agent:';\n\n/** The only shape the `agent` prop accepts, for error messages and docs. */\nexport const COLLAB_AGENT_REF_SHAPE = 'collab_agent:<asset_id>';\n\n/** The asset id when `agent` is a `collab_agent:<asset_id>` ref, else null. */\nexport function parseCollabAgentRef(agent: string | undefined | null): string | null {\n if (typeof agent !== 'string' || !agent.startsWith(COLLAB_AGENT_REF_PREFIX)) return null;\n const assetId = agent.slice(COLLAB_AGENT_REF_PREFIX.length).trim();\n return assetId || null;\n}\n\n/**\n * Resolve the provider's `agent` prop to a collab-agent asset id.\n *\n * An omitted or blank `agent` means \"no agent selected\" — the thread runs the\n * Athena deep agent — and resolves to `null`. A `collab_agent:<asset_id>` ref\n * resolves to the asset id. Any other non-blank value throws: the statewire\n * host cannot honour it, and a selector that is silently dropped would let a\n * misconfigured deployment ship answers from the wrong agent.\n */\nexport function resolveAgentProp({ agent }: { agent: string | undefined | null }): string | null {\n if (agent === undefined || agent === null || agent.trim() === '') return null;\n const assetId = parseCollabAgentRef(agent.trim());\n if (assetId) return assetId;\n throw new Error(\n `[AthenaSDK] Unsupported \\`agent\\` prop ${JSON.stringify(agent)}. The only accepted shape is '${COLLAB_AGENT_REF_SHAPE}' (the asset id of a published collab agent). Named agents are not supported — the statewire host always runs the Athena deep agent; omit \\`agent\\` to use it.`,\n );\n}\n\nexport interface StatewireRunConfigOptions {\n /** LLM model identifier. Defaults to the deep-agent default model — unless a\n * collab agent is selected and its author set one (the backend overlay\n * applies the agent's model when the run sends none), in which case no\n * model is sent so the agent's choice wins. */\n model?: string;\n /** Agent selector. Only the `collab_agent:<asset_id>` shape is accepted: the\n * run executes AS that published collab agent (prompt, tools, model\n * default). Any other non-empty value throws (see {@link resolveAgentProp}). */\n agent?: string;\n /** Collab-agent channel id (built-in like `email`/`sms`, or a user-defined\n * custom channel id) selecting that channel's configuration overrides.\n * Sent as `collab_channel_id`; only meaningful with a collab `agent`. */\n channel?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier, passed through as app_id. */\n appId?: string;\n /** Client-executed tool declarations, passed through as client_tools. The\n * deep-agent runtime binds each as an interrupt-backed tool the client\n * answers via the statewire client-tool bridge. */\n clientTools?: Record<string, unknown>[];\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n}\n\n/**\n * The model a send carries for the host's `model` and `extraRunConfig`, with\n * the precedence {@link buildStatewireRunConfig} applies: `extraRunConfig` is\n * merged last, so its `model` key (when it has one) wins over the `model`\n * prop. `undefined` when the send carries no explicit model.\n */\nexport function effectiveStatewireModel({\n model,\n extraRunConfig,\n}: {\n model: string | undefined;\n extraRunConfig: Record<string, unknown> | undefined;\n}): string | undefined {\n if (extraRunConfig !== undefined && Object.hasOwn(extraRunConfig, 'model')) {\n const override = extraRunConfig.model;\n return typeof override === 'string' && override !== '' ? override : undefined;\n }\n return model === '' ? undefined : model;\n}\n\n/**\n * Build the `runConfig` a deep-agent statewire run is driven by. Commands\n * travel bare on the statewire channel, so this payload rides the ambient\n * model context (`config.runConfig`) instead of the request body.\n *\n * The flattened `custom` fields drive the run, while `panel_config` carries a\n * minimal panel state the backend persists per thread and replays on the\n * statewire snapshot — so a session started from the SDK stays configured\n * when reopened elsewhere.\n */\nexport function buildStatewireRunConfig(\n options: StatewireRunConfigOptions = {},\n): Record<string, unknown> {\n const collabAgentId = resolveAgentProp({ agent: options.agent });\n const collabChannelId =\n collabAgentId && options.channel?.trim() ? options.channel.trim() : undefined;\n // With a collab agent selected and no explicit model, send NO model: the\n // backend overlay then applies the model the agent's author configured\n // instead of the SDK default overriding it.\n const model = options.model ?? (collabAgentId ? undefined : DEFAULT_STATEWIRE_MODEL);\n const enabledTools = Array.from(\n new Set([...(options.tools ?? []), ...(options.frontendToolIds ?? [])]),\n );\n const systemPrompt = options.systemPrompt?.trim() ?? '';\n\n return {\n custom: {\n runtime: DEEP_AGENT_RUNTIME_MARKER,\n // With a collab channel selected, omit the SDK's own 'web' stamp: the\n // request's explicit start_channel would win over the backend overlay's\n // kind-mapped provenance (a custom SMS channel must stamp 'sms').\n ...(collabChannelId ? {} : { start_channel: STATEWIRE_START_CHANNEL }),\n ...(model ? { model } : {}),\n // An empty list is behavior-identical to an absent key for the parser\n // (both coerce to []), but the collab-agent overlay merges request keys\n // OVER the agent definition — so an explicit empty list would erase the\n // agent's configured tools. Omit it when empty.\n ...(enabledTools.length > 0 ? { enabled_tools: enabledTools } : {}),\n panel_config: {\n // A collab agent's thread with no explicit model names none here\n // either: agora stores this panel on the thread's first run and\n // replays it to every client, and a stored SDK default would show as\n // the session's model while the agent's own model runs.\n ...(model ? { model } : {}),\n enabled_tools: enabledTools,\n system_prompt: systemPrompt,\n run_label: STATEWIRE_RUN_LABEL,\n },\n ...(collabAgentId ? { collab_agent_id: collabAgentId } : {}),\n ...(collabChannelId ? { collab_channel_id: collabChannelId } : {}),\n ...(systemPrompt ? { system_prompt: systemPrompt } : {}),\n ...(options.workbench?.length ? { workbench: options.workbench } : {}),\n ...(options.knowledgeBase?.length\n ? { knowledge_base: options.knowledgeBase }\n : {}),\n ...(options.appId ? { app_id: options.appId } : {}),\n ...(options.clientTools?.length ? { client_tools: options.clientTools } : {}),\n ...(options.extraRunConfig ?? {}),\n },\n };\n}\n"],"names":[],"mappings":"AACA,MAAM,4BAA4B;AAIlC,MAAM,0BAA0B;AAIhC,MAAM,sBAAsB;AAGrB,MAAM,0BAA0B;AAGhC,MAAM,0BAA0B;AAGhC,MAAM,yBAAyB;AAG/B,SAAS,oBAAoB,OAAiD;AACnF,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,WAAW,uBAAuB,EAAG,QAAO;AACpF,QAAM,UAAU,MAAM,MAAM,wBAAwB,MAAM,EAAE,KAAA;AAC5D,SAAO,WAAW;AACpB;AAWO,SAAS,iBAAiB,EAAE,SAA8D;AAC/F,MAAI,UAAU,UAAa,UAAU,QAAQ,MAAM,KAAA,MAAW,GAAI,QAAO;AACzE,QAAM,UAAU,oBAAoB,MAAM,KAAA,CAAM;AAChD,MAAI,QAAS,QAAO;AACpB,QAAM,IAAI;AAAA,IACR,0CAA0C,KAAK,UAAU,KAAK,CAAC,iCAAiC,sBAAsB;AAAA,EAAA;AAE1H;AA0CO,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AACF,GAGuB;AACrB,MAAI,mBAAmB,UAAa,OAAO,OAAO,gBAAgB,OAAO,GAAG;AAC1E,UAAM,WAAW,eAAe;AAChC,WAAO,OAAO,aAAa,YAAY,aAAa,KAAK,WAAW;AAAA,EACtE;AACA,SAAO,UAAU,KAAK,SAAY;AACpC;AAYO,SAAS,wBACd,UAAqC,IACZ;AA9G3B;AA+GE,QAAM,gBAAgB,iBAAiB,EAAE,OAAO,QAAQ,OAAO;AAC/D,QAAM,kBACJ,mBAAiB,aAAQ,YAAR,mBAAiB,UAAS,QAAQ,QAAQ,KAAA,IAAS;AAItE,QAAM,QAAQ,QAAQ,UAAU,gBAAgB,SAAY;AAC5D,QAAM,eAAe,MAAM;AAAA,IACzB,oBAAI,IAAI,CAAC,GAAI,QAAQ,SAAS,CAAA,GAAK,GAAI,QAAQ,mBAAmB,EAAG,CAAC;AAAA,EAAA;AAExE,QAAM,iBAAe,aAAQ,iBAAR,mBAAsB,WAAU;AAErD,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,SAAS;AAAA;AAAA;AAAA;AAAA,MAIT,GAAI,kBAAkB,CAAA,IAAK,EAAE,eAAe,wBAAA;AAAA,MAC5C,GAAI,QAAQ,EAAE,MAAA,IAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAKxB,GAAI,aAAa,SAAS,IAAI,EAAE,eAAe,aAAA,IAAiB,CAAA;AAAA,MAChE,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,QAKZ,GAAI,QAAQ,EAAE,MAAA,IAAU,CAAA;AAAA,QACxB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,WAAW;AAAA,MAAA;AAAA,MAEb,GAAI,gBAAgB,EAAE,iBAAiB,cAAA,IAAkB,CAAA;AAAA,MACzD,GAAI,kBAAkB,EAAE,mBAAmB,gBAAA,IAAoB,CAAA;AAAA,MAC/D,GAAI,eAAe,EAAE,eAAe,aAAA,IAAiB,CAAA;AAAA,MACrD,KAAI,aAAQ,cAAR,mBAAmB,UAAS,EAAE,WAAW,QAAQ,UAAA,IAAc,CAAA;AAAA,MACnE,KAAI,aAAQ,kBAAR,mBAAuB,UACvB,EAAE,gBAAgB,QAAQ,cAAA,IAC1B,CAAA;AAAA,MACJ,GAAI,QAAQ,QAAQ,EAAE,QAAQ,QAAQ,MAAA,IAAU,CAAA;AAAA,MAChD,KAAI,aAAQ,gBAAR,mBAAqB,UAAS,EAAE,cAAc,QAAQ,YAAA,IAAgB,CAAA;AAAA,MAC1E,GAAI,QAAQ,kBAAkB,CAAA;AAAA,IAAC;AAAA,EACjC;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"statewire-run-config.js","sources":["../../src/runtime/statewire-run-config.ts"],"sourcesContent":["/** Runtime marker the deep-agent session substrate stamps on sessions. */\nconst DEEP_AGENT_RUNTIME_MARKER = 'athena_deep_agent';\n\n/** Session-origin channel. The backend clamps unknown values to 'web', which\n * is how every SDK-started session has always classified. */\nconst STATEWIRE_START_CHANNEL = 'web';\n\n/** Session label persisted in the thread's panel config (mirrors\n * 'Athena Chrome' / 'Athena mobile' in the sibling statewire hosts). */\nconst STATEWIRE_RUN_LABEL = 'Athena SDK';\n\n/** Deep-agent default model — matches the Olympus and mobile statewire hosts. */\nexport const DEFAULT_STATEWIRE_MODEL = 'claude-sonnet-5-5';\n\n/** Agent-id namespace for collab agents (`collab_agent:<asset_id>`). */\nexport const COLLAB_AGENT_REF_PREFIX = 'collab_agent:';\n\n/** The only shape the `agent` prop accepts, for error messages and docs. */\nexport const COLLAB_AGENT_REF_SHAPE = 'collab_agent:<asset_id>';\n\n/** The asset id when `agent` is a `collab_agent:<asset_id>` ref, else null. */\nexport function parseCollabAgentRef(agent: string | undefined | null): string | null {\n if (typeof agent !== 'string' || !agent.startsWith(COLLAB_AGENT_REF_PREFIX)) return null;\n const assetId = agent.slice(COLLAB_AGENT_REF_PREFIX.length).trim();\n return assetId || null;\n}\n\n/**\n * Resolve the provider's `agent` prop to a collab-agent asset id.\n *\n * An omitted or blank `agent` means \"no agent selected\" — the thread runs the\n * Athena deep agent — and resolves to `null`. A `collab_agent:<asset_id>` ref\n * resolves to the asset id. Any other non-blank value throws: the statewire\n * host cannot honour it, and a selector that is silently dropped would let a\n * misconfigured deployment ship answers from the wrong agent.\n */\nexport function resolveAgentProp({ agent }: { agent: string | undefined | null }): string | null {\n if (agent === undefined || agent === null || agent.trim() === '') return null;\n const assetId = parseCollabAgentRef(agent.trim());\n if (assetId) return assetId;\n throw new Error(\n `[AthenaSDK] Unsupported \\`agent\\` prop ${JSON.stringify(agent)}. The only accepted shape is '${COLLAB_AGENT_REF_SHAPE}' (the asset id of a published collab agent). Named agents are not supported — the statewire host always runs the Athena deep agent; omit \\`agent\\` to use it.`,\n );\n}\n\nexport interface StatewireRunConfigOptions {\n /** LLM model identifier. Defaults to the deep-agent default model — unless a\n * collab agent is selected and its author set one (the backend overlay\n * applies the agent's model when the run sends none), in which case no\n * model is sent so the agent's choice wins. */\n model?: string;\n /** Agent selector. Only the `collab_agent:<asset_id>` shape is accepted: the\n * run executes AS that published collab agent (prompt, tools, model\n * default). Any other non-empty value throws (see {@link resolveAgentProp}). */\n agent?: string;\n /** Collab-agent channel id (built-in like `email`/`sms`, or a user-defined\n * custom channel id) selecting that channel's configuration overrides.\n * Sent as `collab_channel_id`; only meaningful with a collab `agent`. */\n channel?: string;\n /** The agent's mode this send runs in, picked from the chat's mode menu\n * (`AthenaProvider` `modes`): `base` or a mode's id. Sent as\n * `collab_channel_id` in place of `channel`, which then rides as\n * `collab_entry_channel_id` so a session the pick starts still enters\n * through the channel (its switch list, lock and thread list). Only\n * meaningful with a collab `agent`. */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier, passed through as app_id. */\n appId?: string;\n /** Client-executed tool declarations, passed through as client_tools. The\n * deep-agent runtime binds each as an interrupt-backed tool the client\n * answers via the statewire client-tool bridge. */\n clientTools?: Record<string, unknown>[];\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n}\n\n/**\n * The model a send carries for the host's `model` and `extraRunConfig`, with\n * the precedence {@link buildStatewireRunConfig} applies: `extraRunConfig` is\n * merged last, so its `model` key (when it has one) wins over the `model`\n * prop. `undefined` when the send carries no explicit model.\n */\nexport function effectiveStatewireModel({\n model,\n extraRunConfig,\n}: {\n model: string | undefined;\n extraRunConfig: Record<string, unknown> | undefined;\n}): string | undefined {\n if (extraRunConfig !== undefined && Object.hasOwn(extraRunConfig, 'model')) {\n const override = extraRunConfig.model;\n return typeof override === 'string' && override !== '' ? override : undefined;\n }\n return model === '' ? undefined : model;\n}\n\n/**\n * Build the `runConfig` a deep-agent statewire run is driven by. Commands\n * travel bare on the statewire channel, so this payload rides the ambient\n * model context (`config.runConfig`) instead of the request body.\n *\n * The flattened `custom` fields drive the run, while `panel_config` carries a\n * minimal panel state the backend persists per thread and replays on the\n * statewire snapshot — so a session started from the SDK stays configured\n * when reopened elsewhere.\n */\nexport function buildStatewireRunConfig(\n options: StatewireRunConfigOptions = {},\n): Record<string, unknown> {\n const collabAgentId = resolveAgentProp({ agent: options.agent });\n const channel = collabAgentId ? options.channel?.trim() || undefined : undefined;\n const mode = collabAgentId ? options.mode?.trim() || undefined : undefined;\n const collabChannelId = mode ?? channel;\n const collabEntryChannelId = mode && channel && mode !== channel ? channel : undefined;\n // With a collab agent selected and no explicit model, send NO model: the\n // backend overlay then applies the model the agent's author configured\n // instead of the SDK default overriding it.\n const model = options.model ?? (collabAgentId ? undefined : DEFAULT_STATEWIRE_MODEL);\n const enabledTools = Array.from(\n new Set([...(options.tools ?? []), ...(options.frontendToolIds ?? [])]),\n );\n const systemPrompt = options.systemPrompt?.trim() ?? '';\n\n return {\n custom: {\n runtime: DEEP_AGENT_RUNTIME_MARKER,\n // With a collab channel selected, omit the SDK's own 'web' stamp: the\n // request's explicit start_channel would win over the backend overlay's\n // kind-mapped provenance (a custom SMS channel must stamp 'sms').\n ...(collabChannelId ? {} : { start_channel: STATEWIRE_START_CHANNEL }),\n ...(model ? { model } : {}),\n // An empty list is behavior-identical to an absent key for the parser\n // (both coerce to []), but the collab-agent overlay merges request keys\n // OVER the agent definition — so an explicit empty list would erase the\n // agent's configured tools. Omit it when empty.\n ...(enabledTools.length > 0 ? { enabled_tools: enabledTools } : {}),\n panel_config: {\n // A collab agent's thread with no explicit model names none here\n // either: agora stores this panel on the thread's first run and\n // replays it to every client, and a stored SDK default would show as\n // the session's model while the agent's own model runs.\n ...(model ? { model } : {}),\n enabled_tools: enabledTools,\n system_prompt: systemPrompt,\n run_label: STATEWIRE_RUN_LABEL,\n },\n ...(collabAgentId ? { collab_agent_id: collabAgentId } : {}),\n ...(collabChannelId ? { collab_channel_id: collabChannelId } : {}),\n ...(collabEntryChannelId ? { collab_entry_channel_id: collabEntryChannelId } : {}),\n ...(systemPrompt ? { system_prompt: systemPrompt } : {}),\n ...(options.workbench?.length ? { workbench: options.workbench } : {}),\n ...(options.knowledgeBase?.length\n ? { knowledge_base: options.knowledgeBase }\n : {}),\n ...(options.appId ? { app_id: options.appId } : {}),\n ...(options.clientTools?.length ? { client_tools: options.clientTools } : {}),\n ...(options.extraRunConfig ?? {}),\n },\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-server-lane-context.cjs","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the
|
|
1
|
+
{"version":3,"file":"statewire-server-lane-context.cjs","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the\n * thread-config writes in `StatewireThreadConfigLaneSync`) waits for `landed`.\n */\nexport interface AthenaStatewireServerLane {\n /** `true` once this attach's snapshot from the host has arrived. */\n landed: boolean;\n /** The lane in that snapshot (and every later host frame), `null` at version 0. */\n config: DeepAgentServerConfig | null;\n}\n\nexport const STATEWIRE_SERVER_LANE_PENDING: AthenaStatewireServerLane = Object.freeze({\n landed: false,\n config: null,\n});\n\n/** Provided by `AthenaProvider` around the host's children, per attached thread. */\nexport const AthenaStatewireServerLaneContext = createContext<AthenaStatewireServerLane | null>(\n null,\n);\n\n/**\n * The next lane value for a host frame: the same object while the lane's\n * version is unchanged, so a frame that moved only messages (every streamed\n * token) re-renders nothing.\n */\nexport function nextServerLane({\n previous,\n config,\n}: {\n previous: AthenaStatewireServerLane;\n config: DeepAgentServerConfig | null;\n}): AthenaStatewireServerLane {\n if (previous.landed && (previous.config?.version ?? 0) === (config?.version ?? 0)) {\n return previous;\n }\n return { landed: true, config };\n}\n"],"names":["createContext"],"mappings":";;;AAqBO,MAAM,gCAA2D,OAAO,OAAO;AAAA,EACpF,QAAQ;AAAA,EACR,QAAQ;AACV,CAAC;AAGM,MAAM,mCAAmCA,MAAAA;AAAAA,EAC9C;AACF;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAG8B;;AAC5B,MAAI,SAAS,aAAW,cAAS,WAAT,mBAAiB,YAAW,SAAQ,iCAAQ,YAAW,IAAI;AACjF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,QAAQ,MAAM,OAAA;AACzB;;;;"}
|
|
@@ -7,8 +7,8 @@ import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';
|
|
|
7
7
|
* The rendered state starts as a placeholder (or a remembered snapshot) before
|
|
8
8
|
* the attach snapshot lands, and neither says what the server holds: a
|
|
9
9
|
* placeholder has no lane at all and a remembered snapshot may carry an older
|
|
10
|
-
* one. Anything that decides from the lane (`useAthenaThreadModel`, the
|
|
11
|
-
*
|
|
10
|
+
* one. Anything that decides from the lane (`useAthenaThreadModel`, the
|
|
11
|
+
* thread-config writes in `StatewireThreadConfigLaneSync`) waits for `landed`.
|
|
12
12
|
*/
|
|
13
13
|
export interface AthenaStatewireServerLane {
|
|
14
14
|
/** `true` once this attach's snapshot from the host has arrived. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-server-lane-context.js","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the
|
|
1
|
+
{"version":3,"file":"statewire-server-lane-context.js","sources":["../../src/runtime/statewire-server-lane-context.ts"],"sourcesContent":["import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';\nimport { createContext } from 'react';\n\n/**\n * The thread's server config lane as the statewire host last sent it on this\n * attach, read off the transport's own state (`onStateChange`) rather than the\n * thread state the chat renders.\n *\n * The rendered state starts as a placeholder (or a remembered snapshot) before\n * the attach snapshot lands, and neither says what the server holds: a\n * placeholder has no lane at all and a remembered snapshot may carry an older\n * one. Anything that decides from the lane (`useAthenaThreadModel`, the\n * thread-config writes in `StatewireThreadConfigLaneSync`) waits for `landed`.\n */\nexport interface AthenaStatewireServerLane {\n /** `true` once this attach's snapshot from the host has arrived. */\n landed: boolean;\n /** The lane in that snapshot (and every later host frame), `null` at version 0. */\n config: DeepAgentServerConfig | null;\n}\n\nexport const STATEWIRE_SERVER_LANE_PENDING: AthenaStatewireServerLane = Object.freeze({\n landed: false,\n config: null,\n});\n\n/** Provided by `AthenaProvider` around the host's children, per attached thread. */\nexport const AthenaStatewireServerLaneContext = createContext<AthenaStatewireServerLane | null>(\n null,\n);\n\n/**\n * The next lane value for a host frame: the same object while the lane's\n * version is unchanged, so a frame that moved only messages (every streamed\n * token) re-renders nothing.\n */\nexport function nextServerLane({\n previous,\n config,\n}: {\n previous: AthenaStatewireServerLane;\n config: DeepAgentServerConfig | null;\n}): AthenaStatewireServerLane {\n if (previous.landed && (previous.config?.version ?? 0) === (config?.version ?? 0)) {\n return previous;\n }\n return { landed: true, config };\n}\n"],"names":[],"mappings":";AAqBO,MAAM,gCAA2D,OAAO,OAAO;AAAA,EACpF,QAAQ;AAAA,EACR,QAAQ;AACV,CAAC;AAGM,MAAM,mCAAmC;AAAA,EAC9C;AACF;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAG8B;;AAC5B,MAAI,SAAS,aAAW,cAAS,WAAT,mBAAiB,YAAW,SAAQ,iCAAQ,YAAW,IAAI;AACjF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,QAAQ,MAAM,OAAA;AACzB;"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const statewireRunConfig = require("./statewire-run-config.cjs");
|
|
4
|
+
const PROVIDER_THREAD_CONFIG_KEYS = [
|
|
5
|
+
"model",
|
|
6
|
+
"system_prompt",
|
|
7
|
+
"enabled_tools",
|
|
8
|
+
"workbench",
|
|
9
|
+
"knowledge_base"
|
|
10
|
+
];
|
|
11
|
+
const nonBlankString = (value) => typeof value === "string" && value.trim() !== "" ? value : null;
|
|
12
|
+
const stringItems = (value) => value.filter((item) => typeof item === "string");
|
|
13
|
+
const propList = (value) => value !== void 0 && value.length > 0 ? value : null;
|
|
14
|
+
const extraList = (value) => Array.isArray(value) ? stringItems(value) : null;
|
|
15
|
+
function providerThreadConfig({
|
|
16
|
+
model,
|
|
17
|
+
systemPrompt,
|
|
18
|
+
tools,
|
|
19
|
+
frontendToolIds,
|
|
20
|
+
workbench,
|
|
21
|
+
knowledgeBase,
|
|
22
|
+
extraRunConfig
|
|
23
|
+
}) {
|
|
24
|
+
const extra = extraRunConfig ?? {};
|
|
25
|
+
const overrides = (key) => Object.hasOwn(extra, key);
|
|
26
|
+
const enabledTools = Array.from(/* @__PURE__ */ new Set([...tools ?? [], ...frontendToolIds ?? []]));
|
|
27
|
+
const trimmedPrompt = (systemPrompt == null ? void 0 : systemPrompt.trim()) ?? "";
|
|
28
|
+
return {
|
|
29
|
+
model: statewireRunConfig.effectiveStatewireModel({ model, extraRunConfig }) ?? null,
|
|
30
|
+
system_prompt: overrides("system_prompt") ? nonBlankString(extra.system_prompt) : trimmedPrompt === "" ? null : trimmedPrompt,
|
|
31
|
+
enabled_tools: overrides("enabled_tools") ? extraList(extra.enabled_tools) : propList(enabledTools),
|
|
32
|
+
workbench: overrides("workbench") ? extraList(extra.workbench) : propList(workbench),
|
|
33
|
+
knowledge_base: overrides("knowledge_base") ? extraList(extra.knowledge_base) : propList(knowledgeBase)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function readLaneThreadConfigValue({
|
|
37
|
+
custom,
|
|
38
|
+
key
|
|
39
|
+
}) {
|
|
40
|
+
const value = custom[key];
|
|
41
|
+
if (key === "model") return typeof value === "string" && value !== "" ? value : null;
|
|
42
|
+
if (key === "system_prompt") return nonBlankString(value);
|
|
43
|
+
return Array.isArray(value) ? stringItems(value) : null;
|
|
44
|
+
}
|
|
45
|
+
function sameThreadConfigValue(left, right) {
|
|
46
|
+
if (left === right) return true;
|
|
47
|
+
if (!Array.isArray(left) || !Array.isArray(right)) return false;
|
|
48
|
+
return left.length === right.length && left.every((item, index) => item === right[index]);
|
|
49
|
+
}
|
|
50
|
+
function decideThreadConfigLanePatch({
|
|
51
|
+
desired,
|
|
52
|
+
keys,
|
|
53
|
+
landed,
|
|
54
|
+
configVersion,
|
|
55
|
+
custom
|
|
56
|
+
}) {
|
|
57
|
+
if (!landed || configVersion <= 0) return { kind: "wait" };
|
|
58
|
+
const pending = new Set(keys);
|
|
59
|
+
const patch = {};
|
|
60
|
+
for (const key of PROVIDER_THREAD_CONFIG_KEYS) {
|
|
61
|
+
if (!pending.has(key)) continue;
|
|
62
|
+
if (!sameThreadConfigValue(readLaneThreadConfigValue({ custom, key }), desired[key])) {
|
|
63
|
+
copyThreadConfigKey({ target: patch, source: desired, key });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return patchedThreadConfigKeys(patch).length === 0 ? { kind: "done" } : { kind: "patch", patch };
|
|
67
|
+
}
|
|
68
|
+
function copyThreadConfigKey({
|
|
69
|
+
target,
|
|
70
|
+
source,
|
|
71
|
+
key
|
|
72
|
+
}) {
|
|
73
|
+
target[key] = source[key];
|
|
74
|
+
}
|
|
75
|
+
function patchedThreadConfigKeys(patch) {
|
|
76
|
+
return PROVIDER_THREAD_CONFIG_KEYS.filter((key) => Object.hasOwn(patch, key));
|
|
77
|
+
}
|
|
78
|
+
exports.PROVIDER_THREAD_CONFIG_KEYS = PROVIDER_THREAD_CONFIG_KEYS;
|
|
79
|
+
exports.decideThreadConfigLanePatch = decideThreadConfigLanePatch;
|
|
80
|
+
exports.patchedThreadConfigKeys = patchedThreadConfigKeys;
|
|
81
|
+
exports.providerThreadConfig = providerThreadConfig;
|
|
82
|
+
exports.readLaneThreadConfigValue = readLaneThreadConfigValue;
|
|
83
|
+
exports.sameThreadConfigValue = sameThreadConfigValue;
|
|
84
|
+
//# sourceMappingURL=statewire-thread-config-lane.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statewire-thread-config-lane.cjs","sources":["../../src/runtime/statewire-thread-config-lane.ts"],"sourcesContent":["import type { ThreadConfigCustom } from '@athenaintel/agent-runtime';\nimport { effectiveStatewireModel } from './statewire-run-config';\n\n/**\n * The thread-config keys the provider's props own, in the order a\n * `config/patch` lists them.\n *\n * Once a thread has a server config lane (version > 0), agora composes every\n * run from the lane and drops these keys from a send\n * (`merge_custom_over_server_config`), so a change of the prop that feeds one\n * is written to the lane instead (see `StatewireThreadConfigLaneSync`).\n */\nexport const PROVIDER_THREAD_CONFIG_KEYS = [\n 'model',\n 'system_prompt',\n 'enabled_tools',\n 'workbench',\n 'knowledge_base',\n] as const;\n\nexport type ProviderThreadConfigKey = (typeof PROVIDER_THREAD_CONFIG_KEYS)[number];\n\n/**\n * The provider-owned thread-config values as a send carries them and as the\n * lane stores them; `null` is \"the send carries none\": written to the lane it\n * unsets the key, so the collab agent's own value (or the default) applies.\n */\nexport interface ProviderThreadConfig {\n model: string | null;\n system_prompt: string | null;\n enabled_tools: readonly string[] | null;\n workbench: readonly string[] | null;\n knowledge_base: readonly string[] | null;\n}\n\n/** A `config/patch` payload over provider-owned keys: exactly the keys to change. */\nexport type ProviderThreadConfigPatch = Partial<ProviderThreadConfig>;\n\nconst nonBlankString = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() !== '' ? value : null;\n\nconst stringItems = (value: readonly unknown[]): string[] =>\n value.filter((item): item is string => typeof item === 'string');\n\n/** A list prop as the send carries it: omitted (`null`) when empty, as `buildStatewireRunConfig` does. */\nconst propList = (value: readonly string[] | undefined): readonly string[] | null =>\n value !== undefined && value.length > 0 ? value : null;\n\n/**\n * An `extraRunConfig` list as the send carries it: `buildStatewireRunConfig`\n * merges `extraRunConfig` last and verbatim, so an explicit list (an empty one\n * included) is what the send holds.\n */\nconst extraList = (value: unknown): readonly string[] | null =>\n Array.isArray(value) ? stringItems(value) : null;\n\n/**\n * The provider-owned thread-config values a send built from these props\n * carries, with `buildStatewireRunConfig`'s precedence: `extraRunConfig` is\n * merged last, so a key it holds wins over the prop that feeds it.\n *\n * - `model`: the explicit model only (`effectiveStatewireModel`); the SDK's\n * own default is never a choice to write.\n * - `system_prompt`: the trimmed prompt, `null` when blank.\n * - `enabled_tools`: `tools` ∪ `frontendToolIds`; `null` when empty, since the\n * send omits an empty list (it would erase a collab agent's own tools).\n * - `workbench`, `knowledge_base`: the list, `null` when empty.\n *\n * Pure.\n */\nexport function providerThreadConfig({\n model,\n systemPrompt,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n extraRunConfig,\n}: {\n model: string | undefined;\n systemPrompt: string | undefined;\n tools: readonly string[] | undefined;\n frontendToolIds: readonly string[] | undefined;\n workbench: readonly string[] | undefined;\n knowledgeBase: readonly string[] | undefined;\n extraRunConfig: Record<string, unknown> | undefined;\n}): ProviderThreadConfig {\n const extra = extraRunConfig ?? {};\n const overrides = (key: ProviderThreadConfigKey) => Object.hasOwn(extra, key);\n const enabledTools = Array.from(new Set([...(tools ?? []), ...(frontendToolIds ?? [])]));\n const trimmedPrompt = systemPrompt?.trim() ?? '';\n return {\n model: effectiveStatewireModel({ model, extraRunConfig }) ?? null,\n system_prompt: overrides('system_prompt')\n ? nonBlankString(extra.system_prompt)\n : trimmedPrompt === ''\n ? null\n : trimmedPrompt,\n enabled_tools: overrides('enabled_tools')\n ? extraList(extra.enabled_tools)\n : propList(enabledTools),\n workbench: overrides('workbench') ? extraList(extra.workbench) : propList(workbench),\n knowledge_base: overrides('knowledge_base')\n ? extraList(extra.knowledge_base)\n : propList(knowledgeBase),\n };\n}\n\n/**\n * A key of the lane (`state.config.custom`) read as a provider-owned value:\n * a text key is its non-blank string, a list key its string items (an\n * explicit empty list included), anything else `null` (unset).\n */\nexport function readLaneThreadConfigValue({\n custom,\n key,\n}: {\n custom: ThreadConfigCustom;\n key: ProviderThreadConfigKey;\n}): string | readonly string[] | null {\n const value = custom[key];\n // `model` keeps `readLaneModel`'s reading: any non-empty string.\n if (key === 'model') return typeof value === 'string' && value !== '' ? value : null;\n if (key === 'system_prompt') return nonBlankString(value);\n return Array.isArray(value) ? stringItems(value) : null;\n}\n\n/** Whether two provider-owned values are the same (lists compared item by item, in order). */\nexport function sameThreadConfigValue(\n left: string | readonly string[] | null,\n right: string | readonly string[] | null,\n): boolean {\n if (left === right) return true;\n if (!Array.isArray(left) || !Array.isArray(right)) return false;\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\n/**\n * What to do with the pending changes of provider-owned keys:\n *\n * - `wait`: keep them pending. The thread's snapshot has not landed, or the\n * thread has no lane yet (version 0): the next send carries the values and\n * agora's deferral seed persists the ones it keeps. They stay pending so that\n * a lane an EARLIER send seeds (with the previous values) is corrected once\n * it lands.\n * - `done`: the lane already holds every one of them (this client's own\n * unacknowledged writes folded over); nothing to write.\n * - `patch`: issue one `config/patch` carrying exactly the keys whose lane\n * value differs; `null` unsets a key so the agent's own value (or the\n * default) applies.\n */\nexport type ThreadConfigLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: ProviderThreadConfigPatch };\n\nexport function decideThreadConfigLanePatch({\n desired,\n keys,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's values after the changes. */\n desired: ProviderThreadConfig;\n /** The keys whose prop changed during this attach and is not yet written. */\n keys: Iterable<ProviderThreadConfigKey>;\n landed: boolean;\n configVersion: number;\n /** The effective lane: the server config with this client's pending writes folded over. */\n custom: ThreadConfigCustom;\n}): ThreadConfigLaneDecision {\n if (!landed || configVersion <= 0) return { kind: 'wait' };\n const pending = new Set(keys);\n const patch: ProviderThreadConfigPatch = {};\n for (const key of PROVIDER_THREAD_CONFIG_KEYS) {\n if (!pending.has(key)) continue;\n if (!sameThreadConfigValue(readLaneThreadConfigValue({ custom, key }), desired[key])) {\n copyThreadConfigKey({ target: patch, source: desired, key });\n }\n }\n return patchedThreadConfigKeys(patch).length === 0 ? { kind: 'done' } : { kind: 'patch', patch };\n}\n\nfunction copyThreadConfigKey<K extends ProviderThreadConfigKey>({\n target,\n source,\n key,\n}: {\n target: ProviderThreadConfigPatch;\n source: ProviderThreadConfig;\n key: K;\n}): void {\n target[key] = source[key];\n}\n\n/** The keys a patch carries, in {@link PROVIDER_THREAD_CONFIG_KEYS} order. */\nexport function patchedThreadConfigKeys(patch: ProviderThreadConfigPatch): ProviderThreadConfigKey[] {\n return PROVIDER_THREAD_CONFIG_KEYS.filter((key) => Object.hasOwn(patch, key));\n}\n"],"names":["effectiveStatewireModel"],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { ThreadConfigCustom } from '@athenaintel/agent-runtime';
|
|
2
|
+
/**
|
|
3
|
+
* The thread-config keys the provider's props own, in the order a
|
|
4
|
+
* `config/patch` lists them.
|
|
5
|
+
*
|
|
6
|
+
* Once a thread has a server config lane (version > 0), agora composes every
|
|
7
|
+
* run from the lane and drops these keys from a send
|
|
8
|
+
* (`merge_custom_over_server_config`), so a change of the prop that feeds one
|
|
9
|
+
* is written to the lane instead (see `StatewireThreadConfigLaneSync`).
|
|
10
|
+
*/
|
|
11
|
+
export declare const PROVIDER_THREAD_CONFIG_KEYS: readonly ['model', 'system_prompt', 'enabled_tools', 'workbench', 'knowledge_base'];
|
|
12
|
+
export type ProviderThreadConfigKey = (typeof PROVIDER_THREAD_CONFIG_KEYS)[number];
|
|
13
|
+
/**
|
|
14
|
+
* The provider-owned thread-config values as a send carries them and as the
|
|
15
|
+
* lane stores them; `null` is "the send carries none": written to the lane it
|
|
16
|
+
* unsets the key, so the collab agent's own value (or the default) applies.
|
|
17
|
+
*/
|
|
18
|
+
export interface ProviderThreadConfig {
|
|
19
|
+
model: string | null;
|
|
20
|
+
system_prompt: string | null;
|
|
21
|
+
enabled_tools: readonly string[] | null;
|
|
22
|
+
workbench: readonly string[] | null;
|
|
23
|
+
knowledge_base: readonly string[] | null;
|
|
24
|
+
}
|
|
25
|
+
/** A `config/patch` payload over provider-owned keys: exactly the keys to change. */
|
|
26
|
+
export type ProviderThreadConfigPatch = Partial<ProviderThreadConfig>;
|
|
27
|
+
/**
|
|
28
|
+
* The provider-owned thread-config values a send built from these props
|
|
29
|
+
* carries, with `buildStatewireRunConfig`'s precedence: `extraRunConfig` is
|
|
30
|
+
* merged last, so a key it holds wins over the prop that feeds it.
|
|
31
|
+
*
|
|
32
|
+
* - `model`: the explicit model only (`effectiveStatewireModel`); the SDK's
|
|
33
|
+
* own default is never a choice to write.
|
|
34
|
+
* - `system_prompt`: the trimmed prompt, `null` when blank.
|
|
35
|
+
* - `enabled_tools`: `tools` ∪ `frontendToolIds`; `null` when empty, since the
|
|
36
|
+
* send omits an empty list (it would erase a collab agent's own tools).
|
|
37
|
+
* - `workbench`, `knowledge_base`: the list, `null` when empty.
|
|
38
|
+
*
|
|
39
|
+
* Pure.
|
|
40
|
+
*/
|
|
41
|
+
export declare function providerThreadConfig({ model, systemPrompt, tools, frontendToolIds, workbench, knowledgeBase, extraRunConfig, }: {
|
|
42
|
+
model: string | undefined;
|
|
43
|
+
systemPrompt: string | undefined;
|
|
44
|
+
tools: readonly string[] | undefined;
|
|
45
|
+
frontendToolIds: readonly string[] | undefined;
|
|
46
|
+
workbench: readonly string[] | undefined;
|
|
47
|
+
knowledgeBase: readonly string[] | undefined;
|
|
48
|
+
extraRunConfig: Record<string, unknown> | undefined;
|
|
49
|
+
}): ProviderThreadConfig;
|
|
50
|
+
/**
|
|
51
|
+
* A key of the lane (`state.config.custom`) read as a provider-owned value:
|
|
52
|
+
* a text key is its non-blank string, a list key its string items (an
|
|
53
|
+
* explicit empty list included), anything else `null` (unset).
|
|
54
|
+
*/
|
|
55
|
+
export declare function readLaneThreadConfigValue({ custom, key, }: {
|
|
56
|
+
custom: ThreadConfigCustom;
|
|
57
|
+
key: ProviderThreadConfigKey;
|
|
58
|
+
}): string | readonly string[] | null;
|
|
59
|
+
/** Whether two provider-owned values are the same (lists compared item by item, in order). */
|
|
60
|
+
export declare function sameThreadConfigValue(left: string | readonly string[] | null, right: string | readonly string[] | null): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* What to do with the pending changes of provider-owned keys:
|
|
63
|
+
*
|
|
64
|
+
* - `wait`: keep them pending. The thread's snapshot has not landed, or the
|
|
65
|
+
* thread has no lane yet (version 0): the next send carries the values and
|
|
66
|
+
* agora's deferral seed persists the ones it keeps. They stay pending so that
|
|
67
|
+
* a lane an EARLIER send seeds (with the previous values) is corrected once
|
|
68
|
+
* it lands.
|
|
69
|
+
* - `done`: the lane already holds every one of them (this client's own
|
|
70
|
+
* unacknowledged writes folded over); nothing to write.
|
|
71
|
+
* - `patch`: issue one `config/patch` carrying exactly the keys whose lane
|
|
72
|
+
* value differs; `null` unsets a key so the agent's own value (or the
|
|
73
|
+
* default) applies.
|
|
74
|
+
*/
|
|
75
|
+
export type ThreadConfigLaneDecision = {
|
|
76
|
+
kind: 'wait';
|
|
77
|
+
} | {
|
|
78
|
+
kind: 'done';
|
|
79
|
+
} | {
|
|
80
|
+
kind: 'patch';
|
|
81
|
+
patch: ProviderThreadConfigPatch;
|
|
82
|
+
};
|
|
83
|
+
export declare function decideThreadConfigLanePatch({ desired, keys, landed, configVersion, custom, }: {
|
|
84
|
+
/** The provider's values after the changes. */
|
|
85
|
+
desired: ProviderThreadConfig;
|
|
86
|
+
/** The keys whose prop changed during this attach and is not yet written. */
|
|
87
|
+
keys: Iterable<ProviderThreadConfigKey>;
|
|
88
|
+
landed: boolean;
|
|
89
|
+
configVersion: number;
|
|
90
|
+
/** The effective lane: the server config with this client's pending writes folded over. */
|
|
91
|
+
custom: ThreadConfigCustom;
|
|
92
|
+
}): ThreadConfigLaneDecision;
|
|
93
|
+
/** The keys a patch carries, in {@link PROVIDER_THREAD_CONFIG_KEYS} order. */
|
|
94
|
+
export declare function patchedThreadConfigKeys(patch: ProviderThreadConfigPatch): ProviderThreadConfigKey[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { effectiveStatewireModel } from "./statewire-run-config.js";
|
|
2
|
+
const PROVIDER_THREAD_CONFIG_KEYS = [
|
|
3
|
+
"model",
|
|
4
|
+
"system_prompt",
|
|
5
|
+
"enabled_tools",
|
|
6
|
+
"workbench",
|
|
7
|
+
"knowledge_base"
|
|
8
|
+
];
|
|
9
|
+
const nonBlankString = (value) => typeof value === "string" && value.trim() !== "" ? value : null;
|
|
10
|
+
const stringItems = (value) => value.filter((item) => typeof item === "string");
|
|
11
|
+
const propList = (value) => value !== void 0 && value.length > 0 ? value : null;
|
|
12
|
+
const extraList = (value) => Array.isArray(value) ? stringItems(value) : null;
|
|
13
|
+
function providerThreadConfig({
|
|
14
|
+
model,
|
|
15
|
+
systemPrompt,
|
|
16
|
+
tools,
|
|
17
|
+
frontendToolIds,
|
|
18
|
+
workbench,
|
|
19
|
+
knowledgeBase,
|
|
20
|
+
extraRunConfig
|
|
21
|
+
}) {
|
|
22
|
+
const extra = extraRunConfig ?? {};
|
|
23
|
+
const overrides = (key) => Object.hasOwn(extra, key);
|
|
24
|
+
const enabledTools = Array.from(/* @__PURE__ */ new Set([...tools ?? [], ...frontendToolIds ?? []]));
|
|
25
|
+
const trimmedPrompt = (systemPrompt == null ? void 0 : systemPrompt.trim()) ?? "";
|
|
26
|
+
return {
|
|
27
|
+
model: effectiveStatewireModel({ model, extraRunConfig }) ?? null,
|
|
28
|
+
system_prompt: overrides("system_prompt") ? nonBlankString(extra.system_prompt) : trimmedPrompt === "" ? null : trimmedPrompt,
|
|
29
|
+
enabled_tools: overrides("enabled_tools") ? extraList(extra.enabled_tools) : propList(enabledTools),
|
|
30
|
+
workbench: overrides("workbench") ? extraList(extra.workbench) : propList(workbench),
|
|
31
|
+
knowledge_base: overrides("knowledge_base") ? extraList(extra.knowledge_base) : propList(knowledgeBase)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function readLaneThreadConfigValue({
|
|
35
|
+
custom,
|
|
36
|
+
key
|
|
37
|
+
}) {
|
|
38
|
+
const value = custom[key];
|
|
39
|
+
if (key === "model") return typeof value === "string" && value !== "" ? value : null;
|
|
40
|
+
if (key === "system_prompt") return nonBlankString(value);
|
|
41
|
+
return Array.isArray(value) ? stringItems(value) : null;
|
|
42
|
+
}
|
|
43
|
+
function sameThreadConfigValue(left, right) {
|
|
44
|
+
if (left === right) return true;
|
|
45
|
+
if (!Array.isArray(left) || !Array.isArray(right)) return false;
|
|
46
|
+
return left.length === right.length && left.every((item, index) => item === right[index]);
|
|
47
|
+
}
|
|
48
|
+
function decideThreadConfigLanePatch({
|
|
49
|
+
desired,
|
|
50
|
+
keys,
|
|
51
|
+
landed,
|
|
52
|
+
configVersion,
|
|
53
|
+
custom
|
|
54
|
+
}) {
|
|
55
|
+
if (!landed || configVersion <= 0) return { kind: "wait" };
|
|
56
|
+
const pending = new Set(keys);
|
|
57
|
+
const patch = {};
|
|
58
|
+
for (const key of PROVIDER_THREAD_CONFIG_KEYS) {
|
|
59
|
+
if (!pending.has(key)) continue;
|
|
60
|
+
if (!sameThreadConfigValue(readLaneThreadConfigValue({ custom, key }), desired[key])) {
|
|
61
|
+
copyThreadConfigKey({ target: patch, source: desired, key });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return patchedThreadConfigKeys(patch).length === 0 ? { kind: "done" } : { kind: "patch", patch };
|
|
65
|
+
}
|
|
66
|
+
function copyThreadConfigKey({
|
|
67
|
+
target,
|
|
68
|
+
source,
|
|
69
|
+
key
|
|
70
|
+
}) {
|
|
71
|
+
target[key] = source[key];
|
|
72
|
+
}
|
|
73
|
+
function patchedThreadConfigKeys(patch) {
|
|
74
|
+
return PROVIDER_THREAD_CONFIG_KEYS.filter((key) => Object.hasOwn(patch, key));
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
PROVIDER_THREAD_CONFIG_KEYS,
|
|
78
|
+
decideThreadConfigLanePatch,
|
|
79
|
+
patchedThreadConfigKeys,
|
|
80
|
+
providerThreadConfig,
|
|
81
|
+
readLaneThreadConfigValue,
|
|
82
|
+
sameThreadConfigValue
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=statewire-thread-config-lane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statewire-thread-config-lane.js","sources":["../../src/runtime/statewire-thread-config-lane.ts"],"sourcesContent":["import type { ThreadConfigCustom } from '@athenaintel/agent-runtime';\nimport { effectiveStatewireModel } from './statewire-run-config';\n\n/**\n * The thread-config keys the provider's props own, in the order a\n * `config/patch` lists them.\n *\n * Once a thread has a server config lane (version > 0), agora composes every\n * run from the lane and drops these keys from a send\n * (`merge_custom_over_server_config`), so a change of the prop that feeds one\n * is written to the lane instead (see `StatewireThreadConfigLaneSync`).\n */\nexport const PROVIDER_THREAD_CONFIG_KEYS = [\n 'model',\n 'system_prompt',\n 'enabled_tools',\n 'workbench',\n 'knowledge_base',\n] as const;\n\nexport type ProviderThreadConfigKey = (typeof PROVIDER_THREAD_CONFIG_KEYS)[number];\n\n/**\n * The provider-owned thread-config values as a send carries them and as the\n * lane stores them; `null` is \"the send carries none\": written to the lane it\n * unsets the key, so the collab agent's own value (or the default) applies.\n */\nexport interface ProviderThreadConfig {\n model: string | null;\n system_prompt: string | null;\n enabled_tools: readonly string[] | null;\n workbench: readonly string[] | null;\n knowledge_base: readonly string[] | null;\n}\n\n/** A `config/patch` payload over provider-owned keys: exactly the keys to change. */\nexport type ProviderThreadConfigPatch = Partial<ProviderThreadConfig>;\n\nconst nonBlankString = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() !== '' ? value : null;\n\nconst stringItems = (value: readonly unknown[]): string[] =>\n value.filter((item): item is string => typeof item === 'string');\n\n/** A list prop as the send carries it: omitted (`null`) when empty, as `buildStatewireRunConfig` does. */\nconst propList = (value: readonly string[] | undefined): readonly string[] | null =>\n value !== undefined && value.length > 0 ? value : null;\n\n/**\n * An `extraRunConfig` list as the send carries it: `buildStatewireRunConfig`\n * merges `extraRunConfig` last and verbatim, so an explicit list (an empty one\n * included) is what the send holds.\n */\nconst extraList = (value: unknown): readonly string[] | null =>\n Array.isArray(value) ? stringItems(value) : null;\n\n/**\n * The provider-owned thread-config values a send built from these props\n * carries, with `buildStatewireRunConfig`'s precedence: `extraRunConfig` is\n * merged last, so a key it holds wins over the prop that feeds it.\n *\n * - `model`: the explicit model only (`effectiveStatewireModel`); the SDK's\n * own default is never a choice to write.\n * - `system_prompt`: the trimmed prompt, `null` when blank.\n * - `enabled_tools`: `tools` ∪ `frontendToolIds`; `null` when empty, since the\n * send omits an empty list (it would erase a collab agent's own tools).\n * - `workbench`, `knowledge_base`: the list, `null` when empty.\n *\n * Pure.\n */\nexport function providerThreadConfig({\n model,\n systemPrompt,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n extraRunConfig,\n}: {\n model: string | undefined;\n systemPrompt: string | undefined;\n tools: readonly string[] | undefined;\n frontendToolIds: readonly string[] | undefined;\n workbench: readonly string[] | undefined;\n knowledgeBase: readonly string[] | undefined;\n extraRunConfig: Record<string, unknown> | undefined;\n}): ProviderThreadConfig {\n const extra = extraRunConfig ?? {};\n const overrides = (key: ProviderThreadConfigKey) => Object.hasOwn(extra, key);\n const enabledTools = Array.from(new Set([...(tools ?? []), ...(frontendToolIds ?? [])]));\n const trimmedPrompt = systemPrompt?.trim() ?? '';\n return {\n model: effectiveStatewireModel({ model, extraRunConfig }) ?? null,\n system_prompt: overrides('system_prompt')\n ? nonBlankString(extra.system_prompt)\n : trimmedPrompt === ''\n ? null\n : trimmedPrompt,\n enabled_tools: overrides('enabled_tools')\n ? extraList(extra.enabled_tools)\n : propList(enabledTools),\n workbench: overrides('workbench') ? extraList(extra.workbench) : propList(workbench),\n knowledge_base: overrides('knowledge_base')\n ? extraList(extra.knowledge_base)\n : propList(knowledgeBase),\n };\n}\n\n/**\n * A key of the lane (`state.config.custom`) read as a provider-owned value:\n * a text key is its non-blank string, a list key its string items (an\n * explicit empty list included), anything else `null` (unset).\n */\nexport function readLaneThreadConfigValue({\n custom,\n key,\n}: {\n custom: ThreadConfigCustom;\n key: ProviderThreadConfigKey;\n}): string | readonly string[] | null {\n const value = custom[key];\n // `model` keeps `readLaneModel`'s reading: any non-empty string.\n if (key === 'model') return typeof value === 'string' && value !== '' ? value : null;\n if (key === 'system_prompt') return nonBlankString(value);\n return Array.isArray(value) ? stringItems(value) : null;\n}\n\n/** Whether two provider-owned values are the same (lists compared item by item, in order). */\nexport function sameThreadConfigValue(\n left: string | readonly string[] | null,\n right: string | readonly string[] | null,\n): boolean {\n if (left === right) return true;\n if (!Array.isArray(left) || !Array.isArray(right)) return false;\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\n/**\n * What to do with the pending changes of provider-owned keys:\n *\n * - `wait`: keep them pending. The thread's snapshot has not landed, or the\n * thread has no lane yet (version 0): the next send carries the values and\n * agora's deferral seed persists the ones it keeps. They stay pending so that\n * a lane an EARLIER send seeds (with the previous values) is corrected once\n * it lands.\n * - `done`: the lane already holds every one of them (this client's own\n * unacknowledged writes folded over); nothing to write.\n * - `patch`: issue one `config/patch` carrying exactly the keys whose lane\n * value differs; `null` unsets a key so the agent's own value (or the\n * default) applies.\n */\nexport type ThreadConfigLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: ProviderThreadConfigPatch };\n\nexport function decideThreadConfigLanePatch({\n desired,\n keys,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's values after the changes. */\n desired: ProviderThreadConfig;\n /** The keys whose prop changed during this attach and is not yet written. */\n keys: Iterable<ProviderThreadConfigKey>;\n landed: boolean;\n configVersion: number;\n /** The effective lane: the server config with this client's pending writes folded over. */\n custom: ThreadConfigCustom;\n}): ThreadConfigLaneDecision {\n if (!landed || configVersion <= 0) return { kind: 'wait' };\n const pending = new Set(keys);\n const patch: ProviderThreadConfigPatch = {};\n for (const key of PROVIDER_THREAD_CONFIG_KEYS) {\n if (!pending.has(key)) continue;\n if (!sameThreadConfigValue(readLaneThreadConfigValue({ custom, key }), desired[key])) {\n copyThreadConfigKey({ target: patch, source: desired, key });\n }\n }\n return patchedThreadConfigKeys(patch).length === 0 ? { kind: 'done' } : { kind: 'patch', patch };\n}\n\nfunction copyThreadConfigKey<K extends ProviderThreadConfigKey>({\n target,\n source,\n key,\n}: {\n target: ProviderThreadConfigPatch;\n source: ProviderThreadConfig;\n key: K;\n}): void {\n target[key] = source[key];\n}\n\n/** The keys a patch carries, in {@link PROVIDER_THREAD_CONFIG_KEYS} order. */\nexport function patchedThreadConfigKeys(patch: ProviderThreadConfigPatch): ProviderThreadConfigKey[] {\n return PROVIDER_THREAD_CONFIG_KEYS.filter((key) => Object.hasOwn(patch, key));\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -36,6 +36,7 @@ function useAthenaStatewireRuntime(config) {
|
|
|
36
36
|
model,
|
|
37
37
|
agent,
|
|
38
38
|
channel,
|
|
39
|
+
mode,
|
|
39
40
|
tools = EMPTY_TOOL_IDS,
|
|
40
41
|
frontendToolIds = EMPTY_TOOL_IDS,
|
|
41
42
|
frontendToolkit = EMPTY_TOOLKIT,
|
|
@@ -71,6 +72,7 @@ function useAthenaStatewireRuntime(config) {
|
|
|
71
72
|
model,
|
|
72
73
|
agent,
|
|
73
74
|
channel,
|
|
75
|
+
mode,
|
|
74
76
|
tools,
|
|
75
77
|
frontendToolIds,
|
|
76
78
|
workbench,
|
|
@@ -157,8 +159,8 @@ function useAthenaStatewireRuntime(config) {
|
|
|
157
159
|
// core's per-render ref; the value-stable key re-registers (and so
|
|
158
160
|
// notifies) only when the built runConfig actually changed. On a thread
|
|
159
161
|
// with a server config lane, agora keeps only the per-send keys of what
|
|
160
|
-
// this carries; `
|
|
161
|
-
// lane itself.
|
|
162
|
+
// this carries; `StatewireThreadConfigLaneSync` writes a changed model,
|
|
163
|
+
// system prompt, tool list, workbench or knowledge base to the lane itself.
|
|
162
164
|
runConfig: {
|
|
163
165
|
get: () => runConfigValue,
|
|
164
166
|
key: runConfigKey
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAthenaStatewireRuntime.cjs","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentStateHydrated,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionKey } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /**\n * Observes the host's own state: called once the attach's hello has landed\n * (with the snapshot it carried) and then on every later frame — never with\n * the placeholder or remembered snapshot a thread renders before its hello.\n * Called per streamed token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onServerState,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionKey`).\n const authContext = useContext(AthenaAuthContext);\n const principal = authContext?.user?.userId ?? '';\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n // The host's state, told apart from what the thread renders before its\n // hello: statewire publishes the initial (placeholder or remembered) state\n // through `onStateChange` too, and reports `connected` in the same flush\n // right after publishing the state the hello carried. So the latest state\n // seen when the connection first turns `connected` is the hello's, and every\n // state after it is the host's. Refs are per attach: the runtime is mounted\n // per thread.\n const lastStateRef = useRef<DeepAgentStreamValues | null>(null);\n const helloLandedRef = useRef(false);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.)\n session: {\n kind: 'local-storage',\n key: (id) => statewireSessionKey({ syncUrl, principal, threadId: id }),\n },\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`).\n getMessageMetadata: withStagedComposerMarkdown({ threadId }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // First snapshot for this attach ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n // A replay boundary republishes the pre-stream default: not host state.\n if (!isDeepAgentStateHydrated(state)) return;\n lastStateRef.current = state;\n if (helloLandedRef.current) onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange: (connection) => {\n if (connection.status === 'connected' && !helloLandedRef.current) {\n helloLandedRef.current = true;\n const helloState = lastStateRef.current;\n if (helloState) onServerState?.(helloState);\n }\n onRawConnectionChange?.(connection);\n },\n onRunningChange,\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireModelLaneSync` writes a changed `model` to the\n // lane itself.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":["DEEP_AGENT_DEFAULT_MESSAGE_WINDOW","useMemo","collectStatewireClientTools","resolveAgentProp","useContext","AthenaAuthContext","useRef","athenaDiagnostics","buildStatewireRunConfig","statewireClientToolWireEntries","Tools","useAui","useDeepAgentRuntime","resolveStatewireAuthHeaders","statewireSessionKey","withStagedComposerMarkdown","isDeepAgentStateHydrated","isStatewireChannelTeardown","logUnhandledStatewireError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAthenaStatewireRuntime.cjs","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentStateHydrated,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionKey } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /**\n * Observes the host's own state: called once the attach's hello has landed\n * (with the snapshot it carried) and then on every later frame — never with\n * the placeholder or remembered snapshot a thread renders before its hello.\n * Called per streamed token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onServerState,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionKey`).\n const authContext = useContext(AthenaAuthContext);\n const principal = authContext?.user?.userId ?? '';\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n // The host's state, told apart from what the thread renders before its\n // hello: statewire publishes the initial (placeholder or remembered) state\n // through `onStateChange` too, and reports `connected` in the same flush\n // right after publishing the state the hello carried. So the latest state\n // seen when the connection first turns `connected` is the hello's, and every\n // state after it is the host's. Refs are per attach: the runtime is mounted\n // per thread.\n const lastStateRef = useRef<DeepAgentStreamValues | null>(null);\n const helloLandedRef = useRef(false);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.)\n session: {\n kind: 'local-storage',\n key: (id) => statewireSessionKey({ syncUrl, principal, threadId: id }),\n },\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`).\n getMessageMetadata: withStagedComposerMarkdown({ threadId }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // First snapshot for this attach ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n // A replay boundary republishes the pre-stream default: not host state.\n if (!isDeepAgentStateHydrated(state)) return;\n lastStateRef.current = state;\n if (helloLandedRef.current) onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange: (connection) => {\n if (connection.status === 'connected' && !helloLandedRef.current) {\n helloLandedRef.current = true;\n const helloState = lastStateRef.current;\n if (helloState) onServerState?.(helloState);\n }\n onRawConnectionChange?.(connection);\n },\n onRunningChange,\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":["DEEP_AGENT_DEFAULT_MESSAGE_WINDOW","useMemo","collectStatewireClientTools","resolveAgentProp","useContext","AthenaAuthContext","useRef","athenaDiagnostics","buildStatewireRunConfig","statewireClientToolWireEntries","Tools","useAui","useDeepAgentRuntime","resolveStatewireAuthHeaders","statewireSessionKey","withStagedComposerMarkdown","isDeepAgentStateHydrated","isStatewireChannelTeardown","logUnhandledStatewireError"],"mappings":"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"}
|
|
@@ -52,6 +52,8 @@ export interface AthenaStatewireRuntimeConfig {
|
|
|
52
52
|
agent?: string;
|
|
53
53
|
/** Collab-agent channel id selecting that channel's overrides. */
|
|
54
54
|
channel?: string;
|
|
55
|
+
/** The agent's mode picked for this thread (`AthenaProvider` `modes`). */
|
|
56
|
+
mode?: string;
|
|
55
57
|
/** Backend toolkit IDs to enable. */
|
|
56
58
|
tools?: string[];
|
|
57
59
|
/** Frontend tool IDs to include in enabled_tools. */
|
|
@@ -35,6 +35,7 @@ function useAthenaStatewireRuntime(config) {
|
|
|
35
35
|
model,
|
|
36
36
|
agent,
|
|
37
37
|
channel,
|
|
38
|
+
mode,
|
|
38
39
|
tools = EMPTY_TOOL_IDS,
|
|
39
40
|
frontendToolIds = EMPTY_TOOL_IDS,
|
|
40
41
|
frontendToolkit = EMPTY_TOOLKIT,
|
|
@@ -70,6 +71,7 @@ function useAthenaStatewireRuntime(config) {
|
|
|
70
71
|
model,
|
|
71
72
|
agent,
|
|
72
73
|
channel,
|
|
74
|
+
mode,
|
|
73
75
|
tools,
|
|
74
76
|
frontendToolIds,
|
|
75
77
|
workbench,
|
|
@@ -156,8 +158,8 @@ function useAthenaStatewireRuntime(config) {
|
|
|
156
158
|
// core's per-render ref; the value-stable key re-registers (and so
|
|
157
159
|
// notifies) only when the built runConfig actually changed. On a thread
|
|
158
160
|
// with a server config lane, agora keeps only the per-send keys of what
|
|
159
|
-
// this carries; `
|
|
160
|
-
// lane itself.
|
|
161
|
+
// this carries; `StatewireThreadConfigLaneSync` writes a changed model,
|
|
162
|
+
// system prompt, tool list, workbench or knowledge base to the lane itself.
|
|
161
163
|
runConfig: {
|
|
162
164
|
get: () => runConfigValue,
|
|
163
165
|
key: runConfigKey
|