openfox 2.0.112 → 2.0.114
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 +49 -0
- package/README.md +1 -0
- package/dist/CHANGELOG.md +49 -0
- package/dist/agent-defaults/builder.agent.md +1 -0
- package/dist/agent-defaults/planner.agent.md +1 -0
- package/dist/{backend-P3GHHLHJ.js → backend-LVYHLGQJ.js} +2 -2
- package/dist/{chat-handler-BYXZIIV3.js → chat-handler-KWXRSWXZ.js} +32 -26
- package/dist/{chunk-XWNCKIPO.js → chunk-2XD65L7M.js} +2 -2
- package/dist/{chunk-C5NQF2K4.js → chunk-3O77NT4T.js} +29 -10
- package/dist/{chunk-XCK5IBO4.js → chunk-7GWARYQC.js} +60 -1042
- package/dist/{chunk-YHEQTVFV.js → chunk-AZHWLLPP.js} +1 -1
- package/dist/{chunk-FFPCVN5M.js → chunk-BZVW77PI.js} +4 -4
- package/dist/{chunk-SDGNV45R.js → chunk-FW4NDUBL.js} +15 -15
- package/dist/{chunk-Z56SEG4Z.js → chunk-GUHHUDNL.js} +6 -6
- package/dist/{chunk-RT2A2RRL.js → chunk-HP5CIB66.js} +2 -2
- package/dist/{chunk-UAF2FOI5.js → chunk-HV6IALXF.js} +7 -7
- package/dist/{chunk-SYJMUIRC.js → chunk-I7FY2LTR.js} +2 -2
- package/dist/{chunk-RISQXU32.js → chunk-JP7NM545.js} +2 -2
- package/dist/{chunk-NB2D6I64.js → chunk-JXLRL5JR.js} +5 -5
- package/dist/{chunk-RAKPI4OE.js → chunk-K733B5T2.js} +264 -27
- package/dist/{chunk-C372UH7N.js → chunk-KSXCOHHW.js} +18 -20
- package/dist/{chunk-JDT63SSP.js → chunk-L63Q4JQJ.js} +3 -3
- package/dist/{chunk-ERYUSG5C.js → chunk-LXYPMFTH.js} +3 -3
- package/dist/{chunk-FSYRANYR.js → chunk-MUSPWEBB.js} +4 -5
- package/dist/chunk-NCZRWCJN.js +7 -0
- package/dist/{chunk-JR54MDZI.js → chunk-NLO64UE3.js} +2 -2
- package/dist/{chunk-3UILDGOO.js → chunk-NWJLWLKF.js} +8 -8
- package/dist/chunk-OSXPQSLW.js +128 -0
- package/dist/chunk-OTYAEEX3.js +1081 -0
- package/dist/{chunk-PCC4DBPF.js → chunk-OXSTNSCF.js} +2 -2
- package/dist/{chunk-33Q7LCVD.js → chunk-P5UANBBX.js} +6 -4
- package/dist/{chunk-LCQ5AN6Y.js → chunk-PBW3YC3G.js} +89 -1
- package/dist/{chunk-IYTDCPEQ.js → chunk-QD7MRMCH.js} +352 -333
- package/dist/{chunk-N4RTAGFY.js → chunk-SA34STZ6.js} +2 -2
- package/dist/{chunk-FR5LUTLQ.js → chunk-SBSUDHL4.js} +10 -6
- package/dist/{chunk-6FPGJR7O.js → chunk-SFZGMB2G.js} +2 -2
- package/dist/{chunk-SVJFMZ2Q.js → chunk-TKKP56QK.js} +11 -4
- package/dist/{chunk-JNHKKUGJ.js → chunk-UPBWEHIL.js} +30 -148
- package/dist/{chunk-QGXLZZBS.js → chunk-UTIQ7OO5.js} +2 -2
- package/dist/{chunk-RKMP74BB.js → chunk-VPVLO436.js} +4 -4
- package/dist/chunk-W77NBJAZ.js +957 -0
- package/dist/{chunk-P45RJGOT.js → chunk-X25Q6RAV.js} +1 -1
- package/dist/{chunk-BOSKQI62.js → chunk-YGJIK3CG.js} +4 -4
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{client-QNQTX5EA.js → client-EM7ISGUP.js} +6 -6
- package/dist/{compactor-X2KZ3XFU.js → compactor-V3LR7APW.js} +13 -12
- package/dist/{config-TW5FHQEM.js → config-EAB3V4QK.js} +2 -2
- package/dist/{dynamic-context-ZRQO2FJN.js → dynamic-context-MVGOF5V2.js} +10 -9
- package/dist/{events-Y6XXQYFG.js → events-PI7IMPHT.js} +8 -7
- package/dist/{folding-Z4GNWRC3.js → folding-FO57K4JM.js} +6 -5
- package/dist/http-client-33EZ3BLR.js +11 -0
- package/dist/{inspect-proxy-N42Z5TOG.js → inspect-proxy-NHKQQ2CD.js} +4 -4
- package/dist/launch-L5ROVNI3.js +52 -0
- package/dist/{manager-HCMDFEQH.js → manager-66YAEO7K.js} +5 -5
- package/dist/{model-overrides-O3ZYKFP7.js → model-overrides-L53PZNZA.js} +4 -4
- package/dist/orchestrator-XK5K3RPL.js +63 -0
- package/dist/package.json +7 -6
- package/dist/{path-security-525YLND3.js → path-security-RSEI3YKB.js} +12 -11
- package/dist/{platform-MEQUWG6U.js → platform-WA4GK5BO.js} +4 -4
- package/dist/{processor-UN4H4V7F.js → processor-WDZSFBVO.js} +31 -25
- package/dist/{project-creator-BVA55HY6.js → project-creator-676WQXVI.js} +3 -3
- package/dist/{projects-PQXME5S4.js → projects-SSBWIYL4.js} +3 -3
- package/dist/{protocol-D6MISQyz.d.ts → protocol-BzHs024-.d.ts} +23 -3
- package/dist/{protocol-FTHAR2YL.js → protocol-RKSWKNXI.js} +3 -3
- package/dist/provider/index.d.ts +4 -4
- package/dist/{provider-3R4X62LW.js → provider-PLIWRBCF.js} +9 -9
- package/dist/{provider-manager-W5N4XRE5.js → provider-manager-2QSJTPWS.js} +7 -7
- package/dist/{registry-74KPZ5NV.js → registry-ZP4TN2IN.js} +5 -4
- package/dist/{serve-WHFUNQ6Z.js → serve-MZ3BCCWC.js} +36 -33
- package/dist/server/index.d.ts +8 -5
- package/dist/server/index.js +35 -32
- package/dist/server-EPXODFMB.js +55 -0
- package/dist/service-54PGIPDQ.js +25 -0
- package/dist/{session-overrides-XH6I3COP.js → session-overrides-LXN6W7SA.js} +7 -6
- package/dist/{sessions-D772YTWL.js → sessions-CHPVUG6H.js} +8 -5
- package/dist/{settings-KO6DSJLD.js → settings-NEBM3GQX.js} +3 -3
- package/dist/shared/index.d.ts +3 -3
- package/dist/shared/index.js +1 -1
- package/dist/skill-defaults/workflows/SKILL.md +517 -0
- package/dist/tasks-TJXG2V3U.js +217 -0
- package/dist/{tools-HTUTYMKI.js → tools-CIM26IFB.js} +31 -23
- package/dist/{types-BMEOlLT0.d.ts → types-CMtHpDWT.d.ts} +81 -1
- package/dist/{types-D0TgGL3t.d.ts → types-CbggXFvR.d.ts} +1 -1
- package/dist/{update-BRUFGGTW.js → update-UZBBO42X.js} +2 -2
- package/dist/web/assets/{index-nS1p0g8O.css → index-BmILAZrT.css} +1 -1
- package/dist/web/assets/index-rZHXkfMq.js +324 -0
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/dist/workflow-defaults/default.workflow.json +45 -5
- package/dist/{workspace-YDUQZ3HC.js → workspace-2XODU4YJ.js} +4 -4
- package/package.json +7 -6
- package/dist/chunk-P5AA7OYJ.js +0 -7
- package/dist/http-client-2GDKHZIG.js +0 -11
- package/dist/orchestrator-P5EUMC7E.js +0 -57
- package/dist/server-7MOOJR2N.js +0 -48
- package/dist/web/assets/index-Dukvfqm-.js +0 -323
|
@@ -2,46 +2,37 @@ import {
|
|
|
2
2
|
generateSessionNameForSession,
|
|
3
3
|
getSessionMessageCount,
|
|
4
4
|
needsNameGeneration
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NWJLWLKF.js";
|
|
6
|
+
import {
|
|
7
|
+
launchWorkflowRun
|
|
8
|
+
} from "./chunk-W77NBJAZ.js";
|
|
6
9
|
import {
|
|
7
|
-
runAgentTurn,
|
|
8
10
|
runChatTurn
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-FW4NDUBL.js";
|
|
12
|
+
import {
|
|
13
|
+
devServerManager
|
|
14
|
+
} from "./chunk-K733B5T2.js";
|
|
10
15
|
import {
|
|
11
16
|
applyDynamicContext,
|
|
12
17
|
computeSessionHash,
|
|
13
18
|
computeUnifiedDiff
|
|
14
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-GUHHUDNL.js";
|
|
15
20
|
import {
|
|
16
21
|
appendCompactionPrompt
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import {
|
|
19
|
-
devServerManager,
|
|
20
|
-
executeSubAgent,
|
|
21
|
-
getToolRegistryForAgent
|
|
22
|
-
} from "./chunk-RAKPI4OE.js";
|
|
22
|
+
} from "./chunk-VPVLO436.js";
|
|
23
23
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} from "./chunk-JR54MDZI.js";
|
|
24
|
+
onProcessEvent
|
|
25
|
+
} from "./chunk-TKKP56QK.js";
|
|
27
26
|
import {
|
|
28
|
-
|
|
29
|
-
decodeUtf8,
|
|
30
|
-
onProcessEvent,
|
|
31
|
-
spawnShellProcess
|
|
32
|
-
} from "./chunk-SVJFMZ2Q.js";
|
|
33
|
-
import {
|
|
34
|
-
killProcessTree,
|
|
35
|
-
terminateProcessTree
|
|
27
|
+
killProcessTree
|
|
36
28
|
} from "./chunk-I72ACQ6R.js";
|
|
37
29
|
import {
|
|
38
30
|
gitSpawnEnv
|
|
39
31
|
} from "./chunk-J7GAZGZT.js";
|
|
40
32
|
import {
|
|
41
33
|
combineEventsWithSnapshot,
|
|
42
|
-
getCurrentContextWindowId,
|
|
43
34
|
getEventStore
|
|
44
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-JXLRL5JR.js";
|
|
45
36
|
import {
|
|
46
37
|
createChatErrorMessage,
|
|
47
38
|
createChatMessageMessage,
|
|
@@ -56,10 +47,10 @@ import {
|
|
|
56
47
|
parseClientMessage,
|
|
57
48
|
serializeServerMessage,
|
|
58
49
|
storedEventToServerMessage
|
|
59
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-I7FY2LTR.js";
|
|
60
51
|
import {
|
|
61
52
|
getPlatformShell
|
|
62
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-SA34STZ6.js";
|
|
63
54
|
import {
|
|
64
55
|
getPendingQuestionsForSession,
|
|
65
56
|
provideAnswer
|
|
@@ -67,35 +58,23 @@ import {
|
|
|
67
58
|
import {
|
|
68
59
|
buildMessagesFromStoredEvents,
|
|
69
60
|
foldPendingConfirmations
|
|
70
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-UTIQ7OO5.js";
|
|
71
62
|
import {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
getRuntimeConfig,
|
|
75
|
-
jsonSerializer,
|
|
76
|
-
loadAllAgentsDefault,
|
|
77
|
-
resolveDefaultAgentId,
|
|
78
|
-
saveItemToDir
|
|
79
|
-
} from "./chunk-JNHKKUGJ.js";
|
|
63
|
+
getRuntimeConfig
|
|
64
|
+
} from "./chunk-UPBWEHIL.js";
|
|
80
65
|
import {
|
|
81
66
|
getMaxVisibleItems
|
|
82
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-HP5CIB66.js";
|
|
83
68
|
import {
|
|
84
69
|
logger
|
|
85
70
|
} from "./chunk-K44MW7JJ.js";
|
|
86
|
-
import {
|
|
87
|
-
computeSessionStats
|
|
88
|
-
} from "./chunk-VUQCQXXJ.js";
|
|
89
71
|
import {
|
|
90
72
|
createServerMessage
|
|
91
|
-
} from "./chunk-
|
|
92
|
-
import {
|
|
93
|
-
getGlobalConfigDir
|
|
94
|
-
} from "./chunk-CQGTEGKL.js";
|
|
73
|
+
} from "./chunk-X25Q6RAV.js";
|
|
95
74
|
|
|
96
75
|
// src/server/ws/server.ts
|
|
97
76
|
import { WebSocketServer, WebSocket as WebSocket2 } from "ws";
|
|
98
|
-
import { spawn as
|
|
77
|
+
import { spawn as spawn2 } from "child_process";
|
|
99
78
|
import { createHash as createHash2 } from "crypto";
|
|
100
79
|
|
|
101
80
|
// src/server/ws/terminal.ts
|
|
@@ -351,923 +330,17 @@ function unsubscribeAllFromTerminal(ws) {
|
|
|
351
330
|
}
|
|
352
331
|
}
|
|
353
332
|
|
|
354
|
-
// src/server/workflows/registry.ts
|
|
355
|
-
import { readdir, readFile, writeFile, mkdir, access, unlink } from "fs/promises";
|
|
356
|
-
import { join, dirname } from "path";
|
|
357
|
-
import { constants } from "fs";
|
|
358
|
-
import { fileURLToPath } from "url";
|
|
359
|
-
var __bundleDir = dirname(fileURLToPath(import.meta.url));
|
|
360
|
-
var DEFAULTS_DIR = join(__bundleDir, "defaults");
|
|
361
|
-
var DEFAULTS_DIR_ALT = join(__bundleDir, "workflow-defaults");
|
|
362
|
-
var WORKFLOW_EXTENSION = ".workflow.json";
|
|
363
|
-
function getWorkflowsDir(configDir) {
|
|
364
|
-
return join(configDir, "workflows");
|
|
365
|
-
}
|
|
366
|
-
function getProjectWorkflowsDir(projectDir) {
|
|
367
|
-
return join(projectDir, ".openfox", "workflows");
|
|
368
|
-
}
|
|
369
|
-
async function pathExists(path) {
|
|
370
|
-
try {
|
|
371
|
-
await access(path, constants.R_OK);
|
|
372
|
-
return true;
|
|
373
|
-
} catch {
|
|
374
|
-
return false;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
async function loadWorkflowsFromDir(dir) {
|
|
378
|
-
if (!await pathExists(dir)) {
|
|
379
|
-
return [];
|
|
380
|
-
}
|
|
381
|
-
let files;
|
|
382
|
-
try {
|
|
383
|
-
files = (await readdir(dir)).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
|
|
384
|
-
} catch {
|
|
385
|
-
return [];
|
|
386
|
-
}
|
|
387
|
-
const workflows = [];
|
|
388
|
-
for (const file of files) {
|
|
389
|
-
try {
|
|
390
|
-
const raw = await readFile(join(dir, file), "utf-8");
|
|
391
|
-
const parsed = JSON.parse(raw);
|
|
392
|
-
if (parsed.metadata?.id && parsed.steps?.length > 0) {
|
|
393
|
-
workflows.push(parsed);
|
|
394
|
-
} else {
|
|
395
|
-
logger.warn("Skipping invalid workflow file", { file });
|
|
396
|
-
}
|
|
397
|
-
} catch (err) {
|
|
398
|
-
logger.warn("Failed to parse workflow file", { file, error: err instanceof Error ? err.message : String(err) });
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
return workflows;
|
|
402
|
-
}
|
|
403
|
-
async function loadDefaultWorkflows() {
|
|
404
|
-
let defaults = await loadWorkflowsFromDir(DEFAULTS_DIR);
|
|
405
|
-
if (!defaults.length) {
|
|
406
|
-
defaults = await loadWorkflowsFromDir(DEFAULTS_DIR_ALT);
|
|
407
|
-
}
|
|
408
|
-
return defaults;
|
|
409
|
-
}
|
|
410
|
-
async function loadUserWorkflows(configDir) {
|
|
411
|
-
return loadWorkflowsFromDir(getWorkflowsDir(configDir));
|
|
412
|
-
}
|
|
413
|
-
async function loadProjectWorkflows(projectDir) {
|
|
414
|
-
return loadWorkflowsFromDir(getProjectWorkflowsDir(projectDir));
|
|
415
|
-
}
|
|
416
|
-
async function loadAllWorkflows(configDir, projectDir) {
|
|
417
|
-
const [defaultWorkflows, userWorkflows] = await Promise.all([loadDefaultWorkflows(), loadUserWorkflows(configDir)]);
|
|
418
|
-
const workflowMap = /* @__PURE__ */ new Map();
|
|
419
|
-
for (const workflow of defaultWorkflows) {
|
|
420
|
-
workflowMap.set(workflow.metadata.id, workflow);
|
|
421
|
-
}
|
|
422
|
-
for (const workflow of userWorkflows) {
|
|
423
|
-
workflowMap.set(workflow.metadata.id, workflow);
|
|
424
|
-
}
|
|
425
|
-
if (projectDir) {
|
|
426
|
-
const projectWorkflows = await loadProjectWorkflows(projectDir);
|
|
427
|
-
for (const workflow of projectWorkflows) {
|
|
428
|
-
workflowMap.set(workflow.metadata.id, workflow);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return Array.from(workflowMap.values());
|
|
432
|
-
}
|
|
433
|
-
async function saveWorkflowToProject(projectDir, workflow) {
|
|
434
|
-
await saveItemToDir(getProjectWorkflowsDir(projectDir), workflow, WORKFLOW_EXTENSION, jsonSerializer);
|
|
435
|
-
}
|
|
436
|
-
async function deleteProjectWorkflow(projectDir, workflowId) {
|
|
437
|
-
return deleteItemFromDir(getProjectWorkflowsDir(projectDir), workflowId, WORKFLOW_EXTENSION);
|
|
438
|
-
}
|
|
439
|
-
async function getDefaultWorkflowIds() {
|
|
440
|
-
for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {
|
|
441
|
-
try {
|
|
442
|
-
const files = (await readdir(dir)).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
|
|
443
|
-
return files.map((f) => f.replace(WORKFLOW_EXTENSION, ""));
|
|
444
|
-
} catch {
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
return [];
|
|
448
|
-
}
|
|
449
|
-
async function isDefaultWorkflow(workflowId) {
|
|
450
|
-
const defaultIds = await getDefaultWorkflowIds();
|
|
451
|
-
return defaultIds.includes(workflowId);
|
|
452
|
-
}
|
|
453
|
-
function findWorkflowById(workflowId, workflows) {
|
|
454
|
-
return workflows.find((p) => p.metadata.id === workflowId);
|
|
455
|
-
}
|
|
456
|
-
async function workflowExists(configDir, workflowId, projectDir) {
|
|
457
|
-
if (await pathExists(join(getWorkflowsDir(configDir), `${workflowId}${WORKFLOW_EXTENSION}`))) return true;
|
|
458
|
-
if (projectDir && await pathExists(join(getProjectWorkflowsDir(projectDir), `${workflowId}${WORKFLOW_EXTENSION}`)))
|
|
459
|
-
return true;
|
|
460
|
-
return false;
|
|
461
|
-
}
|
|
462
|
-
async function saveWorkflow(configDir, workflow) {
|
|
463
|
-
const workflowsDir = getWorkflowsDir(configDir);
|
|
464
|
-
if (!await pathExists(workflowsDir)) {
|
|
465
|
-
await mkdir(workflowsDir, { recursive: true });
|
|
466
|
-
}
|
|
467
|
-
const filePath = join(workflowsDir, `${workflow.metadata.id}${WORKFLOW_EXTENSION}`);
|
|
468
|
-
await writeFile(filePath, JSON.stringify(workflow, null, 2) + "\n", "utf-8");
|
|
469
|
-
}
|
|
470
|
-
async function deleteWorkflow(configDir, workflowId) {
|
|
471
|
-
const isDefault = await isDefaultWorkflow(workflowId);
|
|
472
|
-
if (isDefault) {
|
|
473
|
-
return { success: false, reason: "Cannot delete built-in defaults" };
|
|
474
|
-
}
|
|
475
|
-
const filePath = join(getWorkflowsDir(configDir), `${workflowId}${WORKFLOW_EXTENSION}`);
|
|
476
|
-
try {
|
|
477
|
-
await unlink(filePath);
|
|
478
|
-
return { success: true };
|
|
479
|
-
} catch {
|
|
480
|
-
return { success: false };
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// src/server/workflows/types.ts
|
|
485
|
-
var TERMINAL_DONE = "$done";
|
|
486
|
-
var TERMINAL_BLOCKED = "$blocked";
|
|
487
|
-
|
|
488
|
-
// src/server/git/diff.ts
|
|
489
|
-
import { spawn as spawn2 } from "child_process";
|
|
490
|
-
function getGitDiffFiles(cwd) {
|
|
491
|
-
return new Promise((resolve) => {
|
|
492
|
-
const env = gitSpawnEnv();
|
|
493
|
-
const diffProc = spawn2("git", ["diff", "--name-status", "HEAD"], {
|
|
494
|
-
cwd,
|
|
495
|
-
env,
|
|
496
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
497
|
-
windowsHide: true
|
|
498
|
-
});
|
|
499
|
-
const statusProc = spawn2("git", ["status", "--porcelain"], {
|
|
500
|
-
cwd,
|
|
501
|
-
env,
|
|
502
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
503
|
-
windowsHide: true
|
|
504
|
-
});
|
|
505
|
-
let diffStdout = "";
|
|
506
|
-
let statusStdout = "";
|
|
507
|
-
let diffExited = false;
|
|
508
|
-
let statusExited = false;
|
|
509
|
-
let diffCode = null;
|
|
510
|
-
let statusCode = null;
|
|
511
|
-
const collect = () => {
|
|
512
|
-
if (!diffExited || !statusExited) return;
|
|
513
|
-
const files = [];
|
|
514
|
-
if (diffCode === 0) {
|
|
515
|
-
for (const line of diffStdout.split("\n")) {
|
|
516
|
-
if (!line.trim()) continue;
|
|
517
|
-
const [statusChar, ...pathParts] = line.split(" ");
|
|
518
|
-
const path = pathParts.join(" ") || statusChar || "";
|
|
519
|
-
if (!path) continue;
|
|
520
|
-
const status = statusChar === "A" ? "added" : statusChar === "D" ? "deleted" : "modified";
|
|
521
|
-
files.push({ path, status, additions: 0, deletions: 0 });
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
if (statusCode === 0) {
|
|
525
|
-
for (const line of statusStdout.split("\n")) {
|
|
526
|
-
if (!line.startsWith("?? ")) continue;
|
|
527
|
-
const path = line.slice(3).trim();
|
|
528
|
-
if (!path) continue;
|
|
529
|
-
files.push({ path, status: "added", additions: 0, deletions: 0 });
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
resolve(files);
|
|
533
|
-
};
|
|
534
|
-
diffProc.stdout.on("data", (data) => {
|
|
535
|
-
diffStdout += data.toString();
|
|
536
|
-
});
|
|
537
|
-
statusProc.stdout.on("data", (data) => {
|
|
538
|
-
statusStdout += data.toString();
|
|
539
|
-
});
|
|
540
|
-
diffProc.on("close", (code) => {
|
|
541
|
-
diffExited = true;
|
|
542
|
-
diffCode = code;
|
|
543
|
-
collect();
|
|
544
|
-
});
|
|
545
|
-
statusProc.on("close", (code) => {
|
|
546
|
-
statusExited = true;
|
|
547
|
-
statusCode = code;
|
|
548
|
-
collect();
|
|
549
|
-
});
|
|
550
|
-
diffProc.on("error", () => {
|
|
551
|
-
diffExited = true;
|
|
552
|
-
diffCode = 1;
|
|
553
|
-
collect();
|
|
554
|
-
});
|
|
555
|
-
statusProc.on("error", () => {
|
|
556
|
-
statusExited = true;
|
|
557
|
-
statusCode = 1;
|
|
558
|
-
collect();
|
|
559
|
-
});
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
async function formatGitDiffFiles(cwd) {
|
|
563
|
-
const files = await getGitDiffFiles(cwd);
|
|
564
|
-
if (files.length === 0) return "(none)";
|
|
565
|
-
return files.map((f) => `- ${f.path} (${f.status})`).join("\n");
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// src/server/workflows/shell.ts
|
|
569
|
-
function executeShellCommand(command, cwd, timeout, signal) {
|
|
570
|
-
return new Promise((resolve, reject) => {
|
|
571
|
-
if (checkAborted(signal)) {
|
|
572
|
-
reject(new Error("Aborted"));
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
const proc = spawnShellProcess(command, cwd, signal);
|
|
576
|
-
const stdoutChunks = [];
|
|
577
|
-
const stderrChunks = [];
|
|
578
|
-
let killed = false;
|
|
579
|
-
const timer = setTimeout(() => {
|
|
580
|
-
killed = true;
|
|
581
|
-
void terminateProcessTree(proc);
|
|
582
|
-
resolve({
|
|
583
|
-
exitCode: 1,
|
|
584
|
-
stdout: decodeUtf8(stdoutChunks),
|
|
585
|
-
stderr: decodeUtf8(stderrChunks) + "\nCommand timed out",
|
|
586
|
-
success: false
|
|
587
|
-
});
|
|
588
|
-
}, timeout);
|
|
589
|
-
const onAbort = () => {
|
|
590
|
-
if (!killed) {
|
|
591
|
-
killed = true;
|
|
592
|
-
void terminateProcessTree(proc, { immediate: true });
|
|
593
|
-
clearTimeout(timer);
|
|
594
|
-
reject(new Error("Aborted"));
|
|
595
|
-
}
|
|
596
|
-
};
|
|
597
|
-
signal?.addEventListener("abort", onAbort);
|
|
598
|
-
proc.stdout?.on("data", (data) => {
|
|
599
|
-
stdoutChunks.push(data);
|
|
600
|
-
});
|
|
601
|
-
proc.stderr?.on("data", (data) => {
|
|
602
|
-
stderrChunks.push(data);
|
|
603
|
-
});
|
|
604
|
-
proc.on("close", (code) => {
|
|
605
|
-
clearTimeout(timer);
|
|
606
|
-
signal?.removeEventListener("abort", onAbort);
|
|
607
|
-
if (killed) return;
|
|
608
|
-
const exitCode = code ?? 1;
|
|
609
|
-
resolve({
|
|
610
|
-
exitCode,
|
|
611
|
-
stdout: decodeUtf8(stdoutChunks),
|
|
612
|
-
stderr: decodeUtf8(stderrChunks),
|
|
613
|
-
success: exitCode === 0
|
|
614
|
-
});
|
|
615
|
-
});
|
|
616
|
-
proc.on("error", (err) => {
|
|
617
|
-
clearTimeout(timer);
|
|
618
|
-
signal?.removeEventListener("abort", onAbort);
|
|
619
|
-
if (killed) return;
|
|
620
|
-
resolve({ exitCode: 1, stdout: decodeUtf8(stdoutChunks), stderr: err.message, success: false });
|
|
621
|
-
});
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
// src/server/workflows/executor.ts
|
|
626
|
-
var TEMPLATE_VARIABLES = [
|
|
627
|
-
{ name: "workdir", description: "Working directory of the session" },
|
|
628
|
-
{ name: "reason", description: 'Human-readable reason (e.g. "2 criteria remaining")' },
|
|
629
|
-
{
|
|
630
|
-
name: "stepOutput",
|
|
631
|
-
description: "Structured output from the previous step (content, stdout, stderr, exitCode, etc.)"
|
|
632
|
-
},
|
|
633
|
-
{
|
|
634
|
-
name: "verifierFindings",
|
|
635
|
-
description: "@deprecated Use stepOutput.content instead. Output from the last sub-agent step"
|
|
636
|
-
},
|
|
637
|
-
{
|
|
638
|
-
name: "previousStepOutput",
|
|
639
|
-
description: "@deprecated Use stepOutput.stdout instead. Output from the last shell step"
|
|
640
|
-
},
|
|
641
|
-
{ name: "criteriaCount", description: "Total number of criteria" },
|
|
642
|
-
{ name: "pendingCount", description: "Number of pending/failed criteria" },
|
|
643
|
-
{ name: "criteriaList", description: "Formatted list of all criteria with status" },
|
|
644
|
-
{ name: "modifiedFiles", description: "List of modified files" }
|
|
645
|
-
];
|
|
646
|
-
function formatCriteriaList(entries) {
|
|
647
|
-
if (entries.length === 0) return "(none)";
|
|
648
|
-
return entries.map((e) => {
|
|
649
|
-
const status = e.status === "passed" ? "[PASSED]" : e.status === "completed" ? "[NEEDS VERIFICATION]" : e.status === "failed" ? "[FAILED]" : "[NOT COMPLETED]";
|
|
650
|
-
return `- **${e.id}** ${status}: ${e.description}`;
|
|
651
|
-
}).join("\n");
|
|
652
|
-
}
|
|
653
|
-
async function formatModifiedFiles(workdir) {
|
|
654
|
-
return formatGitDiffFiles(workdir);
|
|
655
|
-
}
|
|
656
|
-
function resolveTemplate(template, ctx) {
|
|
657
|
-
let result = template;
|
|
658
|
-
for (const { name } of TEMPLATE_VARIABLES) {
|
|
659
|
-
if (name === "stepOutput" || name === "verifierFindings" || name === "previousStepOutput") continue;
|
|
660
|
-
const value = String(ctx[name]);
|
|
661
|
-
result = result.replace(new RegExp(`\\{\\{${name}\\}\\}`, "g"), value);
|
|
662
|
-
}
|
|
663
|
-
result = result.replace(/\{\{stepOutput\.(\w+)\}\}/g, (_, key) => ctx.stepOutput[key] ?? "");
|
|
664
|
-
result = result.replace(/\{\{verifierFindings\}\}/g, ctx.stepOutput["content"] ?? "");
|
|
665
|
-
result = result.replace(/\{\{previousStepOutput\}\}/g, ctx.stepOutput["stdout"] ?? "");
|
|
666
|
-
for (const [key, value] of Object.entries(ctx.params)) {
|
|
667
|
-
result = result.replaceAll(`{{${key}}}`, value);
|
|
668
|
-
}
|
|
669
|
-
return result;
|
|
670
|
-
}
|
|
671
|
-
function evaluateCondition(condition, stepOutcome, metadataEntries) {
|
|
672
|
-
switch (condition.type) {
|
|
673
|
-
case "step_result":
|
|
674
|
-
if (!stepOutcome) return false;
|
|
675
|
-
return stepOutcome.result === condition.result;
|
|
676
|
-
case "metadata_all_match": {
|
|
677
|
-
if (!metadataEntries) return false;
|
|
678
|
-
const entries = metadataEntries[condition.key];
|
|
679
|
-
if (!entries || entries.length === 0) return true;
|
|
680
|
-
return entries.every((e) => e[condition.field] === condition.value);
|
|
681
|
-
}
|
|
682
|
-
case "metadata_all_in": {
|
|
683
|
-
if (!metadataEntries) return false;
|
|
684
|
-
const entries = metadataEntries[condition.key];
|
|
685
|
-
if (!entries || entries.length === 0) return true;
|
|
686
|
-
return entries.every((e) => condition.values.includes(e[condition.field]));
|
|
687
|
-
}
|
|
688
|
-
case "always":
|
|
689
|
-
return true;
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
function evaluateTransitions(transitions, stepOutcome, metadataEntries) {
|
|
693
|
-
for (const transition of transitions) {
|
|
694
|
-
if (evaluateCondition(transition.when, stepOutcome, metadataEntries)) {
|
|
695
|
-
return transition.goto;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
return TERMINAL_BLOCKED;
|
|
699
|
-
}
|
|
700
|
-
var DEFAULT_USER_RESULT = "continue";
|
|
701
|
-
var CONTINUE_CHOICE_ID = "continue";
|
|
702
|
-
function userStepChoices(step) {
|
|
703
|
-
const seen = /* @__PURE__ */ new Set();
|
|
704
|
-
const choices = [];
|
|
705
|
-
for (const t of step.transitions) {
|
|
706
|
-
if (t.when.type === "step_result") {
|
|
707
|
-
const id = t.when.result;
|
|
708
|
-
if (seen.has(id)) continue;
|
|
709
|
-
seen.add(id);
|
|
710
|
-
choices.push({ id, label: id, goto: t.goto });
|
|
711
|
-
} else if (t.when.type === "always") {
|
|
712
|
-
if (seen.has(CONTINUE_CHOICE_ID)) continue;
|
|
713
|
-
seen.add(CONTINUE_CHOICE_ID);
|
|
714
|
-
choices.push({ id: CONTINUE_CHOICE_ID, label: "Continue", goto: t.goto });
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
return choices;
|
|
718
|
-
}
|
|
719
|
-
function emitWorkflowMessage(eventStore, sessionId, content, windowOptions, onMessage) {
|
|
720
|
-
const msgId = crypto.randomUUID();
|
|
721
|
-
eventStore.append(
|
|
722
|
-
sessionId,
|
|
723
|
-
createMessageStartEvent(msgId, "user", content, {
|
|
724
|
-
...windowOptions ?? {},
|
|
725
|
-
isSystemGenerated: true,
|
|
726
|
-
messageKind: "correction",
|
|
727
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
728
|
-
})
|
|
729
|
-
);
|
|
730
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
|
|
731
|
-
if (onMessage) {
|
|
732
|
-
onMessage(
|
|
733
|
-
createChatMessageMessage({
|
|
734
|
-
id: msgId,
|
|
735
|
-
role: "user",
|
|
736
|
-
content,
|
|
737
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
738
|
-
isSystemGenerated: true,
|
|
739
|
-
messageKind: "correction",
|
|
740
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
741
|
-
})
|
|
742
|
-
);
|
|
743
|
-
}
|
|
744
|
-
return msgId;
|
|
745
|
-
}
|
|
746
|
-
function injectGenericKickoff(sessionId) {
|
|
747
|
-
const eventStore = getEventStore();
|
|
748
|
-
const windowOpts = getCurrentWindowMessageOptions(sessionId);
|
|
749
|
-
const msgId = crypto.randomUUID();
|
|
750
|
-
eventStore.append(
|
|
751
|
-
sessionId,
|
|
752
|
-
createMessageStartEvent(msgId, "user", "Proceed with the current step.", {
|
|
753
|
-
...windowOpts ?? {},
|
|
754
|
-
isSystemGenerated: true,
|
|
755
|
-
messageKind: "auto-prompt",
|
|
756
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
757
|
-
})
|
|
758
|
-
);
|
|
759
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
|
|
760
|
-
}
|
|
761
|
-
function getCurrentWindowMessageOptions(sessionId) {
|
|
762
|
-
const contextWindowId = getCurrentContextWindowId(sessionId);
|
|
763
|
-
return contextWindowId ? { contextWindowId } : void 0;
|
|
764
|
-
}
|
|
765
|
-
function buildReason(metadataEntries) {
|
|
766
|
-
const entries = metadataEntries?.["criteria"] ?? [];
|
|
767
|
-
const remaining = entries.filter((e) => e.status !== "passed");
|
|
768
|
-
return `${remaining.length} criteria remaining`;
|
|
769
|
-
}
|
|
770
|
-
async function executeWorkflow(workflow, options, subGroup) {
|
|
771
|
-
const { sessionManager, sessionId, llmClient, signal, onMessage } = options;
|
|
772
|
-
const eventStore = getEventStore();
|
|
773
|
-
const startTime = performance.now();
|
|
774
|
-
let iterations = 0;
|
|
775
|
-
const activeSteps = subGroup ? workflow.steps.filter((s) => s.subGroup === subGroup) : workflow.steps;
|
|
776
|
-
const resumeFromStep = options.resumeFromStep;
|
|
777
|
-
const isResume = !!resumeFromStep;
|
|
778
|
-
let resumeConsumed = false;
|
|
779
|
-
let currentStepId = isResume ? resumeFromStep : subGroup ? activeSteps[0]?.id ?? workflow.entryStep : workflow.entryStep;
|
|
780
|
-
let lastStepOutput = options.initialStepOutput ?? {};
|
|
781
|
-
const firstEntryForStep = /* @__PURE__ */ new Set();
|
|
782
|
-
const messagesBeforeWorkflow = sessionManager.requireSession(sessionId).messages.length;
|
|
783
|
-
const activeStepIds = new Set(activeSteps.map((s) => s.id));
|
|
784
|
-
const stepsById = /* @__PURE__ */ new Map();
|
|
785
|
-
for (const step of activeSteps) {
|
|
786
|
-
stepsById.set(step.id, step);
|
|
787
|
-
}
|
|
788
|
-
if (resumeFromStep) {
|
|
789
|
-
const targetStep = stepsById.get(resumeFromStep);
|
|
790
|
-
if (!targetStep) {
|
|
791
|
-
return {
|
|
792
|
-
finalAction: {
|
|
793
|
-
type: "BLOCKED",
|
|
794
|
-
reason: `Resume target step "${resumeFromStep}" not found in workflow "${workflow.metadata.id}"`,
|
|
795
|
-
blockedCriteria: []
|
|
796
|
-
},
|
|
797
|
-
iterations: 0,
|
|
798
|
-
totalTime: (performance.now() - startTime) / 1e3
|
|
799
|
-
};
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
logger.debug("Workflow executor starting", { sessionId, workflow: workflow.metadata.id });
|
|
803
|
-
let executionId;
|
|
804
|
-
if (isResume) {
|
|
805
|
-
const activeExec = sessionManager.getActiveWorkflowExecution(sessionId);
|
|
806
|
-
if (activeExec) {
|
|
807
|
-
executionId = activeExec.id;
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
if (workflow.startCondition && workflow.startCondition.type !== "always") {
|
|
811
|
-
const session = sessionManager.requireSession(sessionId);
|
|
812
|
-
const conditionMet = evaluateCondition(
|
|
813
|
-
workflow.startCondition,
|
|
814
|
-
null,
|
|
815
|
-
session.metadataEntries
|
|
816
|
-
);
|
|
817
|
-
if (!conditionMet) {
|
|
818
|
-
logger.debug("Workflow start condition not met", { sessionId, condition: workflow.startCondition.type });
|
|
819
|
-
return {
|
|
820
|
-
finalAction: {
|
|
821
|
-
type: "BLOCKED",
|
|
822
|
-
reason: `Start condition not met: ${workflow.startCondition.type}`,
|
|
823
|
-
blockedCriteria: []
|
|
824
|
-
},
|
|
825
|
-
iterations: 0,
|
|
826
|
-
totalTime: (performance.now() - startTime) / 1e3
|
|
827
|
-
};
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
if (!isResume) {
|
|
831
|
-
const startMsgId = crypto.randomUUID();
|
|
832
|
-
const startWindowOpts = getCurrentWindowMessageOptions(sessionId);
|
|
833
|
-
eventStore.append(
|
|
834
|
-
sessionId,
|
|
835
|
-
createMessageStartEvent(
|
|
836
|
-
startMsgId,
|
|
837
|
-
"user",
|
|
838
|
-
JSON.stringify({
|
|
839
|
-
workflowName: workflow.metadata.name,
|
|
840
|
-
workflowId: workflow.metadata.id,
|
|
841
|
-
workflowColor: workflow.metadata.color
|
|
842
|
-
}),
|
|
843
|
-
{ ...startWindowOpts ?? {}, isSystemGenerated: true, messageKind: "workflow-started" }
|
|
844
|
-
)
|
|
845
|
-
);
|
|
846
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: startMsgId } });
|
|
847
|
-
executionId = crypto.randomUUID();
|
|
848
|
-
sessionManager.startWorkflow(
|
|
849
|
-
sessionId,
|
|
850
|
-
executionId,
|
|
851
|
-
workflow.metadata.id,
|
|
852
|
-
workflow.metadata.name,
|
|
853
|
-
workflow.metadata.color,
|
|
854
|
-
options.params ?? {}
|
|
855
|
-
);
|
|
856
|
-
}
|
|
857
|
-
if (options.userMessage) {
|
|
858
|
-
sessionManager.addMessage(sessionId, {
|
|
859
|
-
role: "user",
|
|
860
|
-
content: options.userMessage.content,
|
|
861
|
-
...options.userMessage.attachments ? { attachments: options.userMessage.attachments } : {}
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
|
-
while (iterations < workflow.settings.maxIterations) {
|
|
865
|
-
if (signal?.aborted) {
|
|
866
|
-
logger.debug("Workflow executor aborted \u2014 preserving execution", { sessionId, iterations });
|
|
867
|
-
return {
|
|
868
|
-
finalAction: { type: "RUN_BUILDER", reason: "Aborted" },
|
|
869
|
-
iterations,
|
|
870
|
-
totalTime: (performance.now() - startTime) / 1e3
|
|
871
|
-
};
|
|
872
|
-
}
|
|
873
|
-
iterations++;
|
|
874
|
-
const step = stepsById.get(currentStepId);
|
|
875
|
-
if (!step) {
|
|
876
|
-
logger.error("Workflow step not found", { sessionId, stepId: currentStepId });
|
|
877
|
-
return {
|
|
878
|
-
finalAction: { type: "BLOCKED", reason: `Step "${currentStepId}" not found in workflow`, blockedCriteria: [] },
|
|
879
|
-
iterations,
|
|
880
|
-
totalTime: (performance.now() - startTime) / 1e3
|
|
881
|
-
};
|
|
882
|
-
}
|
|
883
|
-
const session = sessionManager.requireSession(sessionId);
|
|
884
|
-
const currentWindowMessageOptions = getCurrentWindowMessageOptions(sessionId);
|
|
885
|
-
const criteriaEntries = session.metadataEntries["criteria"] ?? [];
|
|
886
|
-
const templateCtx = {
|
|
887
|
-
workdir: sessionManager.getEffectiveWorkdir(sessionId),
|
|
888
|
-
reason: buildReason(session.metadataEntries),
|
|
889
|
-
verifierFindings: lastStepOutput["content"] ?? "",
|
|
890
|
-
previousStepOutput: lastStepOutput["stdout"] ?? "",
|
|
891
|
-
criteriaCount: criteriaEntries.length,
|
|
892
|
-
pendingCount: criteriaEntries.filter((e) => e.status !== "passed").length,
|
|
893
|
-
criteriaList: formatCriteriaList(criteriaEntries),
|
|
894
|
-
modifiedFiles: await formatModifiedFiles(sessionManager.getEffectiveWorkdir(sessionId)),
|
|
895
|
-
stepOutput: lastStepOutput,
|
|
896
|
-
params: options.params ?? {}
|
|
897
|
-
};
|
|
898
|
-
sessionManager.setPhase(sessionId, step.phase);
|
|
899
|
-
if (executionId) {
|
|
900
|
-
sessionManager.updateWorkflowStep(
|
|
901
|
-
sessionId,
|
|
902
|
-
executionId,
|
|
903
|
-
step.id,
|
|
904
|
-
step.name,
|
|
905
|
-
workflow.metadata.id,
|
|
906
|
-
workflow.metadata.name,
|
|
907
|
-
workflow.metadata.color
|
|
908
|
-
);
|
|
909
|
-
}
|
|
910
|
-
if (step.type === "agent") {
|
|
911
|
-
const agentStep = step;
|
|
912
|
-
sessionManager.setMode(sessionId, agentStep.agentId ?? resolveDefaultAgentId());
|
|
913
|
-
}
|
|
914
|
-
logger.debug("Workflow step executing", { sessionId, iteration: iterations, stepId: step.id, stepType: step.type });
|
|
915
|
-
let stepOutcome = null;
|
|
916
|
-
switch (step.type) {
|
|
917
|
-
case "agent": {
|
|
918
|
-
const agentStep = step;
|
|
919
|
-
const STEP_DONE_PROMPT = "\n\nOnce you're done, call step_done()";
|
|
920
|
-
const STEP_DONE_NUDGE = "You haven't called step_done(). If you haven't finished the task, continue and when you're finished call step_done()";
|
|
921
|
-
let promptContent;
|
|
922
|
-
let nudgeContent;
|
|
923
|
-
const isResumingCurrentStep = isResume && step.id === resumeFromStep && !resumeConsumed;
|
|
924
|
-
if (!firstEntryForStep.has(step.id) && agentStep.prompt && !isResumingCurrentStep) {
|
|
925
|
-
const resolvedPrompt = resolveTemplate(agentStep.prompt, templateCtx);
|
|
926
|
-
promptContent = resolvedPrompt + STEP_DONE_PROMPT;
|
|
927
|
-
const promptMsgId = crypto.randomUUID();
|
|
928
|
-
const msgMetadata = { type: "workflow", name: "Workflow", color: "#f59e0b" };
|
|
929
|
-
eventStore.append(
|
|
930
|
-
sessionId,
|
|
931
|
-
createMessageStartEvent(promptMsgId, "user", promptContent, {
|
|
932
|
-
...currentWindowMessageOptions ?? {},
|
|
933
|
-
isSystemGenerated: true,
|
|
934
|
-
messageKind: "auto-prompt",
|
|
935
|
-
metadata: msgMetadata
|
|
936
|
-
})
|
|
937
|
-
);
|
|
938
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: promptMsgId } });
|
|
939
|
-
if (onMessage) {
|
|
940
|
-
onMessage(
|
|
941
|
-
createChatMessageMessage({
|
|
942
|
-
id: promptMsgId,
|
|
943
|
-
role: "user",
|
|
944
|
-
content: promptContent,
|
|
945
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
946
|
-
isSystemGenerated: true,
|
|
947
|
-
messageKind: "auto-prompt",
|
|
948
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
949
|
-
})
|
|
950
|
-
);
|
|
951
|
-
}
|
|
952
|
-
} else if (firstEntryForStep.has(step.id) && !isResumingCurrentStep) {
|
|
953
|
-
const parts = [];
|
|
954
|
-
if (agentStep.nudgePrompt) {
|
|
955
|
-
const resolvedNudge = resolveTemplate(agentStep.nudgePrompt, templateCtx);
|
|
956
|
-
parts.push(resolvedNudge);
|
|
957
|
-
}
|
|
958
|
-
parts.push(STEP_DONE_NUDGE);
|
|
959
|
-
nudgeContent = parts.join("\n\n");
|
|
960
|
-
emitWorkflowMessage(eventStore, sessionId, nudgeContent, currentWindowMessageOptions, onMessage);
|
|
961
|
-
}
|
|
962
|
-
const turnMetrics = new TurnMetrics();
|
|
963
|
-
const es = getEventStore();
|
|
964
|
-
const append = (event) => es.append(sessionId, event);
|
|
965
|
-
let stepDoneCalled = false;
|
|
966
|
-
const agentResult = await runAgentTurn(
|
|
967
|
-
{
|
|
968
|
-
sessionManager,
|
|
969
|
-
sessionId,
|
|
970
|
-
llmClient,
|
|
971
|
-
...options.statsIdentity ? { statsIdentity: options.statsIdentity } : {},
|
|
972
|
-
...signal ? { signal } : {},
|
|
973
|
-
...onMessage ? { onMessage } : {}
|
|
974
|
-
},
|
|
975
|
-
turnMetrics,
|
|
976
|
-
agentStep.agentId ?? resolveDefaultAgentId(),
|
|
977
|
-
append,
|
|
978
|
-
{
|
|
979
|
-
...!firstEntryForStep.has(step.id) && !agentStep.prompt && !isResumingCurrentStep ? { injectKickoff: () => injectGenericKickoff(sessionId) } : {},
|
|
980
|
-
onToolExecuted: (toolCall, toolResult) => {
|
|
981
|
-
if (toolCall.name === "step_done" && toolResult.success) {
|
|
982
|
-
stepDoneCalled = true;
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
);
|
|
987
|
-
firstEntryForStep.add(step.id);
|
|
988
|
-
resumeConsumed = true;
|
|
989
|
-
const agentReturnValue = agentResult.returnValueResult ?? "completed";
|
|
990
|
-
lastStepOutput = {
|
|
991
|
-
...agentResult.returnValueContent ? { content: agentResult.returnValueContent } : {},
|
|
992
|
-
...agentResult.returnValueResult ? { result: agentResult.returnValueResult } : {},
|
|
993
|
-
stepDoneCalled: String(stepDoneCalled)
|
|
994
|
-
};
|
|
995
|
-
stepOutcome = { result: agentReturnValue, output: lastStepOutput };
|
|
996
|
-
if (!stepDoneCalled) {
|
|
997
|
-
logger.debug("step_done not called, looping agent step", {
|
|
998
|
-
sessionId,
|
|
999
|
-
stepId: step.id,
|
|
1000
|
-
iteration: iterations
|
|
1001
|
-
});
|
|
1002
|
-
continue;
|
|
1003
|
-
}
|
|
1004
|
-
break;
|
|
1005
|
-
}
|
|
1006
|
-
case "sub_agent": {
|
|
1007
|
-
const subStep = step;
|
|
1008
|
-
const turnMetrics = new TurnMetrics();
|
|
1009
|
-
const promptTemplate = subStep.prompt ?? "Perform your task.";
|
|
1010
|
-
const resolvedPrompt = resolveTemplate(promptTemplate, templateCtx);
|
|
1011
|
-
const allAgents = await loadAllAgentsDefault();
|
|
1012
|
-
const agentDef = findAgentById(subStep.subAgentType, allAgents);
|
|
1013
|
-
if (!agentDef) {
|
|
1014
|
-
logger.error("Sub-agent definition not found", { subAgentType: subStep.subAgentType });
|
|
1015
|
-
stepOutcome = { result: "error", output: {} };
|
|
1016
|
-
break;
|
|
1017
|
-
}
|
|
1018
|
-
const toolRegistry = getToolRegistryForAgent(agentDef);
|
|
1019
|
-
const filteredToolRegistry = {
|
|
1020
|
-
tools: toolRegistry.tools.filter((t) => t.name !== "step_done"),
|
|
1021
|
-
definitions: toolRegistry.definitions.filter((d) => d.type === "function" && d.function.name !== "step_done"),
|
|
1022
|
-
execute: toolRegistry.execute
|
|
1023
|
-
};
|
|
1024
|
-
const result = await executeSubAgent({
|
|
1025
|
-
subAgentType: subStep.subAgentType,
|
|
1026
|
-
prompt: resolvedPrompt,
|
|
1027
|
-
sessionManager,
|
|
1028
|
-
sessionId,
|
|
1029
|
-
llmClient,
|
|
1030
|
-
toolRegistry: filteredToolRegistry,
|
|
1031
|
-
turnMetrics,
|
|
1032
|
-
statsIdentity: options.statsIdentity ?? {
|
|
1033
|
-
providerId: "",
|
|
1034
|
-
providerName: "",
|
|
1035
|
-
backend: "unknown",
|
|
1036
|
-
model: llmClient.getModel()
|
|
1037
|
-
},
|
|
1038
|
-
...signal ? { signal } : {},
|
|
1039
|
-
...onMessage ? { onMessage } : {}
|
|
1040
|
-
});
|
|
1041
|
-
lastStepOutput = { content: result.content ?? "", ...result.result ? { result: result.result } : {} };
|
|
1042
|
-
stepOutcome = { result: result.result ?? "success", output: lastStepOutput };
|
|
1043
|
-
break;
|
|
1044
|
-
}
|
|
1045
|
-
case "shell": {
|
|
1046
|
-
const shellStep = step;
|
|
1047
|
-
const command = resolveTemplate(shellStep.command, templateCtx);
|
|
1048
|
-
const timeout = shellStep.timeout ?? 6e4;
|
|
1049
|
-
const successCodes = shellStep.successExitCodes ?? [0];
|
|
1050
|
-
const shellMsgId = crypto.randomUUID();
|
|
1051
|
-
eventStore.append(
|
|
1052
|
-
sessionId,
|
|
1053
|
-
createMessageStartEvent(shellMsgId, "user", `Running: \`${command}\``, {
|
|
1054
|
-
...currentWindowMessageOptions ?? {},
|
|
1055
|
-
isSystemGenerated: true,
|
|
1056
|
-
messageKind: "auto-prompt",
|
|
1057
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
1058
|
-
})
|
|
1059
|
-
);
|
|
1060
|
-
if (onMessage) {
|
|
1061
|
-
onMessage(
|
|
1062
|
-
createChatMessageMessage({
|
|
1063
|
-
id: shellMsgId,
|
|
1064
|
-
role: "user",
|
|
1065
|
-
content: `Running: \`${command}\``,
|
|
1066
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1067
|
-
isSystemGenerated: true,
|
|
1068
|
-
messageKind: "auto-prompt",
|
|
1069
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
1070
|
-
})
|
|
1071
|
-
);
|
|
1072
|
-
}
|
|
1073
|
-
const result = await executeShellCommand(
|
|
1074
|
-
command,
|
|
1075
|
-
sessionManager.getEffectiveWorkdir(sessionId),
|
|
1076
|
-
timeout,
|
|
1077
|
-
signal
|
|
1078
|
-
);
|
|
1079
|
-
const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
1080
|
-
lastStepOutput = { stdout: result.stdout ?? "", stderr: result.stderr ?? "", exitCode: String(result.exitCode) };
|
|
1081
|
-
const outputContent = output ? `Exit code: ${result.exitCode}
|
|
1082
|
-
\`\`\`
|
|
1083
|
-
${output.slice(0, 1e4)}
|
|
1084
|
-
\`\`\`` : `Exit code: ${result.exitCode}`;
|
|
1085
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: shellMsgId } });
|
|
1086
|
-
const outputMsgId = crypto.randomUUID();
|
|
1087
|
-
eventStore.append(
|
|
1088
|
-
sessionId,
|
|
1089
|
-
createMessageStartEvent(outputMsgId, "user", outputContent, {
|
|
1090
|
-
...currentWindowMessageOptions ?? {},
|
|
1091
|
-
isSystemGenerated: true,
|
|
1092
|
-
messageKind: "correction"
|
|
1093
|
-
})
|
|
1094
|
-
);
|
|
1095
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: outputMsgId } });
|
|
1096
|
-
if (onMessage) {
|
|
1097
|
-
onMessage(
|
|
1098
|
-
createChatMessageMessage({
|
|
1099
|
-
id: outputMsgId,
|
|
1100
|
-
role: "user",
|
|
1101
|
-
content: outputContent,
|
|
1102
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1103
|
-
isSystemGenerated: true,
|
|
1104
|
-
messageKind: "correction"
|
|
1105
|
-
})
|
|
1106
|
-
);
|
|
1107
|
-
}
|
|
1108
|
-
stepOutcome = { result: successCodes.includes(result.exitCode) ? "success" : "failure", output: lastStepOutput };
|
|
1109
|
-
break;
|
|
1110
|
-
}
|
|
1111
|
-
case "user": {
|
|
1112
|
-
if (resumeFromStep === step.id) {
|
|
1113
|
-
const choice = options.userChoice;
|
|
1114
|
-
const result = choice === void 0 || choice === CONTINUE_CHOICE_ID ? DEFAULT_USER_RESULT : choice;
|
|
1115
|
-
stepOutcome = { result, output: lastStepOutput };
|
|
1116
|
-
break;
|
|
1117
|
-
}
|
|
1118
|
-
if (executionId) {
|
|
1119
|
-
sessionManager.waitAtStep(
|
|
1120
|
-
sessionId,
|
|
1121
|
-
executionId,
|
|
1122
|
-
step.id,
|
|
1123
|
-
step.name,
|
|
1124
|
-
lastStepOutput,
|
|
1125
|
-
workflow.metadata.id,
|
|
1126
|
-
workflow.metadata.name,
|
|
1127
|
-
workflow.metadata.color,
|
|
1128
|
-
userStepChoices(step)
|
|
1129
|
-
);
|
|
1130
|
-
}
|
|
1131
|
-
logger.debug("Workflow paused at user step", { sessionId, stepId: step.id, stepName: step.name });
|
|
1132
|
-
return {
|
|
1133
|
-
finalAction: {
|
|
1134
|
-
type: "WAITING",
|
|
1135
|
-
reason: `Paused at user step: ${step.name}`,
|
|
1136
|
-
workflowId: workflow.metadata.id,
|
|
1137
|
-
stepId: step.id,
|
|
1138
|
-
stepOutput: lastStepOutput
|
|
1139
|
-
},
|
|
1140
|
-
iterations,
|
|
1141
|
-
totalTime: (performance.now() - startTime) / 1e3
|
|
1142
|
-
};
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
const refreshedSession = sessionManager.requireSession(sessionId);
|
|
1146
|
-
const effectiveTransitions = subGroup ? step.transitions.filter((t) => !t.subGroup || t.subGroup === subGroup) : step.transitions;
|
|
1147
|
-
const rawNextStepId = evaluateTransitions(effectiveTransitions, stepOutcome, refreshedSession.metadataEntries);
|
|
1148
|
-
const nextStepId = subGroup && rawNextStepId !== TERMINAL_DONE && rawNextStepId !== TERMINAL_BLOCKED && !activeStepIds.has(rawNextStepId) ? TERMINAL_DONE : rawNextStepId;
|
|
1149
|
-
if (nextStepId === TERMINAL_DONE) {
|
|
1150
|
-
sessionManager.setPhase(sessionId, "done");
|
|
1151
|
-
if (executionId) {
|
|
1152
|
-
sessionManager.completeWorkflow(
|
|
1153
|
-
sessionId,
|
|
1154
|
-
executionId,
|
|
1155
|
-
workflow.metadata.id,
|
|
1156
|
-
workflow.metadata.name,
|
|
1157
|
-
workflow.metadata.color
|
|
1158
|
-
);
|
|
1159
|
-
}
|
|
1160
|
-
const totalTimeSeconds = Math.round((performance.now() - startTime) / 100) / 10;
|
|
1161
|
-
const completedSession = sessionManager.requireSession(sessionId);
|
|
1162
|
-
const workflowMessages = completedSession.messages.slice(messagesBeforeWorkflow);
|
|
1163
|
-
const workflowStats = computeSessionStats(workflowMessages);
|
|
1164
|
-
const totalToolCalls = workflowMessages.reduce((sum, m) => sum + (m.toolCalls?.length ?? 0), 0);
|
|
1165
|
-
const taskCompletedData = {
|
|
1166
|
-
summary: null,
|
|
1167
|
-
iterations,
|
|
1168
|
-
totalTimeSeconds,
|
|
1169
|
-
totalToolCalls,
|
|
1170
|
-
totalTokensGenerated: workflowStats?.generationTokens ?? 0,
|
|
1171
|
-
avgGenerationSpeed: workflowStats?.avgGenerationSpeed ?? 0,
|
|
1172
|
-
responseCount: workflowStats?.responseCount ?? 0,
|
|
1173
|
-
llmCallCount: workflowStats?.llmCallCount ?? 0,
|
|
1174
|
-
criteria: [],
|
|
1175
|
-
workflowName: workflow.metadata.name,
|
|
1176
|
-
workflowId: workflow.metadata.id,
|
|
1177
|
-
...workflow.metadata.color ? { workflowColor: workflow.metadata.color } : {}
|
|
1178
|
-
};
|
|
1179
|
-
eventStore.append(sessionId, { type: "task.completed", data: taskCompletedData });
|
|
1180
|
-
const markerMsgId = crypto.randomUUID();
|
|
1181
|
-
eventStore.append(
|
|
1182
|
-
sessionId,
|
|
1183
|
-
createMessageStartEvent(markerMsgId, "user", JSON.stringify(taskCompletedData), {
|
|
1184
|
-
...currentWindowMessageOptions ?? {},
|
|
1185
|
-
isSystemGenerated: true,
|
|
1186
|
-
messageKind: "task-completed"
|
|
1187
|
-
})
|
|
1188
|
-
);
|
|
1189
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: markerMsgId } });
|
|
1190
|
-
logger.debug("Workflow executor complete", { sessionId, iterations });
|
|
1191
|
-
const doneAction = { type: "DONE" };
|
|
1192
|
-
return {
|
|
1193
|
-
finalAction: doneAction,
|
|
1194
|
-
iterations,
|
|
1195
|
-
totalTime: totalTimeSeconds
|
|
1196
|
-
};
|
|
1197
|
-
}
|
|
1198
|
-
if (nextStepId === TERMINAL_BLOCKED) {
|
|
1199
|
-
sessionManager.setPhase(sessionId, "blocked");
|
|
1200
|
-
if (executionId) {
|
|
1201
|
-
sessionManager.blockWorkflow(
|
|
1202
|
-
sessionId,
|
|
1203
|
-
executionId,
|
|
1204
|
-
workflow.metadata.id,
|
|
1205
|
-
workflow.metadata.name,
|
|
1206
|
-
workflow.metadata.color
|
|
1207
|
-
);
|
|
1208
|
-
}
|
|
1209
|
-
const reason = "No matching transition";
|
|
1210
|
-
emitWorkflowMessage(eventStore, sessionId, `Runner blocked: ${reason}`, currentWindowMessageOptions, onMessage);
|
|
1211
|
-
logger.warn("Workflow executor blocked", { sessionId, iterations, reason });
|
|
1212
|
-
const blockedAction = { type: "BLOCKED", reason, blockedCriteria: [] };
|
|
1213
|
-
return {
|
|
1214
|
-
finalAction: blockedAction,
|
|
1215
|
-
iterations,
|
|
1216
|
-
totalTime: (performance.now() - startTime) / 1e3
|
|
1217
|
-
};
|
|
1218
|
-
}
|
|
1219
|
-
currentStepId = nextStepId;
|
|
1220
|
-
}
|
|
1221
|
-
logger.warn("Workflow executor max iterations reached", { sessionId, iterations });
|
|
1222
|
-
return {
|
|
1223
|
-
finalAction: {
|
|
1224
|
-
type: "BLOCKED",
|
|
1225
|
-
reason: `Max iterations (${workflow.settings.maxIterations}) reached`,
|
|
1226
|
-
blockedCriteria: []
|
|
1227
|
-
},
|
|
1228
|
-
iterations,
|
|
1229
|
-
totalTime: (performance.now() - startTime) / 1e3
|
|
1230
|
-
};
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
// src/server/runner/orchestrator.ts
|
|
1234
|
-
async function runOrchestrator(options) {
|
|
1235
|
-
const runtimeConfig = getRuntimeConfig();
|
|
1236
|
-
const workflowId = options.workflowId ?? runtimeConfig.activeWorkflowId ?? "default";
|
|
1237
|
-
const configDir = getGlobalConfigDir(runtimeConfig.mode ?? "production");
|
|
1238
|
-
const session = options.sessionManager.requireSession(options.sessionId);
|
|
1239
|
-
const projectDir = session.workdir;
|
|
1240
|
-
const workflows = await loadAllWorkflows(configDir, projectDir);
|
|
1241
|
-
const workflow = findWorkflowById(workflowId, workflows);
|
|
1242
|
-
if (!workflow) {
|
|
1243
|
-
throw new Error(`Workflow "${workflowId}" not found`);
|
|
1244
|
-
}
|
|
1245
|
-
const requiredParams = (workflow.metadata.parameters ?? []).filter((p) => p.required);
|
|
1246
|
-
const suppliedParams = options.params ?? {};
|
|
1247
|
-
const missing = requiredParams.filter((p) => !(p.id in suppliedParams));
|
|
1248
|
-
if (missing.length > 0) {
|
|
1249
|
-
const names = missing.map((p) => p.label || p.id).join(", ");
|
|
1250
|
-
throw new Error(`Missing required parameter${missing.length > 1 ? "s" : ""}: ${names}`);
|
|
1251
|
-
}
|
|
1252
|
-
logger.debug("Using workflow executor", {
|
|
1253
|
-
sessionId: options.sessionId,
|
|
1254
|
-
workflow: workflow.metadata.id,
|
|
1255
|
-
subGroup: options.subGroup
|
|
1256
|
-
});
|
|
1257
|
-
return executeWorkflow(workflow, options, options.subGroup);
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
333
|
// src/server/auth.ts
|
|
1261
|
-
import { readFile
|
|
1262
|
-
import { join
|
|
334
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
335
|
+
import { join, dirname, basename } from "path";
|
|
1263
336
|
import { createHash, privateDecrypt, createPublicKey } from "crypto";
|
|
1264
337
|
function getAuthConfigPath() {
|
|
1265
338
|
const configDir = getRuntimeConfig();
|
|
1266
339
|
const mode = configDir.mode === "development" ? "development" : configDir.mode === "test" ? "test" : "production";
|
|
1267
340
|
if (mode === "test") {
|
|
1268
341
|
const cwd = process.cwd();
|
|
1269
|
-
const base = basename(cwd) === "e2e" ? cwd :
|
|
1270
|
-
const testAuthPath =
|
|
342
|
+
const base = basename(cwd) === "e2e" ? cwd : join(cwd, "e2e");
|
|
343
|
+
const testAuthPath = join(base, ".openfox-test", "auth.json");
|
|
1271
344
|
return testAuthPath;
|
|
1272
345
|
}
|
|
1273
346
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "";
|
|
@@ -1277,8 +350,8 @@ function getAuthConfigPath() {
|
|
|
1277
350
|
}
|
|
1278
351
|
function getKeyPath() {
|
|
1279
352
|
const authPath = getAuthConfigPath();
|
|
1280
|
-
const dir =
|
|
1281
|
-
return
|
|
353
|
+
const dir = dirname(authPath);
|
|
354
|
+
return join(dir, "auth.key");
|
|
1282
355
|
}
|
|
1283
356
|
var cachedAuth = null;
|
|
1284
357
|
var cachedPrivateKey = null;
|
|
@@ -1287,9 +360,9 @@ async function loadPrivateKey() {
|
|
|
1287
360
|
return cachedPrivateKey;
|
|
1288
361
|
}
|
|
1289
362
|
const keyPath = getKeyPath();
|
|
1290
|
-
const keyDir =
|
|
363
|
+
const keyDir = dirname(keyPath);
|
|
1291
364
|
try {
|
|
1292
|
-
cachedPrivateKey = await
|
|
365
|
+
cachedPrivateKey = await readFile(keyPath, "utf-8");
|
|
1293
366
|
return cachedPrivateKey;
|
|
1294
367
|
} catch {
|
|
1295
368
|
const { privateKey } = await import("crypto").then(
|
|
@@ -1299,8 +372,8 @@ async function loadPrivateKey() {
|
|
|
1299
372
|
publicKeyEncoding: { type: "spki", format: "pem" }
|
|
1300
373
|
})
|
|
1301
374
|
);
|
|
1302
|
-
await
|
|
1303
|
-
await
|
|
375
|
+
await mkdir(keyDir, { recursive: true });
|
|
376
|
+
await writeFile(keyPath, privateKey, { mode: 384 });
|
|
1304
377
|
cachedPrivateKey = privateKey;
|
|
1305
378
|
return privateKey;
|
|
1306
379
|
}
|
|
@@ -1315,7 +388,7 @@ async function loadServerAuthConfig() {
|
|
|
1315
388
|
}
|
|
1316
389
|
try {
|
|
1317
390
|
const authPath = getAuthConfigPath();
|
|
1318
|
-
const data = await
|
|
391
|
+
const data = await readFile(authPath, "utf-8");
|
|
1319
392
|
const authConfig = JSON.parse(data);
|
|
1320
393
|
cachedAuth = authConfig;
|
|
1321
394
|
return authConfig;
|
|
@@ -1390,7 +463,7 @@ function signalMcpReady() {
|
|
|
1390
463
|
}
|
|
1391
464
|
function moduleGitBranch(cwd) {
|
|
1392
465
|
return new Promise((resolve) => {
|
|
1393
|
-
const proc =
|
|
466
|
+
const proc = spawn2("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
1394
467
|
cwd,
|
|
1395
468
|
env: gitSpawnEnv(),
|
|
1396
469
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -1416,13 +489,13 @@ function hashContent(content) {
|
|
|
1416
489
|
function moduleGitDiff(cwd) {
|
|
1417
490
|
return new Promise((resolve) => {
|
|
1418
491
|
const env = gitSpawnEnv();
|
|
1419
|
-
const diffProc =
|
|
492
|
+
const diffProc = spawn2("git", ["diff", "--name-status", "HEAD"], {
|
|
1420
493
|
cwd,
|
|
1421
494
|
env,
|
|
1422
495
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1423
496
|
windowsHide: true
|
|
1424
497
|
});
|
|
1425
|
-
const statusProc =
|
|
498
|
+
const statusProc = spawn2("git", ["status", "--porcelain"], {
|
|
1426
499
|
cwd,
|
|
1427
500
|
env,
|
|
1428
501
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -2200,8 +1273,8 @@ async function handleClientMessage(ws, client, message, _getLLMClient, _getActiv
|
|
|
2200
1273
|
const sessionId = client.activeSessionId;
|
|
2201
1274
|
const session = sessionManager.requireSession(sessionId);
|
|
2202
1275
|
try {
|
|
2203
|
-
const { buildCachedPrompt } = await import("./dynamic-context-
|
|
2204
|
-
const allAgents = await import("./registry-
|
|
1276
|
+
const { buildCachedPrompt } = await import("./dynamic-context-MVGOF5V2.js");
|
|
1277
|
+
const allAgents = await import("./registry-ZP4TN2IN.js");
|
|
2205
1278
|
const agentDef = allAgents.findAgentById(session.mode, await allAgents.loadAllAgentsDefault()) ?? allAgents.findAgentById("planner", await allAgents.loadAllAgentsDefault());
|
|
2206
1279
|
const modelName = session.providerModel ?? _providerManager?.getCurrentModel();
|
|
2207
1280
|
const { systemPrompt: newPrompt, hash: newHash } = await buildCachedPrompt(
|
|
@@ -2321,8 +1394,6 @@ ${content}` : workflowInfo;
|
|
|
2321
1394
|
const hasUserAttachments = launchAttachments && launchAttachments.length > 0;
|
|
2322
1395
|
const hasUserMessage = hasUserContent || hasUserAttachments;
|
|
2323
1396
|
const isResume = !!launchPayload?.resumeFrom;
|
|
2324
|
-
sessionManager.setRunning(sessionId, true);
|
|
2325
|
-
sendForSession(sessionId, createSessionRunningMessage(true));
|
|
2326
1397
|
const controller = new AbortController();
|
|
2327
1398
|
const existingController = activeAgents.get(sessionId);
|
|
2328
1399
|
if (existingController) {
|
|
@@ -2351,70 +1422,30 @@ ${content}` : workflowInfo;
|
|
|
2351
1422
|
);
|
|
2352
1423
|
}
|
|
2353
1424
|
}
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
exec.workflowId,
|
|
2374
|
-
exec.workflowName,
|
|
2375
|
-
exec.workflowColor
|
|
2376
|
-
);
|
|
2377
|
-
if (resumed) {
|
|
2378
|
-
return {
|
|
2379
|
-
params: resumed.params,
|
|
2380
|
-
initialStepOutput: resumed.stepOutput,
|
|
2381
|
-
...exec.currentStepId ? { resumeFromStep: exec.currentStepId } : {}
|
|
2382
|
-
};
|
|
2383
|
-
}
|
|
2384
|
-
}
|
|
2385
|
-
return {
|
|
2386
|
-
...Object.keys(exec.params).length > 0 ? { params: exec.params } : {},
|
|
2387
|
-
...Object.keys(exec.stepOutput).length > 0 ? { initialStepOutput: exec.stepOutput } : {},
|
|
2388
|
-
...exec.currentStepId ? { resumeFromStep: exec.currentStepId } : {}
|
|
2389
|
-
};
|
|
2390
|
-
})() : {},
|
|
2391
|
-
...hasUserMessage ? {
|
|
2392
|
-
userMessage: {
|
|
1425
|
+
launchWorkflowRun(
|
|
1426
|
+
{
|
|
1427
|
+
sessionManager,
|
|
1428
|
+
sessionId,
|
|
1429
|
+
controller,
|
|
1430
|
+
llmClient: llmForSession(sessionId),
|
|
1431
|
+
statsIdentity: statsForSession(sessionId),
|
|
1432
|
+
broadcastForSession: (sid, msg) => _broadcastForSession(sid, msg),
|
|
1433
|
+
onFinished: () => cleanupAfterTurn(sessionId, controller, sendForSession, true)
|
|
1434
|
+
},
|
|
1435
|
+
{
|
|
1436
|
+
...launchPayload?.workflowId ? { workflowId: launchPayload.workflowId } : {},
|
|
1437
|
+
...launchPayload?.subGroup ? { subGroup: launchPayload.subGroup } : {},
|
|
1438
|
+
...launchPayload?.scope ? { scope: launchPayload.scope } : {},
|
|
1439
|
+
...isResume && launchPayload?.resumeFrom ? { resumeFrom: launchPayload.resumeFrom } : {},
|
|
1440
|
+
...isResume && launchPayload?.stepOutput ? { stepOutput: launchPayload.stepOutput } : {},
|
|
1441
|
+
...isResume && launchPayload?.userChoice ? { userChoice: launchPayload.userChoice } : {},
|
|
1442
|
+
...launchPayload?.params ? { params: launchPayload.params } : {},
|
|
1443
|
+
...hasUserMessage ? {
|
|
2393
1444
|
content: hasUserContent ? launchPayload.content : "",
|
|
2394
1445
|
...hasUserAttachments ? { attachments: launchAttachments } : {}
|
|
2395
|
-
}
|
|
2396
|
-
} : {},
|
|
2397
|
-
signal: controller.signal,
|
|
2398
|
-
onMessage: (msg) => _broadcastForSession(sessionId, msg)
|
|
2399
|
-
// For path confirmation dialogs
|
|
2400
|
-
}).catch((error) => {
|
|
2401
|
-
if (error instanceof Error && error.message === "Aborted") {
|
|
2402
|
-
return;
|
|
1446
|
+
} : {}
|
|
2403
1447
|
}
|
|
2404
|
-
|
|
2405
|
-
logger.error("Runner error", { error: errorMessage, sessionId });
|
|
2406
|
-
_broadcastForSession(
|
|
2407
|
-
sessionId,
|
|
2408
|
-
createServerMessage("chat.error", { error: errorMessage, recoverable: false })
|
|
2409
|
-
);
|
|
2410
|
-
}).finally(() => {
|
|
2411
|
-
try {
|
|
2412
|
-
sessionManager.setRunning(sessionId, false);
|
|
2413
|
-
sendForSession(sessionId, createSessionRunningMessage(false));
|
|
2414
|
-
cleanupAfterTurn(sessionId, controller, sendForSession, true);
|
|
2415
|
-
} catch {
|
|
2416
|
-
}
|
|
2417
|
-
});
|
|
1448
|
+
);
|
|
2418
1449
|
break;
|
|
2419
1450
|
}
|
|
2420
1451
|
// =========================================================================
|
|
@@ -2501,19 +1532,6 @@ ${content}` : workflowInfo;
|
|
|
2501
1532
|
|
|
2502
1533
|
export {
|
|
2503
1534
|
terminalManager,
|
|
2504
|
-
loadDefaultWorkflows,
|
|
2505
|
-
loadUserWorkflows,
|
|
2506
|
-
loadProjectWorkflows,
|
|
2507
|
-
loadAllWorkflows,
|
|
2508
|
-
saveWorkflowToProject,
|
|
2509
|
-
deleteProjectWorkflow,
|
|
2510
|
-
getDefaultWorkflowIds,
|
|
2511
|
-
isDefaultWorkflow,
|
|
2512
|
-
findWorkflowById,
|
|
2513
|
-
workflowExists,
|
|
2514
|
-
saveWorkflow,
|
|
2515
|
-
deleteWorkflow,
|
|
2516
|
-
TEMPLATE_VARIABLES,
|
|
2517
1535
|
loadServerAuthConfig,
|
|
2518
1536
|
getAuthConfig,
|
|
2519
1537
|
requiresAuth,
|
|
@@ -2524,4 +1542,4 @@ export {
|
|
|
2524
1542
|
signalMcpReady,
|
|
2525
1543
|
createWebSocketServer
|
|
2526
1544
|
};
|
|
2527
|
-
//# sourceMappingURL=chunk-
|
|
1545
|
+
//# sourceMappingURL=chunk-7GWARYQC.js.map
|