pantheon-opencode 1.5.0-beta.9 → 1.5.0

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 (82) hide show
  1. package/AGENTS.md +14 -63
  2. package/CHANGELOG.md +304 -0
  3. package/README.md +14 -27
  4. package/README.pt-BR.md +5 -6
  5. package/commands/pantheon.md +1 -35
  6. package/package.json +1 -2
  7. package/plugin.json +1 -1
  8. package/pyproject.toml +2 -5
  9. package/scripts/doctor.mjs +32 -3
  10. package/scripts/install/plugin.mjs +9 -12
  11. package/scripts/mcp_persistence_server.py +1 -1
  12. package/scripts/sync-tui.mjs +8 -11
  13. package/src/agents/apollo.md +1 -0
  14. package/src/agents/gaia.md +1 -0
  15. package/src/agents/zeus.md +9 -52
  16. package/src/instructions/memory-protocol.instructions.md +6 -3
  17. package/src/instructions/zeus-anti-stall.instructions.md +2 -4
  18. package/src/instructions/zeus-council-synthesis.instructions.md +3 -28
  19. package/src/instructions/zeus-timeout-retry.instructions.md +3 -28
  20. package/src/mcp/mcp_persistence_server.py +1 -1
  21. package/src/mcp/toon_codec.py +2 -4
  22. package/src/pantheon/background-job-board.ts +4 -4
  23. package/src/pantheon/{delegation-compaction.ts → compaction-context.ts} +10 -100
  24. package/src/pantheon/cost-command.ts +1 -2
  25. package/src/pantheon/delegation-enforce.ts +59 -14
  26. package/src/pantheon/goal-loop.ts +1 -1
  27. package/src/pantheon/goal-store.ts +1 -1
  28. package/src/pantheon/idle-continuation.ts +4 -6
  29. package/src/pantheon/model-command.ts +1 -2
  30. package/src/pantheon/native-task-status.ts +2 -2
  31. package/src/pantheon/presets.d.mts +0 -20
  32. package/src/pantheon/presets.mjs +0 -64
  33. package/src/pantheon/session-guard.ts +2 -2
  34. package/src/pantheon/session-id.ts +30 -0
  35. package/src/pantheon/task-result-guard.ts +2 -3
  36. package/src/pantheon/todo-enforcer.ts +3 -3
  37. package/src/pantheon/tool-context.ts +23 -0
  38. package/src/pantheon/v2-bridge.ts +1 -4
  39. package/src/plugin-v2.ts +8 -21
  40. package/src/plugin.ts +61 -245
  41. package/src/plugins/pantheon-hooks.ts +1 -1
  42. package/src/plugins/tui/dist/tui.d.ts +212 -81
  43. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  44. package/src/plugins/tui/dist/tui.js +475 -254
  45. package/src/plugins/tui/package-lock.json +2 -2
  46. package/src/plugins/tui/package.json +2 -2
  47. package/src/plugins/tui/src/index.tsx +667 -269
  48. package/src/routing.yml +0 -16
  49. package/src/skills/context-compression/SKILL.md +1 -1
  50. package/scripts/generate-preset-docs.mjs +0 -300
  51. package/scripts/generate-prompts.sh +0 -222
  52. package/scripts/hash_verify.py +0 -192
  53. package/scripts/install/component.mjs +0 -24
  54. package/scripts/install/migrate-config.mjs +0 -302
  55. package/scripts/test-context-compression.sh +0 -169
  56. package/src/pantheon/auto-wake.ts +0 -85
  57. package/src/pantheon/chat-reminders.ts +0 -9
  58. package/src/pantheon/comment-checker.ts +0 -48
  59. package/src/pantheon/compaction-assert.ts +0 -160
  60. package/src/pantheon/compaction-handoff.ts +0 -304
  61. package/src/pantheon/cost-tracker.ts +0 -108
  62. package/src/pantheon/delegate-manager.ts +0 -766
  63. package/src/pantheon/delegation-classifier.ts +0 -307
  64. package/src/pantheon/delegation-finalize.ts +0 -406
  65. package/src/pantheon/delegation-notify.ts +0 -212
  66. package/src/pantheon/delegation-toast.ts +0 -73
  67. package/src/pantheon/delegation.ts +0 -1337
  68. package/src/pantheon/dispatch-guard.ts +0 -109
  69. package/src/pantheon/native-probe.ts +0 -234
  70. package/src/pantheon/permission-eval.ts +0 -284
  71. package/src/pantheon/preemptive-compact.ts +0 -76
  72. package/src/pantheon/provider-capabilities.ts +0 -221
  73. package/src/pantheon/provider-stream-tracker.ts +0 -182
  74. package/src/pantheon/retry-policy.ts +0 -212
  75. package/src/pantheon/step-cap.ts +0 -110
  76. package/src/pantheon/token-opt.ts +0 -689
  77. package/src/pantheon/toon-codec.ts +0 -481
  78. package/src/pantheon/v2-events.ts +0 -148
  79. package/src/pantheon/v2-hooks.ts +0 -287
  80. package/src/pantheon/v2-tool-definitions.ts +0 -331
  81. package/src/pantheon/zeus-delegate-with-retry.ts +0 -406
  82. package/src/plugins/tui/dist/tui.tsx +0 -2853
package/src/routing.yml CHANGED
@@ -535,22 +535,6 @@ background_delegation:
535
535
  read_only_agents: [apollo, gaia]
536
536
  session_max: 3
537
537
  retry_count: 1
538
- # ── R1: Per-error-type retry + provider cooldown (LiteLLM pattern) ──────
539
- # retry_policy: max retries per error class before escalating. Exponential
540
- # backoff (base 1s, doubling, capped 30s) applies between retries. auth
541
- # errors are NEVER retried (0) — a credential problem will not fix itself.
542
- # Enforcement: zeus-delegate-with-retry (manual waves) + RetryPolicyEngine.
543
- retry_policy:
544
- auth: 0
545
- rate_limit: 3
546
- timeout: 2
547
- other: 1
548
- # cooldown: after `allowed_fails` consecutive failures for a provider, skip
549
- # that provider for `cooldown_time_seconds`. A success resets the counter.
550
- # In-memory tracker (no Redis) — process-wide, shared across retry helpers.
551
- cooldown:
552
- allowed_fails: 3
553
- cooldown_time_seconds: 60
554
538
  # ── O5: permission.task — glob rules for which subagents an agent may
555
539
  # invoke (last matching rule wins; deny removes the agent from the delegate
556
540
  # tool description entirely — prevents circular delegation at the
@@ -895,6 +895,6 @@ Camada P0 do Deepwork Plan "Context Window Optimization" (council 2026-08-25, 3/
895
895
  ```
896
896
  Desabilitar: `"enabled": false` (plugin vira no-op, sem throw).
897
897
 
898
- **Session Memory (P1 — já existe, só conectado):** `pantheon-persistence` KV com TTL 4h já fornece `context_save`/`context_get`. Auto-save antes de compactar (`experimental.session.compacting` → `buildCompactionContext` + `todoPreserver.capture`) e recovery pós-compactação (`session.compacted` → `todoPreserver.onCompacted` + `reassertAfterCompaction`) preservam estado sem novo MCP. Testado em `delegation-compaction.test.ts` + `todo-preserve.test.ts`.
898
+ **Session Memory (P1 — já existe, só conectado):** `pantheon-persistence` KV com TTL 4h já fornece `context_save`/`context_get`. Auto-save antes de compactar (`experimental.session.compacting` → `buildCompactionContext` + `todoPreserver.capture`) e recovery pós-compactação (`session.compacted` → `todoPreserver.onCompacted` + `reassertAfterCompaction`) preservam estado sem novo MCP. Testado em `todo-preserve.test.ts`.
899
899
 
900
900
  **Fora de escopo v1 (YAGNI):** tiktoken counting, LLM summarization, budget dashboard — só se medição provar necessidade.
@@ -1,300 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * generate-preset-docs.mjs — Generate markdown tables from src/routing.yml
4
- *
5
- * Reads routing.yml + presets.mjs + model-picker.mjs and prints:
6
- * 1) Presets summary table (perfil | provider/baseURL | key env | pricing 2026 | vision | papéis)
7
- * 2) 14 agents × 4 presets matrix (model + effort + vision)
8
- * 3) Capability table (model prefix → maxEffort, vision)
9
- *
10
- * No secrets are hardcoded — only env var NAMES and baseURLs from routing.yml
11
- * are emitted. Pricing labels come from model-picker PRESET_PRICE.
12
- *
13
- * Usage:
14
- * node scripts/generate-preset-docs.mjs # print all
15
- * node scripts/generate-preset-docs.mjs --summary # only summary
16
- * node scripts/generate-preset-docs.mjs --matrix # only matrix
17
- * node scripts/generate-preset-docs.mjs --json # JSON for tooling
18
- */
19
-
20
- import { readFileSync } from 'node:fs'
21
- import { fileURLToPath } from 'node:url'
22
- import yaml from 'js-yaml'
23
- import { CAPABILITY_TABLE, hasVision, normalizeCapability } from '../src/pantheon/presets.mjs'
24
- import { PRESET_PRICE } from './install/model-picker.mjs'
25
-
26
- const routingPath = fileURLToPath(new URL('../src/routing.yml', import.meta.url))
27
- const raw = readFileSync(routingPath, 'utf8')
28
- const routing = yaml.load(raw)
29
- const presets = routing?.presets ?? {}
30
-
31
- const KNOWN_AGENTS_ORDER = [
32
- 'zeus',
33
- 'athena',
34
- 'themis',
35
- 'hermes',
36
- 'aphrodite',
37
- 'demeter',
38
- 'prometheus',
39
- 'hephaestus',
40
- 'apollo',
41
- 'nyx',
42
- 'gaia',
43
- 'iris',
44
- 'mnemosyne',
45
- 'talos',
46
- ]
47
-
48
- function agentSort(a, b) {
49
- const ia = KNOWN_AGENTS_ORDER.indexOf(a)
50
- const ib = KNOWN_AGENTS_ORDER.indexOf(b)
51
- if (ia === -1 && ib === -1) return a.localeCompare(b)
52
- if (ia === -1) return 1
53
- if (ib === -1) return -1
54
- return ia - ib
55
- }
56
-
57
- function safeEnvLabel(_apiKeyEnv) {
58
- return '`[redacted]`'
59
- }
60
-
61
- function providerLabel(def) {
62
- const entries = Object.entries(def.providers ?? {})
63
- if (entries.length === 0) return '—'
64
- return entries
65
- .map(([id, p]) => `\`${id}\` \`${p.baseURL ?? ''}\` (env: ${safeEnvLabel(p.apiKeyEnv)})`)
66
- .join('<br>')
67
- }
68
-
69
- function pricingLabel(name) {
70
- const p = PRESET_PRICE[name]
71
- if (!p) return '—'
72
- return `${p.label} — ${p.detail}`
73
- }
74
-
75
- function visionLabel(def) {
76
- if (!def.vision) return '—'
77
- const m = def.vision.model
78
- let visionFlag = '—'
79
- try {
80
- visionFlag = hasVision(m) ? '👁️ vision' : 'text-only'
81
- } catch {
82
- visionFlag = 'unknown'
83
- }
84
- return `\`${m}\` [${def.vision.reasoning_effort ?? ''}] ${visionFlag}`
85
- }
86
-
87
- function capabilityBadge(model) {
88
- try {
89
- const v = hasVision(model)
90
- const cap = normalizeCapability(model, 'high')
91
- // cap.variant is clamped effort for 'high'
92
- // also get maxEffort via capabilityEntry
93
- const entry = CAPABILITY_TABLE.find(
94
- (e) =>
95
- model.startsWith(e.prefix) ||
96
- model.slice(model.lastIndexOf('/') + 1).startsWith(e.prefix) ||
97
- model.slice(model.lastIndexOf('/') + 1) === e.prefix,
98
- )
99
- // But use direct lookup via prefix matching like capabilityEntry does
100
- return { vision: v, maxEffort: entry?.maxEffort ?? 'unknown', clamped: cap.variant }
101
- } catch {
102
- return { vision: undefined, maxEffort: 'unknown', clamped: undefined }
103
- }
104
- }
105
-
106
- function buildSummaryTable() {
107
- const lines = []
108
- lines.push(
109
- '| Preset | Provider / BaseURL | Key env (nome) | Pricing 2026 | Vision (fallback) | Papéis / Modelos |',
110
- )
111
- lines.push('|---|---|---|---|---|---|')
112
- for (const name of Object.keys(presets)) {
113
- const def = presets[name]
114
- const prov = providerLabel(def)
115
- // env names redacted to avoid exposing credential-related metadata
116
- const envs =
117
- Object.values(def.providers ?? {})
118
- .map((p) => safeEnvLabel(p.apiKeyEnv))
119
- .join(', ') || '—'
120
- // Actually use providerLabel already includes env, but separate column for key env
121
- const pricing = pricingLabel(name)
122
- const vision = visionLabel(def)
123
- // Papéis grouped: planners/high, implementers/medium, scouts/low
124
- const agents = def.agents ?? {}
125
- const groups = {}
126
- for (const [agent, spec] of Object.entries(agents)) {
127
- const key = `\`${spec.model}\` [${spec.reasoning_effort ?? ''}]`
128
- if (!groups[key]) groups[key] = []
129
- groups[key].push(agent)
130
- }
131
- const papelSummary = Object.entries(groups)
132
- .map(([model, list]) => `${list.join(',')}: ${model}`)
133
- .join('<br>')
134
- lines.push(`| \`${name}\` | ${prov} | ${envs} | ${pricing} | ${vision} | ${papelSummary} |`)
135
- }
136
- return lines.join('\n')
137
- }
138
-
139
- function buildMatrixTable() {
140
- const presetNames = Object.keys(presets)
141
- const lines = []
142
- // header
143
- lines.push(
144
- `| Agente | ${presetNames.map((n) => `\`${n}\``).join(' | ')} | Capability (vision / maxEffort) |`,
145
- )
146
- lines.push(`|---|${presetNames.map(() => '---').join('|')}|---|`)
147
- // collect all agents
148
- const allAgents = new Set()
149
- for (const def of Object.values(presets))
150
- for (const a of Object.keys(def.agents ?? {})) allAgents.add(a)
151
- const sorted = [...allAgents].sort(agentSort)
152
- for (const agent of sorted) {
153
- const cells = presetNames.map((presetName) => {
154
- const spec = presets[presetName]?.agents?.[agent]
155
- if (!spec) return '—'
156
- const badge = capabilityBadge(spec.model)
157
- const visionIcon = badge.vision ? '👁️' : '—'
158
- // don't expose raw key, just model and effort
159
- return `\`${spec.model}\`<br>[${spec.reasoning_effort}] ${visionIcon}`
160
- })
161
- // capability column: pick first preset's model for reference, but show per-agent vision across presets is same family
162
- const sampleModel = presets[presetNames[0]]?.agents?.[agent]?.model ?? ''
163
- let capStr = '—'
164
- if (sampleModel) {
165
- try {
166
- const v = hasVision(sampleModel)
167
- capStr = v ? 'vision' : 'text-only'
168
- } catch {
169
- capStr = 'unknown'
170
- }
171
- }
172
- // Show effort clamp per preset? Instead show generic
173
- lines.push(`| \`${agent}\` | ${cells.join(' | ')} | ${capStr} |`)
174
- }
175
- return lines.join('\n')
176
- }
177
-
178
- function buildDetailedMatrixWithEffort() {
179
- const presetNames = Object.keys(presets)
180
- const lines = []
181
- lines.push(`| Agente | ${presetNames.map((n) => `\`${n}\``).join(' | ')} |`)
182
- lines.push(`|---|${presetNames.map(() => '---').join('|')}|`)
183
- const allAgents = new Set()
184
- for (const def of Object.values(presets))
185
- for (const a of Object.keys(def.agents ?? {})) allAgents.add(a)
186
- const sorted = [...allAgents].sort(agentSort)
187
- for (const agent of sorted) {
188
- const cells = presetNames.map((presetName) => {
189
- const spec = presets[presetName]?.agents?.[agent]
190
- if (!spec) return '—'
191
- let vision = '—'
192
- try {
193
- vision = hasVision(spec.model) ? '👁️' : '·'
194
- } catch {
195
- vision = '?'
196
- }
197
- return `\`${spec.model}\` [${spec.reasoning_effort}] ${vision}`
198
- })
199
- lines.push(`| \`${agent}\` | ${cells.join(' | ')} |`)
200
- }
201
- return lines.join('\n')
202
- }
203
-
204
- function buildProviderTable() {
205
- const lines = []
206
- lines.push('| Preset | Provider | BaseURL | Key env |')
207
- lines.push('|---|---|---|---|')
208
- for (const [name, def] of Object.entries(presets)) {
209
- for (const [pid, prov] of Object.entries(def.providers ?? {})) {
210
- const keyEnvStatus = prov.apiKeyEnv ? 'configured' : 'none'
211
- lines.push(`| \`${name}\` | \`${pid}\` | \`${prov.baseURL ?? ''}\` | \`${keyEnvStatus}\` |`)
212
- }
213
- }
214
- return lines.join('\n')
215
- }
216
-
217
- function buildPricingTable() {
218
- const lines = []
219
- lines.push('| Preset | Pricing 2026 | Detalhe | Gateway / Custo |')
220
- lines.push('|---|---|---|---|')
221
- for (const name of Object.keys(presets)) {
222
- const p = PRESET_PRICE[name] ?? { label: '—', detail: '—' }
223
- const def = presets[name]
224
- const prov = Object.keys(def.providers ?? {}).join(', ')
225
- const costHint =
226
- name === 'go-free'
227
- ? '$0 (free-tier Zen, quota limitada)'
228
- : name === 'go-fast'
229
- ? 'Baixo custo (Go gateway, baixa latência)'
230
- : name === 'go-premium'
231
- ? 'Premium (Go gateway, melhor qualidade)'
232
- : 'Pago por uso (OpenAI direto)'
233
- lines.push(`| \`${name}\` | ${p.label} | ${p.detail} | ${prov} — ${costHint} |`)
234
- }
235
- return lines.join('\n')
236
- }
237
-
238
- function buildCapabilityTable() {
239
- const lines = []
240
- lines.push('| Prefix | Max Effort | Vision | Strip Effort |')
241
- lines.push('|---|---|---|---|')
242
- for (const e of CAPABILITY_TABLE) {
243
- lines.push(
244
- `| \`${e.prefix}\` | ${e.maxEffort ?? '—'} | ${e.vision ? '👁️' : '—'} | ${e.stripEffort ? 'yes' : 'no'} |`,
245
- )
246
- }
247
- return lines.join('\n')
248
- }
249
-
250
- const args = process.argv.slice(2)
251
- if (args.includes('--json')) {
252
- const out = { presets, PRESET_PRICE, CAPABILITY_TABLE }
253
- console.log(JSON.stringify(out, null, 2))
254
- process.exit(0)
255
- }
256
- if (args.includes('--summary')) {
257
- console.log(buildSummaryTable())
258
- process.exit(0)
259
- }
260
- if (args.includes('--matrix')) {
261
- console.log(buildMatrixTable())
262
- process.exit(0)
263
- }
264
- if (args.includes('--provider')) {
265
- console.log(buildProviderTable())
266
- process.exit(0)
267
- }
268
- if (args.includes('--pricing')) {
269
- console.log(buildPricingTable())
270
- process.exit(0)
271
- }
272
- if (args.includes('--capability')) {
273
- console.log(buildCapabilityTable())
274
- process.exit(0)
275
- }
276
-
277
- // default: print all
278
- console.log(
279
- '<!-- Generated from src/routing.yml + src/pantheon/presets.mjs + scripts/install/model-picker.mjs — do not edit manually. Run: node scripts/generate-preset-docs.mjs -->',
280
- )
281
- console.log('')
282
- console.log('### Presets — resumo (provider / baseURL / key / pricing / vision)')
283
- console.log('')
284
- console.log(buildSummaryTable())
285
- console.log('')
286
- console.log('### Provider / BaseURL / Key env')
287
- console.log('')
288
- console.log(buildProviderTable())
289
- console.log('')
290
- console.log('### Pricing 2026')
291
- console.log('')
292
- console.log(buildPricingTable())
293
- console.log('')
294
- console.log('### 14 agentes × 4 presets — modelo + effort + vision')
295
- console.log('')
296
- console.log(buildDetailedMatrixWithEffort())
297
- console.log('')
298
- console.log('### Capability table (prefix → maxEffort, vision)')
299
- console.log('')
300
- console.log(buildCapabilityTable())
@@ -1,222 +0,0 @@
1
- #!/usr/bin/env bash
2
- # generate-prompts.sh — Generate dynamic prompt templates for Pantheon
3
- set -euo pipefail
4
-
5
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
- PANTHEON_DIR="$(dirname "$SCRIPT_DIR")"
7
-
8
- # ── Read active plan ─────────────────────────────────────────────────────────
9
- PLAN_FILE="$PANTHEON_DIR/.pantheon/active-preset.json"
10
- if [[ -f "$PLAN_FILE" ]]; then
11
- PLAN=$(jq -r '.plan // "unknown"' "$PLAN_FILE")
12
- SERVICE=$(jq -r '.service // "unknown"' "$PLAN_FILE")
13
- TIER=$(jq -r '.tier // "unknown"' "$PLAN_FILE")
14
- PRICE=$(jq -r '.price // "unknown"' "$PLAN_FILE")
15
- MONTHLY_REQUESTS=$(jq -r '.limits.monthlyRequests // "unlimited"' "$PLAN_FILE")
16
-
17
- # Build tier-to-model map
18
- TIER_MAP=$(jq -r '
19
- to_entries[]
20
- | select(.key | IN("free","fast","default","premium"))
21
- | " \(.key): \(.value)"
22
- ' "$PLAN_FILE" 2>/dev/null || echo " (unable to parse tiers)")
23
-
24
- # Build agent overrides map
25
- AGENT_OVERRIDES=$(jq -r '
26
- .agent_overrides // {}
27
- | to_entries[]
28
- | " \(.key): \(.value)"
29
- ' "$PLAN_FILE" 2>/dev/null || true)
30
- else
31
- PLAN="default"
32
- SERVICE="opencode"
33
- TIER="default"
34
- PRICE="unknown"
35
- MONTHLY_REQUESTS="unlimited"
36
- TIER_MAP=" default: unknown"
37
- AGENT_OVERRIDES=""
38
- fi
39
-
40
- # ── List agents ──────────────────────────────────────────────────────────────
41
- AGENTS_DIR="$PANTHEON_DIR/src/agents"
42
- AGENTS_LIST=""
43
- if [[ -d "$AGENTS_DIR" ]]; then
44
- AGENTS_LIST=$(ls "$AGENTS_DIR"/*.md 2>/dev/null | xargs -n1 basename | sed 's/\.md$//' | sort | paste -sd ', ' -)
45
- fi
46
-
47
- # ── Create dynamic prompts directory ─────────────────────────────────────────
48
- DYNAMIC_DIR="$PANTHEON_DIR/prompts/dynamic"
49
- mkdir -p "$DYNAMIC_DIR"
50
-
51
- # ── Helper: extract description from agent frontmatter ───────────────────────
52
- extract_description() {
53
- local file="$1"
54
- # Grab the first 'description:' line inside the first YAML frontmatter block
55
- sed -n '/^---$/,/^---$/p' "$file" 2>/dev/null \
56
- | grep -m1 '^description:' \
57
- | sed 's/^description:[[:space:]]*//; s/^"//; s/"$//; s/^'"'"'//; s/'"'"'$//' \
58
- || echo "No description available"
59
- }
60
-
61
- # ── Generate Agora Prompt ─────────────────────────────────────────────────────
62
- AGORA_FILE="$DYNAMIC_DIR/agora-generated.txt"
63
- cat > "$AGORA_FILE" << EOF
64
- # =============================================================================
65
- # Dynamic Agora Prompt
66
- # Generated: $(date -u +"%Y-%m-%dT%H:%M:%SZ")
67
- # Plan: $PLAN
68
- # Service: $SERVICE
69
- # Tier: $TIER
70
- # Price: $PRICE
71
- # Monthly Requests: $MONTHLY_REQUESTS
72
- # =============================================================================
73
-
74
- You are convening an agora with access to these specialists: $AGENTS_LIST
75
-
76
- ## Platform Capabilities
77
- EOF
78
-
79
- if [[ -n "$TIER_MAP" ]]; then
80
- echo "Model Tiers:" >> "$AGORA_FILE"
81
- echo "$TIER_MAP" >> "$AGORA_FILE"
82
- echo "" >> "$AGORA_FILE"
83
- fi
84
-
85
- if [[ -n "$AGENT_OVERRIDES" ]]; then
86
- echo "Agent Overrides:" >> "$AGORA_FILE"
87
- echo "$AGENT_OVERRIDES" >> "$AGORA_FILE"
88
- echo "" >> "$AGORA_FILE"
89
- fi
90
-
91
- cat >> "$AGORA_FILE" << EOF
92
- ## Instructions
93
- 1. Select 3-5 relevant agents based on the question domain
94
- 2. Dispatch them in parallel with the same question
95
- 3. Synthesize their perspectives into a single recommendation
96
- 4. Include confidence level and next steps
97
-
98
- ## Available Specialists
99
- EOF
100
-
101
- for agent_file in "$AGENTS_DIR"/*.md; do
102
- [[ -f "$agent_file" ]] || continue
103
- agent_name=$(basename "$agent_file" .md)
104
- description=$(extract_description "$agent_file")
105
- printf -- "- @%s: %s\n" "$agent_name" "$description" >> "$AGORA_FILE"
106
- done
107
-
108
- # ── Generate Orchestration Prompt ────────────────────────────────────────────
109
- ORCH_FILE="$DYNAMIC_DIR/orchestrate-generated.txt"
110
- cat > "$ORCH_FILE" << EOF
111
- # =============================================================================
112
- # Dynamic Orchestration Prompt
113
- # Generated: $(date -u +"%Y-%m-%dT%H:%M:%SZ")
114
- # Plan: $PLAN
115
- # Service: $SERVICE
116
- # Tier: $TIER
117
- # Price: $PRICE
118
- # Monthly Requests: $MONTHLY_REQUESTS
119
- # =============================================================================
120
-
121
- You are Zeus, the central orchestrator for the Pantheon multi-agent system.
122
-
123
- ## Active Configuration
124
- - Plan: $PLAN
125
- - Service: $SERVICE
126
- - Tier: $TIER
127
- - Price: $PRICE
128
- - Monthly Request Limit: $MONTHLY_REQUESTS
129
-
130
- ## Model Tiers
131
- EOF
132
-
133
- if [[ -n "$TIER_MAP" ]]; then
134
- echo "$TIER_MAP" >> "$ORCH_FILE"
135
- fi
136
-
137
- cat >> "$ORCH_FILE" << EOF
138
-
139
- ## Available Agents
140
- EOF
141
-
142
- for agent_file in "$AGENTS_DIR"/*.md; do
143
- [[ -f "$agent_file" ]] || continue
144
- agent_name=$(basename "$agent_file" .md)
145
- description=$(extract_description "$agent_file")
146
- printf -- "- @%s: %s\n" "$agent_name" "$description" >> "$ORCH_FILE"
147
- done
148
-
149
- cat >> "$ORCH_FILE" << EOF
150
-
151
- ## Orchestration Rules
152
- 1. **Planning**: Delegate to @athena for architecture decisions
153
- 2. **Discovery**: Delegate to @apollo for codebase investigation
154
- 3. **Implementation**: Dispatch @hermes (backend), @aphrodite (frontend), @demeter (database) in parallel when scopes are independent
155
- 4. **Review**: Always route completed work to @themis before merge
156
- 5. **Deploy**: Route infrastructure changes to @prometheus
157
- 6. **Document**: Route memory tasks to @mnemosyne
158
- 7. **Hotfix**: Route small fixes to @talos (bypass orchestration)
159
-
160
- ## Cost-Conscious Routing
161
- - Use \`fast\` tier agents for discovery, documentation, and simple queries
162
- - Use \`default\` tier agents for standard implementation work
163
- - Use \`premium\` tier agents for planning, review, and complex orchestration
164
- - Respect monthly request limits: $MONTHLY_REQUESTS
165
- EOF
166
-
167
- # ── Generate Agent Handoff Prompt ────────────────────────────────────────────
168
- HANDOFF_FILE="$DYNAMIC_DIR/handoff-generated.txt"
169
- cat > "$HANDOFF_FILE" << EOF
170
- # =============================================================================
171
- # Dynamic Agent Handoff Prompt
172
- # Generated: $(date -u +"%Y-%m-%dT%H:%M:%SZ")
173
- # Plan: $PLAN
174
- # Service: $SERVICE
175
- # Tier: $TIER
176
- # =============================================================================
177
-
178
- ## Handoff Tier Assignments
179
- EOF
180
-
181
- if [[ -n "$TIER_MAP" ]]; then
182
- echo "$TIER_MAP" >> "$HANDOFF_FILE"
183
- echo "" >> "$HANDOFF_FILE"
184
- fi
185
-
186
- cat >> "$HANDOFF_FILE" << EOF
187
- ## Agent Directory
188
- EOF
189
-
190
- for agent_file in "$AGENTS_DIR"/*.md; do
191
- [[ -f "$agent_file" ]] || continue
192
- agent_name=$(basename "$agent_file" .md)
193
- description=$(extract_description "$agent_file")
194
- printf -- "- @%s: %s\n" "$agent_name" "$description" >> "$HANDOFF_FILE"
195
- done
196
-
197
- cat >> "$HANDOFF_FILE" << EOF
198
-
199
- ## Handoff Rules
200
- | Direction | Tier | Reason |
201
- |---|---|---|
202
- | Any → Themis | premium | Critical quality + security gate |
203
- | Any → Zeus | premium | Complex orchestration decisions |
204
- | Athena → Zeus | premium | Plan handoff needs careful execution |
205
- | Any → Mnemosyne | fast | Simple documentation writes |
206
- | Hephaestus → Prometheus | default | Infrastructure config generation |
207
- | Hephaestus | fast | Conversational AI dispatch |
208
-
209
- ## Cost Cap Rule
210
- The requested model tier cannot exceed the cost tier of the main conversation model.
211
- EOF
212
-
213
- # ── Summary ────────────────────────────────────────────────────────────────────
214
- echo "✅ Generated dynamic prompts for plan '$PLAN'"
215
- echo " Service: $SERVICE"
216
- echo " Tier: $TIER"
217
- echo " Agents: $AGENTS_LIST"
218
- echo ""
219
- echo " Output files:"
220
- echo " - $AGORA_FILE"
221
- echo " - $ORCH_FILE"
222
- echo " - $HANDOFF_FILE"