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.
Files changed (237) hide show
  1. package/AGENTS.md +21 -21
  2. package/CHANGELOG.md +15 -0
  3. package/README.md +36 -27
  4. package/agent/rules/basalt-content.md +16 -3
  5. package/dist/agent/adapter.d.ts +146 -0
  6. package/dist/agent/adapter.d.ts.map +1 -0
  7. package/dist/agent/adapter.js +473 -0
  8. package/dist/agent/adapter.test.d.ts +2 -0
  9. package/dist/agent/adapter.test.d.ts.map +1 -0
  10. package/dist/agent/ai-sdk-transport.test.d.ts +2 -0
  11. package/dist/agent/ai-sdk-transport.test.d.ts.map +1 -0
  12. package/dist/agent/coalesce.d.ts +20 -4
  13. package/dist/agent/coalesce.d.ts.map +1 -1
  14. package/dist/agent/coalesce.js +76 -8
  15. package/dist/agent/coalesce.test.d.ts +2 -0
  16. package/dist/agent/coalesce.test.d.ts.map +1 -0
  17. package/dist/agent/foreign.test.d.ts +2 -0
  18. package/dist/agent/foreign.test.d.ts.map +1 -0
  19. package/dist/agent/id.d.ts +30 -0
  20. package/dist/agent/id.d.ts.map +1 -1
  21. package/dist/agent/id.js +16 -0
  22. package/dist/agent/id.test.d.ts +2 -0
  23. package/dist/agent/id.test.d.ts.map +1 -0
  24. package/dist/agent/index.d.ts +2 -0
  25. package/dist/agent/index.d.ts.map +1 -1
  26. package/dist/agent/index.js +3 -0
  27. package/dist/agent/merge.d.ts.map +1 -1
  28. package/dist/agent/merge.js +19 -7
  29. package/dist/agent/merge.test.d.ts +2 -0
  30. package/dist/agent/merge.test.d.ts.map +1 -0
  31. package/dist/agent/part-list.d.ts +49 -34
  32. package/dist/agent/part-list.d.ts.map +1 -1
  33. package/dist/agent/part-list.js +42 -6
  34. package/dist/agent/part-list.test.d.ts +2 -0
  35. package/dist/agent/part-list.test.d.ts.map +1 -0
  36. package/dist/agent/parts.d.ts +46 -10
  37. package/dist/agent/parts.d.ts.map +1 -1
  38. package/dist/agent/parts.js +16 -6
  39. package/dist/agent/parts.test.d.ts +2 -0
  40. package/dist/agent/parts.test.d.ts.map +1 -0
  41. package/dist/agent/thread.d.ts +14 -0
  42. package/dist/agent/thread.d.ts.map +1 -1
  43. package/dist/agent/thread.js +8 -2
  44. package/dist/agent/thread.test.d.ts +2 -0
  45. package/dist/agent/thread.test.d.ts.map +1 -0
  46. package/dist/agent/transport.test.d.ts +2 -0
  47. package/dist/agent/transport.test.d.ts.map +1 -0
  48. package/dist/agent/use-agent-stream.test.d.ts +2 -0
  49. package/dist/agent/use-agent-stream.test.d.ts.map +1 -0
  50. package/dist/agent/use-agent-thread-runs.foreign.test.d.ts +2 -0
  51. package/dist/agent/use-agent-thread-runs.foreign.test.d.ts.map +1 -0
  52. package/dist/agent/use-agent-thread-runs.resume.test.d.ts +2 -0
  53. package/dist/agent/use-agent-thread-runs.resume.test.d.ts.map +1 -0
  54. package/dist/agent/use-agent-thread-runs.test.d.ts +2 -0
  55. package/dist/agent/use-agent-thread-runs.test.d.ts.map +1 -0
  56. package/dist/agent/use-agent-thread-runs.wedge.test.d.ts +2 -0
  57. package/dist/agent/use-agent-thread-runs.wedge.test.d.ts.map +1 -0
  58. package/dist/agent-chat/composer.d.ts +130 -8
  59. package/dist/agent-chat/composer.d.ts.map +1 -1
  60. package/dist/agent-chat/composer.js +189 -23
  61. package/dist/agent-chat/composer.test.d.ts +2 -0
  62. package/dist/agent-chat/composer.test.d.ts.map +1 -0
  63. package/dist/agent-chat/index.d.ts +1 -1
  64. package/dist/agent-chat/index.d.ts.map +1 -1
  65. package/dist/agent-chat/thread-detail-panel.d.ts.map +1 -1
  66. package/dist/agent-chat/thread-detail-panel.js +1 -1
  67. package/dist/agent-chat/thread-message.d.ts.map +1 -1
  68. package/dist/agent-chat/thread-message.js +14 -3
  69. package/dist/agent-chat/thread-message.test.d.ts +2 -0
  70. package/dist/agent-chat/thread-message.test.d.ts.map +1 -0
  71. package/dist/agent-chat/thread-workspace.js +1 -1
  72. package/dist/agent-chat/tool-chip.test.d.ts +2 -0
  73. package/dist/agent-chat/tool-chip.test.d.ts.map +1 -0
  74. package/dist/charts/primitives/ChartFrame.test.d.ts +2 -0
  75. package/dist/charts/primitives/ChartFrame.test.d.ts.map +1 -0
  76. package/dist/charts/utils/domain.test.d.ts +2 -0
  77. package/dist/charts/utils/domain.test.d.ts.map +1 -0
  78. package/dist/cli/check-theme.test.d.ts +2 -0
  79. package/dist/cli/check-theme.test.d.ts.map +1 -0
  80. package/dist/cli/help.test.d.ts +2 -0
  81. package/dist/cli/help.test.d.ts.map +1 -0
  82. package/dist/cli/index.d.ts.map +1 -1
  83. package/dist/cli/init-sync.test.d.ts +2 -0
  84. package/dist/cli/init-sync.test.d.ts.map +1 -0
  85. package/dist/cli/placement-engine.test.d.ts +2 -0
  86. package/dist/cli/placement-engine.test.d.ts.map +1 -0
  87. package/dist/cli/tarball-parity.test.d.ts +2 -0
  88. package/dist/cli/tarball-parity.test.d.ts.map +1 -0
  89. package/dist/cli/template-format.test.d.ts +2 -0
  90. package/dist/cli/template-format.test.d.ts.map +1 -0
  91. package/dist/cli/template-ledger.test.d.ts +2 -0
  92. package/dist/cli/template-ledger.test.d.ts.map +1 -0
  93. package/dist/cli/tokens-css.test.d.ts +2 -0
  94. package/dist/cli/tokens-css.test.d.ts.map +1 -0
  95. package/dist/content/article-actions.test.d.ts +2 -0
  96. package/dist/content/article-actions.test.d.ts.map +1 -0
  97. package/dist/content/article-model.test.d.ts +2 -0
  98. package/dist/content/article-model.test.d.ts.map +1 -0
  99. package/dist/content/block-split.test.d.ts +2 -0
  100. package/dist/content/block-split.test.d.ts.map +1 -0
  101. package/dist/content/fence-block.d.ts +37 -10
  102. package/dist/content/fence-block.d.ts.map +1 -1
  103. package/dist/content/fence-block.js +80 -14
  104. package/dist/content/heading-components.d.ts.map +1 -1
  105. package/dist/content/heading-components.js +7 -4
  106. package/dist/content/heading-components.test.d.ts +2 -0
  107. package/dist/content/heading-components.test.d.ts.map +1 -0
  108. package/dist/content/index.d.ts +6 -3
  109. package/dist/content/index.d.ts.map +1 -1
  110. package/dist/content/index.js +5 -1
  111. package/dist/content/markdown.d.ts +101 -14
  112. package/dist/content/markdown.d.ts.map +1 -1
  113. package/dist/content/markdown.js +141 -28
  114. package/dist/content/markdown.test.d.ts +2 -0
  115. package/dist/content/markdown.test.d.ts.map +1 -0
  116. package/dist/content/prose.module.css.test.d.ts +2 -0
  117. package/dist/content/prose.module.css.test.d.ts.map +1 -0
  118. package/dist/content/sanitize.d.ts +170 -0
  119. package/dist/content/sanitize.d.ts.map +1 -0
  120. package/dist/content/sanitize.js +178 -0
  121. package/dist/content/sanitize.test.d.ts +2 -0
  122. package/dist/content/sanitize.test.d.ts.map +1 -0
  123. package/dist/content/slug.test.d.ts +2 -0
  124. package/dist/content/slug.test.d.ts.map +1 -0
  125. package/dist/dashboard/stat-card.test.d.ts +2 -0
  126. package/dist/dashboard/stat-card.test.d.ts.map +1 -0
  127. package/dist/guard/check-source.test.d.ts +2 -0
  128. package/dist/guard/check-source.test.d.ts.map +1 -0
  129. package/dist/guard/guard-hook.test.d.ts +2 -0
  130. package/dist/guard/guard-hook.test.d.ts.map +1 -0
  131. package/dist/index.d.ts +3 -3
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +9 -1
  134. package/dist/provider/index.test.d.ts +2 -0
  135. package/dist/provider/index.test.d.ts.map +1 -0
  136. package/dist/provider/lab-theme.test.d.ts +2 -0
  137. package/dist/provider/lab-theme.test.d.ts.map +1 -0
  138. package/dist/router-tanstack/multi-search-param-store.test.d.ts +2 -0
  139. package/dist/router-tanstack/multi-search-param-store.test.d.ts.map +1 -0
  140. package/dist/styles.floor.test.d.ts +2 -0
  141. package/dist/styles.floor.test.d.ts.map +1 -0
  142. package/dist/surfaces.d.ts +4 -4
  143. package/dist/surfaces.d.ts.map +1 -1
  144. package/dist/surfaces.js +12 -3
  145. package/dist/theme/border-coverage.test.d.ts +18 -0
  146. package/dist/theme/border-coverage.test.d.ts.map +1 -0
  147. package/dist/theme/contrast.test.d.ts +2 -0
  148. package/dist/theme/contrast.test.d.ts.map +1 -0
  149. package/dist/theme/density-option.test.d.ts +2 -0
  150. package/dist/theme/density-option.test.d.ts.map +1 -0
  151. package/dist/theme/density-relations.test.d.ts +2 -0
  152. package/dist/theme/density-relations.test.d.ts.map +1 -0
  153. package/dist/theme/derive-theme.test.d.ts +2 -0
  154. package/dist/theme/derive-theme.test.d.ts.map +1 -0
  155. package/dist/theme/fonts-option.test.d.ts +2 -0
  156. package/dist/theme/fonts-option.test.d.ts.map +1 -0
  157. package/dist/theme/radius-option.test.d.ts +2 -0
  158. package/dist/theme/radius-option.test.d.ts.map +1 -0
  159. package/dist/theme/radius.test.d.ts +2 -0
  160. package/dist/theme/radius.test.d.ts.map +1 -0
  161. package/dist/theme/shadow-surfaces.test.d.ts +26 -0
  162. package/dist/theme/shadow-surfaces.test.d.ts.map +1 -0
  163. package/dist/theme/spacing.test.d.ts +2 -0
  164. package/dist/theme/spacing.test.d.ts.map +1 -0
  165. package/dist/theme/use-basalt-spacing.test.d.ts +2 -0
  166. package/dist/theme/use-basalt-spacing.test.d.ts.map +1 -0
  167. package/dist/theme-lab/derive-controls.test.d.ts +2 -0
  168. package/dist/theme-lab/derive-controls.test.d.ts.map +1 -0
  169. package/dist/theme-lab/derive-state.test.d.ts +2 -0
  170. package/dist/theme-lab/derive-state.test.d.ts.map +1 -0
  171. package/dist/theme-lab/theme-lab.test.d.ts +2 -0
  172. package/dist/theme-lab/theme-lab.test.d.ts.map +1 -0
  173. package/dist/tokens/build-fonts-css.test.d.ts +2 -0
  174. package/dist/tokens/build-fonts-css.test.d.ts.map +1 -0
  175. package/dist/tokens/build-radius-css.test.d.ts +2 -0
  176. package/dist/tokens/build-radius-css.test.d.ts.map +1 -0
  177. package/dist/tokens/density.test.d.ts +2 -0
  178. package/dist/tokens/density.test.d.ts.map +1 -0
  179. package/dist/tokens/derive-radius.test.d.ts +2 -0
  180. package/dist/tokens/derive-radius.test.d.ts.map +1 -0
  181. package/dist/tokens/derive.test.d.ts +2 -0
  182. package/dist/tokens/derive.test.d.ts.map +1 -0
  183. package/dist/tokens/palette.test.d.ts +2 -0
  184. package/dist/tokens/palette.test.d.ts.map +1 -0
  185. package/dist/vite-color-mix.test.d.ts +2 -0
  186. package/dist/vite-color-mix.test.d.ts.map +1 -0
  187. package/dist/vite.test.d.ts +2 -0
  188. package/dist/vite.test.d.ts.map +1 -0
  189. package/llms.txt +6 -6
  190. package/package.json +6 -1
  191. package/src/agent/adapter.test.ts +1403 -0
  192. package/src/agent/adapter.ts +887 -0
  193. package/src/agent/ai-sdk-transport.test.ts +53 -26
  194. package/src/agent/coalesce.test.ts +202 -9
  195. package/src/agent/coalesce.ts +126 -15
  196. package/src/agent/foreign.test.ts +5 -1
  197. package/src/agent/id.test.ts +6 -2
  198. package/src/agent/id.ts +48 -0
  199. package/src/agent/index.ts +8 -0
  200. package/src/agent/merge.test.ts +87 -0
  201. package/src/agent/merge.ts +57 -10
  202. package/src/agent/part-list.test.tsx +31 -1
  203. package/src/agent/part-list.tsx +77 -29
  204. package/src/agent/parts.test.ts +121 -4
  205. package/src/agent/parts.ts +78 -17
  206. package/src/agent/thread.test.ts +75 -2
  207. package/src/agent/thread.ts +21 -1
  208. package/src/agent/use-agent-stream.test.tsx +9 -5
  209. package/src/agent/use-agent-thread-runs.foreign.test.tsx +5 -0
  210. package/src/agent/use-agent-thread-runs.resume.test.tsx +16 -11
  211. package/src/agent/use-agent-thread-runs.test.tsx +30 -17
  212. package/src/agent/use-agent-thread-runs.wedge.test.tsx +13 -7
  213. package/src/agent-chat/composer.test.tsx +924 -0
  214. package/src/agent-chat/composer.tsx +521 -52
  215. package/src/agent-chat/index.ts +1 -1
  216. package/src/agent-chat/thread-detail-panel.tsx +3 -1
  217. package/src/agent-chat/thread-message.test.tsx +141 -1
  218. package/src/agent-chat/thread-message.tsx +29 -4
  219. package/src/agent-chat/thread-workspace.tsx +1 -1
  220. package/src/cli/index.ts +0 -1
  221. package/src/cli/template-format.test.ts +2 -2
  222. package/src/content/fence-block.tsx +242 -15
  223. package/src/content/heading-components.test.tsx +65 -0
  224. package/src/content/heading-components.tsx +26 -5
  225. package/src/content/index.ts +19 -3
  226. package/src/content/markdown.test.tsx +603 -0
  227. package/src/content/markdown.tsx +355 -35
  228. package/src/content/sanitize.test.ts +659 -0
  229. package/src/content/sanitize.ts +510 -0
  230. package/src/dashboard/stat-card.test.tsx +6 -1
  231. package/src/index.ts +13 -1
  232. package/src/surfaces.ts +12 -3
  233. package/src/theme/contrast.test.ts +1 -4
  234. package/src/theme/density-relations.test.ts +4 -2
  235. package/src/theme/fonts-option.test.ts +7 -1
  236. package/src/theme/shadow-surfaces.test.ts +12 -6
  237. 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
  }