@oh-my-pi/pi-coding-agent 17.1.5 → 17.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/{CHANGELOG-qs3vd6xf.md → CHANGELOG-5k4dq4g6.md} +54 -0
  3. package/dist/cli.js +3342 -3274
  4. package/dist/types/capability/index.d.ts +1 -1
  5. package/dist/types/capability/types.d.ts +23 -1
  6. package/dist/types/config/settings-schema.d.ts +39 -2
  7. package/dist/types/cursor.d.ts +2 -1
  8. package/dist/types/extensibility/extensions/runner.d.ts +4 -0
  9. package/dist/types/extensibility/shared-events.d.ts +18 -1
  10. package/dist/types/internal-urls/mcp-protocol.d.ts +3 -2
  11. package/dist/types/internal-urls/parse.d.ts +12 -0
  12. package/dist/types/internal-urls/router.d.ts +6 -0
  13. package/dist/types/internal-urls/types.d.ts +6 -0
  14. package/dist/types/lsp/config.d.ts +1 -0
  15. package/dist/types/lsp/types.d.ts +2 -0
  16. package/dist/types/mcp/manager.d.ts +5 -0
  17. package/dist/types/mcp/tool-bridge.d.ts +13 -0
  18. package/dist/types/modes/components/custom-editor.d.ts +5 -0
  19. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
  20. package/dist/types/modes/rpc/rpc-mode.d.ts +2 -0
  21. package/dist/types/sdk.d.ts +3 -1
  22. package/dist/types/session/agent-session-types.d.ts +8 -6
  23. package/dist/types/session/agent-session.d.ts +28 -1
  24. package/dist/types/session/model-controls.d.ts +4 -1
  25. package/dist/types/session/session-advisors.d.ts +7 -1
  26. package/dist/types/session/session-tools.d.ts +44 -6
  27. package/dist/types/session/streaming-output.d.ts +7 -2
  28. package/dist/types/session/tool-choice-queue.d.ts +6 -4
  29. package/dist/types/session/turn-recovery.d.ts +5 -3
  30. package/dist/types/task/index.d.ts +1 -1
  31. package/dist/types/task/types.d.ts +3 -11
  32. package/dist/types/thinking.d.ts +21 -2
  33. package/dist/types/tools/index.d.ts +8 -3
  34. package/dist/types/tools/output-meta.d.ts +5 -0
  35. package/dist/types/tools/read.d.ts +9 -1
  36. package/dist/types/tools/xdev.d.ts +53 -67
  37. package/dist/types/utils/cpuprofile.d.ts +51 -0
  38. package/dist/types/utils/inspect-image-mode.d.ts +29 -0
  39. package/dist/types/utils/profile-tree.d.ts +47 -0
  40. package/dist/types/utils/sample-profile.d.ts +67 -0
  41. package/dist/types/utils/title-generator.d.ts +17 -16
  42. package/package.json +12 -12
  43. package/src/capability/index.ts +43 -12
  44. package/src/capability/mcp.ts +21 -0
  45. package/src/capability/types.ts +20 -1
  46. package/src/cli/read-cli.ts +44 -2
  47. package/src/config/settings-schema.ts +42 -2
  48. package/src/config/settings.ts +35 -0
  49. package/src/cursor.ts +4 -3
  50. package/src/discovery/builtin-rules/index.ts +2 -0
  51. package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
  52. package/src/eval/py/runner.py +16 -2
  53. package/src/extensibility/extensions/runner.ts +117 -5
  54. package/src/extensibility/extensions/types.ts +0 -1
  55. package/src/extensibility/extensions/wrapper.ts +74 -42
  56. package/src/extensibility/hooks/tool-wrapper.ts +11 -4
  57. package/src/extensibility/hooks/types.ts +0 -1
  58. package/src/extensibility/shared-events.ts +18 -1
  59. package/src/internal-urls/mcp-protocol.ts +17 -3
  60. package/src/internal-urls/parse.ts +31 -0
  61. package/src/internal-urls/router.ts +24 -4
  62. package/src/internal-urls/types.ts +6 -0
  63. package/src/live/transport.ts +2 -2
  64. package/src/lsp/client.ts +2 -2
  65. package/src/lsp/config.ts +4 -0
  66. package/src/lsp/types.ts +2 -0
  67. package/src/mcp/config.ts +26 -14
  68. package/src/mcp/manager.ts +26 -9
  69. package/src/mcp/tool-bridge.ts +52 -1
  70. package/src/memories/index.ts +25 -6
  71. package/src/modes/components/custom-editor.ts +39 -16
  72. package/src/modes/components/status-line/segments.ts +3 -1
  73. package/src/modes/components/tips.txt +2 -1
  74. package/src/modes/components/tool-execution.ts +8 -7
  75. package/src/modes/controllers/command-controller.ts +10 -10
  76. package/src/modes/controllers/extension-ui-controller.ts +7 -7
  77. package/src/modes/controllers/selector-controller.ts +7 -2
  78. package/src/modes/rpc/rpc-mode.ts +60 -47
  79. package/src/prompts/steering/user-interjection.md +2 -5
  80. package/src/prompts/tools/task.md +4 -2
  81. package/src/sdk.ts +64 -58
  82. package/src/session/agent-session-types.ts +8 -5
  83. package/src/session/agent-session.ts +144 -11
  84. package/src/session/model-controls.ts +48 -12
  85. package/src/session/session-advisors.ts +30 -14
  86. package/src/session/session-listing.ts +66 -4
  87. package/src/session/session-tools.ts +162 -54
  88. package/src/session/streaming-output.ts +18 -6
  89. package/src/session/tool-choice-queue.ts +19 -4
  90. package/src/session/turn-recovery.ts +25 -6
  91. package/src/slash-commands/builtin-registry.ts +69 -0
  92. package/src/task/executor.ts +11 -3
  93. package/src/task/index.ts +43 -32
  94. package/src/task/types.ts +12 -17
  95. package/src/thinking.ts +68 -5
  96. package/src/tools/bash.ts +16 -9
  97. package/src/tools/index.ts +36 -16
  98. package/src/tools/output-meta.ts +20 -0
  99. package/src/tools/read.ts +89 -15
  100. package/src/tools/write.ts +16 -7
  101. package/src/tools/xdev.ts +198 -210
  102. package/src/utils/cpuprofile.ts +235 -0
  103. package/src/utils/inspect-image-mode.ts +39 -0
  104. package/src/utils/profile-tree.ts +111 -0
  105. package/src/utils/sample-profile.ts +437 -0
  106. package/src/utils/title-generator.ts +88 -34
  107. package/dist/types/advisor/__tests__/advisor.test.d.ts +0 -1
  108. package/dist/types/advisor/__tests__/config.test.d.ts +0 -1
  109. package/dist/types/advisor/__tests__/emission-guard.test.d.ts +0 -1
  110. package/dist/types/cli/__tests__/auth-gateway-catalog.test.d.ts +0 -1
  111. package/dist/types/cli/update-cli.test.d.ts +0 -1
  112. package/dist/types/config/__tests__/model-registry.test.d.ts +0 -1
  113. package/dist/types/eval/__tests__/agent-bridge.test.d.ts +0 -1
  114. package/dist/types/eval/__tests__/bridge-timeout.test.d.ts +0 -1
  115. package/dist/types/eval/__tests__/budget-bridge.test.d.ts +0 -1
  116. package/dist/types/eval/__tests__/completion-bridge.test.d.ts +0 -1
  117. package/dist/types/eval/__tests__/helpers-local-roots.test.d.ts +0 -1
  118. package/dist/types/eval/__tests__/idle-timeout.test.d.ts +0 -1
  119. package/dist/types/eval/__tests__/js-context-manager.test.d.ts +0 -1
  120. package/dist/types/eval/__tests__/julia-prelude.test.d.ts +0 -1
  121. package/dist/types/eval/__tests__/kernel-spawn.test.d.ts +0 -1
  122. package/dist/types/eval/__tests__/prelude-agent.test.d.ts +0 -1
  123. package/dist/types/eval/__tests__/process-entry-import.test.d.ts +0 -1
  124. package/dist/types/eval/py/__tests__/prelude.test.d.ts +0 -1
  125. package/dist/types/eval/py/__tests__/runner-shell-output.test.d.ts +0 -1
  126. package/dist/types/hindsight/client.test.d.ts +0 -1
  127. package/dist/types/internal-urls/__tests__/agent-protocol-nested.test.d.ts +0 -1
  128. package/dist/types/internal-urls/__tests__/ssh-protocol.test.d.ts +0 -1
  129. package/dist/types/launch/broker-list-order.test.d.ts +0 -1
  130. package/dist/types/launch/broker-output-snapshot.test.d.ts +0 -1
  131. package/dist/types/launch/protocol.test.d.ts +0 -1
  132. package/dist/types/launch/spawn-options.test.d.ts +0 -1
  133. package/dist/types/launch/terminal-output.test.d.ts +0 -1
  134. package/dist/types/live/protocol.test.d.ts +0 -1
  135. package/dist/types/mcp/config-writer.test.d.ts +0 -1
  136. package/dist/types/mcp/smithery-auth.test.d.ts +0 -1
  137. package/dist/types/mcp/smithery-registry.test.d.ts +0 -1
  138. package/dist/types/mcp/transports/stdio.test.d.ts +0 -1
  139. package/dist/types/modes/components/__tests__/dynamic-border.test.d.ts +0 -1
  140. package/dist/types/modes/components/__tests__/move-overlay.test.d.ts +0 -1
  141. package/dist/types/modes/components/__tests__/pause-screen.test.d.ts +0 -1
  142. package/dist/types/modes/components/__tests__/skill-message.test.d.ts +0 -1
  143. package/dist/types/modes/components/custom-editor-plugin-ctor.test.d.ts +0 -1
  144. package/dist/types/modes/components/custom-editor.test.d.ts +0 -1
  145. package/dist/types/modes/components/login-dialog.test.d.ts +0 -1
  146. package/dist/types/modes/components/status-line/component.jj-cache.test.d.ts +0 -1
  147. package/dist/types/modes/components/status-line/component.test.d.ts +0 -1
  148. package/dist/types/modes/components/tool-execution.test.d.ts +0 -1
  149. package/dist/types/modes/controllers/extension-ui-controller.test.d.ts +0 -1
  150. package/dist/types/modes/noninteractive-dispose.test.d.ts +0 -1
  151. package/dist/types/modes/print-mode.test.d.ts +0 -1
  152. package/dist/types/modes/session-teardown.test.d.ts +0 -1
  153. package/dist/types/modes/theme/mermaid-rendering.test.d.ts +0 -1
  154. package/dist/types/modes/utils/transcript-render-helpers.test.d.ts +0 -1
  155. package/dist/types/modes/warp-events.test.d.ts +0 -1
  156. package/dist/types/plan-mode/approved-plan-prompt.test.d.ts +0 -1
  157. package/dist/types/plan-mode/model-transition.test.d.ts +0 -1
  158. package/dist/types/plan-mode/reentry-prompt.test.d.ts +0 -1
  159. package/dist/types/session/agent-session-error-log.test.d.ts +0 -1
  160. package/dist/types/session/blob-store.test.d.ts +0 -1
  161. package/dist/types/session/messages.test.d.ts +0 -1
  162. package/dist/types/session/session-context.test.d.ts +0 -1
  163. package/dist/types/ssh/__tests__/connection-manager-args.test.d.ts +0 -1
  164. package/dist/types/ssh/__tests__/connection-manager-timeout.test.d.ts +0 -1
  165. package/dist/types/ssh/__tests__/file-transfer-posix-guard.test.d.ts +0 -1
  166. package/dist/types/ssh/__tests__/sshfs-mount.test.d.ts +0 -1
  167. package/dist/types/system-prompt.test.d.ts +0 -1
  168. package/dist/types/task/render.test.d.ts +0 -1
  169. package/dist/types/task/spawn-policy.test.d.ts +0 -1
  170. package/dist/types/tools/__tests__/eval-description.test.d.ts +0 -1
  171. package/dist/types/tools/__tests__/glob.test.d.ts +0 -1
  172. package/dist/types/tools/__tests__/json-tree.test.d.ts +0 -1
  173. package/dist/types/tools/__tests__/vibe-render.test.d.ts +0 -1
  174. package/dist/types/tools/hub/launch-compat.test.d.ts +0 -1
  175. package/dist/types/vibe/__tests__/token-rate.test.d.ts +0 -1
  176. package/src/advisor/__tests__/advisor.test.ts +0 -4889
  177. package/src/advisor/__tests__/config.test.ts +0 -349
  178. package/src/advisor/__tests__/emission-guard.test.ts +0 -147
  179. package/src/cli/__tests__/auth-gateway-catalog.test.ts +0 -111
  180. package/src/cli/update-cli.test.ts +0 -28
  181. package/src/config/__tests__/model-registry.test.ts +0 -182
  182. package/src/eval/__tests__/agent-bridge.test.ts +0 -1509
  183. package/src/eval/__tests__/bridge-timeout.test.ts +0 -170
  184. package/src/eval/__tests__/budget-bridge.test.ts +0 -80
  185. package/src/eval/__tests__/completion-bridge.test.ts +0 -412
  186. package/src/eval/__tests__/helpers-local-roots.test.ts +0 -55
  187. package/src/eval/__tests__/idle-timeout.test.ts +0 -80
  188. package/src/eval/__tests__/js-context-manager.test.ts +0 -456
  189. package/src/eval/__tests__/julia-prelude.test.ts +0 -66
  190. package/src/eval/__tests__/kernel-spawn.test.ts +0 -115
  191. package/src/eval/__tests__/prelude-agent.test.ts +0 -156
  192. package/src/eval/__tests__/process-entry-import.test.ts +0 -137
  193. package/src/eval/py/__tests__/prelude.test.ts +0 -104
  194. package/src/eval/py/__tests__/runner-shell-output.test.ts +0 -157
  195. package/src/hindsight/client.test.ts +0 -75
  196. package/src/internal-urls/__tests__/agent-protocol-nested.test.ts +0 -141
  197. package/src/internal-urls/__tests__/ssh-protocol.test.ts +0 -331
  198. package/src/launch/broker-list-order.test.ts +0 -89
  199. package/src/launch/broker-output-snapshot.test.ts +0 -126
  200. package/src/launch/protocol.test.ts +0 -59
  201. package/src/launch/spawn-options.test.ts +0 -31
  202. package/src/launch/terminal-output.test.ts +0 -107
  203. package/src/live/protocol.test.ts +0 -140
  204. package/src/mcp/config-writer.test.ts +0 -43
  205. package/src/mcp/smithery-auth.test.ts +0 -29
  206. package/src/mcp/smithery-registry.test.ts +0 -51
  207. package/src/mcp/transports/stdio.test.ts +0 -427
  208. package/src/modes/components/__tests__/dynamic-border.test.ts +0 -55
  209. package/src/modes/components/__tests__/move-overlay.test.ts +0 -252
  210. package/src/modes/components/__tests__/pause-screen.test.ts +0 -143
  211. package/src/modes/components/__tests__/skill-message.test.ts +0 -94
  212. package/src/modes/components/custom-editor-plugin-ctor.test.ts +0 -36
  213. package/src/modes/components/custom-editor.test.ts +0 -510
  214. package/src/modes/components/login-dialog.test.ts +0 -56
  215. package/src/modes/components/status-line/component.jj-cache.test.ts +0 -229
  216. package/src/modes/components/status-line/component.test.ts +0 -84
  217. package/src/modes/components/tool-execution.test.ts +0 -162
  218. package/src/modes/controllers/extension-ui-controller.test.ts +0 -250
  219. package/src/modes/noninteractive-dispose.test.ts +0 -73
  220. package/src/modes/print-mode.test.ts +0 -71
  221. package/src/modes/session-teardown.test.ts +0 -219
  222. package/src/modes/theme/mermaid-rendering.test.ts +0 -53
  223. package/src/modes/utils/transcript-render-helpers.test.ts +0 -38
  224. package/src/modes/warp-events.test.ts +0 -794
  225. package/src/plan-mode/approved-plan-prompt.test.ts +0 -36
  226. package/src/plan-mode/model-transition.test.ts +0 -60
  227. package/src/plan-mode/reentry-prompt.test.ts +0 -41
  228. package/src/session/agent-session-error-log.test.ts +0 -59
  229. package/src/session/blob-store.test.ts +0 -56
  230. package/src/session/messages.test.ts +0 -282
  231. package/src/session/session-context.test.ts +0 -384
  232. package/src/ssh/__tests__/connection-manager-args.test.ts +0 -191
  233. package/src/ssh/__tests__/connection-manager-timeout.test.ts +0 -61
  234. package/src/ssh/__tests__/file-transfer-posix-guard.test.ts +0 -105
  235. package/src/ssh/__tests__/sshfs-mount.test.ts +0 -13
  236. package/src/system-prompt.test.ts +0 -236
  237. package/src/task/render.test.ts +0 -290
  238. package/src/task/spawn-policy.test.ts +0 -62
  239. package/src/tools/__tests__/eval-description.test.ts +0 -18
  240. package/src/tools/__tests__/glob.test.ts +0 -37
  241. package/src/tools/__tests__/json-tree.test.ts +0 -35
  242. package/src/tools/__tests__/vibe-render.test.ts +0 -210
  243. package/src/tools/hub/launch-compat.test.ts +0 -40
  244. package/src/vibe/__tests__/token-rate.test.ts +0 -96
@@ -8,14 +8,14 @@ export interface RejectInfo {
8
8
  choice: ToolChoice;
9
9
  reason: "aborted" | "error" | "cleared" | "removed" | "unavailable" | "not_invoked";
10
10
  }
11
- /** "requeue" replays the lost yield next turn; "drop" (or void/undefined) discards it. */
12
- export type RejectOutcome = "requeue" | "drop";
11
+ /** Controls whether rejection replays a yield, drops it, or drops its remaining sequence. */
12
+ export type RejectOutcome = "requeue" | "drop" | "drop_sequence";
13
13
  export interface DirectiveCallbacks {
14
14
  /** Fires when the yield completed; onInvoked directives require the requested tool to run first. */
15
15
  onResolved?: (info: ResolveInfo) => void;
16
16
  /**
17
- * Fires when the yield is being discarded. Return "requeue" to replay the
18
- * same value at the head of the queue for the next turn. Default: "drop".
17
+ * Return "requeue" to replay the same value, or "drop_sequence" to discard
18
+ * its directive including later yields. Default: drop the rejected yield.
19
19
  */
20
20
  onRejected?: (info: RejectInfo) => RejectOutcome | undefined;
21
21
  /**
@@ -30,6 +30,8 @@ export interface ToolChoiceDirective {
30
30
  /** Stable label for targeted removal and debugging (e.g. "user-force"). */
31
31
  label: string;
32
32
  callbacks: DirectiveCallbacks;
33
+ /** Original multi-yield directive retained across one-yield replays. */
34
+ sequenceRoot?: ToolChoiceDirective;
33
35
  }
34
36
  export interface PushOptions {
35
37
  /** Prepend to head instead of appending to tail. Default: false. */
@@ -1,8 +1,8 @@
1
1
  import { type Agent, type AgentMessage, type ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { AssistantMessage, CodexCompactionContext, Model, ToolChoice } from "@oh-my-pi/pi-ai";
2
+ import type { AssistantMessage, CodexCompactionContext, Effort, Model, ToolChoice } from "@oh-my-pi/pi-ai";
3
3
  import type { ModelRegistry } from "../config/model-registry.js";
4
4
  import type { Settings } from "../config/settings.js";
5
- import type { ConfiguredThinkingLevel } from "../thinking.js";
5
+ import { type ConfiguredThinkingLevel } from "../thinking.js";
6
6
  import type { AgentSessionEvent } from "./agent-session-events.js";
7
7
  import type { InitialRetryFallbackState } from "./agent-session-types.js";
8
8
  import { type RetryFallbackSelector } from "./retry-fallback-chains.js";
@@ -25,6 +25,8 @@ export interface TurnRecoveryHost {
25
25
  thinkingLevel(): ThinkingLevel | undefined;
26
26
  configuredThinkingLevel(): ConfiguredThinkingLevel | undefined;
27
27
  setThinkingLevel(level: ConfiguredThinkingLevel | undefined): void;
28
+ /** Hard per-session effort ceiling; fallback recovery must never raise thinking above it. */
29
+ thinkingLevelCeiling(): Effort | undefined;
28
30
  isDisposed(): boolean;
29
31
  isStreaming(): boolean;
30
32
  isCompacting(): boolean;
@@ -41,7 +43,7 @@ export interface TurnRecoveryHost {
41
43
  waitForSessionMessagePersistence(message: AssistantMessage): Promise<void>;
42
44
  appendSessionMessage(message: AssistantMessage): void;
43
45
  sessionMessageAlreadyPersisted(message: AssistantMessage): boolean;
44
- setModelWithProviderSessionReset(model: Model): void;
46
+ setModelWithProviderSessionReset(model: Model): Promise<void>;
45
47
  resetCurrentResponsesProviderSession(reason: string): void;
46
48
  maybeAutoRedeemCodexReset(): Promise<boolean>;
47
49
  runAutoCompaction(reason: "overflow" | "threshold" | "idle" | "incomplete", willRetry: boolean, deferred?: boolean, allowDefer?: boolean, options?: {
@@ -71,7 +71,7 @@ export declare class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskT
71
71
  readonly mergeCallAndResult = true;
72
72
  get parameters(): TaskToolSchemaInstance;
73
73
  renderCall(args: unknown, options: Parameters<typeof renderTaskCall>[1], theme: Theme): import("@oh-my-pi/pi-tui").Component;
74
- /** Dynamic description that reflects current disabled-agent settings */
74
+ /** Dynamic description that reflects current task settings. */
75
75
  get description(): string;
76
76
  private constructor();
77
77
  /**
@@ -83,7 +83,6 @@ export declare const taskItemSchema: import("arktype/internal/variants/object.ts
83
83
  name?: string | undefined;
84
84
  agent: import("arktype/internal/attributes.ts").Default<string, "task">;
85
85
  task: string;
86
- effort?: "hi" | "lo" | "med" | undefined;
87
86
  outputSchema?: string | boolean | object | null | undefined;
88
87
  schemaMode?: "permissive" | "strict" | undefined;
89
88
  }, {}>;
@@ -108,7 +107,6 @@ export declare const taskSchema: import("arktype/internal/variants/object.ts").O
108
107
  name?: string | undefined;
109
108
  agent: import("arktype/internal/attributes.ts").Default<string, "task">;
110
109
  task: string;
111
- effort?: "hi" | "lo" | "med" | undefined;
112
110
  outputSchema?: string | boolean | object | null | undefined;
113
111
  schemaMode?: "permissive" | "strict" | undefined;
114
112
  isolated?: boolean | undefined;
@@ -117,7 +115,6 @@ declare const ALL_TASK_SCHEMAS: readonly [import("arktype/internal/variants/obje
117
115
  name?: string | undefined;
118
116
  agent: import("arktype/internal/attributes.ts").Default<string, "task">;
119
117
  task: string;
120
- effort?: "hi" | "lo" | "med" | undefined;
121
118
  outputSchema?: string | boolean | object | null | undefined;
122
119
  schemaMode?: "permissive" | "strict" | undefined;
123
120
  isolated?: boolean | undefined;
@@ -125,7 +122,6 @@ declare const ALL_TASK_SCHEMAS: readonly [import("arktype/internal/variants/obje
125
122
  name?: string | undefined;
126
123
  agent: import("arktype/internal/attributes.ts").Default<string, "task">;
127
124
  task: string;
128
- effort?: "hi" | "lo" | "med" | undefined;
129
125
  outputSchema?: string | boolean | object | null | undefined;
130
126
  schemaMode?: "permissive" | "strict" | undefined;
131
127
  }, {}>, import("arktype/internal/variants/object.ts").ObjectType<{
@@ -134,7 +130,6 @@ declare const ALL_TASK_SCHEMAS: readonly [import("arktype/internal/variants/obje
134
130
  name?: string | undefined;
135
131
  agent: import("arktype/internal/attributes.ts").Default<string, "task">;
136
132
  task: string;
137
- effort?: "hi" | "lo" | "med" | undefined;
138
133
  outputSchema?: string | boolean | object | null | undefined;
139
134
  schemaMode?: "permissive" | "strict" | undefined;
140
135
  isolated?: boolean | undefined;
@@ -145,7 +140,6 @@ declare const ALL_TASK_SCHEMAS: readonly [import("arktype/internal/variants/obje
145
140
  name?: string | undefined;
146
141
  agent: import("arktype/internal/attributes.ts").Default<string, "task">;
147
142
  task: string;
148
- effort?: "hi" | "lo" | "med" | undefined;
149
143
  outputSchema?: string | boolean | object | null | undefined;
150
144
  schemaMode?: "permissive" | "strict" | undefined;
151
145
  }[];
@@ -154,14 +148,12 @@ type DynamicTaskSchema = (typeof ALL_TASK_SCHEMAS)[number];
154
148
  export type TaskSchema = typeof taskSchema;
155
149
  /** Active task tool parameter schema for the current isolation / batch flags */
156
150
  export type TaskToolSchemaInstance = DynamicTaskSchema | BaseType;
151
+ /** Build the task wire schema for the current settings and spawn policy. */
157
152
  export declare function getTaskSchema(options: {
158
153
  isolationEnabled: boolean;
159
154
  batchEnabled: boolean;
160
- }): DynamicTaskSchema;
161
- export declare function getTaskSchema(options: {
162
- isolationEnabled: boolean;
163
- batchEnabled: boolean;
164
- defaultAgent: string;
155
+ effortEnabled?: boolean;
156
+ defaultAgent?: string;
165
157
  }): TaskToolSchemaInstance;
166
158
  /**
167
159
  * Runtime params union over both wire shapes. The model sees exactly one shape
@@ -122,9 +122,28 @@ export type TaskEffort = (typeof TASK_EFFORTS)[number];
122
122
  * at — high, xhigh, or max), `med` = the middle (lower of the two middles for
123
123
  * an even-sized range). Without a model, maps over the full canonical range.
124
124
  * Returns `undefined` when the model has no controllable effort surface, so
125
- * callers fall back to their default selector (e.g. `auto`).
125
+ * callers fall back to their default selector (e.g. `auto`). Throws when the
126
+ * configured ceiling is below the model's lowest supported effort.
126
127
  */
127
- export declare function resolveTaskEffortLevel(model: Model | undefined, effort: TaskEffort): Effort | undefined;
128
+ export declare function resolveTaskEffortLevel(model: Model | undefined, effort: TaskEffort, maxEffort?: Effort): Effort | undefined;
129
+ /**
130
+ * Clamps a concrete thinking selector to a per-session effort ceiling (e.g. a
131
+ * task spawn's `task.maxEffort`-capped effort hint). `off`/`inherit`/
132
+ * `undefined` pass through, as do levels already at or below the ceiling.
133
+ * Levels above it snap to the highest model-supported effort at or below the
134
+ * ceiling. A model whose floor exceeds the ceiling has nothing valid to snap
135
+ * to; the requested level is returned unchanged and the caller is responsible
136
+ * for rejecting or skipping such models (see {@link modelSupportsEffortCeiling}).
137
+ */
138
+ export declare function clampThinkingLevelToCeiling(model: Model | undefined, level: Effort | undefined, ceiling: Effort | undefined): Effort | undefined;
139
+ export declare function clampThinkingLevelToCeiling(model: Model | undefined, level: ThinkingLevel | undefined, ceiling: Effort | undefined): ThinkingLevel | undefined;
140
+ /**
141
+ * True when `model` can honor a thinking-effort ceiling: it either has no
142
+ * controllable effort surface (nothing to cap) or supports at least one effort
143
+ * at or below the ceiling. Retry-fallback candidate filtering uses this to
144
+ * skip models whose floor would force the session above the ceiling.
145
+ */
146
+ export declare function modelSupportsEffortCeiling(model: Model, ceiling: Effort): boolean;
128
147
  /**
129
148
  * The provisional concrete level shown while `auto` is configured but before a
130
149
  * turn has been classified. Prefers the model's `defaultLevel`, otherwise High,
@@ -24,12 +24,13 @@ import type { ToolChoiceQueue } from "../session/tool-choice-queue.js";
24
24
  import type { AgentOutputManager } from "../task/output-manager.js";
25
25
  import { type StructuredSubagentSchemaMode } from "../task/types.js";
26
26
  import type { EventBus } from "../utils/event-bus.js";
27
+ import { type InspectImageMode } from "../utils/inspect-image-mode.js";
27
28
  import type { WorkspaceTree } from "../workspace-tree.js";
28
29
  import { type BuiltinToolName, type HiddenToolName } from "./builtin-names.js";
29
30
  import { type CheckpointState, type CompletedRewindState } from "./checkpoint.js";
30
31
  import type { PlanProposalHandler } from "./resolve.js";
31
32
  import { type TodoPhase } from "./todo.js";
32
- import { XdevRegistry } from "./xdev.js";
33
+ import { type XdevState } from "./xdev.js";
33
34
  export * from "../edit/index.js";
34
35
  export * from "../goals/index.js";
35
36
  export * from "../lsp/index.js";
@@ -204,8 +205,10 @@ export interface ToolSession {
204
205
  isToolActive?: (name: string) => boolean;
205
206
  /** Update the active built-in tool predicate when a session changes tools mid-run. */
206
207
  setActiveToolNames?: (names: Iterable<string>) => void;
207
- /** Tools mounted under `xd://` (set by createTools when `tools.xdev` is active); read/write consult it at execute time. */
208
- xdevRegistry?: XdevRegistry;
208
+ /** Canonical map containing every registered tool exactly once. */
209
+ toolRegistry?: Map<string, Tool>;
210
+ /** `xd://` presentation state backed by {@link toolRegistry}. */
211
+ xdev?: XdevState;
209
212
  /** Agent registry for IRC routing across live sessions. */
210
213
  agentRegistry?: AgentRegistry;
211
214
  /** Idle→parked→revive lifecycle owner; lets the hub kill a non-job-backed agent registration. Default: AgentLifecycleManager.global(). */
@@ -227,6 +230,8 @@ export interface ToolSession {
227
230
  getActiveModelString?: () => string | undefined;
228
231
  /** Get the current session model object (provider/api capabilities), regardless of how it was chosen. */
229
232
  getActiveModel?: () => Model | undefined;
233
+ /** Session-scoped inspect_image mode override set by `/vision`; wins over the persisted setting. */
234
+ getInspectImageModeOverride?: () => InspectImageMode | undefined;
230
235
  /** Get the session's live per-family service tiers (undefined = none). Source of truth for subagent `tier.subagent: inherit`. */
231
236
  getServiceTierByFamily?: () => ServiceTierByFamily | undefined;
232
237
  /** Auth storage for passing to subagents (avoids re-discovery) */
@@ -197,6 +197,11 @@ export declare function stripOutputNotice(text: string, meta: OutputMeta | undef
197
197
  * middle elision with the same per-user configuration.
198
198
  */
199
199
  export declare function resolveOutputSinkHeadBytes(s: Settings | undefined): number;
200
+ /**
201
+ * Resolve the `enforceInlineByteCap` budget for streaming tools (bash/ssh)
202
+ * from session settings: the user's spill threshold plus notice slack.
203
+ */
204
+ export declare function resolveInlineByteCapBudget(s: Settings | undefined): number;
200
205
  /**
201
206
  * Resolve the per-line column cap from session settings. Shared by streaming
202
207
  * executors (bash/python/ssh/eval via OutputSink) and the `read` tool's
@@ -56,12 +56,20 @@ export declare class ReadTool implements AgentTool<typeof readSchema, ReadToolDe
56
56
  readonly approval: (args: unknown) => ToolTier;
57
57
  readonly label = "Read";
58
58
  readonly loadMode = "essential";
59
- readonly description: string;
59
+ description: string;
60
60
  readonly parameters: import("arktype/internal/variants/object.ts").ObjectType<{
61
61
  path: string;
62
62
  }, {}>;
63
63
  readonly strict = true;
64
64
  constructor(session: ToolSession);
65
+ /**
66
+ * Re-evaluate the effective inspect_image state; it can flip when the model
67
+ * or the `/vision` override changes after this tool was constructed. Keeps
68
+ * the behavior branch and the advertised description in lockstep. Called
69
+ * per image read and by tool reconciliation before prompt rebuilds (which
70
+ * passes the post-change availability as `availableOverride`).
71
+ */
72
+ syncInspectImageState(availableOverride?: boolean): boolean;
65
73
  execute(_toolCallId: string, params: ReadParams, signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<ReadToolDetails>, _toolContext?: AgentToolContext): Promise<AgentToolResult<ReadToolDetails>>;
66
74
  }
67
75
  interface ReadRenderArgs {
@@ -9,15 +9,20 @@
9
9
  * read xd://<tool> → tool docs + JSON parameter schema
10
10
  * write xd://<tool> → execute: `content` is the JSON args object
11
11
  *
12
+ * Direct and device dispatch share one canonical tool map. The mounted-name
13
+ * set controls presentation only; dispatch accepts the enabled union of
14
+ * top-level active and mounted names. Listing and prompt docs stay
15
+ * mounted-only because top-level tools already ship their schemas.
16
+ *
12
17
  * Args go through the same machinery as native tool calls: validated with
13
18
  * pi-ai's `validateToolArguments` (the schema is returned on mismatch, so a
14
19
  * malformed call self-corrects without a round trip) and streamed through
15
20
  * the write tool's existing incremental `content` decoding for live render
16
21
  * previews. Compared to a dispatcher def this still costs zero *schema
17
22
  * duplication* — one wire schema per tool instead of one per dispatcher
18
- * branch — but full docs + schema for every mounted device are inlined into
19
- * the system prompt (`XdevRegistry.docsAll()`) so no discovery `read` is
20
- * needed before first use; `read xd://<tool>` remains for on-demand re-fetch.
23
+ * branch — but full docs + schema for every mounted device can be inlined
24
+ * into the system prompt, so no discovery read is needed before first use;
25
+ * `read xd://<tool>` remains for on-demand re-fetch.
21
26
  *
22
27
  * Rendering: the write renderer draws NOTHING until the streamed `path` is
23
28
  * known and provably does not target `xd://`; device writes then delegate to
@@ -54,8 +59,7 @@ export type XdevDocsMode = "inline" | "builtins" | "catalog";
54
59
  * while the `xd://` transport is active. Discoverable tools mount unless they
55
60
  * are pinned top-level by {@link XDEV_KEEP_TOP_LEVEL} or carry the transport
56
61
  * itself ({@link XDEV_TRANSPORT_TOOLS}); essential tools never do. The caller
57
- * gates this on the transport being active (a session-owned
58
- * {@link XdevRegistry} existing).
62
+ * gates this on the transport being active.
59
63
  */
60
64
  export declare function isMountableUnderXdev(tool: {
61
65
  name: string;
@@ -72,69 +76,51 @@ export interface XdevDispatch {
72
76
  }
73
77
  /** Wire the wrapped-renderer lookup. Called once by `renderers.ts`. */
74
78
  export declare function setXdevRendererLookup(lookup: (name: string) => ToolRenderer | undefined): void;
75
- /**
76
- * Registry of tools mounted under `xd://` for one session. `createTools`
77
- * mounts discoverable built-ins first; SDK assembly adds custom tools that do
78
- * not opt out. `read`/`write` consult it at execute time.
79
- */
80
- export declare class XdevRegistry {
81
- #private;
82
- constructor(builtins: Iterable<Tool>);
83
- /**
84
- * Replace the dynamic mount set while preserving the built-in devices. Order
85
- * follows `tools`; names absent from it are dropped. A built-in device is
86
- * never shadowed by a same-named dynamic entry.
87
- */
88
- reconcile(tools: Iterable<Tool>): void;
89
- get size(): number;
90
- /** Mounted tools in catalog order: built-ins first, then dynamic mounts. */
91
- list(): readonly Tool[];
92
- get(name: string): Tool | undefined;
93
- /** `{name, summary}` pairs for prompt templates and /tools display. */
94
- entries(): Array<{
95
- name: string;
96
- summary: string;
97
- }>;
98
- /** `read xd://` listing with one device per line. */
99
- listing(): string;
100
- /** Docs + schema for one device; throws with the listing when unknown. */
101
- docs(name: string): string;
102
- /**
103
- * Char budget for the full docs inlined into the system prompt. Large MCP
104
- * catalogs previously shipped every schema top-level; without a cap they
105
- * would bloat every request. Devices past the budget fall back to a
106
- * one-line summary — their docs stay one `read xd://<tool>` away.
107
- */
108
- static readonly DOCS_TOTAL_BUDGET = 48000;
109
- /** A single device's docs above this size never inline: one pathological
110
- * MCP description must not starve every later device. */
111
- static readonly DOCS_PER_DEVICE_CAP = 10000;
112
- /** Description cap for EXTERNAL devices (dynamic mounts: MCP, custom,
113
- * extension, …) in the system-prompt embedding. Built-in devices inline
114
- * their full curated docs; external descriptions are server-controlled
115
- * prose the model can re-fetch, so only the lede earns prompt space. */
116
- static readonly EXTERNAL_DESCRIPTION_CAP = 200;
117
- /**
118
- * Docs + schema for mounted devices, nested under `##` headings for
119
- * system-prompt embedding. Inlines full docs in catalog order (built-ins
120
- * first) until {@link DOCS_TOTAL_BUDGET} is spent; the rest are listed by
121
- * name + summary with a pointer to on-demand `read xd://<tool>` docs.
122
- * Dynamic mounts embed at most {@link EXTERNAL_DESCRIPTION_CAP} description
123
- * chars (schema always intact); `read xd://<tool>` returns the full text.
124
- */
125
- docsAll(mode?: XdevDocsMode, inlinePatterns?: readonly string[]): string;
126
- /** Docs for selected mounted devices under the configured prompt-doc policy. */
127
- docsFor(names: Iterable<string>, mode: XdevDocsMode, inlinePatterns?: readonly string[]): string;
128
- /**
129
- * Execute a device write: `content` is the JSON args object (empty, `?`, or
130
- * `help` returns docs). Args validate against the wrapped tool's schema —
131
- * the schema comes back in the error on mismatch.
132
- */
133
- dispatch(name: string, content: string, toolCallId: string, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback, context?: AgentToolContext): Promise<{
134
- result: AgentToolResult<unknown>;
135
- xdev: XdevDispatch;
136
- }>;
79
+ /** Shared tool state consumed by the `xd://` presentation layer. */
80
+ export interface XdevState {
81
+ /** Canonical session tool map; direct and device dispatch read the same instances. */
82
+ readonly tools: Map<string, Tool>;
83
+ /** Ordered names currently presented as mounted devices. */
84
+ readonly mountedNames: Set<string>;
85
+ /** Names originating from built-in factories, used only for prompt presentation. */
86
+ readonly builtInNames: Set<string>;
87
+ /** Whether a name is active at the top level. */
88
+ readonly isActive: (name: string) => boolean;
89
+ /** Optional execution-only decorator, such as the ACP permission gate. */
90
+ decorateExecution?(tool: Tool): Tool;
137
91
  }
92
+ /** Full-doc character budget for system-prompt mounted-device sections. */
93
+ export declare const XDEV_DOCS_TOTAL_BUDGET = 48000;
94
+ /** Per-device cap preventing one pathological description from starving later devices. */
95
+ export declare const XDEV_DOCS_PER_DEVICE_CAP = 10000;
96
+ /** Description cap for external mounted tools; their full docs remain readable on demand. */
97
+ export declare const XDEV_EXTERNAL_DESCRIPTION_CAP = 200;
98
+ /** Resolve any enabled tool through the canonical session map. */
99
+ export declare function resolveXdevTool(state: XdevState, name: string): Tool | undefined;
100
+ /** Resolve a mounted tool for top-level fallback execution. */
101
+ export declare function resolveMountedXdevTool(state: XdevState, name: string): Tool | undefined;
102
+ /** Resolve a mounted tool with its execution-only permission decorator. */
103
+ export declare function resolveMountedXdevExecutable(state: XdevState, name: string): Tool | undefined;
104
+ /** Mounted tools in presentation order, resolved from the canonical map. */
105
+ export declare function listXdevTools(state: XdevState): Tool[];
106
+ /** `{name, summary}` pairs for prompt templates and `/tools` display. */
107
+ export declare function xdevEntries(state: XdevState): Array<{
108
+ name: string;
109
+ summary: string;
110
+ }>;
111
+ /** `read xd://` listing with one device per line. */
112
+ export declare function xdevListing(state: XdevState): string;
113
+ /** Docs + schema for any enabled tool. */
114
+ export declare function xdevDocs(state: XdevState, name: string): string;
115
+ /** Docs + schema for mounted devices under the configured prompt-doc policy. */
116
+ export declare function xdevDocsAll(state: XdevState, mode?: XdevDocsMode, inlinePatterns?: readonly string[]): string;
117
+ /** Docs for selected mounted devices under the configured prompt-doc policy. */
118
+ export declare function xdevDocsFor(state: XdevState, names: Iterable<string>, mode: XdevDocsMode, inlinePatterns?: readonly string[]): string;
119
+ /** Execute an enabled canonical tool through `write xd://<tool>`. */
120
+ export declare function dispatchXdevTool(state: XdevState, name: string, content: string, toolCallId: string, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback, context?: AgentToolContext): Promise<{
121
+ result: AgentToolResult<unknown>;
122
+ xdev: XdevDispatch;
123
+ }>;
138
124
  /**
139
125
  * Streaming-safe call preview for an `xd://` write: forwards the decoded inner
140
126
  * args to the mounted tool's renderer (session instance first, then the static
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Parser and renderer for V8 `.cpuprofile` files (emitted by `node --cpu-prof`,
3
+ * `bun --cpu-prof`, Chrome DevTools, and the CDP `Profiler` domain).
4
+ *
5
+ * The raw file is a JSON blob with a flat node table and up to millions of
6
+ * sample/timestamp entries — useless to read directly. `renderCpuProfile`
7
+ * converts it into a compact bottleneck summary:
8
+ *
9
+ * - the hot-path call tree, pruned to frames with meaningful self time,
10
+ * with pass-through chains collapsed and direct recursion flattened
11
+ * - `(idle)` time excluded from on-CPU totals
12
+ * - a profile-wide "top functions by self time" table
13
+ *
14
+ * Consumed by the read tool: `*.cpuprofile` reads show the summary, `:raw`
15
+ * returns the original JSON.
16
+ */
17
+ /** Matches paths the read tool should treat as V8 CPU profiles. */
18
+ export declare function isCpuProfilePath(filePath: string): boolean;
19
+ /** Call-site metadata of one profile node. `lineNumber` is 0-based. */
20
+ export interface CpuProfileCallFrame {
21
+ functionName: string;
22
+ url?: string;
23
+ lineNumber?: number;
24
+ }
25
+ /** One node in the flat profile tree; `children` are node ids. */
26
+ export interface CpuProfileNode {
27
+ id: number;
28
+ callFrame: CpuProfileCallFrame;
29
+ hitCount?: number;
30
+ children?: number[];
31
+ }
32
+ /** Parsed V8 CPU profile. `startTime`/`endTime`/`timeDeltas` are microseconds. */
33
+ export interface CpuProfile {
34
+ nodes: CpuProfileNode[];
35
+ startTime: number;
36
+ endTime: number;
37
+ samples?: number[];
38
+ timeDeltas?: number[];
39
+ }
40
+ /**
41
+ * Parse a `.cpuprofile` JSON blob. Accepts both the bare profile and the CDP
42
+ * `Profiler.stop` result shape (`{ profile: {...} }`). Returns null when the
43
+ * text is not a structurally valid V8 CPU profile.
44
+ */
45
+ export declare function parseCpuProfile(text: string): CpuProfile | null;
46
+ /**
47
+ * Render a V8 CPU profile as an agent-friendly bottleneck summary.
48
+ * Returns null when `text` is not a CPU profile (caller falls back to the
49
+ * plain-text path).
50
+ */
51
+ export declare function renderCpuProfile(text: string): string | null;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Effective-state resolution for the `inspect_image` tool.
3
+ *
4
+ * The tool delegates image understanding to a (possibly different)
5
+ * vision-capable model. That indirection is only useful when the active model
6
+ * cannot consume images itself; when it can (`model.input` includes
7
+ * `"image"`), the tool is redundant and its presence actively degrades the
8
+ * `read` tool, which reduces image reads to metadata-only plus an
9
+ * inspect_image suggestion. `auto` mode therefore exposes the tool only for
10
+ * models without native image input. `on`/`off` force registration regardless
11
+ * of model capability. A session-scoped override (the `/vision` command)
12
+ * takes precedence over the persisted setting for the current session only.
13
+ */
14
+ import type { Model } from "@oh-my-pi/pi-ai";
15
+ import type { Settings } from "../config/settings.js";
16
+ export type InspectImageMode = "auto" | "on" | "off";
17
+ export declare const INSPECT_IMAGE_MODES: readonly ["auto", "on", "off"];
18
+ /** Minimal session surface needed to resolve the effective inspect_image state. */
19
+ export interface InspectImageModeContext {
20
+ settings: Pick<Settings, "get">;
21
+ getActiveModel?: () => Model | undefined;
22
+ getInspectImageModeOverride?: () => InspectImageMode | undefined;
23
+ }
24
+ /**
25
+ * Whether the `inspect_image` tool should be registered/active right now.
26
+ * `auto` registers it only when the active model lacks native image input;
27
+ * an unresolved model is treated as text-only so the tool stays available.
28
+ */
29
+ export declare function isInspectImageToolActive(session: InspectImageModeContext): boolean;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Shared display-tree machinery for profile summaries (macOS `sample` reports,
3
+ * V8 `.cpuprofile` files). Callers build {@link ProfileNode} trees with a
4
+ * domain-specific metric (on-CPU samples, self microseconds, …); this module
5
+ * merges same-key siblings, flattens direct recursion, collapses pass-through
6
+ * chains, and renders the pruned hot-path tree.
7
+ */
8
+ /** Display node: merged, recursion-flattened mirror of a profile subtree. */
9
+ export interface ProfileNode {
10
+ /** Merge/recursion identity (demangled symbol, function@call-site, …). */
11
+ key: string;
12
+ /** Human-readable label; recursion and truncation decorations are applied at render time. */
13
+ label: string;
14
+ /** Inclusive metric for this subtree (on-CPU samples, self µs, …); drives pruning and display. */
15
+ value: number;
16
+ /** Levels of direct recursion flattened into this node. */
17
+ recursion: number;
18
+ children: ProfileNode[];
19
+ }
20
+ /** Merge `b` into `a` (same key), combining values and child lists. */
21
+ export declare function mergeInto(a: ProfileNode, b: ProfileNode): void;
22
+ /**
23
+ * Flatten direct recursion: children carrying the node's own key are dissolved
24
+ * into it (their children promoted and merged), so a 15-deep recursive spine
25
+ * renders as one annotated node.
26
+ */
27
+ export declare function flattenRecursion(node: ProfileNode): void;
28
+ /** `n` as a percentage of `total`, one decimal (`"12.3%"`); `"0%"` when total is empty. */
29
+ export declare function formatPct(n: number, total: number): string;
30
+ /** Options for {@link renderProfileNode}. */
31
+ export interface RenderTreeContext {
32
+ out: string[];
33
+ /** Denominator for percentage annotations. */
34
+ total: number;
35
+ /** Minimum subtree value a child needs to stay visible. */
36
+ minValue: number;
37
+ /** Format a metric value for the left column. */
38
+ formatValue: (value: number) => string;
39
+ /** Left-column width (characters) for formatted values. */
40
+ valueWidth: number;
41
+ }
42
+ /**
43
+ * Render one hot-path subtree: pass-through chains (single kept child, no own
44
+ * contribution above `minValue`) collapse into a single `a › b › c` line, and
45
+ * children below `minValue` are pruned.
46
+ */
47
+ export declare function renderProfileNode(node: ProfileNode, indent: number, ctx: RenderTreeContext): void;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Parser and renderer for macOS `/usr/bin/sample` call-tree reports
3
+ * (conventionally saved as `*.sample.txt`).
4
+ *
5
+ * The raw report is a 10k+ line ASCII call tree with mangled symbols —
6
+ * expensive for an agent to digest. `renderSampleProfile` converts it into a
7
+ * compact bottleneck summary:
8
+ *
9
+ * - per-thread hot paths, pruned to frames with meaningful on-CPU samples,
10
+ * with pass-through chains collapsed and direct recursion flattened
11
+ * - blocked/idle threads reduced to a one-line classification
12
+ * - a process-wide "top functions by self samples" table
13
+ * - Rust v0 and legacy symbols demangled (best-effort, path extraction)
14
+ *
15
+ * Consumed by the read tool: `*.sample.txt` reads show the summary, `:raw`
16
+ * returns the original bytes.
17
+ */
18
+ /** Matches paths the read tool should treat as macOS sample reports. */
19
+ export declare function isSampleProfilePath(filePath: string): boolean;
20
+ /** One frame in the sampled call tree. Counts are sample hits (subtree total). */
21
+ export interface SampleFrame {
22
+ count: number;
23
+ symbol: string;
24
+ module?: string;
25
+ children: SampleFrame[];
26
+ }
27
+ /** One sampled thread: `Thread_<id>` root plus its call tree. */
28
+ export interface SampleThread {
29
+ id: string;
30
+ name?: string;
31
+ total: number;
32
+ roots: SampleFrame[];
33
+ }
34
+ /** Metadata from the report preamble (everything before `Call graph:`). */
35
+ export interface SampleProfileHeader {
36
+ process: string;
37
+ pid: number;
38
+ intervalMs: number;
39
+ path?: string;
40
+ codeType?: string;
41
+ osVersion?: string;
42
+ footprint?: string;
43
+ footprintPeak?: string;
44
+ }
45
+ /** Parsed macOS sample report. */
46
+ export interface SampleProfile {
47
+ header: SampleProfileHeader;
48
+ threads: SampleThread[];
49
+ }
50
+ /**
51
+ * Parse a macOS `sample` report. Returns null when the text does not look
52
+ * like sample output (missing analysis preamble or `Call graph:` section).
53
+ */
54
+ export declare function parseSampleProfile(text: string): SampleProfile | null;
55
+ /**
56
+ * Best-effort demangle of Rust symbols (v0 `_R…` and legacy `_ZN…E`).
57
+ * For v0 this is a path extractor, not a full demangler: identifiers are
58
+ * pulled out in order and joined with `::`, so generic arguments appear as
59
+ * extra path segments. Non-Rust symbols pass through unchanged.
60
+ */
61
+ export declare function demangleSymbol(raw: string): string;
62
+ /**
63
+ * Render a macOS sample report as an agent-friendly bottleneck summary.
64
+ * Returns null when `text` is not sample output (caller falls back to the
65
+ * plain-text path).
66
+ */
67
+ export declare function renderSampleProfile(text: string): string | null;
@@ -20,39 +20,40 @@ export declare function generateSessionTitle(firstMessage: string, registry: Mod
20
20
  export declare function generateTitleOnline(firstMessage: string, registry: ModelRegistry, settings: Settings, sessionId?: string, currentModel?: Model<Api>, metadataResolver?: (provider: string) => Record<string, unknown> | undefined, signal?: AbortSignal, customSystemPrompt?: string): Promise<string | null>;
21
21
  export declare function formatSessionTerminalTitle(sessionName: string | undefined, cwd?: string): string;
22
22
  /**
23
- * Set the terminal title using OSC 0 (sets both tab and window title). Unsupported terminals ignore it.
23
+ * Set the terminal title through the native Win32 API or OSC 0.
24
+ *
25
+ * Repeating the same sanitized title is a no-op on every platform.
24
26
  */
25
27
  export declare function setTerminalTitle(title: string): void;
26
28
  export declare function setSessionTerminalTitle(sessionName: string | undefined, cwd?: string): void;
27
29
  /**
28
30
  * Set a terminal title from an extension's `setTitle()`. Unlike the session base
29
- * title, this owns the terminal verbatim: the run-state separator will not rewrite
30
- * it on the next spinner tick or state change. Cleared when the app next sets an
31
- * authoritative session title via {@link setSessionTerminalTitle}.
31
+ * title, this owns the terminal verbatim: periodic and run-state updates will not
32
+ * rewrite it. Cleared when the app next sets an authoritative session title via
33
+ * {@link setSessionTerminalTitle}.
32
34
  */
33
35
  export declare function setExtensionTerminalTitle(title: string): void;
34
36
  export type TerminalTitleState = "idle" | "working" | "attention";
35
37
  /**
36
- * Compose the terminal title from the `π` brand, a state-carrying SEPARATOR, and
37
- * the session label. The brand never gains a prefix glyph the separator slot
38
- * expresses the run state instead. Pure (no I/O) so the state→separator contract
39
- * is unit-testable:
40
- * - `idle` (user's turn): > label` — reads like a prompt awaiting input;
41
- * - `working`: `π label` — spinner frames animate the separator;
42
- * - `attention`: `π ! label` — agent blocked on the user;
43
- * - disabled: `π: label` — the pre-state layout.
38
+ * Compose the terminal title from the `π` brand, a state-carrying separator, and
39
+ * the session label. Pure (no I/O) so the state→separator contract is testable:
40
+ * - `idle` (user's turn): `π > label`;
41
+ * - `working`: `π ⠋ label` (`π : label` on Windows);
42
+ * - `attention`: ! label`;
43
+ * - disabled: `π: label`.
44
44
  * Without a label the separator trails the brand (`π >`) so the state stays visible.
45
45
  */
46
- export declare function buildTerminalTitleWithState(label: string | undefined, state: TerminalTitleState, frame: number, enabled: boolean): string;
46
+ export declare function buildTerminalTitleWithState(label: string | undefined, state: TerminalTitleState, frame: number, enabled: boolean, platform?: NodeJS.Platform): string;
47
47
  /**
48
48
  * Reflect the agent run state in the terminal title's separator: `working`
49
- * animates spinner frames in the separator slot, `idle` shows `>` (your turn),
50
- * `attention` shows `!` (agent blocked on you). Gated off by `tui.titleState`.
49
+ * animates outside Windows and stays `:` on Windows, `idle` shows `>` (your
50
+ * turn), and `attention` shows `!` (agent blocked on you). Gated off by
51
+ * `tui.titleState`.
51
52
  */
52
53
  export declare function setTerminalTitleState(state: TerminalTitleState): void;
53
54
  /** Enable/disable the run-state separator (driven by the `tui.titleState` setting). */
54
55
  export declare function setTerminalTitleStateEnabled(enabled: boolean): void;
55
- /** Stop the spinner timer; call on session/UI teardown. */
56
+ /** Release terminal-title runtime resources. */
56
57
  export declare function disposeTerminalTitleState(): void;
57
58
  /**
58
59
  * Save the current terminal title on terminals that support xterm window ops.