@oh-my-pi/pi-coding-agent 15.10.11 → 15.11.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 (217) hide show
  1. package/CHANGELOG.md +103 -2
  2. package/dist/cli.js +5790 -5731
  3. package/dist/types/async/index.d.ts +0 -1
  4. package/dist/types/cli/args.d.ts +1 -0
  5. package/dist/types/cli/gallery-fixtures/types.d.ts +5 -0
  6. package/dist/types/cli-commands.d.ts +12 -0
  7. package/dist/types/commands/launch.d.ts +4 -0
  8. package/dist/types/config/api-key-resolver.d.ts +3 -0
  9. package/dist/types/config/keybindings.d.ts +6 -1
  10. package/dist/types/config/model-registry.d.ts +1 -0
  11. package/dist/types/config/model-resolver.d.ts +18 -0
  12. package/dist/types/config/settings-schema.d.ts +85 -34
  13. package/dist/types/config/settings.d.ts +7 -0
  14. package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
  15. package/dist/types/eval/py/executor.d.ts +5 -0
  16. package/dist/types/eval/py/kernel.d.ts +6 -1
  17. package/dist/types/eval/py/runtime.d.ts +9 -0
  18. package/dist/types/exec/bash-executor.d.ts +2 -0
  19. package/dist/types/export/html/template.generated.d.ts +1 -1
  20. package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
  21. package/dist/types/extensibility/extensions/runner.d.ts +3 -2
  22. package/dist/types/extensibility/extensions/types.d.ts +3 -0
  23. package/dist/types/extensibility/shared-events.d.ts +2 -2
  24. package/dist/types/internal-urls/history-protocol.d.ts +14 -0
  25. package/dist/types/internal-urls/index.d.ts +1 -0
  26. package/dist/types/internal-urls/types.d.ts +1 -1
  27. package/dist/types/irc/bus.d.ts +66 -0
  28. package/dist/types/memory-backend/index.d.ts +1 -0
  29. package/dist/types/memory-backend/runtime.d.ts +4 -0
  30. package/dist/types/memory-backend/types.d.ts +66 -1
  31. package/dist/types/modes/components/agent-hub.d.ts +30 -0
  32. package/dist/types/modes/components/compaction-summary-message.d.ts +10 -4
  33. package/dist/types/modes/components/custom-editor.d.ts +2 -0
  34. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  35. package/dist/types/modes/components/ttsr-notification.d.ts +5 -1
  36. package/dist/types/modes/components/welcome.d.ts +3 -9
  37. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  38. package/dist/types/modes/index.d.ts +3 -3
  39. package/dist/types/modes/interactive-mode.d.ts +10 -4
  40. package/dist/types/modes/oauth-manual-input.d.ts +7 -0
  41. package/dist/types/modes/rpc/rpc-client.d.ts +39 -2
  42. package/dist/types/modes/rpc/rpc-mode.d.ts +31 -2
  43. package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
  44. package/dist/types/modes/rpc/rpc-types.d.ts +75 -1
  45. package/dist/types/modes/setup-wizard/index.d.ts +5 -1
  46. package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
  47. package/dist/types/modes/theme/theme.d.ts +2 -1
  48. package/dist/types/modes/types.d.ts +5 -2
  49. package/dist/types/modes/utils/ui-helpers.d.ts +1 -1
  50. package/dist/types/registry/agent-lifecycle.d.ts +51 -0
  51. package/dist/types/registry/agent-registry.d.ts +16 -5
  52. package/dist/types/secrets/index.d.ts +1 -1
  53. package/dist/types/secrets/obfuscator.d.ts +8 -2
  54. package/dist/types/session/agent-session.d.ts +49 -32
  55. package/dist/types/session/messages.d.ts +2 -4
  56. package/dist/types/session/session-history-format.d.ts +12 -0
  57. package/dist/types/session/session-manager.d.ts +21 -3
  58. package/dist/types/session/streaming-output.d.ts +46 -0
  59. package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
  60. package/dist/types/slash-commands/builtin-registry.d.ts +1 -0
  61. package/dist/types/slash-commands/types.d.ts +1 -1
  62. package/dist/types/system-prompt.d.ts +2 -0
  63. package/dist/types/task/executor.d.ts +12 -2
  64. package/dist/types/task/index.d.ts +13 -6
  65. package/dist/types/task/output-manager.d.ts +0 -7
  66. package/dist/types/task/repair-args.d.ts +8 -7
  67. package/dist/types/task/types.d.ts +63 -51
  68. package/dist/types/thinking.d.ts +4 -0
  69. package/dist/types/tiny/title-client.d.ts +11 -0
  70. package/dist/types/tiny/title-protocol.d.ts +1 -0
  71. package/dist/types/tools/browser/tab-worker.d.ts +3 -1
  72. package/dist/types/tools/find.d.ts +0 -11
  73. package/dist/types/tools/grouped-file-output.d.ts +0 -49
  74. package/dist/types/tools/index.d.ts +7 -3
  75. package/dist/types/tools/irc.d.ts +76 -38
  76. package/dist/types/tools/job.d.ts +7 -1
  77. package/dist/types/utils/git.d.ts +15 -2
  78. package/dist/types/utils/title-generator.d.ts +3 -2
  79. package/examples/extensions/with-deps/package.json +1 -0
  80. package/package.json +11 -10
  81. package/scripts/bundle-dist.ts +28 -19
  82. package/src/async/index.ts +0 -1
  83. package/src/auto-thinking/classifier.ts +1 -0
  84. package/src/cli/args.ts +3 -0
  85. package/src/cli/gallery-cli.ts +1 -1
  86. package/src/cli/gallery-fixtures/agentic.ts +230 -115
  87. package/src/cli/gallery-fixtures/types.ts +5 -0
  88. package/src/cli-commands.ts +29 -0
  89. package/src/cli.ts +28 -15
  90. package/src/commands/launch.ts +4 -0
  91. package/src/commit/agentic/tools/analyze-file.ts +38 -19
  92. package/src/commit/model-selection.ts +3 -2
  93. package/src/config/api-key-resolver.ts +8 -6
  94. package/src/config/keybindings.ts +6 -1
  95. package/src/config/model-registry.ts +97 -30
  96. package/src/config/model-resolver.ts +60 -0
  97. package/src/config/settings-schema.ts +99 -55
  98. package/src/config/settings.ts +68 -3
  99. package/src/edit/hashline/execute.ts +39 -2
  100. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  101. package/src/eval/__tests__/agent-bridge.test.ts +5 -3
  102. package/src/eval/agent-bridge.ts +3 -16
  103. package/src/eval/completion-bridge.ts +1 -0
  104. package/src/eval/js/shared/prelude.txt +1 -1
  105. package/src/eval/py/executor.ts +29 -7
  106. package/src/eval/py/index.ts +6 -1
  107. package/src/eval/py/kernel.ts +31 -11
  108. package/src/eval/py/prelude.py +5 -6
  109. package/src/eval/py/runtime.ts +37 -0
  110. package/src/exec/bash-executor.ts +82 -3
  111. package/src/export/html/template.generated.ts +1 -1
  112. package/src/export/html/template.js +38 -13
  113. package/src/extensibility/custom-tools/types.ts +2 -2
  114. package/src/extensibility/extensions/get-commands-handler.ts +2 -1
  115. package/src/extensibility/extensions/runner.ts +6 -1
  116. package/src/extensibility/extensions/types.ts +3 -0
  117. package/src/extensibility/shared-events.ts +2 -2
  118. package/src/hindsight/bank.ts +17 -2
  119. package/src/internal-urls/docs-index.generated.ts +11 -11
  120. package/src/internal-urls/history-protocol.ts +113 -0
  121. package/src/internal-urls/index.ts +1 -0
  122. package/src/internal-urls/router.ts +3 -1
  123. package/src/internal-urls/types.ts +1 -1
  124. package/src/irc/bus.ts +292 -0
  125. package/src/main.ts +26 -66
  126. package/src/memories/index.ts +2 -0
  127. package/src/memory-backend/index.ts +1 -0
  128. package/src/memory-backend/local-backend.ts +9 -0
  129. package/src/memory-backend/off-backend.ts +9 -0
  130. package/src/memory-backend/runtime.ts +66 -0
  131. package/src/memory-backend/types.ts +81 -1
  132. package/src/mnemopi/backend.ts +151 -4
  133. package/src/modes/acp/acp-agent.ts +119 -11
  134. package/src/modes/components/{session-observer-overlay.ts → agent-hub.ts} +586 -367
  135. package/src/modes/components/assistant-message.ts +19 -21
  136. package/src/modes/components/compaction-summary-message.ts +68 -32
  137. package/src/modes/components/custom-editor.ts +10 -0
  138. package/src/modes/components/footer.ts +3 -1
  139. package/src/modes/components/status-line/component.ts +118 -34
  140. package/src/modes/components/tool-execution.ts +31 -1
  141. package/src/modes/components/ttsr-notification.ts +72 -30
  142. package/src/modes/components/welcome.ts +9 -33
  143. package/src/modes/controllers/command-controller.ts +1 -1
  144. package/src/modes/controllers/event-controller.ts +65 -0
  145. package/src/modes/controllers/extension-ui-controller.ts +8 -8
  146. package/src/modes/controllers/input-controller.ts +19 -2
  147. package/src/modes/controllers/mcp-command-controller.ts +38 -3
  148. package/src/modes/controllers/selector-controller.ts +21 -17
  149. package/src/modes/index.ts +3 -21
  150. package/src/modes/interactive-mode.ts +47 -22
  151. package/src/modes/oauth-manual-input.ts +30 -3
  152. package/src/modes/rpc/rpc-client.ts +154 -3
  153. package/src/modes/rpc/rpc-mode.ts +97 -12
  154. package/src/modes/rpc/rpc-subagents.ts +265 -0
  155. package/src/modes/rpc/rpc-types.ts +81 -1
  156. package/src/modes/setup-wizard/index.ts +12 -2
  157. package/src/modes/setup-wizard/lazy.ts +16 -0
  158. package/src/modes/theme/theme.ts +18 -5
  159. package/src/modes/types.ts +5 -5
  160. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  161. package/src/modes/utils/ui-helpers.ts +51 -49
  162. package/src/prompts/system/irc-incoming.md +3 -4
  163. package/src/prompts/system/orchestrate-notice.md +2 -2
  164. package/src/prompts/system/subagent-system-prompt.md +0 -5
  165. package/src/prompts/system/system-prompt.md +1 -0
  166. package/src/prompts/system/workflow-notice.md +2 -2
  167. package/src/prompts/tools/eval.md +3 -3
  168. package/src/prompts/tools/irc.md +29 -19
  169. package/src/prompts/tools/read.md +2 -2
  170. package/src/prompts/tools/task-summary.md +5 -16
  171. package/src/prompts/tools/task.md +38 -29
  172. package/src/registry/agent-lifecycle.ts +218 -0
  173. package/src/registry/agent-registry.ts +16 -5
  174. package/src/sdk.ts +37 -10
  175. package/src/secrets/index.ts +8 -1
  176. package/src/secrets/obfuscator.ts +39 -18
  177. package/src/session/agent-session.ts +422 -291
  178. package/src/session/messages.ts +11 -78
  179. package/src/session/session-history-format.ts +246 -0
  180. package/src/session/session-manager.ts +59 -5
  181. package/src/session/streaming-output.ts +226 -10
  182. package/src/slash-commands/acp-builtins.ts +24 -0
  183. package/src/slash-commands/builtin-registry.ts +20 -0
  184. package/src/slash-commands/types.ts +1 -1
  185. package/src/system-prompt.ts +14 -0
  186. package/src/task/executor.ts +851 -461
  187. package/src/task/index.ts +721 -796
  188. package/src/task/output-manager.ts +0 -11
  189. package/src/task/render.ts +148 -63
  190. package/src/task/repair-args.ts +21 -9
  191. package/src/task/types.ts +82 -66
  192. package/src/thinking.ts +7 -0
  193. package/src/tiny/title-client.ts +34 -5
  194. package/src/tiny/title-protocol.ts +1 -1
  195. package/src/tiny/worker.ts +6 -4
  196. package/src/tools/ask.ts +4 -2
  197. package/src/tools/bash.ts +61 -10
  198. package/src/tools/browser/tab-worker.ts +26 -7
  199. package/src/tools/browser.ts +28 -1
  200. package/src/tools/find.ts +2 -27
  201. package/src/tools/grouped-file-output.ts +1 -118
  202. package/src/tools/image-gen.ts +11 -4
  203. package/src/tools/index.ts +17 -13
  204. package/src/tools/inspect-image.ts +1 -0
  205. package/src/tools/irc.ts +596 -171
  206. package/src/tools/job.ts +41 -7
  207. package/src/tools/read.ts +57 -1
  208. package/src/tools/renderers.ts +2 -0
  209. package/src/tools/resolve.ts +4 -1
  210. package/src/utils/commit-message-generator.ts +1 -0
  211. package/src/utils/git.ts +267 -13
  212. package/src/utils/title-generator.ts +24 -5
  213. package/dist/types/async/support.d.ts +0 -2
  214. package/dist/types/modes/components/session-observer-overlay.d.ts +0 -11
  215. package/dist/types/task/simple-mode.d.ts +0 -8
  216. package/src/async/support.ts +0 -5
  217. package/src/task/simple-mode.ts +0 -27
@@ -1,2 +1 @@
1
1
  export * from "./job-manager";
2
- export * from "./support";
@@ -8,6 +8,7 @@ export interface Args {
8
8
  allowHome?: boolean;
9
9
  provider?: string;
10
10
  model?: string;
11
+ config?: string[];
11
12
  smol?: string;
12
13
  slow?: string;
13
14
  plan?: string;
@@ -34,6 +34,11 @@ export interface GalleryFixture {
34
34
  * real one keeps the gallery honest for these tools.
35
35
  */
36
36
  customRendered?: boolean;
37
+ /**
38
+ * Renderer-registry key to use when the fixture key is a variant of a tool
39
+ * (e.g. `irc_wait` → `irc`). Defaults to the fixture key.
40
+ */
41
+ renderer?: string;
37
42
  /**
38
43
  * Arguments shown during the streaming state — a partial view of {@link args}
39
44
  * as if the tool-call JSON were still arriving. May include `__partialJson`
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import type { CommandEntry } from "@oh-my-pi/pi-utils/cli";
12
12
  export declare const commands: CommandEntry[];
13
+ export declare function reservedTopLevelWordMessage(first: string | undefined, argc?: number): string | undefined;
13
14
  /**
14
15
  * Return true when `first` matches a registered subcommand name or alias.
15
16
  *
@@ -17,3 +18,14 @@ export declare const commands: CommandEntry[];
17
18
  * runner skips ahead to the default `launch` command.
18
19
  */
19
20
  export declare function isSubcommand(first: string | undefined): boolean;
21
+ export type ResolvedCliArgv = {
22
+ argv: string[];
23
+ } | {
24
+ error: string;
25
+ };
26
+ /**
27
+ * Decide what the CLI runner should do with raw argv: reject bare reserved
28
+ * management words, pass help/version through untouched, and route everything
29
+ * that is not a known subcommand to `launch`.
30
+ */
31
+ export declare function resolveCliArgv(argv: string[]): ResolvedCliArgv;
@@ -47,6 +47,10 @@ export default class Index extends Command {
47
47
  description: string;
48
48
  options: string[];
49
49
  };
50
+ config: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
51
+ description: string;
52
+ multiple: true;
53
+ };
50
54
  print: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
51
55
  char: string;
52
56
  description: string;
@@ -4,6 +4,8 @@ export interface ApiKeyResolverOptions {
4
4
  sessionId?: string;
5
5
  /** Provider base URL hint forwarded to the auth-storage cascade. */
6
6
  baseUrl?: string;
7
+ /** Provider model id forwarded to model-scoped usage ranking/backoff. */
8
+ modelId?: string;
7
9
  }
8
10
  /**
9
11
  * Minimal slice of `ModelRegistry` the resolver needs. Typed structurally so
@@ -13,6 +15,7 @@ export interface ApiKeyResolverOptions {
13
15
  export interface ApiKeyResolverRegistry {
14
16
  getApiKeyForProvider(provider: string, sessionId?: string, options?: {
15
17
  baseUrl?: string;
18
+ modelId?: string;
16
19
  forceRefresh?: boolean;
17
20
  signal?: AbortSignal;
18
21
  }): Promise<string | undefined>;
@@ -23,6 +23,7 @@ interface AppKeybindings {
23
23
  "app.clipboard.pasteTextRaw": true;
24
24
  "app.clipboard.copyLine": true;
25
25
  "app.clipboard.copyPrompt": true;
26
+ "app.agents.hub": true;
26
27
  "app.session.new": true;
27
28
  "app.session.tree": true;
28
29
  "app.session.fork": true;
@@ -268,9 +269,13 @@ export declare const KEYBINDINGS: {
268
269
  readonly defaultKeys: [];
269
270
  readonly description: "Resume session";
270
271
  };
272
+ readonly "app.agents.hub": {
273
+ readonly defaultKeys: "alt+a";
274
+ readonly description: "Open the agent hub";
275
+ };
271
276
  readonly "app.session.observe": {
272
277
  readonly defaultKeys: "ctrl+s";
273
- readonly description: "Observe subagent sessions";
278
+ readonly description: "Open the agent hub";
274
279
  };
275
280
  readonly "app.session.togglePath": {
276
281
  readonly defaultKeys: "ctrl+p";
@@ -148,6 +148,7 @@ export declare class ModelRegistry {
148
148
  */
149
149
  getApiKeyForProvider(provider: string, sessionId?: string, options?: {
150
150
  baseUrl?: string;
151
+ modelId?: string;
151
152
  forceRefresh?: boolean;
152
153
  signal?: AbortSignal;
153
154
  }): Promise<string | undefined>;
@@ -174,6 +174,24 @@ export declare function resolveModelScope(patterns: string[], modelRegistry: Pic
174
174
  * rather than falling back to the global default (see issue #1022).
175
175
  */
176
176
  export declare function resolveAllowedModels(modelRegistry: Pick<ModelRegistry, "getAvailable" | "getCanonicalVariants">, settings: Settings | undefined, preferences?: ModelMatchPreferences): Promise<Model<Api>[]>;
177
+ /**
178
+ * Synchronous subset of {@link resolveAllowedModels} for contexts where async is unavailable
179
+ * (e.g. `getAvailableModels()` which is called from the ACP model-list advertisement, RPC
180
+ * `get_available_models`, and the `/model` slash command). Uses the same effective
181
+ * `enabledModels` scope semantics as startup resolution:
182
+ *
183
+ * - Glob selectors match `provider/modelId` and bare model id
184
+ * - Exact canonical ids expand to all available concrete variants
185
+ * - Exact `provider/modelId`, bare ids, provider-scoped fuzzy, and substring selectors
186
+ * resolve through the shared model-pattern matcher
187
+ * - Optional `:thinkingLevel` suffixes are stripped only when valid
188
+ *
189
+ * When no pattern resolves to any model (misconfiguration / typo) an empty list is returned,
190
+ * consistent with the empty-list contract of {@link resolveAllowedModels}. Callers that render
191
+ * a UI picker should treat an empty list as "hide the picker entry", matching how the SDK
192
+ * surfaces the same misconfiguration during session initialization.
193
+ */
194
+ export declare function filterAvailableModelsByEnabledPatterns(available: Model<Api>[], patterns: readonly string[], registry: Pick<ModelRegistry, "getCanonicalVariants">): Model<Api>[];
177
195
  export interface ResolveCliModelResult {
178
196
  model: Model<Api> | undefined;
179
197
  selector?: string;
@@ -62,7 +62,7 @@ export type AnyUiMetadata = UiBase & {
62
62
  };
63
63
  interface BooleanDef {
64
64
  type: "boolean";
65
- default: boolean;
65
+ default: boolean | undefined;
66
66
  ui?: UiBoolean;
67
67
  }
68
68
  interface StringDef {
@@ -1326,12 +1326,12 @@ export declare const SETTINGS_SCHEMA: {
1326
1326
  };
1327
1327
  readonly "compaction.strategy": {
1328
1328
  readonly type: "enum";
1329
- readonly values: readonly ["context-full", "handoff", "shake", "off"];
1329
+ readonly values: readonly ["context-full", "handoff", "shake", "snapcompact", "off"];
1330
1330
  readonly default: "context-full";
1331
1331
  readonly ui: {
1332
1332
  readonly tab: "context";
1333
1333
  readonly label: "Compaction Strategy";
1334
- readonly description: "Choose in-place context-full maintenance, auto-handoff, surgical shake (drop heavy content), or disable auto maintenance (off)";
1334
+ readonly description: "Choose in-place context-full maintenance, auto-handoff, surgical shake (drop heavy content), snapcompact (archive history as dense images), or disable auto maintenance (off)";
1335
1335
  readonly options: readonly [{
1336
1336
  readonly value: "context-full";
1337
1337
  readonly label: "Context-full";
@@ -1344,6 +1344,10 @@ export declare const SETTINGS_SCHEMA: {
1344
1344
  readonly value: "shake";
1345
1345
  readonly label: "Shake";
1346
1346
  readonly description: "Drop heavy content (tool results + large blocks) in place; recover via artifact";
1347
+ }, {
1348
+ readonly value: "snapcompact";
1349
+ readonly label: "Snapcompact";
1350
+ readonly description: "Archive history onto dense bitmap images the model reads back; no LLM call";
1347
1351
  }, {
1348
1352
  readonly value: "off";
1349
1353
  readonly label: "Off";
@@ -1563,6 +1567,15 @@ export declare const SETTINGS_SCHEMA: {
1563
1567
  }];
1564
1568
  };
1565
1569
  };
1570
+ readonly "compaction.supersedeReads": {
1571
+ readonly type: "boolean";
1572
+ readonly default: true;
1573
+ readonly ui: {
1574
+ readonly tab: "context";
1575
+ readonly label: "Supersede Stale Reads";
1576
+ readonly description: "Prune older read results when the same file is read again (cache-aware, runs every turn)";
1577
+ };
1578
+ };
1566
1579
  readonly "branchSummary.enabled": {
1567
1580
  readonly type: "boolean";
1568
1581
  readonly default: false;
@@ -2392,6 +2405,20 @@ export declare const SETTINGS_SCHEMA: {
2392
2405
  readonly type: "number";
2393
2406
  readonly default: number;
2394
2407
  };
2408
+ readonly "shellMinimizer.sourceOutlineLevel": {
2409
+ readonly type: "enum";
2410
+ readonly values: readonly ["default", "aggressive"];
2411
+ readonly default: "default";
2412
+ readonly ui: {
2413
+ readonly tab: "editing";
2414
+ readonly label: "Shell Minimizer Source Outline";
2415
+ readonly description: "Source outline mode for cat/read of source files: default or aggressive";
2416
+ };
2417
+ };
2418
+ readonly "shellMinimizer.legacyFilters": {
2419
+ readonly type: "boolean";
2420
+ readonly default: undefined;
2421
+ };
2395
2422
  readonly "eval.py": {
2396
2423
  readonly type: "boolean";
2397
2424
  readonly default: true;
@@ -2420,6 +2447,15 @@ export declare const SETTINGS_SCHEMA: {
2420
2447
  readonly description: "Whether to keep IPython kernel alive across calls";
2421
2448
  };
2422
2449
  };
2450
+ readonly "python.interpreter": {
2451
+ readonly type: "string";
2452
+ readonly default: "";
2453
+ readonly ui: {
2454
+ readonly tab: "editing";
2455
+ readonly label: "Python Interpreter";
2456
+ readonly description: "Optional path to an exact Python executable. When set, automatic Python runtime discovery is skipped.";
2457
+ };
2458
+ };
2423
2459
  readonly "tools.approval": {
2424
2460
  readonly type: "record";
2425
2461
  readonly default: {};
@@ -2599,22 +2635,13 @@ export declare const SETTINGS_SCHEMA: {
2599
2635
  readonly description: "Enable the ast_edit tool for structural AST rewrites";
2600
2636
  };
2601
2637
  };
2602
- readonly "irc.enabled": {
2603
- readonly type: "boolean";
2604
- readonly default: true;
2605
- readonly ui: {
2606
- readonly tab: "tools";
2607
- readonly label: "IRC";
2608
- readonly description: "Enable agent-to-agent IRC messaging via the irc tool";
2609
- };
2610
- };
2611
2638
  readonly "irc.timeoutMs": {
2612
2639
  readonly type: "number";
2613
2640
  readonly default: 120000;
2614
2641
  readonly ui: {
2615
2642
  readonly tab: "tools";
2616
2643
  readonly label: "IRC Timeout";
2617
- readonly description: "Drop IRC messages whose recipient does not respond within this many milliseconds (0 disables the timeout)";
2644
+ readonly description: "Default timeout for irc wait (and send await:true) in milliseconds; 0 disables the timeout";
2618
2645
  readonly options: readonly [{
2619
2646
  readonly value: "0";
2620
2647
  readonly label: "Disabled";
@@ -2811,7 +2838,7 @@ export declare const SETTINGS_SCHEMA: {
2811
2838
  readonly ui: {
2812
2839
  readonly tab: "tools";
2813
2840
  readonly label: "Async Execution";
2814
- readonly description: "Enable async bash commands and background task execution";
2841
+ readonly description: "Enable async bash commands";
2815
2842
  };
2816
2843
  };
2817
2844
  readonly "async.maxJobs": {
@@ -3056,27 +3083,13 @@ export declare const SETTINGS_SCHEMA: {
3056
3083
  readonly description: "Encourage the agent to delegate work to subagents unless changes are trivial";
3057
3084
  };
3058
3085
  };
3059
- readonly "task.simple": {
3060
- readonly type: "enum";
3061
- readonly values: readonly ["default", "schema-free", "independent"];
3062
- readonly default: "schema-free";
3086
+ readonly "task.batch": {
3087
+ readonly type: "boolean";
3088
+ readonly default: true;
3063
3089
  readonly ui: {
3064
3090
  readonly tab: "tasks";
3065
- readonly label: "Task Input Mode";
3066
- readonly description: "How much shared structure the task tool accepts (default, schema-free, or independent)";
3067
- readonly options: readonly [{
3068
- readonly value: "default";
3069
- readonly label: "Default";
3070
- readonly description: "Shared context and custom task schema are available";
3071
- }, {
3072
- readonly value: "schema-free";
3073
- readonly label: "Schema-free";
3074
- readonly description: "Shared context stays available, but custom task schema is disabled";
3075
- }, {
3076
- readonly value: "independent";
3077
- readonly label: "Independent";
3078
- readonly description: "No shared context or custom task schema; each task must stand alone";
3079
- }];
3091
+ readonly label: "Batch Task Calls";
3092
+ readonly description: "Switch the task tool to its batch shape: one call carries { agent, context, tasks[] } — one subagent per item (with per-item isolation) and a required shared context prepended to every assignment. Each spawn still runs as an independent background agent with the normal idle/parked lifecycle. Disable to restore the flat single-spawn schema.";
3080
3093
  };
3081
3094
  };
3082
3095
  readonly "task.maxConcurrency": {
@@ -3173,6 +3186,38 @@ export declare const SETTINGS_SCHEMA: {
3173
3186
  }];
3174
3187
  };
3175
3188
  };
3189
+ readonly "task.agentIdleTtlMs": {
3190
+ readonly type: "number";
3191
+ readonly default: 420000;
3192
+ readonly ui: {
3193
+ readonly tab: "tasks";
3194
+ readonly label: "Agent Idle TTL";
3195
+ readonly description: "How long an idle subagent stays live in memory before being parked to disk (ms). Parked agents are revived automatically when messaged or resumed. 0 keeps idle agents live until exit.";
3196
+ };
3197
+ };
3198
+ readonly "task.softRequestBudget": {
3199
+ readonly type: "number";
3200
+ readonly default: 90;
3201
+ readonly ui: {
3202
+ readonly tab: "tasks";
3203
+ readonly label: "Soft Subagent Request Budget";
3204
+ readonly description: "Soft per-subagent request budget (assistant requests per run). Crossing it injects one steering notice asking the subagent to wrap up; at 1.5x the budget the run is aborted gracefully, salvaging partial output. 0 disables the guard. Bundled explore/quick_task agents use a lower built-in budget.";
3205
+ readonly options: readonly [{
3206
+ readonly value: "0";
3207
+ readonly label: "Disabled";
3208
+ }, {
3209
+ readonly value: "40";
3210
+ readonly label: "40 requests";
3211
+ }, {
3212
+ readonly value: "90";
3213
+ readonly label: "90 requests";
3214
+ readonly description: "Default";
3215
+ }, {
3216
+ readonly value: "150";
3217
+ readonly label: "150 requests";
3218
+ }];
3219
+ };
3220
+ };
3176
3221
  readonly "task.disabledAgents": {
3177
3222
  readonly type: "array";
3178
3223
  readonly default: string[];
@@ -3896,6 +3941,9 @@ export type SettingPath = keyof Schema;
3896
3941
  /** Infer the value type for a setting path */
3897
3942
  export type SettingValue<P extends SettingPath> = Schema[P] extends {
3898
3943
  type: "boolean";
3944
+ default: undefined;
3945
+ } ? boolean | undefined : Schema[P] extends {
3946
+ type: "boolean";
3899
3947
  } ? boolean : Schema[P] extends {
3900
3948
  type: "string";
3901
3949
  } ? string | undefined : Schema[P] extends {
@@ -3930,7 +3978,7 @@ export type StatusLineSeparatorStyle = SettingValue<"statusLine.separator">;
3930
3978
  export type TreeFilterMode = SettingValue<"treeFilterMode">;
3931
3979
  export interface CompactionSettings {
3932
3980
  enabled: boolean;
3933
- strategy: "context-full" | "handoff" | "shake" | "off";
3981
+ strategy: "context-full" | "handoff" | "shake" | "snapcompact" | "off";
3934
3982
  thresholdPercent: number;
3935
3983
  thresholdTokens: number;
3936
3984
  reserveTokens: number;
@@ -3942,6 +3990,7 @@ export interface CompactionSettings {
3942
3990
  idleEnabled: boolean;
3943
3991
  idleThresholdTokens: number;
3944
3992
  idleTimeoutSeconds: number;
3993
+ supersedeReads: boolean;
3945
3994
  }
3946
3995
  export interface ContextPromotionSettings {
3947
3996
  enabled: boolean;
@@ -4051,6 +4100,8 @@ export interface ShellMinimizerSettings {
4051
4100
  only: string[];
4052
4101
  except: string[];
4053
4102
  maxCaptureBytes: number;
4103
+ sourceOutlineLevel: "default" | "aggressive";
4104
+ legacyFilters: boolean | undefined;
4054
4105
  }
4055
4106
  /** Map group prefix -> typed settings interface */
4056
4107
  export interface GroupTypeMap {
@@ -30,6 +30,8 @@ export interface SettingsOptions {
30
30
  inMemory?: boolean;
31
31
  /** Initial overrides */
32
32
  overrides?: Partial<Record<SettingPath, unknown>>;
33
+ /** Extra config.yml-style overlays loaded after global/project settings */
34
+ configFiles?: string[];
33
35
  }
34
36
  export declare class Settings {
35
37
  #private;
@@ -54,6 +56,11 @@ export declare class Settings {
54
56
  * Returns the merged value from global + project + overrides, or the default.
55
57
  */
56
58
  get<P extends SettingPath>(path: P): SettingValue<P>;
59
+ /**
60
+ * Whether `path` has an explicitly configured value (global config, project
61
+ * config, or runtime override) rather than falling back to the schema default.
62
+ */
63
+ isConfigured(path: SettingPath): boolean;
57
64
  /**
58
65
  * Set a setting value (sync).
59
66
  * Updates global settings and queues a background save.
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Per-session guard against subagents looping on byte-identical no-op edits.
3
+ *
4
+ * A hashline patch can apply cleanly yet produce no change when the body rows
5
+ * are already byte-identical to the targeted lines. {@link executeHashlineSingle}
6
+ * surfaces a soft hint ("re-read the file before issuing another edit"), but in
7
+ * the wild some models ignore the hint and keep re-issuing the same bytes
8
+ * (issue #2081 captured 182 such repeats in 205 calls before the user aborted).
9
+ *
10
+ * This module tracks consecutive byte-identical no-op edits per canonical file
11
+ * path within a single session. Once the same payload no-ops {@link NOOP_HARD_LIMIT}
12
+ * times in a row the caller is expected to escalate from a soft text result to
13
+ * a thrown {@link ToolError} so the agent loop sees a tool *failure* — empirically
14
+ * far more effective at breaking the cycle than the soft hint alone.
15
+ *
16
+ * A successful (non-noop) commit for a path resets that path's counter; a
17
+ * different payload on the same path also resets it because the body hash
18
+ * changed, which is a sign of model progress and deserves another soft hint.
19
+ */
20
+ interface NoopLoopEntry {
21
+ /** Hash of the most recent input that no-op'd on this canonical path. */
22
+ hash: string;
23
+ /** Consecutive no-op count for the same `hash` on this path. */
24
+ count: number;
25
+ }
26
+ /** Cross-session-safe state slot held on the `ToolSession`. */
27
+ export interface NoopLoopGuard {
28
+ entries: Map<string, NoopLoopEntry>;
29
+ }
30
+ /**
31
+ * After this many consecutive byte-identical no-op edits on the same path,
32
+ * {@link recordNoopEdit} returns `escalate: true`. Picked deliberately small
33
+ * so the soft hint still fires once or twice before we escalate — the model
34
+ * deserves a chance to recover, but a tight bound is what actually breaks
35
+ * loops in practice.
36
+ */
37
+ export declare const NOOP_HARD_LIMIT = 3;
38
+ interface NoopLoopGuardOwner {
39
+ noopLoopGuard?: NoopLoopGuard;
40
+ }
41
+ /** Lazily create the per-session guard, mirroring `getFileSnapshotStore`. */
42
+ export declare function getNoopLoopGuard(session: NoopLoopGuardOwner): NoopLoopGuard;
43
+ /** Result of recording one no-op against the guard. */
44
+ export interface NoopRecordResult {
45
+ /** Consecutive identical no-op count, including the current one. */
46
+ count: number;
47
+ /** True once `count >= NOOP_HARD_LIMIT` and the caller MUST escalate. */
48
+ escalate: boolean;
49
+ }
50
+ /**
51
+ * Record a no-op edit for `canonicalPath` keyed by `inputHash` (a stable hash
52
+ * of the raw patch input bytes). Returns the running consecutive-no-op count
53
+ * and whether the caller should escalate from a soft text result to a thrown
54
+ * error.
55
+ *
56
+ * `inputHash` is intentionally derived from the raw model-authored bytes
57
+ * rather than from file content: when the model emits a different payload
58
+ * (even whitespace-only) that's progress and earns a fresh soft hint, but
59
+ * re-issuing the same bytes after being warned is what we want to break.
60
+ */
61
+ export declare function recordNoopEdit(session: NoopLoopGuardOwner, canonicalPath: string, inputHash: string): NoopRecordResult;
62
+ /**
63
+ * Clear the no-op counter for `canonicalPath`. Call after a non-noop commit
64
+ * for the same path so a future no-op starts fresh from the soft hint.
65
+ */
66
+ export declare function resetNoopEdit(session: NoopLoopGuardOwner, canonicalPath: string): void;
67
+ /**
68
+ * Stable hash of the raw patch input. Bun's `Bun.hash` is xxHash64 — fast,
69
+ * non-cryptographic, more than adequate for "is this the same payload?".
70
+ */
71
+ export declare function hashPatchInput(input: string): string;
72
+ export {};
@@ -25,6 +25,11 @@ export interface PythonExecutorOptions {
25
25
  kernelOwnerId?: string;
26
26
  /** Kernel mode (session reuse vs per-call) */
27
27
  kernelMode?: PythonKernelMode;
28
+ /**
29
+ * Explicit interpreter path (`python.interpreter` resolved from the
30
+ * session's settings). Skips automatic runtime discovery when set.
31
+ */
32
+ interpreter?: string;
28
33
  /** Restart the kernel before executing */
29
34
  reset?: boolean;
30
35
  /** Session file path for accessing task outputs */
@@ -45,6 +45,11 @@ interface KernelLifecycleOptions {
45
45
  interface KernelStartOptions extends KernelLifecycleOptions {
46
46
  cwd: string;
47
47
  env?: Record<string, string | undefined>;
48
+ /**
49
+ * Explicit interpreter path (`python.interpreter` from the session's
50
+ * settings). When set, runtime discovery is skipped entirely.
51
+ */
52
+ interpreter?: string;
48
53
  }
49
54
  interface KernelShutdownOptions {
50
55
  signal?: AbortSignal;
@@ -57,7 +62,7 @@ export interface PythonKernelAvailability {
57
62
  /** The probed-working runtime, when one was found. */
58
63
  runtime?: PythonRuntime;
59
64
  }
60
- export declare function checkPythonKernelAvailability(cwd: string): Promise<PythonKernelAvailability>;
65
+ export declare function checkPythonKernelAvailability(cwd: string, interpreter?: string): Promise<PythonKernelAvailability>;
61
66
  export declare class PythonKernel {
62
67
  #private;
63
68
  readonly id: string;
@@ -15,6 +15,15 @@ export declare function filterEnv(env: Record<string, string | undefined>): Reco
15
15
  * Detect virtual environment path from VIRTUAL_ENV or common locations.
16
16
  */
17
17
  export declare function resolveVenvPath(cwd: string): string | undefined;
18
+ /**
19
+ * Resolve an explicitly configured interpreter (`python.interpreter`) into a
20
+ * runtime, bypassing discovery. Does not probe or validate the executable —
21
+ * callers must check it actually runs. `~` expands to the home directory and
22
+ * relative paths resolve against `cwd`. When the interpreter sits inside a
23
+ * virtualenv (a `pyvenv.cfg` above its bin dir), the venv activation env is
24
+ * applied so subprocesses and `pip` resolve consistently.
25
+ */
26
+ export declare function resolveExplicitPythonRuntime(interpreter: string, cwd: string, baseEnv: Record<string, string | undefined>): PythonRuntime;
18
27
  /**
19
28
  * Enumerate candidate Python runtimes in priority order: an active/project venv,
20
29
  * the managed `~/.omp/python-env`, then the system interpreter on PATH. Every
@@ -10,6 +10,8 @@ export interface BashExecutorOptions {
10
10
  sessionKey?: string;
11
11
  /** Additional environment variables to inject */
12
12
  env?: Record<string, string>;
13
+ /** Run through the configured user shell instead of brush parsing directly. */
14
+ useUserShell?: boolean;
13
15
  /** Artifact path/id for full output storage */
14
16
  artifactPath?: string;
15
17
  artifactId?: string;