pantheon-opencode 1.4.2 β†’ 1.5.0-beta.1

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 (98) hide show
  1. package/.pantheon/code-mode/.gitkeep +0 -0
  2. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-1.json +8 -0
  3. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-10.json +8 -0
  4. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-11.json +8 -0
  5. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-2.json +8 -0
  6. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-3.json +8 -0
  7. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-4.json +8 -0
  8. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-5.json +8 -0
  9. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-6.json +8 -0
  10. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-7.json +8 -0
  11. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-8.json +8 -0
  12. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-9.json +8 -0
  13. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/heartbeat.json +8 -0
  14. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/session.json +11 -0
  15. package/.pantheon/code-mode/README.md +93 -0
  16. package/.pantheon/code-mode/checkpoint-session.py +7 -0
  17. package/.pantheon/code-mode/checkpoint-session.sh +11 -0
  18. package/.pantheon/code-mode/checkpoint_session.py +481 -0
  19. package/.pantheon/code-mode/compress-inline.py +450 -0
  20. package/.pantheon/code-mode/eval-llm-judge.py +255 -0
  21. package/.pantheon/code-mode/eval-monte-carlo.py +368 -0
  22. package/.pantheon/code-mode/eval-run.py +197 -0
  23. package/.pantheon/code-mode/eval-static.py +321 -0
  24. package/.pantheon/code-mode/example-sync.sh +5 -0
  25. package/.pantheon/code-mode/session-end-save.py +186 -0
  26. package/.pantheon/code-mode/session-end-save.sh +18 -0
  27. package/.pantheon/code-mode/test-allowed.sh +5 -0
  28. package/.pantheon/code-mode/test-auto-continue-checkpoint.sh +179 -0
  29. package/.pantheon/code-mode/test-env.sh +7 -0
  30. package/.pantheon/code-mode/test-prlimit.sh +9 -0
  31. package/.pantheon/code-mode/test-timeout.sh +6 -0
  32. package/README.md +158 -1189
  33. package/README.pt-BR.md +222 -0
  34. package/bin/pantheon-init.mjs +30 -11
  35. package/opencode.json +1 -0
  36. package/package.json +14 -3
  37. package/plugin.json +15 -0
  38. package/scripts/_pantheon_paths.py +48 -7
  39. package/scripts/ci-validate-yaml.py +7 -2
  40. package/scripts/code_mode_server.py +33 -2
  41. package/scripts/doctor.mjs +135 -127
  42. package/scripts/generate-preset-docs.mjs +127 -66
  43. package/scripts/generate-prompts.sh +2 -2
  44. package/scripts/install/cli-ui.mjs +8 -1
  45. package/scripts/install/config-migration.mjs +401 -0
  46. package/scripts/install/health-check.mjs +3 -3
  47. package/scripts/install/model-picker.mjs +72 -23
  48. package/scripts/install/opencode-version.mjs +47 -0
  49. package/scripts/install/opencode.mjs +261 -88
  50. package/scripts/install/plugin.mjs +112 -42
  51. package/scripts/install/shared.mjs +13 -158
  52. package/scripts/install-mcp.mjs +44 -232
  53. package/scripts/mcp_persistence_server.py +344 -15
  54. package/scripts/mcp_resources_server.py +144 -40
  55. package/scripts/memory_mcp_server.py +2 -2
  56. package/scripts/recover-zenodo-deposition.mjs +146 -0
  57. package/scripts/sync-tui.mjs +32 -7
  58. package/scripts/test-opencode-v1-v2-sandbox.sh +591 -0
  59. package/scripts/uninstall.mjs +298 -954
  60. package/scripts/validate-zenodo-release.mjs +154 -0
  61. package/scripts/zenodo-artifact.mjs +21 -0
  62. package/scripts/zenodo-release-state.mjs +53 -0
  63. package/src/mcp/_pantheon_paths.py +48 -7
  64. package/src/mcp/code_mode_server.py +33 -2
  65. package/src/mcp/eval_store.py +1 -1
  66. package/src/mcp/mcp_persistence_server.py +344 -15
  67. package/src/mcp/mcp_resources_server.py +144 -40
  68. package/src/mcp/pantheon_vision_server.py +1 -1
  69. package/src/mcp/toon_codec.py +491 -0
  70. package/src/pantheon/background-job-board.ts +67 -1
  71. package/src/pantheon/cost-command.ts +6 -2
  72. package/src/pantheon/delegate-manager.ts +384 -0
  73. package/src/pantheon/delegate-task-adapter.ts +444 -0
  74. package/src/pantheon/delegation-notify.ts +35 -20
  75. package/src/pantheon/model-command.ts +86 -32
  76. package/src/pantheon/token-opt.ts +555 -0
  77. package/src/pantheon/toon-codec.ts +481 -0
  78. package/src/pantheon/tui-version-check.ts +1 -3
  79. package/src/pantheon/v2-bridge.ts +129 -0
  80. package/src/pantheon/v2-events.ts +131 -0
  81. package/src/pantheon/v2-hooks.ts +287 -0
  82. package/src/pantheon/v2-tool-definitions.ts +331 -0
  83. package/src/plugin-v2/index.ts +21 -0
  84. package/src/plugin-v2.ts +836 -0
  85. package/src/plugin.ts +57 -10
  86. package/src/plugins/tui/dist/server.d.ts +1 -1
  87. package/src/plugins/tui/dist/server.d.ts.map +1 -1
  88. package/src/plugins/tui/dist/server.js +1 -1
  89. package/src/plugins/tui/dist/server.js.map +1 -1
  90. package/src/plugins/tui/dist/tui.d.ts +10 -7
  91. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  92. package/src/plugins/tui/dist/tui.js +11 -8
  93. package/src/plugins/tui/dist/tui.js.map +1 -1
  94. package/src/plugins/tui/dist/tui.tsx +22 -16
  95. package/src/plugins/tui/package-lock.json +51 -51
  96. package/src/plugins/tui/package.json +7 -7
  97. package/src/plugins/tui/src/index.tsx +22 -16
  98. package/src/skills/README.md +0 -2
@@ -28,88 +28,131 @@ const raw = readFileSync(routingPath, 'utf8')
28
28
  const routing = yaml.load(raw)
29
29
  const presets = routing?.presets ?? {}
30
30
 
31
- const KNOWN_AGENTS_ORDER = ['zeus','athena','themis','hermes','aphrodite','demeter','prometheus','hephaestus','apollo','nyx','gaia','iris','mnemosyne','talos']
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
+ ]
32
47
 
33
- function agentSort(a,b){ const ia = KNOWN_AGENTS_ORDER.indexOf(a); const ib = KNOWN_AGENTS_ORDER.indexOf(b); if(ia===-1&&ib===-1) return a.localeCompare(b); if(ia===-1) return 1; if(ib===-1) return -1; return ia-ib; }
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
+ }
34
56
 
35
- function safeEnvLabel(_apiKeyEnv){
57
+ function safeEnvLabel(_apiKeyEnv) {
36
58
  return '`[redacted]`'
37
59
  }
38
60
 
39
- function providerLabel(def){
61
+ function providerLabel(def) {
40
62
  const entries = Object.entries(def.providers ?? {})
41
- if(entries.length===0) return 'β€”'
42
- return entries.map(([id,p]) => `\`${id}\` \`${p.baseURL ?? ''}\` (env: ${safeEnvLabel(p.apiKeyEnv)})`).join('<br>')
63
+ if (entries.length === 0) return 'β€”'
64
+ return entries
65
+ .map(([id, p]) => `\`${id}\` \`${p.baseURL ?? ''}\` (env: ${safeEnvLabel(p.apiKeyEnv)})`)
66
+ .join('<br>')
43
67
  }
44
68
 
45
- function pricingLabel(name){
69
+ function pricingLabel(name) {
46
70
  const p = PRESET_PRICE[name]
47
- if(!p) return 'β€”'
71
+ if (!p) return 'β€”'
48
72
  return `${p.label} β€” ${p.detail}`
49
73
  }
50
74
 
51
- function visionLabel(def){
52
- if(!def.vision) return 'β€”'
75
+ function visionLabel(def) {
76
+ if (!def.vision) return 'β€”'
53
77
  const m = def.vision.model
54
78
  let visionFlag = 'β€”'
55
- try{ visionFlag = hasVision(m) ? 'πŸ‘οΈ vision' : 'text-only' }catch{ visionFlag = 'unknown' }
79
+ try {
80
+ visionFlag = hasVision(m) ? 'πŸ‘οΈ vision' : 'text-only'
81
+ } catch {
82
+ visionFlag = 'unknown'
83
+ }
56
84
  return `\`${m}\` [${def.vision.reasoning_effort ?? ''}] ${visionFlag}`
57
85
  }
58
86
 
59
- function capabilityBadge(model){
60
- try{
87
+ function capabilityBadge(model) {
88
+ try {
61
89
  const v = hasVision(model)
62
90
  const cap = normalizeCapability(model, 'high')
63
91
  // cap.variant is clamped effort for 'high'
64
92
  // also get maxEffort via capabilityEntry
65
- const entry = CAPABILITY_TABLE.find(e => model.startsWith(e.prefix) || model.slice(model.lastIndexOf('/')+1).startsWith(e.prefix) || model.slice(model.lastIndexOf('/')+1)===e.prefix)
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
+ )
66
99
  // But use direct lookup via prefix matching like capabilityEntry does
67
100
  return { vision: v, maxEffort: entry?.maxEffort ?? 'unknown', clamped: cap.variant }
68
- }catch{
101
+ } catch {
69
102
  return { vision: undefined, maxEffort: 'unknown', clamped: undefined }
70
103
  }
71
104
  }
72
105
 
73
- function buildSummaryTable(){
74
- const lines=[]
75
- lines.push('| Preset | Provider / BaseURL | Key env (nome) | Pricing 2026 | Vision (fallback) | PapΓ©is / Modelos |')
106
+ function buildSummaryTable() {
107
+ const lines = []
108
+ lines.push(
109
+ '| Preset | Provider / BaseURL | Key env (nome) | Pricing 2026 | Vision (fallback) | PapΓ©is / Modelos |',
110
+ )
76
111
  lines.push('|---|---|---|---|---|---|')
77
- for(const name of Object.keys(presets)){
112
+ for (const name of Object.keys(presets)) {
78
113
  const def = presets[name]
79
114
  const prov = providerLabel(def)
80
115
  // env names redacted to avoid exposing credential-related metadata
81
- const envs = Object.values(def.providers ?? {}).map(p=>safeEnvLabel(p.apiKeyEnv)).join(', ') || 'β€”'
116
+ const envs =
117
+ Object.values(def.providers ?? {})
118
+ .map((p) => safeEnvLabel(p.apiKeyEnv))
119
+ .join(', ') || 'β€”'
82
120
  // Actually use providerLabel already includes env, but separate column for key env
83
121
  const pricing = pricingLabel(name)
84
122
  const vision = visionLabel(def)
85
123
  // PapΓ©is grouped: planners/high, implementers/medium, scouts/low
86
124
  const agents = def.agents ?? {}
87
- const groups={}
88
- for(const [agent,spec] of Object.entries(agents)){
125
+ const groups = {}
126
+ for (const [agent, spec] of Object.entries(agents)) {
89
127
  const key = `\`${spec.model}\` [${spec.reasoning_effort ?? ''}]`
90
- if(!groups[key]) groups[key]=[]
128
+ if (!groups[key]) groups[key] = []
91
129
  groups[key].push(agent)
92
130
  }
93
- const papelSummary = Object.entries(groups).map(([model,list])=>`${list.join(',')}: ${model}`).join('<br>')
131
+ const papelSummary = Object.entries(groups)
132
+ .map(([model, list]) => `${list.join(',')}: ${model}`)
133
+ .join('<br>')
94
134
  lines.push(`| \`${name}\` | ${prov} | ${envs} | ${pricing} | ${vision} | ${papelSummary} |`)
95
135
  }
96
136
  return lines.join('\n')
97
137
  }
98
138
 
99
- function buildMatrixTable(){
139
+ function buildMatrixTable() {
100
140
  const presetNames = Object.keys(presets)
101
- const lines=[]
141
+ const lines = []
102
142
  // header
103
- lines.push(`| Agente | ${presetNames.map(n=>`\`${n}\``).join(' | ')} | Capability (vision / maxEffort) |`)
104
- lines.push(`|---|${presetNames.map(()=> '---').join('|')}|---|`)
143
+ lines.push(
144
+ `| Agente | ${presetNames.map((n) => `\`${n}\``).join(' | ')} | Capability (vision / maxEffort) |`,
145
+ )
146
+ lines.push(`|---|${presetNames.map(() => '---').join('|')}|---|`)
105
147
  // collect all agents
106
148
  const allAgents = new Set()
107
- for(const def of Object.values(presets)) for(const a of Object.keys(def.agents ?? {})) allAgents.add(a)
149
+ for (const def of Object.values(presets))
150
+ for (const a of Object.keys(def.agents ?? {})) allAgents.add(a)
108
151
  const sorted = [...allAgents].sort(agentSort)
109
- for(const agent of sorted){
110
- const cells = presetNames.map(presetName=>{
152
+ for (const agent of sorted) {
153
+ const cells = presetNames.map((presetName) => {
111
154
  const spec = presets[presetName]?.agents?.[agent]
112
- if(!spec) return 'β€”'
155
+ if (!spec) return 'β€”'
113
156
  const badge = capabilityBadge(spec.model)
114
157
  const visionIcon = badge.vision ? 'πŸ‘οΈ' : 'β€”'
115
158
  // don't expose raw key, just model and effort
@@ -117,12 +160,14 @@ function buildMatrixTable(){
117
160
  })
118
161
  // capability column: pick first preset's model for reference, but show per-agent vision across presets is same family
119
162
  const sampleModel = presets[presetNames[0]]?.agents?.[agent]?.model ?? ''
120
- let capStr='β€”'
121
- if(sampleModel){
122
- try{
163
+ let capStr = 'β€”'
164
+ if (sampleModel) {
165
+ try {
123
166
  const v = hasVision(sampleModel)
124
167
  capStr = v ? 'vision' : 'text-only'
125
- }catch{ capStr='unknown' }
168
+ } catch {
169
+ capStr = 'unknown'
170
+ }
126
171
  }
127
172
  // Show effort clamp per preset? Instead show generic
128
173
  lines.push(`| \`${agent}\` | ${cells.join(' | ')} | ${capStr} |`)
@@ -130,20 +175,25 @@ function buildMatrixTable(){
130
175
  return lines.join('\n')
131
176
  }
132
177
 
133
- function buildDetailedMatrixWithEffort(){
178
+ function buildDetailedMatrixWithEffort() {
134
179
  const presetNames = Object.keys(presets)
135
- const lines=[]
136
- lines.push(`| Agente | ${presetNames.map(n=>`\`${n}\``).join(' | ')} |`)
137
- lines.push(`|---|${presetNames.map(()=> '---').join('|')}|`)
180
+ const lines = []
181
+ lines.push(`| Agente | ${presetNames.map((n) => `\`${n}\``).join(' | ')} |`)
182
+ lines.push(`|---|${presetNames.map(() => '---').join('|')}|`)
138
183
  const allAgents = new Set()
139
- for(const def of Object.values(presets)) for(const a of Object.keys(def.agents ?? {})) allAgents.add(a)
184
+ for (const def of Object.values(presets))
185
+ for (const a of Object.keys(def.agents ?? {})) allAgents.add(a)
140
186
  const sorted = [...allAgents].sort(agentSort)
141
- for(const agent of sorted){
142
- const cells = presetNames.map(presetName=>{
187
+ for (const agent of sorted) {
188
+ const cells = presetNames.map((presetName) => {
143
189
  const spec = presets[presetName]?.agents?.[agent]
144
- if(!spec) return 'β€”'
190
+ if (!spec) return 'β€”'
145
191
  let vision = 'β€”'
146
- try{ vision = hasVision(spec.model) ? 'πŸ‘οΈ' : 'Β·' }catch{ vision='?' }
192
+ try {
193
+ vision = hasVision(spec.model) ? 'πŸ‘οΈ' : 'Β·'
194
+ } catch {
195
+ vision = '?'
196
+ }
147
197
  return `\`${spec.model}\` [${spec.reasoning_effort}] ${vision}`
148
198
  })
149
199
  lines.push(`| \`${agent}\` | ${cells.join(' | ')} |`)
@@ -151,12 +201,12 @@ function buildDetailedMatrixWithEffort(){
151
201
  return lines.join('\n')
152
202
  }
153
203
 
154
- function buildProviderTable(){
155
- const lines=[]
204
+ function buildProviderTable() {
205
+ const lines = []
156
206
  lines.push('| Preset | Provider | BaseURL | Key env |')
157
207
  lines.push('|---|---|---|---|')
158
- for(const [name,def] of Object.entries(presets)){
159
- for(const [pid,prov] of Object.entries(def.providers ?? {})){
208
+ for (const [name, def] of Object.entries(presets)) {
209
+ for (const [pid, prov] of Object.entries(def.providers ?? {})) {
160
210
  const keyEnvStatus = prov.apiKeyEnv ? 'configured' : 'none'
161
211
  lines.push(`| \`${name}\` | \`${pid}\` | \`${prov.baseURL ?? ''}\` | \`${keyEnvStatus}\` |`)
162
212
  }
@@ -164,59 +214,70 @@ function buildProviderTable(){
164
214
  return lines.join('\n')
165
215
  }
166
216
 
167
- function buildPricingTable(){
168
- const lines=[]
217
+ function buildPricingTable() {
218
+ const lines = []
169
219
  lines.push('| Preset | Pricing 2026 | Detalhe | Gateway / Custo |')
170
220
  lines.push('|---|---|---|---|')
171
- for(const name of Object.keys(presets)){
172
- const p = PRESET_PRICE[name] ?? {label:'β€”',detail:'β€”'}
221
+ for (const name of Object.keys(presets)) {
222
+ const p = PRESET_PRICE[name] ?? { label: 'β€”', detail: 'β€”' }
173
223
  const def = presets[name]
174
224
  const prov = Object.keys(def.providers ?? {}).join(', ')
175
- const costHint = name==='go-free' ? '$0 (free-tier Zen, quota limitada)' : name==='go-fast' ? 'Baixo custo (Go gateway, baixa latΓͺncia)' : name==='go-premium' ? 'Premium (Go gateway, melhor qualidade)' : 'Pago por uso (OpenAI direto)'
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)'
176
233
  lines.push(`| \`${name}\` | ${p.label} | ${p.detail} | ${prov} β€” ${costHint} |`)
177
234
  }
178
235
  return lines.join('\n')
179
236
  }
180
237
 
181
- function buildCapabilityTable(){
182
- const lines=[]
238
+ function buildCapabilityTable() {
239
+ const lines = []
183
240
  lines.push('| Prefix | Max Effort | Vision | Strip Effort |')
184
241
  lines.push('|---|---|---|---|')
185
- for(const e of CAPABILITY_TABLE){
186
- lines.push(`| \`${e.prefix}\` | ${e.maxEffort ?? 'β€”'} | ${e.vision ? 'πŸ‘οΈ' : 'β€”'} | ${e.stripEffort ? 'yes' : 'no'} |`)
242
+ for (const e of CAPABILITY_TABLE) {
243
+ lines.push(
244
+ `| \`${e.prefix}\` | ${e.maxEffort ?? 'β€”'} | ${e.vision ? 'πŸ‘οΈ' : 'β€”'} | ${e.stripEffort ? 'yes' : 'no'} |`,
245
+ )
187
246
  }
188
247
  return lines.join('\n')
189
248
  }
190
249
 
191
250
  const args = process.argv.slice(2)
192
- if(args.includes('--json')){
251
+ if (args.includes('--json')) {
193
252
  const out = { presets, PRESET_PRICE, CAPABILITY_TABLE }
194
- console.log(JSON.stringify(out,null,2))
253
+ console.log(JSON.stringify(out, null, 2))
195
254
  process.exit(0)
196
255
  }
197
- if(args.includes('--summary')){
256
+ if (args.includes('--summary')) {
198
257
  console.log(buildSummaryTable())
199
258
  process.exit(0)
200
259
  }
201
- if(args.includes('--matrix')){
260
+ if (args.includes('--matrix')) {
202
261
  console.log(buildMatrixTable())
203
262
  process.exit(0)
204
263
  }
205
- if(args.includes('--provider')){
264
+ if (args.includes('--provider')) {
206
265
  console.log(buildProviderTable())
207
266
  process.exit(0)
208
267
  }
209
- if(args.includes('--pricing')){
268
+ if (args.includes('--pricing')) {
210
269
  console.log(buildPricingTable())
211
270
  process.exit(0)
212
271
  }
213
- if(args.includes('--capability')){
272
+ if (args.includes('--capability')) {
214
273
  console.log(buildCapabilityTable())
215
274
  process.exit(0)
216
275
  }
217
276
 
218
277
  // default: print all
219
- console.log('<!-- 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 -->')
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
+ )
220
281
  console.log('')
221
282
  console.log('### Presets β€” resumo (provider / baseURL / key / pricing / vision)')
222
283
  console.log('')
@@ -6,7 +6,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
6
  PANTHEON_DIR="$(dirname "$SCRIPT_DIR")"
7
7
 
8
8
  # ── Read active plan ─────────────────────────────────────────────────────────
9
- PLAN_FILE="$PANTHEON_DIR/platform/plans/plan-active.json"
9
+ PLAN_FILE="$PANTHEON_DIR/.pantheon/active-preset.json"
10
10
  if [[ -f "$PLAN_FILE" ]]; then
11
11
  PLAN=$(jq -r '.plan // "unknown"' "$PLAN_FILE")
12
12
  SERVICE=$(jq -r '.service // "unknown"' "$PLAN_FILE")
@@ -38,7 +38,7 @@ else
38
38
  fi
39
39
 
40
40
  # ── List agents ──────────────────────────────────────────────────────────────
41
- AGENTS_DIR="$PANTHEON_DIR/platform/opencode/agents"
41
+ AGENTS_DIR="$PANTHEON_DIR/src/agents"
42
42
  AGENTS_LIST=""
43
43
  if [[ -d "$AGENTS_DIR" ]]; then
44
44
  AGENTS_LIST=$(ls "$AGENTS_DIR"/*.md 2>/dev/null | xargs -n1 basename | sed 's/\.md$//' | sort | paste -sd ', ' -)
@@ -161,7 +161,14 @@ export function printSummary(target, platforms, stats) {
161
161
  if (_quiet) return
162
162
 
163
163
  const line = '\u2500'.repeat(Math.min(process.stdout.columns || 60, 60))
164
- console.log(tag(`${icons.rocket} OpenCode instalado em ${target}`))
164
+ const hasErrors = stats && stats.errors > 0
165
+ console.log(
166
+ tag(
167
+ hasErrors
168
+ ? `${icons.warning} InstalaΓ§Γ£o concluΓ­da com erros em ${target}`
169
+ : `${icons.rocket} OpenCode instalado em ${target}`,
170
+ ),
171
+ )
165
172
  console.log(tag(line))
166
173
  console.log('')
167
174