basalt-ui 1.11.0 → 1.12.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 +15 -0
- package/README.md +36 -27
- package/agent/rules/basalt-content.md +16 -3
- package/dist/agent/adapter.d.ts +146 -0
- package/dist/agent/adapter.d.ts.map +1 -0
- package/dist/agent/adapter.js +473 -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.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 +30 -0
- package/dist/agent/id.d.ts.map +1 -1
- package/dist/agent/id.js +16 -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 +14 -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.test.d.ts +2 -0
- package/dist/agent/use-agent-stream.test.d.ts.map +1 -0
- 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.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 +1 -1
- package/dist/agent-chat/index.d.ts.map +1 -1
- 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-message.d.ts.map +1 -1
- package/dist/agent-chat/thread-message.js +14 -3
- 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-workspace.js +1 -1
- 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/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/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 +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -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 +4 -4
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +12 -3
- 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 +6 -6
- package/package.json +6 -1
- package/src/agent/adapter.test.ts +1403 -0
- package/src/agent/adapter.ts +887 -0
- package/src/agent/ai-sdk-transport.test.ts +53 -26
- 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 +6 -2
- package/src/agent/id.ts +48 -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 +21 -1
- package/src/agent/use-agent-stream.test.tsx +9 -5
- 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 +30 -17
- package/src/agent/use-agent-thread-runs.wedge.test.tsx +13 -7
- package/src/agent-chat/composer.test.tsx +924 -0
- package/src/agent-chat/composer.tsx +521 -52
- package/src/agent-chat/index.ts +1 -1
- package/src/agent-chat/thread-detail-panel.tsx +3 -1
- package/src/agent-chat/thread-message.test.tsx +141 -1
- package/src/agent-chat/thread-message.tsx +29 -4
- package/src/agent-chat/thread-workspace.tsx +1 -1
- 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/index.ts +13 -1
- package/src/surfaces.ts +12 -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 +12 -6
- package/src/theme/use-basalt-spacing.test.tsx +2 -1
|
@@ -17,7 +17,7 @@ import { act, renderHook, waitFor } from '@testing-library/react'
|
|
|
17
17
|
import { useAgentThreadRuns } from './use-agent-thread-runs'
|
|
18
18
|
import type { AgentThread, ThreadsStore } from './thread'
|
|
19
19
|
import type { AgentTransport } from './transport'
|
|
20
|
-
import type { AgentPart } from './parts'
|
|
20
|
+
import type { AgentPart, AgentPartDraft } from './parts'
|
|
21
21
|
import type { AgentOutcome, OutcomeResolver } from './outcome'
|
|
22
22
|
|
|
23
23
|
// ── test-only ThreadsStore double — see use-agent-thread-runs.wedge.test.tsx for the rationale ──
|
|
@@ -100,6 +100,11 @@ function createTestThreadsStore(
|
|
|
100
100
|
threads = []
|
|
101
101
|
activeId = null
|
|
102
102
|
},
|
|
103
|
+
// Always-hydrated, never-erroring — mirrors the localStorage-backed store's real values
|
|
104
|
+
// (see ThreadsStore.hydrated/.error doc comments); this double is a synchronous in-memory
|
|
105
|
+
// stand-in with no async load path to fail.
|
|
106
|
+
hydrated: true,
|
|
107
|
+
error: undefined,
|
|
103
108
|
}
|
|
104
109
|
}
|
|
105
110
|
|
|
@@ -130,7 +135,7 @@ describe('useAgentThreadRuns — concurrency, no-op guard, finalize order, failu
|
|
|
130
135
|
const transport: AgentTransport<AgentPart, string> = {
|
|
131
136
|
async *stream(input) {
|
|
132
137
|
await gates.get(input)?.promise
|
|
133
|
-
yield { type: 'text', text: `done:${input}` }
|
|
138
|
+
yield { id: 'p1', type: 'text', text: `done:${input}` }
|
|
134
139
|
},
|
|
135
140
|
}
|
|
136
141
|
|
|
@@ -173,7 +178,7 @@ describe('useAgentThreadRuns — concurrency, no-op guard, finalize order, failu
|
|
|
173
178
|
async *stream(input) {
|
|
174
179
|
calls.push(input)
|
|
175
180
|
await gate.promise
|
|
176
|
-
yield { type: 'text', text: 'ok' }
|
|
181
|
+
yield { id: 'p1', type: 'text', text: 'ok' }
|
|
177
182
|
},
|
|
178
183
|
}
|
|
179
184
|
|
|
@@ -218,7 +223,7 @@ describe('useAgentThreadRuns — concurrency, no-op guard, finalize order, failu
|
|
|
218
223
|
const transport: AgentTransport<AgentPart, string> = {
|
|
219
224
|
async *stream() {
|
|
220
225
|
await gate.promise
|
|
221
|
-
yield { type: 'text', text: 'hi' }
|
|
226
|
+
yield { id: 'p1', type: 'text', text: 'hi' }
|
|
222
227
|
},
|
|
223
228
|
}
|
|
224
229
|
|
|
@@ -265,7 +270,7 @@ describe('useAgentThreadRuns — concurrency, no-op guard, finalize order, failu
|
|
|
265
270
|
async *stream() {
|
|
266
271
|
throw new Error('boom')
|
|
267
272
|
// eslint-disable-next-line no-unreachable
|
|
268
|
-
yield { type: 'text', text: 'unreachable' }
|
|
273
|
+
yield { id: 'p1', type: 'text', text: 'unreachable' }
|
|
269
274
|
},
|
|
270
275
|
}
|
|
271
276
|
|
|
@@ -294,7 +299,7 @@ describe('useAgentThreadRuns — concurrency, no-op guard, finalize order, failu
|
|
|
294
299
|
const transport: AgentTransport<AgentPart, string> = {
|
|
295
300
|
async *stream(input) {
|
|
296
301
|
calls.push(input)
|
|
297
|
-
yield { type: 'text', text: 'x' }
|
|
302
|
+
yield { id: 'p1', type: 'text', text: 'x' }
|
|
298
303
|
},
|
|
299
304
|
}
|
|
300
305
|
|
|
@@ -316,7 +321,7 @@ describe('useAgentThreadRuns — concurrency, no-op guard, finalize order, failu
|
|
|
316
321
|
const transport: AgentTransport<AgentPart, string> = {
|
|
317
322
|
async *stream(input) {
|
|
318
323
|
calls.push(input)
|
|
319
|
-
yield { type: 'text', text: `done:${input}` }
|
|
324
|
+
yield { id: 'p1', type: 'text', text: `done:${input}` }
|
|
320
325
|
},
|
|
321
326
|
}
|
|
322
327
|
|
|
@@ -364,7 +369,7 @@ describe('useAgentThreadRuns — concurrency, no-op guard, finalize order, failu
|
|
|
364
369
|
|
|
365
370
|
const transport: AgentTransport<AgentPart, string> = {
|
|
366
371
|
async *stream() {
|
|
367
|
-
yield { type: 'text', text: 'hi' }
|
|
372
|
+
yield { id: 'p1', type: 'text', text: 'hi' }
|
|
368
373
|
},
|
|
369
374
|
}
|
|
370
375
|
|
|
@@ -403,11 +408,15 @@ describe('useAgentThreadRuns — stop()/stopAll() lifecycle', () => {
|
|
|
403
408
|
const threadId = store.create()
|
|
404
409
|
|
|
405
410
|
const gate = deferred<void>()
|
|
411
|
+
// Yields id-less drafts on purpose — the assertion below exists specifically to prove
|
|
412
|
+
// withPartIds stamps the missing id as `${threadId}#0`, so the cast documents that the type
|
|
413
|
+
// says AgentPart (identified) while this transport deliberately produces what the real
|
|
414
|
+
// contract is AgentPartDraft (a transport is always permitted to omit id).
|
|
406
415
|
const transport: AgentTransport<AgentPart, string> = {
|
|
407
416
|
async *stream() {
|
|
408
|
-
yield { type: 'text', text: 'partial' }
|
|
417
|
+
yield { type: 'text', text: 'partial' } as AgentPartDraft as AgentPart
|
|
409
418
|
await gate.promise
|
|
410
|
-
yield { type: 'text', text: 'never arrives' }
|
|
419
|
+
yield { type: 'text', text: 'never arrives' } as AgentPartDraft as AgentPart
|
|
411
420
|
},
|
|
412
421
|
}
|
|
413
422
|
|
|
@@ -456,7 +465,7 @@ describe('useAgentThreadRuns — stop()/stopAll() lifecycle', () => {
|
|
|
456
465
|
|
|
457
466
|
const transport: AgentTransport<AgentPart, string> = {
|
|
458
467
|
async *stream() {
|
|
459
|
-
yield { type: 'text', text: 'hi' }
|
|
468
|
+
yield { id: 'p1', type: 'text', text: 'hi' }
|
|
460
469
|
},
|
|
461
470
|
}
|
|
462
471
|
|
|
@@ -498,7 +507,7 @@ describe('useAgentThreadRuns — stop()/stopAll() lifecycle', () => {
|
|
|
498
507
|
|
|
499
508
|
const transport: AgentTransport<AgentPart, string> = {
|
|
500
509
|
async *stream() {
|
|
501
|
-
yield { type: 'text', text: 'x' }
|
|
510
|
+
yield { id: 'p1', type: 'text', text: 'x' }
|
|
502
511
|
},
|
|
503
512
|
}
|
|
504
513
|
|
|
@@ -672,10 +681,10 @@ describe('useAgentThreadRuns — stop()/stopAll() lifecycle', () => {
|
|
|
672
681
|
const transport: AgentTransport<AgentPart, string> = {
|
|
673
682
|
async *stream(input) {
|
|
674
683
|
if (input === 'a') {
|
|
675
|
-
yield { type: 'text', text: 'partial-a' }
|
|
684
|
+
yield { id: 'p1', type: 'text', text: 'partial-a' }
|
|
676
685
|
await gateA.promise
|
|
677
686
|
} else {
|
|
678
|
-
yield { type: 'text', text: 'partial-b' }
|
|
687
|
+
yield { id: 'p1', type: 'text', text: 'partial-b' }
|
|
679
688
|
await gateB.promise
|
|
680
689
|
}
|
|
681
690
|
},
|
|
@@ -748,17 +757,21 @@ describe('useAgentThreadRuns — F1 regression: id-less drafts within one run',
|
|
|
748
757
|
const store = createTestThreadsStore()
|
|
749
758
|
const threadId = store.create()
|
|
750
759
|
|
|
760
|
+
// Yields id-less drafts on purpose — the whole point of this regression is that TWO drafts
|
|
761
|
+
// (of different types, so a real bug wouldn't be "same id" but "no id at all") must not
|
|
762
|
+
// collide via `undefined === undefined`. The cast documents that the type says AgentPart
|
|
763
|
+
// (identified) while a transport is always permitted to omit id (AgentPartDraft).
|
|
751
764
|
const transport: AgentTransport<AgentPart, string> = {
|
|
752
765
|
async *stream() {
|
|
753
|
-
yield { type: 'text', text: 'Hi' }
|
|
766
|
+
yield { type: 'text', text: 'Hi' } as AgentPartDraft as AgentPart
|
|
754
767
|
yield {
|
|
755
768
|
type: 'tool',
|
|
756
769
|
toolCallId: 'c1',
|
|
757
770
|
toolName: 'search',
|
|
758
771
|
state: 'input-available',
|
|
759
772
|
input: { q: 'x' },
|
|
760
|
-
}
|
|
761
|
-
yield { type: 'text', text: 'Bye' }
|
|
773
|
+
} as AgentPartDraft as AgentPart
|
|
774
|
+
yield { type: 'text', text: 'Bye' } as AgentPartDraft as AgentPart
|
|
762
775
|
},
|
|
763
776
|
}
|
|
764
777
|
|
|
@@ -50,11 +50,12 @@
|
|
|
50
50
|
* single attempt.
|
|
51
51
|
*/
|
|
52
52
|
import { describe, expect, test } from 'bun:test'
|
|
53
|
+
import type { JSX } from 'react'
|
|
53
54
|
import { Activity, StrictMode, useState } from 'react'
|
|
54
55
|
import { act, render, renderHook, waitFor } from '@testing-library/react'
|
|
55
56
|
import { useAgentThreadRuns } from './use-agent-thread-runs'
|
|
56
57
|
import type { AgentThread, ThreadsStore } from './thread'
|
|
57
|
-
import type { AgentTransport } from './transport'
|
|
58
|
+
import type { AgentTransport, ResumableAgentTransport } from './transport'
|
|
58
59
|
import type { AgentPart } from './parts'
|
|
59
60
|
import type { ChatMessage } from './history'
|
|
60
61
|
import type { AgentOutcome } from './outcome'
|
|
@@ -134,6 +135,11 @@ function createTestThreadsStore(initial: AgentThread<AgentPart>[] = []): Threads
|
|
|
134
135
|
threads = []
|
|
135
136
|
activeId = null
|
|
136
137
|
},
|
|
138
|
+
// Always-hydrated, never-erroring — mirrors the localStorage-backed store's real values
|
|
139
|
+
// (see ThreadsStore.hydrated/.error doc comments); this double is a synchronous in-memory
|
|
140
|
+
// stand-in with no async load path to fail.
|
|
141
|
+
hydrated: true,
|
|
142
|
+
error: undefined,
|
|
137
143
|
}
|
|
138
144
|
}
|
|
139
145
|
|
|
@@ -199,7 +205,7 @@ describe('useAgentThreadRuns — F3 mount-reconcile / unmount-cleanup wedge', ()
|
|
|
199
205
|
const userMessage: ChatMessage<AgentPart> = {
|
|
200
206
|
id: crypto.randomUUID(),
|
|
201
207
|
role: 'user',
|
|
202
|
-
parts: [{ type: 'text', text: 'hello' }],
|
|
208
|
+
parts: [{ id: 'seed-user-part', type: 'text', text: 'hello' }],
|
|
203
209
|
createdAt: Date.now(),
|
|
204
210
|
}
|
|
205
211
|
const thread = makeThread({
|
|
@@ -210,11 +216,11 @@ describe('useAgentThreadRuns — F3 mount-reconcile / unmount-cleanup wedge', ()
|
|
|
210
216
|
const store = createTestThreadsStore([thread])
|
|
211
217
|
|
|
212
218
|
let resumeCalls = 0
|
|
213
|
-
const transport = {
|
|
219
|
+
const transport: ResumableAgentTransport<AgentPart, string> = {
|
|
214
220
|
async *stream() {},
|
|
215
221
|
async *resume() {
|
|
216
222
|
resumeCalls++
|
|
217
|
-
yield { type: 'text', text: 'resumed' }
|
|
223
|
+
yield { id: 'p1', type: 'text', text: 'resumed' }
|
|
218
224
|
},
|
|
219
225
|
idempotentReplay: true as const,
|
|
220
226
|
}
|
|
@@ -235,7 +241,7 @@ describe('useAgentThreadRuns — F3 mount-reconcile / unmount-cleanup wedge', ()
|
|
|
235
241
|
const userMessage: ChatMessage<AgentPart> = {
|
|
236
242
|
id: crypto.randomUUID(),
|
|
237
243
|
role: 'user',
|
|
238
|
-
parts: [{ type: 'text', text: 'hello' }],
|
|
244
|
+
parts: [{ id: 'seed-user-part', type: 'text', text: 'hello' }],
|
|
239
245
|
createdAt: Date.now(),
|
|
240
246
|
}
|
|
241
247
|
const thread = makeThread({
|
|
@@ -251,12 +257,12 @@ describe('useAgentThreadRuns — F3 mount-reconcile / unmount-cleanup wedge', ()
|
|
|
251
257
|
const gate = deferred<void>()
|
|
252
258
|
|
|
253
259
|
let resumeCalls = 0
|
|
254
|
-
const transport = {
|
|
260
|
+
const transport: ResumableAgentTransport<AgentPart, string> = {
|
|
255
261
|
async *stream() {},
|
|
256
262
|
async *resume() {
|
|
257
263
|
resumeCalls++
|
|
258
264
|
await gate.promise
|
|
259
|
-
yield { type: 'text', text: 'resumed' }
|
|
265
|
+
yield { id: 'p1', type: 'text', text: 'resumed' }
|
|
260
266
|
},
|
|
261
267
|
idempotentReplay: true as const,
|
|
262
268
|
}
|