@ekairos/structure 1.22.46-beta.development.0 → 1.22.47-beta.development.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/steps/commitFromEvents.step.js +1 -20
- package/dist/steps/completeOutput.d.ts +1 -0
- package/dist/steps/completeOutput.js +43 -0
- package/dist/steps/ensureExecutionTrail.step.js +4 -0
- package/dist/steps/persistObjectFromStory.step.js +29 -1
- package/dist/structure.d.ts +25 -0
- package/dist/structure.js +39 -10
- package/package.json +3 -3
|
@@ -1,24 +1,5 @@
|
|
|
1
1
|
import { linkStructureOutputFileToContextByKey } from "../contextPersistence.js";
|
|
2
|
-
|
|
3
|
-
if (!value || typeof value !== "object")
|
|
4
|
-
return false;
|
|
5
|
-
const v = value;
|
|
6
|
-
return v.type === "tool-complete" && v.state === "output-available";
|
|
7
|
-
}
|
|
8
|
-
function findLatestCompleteToolOutput(events) {
|
|
9
|
-
for (let i = events.length - 1; i >= 0; i--) {
|
|
10
|
-
const parts = events[i]?.content?.parts;
|
|
11
|
-
if (!Array.isArray(parts))
|
|
12
|
-
continue;
|
|
13
|
-
for (let j = parts.length - 1; j >= 0; j--) {
|
|
14
|
-
const p = parts[j];
|
|
15
|
-
if (!isToolCompletePart(p))
|
|
16
|
-
continue;
|
|
17
|
-
return p.output;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
2
|
+
import { findLatestCompleteToolOutput } from "./completeOutput.js";
|
|
22
3
|
export async function structureCommitFromEventsStep(params) {
|
|
23
4
|
"use step";
|
|
24
5
|
const contextKey = `structure:${params.structureId}`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function findLatestCompleteToolOutput(events: unknown[]): unknown | null;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
function asRecord(value) {
|
|
2
|
+
if (!value || typeof value !== "object")
|
|
3
|
+
return null;
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
function readPart(value) {
|
|
7
|
+
const record = asRecord(value);
|
|
8
|
+
if (!record)
|
|
9
|
+
return null;
|
|
10
|
+
const nestedPart = asRecord(record.part);
|
|
11
|
+
return nestedPart ?? record;
|
|
12
|
+
}
|
|
13
|
+
function readCompleteOutputFromPart(value) {
|
|
14
|
+
const part = readPart(value);
|
|
15
|
+
if (!part)
|
|
16
|
+
return null;
|
|
17
|
+
if (part.type === "tool-complete" && part.state === "output-available") {
|
|
18
|
+
return part.output ?? null;
|
|
19
|
+
}
|
|
20
|
+
if (part.type !== "action")
|
|
21
|
+
return null;
|
|
22
|
+
const content = asRecord(part.content);
|
|
23
|
+
if (content?.status !== "completed" ||
|
|
24
|
+
content?.actionName !== "complete") {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return content.output ?? null;
|
|
28
|
+
}
|
|
29
|
+
export function findLatestCompleteToolOutput(events) {
|
|
30
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
31
|
+
const event = asRecord(events[i]);
|
|
32
|
+
const content = asRecord(event?.content);
|
|
33
|
+
const parts = Array.isArray(content?.parts) ? content.parts : null;
|
|
34
|
+
if (!parts)
|
|
35
|
+
continue;
|
|
36
|
+
for (let j = parts.length - 1; j >= 0; j--) {
|
|
37
|
+
const output = readCompleteOutputFromPart(parts[j]);
|
|
38
|
+
if (output !== null)
|
|
39
|
+
return output;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
@@ -85,6 +85,10 @@ export async function ensureExecutionTrailStep(params) {
|
|
|
85
85
|
});
|
|
86
86
|
if (!outputItem?.id)
|
|
87
87
|
return;
|
|
88
|
+
const context = await store.getContext?.({ key: params.contextKey });
|
|
89
|
+
if (context?.status === "closed" && store?.updateContextStatus) {
|
|
90
|
+
await store.updateContextStatus({ key: params.contextKey }, "open_idle");
|
|
91
|
+
}
|
|
88
92
|
const execution = await store.createExecution({ key: params.contextKey }, requestItemId, outputItem.id);
|
|
89
93
|
await store.linkItemToExecution({
|
|
90
94
|
itemId: requestItemId,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { findLatestCompleteToolOutput } from "./completeOutput.js";
|
|
1
2
|
function extractJsonObject(text) {
|
|
2
3
|
const trimmed = text.trim();
|
|
3
4
|
if (!trimmed)
|
|
@@ -40,10 +41,37 @@ export async function persistObjectResultFromStoryStep(params) {
|
|
|
40
41
|
const runtime = (await getContextRuntime(params.env));
|
|
41
42
|
const store = runtime.store;
|
|
42
43
|
const contextKey = `structure:${params.datasetId}`;
|
|
43
|
-
const events =
|
|
44
|
+
const events = typeof store.getItems === "function"
|
|
45
|
+
? await store.getItems({ key: contextKey })
|
|
46
|
+
: await store.getEvents({ key: contextKey });
|
|
44
47
|
const { structurePatchContextContentStep, structureGetContextStep } = await import("../dataset/steps.js");
|
|
45
48
|
const ctxResult = await structureGetContextStep({ env: params.env, contextKey });
|
|
46
49
|
const existingContent = ctxResult.ok ? (ctxResult.data?.content ?? {}) : {};
|
|
50
|
+
const completedOutput = findLatestCompleteToolOutput(events ?? []);
|
|
51
|
+
if (completedOutput?.success === true && "result" in completedOutput) {
|
|
52
|
+
const patchResult = await structurePatchContextContentStep({
|
|
53
|
+
env: params.env,
|
|
54
|
+
contextKey,
|
|
55
|
+
patch: {
|
|
56
|
+
structure: {
|
|
57
|
+
kind: "ekairos.structure",
|
|
58
|
+
version: 1,
|
|
59
|
+
structureId: params.datasetId,
|
|
60
|
+
updatedAt: Date.now(),
|
|
61
|
+
state: "completed",
|
|
62
|
+
outputs: {
|
|
63
|
+
...(existingContent?.structure?.outputs ?? {}),
|
|
64
|
+
object: { value: completedOutput.result },
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
if (!patchResult?.ok) {
|
|
70
|
+
const err = patchResult?.error ?? "Failed to persist object result";
|
|
71
|
+
throw new Error(err);
|
|
72
|
+
}
|
|
73
|
+
return { ok: true };
|
|
74
|
+
}
|
|
47
75
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
48
76
|
const e = events[i];
|
|
49
77
|
const parts = e?.content?.parts;
|
package/dist/structure.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ContextModelInit } from "@ekairos/events";
|
|
1
2
|
import { type StructureRowsOutputPagingCursor } from "./rowsOutputPaging.js";
|
|
2
3
|
import type { SandboxConfig } from "@ekairos/sandbox";
|
|
3
4
|
export type StructureSource = {
|
|
@@ -66,10 +67,32 @@ export type StructureBuildResult = {
|
|
|
66
67
|
*/
|
|
67
68
|
dataset?: any;
|
|
68
69
|
};
|
|
70
|
+
type StructureStoryConfig = {
|
|
71
|
+
datasetId: string;
|
|
72
|
+
sources: StructureSource[];
|
|
73
|
+
instructions?: string;
|
|
74
|
+
mode: StructureMode;
|
|
75
|
+
output: StructureOutput;
|
|
76
|
+
outputSchema?: any;
|
|
77
|
+
sandboxId?: string;
|
|
78
|
+
model?: ContextModelInit;
|
|
79
|
+
sandboxConfig?: SandboxConfig;
|
|
80
|
+
};
|
|
81
|
+
export declare function structureRunStoryStep<Env extends {
|
|
82
|
+
orgId: string;
|
|
83
|
+
}>(params: {
|
|
84
|
+
env: Env;
|
|
85
|
+
contextKey: string;
|
|
86
|
+
config: StructureStoryConfig;
|
|
87
|
+
event: any;
|
|
88
|
+
}): Promise<{
|
|
89
|
+
ok: boolean;
|
|
90
|
+
}>;
|
|
69
91
|
export declare function structure<Env extends {
|
|
70
92
|
orgId: string;
|
|
71
93
|
}>(env: Env, opts?: {
|
|
72
94
|
datasetId?: string;
|
|
95
|
+
model?: ContextModelInit;
|
|
73
96
|
sandboxConfig?: SandboxConfig;
|
|
74
97
|
}): {
|
|
75
98
|
datasetId: string;
|
|
@@ -79,5 +102,7 @@ export declare function structure<Env extends {
|
|
|
79
102
|
schema(schema: any): /*elided*/ any;
|
|
80
103
|
asRows(): /*elided*/ any;
|
|
81
104
|
asObject(): /*elided*/ any;
|
|
105
|
+
model(nextModel: ContextModelInit): /*elided*/ any;
|
|
82
106
|
build(userPrompt?: string): Promise<StructureBuildResult>;
|
|
83
107
|
};
|
|
108
|
+
export {};
|
package/dist/structure.js
CHANGED
|
@@ -410,6 +410,35 @@ function createStructureStoryDefinition(config) {
|
|
|
410
410
|
.model(model);
|
|
411
411
|
return { datasetId, story };
|
|
412
412
|
}
|
|
413
|
+
export async function structureRunStoryStep(params) {
|
|
414
|
+
"use step";
|
|
415
|
+
const { story, datasetId } = createStructureStoryDefinition(params.config);
|
|
416
|
+
const { getContextRuntime } = await import("@ekairos/events/runtime");
|
|
417
|
+
const runtime = await getContextRuntime(params.env);
|
|
418
|
+
const shell = await story.react(params.event, {
|
|
419
|
+
env: params.env,
|
|
420
|
+
runtime,
|
|
421
|
+
context: { key: params.contextKey },
|
|
422
|
+
durable: false,
|
|
423
|
+
options: {
|
|
424
|
+
silent: true,
|
|
425
|
+
preventClose: true,
|
|
426
|
+
sendFinish: false,
|
|
427
|
+
maxIterations: 40,
|
|
428
|
+
maxModelSteps: 10,
|
|
429
|
+
},
|
|
430
|
+
});
|
|
431
|
+
await shell.run;
|
|
432
|
+
// Tools are intentionally pure: persist completion outputs post-react by reading tool results from events.
|
|
433
|
+
const commit = await structureCommitFromEventsStep({
|
|
434
|
+
env: params.env,
|
|
435
|
+
structureId: datasetId,
|
|
436
|
+
});
|
|
437
|
+
if (!commit.ok) {
|
|
438
|
+
throw new Error(commit.error);
|
|
439
|
+
}
|
|
440
|
+
return { ok: true };
|
|
441
|
+
}
|
|
413
442
|
export function structure(env, opts) {
|
|
414
443
|
const datasetId = opts?.datasetId ?? createUuidV4();
|
|
415
444
|
const sources = [];
|
|
@@ -417,6 +446,7 @@ export function structure(env, opts) {
|
|
|
417
446
|
let mode = "auto";
|
|
418
447
|
let output = "rows";
|
|
419
448
|
let outputSchema;
|
|
449
|
+
let model = opts?.model;
|
|
420
450
|
const sandboxConfig = opts?.sandboxConfig;
|
|
421
451
|
const api = {
|
|
422
452
|
datasetId,
|
|
@@ -446,6 +476,10 @@ export function structure(env, opts) {
|
|
|
446
476
|
output = "object";
|
|
447
477
|
return api;
|
|
448
478
|
},
|
|
479
|
+
model(nextModel) {
|
|
480
|
+
model = nextModel;
|
|
481
|
+
return api;
|
|
482
|
+
},
|
|
449
483
|
async build(userPrompt) {
|
|
450
484
|
// Guardrail: structure build MUST run inside workflow runtime ("use workflow").
|
|
451
485
|
const workflowMeta = assertRunningInsideWorkflow({ datasetId });
|
|
@@ -458,6 +492,7 @@ export function structure(env, opts) {
|
|
|
458
492
|
mode,
|
|
459
493
|
output,
|
|
460
494
|
outputSchema,
|
|
495
|
+
model,
|
|
461
496
|
sandboxConfig,
|
|
462
497
|
};
|
|
463
498
|
const { story } = createStructureStoryDefinition(storyConfig);
|
|
@@ -495,18 +530,12 @@ export function structure(env, opts) {
|
|
|
495
530
|
}
|
|
496
531
|
}
|
|
497
532
|
async function runStory(evt) {
|
|
498
|
-
|
|
533
|
+
await structureRunStoryStep({
|
|
499
534
|
env,
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
535
|
+
contextKey,
|
|
536
|
+
config: storyConfig,
|
|
537
|
+
event: evt,
|
|
503
538
|
});
|
|
504
|
-
await shell.run;
|
|
505
|
-
// Tools are intentionally pure: persist completion outputs post-react by reading tool results from events.
|
|
506
|
-
const commit = await structureCommitFromEventsStep({ env, structureId: datasetId });
|
|
507
|
-
if (!commit.ok) {
|
|
508
|
-
throw new Error(commit.error);
|
|
509
|
-
}
|
|
510
539
|
}
|
|
511
540
|
async function getContextOrThrow() {
|
|
512
541
|
const ctxResult = await structureGetContextStep({ env, contextKey });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ekairos/structure",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.47-beta.development.0",
|
|
4
4
|
"description": "Ekairos Structure - Unified structured extraction (rows or object) from file/text/dataset inputs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"typecheck": "tsc --noEmit"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@ekairos/domain": "^1.22.
|
|
40
|
-
"@ekairos/sandbox": "^1.22.
|
|
39
|
+
"@ekairos/domain": "^1.22.47-beta.development.0",
|
|
40
|
+
"@ekairos/sandbox": "^1.22.47-beta.development.0",
|
|
41
41
|
"@instantdb/admin": "0.22.126",
|
|
42
42
|
"@instantdb/core": "0.22.126",
|
|
43
43
|
"ai": "^5.0.95",
|