pantheon-opencode 1.3.7 → 1.4.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.
@@ -154,25 +154,29 @@ async function resolvePresetForTui(
154
154
  * Se falhar, retorna null e a View omite a versão.
155
155
  *
156
156
  * Try order:
157
+ * 0a. pantheon-tui/package.json (installed: dist/tui.js → 2 níveis)
158
+ * 0b. pantheon/package.json (dev: src/plugins/tui/dist/tui.tsx → 4 níveis)
157
159
  * 1. api.client.file.read package.json
158
160
  * 2. git describe --tags
159
161
  * 3. opencode --version
160
162
  * 4. null */
161
163
 
162
164
  async function detectVersion(api: TuiPluginApi): Promise<string | null> {
163
- // Try 0: package.json do PACOTE PANTHEON instalado. O TUI é carregado de
164
- // <pacote>/src/plugins/tui/dist/tui.tsx (fix #32 garante esse path) →
165
- // 4 níveis acima (dist → tui → plugins → src → raiz) está o package.json
166
- // do pacote. Funciona em QUALQUER cwd (ex: sandbox sem package.json/git) e
167
- // também em dev (source no repo). Se falhar, cai para os tries abaixo.
165
+ // Try 0a: installed location (2 levels: dist/tui.js → pantheon-tui/package.json)
166
+ try {
167
+ const pkgUrl = new URL('../../package.json', import.meta.url)
168
+ const pkgContent = await readFile(fileURLToPath(pkgUrl), 'utf8')
169
+ const pkg = JSON.parse(pkgContent)
170
+ if (pkg.version) return pkg.version
171
+ } catch {}
172
+
173
+ // Try 0b: dev location (4 levels: src/plugins/tui/dist/tui.tsx → package.json)
168
174
  try {
169
175
  const pkgUrl = new URL('../../../../package.json', import.meta.url)
170
176
  const pkgContent = await readFile(fileURLToPath(pkgUrl), 'utf8')
171
- const match = pkgContent.match(/"version":\s*"([^"]+)"/)
172
- if (match?.[1]) return match[1]
173
- } catch {
174
- /* fall through */
175
- }
177
+ const pkg = JSON.parse(pkgContent)
178
+ if (pkg.version) return pkg.version
179
+ } catch {}
176
180
 
177
181
  // Try 1: package.json do projeto (via worktree path)
178
182
  try {
@@ -45,3 +45,10 @@ Generate a hierarchical map of the codebase to understand its structure, key mod
45
45
  - Focus on structure, not implementation details
46
46
  - Max 3 levels deep unless a module is critical
47
47
  - Return to agent: "Codemap generated. Send to @athena for planning."
48
+
49
+ ## Integração @apollo
50
+ Antes de glob/grep manual, tente `code_query`:
51
+ - `code_query("MyClass")` → busca FTS5 por entidade
52
+ - Fallback para glob/grep se não indexado ou query vazia
53
+ - `code_index("src/")` para indexação incremental (hash-based, skip se não mudou, force=true para re-index)
54
+ - `code_neighbors(entity_id, depth=2)` para grafo de imports/calls
@@ -859,3 +859,42 @@ When `01-active-context.md` exceeds 100 lines:
859
859
  - `skills/wisdom-accumulation/SKILL.md` — learning extraction
860
860
  - `skills/memory-bank/SKILL.md` — memory bank maintenance
861
861
  - `instructions/backend-standards.instructions.md` — zeus scoring reference
862
+
863
+ ---
864
+
865
+ ## 19. Tool Output Sandboxing (v2 P0 — Plugin Hook, 0 MCPs)
866
+
867
+ Camada P0 do Deepwork Plan "Context Window Optimization" (council 2026-08-25, 3/3 High): truncamento simples via `tool.execute.after`, sem tiktoken/LLM em v1 (YAGNI).
868
+
869
+ **Módulo:** `src/pantheon/context-sandbox.ts` (~120 LOC) — `sandboxOutput(tool, output)` + `createContextSandbox(config)`
870
+
871
+ **Limites (defaults sensatos, cobrem 80% do problema):**
872
+
873
+ | Tool | Limite | Ação no excesso |
874
+ |------|--------|-----------------|
875
+ | read | 200 linhas | Primeiras 50 + `[TRUNCATED: N lines]` + últimas 10 |
876
+ | grep | 20 resultados | Top 10 + `[Showing 10 of N matches]` |
877
+ | glob | 50 arquivos | Top 20 + `[showing 20 of N files]` |
878
+ | webfetch | 5000 chars | Primeiros 2000 + `[Content truncated]` |
879
+
880
+ **Integração (ordem fixa — 0-overhead extra):** `tool.execute.after` → `sandboxHandler` (trunca) → `readEnhancer` (hashline tags). Sandbox sempre antes de compression: outputs já chegam enxutos ao context window; compress-inline (L1) só atua sobre o que sobrou. Custo <1ms por call, 0 novos processos.
881
+
882
+ **Config opcional em `opencode.json` (fail-open — defaults quando ausente):**
883
+ ```json
884
+ {
885
+ "context_sandbox": {
886
+ "enabled": true,
887
+ "limits": {
888
+ "read": { "maxLines": 200, "keepHead": 50, "keepTail": 10 },
889
+ "grep": { "maxResults": 20, "keepTop": 10 },
890
+ "glob": { "maxFiles": 50, "keepTop": 20 },
891
+ "webfetch": { "maxChars": 5000, "keepHead": 2000 }
892
+ }
893
+ }
894
+ }
895
+ ```
896
+ Desabilitar: `"enabled": false` (plugin vira no-op, sem throw).
897
+
898
+ **Session Memory (P1 — já existe, só conectado):** `pantheon-persistence` KV com TTL 4h já fornece `context_save`/`context_get`. Auto-save antes de compactar (`experimental.session.compacting` → `buildCompactionContext` + `todoPreserver.capture`) e recovery pós-compactação (`session.compacted` → `todoPreserver.onCompacted` + `reassertAfterCompaction`) preservam estado sem novo MCP. Testado em `delegation-compaction.test.ts` + `todo-preserve.test.ts`.
899
+
900
+ **Fora de escopo v1 (YAGNI):** tiktoken counting, LLM summarization, budget dashboard — só se medição provar necessidade.