funolio-agent 0.17.9 → 1.0.3

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.
Files changed (147) hide show
  1. package/dist/approval.d.ts +7 -6
  2. package/dist/approval.d.ts.map +1 -1
  3. package/dist/approval.js +40 -10
  4. package/dist/approval.js.map +1 -1
  5. package/dist/backfill.js +2 -2
  6. package/dist/backfill.js.map +1 -1
  7. package/dist/clerk-model.d.ts +0 -1
  8. package/dist/clerk-model.d.ts.map +1 -1
  9. package/dist/clerk-model.js +24 -50
  10. package/dist/clerk-model.js.map +1 -1
  11. package/dist/commands/configure-provider.js +2 -2
  12. package/dist/commands/configure-provider.js.map +1 -1
  13. package/dist/commands/configure.d.ts.map +1 -1
  14. package/dist/commands/configure.js +10 -14
  15. package/dist/commands/configure.js.map +1 -1
  16. package/dist/commands/start.d.ts.map +1 -1
  17. package/dist/commands/start.js +17 -2
  18. package/dist/commands/start.js.map +1 -1
  19. package/dist/config.d.ts +1 -1
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/config.js +2 -2
  22. package/dist/config.js.map +1 -1
  23. package/dist/context-window.d.ts +2 -8
  24. package/dist/context-window.d.ts.map +1 -1
  25. package/dist/context-window.js +4 -4
  26. package/dist/context-window.js.map +1 -1
  27. package/dist/eval/orchestrator-front-door-replay.js +43 -2
  28. package/dist/eval/orchestrator-front-door-replay.js.map +1 -1
  29. package/dist/eval/orchestrator-todo-dispatch-replay.d.ts +2 -0
  30. package/dist/eval/orchestrator-todo-dispatch-replay.d.ts.map +1 -0
  31. package/dist/eval/orchestrator-todo-dispatch-replay.js +253 -0
  32. package/dist/eval/orchestrator-todo-dispatch-replay.js.map +1 -0
  33. package/dist/eval/orchestrator-todo-planning-replay.d.ts +2 -0
  34. package/dist/eval/orchestrator-todo-planning-replay.d.ts.map +1 -0
  35. package/dist/eval/orchestrator-todo-planning-replay.js +247 -0
  36. package/dist/eval/orchestrator-todo-planning-replay.js.map +1 -0
  37. package/dist/eval/policy-detection-replay.d.ts +2 -0
  38. package/dist/eval/policy-detection-replay.d.ts.map +1 -0
  39. package/dist/eval/policy-detection-replay.js +122 -0
  40. package/dist/eval/policy-detection-replay.js.map +1 -0
  41. package/dist/eval/todo-worker-runtime-replay.d.ts +2 -0
  42. package/dist/eval/todo-worker-runtime-replay.d.ts.map +1 -0
  43. package/dist/eval/todo-worker-runtime-replay.js +520 -0
  44. package/dist/eval/todo-worker-runtime-replay.js.map +1 -0
  45. package/dist/integration-tokens.d.ts +6 -0
  46. package/dist/integration-tokens.d.ts.map +1 -1
  47. package/dist/integration-tokens.js +43 -0
  48. package/dist/integration-tokens.js.map +1 -1
  49. package/dist/local-data.d.ts +128 -1
  50. package/dist/local-data.d.ts.map +1 -1
  51. package/dist/local-data.js +702 -18
  52. package/dist/local-data.js.map +1 -1
  53. package/dist/local-db.d.ts.map +1 -1
  54. package/dist/local-db.js +216 -12
  55. package/dist/local-db.js.map +1 -1
  56. package/dist/local-funnel.d.ts.map +1 -1
  57. package/dist/local-funnel.js +7 -0
  58. package/dist/local-funnel.js.map +1 -1
  59. package/dist/local-server.d.ts.map +1 -1
  60. package/dist/local-server.js +119 -96
  61. package/dist/local-server.js.map +1 -1
  62. package/dist/mcp/bridge-server.d.ts.map +1 -1
  63. package/dist/mcp/bridge-server.js +8 -2
  64. package/dist/mcp/bridge-server.js.map +1 -1
  65. package/dist/mcp/manager.d.ts +5 -0
  66. package/dist/mcp/manager.d.ts.map +1 -1
  67. package/dist/mcp/manager.js +36 -0
  68. package/dist/mcp/manager.js.map +1 -1
  69. package/dist/mcp/sync-cli-config.d.ts +5 -0
  70. package/dist/mcp/sync-cli-config.d.ts.map +1 -1
  71. package/dist/mcp/sync-cli-config.js +10 -2
  72. package/dist/mcp/sync-cli-config.js.map +1 -1
  73. package/dist/message-loop.d.ts.map +1 -1
  74. package/dist/message-loop.js +113 -14
  75. package/dist/message-loop.js.map +1 -1
  76. package/dist/mqtt-client.d.ts +44 -0
  77. package/dist/mqtt-client.d.ts.map +1 -1
  78. package/dist/mqtt-client.js.map +1 -1
  79. package/dist/orchestration/front-door-policy.d.ts +26 -9
  80. package/dist/orchestration/front-door-policy.d.ts.map +1 -1
  81. package/dist/orchestration/front-door-policy.js +242 -69
  82. package/dist/orchestration/front-door-policy.js.map +1 -1
  83. package/dist/orchestration/orchestrator-blocked-prompt.d.ts +18 -0
  84. package/dist/orchestration/orchestrator-blocked-prompt.d.ts.map +1 -0
  85. package/dist/orchestration/orchestrator-blocked-prompt.js +46 -0
  86. package/dist/orchestration/orchestrator-blocked-prompt.js.map +1 -0
  87. package/dist/orchestration/orchestrator-final-response-prompt.d.ts +10 -0
  88. package/dist/orchestration/orchestrator-final-response-prompt.d.ts.map +1 -0
  89. package/dist/orchestration/orchestrator-final-response-prompt.js +39 -0
  90. package/dist/orchestration/orchestrator-final-response-prompt.js.map +1 -0
  91. package/dist/orchestration/orchestrator-operating-prompt.d.ts +11 -0
  92. package/dist/orchestration/orchestrator-operating-prompt.d.ts.map +1 -1
  93. package/dist/orchestration/orchestrator-operating-prompt.js +106 -36
  94. package/dist/orchestration/orchestrator-operating-prompt.js.map +1 -1
  95. package/dist/orchestration/policy-prompt.d.ts +6 -0
  96. package/dist/orchestration/policy-prompt.d.ts.map +1 -0
  97. package/dist/orchestration/policy-prompt.js +40 -0
  98. package/dist/orchestration/policy-prompt.js.map +1 -0
  99. package/dist/orchestration/worker-operating-prompt.d.ts +16 -0
  100. package/dist/orchestration/worker-operating-prompt.d.ts.map +1 -0
  101. package/dist/orchestration/worker-operating-prompt.js +75 -0
  102. package/dist/orchestration/worker-operating-prompt.js.map +1 -0
  103. package/dist/orchestrator.d.ts +19 -0
  104. package/dist/orchestrator.d.ts.map +1 -1
  105. package/dist/orchestrator.js +614 -54
  106. package/dist/orchestrator.js.map +1 -1
  107. package/dist/policy-detection.d.ts +40 -0
  108. package/dist/policy-detection.d.ts.map +1 -0
  109. package/dist/policy-detection.js +298 -0
  110. package/dist/policy-detection.js.map +1 -0
  111. package/dist/providers/anthropic.d.ts.map +1 -1
  112. package/dist/providers/anthropic.js +28 -5
  113. package/dist/providers/anthropic.js.map +1 -1
  114. package/dist/providers/claude-cli.d.ts.map +1 -1
  115. package/dist/providers/claude-cli.js +11 -2
  116. package/dist/providers/claude-cli.js.map +1 -1
  117. package/dist/providers/codex-cli.d.ts.map +1 -1
  118. package/dist/providers/codex-cli.js +121 -2
  119. package/dist/providers/codex-cli.js.map +1 -1
  120. package/dist/providers/index.d.ts +4 -0
  121. package/dist/providers/index.d.ts.map +1 -1
  122. package/dist/providers/index.js.map +1 -1
  123. package/dist/summarization-pipeline.d.ts +1 -4
  124. package/dist/summarization-pipeline.d.ts.map +1 -1
  125. package/dist/summarization-pipeline.js +43 -56
  126. package/dist/summarization-pipeline.js.map +1 -1
  127. package/dist/tools/index.d.ts.map +1 -1
  128. package/dist/tools/index.js +2 -0
  129. package/dist/tools/index.js.map +1 -1
  130. package/dist/tools/todo-tasks.d.ts +2 -0
  131. package/dist/tools/todo-tasks.d.ts.map +1 -1
  132. package/dist/tools/todo-tasks.js +203 -6
  133. package/dist/tools/todo-tasks.js.map +1 -1
  134. package/dist/types.d.ts +2 -0
  135. package/dist/types.d.ts.map +1 -1
  136. package/dist/wizard-state.d.ts.map +1 -1
  137. package/dist/wizard-state.js +30 -8
  138. package/dist/wizard-state.js.map +1 -1
  139. package/dist/wizard-support.d.ts +2 -2
  140. package/dist/wizard-support.d.ts.map +1 -1
  141. package/dist/wizard-support.js +80 -93
  142. package/dist/wizard-support.js.map +1 -1
  143. package/dist/workflow-engine.d.ts +3 -0
  144. package/dist/workflow-engine.d.ts.map +1 -1
  145. package/dist/workflow-engine.js +111 -82
  146. package/dist/workflow-engine.js.map +1 -1
  147. package/package.json +5 -1
@@ -646,6 +646,46 @@ class WorkflowEngine extends events_1.EventEmitter {
646
646
  reasonLine,
647
647
  ].join('\n');
648
648
  }
649
+ buildOrchestratedTodoWorkerSystemPrompt(step, profile) {
650
+ const role = this.inferRoleForStep(step);
651
+ const roleLine = role === 'research'
652
+ ? 'Your role is researcher. Produce the requested plan or analysis, then complete the TODO through the worker tool.'
653
+ : role === 'qa'
654
+ ? 'Your role is QA. Verify the delivered work, then complete the TODO through the worker tool or create the next fix handoff.'
655
+ : 'Your role is implementer. Do the assigned work, then complete the TODO through the worker tool.';
656
+ return [
657
+ `You are ${profile?.name || 'a Funolio workflow worker'}.`,
658
+ 'You are executing one orchestrated TODO task inside Funolio.',
659
+ roleLine,
660
+ 'Follow the assignment in the user message exactly.',
661
+ 'Use available tools when needed.',
662
+ 'Do not return a plain-text final answer until you have called complete_worker_task or block_worker_task.',
663
+ 'Do not add workflow planning, orchestration narration, or TODO-management commentary outside those tools.',
664
+ 'If blocked after checking available context, call block_worker_task with blocker_summary, checked_context, and user_question.',
665
+ 'If the task is complete, call complete_worker_task with output_summary and any needed handoff prompt or inserted next task.',
666
+ ].join('\n');
667
+ }
668
+ buildOrchestratedTodoHandledResult(taskId) {
669
+ if (!taskId)
670
+ return 'TODO handled.';
671
+ const completed = data.getTodoTask(taskId, 'completed');
672
+ if (completed) {
673
+ return completed.output_summary?.trim()
674
+ || completed.handoff_prompt?.trim()
675
+ || `Completed TODO #${taskId}.`;
676
+ }
677
+ const blocked = data.getTodoTask(taskId, 'active');
678
+ if (blocked?.blocker_summary) {
679
+ return blocked.blocker_summary.trim();
680
+ }
681
+ return `Handled TODO #${taskId}.`;
682
+ }
683
+ orchestratedTodoHandled(taskId) {
684
+ if (!taskId)
685
+ return false;
686
+ return Boolean(data.getTodoTask(taskId, 'completed')
687
+ || data.getTodoTask(taskId, 'active')?.blocker_summary);
688
+ }
649
689
  buildWorkflowStepPrompt(step, pinnedContext, handoffArtifacts) {
650
690
  const sections = [step.prompt.trim()];
651
691
  if (pinnedContext.length > 0) {
@@ -1250,12 +1290,17 @@ class WorkflowEngine extends events_1.EventEmitter {
1250
1290
  ...(activeRuntime.apiStyle ? { apiStyle: activeRuntime.apiStyle } : {}),
1251
1291
  ...(activeRuntime.authMode ? { authMode: activeRuntime.authMode } : {}),
1252
1292
  ...(activeRuntime.extraHeaders ? { extraHeaders: activeRuntime.extraHeaders } : {}),
1293
+ ...(opts?.isOrchestrated ? { preserveMcpBridge: true } : {}),
1294
+ ...(opts?.isOrchestrated ? { toolActorId: step.agentName } : {}),
1295
+ ...(opts?.isOrchestrated ? { toolProjectId: opts?.projectId ?? null } : {}),
1296
+ ...(opts?.isOrchestrated ? { currentTodoTaskId: opts?.taskId } : {}),
1253
1297
  });
1254
1298
  const toolDefs = (0, index_2.getAllToolDefinitions)();
1255
1299
  const workspacePath = opts?.workspacePath?.trim();
1256
1300
  const effectiveProjectDir = workspacePath || this.projectDir;
1257
1301
  const toolCtx = (0, index_2.createToolContext)(effectiveProjectDir, {
1258
1302
  projectId: opts?.projectId ?? null,
1303
+ currentTodoTaskId: opts?.taskId,
1259
1304
  actorType: 'llm',
1260
1305
  actorId: step.agentName || step.agentId,
1261
1306
  });
@@ -1266,6 +1311,9 @@ class WorkflowEngine extends events_1.EventEmitter {
1266
1311
  if (opts?.systemPromptOverride?.trim()) {
1267
1312
  systemPrompt = opts.systemPromptOverride.trim();
1268
1313
  }
1314
+ else if (opts?.isOrchestrated) {
1315
+ systemPrompt = this.buildOrchestratedTodoWorkerSystemPrompt(step, profile);
1316
+ }
1269
1317
  else if (isWorkflowWorker) {
1270
1318
  systemPrompt = this.buildWorkflowWorkerSystemPrompt(step, profile);
1271
1319
  }
@@ -1288,8 +1336,11 @@ class WorkflowEngine extends events_1.EventEmitter {
1288
1336
  });
1289
1337
  systemPrompt = built.systemPrompt;
1290
1338
  }
1291
- const messages = [{ role: 'user', content: prompt }];
1292
- const promptChars = prompt.length;
1339
+ const effectivePrompt = opts?.isOrchestrated && opts?.taskId
1340
+ ? `CURRENT TODO ID: ${opts.taskId}\nUse this TODO id when calling complete_worker_task or block_worker_task.\n\n${prompt}`
1341
+ : prompt;
1342
+ const messages = [{ role: 'user', content: effectivePrompt }];
1343
+ const promptChars = effectivePrompt.length;
1293
1344
  const systemChars = systemPrompt.length;
1294
1345
  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}`);
1295
1346
  // Agentic loop
@@ -1303,11 +1354,14 @@ class WorkflowEngine extends events_1.EventEmitter {
1303
1354
  let emittedChunkHeartbeat = false;
1304
1355
  let chunkBuffer = '';
1305
1356
  let lastChunkForwardAt = 0;
1306
- const toolChoice = !opts?.disableTools
1307
- && !messages.some((message) => message.role === 'tool')
1308
- && this.stepRequiresConcreteArtifact(step, prompt)
1309
- ? 'required'
1310
- : 'auto';
1357
+ const toolChoice = opts?.disableTools
1358
+ ? 'auto'
1359
+ : opts?.isOrchestrated
1360
+ ? 'required'
1361
+ : !messages.some((message) => message.role === 'tool')
1362
+ && this.stepRequiresConcreteArtifact(step, prompt)
1363
+ ? 'required'
1364
+ : 'auto';
1311
1365
  let response;
1312
1366
  try {
1313
1367
  response = await llm.chat({
@@ -1380,6 +1434,10 @@ class WorkflowEngine extends events_1.EventEmitter {
1380
1434
  ...(activeRuntime.apiStyle ? { apiStyle: activeRuntime.apiStyle } : {}),
1381
1435
  ...(activeRuntime.authMode ? { authMode: activeRuntime.authMode } : {}),
1382
1436
  ...(activeRuntime.extraHeaders ? { extraHeaders: activeRuntime.extraHeaders } : {}),
1437
+ ...(opts?.isOrchestrated ? { preserveMcpBridge: true } : {}),
1438
+ ...(opts?.isOrchestrated ? { toolActorId: step.agentName } : {}),
1439
+ ...(opts?.isOrchestrated ? { toolProjectId: opts?.projectId ?? null } : {}),
1440
+ ...(opts?.isOrchestrated ? { currentTodoTaskId: opts?.taskId } : {}),
1383
1441
  });
1384
1442
  console.warn(`[workflow-engine] ${step.agentName} runtime failed, retrying with ${activeRuntime.providerName}`);
1385
1443
  iteration--;
@@ -1432,12 +1490,39 @@ class WorkflowEngine extends events_1.EventEmitter {
1432
1490
  });
1433
1491
  }
1434
1492
  }
1493
+ if (opts?.isOrchestrated && this.orchestratedTodoHandled(opts.taskId)) {
1494
+ return this.buildOrchestratedTodoHandledResult(opts.taskId);
1495
+ }
1435
1496
  continue;
1436
1497
  }
1437
1498
  // No tool calls — final response
1438
1499
  const content = response.content || streamedContent || '';
1439
1500
  const usedToolsThisStep = messages.some((message) => message.role === 'tool');
1440
1501
  const usedMutatingToolsThisStep = messages.some((message) => message.role === 'tool' && this.isMutatingToolName(message.toolName));
1502
+ if (opts?.isOrchestrated && !this.orchestratedTodoHandled(opts.taskId)) {
1503
+ const correction = [
1504
+ 'You did not finish the orchestrated TODO correctly.',
1505
+ 'Do not answer with plain text alone.',
1506
+ 'You must call complete_worker_task when the task is done, or block_worker_task if you cannot proceed.',
1507
+ 'If you already finished the work, call complete_worker_task now with output_summary and any needed handoff.',
1508
+ 'If you are blocked, call block_worker_task now with blocker_summary, checked_context, and user_question.',
1509
+ ].join(' ');
1510
+ const preview = content.replace(/\s+/g, ' ').trim().slice(0, 240);
1511
+ console.warn(`[workflow-engine] orchestrated TODO not completed through worker tool: agent=${step.agentName} iteration=${iteration} preview=${preview}`);
1512
+ if (incompleteExecutionRecoveries < 1) {
1513
+ incompleteExecutionRecoveries++;
1514
+ if (content.trim()) {
1515
+ messages.push({ role: 'assistant', content });
1516
+ }
1517
+ messages.push({ role: 'user', content: correction });
1518
+ const activeSteps = workflowContext?.workflowId
1519
+ ? this.getActiveWorkflows().find((w) => w.id === workflowContext.workflowId)?.steps || [step]
1520
+ : [step];
1521
+ this.emitProgress(workflowContext?.workflowId || 'workflow', step, activeSteps, 'step-progress', opts?.onProgress, `${step.agentName} must finish the TODO using complete_worker_task or block_worker_task.`);
1522
+ continue;
1523
+ }
1524
+ throw new Error('INCOMPLETE_EXECUTION: The worker returned text without completing the TODO via complete_worker_task or block_worker_task.');
1525
+ }
1441
1526
  // Parse structured footer for workflow steps
1442
1527
  const footer = (0, status_parser_1.parseStructuredFooter)(content);
1443
1528
  const artifactTargetsSatisfied = this.requiredArtifactTargetsSatisfied(step, prompt, effectiveProjectDir);
@@ -1478,6 +1563,10 @@ class WorkflowEngine extends events_1.EventEmitter {
1478
1563
  ...(activeRuntime.apiStyle ? { apiStyle: activeRuntime.apiStyle } : {}),
1479
1564
  ...(activeRuntime.authMode ? { authMode: activeRuntime.authMode } : {}),
1480
1565
  ...(activeRuntime.extraHeaders ? { extraHeaders: activeRuntime.extraHeaders } : {}),
1566
+ ...(opts?.isOrchestrated ? { preserveMcpBridge: true } : {}),
1567
+ ...(opts?.isOrchestrated ? { toolActorId: step.agentName } : {}),
1568
+ ...(opts?.isOrchestrated ? { toolProjectId: opts?.projectId ?? null } : {}),
1569
+ ...(opts?.isOrchestrated ? { currentTodoTaskId: opts?.taskId } : {}),
1481
1570
  });
1482
1571
  incompleteExecutionRecoveries = 0;
1483
1572
  iteration--;
@@ -1591,8 +1680,6 @@ class WorkflowEngine extends events_1.EventEmitter {
1591
1680
  const providerConnection = data.findProviderConnection(provider);
1592
1681
  if (providerConnection?.api_key_enc)
1593
1682
  return providerConnection.api_key_enc;
1594
- if (providerConnection?.oauth_token)
1595
- return providerConnection.oauth_token;
1596
1683
  switch (provider) {
1597
1684
  case 'anthropic': return process.env.ANTHROPIC_API_KEY;
1598
1685
  case 'openai': return process.env.OPENAI_API_KEY;
@@ -1612,7 +1699,6 @@ class WorkflowEngine extends events_1.EventEmitter {
1612
1699
  : undefined;
1613
1700
  const resolvedKey = profile?.api_key_enc
1614
1701
  || profileConnection?.api_key_enc
1615
- || profileConnection?.oauth_token
1616
1702
  || apiKey
1617
1703
  || this.resolveApiKey(step.provider);
1618
1704
  if (!resolvedKey) {
@@ -1626,9 +1712,6 @@ class WorkflowEngine extends events_1.EventEmitter {
1626
1712
  };
1627
1713
  }
1628
1714
  async resolveClaudeWorkflowRuntime(step, profile) {
1629
- const profileConnection = profile?.provider_connection_id
1630
- ? data.getProviderConnection(profile.provider_connection_id)
1631
- : undefined;
1632
1715
  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';
1633
1716
  const apiKeyFallback = data.findProviderConnection('anthropic')?.api_key_enc || process.env.ANTHROPIC_API_KEY;
1634
1717
  const apiFallbackConfig = apiKeyFallback
@@ -1646,63 +1729,28 @@ class WorkflowEngine extends events_1.EventEmitter {
1646
1729
  runtimeLabel: 'Subscription CLI',
1647
1730
  ...(apiFallbackConfig ? { fallback: apiFallbackConfig } : {}),
1648
1731
  };
1649
- try {
1650
- const runtime = await (0, subscription_runtime_1.resolveClaudeSubscriptionRuntime)({
1651
- preferredModel,
1652
- inputToken: profileConnection?.access_mode === 'openclaw' ? (profileConnection.api_key_enc || null) : null,
1653
- inputAccessMode: profileConnection?.access_mode || null,
1654
- });
1655
- if (!runtime)
1656
- return cliFallbackConfig;
1657
- return {
1658
- providerName: runtime.providerName,
1659
- apiKey: runtime.apiKey,
1660
- model: runtime.model,
1661
- runtimeLabel: (0, subscription_runtime_1.claudeSubscriptionRuntimeLabel)(runtime.source),
1662
- requestShape: (0, subscription_runtime_1.resolveClaudeSubscriptionRequestShape)(runtime.source),
1663
- baseUrl: runtime.baseUrl,
1664
- apiQuery: runtime.apiQuery,
1665
- authMode: runtime.authMode,
1666
- extraHeaders: runtime.extraHeaders,
1667
- fallback: cliFallbackConfig,
1668
- };
1669
- }
1670
- catch (err) {
1671
- console.warn(`[workflow-engine] Claude subscription auth failed: ${err?.message || err}`);
1672
- return cliFallbackConfig;
1673
- }
1732
+ return cliFallbackConfig;
1674
1733
  }
1675
1734
  async resolveCodexWorkflowRuntime(step, profile) {
1676
1735
  const preferredModel = (0, subscription_runtime_1.resolveSubscriptionApiModel)(step.model || profile?.model, data.findProviderConnection('openai')?.default_model || data.findProviderConnection('codex-cli')?.default_model || undefined)
1677
1736
  || (step.model || profile?.model || 'default').trim()
1678
1737
  || 'default';
1679
- try {
1680
- const runtime = await (0, subscription_runtime_1.resolveCodexSubscriptionRuntime)({ preferredModel });
1681
- if (runtime) {
1682
- return {
1683
- providerName: runtime.providerName,
1684
- apiKey: runtime.apiKey,
1685
- model: runtime.model,
1686
- runtimeLabel: 'Subscription API',
1687
- baseUrl: runtime.baseUrl,
1688
- apiStyle: runtime.apiStyle,
1689
- fallback: {
1690
- providerName: 'codex-cli',
1691
- apiKey: 'cli-auth',
1692
- model: (step.model || profile?.model || 'default').trim() || 'default',
1693
- runtimeLabel: 'Subscription CLI',
1694
- },
1695
- };
1696
- }
1697
- }
1698
- catch (err) {
1699
- console.warn(`[workflow-engine] Codex subscription auth failed: ${err?.message || err}`);
1700
- }
1738
+ const apiKeyFallback = data.findProviderConnection('openai')?.api_key_enc || process.env.OPENAI_API_KEY;
1701
1739
  return {
1702
1740
  providerName: 'codex-cli',
1703
1741
  apiKey: 'cli-auth',
1704
1742
  model: (step.model || profile?.model || 'default').trim() || 'default',
1705
1743
  runtimeLabel: 'Subscription CLI',
1744
+ ...(apiKeyFallback
1745
+ ? {
1746
+ fallback: {
1747
+ providerName: 'openai',
1748
+ apiKey: apiKeyFallback,
1749
+ model: preferredModel,
1750
+ runtimeLabel: 'API Key',
1751
+ },
1752
+ }
1753
+ : {}),
1706
1754
  };
1707
1755
  }
1708
1756
  async preflightWorkflowReadiness(steps) {
@@ -1717,28 +1765,9 @@ class WorkflowEngine extends events_1.EventEmitter {
1717
1765
  failures.push({ step, reason: `Bot profile ${step.agentId} is missing.` });
1718
1766
  continue;
1719
1767
  }
1720
- if (profile.provider === 'claude-cli') {
1721
- const runtime = await (0, subscription_runtime_1.resolveClaudeSubscriptionRuntime)({
1722
- preferredModel: profile.model,
1723
- }).catch(() => null);
1724
- if (runtime?.apiKey)
1725
- continue;
1726
- failures.push({
1727
- step,
1728
- reason: `${profile.name} is not authenticated for Claude subscription access. Reconnect Claude login before running this workflow.`,
1729
- });
1730
- continue;
1731
- }
1732
- if (profile.provider === 'codex-cli') {
1733
- const runtime = await (0, subscription_runtime_1.resolveCodexSubscriptionRuntime)({
1734
- preferredModel: profile.model,
1735
- }).catch(() => null);
1736
- if (runtime?.apiKey)
1737
- continue;
1738
- failures.push({
1739
- step,
1740
- reason: `${profile.name} is not authenticated for Codex subscription access. Reconnect OpenAI/Codex login before running this workflow.`,
1741
- });
1768
+ // CLI providers handle their own auth — skip subscription checks
1769
+ // (subscription API has been removed; CLI binary manages credentials directly)
1770
+ if (profile.provider === 'claude-cli' || profile.provider === 'codex-cli') {
1742
1771
  continue;
1743
1772
  }
1744
1773
  const apiKey = profile.api_key_enc || this.resolveApiKey(profile.provider);