basalt-ui 1.11.0 → 1.13.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/AGENTS.md +21 -21
- package/CHANGELOG.md +32 -0
- package/README.md +63 -51
- package/agent/rules/basalt-agent.md +14 -0
- package/agent/rules/basalt-content.md +16 -3
- package/configs/oxlint-plugin.js +7 -3
- package/configs/oxlint-plugin.test.ts +34 -5
- package/configs/oxlint.json +4 -4
- package/dist/agent/adapter.d.ts +150 -0
- package/dist/agent/adapter.d.ts.map +1 -0
- package/dist/agent/adapter.js +482 -0
- package/dist/agent/adapter.test.d.ts +2 -0
- package/dist/agent/adapter.test.d.ts.map +1 -0
- package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
- package/dist/agent/ai-sdk-transport.js +6 -2
- package/dist/agent/ai-sdk-transport.test.d.ts +2 -0
- package/dist/agent/ai-sdk-transport.test.d.ts.map +1 -0
- package/dist/agent/coalesce.d.ts +20 -4
- package/dist/agent/coalesce.d.ts.map +1 -1
- package/dist/agent/coalesce.js +76 -8
- package/dist/agent/coalesce.test.d.ts +2 -0
- package/dist/agent/coalesce.test.d.ts.map +1 -0
- package/dist/agent/foreign.test.d.ts +2 -0
- package/dist/agent/foreign.test.d.ts.map +1 -0
- package/dist/agent/id.d.ts +78 -0
- package/dist/agent/id.d.ts.map +1 -1
- package/dist/agent/id.js +30 -0
- package/dist/agent/id.test.d.ts +2 -0
- package/dist/agent/id.test.d.ts.map +1 -0
- package/dist/agent/index.d.ts +2 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +3 -0
- package/dist/agent/merge.d.ts.map +1 -1
- package/dist/agent/merge.js +19 -7
- package/dist/agent/merge.test.d.ts +2 -0
- package/dist/agent/merge.test.d.ts.map +1 -0
- package/dist/agent/part-list.d.ts +49 -34
- package/dist/agent/part-list.d.ts.map +1 -1
- package/dist/agent/part-list.js +42 -6
- package/dist/agent/part-list.test.d.ts +2 -0
- package/dist/agent/part-list.test.d.ts.map +1 -0
- package/dist/agent/parts.d.ts +46 -10
- package/dist/agent/parts.d.ts.map +1 -1
- package/dist/agent/parts.js +16 -6
- package/dist/agent/parts.test.d.ts +2 -0
- package/dist/agent/parts.test.d.ts.map +1 -0
- package/dist/agent/thread.d.ts +18 -0
- package/dist/agent/thread.d.ts.map +1 -1
- package/dist/agent/thread.js +8 -2
- package/dist/agent/thread.test.d.ts +2 -0
- package/dist/agent/thread.test.d.ts.map +1 -0
- package/dist/agent/transport.test.d.ts +2 -0
- package/dist/agent/transport.test.d.ts.map +1 -0
- package/dist/agent/use-agent-stream.d.ts.map +1 -1
- package/dist/agent/use-agent-stream.js +2 -2
- package/dist/agent/use-agent-stream.test.d.ts +2 -0
- package/dist/agent/use-agent-stream.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.d.ts +24 -3
- package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.foreign.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.foreign.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.js +55 -15
- package/dist/agent/use-agent-thread-runs.resume.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.resume.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.wedge.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.wedge.test.d.ts.map +1 -0
- package/dist/agent-chat/composer.d.ts +130 -8
- package/dist/agent-chat/composer.d.ts.map +1 -1
- package/dist/agent-chat/composer.js +189 -23
- package/dist/agent-chat/composer.test.d.ts +2 -0
- package/dist/agent-chat/composer.test.d.ts.map +1 -0
- package/dist/agent-chat/index.d.ts +5 -1
- package/dist/agent-chat/index.d.ts.map +1 -1
- package/dist/agent-chat/index.js +2 -0
- package/dist/agent-chat/message-affordances.d.ts +59 -0
- package/dist/agent-chat/message-affordances.d.ts.map +1 -0
- package/dist/agent-chat/message-affordances.js +7 -0
- package/dist/agent-chat/relative-time.d.ts +27 -0
- package/dist/agent-chat/relative-time.d.ts.map +1 -0
- package/dist/agent-chat/relative-time.js +27 -0
- package/dist/agent-chat/relative-time.test.d.ts +2 -0
- package/dist/agent-chat/relative-time.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-detail-panel.d.ts.map +1 -1
- package/dist/agent-chat/thread-detail-panel.js +1 -1
- package/dist/agent-chat/thread-feed-row.d.ts +65 -0
- package/dist/agent-chat/thread-feed-row.d.ts.map +1 -0
- package/dist/agent-chat/thread-feed-row.js +156 -0
- package/dist/agent-chat/thread-feed-row.test.d.ts +2 -0
- package/dist/agent-chat/thread-feed-row.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-feed.d.ts +34 -5
- package/dist/agent-chat/thread-feed.d.ts.map +1 -1
- package/dist/agent-chat/thread-feed.js +52 -19
- package/dist/agent-chat/thread-feed.test.d.ts +2 -0
- package/dist/agent-chat/thread-feed.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-message.d.ts +183 -2
- package/dist/agent-chat/thread-message.d.ts.map +1 -1
- package/dist/agent-chat/thread-message.js +329 -37
- package/dist/agent-chat/thread-message.test.d.ts +2 -0
- package/dist/agent-chat/thread-message.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-outcome-card.d.ts.map +1 -1
- package/dist/agent-chat/thread-outcome-card.js +1 -16
- package/dist/agent-chat/thread-workspace.d.ts +14 -2
- package/dist/agent-chat/thread-workspace.d.ts.map +1 -1
- package/dist/agent-chat/thread-workspace.js +30 -4
- package/dist/agent-chat/thread-workspace.test.d.ts +2 -0
- package/dist/agent-chat/thread-workspace.test.d.ts.map +1 -0
- package/dist/agent-chat/tool-chip.test.d.ts +2 -0
- package/dist/agent-chat/tool-chip.test.d.ts.map +1 -0
- package/dist/agent-chat/virtualize.d.ts +123 -0
- package/dist/agent-chat/virtualize.d.ts.map +1 -0
- package/dist/agent-chat/virtualize.js +9 -0
- package/dist/agent-chat/virtualize.type-guard.test.d.ts +2 -0
- package/dist/agent-chat/virtualize.type-guard.test.d.ts.map +1 -0
- package/dist/charts/primitives/ChartFrame.test.d.ts +2 -0
- package/dist/charts/primitives/ChartFrame.test.d.ts.map +1 -0
- package/dist/charts/utils/domain.test.d.ts +2 -0
- package/dist/charts/utils/domain.test.d.ts.map +1 -0
- package/dist/cli/check-theme.test.d.ts +2 -0
- package/dist/cli/check-theme.test.d.ts.map +1 -0
- package/dist/cli/help.test.d.ts +2 -0
- package/dist/cli/help.test.d.ts.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/init-sync.test.d.ts +2 -0
- package/dist/cli/init-sync.test.d.ts.map +1 -0
- package/dist/cli/placement-engine.test.d.ts +2 -0
- package/dist/cli/placement-engine.test.d.ts.map +1 -0
- package/dist/cli/tarball-parity.test.d.ts +2 -0
- package/dist/cli/tarball-parity.test.d.ts.map +1 -0
- package/dist/cli/template-format.test.d.ts +2 -0
- package/dist/cli/template-format.test.d.ts.map +1 -0
- package/dist/cli/template-ledger.test.d.ts +2 -0
- package/dist/cli/template-ledger.test.d.ts.map +1 -0
- package/dist/cli/tokens-css.test.d.ts +2 -0
- package/dist/cli/tokens-css.test.d.ts.map +1 -0
- package/dist/content/article-actions.test.d.ts +2 -0
- package/dist/content/article-actions.test.d.ts.map +1 -0
- package/dist/content/article-model.test.d.ts +2 -0
- package/dist/content/article-model.test.d.ts.map +1 -0
- package/dist/content/block-split.test.d.ts +2 -0
- package/dist/content/block-split.test.d.ts.map +1 -0
- package/dist/content/fence-block.d.ts +37 -10
- package/dist/content/fence-block.d.ts.map +1 -1
- package/dist/content/fence-block.js +80 -14
- package/dist/content/heading-components.d.ts.map +1 -1
- package/dist/content/heading-components.js +7 -4
- package/dist/content/heading-components.test.d.ts +2 -0
- package/dist/content/heading-components.test.d.ts.map +1 -0
- package/dist/content/index.d.ts +6 -3
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +5 -1
- package/dist/content/markdown.d.ts +101 -14
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +141 -28
- package/dist/content/markdown.test.d.ts +2 -0
- package/dist/content/markdown.test.d.ts.map +1 -0
- package/dist/content/prose.module.css.test.d.ts +2 -0
- package/dist/content/prose.module.css.test.d.ts.map +1 -0
- package/dist/content/sanitize.d.ts +170 -0
- package/dist/content/sanitize.d.ts.map +1 -0
- package/dist/content/sanitize.js +178 -0
- package/dist/content/sanitize.test.d.ts +2 -0
- package/dist/content/sanitize.test.d.ts.map +1 -0
- package/dist/content/slug.test.d.ts +2 -0
- package/dist/content/slug.test.d.ts.map +1 -0
- package/dist/dashboard/stat-card.test.d.ts +2 -0
- package/dist/dashboard/stat-card.test.d.ts.map +1 -0
- package/dist/data/index.d.ts +5 -1
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/virtual-list.d.ts.map +1 -1
- package/dist/data/virtual.d.ts +2 -1
- package/dist/data/virtual.d.ts.map +1 -1
- package/dist/guard/check-source.test.d.ts +2 -0
- package/dist/guard/check-source.test.d.ts.map +1 -0
- package/dist/guard/guard-hook.test.d.ts +2 -0
- package/dist/guard/guard-hook.test.d.ts.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/provider/index.test.d.ts +2 -0
- package/dist/provider/index.test.d.ts.map +1 -0
- package/dist/provider/lab-theme.test.d.ts +2 -0
- package/dist/provider/lab-theme.test.d.ts.map +1 -0
- package/dist/router-tanstack/multi-search-param-store.test.d.ts +2 -0
- package/dist/router-tanstack/multi-search-param-store.test.d.ts.map +1 -0
- package/dist/styles.floor.test.d.ts +2 -0
- package/dist/styles.floor.test.d.ts.map +1 -0
- package/dist/surfaces.d.ts +5 -5
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +14 -4
- package/dist/theme/border-coverage.test.d.ts +18 -0
- package/dist/theme/border-coverage.test.d.ts.map +1 -0
- package/dist/theme/contrast.test.d.ts +2 -0
- package/dist/theme/contrast.test.d.ts.map +1 -0
- package/dist/theme/density-option.test.d.ts +2 -0
- package/dist/theme/density-option.test.d.ts.map +1 -0
- package/dist/theme/density-relations.test.d.ts +2 -0
- package/dist/theme/density-relations.test.d.ts.map +1 -0
- package/dist/theme/derive-theme.test.d.ts +2 -0
- package/dist/theme/derive-theme.test.d.ts.map +1 -0
- package/dist/theme/fonts-option.test.d.ts +2 -0
- package/dist/theme/fonts-option.test.d.ts.map +1 -0
- package/dist/theme/radius-option.test.d.ts +2 -0
- package/dist/theme/radius-option.test.d.ts.map +1 -0
- package/dist/theme/radius.test.d.ts +2 -0
- package/dist/theme/radius.test.d.ts.map +1 -0
- package/dist/theme/shadow-surfaces.test.d.ts +26 -0
- package/dist/theme/shadow-surfaces.test.d.ts.map +1 -0
- package/dist/theme/spacing.test.d.ts +2 -0
- package/dist/theme/spacing.test.d.ts.map +1 -0
- package/dist/theme/use-basalt-spacing.test.d.ts +2 -0
- package/dist/theme/use-basalt-spacing.test.d.ts.map +1 -0
- package/dist/theme-lab/derive-controls.test.d.ts +2 -0
- package/dist/theme-lab/derive-controls.test.d.ts.map +1 -0
- package/dist/theme-lab/derive-state.test.d.ts +2 -0
- package/dist/theme-lab/derive-state.test.d.ts.map +1 -0
- package/dist/theme-lab/theme-lab.test.d.ts +2 -0
- package/dist/theme-lab/theme-lab.test.d.ts.map +1 -0
- package/dist/tokens/build-fonts-css.test.d.ts +2 -0
- package/dist/tokens/build-fonts-css.test.d.ts.map +1 -0
- package/dist/tokens/build-radius-css.test.d.ts +2 -0
- package/dist/tokens/build-radius-css.test.d.ts.map +1 -0
- package/dist/tokens/density.test.d.ts +2 -0
- package/dist/tokens/density.test.d.ts.map +1 -0
- package/dist/tokens/derive-radius.test.d.ts +2 -0
- package/dist/tokens/derive-radius.test.d.ts.map +1 -0
- package/dist/tokens/derive.test.d.ts +2 -0
- package/dist/tokens/derive.test.d.ts.map +1 -0
- package/dist/tokens/palette.test.d.ts +2 -0
- package/dist/tokens/palette.test.d.ts.map +1 -0
- package/dist/vite-color-mix.test.d.ts +2 -0
- package/dist/vite-color-mix.test.d.ts.map +1 -0
- package/dist/vite.test.d.ts +2 -0
- package/dist/vite.test.d.ts.map +1 -0
- package/llms.txt +9 -9
- package/package.json +7 -2
- package/src/agent/adapter.test.ts +1640 -0
- package/src/agent/adapter.ts +945 -0
- package/src/agent/ai-sdk-transport.test.ts +117 -26
- package/src/agent/ai-sdk-transport.ts +8 -2
- package/src/agent/coalesce.test.ts +202 -9
- package/src/agent/coalesce.ts +126 -15
- package/src/agent/foreign.test.ts +5 -1
- package/src/agent/id.test.ts +101 -3
- package/src/agent/id.ts +118 -0
- package/src/agent/index.ts +8 -0
- package/src/agent/merge.test.ts +87 -0
- package/src/agent/merge.ts +57 -10
- package/src/agent/part-list.test.tsx +31 -1
- package/src/agent/part-list.tsx +77 -29
- package/src/agent/parts.test.ts +121 -4
- package/src/agent/parts.ts +78 -17
- package/src/agent/thread.test.ts +75 -2
- package/src/agent/thread.ts +25 -1
- package/src/agent/use-agent-stream.test.tsx +31 -5
- package/src/agent/use-agent-stream.ts +6 -3
- package/src/agent/use-agent-thread-runs.foreign.test.tsx +5 -0
- package/src/agent/use-agent-thread-runs.resume.test.tsx +16 -11
- package/src/agent/use-agent-thread-runs.test.tsx +356 -17
- package/src/agent/use-agent-thread-runs.ts +159 -23
- package/src/agent/use-agent-thread-runs.wedge.test.tsx +93 -7
- package/src/agent-chat/composer.test.tsx +924 -0
- package/src/agent-chat/composer.tsx +521 -52
- package/src/agent-chat/index.ts +13 -1
- package/src/agent-chat/message-affordances.ts +61 -0
- package/src/agent-chat/relative-time.test.ts +95 -0
- package/src/agent-chat/relative-time.ts +55 -0
- package/src/agent-chat/thread-detail-panel.tsx +3 -1
- package/src/agent-chat/thread-feed-row.test.tsx +510 -0
- package/src/agent-chat/thread-feed-row.tsx +274 -0
- package/src/agent-chat/thread-feed.test.tsx +241 -0
- package/src/agent-chat/thread-feed.tsx +119 -18
- package/src/agent-chat/thread-message.test.tsx +1078 -4
- package/src/agent-chat/thread-message.tsx +795 -42
- package/src/agent-chat/thread-outcome-card.tsx +1 -25
- package/src/agent-chat/thread-workspace.test.tsx +169 -0
- package/src/agent-chat/thread-workspace.tsx +70 -6
- package/src/agent-chat/virtualize.ts +132 -0
- package/src/agent-chat/virtualize.type-guard.test.ts +49 -0
- package/src/cli/index.ts +0 -1
- package/src/cli/template-format.test.ts +2 -2
- package/src/content/fence-block.tsx +242 -15
- package/src/content/heading-components.test.tsx +65 -0
- package/src/content/heading-components.tsx +26 -5
- package/src/content/index.ts +19 -3
- package/src/content/markdown.test.tsx +603 -0
- package/src/content/markdown.tsx +355 -35
- package/src/content/sanitize.test.ts +659 -0
- package/src/content/sanitize.ts +510 -0
- package/src/dashboard/stat-card.test.tsx +6 -1
- package/src/data/index.ts +5 -1
- package/src/data/virtual-list.tsx +2 -1
- package/src/data/virtual.ts +2 -1
- package/src/index.ts +18 -1
- package/src/surfaces.ts +13 -3
- package/src/theme/contrast.test.ts +1 -4
- package/src/theme/density-relations.test.ts +4 -2
- package/src/theme/fonts-option.test.ts +7 -1
- package/src/theme/shadow-surfaces.test.ts +21 -6
- package/src/theme/use-basalt-spacing.test.tsx +2 -1
package/dist/agent/parts.d.ts
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Exhaustiveness is enforced at every switch via assertNever (imported from '../register.js').
|
|
5
5
|
* Adding a new variant without a matching case is a tsc error — see the fixture in
|
|
6
|
-
* apps/playground/src/demo/agent-part.type-guard.ts.
|
|
6
|
+
* apps/playground/src/demo/agent-part.type-guard.ts. One caveat for code that folds WIRE data on
|
|
7
|
+
* the render path (`coalesceParts`): keep the compile-time guarantee — bind the value at `never` —
|
|
8
|
+
* but do NOT let the runtime throw, or one malformed chunk kills the whole transcript. See
|
|
9
|
+
* `mergeToolPart`'s default branch for that shape.
|
|
7
10
|
*
|
|
8
11
|
* Eden #231 doctrine: the server-side Elysia route MUST declare `: AsyncGenerator<AgentPart>`
|
|
9
12
|
* explicitly and carry NO t.Object/t.Union response schema. Validate at yield-time. See
|
|
@@ -68,33 +71,66 @@ type ToolApproval = {
|
|
|
68
71
|
};
|
|
69
72
|
type ToolCallBase = PartBase & {
|
|
70
73
|
readonly type: 'tool';
|
|
71
|
-
/** Required on all seven states (was optional — see parts.ts history). */
|
|
72
|
-
readonly toolCallId: string;
|
|
73
74
|
readonly toolName: string;
|
|
74
75
|
/** Wall-clock time from first sighting of this toolCallId to its terminal state. */
|
|
75
76
|
readonly durationMs?: number;
|
|
76
77
|
readonly providerExecuted?: boolean;
|
|
77
78
|
};
|
|
78
|
-
|
|
79
|
+
/**
|
|
80
|
+
* The three IN-FLIGHT states (`input-streaming`, `input-available`, `approval-requested`) carry an
|
|
81
|
+
* authoritative `toolCallId` — the merge key, and for them it is structural. An in-flight part
|
|
82
|
+
* exists only to be superseded by the settled part for the same call; with no merge key it can
|
|
83
|
+
* never be closed, so it would render as a forever-pending chip standing beside the real result.
|
|
84
|
+
* Nothing is lost by rejecting an unidentified one either: the `toolName` and `input` it carries
|
|
85
|
+
* are re-supplied on the settled part. `parseToolCallPart` therefore rejects these when the id is
|
|
86
|
+
* missing or empty.
|
|
87
|
+
*/
|
|
88
|
+
type Identified = ToolCallBase & {
|
|
89
|
+
readonly toolCallId: string;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* The four SETTLED states (`approval-responded` plus the three terminal ones) may legitimately
|
|
93
|
+
* arrive without a `toolCallId`, for two different reasons.
|
|
94
|
+
*
|
|
95
|
+
* `approval-responded` is where the WIRE omits it: the SDK's `tool-approval-response` chunk
|
|
96
|
+
* carries none, and it is resolved by reverse lookup on `approval.id` (coalesce.ts keeps the
|
|
97
|
+
* approvalId -> toolCallId side index that does it).
|
|
98
|
+
*
|
|
99
|
+
* The three terminal states admit the absence for a different reason — tolerance, not wire shape.
|
|
100
|
+
* They are self-contained: each carries the OUTCOME of the call, so a missing id costs only the
|
|
101
|
+
* fold (`coalesceParts` keeps an unresolvable part as its own block and never discards it).
|
|
102
|
+
* Rejecting one instead would delete the only record of how the call ended — silent data loss in a
|
|
103
|
+
* transcript, strictly worse than an unfolded block.
|
|
104
|
+
*
|
|
105
|
+
* The absence is modelled here rather than smuggled through an empty-string sentinel: the union
|
|
106
|
+
* previously declared an always-meaningful `string` that the `approval-responded` wire shape
|
|
107
|
+
* cannot supply, which forced a `''` sentinel into the type and an `as unknown as` cast into every
|
|
108
|
+
* test that built one. A `''` toolCallId is not a value any state accepts; `parseToolCallPart`
|
|
109
|
+
* normalizes one to absent at the wire boundary, so it never reaches the type or a consumer.
|
|
110
|
+
*/
|
|
111
|
+
type MaybeIdentified = ToolCallBase & {
|
|
112
|
+
readonly toolCallId?: string;
|
|
113
|
+
};
|
|
114
|
+
export type ToolCallPart = (Identified & {
|
|
79
115
|
readonly state: 'input-streaming';
|
|
80
116
|
readonly input?: unknown;
|
|
81
|
-
}) | (
|
|
117
|
+
}) | (Identified & {
|
|
82
118
|
readonly state: 'input-available';
|
|
83
119
|
readonly input: unknown;
|
|
84
|
-
}) | (
|
|
120
|
+
}) | (Identified & {
|
|
85
121
|
readonly state: 'approval-requested';
|
|
86
122
|
readonly input: unknown;
|
|
87
123
|
readonly approval: ToolApproval & {
|
|
88
124
|
readonly approved?: never;
|
|
89
125
|
readonly reason?: never;
|
|
90
126
|
};
|
|
91
|
-
}) | (
|
|
127
|
+
}) | (MaybeIdentified & {
|
|
92
128
|
readonly state: 'approval-responded';
|
|
93
129
|
readonly input: unknown;
|
|
94
130
|
readonly approval: ToolApproval & {
|
|
95
131
|
readonly approved: boolean;
|
|
96
132
|
};
|
|
97
|
-
}) | (
|
|
133
|
+
}) | (MaybeIdentified & {
|
|
98
134
|
readonly state: 'output-available';
|
|
99
135
|
readonly input: unknown;
|
|
100
136
|
readonly output: unknown;
|
|
@@ -102,7 +138,7 @@ export type ToolCallPart = (ToolCallBase & {
|
|
|
102
138
|
readonly approval?: ToolApproval & {
|
|
103
139
|
readonly approved?: true;
|
|
104
140
|
};
|
|
105
|
-
}) | (
|
|
141
|
+
}) | (MaybeIdentified & {
|
|
106
142
|
readonly state: 'output-error';
|
|
107
143
|
readonly input?: unknown;
|
|
108
144
|
/** The SDK's field name — there is no field named `error` anywhere in the union. */
|
|
@@ -112,7 +148,7 @@ export type ToolCallPart = (ToolCallBase & {
|
|
|
112
148
|
readonly approval?: ToolApproval & {
|
|
113
149
|
readonly approved?: true;
|
|
114
150
|
};
|
|
115
|
-
}) | (
|
|
151
|
+
}) | (MaybeIdentified & {
|
|
116
152
|
readonly state: 'output-denied';
|
|
117
153
|
readonly input: unknown;
|
|
118
154
|
readonly approval: ToolApproval & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../../src/agent/parts.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../../src/agent/parts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAIH,wGAAwG;AACxG,KAAK,QAAQ,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAIvC;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IACjC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,8GAA8G;AAC9G,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG;IACrC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAoBD,wFAAwF;AACxF,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED,KAAK,YAAY,GAAG,QAAQ,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,oFAAoF;IACpF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACpC,CAAA;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,KAAK,eAAe,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtE,MAAM,MAAM,YAAY,GACpB,CAAC,UAAU,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAC9E,CAAC,UAAU,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,GAC7E,CAAC,UAAU,GAAG;IACZ,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAA;KAAE,CAAA;CACzF,CAAC,GACF,CAAC,eAAe,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAA;CACjE,CAAC,GACF,CAAC,eAAe,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAA;IAClC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;KAAE,CAAA;CAChE,CAAC,GACF,CAAC,eAAe,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IACxB,oFAAoF;IACpF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,mHAAmH;IACnH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;KAAE,CAAA;CAChE,CAAC,GACF,CAAC,eAAe,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAA;KAAE,CAAA;CAC/D,CAAC,CAAA;AAEN,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;AAEjD,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,gEAAiE,CAAA;AAElG,qGAAqG;AACrG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAE7D;AAED,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG;IAClC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,mEAAmE;AACnE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvF;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa,GAAG,YAAY,GAAG,UAAU,GAAG,SAAS,CAAA;AAIpG;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAA;AAC7F,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;AAI/C;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAgD7D;AAsJD,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,SAAS,CAE5D"}
|
package/dist/agent/parts.js
CHANGED
|
@@ -51,36 +51,42 @@ function parseAgentPart(raw) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
function parseToolCallPart(id, obj) {
|
|
54
|
-
if (typeof obj["toolCallId"] !== "string") return null;
|
|
55
54
|
if (typeof obj["toolName"] !== "string") return null;
|
|
56
55
|
if (typeof obj["state"] !== "string") return null;
|
|
57
|
-
const
|
|
56
|
+
const rawToolCallId = obj["toolCallId"];
|
|
57
|
+
if (rawToolCallId !== void 0 && typeof rawToolCallId !== "string") return null;
|
|
58
|
+
const toolCallId = typeof rawToolCallId === "string" && rawToolCallId.length > 0 ? rawToolCallId : void 0;
|
|
59
|
+
const toolName = obj["toolName"];
|
|
58
60
|
const common = {
|
|
59
61
|
id,
|
|
60
62
|
type: "tool",
|
|
61
|
-
toolCallId,
|
|
62
63
|
toolName,
|
|
63
64
|
...typeof obj["durationMs"] === "number" ? { durationMs: obj["durationMs"] } : {},
|
|
64
65
|
...typeof obj["providerExecuted"] === "boolean" ? { providerExecuted: obj["providerExecuted"] } : {}
|
|
65
66
|
};
|
|
67
|
+
const identified = toolCallId !== void 0 ? { ...common, toolCallId } : null;
|
|
68
|
+
const identity = toolCallId !== void 0 ? { toolCallId } : {};
|
|
66
69
|
switch (obj["state"]) {
|
|
67
70
|
case "input-streaming":
|
|
71
|
+
if (identified === null) return null;
|
|
68
72
|
return {
|
|
69
|
-
...
|
|
73
|
+
...identified,
|
|
70
74
|
state: "input-streaming",
|
|
71
75
|
..."input" in obj ? { input: obj["input"] } : {}
|
|
72
76
|
};
|
|
73
77
|
case "input-available":
|
|
78
|
+
if (identified === null) return null;
|
|
74
79
|
if (!("input" in obj)) return null;
|
|
75
|
-
return { ...
|
|
80
|
+
return { ...identified, state: "input-available", input: obj["input"] };
|
|
76
81
|
case "approval-requested": {
|
|
82
|
+
if (identified === null) return null;
|
|
77
83
|
if (!("input" in obj)) return null;
|
|
78
84
|
const approval = parseApproval(obj["approval"]);
|
|
79
85
|
if (approval === null || approval.approved !== void 0 || approval.reason !== void 0) {
|
|
80
86
|
return null;
|
|
81
87
|
}
|
|
82
88
|
return {
|
|
83
|
-
...
|
|
89
|
+
...identified,
|
|
84
90
|
state: "approval-requested",
|
|
85
91
|
input: obj["input"],
|
|
86
92
|
approval
|
|
@@ -92,6 +98,7 @@ function parseToolCallPart(id, obj) {
|
|
|
92
98
|
if (approval === null || typeof approval.approved !== "boolean") return null;
|
|
93
99
|
return {
|
|
94
100
|
...common,
|
|
101
|
+
...identity,
|
|
95
102
|
state: "approval-responded",
|
|
96
103
|
input: obj["input"],
|
|
97
104
|
approval
|
|
@@ -103,6 +110,7 @@ function parseToolCallPart(id, obj) {
|
|
|
103
110
|
if (approval === null || approval.approved !== false) return null;
|
|
104
111
|
return {
|
|
105
112
|
...common,
|
|
113
|
+
...identity,
|
|
106
114
|
state: "output-denied",
|
|
107
115
|
input: obj["input"],
|
|
108
116
|
approval
|
|
@@ -117,6 +125,7 @@ function parseToolCallPart(id, obj) {
|
|
|
117
125
|
}
|
|
118
126
|
return {
|
|
119
127
|
...common,
|
|
128
|
+
...identity,
|
|
120
129
|
state: "output-available",
|
|
121
130
|
input: obj["input"],
|
|
122
131
|
output: obj["output"],
|
|
@@ -132,6 +141,7 @@ function parseToolCallPart(id, obj) {
|
|
|
132
141
|
}
|
|
133
142
|
return {
|
|
134
143
|
...common,
|
|
144
|
+
...identity,
|
|
135
145
|
state: "output-error",
|
|
136
146
|
errorText: obj["errorText"],
|
|
137
147
|
..."input" in obj ? { input: obj["input"] } : {},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parts.test.d.ts","sourceRoot":"","sources":["../../src/agent/parts.test.ts"],"names":[],"mappings":""}
|
package/dist/agent/thread.d.ts
CHANGED
|
@@ -103,6 +103,24 @@ export type ThreadsStore<TPart = AgentPart> = {
|
|
|
103
103
|
readonly remove: (id: string) => void;
|
|
104
104
|
/** Remove all threads and clear the active selection. */
|
|
105
105
|
readonly clear: () => void;
|
|
106
|
+
/**
|
|
107
|
+
* Whether `threads` reflects the backing store yet. Always `true` for the localStorage store
|
|
108
|
+
* (createPersistedState resolves synchronously); meaningful only for an async, server-backed
|
|
109
|
+
* store built with `createAdapterThreadsStore` (./adapter), where it stays `false` until the
|
|
110
|
+
* first `listThreads` SUCCEEDS. Pair it with `error` — `!hydrated && error !== undefined` is a
|
|
111
|
+
* failed load, `!hydrated && error === undefined` is still loading.
|
|
112
|
+
*
|
|
113
|
+
* Gating an empty state on this is the CALLER's job when hand-assembling `ThreadFeed` /
|
|
114
|
+
* `ThreadDetailPanel`; the shipped `ThreadWorkspace` already does it internally, so an
|
|
115
|
+
* async store never flashes "no threads yet" through it before it actually knows.
|
|
116
|
+
*/
|
|
117
|
+
readonly hydrated: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* The most recent persistence failure, or `undefined`. Always `undefined` for the localStorage
|
|
120
|
+
* store, which has no failure the caller can act on. An async store surfaces the rejected
|
|
121
|
+
* load/write here after rolling its optimistic edit back.
|
|
122
|
+
*/
|
|
123
|
+
readonly error: unknown;
|
|
106
124
|
};
|
|
107
125
|
/**
|
|
108
126
|
* Creates a stable persisted multi-thread hook for the given key + version.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread.d.ts","sourceRoot":"","sources":["../../src/agent/thread.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"thread.d.ts","sourceRoot":"","sources":["../../src/agent/thread.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/thread.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useRef } from "react";
|
|
2
2
|
import { createPersistedState } from "../state.js";
|
|
3
|
+
import { mintThreadId } from "./id.js";
|
|
3
4
|
function createThreadsStore(opts) {
|
|
4
5
|
const maxThreads = opts.maxThreads ?? 50;
|
|
5
6
|
const maxMessages = opts.maxMessagesPerThread ?? 100;
|
|
@@ -27,7 +28,7 @@ function createThreadsStore(opts) {
|
|
|
27
28
|
);
|
|
28
29
|
const create = useCallback(
|
|
29
30
|
(createOpts) => {
|
|
30
|
-
const id =
|
|
31
|
+
const id = mintThreadId();
|
|
31
32
|
const now = Date.now();
|
|
32
33
|
const thread = {
|
|
33
34
|
id,
|
|
@@ -122,7 +123,12 @@ function createThreadsStore(opts) {
|
|
|
122
123
|
setResumeToken,
|
|
123
124
|
markRead,
|
|
124
125
|
remove,
|
|
125
|
-
clear
|
|
126
|
+
clear,
|
|
127
|
+
// localStorage resolves synchronously and swallows its own quota errors, so there is never
|
|
128
|
+
// a pending load to await nor a failure a caller could act on. See ./adapter for the async
|
|
129
|
+
// store where these two carry real information.
|
|
130
|
+
hydrated: true,
|
|
131
|
+
error: void 0
|
|
126
132
|
};
|
|
127
133
|
};
|
|
128
134
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread.test.d.ts","sourceRoot":"","sources":["../../src/agent/thread.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.test.d.ts","sourceRoot":"","sources":["../../src/agent/transport.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-agent-stream.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-stream.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAA;AAIlE,MAAM,MAAM,oBAAoB,CAAC,KAAK,EAAE,MAAM,IAAI;IAChD,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;IACvB,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAA;IACzB,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACzC,CAAA;AAID;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAClF,SAAS,GACV,EAAE;IACD,SAAS,EAAE,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;CACzC,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"use-agent-stream.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-stream.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAA;AAIlE,MAAM,MAAM,oBAAoB,CAAC,KAAK,EAAE,MAAM,IAAI;IAChD,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;IACvB,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAA;IACzB,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACzC,CAAA;AAID;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAClF,SAAS,GACV,EAAE;IACD,SAAS,EAAE,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;CACzC,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CA6EtC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import { withPartIds } from "./id.js";
|
|
2
|
+
import { mintThreadId, withPartIds } from "./id.js";
|
|
3
3
|
import { isStartPart } from "./parts.js";
|
|
4
4
|
import { mergePart } from "./merge.js";
|
|
5
5
|
function useAgentStream({
|
|
@@ -25,7 +25,7 @@ function useAgentStream({
|
|
|
25
25
|
setParts([]);
|
|
26
26
|
setError(void 0);
|
|
27
27
|
setStatus("streaming");
|
|
28
|
-
const runId =
|
|
28
|
+
const runId = mintThreadId();
|
|
29
29
|
try {
|
|
30
30
|
for await (const part of withPartIds(runId, transport.stream(input, controller.signal))) {
|
|
31
31
|
if (controllerRef.current !== controller) return;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-stream.test.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-stream.test.tsx"],"names":[],"mappings":""}
|
|
@@ -46,18 +46,39 @@ export type UseAgentThreadRunsArgs<TPart = AgentPart> = {
|
|
|
46
46
|
export type UseAgentThreadRunsReturn<TPart = AgentPart> = {
|
|
47
47
|
/** Live stream state per thread id, for threads with a run in progress or just completed. */
|
|
48
48
|
readonly runs: ReadonlyMap<string, ThreadRunState<TPart>>;
|
|
49
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Start a new turn on `threadId`. No-op if that thread already has a stream in flight.
|
|
51
|
+
*
|
|
52
|
+
* @throws {Error} synchronously, before any state is touched, on a host with no usable
|
|
53
|
+
* `crypto` at all (see `mintMessageId` in `./id.ts` — the id it mints here is the new user
|
|
54
|
+
* ChatMessage's idempotency key, so it degrades to a throw rather than a silent collision).
|
|
55
|
+
* This throw is a true no-op: it happens before `appendMessage`/`setStatus`/the run's
|
|
56
|
+
* controller are registered, so nothing is left half-started — the thread is exactly as it was
|
|
57
|
+
* before the call. A caller invoking `start` from an event handler on a target that must
|
|
58
|
+
* tolerate this (very old WebViews, non-DOM SSR shims) should wrap the call in its own
|
|
59
|
+
* try/catch; this rung is vanishingly rare in practice (see `mintMessageId`'s own doc).
|
|
60
|
+
*/
|
|
50
61
|
readonly start: (threadId: string, input: string) => void;
|
|
51
62
|
/**
|
|
52
63
|
* Replay the last user input sent on `threadId` (same code path as `start`). No-op if
|
|
53
64
|
* `threadId` has never had a turn started, or already has one in flight.
|
|
65
|
+
*
|
|
66
|
+
* @throws {Error} same condition and same true-no-op guarantee as `start` — see its doc.
|
|
54
67
|
*/
|
|
55
68
|
readonly retry: (threadId: string) => void;
|
|
56
69
|
/**
|
|
57
|
-
* Abort the in-flight stream for `threadId` (no-op if
|
|
58
|
-
*
|
|
70
|
+
* Abort the in-flight stream for `threadId` (true no-op only if BOTH `controllersRef` and
|
|
71
|
+
* `runs` have nothing for it — i.e. the thread genuinely isn't live). Preserves whatever content
|
|
72
|
+
* had already arrived: if the run had accumulated any parts, they're persisted as an assistant
|
|
59
73
|
* ChatMessage with `finish: 'stopped'` (unless that message already landed — see finalizeStop),
|
|
60
74
|
* then distilled into an outcome and the thread is settled to 'done'.
|
|
75
|
+
*
|
|
76
|
+
* Defense-in-depth: if `runs` reports `threadId` as `'streaming'` but no controller is
|
|
77
|
+
* registered for it (a phantom entry — not reachable via any path in this hook today, since the
|
|
78
|
+
* unmount-cleanup effect and `finalizeStop` both tear down `controllersRef` and `runs` together,
|
|
79
|
+
* but guarded against here so nothing in this file can EVER wedge a thread the UI shows as live
|
|
80
|
+
* with no way to reach a terminal state), `stop()` still settles it instead of silently
|
|
81
|
+
* no-opping forever.
|
|
61
82
|
*/
|
|
62
83
|
readonly stop: (threadId: string) => void;
|
|
63
84
|
/** Abort every in-flight stream across all threads, settling each the same way stop() would. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-agent-thread-runs.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,WAAW,CAAA;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAA6B,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,SAAS,IAAI;IAC9C,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;CACxB,CAAA;AAID,MAAM,MAAM,sBAAsB,CAAC,KAAK,GAAG,SAAS,IAAI;IACtD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,SAAS,EACd,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,GAC7B,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IACzD,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,CAAA;IACnC,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC,KAAK,CAAC,CAAA;IAC/C;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,EAAE,CAAA;CAClD,CAAA;AAID,MAAM,MAAM,wBAAwB,CAAC,KAAK,GAAG,SAAS,IAAI;IACxD,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAA;IACzD
|
|
1
|
+
{"version":3,"file":"use-agent-thread-runs.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,WAAW,CAAA;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAA6B,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,SAAS,IAAI;IAC9C,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;CACxB,CAAA;AAID,MAAM,MAAM,sBAAsB,CAAC,KAAK,GAAG,SAAS,IAAI;IACtD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,SAAS,EACd,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,GAC7B,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IACzD,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,CAAA;IACnC,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC,KAAK,CAAC,CAAA;IAC/C;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,EAAE,CAAA;CAClD,CAAA;AAID,MAAM,MAAM,wBAAwB,CAAC,KAAK,GAAG,SAAS,IAAI;IACxD,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAA;IACzD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACzD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,gGAAgG;IAChG,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAC7B,CAAA;AAuRD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,SAAS,QAAQ,GAAG,SAAS,EAAE,EACrE,SAAS,EACT,KAAK,EACL,cAAc,EACd,WAAW,GACZ,EAAE,sBAAsB,CAAC,KAAK,CAAC,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAgSjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-thread-runs.foreign.test.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.foreign.test.tsx"],"names":[],"mappings":""}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import { withPartIds } from "./id.js";
|
|
2
|
+
import { mintMessageId, mintThreadId, withPartIds } from "./id.js";
|
|
3
3
|
import { mergePart } from "./merge.js";
|
|
4
4
|
import { isStartPart } from "./parts.js";
|
|
5
5
|
import { isResumable } from "./transport.js";
|
|
6
6
|
function defaultToUserParts(input) {
|
|
7
|
-
return [{ id:
|
|
7
|
+
return [{ id: mintThreadId(), type: "text", text: input }];
|
|
8
8
|
}
|
|
9
9
|
function buildDoneSnapshot(priorThread, threadId, userMessage, assistantMessage) {
|
|
10
10
|
const updatedAt = Date.now();
|
|
@@ -59,7 +59,9 @@ async function consumeAndFinalize(args) {
|
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
const assistantMessage = {
|
|
62
|
-
|
|
62
|
+
// appendMessage's idempotency key — mintMessageId, never mintThreadId (see that helper's
|
|
63
|
+
// doc): a collided id here would silently drop this message, not merge a duplicate thread.
|
|
64
|
+
id: mintMessageId(),
|
|
63
65
|
role: "assistant",
|
|
64
66
|
parts,
|
|
65
67
|
createdAt: Date.now(),
|
|
@@ -101,24 +103,43 @@ async function consumeAndFinalize(args) {
|
|
|
101
103
|
}
|
|
102
104
|
async function finalizeStop(args) {
|
|
103
105
|
const { threadId, parts, alreadyAppended, storeRef, resolveOutcome, setRuns } = args;
|
|
106
|
+
let appendFailed = false;
|
|
104
107
|
if (!alreadyAppended && parts.length > 0) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
try {
|
|
109
|
+
const stoppedMessage = {
|
|
110
|
+
// Same idempotency-key reasoning as consumeAndFinalize's assistantMessage — mintMessageId.
|
|
111
|
+
// This can throw on rung 3 (no usable crypto — see ./id.ts) just like appendMessage
|
|
112
|
+
// (consumer code) can throw for its own reasons; both are caught below so neither can
|
|
113
|
+
// wedge the thread — see this function's doc.
|
|
114
|
+
id: mintMessageId(),
|
|
115
|
+
role: "assistant",
|
|
116
|
+
parts,
|
|
117
|
+
createdAt: Date.now(),
|
|
118
|
+
finish: "stopped"
|
|
119
|
+
};
|
|
120
|
+
storeRef.current.appendMessage(threadId, stoppedMessage);
|
|
121
|
+
} catch {
|
|
122
|
+
appendFailed = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
let settleFailed = appendFailed;
|
|
126
|
+
try {
|
|
127
|
+
storeRef.current.setStatus(threadId, appendFailed ? "error" : "done");
|
|
128
|
+
} catch {
|
|
129
|
+
settleFailed = true;
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
storeRef.current.setResumeToken(threadId, void 0);
|
|
133
|
+
} catch {
|
|
134
|
+
settleFailed = true;
|
|
113
135
|
}
|
|
114
|
-
storeRef.current.setStatus(threadId, "done");
|
|
115
|
-
storeRef.current.setResumeToken(threadId, void 0);
|
|
116
136
|
setRuns((prev) => {
|
|
117
137
|
if (!prev.has(threadId)) return prev;
|
|
118
138
|
const next = new Map(prev);
|
|
119
139
|
next.delete(threadId);
|
|
120
140
|
return next;
|
|
121
141
|
});
|
|
142
|
+
if (settleFailed) return;
|
|
122
143
|
const snapshot = storeRef.current.threads.find((thread) => thread.id === threadId);
|
|
123
144
|
if (snapshot === void 0) return;
|
|
124
145
|
const outcome = await resolveOutcome(snapshot);
|
|
@@ -155,9 +176,20 @@ function useAgentThreadRuns({
|
|
|
155
176
|
};
|
|
156
177
|
useEffect(
|
|
157
178
|
() => () => {
|
|
179
|
+
const abortedThreadIds = Array.from(controllersRef.current.keys());
|
|
158
180
|
controllersRef.current.forEach((controller) => controller.abort());
|
|
159
181
|
controllersRef.current.clear();
|
|
160
182
|
appendedRef.current.clear();
|
|
183
|
+
if (abortedThreadIds.length === 0) return;
|
|
184
|
+
setRuns((prev) => {
|
|
185
|
+
let next;
|
|
186
|
+
for (const threadId of abortedThreadIds) {
|
|
187
|
+
if (!prev.has(threadId)) continue;
|
|
188
|
+
next ??= new Map(prev);
|
|
189
|
+
next.delete(threadId);
|
|
190
|
+
}
|
|
191
|
+
return next ?? prev;
|
|
192
|
+
});
|
|
161
193
|
},
|
|
162
194
|
[]
|
|
163
195
|
);
|
|
@@ -206,7 +238,8 @@ function useAgentThreadRuns({
|
|
|
206
238
|
if (controllersRef.current.has(threadId)) return;
|
|
207
239
|
lastInputRef.current.set(threadId, input);
|
|
208
240
|
const userMessage = {
|
|
209
|
-
|
|
241
|
+
// Same idempotency-key reasoning as consumeAndFinalize's assistantMessage — mintMessageId.
|
|
242
|
+
id: mintMessageId(),
|
|
210
243
|
role: "user",
|
|
211
244
|
parts: toUserPartsRef.current(input),
|
|
212
245
|
createdAt: Date.now()
|
|
@@ -248,7 +281,14 @@ function useAgentThreadRuns({
|
|
|
248
281
|
const stop = useCallback(
|
|
249
282
|
(threadId) => {
|
|
250
283
|
const controller = controllersRef.current.get(threadId);
|
|
251
|
-
if (controller === void 0)
|
|
284
|
+
if (controller === void 0) {
|
|
285
|
+
if (!runsRef.current.has(threadId)) return;
|
|
286
|
+
const parts2 = runsRef.current.get(threadId)?.parts ?? [];
|
|
287
|
+
const alreadyAppended2 = appendedRef.current.has(threadId);
|
|
288
|
+
appendedRef.current.delete(threadId);
|
|
289
|
+
void finalizeStop({ threadId, parts: parts2, alreadyAppended: alreadyAppended2, storeRef, resolveOutcome, setRuns });
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
252
292
|
controllersRef.current.delete(threadId);
|
|
253
293
|
const parts = runsRef.current.get(threadId)?.parts ?? [];
|
|
254
294
|
controller.abort();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-thread-runs.resume.test.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.resume.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-thread-runs.test.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-thread-runs.wedge.test.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.wedge.test.tsx"],"names":[],"mappings":""}
|