experimental-a2 0.8.0 → 0.9.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 (182) hide show
  1. package/AGENTS.md +11 -0
  2. package/CHANGELOG.md +36 -0
  3. package/README.md +29 -0
  4. package/dist/actor-client.d.ts +46 -0
  5. package/dist/actor-client.d.ts.map +1 -0
  6. package/dist/actor-client.js +54 -0
  7. package/dist/actor-client.js.map +1 -0
  8. package/dist/actor-react.d.ts +54 -0
  9. package/dist/actor-react.d.ts.map +1 -0
  10. package/dist/actor-react.js +79 -0
  11. package/dist/actor-react.js.map +1 -0
  12. package/dist/actor-shared-BACubf4x.d.ts +136 -0
  13. package/dist/actor-shared-BACubf4x.d.ts.map +1 -0
  14. package/dist/actor-shared-DI7J5upy.js +127 -0
  15. package/dist/actor-shared-DI7J5upy.js.map +1 -0
  16. package/dist/actor.browser.d.ts +1 -0
  17. package/dist/actor.browser.js +13 -0
  18. package/dist/actor.browser.js.map +1 -0
  19. package/dist/actor.d.ts +176 -0
  20. package/dist/actor.d.ts.map +1 -0
  21. package/dist/actor.js +437 -0
  22. package/dist/actor.js.map +1 -0
  23. package/dist/ai-server.d.ts +2 -2
  24. package/dist/ai-server.js +2 -2
  25. package/dist/ai.d.ts +2 -2
  26. package/dist/client.d.ts +1 -1
  27. package/dist/client.d.ts.map +1 -1
  28. package/dist/client.js +4 -4
  29. package/dist/client.js.map +1 -1
  30. package/dist/{errors-BQuJpe82.js → errors-DCk6ch5n.js} +16 -2
  31. package/dist/{errors-BQuJpe82.js.map → errors-DCk6ch5n.js.map} +1 -1
  32. package/dist/{idempotent-replay-DuqEkYA7.js → idempotent-replay-DVOlyYbx.js} +2 -2
  33. package/dist/{idempotent-replay-DuqEkYA7.js.map → idempotent-replay-DVOlyYbx.js.map} +1 -1
  34. package/dist/index.d.ts +16 -3
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +2 -2
  37. package/dist/react.d.ts +1 -1
  38. package/dist/{contract-jIfaR085.d.ts → reducer-DJKWm3cp.d.ts} +39 -39
  39. package/dist/reducer-DJKWm3cp.d.ts.map +1 -0
  40. package/dist/scheduler-qstash.d.ts +2 -2
  41. package/dist/scheduler-qstash.js +2 -2
  42. package/dist/scheduler-vercel.d.ts +2 -2
  43. package/dist/scheduler-vercel.js +1 -1
  44. package/dist/{server-B2XNevQA.js → server-CBET-jSz.js} +6 -6
  45. package/dist/server-CBET-jSz.js.map +1 -0
  46. package/dist/{server-DjPhHnbI.d.ts → server-CKY3_lbw.d.ts} +3 -3
  47. package/dist/{server-DjPhHnbI.d.ts.map → server-CKY3_lbw.d.ts.map} +1 -1
  48. package/dist/server.d.ts +3 -3
  49. package/dist/server.js +1 -1
  50. package/dist/{store-RJO35BMj.d.ts → store-DGHeBtIQ.d.ts} +2 -2
  51. package/dist/{store-RJO35BMj.d.ts.map → store-DGHeBtIQ.d.ts.map} +1 -1
  52. package/dist/store-memory.d.ts +1 -1
  53. package/dist/store-memory.js +2 -2
  54. package/dist/store-postgres.d.ts +1 -1
  55. package/dist/store-postgres.js +2 -2
  56. package/dist/{store-redis-core-DT01r4GZ.js → store-redis-core-z-ykbyMg.js} +3 -3
  57. package/dist/{store-redis-core-DT01r4GZ.js.map → store-redis-core-z-ykbyMg.js.map} +1 -1
  58. package/dist/store-redis-http.d.ts +1 -1
  59. package/dist/store-redis-http.js +2 -2
  60. package/dist/store-redis.d.ts +1 -1
  61. package/dist/store-redis.js +2 -2
  62. package/dist/store-sqlite.d.ts +1 -1
  63. package/dist/store-sqlite.js +2 -2
  64. package/dist/{wire-B6te_wns.js → wire--yji6mO3.js} +2 -2
  65. package/dist/{wire-B6te_wns.js.map → wire--yji6mO3.js.map} +1 -1
  66. package/docs/actors/01-introduction.mdx +189 -0
  67. package/docs/actors/02-concurrency.mdx +154 -0
  68. package/docs/actors/03-timers.mdx +120 -0
  69. package/docs/actors/04-routes.mdx +352 -0
  70. package/docs/actors/meta.ts +1 -0
  71. package/docs/concepts/meta.ts +1 -0
  72. package/docs/guides/07-examples.mdx +56 -0
  73. package/docs/guides/meta.ts +1 -0
  74. package/docs/index.mdx +16 -0
  75. package/docs/reference/02-errors.mdx +33 -0
  76. package/docs/reference/meta.ts +1 -0
  77. package/examples/README.md +15 -0
  78. package/examples/playground/AGENTS.md +11 -0
  79. package/examples/playground/DEPLOY.md +106 -0
  80. package/examples/playground/README.md +19 -0
  81. package/examples/playground/activity-feed.test.ts +10 -0
  82. package/examples/playground/app/agent/[agentId]/agent-client.tsx +376 -0
  83. package/examples/playground/app/agent/[agentId]/page.tsx +29 -0
  84. package/examples/playground/app/agent/events/route.ts +4 -0
  85. package/examples/playground/app/agent/model.ts +3 -0
  86. package/examples/playground/app/agent/new-agent-session.tsx +98 -0
  87. package/examples/playground/app/agent/page.tsx +25 -0
  88. package/examples/playground/app/agent/scheduler/route.ts +5 -0
  89. package/examples/playground/app/agent/server.ts +153 -0
  90. package/examples/playground/app/agent/session.ts +13 -0
  91. package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +682 -0
  92. package/examples/playground/app/canvas/[canvasId]/canvas-replay.test.ts +68 -0
  93. package/examples/playground/app/canvas/[canvasId]/canvas-replay.ts +19 -0
  94. package/examples/playground/app/canvas/[canvasId]/page.tsx +22 -0
  95. package/examples/playground/app/canvas/[canvasId]/session.ts +19 -0
  96. package/examples/playground/app/canvas/events/route.ts +13 -0
  97. package/examples/playground/app/canvas/model.ts +94 -0
  98. package/examples/playground/app/canvas/open-canvas.tsx +40 -0
  99. package/examples/playground/app/canvas/page.tsx +20 -0
  100. package/examples/playground/app/canvas/server.ts +9 -0
  101. package/examples/playground/app/chat/[chatId]/agent-stream-drawer.test.tsx +118 -0
  102. package/examples/playground/app/chat/[chatId]/agent-stream-drawer.tsx +316 -0
  103. package/examples/playground/app/chat/[chatId]/chat-client.tsx +922 -0
  104. package/examples/playground/app/chat/[chatId]/chat-view.test.ts +152 -0
  105. package/examples/playground/app/chat/[chatId]/chat-view.ts +101 -0
  106. package/examples/playground/app/chat/[chatId]/composer.test.ts +44 -0
  107. package/examples/playground/app/chat/[chatId]/composer.ts +30 -0
  108. package/examples/playground/app/chat/[chatId]/page.tsx +30 -0
  109. package/examples/playground/app/chat/[chatId]/session.ts +7 -0
  110. package/examples/playground/app/chat/events/route.ts +7 -0
  111. package/examples/playground/app/chat/model.test.ts +155 -0
  112. package/examples/playground/app/chat/model.ts +310 -0
  113. package/examples/playground/app/chat/new-conversation.tsx +16 -0
  114. package/examples/playground/app/chat/page.tsx +25 -0
  115. package/examples/playground/app/chat/scheduler/route.ts +5 -0
  116. package/examples/playground/app/chat/server.ts +184 -0
  117. package/examples/playground/app/components/activity-feed.tsx +54 -0
  118. package/examples/playground/app/components/connection-pill.tsx +29 -0
  119. package/examples/playground/app/counter/counter-client.tsx +72 -0
  120. package/examples/playground/app/counter/events/route.ts +4 -0
  121. package/examples/playground/app/counter/model.test.ts +36 -0
  122. package/examples/playground/app/counter/model.ts +31 -0
  123. package/examples/playground/app/counter/page.tsx +24 -0
  124. package/examples/playground/app/counter/server.ts +9 -0
  125. package/examples/playground/app/counter/session.ts +13 -0
  126. package/examples/playground/app/documents/[documentId]/code-editor.tsx +80 -0
  127. package/examples/playground/app/documents/[documentId]/document-client.tsx +525 -0
  128. package/examples/playground/app/documents/[documentId]/page.tsx +23 -0
  129. package/examples/playground/app/documents/[documentId]/session.ts +7 -0
  130. package/examples/playground/app/documents/events/route.ts +4 -0
  131. package/examples/playground/app/documents/model.ts +55 -0
  132. package/examples/playground/app/documents/open-document.tsx +40 -0
  133. package/examples/playground/app/documents/page.tsx +22 -0
  134. package/examples/playground/app/documents/server.ts +9 -0
  135. package/examples/playground/app/globals.css +2078 -0
  136. package/examples/playground/app/layout.tsx +44 -0
  137. package/examples/playground/app/orders/[orderId]/order-client.tsx +140 -0
  138. package/examples/playground/app/orders/[orderId]/page.tsx +29 -0
  139. package/examples/playground/app/orders/[orderId]/session.ts +11 -0
  140. package/examples/playground/app/orders/create/route.ts +30 -0
  141. package/examples/playground/app/orders/events/route.ts +4 -0
  142. package/examples/playground/app/orders/model.ts +79 -0
  143. package/examples/playground/app/orders/new-order-form.tsx +98 -0
  144. package/examples/playground/app/orders/page.tsx +22 -0
  145. package/examples/playground/app/orders/scheduler/route.ts +5 -0
  146. package/examples/playground/app/orders/server.ts +50 -0
  147. package/examples/playground/app/page.tsx +111 -0
  148. package/examples/playground/app/recovery/[recoveryId]/page.tsx +31 -0
  149. package/examples/playground/app/recovery/[recoveryId]/recovery-client.tsx +144 -0
  150. package/examples/playground/app/recovery/[recoveryId]/session.ts +7 -0
  151. package/examples/playground/app/recovery/events/route.ts +3 -0
  152. package/examples/playground/app/recovery/model.ts +55 -0
  153. package/examples/playground/app/recovery/new-recovery-session.tsx +20 -0
  154. package/examples/playground/app/recovery/page.tsx +22 -0
  155. package/examples/playground/app/recovery/scheduler/route.ts +7 -0
  156. package/examples/playground/app/recovery/server.ts +53 -0
  157. package/examples/playground/app/recovery/start/route.ts +41 -0
  158. package/examples/playground/app/vault/[vaultId]/route.ts +19 -0
  159. package/examples/playground/app/vault/page.tsx +12 -0
  160. package/examples/playground/app/vault/server.ts +9 -0
  161. package/examples/playground/app/vault/vault-client.tsx +124 -0
  162. package/examples/playground/app/vault/vault.test.ts +147 -0
  163. package/examples/playground/app/vault/vault.ts +119 -0
  164. package/examples/playground/css.d.ts +4 -0
  165. package/examples/playground/lib/store.ts +15 -0
  166. package/examples/playground/next-env.d.ts +5 -0
  167. package/examples/playground/next.config.ts +10 -0
  168. package/examples/playground/package.json +46 -0
  169. package/examples/playground/tsconfig.json +37 -0
  170. package/examples/playground/vercel.json +40 -0
  171. package/package.json +11 -2
  172. package/src/actor-client.ts +132 -0
  173. package/src/actor-react.ts +143 -0
  174. package/src/actor-shared.ts +356 -0
  175. package/src/actor.browser.ts +12 -0
  176. package/src/actor.ts +914 -0
  177. package/src/client.ts +9 -1
  178. package/src/errors.ts +15 -0
  179. package/src/index.ts +1 -1
  180. package/src/server.ts +13 -3
  181. package/dist/contract-jIfaR085.d.ts.map +0 -1
  182. package/dist/server-B2XNevQA.js.map +0 -1
@@ -0,0 +1,316 @@
1
+ 'use client'
2
+
3
+ import type { ReactNode } from 'react'
4
+ import { useEffect, useRef, useState } from 'react'
5
+ import type { ChatAgentMessage, ChatAgentStep } from '../model'
6
+ import type { AgentStreamSelection } from './chat-view'
7
+
8
+ const json = (value: unknown): string =>
9
+ JSON.stringify(value, null, 2) ?? String(value)
10
+
11
+ const toolStateLabel = (state: string): string => {
12
+ switch (state) {
13
+ case 'input-streaming':
14
+ return 'streaming input'
15
+ case 'input-available':
16
+ return 'running'
17
+ case 'approval-requested':
18
+ return 'awaiting approval'
19
+ case 'approval-responded':
20
+ return 'approval received'
21
+ case 'output-available':
22
+ return 'completed'
23
+ case 'output-error':
24
+ return 'failed'
25
+ case 'output-denied':
26
+ return 'denied'
27
+ default:
28
+ return state
29
+ }
30
+ }
31
+
32
+ export type AgentStreamStatus =
33
+ 'streaming' | 'completed' | 'failed' | 'interrupted'
34
+
35
+ function StreamPart({
36
+ part,
37
+ position,
38
+ }: {
39
+ part: ChatAgentMessage['parts'][number]
40
+ position: number
41
+ }): ReactNode {
42
+ if (part.type === 'step-start') {
43
+ return (
44
+ <div className="agent-stream-step" role="separator">
45
+ <span>Model step</span>
46
+ </div>
47
+ )
48
+ }
49
+
50
+ if (part.type === 'text' || part.type === 'reasoning') {
51
+ return (
52
+ <section className={`agent-stream-part ${part.type}`}>
53
+ <header>
54
+ <span>{part.type === 'reasoning' ? 'Reasoning' : 'Model text'}</span>
55
+ <span className="agent-stream-part-state">
56
+ {part.state ?? 'done'} · not posted
57
+ </span>
58
+ </header>
59
+ {part.text ? (
60
+ <p>{part.text}</p>
61
+ ) : (
62
+ <p className="hint">
63
+ {part.state === 'streaming'
64
+ ? 'Waiting for content…'
65
+ : 'No text was emitted.'}
66
+ </p>
67
+ )}
68
+ {part.providerMetadata === undefined ? null : (
69
+ <details>
70
+ <summary>Provider metadata</summary>
71
+ <pre>{json(part.providerMetadata)}</pre>
72
+ </details>
73
+ )}
74
+ </section>
75
+ )
76
+ }
77
+
78
+ if (part.type === 'tool-post') {
79
+ const output = 'output' in part ? part.output : undefined
80
+ const errorText = 'errorText' in part ? part.errorText : undefined
81
+ return (
82
+ <section className="agent-stream-part tool">
83
+ <header>
84
+ <span>
85
+ Tool <code>post</code>
86
+ </span>
87
+ <span className="agent-stream-part-state">
88
+ {toolStateLabel(part.state)}
89
+ </span>
90
+ </header>
91
+ <div className="agent-stream-value">
92
+ <span>Input</span>
93
+ <pre>{json(part.input)}</pre>
94
+ </div>
95
+ {output === undefined ? null : (
96
+ <div className="agent-stream-value">
97
+ <span>Result</span>
98
+ <pre>{json(output)}</pre>
99
+ </div>
100
+ )}
101
+ {errorText === undefined ? null : <p className="error">{errorText}</p>}
102
+ </section>
103
+ )
104
+ }
105
+
106
+ if (part.type === 'source-url') {
107
+ return (
108
+ <section className="agent-stream-part source">
109
+ <header>
110
+ <span>Source</span>
111
+ </header>
112
+ <a href={part.url} target="_blank" rel="noreferrer">
113
+ {part.title ?? part.url}
114
+ </a>
115
+ </section>
116
+ )
117
+ }
118
+
119
+ if (part.type === 'source-document') {
120
+ return (
121
+ <section className="agent-stream-part source">
122
+ <header>
123
+ <span>Document source</span>
124
+ </header>
125
+ <p>{part.title}</p>
126
+ <code>{part.filename ?? part.mediaType}</code>
127
+ </section>
128
+ )
129
+ }
130
+
131
+ if (part.type === 'file' || part.type === 'reasoning-file') {
132
+ return (
133
+ <section className="agent-stream-part source">
134
+ <header>
135
+ <span>{part.type === 'file' ? 'File' : 'Reasoning file'}</span>
136
+ </header>
137
+ <a href={part.url} target="_blank" rel="noreferrer">
138
+ {'filename' in part && part.filename ? part.filename : part.mediaType}
139
+ </a>
140
+ </section>
141
+ )
142
+ }
143
+
144
+ return (
145
+ <section className="agent-stream-part extended">
146
+ <header>
147
+ <span>{part.type}</span>
148
+ <span className="agent-stream-part-state">part {position + 1}</span>
149
+ </header>
150
+ <pre>{json(part)}</pre>
151
+ </section>
152
+ )
153
+ }
154
+
155
+ function StepMetadata({ step }: { step: ChatAgentStep }): ReactNode {
156
+ return (
157
+ <article className="agent-stream-generation">
158
+ <header>
159
+ <code>{step.model}</code>
160
+ <span>{step.finishReason}</span>
161
+ </header>
162
+ <dl>
163
+ <dt>Generation</dt>
164
+ <dd>
165
+ <code>{step.generationId}</code>
166
+ </dd>
167
+ <dt>Completed</dt>
168
+ <dd>{new Date(step.completedAt).toLocaleString()}</dd>
169
+ <dt>Tokens</dt>
170
+ <dd>{(step.usage.totalTokens ?? 0).toLocaleString()}</dd>
171
+ </dl>
172
+ <details>
173
+ <summary>Full AI SDK usage</summary>
174
+ <pre>{json(step.usage)}</pre>
175
+ </details>
176
+ </article>
177
+ )
178
+ }
179
+
180
+ export function AgentStreamDrawer({
181
+ responseMessageId,
182
+ selection,
183
+ summary,
184
+ status,
185
+ onClose,
186
+ }: {
187
+ responseMessageId: string | null
188
+ selection: AgentStreamSelection | null
189
+ summary: string | null
190
+ status: AgentStreamStatus
191
+ onClose: () => void
192
+ }): ReactNode {
193
+ const dialogRef = useRef<HTMLDialogElement>(null)
194
+ const [rawOpen, setRawOpen] = useState(false)
195
+
196
+ useEffect(() => {
197
+ const dialog = dialogRef.current
198
+ if (!dialog) return
199
+ if (responseMessageId && !dialog.open) dialog.showModal()
200
+ if (!responseMessageId && dialog.open) dialog.close()
201
+ }, [responseMessageId])
202
+
203
+ useEffect(() => setRawOpen(false), [responseMessageId])
204
+
205
+ return (
206
+ <dialog
207
+ id="agent-stream-drawer"
208
+ ref={dialogRef}
209
+ className="agent-stream-drawer"
210
+ aria-labelledby="agent-stream-title"
211
+ onCancel={(event) => {
212
+ event.preventDefault()
213
+ onClose()
214
+ }}
215
+ onKeyDown={(event) => {
216
+ if (event.key === 'Escape') {
217
+ event.preventDefault()
218
+ onClose()
219
+ }
220
+ }}
221
+ onClose={onClose}
222
+ onClick={(event) => {
223
+ if (event.target === event.currentTarget) onClose()
224
+ }}
225
+ >
226
+ <div className="agent-stream-drawer-shell">
227
+ <header className="agent-stream-drawer-header">
228
+ <div>
229
+ <p className="eyebrow">Private model output</p>
230
+ <h2 id="agent-stream-title">Agent stream</h2>
231
+ <p>{summary ?? 'Waiting for stream metadata…'}</p>
232
+ </div>
233
+ <button
234
+ type="button"
235
+ className="secondary compact agent-stream-close"
236
+ aria-label="Close agent stream"
237
+ autoFocus
238
+ onClick={onClose}
239
+ >
240
+ Close
241
+ </button>
242
+ </header>
243
+
244
+ <div className="agent-stream-drawer-body">
245
+ <div className="agent-stream-identity">
246
+ <span
247
+ className={`badge${
248
+ status === 'streaming'
249
+ ? ' live'
250
+ : status === 'failed' || status === 'interrupted'
251
+ ? ' cut'
252
+ : ' done'
253
+ }`}
254
+ >
255
+ {status}
256
+ </span>
257
+ {responseMessageId ? <code>{responseMessageId}</code> : null}
258
+ </div>
259
+
260
+ {selection === null ? (
261
+ <p className="agent-stream-empty">The stream is starting…</p>
262
+ ) : (
263
+ <>
264
+ <section className="agent-stream-section">
265
+ <h3>Ordered UI message parts</h3>
266
+ <p className="hint">
267
+ This is the complete projected stream. Only successful{' '}
268
+ <code>post</code> calls appear in the room.
269
+ </p>
270
+ <div className="agent-stream-parts">
271
+ {selection.parts.length === 0 ? (
272
+ <p className="agent-stream-empty">
273
+ No stream parts have arrived yet.
274
+ </p>
275
+ ) : (
276
+ selection.parts.map((part, position) => (
277
+ <StreamPart
278
+ key={`${responseMessageId ?? 'stream'}:${position}`}
279
+ part={part}
280
+ position={position}
281
+ />
282
+ ))
283
+ )}
284
+ </div>
285
+ </section>
286
+
287
+ <section className="agent-stream-section">
288
+ <h3>Generation metadata</h3>
289
+ {selection.metadata?.steps.length ? (
290
+ <div className="agent-stream-generations">
291
+ {selection.metadata.steps.map((step) => (
292
+ <StepMetadata key={step.generationId} step={step} />
293
+ ))}
294
+ </div>
295
+ ) : (
296
+ <p className="agent-stream-empty">
297
+ No model step has completed yet.
298
+ </p>
299
+ )}
300
+ </section>
301
+
302
+ <details
303
+ className="agent-stream-raw"
304
+ open={rawOpen}
305
+ onToggle={(event) => setRawOpen(event.currentTarget.open)}
306
+ >
307
+ <summary>Raw extended UIMessage</summary>
308
+ {rawOpen ? <pre>{json(selection.message)}</pre> : null}
309
+ </details>
310
+ </>
311
+ )}
312
+ </div>
313
+ </div>
314
+ </dialog>
315
+ )
316
+ }