pantheon-opencode 1.4.3 → 1.5.0-beta.10
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/.pantheon/code-mode/README.md +93 -0
- package/.pantheon/code-mode/checkpoint-session.py +7 -0
- package/.pantheon/code-mode/checkpoint-session.sh +11 -0
- package/.pantheon/code-mode/checkpoint_session.py +481 -0
- package/.pantheon/code-mode/compress-inline.py +450 -0
- package/.pantheon/code-mode/eval-llm-judge.py +255 -0
- package/.pantheon/code-mode/eval-monte-carlo.py +368 -0
- package/.pantheon/code-mode/eval-run.py +197 -0
- package/.pantheon/code-mode/eval-static.py +321 -0
- package/.pantheon/code-mode/example-sync.sh +5 -0
- package/.pantheon/code-mode/manifest.json +21 -0
- package/.pantheon/code-mode/session-end-save.py +186 -0
- package/.pantheon/code-mode/session-end-save.sh +18 -0
- package/.pantheon/code-mode/test-allowed.sh +5 -0
- package/.pantheon/code-mode/test-auto-continue-checkpoint.sh +179 -0
- package/.pantheon/code-mode/test-env.sh +7 -0
- package/.pantheon/code-mode/test-prlimit.sh +9 -0
- package/.pantheon/code-mode/test-timeout.sh +6 -0
- package/CHANGELOG.md +1026 -0
- package/README.md +292 -1080
- package/README.pt-BR.md +308 -0
- package/bin/pantheon-init.mjs +207 -31
- package/opencode.json +1 -0
- package/package.json +34 -14
- package/plugin.json +15 -0
- package/pyproject.toml +65 -0
- package/scripts/_pantheon_paths.py +48 -7
- package/scripts/ci-validate-yaml.py +7 -2
- package/scripts/code_mode_server.py +451 -44
- package/scripts/cost.mjs +30 -14
- package/scripts/doctor.mjs +306 -129
- package/scripts/generate-preset-docs.mjs +127 -66
- package/scripts/generate-prompts.sh +2 -2
- package/scripts/install/cli-ui.mjs +23 -10
- package/scripts/install/config-migration.mjs +399 -0
- package/scripts/install/health-check.mjs +3 -3
- package/scripts/install/model-picker.mjs +72 -23
- package/scripts/install/opencode-version.mjs +47 -0
- package/scripts/install/opencode.mjs +396 -121
- package/scripts/install/plugin.mjs +89 -49
- package/scripts/install/shared.mjs +55 -159
- package/scripts/install/strings.mjs +129 -0
- package/scripts/install-mcp.mjs +45 -232
- package/scripts/manifest-inventory.mjs +410 -0
- package/scripts/mcp_persistence_server.py +798 -60
- package/scripts/mcp_resources_server.py +144 -40
- package/scripts/memory_mcp_server.py +2 -2
- package/scripts/package-evidence.mjs +242 -0
- package/scripts/probe-context-rehydrate.mjs +240 -0
- package/scripts/probe-pantheon-cost.mjs +313 -0
- package/scripts/recover-zenodo-deposition.mjs +146 -0
- package/scripts/release-beta-version.mjs +56 -60
- package/scripts/sync-artifacts.mjs +169 -0
- package/scripts/sync-tui.mjs +135 -42
- package/scripts/test-opencode-v1-v2-sandbox.sh +862 -0
- package/scripts/uninstall.mjs +298 -954
- package/scripts/validate-zenodo-release.mjs +154 -0
- package/scripts/validation-policy.mjs +7 -7
- package/scripts/version-check.mjs +113 -108
- package/scripts/versioning.mjs +230 -86
- package/scripts/zenodo-artifact.mjs +21 -0
- package/scripts/zenodo-release-state.mjs +53 -0
- package/src/agents/mnemosyne.md +1 -1
- package/src/agents/zeus.md +27 -16
- package/src/mcp/_pantheon_paths.py +48 -7
- package/src/mcp/code_mode_server.py +451 -44
- package/src/mcp/eval_store.py +1 -1
- package/src/mcp/mcp_persistence_server.py +798 -60
- package/src/mcp/mcp_resources_server.py +144 -40
- package/src/mcp/pantheon_vision_server.py +1 -1
- package/src/mcp/toon_codec.py +491 -0
- package/src/pantheon/auto-wake.ts +1 -5
- package/src/pantheon/background-job-board.ts +110 -2
- package/src/pantheon/compaction-handoff.ts +304 -0
- package/src/pantheon/cost-command.ts +356 -69
- package/src/pantheon/delegate-manager.ts +766 -0
- package/src/pantheon/delegation-classifier.ts +307 -0
- package/src/pantheon/delegation-enforce.ts +13 -12
- package/src/pantheon/delegation-finalize.ts +406 -0
- package/src/pantheon/delegation-notify.ts +212 -0
- package/src/pantheon/delegation-toast.ts +73 -0
- package/src/pantheon/delegation.ts +1337 -0
- package/src/pantheon/file-persistence-salvage.ts +64 -0
- package/src/pantheon/file-persistence.ts +194 -45
- package/src/pantheon/goal-loop.ts +2 -2
- package/src/pantheon/goal-store.ts +1 -1
- package/src/pantheon/hashline/tool.ts +2 -2
- package/src/pantheon/model-command.ts +2 -1
- package/src/pantheon/native-probe.ts +234 -0
- package/src/pantheon/native-task-status.ts +139 -0
- package/src/pantheon/permission-eval.ts +284 -0
- package/src/pantheon/provider-capabilities.ts +221 -0
- package/src/pantheon/provider-stream-tracker.ts +182 -0
- package/src/pantheon/shared-board.ts +37 -0
- package/src/pantheon/step-cap.ts +110 -0
- package/src/pantheon/task-result-guard.ts +107 -0
- package/src/pantheon/token-opt.ts +689 -0
- package/src/pantheon/tool-ceiling.ts +159 -0
- package/src/pantheon/toon-codec.ts +481 -0
- package/src/pantheon/tui-version-check.ts +1 -3
- package/src/pantheon/v2-bridge.ts +129 -0
- package/src/pantheon/v2-events.ts +148 -0
- package/src/pantheon/v2-hooks.ts +287 -0
- package/src/pantheon/v2-tool-definitions.ts +331 -0
- package/src/pantheon/zeus-delegate-with-retry.ts +406 -0
- package/src/plugin-v2/index.ts +21 -0
- package/src/plugin-v2.ts +824 -0
- package/src/plugin.ts +261 -51
- package/src/plugins/pantheon-hooks.ts +51 -0
- package/src/plugins/tui/dist/tui.d.ts +116 -24
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +416 -149
- package/src/plugins/tui/dist/tui.tsx +456 -87
- package/src/plugins/tui/package-lock.json +51 -51
- package/src/plugins/tui/package.json +7 -7
- package/src/plugins/tui/src/index.tsx +462 -95
- package/src/skills/README.md +0 -2
- package/src/pantheon/tool-context.ts +0 -41
package/README.pt-BR.md
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# Pantheon
|
|
2
|
+
|
|
3
|
+
**Uma forma mais clara de trabalhar com OpenCode em projetos reais.** O
|
|
4
|
+
Pantheon reúne planejamento, implementação, revisão e documentação em uma
|
|
5
|
+
experiência guiada. É um plugin e instalador para OpenCode, feito para pessoas
|
|
6
|
+
e equipes que querem mais estrutura sem perder o controle do próprio código.
|
|
7
|
+
|
|
8
|
+
[English](README.md) ·
|
|
9
|
+
[Repositório](https://github.com/ils15/pantheon-opencode) · [Licença MIT](LICENSE)
|
|
10
|
+
|
|
11
|
+
[](https://github.com/ils15/pantheon-opencode/releases/latest)
|
|
12
|
+
[](https://github.com/ils15/pantheon-opencode/actions)
|
|
13
|
+
[](https://doi.org/10.5281/zenodo.22306637)
|
|
14
|
+
|
|
15
|
+
## O que é?
|
|
16
|
+
|
|
17
|
+
O Pantheon é um companheiro para o [OpenCode](https://opencode.ai/) que ajuda a
|
|
18
|
+
transformar uma ideia em uma alteração revisada. Ele oferece uma forma comum
|
|
19
|
+
de planejar o trabalho, avançar, conferir resultados e preservar o contexto
|
|
20
|
+
útil do projeto.
|
|
21
|
+
|
|
22
|
+
## Por que usar?
|
|
23
|
+
|
|
24
|
+
- **Menos troca de contexto:** planeje e construa no mesmo fluxo.
|
|
25
|
+
- **Alterações mais conscientes:** peça revisões e verificações antes de
|
|
26
|
+
considerar o trabalho concluído.
|
|
27
|
+
- **Um ponto de partida repetível:** use a mesma configuração em projetos e
|
|
28
|
+
com colaboradores diferentes.
|
|
29
|
+
- **Você continua no comando:** o Pantheon apoia suas decisões, mas não
|
|
30
|
+
substitui seu julgamento nem a revisão do código gerado.
|
|
31
|
+
|
|
32
|
+
## Comece em 2 minutos
|
|
33
|
+
|
|
34
|
+
Requisitos: [OpenCode 1.18.4+](https://opencode.ai/docs/) e Node.js 18+.
|
|
35
|
+
|
|
36
|
+
No projeto em que você quer usar o Pantheon:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx pantheon-opencode init
|
|
40
|
+
opencode
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
O instalador orienta você pelas opções disponíveis. Para servidores MCP
|
|
44
|
+
opcionais, instalação local no projeto ou uso sem perguntas, consulte o
|
|
45
|
+
[guia de instalação](docs/INSTALLATION.md).
|
|
46
|
+
|
|
47
|
+
## Um exemplo simples
|
|
48
|
+
|
|
49
|
+
Com o OpenCode em execução, descreva o resultado que você quer:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
/pantheon Adicione exportação CSV à página de relatórios, com testes e revisão.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
O Pantheon ajuda a transformar esse pedido em um plano e em etapas revisadas.
|
|
56
|
+
|
|
57
|
+
## Para quem é?
|
|
58
|
+
|
|
59
|
+
Para desenvolvedores, mantenedores e equipes que usam OpenCode e querem uma
|
|
60
|
+
forma mais consistente de lidar com correções pequenas e mudanças maiores. É
|
|
61
|
+
especialmente útil quando o projeto se beneficia de decisões registradas,
|
|
62
|
+
verificações repetíveis e passagens claras entre etapas do trabalho.
|
|
63
|
+
|
|
64
|
+
## O que inclui?
|
|
65
|
+
|
|
66
|
+
- Um instalador guiado para disponibilizar o Pantheon no OpenCode.
|
|
67
|
+
- Instruções e comandos reutilizáveis para planejar, construir, revisar e
|
|
68
|
+
documentar o trabalho.
|
|
69
|
+
- Memória de projeto para preservar contexto relevante entre sessões.
|
|
70
|
+
- Integrações opcionais para tarefas comuns de desenvolvimento.
|
|
71
|
+
|
|
72
|
+
## Status
|
|
73
|
+
|
|
74
|
+
Versão operacional neste checkout: **v1.5.0-beta.2** (candidata; esta página
|
|
75
|
+
não afirma publicação). O Pantheon foi feito para OpenCode e depende da
|
|
76
|
+
disponibilidade e da configuração do OpenCode e dos serviços opcionais que você
|
|
77
|
+
escolher. Veja as [releases](https://github.com/ils15/pantheon-opencode/releases)
|
|
78
|
+
e o [changelog](CHANGELOG.md) para acompanhar as mudanças publicadas.
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## Execução code-mode (opt-in explícito)
|
|
82
|
+
|
|
83
|
+
Scripts executados pelo MCP server `pantheon-code-mode` (`execute_code_script`)
|
|
84
|
+
só rodam quando aprovados explicitamente. A aprovação fica em
|
|
85
|
+
`.pantheon/code-mode/manifest.json` com o SHA-256 de cada script.
|
|
86
|
+
|
|
87
|
+
- **Sem manifest → nada executa** (`INVALID_STATE`); nunca há execução implícita.
|
|
88
|
+
- **Script fora do manifest → `CONFLICT`**; é preciso aprovar antes.
|
|
89
|
+
- **Hash divergente → `CORRUPT_DATA`**; edições após a aprovação são detectadas.
|
|
90
|
+
|
|
91
|
+
Aprove (ou reaprove) um script com a tool `approve_code_script`. O instalador
|
|
92
|
+
semeia o manifest com o hash de todos os scripts empacotados. Os resultados
|
|
93
|
+
seguem o contrato de nove códigos (`OK`, `UNSUPPORTED`, `UNAVAILABLE`,
|
|
94
|
+
`INVALID_INPUT`, `INVALID_STATE`, `CONFLICT`, `CORRUPT_DATA`, `TIMEOUT`,
|
|
95
|
+
`ESCALATE`) e, com `json_output=true`, incluem o campo `status`.
|
|
96
|
+
|
|
97
|
+
O code-mode resolve primeiro o projeto: `.opencode/.pantheon/code-mode` vem
|
|
98
|
+
antes de `.pantheon/code-mode`. `PANTHEON_PROJECT` sobrescreve o diretório de
|
|
99
|
+
trabalho, e o MCP instalado usa `cwd: "."` para receber o workspace do
|
|
100
|
+
OpenCode. O diretório global só é usado sem um diretório de projeto utilizável;
|
|
101
|
+
depois de selecionar um diretório de projeto, manifest ausente ou corrompido
|
|
102
|
+
falha fechado, sem fallback silencioso. O `doctor` valida o manifest e o
|
|
103
|
+
SHA-256 de cada script sem regenerá-lo.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
## Novidades da 1.5.0-beta.2
|
|
107
|
+
|
|
108
|
+
- Instalador exclusivo para OpenCode: guias de plataformas consolidados em um
|
|
109
|
+
único [guia OpenCode](docs/platforms/opencode.md).
|
|
110
|
+
- Novo CLI `uninstall` com escopos project/global e checagem de ownership:
|
|
111
|
+
`node scripts/uninstall.mjs --project|--global [--dry-run] [--force]`.
|
|
112
|
+
- Recursos MCP endurecidos: correção do `pantheon://agents` e proteção contra
|
|
113
|
+
symlink/traversal nos caminhos de recursos.
|
|
114
|
+
- Compatibilidade com OpenCode V2: merge de configuração `plugins` /
|
|
115
|
+
`mcp.servers.enabled` e launch stdio MCP com PWD correto.
|
|
116
|
+
- `doctor` e health checks de instalação expandidos.
|
|
117
|
+
- Validador de sandbox para instalações globais
|
|
118
|
+
(`scripts/test-opencode-v1-v2-sandbox.sh`) cobrindo OpenCode V1/V2 lado a
|
|
119
|
+
lado — veja [Validação em sandbox](#validação-em-sandbox-v1v2).
|
|
120
|
+
- A flag `--prompts` do instalador está planejada para uma release futura.
|
|
121
|
+
|
|
122
|
+
## OpenCode V1/V2 — Versão dupla (1.5.0-beta.2)
|
|
123
|
+
|
|
124
|
+
O Pantheon tem dois contratos de plugin OpenCode **exclusivos**. A configuração
|
|
125
|
+
comum do OpenCode pode ser compartilhada, mas o registro do plugin Pantheon é
|
|
126
|
+
selecionado por instalação; os plugins Pantheon V1 e V2 nunca devem ser
|
|
127
|
+
registrados juntos.
|
|
128
|
+
|
|
129
|
+
| | V1 | V2 |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| Chave de config do OpenCode | `plugin` singular | `plugins` plural |
|
|
132
|
+
| Registro Pantheon | `src/plugin.ts` mais `src/plugins/pantheon-hooks.ts` | `pantheon-opencode/plugin-v2` (`src/plugin-v2.ts`) |
|
|
133
|
+
| Contrato de runtime | Plugin Pantheon legado, incluindo `pantheon_delegate`, ferramentas read/list, hooks de evento/ferramenta e tratamento de compactação V1 | Plugin V2 completo: 9 ferramentas de orquestração, 4 assinaturas de eventos, session hooks (`prompt`, `context`), tool hooks (`execute.before`/`after`), além de transforms de configuração |
|
|
134
|
+
| APIs V1 | Registradas | Definições próprias de ferramentas via `ctx.tool.transform()` — não pelo caminho do plugin V1 |
|
|
135
|
+
|
|
136
|
+
O plugin V2 fornece 9 ferramentas de orquestração (`pantheon_delegate`,
|
|
137
|
+
`pantheon_delegation_read`, `pantheon_delegation_list`, `hashline_edit`,
|
|
138
|
+
`pantheon_goal_create`, `pantheon_goal_get`, `pantheon_goal_update`,
|
|
139
|
+
`pantheon_cost`, `pantheon_model`), 4 assinaturas de eventos (`session.created`,
|
|
140
|
+
`session.idle`, `session.error`, `session.compacted`), session hooks (`prompt`,
|
|
141
|
+
`context`) e tool hooks (`execute.before`, `execute.after`). O único recurso V2
|
|
142
|
+
sem suporte é `legacy-hooks` (a superfície de API de delegate específica do V1).
|
|
143
|
+
|
|
144
|
+
O pacote expõe os dois contratos como exports importáveis:
|
|
145
|
+
`pantheon-opencode/plugin` (V1), `pantheon-opencode/plugin-v2` (V2) e
|
|
146
|
+
`pantheon-opencode/v2-bridge` (interop opcional), para que o host carregue
|
|
147
|
+
explicitamente o contrato desejado.
|
|
148
|
+
|
|
149
|
+
A ponte V1→V2 (`src/pantheon/v2-bridge.ts`) habilita interop opcional:
|
|
150
|
+
singletons de infraestrutura V1 (BackgroundJobBoard, DelegationClient,
|
|
151
|
+
GoalStore, TodoEnforcer, VisionHandler) são repassados via `ctx.options` do V2.
|
|
152
|
+
A ponte é opcional — o V2 funciona standalone com degradação graciosa.
|
|
153
|
+
|
|
154
|
+
Selecione o contrato explicitamente na instalação:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npx pantheon-opencode init --opencode-version v1
|
|
158
|
+
npx pantheon-opencode init --opencode-version v2
|
|
159
|
+
npx pantheon-opencode init --opencode-version auto
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`--version v1|v2|auto` é aceito como a grafia antiga do seletor quando usado
|
|
163
|
+
depois de `init`. `auto` é conservador, não uma autodetecção geral de
|
|
164
|
+
plataforma: `OPENCODE_VERSION=v1|v2` vence; caso contrário, um `OPENCODE_BIN`
|
|
165
|
+
terminando em `opencode2` seleciona V2; qualquer outro caso seleciona V1. O
|
|
166
|
+
instalador remove referências Pantheon das duas formas de config antes de
|
|
167
|
+
gravar apenas o registro Pantheon selecionado. Entradas de terceiros não são
|
|
168
|
+
convertidas nem reivindicadas por essa regra.
|
|
169
|
+
|
|
170
|
+
O relatório `pantheon_cost`, disponível nos plugins V1 e V2, pode selecionar o banco com
|
|
171
|
+
`PANTHEON_OPENCODE_VERSION=v1` ou `v2` (`opencode.db` ou `opencode-v2.db`).
|
|
172
|
+
`PANTHEON_COST_DB=/caminho/absoluto/para/opencode.db` tem precedência sobre o
|
|
173
|
+
seletor de versão, e um `dbPath` explícito fornecido pelo chamador da
|
|
174
|
+
ferramenta tem precedência sobre ambos. O resolver nunca consulta o banco da
|
|
175
|
+
outra versão e reporta um erro acionável quando o banco selecionado está
|
|
176
|
+
ausente ou com schema incompatível.
|
|
177
|
+
|
|
178
|
+
O instalador continua gravando as configurações de compatibilidade exigidas
|
|
179
|
+
pelo host OpenCode selecionado, como `experimental.subagent_depth`; isso não
|
|
180
|
+
converte um plugin V1 em V2 nem dá hooks V1 ao V2.
|
|
181
|
+
|
|
182
|
+
## Atualizando entre releases (beta.5+)
|
|
183
|
+
|
|
184
|
+
Um comando mantém uma instalação existente em dia:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Sem instalação global, SEMPRE fixe o dist-tag — `npx pantheon-opencode`
|
|
188
|
+
# puro resolve a tag `latest`, que é o release estável (1.4.3):
|
|
189
|
+
npx pantheon-opencode@beta update # canal beta do npm + refresh do config
|
|
190
|
+
npx pantheon-opencode@beta update --stable # canal estável
|
|
191
|
+
|
|
192
|
+
# Com instalação global, use o bin global (o padrão é o canal beta):
|
|
193
|
+
pantheon-opencode update
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
O `update` compara a versão instalada com o dist-tag do npm, roda
|
|
197
|
+
`npm install -g pantheon-opencode@<canal>` e re-executa `init --yes
|
|
198
|
+
--headless` para alinhar merge de config, venv e entradas de MCP com o novo
|
|
199
|
+
pacote. Duas garantias de freshness sustentam isso:
|
|
200
|
+
|
|
201
|
+
- **Sync de artifacts no postinstall** — depois de qualquer `npm install`, os
|
|
202
|
+
artefatos de cópia (agents, skills, AGENTS.md, commands, scripts MCP,
|
|
203
|
+
payload code-mode) são atualizados automaticamente no config dir existente;
|
|
204
|
+
você nunca precisa re-rodar `init` só para atualizar arquivos.
|
|
205
|
+
- **Detecção de drift** — o instalador grava a versão instalada em
|
|
206
|
+
`.pantheon/install-state.json` e o `doctor` avisa quando o pacote é mais
|
|
207
|
+
novo que o último sync, apontando para o `update`.
|
|
208
|
+
|
|
209
|
+
O `init` também ganhou `--components agents,skills,...` (instalação enxuta),
|
|
210
|
+
`--clean` (alias de `--force`), `--opencode-version auto`, escrita atômica do
|
|
211
|
+
config com backup em `opencode.json.bak`, pré-checagens de python3/npm antes
|
|
212
|
+
de escrever qualquer arquivo e runtime Python não-fatal: se a venv falha, a
|
|
213
|
+
instalação completa mas as entradas MCP ficam de fora (com aviso) em vez de
|
|
214
|
+
apontar para um interpretador quebrado.
|
|
215
|
+
|
|
216
|
+
## Releases
|
|
217
|
+
|
|
218
|
+
A publicação é autorizada **somente** por um `workflow_dispatch` explícito do
|
|
219
|
+
workflow `Release` (o input `release_channel` escolhe beta ou stable). Labels
|
|
220
|
+
de PR, push, merge e tag nunca publicam nada, e todos os gates de validação são
|
|
221
|
+
fail-closed: somente um PASS explícito autoriza release evidence. Consulte
|
|
222
|
+
[docs/RELEASING.md](docs/RELEASING.md) para detalhes de validação e recuperação.
|
|
223
|
+
|
|
224
|
+
A validação mantém cada manifest junto do seu lockfile: o root
|
|
225
|
+
`package.json` + `package-lock.json` e o TUI
|
|
226
|
+
`src/plugins/tui/package.json` + `src/plugins/tui/package-lock.json`. Ambos usam
|
|
227
|
+
`npm ci --ignore-scripts`; uma falha em `npm ci` bloqueia a execução e não há
|
|
228
|
+
fallback para `npm install`. Uma release carrega um único tarball `.tgz`, calcula
|
|
229
|
+
o SHA-256 desse mesmo artefato e vincula o tarball e o GitHub Release ao
|
|
230
|
+
`TARGET_SHA` completo; um segundo pack não é intercambiável.
|
|
231
|
+
|
|
232
|
+
## Validação em sandbox (V1/V2)
|
|
233
|
+
|
|
234
|
+
O `scripts/test-opencode-v1-v2-sandbox.sh` valida o pacote instalado
|
|
235
|
+
globalmente como um usuário real dentro de um sandbox isolado (com `HOME`,
|
|
236
|
+
prefix npm e venv próprios) — nunca o ambiente de desenvolvimento. Ele verifica
|
|
237
|
+
OpenCode V1 (`opencode`) e V2 (`opencode2`) lado a lado: binários, conectividade
|
|
238
|
+
MCP, `doctor` e — com `--prompts` — uma bateria de prompts cobrindo o recurso
|
|
239
|
+
`pantheon://agents`, memory store/recall, escrita no filesystem e delegação de
|
|
240
|
+
agente. O gate é fail-closed: todo check obrigatório precisa terminar em PASS
|
|
241
|
+
explícito; timeout, falha de auth/rede/provider e pré-requisitos ausentes
|
|
242
|
+
bloqueiam a execução.
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
scripts/test-opencode-v1-v2-sandbox.sh --prepare # tarball + install + init no sandbox
|
|
246
|
+
scripts/test-opencode-v1-v2-sandbox.sh --run v1 --prompts # validação base + bateria de prompts (V1)
|
|
247
|
+
scripts/test-opencode-v1-v2-sandbox.sh --run v2 # apenas validação base (V2)
|
|
248
|
+
scripts/test-opencode-v1-v2-sandbox.sh --prompts # bateria de prompts para as duas versões
|
|
249
|
+
scripts/test-opencode-v1-v2-sandbox.sh --reset # limpa a raiz do sandbox
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Os modos são combináveis (ex.: `--prepare --run v1 --prompts`). Os binários são
|
|
253
|
+
resolvidos estritamente dentro do prefix npm do sandbox — um sandbox não
|
|
254
|
+
preparado falha rápido em vez de testar silenciosamente a instalação do host.
|
|
255
|
+
|
|
256
|
+
Isso valida somente o sandbox isolado e preparado. Um PASS não prova suporte
|
|
257
|
+
para todo host real nem para configurações de host que não foram exercitadas.
|
|
258
|
+
|
|
259
|
+
Variáveis de ambiente:
|
|
260
|
+
|
|
261
|
+
| Variável | Padrão | Finalidade |
|
|
262
|
+
|----------|---------|---------|
|
|
263
|
+
| `PANTHEON_SANDBOX_ROOT` | `~/pantheon-sandbox` | Raiz do sandbox (recusada se insegura para `--reset`) |
|
|
264
|
+
| `OPENCODE_V1_SPEC` | `opencode-ai@1.18.18` | Spec npm que fornece o binário `opencode` |
|
|
265
|
+
| `OPENCODE_V2_SPEC` | `@opencode-ai/cli@beta` | Spec npm que fornece o binário `opencode2` |
|
|
266
|
+
| `PANTHEON_SANDBOX_MODEL` | `opencode-go/mimo-v2.5` | Modelo usado pelo init e pelos prompts |
|
|
267
|
+
| `PANTHEON_PROMPT_TIMEOUT` | `300` | Timeout por prompt em segundos |
|
|
268
|
+
|
|
269
|
+
Códigos de saída: `0` sem falhas reais · `1` falha real (veja
|
|
270
|
+
`prompts-report.md` na raiz do sandbox) · `2` erro de uso · `3` sandbox não
|
|
271
|
+
preparado.
|
|
272
|
+
|
|
273
|
+
### Divergência intencional do memory MCP
|
|
274
|
+
|
|
275
|
+
`scripts/memory_mcp_server.py` e `src/mcp/memory_mcp_server.py` são
|
|
276
|
+
intencionalmente diferentes. A cópia independente em `scripts/` mantém o
|
|
277
|
+
contrato leve de `memory_*`; a cópia instalada em `src/mcp/` também expõe o
|
|
278
|
+
schema opcional de codemap e `code_index`, `code_query` e `code_neighbors`. As
|
|
279
|
+
outras cópias compartilhadas permanecem idênticas. Não sobrescreva uma cópia de
|
|
280
|
+
memória com a outra.
|
|
281
|
+
|
|
282
|
+
## Documentação
|
|
283
|
+
|
|
284
|
+
- [Instalação](docs/INSTALLATION.md) · [Início rápido](docs/QUICKSTART.md)
|
|
285
|
+
- [Arquitetura](docs/ARCHITECTURE.md) · [Ferramentas MCP](docs/mcp-tools.md)
|
|
286
|
+
- [Plataformas](docs/PLATFORMS.md) · [Atualização](docs/UPGRADING.pt-BR.md)
|
|
287
|
+
- [Referência de agentes](docs/agents/README.md) · [Referência de skills](src/skills/README.md)
|
|
288
|
+
- [Processo de release](docs/RELEASING.md) · [Contribuição](CONTRIBUTING.md)
|
|
289
|
+
- [Changelog](CHANGELOG.md)
|
|
290
|
+
|
|
291
|
+
## Contribua
|
|
292
|
+
|
|
293
|
+
Ideias, relatos de problemas, melhorias na documentação e contribuições de
|
|
294
|
+
código são bem-vindos. Leia [CONTRIBUTING.md](CONTRIBUTING.md) antes de abrir
|
|
295
|
+
uma issue ou pull request.
|
|
296
|
+
|
|
297
|
+
## Citação e DOI
|
|
298
|
+
|
|
299
|
+
O Pantheon é distribuído sob a [Licença MIT](LICENSE). Para o registro histórico
|
|
300
|
+
publicado da v1.4.3 apenas, use o [DOI do Zenodo](https://doi.org/10.5281/zenodo.22306637);
|
|
301
|
+
essa não é a versão operacional atual. Os metadados de citação também estão em
|
|
302
|
+
[CITATION.cff](CITATION.cff).
|
|
303
|
+
|
|
304
|
+
Repositório canônico: <https://github.com/ils15/pantheon-opencode>
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
[Read in English](README.md)
|
package/bin/pantheon-init.mjs
CHANGED
|
@@ -14,17 +14,18 @@
|
|
|
14
14
|
* install for the operator; state isolation is a runtime concern
|
|
15
15
|
* (OPENCODE_DB ~/.local/share/opencode/opencode-v2.db, service port 49375).
|
|
16
16
|
*/
|
|
17
|
-
import fs from 'fs'
|
|
18
|
-
import os from 'os'
|
|
19
|
-
import path from 'path'
|
|
20
|
-
import { fileURLToPath } from 'url'
|
|
17
|
+
import fs from 'node:fs'
|
|
18
|
+
import os from 'node:os'
|
|
19
|
+
import path from 'node:path'
|
|
20
|
+
import { fileURLToPath } from 'node:url'
|
|
21
21
|
|
|
22
22
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
23
23
|
const ROOT = path.resolve(__dirname, '..')
|
|
24
24
|
|
|
25
|
-
const REQUIRED_NODE_MAJOR =
|
|
25
|
+
const REQUIRED_NODE_MAJOR = 22
|
|
26
26
|
if (parseInt(process.versions.node.split('.')[0], 10) < REQUIRED_NODE_MAJOR) {
|
|
27
27
|
console.error(`❌ Node.js >= ${REQUIRED_NODE_MAJOR} required (current: ${process.versions.node})`)
|
|
28
|
+
console.error(' Install a newer Node via nvm: https://github.com/nvm-sh/nvm')
|
|
28
29
|
process.exit(1)
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -50,15 +51,21 @@ function printUsage() {
|
|
|
50
51
|
console.log(' npx pantheon-opencode init --interactive # Force interactive TUI mode')
|
|
51
52
|
console.log(' npx pantheon-opencode init --headless # Force non-interactive mode')
|
|
52
53
|
console.log(' npx pantheon-opencode init -y # Skip confirmations, use defaults')
|
|
53
|
-
console.log(' npx pantheon-opencode init --
|
|
54
|
+
console.log(' npx pantheon-opencode init --components agents,skills,instructions')
|
|
55
|
+
console.log(' npx pantheon-opencode init --opencode-version v1|v2|auto')
|
|
54
56
|
console.log(' npx pantheon-opencode init --preset <name> # Install and activate model preset')
|
|
55
57
|
console.log(' npx pantheon-opencode set-tier <name> # Set active model preset (global)')
|
|
58
|
+
console.log(
|
|
59
|
+
' npx pantheon-opencode update [--stable] # Update package + re-run init (default: beta channel)',
|
|
60
|
+
)
|
|
56
61
|
console.log(
|
|
57
62
|
' npx pantheon-opencode set-tier <name> --project # Set active model preset (project)',
|
|
58
63
|
)
|
|
59
64
|
console.log(' npx pantheon-opencode prune # List legacy artifacts (dry-run)')
|
|
60
65
|
console.log(' npx pantheon-opencode prune --apply # Remove stale backups')
|
|
61
66
|
console.log(' npx pantheon-opencode doctor [--profile] # Run health check')
|
|
67
|
+
console.log(' npx pantheon-opencode uninstall --project # Remove project artifacts safely')
|
|
68
|
+
console.log(' npx pantheon-opencode uninstall --global # Remove global artifacts safely')
|
|
62
69
|
console.log(' npx pantheon-opencode --version, -v # Print version and exit')
|
|
63
70
|
console.log(' npx pantheon-opencode --help # Show this help')
|
|
64
71
|
}
|
|
@@ -78,11 +85,21 @@ async function main() {
|
|
|
78
85
|
// prune handles its own --help (delegated to scripts/prune.mjs), so its
|
|
79
86
|
// dispatch must run BEFORE the generic --help check.
|
|
80
87
|
if (command === 'prune') {
|
|
81
|
-
const { spawnSync } = await import('child_process')
|
|
88
|
+
const { spawnSync } = await import('node:child_process')
|
|
82
89
|
const pruneScript = path.join(ROOT, 'scripts', 'prune.mjs')
|
|
83
90
|
const result = spawnSync(process.execPath, [pruneScript, ...args.slice(1)], {
|
|
84
91
|
stdio: 'inherit',
|
|
85
|
-
cwd:
|
|
92
|
+
cwd: process.cwd(),
|
|
93
|
+
})
|
|
94
|
+
process.exit(result.status ?? 1)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (command === 'uninstall') {
|
|
98
|
+
const { spawnSync } = await import('node:child_process')
|
|
99
|
+
const uninstallScript = path.join(ROOT, 'scripts', 'uninstall.mjs')
|
|
100
|
+
const result = spawnSync(process.execPath, [uninstallScript, ...args.slice(1)], {
|
|
101
|
+
stdio: 'inherit',
|
|
102
|
+
cwd: process.cwd(),
|
|
86
103
|
})
|
|
87
104
|
process.exit(result.status ?? 1)
|
|
88
105
|
}
|
|
@@ -91,7 +108,7 @@ async function main() {
|
|
|
91
108
|
// Forwarding the FULL args (profile, target, --fix, ...) keeps the packaged
|
|
92
109
|
// CLI a thin wrapper; the doctor banner reports the resolved profile.
|
|
93
110
|
if (command === 'doctor') {
|
|
94
|
-
const { spawnSync } = await import('child_process')
|
|
111
|
+
const { spawnSync } = await import('node:child_process')
|
|
95
112
|
const doctorScript = path.join(ROOT, 'scripts', 'doctor.mjs')
|
|
96
113
|
const result = spawnSync(process.execPath, [doctorScript, ...args.slice(1)], {
|
|
97
114
|
stdio: 'inherit',
|
|
@@ -100,6 +117,78 @@ async function main() {
|
|
|
100
117
|
process.exit(result.status ?? 1)
|
|
101
118
|
}
|
|
102
119
|
|
|
120
|
+
// beta.5: one-command update — check npm dist-tag, install, re-init.
|
|
121
|
+
// Default channel is `beta` (the prerelease line); `--stable` uses `latest`.
|
|
122
|
+
if (command === 'update') {
|
|
123
|
+
const channel = args.includes('--stable') ? 'latest' : 'beta'
|
|
124
|
+
const current = readVersion()
|
|
125
|
+
const { spawnSync } = await import('node:child_process')
|
|
126
|
+
const _S = (await import('../scripts/install/strings.mjs')).strings()
|
|
127
|
+
|
|
128
|
+
console.log(`Pantheon OpenCode v${current} — checking the "${channel}" channel...`)
|
|
129
|
+
const view = spawnSync('npm', ['view', `pantheon-opencode@${channel}`, 'version'], {
|
|
130
|
+
encoding: 'utf8',
|
|
131
|
+
timeout: 30_000,
|
|
132
|
+
})
|
|
133
|
+
const latest = (view.stdout || '').trim().split('\n').filter(Boolean).pop()
|
|
134
|
+
if (view.status !== 0 || !latest) {
|
|
135
|
+
console.error(
|
|
136
|
+
`❌ Could not reach the npm registry: ${(view.stderr || view.stdout || '').trim() || 'no version returned'}`,
|
|
137
|
+
)
|
|
138
|
+
process.exit(1)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Prerelease-aware compare: core (major.minor.patch) first, then the
|
|
142
|
+
// beta counter; a stable release outranks any beta of the same core.
|
|
143
|
+
const parsePantheonVersion = (v) => {
|
|
144
|
+
const m = String(v)
|
|
145
|
+
.trim()
|
|
146
|
+
.match(/^(\d+)\.(\d+)\.(\d+)(?:-beta\.(\d+))?$/)
|
|
147
|
+
if (!m) return null
|
|
148
|
+
return {
|
|
149
|
+
core: [+m[1], +m[2], +m[3]],
|
|
150
|
+
beta: m[4] === undefined ? Number.POSITIVE_INFINITY : +m[4],
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const cmp = (a, b) => {
|
|
154
|
+
const pa = parsePantheonVersion(a)
|
|
155
|
+
const pb = parsePantheonVersion(b)
|
|
156
|
+
if (!pa || !pb) return 0
|
|
157
|
+
for (let i = 0; i < 3; i++) {
|
|
158
|
+
if (pa.core[i] !== pb.core[i]) return pa.core[i] - pb.core[i]
|
|
159
|
+
}
|
|
160
|
+
return pa.beta - pb.beta
|
|
161
|
+
}
|
|
162
|
+
if (cmp(latest, current) <= 0) {
|
|
163
|
+
console.log(`✅ Already up to date (installed v${current}; ${channel} channel: v${latest}).`)
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
console.log(`Updating v${current} → v${latest} (channel: ${channel})...`)
|
|
168
|
+
const install = spawnSync('npm', ['install', '-g', `pantheon-opencode@${channel}`], {
|
|
169
|
+
stdio: 'inherit',
|
|
170
|
+
})
|
|
171
|
+
if (install.status !== 0) {
|
|
172
|
+
console.error('❌ npm install failed — the previous installation is untouched.')
|
|
173
|
+
process.exit(install.status ?? 1)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Refresh config/venv/MCP entries with the NEW package (resolved via
|
|
177
|
+
// PATH — the freshly installed global bin).
|
|
178
|
+
const init = spawnSync('pantheon-opencode', ['init', '--yes', '--headless'], {
|
|
179
|
+
stdio: 'inherit',
|
|
180
|
+
shell: process.platform === 'win32',
|
|
181
|
+
})
|
|
182
|
+
if (init.status !== 0 || init.error) {
|
|
183
|
+
console.error(
|
|
184
|
+
'⚠️ Updated, but the config refresh did not complete — run `npx pantheon-opencode init` manually.',
|
|
185
|
+
)
|
|
186
|
+
process.exit(init.status ?? 1)
|
|
187
|
+
}
|
|
188
|
+
console.log(`✅ Updated to v${latest}.`)
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
103
192
|
if (args.includes('--help')) {
|
|
104
193
|
printUsage()
|
|
105
194
|
process.exit(0)
|
|
@@ -183,11 +272,49 @@ async function main() {
|
|
|
183
272
|
const isProject = args.includes('--project')
|
|
184
273
|
const isDryRun = args.includes('--dry-run')
|
|
185
274
|
const skipMCP = args.includes('--no-mcp')
|
|
186
|
-
|
|
275
|
+
// --clean is an alias of --force (both wipe component dirs + recreate venv).
|
|
276
|
+
const forceReinstall = args.includes('--force') || args.includes('--clean')
|
|
187
277
|
const runDoctor = args.includes('--doctor')
|
|
188
278
|
const forceInteractive = args.includes('--interactive')
|
|
189
279
|
const forceHeadless = args.includes('--headless')
|
|
190
280
|
const autoYes = args.includes('--yes') || args.includes('-y')
|
|
281
|
+
|
|
282
|
+
// beta.5: warn on unrecognized flags instead of silently ignoring them.
|
|
283
|
+
const VALUE_FLAGS = new Set([
|
|
284
|
+
'--preset',
|
|
285
|
+
'--model',
|
|
286
|
+
'--small-model',
|
|
287
|
+
'--version',
|
|
288
|
+
'--opencode-version',
|
|
289
|
+
'--components',
|
|
290
|
+
])
|
|
291
|
+
for (let i = 1; i < args.length; i++) {
|
|
292
|
+
const arg = args[i]
|
|
293
|
+
if (!arg.startsWith('--') || arg === '--help') continue
|
|
294
|
+
if (VALUE_FLAGS.has(arg)) {
|
|
295
|
+
i++ // skip the flag's value
|
|
296
|
+
continue
|
|
297
|
+
}
|
|
298
|
+
const bare = arg.split('=', 1)[0]
|
|
299
|
+
if (
|
|
300
|
+
!VALUE_FLAGS.has(bare) &&
|
|
301
|
+
![
|
|
302
|
+
'--project',
|
|
303
|
+
'--dry-run',
|
|
304
|
+
'--no-mcp',
|
|
305
|
+
'--force',
|
|
306
|
+
'--clean',
|
|
307
|
+
'--doctor',
|
|
308
|
+
'--interactive',
|
|
309
|
+
'--headless',
|
|
310
|
+
'--yes',
|
|
311
|
+
'-y',
|
|
312
|
+
].includes(bare)
|
|
313
|
+
) {
|
|
314
|
+
console.error(`⚠️ Unknown option ignored: ${arg}`)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
191
318
|
const presetIndex = args.indexOf('--preset')
|
|
192
319
|
const presetOpt = presetIndex >= 0 ? (args[presetIndex + 1] ?? null) : null
|
|
193
320
|
// Explicit top-level model overrides for the generated config.
|
|
@@ -195,24 +322,73 @@ async function main() {
|
|
|
195
322
|
const modelOpt = modelIndex >= 0 ? (args[modelIndex + 1] ?? null) : null
|
|
196
323
|
const smallModelIndex = args.indexOf('--small-model')
|
|
197
324
|
const smallModelOpt = smallModelIndex >= 0 ? (args[smallModelIndex + 1] ?? null) : null
|
|
198
|
-
// --version v1|v2 labels the install target
|
|
199
|
-
//
|
|
325
|
+
// --version v1|v2|auto labels the install target. `auto` resolves the
|
|
326
|
+
// generation from the opencode binary at install time (see
|
|
327
|
+
// scripts/install/opencode-version.mjs). Invalid values fail fast.
|
|
200
328
|
const versionIndex = args.indexOf('--version')
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
329
|
+
const legacyVersionIndex = args.indexOf('--opencode-version')
|
|
330
|
+
const inlineVersion = args.find((arg) => arg.startsWith('--opencode-version='))
|
|
331
|
+
const versionOpt =
|
|
332
|
+
versionIndex >= 0
|
|
333
|
+
? (args[versionIndex + 1] ?? null)
|
|
334
|
+
: legacyVersionIndex >= 0
|
|
335
|
+
? (args[legacyVersionIndex + 1] ?? null)
|
|
336
|
+
: (inlineVersion?.split('=', 2)[1] ?? null)
|
|
337
|
+
if (
|
|
338
|
+
versionOpt !== null &&
|
|
339
|
+
versionOpt !== 'v1' &&
|
|
340
|
+
versionOpt !== 'v2' &&
|
|
341
|
+
versionOpt !== 'auto'
|
|
342
|
+
) {
|
|
343
|
+
console.error(`❌ Invalid --version "${versionOpt}" — expected v1, v2 or auto`)
|
|
204
344
|
process.exit(1)
|
|
205
345
|
}
|
|
206
346
|
|
|
207
|
-
|
|
208
|
-
|
|
347
|
+
// --components agents,skills,... narrows the install; --no-mcp drops the
|
|
348
|
+
// runtime component. Unknown component names fail fast (typo protection).
|
|
349
|
+
const KNOWN_COMPONENTS = ['agents', 'skills', 'instructions', 'commands', 'plugins', 'runtime']
|
|
350
|
+
const componentsIndex = args.indexOf('--components')
|
|
351
|
+
const inlineComponents = args.find((arg) => arg.startsWith('--components='))
|
|
352
|
+
const componentsOpt =
|
|
353
|
+
componentsIndex >= 0
|
|
354
|
+
? (args[componentsIndex + 1] ?? null)
|
|
355
|
+
: (inlineComponents?.split('=', 2)[1] ?? null)
|
|
356
|
+
let requestedComponents = null
|
|
357
|
+
if (componentsOpt !== null) {
|
|
358
|
+
requestedComponents = componentsOpt
|
|
359
|
+
.split(',')
|
|
360
|
+
.map((c) => c.trim())
|
|
361
|
+
.filter(Boolean)
|
|
362
|
+
const unknown = requestedComponents.filter((c) => !KNOWN_COMPONENTS.includes(c))
|
|
363
|
+
if (requestedComponents.length === 0 || unknown.length > 0) {
|
|
364
|
+
console.error(
|
|
365
|
+
`❌ Invalid --components "${componentsOpt}" — expected comma-separated names from: ${KNOWN_COMPONENTS.join(', ')}`,
|
|
366
|
+
)
|
|
367
|
+
process.exit(1)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const components = requestedComponents ?? [
|
|
372
|
+
'agents',
|
|
373
|
+
'skills',
|
|
374
|
+
'instructions',
|
|
375
|
+
'commands',
|
|
376
|
+
'plugins',
|
|
377
|
+
]
|
|
378
|
+
if (!skipMCP && !components.includes('runtime')) components.push('runtime')
|
|
379
|
+
if (skipMCP) {
|
|
380
|
+
const runtimeIndex = components.indexOf('runtime')
|
|
381
|
+
if (runtimeIndex >= 0) components.splice(runtimeIndex, 1)
|
|
382
|
+
}
|
|
209
383
|
|
|
210
384
|
// Version info
|
|
211
385
|
const version = readVersion()
|
|
386
|
+
const { strings } = await import('../scripts/install/strings.mjs')
|
|
387
|
+
const S = strings()
|
|
212
388
|
|
|
213
389
|
console.log('')
|
|
214
390
|
if (!forceInteractive || isDryRun) {
|
|
215
|
-
console.log(`Pantheon OpenCode v${version} — ${isDryRun ?
|
|
391
|
+
console.log(`Pantheon OpenCode v${version} — ${isDryRun ? S.dryRun : S.installing}`)
|
|
216
392
|
console.log('')
|
|
217
393
|
}
|
|
218
394
|
|
|
@@ -229,17 +405,19 @@ async function main() {
|
|
|
229
405
|
version: versionOpt ?? 'v1',
|
|
230
406
|
})
|
|
231
407
|
} catch (err) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
408
|
+
if (err?.message === 'Canceled') {
|
|
409
|
+
console.error(S.canceled)
|
|
410
|
+
process.exit(130)
|
|
411
|
+
}
|
|
412
|
+
console.error(`${S.installFailed(err.message)}\n${S.failHintNoMcp}\n${S.failHintForce}`)
|
|
235
413
|
process.exit(1)
|
|
236
414
|
}
|
|
237
415
|
|
|
238
416
|
if (runDoctor && !isDryRun) {
|
|
239
417
|
console.log('')
|
|
240
|
-
console.log(
|
|
418
|
+
console.log(` ${S.runningHealthCheck}`)
|
|
241
419
|
try {
|
|
242
|
-
const { spawnSync } = await import('child_process')
|
|
420
|
+
const { spawnSync } = await import('node:child_process')
|
|
243
421
|
const doctorScript = path.join(ROOT, 'scripts', 'doctor.mjs')
|
|
244
422
|
spawnSync(process.execPath, [doctorScript], { stdio: 'inherit', cwd: ROOT })
|
|
245
423
|
} catch {
|
|
@@ -249,16 +427,14 @@ async function main() {
|
|
|
249
427
|
|
|
250
428
|
console.log('')
|
|
251
429
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
|
252
|
-
console.log(`
|
|
430
|
+
console.log(` ${S.installedTitle(version)}`)
|
|
253
431
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
|
254
432
|
console.log('')
|
|
255
|
-
console.log(
|
|
256
|
-
console.log(
|
|
257
|
-
console.log(
|
|
258
|
-
console.log(
|
|
259
|
-
console.log(
|
|
260
|
-
console.log(' 4. For project-local install:')
|
|
261
|
-
console.log(' npx pantheon-opencode init --project')
|
|
433
|
+
console.log(` ${S.nextSteps}`)
|
|
434
|
+
console.log(` ${S.nextVerify}`)
|
|
435
|
+
console.log(` ${S.nextLaunch}`)
|
|
436
|
+
console.log(` ${S.nextAgents}`)
|
|
437
|
+
console.log(` ${S.nextProject}`)
|
|
262
438
|
console.log('')
|
|
263
439
|
|
|
264
440
|
return
|