@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.
@@ -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
+ };