funolio-agent 1.0.47 → 1.0.49
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/agent-config.d.ts +9 -1
- package/dist/agent-config.d.ts.map +1 -1
- package/dist/agent-config.js +4 -1
- package/dist/agent-config.js.map +1 -1
- package/dist/auth/auto-detect.d.ts +1 -0
- package/dist/auth/auto-detect.d.ts.map +1 -1
- package/dist/auth/auto-detect.js +16 -13
- package/dist/auth/auto-detect.js.map +1 -1
- package/dist/auto-organizer.d.ts.map +1 -1
- package/dist/auto-organizer.js +4 -3
- package/dist/auto-organizer.js.map +1 -1
- package/dist/backfill.d.ts.map +1 -1
- package/dist/backfill.js +3 -2
- package/dist/backfill.js.map +1 -1
- package/dist/bot-manager.d.ts +8 -23
- package/dist/bot-manager.d.ts.map +1 -1
- package/dist/bot-manager.js +61 -388
- package/dist/bot-manager.js.map +1 -1
- package/dist/clerk-model.d.ts +5 -1
- package/dist/clerk-model.d.ts.map +1 -1
- package/dist/clerk-model.js +40 -28
- package/dist/clerk-model.js.map +1 -1
- package/dist/cli-session-epoch.d.ts +10 -0
- package/dist/cli-session-epoch.d.ts.map +1 -0
- package/dist/cli-session-epoch.js +61 -0
- package/dist/cli-session-epoch.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +30 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pool.js +1 -1
- package/dist/commands/pool.js.map +1 -1
- package/dist/commands/setup.d.ts +37 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +154 -43
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +195 -164
- package/dist/commands/start.js.map +1 -1
- package/dist/config-cleanup.d.ts.map +1 -1
- package/dist/config-cleanup.js +2 -1
- package/dist/config-cleanup.js.map +1 -1
- package/dist/config.d.ts +6 -9
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -30
- package/dist/config.js.map +1 -1
- package/dist/context-window.d.ts +33 -5
- package/dist/context-window.d.ts.map +1 -1
- package/dist/context-window.js +121 -20
- package/dist/context-window.js.map +1 -1
- package/dist/eval/orchestrator-front-door-replay.js +1 -1
- package/dist/eval/orchestrator-front-door-replay.js.map +1 -1
- package/dist/eval/policy-detection-replay.js +1 -1
- package/dist/eval/policy-detection-replay.js.map +1 -1
- package/dist/integration-tokens.d.ts +1 -6
- package/dist/integration-tokens.d.ts.map +1 -1
- package/dist/integration-tokens.js +38 -40
- package/dist/integration-tokens.js.map +1 -1
- package/dist/local-cli-pty-manager.d.ts +50 -0
- package/dist/local-cli-pty-manager.d.ts.map +1 -0
- package/dist/local-cli-pty-manager.js +645 -0
- package/dist/local-cli-pty-manager.js.map +1 -0
- package/dist/local-data.d.ts +30 -0
- package/dist/local-data.d.ts.map +1 -1
- package/dist/local-data.js +56 -1
- package/dist/local-data.js.map +1 -1
- package/dist/local-db.d.ts.map +1 -1
- package/dist/local-db.js +54 -1
- package/dist/local-db.js.map +1 -1
- package/dist/local-funnel.d.ts.map +1 -1
- package/dist/local-funnel.js +3 -2
- package/dist/local-funnel.js.map +1 -1
- package/dist/local-memory-search.d.ts +1 -0
- package/dist/local-memory-search.d.ts.map +1 -1
- package/dist/local-memory-search.js +101 -18
- package/dist/local-memory-search.js.map +1 -1
- package/dist/local-server.d.ts +0 -16
- package/dist/local-server.d.ts.map +1 -1
- package/dist/local-server.js +339 -287
- package/dist/local-server.js.map +1 -1
- package/dist/mcp/bridge-server.d.ts.map +1 -1
- package/dist/mcp/bridge-server.js +2 -1
- package/dist/mcp/bridge-server.js.map +1 -1
- package/dist/mcp/local-memory-server.d.ts +5 -0
- package/dist/mcp/local-memory-server.d.ts.map +1 -1
- package/dist/mcp/local-memory-server.js +15 -2
- package/dist/mcp/local-memory-server.js.map +1 -1
- package/dist/mcp/manager.d.ts +3 -22
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +66 -388
- package/dist/mcp/manager.js.map +1 -1
- package/dist/memory-extraction.d.ts +2 -0
- package/dist/memory-extraction.d.ts.map +1 -1
- package/dist/memory-extraction.js +3 -1
- package/dist/memory-extraction.js.map +1 -1
- package/dist/message-loop.d.ts +10 -6
- package/dist/message-loop.d.ts.map +1 -1
- package/dist/message-loop.js +241 -540
- package/dist/message-loop.js.map +1 -1
- package/dist/mqtt-client.d.ts +2 -31
- package/dist/mqtt-client.d.ts.map +1 -1
- package/dist/mqtt-client.js +2 -2
- package/dist/mqtt-client.js.map +1 -1
- package/dist/oauth.d.ts +6 -0
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +91 -0
- package/dist/oauth.js.map +1 -1
- package/dist/orchestration/front-door-policy.d.ts +5 -2
- package/dist/orchestration/front-door-policy.d.ts.map +1 -1
- package/dist/orchestration/front-door-policy.js +25 -28
- package/dist/orchestration/front-door-policy.js.map +1 -1
- package/dist/orchestration/orchestrator-blocked-prompt.js +1 -1
- package/dist/orchestration/orchestrator-final-response-prompt.js +1 -1
- package/dist/orchestration/orchestrator-operating-prompt.d.ts +11 -0
- package/dist/orchestration/orchestrator-operating-prompt.d.ts.map +1 -1
- package/dist/orchestration/orchestrator-operating-prompt.js +67 -44
- package/dist/orchestration/orchestrator-operating-prompt.js.map +1 -1
- package/dist/orchestration/worker-operating-prompt.js +3 -3
- package/dist/orchestration/worker-operating-prompt.js.map +1 -1
- package/dist/orchestrator.d.ts +5 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +141 -81
- package/dist/orchestrator.js.map +1 -1
- package/dist/prompt-template.js +3 -3
- package/dist/prompt-template.js.map +1 -1
- package/dist/providers/claude-cli-prompt.d.ts.map +1 -1
- package/dist/providers/claude-cli-prompt.js +22 -6
- package/dist/providers/claude-cli-prompt.js.map +1 -1
- package/dist/providers/claude-cli.d.ts.map +1 -1
- package/dist/providers/claude-cli.js +20 -2
- package/dist/providers/claude-cli.js.map +1 -1
- package/dist/providers/codex-cli.d.ts.map +1 -1
- package/dist/providers/codex-cli.js +71 -16
- package/dist/providers/codex-cli.js.map +1 -1
- package/dist/providers/index.d.ts +11 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/runtime-context.d.ts +10 -0
- package/dist/runtime-context.d.ts.map +1 -0
- package/dist/runtime-context.js +30 -0
- package/dist/runtime-context.js.map +1 -0
- package/dist/subagent/queue.d.ts.map +1 -1
- package/dist/subagent/queue.js +1 -0
- package/dist/subagent/queue.js.map +1 -1
- package/dist/summarization-pipeline.d.ts +1 -0
- package/dist/summarization-pipeline.d.ts.map +1 -1
- package/dist/summarization-pipeline.js +94 -25
- package/dist/summarization-pipeline.js.map +1 -1
- package/dist/tool-permissions.d.ts +2 -0
- package/dist/tool-permissions.d.ts.map +1 -0
- package/dist/tool-permissions.js +25 -0
- package/dist/tool-permissions.js.map +1 -0
- package/dist/tools/index.d.ts +7 -8
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +70 -60
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/search-memory.d.ts.map +1 -1
- package/dist/tools/search-memory.js +9 -3
- package/dist/tools/search-memory.js.map +1 -1
- package/dist/tools/spawn-subagent.d.ts.map +1 -1
- package/dist/tools/spawn-subagent.js +1 -0
- package/dist/tools/spawn-subagent.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +1 -1
- package/dist/wizard-support.d.ts.map +1 -1
- package/dist/wizard-support.js +8 -6
- package/dist/wizard-support.js.map +1 -1
- package/dist/workflow-engine.d.ts +6 -2
- package/dist/workflow-engine.d.ts.map +1 -1
- package/dist/workflow-engine.js +254 -77
- package/dist/workflow-engine.js.map +1 -1
- package/package.json +2 -1
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* No Redis required — runs entirely in-process on the user's machine.
|
|
12
12
|
*/
|
|
13
13
|
import { EventEmitter } from 'events';
|
|
14
|
+
import { AgentRuntimeMode } from './runtime-context';
|
|
14
15
|
export type WorkflowStepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
|
|
15
16
|
export interface WorkflowStep {
|
|
16
17
|
id: string;
|
|
@@ -99,11 +100,14 @@ interface WorkflowRunOptions {
|
|
|
99
100
|
workerMode?: boolean;
|
|
100
101
|
stepDescription?: string;
|
|
101
102
|
disallowCliRuntime?: boolean;
|
|
103
|
+
runtimeMode?: AgentRuntimeMode;
|
|
102
104
|
}
|
|
103
105
|
export declare class WorkflowEngine extends EventEmitter {
|
|
104
106
|
private projectDir;
|
|
107
|
+
private runtimeMode;
|
|
105
108
|
private activeWorkflows;
|
|
106
|
-
constructor(projectDir: string);
|
|
109
|
+
constructor(projectDir: string, runtimeMode?: AgentRuntimeMode);
|
|
110
|
+
getRuntimeMode(): AgentRuntimeMode;
|
|
107
111
|
/**
|
|
108
112
|
* Execute a workflow: decompose a prompt into steps, route, and execute.
|
|
109
113
|
* For simple prompts (single step), runs directly without decomposition.
|
|
@@ -173,6 +177,6 @@ export declare class WorkflowEngine extends EventEmitter {
|
|
|
173
177
|
/** Cancel an active workflow */
|
|
174
178
|
cancel(workflowId: string): boolean;
|
|
175
179
|
}
|
|
176
|
-
export declare function getWorkflowEngine(projectDir?: string): WorkflowEngine;
|
|
180
|
+
export declare function getWorkflowEngine(projectDir?: string, runtimeMode?: AgentRuntimeMode): WorkflowEngine;
|
|
177
181
|
export {};
|
|
178
182
|
//# sourceMappingURL=workflow-engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-engine.d.ts","sourceRoot":"","sources":["../src/workflow-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"workflow-engine.d.ts","sourceRoot":"","sources":["../src/workflow-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/workflow-engine.js
CHANGED
|
@@ -62,18 +62,47 @@ const safeguards_1 = require("./orchestration/safeguards");
|
|
|
62
62
|
const data = __importStar(require("./local-data"));
|
|
63
63
|
const orchestrator_profile_1 = require("./orchestrator-profile");
|
|
64
64
|
const subscription_runtime_1 = require("./auth/subscription-runtime");
|
|
65
|
+
const runtime_context_1 = require("./runtime-context");
|
|
66
|
+
const local_cli_pty_manager_1 = require("./local-cli-pty-manager");
|
|
67
|
+
const cli_session_epoch_1 = require("./cli-session-epoch");
|
|
65
68
|
// ─── Workflow Engine ─────────────────────────────────────────────
|
|
66
69
|
const MAX_STEP_ATTEMPTS = safeguards_1.SAFEGUARDS.MAX_AGENT_ATTEMPTS;
|
|
67
70
|
const MAX_STEPS = safeguards_1.SAFEGUARDS.MAX_WORKFLOW_STEPS;
|
|
68
71
|
function isInteractiveAuthFailure(text) {
|
|
69
72
|
return /\b(not logged in|please run \/login|unauthorized|invalid api key|authentication required)\b/i.test(text);
|
|
70
73
|
}
|
|
74
|
+
const LOCAL_WORKFLOW_RUNTIME_RETRY_LIMIT = 2;
|
|
75
|
+
function shouldRetrySelectedWorkflowRuntime(err) {
|
|
76
|
+
const text = String(err?.message || err || '').toLowerCase();
|
|
77
|
+
if (!text)
|
|
78
|
+
return false;
|
|
79
|
+
if (/\b(no api key|configure one in settings|not available on this machine|not installed|please run \/login|not logged in|invalid api key)\b/i.test(text)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return /\b(429|rate limit|timeout|timed out|temporar|temporarily|econnreset|etimedout|enotfound|econnrefused|socket hang up|network|try again|overloaded|busy)\b/i.test(text);
|
|
83
|
+
}
|
|
84
|
+
async function pauseWorkflowRuntimeRetry(attempt) {
|
|
85
|
+
const delayMs = attempt <= 1 ? 750 : 1500;
|
|
86
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
87
|
+
}
|
|
88
|
+
function buildWorkflowPtyConversationKey(conversationId, step, workflowContext) {
|
|
89
|
+
if (conversationId)
|
|
90
|
+
return conversationId;
|
|
91
|
+
if (workflowContext?.workflowId)
|
|
92
|
+
return `workflow:${workflowContext.workflowId}`;
|
|
93
|
+
return `adhoc:${step.agentId}:${step.id}`;
|
|
94
|
+
}
|
|
71
95
|
class WorkflowEngine extends events_1.EventEmitter {
|
|
72
96
|
projectDir;
|
|
97
|
+
runtimeMode;
|
|
73
98
|
activeWorkflows = new Map();
|
|
74
|
-
constructor(projectDir) {
|
|
99
|
+
constructor(projectDir, runtimeMode) {
|
|
75
100
|
super();
|
|
76
101
|
this.projectDir = projectDir;
|
|
102
|
+
this.runtimeMode = (0, runtime_context_1.normalizeRuntimeMode)(runtimeMode || (0, runtime_context_1.getDefaultRuntimeMode)());
|
|
103
|
+
}
|
|
104
|
+
getRuntimeMode() {
|
|
105
|
+
return this.runtimeMode;
|
|
77
106
|
}
|
|
78
107
|
/**
|
|
79
108
|
* Execute a workflow: decompose a prompt into steps, route, and execute.
|
|
@@ -82,7 +111,8 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
82
111
|
async execute(prompt, conversationId, agentId, opts) {
|
|
83
112
|
const workflowId = crypto.randomUUID();
|
|
84
113
|
const startedAt = Date.now();
|
|
85
|
-
const
|
|
114
|
+
const effectiveRuntimeMode = (0, runtime_context_1.normalizeRuntimeMode)(opts?.runtimeMode || this.runtimeMode);
|
|
115
|
+
const clerk = (0, clerk_model_1.getClerk)({ runtimeMode: effectiveRuntimeMode });
|
|
86
116
|
const allProfiles = data.listAgentProfiles();
|
|
87
117
|
// Filter out orchestrator profiles by default, but allow explicitly assigned specialists
|
|
88
118
|
// and the selected agent back into the planning pool when needed.
|
|
@@ -283,7 +313,7 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
283
313
|
`TODO ITEM #${task.id}: ${task.title}`,
|
|
284
314
|
task.details ? `Task details:\n${task.details}` : '',
|
|
285
315
|
'Work only on this TODO item. Do not mark any other item complete.',
|
|
286
|
-
'When your stage is complete, return the structured footer
|
|
316
|
+
'When your stage is complete, return the structured footer required below so routing can continue automatically.',
|
|
287
317
|
].filter(Boolean).join('\n\n');
|
|
288
318
|
const steps = template.steps
|
|
289
319
|
.sort((a, b) => a.order_index - b.order_index)
|
|
@@ -635,7 +665,7 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
635
665
|
? 'Include REASON only when STATUS is FAIL.'
|
|
636
666
|
: 'Include REASON only when STATUS is BLOCKED.';
|
|
637
667
|
return [
|
|
638
|
-
`You are ${profile?.name || 'a
|
|
668
|
+
`You are ${profile?.name || 'a workflow worker'}.`,
|
|
639
669
|
'Complete only the assigned workflow step.',
|
|
640
670
|
roleLine,
|
|
641
671
|
'Use available tools when the task requires creating, changing, or verifying files.',
|
|
@@ -656,8 +686,8 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
656
686
|
? 'Your role is QA. Verify the delivered work, then complete the TODO through the worker tool or create the next fix handoff.'
|
|
657
687
|
: 'Your role is implementer. Do the assigned work, then complete the TODO through the worker tool.';
|
|
658
688
|
return [
|
|
659
|
-
`You are ${profile?.name || 'a
|
|
660
|
-
'You are executing one orchestrated TODO task
|
|
689
|
+
`You are ${profile?.name || 'a workflow worker'}.`,
|
|
690
|
+
'You are executing one orchestrated TODO task.',
|
|
661
691
|
roleLine,
|
|
662
692
|
'Follow the assignment in the user message exactly.',
|
|
663
693
|
'Use available tools when needed.',
|
|
@@ -833,6 +863,7 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
833
863
|
* Handles checkpoint loop-back and footer-driven retry/failure logic.
|
|
834
864
|
*/
|
|
835
865
|
async executeSteps(workflowId, steps, conversationId, opts) {
|
|
866
|
+
const effectiveRuntimeMode = (0, runtime_context_1.normalizeRuntimeMode)(opts?.runtimeMode || this.runtimeMode);
|
|
836
867
|
const completed = new Set();
|
|
837
868
|
const failed = new Set();
|
|
838
869
|
const allowMissingFooterForDirectStep = !opts?.isOrchestrated && !!opts?.disableDecomposition && steps.length === 1;
|
|
@@ -1115,7 +1146,7 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1115
1146
|
&& !hasFutureQaStep
|
|
1116
1147
|
&& !opts?.isOrchestrated;
|
|
1117
1148
|
if (shouldRunClerkVerification) {
|
|
1118
|
-
const verifyClerk = (0, clerk_model_1.getClerk)();
|
|
1149
|
+
const verifyClerk = (0, clerk_model_1.getClerk)({ runtimeMode: effectiveRuntimeMode });
|
|
1119
1150
|
if (verifyClerk) {
|
|
1120
1151
|
try {
|
|
1121
1152
|
const verification = await verifyClerk.verifyStepOutput(step.description, step.expectedOutput, result);
|
|
@@ -1286,7 +1317,7 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1286
1317
|
}
|
|
1287
1318
|
else if (step.attempts < step.maxAttempts) {
|
|
1288
1319
|
// Nudge on retry — generate adjusted prompt
|
|
1289
|
-
const nudgeClerk = (0, clerk_model_1.getClerk)();
|
|
1320
|
+
const nudgeClerk = (0, clerk_model_1.getClerk)({ runtimeMode: effectiveRuntimeMode });
|
|
1290
1321
|
if (nudgeClerk) {
|
|
1291
1322
|
try {
|
|
1292
1323
|
const nudge = await nudgeClerk.generateNudge(step.description, step.prompt, err.message);
|
|
@@ -1327,12 +1358,14 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1327
1358
|
* Execute a single workflow step: call LLM with tools, agentic loop.
|
|
1328
1359
|
*/
|
|
1329
1360
|
async executeStep(step, prompt, conversationId, opts, apiKey, workflowContext) {
|
|
1361
|
+
const effectiveRuntimeMode = (0, runtime_context_1.normalizeRuntimeMode)(opts?.runtimeMode || this.runtimeMode);
|
|
1330
1362
|
const profile = data.getAgentProfile(step.agentId);
|
|
1331
1363
|
const runtime = await this.resolveStepRuntime(step, profile, apiKey, opts);
|
|
1332
1364
|
let activeRuntime = runtime;
|
|
1333
1365
|
let llm = (0, index_1.createProvider)(activeRuntime.providerName, {
|
|
1334
1366
|
apiKey: activeRuntime.apiKey,
|
|
1335
1367
|
model: activeRuntime.model,
|
|
1368
|
+
runtimeMode: effectiveRuntimeMode,
|
|
1336
1369
|
...(activeRuntime.requestShape ? { requestShape: activeRuntime.requestShape } : {}),
|
|
1337
1370
|
...(activeRuntime.baseUrl ? { baseUrl: activeRuntime.baseUrl } : {}),
|
|
1338
1371
|
...(activeRuntime.apiQuery ? { apiQuery: activeRuntime.apiQuery } : {}),
|
|
@@ -1344,7 +1377,7 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1344
1377
|
...(opts?.isOrchestrated ? { toolProjectId: opts?.projectId ?? null } : {}),
|
|
1345
1378
|
...(opts?.isOrchestrated ? { currentTodoTaskId: opts?.taskId } : {}),
|
|
1346
1379
|
});
|
|
1347
|
-
const toolDefs = (0, index_2.getAllToolDefinitions)();
|
|
1380
|
+
const toolDefs = (0, index_2.getAllToolDefinitions)(effectiveRuntimeMode);
|
|
1348
1381
|
const workspacePath = opts?.workspacePath?.trim();
|
|
1349
1382
|
const effectiveProjectDir = workspacePath || this.projectDir;
|
|
1350
1383
|
const unrestrictedCliProvider = index_1.CLI_PROVIDERS.has(step.provider);
|
|
@@ -1353,12 +1386,13 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1353
1386
|
currentTodoTaskId: opts?.taskId,
|
|
1354
1387
|
actorType: 'llm',
|
|
1355
1388
|
actorId: step.agentName || step.agentId,
|
|
1389
|
+
runtimeMode: effectiveRuntimeMode,
|
|
1356
1390
|
restrictFileAccessToProject: unrestrictedCliProvider ? false : undefined,
|
|
1357
1391
|
});
|
|
1358
1392
|
const isWorkflowWorker = opts?.workerMode !== false;
|
|
1359
1393
|
let systemPrompt = profile?.soul_md
|
|
1360
|
-
|| 'You are
|
|
1361
|
-
const clerk = (0, clerk_model_1.getClerk)();
|
|
1394
|
+
|| 'You are an AI assistant working on a specific task step.';
|
|
1395
|
+
const clerk = (0, clerk_model_1.getClerk)({ runtimeMode: effectiveRuntimeMode });
|
|
1362
1396
|
if (opts?.systemPromptOverride?.trim()) {
|
|
1363
1397
|
systemPrompt = opts.systemPromptOverride.trim();
|
|
1364
1398
|
}
|
|
@@ -1393,11 +1427,23 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1393
1427
|
const messages = [{ role: 'user', content: effectivePrompt }];
|
|
1394
1428
|
const promptChars = effectivePrompt.length;
|
|
1395
1429
|
const systemChars = systemPrompt.length;
|
|
1430
|
+
const isLocalCliSession = effectiveRuntimeMode === 'local_desktop'
|
|
1431
|
+
&& (activeRuntime.providerName === 'claude-cli' || activeRuntime.providerName === 'codex-cli');
|
|
1432
|
+
const hasPersistentConversation = isLocalCliSession && !!conversationId;
|
|
1433
|
+
const cliSessionEpochPlan = hasPersistentConversation
|
|
1434
|
+
? (0, cli_session_epoch_1.selectCliSessionEpoch)(conversationId, step.agentId, activeRuntime.providerName)
|
|
1435
|
+
: { existing: undefined, resumeSessionId: null, resetReason: null };
|
|
1436
|
+
let activeCliSessionId = cliSessionEpochPlan.resumeSessionId;
|
|
1437
|
+
const cliEpochStartedAt = cliSessionEpochPlan.resumeSessionId
|
|
1438
|
+
? (cliSessionEpochPlan.existing?.epoch_started_at || (0, cli_session_epoch_1.localTimestamp)())
|
|
1439
|
+
: (0, cli_session_epoch_1.localTimestamp)();
|
|
1440
|
+
const ptyConversationKey = buildWorkflowPtyConversationKey(conversationId, step, workflowContext);
|
|
1396
1441
|
console.info(`[workflow-engine] step runtime: agent=${step.agentName} provider=${activeRuntime.providerName} model=${activeRuntime.model} runtime=${activeRuntime.runtimeLabel || 'unknown'} promptChars=${promptChars} systemChars=${systemChars} tools=${opts?.disableTools ? 0 : toolDefs.length}`);
|
|
1397
1442
|
// Agentic loop
|
|
1398
1443
|
let iteration = 0;
|
|
1399
1444
|
const MAX_ITERATIONS = safeguards_1.SAFEGUARDS.MAX_WORKFLOW_ITERATIONS;
|
|
1400
1445
|
let incompleteExecutionRecoveries = 0;
|
|
1446
|
+
let selectedRuntimeRetryCount = 0;
|
|
1401
1447
|
while (iteration < MAX_ITERATIONS) {
|
|
1402
1448
|
if (opts?.isOrchestrated && this.orchestratedTodoHandled(opts.taskId)) {
|
|
1403
1449
|
return this.buildOrchestratedTodoHandledResult(opts.taskId);
|
|
@@ -1418,70 +1464,155 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1418
1464
|
: 'auto';
|
|
1419
1465
|
let response;
|
|
1420
1466
|
try {
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1467
|
+
if (isLocalCliSession) {
|
|
1468
|
+
if (cliSessionEpochPlan.resetReason && iteration === 1 && opts?.onWorkerChunk) {
|
|
1469
|
+
const resetDetail = cliSessionEpochPlan.resetReason === 'turn_limit'
|
|
1470
|
+
? 'Resetting CLI session after reaching the turn limit.'
|
|
1471
|
+
: cliSessionEpochPlan.resetReason === 'token_limit'
|
|
1472
|
+
? 'Resetting CLI session after reaching the context budget.'
|
|
1473
|
+
: 'Resetting CLI session because the runtime changed.';
|
|
1474
|
+
opts.onWorkerChunk({
|
|
1475
|
+
type: opts?.isOrchestrated ? 'worker_chunk' : 'chunk',
|
|
1476
|
+
stepId: step.id,
|
|
1477
|
+
agentName: step.agentName,
|
|
1478
|
+
description: step.description,
|
|
1479
|
+
stepIndex: workflowContext?.stepIndex ?? 0,
|
|
1480
|
+
totalSteps: workflowContext?.totalSteps ?? 1,
|
|
1481
|
+
text: resetDetail,
|
|
1482
|
+
});
|
|
1483
|
+
}
|
|
1484
|
+
const ptyManager = (0, local_cli_pty_manager_1.getLocalCliPtySessionManager)();
|
|
1485
|
+
let ptyAttempt = 0;
|
|
1486
|
+
while (true) {
|
|
1487
|
+
ptyAttempt++;
|
|
1488
|
+
try {
|
|
1489
|
+
const ptyResult = await ptyManager.runTurn({
|
|
1490
|
+
conversationId: ptyConversationKey,
|
|
1491
|
+
botId: step.agentId,
|
|
1492
|
+
provider: activeRuntime.providerName,
|
|
1493
|
+
cwd: effectiveProjectDir,
|
|
1494
|
+
systemPrompt,
|
|
1495
|
+
messages,
|
|
1496
|
+
forceFreshSession: !hasPersistentConversation || (iteration === 1 && !cliSessionEpochPlan.resumeSessionId),
|
|
1497
|
+
onDetail: async (detail) => {
|
|
1498
|
+
streamedContent += streamedContent ? `\n${detail}` : detail;
|
|
1499
|
+
if (opts?.onWorkerChunk) {
|
|
1500
|
+
opts.onWorkerChunk({
|
|
1501
|
+
type: opts?.isOrchestrated ? 'worker_chunk' : 'chunk',
|
|
1502
|
+
stepId: step.id,
|
|
1503
|
+
agentName: step.agentName,
|
|
1504
|
+
description: step.description,
|
|
1505
|
+
stepIndex: workflowContext?.stepIndex ?? 0,
|
|
1506
|
+
totalSteps: workflowContext?.totalSteps ?? 1,
|
|
1507
|
+
text: detail,
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
const now = Date.now();
|
|
1511
|
+
if (now - lastChunkProgressAt < 8000)
|
|
1512
|
+
return;
|
|
1513
|
+
lastChunkProgressAt = now;
|
|
1514
|
+
const activeSteps = workflowContext?.workflowId
|
|
1515
|
+
? this.getActiveWorkflows().find((w) => w.id === workflowContext.workflowId)?.steps || [step]
|
|
1516
|
+
: [step];
|
|
1517
|
+
this.emitProgress(workflowContext?.workflowId || 'workflow', step, activeSteps, 'step-progress', opts?.onProgress, `${step.agentName} is still working on ${step.description}`);
|
|
1518
|
+
},
|
|
1519
|
+
});
|
|
1520
|
+
if (ptyResult.sessionId) {
|
|
1521
|
+
activeCliSessionId = ptyResult.sessionId;
|
|
1444
1522
|
}
|
|
1523
|
+
response = {
|
|
1524
|
+
content: ptyResult.content || '',
|
|
1525
|
+
usage: ptyResult.usage,
|
|
1526
|
+
};
|
|
1527
|
+
break;
|
|
1445
1528
|
}
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1529
|
+
catch (ptyErr) {
|
|
1530
|
+
if (ptyAttempt >= LOCAL_WORKFLOW_RUNTIME_RETRY_LIMIT
|
|
1531
|
+
|| !shouldRetrySelectedWorkflowRuntime(ptyErr)) {
|
|
1532
|
+
throw ptyErr;
|
|
1533
|
+
}
|
|
1534
|
+
console.warn(`[workflow-engine] ${step.agentName} selected runtime failed, retrying the same connection (${ptyAttempt + 1}/${LOCAL_WORKFLOW_RUNTIME_RETRY_LIMIT})`);
|
|
1535
|
+
await pauseWorkflowRuntimeRetry(ptyAttempt);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
else {
|
|
1540
|
+
response = await llm.chat({
|
|
1541
|
+
messages,
|
|
1542
|
+
system: systemPrompt,
|
|
1543
|
+
stream: true,
|
|
1544
|
+
toolChoice,
|
|
1545
|
+
onChunk: async (chunk) => {
|
|
1546
|
+
streamedContent += chunk;
|
|
1547
|
+
// Forward chunks to onWorkerChunk with 150ms/80-char buffer
|
|
1548
|
+
if (opts?.onWorkerChunk) {
|
|
1549
|
+
chunkBuffer += chunk;
|
|
1550
|
+
const now2 = Date.now();
|
|
1551
|
+
if (chunkBuffer.length >= 80 || now2 - lastChunkForwardAt >= 150) {
|
|
1552
|
+
opts.onWorkerChunk({
|
|
1553
|
+
type: opts?.isOrchestrated ? 'worker_chunk' : 'chunk',
|
|
1554
|
+
stepId: step.id,
|
|
1555
|
+
agentName: step.agentName,
|
|
1556
|
+
description: step.description,
|
|
1557
|
+
stepIndex: workflowContext?.stepIndex ?? 0,
|
|
1558
|
+
totalSteps: workflowContext?.totalSteps ?? 1,
|
|
1559
|
+
text: chunkBuffer,
|
|
1560
|
+
});
|
|
1561
|
+
chunkBuffer = '';
|
|
1562
|
+
lastChunkForwardAt = now2;
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
// Existing 8-second heartbeat for backward compat
|
|
1566
|
+
const now = Date.now();
|
|
1567
|
+
if (now - lastChunkProgressAt < 8000)
|
|
1568
|
+
return;
|
|
1569
|
+
lastChunkProgressAt = now;
|
|
1570
|
+
const compact = chunk.replace(/\s+/g, ' ').trim();
|
|
1571
|
+
if (!compact && emittedChunkHeartbeat)
|
|
1572
|
+
return;
|
|
1573
|
+
emittedChunkHeartbeat = true;
|
|
1574
|
+
const preview = `${step.agentName} is still working on ${step.description}`;
|
|
1575
|
+
const activeSteps = workflowContext?.workflowId
|
|
1576
|
+
? this.getActiveWorkflows().find((w) => w.id === workflowContext.workflowId)?.steps || [step]
|
|
1577
|
+
: [step];
|
|
1578
|
+
this.emitProgress(workflowContext?.workflowId || 'workflow', step, activeSteps, 'step-progress', opts?.onProgress, preview);
|
|
1579
|
+
},
|
|
1580
|
+
tools: opts?.disableTools ? undefined : toolDefs,
|
|
1581
|
+
cwd: effectiveProjectDir,
|
|
1474
1582
|
});
|
|
1475
|
-
|
|
1583
|
+
// Flush remaining chunk buffer
|
|
1584
|
+
if (opts?.onWorkerChunk && chunkBuffer) {
|
|
1585
|
+
opts.onWorkerChunk({
|
|
1586
|
+
type: opts?.isOrchestrated ? 'worker_chunk' : 'chunk',
|
|
1587
|
+
stepId: step.id,
|
|
1588
|
+
agentName: step.agentName,
|
|
1589
|
+
description: step.description,
|
|
1590
|
+
stepIndex: workflowContext?.stepIndex ?? 0,
|
|
1591
|
+
totalSteps: workflowContext?.totalSteps ?? 1,
|
|
1592
|
+
text: chunkBuffer,
|
|
1593
|
+
});
|
|
1594
|
+
chunkBuffer = '';
|
|
1595
|
+
}
|
|
1476
1596
|
}
|
|
1597
|
+
selectedRuntimeRetryCount = 0;
|
|
1477
1598
|
}
|
|
1478
1599
|
catch (err) {
|
|
1479
1600
|
console.warn(`[workflow-engine] step error: agent=${step.agentName} provider=${activeRuntime.providerName} model=${activeRuntime.model} runtime=${activeRuntime.runtimeLabel || 'unknown'} iteration=${iteration} message=${err?.message || err}`);
|
|
1480
|
-
if (
|
|
1601
|
+
if (effectiveRuntimeMode === 'local_desktop'
|
|
1602
|
+
&& selectedRuntimeRetryCount < (LOCAL_WORKFLOW_RUNTIME_RETRY_LIMIT - 1)
|
|
1603
|
+
&& shouldRetrySelectedWorkflowRuntime(err)) {
|
|
1604
|
+
selectedRuntimeRetryCount++;
|
|
1605
|
+
console.warn(`[workflow-engine] ${step.agentName} selected runtime failed, retrying the same connection (${selectedRuntimeRetryCount + 1}/${LOCAL_WORKFLOW_RUNTIME_RETRY_LIMIT})`);
|
|
1606
|
+
await pauseWorkflowRuntimeRetry(selectedRuntimeRetryCount);
|
|
1607
|
+
iteration--;
|
|
1608
|
+
continue;
|
|
1609
|
+
}
|
|
1610
|
+
if (effectiveRuntimeMode !== 'local_desktop' && activeRuntime.fallback) {
|
|
1481
1611
|
activeRuntime = activeRuntime.fallback;
|
|
1482
1612
|
llm = (0, index_1.createProvider)(activeRuntime.providerName, {
|
|
1483
1613
|
apiKey: activeRuntime.apiKey,
|
|
1484
1614
|
model: activeRuntime.model,
|
|
1615
|
+
runtimeMode: effectiveRuntimeMode,
|
|
1485
1616
|
...(activeRuntime.requestShape ? { requestShape: activeRuntime.requestShape } : {}),
|
|
1486
1617
|
...(activeRuntime.baseUrl ? { baseUrl: activeRuntime.baseUrl } : {}),
|
|
1487
1618
|
...(activeRuntime.apiQuery ? { apiQuery: activeRuntime.apiQuery } : {}),
|
|
@@ -1499,6 +1630,23 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1499
1630
|
}
|
|
1500
1631
|
throw err;
|
|
1501
1632
|
}
|
|
1633
|
+
if (hasPersistentConversation && activeCliSessionId && !response.toolCalls?.length) {
|
|
1634
|
+
const nextEpochTurnCount = cliSessionEpochPlan.resumeSessionId
|
|
1635
|
+
? ((cliSessionEpochPlan.existing?.epoch_turn_count || 0) + 1)
|
|
1636
|
+
: 1;
|
|
1637
|
+
data.upsertCliSessionEpoch({
|
|
1638
|
+
conversationId: conversationId,
|
|
1639
|
+
botId: step.agentId,
|
|
1640
|
+
provider: activeRuntime.providerName,
|
|
1641
|
+
sessionId: activeCliSessionId,
|
|
1642
|
+
epochTurnCount: nextEpochTurnCount,
|
|
1643
|
+
lastInputTokens: response.usage?.inputTokens ?? null,
|
|
1644
|
+
lastOutputTokens: response.usage?.outputTokens ?? null,
|
|
1645
|
+
resetReason: cliSessionEpochPlan.resetReason,
|
|
1646
|
+
epochStartedAt: cliEpochStartedAt,
|
|
1647
|
+
lastUsedAt: (0, cli_session_epoch_1.localTimestamp)(),
|
|
1648
|
+
});
|
|
1649
|
+
}
|
|
1502
1650
|
if (response.toolCalls && response.toolCalls.length > 0) {
|
|
1503
1651
|
messages.push({
|
|
1504
1652
|
role: 'assistant',
|
|
@@ -1610,12 +1758,15 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1610
1758
|
this.emitProgress(workflowContext?.workflowId || 'workflow', step, activeSteps, 'step-progress', opts?.onProgress, `${step.agentName} described intended work instead of executing it. Retrying with an explicit tool-use correction.`);
|
|
1611
1759
|
continue;
|
|
1612
1760
|
}
|
|
1613
|
-
if (
|
|
1761
|
+
if (effectiveRuntimeMode !== 'local_desktop'
|
|
1762
|
+
&& activeRuntime.fallback
|
|
1763
|
+
&& activeRuntime.providerName !== activeRuntime.fallback.providerName) {
|
|
1614
1764
|
console.warn(`[workflow-engine] forcing runtime fallback after repeated incomplete execution: agent=${step.agentName} from=${activeRuntime.providerName} to=${activeRuntime.fallback.providerName}`);
|
|
1615
1765
|
activeRuntime = activeRuntime.fallback;
|
|
1616
1766
|
llm = (0, index_1.createProvider)(activeRuntime.providerName, {
|
|
1617
1767
|
apiKey: activeRuntime.apiKey,
|
|
1618
1768
|
model: activeRuntime.model,
|
|
1769
|
+
runtimeMode: effectiveRuntimeMode,
|
|
1619
1770
|
...(activeRuntime.requestShape ? { requestShape: activeRuntime.requestShape } : {}),
|
|
1620
1771
|
...(activeRuntime.baseUrl ? { baseUrl: activeRuntime.baseUrl } : {}),
|
|
1621
1772
|
...(activeRuntime.apiQuery ? { apiQuery: activeRuntime.apiQuery } : {}),
|
|
@@ -1747,11 +1898,12 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1747
1898
|
}
|
|
1748
1899
|
}
|
|
1749
1900
|
async resolveStepRuntime(step, profile, apiKey, opts) {
|
|
1901
|
+
const effectiveRuntimeMode = (0, runtime_context_1.normalizeRuntimeMode)(opts?.runtimeMode || this.runtimeMode);
|
|
1750
1902
|
if (step.provider === 'claude-cli') {
|
|
1751
|
-
return this.resolveClaudeWorkflowRuntime(step, profile, opts?.disallowCliRuntime === true);
|
|
1903
|
+
return this.resolveClaudeWorkflowRuntime(step, profile, opts?.disallowCliRuntime === true && effectiveRuntimeMode !== 'local_desktop', effectiveRuntimeMode);
|
|
1752
1904
|
}
|
|
1753
1905
|
if (step.provider === 'codex-cli') {
|
|
1754
|
-
return this.resolveCodexWorkflowRuntime(step, profile, opts?.disallowCliRuntime === true);
|
|
1906
|
+
return this.resolveCodexWorkflowRuntime(step, profile, opts?.disallowCliRuntime === true && effectiveRuntimeMode !== 'local_desktop', effectiveRuntimeMode);
|
|
1755
1907
|
}
|
|
1756
1908
|
const profileConnection = profile?.provider_connection_id
|
|
1757
1909
|
? data.getProviderConnection(profile.provider_connection_id)
|
|
@@ -1760,7 +1912,7 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1760
1912
|
|| profileConnection?.api_key_enc
|
|
1761
1913
|
|| apiKey
|
|
1762
1914
|
|| this.resolveApiKey(step.provider);
|
|
1763
|
-
if (!resolvedKey && step.provider === 'openai') {
|
|
1915
|
+
if (effectiveRuntimeMode !== 'local_desktop' && !resolvedKey && step.provider === 'openai') {
|
|
1764
1916
|
const preferredModel = (0, subscription_runtime_1.resolveSubscriptionApiModel)(step.model || profile?.model, data.findProviderConnection('openai')?.default_model || undefined) || (step.model || profile?.model || 'default').trim() || 'default';
|
|
1765
1917
|
const subscriptionRuntime = await (0, subscription_runtime_1.resolveCodexSubscriptionRuntime)({
|
|
1766
1918
|
preferredModel,
|
|
@@ -1786,7 +1938,15 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1786
1938
|
runtimeLabel: 'API Key',
|
|
1787
1939
|
};
|
|
1788
1940
|
}
|
|
1789
|
-
async resolveClaudeWorkflowRuntime(step, profile, disallowCliRuntime = false) {
|
|
1941
|
+
async resolveClaudeWorkflowRuntime(step, profile, disallowCliRuntime = false, runtimeMode = this.runtimeMode) {
|
|
1942
|
+
if (runtimeMode === 'local_desktop') {
|
|
1943
|
+
return {
|
|
1944
|
+
providerName: 'claude-cli',
|
|
1945
|
+
apiKey: 'cli-auth',
|
|
1946
|
+
model: (step.model || profile?.model || 'default').trim() || 'default',
|
|
1947
|
+
runtimeLabel: 'Subscription CLI',
|
|
1948
|
+
};
|
|
1949
|
+
}
|
|
1790
1950
|
const preferredModel = (0, subscription_runtime_1.resolveSubscriptionApiModel)(step.model || profile?.model, data.findProviderConnection('anthropic')?.default_model || data.findProviderConnection('claude-cli')?.default_model || undefined) || (step.model || profile?.model || 'default').trim() || 'default';
|
|
1791
1951
|
const apiKeyFallback = data.findProviderConnection('anthropic')?.api_key_enc || process.env.ANTHROPIC_API_KEY;
|
|
1792
1952
|
const apiFallbackConfig = apiKeyFallback
|
|
@@ -1826,7 +1986,15 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1826
1986
|
};
|
|
1827
1987
|
return cliFallbackConfig;
|
|
1828
1988
|
}
|
|
1829
|
-
async resolveCodexWorkflowRuntime(step, profile, disallowCliRuntime = false) {
|
|
1989
|
+
async resolveCodexWorkflowRuntime(step, profile, disallowCliRuntime = false, runtimeMode = this.runtimeMode) {
|
|
1990
|
+
if (runtimeMode === 'local_desktop') {
|
|
1991
|
+
return {
|
|
1992
|
+
providerName: 'codex-cli',
|
|
1993
|
+
apiKey: 'cli-auth',
|
|
1994
|
+
model: (step.model || profile?.model || 'default').trim() || 'default',
|
|
1995
|
+
runtimeLabel: 'Subscription CLI',
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1830
1998
|
const preferredModel = (0, subscription_runtime_1.resolveSubscriptionApiModel)(step.model || profile?.model, data.findProviderConnection('openai')?.default_model || data.findProviderConnection('codex-cli')?.default_model || undefined)
|
|
1831
1999
|
|| (step.model || profile?.model || 'default').trim()
|
|
1832
2000
|
|| 'default';
|
|
@@ -1979,7 +2147,7 @@ class WorkflowEngine extends events_1.EventEmitter {
|
|
|
1979
2147
|
async replanRemainingSteps(steps, failedStep, agents, defaultProfile) {
|
|
1980
2148
|
if (steps.length <= 1)
|
|
1981
2149
|
return null;
|
|
1982
|
-
const clerk = (0, clerk_model_1.getClerk)();
|
|
2150
|
+
const clerk = (0, clerk_model_1.getClerk)({ runtimeMode: this.runtimeMode });
|
|
1983
2151
|
if (!clerk)
|
|
1984
2152
|
return null;
|
|
1985
2153
|
const completedSummary = steps
|
|
@@ -2070,15 +2238,24 @@ Rules:
|
|
|
2070
2238
|
}
|
|
2071
2239
|
exports.WorkflowEngine = WorkflowEngine;
|
|
2072
2240
|
// ─── Singleton ───────────────────────────────────────────────────
|
|
2073
|
-
|
|
2074
|
-
function getWorkflowEngine(projectDir) {
|
|
2075
|
-
|
|
2076
|
-
|
|
2241
|
+
const _workflowEngines = new Map();
|
|
2242
|
+
function getWorkflowEngine(projectDir, runtimeMode) {
|
|
2243
|
+
const effectiveRuntimeMode = (0, runtime_context_1.normalizeRuntimeMode)(runtimeMode || (0, runtime_context_1.getDefaultRuntimeMode)());
|
|
2244
|
+
const existing = _workflowEngines.get(effectiveRuntimeMode);
|
|
2245
|
+
if (existing) {
|
|
2246
|
+
if (!projectDir || existing.projectDir === projectDir) {
|
|
2247
|
+
return existing;
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
if (projectDir) {
|
|
2251
|
+
const engine = new WorkflowEngine(projectDir, effectiveRuntimeMode);
|
|
2252
|
+
_workflowEngines.set(effectiveRuntimeMode, engine);
|
|
2253
|
+
return engine;
|
|
2077
2254
|
}
|
|
2078
|
-
if (!
|
|
2255
|
+
if (!_workflowEngines.size) {
|
|
2079
2256
|
throw new Error('Workflow engine not initialized. Call getWorkflowEngine(projectDir) first.');
|
|
2080
2257
|
}
|
|
2081
|
-
|
|
2258
|
+
throw new Error(`Workflow engine not initialized for runtime ${effectiveRuntimeMode}. Call getWorkflowEngine(projectDir, runtimeMode) first.`);
|
|
2082
2259
|
}
|
|
2083
2260
|
// ─── JSON Parsing Helper ─────────────────────────────────────────
|
|
2084
2261
|
function parseJsonResponse(text) {
|