@kortyx/agent 0.5.0 → 0.6.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 +21 -0
- package/dist/browser-DxBPQjOI.d.ts +21 -0
- package/dist/browser.d.ts +2 -3
- package/dist/browser.js +44 -5
- package/dist/browser.js.map +1 -0
- package/dist/index.d.ts +136 -16
- package/dist/index.js +876 -22
- package/dist/index.js.map +1 -0
- package/package.json +6 -5
- package/dist/adapters/http-client.d.ts +0 -12
- package/dist/adapters/http-client.d.ts.map +0 -1
- package/dist/adapters/http-client.js +0 -16
- package/dist/adapters/http.d.ts +0 -17
- package/dist/adapters/http.d.ts.map +0 -1
- package/dist/adapters/http.js +0 -66
- package/dist/browser.d.ts.map +0 -1
- package/dist/chat/create-agent.d.ts +0 -33
- package/dist/chat/create-agent.d.ts.map +0 -1
- package/dist/chat/create-agent.js +0 -138
- package/dist/chat/process-chat.d.ts +0 -27
- package/dist/chat/process-chat.d.ts.map +0 -1
- package/dist/chat/process-chat.js +0 -87
- package/dist/index.d.ts.map +0 -1
- package/dist/interrupt/resume-handler.d.ts +0 -27
- package/dist/interrupt/resume-handler.d.ts.map +0 -1
- package/dist/interrupt/resume-handler.js +0 -102
- package/dist/orchestrator.d.ts +0 -22
- package/dist/orchestrator.d.ts.map +0 -1
- package/dist/orchestrator.js +0 -321
- package/dist/stream/transform-graph-stream-for-ui.d.ts +0 -9
- package/dist/stream/transform-graph-stream-for-ui.d.ts.map +0 -1
- package/dist/stream/transform-graph-stream-for-ui.js +0 -60
- package/dist/types/chat-message.d.ts +0 -8
- package/dist/types/chat-message.d.ts.map +0 -1
- package/dist/types/chat-message.js +0 -2
- package/dist/utils/extract-latest-message.d.ts +0 -3
- package/dist/utils/extract-latest-message.d.ts.map +0 -1
- package/dist/utils/extract-latest-message.js +0 -14
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { FrameworkAdapter, PendingRequestRecord } from "@kortyx/runtime";
|
|
2
|
-
import type { StreamChunk } from "@kortyx/stream";
|
|
3
|
-
import type { SelectWorkflowFn } from "../orchestrator";
|
|
4
|
-
import type { ChatMessage } from "../types/chat-message";
|
|
5
|
-
export interface ResumeMeta {
|
|
6
|
-
token: string;
|
|
7
|
-
requestId: string;
|
|
8
|
-
selected: string[];
|
|
9
|
-
cancel?: boolean;
|
|
10
|
-
}
|
|
11
|
-
export type ApplyResumeSelection = (args: {
|
|
12
|
-
pending: PendingRequestRecord;
|
|
13
|
-
selected: string[];
|
|
14
|
-
}) => Record<string, unknown> | null | undefined;
|
|
15
|
-
export declare function parseResumeMeta(msg: ChatMessage | undefined): ResumeMeta | null;
|
|
16
|
-
interface TryResumeArgs {
|
|
17
|
-
lastMessage: ChatMessage | undefined;
|
|
18
|
-
sessionId: string;
|
|
19
|
-
config: Record<string, unknown>;
|
|
20
|
-
selectWorkflow: SelectWorkflowFn;
|
|
21
|
-
defaultWorkflowId?: string;
|
|
22
|
-
applyResumeSelection?: ApplyResumeSelection;
|
|
23
|
-
frameworkAdapter?: FrameworkAdapter;
|
|
24
|
-
}
|
|
25
|
-
export declare function tryPrepareResumeStream({ lastMessage, sessionId, config, selectWorkflow, defaultWorkflowId, applyResumeSelection, frameworkAdapter, }: TryResumeArgs): Promise<AsyncIterable<StreamChunk> | null>;
|
|
26
|
-
export {};
|
|
27
|
-
//# sourceMappingURL=resume-handler.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resume-handler.d.ts","sourceRoot":"","sources":["../../src/interrupt/resume-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EAErB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAE;IACxC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;AAKjD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,GAAG,SAAS,GAC3B,UAAU,GAAG,IAAI,CAuBnB;AAED,UAAU,aAAa;IACrB,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,cAAc,EAAE,gBAAgB,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,WAAW,EACX,SAAS,EACT,MAAM,EACN,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,GACjB,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CA6F5D"}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseResumeMeta = parseResumeMeta;
|
|
4
|
-
exports.tryPrepareResumeStream = tryPrepareResumeStream;
|
|
5
|
-
const runtime_1 = require("@kortyx/runtime");
|
|
6
|
-
const orchestrator_1 = require("../orchestrator");
|
|
7
|
-
const isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8
|
-
function parseResumeMeta(msg) {
|
|
9
|
-
if (!msg || !msg.metadata)
|
|
10
|
-
return null;
|
|
11
|
-
const raw = msg.metadata.resume;
|
|
12
|
-
if (!isRecord(raw))
|
|
13
|
-
return null;
|
|
14
|
-
const token = typeof raw.token === "string" ? raw.token : "";
|
|
15
|
-
const requestId = typeof raw.requestId === "string" ? raw.requestId : "";
|
|
16
|
-
const cancel = raw.cancel === true;
|
|
17
|
-
let selected = [];
|
|
18
|
-
const rawSelected = raw.selected;
|
|
19
|
-
if (typeof rawSelected === "string")
|
|
20
|
-
selected = [rawSelected];
|
|
21
|
-
else if (Array.isArray(rawSelected))
|
|
22
|
-
selected = rawSelected.map(String);
|
|
23
|
-
else if (isRecord(raw.choice) && typeof raw.choice.id === "string")
|
|
24
|
-
selected = [raw.choice.id];
|
|
25
|
-
else if (Array.isArray(raw.choices))
|
|
26
|
-
selected = raw.choices
|
|
27
|
-
.map((c) => (isRecord(c) ? c.id : undefined))
|
|
28
|
-
.filter((id) => typeof id === "string");
|
|
29
|
-
if (!token || !requestId)
|
|
30
|
-
return null;
|
|
31
|
-
return { token, requestId, selected, cancel };
|
|
32
|
-
}
|
|
33
|
-
async function tryPrepareResumeStream({ lastMessage, sessionId, config, selectWorkflow, defaultWorkflowId, applyResumeSelection, frameworkAdapter, }) {
|
|
34
|
-
const meta = parseResumeMeta(lastMessage);
|
|
35
|
-
if (!meta)
|
|
36
|
-
return null;
|
|
37
|
-
const store = frameworkAdapter?.pendingRequests;
|
|
38
|
-
if (!store)
|
|
39
|
-
return null;
|
|
40
|
-
const pending = await store.get(meta.token);
|
|
41
|
-
if (!pending || pending.requestId !== meta.requestId) {
|
|
42
|
-
console.log(`[resume] pending not found or mismatched. token=${meta.token} requestId=${meta.requestId}`);
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
if (meta.cancel) {
|
|
46
|
-
await store.delete(pending.token);
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
console.log(`[resume] token=${meta.token} requestId=${meta.requestId} selected=${JSON.stringify(meta.selected)} sessionId=${sessionId}`);
|
|
50
|
-
const resumeData = applyResumeSelection
|
|
51
|
-
? applyResumeSelection({ pending, selected: meta.selected })
|
|
52
|
-
: meta.selected?.length
|
|
53
|
-
? { coordinates: String(meta.selected[0]) }
|
|
54
|
-
: {};
|
|
55
|
-
const resumeDataPatch = isRecord(resumeData) ? resumeData : {};
|
|
56
|
-
const pendingData = isRecord(pending.state?.data) ? pending.state?.data : {};
|
|
57
|
-
const workflowId = typeof pending.workflow === "string" && pending.workflow.trim()
|
|
58
|
-
? pending.workflow
|
|
59
|
-
: typeof defaultWorkflowId === "string" && defaultWorkflowId.trim()
|
|
60
|
-
? defaultWorkflowId
|
|
61
|
-
: "job-search";
|
|
62
|
-
const resumedState = {
|
|
63
|
-
input: "",
|
|
64
|
-
lastNode: "__start__",
|
|
65
|
-
currentWorkflow: workflowId,
|
|
66
|
-
config,
|
|
67
|
-
memory: {},
|
|
68
|
-
conversationHistory: [],
|
|
69
|
-
awaitingHumanInput: false,
|
|
70
|
-
data: {
|
|
71
|
-
...pendingData,
|
|
72
|
-
...resumeDataPatch,
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
const wf = await selectWorkflow(resumedState.currentWorkflow);
|
|
76
|
-
const resumeValue = meta.selected?.length && pending.schema.kind === "multi-choice"
|
|
77
|
-
? meta.selected.map((x) => String(x))
|
|
78
|
-
: meta.selected?.length
|
|
79
|
-
? String(meta.selected[0])
|
|
80
|
-
: undefined;
|
|
81
|
-
const resumedGraph = await (0, runtime_1.createLangGraph)(wf, {
|
|
82
|
-
...config,
|
|
83
|
-
resume: true,
|
|
84
|
-
...(resumeValue !== undefined ? { resumeValue } : {}),
|
|
85
|
-
});
|
|
86
|
-
await store.delete(pending.token);
|
|
87
|
-
const args = {
|
|
88
|
-
sessionId,
|
|
89
|
-
runId: pending.runId,
|
|
90
|
-
graph: resumedGraph,
|
|
91
|
-
state: resumedState,
|
|
92
|
-
config: {
|
|
93
|
-
...config,
|
|
94
|
-
resume: true,
|
|
95
|
-
...(resumeValue !== undefined ? { resumeValue } : {}),
|
|
96
|
-
},
|
|
97
|
-
selectWorkflow,
|
|
98
|
-
...(frameworkAdapter ? { frameworkAdapter } : {}),
|
|
99
|
-
};
|
|
100
|
-
const stream = await (0, orchestrator_1.orchestrateGraphStream)(args);
|
|
101
|
-
return stream;
|
|
102
|
-
}
|
package/dist/orchestrator.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { GraphState, WorkflowDefinition } from "@kortyx/core";
|
|
2
|
-
import { type FrameworkAdapter } from "@kortyx/runtime";
|
|
3
|
-
export type SelectWorkflowFn = (workflowId: string) => Promise<WorkflowDefinition>;
|
|
4
|
-
export type SaveMemoryFn = (sessionId: string, state: GraphState) => Promise<void>;
|
|
5
|
-
export interface CompiledGraphLike {
|
|
6
|
-
config?: Record<string, unknown>;
|
|
7
|
-
streamEvents: (state: GraphState, options?: {
|
|
8
|
-
version?: string;
|
|
9
|
-
configurable?: Record<string, unknown>;
|
|
10
|
-
}) => AsyncIterable<unknown> | AsyncGenerator<unknown>;
|
|
11
|
-
}
|
|
12
|
-
export interface OrchestrateArgs {
|
|
13
|
-
sessionId?: string;
|
|
14
|
-
runId: string;
|
|
15
|
-
graph: CompiledGraphLike;
|
|
16
|
-
state: GraphState;
|
|
17
|
-
config: Record<string, unknown>;
|
|
18
|
-
selectWorkflow: SelectWorkflowFn;
|
|
19
|
-
frameworkAdapter?: FrameworkAdapter;
|
|
20
|
-
}
|
|
21
|
-
export declare function orchestrateGraphStream({ sessionId, runId, graph, state, config, selectWorkflow, frameworkAdapter, }: OrchestrateArgs): Promise<NodeJS.ReadableStream>;
|
|
22
|
-
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAc,MAAM,cAAc,CAAC;AAC/E,OAAO,EAEL,KAAK,gBAAgB,EAKtB,MAAM,iBAAiB,CAAC;AAKzB,MAAM,MAAM,gBAAgB,GAAG,CAC7B,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEjC,MAAM,MAAM,YAAY,GAAG,CACzB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,KACd,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,CACZ,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KACnE,aAAa,CAAC,OAAO,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,cAAc,EAAE,gBAAgB,CAAC;IACjC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAMD,wBAAsB,sBAAsB,CAAC,EAC3C,SAAS,EACT,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAM,EACN,cAAc,EACd,gBAAgB,GACjB,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAgZlD"}
|
package/dist/orchestrator.js
DELETED
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.orchestrateGraphStream = orchestrateGraphStream;
|
|
4
|
-
const node_stream_1 = require("node:stream");
|
|
5
|
-
const runtime_1 = require("@kortyx/runtime");
|
|
6
|
-
const langgraph_1 = require("@langchain/langgraph");
|
|
7
|
-
const transform_graph_stream_for_ui_1 = require("./stream/transform-graph-stream-for-ui");
|
|
8
|
-
async function orchestrateGraphStream({ sessionId, runId, graph, state, config, selectWorkflow, frameworkAdapter, }) {
|
|
9
|
-
const out = new node_stream_1.PassThrough({ objectMode: true });
|
|
10
|
-
let currentGraph = graph;
|
|
11
|
-
let currentState = state;
|
|
12
|
-
let finished = false;
|
|
13
|
-
const debugEnabled = Boolean(config?.features?.tracing);
|
|
14
|
-
const namespacesUsed = new Set();
|
|
15
|
-
try {
|
|
16
|
-
const sid = config?.session?.id;
|
|
17
|
-
if (sid && typeof sid === "string") {
|
|
18
|
-
out.write({ type: "session", sessionId: sid });
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
catch { }
|
|
22
|
-
const pending = {
|
|
23
|
-
to: null,
|
|
24
|
-
payload: {},
|
|
25
|
-
};
|
|
26
|
-
let lastStatusMsg = "";
|
|
27
|
-
let lastStatusAt = 0;
|
|
28
|
-
let pendingRecordToken = null;
|
|
29
|
-
let activeIsResume = false;
|
|
30
|
-
let wroteHumanInput = false;
|
|
31
|
-
const pendingStore = frameworkAdapter?.pendingRequests;
|
|
32
|
-
const pendingTtlMs = frameworkAdapter?.ttlMs ?? 15 * 60 * 1000;
|
|
33
|
-
const persistAndEmitInterrupt = async (payload) => {
|
|
34
|
-
if (activeIsResume || wroteHumanInput)
|
|
35
|
-
return;
|
|
36
|
-
const token = (0, runtime_1.makeResumeToken)();
|
|
37
|
-
const requestId = (0, runtime_1.makeRequestId)("human");
|
|
38
|
-
pendingRecordToken = token;
|
|
39
|
-
const input = payload.input ?? {};
|
|
40
|
-
const optionsList = Array.isArray(input.options) ? input.options : [];
|
|
41
|
-
const kind = input.kind || (input.multiple ? "multi-choice" : "choice");
|
|
42
|
-
const isText = kind === "text";
|
|
43
|
-
const record = {
|
|
44
|
-
token,
|
|
45
|
-
requestId,
|
|
46
|
-
sessionId,
|
|
47
|
-
runId,
|
|
48
|
-
workflow: payload.workflow || currentState.currentWorkflow,
|
|
49
|
-
node: payload.node || "",
|
|
50
|
-
state: { ...currentState, awaitingHumanInput: true },
|
|
51
|
-
schema: isText
|
|
52
|
-
? {
|
|
53
|
-
kind: kind,
|
|
54
|
-
multiple: Boolean(input.multiple),
|
|
55
|
-
...(input.question ? { question: input.question } : {}),
|
|
56
|
-
}
|
|
57
|
-
: {
|
|
58
|
-
kind: kind,
|
|
59
|
-
multiple: Boolean(input.multiple),
|
|
60
|
-
question: String(input.question || "Please choose an option."),
|
|
61
|
-
},
|
|
62
|
-
options: optionsList.map((option) => ({
|
|
63
|
-
id: String(option.id),
|
|
64
|
-
label: String(option.label),
|
|
65
|
-
description: typeof option.description === "string"
|
|
66
|
-
? option.description
|
|
67
|
-
: undefined,
|
|
68
|
-
value: option.value,
|
|
69
|
-
})),
|
|
70
|
-
createdAt: Date.now(),
|
|
71
|
-
ttlMs: pendingTtlMs,
|
|
72
|
-
};
|
|
73
|
-
if (pendingStore) {
|
|
74
|
-
pendingStore.save(record).catch((error) => {
|
|
75
|
-
console.error("[orchestrator] failed to save pending request", error);
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
out.write({
|
|
79
|
-
type: "interrupt",
|
|
80
|
-
requestId: record.requestId,
|
|
81
|
-
resumeToken: record.token,
|
|
82
|
-
workflow: record.workflow,
|
|
83
|
-
node: record.node,
|
|
84
|
-
input: {
|
|
85
|
-
kind: record.schema.kind,
|
|
86
|
-
multiple: record.schema.multiple,
|
|
87
|
-
question: record.schema.question,
|
|
88
|
-
options: record.options.map((option) => ({
|
|
89
|
-
id: option.id,
|
|
90
|
-
label: option.label,
|
|
91
|
-
description: option.description,
|
|
92
|
-
})),
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
wroteHumanInput = true;
|
|
96
|
-
};
|
|
97
|
-
const forwardEmit = (event, payload) => {
|
|
98
|
-
if (event === "error") {
|
|
99
|
-
const msg = String(payload?.message ?? "Unexpected error");
|
|
100
|
-
out.write({ type: "error", message: msg });
|
|
101
|
-
out.write({ type: "done" });
|
|
102
|
-
finished = true;
|
|
103
|
-
out.end();
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
if (event === "status") {
|
|
107
|
-
if (!debugEnabled)
|
|
108
|
-
return;
|
|
109
|
-
const msg = String(payload?.message ?? "");
|
|
110
|
-
const now = Date.now();
|
|
111
|
-
if (msg && msg === lastStatusMsg && now - lastStatusAt < 250)
|
|
112
|
-
return;
|
|
113
|
-
lastStatusMsg = msg;
|
|
114
|
-
lastStatusAt = now;
|
|
115
|
-
out.write({ type: "status", message: msg });
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
if (event === "text-start") {
|
|
119
|
-
const node = payload?.node;
|
|
120
|
-
if (!node)
|
|
121
|
-
return;
|
|
122
|
-
out.write({ type: "text-start", node });
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (event === "text-delta") {
|
|
126
|
-
const node = payload?.node;
|
|
127
|
-
const delta = String(payload?.delta ?? "");
|
|
128
|
-
if (!node || !delta)
|
|
129
|
-
return;
|
|
130
|
-
out.write({ type: "text-delta", delta, node });
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
if (event === "text-end") {
|
|
134
|
-
const node = payload?.node;
|
|
135
|
-
if (!node)
|
|
136
|
-
return;
|
|
137
|
-
out.write({ type: "text-end", node });
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (event === "message") {
|
|
141
|
-
const node = payload?.node;
|
|
142
|
-
const text = String(payload?.content ?? "");
|
|
143
|
-
out.write({ type: "message", node, content: text });
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
if (event === "structured_data") {
|
|
147
|
-
out.write({
|
|
148
|
-
type: "structured-data",
|
|
149
|
-
node: payload?.node,
|
|
150
|
-
dataType: payload?.dataType,
|
|
151
|
-
data: payload?.data,
|
|
152
|
-
});
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
if (event === "transition") {
|
|
156
|
-
out.write({
|
|
157
|
-
type: "transition",
|
|
158
|
-
transitionTo: payload?.transitionTo,
|
|
159
|
-
payload: payload?.payload ?? {},
|
|
160
|
-
});
|
|
161
|
-
pending.to = payload?.transitionTo ?? null;
|
|
162
|
-
pending.payload =
|
|
163
|
-
payload?.payload ?? {};
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
if (event === "interrupt") {
|
|
167
|
-
const p = payload;
|
|
168
|
-
const local = {
|
|
169
|
-
node: p?.node,
|
|
170
|
-
workflow: p?.workflow,
|
|
171
|
-
input: p?.input,
|
|
172
|
-
};
|
|
173
|
-
void persistAndEmitInterrupt(local).catch((error) => {
|
|
174
|
-
console.error("[orchestrator] failed to emit interrupt", error);
|
|
175
|
-
});
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
(async () => {
|
|
180
|
-
while (true) {
|
|
181
|
-
let workflowFinalState = null;
|
|
182
|
-
currentGraph.config = currentGraph.config || {};
|
|
183
|
-
currentGraph.config.emit = forwardEmit;
|
|
184
|
-
const threadId = currentGraph.config?.session?.id ||
|
|
185
|
-
sessionId ||
|
|
186
|
-
"anonymous-session";
|
|
187
|
-
const checkpointNs = String(currentState.currentWorkflow || "default");
|
|
188
|
-
namespacesUsed.add(checkpointNs);
|
|
189
|
-
if (debugEnabled) {
|
|
190
|
-
out.write({
|
|
191
|
-
type: "status",
|
|
192
|
-
message: `🧵 thread_id=${threadId} run_id=${runId} workflow=${currentState.currentWorkflow}`,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
const isResume = Boolean(currentGraph.config?.resume);
|
|
196
|
-
activeIsResume = isResume;
|
|
197
|
-
const resumeUpdate = currentGraph.config?.resumeUpdate;
|
|
198
|
-
const resumeValue = currentGraph.config?.resumeValue;
|
|
199
|
-
const invokeState = isResume
|
|
200
|
-
? resumeValue !== undefined
|
|
201
|
-
? new langgraph_1.Command({ resume: resumeValue })
|
|
202
|
-
: resumeUpdate
|
|
203
|
-
? new langgraph_1.Command({ update: resumeUpdate })
|
|
204
|
-
: null
|
|
205
|
-
: currentState;
|
|
206
|
-
const runtimeStream = currentGraph.streamEvents(invokeState, {
|
|
207
|
-
version: "v2",
|
|
208
|
-
configurable: {
|
|
209
|
-
thread_id: runId,
|
|
210
|
-
checkpoint_ns: checkpointNs,
|
|
211
|
-
},
|
|
212
|
-
});
|
|
213
|
-
if (debugEnabled) {
|
|
214
|
-
out.write({
|
|
215
|
-
type: "status",
|
|
216
|
-
message: `▶️ streamEvents invoke: resume=${Boolean(currentGraph.config?.resume)} thread_id=${threadId} run_id=${runId} ns=${String(currentState.currentWorkflow || "default")}`,
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
const uiStream = (0, transform_graph_stream_for_ui_1.transformGraphStreamForUI)(runtimeStream, {
|
|
220
|
-
debug: debugEnabled,
|
|
221
|
-
emitStatus: debugEnabled,
|
|
222
|
-
});
|
|
223
|
-
for await (const chunk of uiStream) {
|
|
224
|
-
if (finished)
|
|
225
|
-
break;
|
|
226
|
-
out.write(chunk);
|
|
227
|
-
if (chunk.type === "done") {
|
|
228
|
-
workflowFinalState = chunk.data ?? null;
|
|
229
|
-
break;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
if (finished)
|
|
233
|
-
return;
|
|
234
|
-
const transitionTo = pending.to;
|
|
235
|
-
const transitionPayload = pending.payload;
|
|
236
|
-
pending.to = null;
|
|
237
|
-
pending.payload = {};
|
|
238
|
-
if (transitionTo) {
|
|
239
|
-
try {
|
|
240
|
-
const nextWorkflow = await selectWorkflow(transitionTo);
|
|
241
|
-
const nextGraph = await (0, runtime_1.createLangGraph)(nextWorkflow, {
|
|
242
|
-
...config,
|
|
243
|
-
emit: forwardEmit,
|
|
244
|
-
});
|
|
245
|
-
const mergedData = {
|
|
246
|
-
...(workflowFinalState?.data ?? currentState.data ?? {}),
|
|
247
|
-
...(transitionPayload ?? {}),
|
|
248
|
-
};
|
|
249
|
-
const rawInputFromPayload = transitionPayload?.rawInput;
|
|
250
|
-
const newInput = typeof rawInputFromPayload === "string"
|
|
251
|
-
? rawInputFromPayload
|
|
252
|
-
: currentState.input;
|
|
253
|
-
currentState = {
|
|
254
|
-
...currentState,
|
|
255
|
-
currentWorkflow: transitionTo,
|
|
256
|
-
input: newInput,
|
|
257
|
-
data: mergedData,
|
|
258
|
-
ui: {},
|
|
259
|
-
};
|
|
260
|
-
currentGraph = nextGraph;
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
catch (err) {
|
|
264
|
-
out.write({
|
|
265
|
-
type: "error",
|
|
266
|
-
message: `Transition failed to '${transitionTo}': ${err instanceof Error ? err.message : String(err)}`,
|
|
267
|
-
});
|
|
268
|
-
out.write({ type: "done" });
|
|
269
|
-
out.end();
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if (workflowFinalState) {
|
|
274
|
-
if (workflowFinalState && pendingRecordToken) {
|
|
275
|
-
if (pendingStore) {
|
|
276
|
-
await pendingStore.update(pendingRecordToken, {
|
|
277
|
-
state: workflowFinalState,
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
const shouldKeepFrameworkState = Boolean(pendingRecordToken) ||
|
|
282
|
-
Boolean(workflowFinalState?.awaitingHumanInput);
|
|
283
|
-
if (!shouldKeepFrameworkState) {
|
|
284
|
-
try {
|
|
285
|
-
if (frameworkAdapter?.cleanupRun) {
|
|
286
|
-
await frameworkAdapter.cleanupRun(runId, Array.from(namespacesUsed));
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
const cp = currentGraph.config
|
|
290
|
-
?.checkpointer;
|
|
291
|
-
if (cp?.deleteThread) {
|
|
292
|
-
await cp.deleteThread(runId);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
catch (e) {
|
|
297
|
-
console.error("[orchestrator] framework cleanup failed", e);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
finished = true;
|
|
301
|
-
out.write({ type: "done", data: workflowFinalState });
|
|
302
|
-
out.end();
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
if (!finished) {
|
|
306
|
-
out.write({ type: "done" });
|
|
307
|
-
out.end();
|
|
308
|
-
}
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
})().catch((err) => {
|
|
312
|
-
console.error("[error:orchestrateGraphStream]", err);
|
|
313
|
-
out.write({
|
|
314
|
-
type: "error",
|
|
315
|
-
message: err instanceof Error ? err.message : String(err),
|
|
316
|
-
});
|
|
317
|
-
out.write({ type: "done" });
|
|
318
|
-
out.end();
|
|
319
|
-
});
|
|
320
|
-
return out;
|
|
321
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { StreamChunk } from "@kortyx/stream";
|
|
2
|
-
import type { StreamEvent } from "@langchain/core/tracers/log_stream";
|
|
3
|
-
interface TransformOptions {
|
|
4
|
-
debug?: boolean;
|
|
5
|
-
emitStatus?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare function transformGraphStreamForUI(stream: AsyncIterable<StreamEvent>, options?: TransformOptions): AsyncGenerator<StreamChunk>;
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=transform-graph-stream-for-ui.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transform-graph-stream-for-ui.d.ts","sourceRoot":"","sources":["../../src/stream/transform-graph-stream-for-ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAEtE,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAQD,wBAAuB,yBAAyB,CAC9C,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,EAClC,OAAO,GAAE,gBAAqB,GAC7B,cAAc,CAAC,WAAW,CAAC,CA6D7B"}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.transformGraphStreamForUI = transformGraphStreamForUI;
|
|
4
|
-
async function* transformGraphStreamForUI(stream, options = {}) {
|
|
5
|
-
const { debug = false, emitStatus = debug } = options;
|
|
6
|
-
const startedNodes = new Set();
|
|
7
|
-
const endedNodes = new Set();
|
|
8
|
-
for await (const event of stream) {
|
|
9
|
-
const { event: type, name, data } = event ?? {};
|
|
10
|
-
if (debug)
|
|
11
|
-
console.log(`[debug:event]`, JSON.stringify(event, null, 2));
|
|
12
|
-
switch (type) {
|
|
13
|
-
case "on_chain_start":
|
|
14
|
-
if (name && !name.startsWith("ChannelWrite")) {
|
|
15
|
-
if (name === "__start__" || name === "__end__")
|
|
16
|
-
break;
|
|
17
|
-
if (startedNodes.has(name))
|
|
18
|
-
break;
|
|
19
|
-
startedNodes.add(name);
|
|
20
|
-
if (debug)
|
|
21
|
-
console.log(`[debug:start] node=${name}`);
|
|
22
|
-
if (emitStatus) {
|
|
23
|
-
yield { type: "status", message: `Processing node: ${name}` };
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
break;
|
|
27
|
-
case "on_chain_end": {
|
|
28
|
-
const nodeName = name;
|
|
29
|
-
const output = data?.output;
|
|
30
|
-
if (debug)
|
|
31
|
-
console.log(`[debug:on_chain_end:${nodeName}] output=`, JSON.stringify(output, null, 2));
|
|
32
|
-
if (!output || nodeName?.startsWith("ChannelWrite"))
|
|
33
|
-
break;
|
|
34
|
-
if (nodeName !== "__start__" && nodeName !== "__end__") {
|
|
35
|
-
if (!endedNodes.has(nodeName)) {
|
|
36
|
-
if (emitStatus) {
|
|
37
|
-
yield {
|
|
38
|
-
type: "status",
|
|
39
|
-
message: `✅ Completed node: ${nodeName}`,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
endedNodes.add(nodeName);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
case "on_graph_end": {
|
|
48
|
-
if (debug)
|
|
49
|
-
console.log(`[debug:on_graph_end]`, JSON.stringify(data, null, 2));
|
|
50
|
-
yield { type: "done", data: data?.output ?? null };
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
default:
|
|
54
|
-
if (debug) {
|
|
55
|
-
console.warn(`[debug:unknown_event]`, type);
|
|
56
|
-
}
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chat-message.d.ts","sourceRoot":"","sources":["../../src/types/chat-message.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAChD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extract-latest-message.d.ts","sourceRoot":"","sources":["../../src/utils/extract-latest-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAUxE"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractLatestUserMessage = extractLatestUserMessage;
|
|
4
|
-
function extractLatestUserMessage(messages) {
|
|
5
|
-
if (!messages || messages.length === 0)
|
|
6
|
-
return "";
|
|
7
|
-
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
8
|
-
const msg = messages[i];
|
|
9
|
-
if (msg?.role === "user" && msg?.content?.trim()) {
|
|
10
|
-
return msg.content.trim();
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
return "";
|
|
14
|
-
}
|