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
|
@@ -65,10 +65,7 @@ const modelArgs = {
|
|
|
65
65
|
.optional()
|
|
66
66
|
.describe('Operation: status/show, set, or reset. No args runs wizard.'),
|
|
67
67
|
agent: z.string().optional().describe('Agent name (one of 14 canonical agents).'),
|
|
68
|
-
model: z
|
|
69
|
-
.string()
|
|
70
|
-
.optional()
|
|
71
|
-
.describe('Model in provider/model-id format; used by set.'),
|
|
68
|
+
model: z.string().optional().describe('Model in provider/model-id format; used by set.'),
|
|
72
69
|
effort: z
|
|
73
70
|
.enum(['low', 'medium', 'high'])
|
|
74
71
|
.optional()
|
|
@@ -357,10 +354,7 @@ function presetPathForScope(options: ModelCommandOptions, scope: ModelScope): st
|
|
|
357
354
|
return globalCandidates[0] ?? candidates[0]!
|
|
358
355
|
}
|
|
359
356
|
|
|
360
|
-
async function readActivePresetRaw(
|
|
361
|
-
path: string,
|
|
362
|
-
label: string,
|
|
363
|
-
): Promise<ReadFileResult> {
|
|
357
|
+
async function readActivePresetRaw(path: string, label: string): Promise<ReadFileResult> {
|
|
364
358
|
const file = await readRegularFile(path, label)
|
|
365
359
|
if (file === undefined) return { exists: false, valid: true, data: null }
|
|
366
360
|
try {
|
|
@@ -368,7 +362,13 @@ async function readActivePresetRaw(
|
|
|
368
362
|
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
369
363
|
return { exists: true, valid: false, data: null, content: file.content, mode: file.mode }
|
|
370
364
|
}
|
|
371
|
-
return {
|
|
365
|
+
return {
|
|
366
|
+
exists: true,
|
|
367
|
+
valid: true,
|
|
368
|
+
data: parsed as Record<string, unknown>,
|
|
369
|
+
content: file.content,
|
|
370
|
+
mode: file.mode,
|
|
371
|
+
}
|
|
372
372
|
} catch {
|
|
373
373
|
return { exists: true, valid: false, data: null, content: file.content, mode: file.mode }
|
|
374
374
|
}
|
|
@@ -444,9 +444,21 @@ async function writeActivePresetAtomically(
|
|
|
444
444
|
if (current.content === undefined) {
|
|
445
445
|
throw new ModelCommandError('configuration content could not be read; file preserved')
|
|
446
446
|
}
|
|
447
|
-
await atomicReplace(
|
|
447
|
+
await atomicReplace(
|
|
448
|
+
backupPath,
|
|
449
|
+
current.content,
|
|
450
|
+
backupMode,
|
|
451
|
+
'configuration backup',
|
|
452
|
+
backup !== undefined,
|
|
453
|
+
)
|
|
448
454
|
}
|
|
449
|
-
await atomicReplace(
|
|
455
|
+
await atomicReplace(
|
|
456
|
+
path,
|
|
457
|
+
`${JSON.stringify(data, null, 2)}\n`,
|
|
458
|
+
originalMode,
|
|
459
|
+
'configuration file',
|
|
460
|
+
current.exists,
|
|
461
|
+
)
|
|
450
462
|
}
|
|
451
463
|
|
|
452
464
|
function ensureActivePresetShape(
|
|
@@ -460,11 +472,21 @@ function ensureActivePresetShape(
|
|
|
460
472
|
}
|
|
461
473
|
if (typeof out.source !== 'string') out.source = 'cli'
|
|
462
474
|
out.updated_at = new Date().toISOString()
|
|
463
|
-
if (
|
|
475
|
+
if (
|
|
476
|
+
out.overrides === undefined ||
|
|
477
|
+
out.overrides === null ||
|
|
478
|
+
typeof out.overrides !== 'object' ||
|
|
479
|
+
Array.isArray(out.overrides)
|
|
480
|
+
) {
|
|
464
481
|
out.overrides = {}
|
|
465
482
|
}
|
|
466
483
|
const overrides = out.overrides as Record<string, unknown>
|
|
467
|
-
if (
|
|
484
|
+
if (
|
|
485
|
+
overrides.agents === undefined ||
|
|
486
|
+
overrides.agents === null ||
|
|
487
|
+
typeof overrides.agents !== 'object' ||
|
|
488
|
+
Array.isArray(overrides.agents)
|
|
489
|
+
) {
|
|
468
490
|
overrides.agents = {}
|
|
469
491
|
}
|
|
470
492
|
return out
|
|
@@ -509,14 +531,25 @@ async function updateActivePreset(
|
|
|
509
531
|
} catch {
|
|
510
532
|
// ignore
|
|
511
533
|
}
|
|
512
|
-
} else if (
|
|
534
|
+
} else if (
|
|
535
|
+
current.data &&
|
|
536
|
+
typeof current.data === 'object' &&
|
|
537
|
+
(current.data as Record<string, unknown>).preset
|
|
538
|
+
) {
|
|
513
539
|
const existing = (current.data as Record<string, unknown>).preset as string
|
|
514
|
-
if (
|
|
540
|
+
if (
|
|
541
|
+
typeof existing === 'string' &&
|
|
542
|
+
existing.trim() !== '' &&
|
|
543
|
+
SAFE_PRESET_NAME.test(existing.trim())
|
|
544
|
+
) {
|
|
515
545
|
fallbackPreset = existing.trim()
|
|
516
546
|
}
|
|
517
547
|
}
|
|
518
548
|
|
|
519
|
-
const shaped = ensureActivePresetShape(
|
|
549
|
+
const shaped = ensureActivePresetShape(
|
|
550
|
+
current.data as Record<string, unknown> | null,
|
|
551
|
+
fallbackPreset,
|
|
552
|
+
)
|
|
520
553
|
const overrides = shaped.overrides as Record<string, unknown>
|
|
521
554
|
const agents = overrides.agents as Record<string, unknown>
|
|
522
555
|
|
|
@@ -551,7 +584,10 @@ async function updateActivePreset(
|
|
|
551
584
|
|
|
552
585
|
// If clamped, append warning
|
|
553
586
|
if (variantInfo.clamped) {
|
|
554
|
-
visionWarning = [
|
|
587
|
+
visionWarning = [
|
|
588
|
+
visionWarning,
|
|
589
|
+
`effort clamped to ${variantInfo.variant} for model ${model}`,
|
|
590
|
+
]
|
|
555
591
|
.filter(Boolean)
|
|
556
592
|
.join('; ')
|
|
557
593
|
}
|
|
@@ -584,10 +620,6 @@ async function updateActivePreset(
|
|
|
584
620
|
|
|
585
621
|
// ─── Status ─────────────────────────────────────────────────────────────────
|
|
586
622
|
|
|
587
|
-
function silentLogger(): ModelCommandLogger {
|
|
588
|
-
return { warn: () => {}, log: () => {} }
|
|
589
|
-
}
|
|
590
|
-
|
|
591
623
|
async function resolvePerAgentStatus(options: ModelCommandOptions): Promise<{
|
|
592
624
|
presetName: string | null
|
|
593
625
|
presetSource: string | null
|
|
@@ -624,12 +656,20 @@ async function resolvePerAgentStatus(options: ModelCommandOptions): Promise<{
|
|
|
624
656
|
let vision: boolean | undefined
|
|
625
657
|
|
|
626
658
|
if (resolved) {
|
|
627
|
-
const merged = (
|
|
659
|
+
const merged = (
|
|
660
|
+
resolved.agents as Record<
|
|
661
|
+
string,
|
|
662
|
+
{ model?: string; reasoning_effort?: string; variant?: string }
|
|
663
|
+
>
|
|
664
|
+
)?.[key]
|
|
628
665
|
if (merged?.model) {
|
|
629
666
|
model = merged.model
|
|
630
|
-
effort =
|
|
667
|
+
effort =
|
|
668
|
+
(merged as { reasoning_effort?: string }).reasoning_effort ??
|
|
669
|
+
(merged as { variant?: string }).variant
|
|
631
670
|
// Determine origin: file overrides > file preset > env
|
|
632
|
-
const fileOverrides = (resolved.overrides as { agents?: Record<string, unknown> } | null)
|
|
671
|
+
const fileOverrides = (resolved.overrides as { agents?: Record<string, unknown> } | null)
|
|
672
|
+
?.agents
|
|
633
673
|
if (resolved.source === 'file' && fileOverrides && Object.hasOwn(fileOverrides, key)) {
|
|
634
674
|
origin = 'override'
|
|
635
675
|
} else if (resolved.source === 'env') {
|
|
@@ -665,7 +705,8 @@ async function renderStatus(options: ModelCommandOptions): Promise<string> {
|
|
|
665
705
|
const lines: string[] = []
|
|
666
706
|
lines.push('Pantheon model configuration per-agent (restart OpenCode after changes):')
|
|
667
707
|
if (presetName) {
|
|
668
|
-
const originLabel =
|
|
708
|
+
const originLabel =
|
|
709
|
+
presetSource === 'env' ? 'env' : presetSource === 'file' ? 'preset' : presetSource
|
|
669
710
|
lines.push(`active preset: ${presetName} (${presetSource ?? 'unknown'})`)
|
|
670
711
|
// For test compatibility, also show origin mapping explicitly
|
|
671
712
|
void originLabel
|
|
@@ -700,7 +741,8 @@ export function buildWizardQuestions(): unknown[] {
|
|
|
700
741
|
},
|
|
701
742
|
{
|
|
702
743
|
header: 'Modelo',
|
|
703
|
-
question:
|
|
744
|
+
question:
|
|
745
|
+
'Informe o modelo em provider/model-id (ex: openai/gpt-5.6 ou opencode-go/kimi-k2.7-code)',
|
|
704
746
|
kind: 'text',
|
|
705
747
|
},
|
|
706
748
|
{
|
|
@@ -717,8 +759,14 @@ export function buildWizardQuestions(): unknown[] {
|
|
|
717
759
|
header: 'Escopo',
|
|
718
760
|
question: 'Onde salvar o override?',
|
|
719
761
|
options: [
|
|
720
|
-
{
|
|
721
|
-
|
|
762
|
+
{
|
|
763
|
+
label: 'project',
|
|
764
|
+
description: './.pantheon/active-preset.json (escopo do projeto, seguro)',
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
label: 'global',
|
|
768
|
+
description: '~/.config/opencode/.pantheon/active-preset.json (global)',
|
|
769
|
+
},
|
|
722
770
|
],
|
|
723
771
|
multiSelect: false,
|
|
724
772
|
},
|
|
@@ -741,11 +789,15 @@ async function promptViaReadline(
|
|
|
741
789
|
answers.model = modelAns
|
|
742
790
|
|
|
743
791
|
const effortQ = questions[2]!
|
|
744
|
-
const effortAns = (await rl.question(`${effortQ.question} [low/medium/high] : `))
|
|
792
|
+
const effortAns = (await rl.question(`${effortQ.question} [low/medium/high] : `))
|
|
793
|
+
.trim()
|
|
794
|
+
.toLowerCase()
|
|
745
795
|
answers.effort = effortAns || 'medium'
|
|
746
796
|
|
|
747
797
|
const scopeQ = questions[3]!
|
|
748
|
-
const scopeAns = (await rl.question(`${scopeQ.question} [project/global] : `))
|
|
798
|
+
const scopeAns = (await rl.question(`${scopeQ.question} [project/global] : `))
|
|
799
|
+
.trim()
|
|
800
|
+
.toLowerCase()
|
|
749
801
|
answers.scope = scopeAns || 'project'
|
|
750
802
|
|
|
751
803
|
return answers
|
|
@@ -779,7 +831,8 @@ async function runWizard(options: ModelCommandOptions): Promise<string> {
|
|
|
779
831
|
const agent = typeof answers.agent === 'string' ? answers.agent.trim() : ''
|
|
780
832
|
const model = typeof answers.model === 'string' ? answers.model.trim() : ''
|
|
781
833
|
const effort = typeof answers.effort === 'string' ? answers.effort.trim().toLowerCase() : ''
|
|
782
|
-
const scopeRaw =
|
|
834
|
+
const scopeRaw =
|
|
835
|
+
typeof answers.scope === 'string' ? answers.scope.trim().toLowerCase() : 'project'
|
|
783
836
|
const scope: ModelScope = scopeRaw === 'global' ? 'global' : 'project'
|
|
784
837
|
|
|
785
838
|
if (!agent) return 'pantheon_model wizard failed: agent is required'
|
|
@@ -830,7 +883,8 @@ export function createModelCommand(options: ModelCommandOptions = {}): ModelTool
|
|
|
830
883
|
return await runWizard(options)
|
|
831
884
|
}
|
|
832
885
|
|
|
833
|
-
const action: ModelAction = (args.action ??
|
|
886
|
+
const action: ModelAction = (args.action ??
|
|
887
|
+
(hasAgentModelEffort ? 'set' : 'status')) as ModelAction
|
|
834
888
|
|
|
835
889
|
if (action === 'status' || action === 'show') return await renderStatus(options)
|
|
836
890
|
|