@ekairos/story 1.21.29-beta.0 → 1.21.32-beta.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/README.md +174 -0
- package/dist/agent.builder.d.ts +52 -0
- package/dist/agent.builder.d.ts.map +1 -0
- package/dist/agent.builder.js +110 -0
- package/dist/agent.builder.js.map +1 -0
- package/dist/agent.d.ts +2 -119
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.engine.d.ts +75 -0
- package/dist/agent.engine.d.ts.map +1 -0
- package/dist/agent.engine.js +455 -0
- package/dist/agent.engine.js.map +1 -0
- package/dist/agent.js +8 -607
- package/dist/agent.js.map +1 -1
- package/dist/ekairos.config.d.ts +21 -0
- package/dist/ekairos.config.d.ts.map +1 -0
- package/dist/ekairos.config.js +26 -0
- package/dist/ekairos.config.js.map +1 -0
- package/dist/events.d.ts +11 -7
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +37 -210
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -25
- package/dist/index.js.map +1 -1
- package/dist/legacy.story.d.ts +5 -0
- package/dist/legacy.story.d.ts.map +1 -0
- package/dist/legacy.story.js +15 -0
- package/dist/legacy.story.js.map +1 -0
- package/dist/runtime.d.ts +12 -0
- package/dist/runtime.js +12 -0
- package/dist/schema-document.d.ts +0 -1
- package/dist/schema-document.js +14 -18
- package/dist/schema-document.js.map +1 -1
- package/dist/schema.d.ts +0 -1
- package/dist/schema.js +22 -26
- package/dist/schema.js.map +1 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +2 -1
- package/dist/service.js.map +1 -1
- package/dist/steps/do-story-stream-step.d.ts +29 -0
- package/dist/steps/do-story-stream-step.d.ts.map +1 -0
- package/dist/steps/do-story-stream-step.js +89 -0
- package/dist/steps/do-story-stream-step.js.map +1 -0
- package/dist/steps/index.d.ts +1 -3
- package/dist/steps/index.d.ts.map +1 -1
- package/dist/steps/index.js +3 -17
- package/dist/steps/index.js.map +1 -1
- package/dist/steps/store.steps.d.ts +43 -0
- package/dist/steps/store.steps.d.ts.map +1 -0
- package/dist/steps/store.steps.js +123 -0
- package/dist/steps/store.steps.js.map +1 -0
- package/dist/steps/story.steps.d.ts +35 -0
- package/dist/steps/story.steps.d.ts.map +1 -0
- package/dist/steps/story.steps.js +59 -0
- package/dist/steps/story.steps.js.map +1 -0
- package/dist/steps/stream.steps.d.ts +28 -0
- package/dist/steps/stream.steps.d.ts.map +1 -0
- package/dist/steps/stream.steps.js +75 -0
- package/dist/steps/stream.steps.js.map +1 -0
- package/dist/stores/instant.document-parser.d.ts +5 -0
- package/dist/stores/instant.document-parser.d.ts.map +1 -0
- package/dist/stores/instant.document-parser.js +116 -0
- package/dist/stores/instant.document-parser.js.map +1 -0
- package/dist/stores/instant.documents.d.ts +16 -0
- package/dist/stores/instant.documents.js +108 -0
- package/dist/stores/instant.store.d.ts +40 -0
- package/dist/stores/instant.store.d.ts.map +1 -0
- package/dist/stores/instant.store.js +207 -0
- package/dist/stores/instant.store.js.map +1 -0
- package/dist/story.builder.d.ts +116 -0
- package/dist/story.builder.d.ts.map +1 -0
- package/dist/story.builder.js +130 -0
- package/dist/story.builder.js.map +1 -0
- package/dist/story.config.d.ts +43 -0
- package/dist/story.config.d.ts.map +1 -0
- package/dist/story.config.js +57 -0
- package/dist/story.config.js.map +1 -0
- package/dist/story.d.ts +2 -50
- package/dist/story.d.ts.map +1 -1
- package/dist/story.engine.d.ts +174 -0
- package/dist/story.engine.d.ts.map +1 -0
- package/dist/story.engine.js +283 -0
- package/dist/story.engine.js.map +1 -0
- package/dist/story.js +6 -55
- package/dist/story.js.map +1 -1
- package/dist/story.legacy.d.ts +12 -0
- package/dist/story.legacy.d.ts.map +1 -0
- package/dist/story.legacy.js +15 -0
- package/dist/story.legacy.js.map +1 -0
- package/dist/story.registry.d.ts +21 -0
- package/dist/story.registry.d.ts.map +1 -0
- package/dist/story.registry.js +30 -0
- package/dist/story.registry.js.map +1 -0
- package/dist/story.store.d.ts +59 -0
- package/dist/story.store.d.ts.map +1 -0
- package/dist/story.store.js +1 -0
- package/dist/story.store.js.map +1 -0
- package/dist/story.streams.d.ts +55 -0
- package/dist/story.streams.d.ts.map +1 -0
- package/dist/story.streams.js +99 -0
- package/dist/story.streams.js.map +1 -0
- package/dist/story.toolcalls.d.ts +60 -0
- package/dist/story.toolcalls.d.ts.map +1 -0
- package/dist/story.toolcalls.js +73 -0
- package/dist/story.toolcalls.js.map +1 -0
- package/dist/tools-to-model-tools.d.ts +19 -0
- package/dist/tools-to-model-tools.js +21 -0
- package/dist/workflow.d.ts +20 -0
- package/dist/workflow.js +27 -0
- package/package.json +15 -4
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Story = void 0;
|
|
4
|
+
const admin_1 = require("@instantdb/admin");
|
|
5
|
+
const braintrust_1 = require("braintrust");
|
|
6
|
+
const ai_1 = require("ai");
|
|
7
|
+
const openai_1 = require("@ai-sdk/openai");
|
|
8
|
+
const zod_1 = require("zod");
|
|
9
|
+
const service_1 = require("./service");
|
|
10
|
+
const events_1 = require("./events");
|
|
11
|
+
// Inicializar Braintrust logger
|
|
12
|
+
const logger = (0, braintrust_1.initLogger)({
|
|
13
|
+
projectName: "pulzar platform",
|
|
14
|
+
apiKey: process.env.BRAINTRUST_API_KEY,
|
|
15
|
+
});
|
|
16
|
+
const createDataStream = ai_1.createUIMessageStream;
|
|
17
|
+
class Story {
|
|
18
|
+
constructor(db, opts = {}) {
|
|
19
|
+
this.opts = opts;
|
|
20
|
+
this.db = db;
|
|
21
|
+
this.agentService = new service_1.AgentService(db);
|
|
22
|
+
}
|
|
23
|
+
getModel(_context) {
|
|
24
|
+
return "openai/gpt-5";
|
|
25
|
+
}
|
|
26
|
+
includeBaseTools() {
|
|
27
|
+
return { createMessage: true, requestDirection: true, end: true };
|
|
28
|
+
}
|
|
29
|
+
async getFinalizationToolNames() {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
getBaseTools(_dataStream, _threadId) {
|
|
33
|
+
const include = this.includeBaseTools();
|
|
34
|
+
const baseTools = {};
|
|
35
|
+
if (include.createMessage) {
|
|
36
|
+
baseTools.createMessage = (0, ai_1.tool)({
|
|
37
|
+
description: "Send a message to the user. Use for final confirmations or information.",
|
|
38
|
+
inputSchema: zod_1.z.object({
|
|
39
|
+
message: zod_1.z.string().describe("Message for the user in markdown format"),
|
|
40
|
+
type: zod_1.z
|
|
41
|
+
.enum(["info", "confirmation", "warning", "error", "success"])
|
|
42
|
+
.default("info"),
|
|
43
|
+
includeContext: zod_1.z.boolean().optional(),
|
|
44
|
+
}),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (include.requestDirection) {
|
|
48
|
+
baseTools.requestDirection = (0, ai_1.tool)({
|
|
49
|
+
description: "Ask a human for guidance when blocked or unsure.",
|
|
50
|
+
inputSchema: zod_1.z.object({
|
|
51
|
+
issue: zod_1.z.string(),
|
|
52
|
+
context: zod_1.z.string(),
|
|
53
|
+
suggestedActions: zod_1.z.array(zod_1.z.string()).optional(),
|
|
54
|
+
urgency: zod_1.z.enum(["low", "medium", "high"]).default("medium"),
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (include.end) {
|
|
59
|
+
baseTools.end = (0, ai_1.tool)({
|
|
60
|
+
description: "End the current interaction loop.",
|
|
61
|
+
inputSchema: zod_1.z.object({}).strict(),
|
|
62
|
+
execute: async () => {
|
|
63
|
+
return { success: true, message: "Ended" };
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return baseTools;
|
|
68
|
+
}
|
|
69
|
+
async executeCreateMessage(eventId, args, threadId, dataStream) {
|
|
70
|
+
const assistantMessage = {
|
|
71
|
+
id: eventId,
|
|
72
|
+
role: "assistant",
|
|
73
|
+
content: args.message,
|
|
74
|
+
createdAt: new Date(),
|
|
75
|
+
};
|
|
76
|
+
try {
|
|
77
|
+
await this.saveMessagesToThread(threadId, [assistantMessage]);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// noop
|
|
81
|
+
}
|
|
82
|
+
if (dataStream) {
|
|
83
|
+
// dataStream.writeData(...)
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
success: true,
|
|
87
|
+
message: args.message,
|
|
88
|
+
data: { messageId: assistantMessage.id, threadId },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async executeRequestDirection(eventId, args, threadId, _dataStream) {
|
|
92
|
+
const systemMessage = {
|
|
93
|
+
id: eventId,
|
|
94
|
+
role: "assistant",
|
|
95
|
+
content: `Direction requested: ${args.issue}\nContext: ${args.context}`,
|
|
96
|
+
createdAt: new Date(),
|
|
97
|
+
};
|
|
98
|
+
return { success: true, message: "Direction requested", data: { messageId: systemMessage.id, threadId } };
|
|
99
|
+
}
|
|
100
|
+
async progressStream(incomingEvent, contextIdentifier, options) {
|
|
101
|
+
// get or create context
|
|
102
|
+
const currentContext = await this.agentService.getOrCreateContext(contextIdentifier);
|
|
103
|
+
const contextSelector = contextIdentifier?.id
|
|
104
|
+
? { id: String(contextIdentifier.id) }
|
|
105
|
+
: contextIdentifier?.key
|
|
106
|
+
? { key: contextIdentifier.key }
|
|
107
|
+
: { id: String(currentContext.id) };
|
|
108
|
+
// save incoming event
|
|
109
|
+
const triggerEvent = await this.agentService.saveEvent(contextSelector, incomingEvent);
|
|
110
|
+
const triggerEventId = triggerEvent.id; // trigger event id
|
|
111
|
+
const eventId = (0, admin_1.id)(); // reaction event id
|
|
112
|
+
// Set context status to "streaming" before creating execution
|
|
113
|
+
await this.agentService.updateContextStatus(contextSelector, "streaming");
|
|
114
|
+
// create execution and set context status
|
|
115
|
+
const execution = await this.agentService.createExecution(contextSelector, triggerEventId, eventId);
|
|
116
|
+
const executionId = execution.id;
|
|
117
|
+
let latestReactionEvent = null;
|
|
118
|
+
let executionStatus = "executing";
|
|
119
|
+
const markFailure = async () => {
|
|
120
|
+
if (latestReactionEvent && latestReactionEvent.status !== "failed") {
|
|
121
|
+
try {
|
|
122
|
+
latestReactionEvent = await this.agentService.updateEvent(latestReactionEvent.id, {
|
|
123
|
+
...latestReactionEvent,
|
|
124
|
+
status: "failed",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch (eventError) {
|
|
128
|
+
console.error("Failed to mark reaction event as failed", eventError);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (executionStatus === "executing") {
|
|
132
|
+
try {
|
|
133
|
+
await this.agentService.completeExecution(contextSelector, executionId, "failed");
|
|
134
|
+
executionStatus = "failed";
|
|
135
|
+
}
|
|
136
|
+
catch (executionError) {
|
|
137
|
+
console.error("Failed to mark execution as failed", executionError);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const dataStreamResult = createDataStream({
|
|
142
|
+
execute: async ({ writer: dataStream }) => {
|
|
143
|
+
let loopSafety = 0;
|
|
144
|
+
const MAX_LOOPS = 20;
|
|
145
|
+
// load previous events (already in chronological order from InstantDB)
|
|
146
|
+
const events = await this.agentService.getEvents(contextSelector);
|
|
147
|
+
let reactionEvent = await this.agentService.saveEvent(contextSelector, {
|
|
148
|
+
id: eventId,
|
|
149
|
+
type: "assistant",
|
|
150
|
+
channel: "agent",
|
|
151
|
+
createdAt: new Date().toISOString(),
|
|
152
|
+
content: { parts: [] },
|
|
153
|
+
status: "pending",
|
|
154
|
+
});
|
|
155
|
+
latestReactionEvent = reactionEvent;
|
|
156
|
+
dataStream.write({ type: "event-start", data: { eventId: eventId } });
|
|
157
|
+
while (loopSafety < MAX_LOOPS) {
|
|
158
|
+
dataStream.write({ type: "start-step" });
|
|
159
|
+
loopSafety++;
|
|
160
|
+
// Read context
|
|
161
|
+
const currentContext = await this.agentService.getContext(contextSelector);
|
|
162
|
+
dataStream.write({
|
|
163
|
+
type: "data-context-id",
|
|
164
|
+
data: { contextId: currentContext.id },
|
|
165
|
+
});
|
|
166
|
+
// Initialize on each loop and get new context data
|
|
167
|
+
const contextContent = await this.initialize(currentContext);
|
|
168
|
+
// Update context
|
|
169
|
+
const updatedContext = await this.agentService.updateContextContent({ id: String(currentContext.id) }, contextContent);
|
|
170
|
+
// Build tools
|
|
171
|
+
const subclassToolsAll = await this.buildTools(updatedContext, dataStream);
|
|
172
|
+
// Build base tools for agent loop control
|
|
173
|
+
const baseTools = this.getBaseTools(dataStream, String(updatedContext.id));
|
|
174
|
+
const tools = { ...subclassToolsAll, ...baseTools };
|
|
175
|
+
// Add web search if enabled
|
|
176
|
+
if (options?.webSearch) {
|
|
177
|
+
tools.web_search = openai_1.openai.tools.webSearch();
|
|
178
|
+
}
|
|
179
|
+
// Extract execute functions from tools
|
|
180
|
+
const executeMap = {};
|
|
181
|
+
for (const [name, t] of Object.entries(subclassToolsAll)) {
|
|
182
|
+
if (t.execute) {
|
|
183
|
+
executeMap[name] = t.execute;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const include = this.includeBaseTools();
|
|
187
|
+
if (include.createMessage) {
|
|
188
|
+
executeMap["createMessage"] = (args) => this.executeCreateMessage(eventId, args, String(updatedContext.id), dataStream);
|
|
189
|
+
}
|
|
190
|
+
if (include.requestDirection) {
|
|
191
|
+
executeMap["requestDirection"] = (args) => this.executeRequestDirection(eventId, args, String(updatedContext.id), dataStream);
|
|
192
|
+
}
|
|
193
|
+
// Remove execute from tool definitions before sending to model
|
|
194
|
+
for (const [, t] of Object.entries(tools)) {
|
|
195
|
+
delete t.execute;
|
|
196
|
+
}
|
|
197
|
+
const messagesForModel = await (0, events_1.convertEventsToModelMessages)(reactionEvent.status !== "pending" ? [...events, reactionEvent] : [...events], this.db);
|
|
198
|
+
const systemPrompt = await this.buildSystemPrompt(updatedContext);
|
|
199
|
+
const providerOptions = {};
|
|
200
|
+
const hasReasoning = options?.reasoningEffort && options.reasoningEffort !== "off";
|
|
201
|
+
if (hasReasoning) {
|
|
202
|
+
providerOptions.openai = {
|
|
203
|
+
reasoningEffort: options.reasoningEffort,
|
|
204
|
+
reasoningSummary: "detailed",
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
// Allow more steps when using reasoning to give the model time to think
|
|
208
|
+
const maxSteps = hasReasoning ? 5 : 1;
|
|
209
|
+
const result = (0, ai_1.streamText)({
|
|
210
|
+
model: this.getModel(updatedContext),
|
|
211
|
+
system: systemPrompt,
|
|
212
|
+
messages: messagesForModel,
|
|
213
|
+
tools,
|
|
214
|
+
toolChoice: "required",
|
|
215
|
+
stopWhen: (0, ai_1.stepCountIs)(maxSteps),
|
|
216
|
+
experimental_transform: (0, ai_1.smoothStream)({
|
|
217
|
+
delayInMs: 30,
|
|
218
|
+
chunking: "word",
|
|
219
|
+
}),
|
|
220
|
+
...(Object.keys(providerOptions).length > 0 && { providerOptions }),
|
|
221
|
+
});
|
|
222
|
+
result.consumeStream();
|
|
223
|
+
let resolveFinish;
|
|
224
|
+
let rejectFinish;
|
|
225
|
+
const finishPromise = new Promise((resolve, reject) => {
|
|
226
|
+
resolveFinish = resolve;
|
|
227
|
+
rejectFinish = reject;
|
|
228
|
+
});
|
|
229
|
+
dataStream.merge(result
|
|
230
|
+
.toUIMessageStream({
|
|
231
|
+
sendStart: false,
|
|
232
|
+
generateMessageId: () => eventId,
|
|
233
|
+
messageMetadata() {
|
|
234
|
+
return {
|
|
235
|
+
eventId: eventId,
|
|
236
|
+
};
|
|
237
|
+
},
|
|
238
|
+
onFinish: ({ messages }) => {
|
|
239
|
+
const lastEvent = (0, events_1.createAssistantEventFromUIMessages)(eventId, messages);
|
|
240
|
+
resolveFinish(lastEvent);
|
|
241
|
+
},
|
|
242
|
+
onError: (e) => {
|
|
243
|
+
rejectFinish(e);
|
|
244
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
245
|
+
return message;
|
|
246
|
+
},
|
|
247
|
+
})
|
|
248
|
+
.pipeThrough(new TransformStream({
|
|
249
|
+
transform(chunk, controller) {
|
|
250
|
+
if (chunk.type === "start")
|
|
251
|
+
return;
|
|
252
|
+
if (chunk.type === "finish-step")
|
|
253
|
+
return;
|
|
254
|
+
if (chunk.type === "start-step")
|
|
255
|
+
return;
|
|
256
|
+
if (chunk.type === "finish")
|
|
257
|
+
return;
|
|
258
|
+
controller.enqueue(chunk);
|
|
259
|
+
},
|
|
260
|
+
})));
|
|
261
|
+
const lastEvent = await finishPromise;
|
|
262
|
+
const toolCalls = (lastEvent.content.parts || []).reduce((acc, p) => {
|
|
263
|
+
if (typeof p.type === "string" && p.type.startsWith("tool-")) {
|
|
264
|
+
const toolName = p.type.split("-")[1];
|
|
265
|
+
acc.push({ toolCallId: p.toolCallId, toolName: toolName, args: p.input });
|
|
266
|
+
}
|
|
267
|
+
return acc;
|
|
268
|
+
}, []);
|
|
269
|
+
if (!toolCalls.length) {
|
|
270
|
+
const shouldEndInteraction = await this.callOnEnd(lastEvent);
|
|
271
|
+
if (shouldEndInteraction) {
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const reactionEventWithParts = {
|
|
277
|
+
...reactionEvent,
|
|
278
|
+
content: { parts: [...reactionEvent.content.parts, ...lastEvent.content.parts] },
|
|
279
|
+
};
|
|
280
|
+
let currentEventState = await this.agentService.updateEvent(reactionEvent.id, reactionEventWithParts);
|
|
281
|
+
latestReactionEvent = currentEventState;
|
|
282
|
+
const executionResults = await Promise.all(toolCalls.map(async (tc) => {
|
|
283
|
+
let execSuccess = true;
|
|
284
|
+
let execMessage = "Executed";
|
|
285
|
+
let execResult = null;
|
|
286
|
+
try {
|
|
287
|
+
const execFn = executeMap[tc.toolName];
|
|
288
|
+
if (execFn) {
|
|
289
|
+
execResult = await execFn(tc.args);
|
|
290
|
+
execSuccess = execResult?.success !== false;
|
|
291
|
+
execMessage = execResult?.message || execMessage;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
execSuccess = false;
|
|
296
|
+
execMessage = err.message;
|
|
297
|
+
}
|
|
298
|
+
return { tc, execSuccess, execMessage, execResult };
|
|
299
|
+
}));
|
|
300
|
+
let exitOuterLoop = false;
|
|
301
|
+
const customFinalizationTools = await this.getFinalizationToolNames();
|
|
302
|
+
const allFinalToolNames = [...Story.FINAL_TOOL_NAMES, ...customFinalizationTools];
|
|
303
|
+
for (const { tc, execSuccess, execMessage, execResult } of executionResults) {
|
|
304
|
+
try {
|
|
305
|
+
if (execSuccess) {
|
|
306
|
+
dataStream.write({
|
|
307
|
+
type: "tool-output-available",
|
|
308
|
+
toolCallId: tc.toolCallId,
|
|
309
|
+
output: execResult,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
dataStream.write({
|
|
314
|
+
type: "tool-output-error",
|
|
315
|
+
toolCallId: tc.toolCallId,
|
|
316
|
+
errorText: String(execMessage || "Error"),
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
catch (e) {
|
|
321
|
+
console.error("Failed to write tool result to stream", e);
|
|
322
|
+
}
|
|
323
|
+
const existingParts = currentEventState?.content?.parts || [];
|
|
324
|
+
const mergedParts = existingParts.map((p) => {
|
|
325
|
+
if (p.type === `tool-${tc.toolName}` && p.toolCallId === tc.toolCallId) {
|
|
326
|
+
if (execSuccess) {
|
|
327
|
+
return { ...p, state: "output-available", output: execResult };
|
|
328
|
+
}
|
|
329
|
+
return { ...p, state: "output-error", errorText: String(execMessage || "Error") };
|
|
330
|
+
}
|
|
331
|
+
return p;
|
|
332
|
+
});
|
|
333
|
+
currentEventState = await this.agentService.updateEvent(currentEventState.id, {
|
|
334
|
+
id: currentEventState.id,
|
|
335
|
+
type: currentEventState.type,
|
|
336
|
+
channel: "agent",
|
|
337
|
+
createdAt: currentEventState.createdAt,
|
|
338
|
+
content: { parts: mergedParts },
|
|
339
|
+
});
|
|
340
|
+
dataStream.write({ type: "finish-step" });
|
|
341
|
+
await this.opts.onToolCallExecuted?.({
|
|
342
|
+
id: currentEventState.id,
|
|
343
|
+
toolCall: tc,
|
|
344
|
+
event: currentEventState.id,
|
|
345
|
+
success: execSuccess,
|
|
346
|
+
message: execMessage,
|
|
347
|
+
result: execResult,
|
|
348
|
+
});
|
|
349
|
+
let shouldEnd = false;
|
|
350
|
+
if (!execSuccess) {
|
|
351
|
+
const shouldEndInteraction = await this.callOnEnd(lastEvent);
|
|
352
|
+
if (shouldEndInteraction)
|
|
353
|
+
shouldEnd = true;
|
|
354
|
+
}
|
|
355
|
+
if (!shouldEnd) {
|
|
356
|
+
if (allFinalToolNames.includes(tc.toolName)) {
|
|
357
|
+
const shouldEndInteraction = await this.callOnEnd(lastEvent);
|
|
358
|
+
if (shouldEndInteraction)
|
|
359
|
+
shouldEnd = true;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (shouldEnd) {
|
|
363
|
+
dataStream.write({ type: "finish", override: true });
|
|
364
|
+
exitOuterLoop = true;
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
reactionEvent = currentEventState;
|
|
369
|
+
if (exitOuterLoop) {
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
reactionEvent = await this.agentService.updateEvent(reactionEvent.id, {
|
|
374
|
+
...reactionEvent,
|
|
375
|
+
status: "completed",
|
|
376
|
+
});
|
|
377
|
+
latestReactionEvent = reactionEvent;
|
|
378
|
+
try {
|
|
379
|
+
await this.agentService.completeExecution(contextSelector, executionId, "completed");
|
|
380
|
+
executionStatus = "completed";
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
console.error("Failed to mark execution as completed", error);
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
onError: (error) => {
|
|
387
|
+
console.error("Agent error:", error);
|
|
388
|
+
void markFailure();
|
|
389
|
+
return error instanceof Error ? error.message : String(error);
|
|
390
|
+
},
|
|
391
|
+
onFinish: async () => {
|
|
392
|
+
if (executionStatus === "executing") {
|
|
393
|
+
try {
|
|
394
|
+
await this.agentService.completeExecution(contextSelector, executionId, "completed");
|
|
395
|
+
executionStatus = "completed";
|
|
396
|
+
}
|
|
397
|
+
catch (executionError) {
|
|
398
|
+
console.error("Failed to finalize execution on finish", executionError);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
});
|
|
403
|
+
const dataStreamFilteredResult = dataStreamResult.pipeThrough(new TransformStream({
|
|
404
|
+
transform(chunk, controller) {
|
|
405
|
+
if (chunk.type === "start")
|
|
406
|
+
return;
|
|
407
|
+
if (chunk.type === "event-start") {
|
|
408
|
+
controller.enqueue({ type: "start", messageId: chunk.data.eventId });
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
controller.enqueue(chunk);
|
|
412
|
+
},
|
|
413
|
+
}));
|
|
414
|
+
return {
|
|
415
|
+
contextId: currentContext.id,
|
|
416
|
+
triggerEventId,
|
|
417
|
+
reactionEventId: eventId,
|
|
418
|
+
stream: dataStreamFilteredResult,
|
|
419
|
+
executionId,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
async saveMessagesToThread(_threadId, _messages) {
|
|
423
|
+
// Placeholder for persistence hook. Not implemented in current scope.
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
async callOnEnd(lastEvent) {
|
|
427
|
+
if (!this.opts.onEnd) {
|
|
428
|
+
return true;
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
const result = await this.opts.onEnd(lastEvent);
|
|
432
|
+
if (typeof result === "boolean") {
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
if (result && typeof result === "object") {
|
|
436
|
+
if (Object.prototype.hasOwnProperty.call(result, "end")) {
|
|
437
|
+
return Boolean(result.end);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
console.error("onEnd callback failed", error);
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
exports.Story = Story;
|
|
449
|
+
Story.FINAL_TOOL_NAMES = [
|
|
450
|
+
"createMessage",
|
|
451
|
+
"requestDirection",
|
|
452
|
+
"end",
|
|
453
|
+
];
|
|
454
|
+
// NOTE: No `Agent` alias — la API pública es Story.
|
|
455
|
+
//# sourceMappingURL=agent.engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.engine.js","sourceRoot":"","sources":["../src/agent.engine.ts"],"names":[],"mappings":"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","sourcesContent":["import { id, type InstantAdminDatabase } from \"@instantdb/admin\"\r\nimport { initLogger } from \"braintrust\"\r\nimport {\r\n createUIMessageStream,\r\n smoothStream,\r\n stepCountIs,\r\n streamText,\r\n tool,\r\n type Tool,\r\n type UIMessage,\r\n type UIMessageStreamWriter,\r\n} from \"ai\"\r\nimport { openai } from \"@ai-sdk/openai\"\r\nimport { z } from \"zod\"\r\n\r\nimport type { SchemaOf } from \"@ekairos/domain\"\r\nimport { storyDomain } from \"./schema\"\r\nimport type {\r\n ContextEvent,\r\n ContextIdentifier,\r\n StoredContext,\r\n} from \"./service\"\r\nimport { AgentService } from \"./service\"\r\nimport {\r\n createAssistantEventFromUIMessages,\r\n convertEventsToModelMessages,\r\n} from \"./events\"\r\n\r\n// Inicializar Braintrust logger\r\nconst logger = initLogger({\r\n projectName: \"pulzar platform\",\r\n apiKey: process.env.BRAINTRUST_API_KEY,\r\n})\r\n\r\n// Define your custom message type with data part schemas\r\nexport type AgentMessage = UIMessage<\r\n never, // metadata type\r\n {\r\n weather: {\r\n city: string\r\n weather?: string\r\n status: \"loading\" | \"success\"\r\n }\r\n notification: {\r\n message: string\r\n level: \"info\" | \"warning\" | \"error\"\r\n }\r\n } // data parts type\r\n>\r\n\r\nexport interface StoryOptions {\r\n onEventCreated?: (event: any) => void | Promise<void>\r\n evaluateToolCalls?: (toolCalls: any[]) => Promise<{\r\n success: boolean\r\n message?: string\r\n }>\r\n onToolCallExecuted?: (executionEvent: any) => void | Promise<void>\r\n onEnd?: (\r\n lastEvent: ContextEvent\r\n ) => void | { end?: boolean } | Promise<void | { end?: boolean }>\r\n}\r\n\r\nexport interface ProgressStreamOptions {\r\n reasoningEffort?: \"off\" | \"low\" | \"medium\" | \"high\"\r\n webSearch?: boolean\r\n}\r\n\r\nexport type DataStreamWriter = UIMessageStreamWriter<AgentMessage>\r\nconst createDataStream = createUIMessageStream\r\n\r\nexport abstract class Story<Context> {\r\n protected db: InstantAdminDatabase<SchemaOf<typeof storyDomain>>\r\n protected agentService: AgentService\r\n\r\n constructor(\r\n db: InstantAdminDatabase<SchemaOf<typeof storyDomain>>,\r\n private opts: StoryOptions = {}\r\n ) {\r\n this.db = db\r\n this.agentService = new AgentService(db)\r\n }\r\n\r\n protected abstract buildSystemPrompt(\r\n context: StoredContext<Context>,\r\n ...args: any[]\r\n ): Promise<string> | string\r\n protected abstract buildTools(\r\n context: StoredContext<Context>,\r\n dataStream: DataStreamWriter\r\n ): Promise<Record<string, Tool>>\r\n protected abstract initialize(context: StoredContext<Context>): Promise<Context>\r\n\r\n protected getModel(_context: StoredContext<Context>) {\r\n return \"openai/gpt-5\"\r\n }\r\n\r\n protected includeBaseTools(): {\r\n createMessage: boolean\r\n requestDirection: boolean\r\n end: boolean\r\n } {\r\n return { createMessage: true, requestDirection: true, end: true }\r\n }\r\n\r\n protected async getFinalizationToolNames(): Promise<string[]> {\r\n return []\r\n }\r\n\r\n private static readonly FINAL_TOOL_NAMES = [\r\n \"createMessage\",\r\n \"requestDirection\",\r\n \"end\",\r\n ]\r\n\r\n protected getBaseTools(\r\n _dataStream: DataStreamWriter,\r\n _threadId: string\r\n ): Record<string, Tool> {\r\n const include = this.includeBaseTools()\r\n const baseTools: Record<string, Tool> = {}\r\n\r\n if (include.createMessage) {\r\n baseTools.createMessage = tool({\r\n description:\r\n \"Send a message to the user. Use for final confirmations or information.\",\r\n inputSchema: z.object({\r\n message: z.string().describe(\"Message for the user in markdown format\"),\r\n type: z\r\n .enum([\"info\", \"confirmation\", \"warning\", \"error\", \"success\"])\r\n .default(\"info\"),\r\n includeContext: z.boolean().optional(),\r\n }),\r\n })\r\n }\r\n\r\n if (include.requestDirection) {\r\n baseTools.requestDirection = tool({\r\n description: \"Ask a human for guidance when blocked or unsure.\",\r\n inputSchema: z.object({\r\n issue: z.string(),\r\n context: z.string(),\r\n suggestedActions: z.array(z.string()).optional(),\r\n urgency: z.enum([\"low\", \"medium\", \"high\"]).default(\"medium\"),\r\n }),\r\n })\r\n }\r\n\r\n if (include.end) {\r\n baseTools.end = tool({\r\n description: \"End the current interaction loop.\",\r\n inputSchema: z.object({}).strict(),\r\n execute: async () => {\r\n return { success: true, message: \"Ended\" }\r\n },\r\n })\r\n }\r\n\r\n return baseTools\r\n }\r\n\r\n protected async executeCreateMessage(\r\n eventId: string,\r\n args: {\r\n message: string\r\n type: \"info\" | \"confirmation\" | \"warning\" | \"error\" | \"success\"\r\n includeContext?: boolean\r\n },\r\n threadId: string,\r\n dataStream?: DataStreamWriter\r\n ): Promise<any> {\r\n const assistantMessage = {\r\n id: eventId,\r\n role: \"assistant\" as const,\r\n content: args.message,\r\n createdAt: new Date(),\r\n } as any\r\n try {\r\n await this.saveMessagesToThread(threadId, [assistantMessage])\r\n } catch {\r\n // noop\r\n }\r\n if (dataStream) {\r\n // dataStream.writeData(...)\r\n }\r\n return {\r\n success: true,\r\n message: args.message,\r\n data: { messageId: assistantMessage.id, threadId },\r\n }\r\n }\r\n\r\n protected async executeRequestDirection(\r\n eventId: string,\r\n args: {\r\n issue: string\r\n context: string\r\n suggestedActions?: string[]\r\n urgency: \"low\" | \"medium\" | \"high\"\r\n },\r\n threadId: string,\r\n _dataStream?: DataStreamWriter\r\n ): Promise<any> {\r\n const systemMessage = {\r\n id: eventId,\r\n role: \"assistant\" as const,\r\n content: `Direction requested: ${args.issue}\\nContext: ${args.context}`,\r\n createdAt: new Date(),\r\n } as any\r\n return { success: true, message: \"Direction requested\", data: { messageId: systemMessage.id, threadId } }\r\n }\r\n\r\n public async progressStream(\r\n incomingEvent: ContextEvent,\r\n contextIdentifier: ContextIdentifier | null,\r\n options?: ProgressStreamOptions\r\n ) {\r\n // get or create context\r\n const currentContext =\r\n await this.agentService.getOrCreateContext<Context>(contextIdentifier)\r\n\r\n const contextSelector: ContextIdentifier = contextIdentifier?.id\r\n ? { id: String(contextIdentifier.id) }\r\n : contextIdentifier?.key\r\n ? { key: contextIdentifier.key }\r\n : { id: String(currentContext.id) }\r\n\r\n // save incoming event\r\n const triggerEvent = await this.agentService.saveEvent(\r\n contextSelector,\r\n incomingEvent\r\n )\r\n\r\n const triggerEventId = triggerEvent.id // trigger event id\r\n const eventId = id() // reaction event id\r\n\r\n // Set context status to \"streaming\" before creating execution\r\n await this.agentService.updateContextStatus(contextSelector, \"streaming\")\r\n\r\n // create execution and set context status\r\n const execution = await this.agentService.createExecution(\r\n contextSelector,\r\n triggerEventId,\r\n eventId\r\n )\r\n const executionId = execution.id\r\n\r\n let latestReactionEvent: ContextEvent | null = null\r\n let executionStatus: \"executing\" | \"completed\" | \"failed\" = \"executing\"\r\n\r\n const markFailure = async () => {\r\n if (latestReactionEvent && latestReactionEvent.status !== \"failed\") {\r\n try {\r\n latestReactionEvent = await this.agentService.updateEvent(\r\n latestReactionEvent.id,\r\n {\r\n ...latestReactionEvent,\r\n status: \"failed\",\r\n }\r\n )\r\n } catch (eventError) {\r\n console.error(\"Failed to mark reaction event as failed\", eventError)\r\n }\r\n }\r\n\r\n if (executionStatus === \"executing\") {\r\n try {\r\n await this.agentService.completeExecution(\r\n contextSelector,\r\n executionId,\r\n \"failed\"\r\n )\r\n executionStatus = \"failed\"\r\n } catch (executionError) {\r\n console.error(\"Failed to mark execution as failed\", executionError)\r\n }\r\n }\r\n }\r\n\r\n const dataStreamResult = createDataStream({\r\n execute: async ({ writer: dataStream }: { writer: DataStreamWriter }) => {\r\n let loopSafety = 0\r\n const MAX_LOOPS = 20\r\n\r\n // load previous events (already in chronological order from InstantDB)\r\n const events: ContextEvent[] = await this.agentService.getEvents(\r\n contextSelector\r\n )\r\n\r\n let reactionEvent = await this.agentService.saveEvent(contextSelector, {\r\n id: eventId,\r\n type: \"assistant\",\r\n channel: \"agent\",\r\n createdAt: new Date().toISOString(),\r\n content: { parts: [] },\r\n status: \"pending\",\r\n } as any)\r\n latestReactionEvent = reactionEvent\r\n\r\n dataStream.write({ type: \"event-start\", data: { eventId: eventId } } as any)\r\n\r\n while (loopSafety < MAX_LOOPS) {\r\n dataStream.write({ type: \"start-step\" } as any)\r\n loopSafety++\r\n\r\n // Read context\r\n const currentContext = await this.agentService.getContext<Context>(\r\n contextSelector\r\n )\r\n dataStream.write({\r\n type: \"data-context-id\",\r\n data: { contextId: currentContext.id },\r\n } as any)\r\n\r\n // Initialize on each loop and get new context data\r\n const contextContent = await this.initialize(currentContext)\r\n\r\n // Update context\r\n const updatedContext = await this.agentService.updateContextContent(\r\n { id: String(currentContext.id) },\r\n contextContent\r\n )\r\n\r\n // Build tools\r\n const subclassToolsAll = await this.buildTools(updatedContext, dataStream)\r\n\r\n // Build base tools for agent loop control\r\n const baseTools = this.getBaseTools(dataStream, String(updatedContext.id))\r\n const tools: Record<string, Tool> = { ...subclassToolsAll, ...baseTools }\r\n\r\n // Add web search if enabled\r\n if (options?.webSearch) {\r\n tools.web_search = openai.tools.webSearch() as any\r\n }\r\n\r\n // Extract execute functions from tools\r\n const executeMap: Record<string, (args: any) => Promise<any>> = {}\r\n for (const [name, t] of Object.entries(subclassToolsAll)) {\r\n if ((t as any).execute) {\r\n executeMap[name] = (t as any).execute as (args: any) => Promise<any>\r\n }\r\n }\r\n\r\n const include = this.includeBaseTools()\r\n if (include.createMessage) {\r\n executeMap[\"createMessage\"] = (args: any) =>\r\n this.executeCreateMessage(\r\n eventId,\r\n args,\r\n String(updatedContext.id),\r\n dataStream\r\n )\r\n }\r\n if (include.requestDirection) {\r\n executeMap[\"requestDirection\"] = (args: any) =>\r\n this.executeRequestDirection(\r\n eventId,\r\n args,\r\n String(updatedContext.id),\r\n dataStream\r\n )\r\n }\r\n\r\n // Remove execute from tool definitions before sending to model\r\n for (const [, t] of Object.entries(tools)) {\r\n delete (t as any).execute\r\n }\r\n\r\n const messagesForModel = await convertEventsToModelMessages(\r\n reactionEvent.status !== \"pending\" ? [...events, reactionEvent] : [...events],\r\n this.db\r\n )\r\n\r\n const systemPrompt = await this.buildSystemPrompt(updatedContext)\r\n\r\n const providerOptions: any = {}\r\n const hasReasoning =\r\n options?.reasoningEffort && options.reasoningEffort !== \"off\"\r\n\r\n if (hasReasoning) {\r\n providerOptions.openai = {\r\n reasoningEffort: options.reasoningEffort,\r\n reasoningSummary: \"detailed\",\r\n }\r\n }\r\n\r\n // Allow more steps when using reasoning to give the model time to think\r\n const maxSteps = hasReasoning ? 5 : 1\r\n\r\n const result = streamText({\r\n model: this.getModel(updatedContext) as any,\r\n system: systemPrompt,\r\n messages: messagesForModel as any,\r\n tools,\r\n toolChoice: \"required\",\r\n stopWhen: stepCountIs(maxSteps),\r\n experimental_transform: smoothStream({\r\n delayInMs: 30,\r\n chunking: \"word\",\r\n }),\r\n ...(Object.keys(providerOptions).length > 0 && { providerOptions }),\r\n })\r\n\r\n result.consumeStream()\r\n\r\n let resolveFinish!: (value: ContextEvent) => void\r\n let rejectFinish!: (reason?: unknown) => void\r\n const finishPromise = new Promise<ContextEvent>((resolve, reject) => {\r\n resolveFinish = resolve\r\n rejectFinish = reject\r\n })\r\n\r\n dataStream.merge(\r\n result\r\n .toUIMessageStream({\r\n sendStart: false,\r\n generateMessageId: () => eventId,\r\n messageMetadata() {\r\n return {\r\n eventId: eventId,\r\n }\r\n },\r\n onFinish: ({ messages }) => {\r\n const lastEvent = createAssistantEventFromUIMessages(\r\n eventId,\r\n messages as any\r\n )\r\n resolveFinish(lastEvent)\r\n },\r\n onError: (e: unknown) => {\r\n rejectFinish(e)\r\n const message = e instanceof Error ? e.message : String(e)\r\n return message\r\n },\r\n })\r\n .pipeThrough(\r\n new TransformStream({\r\n transform(chunk: any, controller: any) {\r\n if (chunk.type === \"start\") return\r\n if (chunk.type === \"finish-step\") return\r\n if (chunk.type === \"start-step\") return\r\n if (chunk.type === \"finish\") return\r\n controller.enqueue(chunk as any)\r\n },\r\n })\r\n )\r\n )\r\n\r\n const lastEvent = await finishPromise\r\n\r\n const toolCalls = (lastEvent.content.parts || []).reduce(\r\n (acc: any[], p: any) => {\r\n if (typeof p.type === \"string\" && p.type.startsWith(\"tool-\")) {\r\n const toolName = p.type.split(\"-\")[1]\r\n acc.push({ toolCallId: p.toolCallId, toolName: toolName, args: p.input })\r\n }\r\n return acc\r\n },\r\n []\r\n )\r\n\r\n if (!toolCalls.length) {\r\n const shouldEndInteraction = await this.callOnEnd(lastEvent)\r\n if (shouldEndInteraction) {\r\n break\r\n }\r\n continue\r\n }\r\n\r\n const reactionEventWithParts = {\r\n ...reactionEvent,\r\n content: { parts: [...reactionEvent.content.parts, ...lastEvent.content.parts] },\r\n }\r\n\r\n let currentEventState = await this.agentService.updateEvent(\r\n reactionEvent.id,\r\n reactionEventWithParts\r\n )\r\n latestReactionEvent = currentEventState\r\n\r\n const executionResults = await Promise.all(\r\n toolCalls.map(async (tc: any) => {\r\n let execSuccess = true\r\n let execMessage = \"Executed\"\r\n let execResult: any = null\r\n try {\r\n const execFn = executeMap[tc.toolName]\r\n if (execFn) {\r\n execResult = await execFn(tc.args)\r\n execSuccess = execResult?.success !== false\r\n execMessage = execResult?.message || execMessage\r\n }\r\n } catch (err: any) {\r\n execSuccess = false\r\n execMessage = err.message\r\n }\r\n return { tc, execSuccess, execMessage, execResult }\r\n })\r\n )\r\n\r\n let exitOuterLoop = false\r\n const customFinalizationTools = await this.getFinalizationToolNames()\r\n const allFinalToolNames = [...Story.FINAL_TOOL_NAMES, ...customFinalizationTools]\r\n\r\n for (const { tc, execSuccess, execMessage, execResult } of executionResults) {\r\n try {\r\n if (execSuccess) {\r\n dataStream.write({\r\n type: \"tool-output-available\",\r\n toolCallId: tc.toolCallId,\r\n output: execResult,\r\n } as any)\r\n } else {\r\n dataStream.write({\r\n type: \"tool-output-error\",\r\n toolCallId: tc.toolCallId,\r\n errorText: String(execMessage || \"Error\"),\r\n } as any)\r\n }\r\n } catch (e) {\r\n console.error(\"Failed to write tool result to stream\", e)\r\n }\r\n\r\n const existingParts = currentEventState?.content?.parts || []\r\n const mergedParts = existingParts.map((p: any) => {\r\n if (p.type === `tool-${tc.toolName}` && p.toolCallId === tc.toolCallId) {\r\n if (execSuccess) {\r\n return { ...p, state: \"output-available\", output: execResult }\r\n }\r\n return { ...p, state: \"output-error\", errorText: String(execMessage || \"Error\") }\r\n }\r\n return p\r\n })\r\n\r\n currentEventState = await this.agentService.updateEvent(\r\n currentEventState.id,\r\n {\r\n id: currentEventState.id,\r\n type: currentEventState.type,\r\n channel: \"agent\",\r\n createdAt: currentEventState.createdAt,\r\n content: { parts: mergedParts },\r\n } as any\r\n )\r\n\r\n dataStream.write({ type: \"finish-step\" } as any)\r\n\r\n await this.opts.onToolCallExecuted?.({\r\n id: currentEventState.id,\r\n toolCall: tc,\r\n event: currentEventState.id,\r\n success: execSuccess,\r\n message: execMessage,\r\n result: execResult,\r\n })\r\n\r\n let shouldEnd = false\r\n if (!execSuccess) {\r\n const shouldEndInteraction = await this.callOnEnd(lastEvent)\r\n if (shouldEndInteraction) shouldEnd = true\r\n }\r\n\r\n if (!shouldEnd) {\r\n if (allFinalToolNames.includes(tc.toolName)) {\r\n const shouldEndInteraction = await this.callOnEnd(lastEvent)\r\n if (shouldEndInteraction) shouldEnd = true\r\n }\r\n }\r\n\r\n if (shouldEnd) {\r\n dataStream.write({ type: \"finish\", override: true } as any)\r\n exitOuterLoop = true\r\n break\r\n }\r\n }\r\n\r\n reactionEvent = currentEventState\r\n\r\n if (exitOuterLoop) {\r\n break\r\n }\r\n }\r\n\r\n reactionEvent = await this.agentService.updateEvent(reactionEvent.id, {\r\n ...reactionEvent,\r\n status: \"completed\",\r\n } as any)\r\n latestReactionEvent = reactionEvent\r\n try {\r\n await this.agentService.completeExecution(contextSelector, executionId, \"completed\")\r\n executionStatus = \"completed\"\r\n } catch (error) {\r\n console.error(\"Failed to mark execution as completed\", error)\r\n }\r\n },\r\n onError: (error) => {\r\n console.error(\"Agent error:\", error)\r\n void markFailure()\r\n return error instanceof Error ? error.message : String(error)\r\n },\r\n onFinish: async () => {\r\n if (executionStatus === \"executing\") {\r\n try {\r\n await this.agentService.completeExecution(contextSelector, executionId, \"completed\")\r\n executionStatus = \"completed\"\r\n } catch (executionError) {\r\n console.error(\"Failed to finalize execution on finish\", executionError)\r\n }\r\n }\r\n },\r\n })\r\n\r\n const dataStreamFilteredResult = dataStreamResult.pipeThrough(\r\n new TransformStream({\r\n transform(chunk: any, controller: any) {\r\n if (chunk.type === \"start\") return\r\n if (chunk.type === \"event-start\") {\r\n controller.enqueue({ type: \"start\", messageId: chunk.data.eventId })\r\n return\r\n }\r\n controller.enqueue(chunk as any)\r\n },\r\n })\r\n )\r\n\r\n return {\r\n contextId: currentContext.id,\r\n triggerEventId,\r\n reactionEventId: eventId,\r\n stream: dataStreamFilteredResult,\r\n executionId,\r\n }\r\n }\r\n\r\n private async saveMessagesToThread(_threadId: string, _messages: Array<any>) {\r\n // Placeholder for persistence hook. Not implemented in current scope.\r\n return\r\n }\r\n\r\n private async callOnEnd(lastEvent: ContextEvent): Promise<boolean> {\r\n if (!this.opts.onEnd) {\r\n return true\r\n }\r\n\r\n try {\r\n const result = await this.opts.onEnd(lastEvent)\r\n if (typeof result === \"boolean\") {\r\n return result\r\n }\r\n if (result && typeof result === \"object\") {\r\n if (Object.prototype.hasOwnProperty.call(result, \"end\")) {\r\n return Boolean((result as any).end)\r\n }\r\n }\r\n return true\r\n } catch (error) {\r\n console.error(\"onEnd callback failed\", error)\r\n return true\r\n }\r\n }\r\n}\r\n\r\n// NOTE: No `Agent` alias — la API pública es Story.\r\n\r\n\r\n"]}
|