funolio-agent 1.0.53 → 1.1.65
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/approval.d.ts +1 -6
- package/dist/approval.d.ts.map +1 -1
- package/dist/approval.js +2 -7
- package/dist/approval.js.map +1 -1
- package/dist/auth/credential-reader.d.ts.map +1 -1
- package/dist/auth/credential-reader.js +4 -3
- package/dist/auth/credential-reader.js.map +1 -1
- package/dist/auth/token-refresh.d.ts +8 -0
- package/dist/auth/token-refresh.d.ts.map +1 -1
- package/dist/auth/token-refresh.js +82 -52
- package/dist/auth/token-refresh.js.map +1 -1
- package/dist/auto-organizer.d.ts.map +1 -1
- package/dist/auto-organizer.js +6 -7
- package/dist/auto-organizer.js.map +1 -1
- package/dist/bench-prefix.d.ts +16 -0
- package/dist/bench-prefix.d.ts.map +1 -0
- package/dist/bench-prefix.js +25 -0
- package/dist/bench-prefix.js.map +1 -0
- package/dist/bot-manager.d.ts +5 -1
- package/dist/bot-manager.d.ts.map +1 -1
- package/dist/bot-manager.js +46 -27
- package/dist/bot-manager.js.map +1 -1
- package/dist/chat-sync.d.ts +42 -0
- package/dist/chat-sync.d.ts.map +1 -0
- package/dist/chat-sync.js +95 -0
- package/dist/chat-sync.js.map +1 -0
- package/dist/clerk-model.d.ts +7 -0
- package/dist/clerk-model.d.ts.map +1 -1
- package/dist/clerk-model.js +42 -8
- package/dist/clerk-model.js.map +1 -1
- package/dist/cli-bootstrap-history.d.ts +10 -0
- package/dist/cli-bootstrap-history.d.ts.map +1 -0
- package/dist/cli-bootstrap-history.js +112 -0
- package/dist/cli-bootstrap-history.js.map +1 -0
- package/dist/cli-models.d.ts +8 -0
- package/dist/cli-models.d.ts.map +1 -0
- package/dist/cli-models.js +91 -0
- package/dist/cli-models.js.map +1 -0
- package/dist/cli-session-epoch.d.ts +13 -3
- package/dist/cli-session-epoch.d.ts.map +1 -1
- package/dist/cli-session-epoch.js +53 -4
- package/dist/cli-session-epoch.js.map +1 -1
- package/dist/cli-session-registry.d.ts +35 -0
- package/dist/cli-session-registry.d.ts.map +1 -0
- package/dist/cli-session-registry.js +177 -0
- package/dist/cli-session-registry.js.map +1 -0
- package/dist/cli.js +62 -0
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-server-manager.d.ts +189 -0
- package/dist/codex-app-server-manager.d.ts.map +1 -0
- package/dist/codex-app-server-manager.js +1468 -0
- package/dist/codex-app-server-manager.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +8 -30
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pool.d.ts +32 -0
- package/dist/commands/pool.d.ts.map +1 -1
- package/dist/commands/pool.js +145 -66
- package/dist/commands/pool.js.map +1 -1
- package/dist/commands/setup.d.ts +4 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +9 -25
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/start.d.ts +21 -0
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +559 -63
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +5 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/completion-marker.d.ts +7 -0
- package/dist/completion-marker.d.ts.map +1 -0
- package/dist/completion-marker.js +28 -0
- package/dist/completion-marker.js.map +1 -0
- package/dist/config.d.ts +7 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +184 -60
- package/dist/config.js.map +1 -1
- package/dist/context-window.d.ts +37 -1
- package/dist/context-window.d.ts.map +1 -1
- package/dist/context-window.js +210 -17
- package/dist/context-window.js.map +1 -1
- package/dist/live-activity.d.ts +31 -0
- package/dist/live-activity.d.ts.map +1 -0
- package/dist/live-activity.js +36 -0
- package/dist/live-activity.js.map +1 -0
- package/dist/local-chat-execution.d.ts +114 -0
- package/dist/local-chat-execution.d.ts.map +1 -0
- package/dist/local-chat-execution.js +349 -0
- package/dist/local-chat-execution.js.map +1 -0
- package/dist/local-cli-pty-manager.d.ts +186 -0
- package/dist/local-cli-pty-manager.d.ts.map +1 -1
- package/dist/local-cli-pty-manager.js +2581 -164
- package/dist/local-cli-pty-manager.js.map +1 -1
- package/dist/local-conversation-gateway.d.ts +110 -0
- package/dist/local-conversation-gateway.d.ts.map +1 -0
- package/dist/local-conversation-gateway.js +175 -0
- package/dist/local-conversation-gateway.js.map +1 -0
- package/dist/local-data.d.ts +276 -5
- package/dist/local-data.d.ts.map +1 -1
- package/dist/local-data.js +1201 -86
- package/dist/local-data.js.map +1 -1
- package/dist/local-db.d.ts +6 -0
- package/dist/local-db.d.ts.map +1 -1
- package/dist/local-db.js +428 -2
- package/dist/local-db.js.map +1 -1
- package/dist/local-funnel.d.ts.map +1 -1
- package/dist/local-funnel.js +6 -5
- package/dist/local-funnel.js.map +1 -1
- package/dist/local-server.d.ts +55 -0
- package/dist/local-server.d.ts.map +1 -1
- package/dist/local-server.js +3281 -441
- package/dist/local-server.js.map +1 -1
- package/dist/managed-process-registry.d.ts +59 -0
- package/dist/managed-process-registry.d.ts.map +1 -0
- package/dist/managed-process-registry.js +390 -0
- package/dist/managed-process-registry.js.map +1 -0
- package/dist/mcp/claude-config-writer.d.ts +5 -5
- package/dist/mcp/claude-config-writer.d.ts.map +1 -1
- package/dist/mcp/claude-config-writer.js +19 -11
- package/dist/mcp/claude-config-writer.js.map +1 -1
- package/dist/mcp/index.d.ts +4 -2
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/sync-cli-config.d.ts +42 -4
- package/dist/mcp/sync-cli-config.d.ts.map +1 -1
- package/dist/mcp/sync-cli-config.js +497 -17
- package/dist/mcp/sync-cli-config.js.map +1 -1
- package/dist/message-loop.d.ts +6 -0
- package/dist/message-loop.d.ts.map +1 -1
- package/dist/message-loop.js +281 -89
- package/dist/message-loop.js.map +1 -1
- package/dist/mqtt-client.d.ts +44 -1
- package/dist/mqtt-client.d.ts.map +1 -1
- package/dist/mqtt-client.js +284 -46
- package/dist/mqtt-client.js.map +1 -1
- package/dist/mqtt-data-relay.d.ts +44 -0
- package/dist/mqtt-data-relay.d.ts.map +1 -0
- package/dist/mqtt-data-relay.js +106 -0
- package/dist/mqtt-data-relay.js.map +1 -0
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +69 -29
- package/dist/oauth.js.map +1 -1
- package/dist/orchestration/capabilities.d.ts +13 -0
- package/dist/orchestration/capabilities.d.ts.map +1 -0
- package/dist/orchestration/capabilities.js +152 -0
- package/dist/orchestration/capabilities.js.map +1 -0
- package/dist/orchestration/dispatch-executor.d.ts +83 -0
- package/dist/orchestration/dispatch-executor.d.ts.map +1 -0
- package/dist/orchestration/dispatch-executor.js +266 -0
- package/dist/orchestration/dispatch-executor.js.map +1 -0
- package/dist/orchestration/dispatch-hint.d.ts +134 -0
- package/dist/orchestration/dispatch-hint.d.ts.map +1 -0
- package/dist/orchestration/dispatch-hint.js +247 -0
- package/dist/orchestration/dispatch-hint.js.map +1 -0
- package/dist/orchestration/dispatch-runner.d.ts +106 -0
- package/dist/orchestration/dispatch-runner.d.ts.map +1 -0
- package/dist/orchestration/dispatch-runner.js +604 -0
- package/dist/orchestration/dispatch-runner.js.map +1 -0
- package/dist/orchestration/dispatch-tools.d.ts +167 -0
- package/dist/orchestration/dispatch-tools.d.ts.map +1 -0
- package/dist/orchestration/dispatch-tools.js +328 -0
- package/dist/orchestration/dispatch-tools.js.map +1 -0
- package/dist/orchestration/front-door-policy.d.ts +35 -10
- package/dist/orchestration/front-door-policy.d.ts.map +1 -1
- package/dist/orchestration/front-door-policy.js +30 -267
- package/dist/orchestration/front-door-policy.js.map +1 -1
- package/dist/orchestration/orchestrator-dispatch-prompt.d.ts +43 -0
- package/dist/orchestration/orchestrator-dispatch-prompt.d.ts.map +1 -0
- package/dist/orchestration/orchestrator-dispatch-prompt.js +267 -0
- package/dist/orchestration/orchestrator-dispatch-prompt.js.map +1 -0
- package/dist/orchestration/orchestrator-operating-prompt.d.ts +15 -0
- package/dist/orchestration/orchestrator-operating-prompt.d.ts.map +1 -1
- package/dist/orchestration/orchestrator-operating-prompt.js +206 -20
- package/dist/orchestration/orchestrator-operating-prompt.js.map +1 -1
- package/dist/orchestration/plan-import.d.ts +39 -0
- package/dist/orchestration/plan-import.d.ts.map +1 -0
- package/dist/orchestration/plan-import.js +547 -0
- package/dist/orchestration/plan-import.js.map +1 -0
- package/dist/orchestration/validation.d.ts +40 -0
- package/dist/orchestration/validation.d.ts.map +1 -0
- package/dist/orchestration/validation.js +203 -0
- package/dist/orchestration/validation.js.map +1 -0
- package/dist/orchestration/worker-operating-prompt.d.ts +2 -0
- package/dist/orchestration/worker-operating-prompt.d.ts.map +1 -1
- package/dist/orchestration/worker-operating-prompt.js +36 -46
- package/dist/orchestration/worker-operating-prompt.js.map +1 -1
- package/dist/orchestrator.d.ts +214 -33
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +2200 -1100
- package/dist/orchestrator.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +8 -4
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/claude-cli-prompt.d.ts.map +1 -1
- package/dist/providers/claude-cli-prompt.js +49 -5
- 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 +81 -5
- package/dist/providers/claude-cli.js.map +1 -1
- package/dist/providers/codex-cli.d.ts +10 -6
- package/dist/providers/codex-cli.d.ts.map +1 -1
- package/dist/providers/codex-cli.js +204 -26
- package/dist/providers/codex-cli.js.map +1 -1
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +15 -5
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/index.d.ts +15 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +13 -5
- package/dist/providers/openai.js.map +1 -1
- package/dist/response-guard.js +1 -1
- package/dist/response-guard.js.map +1 -1
- package/dist/server-adapter.d.ts +8 -0
- package/dist/server-adapter.d.ts.map +1 -1
- package/dist/server-adapter.js +7 -0
- package/dist/server-adapter.js.map +1 -1
- package/dist/service-mode.d.ts +1 -1
- package/dist/service-mode.d.ts.map +1 -1
- package/dist/service-mode.js +64 -1
- package/dist/service-mode.js.map +1 -1
- package/dist/service-setup-only.d.ts +8 -0
- package/dist/service-setup-only.d.ts.map +1 -0
- package/dist/service-setup-only.js +37 -0
- package/dist/service-setup-only.js.map +1 -0
- package/dist/slash-commands.d.ts +21 -0
- package/dist/slash-commands.d.ts.map +1 -0
- package/dist/slash-commands.js +99 -0
- package/dist/slash-commands.js.map +1 -0
- package/dist/subagent/index.d.ts +4 -2
- package/dist/subagent/index.d.ts.map +1 -1
- package/dist/subagent/index.js.map +1 -1
- package/dist/summarization-pipeline.d.ts.map +1 -1
- package/dist/summarization-pipeline.js +1 -9
- package/dist/summarization-pipeline.js.map +1 -1
- package/dist/token-counter.d.ts.map +1 -1
- package/dist/token-counter.js +11 -4
- package/dist/token-counter.js.map +1 -1
- package/dist/tool-filter.d.ts.map +1 -1
- package/dist/tool-filter.js +10 -6
- package/dist/tool-filter.js.map +1 -1
- package/dist/tools/admin-tools.d.ts.map +1 -1
- package/dist/tools/admin-tools.js +20 -5
- package/dist/tools/admin-tools.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/run-command.d.ts.map +1 -1
- package/dist/tools/run-command.js +5 -1
- package/dist/tools/run-command.js.map +1 -1
- package/dist/tools/search-conversation-history.d.ts +16 -0
- package/dist/tools/search-conversation-history.d.ts.map +1 -0
- package/dist/tools/search-conversation-history.js +334 -0
- package/dist/tools/search-conversation-history.js.map +1 -0
- package/dist/tools/todo-tasks.d.ts.map +1 -1
- package/dist/tools/todo-tasks.js +77 -5
- package/dist/tools/todo-tasks.js.map +1 -1
- package/dist/usage-log.d.ts +62 -0
- package/dist/usage-log.d.ts.map +1 -0
- package/dist/usage-log.js +98 -0
- package/dist/usage-log.js.map +1 -0
- package/dist/wizard-state.d.ts +20 -0
- package/dist/wizard-state.d.ts.map +1 -1
- package/dist/wizard-state.js +90 -3
- package/dist/wizard-state.js.map +1 -1
- package/dist/wizard-support.d.ts.map +1 -1
- package/dist/wizard-support.js +27 -1
- package/dist/wizard-support.js.map +1 -1
- package/dist/workflow-engine.d.ts +44 -2
- package/dist/workflow-engine.d.ts.map +1 -1
- package/dist/workflow-engine.js +932 -111
- package/dist/workflow-engine.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ORCHESTRATOR_DISPATCH_PROMPT_BODY = void 0;
|
|
4
|
+
exports.buildOrchestratorDispatchPrompt = buildOrchestratorDispatchPrompt;
|
|
5
|
+
const PROMPT_BODY_STATIC = `You are the orchestrator for a Funolio multi-bot conversation.
|
|
6
|
+
|
|
7
|
+
Your job: understand the user's request, decide whether to handle it yourself or
|
|
8
|
+
delegate to a worker bot, and return a structured tool call. The user's prompt
|
|
9
|
+
is authoritative — treat it as such.
|
|
10
|
+
|
|
11
|
+
OPERATING RULE
|
|
12
|
+
|
|
13
|
+
You handle every request yourself UNLESS it falls under one of the capabilities
|
|
14
|
+
listed below in CAPABILITIES WITH A DEDICATED BOT. For those capabilities,
|
|
15
|
+
delegate to the bot that owns that priority.
|
|
16
|
+
|
|
17
|
+
Anything outside the listed capabilities — reading a file, summarizing, answering a
|
|
18
|
+
question, giving status, writing a short reply, clarifying something — you do
|
|
19
|
+
directly. You have read-side tools for this:
|
|
20
|
+
|
|
21
|
+
- read_file, list_directory, search_codebase — inspect the project.
|
|
22
|
+
- search_local_memory — look up stored project memory.
|
|
23
|
+
- list_tasks — see the current TODO queue.
|
|
24
|
+
- web_search, web_fetch — external info.
|
|
25
|
+
|
|
26
|
+
Use these tools freely when you need context to answer. When you're done
|
|
27
|
+
gathering context, end the turn with reply_directly.
|
|
28
|
+
|
|
29
|
+
WRITE-SIDE WORK (creating or changing files, running commands) IS NOT
|
|
30
|
+
available to you directly — those are role-specific jobs. Delegate them to
|
|
31
|
+
the appropriate bot from the list below via delegate_single or
|
|
32
|
+
create_workflow.
|
|
33
|
+
|
|
34
|
+
MULTI-TURN FLOW
|
|
35
|
+
|
|
36
|
+
If you need multiple pieces of context, call the read-side tools across
|
|
37
|
+
multiple turns. Funolio feeds each tool's result back to you automatically.
|
|
38
|
+
Only when you have what you need, end the conversation with exactly one
|
|
39
|
+
of the three dispatch tools.
|
|
40
|
+
|
|
41
|
+
Do NOT mix a read-side tool call with a dispatch tool call in the same
|
|
42
|
+
turn — that's ambiguous and will be rejected. Gather first, then
|
|
43
|
+
dispatch on a subsequent turn.
|
|
44
|
+
|
|
45
|
+
THREE DISPATCH TOOLS
|
|
46
|
+
|
|
47
|
+
Every turn ends by calling exactly ONE of these three tools:
|
|
48
|
+
|
|
49
|
+
reply_directly(text)
|
|
50
|
+
Your answer to the user. Use for questions, clarifications, status,
|
|
51
|
+
summaries, greetings, and anything that does not require a role-specific
|
|
52
|
+
bot. The text you provide becomes the user's reply.
|
|
53
|
+
|
|
54
|
+
delegate_single(task_instructions, bot_name?, role?, success_criteria?)
|
|
55
|
+
Delegate a single task to one worker bot. Creates one TODO.
|
|
56
|
+
Provide at least one of bot_name or role.
|
|
57
|
+
- bot_name routes to that specific bot.
|
|
58
|
+
- role picks the highest-priority bot for that role.
|
|
59
|
+
- When both are provided, bot_name wins.
|
|
60
|
+
Optional title may be supplied for the TODO label.
|
|
61
|
+
task_instructions must include every concrete reference the worker
|
|
62
|
+
needs — file paths, URLs, artifact names, the relevant user spec —
|
|
63
|
+
so the worker can act without prospecting for context.
|
|
64
|
+
|
|
65
|
+
create_workflow(steps[])
|
|
66
|
+
Create an ordered multi-step workflow. Use when the user needs multiple
|
|
67
|
+
roles in sequence (e.g. research → coding → QA → verify).
|
|
68
|
+
Each step requires task_instructions plus bot_name or role.
|
|
69
|
+
Each step may include a short title for the TODO label.
|
|
70
|
+
Optional handoff_to_next passes context from one step's worker to the
|
|
71
|
+
next worker's task prompt. Each step's task_instructions must carry
|
|
72
|
+
concrete references for that worker.
|
|
73
|
+
|
|
74
|
+
If the hint includes selected_workflow_template or candidate_workflow_plan,
|
|
75
|
+
Funolio detected an obvious user-requested workflow candidate. Treat it as a
|
|
76
|
+
suggestion, not a command. Approve it by calling create_workflow with the
|
|
77
|
+
listed steps, modify it by calling create_workflow with corrected steps, or
|
|
78
|
+
reject it with reply_directly if the candidate is wrong or unclear.
|
|
79
|
+
|
|
80
|
+
If the hint also shows existing_todos that match the candidate, Funolio has
|
|
81
|
+
already created visible proposed TODOs but has NOT started any workers. In
|
|
82
|
+
that case you do not need to call a dispatch tool just to approve the proposal.
|
|
83
|
+
If it is correct, reply with exactly: APPROVE_PROPOSED_WORKFLOW. If it is
|
|
84
|
+
wrong or unclear, reply with exactly: REJECT_PROPOSED_WORKFLOW followed by one
|
|
85
|
+
short reason. If you need edits, call create_workflow with the corrected plan.
|
|
86
|
+
|
|
87
|
+
For selected_workflow_template, the user explicitly selected or named that
|
|
88
|
+
saved workflow. If you agree, keep exactly the listed step order and bot_name
|
|
89
|
+
values. You author each step's title and task_instructions from the user's
|
|
90
|
+
request and the intended role of that bot. Do not emit generic labels like
|
|
91
|
+
"Complete Ben's workflow step", "Coding", "QA", or "Verify". The saved
|
|
92
|
+
template provides bot order; it is not a substitute for your per-run task
|
|
93
|
+
writing.
|
|
94
|
+
|
|
95
|
+
TODO COMPLETION RULE
|
|
96
|
+
|
|
97
|
+
Do NOT call complete_worker_task or block_worker_task. Those are the worker's
|
|
98
|
+
tools for reporting status on their own TODO. The orchestrator calling them
|
|
99
|
+
would mark a worker's task done without the worker actually doing it.
|
|
100
|
+
|
|
101
|
+
Rare exception — deliberate override: if a worker is permanently stuck and
|
|
102
|
+
the user has explicitly asked you to clean up the stuck TODO, call
|
|
103
|
+
complete_worker_task or block_worker_task with a clear reason. The system
|
|
104
|
+
logs these to the orchestration audit trail.
|
|
105
|
+
|
|
106
|
+
QA PASS/FAIL
|
|
107
|
+
|
|
108
|
+
Workers declare QA pass/fail via the qa_result argument on
|
|
109
|
+
complete_worker_task — not via prose. As the orchestrator you do not
|
|
110
|
+
classify worker output; you trust the structured signal. If QA passes,
|
|
111
|
+
the workflow continues. If QA fails, the runtime auto-creates a fix
|
|
112
|
+
task + re-QA cycle based on the worker's findings.
|
|
113
|
+
|
|
114
|
+
HINT BLOCK
|
|
115
|
+
|
|
116
|
+
Every turn includes a structured context block containing the user prompt,
|
|
117
|
+
conversation metadata, available bots with their role priority lists,
|
|
118
|
+
existing TODOs, and effective policy. The \`advisory\` sub-block contains
|
|
119
|
+
heuristic keyword suggestions — treat it as advisory only; trust the user
|
|
120
|
+
prompt and the available bots list.
|
|
121
|
+
|
|
122
|
+
When the hint includes \`conversation.recent_turns\`, read those turns before
|
|
123
|
+
deciding. They are especially important for stateless/API orchestrators when the
|
|
124
|
+
user refers to "the page", "that file", "the last fix", or similar shorthand.
|
|
125
|
+
|
|
126
|
+
When the hint includes \`conversation.bootstrap_history_file\`, read that file
|
|
127
|
+
for context. This is used for fresh CLI orchestrator sessions. Use it for
|
|
128
|
+
context only and do not mention the file path unless the user asks.
|
|
129
|
+
|
|
130
|
+
PLAN FILE EXECUTION
|
|
131
|
+
|
|
132
|
+
When the hint includes \`plan_execution_intent.mode\`:
|
|
133
|
+
|
|
134
|
+
- \`per_step_todos\`
|
|
135
|
+
The user explicitly wants a file/plan expanded into sequential worker TODOs.
|
|
136
|
+
First read the referenced file. Only do this if the file actually contains
|
|
137
|
+
structured steps (numbered items, lettered items, bullet items, or clearly
|
|
138
|
+
separated actionable sections). Then create ONE ordered workflow where each
|
|
139
|
+
parsed file step is expanded through the user-requested worker sequence.
|
|
140
|
+
Example: if the user asked for Ben coding then John QA, file step 1 becomes
|
|
141
|
+
Ben step 1 -> John QA step 1, file step 2 becomes Ben step 2 -> John QA step 2.
|
|
142
|
+
Do not collapse the entire file into one coarse TODO.
|
|
143
|
+
|
|
144
|
+
- \`per_step_workflow\`
|
|
145
|
+
The user explicitly wants each file step to run through the selected or
|
|
146
|
+
named workflow template. First read the referenced file. Only proceed if
|
|
147
|
+
the file actually contains structured steps. Then expand EACH parsed file
|
|
148
|
+
step through the saved workflow order. Example: if the selected workflow is
|
|
149
|
+
Brain -> Ben -> John, file step 1 becomes Brain step 1 -> Ben step 1 ->
|
|
150
|
+
John step 1; then file step 2 repeats the same workflow order.
|
|
151
|
+
If no selected/named workflow is actually available, ask the user to pick
|
|
152
|
+
one instead of guessing.
|
|
153
|
+
|
|
154
|
+
If the file is not structured enough to identify separate steps, reply_directly
|
|
155
|
+
and ask the user to clarify or reformat the plan instead of guessing.
|
|
156
|
+
|
|
157
|
+
When this orchestrator runs through an API provider (OpenAI, Anthropic API,
|
|
158
|
+
Google Gemini, etc.), the hint block that reaches the provider includes
|
|
159
|
+
local project path metadata (project_folder). That's deliberate — the path
|
|
160
|
+
lets you write accurate task_instructions for workers.
|
|
161
|
+
|
|
162
|
+
ROLE-BASED DISPATCH DETAILS
|
|
163
|
+
|
|
164
|
+
When you use \`role\` without naming a bot, the dispatcher picks the
|
|
165
|
+
highest-priority bot for that role from the available_bots list in the
|
|
166
|
+
hint. Ties break toward bots that don't already have active TODOs in this
|
|
167
|
+
conversation.
|
|
168
|
+
|
|
169
|
+
Role strings are matched case-insensitively after whitespace normalization.
|
|
170
|
+
"QA" == "qa" == " QA ". There is no alias table — use the exact role labels
|
|
171
|
+
from the \`role_priorities\` of the bots in the hint.
|
|
172
|
+
|
|
173
|
+
NATIVE TOOL CALLS VS TEXT FALLBACK
|
|
174
|
+
|
|
175
|
+
If your provider supports native tool calls (Anthropic API, OpenAI API,
|
|
176
|
+
Google Gemini API, etc.), invoke one of the three dispatch tools directly.
|
|
177
|
+
|
|
178
|
+
If your provider does NOT support native tool calls (Claude CLI, Codex CLI,
|
|
179
|
+
or any other text-only interface), emit exactly ONE fenced JSON block as
|
|
180
|
+
your ENTIRE response, with no prose before or after:
|
|
181
|
+
|
|
182
|
+
\`\`\`json
|
|
183
|
+
{"tool": "delegate_single", "arguments": {"bot_name": "Ben", "task_instructions": "Fix the login bug in C:\\\\Projects\\\\app\\\\login.ts"}}
|
|
184
|
+
\`\`\`
|
|
185
|
+
|
|
186
|
+
The shape must be:
|
|
187
|
+
- \`tool\`: one of "reply_directly", "delegate_single", "create_workflow"
|
|
188
|
+
- \`arguments\`: the same fields documented above for that tool
|
|
189
|
+
|
|
190
|
+
Funolio parses this block identically to a native tool call — same
|
|
191
|
+
validators, same executor, same audit trail. Emit exactly one block per
|
|
192
|
+
turn.`;
|
|
193
|
+
/**
|
|
194
|
+
* Build the "CAPABILITIES WITH A DEDICATED BOT" section dynamically from the
|
|
195
|
+
* hint's active bots. For each distinct role priority across bots, lists
|
|
196
|
+
* the bot(s) that own that role. Steven's rule: exceptions to "do it
|
|
197
|
+
* yourself" come from settings — i.e. from the bots the user actually
|
|
198
|
+
* configured.
|
|
199
|
+
*/
|
|
200
|
+
function buildRolesSection(bots) {
|
|
201
|
+
const rolesToBots = new Map();
|
|
202
|
+
for (const bot of bots) {
|
|
203
|
+
if (!bot.is_active)
|
|
204
|
+
continue;
|
|
205
|
+
for (const role of bot.role_priorities || []) {
|
|
206
|
+
const key = String(role || '').trim();
|
|
207
|
+
if (!key)
|
|
208
|
+
continue;
|
|
209
|
+
const list = rolesToBots.get(key) || [];
|
|
210
|
+
if (!list.includes(bot.name))
|
|
211
|
+
list.push(bot.name);
|
|
212
|
+
rolesToBots.set(key, list);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (rolesToBots.size === 0) {
|
|
216
|
+
return [
|
|
217
|
+
'CAPABILITIES WITH A DEDICATED BOT',
|
|
218
|
+
'',
|
|
219
|
+
'(none configured for this conversation — handle every request yourself via reply_directly, unless the user explicitly names a bot.)',
|
|
220
|
+
].join('\n');
|
|
221
|
+
}
|
|
222
|
+
const lines = ['CAPABILITIES WITH A DEDICATED BOT', ''];
|
|
223
|
+
const sorted = Array.from(rolesToBots.entries()).sort(([a], [b]) => a.localeCompare(b));
|
|
224
|
+
for (const [role, owners] of sorted) {
|
|
225
|
+
lines.push(` - ${role} → ${owners.join(', ')}`);
|
|
226
|
+
}
|
|
227
|
+
lines.push('');
|
|
228
|
+
lines.push('These are the ONLY roles for which delegation is preferred. Any');
|
|
229
|
+
lines.push('request that does not cleanly map to one of the roles above, you');
|
|
230
|
+
lines.push('handle yourself via reply_directly.');
|
|
231
|
+
return lines.join('\n');
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Build the full system prompt for an orchestrator turn.
|
|
235
|
+
*
|
|
236
|
+
* Output shape:
|
|
237
|
+
* [Orchestrator Operating Prompt]
|
|
238
|
+
* <static body>
|
|
239
|
+
*
|
|
240
|
+
* <dynamic roles-with-a-dedicated-bot section>
|
|
241
|
+
*
|
|
242
|
+
* [Additional Guidance] — if provided
|
|
243
|
+
* <soul_md or bot-specific text>
|
|
244
|
+
*
|
|
245
|
+
* [Hint Block]
|
|
246
|
+
* <JSON-stringified hint>
|
|
247
|
+
*
|
|
248
|
+
* [End of Hint]
|
|
249
|
+
*/
|
|
250
|
+
function buildOrchestratorDispatchPrompt(input) {
|
|
251
|
+
const rolesSection = buildRolesSection(input.hint.available_bots || []);
|
|
252
|
+
const parts = [
|
|
253
|
+
'[Orchestrator Operating Prompt]',
|
|
254
|
+
PROMPT_BODY_STATIC.trim(),
|
|
255
|
+
'',
|
|
256
|
+
rolesSection,
|
|
257
|
+
];
|
|
258
|
+
const guidance = input.additionalGuidance?.trim();
|
|
259
|
+
if (guidance) {
|
|
260
|
+
parts.push('', '[Additional Guidance]', guidance);
|
|
261
|
+
}
|
|
262
|
+
parts.push('', '[Hint Block]', JSON.stringify(input.hint, null, 2), '[End of Hint]');
|
|
263
|
+
return parts.join('\n');
|
|
264
|
+
}
|
|
265
|
+
/** Export the static body for tests. */
|
|
266
|
+
exports.ORCHESTRATOR_DISPATCH_PROMPT_BODY = PROMPT_BODY_STATIC;
|
|
267
|
+
//# sourceMappingURL=orchestrator-dispatch-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator-dispatch-prompt.js","sourceRoot":"","sources":["../../src/orchestration/orchestrator-dispatch-prompt.ts"],"names":[],"mappings":";;;AA4QA,0EAcC;AAxQD,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2LrB,CAAC;AAQP;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,IAAoB;IAC7C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;IAChD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,SAAS;YAAE,SAAS;QAC7B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,eAAe,IAAI,EAAE,EAAE,CAAC;YAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClD,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,mCAAmC;YACnC,EAAE;YACF,qIAAqI;SACtI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IACD,MAAM,KAAK,GAAa,CAAC,mCAAmC,EAAE,EAAE,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;IAC9E,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAC/E,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,+BAA+B,CAAC,KAA2C;IACzF,MAAM,YAAY,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,KAAK,GAAa;QACtB,iCAAiC;QACjC,kBAAkB,CAAC,IAAI,EAAE;QACzB,EAAE;QACF,YAAY;KACb,CAAC;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAClD,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,uBAAuB,EAAE,QAAQ,CAAC,CAAC;IACpD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;IACrF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,wCAAwC;AAC3B,QAAA,iCAAiC,GAAG,kBAAkB,CAAC"}
|
|
@@ -8,7 +8,9 @@ export interface OrchestratorFrontDoorDecision {
|
|
|
8
8
|
delegate_request?: string;
|
|
9
9
|
workflow_request?: string;
|
|
10
10
|
clarification_questions?: string[];
|
|
11
|
+
narration?: string;
|
|
11
12
|
}
|
|
13
|
+
export declare const ORCHESTRATOR_DECISION_SENTINEL = "===DECISION===";
|
|
12
14
|
export interface SpecialistInfo {
|
|
13
15
|
name: string;
|
|
14
16
|
roleLabel: string;
|
|
@@ -35,6 +37,7 @@ export declare function buildOrchestratorOperatingPrompt(input: {
|
|
|
35
37
|
primaryRole?: string | null;
|
|
36
38
|
specialists?: SpecialistInfo[];
|
|
37
39
|
workflowNames?: string[];
|
|
40
|
+
localPromptContract?: 'legacy' | 'api_or_fresh_cli' | 'cli_recurring';
|
|
38
41
|
entryMode?: 'normal' | 'orchestration_bias';
|
|
39
42
|
signalSummary?: FrontDoorSignalSummary;
|
|
40
43
|
systemSuggestion?: FrontDoorSystemSuggestion | null;
|
|
@@ -43,7 +46,19 @@ export declare function buildOrchestratorOperatingPrompt(input: {
|
|
|
43
46
|
effectivePolicy?: string | null;
|
|
44
47
|
recentSummary?: string | null;
|
|
45
48
|
lastFiveTurns?: string | null;
|
|
49
|
+
bootstrapHistoryFilePath?: string | null;
|
|
46
50
|
decisionOnly?: boolean;
|
|
51
|
+
defaultBotName?: string | null;
|
|
47
52
|
}): string;
|
|
53
|
+
/**
|
|
54
|
+
* Splits the LLM raw output at the ===DECISION=== sentinel.
|
|
55
|
+
* Returns { narration, decisionText } where narration may be empty if the
|
|
56
|
+
* LLM did not follow the format. The decisionText is the portion after
|
|
57
|
+
* the sentinel (or the entire raw if no sentinel was found, for backward compat).
|
|
58
|
+
*/
|
|
59
|
+
export declare function splitOrchestratorNarrationAndDecision(raw: string): {
|
|
60
|
+
narration: string;
|
|
61
|
+
decisionText: string;
|
|
62
|
+
};
|
|
48
63
|
export declare function parseOrchestratorFrontDoorDecision(raw: string): OrchestratorFrontDoorDecision | null;
|
|
49
64
|
//# sourceMappingURL=orchestrator-operating-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator-operating-prompt.d.ts","sourceRoot":"","sources":["../../src/orchestration/orchestrator-operating-prompt.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GACjC,SAAS,GACT,cAAc,GACd,UAAU,GACV,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,yBAAyB,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"orchestrator-operating-prompt.d.ts","sourceRoot":"","sources":["../../src/orchestration/orchestrator-operating-prompt.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GACjC,SAAS,GACT,cAAc,GACd,UAAU,GACV,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,yBAAyB,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,8BAA8B,mBAAmB,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC;CAC7D;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE;IACtD,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,mBAAmB,CAAC,EAAE,QAAQ,GAAG,kBAAkB,GAAG,eAAe,CAAC;IACtE,SAAS,CAAC,EAAE,QAAQ,GAAG,oBAAoB,CAAC;IAC5C,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,gBAAgB,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACpD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,MAAM,CAgWT;AAED;;;;;GAKG;AACH,wBAAgB,qCAAqC,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAS9G;AAED,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,MAAM,GAAG,6BAA6B,GAAG,IAAI,CA+CpG"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ORCHESTRATOR_DECISION_SENTINEL = void 0;
|
|
3
4
|
exports.buildOrchestratorOperatingPrompt = buildOrchestratorOperatingPrompt;
|
|
5
|
+
exports.splitOrchestratorNarrationAndDecision = splitOrchestratorNarrationAndDecision;
|
|
4
6
|
exports.parseOrchestratorFrontDoorDecision = parseOrchestratorFrontDoorDecision;
|
|
7
|
+
exports.ORCHESTRATOR_DECISION_SENTINEL = '===DECISION===';
|
|
5
8
|
function buildOrchestratorOperatingPrompt(input) {
|
|
6
9
|
const primaryRole = input.primaryRole?.trim() || 'generalist';
|
|
7
10
|
const specialists = input.specialists || [];
|
|
@@ -22,6 +25,7 @@ function buildOrchestratorOperatingPrompt(input) {
|
|
|
22
25
|
const workflowLines = workflowNames.length > 0
|
|
23
26
|
? workflowNames.map((w) => `- "${w}"`).join('\n')
|
|
24
27
|
: '(none)';
|
|
28
|
+
const localPromptContract = input.localPromptContract || 'legacy';
|
|
25
29
|
const decisionOnly = input.decisionOnly !== false;
|
|
26
30
|
const entryMode = input.entryMode || 'normal';
|
|
27
31
|
const projectName = input.projectName?.trim() || '(none)';
|
|
@@ -29,6 +33,8 @@ function buildOrchestratorOperatingPrompt(input) {
|
|
|
29
33
|
const effectivePolicy = input.effectivePolicy?.trim() || 'No confirmed special policy is set.';
|
|
30
34
|
const recentSummary = input.recentSummary?.trim() || '(none)';
|
|
31
35
|
const lastFiveTurns = input.lastFiveTurns?.trim() || '(no recent turns)';
|
|
36
|
+
const bootstrapHistoryFilePath = input.bootstrapHistoryFilePath?.trim() || null;
|
|
37
|
+
const defaultBotName = input.defaultBotName?.trim() || '(none)';
|
|
32
38
|
const signalLines = input.signalSummary
|
|
33
39
|
? [
|
|
34
40
|
input.signalSummary.matchedBots?.length ? `- Matched bot names: ${input.signalSummary.matchedBots.join(', ')}` : null,
|
|
@@ -60,6 +66,128 @@ ${signalLines || '- No additional signal details recorded.'}`
|
|
|
60
66
|
Pay attention to the ENTIRE user prompt before deciding. The most important routing signal may appear anywhere in the prompt, including near the end.
|
|
61
67
|
Default to handling the request yourself unless the code front door gives a strong delegation or workflow suggestion or the user clearly directs work to an available worker.
|
|
62
68
|
${signalLines || ''}`.trim();
|
|
69
|
+
if (localPromptContract !== 'legacy') {
|
|
70
|
+
return `You are acting as Orchestrator and ${primaryRole} in this request.
|
|
71
|
+
|
|
72
|
+
By default, you do the work yourself.
|
|
73
|
+
|
|
74
|
+
Only split the work when:
|
|
75
|
+
- part of the request clearly belongs to another listed bot or role
|
|
76
|
+
- the user explicitly asks for a named workflow that is listed here
|
|
77
|
+
- the request clearly requires multiple bots doing different tasks
|
|
78
|
+
|
|
79
|
+
Workflow and TODOs are not the same.
|
|
80
|
+
Use a saved workflow template when the user names one that is listed here.
|
|
81
|
+
Use TODOs when the work needs to be split across multiple bots or roles.
|
|
82
|
+
|
|
83
|
+
If you keep the work, do the work now in this same response.
|
|
84
|
+
If you split the work, create the needed TODOs and stop after clearly setting up the next step.
|
|
85
|
+
|
|
86
|
+
If the user mentions another bot only as context, history, or authorship, keep the work and handle it yourself.
|
|
87
|
+
Handle these kinds of direct orchestration work yourself by default:
|
|
88
|
+
- answer user questions
|
|
89
|
+
- inspect the project or codebase and explain findings
|
|
90
|
+
- read files
|
|
91
|
+
- write or update plain-text notes, plans, fix lists, and summaries
|
|
92
|
+
- create, edit, reorder, or explain TODOs
|
|
93
|
+
- break work into sequential steps
|
|
94
|
+
- summarize progress and status
|
|
95
|
+
- ask clarifying questions
|
|
96
|
+
- do lightweight project research and comparison
|
|
97
|
+
- keep work that does not clearly belong to a listed worker role
|
|
98
|
+
|
|
99
|
+
If you cannot complete kept work directly, use the default bot instead of forcing a worker workflow.
|
|
100
|
+
|
|
101
|
+
Available Bots and Roles
|
|
102
|
+
${specialistLines}
|
|
103
|
+
|
|
104
|
+
Default Bot
|
|
105
|
+
- ${defaultBotName}
|
|
106
|
+
|
|
107
|
+
Named Workflows
|
|
108
|
+
${workflowLines}
|
|
109
|
+
If the user names a saved workflow listed here, execute that template sequentially.
|
|
110
|
+
If no matching saved workflow is listed, do not treat the word "workflow" as a template error. Use normal language context.
|
|
111
|
+
|
|
112
|
+
Project
|
|
113
|
+
- Name: ${projectName}
|
|
114
|
+
- Folder: ${projectFolder}
|
|
115
|
+
${localPromptContract === 'api_or_fresh_cli'
|
|
116
|
+
? bootstrapHistoryFilePath
|
|
117
|
+
? `
|
|
118
|
+
|
|
119
|
+
Bootstrap History File
|
|
120
|
+
Please read the history file at: ${bootstrapHistoryFilePath}
|
|
121
|
+
Use it for context only. Do not mention the file or path unless the user asks.`
|
|
122
|
+
: `
|
|
123
|
+
|
|
124
|
+
Recent Summary
|
|
125
|
+
${recentSummary}
|
|
126
|
+
|
|
127
|
+
Last 5 Turns
|
|
128
|
+
${lastFiveTurns}`
|
|
129
|
+
: ''}
|
|
130
|
+
|
|
131
|
+
${decisionOnly
|
|
132
|
+
? `OUTPUT FORMAT (TWO PARTS — narration THEN decision JSON)
|
|
133
|
+
|
|
134
|
+
PART 1: NARRATION
|
|
135
|
+
Write exactly ONE short, friendly, natural sentence telling the user what you're about to do.
|
|
136
|
+
- Be conversational and warm, like a helpful colleague casually narrating their plan to a teammate.
|
|
137
|
+
- Vary the wording every time. Never sound scripted or robotic.
|
|
138
|
+
- If you're routing to specific bots, mention them by name in a natural way.
|
|
139
|
+
- Do NOT say "I am reviewing your request" or any similar boilerplate.
|
|
140
|
+
- Do NOT use exclamation points unless the moment really calls for it.
|
|
141
|
+
- Do NOT add any preamble, headers, or labels — just the sentence itself.
|
|
142
|
+
|
|
143
|
+
PART 2: DECISION
|
|
144
|
+
After the narration, on a new line, write exactly the marker ${exports.ORCHESTRATOR_DECISION_SENTINEL}
|
|
145
|
+
Then on the next line, write exactly one JSON object describing your decision.
|
|
146
|
+
Do not wrap JSON in markdown fences.
|
|
147
|
+
Do not add commentary before or after the JSON.
|
|
148
|
+
|
|
149
|
+
EXAMPLE:
|
|
150
|
+
${(() => {
|
|
151
|
+
const researchBot = specialists.find((s) => /research|brainstorm|plan/i.test(s.roleLabel));
|
|
152
|
+
const codingBot = specialists.find((s) => /cod|build|develop|engineer/i.test(s.roleLabel));
|
|
153
|
+
const qaBot = specialists.find((s) => /qa|review/i.test(s.roleLabel));
|
|
154
|
+
const rName = researchBot?.name || 'the researcher';
|
|
155
|
+
const cName = codingBot?.name || 'the coder';
|
|
156
|
+
const qName = qaBot?.name || 'the reviewer';
|
|
157
|
+
return `Got it — I'll have ${rName} sketch a plan first, then ${cName} can build it and ${qName} will give it a once-over.
|
|
158
|
+
${exports.ORCHESTRATOR_DECISION_SENTINEL}
|
|
159
|
+
${JSON.stringify({
|
|
160
|
+
mode: 'workflow',
|
|
161
|
+
reason: 'Multi-step build',
|
|
162
|
+
workflow_request: `${rName} plan, ${cName} code, ${qName} QA`,
|
|
163
|
+
}, null, 2)}`;
|
|
164
|
+
})()}
|
|
165
|
+
|
|
166
|
+
THE JSON SCHEMA:`
|
|
167
|
+
: `OUTPUT FORMAT (TWO PARTS — narration THEN decision/answer)
|
|
168
|
+
|
|
169
|
+
PART 1: NARRATION
|
|
170
|
+
If you are splitting the work, write exactly ONE short, friendly sentence first telling the user what you're about to do.
|
|
171
|
+
Be natural and warm. Vary the wording. No robotic boilerplate.
|
|
172
|
+
If you are keeping the work and answering directly, skip narration and just return your answer.
|
|
173
|
+
|
|
174
|
+
PART 2: DECISION OR DIRECT ANSWER
|
|
175
|
+
- If you keep the work: return the user-facing answer directly with no JSON, no sentinel.
|
|
176
|
+
- If you split the work: after narration, on a new line write ${exports.ORCHESTRATOR_DECISION_SENTINEL}, then write exactly one JSON object.
|
|
177
|
+
- Do not wrap JSON in markdown fences.
|
|
178
|
+
|
|
179
|
+
THE JSON SCHEMA:`}
|
|
180
|
+
${JSON.stringify({
|
|
181
|
+
mode: decisionOnly ? 'respond | execute_self | delegate | workflow | clarify' : 'respond | delegate | workflow | clarify',
|
|
182
|
+
reason: 'short explanation',
|
|
183
|
+
response: 'only for respond',
|
|
184
|
+
delegate_target: 'bot name or NONE',
|
|
185
|
+
delegate_role: 'coding | qa | research | none',
|
|
186
|
+
delegate_request: 'self-contained task',
|
|
187
|
+
workflow_request: 'short objective',
|
|
188
|
+
clarification_questions: [],
|
|
189
|
+
}, null, 2)}`;
|
|
190
|
+
}
|
|
63
191
|
return `You are ${input.orchestratorName}.
|
|
64
192
|
|
|
65
193
|
${decisionOnly
|
|
@@ -88,24 +216,31 @@ DELEGATION POSTURE
|
|
|
88
216
|
- If the system suggests a TODO or workflow for work that cannot be clearly delegated to an available worker other than yourself, do not create a TODO or workflow. Handle the request yourself instead.
|
|
89
217
|
- You may delegate without a system suggestion only when the user clearly directs work to an available worker, role, or specialist other than yourself.
|
|
90
218
|
- If you disagree with the system suggestion, explain why in the "reason" field.
|
|
219
|
+
- If no listed worker role clearly matches the task, keep the work yourself.
|
|
220
|
+
- If you cannot complete kept work directly, use the default bot instead of forcing a worker workflow.
|
|
91
221
|
|
|
92
222
|
---
|
|
93
223
|
|
|
94
224
|
Available Workers
|
|
95
225
|
${specialistLines}
|
|
96
226
|
|
|
227
|
+
Default Bot
|
|
228
|
+
- ${defaultBotName}
|
|
229
|
+
|
|
97
230
|
AVAILABLE WORKER BOUNDARY
|
|
98
231
|
- Delegable work is defined by the available bots, their roles, and their stated responsibilities in this project.
|
|
99
232
|
- A bot name, model name, or prior worker reference is not by itself a delegation request.
|
|
100
233
|
- If the user mentions a worker only as context, history, or authorship, keep the request and handle it yourself.
|
|
101
234
|
- Delegate when the request clearly directs work to an available worker or clearly requires work owned by that worker's role.
|
|
235
|
+
- Handle these kinds of work yourself by default: answering user questions, inspecting the project or codebase and explaining findings, reading files, writing or updating plain-text notes/plans/fix lists/summaries, creating/editing/reordering TODOs, breaking work into sequential steps, summarizing progress/status, asking clarifying questions, and lightweight project research/comparison.
|
|
102
236
|
|
|
103
237
|
---
|
|
104
238
|
|
|
105
239
|
Available Workflows
|
|
106
240
|
${workflowLines}
|
|
107
241
|
- Use workflow when the system suggests workflow and that suggestion is correct, or when the user clearly requests multi-worker or staged work.
|
|
108
|
-
- If
|
|
242
|
+
- If the user names a saved workflow listed here, execute that template sequentially.
|
|
243
|
+
- If no matching saved workflow is listed, do not treat the word "workflow" as a template error. Use normal language context.
|
|
109
244
|
- Delegate ONE clear task only.
|
|
110
245
|
|
|
111
246
|
- delegate_request MUST be fully self-contained:
|
|
@@ -118,8 +253,8 @@ ${workflowLines}
|
|
|
118
253
|
- The receiving bot has NO prior context
|
|
119
254
|
- Do NOT reference prior conversation ("as discussed", "above", etc.)
|
|
120
255
|
|
|
121
|
-
-
|
|
122
|
-
-
|
|
256
|
+
- Treat the listed worker roles and responsibilities as the explicit delegation scope for worker bots.
|
|
257
|
+
- Work outside those listed worker scopes should stay with you unless you intentionally fall back to the default bot.
|
|
123
258
|
|
|
124
259
|
---
|
|
125
260
|
|
|
@@ -149,15 +284,45 @@ DECISION ORDER
|
|
|
149
284
|
---
|
|
150
285
|
|
|
151
286
|
${decisionOnly
|
|
152
|
-
? `OUTPUT JSON
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
-
|
|
158
|
-
- If you
|
|
287
|
+
? `OUTPUT FORMAT (TWO PARTS — narration THEN decision JSON)
|
|
288
|
+
|
|
289
|
+
PART 1: NARRATION
|
|
290
|
+
Write exactly ONE short, friendly, natural sentence telling the user what you're about to do.
|
|
291
|
+
- Be conversational and warm, like a helpful colleague casually narrating their plan to a teammate.
|
|
292
|
+
- Vary the wording every time. Never sound scripted or robotic.
|
|
293
|
+
- If you're routing to specific bots, mention them by name in a natural way.
|
|
294
|
+
- Do NOT say "I am reviewing your request" or any similar boilerplate.
|
|
295
|
+
- Do NOT use exclamation points unless the moment really calls for it.
|
|
296
|
+
- Do NOT add any preamble, headers, or labels — just the sentence itself.
|
|
297
|
+
|
|
298
|
+
PART 2: DECISION
|
|
299
|
+
After the narration, on a new line, write exactly the marker ${exports.ORCHESTRATOR_DECISION_SENTINEL}
|
|
300
|
+
Then on the next line, write exactly one JSON object describing your decision.
|
|
301
|
+
Do not wrap JSON in markdown fences.
|
|
302
|
+
|
|
303
|
+
EXAMPLE:
|
|
304
|
+
Got it — I'll have Brain sketch a plan first, then Ben can build it and John will give it a once-over.
|
|
305
|
+
${exports.ORCHESTRATOR_DECISION_SENTINEL}
|
|
306
|
+
${JSON.stringify({
|
|
307
|
+
mode: 'workflow',
|
|
308
|
+
reason: 'Multi-step build',
|
|
309
|
+
workflow_request: 'Brain plan, Ben code, John QA',
|
|
310
|
+
}, null, 2)}
|
|
311
|
+
|
|
312
|
+
THE JSON SCHEMA:`
|
|
313
|
+
: `OUTPUT FORMAT (TWO PARTS — narration THEN decision/answer)
|
|
314
|
+
|
|
315
|
+
PART 1: NARRATION
|
|
316
|
+
If you are splitting the work, write exactly ONE short, friendly sentence first telling the user what you're about to do.
|
|
317
|
+
Be natural and warm. Vary the wording. No robotic boilerplate.
|
|
318
|
+
If you are keeping the work and answering directly, skip narration and just return your answer.
|
|
319
|
+
|
|
320
|
+
PART 2: DECISION OR DIRECT ANSWER
|
|
321
|
+
- If you keep the work: return the user-facing answer directly with no JSON, no sentinel.
|
|
322
|
+
- If you split the work: after narration, on a new line write ${exports.ORCHESTRATOR_DECISION_SENTINEL}, then write exactly one JSON object.
|
|
159
323
|
- Do not wrap JSON in markdown fences.
|
|
160
|
-
|
|
324
|
+
|
|
325
|
+
THE JSON SCHEMA:`}
|
|
161
326
|
${JSON.stringify({
|
|
162
327
|
mode: decisionOnly ? 'respond | execute_self | delegate | workflow | clarify' : 'respond | delegate | workflow | clarify',
|
|
163
328
|
reason: 'short explanation',
|
|
@@ -183,13 +348,37 @@ RECENT SUMMARY
|
|
|
183
348
|
${recentSummary}
|
|
184
349
|
|
|
185
350
|
LAST 5 TURNS
|
|
186
|
-
${lastFiveTurns}
|
|
351
|
+
${lastFiveTurns}${bootstrapHistoryFilePath
|
|
352
|
+
? `
|
|
353
|
+
|
|
354
|
+
BOOTSTRAP HISTORY FILE
|
|
355
|
+
Please read the history file at: ${bootstrapHistoryFilePath}
|
|
356
|
+
Use it for context only. Do not mention the file or path unless the user asks.`
|
|
357
|
+
: ''}`;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Splits the LLM raw output at the ===DECISION=== sentinel.
|
|
361
|
+
* Returns { narration, decisionText } where narration may be empty if the
|
|
362
|
+
* LLM did not follow the format. The decisionText is the portion after
|
|
363
|
+
* the sentinel (or the entire raw if no sentinel was found, for backward compat).
|
|
364
|
+
*/
|
|
365
|
+
function splitOrchestratorNarrationAndDecision(raw) {
|
|
366
|
+
const text = String(raw || '');
|
|
367
|
+
const sentinelIdx = text.indexOf(exports.ORCHESTRATOR_DECISION_SENTINEL);
|
|
368
|
+
if (sentinelIdx < 0) {
|
|
369
|
+
return { narration: '', decisionText: text };
|
|
370
|
+
}
|
|
371
|
+
const narration = text.slice(0, sentinelIdx).trim();
|
|
372
|
+
const decisionText = text.slice(sentinelIdx + exports.ORCHESTRATOR_DECISION_SENTINEL.length).trim();
|
|
373
|
+
return { narration, decisionText };
|
|
187
374
|
}
|
|
188
375
|
function parseOrchestratorFrontDoorDecision(raw) {
|
|
189
376
|
const trimmed = String(raw || '').trim();
|
|
190
377
|
if (!trimmed)
|
|
191
378
|
return null;
|
|
192
|
-
const
|
|
379
|
+
const { narration, decisionText } = splitOrchestratorNarrationAndDecision(trimmed);
|
|
380
|
+
const sourceForJson = decisionText || trimmed;
|
|
381
|
+
const unfenced = sourceForJson
|
|
193
382
|
.replace(/^```json\s*/i, '')
|
|
194
383
|
.replace(/^```\s*/i, '')
|
|
195
384
|
.replace(/\s*```$/i, '')
|
|
@@ -211,13 +400,9 @@ function parseOrchestratorFrontDoorDecision(raw) {
|
|
|
211
400
|
else {
|
|
212
401
|
normalizedMode = 'execute_self';
|
|
213
402
|
}
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (/which (worker|bot|agent|specialist)|ready to coordinate|get the right bots|before i start|need a few details|i need to know|which .* should handle|let me (coordinate|orchestrate|route|assign)/i.test(resp)) {
|
|
218
|
-
normalizedMode = 'execute_self';
|
|
219
|
-
}
|
|
220
|
-
}
|
|
403
|
+
// Prefer top-level narration field on the JSON object if present, otherwise the pre-sentinel text.
|
|
404
|
+
const narrationFromJson = typeof parsed.narration === 'string' ? parsed.narration.trim() : '';
|
|
405
|
+
const finalNarration = narrationFromJson || narration || '';
|
|
221
406
|
return {
|
|
222
407
|
mode: normalizedMode,
|
|
223
408
|
reason: String(parsed.reason || '').trim(),
|
|
@@ -229,6 +414,7 @@ function parseOrchestratorFrontDoorDecision(raw) {
|
|
|
229
414
|
clarification_questions: Array.isArray(parsed.clarification_questions)
|
|
230
415
|
? parsed.clarification_questions.map((item) => String(item || '').trim()).filter(Boolean)
|
|
231
416
|
: undefined,
|
|
417
|
+
narration: finalNarration || undefined,
|
|
232
418
|
};
|
|
233
419
|
}
|
|
234
420
|
catch {
|