experimental-a2 0.0.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 (68) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/dist/ai-server.browser.d.ts +1 -0
  3. package/dist/ai-server.browser.js +4 -0
  4. package/dist/ai-server.d.ts +65 -0
  5. package/dist/ai-server.js +494 -0
  6. package/dist/ai.d.ts +282 -0
  7. package/dist/ai.js +922 -0
  8. package/dist/cache-indexeddb.d.ts +1 -0
  9. package/dist/cache-indexeddb.js +0 -0
  10. package/dist/client.d.ts +90 -0
  11. package/dist/client.js +410 -0
  12. package/dist/contract-B0kAXoaL.js +60 -0
  13. package/dist/contract-DL8btVd9.d.ts +161 -0
  14. package/dist/devtools-server.browser.d.ts +1 -0
  15. package/dist/devtools-server.browser.js +4 -0
  16. package/dist/devtools-server.d.ts +22 -0
  17. package/dist/devtools-server.js +1087 -0
  18. package/dist/errors-BJRMd-h6.js +23 -0
  19. package/dist/errors-xL_JTXsY.d.ts +20 -0
  20. package/dist/http.d.ts +44 -0
  21. package/dist/http.js +119 -0
  22. package/dist/index.d.ts +5 -0
  23. package/dist/index.js +3 -0
  24. package/dist/inspection-E7qbD0Xj.js +10 -0
  25. package/dist/internal-Dm8Ejnud.js +36 -0
  26. package/dist/log-Dg1I8NRr.d.ts +245 -0
  27. package/dist/log-memory.d.ts +11 -0
  28. package/dist/log-memory.js +345 -0
  29. package/dist/log-polling-RO7kclzR.js +83 -0
  30. package/dist/log-postgres.d.ts +40 -0
  31. package/dist/log-postgres.js +628 -0
  32. package/dist/log-redis.d.ts +31 -0
  33. package/dist/log-redis.js +711 -0
  34. package/dist/log-sqlite.d.ts +17 -0
  35. package/dist/log-sqlite.js +450 -0
  36. package/dist/log-yJbXUf72.js +5 -0
  37. package/dist/otel.d.ts +12 -0
  38. package/dist/otel.js +41 -0
  39. package/dist/react.d.ts +54 -0
  40. package/dist/react.js +85 -0
  41. package/dist/recovery-vercel.d.ts +60 -0
  42. package/dist/recovery-vercel.js +120 -0
  43. package/dist/retryable-lazy-DZWmHpii.js +19 -0
  44. package/dist/server-DYsnKTTy.js +780 -0
  45. package/dist/server.browser.d.ts +1 -0
  46. package/dist/server.browser.js +11 -0
  47. package/dist/server.d.ts +136 -0
  48. package/dist/server.js +2 -0
  49. package/dist/telemetry-C78al20p.d.ts +32 -0
  50. package/dist/validate-XKT4FSNn.js +28 -0
  51. package/dist/wire-2QpU1EtJ.js +62 -0
  52. package/docs/01-quickstart.mdx +214 -0
  53. package/docs/concepts/01-contracts.mdx +138 -0
  54. package/docs/concepts/02-handlers.mdx +146 -0
  55. package/docs/concepts/03-durability.mdx +230 -0
  56. package/docs/concepts/04-state.mdx +133 -0
  57. package/docs/guides/01-timers.mdx +85 -0
  58. package/docs/guides/02-cancellation.mdx +107 -0
  59. package/docs/guides/03-react.mdx +234 -0
  60. package/docs/guides/04-local-first.mdx +88 -0
  61. package/docs/guides/05-production.mdx +179 -0
  62. package/docs/guides/06-ai-agents.mdx +659 -0
  63. package/docs/guides/07-devtools.mdx +101 -0
  64. package/docs/guides/08-application-data.mdx +114 -0
  65. package/docs/index.mdx +282 -0
  66. package/docs/reference/01-api.mdx +637 -0
  67. package/docs/reference/02-errors.mdx +77 -0
  68. package/package.json +111 -0
@@ -0,0 +1,494 @@
1
+ import { t as createServer } from "./server-DYsnKTTy.js";
2
+ import { ToolLoopAgent, createAgentUIStream } from "ai";
3
+ //#region src/ai-server.ts
4
+ /**
5
+ * a2/ai/server — the server-only implementation of an a2/ai definition.
6
+ *
7
+ * `createHandlers()` exposes the ordinary A2 handler table;
8
+ * `createAgentServer()` is its batteries-included assembly with createServer.
9
+ */
10
+ const resolve = async (value, context) => typeof value === "function" ? await value(context) : value;
11
+ const modelName = (model) => {
12
+ if (typeof model === "string") return model;
13
+ if ("modelId" in model && typeof model.modelId === "string") return model.modelId;
14
+ return "custom";
15
+ };
16
+ const errorMessage = (error) => error instanceof Error ? error.message : String(error);
17
+ const addTokenCounts = (left, right) => left === void 0 && right === void 0 ? void 0 : (left ?? 0) + (right ?? 0);
18
+ const addUsage = (left, right) => {
19
+ return {
20
+ inputTokens: addTokenCounts(left?.inputTokens, right.inputTokens),
21
+ inputTokenDetails: {
22
+ noCacheTokens: addTokenCounts(left?.inputTokenDetails.noCacheTokens, right.inputTokenDetails.noCacheTokens),
23
+ cacheReadTokens: addTokenCounts(left?.inputTokenDetails.cacheReadTokens, right.inputTokenDetails.cacheReadTokens),
24
+ cacheWriteTokens: addTokenCounts(left?.inputTokenDetails.cacheWriteTokens, right.inputTokenDetails.cacheWriteTokens)
25
+ },
26
+ outputTokens: addTokenCounts(left?.outputTokens, right.outputTokens),
27
+ outputTokenDetails: {
28
+ textTokens: addTokenCounts(left?.outputTokenDetails.textTokens, right.outputTokenDetails.textTokens),
29
+ reasoningTokens: addTokenCounts(left?.outputTokenDetails.reasoningTokens, right.outputTokenDetails.reasoningTokens)
30
+ },
31
+ totalTokens: addTokenCounts(left?.totalTokens, right.totalTokens)
32
+ };
33
+ };
34
+ const isBoundaryChunk = (chunk) => chunk !== void 0 && (chunk.type === "text-end" || chunk.type === "reasoning-end" || chunk.type === "tool-input-available" || chunk.type === "tool-input-error" || chunk.type === "tool-output-available" || chunk.type === "tool-output-error" || chunk.type === "tool-output-denied" || chunk.type === "tool-approval-request" || chunk.type === "finish" || chunk.type === "abort" || chunk.type === "error");
35
+ const nextOrTimer = async (next, delayMs) => {
36
+ let timer;
37
+ try {
38
+ return await Promise.race([next.then((result) => ({
39
+ type: "next",
40
+ result
41
+ })), new Promise((finishTimer) => {
42
+ timer = setTimeout(() => finishTimer({ type: "timer" }), delayMs);
43
+ timer.unref?.();
44
+ })]);
45
+ } finally {
46
+ if (timer !== void 0) clearTimeout(timer);
47
+ }
48
+ };
49
+ async function generateWithAISDK(context) {
50
+ const { onStepEnd, onStepFinish, ...settings } = context.generation;
51
+ const userOnStepEnd = onStepEnd ?? onStepFinish;
52
+ const agentSettings = {
53
+ ...settings,
54
+ id: context.generationId,
55
+ model: context.model,
56
+ tools: context.tools,
57
+ ...context.instructions === void 0 ? {} : { instructions: context.instructions }
58
+ };
59
+ const sdkAgent = new ToolLoopAgent(agentSettings);
60
+ let usage;
61
+ let finishReason;
62
+ return {
63
+ stream: await createAgentUIStream({
64
+ agent: sdkAgent,
65
+ uiMessages: context.messages,
66
+ generateMessageId: () => context.responseMessageId,
67
+ abortSignal: context.signal,
68
+ async onStepEnd(step) {
69
+ usage = addUsage(usage, step.usage);
70
+ await userOnStepEnd?.(step);
71
+ },
72
+ onEnd(event) {
73
+ finishReason = event.finishReason;
74
+ }
75
+ }),
76
+ completion: () => ({
77
+ ...finishReason === void 0 ? {} : { finishReason },
78
+ ...usage === void 0 ? {} : { usage }
79
+ })
80
+ };
81
+ }
82
+ async function* consumeGeneration(options) {
83
+ const pending = [];
84
+ let streamedFinishReason;
85
+ const maxChunks = options.progress?.maxChunks ?? 16;
86
+ const maxDelayMs = options.progress?.maxDelayMs ?? 30;
87
+ let lastFlush = Date.now();
88
+ const chunks = options.source.stream[Symbol.asyncIterator]();
89
+ let pendingChunk = chunks.next();
90
+ try {
91
+ for (;;) {
92
+ let result;
93
+ if (pending.length > 0) {
94
+ const remaining = Math.max(0, maxDelayMs - (Date.now() - lastFlush));
95
+ const outcome = await nextOrTimer(pendingChunk, remaining);
96
+ if (outcome.type === "timer") {
97
+ yield {
98
+ type: "progress",
99
+ chunks: pending.splice(0)
100
+ };
101
+ lastFlush = Date.now();
102
+ continue;
103
+ }
104
+ result = outcome.result;
105
+ } else result = await pendingChunk;
106
+ if (result.done) break;
107
+ const chunk = result.value;
108
+ pending.push(chunk);
109
+ if (chunk.type === "finish") streamedFinishReason = chunk.finishReason;
110
+ pendingChunk = chunks.next();
111
+ if (pending.length >= maxChunks || isBoundaryChunk(pending.at(-1))) {
112
+ yield {
113
+ type: "progress",
114
+ chunks: pending.splice(0)
115
+ };
116
+ lastFlush = Date.now();
117
+ }
118
+ }
119
+ } catch (error) {
120
+ if (pending.length > 0) yield {
121
+ type: "progress",
122
+ chunks: pending.splice(0)
123
+ };
124
+ throw error;
125
+ }
126
+ const completion = options.source.completion?.();
127
+ if (pending.length > 0) yield {
128
+ type: "progress",
129
+ chunks: pending.splice(0)
130
+ };
131
+ const finishReason = completion?.finishReason ?? streamedFinishReason;
132
+ yield {
133
+ type: "finish",
134
+ ...finishReason === void 0 ? {} : { finishReason },
135
+ ...completion?.usage === void 0 ? {} : { usage: completion.usage }
136
+ };
137
+ }
138
+ const replay = (definition, history) => {
139
+ let state = definition.reducer.initialState;
140
+ for (const event of history) state = definition.reducer.fold(state, event);
141
+ return state;
142
+ };
143
+ const contextMessages = (state) => {
144
+ const compaction = state.compaction;
145
+ if (compaction?.status !== "completed" || !compaction.messages) return state.messages;
146
+ const boundary = state.messages.findIndex((message) => message.id === compaction.throughMessageId);
147
+ return boundary === -1 ? state.messages : [...compaction.messages, ...state.messages.slice(boundary + 1)];
148
+ };
149
+ const lifecycleEvents = (options) => {
150
+ const result = [];
151
+ for (const [chunkIndex, chunk] of options.chunks.entries()) {
152
+ const resultId = `${options.generationId}:tool-result:${options.sequence}:${chunkIndex}`;
153
+ if (chunk.type === "tool-input-available") {
154
+ const payload = {
155
+ requestId: options.requestId,
156
+ messageId: options.messageId,
157
+ generationId: options.generationId,
158
+ toolCallId: chunk.toolCallId,
159
+ toolName: chunk.toolName,
160
+ input: chunk.input,
161
+ ...chunk.dynamic === void 0 ? {} : { dynamic: chunk.dynamic },
162
+ ...chunk.providerExecuted === void 0 ? {} : { providerExecuted: chunk.providerExecuted },
163
+ ...chunk.providerMetadata === void 0 ? {} : { providerMetadata: chunk.providerMetadata },
164
+ ...chunk.toolMetadata === void 0 ? {} : { toolMetadata: chunk.toolMetadata },
165
+ ...chunk.title === void 0 ? {} : { title: chunk.title }
166
+ };
167
+ result.push({
168
+ type: "ai.tool.called",
169
+ id: `${options.generationId}:tool:${chunk.toolCallId}:called`,
170
+ payload
171
+ });
172
+ } else if (chunk.type === "tool-input-error") {
173
+ const payload = {
174
+ requestId: options.requestId,
175
+ messageId: options.messageId,
176
+ generationId: options.generationId,
177
+ toolCallId: chunk.toolCallId,
178
+ toolName: chunk.toolName,
179
+ ...chunk.dynamic ? { input: chunk.input } : { rawInput: chunk.input },
180
+ error: chunk.errorText,
181
+ phase: "input",
182
+ ...chunk.dynamic === void 0 ? {} : { dynamic: chunk.dynamic },
183
+ ...chunk.providerExecuted === void 0 ? {} : { providerExecuted: chunk.providerExecuted },
184
+ ...chunk.providerMetadata === void 0 ? {} : { providerMetadata: chunk.providerMetadata },
185
+ ...chunk.toolMetadata === void 0 ? {} : { toolMetadata: chunk.toolMetadata }
186
+ };
187
+ result.push({
188
+ type: "ai.tool.result",
189
+ id: resultId,
190
+ payload
191
+ });
192
+ } else if (chunk.type === "tool-output-available") {
193
+ const payload = {
194
+ requestId: options.requestId,
195
+ messageId: options.messageId,
196
+ generationId: options.generationId,
197
+ toolCallId: chunk.toolCallId,
198
+ output: chunk.output,
199
+ phase: "execution",
200
+ ...chunk.preliminary === void 0 ? {} : { preliminary: chunk.preliminary },
201
+ ...chunk.dynamic === void 0 ? {} : { dynamic: chunk.dynamic },
202
+ ...chunk.providerExecuted === void 0 ? {} : { providerExecuted: chunk.providerExecuted },
203
+ ...chunk.providerMetadata === void 0 ? {} : { providerMetadata: chunk.providerMetadata },
204
+ ...chunk.toolMetadata === void 0 ? {} : { toolMetadata: chunk.toolMetadata }
205
+ };
206
+ result.push({
207
+ type: "ai.tool.result",
208
+ id: resultId,
209
+ payload
210
+ });
211
+ } else if (chunk.type === "tool-output-error") {
212
+ const payload = {
213
+ requestId: options.requestId,
214
+ messageId: options.messageId,
215
+ generationId: options.generationId,
216
+ toolCallId: chunk.toolCallId,
217
+ error: chunk.errorText,
218
+ phase: "execution",
219
+ ...chunk.dynamic === void 0 ? {} : { dynamic: chunk.dynamic },
220
+ ...chunk.providerExecuted === void 0 ? {} : { providerExecuted: chunk.providerExecuted },
221
+ ...chunk.providerMetadata === void 0 ? {} : { providerMetadata: chunk.providerMetadata },
222
+ ...chunk.toolMetadata === void 0 ? {} : { toolMetadata: chunk.toolMetadata }
223
+ };
224
+ result.push({
225
+ type: "ai.tool.result",
226
+ id: resultId,
227
+ payload
228
+ });
229
+ } else if (chunk.type === "tool-output-denied") {
230
+ const payload = {
231
+ requestId: options.requestId,
232
+ messageId: options.messageId,
233
+ generationId: options.generationId,
234
+ toolCallId: chunk.toolCallId,
235
+ denied: true,
236
+ phase: "execution"
237
+ };
238
+ result.push({
239
+ type: "ai.tool.result",
240
+ id: resultId,
241
+ payload
242
+ });
243
+ } else if (chunk.type === "tool-approval-request") {
244
+ const payload = {
245
+ messageId: options.messageId,
246
+ generationId: options.generationId,
247
+ approvalId: chunk.approvalId,
248
+ toolCallId: chunk.toolCallId,
249
+ ...chunk.isAutomatic === void 0 ? {} : { isAutomatic: chunk.isAutomatic },
250
+ ...chunk.signature === void 0 ? {} : { signature: chunk.signature }
251
+ };
252
+ result.push({
253
+ type: "ai.approval.requested",
254
+ id: `${options.generationId}:approval:${chunk.approvalId}`,
255
+ payload
256
+ });
257
+ }
258
+ }
259
+ return result;
260
+ };
261
+ /**
262
+ * Build the ordinary A2 handler table for the built-in agent protocol.
263
+ * Application handlers can be spread beside this table.
264
+ */
265
+ function createHandlers(options) {
266
+ if (options.model === void 0) throw new TypeError("createHandlers requires model");
267
+ if (options.progress?.maxChunks !== void 0 && (!Number.isInteger(options.progress.maxChunks) || options.progress.maxChunks < 1)) throw new TypeError("progress.maxChunks must be a positive integer");
268
+ if (options.progress?.maxDelayMs !== void 0 && (!Number.isFinite(options.progress.maxDelayMs) || options.progress.maxDelayMs < 0)) throw new TypeError("progress.maxDelayMs must be a non-negative number");
269
+ const generationHandler = async (ctx) => {
270
+ const history = await ctx.history();
271
+ const requestId = ctx.event.id;
272
+ const request = ctx.event.payload;
273
+ if (history.some((event) => event.type === "ai.session.closed")) return;
274
+ if (history.some((event) => {
275
+ if (event.type === "ai.generation.completed") return event.payload.requestId === requestId;
276
+ if (event.type !== "ai.generation.failed") return false;
277
+ const payload = event.payload;
278
+ return payload.requestId === requestId && payload.superseded !== true;
279
+ })) return;
280
+ const previousStarts = history.filter((event) => event.type === "ai.generation.started" && event.payload.requestId === requestId);
281
+ const attempt = previousStarts.length + 1;
282
+ const generationId = `${requestId}:generation:${attempt}`;
283
+ const responseMessageId = request.responseMessageId ?? (request.reason === "message" ? `${request.messageId}:assistant` : request.messageId);
284
+ const previous = previousStarts.at(-1);
285
+ const incompleteId = previous ? previous.payload.generationId : void 0;
286
+ const promptHistory = incompleteId === void 0 && request.reason !== "retry" ? history : history.filter((event) => !(event.type === "ai.generation.progress" && (incompleteId !== void 0 && event.payload.generationId === incompleteId || request.reason === "retry" && event.payload.responseMessageId === responseMessageId)));
287
+ let state = replay(options.agent, promptHistory);
288
+ const resolverContext = {
289
+ event: ctx.event,
290
+ state,
291
+ history,
292
+ signal: ctx.signal
293
+ };
294
+ const resolvedModel = await resolve(options.model, resolverContext);
295
+ if (resolvedModel === void 0) throw new TypeError("the model resolver returned undefined");
296
+ const started = {
297
+ requestId,
298
+ messageId: request.messageId,
299
+ generationId,
300
+ responseMessageId,
301
+ attempt,
302
+ model: modelName(resolvedModel)
303
+ };
304
+ const startEvents = [];
305
+ if (previous) {
306
+ const payload = previous.payload;
307
+ const superseded = {
308
+ requestId,
309
+ messageId: payload.messageId,
310
+ generationId: payload.generationId,
311
+ responseMessageId: payload.responseMessageId,
312
+ error: "generation attempt was superseded after an incomplete run",
313
+ superseded: true
314
+ };
315
+ startEvents.push({
316
+ type: "ai.generation.failed",
317
+ id: `${payload.generationId}:superseded`,
318
+ payload: superseded
319
+ });
320
+ }
321
+ startEvents.push({
322
+ type: "ai.generation.started",
323
+ id: generationId,
324
+ payload: started
325
+ });
326
+ await ctx.append(...startEvents);
327
+ let messages = contextMessages(state);
328
+ if (options.compaction) {
329
+ const compactionContext = {
330
+ ...resolverContext,
331
+ messages
332
+ };
333
+ if (await options.compaction.shouldCompact(compactionContext)) {
334
+ const throughMessageId = messages.at(-1)?.id ?? request.messageId;
335
+ await ctx.append({
336
+ type: "ai.compaction.requested",
337
+ id: `${generationId}:compaction:requested`,
338
+ payload: {
339
+ generationId,
340
+ throughMessageId
341
+ }
342
+ });
343
+ messages = await options.compaction.compact(compactionContext);
344
+ const completed = {
345
+ generationId,
346
+ throughMessageId,
347
+ messages
348
+ };
349
+ await ctx.append({
350
+ type: "ai.compaction.completed",
351
+ id: `${generationId}:compaction:completed`,
352
+ payload: completed
353
+ });
354
+ state = {
355
+ ...state,
356
+ compaction: {
357
+ status: "completed",
358
+ ...completed
359
+ }
360
+ };
361
+ }
362
+ }
363
+ try {
364
+ const resolvedInstructions = options.instructions === void 0 ? void 0 : await resolve(options.instructions, resolverContext);
365
+ const generateContext = {
366
+ request: ctx.event,
367
+ requestId,
368
+ generationId,
369
+ responseMessageId,
370
+ messages,
371
+ state,
372
+ history,
373
+ signal: ctx.signal,
374
+ model: resolvedModel,
375
+ tools: options.tools ?? {},
376
+ ...resolvedInstructions === void 0 ? {} : { instructions: resolvedInstructions },
377
+ generation: options.generation ?? {}
378
+ };
379
+ const updates = consumeGeneration({
380
+ source: options.generate === void 0 ? await generateWithAISDK(generateContext) : { stream: await options.generate(generateContext) },
381
+ ...options.progress === void 0 ? {} : { progress: options.progress }
382
+ });
383
+ let sequence = 0;
384
+ let finish;
385
+ for await (const update of updates) {
386
+ ctx.signal.throwIfAborted();
387
+ if (update.type === "finish") {
388
+ finish = update;
389
+ continue;
390
+ }
391
+ const progress = {
392
+ requestId,
393
+ messageId: request.messageId,
394
+ generationId,
395
+ responseMessageId,
396
+ sequence,
397
+ chunks: update.chunks
398
+ };
399
+ const extras = lifecycleEvents({
400
+ requestId,
401
+ messageId: responseMessageId,
402
+ generationId,
403
+ sequence,
404
+ chunks: update.chunks
405
+ });
406
+ await ctx.append({
407
+ type: "ai.generation.progress",
408
+ id: `${generationId}:progress:${sequence}`,
409
+ payload: progress
410
+ }, ...extras);
411
+ sequence += 1;
412
+ }
413
+ if (!finish) throw new Error("agent generation finished without output");
414
+ const completed = {
415
+ requestId,
416
+ messageId: request.messageId,
417
+ generationId,
418
+ responseMessageId,
419
+ ...finish.finishReason === void 0 ? {} : { finishReason: finish.finishReason },
420
+ ...finish.usage === void 0 ? {} : { usage: finish.usage }
421
+ };
422
+ const messageCompleted = { messageId: responseMessageId };
423
+ await ctx.append({
424
+ type: "ai.generation.completed",
425
+ id: `${generationId}:completed`,
426
+ payload: completed
427
+ }, {
428
+ type: "ai.message.completed",
429
+ id: `${generationId}:message:completed`,
430
+ payload: messageCompleted
431
+ });
432
+ } catch (error) {
433
+ if (ctx.signal.aborted) {
434
+ const interrupted = {
435
+ messageId: responseMessageId,
436
+ generationId,
437
+ reason: "aborted"
438
+ };
439
+ await ctx.append({
440
+ type: "ai.message.interrupted",
441
+ id: `${generationId}:interrupted`,
442
+ payload: interrupted
443
+ });
444
+ return;
445
+ }
446
+ const failed = {
447
+ requestId,
448
+ messageId: request.messageId,
449
+ generationId,
450
+ responseMessageId,
451
+ error: errorMessage(error)
452
+ };
453
+ await ctx.append({
454
+ type: "ai.generation.failed",
455
+ id: `${generationId}:failed`,
456
+ payload: failed
457
+ });
458
+ }
459
+ };
460
+ return { "ai.generation.requested": {
461
+ abortOn: {
462
+ "ai.message.interrupted": (event, trigger) => {
463
+ const responseMessageId = trigger.payload.responseMessageId ?? (trigger.payload.reason === "message" ? `${trigger.payload.messageId}:assistant` : trigger.payload.messageId);
464
+ return event.payload.messageId === responseMessageId;
465
+ },
466
+ "ai.session.closed": true
467
+ },
468
+ handler: generationHandler
469
+ } };
470
+ }
471
+ /** Assemble an A2 server with the built-in agent handlers and app extensions. */
472
+ function createAgentServer(options) {
473
+ const { agent: definition, model, tools, instructions, generation, generate, compaction, progress, handlers, ...serverOptions } = options;
474
+ const builtIns = createHandlers({
475
+ agent: definition,
476
+ model,
477
+ ...tools === void 0 ? {} : { tools },
478
+ ...instructions === void 0 ? {} : { instructions },
479
+ ...generation === void 0 ? {} : { generation },
480
+ ...generate === void 0 ? {} : { generate },
481
+ ...compaction === void 0 ? {} : { compaction },
482
+ ...progress === void 0 ? {} : { progress }
483
+ });
484
+ return createServer({
485
+ ...serverOptions,
486
+ contract: definition.contract,
487
+ handlers: {
488
+ ...builtIns,
489
+ ...handlers
490
+ }
491
+ });
492
+ }
493
+ //#endregion
494
+ export { createAgentServer, createHandlers };