pantheon-opencode 1.6.0-beta.6 → 1.6.0-beta.7

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 (58) hide show
  1. package/AGENTS.md +27 -820
  2. package/CHANGELOG.md +116 -0
  3. package/README.md +132 -39
  4. package/README.pt-BR.md +47 -23
  5. package/package.json +6 -1
  6. package/plugin.json +1 -1
  7. package/pyproject.toml +3 -1
  8. package/scripts/build-agents-md.mjs +162 -28
  9. package/scripts/doctor.mjs +104 -22
  10. package/scripts/install/agents-md.mjs +2 -2
  11. package/scripts/install/config-migration.mjs +154 -7
  12. package/scripts/install/opencode.mjs +202 -40
  13. package/scripts/install/shared.mjs +115 -7
  14. package/scripts/install/strings.mjs +8 -0
  15. package/scripts/probe-pantheon-cost.mjs +16 -3
  16. package/scripts/sync-artifacts.mjs +2 -2
  17. package/scripts/test-opencode-v2-sandbox.sh +820 -86
  18. package/skills-lock.json +6 -5
  19. package/src/agents/aphrodite.md +17 -28
  20. package/src/agents/demeter.md +8 -18
  21. package/src/agents/hephaestus.md +10 -11
  22. package/src/agents/hermes.md +15 -30
  23. package/src/agents/prometheus.md +16 -10
  24. package/src/agents/talos.md +4 -1
  25. package/src/agents/themis.md +4 -3
  26. package/src/agents/zeus.md +16 -280
  27. package/src/instructions/agent-return-format.instructions.md +4 -50
  28. package/src/instructions/backend-standards.instructions.md +2 -0
  29. package/src/instructions/frontend-standards.instructions.md +3 -1
  30. package/src/instructions/memory-protocol.instructions.md +12 -121
  31. package/src/instructions/zeus-anti-stall.instructions.md +8 -111
  32. package/src/instructions/zeus-communication-rules.instructions.md +0 -1
  33. package/src/instructions/zeus-memory-operations.instructions.md +26 -0
  34. package/src/instructions/zeus-timeout-retry.instructions.md +9 -130
  35. package/src/pantheon/secret-scanner.ts +489 -0
  36. package/src/pantheon/v2-delegation-enforce.ts +86 -0
  37. package/src/pantheon/v2-execute-after.ts +186 -0
  38. package/src/pantheon/v2-unsupported.mjs +0 -23
  39. package/src/plugin-v2.ts +254 -102
  40. package/src/plugins/pantheon-hooks.ts +82 -35
  41. package/src/plugins/tui/README.md +14 -0
  42. package/src/plugins/tui/dist/tui.d.ts +11 -8
  43. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  44. package/src/plugins/tui/dist/tui.js +102 -62
  45. package/src/plugins/tui/package-lock.json +30 -33
  46. package/src/plugins/tui/package.json +5 -1
  47. package/src/plugins/tui/src/index.tsx +163 -107
  48. package/src/plugins/tui/tsdown.config.ts +17 -0
  49. package/src/routing.yml +12 -9
  50. package/src/skills/README.md +9 -4
  51. package/src/skills/agent-coordination/SKILL.md +13 -83
  52. package/src/skills/artifact-management/SKILL.md +12 -5
  53. package/src/skills/auto-continue/SKILL.md +37 -27
  54. package/src/skills/code-review-checklist/SKILL.md +5 -5
  55. package/src/skills/council-synthesis/SKILL.md +29 -0
  56. package/src/skills/tdd-with-agents/SKILL.md +18 -10
  57. package/scripts/hooks/scan-secrets.sh +0 -97
  58. package/src/instructions/zeus-council-synthesis.instructions.md +0 -299
@@ -4,14 +4,13 @@
4
4
  * Re-created per Council Synthesis 2026-08-05 (P0): the previous hook plugin
5
5
  * was removed on 24-25/07 because it used the Bun Shell `$` from the plugin
6
6
  * API, whose interface has NO `.timeout()` method — every hook crashed with
7
- * `TypeError: $.quiet().nothrow().timeout is not a function`. The 10 functional
7
+ * `TypeError: $.quiet().nothrow().timeout is not a function`. The remaining
8
8
  * scripts in scripts/hooks/ (gitleaks covers only staged files, NOT tool
9
9
  * calls) were left orphaned. This plugin wires them back into the opencode
10
10
  * runtime via `node:child_process` (version-proof — see hook-runner.ts).
11
11
  *
12
- * Hook mapping (Claude Code protocol payload {tool_name, tool_input,
13
- * agent_id, session_id} delivered on the script stdin):
14
- * - tool.execute.before → validate-talos-scope.sh, scan-secrets.sh,
12
+ * Hook mapping:
13
+ * - tool.execute.before → in-process secret scan, validate-talos-scope.sh,
15
14
  * validate-tool-safety.sh + on-subagent-delegation-start.sh (only when the
16
15
  * tool is a delegation tool such as `task`, to keep the audit log honest)
17
16
  * - tool.execute.after → format-multi-language.sh, log-session-start.sh +
@@ -23,7 +22,7 @@
23
22
  * ({tool, sessionID, callID}). P0-4 (2026-08-06): a `chat.params` hook
24
23
  * records the active agent per session (sessionAgent map), so payloadFor()
25
24
  * now resolves the real agent_id — validate-talos-scope.sh enforces the
26
- * Talos file-count boundary; the agent-agnostic scan-secrets and
25
+ * Talos file-count boundary; the agent-agnostic secret scanner and
27
26
  * validate-tool-safety protections remain fully active.
28
27
  * - tool.execute.before CAN hard-deny — the old "cannot hard-deny" claim
29
28
  * below this line is OUTDATED for 1.18.x (verified 2026-08-06 on the
@@ -34,15 +33,15 @@
34
33
  * the tool body runs (the docs' .env-protection example relies on this).
35
34
  * The permission system remains the primary deny path, but a thrown
36
35
  * hook error is now a supported hard block (hybrid blocking, Fix 2
37
- * 2026-08-06): scan-secrets.sh exits 2 on high-confidence token matches
38
- * → the plugin logs via reportFailure (non-TUI channels) and THEN throws
36
+ * 2026-08-06): high-confidence token matches → the plugin logs via
37
+ * reportFailure (non-TUI channels) and THEN throws
39
38
  * the DELIBERATE block error — the ONLY throw in this plugin. Exit 1
40
39
  * (low-confidence header/KEY names) stays advisory: toast + logs, no
41
40
  * block.
42
41
  * - Logging policy (P0 fix 2026-08-06): NON-ZERO exit → NEVER console.
43
42
  * `console.error` in a plugin writes to the process stderr, which the
44
43
  * opencode TUI renders directly into the terminal — that polluted the
45
- * chat with `[pantheon-hooks:scan-secrets.sh] exit 1: [SECRET SCAN]...`
44
+ * chat with noisy nonzero hook output
46
45
  * spam on every tool call. Non-zero exits now go to THREE non-TUI channels:
47
46
  * 1. client.tui.showToast() — one short, deduped TUI toast (per
48
47
  * (script, exit code, masked match) per session) so the user gets a
@@ -60,8 +59,8 @@
60
59
  * - Hooks NEVER throw: every body is try/catch'd and only logs. All three
61
60
  * reporting channels (toast, app.log, file append) are individually
62
61
  * try/catch'd so a failure in one can never take down the session.
63
- * EXCEPTION (Fix 2, 2026-08-06): the deliberate scan-secrets high-
64
- * confidence block — when scan-secrets.sh exits 2, the hook awaits
62
+ * EXCEPTION (Fix 2, 2026-08-06): the deliberate high-confidence secret
63
+ * block — when the in-process scanner finds a token, the hook awaits
65
64
  * reportFailure FIRST (app.log + hooks.log) and only then throws. The
66
65
  * throw is deliberately NOT swallowed by the surrounding try/catch
67
66
  * (handled via a blockError variable thrown after it), because that
@@ -177,6 +176,7 @@ import { appendFile, mkdir } from 'node:fs/promises'
177
176
  import { join } from 'node:path'
178
177
  import type { Plugin, PluginInput } from '@opencode-ai/plugin'
179
178
  import { pantheonPluginOnce } from '../pantheon/plugin-once.ts'
179
+ import { scanSecretPayload } from '../pantheon/secret-scanner.ts'
180
180
  import { getSharedBoard } from '../pantheon/shared-board.ts'
181
181
  import { type HookPayload, type HookResult, runHook } from './hook-runner.ts'
182
182
 
@@ -320,8 +320,7 @@ const sessionAgent = new Map<string, { agent: string; at: number }>()
320
320
  const RISKY_PATH_RE = /migration|schema\.sql|alembic|models\/|auth|password|token|secret/i
321
321
 
322
322
  /**
323
- * Fix 1 (2026-08-06): high-confidence secret token formats — mirrors
324
- * scripts/hooks/scan-secrets.sh HIGH_CONFIDENCE_PATTERNS. Used by maskSecret()
323
+ * Fix 1 (2026-08-06): high-confidence secret token formats. Used by maskSecret()
325
324
  * to REDACT secret VALUES from any plugin log line: the talos-guard must
326
325
  * never write a raw credential to hooks.log (a real `sk-bf-...` token leaked
327
326
  * in plain text there on 2026-08-06). Header/KEY names (the Bifrost header alone,
@@ -341,8 +340,8 @@ function maskSecret(text: string): string {
341
340
  }
342
341
 
343
342
  /**
344
- * Fix 2 (2026-08-06): message thrown when scan-secrets.sh exits 2
345
- * (HIGH_CONFIDENCE token match). This is the ONLY deliberate throw in the
343
+ * Fix 2 (2026-08-06): message thrown on a high-confidence token match.
344
+ * This is the ONLY deliberate throw in the
346
345
  * plugin — it is thrown AFTER reportFailure so the log channels always write
347
346
  * first, and it is NOT swallowed by the hook's try/catch: opencode's
348
347
  * Plugin.trigger has no catch around hook invocations, so the rejection
@@ -1093,9 +1092,8 @@ function flushIdleReminders(ctx: HookContext): void {
1093
1092
  * (echo routed to structured log + hooks.log, never the TUI).
1094
1093
  * No console.error / console.log anywhere in this path — the TUI stays clean.
1095
1094
  *
1096
- * Returns the underlying HookResult (or null on unexpected failure) so the
1097
- * tool.execute.before handler can inspect scan-secrets.sh's exit code for the
1098
- * Fix-2 hybrid block (code 2 = high-confidence token → throw after logging).
1095
+ * Returns the underlying HookResult (or null on unexpected failure) for the
1096
+ * non-scanner script hooks.
1099
1097
  */
1100
1098
  async function safeRun(
1101
1099
  ctx: HookContext,
@@ -1177,15 +1175,26 @@ const plugin: Plugin = async ({ client, directory }) => {
1177
1175
  // catch: opencode propagates the rejection to fail the tool call.
1178
1176
  let blockError: Error | null = null
1179
1177
  try {
1180
- const hooks = ['validate-talos-scope.sh', 'scan-secrets.sh', 'validate-tool-safety.sh']
1178
+ const hooks = ['validate-talos-scope.sh', 'validate-tool-safety.sh']
1181
1179
  // P0-2: the delegation record must exist BEFORE the payload is built
1182
1180
  // so the start hook receives the delegation_id the stop hook joins on.
1183
- let payload = payloadFor(input, output?.args ?? {})
1184
- if (DELEGATION_TOOL_RE.test(input.tool)) {
1181
+ const args = output?.args ?? (input as { args?: unknown }).args
1182
+ let payload = payloadFor(input, args)
1183
+ // Validate and scan before touching delegation args or launching any
1184
+ // hook subprocess. The shared scanner catches malformed serialization
1185
+ // and returns a fixed fail-closed result.
1186
+ const scan = scanSecretPayload({ ...payload, tool_input: args })
1187
+ if (scan.status === 'invalid') {
1188
+ blockError = new Error(
1189
+ '[pantheon-hooks] Bloqueado: o scanner de segredos não validou a entrada da ferramenta (fail-closed)',
1190
+ )
1191
+ } else if (scan.status === 'block') {
1192
+ blockError = new Error(SECRET_BLOCK_MESSAGE)
1193
+ }
1194
+ if (blockError === null && DELEGATION_TOOL_RE.test(input.tool)) {
1185
1195
  hooks.push('on-subagent-delegation-start.sh')
1186
1196
  // tool.execute.before carries args on `output` (typed); `input.args`
1187
1197
  // also exists at runtime — read from whichever is present.
1188
- const args = output?.args ?? (input as { args?: unknown }).args
1189
1198
  const start: DelegationStart = {
1190
1199
  delegation_id: crypto.randomUUID(),
1191
1200
  agent: delegationAgent(input.tool, args),
@@ -1222,7 +1231,7 @@ const plugin: Plugin = async ({ client, directory }) => {
1222
1231
  const isWriteIntent =
1223
1232
  WRITE_INTENT_TOOLS.has(input.tool) ||
1224
1233
  (input.tool === 'bash' && BASH_WRITE_INTENT_RE.test(bashCommand))
1225
- if (isWriteIntent) {
1234
+ if (blockError === null && isWriteIntent) {
1226
1235
  try {
1227
1236
  const values: string[] = []
1228
1237
  const scan = (v: unknown): void => {
@@ -1273,25 +1282,63 @@ const plugin: Plugin = async ({ client, directory }) => {
1273
1282
  // Advisory only — a failure here must never take down the hook.
1274
1283
  }
1275
1284
  }
1276
- // Fix 2 hybrid blocking: safeRun returns each script's HookResult;
1277
- // scan-secrets.sh exits 2 on HIGH_CONFIDENCE token matches
1278
- // (sk-bf-*, AKIA..., ghp_..., glpat-..., JWT, bearer...) → BLOCK the
1279
- // tool call. Exit 1 (low-confidence header/KEY names) stays advisory
1280
- // — safeRun already logged + toasted it, no block. The toast for
1281
- // code 1/2 fires inside safeRun BEFORE we reach the throw, and the
1282
- // reportFailure below is awaited first — log channels always write.
1283
- const results = await Promise.all(
1284
- hooks.map(async (script) => ({ script, result: await safeRun(ctx, script, payload) })),
1285
- )
1286
- const scan = results.find((r) => r.script === 'scan-secrets.sh')
1287
- if (scan?.result?.code === 2) {
1285
+ // Scan the same serialized hook payload the removed stdin protocol
1286
+ // delivered, but in-process and without logging untrusted input.
1287
+ if (scan.status === 'invalid') {
1288
+ const message =
1289
+ '[pantheon-hooks] Bloqueado: o scanner de segredos não validou a entrada da ferramenta (fail-closed)'
1290
+ await reportFailure(
1291
+ ctx,
1292
+ message,
1293
+ { script: 'secret-scan', tool: input.tool, blocked: true, reason: 'invalid-input' },
1294
+ 'error',
1295
+ )
1296
+ blockError = new Error(message)
1297
+ } else if (scan.status === 'block') {
1298
+ for (const finding of scan.findings) {
1299
+ await reportFailure(
1300
+ ctx,
1301
+ `[SECRET SCAN] High-confidence secret detected: ${finding.masked} (pattern: ${finding.pattern})`,
1302
+ { script: 'secret-scan', tool: input.tool, pattern: finding.pattern },
1303
+ 'error',
1304
+ )
1305
+ }
1288
1306
  await reportFailure(
1289
1307
  ctx,
1290
1308
  SECRET_BLOCK_MESSAGE,
1291
- { script: 'scan-secrets', tool: input.tool, blocked: true, code: 2 },
1309
+ { script: 'secret-scan', tool: input.tool, blocked: true },
1292
1310
  'error',
1293
1311
  )
1312
+ void notifyToast(ctx, {
1313
+ title: 'Pantheon Hook',
1314
+ message: '⚠️ High-confidence secret detected — tool call blocked',
1315
+ variant: 'error',
1316
+ duration: 4000,
1317
+ category: 'errors',
1318
+ dedupeKey: `secret-scan|block|${input.sessionID}`,
1319
+ })
1294
1320
  blockError = new Error(SECRET_BLOCK_MESSAGE)
1321
+ } else if (scan.status === 'advisory') {
1322
+ for (const finding of scan.findings) {
1323
+ await reportFailure(
1324
+ ctx,
1325
+ `[SECRET SCAN] Potential secret detected (low confidence): ${finding.masked} (pattern: ${finding.pattern})`,
1326
+ { script: 'secret-scan', tool: input.tool, pattern: finding.pattern },
1327
+ 'warn',
1328
+ )
1329
+ }
1330
+ void notifyToast(ctx, {
1331
+ title: 'Pantheon Hook',
1332
+ message: '⚠️ Possible secret detected — see log',
1333
+ variant: 'warning',
1334
+ duration: 4000,
1335
+ category: 'errors',
1336
+ dedupeKey: `secret-scan|advisory|${input.sessionID}`,
1337
+ })
1338
+ }
1339
+
1340
+ if (blockError === null) {
1341
+ await Promise.all(hooks.map(async (script) => safeRun(ctx, script, payload)))
1295
1342
  }
1296
1343
  } catch {
1297
1344
  // Never let a hook take down the opencode session — except the
@@ -0,0 +1,14 @@
1
+ # Pantheon TUI compatibility
2
+
3
+ - **OpenCode V1:** supported by the existing `@opencode-ai/plugin@1.18.33`
4
+ TUI API and its `sidebar_content` / `app_bottom` slots.
5
+ - **OpenCode V2 TUI:** unsupported. This package still exports the V1
6
+ `TuiPlugin` factory; it has no verified V2 TUI adapter. Do not infer the V2
7
+ TUI registration or slot contract from the V2 plugin `setup` contract. The
8
+ installed OpenCode host could not be analyzed with REA in this environment
9
+ because no native analysis provider was available, so a V2 contract must be
10
+ verified against a suitable shipped host artifact before adding an adapter.
11
+
12
+ The V1 UI and its slot registrations remain unchanged. Keep this package on its
13
+ existing V1 pins until a separately verified V2 migration can preserve the
14
+ legacy UI behavior or explicitly replace it.
@@ -1,4 +1,4 @@
1
- import { TuiPluginModule } from "@opencode-ai/plugin/tui";
1
+ import { TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui";
2
2
  //#region src/index.d.ts
3
3
  export type DelegationEntry = {
4
4
  /** Job alias, e.g. "apo-1" (from the H1 title, falling back to filename). */
@@ -487,17 +487,20 @@ export declare function navigateToDelegationSession(route: {
487
487
  export declare function createDelegationRowOpenHandler(route: {
488
488
  navigate?: (name: string, params?: Record<string, unknown>) => void | PromiseLike<void>;
489
489
  } | undefined, taskID: string | undefined): () => void;
490
- /** Plugin-level live delegation store shared with the event subscriptions
491
- * in `tui()`: the map of live entries + a version signal bumped on every
492
- * mutation. The View subscribes to the version (in an effect) to refresh the
493
- * durable child list and also reads the map as an optimistic live source. */
490
+ /** Plugin-level live delegation store shared by event subscriptions and View.
491
+ * Mutations notify subscribers so the View can refresh its durable child
492
+ * list while also reading the map as an optimistic live source. */
494
493
  export type LiveDelegationStore = {
495
494
  map: Map<string, LiveDelegationEntry>;
496
- /** Reactive version getter — View reads it inside an effect to re-fetch. */
497
- version: () => number;
498
- /** Bump the version after a live mutation. */
495
+ /** Subscribe to invalidations consumed by the sidebar's refresh path. */
496
+ subscribe: (listener: () => void) => () => void;
497
+ /** Notify sidebar subscribers after a live mutation. */
499
498
  bump: () => void;
500
499
  };
500
+ /** Create the observable live store shared by task events and the sidebar. */
501
+ export declare function createLiveDelegationStore(): LiveDelegationStore;
502
+ /** Register the live task-part events that invalidate the sidebar store. */
503
+ export declare function registerLiveDelegationEvents(api: TuiPluginApi, liveStore: LiveDelegationStore): () => void;
501
504
  declare const plugin: TuiPluginModule & {
502
505
  id: string;
503
506
  setup: () => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":"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"}
1
+ {"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { appendFile, mkdir, readFile, readdir, writeFile } from "node:fs/promise
4
4
  import { homedir } from "node:os";
5
5
  import { dirname, join } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
- import { For, Show, createEffect, createMemo, createResource, createSignal, onCleanup, onMount } from "solid-js";
7
+ import { For, Show, createMemo, createResource, createSignal, onCleanup, onMount } from "solid-js";
8
8
  //#region src/index.tsx
9
9
  /** @jsxImportSource @opentui/solid */
10
10
  /**
@@ -167,7 +167,7 @@ async function detectVersion(api) {
167
167
  if (ver) return ver;
168
168
  }
169
169
  } catch {}
170
- return "1.6.0-beta.6";
170
+ return "1.6.0-beta.7";
171
171
  }
172
172
  /**
173
173
  * usage-bar — AI subscription usage gauge for the opencode TUI.
@@ -509,12 +509,22 @@ async function loadConfig(configPath) {
509
509
  return defaultConfig();
510
510
  }
511
511
  }
512
- /** Vendored usage-bar plugin init: reads config, seeds the kv cache, starts
513
- * the poll loop and registers the `app_bottom` slot. Skips everything (and
512
+ /** Vendored usage-bar plugin init: reads config, seeds the kv cache, registers
513
+ * the `app_bottom` slot, then starts the poll loop. Skips everything (and
514
514
  * registers nothing) when no provider is enabled — mirrors the standalone
515
515
  * plugin's early return. */
516
516
  async function setupUsageBar(api) {
517
+ let disposed = false;
518
+ let clockInterval;
519
+ const pollTimeouts = /* @__PURE__ */ new Set();
520
+ api.lifecycle.onDispose(() => {
521
+ disposed = true;
522
+ if (clockInterval !== void 0) clearInterval(clockInterval);
523
+ for (const timeout of pollTimeouts) clearTimeout(timeout);
524
+ pollTimeouts.clear();
525
+ });
517
526
  const config = await loadConfig(api.state.path?.config);
527
+ if (disposed) return;
518
528
  if (api.state.path?.state) opencodeAuthFile = join(api.state.path.state, "auth.json");
519
529
  const enabled = providers.filter((p) => config.providers[p.id].enabled);
520
530
  if (enabled.length === 0) return;
@@ -526,28 +536,6 @@ async function setupUsageBar(api) {
526
536
  const [byProvider, setByProvider] = createSignal(seed);
527
537
  const [byStatus, setByStatus] = createSignal({});
528
538
  const [now, setNow] = createSignal(Date.now());
529
- setInterval(() => setNow(Date.now()), 1e3);
530
- for (const p of enabled) {
531
- const cfg = config.providers[p.id];
532
- const poll = async () => {
533
- const statusP = config.showStatus && p.statusUrl ? fetchStatus(p.statusUrl) : null;
534
- const [all, status] = await Promise.all([p.fetchUsage(cfg), statusP]);
535
- if (all) {
536
- const windows = all.filter((w) => cfg.show[w.category] && w.resetsAt > Date.now());
537
- setByProvider((prev) => ({
538
- ...prev,
539
- [p.id]: windows
540
- }));
541
- api.kv.set(`usage-bar.${p.id}.windows`, windows);
542
- }
543
- if (status !== null) setByStatus((prev) => ({
544
- ...prev,
545
- [p.id]: status
546
- }));
547
- setTimeout(poll, all ? POLL_MS : POLL_MS * 3);
548
- };
549
- poll();
550
- }
551
539
  api.slots.register({
552
540
  order: 60,
553
541
  slots: { app_bottom() {
@@ -696,6 +684,42 @@ async function setupUsageBar(api) {
696
684
  });
697
685
  } }
698
686
  });
687
+ clockInterval = setInterval(() => setNow(Date.now()), 1e3);
688
+ const schedulePoll = (run, delay) => {
689
+ if (disposed) return;
690
+ const timeout = setTimeout(() => {
691
+ pollTimeouts.delete(timeout);
692
+ if (!disposed) run();
693
+ }, delay);
694
+ pollTimeouts.add(timeout);
695
+ };
696
+ for (const p of enabled) {
697
+ const cfg = config.providers[p.id];
698
+ const poll = async () => {
699
+ if (disposed) return;
700
+ const statusP = config.showStatus && p.statusUrl ? fetchStatus(p.statusUrl) : null;
701
+ const [all, status] = await Promise.all([p.fetchUsage(cfg), statusP]);
702
+ if (disposed) return;
703
+ if (all) {
704
+ const windows = all.filter((w) => cfg.show[w.category] && w.resetsAt > Date.now());
705
+ setByProvider((prev) => ({
706
+ ...prev,
707
+ [p.id]: windows
708
+ }));
709
+ api.kv.set(`usage-bar.${p.id}.windows`, windows);
710
+ }
711
+ if (status !== null) setByStatus((prev) => ({
712
+ ...prev,
713
+ [p.id]: status
714
+ }));
715
+ schedulePoll(runPoll, all ? POLL_MS : POLL_MS * 3);
716
+ };
717
+ const runPoll = () => {
718
+ if (disposed) return;
719
+ poll().catch(() => schedulePoll(runPoll, POLL_MS * 3));
720
+ };
721
+ runPoll();
722
+ }
699
723
  }
700
724
  /** True for `\s` characters (space, tab, newline, CR) — plain char checks so
701
725
  * the parser stays regex-free (CodeQL flagged the old `\s*`/`\s+` + `(.+)`
@@ -1805,10 +1829,49 @@ function DelegationRow(props) {
1805
1829
  return _el$13;
1806
1830
  })();
1807
1831
  }
1808
- /** Plugin-level live delegation store shared with the event subscriptions
1809
- * in `tui()`: the map of live entries + a version signal bumped on every
1810
- * mutation. The View subscribes to the version (in an effect) to refresh the
1811
- * durable child list and also reads the map as an optimistic live source. */
1832
+ /** Plugin-level live delegation store shared by event subscriptions and View.
1833
+ * Mutations notify subscribers so the View can refresh its durable child
1834
+ * list while also reading the map as an optimistic live source. */
1835
+ /** Create the observable live store shared by task events and the sidebar. */
1836
+ function createLiveDelegationStore() {
1837
+ const listeners = /* @__PURE__ */ new Set();
1838
+ return {
1839
+ map: /* @__PURE__ */ new Map(),
1840
+ subscribe(listener) {
1841
+ listeners.add(listener);
1842
+ return () => listeners.delete(listener);
1843
+ },
1844
+ bump() {
1845
+ for (const listener of listeners) listener();
1846
+ }
1847
+ };
1848
+ }
1849
+ /** Register the live task-part events that invalidate the sidebar store. */
1850
+ function registerLiveDelegationEvents(api, liveStore) {
1851
+ const unsubLive = [];
1852
+ try {
1853
+ unsubLive.push(api.event.on("message.part.updated", (event) => {
1854
+ const props = event?.properties ?? {};
1855
+ const part = props.part ?? props.info?.part;
1856
+ if (part === void 0) return;
1857
+ const sample = extractToolActivity(part);
1858
+ if (sample !== null) trackToolActivity(latestToolActivity, sample.sessionID, sample.activity);
1859
+ if (reduceDelegationToolPart(liveStore.map, part)) liveStore.bump();
1860
+ }));
1861
+ } catch {}
1862
+ try {
1863
+ unsubLive.push(api.event.on("message.part.removed", (event) => {
1864
+ const props = event?.properties ?? {};
1865
+ const partID = props.partID ?? props.part?.id;
1866
+ if (partID !== void 0 && removeDelegationEntry(liveStore.map, partID)) liveStore.bump();
1867
+ }));
1868
+ } catch {}
1869
+ return () => {
1870
+ for (const unsub of unsubLive) try {
1871
+ unsub();
1872
+ } catch {}
1873
+ };
1874
+ }
1812
1875
  function View(props) {
1813
1876
  const [showSessions, setShowSessions] = createSignal(false);
1814
1877
  const [showDelegations, setShowDelegations] = createSignal(true);
@@ -1938,11 +2001,12 @@ function View(props) {
1938
2001
  cleanup.push(props.api.event.on("session.deleted", eventRefresh));
1939
2002
  cleanup.push(props.api.event.on("session.status", eventRefresh));
1940
2003
  } catch {}
1941
- createEffect(() => {
1942
- props.liveStore.version();
2004
+ cleanup.push(props.liveStore.subscribe(() => {
1943
2005
  eventRefreshCount += 1;
1944
2006
  refreshDelegations();
1945
- });
2007
+ }));
2008
+ eventRefreshCount += 1;
2009
+ refreshDelegations();
1946
2010
  const poll = setInterval(() => {
1947
2011
  setNow(Date.now());
1948
2012
  refreshDelegations();
@@ -2168,35 +2232,11 @@ const tui = (api, _options, _meta) => {
2168
2232
  if (pantheonPluginOnce("pantheon:tui")) return;
2169
2233
  const [version, setVersion] = createSignal(null);
2170
2234
  detectVersion(api).then((detected) => setVersion(detected)).catch(() => setVersion(null));
2171
- setupUsageBar(api);
2172
- const [liveVersion, setLiveVersion] = createSignal(0);
2173
- const liveStore = {
2174
- map: /* @__PURE__ */ new Map(),
2175
- version: liveVersion,
2176
- bump: () => setLiveVersion((v) => v + 1)
2177
- };
2178
- const unsubLive = [];
2179
- try {
2180
- unsubLive.push(api.event.on("message.part.updated", (event) => {
2181
- const props = event?.properties ?? {};
2182
- const part = props.part ?? props.info?.part;
2183
- if (part === void 0) return;
2184
- const sample = extractToolActivity(part);
2185
- if (sample !== null) trackToolActivity(latestToolActivity, sample.sessionID, sample.activity);
2186
- if (reduceDelegationToolPart(liveStore.map, part)) liveStore.bump();
2187
- }));
2188
- } catch {}
2189
- try {
2190
- unsubLive.push(api.event.on("message.part.removed", (event) => {
2191
- const props = event?.properties ?? {};
2192
- const partID = props.partID ?? props.part?.id;
2193
- if (partID !== void 0 && removeDelegationEntry(liveStore.map, partID)) liveStore.bump();
2194
- }));
2195
- } catch {}
2235
+ setupUsageBar(api).catch(() => void 0);
2236
+ const liveStore = createLiveDelegationStore();
2237
+ const unsubscribeLive = registerLiveDelegationEvents(api, liveStore);
2196
2238
  api.lifecycle.onDispose(() => {
2197
- for (const unsub of unsubLive) try {
2198
- unsub();
2199
- } catch {}
2239
+ unsubscribeLive();
2200
2240
  liveStore.map.clear();
2201
2241
  });
2202
2242
  api.slots.register({
@@ -2221,6 +2261,6 @@ const plugin = {
2221
2261
  setup: async () => {}
2222
2262
  };
2223
2263
  //#endregion
2224
- export { DELEGATION_ALIAS_WIDTH, DELEGATION_CHILDREN_RECENCY_MS, DELEGATION_CHILD_STATUS_GRACE_MS, DELEGATION_DESCRIPTION_MAX, DELEGATION_DONE_RETENTION_MS, DELEGATION_ELAPSED_WIDTH, DELEGATION_FAILED_RETENTION_MS, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, IDLE_SILENCE_MS, NATIVE_LIVE_ALIASLESS_TTL_MS, STALE_RUNNING_THRESHOLD_MS, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, createDelegationRowOpenHandler, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, filterDelegationsToSession, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
2264
+ export { DELEGATION_ALIAS_WIDTH, DELEGATION_CHILDREN_RECENCY_MS, DELEGATION_CHILD_STATUS_GRACE_MS, DELEGATION_DESCRIPTION_MAX, DELEGATION_DONE_RETENTION_MS, DELEGATION_ELAPSED_WIDTH, DELEGATION_FAILED_RETENTION_MS, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, IDLE_SILENCE_MS, NATIVE_LIVE_ALIASLESS_TTL_MS, STALE_RUNNING_THRESHOLD_MS, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, createDelegationRowOpenHandler, createLiveDelegationStore, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, filterDelegationsToSession, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readDelegationEntries, reduceDelegationToolPart, registerLiveDelegationEvents, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
2225
2265
 
2226
2266
  //# sourceMappingURL=tui.js.map
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pantheon-tui",
3
- "version": "1.6.0-beta.6",
3
+ "version": "1.6.0-beta.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pantheon-tui",
9
- "version": "1.6.0-beta.6",
9
+ "version": "1.6.0-beta.7",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@opencode-ai/plugin": "1.18.33",
@@ -41,19 +41,6 @@
41
41
  "node": ">=18"
42
42
  }
43
43
  },
44
- "node_modules/@ampproject/remapping": {
45
- "version": "2.3.0",
46
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
47
- "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
48
- "license": "Apache-2.0",
49
- "dependencies": {
50
- "@jridgewell/gen-mapping": "^0.3.5",
51
- "@jridgewell/trace-mapping": "^0.3.24"
52
- },
53
- "engines": {
54
- "node": ">=6.0.0"
55
- }
56
- },
57
44
  "node_modules/@babel/code-frame": {
58
45
  "version": "7.29.7",
59
46
  "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
@@ -78,21 +65,21 @@
78
65
  }
79
66
  },
80
67
  "node_modules/@babel/core": {
81
- "version": "7.28.0",
82
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
83
- "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
84
- "license": "MIT",
85
- "dependencies": {
86
- "@ampproject/remapping": "^2.2.0",
87
- "@babel/code-frame": "^7.27.1",
88
- "@babel/generator": "^7.28.0",
89
- "@babel/helper-compilation-targets": "^7.27.2",
90
- "@babel/helper-module-transforms": "^7.27.3",
91
- "@babel/helpers": "^7.27.6",
92
- "@babel/parser": "^7.28.0",
93
- "@babel/template": "^7.27.2",
94
- "@babel/traverse": "^7.28.0",
95
- "@babel/types": "^7.28.0",
68
+ "version": "7.29.7",
69
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
70
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
71
+ "license": "MIT",
72
+ "dependencies": {
73
+ "@babel/code-frame": "^7.29.7",
74
+ "@babel/generator": "^7.29.7",
75
+ "@babel/helper-compilation-targets": "^7.29.7",
76
+ "@babel/helper-module-transforms": "^7.29.7",
77
+ "@babel/helpers": "^7.29.7",
78
+ "@babel/parser": "^7.29.7",
79
+ "@babel/template": "^7.29.7",
80
+ "@babel/traverse": "^7.29.7",
81
+ "@babel/types": "^7.29.7",
82
+ "@jridgewell/remapping": "^2.3.5",
96
83
  "convert-source-map": "^2.0.0",
97
84
  "debug": "^4.1.0",
98
85
  "gensync": "^1.0.0-beta.2",
@@ -469,6 +456,16 @@
469
456
  "@jridgewell/trace-mapping": "^0.3.24"
470
457
  }
471
458
  },
459
+ "node_modules/@jridgewell/remapping": {
460
+ "version": "2.3.5",
461
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
462
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
463
+ "license": "MIT",
464
+ "dependencies": {
465
+ "@jridgewell/gen-mapping": "^0.3.5",
466
+ "@jridgewell/trace-mapping": "^0.3.24"
467
+ }
468
+ },
472
469
  "node_modules/@jridgewell/resolve-uri": {
473
470
  "version": "3.1.2",
474
471
  "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
@@ -2537,9 +2534,9 @@
2537
2534
  }
2538
2535
  },
2539
2536
  "node_modules/seroval": {
2540
- "version": "1.5.6",
2541
- "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.5.6.tgz",
2542
- "integrity": "sha512-rVQVWjjSvlINzaQPZH5JFqsqEsIWdTxY3iJZCnTL/5gQbXIRooVZKI60tVCkOVfzcRPejboxO2t0P89dg5mQaA==",
2537
+ "version": "1.6.8",
2538
+ "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.6.8.tgz",
2539
+ "integrity": "sha512-HlSgSAkTk4EqHcje1ptJjfZi1YDv5KbhVJ/d3P7T/nAXua2VmDu+AKDX5VTdFfZf48nDkWB2TKYt0DrCSa+3wg==",
2543
2540
  "license": "MIT",
2544
2541
  "engines": {
2545
2542
  "node": ">=10"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pantheon-tui",
3
3
  "type": "module",
4
- "version": "1.6.0-beta.6",
4
+ "version": "1.6.0-beta.7",
5
5
  "description": "Pantheon TUI plugin — sidebar (version, preset, sessions, real-time delegations) + AI subscription usage gauges incl. OpenCode Go/Zen dollar limits (vendored, MIT)",
6
6
  "license": "MIT",
7
7
  "engines": {
@@ -31,8 +31,12 @@
31
31
  "tsdown": "0.23.0"
32
32
  },
33
33
  "overrides": {
34
+ "@babel/core": "7.29.7",
35
+ "seroval": "1.6.8",
36
+ "solid-js": "1.9.12",
34
37
  "rolldown": "1.2.7"
35
38
  },
39
+ "//overrides": "TUI production advisory fixes: Babel >=7.29.6 and Seroval >=1.6.3; Solid stays at 1.9.12 to satisfy OpenTUI's exact peer. Remove only after upstream ranges include fixed versions; Seroval compatibility is covered by the Solid serializer regression test.",
36
40
  "dependencies": {
37
41
  "@opencode-ai/plugin": "1.18.33",
38
42
  "@opentui/core": "0.5.10",