@oh-my-pi/pi-coding-agent 15.7.5 → 15.8.0

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 (146) hide show
  1. package/CHANGELOG.md +159 -182
  2. package/dist/types/async/job-manager.d.ts +3 -3
  3. package/dist/types/cli/args.d.ts +1 -0
  4. package/dist/types/cli/claude-trace-cli.d.ts +54 -0
  5. package/dist/types/cli/session-picker.d.ts +10 -3
  6. package/dist/types/cli/update-cli.d.ts +17 -0
  7. package/dist/types/commands/launch.d.ts +3 -0
  8. package/dist/types/config/keybindings.d.ts +5 -0
  9. package/dist/types/config/settings-schema.d.ts +11 -2
  10. package/dist/types/config/settings.d.ts +13 -0
  11. package/dist/types/eval/__tests__/heartbeat.test.d.ts +1 -0
  12. package/dist/types/eval/concurrency-bridge.d.ts +26 -0
  13. package/dist/types/eval/heartbeat.d.ts +45 -0
  14. package/dist/types/eval/js/tool-bridge.d.ts +2 -1
  15. package/dist/types/extensibility/extensions/loader.d.ts +2 -2
  16. package/dist/types/extensibility/extensions/runner.d.ts +2 -1
  17. package/dist/types/extensibility/extensions/types.d.ts +24 -5
  18. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +11 -0
  19. package/dist/types/lsp/diagnostics-ledger.d.ts +10 -0
  20. package/dist/types/lsp/index.d.ts +2 -0
  21. package/dist/types/lsp/utils.d.ts +4 -0
  22. package/dist/types/main.d.ts +5 -0
  23. package/dist/types/modes/acp/acp-agent.d.ts +1 -1
  24. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  25. package/dist/types/modes/components/custom-editor.d.ts +3 -2
  26. package/dist/types/modes/components/hook-selector.d.ts +10 -1
  27. package/dist/types/modes/components/session-selector.d.ts +32 -5
  28. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  29. package/dist/types/modes/controllers/extension-ui-controller.d.ts +3 -3
  30. package/dist/types/modes/controllers/input-controller.d.ts +1 -0
  31. package/dist/types/modes/interactive-mode.d.ts +10 -3
  32. package/dist/types/modes/rpc/rpc-mode.d.ts +1 -1
  33. package/dist/types/modes/theme/theme.d.ts +1 -1
  34. package/dist/types/modes/types.d.ts +5 -3
  35. package/dist/types/registry/agent-registry.d.ts +1 -1
  36. package/dist/types/sdk.d.ts +2 -2
  37. package/dist/types/session/agent-session.d.ts +12 -3
  38. package/dist/types/session/history-storage.d.ts +16 -1
  39. package/dist/types/session/session-manager.d.ts +4 -0
  40. package/dist/types/task/output-manager.d.ts +6 -15
  41. package/dist/types/tools/ask.d.ts +8 -6
  42. package/dist/types/tools/eval-backends.d.ts +12 -0
  43. package/dist/types/tools/eval-render.d.ts +52 -0
  44. package/dist/types/tools/eval.d.ts +2 -35
  45. package/dist/types/tools/find.d.ts +0 -9
  46. package/dist/types/tools/index.d.ts +5 -12
  47. package/dist/types/tools/path-utils.d.ts +16 -0
  48. package/dist/types/tools/sqlite-reader.d.ts +25 -8
  49. package/dist/types/tui/output-block.d.ts +4 -3
  50. package/dist/types/utils/clipboard.d.ts +4 -0
  51. package/dist/types/web/kagi.d.ts +76 -0
  52. package/dist/types/web/search/providers/exa.d.ts +7 -1
  53. package/dist/types/web/search/providers/kagi.d.ts +1 -0
  54. package/examples/extensions/README.md +1 -0
  55. package/examples/extensions/thinking-note.ts +13 -0
  56. package/package.json +9 -9
  57. package/src/async/job-manager.ts +3 -3
  58. package/src/cli/args.ts +6 -2
  59. package/src/cli/claude-trace-cli.ts +783 -0
  60. package/src/cli/session-picker.ts +36 -10
  61. package/src/cli/update-cli.ts +35 -2
  62. package/src/commands/launch.ts +3 -0
  63. package/src/config/keybindings.ts +6 -0
  64. package/src/config/model-registry.ts +33 -4
  65. package/src/config/settings-schema.ts +12 -2
  66. package/src/config/settings.ts +23 -0
  67. package/src/discovery/claude-plugins.ts +7 -9
  68. package/src/discovery/claude.ts +41 -22
  69. package/src/edit/index.ts +23 -3
  70. package/src/eval/__tests__/agent-bridge.test.ts +148 -4
  71. package/src/eval/__tests__/heartbeat.test.ts +84 -0
  72. package/src/eval/__tests__/llm-bridge.test.ts +30 -0
  73. package/src/eval/agent-bridge.ts +44 -38
  74. package/src/eval/concurrency-bridge.ts +34 -0
  75. package/src/eval/heartbeat.ts +74 -0
  76. package/src/eval/js/executor.ts +13 -9
  77. package/src/eval/js/shared/prelude.txt +20 -17
  78. package/src/eval/js/tool-bridge.ts +5 -0
  79. package/src/eval/llm-bridge.ts +20 -14
  80. package/src/eval/py/executor.ts +14 -18
  81. package/src/eval/py/prelude.py +23 -15
  82. package/src/exec/bash-executor.ts +31 -5
  83. package/src/extensibility/extensions/loader.ts +16 -18
  84. package/src/extensibility/extensions/runner.ts +22 -17
  85. package/src/extensibility/extensions/types.ts +39 -5
  86. package/src/extensibility/plugins/legacy-pi-compat.ts +115 -131
  87. package/src/extensibility/skills.ts +0 -1
  88. package/src/internal-urls/docs-index.generated.ts +14 -13
  89. package/src/lsp/diagnostics-ledger.ts +51 -0
  90. package/src/lsp/index.ts +9 -22
  91. package/src/lsp/utils.ts +21 -0
  92. package/src/main.ts +92 -24
  93. package/src/modes/acp/acp-agent.ts +8 -4
  94. package/src/modes/acp/acp-event-mapper.ts +54 -4
  95. package/src/modes/components/assistant-message.ts +28 -1
  96. package/src/modes/components/custom-editor.ts +19 -7
  97. package/src/modes/components/hook-selector.ts +229 -44
  98. package/src/modes/components/oauth-selector.ts +12 -6
  99. package/src/modes/components/session-selector.ts +179 -24
  100. package/src/modes/components/tool-execution.ts +36 -7
  101. package/src/modes/controllers/command-controller.ts +2 -11
  102. package/src/modes/controllers/event-controller.ts +5 -2
  103. package/src/modes/controllers/extension-ui-controller.ts +6 -4
  104. package/src/modes/controllers/input-controller.ts +19 -16
  105. package/src/modes/controllers/selector-controller.ts +61 -21
  106. package/src/modes/interactive-mode.ts +127 -16
  107. package/src/modes/rpc/rpc-mode.ts +17 -6
  108. package/src/modes/theme/theme-schema.json +30 -0
  109. package/src/modes/theme/theme.ts +39 -2
  110. package/src/modes/types.ts +7 -3
  111. package/src/modes/utils/ui-helpers.ts +5 -2
  112. package/src/prompts/system/orchestrate-notice.md +5 -3
  113. package/src/prompts/system/workflow-notice.md +2 -2
  114. package/src/prompts/tools/ask.md +2 -1
  115. package/src/prompts/tools/eval.md +6 -6
  116. package/src/prompts/tools/find.md +1 -1
  117. package/src/prompts/tools/irc.md +6 -6
  118. package/src/prompts/tools/search.md +1 -1
  119. package/src/prompts/tools/task.md +1 -1
  120. package/src/registry/agent-registry.ts +1 -1
  121. package/src/sdk.ts +85 -31
  122. package/src/session/agent-session.ts +127 -57
  123. package/src/session/history-storage.ts +56 -12
  124. package/src/session/session-manager.ts +34 -0
  125. package/src/task/output-manager.ts +40 -48
  126. package/src/task/render.ts +3 -8
  127. package/src/tools/ask.ts +74 -32
  128. package/src/tools/browser/tab-worker.ts +8 -5
  129. package/src/tools/eval-backends.ts +38 -0
  130. package/src/tools/eval-render.ts +750 -0
  131. package/src/tools/eval.ts +27 -754
  132. package/src/tools/find.ts +5 -29
  133. package/src/tools/index.ts +8 -38
  134. package/src/tools/path-utils.ts +144 -1
  135. package/src/tools/read.ts +47 -0
  136. package/src/tools/renderers.ts +1 -1
  137. package/src/tools/search.ts +2 -27
  138. package/src/tools/sqlite-reader.ts +92 -9
  139. package/src/tools/write.ts +9 -1
  140. package/src/tui/output-block.ts +5 -4
  141. package/src/utils/clipboard.ts +38 -1
  142. package/src/utils/open.ts +37 -2
  143. package/src/web/kagi.ts +168 -49
  144. package/src/web/search/providers/anthropic.ts +1 -1
  145. package/src/web/search/providers/exa.ts +20 -86
  146. package/src/web/search/providers/kagi.ts +4 -0
@@ -34,6 +34,14 @@ export declare class ToolExecutionComponent extends Container {
34
34
  * This triggers an immediate final diff computation for edit-like tools.
35
35
  */
36
36
  setArgsComplete(_toolCallId?: string): void;
37
+ /**
38
+ * Await the streaming diff recompute kicked off by the most recent
39
+ * `updateArgs`/`setArgsComplete`. The recompute reads the file and re-runs the
40
+ * whole-file Myers diff off the render path, signalling completion only via a
41
+ * throttled `requestRender`. Tests await this to sample a *settled* preview
42
+ * deterministically instead of racing the spinner's render ticks.
43
+ */
44
+ whenPreviewSettled(): Promise<void>;
37
45
  updateResult(result: {
38
46
  content: Array<{
39
47
  type: string;
@@ -1,9 +1,9 @@
1
1
  import type { Component, TUI } from "@oh-my-pi/pi-tui";
2
2
  import { KeybindingsManager } from "../../config/keybindings";
3
- import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetContent, ExtensionWidgetOptions, TerminalInputHandler } from "../../extensibility/extensions";
3
+ import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionUISelectItem, ExtensionWidgetContent, ExtensionWidgetOptions, TerminalInputHandler } from "../../extensibility/extensions";
4
4
  import { type HookSelectorSlider } from "../../modes/components/hook-selector";
5
5
  import { type Theme } from "../../modes/theme/theme";
6
- import type { InteractiveModeContext } from "../../modes/types";
6
+ import type { InteractiveModeContext, InteractiveSelectorDialogOptions } from "../../modes/types";
7
7
  export declare class ExtensionUiController {
8
8
  #private;
9
9
  private ctx;
@@ -30,7 +30,7 @@ export declare class ExtensionUiController {
30
30
  /**
31
31
  * Show a selector for hooks.
32
32
  */
33
- showHookSelector(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions, extra?: {
33
+ showHookSelector(title: string, options: ExtensionUISelectItem[], dialogOptions?: InteractiveSelectorDialogOptions, extra?: {
34
34
  slider?: HookSelectorSlider;
35
35
  }): Promise<string | undefined>;
36
36
  /**
@@ -18,6 +18,7 @@ export declare class InputController {
18
18
  }): number;
19
19
  handleBackgroundCommand(): void;
20
20
  handleImagePaste(): Promise<boolean>;
21
+ handleClipboardTextRawPaste(): Promise<void>;
21
22
  createAutocompleteProvider(commands: SlashCommand[], basePath: string): AutocompleteProvider;
22
23
  /** Copy the current editor line to the system clipboard. */
23
24
  handleCopyCurrentLine(): void;
@@ -5,7 +5,7 @@ import type { Component, EditorTheme } from "@oh-my-pi/pi-tui";
5
5
  import { Container, Loader, Spacer, Text, TUI } from "@oh-my-pi/pi-tui";
6
6
  import { KeybindingsManager } from "../config/keybindings";
7
7
  import { Settings } from "../config/settings";
8
- import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetContent, ExtensionWidgetOptions } from "../extensibility/extensions";
8
+ import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionUISelectItem, ExtensionWidgetContent, ExtensionWidgetOptions } from "../extensibility/extensions";
9
9
  import type { CompactOptions } from "../extensibility/extensions/types";
10
10
  import { type PlanApprovalDetails } from "../plan-mode/approved-plan";
11
11
  import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
@@ -26,7 +26,7 @@ import type { ToolExecutionHandle } from "./components/tool-execution";
26
26
  import { type LoopLimitRuntime } from "./loop-limit";
27
27
  import { OAuthManualInputManager } from "./oauth-manual-input";
28
28
  import type { Theme } from "./theme/theme";
29
- import type { CompactionQueuedMessage, InteractiveModeContext, InteractiveModeInitOptions, SubmittedUserInput, TodoItem, TodoPhase } from "./types";
29
+ import type { CompactionQueuedMessage, InteractiveModeContext, InteractiveModeInitOptions, InteractiveSelectorDialogOptions, SubmittedUserInput, TodoItem, TodoPhase } from "./types";
30
30
  /** Options for creating an InteractiveMode instance (for future API use) */
31
31
  export interface InteractiveModeOptions {
32
32
  /** Providers that were migrated during startup */
@@ -112,6 +112,13 @@ export declare class InteractiveMode implements InteractiveModeContext {
112
112
  init(options?: InteractiveModeInitOptions): Promise<void>;
113
113
  /** Reload slash commands and autocomplete for the provided working directory. */
114
114
  refreshSlashCommandState(cwd?: string): Promise<void>;
115
+ /**
116
+ * Re-point the process and every cwd-derived cache at `newCwd` after the
117
+ * active session's working directory changed (`/move` relocation or resuming
118
+ * a session from another project). The SessionManager's cwd MUST already
119
+ * reflect `newCwd` before this is called.
120
+ */
121
+ applyCwdChange(newCwd: string): Promise<void>;
115
122
  getUserInput(): Promise<SubmittedUserInput>;
116
123
  disableLoopMode(message?: string): void;
117
124
  /**
@@ -253,7 +260,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
253
260
  emitCustomToolSessionEvent(reason: "start" | "switch" | "branch" | "tree" | "shutdown", previousSessionFile?: string): Promise<void>;
254
261
  setHookWidget(key: string, content: ExtensionWidgetContent, options?: ExtensionWidgetOptions): void;
255
262
  setHookStatus(key: string, text: string | undefined): void;
256
- showHookSelector(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions, extra?: {
263
+ showHookSelector(title: string, options: ExtensionUISelectItem[], dialogOptions?: InteractiveSelectorDialogOptions, extra?: {
257
264
  slider?: HookSelectorSlider;
258
265
  }): Promise<string | undefined>;
259
266
  hideHookSelector(): void;
@@ -1,4 +1,4 @@
1
- import type { ExtensionUIContext, ExtensionUIDialogOptions } from "../../extensibility/extensions";
1
+ import { type ExtensionUIContext, type ExtensionUIDialogOptions } from "../../extensibility/extensions";
2
2
  import type { AgentSession } from "../../session/agent-session";
3
3
  import type { RpcExtensionUIRequest, RpcExtensionUIResponse, RpcHostToolCallRequest, RpcHostToolCancelRequest, RpcHostUriCancelRequest, RpcHostUriRequest, RpcResponse } from "./rpc-types";
4
4
  export type * from "./rpc-types";
@@ -17,7 +17,7 @@ export declare class Theme {
17
17
  #private;
18
18
  private readonly mode;
19
19
  private readonly symbolPreset;
20
- constructor(fgColors: Record<ThemeColor, string | number>, bgColors: Record<ThemeBg, string | number>, mode: ColorMode, symbolPreset: SymbolPreset, symbolOverrides: Partial<Record<SymbolKey, string>>);
20
+ constructor(fgColors: Record<ThemeColor, string | number>, bgColors: Record<ThemeBg, string | number>, mode: ColorMode, symbolPreset: SymbolPreset, symbolOverrides: Partial<Record<SymbolKey, string>>, spinnerFramesOverrides?: Partial<Record<SpinnerType, string[]>>);
21
21
  fg(color: ThemeColor, text: string): string;
22
22
  bg(color: ThemeBg, text: string): string;
23
23
  bold(text: string): string;
@@ -4,7 +4,7 @@ import type { AssistantMessage, ImageContent, Message, UsageReport } from "@oh-m
4
4
  import type { Component, Container, EditorTheme, Loader, Spacer, Text, TUI } from "@oh-my-pi/pi-tui";
5
5
  import type { KeybindingsManager } from "../config/keybindings";
6
6
  import type { Settings } from "../config/settings";
7
- import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetContent, ExtensionWidgetOptions } from "../extensibility/extensions";
7
+ import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionUISelectItem, ExtensionWidgetContent, ExtensionWidgetOptions } from "../extensibility/extensions";
8
8
  import type { CompactOptions } from "../extensibility/extensions/types";
9
9
  import type { MCPManager } from "../mcp";
10
10
  import type { PlanApprovalDetails } from "../plan-mode/approved-plan";
@@ -19,7 +19,7 @@ import type { CustomEditor } from "./components/custom-editor";
19
19
  import type { EvalExecutionComponent } from "./components/eval-execution";
20
20
  import type { HookEditorComponent } from "./components/hook-editor";
21
21
  import type { HookInputComponent } from "./components/hook-input";
22
- import type { HookSelectorComponent } from "./components/hook-selector";
22
+ import type { HookSelectorComponent, HookSelectorOptions } from "./components/hook-selector";
23
23
  import type { StatusLineComponent } from "./components/status-line";
24
24
  import type { ToolExecutionHandle } from "./components/tool-execution";
25
25
  import type { LoopLimitRuntime } from "./loop-limit";
@@ -51,6 +51,7 @@ export type TodoPhase = {
51
51
  export interface InteractiveModeInitOptions {
52
52
  suppressWelcomeIntro?: boolean;
53
53
  }
54
+ export type InteractiveSelectorDialogOptions = ExtensionUIDialogOptions & Pick<HookSelectorOptions, "disabledIndices">;
54
55
  export interface InteractiveModeContext {
55
56
  ui: TUI;
56
57
  chatContainer: Container;
@@ -217,6 +218,7 @@ export interface InteractiveModeContext {
217
218
  executeCompaction(customInstructionsOrOptions?: string | CompactOptions, isAuto?: boolean): Promise<CompactionOutcome>;
218
219
  openInBrowser(urlOrPath: string): void;
219
220
  refreshSlashCommandState(cwd?: string): Promise<void>;
221
+ applyCwdChange(newCwd: string): Promise<void>;
220
222
  showSettingsSelector(): void;
221
223
  showHistorySearch(): void;
222
224
  showExtensionsDashboard(): void;
@@ -264,7 +266,7 @@ export interface InteractiveModeContext {
264
266
  emitCustomToolSessionEvent(reason: "start" | "switch" | "branch" | "tree" | "shutdown", previousSessionFile?: string): Promise<void>;
265
267
  setHookWidget(key: string, content: ExtensionWidgetContent, options?: ExtensionWidgetOptions): void;
266
268
  setHookStatus(key: string, text: string | undefined): void;
267
- showHookSelector(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
269
+ showHookSelector(title: string, options: ExtensionUISelectItem[], dialogOptions?: InteractiveSelectorDialogOptions): Promise<string | undefined>;
268
270
  hideHookSelector(): void;
269
271
  showHookInput(title: string, placeholder?: string): Promise<string | undefined>;
270
272
  hideHookInput(): void;
@@ -6,7 +6,7 @@
6
6
  * creation and removed when the owner releases them.
7
7
  */
8
8
  import type { AgentSession } from "../session/agent-session";
9
- export declare const MAIN_AGENT_ID = "0-Main";
9
+ export declare const MAIN_AGENT_ID = "Main";
10
10
  export type AgentStatus = "running" | "idle" | "completed" | "aborted";
11
11
  export type AgentKind = "main" | "sub";
12
12
  export interface AgentRef {
@@ -101,13 +101,13 @@ export interface CreateAgentSessionOptions {
101
101
  parentHindsightSessionState?: HindsightSessionState;
102
102
  /** Parent Mnemopi state to alias for subagent memory tools. */
103
103
  parentMnemopiSessionState?: MnemopiSessionState;
104
- /** Pre-allocated agent identity for IRC routing. Default: "0-Main" for top-level, parentTaskPrefix-derived for sub. */
104
+ /** Pre-allocated agent identity for IRC routing. Default: "Main" for top-level, parentTaskPrefix-derived for sub. */
105
105
  agentId?: string;
106
106
  /** Display name for the agent in IRC. Default: "main" or "sub". */
107
107
  agentDisplayName?: string;
108
108
  /** Optional shared agent registry for IRC routing. Default: AgentRegistry.global(). */
109
109
  agentRegistry?: AgentRegistry;
110
- /** Parent task ID prefix for nested artifact naming (e.g., "6-Extensions") */
110
+ /** Parent task ID prefix for nested artifact naming (e.g., "Extensions") */
111
111
  parentTaskPrefix?: string;
112
112
  /** Inherited eval executor session id for subagents sharing parent eval state. */
113
113
  parentEvalSessionId?: string;
@@ -201,7 +201,7 @@ export interface AgentSessionConfig {
201
201
  * **MUST NOT** dispose it on their own teardown.
202
202
  */
203
203
  ownedAsyncJobManager?: AsyncJobManager;
204
- /** Agent identity (registry id like "0-Main" or "3-Alice") used for IRC routing. */
204
+ /** Agent identity (registry id like "Main" or "Alice") used for IRC routing. */
205
205
  agentId?: string;
206
206
  /** Shared agent registry (for forwarding IRC observations to the main session UI). */
207
207
  agentRegistry?: AgentRegistry;
@@ -438,8 +438,15 @@ export declare class AgentSession {
438
438
  /**
439
439
  * Replace MCP tools in the registry and recompute the visible MCP tool set immediately.
440
440
  * This allows /mcp add/remove/reauth to take effect without restarting the session.
441
+ *
442
+ * @param mcpTools The new MCP tools to register.
443
+ * @param options.activateAll When true, force-activates every newly registered MCP tool
444
+ * regardless of prior selection state. Used when an ACP client provisions MCP servers
445
+ * for a session where MCP discovery is disabled.
441
446
  */
442
- refreshMCPTools(mcpTools: CustomTool[]): Promise<void>;
447
+ refreshMCPTools(mcpTools: CustomTool[], options?: {
448
+ activateAll?: boolean;
449
+ }): Promise<void>;
443
450
  /**
444
451
  * Replace RPC host-owned tools and refresh the active tool set before the next model call.
445
452
  */
@@ -966,7 +973,9 @@ export declare class AgentSession {
966
973
  * Uses the last assistant message's usage data when available,
967
974
  * otherwise estimates tokens for all messages.
968
975
  */
969
- getContextUsage(): ContextUsage | undefined;
976
+ getContextUsage(options?: {
977
+ contextWindow?: number;
978
+ }): ContextUsage | undefined;
970
979
  fetchUsageReports(signal?: AbortSignal): Promise<UsageReport[] | null>;
971
980
  /**
972
981
  * Export session to HTML.
@@ -3,6 +3,8 @@ export interface HistoryEntry {
3
3
  prompt: string;
4
4
  created_at: number;
5
5
  cwd?: string;
6
+ /** ID of the session the prompt was submitted from, if known. */
7
+ sessionId?: string;
6
8
  }
7
9
  export declare class HistoryStorage {
8
10
  #private;
@@ -10,7 +12,20 @@ export declare class HistoryStorage {
10
12
  static open(dbPath?: string): HistoryStorage;
11
13
  /** @internal Reset the singleton — test-only. */
12
14
  static resetInstance(): void;
13
- add(prompt: string, cwd?: string): Promise<void>;
15
+ /**
16
+ * Register a resolver that supplies the current session ID for prompts added
17
+ * without an explicit `sessionId`. Evaluated synchronously at `add()` time so
18
+ * batched writes capture the session active when the prompt was submitted.
19
+ */
20
+ setSessionResolver(resolver: () => string | undefined): void;
21
+ add(prompt: string, cwd?: string, sessionId?: string): Promise<void>;
14
22
  getRecent(limit: number): HistoryEntry[];
15
23
  search(query: string, limit: number): HistoryEntry[];
24
+ /**
25
+ * IDs of the sessions whose stored prompts match `query`, ordered by match
26
+ * relevance (most relevant/recent first) and de-duplicated. Prompts with no
27
+ * recorded session are skipped. Used to augment session ranking in the
28
+ * resume picker with prompts that the 4KB session-list prefix never sees.
29
+ */
30
+ matchingSessionIds(query: string, limit?: number): string[];
16
31
  }
@@ -169,6 +169,8 @@ export interface SessionContext {
169
169
  /** Mode-specific data from the last mode_change entry */
170
170
  modeData?: Record<string, unknown>;
171
171
  }
172
+ /** Lists session model strings to try when restoring, in fallback order. */
173
+ export declare function getRestorableSessionModels(models: Readonly<Record<string, string>>, lastModelChangeRole: string | undefined): string[];
172
174
  export interface SessionInfo {
173
175
  path: string;
174
176
  id: string;
@@ -253,6 +255,8 @@ export interface ResolvedSessionMatch {
253
255
  }
254
256
  export declare function resolveResumableSession(sessionArg: string, cwd: string, sessionDir?: string, storage?: SessionStorage): Promise<ResolvedSessionMatch | undefined>;
255
257
  interface SessionManagerStateSnapshot {
258
+ cwd: string;
259
+ sessionDir: string;
256
260
  sessionId: string;
257
261
  sessionName: string | undefined;
258
262
  titleSource: "auto" | "user" | undefined;
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * Manages agent output ID allocation to ensure uniqueness.
3
3
  *
4
- * Each allocated ID gets a numeric prefix based on allocation order.
5
- * If configured with a parent prefix, the numeric prefix is appended after
6
- * the parent (e.g., "0-Parent.0-Child").
7
- * On resume, scans existing files to find the next available index.
4
+ * The first allocation of a given name keeps the name as-is; subsequent
5
+ * allocations of the same name get a `-2`, `-3`, suffix. On resume, scans
6
+ * existing output files so previously written outputs are never overwritten.
8
7
  */
9
8
  export declare class AgentOutputManager {
10
9
  #private;
@@ -12,10 +11,10 @@ export declare class AgentOutputManager {
12
11
  parentPrefix?: string;
13
12
  });
14
13
  /**
15
- * Allocate a unique ID with numeric prefix.
14
+ * Allocate a unique ID.
16
15
  *
17
- * @param id Requested ID (e.g., "AuthProvider")
18
- * @returns Unique ID with prefix (e.g., "0-AuthProvider")
16
+ * @param id Requested ID (e.g., "Anna")
17
+ * @returns Unique ID ("Anna" first, then "Anna-2", "Anna-3", …)
19
18
  */
20
19
  allocate(id: string): Promise<string>;
21
20
  /**
@@ -25,12 +24,4 @@ export declare class AgentOutputManager {
25
24
  * @returns Array of unique IDs in same order
26
25
  */
27
26
  allocateBatch(ids: string[]): Promise<string[]>;
28
- /**
29
- * Get the next ID that would be allocated (without allocating).
30
- */
31
- peekNextIndex(): Promise<number>;
32
- /**
33
- * Reset state (primarily for testing).
34
- */
35
- reset(): void;
36
27
  }
@@ -26,6 +26,7 @@ declare const askSchema: z.ZodObject<{
26
26
  question: z.ZodString;
27
27
  options: z.ZodArray<z.ZodObject<{
28
28
  label: z.ZodString;
29
+ description: z.ZodOptional<z.ZodString>;
29
30
  }, z.core.$strip>>;
30
31
  multi: z.ZodOptional<z.ZodBoolean>;
31
32
  recommended: z.ZodOptional<z.ZodNumber>;
@@ -71,6 +72,7 @@ export declare class AskTool implements AgentTool<typeof askSchema, AskToolDetai
71
72
  question: z.ZodString;
72
73
  options: z.ZodArray<z.ZodObject<{
73
74
  label: z.ZodString;
75
+ description: z.ZodOptional<z.ZodString>;
74
76
  }, z.core.$strip>>;
75
77
  multi: z.ZodOptional<z.ZodBoolean>;
76
78
  recommended: z.ZodOptional<z.ZodNumber>;
@@ -82,18 +84,18 @@ export declare class AskTool implements AgentTool<typeof askSchema, AskToolDetai
82
84
  static createIf(session: ToolSession): AskTool | null;
83
85
  execute(_toolCallId: string, params: AskParams, signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<AskToolDetails>, context?: AgentToolContext): Promise<AgentToolResult<AskToolDetails>>;
84
86
  }
87
+ interface AskRenderOption {
88
+ label: string;
89
+ description?: string;
90
+ }
85
91
  interface AskRenderArgs {
86
92
  question?: string;
87
- options?: Array<{
88
- label: string;
89
- }>;
93
+ options?: AskRenderOption[];
90
94
  multi?: boolean;
91
95
  questions?: Array<{
92
96
  id: string;
93
97
  question: string;
94
- options: Array<{
95
- label: string;
96
- }>;
98
+ options: AskRenderOption[];
97
99
  multi?: boolean;
98
100
  }>;
99
101
  }
@@ -0,0 +1,12 @@
1
+ import type { ToolSession } from ".";
2
+ export interface EvalBackendsAllowance {
3
+ python: boolean;
4
+ js: boolean;
5
+ }
6
+ /** Read per-backend allowance from settings (defaults true). */
7
+ export declare function readEvalBackendsAllowance(session: ToolSession): EvalBackendsAllowance;
8
+ /**
9
+ * Materialize the active eval backend allowance: PI_PY / PI_JS env flags
10
+ * override the per-key settings; otherwise settings (defaults true) win.
11
+ */
12
+ export declare function resolveEvalBackends(session: ToolSession): EvalBackendsAllowance;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * TUI rendering for the eval tool.
3
+ *
4
+ * Split out from `eval.ts` so the renderer can be imported by `renderers.ts`
5
+ * without dragging the eval *runtime* (JS/Python backends -> agent bridge ->
6
+ * task executor -> sdk -> extension loader -> root barrel) into the renderer
7
+ * module graph. That transitive chain re-enters `renderers.ts` while `eval.ts`
8
+ * is still initializing, which previously crashed module load with a TDZ
9
+ * `Cannot access 'evalToolRenderer' before initialization`.
10
+ */
11
+ import type { Component } from "@oh-my-pi/pi-tui";
12
+ import type { EvalStatusEvent, EvalToolDetails } from "../eval/types";
13
+ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
14
+ import { type Theme } from "../modes/theme/theme";
15
+ export declare const EVAL_DEFAULT_PREVIEW_LINES = 10;
16
+ interface EvalRenderCellArg {
17
+ language?: string;
18
+ code?: string;
19
+ title?: string;
20
+ }
21
+ interface EvalRenderArgs {
22
+ cells?: EvalRenderCellArg[];
23
+ __partialJson?: string;
24
+ }
25
+ interface EvalRenderContext {
26
+ output?: string;
27
+ expanded?: boolean;
28
+ previewLines?: number;
29
+ timeout?: number;
30
+ }
31
+ /**
32
+ * Append or replace a status event. `agent` events are progress snapshots keyed
33
+ * by `id`, so they coalesce in place (preserving first-seen order); every other
34
+ * op is a discrete action and simply appends. Keeps the persisted event list
35
+ * bounded even when a subagent emits hundreds of throttled progress ticks.
36
+ */
37
+ export declare function upsertStatusEvent(events: EvalStatusEvent[], event: EvalStatusEvent): void;
38
+ export declare const evalToolRenderer: {
39
+ renderCall(args: EvalRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component;
40
+ renderResult(result: {
41
+ content: Array<{
42
+ type: string;
43
+ text?: string;
44
+ }>;
45
+ details?: EvalToolDetails;
46
+ }, options: RenderResultOptions & {
47
+ renderContext?: EvalRenderContext;
48
+ }, uiTheme: Theme, _args?: EvalRenderArgs): Component;
49
+ mergeCallAndResult: boolean;
50
+ inline: boolean;
51
+ };
52
+ export {};
@@ -1,11 +1,8 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
- import type { Component } from "@oh-my-pi/pi-tui";
3
2
  import * as z from "zod/v4";
4
3
  import type { EvalToolDetails } from "../eval/types";
5
- import type { RenderResultOptions } from "../extensibility/custom-tools/types";
6
- import { type Theme } from "../modes/theme/theme";
7
- import { type ToolSession } from ".";
8
- export declare const EVAL_DEFAULT_PREVIEW_LINES = 10;
4
+ import type { ToolSession } from ".";
5
+ export { EVAL_DEFAULT_PREVIEW_LINES, evalToolRenderer } from "./eval-render";
9
6
  /**
10
7
  * Per-cell input. Each cell runs in order; state persists within a language
11
8
  * across cells and across tool calls.
@@ -78,33 +75,3 @@ export declare class EvalTool implements AgentTool<typeof evalSchema> {
78
75
  constructor(session: ToolSession | null, options?: EvalToolOptions);
79
76
  execute(_toolCallId: string, params: z.infer<typeof evalSchema>, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback, _ctx?: AgentToolContext): Promise<AgentToolResult<EvalToolDetails | undefined>>;
80
77
  }
81
- interface EvalRenderCellArg {
82
- language?: string;
83
- code?: string;
84
- title?: string;
85
- }
86
- interface EvalRenderArgs {
87
- cells?: EvalRenderCellArg[];
88
- __partialJson?: string;
89
- }
90
- interface EvalRenderContext {
91
- output?: string;
92
- expanded?: boolean;
93
- previewLines?: number;
94
- timeout?: number;
95
- }
96
- export declare const evalToolRenderer: {
97
- renderCall(args: EvalRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component;
98
- renderResult(result: {
99
- content: Array<{
100
- type: string;
101
- text?: string;
102
- }>;
103
- details?: EvalToolDetails;
104
- }, options: RenderResultOptions & {
105
- renderContext?: EvalRenderContext;
106
- }, uiTheme: Theme, _args?: EvalRenderArgs): Component;
107
- mergeCallAndResult: boolean;
108
- inline: boolean;
109
- };
110
- export {};
@@ -14,15 +14,6 @@ declare const findSchema: z.ZodObject<{
14
14
  timeout: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
15
15
  }, z.core.$strict>;
16
16
  export type FindToolInput = z.infer<typeof findSchema>;
17
- /**
18
- * Reject comma-separated path lists packed into a single array element
19
- * (`["a.py,b.py"]`). The schema is array-of-string; agents that pass a
20
- * single comma-joined element get silent no-matches otherwise.
21
- *
22
- * Commas inside brace expansion (`{a,b}`) are legitimate glob syntax and
23
- * must pass through.
24
- */
25
- export declare function validateFindPathInputs(paths: readonly string[]): void;
26
17
  /**
27
18
  * Group find matches by their directory so the model doesn't pay repeated
28
19
  * tokens for shared path prefixes. Preserves the input order: groups appear in
@@ -37,6 +37,7 @@ export * from "./browser";
37
37
  export * from "./checkpoint";
38
38
  export * from "./debug";
39
39
  export * from "./eval";
40
+ export * from "./eval-backends";
40
41
  export * from "./find";
41
42
  export * from "./gh";
42
43
  export * from "./image-gen";
@@ -111,7 +112,7 @@ export interface ToolSession {
111
112
  getHindsightSessionState?: () => HindsightSessionState | undefined;
112
113
  /** Get Mnemopi runtime state for this agent session. */
113
114
  getMnemopiSessionState?: () => MnemopiSessionState | undefined;
114
- /** Agent identity used for IRC routing. Returns the registry id (e.g. "0-Main", "0-AuthLoader"). */
115
+ /** Agent identity used for IRC routing. Returns the registry id (e.g. "Main", "AuthLoader"). */
115
116
  getAgentId?: () => string | null;
116
117
  /** Look up a registered tool by name (used by the eval js backend's tool bridge). */
117
118
  getToolByName?: (name: string) => AgentTool | undefined;
@@ -218,6 +219,9 @@ export interface ToolSession {
218
219
  * to splice the recorded region with replacement content. Lazily initialized
219
220
  * by `getConflictHistory`. */
220
221
  conflictHistory?: import("./conflict-detect").ConflictHistory;
222
+ /** Per-session ledger of post-edit LSP diagnostics already surfaced to the
223
+ * model for each file. Lazily initialized by `getDiagnosticsLedger`. */
224
+ diagnosticsLedger?: import("../lsp/diagnostics-ledger").DiagnosticsLedger;
221
225
  /** Queue a hidden message to be injected at the next agent turn. */
222
226
  queueDeferredMessage?(message: CustomMessage): void;
223
227
  /** Get the active OpenTelemetry config so subagent dispatch can forward
@@ -241,17 +245,6 @@ export declare function computeEssentialBuiltinNames(settings: Settings): string
241
245
  export declare const BUILTIN_TOOLS: Record<string, ToolFactory>;
242
246
  export declare const HIDDEN_TOOLS: Record<string, ToolFactory>;
243
247
  export type ToolName = keyof typeof BUILTIN_TOOLS;
244
- export interface EvalBackendsAllowance {
245
- python: boolean;
246
- js: boolean;
247
- }
248
- /** Read per-backend allowance from settings (defaults true). */
249
- export declare function readEvalBackendsAllowance(session: ToolSession): EvalBackendsAllowance;
250
- /**
251
- * Materialize the active eval backend allowance: PI_PY / PI_JS env flags
252
- * override the per-key settings; otherwise settings (defaults true) win.
253
- */
254
- export declare function resolveEvalBackends(session: ToolSession): EvalBackendsAllowance;
255
248
  /**
256
249
  * Create tools from BUILTIN_TOOLS registry.
257
250
  */
@@ -69,6 +69,21 @@ export declare function formatPathRelativeToCwd(filePath: string, cwd: string, o
69
69
  export declare function stripOuterDoubleQuotes(input: string): string;
70
70
  export declare function normalizePathLikeInput(input: string): string;
71
71
  export declare function hasGlobPathChars(filePath: string): boolean;
72
+ type PathEntrySplitter = (item: string) => {
73
+ basePath: string;
74
+ };
75
+ /**
76
+ * Split one path-like entry whose multiple targets were flattened into one
77
+ * string. Existing paths are kept intact, so real filenames containing spaces,
78
+ * commas, or semicolons win over delimiter recovery.
79
+ */
80
+ export declare function splitDelimitedPathEntry(entry: string, cwd: string, options?: {
81
+ splitter?: PathEntrySplitter;
82
+ }): Promise<string[] | null>;
83
+ /** Expand delimited entries in-place while preserving unsplit entries. */
84
+ export declare function expandDelimitedPathEntries(entries: readonly string[], cwd: string, options?: {
85
+ splitter?: PathEntrySplitter;
86
+ }): Promise<string[]>;
72
87
  export interface ParsedSearchPath {
73
88
  basePath: string;
74
89
  glob?: string;
@@ -170,3 +185,4 @@ export interface ToolScopeResolution {
170
185
  * 5. stat the resolved base path so callers can branch on directory vs file scope.
171
186
  */
172
187
  export declare function resolveToolSearchScope(opts: ToolScopeOptions): Promise<ToolScopeResolution>;
188
+ export {};
@@ -32,13 +32,33 @@ export type SqliteRowLookup = {
32
32
  } | {
33
33
  kind: "rowid";
34
34
  };
35
+ /**
36
+ * Row count for a table in the listing.
37
+ * - `exact`: counted in full (the table is small enough to count cheaply).
38
+ * - `estimate`: the planner's `sqlite_stat1` figure; the table is too large to
39
+ * scan, so this may be stale.
40
+ * - `atLeast`: a lower bound; counting was capped before reaching the end.
41
+ */
42
+ export type TableRowCount = {
43
+ kind: "exact";
44
+ rows: number;
45
+ } | {
46
+ kind: "estimate";
47
+ rows: number;
48
+ } | {
49
+ kind: "atLeast";
50
+ rows: number;
51
+ };
52
+ export interface SqliteTableSummary {
53
+ name: string;
54
+ count: TableRowCount;
55
+ }
35
56
  export declare function parseSqlitePathCandidates(filePath: string): SqlitePathCandidate[];
36
57
  export declare function isSqliteFile(absolutePath: string): Promise<boolean>;
37
58
  export declare function parseSqliteSelector(subPath: string, queryString: string): SqliteSelector;
38
- export declare function listTables(db: Database): {
39
- name: string;
40
- rowCount: number;
41
- }[];
59
+ export declare function listTables(db: Database, options?: {
60
+ probeCap?: number;
61
+ }): SqliteTableSummary[];
42
62
  export declare function getTableSchema(db: Database, table: string): string;
43
63
  export declare function getTablePrimaryKey(db: Database, table: string): {
44
64
  column: string;
@@ -75,10 +95,7 @@ export declare function deleteRowByKey(db: Database, table: string, pk: {
75
95
  type?: string;
76
96
  }, key: string): number;
77
97
  export declare function deleteRowByRowId(db: Database, table: string, key: string): number;
78
- export declare function renderTableList(tables: {
79
- name: string;
80
- rowCount: number;
81
- }[]): string;
98
+ export declare function renderTableList(tables: SqliteTableSummary[]): string;
82
99
  export declare function renderSchema(createSql: string, sampleRows: {
83
100
  columns: string[];
84
101
  rows: Record<string, unknown>[];
@@ -14,9 +14,10 @@ export interface OutputBlockOptions {
14
14
  animate?: boolean;
15
15
  }
16
16
  /**
17
- * Monotonic frame counter for animated borders. Quantized coarse enough to
18
- * coalesce multiple render passes inside one frame, fine enough to advance on
19
- * every spinner interval so cached blocks re-render while the segment travels.
17
+ * Monotonic frame counter for animated borders, quantized to the TUI's ~16ms
18
+ * render cap so the cache key advances once per ~60fps frame fine enough for a
19
+ * smooth segment sweep, coarse enough to coalesce multiple render passes that
20
+ * land inside the same frame.
20
21
  */
21
22
  export declare function borderShimmerTick(): number;
22
23
  /**
@@ -20,3 +20,7 @@ export declare function copyToClipboard(text: string): Promise<void>;
20
20
  * @returns PNG payload or null when no image is available.
21
21
  */
22
22
  export declare function readImageFromClipboard(): Promise<ClipboardImage | null>;
23
+ /**
24
+ * Read plain text from the system clipboard.
25
+ */
26
+ export declare function readTextFromClipboard(): Promise<string>;