pantheon-opencode 1.3.0 → 1.3.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/README.md +11 -0
- package/package.json +1 -1
- package/scripts/doctor.mjs +80 -31
- package/scripts/validation-policy.mjs +18 -0
- package/src/plugins/hook-runner.ts +44 -4
- package/src/plugins/tui/package-lock.json +34 -5
- package/src/plugins/tui/package.json +1 -1
package/README.md
CHANGED
|
@@ -187,6 +187,17 @@ opencode
|
|
|
187
187
|
> **Minimal:** `--headless --no-mcp` installs only agents (~2s).
|
|
188
188
|
> **Full:** `--headless` also creates Python venv + MCP servers (memory, persistence, KV, vision).
|
|
189
189
|
|
|
190
|
+
### Doctor validation statuses
|
|
191
|
+
|
|
192
|
+
The doctor reports each check as **PASS**, **WARN**, **ERROR**, or **SKIP**. WARN is
|
|
193
|
+
advisory and exits 0; ERROR is blocking and exits 2. The `global` and `sandbox`
|
|
194
|
+
profiles require the core `pantheon-memory` and `pantheon-resources` MCPs, while
|
|
195
|
+
`lite` treats MCPs and optional helpers (`platform`, `gh_grep`, Context7, and
|
|
196
|
+
`validate-agent-frontmatter.py`) as informational/skipped. Optional warnings are
|
|
197
|
+
never used to hide missing required MCPs. When ERROR and WARN coexist, the final
|
|
198
|
+
summary explicitly reports the blocking error and exit code 2; it never reports a
|
|
199
|
+
positive “no blocking errors” result.
|
|
200
|
+
|
|
190
201
|
---
|
|
191
202
|
|
|
192
203
|
### Approval Gates
|
package/package.json
CHANGED
package/scripts/doctor.mjs
CHANGED
|
@@ -18,16 +18,14 @@
|
|
|
18
18
|
* node scripts/doctor.mjs --verbose
|
|
19
19
|
* node scripts/doctor.mjs --help
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* 1 = warnings only
|
|
24
|
-
* 2 = errors (needs attention)
|
|
21
|
+
* Result classification: PASS, WARN (advisory), ERROR (blocking), or SKIP.
|
|
22
|
+
* Exit codes: 0 = no blocking errors (warnings are allowed), 2 = errors.
|
|
25
23
|
*/
|
|
26
24
|
|
|
27
25
|
import { spawn as spawnAsync, spawnSync } from 'node:child_process'
|
|
28
26
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'
|
|
29
27
|
import { homedir } from 'node:os'
|
|
30
|
-
import { basename, dirname, join } from 'node:path'
|
|
28
|
+
import { basename, dirname, join, resolve } from 'node:path'
|
|
31
29
|
import { fileURLToPath } from 'node:url'
|
|
32
30
|
|
|
33
31
|
// ---------------------------------------------------------------------------
|
|
@@ -67,6 +65,7 @@ function parseArgs(argv) {
|
|
|
67
65
|
fix: false,
|
|
68
66
|
verbose: false,
|
|
69
67
|
help: false,
|
|
68
|
+
profile: process.env.PANTHEON_PROFILE ?? 'auto',
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
for (let i = 2; i < argv.length; i++) {
|
|
@@ -83,6 +82,9 @@ function parseArgs(argv) {
|
|
|
83
82
|
case '--verbose':
|
|
84
83
|
args.verbose = true
|
|
85
84
|
break
|
|
85
|
+
case '--profile':
|
|
86
|
+
args.profile = argv[++i] ?? 'auto'
|
|
87
|
+
break
|
|
86
88
|
case '--help':
|
|
87
89
|
case '-h':
|
|
88
90
|
args.help = true
|
|
@@ -97,6 +99,10 @@ function parseArgs(argv) {
|
|
|
97
99
|
args.target = process.cwd()
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
if (args.profile === 'auto') {
|
|
103
|
+
args.profile = args.target.includes('pantheon-sandbox') ? 'sandbox' : 'global'
|
|
104
|
+
}
|
|
105
|
+
|
|
100
106
|
// Resolve to absolute
|
|
101
107
|
if (!args.target.startsWith('/')) {
|
|
102
108
|
args.target = join(process.cwd(), args.target)
|
|
@@ -129,7 +135,6 @@ function pass(msg) {
|
|
|
129
135
|
}
|
|
130
136
|
function warn(msg) {
|
|
131
137
|
emit('warn', msg)
|
|
132
|
-
if (exitCode < 1) exitCode = 1
|
|
133
138
|
}
|
|
134
139
|
function error(msg) {
|
|
135
140
|
emit('error', msg)
|
|
@@ -153,6 +158,7 @@ function showHelp() {
|
|
|
153
158
|
node scripts/doctor.mjs auto-detect, cwd
|
|
154
159
|
node scripts/doctor.mjs --target /path/to/project target project
|
|
155
160
|
node scripts/doctor.mjs --platform opencode specific platform
|
|
161
|
+
node scripts/doctor.mjs --profile global|lite|sandbox profile policy
|
|
156
162
|
node scripts/doctor.mjs --fix attempt auto-fixes
|
|
157
163
|
node scripts/doctor.mjs --verbose detailed output
|
|
158
164
|
node scripts/doctor.mjs --help show this help
|
|
@@ -168,9 +174,10 @@ function showHelp() {
|
|
|
168
174
|
F. Runtime Layer — venv python + pinned pip dependencies
|
|
169
175
|
|
|
170
176
|
Exit codes:
|
|
171
|
-
0 —
|
|
172
|
-
|
|
173
|
-
|
|
177
|
+
0 — no blocking errors (warnings are advisory)
|
|
178
|
+
2 — blocking errors
|
|
179
|
+
|
|
180
|
+
Profiles: global (core MCPs required), lite (MCPs optional), sandbox (core MCPs required)
|
|
174
181
|
|
|
175
182
|
Report bugs: https://github.com/ils15/pantheon/issues
|
|
176
183
|
`)
|
|
@@ -239,7 +246,7 @@ function checkAgentFiles(args) {
|
|
|
239
246
|
|
|
240
247
|
// Determine which platforms to check
|
|
241
248
|
if (!existsSync(PLATFORM_DIR)) {
|
|
242
|
-
|
|
249
|
+
info(`Platform component not distributed in this package — platform check skipped (${args.profile} profile)`)
|
|
243
250
|
return
|
|
244
251
|
}
|
|
245
252
|
const platformDirs = readdirSync(PLATFORM_DIR, { withFileTypes: true })
|
|
@@ -248,7 +255,7 @@ function checkAgentFiles(args) {
|
|
|
248
255
|
.filter((name) => !args.platform || name === args.platform)
|
|
249
256
|
|
|
250
257
|
if (platformDirs.length === 0) {
|
|
251
|
-
|
|
258
|
+
info(`No platform directories found in platform/ — platform check skipped (${args.profile} profile)`)
|
|
252
259
|
return
|
|
253
260
|
}
|
|
254
261
|
|
|
@@ -354,9 +361,14 @@ function checkMcpConfig(args) {
|
|
|
354
361
|
section('B. MCP Configuration')
|
|
355
362
|
|
|
356
363
|
const configs = collectMcpConfigs(args)
|
|
364
|
+
const requiredMcpNames = args.profile === 'lite' ? [] : ['pantheon-memory', 'pantheon-resources']
|
|
357
365
|
|
|
358
366
|
if (configs.length === 0) {
|
|
359
|
-
|
|
367
|
+
if (requiredMcpNames.length > 0) {
|
|
368
|
+
error(`No opencode.json found; required MCPs missing: ${requiredMcpNames.join(', ')}`)
|
|
369
|
+
} else {
|
|
370
|
+
info(`No opencode.json found for ${args.profile} profile — MCP check skipped`)
|
|
371
|
+
}
|
|
360
372
|
return
|
|
361
373
|
}
|
|
362
374
|
|
|
@@ -365,11 +377,12 @@ function checkMcpConfig(args) {
|
|
|
365
377
|
|
|
366
378
|
const mcp = cfg.data.mcp
|
|
367
379
|
if (!mcp || typeof mcp !== 'object') {
|
|
368
|
-
|
|
380
|
+
if (requiredMcpNames.length > 0) error(`${cfg.label}: required MCPs missing — no "mcp" section`)
|
|
381
|
+
else info(`${cfg.label}: no "mcp" section (${args.profile} profile — optional)`)
|
|
369
382
|
continue
|
|
370
383
|
}
|
|
371
384
|
|
|
372
|
-
// 1. gh_grep MCP check
|
|
385
|
+
// 1. gh_grep MCP check (optional in every supported profile)
|
|
373
386
|
const ghGrep = mcp.gh_grep
|
|
374
387
|
if (ghGrep) {
|
|
375
388
|
if (ghGrep.type === 'remote' && ghGrep.url === 'https://mcp.grep.app') {
|
|
@@ -383,7 +396,7 @@ function checkMcpConfig(args) {
|
|
|
383
396
|
warn(`${cfg.label}: gh_grep MCP may need review — ${detail}`)
|
|
384
397
|
}
|
|
385
398
|
} else {
|
|
386
|
-
|
|
399
|
+
info(`${cfg.label}: optional gh_grep MCP not configured (${args.profile} profile)`)
|
|
387
400
|
}
|
|
388
401
|
|
|
389
402
|
// 2. Context7 MCP check
|
|
@@ -406,7 +419,7 @@ function checkMcpConfig(args) {
|
|
|
406
419
|
warn(`${cfg.label}: Context7 MCP issues — ${details.join(', ')}`)
|
|
407
420
|
}
|
|
408
421
|
} else {
|
|
409
|
-
|
|
422
|
+
info(`${cfg.label}: optional Context7 MCP not configured (${args.profile} profile)`)
|
|
410
423
|
}
|
|
411
424
|
|
|
412
425
|
// 3. Check for deprecated "tools" field format
|
|
@@ -450,6 +463,14 @@ function checkMcpConfig(args) {
|
|
|
450
463
|
}
|
|
451
464
|
}
|
|
452
465
|
}
|
|
466
|
+
|
|
467
|
+
if (requiredMcpNames.length > 0) {
|
|
468
|
+
const configured = new Set(configs.flatMap((cfg) => Object.keys(cfg.data.mcp ?? {})))
|
|
469
|
+
for (const required of requiredMcpNames) {
|
|
470
|
+
if (configured.has(required)) pass(`Required MCP "${required}" configured in an available config`)
|
|
471
|
+
else error(`Required MCP "${required}" not configured in any available config`)
|
|
472
|
+
}
|
|
473
|
+
}
|
|
453
474
|
}
|
|
454
475
|
|
|
455
476
|
// ---------------------------------------------------------------------------
|
|
@@ -558,7 +579,11 @@ async function checkMcpRuntimeSmoke(args) {
|
|
|
558
579
|
}
|
|
559
580
|
|
|
560
581
|
if (local.length === 0) {
|
|
561
|
-
|
|
582
|
+
if (args.profile === 'lite') {
|
|
583
|
+
info('No local MCP servers found in lite profile — smoke test skipped')
|
|
584
|
+
} else {
|
|
585
|
+
error('No local MCP servers found in any config — required runtime MCPs are missing')
|
|
586
|
+
}
|
|
562
587
|
return
|
|
563
588
|
}
|
|
564
589
|
|
|
@@ -620,7 +645,7 @@ function checkPermissionMismatches(args) {
|
|
|
620
645
|
// Locate the validation script
|
|
621
646
|
const validator = join(ROOT, 'scripts', 'validate-agent-frontmatter.py')
|
|
622
647
|
if (!existsSync(validator)) {
|
|
623
|
-
|
|
648
|
+
info(`validate-agent-frontmatter.py not found — optional helper skipped (${args.profile} profile)`)
|
|
624
649
|
return
|
|
625
650
|
}
|
|
626
651
|
|
|
@@ -871,14 +896,18 @@ function checkRequirementLine(line, installed) {
|
|
|
871
896
|
}
|
|
872
897
|
}
|
|
873
898
|
|
|
874
|
-
function checkVenvLayer() {
|
|
899
|
+
function checkVenvLayer(args) {
|
|
875
900
|
section('F. Runtime Layer — Venv, Python & Dependencies')
|
|
876
901
|
|
|
877
902
|
const configDir = join(homedir(), '.config', 'opencode')
|
|
878
903
|
const venvPython = join(configDir, '.venv', 'bin', 'python3')
|
|
879
904
|
|
|
880
905
|
if (!existsSync(venvPython)) {
|
|
881
|
-
|
|
906
|
+
if (args.profile === 'lite') {
|
|
907
|
+
info(`Venv python not found — runtime layer skipped for lite profile`)
|
|
908
|
+
} else {
|
|
909
|
+
error(`Venv python not found: ${venvPython} (run \`pantheon-opencode init\` to create it)`)
|
|
910
|
+
}
|
|
882
911
|
return
|
|
883
912
|
}
|
|
884
913
|
pass(`Venv python exists: ${venvPython}`)
|
|
@@ -924,6 +953,30 @@ function checkVenvLayer() {
|
|
|
924
953
|
// Summary
|
|
925
954
|
// ---------------------------------------------------------------------------
|
|
926
955
|
|
|
956
|
+
/**
|
|
957
|
+
* Return the final doctor status message without masking blocking errors.
|
|
958
|
+
* @param {{ error: number; warn: number }} summaryCounts
|
|
959
|
+
* @param {number} summaryExitCode
|
|
960
|
+
* @returns {string}
|
|
961
|
+
*/
|
|
962
|
+
export function summaryMessage(summaryCounts, summaryExitCode) {
|
|
963
|
+
if (summaryCounts.error > 0 || summaryExitCode !== 0) {
|
|
964
|
+
const errorText = summaryCounts.error > 0
|
|
965
|
+
? `${summaryCounts.error} blocking error(s) found`
|
|
966
|
+
: 'Blocking check failure'
|
|
967
|
+
const warningText = summaryCounts.warn > 0
|
|
968
|
+
? `; ${summaryCounts.warn} warning(s) remain advisory`
|
|
969
|
+
: ''
|
|
970
|
+
return `❌ ${errorText}${warningText} — exit code ${summaryExitCode}`
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
if (summaryCounts.warn > 0) {
|
|
974
|
+
return `⚠️ Checks passed with ${summaryCounts.warn} warning(s) — warnings are advisory`
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
return '✅ All checks passed!'
|
|
978
|
+
}
|
|
979
|
+
|
|
927
980
|
function printSummary(targetPath) {
|
|
928
981
|
console.log(`\n${'='.repeat(60)}`)
|
|
929
982
|
console.log(' Summary')
|
|
@@ -934,13 +987,7 @@ function printSummary(targetPath) {
|
|
|
934
987
|
console.log(` ${ICON.info} ${counts.info} info`)
|
|
935
988
|
console.log('')
|
|
936
989
|
|
|
937
|
-
|
|
938
|
-
console.log(' ✅ All checks passed!')
|
|
939
|
-
} else if (exitCode === 1) {
|
|
940
|
-
console.log(' ⚠️ Warnings found — review above (some may be auto-fixable with --fix)')
|
|
941
|
-
} else {
|
|
942
|
-
console.log(' ❌ Errors found — needs attention')
|
|
943
|
-
}
|
|
990
|
+
console.log(` ${summaryMessage(counts, exitCode)}`)
|
|
944
991
|
|
|
945
992
|
console.log(`\n Target: ${process.argv.includes('--target') ? targetPath : 'current directory'}`)
|
|
946
993
|
console.log('')
|
|
@@ -994,7 +1041,9 @@ async function main() {
|
|
|
994
1041
|
process.exit(exitCode)
|
|
995
1042
|
}
|
|
996
1043
|
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1044
|
+
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
1045
|
+
main().catch((err) => {
|
|
1046
|
+
console.error(`❌ Doctor crashed: ${err.stack ?? err.message}`)
|
|
1047
|
+
process.exit(2)
|
|
1048
|
+
})
|
|
1049
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Status/exit policy shared by installation validation and its tests. */
|
|
2
|
+
export const VALIDATION_STATUS = Object.freeze({ PASS: 'PASS', WARN: 'WARN', ERROR: 'ERROR', SKIP: 'SKIP' })
|
|
3
|
+
|
|
4
|
+
export function classifyDoctorExit(exitStatus, output = '') {
|
|
5
|
+
if (exitStatus === 0) return VALIDATION_STATUS.PASS
|
|
6
|
+
if (exitStatus === 1 && !/(?:❌\s*)?[1-9]\d*\s+errors?/i.test(output)) {
|
|
7
|
+
return VALIDATION_STATUS.WARN
|
|
8
|
+
}
|
|
9
|
+
return VALIDATION_STATUS.ERROR
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function classifyTuiExit(exitStatus) {
|
|
13
|
+
return exitStatus === 0 ? VALIDATION_STATUS.PASS : VALIDATION_STATUS.ERROR
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function validationExitCode(doctorStatus, tuiStatus) {
|
|
17
|
+
return doctorStatus === VALIDATION_STATUS.ERROR || tuiStatus === VALIDATION_STATUS.ERROR ? 1 : 0
|
|
18
|
+
}
|
|
@@ -98,21 +98,37 @@ export function runHook(
|
|
|
98
98
|
const scriptPath = path.join(opts.cwd ?? resolveHooksDir(), script)
|
|
99
99
|
const timeout = opts.timeout ?? HOOK_TIMEOUT_MS
|
|
100
100
|
|
|
101
|
+
let serializedPayload: string
|
|
102
|
+
try {
|
|
103
|
+
serializedPayload = JSON.stringify(payload)
|
|
104
|
+
} catch (err) {
|
|
105
|
+
// Fail closed: a scanner hook must not run without the payload it is
|
|
106
|
+
// supposed to inspect, and serialization errors must never reject.
|
|
107
|
+
return Promise.resolve({
|
|
108
|
+
code: 1,
|
|
109
|
+
stdout: '',
|
|
110
|
+
stderr: `payload serialization failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
111
|
+
signal: null,
|
|
112
|
+
timedOut: false,
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
101
116
|
return new Promise<HookResult>((resolve) => {
|
|
102
117
|
const stdoutBuf: { value: string } = { value: '' }
|
|
103
118
|
const stderrBuf: { value: string } = { value: '' }
|
|
104
119
|
let settled = false
|
|
120
|
+
let timedOut = false
|
|
121
|
+
let timeoutHandle: NodeJS.Timeout | undefined
|
|
105
122
|
|
|
106
123
|
const settle = (result: HookResult) => {
|
|
107
124
|
if (!settled) {
|
|
108
125
|
settled = true
|
|
126
|
+
if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)
|
|
109
127
|
resolve(result)
|
|
110
128
|
}
|
|
111
129
|
}
|
|
112
130
|
|
|
113
131
|
const spawnOpts = {
|
|
114
|
-
timeout,
|
|
115
|
-
killSignal: 'SIGKILL' as const,
|
|
116
132
|
env: hookEnv(payload, opts.env),
|
|
117
133
|
// stdio:'pipe' is equivalent to ['pipe','pipe','pipe'] — it guarantees
|
|
118
134
|
// the child's stdin is OUR pipe, NEVER the opencode TUI's terminal
|
|
@@ -120,6 +136,10 @@ export function runHook(
|
|
|
120
136
|
// the opencode core hook timeout).
|
|
121
137
|
stdio: 'pipe' as const,
|
|
122
138
|
windowsHide: true,
|
|
139
|
+
// A process group lets the timeout kill shell descendants too. Without
|
|
140
|
+
// this, a shell hook can leave `sleep` holding stdout/stderr open after
|
|
141
|
+
// the shell itself receives SIGKILL, so the Promise would not settle.
|
|
142
|
+
...(process.platform !== 'win32' ? { detached: true } : {}),
|
|
123
143
|
...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),
|
|
124
144
|
}
|
|
125
145
|
|
|
@@ -172,15 +192,35 @@ export function runHook(
|
|
|
172
192
|
stdout: stdoutBuf.value,
|
|
173
193
|
stderr: stderrBuf.value,
|
|
174
194
|
signal,
|
|
175
|
-
timedOut
|
|
195
|
+
timedOut,
|
|
176
196
|
})
|
|
177
197
|
})
|
|
178
198
|
|
|
199
|
+
timeoutHandle = setTimeout(() => {
|
|
200
|
+
timedOut = true
|
|
201
|
+
try {
|
|
202
|
+
// Negative PIDs target the process group created by `detached`.
|
|
203
|
+
if (process.platform !== 'win32' && child.pid !== undefined) {
|
|
204
|
+
process.kill(-child.pid, 'SIGKILL')
|
|
205
|
+
} else {
|
|
206
|
+
child.kill('SIGKILL')
|
|
207
|
+
}
|
|
208
|
+
} catch {
|
|
209
|
+
// The child may have exited between the timer and kill call. The
|
|
210
|
+
// close/error handlers still produce the structured result.
|
|
211
|
+
try {
|
|
212
|
+
child.kill('SIGKILL')
|
|
213
|
+
} catch {
|
|
214
|
+
// Hooks must never leak a kill failure to the plugin host.
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}, timeout)
|
|
218
|
+
|
|
179
219
|
// Deliver the Claude Code protocol JSON on stdin. stdin.end() runs
|
|
180
220
|
// UNCONDITIONALLY — even for an empty payload {} or a script that never
|
|
181
221
|
// reads stdin — so the child can never block waiting for input and hit
|
|
182
222
|
// the runtime hook timeout (reported as "Hook X timed out after 30000ms").
|
|
183
|
-
child.stdin.write(
|
|
223
|
+
child.stdin.write(serializedPayload)
|
|
184
224
|
child.stdin.end()
|
|
185
225
|
})
|
|
186
226
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantheon-tui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pantheon-tui",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.3.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@opencode-ai/plugin": ">=1.14.0",
|
|
@@ -1526,9 +1526,9 @@
|
|
|
1526
1526
|
}
|
|
1527
1527
|
},
|
|
1528
1528
|
"node_modules/brace-expansion": {
|
|
1529
|
-
"version": "2.1.
|
|
1530
|
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.
|
|
1531
|
-
"integrity": "sha512-
|
|
1529
|
+
"version": "2.1.4",
|
|
1530
|
+
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
|
|
1531
|
+
"integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
|
|
1532
1532
|
"license": "MIT",
|
|
1533
1533
|
"dependencies": {
|
|
1534
1534
|
"balanced-match": "^1.0.0"
|
|
@@ -2703,6 +2703,20 @@
|
|
|
2703
2703
|
"license": "0BSD",
|
|
2704
2704
|
"optional": true
|
|
2705
2705
|
},
|
|
2706
|
+
"node_modules/typescript": {
|
|
2707
|
+
"version": "5.9.3",
|
|
2708
|
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
|
2709
|
+
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
|
2710
|
+
"license": "Apache-2.0",
|
|
2711
|
+
"peer": true,
|
|
2712
|
+
"bin": {
|
|
2713
|
+
"tsc": "bin/tsc",
|
|
2714
|
+
"tsserver": "bin/tsserver"
|
|
2715
|
+
},
|
|
2716
|
+
"engines": {
|
|
2717
|
+
"node": ">=14.17"
|
|
2718
|
+
}
|
|
2719
|
+
},
|
|
2706
2720
|
"node_modules/unconfig-core": {
|
|
2707
2721
|
"version": "7.5.0",
|
|
2708
2722
|
"resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.5.0.tgz",
|
|
@@ -2773,6 +2787,21 @@
|
|
|
2773
2787
|
"url": "https://github.com/sponsors/sxzz"
|
|
2774
2788
|
}
|
|
2775
2789
|
},
|
|
2790
|
+
"node_modules/web-tree-sitter": {
|
|
2791
|
+
"version": "0.25.10",
|
|
2792
|
+
"resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.25.10.tgz",
|
|
2793
|
+
"integrity": "sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA==",
|
|
2794
|
+
"license": "MIT",
|
|
2795
|
+
"peer": true,
|
|
2796
|
+
"peerDependencies": {
|
|
2797
|
+
"@types/emscripten": "^1.40.0"
|
|
2798
|
+
},
|
|
2799
|
+
"peerDependenciesMeta": {
|
|
2800
|
+
"@types/emscripten": {
|
|
2801
|
+
"optional": true
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
},
|
|
2776
2805
|
"node_modules/which": {
|
|
2777
2806
|
"version": "2.0.2",
|
|
2778
2807
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantheon-tui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.1",
|
|
5
5
|
"description": "Pantheon TUI plugin — sidebar (agents, sessions, commands, config, memory, active preset) + AI subscription usage gauges incl. OpenCode Go/Zen dollar limits (vendored, MIT)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"exports": {
|