pantheon-opencode 1.5.0-beta.15 → 1.5.0-beta.16
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/AGENTS.md +14 -63
- package/CHANGELOG.md +27 -0
- package/README.md +1 -2
- package/README.pt-BR.md +1 -1
- package/commands/pantheon.md +1 -35
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/pyproject.toml +1 -1
- package/src/instructions/memory-protocol.instructions.md +6 -3
- package/src/instructions/zeus-anti-stall.instructions.md +2 -4
- package/src/instructions/zeus-council-synthesis.instructions.md +3 -28
- package/src/instructions/zeus-timeout-retry.instructions.md +3 -28
- package/src/mcp/toon_codec.py +2 -4
- package/src/plugins/tui/dist/tui.js +1 -1
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +1 -1
- package/scripts/dev-tui.sh +0 -48
- package/scripts/generate-preset-docs.mjs +0 -300
- package/scripts/generate-prompts.sh +0 -222
- package/scripts/install/component.mjs +0 -24
- package/scripts/install/migrate-config.mjs +0 -302
- package/src/pantheon/toon-codec.ts +0 -481
|
@@ -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"
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* component.mjs — Component resolution utilities for the OpenCode installer
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/** Available component identifiers */
|
|
6
|
-
export const COMPONENT_NAMES = [
|
|
7
|
-
'agents',
|
|
8
|
-
'skills',
|
|
9
|
-
'instructions',
|
|
10
|
-
'prompts',
|
|
11
|
-
'commands',
|
|
12
|
-
'plugins',
|
|
13
|
-
'runtime',
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Parse --components flag into a Set.
|
|
18
|
-
* @param {string|string[]} spec - Comma-separated string or array of component names
|
|
19
|
-
* @returns {Set<string>}
|
|
20
|
-
*/
|
|
21
|
-
export function resolveComponents(spec) {
|
|
22
|
-
if (Array.isArray(spec)) return new Set(spec)
|
|
23
|
-
return new Set(spec.split(',').map((s) => s.trim()))
|
|
24
|
-
}
|