pantheon-opencode 1.6.0-beta.2 → 1.6.0-beta.4
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/CHANGELOG.md +112 -0
- package/README.md +47 -15
- package/README.pt-BR.md +43 -13
- package/package.json +13 -10
- package/plugin.json +1 -1
- package/pyproject.toml +1 -1
- package/scripts/code_mode_server.py +1 -1
- package/scripts/cost.mjs +244 -41
- package/scripts/install/agents-md.mjs +2 -2
- package/scripts/install/health-check.mjs +9 -2
- package/scripts/install/shared.mjs +5 -5
- package/scripts/mcp_persistence_server.py +1 -1
- package/scripts/mcp_resources_server.py +1 -1
- package/scripts/memory_mcp_server.py +1 -1
- package/scripts/probe-context-rehydrate.mjs +6 -0
- package/scripts/probe-pantheon-cost.mjs +71 -15
- package/scripts/validate-routing.mjs +3 -3
- package/src/mcp/code_mode_server.py +1 -1
- package/src/mcp/mcp_persistence_server.py +1 -1
- package/src/mcp/mcp_resources_server.py +1 -1
- package/src/mcp/memory_mcp_server.py +1 -1
- package/src/mcp/pantheon_vision_server.py +1 -1
- package/src/mcp/requirements-mcp.txt +6 -4
- package/src/mcp/requirements-vision.txt +2 -2
- package/src/pantheon/cost-command.ts +399 -101
- package/src/pantheon/delegation-enforce.ts +10 -1
- package/src/pantheon/presets.mjs +3 -3
- package/src/pantheon/v2-tools.ts +426 -0
- package/src/plugin-v2.ts +473 -190
- package/src/plugins/tui/dist/server.d.ts +1 -2
- package/src/plugins/tui/dist/server.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.d.ts +74 -74
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +17 -20
- package/src/plugins/tui/package-lock.json +364 -317
- package/src/plugins/tui/package.json +8 -5
- package/src/plugins/tui/tsconfig.build.json +5 -0
- package/src/plugins/tui/tsdown.config.ts +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -18,6 +18,118 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
18
18
|
|
|
19
19
|
## ✅ Closed Issues
|
|
20
20
|
|
|
21
|
+
## [v1.6.0-beta.4] - 2026-10-03
|
|
22
|
+
|
|
23
|
+
<!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
|
|
24
|
+
move this section to a versioned entry and reset the template below. -->
|
|
25
|
+
|
|
26
|
+
## 🆕 What's New
|
|
27
|
+
|
|
28
|
+
- **Canário host-backed que dirige `hashline_edit` end-to-end** (`tests/canary/plugin-v2-tool-canary.test.mjs`, 12 casos): carrega `src/plugin-v2.ts` pelo loader real do host `opencode 2.0.22` e registra `Object.keys(ctx)` de dentro do host — medidos, `tool`/`event`/`permission`/`session` existem e `catalog` não. É o primeiro gate que dirige uma ferramenta do Pantheon por um host real. O canário existente só dirige o `read` embutido, e foi por isso que `draft.add()` sem `output` sobreviveu 26 dias com todos os testes verdes.
|
|
29
|
+
- **Os quatro domínios que o SDK `@opencode-ai/plugin` não tipa** (`tool`, `event`, `permission`, `session`) passaram a uma declaração estrutural local (`HostPluginContext`) e **um** cast documentado (`hostDomains()`), no lugar de seis `as unknown as Record<string, unknown>` que não verificavam tipo nenhum. Todo membro continua opcional e todo chamador reconferir antes de usar. A linha estável do SDK é `1.18.x` e não carrega o contrato do host — `1.18.34` (`latest`) é idêntica a `1.18.33`, então seguir o `dev` diário resolveria pior, não melhor.
|
|
30
|
+
|
|
31
|
+
## 🐞 Fixed
|
|
32
|
+
|
|
33
|
+
- `pantheon_cost` respondia `CORRUPT_DATA` em **toda** chamada contra o host 2.0.22: exigia a tabela `message`, que não existe nesse banco. Os tokens de assistant **estão** legíveis em `session_message`. **Não é renomeação:** `session_message` tem coluna `data`, mas não tem a chave `role` dentro dela — `json_type(data,'$.role')` é nulo em **0 de 40 307** linhas válidas. O V1 marca turnos de assistant com `data.role`; o V2 marca pela **coluna** `type`. Trocar apenas o nome da tabela casaria com nada e devolveria `status: OK` em silêncio. A detecção passa a ser por **presença de tabela**, porque as duas famílias coexistem em bancos migrados.
|
|
34
|
+
- `PANTHEON_OPENCODE_VERSION` nunca selecionou o schema: só mudava o **nome do arquivo**, e `opencode-v2.db` é o isolamento do sandbox via `OPENCODE_DB`, não um banco de host 2.x. A distinção v1/v2 é o **schema detectado**; a variável agora apenas restringe um conjunto já detectado e falha rápido quando pede uma família ausente.
|
|
35
|
+
- `scripts/cost.mjs` duplicava o mesmo bug literal, com o mesmo assert — o fallback continuava morto. `probe-pantheon-cost.mjs` acompanha.
|
|
36
|
+
- O report agora **declara a cobertura temporal** que ele mediu (janela varrida, linha mais antiga), em vez de apresentar totais como se cobrissem meses.
|
|
37
|
+
|
|
38
|
+
## ⚠️ Known Issues
|
|
39
|
+
|
|
40
|
+
- O canário **host-backed pula no CI**: o runner não tem binário `opencode`. O skip é **visível** no log (`::notice`), e os dois casos sem host rodam incondicionalmente, com `PANTHEON_TOOL_CANARY_BIN` apontado para um caminho inexistente. Rodar de verdade exige um modo no script de sandbox — **não feito**.
|
|
41
|
+
- A cobertura de custo do banco v2 é de **~8,3 dias** nesta máquina (primeiro registro em 2026-09-25). O histórico v1 (~96 dias) fica num diretório irmão com nome de epoch, que **não** é contrato e por isso não é descoberto automaticamente. Quem quiser aponta `PANTHEON_COST_DB`.
|
|
42
|
+
- `metadata.phase` nunca existiu em v1 nem em v2 — medido: 0 linhas de `session_message` têm `$.metadata.phase` nem `$.phase`. A coluna Phase sempre foi `unknown`. Não é regressão, é feature que nunca funcionou.
|
|
43
|
+
## [v1.6.0-beta.3] - 2026-10-03
|
|
44
|
+
|
|
45
|
+
<!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
|
|
46
|
+
move this section to a versioned entry and reset the template below. -->
|
|
47
|
+
|
|
48
|
+
## 🆕 What's New
|
|
49
|
+
- **Três ferramentas V2 agora executam de verdade**: `hashline_edit`,
|
|
50
|
+
`pantheon_cost` e `pantheon_model` rodam no host `opencode v2.0.x`. Antes
|
|
51
|
+
eram placeholders que declaravam sucesso sem fazer nada.
|
|
52
|
+
- **Enforcement de sessão read-only no caminho V2**: `apollo` e `gaia` voltam
|
|
53
|
+
a ter escrita bloqueada, com o guard registrado no próprio plugin V2 — sem
|
|
54
|
+
depender de uma ponte que a instalação V2 não monta.
|
|
55
|
+
- **Varredura de segredos de alta confiança no caminho V2**: o único hard block
|
|
56
|
+
de segurança que a V1 tinha, e que estava inerte por viver num plugin que a
|
|
57
|
+
instalação V2 não carrega, passa a rodar.
|
|
58
|
+
|
|
59
|
+
## 🐞 Fixed
|
|
60
|
+
- **As 6 ferramentas de plugin do V2 falhavam em 100% das chamadas**:
|
|
61
|
+
`hashline_edit`, `pantheon_cost` e `pantheon_model` lançavam
|
|
62
|
+
`Tool result declared output without an output schema` em toda invocação. A
|
|
63
|
+
causa era assimetria local — `draft.add()` não declarava `output` enquanto o
|
|
64
|
+
`execute` resolvia `{ output: string }`. O host exige simetria nos dois
|
|
65
|
+
sentidos: resultado com `output` e nenhuma declaração lança, assim como
|
|
66
|
+
declaração sem `output` no resultado. `output` passou a ser **obrigatório** na
|
|
67
|
+
interface `V2ToolDef`, então o compilador exige a declaração daqui em diante.
|
|
68
|
+
- **A suíte exigia o defeito**: `tests/pantheon/plugin-v2-contract.test.ts`
|
|
69
|
+
afirmava que o resultado carregava `.output` string — literalmente a condição
|
|
70
|
+
de falha, contra um mock que não reproduzia a exigência do host. O teste foi
|
|
71
|
+
reescrito para o invariante de simetria, contra um mock que constrói o
|
|
72
|
+
`outputSchema` a partir de `def.output` como o host faz
|
|
73
|
+
(`output: I.outputSchema ?? {}`), cobrindo as duas direções do bicondicional.
|
|
74
|
+
- **A imposição read-only não existia na superfície V2**: `createEnforcementGuard`
|
|
75
|
+
só era instanciado em `src/plugin.ts`, que o `opencode.json` da release não
|
|
76
|
+
declara — V2 nunca carrega V1. Com `hashline_edit` funcional, uma sessão
|
|
77
|
+
somente-leitura podia escrever arquivos. O guard passou a ser registrado no
|
|
78
|
+
hook `execute.before` do V2, e `pantheon_model` — que escreve
|
|
79
|
+
`active-preset.json` em escopo project e global — foi acrescentado a
|
|
80
|
+
`DEFAULT_BLOCKED_TOOLS`, o que corrige também a V1. `pantheon_cost` ficou de
|
|
81
|
+
fora de propósito: só lê `opencode.db`.
|
|
82
|
+
- **O único hard block de segurança da V1 estava inerte**: o scan de segredos de
|
|
83
|
+
alta confiança vivia em `src/plugins/pantheon-hooks.ts`, um plugin que a
|
|
84
|
+
instalação V2 não carrega — inerte por construção, não por má configuração.
|
|
85
|
+
Passou a rodar dentro do `execute.before` do V2
|
|
86
|
+
(`scripts/hooks/scan-secrets.sh`; exit 2 bloqueia, exit 1 é advisory e só
|
|
87
|
+
registra). O caminho do script foi verificado a partir do tarball instalado,
|
|
88
|
+
não só do repo.
|
|
89
|
+
- **Cinco comentários afirmavam cobertura que não existe** ("wired through the
|
|
90
|
+
V1…"). Corrigidos — é o defeito "anunciado como vivo, morto no caminho", a
|
|
91
|
+
mesma classe do bug original, transferida do tool para o controle de segurança.
|
|
92
|
+
|
|
93
|
+
## ⚠️ Known Issues
|
|
94
|
+
- **A release entrega 3 ferramentas V2 funcionais, não 6**:
|
|
95
|
+
`pantheon_goal_create`, `pantheon_goal_get` e `pantheon_goal_update` foram
|
|
96
|
+
**removidos** da superfície V2. `GoalLoopDeps` exige `store`, `client` e
|
|
97
|
+
`board`, que não existem no `PluginContext` V2, e a bridge V1 resolve para
|
|
98
|
+
`null` fora da V1. Registrá-las como placeholders não funcionais seria pior
|
|
99
|
+
que a ausência: anunciá-las seria mentira silenciosa. Marcador `goal-tools`
|
|
100
|
+
em `V2_UNSUPPORTED_FEATURES`. **Breaking** para quem usava esses tools no
|
|
101
|
+
host V2 — o contrato V1 permanece disponível para o goal loop.
|
|
102
|
+
- **A matriz de delegação nativa da V1 não é replicada na V2**: o guard V2 cobre
|
|
103
|
+
a lista de ferramentas bloqueadas, mas não a matriz caller→target nem a negação
|
|
104
|
+
de `task` em sessão filha. A matriz precisa de uma hierarquia de sessões
|
|
105
|
+
semeada a partir dos metadados de sessão, e o V2 não expõe esse caminho de
|
|
106
|
+
semeadura — `SessionHierarchyRegistry.isRoot` reporta `true` para sessões
|
|
107
|
+
desconhecidas enquanto não semeada, então semeá-la pela metade negaria todo
|
|
108
|
+
`task()`. O branch é pulado em vez de negado indiscriminadamente. Marcador
|
|
109
|
+
`delegation-matrix`. `task` continua negada em sessão somente-leitura pela
|
|
110
|
+
lista de ferramentas bloqueadas, então a profundidade 2 se sustenta; o que
|
|
111
|
+
não existe é a matriz. Coberto por `experimental.subagent_depth` nesta
|
|
112
|
+
configuração, mas a garantia do plugin não existe.
|
|
113
|
+
- **O log do scan de segredos escreve só em `.pantheon/logs/hooks.log`**: o
|
|
114
|
+
`PluginContext` V2 não expõe `client` nem `directory`, então os canais de log
|
|
115
|
+
estruturado e de toast da V1 não existem nessa superfície. É menos
|
|
116
|
+
observabilidade, não menos bloqueio.
|
|
117
|
+
- **Falha de infraestrutura do scanner é fail-open por decisão**: script ausente
|
|
118
|
+
ou timeout não bloqueiam. `runHook` nunca rejeita e um erro de infraestrutura
|
|
119
|
+
não deve negar chamadas não relacionadas. Ausência do script não bloqueia.
|
|
120
|
+
|
|
121
|
+
## ✅ Closed Issues
|
|
122
|
+
- **Drift de documentação no `README.pt-BR.md`**: a tabela de contrato de
|
|
123
|
+
runtime e o parágrafo de superfície listavam 6 ferramentas V2 e as 3 de goal,
|
|
124
|
+
que não estão registradas. Corrigido para 3 ferramentas, com a razão da
|
|
125
|
+
ausência e o ponto de imposição read-only.
|
|
126
|
+
- **Cinco comentários de falsa cobertura** sobre a imposição read-only e o scan
|
|
127
|
+
de segredos.
|
|
128
|
+
- **Shim do loader JSON do ajv elevado a bootstrap de módulo**: o patch de
|
|
129
|
+
`Module._extensions['.json']` era aplicado de dentro de `loadAjv()` e ficava
|
|
130
|
+
vivo durante todo o run, podendo vazar entre arquivos de teste e se manifestar
|
|
131
|
+
longe da causa. Agora instala, carrega e restaura em nível de módulo, antes de
|
|
132
|
+
qualquer corpo de teste, com `finally`.
|
|
21
133
|
## [v1.6.0-beta.2] - 2026-10-02
|
|
22
134
|
|
|
23
135
|
## 🆕 What's New
|
package/README.md
CHANGED
|
@@ -50,6 +50,8 @@ opencode
|
|
|
50
50
|
The installer guides you through the available setup. For optional MCP servers,
|
|
51
51
|
project-local installation, or non-interactive setup, see the
|
|
52
52
|
[installation guide](docs/INSTALLATION.md).
|
|
53
|
+
The bundled Python MCP servers use the pinned MCP SDK 2.2.0 and standalone
|
|
54
|
+
FastMCP 4.0.10 runtime; see the [MCP guide](docs/MCP.md).
|
|
53
55
|
|
|
54
56
|
## A simple example
|
|
55
57
|
|
|
@@ -186,16 +188,36 @@ per installation; V1 and V2 Pantheon plugins must never be registered together.
|
|
|
186
188
|
|---|---|---|
|
|
187
189
|
| OpenCode config key | singular `plugin` | plural `plugins` |
|
|
188
190
|
| Pantheon registration | `src/plugin.ts` plus `src/plugins/pantheon-hooks.ts` | `<installed>/src/plugin-v2` directory (`index.ts` re-exports `src/plugin-v2.ts`) |
|
|
189
|
-
| Runtime contract | Pantheon V1 plugin: 6 tools (`hashline_edit`, the 3 goal tools, `pantheon_cost`, `pantheon_model`), event/tool hooks and V1 compaction handling | Full V2 plugin:
|
|
191
|
+
| Runtime contract | Pantheon V1 plugin: 6 tools (`hashline_edit`, the 3 goal tools, `pantheon_cost`, `pantheon_model`), event/tool hooks and V1 compaction handling | Full V2 plugin: 3 tools (`hashline_edit`, `pantheon_cost`, `pantheon_model`), 4 event subscriptions, session hooks (`prompt`, `context`), a read-only-enforcing tool `execute.before` hook, plus configuration transforms |
|
|
190
192
|
| V1 APIs | Registered | Own tool definitions via `ctx.tool.transform()` — not the V1 plugin path |
|
|
191
193
|
|
|
192
|
-
The V2 plugin provides
|
|
193
|
-
`
|
|
194
|
-
`
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
`
|
|
194
|
+
The V2 plugin provides 3 orchestration tools (`hashline_edit`, `pantheon_cost`,
|
|
195
|
+
`pantheon_model`), 4 event subscriptions (`session.created`, `session.idle`,
|
|
196
|
+
`session.error`, `session.compacted`), session hooks (`prompt`, `context`),
|
|
197
|
+
and a tool `execute.before` hook that enforces read-only sessions. The 3 goal
|
|
198
|
+
tools are **not**
|
|
199
|
+
registered on V2: the goal loop needs a `GoalStore`, a `GoalLoopClient` and a
|
|
200
|
+
`BackgroundJobBoard`, none of which the V2 `PluginContext` exposes, so the gap
|
|
201
|
+
is reported as the `goal-tools` unsupported-feature marker. Use the V1
|
|
202
|
+
contract if you need the goal loop.
|
|
203
|
+
|
|
204
|
+
The V2 `execute.before` hook is the read-only enforcement point for that
|
|
205
|
+
surface: the host includes the active agent on the event, a read-only agent
|
|
206
|
+
(`apollo`, `gaia`) registers its session, and the shared
|
|
207
|
+
`createEnforcementGuard` throws to deny `edit`, `write`, `bash`, `task`,
|
|
208
|
+
`hashline_edit` and `pantheon_model`. It does **not** rely on the V1
|
|
209
|
+
`tool.execute.before` hook, which lives in `src/plugin.ts` and is not loaded
|
|
210
|
+
when only `plugin-v2` is configured. The companion `execute.after` hook and the
|
|
211
|
+
`permission.evaluate` hook are registration points with no V2-side behaviour,
|
|
212
|
+
and the V1 caller/target delegation matrix for native `task()` is not enforced
|
|
213
|
+
on V2.
|
|
214
|
+
|
|
215
|
+
Every V2 tool declares an `output` schema. OpenCode 2.0.x requires the
|
|
216
|
+
declaration and the resolved result to agree in both directions, so an
|
|
217
|
+
undeclared tool — or one that returns `output` without declaring it — fails on
|
|
218
|
+
every call. Unsupported V2 features are `legacy-hooks` (the V1-specific hook
|
|
219
|
+
surface), `catalog-transform`, `integration-transform`, `skill-transform` and
|
|
220
|
+
`goal-tools`.
|
|
199
221
|
|
|
200
222
|
The package exposes both contracts as importable exports: `pantheon-opencode/plugin`
|
|
201
223
|
(V1), `pantheon-opencode/plugin-v2` (V2) and `pantheon-opencode/v2-bridge`
|
|
@@ -222,13 +244,23 @@ Pantheon references from both config shapes before writing only the selected
|
|
|
222
244
|
Pantheon registration. Third-party entries are not converted or claimed by
|
|
223
245
|
this rule.
|
|
224
246
|
|
|
225
|
-
The
|
|
226
|
-
`
|
|
227
|
-
`PANTHEON_COST_DB=/absolute/path/to/opencode.db
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
247
|
+
The `pantheon_cost` report resolves its database by PATH, in this order: an
|
|
248
|
+
explicit `dbPath` supplied by the tool caller, then
|
|
249
|
+
`PANTHEON_COST_DB=/absolute/path/to/opencode.db`, then `OPENCODE_DB`, then the
|
|
250
|
+
XDG default `opencode.db`. There is no per-version filename in that chain:
|
|
251
|
+
`opencode-v2.db` is not a host 2.x database — it is the name a sandbox gives
|
|
252
|
+
its own state database through `OPENCODE_DB`.
|
|
253
|
+
|
|
254
|
+
The v1/v2 distinction is the DETECTED SCHEMA, not the file name. The report
|
|
255
|
+
looks for the `message` and `session_message` tables and reads whichever the
|
|
256
|
+
open database actually holds, because a migrated database carries both
|
|
257
|
+
families at once. `PANTHEON_OPENCODE_VERSION=v1|v2` selects no file: it only
|
|
258
|
+
narrows an already-detected set to one table family, and fails fast when the
|
|
259
|
+
value is neither `v1` nor `v2` or when the requested family is not there. Left
|
|
260
|
+
unset, every detected family is read. A database carrying neither table comes
|
|
261
|
+
back as an actionable error (`CORRUPT_DATA`), and a ledger that exists but
|
|
262
|
+
yields no readable tokens as `UNSUPPORTED` — never as a successful empty
|
|
263
|
+
report.
|
|
232
264
|
|
|
233
265
|
The installer still writes the compatibility settings required by the selected
|
|
234
266
|
OpenCode host, such as `experimental.subagent_depth`; this does not convert a
|
package/README.pt-BR.md
CHANGED
|
@@ -122,16 +122,36 @@ registrados juntos.
|
|
|
122
122
|
|---|---|---|
|
|
123
123
|
| Chave de config do OpenCode | `plugin` singular | `plugins` plural |
|
|
124
124
|
| Registro Pantheon | `src/plugin.ts` mais `src/plugins/pantheon-hooks.ts` | `pantheon-opencode/plugin-v2` (`src/plugin-v2.ts`) |
|
|
125
|
-
| Contrato de runtime | Plugin Pantheon V1: 6 ferramentas (`hashline_edit`, as 3 ferramentas de goal, `pantheon_cost`, `pantheon_model`), hooks de evento/ferramenta e tratamento de compactação V1 | Plugin V2 completo:
|
|
125
|
+
| Contrato de runtime | Plugin Pantheon V1: 6 ferramentas (`hashline_edit`, as 3 ferramentas de goal, `pantheon_cost`, `pantheon_model`), hooks de evento/ferramenta e tratamento de compactação V1 | Plugin V2 completo: 3 ferramentas (`hashline_edit`, `pantheon_cost`, `pantheon_model`), 4 assinaturas de eventos, session hooks (`prompt`, `context`), um hook de ferramenta `execute.before` que impõe sessões somente-leitura, além de transforms de configuração |
|
|
126
126
|
| APIs V1 | Registradas | Definições próprias de ferramentas via `ctx.tool.transform()` — não pelo caminho do plugin V1 |
|
|
127
127
|
|
|
128
|
-
O plugin V2 fornece
|
|
129
|
-
`pantheon_goal_create`, `pantheon_goal_get`, `pantheon_goal_update`,
|
|
128
|
+
O plugin V2 fornece 3 ferramentas de orquestração (`hashline_edit`,
|
|
130
129
|
`pantheon_cost`, `pantheon_model`), 4 assinaturas de eventos (`session.created`,
|
|
131
130
|
`session.idle`, `session.error`, `session.compacted`), session hooks (`prompt`,
|
|
132
|
-
`context`) e
|
|
133
|
-
|
|
134
|
-
`
|
|
131
|
+
`context`) e um hook de ferramenta `execute.before` que impõe sessões
|
|
132
|
+
somente-leitura. As 3 ferramentas de goal **não** são
|
|
133
|
+
registradas no V2: o goal loop precisa de um `GoalStore`, de um
|
|
134
|
+
`GoalLoopClient` e de um `BackgroundJobBoard`, nenhum dos quais o
|
|
135
|
+
`PluginContext` do V2 expõe, então a lacuna é reportada como o marcador de
|
|
136
|
+
recurso sem suporte `goal-tools`. Use o contrato V1 se precisar do goal loop.
|
|
137
|
+
|
|
138
|
+
O hook `execute.before` do V2 é o ponto de imposição de sessões somente-leitura
|
|
139
|
+
dessa superfície: o host inclui o agente ativo no evento, um agente somente-leitura
|
|
140
|
+
(`apollo`, `gaia`) registra sua sessão, e o `createEnforcementGuard`
|
|
141
|
+
compartilhado lança para negar `edit`, `write`, `bash`, `task`,
|
|
142
|
+
`hashline_edit` e `pantheon_model`. Ele **não** depende do hook
|
|
143
|
+
`tool.execute.before` do V1, que vive em `src/plugin.ts` e não é carregado
|
|
144
|
+
quando apenas `plugin-v2` está configurado. Os hooks companheiros
|
|
145
|
+
`execute.after` e `permission.evaluate` são pontos de registro sem comportamento
|
|
146
|
+
do lado V2, e a matriz de delegação caller/target da V1 para o `task()` nativo
|
|
147
|
+
não é imposta no V2.
|
|
148
|
+
|
|
149
|
+
Toda ferramenta V2 declara um schema `output`. O OpenCode 2.0.x exige que a
|
|
150
|
+
declaração e o resultado resolvido concordem nos dois sentidos, então uma
|
|
151
|
+
ferramenta sem declaração — ou que retorne `output` sem declará-lo — falha em
|
|
152
|
+
toda chamada. Os recursos V2 sem suporte são `legacy-hooks` (a superfície de
|
|
153
|
+
hooks específica do V1), `catalog-transform`, `integration-transform`,
|
|
154
|
+
`skill-transform` e `goal-tools`.
|
|
135
155
|
|
|
136
156
|
O pacote expõe os dois contratos como exports importáveis:
|
|
137
157
|
`pantheon-opencode/plugin` (V1), `pantheon-opencode/plugin-v2` (V2) e
|
|
@@ -159,13 +179,23 @@ instalador remove referências Pantheon das duas formas de config antes de
|
|
|
159
179
|
gravar apenas o registro Pantheon selecionado. Entradas de terceiros não são
|
|
160
180
|
convertidas nem reivindicadas por essa regra.
|
|
161
181
|
|
|
162
|
-
O relatório `pantheon_cost`, disponível nos plugins V1 e V2,
|
|
163
|
-
|
|
164
|
-
`PANTHEON_COST_DB=/caminho/absoluto/para/opencode.db
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
182
|
+
O relatório `pantheon_cost`, disponível nos plugins V1 e V2, resolve o banco por
|
|
183
|
+
CAMINHO, nesta ordem: um `dbPath` explícito fornecido pelo chamador da
|
|
184
|
+
ferramenta, depois `PANTHEON_COST_DB=/caminho/absoluto/para/opencode.db`,
|
|
185
|
+
depois `OPENCODE_DB`, e por fim o padrão do XDG `opencode.db`. Não há nome de
|
|
186
|
+
arquivo por versão nessa cadeia: `opencode-v2.db` não é um banco de um host 2.x
|
|
187
|
+
— é o nome que um sandbox dá ao próprio banco de estado via `OPENCODE_DB`.
|
|
188
|
+
|
|
189
|
+
A distinção v1/v2 é o SCHEMA DETECTADO, não o nome do arquivo. O relatório
|
|
190
|
+
procura as tabelas `message` e `session_message` e lê aquele que o banco aberto
|
|
191
|
+
realmente tiver, porque um banco migrado carrega as duas famílias ao mesmo
|
|
192
|
+
tempo. `PANTHEON_OPENCODE_VERSION=v1|v2` não seleciona arquivo nenhum: apenas
|
|
193
|
+
estreita um conjunto já detectado para uma família de tabelas, e falha rápido
|
|
194
|
+
quando o valor não é `v1` nem `v2` ou quando a família pedida não existe lá.
|
|
195
|
+
Sem a variável, todas as famílias detectadas são lidas. Um banco sem nenhuma
|
|
196
|
+
das duas tabelas volta como erro acionável (`CORRUPT_DATA`), e um ledger que
|
|
197
|
+
existe mas não produz tokens legíveis como `UNSUPPORTED` — nunca como um
|
|
198
|
+
relatório vazio com sucesso.
|
|
169
199
|
|
|
170
200
|
O instalador continua gravando as configurações de compatibilidade exigidas
|
|
171
201
|
pelo host OpenCode selecionado, como `experimental.subagent_depth`; isso não
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantheon-opencode",
|
|
3
|
-
"version": "1.6.0-beta.
|
|
3
|
+
"version": "1.6.0-beta.4",
|
|
4
4
|
"description": "Multi-agent orchestration for OpenCode — 14 specialized agents, TDD, Themis review gates.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"coverage:plugin-v2": "node scripts/check-plugin-v2-coverage.mjs",
|
|
47
47
|
"test:ts": "for f in tests/pantheon/*.test.ts; do if [ \"$f\" = tests/pantheon/plugin-v2-contract.test.ts ]; then NODE_OPTIONS=--conditions=import tsx \"$f\"; else tsx \"$f\"; fi || exit 1; done",
|
|
48
48
|
"test:hooks": "node --test tests/pantheon/plugin-v2-hook-canary.test.mjs",
|
|
49
|
+
"test:tool-canary": "node --test tests/canary/plugin-v2-tool-canary.test.mjs",
|
|
49
50
|
"test:all": "npm run test:ci && npm run test:node && npm run test:ts",
|
|
50
51
|
"test": "npm run test:all",
|
|
51
52
|
"test:ci": "python3 -m pytest -q --tb=short 2>&1"
|
|
@@ -97,20 +98,22 @@
|
|
|
97
98
|
"!**/*.pyc"
|
|
98
99
|
],
|
|
99
100
|
"dependencies": {
|
|
100
|
-
"@opencode-ai/plugin": "1.18.
|
|
101
|
-
"js-yaml": "^4.
|
|
102
|
-
"zod": "4.1.8"
|
|
101
|
+
"@opencode-ai/plugin": "1.18.33",
|
|
102
|
+
"js-yaml": "^5.4.2",
|
|
103
|
+
"zod": "4.1.8",
|
|
104
|
+
"@opencode-ai/sdk": "1.18.33"
|
|
103
105
|
},
|
|
104
106
|
"devDependencies": {
|
|
105
|
-
"@biomejs/biome": "2.5.
|
|
106
|
-
"@commitlint/cli": "21.2.
|
|
107
|
-
"@commitlint/config-conventional": "21.2.
|
|
107
|
+
"@biomejs/biome": "2.5.14",
|
|
108
|
+
"@commitlint/cli": "21.2.3",
|
|
109
|
+
"@commitlint/config-conventional": "21.2.3",
|
|
110
|
+
"ajv": "8.20.0",
|
|
108
111
|
"husky": "^9.1.7",
|
|
109
|
-
"tsx": "4.23.
|
|
110
|
-
"typescript": "
|
|
112
|
+
"tsx": "4.23.15",
|
|
113
|
+
"typescript": "7.0.2"
|
|
111
114
|
},
|
|
112
115
|
"overrides": {
|
|
113
|
-
"rolldown": "1.2.
|
|
116
|
+
"rolldown": "1.2.7"
|
|
114
117
|
},
|
|
115
118
|
"repository": {
|
|
116
119
|
"type": "git",
|
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantheon",
|
|
3
3
|
"publisher": "ils15",
|
|
4
|
-
"version": "1.6.0-beta.
|
|
4
|
+
"version": "1.6.0-beta.4",
|
|
5
5
|
"displayName": "Pantheon",
|
|
6
6
|
"description": "Conductor-Delegate orchestration platform with 14 specialized agents, 21 skills, and OpenCode support.",
|
|
7
7
|
"agents": "./src/agents",
|
package/pyproject.toml
CHANGED
|
@@ -36,7 +36,7 @@ from typing import Any
|
|
|
36
36
|
|
|
37
37
|
import yaml
|
|
38
38
|
from _pantheon_paths import pantheon_home, pantheon_project
|
|
39
|
-
from
|
|
39
|
+
from fastmcp import FastMCP
|
|
40
40
|
|
|
41
41
|
# ── Constants ─────────────────────────────────────────────────────────────────
|
|
42
42
|
ALLOWED_EXTENSIONS: frozenset[str] = frozenset({".sh", ".py"})
|