@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.
Files changed (45) hide show
  1. package/README.md +5 -3
  2. package/dist/codex.d.ts +11 -2
  3. package/dist/codex.js +13 -5
  4. package/dist/context.action.d.ts +55 -0
  5. package/dist/context.action.js +25 -0
  6. package/dist/context.builder.d.ts +52 -42
  7. package/dist/context.builder.js +29 -24
  8. package/dist/context.d.ts +2 -1
  9. package/dist/context.engine.d.ts +50 -47
  10. package/dist/context.engine.js +222 -173
  11. package/dist/context.events.js +28 -87
  12. package/dist/context.js +1 -0
  13. package/dist/context.part-identity.d.ts +40 -0
  14. package/dist/context.part-identity.js +268 -0
  15. package/dist/context.parts.d.ts +389 -164
  16. package/dist/context.parts.js +235 -224
  17. package/dist/context.registry.d.ts +1 -1
  18. package/dist/context.runtime.d.ts +10 -4
  19. package/dist/context.runtime.js +7 -1
  20. package/dist/context.step-stream.d.ts +16 -2
  21. package/dist/context.step-stream.js +58 -16
  22. package/dist/context.stream.d.ts +4 -0
  23. package/dist/context.stream.js +23 -1
  24. package/dist/context.toolcalls.d.ts +8 -20
  25. package/dist/context.toolcalls.js +61 -55
  26. package/dist/index.d.ts +8 -4
  27. package/dist/index.js +5 -3
  28. package/dist/reactors/ai-sdk.chunk-map.js +27 -0
  29. package/dist/reactors/ai-sdk.reactor.d.ts +8 -9
  30. package/dist/reactors/ai-sdk.reactor.js +2 -5
  31. package/dist/reactors/ai-sdk.step.d.ts +2 -3
  32. package/dist/reactors/ai-sdk.step.js +10 -7
  33. package/dist/reactors/scripted.reactor.d.ts +7 -4
  34. package/dist/reactors/types.d.ts +8 -8
  35. package/dist/schema.d.ts +273 -2
  36. package/dist/schema.js +1 -1
  37. package/dist/steps/store.steps.d.ts +51 -12
  38. package/dist/steps/store.steps.js +137 -0
  39. package/dist/steps/stream.steps.d.ts +15 -0
  40. package/dist/steps/stream.steps.js +16 -5
  41. package/dist/steps/trace.steps.d.ts +4 -4
  42. package/dist/steps/trace.steps.js +21 -6
  43. package/dist/tools-to-model-tools.d.ts +4 -2
  44. package/dist/tools-to-model-tools.js +30 -11
  45. package/package.json +7 -6
@@ -1,4 +1,5 @@
1
1
  import { isContextStreamChunkType, } from "./context.contract.js";
2
+ import { assertValidContextPartChunkIdentity } from "./context.part-identity.js";
2
3
  export const CONTEXT_STEP_STREAM_VERSION = 1;
3
4
  function assertObject(value, label) {
4
5
  if (!value || typeof value !== "object") {
@@ -15,43 +16,84 @@ function assertNumber(value, label) {
15
16
  throw new Error(`Invalid ${label}: expected number.`);
16
17
  }
17
18
  }
19
+ function assertPositiveInteger(value, label) {
20
+ assertNumber(value, label);
21
+ if (!Number.isSafeInteger(value) || value < 1) {
22
+ throw new Error(`Invalid ${label}: expected positive integer.`);
23
+ }
24
+ }
25
+ function assertIsoDateString(value, label) {
26
+ assertString(value, label);
27
+ if (Number.isNaN(Date.parse(value))) {
28
+ throw new Error(`Invalid ${label}: expected ISO date string.`);
29
+ }
30
+ }
18
31
  function assertOptionalString(value, label) {
19
32
  if (typeof value === "undefined")
20
33
  return;
21
34
  assertString(value, label);
22
35
  }
23
36
  export function createContextStepStreamChunk(params) {
24
- return {
37
+ const chunk = {
25
38
  version: CONTEXT_STEP_STREAM_VERSION,
26
39
  at: params.at ?? new Date().toISOString(),
27
40
  sequence: params.sequence,
28
41
  chunkType: params.chunkType,
42
+ partId: params.partId,
43
+ providerPartId: params.providerPartId,
44
+ partType: params.partType,
45
+ partSlot: params.partSlot,
29
46
  provider: params.provider,
30
47
  providerChunkType: params.providerChunkType,
31
48
  actionRef: params.actionRef,
32
49
  data: params.data,
33
50
  raw: params.raw,
34
51
  };
52
+ validateContextStepStreamChunk(chunk, {
53
+ stepId: params.stepId,
54
+ label: "context step stream chunk",
55
+ });
56
+ return chunk;
35
57
  }
36
- export function parseContextStepStreamChunk(value) {
37
- const parsed = typeof value === "string" ? JSON.parse(value) : value;
38
- assertObject(parsed, "context step stream chunk");
39
- assertNumber(parsed.version, "context step stream chunk.version");
40
- if (parsed.version !== CONTEXT_STEP_STREAM_VERSION) {
41
- throw new Error(`Unsupported context step stream chunk version: ${String(parsed.version)}`);
58
+ export function validateContextStepStreamChunk(value, options = {}) {
59
+ const label = options.label ?? "context step stream chunk";
60
+ assertObject(value, label);
61
+ assertNumber(value.version, `${label}.version`);
62
+ if (value.version !== CONTEXT_STEP_STREAM_VERSION) {
63
+ throw new Error(`Unsupported ${label}.version: ${String(value.version)}`);
42
64
  }
43
- assertString(parsed.at, "context step stream chunk.at");
44
- assertNumber(parsed.sequence, "context step stream chunk.sequence");
45
- assertString(parsed.chunkType, "context step stream chunk.chunkType");
46
- if (!isContextStreamChunkType(parsed.chunkType)) {
47
- throw new Error(`Invalid context step stream chunk.chunkType: ${String(parsed.chunkType)}`);
65
+ assertIsoDateString(value.at, `${label}.at`);
66
+ assertPositiveInteger(value.sequence, `${label}.sequence`);
67
+ assertString(value.chunkType, `${label}.chunkType`);
68
+ if (!isContextStreamChunkType(value.chunkType)) {
69
+ throw new Error(`Invalid ${label}.chunkType: ${String(value.chunkType)}`);
48
70
  }
49
- assertOptionalString(parsed.provider, "context step stream chunk.provider");
50
- assertOptionalString(parsed.providerChunkType, "context step stream chunk.providerChunkType");
51
- assertOptionalString(parsed.actionRef, "context step stream chunk.actionRef");
71
+ assertOptionalString(value.partId, `${label}.partId`);
72
+ assertOptionalString(value.providerPartId, `${label}.providerPartId`);
73
+ assertOptionalString(value.partType, `${label}.partType`);
74
+ assertOptionalString(value.partSlot, `${label}.partSlot`);
75
+ assertOptionalString(value.provider, `${label}.provider`);
76
+ assertOptionalString(value.providerChunkType, `${label}.providerChunkType`);
77
+ assertOptionalString(value.actionRef, `${label}.actionRef`);
78
+ assertValidContextPartChunkIdentity({
79
+ label,
80
+ stepId: options.stepId,
81
+ chunkType: value.chunkType,
82
+ partId: value.partId,
83
+ provider: value.provider,
84
+ providerPartId: value.providerPartId,
85
+ partType: value.partType,
86
+ partSlot: value.partSlot,
87
+ actionRef: value.actionRef,
88
+ });
89
+ }
90
+ export function parseContextStepStreamChunk(value, options = {}) {
91
+ const parsed = typeof value === "string" ? JSON.parse(value) : value;
92
+ validateContextStepStreamChunk(parsed, options);
52
93
  return parsed;
53
94
  }
54
- export function encodeContextStepStreamChunk(chunk) {
95
+ export function encodeContextStepStreamChunk(chunk, options = {}) {
96
+ validateContextStepStreamChunk(chunk, options);
55
97
  return `${JSON.stringify(chunk)}\n`;
56
98
  }
57
99
  export function contextStreamByteLength(value) {
@@ -129,6 +129,10 @@ export type ChunkEmittedEvent = ContextStreamEventBase & {
129
129
  stepId?: string;
130
130
  itemId?: string;
131
131
  partKey?: string;
132
+ partId?: string;
133
+ providerPartId?: string;
134
+ partType?: string;
135
+ partSlot?: string;
132
136
  actionRef?: string;
133
137
  provider?: string;
134
138
  providerChunkType?: string;
@@ -1,4 +1,5 @@
1
1
  import { isContextStreamChunkType } from "./context.contract.js";
2
+ import { assertValidContextPartChunkIdentity } from "./context.part-identity.js";
2
3
  function assertObject(value, label) {
3
4
  if (!value || typeof value !== "object") {
4
5
  throw new Error(`Invalid ${label}: expected object.`);
@@ -14,6 +15,12 @@ function assertNumber(value, label) {
14
15
  throw new Error(`Invalid ${label}: expected number.`);
15
16
  }
16
17
  }
18
+ function assertPositiveInteger(value, label) {
19
+ assertNumber(value, label);
20
+ if (!Number.isSafeInteger(value) || value < 1) {
21
+ throw new Error(`Invalid ${label}: expected positive integer.`);
22
+ }
23
+ }
17
24
  function assertOptionalString(value, label) {
18
25
  if (value !== undefined) {
19
26
  assertString(value, label);
@@ -121,10 +128,25 @@ export function parseContextStreamEvent(value) {
121
128
  assertOptionalString(value.stepId, `${type}.stepId`);
122
129
  assertOptionalString(value.itemId, `${type}.itemId`);
123
130
  assertOptionalString(value.partKey, `${type}.partKey`);
131
+ assertOptionalString(value.partId, `${type}.partId`);
132
+ assertOptionalString(value.providerPartId, `${type}.providerPartId`);
133
+ assertOptionalString(value.partType, `${type}.partType`);
134
+ assertOptionalString(value.partSlot, `${type}.partSlot`);
124
135
  assertOptionalString(value.actionRef, `${type}.actionRef`);
125
136
  assertOptionalString(value.provider, `${type}.provider`);
126
137
  assertOptionalString(value.providerChunkType, `${type}.providerChunkType`);
127
- assertOptionalNumber(value.sequence, `${type}.sequence`);
138
+ assertPositiveInteger(value.sequence, `${type}.sequence`);
139
+ assertValidContextPartChunkIdentity({
140
+ label: type,
141
+ chunkType: value.chunkType,
142
+ stepId: typeof value.stepId === "string" ? value.stepId : undefined,
143
+ partId: typeof value.partId === "string" ? value.partId : undefined,
144
+ provider: typeof value.provider === "string" ? value.provider : undefined,
145
+ providerPartId: typeof value.providerPartId === "string" ? value.providerPartId : undefined,
146
+ partType: typeof value.partType === "string" ? value.partType : undefined,
147
+ partSlot: typeof value.partSlot === "string" ? value.partSlot : undefined,
148
+ actionRef: typeof value.actionRef === "string" ? value.actionRef : undefined,
149
+ });
128
150
  return value;
129
151
  }
130
152
  default:
@@ -1,13 +1,12 @@
1
1
  /**
2
2
  * ## context.toolcalls.ts
3
3
  *
4
- * This module isolates the **tool-call plumbing** used by `context.engine.ts`.
4
+ * This module isolates the **action-call plumbing** used by `context.engine.ts`.
5
5
  *
6
- * In our runtime, tool calls are represented as **event parts** produced by the AI SDK.
6
+ * In our runtime, model tool calls are normalized into semantic `action` event parts.
7
7
  * The engine needs to:
8
- * - extract a normalized list of tool calls from `event.content.parts`, and
9
- * - merge tool execution outcomes back into those parts (so the persisted event reflects
10
- * `output-available` / `output-error`, etc.).
8
+ * - extract a normalized list of action requests from `event.content.parts`, and
9
+ * - merge action execution outcomes back into those parts.
11
10
  *
12
11
  * Keeping this logic here helps `context.engine.ts` read like orchestration, and keeps
13
12
  * these transformations testable and reusable.
@@ -19,28 +18,17 @@ export type ToolCall = {
19
18
  args: any;
20
19
  };
21
20
  /**
22
- * Extracts tool calls from an event's `parts` array.
21
+ * Extracts action requests from an event's `parts` array.
23
22
  *
24
- * Expected part shape (loosely):
25
- * - `type`: string like `"tool-<toolName>"`
26
- * - `toolCallId`: string
27
- * - `input`: any (tool args)
28
- *
29
- * We intentionally treat the input as `any` because the part schema is produced by the AI SDK.
23
+ * Also accepts raw AI SDK tool UI parts before persistence normalization.
30
24
  */
31
25
  export declare function extractToolCallsFromParts(parts: any[] | undefined | null): ToolCall[];
32
26
  /**
33
- * Applies a tool execution outcome to the matching tool part.
27
+ * Applies an action execution outcome to the matching action part.
34
28
  *
35
29
  * This does not mutate `parts` — it returns a new array.
36
30
  *
37
- * We match the tool part by:
38
- * - `type === "tool-<toolName>"` and
39
- * - `toolCallId` equality
40
- *
41
- * Then we set:
42
- * - on success: `{ state: "output-available", output: <result> }`
43
- * - on failure: `{ state: "output-error", errorText: <message> }`
31
+ * We match by action name and action call id.
44
32
  */
45
33
  export declare function applyToolExecutionResultToParts(parts: any[], toolCall: Pick<ToolCall, "toolCallId" | "toolName">, execution: {
46
34
  success: boolean;
@@ -1,38 +1,30 @@
1
1
  /**
2
2
  * ## context.toolcalls.ts
3
3
  *
4
- * This module isolates the **tool-call plumbing** used by `context.engine.ts`.
4
+ * This module isolates the **action-call plumbing** used by `context.engine.ts`.
5
5
  *
6
- * In our runtime, tool calls are represented as **event parts** produced by the AI SDK.
6
+ * In our runtime, model tool calls are normalized into semantic `action` event parts.
7
7
  * The engine needs to:
8
- * - extract a normalized list of tool calls from `event.content.parts`, and
9
- * - merge tool execution outcomes back into those parts (so the persisted event reflects
10
- * `output-available` / `output-error`, etc.).
8
+ * - extract a normalized list of action requests from `event.content.parts`, and
9
+ * - merge action execution outcomes back into those parts.
11
10
  *
12
11
  * Keeping this logic here helps `context.engine.ts` read like orchestration, and keeps
13
12
  * these transformations testable and reusable.
14
13
  */
15
- import { isContextPartEnvelope, normalizePartsForPersistence, normalizeToolResultContentToBlocks, } from "./context.parts.js";
14
+ import { isContextPartEnvelope, normalizePartsForPersistence, } from "./context.parts.js";
16
15
  /**
17
- * Extracts tool calls from an event's `parts` array.
16
+ * Extracts action requests from an event's `parts` array.
18
17
  *
19
- * Expected part shape (loosely):
20
- * - `type`: string like `"tool-<toolName>"`
21
- * - `toolCallId`: string
22
- * - `input`: any (tool args)
23
- *
24
- * We intentionally treat the input as `any` because the part schema is produced by the AI SDK.
18
+ * Also accepts raw AI SDK tool UI parts before persistence normalization.
25
19
  */
26
20
  export function extractToolCallsFromParts(parts) {
27
21
  const safeParts = parts ?? [];
28
22
  return safeParts.reduce((acc, p) => {
29
- if (isContextPartEnvelope(p) && p.type === "tool-call") {
30
- const firstContent = Array.isArray(p.content) ? p.content[0] : undefined;
31
- const args = firstContent && firstContent.type === "json" ? firstContent.value : p.content;
23
+ if (isContextPartEnvelope(p) && p.type === "action" && p.content.status === "started") {
32
24
  acc.push({
33
- toolCallId: p.toolCallId,
34
- toolName: p.toolName,
35
- args,
25
+ toolCallId: p.content.actionCallId,
26
+ toolName: p.content.actionName,
27
+ args: p.content.input,
36
28
  });
37
29
  return acc;
38
30
  }
@@ -44,56 +36,70 @@ export function extractToolCallsFromParts(parts) {
44
36
  }, []);
45
37
  }
46
38
  /**
47
- * Applies a tool execution outcome to the matching tool part.
39
+ * Applies an action execution outcome to the matching action part.
48
40
  *
49
41
  * This does not mutate `parts` — it returns a new array.
50
42
  *
51
- * We match the tool part by:
52
- * - `type === "tool-<toolName>"` and
53
- * - `toolCallId` equality
54
- *
55
- * Then we set:
56
- * - on success: `{ state: "output-available", output: <result> }`
57
- * - on failure: `{ state: "output-error", errorText: <message> }`
43
+ * We match by action name and action call id.
58
44
  */
59
45
  export function applyToolExecutionResultToParts(parts, toolCall, execution) {
60
46
  const normalized = normalizePartsForPersistence(parts);
61
47
  const next = [];
62
48
  let insertedResult = false;
63
- const resultContent = execution.success
64
- ? normalizeToolResultContentToBlocks(execution.result)
65
- : [
66
- {
67
- type: "text",
68
- text: String(execution.message || "Error"),
69
- },
70
- ];
71
49
  for (const part of normalized) {
72
50
  next.push(part);
73
- if (part.type !== "tool-call") {
51
+ if (part.type !== "action" || part.content.status !== "started") {
74
52
  continue;
75
53
  }
76
- if (part.toolCallId !== toolCall.toolCallId ||
77
- part.toolName !== toolCall.toolName) {
54
+ if (part.content.actionCallId !== toolCall.toolCallId ||
55
+ part.content.actionName !== toolCall.toolName) {
78
56
  continue;
79
57
  }
80
- next.push({
81
- type: "tool-result",
82
- toolCallId: toolCall.toolCallId,
83
- toolName: toolCall.toolName,
84
- state: execution.success ? "output-available" : "output-error",
85
- content: resultContent,
86
- });
58
+ next.push(execution.success
59
+ ? {
60
+ type: "action",
61
+ content: {
62
+ status: "completed",
63
+ actionCallId: toolCall.toolCallId,
64
+ actionName: toolCall.toolName,
65
+ output: execution.result,
66
+ },
67
+ }
68
+ : {
69
+ type: "action",
70
+ content: {
71
+ status: "failed",
72
+ actionCallId: toolCall.toolCallId,
73
+ actionName: toolCall.toolName,
74
+ error: {
75
+ message: String(execution.message || "Error"),
76
+ },
77
+ },
78
+ });
87
79
  insertedResult = true;
88
80
  }
89
81
  if (!insertedResult) {
90
- next.push({
91
- type: "tool-result",
92
- toolCallId: toolCall.toolCallId,
93
- toolName: toolCall.toolName,
94
- state: execution.success ? "output-available" : "output-error",
95
- content: resultContent,
96
- });
82
+ next.push(execution.success
83
+ ? {
84
+ type: "action",
85
+ content: {
86
+ status: "completed",
87
+ actionCallId: toolCall.toolCallId,
88
+ actionName: toolCall.toolName,
89
+ output: execution.result,
90
+ },
91
+ }
92
+ : {
93
+ type: "action",
94
+ content: {
95
+ status: "failed",
96
+ actionCallId: toolCall.toolCallId,
97
+ actionName: toolCall.toolName,
98
+ error: {
99
+ message: String(execution.message || "Error"),
100
+ },
101
+ },
102
+ });
97
103
  }
98
104
  return next;
99
105
  }
@@ -109,9 +115,9 @@ export function applyToolExecutionResultToParts(parts, toolCall, execution) {
109
115
  */
110
116
  export function didToolExecute(event, toolName) {
111
117
  const parts = (event.content.parts ?? []).flatMap((part) => isContextPartEnvelope(part) ? [part] : normalizePartsForPersistence([part]));
112
- return parts.some((p) => (p.type === "tool-result" &&
113
- p.toolName === toolName &&
114
- (p.state === "output-available" || p.state === "output-error")) ||
118
+ return parts.some((p) => (p.type === "action" &&
119
+ p.content.actionName === toolName &&
120
+ (p.content.status === "completed" || p.content.status === "failed")) ||
115
121
  (p.type === `tool-${toolName}` &&
116
122
  (p.state === "output-available" || p.state === "output-error")));
117
123
  }
package/dist/index.d.ts CHANGED
@@ -1,18 +1,22 @@
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";
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, defineAction, action, type RegistrableContextBuilder, type ContextReactParams, type ContextDirectReactParams, type ContextDurableReactParams, type ContextReactResult, type ContextReactBase, type ContextReactFinalResult, type ContextDirectRun, type ContextReactRun, type ContextWorkflowRun, type ContextDurableWorkflowPayload, type ContextDurableWorkflowFunction, type ContextModelInit, type ContextTool, type ContextAction, type ContextActionBase, type ContextActionExecuteParams, type AnyContextAction, type ContextActionDefinition, type DefineContextActionDefinition, type DefineContextActionExecute, type LegacyContextActionDefinition, type LegacyContextActionExecute, type ContextActionExecute, type ContextActionInput, type ContextActionOutput, type ContextProviderDefinedAction, type ContextActionSchema, 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";
5
5
  export { eventsDomain } from "./schema.js";
6
6
  export { didToolExecute, extractToolCallsFromParts } from "./context.toolcalls.js";
7
- export { contextPartSchema, contextPartEnvelopeSchema, contextPartContentSchema, isContextPartEnvelope, parseContextPartEnvelope, normalizePartsForPersistence, } from "./context.parts.js";
8
- export type { ContextPart, ContextPartEnvelope, ContextPartContent, } from "./context.parts.js";
7
+ export { actionsToActionSpecs, actionSpecToAiSdkTool, type SerializableActionSpec, type SerializableFunctionActionSpec, type SerializableProviderDefinedActionSpec, } from "./tools-to-model-tools.js";
8
+ export { reactorMetadataSchema, contextPartSchema, contextPartEnvelopeSchema, contextPartContentSchema, contextMessagePartSchema, contextReasoningPartSchema, contextSourcePartSchema, contextActionPartSchema, contextEnginePartSchema, createContextPartSchema, parseContextPart, isContextPartEnvelope, parseContextPartEnvelope, normalizePartsForPersistence, } from "./context.parts.js";
9
+ export type { ReactorMetadata, ContextEnginePart, ContextActionPart, ContextActionStartedPart, ContextActionCompletedPart, ContextActionFailedPart, ContextPartActionMap, ContextPart, ContextPartEnvelope, ContextPartContent, ContextInlineContent, } from "./context.parts.js";
9
10
  export { INPUT_ITEM_TYPE, INPUT_TEXT_ITEM_TYPE, OUTPUT_ITEM_TYPE, WEB_CHANNEL, AGENT_CHANNEL, EMAIL_CHANNEL, createUserItemFromUIMessages, createAssistantItemFromUIMessages, convertToUIMessage, convertItemToModelMessages, convertItemsToModelMessages, convertModelMessageToItem, isContextOutputPart, normalizeContextOutputPart, type ResponseMessage, type ContextOutputPart, type ContextOutputContentPart, } from "./context.events.js";
10
11
  export { CONTEXT_STATUSES, EXECUTION_STATUSES, STEP_STATUSES, STEP_KINDS, ITEM_STATUSES, ITEM_TYPES, CHANNELS, TRACE_EVENT_KINDS, CONTEXT_STREAM_CHUNK_TYPES, STREAM_LIFECYCLE_CHUNK_TYPES, STREAM_TEXT_CHUNK_TYPES, STREAM_REASONING_CHUNK_TYPES, STREAM_ACTION_CHUNK_TYPES, STREAM_SOURCE_CHUNK_TYPES, STREAM_METADATA_CHUNK_TYPES, STREAM_ERROR_CHUNK_TYPES, CONTEXT_TRANSITIONS, EXECUTION_TRANSITIONS, STEP_TRANSITIONS, ITEM_TRANSITIONS, canContextTransition, canExecutionTransition, canStepTransition, canItemTransition, assertContextTransition, assertExecutionTransition, assertStepTransition, assertItemTransition, isContextStreamChunkType, assertContextPartKey, } from "./context.contract.js";
11
12
  export type { Transition, ContextStatus, ExecutionStatus, StepStatus, StepKind, ItemStatus, ItemType, Channel, TraceEventKind, ContextStreamChunkType, ContextTransition, ExecutionTransition, StepTransition, ItemTransition, } from "./context.contract.js";
12
13
  export { DEFAULT_CODEX_TOOL_NAME, DEFAULT_CODEX_MODEL, codexToolInputSchema, buildDefaultCodexNarrative, didCodexToolExecute, createCodexContextBuilder, type CodexContextRuntimeMode, type CodexContextReasoningLevel, type CodexContextRuntime, type CodexContextEnv, type CodexToolInput, type CodexToolOutput, type CodexExecuteArgs, type CodexContextBuilderConfig, type CodexContextBuilder, } from "./codex.js";
13
14
  export { useContext, type ContextSnapshot, type ContextStreamChunk, type UseContextOptions, } from "./react.js";
14
15
  export { parseContextStreamEvent, assertContextStreamTransitions, validateContextStreamTimeline, } from "./context.stream.js";
15
- export { CONTEXT_STEP_STREAM_VERSION, createContextStepStreamChunk, parseContextStepStreamChunk, encodeContextStepStreamChunk, } from "./context.step-stream.js";
16
+ export { CONTEXT_STEP_STREAM_VERSION, createContextStepStreamChunk, validateContextStepStreamChunk, parseContextStepStreamChunk, encodeContextStepStreamChunk, } from "./context.step-stream.js";
17
+ export type { ContextStepStreamChunkValidationOptions, } from "./context.step-stream.js";
18
+ export { CONTEXT_PART_ID_NAMESPACE, CONTEXT_PART_UUID_RE, CONTEXT_STREAM_PART_TYPES, assertValidContextPartChunkIdentity, resolveContextPartChunkDescriptor, resolveContextPartChunkIdentity, resolveContextPartId, resolveContextStreamPartSlot, resolveContextStreamPartType, uuidV5, } from "./context.part-identity.js";
19
+ export type { ContextPartChunkDescriptor, ContextPartChunkIdentity, ContextPartChunkIdentityInput, ContextPartChunkValidationInput, ContextStreamPartSlot, ContextStreamPartType, } from "./context.part-identity.js";
16
20
  export type { ContextStreamEvent, ContextCreatedEvent, ContextResolvedEvent, ContextStatusChangedEvent, ContextContentUpdatedEvent, ExecutionCreatedEvent, ExecutionCompletedEvent, ExecutionFailedEvent, ItemCreatedEvent, ItemUpdatedEvent, ItemPendingEvent, ItemCompletedEvent, StepCreatedEvent, StepUpdatedEvent, StepCompletedEvent, StepFailedEvent, PartCreatedEvent, PartUpdatedEvent, ChunkEmittedEvent, } from "./context.stream.js";
17
21
  export type { ContextStepStreamChunk } from "./context.step-stream.js";
18
22
  export type { ContextSkillPackage, ContextSkillPackageFile } from "./context.skill.js";
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
- export { context, createContext, createAiSdkReactor, createScriptedReactor, ContextEngine, runContextReactionDirect, } from "./context.js";
1
+ export { context, createContext, createAiSdkReactor, createScriptedReactor, ContextEngine, defineAction, action, runContextReactionDirect, } from "./context.js";
2
2
  export { registerContext, getContext, getContextFactory, hasContext, listContexts, } from "./context.registry.js";
3
3
  export { eventsDomain } from "./schema.js";
4
4
  export { didToolExecute, extractToolCallsFromParts } from "./context.toolcalls.js";
5
- export { contextPartSchema, contextPartEnvelopeSchema, contextPartContentSchema, isContextPartEnvelope, parseContextPartEnvelope, normalizePartsForPersistence, } from "./context.parts.js";
5
+ export { actionsToActionSpecs, actionSpecToAiSdkTool, } from "./tools-to-model-tools.js";
6
+ export { reactorMetadataSchema, contextPartSchema, contextPartEnvelopeSchema, contextPartContentSchema, contextMessagePartSchema, contextReasoningPartSchema, contextSourcePartSchema, contextActionPartSchema, contextEnginePartSchema, createContextPartSchema, parseContextPart, isContextPartEnvelope, parseContextPartEnvelope, normalizePartsForPersistence, } from "./context.parts.js";
6
7
  export { INPUT_ITEM_TYPE, INPUT_TEXT_ITEM_TYPE, OUTPUT_ITEM_TYPE, WEB_CHANNEL, AGENT_CHANNEL, EMAIL_CHANNEL, createUserItemFromUIMessages, createAssistantItemFromUIMessages, convertToUIMessage, convertItemToModelMessages, convertItemsToModelMessages, convertModelMessageToItem, isContextOutputPart, normalizeContextOutputPart, } from "./context.events.js";
7
8
  export { CONTEXT_STATUSES, EXECUTION_STATUSES, STEP_STATUSES, STEP_KINDS, ITEM_STATUSES, ITEM_TYPES, CHANNELS, TRACE_EVENT_KINDS, CONTEXT_STREAM_CHUNK_TYPES, STREAM_LIFECYCLE_CHUNK_TYPES, STREAM_TEXT_CHUNK_TYPES, STREAM_REASONING_CHUNK_TYPES, STREAM_ACTION_CHUNK_TYPES, STREAM_SOURCE_CHUNK_TYPES, STREAM_METADATA_CHUNK_TYPES, STREAM_ERROR_CHUNK_TYPES, CONTEXT_TRANSITIONS, EXECUTION_TRANSITIONS, STEP_TRANSITIONS, ITEM_TRANSITIONS, canContextTransition, canExecutionTransition, canStepTransition, canItemTransition, assertContextTransition, assertExecutionTransition, assertStepTransition, assertItemTransition, isContextStreamChunkType, assertContextPartKey, } from "./context.contract.js";
8
9
  export { DEFAULT_CODEX_TOOL_NAME, DEFAULT_CODEX_MODEL, codexToolInputSchema, buildDefaultCodexNarrative, didCodexToolExecute, createCodexContextBuilder, } from "./codex.js";
9
10
  export { useContext, } from "./react.js";
10
11
  export { parseContextStreamEvent, assertContextStreamTransitions, validateContextStreamTimeline, } from "./context.stream.js";
11
- export { CONTEXT_STEP_STREAM_VERSION, createContextStepStreamChunk, parseContextStepStreamChunk, encodeContextStepStreamChunk, } from "./context.step-stream.js";
12
+ export { CONTEXT_STEP_STREAM_VERSION, createContextStepStreamChunk, validateContextStepStreamChunk, parseContextStepStreamChunk, encodeContextStepStreamChunk, } from "./context.step-stream.js";
13
+ export { CONTEXT_PART_ID_NAMESPACE, CONTEXT_PART_UUID_RE, CONTEXT_STREAM_PART_TYPES, assertValidContextPartChunkIdentity, resolveContextPartChunkDescriptor, resolveContextPartChunkIdentity, resolveContextPartId, resolveContextStreamPartSlot, resolveContextStreamPartType, uuidV5, } from "./context.part-identity.js";
@@ -1,3 +1,4 @@
1
+ import { resolveContextPartChunkIdentity } from "../context.part-identity.js";
1
2
  const REDACT_KEY = /token|authorization|cookie|secret|api[_-]?key|password/i;
2
3
  function asRecord(value) {
3
4
  if (!value || typeof value !== "object")
@@ -119,10 +120,32 @@ function buildNormalizedData(chunk) {
119
120
  }
120
121
  return toJsonSafe(normalized) ?? {};
121
122
  }
123
+ function readProviderPartId(chunk, chunkType) {
124
+ if (chunkType.startsWith("chunk.action_")) {
125
+ return readString(chunk, "toolCallId") ?? readString(chunk, "id");
126
+ }
127
+ if (chunkType.startsWith("chunk.text_") || chunkType.startsWith("chunk.reasoning_")) {
128
+ return readString(chunk, "id");
129
+ }
130
+ if (chunkType.startsWith("chunk.source_")) {
131
+ return readString(chunk, "sourceId");
132
+ }
133
+ if (chunkType === "chunk.file") {
134
+ return readString(chunk, "id") ?? readString(chunk, "url");
135
+ }
136
+ return undefined;
137
+ }
122
138
  export function mapAiSdkChunkToContextEvent(params) {
123
139
  const chunk = asRecord(params.chunk);
124
140
  const providerChunkType = readString(chunk, "type") ?? "unknown";
125
141
  const chunkType = mapAiSdkChunkType(providerChunkType);
142
+ const providerPartId = readProviderPartId(chunk, chunkType);
143
+ const identity = resolveContextPartChunkIdentity({
144
+ stepId: params.stepId,
145
+ provider: params.provider ?? "ai-sdk",
146
+ providerPartId,
147
+ chunkType,
148
+ });
126
149
  const actionRef = readString(chunk, "toolCallId") ??
127
150
  readString(chunk, "id");
128
151
  return {
@@ -133,6 +156,10 @@ export function mapAiSdkChunkToContextEvent(params) {
133
156
  executionId: params.executionId,
134
157
  stepId: params.stepId,
135
158
  itemId: params.itemId,
159
+ partId: identity?.partId,
160
+ providerPartId: identity?.providerPartId,
161
+ partType: identity?.partType,
162
+ partSlot: identity?.partSlot,
136
163
  actionRef: chunkType.startsWith("chunk.action_") ? actionRef : undefined,
137
164
  provider: params.provider,
138
165
  providerChunkType,
@@ -1,12 +1,13 @@
1
1
  import type { ContextEnvironment } from "../context.config.js";
2
- import type { ContextRuntime } from "../context.runtime.js";
2
+ import type { DomainSchemaResult } from "@ekairos/domain";
3
+ import type { ContextRuntime, ContextRuntimeHandleForDomain } from "../context.runtime.js";
3
4
  import type { ContextModelInit } from "../context.engine.js";
4
5
  import type { ContextIdentifier, StoredContext, ContextItem } from "../context.store.js";
6
+ import { eventsDomain } from "../schema.js";
5
7
  import type { ContextReactor } from "./types.js";
6
- export type CreateAiSdkReactorOptions<Context = unknown, Env extends ContextEnvironment = ContextEnvironment, Config = unknown> = {
8
+ export type CreateAiSdkReactorOptions<Context = unknown, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainSchemaResult = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>, Config = unknown> = {
7
9
  resolveConfig?: (params: {
8
- runtime: ContextRuntime<Env>;
9
- env: Env;
10
+ runtime: ContextRuntimeHandleForDomain<Env, RequiredDomain>;
10
11
  context: StoredContext<Context>;
11
12
  contextIdentifier: ContextIdentifier;
12
13
  triggerEvent: ContextItem;
@@ -18,20 +19,18 @@ export type CreateAiSdkReactorOptions<Context = unknown, Env extends ContextEnvi
18
19
  iteration: number;
19
20
  }) => Promise<Config> | Config;
20
21
  selectModel?: (params: {
21
- runtime: ContextRuntime<Env>;
22
- env: Env;
22
+ runtime: ContextRuntimeHandleForDomain<Env, RequiredDomain>;
23
23
  context: StoredContext<Context>;
24
24
  triggerEvent: ContextItem;
25
25
  baseModel: ContextModelInit;
26
26
  config: Config;
27
27
  }) => Promise<ContextModelInit> | ContextModelInit;
28
28
  selectMaxModelSteps?: (params: {
29
- runtime: ContextRuntime<Env>;
30
- env: Env;
29
+ runtime: ContextRuntimeHandleForDomain<Env, RequiredDomain>;
31
30
  context: StoredContext<Context>;
32
31
  triggerEvent: ContextItem;
33
32
  baseMaxModelSteps: number;
34
33
  config: Config;
35
34
  }) => Promise<number> | number;
36
35
  };
37
- export declare function createAiSdkReactor<Context = unknown, Env extends ContextEnvironment = ContextEnvironment, Config = unknown>(options?: CreateAiSdkReactorOptions<Context, Env, Config>): ContextReactor<Context, Env>;
36
+ export declare function createAiSdkReactor<Context = unknown, Env extends ContextEnvironment = ContextEnvironment, RequiredDomain extends DomainSchemaResult = typeof eventsDomain, Runtime extends ContextRuntime<Env> = ContextRuntime<Env>, Config = unknown>(options?: CreateAiSdkReactorOptions<Context, Env, RequiredDomain, Runtime, Config>): ContextReactor<Context, Env, RequiredDomain, Runtime>;
@@ -1,11 +1,11 @@
1
1
  import { executeAiSdkReaction } from "./ai-sdk.step.js";
2
+ import { actionsToActionSpecs } from "../tools-to-model-tools.js";
2
3
  export function createAiSdkReactor(options) {
3
4
  return async (params) => {
4
5
  let config;
5
6
  if (options?.resolveConfig) {
6
7
  config = await options.resolveConfig({
7
8
  runtime: params.runtime,
8
- env: params.env,
9
9
  context: params.context,
10
10
  contextIdentifier: params.contextIdentifier,
11
11
  triggerEvent: params.triggerEvent,
@@ -20,7 +20,6 @@ export function createAiSdkReactor(options) {
20
20
  const model = options?.selectModel && config !== undefined
21
21
  ? await options.selectModel({
22
22
  runtime: params.runtime,
23
- env: params.env,
24
23
  context: params.context,
25
24
  triggerEvent: params.triggerEvent,
26
25
  baseModel: params.model,
@@ -30,7 +29,6 @@ export function createAiSdkReactor(options) {
30
29
  const maxSteps = options?.selectMaxModelSteps && config !== undefined
31
30
  ? await options.selectMaxModelSteps({
32
31
  runtime: params.runtime,
33
- env: params.env,
34
32
  context: params.context,
35
33
  triggerEvent: params.triggerEvent,
36
34
  baseMaxModelSteps: params.maxModelSteps,
@@ -39,12 +37,11 @@ export function createAiSdkReactor(options) {
39
37
  : params.maxModelSteps;
40
38
  const result = await executeAiSdkReaction({
41
39
  runtime: params.runtime,
42
- env: params.env,
43
40
  contextIdentifier: params.contextIdentifier,
44
41
  events: params.events,
45
42
  model,
46
43
  system: params.systemPrompt,
47
- tools: params.actionSpecs,
44
+ tools: actionsToActionSpecs(params.actions),
48
45
  eventId: params.eventId,
49
46
  iteration: params.iteration,
50
47
  maxSteps,
@@ -13,9 +13,8 @@ import { type SerializableActionSpec } from "../tools-to-model-tools.js";
13
13
  * - map provider chunks to the Context stream contract
14
14
  * - emit UI chunks and persist step stream chunks
15
15
  */
16
- export declare function executeAiSdkReaction(params: {
17
- runtime: import("../context.runtime.js").ContextRuntime<ContextEnvironment>;
18
- env: ContextEnvironment;
16
+ export declare function executeAiSdkReaction<Env extends ContextEnvironment = ContextEnvironment>(params: {
17
+ runtime: import("../context.runtime.js").ContextRuntimeServiceHandle;
19
18
  contextIdentifier: ContextIdentifier;
20
19
  events?: ContextItem[];
21
20
  model: ContextModelInit;
@@ -13,7 +13,7 @@ async function readWorkflowMetadata() {
13
13
  return null;
14
14
  }
15
15
  }
16
- async function resolveWorkflowRunId(env, executionId) {
16
+ async function resolveWorkflowRunId(runtime, executionId) {
17
17
  let runId = "";
18
18
  const meta = await readWorkflowMetadata();
19
19
  if (meta && meta.workflowRunId !== undefined && meta.workflowRunId !== null) {
@@ -21,9 +21,7 @@ async function resolveWorkflowRunId(env, executionId) {
21
21
  }
22
22
  if (!runId && executionId) {
23
23
  try {
24
- const { getContextRuntime } = await import("../runtime.js");
25
- const runtime = await getContextRuntime(env);
26
- const db = runtime?.db;
24
+ const db = await runtime.db();
27
25
  if (db) {
28
26
  const q = await db.query({
29
27
  event_executions: {
@@ -135,7 +133,7 @@ export async function executeAiSdkReaction(params) {
135
133
  rejectFinish = reject;
136
134
  });
137
135
  const modelId = typeof params.model === "string" ? params.model : "";
138
- const mappedProvider = modelId.includes("/") ? modelId.split("/")[0] : undefined;
136
+ const mappedProvider = modelId.includes("/") ? modelId.split("/")[0] || "ai-sdk" : "ai-sdk";
139
137
  const contextStepStreamWriter = params.contextStepStream?.getWriter();
140
138
  try {
141
139
  const uiStream = result
@@ -180,6 +178,11 @@ export async function executeAiSdkReaction(params) {
180
178
  at: mapped.at,
181
179
  sequence: mapped.sequence,
182
180
  chunkType: mapped.chunkType,
181
+ stepId: params.stepId,
182
+ partId: mapped.partId,
183
+ providerPartId: mapped.providerPartId,
184
+ partType: mapped.partType,
185
+ partSlot: mapped.partSlot,
183
186
  provider: mapped.provider,
184
187
  providerChunkType: mapped.providerChunkType,
185
188
  actionRef: mapped.actionRef,
@@ -294,10 +297,10 @@ export async function executeAiSdkReaction(params) {
294
297
  rawProviderMetadata: providerMetadataJson,
295
298
  };
296
299
  try {
297
- const runId = await resolveWorkflowRunId(params.env, params.executionId);
300
+ const runId = await resolveWorkflowRunId(params.runtime, params.executionId);
298
301
  if (runId && llm) {
299
302
  await writeContextTraceEvents({
300
- env: params.env,
303
+ runtime: params.runtime,
301
304
  events: [
302
305
  {
303
306
  workflowRunId: runId,