@athenaintel/react 0.30.0 → 0.32.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.
Files changed (147) hide show
  1. package/README.md +61 -0
  2. package/dist/agent-runtime/src/athena-asset-drag.cjs +44 -0
  3. package/dist/agent-runtime/src/athena-asset-drag.cjs.map +1 -0
  4. package/dist/agent-runtime/src/athena-asset-drag.js +44 -0
  5. package/dist/agent-runtime/src/athena-asset-drag.js.map +1 -0
  6. package/dist/agent-runtime/src/config-mutations.cjs +59 -0
  7. package/dist/agent-runtime/src/config-mutations.cjs.map +1 -0
  8. package/dist/agent-runtime/src/config-mutations.js +59 -0
  9. package/dist/agent-runtime/src/config-mutations.js.map +1 -0
  10. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +6 -0
  11. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  12. package/dist/agent-runtime/src/generated/runconfig-contract.js +6 -0
  13. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  14. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +48 -0
  15. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  16. package/dist/agent-runtime/src/quota-safe-local-storage-session.js +49 -1
  17. package/dist/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
  18. package/dist/agent-runtime/src/tool-metadata.cjs +25 -6
  19. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  20. package/dist/agent-runtime/src/tool-metadata.js +25 -6
  21. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  22. package/dist/agent-runtime/src/use-deep-agent-config.cjs +117 -1
  23. package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
  24. package/dist/agent-runtime/src/use-deep-agent-config.js +118 -2
  25. package/dist/agent-runtime/src/use-deep-agent-config.js.map +1 -1
  26. package/dist/assets/AthenaAssetEmbed.cjs +6 -1
  27. package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
  28. package/dist/assets/AthenaAssetEmbed.d.ts +2 -0
  29. package/dist/assets/AthenaAssetEmbed.js +7 -2
  30. package/dist/assets/AthenaAssetEmbed.js.map +1 -1
  31. package/dist/assets/asset-embed-messages.cjs +6 -0
  32. package/dist/assets/asset-embed-messages.cjs.map +1 -1
  33. package/dist/assets/asset-embed-messages.d.ts +7 -0
  34. package/dist/assets/asset-embed-messages.js +6 -0
  35. package/dist/assets/asset-embed-messages.js.map +1 -1
  36. package/dist/chat/AthenaChat.cjs +41 -26
  37. package/dist/chat/AthenaChat.cjs.map +1 -1
  38. package/dist/chat/AthenaChat.js +41 -26
  39. package/dist/chat/AthenaChat.js.map +1 -1
  40. package/dist/chat/super-grouping/SuperGroupingCard.cjs +31 -11
  41. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  42. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +14 -3
  43. package/dist/chat/super-grouping/SuperGroupingCard.js +32 -12
  44. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  45. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +80 -53
  46. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
  47. package/dist/chat/super-grouping/SuperGroupingTranscript.d.ts +2 -2
  48. package/dist/chat/super-grouping/SuperGroupingTranscript.js +81 -54
  49. package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
  50. package/dist/chat/super-grouping/activity-timeline.cjs +19 -4
  51. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  52. package/dist/chat/super-grouping/activity-timeline.d.ts +20 -1
  53. package/dist/chat/super-grouping/activity-timeline.js +19 -4
  54. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  55. package/dist/chat/super-grouping/index.cjs +2 -0
  56. package/dist/chat/super-grouping/index.cjs.map +1 -1
  57. package/dist/chat/super-grouping/index.d.ts +1 -1
  58. package/dist/chat/super-grouping/index.js +3 -1
  59. package/dist/chat/super-grouping/toolkit-map.cjs +1 -0
  60. package/dist/chat/super-grouping/toolkit-map.cjs.map +1 -1
  61. package/dist/chat/super-grouping/toolkit-map.js +1 -0
  62. package/dist/chat/super-grouping/toolkit-map.js.map +1 -1
  63. package/dist/chat-ui/composer/tiptap-composer.cjs +40 -4
  64. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  65. package/dist/chat-ui/composer/tiptap-composer.js +40 -4
  66. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  67. package/dist/chat-ui/mentions/mention-chip.cjs +29 -2
  68. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  69. package/dist/chat-ui/mentions/mention-chip.d.ts +2 -5
  70. package/dist/chat-ui/mentions/mention-chip.js +30 -3
  71. package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
  72. package/dist/chat-ui/mentions/mention-extension.cjs +1 -1
  73. package/dist/chat-ui/mentions/mention-extension.cjs.map +1 -1
  74. package/dist/chat-ui/mentions/mention-extension.js +1 -1
  75. package/dist/chat-ui/mentions/mention-extension.js.map +1 -1
  76. package/dist/chat-ui/mentions/use-account-workspace-id.cjs +61 -0
  77. package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -0
  78. package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +3 -0
  79. package/dist/chat-ui/mentions/use-account-workspace-id.js +61 -0
  80. package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -0
  81. package/dist/chat-ui/mentions/use-member-avatar.cjs +75 -0
  82. package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -0
  83. package/dist/chat-ui/mentions/use-member-avatar.d.ts +2 -0
  84. package/dist/chat-ui/mentions/use-member-avatar.js +75 -0
  85. package/dist/chat-ui/mentions/use-member-avatar.js.map +1 -0
  86. package/dist/collab/client.cjs +80 -19
  87. package/dist/collab/client.cjs.map +1 -1
  88. package/dist/collab/client.d.ts +22 -0
  89. package/dist/collab/client.js +80 -19
  90. package/dist/collab/client.js.map +1 -1
  91. package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
  92. package/dist/diagnostics/athena-diagnostics.d.ts +3 -1
  93. package/dist/diagnostics/athena-diagnostics.js.map +1 -1
  94. package/dist/index.cjs +4 -0
  95. package/dist/index.cjs.map +1 -1
  96. package/dist/index.d.ts +3 -1
  97. package/dist/index.js +5 -1
  98. package/dist/index.js.map +1 -1
  99. package/dist/provider/AthenaProvider.cjs +34 -4
  100. package/dist/provider/AthenaProvider.cjs.map +1 -1
  101. package/dist/provider/AthenaProvider.d.ts +7 -1
  102. package/dist/provider/AthenaProvider.js +36 -6
  103. package/dist/provider/AthenaProvider.js.map +1 -1
  104. package/dist/react/package.json.cjs +1 -1
  105. package/dist/react/package.json.js +1 -1
  106. package/dist/runtime/StatewireModelLaneSync.cjs +96 -0
  107. package/dist/runtime/StatewireModelLaneSync.cjs.map +1 -0
  108. package/dist/runtime/StatewireModelLaneSync.d.ts +45 -0
  109. package/dist/runtime/StatewireModelLaneSync.js +96 -0
  110. package/dist/runtime/StatewireModelLaneSync.js.map +1 -0
  111. package/dist/runtime/statewire-lifecycle.cjs +5 -2
  112. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  113. package/dist/runtime/statewire-lifecycle.d.ts +5 -0
  114. package/dist/runtime/statewire-lifecycle.js +5 -2
  115. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  116. package/dist/runtime/statewire-model-lane.cjs +28 -0
  117. package/dist/runtime/statewire-model-lane.cjs.map +1 -0
  118. package/dist/runtime/statewire-model-lane.d.ts +64 -0
  119. package/dist/runtime/statewire-model-lane.js +28 -0
  120. package/dist/runtime/statewire-model-lane.js.map +1 -0
  121. package/dist/runtime/statewire-run-config.cjs +16 -2
  122. package/dist/runtime/statewire-run-config.cjs.map +1 -1
  123. package/dist/runtime/statewire-run-config.d.ts +10 -0
  124. package/dist/runtime/statewire-run-config.js +16 -2
  125. package/dist/runtime/statewire-run-config.js.map +1 -1
  126. package/dist/runtime/statewire-server-lane-context.cjs +24 -0
  127. package/dist/runtime/statewire-server-lane-context.cjs.map +1 -0
  128. package/dist/runtime/statewire-server-lane-context.d.ts +30 -0
  129. package/dist/runtime/statewire-server-lane-context.js +24 -0
  130. package/dist/runtime/statewire-server-lane-context.js.map +1 -0
  131. package/dist/runtime/useAthenaStatewireRuntime.cjs +38 -18
  132. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  133. package/dist/runtime/useAthenaStatewireRuntime.d.ts +8 -1
  134. package/dist/runtime/useAthenaStatewireRuntime.js +39 -19
  135. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  136. package/dist/styles.css +1 -1
  137. package/dist/threads/api.cjs +2 -1
  138. package/dist/threads/api.cjs.map +1 -1
  139. package/dist/threads/api.d.ts +1 -0
  140. package/dist/threads/api.js +2 -1
  141. package/dist/threads/api.js.map +1 -1
  142. package/dist/threads/use-athena-thread-model.cjs +14 -0
  143. package/dist/threads/use-athena-thread-model.cjs.map +1 -0
  144. package/dist/threads/use-athena-thread-model.d.ts +22 -0
  145. package/dist/threads/use-athena-thread-model.js +14 -0
  146. package/dist/threads/use-athena-thread-model.js.map +1 -0
  147. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"statewire-lifecycle.cjs","sources":["../../src/runtime/statewire-lifecycle.ts"],"sourcesContent":["import {\n COLLAB_AGENT_CHANNEL_SESSION_MISMATCH,\n isLegacyThreadReadOnlyRejection,\n isStatewireChannelTeardown,\n statewireRejectionCode,\n statewireRejectionDetailMessage,\n statewireRejectionPayload,\n} from '@athenaintel/agent-runtime';\nimport type { DeepAgentConnectionState } from '@athenaintel/agent-runtime';\n\n/** A user-visible notice mapped from a statewire transport error. */\nexport interface AthenaStatewireErrorNotice {\n kind: 'paywall' | 'read-only' | 'command';\n title: string;\n message: string;\n /**\n * The server's structured `detail.code` (`collab_agent_channel_session_mismatch`,\n * `legacy_thread_read_only`, …), when the rejection carried one — what a\n * host matches on to offer the right next step.\n */\n code?: string;\n}\n\n/**\n * Map the statewire failure envelope to a concise, actionable notice.\n * Returns null for expected channel teardowns (thread switch, unmount),\n * which must not surface as errors.\n */\nexport function athenaStatewireErrorNotice(\n error: unknown,\n): AthenaStatewireErrorNotice | null {\n if (isStatewireChannelTeardown(error)) return null;\n const rejection = statewireRejectionPayload(error);\n // The server's own detail names the actionable reason; the Error message is\n // generic client-side text like `command rejected (500)`.\n const detail = statewireRejectionDetailMessage(error);\n\n if (rejection?.status === 402) {\n return {\n kind: 'paywall',\n title: 'Usage limit reached',\n message:\n detail ?? 'Athena could not start this run. Review usage or billing to continue.',\n };\n }\n\n const code = statewireRejectionCode(error);\n const withCode = code === null ? {} : { code };\n\n // Legacy-thread dispatch fence: an out-of-band run is writing this\n // pre-cutover thread (or its adoption failed). A per-send failure, not a\n // standing state — the server's detail names the actionable reason (wait\n // for the run vs. start a new chat).\n if (isLegacyThreadReadOnlyRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message:\n detail ??\n 'This conversation cannot take new messages right now. Try again shortly, or start a new chat.',\n ...withCode,\n };\n }\n\n // A session keeps the collab-agent channel (the app's mode) it started on:\n // the send asked for another one. Nothing about the chat is broken — the\n // way on is a new session — so it reads as the amber \"not sent\", not red.\n if (code === COLLAB_AGENT_CHANNEL_SESSION_MISMATCH) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: detail ?? 'This session runs in another mode. Start a new session to use this one.',\n code,\n };\n }\n\n return {\n kind: 'command',\n title: 'Message was not sent',\n message:\n detail ??\n (error instanceof Error && error.message.length > 0\n ? error.message\n : 'The chat runtime rejected the command. Please try again.'),\n ...withCode,\n };\n}\n\n/** Shared lifecycle state for the statewire transport, provided by\n * `AthenaProvider` in statewire mode and read by the chat banners. */\nexport interface AthenaStatewireLifecycleState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n dismissError: () => void;\n}\n\n/** The provider's reducer state behind {@link AthenaStatewireLifecycleState}. */\nexport interface StatewireLifecycleReducerState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n}\n\nexport type StatewireLifecycleAction =\n | { type: 'connection'; connection: DeepAgentConnectionState | null }\n | { type: 'error'; error: AthenaStatewireErrorNotice | null }\n | { type: 'raw-connection'; reconnect: () => void };\n\nexport const initialStatewireLifecycle: StatewireLifecycleReducerState = {\n connection: null,\n error: null,\n reconnect: null,\n};\n\n/**\n * Folds the runtime's lifecycle observations into the banner state. A healthy\n * channel — connected, or disconnected only because the instance is quiet\n * (`idle`) or the chat has not sent yet (`deferred`) — clears a stale\n * send/transport error: leaving it up tells the user the chat is broken after\n * it has come back.\n */\nexport function statewireLifecycleReducer(\n state: StatewireLifecycleReducerState,\n action: StatewireLifecycleAction,\n): StatewireLifecycleReducerState {\n switch (action.type) {\n case 'connection': {\n const healthy =\n action.connection?.status === 'connected' ||\n action.connection?.status === 'standby';\n return {\n ...state,\n connection: action.connection,\n error: healthy ? null : state.error,\n };\n }\n case 'error':\n return { ...state, error: action.error };\n case 'raw-connection':\n return { ...state, reconnect: action.reconnect };\n }\n}\n"],"names":["isStatewireChannelTeardown","statewireRejectionPayload","statewireRejectionDetailMessage","statewireRejectionCode","isLegacyThreadReadOnlyRejection","COLLAB_AGENT_CHANNEL_SESSION_MISMATCH"],"mappings":";;;AA4BO,SAAS,2BACd,OACmC;AACnC,MAAIA,OAAAA,2BAA2B,KAAK,EAAG,QAAO;AAC9C,QAAM,YAAYC,OAAAA,0BAA0B,KAAK;AAGjD,QAAM,SAASC,OAAAA,gCAAgC,KAAK;AAEpD,OAAI,uCAAW,YAAW,KAAK;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UAAU;AAAA,IAAA;AAAA,EAEhB;AAEA,QAAM,OAAOC,OAAAA,uBAAuB,KAAK;AACzC,QAAM,WAAW,SAAS,OAAO,CAAA,IAAK,EAAE,KAAA;AAMxC,MAAIC,OAAAA,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UACA;AAAA,MACF,GAAG;AAAA,IAAA;AAAA,EAEP;AAKA,MAAI,SAASC,OAAAA,uCAAuC;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE,WACC,iBAAiB,SAAS,MAAM,QAAQ,SAAS,IAC9C,MAAM,UACN;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAuBO,MAAM,4BAA4D;AAAA,EACvE,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AACb;AASO,SAAS,0BACd,OACA,QACgC;;AAChC,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,cAAc;AACjB,YAAM,YACJ,YAAO,eAAP,mBAAmB,YAAW,iBAC9B,YAAO,eAAP,mBAAmB,YAAW;AAChC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,OAAO,UAAU,OAAO,MAAM;AAAA,MAAA;AAAA,IAElC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAA;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,OAAO,UAAA;AAAA,EAAU;AAErD;;;;"}
1
+ {"version":3,"file":"statewire-lifecycle.cjs","sources":["../../src/runtime/statewire-lifecycle.ts"],"sourcesContent":["import {\n COLLAB_AGENT_CHANNEL_SESSION_MISMATCH,\n isLegacyThreadReadOnlyRejection,\n isStatewireChannelTeardown,\n statewireRejectionCode,\n statewireRejectionDetailMessage,\n statewireRejectionPayload,\n} from '@athenaintel/agent-runtime';\nimport type { DeepAgentConnectionState } from '@athenaintel/agent-runtime';\n\n/** A user-visible notice mapped from a statewire transport error. */\nexport interface AthenaStatewireErrorNotice {\n kind: 'paywall' | 'read-only' | 'command';\n title: string;\n message: string;\n /**\n * The server's structured `detail.code` (`collab_agent_channel_session_mismatch`,\n * `legacy_thread_read_only`, …), when the rejection carried one — what a\n * host matches on to offer the right next step.\n */\n code?: string;\n}\n\n/**\n * Map the statewire failure envelope to a concise, actionable notice.\n * Returns null for expected channel teardowns (thread switch, unmount),\n * which must not surface as errors.\n */\nexport function athenaStatewireErrorNotice(\n error: unknown,\n): AthenaStatewireErrorNotice | null {\n if (isStatewireChannelTeardown(error)) return null;\n const rejection = statewireRejectionPayload(error);\n // The server's own detail names the actionable reason; the Error message is\n // generic client-side text like `command rejected (500)`.\n const detail = statewireRejectionDetailMessage(error);\n\n if (rejection?.status === 402) {\n return {\n kind: 'paywall',\n title: 'Usage limit reached',\n message:\n detail ?? 'Athena could not start this run. Review usage or billing to continue.',\n };\n }\n\n const code = statewireRejectionCode(error);\n const withCode = code === null ? {} : { code };\n\n // Legacy-thread dispatch fence: an out-of-band run is writing this\n // pre-cutover thread (or its adoption failed). A per-send failure, not a\n // standing state — the server's detail names the actionable reason (wait\n // for the run vs. start a new chat).\n if (isLegacyThreadReadOnlyRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message:\n detail ??\n 'This conversation cannot take new messages right now. Try again shortly, or start a new chat.',\n ...withCode,\n };\n }\n\n // A session keeps the collab-agent channel (the app's mode) it started on:\n // the send asked for another one. Nothing about the chat is broken — the\n // way on is a new session — so it reads as the amber \"not sent\", not red.\n if (code === COLLAB_AGENT_CHANNEL_SESSION_MISMATCH) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: detail ?? 'This session runs in another mode. Start a new session to use this one.',\n code,\n };\n }\n\n return {\n kind: 'command',\n title: 'Message was not sent',\n message:\n detail ??\n (error instanceof Error && error.message.length > 0\n ? error.message\n : 'The chat runtime rejected the command. Please try again.'),\n ...withCode,\n };\n}\n\n/** Shared lifecycle state for the statewire transport, provided by\n * `AthenaProvider` in statewire mode and read by the chat banners. */\nexport interface AthenaStatewireLifecycleState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n dismissError: () => void;\n}\n\n/** The provider's reducer state behind {@link AthenaStatewireLifecycleState}. */\nexport interface StatewireLifecycleReducerState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n}\n\nexport type StatewireLifecycleAction =\n | { type: 'connection'; connection: DeepAgentConnectionState | null }\n | { type: 'error'; error: AthenaStatewireErrorNotice | null }\n | { type: 'raw-connection'; reconnect: () => void };\n\nexport const initialStatewireLifecycle: StatewireLifecycleReducerState = {\n connection: null,\n error: null,\n reconnect: null,\n};\n\n/**\n * Folds the runtime's lifecycle observations into the banner state. A healthy\n * channel — connected, or disconnected only because the instance is quiet\n * (`idle`) or the chat has not sent yet (`deferred`) — clears a stale\n * send/transport error: leaving it up tells the user the chat is broken after\n * it has come back.\n */\n/**\n * Whether the statewire channel can take a command now: connected, or on\n * standby (attached and idle). `null` (no connection observed yet) is not.\n */\nexport function isStatewireChannelLive(connection: DeepAgentConnectionState | null): boolean {\n return connection?.status === 'connected' || connection?.status === 'standby';\n}\n\nexport function statewireLifecycleReducer(\n state: StatewireLifecycleReducerState,\n action: StatewireLifecycleAction,\n): StatewireLifecycleReducerState {\n switch (action.type) {\n case 'connection': {\n const healthy = isStatewireChannelLive(action.connection);\n return {\n ...state,\n connection: action.connection,\n error: healthy ? null : state.error,\n };\n }\n case 'error':\n return { ...state, error: action.error };\n case 'raw-connection':\n return { ...state, reconnect: action.reconnect };\n }\n}\n"],"names":["isStatewireChannelTeardown","statewireRejectionPayload","statewireRejectionDetailMessage","statewireRejectionCode","isLegacyThreadReadOnlyRejection","COLLAB_AGENT_CHANNEL_SESSION_MISMATCH"],"mappings":";;;AA4BO,SAAS,2BACd,OACmC;AACnC,MAAIA,OAAAA,2BAA2B,KAAK,EAAG,QAAO;AAC9C,QAAM,YAAYC,OAAAA,0BAA0B,KAAK;AAGjD,QAAM,SAASC,OAAAA,gCAAgC,KAAK;AAEpD,OAAI,uCAAW,YAAW,KAAK;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UAAU;AAAA,IAAA;AAAA,EAEhB;AAEA,QAAM,OAAOC,OAAAA,uBAAuB,KAAK;AACzC,QAAM,WAAW,SAAS,OAAO,CAAA,IAAK,EAAE,KAAA;AAMxC,MAAIC,OAAAA,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UACA;AAAA,MACF,GAAG;AAAA,IAAA;AAAA,EAEP;AAKA,MAAI,SAASC,OAAAA,uCAAuC;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE,WACC,iBAAiB,SAAS,MAAM,QAAQ,SAAS,IAC9C,MAAM,UACN;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAuBO,MAAM,4BAA4D;AAAA,EACvE,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AACb;AAaO,SAAS,uBAAuB,YAAsD;AAC3F,UAAO,yCAAY,YAAW,gBAAe,yCAAY,YAAW;AACtE;AAEO,SAAS,0BACd,OACA,QACgC;AAChC,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,cAAc;AACjB,YAAM,UAAU,uBAAuB,OAAO,UAAU;AACxD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,OAAO,UAAU,OAAO,MAAM;AAAA,MAAA;AAAA,IAElC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAA;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,OAAO,UAAA;AAAA,EAAU;AAErD;;;;;"}
@@ -49,4 +49,9 @@ export declare const initialStatewireLifecycle: StatewireLifecycleReducerState;
49
49
  * send/transport error: leaving it up tells the user the chat is broken after
50
50
  * it has come back.
51
51
  */
52
+ /**
53
+ * Whether the statewire channel can take a command now: connected, or on
54
+ * standby (attached and idle). `null` (no connection observed yet) is not.
55
+ */
56
+ export declare function isStatewireChannelLive(connection: DeepAgentConnectionState | null): boolean;
52
57
  export declare function statewireLifecycleReducer(state: StatewireLifecycleReducerState, action: StatewireLifecycleAction): StatewireLifecycleReducerState;
@@ -40,11 +40,13 @@ const initialStatewireLifecycle = {
40
40
  error: null,
41
41
  reconnect: null
42
42
  };
43
+ function isStatewireChannelLive(connection) {
44
+ return (connection == null ? void 0 : connection.status) === "connected" || (connection == null ? void 0 : connection.status) === "standby";
45
+ }
43
46
  function statewireLifecycleReducer(state, action) {
44
- var _a, _b;
45
47
  switch (action.type) {
46
48
  case "connection": {
47
- const healthy = ((_a = action.connection) == null ? void 0 : _a.status) === "connected" || ((_b = action.connection) == null ? void 0 : _b.status) === "standby";
49
+ const healthy = isStatewireChannelLive(action.connection);
48
50
  return {
49
51
  ...state,
50
52
  connection: action.connection,
@@ -60,6 +62,7 @@ function statewireLifecycleReducer(state, action) {
60
62
  export {
61
63
  athenaStatewireErrorNotice,
62
64
  initialStatewireLifecycle,
65
+ isStatewireChannelLive,
63
66
  statewireLifecycleReducer
64
67
  };
65
68
  //# sourceMappingURL=statewire-lifecycle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"statewire-lifecycle.js","sources":["../../src/runtime/statewire-lifecycle.ts"],"sourcesContent":["import {\n COLLAB_AGENT_CHANNEL_SESSION_MISMATCH,\n isLegacyThreadReadOnlyRejection,\n isStatewireChannelTeardown,\n statewireRejectionCode,\n statewireRejectionDetailMessage,\n statewireRejectionPayload,\n} from '@athenaintel/agent-runtime';\nimport type { DeepAgentConnectionState } from '@athenaintel/agent-runtime';\n\n/** A user-visible notice mapped from a statewire transport error. */\nexport interface AthenaStatewireErrorNotice {\n kind: 'paywall' | 'read-only' | 'command';\n title: string;\n message: string;\n /**\n * The server's structured `detail.code` (`collab_agent_channel_session_mismatch`,\n * `legacy_thread_read_only`, …), when the rejection carried one — what a\n * host matches on to offer the right next step.\n */\n code?: string;\n}\n\n/**\n * Map the statewire failure envelope to a concise, actionable notice.\n * Returns null for expected channel teardowns (thread switch, unmount),\n * which must not surface as errors.\n */\nexport function athenaStatewireErrorNotice(\n error: unknown,\n): AthenaStatewireErrorNotice | null {\n if (isStatewireChannelTeardown(error)) return null;\n const rejection = statewireRejectionPayload(error);\n // The server's own detail names the actionable reason; the Error message is\n // generic client-side text like `command rejected (500)`.\n const detail = statewireRejectionDetailMessage(error);\n\n if (rejection?.status === 402) {\n return {\n kind: 'paywall',\n title: 'Usage limit reached',\n message:\n detail ?? 'Athena could not start this run. Review usage or billing to continue.',\n };\n }\n\n const code = statewireRejectionCode(error);\n const withCode = code === null ? {} : { code };\n\n // Legacy-thread dispatch fence: an out-of-band run is writing this\n // pre-cutover thread (or its adoption failed). A per-send failure, not a\n // standing state — the server's detail names the actionable reason (wait\n // for the run vs. start a new chat).\n if (isLegacyThreadReadOnlyRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message:\n detail ??\n 'This conversation cannot take new messages right now. Try again shortly, or start a new chat.',\n ...withCode,\n };\n }\n\n // A session keeps the collab-agent channel (the app's mode) it started on:\n // the send asked for another one. Nothing about the chat is broken — the\n // way on is a new session — so it reads as the amber \"not sent\", not red.\n if (code === COLLAB_AGENT_CHANNEL_SESSION_MISMATCH) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: detail ?? 'This session runs in another mode. Start a new session to use this one.',\n code,\n };\n }\n\n return {\n kind: 'command',\n title: 'Message was not sent',\n message:\n detail ??\n (error instanceof Error && error.message.length > 0\n ? error.message\n : 'The chat runtime rejected the command. Please try again.'),\n ...withCode,\n };\n}\n\n/** Shared lifecycle state for the statewire transport, provided by\n * `AthenaProvider` in statewire mode and read by the chat banners. */\nexport interface AthenaStatewireLifecycleState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n dismissError: () => void;\n}\n\n/** The provider's reducer state behind {@link AthenaStatewireLifecycleState}. */\nexport interface StatewireLifecycleReducerState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n}\n\nexport type StatewireLifecycleAction =\n | { type: 'connection'; connection: DeepAgentConnectionState | null }\n | { type: 'error'; error: AthenaStatewireErrorNotice | null }\n | { type: 'raw-connection'; reconnect: () => void };\n\nexport const initialStatewireLifecycle: StatewireLifecycleReducerState = {\n connection: null,\n error: null,\n reconnect: null,\n};\n\n/**\n * Folds the runtime's lifecycle observations into the banner state. A healthy\n * channel — connected, or disconnected only because the instance is quiet\n * (`idle`) or the chat has not sent yet (`deferred`) — clears a stale\n * send/transport error: leaving it up tells the user the chat is broken after\n * it has come back.\n */\nexport function statewireLifecycleReducer(\n state: StatewireLifecycleReducerState,\n action: StatewireLifecycleAction,\n): StatewireLifecycleReducerState {\n switch (action.type) {\n case 'connection': {\n const healthy =\n action.connection?.status === 'connected' ||\n action.connection?.status === 'standby';\n return {\n ...state,\n connection: action.connection,\n error: healthy ? null : state.error,\n };\n }\n case 'error':\n return { ...state, error: action.error };\n case 'raw-connection':\n return { ...state, reconnect: action.reconnect };\n }\n}\n"],"names":[],"mappings":";AA4BO,SAAS,2BACd,OACmC;AACnC,MAAI,2BAA2B,KAAK,EAAG,QAAO;AAC9C,QAAM,YAAY,0BAA0B,KAAK;AAGjD,QAAM,SAAS,gCAAgC,KAAK;AAEpD,OAAI,uCAAW,YAAW,KAAK;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UAAU;AAAA,IAAA;AAAA,EAEhB;AAEA,QAAM,OAAO,uBAAuB,KAAK;AACzC,QAAM,WAAW,SAAS,OAAO,CAAA,IAAK,EAAE,KAAA;AAMxC,MAAI,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UACA;AAAA,MACF,GAAG;AAAA,IAAA;AAAA,EAEP;AAKA,MAAI,SAAS,uCAAuC;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE,WACC,iBAAiB,SAAS,MAAM,QAAQ,SAAS,IAC9C,MAAM,UACN;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAuBO,MAAM,4BAA4D;AAAA,EACvE,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AACb;AASO,SAAS,0BACd,OACA,QACgC;;AAChC,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,cAAc;AACjB,YAAM,YACJ,YAAO,eAAP,mBAAmB,YAAW,iBAC9B,YAAO,eAAP,mBAAmB,YAAW;AAChC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,OAAO,UAAU,OAAO,MAAM;AAAA,MAAA;AAAA,IAElC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAA;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,OAAO,UAAA;AAAA,EAAU;AAErD;"}
1
+ {"version":3,"file":"statewire-lifecycle.js","sources":["../../src/runtime/statewire-lifecycle.ts"],"sourcesContent":["import {\n COLLAB_AGENT_CHANNEL_SESSION_MISMATCH,\n isLegacyThreadReadOnlyRejection,\n isStatewireChannelTeardown,\n statewireRejectionCode,\n statewireRejectionDetailMessage,\n statewireRejectionPayload,\n} from '@athenaintel/agent-runtime';\nimport type { DeepAgentConnectionState } from '@athenaintel/agent-runtime';\n\n/** A user-visible notice mapped from a statewire transport error. */\nexport interface AthenaStatewireErrorNotice {\n kind: 'paywall' | 'read-only' | 'command';\n title: string;\n message: string;\n /**\n * The server's structured `detail.code` (`collab_agent_channel_session_mismatch`,\n * `legacy_thread_read_only`, …), when the rejection carried one — what a\n * host matches on to offer the right next step.\n */\n code?: string;\n}\n\n/**\n * Map the statewire failure envelope to a concise, actionable notice.\n * Returns null for expected channel teardowns (thread switch, unmount),\n * which must not surface as errors.\n */\nexport function athenaStatewireErrorNotice(\n error: unknown,\n): AthenaStatewireErrorNotice | null {\n if (isStatewireChannelTeardown(error)) return null;\n const rejection = statewireRejectionPayload(error);\n // The server's own detail names the actionable reason; the Error message is\n // generic client-side text like `command rejected (500)`.\n const detail = statewireRejectionDetailMessage(error);\n\n if (rejection?.status === 402) {\n return {\n kind: 'paywall',\n title: 'Usage limit reached',\n message:\n detail ?? 'Athena could not start this run. Review usage or billing to continue.',\n };\n }\n\n const code = statewireRejectionCode(error);\n const withCode = code === null ? {} : { code };\n\n // Legacy-thread dispatch fence: an out-of-band run is writing this\n // pre-cutover thread (or its adoption failed). A per-send failure, not a\n // standing state — the server's detail names the actionable reason (wait\n // for the run vs. start a new chat).\n if (isLegacyThreadReadOnlyRejection(error)) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message:\n detail ??\n 'This conversation cannot take new messages right now. Try again shortly, or start a new chat.',\n ...withCode,\n };\n }\n\n // A session keeps the collab-agent channel (the app's mode) it started on:\n // the send asked for another one. Nothing about the chat is broken — the\n // way on is a new session — so it reads as the amber \"not sent\", not red.\n if (code === COLLAB_AGENT_CHANNEL_SESSION_MISMATCH) {\n return {\n kind: 'read-only',\n title: 'Message was not sent',\n message: detail ?? 'This session runs in another mode. Start a new session to use this one.',\n code,\n };\n }\n\n return {\n kind: 'command',\n title: 'Message was not sent',\n message:\n detail ??\n (error instanceof Error && error.message.length > 0\n ? error.message\n : 'The chat runtime rejected the command. Please try again.'),\n ...withCode,\n };\n}\n\n/** Shared lifecycle state for the statewire transport, provided by\n * `AthenaProvider` in statewire mode and read by the chat banners. */\nexport interface AthenaStatewireLifecycleState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n dismissError: () => void;\n}\n\n/** The provider's reducer state behind {@link AthenaStatewireLifecycleState}. */\nexport interface StatewireLifecycleReducerState {\n connection: DeepAgentConnectionState | null;\n error: AthenaStatewireErrorNotice | null;\n reconnect: (() => void) | null;\n}\n\nexport type StatewireLifecycleAction =\n | { type: 'connection'; connection: DeepAgentConnectionState | null }\n | { type: 'error'; error: AthenaStatewireErrorNotice | null }\n | { type: 'raw-connection'; reconnect: () => void };\n\nexport const initialStatewireLifecycle: StatewireLifecycleReducerState = {\n connection: null,\n error: null,\n reconnect: null,\n};\n\n/**\n * Folds the runtime's lifecycle observations into the banner state. A healthy\n * channel — connected, or disconnected only because the instance is quiet\n * (`idle`) or the chat has not sent yet (`deferred`) — clears a stale\n * send/transport error: leaving it up tells the user the chat is broken after\n * it has come back.\n */\n/**\n * Whether the statewire channel can take a command now: connected, or on\n * standby (attached and idle). `null` (no connection observed yet) is not.\n */\nexport function isStatewireChannelLive(connection: DeepAgentConnectionState | null): boolean {\n return connection?.status === 'connected' || connection?.status === 'standby';\n}\n\nexport function statewireLifecycleReducer(\n state: StatewireLifecycleReducerState,\n action: StatewireLifecycleAction,\n): StatewireLifecycleReducerState {\n switch (action.type) {\n case 'connection': {\n const healthy = isStatewireChannelLive(action.connection);\n return {\n ...state,\n connection: action.connection,\n error: healthy ? null : state.error,\n };\n }\n case 'error':\n return { ...state, error: action.error };\n case 'raw-connection':\n return { ...state, reconnect: action.reconnect };\n }\n}\n"],"names":[],"mappings":";AA4BO,SAAS,2BACd,OACmC;AACnC,MAAI,2BAA2B,KAAK,EAAG,QAAO;AAC9C,QAAM,YAAY,0BAA0B,KAAK;AAGjD,QAAM,SAAS,gCAAgC,KAAK;AAEpD,OAAI,uCAAW,YAAW,KAAK;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UAAU;AAAA,IAAA;AAAA,EAEhB;AAEA,QAAM,OAAO,uBAAuB,KAAK;AACzC,QAAM,WAAW,SAAS,OAAO,CAAA,IAAK,EAAE,KAAA;AAMxC,MAAI,gCAAgC,KAAK,GAAG;AAC1C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SACE,UACA;AAAA,MACF,GAAG;AAAA,IAAA;AAAA,EAEP;AAKA,MAAI,SAAS,uCAAuC;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE,WACC,iBAAiB,SAAS,MAAM,QAAQ,SAAS,IAC9C,MAAM,UACN;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAuBO,MAAM,4BAA4D;AAAA,EACvE,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AACb;AAaO,SAAS,uBAAuB,YAAsD;AAC3F,UAAO,yCAAY,YAAW,gBAAe,yCAAY,YAAW;AACtE;AAEO,SAAS,0BACd,OACA,QACgC;AAChC,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,cAAc;AACjB,YAAM,UAAU,uBAAuB,OAAO,UAAU;AACxD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,OAAO,UAAU,OAAO,MAAM;AAAA,MAAA;AAAA,IAElC;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAA;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,OAAO,UAAA;AAAA,EAAU;AAErD;"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function readLaneModel(custom) {
4
+ const model = custom.model;
5
+ return typeof model === "string" && model !== "" ? model : null;
6
+ }
7
+ function threadModelFromLane({
8
+ lane,
9
+ ready
10
+ }) {
11
+ if (!ready || lane === null) return { model: null, configured: false, ready };
12
+ return { model: readLaneModel(lane.custom), configured: true, ready };
13
+ }
14
+ function decideModelLanePatch({
15
+ desiredModel,
16
+ landed,
17
+ configVersion,
18
+ custom
19
+ }) {
20
+ if (!landed || configVersion <= 0) return { kind: "wait" };
21
+ const desired = desiredModel === void 0 || desiredModel === "" ? null : desiredModel;
22
+ if (readLaneModel(custom) === desired) return { kind: "done" };
23
+ return { kind: "patch", patch: { model: desired } };
24
+ }
25
+ exports.decideModelLanePatch = decideModelLanePatch;
26
+ exports.readLaneModel = readLaneModel;
27
+ exports.threadModelFromLane = threadModelFromLane;
28
+ //# sourceMappingURL=statewire-model-lane.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statewire-model-lane.cjs","sources":["../../src/runtime/statewire-model-lane.ts"],"sourcesContent":["import type { DeepAgentServerConfig, ThreadConfigCustom } from '@athenaintel/agent-runtime';\n\n/**\n * The model a thread's server config lane (`state.config.custom`) pins, as the\n * host app should read it, plus whether there is a lane at all.\n *\n * Once a thread has a lane (version > 0), agora runs every turn with the lane's\n * thread-config keys and drops the ones a send carries, `model` included: the\n * lane, not the provider's `model` prop, decides which model a turn uses.\n */\nexport interface AthenaThreadModel {\n /**\n * The model the lane pins, or `null` when it pins none: the run then uses the\n * selected collab agent's own model, or the deployment default.\n */\n model: string | null;\n /** `true` once the thread has a server config lane (version > 0). */\n configured: boolean;\n /**\n * `true` once the statewire host's snapshot of this thread has arrived (the\n * placeholder or remembered snapshot a thread shows while it loads does not\n * count: it may carry no lane, or an older one). Before that `model` is\n * `null` and `configured` is `false` whatever the thread holds, so wait for\n * `ready` before treating \"no model\" as an answer.\n */\n ready: boolean;\n}\n\n/** The lane's `model` key, or `null` when it carries none (or a non-string). */\nexport function readLaneModel(custom: ThreadConfigCustom): string | null {\n const model = custom.model;\n return typeof model === 'string' && model !== '' ? model : null;\n}\n\n/** {@link AthenaThreadModel} from the lane and the landed flag. Pure. */\nexport function threadModelFromLane({\n lane,\n ready,\n}: {\n lane: DeepAgentServerConfig | null;\n ready: boolean;\n}): AthenaThreadModel {\n if (!ready || lane === null) return { model: null, configured: false, ready };\n return { model: readLaneModel(lane.custom), configured: true, ready };\n}\n\n/**\n * What to do with a `model` prop change the host made during an attach:\n *\n * - `wait`: keep the change pending. The thread's snapshot has not landed, or\n * the thread has no lane yet (version 0). A version-0 thread needs nothing:\n * the next send carries the model and agora's deferral seed persists it. The\n * change stays pending only so that a lane an EARLIER send seeds (with the\n * previous model) is corrected once it lands.\n * - `done`: the lane already holds the model (this client's own unacknowledged\n * writes folded over); nothing to write.\n * - `patch`: issue `config/patch {model}`; `null` unsets the lane's model so\n * the agent's own model (or the deployment default) applies.\n */\nexport type ModelLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: { model: string | null } };\n\nexport function decideModelLanePatch({\n desiredModel,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's `model` prop after the change (`undefined` = no explicit model). */\n desiredModel: string | undefined;\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}): ModelLaneDecision {\n if (!landed || configVersion <= 0) return { kind: 'wait' };\n const desired = desiredModel === undefined || desiredModel === '' ? null : desiredModel;\n if (readLaneModel(custom) === desired) return { kind: 'done' };\n return { kind: 'patch', patch: { model: desired } };\n}\n"],"names":[],"mappings":";;AA6BO,SAAS,cAAc,QAA2C;AACvE,QAAM,QAAQ,OAAO;AACrB,SAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC7D;AAGO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGsB;AACpB,MAAI,CAAC,SAAS,SAAS,KAAM,QAAO,EAAE,OAAO,MAAM,YAAY,OAAO,MAAA;AACtE,SAAO,EAAE,OAAO,cAAc,KAAK,MAAM,GAAG,YAAY,MAAM,MAAA;AAChE;AAoBO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOsB;AACpB,MAAI,CAAC,UAAU,iBAAiB,EAAG,QAAO,EAAE,MAAM,OAAA;AAClD,QAAM,UAAU,iBAAiB,UAAa,iBAAiB,KAAK,OAAO;AAC3E,MAAI,cAAc,MAAM,MAAM,QAAS,QAAO,EAAE,MAAM,OAAA;AACtD,SAAO,EAAE,MAAM,SAAS,OAAO,EAAE,OAAO,UAAQ;AAClD;;;;"}
@@ -0,0 +1,64 @@
1
+ import type { DeepAgentServerConfig, ThreadConfigCustom } from '@athenaintel/agent-runtime';
2
+ /**
3
+ * The model a thread's server config lane (`state.config.custom`) pins, as the
4
+ * host app should read it, plus whether there is a lane at all.
5
+ *
6
+ * Once a thread has a lane (version > 0), agora runs every turn with the lane's
7
+ * thread-config keys and drops the ones a send carries, `model` included: the
8
+ * lane, not the provider's `model` prop, decides which model a turn uses.
9
+ */
10
+ export interface AthenaThreadModel {
11
+ /**
12
+ * The model the lane pins, or `null` when it pins none: the run then uses the
13
+ * selected collab agent's own model, or the deployment default.
14
+ */
15
+ model: string | null;
16
+ /** `true` once the thread has a server config lane (version > 0). */
17
+ configured: boolean;
18
+ /**
19
+ * `true` once the statewire host's snapshot of this thread has arrived (the
20
+ * placeholder or remembered snapshot a thread shows while it loads does not
21
+ * count: it may carry no lane, or an older one). Before that `model` is
22
+ * `null` and `configured` is `false` whatever the thread holds, so wait for
23
+ * `ready` before treating "no model" as an answer.
24
+ */
25
+ ready: boolean;
26
+ }
27
+ /** The lane's `model` key, or `null` when it carries none (or a non-string). */
28
+ export declare function readLaneModel(custom: ThreadConfigCustom): string | null;
29
+ /** {@link AthenaThreadModel} from the lane and the landed flag. Pure. */
30
+ export declare function threadModelFromLane({ lane, ready, }: {
31
+ lane: DeepAgentServerConfig | null;
32
+ ready: boolean;
33
+ }): AthenaThreadModel;
34
+ /**
35
+ * What to do with a `model` prop change the host made during an attach:
36
+ *
37
+ * - `wait`: keep the change pending. The thread's snapshot has not landed, or
38
+ * the thread has no lane yet (version 0). A version-0 thread needs nothing:
39
+ * the next send carries the model and agora's deferral seed persists it. The
40
+ * change stays pending only so that a lane an EARLIER send seeds (with the
41
+ * previous model) is corrected once it lands.
42
+ * - `done`: the lane already holds the model (this client's own unacknowledged
43
+ * writes folded over); nothing to write.
44
+ * - `patch`: issue `config/patch {model}`; `null` unsets the lane's model so
45
+ * the agent's own model (or the deployment default) applies.
46
+ */
47
+ export type ModelLaneDecision = {
48
+ kind: 'wait';
49
+ } | {
50
+ kind: 'done';
51
+ } | {
52
+ kind: 'patch';
53
+ patch: {
54
+ model: string | null;
55
+ };
56
+ };
57
+ export declare function decideModelLanePatch({ desiredModel, landed, configVersion, custom, }: {
58
+ /** The provider's `model` prop after the change (`undefined` = no explicit model). */
59
+ desiredModel: string | undefined;
60
+ landed: boolean;
61
+ configVersion: number;
62
+ /** The effective lane: the server config with this client's pending writes folded over. */
63
+ custom: ThreadConfigCustom;
64
+ }): ModelLaneDecision;
@@ -0,0 +1,28 @@
1
+ function readLaneModel(custom) {
2
+ const model = custom.model;
3
+ return typeof model === "string" && model !== "" ? model : null;
4
+ }
5
+ function threadModelFromLane({
6
+ lane,
7
+ ready
8
+ }) {
9
+ if (!ready || lane === null) return { model: null, configured: false, ready };
10
+ return { model: readLaneModel(lane.custom), configured: true, ready };
11
+ }
12
+ function decideModelLanePatch({
13
+ desiredModel,
14
+ landed,
15
+ configVersion,
16
+ custom
17
+ }) {
18
+ if (!landed || configVersion <= 0) return { kind: "wait" };
19
+ const desired = desiredModel === void 0 || desiredModel === "" ? null : desiredModel;
20
+ if (readLaneModel(custom) === desired) return { kind: "done" };
21
+ return { kind: "patch", patch: { model: desired } };
22
+ }
23
+ export {
24
+ decideModelLanePatch,
25
+ readLaneModel,
26
+ threadModelFromLane
27
+ };
28
+ //# sourceMappingURL=statewire-model-lane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statewire-model-lane.js","sources":["../../src/runtime/statewire-model-lane.ts"],"sourcesContent":["import type { DeepAgentServerConfig, ThreadConfigCustom } from '@athenaintel/agent-runtime';\n\n/**\n * The model a thread's server config lane (`state.config.custom`) pins, as the\n * host app should read it, plus whether there is a lane at all.\n *\n * Once a thread has a lane (version > 0), agora runs every turn with the lane's\n * thread-config keys and drops the ones a send carries, `model` included: the\n * lane, not the provider's `model` prop, decides which model a turn uses.\n */\nexport interface AthenaThreadModel {\n /**\n * The model the lane pins, or `null` when it pins none: the run then uses the\n * selected collab agent's own model, or the deployment default.\n */\n model: string | null;\n /** `true` once the thread has a server config lane (version > 0). */\n configured: boolean;\n /**\n * `true` once the statewire host's snapshot of this thread has arrived (the\n * placeholder or remembered snapshot a thread shows while it loads does not\n * count: it may carry no lane, or an older one). Before that `model` is\n * `null` and `configured` is `false` whatever the thread holds, so wait for\n * `ready` before treating \"no model\" as an answer.\n */\n ready: boolean;\n}\n\n/** The lane's `model` key, or `null` when it carries none (or a non-string). */\nexport function readLaneModel(custom: ThreadConfigCustom): string | null {\n const model = custom.model;\n return typeof model === 'string' && model !== '' ? model : null;\n}\n\n/** {@link AthenaThreadModel} from the lane and the landed flag. Pure. */\nexport function threadModelFromLane({\n lane,\n ready,\n}: {\n lane: DeepAgentServerConfig | null;\n ready: boolean;\n}): AthenaThreadModel {\n if (!ready || lane === null) return { model: null, configured: false, ready };\n return { model: readLaneModel(lane.custom), configured: true, ready };\n}\n\n/**\n * What to do with a `model` prop change the host made during an attach:\n *\n * - `wait`: keep the change pending. The thread's snapshot has not landed, or\n * the thread has no lane yet (version 0). A version-0 thread needs nothing:\n * the next send carries the model and agora's deferral seed persists it. The\n * change stays pending only so that a lane an EARLIER send seeds (with the\n * previous model) is corrected once it lands.\n * - `done`: the lane already holds the model (this client's own unacknowledged\n * writes folded over); nothing to write.\n * - `patch`: issue `config/patch {model}`; `null` unsets the lane's model so\n * the agent's own model (or the deployment default) applies.\n */\nexport type ModelLaneDecision =\n | { kind: 'wait' }\n | { kind: 'done' }\n | { kind: 'patch'; patch: { model: string | null } };\n\nexport function decideModelLanePatch({\n desiredModel,\n landed,\n configVersion,\n custom,\n}: {\n /** The provider's `model` prop after the change (`undefined` = no explicit model). */\n desiredModel: string | undefined;\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}): ModelLaneDecision {\n if (!landed || configVersion <= 0) return { kind: 'wait' };\n const desired = desiredModel === undefined || desiredModel === '' ? null : desiredModel;\n if (readLaneModel(custom) === desired) return { kind: 'done' };\n return { kind: 'patch', patch: { model: desired } };\n}\n"],"names":[],"mappings":"AA6BO,SAAS,cAAc,QAA2C;AACvE,QAAM,QAAQ,OAAO;AACrB,SAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC7D;AAGO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGsB;AACpB,MAAI,CAAC,SAAS,SAAS,KAAM,QAAO,EAAE,OAAO,MAAM,YAAY,OAAO,MAAA;AACtE,SAAO,EAAE,OAAO,cAAc,KAAK,MAAM,GAAG,YAAY,MAAM,MAAA;AAChE;AAoBO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOsB;AACpB,MAAI,CAAC,UAAU,iBAAiB,EAAG,QAAO,EAAE,MAAM,OAAA;AAClD,QAAM,UAAU,iBAAiB,UAAa,iBAAiB,KAAK,OAAO;AAC3E,MAAI,cAAc,MAAM,MAAM,QAAS,QAAO,EAAE,MAAM,OAAA;AACtD,SAAO,EAAE,MAAM,SAAS,OAAO,EAAE,OAAO,UAAQ;AAClD;"}
@@ -19,12 +19,21 @@ function resolveAgentProp({ agent }) {
19
19
  `[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.`
20
20
  );
21
21
  }
22
+ function effectiveStatewireModel({
23
+ model,
24
+ extraRunConfig
25
+ }) {
26
+ if (extraRunConfig !== void 0 && Object.hasOwn(extraRunConfig, "model")) {
27
+ const override = extraRunConfig.model;
28
+ return typeof override === "string" && override !== "" ? override : void 0;
29
+ }
30
+ return model === "" ? void 0 : model;
31
+ }
22
32
  function buildStatewireRunConfig(options = {}) {
23
33
  var _a, _b, _c, _d, _e;
24
34
  const collabAgentId = resolveAgentProp({ agent: options.agent });
25
35
  const collabChannelId = collabAgentId && ((_a = options.channel) == null ? void 0 : _a.trim()) ? options.channel.trim() : void 0;
26
36
  const model = options.model ?? (collabAgentId ? void 0 : DEFAULT_STATEWIRE_MODEL);
27
- const panelModel = model ?? DEFAULT_STATEWIRE_MODEL;
28
37
  const enabledTools = Array.from(
29
38
  /* @__PURE__ */ new Set([...options.tools ?? [], ...options.frontendToolIds ?? []])
30
39
  );
@@ -43,7 +52,11 @@ function buildStatewireRunConfig(options = {}) {
43
52
  // agent's configured tools. Omit it when empty.
44
53
  ...enabledTools.length > 0 ? { enabled_tools: enabledTools } : {},
45
54
  panel_config: {
46
- model: panelModel,
55
+ // A collab agent's thread with no explicit model names none here
56
+ // either: agora stores this panel on the thread's first run and
57
+ // replays it to every client, and a stored SDK default would show as
58
+ // the session's model while the agent's own model runs.
59
+ ...model ? { model } : {},
47
60
  enabled_tools: enabledTools,
48
61
  system_prompt: systemPrompt,
49
62
  run_label: STATEWIRE_RUN_LABEL
@@ -63,6 +76,7 @@ exports.COLLAB_AGENT_REF_PREFIX = COLLAB_AGENT_REF_PREFIX;
63
76
  exports.COLLAB_AGENT_REF_SHAPE = COLLAB_AGENT_REF_SHAPE;
64
77
  exports.DEFAULT_STATEWIRE_MODEL = DEFAULT_STATEWIRE_MODEL;
65
78
  exports.buildStatewireRunConfig = buildStatewireRunConfig;
79
+ exports.effectiveStatewireModel = effectiveStatewireModel;
66
80
  exports.parseCollabAgentRef = parseCollabAgentRef;
67
81
  exports.resolveAgentProp = resolveAgentProp;
68
82
  //# sourceMappingURL=statewire-run-config.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"statewire-run-config.cjs","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 * 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 panelModel = model ?? 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 model: panelModel,\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;AA8CO,SAAS,wBACd,UAAqC,IACZ;;AACzB,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,aAAa,SAAS;AAC5B,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,QACZ,OAAO;AAAA,QACP,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.cjs","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;;AACzB,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;;;;;;;;"}
@@ -51,6 +51,16 @@ export interface StatewireRunConfigOptions {
51
51
  /** Additional fields merged into runConfig.custom. */
52
52
  extraRunConfig?: Record<string, unknown>;
53
53
  }
54
+ /**
55
+ * The model a send carries for the host's `model` and `extraRunConfig`, with
56
+ * the precedence {@link buildStatewireRunConfig} applies: `extraRunConfig` is
57
+ * merged last, so its `model` key (when it has one) wins over the `model`
58
+ * prop. `undefined` when the send carries no explicit model.
59
+ */
60
+ export declare function effectiveStatewireModel({ model, extraRunConfig, }: {
61
+ model: string | undefined;
62
+ extraRunConfig: Record<string, unknown> | undefined;
63
+ }): string | undefined;
54
64
  /**
55
65
  * Build the `runConfig` a deep-agent statewire run is driven by. Commands
56
66
  * travel bare on the statewire channel, so this payload rides the ambient
@@ -17,12 +17,21 @@ function resolveAgentProp({ agent }) {
17
17
  `[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.`
18
18
  );
19
19
  }
20
+ function effectiveStatewireModel({
21
+ model,
22
+ extraRunConfig
23
+ }) {
24
+ if (extraRunConfig !== void 0 && Object.hasOwn(extraRunConfig, "model")) {
25
+ const override = extraRunConfig.model;
26
+ return typeof override === "string" && override !== "" ? override : void 0;
27
+ }
28
+ return model === "" ? void 0 : model;
29
+ }
20
30
  function buildStatewireRunConfig(options = {}) {
21
31
  var _a, _b, _c, _d, _e;
22
32
  const collabAgentId = resolveAgentProp({ agent: options.agent });
23
33
  const collabChannelId = collabAgentId && ((_a = options.channel) == null ? void 0 : _a.trim()) ? options.channel.trim() : void 0;
24
34
  const model = options.model ?? (collabAgentId ? void 0 : DEFAULT_STATEWIRE_MODEL);
25
- const panelModel = model ?? DEFAULT_STATEWIRE_MODEL;
26
35
  const enabledTools = Array.from(
27
36
  /* @__PURE__ */ new Set([...options.tools ?? [], ...options.frontendToolIds ?? []])
28
37
  );
@@ -41,7 +50,11 @@ function buildStatewireRunConfig(options = {}) {
41
50
  // agent's configured tools. Omit it when empty.
42
51
  ...enabledTools.length > 0 ? { enabled_tools: enabledTools } : {},
43
52
  panel_config: {
44
- model: panelModel,
53
+ // A collab agent's thread with no explicit model names none here
54
+ // either: agora stores this panel on the thread's first run and
55
+ // replays it to every client, and a stored SDK default would show as
56
+ // the session's model while the agent's own model runs.
57
+ ...model ? { model } : {},
45
58
  enabled_tools: enabledTools,
46
59
  system_prompt: systemPrompt,
47
60
  run_label: STATEWIRE_RUN_LABEL
@@ -62,6 +75,7 @@ export {
62
75
  COLLAB_AGENT_REF_SHAPE,
63
76
  DEFAULT_STATEWIRE_MODEL,
64
77
  buildStatewireRunConfig,
78
+ effectiveStatewireModel,
65
79
  parseCollabAgentRef,
66
80
  resolveAgentProp
67
81
  };
@@ -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 * 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 panelModel = model ?? 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 model: panelModel,\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;AA8CO,SAAS,wBACd,UAAqC,IACZ;AA1F3B;AA2FE,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,aAAa,SAAS;AAC5B,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,QACZ,OAAO;AAAA,QACP,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 /** 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;"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const react = require("react");
4
+ const STATEWIRE_SERVER_LANE_PENDING = Object.freeze({
5
+ landed: false,
6
+ config: null
7
+ });
8
+ const AthenaStatewireServerLaneContext = react.createContext(
9
+ null
10
+ );
11
+ function nextServerLane({
12
+ previous,
13
+ config
14
+ }) {
15
+ var _a;
16
+ if (previous.landed && (((_a = previous.config) == null ? void 0 : _a.version) ?? 0) === ((config == null ? void 0 : config.version) ?? 0)) {
17
+ return previous;
18
+ }
19
+ return { landed: true, config };
20
+ }
21
+ exports.AthenaStatewireServerLaneContext = AthenaStatewireServerLaneContext;
22
+ exports.STATEWIRE_SERVER_LANE_PENDING = STATEWIRE_SERVER_LANE_PENDING;
23
+ exports.nextServerLane = nextServerLane;
24
+ //# sourceMappingURL=statewire-server-lane-context.cjs.map
@@ -0,0 +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 model\n * write in `StatewireModelLaneSync`) 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;;;;"}
@@ -0,0 +1,30 @@
1
+ import type { DeepAgentServerConfig } from '@athenaintel/agent-runtime';
2
+ /**
3
+ * The thread's server config lane as the statewire host last sent it on this
4
+ * attach, read off the transport's own state (`onStateChange`) rather than the
5
+ * thread state the chat renders.
6
+ *
7
+ * The rendered state starts as a placeholder (or a remembered snapshot) before
8
+ * the attach snapshot lands, and neither says what the server holds: a
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 model
11
+ * write in `StatewireModelLaneSync`) waits for `landed`.
12
+ */
13
+ export interface AthenaStatewireServerLane {
14
+ /** `true` once this attach's snapshot from the host has arrived. */
15
+ landed: boolean;
16
+ /** The lane in that snapshot (and every later host frame), `null` at version 0. */
17
+ config: DeepAgentServerConfig | null;
18
+ }
19
+ export declare const STATEWIRE_SERVER_LANE_PENDING: AthenaStatewireServerLane;
20
+ /** Provided by `AthenaProvider` around the host's children, per attached thread. */
21
+ export declare const AthenaStatewireServerLaneContext: import("react").Context<AthenaStatewireServerLane | null>;
22
+ /**
23
+ * The next lane value for a host frame: the same object while the lane's
24
+ * version is unchanged, so a frame that moved only messages (every streamed
25
+ * token) re-renders nothing.
26
+ */
27
+ export declare function nextServerLane({ previous, config, }: {
28
+ previous: AthenaStatewireServerLane;
29
+ config: DeepAgentServerConfig | null;
30
+ }): AthenaStatewireServerLane;
@@ -0,0 +1,24 @@
1
+ import { createContext } from "react";
2
+ const STATEWIRE_SERVER_LANE_PENDING = Object.freeze({
3
+ landed: false,
4
+ config: null
5
+ });
6
+ const AthenaStatewireServerLaneContext = createContext(
7
+ null
8
+ );
9
+ function nextServerLane({
10
+ previous,
11
+ config
12
+ }) {
13
+ var _a;
14
+ if (previous.landed && (((_a = previous.config) == null ? void 0 : _a.version) ?? 0) === ((config == null ? void 0 : config.version) ?? 0)) {
15
+ return previous;
16
+ }
17
+ return { landed: true, config };
18
+ }
19
+ export {
20
+ AthenaStatewireServerLaneContext,
21
+ STATEWIRE_SERVER_LANE_PENDING,
22
+ nextServerLane
23
+ };
24
+ //# sourceMappingURL=statewire-server-lane-context.js.map
@@ -0,0 +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 model\n * write in `StatewireModelLaneSync`) 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;"}