@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
@@ -9,8 +9,8 @@ export interface AsyncJob {
9
9
  resultText?: string;
10
10
  errorText?: string;
11
11
  /**
12
- * Registry id of the agent that registered the job (e.g. "0-Main",
13
- * "3-AuthLoader"). Used by scoped cancel/list APIs so a subagent's teardown
12
+ * Registry id of the agent that registered the job (e.g. "Main",
13
+ * "AuthLoader"). Used by scoped cancel/list APIs so a subagent's teardown
14
14
  * does not cancel its parent's jobs. Undefined for callers that don't
15
15
  * supply an id (e.g. legacy tests, SDK consumers without an agent context).
16
16
  */
@@ -36,7 +36,7 @@ export interface AsyncJobRegisterOptions {
36
36
  /**
37
37
  * Filter applied to job query/cancel APIs. With `ownerId`, results are
38
38
  * restricted to jobs registered by that agent (registry id from
39
- * `AgentRegistry`, e.g. "0-Main", "3-AuthLoader").
39
+ * `AgentRegistry`, e.g. "Main", "AuthLoader").
40
40
  */
41
41
  export interface AsyncJobFilter {
42
42
  ownerId?: string;
@@ -15,6 +15,7 @@ export interface Args {
15
15
  systemPrompt?: string;
16
16
  appendSystemPrompt?: string;
17
17
  thinking?: Effort;
18
+ hideThinking?: boolean;
18
19
  continue?: boolean;
19
20
  resume?: string | true;
20
21
  help?: boolean;
@@ -0,0 +1,54 @@
1
+ export declare const CLAUDE_TRACE_DEBUG_CERT = "-----BEGIN CERTIFICATE-----\nMIIDFzCCAf+gAwIBAgIUAe9omAqLbydZc5ZYZGhwbbpMSF0wDQYJKoZIhvcNAQEL\nBQAwGzEZMBcGA1UEAwwQb21wLWNsYXVkZS10cmFjZTAeFw0yNjA2MDIwODA2MjFa\nFw0zNjA1MzAwODA2MjFaMBsxGTAXBgNVBAMMEG9tcC1jbGF1ZGUtdHJhY2UwggEi\nMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmpGe5T8B0oA2L82Rn5JJdXOBS\nZX0DyBjiIK+Tqe8T3oAr41XDLnweqtrMDSBDYbVqAoKjNbaTUSYYcxSm0MAVs63w\n08SfJmShZM9pElfANqXqMiyhksFgji7JEyt/rbbId207a7s5KvRvm3g/sxN/wGtr\nC5LCLMlc2GWEGD8qrVIQbmLw884qvtXi70RFUPP3Wpy4wGMWSdE+9IA27R5cMJS5\noHsO4HGB6J8VzLY+HGY2yr4BJ9qrAyjd1UetFd9RdcjyWpsbAfX8nWP+uleTNOiT\nExNz7dPt/k6OPLNmI1iT/ruRS0uUzHZTimPd67TPQR/70RaW7Bh5wArawGw9AgMB\nAAGjUzBRMB0GA1UdDgQWBBQa4Ir8P3GAolZoPiuB4V2cq3riAjAfBgNVHSMEGDAW\ngBQa4Ir8P3GAolZoPiuB4V2cq3riAjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3\nDQEBCwUAA4IBAQClPYki235gDEUu7eDm60qsAGWxbKVv4pSh+vB+xgNgzMk4aOuU\nmSfp8Y8covwklph8VfDoKTaEGqqX0Q5s74Ctl6Mwy7b0u8Zztk/g4GynLocI7TQD\nftZMgZka49+FkEsjp+XZtQbO4vOL5UsccpsLhFQQQuhVyiJ4gNo/VzgvSDkBuf3Q\nRz7xFiDKCqFEoMPty4+nKEw5832FJ5mDCOyMk6fGSO8Wbt/hmRQQFu2cSdoBs0OT\nAQQJETQjPkKeTDX4jdSAlOeKwfyjfdfgeQuMkzX8xafisJa66MLPzOVbIuGbvbWD\nQVCd76iYPcfNK+JZUhmAUvTHSuwgJMZ6+NgI\n-----END CERTIFICATE-----";
2
+ export declare const CLAUDE_TRACE_DEBUG_KEY = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmpGe5T8B0oA2L\n82Rn5JJdXOBSZX0DyBjiIK+Tqe8T3oAr41XDLnweqtrMDSBDYbVqAoKjNbaTUSYY\ncxSm0MAVs63w08SfJmShZM9pElfANqXqMiyhksFgji7JEyt/rbbId207a7s5KvRv\nm3g/sxN/wGtrC5LCLMlc2GWEGD8qrVIQbmLw884qvtXi70RFUPP3Wpy4wGMWSdE+\n9IA27R5cMJS5oHsO4HGB6J8VzLY+HGY2yr4BJ9qrAyjd1UetFd9RdcjyWpsbAfX8\nnWP+uleTNOiTExNz7dPt/k6OPLNmI1iT/ruRS0uUzHZTimPd67TPQR/70RaW7Bh5\nwArawGw9AgMBAAECggEADX2mhA3H0pPuj35J36X/5Me9xWM//AwOr6febwGalazg\nCtg3EOZ01/VptzaiKQetAdhoLmxidooNn9HD7JQJKPid7q7w7m1+R26mN/xrLD2A\nWyBqv+iQoo+ANs5y1BMChuIxmVY/FwFk6UWDNlekuXqgzPln4okbrYTmBbaszniO\nMu1SI/3fpnTA3iJ634FUSRVoUPP8r0WEEUtpW1wAhsJR701gvKRYw/+YcRglkhm7\nT4l6TuBcgIVzUqAc3oZLHVIMKN0ZprZSeopSRozTcUANfYONakvK9Hx1qf+/rmTR\nqZHg2uOxlqvxyABnwdk8rmyFx8YqUeN9jaAbbXxtBQKBgQDQRjc0gVg4STqcFqUu\nFW35MZ88S7+xTuRd/EG1dpsu2lptx1yhSLTsF5GfxBQKXCQUfWrpkyuCmlV6s+wJ\nH0LSyAJQ4ffBsFterQz7dRKTlhRJNk5PYn8jjNCAuBYVSbQZqZ3yZgG3CT3G5+PZ\n8Ln3tJHqTRfP5B8KTMcNYiLI0wKBgQDM0/gdb9Dvdz/32GIpxwNNIb52IxnNVVrm\nM69+4XNg6CqvctZFuaMQ03W2J5IKAdESaCGLz9pwHZRjfBORcw3BPKD2QkfN5NJg\nhWvLlfAsblCYiCCjTCB6rf1OJOQ5fHoNFh1wqDaQCk0flsb9nlZmQQR5ZUHaJhSC\nQqMmeKvMrwKBgQDDzp+sH0Z/dGlDwg59auw/caWRHG4WFmOg8L4eCmoO/H4z41B0\n2VQu+mGQYNmue733/Yl8Gz62xL5EY88vLFK4tA1pWWiCknj0Y6Fm70QNuPVNd17c\nR2/cTlDgEzG/xdEqp0q1T62hFXEdBXoztZxBA2SDcQNIEeIU3uXs8SxevQKBgFp4\nacf+wody4aNERR900sV32RtvJ49lWxAA1kwxone0NF5oV7JWa2scK4r4cW3QHZuG\nuQJ7HV2WAxvqCu6cpf+rGuGKpxKPNkkBxXoX0Qye8SReRCQ8lL/7J74jV1b43yP2\nl6xR8D+w/R2tyFjvXfQuVZ6VFgAX/8kFS/DLLf7rAoGAcnFgCwyzcq6FWL8iW23J\nGnbZ0IQk6SPch87MzMmnOFlEXrCf5l832vwI65tNzOoB0yQoWVfBv5sb4Zy9zeFj\nFbkpRZC0Kfi9PLzDV4IawoIINYthOJxIKJg+yrmrUWCggXxwdzYIYKLRIskMXoYs\nmNMXfUstElEcKO7+DKiPi6U=\n-----END PRIVATE KEY-----";
3
+ export interface HeaderEntry {
4
+ name: string;
5
+ value: string;
6
+ }
7
+ export interface CapturedRequest {
8
+ method: string;
9
+ path: string;
10
+ version: string;
11
+ headers: HeaderEntry[];
12
+ body: string;
13
+ }
14
+ export interface CapturedResponse {
15
+ statusCode: number | undefined;
16
+ statusMessage: string;
17
+ version: string;
18
+ headers: HeaderEntry[];
19
+ body: string;
20
+ }
21
+ export interface CapturedMessagesExchange {
22
+ target: string;
23
+ request: CapturedRequest;
24
+ response: CapturedResponse;
25
+ }
26
+ export interface ClaudeMessagesProxyOptions {
27
+ host?: string;
28
+ port?: number;
29
+ upstreamTlsRejectUnauthorized?: boolean;
30
+ }
31
+ export interface ClaudeTraceCommandArgs {
32
+ command?: string;
33
+ message?: string;
34
+ cwd?: string;
35
+ host?: string;
36
+ port?: number;
37
+ timeoutMs?: number;
38
+ inputDelayMs?: number;
39
+ json?: boolean;
40
+ upstreamTlsRejectUnauthorized?: boolean;
41
+ }
42
+ export declare function formatCapturedMessagesExchange(exchange: CapturedMessagesExchange): string;
43
+ export declare class ClaudeMessagesProxy {
44
+ #private;
45
+ constructor(options?: ClaudeMessagesProxyOptions);
46
+ get host(): string;
47
+ get port(): number;
48
+ get url(): string;
49
+ start(): Promise<void>;
50
+ stop(): Promise<void>;
51
+ waitForCapture(timeoutMs: number): Promise<CapturedMessagesExchange>;
52
+ }
53
+ export declare function runClaudeMessagesCapture(args?: ClaudeTraceCommandArgs): Promise<CapturedMessagesExchange>;
54
+ export declare function runClaudeTraceCommand(args?: ClaudeTraceCommandArgs): Promise<void>;
@@ -1,3 +1,10 @@
1
- import type { SessionInfo } from "../session/session-manager";
2
- /** Show TUI session selector and return selected session path or null if cancelled */
3
- export declare function selectSession(sessions: SessionInfo[]): Promise<string | null>;
1
+ import { type SessionInfo } from "../session/session-manager";
2
+ /**
3
+ * Show the TUI session selector and return the selected session, or null if
4
+ * cancelled. Tab toggles between current-folder and all-projects scope; the
5
+ * all-projects list is loaded lazily via `SessionManager.listAll`.
6
+ */
7
+ export declare function selectSession(sessions: SessionInfo[], options?: {
8
+ allSessions?: SessionInfo[];
9
+ startInAllScope?: boolean;
10
+ }): Promise<SessionInfo | null>;
@@ -25,6 +25,23 @@ export declare function resolveUpdateMethodForTest(ompPath: string, bunBinDir: s
25
25
  * Atomically replace the installed binary and roll back if version verification fails.
26
26
  */
27
27
  export declare function replaceBinaryForUpdate(options: BinaryReplacementOptions): Promise<InstalledVersionVerification>;
28
+ /**
29
+ * Build the bun argv used to globally install a specific omp version.
30
+ *
31
+ * The version is selected by hitting {@link NPM_REGISTRY} directly in
32
+ * {@link getLatestRelease}, so the install MUST observe the same catalog:
33
+ *
34
+ * - `--registry=${NPM_REGISTRY}` pins the install to the official registry
35
+ * regardless of the user's bunfig/`.npmrc`. A mirror (corporate proxy,
36
+ * Taobao, …) that hasn't yet replicated the release would otherwise reject
37
+ * a version the upstream registry already advertises.
38
+ * - `--no-cache` tells bun to ignore its on-disk manifest snapshot so it
39
+ * re-fetches metadata from that registry on every invocation.
40
+ *
41
+ * Together these two flags make `omp update` produce exactly the registry
42
+ * lookup the version check just performed. See #1686.
43
+ */
44
+ export declare function buildBunInstallArgs(expectedVersion: string): string[];
28
45
  /**
29
46
  * Run the update command.
30
47
  */
@@ -81,6 +81,9 @@ export default class Index extends Command {
81
81
  description: string;
82
82
  options: import("@oh-my-pi/pi-ai").Effort[];
83
83
  };
84
+ "hide-thinking": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
85
+ description: string;
86
+ };
84
87
  hook: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
85
88
  description: string;
86
89
  multiple: true;
@@ -19,6 +19,7 @@ interface AppKeybindings {
19
19
  "app.message.followUp": true;
20
20
  "app.message.dequeue": true;
21
21
  "app.clipboard.pasteImage": true;
22
+ "app.clipboard.pasteTextRaw": true;
22
23
  "app.clipboard.copyLine": true;
23
24
  "app.clipboard.copyPrompt": true;
24
25
  "app.session.new": true;
@@ -230,6 +231,10 @@ export declare const KEYBINDINGS: {
230
231
  readonly defaultKeys: "alt+v" | "ctrl+v";
231
232
  readonly description: "Paste image from clipboard";
232
233
  };
234
+ readonly "app.clipboard.pasteTextRaw": {
235
+ readonly defaultKeys: ["ctrl+shift+v", "alt+shift+v"];
236
+ readonly description: "Paste text from clipboard as raw text (no collapse)";
237
+ };
233
238
  readonly "app.clipboard.copyLine": {
234
239
  readonly defaultKeys: "alt+shift+l";
235
240
  readonly description: "Copy current line";
@@ -2299,6 +2299,15 @@ export declare const SETTINGS_SCHEMA: {
2299
2299
  readonly description: "Return LSP diagnostics after editing code files";
2300
2300
  };
2301
2301
  };
2302
+ readonly "lsp.diagnosticsDeduplicate": {
2303
+ readonly type: "boolean";
2304
+ readonly default: true;
2305
+ readonly ui: {
2306
+ readonly tab: "editing";
2307
+ readonly label: "Deduplicate Diagnostics";
2308
+ readonly description: "Suppress post-edit LSP diagnostics already shown for a file; only surface new or changed ones";
2309
+ };
2310
+ };
2302
2311
  readonly "bashInterceptor.enabled": {
2303
2312
  readonly type: "boolean";
2304
2313
  readonly default: false;
@@ -3272,7 +3281,7 @@ export declare const SETTINGS_SCHEMA: {
3272
3281
  }, {
3273
3282
  readonly value: "exa";
3274
3283
  readonly label: "Exa";
3275
- readonly description: "Uses Exa API when EXA_API_KEY is set; falls back to Exa MCP";
3284
+ readonly description: "Requires EXA_API_KEY";
3276
3285
  }, {
3277
3286
  readonly value: "brave";
3278
3287
  readonly label: "Brave";
@@ -3312,7 +3321,7 @@ export declare const SETTINGS_SCHEMA: {
3312
3321
  }, {
3313
3322
  readonly value: "kagi";
3314
3323
  readonly label: "Kagi";
3315
- readonly description: "Requires KAGI_API_KEY and Kagi Search API beta access";
3324
+ readonly description: "Requires KAGI_API_KEY (Kagi V1 Search API)";
3316
3325
  }, {
3317
3326
  readonly value: "synthetic";
3318
3327
  readonly label: "Synthetic";
@@ -74,6 +74,19 @@ export declare class Settings {
74
74
  */
75
75
  flush(): Promise<void>;
76
76
  cloneForCwd(cwd: string): Promise<Settings>;
77
+ /**
78
+ * Re-scope this instance to a new working directory *in place*: reload the
79
+ * project layer (`.claude/settings.yml` etc.) from `cwd`, re-resolve
80
+ * path-scoped settings against it, and re-fire side-effect hooks (theme,
81
+ * symbols, tab width, …). Global settings and runtime overrides are preserved.
82
+ *
83
+ * Unlike {@link cloneForCwd}, this mutates the live instance, so every holder
84
+ * (the `settings` proxy, the active session, controllers) observes the new
85
+ * project scope without swapping references — used when the process changes
86
+ * directory mid-run (`/move`, cross-project resume). No-op when `cwd` is
87
+ * already the current scope.
88
+ */
89
+ reloadForCwd(cwd: string): Promise<void>;
77
90
  getStorage(): AgentStorage | null;
78
91
  getCwd(): string;
79
92
  getAgentDir(): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Host-side handler for the eval `parallel()` / `pipeline()` worker pool.
3
+ *
4
+ * The pool ceiling is not a kernel-side knob: it tracks the `task.maxConcurrency`
5
+ * setting so an eval fan-out runs as wide as a `task` tool batch would. `0` means
6
+ * unbounded — run every item at once, exactly like `task.maxConcurrency = 0`.
7
+ */
8
+ import type { ToolSession } from "../tools";
9
+ import type { JsStatusEvent } from "./js/shared/types";
10
+ /** Synthetic bridge name reserved for the parallel-pool ceiling across both runtimes. */
11
+ export declare const EVAL_CONCURRENCY_BRIDGE_NAME = "__concurrency__";
12
+ export interface EvalConcurrencyBridgeOptions {
13
+ session: ToolSession;
14
+ signal?: AbortSignal;
15
+ emitStatus?: (event: JsStatusEvent) => void;
16
+ }
17
+ export interface EvalConcurrencyResult {
18
+ /** Worker-pool ceiling; `0` means unbounded (run every item at once). */
19
+ limit: number;
20
+ }
21
+ /**
22
+ * Resolve the worker-pool ceiling for an eval cell's `parallel()`/`pipeline()`
23
+ * helpers from the live `task.maxConcurrency` setting. Negative/non-finite
24
+ * values collapse to `0` (unbounded), matching the `task` tool's own handling.
25
+ */
26
+ export declare function runEvalConcurrency(_args: unknown, options: EvalConcurrencyBridgeOptions): EvalConcurrencyResult;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Keepalive for in-flight host-side eval bridge calls.
3
+ *
4
+ * The eval watchdog ({@link ../tools/eval IdleTimeout}) caps a cell's `timeout`
5
+ * as a wall-clock budget on the cell's *own* work, but pauses that budget while
6
+ * a host-side `agent()`/`parallel()` (via `runSubprocess`) or `llm()` (a single
7
+ * completion) call is in flight. Those calls are the only thing that re-arms the
8
+ * watchdog — and they can run for long stretches with **no** status of their own
9
+ * (a subagent's time-to-first-token on a reasoning model, a long quiet nested
10
+ * tool, or the entire body of a oneshot `llm()` call). Without a keepalive the
11
+ * watchdog would mistake that delegated work for the cell stalling and abort it
12
+ * mid-flight, killing the subagent.
13
+ *
14
+ * {@link withBridgeHeartbeat} bridges that gap by emitting a synthetic
15
+ * {@link EVAL_HEARTBEAT_OP} status event immediately when the call begins and
16
+ * then on a fixed cadence until it settles. The event rides the same
17
+ * `emitStatus → onStatus` channel both runtimes already forward, so it re-arms
18
+ * the watchdog without any new plumbing. The heartbeat is the *sole* signal that
19
+ * extends the budget: consumers MUST treat it as a pure keepalive — bump the
20
+ * watchdog and drop it (never persist or render it) — see the executor display
21
+ * sinks and the eval tool's `onStatus` handler. Every other status event
22
+ * (compute helpers, `log()`/`phase()`, tool results) counts against the budget.
23
+ */
24
+ import type { JsStatusEvent } from "./js/shared/types";
25
+ /**
26
+ * Synthetic status op emitted purely to keep the eval idle watchdog alive while
27
+ * a host-side bridge call is in flight. Carries no payload.
28
+ */
29
+ export declare const EVAL_HEARTBEAT_OP = "heartbeat";
30
+ /**
31
+ * Test seam: override the heartbeat cadence so integration tests can exercise
32
+ * the keepalive within a sub-second idle budget. Pass no value to restore the
33
+ * production default.
34
+ */
35
+ export declare function setBridgeHeartbeatIntervalMs(ms?: number): void;
36
+ /**
37
+ * Run {@link operation}, pumping {@link EVAL_HEARTBEAT_OP} status events through
38
+ * {@link emitStatus} — one immediately, then on a fixed cadence — until it
39
+ * settles. The immediate beat pauses the watchdog the instant the call begins,
40
+ * so a bridge call that starts close to the budget edge (after the cell already
41
+ * spent most of it computing) is not aborted before the first interval tick. A
42
+ * no-op wrapper when no `emitStatus` sink is wired (the heartbeat would reach
43
+ * nobody).
44
+ */
45
+ export declare function withBridgeHeartbeat<T>(emitStatus: ((event: JsStatusEvent) => void) | undefined, operation: () => Promise<T>): Promise<T>;
@@ -1,5 +1,6 @@
1
1
  import type { ToolSession } from "../../tools";
2
2
  import { type EvalBudgetResult } from "../budget-bridge";
3
+ import { type EvalConcurrencyResult } from "../concurrency-bridge";
3
4
  import type { JsStatusEvent } from "./shared/types";
4
5
  export type { JsStatusEvent } from "./shared/types";
5
6
  interface ToolBridgeOptions {
@@ -7,7 +8,7 @@ interface ToolBridgeOptions {
7
8
  signal?: AbortSignal;
8
9
  emitStatus?: (event: JsStatusEvent) => void;
9
10
  }
10
- type ToolValue = string | EvalBudgetResult | {
11
+ type ToolValue = string | EvalBudgetResult | EvalConcurrencyResult | {
11
12
  text: string;
12
13
  details?: unknown;
13
14
  images?: Array<{
@@ -1,6 +1,6 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
2
  import { EventBus } from "../../utils/event-bus";
3
- import type { Extension, ExtensionFactory, ExtensionRuntime as IExtensionRuntime, LoadExtensionsResult } from "./types";
3
+ import type { Extension, ExtensionFactory, ExtensionRuntime as IExtensionRuntime, LoadExtensionsResult, ProviderConfig } from "./types";
4
4
  export declare class ExtensionRuntimeNotInitializedError extends Error {
5
5
  constructor();
6
6
  }
@@ -12,7 +12,7 @@ export declare class ExtensionRuntime implements IExtensionRuntime {
12
12
  flagValues: Map<string, string | boolean>;
13
13
  pendingProviderRegistrations: Array<{
14
14
  name: string;
15
- config: import("./types").ProviderConfig;
15
+ config: ProviderConfig;
16
16
  sourceId: string;
17
17
  }>;
18
18
  sendMessage(): void;
@@ -6,7 +6,7 @@ import type { CredentialDisabledEvent, ImageContent, Model, ProviderResponseMeta
6
6
  import type { KeyId } from "@oh-my-pi/pi-tui";
7
7
  import type { ModelRegistry } from "../../config/model-registry";
8
8
  import type { SessionManager } from "../../session/session-manager";
9
- import type { AfterProviderResponseEvent, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types";
9
+ import type { AfterProviderResponseEvent, AssistantThinkingRenderer, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types";
10
10
  /** Combined result from all before_agent_start handlers */
11
11
  interface BeforeAgentStartCombinedResult {
12
12
  messages?: NonNullable<BeforeAgentStartEventResult["message"]>[];
@@ -98,6 +98,7 @@ export declare class ExtensionRunner {
98
98
  emitError(error: ExtensionError): void;
99
99
  hasHandlers(eventType: string): boolean;
100
100
  getMessageRenderer(customType: string): MessageRenderer | undefined;
101
+ getAssistantThinkingRenderers(): AssistantThinkingRenderer[];
101
102
  getRegisteredCommands(reserved?: Set<string>): RegisteredCommand[];
102
103
  getCommandDiagnostics(): Array<{
103
104
  type: string;
@@ -13,6 +13,8 @@ import type { Api, AssistantMessageEvent, AssistantMessageEventStream, Context,
13
13
  import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/utils/oauth/types";
14
14
  import type * as piCodingAgent from "@oh-my-pi/pi-coding-agent";
15
15
  import type { AutocompleteItem, Component, EditorTheme, KeyId, TUI } from "@oh-my-pi/pi-tui";
16
+ import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
17
+ import type * as Zod from "zod/v4";
16
18
  import type { KeybindingsManager } from "../../config/keybindings";
17
19
  import type { ModelRegistry } from "../../config/model-registry";
18
20
  import type { EditToolDetails } from "../../edit";
@@ -27,9 +29,16 @@ import type { BashToolDetails, BashToolInput, FindToolDetails, FindToolInput, Re
27
29
  import type { EventBus } from "../../utils/event-bus";
28
30
  import type { AgentEndEvent, AgentStartEvent, AutoCompactionEndEvent, AutoCompactionStartEvent, AutoRetryEndEvent, AutoRetryStartEvent, ContextEvent, GoalUpdatedEvent, SessionBeforeBranchEvent, SessionBeforeBranchResult, SessionBeforeCompactEvent, SessionBeforeCompactResult, SessionBeforeSwitchEvent, SessionBeforeSwitchResult, SessionBeforeTreeEvent, SessionBeforeTreeResult, SessionBranchEvent, SessionCompactEvent, SessionCompactingEvent, SessionCompactingResult, SessionEvent, SessionShutdownEvent, SessionStartEvent, SessionSwitchEvent, SessionTreeEvent, TodoReminderEvent, ToolCallEventResult, ToolResultEventResult, TtsrTriggeredEvent, TurnEndEvent, TurnStartEvent } from "../shared-events";
29
31
  import type { SlashCommandInfo } from "../slash-commands";
32
+ import type * as TypeBox from "../typebox";
30
33
  export type { AppKeybinding, KeybindingsManager } from "../../config/keybindings";
31
34
  export type { ExecOptions, ExecResult } from "../../exec/exec";
32
35
  export type { AgentToolResult, AgentToolUpdateCallback };
36
+ export interface ExtensionUISelectOption {
37
+ label: string;
38
+ description?: string;
39
+ }
40
+ export type ExtensionUISelectItem = string | ExtensionUISelectOption;
41
+ export declare function getExtensionUISelectOptionLabel(option: ExtensionUISelectItem): string;
33
42
  /**
34
43
  * UI dialog options for extensions.
35
44
  */
@@ -70,8 +79,8 @@ export type ExtensionWidgetContent = string[] | ExtensionUiComponentFactory | un
70
79
  * Each mode (interactive, RPC, print) provides its own implementation.
71
80
  */
72
81
  export interface ExtensionUIContext {
73
- /** Show a selector and return the user's choice. */
74
- select(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
82
+ /** Show a selector and return the selected label, even when an option also includes a description. */
83
+ select(title: string, options: ExtensionUISelectItem[], dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
75
84
  /** Show a confirmation dialog. */
76
85
  confirm(title: string, message: string, dialogOptions?: ExtensionUIDialogOptions): Promise<boolean>;
77
86
  /** Show a text input dialog. */
@@ -508,6 +517,13 @@ export interface MessageRenderOptions {
508
517
  expanded: boolean;
509
518
  }
510
519
  export type MessageRenderer<T = unknown> = (message: CustomMessage<T>, options: MessageRenderOptions, theme: Theme) => Component | undefined;
520
+ export interface AssistantThinkingRenderContext {
521
+ contentIndex: number;
522
+ thinkingIndex: number;
523
+ text: string;
524
+ requestRender(): void;
525
+ }
526
+ export type AssistantThinkingRenderer = (context: AssistantThinkingRenderContext, theme: Theme) => Component | undefined;
511
527
  export interface RegisteredCommand {
512
528
  name: string;
513
529
  description?: string;
@@ -521,11 +537,11 @@ export type ExtensionHandler<E, R = undefined> = (event: E, ctx: ExtensionContex
521
537
  */
522
538
  export interface ExtensionAPI {
523
539
  /** File logger for error/warning/debug messages */
524
- logger: typeof import("@oh-my-pi/pi-utils").logger;
540
+ logger: typeof PiLogger;
525
541
  /** Injected zod-backed typebox shim for legacy `Type.Object(...)` parameter authoring. */
526
- typebox: typeof import("../typebox");
542
+ typebox: typeof TypeBox;
527
543
  /** Injected zod module for Zod-authored extension tools (canonical going forward). */
528
- zod: typeof import("zod/v4");
544
+ zod: typeof Zod;
529
545
  /** Injected pi-coding-agent exports for accessing SDK utilities */
530
546
  pi: typeof piCodingAgent;
531
547
  on(event: "resources_discover", handler: ExtensionHandler<ResourcesDiscoverEvent, ResourcesDiscoverResult>): void;
@@ -592,6 +608,8 @@ export interface ExtensionAPI {
592
608
  getFlag(name: string): boolean | string | undefined;
593
609
  /** Register a custom renderer for CustomMessageEntry. */
594
610
  registerMessageRenderer<T = unknown>(customType: string, renderer: MessageRenderer<T>): void;
611
+ /** Register a renderer for assistant thinking blocks. Rendered after the original thinking text. */
612
+ registerAssistantThinkingRenderer(renderer: AssistantThinkingRenderer): void;
595
613
  /**
596
614
  * Send a custom message to the session.
597
615
  *
@@ -840,6 +858,7 @@ export interface Extension {
840
858
  label?: string;
841
859
  handlers: Map<string, HandlerFn[]>;
842
860
  tools: Map<string, RegisteredTool<any, any>>;
861
+ assistantThinkingRenderers: AssistantThinkingRenderer[];
843
862
  messageRenderers: Map<string, MessageRenderer>;
844
863
  commands: Map<string, RegisteredCommand>;
845
864
  flags: Map<string, ExtensionFlag>;
@@ -13,6 +13,17 @@ import * as path from "node:path";
13
13
  * Exported for tests; production callers use `BUNFS_PACKAGE_ROOT` below.
14
14
  */
15
15
  export declare function __computeBunfsPackageRoot(metaDir: string, pathImpl?: typeof path): string;
16
+ /**
17
+ * Load a legacy Pi extension module from its real on-disk location.
18
+ *
19
+ * The extension runs in place, so its `import.meta.url` is the real source file
20
+ * and `__dirname`-relative `readFileSync` asset loads (HTML/CSS bundled next to
21
+ * the entry) resolve exactly as they do under the original Pi runtime — no
22
+ * temp-directory mirroring and no asset copying. An `onLoad` hook scoped to the
23
+ * entry's relative-import graph rewrites only the legacy `@(scope)/pi-*` and
24
+ * `@sinclair/typebox` imports in the extension's own source; everything else
25
+ * resolves natively.
26
+ */
16
27
  export declare function loadLegacyPiModule(resolvedPath: string): Promise<unknown>;
17
28
  export declare function installLegacyPiSpecifierShim(): void;
18
29
  /** Test seam: clears the memoized canonical specifier resolutions. */
@@ -0,0 +1,10 @@
1
+ import type { FileDiagnosticsResult } from "./index";
2
+ export declare function diagnosticIdentity(message: string): string;
3
+ export declare class DiagnosticsLedger {
4
+ #private;
5
+ reduce(absPath: string, result: FileDiagnosticsResult): FileDiagnosticsResult;
6
+ }
7
+ export interface DiagnosticsLedgerOwner {
8
+ diagnosticsLedger?: DiagnosticsLedger;
9
+ }
10
+ export declare function getDiagnosticsLedger(owner: DiagnosticsLedgerOwner): DiagnosticsLedger;
@@ -71,6 +71,8 @@ export interface WritethroughOptions {
71
71
  onDeferredDiagnostics?: (diagnostics: FileDiagnosticsResult) => void;
72
72
  /** Signal to cancel a pending deferred diagnostics fetch. */
73
73
  deferredSignal?: AbortSignal;
74
+ /** Transform diagnostics before surfacing them after a successful fetch. */
75
+ transformDiagnostics?: (absPath: string, result: FileDiagnosticsResult) => FileDiagnosticsResult;
74
76
  }
75
77
  /** Per-file deferred LSP diagnostics wiring for {@link WritethroughCallback}. */
76
78
  export type WritethroughDeferredHandle = {
@@ -39,6 +39,10 @@ export declare function formatGroupedDiagnosticMessages(messages: string[]): str
39
39
  * Format diagnostics grouped by severity.
40
40
  */
41
41
  export declare function formatDiagnosticsSummary(diagnostics: Diagnostic[]): string;
42
+ export declare function summarizeDiagnosticMessages(messages: string[]): {
43
+ summary: string;
44
+ errored: boolean;
45
+ };
42
46
  /**
43
47
  * Format a location as file:line:col relative to cwd.
44
48
  */
@@ -12,6 +12,7 @@ import type { SubmittedUserInput } from "./modes/types";
12
12
  import { type CreateAgentSessionOptions, type CreateAgentSessionResult, createAgentSession, discoverAuthStorage } from "./sdk";
13
13
  import type { AgentSession } from "./session/agent-session";
14
14
  import type { AuthStorage } from "./session/auth-storage";
15
+ import { type SessionInfo, SessionManager } from "./session/session-manager";
15
16
  export interface InteractiveModeNotify {
16
17
  kind: "warn" | "error" | "info";
17
18
  message: string;
@@ -39,6 +40,10 @@ export interface AcpSessionFactoryOptions {
39
40
  * tool registry and shadow the client-supplied servers (issue #1234).
40
41
  */
41
42
  export declare function createAcpSessionFactory(args: AcpSessionFactoryOptions): AcpSessionFactory;
43
+ type ForkSessionPromptResult = "accepted" | "declined" | "unavailable";
44
+ type ForkSessionPrompt = (session: SessionInfo) => Promise<ForkSessionPromptResult>;
45
+ /** Resolves CLI session flags into an existing, forked, in-memory, or cancelled session manager. */
46
+ export declare function createSessionManager(parsed: Args, cwd: string, activeSettings?: Settings, askToForkSession?: ForkSessionPrompt): Promise<SessionManager | undefined>;
42
47
  interface RunRootCommandDependencies {
43
48
  createAgentSession?: typeof createAgentSession;
44
49
  discoverAuthStorage?: typeof discoverAuthStorage;
@@ -1,5 +1,5 @@
1
1
  import { type Agent, type AgentSideConnection, type AuthenticateRequest, type AuthenticateResponse, type ClientCapabilities, type CloseSessionRequest, type CloseSessionResponse, type ForkSessionRequest, type ForkSessionResponse, type InitializeRequest, type InitializeResponse, type ListSessionsRequest, type ListSessionsResponse, type LoadSessionRequest, type LoadSessionResponse, type NewSessionRequest, type NewSessionResponse, type PromptRequest, type PromptResponse, type ResumeSessionRequest, type ResumeSessionResponse, type SetSessionConfigOptionRequest, type SetSessionConfigOptionResponse, type SetSessionModelRequest, type SetSessionModelResponse, type SetSessionModeRequest, type SetSessionModeResponse } from "@agentclientprotocol/sdk";
2
- import type { ExtensionUIContext } from "../../extensibility/extensions";
2
+ import { type ExtensionUIContext } from "../../extensibility/extensions";
3
3
  import type { AgentSession } from "../../session/agent-session";
4
4
  /**
5
5
  * Delay between `session/new` (or `session/load` / `session/resume` /
@@ -1,5 +1,6 @@
1
1
  import type { AssistantMessage, ImageContent, Usage } from "@oh-my-pi/pi-ai";
2
2
  import { Container } from "@oh-my-pi/pi-tui";
3
+ import type { AssistantThinkingRenderer } from "../../extensibility/extensions/types";
3
4
  /**
4
5
  * Component that renders a complete assistant message
5
6
  */
@@ -7,7 +8,8 @@ export declare class AssistantMessageComponent extends Container {
7
8
  #private;
8
9
  private hideThinkingBlock;
9
10
  private readonly onImageUpdate?;
10
- constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, onImageUpdate?: (() => void) | undefined);
11
+ private readonly thinkingRenderers;
12
+ constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, onImageUpdate?: (() => void) | undefined, thinkingRenderers?: readonly AssistantThinkingRenderer[]);
11
13
  invalidate(): void;
12
14
  setHideThinkingBlock(hide: boolean): void;
13
15
  setToolResultImages(toolCallId: string, images: ImageContent[]): void;
@@ -1,6 +1,6 @@
1
1
  import { Editor, type KeyId } from "@oh-my-pi/pi-tui";
2
2
  import type { AppKeybinding } from "../../config/keybindings";
3
- type ConfigurableEditorAction = Extract<AppKeybinding, "app.interrupt" | "app.clear" | "app.exit" | "app.suspend" | "app.thinking.cycle" | "app.model.cycleForward" | "app.model.cycleBackward" | "app.model.select" | "app.model.selectTemporary" | "app.tools.expand" | "app.thinking.toggle" | "app.editor.external" | "app.history.search" | "app.message.dequeue" | "app.clipboard.pasteImage" | "app.clipboard.copyPrompt">;
3
+ type ConfigurableEditorAction = Extract<AppKeybinding, "app.interrupt" | "app.clear" | "app.exit" | "app.suspend" | "app.thinking.cycle" | "app.model.cycleForward" | "app.model.cycleBackward" | "app.model.select" | "app.model.selectTemporary" | "app.tools.expand" | "app.thinking.toggle" | "app.editor.external" | "app.history.search" | "app.message.dequeue" | "app.clipboard.pasteImage" | "app.clipboard.pasteTextRaw" | "app.clipboard.copyPrompt">;
4
4
  /**
5
5
  * Custom editor that handles configurable app-level shortcuts for coding-agent.
6
6
  */
@@ -10,7 +10,6 @@ export declare class CustomEditor extends Editor {
10
10
  * them, skipping any occurrence inside code spans, fenced blocks, or XML sections. */
11
11
  decorateText: (text: string) => string;
12
12
  onEscape?: () => void;
13
- shouldBypassAutocompleteOnEscape?: () => boolean;
14
13
  onClear?: () => void;
15
14
  onExit?: () => void;
16
15
  onCycleThinkingLevel?: () => void;
@@ -27,6 +26,8 @@ export declare class CustomEditor extends Editor {
27
26
  onCopyPrompt?: () => void;
28
27
  /** Called when the configured image-paste shortcut is pressed. */
29
28
  onPasteImage?: () => Promise<boolean>;
29
+ /** Called when the configured raw text-paste shortcut is pressed. */
30
+ onPasteTextRaw?: () => void;
30
31
  /** Called when the configured dequeue shortcut is pressed. */
31
32
  onDequeue?: () => void;
32
33
  /** Called when Caps Lock is pressed. */
@@ -41,10 +41,19 @@ export interface HookSelectorOptions {
41
41
  onExternalEditor?: () => void;
42
42
  helpText?: string;
43
43
  slider?: HookSelectorSlider;
44
+ /** Indices into the original options that cannot be selected: they render
45
+ * dimmed, are skipped during navigation, and reject enter/timeout. */
46
+ disabledIndices?: readonly number[];
44
47
  }
48
+ export interface HookSelectorOption {
49
+ label: string;
50
+ description?: string;
51
+ }
52
+ export type HookSelectorOptionInput = string | HookSelectorOption;
45
53
  export declare class HookSelectorComponent extends Container {
46
54
  #private;
47
- constructor(title: string, options: string[], onSelect: (option: string) => void, onCancel: () => void, opts?: HookSelectorOptions);
55
+ constructor(title: string, options: HookSelectorOptionInput[], onSelect: (option: string) => void, onCancel: () => void, opts?: HookSelectorOptions);
48
56
  handleInput(keyData: string): void;
57
+ render(width: number): string[];
49
58
  dispose(): void;
50
59
  }
@@ -1,28 +1,55 @@
1
1
  import { type Component, Container } from "@oh-my-pi/pi-tui";
2
2
  import type { SessionInfo } from "../../session/session-manager";
3
+ /** Returns the IDs of sessions whose recorded prompts match a query, best first. */
4
+ export type SessionHistoryMatcher = (query: string) => string[];
5
+ /**
6
+ * Combine fuzzy session matches with prompt-history matches for ranking, using
7
+ * both signals rather than replacing one with the other.
8
+ *
9
+ * - `fuzzy` is the ordered fuzzy-filter result over session metadata (best first).
10
+ * - `historyIds` are session IDs whose recorded prompts matched the query,
11
+ * ordered by history relevance (best first); duplicates are tolerated.
12
+ *
13
+ * Ranking: sessions matched by **both** signals lead (keeping fuzzy order), then
14
+ * fuzzy-only matches, then history-only matches (by history order). A fuzzy match
15
+ * is never dropped, and history matches not present in `allSessions` (e.g. deleted
16
+ * or out-of-scope sessions) are ignored since they cannot be resumed from here.
17
+ */
18
+ export declare function mergeSessionRanking(allSessions: SessionInfo[], fuzzy: SessionInfo[], historyIds: string[]): SessionInfo[];
3
19
  /**
4
20
  * Custom session list component with multi-line items and search
5
21
  */
6
22
  declare class SessionList implements Component {
7
23
  #private;
8
- private readonly allSessions;
9
- private readonly showCwd;
10
- onSelect?: (sessionPath: string) => void;
24
+ onSelect?: (session: SessionInfo) => void;
11
25
  onCancel?: () => void;
12
26
  onExit: () => void;
27
+ onToggleScope?: () => void;
13
28
  onDeleteRequest?: (session: SessionInfo) => void;
14
- constructor(allSessions: SessionInfo[], showCwd?: boolean);
29
+ constructor(sessions: SessionInfo[], showCwd?: boolean, historyMatcher?: SessionHistoryMatcher);
30
+ /** Replace the visible dataset, e.g. when toggling folder/all-projects scope. */
31
+ setSessions(sessions: SessionInfo[], showCwd: boolean): void;
15
32
  removeSession(sessionPath: string): void;
16
33
  invalidate(): void;
17
34
  render(width: number): string[];
18
35
  handleInput(keyData: string): void;
19
36
  }
37
+ export interface SessionSelectorOptions {
38
+ onDelete?: (session: SessionInfo) => Promise<boolean>;
39
+ historyMatcher?: SessionHistoryMatcher;
40
+ /** Loads sessions across all projects for the all-projects scope toggle (Tab). */
41
+ loadAllSessions?: () => Promise<SessionInfo[]>;
42
+ /** Preloaded all-projects list; cached so the first Tab toggle is instant. */
43
+ allSessions?: SessionInfo[];
44
+ /** Open directly in all-projects scope (e.g. the current folder has no sessions). */
45
+ startInAllScope?: boolean;
46
+ }
20
47
  /**
21
48
  * Component that renders a session selector with optional confirmation dialog
22
49
  */
23
50
  export declare class SessionSelectorComponent extends Container {
24
51
  #private;
25
- constructor(sessions: SessionInfo[], onSelect: (sessionPath: string) => void, onCancel: () => void, onExit: () => void, onDelete?: (session: SessionInfo) => Promise<boolean>);
52
+ constructor(sessions: SessionInfo[], onSelect: (session: SessionInfo) => void, onCancel: () => void, onExit: () => void, options?: SessionSelectorOptions);
26
53
  setOnRequestRender(callback: () => void): void;
27
54
  handleInput(keyData: string): void;
28
55
  getSessionList(): SessionList;