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.
Files changed (107) hide show
  1. package/.pantheon/code-mode/manifest.json +21 -0
  2. package/AGENTS.md +14 -63
  3. package/CHANGELOG.md +1260 -0
  4. package/README.md +162 -23
  5. package/README.pt-BR.md +104 -19
  6. package/bin/pantheon-init.mjs +178 -21
  7. package/commands/pantheon.md +1 -35
  8. package/package.json +23 -15
  9. package/plugin.json +1 -1
  10. package/pyproject.toml +62 -0
  11. package/scripts/code_mode_server.py +431 -55
  12. package/scripts/doctor.mjs +207 -9
  13. package/scripts/install/cli-ui.mjs +17 -11
  14. package/scripts/install/config-migration.mjs +4 -6
  15. package/scripts/install/opencode.mjs +137 -35
  16. package/scripts/install/plugin.mjs +12 -45
  17. package/scripts/install/shared.mjs +43 -2
  18. package/scripts/install/strings.mjs +129 -0
  19. package/scripts/install-mcp.mjs +1 -0
  20. package/scripts/manifest-inventory.mjs +410 -0
  21. package/scripts/mcp_persistence_server.py +536 -164
  22. package/scripts/package-evidence.mjs +242 -0
  23. package/scripts/probe-pantheon-cost.mjs +10 -1
  24. package/scripts/release-beta-version.mjs +56 -60
  25. package/scripts/sync-artifacts.mjs +169 -0
  26. package/scripts/sync-tui.mjs +129 -64
  27. package/scripts/test-opencode-v1-v2-sandbox.sh +79 -161
  28. package/scripts/validation-policy.mjs +7 -7
  29. package/scripts/version-check.mjs +113 -108
  30. package/scripts/versioning.mjs +230 -86
  31. package/src/agents/apollo.md +1 -0
  32. package/src/agents/gaia.md +1 -0
  33. package/src/agents/mnemosyne.md +1 -1
  34. package/src/agents/zeus.md +11 -54
  35. package/src/instructions/memory-protocol.instructions.md +6 -3
  36. package/src/instructions/zeus-anti-stall.instructions.md +2 -4
  37. package/src/instructions/zeus-council-synthesis.instructions.md +3 -28
  38. package/src/instructions/zeus-timeout-retry.instructions.md +3 -28
  39. package/src/mcp/code_mode_server.py +431 -55
  40. package/src/mcp/mcp_persistence_server.py +536 -164
  41. package/src/mcp/toon_codec.py +2 -4
  42. package/src/pantheon/background-job-board.ts +47 -5
  43. package/src/pantheon/{delegation-compaction.ts → compaction-context.ts} +10 -100
  44. package/src/pantheon/cost-command.ts +309 -44
  45. package/src/pantheon/delegation-enforce.ts +59 -14
  46. package/src/pantheon/file-persistence-salvage.ts +64 -0
  47. package/src/pantheon/file-persistence.ts +194 -45
  48. package/src/pantheon/goal-loop.ts +1 -1
  49. package/src/pantheon/goal-store.ts +1 -1
  50. package/src/pantheon/idle-continuation.ts +4 -6
  51. package/src/pantheon/model-command.ts +1 -2
  52. package/src/pantheon/native-task-status.ts +139 -0
  53. package/src/pantheon/presets.d.mts +0 -20
  54. package/src/pantheon/presets.mjs +0 -64
  55. package/src/pantheon/session-guard.ts +2 -2
  56. package/src/pantheon/session-id.ts +30 -0
  57. package/src/pantheon/shared-board.ts +37 -0
  58. package/src/pantheon/task-result-guard.ts +106 -0
  59. package/src/pantheon/todo-enforcer.ts +3 -3
  60. package/src/pantheon/tool-ceiling.ts +159 -0
  61. package/src/pantheon/tool-context.ts +23 -0
  62. package/src/pantheon/v2-bridge.ts +1 -4
  63. package/src/plugin-v2.ts +8 -21
  64. package/src/plugin.ts +83 -251
  65. package/src/plugins/pantheon-hooks.ts +51 -0
  66. package/src/plugins/tui/dist/server.d.ts +1 -1
  67. package/src/plugins/tui/dist/server.d.ts.map +1 -1
  68. package/src/plugins/tui/dist/server.js +1 -1
  69. package/src/plugins/tui/dist/server.js.map +1 -1
  70. package/src/plugins/tui/dist/tui.d.ts +261 -77
  71. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  72. package/src/plugins/tui/dist/tui.js +640 -234
  73. package/src/plugins/tui/dist/tui.js.map +1 -1
  74. package/src/plugins/tui/package-lock.json +2 -2
  75. package/src/plugins/tui/package.json +2 -2
  76. package/src/plugins/tui/src/index.tsx +872 -226
  77. package/src/routing.yml +0 -16
  78. package/src/skills/context-compression/SKILL.md +1 -1
  79. package/scripts/generate-preset-docs.mjs +0 -300
  80. package/scripts/generate-prompts.sh +0 -222
  81. package/scripts/hash_verify.py +0 -192
  82. package/scripts/install/component.mjs +0 -24
  83. package/scripts/install/migrate-config.mjs +0 -302
  84. package/scripts/test-context-compression.sh +0 -169
  85. package/src/pantheon/auto-wake.ts +0 -89
  86. package/src/pantheon/chat-reminders.ts +0 -9
  87. package/src/pantheon/comment-checker.ts +0 -48
  88. package/src/pantheon/compaction-assert.ts +0 -160
  89. package/src/pantheon/cost-tracker.ts +0 -108
  90. package/src/pantheon/delegate-manager.ts +0 -669
  91. package/src/pantheon/delegation-classifier.ts +0 -307
  92. package/src/pantheon/delegation-finalize.ts +0 -374
  93. package/src/pantheon/delegation-notify.ts +0 -212
  94. package/src/pantheon/delegation-toast.ts +0 -73
  95. package/src/pantheon/delegation.ts +0 -1120
  96. package/src/pantheon/dispatch-guard.ts +0 -109
  97. package/src/pantheon/permission-eval.ts +0 -284
  98. package/src/pantheon/preemptive-compact.ts +0 -76
  99. package/src/pantheon/retry-policy.ts +0 -212
  100. package/src/pantheon/step-cap.ts +0 -110
  101. package/src/pantheon/token-opt.ts +0 -781
  102. package/src/pantheon/toon-codec.ts +0 -481
  103. package/src/pantheon/v2-events.ts +0 -131
  104. package/src/pantheon/v2-hooks.ts +0 -287
  105. package/src/pantheon/v2-tool-definitions.ts +0 -331
  106. package/src/pantheon/zeus-delegate-with-retry.ts +0 -406
  107. package/src/plugins/tui/dist/tui.tsx +0 -2605
@@ -1,212 +0,0 @@
1
- /**
2
- * Delegation event wiring — observe background-job lifecycle events and
3
- * route them to finalize. This module is the `event`-hook complement of the
4
- * board: `session.idle`/`session.error` on a child session that is a board
5
- * job → `finalizeDelegation` (Phase 2), which transitions the board and
6
- * fires `onTerminal`.
7
- *
8
- * NOT a notification channel. The user policy is ZERO delegation
9
- * notifications in the chat transcript — no `<task-notification>` block is
10
- * ever injected into a `chat.message` output, and no queued delivery path
11
- * exists. Completion visibility lives in the legitimate channels only:
12
- * the board `[unread]` marker (`pantheon_delegation_list`),
13
- * `pantheon_delegation_read`, TUI toasts (pantheon-hooks, PANTHEON_TOASTS
14
- * gate), and compaction carry-forward. The plugin's `onTerminal` listener
15
- * writes a file-only log line for the on-disk audit trail.
16
- *
17
- * `handleDelegationEvent` wires the `event` hook: `session.idle`/`session.error`
18
- * on a child session that is a board job → `finalizeDelegation` (Phase 2),
19
- * which transitions the board and fires `onTerminal`. Finalize never notifies
20
- * directly, and `markReconciled` does not re-fire onTerminal (reconcile is an
21
- * acknowledgment, not a completion), so every job gets exactly ONE terminal
22
- * transition — never a reconciled echo. Unknown sessions are ignored.
23
- *
24
- * `finalizeIdleChildrenWithoutMd` proactively finalizes children confirmed
25
- * idle by the V1 session-status API but with no MD report on disk — eliminates
26
- * the phantom "running" window during `pullOutput` without treating a board
27
- * record's `running` state as proof that the child is idle. Wired into a
28
- * periodic scan via `startIdleChildScan` (default 30 s cadence).
29
- *
30
- * Pure TypeScript — zero runtime dependencies beyond the board types.
31
- *
32
- * Follow-up (Themis review, Phase 5): `extractErrorMessage` handles the two
33
- * observed `session.error` error shapes (string, { message }). The opencode SDK
34
- * MAY expose other shapes (e.g. Error-like with non-string `message`) — if a
35
- * real session.error ever carries one, the extraction degrades to the generic
36
- * "session error" label. No code change: there is no evidence any other shape
37
- * occurs in practice; revisit if a session.error shows an unexpected payload.
38
- *
39
- * @module delegation-notify
40
- */
41
-
42
- import type { BackgroundJobRecord } from './background-job-board.ts'
43
- import type { FinalizeInput } from './delegation-finalize.ts'
44
-
45
- export type { FinalizeInput } from './delegation-finalize.ts'
46
-
47
- /** Default cadence for the proactive idle-child scan (30 s). */
48
- export const IDLE_SCAN_INTERVAL_MS = 30_000
49
-
50
- // ─── Types ─────────────────────────────────────────────────────────────
51
-
52
- /** Structural view of the event payload the `event` hook receives. */
53
- export interface DelegationEventLike {
54
- type?: string
55
- properties?: Record<string, unknown>
56
- }
57
-
58
- /** Dependencies threaded to handleDelegationEvent (board lookup + finalize). */
59
- export interface DelegationEventDeps {
60
- /** Look up a board job by session ID (child session IDs are task IDs). */
61
- board: { get(taskID: string): BackgroundJobRecord | undefined }
62
- /** Bound Phase 2 finalize — clears the timeout timer + writes the report. */
63
- finalize: (childSessionID: string, opts: FinalizeInput) => Promise<unknown>
64
- }
65
-
66
- // ─── Event → finalize wiring ───────────────────────────────────────────
67
-
68
- function extractErrorMessage(error: unknown): string {
69
- if (typeof error === 'string' && error.trim() !== '') return error
70
- if (error && typeof error === 'object' && 'message' in error) {
71
- const message = (error as { message: unknown }).message
72
- if (typeof message === 'string' && message.trim() !== '') return message
73
- }
74
- return 'session error'
75
- }
76
-
77
- /**
78
- * Handle a lifecycle event for background delegations:
79
- * - `session.idle` on a board job → finalize as completed;
80
- * - `session.error` on a board job → finalize as error (message extracted);
81
- * - any other event, a missing session ID, or an unknown session → no-op.
82
- *
83
- * Finalize transitions the board, which fires `onTerminal` (the plugin's
84
- * file-only audit log — no chat delivery; see module header). The board's
85
- * same-terminal idempotency makes repeated idles harmless (finalize rewrites
86
- * the report but never transitions a terminal job to a different state).
87
- *
88
- * @returns True when the event named a board job (handled).
89
- */
90
- export async function handleDelegationEvent(
91
- ev: DelegationEventLike,
92
- deps: DelegationEventDeps,
93
- ): Promise<boolean> {
94
- const type = ev?.type
95
- if (type !== 'session.idle' && type !== 'session.error') return false
96
- const sessionID = ev.properties?.sessionID
97
- if (typeof sessionID !== 'string' || sessionID === '') return false
98
- if (deps.board.get(sessionID) === undefined) return false
99
-
100
- if (type === 'session.idle') {
101
- await deps.finalize(sessionID, { state: 'completed' })
102
- } else {
103
- await deps.finalize(sessionID, {
104
- state: 'error',
105
- error: extractErrorMessage(ev.properties?.error),
106
- })
107
- }
108
- return true
109
- }
110
-
111
- // ─── Proactive finalize (Fix 2) ────────────────────────────────────────
112
-
113
- /** Dependencies for idle-child scanning. */
114
- export interface IdleChildScanDeps {
115
- /** Look up a board job by session ID (child session IDs are task IDs). */
116
- board: {
117
- get(taskID: string): BackgroundJobRecord | undefined
118
- list(parentSessionID?: string): BackgroundJobRecord[]
119
- }
120
- /** Bound Phase 2 finalize — clears the timeout timer + writes the report. */
121
- finalize: (childSessionID: string, opts: FinalizeInput) => Promise<unknown>
122
- /**
123
- * Confirm the child's native V1 session status. `undefined` means the
124
- * status is unavailable and MUST NOT be treated as idle.
125
- */
126
- isIdle?: (childSessionID: string) => Promise<boolean | undefined>
127
- /**
128
- * Check whether an MD report exists for the given board job.
129
- * Receives the full job record so the caller can construct the report
130
- * path from `job.parentSessionID` + `job.alias`.
131
- * If the function throws, the scan skips that child (fail-open).
132
- */
133
- hasReport: (job: BackgroundJobRecord) => boolean
134
- /** Optional logger for diagnostic messages. */
135
- logger?: { info?: (msg: string) => void; warn?: (msg: string) => void }
136
- }
137
-
138
- /**
139
- * Scan running board jobs for children whose V1 session status is confirmed
140
- * idle but have no MD report on disk, and proactively finalize them. This
141
- * eliminates the phantom "running" window that occurs between `session.idle`
142
- * firing and the `pullOutput`→`writeDelegationReport` cycle completing.
143
- *
144
- * Called from the periodic idle-child scan (`startIdleChildScan`, default 30 s).
145
- * The scan is O(N) where N = number of running jobs (typically < 10).
146
- *
147
- * A missing status probe is an explicit unknown state, not an idle signal, so
148
- * legacy embedders without the V1 API fail closed. Errors are caught
149
- * per-child so one failure never blocks the rest.
150
- *
151
- * @returns Number of children finalized (for diagnostics).
152
- */
153
- export async function finalizeIdleChildrenWithoutMd(deps: IdleChildScanDeps): Promise<number> {
154
- const runningJobs = deps.board.list().filter((j: BackgroundJobRecord) => j.state === 'running')
155
-
156
- let finalized = 0
157
- for (const job of runningJobs) {
158
- try {
159
- if (deps.isIdle === undefined) {
160
- deps.logger?.warn?.(
161
- `[delegation-notify] idle status unknown for ${job.taskID}; proactive finalize skipped`,
162
- )
163
- continue
164
- }
165
- const idle = await deps.isIdle(job.taskID)
166
- if (idle !== true) {
167
- if (idle === undefined) {
168
- deps.logger?.warn?.(
169
- `[delegation-notify] idle status unknown for ${job.taskID}; proactive finalize skipped`,
170
- )
171
- }
172
- continue
173
- }
174
- // If the child already has an MD report, finalize was already handled
175
- // by handleDelegationEvent — skip.
176
- if (deps.hasReport(job)) continue
177
- // Child is idle on the board but has no report — proactively finalize.
178
- await deps.finalize(job.taskID, { state: 'completed' })
179
- finalized++
180
- } catch (err) {
181
- deps.logger?.warn?.(`[delegation-notify] proactive finalize failed for ${job.taskID}: ${err}`)
182
- }
183
- }
184
- return finalized
185
- }
186
-
187
- // ─── Periodic scan launcher ─────────────────────────────────────────────
188
-
189
- /**
190
- * Start a periodic scan that proactively finalizes idle board children
191
- * without MD reports. The scan runs every `intervalMs` (default 30 s) and
192
- * is **unref'd** so it never holds the process open on its own.
193
- *
194
- * The timer is idempotent — calling this function multiple times is safe
195
- * (each call creates an independent timer, but the underlying finalize
196
- * operation is itself idempotent due to the board's same-terminal guard).
197
- *
198
- * @returns A `NodeJS.Timeout` handle that can be cleared with
199
- * `clearInterval(handle)` to stop the scan.
200
- */
201
- export function startIdleChildScan(
202
- deps: IdleChildScanDeps,
203
- intervalMs: number = IDLE_SCAN_INTERVAL_MS,
204
- ): NodeJS.Timeout {
205
- const timer = setInterval(() => {
206
- void finalizeIdleChildrenWithoutMd(deps).catch((err) => {
207
- deps.logger?.warn?.(`[delegation-notify] periodic idle scan failed: ${err}`)
208
- })
209
- }, intervalMs)
210
- timer.unref()
211
- return timer
212
- }
@@ -1,73 +0,0 @@
1
- import type { BackgroundJobRecord } from './background-job-board.ts'
2
-
3
- type ToastCategory = 'errors' | 'delegations' | 'council'
4
-
5
- const toastMode = (process.env.PANTHEON_TOASTS ?? '').trim().toLowerCase()
6
- const enabledToastCategories: ReadonlySet<ToastCategory> = (() => {
7
- switch (toastMode) {
8
- case 'off':
9
- return new Set()
10
- case 'errors':
11
- return new Set(['errors'])
12
- case 'council':
13
- return new Set(['errors', 'council'])
14
- case 'all':
15
- return new Set(['errors', 'delegations', 'council'])
16
- default:
17
- return new Set(['errors', 'delegations', 'council'])
18
- }
19
- })()
20
- const terminalToastsShown = new Set<string>()
21
- const terminalStates = new Set(['completed', 'error', 'cancelled'])
22
-
23
- /** Match the lifecycle toast gate used by pantheon-hooks. */
24
- export function delegationToastEnabled(): boolean {
25
- return enabledToastCategories.has('delegations')
26
- }
27
-
28
- export type ToastClient = {
29
- tui?: {
30
- showToast?: (input: {
31
- body: {
32
- title?: string
33
- message: string
34
- variant: 'info' | 'success' | 'warning' | 'error'
35
- duration: number
36
- }
37
- }) => Promise<unknown>
38
- }
39
- }
40
-
41
- /** Best-effort visual completion signal; never affects board finalization. */
42
- export async function showDelegationTerminalToast(
43
- client: ToastClient,
44
- job: Pick<BackgroundJobRecord, 'taskID' | 'alias' | 'agent' | 'state' | 'timedOut'>,
45
- ): Promise<void> {
46
- try {
47
- if (!delegationToastEnabled()) return
48
- const isTerminal = job.timedOut || terminalStates.has(job.state)
49
- if (isTerminal) {
50
- if (terminalToastsShown.has(job.taskID)) return
51
- terminalToastsShown.add(job.taskID)
52
- }
53
- const showToast = client.tui?.showToast
54
- if (typeof showToast !== 'function') return
55
- const state = job.timedOut ? 'timeout' : job.state
56
- const variant =
57
- state === 'completed'
58
- ? 'success'
59
- : state === 'error' || state === 'timeout'
60
- ? 'error'
61
- : 'warning'
62
- await showToast({
63
- body: {
64
- title: 'Delegação concluída',
65
- message: `${job.alias} (${job.agent}) — ${state}`,
66
- variant,
67
- duration: 4000,
68
- },
69
- })
70
- } catch {
71
- // TUI is optional (and may disappear during shutdown); completion is durable.
72
- }
73
- }