@ai-setting/roy-agent-core 1.4.11 → 1.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +7825 -0
- package/dist/index.js +1040 -6526
- package/dist/shared/chunk-0q6s9wm6.js +249 -0
- package/dist/shared/chunk-1aakcfp1.js +15 -0
- package/dist/shared/chunk-1d4rwms4.js +25 -0
- package/dist/shared/chunk-1pf5mfgd.js +82 -0
- package/dist/shared/chunk-1qwabsm0.js +154 -0
- package/dist/shared/chunk-25x2pdtp.js +107 -0
- package/dist/shared/chunk-2b5kbhx3.js +366 -0
- package/dist/shared/chunk-91bas8w5.js +20 -0
- package/dist/shared/chunk-9qzt1v1p.js +10 -0
- package/dist/shared/chunk-a9qmy3sc.js +296 -0
- package/dist/shared/chunk-g6j5n3gv.js +549 -0
- package/dist/shared/chunk-hs7tbmje.js +24 -0
- package/dist/shared/chunk-mf5xqbdh.js +14 -0
- package/dist/shared/chunk-q9j99fsm.js +368 -0
- package/dist/shared/chunk-rncy3rtd.js +3140 -0
- package/dist/shared/chunk-t1rh6jtm.js +205 -0
- package/dist/shared/chunk-wbkh7wat.js +52 -0
- package/dist/shared/chunk-yqmx37vm.js +10 -0
- package/dist/shared/chunk-ze20rksg.js +102 -0
- package/package.json +8 -8
- package/dist/config/index.js +0 -1647
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__esm
|
|
3
|
+
} from "./chunk-wbkh7wat.js";
|
|
4
|
+
|
|
5
|
+
// src/env/workflow/types/workflow-hil.ts
|
|
6
|
+
function createNodeInterruptEvent(runId, nodeId, nodeType, query, agentSessionId) {
|
|
7
|
+
return {
|
|
8
|
+
type: "node.interrupt",
|
|
9
|
+
run_id: runId,
|
|
10
|
+
timestamp: Date.now(),
|
|
11
|
+
node_id: nodeId,
|
|
12
|
+
node_type: nodeType,
|
|
13
|
+
query,
|
|
14
|
+
...agentSessionId ? { agent_session_id: agentSessionId } : {}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
var AskUserError;
|
|
18
|
+
var init_workflow_hil = __esm(() => {
|
|
19
|
+
AskUserError = class AskUserError extends Error {
|
|
20
|
+
runId;
|
|
21
|
+
sessionId;
|
|
22
|
+
nodeId;
|
|
23
|
+
nodeType;
|
|
24
|
+
query;
|
|
25
|
+
agentSessionId;
|
|
26
|
+
timestamp;
|
|
27
|
+
type = "ask-user";
|
|
28
|
+
name = "AskUserError";
|
|
29
|
+
constructor(runId, sessionId, nodeId, nodeType, query, agentSessionId, timestamp = Date.now()) {
|
|
30
|
+
super(`[${nodeType}:${nodeId}] Ask user: ${query}`);
|
|
31
|
+
this.runId = runId;
|
|
32
|
+
this.sessionId = sessionId;
|
|
33
|
+
this.nodeId = nodeId;
|
|
34
|
+
this.nodeType = nodeType;
|
|
35
|
+
this.query = query;
|
|
36
|
+
this.agentSessionId = agentSessionId;
|
|
37
|
+
this.timestamp = timestamp;
|
|
38
|
+
}
|
|
39
|
+
toEvent() {
|
|
40
|
+
return {
|
|
41
|
+
type: "workflow.ask-user",
|
|
42
|
+
run_id: this.runId,
|
|
43
|
+
timestamp: this.timestamp,
|
|
44
|
+
session_id: this.sessionId,
|
|
45
|
+
node_id: this.nodeId,
|
|
46
|
+
node_type: this.nodeType,
|
|
47
|
+
query: this.query
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// src/env/workflow/nodes/agent-component-adapter.ts
|
|
54
|
+
class AgentComponentAdapter {
|
|
55
|
+
agentComponent;
|
|
56
|
+
options;
|
|
57
|
+
_sessionComponent;
|
|
58
|
+
agentSessionPrefix = "agent";
|
|
59
|
+
_currentAgentSessionId;
|
|
60
|
+
pendingSessions = new Map;
|
|
61
|
+
runSessionToAgentSessions = new Map;
|
|
62
|
+
constructor(agentComponent, options = {}, _sessionComponent) {
|
|
63
|
+
this.agentComponent = agentComponent;
|
|
64
|
+
this.options = options;
|
|
65
|
+
this._sessionComponent = _sessionComponent;
|
|
66
|
+
}
|
|
67
|
+
setSessionComponent(sessionComponent) {
|
|
68
|
+
this._sessionComponent = sessionComponent;
|
|
69
|
+
}
|
|
70
|
+
getCurrentAgentSessionId() {
|
|
71
|
+
return this._currentAgentSessionId;
|
|
72
|
+
}
|
|
73
|
+
registerAgent(name, config) {
|
|
74
|
+
this.agentComponent.registerAgent(name, {
|
|
75
|
+
type: config.type || "general",
|
|
76
|
+
model: config.model,
|
|
77
|
+
systemPrompt: config.systemPrompt,
|
|
78
|
+
maxIterations: config.maxIterations,
|
|
79
|
+
allowedTools: config.allowedTools,
|
|
80
|
+
deniedTools: config.deniedTools,
|
|
81
|
+
timeout: config.timeout,
|
|
82
|
+
maxErrorRetries: config.maxErrorRetries
|
|
83
|
+
});
|
|
84
|
+
if (config.sessionIdPrefix) {
|
|
85
|
+
this.agentSessionPrefixes.set(name, config.sessionIdPrefix);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async run(config, resumeOptions) {
|
|
89
|
+
const startTime = Date.now();
|
|
90
|
+
const nodeId = config.nodeId || "unknown";
|
|
91
|
+
const runId = config.runId || "unknown";
|
|
92
|
+
const workflowSessionId = config.workflowSessionId;
|
|
93
|
+
const existingAgentSessionId = config.agentSessionId;
|
|
94
|
+
const resumeAgentSessionId = resumeOptions?.agentSessionId;
|
|
95
|
+
const isResume = !!resumeOptions?.userResponse || !!existingAgentSessionId || !!resumeAgentSessionId;
|
|
96
|
+
let agentSessionId;
|
|
97
|
+
if (isResume && (this._currentAgentSessionId || existingAgentSessionId || resumeAgentSessionId)) {
|
|
98
|
+
agentSessionId = resumeAgentSessionId || existingAgentSessionId || this._currentAgentSessionId;
|
|
99
|
+
if (resumeOptions?.userResponse && this._sessionComponent && agentSessionId) {
|
|
100
|
+
try {
|
|
101
|
+
await this._sessionComponent.addMessage(agentSessionId, {
|
|
102
|
+
role: "user",
|
|
103
|
+
content: resumeOptions.userResponse,
|
|
104
|
+
metadata: {
|
|
105
|
+
type: "user_intent",
|
|
106
|
+
intent: "workflow.resume",
|
|
107
|
+
workflowNodeId: nodeId
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.warn(`Failed to add user response to agent session ${agentSessionId}:`, error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
if (this._sessionComponent) {
|
|
116
|
+
agentSessionId = `${this.agentSessionPrefix}_${runId}_${nodeId}_${Date.now()}`;
|
|
117
|
+
try {
|
|
118
|
+
await this._sessionComponent.create({
|
|
119
|
+
title: `Agent Session: ${config.type} (${agentSessionId})`,
|
|
120
|
+
metadata: {
|
|
121
|
+
type: "agent",
|
|
122
|
+
workflowRunId: runId,
|
|
123
|
+
workflowNodeId: nodeId
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
this._currentAgentSessionId = agentSessionId;
|
|
127
|
+
if (workflowSessionId) {
|
|
128
|
+
const mapping = this.runSessionToAgentSessions.get(workflowSessionId) || [];
|
|
129
|
+
mapping.push(agentSessionId);
|
|
130
|
+
this.runSessionToAgentSessions.set(workflowSessionId, mapping);
|
|
131
|
+
}
|
|
132
|
+
this.pendingSessions.set(agentSessionId, {
|
|
133
|
+
agentSessionId,
|
|
134
|
+
nodeId,
|
|
135
|
+
runId,
|
|
136
|
+
createdAt: Date.now()
|
|
137
|
+
});
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.warn(`Failed to create agent session ${agentSessionId}:`, error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
const context = {};
|
|
145
|
+
if (config.options?.timeout) {
|
|
146
|
+
context.abort = new AbortController;
|
|
147
|
+
}
|
|
148
|
+
if (agentSessionId) {
|
|
149
|
+
context.sessionId = agentSessionId;
|
|
150
|
+
}
|
|
151
|
+
if (config.options?.allowedTools) {
|
|
152
|
+
context.allowedTools = config.options.allowedTools;
|
|
153
|
+
}
|
|
154
|
+
if (config.options?.deniedTools) {
|
|
155
|
+
context.deniedTools = config.options.deniedTools;
|
|
156
|
+
}
|
|
157
|
+
if (config.workflowHistory) {
|
|
158
|
+
context.workflowHistory = config.workflowHistory;
|
|
159
|
+
}
|
|
160
|
+
const result = await this.agentComponent.run(config.type || "general", config.prompt, context);
|
|
161
|
+
if (result.error?.startsWith("__ASK_USER_ERROR__:")) {
|
|
162
|
+
const jsonStr = result.error.substring("__ASK_USER_ERROR__:".length);
|
|
163
|
+
const errorInfo = JSON.parse(jsonStr);
|
|
164
|
+
throw new AskUserError(runId, errorInfo.sessionId, errorInfo.nodeId, errorInfo.nodeType || "agent", errorInfo.query);
|
|
165
|
+
}
|
|
166
|
+
const duration = Date.now() - startTime;
|
|
167
|
+
if (agentSessionId) {
|
|
168
|
+
this.pendingSessions.delete(agentSessionId);
|
|
169
|
+
}
|
|
170
|
+
const messages = result._messages || [];
|
|
171
|
+
return {
|
|
172
|
+
output: result.finalText || result.output,
|
|
173
|
+
metadata: {
|
|
174
|
+
duration,
|
|
175
|
+
iterations: result.iterations,
|
|
176
|
+
toolCalls: result.toolCalls?.length,
|
|
177
|
+
agentSessionId
|
|
178
|
+
},
|
|
179
|
+
messages
|
|
180
|
+
};
|
|
181
|
+
} catch (error) {
|
|
182
|
+
const isAskUserError = error instanceof Error && error.name === "AskUserError";
|
|
183
|
+
if (isAskUserError) {
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
const duration = Date.now() - startTime;
|
|
187
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
188
|
+
if (agentSessionId) {
|
|
189
|
+
this.pendingSessions.delete(agentSessionId);
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
output: undefined,
|
|
193
|
+
metadata: {
|
|
194
|
+
duration,
|
|
195
|
+
error: errorMessage,
|
|
196
|
+
agentSessionId
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
} finally {
|
|
200
|
+
if (!isResume) {
|
|
201
|
+
this._currentAgentSessionId = undefined;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async resumeAgent(agentSessionId, userResponse, config) {
|
|
206
|
+
if (this._sessionComponent) {
|
|
207
|
+
try {
|
|
208
|
+
await this._sessionComponent.addMessage(agentSessionId, {
|
|
209
|
+
role: "user",
|
|
210
|
+
content: userResponse,
|
|
211
|
+
metadata: {
|
|
212
|
+
type: "user_intent",
|
|
213
|
+
intent: "workflow.resume"
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
this.pendingSessions.delete(agentSessionId);
|
|
217
|
+
this._currentAgentSessionId = agentSessionId;
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.warn(`Failed to add user response to agent session ${agentSessionId}:`, error);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
config.agentSessionId = agentSessionId;
|
|
223
|
+
return this.run(config, { userResponse });
|
|
224
|
+
}
|
|
225
|
+
getPendingSession(agentSessionId) {
|
|
226
|
+
return this.pendingSessions.get(agentSessionId);
|
|
227
|
+
}
|
|
228
|
+
getPendingSessionsForRun(runId) {
|
|
229
|
+
return Array.from(this.pendingSessions.values()).filter((session) => session.runId === runId);
|
|
230
|
+
}
|
|
231
|
+
getAgentSessionsForWorkflowSession(workflowSessionId) {
|
|
232
|
+
return this.runSessionToAgentSessions.get(workflowSessionId) || [];
|
|
233
|
+
}
|
|
234
|
+
hasAgent(name) {
|
|
235
|
+
return this.agentComponent.getAgent(name) !== undefined;
|
|
236
|
+
}
|
|
237
|
+
listAgents() {
|
|
238
|
+
return this.agentComponent.listAgents().map((a) => a.name);
|
|
239
|
+
}
|
|
240
|
+
getAgentComponent() {
|
|
241
|
+
return this.agentComponent;
|
|
242
|
+
}
|
|
243
|
+
agentSessionPrefixes = new Map;
|
|
244
|
+
}
|
|
245
|
+
var init_agent_component_adapter = __esm(() => {
|
|
246
|
+
init_workflow_hil();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
export { createNodeInterruptEvent, AskUserError, init_workflow_hil, AgentComponentAdapter, init_agent_component_adapter };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OTelTracerProvider,
|
|
3
|
+
getTracerProvider,
|
|
4
|
+
init_tracer_provider,
|
|
5
|
+
resetTracerProvider
|
|
6
|
+
} from "./chunk-q9j99fsm.js";
|
|
7
|
+
import"./chunk-1qwabsm0.js";
|
|
8
|
+
import"./chunk-wbkh7wat.js";
|
|
9
|
+
init_tracer_provider();
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
resetTracerProvider,
|
|
13
|
+
getTracerProvider,
|
|
14
|
+
OTelTracerProvider
|
|
15
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bashTool,
|
|
3
|
+
echoTool,
|
|
4
|
+
editFileTool,
|
|
5
|
+
getAllBuiltInTools,
|
|
6
|
+
getBuiltInTool,
|
|
7
|
+
globTool,
|
|
8
|
+
grepTool,
|
|
9
|
+
readFileTool,
|
|
10
|
+
writeFileTool
|
|
11
|
+
} from "./chunk-g6j5n3gv.js";
|
|
12
|
+
import"./chunk-q9j99fsm.js";
|
|
13
|
+
import"./chunk-1qwabsm0.js";
|
|
14
|
+
import"./chunk-wbkh7wat.js";
|
|
15
|
+
export {
|
|
16
|
+
writeFileTool,
|
|
17
|
+
readFileTool,
|
|
18
|
+
grepTool,
|
|
19
|
+
globTool,
|
|
20
|
+
getBuiltInTool,
|
|
21
|
+
getAllBuiltInTools,
|
|
22
|
+
editFileTool,
|
|
23
|
+
echoTool,
|
|
24
|
+
bashTool
|
|
25
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createLogger,
|
|
3
|
+
init_logger
|
|
4
|
+
} from "./chunk-a9qmy3sc.js";
|
|
5
|
+
import {
|
|
6
|
+
__require
|
|
7
|
+
} from "./chunk-wbkh7wat.js";
|
|
8
|
+
|
|
9
|
+
// src/env/workflow/storage/sqlite.ts
|
|
10
|
+
init_logger();
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
var logger = createLogger("workflow:sqlite");
|
|
13
|
+
function getDefaultDataDir() {
|
|
14
|
+
const home = process.env.HOME || process.env.USERPROFILE || "/tmp";
|
|
15
|
+
return join(home, ".local", "share", "roy-agent");
|
|
16
|
+
}
|
|
17
|
+
function getDatabasePath() {
|
|
18
|
+
return join(getDefaultDataDir(), "workflows.db");
|
|
19
|
+
}
|
|
20
|
+
var dbInstance = null;
|
|
21
|
+
function getDatabase(path) {
|
|
22
|
+
if (!dbInstance) {
|
|
23
|
+
const dbPath = path ?? getDatabasePath();
|
|
24
|
+
const dbDir = dbPath.substring(0, dbPath.lastIndexOf("/"));
|
|
25
|
+
if (dbDir && dbDir !== "/") {
|
|
26
|
+
try {
|
|
27
|
+
const { mkdirSync } = __require("fs");
|
|
28
|
+
mkdirSync(dbDir, { recursive: true });
|
|
29
|
+
} catch {}
|
|
30
|
+
}
|
|
31
|
+
const { Database } = __require("bun:sqlite");
|
|
32
|
+
dbInstance = new Database(dbPath);
|
|
33
|
+
try {
|
|
34
|
+
if (typeof dbInstance.pragma === "function") {
|
|
35
|
+
dbInstance.pragma("journal_mode = WAL");
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
logger?.debug("WAL mode not available, using default journal mode");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return dbInstance;
|
|
42
|
+
}
|
|
43
|
+
function closeDatabase() {
|
|
44
|
+
if (dbInstance) {
|
|
45
|
+
dbInstance.close();
|
|
46
|
+
dbInstance = null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function initializeTables() {
|
|
50
|
+
const db = getDatabase();
|
|
51
|
+
db.exec(`
|
|
52
|
+
CREATE TABLE IF NOT EXISTS workflows (
|
|
53
|
+
id TEXT PRIMARY KEY,
|
|
54
|
+
name TEXT NOT NULL UNIQUE,
|
|
55
|
+
version TEXT NOT NULL DEFAULT '1.0',
|
|
56
|
+
description TEXT,
|
|
57
|
+
definition TEXT NOT NULL,
|
|
58
|
+
config TEXT NOT NULL DEFAULT '{}',
|
|
59
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
60
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
61
|
+
task_id INTEGER,
|
|
62
|
+
created_at TEXT NOT NULL,
|
|
63
|
+
updated_at TEXT NOT NULL
|
|
64
|
+
)
|
|
65
|
+
`);
|
|
66
|
+
db.exec(`
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_workflows_name ON workflows(name);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_workflows_tags ON workflows(tags);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_workflows_task_id ON workflows(task_id);
|
|
70
|
+
`);
|
|
71
|
+
}
|
|
72
|
+
function resetDatabase() {
|
|
73
|
+
closeDatabase();
|
|
74
|
+
dbInstance = null;
|
|
75
|
+
}
|
|
76
|
+
function initDatabase(path) {
|
|
77
|
+
const db = getDatabase(path);
|
|
78
|
+
initializeTables();
|
|
79
|
+
return db;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export { getDatabasePath, getDatabase, closeDatabase, initializeTables, resetDatabase, initDatabase };
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__esm,
|
|
3
|
+
__require
|
|
4
|
+
} from "./chunk-wbkh7wat.js";
|
|
5
|
+
|
|
6
|
+
// src/env/log-trace/span-storage.ts
|
|
7
|
+
class SQLiteSpanStorage {
|
|
8
|
+
db = null;
|
|
9
|
+
dbPath;
|
|
10
|
+
initialized = false;
|
|
11
|
+
constructor(dbPath) {
|
|
12
|
+
if (!dbPath) {
|
|
13
|
+
throw new Error("SQLiteSpanStorage requires a valid dbPath parameter");
|
|
14
|
+
}
|
|
15
|
+
if (dbPath === ":memory:") {
|
|
16
|
+
throw new Error("SQLiteSpanStorage does not support :memory: mode. Use a file path instead.");
|
|
17
|
+
}
|
|
18
|
+
this.dbPath = dbPath;
|
|
19
|
+
}
|
|
20
|
+
async initialize() {
|
|
21
|
+
if (this.initialized)
|
|
22
|
+
return;
|
|
23
|
+
const { Database } = __require("bun:sqlite");
|
|
24
|
+
const fs = __require("fs");
|
|
25
|
+
const path = __require("path");
|
|
26
|
+
const dir = path.dirname(this.dbPath);
|
|
27
|
+
if (!fs.existsSync(dir)) {
|
|
28
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
this.db = new Database(this.dbPath);
|
|
31
|
+
this.db.run("PRAGMA journal_mode=WAL");
|
|
32
|
+
this.db.run("PRAGMA busy_timeout=5000");
|
|
33
|
+
this.db.run("PRAGMA synchronous=NORMAL");
|
|
34
|
+
this.db.run(`
|
|
35
|
+
CREATE TABLE IF NOT EXISTS span (
|
|
36
|
+
span_id TEXT PRIMARY KEY,
|
|
37
|
+
trace_id TEXT NOT NULL,
|
|
38
|
+
parent_span_id TEXT,
|
|
39
|
+
name TEXT NOT NULL,
|
|
40
|
+
kind TEXT NOT NULL,
|
|
41
|
+
status TEXT NOT NULL,
|
|
42
|
+
start_time INTEGER NOT NULL,
|
|
43
|
+
end_time INTEGER,
|
|
44
|
+
attributes TEXT,
|
|
45
|
+
result TEXT,
|
|
46
|
+
error TEXT,
|
|
47
|
+
time_created INTEGER NOT NULL
|
|
48
|
+
)
|
|
49
|
+
`);
|
|
50
|
+
this.db.run("CREATE INDEX IF NOT EXISTS idx_span_trace ON span(trace_id)");
|
|
51
|
+
this.db.run("CREATE INDEX IF NOT EXISTS idx_span_parent ON span(parent_span_id)");
|
|
52
|
+
this.initialized = true;
|
|
53
|
+
}
|
|
54
|
+
save(span) {
|
|
55
|
+
if (!this.db)
|
|
56
|
+
return;
|
|
57
|
+
const stmt = this.db.prepare(`
|
|
58
|
+
INSERT OR REPLACE INTO span
|
|
59
|
+
(span_id, trace_id, parent_span_id, name, kind, status, start_time, end_time, attributes, result, error, time_created)
|
|
60
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
61
|
+
`);
|
|
62
|
+
const resultValue = span.result !== undefined && span.result !== null ? typeof span.result === "string" ? span.result : JSON.stringify(span.result) : null;
|
|
63
|
+
stmt.run(span.spanId, span.traceId, span.parentSpanId || null, span.name, span.kind, span.status, span.startTime, span.endTime || null, JSON.stringify(span.attributes), resultValue, span.error || null, Date.now());
|
|
64
|
+
}
|
|
65
|
+
saveBatch(spans) {
|
|
66
|
+
for (const span of spans) {
|
|
67
|
+
this.save(span);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
findByTraceId(traceId) {
|
|
71
|
+
if (!this.db)
|
|
72
|
+
return [];
|
|
73
|
+
const rows = this.db.prepare("SELECT * FROM span WHERE trace_id = ?").all(traceId);
|
|
74
|
+
return this.buildTree(rows.map(this.rowToSpan));
|
|
75
|
+
}
|
|
76
|
+
findBySpanId(spanId) {
|
|
77
|
+
if (!this.db)
|
|
78
|
+
return;
|
|
79
|
+
const row = this.db.prepare("SELECT * FROM span WHERE span_id = ?").get(spanId);
|
|
80
|
+
return row ? this.rowToSpan(row) : undefined;
|
|
81
|
+
}
|
|
82
|
+
listTraces(limit = 10) {
|
|
83
|
+
if (!this.db)
|
|
84
|
+
return [];
|
|
85
|
+
const rows = this.db.prepare(`
|
|
86
|
+
SELECT trace_id,
|
|
87
|
+
MIN(start_time) as start_time,
|
|
88
|
+
MAX(end_time) as end_time,
|
|
89
|
+
COUNT(*) as span_count
|
|
90
|
+
FROM span
|
|
91
|
+
GROUP BY trace_id
|
|
92
|
+
ORDER BY start_time DESC
|
|
93
|
+
LIMIT ?
|
|
94
|
+
`).all(limit);
|
|
95
|
+
return rows.map((row) => ({
|
|
96
|
+
traceId: row.trace_id,
|
|
97
|
+
rootSpanName: "unknown",
|
|
98
|
+
startTime: row.start_time,
|
|
99
|
+
endTime: row.end_time,
|
|
100
|
+
duration: row.end_time - row.start_time,
|
|
101
|
+
spanCount: row.span_count,
|
|
102
|
+
status: "ok"
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
deleteByTraceId(traceId) {
|
|
106
|
+
if (this.db) {
|
|
107
|
+
this.db.prepare("DELETE FROM span WHERE trace_id = ?").run(traceId);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
close() {
|
|
111
|
+
if (this.db) {
|
|
112
|
+
this.db.close();
|
|
113
|
+
this.db = null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
rowToSpan(row) {
|
|
117
|
+
return {
|
|
118
|
+
traceId: row.trace_id,
|
|
119
|
+
spanId: row.span_id,
|
|
120
|
+
parentSpanId: row.parent_span_id,
|
|
121
|
+
name: row.name,
|
|
122
|
+
kind: row.kind,
|
|
123
|
+
status: row.status,
|
|
124
|
+
startTime: row.start_time,
|
|
125
|
+
endTime: row.end_time,
|
|
126
|
+
attributes: row.attributes ? JSON.parse(row.attributes) : {},
|
|
127
|
+
result: row.result || undefined,
|
|
128
|
+
error: row.error || undefined
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
buildTree(spans) {
|
|
132
|
+
const spanMap = new Map;
|
|
133
|
+
const roots = [];
|
|
134
|
+
for (const span of spans) {
|
|
135
|
+
spanMap.set(span.spanId, { ...span, children: [] });
|
|
136
|
+
}
|
|
137
|
+
for (const span of spanMap.values()) {
|
|
138
|
+
if (span.parentSpanId) {
|
|
139
|
+
const parent = spanMap.get(span.parentSpanId);
|
|
140
|
+
if (parent) {
|
|
141
|
+
parent.children.push(span);
|
|
142
|
+
} else {
|
|
143
|
+
roots.push(span);
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
roots.push(span);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return roots;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
var init_span_storage = () => {};
|
|
153
|
+
|
|
154
|
+
export { SQLiteSpanStorage, init_span_storage };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__esm
|
|
3
|
+
} from "./chunk-wbkh7wat.js";
|
|
4
|
+
|
|
5
|
+
// src/env/workflow/utils/session-recovery.ts
|
|
6
|
+
function inferNextNode(messages, definition) {
|
|
7
|
+
if (messages.length === 0) {
|
|
8
|
+
return { type: "entry_node", nodeId: definition.entryNode };
|
|
9
|
+
}
|
|
10
|
+
const lastMessage = messages[messages.length - 1];
|
|
11
|
+
const metadata = lastMessage.metadata;
|
|
12
|
+
switch (metadata?.type) {
|
|
13
|
+
case "workflow.node.call":
|
|
14
|
+
return {
|
|
15
|
+
type: "resume_node",
|
|
16
|
+
nodeId: metadata.workflowNodeId,
|
|
17
|
+
agentSessionId: metadata.agentSessionId
|
|
18
|
+
};
|
|
19
|
+
case "workflow.node.interrupt":
|
|
20
|
+
return {
|
|
21
|
+
type: "ask_user",
|
|
22
|
+
nodeId: metadata.workflowNodeId,
|
|
23
|
+
agentSessionId: metadata.agentSessionId
|
|
24
|
+
};
|
|
25
|
+
case "workflow.node.result":
|
|
26
|
+
return getNextNodes(metadata.workflowNodeId, definition);
|
|
27
|
+
default:
|
|
28
|
+
const lastCall = findLastCallMessage(messages);
|
|
29
|
+
if (lastCall) {
|
|
30
|
+
const callMetadata = lastCall.metadata;
|
|
31
|
+
return {
|
|
32
|
+
type: "resume_node",
|
|
33
|
+
nodeId: callMetadata.workflowNodeId,
|
|
34
|
+
agentSessionId: callMetadata.agentSessionId
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return { type: "entry_node", nodeId: definition.entryNode };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function getNextNodes(completedNodeId, definition) {
|
|
41
|
+
if (!definition.edges) {
|
|
42
|
+
return { type: "next_nodes", nodeIds: [] };
|
|
43
|
+
}
|
|
44
|
+
const nextNodeIds = definition.edges.filter((edge) => edge.from === completedNodeId).map((edge) => edge.to);
|
|
45
|
+
return { type: "next_nodes", nodeIds: nextNodeIds };
|
|
46
|
+
}
|
|
47
|
+
function findLastInterruptMessage(messages) {
|
|
48
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
49
|
+
const msg = messages[i];
|
|
50
|
+
if (msg.metadata?.type === "workflow.node.interrupt") {
|
|
51
|
+
return msg;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function findLastCallMessage(messages) {
|
|
57
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
58
|
+
const msg = messages[i];
|
|
59
|
+
if (msg.metadata?.type === "workflow.node.call") {
|
|
60
|
+
return msg;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
function parseNodeOutputs(messages) {
|
|
66
|
+
const outputs = new Map;
|
|
67
|
+
let lastCallNodeId = null;
|
|
68
|
+
for (const msg of messages) {
|
|
69
|
+
const metadata = msg.metadata;
|
|
70
|
+
if (metadata?.type === "workflow.node.call") {
|
|
71
|
+
lastCallNodeId = metadata.workflowNodeId;
|
|
72
|
+
} else if (metadata?.type === "workflow.node.result" && lastCallNodeId) {
|
|
73
|
+
try {
|
|
74
|
+
outputs.set(lastCallNodeId, JSON.parse(msg.content));
|
|
75
|
+
} catch {
|
|
76
|
+
outputs.set(lastCallNodeId, msg.content);
|
|
77
|
+
}
|
|
78
|
+
lastCallNodeId = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return outputs;
|
|
82
|
+
}
|
|
83
|
+
function hasPendingAskUser(messages) {
|
|
84
|
+
if (messages.length === 0)
|
|
85
|
+
return false;
|
|
86
|
+
const lastMessage = messages[messages.length - 1];
|
|
87
|
+
const metadata = lastMessage.metadata;
|
|
88
|
+
return metadata?.type === "workflow.node.interrupt";
|
|
89
|
+
}
|
|
90
|
+
function getAgentSessionIdFromInterrupt(messages) {
|
|
91
|
+
const lastInterrupt = findLastInterruptMessage(messages);
|
|
92
|
+
if (!lastInterrupt)
|
|
93
|
+
return null;
|
|
94
|
+
const metadata = lastInterrupt.metadata;
|
|
95
|
+
return metadata?.agentSessionId || null;
|
|
96
|
+
}
|
|
97
|
+
var init_session_recovery = () => {};
|
|
98
|
+
init_session_recovery();
|
|
99
|
+
|
|
100
|
+
export {
|
|
101
|
+
parseNodeOutputs,
|
|
102
|
+
inferNextNode,
|
|
103
|
+
hasPendingAskUser,
|
|
104
|
+
getAgentSessionIdFromInterrupt,
|
|
105
|
+
findLastInterruptMessage,
|
|
106
|
+
findLastCallMessage
|
|
107
|
+
};
|