pantheon-opencode 1.5.0-beta.1 → 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/manifest.json +21 -0
- package/CHANGELOG.md +1026 -0
- package/README.md +171 -16
- package/README.pt-BR.md +99 -13
- package/bin/pantheon-init.mjs +178 -21
- package/package.json +23 -14
- package/plugin.json +1 -1
- package/pyproject.toml +65 -0
- package/scripts/code_mode_server.py +431 -55
- package/scripts/cost.mjs +30 -14
- package/scripts/doctor.mjs +178 -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 +3 -33
- 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 +537 -128
- 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/release-beta-version.mjs +56 -60
- package/scripts/sync-artifacts.mjs +169 -0
- package/scripts/sync-tui.mjs +121 -53
- package/scripts/test-opencode-v1-v2-sandbox.sh +367 -96
- package/scripts/validation-policy.mjs +7 -7
- package/scripts/version-check.mjs +113 -108
- package/scripts/versioning.mjs +230 -86
- package/src/agents/mnemosyne.md +1 -1
- package/src/agents/zeus.md +2 -2
- package/src/mcp/code_mode_server.py +431 -55
- package/src/mcp/mcp_persistence_server.py +537 -128
- package/src/pantheon/auto-wake.ts +1 -5
- package/src/pantheon/background-job-board.ts +43 -1
- package/src/pantheon/compaction-handoff.ts +304 -0
- package/src/pantheon/cost-command.ts +345 -62
- package/src/pantheon/delegate-manager.ts +390 -8
- package/src/pantheon/delegation-finalize.ts +32 -0
- package/src/pantheon/delegation.ts +235 -18
- package/src/pantheon/file-persistence-salvage.ts +64 -0
- package/src/pantheon/file-persistence.ts +194 -45
- package/src/pantheon/native-probe.ts +234 -0
- package/src/pantheon/native-task-status.ts +139 -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/task-result-guard.ts +107 -0
- package/src/pantheon/token-opt.ts +146 -12
- package/src/pantheon/tool-ceiling.ts +159 -0
- package/src/pantheon/v2-events.ts +18 -1
- package/src/plugin-v2.ts +2 -14
- package/src/plugin.ts +28 -17
- 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 +116 -27
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +414 -150
- package/src/plugins/tui/dist/tui.js.map +1 -1
- package/src/plugins/tui/dist/tui.tsx +447 -84
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +1 -1
- package/src/plugins/tui/src/index.tsx +447 -84
- package/.pantheon/code-mode/.gitkeep +0 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-1.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-10.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-11.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-2.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-3.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-4.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-5.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-6.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-7.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-8.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-9.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/heartbeat.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/session.json +0 -11
- package/src/pantheon/delegate-task-adapter.ts +0 -444
|
@@ -4,14 +4,14 @@ export const VALIDATION_STATUS = Object.freeze({
|
|
|
4
4
|
WARN: 'WARN',
|
|
5
5
|
ERROR: 'ERROR',
|
|
6
6
|
SKIP: 'SKIP',
|
|
7
|
+
AMBIENTAL: 'AMBIENTAL',
|
|
8
|
+
NOT_TESTED: 'NOT_TESTED',
|
|
7
9
|
})
|
|
8
10
|
|
|
9
|
-
export function classifyDoctorExit(exitStatus,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
return VALIDATION_STATUS.ERROR
|
|
11
|
+
export function classifyDoctorExit(exitStatus, _output = '') {
|
|
12
|
+
return Number.isInteger(exitStatus) && exitStatus === 0
|
|
13
|
+
? VALIDATION_STATUS.PASS
|
|
14
|
+
: VALIDATION_STATUS.ERROR
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function classifyTuiExit(exitStatus) {
|
|
@@ -19,5 +19,5 @@ export function classifyTuiExit(exitStatus) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export function validationExitCode(doctorStatus, tuiStatus) {
|
|
22
|
-
return doctorStatus === VALIDATION_STATUS.
|
|
22
|
+
return doctorStatus === VALIDATION_STATUS.PASS && tuiStatus === VALIDATION_STATUS.PASS ? 0 : 1
|
|
23
23
|
}
|
|
@@ -1,151 +1,156 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* version-check.mjs — Single source of truth enforcement
|
|
4
|
-
*
|
|
5
|
-
* package.json is the SOURCE OF TRUTH for the Pantheon version.
|
|
6
|
-
* Every other manifest (pyproject.toml, plugin.json, src/plugins/tui/package.json)
|
|
7
|
-
* MUST carry the same version. This script:
|
|
8
|
-
*
|
|
9
|
-
* - compares every manifest against package.json and prints a divergence
|
|
10
|
-
* table when they differ (exit code 1),
|
|
11
|
-
* - with --fix, rewrites each divergent manifest to the package.json version.
|
|
12
|
-
*
|
|
13
|
-
* Mirrors the MANIFEST_FILES list in scripts/versioning.mjs so `apply`
|
|
14
|
-
* and `check` can never drift apart.
|
|
15
|
-
*
|
|
16
|
-
* Usage:
|
|
17
|
-
* node scripts/version-check.mjs # verify (exit 0 = in sync)
|
|
18
|
-
* node scripts/version-check.mjs --fix # sync all manifests
|
|
19
|
-
*/
|
|
2
|
+
/** Fail-closed version and lockfile validation. */
|
|
20
3
|
|
|
21
|
-
import { readFileSync
|
|
4
|
+
import { readFileSync } from 'node:fs'
|
|
22
5
|
import { join } from 'node:path'
|
|
23
|
-
import {
|
|
6
|
+
import { pathToFileURL } from 'node:url'
|
|
7
|
+
import {
|
|
8
|
+
LOCK_INVENTORY,
|
|
9
|
+
VERSION_MANIFEST_INVENTORY,
|
|
10
|
+
validateInventory,
|
|
11
|
+
writeInventoryVersion,
|
|
12
|
+
} from './manifest-inventory.mjs'
|
|
24
13
|
|
|
25
|
-
|
|
26
|
-
export const MANIFESTS =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
kind: 'json',
|
|
33
|
-
},
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
function readTomlVersion(filePath) {
|
|
37
|
-
const text = readFileSync(filePath, 'utf-8')
|
|
38
|
-
const match = text.match(/^version\s*=\s*"([^"]+)"/m)
|
|
39
|
-
if (!match) throw new Error(`no version field in ${filePath}`)
|
|
40
|
-
return match[1]
|
|
41
|
-
}
|
|
14
|
+
// Kept as a public compatibility API. New code must use MANIFEST_INVENTORY.
|
|
15
|
+
export const MANIFESTS = Object.freeze(
|
|
16
|
+
['pyproject.toml', 'plugin.json', 'src/plugins/tui/package.json'].map((file) => {
|
|
17
|
+
const entry = VERSION_MANIFEST_INVENTORY.find((item) => item.file === file)
|
|
18
|
+
return { name: file, file, kind: entry.kind }
|
|
19
|
+
}),
|
|
20
|
+
)
|
|
42
21
|
|
|
43
|
-
function
|
|
44
|
-
|
|
22
|
+
function readLegacyVersion(root, manifest) {
|
|
23
|
+
const path = join(root, manifest.file)
|
|
24
|
+
const text = readFileSync(path, 'utf8')
|
|
25
|
+
if (manifest.kind === 'toml') {
|
|
26
|
+
const match = text.match(/^version\s*=\s*"([^"]+)"/m)
|
|
27
|
+
if (!match) throw new Error(`${manifest.file} is missing version`)
|
|
28
|
+
return match[1]
|
|
29
|
+
}
|
|
30
|
+
const data = JSON.parse(text)
|
|
31
|
+
if (typeof data.version !== 'string') throw new Error(`${manifest.file} is missing version`)
|
|
32
|
+
return data.version
|
|
45
33
|
}
|
|
46
34
|
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
} catch {
|
|
51
|
-
return null
|
|
52
|
-
}
|
|
35
|
+
function readSourceVersion(root) {
|
|
36
|
+
const data = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
|
|
37
|
+
return typeof data.version === 'string' ? data.version : null
|
|
53
38
|
}
|
|
54
39
|
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const updated = text.replace(/^(version\s*=\s*")[^"]+(")/m, `$1${version}$2`)
|
|
59
|
-
writeFileSync(filePath, updated)
|
|
60
|
-
} else {
|
|
61
|
-
const content = JSON.parse(readFileSync(filePath, 'utf-8'))
|
|
62
|
-
content.version = version
|
|
63
|
-
writeFileSync(filePath, `${JSON.stringify(content, null, 2)}\n`)
|
|
64
|
-
}
|
|
40
|
+
function readLockVersion(root, entry) {
|
|
41
|
+
const data = JSON.parse(readFileSync(join(root, entry.file), 'utf8'))
|
|
42
|
+
return typeof data.version === 'string' ? data.version : null
|
|
65
43
|
}
|
|
66
44
|
|
|
67
45
|
/**
|
|
68
|
-
* Compare
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* @returns {{source: string, manifests: Array<{name: string, version: string|null, ok: boolean}>, ok: boolean}}
|
|
72
|
-
* - source: version read from package.json
|
|
73
|
-
* - manifests: per-manifest {name, version (null when unreadable), ok}
|
|
74
|
-
* - ok: true when every manifest matches the source version
|
|
46
|
+
* Compare versions while retaining the historical MANIFESTS result shape.
|
|
47
|
+
* Invalid/missing inventory entries are represented as null so callers can
|
|
48
|
+
* display a useful table; all CLI mutation paths use validateInventory first.
|
|
75
49
|
*/
|
|
76
50
|
export function compareVersions(root) {
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
51
|
+
let source = null
|
|
52
|
+
const errors = []
|
|
53
|
+
try {
|
|
54
|
+
source = readSourceVersion(root)
|
|
55
|
+
} catch (error) {
|
|
56
|
+
errors.push(`package.json: ${error.message}`)
|
|
57
|
+
}
|
|
58
|
+
const manifests = MANIFESTS.map((manifest) => {
|
|
59
|
+
let version = null
|
|
60
|
+
try {
|
|
61
|
+
version = readLegacyVersion(root, manifest)
|
|
62
|
+
} catch (error) {
|
|
63
|
+
errors.push(`${manifest.file}: ${error.message}`)
|
|
64
|
+
}
|
|
65
|
+
return { name: manifest.name, version, ok: version !== null && version === source }
|
|
81
66
|
})
|
|
82
|
-
|
|
67
|
+
const locks = LOCK_INVENTORY.map((entry) => {
|
|
68
|
+
let version = null
|
|
69
|
+
try {
|
|
70
|
+
version = readLockVersion(root, entry)
|
|
71
|
+
} catch (error) {
|
|
72
|
+
errors.push(`${entry.file}: ${error.message}`)
|
|
73
|
+
}
|
|
74
|
+
return { name: entry.file, version, ok: version !== null && version === source }
|
|
75
|
+
})
|
|
76
|
+
try {
|
|
77
|
+
validateInventory(root)
|
|
78
|
+
} catch (error) {
|
|
79
|
+
errors.push(error.message)
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
source,
|
|
83
|
+
manifests,
|
|
84
|
+
locks,
|
|
85
|
+
errors: [...new Set(errors)],
|
|
86
|
+
ok:
|
|
87
|
+
source !== null &&
|
|
88
|
+
manifests.every((item) => item.ok) &&
|
|
89
|
+
locks.every((item) => item.ok) &&
|
|
90
|
+
errors.length === 0,
|
|
91
|
+
}
|
|
83
92
|
}
|
|
84
93
|
|
|
85
94
|
/**
|
|
86
|
-
* Rewrite every
|
|
87
|
-
*
|
|
88
|
-
* @param {string} root - repository root
|
|
89
|
-
* @returns {number} count of manifests rewritten
|
|
95
|
+
* Rewrite only version metadata after every inventory entry has passed the
|
|
96
|
+
* structural preflight. A second validation is performed by the CLI.
|
|
90
97
|
*/
|
|
91
98
|
export function syncToSource(root) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return changed
|
|
99
|
+
const inventory = validateInventory(root, { allowVersionDivergence: true })
|
|
100
|
+
const source = inventory.sourceVersion
|
|
101
|
+
const changed = inventory.versions.filter(({ version }) => version !== source).length
|
|
102
|
+
const lockChanged = inventory.documents.filter(
|
|
103
|
+
({ entry, data }) => entry.role === 'lock' && data.version !== source,
|
|
104
|
+
).length
|
|
105
|
+
if (changed || lockChanged) writeInventoryVersion(inventory, source)
|
|
106
|
+
return changed + lockChanged
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
function printDivergenceTable(result) {
|
|
104
110
|
const rows = [
|
|
105
111
|
['manifest', 'version', 'status'],
|
|
106
|
-
...result.manifests.map((
|
|
112
|
+
...result.manifests.map((item) => [
|
|
113
|
+
item.name,
|
|
114
|
+
item.version ?? 'MISSING',
|
|
115
|
+
item.ok ? 'ok' : 'DIVERGENT',
|
|
116
|
+
]),
|
|
117
|
+
...result.locks.map((item) => [
|
|
118
|
+
item.name,
|
|
119
|
+
item.version ?? 'MISSING',
|
|
120
|
+
item.ok ? 'ok' : 'DIVERGENT',
|
|
121
|
+
]),
|
|
107
122
|
]
|
|
108
|
-
const widths = rows[0].map((_,
|
|
109
|
-
console.log(`Source of truth: package.json → v${result.source}\n`)
|
|
110
|
-
for (const row of rows)
|
|
111
|
-
console.log(row.map((cell,
|
|
112
|
-
}
|
|
123
|
+
const widths = rows[0].map((_, index) => Math.max(...rows.map((row) => row[index].length)))
|
|
124
|
+
console.log(`Source of truth: package.json → v${result.source ?? 'INVALID'}\n`)
|
|
125
|
+
for (const row of rows)
|
|
126
|
+
console.log(row.map((cell, index) => cell.padEnd(widths[index])).join(' '))
|
|
127
|
+
for (const error of result.errors) console.error(`version-check: ${error}`)
|
|
113
128
|
console.log('')
|
|
114
129
|
}
|
|
115
130
|
|
|
116
131
|
const isDirectRun = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href
|
|
117
132
|
|
|
118
133
|
if (isDirectRun) {
|
|
119
|
-
// npm scripts run from the package root, so the working directory is the
|
|
120
|
-
// repository root to check. Explicit cwd keeps the CLI testable.
|
|
121
134
|
const root = process.cwd()
|
|
122
135
|
const fix = process.argv.includes('--fix')
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
result = compareVersions(root)
|
|
126
|
-
} catch (error) {
|
|
127
|
-
console.error(`version-check: cannot read package.json — ${error.message}`)
|
|
128
|
-
process.exit(1)
|
|
129
|
-
}
|
|
130
|
-
|
|
136
|
+
const result = compareVersions(root)
|
|
131
137
|
if (result.ok) {
|
|
132
|
-
console.log(`✓ All manifests match package.json v${result.source}`)
|
|
138
|
+
console.log(`✓ All manifests match package.json v${result.source}; locks are in sync`)
|
|
133
139
|
process.exit(0)
|
|
134
140
|
}
|
|
135
|
-
|
|
136
141
|
printDivergenceTable(result)
|
|
137
|
-
if (fix) {
|
|
142
|
+
if (!fix) {
|
|
143
|
+
console.error('version-check: inventory is invalid or out of sync')
|
|
144
|
+
process.exit(1)
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
138
147
|
const changed = syncToSource(root)
|
|
139
148
|
const after = compareVersions(root)
|
|
140
|
-
if (after.ok)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
console.error(
|
|
145
|
-
`version-check: sync incomplete — ${after.manifests.filter((m) => !m.ok).length} manifest(s) still divergent`,
|
|
146
|
-
)
|
|
149
|
+
if (!after.ok) throw new Error(after.errors.join('; ') || 'inventory remains divergent')
|
|
150
|
+
console.log(`✓ Synced ${changed} metadata entries to v${after.source}`)
|
|
151
|
+
process.exit(0)
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error(`version-check: refusing to write: ${error.message}`)
|
|
147
154
|
process.exit(1)
|
|
148
155
|
}
|
|
149
|
-
console.error('version-check: manifests out of sync (run with --fix to sync)')
|
|
150
|
-
process.exit(1)
|
|
151
156
|
}
|