pantheon-opencode 1.5.0-beta.2 → 1.5.0-beta.20
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/manifest.json +21 -0
- package/AGENTS.md +14 -63
- package/CHANGELOG.md +1260 -0
- package/README.md +162 -23
- package/README.pt-BR.md +104 -19
- package/bin/pantheon-init.mjs +178 -21
- package/commands/pantheon.md +1 -35
- package/package.json +23 -15
- package/plugin.json +1 -1
- package/pyproject.toml +62 -0
- package/scripts/code_mode_server.py +431 -55
- package/scripts/doctor.mjs +207 -9
- package/scripts/install/cli-ui.mjs +17 -11
- package/scripts/install/config-migration.mjs +4 -6
- package/scripts/install/opencode.mjs +137 -35
- package/scripts/install/plugin.mjs +12 -45
- package/scripts/install/shared.mjs +43 -2
- package/scripts/install/strings.mjs +129 -0
- package/scripts/install-mcp.mjs +1 -0
- package/scripts/manifest-inventory.mjs +410 -0
- package/scripts/mcp_persistence_server.py +536 -164
- package/scripts/package-evidence.mjs +242 -0
- package/scripts/probe-pantheon-cost.mjs +10 -1
- package/scripts/release-beta-version.mjs +56 -60
- package/scripts/sync-artifacts.mjs +169 -0
- package/scripts/sync-tui.mjs +129 -64
- package/scripts/test-opencode-v1-v2-sandbox.sh +79 -161
- package/scripts/validation-policy.mjs +7 -7
- package/scripts/version-check.mjs +113 -108
- package/scripts/versioning.mjs +230 -86
- package/src/agents/apollo.md +1 -0
- package/src/agents/gaia.md +1 -0
- package/src/agents/mnemosyne.md +1 -1
- package/src/agents/zeus.md +11 -54
- package/src/instructions/memory-protocol.instructions.md +6 -3
- package/src/instructions/zeus-anti-stall.instructions.md +2 -4
- package/src/instructions/zeus-council-synthesis.instructions.md +3 -28
- package/src/instructions/zeus-timeout-retry.instructions.md +3 -28
- package/src/mcp/code_mode_server.py +431 -55
- package/src/mcp/mcp_persistence_server.py +536 -164
- package/src/mcp/toon_codec.py +2 -4
- package/src/pantheon/background-job-board.ts +47 -5
- package/src/pantheon/{delegation-compaction.ts → compaction-context.ts} +10 -100
- package/src/pantheon/cost-command.ts +309 -44
- package/src/pantheon/delegation-enforce.ts +59 -14
- package/src/pantheon/file-persistence-salvage.ts +64 -0
- package/src/pantheon/file-persistence.ts +194 -45
- package/src/pantheon/goal-loop.ts +1 -1
- package/src/pantheon/goal-store.ts +1 -1
- package/src/pantheon/idle-continuation.ts +4 -6
- package/src/pantheon/model-command.ts +1 -2
- package/src/pantheon/native-task-status.ts +139 -0
- package/src/pantheon/presets.d.mts +0 -20
- package/src/pantheon/presets.mjs +0 -64
- package/src/pantheon/session-guard.ts +2 -2
- package/src/pantheon/session-id.ts +30 -0
- package/src/pantheon/shared-board.ts +37 -0
- package/src/pantheon/task-result-guard.ts +106 -0
- package/src/pantheon/todo-enforcer.ts +3 -3
- package/src/pantheon/tool-ceiling.ts +159 -0
- package/src/pantheon/tool-context.ts +23 -0
- package/src/pantheon/v2-bridge.ts +1 -4
- package/src/plugin-v2.ts +8 -21
- package/src/plugin.ts +83 -251
- package/src/plugins/pantheon-hooks.ts +51 -0
- package/src/plugins/tui/dist/server.d.ts +1 -1
- package/src/plugins/tui/dist/server.d.ts.map +1 -1
- package/src/plugins/tui/dist/server.js +1 -1
- package/src/plugins/tui/dist/server.js.map +1 -1
- package/src/plugins/tui/dist/tui.d.ts +261 -77
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +640 -234
- package/src/plugins/tui/dist/tui.js.map +1 -1
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +2 -2
- package/src/plugins/tui/src/index.tsx +872 -226
- package/src/routing.yml +0 -16
- package/src/skills/context-compression/SKILL.md +1 -1
- package/scripts/generate-preset-docs.mjs +0 -300
- package/scripts/generate-prompts.sh +0 -222
- package/scripts/hash_verify.py +0 -192
- package/scripts/install/component.mjs +0 -24
- package/scripts/install/migrate-config.mjs +0 -302
- package/scripts/test-context-compression.sh +0 -169
- package/src/pantheon/auto-wake.ts +0 -89
- package/src/pantheon/chat-reminders.ts +0 -9
- package/src/pantheon/comment-checker.ts +0 -48
- package/src/pantheon/compaction-assert.ts +0 -160
- package/src/pantheon/cost-tracker.ts +0 -108
- package/src/pantheon/delegate-manager.ts +0 -669
- package/src/pantheon/delegation-classifier.ts +0 -307
- package/src/pantheon/delegation-finalize.ts +0 -374
- package/src/pantheon/delegation-notify.ts +0 -212
- package/src/pantheon/delegation-toast.ts +0 -73
- package/src/pantheon/delegation.ts +0 -1120
- package/src/pantheon/dispatch-guard.ts +0 -109
- package/src/pantheon/permission-eval.ts +0 -284
- package/src/pantheon/preemptive-compact.ts +0 -76
- package/src/pantheon/retry-policy.ts +0 -212
- package/src/pantheon/step-cap.ts +0 -110
- package/src/pantheon/token-opt.ts +0 -781
- package/src/pantheon/toon-codec.ts +0 -481
- package/src/pantheon/v2-events.ts +0 -131
- package/src/pantheon/v2-hooks.ts +0 -287
- package/src/pantheon/v2-tool-definitions.ts +0 -331
- package/src/pantheon/zeus-delegate-with-retry.ts +0 -406
- package/src/plugins/tui/dist/tui.tsx +0 -2605
package/scripts/sync-tui.mjs
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
* If the user hasn't initialized yet → do nothing (silent exit).
|
|
11
11
|
*/
|
|
12
12
|
import { execSync } from 'node:child_process'
|
|
13
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
13
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
14
14
|
import { homedir } from 'node:os'
|
|
15
15
|
import { join } from 'node:path'
|
|
16
|
-
import { fileURLToPath } from 'node:url'
|
|
16
|
+
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
17
17
|
|
|
18
18
|
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
|
19
19
|
const ROOT = join(__dirname, '..')
|
|
@@ -58,9 +58,9 @@ function resolveConfigDir() {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
|
-
* Copy plugin runtime files (dist/*, package.json,
|
|
62
|
-
*
|
|
63
|
-
*
|
|
61
|
+
* Copy plugin runtime files (the bundled dist/*, package.json,
|
|
62
|
+
* package-lock.json) from srcDir to dstDir. Skips files that are byte-identical.
|
|
63
|
+
* The raw TSX source is never copied — the loader consumes only the bundle.
|
|
64
64
|
* @returns {{ created: number, skipped: number }}
|
|
65
65
|
*/
|
|
66
66
|
function copyPluginFiles(srcDir, dstDir) {
|
|
@@ -69,13 +69,10 @@ function copyPluginFiles(srcDir, dstDir) {
|
|
|
69
69
|
mkdirSync(dstDir, { recursive: true })
|
|
70
70
|
mkdirSync(join(dstDir, 'dist'), { recursive: true })
|
|
71
71
|
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (writeIfChanged(join(dstDir, 'index.tsx'), content)) result.created++
|
|
77
|
-
else result.skipped++
|
|
78
|
-
}
|
|
72
|
+
// Drop legacy raw copies from previous installs (root index.tsx + dist/tui.tsx).
|
|
73
|
+
// The loader consumes only the bundle, so stale raws must not linger.
|
|
74
|
+
rmSync(join(dstDir, 'index.tsx'), { force: true })
|
|
75
|
+
rmSync(join(dstDir, 'dist', 'tui.tsx'), { force: true })
|
|
79
76
|
|
|
80
77
|
// dist/*
|
|
81
78
|
const distSrc = join(srcDir, 'dist')
|
|
@@ -106,68 +103,136 @@ function copyPluginFiles(srcDir, dstDir) {
|
|
|
106
103
|
return result
|
|
107
104
|
}
|
|
108
105
|
|
|
109
|
-
// ──
|
|
110
|
-
|
|
111
|
-
try {
|
|
112
|
-
const configDir = resolveConfigDir()
|
|
113
|
-
if (!configDir) {
|
|
114
|
-
// User hasn't run init yet — silent exit, no error
|
|
115
|
-
process.exit(0)
|
|
116
|
-
}
|
|
106
|
+
// ── npm env hygiene ────────────────────────────────────────────────────
|
|
117
107
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
108
|
+
/**
|
|
109
|
+
* npm lifecycle env vars that put a nested `npm ci` into global context and
|
|
110
|
+
* make it abort with ECIGLOBAL ("`npm ci` does not work for global packages").
|
|
111
|
+
* When the package itself is installed with `npm install -g`, npm injects these
|
|
112
|
+
* into the postinstall environment; the TUI dependency sync is a local
|
|
113
|
+
* operation and must never inherit them.
|
|
114
|
+
*/
|
|
115
|
+
const GLOBAL_NPM_ENV_KEYS = new Set([
|
|
116
|
+
'npm_config_global',
|
|
117
|
+
'npm_config_globalconfig',
|
|
118
|
+
'npm_config_prefix',
|
|
119
|
+
'npm_config_location',
|
|
120
|
+
])
|
|
123
121
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Return a copy of `env` with global-context npm config vars removed.
|
|
124
|
+
* Matching is case-insensitive so Windows-style uppercase keys are handled.
|
|
125
|
+
* @param {NodeJS.ProcessEnv} [env]
|
|
126
|
+
* @returns {NodeJS.ProcessEnv}
|
|
127
|
+
*/
|
|
128
|
+
export function sanitizeNpmEnv(env = process.env) {
|
|
129
|
+
const clean = { ...env }
|
|
130
|
+
for (const key of Object.keys(clean)) {
|
|
131
|
+
if (GLOBAL_NPM_ENV_KEYS.has(key.toLowerCase())) delete clean[key]
|
|
129
132
|
}
|
|
133
|
+
return clean
|
|
134
|
+
}
|
|
130
135
|
|
|
131
|
-
|
|
132
|
-
const installedVersion = readVersion(join(tuiCopyDir, 'package.json'))
|
|
133
|
-
const sourceVersion = readVersion(join(tuiSrcDir, 'package.json'))
|
|
134
|
-
|
|
135
|
-
// Copy fresh files
|
|
136
|
-
const { created } = copyPluginFiles(tuiSrcDir, tuiCopyDir)
|
|
136
|
+
// ── Main ───────────────────────────────────────────────────────────────
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
// operator explicitly opts into the non-deterministic legacy fallback.
|
|
138
|
+
async function main() {
|
|
140
139
|
try {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
140
|
+
const configDir = resolveConfigDir()
|
|
141
|
+
if (!configDir) {
|
|
142
|
+
// User hasn't run init yet — silent exit, no error
|
|
143
|
+
process.exit(0)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const tuiCopyDir = join(configDir, 'plugins', 'pantheon-tui')
|
|
147
|
+
if (!existsSync(tuiCopyDir)) {
|
|
148
|
+
// beta.5: no TUI install (plugins component omitted) — skip the TUI
|
|
149
|
+
// sync but STILL refresh the copy-only artifacts below.
|
|
150
|
+
const { syncCopyArtifacts } = await import('./sync-artifacts.mjs')
|
|
151
|
+
const synced = syncCopyArtifacts(configDir)
|
|
152
|
+
if (synced.errors.length > 0) {
|
|
153
|
+
for (const e of synced.errors) console.error(` ⚠️ artifact sync: ${e}`)
|
|
152
154
|
}
|
|
155
|
+
console.log(
|
|
156
|
+
` Artifacts synced: ${synced.created} updated, ${synced.skipped} already current`,
|
|
157
|
+
)
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Source: TUI plugin inside the installed package
|
|
162
|
+
const tuiSrcDir = join(ROOT, 'src', 'plugins', 'tui')
|
|
163
|
+
if (!existsSync(tuiSrcDir)) {
|
|
164
|
+
throw new Error(`TUI plugin source not found: ${tuiSrcDir}`)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Compare versions before copy
|
|
168
|
+
const installedVersion = readVersion(join(tuiCopyDir, 'package.json'))
|
|
169
|
+
const sourceVersion = readVersion(join(tuiSrcDir, 'package.json'))
|
|
170
|
+
|
|
171
|
+
// Copy fresh files
|
|
172
|
+
const { created } = copyPluginFiles(tuiSrcDir, tuiCopyDir)
|
|
173
|
+
|
|
174
|
+
// Lockfile installation is the only accepted dependency path. Strip
|
|
175
|
+
// global-context npm vars so a global postinstall can't trigger ECIGLOBAL.
|
|
176
|
+
execSync('npm ci --omit=dev --no-audit --no-fund', {
|
|
177
|
+
cwd: tuiCopyDir,
|
|
178
|
+
stdio: 'pipe',
|
|
179
|
+
env: sanitizeNpmEnv(),
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
// Log result
|
|
183
|
+
if (installedVersion && sourceVersion && installedVersion === sourceVersion && created === 0) {
|
|
184
|
+
console.log(` TUI plugin already up to date (v${sourceVersion})`)
|
|
153
185
|
} else {
|
|
154
|
-
console.
|
|
155
|
-
|
|
156
|
-
`PANTHEON_ALLOW_NPM_INSTALL_FALLBACK=1 to explicitly allow npm install: ${err.message}`,
|
|
186
|
+
console.log(
|
|
187
|
+
` TUI plugin updated to v${sourceVersion || 'latest'}${installedVersion ? ` (was v${installedVersion})` : ''}`,
|
|
157
188
|
)
|
|
158
189
|
}
|
|
159
|
-
}
|
|
160
190
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
)
|
|
191
|
+
// ── beta.5 freshness guarantee: refresh ALL copy-only artifacts ──
|
|
192
|
+
// Agents, skills, AGENTS.md, commands, MCP scripts, code-mode payload.
|
|
193
|
+
// The plugin references in opencode.json already point INTO this package,
|
|
194
|
+
// so only the copies would go stale after a package update.
|
|
195
|
+
const { syncCopyArtifacts } = await import('./sync-artifacts.mjs')
|
|
196
|
+
const { readState, writeState } = await import('./install/state.mjs')
|
|
197
|
+
const pkgVersion = readVersion(join(ROOT, 'package.json')) ?? 'unknown'
|
|
198
|
+
const synced = syncCopyArtifacts(configDir)
|
|
199
|
+
if (synced.errors.length > 0) {
|
|
200
|
+
for (const e of synced.errors) console.error(` ⚠️ artifact sync: ${e}`)
|
|
201
|
+
}
|
|
202
|
+
console.log(` Artifacts synced: ${synced.created} updated, ${synced.skipped} already current`)
|
|
203
|
+
|
|
204
|
+
// Version marker so doctor can detect a stale installation and point the
|
|
205
|
+
// user at `pantheon-opencode update` for the full refresh (config merge,
|
|
206
|
+
// venv, MCP entries).
|
|
207
|
+
try {
|
|
208
|
+
const previous = readState(configDir)
|
|
209
|
+
writeState(configDir, {
|
|
210
|
+
pantheon_version: pkgVersion,
|
|
211
|
+
previous_version: previous?.pantheon_version ?? null,
|
|
212
|
+
})
|
|
213
|
+
if (previous?.pantheon_version && previous.pantheon_version !== pkgVersion) {
|
|
214
|
+
console.log(
|
|
215
|
+
` ⚠️ Installation moved ${previous.pantheon_version} → ${pkgVersion}. ` +
|
|
216
|
+
'Run `npx pantheon-opencode init` to refresh config/venv/MCP entries.',
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
220
|
+
// Marker is best-effort — never fail the postinstall over it.
|
|
221
|
+
}
|
|
222
|
+
} catch (err) {
|
|
223
|
+
console.error(`❌ TUI sync failed: ${err.message}`)
|
|
224
|
+
process.exitCode = 1
|
|
168
225
|
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Only run when invoked directly (`node scripts/sync-tui.mjs`). Importing this
|
|
229
|
+
// module for unit tests must not trigger the side-effecting postinstall sync.
|
|
230
|
+
const isDirectRun =
|
|
231
|
+
Boolean(process.argv[1]) && pathToFileURL(process.argv[1]).href === import.meta.url
|
|
232
|
+
|
|
233
|
+
if (isDirectRun) {
|
|
234
|
+
main().catch((err) => {
|
|
235
|
+
console.error(`❌ TUI sync failed: ${err.message}`)
|
|
236
|
+
process.exitCode = 1
|
|
237
|
+
})
|
|
173
238
|
}
|