@ai-setting/roy-agent-core 1.6.17 → 1.6.19
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/env/agent/index.js +1 -1
- package/dist/env/event-source/index.js +3 -3
- package/dist/env/index.js +11 -11
- package/dist/env/prompt/index.js +2 -2
- package/dist/env/task/delegate/index.js +2 -2
- package/dist/env/task/index.js +4 -4
- package/dist/env/task/plugins/index.js +2 -2
- package/dist/env/task/tools/index.js +1 -1
- package/dist/env/workflow/engine/index.js +1 -1
- package/dist/env/workflow/index.js +3 -3
- package/dist/env/workflow/tools/index.js +1 -1
- package/dist/index.js +12 -12
- package/dist/shared/@ai-setting/{roy-agent-core-pq1q854s.js → roy-agent-core-4djnmd86.js} +45 -22
- package/dist/shared/@ai-setting/{roy-agent-core-cfqm5w9b.js → roy-agent-core-5ka95kh7.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-m134hen4.js → roy-agent-core-5kc9qtej.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-bsxgrqzq.js → roy-agent-core-8wd5awxg.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-yqxrekhg.js → roy-agent-core-btp589bw.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-r0t34bbh.js → roy-agent-core-c7e3htaq.js} +146 -8
- package/dist/shared/@ai-setting/{roy-agent-core-yr3fp8tv.js → roy-agent-core-f1cjs6c4.js} +28 -5
- package/dist/shared/@ai-setting/{roy-agent-core-4z7dzcgb.js → roy-agent-core-kkt2ndpf.js} +168 -7
- package/dist/shared/@ai-setting/{roy-agent-core-dnns0v64.js → roy-agent-core-m0wy7p0q.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-x36fsm47.js → roy-agent-core-mekk4as5.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-4cgkj7v0.js → roy-agent-core-mqeqevym.js} +679 -32
- package/dist/shared/@ai-setting/{roy-agent-core-edbhy767.js → roy-agent-core-qyb2z42s.js} +27 -1
- package/package.json +1 -1
|
@@ -92,7 +92,101 @@ var TreeTasksToolSchema = z.object({
|
|
|
92
92
|
init_env_context();
|
|
93
93
|
init_logger();
|
|
94
94
|
import { execSync } from "child_process";
|
|
95
|
-
|
|
95
|
+
|
|
96
|
+
// src/env/task/task-child-context.ts
|
|
97
|
+
init_logger();
|
|
98
|
+
var logger = createLogger("task-child-context");
|
|
99
|
+
var STRIPPED_KEYS = ["commit", "token", "secret", "password", "api_key"];
|
|
100
|
+
function stripSensitiveKeys(obj) {
|
|
101
|
+
if (obj === null || obj === undefined)
|
|
102
|
+
return obj;
|
|
103
|
+
if (Array.isArray(obj))
|
|
104
|
+
return obj.map(stripSensitiveKeys);
|
|
105
|
+
if (typeof obj !== "object")
|
|
106
|
+
return obj;
|
|
107
|
+
const out = {};
|
|
108
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
109
|
+
const lower = k.toLowerCase();
|
|
110
|
+
if (STRIPPED_KEYS.some((s) => lower.includes(s)))
|
|
111
|
+
continue;
|
|
112
|
+
out[k] = stripSensitiveKeys(v);
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
function inheritChildContext(args) {
|
|
117
|
+
const { parent, overrides = {} } = args;
|
|
118
|
+
const contextInherit = overrides.contextInherit !== false;
|
|
119
|
+
const inheritTags = overrides.inheritTags === true;
|
|
120
|
+
const project_path = overrides.projectPath ?? parent.projectPath ?? "unknown";
|
|
121
|
+
let parentCtx = {};
|
|
122
|
+
if (parent.contextJson && parent.contextJson.trim().length > 0) {
|
|
123
|
+
try {
|
|
124
|
+
const parsed = JSON.parse(parent.contextJson);
|
|
125
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
126
|
+
parentCtx = parsed;
|
|
127
|
+
}
|
|
128
|
+
} catch (err) {
|
|
129
|
+
logger.debug(`[task-child-context] parent #${parent.taskId} context is malformed JSON; ` + `continuing with empty inherited context (${err instanceof Error ? err.message : String(err)})`);
|
|
130
|
+
parentCtx = {};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const childCtx = {};
|
|
134
|
+
if (contextInherit) {
|
|
135
|
+
if (parentCtx.worktree_path !== undefined && overrides.worktreePath === undefined) {
|
|
136
|
+
childCtx.worktree_path = parentCtx.worktree_path;
|
|
137
|
+
}
|
|
138
|
+
if (parentCtx.branch !== undefined && overrides.branch === undefined) {
|
|
139
|
+
childCtx.branch = parentCtx.branch;
|
|
140
|
+
}
|
|
141
|
+
if (parentCtx.parent_branch !== undefined) {
|
|
142
|
+
childCtx.parent_branch = parentCtx.parent_branch;
|
|
143
|
+
}
|
|
144
|
+
if (parentCtx.type !== undefined) {
|
|
145
|
+
childCtx.type = parentCtx.type;
|
|
146
|
+
}
|
|
147
|
+
if (parentCtx.prior_context && typeof parentCtx.prior_context === "object") {
|
|
148
|
+
const pc = parentCtx.prior_context;
|
|
149
|
+
const safe = {};
|
|
150
|
+
for (const [k, v] of Object.entries(pc)) {
|
|
151
|
+
if (k.toLowerCase() === "commit")
|
|
152
|
+
continue;
|
|
153
|
+
safe[k] = v;
|
|
154
|
+
}
|
|
155
|
+
if (Object.keys(safe).length > 0) {
|
|
156
|
+
childCtx.prior_context = safe;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const reserved = new Set([
|
|
160
|
+
"worktree_path",
|
|
161
|
+
"branch",
|
|
162
|
+
"parent_branch",
|
|
163
|
+
"type",
|
|
164
|
+
"prior_context",
|
|
165
|
+
"created_at"
|
|
166
|
+
]);
|
|
167
|
+
for (const [k, v] of Object.entries(parentCtx)) {
|
|
168
|
+
if (reserved.has(k))
|
|
169
|
+
continue;
|
|
170
|
+
childCtx[k] = v;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (overrides.worktreePath !== undefined)
|
|
174
|
+
childCtx.worktree_path = overrides.worktreePath;
|
|
175
|
+
if (overrides.branch !== undefined)
|
|
176
|
+
childCtx.branch = overrides.branch;
|
|
177
|
+
const createdAt = overrides.createdAt ?? new Date().toISOString();
|
|
178
|
+
childCtx.created_at = createdAt;
|
|
179
|
+
childCtx.child_of = parent.taskId;
|
|
180
|
+
const sanitized = stripSensitiveKeys(childCtx);
|
|
181
|
+
return {
|
|
182
|
+
project_path,
|
|
183
|
+
context: JSON.stringify(sanitized),
|
|
184
|
+
inheritedTags: inheritTags ? parent.tags ?? [] : []
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/env/task/tools/create-tool.ts
|
|
189
|
+
var logger2 = createLogger("task:tools:create");
|
|
96
190
|
function detectWorktree() {
|
|
97
191
|
try {
|
|
98
192
|
const toplevel = execSync("git rev-parse --show-toplevel", {
|
|
@@ -242,9 +336,53 @@ function createTaskTool(taskComponent) {
|
|
|
242
336
|
const sessionId = ctx.session_id || "unknown";
|
|
243
337
|
const detectedWorktree = detectWorktree();
|
|
244
338
|
let enrichedContext = params.context;
|
|
339
|
+
let inheritedProjectPath = params.project_path && params.project_path.trim() !== "" ? params.project_path : undefined;
|
|
340
|
+
let inheritedTags = params.tags;
|
|
341
|
+
let inheritedContext;
|
|
342
|
+
if (params.parent_task_id !== undefined && params.parent_task_id !== null) {
|
|
343
|
+
try {
|
|
344
|
+
const parent = await taskComponent.getTask(params.parent_task_id);
|
|
345
|
+
if (parent) {
|
|
346
|
+
const inherited = inheritChildContext({
|
|
347
|
+
parent: {
|
|
348
|
+
taskId: parent.id,
|
|
349
|
+
projectPath: parent.project_path,
|
|
350
|
+
contextJson: parent.context ?? "",
|
|
351
|
+
tags: parent.tags
|
|
352
|
+
},
|
|
353
|
+
overrides: {
|
|
354
|
+
projectPath: inheritedProjectPath,
|
|
355
|
+
branch: undefined,
|
|
356
|
+
worktreePath: undefined,
|
|
357
|
+
inheritTags: params.tags === undefined,
|
|
358
|
+
contextInherit: true
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
if (inheritedProjectPath === undefined) {
|
|
362
|
+
inheritedProjectPath = inherited.project_path;
|
|
363
|
+
}
|
|
364
|
+
if (params.tags === undefined)
|
|
365
|
+
inheritedTags = inherited.inheritedTags;
|
|
366
|
+
inheritedContext = inherited.context;
|
|
367
|
+
}
|
|
368
|
+
} catch (err) {
|
|
369
|
+
logger2.debug(`[task_create] failed to pre-load parent #${params.parent_task_id} for context inheritance: ${err instanceof Error ? err.message : String(err)}`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
245
372
|
try {
|
|
246
373
|
const ctxObj = params.context ? JSON.parse(params.context) : {};
|
|
247
374
|
const obj = typeof ctxObj === "object" && ctxObj !== null && !Array.isArray(ctxObj) ? ctxObj : {};
|
|
375
|
+
if (inheritedContext) {
|
|
376
|
+
try {
|
|
377
|
+
const inheritedObj = JSON.parse(inheritedContext);
|
|
378
|
+
if (inheritedObj && typeof inheritedObj === "object" && !Array.isArray(inheritedObj)) {
|
|
379
|
+
for (const [k, v] of Object.entries(inheritedObj)) {
|
|
380
|
+
if (obj[k] === undefined)
|
|
381
|
+
obj[k] = v;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
} catch {}
|
|
385
|
+
}
|
|
248
386
|
if (!obj.created_at) {
|
|
249
387
|
obj.created_at = new Date().toISOString();
|
|
250
388
|
}
|
|
@@ -264,13 +402,13 @@ function createTaskTool(taskComponent) {
|
|
|
264
402
|
type: params.type || "normal",
|
|
265
403
|
goals_and_expected_deliverables: params.goals_and_expected_deliverables,
|
|
266
404
|
due_date: params.due_date,
|
|
267
|
-
tags:
|
|
405
|
+
tags: inheritedTags,
|
|
268
406
|
sessionId,
|
|
269
|
-
project_path: params.project_path,
|
|
407
|
+
project_path: inheritedProjectPath ?? params.project_path,
|
|
270
408
|
context: enrichedContext
|
|
271
409
|
});
|
|
272
410
|
setCurrentTaskId(task.id);
|
|
273
|
-
|
|
411
|
+
logger2.info(`[createTask] Trace: Task #${task.id} created, currentTaskId=${task.id} set in EnvContext`);
|
|
274
412
|
return {
|
|
275
413
|
success: true,
|
|
276
414
|
output: `Task created successfully: #${task.id} - ${task.title}`,
|
|
@@ -550,7 +688,7 @@ function batchDeleteTaskTool(taskComponent) {
|
|
|
550
688
|
// src/env/task/tools/update-tool.ts
|
|
551
689
|
init_env_context();
|
|
552
690
|
init_logger();
|
|
553
|
-
var
|
|
691
|
+
var logger3 = createLogger("tool:update-task");
|
|
554
692
|
async function detectCycle(taskComponent, taskId, newParentId) {
|
|
555
693
|
const visited = new Set;
|
|
556
694
|
let currentId = newParentId;
|
|
@@ -624,7 +762,7 @@ function updateTaskTool(taskComponent) {
|
|
|
624
762
|
});
|
|
625
763
|
}
|
|
626
764
|
setCurrentTaskId(task.id);
|
|
627
|
-
|
|
765
|
+
logger3.info(`[updateTask] Trace: Task #${task.id} updated, currentTaskId=${task.id} set in EnvContext`);
|
|
628
766
|
return {
|
|
629
767
|
success: true,
|
|
630
768
|
output: `Task updated: #${task.id} - ${task.title}`,
|
|
@@ -678,7 +816,7 @@ function deleteTaskTool(taskComponent) {
|
|
|
678
816
|
// src/env/task/tools/complete-tool.ts
|
|
679
817
|
init_env_context();
|
|
680
818
|
init_logger();
|
|
681
|
-
var
|
|
819
|
+
var logger4 = createLogger("task:tools:complete");
|
|
682
820
|
function completeTaskTool(taskComponent) {
|
|
683
821
|
return {
|
|
684
822
|
name: "task_complete",
|
|
@@ -715,7 +853,7 @@ function completeTaskTool(taskComponent) {
|
|
|
715
853
|
};
|
|
716
854
|
}
|
|
717
855
|
setCurrentTaskId(undefined);
|
|
718
|
-
|
|
856
|
+
logger4.info(`[completeTask] Trace: Task #${params.task_id} completed, currentTaskId cleared from EnvContext`);
|
|
719
857
|
return {
|
|
720
858
|
success: true,
|
|
721
859
|
output: `Task completed: #${task.id} - ${task.title}`,
|
|
@@ -2322,7 +2322,7 @@ var init_engine = __esm(() => {
|
|
|
2322
2322
|
scheduler.markFailed(nodeId);
|
|
2323
2323
|
}
|
|
2324
2324
|
}
|
|
2325
|
-
async checkLoopGuardWithSnapshot(sessionState, templateResolver, reEntryId,
|
|
2325
|
+
async checkLoopGuardWithSnapshot(sessionState, templateResolver, reEntryId, snapshotPreviousOutput) {
|
|
2326
2326
|
const guard = sessionState.dagManager.getLoopGuard(reEntryId);
|
|
2327
2327
|
if (!guard) {
|
|
2328
2328
|
return { trip: false, counterKey: "", nextCount: 0 };
|
|
@@ -2330,19 +2330,42 @@ var init_engine = __esm(() => {
|
|
|
2330
2330
|
const counterKey = `_loop_guard_consecutive_${reEntryId}`;
|
|
2331
2331
|
const previousCount = sessionState.loopGuardCounters.get(reEntryId) ?? 0;
|
|
2332
2332
|
const previousValue = templateResolver.resolveValue(guard.previous_signal);
|
|
2333
|
-
const
|
|
2333
|
+
const resolvedCwdRaw = templateResolver.resolveValue(guard.cwd);
|
|
2334
|
+
const resolvedCwd = typeof resolvedCwdRaw === "string" && resolvedCwdRaw.length > 0 ? resolvedCwdRaw : undefined;
|
|
2335
|
+
const resolvedCommandRaw = templateResolver.resolveValue(guard.current_signal_command);
|
|
2336
|
+
const resolvedCommand = typeof resolvedCommandRaw === "string" && resolvedCommandRaw.length > 0 ? resolvedCommandRaw : guard.current_signal_command;
|
|
2337
|
+
const cwd = resolvedCwd ?? sessionState.config.workflowInput?.project_path ?? process.cwd();
|
|
2334
2338
|
let currentValue;
|
|
2335
2339
|
try {
|
|
2336
|
-
const { stdout } = await execFileAsync("/bin/sh", ["-c",
|
|
2340
|
+
const { stdout } = await execFileAsync("/bin/sh", ["-c", resolvedCommand], {
|
|
2337
2341
|
cwd,
|
|
2338
2342
|
timeout: 1e4
|
|
2339
2343
|
});
|
|
2340
2344
|
currentValue = stdout.trim();
|
|
2341
2345
|
} catch (err) {
|
|
2342
|
-
|
|
2343
|
-
|
|
2346
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
2347
|
+
logger3.error(`[WorkflowEngine] loop_guard command failed for ${reEntryId}: ${errMessage}. Counting as no-progress.`);
|
|
2348
|
+
const nextCount2 = previousCount + 1;
|
|
2349
|
+
const maxAllowed2 = guard.max_consecutive_no_progress;
|
|
2350
|
+
if (nextCount2 >= maxAllowed2) {
|
|
2351
|
+
const failMessage = guard.fail_message ?? `loop_guard command failed for ${reEntryId} after ${nextCount2} consecutive re-entries: ${errMessage}`;
|
|
2352
|
+
return { trip: true, failMessage, counterKey, nextCount: nextCount2 };
|
|
2353
|
+
}
|
|
2354
|
+
sessionState.loopGuardCounters.set(reEntryId, nextCount2);
|
|
2355
|
+
return { trip: false, counterKey, nextCount: nextCount2 };
|
|
2344
2356
|
}
|
|
2345
2357
|
if (previousValue === undefined) {
|
|
2358
|
+
const snapshotHasContent = snapshotPreviousOutput !== undefined && snapshotPreviousOutput !== null && typeof snapshotPreviousOutput === "object" && Object.keys(snapshotPreviousOutput).length > 0;
|
|
2359
|
+
if (snapshotHasContent) {
|
|
2360
|
+
const nextCount2 = previousCount + 1;
|
|
2361
|
+
const maxAllowed2 = guard.max_consecutive_no_progress;
|
|
2362
|
+
if (nextCount2 >= maxAllowed2) {
|
|
2363
|
+
const failMessage = guard.fail_message ?? `loop_guard previous_signal path unresolved for ${reEntryId} after ${nextCount2} consecutive re-entries: ${guard.previous_signal}`;
|
|
2364
|
+
return { trip: true, failMessage, counterKey, nextCount: nextCount2 };
|
|
2365
|
+
}
|
|
2366
|
+
sessionState.loopGuardCounters.set(reEntryId, nextCount2);
|
|
2367
|
+
return { trip: false, counterKey, nextCount: nextCount2 };
|
|
2368
|
+
}
|
|
2346
2369
|
return { trip: false, counterKey, nextCount: 0 };
|
|
2347
2370
|
}
|
|
2348
2371
|
const isUnchanged = JSON.stringify(previousValue) === JSON.stringify(currentValue);
|
|
@@ -648,6 +648,128 @@ function buildErrorReturn(args) {
|
|
|
648
648
|
}
|
|
649
649
|
};
|
|
650
650
|
}
|
|
651
|
+
var MAX_ERROR_MESSAGE_CHARS = 1500;
|
|
652
|
+
var ERROR_CLASSIFICATION_PREFIX = "[ErrorType=";
|
|
653
|
+
function classifyError(error) {
|
|
654
|
+
if (error instanceof Error) {
|
|
655
|
+
const rawName = typeof error.name === "string" && error.name.trim() ? error.name.trim() : "Error";
|
|
656
|
+
const safeName = rawName.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 80);
|
|
657
|
+
if (!error.message)
|
|
658
|
+
return `${ERROR_CLASSIFICATION_PREFIX}${safeName}:EmptyMessage]`;
|
|
659
|
+
return `${ERROR_CLASSIFICATION_PREFIX}${safeName}]`;
|
|
660
|
+
}
|
|
661
|
+
if (error === null)
|
|
662
|
+
return `${ERROR_CLASSIFICATION_PREFIX}Null]`;
|
|
663
|
+
if (error === undefined)
|
|
664
|
+
return `${ERROR_CLASSIFICATION_PREFIX}Undefined]`;
|
|
665
|
+
if (typeof error === "string") {
|
|
666
|
+
if (error.trim().length === 0)
|
|
667
|
+
return `${ERROR_CLASSIFICATION_PREFIX}EmptyString]`;
|
|
668
|
+
return `${ERROR_CLASSIFICATION_PREFIX}String]`;
|
|
669
|
+
}
|
|
670
|
+
if (typeof error === "number")
|
|
671
|
+
return `${ERROR_CLASSIFICATION_PREFIX}Number]`;
|
|
672
|
+
if (typeof error === "boolean")
|
|
673
|
+
return `${ERROR_CLASSIFICATION_PREFIX}Boolean]`;
|
|
674
|
+
if (typeof error === "object")
|
|
675
|
+
return `${ERROR_CLASSIFICATION_PREFIX}Object]`;
|
|
676
|
+
return `${ERROR_CLASSIFICATION_PREFIX}Unknown]`;
|
|
677
|
+
}
|
|
678
|
+
function normalizeErrorMessage(error) {
|
|
679
|
+
if (error instanceof Error) {
|
|
680
|
+
if (typeof error.message === "string" && error.message.length > 0) {
|
|
681
|
+
return error.message;
|
|
682
|
+
}
|
|
683
|
+
return error.name && error.name !== "Error" ? error.name : "";
|
|
684
|
+
}
|
|
685
|
+
if (typeof error === "string")
|
|
686
|
+
return error;
|
|
687
|
+
if (typeof error === "number" || typeof error === "boolean") {
|
|
688
|
+
return String(error);
|
|
689
|
+
}
|
|
690
|
+
return "";
|
|
691
|
+
}
|
|
692
|
+
function sanitizeErrorMessage(message, sensitive) {
|
|
693
|
+
if (!message || sensitive.length === 0)
|
|
694
|
+
return message;
|
|
695
|
+
let sanitized = message;
|
|
696
|
+
const ordered = [...sensitive].sort((a, b) => b.length - a.length);
|
|
697
|
+
for (const secret of ordered) {
|
|
698
|
+
if (!secret)
|
|
699
|
+
continue;
|
|
700
|
+
sanitized = sanitized.split(secret).join("[REDACTED]");
|
|
701
|
+
}
|
|
702
|
+
return sanitized;
|
|
703
|
+
}
|
|
704
|
+
function capErrorLength(message, max = MAX_ERROR_MESSAGE_CHARS) {
|
|
705
|
+
if (typeof message !== "string" || message.length <= max)
|
|
706
|
+
return message;
|
|
707
|
+
const truncated = message.substring(0, max);
|
|
708
|
+
return `${truncated}…[truncated ${message.length - max} chars; original=${message.length}]`;
|
|
709
|
+
}
|
|
710
|
+
function errorMessageBaseFor(message) {
|
|
711
|
+
return typeof message === "string" && message.length > 0 ? message : "";
|
|
712
|
+
}
|
|
713
|
+
function collectSensitiveValues(input, messageForEnvScan) {
|
|
714
|
+
const sensitive = [];
|
|
715
|
+
if (input && typeof input === "object") {
|
|
716
|
+
for (const v of Object.values(input)) {
|
|
717
|
+
if (typeof v === "string" && v.length >= 6)
|
|
718
|
+
sensitive.push(v);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
const envSecretKeys = new Set;
|
|
722
|
+
try {
|
|
723
|
+
for (const [k, v] of Object.entries(process.env ?? {})) {
|
|
724
|
+
if (typeof v !== "string" || v.length < 6)
|
|
725
|
+
continue;
|
|
726
|
+
const kLower = k.toLowerCase();
|
|
727
|
+
if (kLower.includes("token") || kLower.includes("secret") || kLower.includes("password") || kLower.includes("api_key") || kLower.includes("apikey")) {
|
|
728
|
+
sensitive.push(v);
|
|
729
|
+
envSecretKeys.add(k);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
} catch {}
|
|
733
|
+
if (messageForEnvScan) {
|
|
734
|
+
try {
|
|
735
|
+
for (const [k, v] of Object.entries(process.env ?? {})) {
|
|
736
|
+
if (typeof v !== "string" || v.length < 8)
|
|
737
|
+
continue;
|
|
738
|
+
if (envSecretKeys.has(k))
|
|
739
|
+
continue;
|
|
740
|
+
if (messageForEnvScan.includes(v) && (/[0-9_-]/.test(v) || /^[A-Za-z0-9+/=_-]+$/.test(v))) {
|
|
741
|
+
sensitive.push(v);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
} catch {}
|
|
745
|
+
}
|
|
746
|
+
return sensitive;
|
|
747
|
+
}
|
|
748
|
+
function extractStackSummary(message) {
|
|
749
|
+
if (typeof message !== "string" || message.length === 0)
|
|
750
|
+
return "";
|
|
751
|
+
const lines = message.split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.length > 0);
|
|
752
|
+
if (lines.length === 0)
|
|
753
|
+
return "";
|
|
754
|
+
const picked = [lines[0]];
|
|
755
|
+
let frameCount = 0;
|
|
756
|
+
for (let i = 1;i < lines.length; i++) {
|
|
757
|
+
const line = lines[i];
|
|
758
|
+
if (/^\s*(File\s+|at\s+)/.test(line)) {
|
|
759
|
+
picked.push(line);
|
|
760
|
+
frameCount++;
|
|
761
|
+
if (frameCount >= 3)
|
|
762
|
+
break;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
const lastLine = lines[lines.length - 1];
|
|
766
|
+
if (picked[picked.length - 1] !== lastLine && !/^\s*(File\s+|at\s+)/.test(lastLine)) {
|
|
767
|
+
picked.push(lastLine);
|
|
768
|
+
}
|
|
769
|
+
const joined = picked.join(`
|
|
770
|
+
`);
|
|
771
|
+
return joined.length > 600 ? joined.slice(0, 600) + "…[truncated]" : joined;
|
|
772
|
+
}
|
|
651
773
|
var RunWorkflowInputSchema = z8.object({
|
|
652
774
|
workflow_name: z8.string().describe("Name of the workflow to run"),
|
|
653
775
|
input: z8.record(z8.any()).optional().describe("Input to pass to the workflow"),
|
|
@@ -801,11 +923,42 @@ function createRunWorkflowTool(workflowService, hooks) {
|
|
|
801
923
|
}
|
|
802
924
|
durationMs = Date.now() - startTime;
|
|
803
925
|
const finalRunId = capturedByCallback ? capturedRunId : result.runId ?? "";
|
|
926
|
+
const resolvedStatus = result.status;
|
|
927
|
+
const isResolvedFailure = resolvedStatus === "failed" || resolvedStatus === "stopped";
|
|
928
|
+
const sensitiveForResolved = collectSensitiveValues(input, errorMessageBaseFor(result.error ?? ""));
|
|
929
|
+
const sanitizedResolvedMessage = sanitizeErrorMessage(errorMessageBaseFor(result.error ?? ""), sensitiveForResolved);
|
|
930
|
+
const resolvedErrorClassification = result.error ? classifyError(new Error(result.error)) : "[ErrorType=EmptyMessage]";
|
|
931
|
+
const resolvedErrorMessage = capErrorLength(sanitizedResolvedMessage.length > 0 ? sanitizedResolvedMessage : "Workflow reported status=failed without an error message (runId=" + finalRunId + ")");
|
|
932
|
+
if (isResolvedFailure) {
|
|
933
|
+
const failureCode = result.error ? "WORKFLOW_FAILED" : "WORKFLOW_FAILED_NO_MESSAGE";
|
|
934
|
+
return {
|
|
935
|
+
success: false,
|
|
936
|
+
output: {
|
|
937
|
+
run_id: finalRunId,
|
|
938
|
+
session_id: result.sessionId ?? finalRunId,
|
|
939
|
+
status: resolvedStatus,
|
|
940
|
+
error: result.error,
|
|
941
|
+
error_code: failureCode,
|
|
942
|
+
error_message: result.error ? sanitizedResolvedMessage : "",
|
|
943
|
+
error_stack_summary: extractStackSummary(result.error ?? ""),
|
|
944
|
+
output: result.output,
|
|
945
|
+
duration_ms: result.durationMs || durationMs,
|
|
946
|
+
...result.pendingNodeId ? { pending_node_id: result.pendingNodeId } : {},
|
|
947
|
+
...result.query ? { query: result.query } : {},
|
|
948
|
+
...result.agentSessionId ? { agent_session_id: result.agentSessionId } : {}
|
|
949
|
+
},
|
|
950
|
+
error: `${resolvedErrorMessage} ${resolvedErrorClassification} (runId: ${finalRunId})`,
|
|
951
|
+
metadata: {
|
|
952
|
+
execution_time_ms: durationMs,
|
|
953
|
+
run_id: finalRunId
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
}
|
|
804
957
|
return {
|
|
805
|
-
success:
|
|
958
|
+
success: resolvedStatus === "completed" || resolvedStatus === "paused",
|
|
806
959
|
output: {
|
|
807
960
|
run_id: finalRunId,
|
|
808
|
-
status:
|
|
961
|
+
status: resolvedStatus,
|
|
809
962
|
output: result.output,
|
|
810
963
|
error: result.error,
|
|
811
964
|
duration_ms: result.durationMs || durationMs,
|
|
@@ -823,9 +976,13 @@ function createRunWorkflowTool(workflowService, hooks) {
|
|
|
823
976
|
clearTimeout(timeoutHandle);
|
|
824
977
|
}
|
|
825
978
|
durationMs = Date.now() - startTime;
|
|
826
|
-
const
|
|
979
|
+
const errorClassification = classifyError(error);
|
|
980
|
+
const rawErrorMessage = normalizeErrorMessage(error);
|
|
981
|
+
const errorMessageBase = rawErrorMessage.length > 0 ? rawErrorMessage : `${errorClassification} (no message from thrown value)`;
|
|
827
982
|
const errorRunId = capturedRunId ?? reservedRunId;
|
|
828
|
-
|
|
983
|
+
const sensitiveValues = collectSensitiveValues(input, errorMessageBase);
|
|
984
|
+
const sanitizedMessage = sanitizeErrorMessage(errorMessageBase, sensitiveValues);
|
|
985
|
+
if (sanitizedMessage.includes("Workflow not found")) {
|
|
829
986
|
return buildErrorReturn({
|
|
830
987
|
errorRunId,
|
|
831
988
|
status: "failed",
|
|
@@ -833,7 +990,7 @@ function createRunWorkflowTool(workflowService, hooks) {
|
|
|
833
990
|
durationMs
|
|
834
991
|
});
|
|
835
992
|
}
|
|
836
|
-
const isTimeoutLike =
|
|
993
|
+
const isTimeoutLike = sanitizedMessage.includes("abort") || sanitizedMessage.includes("timed out") || sanitizedMessage.includes("execution timeout:");
|
|
837
994
|
if (isTimeoutLike) {
|
|
838
995
|
if (!timedOut) {
|
|
839
996
|
attemptStopOnTimeout(workflowService, errorRunId, "timed out");
|
|
@@ -846,12 +1003,16 @@ function createRunWorkflowTool(workflowService, hooks) {
|
|
|
846
1003
|
});
|
|
847
1004
|
}
|
|
848
1005
|
if (logger7?.error) {
|
|
849
|
-
logger7.error(`Failed to run workflow: ${workflow_name}`, {
|
|
1006
|
+
logger7.error(`Failed to run workflow: ${workflow_name}`, {
|
|
1007
|
+
error: rawErrorMessage,
|
|
1008
|
+
errorClassification
|
|
1009
|
+
});
|
|
850
1010
|
}
|
|
1011
|
+
const composed = rawErrorMessage.length > 0 ? `Failed to run workflow ${workflow_name}: ${sanitizedMessage} ${errorClassification}` : `Failed to run workflow ${workflow_name} ${errorClassification}: ${sanitizedMessage}`;
|
|
851
1012
|
return buildErrorReturn({
|
|
852
1013
|
errorRunId,
|
|
853
1014
|
status: "failed",
|
|
854
|
-
errorMessage:
|
|
1015
|
+
errorMessage: capErrorLength(composed),
|
|
855
1016
|
durationMs
|
|
856
1017
|
});
|
|
857
1018
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
WorkflowEngine,
|
|
7
7
|
exports_engine,
|
|
8
8
|
init_engine
|
|
9
|
-
} from "./roy-agent-core-
|
|
9
|
+
} from "./roy-agent-core-f1cjs6c4.js";
|
|
10
10
|
import {
|
|
11
11
|
askUserTool,
|
|
12
12
|
createRunWorkflowTool,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
createWorkflowSearchTool,
|
|
19
19
|
createWorkflowTagListTool,
|
|
20
20
|
createWorkflowValidateTool
|
|
21
|
-
} from "./roy-agent-core-
|
|
21
|
+
} from "./roy-agent-core-kkt2ndpf.js";
|
|
22
22
|
import {
|
|
23
23
|
WorkflowService
|
|
24
24
|
} from "./roy-agent-core-r15sn7ve.js";
|