@ekairos/events 1.22.39-beta.development.0 → 1.22.40-beta.development.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/README.md +5 -3
- package/dist/codex.d.ts +11 -2
- package/dist/codex.js +13 -5
- package/dist/context.action.d.ts +55 -0
- package/dist/context.action.js +25 -0
- package/dist/context.builder.d.ts +52 -42
- package/dist/context.builder.js +29 -24
- package/dist/context.d.ts +2 -1
- package/dist/context.engine.d.ts +50 -47
- package/dist/context.engine.js +222 -173
- package/dist/context.events.js +28 -87
- package/dist/context.js +1 -0
- package/dist/context.part-identity.d.ts +40 -0
- package/dist/context.part-identity.js +268 -0
- package/dist/context.parts.d.ts +389 -164
- package/dist/context.parts.js +235 -224
- package/dist/context.registry.d.ts +1 -1
- package/dist/context.runtime.d.ts +10 -4
- package/dist/context.runtime.js +7 -1
- package/dist/context.step-stream.d.ts +16 -2
- package/dist/context.step-stream.js +58 -16
- package/dist/context.stream.d.ts +4 -0
- package/dist/context.stream.js +23 -1
- package/dist/context.toolcalls.d.ts +8 -20
- package/dist/context.toolcalls.js +61 -55
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -3
- package/dist/reactors/ai-sdk.chunk-map.js +27 -0
- package/dist/reactors/ai-sdk.reactor.d.ts +8 -9
- package/dist/reactors/ai-sdk.reactor.js +2 -5
- package/dist/reactors/ai-sdk.step.d.ts +2 -3
- package/dist/reactors/ai-sdk.step.js +10 -7
- package/dist/reactors/scripted.reactor.d.ts +7 -4
- package/dist/reactors/types.d.ts +8 -8
- package/dist/schema.d.ts +273 -2
- package/dist/schema.js +1 -1
- package/dist/steps/store.steps.d.ts +51 -12
- package/dist/steps/store.steps.js +137 -0
- package/dist/steps/stream.steps.d.ts +15 -0
- package/dist/steps/stream.steps.js +16 -5
- package/dist/steps/trace.steps.d.ts +4 -4
- package/dist/steps/trace.steps.js +21 -6
- package/dist/tools-to-model-tools.d.ts +4 -2
- package/dist/tools-to-model-tools.js +30 -11
- package/package.json +7 -6
package/dist/context.engine.js
CHANGED
|
@@ -2,38 +2,18 @@ import { getContextRuntimeServices } from "./context.runtime.js";
|
|
|
2
2
|
import { OUTPUT_ITEM_TYPE, WEB_CHANNEL } from "./context.events.js";
|
|
3
3
|
import { applyToolExecutionResultToParts } from "./context.toolcalls.js";
|
|
4
4
|
import { isContextPartEnvelope, normalizePartsForPersistence, } from "./context.parts.js";
|
|
5
|
-
import { actionsToActionSpecs } from "./tools-to-model-tools.js";
|
|
6
5
|
import { createAiSdkReactor, } from "./context.reactor.js";
|
|
7
|
-
import { abortPersistedContextStepStream,
|
|
8
|
-
import { completeExecution, createContextStep, getContextItems, initializeContext, saveTriggerAndCreateExecution, saveContextPartsStep, updateContextContent, updateContextReactor, updateContextStatus, updateItem, updateContextStep, } from "./steps/store.steps.js";
|
|
6
|
+
import { abortPersistedContextStepStream, closeContextStream, createPersistedContextStepStreamForRuntime, finalizePersistedContextStepStreamForRuntime, } from "./steps/stream.steps.js";
|
|
7
|
+
import { completeExecution, createContextStep, finalizeReactionStep, getContextItems, initializeContext, openReactionStep, saveTriggerAndCreateExecution, saveContextPartsAndUpdateReaction, saveContextPartsStep, updateContextContent, updateContextReactor, updateContextStatus, updateItem, updateContextStep, } from "./steps/store.steps.js";
|
|
9
8
|
import { getClientResumeHookUrl, toolApprovalHookToken, toolApprovalWebhookToken, } from "./context.hooks.js";
|
|
10
9
|
import { getContextDurableWorkflow } from "./context.durable.js";
|
|
11
10
|
export async function runContextReactionDirect(context, triggerEvent, params) {
|
|
12
11
|
return await ContextEngine.runDirect(context, triggerEvent, params);
|
|
13
12
|
}
|
|
14
|
-
async function legacyRuntimeFromEnv(env) {
|
|
15
|
-
const { getContextRuntime } = await import("./runtime.step.js");
|
|
16
|
-
const legacy = (await getContextRuntime(env));
|
|
17
|
-
return {
|
|
18
|
-
env,
|
|
19
|
-
db: async () => legacy.db,
|
|
20
|
-
resolve: async () => ({
|
|
21
|
-
db: legacy.db,
|
|
22
|
-
meta: () => ({
|
|
23
|
-
domain: legacy.domain,
|
|
24
|
-
}),
|
|
25
|
-
}),
|
|
26
|
-
meta: () => ({
|
|
27
|
-
domain: legacy.domain,
|
|
28
|
-
}),
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
13
|
async function resolveReactRuntime(params) {
|
|
32
14
|
if (params.runtime)
|
|
33
15
|
return params.runtime;
|
|
34
|
-
|
|
35
|
-
return await legacyRuntimeFromEnv(params.env);
|
|
36
|
-
throw new Error("ContextEngine.react requires either runtime or env.");
|
|
16
|
+
throw new Error("ContextEngine.react requires runtime.");
|
|
37
17
|
}
|
|
38
18
|
export { toolApprovalHookToken, toolApprovalWebhookToken, getClientResumeHookUrl };
|
|
39
19
|
function nowIso() {
|
|
@@ -48,13 +28,21 @@ function summarizePartPreview(part) {
|
|
|
48
28
|
if (!part || typeof part !== "object")
|
|
49
29
|
return {};
|
|
50
30
|
if (isContextPartEnvelope(part)) {
|
|
51
|
-
const preview = part.
|
|
52
|
-
? part.content[0]
|
|
53
|
-
:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
31
|
+
const preview = part.type === "message"
|
|
32
|
+
? part.content.text ?? JSON.stringify(part.content.blocks?.[0] ?? part)
|
|
33
|
+
: part.type === "reasoning"
|
|
34
|
+
? part.content.text
|
|
35
|
+
: part.type === "source"
|
|
36
|
+
? JSON.stringify(part.content.sources[0] ?? part)
|
|
37
|
+
: part.content.status === "failed"
|
|
38
|
+
? part.content.error.message
|
|
39
|
+
: JSON.stringify(part.content);
|
|
40
|
+
const state = part.type === "reasoning"
|
|
41
|
+
? part.content.state
|
|
42
|
+
: part.type === "action"
|
|
43
|
+
? part.content.status
|
|
44
|
+
: undefined;
|
|
45
|
+
const toolCallId = part.type === "action" ? part.content.actionCallId : undefined;
|
|
58
46
|
return {
|
|
59
47
|
partPreview: preview ? clipPreview(preview) : undefined,
|
|
60
48
|
partState: state,
|
|
@@ -233,6 +221,31 @@ async function createRuntimeOps(runtimeHandle, benchmark) {
|
|
|
233
221
|
},
|
|
234
222
|
};
|
|
235
223
|
},
|
|
224
|
+
openReactionStep: async ({ contextIdentifier, content, executionId, iteration }) => {
|
|
225
|
+
const stepId = makeRuntimeId();
|
|
226
|
+
const now = new Date();
|
|
227
|
+
await instrumentedDb.transact([
|
|
228
|
+
instrumentedDb.tx.event_steps[stepId].create({
|
|
229
|
+
createdAt: now,
|
|
230
|
+
updatedAt: now,
|
|
231
|
+
status: "running",
|
|
232
|
+
iteration,
|
|
233
|
+
}),
|
|
234
|
+
instrumentedDb.tx.event_steps[stepId].link({ execution: executionId }),
|
|
235
|
+
]);
|
|
236
|
+
const stream = await createPersistedContextStepStreamForRuntime({ db: instrumentedDb }, {
|
|
237
|
+
executionId,
|
|
238
|
+
stepId,
|
|
239
|
+
});
|
|
240
|
+
const context = await store.updateContextContent(contextIdentifier, content);
|
|
241
|
+
const events = await store.getItems(contextIdentifier);
|
|
242
|
+
return {
|
|
243
|
+
stepId,
|
|
244
|
+
stream,
|
|
245
|
+
context,
|
|
246
|
+
events,
|
|
247
|
+
};
|
|
248
|
+
},
|
|
236
249
|
createContextStep: async ({ executionId, iteration }) => {
|
|
237
250
|
const stepId = makeRuntimeId();
|
|
238
251
|
await instrumentedDb.transact([
|
|
@@ -254,9 +267,48 @@ async function createRuntimeOps(runtimeHandle, benchmark) {
|
|
|
254
267
|
}),
|
|
255
268
|
]);
|
|
256
269
|
},
|
|
270
|
+
finalizeReactionStep: async (params) => {
|
|
271
|
+
if (params.session) {
|
|
272
|
+
await finalizePersistedContextStepStreamForRuntime({
|
|
273
|
+
runtime: { db: instrumentedDb },
|
|
274
|
+
session: params.session,
|
|
275
|
+
mode: "close",
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
await instrumentedDb.transact([
|
|
279
|
+
instrumentedDb.tx.event_steps[params.stepId].update({
|
|
280
|
+
...params.patch,
|
|
281
|
+
updatedAt: new Date(),
|
|
282
|
+
}),
|
|
283
|
+
]);
|
|
284
|
+
if (!params.reactionEventId || !params.reactionEvent) {
|
|
285
|
+
return {};
|
|
286
|
+
}
|
|
287
|
+
await instrumentedDb.transact([
|
|
288
|
+
instrumentedDb.tx.event_items[params.reactionEventId].update(params.reactionEvent),
|
|
289
|
+
]);
|
|
290
|
+
return {
|
|
291
|
+
reactionEvent: {
|
|
292
|
+
...params.reactionEvent,
|
|
293
|
+
id: params.reactionEventId,
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
},
|
|
257
297
|
saveContextPartsStep: async (params) => {
|
|
258
298
|
await store.saveStepParts({ stepId: params.stepId, parts: params.parts });
|
|
259
299
|
},
|
|
300
|
+
saveContextPartsAndUpdateReaction: async (params) => {
|
|
301
|
+
await store.saveStepParts({ stepId: params.stepId, parts: params.parts });
|
|
302
|
+
await instrumentedDb.transact([
|
|
303
|
+
instrumentedDb.tx.event_items[params.reactionEventId].update(params.reactionEvent),
|
|
304
|
+
]);
|
|
305
|
+
return {
|
|
306
|
+
reactionEvent: {
|
|
307
|
+
...params.reactionEvent,
|
|
308
|
+
id: params.reactionEventId,
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
},
|
|
260
312
|
getItems: async (contextIdentifier) => await store.getItems(contextIdentifier),
|
|
261
313
|
updateItem: async (itemId, item) => {
|
|
262
314
|
await instrumentedDb.transact([instrumentedDb.tx.event_items[itemId].update(item)]);
|
|
@@ -288,9 +340,12 @@ async function createWorkflowOps(runtime) {
|
|
|
288
340
|
updateContextReactor: async (contextIdentifier, reactor) => await updateContextReactor({ runtime, contextIdentifier, reactor }),
|
|
289
341
|
updateContextStatus: async (contextIdentifier, status) => await updateContextStatus({ runtime, contextIdentifier, status }),
|
|
290
342
|
saveTriggerAndCreateExecution: async ({ contextIdentifier, triggerEvent }) => await saveTriggerAndCreateExecution({ runtime, contextIdentifier, triggerEvent }),
|
|
343
|
+
openReactionStep: async (params) => await openReactionStep({ runtime, ...params }),
|
|
291
344
|
createContextStep: async ({ executionId, iteration }) => await createContextStep({ runtime, executionId, iteration }),
|
|
292
345
|
updateContextStep: async (params) => await updateContextStep({ runtime, ...params }),
|
|
346
|
+
finalizeReactionStep: async (params) => await finalizeReactionStep({ runtime, ...params }),
|
|
293
347
|
saveContextPartsStep: async (params) => await saveContextPartsStep({ runtime, ...params }),
|
|
348
|
+
saveContextPartsAndUpdateReaction: async (params) => await saveContextPartsAndUpdateReaction({ runtime, ...params }),
|
|
294
349
|
getItems: async (contextIdentifier) => await getContextItems({ runtime, contextIdentifier }),
|
|
295
350
|
updateItem: async (itemId, item, opts) => await updateItem({ runtime, eventId: itemId, event: item, opts }),
|
|
296
351
|
completeExecution: async (contextIdentifier, executionId, status) => await completeExecution({ runtime, contextIdentifier, executionId, status }),
|
|
@@ -307,9 +362,11 @@ async function getContextEngineOps(runtime, benchmark) {
|
|
|
307
362
|
export class ContextEngine {
|
|
308
363
|
constructor(opts = {}, reactor) {
|
|
309
364
|
this.opts = opts;
|
|
310
|
-
this.reactor =
|
|
365
|
+
this.reactor =
|
|
366
|
+
reactor ??
|
|
367
|
+
createAiSdkReactor();
|
|
311
368
|
}
|
|
312
|
-
async buildSkills(_context, _env) {
|
|
369
|
+
async buildSkills(_context, _env, _runtime) {
|
|
313
370
|
return [];
|
|
314
371
|
}
|
|
315
372
|
/**
|
|
@@ -329,13 +386,13 @@ export class ContextEngine {
|
|
|
329
386
|
* the builder) so results are durable and replay-safe.
|
|
330
387
|
* - If it’s pure/deterministic, it can run in workflow context.
|
|
331
388
|
*/
|
|
332
|
-
async expandEvents(events, _context, _env) {
|
|
389
|
+
async expandEvents(events, _context, _env, _runtime) {
|
|
333
390
|
return events;
|
|
334
391
|
}
|
|
335
|
-
getModel(_context, _env) {
|
|
392
|
+
getModel(_context, _env, _runtime) {
|
|
336
393
|
return "openai/gpt-5";
|
|
337
394
|
}
|
|
338
|
-
getReactor(_context, _env) {
|
|
395
|
+
getReactor(_context, _env, _runtime) {
|
|
339
396
|
return this.reactor;
|
|
340
397
|
}
|
|
341
398
|
/**
|
|
@@ -350,10 +407,10 @@ export class ContextEngine {
|
|
|
350
407
|
return true;
|
|
351
408
|
}
|
|
352
409
|
async react(triggerEvent, params) {
|
|
353
|
-
if (params.durable) {
|
|
354
|
-
return await ContextEngine.
|
|
410
|
+
if (params.durable === false) {
|
|
411
|
+
return await ContextEngine.runDirect(this, triggerEvent, params);
|
|
355
412
|
}
|
|
356
|
-
return await ContextEngine.
|
|
413
|
+
return await ContextEngine.startDurable(this, triggerEvent, params);
|
|
357
414
|
}
|
|
358
415
|
static async prepareExecutionShell(story, triggerEvent, params) {
|
|
359
416
|
const runtimeHandle = await resolveReactRuntime(params);
|
|
@@ -364,7 +421,11 @@ export class ContextEngine {
|
|
|
364
421
|
let currentContext = ctxResult.context;
|
|
365
422
|
const contextSelector = { id: String(currentContext.id) };
|
|
366
423
|
if (ctxResult.isNew) {
|
|
367
|
-
await story.opts.onContextCreated?.({
|
|
424
|
+
await story.opts.onContextCreated?.({
|
|
425
|
+
env,
|
|
426
|
+
runtime: runtimeHandle,
|
|
427
|
+
context: currentContext,
|
|
428
|
+
});
|
|
368
429
|
}
|
|
369
430
|
if (currentContext.status === "closed") {
|
|
370
431
|
await measureBenchmark(params.__benchmark, "react.reopenClosedContextMs", async () => await ops.updateContextStatus(contextSelector, "open_idle"));
|
|
@@ -376,6 +437,7 @@ export class ContextEngine {
|
|
|
376
437
|
}));
|
|
377
438
|
currentContext = { ...currentContext, status: "open_streaming" };
|
|
378
439
|
return {
|
|
440
|
+
runtimeHandle,
|
|
379
441
|
contextSelector,
|
|
380
442
|
currentContext,
|
|
381
443
|
trigger: shell.triggerEvent,
|
|
@@ -400,10 +462,10 @@ export class ContextEngine {
|
|
|
400
462
|
const shell = await ContextEngine.prepareExecutionShell(story, triggerEvent, params);
|
|
401
463
|
let run;
|
|
402
464
|
try {
|
|
403
|
-
const [{ start }] = await Promise.all([
|
|
465
|
+
const [{ start }] = await measureBenchmark(params.__benchmark, "react.durable.importWorkflowApiMs", async () => await Promise.all([
|
|
404
466
|
import("workflow/api"),
|
|
405
|
-
]);
|
|
406
|
-
const startedRun = await start(workflow, [
|
|
467
|
+
]));
|
|
468
|
+
const startedRun = await measureBenchmark(params.__benchmark, "react.durable.startWorkflowMs", async () => await start(workflow, [
|
|
407
469
|
{
|
|
408
470
|
contextKey,
|
|
409
471
|
runtime: runtimeHandle,
|
|
@@ -423,19 +485,19 @@ export class ContextEngine {
|
|
|
423
485
|
execution: shell.execution,
|
|
424
486
|
},
|
|
425
487
|
},
|
|
426
|
-
]);
|
|
488
|
+
]));
|
|
427
489
|
run = {
|
|
428
490
|
runId: String(startedRun.runId),
|
|
429
491
|
status: startedRun.status,
|
|
430
492
|
returnValue: startedRun.returnValue,
|
|
431
493
|
};
|
|
432
|
-
const runtime = await createRuntimeOps(runtimeHandle);
|
|
433
|
-
await runtime.db.transact([
|
|
494
|
+
const runtime = await measureBenchmark(params.__benchmark, "react.durable.resolveRuntimeOpsMs", async () => await createRuntimeOps(runtimeHandle, params.__benchmark));
|
|
495
|
+
await measureBenchmark(params.__benchmark, "react.durable.persistWorkflowRunIdMs", async () => await runtime.db.transact([
|
|
434
496
|
runtime.db.tx.event_executions[shell.execution.id].update({
|
|
435
497
|
workflowRunId: startedRun.runId,
|
|
436
498
|
updatedAt: new Date(),
|
|
437
499
|
}),
|
|
438
|
-
]);
|
|
500
|
+
]));
|
|
439
501
|
}
|
|
440
502
|
catch (error) {
|
|
441
503
|
const ops = await getContextEngineOps(runtimeHandle, params.__benchmark);
|
|
@@ -451,6 +513,26 @@ export class ContextEngine {
|
|
|
451
513
|
};
|
|
452
514
|
}
|
|
453
515
|
static async runDirect(story, triggerEvent, params) {
|
|
516
|
+
if (!params.__bootstrap) {
|
|
517
|
+
const shell = await ContextEngine.prepareExecutionShell(story, triggerEvent, params);
|
|
518
|
+
const run = ContextEngine.runDirect(story, triggerEvent, {
|
|
519
|
+
...params,
|
|
520
|
+
runtime: shell.runtimeHandle,
|
|
521
|
+
__bootstrap: {
|
|
522
|
+
contextId: shell.currentContext.id,
|
|
523
|
+
trigger: shell.trigger,
|
|
524
|
+
reaction: shell.reaction,
|
|
525
|
+
execution: shell.execution,
|
|
526
|
+
},
|
|
527
|
+
});
|
|
528
|
+
return {
|
|
529
|
+
context: shell.currentContext,
|
|
530
|
+
trigger: shell.trigger,
|
|
531
|
+
reaction: shell.reaction,
|
|
532
|
+
execution: shell.execution,
|
|
533
|
+
run,
|
|
534
|
+
};
|
|
535
|
+
}
|
|
454
536
|
const runtimeHandle = await resolveReactRuntime(params);
|
|
455
537
|
const env = runtimeHandle.env;
|
|
456
538
|
const ops = await measureBenchmark(params.__benchmark, "react.resolveOpsMs", async () => await getContextEngineOps(runtimeHandle, params.__benchmark));
|
|
@@ -520,18 +602,19 @@ export class ContextEngine {
|
|
|
520
602
|
};
|
|
521
603
|
try {
|
|
522
604
|
for (let iter = 0; iter < maxIterations; iter++) {
|
|
523
|
-
// Create a persisted step per iteration (IDs generated in step runtime for replay safety)
|
|
524
605
|
const stagePrefix = `react.iteration.${iter}`;
|
|
525
|
-
|
|
606
|
+
// Hook: Context DSL `context()` (implemented by subclasses via `initialize()`)
|
|
607
|
+
const nextContent = await measureBenchmark(params.__benchmark, `${stagePrefix}.contextMs`, async () => await story.initialize(updatedContext, env, runtimeHandle));
|
|
608
|
+
const openedStep = await measureBenchmark(params.__benchmark, `${stagePrefix}.openReactionStepMs`, async () => await ops.openReactionStep({
|
|
609
|
+
contextIdentifier: activeContextSelector,
|
|
610
|
+
content: nextContent,
|
|
526
611
|
executionId,
|
|
527
612
|
iteration: iter,
|
|
528
613
|
}));
|
|
529
|
-
currentStepId =
|
|
530
|
-
currentStepStream =
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
stepId: stepCreate.stepId,
|
|
534
|
-
});
|
|
614
|
+
currentStepId = openedStep.stepId;
|
|
615
|
+
currentStepStream = openedStep.stream;
|
|
616
|
+
updatedContext = openedStep.context;
|
|
617
|
+
const rawEvents = openedStep.events;
|
|
535
618
|
await emitContextEvents({
|
|
536
619
|
silent,
|
|
537
620
|
writable,
|
|
@@ -539,20 +622,11 @@ export class ContextEngine {
|
|
|
539
622
|
{
|
|
540
623
|
type: "step.created",
|
|
541
624
|
at: nowIso(),
|
|
542
|
-
stepId: String(
|
|
625
|
+
stepId: String(openedStep.stepId),
|
|
543
626
|
executionId,
|
|
544
627
|
iteration: iter,
|
|
545
628
|
status: "running",
|
|
546
629
|
},
|
|
547
|
-
],
|
|
548
|
-
});
|
|
549
|
-
// Hook: Context DSL `context()` (implemented by subclasses via `initialize()`)
|
|
550
|
-
const nextContent = await measureBenchmark(params.__benchmark, `${stagePrefix}.contextMs`, async () => await story.initialize(updatedContext, env));
|
|
551
|
-
updatedContext = await measureBenchmark(params.__benchmark, `${stagePrefix}.persistContextMs`, async () => await ops.updateContextContent(activeContextSelector, nextContent));
|
|
552
|
-
await emitContextEvents({
|
|
553
|
-
silent,
|
|
554
|
-
writable,
|
|
555
|
-
events: [
|
|
556
630
|
{
|
|
557
631
|
type: "context.content_updated",
|
|
558
632
|
at: nowIso(),
|
|
@@ -560,17 +634,17 @@ export class ContextEngine {
|
|
|
560
634
|
},
|
|
561
635
|
],
|
|
562
636
|
});
|
|
563
|
-
await story.opts.onContextUpdated?.({
|
|
637
|
+
await story.opts.onContextUpdated?.({
|
|
638
|
+
env,
|
|
639
|
+
runtime: runtimeHandle,
|
|
640
|
+
context: updatedContext,
|
|
641
|
+
});
|
|
564
642
|
// Hook: Context DSL `narrative()` (implemented by subclasses via `buildSystemPrompt()`)
|
|
565
|
-
const systemPrompt = await measureBenchmark(params.__benchmark, `${stagePrefix}.narrativeMs`, async () => await story.buildSystemPrompt(updatedContext, env));
|
|
643
|
+
const systemPrompt = await measureBenchmark(params.__benchmark, `${stagePrefix}.narrativeMs`, async () => await story.buildSystemPrompt(updatedContext, env, runtimeHandle));
|
|
566
644
|
// Hook: Context DSL `actions()` (implemented by subclasses via `buildTools()`)
|
|
567
|
-
const toolsAll = await measureBenchmark(params.__benchmark, `${stagePrefix}.actionsMs`, async () => await story.buildTools(updatedContext, env));
|
|
568
|
-
const skillsAll = await measureBenchmark(params.__benchmark, `${stagePrefix}.skillsMs`, async () => await story.buildSkills(updatedContext, env));
|
|
569
|
-
const
|
|
570
|
-
const expandedEvents = await measureBenchmark(params.__benchmark, `${stagePrefix}.expandEventsMs`, async () => await story.expandEvents(rawEvents, updatedContext, env));
|
|
571
|
-
// IMPORTANT: step args must be serializable.
|
|
572
|
-
// Match DurableAgent behavior: convert tool input schemas to plain JSON Schema in workflow context.
|
|
573
|
-
const actionSpecs = actionsToActionSpecs(toolsAll);
|
|
645
|
+
const toolsAll = await measureBenchmark(params.__benchmark, `${stagePrefix}.actionsMs`, async () => await story.buildTools(updatedContext, env, runtimeHandle));
|
|
646
|
+
const skillsAll = await measureBenchmark(params.__benchmark, `${stagePrefix}.skillsMs`, async () => await story.buildSkills(updatedContext, env, runtimeHandle));
|
|
647
|
+
const expandedEvents = await measureBenchmark(params.__benchmark, `${stagePrefix}.expandEventsMs`, async () => await story.expandEvents(rawEvents, updatedContext, env, runtimeHandle));
|
|
574
648
|
// Execute model reaction for this iteration using the stable reaction event id.
|
|
575
649
|
//
|
|
576
650
|
// IMPORTANT:
|
|
@@ -578,7 +652,7 @@ export class ContextEngine {
|
|
|
578
652
|
// If we stream with a per-step id, the UI will render an optimistic assistant message
|
|
579
653
|
// (step id) and then a second persisted assistant message (reaction id) with the same
|
|
580
654
|
// content once InstantDB updates.
|
|
581
|
-
const reactor = story.getReactor(updatedContext, env);
|
|
655
|
+
const reactor = story.getReactor(updatedContext, env, runtimeHandle);
|
|
582
656
|
const reactionPartsBeforeStep = Array.isArray(reactionEvent.content?.parts)
|
|
583
657
|
? [...reactionEvent.content.parts]
|
|
584
658
|
: [];
|
|
@@ -589,38 +663,38 @@ export class ContextEngine {
|
|
|
589
663
|
if (nextSignature === persistedReactionPartsSignature)
|
|
590
664
|
return;
|
|
591
665
|
persistedReactionPartsSignature = nextSignature;
|
|
592
|
-
await ops.
|
|
593
|
-
stepId:
|
|
666
|
+
const saved = await ops.saveContextPartsAndUpdateReaction({
|
|
667
|
+
stepId: openedStep.stepId,
|
|
594
668
|
parts: normalizedParts,
|
|
669
|
+
reactionEventId: reactionEvent.id,
|
|
670
|
+
reactionEvent: {
|
|
671
|
+
...reactionEvent,
|
|
672
|
+
content: {
|
|
673
|
+
...reactionEvent.content,
|
|
674
|
+
parts: [...reactionPartsBeforeStep, ...normalizedParts],
|
|
675
|
+
},
|
|
676
|
+
status: "pending",
|
|
677
|
+
},
|
|
595
678
|
executionId,
|
|
596
679
|
contextId: String(currentContext.id),
|
|
597
680
|
iteration: iter,
|
|
598
681
|
});
|
|
599
|
-
reactionEvent =
|
|
600
|
-
...reactionEvent,
|
|
601
|
-
content: {
|
|
602
|
-
...reactionEvent.content,
|
|
603
|
-
parts: [...reactionPartsBeforeStep, ...normalizedParts],
|
|
604
|
-
},
|
|
605
|
-
status: "pending",
|
|
606
|
-
}, { executionId, contextId: String(currentContext.id) });
|
|
682
|
+
reactionEvent = saved.reactionEvent;
|
|
607
683
|
};
|
|
608
684
|
const reactionResult = await measureBenchmark(params.__benchmark, `${stagePrefix}.reactorMs`, async () => await reactor({
|
|
609
685
|
runtime: runtimeHandle,
|
|
610
|
-
env,
|
|
611
686
|
context: updatedContext,
|
|
612
687
|
contextIdentifier: activeContextSelector,
|
|
613
688
|
events: expandedEvents,
|
|
614
689
|
triggerEvent,
|
|
615
|
-
model: story.getModel(updatedContext, env),
|
|
690
|
+
model: story.getModel(updatedContext, env, runtimeHandle),
|
|
616
691
|
systemPrompt,
|
|
617
692
|
actions: toolsAll,
|
|
618
|
-
actionSpecs,
|
|
619
693
|
skills: skillsAll,
|
|
620
694
|
eventId: reactionEventId,
|
|
621
695
|
executionId,
|
|
622
696
|
contextId: String(currentContext.id),
|
|
623
|
-
stepId: String(
|
|
697
|
+
stepId: String(openedStep.stepId),
|
|
624
698
|
iteration: iter,
|
|
625
699
|
maxModelSteps,
|
|
626
700
|
// Only emit a `start` chunk once per story turn.
|
|
@@ -659,21 +733,35 @@ export class ContextEngine {
|
|
|
659
733
|
parts: stepParts,
|
|
660
734
|
},
|
|
661
735
|
};
|
|
662
|
-
|
|
663
|
-
|
|
736
|
+
const nextAssistantParts = Array.isArray(assistantEventEffective.content?.parts)
|
|
737
|
+
? assistantEventEffective.content.parts
|
|
738
|
+
: [];
|
|
739
|
+
const nextReactionEvent = {
|
|
740
|
+
...reactionEvent,
|
|
741
|
+
content: {
|
|
742
|
+
...reactionEvent.content,
|
|
743
|
+
parts: [...reactionPartsBeforeStep, ...nextAssistantParts],
|
|
744
|
+
},
|
|
745
|
+
status: "pending",
|
|
746
|
+
};
|
|
747
|
+
const appendedReactorOutput = await measureBenchmark(params.__benchmark, `${stagePrefix}.appendReactorOutputMs`, async () => await ops.saveContextPartsAndUpdateReaction({
|
|
748
|
+
stepId: openedStep.stepId,
|
|
664
749
|
parts: stepParts,
|
|
750
|
+
reactionEventId: reactionEvent.id,
|
|
751
|
+
reactionEvent: nextReactionEvent,
|
|
665
752
|
executionId,
|
|
666
753
|
contextId: String(currentContext.id),
|
|
667
754
|
iteration: iter,
|
|
668
755
|
}));
|
|
756
|
+
reactionEvent = appendedReactorOutput.reactionEvent;
|
|
669
757
|
await emitContextEvents({
|
|
670
758
|
silent,
|
|
671
759
|
writable,
|
|
672
760
|
events: stepParts.map((part, idx) => ({
|
|
673
761
|
type: "part.created",
|
|
674
762
|
at: nowIso(),
|
|
675
|
-
partKey: `${String(
|
|
676
|
-
stepId: String(
|
|
763
|
+
partKey: `${String(openedStep.stepId)}:${idx}`,
|
|
764
|
+
stepId: String(openedStep.stepId),
|
|
677
765
|
idx,
|
|
678
766
|
partType: part && typeof part.type === "string"
|
|
679
767
|
? String(part.type)
|
|
@@ -681,19 +769,6 @@ export class ContextEngine {
|
|
|
681
769
|
...summarizePartPreview(part),
|
|
682
770
|
})),
|
|
683
771
|
});
|
|
684
|
-
// Persist/append the aggregated reaction event (stable `reactionEventId` for the execution).
|
|
685
|
-
const nextAssistantParts = Array.isArray(assistantEventEffective.content?.parts)
|
|
686
|
-
? assistantEventEffective.content.parts
|
|
687
|
-
: [];
|
|
688
|
-
const nextReactionEvent = {
|
|
689
|
-
...reactionEvent,
|
|
690
|
-
content: {
|
|
691
|
-
...reactionEvent.content,
|
|
692
|
-
parts: [...reactionPartsBeforeStep, ...nextAssistantParts],
|
|
693
|
-
},
|
|
694
|
-
status: "pending",
|
|
695
|
-
};
|
|
696
|
-
reactionEvent = await measureBenchmark(params.__benchmark, `${stagePrefix}.persistAssistantReactionMs`, async () => await ops.updateItem(reactionEvent.id, nextReactionEvent, { executionId, contextId: String(currentContext.id) }));
|
|
697
772
|
if (reactionResult.reactor?.kind) {
|
|
698
773
|
updatedContext = await measureBenchmark(params.__benchmark, `${stagePrefix}.persistReactorStateMs`, async () => await ops.updateContextReactor(activeContextSelector, {
|
|
699
774
|
kind: reactionResult.reactor.kind,
|
|
@@ -703,32 +778,8 @@ export class ContextEngine {
|
|
|
703
778
|
},
|
|
704
779
|
}));
|
|
705
780
|
}
|
|
706
|
-
if (currentStepStream) {
|
|
707
|
-
await closePersistedContextStepStream({
|
|
708
|
-
runtime: runtimeHandle,
|
|
709
|
-
session: currentStepStream,
|
|
710
|
-
});
|
|
711
|
-
currentStepStream = null;
|
|
712
|
-
}
|
|
713
781
|
story.opts.onEventCreated?.(assistantEventEffective);
|
|
714
782
|
const firstActionRequest = actionRequests?.[0];
|
|
715
|
-
await measureBenchmark(params.__benchmark, `${stagePrefix}.markStepRunningMs`, async () => await ops.updateContextStep({
|
|
716
|
-
stepId: stepCreate.stepId,
|
|
717
|
-
patch: firstActionRequest
|
|
718
|
-
? {
|
|
719
|
-
kind: "action_execute",
|
|
720
|
-
actionName: typeof firstActionRequest.actionName === "string"
|
|
721
|
-
? firstActionRequest.actionName
|
|
722
|
-
: undefined,
|
|
723
|
-
actionInput: firstActionRequest.input,
|
|
724
|
-
}
|
|
725
|
-
: {
|
|
726
|
-
kind: "message",
|
|
727
|
-
},
|
|
728
|
-
executionId,
|
|
729
|
-
contextId: String(currentContext.id),
|
|
730
|
-
iteration: iter,
|
|
731
|
-
}));
|
|
732
783
|
await emitContextEvents({
|
|
733
784
|
silent,
|
|
734
785
|
writable,
|
|
@@ -736,7 +787,7 @@ export class ContextEngine {
|
|
|
736
787
|
{
|
|
737
788
|
type: "step.updated",
|
|
738
789
|
at: nowIso(),
|
|
739
|
-
stepId: String(
|
|
790
|
+
stepId: String(openedStep.stepId),
|
|
740
791
|
executionId,
|
|
741
792
|
iteration: iter,
|
|
742
793
|
status: "running",
|
|
@@ -751,9 +802,13 @@ export class ContextEngine {
|
|
|
751
802
|
if (!actionRequests.length) {
|
|
752
803
|
const endResult = await story.callOnEnd(assistantEventEffective);
|
|
753
804
|
if (endResult) {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
805
|
+
const completedReactionEvent = {
|
|
806
|
+
...reactionEvent,
|
|
807
|
+
status: "completed",
|
|
808
|
+
};
|
|
809
|
+
const finalized = await measureBenchmark(params.__benchmark, `${stagePrefix}.finalizeReactionStepMs`, async () => await ops.finalizeReactionStep({
|
|
810
|
+
session: currentStepStream,
|
|
811
|
+
stepId: openedStep.stepId,
|
|
757
812
|
patch: {
|
|
758
813
|
status: "completed",
|
|
759
814
|
kind: "message",
|
|
@@ -761,10 +816,14 @@ export class ContextEngine {
|
|
|
761
816
|
actionResults: [],
|
|
762
817
|
continueLoop: false,
|
|
763
818
|
},
|
|
819
|
+
reactionEventId,
|
|
820
|
+
reactionEvent: completedReactionEvent,
|
|
764
821
|
executionId,
|
|
765
822
|
contextId: String(currentContext.id),
|
|
766
823
|
iteration: iter,
|
|
767
824
|
}));
|
|
825
|
+
currentStepStream = null;
|
|
826
|
+
reactionEvent = finalized.reactionEvent ?? completedReactionEvent;
|
|
768
827
|
await emitContextEvents({
|
|
769
828
|
silent,
|
|
770
829
|
writable,
|
|
@@ -772,7 +831,7 @@ export class ContextEngine {
|
|
|
772
831
|
{
|
|
773
832
|
type: "step.updated",
|
|
774
833
|
at: nowIso(),
|
|
775
|
-
stepId: String(
|
|
834
|
+
stepId: String(openedStep.stepId),
|
|
776
835
|
executionId,
|
|
777
836
|
iteration: iter,
|
|
778
837
|
status: "completed",
|
|
@@ -781,18 +840,13 @@ export class ContextEngine {
|
|
|
781
840
|
{
|
|
782
841
|
type: "step.completed",
|
|
783
842
|
at: nowIso(),
|
|
784
|
-
stepId: String(
|
|
843
|
+
stepId: String(openedStep.stepId),
|
|
785
844
|
executionId,
|
|
786
845
|
iteration: iter,
|
|
787
846
|
status: "completed",
|
|
788
847
|
},
|
|
789
848
|
],
|
|
790
849
|
});
|
|
791
|
-
// Mark reaction event completed
|
|
792
|
-
await measureBenchmark(params.__benchmark, `${stagePrefix}.completeReactionMs`, async () => await ops.updateItem(reactionEventId, {
|
|
793
|
-
...reactionEvent,
|
|
794
|
-
status: "completed",
|
|
795
|
-
}, { executionId, contextId: String(currentContext.id) }));
|
|
796
850
|
await emitContextEvents({
|
|
797
851
|
silent,
|
|
798
852
|
writable,
|
|
@@ -832,10 +886,6 @@ export class ContextEngine {
|
|
|
832
886
|
if (!silent) {
|
|
833
887
|
await closeContextStream({ preventClose, sendFinish, writable });
|
|
834
888
|
}
|
|
835
|
-
reactionEvent = {
|
|
836
|
-
...reactionEvent,
|
|
837
|
-
status: "completed",
|
|
838
|
-
};
|
|
839
889
|
return {
|
|
840
890
|
context: updatedContext,
|
|
841
891
|
trigger,
|
|
@@ -887,7 +937,6 @@ export class ContextEngine {
|
|
|
887
937
|
const executeAction = toolDef.execute;
|
|
888
938
|
const output = await Reflect.apply(executeAction, undefined, [actionInput, {
|
|
889
939
|
runtime: runtimeHandle,
|
|
890
|
-
env,
|
|
891
940
|
context: updatedContext,
|
|
892
941
|
contextIdentifier: activeContextSelector,
|
|
893
942
|
toolCallId: actionRequest.actionRef,
|
|
@@ -896,8 +945,9 @@ export class ContextEngine {
|
|
|
896
945
|
executionId,
|
|
897
946
|
triggerEventId,
|
|
898
947
|
contextId: currentContext.id,
|
|
899
|
-
stepId: String(
|
|
948
|
+
stepId: String(openedStep.stepId),
|
|
900
949
|
iteration: iter,
|
|
950
|
+
contextStepStream: currentStepStream?.stream,
|
|
901
951
|
}]);
|
|
902
952
|
return { actionRequest, success: true, output };
|
|
903
953
|
}
|
|
@@ -923,7 +973,7 @@ export class ContextEngine {
|
|
|
923
973
|
});
|
|
924
974
|
}
|
|
925
975
|
await measureBenchmark(params.__benchmark, `${stagePrefix}.saveFinalStepPartsMs`, async () => await ops.saveContextPartsStep({
|
|
926
|
-
stepId:
|
|
976
|
+
stepId: openedStep.stepId,
|
|
927
977
|
parts: finalizedStepParts,
|
|
928
978
|
executionId,
|
|
929
979
|
contextId: String(currentContext.id),
|
|
@@ -955,36 +1005,47 @@ export class ContextEngine {
|
|
|
955
1005
|
// so stories can inspect `reactionEvent.content.parts` deterministically.
|
|
956
1006
|
const continueLoop = await measureBenchmark(params.__benchmark, `${stagePrefix}.shouldContinueMs`, async () => await story.shouldContinue({
|
|
957
1007
|
env,
|
|
1008
|
+
runtime: runtimeHandle,
|
|
958
1009
|
context: updatedContext,
|
|
959
1010
|
reactionEvent,
|
|
960
1011
|
assistantEvent: assistantEventEffective,
|
|
961
1012
|
actionRequests,
|
|
962
1013
|
actionResults: actionResults,
|
|
963
1014
|
}));
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1015
|
+
const firstActionResult = actionResults?.[0];
|
|
1016
|
+
const finalizedReactionStatus = continueLoop === false ? "completed" : "pending";
|
|
1017
|
+
const finalizedReactionEvent = {
|
|
1018
|
+
...reactionEvent,
|
|
1019
|
+
status: finalizedReactionStatus,
|
|
1020
|
+
};
|
|
1021
|
+
const finalizedStep = await measureBenchmark(params.__benchmark, `${stagePrefix}.finalizeReactionStepMs`, async () => await ops.finalizeReactionStep({
|
|
1022
|
+
session: currentStepStream,
|
|
1023
|
+
stepId: openedStep.stepId,
|
|
967
1024
|
patch: {
|
|
968
1025
|
status: "completed",
|
|
969
1026
|
kind: actionRequests?.length ? "action_result" : "message",
|
|
970
|
-
actionName: typeof
|
|
971
|
-
?
|
|
1027
|
+
actionName: typeof firstActionResult?.actionRequest?.actionName === "string"
|
|
1028
|
+
? firstActionResult.actionRequest.actionName
|
|
972
1029
|
: undefined,
|
|
973
|
-
actionInput:
|
|
974
|
-
actionOutput:
|
|
975
|
-
?
|
|
1030
|
+
actionInput: firstActionResult?.actionRequest?.input,
|
|
1031
|
+
actionOutput: firstActionResult?.success === true
|
|
1032
|
+
? firstActionResult?.output
|
|
976
1033
|
: undefined,
|
|
977
|
-
actionError:
|
|
978
|
-
? String(
|
|
1034
|
+
actionError: firstActionResult?.success === false
|
|
1035
|
+
? String(firstActionResult?.errorText ?? "action_execution_failed")
|
|
979
1036
|
: undefined,
|
|
980
1037
|
actionRequests,
|
|
981
1038
|
actionResults,
|
|
982
1039
|
continueLoop: continueLoop !== false,
|
|
983
1040
|
},
|
|
1041
|
+
reactionEventId,
|
|
1042
|
+
reactionEvent: finalizedReactionEvent,
|
|
984
1043
|
executionId,
|
|
985
1044
|
contextId: String(currentContext.id),
|
|
986
1045
|
iteration: iter,
|
|
987
1046
|
}));
|
|
1047
|
+
currentStepStream = null;
|
|
1048
|
+
reactionEvent = finalizedStep.reactionEvent ?? finalizedReactionEvent;
|
|
988
1049
|
await emitContextEvents({
|
|
989
1050
|
silent,
|
|
990
1051
|
writable,
|
|
@@ -992,19 +1053,19 @@ export class ContextEngine {
|
|
|
992
1053
|
{
|
|
993
1054
|
type: "step.updated",
|
|
994
1055
|
at: nowIso(),
|
|
995
|
-
stepId: String(
|
|
1056
|
+
stepId: String(openedStep.stepId),
|
|
996
1057
|
executionId,
|
|
997
1058
|
iteration: iter,
|
|
998
1059
|
status: "completed",
|
|
999
1060
|
kind: actionRequests?.length ? "action_result" : "message",
|
|
1000
|
-
actionName: typeof
|
|
1001
|
-
?
|
|
1061
|
+
actionName: typeof firstActionResult?.actionRequest?.actionName === "string"
|
|
1062
|
+
? firstActionResult.actionRequest.actionName
|
|
1002
1063
|
: undefined,
|
|
1003
1064
|
},
|
|
1004
1065
|
{
|
|
1005
1066
|
type: "step.completed",
|
|
1006
1067
|
at: nowIso(),
|
|
1007
|
-
stepId: String(
|
|
1068
|
+
stepId: String(openedStep.stepId),
|
|
1008
1069
|
executionId,
|
|
1009
1070
|
iteration: iter,
|
|
1010
1071
|
status: "completed",
|
|
@@ -1012,10 +1073,6 @@ export class ContextEngine {
|
|
|
1012
1073
|
],
|
|
1013
1074
|
});
|
|
1014
1075
|
if (continueLoop !== false) {
|
|
1015
|
-
reactionEvent = await measureBenchmark(params.__benchmark, `${stagePrefix}.persistPendingReactionMs`, async () => await ops.updateItem(reactionEventId, {
|
|
1016
|
-
...reactionEvent,
|
|
1017
|
-
status: "pending",
|
|
1018
|
-
}, { executionId, contextId: String(currentContext.id) }));
|
|
1019
1076
|
await emitContextEvents({
|
|
1020
1077
|
silent,
|
|
1021
1078
|
writable,
|
|
@@ -1032,10 +1089,6 @@ export class ContextEngine {
|
|
|
1032
1089
|
});
|
|
1033
1090
|
}
|
|
1034
1091
|
if (continueLoop === false) {
|
|
1035
|
-
await measureBenchmark(params.__benchmark, `${stagePrefix}.completeReactionMs`, async () => await ops.updateItem(reactionEventId, {
|
|
1036
|
-
...reactionEvent,
|
|
1037
|
-
status: "completed",
|
|
1038
|
-
}, { executionId, contextId: String(currentContext.id) }));
|
|
1039
1092
|
await emitContextEvents({
|
|
1040
1093
|
silent,
|
|
1041
1094
|
writable,
|
|
@@ -1075,10 +1128,6 @@ export class ContextEngine {
|
|
|
1075
1128
|
if (!silent) {
|
|
1076
1129
|
await closeContextStream({ preventClose, sendFinish, writable });
|
|
1077
1130
|
}
|
|
1078
|
-
reactionEvent = {
|
|
1079
|
-
...reactionEvent,
|
|
1080
|
-
status: "completed",
|
|
1081
|
-
};
|
|
1082
1131
|
return {
|
|
1083
1132
|
context: updatedContext,
|
|
1084
1133
|
trigger,
|