@athenaintel/react 0.59.0 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -19
- package/dist/agent-runtime/src/composer-markdown.cjs +0 -16
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.js +1 -17
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/named-agents.js +1 -1
- package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
- package/dist/agent-runtime/src/offline-status.d.ts +27 -0
- package/dist/agent-runtime/src/offline-status.js.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +7 -0
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +7 -0
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/chat/AthenaChat.cjs +15 -5
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.js +16 -6
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat-ui/index.cjs +2 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +1 -0
- package/dist/chat-ui/index.js +2 -0
- package/dist/chat-ui/index.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +9 -3
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.js +9 -3
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs +18 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.d.ts +10 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.js +19 -3
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +9 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +6 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js +9 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs +89 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs.map +1 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.d.ts +8 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js +89 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js.map +1 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs +140 -116
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.d.ts +46 -12
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js +141 -117
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +37 -6
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js +39 -8
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
- package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs +12 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs.map +1 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.d.ts +8 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.js +12 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.js.map +1 -0
- package/dist/collab/client.cjs +24 -1
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +16 -0
- package/dist/collab/client.js +24 -1
- package/dist/collab/client.js.map +1 -1
- package/dist/composer/attached-references.js +1 -1
- package/dist/composer/staged-message-metadata.cjs +12 -0
- package/dist/composer/staged-message-metadata.cjs.map +1 -0
- package/dist/composer/staged-message-metadata.d.ts +15 -0
- package/dist/composer/staged-message-metadata.js +12 -0
- package/dist/composer/staged-message-metadata.js.map +1 -0
- package/dist/data/athena-request.cjs +2 -0
- package/dist/data/athena-request.cjs.map +1 -1
- package/dist/data/athena-request.js +2 -0
- package/dist/data/athena-request.js.map +1 -1
- package/dist/provider/AthenaProvider.cjs +4 -3
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.js +4 -3
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/anchors/parse.cjs +11 -1
- package/dist/references/src/anchors/parse.cjs.map +1 -1
- package/dist/references/src/anchors/parse.js +11 -1
- package/dist/references/src/anchors/parse.js.map +1 -1
- package/dist/references/src/anchors/schemas.d.ts +1 -0
- package/dist/references/src/anchors/serialize.cjs +1 -0
- package/dist/references/src/anchors/serialize.cjs.map +1 -1
- package/dist/references/src/anchors/serialize.js +1 -0
- package/dist/references/src/anchors/serialize.js.map +1 -1
- package/dist/references/src/anchors/types.cjs.map +1 -1
- package/dist/references/src/anchors/types.d.ts +9 -0
- package/dist/references/src/anchors/types.js.map +1 -1
- package/dist/references/src/schemas.d.ts +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.cjs +6 -8
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.js +6 -8
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/threads/statewire-thread-list.cjs +14 -2
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.d.ts +11 -2
- package/dist/threads/statewire-thread-list.js +14 -2
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/tools/drive-tool-uis.cjs +8 -4
- package/dist/tools/drive-tool-uis.cjs.map +1 -1
- package/dist/tools/drive-tool-uis.d.ts +5 -4
- package/dist/tools/drive-tool-uis.js +9 -5
- package/dist/tools/drive-tool-uis.js.map +1 -1
- package/dist/version.cjs +4 -0
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.ts +9 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -1
- package/dist/workbench/live-desktop-api.cjs +2 -1
- package/dist/workbench/live-desktop-api.cjs.map +1 -1
- package/dist/workbench/live-desktop-api.js +2 -1
- package/dist/workbench/live-desktop-api.js.map +1 -1
- package/dist/workbench/session-workspace-api.cjs +7 -2
- package/dist/workbench/session-workspace-api.cjs.map +1 -1
- package/dist/workbench/session-workspace-api.d.ts +10 -0
- package/dist/workbench/session-workspace-api.js +7 -2
- package/dist/workbench/session-workspace-api.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","sources":["../../../../../references/src/anchors/types.ts"],"sourcesContent":["/**\n * Anchor types — Level 2 of the reference system.\n *\n * Each anchor describes a specific location within an asset.\n * Discriminated union on `type`. Ordered alphabetically.\n *\n * Property names use camelCase; the `type` discriminator string stays snake_case\n * (it's a version identifier, not a property name).\n */\n\n// ---------------------------------------------------------------------------\n// Individual anchor types (alphabetical by `type` discriminator)\n// ---------------------------------------------------------------------------\n\nexport type CellAnchor = { type: 'cell'; cellId: string };\nexport type CellRangeAnchor = {\n type: 'cell_range';\n startCellId: string;\n endCellId: string;\n};\nexport type CommentAnchor = {\n type: 'comment';\n threadId: string;\n commentId: string;\n};\nexport type CommentThreadAnchor = { type: 'comment_thread'; threadId: string };\n/**\n * An inclusive, 1-based line range of one file of a repository source — a\n * GitHub `catalog` asset whose files Clio indexes\n * (`docs/clio/21-repository-source.md`). `path` is the repo-relative,\n * `/`-separated file path: structure, not content. Distinct from the\n * path-less `line_range` so a reader that does not know the kind fails closed\n * instead of dropping the file. Bounds, path grammar and the byte cap are\n * shared with Clio's `LineRangeLocator` (`./file-line-range.ts`).\n *\n * Wire form (canonical — parameters sorted, as Clio writes it):\n * `anchor=file_line_range&end_line=<m>&path=<path>&start_line=<n>`.\n */\nexport type FileLineRangeAnchor = {\n type: 'file_line_range';\n path: string;\n startLine: number;\n endLine: number;\n};\nexport type LineAnchor = { type: 'line'; line: number };\nexport type LineRangeAnchor = {\n type: 'line_range';\n startLine: number;\n endLine: number;\n};\n/**\n * A single chat message in a session transcript.\n *\n * `messageId` is the **Athena message tracking id** — the same uuid4 that\n * appears as `user_message_tracking_id` / `ai_message_tracking_id` in Keryx\n * activity attributions (built by `build_agent_attributions`,\n * agora/services/keryx/client.py), as `trackingId` on session Y.Doc\n * liveMessages, as the `data-message-tracking-id` DOM attribute, and as the\n * existing `scroll_to_message` URL param in Olympus. It is NOT the LangChain\n * checkpoint `message.id`.\n *\n * Wire form: `anchor=msg&msg_id=…` (the pre-rename spellings\n * `anchor=message&message_id=…` are still parsed).\n */\nexport type MessageAnchor = { type: 'msg'; messageId: string };\n/**\n * Inclusive span of session messages in transcript order. Both ids are\n * Athena message tracking ids (see `MessageAnchor`).\n */\nexport type MessageRangeAnchor = {\n type: 'msg_range';\n startMessageId: string;\n endMessageId: string;\n};\n/**\n * One top-level block (paragraph, heading, list, table, code fence, …) of a\n * session message's markdown body. `messageId` is the Athena message tracking\n * id (see `MessageAnchor`); `block` is the 1-based position among the\n * message's top-level blocks. `hash` is an optional short fingerprint of the\n * block's normalized text (see `messageBlockHash`) so consumers can detect\n * that the block at that position no longer holds the linked content.\n *\n * URL params: `msg_id`, `block`, `hash`.\n */\nexport type MessageBlockAnchor = {\n type: 'msg_block';\n messageId: string;\n block: number;\n hash?: string;\n};\n/**\n * A heading-delimited section of a session message: the heading whose slug\n * (see `messageHeadingSlug`) equals `heading`, through the block before the\n * next heading of the same or a higher level. `nth` (1-based) disambiguates\n * repeated headings; absent ⇒ first.\n *\n * URL params: `msg_id`, `heading`, `nth`.\n */\nexport type MessageSectionAnchor = {\n type: 'msg_section';\n messageId: string;\n heading: string;\n nth?: number;\n};\n/**\n * An exact text span inside a session message. `text` is the quoted excerpt,\n * matched against the message's whitespace-normalized plain text (see\n * `normalizeMessageText`). Optional `block` narrows the search to one\n * top-level block (1-based); optional `prefix` / `suffix` are the normalized\n * text immediately before / after the span, used to pick between repeated\n * occurrences. Consumers fall back to the block, then the whole message, when\n * the span can't be found.\n *\n * URL params: `msg_id`, `text`, `block`, `prefix`, `suffix`.\n */\nexport type MessageTextAnchor = {\n type: 'msg_text';\n messageId: string;\n text: string;\n block?: number;\n prefix?: string;\n suffix?: string;\n};\nexport type PageAnchor = { type: 'page'; page: number };\n/**\n * A file path inside an asset, optionally narrowed to a 1-based source\n * location. `column` is only meaningful when `line` is present.\n */\nexport type PathAnchor = {\n type: 'path';\n path: string;\n line?: number;\n column?: number;\n};\nexport type PageRangeAnchor = {\n type: 'page_range';\n startPage: number;\n endPage: number;\n};\n/** Coordinate unit for a `page_rect` anchor. Absent ⇒ `percent`. */\nexport const PageRectUnit = {\n /** Percentages of the page dimensions (0-100). Resolution-independent. */\n Percent: 'percent',\n /**\n * PDF points (1/72\"), the unit of the legacy `bbox_left/bbox_top/...`\n * citation-URL params and of PDF viewer page coordinates.\n */\n Point: 'point',\n} as const;\n\nexport type PageRectUnit = (typeof PageRectUnit)[keyof typeof PageRectUnit];\n\n/**\n * Rectangular region on a specific page. `x`/`y`/`width`/`height` are in\n * `unit` coordinates — percentages of the page dimensions (0-100) when\n * `unit` is absent or `percent`, PDF points when `unit` is `point`.\n */\nexport type PageRectAnchor = {\n type: 'page_rect';\n page: number;\n x: number;\n y: number;\n width: number;\n height: number;\n unit?: PageRectUnit;\n};\n/**\n * A quoted text span on a specific page. `text` is the selected excerpt,\n * re-located by text search when the anchor is resolved. Optional `prefix` /\n * `suffix` are the normalized text immediately before / after the span, used\n * to pick between repeated occurrences of `text` on the page (the same\n * contract as `MessageTextAnchor`). Optional `hash` is a short fingerprint of\n * the cited unit's normalized text (the `MessageBlockAnchor` pattern:\n * `messageBlockHash`, 32-bit FNV-1a as 8 hex chars) so a consumer can tell a\n * stale citation from a live one and fall back to text search. The anchor\n * never stores geometry; rectangles are derived when it is resolved.\n *\n * URL params: `page`, `text`, `prefix`, `suffix`, `hash`.\n */\nexport type PageTextAnchor = {\n type: 'page_text';\n page: number;\n text: string;\n prefix?: string;\n suffix?: string;\n hash?: string;\n};\nexport type PmNodeAnchor = { type: 'pm_node'; nodeId: string };\nexport type PmNodeRangeAnchor = {\n type: 'pm_node_range';\n startNodeId: string;\n endNodeId: string;\n};\n/** Pixel-based region anchor for images. Coordinates relative to natural image dimensions. */\nexport type PixelRangeAnchor = {\n type: 'pixel_range';\n x: number;\n y: number;\n width: number;\n height: number;\n};\n/** ProseMirror mark pointer; composite `markType:instanceId` (e.g. CommentsKit `thread` + thread id). */\nexport type PmMarkAnchor = { type: 'pm_mark'; markId: string };\n/** Percentage-based region (0-100). Resolution-independent. */\nexport type RectAnchor = {\n type: 'rect';\n x: number;\n y: number;\n width: number;\n height: number;\n};\n/**\n * Named slice of an asset's persisted metadata (e.g. a computer asset's `status` / `ports`\n * section), or a section of a recording's generated notes (`decisions`, `action_items`,\n * `open_questions`, `notes`). `topic` is the 1-based `### topic` under a recording's Notes\n * (`section=notes&topic=2`), as Clio's notes hits name it; absent for every other section.\n */\nexport type SectionAnchor = { type: 'section'; section: string; topic?: number };\n/**\n * How a cited value relates to a generative (query) anchor's result.\n *\n * Absent ⇒ consumers MUST treat it as `supporting`. The (de)serializer never\n * defaults it, so round-trips stay exact.\n */\nexport const QueryResultRelationship = {\n /** The cell value IS (a cell of) the query result — a 1:1 extraction. */\n Exact: 'exact',\n /**\n * The cell value is authored (e.g. a narrative claim); the query result is\n * supporting evidence / justification, not the value itself. Re-running the\n * query is read-only verification and never replaces the cell value.\n */\n Supporting: 'supporting',\n} as const;\n\nexport type QueryResultRelationship =\n (typeof QueryResultRelationship)[keyof typeof QueryResultRelationship];\n\n/**\n * Generative anchor — a value derived from a semantic-model (Cube.js) query.\n *\n * Unlike positional anchors (page/cell/line), the \"location\" is the\n * transformation itself: the full Cube.js query spec that was run. Re-running\n * it is read-only verification; it never overwrites the cited value.\n */\nexport type SemanticQueryAnchor = {\n type: 'semantic_query';\n /** The full Cube.js query spec that produced the result (the codified transformation). */\n query: Record<string, unknown>;\n /** Cited measure/dimension id, e.g. `orders.total_revenue`. Omit ⇒ the whole result is the evidence. */\n field?: string;\n /** Dimension/key values identifying the cited row. Robust to re-ordering, unlike `rowIndex`. */\n rowKey?: Record<string, string>;\n /** Positional fallback row selector. */\n rowIndex?: number;\n /** Whether the cell value equals the result (`exact`) or is authored evidence (`supporting`). */\n relationship?: QueryResultRelationship;\n /** Provenance: semantic-model schema version at run time. */\n schemaVersion?: number;\n /** Provenance: sha256 of the deployed YAML at run time, for drift detection. */\n schemaHash?: string;\n /**\n * Provenance for lakehouse-backed models: each source table's Iceberg identity\n * and snapshot when the value was computed (`\"<namespace>.<table>\"` →\n * `\"<table_uuid>:<snapshot_id>\"`, the snapshot empty for a table never written).\n * Compared with the live tables by the freshness check.\n */\n sourceSnapshots?: Record<string, string>;\n /** Provenance: the result's \"data as of\" instant (ISO-8601 UTC) at capture. */\n dataAsOf?: string;\n};\n/**\n * One or more shapes on a presentation slide. `shapeIds` are stable Yjs\n * ElementIds (the SDK's `shape.shape_id`) and resolve the anchor on their\n * own; `slideId` / `slideIndex` (1-based) are optional refinements.\n */\nexport type ShapeAnchor = {\n type: 'shape';\n slideId?: string;\n slideIndex?: number;\n shapeIds: string[];\n};\n/**\n * A single cell. `chartId` (`chart=`) names the chart anchored at the cell\n * when the place is that chart, not the cell's value: a chart sits right of\n * and below its anchor cell, so a reader reveals it from that corner.\n */\nexport type SheetCellAnchor = {\n type: 'sheet_cell';\n sheetId: number;\n cell: string;\n chartId?: string;\n};\nexport type SheetRangeAnchor = {\n type: 'sheet_range';\n sheetId: number;\n range: string;\n /**\n * The spreadsheet engine's shift-log frontier (writer id → seq, `RncEngine.shiftLogFrontier`) the\n * moment `range` was taken, so a reader with the live engine can resolve the range to its current\n * coordinates after rows/columns were inserted or deleted since (`RncEngine.transformRange`).\n * Absent on an anchor taken without an engine, which resolves to `range` as stored.\n */\n frontier?: Record<string, number>;\n};\n/** A whole worksheet / sheet tab in a spreadsheet. */\nexport type SheetTabAnchor = {\n type: 'sheet_tab';\n sheetId: number;\n};\n/**\n * A named Excel table (ListObject) within a worksheet. Stable identity:\n * the table's name survives sorts, inserts, and row additions that would\n * break a raw `sheet_range`. Use this anchor in preference to\n * `sheet_range` whenever the user is binding to a structured table.\n *\n * `fallbackRange` is an optional A1-style range used by resolvers when\n * the table has been deleted or renamed — best-effort recovery.\n */\nexport type SheetTableAnchor = {\n type: 'sheet_table';\n sheetId: number;\n tableName: string;\n fallbackRange?: string;\n};\n/**\n * One table of an Orion lakehouse namespace, addressed on the namespace asset\n * (tables have no asset rows). `table` is the name within the namespace;\n * `tableUuid` is the Iceberg table UUID, the stable identity that detects a\n * drop-and-recreate or rename; `snapshotId` pins a read to one Iceberg\n * snapshot (an unsupported pinned read is rejected, never served from current\n * data).\n */\nexport type LakehouseTableAnchor = {\n type: 'lakehouse_table';\n table: string;\n tableUuid?: string;\n snapshotId?: string;\n};\n/**\n * A whole slide of a PPTX deck. `slideId` is the stable Yjs SlideId (the\n * SDK's `slide.slide_id`); `slideIndex` is the 1-based display position.\n * At least one must be present; producers should emit both when known.\n */\nexport type SlideAnchor = {\n type: 'slide';\n slideId?: string;\n slideIndex?: number;\n};\n/**\n * Generative anchor — a value derived from a SQL query.\n *\n * The transformation is the SQL text, carried inline or (preferred) as a\n * governed, re-runnable `query_snippet` asset. Re-running it is read-only\n * verification; it never overwrites the cited value.\n */\nexport type SqlQueryAnchor = {\n type: 'sql_query';\n /** The SQL that produced the result. Optional when `querySnippetAssetId` is set. */\n sql?: string;\n /** A re-runnable `query_snippet` asset that holds the SQL (preferred over inline `sql`). */\n querySnippetAssetId?: string;\n /** SQL dialect, e.g. `postgres`, `snowflake`. */\n dialect?: string;\n /** Cited result column name. Omit ⇒ the whole result is the evidence. */\n field?: string;\n /** Identifying column values for the cited row. Robust to re-ordering, unlike `rowIndex`. */\n rowKey?: Record<string, string>;\n /** Positional fallback row selector. */\n rowIndex?: number;\n /** Whether the cell value equals the result (`exact`) or is authored evidence (`supporting`). */\n relationship?: QueryResultRelationship;\n};\n/** Time string in \"H:MM:SS\" / \"MM:SS\" / \"M:SS\" format. No plain seconds. */\nexport type TimeAnchor = { type: 'time'; time: string };\nexport type TimeRangeAnchor = {\n type: 'time_range';\n startTime: string;\n endTime: string;\n};\n/**\n * A tool invocation in a session transcript. `toolCallId` is the\n * LangChain-native tool call id (the key used by session Y.Doc\n * liveToolCalls), NOT an Athena message tracking id. `messageId` is the\n * tracking id of the assistant message that issued the call, when the\n * producer knows it (Keryx activity carries both as `tool_call_id` and\n * `ai_message_tracking_id`); it lets a consumer still land on the owning\n * message when the call itself is not in view (e.g. an abandoned branch).\n */\nexport type ToolCallAnchor = { type: 'tool_call'; toolCallId: string; messageId?: string };\n\n// ---------------------------------------------------------------------------\n// Union\n// ---------------------------------------------------------------------------\n\nexport type Anchor =\n | CellAnchor\n | CellRangeAnchor\n | CommentAnchor\n | CommentThreadAnchor\n | FileLineRangeAnchor\n | LineAnchor\n | LineRangeAnchor\n | MessageAnchor\n | MessageRangeAnchor\n | MessageBlockAnchor\n | MessageSectionAnchor\n | MessageTextAnchor\n | PageAnchor\n | PageRangeAnchor\n | PathAnchor\n | PageRectAnchor\n | PageTextAnchor\n | PixelRangeAnchor\n | PmNodeAnchor\n | PmNodeRangeAnchor\n | PmMarkAnchor\n | RectAnchor\n | SectionAnchor\n | SemanticQueryAnchor\n | ShapeAnchor\n | SheetCellAnchor\n | SheetRangeAnchor\n | SheetTabAnchor\n | SheetTableAnchor\n | LakehouseTableAnchor\n | SlideAnchor\n | SqlQueryAnchor\n | TimeAnchor\n | TimeRangeAnchor\n | ToolCallAnchor;\n\n// ---------------------------------------------------------------------------\n// AnchorType — string literal union of all `type` discriminators\n// ---------------------------------------------------------------------------\n\nexport type AnchorType = Anchor['type'];\n\nexport const AnchorType = {\n Cell: 'cell',\n CellRange: 'cell_range',\n Comment: 'comment',\n CommentThread: 'comment_thread',\n FileLineRange: 'file_line_range',\n Line: 'line',\n LineRange: 'line_range',\n Message: 'msg',\n MessageRange: 'msg_range',\n MessageBlock: 'msg_block',\n MessageSection: 'msg_section',\n MessageText: 'msg_text',\n Page: 'page',\n PageRange: 'page_range',\n Path: 'path',\n PageRect: 'page_rect',\n PageText: 'page_text',\n PixelRange: 'pixel_range',\n PmMark: 'pm_mark',\n PmNode: 'pm_node',\n PmNodeRange: 'pm_node_range',\n Rect: 'rect',\n Section: 'section',\n SemanticQuery: 'semantic_query',\n Shape: 'shape',\n SheetCell: 'sheet_cell',\n SheetRange: 'sheet_range',\n SheetTab: 'sheet_tab',\n SheetTable: 'sheet_table',\n LakehouseTable: 'lakehouse_table',\n Slide: 'slide',\n SqlQuery: 'sql_query',\n Time: 'time',\n TimeRange: 'time_range',\n ToolCall: 'tool_call',\n} as const satisfies Record<string, AnchorType>;\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/**\n * Pre-rename session anchor spellings that are still accepted on input so\n * links shared before the `msg*` rename keep resolving. Output always uses\n * the current names (see `serialize.ts`).\n */\nexport const LEGACY_ANCHOR_TYPES: Readonly<Record<string, AnchorType>> = {\n message: 'msg',\n message_range: 'msg_range',\n};\n\nexport function isAnchorType(value: unknown): value is AnchorType {\n return typeof value === 'string' && Object.values(AnchorType).includes(value as AnchorType);\n}\n\n/**\n * Quick check: validates only the `type` discriminator string.\n * For full structural validation, use `parseAnchor` from `./schemas`.\n */\nexport function isAnchor(value: unknown): value is Anchor {\n if (typeof value !== 'object' || value === null) return false;\n return isAnchorType((value as Record<string, unknown>).type);\n}\n\n// ---------------------------------------------------------------------------\n// Runtime-only types (not stored, produced by accessors)\n// ---------------------------------------------------------------------------\n\n/** Runtime form of TimeAnchor with pre-computed seconds. */\nexport type TimeAnchorSeconds = { type: 'time_seconds'; timeSeconds: number };\n/** Runtime form of TimeRangeAnchor with pre-computed seconds. */\nexport type TimeRangeAnchorSeconds = {\n type: 'time_range_seconds';\n startTimeSeconds: number;\n endTimeSeconds: number;\n};\n"],"names":[],"mappings":";;AAsbO,MAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,eAAe;AAAA,EACf,eAAe;AAAA,EACf,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,WAAW;AAAA,EACX,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,MAAM;AAAA,EACN,SAAS;AAAA,EACT,eAAe;AAAA,EACf,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AACZ;AAWO,MAAM,sBAA4D;AAAA,EACvE,SAAS;AAAA,EACT,eAAe;AACjB;AAEO,SAAS,aAAa,OAAqC;AAChE,SAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,EAAE,SAAS,KAAmB;AAC5F;AAMO,SAAS,SAAS,OAAiC;AACxD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,SAAO,aAAc,MAAkC,IAAI;AAC7D;;;;;"}
|
|
1
|
+
{"version":3,"file":"types.cjs","sources":["../../../../../references/src/anchors/types.ts"],"sourcesContent":["/**\n * Anchor types — Level 2 of the reference system.\n *\n * Each anchor describes a specific location within an asset.\n * Discriminated union on `type`. Ordered alphabetically.\n *\n * Property names use camelCase; the `type` discriminator string stays snake_case\n * (it's a version identifier, not a property name).\n */\n\n// ---------------------------------------------------------------------------\n// Individual anchor types (alphabetical by `type` discriminator)\n// ---------------------------------------------------------------------------\n\nexport type CellAnchor = { type: 'cell'; cellId: string };\nexport type CellRangeAnchor = {\n type: 'cell_range';\n startCellId: string;\n endCellId: string;\n};\nexport type CommentAnchor = {\n type: 'comment';\n threadId: string;\n commentId: string;\n};\nexport type CommentThreadAnchor = { type: 'comment_thread'; threadId: string };\n/**\n * An inclusive, 1-based line range of one file of a repository source — a\n * GitHub `catalog` asset whose files Clio indexes\n * (`docs/clio/21-repository-source.md`). `path` is the repo-relative,\n * `/`-separated file path: structure, not content. Distinct from the\n * path-less `line_range` so a reader that does not know the kind fails closed\n * instead of dropping the file. Bounds, path grammar and the byte cap are\n * shared with Clio's `LineRangeLocator` (`./file-line-range.ts`).\n *\n * Wire form (canonical — parameters sorted, as Clio writes it):\n * `anchor=file_line_range&end_line=<m>&path=<path>&start_line=<n>`.\n */\nexport type FileLineRangeAnchor = {\n type: 'file_line_range';\n path: string;\n startLine: number;\n endLine: number;\n};\nexport type LineAnchor = { type: 'line'; line: number };\nexport type LineRangeAnchor = {\n type: 'line_range';\n startLine: number;\n endLine: number;\n};\n/**\n * A single chat message in a session transcript.\n *\n * `messageId` is the **Athena message tracking id** — the same uuid4 that\n * appears as `user_message_tracking_id` / `ai_message_tracking_id` in Keryx\n * activity attributions (built by `build_agent_attributions`,\n * agora/services/keryx/client.py), as `trackingId` on session Y.Doc\n * liveMessages, as the `data-message-tracking-id` DOM attribute, and as the\n * existing `scroll_to_message` URL param in Olympus. It is NOT the LangChain\n * checkpoint `message.id`.\n *\n * Wire form: `anchor=msg&msg_id=…` (the pre-rename spellings\n * `anchor=message&message_id=…` are still parsed).\n */\nexport type MessageAnchor = { type: 'msg'; messageId: string };\n/**\n * Inclusive span of session messages in transcript order. Both ids are\n * Athena message tracking ids (see `MessageAnchor`).\n */\nexport type MessageRangeAnchor = {\n type: 'msg_range';\n startMessageId: string;\n endMessageId: string;\n};\n/**\n * One top-level block (paragraph, heading, list, table, code fence, …) of a\n * session message's markdown body. `messageId` is the Athena message tracking\n * id (see `MessageAnchor`); `block` is the 1-based position among the\n * message's top-level blocks. `hash` is an optional short fingerprint of the\n * block's normalized text (see `messageBlockHash`) so consumers can detect\n * that the block at that position no longer holds the linked content.\n *\n * URL params: `msg_id`, `block`, `hash`.\n */\nexport type MessageBlockAnchor = {\n type: 'msg_block';\n messageId: string;\n block: number;\n hash?: string;\n};\n/**\n * A heading-delimited section of a session message: the heading whose slug\n * (see `messageHeadingSlug`) equals `heading`, through the block before the\n * next heading of the same or a higher level. `nth` (1-based) disambiguates\n * repeated headings; absent ⇒ first.\n *\n * URL params: `msg_id`, `heading`, `nth`.\n */\nexport type MessageSectionAnchor = {\n type: 'msg_section';\n messageId: string;\n heading: string;\n nth?: number;\n};\n/**\n * An exact text span inside a session message. `text` is the quoted excerpt,\n * matched against the message's whitespace-normalized plain text (see\n * `normalizeMessageText`). Optional `block` narrows the search to one\n * top-level block (1-based); optional `prefix` / `suffix` are the normalized\n * text immediately before / after the span, used to pick between repeated\n * occurrences. Consumers fall back to the block, then the whole message, when\n * the span can't be found.\n *\n * URL params: `msg_id`, `text`, `block`, `prefix`, `suffix`.\n */\nexport type MessageTextAnchor = {\n type: 'msg_text';\n messageId: string;\n text: string;\n block?: number;\n prefix?: string;\n suffix?: string;\n};\nexport type PageAnchor = { type: 'page'; page: number };\n/**\n * A file path inside an asset, optionally narrowed to a 1-based source\n * location. `column` is only meaningful when `line` is present.\n */\nexport type PathAnchor = {\n type: 'path';\n path: string;\n line?: number;\n column?: number;\n};\nexport type PageRangeAnchor = {\n type: 'page_range';\n startPage: number;\n endPage: number;\n};\n/** Coordinate unit for a `page_rect` anchor. Absent ⇒ `percent`. */\nexport const PageRectUnit = {\n /** Percentages of the page dimensions (0-100). Resolution-independent. */\n Percent: 'percent',\n /**\n * PDF points (1/72\"), the unit of the legacy `bbox_left/bbox_top/...`\n * citation-URL params and of PDF viewer page coordinates.\n */\n Point: 'point',\n} as const;\n\nexport type PageRectUnit = (typeof PageRectUnit)[keyof typeof PageRectUnit];\n\n/**\n * Rectangular region on a specific page. `x`/`y`/`width`/`height` are in\n * `unit` coordinates — percentages of the page dimensions (0-100) when\n * `unit` is absent or `percent`, PDF points when `unit` is `point`.\n */\nexport type PageRectAnchor = {\n type: 'page_rect';\n page: number;\n x: number;\n y: number;\n width: number;\n height: number;\n unit?: PageRectUnit;\n};\n/**\n * A quoted text span on a specific page. `text` is the selected excerpt,\n * re-located by text search when the anchor is resolved. Optional `prefix` /\n * `suffix` are the normalized text immediately before / after the span, used\n * to pick between repeated occurrences of `text` on the page (the same\n * contract as `MessageTextAnchor`). Optional `hash` is a short fingerprint of\n * the cited unit's normalized text (the `MessageBlockAnchor` pattern:\n * `messageBlockHash`, 32-bit FNV-1a as 8 hex chars) so a consumer can tell a\n * stale citation from a live one and fall back to text search. The anchor\n * never stores geometry; rectangles are derived when it is resolved.\n *\n * URL params: `page`, `text`, `prefix`, `suffix`, `hash`.\n */\nexport type PageTextAnchor = {\n type: 'page_text';\n page: number;\n text: string;\n prefix?: string;\n suffix?: string;\n hash?: string;\n};\nexport type PmNodeAnchor = { type: 'pm_node'; nodeId: string };\nexport type PmNodeRangeAnchor = {\n type: 'pm_node_range';\n startNodeId: string;\n endNodeId: string;\n};\n/** Pixel-based region anchor for images. Coordinates relative to natural image dimensions. */\nexport type PixelRangeAnchor = {\n type: 'pixel_range';\n x: number;\n y: number;\n width: number;\n height: number;\n};\n/** ProseMirror mark pointer; composite `markType:instanceId` (e.g. CommentsKit `thread` + thread id). */\nexport type PmMarkAnchor = { type: 'pm_mark'; markId: string };\n/** Percentage-based region (0-100). Resolution-independent. */\nexport type RectAnchor = {\n type: 'rect';\n x: number;\n y: number;\n width: number;\n height: number;\n};\n/**\n * Named slice of an asset's persisted metadata (e.g. a computer asset's `status` / `ports`\n * section), or a section of a recording's generated notes (`decisions`, `action_items`,\n * `open_questions`, `notes`). `topic` is the 1-based `### topic` under a recording's Notes\n * (`section=notes&topic=2`), as Clio's notes hits name it; absent for every other section.\n */\nexport type SectionAnchor = { type: 'section'; section: string; topic?: number };\n/**\n * How a cited value relates to a generative (query) anchor's result.\n *\n * Absent ⇒ consumers MUST treat it as `supporting`. The (de)serializer never\n * defaults it, so round-trips stay exact.\n */\nexport const QueryResultRelationship = {\n /** The cell value IS (a cell of) the query result — a 1:1 extraction. */\n Exact: 'exact',\n /**\n * The cell value is authored (e.g. a narrative claim); the query result is\n * supporting evidence / justification, not the value itself. Re-running the\n * query is read-only verification and never replaces the cell value.\n */\n Supporting: 'supporting',\n} as const;\n\nexport type QueryResultRelationship =\n (typeof QueryResultRelationship)[keyof typeof QueryResultRelationship];\n\n/**\n * Generative anchor — a value derived from a semantic-model (Cube.js) query.\n *\n * Unlike positional anchors (page/cell/line), the \"location\" is the\n * transformation itself: the full Cube.js query spec that was run. Re-running\n * it is read-only verification; it never overwrites the cited value.\n */\nexport type SemanticQueryAnchor = {\n type: 'semantic_query';\n /** The full Cube.js query spec that produced the result (the codified transformation). */\n query: Record<string, unknown>;\n /** Cited measure/dimension id, e.g. `orders.total_revenue`. Omit ⇒ the whole result is the evidence. */\n field?: string;\n /** Dimension/key values identifying the cited row. Robust to re-ordering, unlike `rowIndex`. */\n rowKey?: Record<string, string>;\n /** Positional fallback row selector. */\n rowIndex?: number;\n /** Whether the cell value equals the result (`exact`) or is authored evidence (`supporting`). */\n relationship?: QueryResultRelationship;\n /** Provenance: semantic-model schema version at run time. */\n schemaVersion?: number;\n /** Provenance: sha256 of the deployed YAML at run time, for drift detection. */\n schemaHash?: string;\n /**\n * Provenance for lakehouse-backed models: each source table's Iceberg identity\n * and snapshot when the value was computed (`\"<namespace>.<table>\"` →\n * `\"<table_uuid>:<snapshot_id>\"`, the snapshot empty for a table never written).\n * Compared with the live tables by the freshness check.\n */\n sourceSnapshots?: Record<string, string>;\n /** Provenance: the result's \"data as of\" instant (ISO-8601 UTC) at capture. */\n dataAsOf?: string;\n};\n/**\n * One or more shapes on a presentation slide. `shapeIds` are stable Yjs\n * ElementIds (the SDK's `shape.shape_id`) and resolve the anchor on their\n * own; `slideId` / `slideIndex` (1-based) are optional refinements.\n */\nexport type ShapeAnchor = {\n type: 'shape';\n slideId?: string;\n slideIndex?: number;\n shapeIds: string[];\n};\n/**\n * A single cell. `chartId` (`chart=`) names the chart anchored at the cell\n * when the place is that chart, not the cell's value: a chart sits right of\n * and below its anchor cell, so a reader reveals it from that corner.\n */\nexport type SheetCellAnchor = {\n type: 'sheet_cell';\n sheetId: number;\n cell: string;\n chartId?: string;\n};\nexport type SheetRangeAnchor = {\n type: 'sheet_range';\n sheetId: number;\n range: string;\n /**\n * The spreadsheet engine's shift-log frontier (writer id → seq, `RncEngine.shiftLogFrontier`) the\n * moment `range` was taken, so a reader with the live engine can resolve the range to its current\n * coordinates after rows/columns were inserted or deleted since (`RncEngine.transformRange`).\n * Absent on an anchor taken without an engine, which resolves to `range` as stored.\n */\n frontier?: Record<string, number>;\n /**\n * The engine's line anchor for `range` (`SpreadsheetEngine.anchorRange`: standard padded base64 of\n * the range's row and column ids), taken with `range` on a stable-ids (v5) document. A v5 sheet's\n * cells follow their row and column ids, so a range resolved positionally (`frontier`) can name\n * other cells than the data after concurrent inserts or deletes; a reader with the live engine\n * resolves this instead (`resolveAnchor`), and falls back to `frontier` / `range` without one.\n * Absent on a positional (v3) document, whose engine takes no line anchors.\n */\n stableRange?: string;\n};\n/** A whole worksheet / sheet tab in a spreadsheet. */\nexport type SheetTabAnchor = {\n type: 'sheet_tab';\n sheetId: number;\n};\n/**\n * A named Excel table (ListObject) within a worksheet. Stable identity:\n * the table's name survives sorts, inserts, and row additions that would\n * break a raw `sheet_range`. Use this anchor in preference to\n * `sheet_range` whenever the user is binding to a structured table.\n *\n * `fallbackRange` is an optional A1-style range used by resolvers when\n * the table has been deleted or renamed — best-effort recovery.\n */\nexport type SheetTableAnchor = {\n type: 'sheet_table';\n sheetId: number;\n tableName: string;\n fallbackRange?: string;\n};\n/**\n * One table of an Orion lakehouse namespace, addressed on the namespace asset\n * (tables have no asset rows). `table` is the name within the namespace;\n * `tableUuid` is the Iceberg table UUID, the stable identity that detects a\n * drop-and-recreate or rename; `snapshotId` pins a read to one Iceberg\n * snapshot (an unsupported pinned read is rejected, never served from current\n * data).\n */\nexport type LakehouseTableAnchor = {\n type: 'lakehouse_table';\n table: string;\n tableUuid?: string;\n snapshotId?: string;\n};\n/**\n * A whole slide of a PPTX deck. `slideId` is the stable Yjs SlideId (the\n * SDK's `slide.slide_id`); `slideIndex` is the 1-based display position.\n * At least one must be present; producers should emit both when known.\n */\nexport type SlideAnchor = {\n type: 'slide';\n slideId?: string;\n slideIndex?: number;\n};\n/**\n * Generative anchor — a value derived from a SQL query.\n *\n * The transformation is the SQL text, carried inline or (preferred) as a\n * governed, re-runnable `query_snippet` asset. Re-running it is read-only\n * verification; it never overwrites the cited value.\n */\nexport type SqlQueryAnchor = {\n type: 'sql_query';\n /** The SQL that produced the result. Optional when `querySnippetAssetId` is set. */\n sql?: string;\n /** A re-runnable `query_snippet` asset that holds the SQL (preferred over inline `sql`). */\n querySnippetAssetId?: string;\n /** SQL dialect, e.g. `postgres`, `snowflake`. */\n dialect?: string;\n /** Cited result column name. Omit ⇒ the whole result is the evidence. */\n field?: string;\n /** Identifying column values for the cited row. Robust to re-ordering, unlike `rowIndex`. */\n rowKey?: Record<string, string>;\n /** Positional fallback row selector. */\n rowIndex?: number;\n /** Whether the cell value equals the result (`exact`) or is authored evidence (`supporting`). */\n relationship?: QueryResultRelationship;\n};\n/** Time string in \"H:MM:SS\" / \"MM:SS\" / \"M:SS\" format. No plain seconds. */\nexport type TimeAnchor = { type: 'time'; time: string };\nexport type TimeRangeAnchor = {\n type: 'time_range';\n startTime: string;\n endTime: string;\n};\n/**\n * A tool invocation in a session transcript. `toolCallId` is the\n * LangChain-native tool call id (the key used by session Y.Doc\n * liveToolCalls), NOT an Athena message tracking id. `messageId` is the\n * tracking id of the assistant message that issued the call, when the\n * producer knows it (Keryx activity carries both as `tool_call_id` and\n * `ai_message_tracking_id`); it lets a consumer still land on the owning\n * message when the call itself is not in view (e.g. an abandoned branch).\n */\nexport type ToolCallAnchor = { type: 'tool_call'; toolCallId: string; messageId?: string };\n\n// ---------------------------------------------------------------------------\n// Union\n// ---------------------------------------------------------------------------\n\nexport type Anchor =\n | CellAnchor\n | CellRangeAnchor\n | CommentAnchor\n | CommentThreadAnchor\n | FileLineRangeAnchor\n | LineAnchor\n | LineRangeAnchor\n | MessageAnchor\n | MessageRangeAnchor\n | MessageBlockAnchor\n | MessageSectionAnchor\n | MessageTextAnchor\n | PageAnchor\n | PageRangeAnchor\n | PathAnchor\n | PageRectAnchor\n | PageTextAnchor\n | PixelRangeAnchor\n | PmNodeAnchor\n | PmNodeRangeAnchor\n | PmMarkAnchor\n | RectAnchor\n | SectionAnchor\n | SemanticQueryAnchor\n | ShapeAnchor\n | SheetCellAnchor\n | SheetRangeAnchor\n | SheetTabAnchor\n | SheetTableAnchor\n | LakehouseTableAnchor\n | SlideAnchor\n | SqlQueryAnchor\n | TimeAnchor\n | TimeRangeAnchor\n | ToolCallAnchor;\n\n// ---------------------------------------------------------------------------\n// AnchorType — string literal union of all `type` discriminators\n// ---------------------------------------------------------------------------\n\nexport type AnchorType = Anchor['type'];\n\nexport const AnchorType = {\n Cell: 'cell',\n CellRange: 'cell_range',\n Comment: 'comment',\n CommentThread: 'comment_thread',\n FileLineRange: 'file_line_range',\n Line: 'line',\n LineRange: 'line_range',\n Message: 'msg',\n MessageRange: 'msg_range',\n MessageBlock: 'msg_block',\n MessageSection: 'msg_section',\n MessageText: 'msg_text',\n Page: 'page',\n PageRange: 'page_range',\n Path: 'path',\n PageRect: 'page_rect',\n PageText: 'page_text',\n PixelRange: 'pixel_range',\n PmMark: 'pm_mark',\n PmNode: 'pm_node',\n PmNodeRange: 'pm_node_range',\n Rect: 'rect',\n Section: 'section',\n SemanticQuery: 'semantic_query',\n Shape: 'shape',\n SheetCell: 'sheet_cell',\n SheetRange: 'sheet_range',\n SheetTab: 'sheet_tab',\n SheetTable: 'sheet_table',\n LakehouseTable: 'lakehouse_table',\n Slide: 'slide',\n SqlQuery: 'sql_query',\n Time: 'time',\n TimeRange: 'time_range',\n ToolCall: 'tool_call',\n} as const satisfies Record<string, AnchorType>;\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/**\n * Pre-rename session anchor spellings that are still accepted on input so\n * links shared before the `msg*` rename keep resolving. Output always uses\n * the current names (see `serialize.ts`).\n */\nexport const LEGACY_ANCHOR_TYPES: Readonly<Record<string, AnchorType>> = {\n message: 'msg',\n message_range: 'msg_range',\n};\n\nexport function isAnchorType(value: unknown): value is AnchorType {\n return typeof value === 'string' && Object.values(AnchorType).includes(value as AnchorType);\n}\n\n/**\n * Quick check: validates only the `type` discriminator string.\n * For full structural validation, use `parseAnchor` from `./schemas`.\n */\nexport function isAnchor(value: unknown): value is Anchor {\n if (typeof value !== 'object' || value === null) return false;\n return isAnchorType((value as Record<string, unknown>).type);\n}\n\n// ---------------------------------------------------------------------------\n// Runtime-only types (not stored, produced by accessors)\n// ---------------------------------------------------------------------------\n\n/** Runtime form of TimeAnchor with pre-computed seconds. */\nexport type TimeAnchorSeconds = { type: 'time_seconds'; timeSeconds: number };\n/** Runtime form of TimeRangeAnchor with pre-computed seconds. */\nexport type TimeRangeAnchorSeconds = {\n type: 'time_range_seconds';\n startTimeSeconds: number;\n endTimeSeconds: number;\n};\n"],"names":[],"mappings":";;AA+bO,MAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,eAAe;AAAA,EACf,eAAe;AAAA,EACf,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,WAAW;AAAA,EACX,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,MAAM;AAAA,EACN,SAAS;AAAA,EACT,eAAe;AAAA,EACf,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AACZ;AAWO,MAAM,sBAA4D;AAAA,EACvE,SAAS;AAAA,EACT,eAAe;AACjB;AAEO,SAAS,aAAa,OAAqC;AAChE,SAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,EAAE,SAAS,KAAmB;AAC5F;AAMO,SAAS,SAAS,OAAiC;AACxD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,SAAO,aAAc,MAAkC,IAAI;AAC7D;;;;;"}
|
|
@@ -317,6 +317,15 @@ export type SheetRangeAnchor = {
|
|
|
317
317
|
* Absent on an anchor taken without an engine, which resolves to `range` as stored.
|
|
318
318
|
*/
|
|
319
319
|
frontier?: Record<string, number>;
|
|
320
|
+
/**
|
|
321
|
+
* The engine's line anchor for `range` (`SpreadsheetEngine.anchorRange`: standard padded base64 of
|
|
322
|
+
* the range's row and column ids), taken with `range` on a stable-ids (v5) document. A v5 sheet's
|
|
323
|
+
* cells follow their row and column ids, so a range resolved positionally (`frontier`) can name
|
|
324
|
+
* other cells than the data after concurrent inserts or deletes; a reader with the live engine
|
|
325
|
+
* resolves this instead (`resolveAnchor`), and falls back to `frontier` / `range` without one.
|
|
326
|
+
* Absent on a positional (v3) document, whose engine takes no line anchors.
|
|
327
|
+
*/
|
|
328
|
+
stableRange?: string;
|
|
320
329
|
};
|
|
321
330
|
/** A whole worksheet / sheet tab in a spreadsheet. */
|
|
322
331
|
export type SheetTabAnchor = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../../../../references/src/anchors/types.ts"],"sourcesContent":["/**\n * Anchor types — Level 2 of the reference system.\n *\n * Each anchor describes a specific location within an asset.\n * Discriminated union on `type`. Ordered alphabetically.\n *\n * Property names use camelCase; the `type` discriminator string stays snake_case\n * (it's a version identifier, not a property name).\n */\n\n// ---------------------------------------------------------------------------\n// Individual anchor types (alphabetical by `type` discriminator)\n// ---------------------------------------------------------------------------\n\nexport type CellAnchor = { type: 'cell'; cellId: string };\nexport type CellRangeAnchor = {\n type: 'cell_range';\n startCellId: string;\n endCellId: string;\n};\nexport type CommentAnchor = {\n type: 'comment';\n threadId: string;\n commentId: string;\n};\nexport type CommentThreadAnchor = { type: 'comment_thread'; threadId: string };\n/**\n * An inclusive, 1-based line range of one file of a repository source — a\n * GitHub `catalog` asset whose files Clio indexes\n * (`docs/clio/21-repository-source.md`). `path` is the repo-relative,\n * `/`-separated file path: structure, not content. Distinct from the\n * path-less `line_range` so a reader that does not know the kind fails closed\n * instead of dropping the file. Bounds, path grammar and the byte cap are\n * shared with Clio's `LineRangeLocator` (`./file-line-range.ts`).\n *\n * Wire form (canonical — parameters sorted, as Clio writes it):\n * `anchor=file_line_range&end_line=<m>&path=<path>&start_line=<n>`.\n */\nexport type FileLineRangeAnchor = {\n type: 'file_line_range';\n path: string;\n startLine: number;\n endLine: number;\n};\nexport type LineAnchor = { type: 'line'; line: number };\nexport type LineRangeAnchor = {\n type: 'line_range';\n startLine: number;\n endLine: number;\n};\n/**\n * A single chat message in a session transcript.\n *\n * `messageId` is the **Athena message tracking id** — the same uuid4 that\n * appears as `user_message_tracking_id` / `ai_message_tracking_id` in Keryx\n * activity attributions (built by `build_agent_attributions`,\n * agora/services/keryx/client.py), as `trackingId` on session Y.Doc\n * liveMessages, as the `data-message-tracking-id` DOM attribute, and as the\n * existing `scroll_to_message` URL param in Olympus. It is NOT the LangChain\n * checkpoint `message.id`.\n *\n * Wire form: `anchor=msg&msg_id=…` (the pre-rename spellings\n * `anchor=message&message_id=…` are still parsed).\n */\nexport type MessageAnchor = { type: 'msg'; messageId: string };\n/**\n * Inclusive span of session messages in transcript order. Both ids are\n * Athena message tracking ids (see `MessageAnchor`).\n */\nexport type MessageRangeAnchor = {\n type: 'msg_range';\n startMessageId: string;\n endMessageId: string;\n};\n/**\n * One top-level block (paragraph, heading, list, table, code fence, …) of a\n * session message's markdown body. `messageId` is the Athena message tracking\n * id (see `MessageAnchor`); `block` is the 1-based position among the\n * message's top-level blocks. `hash` is an optional short fingerprint of the\n * block's normalized text (see `messageBlockHash`) so consumers can detect\n * that the block at that position no longer holds the linked content.\n *\n * URL params: `msg_id`, `block`, `hash`.\n */\nexport type MessageBlockAnchor = {\n type: 'msg_block';\n messageId: string;\n block: number;\n hash?: string;\n};\n/**\n * A heading-delimited section of a session message: the heading whose slug\n * (see `messageHeadingSlug`) equals `heading`, through the block before the\n * next heading of the same or a higher level. `nth` (1-based) disambiguates\n * repeated headings; absent ⇒ first.\n *\n * URL params: `msg_id`, `heading`, `nth`.\n */\nexport type MessageSectionAnchor = {\n type: 'msg_section';\n messageId: string;\n heading: string;\n nth?: number;\n};\n/**\n * An exact text span inside a session message. `text` is the quoted excerpt,\n * matched against the message's whitespace-normalized plain text (see\n * `normalizeMessageText`). Optional `block` narrows the search to one\n * top-level block (1-based); optional `prefix` / `suffix` are the normalized\n * text immediately before / after the span, used to pick between repeated\n * occurrences. Consumers fall back to the block, then the whole message, when\n * the span can't be found.\n *\n * URL params: `msg_id`, `text`, `block`, `prefix`, `suffix`.\n */\nexport type MessageTextAnchor = {\n type: 'msg_text';\n messageId: string;\n text: string;\n block?: number;\n prefix?: string;\n suffix?: string;\n};\nexport type PageAnchor = { type: 'page'; page: number };\n/**\n * A file path inside an asset, optionally narrowed to a 1-based source\n * location. `column` is only meaningful when `line` is present.\n */\nexport type PathAnchor = {\n type: 'path';\n path: string;\n line?: number;\n column?: number;\n};\nexport type PageRangeAnchor = {\n type: 'page_range';\n startPage: number;\n endPage: number;\n};\n/** Coordinate unit for a `page_rect` anchor. Absent ⇒ `percent`. */\nexport const PageRectUnit = {\n /** Percentages of the page dimensions (0-100). Resolution-independent. */\n Percent: 'percent',\n /**\n * PDF points (1/72\"), the unit of the legacy `bbox_left/bbox_top/...`\n * citation-URL params and of PDF viewer page coordinates.\n */\n Point: 'point',\n} as const;\n\nexport type PageRectUnit = (typeof PageRectUnit)[keyof typeof PageRectUnit];\n\n/**\n * Rectangular region on a specific page. `x`/`y`/`width`/`height` are in\n * `unit` coordinates — percentages of the page dimensions (0-100) when\n * `unit` is absent or `percent`, PDF points when `unit` is `point`.\n */\nexport type PageRectAnchor = {\n type: 'page_rect';\n page: number;\n x: number;\n y: number;\n width: number;\n height: number;\n unit?: PageRectUnit;\n};\n/**\n * A quoted text span on a specific page. `text` is the selected excerpt,\n * re-located by text search when the anchor is resolved. Optional `prefix` /\n * `suffix` are the normalized text immediately before / after the span, used\n * to pick between repeated occurrences of `text` on the page (the same\n * contract as `MessageTextAnchor`). Optional `hash` is a short fingerprint of\n * the cited unit's normalized text (the `MessageBlockAnchor` pattern:\n * `messageBlockHash`, 32-bit FNV-1a as 8 hex chars) so a consumer can tell a\n * stale citation from a live one and fall back to text search. The anchor\n * never stores geometry; rectangles are derived when it is resolved.\n *\n * URL params: `page`, `text`, `prefix`, `suffix`, `hash`.\n */\nexport type PageTextAnchor = {\n type: 'page_text';\n page: number;\n text: string;\n prefix?: string;\n suffix?: string;\n hash?: string;\n};\nexport type PmNodeAnchor = { type: 'pm_node'; nodeId: string };\nexport type PmNodeRangeAnchor = {\n type: 'pm_node_range';\n startNodeId: string;\n endNodeId: string;\n};\n/** Pixel-based region anchor for images. Coordinates relative to natural image dimensions. */\nexport type PixelRangeAnchor = {\n type: 'pixel_range';\n x: number;\n y: number;\n width: number;\n height: number;\n};\n/** ProseMirror mark pointer; composite `markType:instanceId` (e.g. CommentsKit `thread` + thread id). */\nexport type PmMarkAnchor = { type: 'pm_mark'; markId: string };\n/** Percentage-based region (0-100). Resolution-independent. */\nexport type RectAnchor = {\n type: 'rect';\n x: number;\n y: number;\n width: number;\n height: number;\n};\n/**\n * Named slice of an asset's persisted metadata (e.g. a computer asset's `status` / `ports`\n * section), or a section of a recording's generated notes (`decisions`, `action_items`,\n * `open_questions`, `notes`). `topic` is the 1-based `### topic` under a recording's Notes\n * (`section=notes&topic=2`), as Clio's notes hits name it; absent for every other section.\n */\nexport type SectionAnchor = { type: 'section'; section: string; topic?: number };\n/**\n * How a cited value relates to a generative (query) anchor's result.\n *\n * Absent ⇒ consumers MUST treat it as `supporting`. The (de)serializer never\n * defaults it, so round-trips stay exact.\n */\nexport const QueryResultRelationship = {\n /** The cell value IS (a cell of) the query result — a 1:1 extraction. */\n Exact: 'exact',\n /**\n * The cell value is authored (e.g. a narrative claim); the query result is\n * supporting evidence / justification, not the value itself. Re-running the\n * query is read-only verification and never replaces the cell value.\n */\n Supporting: 'supporting',\n} as const;\n\nexport type QueryResultRelationship =\n (typeof QueryResultRelationship)[keyof typeof QueryResultRelationship];\n\n/**\n * Generative anchor — a value derived from a semantic-model (Cube.js) query.\n *\n * Unlike positional anchors (page/cell/line), the \"location\" is the\n * transformation itself: the full Cube.js query spec that was run. Re-running\n * it is read-only verification; it never overwrites the cited value.\n */\nexport type SemanticQueryAnchor = {\n type: 'semantic_query';\n /** The full Cube.js query spec that produced the result (the codified transformation). */\n query: Record<string, unknown>;\n /** Cited measure/dimension id, e.g. `orders.total_revenue`. Omit ⇒ the whole result is the evidence. */\n field?: string;\n /** Dimension/key values identifying the cited row. Robust to re-ordering, unlike `rowIndex`. */\n rowKey?: Record<string, string>;\n /** Positional fallback row selector. */\n rowIndex?: number;\n /** Whether the cell value equals the result (`exact`) or is authored evidence (`supporting`). */\n relationship?: QueryResultRelationship;\n /** Provenance: semantic-model schema version at run time. */\n schemaVersion?: number;\n /** Provenance: sha256 of the deployed YAML at run time, for drift detection. */\n schemaHash?: string;\n /**\n * Provenance for lakehouse-backed models: each source table's Iceberg identity\n * and snapshot when the value was computed (`\"<namespace>.<table>\"` →\n * `\"<table_uuid>:<snapshot_id>\"`, the snapshot empty for a table never written).\n * Compared with the live tables by the freshness check.\n */\n sourceSnapshots?: Record<string, string>;\n /** Provenance: the result's \"data as of\" instant (ISO-8601 UTC) at capture. */\n dataAsOf?: string;\n};\n/**\n * One or more shapes on a presentation slide. `shapeIds` are stable Yjs\n * ElementIds (the SDK's `shape.shape_id`) and resolve the anchor on their\n * own; `slideId` / `slideIndex` (1-based) are optional refinements.\n */\nexport type ShapeAnchor = {\n type: 'shape';\n slideId?: string;\n slideIndex?: number;\n shapeIds: string[];\n};\n/**\n * A single cell. `chartId` (`chart=`) names the chart anchored at the cell\n * when the place is that chart, not the cell's value: a chart sits right of\n * and below its anchor cell, so a reader reveals it from that corner.\n */\nexport type SheetCellAnchor = {\n type: 'sheet_cell';\n sheetId: number;\n cell: string;\n chartId?: string;\n};\nexport type SheetRangeAnchor = {\n type: 'sheet_range';\n sheetId: number;\n range: string;\n /**\n * The spreadsheet engine's shift-log frontier (writer id → seq, `RncEngine.shiftLogFrontier`) the\n * moment `range` was taken, so a reader with the live engine can resolve the range to its current\n * coordinates after rows/columns were inserted or deleted since (`RncEngine.transformRange`).\n * Absent on an anchor taken without an engine, which resolves to `range` as stored.\n */\n frontier?: Record<string, number>;\n};\n/** A whole worksheet / sheet tab in a spreadsheet. */\nexport type SheetTabAnchor = {\n type: 'sheet_tab';\n sheetId: number;\n};\n/**\n * A named Excel table (ListObject) within a worksheet. Stable identity:\n * the table's name survives sorts, inserts, and row additions that would\n * break a raw `sheet_range`. Use this anchor in preference to\n * `sheet_range` whenever the user is binding to a structured table.\n *\n * `fallbackRange` is an optional A1-style range used by resolvers when\n * the table has been deleted or renamed — best-effort recovery.\n */\nexport type SheetTableAnchor = {\n type: 'sheet_table';\n sheetId: number;\n tableName: string;\n fallbackRange?: string;\n};\n/**\n * One table of an Orion lakehouse namespace, addressed on the namespace asset\n * (tables have no asset rows). `table` is the name within the namespace;\n * `tableUuid` is the Iceberg table UUID, the stable identity that detects a\n * drop-and-recreate or rename; `snapshotId` pins a read to one Iceberg\n * snapshot (an unsupported pinned read is rejected, never served from current\n * data).\n */\nexport type LakehouseTableAnchor = {\n type: 'lakehouse_table';\n table: string;\n tableUuid?: string;\n snapshotId?: string;\n};\n/**\n * A whole slide of a PPTX deck. `slideId` is the stable Yjs SlideId (the\n * SDK's `slide.slide_id`); `slideIndex` is the 1-based display position.\n * At least one must be present; producers should emit both when known.\n */\nexport type SlideAnchor = {\n type: 'slide';\n slideId?: string;\n slideIndex?: number;\n};\n/**\n * Generative anchor — a value derived from a SQL query.\n *\n * The transformation is the SQL text, carried inline or (preferred) as a\n * governed, re-runnable `query_snippet` asset. Re-running it is read-only\n * verification; it never overwrites the cited value.\n */\nexport type SqlQueryAnchor = {\n type: 'sql_query';\n /** The SQL that produced the result. Optional when `querySnippetAssetId` is set. */\n sql?: string;\n /** A re-runnable `query_snippet` asset that holds the SQL (preferred over inline `sql`). */\n querySnippetAssetId?: string;\n /** SQL dialect, e.g. `postgres`, `snowflake`. */\n dialect?: string;\n /** Cited result column name. Omit ⇒ the whole result is the evidence. */\n field?: string;\n /** Identifying column values for the cited row. Robust to re-ordering, unlike `rowIndex`. */\n rowKey?: Record<string, string>;\n /** Positional fallback row selector. */\n rowIndex?: number;\n /** Whether the cell value equals the result (`exact`) or is authored evidence (`supporting`). */\n relationship?: QueryResultRelationship;\n};\n/** Time string in \"H:MM:SS\" / \"MM:SS\" / \"M:SS\" format. No plain seconds. */\nexport type TimeAnchor = { type: 'time'; time: string };\nexport type TimeRangeAnchor = {\n type: 'time_range';\n startTime: string;\n endTime: string;\n};\n/**\n * A tool invocation in a session transcript. `toolCallId` is the\n * LangChain-native tool call id (the key used by session Y.Doc\n * liveToolCalls), NOT an Athena message tracking id. `messageId` is the\n * tracking id of the assistant message that issued the call, when the\n * producer knows it (Keryx activity carries both as `tool_call_id` and\n * `ai_message_tracking_id`); it lets a consumer still land on the owning\n * message when the call itself is not in view (e.g. an abandoned branch).\n */\nexport type ToolCallAnchor = { type: 'tool_call'; toolCallId: string; messageId?: string };\n\n// ---------------------------------------------------------------------------\n// Union\n// ---------------------------------------------------------------------------\n\nexport type Anchor =\n | CellAnchor\n | CellRangeAnchor\n | CommentAnchor\n | CommentThreadAnchor\n | FileLineRangeAnchor\n | LineAnchor\n | LineRangeAnchor\n | MessageAnchor\n | MessageRangeAnchor\n | MessageBlockAnchor\n | MessageSectionAnchor\n | MessageTextAnchor\n | PageAnchor\n | PageRangeAnchor\n | PathAnchor\n | PageRectAnchor\n | PageTextAnchor\n | PixelRangeAnchor\n | PmNodeAnchor\n | PmNodeRangeAnchor\n | PmMarkAnchor\n | RectAnchor\n | SectionAnchor\n | SemanticQueryAnchor\n | ShapeAnchor\n | SheetCellAnchor\n | SheetRangeAnchor\n | SheetTabAnchor\n | SheetTableAnchor\n | LakehouseTableAnchor\n | SlideAnchor\n | SqlQueryAnchor\n | TimeAnchor\n | TimeRangeAnchor\n | ToolCallAnchor;\n\n// ---------------------------------------------------------------------------\n// AnchorType — string literal union of all `type` discriminators\n// ---------------------------------------------------------------------------\n\nexport type AnchorType = Anchor['type'];\n\nexport const AnchorType = {\n Cell: 'cell',\n CellRange: 'cell_range',\n Comment: 'comment',\n CommentThread: 'comment_thread',\n FileLineRange: 'file_line_range',\n Line: 'line',\n LineRange: 'line_range',\n Message: 'msg',\n MessageRange: 'msg_range',\n MessageBlock: 'msg_block',\n MessageSection: 'msg_section',\n MessageText: 'msg_text',\n Page: 'page',\n PageRange: 'page_range',\n Path: 'path',\n PageRect: 'page_rect',\n PageText: 'page_text',\n PixelRange: 'pixel_range',\n PmMark: 'pm_mark',\n PmNode: 'pm_node',\n PmNodeRange: 'pm_node_range',\n Rect: 'rect',\n Section: 'section',\n SemanticQuery: 'semantic_query',\n Shape: 'shape',\n SheetCell: 'sheet_cell',\n SheetRange: 'sheet_range',\n SheetTab: 'sheet_tab',\n SheetTable: 'sheet_table',\n LakehouseTable: 'lakehouse_table',\n Slide: 'slide',\n SqlQuery: 'sql_query',\n Time: 'time',\n TimeRange: 'time_range',\n ToolCall: 'tool_call',\n} as const satisfies Record<string, AnchorType>;\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/**\n * Pre-rename session anchor spellings that are still accepted on input so\n * links shared before the `msg*` rename keep resolving. Output always uses\n * the current names (see `serialize.ts`).\n */\nexport const LEGACY_ANCHOR_TYPES: Readonly<Record<string, AnchorType>> = {\n message: 'msg',\n message_range: 'msg_range',\n};\n\nexport function isAnchorType(value: unknown): value is AnchorType {\n return typeof value === 'string' && Object.values(AnchorType).includes(value as AnchorType);\n}\n\n/**\n * Quick check: validates only the `type` discriminator string.\n * For full structural validation, use `parseAnchor` from `./schemas`.\n */\nexport function isAnchor(value: unknown): value is Anchor {\n if (typeof value !== 'object' || value === null) return false;\n return isAnchorType((value as Record<string, unknown>).type);\n}\n\n// ---------------------------------------------------------------------------\n// Runtime-only types (not stored, produced by accessors)\n// ---------------------------------------------------------------------------\n\n/** Runtime form of TimeAnchor with pre-computed seconds. */\nexport type TimeAnchorSeconds = { type: 'time_seconds'; timeSeconds: number };\n/** Runtime form of TimeRangeAnchor with pre-computed seconds. */\nexport type TimeRangeAnchorSeconds = {\n type: 'time_range_seconds';\n startTimeSeconds: number;\n endTimeSeconds: number;\n};\n"],"names":[],"mappings":"AAsbO,MAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,eAAe;AAAA,EACf,eAAe;AAAA,EACf,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,WAAW;AAAA,EACX,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,MAAM;AAAA,EACN,SAAS;AAAA,EACT,eAAe;AAAA,EACf,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AACZ;AAWO,MAAM,sBAA4D;AAAA,EACvE,SAAS;AAAA,EACT,eAAe;AACjB;AAEO,SAAS,aAAa,OAAqC;AAChE,SAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,EAAE,SAAS,KAAmB;AAC5F;AAMO,SAAS,SAAS,OAAiC;AACxD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,SAAO,aAAc,MAAkC,IAAI;AAC7D;"}
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../../../../references/src/anchors/types.ts"],"sourcesContent":["/**\n * Anchor types — Level 2 of the reference system.\n *\n * Each anchor describes a specific location within an asset.\n * Discriminated union on `type`. Ordered alphabetically.\n *\n * Property names use camelCase; the `type` discriminator string stays snake_case\n * (it's a version identifier, not a property name).\n */\n\n// ---------------------------------------------------------------------------\n// Individual anchor types (alphabetical by `type` discriminator)\n// ---------------------------------------------------------------------------\n\nexport type CellAnchor = { type: 'cell'; cellId: string };\nexport type CellRangeAnchor = {\n type: 'cell_range';\n startCellId: string;\n endCellId: string;\n};\nexport type CommentAnchor = {\n type: 'comment';\n threadId: string;\n commentId: string;\n};\nexport type CommentThreadAnchor = { type: 'comment_thread'; threadId: string };\n/**\n * An inclusive, 1-based line range of one file of a repository source — a\n * GitHub `catalog` asset whose files Clio indexes\n * (`docs/clio/21-repository-source.md`). `path` is the repo-relative,\n * `/`-separated file path: structure, not content. Distinct from the\n * path-less `line_range` so a reader that does not know the kind fails closed\n * instead of dropping the file. Bounds, path grammar and the byte cap are\n * shared with Clio's `LineRangeLocator` (`./file-line-range.ts`).\n *\n * Wire form (canonical — parameters sorted, as Clio writes it):\n * `anchor=file_line_range&end_line=<m>&path=<path>&start_line=<n>`.\n */\nexport type FileLineRangeAnchor = {\n type: 'file_line_range';\n path: string;\n startLine: number;\n endLine: number;\n};\nexport type LineAnchor = { type: 'line'; line: number };\nexport type LineRangeAnchor = {\n type: 'line_range';\n startLine: number;\n endLine: number;\n};\n/**\n * A single chat message in a session transcript.\n *\n * `messageId` is the **Athena message tracking id** — the same uuid4 that\n * appears as `user_message_tracking_id` / `ai_message_tracking_id` in Keryx\n * activity attributions (built by `build_agent_attributions`,\n * agora/services/keryx/client.py), as `trackingId` on session Y.Doc\n * liveMessages, as the `data-message-tracking-id` DOM attribute, and as the\n * existing `scroll_to_message` URL param in Olympus. It is NOT the LangChain\n * checkpoint `message.id`.\n *\n * Wire form: `anchor=msg&msg_id=…` (the pre-rename spellings\n * `anchor=message&message_id=…` are still parsed).\n */\nexport type MessageAnchor = { type: 'msg'; messageId: string };\n/**\n * Inclusive span of session messages in transcript order. Both ids are\n * Athena message tracking ids (see `MessageAnchor`).\n */\nexport type MessageRangeAnchor = {\n type: 'msg_range';\n startMessageId: string;\n endMessageId: string;\n};\n/**\n * One top-level block (paragraph, heading, list, table, code fence, …) of a\n * session message's markdown body. `messageId` is the Athena message tracking\n * id (see `MessageAnchor`); `block` is the 1-based position among the\n * message's top-level blocks. `hash` is an optional short fingerprint of the\n * block's normalized text (see `messageBlockHash`) so consumers can detect\n * that the block at that position no longer holds the linked content.\n *\n * URL params: `msg_id`, `block`, `hash`.\n */\nexport type MessageBlockAnchor = {\n type: 'msg_block';\n messageId: string;\n block: number;\n hash?: string;\n};\n/**\n * A heading-delimited section of a session message: the heading whose slug\n * (see `messageHeadingSlug`) equals `heading`, through the block before the\n * next heading of the same or a higher level. `nth` (1-based) disambiguates\n * repeated headings; absent ⇒ first.\n *\n * URL params: `msg_id`, `heading`, `nth`.\n */\nexport type MessageSectionAnchor = {\n type: 'msg_section';\n messageId: string;\n heading: string;\n nth?: number;\n};\n/**\n * An exact text span inside a session message. `text` is the quoted excerpt,\n * matched against the message's whitespace-normalized plain text (see\n * `normalizeMessageText`). Optional `block` narrows the search to one\n * top-level block (1-based); optional `prefix` / `suffix` are the normalized\n * text immediately before / after the span, used to pick between repeated\n * occurrences. Consumers fall back to the block, then the whole message, when\n * the span can't be found.\n *\n * URL params: `msg_id`, `text`, `block`, `prefix`, `suffix`.\n */\nexport type MessageTextAnchor = {\n type: 'msg_text';\n messageId: string;\n text: string;\n block?: number;\n prefix?: string;\n suffix?: string;\n};\nexport type PageAnchor = { type: 'page'; page: number };\n/**\n * A file path inside an asset, optionally narrowed to a 1-based source\n * location. `column` is only meaningful when `line` is present.\n */\nexport type PathAnchor = {\n type: 'path';\n path: string;\n line?: number;\n column?: number;\n};\nexport type PageRangeAnchor = {\n type: 'page_range';\n startPage: number;\n endPage: number;\n};\n/** Coordinate unit for a `page_rect` anchor. Absent ⇒ `percent`. */\nexport const PageRectUnit = {\n /** Percentages of the page dimensions (0-100). Resolution-independent. */\n Percent: 'percent',\n /**\n * PDF points (1/72\"), the unit of the legacy `bbox_left/bbox_top/...`\n * citation-URL params and of PDF viewer page coordinates.\n */\n Point: 'point',\n} as const;\n\nexport type PageRectUnit = (typeof PageRectUnit)[keyof typeof PageRectUnit];\n\n/**\n * Rectangular region on a specific page. `x`/`y`/`width`/`height` are in\n * `unit` coordinates — percentages of the page dimensions (0-100) when\n * `unit` is absent or `percent`, PDF points when `unit` is `point`.\n */\nexport type PageRectAnchor = {\n type: 'page_rect';\n page: number;\n x: number;\n y: number;\n width: number;\n height: number;\n unit?: PageRectUnit;\n};\n/**\n * A quoted text span on a specific page. `text` is the selected excerpt,\n * re-located by text search when the anchor is resolved. Optional `prefix` /\n * `suffix` are the normalized text immediately before / after the span, used\n * to pick between repeated occurrences of `text` on the page (the same\n * contract as `MessageTextAnchor`). Optional `hash` is a short fingerprint of\n * the cited unit's normalized text (the `MessageBlockAnchor` pattern:\n * `messageBlockHash`, 32-bit FNV-1a as 8 hex chars) so a consumer can tell a\n * stale citation from a live one and fall back to text search. The anchor\n * never stores geometry; rectangles are derived when it is resolved.\n *\n * URL params: `page`, `text`, `prefix`, `suffix`, `hash`.\n */\nexport type PageTextAnchor = {\n type: 'page_text';\n page: number;\n text: string;\n prefix?: string;\n suffix?: string;\n hash?: string;\n};\nexport type PmNodeAnchor = { type: 'pm_node'; nodeId: string };\nexport type PmNodeRangeAnchor = {\n type: 'pm_node_range';\n startNodeId: string;\n endNodeId: string;\n};\n/** Pixel-based region anchor for images. Coordinates relative to natural image dimensions. */\nexport type PixelRangeAnchor = {\n type: 'pixel_range';\n x: number;\n y: number;\n width: number;\n height: number;\n};\n/** ProseMirror mark pointer; composite `markType:instanceId` (e.g. CommentsKit `thread` + thread id). */\nexport type PmMarkAnchor = { type: 'pm_mark'; markId: string };\n/** Percentage-based region (0-100). Resolution-independent. */\nexport type RectAnchor = {\n type: 'rect';\n x: number;\n y: number;\n width: number;\n height: number;\n};\n/**\n * Named slice of an asset's persisted metadata (e.g. a computer asset's `status` / `ports`\n * section), or a section of a recording's generated notes (`decisions`, `action_items`,\n * `open_questions`, `notes`). `topic` is the 1-based `### topic` under a recording's Notes\n * (`section=notes&topic=2`), as Clio's notes hits name it; absent for every other section.\n */\nexport type SectionAnchor = { type: 'section'; section: string; topic?: number };\n/**\n * How a cited value relates to a generative (query) anchor's result.\n *\n * Absent ⇒ consumers MUST treat it as `supporting`. The (de)serializer never\n * defaults it, so round-trips stay exact.\n */\nexport const QueryResultRelationship = {\n /** The cell value IS (a cell of) the query result — a 1:1 extraction. */\n Exact: 'exact',\n /**\n * The cell value is authored (e.g. a narrative claim); the query result is\n * supporting evidence / justification, not the value itself. Re-running the\n * query is read-only verification and never replaces the cell value.\n */\n Supporting: 'supporting',\n} as const;\n\nexport type QueryResultRelationship =\n (typeof QueryResultRelationship)[keyof typeof QueryResultRelationship];\n\n/**\n * Generative anchor — a value derived from a semantic-model (Cube.js) query.\n *\n * Unlike positional anchors (page/cell/line), the \"location\" is the\n * transformation itself: the full Cube.js query spec that was run. Re-running\n * it is read-only verification; it never overwrites the cited value.\n */\nexport type SemanticQueryAnchor = {\n type: 'semantic_query';\n /** The full Cube.js query spec that produced the result (the codified transformation). */\n query: Record<string, unknown>;\n /** Cited measure/dimension id, e.g. `orders.total_revenue`. Omit ⇒ the whole result is the evidence. */\n field?: string;\n /** Dimension/key values identifying the cited row. Robust to re-ordering, unlike `rowIndex`. */\n rowKey?: Record<string, string>;\n /** Positional fallback row selector. */\n rowIndex?: number;\n /** Whether the cell value equals the result (`exact`) or is authored evidence (`supporting`). */\n relationship?: QueryResultRelationship;\n /** Provenance: semantic-model schema version at run time. */\n schemaVersion?: number;\n /** Provenance: sha256 of the deployed YAML at run time, for drift detection. */\n schemaHash?: string;\n /**\n * Provenance for lakehouse-backed models: each source table's Iceberg identity\n * and snapshot when the value was computed (`\"<namespace>.<table>\"` →\n * `\"<table_uuid>:<snapshot_id>\"`, the snapshot empty for a table never written).\n * Compared with the live tables by the freshness check.\n */\n sourceSnapshots?: Record<string, string>;\n /** Provenance: the result's \"data as of\" instant (ISO-8601 UTC) at capture. */\n dataAsOf?: string;\n};\n/**\n * One or more shapes on a presentation slide. `shapeIds` are stable Yjs\n * ElementIds (the SDK's `shape.shape_id`) and resolve the anchor on their\n * own; `slideId` / `slideIndex` (1-based) are optional refinements.\n */\nexport type ShapeAnchor = {\n type: 'shape';\n slideId?: string;\n slideIndex?: number;\n shapeIds: string[];\n};\n/**\n * A single cell. `chartId` (`chart=`) names the chart anchored at the cell\n * when the place is that chart, not the cell's value: a chart sits right of\n * and below its anchor cell, so a reader reveals it from that corner.\n */\nexport type SheetCellAnchor = {\n type: 'sheet_cell';\n sheetId: number;\n cell: string;\n chartId?: string;\n};\nexport type SheetRangeAnchor = {\n type: 'sheet_range';\n sheetId: number;\n range: string;\n /**\n * The spreadsheet engine's shift-log frontier (writer id → seq, `RncEngine.shiftLogFrontier`) the\n * moment `range` was taken, so a reader with the live engine can resolve the range to its current\n * coordinates after rows/columns were inserted or deleted since (`RncEngine.transformRange`).\n * Absent on an anchor taken without an engine, which resolves to `range` as stored.\n */\n frontier?: Record<string, number>;\n /**\n * The engine's line anchor for `range` (`SpreadsheetEngine.anchorRange`: standard padded base64 of\n * the range's row and column ids), taken with `range` on a stable-ids (v5) document. A v5 sheet's\n * cells follow their row and column ids, so a range resolved positionally (`frontier`) can name\n * other cells than the data after concurrent inserts or deletes; a reader with the live engine\n * resolves this instead (`resolveAnchor`), and falls back to `frontier` / `range` without one.\n * Absent on a positional (v3) document, whose engine takes no line anchors.\n */\n stableRange?: string;\n};\n/** A whole worksheet / sheet tab in a spreadsheet. */\nexport type SheetTabAnchor = {\n type: 'sheet_tab';\n sheetId: number;\n};\n/**\n * A named Excel table (ListObject) within a worksheet. Stable identity:\n * the table's name survives sorts, inserts, and row additions that would\n * break a raw `sheet_range`. Use this anchor in preference to\n * `sheet_range` whenever the user is binding to a structured table.\n *\n * `fallbackRange` is an optional A1-style range used by resolvers when\n * the table has been deleted or renamed — best-effort recovery.\n */\nexport type SheetTableAnchor = {\n type: 'sheet_table';\n sheetId: number;\n tableName: string;\n fallbackRange?: string;\n};\n/**\n * One table of an Orion lakehouse namespace, addressed on the namespace asset\n * (tables have no asset rows). `table` is the name within the namespace;\n * `tableUuid` is the Iceberg table UUID, the stable identity that detects a\n * drop-and-recreate or rename; `snapshotId` pins a read to one Iceberg\n * snapshot (an unsupported pinned read is rejected, never served from current\n * data).\n */\nexport type LakehouseTableAnchor = {\n type: 'lakehouse_table';\n table: string;\n tableUuid?: string;\n snapshotId?: string;\n};\n/**\n * A whole slide of a PPTX deck. `slideId` is the stable Yjs SlideId (the\n * SDK's `slide.slide_id`); `slideIndex` is the 1-based display position.\n * At least one must be present; producers should emit both when known.\n */\nexport type SlideAnchor = {\n type: 'slide';\n slideId?: string;\n slideIndex?: number;\n};\n/**\n * Generative anchor — a value derived from a SQL query.\n *\n * The transformation is the SQL text, carried inline or (preferred) as a\n * governed, re-runnable `query_snippet` asset. Re-running it is read-only\n * verification; it never overwrites the cited value.\n */\nexport type SqlQueryAnchor = {\n type: 'sql_query';\n /** The SQL that produced the result. Optional when `querySnippetAssetId` is set. */\n sql?: string;\n /** A re-runnable `query_snippet` asset that holds the SQL (preferred over inline `sql`). */\n querySnippetAssetId?: string;\n /** SQL dialect, e.g. `postgres`, `snowflake`. */\n dialect?: string;\n /** Cited result column name. Omit ⇒ the whole result is the evidence. */\n field?: string;\n /** Identifying column values for the cited row. Robust to re-ordering, unlike `rowIndex`. */\n rowKey?: Record<string, string>;\n /** Positional fallback row selector. */\n rowIndex?: number;\n /** Whether the cell value equals the result (`exact`) or is authored evidence (`supporting`). */\n relationship?: QueryResultRelationship;\n};\n/** Time string in \"H:MM:SS\" / \"MM:SS\" / \"M:SS\" format. No plain seconds. */\nexport type TimeAnchor = { type: 'time'; time: string };\nexport type TimeRangeAnchor = {\n type: 'time_range';\n startTime: string;\n endTime: string;\n};\n/**\n * A tool invocation in a session transcript. `toolCallId` is the\n * LangChain-native tool call id (the key used by session Y.Doc\n * liveToolCalls), NOT an Athena message tracking id. `messageId` is the\n * tracking id of the assistant message that issued the call, when the\n * producer knows it (Keryx activity carries both as `tool_call_id` and\n * `ai_message_tracking_id`); it lets a consumer still land on the owning\n * message when the call itself is not in view (e.g. an abandoned branch).\n */\nexport type ToolCallAnchor = { type: 'tool_call'; toolCallId: string; messageId?: string };\n\n// ---------------------------------------------------------------------------\n// Union\n// ---------------------------------------------------------------------------\n\nexport type Anchor =\n | CellAnchor\n | CellRangeAnchor\n | CommentAnchor\n | CommentThreadAnchor\n | FileLineRangeAnchor\n | LineAnchor\n | LineRangeAnchor\n | MessageAnchor\n | MessageRangeAnchor\n | MessageBlockAnchor\n | MessageSectionAnchor\n | MessageTextAnchor\n | PageAnchor\n | PageRangeAnchor\n | PathAnchor\n | PageRectAnchor\n | PageTextAnchor\n | PixelRangeAnchor\n | PmNodeAnchor\n | PmNodeRangeAnchor\n | PmMarkAnchor\n | RectAnchor\n | SectionAnchor\n | SemanticQueryAnchor\n | ShapeAnchor\n | SheetCellAnchor\n | SheetRangeAnchor\n | SheetTabAnchor\n | SheetTableAnchor\n | LakehouseTableAnchor\n | SlideAnchor\n | SqlQueryAnchor\n | TimeAnchor\n | TimeRangeAnchor\n | ToolCallAnchor;\n\n// ---------------------------------------------------------------------------\n// AnchorType — string literal union of all `type` discriminators\n// ---------------------------------------------------------------------------\n\nexport type AnchorType = Anchor['type'];\n\nexport const AnchorType = {\n Cell: 'cell',\n CellRange: 'cell_range',\n Comment: 'comment',\n CommentThread: 'comment_thread',\n FileLineRange: 'file_line_range',\n Line: 'line',\n LineRange: 'line_range',\n Message: 'msg',\n MessageRange: 'msg_range',\n MessageBlock: 'msg_block',\n MessageSection: 'msg_section',\n MessageText: 'msg_text',\n Page: 'page',\n PageRange: 'page_range',\n Path: 'path',\n PageRect: 'page_rect',\n PageText: 'page_text',\n PixelRange: 'pixel_range',\n PmMark: 'pm_mark',\n PmNode: 'pm_node',\n PmNodeRange: 'pm_node_range',\n Rect: 'rect',\n Section: 'section',\n SemanticQuery: 'semantic_query',\n Shape: 'shape',\n SheetCell: 'sheet_cell',\n SheetRange: 'sheet_range',\n SheetTab: 'sheet_tab',\n SheetTable: 'sheet_table',\n LakehouseTable: 'lakehouse_table',\n Slide: 'slide',\n SqlQuery: 'sql_query',\n Time: 'time',\n TimeRange: 'time_range',\n ToolCall: 'tool_call',\n} as const satisfies Record<string, AnchorType>;\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/**\n * Pre-rename session anchor spellings that are still accepted on input so\n * links shared before the `msg*` rename keep resolving. Output always uses\n * the current names (see `serialize.ts`).\n */\nexport const LEGACY_ANCHOR_TYPES: Readonly<Record<string, AnchorType>> = {\n message: 'msg',\n message_range: 'msg_range',\n};\n\nexport function isAnchorType(value: unknown): value is AnchorType {\n return typeof value === 'string' && Object.values(AnchorType).includes(value as AnchorType);\n}\n\n/**\n * Quick check: validates only the `type` discriminator string.\n * For full structural validation, use `parseAnchor` from `./schemas`.\n */\nexport function isAnchor(value: unknown): value is Anchor {\n if (typeof value !== 'object' || value === null) return false;\n return isAnchorType((value as Record<string, unknown>).type);\n}\n\n// ---------------------------------------------------------------------------\n// Runtime-only types (not stored, produced by accessors)\n// ---------------------------------------------------------------------------\n\n/** Runtime form of TimeAnchor with pre-computed seconds. */\nexport type TimeAnchorSeconds = { type: 'time_seconds'; timeSeconds: number };\n/** Runtime form of TimeRangeAnchor with pre-computed seconds. */\nexport type TimeRangeAnchorSeconds = {\n type: 'time_range_seconds';\n startTimeSeconds: number;\n endTimeSeconds: number;\n};\n"],"names":[],"mappings":"AA+bO,MAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,eAAe;AAAA,EACf,eAAe;AAAA,EACf,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,WAAW;AAAA,EACX,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,MAAM;AAAA,EACN,SAAS;AAAA,EACT,eAAe;AAAA,EACf,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AACZ;AAWO,MAAM,sBAA4D;AAAA,EACvE,SAAS;AAAA,EACT,eAAe;AACjB;AAEO,SAAS,aAAa,OAAqC;AAChE,SAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,EAAE,SAAS,KAAmB;AAC5F;AAMO,SAAS,SAAS,OAAiC;AACxD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,SAAO,aAAc,MAAkC,IAAI;AAC7D;"}
|
|
@@ -199,6 +199,7 @@ export declare const assetReferenceSchema: z.ZodObject<{
|
|
|
199
199
|
sheetId: z.ZodNumber;
|
|
200
200
|
range: z.ZodString;
|
|
201
201
|
frontier: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
202
|
+
stableRange: z.ZodOptional<z.ZodString>;
|
|
202
203
|
}, z.core.$strip>, z.ZodObject<{
|
|
203
204
|
type: z.ZodLiteral<"sheet_tab">;
|
|
204
205
|
sheetId: z.ZodNumber;
|
|
@@ -398,6 +399,7 @@ export declare const threadReferenceDataSchema: z.ZodObject<{
|
|
|
398
399
|
sheetId: z.ZodNumber;
|
|
399
400
|
range: z.ZodString;
|
|
400
401
|
frontier: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
402
|
+
stableRange: z.ZodOptional<z.ZodString>;
|
|
401
403
|
}, z.core.$strip>, z.ZodObject<{
|
|
402
404
|
type: z.ZodLiteral<"sheet_tab">;
|
|
403
405
|
sheetId: z.ZodNumber;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const react = require("@assistant-ui/react");
|
|
4
|
-
const namedAgents = require("../agent-runtime/src/named-agents.cjs");
|
|
5
4
|
const require$$0 = require("react");
|
|
6
5
|
const AthenaAuthContext = require("../auth/AthenaAuthContext.cjs");
|
|
7
6
|
const statewireClientTools = require("../chat/statewire-client-tools.cjs");
|
|
8
|
-
const
|
|
7
|
+
const stagedMessageMetadata = require("../composer/staged-message-metadata.cjs");
|
|
9
8
|
const athenaDiagnostics = require("../diagnostics/athena-diagnostics.cjs");
|
|
10
9
|
const statewireAuthHeaders = require("./statewire-auth-headers.cjs");
|
|
11
10
|
const statewireSessionKey = require("./statewire-session-key.cjs");
|
|
@@ -16,7 +15,6 @@ const useDeepAgentRuntime = require("../agent-runtime/src/use-deep-agent-runtime
|
|
|
16
15
|
const subagentTranscripts = require("../agent-runtime/src/subagent-transcripts.cjs");
|
|
17
16
|
const errors = require("../agent-runtime/src/errors.cjs");
|
|
18
17
|
const protocol = require("../agent-runtime/src/protocol.cjs");
|
|
19
|
-
const composerMarkdown = require("../agent-runtime/src/composer-markdown.cjs");
|
|
20
18
|
const chatOutboxStorage = require("../agent-runtime/src/chat-outbox-storage.cjs");
|
|
21
19
|
const ATHENA_SDK_MESSAGE_WINDOW = {
|
|
22
20
|
size: runconfigContract.DEEP_AGENT_DEFAULT_MESSAGE_WINDOW
|
|
@@ -183,11 +181,11 @@ function useAthenaStatewireRuntime(config) {
|
|
|
183
181
|
// names, so agora reads the message's own list, as Olympus's messages do,
|
|
184
182
|
// and one an app attached objects to (`useAttachToChat`) carries them as
|
|
185
183
|
// structured references, which agora resolves with the sender's own
|
|
186
|
-
// permission before the agent is told.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
184
|
+
// permission before the agent is told. Only the monorepo's patch of
|
|
185
|
+
// `@assistant-ui/react-statewire` reads this option: an app on the stock
|
|
186
|
+
// package from npm never runs it, which is why `AthenaChat` sends a
|
|
187
|
+
// message with attachments with its metadata on the message itself.
|
|
188
|
+
getMessageMetadata: () => stagedMessageMetadata.takeStagedMessageMetadata(threadId),
|
|
191
189
|
useClient: useSdkClient,
|
|
192
190
|
onStateChange: (state) => {
|
|
193
191
|
if (!protocol.isDeepAgentHostState(state)) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAthenaStatewireRuntime.cjs","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n ChatSessionStorage,\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n adoptUnscopedLocalStorageSessions,\n localStorageSessionKey,\n persistedSessionHoldsSends,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { stagedNamedAgentsMessageMetadata } from '@athenaintel/agent-runtime/named-agents';\nimport { useContext, useMemo, useRef, useState } from 'react';\nimport type { AthenaChatSessionKeeping } from '../offline/chat-outbox';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { withStagedAttachedReferences } from '../composer/attached-references';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionLanes, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier\n * steps, as the transcript drawer of `AthenaChat`'s subagent lanes does\n * (\"Load earlier steps\"). When true, its attaches declare the deep-agent\n * lane-cut contract (protocol 2): the host sends a finished subagent's card\n * cut to its newest steps, as it sends a running one, and the drawer reads\n * the rest. Default `false`, so a chat that does not page lanes declares the\n * default contract and finished lanes arrive whole; a host whose\n * `AthenaChat` renders every `task` call in the subagent lanes turns it on\n * through `AthenaProvider`'s `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * @deprecated Ignored. Older history pages by command (`history/page`) on\n * every host that serves it, into the conversation's own store, which every\n * reader of the thread joins; there is nothing to pass.\n */\n historyPages?: unknown;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Plan mode (`AthenaProviderProps.planMode`); `undefined` sends none. */\n planMode?: boolean;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update. */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Where the thread's session lives when the provider keeps a chat outbox (the outbox is the\n * session's outbox): sealed in IndexedDB, or in page memory where there is no write key;\n * `pending` until the provider knows which. Omitted: localStorage, as without an outbox.\n */\n chatSession?: AthenaChatSessionKeeping;\n /**\n * Whether the app is in front: while it says no, sends queued before this page mounted are held\n * for the chat outbox's countdown instead of going from a hidden tab.\n */\n foreground?: { get(): boolean };\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n planMode,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n chatSession,\n foreground,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionLanes`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n const lanes = useMemo(\n () => (principal === null ? null : statewireSessionLanes({ syncUrl, principal })),\n [syncUrl, principal],\n );\n\n // A thread whose localStorage record (an earlier build's) still holds sends stays on it until\n // they drain: moving a live record to another store would give an older tab and this one the\n // same client lane. Read once per thread and principal, when the outbox's store is known.\n const localSessionKey =\n lanes === null\n ? null\n : localStorageSessionKey({ namespace: lanes.namespace, principal: lanes.principal, threadId });\n const transitionKey =\n chatSession && chatSession.kind !== 'pending' ? localSessionKey : null;\n const [localTransition, setLocalTransition] = useState<{ key: string; holds: boolean } | null>(\n null,\n );\n let staysOnLocalStorage = localTransition?.key === transitionKey ? localTransition.holds : false;\n if (transitionKey !== null && lanes !== null && localTransition?.key !== transitionKey) {\n // A lane statewire 0.24 kept for this principal moves under its scoped key first.\n adoptUnscopedLocalStorageSessions({ ...lanes, threadId });\n staysOnLocalStorage = persistedSessionHoldsSends(transitionKey);\n setLocalTransition({ key: transitionKey, holds: staysOnLocalStorage });\n }\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n planMode,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n //\n // With a chat outbox the session is the outbox's store (`chatSession`), scoped by the\n // outbox's owner, and pending until the provider has read whether it may keep it sealed.\n session:\n lanes === null || chatSession?.kind === 'pending'\n ? { kind: 'pending' }\n : !chatSession || staysOnLocalStorage\n ? { kind: 'local-storage', ...lanes }\n : {\n kind: 'storage',\n session: (id) =>\n chatSession.kind === 'sealed'\n ? ChatSessionStorage({\n kind: 'sealed',\n threadId: id,\n namespace: chatSession.namespace,\n principal: chatSession.principal,\n codec: chatSession.codec,\n })\n : chatSession.sealedThreads?.threads.has(id)\n ? ChatSessionStorage({\n kind: 'sealed',\n threadId: id,\n namespace: chatSession.sealedThreads.namespace,\n principal: chatSession.principal,\n codec: chatSession.sealedThreads.codec,\n })\n : ChatSessionStorage({\n kind: 'memory',\n threadId: id,\n scope: chatSession.scope,\n principal: chatSession.principal,\n }),\n },\n ...(foreground && { foreground }),\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // lanes (`SubagentTaskToolUI`) show.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`). A send that names\n // agents (`AthenaChat`'s Agents category) also carries the agents it\n // names, so agora reads the message's own list, as Olympus's messages do,\n // and one an app attached objects to (`useAttachToChat`) carries them as\n // structured references, which agora resolves with the sender's own\n // permission before the agent is told.\n getMessageMetadata: withStagedComposerMarkdown({\n threadId,\n getMessageMetadata: () =>\n withStagedAttachedReferences(threadId, stagedNamedAgentsMessageMetadata(threadId)),\n }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself,\n // and `StatewirePlanModeLaneSync` a changed plan mode. The agents a send\n // names ride its message (`getMessageMetadata`), not the run config.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":["DEEP_AGENT_DEFAULT_MESSAGE_WINDOW","useMemo","collectStatewireClientTools","resolveAgentProp","statewireSessionPrincipal","useContext","AthenaAuthContext","statewireSessionLanes","localStorageSessionKey","useState","adoptUnscopedLocalStorageSessions","persistedSessionHoldsSends","useRef","athenaDiagnostics","buildStatewireRunConfig","statewireClientToolWireEntries","Tools","useAui","useDeepAgentRuntime","resolveStatewireAuthHeaders","ChatSessionStorage","createSubagentTranscriptConversionCache","withStagedComposerMarkdown","withStagedAttachedReferences","stagedNamedAgentsMessageMetadata","isDeepAgentHostState","isStatewireChannelTeardown","logUnhandledStatewireError"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuDO,MAAM,4BAA+D;AAAA,EAC1E,MAAMA,kBAAAA;AACR;AAmHA,MAAM,gBAAyB,CAAA;AAC/B,MAAM,iBAA2B,CAAA;AAI1B,SAAS,wBACd,iBACwB;AACxB,SAAOC,WAAAA;AAAAA,IACL,MAAMC,qBAAAA,4BAA4B,mBAAmB,aAAa;AAAA,IAClE,CAAC,eAAe;AAAA,EAAA;AAEpB;AAaO,SAAS,0BACd,QACiB;AACjB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,sBAAsB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AAMJC,qBAAAA,iBAAiB,EAAE,OAAO;AAE1B,QAAM,cAAc,wBAAwB,eAAe;AAK3D,QAAM,YAAYC,oBAAAA,0BAA0BC,WAAAA,WAAWC,kBAAAA,iBAAiB,CAAC;AACzE,QAAM,QAAQL,WAAAA;AAAAA,IACZ,MAAO,cAAc,OAAO,OAAOM,oBAAAA,sBAAsB,EAAE,SAAS,WAAW;AAAA,IAC/E,CAAC,SAAS,SAAS;AAAA,EAAA;AAMrB,QAAM,kBACJ,UAAU,OACN,OACAC,6BAAAA,uBAAuB,EAAE,WAAW,MAAM,WAAW,WAAW,MAAM,WAAW,UAAU;AACjG,QAAM,gBACJ,eAAe,YAAY,SAAS,YAAY,kBAAkB;AACpE,QAAM,CAAC,iBAAiB,kBAAkB,IAAIC,WAAAA;AAAAA,IAC5C;AAAA,EAAA;AAEF,MAAI,uBAAsB,mDAAiB,SAAQ,gBAAgB,gBAAgB,QAAQ;AAC3F,MAAI,kBAAkB,QAAQ,UAAU,SAAQ,mDAAiB,SAAQ,eAAe;AAEtFC,iCAAAA,kCAAkC,EAAE,GAAG,OAAO,UAAU;AACxD,0BAAsBC,6BAAAA,2BAA2B,aAAa;AAC9D,uBAAmB,EAAE,KAAK,eAAe,OAAO,qBAAqB;AAAA,EACvE;AAGA,QAAM,gBAAgBC,WAAAA,OAAwD,IAAI;AAClF,QAAM,kBAAkBA,WAAAA,OAAsB,IAAI;AAClD,MAAI,gBAAgB,YAAY,UAAU;AACxC,oBAAgB,UAAU;AAC1B,kBAAc,UAAUC,kBAAAA,kBAAkB;AAAA,MACxC,oBAAoB,QAAQ;AAAA,MAC5B;AAAA,MACA,EAAE,WAAW,UAAU,aAAa,UAAA;AAAA,IAAU;AAAA,EAElD;AAQA,QAAM,iBAAiBC,mBAAAA,wBAAwB;AAAA,IAC7C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAaC,qBAAAA,+BAA+B,WAAW;AAAA,EAAA,CACxD;AACD,QAAM,eAAe,KAAK,UAAU,cAAc;AAElD,QAAM,WAAWd,mBAAQ,MAAMe,YAAM,EAAE,SAAS,gBAAA,CAAiB,GAAG,CAAC,eAAe,CAAC;AAIrF,QAAM,eAAe,CAAC,WAAmCC,MAAAA,OAAO,EAAE,QAAQ,OAAO,UAAU;AAE3F,SAAOC,wCAAoB;AAAA,IACzB,SAAS;AAAA,IACT;AAAA,IACA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,IAKT,SAAS,CAAC,QAAQC,iDAA4B,EAAE,QAAQ,OAAO,SAAA,GAAY,GAAG;AAAA,IAC9E;AAAA;AAAA;AAAA,IAGA,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBhB,SACE,UAAU,SAAQ,2CAAa,UAAS,YACpC,EAAE,MAAM,UAAA,IACR,CAAC,eAAe,sBACd,EAAE,MAAM,iBAAiB,GAAG,UAC5B;AAAA,MACE,MAAM;AAAA,MACN,SAAS,CAAC,OAAA;;AACR,2BAAY,SAAS,WACjBC,kBAAAA,mBAAmB;AAAA,UACjB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW,YAAY;AAAA,UACvB,WAAW,YAAY;AAAA,UACvB,OAAO,YAAY;AAAA,QAAA,CACpB,MACD,iBAAY,kBAAZ,mBAA2B,QAAQ,IAAI,OACrCA,qCAAmB;AAAA,UACjB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW,YAAY,cAAc;AAAA,UACrC,WAAW,YAAY;AAAA,UACvB,OAAO,YAAY,cAAc;AAAA,QAAA,CAClC,IACDA,kBAAAA,mBAAmB;AAAA,UACjB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO,YAAY;AAAA,UACnB,WAAW,YAAY;AAAA,QAAA,CACxB;AAAA;AAAA,IAAA;AAAA,IAEnB,GAAI,cAAc,EAAE,WAAA;AAAA,IACpB;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,IAIA,uBAAuBC,oBAAAA;AAAAA;AAAAA,IAEvB,aAAa;AAAA,IACb,cAAc,EAAE,MAAM,MAAM,QAAQ,MAAM,UAAU,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASpD,oBAAoBC,iBAAAA,2BAA2B;AAAA,MAC7C;AAAA,MACA,oBAAoB,MAClBC,mBAAAA,6BAA6B,UAAUC,YAAAA,iCAAiC,QAAQ,CAAC;AAAA,IAAA,CACpF;AAAA,IACD,WAAW;AAAA,IACX,eAAe,CAAC,UAAU;AAMxB,UAAI,CAACC,SAAAA,qBAAqB,KAAK,EAAG;AAElC,YAAM,UAAU,cAAc;AAC9B,UAAI,SAAS;AACX,sBAAc,UAAU;AACxB,gBAAQ,sBAAsB,EAAE,MAAM,EAAE,WAAW,SAAA,GAAY;AAAA,MACjE;AACA,qDAAgB;AAAA,IAClB;AAAA,IACA,oBAAoB,CAAC,eAAe;AAClCZ,wBAAAA,kBAAkB,MAAM,yBAAwB,yCAAY,WAAU,IAAI;AAC1E,WAAI,yCAAY,YAAW,WAAW;AACpCA,0BAAAA,kBAAkB,KAAK,wBAAwB;AAAA,UAC7C,OAAO;AAAA,UACP,MAAM;AAAA,YACJ,QAAQ,WAAW;AAAA,YACnB,QAAQ,WAAW;AAAA,YACnB,SAAS,WAAW;AAAA,UAAA;AAAA,QACtB,CACD;AAAA,MACH;AACA,+DAAqB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,mBAAmB,EAAE,gBAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASzB,WAAW;AAAA,MACT,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,IAAA;AAAA,IAEP,SAAS,CAAC,UAAU;AAClB,UAAI,CAACa,OAAAA,2BAA2B,KAAK,GAAG;AACtCb,0BAAAA,kBAAkB;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,YACT,MAAM;AAAA,UAAA;AAAA,UAER,EAAE,WAAW,SAAA;AAAA,QAAS;AAAA,MAE1B;AACA,UAAI,SAAS;AACX,gBAAQ,KAAK;AACb;AAAA,MACF;AACAc,0BAAAA,2BAA2B,aAAa,KAAK;AAAA,IAC/C;AAAA,EAAA,CACD;AACH;;;;;"}
|
|
1
|
+
{"version":3,"file":"useAthenaStatewireRuntime.cjs","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n ChatSessionStorage,\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n adoptUnscopedLocalStorageSessions,\n localStorageSessionKey,\n persistedSessionHoldsSends,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef, useState } from 'react';\nimport type { AthenaChatSessionKeeping } from '../offline/chat-outbox';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { takeStagedMessageMetadata } from '../composer/staged-message-metadata';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionLanes, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier\n * steps, as the transcript drawer of `AthenaChat`'s subagent lanes does\n * (\"Load earlier steps\"). When true, its attaches declare the deep-agent\n * lane-cut contract (protocol 2): the host sends a finished subagent's card\n * cut to its newest steps, as it sends a running one, and the drawer reads\n * the rest. Default `false`, so a chat that does not page lanes declares the\n * default contract and finished lanes arrive whole; a host whose\n * `AthenaChat` renders every `task` call in the subagent lanes turns it on\n * through `AthenaProvider`'s `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * @deprecated Ignored. Older history pages by command (`history/page`) on\n * every host that serves it, into the conversation's own store, which every\n * reader of the thread joins; there is nothing to pass.\n */\n historyPages?: unknown;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Plan mode (`AthenaProviderProps.planMode`); `undefined` sends none. */\n planMode?: boolean;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update. */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Where the thread's session lives when the provider keeps a chat outbox (the outbox is the\n * session's outbox): sealed in IndexedDB, or in page memory where there is no write key;\n * `pending` until the provider knows which. Omitted: localStorage, as without an outbox.\n */\n chatSession?: AthenaChatSessionKeeping;\n /**\n * Whether the app is in front: while it says no, sends queued before this page mounted are held\n * for the chat outbox's countdown instead of going from a hidden tab.\n */\n foreground?: { get(): boolean };\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n planMode,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n chatSession,\n foreground,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionLanes`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n const lanes = useMemo(\n () => (principal === null ? null : statewireSessionLanes({ syncUrl, principal })),\n [syncUrl, principal],\n );\n\n // A thread whose localStorage record (an earlier build's) still holds sends stays on it until\n // they drain: moving a live record to another store would give an older tab and this one the\n // same client lane. Read once per thread and principal, when the outbox's store is known.\n const localSessionKey =\n lanes === null\n ? null\n : localStorageSessionKey({ namespace: lanes.namespace, principal: lanes.principal, threadId });\n const transitionKey =\n chatSession && chatSession.kind !== 'pending' ? localSessionKey : null;\n const [localTransition, setLocalTransition] = useState<{ key: string; holds: boolean } | null>(\n null,\n );\n let staysOnLocalStorage = localTransition?.key === transitionKey ? localTransition.holds : false;\n if (transitionKey !== null && lanes !== null && localTransition?.key !== transitionKey) {\n // A lane statewire 0.24 kept for this principal moves under its scoped key first.\n adoptUnscopedLocalStorageSessions({ ...lanes, threadId });\n staysOnLocalStorage = persistedSessionHoldsSends(transitionKey);\n setLocalTransition({ key: transitionKey, holds: staysOnLocalStorage });\n }\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n planMode,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n //\n // With a chat outbox the session is the outbox's store (`chatSession`), scoped by the\n // outbox's owner, and pending until the provider has read whether it may keep it sealed.\n session:\n lanes === null || chatSession?.kind === 'pending'\n ? { kind: 'pending' }\n : !chatSession || staysOnLocalStorage\n ? { kind: 'local-storage', ...lanes }\n : {\n kind: 'storage',\n session: (id) =>\n chatSession.kind === 'sealed'\n ? ChatSessionStorage({\n kind: 'sealed',\n threadId: id,\n namespace: chatSession.namespace,\n principal: chatSession.principal,\n codec: chatSession.codec,\n })\n : chatSession.sealedThreads?.threads.has(id)\n ? ChatSessionStorage({\n kind: 'sealed',\n threadId: id,\n namespace: chatSession.sealedThreads.namespace,\n principal: chatSession.principal,\n codec: chatSession.sealedThreads.codec,\n })\n : ChatSessionStorage({\n kind: 'memory',\n threadId: id,\n scope: chatSession.scope,\n principal: chatSession.principal,\n }),\n },\n ...(foreground && { foreground }),\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // lanes (`SubagentTaskToolUI`) show.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`). A send that names\n // agents (`AthenaChat`'s Agents category) also carries the agents it\n // names, so agora reads the message's own list, as Olympus's messages do,\n // and one an app attached objects to (`useAttachToChat`) carries them as\n // structured references, which agora resolves with the sender's own\n // permission before the agent is told. Only the monorepo's patch of\n // `@assistant-ui/react-statewire` reads this option: an app on the stock\n // package from npm never runs it, which is why `AthenaChat` sends a\n // message with attachments with its metadata on the message itself.\n getMessageMetadata: () => takeStagedMessageMetadata(threadId),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself,\n // and `StatewirePlanModeLaneSync` a changed plan mode. The agents a send\n // names ride its message (`getMessageMetadata`), not the run config.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":["DEEP_AGENT_DEFAULT_MESSAGE_WINDOW","useMemo","collectStatewireClientTools","resolveAgentProp","statewireSessionPrincipal","useContext","AthenaAuthContext","statewireSessionLanes","localStorageSessionKey","useState","adoptUnscopedLocalStorageSessions","persistedSessionHoldsSends","useRef","athenaDiagnostics","buildStatewireRunConfig","statewireClientToolWireEntries","Tools","useAui","useDeepAgentRuntime","resolveStatewireAuthHeaders","ChatSessionStorage","createSubagentTranscriptConversionCache","takeStagedMessageMetadata","isDeepAgentHostState","isStatewireChannelTeardown","logUnhandledStatewireError"],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Tools, useAui } from "@assistant-ui/react";
|
|
2
|
-
import { stagedNamedAgentsMessageMetadata } from "../agent-runtime/src/named-agents.js";
|
|
3
2
|
import { useContext, useMemo, useState, useRef } from "react";
|
|
4
3
|
import { AthenaAuthContext } from "../auth/AthenaAuthContext.js";
|
|
5
4
|
import { statewireClientToolWireEntries, collectStatewireClientTools } from "../chat/statewire-client-tools.js";
|
|
6
|
-
import {
|
|
5
|
+
import { takeStagedMessageMetadata } from "../composer/staged-message-metadata.js";
|
|
7
6
|
import { athenaDiagnostics } from "../diagnostics/athena-diagnostics.js";
|
|
8
7
|
import { resolveStatewireAuthHeaders } from "./statewire-auth-headers.js";
|
|
9
8
|
import { statewireSessionPrincipal, statewireSessionLanes } from "./statewire-session-key.js";
|
|
@@ -15,7 +14,6 @@ import { useDeepAgentRuntime, logUnhandledStatewireError } from "../agent-runtim
|
|
|
15
14
|
import { createSubagentTranscriptConversionCache } from "../agent-runtime/src/subagent-transcripts.js";
|
|
16
15
|
import { isStatewireChannelTeardown } from "../agent-runtime/src/errors.js";
|
|
17
16
|
import { isDeepAgentHostState } from "../agent-runtime/src/protocol.js";
|
|
18
|
-
import { withStagedComposerMarkdown } from "../agent-runtime/src/composer-markdown.js";
|
|
19
17
|
import { ChatSessionStorage } from "../agent-runtime/src/chat-outbox-storage.js";
|
|
20
18
|
const ATHENA_SDK_MESSAGE_WINDOW = {
|
|
21
19
|
size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW
|
|
@@ -182,11 +180,11 @@ function useAthenaStatewireRuntime(config) {
|
|
|
182
180
|
// names, so agora reads the message's own list, as Olympus's messages do,
|
|
183
181
|
// and one an app attached objects to (`useAttachToChat`) carries them as
|
|
184
182
|
// structured references, which agora resolves with the sender's own
|
|
185
|
-
// permission before the agent is told.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
183
|
+
// permission before the agent is told. Only the monorepo's patch of
|
|
184
|
+
// `@assistant-ui/react-statewire` reads this option: an app on the stock
|
|
185
|
+
// package from npm never runs it, which is why `AthenaChat` sends a
|
|
186
|
+
// message with attachments with its metadata on the message itself.
|
|
187
|
+
getMessageMetadata: () => takeStagedMessageMetadata(threadId),
|
|
190
188
|
useClient: useSdkClient,
|
|
191
189
|
onStateChange: (state) => {
|
|
192
190
|
if (!isDeepAgentHostState(state)) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAthenaStatewireRuntime.js","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n ChatSessionStorage,\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n adoptUnscopedLocalStorageSessions,\n localStorageSessionKey,\n persistedSessionHoldsSends,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { stagedNamedAgentsMessageMetadata } from '@athenaintel/agent-runtime/named-agents';\nimport { useContext, useMemo, useRef, useState } from 'react';\nimport type { AthenaChatSessionKeeping } from '../offline/chat-outbox';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { withStagedAttachedReferences } from '../composer/attached-references';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionLanes, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier\n * steps, as the transcript drawer of `AthenaChat`'s subagent lanes does\n * (\"Load earlier steps\"). When true, its attaches declare the deep-agent\n * lane-cut contract (protocol 2): the host sends a finished subagent's card\n * cut to its newest steps, as it sends a running one, and the drawer reads\n * the rest. Default `false`, so a chat that does not page lanes declares the\n * default contract and finished lanes arrive whole; a host whose\n * `AthenaChat` renders every `task` call in the subagent lanes turns it on\n * through `AthenaProvider`'s `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * @deprecated Ignored. Older history pages by command (`history/page`) on\n * every host that serves it, into the conversation's own store, which every\n * reader of the thread joins; there is nothing to pass.\n */\n historyPages?: unknown;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Plan mode (`AthenaProviderProps.planMode`); `undefined` sends none. */\n planMode?: boolean;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update. */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Where the thread's session lives when the provider keeps a chat outbox (the outbox is the\n * session's outbox): sealed in IndexedDB, or in page memory where there is no write key;\n * `pending` until the provider knows which. Omitted: localStorage, as without an outbox.\n */\n chatSession?: AthenaChatSessionKeeping;\n /**\n * Whether the app is in front: while it says no, sends queued before this page mounted are held\n * for the chat outbox's countdown instead of going from a hidden tab.\n */\n foreground?: { get(): boolean };\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n planMode,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n chatSession,\n foreground,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionLanes`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n const lanes = useMemo(\n () => (principal === null ? null : statewireSessionLanes({ syncUrl, principal })),\n [syncUrl, principal],\n );\n\n // A thread whose localStorage record (an earlier build's) still holds sends stays on it until\n // they drain: moving a live record to another store would give an older tab and this one the\n // same client lane. Read once per thread and principal, when the outbox's store is known.\n const localSessionKey =\n lanes === null\n ? null\n : localStorageSessionKey({ namespace: lanes.namespace, principal: lanes.principal, threadId });\n const transitionKey =\n chatSession && chatSession.kind !== 'pending' ? localSessionKey : null;\n const [localTransition, setLocalTransition] = useState<{ key: string; holds: boolean } | null>(\n null,\n );\n let staysOnLocalStorage = localTransition?.key === transitionKey ? localTransition.holds : false;\n if (transitionKey !== null && lanes !== null && localTransition?.key !== transitionKey) {\n // A lane statewire 0.24 kept for this principal moves under its scoped key first.\n adoptUnscopedLocalStorageSessions({ ...lanes, threadId });\n staysOnLocalStorage = persistedSessionHoldsSends(transitionKey);\n setLocalTransition({ key: transitionKey, holds: staysOnLocalStorage });\n }\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n planMode,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n //\n // With a chat outbox the session is the outbox's store (`chatSession`), scoped by the\n // outbox's owner, and pending until the provider has read whether it may keep it sealed.\n session:\n lanes === null || chatSession?.kind === 'pending'\n ? { kind: 'pending' }\n : !chatSession || staysOnLocalStorage\n ? { kind: 'local-storage', ...lanes }\n : {\n kind: 'storage',\n session: (id) =>\n chatSession.kind === 'sealed'\n ? ChatSessionStorage({\n kind: 'sealed',\n threadId: id,\n namespace: chatSession.namespace,\n principal: chatSession.principal,\n codec: chatSession.codec,\n })\n : chatSession.sealedThreads?.threads.has(id)\n ? ChatSessionStorage({\n kind: 'sealed',\n threadId: id,\n namespace: chatSession.sealedThreads.namespace,\n principal: chatSession.principal,\n codec: chatSession.sealedThreads.codec,\n })\n : ChatSessionStorage({\n kind: 'memory',\n threadId: id,\n scope: chatSession.scope,\n principal: chatSession.principal,\n }),\n },\n ...(foreground && { foreground }),\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // lanes (`SubagentTaskToolUI`) show.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`). A send that names\n // agents (`AthenaChat`'s Agents category) also carries the agents it\n // names, so agora reads the message's own list, as Olympus's messages do,\n // and one an app attached objects to (`useAttachToChat`) carries them as\n // structured references, which agora resolves with the sender's own\n // permission before the agent is told.\n getMessageMetadata: withStagedComposerMarkdown({\n threadId,\n getMessageMetadata: () =>\n withStagedAttachedReferences(threadId, stagedNamedAgentsMessageMetadata(threadId)),\n }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself,\n // and `StatewirePlanModeLaneSync` a changed plan mode. The agents a send\n // names ride its message (`getMessageMetadata`), not the run config.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAthenaStatewireRuntime.js","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n ChatSessionStorage,\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n adoptUnscopedLocalStorageSessions,\n localStorageSessionKey,\n persistedSessionHoldsSends,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef, useState } from 'react';\nimport type { AthenaChatSessionKeeping } from '../offline/chat-outbox';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { takeStagedMessageMetadata } from '../composer/staged-message-metadata';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionLanes, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier\n * steps, as the transcript drawer of `AthenaChat`'s subagent lanes does\n * (\"Load earlier steps\"). When true, its attaches declare the deep-agent\n * lane-cut contract (protocol 2): the host sends a finished subagent's card\n * cut to its newest steps, as it sends a running one, and the drawer reads\n * the rest. Default `false`, so a chat that does not page lanes declares the\n * default contract and finished lanes arrive whole; a host whose\n * `AthenaChat` renders every `task` call in the subagent lanes turns it on\n * through `AthenaProvider`'s `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * @deprecated Ignored. Older history pages by command (`history/page`) on\n * every host that serves it, into the conversation's own store, which every\n * reader of the thread joins; there is nothing to pass.\n */\n historyPages?: unknown;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Plan mode (`AthenaProviderProps.planMode`); `undefined` sends none. */\n planMode?: boolean;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update. */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Where the thread's session lives when the provider keeps a chat outbox (the outbox is the\n * session's outbox): sealed in IndexedDB, or in page memory where there is no write key;\n * `pending` until the provider knows which. Omitted: localStorage, as without an outbox.\n */\n chatSession?: AthenaChatSessionKeeping;\n /**\n * Whether the app is in front: while it says no, sends queued before this page mounted are held\n * for the chat outbox's countdown instead of going from a hidden tab.\n */\n foreground?: { get(): boolean };\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n planMode,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n chatSession,\n foreground,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionLanes`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n const lanes = useMemo(\n () => (principal === null ? null : statewireSessionLanes({ syncUrl, principal })),\n [syncUrl, principal],\n );\n\n // A thread whose localStorage record (an earlier build's) still holds sends stays on it until\n // they drain: moving a live record to another store would give an older tab and this one the\n // same client lane. Read once per thread and principal, when the outbox's store is known.\n const localSessionKey =\n lanes === null\n ? null\n : localStorageSessionKey({ namespace: lanes.namespace, principal: lanes.principal, threadId });\n const transitionKey =\n chatSession && chatSession.kind !== 'pending' ? localSessionKey : null;\n const [localTransition, setLocalTransition] = useState<{ key: string; holds: boolean } | null>(\n null,\n );\n let staysOnLocalStorage = localTransition?.key === transitionKey ? localTransition.holds : false;\n if (transitionKey !== null && lanes !== null && localTransition?.key !== transitionKey) {\n // A lane statewire 0.24 kept for this principal moves under its scoped key first.\n adoptUnscopedLocalStorageSessions({ ...lanes, threadId });\n staysOnLocalStorage = persistedSessionHoldsSends(transitionKey);\n setLocalTransition({ key: transitionKey, holds: staysOnLocalStorage });\n }\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n planMode,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n //\n // With a chat outbox the session is the outbox's store (`chatSession`), scoped by the\n // outbox's owner, and pending until the provider has read whether it may keep it sealed.\n session:\n lanes === null || chatSession?.kind === 'pending'\n ? { kind: 'pending' }\n : !chatSession || staysOnLocalStorage\n ? { kind: 'local-storage', ...lanes }\n : {\n kind: 'storage',\n session: (id) =>\n chatSession.kind === 'sealed'\n ? ChatSessionStorage({\n kind: 'sealed',\n threadId: id,\n namespace: chatSession.namespace,\n principal: chatSession.principal,\n codec: chatSession.codec,\n })\n : chatSession.sealedThreads?.threads.has(id)\n ? ChatSessionStorage({\n kind: 'sealed',\n threadId: id,\n namespace: chatSession.sealedThreads.namespace,\n principal: chatSession.principal,\n codec: chatSession.sealedThreads.codec,\n })\n : ChatSessionStorage({\n kind: 'memory',\n threadId: id,\n scope: chatSession.scope,\n principal: chatSession.principal,\n }),\n },\n ...(foreground && { foreground }),\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // lanes (`SubagentTaskToolUI`) show.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`). A send that names\n // agents (`AthenaChat`'s Agents category) also carries the agents it\n // names, so agora reads the message's own list, as Olympus's messages do,\n // and one an app attached objects to (`useAttachToChat`) carries them as\n // structured references, which agora resolves with the sender's own\n // permission before the agent is told. Only the monorepo's patch of\n // `@assistant-ui/react-statewire` reads this option: an app on the stock\n // package from npm never runs it, which is why `AthenaChat` sends a\n // message with attachments with its metadata on the message itself.\n getMessageMetadata: () => takeStagedMessageMetadata(threadId),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself,\n // and `StatewirePlanModeLaneSync` a changed plan mode. The agents a send\n // names ride its message (`getMessageMetadata`), not the run config.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":[],"mappings":"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"}
|