@kortyx/agent 0.14.2 → 0.15.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/CHANGELOG.md +23 -0
- package/LICENSE +51 -43
- package/dist/index.d.ts +22 -4
- package/dist/index.js +518 -26
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ __export(index_exports, {
|
|
|
29
29
|
parseChatRequestBody: () => parseChatRequestBody,
|
|
30
30
|
parseCheckpointRequestBody: () => parseCheckpointRequestBody,
|
|
31
31
|
parseResumeMeta: () => parseResumeMeta,
|
|
32
|
+
projectWorkflowTopology: () => projectWorkflowTopology,
|
|
32
33
|
streamChat: () => streamChat,
|
|
33
34
|
streamChatFromRoute: () => streamChatFromRoute,
|
|
34
35
|
transformGraphStreamForUI: () => transformGraphStreamForUI,
|
|
@@ -187,6 +188,266 @@ var import_providers = require("@kortyx/providers");
|
|
|
187
188
|
var import_runtime4 = require("@kortyx/runtime");
|
|
188
189
|
var import_zod2 = require("zod");
|
|
189
190
|
|
|
191
|
+
// src/telemetry/events.ts
|
|
192
|
+
var import_node_crypto = require("crypto");
|
|
193
|
+
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
194
|
+
var createId = () => {
|
|
195
|
+
try {
|
|
196
|
+
return (0, import_node_crypto.randomUUID)();
|
|
197
|
+
} catch {
|
|
198
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
var shouldCaptureTelemetryContent = (value, side) => {
|
|
202
|
+
if (value === true) return true;
|
|
203
|
+
return Boolean(
|
|
204
|
+
value && typeof value === "object" && !Array.isArray(value) && value[side] === true
|
|
205
|
+
);
|
|
206
|
+
};
|
|
207
|
+
var emitTelemetryEvent = (args) => {
|
|
208
|
+
const telemetry = isRecord(args.config.telemetry) ? args.config.telemetry : void 0;
|
|
209
|
+
const base = telemetry?.correlation;
|
|
210
|
+
const runId = args.correlation?.runId ?? base?.runId;
|
|
211
|
+
const workflowId = args.correlation?.workflowId ?? base?.workflowId;
|
|
212
|
+
if (!telemetry?.reporter || !telemetry.environment || !telemetry.service || !runId || !workflowId) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const context = isRecord(args.config.context) ? args.config.context : {};
|
|
216
|
+
const event = {
|
|
217
|
+
schemaVersion: 1,
|
|
218
|
+
eventId: createId(),
|
|
219
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
220
|
+
environment: telemetry.environment,
|
|
221
|
+
service: telemetry.service,
|
|
222
|
+
correlation: {
|
|
223
|
+
runId,
|
|
224
|
+
workflowId,
|
|
225
|
+
...base?.sessionId ? { sessionId: base.sessionId } : {},
|
|
226
|
+
...base?.workflowRevisionId ? { workflowRevisionId: base.workflowRevisionId } : {},
|
|
227
|
+
...base?.topologyHash ? { topologyHash: base.topologyHash } : {},
|
|
228
|
+
...base?.nodeId ? { nodeId: base.nodeId } : {},
|
|
229
|
+
...args.correlation ?? {}
|
|
230
|
+
},
|
|
231
|
+
...telemetry.metadata || telemetry.tags || context.userId || context.tenantId ? {
|
|
232
|
+
context: {
|
|
233
|
+
...typeof context.userId === "string" ? { userId: context.userId } : {},
|
|
234
|
+
...typeof context.tenantId === "string" ? { tenantId: context.tenantId } : {},
|
|
235
|
+
...telemetry.tags ? { tags: telemetry.tags } : {},
|
|
236
|
+
...telemetry.metadata ? { metadata: telemetry.metadata } : {}
|
|
237
|
+
}
|
|
238
|
+
} : {},
|
|
239
|
+
type: args.type,
|
|
240
|
+
payload: args.payload
|
|
241
|
+
};
|
|
242
|
+
try {
|
|
243
|
+
void Promise.resolve(telemetry.reporter.emit([event])).then(async () => {
|
|
244
|
+
if (!args.flush) return;
|
|
245
|
+
const flush = telemetry.flush;
|
|
246
|
+
if (typeof flush === "function") await flush.call(telemetry);
|
|
247
|
+
}).catch(() => {
|
|
248
|
+
});
|
|
249
|
+
} catch {
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// src/telemetry/topology.ts
|
|
254
|
+
var import_node_crypto2 = require("crypto");
|
|
255
|
+
var isRecord2 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
256
|
+
var stableValue = (value) => {
|
|
257
|
+
if (Array.isArray(value)) return value.map(stableValue);
|
|
258
|
+
if (!isRecord2(value)) return value;
|
|
259
|
+
return Object.fromEntries(
|
|
260
|
+
Object.entries(value).filter(([, nested]) => typeof nested !== "function").sort(([a], [b]) => a.localeCompare(b)).map(([key, nested]) => [key, stableValue(nested)])
|
|
261
|
+
);
|
|
262
|
+
};
|
|
263
|
+
var asString = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
|
|
264
|
+
var metadata = (value) => isRecord2(value) ? stableValue(value) : void 0;
|
|
265
|
+
var tagsFrom = (workflow) => {
|
|
266
|
+
const raw = isRecord2(workflow.metadata) ? workflow.metadata.tags : void 0;
|
|
267
|
+
if (!Array.isArray(raw)) return void 0;
|
|
268
|
+
const tags = raw.filter((tag) => typeof tag === "string").sort();
|
|
269
|
+
return tags.length > 0 ? tags : void 0;
|
|
270
|
+
};
|
|
271
|
+
var wordsFrom = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1-$2").split(/[^a-zA-Z0-9]+/).map((word) => word.toLowerCase()).filter(Boolean);
|
|
272
|
+
var camelFromWorkflowId = (workflowId) => {
|
|
273
|
+
const [first = "", ...rest] = wordsFrom(workflowId);
|
|
274
|
+
return [
|
|
275
|
+
first,
|
|
276
|
+
...rest.map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`)
|
|
277
|
+
].join("");
|
|
278
|
+
};
|
|
279
|
+
var resolveMemberTransitionTarget = (memberName, knownWorkflowIds) => {
|
|
280
|
+
const exact = knownWorkflowIds.find(
|
|
281
|
+
(workflowId) => camelFromWorkflowId(workflowId) === memberName
|
|
282
|
+
);
|
|
283
|
+
if (exact) return exact;
|
|
284
|
+
const memberWords = new Set(wordsFrom(memberName));
|
|
285
|
+
const candidates = knownWorkflowIds.map((workflowId) => {
|
|
286
|
+
const workflowWords = wordsFrom(workflowId);
|
|
287
|
+
const matched = workflowWords.filter((word) => memberWords.has(word));
|
|
288
|
+
return {
|
|
289
|
+
workflowId,
|
|
290
|
+
matched: matched.length,
|
|
291
|
+
total: workflowWords.length
|
|
292
|
+
};
|
|
293
|
+
}).filter(
|
|
294
|
+
(candidate) => candidate.total > 0 && candidate.matched === candidate.total
|
|
295
|
+
).sort(
|
|
296
|
+
(a, b) => b.matched - a.matched || a.workflowId.localeCompare(b.workflowId)
|
|
297
|
+
);
|
|
298
|
+
if (candidates.length !== 1) return void 0;
|
|
299
|
+
return candidates[0]?.workflowId;
|
|
300
|
+
};
|
|
301
|
+
var transitionTargetsFromRun = (run, knownWorkflowIds) => {
|
|
302
|
+
if (typeof run !== "function") return [];
|
|
303
|
+
const source = Function.prototype.toString.call(run);
|
|
304
|
+
const targets = /* @__PURE__ */ new Set();
|
|
305
|
+
for (const match of source.matchAll(
|
|
306
|
+
/\btransitionTo\s*:\s*(['"`])([^'"`$]+)\1/g
|
|
307
|
+
)) {
|
|
308
|
+
const target = match[2]?.trim();
|
|
309
|
+
if (target) targets.add(target);
|
|
310
|
+
}
|
|
311
|
+
for (const match of source.matchAll(
|
|
312
|
+
/\btransitionTo\s*:\s*(?:[A-Za-z_$][\w$]*\.)+([A-Za-z_$][\w$]*)/g
|
|
313
|
+
)) {
|
|
314
|
+
const memberName = match[1];
|
|
315
|
+
const target = resolveMemberTransitionTarget(memberName, knownWorkflowIds);
|
|
316
|
+
if (target) targets.add(target);
|
|
317
|
+
}
|
|
318
|
+
for (const match of source.matchAll(
|
|
319
|
+
/\btransitionTo\s*:\s*(?:[A-Za-z_$][\w$]*\.)*[A-Za-z_$][\w$]*\[['"`]([A-Za-z_$][\w$]*)['"`]\]/g
|
|
320
|
+
)) {
|
|
321
|
+
const memberName = match[1];
|
|
322
|
+
const target = resolveMemberTransitionTarget(memberName, knownWorkflowIds);
|
|
323
|
+
if (target) targets.add(target);
|
|
324
|
+
}
|
|
325
|
+
return [...targets].sort();
|
|
326
|
+
};
|
|
327
|
+
var transitionsFromNodes = (workflow, knownWorkflowIds) => {
|
|
328
|
+
const transitions = /* @__PURE__ */ new Map();
|
|
329
|
+
for (const [sourceNodeId, node] of Object.entries(
|
|
330
|
+
workflow.nodes
|
|
331
|
+
)) {
|
|
332
|
+
for (const targetWorkflowId of transitionTargetsFromRun(
|
|
333
|
+
node.run,
|
|
334
|
+
knownWorkflowIds
|
|
335
|
+
)) {
|
|
336
|
+
if (targetWorkflowId === workflow.id) continue;
|
|
337
|
+
const key = `${sourceNodeId}:${targetWorkflowId}`;
|
|
338
|
+
transitions.set(key, { sourceNodeId, targetWorkflowId });
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return [...transitions.values()].sort(
|
|
342
|
+
(a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b))
|
|
343
|
+
);
|
|
344
|
+
};
|
|
345
|
+
var projectWorkflowTopology = (args) => {
|
|
346
|
+
const nodes = Object.entries(
|
|
347
|
+
args.workflow.nodes
|
|
348
|
+
).map(([id, node]) => {
|
|
349
|
+
const nodeMetadata = metadata(node.metadata);
|
|
350
|
+
const params = metadata(node.params);
|
|
351
|
+
const model = isRecord2(node.params) ? isRecord2(node.params.model) ? node.params.model : void 0 : void 0;
|
|
352
|
+
const provider = isRecord2(model) ? asString(model.provider) ?? asString(model.providerId) : void 0;
|
|
353
|
+
const modelName = isRecord2(model) ? asString(model.name) ?? asString(model.modelId) : void 0;
|
|
354
|
+
return {
|
|
355
|
+
id,
|
|
356
|
+
...asString(nodeMetadata?.label) ? { label: asString(nodeMetadata?.label) } : {},
|
|
357
|
+
...asString(nodeMetadata?.type) ? { type: asString(nodeMetadata?.type) } : {},
|
|
358
|
+
...provider ? { provider } : {},
|
|
359
|
+
...modelName ? { model: modelName } : {},
|
|
360
|
+
...nodeMetadata ? { metadata: nodeMetadata } : {},
|
|
361
|
+
// These fields feed the hash but are intentionally not sent as Studio
|
|
362
|
+
// display metadata. They are stripped below after hashing.
|
|
363
|
+
_execution: {
|
|
364
|
+
...typeof node.run === "string" ? { run: node.run } : {},
|
|
365
|
+
...params ? { params } : {},
|
|
366
|
+
...node.behavior ? { behavior: stableValue(node.behavior) } : {}
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
}).sort((a, b) => a.id.localeCompare(b.id));
|
|
370
|
+
const edges = args.workflow.edges.map((edge) => {
|
|
371
|
+
const condition = isRecord2(edge[2]) ? asString(edge[2].when) : void 0;
|
|
372
|
+
return {
|
|
373
|
+
sourceNodeId: edge[0],
|
|
374
|
+
targetNodeId: edge[1],
|
|
375
|
+
...condition ? { condition } : {}
|
|
376
|
+
};
|
|
377
|
+
}).sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
|
|
378
|
+
const transitions = transitionsFromNodes(
|
|
379
|
+
args.workflow,
|
|
380
|
+
args.knownWorkflowIds ?? []
|
|
381
|
+
);
|
|
382
|
+
const tags = tagsFrom(args.workflow);
|
|
383
|
+
const hashInput = stableValue({
|
|
384
|
+
workflowId: args.workflow.id,
|
|
385
|
+
nodes: nodes.map((node) => ({ id: node.id, ...node._execution })),
|
|
386
|
+
edges,
|
|
387
|
+
transitions
|
|
388
|
+
});
|
|
389
|
+
const topologyHash = (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(hashInput)).digest("hex");
|
|
390
|
+
return {
|
|
391
|
+
schemaVersion: 1,
|
|
392
|
+
environment: args.environment,
|
|
393
|
+
service: args.service,
|
|
394
|
+
workflow: {
|
|
395
|
+
id: args.workflow.id,
|
|
396
|
+
declaredVersion: args.workflow.version,
|
|
397
|
+
...args.workflow.description ? { description: args.workflow.description } : {},
|
|
398
|
+
...tags ? { tags } : {},
|
|
399
|
+
topologyHash,
|
|
400
|
+
nodes: nodes.map(({ _execution: _ignored, ...node }) => node),
|
|
401
|
+
edges,
|
|
402
|
+
...transitions.length > 0 ? { transitions } : {}
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
};
|
|
406
|
+
var prepareWorkflowTelemetry = (args) => {
|
|
407
|
+
const telemetry = isRecord2(args.config.telemetry) ? args.config.telemetry : void 0;
|
|
408
|
+
if (!telemetry?.reporter || !telemetry.environment || !telemetry.service) {
|
|
409
|
+
return args.config;
|
|
410
|
+
}
|
|
411
|
+
let snapshot;
|
|
412
|
+
try {
|
|
413
|
+
snapshot = projectWorkflowTopology({
|
|
414
|
+
workflow: args.workflow,
|
|
415
|
+
environment: telemetry.environment,
|
|
416
|
+
service: telemetry.service,
|
|
417
|
+
knownWorkflowIds: args.knownWorkflowIds
|
|
418
|
+
});
|
|
419
|
+
} catch {
|
|
420
|
+
return args.config;
|
|
421
|
+
}
|
|
422
|
+
let workflowRevisionId;
|
|
423
|
+
try {
|
|
424
|
+
workflowRevisionId = telemetry.reporter.getWorkflowRevisionId?.({
|
|
425
|
+
environment: snapshot.environment,
|
|
426
|
+
workflowId: snapshot.workflow.id,
|
|
427
|
+
topologyHash: snapshot.workflow.topologyHash
|
|
428
|
+
});
|
|
429
|
+
void Promise.resolve(
|
|
430
|
+
telemetry.reporter.ensureWorkflowTopology(snapshot)
|
|
431
|
+
).catch(() => {
|
|
432
|
+
});
|
|
433
|
+
} catch {
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
...args.config,
|
|
437
|
+
telemetry: {
|
|
438
|
+
...telemetry,
|
|
439
|
+
correlation: {
|
|
440
|
+
...telemetry.correlation ?? {},
|
|
441
|
+
runId: args.runId,
|
|
442
|
+
...args.sessionId ? { sessionId: args.sessionId } : {},
|
|
443
|
+
workflowId: snapshot.workflow.id,
|
|
444
|
+
topologyHash: snapshot.workflow.topologyHash,
|
|
445
|
+
...workflowRevisionId ? { workflowRevisionId } : {}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
};
|
|
450
|
+
|
|
190
451
|
// src/chat/process-chat.ts
|
|
191
452
|
var import_runtime3 = require("@kortyx/runtime");
|
|
192
453
|
|
|
@@ -263,50 +524,71 @@ async function* transformGraphStreamForUI(stream, options = {}) {
|
|
|
263
524
|
}
|
|
264
525
|
|
|
265
526
|
// src/orchestrator.ts
|
|
266
|
-
var
|
|
267
|
-
var isGraphState = (value) =>
|
|
527
|
+
var isRecord3 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
528
|
+
var isGraphState = (value) => isRecord3(value) && typeof value.currentWorkflow === "string";
|
|
268
529
|
var getGraphCheckpointId = (snapshot) => {
|
|
269
|
-
if (!
|
|
270
|
-
const config =
|
|
271
|
-
const configurable = config &&
|
|
530
|
+
if (!isRecord3(snapshot)) return void 0;
|
|
531
|
+
const config = isRecord3(snapshot.config) ? snapshot.config : void 0;
|
|
532
|
+
const configurable = config && isRecord3(config.configurable) ? config.configurable : void 0;
|
|
272
533
|
const checkpointId = configurable?.checkpoint_id;
|
|
273
534
|
return typeof checkpointId === "string" && checkpointId.length > 0 ? checkpointId : void 0;
|
|
274
535
|
};
|
|
275
536
|
var getTraceAdapter = (config) => {
|
|
276
|
-
const telemetry =
|
|
537
|
+
const telemetry = isRecord3(config.telemetry) ? config.telemetry : void 0;
|
|
277
538
|
const traceAdapter = telemetry?.trace ?? config.reasonTrace;
|
|
278
|
-
return
|
|
539
|
+
return isRecord3(traceAdapter) ? traceAdapter : void 0;
|
|
279
540
|
};
|
|
280
541
|
async function orchestrateGraphStream({
|
|
281
542
|
sessionId,
|
|
282
543
|
runId,
|
|
283
544
|
graph,
|
|
284
545
|
state,
|
|
285
|
-
config,
|
|
546
|
+
config: initialConfig,
|
|
286
547
|
selectWorkflow,
|
|
548
|
+
knownWorkflowIds,
|
|
287
549
|
frameworkAdapter
|
|
288
550
|
}) {
|
|
289
551
|
const out = new import_node_stream.PassThrough({ objectMode: true });
|
|
552
|
+
let config = initialConfig;
|
|
290
553
|
let currentGraph = graph;
|
|
291
554
|
let currentState = state;
|
|
292
555
|
let finished = false;
|
|
293
556
|
let structuredSeq = 0;
|
|
294
557
|
const debugEnabled = Boolean(config?.features?.tracing);
|
|
295
558
|
const traceAdapter = getTraceAdapter(config);
|
|
296
|
-
const contextMeta =
|
|
297
|
-
const telemetryConfig =
|
|
559
|
+
const contextMeta = isRecord3(config.context) ? config.context : {};
|
|
560
|
+
const telemetryConfig = isRecord3(config.telemetry) ? config.telemetry : {};
|
|
561
|
+
const emitResumeFailure = (resumeError) => {
|
|
562
|
+
const interruptId = typeof config.telemetryInterruptId === "string" ? config.telemetryInterruptId : void 0;
|
|
563
|
+
if (!interruptId) return;
|
|
564
|
+
emitTelemetryEvent({
|
|
565
|
+
config,
|
|
566
|
+
type: "interrupt.resolved",
|
|
567
|
+
correlation: typeof config.telemetryInterruptNodeId === "string" ? { nodeId: config.telemetryInterruptNodeId } : void 0,
|
|
568
|
+
payload: {
|
|
569
|
+
interruptId,
|
|
570
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
571
|
+
resumeOutcome: "failed",
|
|
572
|
+
resumeError: resumeError instanceof Error ? resumeError.message : String(resumeError)
|
|
573
|
+
},
|
|
574
|
+
flush: true
|
|
575
|
+
});
|
|
576
|
+
};
|
|
577
|
+
const telemetryCorrelation = isRecord3(telemetryConfig.correlation) ? telemetryConfig.correlation : {};
|
|
298
578
|
const runSpanArgs = {
|
|
299
579
|
name: "kortyx.run",
|
|
300
580
|
attributes: {
|
|
301
581
|
...sessionId ? { sessionId } : {},
|
|
302
582
|
runId,
|
|
303
583
|
workflowId: state.currentWorkflow,
|
|
584
|
+
...typeof telemetryCorrelation.topologyHash === "string" ? { topologyHash: telemetryCorrelation.topologyHash } : {},
|
|
585
|
+
...typeof telemetryCorrelation.workflowRevisionId === "string" ? { workflowRevisionId: telemetryCorrelation.workflowRevisionId } : {},
|
|
304
586
|
...typeof contextMeta.userId === "string" ? { userId: contextMeta.userId } : {},
|
|
305
587
|
...typeof contextMeta.tenantId === "string" ? { tenantId: contextMeta.tenantId } : {}
|
|
306
588
|
},
|
|
307
589
|
telemetry: {
|
|
308
590
|
metadata: {
|
|
309
|
-
...
|
|
591
|
+
...isRecord3(telemetryConfig.metadata) ? telemetryConfig.metadata : {},
|
|
310
592
|
...contextMeta
|
|
311
593
|
},
|
|
312
594
|
tags: Array.isArray(telemetryConfig.tags) ? telemetryConfig.tags : void 0,
|
|
@@ -328,7 +610,9 @@ async function orchestrateGraphStream({
|
|
|
328
610
|
}
|
|
329
611
|
const pending = {
|
|
330
612
|
to: null,
|
|
331
|
-
payload: {}
|
|
613
|
+
payload: {},
|
|
614
|
+
sourceNodeId: void 0,
|
|
615
|
+
sourceWorkflowId: void 0
|
|
332
616
|
};
|
|
333
617
|
let lastStatusMsg = "";
|
|
334
618
|
let lastStatusAt = 0;
|
|
@@ -430,6 +714,34 @@ async function orchestrateGraphStream({
|
|
|
430
714
|
}))
|
|
431
715
|
}
|
|
432
716
|
});
|
|
717
|
+
emitTelemetryEvent({
|
|
718
|
+
config,
|
|
719
|
+
type: "interrupt.created",
|
|
720
|
+
correlation: { nodeId: record.node },
|
|
721
|
+
payload: {
|
|
722
|
+
interruptId: record.requestId,
|
|
723
|
+
requestId: record.requestId,
|
|
724
|
+
kind: record.schema.kind,
|
|
725
|
+
interactionMode: record.schema.kind === "text" ? "freeform" : record.options.length > 0 ? "static-options" : record.schema.schemaId ? "dynamic-picker" : "unknown",
|
|
726
|
+
...record.schema.schemaId ? { schemaId: record.schema.schemaId } : {},
|
|
727
|
+
...record.schema.schemaVersion ? { schemaVersion: record.schema.schemaVersion } : {},
|
|
728
|
+
...typeof record.schema.question === "string" && shouldCaptureTelemetryContent(telemetryConfig.captureContent, "output") ? { question: record.schema.question } : {},
|
|
729
|
+
...shouldCaptureTelemetryContent(
|
|
730
|
+
telemetryConfig.captureContent,
|
|
731
|
+
"output"
|
|
732
|
+
) ? {
|
|
733
|
+
options: record.options.map((option) => ({
|
|
734
|
+
id: option.id,
|
|
735
|
+
label: option.label,
|
|
736
|
+
...option.description ? { description: option.description } : {}
|
|
737
|
+
}))
|
|
738
|
+
} : {},
|
|
739
|
+
optionCount: record.options.length,
|
|
740
|
+
nodeId: record.node,
|
|
741
|
+
expiresAt: new Date(record.createdAt + record.ttlMs).toISOString()
|
|
742
|
+
},
|
|
743
|
+
flush: true
|
|
744
|
+
});
|
|
433
745
|
wroteHumanInput = true;
|
|
434
746
|
};
|
|
435
747
|
const forwardEmit = (event, payload) => {
|
|
@@ -595,6 +907,9 @@ async function orchestrateGraphStream({
|
|
|
595
907
|
});
|
|
596
908
|
pending.to = payload?.transitionTo ?? null;
|
|
597
909
|
pending.payload = payload?.payload ?? {};
|
|
910
|
+
const transition = payload;
|
|
911
|
+
pending.sourceNodeId = typeof transition.node === "string" ? transition.node : void 0;
|
|
912
|
+
pending.sourceWorkflowId = typeof transition.workflow === "string" ? transition.workflow : void 0;
|
|
598
913
|
return;
|
|
599
914
|
}
|
|
600
915
|
if (event === "interrupt") {
|
|
@@ -637,7 +952,7 @@ async function orchestrateGraphStream({
|
|
|
637
952
|
checkpoint_ns: checkpointNs
|
|
638
953
|
}
|
|
639
954
|
});
|
|
640
|
-
const values =
|
|
955
|
+
const values = isRecord3(snapshot) && "values" in snapshot ? snapshot.values : snapshot;
|
|
641
956
|
const checkpointId = getGraphCheckpointId(snapshot) ?? await readLatestGraphCheckpointId();
|
|
642
957
|
if (!isGraphState(values)) {
|
|
643
958
|
return checkpointId ? { state: currentState, checkpointId } : null;
|
|
@@ -696,11 +1011,40 @@ async function orchestrateGraphStream({
|
|
|
696
1011
|
}
|
|
697
1012
|
const transitionTo = pending.to;
|
|
698
1013
|
const transitionPayload = pending.payload;
|
|
1014
|
+
const sourceNodeId = pending.sourceNodeId;
|
|
1015
|
+
const sourceWorkflowId = pending.sourceWorkflowId;
|
|
699
1016
|
pending.to = null;
|
|
700
1017
|
pending.payload = {};
|
|
1018
|
+
pending.sourceNodeId = void 0;
|
|
1019
|
+
pending.sourceWorkflowId = void 0;
|
|
701
1020
|
if (transitionTo) {
|
|
702
1021
|
try {
|
|
703
1022
|
const nextWorkflow = await selectWorkflow(transitionTo);
|
|
1023
|
+
const sourceTelemetry = isRecord3(config.telemetry) ? config.telemetry : {};
|
|
1024
|
+
config = prepareWorkflowTelemetry({
|
|
1025
|
+
config,
|
|
1026
|
+
workflow: nextWorkflow,
|
|
1027
|
+
runId,
|
|
1028
|
+
sessionId,
|
|
1029
|
+
knownWorkflowIds
|
|
1030
|
+
});
|
|
1031
|
+
const targetTelemetry = isRecord3(config.telemetry) ? config.telemetry : {};
|
|
1032
|
+
emitTelemetryEvent({
|
|
1033
|
+
config,
|
|
1034
|
+
type: "workflow.transitioned",
|
|
1035
|
+
...sourceNodeId ? { correlation: { nodeId: sourceNodeId } } : {},
|
|
1036
|
+
payload: {
|
|
1037
|
+
sourceNodeId: sourceNodeId ?? "",
|
|
1038
|
+
sourceWorkflowId: sourceWorkflowId ?? String(currentState.currentWorkflow),
|
|
1039
|
+
...typeof sourceTelemetry.correlation === "object" && sourceTelemetry.correlation && typeof sourceTelemetry.correlation.workflowRevisionId === "string" ? {
|
|
1040
|
+
sourceWorkflowRevisionId: sourceTelemetry.correlation.workflowRevisionId
|
|
1041
|
+
} : {},
|
|
1042
|
+
targetWorkflowId: transitionTo,
|
|
1043
|
+
...typeof targetTelemetry.correlation === "object" && targetTelemetry.correlation && typeof targetTelemetry.correlation.workflowRevisionId === "string" ? {
|
|
1044
|
+
targetWorkflowRevisionId: targetTelemetry.correlation.workflowRevisionId
|
|
1045
|
+
} : {}
|
|
1046
|
+
}
|
|
1047
|
+
});
|
|
704
1048
|
const nextGraph = await (0, import_runtime.createExecutionGraph)(nextWorkflow, {
|
|
705
1049
|
...config,
|
|
706
1050
|
emit: forwardEmit
|
|
@@ -715,6 +1059,7 @@ async function orchestrateGraphStream({
|
|
|
715
1059
|
currentState = {
|
|
716
1060
|
...currentState,
|
|
717
1061
|
currentWorkflow: transitionTo,
|
|
1062
|
+
config,
|
|
718
1063
|
input: newInput,
|
|
719
1064
|
data: mergedData,
|
|
720
1065
|
ui: {}
|
|
@@ -804,6 +1149,16 @@ async function orchestrateGraphStream({
|
|
|
804
1149
|
turnIndex: checkpoint.turnIndex,
|
|
805
1150
|
...checkpoint.label ? { label: checkpoint.label } : {}
|
|
806
1151
|
});
|
|
1152
|
+
emitTelemetryEvent({
|
|
1153
|
+
config,
|
|
1154
|
+
type: "session.checkpointed",
|
|
1155
|
+
payload: {
|
|
1156
|
+
checkpointId: checkpoint.id,
|
|
1157
|
+
turnIndex: checkpoint.turnIndex,
|
|
1158
|
+
...checkpoint.parentCheckpointId ? { parentCheckpointId: checkpoint.parentCheckpointId } : {},
|
|
1159
|
+
nodes: checkpoint.nodes
|
|
1160
|
+
}
|
|
1161
|
+
});
|
|
807
1162
|
} catch (error) {
|
|
808
1163
|
console.error("[orchestrator] session checkpoint failed", error);
|
|
809
1164
|
}
|
|
@@ -853,6 +1208,16 @@ async function orchestrateGraphStream({
|
|
|
853
1208
|
turnIndex: checkpoint.turnIndex,
|
|
854
1209
|
...checkpoint.label ? { label: checkpoint.label } : {}
|
|
855
1210
|
});
|
|
1211
|
+
emitTelemetryEvent({
|
|
1212
|
+
config,
|
|
1213
|
+
type: "session.checkpointed",
|
|
1214
|
+
payload: {
|
|
1215
|
+
checkpointId: checkpoint.id,
|
|
1216
|
+
turnIndex: checkpoint.turnIndex,
|
|
1217
|
+
...checkpoint.parentCheckpointId ? { parentCheckpointId: checkpoint.parentCheckpointId } : {},
|
|
1218
|
+
nodes: checkpoint.nodes
|
|
1219
|
+
}
|
|
1220
|
+
});
|
|
856
1221
|
} catch (error) {
|
|
857
1222
|
console.error("[orchestrator] session checkpoint failed", error);
|
|
858
1223
|
}
|
|
@@ -887,6 +1252,7 @@ async function orchestrateGraphStream({
|
|
|
887
1252
|
}) : runLoop(fallbackRunSpan ?? {});
|
|
888
1253
|
runPromise.catch((err) => {
|
|
889
1254
|
fallbackRunSpan?.fail?.(err);
|
|
1255
|
+
emitResumeFailure(err);
|
|
890
1256
|
console.error("[error:orchestrateGraphStream]", err);
|
|
891
1257
|
out.write({
|
|
892
1258
|
type: "error",
|
|
@@ -899,11 +1265,16 @@ async function orchestrateGraphStream({
|
|
|
899
1265
|
}
|
|
900
1266
|
|
|
901
1267
|
// src/interrupt/resume-handler.ts
|
|
902
|
-
var
|
|
1268
|
+
var isRecord4 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1269
|
+
var responseFromSelection = (selected) => {
|
|
1270
|
+
if (selected.length === 0) return void 0;
|
|
1271
|
+
if (selected.length === 1) return selected[0];
|
|
1272
|
+
return JSON.stringify(selected);
|
|
1273
|
+
};
|
|
903
1274
|
function parseResumeMeta(msg) {
|
|
904
1275
|
if (!msg || !msg.metadata) return null;
|
|
905
1276
|
const raw = msg.metadata.resume;
|
|
906
|
-
if (!
|
|
1277
|
+
if (!isRecord4(raw)) return null;
|
|
907
1278
|
const token = typeof raw.token === "string" ? raw.token : "";
|
|
908
1279
|
const requestId = typeof raw.requestId === "string" ? raw.requestId : "";
|
|
909
1280
|
const cancel = raw.cancel === true;
|
|
@@ -911,10 +1282,10 @@ function parseResumeMeta(msg) {
|
|
|
911
1282
|
const rawSelected = raw.selected;
|
|
912
1283
|
if (typeof rawSelected === "string") selected = [rawSelected];
|
|
913
1284
|
else if (Array.isArray(rawSelected)) selected = rawSelected.map(String);
|
|
914
|
-
else if (
|
|
1285
|
+
else if (isRecord4(raw.choice) && typeof raw.choice.id === "string")
|
|
915
1286
|
selected = [raw.choice.id];
|
|
916
1287
|
else if (Array.isArray(raw.choices))
|
|
917
|
-
selected = raw.choices.map((c) =>
|
|
1288
|
+
selected = raw.choices.map((c) => isRecord4(c) ? c.id : void 0).filter((id) => typeof id === "string");
|
|
918
1289
|
if (!token || !requestId) return null;
|
|
919
1290
|
return { token, requestId, selected, cancel };
|
|
920
1291
|
}
|
|
@@ -923,6 +1294,7 @@ async function tryPrepareResumeStream({
|
|
|
923
1294
|
sessionId,
|
|
924
1295
|
config,
|
|
925
1296
|
selectWorkflow,
|
|
1297
|
+
knownWorkflowIds,
|
|
926
1298
|
defaultWorkflowId,
|
|
927
1299
|
applyResumeSelection,
|
|
928
1300
|
frameworkAdapter
|
|
@@ -940,6 +1312,21 @@ async function tryPrepareResumeStream({
|
|
|
940
1312
|
}
|
|
941
1313
|
if (meta.cancel) {
|
|
942
1314
|
await store.delete(pending.token);
|
|
1315
|
+
emitTelemetryEvent({
|
|
1316
|
+
config,
|
|
1317
|
+
type: "interrupt.cancelled",
|
|
1318
|
+
correlation: {
|
|
1319
|
+
runId: pending.runId,
|
|
1320
|
+
sessionId,
|
|
1321
|
+
workflowId: pending.workflow,
|
|
1322
|
+
nodeId: pending.node
|
|
1323
|
+
},
|
|
1324
|
+
payload: {
|
|
1325
|
+
interruptId: pending.requestId,
|
|
1326
|
+
reason: "cancelled_by_client"
|
|
1327
|
+
},
|
|
1328
|
+
flush: true
|
|
1329
|
+
});
|
|
943
1330
|
return null;
|
|
944
1331
|
}
|
|
945
1332
|
console.log(
|
|
@@ -948,10 +1335,10 @@ async function tryPrepareResumeStream({
|
|
|
948
1335
|
)} sessionId=${sessionId}`
|
|
949
1336
|
);
|
|
950
1337
|
const resumeData = applyResumeSelection ? applyResumeSelection({ pending, selected: meta.selected }) : meta.selected?.length ? { coordinates: String(meta.selected[0]) } : {};
|
|
951
|
-
const resumeDataPatch =
|
|
952
|
-
const pendingMeta =
|
|
953
|
-
const resumeStatePatch =
|
|
954
|
-
const pendingData =
|
|
1338
|
+
const resumeDataPatch = isRecord4(resumeData) ? resumeData : {};
|
|
1339
|
+
const pendingMeta = isRecord4(pending.schema?.meta) ? pending.schema.meta : {};
|
|
1340
|
+
const resumeStatePatch = isRecord4(pendingMeta.__kortyxResumeStatePatch) ? pendingMeta.__kortyxResumeStatePatch : void 0;
|
|
1341
|
+
const pendingData = isRecord4(pending.state?.data) ? pending.state?.data : {};
|
|
955
1342
|
const workflowId = typeof pending.workflow === "string" && pending.workflow.trim() ? pending.workflow : typeof defaultWorkflowId === "string" && defaultWorkflowId.trim() ? defaultWorkflowId : "job-search";
|
|
956
1343
|
const resumedState = {
|
|
957
1344
|
// For static breakpoints, resume with null input (set in orchestrator),
|
|
@@ -969,6 +1356,14 @@ async function tryPrepareResumeStream({
|
|
|
969
1356
|
}
|
|
970
1357
|
};
|
|
971
1358
|
const wf = await selectWorkflow(resumedState.currentWorkflow);
|
|
1359
|
+
const telemetryConfig = prepareWorkflowTelemetry({
|
|
1360
|
+
config,
|
|
1361
|
+
workflow: wf,
|
|
1362
|
+
runId: pending.runId,
|
|
1363
|
+
sessionId,
|
|
1364
|
+
knownWorkflowIds
|
|
1365
|
+
});
|
|
1366
|
+
resumedState.config = telemetryConfig;
|
|
972
1367
|
const resumeUpdate = {};
|
|
973
1368
|
if (Object.keys(resumeDataPatch).length > 0) {
|
|
974
1369
|
resumeUpdate.data = {
|
|
@@ -983,26 +1378,52 @@ async function tryPrepareResumeStream({
|
|
|
983
1378
|
const resumeValue = meta.selected?.length && pending.schema.kind === "multi-choice" ? meta.selected.map((x) => String(x)) : meta.selected?.length ? String(meta.selected[0]) : void 0;
|
|
984
1379
|
const resumeCheckpointId = typeof pending.graphCheckpointId === "string" && pending.graphCheckpointId.length > 0 ? pending.graphCheckpointId : void 0;
|
|
985
1380
|
const resumedGraph = await (0, import_runtime2.createExecutionGraph)(wf, {
|
|
986
|
-
...
|
|
1381
|
+
...telemetryConfig,
|
|
987
1382
|
resume: true,
|
|
988
1383
|
...resumeValue !== void 0 ? { resumeValue } : {},
|
|
989
1384
|
...resumeCheckpointId ? { resumeCheckpointId } : {},
|
|
990
1385
|
...hasResumeUpdate ? { resumeUpdate } : {}
|
|
991
1386
|
});
|
|
992
1387
|
await store.delete(pending.token);
|
|
1388
|
+
const response = responseFromSelection(meta.selected);
|
|
1389
|
+
const telemetry = isRecord4(telemetryConfig.telemetry) ? telemetryConfig.telemetry : {};
|
|
1390
|
+
const responseCaptured = Boolean(
|
|
1391
|
+
response && shouldCaptureTelemetryContent(telemetry.captureContent, "input")
|
|
1392
|
+
);
|
|
1393
|
+
emitTelemetryEvent({
|
|
1394
|
+
config: telemetryConfig,
|
|
1395
|
+
type: "interrupt.resolved",
|
|
1396
|
+
correlation: {
|
|
1397
|
+
runId: pending.runId,
|
|
1398
|
+
sessionId,
|
|
1399
|
+
workflowId,
|
|
1400
|
+
nodeId: pending.node
|
|
1401
|
+
},
|
|
1402
|
+
payload: {
|
|
1403
|
+
interruptId: pending.requestId,
|
|
1404
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1405
|
+
resumeOutcome: "resumed",
|
|
1406
|
+
responseCaptured,
|
|
1407
|
+
...responseCaptured && response ? { response } : {}
|
|
1408
|
+
},
|
|
1409
|
+
flush: true
|
|
1410
|
+
});
|
|
993
1411
|
const args = {
|
|
994
1412
|
sessionId,
|
|
995
1413
|
runId: pending.runId,
|
|
996
1414
|
graph: resumedGraph,
|
|
997
1415
|
state: resumedState,
|
|
998
1416
|
config: {
|
|
999
|
-
...
|
|
1417
|
+
...telemetryConfig,
|
|
1000
1418
|
resume: true,
|
|
1419
|
+
telemetryInterruptId: pending.requestId,
|
|
1420
|
+
telemetryInterruptNodeId: pending.node,
|
|
1001
1421
|
...resumeValue !== void 0 ? { resumeValue } : {},
|
|
1002
1422
|
...resumeCheckpointId ? { resumeCheckpointId } : {},
|
|
1003
1423
|
...hasResumeUpdate ? { resumeUpdate } : {}
|
|
1004
1424
|
},
|
|
1005
1425
|
selectWorkflow,
|
|
1426
|
+
knownWorkflowIds,
|
|
1006
1427
|
frameworkAdapter
|
|
1007
1428
|
};
|
|
1008
1429
|
const stream = await orchestrateGraphStream(args);
|
|
@@ -1030,12 +1451,13 @@ async function streamChat({
|
|
|
1030
1451
|
loadRuntimeConfig,
|
|
1031
1452
|
selectWorkflow,
|
|
1032
1453
|
workflowRegistry,
|
|
1454
|
+
knownWorkflowIds,
|
|
1033
1455
|
frameworkAdapter,
|
|
1034
1456
|
getProvider,
|
|
1035
1457
|
applyResumeSelection
|
|
1036
1458
|
}) {
|
|
1037
1459
|
const config = await loadRuntimeConfig(options);
|
|
1038
|
-
|
|
1460
|
+
let runtimeConfig = {
|
|
1039
1461
|
...config,
|
|
1040
1462
|
getProvider,
|
|
1041
1463
|
...frameworkAdapter ? { checkpointer: frameworkAdapter.checkpointer } : {}
|
|
@@ -1078,6 +1500,7 @@ async function streamChat({
|
|
|
1078
1500
|
sessionId: resolvedSessionId,
|
|
1079
1501
|
config: runtimeConfig,
|
|
1080
1502
|
selectWorkflow: workflowSelector,
|
|
1503
|
+
knownWorkflowIds,
|
|
1081
1504
|
...frameworkAdapter ? { frameworkAdapter } : {},
|
|
1082
1505
|
...defaultWorkflowId ? { defaultWorkflowId } : {},
|
|
1083
1506
|
...applyResumeSelection ? { applyResumeSelection } : {}
|
|
@@ -1103,6 +1526,13 @@ async function streamChat({
|
|
|
1103
1526
|
}
|
|
1104
1527
|
const currentWorkflow = requestedWorkflowId ? baseState.currentWorkflow : headCheckpoint?.state.currentWorkflow ?? baseState.currentWorkflow;
|
|
1105
1528
|
const selectedWorkflow = await workflowSelector(currentWorkflow);
|
|
1529
|
+
runtimeConfig = prepareWorkflowTelemetry({
|
|
1530
|
+
config: runtimeConfig,
|
|
1531
|
+
workflow: selectedWorkflow,
|
|
1532
|
+
runId,
|
|
1533
|
+
sessionId: resolvedSessionId,
|
|
1534
|
+
knownWorkflowIds
|
|
1535
|
+
});
|
|
1106
1536
|
const graph = await (0, import_runtime3.createExecutionGraph)(selectedWorkflow, runtimeConfig);
|
|
1107
1537
|
const initialState = headCheckpoint ? {
|
|
1108
1538
|
...headCheckpoint.state,
|
|
@@ -1115,7 +1545,7 @@ async function streamChat({
|
|
|
1115
1545
|
...runtime.requestedWorkflow ? { requestedWorkflow: runtime.requestedWorkflow } : {},
|
|
1116
1546
|
...runtime.priorMessages ? { priorMessages: runtime.priorMessages } : {}
|
|
1117
1547
|
}
|
|
1118
|
-
} : { ...baseState, currentWorkflow };
|
|
1548
|
+
} : { ...baseState, config: runtimeConfig, currentWorkflow };
|
|
1119
1549
|
const orchestratedStream = await orchestrateGraphStream({
|
|
1120
1550
|
sessionId: resolvedSessionId,
|
|
1121
1551
|
runId,
|
|
@@ -1123,6 +1553,7 @@ async function streamChat({
|
|
|
1123
1553
|
state: initialState,
|
|
1124
1554
|
config: runtimeConfig,
|
|
1125
1555
|
selectWorkflow: workflowSelector,
|
|
1556
|
+
knownWorkflowIds,
|
|
1126
1557
|
...frameworkAdapter ? { frameworkAdapter } : {}
|
|
1127
1558
|
});
|
|
1128
1559
|
return orchestratedStream;
|
|
@@ -1236,6 +1667,22 @@ function createAgent(args) {
|
|
|
1236
1667
|
fallbackId: resolvedDefaultWorkflowId ?? "general-chat"
|
|
1237
1668
|
});
|
|
1238
1669
|
})();
|
|
1670
|
+
const registeredWorkflowsPromise = registryPromise.then(
|
|
1671
|
+
(registry) => registry?.list?.()
|
|
1672
|
+
);
|
|
1673
|
+
const projectTopology = async (options) => {
|
|
1674
|
+
const registeredWorkflows = await registeredWorkflowsPromise;
|
|
1675
|
+
if (!registeredWorkflows?.length) return [];
|
|
1676
|
+
const knownWorkflowIds = registeredWorkflows.map((workflow) => workflow.id);
|
|
1677
|
+
return registeredWorkflows.map(
|
|
1678
|
+
(workflow) => projectWorkflowTopology({
|
|
1679
|
+
workflow,
|
|
1680
|
+
environment: options.environment,
|
|
1681
|
+
service: options.service,
|
|
1682
|
+
knownWorkflowIds
|
|
1683
|
+
})
|
|
1684
|
+
);
|
|
1685
|
+
};
|
|
1239
1686
|
const streamChat2 = async (messages, options) => {
|
|
1240
1687
|
const parsedOptions = parseAgentProcessOptions(options);
|
|
1241
1688
|
const registry = await registryPromise;
|
|
@@ -1244,11 +1691,18 @@ function createAgent(args) {
|
|
|
1244
1691
|
"createAgent requires workflows, workflowsDir, or workflowRegistry."
|
|
1245
1692
|
);
|
|
1246
1693
|
}
|
|
1694
|
+
const registeredWorkflows = await registeredWorkflowsPromise.catch(
|
|
1695
|
+
() => void 0
|
|
1696
|
+
);
|
|
1697
|
+
const knownWorkflowIds = registeredWorkflows?.map(
|
|
1698
|
+
(workflow) => workflow.id
|
|
1699
|
+
);
|
|
1247
1700
|
return streamChat({
|
|
1248
1701
|
...resolvedDefaultWorkflowId ? { defaultWorkflowId: resolvedDefaultWorkflowId } : {},
|
|
1249
1702
|
messages,
|
|
1250
1703
|
options: parsedOptions,
|
|
1251
1704
|
workflowRegistry: registry,
|
|
1705
|
+
...knownWorkflowIds ? { knownWorkflowIds } : {},
|
|
1252
1706
|
frameworkAdapter: resolvedFrameworkAdapter,
|
|
1253
1707
|
getProvider: resolvedGetProvider,
|
|
1254
1708
|
loadRuntimeConfig: (runtimeOptions) => ({
|
|
@@ -1265,6 +1719,7 @@ function createAgent(args) {
|
|
|
1265
1719
|
const listCheckpoints = (sessionId) => resolvedFrameworkAdapter.sessionCheckpoints.list(sessionId);
|
|
1266
1720
|
const getCheckpoint = (id) => resolvedFrameworkAdapter.sessionCheckpoints.get(id);
|
|
1267
1721
|
const rollbackTo = async (id) => {
|
|
1722
|
+
const target = await resolvedFrameworkAdapter.sessionCheckpoints.get(id);
|
|
1268
1723
|
const result = await resolvedFrameworkAdapter.sessionCheckpoints.rollbackTo(id);
|
|
1269
1724
|
const activePendingRequests = await Promise.all(
|
|
1270
1725
|
result.activePendingRequests.map(
|
|
@@ -1284,6 +1739,21 @@ function createAgent(args) {
|
|
|
1284
1739
|
(request) => resolvedFrameworkAdapter.pendingRequests.save(request)
|
|
1285
1740
|
)
|
|
1286
1741
|
]);
|
|
1742
|
+
if (target) {
|
|
1743
|
+
emitTelemetryEvent({
|
|
1744
|
+
config: { ...telemetry ? { telemetry } : {} },
|
|
1745
|
+
type: "session.rolled_back",
|
|
1746
|
+
correlation: {
|
|
1747
|
+
runId: target.runId,
|
|
1748
|
+
sessionId: target.sessionId,
|
|
1749
|
+
workflowId: target.workflow
|
|
1750
|
+
},
|
|
1751
|
+
payload: {
|
|
1752
|
+
checkpointId: target.id,
|
|
1753
|
+
invalidatedInterruptIds: result.invalidatedInterruptTokens
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1287
1757
|
return { ...result, activePendingRequests };
|
|
1288
1758
|
};
|
|
1289
1759
|
const fork = async (id, options) => {
|
|
@@ -1306,12 +1776,33 @@ function createAgent(args) {
|
|
|
1306
1776
|
(request) => resolvedFrameworkAdapter.pendingRequests.save(request)
|
|
1307
1777
|
)
|
|
1308
1778
|
);
|
|
1779
|
+
emitTelemetryEvent({
|
|
1780
|
+
config: { ...telemetry ? { telemetry } : {} },
|
|
1781
|
+
type: "session.forked",
|
|
1782
|
+
correlation: {
|
|
1783
|
+
runId: result.checkpoint.runId,
|
|
1784
|
+
sessionId: result.checkpoint.sessionId,
|
|
1785
|
+
workflowId: result.checkpoint.workflow
|
|
1786
|
+
},
|
|
1787
|
+
payload: {
|
|
1788
|
+
newSessionId: result.sessionId,
|
|
1789
|
+
parentSessionId: result.parentSessionId,
|
|
1790
|
+
forkedFromCheckpointId: result.forkedFrom
|
|
1791
|
+
}
|
|
1792
|
+
});
|
|
1309
1793
|
return {
|
|
1310
1794
|
...result,
|
|
1311
1795
|
checkpoint: { ...result.checkpoint, activePendingRequests }
|
|
1312
1796
|
};
|
|
1313
1797
|
};
|
|
1314
|
-
return {
|
|
1798
|
+
return {
|
|
1799
|
+
projectTopology,
|
|
1800
|
+
streamChat: streamChat2,
|
|
1801
|
+
listCheckpoints,
|
|
1802
|
+
getCheckpoint,
|
|
1803
|
+
rollbackTo,
|
|
1804
|
+
fork
|
|
1805
|
+
};
|
|
1315
1806
|
}
|
|
1316
1807
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1317
1808
|
0 && (module.exports = {
|
|
@@ -1325,6 +1816,7 @@ function createAgent(args) {
|
|
|
1325
1816
|
parseChatRequestBody,
|
|
1326
1817
|
parseCheckpointRequestBody,
|
|
1327
1818
|
parseResumeMeta,
|
|
1819
|
+
projectWorkflowTopology,
|
|
1328
1820
|
streamChat,
|
|
1329
1821
|
streamChatFromRoute,
|
|
1330
1822
|
transformGraphStreamForUI,
|