@ashx-j/lunr 0.2.9 → 0.2.11

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 (145) hide show
  1. package/dist/builtin-extensions/ashxj-spinners.d.ts +1 -4
  2. package/dist/builtin-extensions/ashxj-spinners.d.ts.map +1 -1
  3. package/dist/builtin-extensions/ashxj-spinners.js +3 -29
  4. package/dist/builtin-extensions/ashxj-spinners.js.map +1 -1
  5. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  6. package/dist/builtin-extensions/ashxj-tui.js +5 -4
  7. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  8. package/dist/builtin-extensions/lunr-cron.d.ts.map +1 -1
  9. package/dist/builtin-extensions/lunr-cron.js +6 -1
  10. package/dist/builtin-extensions/lunr-cron.js.map +1 -1
  11. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
  12. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +1 -1
  13. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
  14. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +3 -4
  16. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +2 -2
  19. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +2 -2
  21. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +4 -4
  23. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  25. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +5 -1
  26. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  27. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +8 -7
  29. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +2 -2
  31. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js +2 -2
  33. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +4 -3
  35. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +2 -2
  37. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +4 -6
  39. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  40. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +26 -18
  41. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  42. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  43. package/dist/builtin-extensions/pi-web-access/index.js +3 -1
  44. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  45. package/dist/catalog/models.json +1 -1
  46. package/dist/catalog/providers/nvidia.json +1 -1
  47. package/dist/catalog/providers/opencode-go.json +1 -1
  48. package/dist/catalog/providers/opencode.json +1 -1
  49. package/dist/catalog/providers/openrouter.json +1 -1
  50. package/dist/catalog/providers/qwen-cloud-cn.json +1 -1
  51. package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
  52. package/dist/catalog/providers/xai.json +1 -1
  53. package/dist/catalog/publication.json +3 -3
  54. package/dist/core/agent-session.d.ts +2 -0
  55. package/dist/core/agent-session.d.ts.map +1 -1
  56. package/dist/core/agent-session.js +11 -3
  57. package/dist/core/agent-session.js.map +1 -1
  58. package/dist/core/customize.d.ts +1 -0
  59. package/dist/core/customize.d.ts.map +1 -1
  60. package/dist/core/customize.js +3 -0
  61. package/dist/core/customize.js.map +1 -1
  62. package/dist/core/models-store.d.ts.map +1 -1
  63. package/dist/core/models-store.js +13 -1
  64. package/dist/core/models-store.js.map +1 -1
  65. package/dist/core/permissions.d.ts +9 -0
  66. package/dist/core/permissions.d.ts.map +1 -1
  67. package/dist/core/permissions.js +60 -20
  68. package/dist/core/permissions.js.map +1 -1
  69. package/dist/core/plan-mode.d.ts.map +1 -1
  70. package/dist/core/plan-mode.js +49 -7
  71. package/dist/core/plan-mode.js.map +1 -1
  72. package/dist/core/settings-manager.d.ts +3 -0
  73. package/dist/core/settings-manager.d.ts.map +1 -1
  74. package/dist/core/settings-manager.js +8 -0
  75. package/dist/core/settings-manager.js.map +1 -1
  76. package/dist/core/swarm.d.ts +17 -4
  77. package/dist/core/swarm.d.ts.map +1 -1
  78. package/dist/core/swarm.js +36 -4
  79. package/dist/core/swarm.js.map +1 -1
  80. package/dist/core/tools/bash.d.ts.map +1 -1
  81. package/dist/core/tools/bash.js +2 -1
  82. package/dist/core/tools/bash.js.map +1 -1
  83. package/dist/core/tools/edit.d.ts.map +1 -1
  84. package/dist/core/tools/edit.js +9 -6
  85. package/dist/core/tools/edit.js.map +1 -1
  86. package/dist/core/tools/find.d.ts.map +1 -1
  87. package/dist/core/tools/find.js +2 -1
  88. package/dist/core/tools/find.js.map +1 -1
  89. package/dist/core/tools/grep.d.ts.map +1 -1
  90. package/dist/core/tools/grep.js +2 -1
  91. package/dist/core/tools/grep.js.map +1 -1
  92. package/dist/core/tools/ls.d.ts.map +1 -1
  93. package/dist/core/tools/ls.js +2 -1
  94. package/dist/core/tools/ls.js.map +1 -1
  95. package/dist/core/tools/read.d.ts.map +1 -1
  96. package/dist/core/tools/read.js +2 -1
  97. package/dist/core/tools/read.js.map +1 -1
  98. package/dist/core/tools/render-utils.d.ts +13 -3
  99. package/dist/core/tools/render-utils.d.ts.map +1 -1
  100. package/dist/core/tools/render-utils.js +10 -2
  101. package/dist/core/tools/render-utils.js.map +1 -1
  102. package/dist/core/tools/write.d.ts.map +1 -1
  103. package/dist/core/tools/write.js +5 -3
  104. package/dist/core/tools/write.js.map +1 -1
  105. package/dist/gateway/agent-bridge.d.ts +2 -1
  106. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  107. package/dist/gateway/agent-bridge.js +11 -1
  108. package/dist/gateway/agent-bridge.js.map +1 -1
  109. package/dist/gateway/commands.d.ts.map +1 -1
  110. package/dist/gateway/commands.js +2 -1
  111. package/dist/gateway/commands.js.map +1 -1
  112. package/dist/gateway/cron.d.ts +4 -1
  113. package/dist/gateway/cron.d.ts.map +1 -1
  114. package/dist/gateway/cron.js +17 -8
  115. package/dist/gateway/cron.js.map +1 -1
  116. package/dist/gateway/router.d.ts +1 -1
  117. package/dist/gateway/router.d.ts.map +1 -1
  118. package/dist/gateway/router.js.map +1 -1
  119. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  120. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  121. package/dist/modes/interactive/components/settings-selector.js +11 -1
  122. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  123. package/dist/modes/interactive/components/thinking-tail.d.ts +1 -0
  124. package/dist/modes/interactive/components/thinking-tail.d.ts.map +1 -1
  125. package/dist/modes/interactive/components/thinking-tail.js +2 -6
  126. package/dist/modes/interactive/components/thinking-tail.js.map +1 -1
  127. package/dist/modes/interactive/components/tool-execution.d.ts +6 -0
  128. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  129. package/dist/modes/interactive/components/tool-execution.js +75 -16
  130. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  131. package/dist/modes/interactive/interactive-mode.d.ts +15 -1
  132. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  133. package/dist/modes/interactive/interactive-mode.js +139 -34
  134. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  135. package/docs/terminal-setup.md +2 -2
  136. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  137. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  138. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  139. package/examples/extensions/gondolin/package-lock.json +2 -2
  140. package/examples/extensions/gondolin/package.json +1 -1
  141. package/examples/extensions/sandbox/package-lock.json +2 -2
  142. package/examples/extensions/sandbox/package.json +1 -1
  143. package/examples/extensions/with-deps/package-lock.json +2 -2
  144. package/examples/extensions/with-deps/package.json +1 -1
  145. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"ashxj-tui.js","sourceRoot":"","sources":["../../src/builtin-extensions/ashxj-tui.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ashxj-tui — a custom slim chatbox for pi.\n *\n * Replaces pi-zentui's prompt box + statusline with:\n * - A rounded prompt box that auto-expands as the typed message wraps to\n * multiple rows (the sides extend; height grows with content).\n * - A right-aligned chip on the box's BOTTOM border:\n * model · provider · effort (e.g. `glm-5.2 · Ollama Cloud · xhigh`)\n * - A slim stats line (extension statuses · context% · ↑↓; each segment\n * toggle-gated via the lunr customize bridge) BELOW the box, not wrapped\n * around the input.\n * - No session-mode indicator anywhere (pi has no such concept).\n *\n * Loaded by pi via jiti — no build step, plain TypeScript.\n *\n * NOTE on type imports (see `ashxj-thinking`/`simple-memory` for the convention):\n * This file declares structural types inline rather than importing them from\n * `@ashx-j/lunr` / `@ashx-j/lunr-tui`.\n * pi-coding-agent's `index.d.ts` re-exports from internal `.d.ts` files that\n * contain subpath imports like `@ashx-j/lunr-ai/compat`, which do not\n * resolve under `tsc` with a file argument. We keep the typecheck\n * self-contained with inline types and verify via the included `tsconfig.json`\n * (`moduleResolution: \"Bundler\"` + `skipLibCheck: true`).\n *\n * The ONE exception is `CustomEditor`, imported as a RUNTIME VALUE directly\n * from its defining module (`modes/interactive/components/custom-editor.ts`).\n * We must `extends` it to inherit pi's app keybindings (escape, ctrl+d, model\n * switching, extension shortcuts) — wrapping would lose those. It is imported\n * from the concrete module, NOT the package barrel, because the barrel\n * re-exports main.ts which imports this file — a circular import that crashes\n * under vite-node (`Class extends value undefined`).\n */\n\nimport { CustomEditor } from \"../modes/interactive/components/custom-editor.js\";\n\n// lunr: customize bridge — read the prompt-symbol toggle (bridgeless → no symbol).\nconst PROMPT_SYMBOL_BRIDGE = Symbol.for(\"@lunr/customize\");\nconst PERMISSION_MODE_BRIDGE = Symbol.for(\"@lunr/permission-mode\");\ninterface CustomizeBridgeForPrompt {\n\tgetPromptSymbol(): boolean;\n\t// lunr: footer element toggles (added to the same bridge).\n\tgetFooterMcp?(): boolean;\n\tgetFooterLsp?(): boolean;\n\tgetFooterContext?(): boolean;\n\tgetFooterTokens?(): boolean;\n\tgetFooterStatuses?(): boolean;\n\tgetFooterGit?(): boolean;\n\tgetFooterPlan?(): boolean;\n\tgetFooterPlanBar?(): boolean;\n}\ninterface PermissionModeBridgeForFooter {\n\tgetMode(): string | undefined;\n}\nfunction lunrCustomizeBridge(): CustomizeBridgeForPrompt | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[PROMPT_SYMBOL_BRIDGE] as CustomizeBridgeForPrompt | undefined;\n}\nfunction lunrPermissionModeBridge(): PermissionModeBridgeForFooter | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[PERMISSION_MODE_BRIDGE] as PermissionModeBridgeForFooter | undefined;\n}\nfunction lunrPromptSymbolEnabled(): boolean {\n\treturn lunrCustomizeBridge()?.getPromptSymbol() ?? false;\n}\n// lunr: footer toggles, read at render time. Bridgeless / missing-getter fallback\n// matches the settings-manager defaults: MCP on, LSP off, everything else on.\nfunction lunrFooterToggles(): {\n\tmcp: boolean;\n\tlsp: boolean;\n\tcontext: boolean;\n\ttokens: boolean;\n\tstatuses: boolean;\n\tgit: boolean;\n\tplan: boolean;\n\tplanBar: boolean;\n} {\n\tconst bridge = lunrCustomizeBridge();\n\treturn {\n\t\tmcp: bridge?.getFooterMcp?.() ?? true,\n\t\tlsp: bridge?.getFooterLsp?.() ?? false,\n\t\tcontext: bridge?.getFooterContext?.() ?? true,\n\t\ttokens: bridge?.getFooterTokens?.() ?? true,\n\t\tstatuses: bridge?.getFooterStatuses?.() ?? true,\n\t\tgit: bridge?.getFooterGit?.() ?? true,\n\t\tplan: bridge?.getFooterPlan?.() ?? true,\n\t\tplanBar: bridge?.getFooterPlanBar?.() ?? true,\n\t};\n}\n\nconst USAGE_SERVICE_BRIDGE = Symbol.for(\"@lunr/usage-service\");\ninterface UsageServiceBridgeForFooter {\n\tpickForFooter?(providerId: string): { label: string; usedPercent: number } | undefined;\n\tprefetch?(providerId: string): void;\n}\nfunction lunrUsageBridge(): UsageServiceBridgeForFooter | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[USAGE_SERVICE_BRIDGE] as UsageServiceBridgeForFooter | undefined;\n}\n\nfunction compactPlanBar(percent: number, theme: Theme): string {\n\tconst cells = 8;\n\tconst clamped = Math.max(0, Math.min(100, percent));\n\tconst filled = Math.round((clamped / 100) * cells);\n\tconst token = clamped > 90 ? \"error\" : clamped > 70 ? \"warning\" : \"success\";\n\tconst fill = filled > 0 ? color(theme, token, \"█\".repeat(filled)) : \"\";\n\tconst rest = filled < cells ? color(theme, \"dim\", \"░\".repeat(cells - filled)) : \"\";\n\treturn fill + rest;\n}\n// lunr: permission mode for the footer safety indicator (always shown).\nfunction lunrPermissionMode(): string | undefined {\n\treturn lunrPermissionModeBridge()?.getMode();\n}\n// lunr: prompt glyph comes from the theme tokens `glyphs.promptMoon` /\n// `glyphs.promptArrow` (defaults below match moon.json). An empty token hides\n// that part; both empty = no glyph at all.\nfunction lunrPromptGlyph(theme: Theme | undefined): string {\n\tconst moon = theme?.glyph?.(\"promptMoon\") ?? \"☾\";\n\tconst arrow = theme?.glyph?.(\"promptArrow\") ?? \">\";\n\tconst parts = [moon, arrow].filter((s) => s !== \"\");\n\treturn parts.length > 0 ? `${parts.join(\" \")} ` : \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Minimal structural types (inline — see file header)\n// ---------------------------------------------------------------------------\n\ntype ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\n/** Theme token for the chatbox thinking-level border / effort chip. */\nexport function thinkingThemeToken(level: ThinkingLevel): string {\n\tswitch (level) {\n\t\tcase \"off\":\n\t\t\treturn \"thinkingOff\";\n\t\tcase \"minimal\":\n\t\t\treturn \"thinkingMinimal\";\n\t\tcase \"low\":\n\t\t\treturn \"thinkingLow\";\n\t\tcase \"medium\":\n\t\t\treturn \"thinkingMedium\";\n\t\tcase \"high\":\n\t\t\treturn \"thinkingHigh\";\n\t\tcase \"xhigh\":\n\t\t\treturn \"thinkingXhigh\";\n\t\tcase \"max\":\n\t\t\treturn \"thinkingMax\";\n\t\tdefault:\n\t\t\treturn \"thinkingOff\";\n\t}\n}\n\n/** Chip effort label — identity, locked so xhigh/max are never mapped down to high. */\nexport function formatChipEffort(level: ThinkingLevel): string {\n\treturn level;\n}\n\n/** Trimmed view of pi's `Theme` — only the methods we use. */\ninterface Theme {\n\tfg(token: string, text: string): string;\n\t/** lunr: prompt glyph tokens (optional for forward/backward compat). */\n\tglyph?(name: \"promptMoon\" | \"promptArrow\"): string;\n}\n\n/** Trimmed view of `pi-tui`'s `TUI` — only the method we use. */\ninterface TUIHandle {\n\trequestRender(force?: boolean): void;\n}\n\n/** Trimmed view of `pi-tui`'s `EditorTheme`. */\ninterface EditorThemeLike {\n\tborderColor: (str: string) => string;\n\tselectList: unknown;\n}\n\n/** Opaque keybindings manager. */\ninterface KeybindingsLike {\n\treadonly _?: unknown;\n}\n\n/** Trimmed view of an autocomplete list (the editor's private `autocompleteList`). */\ninterface AutocompleteListLike {\n\trender(width: number): string[];\n}\n\n/** Trimmed view of pi's `ReadonlyFooterDataProvider`. */\ninterface ReadonlyFooterDataProvider {\n\tgetGitBranch(): string | null;\n\tgetGitDiffstat?(): { added: number; removed: number } | null;\n\tgetExtensionStatuses(): ReadonlyMap<string, string>;\n\tgetAvailableProviderCount(): number;\n\tonBranchChange(callback: () => void): () => void;\n}\n\n/** Trimmed view of the `getContextUsage` return value. */\ninterface ContextUsage {\n\ttokens: number | null;\n\tcontextWindow: number;\n\tpercent: number | null;\n}\n\n/** Trimmed view of an assistant message's usage — the bits we render. */\ninterface AssistantUsage {\n\tinput: number;\n\toutput: number;\n\tcost: { total: number };\n}\n\n/** Trimmed view of an assistant message. */\ninterface AssistantMessageLike {\n\trole: \"assistant\";\n\tusage: AssistantUsage;\n}\n\n/** Trimmed view of a session entry — only what we iterate over. */\ntype SessionEntry =\n\t| { type: \"message\"; message: AssistantMessageLike }\n\t| { type: string; message?: unknown };\n\n/** Trimmed view of a `ReadonlySessionManager`. */\ninterface ReadonlySessionManagerLike {\n\tgetEntries(): readonly SessionEntry[];\n\tgetBranch?(): readonly SessionEntry[];\n}\n\n/** Trimmed view of a `Model`. */\ninterface ModelLike {\n\tid?: string;\n\tprovider?: string;\n\tcontextWindow?: number;\n\treasoning?: boolean;\n\tthinkingLevelMap?: Record<string, string | null>;\n}\n\ninterface ExtensionUIContextLike {\n\tsetEditorComponent(factory: EditorFactoryLike | undefined): void;\n\tsetFooter(factory: FooterFactoryLike | undefined): void;\n\treadonly theme?: Theme;\n}\n\n/** Trimmed view of `ExtensionContext`. */\ninterface ExtensionContextLike {\n\tmode: \"tui\" | \"rpc\" | \"json\" | \"print\";\n\thasUI: boolean;\n\tmodel: ModelLike | undefined;\n\tsessionManager: ReadonlySessionManagerLike;\n\tgetContextUsage(): ContextUsage | undefined;\n\tui: ExtensionUIContextLike;\n}\n\n/** Trimmed view of `ExtensionAPI`. */\ninterface ExtensionAPI {\n\tgetThinkingLevel(): ThinkingLevel;\n\ton(event: string, handler: (event: unknown, ctx: ExtensionContextLike) => void): void;\n}\n\n/** `setEditorComponent` factory shape. */\ntype EditorFactoryLike = (\n\ttui: TUIHandle,\n\ttheme: EditorThemeLike,\n\tkeybindings: KeybindingsLike,\n) => EditorComponentLike;\n\ninterface EditorComponentLike {\n\trender(width: number): string[];\n\tgetText(): string;\n\tsetText(text: string): void;\n\tinvalidate(): void;\n\thandleInput?(data: string): void;\n}\n\n/** `setFooter` factory shape. */\ntype FooterFactoryLike = (\n\ttui: TUIHandle,\n\ttheme: Theme,\n\tfooterData: ReadonlyFooterDataProvider,\n) => FooterComponentLike;\n\ninterface FooterComponentLike {\n\trender(width: number): string[];\n\tdispose?(): void;\n\tinvalidate?(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Display-width helpers (ANSI-aware; CJK-aware)\n//\n// The editor (`Editor.render`) word-wraps to the given width using grapheme\n// width, so each returned line is ≤ that many visual columns. To right-pad a\n// line for our box we need a width model that matches closely enough: skip ALL\n// escape sequences (SGR color, OSC/DCS/APC/PM/SOS string sequences such as\n// pi-tui's `CURSOR_MARKER` `ESC _pi:c BEL`, and two-char escapes), count common\n// East-Asian wide ranges as 2, combining marks and variation selectors as 0.\n// Handling the string sequences as 0-width is what keeps the right `│` rail\n// aligned on the focused (cursor) line — the base editor embeds the marker and\n// the TUI strips it at flush time, so we must not count it here.\n// ---------------------------------------------------------------------------\n\nfunction skipAnsi(str: string, pos: number): number {\n\tif (str.charCodeAt(pos) !== 0x1b) return 0;\n\tconst next = str.charCodeAt(pos + 1);\n\t// CSI: ESC [ ... <final 0x40-0x7e>\n\tif (next === 0x5b /* [ */) {\n\t\tlet j = pos + 2;\n\t\twhile (j < str.length) {\n\t\t\tconst c = str.charCodeAt(j);\n\t\t\tif (c >= 0x40 && c <= 0x7e) return j + 1 - pos;\n\t\t\tj++;\n\t\t}\n\t\treturn str.length - pos; // unterminated; consume the rest\n\t}\n\t// String sequences — OSC (]), DCS (P), APC (_), PM (^), SOS (X) — terminated\n\t// by BEL (0x07) or ST (ESC \\). pi-tui's CURSOR_MARKER `ESC _pi:c BEL` is APC;\n\t// OSC color queries are OSC. All are zero visual width.\n\tif (\n\t\tnext === 0x5d /* ] */ ||\n\t\tnext === 0x50 /* P */ ||\n\t\tnext === 0x5f /* _ */ ||\n\t\tnext === 0x5e /* ^ */ ||\n\t\tnext === 0x58 /* X */\n\t) {\n\t\tlet j = pos + 2;\n\t\twhile (j < str.length) {\n\t\t\tconst c = str.charCodeAt(j);\n\t\t\tif (c === 0x07 /* BEL */) return j + 1 - pos;\n\t\t\tif (c === 0x1b && str.charCodeAt(j + 1) === 0x5c /* \\ */) return j + 2 - pos;\n\t\t\tj++;\n\t\t}\n\t\treturn str.length - pos; // unterminated; consume the rest\n\t}\n\t// Any other ESC sequence: consume ESC + one final byte (e.g. ESC c, ESC \\,\n\t// ESC ( B). A lone trailing ESC with no following byte is 0 width too.\n\treturn Number.isNaN(next) ? 1 : 2;\n}\n\nfunction isWide(cp: number): boolean {\n\treturn (\n\t\t(cp >= 0x1100 && cp <= 0x115f) ||\n\t\t(cp >= 0x2e80 && cp <= 0x303e) ||\n\t\t(cp >= 0x3041 && cp <= 0x33ff) ||\n\t\t(cp >= 0x3400 && cp <= 0x4dbf) ||\n\t\t(cp >= 0x4e00 && cp <= 0x9fff) ||\n\t\t(cp >= 0xa000 && cp <= 0xa4cf) ||\n\t\t(cp >= 0xac00 && cp <= 0xd7a3) ||\n\t\t(cp >= 0xf900 && cp <= 0xfaff) ||\n\t\t(cp >= 0xfe30 && cp <= 0xfe4f) ||\n\t\t(cp >= 0xff00 && cp <= 0xff60) ||\n\t\t(cp >= 0xffe0 && cp <= 0xffe6) ||\n\t\t(cp >= 0x1f300 && cp <= 0x1faff) ||\n\t\t(cp >= 0x20000 && cp <= 0x3fffd)\n\t);\n}\n\nfunction charWidth(cp: number): number {\n\tif (cp >= 0x20 && cp < 0x7f) return 1;\n\tif ((cp >= 0x0300 && cp <= 0x036f) || (cp >= 0xfe00 && cp <= 0xfe0f) || cp === 0x200d) return 0;\n\treturn isWide(cp) ? 2 : 1;\n}\n\n/** Visible width of a string, ignoring SGR color codes. */\nfunction displayWidth(str: string): number {\n\tlet w = 0;\n\tlet i = 0;\n\twhile (i < str.length) {\n\t\tconst skip = skipAnsi(str, i);\n\t\tif (skip > 0) {\n\t\t\ti += skip;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cp = str.codePointAt(i) ?? 0;\n\t\tw += charWidth(cp);\n\t\ti += cp > 0xffff ? 2 : 1;\n\t}\n\treturn w;\n}\n\n/** Right-pad a (possibly colored) line to `width` visible columns. */\nfunction padRight(line: string, width: number): string {\n\tconst w = displayWidth(line);\n\tif (w >= width) return line;\n\treturn line + \" \".repeat(width - w);\n}\n\n/** Truncate a plain (non-ANSI) string to `maxWidth` visible columns. */\nfunction truncatePlain(text: string, maxWidth: number): string {\n\tif (maxWidth <= 0) return \"\";\n\tif (displayWidth(text) <= maxWidth) return text;\n\tlet out = \"\";\n\tlet w = 0;\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst code = text.codePointAt(i) ?? 0;\n\t\tconst cw = charWidth(code);\n\t\tif (w + cw > maxWidth) break;\n\t\tout += String.fromCodePoint(code);\n\t\tw += cw;\n\t\ti += code > 0xffff ? 2 : 1;\n\t}\n\treturn out;\n}\n\n/** Truncate a (possibly ANSI-colored) string to `maxWidth` visible columns,\n * re-emitting an SGR reset at the cut so styling doesn't bleed. */\nfunction truncateToWidth(text: string, maxWidth: number, ellipsis = \"\"): string {\n\tif (maxWidth <= 0) return \"\";\n\tif (displayWidth(text) <= maxWidth) return text;\n\tconst target = Math.max(0, maxWidth - displayWidth(ellipsis));\n\tlet out = \"\";\n\tlet w = 0;\n\tlet i = 0;\n\twhile (i < text.length && w < target) {\n\t\tconst skip = skipAnsi(text, i);\n\t\tif (skip > 0) {\n\t\t\tout += text.slice(i, i + skip);\n\t\t\ti += skip;\n\t\t\tcontinue;\n\t\t}\n\t\tconst code = text.codePointAt(i) ?? 0;\n\t\tconst cw = charWidth(code);\n\t\tif (w + cw > target) break;\n\t\tout += String.fromCodePoint(code);\n\t\tw += cw;\n\t\ti += code > 0xffff ? 2 : 1;\n\t}\n\tout += \"\\x1b[0m\";\n\treturn out + ellipsis;\n}\n\n/** Clamp each rendered line to `width` visible columns (fallback path). */\nfunction clampLines(lines: string[], width: number): string[] {\n\treturn lines.map((l) => (displayWidth(l) > width ? truncateToWidth(l, width, \"\") : l));\n}\n\n/** Apply a theme `fg` token safely; falls back to plain text. */\nfunction color(theme: Theme | undefined, token: string, text: string): string {\n\ttry {\n\t\treturn theme?.fg?.(token, text) ?? text;\n\t} catch {\n\t\treturn text;\n\t}\n}\n\n// lunr: strip ANSI escape sequences so footer statuses can be re-colored uniformly.\nfunction stripAnsi(s: string): string {\n\treturn s.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\n// ---------------------------------------------------------------------------\n// Stats formatting\n// ---------------------------------------------------------------------------\n\n/** Compact token-count formatter: `999`, `1.2k`, `15k`, `1.2M`, `15M`.\n * Matches pi's FooterComponent / the captured zentui examples\n * (`↑9.0M ↓112k`, `20%/1.0M`). */\nfunction formatCount(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\n/** Sum input/output tokens across assistant messages in the session. */\nfunction getUsageTotals(ctx: ExtensionContextLike): { input: number; output: number } {\n\tlet input = 0;\n\tlet output = 0;\n\tconst entries = ctx.sessionManager.getEntries?.() ?? ctx.sessionManager.getBranch?.() ?? [];\n\tfor (const entry of entries as readonly SessionEntry[]) {\n\t\tif (entry.type !== \"message\") continue;\n\t\tconst m = entry.message as AssistantMessageLike | undefined;\n\t\tif (!m || m.role !== \"assistant\") continue;\n\t\tconst u = m.usage;\n\t\tif (!u) continue;\n\t\tinput += u.input ?? 0;\n\t\toutput += u.output ?? 0;\n\t}\n\treturn { input, output };\n}\n\n// ---------------------------------------------------------------------------\n// Provider display label\n//\n// `ctx.model.provider` is a ProviderId string (e.g. `\"ollama-cloud\"`), NOT the\n// human label. `BUILT_IN_PROVIDER_DISPLAY_NAMES` exists in pi core but is not\n// re-exported to extensions, so we derive the label (mirrors zentui's\n// `formatProviderLabel`, with an explicit `ollama-cloud` entry).\n// ---------------------------------------------------------------------------\n\nfunction formatProviderLabel(provider: string | undefined): string {\n\tif (!provider) return \"Unknown\";\n\tconst known: Record<string, string> = {\n\t\tanthropic: \"Anthropic\",\n\t\tgemini: \"Google\",\n\t\tgoogle: \"Google\",\n\t\tollama: \"Ollama\",\n\t\t\"ollama-cloud\": \"Ollama Cloud\",\n\t\topenai: \"OpenAI\",\n\t\t\"openai-codex\": \"OpenAI\",\n\t\tmistral: \"Mistral\",\n\t};\n\treturn (\n\t\tknown[provider] ??\n\t\tprovider.replace(/[-_]/g, \" \").replace(/\\b\\w/g, (c) => c.toUpperCase())\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// The chip: `model · provider · effort`\n// ---------------------------------------------------------------------------\n\nfunction colorEffort(theme: Theme | undefined, level: ThinkingLevel, text: string): string {\n\tconst token = thinkingThemeToken(level);\n\tconst painted = color(theme, token, text);\n\tif (token === \"thinkingMax\" && painted === text) {\n\t\treturn color(theme, \"thinkingXhigh\", text);\n\t}\n\treturn painted;\n}\n\nfunction buildChip(ctx: ExtensionContextLike, pi: ExtensionAPI): { left: string; effort: string; level: ThinkingLevel } {\n\tconst modelId = ctx.model?.id ?? \"no-model\";\n\tconst providerLabel = formatProviderLabel(ctx.model?.provider);\n\tconst level = pi.getThinkingLevel();\n\tconst effort = formatChipEffort(level);\n\treturn { left: `${modelId} \\u00b7 ${providerLabel} \\u00b7 `, effort, level };\n}\n\n// ---------------------------------------------------------------------------\n// The prompt box — `ChatboxEditor extends CustomEditor`\n// ---------------------------------------------------------------------------\n\nclass ChatboxEditor extends CustomEditor {\n\tprivate readonly ctx: ExtensionContextLike;\n\tprivate readonly pi: ExtensionAPI;\n\n\tconstructor(\n\t\ttui: TUIHandle,\n\t\ttheme: EditorThemeLike,\n\t\tkeybindings: KeybindingsLike,\n\t\tctx: ExtensionContextLike,\n\t\tpi: ExtensionAPI,\n\t) {\n\t\t// CustomEditor ctor: (tui, theme, keybindings, options?: EditorOptions).\n\t\t// Casts keep the inline types from leaking into the real base signature.\n\t\tsuper(tui as unknown as never, theme as unknown as never, keybindings as unknown as never, {\n\t\t\tpaddingX: 0,\n\t\t});\n\t\tthis.ctx = ctx;\n\t\tthis.pi = pi;\n\t\t// lunr: do not clobber borderColor — InteractiveMode.updateEditorBorderColor()\n\t\t// owns it (thinkingOff…thinkingMax, or bashMode).\n\t}\n\n\tprivate color(token: string, text: string): string {\n\t\treturn color(this.ctx.ui?.theme, token, text);\n\t}\n\n\toverride render(width: number): string[] {\n\t\t// Too narrow to draw a box — defer to the base editor, clamped.\n\t\tif (width <= 4) {\n\t\t\treturn clampLines(super.render(width), width);\n\t\t}\n\n\t\t// Rails: `│ ` (left) + ` │` (right) => 4 columns of chrome.\n\t\tconst promptSymbol = lunrPromptSymbolEnabled();\n\t\tconst glyph = lunrPromptGlyph(this.ctx.ui?.theme);\n\t\tconst glyphW = promptSymbol ? displayWidth(glyph) : 0;\n\t\tconst innerWidth = Math.max(1, width - 4 - glyphW);\n\t\tconst base = super.render(innerWidth);\n\n\t\t// The base editor appends the autocomplete menu lines (if any) to the END\n\t\t// of its render output. Split them off so the body sits inside the box and\n\t\t// the autocomplete renders BELOW the bottom border (preserves slash\n\t\t// commands). Mirrors zentui's `renderPolishedFrame`.\n\t\tconst showing = this.isShowingAutocomplete();\n\t\tconst acList = (this as unknown as { autocompleteList?: AutocompleteListLike }).autocompleteList;\n\t\tlet acCount = 0;\n\t\tif (showing && acList && typeof acList.render === \"function\") {\n\t\t\ttry {\n\t\t\t\tacCount = acList.render(innerWidth).length;\n\t\t\t} catch {\n\t\t\t\tacCount = 0;\n\t\t\t}\n\t\t}\n\n\t\t// `super.render` returns [base top ─ border, ...wrapped text lines, base\n\t\t// bottom ─ border, ...autocomplete lines] — the base editor draws its OWN\n\t\t// straight borders and (when active) appends the autocomplete menu. Split the\n\t\t// autocomplete off the end, then STRIP the base's first/last lines (its own\n\t\t// borders) so we don't render them a second time inside our rounded frame.\n\t\t// Mirrors zentui's `editorFrame.slice(1, -1)` (renderPolishedFrame).\n\t\tlet frame = base;\n\t\tlet acLines: string[] = [];\n\t\tif (acCount > 0 && acCount < frame.length) {\n\t\t\tacLines = frame.slice(frame.length - acCount);\n\t\t\tframe = frame.slice(0, frame.length - acCount);\n\t\t}\n\t\tconst inner = frame.length >= 2 ? frame.slice(1, frame.length - 1) : frame;\n\t\tconst body = inner.length > 0 ? inner : [\"\"];\n\n\t\tconst border = (s: string): string => this.borderColor(s);\n\n\t\t// Top border: ╭─…─╮\n\t\tconst top = border(\"\\u256d\" + \"\\u2500\".repeat(width - 2) + \"\\u256e\");\n\n\t\t// Body: │ <padded line> │ (auto-grows with the number of wrapped lines)\n\t\t// lunr: prefix the first body line with the dim theme prompt glyph (☾ > by\n\t\t// default); a same-width blank gutter keeps subsequent lines aligned.\n\t\tconst gutter = glyphW > 0 ? \" \".repeat(glyphW) : \"\";\n\t\tconst bodyLines = body.map((ln: string, i: number) => {\n\t\t\tconst prefix = i === 0 && glyphW > 0 ? this.color(\"dim\", glyph) : gutter;\n\t\t\treturn border(\"\\u2502 \") + prefix + padRight(ln, innerWidth) + border(\" \\u2502\");\n\t\t});\n\n\t\t// Bottom border with the right-aligned chip: ╰─…─ <chip> ─╯\n\t\tconst bottom = this.renderBottomBorder(width);\n\n\t\treturn [top, ...bodyLines, bottom, ...acLines];\n\t}\n\n\tprivate renderBottomBorder(width: number): string {\n\t\tconst border = (s: string): string => this.borderColor(s);\n\t\tconst parts = buildChip(this.ctx, this.pi);\n\t\tconst plain = parts.left + parts.effort;\n\t\tconst overhead = 4;\n\t\tconst maxChip = Math.max(0, width - overhead);\n\t\tconst truncated = displayWidth(plain) > maxChip;\n\t\tconst chipPlain = truncated ? truncatePlain(plain, maxChip) : plain;\n\t\tconst chipW = displayWidth(chipPlain);\n\t\tconst dashTotal = Math.max(0, width - overhead - chipW);\n\t\t// Right-align the chip: a single trailing dash before the corner, the\n\t\t// rest lead (right-aligns the chip near the corner).\n\t\tconst rightDashes = Math.min(dashTotal, 1);\n\t\tconst leftDashes = dashTotal - rightDashes;\n\n\t\tconst left = \"\\u2570\" + \"\\u2500\".repeat(leftDashes) + \" \";\n\t\tconst right = \" \" + \"\\u2500\".repeat(rightDashes) + \"\\u256f\";\n\t\tconst theme = this.ctx.ui?.theme;\n\t\t// Truncated chips may have lost the effort token — paint all white.\n\t\t// Otherwise model/provider stay white and the effort uses the thinking token.\n\t\tconst chip = truncated\n\t\t\t? this.color(\"white\", chipPlain)\n\t\t\t: this.color(\"white\", parts.left) + colorEffort(theme, parts.level, parts.effort);\n\t\treturn border(left) + chip + border(right);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// The stats line (footer) — slim, single line, BELOW the box\n// ---------------------------------------------------------------------------\n\nfunction renderStatsLine(\n\twidth: number,\n\tctx: ExtensionContextLike,\n\ttheme: Theme,\n\tfooterData: ReadonlyFooterDataProvider,\n): string[] {\n\tconst sep = color(theme, \"accent2\", \" | \"); // lunr: theme-polish — separator uses subtle accent2 blue (was bright-black plain fallback)\n\tconst parts: string[] = [];\n\n\t// lunr: mode zone — permission mode + agent-mode statuses (plan/goal/swarm/research)\n\t// render as ONE segment (dim middot-separated), not scattered across piped sections.\n\tconst modeZone: string[] = [];\n\n\t// lunr: permission mode safety indicator — always shown (not toggle-gated).\n\tconst mode = lunrPermissionMode();\n\tif (mode === \"yolo\" || mode === \"auto\") modeZone.push(color(theme, \"warning\", mode));\n\telse if (mode === \"manual\" || mode === \"plan\") modeZone.push(color(theme, \"white\", mode)); // lunr: theme-polish — manual/plan read white (was dim)\n\n\t// lunr: footer element toggles from the customize bridge (read at render time).\n\tconst footerToggles = lunrFooterToggles();\n\n\t// 1) Extension statuses published by other extensions (rendered as-is,\n\t// already styled): LSP (`pi-lsp-extension`), MCP (`pi-mcp-adapter`),\n\t// throughput/tokens (`pi-tps-was-taken`). These are NOT on `ctx` directly.\n\tconst statuses = footerData.getExtensionStatuses?.();\n\tif (statuses && statuses.size > 0) {\n\t\t// lunr: status segments are toggle-gated via the customize bridge:\n\t\t// footerStatuses gates plan/goal/swarm/research/tps, footerMcp gates\n\t\t// mcp/mcp-auth, footerLsp gates lsp. Publishers keep calling\n\t\t// ctx.ui.setStatus harmlessly when their segment is hidden.\n\t\t// lunr: plan/goal/swarm/research join the mode zone; tps/mcp/lsp stay piped.\n\t\tconst modeKeys: string[] = footerToggles.statuses ? [\"plan\", \"goal\", \"swarm\", \"research\"] : [];\n\t\tfor (const key of modeKeys) {\n\t\t\tconst v = statuses.get(key);\n\t\t\tif (v) modeZone.push(color(theme, \"white\", stripAnsi(v)));\n\t\t}\n\t\tconst pipedKeys: string[] = [];\n\t\tif (footerToggles.statuses) pipedKeys.push(\"tps\");\n\t\tif (footerToggles.mcp) pipedKeys.push(\"mcp\", \"mcp-auth\");\n\t\tif (footerToggles.lsp) pipedKeys.push(\"lsp\");\n\t\tfor (const key of pipedKeys) {\n\t\t\tconst v = statuses.get(key);\n\t\t\t// lunr: unify footer status colors (white, was dim) so the whole stats line reads as one tone.\n\t\t\tif (v) parts.push(color(theme, \"white\", stripAnsi(v))); // lunr: theme-polish — status segments white (was dim)\n\t\t}\n\t}\n\tif (modeZone.length > 0) {\n\t\tparts.unshift(modeZone.join(color(theme, \"dim\", \" · \")));\n\t}\n\n\t// lunr: git branch + working-tree +/- vs HEAD (gated on footerGit).\n\tif (footerToggles.git) {\n\t\tconst branch = footerData.getGitBranch?.();\n\t\tif (branch) {\n\t\t\tconst diff = footerData.getGitDiffstat?.();\n\t\t\tlet gitSeg = color(theme, \"white\", branch);\n\t\t\tif (diff && (diff.added !== 0 || diff.removed !== 0)) {\n\t\t\t\tgitSeg +=\n\t\t\t\t\t` ${color(theme, \"success\", `+${diff.added}`)} ${color(theme, \"error\", `-${diff.removed}`)}`;\n\t\t\t}\n\t\t\tparts.push(gitSeg);\n\t\t}\n\t}\n\n\t// lunr: live subscription window bar (gated on footerPlan). Hidden with no plan.\n\tif (footerToggles.plan) {\n\t\tconst provider = ctx.model?.provider;\n\t\tif (provider) {\n\t\t\tconst usage = lunrUsageBridge();\n\t\t\tusage?.prefetch?.(provider);\n\t\t\tconst seg = usage?.pickForFooter?.(provider);\n\t\t\tif (seg) {\n\t\t\t\tconst pct = `${Math.round(seg.usedPercent)}%`;\n\t\t\t\tconst barColor = seg.usedPercent > 90 ? \"error\" : seg.usedPercent > 70 ? \"warning\" : \"success\";\n\t\t\t\tconst bar = footerToggles.planBar ? `${compactPlanBar(seg.usedPercent, theme)} ` : \"\";\n\t\t\t\tparts.push(color(theme, \"white\", seg.label) + \" \" + bar + color(theme, barColor, pct));\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2) Context usage: `pct/window` (lunr: gated on footerContext).\n\tif (footerToggles.context) {\n\t\tconst usage = ctx.getContextUsage();\n\t\tconst win = ctx.model?.contextWindow ?? usage?.contextWindow ?? 0;\n\t\tconst pct = usage?.percent == null ? \"?\" : `${Math.round(usage.percent)}%`;\n\t\tconst ctxSeg = `${pct}/${formatCount(win)}`;\n\t\tconst pv = usage?.percent ?? 0;\n\t\tif (pv > 90) parts.push(color(theme, \"error\", ctxSeg));\n\t\telse if (pv > 70) parts.push(color(theme, \"warning\", ctxSeg));\n\t\telse parts.push(color(theme, \"white\", ctxSeg)); // lunr: theme-polish — normal context % white (was dim)\n\t}\n\n\t// 3) Token totals: ↑in ↓out (lunr: gated on footerTokens).\n\tif (footerToggles.tokens) {\n\t\tconst totals = getUsageTotals(ctx);\n\t\tparts.push(color(theme, \"white\", `\\u2191${formatCount(totals.input)} \\u2193${formatCount(totals.output)}`)); // lunr: theme-polish — token totals white (was dim)\n\t}\n\n\t// lunr: cost/usage counter segment removed entirely (both the $x.xxx dollar\n\t// counter for API-key providers and the plan-usage limit bar for OAuth/subscription\n\t// providers). Segments 1-3 (statuses, context, tokens) remain.\n\n\tlet line = parts.join(sep);\n\tif (displayWidth(line) > width) {\n\t\tline = truncateToWidth(line, width, \"\");\n\t}\n\treturn [line];\n}\n\n// ---------------------------------------------------------------------------\n// Install / teardown\n// ---------------------------------------------------------------------------\n\nfunction installEditor(\n\tctx: ExtensionContextLike,\n\tpi: ExtensionAPI,\n\tsetRequestor: (r: () => void) => void,\n): void {\n\tif (typeof ctx.ui.setEditorComponent !== \"function\") return;\n\tconst factory: EditorFactoryLike = (tui, _theme, _keybindings) => {\n\t\tsetRequestor(() => {\n\t\t\ttry {\n\t\t\t\ttui.requestRender();\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t});\n\t\treturn new ChatboxEditor(tui, _theme, _keybindings, ctx, pi);\n\t};\n\tctx.ui.setEditorComponent(factory);\n}\n\nfunction installFooter(\n\tctx: ExtensionContextLike,\n\tsetRequestor: (r: () => void) => void,\n): void {\n\tif (typeof ctx.ui.setFooter !== \"function\") return;\n\tlet disposed = false;\n\tconst factory: FooterFactoryLike = (tui, _theme, _footerData) => {\n\t\tsetRequestor(() => {\n\t\t\ttry {\n\t\t\t\ttui.requestRender();\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t});\n\t\treturn {\n\t\t\tinvalidate(): void {\n\t\t\t\t// render is pure\n\t\t\t},\n\t\t\tdispose(): void {\n\t\t\t\tdisposed = true;\n\t\t\t},\n\t\t\trender(width: number): string[] {\n\t\t\t\tif (disposed) return [];\n\t\t\t\treturn renderStatsLine(width, ctx, _theme, _footerData);\n\t\t\t},\n\t\t};\n\t};\n\tctx.ui.setFooter(factory);\n}\n\n// ---------------------------------------------------------------------------\n// Extension entry point\n// ---------------------------------------------------------------------------\n\nexport default function (pi: ExtensionAPI): void {\n\tlet renderRequestor: (() => void) | undefined = undefined;\n\tconst requestRender = (): void => {\n\t\ttry {\n\t\t\trenderRequestor?.();\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t};\n\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\tif (!ctx.hasUI || ctx.mode !== \"tui\") return;\n\t\tinstallEditor(ctx, pi, (r) => {\n\t\t\trenderRequestor = r;\n\t\t});\n\t\tinstallFooter(ctx, (r) => {\n\t\t\tif (!renderRequestor) renderRequestor = r;\n\t\t});\n\t});\n\n\tpi.on(\"session_shutdown\", (_event, ctx) => {\n\t\ttry {\n\t\t\tif (typeof ctx.ui?.setEditorComponent === \"function\") ctx.ui.setEditorComponent(undefined);\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\ttry {\n\t\t\tif (typeof ctx.ui?.setFooter === \"function\") ctx.ui.setFooter(undefined);\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\trenderRequestor = undefined;\n\t});\n\n\t// Re-render triggers: model/provider + effort (chip), and token/cost/context\n\t// (stats line). Event names match those zentui wires.\n\tconst reRenderEvents = [\n\t\t\"model_select\",\n\t\t\"thinking_level_select\",\n\t\t\"agent_end\",\n\t\t\"message_end\",\n\t\t\"tool_execution_end\",\n\t\t\"session_compact\",\n\t];\n\tfor (const ev of reRenderEvents) {\n\t\tpi.on(ev, () => requestRender());\n\t}\n}"]}
1
+ {"version":3,"file":"ashxj-tui.js","sourceRoot":"","sources":["../../src/builtin-extensions/ashxj-tui.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ashxj-tui — a custom slim chatbox for pi.\n *\n * Replaces pi-zentui's prompt box + statusline with:\n * - A rounded prompt box that auto-expands as the typed message wraps to\n * multiple rows (the sides extend; height grows with content).\n * - A right-aligned chip on the box's BOTTOM border:\n * model · provider · effort (e.g. `glm-5.2 · Ollama Cloud · xhigh`)\n * - A slim stats line (extension statuses · context% · ↑↓; each segment\n * toggle-gated via the lunr customize bridge) BELOW the box, not wrapped\n * around the input.\n * - No session-mode indicator anywhere (pi has no such concept).\n *\n * Loaded by pi via jiti — no build step, plain TypeScript.\n *\n * NOTE on type imports (see `ashxj-thinking`/`simple-memory` for the convention):\n * This file declares structural types inline rather than importing them from\n * `@ashx-j/lunr` / `@ashx-j/lunr-tui`.\n * pi-coding-agent's `index.d.ts` re-exports from internal `.d.ts` files that\n * contain subpath imports like `@ashx-j/lunr-ai/compat`, which do not\n * resolve under `tsc` with a file argument. We keep the typecheck\n * self-contained with inline types and verify via the included `tsconfig.json`\n * (`moduleResolution: \"Bundler\"` + `skipLibCheck: true`).\n *\n * The ONE exception is `CustomEditor`, imported as a RUNTIME VALUE directly\n * from its defining module (`modes/interactive/components/custom-editor.ts`).\n * We must `extends` it to inherit pi's app keybindings (escape, ctrl+d, model\n * switching, extension shortcuts) — wrapping would lose those. It is imported\n * from the concrete module, NOT the package barrel, because the barrel\n * re-exports main.ts which imports this file — a circular import that crashes\n * under vite-node (`Class extends value undefined`).\n */\n\nimport { CustomEditor } from \"../modes/interactive/components/custom-editor.js\";\n\n// lunr: customize bridge — read the prompt-symbol toggle (bridgeless → no symbol).\nconst PROMPT_SYMBOL_BRIDGE = Symbol.for(\"@lunr/customize\");\nconst PERMISSION_MODE_BRIDGE = Symbol.for(\"@lunr/permission-mode\");\ninterface CustomizeBridgeForPrompt {\n\tgetPromptSymbol(): boolean;\n\t// lunr: footer element toggles (added to the same bridge).\n\tgetFooterMcp?(): boolean;\n\tgetFooterLsp?(): boolean;\n\tgetFooterContext?(): boolean;\n\tgetFooterTokens?(): boolean;\n\tgetFooterTps?(): boolean;\n\tgetFooterStatuses?(): boolean;\n\tgetFooterGit?(): boolean;\n\tgetFooterPlan?(): boolean;\n\tgetFooterPlanBar?(): boolean;\n}\ninterface PermissionModeBridgeForFooter {\n\tgetMode(): string | undefined;\n}\nfunction lunrCustomizeBridge(): CustomizeBridgeForPrompt | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[PROMPT_SYMBOL_BRIDGE] as CustomizeBridgeForPrompt | undefined;\n}\nfunction lunrPermissionModeBridge(): PermissionModeBridgeForFooter | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[PERMISSION_MODE_BRIDGE] as PermissionModeBridgeForFooter | undefined;\n}\nfunction lunrPromptSymbolEnabled(): boolean {\n\treturn lunrCustomizeBridge()?.getPromptSymbol() ?? false;\n}\n// lunr: footer toggles, read at render time. Bridgeless / missing-getter fallback\n// matches the settings-manager defaults: MCP on, LSP off, everything else on.\nfunction lunrFooterToggles(): {\n\tmcp: boolean;\n\tlsp: boolean;\n\tcontext: boolean;\n\ttokens: boolean;\n\ttps: boolean;\n\tstatuses: boolean;\n\tgit: boolean;\n\tplan: boolean;\n\tplanBar: boolean;\n} {\n\tconst bridge = lunrCustomizeBridge();\n\treturn {\n\t\tmcp: bridge?.getFooterMcp?.() ?? true,\n\t\tlsp: bridge?.getFooterLsp?.() ?? false,\n\t\tcontext: bridge?.getFooterContext?.() ?? true,\n\t\ttokens: bridge?.getFooterTokens?.() ?? true,\n\t\ttps: bridge?.getFooterTps?.() ?? true,\n\t\tstatuses: bridge?.getFooterStatuses?.() ?? true,\n\t\tgit: bridge?.getFooterGit?.() ?? true,\n\t\tplan: bridge?.getFooterPlan?.() ?? true,\n\t\tplanBar: bridge?.getFooterPlanBar?.() ?? true,\n\t};\n}\n\nconst USAGE_SERVICE_BRIDGE = Symbol.for(\"@lunr/usage-service\");\ninterface UsageServiceBridgeForFooter {\n\tpickForFooter?(providerId: string): { label: string; usedPercent: number } | undefined;\n\tprefetch?(providerId: string): void;\n}\nfunction lunrUsageBridge(): UsageServiceBridgeForFooter | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[USAGE_SERVICE_BRIDGE] as UsageServiceBridgeForFooter | undefined;\n}\n\nfunction compactPlanBar(percent: number, theme: Theme): string {\n\tconst cells = 8;\n\tconst clamped = Math.max(0, Math.min(100, percent));\n\tconst filled = Math.round((clamped / 100) * cells);\n\tconst token = clamped > 90 ? \"error\" : clamped > 70 ? \"warning\" : \"success\";\n\tconst fill = filled > 0 ? color(theme, token, \"█\".repeat(filled)) : \"\";\n\tconst rest = filled < cells ? color(theme, \"dim\", \"░\".repeat(cells - filled)) : \"\";\n\treturn fill + rest;\n}\n// lunr: permission mode for the footer safety indicator (always shown).\nfunction lunrPermissionMode(): string | undefined {\n\treturn lunrPermissionModeBridge()?.getMode();\n}\n// lunr: prompt glyph comes from the theme tokens `glyphs.promptMoon` /\n// `glyphs.promptArrow` (defaults below match moon.json). An empty token hides\n// that part; both empty = no glyph at all.\nfunction lunrPromptGlyph(theme: Theme | undefined): string {\n\tconst moon = theme?.glyph?.(\"promptMoon\") ?? \"☾\";\n\tconst arrow = theme?.glyph?.(\"promptArrow\") ?? \">\";\n\tconst parts = [moon, arrow].filter((s) => s !== \"\");\n\treturn parts.length > 0 ? `${parts.join(\" \")} ` : \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Minimal structural types (inline — see file header)\n// ---------------------------------------------------------------------------\n\ntype ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\n/** Theme token for the chatbox thinking-level border / effort chip. */\nexport function thinkingThemeToken(level: ThinkingLevel): string {\n\tswitch (level) {\n\t\tcase \"off\":\n\t\t\treturn \"thinkingOff\";\n\t\tcase \"minimal\":\n\t\t\treturn \"thinkingMinimal\";\n\t\tcase \"low\":\n\t\t\treturn \"thinkingLow\";\n\t\tcase \"medium\":\n\t\t\treturn \"thinkingMedium\";\n\t\tcase \"high\":\n\t\t\treturn \"thinkingHigh\";\n\t\tcase \"xhigh\":\n\t\t\treturn \"thinkingXhigh\";\n\t\tcase \"max\":\n\t\t\treturn \"thinkingMax\";\n\t\tdefault:\n\t\t\treturn \"thinkingOff\";\n\t}\n}\n\n/** Chip effort label — identity, locked so xhigh/max are never mapped down to high. */\nexport function formatChipEffort(level: ThinkingLevel): string {\n\treturn level;\n}\n\n/** Trimmed view of pi's `Theme` — only the methods we use. */\ninterface Theme {\n\tfg(token: string, text: string): string;\n\t/** lunr: prompt glyph tokens (optional for forward/backward compat). */\n\tglyph?(name: \"promptMoon\" | \"promptArrow\"): string;\n}\n\n/** Trimmed view of `pi-tui`'s `TUI` — only the method we use. */\ninterface TUIHandle {\n\trequestRender(force?: boolean): void;\n}\n\n/** Trimmed view of `pi-tui`'s `EditorTheme`. */\ninterface EditorThemeLike {\n\tborderColor: (str: string) => string;\n\tselectList: unknown;\n}\n\n/** Opaque keybindings manager. */\ninterface KeybindingsLike {\n\treadonly _?: unknown;\n}\n\n/** Trimmed view of an autocomplete list (the editor's private `autocompleteList`). */\ninterface AutocompleteListLike {\n\trender(width: number): string[];\n}\n\n/** Trimmed view of pi's `ReadonlyFooterDataProvider`. */\ninterface ReadonlyFooterDataProvider {\n\tgetGitBranch(): string | null;\n\tgetGitDiffstat?(): { added: number; removed: number } | null;\n\tgetExtensionStatuses(): ReadonlyMap<string, string>;\n\tgetAvailableProviderCount(): number;\n\tonBranchChange(callback: () => void): () => void;\n}\n\n/** Trimmed view of the `getContextUsage` return value. */\ninterface ContextUsage {\n\ttokens: number | null;\n\tcontextWindow: number;\n\tpercent: number | null;\n}\n\n/** Trimmed view of an assistant message's usage — the bits we render. */\ninterface AssistantUsage {\n\tinput: number;\n\toutput: number;\n\tcost: { total: number };\n}\n\n/** Trimmed view of an assistant message. */\ninterface AssistantMessageLike {\n\trole: \"assistant\";\n\tusage: AssistantUsage;\n}\n\n/** Trimmed view of a session entry — only what we iterate over. */\ntype SessionEntry =\n\t| { type: \"message\"; message: AssistantMessageLike }\n\t| { type: string; message?: unknown };\n\n/** Trimmed view of a `ReadonlySessionManager`. */\ninterface ReadonlySessionManagerLike {\n\tgetEntries(): readonly SessionEntry[];\n\tgetBranch?(): readonly SessionEntry[];\n}\n\n/** Trimmed view of a `Model`. */\ninterface ModelLike {\n\tid?: string;\n\tprovider?: string;\n\tcontextWindow?: number;\n\treasoning?: boolean;\n\tthinkingLevelMap?: Record<string, string | null>;\n}\n\ninterface ExtensionUIContextLike {\n\tsetEditorComponent(factory: EditorFactoryLike | undefined): void;\n\tsetFooter(factory: FooterFactoryLike | undefined): void;\n\treadonly theme?: Theme;\n}\n\n/** Trimmed view of `ExtensionContext`. */\ninterface ExtensionContextLike {\n\tmode: \"tui\" | \"rpc\" | \"json\" | \"print\";\n\thasUI: boolean;\n\tmodel: ModelLike | undefined;\n\tsessionManager: ReadonlySessionManagerLike;\n\tgetContextUsage(): ContextUsage | undefined;\n\tui: ExtensionUIContextLike;\n}\n\n/** Trimmed view of `ExtensionAPI`. */\ninterface ExtensionAPI {\n\tgetThinkingLevel(): ThinkingLevel;\n\ton(event: string, handler: (event: unknown, ctx: ExtensionContextLike) => void): void;\n}\n\n/** `setEditorComponent` factory shape. */\ntype EditorFactoryLike = (\n\ttui: TUIHandle,\n\ttheme: EditorThemeLike,\n\tkeybindings: KeybindingsLike,\n) => EditorComponentLike;\n\ninterface EditorComponentLike {\n\trender(width: number): string[];\n\tgetText(): string;\n\tsetText(text: string): void;\n\tinvalidate(): void;\n\thandleInput?(data: string): void;\n}\n\n/** `setFooter` factory shape. */\ntype FooterFactoryLike = (\n\ttui: TUIHandle,\n\ttheme: Theme,\n\tfooterData: ReadonlyFooterDataProvider,\n) => FooterComponentLike;\n\ninterface FooterComponentLike {\n\trender(width: number): string[];\n\tdispose?(): void;\n\tinvalidate?(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Display-width helpers (ANSI-aware; CJK-aware)\n//\n// The editor (`Editor.render`) word-wraps to the given width using grapheme\n// width, so each returned line is ≤ that many visual columns. To right-pad a\n// line for our box we need a width model that matches closely enough: skip ALL\n// escape sequences (SGR color, OSC/DCS/APC/PM/SOS string sequences such as\n// pi-tui's `CURSOR_MARKER` `ESC _pi:c BEL`, and two-char escapes), count common\n// East-Asian wide ranges as 2, combining marks and variation selectors as 0.\n// Handling the string sequences as 0-width is what keeps the right `│` rail\n// aligned on the focused (cursor) line — the base editor embeds the marker and\n// the TUI strips it at flush time, so we must not count it here.\n// ---------------------------------------------------------------------------\n\nfunction skipAnsi(str: string, pos: number): number {\n\tif (str.charCodeAt(pos) !== 0x1b) return 0;\n\tconst next = str.charCodeAt(pos + 1);\n\t// CSI: ESC [ ... <final 0x40-0x7e>\n\tif (next === 0x5b /* [ */) {\n\t\tlet j = pos + 2;\n\t\twhile (j < str.length) {\n\t\t\tconst c = str.charCodeAt(j);\n\t\t\tif (c >= 0x40 && c <= 0x7e) return j + 1 - pos;\n\t\t\tj++;\n\t\t}\n\t\treturn str.length - pos; // unterminated; consume the rest\n\t}\n\t// String sequences — OSC (]), DCS (P), APC (_), PM (^), SOS (X) — terminated\n\t// by BEL (0x07) or ST (ESC \\). pi-tui's CURSOR_MARKER `ESC _pi:c BEL` is APC;\n\t// OSC color queries are OSC. All are zero visual width.\n\tif (\n\t\tnext === 0x5d /* ] */ ||\n\t\tnext === 0x50 /* P */ ||\n\t\tnext === 0x5f /* _ */ ||\n\t\tnext === 0x5e /* ^ */ ||\n\t\tnext === 0x58 /* X */\n\t) {\n\t\tlet j = pos + 2;\n\t\twhile (j < str.length) {\n\t\t\tconst c = str.charCodeAt(j);\n\t\t\tif (c === 0x07 /* BEL */) return j + 1 - pos;\n\t\t\tif (c === 0x1b && str.charCodeAt(j + 1) === 0x5c /* \\ */) return j + 2 - pos;\n\t\t\tj++;\n\t\t}\n\t\treturn str.length - pos; // unterminated; consume the rest\n\t}\n\t// Any other ESC sequence: consume ESC + one final byte (e.g. ESC c, ESC \\,\n\t// ESC ( B). A lone trailing ESC with no following byte is 0 width too.\n\treturn Number.isNaN(next) ? 1 : 2;\n}\n\nfunction isWide(cp: number): boolean {\n\treturn (\n\t\t(cp >= 0x1100 && cp <= 0x115f) ||\n\t\t(cp >= 0x2e80 && cp <= 0x303e) ||\n\t\t(cp >= 0x3041 && cp <= 0x33ff) ||\n\t\t(cp >= 0x3400 && cp <= 0x4dbf) ||\n\t\t(cp >= 0x4e00 && cp <= 0x9fff) ||\n\t\t(cp >= 0xa000 && cp <= 0xa4cf) ||\n\t\t(cp >= 0xac00 && cp <= 0xd7a3) ||\n\t\t(cp >= 0xf900 && cp <= 0xfaff) ||\n\t\t(cp >= 0xfe30 && cp <= 0xfe4f) ||\n\t\t(cp >= 0xff00 && cp <= 0xff60) ||\n\t\t(cp >= 0xffe0 && cp <= 0xffe6) ||\n\t\t(cp >= 0x1f300 && cp <= 0x1faff) ||\n\t\t(cp >= 0x20000 && cp <= 0x3fffd)\n\t);\n}\n\nfunction charWidth(cp: number): number {\n\tif (cp >= 0x20 && cp < 0x7f) return 1;\n\tif ((cp >= 0x0300 && cp <= 0x036f) || (cp >= 0xfe00 && cp <= 0xfe0f) || cp === 0x200d) return 0;\n\treturn isWide(cp) ? 2 : 1;\n}\n\n/** Visible width of a string, ignoring SGR color codes. */\nfunction displayWidth(str: string): number {\n\tlet w = 0;\n\tlet i = 0;\n\twhile (i < str.length) {\n\t\tconst skip = skipAnsi(str, i);\n\t\tif (skip > 0) {\n\t\t\ti += skip;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cp = str.codePointAt(i) ?? 0;\n\t\tw += charWidth(cp);\n\t\ti += cp > 0xffff ? 2 : 1;\n\t}\n\treturn w;\n}\n\n/** Right-pad a (possibly colored) line to `width` visible columns. */\nfunction padRight(line: string, width: number): string {\n\tconst w = displayWidth(line);\n\tif (w >= width) return line;\n\treturn line + \" \".repeat(width - w);\n}\n\n/** Truncate a plain (non-ANSI) string to `maxWidth` visible columns. */\nfunction truncatePlain(text: string, maxWidth: number): string {\n\tif (maxWidth <= 0) return \"\";\n\tif (displayWidth(text) <= maxWidth) return text;\n\tlet out = \"\";\n\tlet w = 0;\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst code = text.codePointAt(i) ?? 0;\n\t\tconst cw = charWidth(code);\n\t\tif (w + cw > maxWidth) break;\n\t\tout += String.fromCodePoint(code);\n\t\tw += cw;\n\t\ti += code > 0xffff ? 2 : 1;\n\t}\n\treturn out;\n}\n\n/** Truncate a (possibly ANSI-colored) string to `maxWidth` visible columns,\n * re-emitting an SGR reset at the cut so styling doesn't bleed. */\nfunction truncateToWidth(text: string, maxWidth: number, ellipsis = \"\"): string {\n\tif (maxWidth <= 0) return \"\";\n\tif (displayWidth(text) <= maxWidth) return text;\n\tconst target = Math.max(0, maxWidth - displayWidth(ellipsis));\n\tlet out = \"\";\n\tlet w = 0;\n\tlet i = 0;\n\twhile (i < text.length && w < target) {\n\t\tconst skip = skipAnsi(text, i);\n\t\tif (skip > 0) {\n\t\t\tout += text.slice(i, i + skip);\n\t\t\ti += skip;\n\t\t\tcontinue;\n\t\t}\n\t\tconst code = text.codePointAt(i) ?? 0;\n\t\tconst cw = charWidth(code);\n\t\tif (w + cw > target) break;\n\t\tout += String.fromCodePoint(code);\n\t\tw += cw;\n\t\ti += code > 0xffff ? 2 : 1;\n\t}\n\tout += \"\\x1b[0m\";\n\treturn out + ellipsis;\n}\n\n/** Clamp each rendered line to `width` visible columns (fallback path). */\nfunction clampLines(lines: string[], width: number): string[] {\n\treturn lines.map((l) => (displayWidth(l) > width ? truncateToWidth(l, width, \"\") : l));\n}\n\n/** Apply a theme `fg` token safely; falls back to plain text. */\nfunction color(theme: Theme | undefined, token: string, text: string): string {\n\ttry {\n\t\treturn theme?.fg?.(token, text) ?? text;\n\t} catch {\n\t\treturn text;\n\t}\n}\n\n// lunr: strip ANSI escape sequences so footer statuses can be re-colored uniformly.\nfunction stripAnsi(s: string): string {\n\treturn s.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\n// ---------------------------------------------------------------------------\n// Stats formatting\n// ---------------------------------------------------------------------------\n\n/** Compact token-count formatter: `999`, `1.2k`, `15k`, `1.2M`, `15M`.\n * Matches pi's FooterComponent / the captured zentui examples\n * (`↑9.0M ↓112k`, `20%/1.0M`). */\nfunction formatCount(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\n/** Sum input/output tokens across assistant messages in the session. */\nfunction getUsageTotals(ctx: ExtensionContextLike): { input: number; output: number } {\n\tlet input = 0;\n\tlet output = 0;\n\tconst entries = ctx.sessionManager.getEntries?.() ?? ctx.sessionManager.getBranch?.() ?? [];\n\tfor (const entry of entries as readonly SessionEntry[]) {\n\t\tif (entry.type !== \"message\") continue;\n\t\tconst m = entry.message as AssistantMessageLike | undefined;\n\t\tif (!m || m.role !== \"assistant\") continue;\n\t\tconst u = m.usage;\n\t\tif (!u) continue;\n\t\tinput += u.input ?? 0;\n\t\toutput += u.output ?? 0;\n\t}\n\treturn { input, output };\n}\n\n// ---------------------------------------------------------------------------\n// Provider display label\n//\n// `ctx.model.provider` is a ProviderId string (e.g. `\"ollama-cloud\"`), NOT the\n// human label. `BUILT_IN_PROVIDER_DISPLAY_NAMES` exists in pi core but is not\n// re-exported to extensions, so we derive the label (mirrors zentui's\n// `formatProviderLabel`, with an explicit `ollama-cloud` entry).\n// ---------------------------------------------------------------------------\n\nfunction formatProviderLabel(provider: string | undefined): string {\n\tif (!provider) return \"Unknown\";\n\tconst known: Record<string, string> = {\n\t\tanthropic: \"Anthropic\",\n\t\tgemini: \"Google\",\n\t\tgoogle: \"Google\",\n\t\tollama: \"Ollama\",\n\t\t\"ollama-cloud\": \"Ollama Cloud\",\n\t\topenai: \"OpenAI\",\n\t\t\"openai-codex\": \"OpenAI\",\n\t\tmistral: \"Mistral\",\n\t};\n\treturn (\n\t\tknown[provider] ??\n\t\tprovider.replace(/[-_]/g, \" \").replace(/\\b\\w/g, (c) => c.toUpperCase())\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// The chip: `model · provider · effort`\n// ---------------------------------------------------------------------------\n\nfunction colorEffort(theme: Theme | undefined, level: ThinkingLevel, text: string): string {\n\tconst token = thinkingThemeToken(level);\n\tconst painted = color(theme, token, text);\n\tif (token === \"thinkingMax\" && painted === text) {\n\t\treturn color(theme, \"thinkingXhigh\", text);\n\t}\n\treturn painted;\n}\n\nfunction buildChip(ctx: ExtensionContextLike, pi: ExtensionAPI): { left: string; effort: string; level: ThinkingLevel } {\n\tconst modelId = ctx.model?.id ?? \"no-model\";\n\tconst providerLabel = formatProviderLabel(ctx.model?.provider);\n\tconst level = pi.getThinkingLevel();\n\tconst effort = formatChipEffort(level);\n\treturn { left: `${modelId} \\u00b7 ${providerLabel} \\u00b7 `, effort, level };\n}\n\n// ---------------------------------------------------------------------------\n// The prompt box — `ChatboxEditor extends CustomEditor`\n// ---------------------------------------------------------------------------\n\nclass ChatboxEditor extends CustomEditor {\n\tprivate readonly ctx: ExtensionContextLike;\n\tprivate readonly pi: ExtensionAPI;\n\n\tconstructor(\n\t\ttui: TUIHandle,\n\t\ttheme: EditorThemeLike,\n\t\tkeybindings: KeybindingsLike,\n\t\tctx: ExtensionContextLike,\n\t\tpi: ExtensionAPI,\n\t) {\n\t\t// CustomEditor ctor: (tui, theme, keybindings, options?: EditorOptions).\n\t\t// Casts keep the inline types from leaking into the real base signature.\n\t\tsuper(tui as unknown as never, theme as unknown as never, keybindings as unknown as never, {\n\t\t\tpaddingX: 0,\n\t\t});\n\t\tthis.ctx = ctx;\n\t\tthis.pi = pi;\n\t\t// lunr: do not clobber borderColor — InteractiveMode.updateEditorBorderColor()\n\t\t// owns it (thinkingOff…thinkingMax, or bashMode).\n\t}\n\n\tprivate color(token: string, text: string): string {\n\t\treturn color(this.ctx.ui?.theme, token, text);\n\t}\n\n\toverride render(width: number): string[] {\n\t\t// Too narrow to draw a box — defer to the base editor, clamped.\n\t\tif (width <= 4) {\n\t\t\treturn clampLines(super.render(width), width);\n\t\t}\n\n\t\t// Rails: `│ ` (left) + ` │` (right) => 4 columns of chrome.\n\t\tconst promptSymbol = lunrPromptSymbolEnabled();\n\t\tconst glyph = lunrPromptGlyph(this.ctx.ui?.theme);\n\t\tconst glyphW = promptSymbol ? displayWidth(glyph) : 0;\n\t\tconst innerWidth = Math.max(1, width - 4 - glyphW);\n\t\tconst base = super.render(innerWidth);\n\n\t\t// The base editor appends the autocomplete menu lines (if any) to the END\n\t\t// of its render output. Split them off so the body sits inside the box and\n\t\t// the autocomplete renders BELOW the bottom border (preserves slash\n\t\t// commands). Mirrors zentui's `renderPolishedFrame`.\n\t\tconst showing = this.isShowingAutocomplete();\n\t\tconst acList = (this as unknown as { autocompleteList?: AutocompleteListLike }).autocompleteList;\n\t\tlet acCount = 0;\n\t\tif (showing && acList && typeof acList.render === \"function\") {\n\t\t\ttry {\n\t\t\t\tacCount = acList.render(innerWidth).length;\n\t\t\t} catch {\n\t\t\t\tacCount = 0;\n\t\t\t}\n\t\t}\n\n\t\t// `super.render` returns [base top ─ border, ...wrapped text lines, base\n\t\t// bottom ─ border, ...autocomplete lines] — the base editor draws its OWN\n\t\t// straight borders and (when active) appends the autocomplete menu. Split the\n\t\t// autocomplete off the end, then STRIP the base's first/last lines (its own\n\t\t// borders) so we don't render them a second time inside our rounded frame.\n\t\t// Mirrors zentui's `editorFrame.slice(1, -1)` (renderPolishedFrame).\n\t\tlet frame = base;\n\t\tlet acLines: string[] = [];\n\t\tif (acCount > 0 && acCount < frame.length) {\n\t\t\tacLines = frame.slice(frame.length - acCount);\n\t\t\tframe = frame.slice(0, frame.length - acCount);\n\t\t}\n\t\tconst inner = frame.length >= 2 ? frame.slice(1, frame.length - 1) : frame;\n\t\tconst body = inner.length > 0 ? inner : [\"\"];\n\n\t\tconst border = (s: string): string => this.borderColor(s);\n\n\t\t// Top border: ╭─…─╮\n\t\tconst top = border(\"\\u256d\" + \"\\u2500\".repeat(width - 2) + \"\\u256e\");\n\n\t\t// Body: │ <padded line> │ (auto-grows with the number of wrapped lines)\n\t\t// lunr: prefix the first body line with the dim theme prompt glyph (☾ > by\n\t\t// default); a same-width blank gutter keeps subsequent lines aligned.\n\t\tconst gutter = glyphW > 0 ? \" \".repeat(glyphW) : \"\";\n\t\tconst bodyLines = body.map((ln: string, i: number) => {\n\t\t\tconst prefix = i === 0 && glyphW > 0 ? this.color(\"dim\", glyph) : gutter;\n\t\t\treturn border(\"\\u2502 \") + prefix + padRight(ln, innerWidth) + border(\" \\u2502\");\n\t\t});\n\n\t\t// Bottom border with the right-aligned chip: ╰─…─ <chip> ─╯\n\t\tconst bottom = this.renderBottomBorder(width);\n\n\t\treturn [top, ...bodyLines, bottom, ...acLines];\n\t}\n\n\tprivate renderBottomBorder(width: number): string {\n\t\tconst border = (s: string): string => this.borderColor(s);\n\t\tconst parts = buildChip(this.ctx, this.pi);\n\t\tconst plain = parts.left + parts.effort;\n\t\tconst overhead = 4;\n\t\tconst maxChip = Math.max(0, width - overhead);\n\t\tconst truncated = displayWidth(plain) > maxChip;\n\t\tconst chipPlain = truncated ? truncatePlain(plain, maxChip) : plain;\n\t\tconst chipW = displayWidth(chipPlain);\n\t\tconst dashTotal = Math.max(0, width - overhead - chipW);\n\t\t// Right-align the chip: a single trailing dash before the corner, the\n\t\t// rest lead (right-aligns the chip near the corner).\n\t\tconst rightDashes = Math.min(dashTotal, 1);\n\t\tconst leftDashes = dashTotal - rightDashes;\n\n\t\tconst left = \"\\u2570\" + \"\\u2500\".repeat(leftDashes) + \" \";\n\t\tconst right = \" \" + \"\\u2500\".repeat(rightDashes) + \"\\u256f\";\n\t\tconst theme = this.ctx.ui?.theme;\n\t\t// Truncated chips may have lost the effort token — paint all white.\n\t\t// Otherwise model/provider stay white and the effort uses the thinking token.\n\t\tconst chip = truncated\n\t\t\t? this.color(\"white\", chipPlain)\n\t\t\t: this.color(\"white\", parts.left) + colorEffort(theme, parts.level, parts.effort);\n\t\treturn border(left) + chip + border(right);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// The stats line (footer) — slim, single line, BELOW the box\n// ---------------------------------------------------------------------------\n\nfunction renderStatsLine(\n\twidth: number,\n\tctx: ExtensionContextLike,\n\ttheme: Theme,\n\tfooterData: ReadonlyFooterDataProvider,\n): string[] {\n\tconst sep = color(theme, \"accent2\", \" | \"); // lunr: theme-polish — separator uses subtle accent2 blue (was bright-black plain fallback)\n\tconst parts: string[] = [];\n\n\t// lunr: mode zone — permission mode + agent-mode statuses (plan/goal/swarm/research)\n\t// render as ONE segment (dim middot-separated), not scattered across piped sections.\n\tconst modeZone: string[] = [];\n\n\t// lunr: permission mode safety indicator — always shown (not toggle-gated).\n\tconst mode = lunrPermissionMode();\n\tif (mode === \"yolo\" || mode === \"auto\") modeZone.push(color(theme, \"warning\", mode));\n\telse if (mode === \"manual\" || mode === \"plan\") modeZone.push(color(theme, \"white\", mode)); // lunr: theme-polish — manual/plan read white (was dim)\n\n\t// lunr: footer element toggles from the customize bridge (read at render time).\n\tconst footerToggles = lunrFooterToggles();\n\n\t// 1) Extension statuses published by other extensions (rendered as-is,\n\t// already styled): LSP (`pi-lsp-extension`), MCP (`pi-mcp-adapter`),\n\t// throughput/tokens (`pi-tps-was-taken`). These are NOT on `ctx` directly.\n\tconst statuses = footerData.getExtensionStatuses?.();\n\tif (statuses && statuses.size > 0) {\n\t\t// lunr: status segments are toggle-gated via the customize bridge:\n\t\t// footerStatuses gates plan/goal/swarm/research, footerTps gates tps,\n\t\t// footerMcp gates mcp/mcp-auth, footerLsp gates lsp. Publishers keep\n\t\t// calling ctx.ui.setStatus harmlessly when their segment is hidden.\n\t\t// lunr: plan/goal/swarm/research join the mode zone; tps/mcp/lsp stay piped.\n\t\tconst modeKeys: string[] = footerToggles.statuses ? [\"plan\", \"goal\", \"swarm\", \"research\"] : [];\n\t\tfor (const key of modeKeys) {\n\t\t\tconst v = statuses.get(key);\n\t\t\tif (v) modeZone.push(color(theme, \"white\", stripAnsi(v)));\n\t\t}\n\t\tconst pipedKeys: string[] = [];\n\t\tif (footerToggles.tps) pipedKeys.push(\"tps\");\n\t\tif (footerToggles.mcp) pipedKeys.push(\"mcp\", \"mcp-auth\");\n\t\tif (footerToggles.lsp) pipedKeys.push(\"lsp\");\n\t\tfor (const key of pipedKeys) {\n\t\t\tconst v = statuses.get(key);\n\t\t\t// lunr: unify footer status colors (white, was dim) so the whole stats line reads as one tone.\n\t\t\tif (v) parts.push(color(theme, \"white\", stripAnsi(v))); // lunr: theme-polish — status segments white (was dim)\n\t\t}\n\t}\n\tif (modeZone.length > 0) {\n\t\tparts.unshift(modeZone.join(color(theme, \"dim\", \" · \")));\n\t}\n\n\t// lunr: git branch + working-tree +/- vs HEAD (gated on footerGit).\n\tif (footerToggles.git) {\n\t\tconst branch = footerData.getGitBranch?.();\n\t\tif (branch) {\n\t\t\tconst diff = footerData.getGitDiffstat?.();\n\t\t\tlet gitSeg = color(theme, \"white\", branch);\n\t\t\tif (diff && (diff.added !== 0 || diff.removed !== 0)) {\n\t\t\t\tgitSeg +=\n\t\t\t\t\t` ${color(theme, \"success\", `+${diff.added}`)} ${color(theme, \"error\", `-${diff.removed}`)}`;\n\t\t\t}\n\t\t\tparts.push(gitSeg);\n\t\t}\n\t}\n\n\t// lunr: live subscription window bar (gated on footerPlan). Hidden with no plan.\n\tif (footerToggles.plan) {\n\t\tconst provider = ctx.model?.provider;\n\t\tif (provider) {\n\t\t\tconst usage = lunrUsageBridge();\n\t\t\tusage?.prefetch?.(provider);\n\t\t\tconst seg = usage?.pickForFooter?.(provider);\n\t\t\tif (seg) {\n\t\t\t\tconst pct = `${Math.round(seg.usedPercent)}%`;\n\t\t\t\tconst barColor = seg.usedPercent > 90 ? \"error\" : seg.usedPercent > 70 ? \"warning\" : \"success\";\n\t\t\t\tconst bar = footerToggles.planBar ? `${compactPlanBar(seg.usedPercent, theme)} ` : \"\";\n\t\t\t\tparts.push(color(theme, \"white\", seg.label) + \" \" + bar + color(theme, barColor, pct));\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2) Context usage: `pct/window` (lunr: gated on footerContext).\n\tif (footerToggles.context) {\n\t\tconst usage = ctx.getContextUsage();\n\t\tconst win = ctx.model?.contextWindow ?? usage?.contextWindow ?? 0;\n\t\tconst pct = usage?.percent == null ? \"?\" : `${Math.round(usage.percent)}%`;\n\t\tconst ctxSeg = `${pct}/${formatCount(win)}`;\n\t\tconst pv = usage?.percent ?? 0;\n\t\tif (pv > 90) parts.push(color(theme, \"error\", ctxSeg));\n\t\telse if (pv > 70) parts.push(color(theme, \"warning\", ctxSeg));\n\t\telse parts.push(color(theme, \"white\", ctxSeg)); // lunr: theme-polish — normal context % white (was dim)\n\t}\n\n\t// 3) Token totals: ↑in ↓out (lunr: gated on footerTokens).\n\tif (footerToggles.tokens) {\n\t\tconst totals = getUsageTotals(ctx);\n\t\tparts.push(color(theme, \"white\", `\\u2191${formatCount(totals.input)} \\u2193${formatCount(totals.output)}`)); // lunr: theme-polish — token totals white (was dim)\n\t}\n\n\t// lunr: cost/usage counter segment removed entirely (both the $x.xxx dollar\n\t// counter for API-key providers and the plan-usage limit bar for OAuth/subscription\n\t// providers). Segments 1-3 (statuses, context, tokens) remain.\n\n\tlet line = parts.join(sep);\n\tif (displayWidth(line) > width) {\n\t\tline = truncateToWidth(line, width, \"\");\n\t}\n\treturn [line];\n}\n\n// ---------------------------------------------------------------------------\n// Install / teardown\n// ---------------------------------------------------------------------------\n\nfunction installEditor(\n\tctx: ExtensionContextLike,\n\tpi: ExtensionAPI,\n\tsetRequestor: (r: () => void) => void,\n): void {\n\tif (typeof ctx.ui.setEditorComponent !== \"function\") return;\n\tconst factory: EditorFactoryLike = (tui, _theme, _keybindings) => {\n\t\tsetRequestor(() => {\n\t\t\ttry {\n\t\t\t\ttui.requestRender();\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t});\n\t\treturn new ChatboxEditor(tui, _theme, _keybindings, ctx, pi);\n\t};\n\tctx.ui.setEditorComponent(factory);\n}\n\nfunction installFooter(\n\tctx: ExtensionContextLike,\n\tsetRequestor: (r: () => void) => void,\n): void {\n\tif (typeof ctx.ui.setFooter !== \"function\") return;\n\tlet disposed = false;\n\tconst factory: FooterFactoryLike = (tui, _theme, _footerData) => {\n\t\tsetRequestor(() => {\n\t\t\ttry {\n\t\t\t\ttui.requestRender();\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t});\n\t\treturn {\n\t\t\tinvalidate(): void {\n\t\t\t\t// render is pure\n\t\t\t},\n\t\t\tdispose(): void {\n\t\t\t\tdisposed = true;\n\t\t\t},\n\t\t\trender(width: number): string[] {\n\t\t\t\tif (disposed) return [];\n\t\t\t\treturn renderStatsLine(width, ctx, _theme, _footerData);\n\t\t\t},\n\t\t};\n\t};\n\tctx.ui.setFooter(factory);\n}\n\n// ---------------------------------------------------------------------------\n// Extension entry point\n// ---------------------------------------------------------------------------\n\nexport default function (pi: ExtensionAPI): void {\n\tlet renderRequestor: (() => void) | undefined = undefined;\n\tconst requestRender = (): void => {\n\t\ttry {\n\t\t\trenderRequestor?.();\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t};\n\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\tif (!ctx.hasUI || ctx.mode !== \"tui\") return;\n\t\tinstallEditor(ctx, pi, (r) => {\n\t\t\trenderRequestor = r;\n\t\t});\n\t\tinstallFooter(ctx, (r) => {\n\t\t\tif (!renderRequestor) renderRequestor = r;\n\t\t});\n\t});\n\n\tpi.on(\"session_shutdown\", (_event, ctx) => {\n\t\ttry {\n\t\t\tif (typeof ctx.ui?.setEditorComponent === \"function\") ctx.ui.setEditorComponent(undefined);\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\ttry {\n\t\t\tif (typeof ctx.ui?.setFooter === \"function\") ctx.ui.setFooter(undefined);\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\trenderRequestor = undefined;\n\t});\n\n\t// Re-render triggers: model/provider + effort (chip), and token/cost/context\n\t// (stats line). Event names match those zentui wires.\n\tconst reRenderEvents = [\n\t\t\"model_select\",\n\t\t\"thinking_level_select\",\n\t\t\"agent_end\",\n\t\t\"message_end\",\n\t\t\"tool_execution_end\",\n\t\t\"session_compact\",\n\t];\n\tfor (const ev of reRenderEvents) {\n\t\tpi.on(ev, () => requestRender());\n\t}\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"lunr-cron.d.ts","sourceRoot":"","sources":["../../src/builtin-extensions/lunr-cron.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AAsFtF,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,GAAG,IAAI,CAyP/C","sourcesContent":["// @ts-nocheck\n/**\n * lunr-cron — lunR-native scheduled jobs (Phase 1: local TUI delivery;\n * Phase 4: gateway delivery + origin stamping).\n *\n * lunR: this file is lunR-native (not an absorbed upstream extension). It wires\n * core/cron (jobs store + scheduler) into the interactive session:\n *\n * - `/cron list|create|pause|resume|run|remove|status` command.\n * - One `cron` tool (TypeBox) so the agent can manage jobs. The shared\n * core/cron/fire-guard depth counter refuses the tool while a cron-fired\n * turn is in flight — TUI-fired OR gateway-fired (jobs cannot schedule\n * jobs).\n * - Jobs created inside a gateway chat turn are stamped with that chat as\n * their origin and default deliver to \"origin\" (core/cron/origin-context).\n * - Scheduler starts on session_start only in \"tui\" mode, stops on\n * session_shutdown. runJob = sendUserMessage + wait for agent_end;\n * deliverResult reads the `@lunr/cron-delivery` bridge on globalThis\n * (registered here as the local notify; the Phase 4 gateway replaces\n * it — core/cron/scheduler.ts never touches the bridge itself).\n *\n * `// @ts-nocheck` matches the builtin-extension convention (see lunr-behavior).\n * Runtime imports stay on concrete core modules — never the package barrel.\n */\n\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr\";\nimport { Type } from \"@sinclair/typebox\";\nimport { beginCronFire, endCronFire, isCronFire } from \"../core/cron/fire-guard.ts\";\nimport {\n\tcreateJob,\n\tgetJob,\n\tlistJobs,\n\tparseSchedule,\n\tpauseJob,\n\tremoveJob,\n\tresumeJob,\n\tupdateJob,\n} from \"../core/cron/jobs.ts\";\nimport { currentOrigin } from \"../core/cron/origin-context.ts\";\nimport { executeJob, startScheduler } from \"../core/cron/scheduler.ts\";\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n/** The cron-fired turn currently waiting for agent_end. */\nlet pendingRun: { resolve: (text: string) => void; reject: (err: Error) => void } | null = null;\nlet scheduler: { stop(): void } | null = null;\nlet lastCtx: ExtensionContext | null = null;\n\nconst DELIVERY_BRIDGE_SYMBOL = Symbol.for(\"@lunr/cron-delivery\");\n\n// ---------------------------------------------------------------------------\n// Turn plumbing\n// ---------------------------------------------------------------------------\n\n/** Final assistant text from an agent_end messages array (last assistant message, text blocks only). */\nfunction extractAssistantText(messages: unknown[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i] as any;\n\t\tif (msg?.role !== \"assistant\") continue;\n\t\tconst parts = Array.isArray(msg.content) ? msg.content : [];\n\t\tconst text = parts\n\t\t\t.filter((p: any) => p?.type === \"text\")\n\t\t\t.map((p: any) => String(p.text ?? \"\"))\n\t\t\t.join(\"\")\n\t\t\t.trim();\n\t\tif (text) return text;\n\t}\n\treturn \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\nfunction fmtTime(iso: string | null): string {\n\tif (!iso) return \"-\";\n\tconst d = new Date(iso);\n\tif (Number.isNaN(d.getTime())) return \"-\";\n\tconst p = (n: number) => String(n).padStart(2, \"0\");\n\t// Stored timestamps are UTC ISO; render in local time so users read wall-clock.\n\treturn `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;\n}\n\nfunction formatJobList(): string {\n\tconst jobs = listJobs();\n\tif (jobs.length === 0) return \"No cron jobs. Create one with /cron create <schedule> <prompt>.\";\n\tconst lines = jobs.map(\n\t\t(j) =>\n\t\t\t`${j.id} ${j.state}${j.enabled ? \"\" : \" (disabled)\"} ${j.scheduleDisplay} next=${fmtTime(j.nextRunAt)} last=${j.lastStatus ?? \"-\"}${j.lastError ? ` (${j.lastError})` : \"\"} ${j.name}`,\n\t);\n\treturn `Cron jobs (${jobs.length}):\\n${lines.join(\"\\n\")}`;\n}\n\nfunction formatStatus(): string {\n\tconst jobs = listJobs();\n\tconst count = (s: string) => jobs.filter((j) => j.state === s).length;\n\tconst next = jobs\n\t\t.filter((j) => j.enabled && j.state === \"scheduled\" && j.nextRunAt)\n\t\t.sort((a, b) => String(a.nextRunAt).localeCompare(String(b.nextRunAt)))[0];\n\treturn (\n\t\t`Cron: scheduler ${scheduler ? \"running\" : \"stopped\"}; ${jobs.length} job(s) — ` +\n\t\t`${count(\"scheduled\")} scheduled, ${count(\"paused\")} paused, ${count(\"completed\")} completed, ${count(\"error\")} error.` +\n\t\t(next ? ` Next: '${next.name}' at ${fmtTime(next.nextRunAt)}.` : \"\")\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Extension\n// ---------------------------------------------------------------------------\n\nexport default function (pi: ExtensionAPI): void {\n\t// --- Local delivery bridge (Phase 4 gateway replaces this) ---\n\t(globalThis as Record<symbol, unknown>)[DELIVERY_BRIDGE_SYMBOL] = async (job: { name: string }, _content: string) => {\n\t\ttry {\n\t\t\tlastCtx?.ui.notify(`Cron job '${job.name}' finished`, \"info\");\n\t\t\treturn null;\n\t\t} catch (err) {\n\t\t\treturn String((err as Error)?.message ?? err);\n\t\t}\n\t};\n\n\t// --- Scheduler deps (TUI) ---\n\tconst runJob = (prompt: string, _job: unknown): Promise<string> => {\n\t\tif (pendingRun) return Promise.reject(new Error(\"another cron job turn is already in flight\"));\n\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\tbeginCronFire();\n\t\t\tpendingRun = { resolve, reject };\n\t\t\ttry {\n\t\t\t\tpi.sendUserMessage(prompt);\n\t\t\t} catch (err) {\n\t\t\t\tpendingRun = null;\n\t\t\t\tendCronFire();\n\t\t\t\treject(err as Error);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst deliverResult = async (job: any, content: string): Promise<void> => {\n\t\tconst bridge = (globalThis as Record<symbol, unknown>)[DELIVERY_BRIDGE_SYMBOL] as\n\t\t\t| ((job: unknown, content: string) => Promise<string | null>)\n\t\t\t| undefined;\n\t\tif (!bridge) throw new Error(\"no cron delivery bridge registered\");\n\t\tconst err = await bridge(job, content);\n\t\tif (err) throw new Error(String(err));\n\t};\n\n\tconst schedulerDeps = { runJob, deliverResult };\n\n\t/** Manual trigger: run inline when idle, otherwise make the job due for the next tick. */\n\tconst triggerRun = async (job: any, ctx: ExtensionContext): Promise<string> => {\n\t\tif (ctx.isIdle()) {\n\t\t\ttry {\n\t\t\t\tawait executeJob(getJob(job.id), schedulerDeps);\n\t\t\t\treturn `Cron job '${job.name}' (${job.id}) finished.`;\n\t\t\t} catch (err) {\n\t\t\t\treturn `Cron job '${job.name}' (${job.id}) failed: ${String((err as Error)?.message ?? err)}`;\n\t\t\t}\n\t\t}\n\t\tawait updateJob(job.id, { nextRunAt: new Date().toISOString() });\n\t\treturn `Cron job '${job.name}' (${job.id}) queued for the next scheduler tick.`;\n\t};\n\n\t// --- Resolve the cron-fired turn when the agent turn ends ---\n\tpi.on(\"agent_end\", (event) => {\n\t\tif (!pendingRun) return;\n\t\tconst pending = pendingRun;\n\t\tpendingRun = null;\n\t\tendCronFire();\n\t\tpending.resolve(extractAssistantText(event.messages ?? []));\n\t});\n\n\t// --- Scheduler lifecycle: TUI sessions only ---\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\tlastCtx = ctx;\n\t\tif (ctx.mode !== \"tui\") return;\n\t\tscheduler?.stop();\n\t\tscheduler = startScheduler(schedulerDeps);\n\t});\n\n\tpi.on(\"session_shutdown\", () => {\n\t\tscheduler?.stop();\n\t\tscheduler = null;\n\t});\n\n\t// --- /cron command ---\n\tpi.registerCommand(\"cron\", {\n\t\tdescription: \"Manage cron jobs: /cron list | create <schedule> <prompt> | pause|resume|run|remove <id-or-name> | status\",\n\t\tgetArgumentCompletions: (prefix: string) => {\n\t\t\tconst subs = [\"list\", \"create\", \"pause\", \"resume\", \"run\", \"remove\", \"status\"];\n\t\t\tconst lower = prefix.toLowerCase();\n\t\t\treturn subs\n\t\t\t\t.filter((s) => s.startsWith(lower))\n\t\t\t\t.map((s) => ({ value: s, label: s, description: `/cron ${s}` }));\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tlastCtx = ctx;\n\t\t\tconst tokens = args.trim().split(/\\s+/).filter(Boolean);\n\t\t\tconst sub = (tokens.shift() ?? \"list\").toLowerCase();\n\t\t\ttry {\n\t\t\t\tswitch (sub) {\n\t\t\t\t\tcase \"list\": {\n\t\t\t\t\t\tctx.ui.notify(formatJobList(), \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"status\": {\n\t\t\t\t\t\tctx.ui.notify(formatStatus(), \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"create\": {\n\t\t\t\t\t\t// Greedy: the schedule is the shortest leading token run that parses.\n\t\t\t\t\t\tlet used = 0;\n\t\t\t\t\t\tfor (let k = 1; k <= Math.min(6, tokens.length); k++) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tparseSchedule(tokens.slice(0, k).join(\" \"));\n\t\t\t\t\t\t\t\tused = k;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// keep extending\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst prompt = tokens.slice(used).join(\" \").trim();\n\t\t\t\t\t\tif (!used || !prompt) {\n\t\t\t\t\t\t\tctx.ui.notify(\"Usage: /cron create <schedule> <prompt> — e.g. /cron create every 30m check the deploy\", \"error\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst job = await createJob({ prompt, schedule: tokens.slice(0, used).join(\" \") });\n\t\t\t\t\t\tctx.ui.notify(`Created cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`, \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"pause\":\n\t\t\t\t\tcase \"resume\":\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\tcase \"run\": {\n\t\t\t\t\t\tconst idOrName = tokens.join(\" \").trim();\n\t\t\t\t\t\tif (!idOrName) {\n\t\t\t\t\t\t\tctx.ui.notify(`Usage: /cron ${sub} <id-or-name>`, \"error\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (sub === \"pause\") {\n\t\t\t\t\t\t\tconst job = await pauseJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Paused cron job '${job.name}' (${job.id}).`, \"info\");\n\t\t\t\t\t\t} else if (sub === \"resume\") {\n\t\t\t\t\t\t\tconst job = await resumeJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Resumed cron job '${job.name}' (${job.id}) — next run ${fmtTime(job.nextRunAt)}.`, \"info\");\n\t\t\t\t\t\t} else if (sub === \"remove\") {\n\t\t\t\t\t\t\tconst job = await removeJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Removed cron job '${job.name}' (${job.id}).`, \"info\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst job = getJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(await triggerRun(job, ctx), \"info\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tctx.ui.notify(\"Usage: /cron list | create <schedule> <prompt> | pause|resume|run|remove <id-or-name> | status\", \"error\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tctx.ui.notify(String((err as Error)?.message ?? err), \"error\");\n\t\t\t}\n\t\t},\n\t});\n\n\t// --- cron tool (agent-facing) ---\n\tpi.registerTool({\n\t\tname: \"cron\",\n\t\tlabel: \"Cron\",\n\t\tdescription: [\n\t\t\t\"Manage scheduled cron jobs that run prompts unattended in this session.\",\n\t\t\t\"Actions: create (needs prompt + schedule), list, update (id + fields), pause, resume, remove, run (trigger now).\",\n\t\t\t\"Schedule formats: 'every 30m' / 'every 2h' / 'every 1d' (recurring), '30m'/'2h' or an ISO timestamp (one-shot), or a 5-field cron expression.\",\n\t\t\t\"Job output is delivered automatically; the job's prompt can answer [SILENT] to suppress delivery.\",\n\t\t].join(\"\\n\"),\n\t\tparameters: Type.Object({\n\t\t\taction: Type.Union([\n\t\t\t\tType.Literal(\"create\"),\n\t\t\t\tType.Literal(\"list\"),\n\t\t\t\tType.Literal(\"update\"),\n\t\t\t\tType.Literal(\"pause\"),\n\t\t\t\tType.Literal(\"resume\"),\n\t\t\t\tType.Literal(\"remove\"),\n\t\t\t\tType.Literal(\"run\"),\n\t\t\t]),\n\t\t\tid: Type.Optional(Type.String({ description: \"Job id or unique name (all actions except create/list).\" })),\n\t\t\tname: Type.Optional(Type.String({ description: \"Display name (<=50 chars); derived from the prompt when omitted.\" })),\n\t\t\tprompt: Type.Optional(Type.String({ description: \"The prompt the job runs (create/update).\" })),\n\t\t\tschedule: Type.Optional(Type.String({ description: \"Schedule input (create/update).\" })),\n\t\t\tdeliver: Type.Optional(\n\t\t\t\tType.String({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Delivery target(s), comma-separated: 'local' (output file only), 'origin' (the chat that created the job), 'telegram'/'discord' (platform home channel), or 'telegram:<chatId>[:<threadId>]' / 'discord:<chatId>[:<threadId>]'. Defaults to 'origin' when created from a gateway chat, else 'local'.\",\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n\t\t\tconst text = (t: string) => ({ content: [{ type: \"text\" as const, text: t }] });\n\t\t\tif (isCronFire()) {\n\t\t\t\treturn text(\"cron: unavailable while a cron-fired turn is running (cron jobs cannot schedule cron jobs).\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tswitch (params.action) {\n\t\t\t\t\tcase \"create\": {\n\t\t\t\t\t\tif (!params.prompt?.trim() || !params.schedule?.trim()) {\n\t\t\t\t\t\t\treturn text(\"cron create: prompt and schedule are required.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Inside a gateway chat turn, stamp the chat as the delivery\n\t\t\t\t\t\t// origin and default deliver to \"origin\" (Phase 4); outside\n\t\t\t\t\t\t// any origin context the default stays \"local\".\n\t\t\t\t\t\tconst origin = currentOrigin();\n\t\t\t\t\t\tconst job = await createJob({\n\t\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\t\tschedule: params.schedule,\n\t\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\t\tdeliver: params.deliver ?? (origin ? \"origin\" : undefined),\n\t\t\t\t\t\t\torigin: origin ? { ...origin } : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn text(`Created cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"list\": {\n\t\t\t\t\t\treturn text(formatJobList());\n\t\t\t\t\t}\n\t\t\t\t\tcase \"update\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron update: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await updateJob(params.id, {\n\t\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\t\tschedule: params.schedule,\n\t\t\t\t\t\t\tdeliver: params.deliver,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn text(`Updated cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"pause\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron pause: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await pauseJob(params.id);\n\t\t\t\t\t\treturn text(`Paused cron job '${job.name}' (${job.id}).`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"resume\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron resume: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await resumeJob(params.id);\n\t\t\t\t\t\treturn text(`Resumed cron job '${job.name}' (${job.id}) — next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"remove\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron remove: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await removeJob(params.id);\n\t\t\t\t\t\treturn text(`Removed cron job '${job.name}' (${job.id}).`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"run\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron run: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = getJob(params.id);\n\t\t\t\t\t\treturn text(await triggerRun(job, ctx));\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn text(`cron: unknown action \"${String(params.action)}\".`);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\treturn text(`cron: ${String((err as Error)?.message ?? err)}`);\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"lunr-cron.d.ts","sourceRoot":"","sources":["../../src/builtin-extensions/lunr-cron.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AAyFtF,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,GAAG,IAAI,CA6P/C","sourcesContent":["// @ts-nocheck\n/**\n * lunr-cron — lunR-native scheduled jobs (Phase 1: local TUI delivery;\n * Phase 4: gateway delivery + origin stamping).\n *\n * lunR: this file is lunR-native (not an absorbed upstream extension). It wires\n * core/cron (jobs store + scheduler) into the interactive session:\n *\n * - `/cron list|create|pause|resume|run|remove|status` command.\n * - One `cron` tool (TypeBox) so the agent can manage jobs. The shared\n * core/cron/fire-guard depth counter refuses the tool while a cron-fired\n * turn is in flight — TUI-fired OR gateway-fired (jobs cannot schedule\n * jobs).\n * - Jobs created inside a gateway chat turn are stamped with that chat as\n * their origin and default deliver to \"origin\" (core/cron/origin-context).\n * - Scheduler starts on session_start only in \"tui\" mode, stops on\n * session_shutdown. runJob = sendUserMessage + wait for agent_end;\n * deliverResult reads the `@lunr/cron-delivery` bridge on globalThis\n * (registered here as the local notify; the Phase 4 gateway replaces\n * it — core/cron/scheduler.ts never touches the bridge itself).\n *\n * `// @ts-nocheck` matches the builtin-extension convention (see lunr-behavior).\n * Runtime imports stay on concrete core modules — never the package barrel.\n */\n\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr\";\nimport { Type } from \"@sinclair/typebox\";\nimport { beginCronFire, endCronFire, isCronFire } from \"../core/cron/fire-guard.ts\";\nimport {\n\tcreateJob,\n\tgetJob,\n\tlistJobs,\n\tparseSchedule,\n\tpauseJob,\n\tremoveJob,\n\tresumeJob,\n\tsetCronDeliverValidator,\n\tupdateJob,\n} from \"../core/cron/jobs.ts\";\nimport { currentOrigin } from \"../core/cron/origin-context.ts\";\nimport { executeJob, startScheduler } from \"../core/cron/scheduler.ts\";\nimport { loadGatewayConfig } from \"../gateway/config.ts\";\nimport { createDeliverValidator } from \"../gateway/cron.ts\";\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n/** The cron-fired turn currently waiting for agent_end. */\nlet pendingRun: { resolve: (text: string) => void; reject: (err: Error) => void } | null = null;\nlet scheduler: { stop(): void } | null = null;\nlet lastCtx: ExtensionContext | null = null;\n\nconst DELIVERY_BRIDGE_SYMBOL = Symbol.for(\"@lunr/cron-delivery\");\n\n// ---------------------------------------------------------------------------\n// Turn plumbing\n// ---------------------------------------------------------------------------\n\n/** Final assistant text from an agent_end messages array (last assistant message, text blocks only). */\nfunction extractAssistantText(messages: unknown[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i] as any;\n\t\tif (msg?.role !== \"assistant\") continue;\n\t\tconst parts = Array.isArray(msg.content) ? msg.content : [];\n\t\tconst text = parts\n\t\t\t.filter((p: any) => p?.type === \"text\")\n\t\t\t.map((p: any) => String(p.text ?? \"\"))\n\t\t\t.join(\"\")\n\t\t\t.trim();\n\t\tif (text) return text;\n\t}\n\treturn \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\nfunction fmtTime(iso: string | null): string {\n\tif (!iso) return \"-\";\n\tconst d = new Date(iso);\n\tif (Number.isNaN(d.getTime())) return \"-\";\n\tconst p = (n: number) => String(n).padStart(2, \"0\");\n\t// Stored timestamps are UTC ISO; render in local time so users read wall-clock.\n\treturn `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;\n}\n\nfunction formatJobList(): string {\n\tconst jobs = listJobs();\n\tif (jobs.length === 0) return \"No cron jobs. Create one with /cron create <schedule> <prompt>.\";\n\tconst lines = jobs.map(\n\t\t(j) =>\n\t\t\t`${j.id} ${j.state}${j.enabled ? \"\" : \" (disabled)\"} ${j.scheduleDisplay} next=${fmtTime(j.nextRunAt)} last=${j.lastStatus ?? \"-\"}${j.lastError ? ` (${j.lastError})` : \"\"} ${j.name}`,\n\t);\n\treturn `Cron jobs (${jobs.length}):\\n${lines.join(\"\\n\")}`;\n}\n\nfunction formatStatus(): string {\n\tconst jobs = listJobs();\n\tconst count = (s: string) => jobs.filter((j) => j.state === s).length;\n\tconst next = jobs\n\t\t.filter((j) => j.enabled && j.state === \"scheduled\" && j.nextRunAt)\n\t\t.sort((a, b) => String(a.nextRunAt).localeCompare(String(b.nextRunAt)))[0];\n\treturn (\n\t\t`Cron: scheduler ${scheduler ? \"running\" : \"stopped\"}; ${jobs.length} job(s) — ` +\n\t\t`${count(\"scheduled\")} scheduled, ${count(\"paused\")} paused, ${count(\"completed\")} completed, ${count(\"error\")} error.` +\n\t\t(next ? ` Next: '${next.name}' at ${fmtTime(next.nextRunAt)}.` : \"\")\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Extension\n// ---------------------------------------------------------------------------\n\nexport default function (pi: ExtensionAPI): void {\n\t// Same allowlist the gateway uses, so a TUI session cannot persist a job\n\t// that later posts to a chat the bot can reach but is not allowed.\n\tsetCronDeliverValidator(createDeliverValidator(loadGatewayConfig()));\n\n\t// --- Local delivery bridge (Phase 4 gateway replaces this) ---\n\t(globalThis as Record<symbol, unknown>)[DELIVERY_BRIDGE_SYMBOL] = async (job: { name: string }, _content: string) => {\n\t\ttry {\n\t\t\tlastCtx?.ui.notify(`Cron job '${job.name}' finished`, \"info\");\n\t\t\treturn null;\n\t\t} catch (err) {\n\t\t\treturn String((err as Error)?.message ?? err);\n\t\t}\n\t};\n\n\t// --- Scheduler deps (TUI) ---\n\tconst runJob = (prompt: string, _job: unknown): Promise<string> => {\n\t\tif (pendingRun) return Promise.reject(new Error(\"another cron job turn is already in flight\"));\n\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\tbeginCronFire();\n\t\t\tpendingRun = { resolve, reject };\n\t\t\ttry {\n\t\t\t\tpi.sendUserMessage(prompt);\n\t\t\t} catch (err) {\n\t\t\t\tpendingRun = null;\n\t\t\t\tendCronFire();\n\t\t\t\treject(err as Error);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst deliverResult = async (job: any, content: string): Promise<void> => {\n\t\tconst bridge = (globalThis as Record<symbol, unknown>)[DELIVERY_BRIDGE_SYMBOL] as\n\t\t\t| ((job: unknown, content: string) => Promise<string | null>)\n\t\t\t| undefined;\n\t\tif (!bridge) throw new Error(\"no cron delivery bridge registered\");\n\t\tconst err = await bridge(job, content);\n\t\tif (err) throw new Error(String(err));\n\t};\n\n\tconst schedulerDeps = { runJob, deliverResult };\n\n\t/** Manual trigger: run inline when idle, otherwise make the job due for the next tick. */\n\tconst triggerRun = async (job: any, ctx: ExtensionContext): Promise<string> => {\n\t\tif (ctx.isIdle()) {\n\t\t\ttry {\n\t\t\t\tawait executeJob(getJob(job.id), schedulerDeps);\n\t\t\t\treturn `Cron job '${job.name}' (${job.id}) finished.`;\n\t\t\t} catch (err) {\n\t\t\t\treturn `Cron job '${job.name}' (${job.id}) failed: ${String((err as Error)?.message ?? err)}`;\n\t\t\t}\n\t\t}\n\t\tawait updateJob(job.id, { nextRunAt: new Date().toISOString() });\n\t\treturn `Cron job '${job.name}' (${job.id}) queued for the next scheduler tick.`;\n\t};\n\n\t// --- Resolve the cron-fired turn when the agent turn ends ---\n\tpi.on(\"agent_end\", (event) => {\n\t\tif (!pendingRun) return;\n\t\tconst pending = pendingRun;\n\t\tpendingRun = null;\n\t\tendCronFire();\n\t\tpending.resolve(extractAssistantText(event.messages ?? []));\n\t});\n\n\t// --- Scheduler lifecycle: TUI sessions only ---\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\tlastCtx = ctx;\n\t\tif (ctx.mode !== \"tui\") return;\n\t\tscheduler?.stop();\n\t\tscheduler = startScheduler(schedulerDeps);\n\t});\n\n\tpi.on(\"session_shutdown\", () => {\n\t\tscheduler?.stop();\n\t\tscheduler = null;\n\t});\n\n\t// --- /cron command ---\n\tpi.registerCommand(\"cron\", {\n\t\tdescription: \"Manage cron jobs: /cron list | create <schedule> <prompt> | pause|resume|run|remove <id-or-name> | status\",\n\t\tgetArgumentCompletions: (prefix: string) => {\n\t\t\tconst subs = [\"list\", \"create\", \"pause\", \"resume\", \"run\", \"remove\", \"status\"];\n\t\t\tconst lower = prefix.toLowerCase();\n\t\t\treturn subs\n\t\t\t\t.filter((s) => s.startsWith(lower))\n\t\t\t\t.map((s) => ({ value: s, label: s, description: `/cron ${s}` }));\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tlastCtx = ctx;\n\t\t\tconst tokens = args.trim().split(/\\s+/).filter(Boolean);\n\t\t\tconst sub = (tokens.shift() ?? \"list\").toLowerCase();\n\t\t\ttry {\n\t\t\t\tswitch (sub) {\n\t\t\t\t\tcase \"list\": {\n\t\t\t\t\t\tctx.ui.notify(formatJobList(), \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"status\": {\n\t\t\t\t\t\tctx.ui.notify(formatStatus(), \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"create\": {\n\t\t\t\t\t\t// Greedy: the schedule is the shortest leading token run that parses.\n\t\t\t\t\t\tlet used = 0;\n\t\t\t\t\t\tfor (let k = 1; k <= Math.min(6, tokens.length); k++) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tparseSchedule(tokens.slice(0, k).join(\" \"));\n\t\t\t\t\t\t\t\tused = k;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// keep extending\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst prompt = tokens.slice(used).join(\" \").trim();\n\t\t\t\t\t\tif (!used || !prompt) {\n\t\t\t\t\t\t\tctx.ui.notify(\"Usage: /cron create <schedule> <prompt> — e.g. /cron create every 30m check the deploy\", \"error\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst job = await createJob({ prompt, schedule: tokens.slice(0, used).join(\" \") });\n\t\t\t\t\t\tctx.ui.notify(`Created cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`, \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"pause\":\n\t\t\t\t\tcase \"resume\":\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\tcase \"run\": {\n\t\t\t\t\t\tconst idOrName = tokens.join(\" \").trim();\n\t\t\t\t\t\tif (!idOrName) {\n\t\t\t\t\t\t\tctx.ui.notify(`Usage: /cron ${sub} <id-or-name>`, \"error\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (sub === \"pause\") {\n\t\t\t\t\t\t\tconst job = await pauseJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Paused cron job '${job.name}' (${job.id}).`, \"info\");\n\t\t\t\t\t\t} else if (sub === \"resume\") {\n\t\t\t\t\t\t\tconst job = await resumeJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Resumed cron job '${job.name}' (${job.id}) — next run ${fmtTime(job.nextRunAt)}.`, \"info\");\n\t\t\t\t\t\t} else if (sub === \"remove\") {\n\t\t\t\t\t\t\tconst job = await removeJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Removed cron job '${job.name}' (${job.id}).`, \"info\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst job = getJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(await triggerRun(job, ctx), \"info\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tctx.ui.notify(\"Usage: /cron list | create <schedule> <prompt> | pause|resume|run|remove <id-or-name> | status\", \"error\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tctx.ui.notify(String((err as Error)?.message ?? err), \"error\");\n\t\t\t}\n\t\t},\n\t});\n\n\t// --- cron tool (agent-facing) ---\n\tpi.registerTool({\n\t\tname: \"cron\",\n\t\tlabel: \"Cron\",\n\t\tdescription: [\n\t\t\t\"Manage scheduled cron jobs that run prompts unattended in this session.\",\n\t\t\t\"Actions: create (needs prompt + schedule), list, update (id + fields), pause, resume, remove, run (trigger now).\",\n\t\t\t\"Schedule formats: 'every 30m' / 'every 2h' / 'every 1d' (recurring), '30m'/'2h' or an ISO timestamp (one-shot), or a 5-field cron expression.\",\n\t\t\t\"Job output is delivered automatically; the job's prompt can answer [SILENT] to suppress delivery.\",\n\t\t].join(\"\\n\"),\n\t\tparameters: Type.Object({\n\t\t\taction: Type.Union([\n\t\t\t\tType.Literal(\"create\"),\n\t\t\t\tType.Literal(\"list\"),\n\t\t\t\tType.Literal(\"update\"),\n\t\t\t\tType.Literal(\"pause\"),\n\t\t\t\tType.Literal(\"resume\"),\n\t\t\t\tType.Literal(\"remove\"),\n\t\t\t\tType.Literal(\"run\"),\n\t\t\t]),\n\t\t\tid: Type.Optional(Type.String({ description: \"Job id or unique name (all actions except create/list).\" })),\n\t\t\tname: Type.Optional(Type.String({ description: \"Display name (<=50 chars); derived from the prompt when omitted.\" })),\n\t\t\tprompt: Type.Optional(Type.String({ description: \"The prompt the job runs (create/update).\" })),\n\t\t\tschedule: Type.Optional(Type.String({ description: \"Schedule input (create/update).\" })),\n\t\t\tdeliver: Type.Optional(\n\t\t\t\tType.String({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Delivery target(s), comma-separated: 'local' (output file only), 'origin' (the chat that created the job), 'telegram'/'discord' (platform home channel), or 'telegram:<chatId>[:<threadId>]' / 'discord:<chatId>[:<threadId>]'. Defaults to 'origin' when created from a gateway chat, else 'local'.\",\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n\t\t\tconst text = (t: string) => ({ content: [{ type: \"text\" as const, text: t }] });\n\t\t\tif (isCronFire()) {\n\t\t\t\treturn text(\"cron: unavailable while a cron-fired turn is running (cron jobs cannot schedule cron jobs).\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tswitch (params.action) {\n\t\t\t\t\tcase \"create\": {\n\t\t\t\t\t\tif (!params.prompt?.trim() || !params.schedule?.trim()) {\n\t\t\t\t\t\t\treturn text(\"cron create: prompt and schedule are required.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Inside a gateway chat turn, stamp the chat as the delivery\n\t\t\t\t\t\t// origin and default deliver to \"origin\" (Phase 4); outside\n\t\t\t\t\t\t// any origin context the default stays \"local\".\n\t\t\t\t\t\tconst origin = currentOrigin();\n\t\t\t\t\t\tconst job = await createJob({\n\t\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\t\tschedule: params.schedule,\n\t\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\t\tdeliver: params.deliver ?? (origin ? \"origin\" : undefined),\n\t\t\t\t\t\t\torigin: origin ? { ...origin } : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn text(`Created cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"list\": {\n\t\t\t\t\t\treturn text(formatJobList());\n\t\t\t\t\t}\n\t\t\t\t\tcase \"update\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron update: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await updateJob(params.id, {\n\t\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\t\tschedule: params.schedule,\n\t\t\t\t\t\t\tdeliver: params.deliver,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn text(`Updated cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"pause\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron pause: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await pauseJob(params.id);\n\t\t\t\t\t\treturn text(`Paused cron job '${job.name}' (${job.id}).`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"resume\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron resume: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await resumeJob(params.id);\n\t\t\t\t\t\treturn text(`Resumed cron job '${job.name}' (${job.id}) — next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"remove\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron remove: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await removeJob(params.id);\n\t\t\t\t\t\treturn text(`Removed cron job '${job.name}' (${job.id}).`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"run\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron run: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = getJob(params.id);\n\t\t\t\t\t\treturn text(await triggerRun(job, ctx));\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn text(`cron: unknown action \"${String(params.action)}\".`);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\treturn text(`cron: ${String((err as Error)?.message ?? err)}`);\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
@@ -24,9 +24,11 @@
24
24
  */
25
25
  import { Type } from "@sinclair/typebox";
26
26
  import { beginCronFire, endCronFire, isCronFire } from "../core/cron/fire-guard.js";
27
- import { createJob, getJob, listJobs, parseSchedule, pauseJob, removeJob, resumeJob, updateJob, } from "../core/cron/jobs.js";
27
+ import { createJob, getJob, listJobs, parseSchedule, pauseJob, removeJob, resumeJob, setCronDeliverValidator, updateJob, } from "../core/cron/jobs.js";
28
28
  import { currentOrigin } from "../core/cron/origin-context.js";
29
29
  import { executeJob, startScheduler } from "../core/cron/scheduler.js";
30
+ import { loadGatewayConfig } from "../gateway/config.js";
31
+ import { createDeliverValidator } from "../gateway/cron.js";
30
32
  // ---------------------------------------------------------------------------
31
33
  // Module state
32
34
  // ---------------------------------------------------------------------------
@@ -89,6 +91,9 @@ function formatStatus() {
89
91
  // Extension
90
92
  // ---------------------------------------------------------------------------
91
93
  export default function (pi) {
94
+ // Same allowlist the gateway uses, so a TUI session cannot persist a job
95
+ // that later posts to a chat the bot can reach but is not allowed.
96
+ setCronDeliverValidator(createDeliverValidator(loadGatewayConfig()));
92
97
  // --- Local delivery bridge (Phase 4 gateway replaces this) ---
93
98
  globalThis[DELIVERY_BRIDGE_SYMBOL] = async (job, _content) => {
94
99
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"lunr-cron.js","sourceRoot":"","sources":["../../src/builtin-extensions/lunr-cron.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\n/**\n * lunr-cron — lunR-native scheduled jobs (Phase 1: local TUI delivery;\n * Phase 4: gateway delivery + origin stamping).\n *\n * lunR: this file is lunR-native (not an absorbed upstream extension). It wires\n * core/cron (jobs store + scheduler) into the interactive session:\n *\n * - `/cron list|create|pause|resume|run|remove|status` command.\n * - One `cron` tool (TypeBox) so the agent can manage jobs. The shared\n * core/cron/fire-guard depth counter refuses the tool while a cron-fired\n * turn is in flight — TUI-fired OR gateway-fired (jobs cannot schedule\n * jobs).\n * - Jobs created inside a gateway chat turn are stamped with that chat as\n * their origin and default deliver to \"origin\" (core/cron/origin-context).\n * - Scheduler starts on session_start only in \"tui\" mode, stops on\n * session_shutdown. runJob = sendUserMessage + wait for agent_end;\n * deliverResult reads the `@lunr/cron-delivery` bridge on globalThis\n * (registered here as the local notify; the Phase 4 gateway replaces\n * it — core/cron/scheduler.ts never touches the bridge itself).\n *\n * `// @ts-nocheck` matches the builtin-extension convention (see lunr-behavior).\n * Runtime imports stay on concrete core modules — never the package barrel.\n */\n\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr\";\nimport { Type } from \"@sinclair/typebox\";\nimport { beginCronFire, endCronFire, isCronFire } from \"../core/cron/fire-guard.ts\";\nimport {\n\tcreateJob,\n\tgetJob,\n\tlistJobs,\n\tparseSchedule,\n\tpauseJob,\n\tremoveJob,\n\tresumeJob,\n\tupdateJob,\n} from \"../core/cron/jobs.ts\";\nimport { currentOrigin } from \"../core/cron/origin-context.ts\";\nimport { executeJob, startScheduler } from \"../core/cron/scheduler.ts\";\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n/** The cron-fired turn currently waiting for agent_end. */\nlet pendingRun: { resolve: (text: string) => void; reject: (err: Error) => void } | null = null;\nlet scheduler: { stop(): void } | null = null;\nlet lastCtx: ExtensionContext | null = null;\n\nconst DELIVERY_BRIDGE_SYMBOL = Symbol.for(\"@lunr/cron-delivery\");\n\n// ---------------------------------------------------------------------------\n// Turn plumbing\n// ---------------------------------------------------------------------------\n\n/** Final assistant text from an agent_end messages array (last assistant message, text blocks only). */\nfunction extractAssistantText(messages: unknown[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i] as any;\n\t\tif (msg?.role !== \"assistant\") continue;\n\t\tconst parts = Array.isArray(msg.content) ? msg.content : [];\n\t\tconst text = parts\n\t\t\t.filter((p: any) => p?.type === \"text\")\n\t\t\t.map((p: any) => String(p.text ?? \"\"))\n\t\t\t.join(\"\")\n\t\t\t.trim();\n\t\tif (text) return text;\n\t}\n\treturn \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\nfunction fmtTime(iso: string | null): string {\n\tif (!iso) return \"-\";\n\tconst d = new Date(iso);\n\tif (Number.isNaN(d.getTime())) return \"-\";\n\tconst p = (n: number) => String(n).padStart(2, \"0\");\n\t// Stored timestamps are UTC ISO; render in local time so users read wall-clock.\n\treturn `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;\n}\n\nfunction formatJobList(): string {\n\tconst jobs = listJobs();\n\tif (jobs.length === 0) return \"No cron jobs. Create one with /cron create <schedule> <prompt>.\";\n\tconst lines = jobs.map(\n\t\t(j) =>\n\t\t\t`${j.id} ${j.state}${j.enabled ? \"\" : \" (disabled)\"} ${j.scheduleDisplay} next=${fmtTime(j.nextRunAt)} last=${j.lastStatus ?? \"-\"}${j.lastError ? ` (${j.lastError})` : \"\"} ${j.name}`,\n\t);\n\treturn `Cron jobs (${jobs.length}):\\n${lines.join(\"\\n\")}`;\n}\n\nfunction formatStatus(): string {\n\tconst jobs = listJobs();\n\tconst count = (s: string) => jobs.filter((j) => j.state === s).length;\n\tconst next = jobs\n\t\t.filter((j) => j.enabled && j.state === \"scheduled\" && j.nextRunAt)\n\t\t.sort((a, b) => String(a.nextRunAt).localeCompare(String(b.nextRunAt)))[0];\n\treturn (\n\t\t`Cron: scheduler ${scheduler ? \"running\" : \"stopped\"}; ${jobs.length} job(s) — ` +\n\t\t`${count(\"scheduled\")} scheduled, ${count(\"paused\")} paused, ${count(\"completed\")} completed, ${count(\"error\")} error.` +\n\t\t(next ? ` Next: '${next.name}' at ${fmtTime(next.nextRunAt)}.` : \"\")\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Extension\n// ---------------------------------------------------------------------------\n\nexport default function (pi: ExtensionAPI): void {\n\t// --- Local delivery bridge (Phase 4 gateway replaces this) ---\n\t(globalThis as Record<symbol, unknown>)[DELIVERY_BRIDGE_SYMBOL] = async (job: { name: string }, _content: string) => {\n\t\ttry {\n\t\t\tlastCtx?.ui.notify(`Cron job '${job.name}' finished`, \"info\");\n\t\t\treturn null;\n\t\t} catch (err) {\n\t\t\treturn String((err as Error)?.message ?? err);\n\t\t}\n\t};\n\n\t// --- Scheduler deps (TUI) ---\n\tconst runJob = (prompt: string, _job: unknown): Promise<string> => {\n\t\tif (pendingRun) return Promise.reject(new Error(\"another cron job turn is already in flight\"));\n\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\tbeginCronFire();\n\t\t\tpendingRun = { resolve, reject };\n\t\t\ttry {\n\t\t\t\tpi.sendUserMessage(prompt);\n\t\t\t} catch (err) {\n\t\t\t\tpendingRun = null;\n\t\t\t\tendCronFire();\n\t\t\t\treject(err as Error);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst deliverResult = async (job: any, content: string): Promise<void> => {\n\t\tconst bridge = (globalThis as Record<symbol, unknown>)[DELIVERY_BRIDGE_SYMBOL] as\n\t\t\t| ((job: unknown, content: string) => Promise<string | null>)\n\t\t\t| undefined;\n\t\tif (!bridge) throw new Error(\"no cron delivery bridge registered\");\n\t\tconst err = await bridge(job, content);\n\t\tif (err) throw new Error(String(err));\n\t};\n\n\tconst schedulerDeps = { runJob, deliverResult };\n\n\t/** Manual trigger: run inline when idle, otherwise make the job due for the next tick. */\n\tconst triggerRun = async (job: any, ctx: ExtensionContext): Promise<string> => {\n\t\tif (ctx.isIdle()) {\n\t\t\ttry {\n\t\t\t\tawait executeJob(getJob(job.id), schedulerDeps);\n\t\t\t\treturn `Cron job '${job.name}' (${job.id}) finished.`;\n\t\t\t} catch (err) {\n\t\t\t\treturn `Cron job '${job.name}' (${job.id}) failed: ${String((err as Error)?.message ?? err)}`;\n\t\t\t}\n\t\t}\n\t\tawait updateJob(job.id, { nextRunAt: new Date().toISOString() });\n\t\treturn `Cron job '${job.name}' (${job.id}) queued for the next scheduler tick.`;\n\t};\n\n\t// --- Resolve the cron-fired turn when the agent turn ends ---\n\tpi.on(\"agent_end\", (event) => {\n\t\tif (!pendingRun) return;\n\t\tconst pending = pendingRun;\n\t\tpendingRun = null;\n\t\tendCronFire();\n\t\tpending.resolve(extractAssistantText(event.messages ?? []));\n\t});\n\n\t// --- Scheduler lifecycle: TUI sessions only ---\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\tlastCtx = ctx;\n\t\tif (ctx.mode !== \"tui\") return;\n\t\tscheduler?.stop();\n\t\tscheduler = startScheduler(schedulerDeps);\n\t});\n\n\tpi.on(\"session_shutdown\", () => {\n\t\tscheduler?.stop();\n\t\tscheduler = null;\n\t});\n\n\t// --- /cron command ---\n\tpi.registerCommand(\"cron\", {\n\t\tdescription: \"Manage cron jobs: /cron list | create <schedule> <prompt> | pause|resume|run|remove <id-or-name> | status\",\n\t\tgetArgumentCompletions: (prefix: string) => {\n\t\t\tconst subs = [\"list\", \"create\", \"pause\", \"resume\", \"run\", \"remove\", \"status\"];\n\t\t\tconst lower = prefix.toLowerCase();\n\t\t\treturn subs\n\t\t\t\t.filter((s) => s.startsWith(lower))\n\t\t\t\t.map((s) => ({ value: s, label: s, description: `/cron ${s}` }));\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tlastCtx = ctx;\n\t\t\tconst tokens = args.trim().split(/\\s+/).filter(Boolean);\n\t\t\tconst sub = (tokens.shift() ?? \"list\").toLowerCase();\n\t\t\ttry {\n\t\t\t\tswitch (sub) {\n\t\t\t\t\tcase \"list\": {\n\t\t\t\t\t\tctx.ui.notify(formatJobList(), \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"status\": {\n\t\t\t\t\t\tctx.ui.notify(formatStatus(), \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"create\": {\n\t\t\t\t\t\t// Greedy: the schedule is the shortest leading token run that parses.\n\t\t\t\t\t\tlet used = 0;\n\t\t\t\t\t\tfor (let k = 1; k <= Math.min(6, tokens.length); k++) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tparseSchedule(tokens.slice(0, k).join(\" \"));\n\t\t\t\t\t\t\t\tused = k;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// keep extending\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst prompt = tokens.slice(used).join(\" \").trim();\n\t\t\t\t\t\tif (!used || !prompt) {\n\t\t\t\t\t\t\tctx.ui.notify(\"Usage: /cron create <schedule> <prompt> — e.g. /cron create every 30m check the deploy\", \"error\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst job = await createJob({ prompt, schedule: tokens.slice(0, used).join(\" \") });\n\t\t\t\t\t\tctx.ui.notify(`Created cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`, \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"pause\":\n\t\t\t\t\tcase \"resume\":\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\tcase \"run\": {\n\t\t\t\t\t\tconst idOrName = tokens.join(\" \").trim();\n\t\t\t\t\t\tif (!idOrName) {\n\t\t\t\t\t\t\tctx.ui.notify(`Usage: /cron ${sub} <id-or-name>`, \"error\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (sub === \"pause\") {\n\t\t\t\t\t\t\tconst job = await pauseJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Paused cron job '${job.name}' (${job.id}).`, \"info\");\n\t\t\t\t\t\t} else if (sub === \"resume\") {\n\t\t\t\t\t\t\tconst job = await resumeJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Resumed cron job '${job.name}' (${job.id}) — next run ${fmtTime(job.nextRunAt)}.`, \"info\");\n\t\t\t\t\t\t} else if (sub === \"remove\") {\n\t\t\t\t\t\t\tconst job = await removeJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Removed cron job '${job.name}' (${job.id}).`, \"info\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst job = getJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(await triggerRun(job, ctx), \"info\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tctx.ui.notify(\"Usage: /cron list | create <schedule> <prompt> | pause|resume|run|remove <id-or-name> | status\", \"error\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tctx.ui.notify(String((err as Error)?.message ?? err), \"error\");\n\t\t\t}\n\t\t},\n\t});\n\n\t// --- cron tool (agent-facing) ---\n\tpi.registerTool({\n\t\tname: \"cron\",\n\t\tlabel: \"Cron\",\n\t\tdescription: [\n\t\t\t\"Manage scheduled cron jobs that run prompts unattended in this session.\",\n\t\t\t\"Actions: create (needs prompt + schedule), list, update (id + fields), pause, resume, remove, run (trigger now).\",\n\t\t\t\"Schedule formats: 'every 30m' / 'every 2h' / 'every 1d' (recurring), '30m'/'2h' or an ISO timestamp (one-shot), or a 5-field cron expression.\",\n\t\t\t\"Job output is delivered automatically; the job's prompt can answer [SILENT] to suppress delivery.\",\n\t\t].join(\"\\n\"),\n\t\tparameters: Type.Object({\n\t\t\taction: Type.Union([\n\t\t\t\tType.Literal(\"create\"),\n\t\t\t\tType.Literal(\"list\"),\n\t\t\t\tType.Literal(\"update\"),\n\t\t\t\tType.Literal(\"pause\"),\n\t\t\t\tType.Literal(\"resume\"),\n\t\t\t\tType.Literal(\"remove\"),\n\t\t\t\tType.Literal(\"run\"),\n\t\t\t]),\n\t\t\tid: Type.Optional(Type.String({ description: \"Job id or unique name (all actions except create/list).\" })),\n\t\t\tname: Type.Optional(Type.String({ description: \"Display name (<=50 chars); derived from the prompt when omitted.\" })),\n\t\t\tprompt: Type.Optional(Type.String({ description: \"The prompt the job runs (create/update).\" })),\n\t\t\tschedule: Type.Optional(Type.String({ description: \"Schedule input (create/update).\" })),\n\t\t\tdeliver: Type.Optional(\n\t\t\t\tType.String({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Delivery target(s), comma-separated: 'local' (output file only), 'origin' (the chat that created the job), 'telegram'/'discord' (platform home channel), or 'telegram:<chatId>[:<threadId>]' / 'discord:<chatId>[:<threadId>]'. Defaults to 'origin' when created from a gateway chat, else 'local'.\",\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n\t\t\tconst text = (t: string) => ({ content: [{ type: \"text\" as const, text: t }] });\n\t\t\tif (isCronFire()) {\n\t\t\t\treturn text(\"cron: unavailable while a cron-fired turn is running (cron jobs cannot schedule cron jobs).\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tswitch (params.action) {\n\t\t\t\t\tcase \"create\": {\n\t\t\t\t\t\tif (!params.prompt?.trim() || !params.schedule?.trim()) {\n\t\t\t\t\t\t\treturn text(\"cron create: prompt and schedule are required.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Inside a gateway chat turn, stamp the chat as the delivery\n\t\t\t\t\t\t// origin and default deliver to \"origin\" (Phase 4); outside\n\t\t\t\t\t\t// any origin context the default stays \"local\".\n\t\t\t\t\t\tconst origin = currentOrigin();\n\t\t\t\t\t\tconst job = await createJob({\n\t\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\t\tschedule: params.schedule,\n\t\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\t\tdeliver: params.deliver ?? (origin ? \"origin\" : undefined),\n\t\t\t\t\t\t\torigin: origin ? { ...origin } : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn text(`Created cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"list\": {\n\t\t\t\t\t\treturn text(formatJobList());\n\t\t\t\t\t}\n\t\t\t\t\tcase \"update\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron update: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await updateJob(params.id, {\n\t\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\t\tschedule: params.schedule,\n\t\t\t\t\t\t\tdeliver: params.deliver,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn text(`Updated cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"pause\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron pause: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await pauseJob(params.id);\n\t\t\t\t\t\treturn text(`Paused cron job '${job.name}' (${job.id}).`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"resume\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron resume: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await resumeJob(params.id);\n\t\t\t\t\t\treturn text(`Resumed cron job '${job.name}' (${job.id}) — next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"remove\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron remove: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await removeJob(params.id);\n\t\t\t\t\t\treturn text(`Removed cron job '${job.name}' (${job.id}).`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"run\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron run: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = getJob(params.id);\n\t\t\t\t\t\treturn text(await triggerRun(job, ctx));\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn text(`cron: unknown action \"${String(params.action)}\".`);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\treturn text(`cron: ${String((err as Error)?.message ?? err)}`);\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"lunr-cron.js","sourceRoot":"","sources":["../../src/builtin-extensions/lunr-cron.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\n/**\n * lunr-cron — lunR-native scheduled jobs (Phase 1: local TUI delivery;\n * Phase 4: gateway delivery + origin stamping).\n *\n * lunR: this file is lunR-native (not an absorbed upstream extension). It wires\n * core/cron (jobs store + scheduler) into the interactive session:\n *\n * - `/cron list|create|pause|resume|run|remove|status` command.\n * - One `cron` tool (TypeBox) so the agent can manage jobs. The shared\n * core/cron/fire-guard depth counter refuses the tool while a cron-fired\n * turn is in flight — TUI-fired OR gateway-fired (jobs cannot schedule\n * jobs).\n * - Jobs created inside a gateway chat turn are stamped with that chat as\n * their origin and default deliver to \"origin\" (core/cron/origin-context).\n * - Scheduler starts on session_start only in \"tui\" mode, stops on\n * session_shutdown. runJob = sendUserMessage + wait for agent_end;\n * deliverResult reads the `@lunr/cron-delivery` bridge on globalThis\n * (registered here as the local notify; the Phase 4 gateway replaces\n * it — core/cron/scheduler.ts never touches the bridge itself).\n *\n * `// @ts-nocheck` matches the builtin-extension convention (see lunr-behavior).\n * Runtime imports stay on concrete core modules — never the package barrel.\n */\n\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr\";\nimport { Type } from \"@sinclair/typebox\";\nimport { beginCronFire, endCronFire, isCronFire } from \"../core/cron/fire-guard.ts\";\nimport {\n\tcreateJob,\n\tgetJob,\n\tlistJobs,\n\tparseSchedule,\n\tpauseJob,\n\tremoveJob,\n\tresumeJob,\n\tsetCronDeliverValidator,\n\tupdateJob,\n} from \"../core/cron/jobs.ts\";\nimport { currentOrigin } from \"../core/cron/origin-context.ts\";\nimport { executeJob, startScheduler } from \"../core/cron/scheduler.ts\";\nimport { loadGatewayConfig } from \"../gateway/config.ts\";\nimport { createDeliverValidator } from \"../gateway/cron.ts\";\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n/** The cron-fired turn currently waiting for agent_end. */\nlet pendingRun: { resolve: (text: string) => void; reject: (err: Error) => void } | null = null;\nlet scheduler: { stop(): void } | null = null;\nlet lastCtx: ExtensionContext | null = null;\n\nconst DELIVERY_BRIDGE_SYMBOL = Symbol.for(\"@lunr/cron-delivery\");\n\n// ---------------------------------------------------------------------------\n// Turn plumbing\n// ---------------------------------------------------------------------------\n\n/** Final assistant text from an agent_end messages array (last assistant message, text blocks only). */\nfunction extractAssistantText(messages: unknown[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i] as any;\n\t\tif (msg?.role !== \"assistant\") continue;\n\t\tconst parts = Array.isArray(msg.content) ? msg.content : [];\n\t\tconst text = parts\n\t\t\t.filter((p: any) => p?.type === \"text\")\n\t\t\t.map((p: any) => String(p.text ?? \"\"))\n\t\t\t.join(\"\")\n\t\t\t.trim();\n\t\tif (text) return text;\n\t}\n\treturn \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\nfunction fmtTime(iso: string | null): string {\n\tif (!iso) return \"-\";\n\tconst d = new Date(iso);\n\tif (Number.isNaN(d.getTime())) return \"-\";\n\tconst p = (n: number) => String(n).padStart(2, \"0\");\n\t// Stored timestamps are UTC ISO; render in local time so users read wall-clock.\n\treturn `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;\n}\n\nfunction formatJobList(): string {\n\tconst jobs = listJobs();\n\tif (jobs.length === 0) return \"No cron jobs. Create one with /cron create <schedule> <prompt>.\";\n\tconst lines = jobs.map(\n\t\t(j) =>\n\t\t\t`${j.id} ${j.state}${j.enabled ? \"\" : \" (disabled)\"} ${j.scheduleDisplay} next=${fmtTime(j.nextRunAt)} last=${j.lastStatus ?? \"-\"}${j.lastError ? ` (${j.lastError})` : \"\"} ${j.name}`,\n\t);\n\treturn `Cron jobs (${jobs.length}):\\n${lines.join(\"\\n\")}`;\n}\n\nfunction formatStatus(): string {\n\tconst jobs = listJobs();\n\tconst count = (s: string) => jobs.filter((j) => j.state === s).length;\n\tconst next = jobs\n\t\t.filter((j) => j.enabled && j.state === \"scheduled\" && j.nextRunAt)\n\t\t.sort((a, b) => String(a.nextRunAt).localeCompare(String(b.nextRunAt)))[0];\n\treturn (\n\t\t`Cron: scheduler ${scheduler ? \"running\" : \"stopped\"}; ${jobs.length} job(s) — ` +\n\t\t`${count(\"scheduled\")} scheduled, ${count(\"paused\")} paused, ${count(\"completed\")} completed, ${count(\"error\")} error.` +\n\t\t(next ? ` Next: '${next.name}' at ${fmtTime(next.nextRunAt)}.` : \"\")\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Extension\n// ---------------------------------------------------------------------------\n\nexport default function (pi: ExtensionAPI): void {\n\t// Same allowlist the gateway uses, so a TUI session cannot persist a job\n\t// that later posts to a chat the bot can reach but is not allowed.\n\tsetCronDeliverValidator(createDeliverValidator(loadGatewayConfig()));\n\n\t// --- Local delivery bridge (Phase 4 gateway replaces this) ---\n\t(globalThis as Record<symbol, unknown>)[DELIVERY_BRIDGE_SYMBOL] = async (job: { name: string }, _content: string) => {\n\t\ttry {\n\t\t\tlastCtx?.ui.notify(`Cron job '${job.name}' finished`, \"info\");\n\t\t\treturn null;\n\t\t} catch (err) {\n\t\t\treturn String((err as Error)?.message ?? err);\n\t\t}\n\t};\n\n\t// --- Scheduler deps (TUI) ---\n\tconst runJob = (prompt: string, _job: unknown): Promise<string> => {\n\t\tif (pendingRun) return Promise.reject(new Error(\"another cron job turn is already in flight\"));\n\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\tbeginCronFire();\n\t\t\tpendingRun = { resolve, reject };\n\t\t\ttry {\n\t\t\t\tpi.sendUserMessage(prompt);\n\t\t\t} catch (err) {\n\t\t\t\tpendingRun = null;\n\t\t\t\tendCronFire();\n\t\t\t\treject(err as Error);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst deliverResult = async (job: any, content: string): Promise<void> => {\n\t\tconst bridge = (globalThis as Record<symbol, unknown>)[DELIVERY_BRIDGE_SYMBOL] as\n\t\t\t| ((job: unknown, content: string) => Promise<string | null>)\n\t\t\t| undefined;\n\t\tif (!bridge) throw new Error(\"no cron delivery bridge registered\");\n\t\tconst err = await bridge(job, content);\n\t\tif (err) throw new Error(String(err));\n\t};\n\n\tconst schedulerDeps = { runJob, deliverResult };\n\n\t/** Manual trigger: run inline when idle, otherwise make the job due for the next tick. */\n\tconst triggerRun = async (job: any, ctx: ExtensionContext): Promise<string> => {\n\t\tif (ctx.isIdle()) {\n\t\t\ttry {\n\t\t\t\tawait executeJob(getJob(job.id), schedulerDeps);\n\t\t\t\treturn `Cron job '${job.name}' (${job.id}) finished.`;\n\t\t\t} catch (err) {\n\t\t\t\treturn `Cron job '${job.name}' (${job.id}) failed: ${String((err as Error)?.message ?? err)}`;\n\t\t\t}\n\t\t}\n\t\tawait updateJob(job.id, { nextRunAt: new Date().toISOString() });\n\t\treturn `Cron job '${job.name}' (${job.id}) queued for the next scheduler tick.`;\n\t};\n\n\t// --- Resolve the cron-fired turn when the agent turn ends ---\n\tpi.on(\"agent_end\", (event) => {\n\t\tif (!pendingRun) return;\n\t\tconst pending = pendingRun;\n\t\tpendingRun = null;\n\t\tendCronFire();\n\t\tpending.resolve(extractAssistantText(event.messages ?? []));\n\t});\n\n\t// --- Scheduler lifecycle: TUI sessions only ---\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\tlastCtx = ctx;\n\t\tif (ctx.mode !== \"tui\") return;\n\t\tscheduler?.stop();\n\t\tscheduler = startScheduler(schedulerDeps);\n\t});\n\n\tpi.on(\"session_shutdown\", () => {\n\t\tscheduler?.stop();\n\t\tscheduler = null;\n\t});\n\n\t// --- /cron command ---\n\tpi.registerCommand(\"cron\", {\n\t\tdescription: \"Manage cron jobs: /cron list | create <schedule> <prompt> | pause|resume|run|remove <id-or-name> | status\",\n\t\tgetArgumentCompletions: (prefix: string) => {\n\t\t\tconst subs = [\"list\", \"create\", \"pause\", \"resume\", \"run\", \"remove\", \"status\"];\n\t\t\tconst lower = prefix.toLowerCase();\n\t\t\treturn subs\n\t\t\t\t.filter((s) => s.startsWith(lower))\n\t\t\t\t.map((s) => ({ value: s, label: s, description: `/cron ${s}` }));\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tlastCtx = ctx;\n\t\t\tconst tokens = args.trim().split(/\\s+/).filter(Boolean);\n\t\t\tconst sub = (tokens.shift() ?? \"list\").toLowerCase();\n\t\t\ttry {\n\t\t\t\tswitch (sub) {\n\t\t\t\t\tcase \"list\": {\n\t\t\t\t\t\tctx.ui.notify(formatJobList(), \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"status\": {\n\t\t\t\t\t\tctx.ui.notify(formatStatus(), \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"create\": {\n\t\t\t\t\t\t// Greedy: the schedule is the shortest leading token run that parses.\n\t\t\t\t\t\tlet used = 0;\n\t\t\t\t\t\tfor (let k = 1; k <= Math.min(6, tokens.length); k++) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tparseSchedule(tokens.slice(0, k).join(\" \"));\n\t\t\t\t\t\t\t\tused = k;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// keep extending\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst prompt = tokens.slice(used).join(\" \").trim();\n\t\t\t\t\t\tif (!used || !prompt) {\n\t\t\t\t\t\t\tctx.ui.notify(\"Usage: /cron create <schedule> <prompt> — e.g. /cron create every 30m check the deploy\", \"error\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst job = await createJob({ prompt, schedule: tokens.slice(0, used).join(\" \") });\n\t\t\t\t\t\tctx.ui.notify(`Created cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`, \"info\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"pause\":\n\t\t\t\t\tcase \"resume\":\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\tcase \"run\": {\n\t\t\t\t\t\tconst idOrName = tokens.join(\" \").trim();\n\t\t\t\t\t\tif (!idOrName) {\n\t\t\t\t\t\t\tctx.ui.notify(`Usage: /cron ${sub} <id-or-name>`, \"error\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (sub === \"pause\") {\n\t\t\t\t\t\t\tconst job = await pauseJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Paused cron job '${job.name}' (${job.id}).`, \"info\");\n\t\t\t\t\t\t} else if (sub === \"resume\") {\n\t\t\t\t\t\t\tconst job = await resumeJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Resumed cron job '${job.name}' (${job.id}) — next run ${fmtTime(job.nextRunAt)}.`, \"info\");\n\t\t\t\t\t\t} else if (sub === \"remove\") {\n\t\t\t\t\t\t\tconst job = await removeJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(`Removed cron job '${job.name}' (${job.id}).`, \"info\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst job = getJob(idOrName);\n\t\t\t\t\t\t\tctx.ui.notify(await triggerRun(job, ctx), \"info\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tctx.ui.notify(\"Usage: /cron list | create <schedule> <prompt> | pause|resume|run|remove <id-or-name> | status\", \"error\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tctx.ui.notify(String((err as Error)?.message ?? err), \"error\");\n\t\t\t}\n\t\t},\n\t});\n\n\t// --- cron tool (agent-facing) ---\n\tpi.registerTool({\n\t\tname: \"cron\",\n\t\tlabel: \"Cron\",\n\t\tdescription: [\n\t\t\t\"Manage scheduled cron jobs that run prompts unattended in this session.\",\n\t\t\t\"Actions: create (needs prompt + schedule), list, update (id + fields), pause, resume, remove, run (trigger now).\",\n\t\t\t\"Schedule formats: 'every 30m' / 'every 2h' / 'every 1d' (recurring), '30m'/'2h' or an ISO timestamp (one-shot), or a 5-field cron expression.\",\n\t\t\t\"Job output is delivered automatically; the job's prompt can answer [SILENT] to suppress delivery.\",\n\t\t].join(\"\\n\"),\n\t\tparameters: Type.Object({\n\t\t\taction: Type.Union([\n\t\t\t\tType.Literal(\"create\"),\n\t\t\t\tType.Literal(\"list\"),\n\t\t\t\tType.Literal(\"update\"),\n\t\t\t\tType.Literal(\"pause\"),\n\t\t\t\tType.Literal(\"resume\"),\n\t\t\t\tType.Literal(\"remove\"),\n\t\t\t\tType.Literal(\"run\"),\n\t\t\t]),\n\t\t\tid: Type.Optional(Type.String({ description: \"Job id or unique name (all actions except create/list).\" })),\n\t\t\tname: Type.Optional(Type.String({ description: \"Display name (<=50 chars); derived from the prompt when omitted.\" })),\n\t\t\tprompt: Type.Optional(Type.String({ description: \"The prompt the job runs (create/update).\" })),\n\t\t\tschedule: Type.Optional(Type.String({ description: \"Schedule input (create/update).\" })),\n\t\t\tdeliver: Type.Optional(\n\t\t\t\tType.String({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Delivery target(s), comma-separated: 'local' (output file only), 'origin' (the chat that created the job), 'telegram'/'discord' (platform home channel), or 'telegram:<chatId>[:<threadId>]' / 'discord:<chatId>[:<threadId>]'. Defaults to 'origin' when created from a gateway chat, else 'local'.\",\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n\t\t\tconst text = (t: string) => ({ content: [{ type: \"text\" as const, text: t }] });\n\t\t\tif (isCronFire()) {\n\t\t\t\treturn text(\"cron: unavailable while a cron-fired turn is running (cron jobs cannot schedule cron jobs).\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tswitch (params.action) {\n\t\t\t\t\tcase \"create\": {\n\t\t\t\t\t\tif (!params.prompt?.trim() || !params.schedule?.trim()) {\n\t\t\t\t\t\t\treturn text(\"cron create: prompt and schedule are required.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Inside a gateway chat turn, stamp the chat as the delivery\n\t\t\t\t\t\t// origin and default deliver to \"origin\" (Phase 4); outside\n\t\t\t\t\t\t// any origin context the default stays \"local\".\n\t\t\t\t\t\tconst origin = currentOrigin();\n\t\t\t\t\t\tconst job = await createJob({\n\t\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\t\tschedule: params.schedule,\n\t\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\t\tdeliver: params.deliver ?? (origin ? \"origin\" : undefined),\n\t\t\t\t\t\t\torigin: origin ? { ...origin } : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn text(`Created cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"list\": {\n\t\t\t\t\t\treturn text(formatJobList());\n\t\t\t\t\t}\n\t\t\t\t\tcase \"update\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron update: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await updateJob(params.id, {\n\t\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\t\tschedule: params.schedule,\n\t\t\t\t\t\t\tdeliver: params.deliver,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn text(`Updated cron job '${job.name}' (${job.id}) — ${job.scheduleDisplay}, next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"pause\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron pause: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await pauseJob(params.id);\n\t\t\t\t\t\treturn text(`Paused cron job '${job.name}' (${job.id}).`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"resume\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron resume: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await resumeJob(params.id);\n\t\t\t\t\t\treturn text(`Resumed cron job '${job.name}' (${job.id}) — next run ${fmtTime(job.nextRunAt)}.`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"remove\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron remove: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = await removeJob(params.id);\n\t\t\t\t\t\treturn text(`Removed cron job '${job.name}' (${job.id}).`);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"run\": {\n\t\t\t\t\t\tif (!params.id) return text(\"cron run: id (or unique name) is required.\");\n\t\t\t\t\t\tconst job = getJob(params.id);\n\t\t\t\t\t\treturn text(await triggerRun(job, ctx));\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn text(`cron: unknown action \"${String(params.action)}\".`);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\treturn text(`cron: ${String((err as Error)?.message ?? err)}`);\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fanout-child.d.ts","sourceRoot":"","sources":["../../../../../src/builtin-extensions/pi-subagents/src/extension/fanout-child.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,iCAAiC,CAAC;AA+HpF,MAAM,CAAC,OAAO,UAAU,oCAAoC,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA2CnF","sourcesContent":["// @ts-nocheck\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ExtensionAPI, ToolDefinition } from \"@ashx-j/lunr\";\nimport { discoverAgents } from \"../agents/agents.ts\";\nimport { getArtifactsDir } from \"../shared/artifacts.ts\";\nimport { createSubagentExecutor, type SubagentParamsLike } from \"../runs/foreground/subagent-executor.ts\";\nimport { resolveWaitToolConfig } from \"../runs/background/wait-config.ts\";\nimport { SUBAGENT_CHILD_ENV, SUBAGENT_FANOUT_CHILD_ENV } from \"../runs/shared/pi-args.ts\";\nimport { readNestedControlRequests, resolveNestedRouteFromEnv, writeNestedControlResult } from \"../runs/shared/nested-events.ts\";\nimport { deliverSubagentIntercomMessageEvent } from \"../intercom/result-intercom.ts\";\nimport { resolveSubagentIntercomTarget } from \"../intercom/intercom-bridge.ts\";\nimport { SubagentParams } from \"./schemas.ts\";\nimport { loadConfig } from \"./config.ts\";\nimport { type Details, type SubagentState } from \"../shared/types.ts\";\n\nfunction getSubagentSessionRoot(parentSessionFile: string | null): string {\n\tif (parentSessionFile) {\n\t\tconst baseName = path.basename(parentSessionFile, \".jsonl\");\n\t\tconst sessionsDir = path.dirname(parentSessionFile);\n\t\treturn path.join(sessionsDir, baseName);\n\t}\n\treturn fs.mkdtempSync(path.join(os.tmpdir(), \"pi-subagent-session-\"));\n}\n\nfunction expandTilde(p: string): string {\n\treturn p.startsWith(\"~/\") ? path.join(os.homedir(), p.slice(2)) : p;\n}\n\nfunction createChildSafeState(): SubagentState {\n\treturn {\n\t\tbaseCwd: \"\",\n\t\tcurrentSessionId: null,\n\t\tsubagentInProgress: false,\n\t\tsubagentSpawns: { sessionId: null, count: 0 },\n\t\tasyncJobs: new Map(),\n\t\tforegroundRuns: new Map(),\n\t\tforegroundControls: new Map(),\n\t\tlastForegroundControlId: null,\n\t\tpendingForegroundControlNotices: new Map(),\n\t\tcleanupTimers: new Map(),\n\t\tlastUiContext: null,\n\t\tpoller: null,\n\t\tcompletionSeen: new Map(),\n\t\twatcher: null,\n\t\twatcherRestartTimer: null,\n\t\tresultFileCoalescer: {\n\t\t\tschedule: () => false,\n\t\t\tclear: () => {},\n\t\t},\n\t};\n}\n\nfunction startNestedControlInboxListener(pi: ExtensionAPI, state: SubagentState): NodeJS.Timeout | undefined {\n\tlet route;\n\ttry {\n\t\troute = resolveNestedRouteFromEnv();\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (!route) return undefined;\n\tconst seen = new Set<string>();\n\tconst inFlight = new Set<string>();\n\tconst pendingResults = new Map<string, Parameters<typeof writeNestedControlResult>[1]>();\n\tconst timer = setInterval(() => {\n\t\ttry {\n\t\t\tfor (const request of readNestedControlRequests(route)) {\n\t\t\t\tif (seen.has(request.requestId) || inFlight.has(request.requestId)) continue;\n\t\t\t\tinFlight.add(request.requestId);\n\t\t\t\tvoid (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet result = pendingResults.get(request.requestId);\n\t\t\t\t\t\tif (!result) {\n\t\t\t\t\t\t\tlet ok = false;\n\t\t\t\t\t\t\tlet message = \"Control request failed.\";\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst control = state.foregroundControls.get(request.targetRunId);\n\t\t\t\t\t\t\t\tif (!control) {\n\t\t\t\t\t\t\t\t\tmessage = `Nested run ${request.targetRunId} is not active in this fanout child.`;\n\t\t\t\t\t\t\t\t} else if (request.action === \"interrupt\") {\n\t\t\t\t\t\t\t\t\tok = control.interrupt?.() === true;\n\t\t\t\t\t\t\t\t\tmessage = ok\n\t\t\t\t\t\t\t\t\t\t? `Interrupt requested for nested run ${request.targetRunId}.`\n\t\t\t\t\t\t\t\t\t\t: `Nested run ${request.targetRunId} has no active child step to interrupt.`;\n\t\t\t\t\t\t\t\t} else if (!request.message?.trim()) {\n\t\t\t\t\t\t\t\t\tmessage = \"Nested resume requires message.\";\n\t\t\t\t\t\t\t\t} else if (!control.currentAgent) {\n\t\t\t\t\t\t\t\t\tmessage = `Nested run ${request.targetRunId} has no active child message route.`;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tconst index = control.currentIndex ?? 0;\n\t\t\t\t\t\t\t\t\tconst target = resolveSubagentIntercomTarget(request.targetRunId, control.currentAgent, index);\n\t\t\t\t\t\t\t\t\tok = await deliverSubagentIntercomMessageEvent(\n\t\t\t\t\t\t\t\t\t\tpi.events,\n\t\t\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\t\t\t`Follow-up for nested run ${request.targetRunId} (${control.currentAgent}):\\n\\n${request.message.trim()}`,\n\t\t\t\t\t\t\t\t\t\t500,\n\t\t\t\t\t\t\t\t\t\t{ source: \"nested-resume\", runId: request.targetRunId, agent: control.currentAgent, index },\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tmessage = ok\n\t\t\t\t\t\t\t\t\t\t? `Delivered follow-up to live nested run ${request.targetRunId}.`\n\t\t\t\t\t\t\t\t\t\t: `Nested child intercom target is not registered: ${target}`;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tmessage = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresult = { ts: Date.now(), requestId: request.requestId, targetRunId: request.targetRunId, ok, message };\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twriteNestedControlResult(route, result);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tpendingResults.set(request.requestId, result);\n\t\t\t\t\t\t\tconsole.error(`Failed to write nested control result for request '${request.requestId}' targeting '${request.targetRunId}' via inbox '${route.controlInbox}'; keeping request for retry:`, error);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpendingResults.delete(request.requestId);\n\t\t\t\t\t\tseen.add(request.requestId);\n\t\t\t\t\t\ttry { fs.unlinkSync(request.filePath); } catch {}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tinFlight.delete(request.requestId);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to poll nested control inbox '${route.controlInbox}' for root '${route.rootRunId}':`, error);\n\t\t}\n\t}, 200);\n\ttimer.unref?.();\n\treturn timer;\n}\n\nexport default function registerFanoutChildSubagentExtension(pi: ExtensionAPI): void {\n\tif (process.env[SUBAGENT_CHILD_ENV] !== \"1\" || process.env[SUBAGENT_FANOUT_CHILD_ENV] !== \"1\") return;\n\n\tconst globalStore = globalThis as Record<string, unknown>;\n\tconst registeredKey = \"__piSubagentFanoutChildRegisteredApis\";\n\tconst registeredApis = globalStore[registeredKey] instanceof WeakSet\n\t\t? globalStore[registeredKey] as WeakSet<ExtensionAPI>\n\t\t: new WeakSet<ExtensionAPI>();\n\tglobalStore[registeredKey] = registeredApis;\n\tif (registeredApis.has(pi)) return;\n\tregisteredApis.add(pi);\n\n\tconst config = loadConfig();\n\tconst state = createChildSafeState();\n\tconst executor = createSubagentExecutor({\n\t\tpi,\n\t\tstate,\n\t\tconfig,\n\t\tasyncByDefault: config.asyncByDefault === true,\n\t\twaitToolEnabled: resolveWaitToolConfig(config.waitTool).enabled,\n\t\ttempArtifactsDir: getArtifactsDir(null),\n\t\tgetSubagentSessionRoot,\n\t\texpandTilde,\n\t\tdiscoverAgents,\n\t\tallowMutatingManagementActions: false,\n\t});\n\n\tconst tool: ToolDefinition<typeof SubagentParams, Details> = {\n\t\tname: \"subagent\",\n\t\tlabel: \"Subagent\",\n\t\tdescription: [\n\t\t\t\"Delegate to subagents from child-safe fanout mode.\",\n\t\t\t\"Allowed management/control actions: list, get, status, interrupt, resume, steer, append-step, doctor.\",\n\t\t\t\"Agent config mutation actions (create, update, delete, eject, disable, enable, reset) are blocked in this mode.\",\n\t\t].join(\"\\n\"),\n\t\tparameters: SubagentParams,\n\t\texecute(id, params, signal, onUpdate, ctx) {\n\t\t\treturn executor.execute(id, params as SubagentParamsLike, signal, onUpdate, ctx);\n\t\t},\n\t};\n\n\tpi.registerTool(tool);\n\tstartNestedControlInboxListener(pi, state);\n}\n"]}
1
+ {"version":3,"file":"fanout-child.d.ts","sourceRoot":"","sources":["../../../../../src/builtin-extensions/pi-subagents/src/extension/fanout-child.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,iCAAiC,CAAC;AA+HpF,MAAM,CAAC,OAAO,UAAU,oCAAoC,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA2CnF","sourcesContent":["// @ts-nocheck\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ExtensionAPI, ToolDefinition } from \"@ashx-j/lunr\";\nimport { discoverAgents } from \"../agents/agents.ts\";\nimport { getArtifactsDir } from \"../shared/artifacts.ts\";\nimport { createSubagentExecutor, type SubagentParamsLike } from \"../runs/foreground/subagent-executor.ts\";\nimport { resolveWaitToolConfig } from \"../runs/background/wait-config.ts\";\nimport { SUBAGENT_CHILD_ENV, SUBAGENT_FANOUT_CHILD_ENV } from \"../runs/shared/pi-args.ts\";\nimport { readNestedControlRequests, resolveNestedRouteFromEnv, writeNestedControlResult } from \"../runs/shared/nested-events.ts\";\nimport { deliverSubagentIntercomMessageEvent } from \"../intercom/result-intercom.ts\";\nimport { resolveSubagentIntercomTarget } from \"../intercom/intercom-bridge.ts\";\nimport { SubagentParams } from \"./schemas.ts\";\nimport { loadConfig } from \"./config.ts\";\nimport { type Details, type SubagentState } from \"../shared/types.ts\";\n\nfunction getSubagentSessionRoot(parentSessionFile: string | null): string {\n\tif (parentSessionFile) {\n\t\tconst baseName = path.basename(parentSessionFile, \".jsonl\");\n\t\tconst sessionsDir = path.dirname(parentSessionFile);\n\t\treturn path.join(sessionsDir, baseName);\n\t}\n\treturn fs.mkdtempSync(path.join(os.tmpdir(), \"pi-subagent-session-\"));\n}\n\nfunction expandTilde(p: string): string {\n\treturn p.startsWith(\"~/\") ? path.join(os.homedir(), p.slice(2)) : p;\n}\n\nfunction createChildSafeState(): SubagentState {\n\treturn {\n\t\tbaseCwd: \"\",\n\t\tcurrentSessionId: null,\n\t\tforegroundSubagentInFlight: 0,\n\t\tsubagentSpawns: { sessionId: null, count: 0 },\n\t\tasyncJobs: new Map(),\n\t\tforegroundRuns: new Map(),\n\t\tforegroundControls: new Map(),\n\t\tlastForegroundControlId: null,\n\t\tpendingForegroundControlNotices: new Map(),\n\t\tcleanupTimers: new Map(),\n\t\tlastUiContext: null,\n\t\tpoller: null,\n\t\tcompletionSeen: new Map(),\n\t\twatcher: null,\n\t\twatcherRestartTimer: null,\n\t\tresultFileCoalescer: {\n\t\t\tschedule: () => false,\n\t\t\tclear: () => {},\n\t\t},\n\t};\n}\n\nfunction startNestedControlInboxListener(pi: ExtensionAPI, state: SubagentState): NodeJS.Timeout | undefined {\n\tlet route;\n\ttry {\n\t\troute = resolveNestedRouteFromEnv();\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (!route) return undefined;\n\tconst seen = new Set<string>();\n\tconst inFlight = new Set<string>();\n\tconst pendingResults = new Map<string, Parameters<typeof writeNestedControlResult>[1]>();\n\tconst timer = setInterval(() => {\n\t\ttry {\n\t\t\tfor (const request of readNestedControlRequests(route)) {\n\t\t\t\tif (seen.has(request.requestId) || inFlight.has(request.requestId)) continue;\n\t\t\t\tinFlight.add(request.requestId);\n\t\t\t\tvoid (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet result = pendingResults.get(request.requestId);\n\t\t\t\t\t\tif (!result) {\n\t\t\t\t\t\t\tlet ok = false;\n\t\t\t\t\t\t\tlet message = \"Control request failed.\";\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst control = state.foregroundControls.get(request.targetRunId);\n\t\t\t\t\t\t\t\tif (!control) {\n\t\t\t\t\t\t\t\t\tmessage = `Nested run ${request.targetRunId} is not active in this fanout child.`;\n\t\t\t\t\t\t\t\t} else if (request.action === \"interrupt\") {\n\t\t\t\t\t\t\t\t\tok = control.interrupt?.() === true;\n\t\t\t\t\t\t\t\t\tmessage = ok\n\t\t\t\t\t\t\t\t\t\t? `Interrupt requested for nested run ${request.targetRunId}.`\n\t\t\t\t\t\t\t\t\t\t: `Nested run ${request.targetRunId} has no active child step to interrupt.`;\n\t\t\t\t\t\t\t\t} else if (!request.message?.trim()) {\n\t\t\t\t\t\t\t\t\tmessage = \"Nested resume requires message.\";\n\t\t\t\t\t\t\t\t} else if (!control.currentAgent) {\n\t\t\t\t\t\t\t\t\tmessage = `Nested run ${request.targetRunId} has no active child message route.`;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tconst index = control.currentIndex ?? 0;\n\t\t\t\t\t\t\t\t\tconst target = resolveSubagentIntercomTarget(request.targetRunId, control.currentAgent, index);\n\t\t\t\t\t\t\t\t\tok = await deliverSubagentIntercomMessageEvent(\n\t\t\t\t\t\t\t\t\t\tpi.events,\n\t\t\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\t\t\t`Follow-up for nested run ${request.targetRunId} (${control.currentAgent}):\\n\\n${request.message.trim()}`,\n\t\t\t\t\t\t\t\t\t\t500,\n\t\t\t\t\t\t\t\t\t\t{ source: \"nested-resume\", runId: request.targetRunId, agent: control.currentAgent, index },\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tmessage = ok\n\t\t\t\t\t\t\t\t\t\t? `Delivered follow-up to live nested run ${request.targetRunId}.`\n\t\t\t\t\t\t\t\t\t\t: `Nested child intercom target is not registered: ${target}`;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tmessage = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresult = { ts: Date.now(), requestId: request.requestId, targetRunId: request.targetRunId, ok, message };\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twriteNestedControlResult(route, result);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tpendingResults.set(request.requestId, result);\n\t\t\t\t\t\t\tconsole.error(`Failed to write nested control result for request '${request.requestId}' targeting '${request.targetRunId}' via inbox '${route.controlInbox}'; keeping request for retry:`, error);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpendingResults.delete(request.requestId);\n\t\t\t\t\t\tseen.add(request.requestId);\n\t\t\t\t\t\ttry { fs.unlinkSync(request.filePath); } catch {}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tinFlight.delete(request.requestId);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to poll nested control inbox '${route.controlInbox}' for root '${route.rootRunId}':`, error);\n\t\t}\n\t}, 200);\n\ttimer.unref?.();\n\treturn timer;\n}\n\nexport default function registerFanoutChildSubagentExtension(pi: ExtensionAPI): void {\n\tif (process.env[SUBAGENT_CHILD_ENV] !== \"1\" || process.env[SUBAGENT_FANOUT_CHILD_ENV] !== \"1\") return;\n\n\tconst globalStore = globalThis as Record<string, unknown>;\n\tconst registeredKey = \"__piSubagentFanoutChildRegisteredApis\";\n\tconst registeredApis = globalStore[registeredKey] instanceof WeakSet\n\t\t? globalStore[registeredKey] as WeakSet<ExtensionAPI>\n\t\t: new WeakSet<ExtensionAPI>();\n\tglobalStore[registeredKey] = registeredApis;\n\tif (registeredApis.has(pi)) return;\n\tregisteredApis.add(pi);\n\n\tconst config = loadConfig();\n\tconst state = createChildSafeState();\n\tconst executor = createSubagentExecutor({\n\t\tpi,\n\t\tstate,\n\t\tconfig,\n\t\tasyncByDefault: config.asyncByDefault === true,\n\t\twaitToolEnabled: resolveWaitToolConfig(config.waitTool).enabled,\n\t\ttempArtifactsDir: getArtifactsDir(null),\n\t\tgetSubagentSessionRoot,\n\t\texpandTilde,\n\t\tdiscoverAgents,\n\t\tallowMutatingManagementActions: false,\n\t});\n\n\tconst tool: ToolDefinition<typeof SubagentParams, Details> = {\n\t\tname: \"subagent\",\n\t\tlabel: \"Subagent\",\n\t\tdescription: [\n\t\t\t\"Delegate to subagents from child-safe fanout mode.\",\n\t\t\t\"Allowed management/control actions: list, get, status, interrupt, resume, steer, append-step, doctor.\",\n\t\t\t\"Agent config mutation actions (create, update, delete, eject, disable, enable, reset) are blocked in this mode.\",\n\t\t].join(\"\\n\"),\n\t\tparameters: SubagentParams,\n\t\texecute(id, params, signal, onUpdate, ctx) {\n\t\t\treturn executor.execute(id, params as SubagentParamsLike, signal, onUpdate, ctx);\n\t\t},\n\t};\n\n\tpi.registerTool(tool);\n\tstartNestedControlInboxListener(pi, state);\n}\n"]}
@@ -27,7 +27,7 @@ function createChildSafeState() {
27
27
  return {
28
28
  baseCwd: "",
29
29
  currentSessionId: null,
30
- subagentInProgress: false,
30
+ foregroundSubagentInFlight: 0,
31
31
  subagentSpawns: { sessionId: null, count: 0 },
32
32
  asyncJobs: new Map(),
33
33
  foregroundRuns: new Map(),