@ekairos/events 1.22.4-beta.development.0 → 1.22.5-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 +56 -83
- package/dist/context.d.ts +1 -1
- package/dist/context.engine.d.ts +24 -3
- package/dist/context.engine.js +55 -39
- package/dist/context.runtime.d.ts +11 -0
- package/dist/context.runtime.js +21 -0
- package/dist/index.d.ts +1 -1
- package/dist/reactors/ai-sdk.reactor.d.ts +4 -0
- package/dist/reactors/ai-sdk.reactor.js +4 -0
- package/dist/reactors/ai-sdk.step.d.ts +1 -0
- package/dist/reactors/ai-sdk.step.js +6 -3
- package/dist/reactors/types.d.ts +2 -0
- package/dist/runtime.step.js +1 -1
- package/dist/steps/store.steps.d.ts +55 -22
- package/dist/steps/store.steps.js +71 -78
- package/dist/steps/stream.steps.d.ts +4 -3
- package/dist/steps/stream.steps.js +14 -9
- package/dist/steps/trace.steps.d.ts +2 -0
- package/dist/steps/trace.steps.js +5 -2
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -2,114 +2,87 @@
|
|
|
2
2
|
|
|
3
3
|
Context-first durable execution runtime for Ekairos.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## What this package does
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- `
|
|
7
|
+
- creates durable contexts with `createContext(...)`
|
|
8
|
+
- persists executions, steps, parts, and items
|
|
9
|
+
- runs direct or durable `react(...)` loops
|
|
10
|
+
- adapts model/tool output into canonical `event_parts`
|
|
11
|
+
|
|
12
|
+
## Main APIs
|
|
13
|
+
|
|
14
|
+
- `createContext`
|
|
15
|
+
- `ContextEngine`
|
|
16
|
+
- `createAiSdkReactor`
|
|
17
|
+
- `createScriptedReactor`
|
|
18
|
+
- `runContextReactionDirect`
|
|
10
19
|
- `eventsDomain`
|
|
11
|
-
- `getContextRuntime`, `getContextEnv`, `registerContextEnv`
|
|
12
20
|
|
|
13
21
|
## Runtime model
|
|
14
22
|
|
|
23
|
+
Canonical entities:
|
|
24
|
+
|
|
15
25
|
- `event_contexts`
|
|
16
26
|
- `event_items`
|
|
17
27
|
- `event_executions`
|
|
18
28
|
- `event_steps`
|
|
19
29
|
- `event_parts`
|
|
20
|
-
- `
|
|
21
|
-
- `event_trace_runs`
|
|
22
|
-
- `event_trace_spans`
|
|
23
|
-
|
|
24
|
-
The aggregate is `context`. Executions, steps, parts, and items are scoped to a context.
|
|
25
|
-
|
|
26
|
-
## Canonical Parts
|
|
30
|
+
- `event_trace_*`
|
|
27
31
|
|
|
28
|
-
`event_parts` is the
|
|
32
|
+
`event_parts` is the source of truth for replay.
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- `event_parts.part` is the source of truth for replay and inspection.
|
|
33
|
-
- `event_items.content.parts` on output items is maintained as a compatibility mirror and is deprecated as a replay source.
|
|
34
|
-
- Provider/model-specific values must live under `metadata`, never as first-class semantic fields.
|
|
35
|
-
|
|
36
|
-
Canonical part kinds:
|
|
37
|
-
|
|
38
|
-
- `content`
|
|
39
|
-
- `reasoning`
|
|
40
|
-
- `source`
|
|
41
|
-
- `tool-call`
|
|
42
|
-
- `tool-result`
|
|
34
|
+
## Example
|
|
43
35
|
|
|
44
|
-
|
|
36
|
+
```ts
|
|
37
|
+
import { createContext } from "@ekairos/events";
|
|
45
38
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
const supportContext = createContext<{ orgId: string }>("support.agent")
|
|
40
|
+
.context((stored, env) => ({
|
|
41
|
+
...stored.content,
|
|
42
|
+
orgId: env.orgId,
|
|
43
|
+
}))
|
|
44
|
+
.narrative(() => "You are a precise assistant.")
|
|
45
|
+
.actions(() => ({}))
|
|
46
|
+
.build();
|
|
47
|
+
```
|
|
51
48
|
|
|
52
|
-
|
|
49
|
+
Run directly:
|
|
53
50
|
|
|
54
51
|
```ts
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
state: "output-available",
|
|
60
|
-
content: [
|
|
61
|
-
{
|
|
62
|
-
type: "text",
|
|
63
|
-
text: "Zoomed crop of the requested region.",
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
type: "file",
|
|
67
|
-
mediaType: "image/png",
|
|
68
|
-
filename: "inspect-region.png",
|
|
69
|
-
data: "iVBORw0KGgoAAAANSUhEUgAA...",
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
metadata: {
|
|
73
|
-
provider: {
|
|
74
|
-
itemId: "fc_041cb...",
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
}
|
|
52
|
+
await supportContext.react(triggerEvent, {
|
|
53
|
+
runtime,
|
|
54
|
+
context: { key: "support:org_123" },
|
|
55
|
+
});
|
|
78
56
|
```
|
|
79
57
|
|
|
80
|
-
|
|
58
|
+
Run durably:
|
|
81
59
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
60
|
+
```ts
|
|
61
|
+
const shell = await supportContext.react(triggerEvent, {
|
|
62
|
+
runtime,
|
|
63
|
+
context: { key: "support:org_123" },
|
|
64
|
+
durable: true,
|
|
65
|
+
});
|
|
88
66
|
|
|
89
|
-
|
|
90
|
-
pnpm add @ekairos/events
|
|
67
|
+
const final = await shell.run?.returnValue;
|
|
91
68
|
```
|
|
92
69
|
|
|
93
|
-
##
|
|
70
|
+
## Tool execution model
|
|
94
71
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
type Env = { orgId: string };
|
|
72
|
+
Context tools now receive runtime-aware execution context.
|
|
73
|
+
That lets a tool do this inside `"use step"`:
|
|
99
74
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.actions(() => ({}))
|
|
107
|
-
.reactor(createAiSdkReactor())
|
|
108
|
-
.build();
|
|
75
|
+
```ts
|
|
76
|
+
async function execute(input, ctx) {
|
|
77
|
+
"use step";
|
|
78
|
+
const domain = await ctx.runtime.use(myDomain);
|
|
79
|
+
return await domain.actions.doSomething(input);
|
|
80
|
+
}
|
|
109
81
|
```
|
|
110
82
|
|
|
111
|
-
##
|
|
83
|
+
## Tests
|
|
112
84
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
85
|
+
```bash
|
|
86
|
+
pnpm --filter @ekairos/events test
|
|
87
|
+
pnpm --filter @ekairos/events test:workflow
|
|
88
|
+
```
|
package/dist/context.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ContextEngine, type ContextOptions, type ContextStreamOptions, type ShouldContinue, type ContextShouldContinueArgs, type ContextReactParams, type ContextReactResult, type ContextDurableWorkflowPayload, type ContextDurableWorkflowFunction, type ContextModelInit, type ContextTool, runContextReactionDirect, } from "./context.engine.js";
|
|
1
|
+
export { ContextEngine, type ContextOptions, type ContextStreamOptions, type ShouldContinue, type ContextShouldContinueArgs, type ContextReactParams, type ContextReactResult, type ContextWorkflowRun, type ContextDurableWorkflowPayload, type ContextDurableWorkflowFunction, type ContextModelInit, type ContextTool, type ContextToolExecuteContext, runContextReactionDirect, } from "./context.engine.js";
|
|
2
2
|
export { context, createContext, type ContextConfig, type ContextInstance, type RegistrableContextBuilder, } from "./context.builder.js";
|
|
3
3
|
export { createAiSdkReactor, createScriptedReactor, type CreateAiSdkReactorOptions, type CreateScriptedReactorOptions, type ScriptedReactorStep, type ContextReactor, type ContextReactorParams, type ContextReactionResult, type ContextActionRequest, type ContextReactionLLM, } from "./context.reactor.js";
|
|
4
4
|
export type { ContextSkillPackage, ContextSkillPackageFile, } from "./context.skill.js";
|
package/dist/context.engine.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { Tool, UIMessageChunk } from "ai";
|
|
1
|
+
import type { ModelMessage, Tool, UIMessageChunk } from "ai";
|
|
2
2
|
import type { ContextEnvironment } from "./context.config.js";
|
|
3
|
+
import type { ContextRuntime } from "./context.runtime.js";
|
|
3
4
|
import type { ContextExecution, ContextItem, ContextIdentifier, StoredContext } from "./context.store.js";
|
|
4
5
|
import type { ContextSkillPackage } from "./context.skill.js";
|
|
5
6
|
import { type ContextReactor } from "./context.reactor.js";
|
|
@@ -68,7 +69,7 @@ export interface ContextStreamOptions {
|
|
|
68
69
|
*/
|
|
69
70
|
export type ContextModelInit = string | (() => Promise<any>);
|
|
70
71
|
export type ContextReactParams<Env extends ContextEnvironment = ContextEnvironment> = {
|
|
71
|
-
|
|
72
|
+
runtime: ContextRuntime<Env>;
|
|
72
73
|
/**
|
|
73
74
|
* Context selector (exclusive: `{ id }` OR `{ key }`).
|
|
74
75
|
* - `{ id }` resolves a concrete context id.
|
|
@@ -95,16 +96,36 @@ export type ContextReactResult<Context = any> = {
|
|
|
95
96
|
trigger: ContextItem;
|
|
96
97
|
reaction: ContextItem;
|
|
97
98
|
execution: ContextExecution;
|
|
99
|
+
run?: ContextWorkflowRun<Context>;
|
|
100
|
+
};
|
|
101
|
+
export type ContextWorkflowRun<Context = any> = {
|
|
102
|
+
runId: string;
|
|
103
|
+
status: Promise<"pending" | "running" | "completed" | "failed" | "cancelled">;
|
|
104
|
+
returnValue: Promise<ContextReactResult<Context>>;
|
|
98
105
|
};
|
|
99
106
|
export type ContextDurableWorkflowPayload<Env extends ContextEnvironment = ContextEnvironment> = {
|
|
100
107
|
contextKey: string;
|
|
101
|
-
|
|
108
|
+
runtime: ContextRuntime<Env>;
|
|
102
109
|
context?: ContextIdentifier | null;
|
|
103
110
|
triggerEvent: ContextItem;
|
|
104
111
|
options?: Omit<ContextStreamOptions, "writable">;
|
|
105
112
|
bootstrap: NonNullable<ContextReactParams<Env>["__bootstrap"]>;
|
|
106
113
|
};
|
|
107
114
|
export type ContextDurableWorkflowFunction<Context = any, Env extends ContextEnvironment = ContextEnvironment> = (payload: ContextDurableWorkflowPayload<Env>) => Promise<ContextReactResult<Context>>;
|
|
115
|
+
export type ContextToolExecuteContext<Context = any, Env extends ContextEnvironment = ContextEnvironment> = {
|
|
116
|
+
runtime: ContextRuntime<Env>;
|
|
117
|
+
env: Env;
|
|
118
|
+
context: StoredContext<Context>;
|
|
119
|
+
contextIdentifier: ContextIdentifier;
|
|
120
|
+
toolCallId: string;
|
|
121
|
+
messages: ModelMessage[];
|
|
122
|
+
eventId: string;
|
|
123
|
+
executionId: string;
|
|
124
|
+
triggerEventId: string;
|
|
125
|
+
contextId: string;
|
|
126
|
+
stepId: string;
|
|
127
|
+
iteration: number;
|
|
128
|
+
};
|
|
108
129
|
export { toolApprovalHookToken, toolApprovalWebhookToken, getClientResumeHookUrl };
|
|
109
130
|
/**
|
|
110
131
|
* Context-level tool type.
|
package/dist/context.engine.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
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";
|
|
@@ -89,9 +89,8 @@ async function readActiveWorkflowRunId() {
|
|
|
89
89
|
return null;
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
async function createRuntimeOps(
|
|
93
|
-
const
|
|
94
|
-
const runtime = await getContextRuntime(env);
|
|
92
|
+
async function createRuntimeOps(runtimeHandle, benchmark) {
|
|
93
|
+
const runtime = await getContextRuntimeServices(runtimeHandle);
|
|
95
94
|
const { db } = runtime;
|
|
96
95
|
const { InstantStore } = await import("./stores/instant.store.js");
|
|
97
96
|
const requireContextId = (contextIdentifier) => {
|
|
@@ -255,27 +254,27 @@ async function createRuntimeOps(env, benchmark) {
|
|
|
255
254
|
},
|
|
256
255
|
};
|
|
257
256
|
}
|
|
258
|
-
async function createWorkflowOps(
|
|
257
|
+
async function createWorkflowOps(runtime) {
|
|
258
|
+
const env = runtime.env;
|
|
259
259
|
return {
|
|
260
|
-
initializeContext: async (contextIdentifier, opts) => await initializeContext(
|
|
261
|
-
updateContextContent: async (contextIdentifier, content) => await updateContextContent(
|
|
262
|
-
updateContextStatus: async (contextIdentifier, status) => await updateContextStatus(
|
|
263
|
-
saveTriggerAndCreateExecution: async ({ contextIdentifier, triggerEvent }) => await saveTriggerAndCreateExecution({
|
|
264
|
-
createContextStep: async ({ executionId, iteration }) => await createContextStep({
|
|
265
|
-
updateContextStep: async (params) => await updateContextStep({
|
|
266
|
-
saveContextPartsStep: async (params) => await saveContextPartsStep({
|
|
267
|
-
updateItem: async (itemId, item, opts) => await updateItem(
|
|
268
|
-
completeExecution: async (contextIdentifier, executionId, status) => await completeExecution(
|
|
260
|
+
initializeContext: async (contextIdentifier, opts) => await initializeContext({ runtime, contextIdentifier, opts }),
|
|
261
|
+
updateContextContent: async (contextIdentifier, content) => await updateContextContent({ runtime, contextIdentifier, content }),
|
|
262
|
+
updateContextStatus: async (contextIdentifier, status) => await updateContextStatus({ runtime, contextIdentifier, status }),
|
|
263
|
+
saveTriggerAndCreateExecution: async ({ contextIdentifier, triggerEvent }) => await saveTriggerAndCreateExecution({ runtime, contextIdentifier, triggerEvent }),
|
|
264
|
+
createContextStep: async ({ executionId, iteration }) => await createContextStep({ runtime, executionId, iteration }),
|
|
265
|
+
updateContextStep: async (params) => await updateContextStep({ runtime, ...params }),
|
|
266
|
+
saveContextPartsStep: async (params) => await saveContextPartsStep({ runtime, ...params }),
|
|
267
|
+
updateItem: async (itemId, item, opts) => await updateItem({ runtime, eventId: itemId, event: item, opts }),
|
|
268
|
+
completeExecution: async (contextIdentifier, executionId, status) => await completeExecution({ runtime, contextIdentifier, executionId, status }),
|
|
269
269
|
};
|
|
270
270
|
}
|
|
271
|
-
async function getContextEngineOps(
|
|
271
|
+
async function getContextEngineOps(runtime, benchmark) {
|
|
272
|
+
const env = runtime.env;
|
|
272
273
|
const workflowRunId = await readActiveWorkflowRunId();
|
|
273
274
|
if (workflowRunId) {
|
|
274
|
-
|
|
275
|
-
return await createWorkflowOps(env);
|
|
275
|
+
return await createWorkflowOps(runtime);
|
|
276
276
|
}
|
|
277
|
-
|
|
278
|
-
return await createRuntimeOps(env, benchmark);
|
|
277
|
+
return await createRuntimeOps(runtime, benchmark);
|
|
279
278
|
}
|
|
280
279
|
export class ContextEngine {
|
|
281
280
|
constructor(opts = {}, reactor) {
|
|
@@ -329,13 +328,14 @@ export class ContextEngine {
|
|
|
329
328
|
return await ContextEngine.runDirect(this, triggerEvent, params);
|
|
330
329
|
}
|
|
331
330
|
static async prepareExecutionShell(story, triggerEvent, params) {
|
|
332
|
-
const
|
|
331
|
+
const env = params.runtime.env;
|
|
332
|
+
const ops = await measureBenchmark(params.__benchmark, "react.resolveOpsMs", async () => await getContextEngineOps(params.runtime, params.__benchmark));
|
|
333
333
|
const silent = params.options?.silent ?? false;
|
|
334
334
|
const ctxResult = await measureBenchmark(params.__benchmark, "react.initializeContextMs", async () => await ops.initializeContext(params.context ?? null, { silent }));
|
|
335
335
|
let currentContext = ctxResult.context;
|
|
336
336
|
const contextSelector = { id: String(currentContext.id) };
|
|
337
337
|
if (ctxResult.isNew) {
|
|
338
|
-
await story.opts.onContextCreated?.({ env
|
|
338
|
+
await story.opts.onContextCreated?.({ env, context: currentContext });
|
|
339
339
|
}
|
|
340
340
|
if (currentContext.status === "closed") {
|
|
341
341
|
await measureBenchmark(params.__benchmark, "react.reopenClosedContextMs", async () => await ops.updateContextStatus(contextSelector, "open_idle"));
|
|
@@ -355,6 +355,7 @@ export class ContextEngine {
|
|
|
355
355
|
};
|
|
356
356
|
}
|
|
357
357
|
static async startDurable(story, triggerEvent, params) {
|
|
358
|
+
const env = params.runtime.env;
|
|
358
359
|
if (params.options?.writable) {
|
|
359
360
|
throw new Error("ContextEngine.react: durable runs manage their own workflow stream");
|
|
360
361
|
}
|
|
@@ -367,14 +368,15 @@ export class ContextEngine {
|
|
|
367
368
|
throw new Error("ContextEngine.react: durable workflow is not configured. Call configureContextDurableWorkflow(...) in runtime bootstrap.");
|
|
368
369
|
}
|
|
369
370
|
const shell = await ContextEngine.prepareExecutionShell(story, triggerEvent, params);
|
|
371
|
+
let run;
|
|
370
372
|
try {
|
|
371
373
|
const [{ start }] = await Promise.all([
|
|
372
374
|
import("workflow/api"),
|
|
373
375
|
]);
|
|
374
|
-
const
|
|
376
|
+
const startedRun = await start(workflow, [
|
|
375
377
|
{
|
|
376
378
|
contextKey,
|
|
377
|
-
|
|
379
|
+
runtime: params.runtime,
|
|
378
380
|
context: params.context ?? null,
|
|
379
381
|
triggerEvent,
|
|
380
382
|
options: {
|
|
@@ -392,16 +394,21 @@ export class ContextEngine {
|
|
|
392
394
|
},
|
|
393
395
|
},
|
|
394
396
|
]);
|
|
395
|
-
|
|
397
|
+
run = {
|
|
398
|
+
runId: String(startedRun.runId),
|
|
399
|
+
status: startedRun.status,
|
|
400
|
+
returnValue: startedRun.returnValue,
|
|
401
|
+
};
|
|
402
|
+
const runtime = await createRuntimeOps(params.runtime);
|
|
396
403
|
await runtime.db.transact([
|
|
397
404
|
runtime.db.tx.event_executions[shell.execution.id].update({
|
|
398
|
-
workflowRunId:
|
|
405
|
+
workflowRunId: startedRun.runId,
|
|
399
406
|
updatedAt: new Date(),
|
|
400
407
|
}),
|
|
401
408
|
]);
|
|
402
409
|
}
|
|
403
410
|
catch (error) {
|
|
404
|
-
const ops = await getContextEngineOps(params.
|
|
411
|
+
const ops = await getContextEngineOps(params.runtime, params.__benchmark);
|
|
405
412
|
await ops.completeExecution(shell.contextSelector, shell.execution.id, "failed").catch(() => null);
|
|
406
413
|
throw error;
|
|
407
414
|
}
|
|
@@ -410,10 +417,12 @@ export class ContextEngine {
|
|
|
410
417
|
trigger: shell.trigger,
|
|
411
418
|
reaction: shell.reaction,
|
|
412
419
|
execution: shell.execution,
|
|
420
|
+
run,
|
|
413
421
|
};
|
|
414
422
|
}
|
|
415
423
|
static async runDirect(story, triggerEvent, params) {
|
|
416
|
-
const
|
|
424
|
+
const env = params.runtime.env;
|
|
425
|
+
const ops = await measureBenchmark(params.__benchmark, "react.resolveOpsMs", async () => await getContextEngineOps(params.runtime, params.__benchmark));
|
|
417
426
|
const maxIterations = params.options?.maxIterations ?? 20;
|
|
418
427
|
const maxModelSteps = params.options?.maxModelSteps ?? 1;
|
|
419
428
|
const preventClose = params.options?.preventClose ?? false;
|
|
@@ -488,7 +497,7 @@ export class ContextEngine {
|
|
|
488
497
|
}));
|
|
489
498
|
currentStepId = stepCreate.stepId;
|
|
490
499
|
currentStepStream = await createPersistedContextStepStream({
|
|
491
|
-
|
|
500
|
+
runtime: params.runtime,
|
|
492
501
|
executionId,
|
|
493
502
|
stepId: stepCreate.stepId,
|
|
494
503
|
});
|
|
@@ -507,7 +516,7 @@ export class ContextEngine {
|
|
|
507
516
|
],
|
|
508
517
|
});
|
|
509
518
|
// Hook: Context DSL `context()` (implemented by subclasses via `initialize()`)
|
|
510
|
-
const nextContent = await measureBenchmark(params.__benchmark, `${stagePrefix}.contextMs`, async () => await story.initialize(updatedContext,
|
|
519
|
+
const nextContent = await measureBenchmark(params.__benchmark, `${stagePrefix}.contextMs`, async () => await story.initialize(updatedContext, env));
|
|
511
520
|
updatedContext = await measureBenchmark(params.__benchmark, `${stagePrefix}.persistContextMs`, async () => await ops.updateContextContent(activeContextSelector, nextContent));
|
|
512
521
|
await emitContextEvents({
|
|
513
522
|
silent,
|
|
@@ -520,12 +529,12 @@ export class ContextEngine {
|
|
|
520
529
|
},
|
|
521
530
|
],
|
|
522
531
|
});
|
|
523
|
-
await story.opts.onContextUpdated?.({ env
|
|
532
|
+
await story.opts.onContextUpdated?.({ env, context: updatedContext });
|
|
524
533
|
// Hook: Context DSL `narrative()` (implemented by subclasses via `buildSystemPrompt()`)
|
|
525
|
-
const systemPrompt = await measureBenchmark(params.__benchmark, `${stagePrefix}.narrativeMs`, async () => await story.buildSystemPrompt(updatedContext,
|
|
534
|
+
const systemPrompt = await measureBenchmark(params.__benchmark, `${stagePrefix}.narrativeMs`, async () => await story.buildSystemPrompt(updatedContext, env));
|
|
526
535
|
// Hook: Context DSL `actions()` (implemented by subclasses via `buildTools()`)
|
|
527
|
-
const toolsAll = await measureBenchmark(params.__benchmark, `${stagePrefix}.actionsMs`, async () => await story.buildTools(updatedContext,
|
|
528
|
-
const skillsAll = await measureBenchmark(params.__benchmark, `${stagePrefix}.skillsMs`, async () => await story.buildSkills(updatedContext,
|
|
536
|
+
const toolsAll = await measureBenchmark(params.__benchmark, `${stagePrefix}.actionsMs`, async () => await story.buildTools(updatedContext, env));
|
|
537
|
+
const skillsAll = await measureBenchmark(params.__benchmark, `${stagePrefix}.skillsMs`, async () => await story.buildSkills(updatedContext, env));
|
|
529
538
|
// IMPORTANT: step args must be serializable.
|
|
530
539
|
// Match DurableAgent behavior: convert tool input schemas to plain JSON Schema in workflow context.
|
|
531
540
|
const toolsForModel = toolsToModelTools(toolsAll);
|
|
@@ -536,7 +545,7 @@ export class ContextEngine {
|
|
|
536
545
|
// If we stream with a per-step id, the UI will render an optimistic assistant message
|
|
537
546
|
// (step id) and then a second persisted assistant message (reaction id) with the same
|
|
538
547
|
// content once InstantDB updates.
|
|
539
|
-
const reactor = story.getReactor(updatedContext,
|
|
548
|
+
const reactor = story.getReactor(updatedContext, env);
|
|
540
549
|
const reactionPartsBeforeStep = Array.isArray(reactionEvent.content?.parts)
|
|
541
550
|
? [...reactionEvent.content.parts]
|
|
542
551
|
: [];
|
|
@@ -564,11 +573,12 @@ export class ContextEngine {
|
|
|
564
573
|
}, { executionId, contextId: String(currentContext.id) });
|
|
565
574
|
};
|
|
566
575
|
const { assistantEvent, actionRequests, messagesForModel } = await measureBenchmark(params.__benchmark, `${stagePrefix}.reactorMs`, async () => await reactor({
|
|
567
|
-
|
|
576
|
+
runtime: params.runtime,
|
|
577
|
+
env,
|
|
568
578
|
context: updatedContext,
|
|
569
579
|
contextIdentifier: activeContextSelector,
|
|
570
580
|
triggerEvent,
|
|
571
|
-
model: story.getModel(updatedContext,
|
|
581
|
+
model: story.getModel(updatedContext, env),
|
|
572
582
|
systemPrompt,
|
|
573
583
|
actions: toolsAll,
|
|
574
584
|
toolsForModel,
|
|
@@ -651,7 +661,7 @@ export class ContextEngine {
|
|
|
651
661
|
reactionEvent = await measureBenchmark(params.__benchmark, `${stagePrefix}.persistAssistantReactionMs`, async () => await ops.updateItem(reactionEvent.id, nextReactionEvent, { executionId, contextId: String(currentContext.id) }));
|
|
652
662
|
if (currentStepStream) {
|
|
653
663
|
await closePersistedContextStepStream({
|
|
654
|
-
|
|
664
|
+
runtime: params.runtime,
|
|
655
665
|
session: currentStepStream,
|
|
656
666
|
});
|
|
657
667
|
currentStepStream = null;
|
|
@@ -832,12 +842,18 @@ export class ContextEngine {
|
|
|
832
842
|
}
|
|
833
843
|
}
|
|
834
844
|
const output = await toolDef.execute(actionInput, {
|
|
845
|
+
runtime: params.runtime,
|
|
846
|
+
env,
|
|
847
|
+
context: updatedContext,
|
|
848
|
+
contextIdentifier: activeContextSelector,
|
|
835
849
|
toolCallId: actionRequest.actionRef,
|
|
836
850
|
messages: messagesForModel,
|
|
837
851
|
eventId: reactionEventId,
|
|
838
852
|
executionId,
|
|
839
853
|
triggerEventId,
|
|
840
854
|
contextId: currentContext.id,
|
|
855
|
+
stepId: String(stepCreate.stepId),
|
|
856
|
+
iteration: iter,
|
|
841
857
|
});
|
|
842
858
|
return { actionRequest, success: true, output };
|
|
843
859
|
}
|
|
@@ -894,7 +910,7 @@ export class ContextEngine {
|
|
|
894
910
|
// IMPORTANT: we call this after tool results have been merged into the persisted `reactionEvent`,
|
|
895
911
|
// so stories can inspect `reactionEvent.content.parts` deterministically.
|
|
896
912
|
const continueLoop = await measureBenchmark(params.__benchmark, `${stagePrefix}.shouldContinueMs`, async () => await story.shouldContinue({
|
|
897
|
-
env
|
|
913
|
+
env,
|
|
898
914
|
context: updatedContext,
|
|
899
915
|
reactionEvent,
|
|
900
916
|
assistantEvent: assistantEventEffective,
|
|
@@ -1033,7 +1049,7 @@ export class ContextEngine {
|
|
|
1033
1049
|
if (currentStepStream) {
|
|
1034
1050
|
try {
|
|
1035
1051
|
await abortPersistedContextStepStream({
|
|
1036
|
-
|
|
1052
|
+
runtime: params.runtime,
|
|
1037
1053
|
session: currentStepStream,
|
|
1038
1054
|
reason: error instanceof Error ? error.message : String(error),
|
|
1039
1055
|
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConcreteDomain } from "@ekairos/domain";
|
|
2
|
+
import type { ExplicitRuntimeLike } from "@ekairos/domain/runtime";
|
|
3
|
+
import type { ContextEnvironment } from "./context.config.js";
|
|
4
|
+
import type { ContextStore } from "./context.store.js";
|
|
5
|
+
export type ContextRuntime<Env extends ContextEnvironment = ContextEnvironment> = ExplicitRuntimeLike<Env, any, any>;
|
|
6
|
+
export type ContextRuntimeServices = {
|
|
7
|
+
db: any;
|
|
8
|
+
store: ContextStore;
|
|
9
|
+
domain?: ConcreteDomain<any, any>;
|
|
10
|
+
};
|
|
11
|
+
export declare function getContextRuntimeServices(runtime: ContextRuntime<any>): Promise<ContextRuntimeServices>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const storeByDb = new WeakMap();
|
|
2
|
+
export async function getContextRuntimeServices(runtime) {
|
|
3
|
+
const db = await runtime.db();
|
|
4
|
+
if (!db) {
|
|
5
|
+
throw new Error("Context runtime did not provide a database instance.");
|
|
6
|
+
}
|
|
7
|
+
let store = typeof db === "object" && db !== null ? storeByDb.get(db) : undefined;
|
|
8
|
+
if (!store) {
|
|
9
|
+
const { InstantStore } = await import("./stores/instant.store.js");
|
|
10
|
+
store = new InstantStore(db);
|
|
11
|
+
if (typeof db === "object" && db !== null) {
|
|
12
|
+
storeByDb.set(db, store);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const resolved = await runtime.resolve();
|
|
16
|
+
return {
|
|
17
|
+
db,
|
|
18
|
+
store,
|
|
19
|
+
domain: typeof resolved === "object" && resolved !== null ? resolved.meta?.()?.domain : undefined,
|
|
20
|
+
};
|
|
21
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { context, createContext, createAiSdkReactor, createScriptedReactor, type CreateAiSdkReactorOptions, type CreateScriptedReactorOptions, type ScriptedReactorStep, type ContextConfig, type ContextInstance, type ContextOptions, type ContextStreamOptions, type ContextReactor, type ContextReactorParams, type ContextReactionResult, type ContextActionRequest, type ContextReactionLLM, ContextEngine, type RegistrableContextBuilder, type ContextReactParams, type ContextReactResult, type ContextDurableWorkflowPayload, type ContextDurableWorkflowFunction, type ContextModelInit, type ContextTool, runContextReactionDirect, } from "./context.js";
|
|
1
|
+
export { context, createContext, createAiSdkReactor, createScriptedReactor, type CreateAiSdkReactorOptions, type CreateScriptedReactorOptions, type ScriptedReactorStep, type ContextConfig, type ContextInstance, type ContextOptions, type ContextStreamOptions, type ContextReactor, type ContextReactorParams, type ContextReactionResult, type ContextActionRequest, type ContextReactionLLM, ContextEngine, type RegistrableContextBuilder, type ContextReactParams, type ContextReactResult, type ContextWorkflowRun, type ContextDurableWorkflowPayload, type ContextDurableWorkflowFunction, type ContextModelInit, type ContextTool, type ContextToolExecuteContext, runContextReactionDirect, } from "./context.js";
|
|
2
2
|
export type { ContextStore, ContextIdentifier, StoredContext, ContextItem, ContextExecution, } from "./context.store.js";
|
|
3
3
|
export type { WireDate, ContextMirrorContext, ContextMirrorExecution, ContextMirrorWrite, ContextMirrorRequest, } from "./mirror.js";
|
|
4
4
|
export { registerContext, getContext, getContextFactory, hasContext, listContexts, type ContextKey, } from "./context.registry.js";
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ContextEnvironment } from "../context.config.js";
|
|
2
|
+
import type { ContextRuntime } from "../context.runtime.js";
|
|
2
3
|
import type { ContextModelInit } from "../context.engine.js";
|
|
3
4
|
import type { ContextIdentifier, StoredContext, ContextItem } from "../context.store.js";
|
|
4
5
|
import type { ContextReactor } from "./types.js";
|
|
5
6
|
export type CreateAiSdkReactorOptions<Context = unknown, Env extends ContextEnvironment = ContextEnvironment, Config = unknown> = {
|
|
6
7
|
resolveConfig?: (params: {
|
|
8
|
+
runtime: ContextRuntime<Env>;
|
|
7
9
|
env: Env;
|
|
8
10
|
context: StoredContext<Context>;
|
|
9
11
|
contextIdentifier: ContextIdentifier;
|
|
@@ -16,6 +18,7 @@ export type CreateAiSdkReactorOptions<Context = unknown, Env extends ContextEnvi
|
|
|
16
18
|
iteration: number;
|
|
17
19
|
}) => Promise<Config> | Config;
|
|
18
20
|
selectModel?: (params: {
|
|
21
|
+
runtime: ContextRuntime<Env>;
|
|
19
22
|
env: Env;
|
|
20
23
|
context: StoredContext<Context>;
|
|
21
24
|
triggerEvent: ContextItem;
|
|
@@ -23,6 +26,7 @@ export type CreateAiSdkReactorOptions<Context = unknown, Env extends ContextEnvi
|
|
|
23
26
|
config: Config;
|
|
24
27
|
}) => Promise<ContextModelInit> | ContextModelInit;
|
|
25
28
|
selectMaxModelSteps?: (params: {
|
|
29
|
+
runtime: ContextRuntime<Env>;
|
|
26
30
|
env: Env;
|
|
27
31
|
context: StoredContext<Context>;
|
|
28
32
|
triggerEvent: ContextItem;
|
|
@@ -4,6 +4,7 @@ export function createAiSdkReactor(options) {
|
|
|
4
4
|
let config;
|
|
5
5
|
if (options?.resolveConfig) {
|
|
6
6
|
config = await options.resolveConfig({
|
|
7
|
+
runtime: params.runtime,
|
|
7
8
|
env: params.env,
|
|
8
9
|
context: params.context,
|
|
9
10
|
contextIdentifier: params.contextIdentifier,
|
|
@@ -18,6 +19,7 @@ export function createAiSdkReactor(options) {
|
|
|
18
19
|
}
|
|
19
20
|
const model = options?.selectModel && config !== undefined
|
|
20
21
|
? await options.selectModel({
|
|
22
|
+
runtime: params.runtime,
|
|
21
23
|
env: params.env,
|
|
22
24
|
context: params.context,
|
|
23
25
|
triggerEvent: params.triggerEvent,
|
|
@@ -27,6 +29,7 @@ export function createAiSdkReactor(options) {
|
|
|
27
29
|
: params.model;
|
|
28
30
|
const maxSteps = options?.selectMaxModelSteps && config !== undefined
|
|
29
31
|
? await options.selectMaxModelSteps({
|
|
32
|
+
runtime: params.runtime,
|
|
30
33
|
env: params.env,
|
|
31
34
|
context: params.context,
|
|
32
35
|
triggerEvent: params.triggerEvent,
|
|
@@ -35,6 +38,7 @@ export function createAiSdkReactor(options) {
|
|
|
35
38
|
})
|
|
36
39
|
: params.maxModelSteps;
|
|
37
40
|
const result = await executeAiSdkReaction({
|
|
41
|
+
runtime: params.runtime,
|
|
38
42
|
env: params.env,
|
|
39
43
|
contextIdentifier: params.contextIdentifier,
|
|
40
44
|
model,
|
|
@@ -14,6 +14,7 @@ import type { SerializableToolForModel } from "../tools-to-model-tools.js";
|
|
|
14
14
|
* - emit UI chunks and persist step stream chunks
|
|
15
15
|
*/
|
|
16
16
|
export declare function executeAiSdkReaction(params: {
|
|
17
|
+
runtime: import("../context.runtime.js").ContextRuntime<ContextEnvironment>;
|
|
17
18
|
env: ContextEnvironment;
|
|
18
19
|
contextIdentifier: ContextIdentifier;
|
|
19
20
|
model: ContextModelInit;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getContextRuntimeServices } from "../context.runtime.js";
|
|
1
2
|
import { OUTPUT_ITEM_TYPE } from "../context.events.js";
|
|
2
3
|
import { createContextStepStreamChunk, encodeContextStepStreamChunk, } from "../context.step-stream.js";
|
|
3
4
|
import { mapAiSdkChunkToContextEvent } from "./ai-sdk.chunk-map.js";
|
|
@@ -82,8 +83,7 @@ function safeErrorJson(error) {
|
|
|
82
83
|
*/
|
|
83
84
|
export async function executeAiSdkReaction(params) {
|
|
84
85
|
"use step";
|
|
85
|
-
const {
|
|
86
|
-
const { store } = await getContextRuntime(params.env);
|
|
86
|
+
const { store } = await getContextRuntimeServices(params.runtime);
|
|
87
87
|
let events;
|
|
88
88
|
try {
|
|
89
89
|
events = await store.getItems(params.contextIdentifier);
|
|
@@ -221,7 +221,10 @@ export async function executeAiSdkReaction(params) {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
finally {
|
|
224
|
-
contextStepStreamWriter
|
|
224
|
+
const streamWriter = contextStepStreamWriter;
|
|
225
|
+
if (typeof streamWriter?.releaseLock === "function") {
|
|
226
|
+
streamWriter.releaseLock();
|
|
227
|
+
}
|
|
225
228
|
}
|
|
226
229
|
const assistantEvent = await finishPromise;
|
|
227
230
|
const finishedAtMs = Date.now();
|
package/dist/reactors/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ModelMessage, UIMessageChunk } from "ai";
|
|
2
2
|
import type { ContextEnvironment } from "../context.config.js";
|
|
3
|
+
import type { ContextRuntime } from "../context.runtime.js";
|
|
3
4
|
import type { ContextModelInit } from "../context.engine.js";
|
|
4
5
|
import type { ContextIdentifier, StoredContext, ContextItem } from "../context.store.js";
|
|
5
6
|
import type { ContextSkillPackage } from "../context.skill.js";
|
|
@@ -28,6 +29,7 @@ export type ContextReactionResult = {
|
|
|
28
29
|
llm?: ContextReactionLLM;
|
|
29
30
|
};
|
|
30
31
|
export type ContextReactorParams<Context = unknown, Env extends ContextEnvironment = ContextEnvironment> = {
|
|
32
|
+
runtime: ContextRuntime<Env>;
|
|
31
33
|
env: Env;
|
|
32
34
|
context: StoredContext<Context>;
|
|
33
35
|
contextIdentifier: ContextIdentifier;
|
package/dist/runtime.step.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { coerceContextRuntime } from "./context.config.js";
|
|
2
2
|
import { eventsDomain } from "./schema.js";
|
|
3
3
|
export async function getContextRuntime(env) {
|
|
4
|
-
const { resolveRuntime } = await import("@ekairos/domain/runtime
|
|
4
|
+
const { resolveRuntime } = await import("@ekairos/domain/runtime");
|
|
5
5
|
const resolved = await resolveRuntime(eventsDomain, env);
|
|
6
6
|
return await coerceContextRuntime(resolved);
|
|
7
7
|
}
|