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.
Files changed (173) hide show
  1. package/dist/agent-config.d.ts +9 -1
  2. package/dist/agent-config.d.ts.map +1 -1
  3. package/dist/agent-config.js +4 -1
  4. package/dist/agent-config.js.map +1 -1
  5. package/dist/auth/auto-detect.d.ts +1 -0
  6. package/dist/auth/auto-detect.d.ts.map +1 -1
  7. package/dist/auth/auto-detect.js +16 -13
  8. package/dist/auth/auto-detect.js.map +1 -1
  9. package/dist/auto-organizer.d.ts.map +1 -1
  10. package/dist/auto-organizer.js +4 -3
  11. package/dist/auto-organizer.js.map +1 -1
  12. package/dist/backfill.d.ts.map +1 -1
  13. package/dist/backfill.js +3 -2
  14. package/dist/backfill.js.map +1 -1
  15. package/dist/bot-manager.d.ts +8 -23
  16. package/dist/bot-manager.d.ts.map +1 -1
  17. package/dist/bot-manager.js +61 -388
  18. package/dist/bot-manager.js.map +1 -1
  19. package/dist/clerk-model.d.ts +5 -1
  20. package/dist/clerk-model.d.ts.map +1 -1
  21. package/dist/clerk-model.js +40 -28
  22. package/dist/clerk-model.js.map +1 -1
  23. package/dist/cli-session-epoch.d.ts +10 -0
  24. package/dist/cli-session-epoch.d.ts.map +1 -0
  25. package/dist/cli-session-epoch.js +61 -0
  26. package/dist/cli-session-epoch.js.map +1 -0
  27. package/dist/commands/init.d.ts.map +1 -1
  28. package/dist/commands/init.js +30 -1
  29. package/dist/commands/init.js.map +1 -1
  30. package/dist/commands/pool.js +1 -1
  31. package/dist/commands/pool.js.map +1 -1
  32. package/dist/commands/setup.d.ts +37 -0
  33. package/dist/commands/setup.d.ts.map +1 -1
  34. package/dist/commands/setup.js +154 -43
  35. package/dist/commands/setup.js.map +1 -1
  36. package/dist/commands/start.d.ts.map +1 -1
  37. package/dist/commands/start.js +195 -164
  38. package/dist/commands/start.js.map +1 -1
  39. package/dist/config-cleanup.d.ts.map +1 -1
  40. package/dist/config-cleanup.js +2 -1
  41. package/dist/config-cleanup.js.map +1 -1
  42. package/dist/config.d.ts +6 -9
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/config.js +8 -30
  45. package/dist/config.js.map +1 -1
  46. package/dist/context-window.d.ts +33 -5
  47. package/dist/context-window.d.ts.map +1 -1
  48. package/dist/context-window.js +121 -20
  49. package/dist/context-window.js.map +1 -1
  50. package/dist/eval/orchestrator-front-door-replay.js +1 -1
  51. package/dist/eval/orchestrator-front-door-replay.js.map +1 -1
  52. package/dist/eval/policy-detection-replay.js +1 -1
  53. package/dist/eval/policy-detection-replay.js.map +1 -1
  54. package/dist/integration-tokens.d.ts +1 -6
  55. package/dist/integration-tokens.d.ts.map +1 -1
  56. package/dist/integration-tokens.js +38 -40
  57. package/dist/integration-tokens.js.map +1 -1
  58. package/dist/local-cli-pty-manager.d.ts +50 -0
  59. package/dist/local-cli-pty-manager.d.ts.map +1 -0
  60. package/dist/local-cli-pty-manager.js +645 -0
  61. package/dist/local-cli-pty-manager.js.map +1 -0
  62. package/dist/local-data.d.ts +30 -0
  63. package/dist/local-data.d.ts.map +1 -1
  64. package/dist/local-data.js +56 -1
  65. package/dist/local-data.js.map +1 -1
  66. package/dist/local-db.d.ts.map +1 -1
  67. package/dist/local-db.js +54 -1
  68. package/dist/local-db.js.map +1 -1
  69. package/dist/local-funnel.d.ts.map +1 -1
  70. package/dist/local-funnel.js +3 -2
  71. package/dist/local-funnel.js.map +1 -1
  72. package/dist/local-memory-search.d.ts +1 -0
  73. package/dist/local-memory-search.d.ts.map +1 -1
  74. package/dist/local-memory-search.js +101 -18
  75. package/dist/local-memory-search.js.map +1 -1
  76. package/dist/local-server.d.ts +0 -16
  77. package/dist/local-server.d.ts.map +1 -1
  78. package/dist/local-server.js +339 -287
  79. package/dist/local-server.js.map +1 -1
  80. package/dist/mcp/bridge-server.d.ts.map +1 -1
  81. package/dist/mcp/bridge-server.js +2 -1
  82. package/dist/mcp/bridge-server.js.map +1 -1
  83. package/dist/mcp/local-memory-server.d.ts +5 -0
  84. package/dist/mcp/local-memory-server.d.ts.map +1 -1
  85. package/dist/mcp/local-memory-server.js +15 -2
  86. package/dist/mcp/local-memory-server.js.map +1 -1
  87. package/dist/mcp/manager.d.ts +3 -22
  88. package/dist/mcp/manager.d.ts.map +1 -1
  89. package/dist/mcp/manager.js +66 -388
  90. package/dist/mcp/manager.js.map +1 -1
  91. package/dist/memory-extraction.d.ts +2 -0
  92. package/dist/memory-extraction.d.ts.map +1 -1
  93. package/dist/memory-extraction.js +3 -1
  94. package/dist/memory-extraction.js.map +1 -1
  95. package/dist/message-loop.d.ts +10 -6
  96. package/dist/message-loop.d.ts.map +1 -1
  97. package/dist/message-loop.js +241 -540
  98. package/dist/message-loop.js.map +1 -1
  99. package/dist/mqtt-client.d.ts +2 -31
  100. package/dist/mqtt-client.d.ts.map +1 -1
  101. package/dist/mqtt-client.js +2 -2
  102. package/dist/mqtt-client.js.map +1 -1
  103. package/dist/oauth.d.ts +6 -0
  104. package/dist/oauth.d.ts.map +1 -1
  105. package/dist/oauth.js +91 -0
  106. package/dist/oauth.js.map +1 -1
  107. package/dist/orchestration/front-door-policy.d.ts +5 -2
  108. package/dist/orchestration/front-door-policy.d.ts.map +1 -1
  109. package/dist/orchestration/front-door-policy.js +25 -28
  110. package/dist/orchestration/front-door-policy.js.map +1 -1
  111. package/dist/orchestration/orchestrator-blocked-prompt.js +1 -1
  112. package/dist/orchestration/orchestrator-final-response-prompt.js +1 -1
  113. package/dist/orchestration/orchestrator-operating-prompt.d.ts +11 -0
  114. package/dist/orchestration/orchestrator-operating-prompt.d.ts.map +1 -1
  115. package/dist/orchestration/orchestrator-operating-prompt.js +67 -44
  116. package/dist/orchestration/orchestrator-operating-prompt.js.map +1 -1
  117. package/dist/orchestration/worker-operating-prompt.js +3 -3
  118. package/dist/orchestration/worker-operating-prompt.js.map +1 -1
  119. package/dist/orchestrator.d.ts +5 -1
  120. package/dist/orchestrator.d.ts.map +1 -1
  121. package/dist/orchestrator.js +141 -81
  122. package/dist/orchestrator.js.map +1 -1
  123. package/dist/prompt-template.js +3 -3
  124. package/dist/prompt-template.js.map +1 -1
  125. package/dist/providers/claude-cli-prompt.d.ts.map +1 -1
  126. package/dist/providers/claude-cli-prompt.js +22 -6
  127. package/dist/providers/claude-cli-prompt.js.map +1 -1
  128. package/dist/providers/claude-cli.d.ts.map +1 -1
  129. package/dist/providers/claude-cli.js +20 -2
  130. package/dist/providers/claude-cli.js.map +1 -1
  131. package/dist/providers/codex-cli.d.ts.map +1 -1
  132. package/dist/providers/codex-cli.js +71 -16
  133. package/dist/providers/codex-cli.js.map +1 -1
  134. package/dist/providers/index.d.ts +11 -0
  135. package/dist/providers/index.d.ts.map +1 -1
  136. package/dist/providers/index.js.map +1 -1
  137. package/dist/runtime-context.d.ts +10 -0
  138. package/dist/runtime-context.d.ts.map +1 -0
  139. package/dist/runtime-context.js +30 -0
  140. package/dist/runtime-context.js.map +1 -0
  141. package/dist/subagent/queue.d.ts.map +1 -1
  142. package/dist/subagent/queue.js +1 -0
  143. package/dist/subagent/queue.js.map +1 -1
  144. package/dist/summarization-pipeline.d.ts +1 -0
  145. package/dist/summarization-pipeline.d.ts.map +1 -1
  146. package/dist/summarization-pipeline.js +94 -25
  147. package/dist/summarization-pipeline.js.map +1 -1
  148. package/dist/tool-permissions.d.ts +2 -0
  149. package/dist/tool-permissions.d.ts.map +1 -0
  150. package/dist/tool-permissions.js +25 -0
  151. package/dist/tool-permissions.js.map +1 -0
  152. package/dist/tools/index.d.ts +7 -8
  153. package/dist/tools/index.d.ts.map +1 -1
  154. package/dist/tools/index.js +70 -60
  155. package/dist/tools/index.js.map +1 -1
  156. package/dist/tools/search-memory.d.ts.map +1 -1
  157. package/dist/tools/search-memory.js +9 -3
  158. package/dist/tools/search-memory.js.map +1 -1
  159. package/dist/tools/spawn-subagent.d.ts.map +1 -1
  160. package/dist/tools/spawn-subagent.js +1 -0
  161. package/dist/tools/spawn-subagent.js.map +1 -1
  162. package/dist/types.d.ts +3 -0
  163. package/dist/types.d.ts.map +1 -1
  164. package/dist/types.js +0 -3
  165. package/dist/types.js.map +1 -1
  166. package/dist/wizard-support.d.ts.map +1 -1
  167. package/dist/wizard-support.js +8 -6
  168. package/dist/wizard-support.js.map +1 -1
  169. package/dist/workflow-engine.d.ts +6 -2
  170. package/dist/workflow-engine.d.ts.map +1 -1
  171. package/dist/workflow-engine.js +254 -77
  172. package/dist/workflow-engine.js.map +1 -1
  173. package/package.json +2 -1
@@ -89,6 +89,9 @@ class OrchestratorAgent {
89
89
  this.clerk = clerk;
90
90
  this.workflowEngine = workflowEngine;
91
91
  }
92
+ isLocalDesktopRuntime() {
93
+ return this.workflowEngine.getRuntimeMode() === 'local_desktop';
94
+ }
92
95
  getLastResponseMeta() {
93
96
  return this.lastResponseMeta;
94
97
  }
@@ -112,6 +115,54 @@ class OrchestratorAgent {
112
115
  }
113
116
  }
114
117
  }
118
+ getAgentRoutingReferences(agent) {
119
+ const refs = new Set();
120
+ const add = (value) => {
121
+ const trimmed = String(value || '').trim();
122
+ if (trimmed)
123
+ refs.add(trimmed);
124
+ };
125
+ add(agent.name);
126
+ const modelProviderText = `${agent.provider || ''} ${agent.model || ''}`.toLowerCase();
127
+ if (modelProviderText.includes('claude'))
128
+ add('Claude');
129
+ if (modelProviderText.includes('codex'))
130
+ add('Codex');
131
+ if (/\bgpt\b|gpt-/.test(modelProviderText))
132
+ add('GPT');
133
+ return Array.from(refs);
134
+ }
135
+ describeAgentResponsibilities(agent) {
136
+ const candidates = [
137
+ agent.purpose_md,
138
+ agent.identity_summary,
139
+ agent.skills_md,
140
+ agent.role_label,
141
+ agent.role_class,
142
+ ].map((value) => String(value || '').replace(/\s+/g, ' ').trim()).filter(Boolean);
143
+ for (const candidate of candidates) {
144
+ const cleaned = candidate
145
+ .replace(/^#+\s*/g, '')
146
+ .replace(/^\-\s*/g, '')
147
+ .replace(/^you are\s+/i, '')
148
+ .replace(/^role:\s*/i, '')
149
+ .trim();
150
+ if (cleaned) {
151
+ return cleaned.length > 180 ? `${cleaned.slice(0, 177).trim()}...` : cleaned;
152
+ }
153
+ }
154
+ const normalizedRole = String(agent.role_class || agent.role_label || '').trim().toLowerCase();
155
+ if (normalizedRole === 'code' || normalizedRole === 'coding') {
156
+ return 'implementation, code changes, fixes, and app changes';
157
+ }
158
+ if (normalizedRole === 'qa') {
159
+ return 'QA, review, verification, and testing';
160
+ }
161
+ if (normalizedRole === 'research') {
162
+ return 'brainstorming, research, planning, and evaluation';
163
+ }
164
+ return 'general assistance';
165
+ }
115
166
  /**
116
167
  * Main entry point. User sends a message, O handles everything.
117
168
  * Returns O's response to display to the user.
@@ -1498,11 +1549,15 @@ class OrchestratorAgent {
1498
1549
  .map((agent) => ({
1499
1550
  name: agent.name,
1500
1551
  roleLabel: agent.role_label || agent.role_class || 'general',
1552
+ references: this.getAgentRoutingReferences(agent),
1553
+ responsibilities: this.describeAgentResponsibilities(agent),
1501
1554
  }));
1502
1555
  const signalSpecialists = allProfiles
1503
1556
  .map((agent) => ({
1504
1557
  name: agent.name,
1505
1558
  roleLabel: agent.role_label || agent.role_class || 'general',
1559
+ references: this.getAgentRoutingReferences(agent),
1560
+ responsibilities: this.describeAgentResponsibilities(agent),
1506
1561
  }));
1507
1562
  // Build workflow names list from enabled templates
1508
1563
  const workflowNames = [];
@@ -1521,16 +1576,17 @@ class OrchestratorAgent {
1521
1576
  roleAssignments,
1522
1577
  });
1523
1578
  const normalizeName = (value) => String(value || '').trim().toLowerCase();
1524
- const fastDecision = this.buildFastFrontDoorDecision(prompt, frontDoorSignals, promptAssignments, roleAssignments);
1525
- if (fastDecision) {
1526
- this.recordOrchestrationAudit(state, 'understand_request', 'path_selected', fastDecision.reason, {
1527
- decisionMode: fastDecision.mode,
1528
- delegateTarget: fastDecision.delegate_target || null,
1529
- delegateRole: fastDecision.delegate_role || null,
1530
- fastPath: true,
1579
+ const systemSuggestion = this.buildFrontDoorSystemSuggestion(prompt, frontDoorSignals, promptAssignments, roleAssignments);
1580
+ if (systemSuggestion) {
1581
+ this.recordOrchestrationAudit(state, 'understand_request', 'path_selected', systemSuggestion.reason, {
1582
+ decisionMode: systemSuggestion.mode,
1583
+ delegateTarget: systemSuggestion.delegateTarget || null,
1584
+ delegateRole: systemSuggestion.delegateRole || null,
1585
+ suggestionConfidence: systemSuggestion.confidence || null,
1586
+ fastPath: false,
1531
1587
  });
1532
- return this.handleFrontDoorDecision(fastDecision, prompt, conversationId, opts, orchestratorBot, projectId, project, policy, promptAssignments, roleAssignments, overview, state, signalSpecialists, workflowNames);
1533
1588
  }
1589
+ const useSinglePassOrchestrator = this.isLocalDesktopRuntime();
1534
1590
  const operatingPrompt = (0, orchestrator_operating_prompt_1.buildOrchestratorOperatingPrompt)({
1535
1591
  orchestratorName: orchestratorBot.name,
1536
1592
  primaryRole: orchestratorBot.role_label || orchestratorBot.role_class || null,
@@ -1545,6 +1601,7 @@ class OrchestratorAgent {
1545
1601
  explicitWorkflowKeyword: frontDoorSignals.explicitWorkflowKeyword,
1546
1602
  explicitDelegationKeyword: frontDoorSignals.explicitDelegationKeyword,
1547
1603
  },
1604
+ systemSuggestion,
1548
1605
  projectName: overview?.project.name || project?.name || null,
1549
1606
  projectFolder: project?.folder || overview?.project.folder || null,
1550
1607
  effectivePolicy: (0, policy_prompt_1.buildEffectivePolicyPromptSection)(policy, {
@@ -1553,6 +1610,7 @@ class OrchestratorAgent {
1553
1610
  }),
1554
1611
  recentSummary: recentSummaryText,
1555
1612
  lastFiveTurns: recentTurnsText,
1613
+ decisionOnly: !useSinglePassOrchestrator,
1556
1614
  });
1557
1615
  const decisionPrompt = [
1558
1616
  'This is a routing decision only. Do not perform the task.',
@@ -1569,15 +1627,44 @@ class OrchestratorAgent {
1569
1627
  this.reportHiddenRoleProgress(opts, 'orchestrator', 'Still understanding the request');
1570
1628
  }, 8_000);
1571
1629
  try {
1572
- const result = await this.runNodeWithRetry('understand_request', state, async () => this.workflowEngine.execute(decisionPrompt, null, orchestratorBot.id, {
1573
- disableDecomposition: true,
1574
- disableTools: true,
1575
- disallowCliRuntime: true,
1576
- projectId: projectId || null,
1577
- workspacePath: project?.folder?.trim() || undefined,
1578
- systemPromptOverride: operatingPrompt,
1579
- }));
1580
- decision = (0, orchestrator_operating_prompt_1.parseOrchestratorFrontDoorDecision)(result.mergedResult);
1630
+ if (useSinglePassOrchestrator) {
1631
+ const result = await this.runNodeWithRetry('understand_request', state, async () => this.workflowEngine.execute(prompt, conversationId, orchestratorBot.id, {
1632
+ disableDecomposition: true,
1633
+ isOrchestrated: false,
1634
+ projectId: projectId || null,
1635
+ workspacePath: project?.folder?.trim() || undefined,
1636
+ persistConversationMessages: false,
1637
+ workerMode: false,
1638
+ systemPromptOverride: operatingPrompt,
1639
+ onWorkerChunk: opts.onWorkerChunk,
1640
+ onProgress: (progress) => {
1641
+ if (progress.event === 'step-failed') {
1642
+ this.reportHiddenRoleProgress(opts, 'orchestrator', `${progress.step.agentName} hit an issue while working on the request`);
1643
+ }
1644
+ },
1645
+ }));
1646
+ const parsed = (0, orchestrator_operating_prompt_1.parseOrchestratorFrontDoorDecision)(result.mergedResult);
1647
+ if (parsed && ['delegate', 'workflow', 'clarify', 'respond'].includes(parsed.mode)) {
1648
+ decision = parsed;
1649
+ }
1650
+ else if (parsed?.mode === 'execute_self') {
1651
+ decision = parsed;
1652
+ }
1653
+ else {
1654
+ clearInterval(understandingHeartbeat);
1655
+ return (await this.finalizeOwnedExecutionResult(result, prompt, conversationId, orchestratorBot, roleAssignments, project, opts, state)).response;
1656
+ }
1657
+ }
1658
+ else {
1659
+ const result = await this.runNodeWithRetry('understand_request', state, async () => this.workflowEngine.execute(decisionPrompt, null, orchestratorBot.id, {
1660
+ disableDecomposition: true,
1661
+ disableTools: true,
1662
+ projectId: projectId || null,
1663
+ workspacePath: project?.folder?.trim() || undefined,
1664
+ systemPromptOverride: operatingPrompt,
1665
+ }));
1666
+ decision = (0, orchestrator_operating_prompt_1.parseOrchestratorFrontDoorDecision)(result.mergedResult);
1667
+ }
1581
1668
  }
1582
1669
  catch {
1583
1670
  decision = null;
@@ -1585,9 +1672,19 @@ class OrchestratorAgent {
1585
1672
  finally {
1586
1673
  clearInterval(understandingHeartbeat);
1587
1674
  }
1675
+ if (!decision && systemSuggestion) {
1676
+ decision = {
1677
+ mode: systemSuggestion.mode,
1678
+ reason: systemSuggestion.reason,
1679
+ delegate_target: systemSuggestion.delegateTarget || undefined,
1680
+ delegate_role: systemSuggestion.delegateRole || undefined,
1681
+ delegate_request: systemSuggestion.mode === 'delegate' ? prompt : undefined,
1682
+ workflow_request: systemSuggestion.mode === 'workflow' ? prompt : undefined,
1683
+ };
1684
+ }
1588
1685
  if (!decision) {
1589
- const fallbackTaskType = (0, front_door_policy_1.inferFrontDoorTaskType)(prompt);
1590
1686
  const promptAssignedRoles = [promptAssignments.coding, promptAssignments.qa, promptAssignments.research].filter(Boolean).length;
1687
+ const fallbackTaskType = (0, front_door_policy_1.inferFrontDoorTaskType)(prompt);
1591
1688
  if (frontDoorSignals.preferredMode === 'workflow') {
1592
1689
  decision = {
1593
1690
  mode: 'workflow',
@@ -1617,82 +1714,42 @@ class OrchestratorAgent {
1617
1714
  delegate_request: prompt,
1618
1715
  };
1619
1716
  }
1620
- else if (fallbackTaskType === 'coding' && roleAssignments.coding) {
1621
- decision = {
1622
- mode: 'delegate',
1623
- reason: 'Code-based front door recovered routing for a coding task owned by the coding worker.',
1624
- delegate_target: roleAssignments.coding,
1625
- delegate_role: 'coding',
1626
- delegate_request: prompt,
1627
- };
1628
- }
1629
- else if (fallbackTaskType === 'qa' && roleAssignments.qa) {
1630
- decision = {
1631
- mode: 'delegate',
1632
- reason: 'Code-based front door recovered routing for a QA task owned by the QA worker.',
1633
- delegate_target: roleAssignments.qa,
1634
- delegate_role: 'qa',
1635
- delegate_request: prompt,
1636
- };
1637
- }
1638
- else if (fallbackTaskType === 'research' && roleAssignments.research) {
1717
+ else {
1639
1718
  decision = {
1640
- mode: 'delegate',
1641
- reason: 'Code-based front door recovered routing for a research task owned by the research worker.',
1642
- delegate_target: roleAssignments.research,
1643
- delegate_role: 'research',
1644
- delegate_request: prompt,
1719
+ mode: 'execute_self',
1720
+ reason: 'No strong routing evidence was found. Handle the request directly.',
1645
1721
  };
1646
1722
  }
1647
1723
  }
1648
1724
  return this.handleFrontDoorDecision(decision, prompt, conversationId, opts, orchestratorBot, projectId, project, policy, promptAssignments, roleAssignments, overview, state, signalSpecialists, workflowNames);
1649
1725
  }
1650
- buildFastFrontDoorDecision(prompt, frontDoorSignals, promptAssignments, roleAssignments) {
1726
+ buildFrontDoorSystemSuggestion(prompt, frontDoorSignals, promptAssignments, roleAssignments) {
1651
1727
  const normalizeName = (value) => String(value || '').trim().toLowerCase();
1652
1728
  const taskType = (0, front_door_policy_1.inferFrontDoorTaskType)(prompt);
1653
- const normalizedPrompt = prompt.trim().toLowerCase();
1654
- if (taskType === 'conversation') {
1655
- if (/\b(hello|hi|hey|are you there|good morning|good afternoon|good evening)\b/i.test(normalizedPrompt)) {
1656
- return {
1657
- mode: 'respond',
1658
- reason: 'Code-first front door handled a simple greeting conversationally.',
1659
- response: "I'm here and ready. Tell me what you want me to coordinate.",
1660
- };
1661
- }
1662
- if (/\b(thanks|thank you|great work|good work|nice work|well done|awesome|perfect|just complementing you|just complimenting you|complimenting you|nothing else)\b/i.test(normalizedPrompt)) {
1663
- return {
1664
- mode: 'respond',
1665
- reason: 'Code-first front door handled a simple conversational compliment without invoking workflow routing.',
1666
- response: "Thanks. I'm here when you need me.",
1667
- };
1668
- }
1729
+ if (taskType === 'policy' || taskType === 'status' || taskType === 'conversation')
1730
+ return null;
1731
+ if (/\bwhat do you think|can we|should we|do you agree|need to discuss|discuss more|is this a good idea|thoughts\??|recommend(?:ation)?\b/i.test(prompt)) {
1732
+ return null;
1669
1733
  }
1734
+ if ((0, front_door_policy_1.isContextualWorkerReferencePrompt)(prompt))
1735
+ return null;
1670
1736
  const promptAssignedRoles = [promptAssignments.coding, promptAssignments.qa, promptAssignments.research].filter(Boolean).length;
1671
- const multiWorkerRequested = taskType === 'mixed'
1737
+ const multiWorkerRequested = frontDoorSignals.matchedWorkflowNames.length > 0
1738
+ || frontDoorSignals.preferredMode === 'workflow'
1739
+ || taskType === 'mixed'
1672
1740
  || promptAssignedRoles >= 2
1673
1741
  || frontDoorSignals.matchedBots.length >= 2
1674
- || frontDoorSignals.matchedRoles.length >= 2
1675
- || frontDoorSignals.matchedWorkflowNames.length > 0
1676
- || frontDoorSignals.preferredMode === 'workflow';
1742
+ || frontDoorSignals.matchedRoles.length >= 2;
1677
1743
  if (multiWorkerRequested) {
1678
1744
  return {
1679
1745
  mode: 'workflow',
1680
1746
  reason: frontDoorSignals.matchedWorkflowNames.length > 0
1681
- ? 'Code-first front door fast-pathed a named or selected workflow request without waiting on orchestrator routing.'
1682
- : 'Code-first front door fast-pathed an obvious staged multi-worker request without waiting on orchestrator routing.',
1683
- workflow_request: prompt,
1747
+ ? 'Code-based front door suggests workflow because the prompt names an available workflow.'
1748
+ : 'Code-based front door suggests workflow because the prompt clearly points to multi-worker or staged work.',
1749
+ confidence: frontDoorSignals.matchedWorkflowNames.length > 0 || frontDoorSignals.explicitOrchestrationRequested ? 'high' : 'medium',
1684
1750
  };
1685
1751
  }
1686
- if (taskType === 'policy' || taskType === 'status' || taskType === 'conversation')
1687
- return null;
1688
- if (/\bwhat do you think|can we|should we|do you agree|need to discuss|discuss more|is this a good idea|thoughts\??|recommend(?:ation)?\b/i.test(prompt)) {
1689
- return null;
1690
- }
1691
- const preferredTarget = frontDoorSignals.preferredTarget
1692
- || (taskType === 'coding' ? roleAssignments.coding
1693
- : taskType === 'qa' ? roleAssignments.qa
1694
- : taskType === 'research' ? roleAssignments.research
1695
- : null);
1752
+ const preferredTarget = frontDoorSignals.preferredTarget;
1696
1753
  if (!preferredTarget)
1697
1754
  return null;
1698
1755
  const delegateRole = frontDoorSignals.matchedRoles[0]
@@ -1702,11 +1759,11 @@ class OrchestratorAgent {
1702
1759
  return {
1703
1760
  mode: 'delegate',
1704
1761
  reason: frontDoorSignals.explicitOrchestrationRequested
1705
- ? 'Code-first front door fast-pathed an explicit single-worker request without waiting on orchestrator routing.'
1706
- : 'Code-first front door fast-pathed a single-worker task to the assigned specialist.',
1707
- delegate_target: preferredTarget,
1708
- delegate_role: delegateRole,
1709
- delegate_request: prompt,
1762
+ ? 'Code-based front door suggests delegate because the prompt explicitly requests worker assignment or TODO handling.'
1763
+ : 'Code-based front door suggests delegate because the prompt clearly assigns one available worker or role.',
1764
+ confidence: frontDoorSignals.explicitOrchestrationRequested ? 'high' : 'medium',
1765
+ delegateTarget: preferredTarget,
1766
+ delegateRole,
1710
1767
  };
1711
1768
  }
1712
1769
  async handleFrontDoorDecision(decision, prompt, conversationId, opts, orchestratorBot, projectId, project, policy, promptAssignments, roleAssignments, overview, state, signalSpecialists, workflowNames) {
@@ -2402,6 +2459,9 @@ class OrchestratorAgent {
2402
2459
  }
2403
2460
  },
2404
2461
  }));
2462
+ return this.finalizeOwnedExecutionResult(result, prompt, conversationId, orchestratorBot, roleAssignments, project, opts, state, options);
2463
+ }
2464
+ async finalizeOwnedExecutionResult(result, prompt, conversationId, orchestratorBot, roleAssignments, project, opts, state, options) {
2405
2465
  const response = this.stripWorkerProtocol(result.mergedResult);
2406
2466
  const footer = (0, status_parser_1.parseStructuredFooter)(result.mergedResult);
2407
2467
  const failureStep = result.steps.find((step) => step.status === 'failed');