@ekairos/events 1.22.34-beta.development.0 → 1.22.35
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 +58 -83
- package/dist/codex.d.ts +11 -2
- package/dist/codex.js +16 -8
- package/dist/context.action-calls.d.ts +48 -0
- package/dist/context.action-calls.js +123 -0
- package/dist/context.action.d.ts +55 -0
- package/dist/context.action.js +25 -0
- package/dist/context.builder.d.ts +71 -43
- package/dist/context.builder.js +123 -28
- package/dist/context.config.d.ts +2 -1
- package/dist/context.config.js +8 -3
- package/dist/context.contract.d.ts +2 -4
- package/dist/context.contract.js +3 -9
- package/dist/context.d.ts +3 -2
- package/dist/context.engine.d.ts +75 -46
- package/dist/context.engine.js +538 -302
- 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 +270 -0
- package/dist/context.parts.d.ts +389 -164
- package/dist/context.parts.js +343 -218
- package/dist/context.registry.d.ts +1 -1
- package/dist/context.runtime.d.ts +21 -0
- package/dist/context.runtime.js +39 -0
- package/dist/context.step-stream.d.ts +16 -2
- package/dist/context.step-stream.js +58 -16
- package/dist/context.store.d.ts +63 -10
- package/dist/context.stream.d.ts +14 -4
- package/dist/context.stream.js +31 -3
- package/dist/domain.d.ts +1 -0
- package/dist/domain.js +1 -0
- package/dist/index.d.ts +13 -10
- package/dist/index.js +7 -6
- package/dist/react.context-event-parts.d.ts +18 -0
- package/dist/react.context-event-parts.js +509 -0
- package/dist/react.d.ts +7 -42
- package/dist/react.js +4 -87
- package/dist/react.step-stream.d.ts +39 -0
- package/dist/react.step-stream.js +625 -0
- package/dist/react.types.d.ts +121 -0
- package/dist/react.types.js +2 -0
- package/dist/react.use-context.d.ts +7 -0
- package/dist/react.use-context.js +867 -0
- package/dist/reactors/ai-sdk.chunk-map.d.ts +1 -0
- package/dist/reactors/ai-sdk.chunk-map.js +56 -5
- package/dist/reactors/ai-sdk.reactor.d.ts +8 -5
- package/dist/reactors/ai-sdk.reactor.js +10 -9
- package/dist/reactors/ai-sdk.step.d.ts +6 -6
- package/dist/reactors/ai-sdk.step.js +32 -24
- package/dist/reactors/scripted.reactor.d.ts +7 -4
- package/dist/reactors/types.d.ts +23 -8
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.js +9 -0
- package/dist/runtime.step.js +2 -2
- package/dist/schema.d.ts +268 -2
- package/dist/schema.js +5 -9
- package/dist/steps/do-context-stream-step.d.ts +2 -2
- package/dist/steps/do-context-stream-step.js +6 -8
- package/dist/steps/durable.steps.d.ts +28 -0
- package/dist/steps/durable.steps.js +34 -0
- package/dist/steps/store.steps.d.ts +121 -39
- package/dist/steps/store.steps.js +266 -111
- package/dist/steps/stream.steps.d.ts +36 -3
- package/dist/steps/stream.steps.js +137 -14
- package/dist/steps/trace.steps.d.ts +4 -2
- package/dist/steps/trace.steps.js +26 -8
- package/dist/stores/instant.store.d.ts +15 -11
- package/dist/stores/instant.store.js +155 -6
- package/dist/tools-to-model-tools.d.ts +39 -3
- package/dist/tools-to-model-tools.js +63 -6
- package/package.json +20 -6
- package/dist/context.toolcalls.d.ts +0 -60
- package/dist/context.toolcalls.js +0 -117
package/README.md
CHANGED
|
@@ -2,114 +2,89 @@
|
|
|
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
|
-
|
|
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
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
The AI SDK bridge projects canonical parts to:
|
|
52
|
+
const shell = await supportContext.react(triggerEvent, {
|
|
53
|
+
runtime,
|
|
54
|
+
context: { key: "support:org_123" },
|
|
55
|
+
durable: false,
|
|
56
|
+
});
|
|
81
57
|
|
|
82
|
-
|
|
83
|
-
|
|
58
|
+
const final = await shell.run!;
|
|
59
|
+
```
|
|
84
60
|
|
|
85
|
-
|
|
61
|
+
Run durably:
|
|
86
62
|
|
|
87
|
-
|
|
63
|
+
```ts
|
|
64
|
+
const shell = await supportContext.react(triggerEvent, {
|
|
65
|
+
runtime,
|
|
66
|
+
context: { key: "support:org_123" },
|
|
67
|
+
});
|
|
88
68
|
|
|
89
|
-
|
|
90
|
-
pnpm add @ekairos/events
|
|
69
|
+
const final = await shell.run!.returnValue;
|
|
91
70
|
```
|
|
92
71
|
|
|
93
|
-
##
|
|
94
|
-
|
|
95
|
-
```ts
|
|
96
|
-
import { createContext, createAiSdkReactor } from "@ekairos/events";
|
|
72
|
+
## Tool execution model
|
|
97
73
|
|
|
98
|
-
|
|
74
|
+
Context tools now receive runtime-aware execution context.
|
|
75
|
+
That lets a tool do this inside `"use step"`:
|
|
99
76
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.actions(() => ({}))
|
|
107
|
-
.reactor(createAiSdkReactor())
|
|
108
|
-
.build();
|
|
77
|
+
```ts
|
|
78
|
+
async function execute(input, ctx) {
|
|
79
|
+
"use step";
|
|
80
|
+
const domain = await ctx.runtime.use(myDomain);
|
|
81
|
+
return await domain.actions.doSomething(input);
|
|
82
|
+
}
|
|
109
83
|
```
|
|
110
84
|
|
|
111
|
-
##
|
|
85
|
+
## Tests
|
|
112
86
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
87
|
+
```bash
|
|
88
|
+
pnpm --filter @ekairos/events test
|
|
89
|
+
pnpm --filter @ekairos/events test:workflow
|
|
90
|
+
```
|
package/dist/codex.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { ContextEnvironment } from "./context.config.js";
|
|
3
|
-
import type { ContextModelInit, ContextOptions, ContextReactParams, ContextShouldContinueArgs
|
|
3
|
+
import type { ContextModelInit, ContextOptions, ContextReactParams, ContextShouldContinueArgs } from "./context.engine.js";
|
|
4
|
+
import type { ContextTool } from "./context.action.js";
|
|
4
5
|
import type { ContextKey } from "./context.registry.js";
|
|
5
6
|
import type { StoredContext, ContextItem } from "./context.store.js";
|
|
6
7
|
import type { ContextInstance } from "./context.js";
|
|
@@ -49,6 +50,14 @@ export declare const codexToolInputSchema: z.ZodObject<{
|
|
|
49
50
|
fileId: z.ZodOptional<z.ZodString>;
|
|
50
51
|
}, z.core.$strip>>>;
|
|
51
52
|
}, z.core.$strip>;
|
|
53
|
+
export declare const codexToolOutputSchema: z.ZodObject<{
|
|
54
|
+
contextId: z.ZodString;
|
|
55
|
+
turnId: z.ZodString;
|
|
56
|
+
assistantText: z.ZodString;
|
|
57
|
+
reasoningText: z.ZodString;
|
|
58
|
+
diff: z.ZodString;
|
|
59
|
+
toolParts: z.ZodArray<z.ZodAny>;
|
|
60
|
+
}, z.core.$strip>;
|
|
52
61
|
export type CodexExecuteArgs<Context, Env extends CodexContextEnv = CodexContextEnv> = {
|
|
53
62
|
context: StoredContext<Context>;
|
|
54
63
|
env: Env;
|
|
@@ -61,7 +70,7 @@ export type CodexContextBuilderConfig<Context, Env extends CodexContextEnv = Cod
|
|
|
61
70
|
executeCodex: (args: CodexExecuteArgs<Context, Env>) => Promise<CodexToolOutput>;
|
|
62
71
|
narrative?: (context: StoredContext<Context>, env: Env) => Promise<string> | string;
|
|
63
72
|
system?: (context: StoredContext<Context>, env: Env) => Promise<string> | string;
|
|
64
|
-
actions?: (context: StoredContext<Context>, env: Env) => Promise<Record<string, ContextTool
|
|
73
|
+
actions?: (context: StoredContext<Context>, env: Env) => Promise<Record<string, ContextTool<Context, Env>>> | Record<string, ContextTool<Context, Env>>;
|
|
65
74
|
model?: ContextModelInit | ((context: StoredContext<Context>, env: Env) => ContextModelInit);
|
|
66
75
|
shouldContinue?: (args: ContextShouldContinueArgs<Context, Env>) => Promise<boolean> | boolean;
|
|
67
76
|
toolName?: string;
|
package/dist/codex.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { tool } from "ai";
|
|
2
1
|
import { z } from "zod";
|
|
3
|
-
import { createContext } from "./context.js";
|
|
4
|
-
import {
|
|
2
|
+
import { createContext, defineAction } from "./context.js";
|
|
3
|
+
import { didActionExecute } from "./context.action-calls.js";
|
|
5
4
|
export const DEFAULT_CODEX_TOOL_NAME = "codex";
|
|
6
5
|
export const DEFAULT_CODEX_MODEL = "openai/gpt-5.2";
|
|
7
6
|
export const codexToolInputSchema = z.object({
|
|
@@ -17,6 +16,14 @@ export const codexToolInputSchema = z.object({
|
|
|
17
16
|
}))
|
|
18
17
|
.optional(),
|
|
19
18
|
});
|
|
19
|
+
export const codexToolOutputSchema = z.object({
|
|
20
|
+
contextId: z.string(),
|
|
21
|
+
turnId: z.string(),
|
|
22
|
+
assistantText: z.string(),
|
|
23
|
+
reasoningText: z.string(),
|
|
24
|
+
diff: z.string(),
|
|
25
|
+
toolParts: z.array(z.any()),
|
|
26
|
+
});
|
|
20
27
|
function toRecord(value) {
|
|
21
28
|
if (!value || typeof value !== "object")
|
|
22
29
|
return {};
|
|
@@ -47,7 +54,7 @@ export function buildDefaultCodexNarrative(content) {
|
|
|
47
54
|
].join("\n");
|
|
48
55
|
}
|
|
49
56
|
export function didCodexToolExecute(event, toolName = DEFAULT_CODEX_TOOL_NAME) {
|
|
50
|
-
return
|
|
57
|
+
return didActionExecute(event, toolName);
|
|
51
58
|
}
|
|
52
59
|
export function createCodexContextBuilder(config) {
|
|
53
60
|
const toolName = config.toolName ?? DEFAULT_CODEX_TOOL_NAME;
|
|
@@ -59,7 +66,7 @@ export function createCodexContextBuilder(config) {
|
|
|
59
66
|
const model = config.model ??
|
|
60
67
|
((_ctx, env) => (typeof env.model === "string" && env.model.trim()) || DEFAULT_CODEX_MODEL);
|
|
61
68
|
const shouldContinue = config.shouldContinue ??
|
|
62
|
-
((args) => !
|
|
69
|
+
((args) => !didActionExecute(args.reactionEvent, toolName));
|
|
63
70
|
let builder = createContext(config.key)
|
|
64
71
|
.context(config.context)
|
|
65
72
|
.narrative(narrative)
|
|
@@ -70,10 +77,11 @@ export function createCodexContextBuilder(config) {
|
|
|
70
77
|
}
|
|
71
78
|
return {
|
|
72
79
|
...additional,
|
|
73
|
-
[toolName]:
|
|
80
|
+
[toolName]: defineAction({
|
|
74
81
|
description: toolDescription,
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
input: codexToolInputSchema,
|
|
83
|
+
output: codexToolOutputSchema,
|
|
84
|
+
execute: async ({ input }) => await config.executeCodex({
|
|
77
85
|
context: ctx,
|
|
78
86
|
env,
|
|
79
87
|
input,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ## context.action-calls.ts
|
|
3
|
+
*
|
|
4
|
+
* This module isolates the **action-call plumbing** used by `context.engine.ts`.
|
|
5
|
+
*
|
|
6
|
+
* In our runtime, provider tool calls are normalized into semantic `action` event parts.
|
|
7
|
+
* The engine needs to:
|
|
8
|
+
* - extract a normalized list of action requests from `event.content.parts`, and
|
|
9
|
+
* - merge action execution outcomes back into those parts.
|
|
10
|
+
*
|
|
11
|
+
* Keeping this logic here helps `context.engine.ts` read like orchestration, and keeps
|
|
12
|
+
* these transformations testable and reusable.
|
|
13
|
+
*/
|
|
14
|
+
import type { ContextItem } from "./context.store.js";
|
|
15
|
+
export type ContextActionCall = {
|
|
16
|
+
actionCallId: string;
|
|
17
|
+
actionName: string;
|
|
18
|
+
args: any;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Extracts action requests from an event's `parts` array.
|
|
22
|
+
*
|
|
23
|
+
* Also accepts raw AI SDK tool UI parts before persistence normalization.
|
|
24
|
+
*/
|
|
25
|
+
export declare function extractActionCallsFromParts(parts: any[] | undefined | null): ContextActionCall[];
|
|
26
|
+
/**
|
|
27
|
+
* Applies an action execution outcome to the matching action part.
|
|
28
|
+
*
|
|
29
|
+
* This does not mutate `parts` — it returns a new array.
|
|
30
|
+
*
|
|
31
|
+
* We match by action name and action call id.
|
|
32
|
+
*/
|
|
33
|
+
export declare function applyActionExecutionResultToParts(parts: any[], actionCall: Pick<ContextActionCall, "actionCallId" | "actionName">, execution: {
|
|
34
|
+
success: boolean;
|
|
35
|
+
result: any;
|
|
36
|
+
message?: string;
|
|
37
|
+
}): any[];
|
|
38
|
+
/**
|
|
39
|
+
* Returns `true` when a given action has a **settled** execution result in an event's parts.
|
|
40
|
+
*
|
|
41
|
+
* We treat an action part as "executed" once it has either:
|
|
42
|
+
* - `state: "output-available"` (success), or
|
|
43
|
+
* - `state: "output-error"` (failure).
|
|
44
|
+
*
|
|
45
|
+
* This is useful for stop/continue logic in `context.shouldContinue(...)` where you want to
|
|
46
|
+
* decide based on the persisted `reactionEvent` (not ephemeral in-memory arrays).
|
|
47
|
+
*/
|
|
48
|
+
export declare function didActionExecute(event: Pick<ContextItem, "content">, actionName: string): boolean;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ## context.action-calls.ts
|
|
3
|
+
*
|
|
4
|
+
* This module isolates the **action-call plumbing** used by `context.engine.ts`.
|
|
5
|
+
*
|
|
6
|
+
* In our runtime, provider tool calls are normalized into semantic `action` event parts.
|
|
7
|
+
* The engine needs to:
|
|
8
|
+
* - extract a normalized list of action requests from `event.content.parts`, and
|
|
9
|
+
* - merge action execution outcomes back into those parts.
|
|
10
|
+
*
|
|
11
|
+
* Keeping this logic here helps `context.engine.ts` read like orchestration, and keeps
|
|
12
|
+
* these transformations testable and reusable.
|
|
13
|
+
*/
|
|
14
|
+
import { isContextPartEnvelope, normalizePartsForPersistence, } from "./context.parts.js";
|
|
15
|
+
/**
|
|
16
|
+
* Extracts action requests from an event's `parts` array.
|
|
17
|
+
*
|
|
18
|
+
* Also accepts raw AI SDK tool UI parts before persistence normalization.
|
|
19
|
+
*/
|
|
20
|
+
export function extractActionCallsFromParts(parts) {
|
|
21
|
+
const safeParts = parts ?? [];
|
|
22
|
+
return safeParts.reduce((acc, p) => {
|
|
23
|
+
if (isContextPartEnvelope(p) && p.type === "action" && p.content.status === "started") {
|
|
24
|
+
acc.push({
|
|
25
|
+
actionCallId: p.content.actionCallId,
|
|
26
|
+
actionName: p.content.actionName,
|
|
27
|
+
args: p.content.input,
|
|
28
|
+
});
|
|
29
|
+
return acc;
|
|
30
|
+
}
|
|
31
|
+
if (typeof p?.type === "string" && p.type.startsWith("tool-")) {
|
|
32
|
+
const actionName = p.type.split("-").slice(1).join("-");
|
|
33
|
+
acc.push({ actionCallId: p.toolCallId, actionName, args: p.input });
|
|
34
|
+
}
|
|
35
|
+
return acc;
|
|
36
|
+
}, []);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Applies an action execution outcome to the matching action part.
|
|
40
|
+
*
|
|
41
|
+
* This does not mutate `parts` — it returns a new array.
|
|
42
|
+
*
|
|
43
|
+
* We match by action name and action call id.
|
|
44
|
+
*/
|
|
45
|
+
export function applyActionExecutionResultToParts(parts, actionCall, execution) {
|
|
46
|
+
const normalized = normalizePartsForPersistence(parts);
|
|
47
|
+
const next = [];
|
|
48
|
+
let insertedResult = false;
|
|
49
|
+
for (const part of normalized) {
|
|
50
|
+
next.push(part);
|
|
51
|
+
if (part.type !== "action" || part.content.status !== "started") {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (part.content.actionCallId !== actionCall.actionCallId ||
|
|
55
|
+
part.content.actionName !== actionCall.actionName) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
next.push(execution.success
|
|
59
|
+
? {
|
|
60
|
+
type: "action",
|
|
61
|
+
content: {
|
|
62
|
+
status: "completed",
|
|
63
|
+
actionCallId: actionCall.actionCallId,
|
|
64
|
+
actionName: actionCall.actionName,
|
|
65
|
+
output: execution.result,
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
: {
|
|
69
|
+
type: "action",
|
|
70
|
+
content: {
|
|
71
|
+
status: "failed",
|
|
72
|
+
actionCallId: actionCall.actionCallId,
|
|
73
|
+
actionName: actionCall.actionName,
|
|
74
|
+
error: {
|
|
75
|
+
message: String(execution.message || "Error"),
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
insertedResult = true;
|
|
80
|
+
}
|
|
81
|
+
if (!insertedResult) {
|
|
82
|
+
next.push(execution.success
|
|
83
|
+
? {
|
|
84
|
+
type: "action",
|
|
85
|
+
content: {
|
|
86
|
+
status: "completed",
|
|
87
|
+
actionCallId: actionCall.actionCallId,
|
|
88
|
+
actionName: actionCall.actionName,
|
|
89
|
+
output: execution.result,
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
: {
|
|
93
|
+
type: "action",
|
|
94
|
+
content: {
|
|
95
|
+
status: "failed",
|
|
96
|
+
actionCallId: actionCall.actionCallId,
|
|
97
|
+
actionName: actionCall.actionName,
|
|
98
|
+
error: {
|
|
99
|
+
message: String(execution.message || "Error"),
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return next;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Returns `true` when a given action has a **settled** execution result in an event's parts.
|
|
108
|
+
*
|
|
109
|
+
* We treat an action part as "executed" once it has either:
|
|
110
|
+
* - `state: "output-available"` (success), or
|
|
111
|
+
* - `state: "output-error"` (failure).
|
|
112
|
+
*
|
|
113
|
+
* This is useful for stop/continue logic in `context.shouldContinue(...)` where you want to
|
|
114
|
+
* decide based on the persisted `reactionEvent` (not ephemeral in-memory arrays).
|
|
115
|
+
*/
|
|
116
|
+
export function didActionExecute(event, actionName) {
|
|
117
|
+
const parts = (event.content.parts ?? []).flatMap((part) => isContextPartEnvelope(part) ? [part] : normalizePartsForPersistence([part]));
|
|
118
|
+
return parts.some((p) => (p.type === "action" &&
|
|
119
|
+
p.content.actionName === actionName &&
|
|
120
|
+
(p.content.status === "completed" || p.content.status === "failed")) ||
|
|
121
|
+
(p.type === `tool-${actionName}` &&
|
|
122
|
+
(p.state === "output-available" || p.state === "output-error")));
|
|
123
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { DomainLike } from "@ekairos/domain";
|
|
2
|
+
import type { z } from "zod";
|
|
3
|
+
import type { ContextEnvironment } from "./context.config.js";
|
|
4
|
+
import type { ContextToolExecuteContext } from "./context.engine.js";
|
|
5
|
+
import type { ContextRuntime } from "./context.runtime.js";
|
|
6
|
+
import { eventsDomain } from "./schema.js";
|
|
7
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
8
|
+
export type ContextActionSchema = z.ZodType;
|
|
9
|
+
export type ContextActionBase = {
|
|
10
|
+
type?: "function";
|
|
11
|
+
description?: string;
|
|
12
|
+
providerOptions?: unknown;
|
|
13
|
+
auto?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type ContextProviderDefinedAction = {
|
|
16
|
+
type: "provider-defined";
|
|
17
|
+
id: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
args?: Record<string, unknown>;
|
|
20
|
+
auto?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export type ContextActionExecuteParams<TInput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = ContextToolExecuteContext<Context, Env, RequiredDomain, Runtime> & {
|
|
23
|
+
input: z.output<TInput>;
|
|
24
|
+
};
|
|
25
|
+
export type DefineContextActionExecute<TInput extends ContextActionSchema, TOutput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = (params: ContextActionExecuteParams<TInput, Context, Env, RequiredDomain, Runtime>) => MaybePromise<z.output<TOutput>>;
|
|
26
|
+
export type ContextActionExecute<TInput extends ContextActionSchema, TOutput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = DefineContextActionExecute<TInput, TOutput, Context, Env, RequiredDomain, Runtime>;
|
|
27
|
+
export type LegacyContextActionExecute<TInput extends ContextActionSchema, TOutput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = (input: z.output<TInput>, context: ContextToolExecuteContext<Context, Env, RequiredDomain, Runtime>) => MaybePromise<z.output<TOutput>>;
|
|
28
|
+
export type DefineContextActionDefinition<TInput extends ContextActionSchema, TOutput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = ContextActionBase & {
|
|
29
|
+
input: TInput;
|
|
30
|
+
output: TOutput;
|
|
31
|
+
execute: DefineContextActionExecute<TInput, TOutput, Context, Env, RequiredDomain, Runtime>;
|
|
32
|
+
};
|
|
33
|
+
export type LegacyContextActionDefinition<TInput extends ContextActionSchema, TOutput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = ContextActionBase & {
|
|
34
|
+
input: TInput;
|
|
35
|
+
output: TOutput;
|
|
36
|
+
execute: LegacyContextActionExecute<TInput, TOutput, Context, Env, RequiredDomain, Runtime>;
|
|
37
|
+
};
|
|
38
|
+
export type ContextActionDefinition<TInput extends ContextActionSchema, TOutput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = DefineContextActionDefinition<TInput, TOutput, Context, Env, RequiredDomain, Runtime>;
|
|
39
|
+
export type ContextAction<TInput extends ContextActionSchema = ContextActionSchema, TOutput extends ContextActionSchema = ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = ContextActionBase & {
|
|
40
|
+
input: TInput;
|
|
41
|
+
output: TOutput;
|
|
42
|
+
inputSchema: TInput;
|
|
43
|
+
outputSchema: TOutput;
|
|
44
|
+
execute: LegacyContextActionExecute<TInput, TOutput, Context, Env, RequiredDomain, Runtime>;
|
|
45
|
+
};
|
|
46
|
+
export type AnyContextAction = ContextAction<ContextActionSchema, ContextActionSchema, any, any, any, any>;
|
|
47
|
+
export type ContextTool<Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>> = ContextAction<ContextActionSchema, ContextActionSchema, Context, Env, RequiredDomain, Runtime> | ContextProviderDefinedAction;
|
|
48
|
+
export type ContextActionInput<TAction> = TAction extends ContextAction<infer TInput, any, any, any> ? z.output<TInput> : never;
|
|
49
|
+
export type ContextActionOutput<TAction> = TAction extends ContextAction<any, infer TOutput, any, any> ? z.output<TOutput> : never;
|
|
50
|
+
export declare function defineAction<TInput extends ContextActionSchema, TOutput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>>(definition: DefineContextActionDefinition<TInput, TOutput, Context, Env, RequiredDomain, Runtime>): ContextAction<TInput, TOutput, Context, Env, RequiredDomain, Runtime>;
|
|
51
|
+
/**
|
|
52
|
+
* @deprecated Use defineAction().
|
|
53
|
+
*/
|
|
54
|
+
export declare function action<TInput extends ContextActionSchema, TOutput extends ContextActionSchema, Context = any, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainLike = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>>(definition: LegacyContextActionDefinition<TInput, TOutput, Context, Env, RequiredDomain, Runtime>): ContextAction<TInput, TOutput, Context, Env, RequiredDomain, Runtime>;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function createContextAction(definition, invoke) {
|
|
2
|
+
const execute = async (input, context) => {
|
|
3
|
+
const parsedInput = definition.input.parse(input);
|
|
4
|
+
const result = await invoke(parsedInput, context);
|
|
5
|
+
return definition.output.parse(result);
|
|
6
|
+
};
|
|
7
|
+
return {
|
|
8
|
+
...definition,
|
|
9
|
+
inputSchema: definition.input,
|
|
10
|
+
outputSchema: definition.output,
|
|
11
|
+
execute,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function defineAction(definition) {
|
|
15
|
+
return createContextAction(definition, async (input, context) => await definition.execute({
|
|
16
|
+
...context,
|
|
17
|
+
input,
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated Use defineAction().
|
|
22
|
+
*/
|
|
23
|
+
export function action(definition) {
|
|
24
|
+
return createContextAction(definition, async (input, context) => await definition.execute(input, context));
|
|
25
|
+
}
|