@oh-my-pi/pi-coding-agent 17.0.4 → 17.0.5

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 (112) hide show
  1. package/CHANGELOG.md +86 -43
  2. package/dist/cli.js +3540 -3521
  3. package/dist/types/advisor/advise-tool.d.ts +3 -0
  4. package/dist/types/advisor/runtime.d.ts +7 -1
  5. package/dist/types/async/job-manager.d.ts +2 -0
  6. package/dist/types/config/model-registry.d.ts +7 -0
  7. package/dist/types/config/model-resolver.d.ts +8 -0
  8. package/dist/types/config/models-config-schema.d.ts +10 -0
  9. package/dist/types/config/models-config.d.ts +6 -0
  10. package/dist/types/dap/client.d.ts +10 -0
  11. package/dist/types/dap/types.d.ts +6 -5
  12. package/dist/types/extensibility/extensions/runner.d.ts +4 -2
  13. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +16 -0
  14. package/dist/types/launch/spawn-options.d.ts +10 -0
  15. package/dist/types/launch/spawn-options.test.d.ts +1 -0
  16. package/dist/types/modes/components/status-line/component.d.ts +2 -3
  17. package/dist/types/modes/components/status-line/types.d.ts +3 -1
  18. package/dist/types/modes/components/tool-execution.d.ts +2 -0
  19. package/dist/types/modes/components/transcript-container.d.ts +4 -3
  20. package/dist/types/modes/components/tree-selector.d.ts +6 -2
  21. package/dist/types/modes/interactive-mode.d.ts +2 -0
  22. package/dist/types/modes/print-mode.d.ts +4 -0
  23. package/dist/types/modes/rpc/rpc-input.d.ts +5 -0
  24. package/dist/types/modes/rpc/rpc-mode.d.ts +1 -1
  25. package/dist/types/modes/types.d.ts +2 -0
  26. package/dist/types/sdk.d.ts +2 -0
  27. package/dist/types/session/agent-session.d.ts +19 -1
  28. package/dist/types/session/messages.d.ts +6 -0
  29. package/dist/types/tools/browser/aria/aria-snapshot.d.ts +17 -7
  30. package/dist/types/tools/browser/cmux/socket-client.d.ts +2 -0
  31. package/dist/types/tools/browser/tab-protocol.d.ts +2 -0
  32. package/dist/types/tools/browser/tab-worker.d.ts +2 -0
  33. package/dist/types/tools/gh.d.ts +5 -3
  34. package/dist/types/tools/hub/index.d.ts +1 -1
  35. package/dist/types/tools/hub/jobs.d.ts +1 -0
  36. package/dist/types/tools/hub/types.d.ts +2 -0
  37. package/dist/types/tools/tool-timeouts.d.ts +1 -1
  38. package/dist/types/utils/git.d.ts +33 -0
  39. package/dist/types/web/search/providers/codex.d.ts +1 -1
  40. package/package.json +12 -12
  41. package/src/advisor/__tests__/advisor.test.ts +150 -0
  42. package/src/advisor/advise-tool.ts +4 -0
  43. package/src/advisor/runtime.ts +38 -14
  44. package/src/async/job-manager.ts +3 -0
  45. package/src/cli/bench-cli.ts +8 -2
  46. package/src/cli/dry-balance-cli.ts +1 -0
  47. package/src/config/model-registry.ts +89 -8
  48. package/src/config/model-resolver.ts +78 -14
  49. package/src/config/models-config-schema.ts +1 -0
  50. package/src/config/settings.ts +3 -1
  51. package/src/dap/client.ts +168 -1
  52. package/src/dap/config.ts +51 -1
  53. package/src/dap/session.ts +575 -234
  54. package/src/dap/types.ts +6 -5
  55. package/src/discovery/agents.ts +2 -2
  56. package/src/extensibility/extensions/runner.ts +6 -4
  57. package/src/extensibility/legacy-pi-coding-agent-shim.ts +26 -0
  58. package/src/launch/broker.ts +34 -31
  59. package/src/launch/client.ts +7 -1
  60. package/src/launch/spawn-options.test.ts +31 -0
  61. package/src/launch/spawn-options.ts +17 -0
  62. package/src/lsp/types.ts +5 -1
  63. package/src/main.ts +17 -4
  64. package/src/mcp/transports/stdio.test.ts +9 -1
  65. package/src/modes/components/ask-dialog.ts +137 -73
  66. package/src/modes/components/status-line/component.ts +2 -2
  67. package/src/modes/components/status-line/segments.ts +20 -3
  68. package/src/modes/components/status-line/types.ts +3 -1
  69. package/src/modes/components/tool-execution.ts +5 -0
  70. package/src/modes/components/transcript-container.ts +23 -122
  71. package/src/modes/components/tree-selector.ts +10 -4
  72. package/src/modes/controllers/event-controller.ts +1 -2
  73. package/src/modes/controllers/input-controller.ts +1 -1
  74. package/src/modes/controllers/selector-controller.ts +29 -8
  75. package/src/modes/interactive-mode.ts +40 -8
  76. package/src/modes/noninteractive-dispose.test.ts +12 -1
  77. package/src/modes/print-mode.ts +21 -9
  78. package/src/modes/rpc/rpc-input.ts +38 -0
  79. package/src/modes/rpc/rpc-mode.ts +7 -2
  80. package/src/modes/setup-wizard/scenes/sign-in.ts +3 -1
  81. package/src/modes/types.ts +2 -0
  82. package/src/modes/utils/ui-helpers.ts +3 -2
  83. package/src/prompts/tools/browser.md +3 -2
  84. package/src/prompts/tools/debug.md +2 -7
  85. package/src/prompts/tools/github.md +6 -1
  86. package/src/prompts/tools/hub.md +4 -2
  87. package/src/prompts/tools/task-async-contract.md +1 -0
  88. package/src/prompts/tools/task.md +9 -2
  89. package/src/sdk.ts +38 -6
  90. package/src/session/agent-session.ts +395 -162
  91. package/src/session/messages.test.ts +91 -0
  92. package/src/session/messages.ts +248 -110
  93. package/src/slash-commands/builtin-registry.ts +1 -0
  94. package/src/task/executor.ts +59 -33
  95. package/src/task/index.ts +46 -9
  96. package/src/task/worktree.ts +10 -0
  97. package/src/tools/browser/aria/aria-snapshot.ts +36 -8
  98. package/src/tools/browser/cmux/cmux-tab.ts +2 -1
  99. package/src/tools/browser/cmux/socket-client.ts +139 -3
  100. package/src/tools/browser/run-cancellation.ts +4 -0
  101. package/src/tools/browser/tab-protocol.ts +2 -0
  102. package/src/tools/browser/tab-supervisor.ts +21 -11
  103. package/src/tools/browser/tab-worker.ts +199 -33
  104. package/src/tools/debug.ts +3 -0
  105. package/src/tools/gh.ts +40 -2
  106. package/src/tools/hub/index.ts +4 -1
  107. package/src/tools/hub/jobs.ts +42 -1
  108. package/src/tools/hub/types.ts +2 -0
  109. package/src/tools/tool-timeouts.ts +1 -1
  110. package/src/utils/git.ts +237 -0
  111. package/src/web/search/index.ts +9 -5
  112. package/src/web/search/providers/codex.ts +195 -99
@@ -54,6 +54,8 @@ export declare function isAdvisorInterruptImmuneTurnActive(opts: {
54
54
  /**
55
55
  * Decide how one advisor note reaches the primary agent.
56
56
  *
57
+ * - A `preserveOnly` caller records every note that arrives while the primary
58
+ * is idle as a visible card and never starts a new primary turn.
57
59
  * - A non-interrupting `nit` always rides the non-interrupting aside queue.
58
60
  * - An interrupting `concern`/`blocker` is normally steered into the agent: into
59
61
  * the live turn while one is streaming, or (when idle) a triggered turn so the
@@ -82,6 +84,7 @@ export declare function resolveAdvisorDeliveryChannel(opts: {
82
84
  aborting: boolean;
83
85
  terminalAnswerNoQueuedWork?: boolean;
84
86
  interruptImmuneTurnActive?: boolean;
87
+ preserveOnly?: boolean;
85
88
  }): AdvisorDeliveryChannel;
86
89
  /**
87
90
  * Derive the advisor loop's telemetry from the primary session's config so the
@@ -117,7 +117,13 @@ export declare class AdvisorRuntime {
117
117
  onTurnEnd(messages?: AgentMessage[], opts?: {
118
118
  willContinue?: boolean;
119
119
  }): void;
120
- waitForCatchup(maxMs: number, threshold: number, signal?: AbortSignal): Promise<void>;
120
+ /**
121
+ * Wait until the advisor backlog falls below `threshold`.
122
+ *
123
+ * Returns `false` when the deadline, abort signal, or a runtime failure releases
124
+ * the waiter before the requested backlog was drained.
125
+ */
126
+ waitForCatchup(maxMs: number, threshold: number, signal?: AbortSignal): Promise<boolean>;
121
127
  dispose(): void;
122
128
  /**
123
129
  * Re-prime the advisor after a history rewrite (compaction, session
@@ -8,6 +8,8 @@ export interface AsyncJob {
8
8
  promise: Promise<void>;
9
9
  resultText?: string;
10
10
  errorText?: string;
11
+ /** Latest tool-render details reported by the running job. */
12
+ latestDetails?: Record<string, unknown>;
11
13
  /**
12
14
  * Registry id of the agent that registered the job (e.g. "Main",
13
15
  * "AuthLoader"). Used by scoped cancel/list APIs so a subagent's teardown
@@ -124,6 +124,13 @@ export declare class ModelRegistry {
124
124
  * {@link ModelRegistry.resolver}.
125
125
  */
126
126
  hasConfiguredAuth(model: Model<Api>): boolean;
127
+ /**
128
+ * Whether the provider's configured API key is resolved from a command.
129
+ *
130
+ * Callers use this to distinguish the registry's command-first resolver
131
+ * path from lower-priority credentials in {@link authStorage}.
132
+ */
133
+ hasCommandBackedApiKey(provider: string): boolean;
127
134
  getDiscoverableProviders(): string[];
128
135
  getProviderDiscoveryState(provider: string): ProviderDiscoveryState | undefined;
129
136
  /**
@@ -133,6 +133,8 @@ export declare function resolveAgentPrewalkPattern(options: AgentPrewalkResoluti
133
133
  export interface ResolvedModelRoleValue {
134
134
  model: Model<Api> | undefined;
135
135
  thinkingLevel?: ConfiguredThinkingLevel;
136
+ /** matchedPatternIndex identifies the first configured pattern that matched an available model. */
137
+ matchedPatternIndex?: number;
136
138
  explicitThinkingLevel: boolean;
137
139
  warning: string | undefined;
138
140
  }
@@ -263,6 +265,10 @@ export declare function resolveAllowedModels(modelRegistry: Pick<ModelRegistry,
263
265
  export declare function filterAvailableModelsByEnabledPatterns(available: Model<Api>[], patterns: readonly string[], settings?: Settings): Model<Api>[];
264
266
  export interface ResolveCliModelResult {
265
267
  model: Model<Api> | undefined;
268
+ /** configuredPatterns is the full configured fallback chain when the selector resolves through a role. */
269
+ configuredPatterns?: string[];
270
+ /** configuredPatternIndex identifies the configured role pattern that matched an available model. */
271
+ configuredPatternIndex?: number;
266
272
  selector?: string;
267
273
  thinkingLevel?: ConfiguredThinkingLevel;
268
274
  warning: string | undefined;
@@ -270,6 +276,8 @@ export interface ResolveCliModelResult {
270
276
  }
271
277
  /**
272
278
  * Resolve a single model from CLI flags.
279
+ *
280
+ * Exact model names take precedence over configured role names.
273
281
  */
274
282
  export declare function resolveCliModel(options: {
275
283
  cliProvider?: string;
@@ -47,6 +47,7 @@ export declare const OpenAICompatSchema: import("arktype/internal/variants/objec
47
47
  strictResponsesPairing?: boolean | undefined;
48
48
  supportsImageDetailOriginal?: boolean | undefined;
49
49
  supportsEagerToolInputStreaming?: boolean | undefined;
50
+ allowAnthropicHeaderOverrides?: boolean | undefined;
50
51
  requiresToolResultId?: boolean | undefined;
51
52
  replayUnsignedThinking?: boolean | undefined;
52
53
  whenThinking?: {
@@ -98,6 +99,7 @@ export declare const OpenAICompatSchema: import("arktype/internal/variants/objec
98
99
  strictResponsesPairing?: boolean | undefined;
99
100
  supportsImageDetailOriginal?: boolean | undefined;
100
101
  supportsEagerToolInputStreaming?: boolean | undefined;
102
+ allowAnthropicHeaderOverrides?: boolean | undefined;
101
103
  requiresToolResultId?: boolean | undefined;
102
104
  replayUnsignedThinking?: boolean | undefined;
103
105
  } | undefined;
@@ -192,6 +194,7 @@ export declare const ModelOverrideSchema: import("arktype/internal/variants/obje
192
194
  strictResponsesPairing?: boolean | undefined;
193
195
  supportsImageDetailOriginal?: boolean | undefined;
194
196
  supportsEagerToolInputStreaming?: boolean | undefined;
197
+ allowAnthropicHeaderOverrides?: boolean | undefined;
195
198
  requiresToolResultId?: boolean | undefined;
196
199
  replayUnsignedThinking?: boolean | undefined;
197
200
  whenThinking?: {
@@ -243,6 +246,7 @@ export declare const ModelOverrideSchema: import("arktype/internal/variants/obje
243
246
  strictResponsesPairing?: boolean | undefined;
244
247
  supportsImageDetailOriginal?: boolean | undefined;
245
248
  supportsEagerToolInputStreaming?: boolean | undefined;
249
+ allowAnthropicHeaderOverrides?: boolean | undefined;
246
250
  requiresToolResultId?: boolean | undefined;
247
251
  replayUnsignedThinking?: boolean | undefined;
248
252
  } | undefined;
@@ -324,6 +328,7 @@ export declare const ModelsConfigSchema: import("arktype/internal/variants/objec
324
328
  strictResponsesPairing?: boolean | undefined;
325
329
  supportsImageDetailOriginal?: boolean | undefined;
326
330
  supportsEagerToolInputStreaming?: boolean | undefined;
331
+ allowAnthropicHeaderOverrides?: boolean | undefined;
327
332
  requiresToolResultId?: boolean | undefined;
328
333
  replayUnsignedThinking?: boolean | undefined;
329
334
  whenThinking?: {
@@ -375,6 +380,7 @@ export declare const ModelsConfigSchema: import("arktype/internal/variants/objec
375
380
  strictResponsesPairing?: boolean | undefined;
376
381
  supportsImageDetailOriginal?: boolean | undefined;
377
382
  supportsEagerToolInputStreaming?: boolean | undefined;
383
+ allowAnthropicHeaderOverrides?: boolean | undefined;
378
384
  requiresToolResultId?: boolean | undefined;
379
385
  replayUnsignedThinking?: boolean | undefined;
380
386
  } | undefined;
@@ -486,6 +492,7 @@ export declare const ModelsConfigSchema: import("arktype/internal/variants/objec
486
492
  strictResponsesPairing?: boolean | undefined;
487
493
  supportsImageDetailOriginal?: boolean | undefined;
488
494
  supportsEagerToolInputStreaming?: boolean | undefined;
495
+ allowAnthropicHeaderOverrides?: boolean | undefined;
489
496
  requiresToolResultId?: boolean | undefined;
490
497
  replayUnsignedThinking?: boolean | undefined;
491
498
  whenThinking?: {
@@ -537,6 +544,7 @@ export declare const ModelsConfigSchema: import("arktype/internal/variants/objec
537
544
  strictResponsesPairing?: boolean | undefined;
538
545
  supportsImageDetailOriginal?: boolean | undefined;
539
546
  supportsEagerToolInputStreaming?: boolean | undefined;
547
+ allowAnthropicHeaderOverrides?: boolean | undefined;
540
548
  requiresToolResultId?: boolean | undefined;
541
549
  replayUnsignedThinking?: boolean | undefined;
542
550
  } | undefined;
@@ -644,6 +652,7 @@ export declare const ModelsConfigSchema: import("arktype/internal/variants/objec
644
652
  strictResponsesPairing?: boolean | undefined;
645
653
  supportsImageDetailOriginal?: boolean | undefined;
646
654
  supportsEagerToolInputStreaming?: boolean | undefined;
655
+ allowAnthropicHeaderOverrides?: boolean | undefined;
647
656
  requiresToolResultId?: boolean | undefined;
648
657
  replayUnsignedThinking?: boolean | undefined;
649
658
  whenThinking?: {
@@ -695,6 +704,7 @@ export declare const ModelsConfigSchema: import("arktype/internal/variants/objec
695
704
  strictResponsesPairing?: boolean | undefined;
696
705
  supportsImageDetailOriginal?: boolean | undefined;
697
706
  supportsEagerToolInputStreaming?: boolean | undefined;
707
+ allowAnthropicHeaderOverrides?: boolean | undefined;
698
708
  requiresToolResultId?: boolean | undefined;
699
709
  replayUnsignedThinking?: boolean | undefined;
700
710
  } | undefined;
@@ -85,6 +85,7 @@ export declare const ModelsConfigFile: ConfigFile<{
85
85
  strictResponsesPairing?: boolean | undefined;
86
86
  supportsImageDetailOriginal?: boolean | undefined;
87
87
  supportsEagerToolInputStreaming?: boolean | undefined;
88
+ allowAnthropicHeaderOverrides?: boolean | undefined;
88
89
  requiresToolResultId?: boolean | undefined;
89
90
  replayUnsignedThinking?: boolean | undefined;
90
91
  whenThinking?: {
@@ -136,6 +137,7 @@ export declare const ModelsConfigFile: ConfigFile<{
136
137
  strictResponsesPairing?: boolean | undefined;
137
138
  supportsImageDetailOriginal?: boolean | undefined;
138
139
  supportsEagerToolInputStreaming?: boolean | undefined;
140
+ allowAnthropicHeaderOverrides?: boolean | undefined;
139
141
  requiresToolResultId?: boolean | undefined;
140
142
  replayUnsignedThinking?: boolean | undefined;
141
143
  } | undefined;
@@ -231,6 +233,7 @@ export declare const ModelsConfigFile: ConfigFile<{
231
233
  strictResponsesPairing?: boolean | undefined;
232
234
  supportsImageDetailOriginal?: boolean | undefined;
233
235
  supportsEagerToolInputStreaming?: boolean | undefined;
236
+ allowAnthropicHeaderOverrides?: boolean | undefined;
234
237
  requiresToolResultId?: boolean | undefined;
235
238
  replayUnsignedThinking?: boolean | undefined;
236
239
  whenThinking?: {
@@ -282,6 +285,7 @@ export declare const ModelsConfigFile: ConfigFile<{
282
285
  strictResponsesPairing?: boolean | undefined;
283
286
  supportsImageDetailOriginal?: boolean | undefined;
284
287
  supportsEagerToolInputStreaming?: boolean | undefined;
288
+ allowAnthropicHeaderOverrides?: boolean | undefined;
285
289
  requiresToolResultId?: boolean | undefined;
286
290
  replayUnsignedThinking?: boolean | undefined;
287
291
  } | undefined;
@@ -373,6 +377,7 @@ export declare const ModelsConfigFile: ConfigFile<{
373
377
  strictResponsesPairing?: boolean | undefined;
374
378
  supportsImageDetailOriginal?: boolean | undefined;
375
379
  supportsEagerToolInputStreaming?: boolean | undefined;
380
+ allowAnthropicHeaderOverrides?: boolean | undefined;
376
381
  requiresToolResultId?: boolean | undefined;
377
382
  replayUnsignedThinking?: boolean | undefined;
378
383
  whenThinking?: {
@@ -424,6 +429,7 @@ export declare const ModelsConfigFile: ConfigFile<{
424
429
  strictResponsesPairing?: boolean | undefined;
425
430
  supportsImageDetailOriginal?: boolean | undefined;
426
431
  supportsEagerToolInputStreaming?: boolean | undefined;
432
+ allowAnthropicHeaderOverrides?: boolean | undefined;
427
433
  requiresToolResultId?: boolean | undefined;
428
434
  replayUnsignedThinking?: boolean | undefined;
429
435
  } | undefined;
@@ -23,14 +23,24 @@ export declare class DapClient {
23
23
  readonly adapter: DapResolvedAdapter;
24
24
  readonly cwd: string;
25
25
  readonly proc: DapClientState["proc"];
26
+ /** TCP server port reused by child DAP sessions. */
27
+ readonly port?: number;
26
28
  constructor(adapter: DapResolvedAdapter, cwd: string, proc: DapClientState["proc"], options?: {
27
29
  readable?: ReadableStream<Uint8Array>;
28
30
  writeSink?: DapWriteSink;
29
31
  socket?: {
30
32
  end(): void;
31
33
  };
34
+ port?: number;
32
35
  });
33
36
  static spawn({ adapter, cwd, socketReadyTimeoutMs }: DapSpawnOptions): Promise<DapClient>;
37
+ /** Connect to another session on an existing TCP DAP server. */
38
+ static connect({ adapter, cwd, host, port, }: {
39
+ adapter: DapResolvedAdapter;
40
+ cwd: string;
41
+ host: string;
42
+ port: number;
43
+ }): Promise<DapClient>;
34
44
  get capabilities(): DapCapabilities | undefined;
35
45
  get lastActivity(): number;
36
46
  isAlive(): boolean;
@@ -418,10 +418,9 @@ export interface DapAdapterConfig {
418
418
  launchDefaults?: Record<string, unknown>;
419
419
  attachDefaults?: Record<string, unknown>;
420
420
  /** "stdio" (default): communicate via stdin/stdout pipes.
421
- * "socket": adapter uses a network socket instead of stdio.
422
- * On Linux, connects via a unix domain socket.
423
- * On macOS, the adapter dials into a local TCP listener (--client-addr). */
424
- connectMode?: "stdio" | "socket";
421
+ * "socket": adapter-specific socket launch (currently Delve).
422
+ * "tcp": spawn a DAP server with `${port}` substituted in `args`, then connect to it. */
423
+ connectMode?: "stdio" | "socket" | "tcp";
425
424
  /** When true, the adapter accepts a directory as the launch `program`
426
425
  * (e.g. dlv treats it as a Go package path). When false/undefined, the
427
426
  * debug tool rejects directory programs upfront. */
@@ -437,7 +436,7 @@ export interface DapResolvedAdapter {
437
436
  rootMarkers: string[];
438
437
  launchDefaults: Record<string, unknown>;
439
438
  attachDefaults: Record<string, unknown>;
440
- connectMode: "stdio" | "socket";
439
+ connectMode: "stdio" | "socket" | "tcp";
441
440
  acceptsDirectoryProgram: boolean;
442
441
  }
443
442
  export interface DapBreakpointRecord {
@@ -508,6 +507,8 @@ export interface DapSessionSummary {
508
507
  outputTruncated: boolean;
509
508
  exitCode?: number;
510
509
  needsConfigurationDone: boolean;
510
+ parentSessionId?: string;
511
+ childSessionIds?: string[];
511
512
  }
512
513
  export interface DapContinueOutcome {
513
514
  snapshot: DapSessionSummary;
@@ -113,7 +113,8 @@ export declare class ExtensionRunner {
113
113
  path: string;
114
114
  }>;
115
115
  getCommand(name: string): RegisteredCommand | undefined;
116
- createContext(): ExtensionContext;
116
+ /** Creates an extension context, optionally scoped to a provider request model. */
117
+ createContext(model?: Model): ExtensionContext;
117
118
  /**
118
119
  * Request a graceful shutdown. Called by extension tools and event handlers.
119
120
  */
@@ -164,7 +165,8 @@ export declare class ExtensionRunner {
164
165
  /** Emit input event. Transforms chain, "handled" short-circuits. */
165
166
  emitInput(text: string, images: ImageContent[] | undefined, source: "interactive" | "rpc" | "extension"): Promise<InputEventResult>;
166
167
  emitContext(messages: AgentMessage[]): Promise<AgentMessage[]>;
167
- emitBeforeProviderRequest(payload: unknown): Promise<BeforeProviderRequestEventResult>;
168
+ /** Runs request payload hooks with the model used for that provider request. */
169
+ emitBeforeProviderRequest(payload: unknown, model?: Model): Promise<BeforeProviderRequestEventResult>;
168
170
  emitAfterProviderResponse(response: ProviderResponseMetadata, _model?: Model): Promise<void>;
169
171
  emitBeforeAgentStart(prompt: string, images: ImageContent[] | undefined, systemPrompt: string[]): Promise<BeforeAgentStartCombinedResult | undefined>;
170
172
  }
@@ -353,6 +353,22 @@ export declare class AuthStorage {
353
353
  }
354
354
  /** Read the first active credential for a legacy extension provider. */
355
355
  export declare function readStoredCredential(provider: string): AuthCredential | undefined;
356
+ export { getProjectDir } from "@oh-my-pi/pi-utils";
357
+ /**
358
+ * Coding-agent package install directory, matching pi's string-valued
359
+ * `getPackageDir()` contract (extensions do `path.join(getPackageDir(), ...)`
360
+ * to auto-allow bundled docs/resources).
361
+ *
362
+ * omp's canonical `getPackageDir()` (`../config`) returns `undefined` inside a
363
+ * `bun --compile` binary — `import.meta.dir` is `/$bunfs/root` and no owning
364
+ * `package.json` exists (issue #1423). Returning `undefined` there would crash
365
+ * every legacy `path.join(getPackageDir(), ...)` at runtime in the shipped
366
+ * binary, the primary distribution. So fall back to the executable's own
367
+ * directory in compiled mode, where the binary *is* the install root. The
368
+ * `PI_PACKAGE_DIR` override and dev/source/npm-dist walk-up still win via the
369
+ * canonical helper.
370
+ */
371
+ export declare function getPackageDir(): string;
356
372
  export * from "../index.js";
357
373
  export { formatBytes as formatSize } from "../tools/render-utils.js";
358
374
  export { Type } from "./typebox.js";
@@ -0,0 +1,10 @@
1
+ /** Platform-specific options for the launch broker and its non-PTY children. */
2
+ export interface DaemonSpawnOptions {
3
+ detached: boolean;
4
+ windowsHide?: boolean;
5
+ }
6
+ /** Keep launch processes headless without discarding an inheritable Windows console. */
7
+ export declare function resolveDaemonSpawnOptions(opts: {
8
+ platform: NodeJS.Platform;
9
+ hostHasInheritableConsole: boolean;
10
+ }): DaemonSpawnOptions;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,6 @@
1
1
  import { type Component } from "@oh-my-pi/pi-tui";
2
2
  import type { AgentSession } from "../../../session/agent-session.js";
3
+ import { type SegmentContext } from "./segments.js";
3
4
  import type { CollabStatus, EffectiveStatusLineSettings, StatusLineSettings } from "./types.js";
4
5
  export declare class StatusLineComponent implements Component {
5
6
  #private;
@@ -55,9 +56,7 @@ export declare class StatusLineComponent implements Component {
55
56
  enabled: boolean;
56
57
  paused: boolean;
57
58
  } | undefined): void;
58
- setLoopModeStatus(status: {
59
- enabled: boolean;
60
- } | undefined): void;
59
+ setLoopModeStatus(status: NonNullable<SegmentContext["loopMode"]> | undefined): void;
61
60
  setGoalModeStatus(status: {
62
61
  enabled: boolean;
63
62
  paused: boolean;
@@ -2,6 +2,7 @@ import type { CollabSessionState } from "../../../collab/protocol.js";
2
2
  import type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle } from "../../../config/settings-schema.js";
3
3
  import type { AgentSession } from "../../../session/agent-session.js";
4
4
  import type { ActiveRepoContext } from "../../../utils/active-repo-context.js";
5
+ import type { LoopLimitRuntime } from "../../loop-limit.js";
5
6
  export type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle };
6
7
  /** Collab session indicator + (guest-only) host-state override for segments. */
7
8
  export interface CollabStatus {
@@ -64,7 +65,8 @@ export interface SegmentContext {
64
65
  enabled: boolean;
65
66
  } | null;
66
67
  loopMode: {
67
- enabled: boolean;
68
+ state: "waiting" | "running" | "paused";
69
+ limit?: LoopLimitRuntime;
68
70
  } | null;
69
71
  goalMode: {
70
72
  enabled: boolean;
@@ -92,6 +92,8 @@ export declare class ToolExecutionComponent extends Container implements NativeS
92
92
  * immutable native scrollback before the result replaces them.
93
93
  */
94
94
  getNativeScrollbackLiveRegionStart(): number | undefined;
95
+ /** Keeps the in-flight `vibe_wait` TV wall out of immutable native scrollback. */
96
+ isNativeScrollbackLiveRegionPinned(): boolean;
95
97
  /**
96
98
  * Whether this block has reached a terminal state for transcript freezing.
97
99
  * Reports `false` while it can still visually change so the
@@ -1,4 +1,4 @@
1
- import { type Component, Container, type NativeScrollbackCommittedRows, type NativeScrollbackLiveRegion, type NativeScrollbackReplay, type RenderStablePrefix, type ViewportTailProvider } from "@oh-my-pi/pi-tui";
1
+ import { type Component, Container, type NativeScrollbackCommittedRows, type NativeScrollbackLiveRegion, type RenderStablePrefix, type ViewportTailProvider } from "@oh-my-pi/pi-tui";
2
2
  /**
3
3
  * Transcript container that renders every block's current content each frame
4
4
  * and reports the native-scrollback exactness boundary
@@ -24,14 +24,15 @@ import { type Component, Container, type NativeScrollbackCommittedRows, type Nat
24
24
  * through {@link RenderStablePrefix} so the engine can skip marker scanning,
25
25
  * line preparation, and the committed-prefix audit for those rows.
26
26
  */
27
- export declare class TranscriptContainer extends Container implements NativeScrollbackLiveRegion, NativeScrollbackCommittedRows, NativeScrollbackReplay, RenderStablePrefix, ViewportTailProvider {
27
+ export declare class TranscriptContainer extends Container implements NativeScrollbackLiveRegion, NativeScrollbackCommittedRows, RenderStablePrefix, ViewportTailProvider {
28
28
  #private;
29
29
  invalidate(): void;
30
30
  clear(): void;
31
31
  setNativeScrollbackCommittedRows(rows: number): void;
32
- prepareNativeScrollbackReplay(): void;
33
32
  getRenderStablePrefixRows(): number;
34
33
  getNativeScrollbackLiveRegionStart(): number | undefined;
34
+ /** Propagates viewport pinning from the first still-mutating transcript block. */
35
+ isNativeScrollbackLiveRegionPinned(): boolean;
35
36
  /**
36
37
  * Whether none of `component`'s rows (per the most recent render) have
37
38
  * entered native scrollback. Callers that retract ephemeral blocks (IRC
@@ -7,7 +7,9 @@ declare class TreeList implements Component {
7
7
  #private;
8
8
  private readonly currentLeafId;
9
9
  private readonly maxVisibleLines;
10
- onSelect?: (entryId: string) => void;
10
+ onSelect?: (entryId: string, options: {
11
+ summarize: boolean;
12
+ }) => void;
11
13
  onCancel?: () => void;
12
14
  onLabelEdit?: (entryId: string, currentLabel: string | undefined) => void;
13
15
  constructor(tree: SessionTreeNode[], currentLeafId: string | null, maxVisibleLines: number, initialFilterMode?: FilterMode, initialSelectedId?: string);
@@ -24,7 +26,9 @@ declare class TreeList implements Component {
24
26
  export declare class TreeSelectorComponent extends Container {
25
27
  #private;
26
28
  private readonly onLabelChangeCallback?;
27
- constructor(tree: SessionTreeNode[], currentLeafId: string | null, terminalHeight: number, onSelect: (entryId: string) => void, onCancel: () => void, onLabelChangeCallback?: ((entryId: string, label: string | undefined) => void) | undefined, initialFilterMode?: FilterMode);
29
+ constructor(tree: SessionTreeNode[], currentLeafId: string | null, terminalHeight: number, onSelect: (entryId: string, options: {
30
+ summarize: boolean;
31
+ }) => void, onCancel: () => void, onLabelChangeCallback?: ((entryId: string, label: string | undefined) => void) | undefined, initialFilterMode?: FilterMode);
28
32
  handleInput(keyData: string): void;
29
33
  getTreeList(): TreeList;
30
34
  }
@@ -108,6 +108,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
108
108
  vibeModeEnabled: boolean;
109
109
  planModePlanFilePath: string | undefined;
110
110
  loopModeEnabled: boolean;
111
+ loopModePaused: boolean;
111
112
  loopPrompt: string | undefined;
112
113
  loopLimit: LoopLimitRuntime | undefined;
113
114
  todoPhases: TodoPhase[];
@@ -195,6 +196,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
195
196
  applyCwdChange(newCwd: string): Promise<void>;
196
197
  getUserInput(): Promise<SubmittedUserInput>;
197
198
  disableLoopMode(message?: string): void;
199
+ setLoopPrompt(prompt: string): void;
198
200
  /**
199
201
  * Pause the loop without exiting it: drops the captured prompt and any
200
202
  * pending auto-resubmit. Loop mode stays enabled — the next prompt the
@@ -15,6 +15,10 @@ export interface PrintModeOptions {
15
15
  /** If true, include thinking blocks in text output */
16
16
  printThoughts?: boolean;
17
17
  }
18
+ /** Matches the longest built-in provider request deadline while bounding tool-loop stalls. */
19
+ export declare const PRINT_MODE_ADVISOR_DRAIN_TIMEOUT_MS: number;
20
+ /** Error exits cannot hold automation for the full normal drain budget. */
21
+ export declare const PRINT_MODE_ERROR_ADVISOR_DRAIN_TIMEOUT_MS = 30000;
18
22
  /**
19
23
  * Shape an event for `--mode json` output.
20
24
  *
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Claims Bun's singleton stdin reader immediately and exposes a separately readable stream.
3
+ * RPC startup uses this before extension discovery so in-process modules cannot steal protocol input.
4
+ */
5
+ export declare function claimRpcInput(): ReadableStream<Uint8Array>;
@@ -162,4 +162,4 @@ export declare function requestRpcEditor(pendingRequests: Map<string, PendingExt
162
162
  * Run in RPC mode.
163
163
  * Listens for JSON commands on stdin, outputs events and responses on stdout.
164
164
  */
165
- export declare function runRpcMode(session: AgentSession, setToolUIContext?: (uiContext: ExtensionUIContext, hasUI: boolean) => void, eventBus?: EventBus): Promise<never>;
165
+ export declare function runRpcMode(session: AgentSession, setToolUIContext?: (uiContext: ExtensionUIContext, hasUI: boolean) => void, eventBus?: EventBus, input?: ReadableStream<Uint8Array>): Promise<never>;
@@ -139,6 +139,7 @@ export interface InteractiveModeContext {
139
139
  goalModeEnabled: boolean;
140
140
  goalModePaused: boolean;
141
141
  loopModeEnabled: boolean;
142
+ loopModePaused: boolean;
142
143
  loopPrompt?: string;
143
144
  loopLimit?: LoopLimitRuntime;
144
145
  planModePlanFilePath?: string;
@@ -389,6 +390,7 @@ export interface InteractiveModeContext {
389
390
  handleGoalModeCommand(rest?: string): Promise<void>;
390
391
  handleGuidedGoalCommand(rest?: string): Promise<void>;
391
392
  handleLoopCommand(args?: string): Promise<string | undefined>;
393
+ setLoopPrompt(prompt: string): void;
392
394
  disableLoopMode(): void;
393
395
  pauseLoop(): void;
394
396
  handlePlanApproval(details: PlanApprovalDetails): Promise<void>;
@@ -46,6 +46,8 @@ export interface CreateAgentSessionOptions {
46
46
  modelPatternAuthFallback?: string;
47
47
  /** Role name used to install retry fallbacks after deferred subagent patterns resolve. */
48
48
  modelPatternFallbackRole?: string;
49
+ /** Validated default retry chain to install when a deferred singleton pattern resolves. */
50
+ modelPatternDefaultFallbackChain?: string[];
49
51
  /** Thinking selector. Default: from settings, else unset */
50
52
  thinkingLevel?: ConfiguredThinkingLevel;
51
53
  /** Models available for cycling (Ctrl+P in interactive mode) */
@@ -657,10 +657,26 @@ export declare class AgentSession {
657
657
  get isAborting(): boolean;
658
658
  /** Wait until streaming and deferred recovery work are fully settled. */
659
659
  waitForIdle(): Promise<void>;
660
+ /**
661
+ * Prevent advisor notes from starting hidden primary turns while a headless
662
+ * caller prints and drains the final primary response.
663
+ */
664
+ prepareForHeadlessAdvisorDrain(): void;
665
+ /**
666
+ * Wait for active advisor reviews and their emitted card events before a
667
+ * headless caller disposes the session. Returns `false` and logs work disposal
668
+ * will abandon when the shared deadline expires or an advisor fails.
669
+ */
670
+ waitForAdvisorCatchup(timeoutMs: number): Promise<boolean>;
660
671
  drainAsyncJobDeliveriesForAcp(options?: {
661
672
  timeoutMs?: number;
662
673
  }): Promise<boolean>;
663
- /** Most recent assistant message in agent state. */
674
+ /**
675
+ * Most recent settled assistant message. A classifier-refusal turn pruned
676
+ * from active context at settle is still reported until the next run
677
+ * starts, so terminal-outcome consumers (print mode, task executor) see
678
+ * the refusal error rather than the previous turn — or nothing.
679
+ */
664
680
  getLastAssistantMessage(): AssistantMessage | undefined;
665
681
  /** Current effective system prompt blocks (includes any per-turn extension modifications) */
666
682
  get systemPrompt(): string[];
@@ -738,6 +754,8 @@ export declare class AgentSession {
738
754
  * to avoid racing against the delivery turn.
739
755
  */
740
756
  get hasPostPromptWork(): boolean;
757
+ /** Register post-prompt work in tests without driving a full agent turn. */
758
+ trackPostPromptTaskForTests(task: Promise<unknown>): void;
741
759
  /** All messages including custom types like BashExecutionMessage */
742
760
  get messages(): AgentMessage[];
743
761
  /** Latest image attachments addressable by tools as `Image #N` or `attachment://N`. */
@@ -250,5 +250,11 @@ export declare function sanitizeRehydratedOpenAIResponsesAssistantMessage(messag
250
250
  * - Agent's transormToLlm option (for prompt calls and queued messages)
251
251
  * - Compaction's generateSummary (for summarization)
252
252
  * - Custom extensions and tools
253
+ *
254
+ * Settled history converts once and is reused per message identity: an
255
+ * append-only turn on the same array re-pays only the new suffix, and an
256
+ * unchanged re-convert of the same array hands back the same outer `Message[]`.
257
+ * Owner mutations (prune/shake/strip-images) invalidate the affected message
258
+ * through the shared registry before the next pass.
253
259
  */
254
260
  export declare function convertToLlm(messages: AgentMessage[]): Message[];
@@ -19,13 +19,23 @@ export declare function captureAriaSnapshot(page: Page, root: ElementHandle | nu
19
19
  */
20
20
  export declare function resolveAriaRefHandle(page: Page, ref: string): Promise<ElementHandle | null>;
21
21
  /**
22
- * Recognize the explicit `[ref=eN]` selector forms and return the bare ref id,
23
- * else null. Accepts `aria-ref=e5` (Playwright-MCP style), `aria-ref/e5`, and
24
- * `ariaref/e5` — lets `tab.click("aria-ref=e5")` etc. act on snapshot refs. A
25
- * bare `e5` is intentionally NOT a ref selector: the cmux backend already uses
26
- * bare `eN`/`@eN` for its own observe ids, so requiring the prefix keeps action
27
- * selectors meaning the same thing on both backends. (`tab.ref("e5")` still
28
- * accepts a bare id directly.)
22
+ * Guard the selector funnels: `tab.click`/`type`/`fill`/`waitFor*`/`scrollIntoView`
23
+ * take string selectors only, but user `run` code routinely passes the ElementHandle
24
+ * from `tab.id(n)`/`tab.ref(...)` (or an un-awaited Promise of one) straight in.
25
+ * Without this the value reaches `.trim()`/`.startsWith()` and throws the opaque,
26
+ * minified `A.trim is not a function` instead of a recovery-naming ToolError.
27
+ */
28
+ export declare function assertSelectorString(selector: unknown): asserts selector is string;
29
+ /**
30
+ * Recognize a snapshot-ref selector and return the bare ref id, else null.
31
+ * Accepts `aria-ref=e5` (Playwright-MCP style), `aria-ref/e5`, `ariaref/e5`,
32
+ * and bare `e5`/`@e5`: agents copy ids straight out of the snapshot YAML
33
+ * (`[ref=e5]`), so `tab.click("e5")` must act on the ref instead of falling
34
+ * through to a CSS tag selector that can never match. Bare ids are safe to
35
+ * claim here — an eN tag name is not real HTML, and the tab-worker backend's
36
+ * observe ids are numeric (`tab.id(7)`), so refs are its only eN namespace.
37
+ * (The cmux backend parses selectors itself and routes bare `eN` to its own
38
+ * observe ids; either way `eN` means "the id from the last page dump".)
29
39
  */
30
40
  export declare function parseAriaRefSelector(selector: string): string | null;
31
41
  /**
@@ -9,6 +9,8 @@ export declare class CmuxSocketClient {
9
9
  constructor(opts: {
10
10
  socketPath: string;
11
11
  password?: string;
12
+ relayId?: string;
13
+ relayToken?: string;
12
14
  });
13
15
  connect(): Promise<void>;
14
16
  request(method: string, params: Record<string, unknown>, opts?: {
@@ -115,6 +115,8 @@ export interface RunErrorPayload {
115
115
  stack?: string;
116
116
  isToolError: boolean;
117
117
  isAbort: boolean;
118
+ /** The worker could not restore tab-scoped browser state and must be recycled. */
119
+ recoverTab?: boolean;
118
120
  }
119
121
  export type WorkerOutbound = {
120
122
  type: "ready";
@@ -27,6 +27,8 @@ export interface OpTimeouts {
27
27
  }
28
28
  /** Resolve the per-op fail-fast ceilings for a given cell budget. */
29
29
  export declare function resolveOpTimeouts(cellTimeoutMs: number): OpTimeouts;
30
+ /** Queue a wheel event without treating a delayed renderer acknowledgement as dispatch failure. */
31
+ export declare function dispatchScroll(dispatch: () => Promise<void>, ackTimeoutMs?: number): Promise<void>;
30
32
  /**
31
33
  * Effective timeout for a wait helper (`waitFor*`). A positive explicit `{ timeout }` is
32
34
  * honored but clamped to the cell budget so it still fails fast + named; raising the tool