@ekairos/events 1.22.44-beta.development.0 → 1.22.46-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.
@@ -3,9 +3,7 @@ import { OUTPUT_ITEM_TYPE, WEB_CHANNEL } from "./context.events.js";
3
3
  import { applyToolExecutionResultToParts } from "./context.toolcalls.js";
4
4
  import { isContextPartEnvelope, normalizePartsForPersistence, } from "./context.parts.js";
5
5
  import { createAiSdkReactor, } from "./context.reactor.js";
6
- import { abortPersistedContextStepStream, closeContextStream, createPersistedContextStepStreamForRuntime, finalizePersistedContextStepStreamForRuntime, } from "./steps/stream.steps.js";
7
- import { createContextStepStreamChunk, encodeContextStepStreamChunk, } from "./context.step-stream.js";
8
- import { resolveContextPartChunkIdentity } from "./context.part-identity.js";
6
+ import { abortPersistedContextStepStream, closeContextStream, createPersistedContextStepStreamForRuntime, finalizePersistedContextStepStreamForRuntime, writeActionResultPartChunks, } from "./steps/stream.steps.js";
9
7
  import { completeExecution, createContextStep, finalizeReactionStep, getContextItems, initializeContext, openReactionStep, saveTriggerAndCreateExecution, saveContextPartsAndUpdateReaction, saveContextPartsStep, updateContextContent, updateContextReactor, updateContextStatus, updateItem, updateContextStep, } from "./steps/store.steps.js";
10
8
  import { getClientResumeHookUrl, toolApprovalHookToken, toolApprovalWebhookToken, } from "./context.hooks.js";
11
9
  import { getContextDurableWorkflow } from "./context.durable.js";
@@ -88,112 +86,6 @@ function summarizePartPreview(part) {
88
86
  async function emitContextEvents(params) {
89
87
  void params;
90
88
  }
91
- function toJsonSafeRecord(value) {
92
- if (typeof value === "undefined")
93
- return undefined;
94
- try {
95
- const json = JSON.parse(JSON.stringify(value));
96
- return json && typeof json === "object"
97
- ? json
98
- : { value: json };
99
- }
100
- catch {
101
- return undefined;
102
- }
103
- }
104
- async function writeActionResultPartChunks(params) {
105
- if (!params.session || params.actionResults.length === 0)
106
- return;
107
- const writer = params.session.stream.getWriter();
108
- const events = [];
109
- const sequenceBase = Date.now();
110
- try {
111
- for (let index = 0; index < params.actionResults.length; index += 1) {
112
- const result = params.actionResults[index];
113
- const actionRef = String(result.actionRequest.actionRef || "");
114
- const actionName = String(result.actionRequest.actionName || "");
115
- if (!actionRef || !actionName)
116
- continue;
117
- const chunkType = result.success
118
- ? "chunk.action_completed"
119
- : "chunk.action_failed";
120
- const identity = resolveContextPartChunkIdentity({
121
- stepId: params.session.stepId,
122
- provider: "ekairos",
123
- providerPartId: actionRef,
124
- chunkType,
125
- });
126
- if (!identity)
127
- continue;
128
- const data = result.success
129
- ? {
130
- toolCallId: actionRef,
131
- toolName: actionName,
132
- output: toJsonSafeRecord(result.output),
133
- }
134
- : {
135
- toolCallId: actionRef,
136
- toolName: actionName,
137
- error: {
138
- message: String(result.errorText || "Action failed."),
139
- },
140
- };
141
- const at = nowIso();
142
- const sequence = sequenceBase + index;
143
- const persistedChunk = createContextStepStreamChunk({
144
- at,
145
- sequence,
146
- chunkType,
147
- stepId: params.session.stepId,
148
- partId: identity.partId,
149
- providerPartId: identity.providerPartId,
150
- partType: identity.partType,
151
- partSlot: identity.partSlot,
152
- provider: "ekairos",
153
- providerChunkType: result.success
154
- ? "action_completed"
155
- : "action_failed",
156
- actionRef,
157
- data,
158
- });
159
- await writer.write(encodeContextStepStreamChunk(persistedChunk, {
160
- stepId: params.session.stepId,
161
- }));
162
- events.push({
163
- type: "chunk.emitted",
164
- at,
165
- chunkType,
166
- contextId: params.contextId,
167
- executionId: params.executionId,
168
- stepId: params.session.stepId,
169
- itemId: params.itemId,
170
- sequence,
171
- provider: "ekairos",
172
- providerChunkType: result.success
173
- ? "action_completed"
174
- : "action_failed",
175
- actionRef,
176
- partId: identity.partId,
177
- providerPartId: identity.providerPartId,
178
- partType: identity.partType,
179
- partSlot: identity.partSlot,
180
- data,
181
- });
182
- }
183
- }
184
- finally {
185
- if (typeof writer?.releaseLock === "function") {
186
- writer.releaseLock();
187
- }
188
- }
189
- if (events.length > 0) {
190
- await emitContextEvents({
191
- silent: params.silent ?? false,
192
- writable: params.writable,
193
- events,
194
- });
195
- }
196
- }
197
89
  async function measureBenchmark(benchmark, name, run) {
198
90
  if (!benchmark)
199
91
  return await run();
@@ -1062,15 +954,18 @@ export class ContextEngine {
1062
954
  };
1063
955
  }
1064
956
  })));
1065
- await measureBenchmark(params.__benchmark, `${stagePrefix}.writeActionResultPartChunksMs`, async () => await writeActionResultPartChunks({
957
+ const actionResultChunkEvents = await measureBenchmark(params.__benchmark, `${stagePrefix}.writeActionResultPartChunksMs`, async () => await writeActionResultPartChunks({
1066
958
  session: currentStepStream,
1067
- writable,
1068
- silent,
1069
959
  contextId: String(currentContext.id),
1070
960
  executionId,
1071
961
  itemId: reactionEventId,
1072
962
  actionResults: actionResults,
1073
963
  }));
964
+ await emitContextEvents({
965
+ silent,
966
+ writable,
967
+ events: actionResultChunkEvents,
968
+ });
1074
969
  // Merge action results into persisted parts (so next LLM call can see them)
1075
970
  let finalizedStepParts = Array.isArray(stepParts) ? [...stepParts] : [];
1076
971
  for (const r of actionResults) {
@@ -248,8 +248,11 @@ export function assertValidContextPartChunkIdentity(input) {
248
248
  if (!isActionChunk && typeof input.actionRef !== "undefined") {
249
249
  throw new Error(`Invalid ${fieldLabel(label, "actionRef")}: only action chunks can carry actionRef.`);
250
250
  }
251
- if (isActionChunk && typeof input.actionRef !== "undefined") {
252
- assertPartIdentityString(input.actionRef, fieldLabel(label, "actionRef"));
251
+ if (isActionChunk) {
252
+ const actionRef = assertPartIdentityString(input.actionRef, fieldLabel(label, "actionRef"));
253
+ if (actionRef !== providerPartId) {
254
+ throw new Error(`Invalid ${fieldLabel(label, "actionRef")}: action chunks require actionRef to match providerPartId.`);
255
+ }
253
256
  }
254
257
  const stepId = normalizeIdentityField(input.stepId);
255
258
  if (!stepId)
@@ -8,5 +8,6 @@ export type MapAiSdkChunkToContextEventParams = {
8
8
  itemId?: string;
9
9
  provider?: string;
10
10
  sequence: number;
11
+ actionNameByRef?: Map<string, string>;
11
12
  };
12
13
  export declare function mapAiSdkChunkToContextEvent(params: MapAiSdkChunkToContextEventParams): ChunkEmittedEvent;
@@ -103,6 +103,7 @@ function buildNormalizedData(chunk) {
103
103
  "inputTextDelta",
104
104
  "outputTextDelta",
105
105
  "state",
106
+ "actionName",
106
107
  "toolName",
107
108
  "toolCallId",
108
109
  "input",
@@ -153,6 +154,24 @@ export function mapAiSdkChunkToContextEvent(params) {
153
154
  });
154
155
  const actionRef = readString(chunk, "toolCallId") ??
155
156
  readString(chunk, "id");
157
+ let data = buildNormalizedData(chunk);
158
+ if (chunkType.startsWith("chunk.action_") && actionRef) {
159
+ const observedActionName = readString(chunk, "actionName") ??
160
+ readString(chunk, "toolName") ??
161
+ readString(data, "actionName") ??
162
+ readString(data, "toolName");
163
+ if (observedActionName) {
164
+ params.actionNameByRef?.set(actionRef, observedActionName);
165
+ }
166
+ const knownActionName = observedActionName ?? params.actionNameByRef?.get(actionRef);
167
+ if (knownActionName) {
168
+ data = {
169
+ ...data,
170
+ actionName: readString(data, "actionName") ?? knownActionName,
171
+ toolName: readString(data, "toolName") ?? knownActionName,
172
+ };
173
+ }
174
+ }
156
175
  return {
157
176
  type: "chunk.emitted",
158
177
  at: new Date().toISOString(),
@@ -169,7 +188,7 @@ export function mapAiSdkChunkToContextEvent(params) {
169
188
  provider: params.provider,
170
189
  providerChunkType,
171
190
  sequence: params.sequence,
172
- data: buildNormalizedData(chunk),
191
+ data,
173
192
  raw: sanitizeRaw(chunk),
174
193
  };
175
194
  }
@@ -135,6 +135,7 @@ export async function executeAiSdkReaction(params) {
135
135
  const modelId = typeof params.model === "string" ? params.model : "";
136
136
  const mappedProvider = modelId.includes("/") ? modelId.split("/")[0] || "ai-sdk" : "ai-sdk";
137
137
  const contextStepStreamWriter = params.contextStepStream?.getWriter();
138
+ const actionNameByRef = new Map();
138
139
  try {
139
140
  const uiStream = result
140
141
  .toUIMessageStream({
@@ -173,6 +174,7 @@ export async function executeAiSdkReaction(params) {
173
174
  itemId: params.eventId,
174
175
  provider: mappedProvider,
175
176
  sequence: ++chunkSequence,
177
+ actionNameByRef,
176
178
  });
177
179
  const persistedChunk = createContextStepStreamChunk({
178
180
  at: mapped.at,
@@ -50,6 +50,22 @@ export declare function abortPersistedContextStepStream(params: {
50
50
  session: PersistedContextStepStreamSession;
51
51
  reason?: string | null;
52
52
  }): Promise<void>;
53
+ export declare function writeActionResultPartChunks(params: {
54
+ session?: PersistedContextStepStreamSession | null;
55
+ contextId: string;
56
+ executionId: string;
57
+ itemId: string;
58
+ actionResults: Array<{
59
+ actionRequest: {
60
+ actionRef: string;
61
+ actionName: string;
62
+ input: unknown;
63
+ };
64
+ success: boolean;
65
+ output: unknown;
66
+ errorText?: string;
67
+ }>;
68
+ }): Promise<ContextStreamEvent[]>;
53
69
  export declare function readPersistedContextStepStream(params: {
54
70
  db: any;
55
71
  clientId?: string;
@@ -1,5 +1,6 @@
1
1
  import { getContextRuntimeServices } from "../context.runtime.js";
2
- import { contextStreamByteLength, parseContextStepStreamChunk, } from "../context.step-stream.js";
2
+ import { createContextStepStreamChunk, contextStreamByteLength, encodeContextStepStreamChunk, parseContextStepStreamChunk, } from "../context.step-stream.js";
3
+ import { resolveContextPartChunkIdentity } from "../context.part-identity.js";
3
4
  export async function writeContextEvents(params) {
4
5
  "use step";
5
6
  const writable = params.writable;
@@ -48,6 +49,19 @@ function asRecord(value) {
48
49
  function asString(value) {
49
50
  return typeof value === "string" ? value.trim() : "";
50
51
  }
52
+ function toJsonSafeRecord(value) {
53
+ if (typeof value === "undefined")
54
+ return undefined;
55
+ try {
56
+ const json = JSON.parse(JSON.stringify(value));
57
+ return json && typeof json === "object"
58
+ ? json
59
+ : { value: json };
60
+ }
61
+ catch {
62
+ return undefined;
63
+ }
64
+ }
51
65
  function createUnsetStreamLinkTx(db, executionId, label, streamId) {
52
66
  try {
53
67
  return db.tx.event_executions[executionId].unlink({ [label]: streamId });
@@ -169,6 +183,100 @@ export async function abortPersistedContextStepStream(params) {
169
183
  abortReason: params.reason,
170
184
  });
171
185
  }
186
+ export async function writeActionResultPartChunks(params) {
187
+ "use step";
188
+ if (!params.session || params.actionResults.length === 0)
189
+ return [];
190
+ const writer = params.session.stream.getWriter();
191
+ const events = [];
192
+ const sequenceBase = Date.now();
193
+ try {
194
+ for (let index = 0; index < params.actionResults.length; index += 1) {
195
+ const result = params.actionResults[index];
196
+ const actionRef = String(result.actionRequest.actionRef || "");
197
+ const actionName = String(result.actionRequest.actionName || "");
198
+ if (!actionRef || !actionName)
199
+ continue;
200
+ const chunkType = result.success
201
+ ? "chunk.action_completed"
202
+ : "chunk.action_failed";
203
+ const identity = resolveContextPartChunkIdentity({
204
+ stepId: params.session.stepId,
205
+ provider: "ekairos",
206
+ providerPartId: actionRef,
207
+ chunkType,
208
+ });
209
+ if (!identity)
210
+ continue;
211
+ const data = result.success
212
+ ? {
213
+ actionRef,
214
+ actionCallId: actionRef,
215
+ actionName,
216
+ toolCallId: actionRef,
217
+ toolName: actionName,
218
+ output: toJsonSafeRecord(result.output),
219
+ }
220
+ : {
221
+ actionRef,
222
+ actionCallId: actionRef,
223
+ actionName,
224
+ toolCallId: actionRef,
225
+ toolName: actionName,
226
+ error: {
227
+ message: String(result.errorText || "Action failed."),
228
+ },
229
+ };
230
+ const at = new Date().toISOString();
231
+ const sequence = sequenceBase + index;
232
+ const persistedChunk = createContextStepStreamChunk({
233
+ at,
234
+ sequence,
235
+ chunkType,
236
+ stepId: params.session.stepId,
237
+ partId: identity.partId,
238
+ providerPartId: identity.providerPartId,
239
+ partType: identity.partType,
240
+ partSlot: identity.partSlot,
241
+ provider: "ekairos",
242
+ providerChunkType: result.success
243
+ ? "action_completed"
244
+ : "action_failed",
245
+ actionRef,
246
+ data,
247
+ });
248
+ await writer.write(encodeContextStepStreamChunk(persistedChunk, {
249
+ stepId: params.session.stepId,
250
+ }));
251
+ events.push({
252
+ type: "chunk.emitted",
253
+ at,
254
+ chunkType,
255
+ contextId: params.contextId,
256
+ executionId: params.executionId,
257
+ stepId: params.session.stepId,
258
+ itemId: params.itemId,
259
+ sequence,
260
+ provider: "ekairos",
261
+ providerChunkType: result.success
262
+ ? "action_completed"
263
+ : "action_failed",
264
+ actionRef,
265
+ partId: identity.partId,
266
+ providerPartId: identity.providerPartId,
267
+ partType: identity.partType,
268
+ partSlot: identity.partSlot,
269
+ data,
270
+ });
271
+ }
272
+ }
273
+ finally {
274
+ if (typeof writer?.releaseLock === "function") {
275
+ writer.releaseLock();
276
+ }
277
+ }
278
+ return events;
279
+ }
172
280
  export async function readPersistedContextStepStream(params) {
173
281
  if (!params.db?.streams?.createReadStream) {
174
282
  throw new Error("InstantDB streams are not available on the provided runtime.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekairos/events",
3
- "version": "1.22.44-beta.development.0",
3
+ "version": "1.22.46-beta.development.0",
4
4
  "description": "Ekairos Events - Context-first workflow runtime",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -127,7 +127,7 @@
127
127
  },
128
128
  "dependencies": {
129
129
  "@ai-sdk/openai": "^2.0.52",
130
- "@ekairos/domain": "^1.22.44-beta.development.0",
130
+ "@ekairos/domain": "^1.22.46-beta.development.0",
131
131
  "@instantdb/admin": "0.22.158",
132
132
  "@instantdb/core": "0.22.142",
133
133
  "@vercel/mcp-adapter": "^1.0.0",