@ekairos/events 1.22.35-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 +5 -3
- 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 +60 -52
- package/dist/context.engine.js +506 -297
- 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 +14 -4
- package/dist/context.runtime.js +21 -3
- package/dist/context.step-stream.d.ts +16 -2
- package/dist/context.step-stream.js +58 -16
- package/dist/context.store.d.ts +55 -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 -9
- package/dist/reactors/ai-sdk.reactor.js +6 -9
- package/dist/reactors/ai-sdk.step.d.ts +4 -5
- package/dist/reactors/ai-sdk.step.js +24 -17
- package/dist/reactors/scripted.reactor.d.ts +7 -4
- package/dist/reactors/types.d.ts +19 -10
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.js +9 -0
- package/dist/runtime.step.js +1 -1
- package/dist/schema.d.ts +268 -2
- package/dist/schema.js +4 -9
- package/dist/steps/do-context-stream-step.js +4 -4
- package/dist/steps/durable.steps.d.ts +28 -0
- package/dist/steps/durable.steps.js +34 -0
- package/dist/steps/store.steps.d.ts +64 -22
- package/dist/steps/store.steps.js +192 -35
- package/dist/steps/stream.steps.d.ts +32 -0
- package/dist/steps/stream.steps.js +124 -6
- package/dist/steps/trace.steps.d.ts +4 -4
- package/dist/steps/trace.steps.js +21 -6
- package/dist/stores/instant.store.d.ts +11 -11
- package/dist/stores/instant.store.js +136 -6
- package/dist/tools-to-model-tools.d.ts +4 -2
- package/dist/tools-to-model-tools.js +30 -11
- package/package.json +18 -7
- package/dist/context.toolcalls.d.ts +0 -60
- package/dist/context.toolcalls.js +0 -117
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../polyfills/dom-events.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { DomainLike } from "@ekairos/domain";
|
|
3
3
|
import type { ModelMessage } from "ai";
|
|
4
|
-
import type { ContextItem, ContextIdentifier, ContextStatus, StoredContext, ContextStore } from "../context.store.js";
|
|
4
|
+
import type { ContextItem, ContextIdentifier, ContextResource, ContextStatus, StoredContextResource, StoredContext, ContextStore } from "../context.store.js";
|
|
5
5
|
export { parseAndStoreDocument } from "./instant.document-parser.js";
|
|
6
6
|
export { coerceDocumentTextPages, expandEventsWithInstantDocuments, } from "./instant.documents.js";
|
|
7
7
|
export type InstantStoreDb = any;
|
|
@@ -14,12 +14,20 @@ export declare class InstantStore implements ContextStore {
|
|
|
14
14
|
getOrCreateContext<C>(contextIdentifier: ContextIdentifier | null): Promise<StoredContext<C>>;
|
|
15
15
|
getContext<C>(contextIdentifier: ContextIdentifier): Promise<StoredContext<C> | null>;
|
|
16
16
|
updateContextContent<C>(contextIdentifier: ContextIdentifier, content: C): Promise<StoredContext<C>>;
|
|
17
|
+
updateContextDefinition<C>(contextIdentifier: ContextIdentifier, definition: {
|
|
18
|
+
description?: string | null;
|
|
19
|
+
goal?: string | null;
|
|
20
|
+
}): Promise<StoredContext<C>>;
|
|
17
21
|
updateContextReactor<C>(contextIdentifier: ContextIdentifier, reactor: {
|
|
18
22
|
kind: string;
|
|
19
23
|
state?: Record<string, unknown> | null;
|
|
20
24
|
}): Promise<StoredContext<C>>;
|
|
21
25
|
updateContextStatus(contextIdentifier: ContextIdentifier, status: ContextStatus): Promise<void>;
|
|
22
26
|
private resolveContext;
|
|
27
|
+
private normalizeContextResource;
|
|
28
|
+
private normalizeContextResources;
|
|
29
|
+
getContextResources(contextIdentifier: ContextIdentifier): Promise<StoredContextResource[]>;
|
|
30
|
+
upsertContextResources(contextIdentifier: ContextIdentifier, resources: ContextResource[]): Promise<StoredContextResource[]>;
|
|
23
31
|
saveItem(contextIdentifier: ContextIdentifier, event: ContextItem): Promise<ContextItem>;
|
|
24
32
|
updateItem(eventId: string, event: ContextItem): Promise<ContextItem>;
|
|
25
33
|
getItem(eventId: string): Promise<ContextItem | null>;
|
|
@@ -38,14 +46,6 @@ export declare class InstantStore implements ContextStore {
|
|
|
38
46
|
}>;
|
|
39
47
|
updateStep(stepId: string, patch: Partial<{
|
|
40
48
|
status: "running" | "completed" | "failed";
|
|
41
|
-
kind: "message" | "action_execute" | "action_result";
|
|
42
|
-
actionName: string;
|
|
43
|
-
actionInput: unknown;
|
|
44
|
-
actionOutput: unknown;
|
|
45
|
-
actionError: string;
|
|
46
|
-
actionRequests: any;
|
|
47
|
-
actionResults: any;
|
|
48
|
-
continueLoop: boolean;
|
|
49
49
|
errorText: string;
|
|
50
50
|
updatedAt: Date;
|
|
51
51
|
}>): Promise<void>;
|
|
@@ -62,7 +62,7 @@ export declare class InstantStore implements ContextStore {
|
|
|
62
62
|
export declare function createInstantStoreRuntime(params: {
|
|
63
63
|
getDb: (orgId: string) => Promise<InstantStoreDb> | InstantStoreDb;
|
|
64
64
|
getOrgId?: (env: Record<string, unknown>) => string;
|
|
65
|
-
domain?:
|
|
65
|
+
domain?: DomainLike;
|
|
66
66
|
}): (env: Record<string, unknown>) => Promise<{
|
|
67
67
|
store: InstantStore;
|
|
68
68
|
db: InstantStoreDb;
|
|
@@ -71,6 +71,43 @@ function ensureValidEntityId(value, label) {
|
|
|
71
71
|
}
|
|
72
72
|
return normalized;
|
|
73
73
|
}
|
|
74
|
+
function sanitizeInstantString(value) {
|
|
75
|
+
return value.includes("\u0000") ? value.replace(/\u0000/g, "") : value;
|
|
76
|
+
}
|
|
77
|
+
function isOpaqueJsonValue(value) {
|
|
78
|
+
return (value instanceof Date ||
|
|
79
|
+
value instanceof ArrayBuffer ||
|
|
80
|
+
ArrayBuffer.isView(value));
|
|
81
|
+
}
|
|
82
|
+
function sanitizeInstantValue(value, seen = new WeakMap()) {
|
|
83
|
+
if (typeof value === "string") {
|
|
84
|
+
return sanitizeInstantString(value);
|
|
85
|
+
}
|
|
86
|
+
if (value === null || value === undefined || typeof value !== "object") {
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
if (isOpaqueJsonValue(value)) {
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
const cached = seen.get(value);
|
|
93
|
+
if (cached) {
|
|
94
|
+
return cached;
|
|
95
|
+
}
|
|
96
|
+
if (Array.isArray(value)) {
|
|
97
|
+
const out = [];
|
|
98
|
+
seen.set(value, out);
|
|
99
|
+
for (const item of value) {
|
|
100
|
+
out.push(sanitizeInstantValue(item, seen));
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
const out = {};
|
|
105
|
+
seen.set(value, out);
|
|
106
|
+
for (const [key, entryValue] of Object.entries(value)) {
|
|
107
|
+
out[sanitizeInstantString(key)] = sanitizeInstantValue(entryValue, seen);
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
74
111
|
function logInstantTransactFailure(params) {
|
|
75
112
|
if (!shouldDebugInstantStore())
|
|
76
113
|
return;
|
|
@@ -118,6 +155,9 @@ export class InstantStore {
|
|
|
118
155
|
? new Date(row.updatedAt)
|
|
119
156
|
: undefined,
|
|
120
157
|
content: row?.content ?? null,
|
|
158
|
+
description: typeof row?.description === "string" ? row.description : null,
|
|
159
|
+
goal: typeof row?.goal === "string" ? row.goal : null,
|
|
160
|
+
resources: this.normalizeContextResources(row?.resources),
|
|
121
161
|
reactor: row?.reactor && typeof row.reactor === "object"
|
|
122
162
|
? row.reactor
|
|
123
163
|
: null,
|
|
@@ -147,6 +187,9 @@ export class InstantStore {
|
|
|
147
187
|
key,
|
|
148
188
|
status: "open_idle",
|
|
149
189
|
content: {},
|
|
190
|
+
description: undefined,
|
|
191
|
+
goal: undefined,
|
|
192
|
+
resources: [],
|
|
150
193
|
reactor: undefined,
|
|
151
194
|
}),
|
|
152
195
|
]);
|
|
@@ -207,6 +250,28 @@ export class InstantStore {
|
|
|
207
250
|
throw new Error("InstantStore: context not found after update");
|
|
208
251
|
return updated;
|
|
209
252
|
}
|
|
253
|
+
async updateContextDefinition(contextIdentifier, definition) {
|
|
254
|
+
const context = await this.getContext(contextIdentifier);
|
|
255
|
+
if (!context?.id)
|
|
256
|
+
throw new Error("InstantStore: context not found");
|
|
257
|
+
const update = {
|
|
258
|
+
updatedAt: new Date(),
|
|
259
|
+
};
|
|
260
|
+
if (definition.description !== undefined) {
|
|
261
|
+
update.description =
|
|
262
|
+
typeof definition.description === "string" ? definition.description : undefined;
|
|
263
|
+
}
|
|
264
|
+
if (definition.goal !== undefined) {
|
|
265
|
+
update.goal = typeof definition.goal === "string" ? definition.goal : undefined;
|
|
266
|
+
}
|
|
267
|
+
await this.db.transact([
|
|
268
|
+
this.db.tx.event_contexts[context.id].update(update),
|
|
269
|
+
]);
|
|
270
|
+
const updated = await this.getContext({ id: context.id });
|
|
271
|
+
if (!updated)
|
|
272
|
+
throw new Error("InstantStore: context not found after definition update");
|
|
273
|
+
return updated;
|
|
274
|
+
}
|
|
210
275
|
async updateContextReactor(contextIdentifier, reactor) {
|
|
211
276
|
const context = await this.getContext(contextIdentifier);
|
|
212
277
|
if (!context?.id)
|
|
@@ -242,8 +307,69 @@ export class InstantStore {
|
|
|
242
307
|
throw new Error("InstantStore: context not found");
|
|
243
308
|
return context;
|
|
244
309
|
}
|
|
310
|
+
normalizeContextResource(resource) {
|
|
311
|
+
if (!resource || typeof resource !== "object")
|
|
312
|
+
return null;
|
|
313
|
+
const record = resource;
|
|
314
|
+
const key = typeof record.key === "string" ? record.key.trim() : "";
|
|
315
|
+
const type = typeof record.type === "string" ? record.type.trim() : "";
|
|
316
|
+
const name = typeof record.name === "string" ? record.name.trim() : "";
|
|
317
|
+
const description = typeof record.description === "string" ? record.description.trim() : "";
|
|
318
|
+
if (!key || !type || !name || !description)
|
|
319
|
+
return null;
|
|
320
|
+
return {
|
|
321
|
+
...record,
|
|
322
|
+
key,
|
|
323
|
+
type,
|
|
324
|
+
name,
|
|
325
|
+
description,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
normalizeContextResources(value) {
|
|
329
|
+
if (!Array.isArray(value))
|
|
330
|
+
return [];
|
|
331
|
+
return value.flatMap((resource) => {
|
|
332
|
+
const normalized = this.normalizeContextResource(resource);
|
|
333
|
+
return normalized ? [normalized] : [];
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
async getContextResources(contextIdentifier) {
|
|
337
|
+
const context = await this.resolveContext(contextIdentifier);
|
|
338
|
+
return context.resources ?? [];
|
|
339
|
+
}
|
|
340
|
+
async upsertContextResources(contextIdentifier, resources) {
|
|
341
|
+
const context = await this.resolveContext(contextIdentifier);
|
|
342
|
+
const now = new Date();
|
|
343
|
+
const storedResources = [];
|
|
344
|
+
for (const resource of resources) {
|
|
345
|
+
const resourceKey = typeof resource.key === "string" ? resource.key.trim() : "";
|
|
346
|
+
const type = typeof resource.type === "string" ? resource.type.trim() : "";
|
|
347
|
+
const name = typeof resource.name === "string" ? resource.name.trim() : "";
|
|
348
|
+
const description = typeof resource.description === "string" ? resource.description.trim() : "";
|
|
349
|
+
if (!resourceKey || !type || !name || !description) {
|
|
350
|
+
throw new Error("InstantStore: context resources require key, type, name, and description.");
|
|
351
|
+
}
|
|
352
|
+
const sanitizedResource = sanitizeInstantValue(resource);
|
|
353
|
+
const storedResource = {
|
|
354
|
+
...sanitizedResource,
|
|
355
|
+
key: resourceKey,
|
|
356
|
+
type,
|
|
357
|
+
name,
|
|
358
|
+
description,
|
|
359
|
+
};
|
|
360
|
+
storedResources.push(storedResource);
|
|
361
|
+
}
|
|
362
|
+
await this.db.transact([
|
|
363
|
+
this.db.tx.event_contexts[context.id].update({
|
|
364
|
+
resources: storedResources,
|
|
365
|
+
updatedAt: now,
|
|
366
|
+
}),
|
|
367
|
+
]);
|
|
368
|
+
return await this.getContextResources({ id: context.id });
|
|
369
|
+
}
|
|
245
370
|
async saveItem(contextIdentifier, event) {
|
|
246
371
|
const eventId = ensureValidEntityId(event?.id, "event.id");
|
|
372
|
+
const sanitizedEvent = sanitizeInstantValue(event);
|
|
247
373
|
const context = await this.resolveContext(contextIdentifier);
|
|
248
374
|
const existing = await this.getItem(eventId);
|
|
249
375
|
if (existing?.status && existing.status !== "stored") {
|
|
@@ -251,7 +377,7 @@ export class InstantStore {
|
|
|
251
377
|
}
|
|
252
378
|
const txs = [
|
|
253
379
|
this.db.tx.event_items[eventId].update({
|
|
254
|
-
...
|
|
380
|
+
...sanitizedEvent,
|
|
255
381
|
id: eventId,
|
|
256
382
|
status: "stored",
|
|
257
383
|
}),
|
|
@@ -277,7 +403,7 @@ export class InstantStore {
|
|
|
277
403
|
throw error;
|
|
278
404
|
}
|
|
279
405
|
return {
|
|
280
|
-
...
|
|
406
|
+
...sanitizedEvent,
|
|
281
407
|
id: eventId,
|
|
282
408
|
status: "stored",
|
|
283
409
|
};
|
|
@@ -287,10 +413,11 @@ export class InstantStore {
|
|
|
287
413
|
if (current?.status && event.status && current.status !== event.status) {
|
|
288
414
|
assertItemTransition(current.status, event.status);
|
|
289
415
|
}
|
|
290
|
-
|
|
416
|
+
const sanitizedEvent = sanitizeInstantValue(event);
|
|
417
|
+
await this.db.transact([this.db.tx.event_items[eventId].update(sanitizedEvent)]);
|
|
291
418
|
return {
|
|
292
419
|
...current,
|
|
293
|
-
...
|
|
420
|
+
...sanitizedEvent,
|
|
294
421
|
id: eventId,
|
|
295
422
|
};
|
|
296
423
|
}
|
|
@@ -517,9 +644,12 @@ export class InstantStore {
|
|
|
517
644
|
}
|
|
518
645
|
}
|
|
519
646
|
const update = {
|
|
520
|
-
...patch,
|
|
521
647
|
updatedAt: patch.updatedAt ?? new Date(),
|
|
522
648
|
};
|
|
649
|
+
if (patch.status !== undefined)
|
|
650
|
+
update.status = patch.status;
|
|
651
|
+
if (patch.errorText !== undefined)
|
|
652
|
+
update.errorText = patch.errorText;
|
|
523
653
|
await this.db.transact([this.db.tx.event_steps[stepId].update(update)]);
|
|
524
654
|
}
|
|
525
655
|
async linkItemToExecution(params) {
|
|
@@ -528,7 +658,7 @@ export class InstantStore {
|
|
|
528
658
|
]);
|
|
529
659
|
}
|
|
530
660
|
async saveStepParts(params) {
|
|
531
|
-
const parts = normalizePartsForPersistence(Array.isArray(params.parts) ? params.parts : []);
|
|
661
|
+
const parts = sanitizeInstantValue(normalizePartsForPersistence(Array.isArray(params.parts) ? params.parts : []));
|
|
532
662
|
if (parts.length === 0)
|
|
533
663
|
return;
|
|
534
664
|
const txs = parts.map((part, idx) => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type Tool } from "ai";
|
|
2
1
|
/**
|
|
3
2
|
* Serializable "tool" shape to pass across the Workflow step boundary.
|
|
4
3
|
*
|
|
@@ -10,6 +9,7 @@ export type SerializableFunctionActionSpec = {
|
|
|
10
9
|
type?: "function";
|
|
11
10
|
description?: string;
|
|
12
11
|
inputSchema: unknown;
|
|
12
|
+
outputSchema?: unknown;
|
|
13
13
|
providerOptions?: unknown;
|
|
14
14
|
};
|
|
15
15
|
export type SerializableProviderDefinedActionSpec = {
|
|
@@ -29,7 +29,7 @@ export type SerializableToolForModel = SerializableActionSpec;
|
|
|
29
29
|
* This matches DurableAgent's internal `toolsToModelTools` behavior:
|
|
30
30
|
* `inputSchema: asSchema(tool.inputSchema).jsonSchema`
|
|
31
31
|
*/
|
|
32
|
-
export declare function actionsToActionSpecs(tools: Record<string,
|
|
32
|
+
export declare function actionsToActionSpecs(tools: Record<string, unknown>): Record<string, SerializableActionSpec>;
|
|
33
33
|
export declare function actionSpecToAiSdkTool(name: string, spec: SerializableActionSpec, wrapJsonSchema: (schema: unknown) => unknown): {
|
|
34
34
|
type: "provider-defined";
|
|
35
35
|
id: string;
|
|
@@ -37,11 +37,13 @@ export declare function actionSpecToAiSdkTool(name: string, spec: SerializableAc
|
|
|
37
37
|
args: Record<string, unknown>;
|
|
38
38
|
description?: undefined;
|
|
39
39
|
inputSchema?: undefined;
|
|
40
|
+
outputSchema?: undefined;
|
|
40
41
|
providerOptions?: undefined;
|
|
41
42
|
} | {
|
|
42
43
|
type: "function";
|
|
43
44
|
description: string | undefined;
|
|
44
45
|
inputSchema: unknown;
|
|
46
|
+
outputSchema: unknown;
|
|
45
47
|
providerOptions: unknown;
|
|
46
48
|
id?: undefined;
|
|
47
49
|
name?: undefined;
|
|
@@ -1,10 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
function toJsonSchema(schema) {
|
|
3
|
+
if (!schema)
|
|
4
|
+
return schema;
|
|
5
|
+
const jsonSchema = schema?.jsonSchema;
|
|
6
|
+
if (jsonSchema)
|
|
7
|
+
return jsonSchema;
|
|
8
|
+
try {
|
|
9
|
+
return z.toJSONSchema(schema);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return schema;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function asRecord(value) {
|
|
16
|
+
return value && typeof value === "object" ? value : {};
|
|
17
|
+
}
|
|
2
18
|
function isProviderDefinedTool(tool) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
tool.id.trim().length > 0);
|
|
19
|
+
const record = asRecord(tool);
|
|
20
|
+
return (record.type === "provider-defined" &&
|
|
21
|
+
typeof record.id === "string" &&
|
|
22
|
+
record.id.trim().length > 0);
|
|
8
23
|
}
|
|
9
24
|
/**
|
|
10
25
|
* Convert AI SDK tools to a serializable representation that can be passed to `"use-step"` functions.
|
|
@@ -24,15 +39,18 @@ export function actionsToActionSpecs(tools) {
|
|
|
24
39
|
};
|
|
25
40
|
continue;
|
|
26
41
|
}
|
|
27
|
-
const
|
|
42
|
+
const record = asRecord(tool);
|
|
43
|
+
const inputSchema = record.inputSchema ?? record.input;
|
|
28
44
|
if (!inputSchema) {
|
|
29
|
-
throw new Error(`Context:
|
|
45
|
+
throw new Error(`Context: action "${name}" is missing input/inputSchema (required for model action calls)`);
|
|
30
46
|
}
|
|
47
|
+
const outputSchema = record.outputSchema ?? record.output;
|
|
31
48
|
out[name] = {
|
|
32
49
|
type: "function",
|
|
33
|
-
description:
|
|
34
|
-
inputSchema:
|
|
35
|
-
|
|
50
|
+
description: typeof record.description === "string" ? record.description : undefined,
|
|
51
|
+
inputSchema: toJsonSchema(inputSchema),
|
|
52
|
+
outputSchema: outputSchema ? toJsonSchema(outputSchema) : undefined,
|
|
53
|
+
providerOptions: record.providerOptions,
|
|
36
54
|
};
|
|
37
55
|
}
|
|
38
56
|
return out;
|
|
@@ -50,6 +68,7 @@ export function actionSpecToAiSdkTool(name, spec, wrapJsonSchema) {
|
|
|
50
68
|
type: "function",
|
|
51
69
|
description: spec.description,
|
|
52
70
|
inputSchema: wrapJsonSchema(spec.inputSchema),
|
|
71
|
+
outputSchema: spec.outputSchema ? wrapJsonSchema(spec.outputSchema) : undefined,
|
|
53
72
|
providerOptions: spec.providerOptions,
|
|
54
73
|
};
|
|
55
74
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ekairos/events",
|
|
3
|
-
"version": "1.22.35
|
|
3
|
+
"version": "1.22.35",
|
|
4
4
|
"description": "Ekairos Events - Context-first workflow runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,6 +30,12 @@
|
|
|
30
30
|
"require": "./dist/schema.js",
|
|
31
31
|
"default": "./dist/schema.js"
|
|
32
32
|
},
|
|
33
|
+
"./domain": {
|
|
34
|
+
"types": "./dist/domain.d.ts",
|
|
35
|
+
"import": "./dist/domain.js",
|
|
36
|
+
"require": "./dist/domain.js",
|
|
37
|
+
"default": "./dist/domain.js"
|
|
38
|
+
},
|
|
33
39
|
"./runtime": {
|
|
34
40
|
"types": "./dist/runtime.d.ts",
|
|
35
41
|
"import": "./dist/runtime.js",
|
|
@@ -78,6 +84,9 @@
|
|
|
78
84
|
"schema": [
|
|
79
85
|
"dist/schema.d.ts"
|
|
80
86
|
],
|
|
87
|
+
"domain": [
|
|
88
|
+
"dist/domain.d.ts"
|
|
89
|
+
],
|
|
81
90
|
"runtime": [
|
|
82
91
|
"dist/runtime.d.ts"
|
|
83
92
|
],
|
|
@@ -107,6 +116,7 @@
|
|
|
107
116
|
"watch": "tsc -p tsconfig.json --watch",
|
|
108
117
|
"clean": "node -e \"require('fs').rmSync('dist', {recursive:true, force:true})\"",
|
|
109
118
|
"typecheck": "tsc --noEmit",
|
|
119
|
+
"typecheck:tests": "tsc --noEmit -p tsconfig.typecheck.json",
|
|
110
120
|
"test": "vitest run -c vitest.config.mts",
|
|
111
121
|
"test:workflow": "vitest run -c vitest.workflow.config.mts",
|
|
112
122
|
"pretest:ai-sdk-reactor": "pnpm --filter @ekairos/domain build",
|
|
@@ -117,7 +127,7 @@
|
|
|
117
127
|
},
|
|
118
128
|
"dependencies": {
|
|
119
129
|
"@ai-sdk/openai": "^2.0.52",
|
|
120
|
-
"@ekairos/domain": "^1.22.35
|
|
130
|
+
"@ekairos/domain": "^1.22.35",
|
|
121
131
|
"@instantdb/admin": "0.22.158",
|
|
122
132
|
"@instantdb/core": "0.22.142",
|
|
123
133
|
"@vercel/mcp-adapter": "^1.0.0",
|
|
@@ -126,20 +136,21 @@
|
|
|
126
136
|
"ajv": "^8.17.1",
|
|
127
137
|
"jose": "^6.1.3",
|
|
128
138
|
"llamaindex": "^0.12.0",
|
|
139
|
+
"partial-json": "^0.1.7",
|
|
129
140
|
"react": "^19.2.0",
|
|
130
|
-
"workflow": "5.0.0-beta.
|
|
141
|
+
"workflow": "5.0.0-beta.5",
|
|
131
142
|
"xmlbuilder2": "^3.1.1",
|
|
132
143
|
"zod": "^4.3.6"
|
|
133
144
|
},
|
|
134
145
|
"devDependencies": {
|
|
135
146
|
"@ekairos/testing": "workspace:*",
|
|
136
147
|
"@ekairos/tsconfig": "workspace:*",
|
|
137
|
-
"@workflow/serde": "5.0.0-beta.0",
|
|
138
|
-
"@workflow/vitest": "5.0.0-beta.1",
|
|
139
148
|
"@types/node": "^24.5.0",
|
|
140
149
|
"@types/react": "^19.2.2",
|
|
150
|
+
"@workflow/serde": "5.0.0-beta.1",
|
|
151
|
+
"@workflow/vitest": "5.0.0-beta.5",
|
|
141
152
|
"dotenv": "^17.2.3",
|
|
142
|
-
"
|
|
143
|
-
"
|
|
153
|
+
"typescript": "^5.9.2",
|
|
154
|
+
"vitest": "^4.0.8"
|
|
144
155
|
}
|
|
145
156
|
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ## context.toolcalls.ts
|
|
3
|
-
*
|
|
4
|
-
* This module isolates the **tool-call plumbing** used by `context.engine.ts`.
|
|
5
|
-
*
|
|
6
|
-
* In our runtime, tool calls are represented as **event parts** produced by the AI SDK.
|
|
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.).
|
|
11
|
-
*
|
|
12
|
-
* Keeping this logic here helps `context.engine.ts` read like orchestration, and keeps
|
|
13
|
-
* these transformations testable and reusable.
|
|
14
|
-
*/
|
|
15
|
-
import type { ContextItem } from "./context.store.js";
|
|
16
|
-
export type ToolCall = {
|
|
17
|
-
toolCallId: string;
|
|
18
|
-
toolName: string;
|
|
19
|
-
args: any;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Extracts tool calls from an event's `parts` array.
|
|
23
|
-
*
|
|
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.
|
|
30
|
-
*/
|
|
31
|
-
export declare function extractToolCallsFromParts(parts: any[] | undefined | null): ToolCall[];
|
|
32
|
-
/**
|
|
33
|
-
* Applies a tool execution outcome to the matching tool part.
|
|
34
|
-
*
|
|
35
|
-
* This does not mutate `parts` — it returns a new array.
|
|
36
|
-
*
|
|
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> }`
|
|
44
|
-
*/
|
|
45
|
-
export declare function applyToolExecutionResultToParts(parts: any[], toolCall: Pick<ToolCall, "toolCallId" | "toolName">, execution: {
|
|
46
|
-
success: boolean;
|
|
47
|
-
result: any;
|
|
48
|
-
message?: string;
|
|
49
|
-
}): any[];
|
|
50
|
-
/**
|
|
51
|
-
* Returns `true` when a given tool has a **settled** execution result in an event's parts.
|
|
52
|
-
*
|
|
53
|
-
* We treat a tool part as "executed" once it has either:
|
|
54
|
-
* - `state: "output-available"` (success), or
|
|
55
|
-
* - `state: "output-error"` (failure).
|
|
56
|
-
*
|
|
57
|
-
* This is useful for stop/continue logic in `context.shouldContinue(...)` where you want to
|
|
58
|
-
* decide based on the persisted `reactionEvent` (not ephemeral in-memory arrays).
|
|
59
|
-
*/
|
|
60
|
-
export declare function didToolExecute(event: Pick<ContextItem, "content">, toolName: string): boolean;
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ## context.toolcalls.ts
|
|
3
|
-
*
|
|
4
|
-
* This module isolates the **tool-call plumbing** used by `context.engine.ts`.
|
|
5
|
-
*
|
|
6
|
-
* In our runtime, tool calls are represented as **event parts** produced by the AI SDK.
|
|
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.).
|
|
11
|
-
*
|
|
12
|
-
* Keeping this logic here helps `context.engine.ts` read like orchestration, and keeps
|
|
13
|
-
* these transformations testable and reusable.
|
|
14
|
-
*/
|
|
15
|
-
import { isContextPartEnvelope, normalizePartsForPersistence, normalizeToolResultContentToBlocks, } from "./context.parts.js";
|
|
16
|
-
/**
|
|
17
|
-
* Extracts tool calls from an event's `parts` array.
|
|
18
|
-
*
|
|
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.
|
|
25
|
-
*/
|
|
26
|
-
export function extractToolCallsFromParts(parts) {
|
|
27
|
-
const safeParts = parts ?? [];
|
|
28
|
-
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;
|
|
32
|
-
acc.push({
|
|
33
|
-
toolCallId: p.toolCallId,
|
|
34
|
-
toolName: p.toolName,
|
|
35
|
-
args,
|
|
36
|
-
});
|
|
37
|
-
return acc;
|
|
38
|
-
}
|
|
39
|
-
if (typeof p?.type === "string" && p.type.startsWith("tool-")) {
|
|
40
|
-
const toolName = p.type.split("-").slice(1).join("-");
|
|
41
|
-
acc.push({ toolCallId: p.toolCallId, toolName, args: p.input });
|
|
42
|
-
}
|
|
43
|
-
return acc;
|
|
44
|
-
}, []);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Applies a tool execution outcome to the matching tool part.
|
|
48
|
-
*
|
|
49
|
-
* This does not mutate `parts` — it returns a new array.
|
|
50
|
-
*
|
|
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> }`
|
|
58
|
-
*/
|
|
59
|
-
export function applyToolExecutionResultToParts(parts, toolCall, execution) {
|
|
60
|
-
const normalized = normalizePartsForPersistence(parts);
|
|
61
|
-
const next = [];
|
|
62
|
-
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
|
-
for (const part of normalized) {
|
|
72
|
-
next.push(part);
|
|
73
|
-
if (part.type !== "tool-call") {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
if (part.toolCallId !== toolCall.toolCallId ||
|
|
77
|
-
part.toolName !== toolCall.toolName) {
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
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
|
-
});
|
|
87
|
-
insertedResult = true;
|
|
88
|
-
}
|
|
89
|
-
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
|
-
});
|
|
97
|
-
}
|
|
98
|
-
return next;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Returns `true` when a given tool has a **settled** execution result in an event's parts.
|
|
102
|
-
*
|
|
103
|
-
* We treat a tool part as "executed" once it has either:
|
|
104
|
-
* - `state: "output-available"` (success), or
|
|
105
|
-
* - `state: "output-error"` (failure).
|
|
106
|
-
*
|
|
107
|
-
* This is useful for stop/continue logic in `context.shouldContinue(...)` where you want to
|
|
108
|
-
* decide based on the persisted `reactionEvent` (not ephemeral in-memory arrays).
|
|
109
|
-
*/
|
|
110
|
-
export function didToolExecute(event, toolName) {
|
|
111
|
-
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")) ||
|
|
115
|
-
(p.type === `tool-${toolName}` &&
|
|
116
|
-
(p.state === "output-available" || p.state === "output-error")));
|
|
117
|
-
}
|