pantheon-opencode 1.4.2 → 1.5.0-beta.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.
- package/.pantheon/code-mode/.gitkeep +0 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-1.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-10.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-11.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-2.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-3.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-4.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-5.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-6.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-7.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-8.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-9.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/heartbeat.json +8 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/session.json +11 -0
- 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/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/README.md +158 -1189
- package/README.pt-BR.md +222 -0
- package/bin/pantheon-init.mjs +30 -11
- package/opencode.json +1 -0
- package/package.json +14 -3
- package/plugin.json +15 -0
- package/scripts/_pantheon_paths.py +48 -7
- package/scripts/ci-validate-yaml.py +7 -2
- package/scripts/code_mode_server.py +33 -2
- package/scripts/doctor.mjs +135 -127
- package/scripts/generate-preset-docs.mjs +127 -66
- package/scripts/generate-prompts.sh +2 -2
- package/scripts/install/cli-ui.mjs +8 -1
- package/scripts/install/config-migration.mjs +401 -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 +261 -88
- package/scripts/install/plugin.mjs +112 -42
- package/scripts/install/shared.mjs +13 -158
- package/scripts/install-mcp.mjs +44 -232
- package/scripts/mcp_persistence_server.py +344 -15
- package/scripts/mcp_resources_server.py +144 -40
- package/scripts/memory_mcp_server.py +2 -2
- package/scripts/recover-zenodo-deposition.mjs +146 -0
- package/scripts/sync-tui.mjs +32 -7
- package/scripts/test-opencode-v1-v2-sandbox.sh +591 -0
- package/scripts/uninstall.mjs +298 -954
- package/scripts/validate-zenodo-release.mjs +154 -0
- package/scripts/zenodo-artifact.mjs +21 -0
- package/scripts/zenodo-release-state.mjs +53 -0
- package/src/mcp/_pantheon_paths.py +48 -7
- package/src/mcp/code_mode_server.py +33 -2
- package/src/mcp/eval_store.py +1 -1
- package/src/mcp/mcp_persistence_server.py +344 -15
- 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/background-job-board.ts +67 -1
- package/src/pantheon/cost-command.ts +6 -2
- package/src/pantheon/delegate-manager.ts +384 -0
- package/src/pantheon/delegate-task-adapter.ts +444 -0
- package/src/pantheon/delegation-notify.ts +35 -20
- package/src/pantheon/model-command.ts +86 -32
- package/src/pantheon/token-opt.ts +555 -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 +131 -0
- package/src/pantheon/v2-hooks.ts +287 -0
- package/src/pantheon/v2-tool-definitions.ts +331 -0
- package/src/plugin-v2/index.ts +21 -0
- package/src/plugin-v2.ts +836 -0
- package/src/plugin.ts +57 -10
- 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 +10 -7
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +11 -8
- package/src/plugins/tui/dist/tui.js.map +1 -1
- package/src/plugins/tui/dist/tui.tsx +22 -16
- package/src/plugins/tui/package-lock.json +51 -51
- package/src/plugins/tui/package.json +7 -7
- package/src/plugins/tui/src/index.tsx +22 -16
- package/src/skills/README.md +0 -2
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import { execSync } from 'node:child_process'
|
|
6
6
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync } from 'node:fs'
|
|
7
|
-
import { join } from 'node:path'
|
|
7
|
+
import { isAbsolute, join, resolve } from 'node:path'
|
|
8
8
|
import { warning } from './cli-ui.mjs'
|
|
9
|
-
import { writeIfChanged } from './shared.mjs'
|
|
9
|
+
import { ROOT, writeIfChanged } from './shared.mjs'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Copy a plugin's runtime payload (src/index.tsx → index.tsx, dist/*,
|
|
13
|
-
* package.json) from source to destination.
|
|
13
|
+
* package.json and package-lock.json) from source to destination.
|
|
14
14
|
* @param {string} srcDir - Source plugin directory (e.g. ROOT/src/plugins/tui)
|
|
15
15
|
* @param {string} dstDir - Destination plugin directory
|
|
16
16
|
* @param {object} [options]
|
|
@@ -58,6 +58,19 @@ export function copyPluginFiles(srcDir, dstDir, { dryRun = false } = {}) {
|
|
|
58
58
|
else result.skipped++
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// Copy the lockfile so dependency installation is reproducible. A missing
|
|
62
|
+
// lockfile is intentionally not synthesized by the installer.
|
|
63
|
+
const lockSrc = join(srcDir, 'package-lock.json')
|
|
64
|
+
if (existsSync(lockSrc)) {
|
|
65
|
+
const lockStatus = writeIfChanged(
|
|
66
|
+
join(dstDir, 'package-lock.json'),
|
|
67
|
+
readFileSync(lockSrc, 'utf8'),
|
|
68
|
+
dryRun,
|
|
69
|
+
)
|
|
70
|
+
if (lockStatus === 'created') result.created++
|
|
71
|
+
else result.skipped++
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
return result
|
|
62
75
|
}
|
|
63
76
|
|
|
@@ -81,13 +94,31 @@ export function installPlugin(srcDir, dstDir, { dryRun = false, clean = false }
|
|
|
81
94
|
result.created += copyResult.created
|
|
82
95
|
result.skipped += copyResult.skipped
|
|
83
96
|
|
|
84
|
-
// Install plugin dependencies (@opentui/core, @opentui/solid, solid-js)
|
|
97
|
+
// Install plugin dependencies (@opentui/core, @opentui/solid, solid-js).
|
|
98
|
+
// npm ci is deterministic when the copied lockfile is present. The legacy
|
|
99
|
+
// fallback is opt-in because npm install may rewrite the dependency graph.
|
|
85
100
|
if (!dryRun) {
|
|
86
101
|
try {
|
|
87
|
-
execSync('npm
|
|
102
|
+
execSync('npm ci --omit=dev --no-audit --no-fund', { cwd: dstDir, stdio: 'pipe' })
|
|
88
103
|
} catch (e) {
|
|
89
|
-
|
|
90
|
-
|
|
104
|
+
if (process.env.PANTHEON_ALLOW_NPM_INSTALL_FALLBACK === '1') {
|
|
105
|
+
warning(`npm ci failed; explicit fallback enabled: ${e.message}`)
|
|
106
|
+
try {
|
|
107
|
+
execSync('npm install --omit=dev --no-audit --no-fund --package-lock=false', {
|
|
108
|
+
cwd: dstDir,
|
|
109
|
+
stdio: 'pipe',
|
|
110
|
+
})
|
|
111
|
+
} catch (fallbackError) {
|
|
112
|
+
warning(`Failed to install TUI plugin dependencies: ${fallbackError.message}`)
|
|
113
|
+
result.errors++
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
warning(
|
|
117
|
+
`npm ci failed; dependencies were not changed. Set ` +
|
|
118
|
+
`PANTHEON_ALLOW_NPM_INSTALL_FALLBACK=1 to explicitly allow npm install: ${e.message}`,
|
|
119
|
+
)
|
|
120
|
+
result.errors++
|
|
121
|
+
}
|
|
91
122
|
}
|
|
92
123
|
}
|
|
93
124
|
|
|
@@ -103,9 +134,12 @@ export function installPlugin(srcDir, dstDir, { dryRun = false, clean = false }
|
|
|
103
134
|
export function installPluginDependencies(pluginDir, { dryRun = false } = {}) {
|
|
104
135
|
if (dryRun) return
|
|
105
136
|
try {
|
|
106
|
-
execSync('npm
|
|
137
|
+
execSync('npm ci --omit=dev --no-audit --no-fund', { cwd: pluginDir, stdio: 'pipe' })
|
|
107
138
|
} catch (e) {
|
|
108
|
-
warning(
|
|
139
|
+
warning(
|
|
140
|
+
`npm ci failed; dependencies were not changed. Set ` +
|
|
141
|
+
`PANTHEON_ALLOW_NPM_INSTALL_FALLBACK=1 to explicitly allow npm install: ${e.message}`,
|
|
142
|
+
)
|
|
109
143
|
}
|
|
110
144
|
}
|
|
111
145
|
|
|
@@ -137,42 +171,70 @@ export function registerPlugin(tuiJsonPath, pluginId, { dryRun = false } = {}) {
|
|
|
137
171
|
}
|
|
138
172
|
|
|
139
173
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* copied plugins/pantheon-tui target, tsx and js eras)
|
|
144
|
-
* - the in-package source dir (src/plugins/tui) — a registration pointing
|
|
145
|
-
* into the installed package breaks on reinstall/upgrade (the dir is
|
|
146
|
-
* replaced under a live registration)
|
|
147
|
-
* - bare copied dirs (plugins/pantheon-tui) from any OLD install target —
|
|
148
|
-
* indistinguishable from the current copied dir without knowing the
|
|
149
|
-
* install target, so they are flagged too; syncTuiRegistration keeps the
|
|
150
|
-
* current ref via unregister-then-register
|
|
151
|
-
* - node_modules copies (npx cache installs of the vendored plugin)
|
|
174
|
+
* Exact relative markers written by previous installers. These are intentionally
|
|
175
|
+
* complete references, not suffixes: a user-owned path may contain
|
|
176
|
+
* `pantheon-opencode` or end in the same filename without being ours.
|
|
152
177
|
*/
|
|
153
178
|
export const TUI_STALE_SUFFIXES = [
|
|
154
|
-
'
|
|
155
|
-
'
|
|
156
|
-
'/
|
|
157
|
-
'
|
|
158
|
-
'
|
|
159
|
-
'
|
|
160
|
-
'/node_modules/pantheon-tui',
|
|
179
|
+
'plugins/pantheon-tui',
|
|
180
|
+
'plugins/pantheon-tui/dist/tui.tsx',
|
|
181
|
+
'plugins/pantheon-tui/dist/tui.js',
|
|
182
|
+
'npx pantheon-tui',
|
|
183
|
+
'npx -y pantheon-tui',
|
|
184
|
+
'npx:pantheon-tui',
|
|
161
185
|
]
|
|
162
186
|
|
|
187
|
+
const PACKAGE_TUI_PATHS = [
|
|
188
|
+
join(ROOT, 'src', 'plugins', 'tui'),
|
|
189
|
+
join(ROOT, 'src', 'plugins', 'tui', 'dist', 'tui.tsx'),
|
|
190
|
+
join(ROOT, 'src', 'plugins', 'tui', 'dist', 'tui.js'),
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
function normalizePluginPath(ref) {
|
|
194
|
+
return ref.replaceAll('\\', '/')
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function exactManagedPaths(knownPantheonPaths) {
|
|
198
|
+
return new Set(
|
|
199
|
+
[...PACKAGE_TUI_PATHS, ...knownPantheonPaths]
|
|
200
|
+
.filter((path) => typeof path === 'string')
|
|
201
|
+
.map((path) => normalizePluginPath(path)),
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function isExactNpxMarker(ref) {
|
|
206
|
+
return (
|
|
207
|
+
/^npx(?:\s+-y)?\s+pantheon-tui(?:@[A-Za-z0-9._-]+)?$/i.test(ref) ||
|
|
208
|
+
/^npx:pantheon-tui(?:@[A-Za-z0-9._-]+)?$/i.test(ref) ||
|
|
209
|
+
/(?:^|\/)\.npm\/_npx\/[^/]+\/node_modules\/pantheon-tui(?:\/|$)/i.test(ref)
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
|
|
163
213
|
/**
|
|
164
|
-
*
|
|
214
|
+
* Return whether a registration is unambiguously one of our old TUI refs.
|
|
215
|
+
*
|
|
165
216
|
* @param {unknown} ref - tui.json plugin entry
|
|
217
|
+
* @param {string[]} [knownPantheonPaths=[]] - paths owned by this installer
|
|
166
218
|
* @returns {boolean}
|
|
167
219
|
*/
|
|
168
|
-
export function
|
|
220
|
+
export function isPantheonTuiRef(ref, knownPantheonPaths = []) {
|
|
169
221
|
if (typeof ref !== 'string') return false
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
222
|
+
const normalized = normalizePluginPath(ref)
|
|
223
|
+
if (TUI_STALE_SUFFIXES.includes(normalized)) return true
|
|
224
|
+
if (isExactNpxMarker(normalized)) return true
|
|
225
|
+
|
|
226
|
+
const knownPaths = exactManagedPaths(knownPantheonPaths)
|
|
227
|
+
if (knownPaths.has(normalized)) return true
|
|
228
|
+
return isAbsolute(normalized) && knownPaths.has(normalizePluginPath(resolve(normalized)))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Whether a single tui.json plugin entry is a stale Pantheon TUI reference.
|
|
233
|
+
* @param {unknown} ref - tui.json plugin entry
|
|
234
|
+
* @returns {boolean}
|
|
235
|
+
*/
|
|
236
|
+
export function isStaleTuiRef(ref, knownPantheonPaths = []) {
|
|
237
|
+
return isPantheonTuiRef(ref, knownPantheonPaths)
|
|
176
238
|
}
|
|
177
239
|
|
|
178
240
|
/**
|
|
@@ -181,8 +243,10 @@ export function isStaleTuiRef(ref) {
|
|
|
181
243
|
* @param {unknown[]} pluginArray - tui.json plugin array
|
|
182
244
|
* @returns {string[]}
|
|
183
245
|
*/
|
|
184
|
-
export function staleTuiRefs(pluginArray) {
|
|
185
|
-
return (Array.isArray(pluginArray) ? pluginArray : []).filter(
|
|
246
|
+
export function staleTuiRefs(pluginArray, knownPantheonPaths = []) {
|
|
247
|
+
return (Array.isArray(pluginArray) ? pluginArray : []).filter((ref) =>
|
|
248
|
+
isStaleTuiRef(ref, knownPantheonPaths),
|
|
249
|
+
)
|
|
186
250
|
}
|
|
187
251
|
|
|
188
252
|
/**
|
|
@@ -193,7 +257,11 @@ export function staleTuiRefs(pluginArray) {
|
|
|
193
257
|
* @param {boolean} [options.dryRun=false]
|
|
194
258
|
* @returns {'created'|'skipped'}
|
|
195
259
|
*/
|
|
196
|
-
export function unregisterPlugin(
|
|
260
|
+
export function unregisterPlugin(
|
|
261
|
+
tuiJsonPath,
|
|
262
|
+
pluginId,
|
|
263
|
+
{ dryRun = false, knownPantheonPaths = [] } = {},
|
|
264
|
+
) {
|
|
197
265
|
if (!existsSync(tuiJsonPath)) {
|
|
198
266
|
// Nothing to clean — and never create an empty tui.json in a location
|
|
199
267
|
// OpenCode reads (the cross-location cleanup also touches global config
|
|
@@ -215,10 +283,12 @@ export function unregisterPlugin(tuiJsonPath, pluginId, { dryRun = false } = {})
|
|
|
215
283
|
// bare copy dirs from previous install targets, and npx cache copies.
|
|
216
284
|
// Without removing the absolute paths, each init run accumulates another
|
|
217
285
|
// TUI plugin and OpenCode loads stale copies.
|
|
218
|
-
const exactStale =
|
|
286
|
+
const exactStale = new Set(
|
|
287
|
+
[pluginId, `${pluginId}/dist/tui.tsx`, `${pluginId}/dist/tui.js`].map(normalizePluginPath),
|
|
288
|
+
)
|
|
219
289
|
tuiConfig.plugin = tuiConfig.plugin.filter((ref) => {
|
|
220
|
-
if (exactStale.
|
|
221
|
-
return !
|
|
290
|
+
if (typeof ref === 'string' && exactStale.has(normalizePluginPath(ref))) return false
|
|
291
|
+
return !isPantheonTuiRef(ref, knownPantheonPaths)
|
|
222
292
|
})
|
|
223
293
|
const tuiContent = `${JSON.stringify(tuiConfig, null, 2)}\n`
|
|
224
294
|
return writeIfChanged(tuiJsonPath, tuiContent, dryRun)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* shared.mjs — Shared utilities for
|
|
2
|
+
* shared.mjs — Shared utilities for the OpenCode installer
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import {
|
|
@@ -26,8 +26,6 @@ import yaml from 'js-yaml'
|
|
|
26
26
|
export const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
27
27
|
export const ROOT = join(__dirname, '..', '..')
|
|
28
28
|
export const AGENTS_DIR = join(ROOT, 'src', 'agents')
|
|
29
|
-
// PLATFORM_DIR is deprecated — platform/ was removed in v1.0
|
|
30
|
-
export const PLATFORM_DIR = join(ROOT, 'platform')
|
|
31
29
|
|
|
32
30
|
// Auto-detect agent names from agents/ directory
|
|
33
31
|
export function getAgentNames() {
|
|
@@ -43,33 +41,7 @@ export function getAgentNames() {
|
|
|
43
41
|
// Cached constant for backward compatibility
|
|
44
42
|
export const AGENT_NAMES = getAgentNames()
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
export const PLATFORM_DETECTORS = {
|
|
48
|
-
opencode: (target) =>
|
|
49
|
-
existsSync(join(target, 'opencode.json')) ||
|
|
50
|
-
existsSync(join(target, 'platform', 'opencode', 'opencode.json')),
|
|
51
|
-
claude: (target) => existsSync(join(target, '.claude')) || existsSync(join(target, 'CLAUDE.md')),
|
|
52
|
-
cursor: (target) =>
|
|
53
|
-
existsSync(join(target, '.cursor')) || existsSync(join(target, '.cursorrules')),
|
|
54
|
-
windsurf: (target) =>
|
|
55
|
-
existsSync(join(target, '.windsurf')) || existsSync(join(target, '.windsurfrules')),
|
|
56
|
-
copilot: (target) =>
|
|
57
|
-
existsSync(join(target, '.github', 'copilot-instructions.md')) ||
|
|
58
|
-
existsSync(join(target, '.vscode')),
|
|
59
|
-
continue: (target) =>
|
|
60
|
-
existsSync(join(target, '.continue', 'config.yaml')) || existsSync(join(target, '.continue')),
|
|
61
|
-
cline: (target) => existsSync(join(target, '.clinerules')),
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export const summary = {
|
|
65
|
-
opencode: { created: 0, skipped: 0, errors: 0 },
|
|
66
|
-
claude: { created: 0, skipped: 0, errors: 0 },
|
|
67
|
-
cursor: { created: 0, skipped: 0, errors: 0 },
|
|
68
|
-
windsurf: { created: 0, skipped: 0, errors: 0 },
|
|
69
|
-
copilot: { created: 0, skipped: 0, errors: 0 },
|
|
70
|
-
continue: { created: 0, skipped: 0, errors: 0 },
|
|
71
|
-
cline: { created: 0, skipped: 0, errors: 0 },
|
|
72
|
-
}
|
|
44
|
+
export const summary = { opencode: { created: 0, skipped: 0, errors: 0 } }
|
|
73
45
|
|
|
74
46
|
export function showHelp() {
|
|
75
47
|
console.log(`
|
|
@@ -78,9 +50,7 @@ pantheon-init.mjs — Pantheon OpenCode installer
|
|
|
78
50
|
Usage:
|
|
79
51
|
npx pantheon-opencode init auto-detect, cwd
|
|
80
52
|
npx pantheon-opencode init --project auto-detect, project
|
|
81
|
-
npx pantheon-opencode init --project
|
|
82
|
-
npx pantheon-opencode init --project --platforms all all platforms
|
|
83
|
-
npx pantheon-opencode init --detect detect platforms without installing
|
|
53
|
+
npx pantheon-opencode init --project install in a project
|
|
84
54
|
npx pantheon-opencode init --project --dry-run preview without writing
|
|
85
55
|
npx pantheon-opencode init --project --backup create timestamped backup before writing
|
|
86
56
|
npx pantheon-opencode init --project --clean wipe + fresh install (all components)
|
|
@@ -101,19 +71,8 @@ Clean mode (--clean):
|
|
|
101
71
|
re-installs fresh from source. Useful after removing/renaming agents or skills.
|
|
102
72
|
OFF by default — without --clean only copies new/changed files (never deletes).
|
|
103
73
|
|
|
104
|
-
|
|
74
|
+
Platform:
|
|
105
75
|
opencode → .opencode/agents/ + opencode.json
|
|
106
|
-
claude → .claude/agents/ + CLAUDE.md + settings.json
|
|
107
|
-
cursor → .cursor/rules/ (renamed .mdc files)
|
|
108
|
-
windsurf → .windsurf/agents/ + .windsurfrules
|
|
109
|
-
copilot → .github/agents/ symlinks + .vscode/settings.json check
|
|
110
|
-
continue → .continue/rules/ + .continue/config.yaml
|
|
111
|
-
cline → .clinerules/ (no extension, plain markdown)
|
|
112
|
-
all → install every platform
|
|
113
|
-
|
|
114
|
-
When --platforms is omitted, the script auto-detects which platforms
|
|
115
|
-
the target project already supports (based on config files present).
|
|
116
|
-
If none are detected, ALL platforms are installed.
|
|
117
76
|
`)
|
|
118
77
|
}
|
|
119
78
|
|
|
@@ -206,63 +165,25 @@ export function createBackup(target) {
|
|
|
206
165
|
}
|
|
207
166
|
|
|
208
167
|
export function detectAndReport(target) {
|
|
209
|
-
const
|
|
210
|
-
opencode: 'OpenCode',
|
|
211
|
-
claude: 'Claude Code',
|
|
212
|
-
cursor: 'Cursor',
|
|
213
|
-
windsurf: 'Windsurf',
|
|
214
|
-
copilot: 'VS Code / Copilot',
|
|
215
|
-
continue: 'Continue.dev',
|
|
216
|
-
cline: 'Cline',
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const CONFIG_FILES = {
|
|
220
|
-
opencode: () => 'opencode.json',
|
|
221
|
-
claude: () => '.claude/ or CLAUDE.md',
|
|
222
|
-
cursor: () => '.cursor/ or .cursorrules',
|
|
223
|
-
windsurf: () => '.windsurf/ or .windsurfrules',
|
|
224
|
-
copilot: () => '.github/copilot-instructions.md or .vscode/',
|
|
225
|
-
continue: () => '.continue/config.yaml or .continue/',
|
|
226
|
-
cline: () => '.clinerules',
|
|
227
|
-
}
|
|
168
|
+
const found = detectPlatforms(target).length > 0
|
|
228
169
|
|
|
229
170
|
console.log(`\n 🔍 Pantheon Platform Detection`)
|
|
230
171
|
console.log(` Target: ${target}\n`)
|
|
231
172
|
|
|
232
|
-
const results = []
|
|
233
|
-
for (const [platform, detector] of Object.entries(PLATFORM_DETECTORS)) {
|
|
234
|
-
const found = detector(target)
|
|
235
|
-
results.push({ platform, found })
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Table header
|
|
239
173
|
console.log(` ${'Platform'.padEnd(12)} ${'Detected?'.padEnd(12)} Config file`)
|
|
240
174
|
console.log(` ${'─'.repeat(55)}`)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
console.log(` ${PLATFORM_LABELS[r.platform].padEnd(12)} ${status.padEnd(12)} ${configFile}`)
|
|
175
|
+
const status = (found ? '✅ YES' : '❌ no').padEnd(12)
|
|
176
|
+
console.log(` ${'OpenCode'.padEnd(12)} ${status} ${found ? 'opencode.json' : '(not found)'}`)
|
|
177
|
+
console.log(`\n 📊 ${found ? 1 : 0} of 1 platforms detected.`)
|
|
178
|
+
if (found) {
|
|
179
|
+
console.log(' → Install with: npx pantheon-opencode init')
|
|
247
180
|
}
|
|
248
181
|
|
|
249
|
-
|
|
250
|
-
if (detected.length > 0) {
|
|
251
|
-
const names = detected.map((r) => r.platform).join(',')
|
|
252
|
-
console.log(` → Install with: npx pantheon-opencode init --platforms ${names}`)
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return detected.map((r) => r.platform)
|
|
182
|
+
return found ? ['opencode'] : []
|
|
256
183
|
}
|
|
257
184
|
|
|
258
185
|
export function detectPlatforms(target) {
|
|
259
|
-
|
|
260
|
-
for (const [platform, detector] of Object.entries(PLATFORM_DETECTORS)) {
|
|
261
|
-
if (detector(target)) {
|
|
262
|
-
detected.push(platform)
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
return detected
|
|
186
|
+
return existsSync(join(target, 'opencode.json')) ? ['opencode'] : []
|
|
266
187
|
}
|
|
267
188
|
|
|
268
189
|
export function sourceDirValid(dir) {
|
|
@@ -569,16 +490,6 @@ export function validateMcpServers(mcpServers, _agentTools = []) {
|
|
|
569
490
|
}
|
|
570
491
|
|
|
571
492
|
export function printSummary(target, platforms) {
|
|
572
|
-
const PLATFORM_LABELS = {
|
|
573
|
-
opencode: 'OpenCode',
|
|
574
|
-
claude: 'Claude Code',
|
|
575
|
-
cursor: 'Cursor',
|
|
576
|
-
windsurf: 'Windsurf',
|
|
577
|
-
copilot: 'VS Code / Copilot',
|
|
578
|
-
continue: 'Continue.dev',
|
|
579
|
-
cline: 'Cline',
|
|
580
|
-
}
|
|
581
|
-
|
|
582
493
|
console.log('')
|
|
583
494
|
console.log('='.repeat(60))
|
|
584
495
|
console.log('📋 Installation Summary')
|
|
@@ -590,7 +501,7 @@ export function printSummary(target, platforms) {
|
|
|
590
501
|
let totalErrors = 0
|
|
591
502
|
|
|
592
503
|
for (const platform of platforms) {
|
|
593
|
-
const label =
|
|
504
|
+
const label = platform === 'opencode' ? 'OpenCode' : platform
|
|
594
505
|
const stats = summary[platform]
|
|
595
506
|
totalCreated += stats.created
|
|
596
507
|
totalSkipped += stats.skipped
|
|
@@ -624,62 +535,6 @@ export function printSummary(target, platforms) {
|
|
|
624
535
|
console.log('')
|
|
625
536
|
}
|
|
626
537
|
|
|
627
|
-
if (platforms.includes('claude')) {
|
|
628
|
-
console.log(' Claude Code:')
|
|
629
|
-
console.log(` - Run \`claude\` in ${target}`)
|
|
630
|
-
console.log(' - Agents in .claude/agents/')
|
|
631
|
-
console.log(' - Skills in .claude/skills/')
|
|
632
|
-
console.log(' - Settings in .claude/settings.json')
|
|
633
|
-
console.log('')
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
if (platforms.includes('cursor')) {
|
|
637
|
-
console.log(' Cursor:')
|
|
638
|
-
console.log(` - Rules in .cursor/rules/ (.mdc format)`)
|
|
639
|
-
console.log(' - Skills in .cursor/skills/')
|
|
640
|
-
console.log(' - AGENTS.md in project root')
|
|
641
|
-
console.log(' - Use @agent-name in Agent mode')
|
|
642
|
-
console.log('')
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
if (platforms.includes('windsurf')) {
|
|
646
|
-
console.log(' Windsurf (Cascade):')
|
|
647
|
-
console.log(` - Rules in .windsurf/rules/`)
|
|
648
|
-
console.log(' - Skills in .windsurf/skills/')
|
|
649
|
-
console.log(' - Workflows in .windsurf/workflows/ (/orchestrate, /code-review)')
|
|
650
|
-
console.log(' - AGENTS.md in project root')
|
|
651
|
-
console.log('')
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
if (platforms.includes('copilot')) {
|
|
655
|
-
console.log(' VS Code / Copilot:')
|
|
656
|
-
console.log(` - Agents in .github/agents/`)
|
|
657
|
-
console.log(' - Ensure .vscode/settings.json has plugin config')
|
|
658
|
-
console.log(' - Use @agent-name in VS Code Copilot Chat')
|
|
659
|
-
console.log(' - Plugin manifest in plugin.json')
|
|
660
|
-
console.log('')
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
if (platforms.includes('continue')) {
|
|
664
|
-
console.log(' Continue.dev:')
|
|
665
|
-
console.log(` - Rules in .continue/rules/`)
|
|
666
|
-
console.log(' - Config in .continue/config.yaml')
|
|
667
|
-
console.log(' - Rules are injected into system prompts (no @name invocation)')
|
|
668
|
-
console.log(' - Edit config.yaml to set API keys and models')
|
|
669
|
-
console.log(' - Use /reload to apply config changes')
|
|
670
|
-
console.log('')
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
if (platforms.includes('cline')) {
|
|
674
|
-
console.log(' Cline:')
|
|
675
|
-
console.log(` - Agent rules in .clinerules/ (no extension, plain markdown)`)
|
|
676
|
-
console.log(' - Skills in .clinerules/skills/')
|
|
677
|
-
console.log(' - Commands in .clinerules/commands/')
|
|
678
|
-
console.log(' - AGENTS.md in project root')
|
|
679
|
-
console.log(' - Invoke agents with @agent-name in Cline chat')
|
|
680
|
-
console.log('')
|
|
681
|
-
}
|
|
682
|
-
|
|
683
538
|
console.log(' 📚 Full documentation: https://github.com/ils15/pantheon')
|
|
684
539
|
console.log(' 🐛 Report issues: https://github.com/ils15/pantheon/issues')
|
|
685
540
|
}
|