@oh-my-pi/pi-coding-agent 17.1.8 → 17.2.1

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 (246) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/dist/{CHANGELOG-vt8ene9g.md → CHANGELOG-dj46zzrm.md} +110 -0
  3. package/dist/cli.js +10009 -9654
  4. package/dist/{template-dys3vk5b.js → template-8vdv6xb4.js} +1 -1
  5. package/dist/types/advisor/runtime.d.ts +8 -2
  6. package/dist/types/advisor/transcript-recorder.d.ts +15 -0
  7. package/dist/types/auto-thinking/classifier.d.ts +9 -2
  8. package/dist/types/cli/args.d.ts +2 -0
  9. package/dist/types/cli/session-picker.d.ts +14 -7
  10. package/dist/types/collab/guest.d.ts +21 -2
  11. package/dist/types/commands/launch.d.ts +6 -0
  12. package/dist/types/config/model-discovery.d.ts +12 -0
  13. package/dist/types/config/settings-schema.d.ts +73 -8
  14. package/dist/types/cursor-bridge-tools.d.ts +54 -0
  15. package/dist/types/cursor.d.ts +193 -8
  16. package/dist/types/edit/edit-clipboard.d.ts +19 -0
  17. package/dist/types/edit/hashline/diff.d.ts +9 -1
  18. package/dist/types/edit/index.d.ts +8 -1
  19. package/dist/types/edit/streaming.d.ts +8 -1
  20. package/dist/types/extensibility/extensions/runner.d.ts +19 -2
  21. package/dist/types/extensibility/extensions/types.d.ts +25 -1
  22. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +25 -0
  23. package/dist/types/internal-urls/index.d.ts +1 -0
  24. package/dist/types/internal-urls/local-protocol.d.ts +3 -2
  25. package/dist/types/internal-urls/security-protocol.d.ts +15 -0
  26. package/dist/types/internal-urls/types.d.ts +1 -1
  27. package/dist/types/launch/terminal-output-worker-client.d.ts +5 -0
  28. package/dist/types/launch/terminal-output-worker-protocol.d.ts +14 -0
  29. package/dist/types/launch/terminal-output-worker.d.ts +1 -0
  30. package/dist/types/lsp/client.d.ts +2 -0
  31. package/dist/types/main.d.ts +2 -0
  32. package/dist/types/mcp/manager.d.ts +33 -4
  33. package/dist/types/modes/components/codex-reset-fireworks.d.ts +51 -0
  34. package/dist/types/modes/components/read-tool-group.d.ts +12 -0
  35. package/dist/types/modes/components/session-selector.d.ts +6 -0
  36. package/dist/types/modes/components/status-line/component.d.ts +23 -0
  37. package/dist/types/modes/components/tool-execution.d.ts +16 -7
  38. package/dist/types/modes/components/usage-row.d.ts +2 -0
  39. package/dist/types/modes/controllers/mcp-command-controller.d.ts +26 -1
  40. package/dist/types/modes/controllers/selector-controller.d.ts +2 -1
  41. package/dist/types/modes/interactive-mode.d.ts +4 -2
  42. package/dist/types/modes/rpc/rpc-client.d.ts +7 -0
  43. package/dist/types/modes/rpc/rpc-types.d.ts +16 -0
  44. package/dist/types/modes/theme/theme.d.ts +12 -1
  45. package/dist/types/modes/types.d.ts +2 -1
  46. package/dist/types/sdk.d.ts +18 -0
  47. package/dist/types/security/auth.d.ts +30 -0
  48. package/dist/types/security/cloud.d.ts +79 -0
  49. package/dist/types/security/comparison.d.ts +49 -0
  50. package/dist/types/security/contracts/ids.d.ts +15 -0
  51. package/dist/types/security/contracts/index.d.ts +4 -0
  52. package/dist/types/security/contracts/schemas.d.ts +660 -0
  53. package/dist/types/security/contracts/types.d.ts +234 -0
  54. package/dist/types/security/contracts/validation.d.ts +5 -0
  55. package/dist/types/security/coordinator.d.ts +100 -0
  56. package/dist/types/security/importers/codex-security.d.ts +7 -0
  57. package/dist/types/security/importers/index.d.ts +2 -0
  58. package/dist/types/security/importers/sarif.d.ts +9 -0
  59. package/dist/types/security/index.d.ts +13 -0
  60. package/dist/types/security/preflight.d.ts +61 -0
  61. package/dist/types/security/provenance.d.ts +24 -0
  62. package/dist/types/security/publication.d.ts +78 -0
  63. package/dist/types/security/remediation.d.ts +27 -0
  64. package/dist/types/security/resource-output.d.ts +8 -0
  65. package/dist/types/security/sarif.d.ts +2 -0
  66. package/dist/types/security/store.d.ts +40 -0
  67. package/dist/types/session/agent-session-events.d.ts +2 -0
  68. package/dist/types/session/agent-session-types.d.ts +36 -1
  69. package/dist/types/session/agent-session.d.ts +4 -2
  70. package/dist/types/session/claude-session-store.d.ts +13 -0
  71. package/dist/types/session/codex-session-store.d.ts +14 -0
  72. package/dist/types/session/credential-pin.d.ts +58 -0
  73. package/dist/types/session/foreign-session-import.d.ts +15 -0
  74. package/dist/types/session/foreign-session-jsonl.d.ts +9 -0
  75. package/dist/types/session/foreign-session-store.d.ts +23 -0
  76. package/dist/types/session/session-advisors.d.ts +47 -2
  77. package/dist/types/session/session-entries.d.ts +19 -1
  78. package/dist/types/session/session-handoff.d.ts +4 -1
  79. package/dist/types/session/session-loader.d.ts +2 -0
  80. package/dist/types/session/session-maintenance.d.ts +1 -1
  81. package/dist/types/session/session-manager.d.ts +21 -0
  82. package/dist/types/session/session-tools.d.ts +25 -1
  83. package/dist/types/session/turn-recovery.d.ts +10 -4
  84. package/dist/types/slash-commands/helpers/security.d.ts +2 -0
  85. package/dist/types/system-prompt.d.ts +4 -1
  86. package/dist/types/task/executor.d.ts +14 -2
  87. package/dist/types/task/render.d.ts +7 -0
  88. package/dist/types/thinking.d.ts +18 -6
  89. package/dist/types/tools/acp-bridge.d.ts +28 -5
  90. package/dist/types/tools/builtin-names.d.ts +1 -1
  91. package/dist/types/tools/grep.d.ts +17 -1
  92. package/dist/types/tools/hub/launch.d.ts +5 -1
  93. package/dist/types/tools/index.d.ts +10 -2
  94. package/dist/types/tools/path-utils.d.ts +19 -0
  95. package/dist/types/tools/read.d.ts +2 -0
  96. package/dist/types/tools/security-scan.d.ts +96 -0
  97. package/dist/types/tools/xdev.d.ts +2 -1
  98. package/dist/types/utils/changelog.d.ts +19 -0
  99. package/dist/types/utils/git.d.ts +10 -0
  100. package/dist/types/utils/jj.d.ts +11 -4
  101. package/dist/types/web/search/types.d.ts +2 -2
  102. package/package.json +12 -12
  103. package/scripts/security-compare.ts +40 -0
  104. package/src/advisor/runtime.ts +138 -12
  105. package/src/advisor/transcript-recorder.ts +56 -0
  106. package/src/auto-thinking/classifier.ts +48 -10
  107. package/src/cli/args.ts +6 -0
  108. package/src/cli/flag-tables.ts +2 -0
  109. package/src/cli/gallery-fixtures/fs.ts +25 -0
  110. package/src/cli/session-picker.ts +34 -17
  111. package/src/cli/ttsr-cli.ts +19 -1
  112. package/src/cli.ts +9 -0
  113. package/src/collab/guest.ts +37 -4
  114. package/src/collab/host.ts +1 -0
  115. package/src/commands/launch.ts +6 -0
  116. package/src/config/model-discovery.ts +32 -5
  117. package/src/config/model-registry.ts +107 -25
  118. package/src/config/settings-schema.ts +77 -6
  119. package/src/config/settings.ts +25 -0
  120. package/src/cursor-bridge-tools.ts +81 -0
  121. package/src/cursor.ts +463 -12
  122. package/src/edit/edit-clipboard.ts +23 -0
  123. package/src/edit/hashline/diff.ts +49 -10
  124. package/src/edit/hashline/execute.ts +38 -6
  125. package/src/edit/hashline/filesystem.ts +27 -3
  126. package/src/edit/index.ts +12 -2
  127. package/src/edit/renderer.ts +4 -4
  128. package/src/edit/streaming.ts +17 -2
  129. package/src/eval/py/prelude.py +7 -3
  130. package/src/export/html/template.js +1 -1
  131. package/src/extensibility/extensions/runner.ts +70 -0
  132. package/src/extensibility/extensions/types.ts +30 -0
  133. package/src/extensibility/legacy-pi-coding-agent-shim.ts +65 -13
  134. package/src/internal-urls/index.ts +1 -0
  135. package/src/internal-urls/local-protocol.ts +3 -2
  136. package/src/internal-urls/mcp-protocol.ts +4 -1
  137. package/src/internal-urls/router.ts +4 -1
  138. package/src/internal-urls/security-protocol.ts +261 -0
  139. package/src/internal-urls/types.ts +1 -1
  140. package/src/launch/terminal-output-worker-client.ts +53 -0
  141. package/src/launch/terminal-output-worker-protocol.ts +11 -0
  142. package/src/launch/terminal-output-worker.ts +23 -0
  143. package/src/lsp/client.ts +18 -3
  144. package/src/lsp/index.ts +7 -0
  145. package/src/lsp/render.ts +1 -1
  146. package/src/main.ts +127 -56
  147. package/src/mcp/manager.ts +120 -18
  148. package/src/modes/acp/acp-agent.ts +15 -9
  149. package/src/modes/components/chat-transcript-builder.ts +30 -11
  150. package/src/modes/components/codex-reset-fireworks.ts +369 -0
  151. package/src/modes/components/read-tool-group.ts +159 -17
  152. package/src/modes/components/session-selector.ts +19 -3
  153. package/src/modes/components/status-line/component.ts +381 -54
  154. package/src/modes/components/tool-execution.ts +78 -31
  155. package/src/modes/components/usage-row.ts +10 -5
  156. package/src/modes/controllers/event-controller.ts +26 -4
  157. package/src/modes/controllers/mcp-command-controller.ts +68 -3
  158. package/src/modes/controllers/selector-controller.ts +94 -36
  159. package/src/modes/controllers/tan-command-controller.ts +14 -0
  160. package/src/modes/interactive-mode.ts +31 -17
  161. package/src/modes/rpc/host-uris.ts +6 -0
  162. package/src/modes/rpc/rpc-client.ts +18 -0
  163. package/src/modes/rpc/rpc-mode.ts +16 -1
  164. package/src/modes/rpc/rpc-types.ts +11 -0
  165. package/src/modes/theme/theme.ts +151 -6
  166. package/src/modes/types.ts +2 -1
  167. package/src/modes/utils/ui-helpers.ts +38 -21
  168. package/src/prompts/agents/security-reviewer.md +75 -0
  169. package/src/prompts/security/scan-coordinator.md +7 -0
  170. package/src/prompts/security/scan-request.md +21 -0
  171. package/src/prompts/security/validate-request.md +8 -0
  172. package/src/prompts/system/auto-thinking-difficulty.md +4 -2
  173. package/src/prompts/system/plan-mode-active.md +2 -2
  174. package/src/prompts/system/system-prompt.md +6 -0
  175. package/src/prompts/system/xdev-mount-notice.md +1 -1
  176. package/src/prompts/tools/bash.md +15 -17
  177. package/src/prompts/tools/checkpoint.md +1 -1
  178. package/src/prompts/tools/glob.md +7 -6
  179. package/src/prompts/tools/grep.md +7 -6
  180. package/src/prompts/tools/security-publish.md +1 -0
  181. package/src/prompts/tools/security-scan.md +1 -0
  182. package/src/sdk.ts +212 -21
  183. package/src/security/auth.ts +98 -0
  184. package/src/security/cloud.ts +686 -0
  185. package/src/security/comparison.ts +255 -0
  186. package/src/security/contracts/ids.ts +111 -0
  187. package/src/security/contracts/index.ts +4 -0
  188. package/src/security/contracts/schemas.ts +201 -0
  189. package/src/security/contracts/types.ts +254 -0
  190. package/src/security/contracts/validation.ts +65 -0
  191. package/src/security/coordinator.ts +708 -0
  192. package/src/security/importers/codex-security.ts +387 -0
  193. package/src/security/importers/index.ts +2 -0
  194. package/src/security/importers/sarif.ts +357 -0
  195. package/src/security/index.ts +13 -0
  196. package/src/security/preflight.ts +405 -0
  197. package/src/security/provenance.ts +106 -0
  198. package/src/security/publication.ts +326 -0
  199. package/src/security/remediation.ts +93 -0
  200. package/src/security/resource-output.ts +50 -0
  201. package/src/security/sarif.ts +78 -0
  202. package/src/security/store.ts +430 -0
  203. package/src/session/agent-session-events.ts +1 -0
  204. package/src/session/agent-session-types.ts +40 -1
  205. package/src/session/agent-session.ts +302 -175
  206. package/src/session/claude-session-store.ts +426 -0
  207. package/src/session/codex-session-store.ts +673 -0
  208. package/src/session/credential-pin.ts +93 -0
  209. package/src/session/foreign-session-import.ts +52 -0
  210. package/src/session/foreign-session-jsonl.ts +29 -0
  211. package/src/session/foreign-session-store.ts +26 -0
  212. package/src/session/model-controls.ts +11 -3
  213. package/src/session/session-advisors.ts +140 -16
  214. package/src/session/session-entries.ts +21 -1
  215. package/src/session/session-handoff.ts +20 -3
  216. package/src/session/session-loader.ts +25 -9
  217. package/src/session/session-maintenance.ts +59 -11
  218. package/src/session/session-manager.ts +61 -0
  219. package/src/session/session-tools.ts +107 -5
  220. package/src/session/settings-stream-fn.ts +1 -0
  221. package/src/session/turn-recovery.ts +97 -51
  222. package/src/slash-commands/builtin-registry.ts +152 -3
  223. package/src/slash-commands/helpers/security.ts +451 -0
  224. package/src/system-prompt.ts +7 -2
  225. package/src/task/agents.ts +2 -0
  226. package/src/task/executor.ts +20 -4
  227. package/src/task/render.ts +20 -4
  228. package/src/task/structured-subagent.ts +6 -4
  229. package/src/thinking.ts +29 -10
  230. package/src/tools/acp-bridge.ts +52 -8
  231. package/src/tools/browser.ts +5 -0
  232. package/src/tools/builtin-names.ts +1 -0
  233. package/src/tools/checkpoint.ts +0 -13
  234. package/src/tools/grep.ts +64 -8
  235. package/src/tools/hub/launch.ts +10 -15
  236. package/src/tools/index.ts +37 -5
  237. package/src/tools/path-utils.ts +91 -0
  238. package/src/tools/read.ts +3 -0
  239. package/src/tools/security-scan.ts +287 -0
  240. package/src/tools/write.ts +9 -3
  241. package/src/tools/xdev.ts +39 -14
  242. package/src/utils/changelog.ts +144 -4
  243. package/src/utils/git.ts +61 -14
  244. package/src/utils/jj.ts +19 -13
  245. package/src/web/search/providers/codex.ts +34 -0
  246. package/src/web/search/types.ts +1 -1
@@ -1,4 +1,4 @@
1
- import type { Agent, AgentMessage, AgentTool, StreamFn, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
1
+ import type { Agent, AgentMessage, AgentTool, AgentToolContext, StreamFn, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
2
  import type { Context, Effort, ImageContent, Message, MessageAttribution, Model, OAuthAccountSummary, ServiceTierByFamily, SimpleStreamOptions, ToolChoice } from "@oh-my-pi/pi-ai";
3
3
  import type { postmortem } from "@oh-my-pi/pi-utils";
4
4
  import type { AdvisorConfig } from "../advisor/index.js";
@@ -6,6 +6,7 @@ import type { AsyncJob, AsyncJobDeliveryState, AsyncJobManager } from "../async/
6
6
  import type { ModelRegistry } from "../config/model-registry.js";
7
7
  import type { PromptTemplate } from "../config/prompt-templates.js";
8
8
  import type { Settings, SkillsSettings } from "../config/settings.js";
9
+ import type { CursorMcpResourceAdapter } from "../cursor.js";
9
10
  import type { RawSseDebugBuffer } from "../debug/raw-sse-buffer.js";
10
11
  import type { TtsrManager } from "../export/ttsr.js";
11
12
  import type { LoadedCustomCommand } from "../extensibility/custom-commands/index.js";
@@ -143,6 +144,8 @@ export interface AgentSessionConfig {
143
144
  sideStreamFn?: StreamFn;
144
145
  /** Stream wrapper for advisor requests. */
145
146
  advisorStreamFn?: StreamFn;
147
+ /** Advisor spend already recorded for the session being opened, restored on resume. */
148
+ initialAdvisorCosts?: ReadonlyMap<string, number>;
146
149
  /** Prefer websocket transport for OpenAI Codex requests when supported. */
147
150
  preferWebsockets?: boolean;
148
151
  /** Provider payload hook used by the active session request path. */
@@ -194,6 +197,38 @@ export interface AgentSessionConfig {
194
197
  providerPromptCacheKeySource?: "explicit" | "fork";
195
198
  /** Full advisor toolset built against an advisor-scoped tool session. */
196
199
  advisorTools?: AgentTool[];
200
+ /**
201
+ * Build a `grep` honoring a Cursor `pi_grep` frame's own context width and
202
+ * match cap, against the advisor-scoped tool session. Without it an advisor
203
+ * running on Cursor silently drops both fields.
204
+ */
205
+ advisorCreateGrepTool?(options: {
206
+ context?: number;
207
+ totalMatchLimit?: number;
208
+ }): AgentTool | undefined;
209
+ /**
210
+ * Build the `replace`-mode `edit` a Cursor `pi_edit` frame needs, against the
211
+ * advisor-scoped tool session. The advisor's ordinary instance follows the
212
+ * configured `edit.mode` and rejects the frame's `old_text`/`new_text` pairs.
213
+ */
214
+ advisorCreateEditTool?(): AgentTool | undefined;
215
+ /**
216
+ * The execute-time context the advisor's bridge tools resolve approval from.
217
+ *
218
+ * `ExtensionToolWrapper` reads `tools.approvalMode`, per-tool
219
+ * `tools.approval.<tool>` policies and `autoApprove` only from this context;
220
+ * with none it defaults to `yolo` with empty policies, so a bridge tool would
221
+ * run a native frame the user configured `ask` or `deny` for.
222
+ */
223
+ advisorGetToolContext?: () => AgentToolContext | undefined;
224
+ /**
225
+ * The live MCP connections the advisor's Cursor resource frames answer from.
226
+ *
227
+ * Advisors share the session's connections and may be granted tools from
228
+ * those same servers; without this their `list_mcp_resources` reports an
229
+ * empty catalog and every `read_mcp_resource` a `not_found`.
230
+ */
231
+ advisorMcpResources?: CursorMcpResourceAdapter;
197
232
  /** Preloaded watchdog prompt content for the advisor. */
198
233
  advisorWatchdogPrompt?: string;
199
234
  /** Shared advisor instructions loaded from WATCHDOG.yml. */
@@ -12,12 +12,12 @@
12
12
  *
13
13
  * Modes use this class and add their own I/O layer on top.
14
14
  */
15
- import type { InMemorySnapshotStore } from "@oh-my-pi/hashline";
15
+ import type { Clipboard, InMemorySnapshotStore } from "@oh-my-pi/hashline";
16
16
  import { type Agent, type AgentMessage, type AgentState, type AgentTool, type AgentToolContext, type AgentToolResult, type ThinkingLevel, type ToolChoiceDirective } from "@oh-my-pi/pi-agent-core";
17
17
  import { type CompactionResult, type ShakeConfig } from "@oh-my-pi/pi-agent-core/compaction";
18
18
  import type { AssistantMessage, ImageContent, Message, Model, ProviderSessionState, ResetCreditAccountStatus, ResetCreditRedeemOutcome, ResetCreditTarget, ServiceTier, ServiceTierByFamily, ServiceTierFamily, SimpleStreamOptions, TextContent, UsageReport } from "@oh-my-pi/pi-ai";
19
19
  import { type Effort } from "@oh-my-pi/pi-ai";
20
- import type { AdvisorConfig, AdvisorRuntimeStatus } from "../advisor/index.js";
20
+ import { type AdvisorConfig, type AdvisorRuntimeStatus } from "../advisor/index.js";
21
21
  import { AsyncJobManager } from "../async/index.js";
22
22
  import type { ModelRegistry } from "../config/model-registry.js";
23
23
  import { type ResolvedModelRoleValue } from "../config/model-resolver.js";
@@ -75,6 +75,8 @@ export declare class AgentSession {
75
75
  }>;
76
76
  readonly yieldQueue: YieldQueue;
77
77
  fileSnapshotStore?: InMemorySnapshotStore;
78
+ /** Per-session `CUT`/`PASTE` clipboard register shared across edit calls. */
79
+ editClipboard?: Clipboard;
78
80
  readonly configWarnings: string[];
79
81
  readonly rawSseDebugBuffer: RawSseDebugBuffer;
80
82
  /**
@@ -0,0 +1,13 @@
1
+ import type { ForeignSessionInfo, ForeignSessionStore } from "./foreign-session-store.js";
2
+ import { SessionManager } from "./session-manager.js";
3
+ /** Imports Claude Code JSONL sessions into non-persistent OMP session managers. */
4
+ export declare class ClaudeSessionStore implements ForeignSessionStore {
5
+ #private;
6
+ readonly source = "claude";
7
+ /** Creates a store rooted at Claude's data directory, or at a fixture root when supplied. */
8
+ constructor(root?: string);
9
+ /** Lists indexed Claude sessions without reading transcript bodies. */
10
+ list(): Promise<ForeignSessionInfo[]>;
11
+ /** Loads and converts a Claude transcript while preserving its source tree and timestamps. */
12
+ load(info: ForeignSessionInfo): Promise<SessionManager>;
13
+ }
@@ -0,0 +1,14 @@
1
+ import type { ForeignSessionInfo, ForeignSessionStore } from "./foreign-session-store.js";
2
+ import { SessionManager } from "./session-manager.js";
3
+ /** Imports locally stored OpenAI Codex sessions into OMP's in-memory session format. */
4
+ export declare class CodexSessionStore implements ForeignSessionStore {
5
+ #private;
6
+ /** Foreign-session source discriminator. */
7
+ readonly source = "codex";
8
+ /** Uses the supplied Codex data root, or ~/.codex by default. */
9
+ constructor(rootDirectory?: string);
10
+ /** Lists Codex sessions from its state index without reading transcript bodies. */
11
+ list(): Promise<ForeignSessionInfo[]>;
12
+ /** Converts one Codex rollout into a non-persistent OMP session. */
13
+ load(info: ForeignSessionInfo): Promise<SessionManager>;
14
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Session-file persistence of the OAuth account that served a session.
3
+ *
4
+ * Provider prompt caches are account-scoped (Anthropic bills a full cache
5
+ * re-write after an account flip), and the auth store's session-sticky routing
6
+ * is process-local when a remote auth broker is configured — the broker
7
+ * store's KV cache is in-memory, so sticky rows die with the CLI process.
8
+ * Resuming a session in a fresh process then re-ranks accounts by usage
9
+ * headroom, which is biased *away* from the account that just served the
10
+ * session (it has the highest recent burn), cold-missing the entire prefix.
11
+ *
12
+ * These helpers close the loop through the session file itself: after each
13
+ * assistant turn the serving account is recorded as a `credential_pin` entry,
14
+ * and on session adoption the pin is matched against the stored accounts and
15
+ * seeded back into the auth store with the session's effective last-use
16
+ * timestamp, so the provider's warm-window semantics still decide whether to
17
+ * stick or re-rank.
18
+ */
19
+ import type { AuthStorage } from "./auth-storage.js";
20
+ import type { SessionManager } from "./session-manager.js";
21
+ /** Account fields shared by `OAuthAccountIdentity` and `OAuthAccountSummary`. */
22
+ interface CredentialPinIdentity {
23
+ accountId?: string;
24
+ email?: string;
25
+ projectId?: string;
26
+ orgId?: string;
27
+ }
28
+ /**
29
+ * Stable identifier for a provider account within its billing scope. The
30
+ * digest covers the full scope tuple — the same account in two orgs (Anthropic
31
+ * multi-subscription) or projects (Gemini) is two distinct cache domains and
32
+ * must produce two distinct pins. The digest input is the persisted contract
33
+ * for `CredentialPinEntry.hash` — changing it orphans every recorded pin.
34
+ *
35
+ * Hashing avoids embedding raw emails/uuids in session files, but an unsalted
36
+ * digest of a guessable email is still linkable — treat exported sessions
37
+ * accordingly.
38
+ *
39
+ * Returns `undefined` when the identity carries no account key at all.
40
+ */
41
+ export declare function credentialPinHash(provider: string, identity: CredentialPinIdentity): string | undefined;
42
+ /**
43
+ * Record the account that served the latest assistant turn for `provider`.
44
+ * Appends a `credential_pin` entry only when the account differs from the
45
+ * branch's latest pin, so steady-state sessions add a single entry; the
46
+ * effective last-use time is derived from later assistant turns on read
47
+ * (see `SessionManager.getCredentialPins`).
48
+ */
49
+ export declare function recordCredentialPin(authStorage: AuthStorage, sessionManager: SessionManager, sessionId: string, provider: string): void;
50
+ /**
51
+ * Re-pin the accounts recorded in the session file onto the auth store's
52
+ * session stickiness. No-op per provider when the account is gone (logged out)
53
+ * or when a live sticky already exists (same-process branch/session switches
54
+ * must not clobber fresher routing). Seeds with the session's effective
55
+ * last-use time so stale resumes still fall through to usage ranking.
56
+ */
57
+ export declare function seedCredentialPins(authStorage: AuthStorage, sessionManager: SessionManager, sessionId: string): void;
58
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { ForeignSessionInfo, ForeignSessionSource, ForeignSessionStore } from "./foreign-session-store.js";
2
+ import type { SessionInfo } from "./session-listing.js";
3
+ import type { SessionManager } from "./session-manager.js";
4
+ /** Construct the importer for a supported foreign session source. */
5
+ export declare function createForeignSessionStore(source: ForeignSessionSource): ForeignSessionStore;
6
+ /** Display name for a supported foreign session source. */
7
+ export declare function foreignSessionSourceName(source: ForeignSessionSource): string;
8
+ /** Convert lightweight foreign metadata for the existing session picker. */
9
+ export declare function foreignSessionInfoToSessionInfo(info: ForeignSessionInfo): SessionInfo;
10
+ /** Import and persist one foreign session under a fresh OMP session identity. */
11
+ export declare function persistForeignSession(store: ForeignSessionStore, info: ForeignSessionInfo, options?: {
12
+ fallbackCwd?: string;
13
+ sessionDir?: string;
14
+ suppressBreadcrumb?: boolean;
15
+ }): Promise<SessionManager>;
@@ -0,0 +1,9 @@
1
+ /** One readable object record from a foreign JSONL transcript. */
2
+ export interface ForeignJsonRecord {
3
+ readonly value: Record<string, unknown>;
4
+ readonly line: number;
5
+ }
6
+ /** Stream valid object records while tolerating malformed or truncated lines. */
7
+ export declare function readForeignJsonRecords(filePath: string): AsyncGenerator<ForeignJsonRecord>;
8
+ /** Read every valid object record from a foreign JSONL transcript. */
9
+ export declare function collectForeignJsonRecords(filePath: string): Promise<ForeignJsonRecord[]>;
@@ -0,0 +1,23 @@
1
+ import type { SessionManager } from "./session-manager.js";
2
+ /** External coding-agent session source supported by OMP imports. */
3
+ export type ForeignSessionSource = "claude" | "codex";
4
+ /** Lightweight source metadata used to choose a foreign session before loading its transcript. */
5
+ export interface ForeignSessionInfo {
6
+ readonly source: ForeignSessionSource;
7
+ readonly id: string;
8
+ readonly path: string;
9
+ readonly cwd: string;
10
+ readonly title?: string;
11
+ readonly created: Date;
12
+ readonly modified: Date;
13
+ readonly messageCount?: number;
14
+ readonly firstMessage?: string;
15
+ }
16
+ /** Lists and converts sessions owned by another coding agent. */
17
+ export interface ForeignSessionStore {
18
+ readonly source: ForeignSessionSource;
19
+ /** Lists source sessions without parsing complete transcripts. */
20
+ list(): Promise<ForeignSessionInfo[]>;
21
+ /** Converts one source session into a non-persistent OMP session. */
22
+ load(session: ForeignSessionInfo): Promise<SessionManager>;
23
+ }
@@ -1,8 +1,9 @@
1
- import { Agent, type AgentMessage, type AgentTool, type StreamFn } from "@oh-my-pi/pi-agent-core";
1
+ import { Agent, type AgentMessage, type AgentTool, type AgentToolContext, type StreamFn } from "@oh-my-pi/pi-agent-core";
2
2
  import type { CodexCompactionContext, Context, Message, Model, ProviderSessionState, ServiceTier, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
3
3
  import { type AdvisorConfig, type AdvisorRuntimeStatus } from "../advisor/index.js";
4
4
  import type { ModelRegistry } from "../config/model-registry.js";
5
5
  import type { Settings } from "../config/settings.js";
6
+ import { type CursorMcpResourceAdapter } from "../cursor.js";
6
7
  import type { PlanModeState } from "../plan-mode/state.js";
7
8
  import type { SecretObfuscator } from "../secrets/obfuscator.js";
8
9
  import type { AgentSessionEvent } from "./agent-session-events.js";
@@ -51,12 +52,47 @@ export interface PerAdvisorStat {
51
52
  export interface SessionAdvisorsOptions {
52
53
  enabled: boolean;
53
54
  tools?: AgentTool[];
55
+ /**
56
+ * Build a `grep` honoring a Cursor `pi_grep` frame's own context width and
57
+ * match cap. The advisor's tools are fixed instances carrying session
58
+ * defaults, so without this an advisor running against Cursor silently
59
+ * drops both fields — the same gap the primary bridge closes.
60
+ */
61
+ createGrepTool?(options: {
62
+ context?: number;
63
+ totalMatchLimit?: number;
64
+ }): AgentTool | undefined;
65
+ /**
66
+ * Build the `replace`-mode `edit` a Cursor `pi_edit` frame needs. The
67
+ * advisor's own instance follows the configured `edit.mode` (`hashline` by
68
+ * default), whose schema the frame's `old_text`/`new_text` pairs do not
69
+ * match, so without this every native advisor edit fails validation.
70
+ */
71
+ createEditTool?(): AgentTool | undefined;
72
+ /**
73
+ * The execute-time context the bridge's tools resolve approval from.
74
+ *
75
+ * `ExtensionToolWrapper` reads the approval mode, per-tool policies and
76
+ * `autoApprove` only from here; with none it falls back to `yolo` and empty
77
+ * policies, so a native frame would run past a configured `ask` or `deny`.
78
+ */
79
+ getToolContext?: () => AgentToolContext | undefined;
80
+ /**
81
+ * The live MCP connections Cursor's resource frames answer from.
82
+ *
83
+ * Advisors share the session's connections and may hold tools from those
84
+ * same servers, so without this their frames report that every server
85
+ * advertises nothing.
86
+ */
87
+ mcpResources?: CursorMcpResourceAdapter;
54
88
  watchdogPrompt?: string;
55
89
  sharedInstructions?: string;
56
90
  contextPrompt?: string;
57
91
  configs?: AdvisorConfig[];
58
92
  streamFn?: StreamFn;
59
93
  transformProviderContext?: (context: Context, model: Model) => Context | Promise<Context>;
94
+ /** Advisor spend already persisted for this session, restored on resume. */
95
+ initialCosts?: ReadonlyMap<string, number>;
60
96
  }
61
97
  /** Options accepted when an advisor injects a primary-session message. */
62
98
  export interface AdvisorMessageDeliveryOptions {
@@ -93,7 +129,7 @@ export interface SessionAdvisorsHost {
93
129
  hasPendingNextTurnMessages(): boolean;
94
130
  convertToLlmForSideRequest(messages: AgentMessage[]): Message[];
95
131
  effectiveServiceTier(model: Model): ServiceTier | undefined;
96
- resolveContextPromotionTarget(currentModel: Model, contextWindow: number): Promise<Model | undefined>;
132
+ resolveContextPromotionTarget(currentModel: Model, contextWindow: number, signal: AbortSignal): Promise<Model | undefined>;
97
133
  resolveCompactionModelCandidates(preferredModel: Model | null | undefined, availableModels: Model[]): Model[];
98
134
  resolveRetryFallbackRole(currentSelector: string, currentModel?: Model | null): string | undefined;
99
135
  findRetryFallbackCandidates(role: string, currentSelector: string, currentModel?: Model | null): RetryFallbackSelector[];
@@ -118,14 +154,23 @@ export declare class SessionAdvisors {
118
154
  buildRuntime(seedToCurrent?: boolean): boolean;
119
155
  /** Stops every advisor runtime and starts recorder shutdown. */
120
156
  stopRuntime(): void;
157
+ /**
158
+ * Pause advisor work while old-session recorder feeds remain attached, then
159
+ * detach only after any active prompt has settled.
160
+ */
161
+ drainAndDetachRecorders(): Promise<void>;
121
162
  /** Detaches and drains recorder feeds before transcript artifacts are removed. */
122
163
  detachAndCloseRecorders(): Promise<void>;
164
+ /** Reattach recorder feeds and resume work after a rolled-back or preserving transition. */
165
+ reattachRecorderFeeds(): void;
123
166
  /** Re-primes advisor transcript views across a conversation boundary. */
124
167
  resetSessionState(options?: {
125
168
  preserveCost?: boolean;
126
169
  }): void;
127
170
  /** Drop the recorded spend once a conversation boundary has committed. */
128
171
  clearCost(): void;
172
+ /** Replace the ledger with the spend recorded for the session becoming active. */
173
+ restoreCost(costs: ReadonlyMap<string, number>): void;
129
174
  /**
130
175
  * Rebind every live advisor to the active primary conversation's provider
131
176
  * identity (session id, prompt-cache key, credential + metadata resolvers,
@@ -134,6 +134,7 @@ export interface TitleChangeEntry extends SessionEntryBase {
134
134
  declare module "@oh-my-pi/pi-agent-core/compaction/entries" {
135
135
  interface CustomCompactionSessionEntries {
136
136
  titleChange: TitleChangeEntry;
137
+ credentialPin: CredentialPinEntry;
137
138
  }
138
139
  }
139
140
  /** TTSR injection entry - tracks which time-traveling rules have been injected this session. */
@@ -142,6 +143,23 @@ export interface TtsrInjectionEntry extends SessionEntryBase {
142
143
  /** Names of rules that were injected */
143
144
  injectedRules: string[];
144
145
  }
146
+ /**
147
+ * Records which OAuth account served this session's requests for a provider.
148
+ *
149
+ * Provider prompt caches (Anthropic in particular) are account-scoped, and the
150
+ * auth store's session-sticky routing is process-local under a remote auth
151
+ * broker, so resume must re-pin the same account to reuse the warm cache
152
+ * prefix. Stores a sha-256 of the account + billing-scope tuple instead of
153
+ * the raw email/uuid/org; note an unsalted digest of a guessable email is
154
+ * still linkable, so exported sessions are pseudonymous, not anonymous.
155
+ */
156
+ export interface CredentialPinEntry extends SessionEntryBase {
157
+ type: "credential_pin";
158
+ /** Provider id the pin applies to (e.g. "anthropic"). */
159
+ provider: string;
160
+ /** `credentialPinHash()` of the serving account's identity + scope tuple. */
161
+ hash: string;
162
+ }
145
163
  /** Session init entry - captures initial context for subagent sessions (debugging/replay). */
146
164
  export interface SessionInitEntry extends SessionEntryBase {
147
165
  type: "session_init";
@@ -192,7 +210,7 @@ export interface CustomMessageEntry<T = unknown> extends SessionEntryBase {
192
210
  attribution?: MessageAttribution;
193
211
  }
194
212
  /** Session entry - has id/parentId for tree structure (returned by "read" methods in SessionManager) */
195
- export type SessionEntry = SessionMessageEntry | ThinkingLevelChangeEntry | ModelChangeEntry | ServiceTierChangeEntry | CompactionEntry | BranchSummaryEntry | CustomEntry | CustomMessageEntry | LabelEntry | TitleChangeEntry | TtsrInjectionEntry | SessionInitEntry | ModeChangeEntry;
213
+ export type SessionEntry = SessionMessageEntry | ThinkingLevelChangeEntry | ModelChangeEntry | ServiceTierChangeEntry | CompactionEntry | BranchSummaryEntry | CustomEntry | CustomMessageEntry | LabelEntry | TitleChangeEntry | TtsrInjectionEntry | SessionInitEntry | ModeChangeEntry | CredentialPinEntry;
196
214
  /** Raw logical file entry after loaders strip any fixed-width title slot. */
197
215
  export type FileEntry = SessionHeader | SessionEntry;
198
216
  /** Physical JSONL entry before slot-aware loaders fold the title slot. */
@@ -44,7 +44,10 @@ export interface SessionHandoffHost {
44
44
  clearPendingNextTurnMessages(): void;
45
45
  resetTodoCycle(): void;
46
46
  buildDisplaySessionContext(): SessionContext;
47
- resetAdvisorRuntimes(): void;
47
+ resetAdvisorSessionState(): void;
48
+ drainAndDetachAdvisorRecorders(): Promise<void>;
49
+ reattachAdvisorRecorderFeeds(): void;
50
+ clearAdvisorCost(): void;
48
51
  syncTodoPhasesFromBranch(): void;
49
52
  }
50
53
  /** Generates handoff documents and owns the handoff session transition. */
@@ -8,6 +8,8 @@ export declare function parseSessionContent(content: string): {
8
8
  entries: FileEntry[];
9
9
  titleSlot: SessionTitleUpdate | undefined;
10
10
  };
11
+ /** Parse session JSONL and visit each entry without retaining prior entries. */
12
+ export declare function visitEntriesFromFileStream(filePath: string, visit: (entry: FileEntry) => void): Promise<SessionTitleUpdate | undefined>;
11
13
  /** Exported for testing — the ≥8MiB streaming path (works on any file size). */
12
14
  export declare function loadEntriesFromFileStream(filePath: string): Promise<{
13
15
  entries: FileEntry[];
@@ -214,7 +214,7 @@ export declare class SessionMaintenance {
214
214
  * is true.
215
215
  */
216
216
  checkCompaction(assistantMessage: AssistantMessage, skipAbortedCheck?: boolean, allowDefer?: boolean, autoContinue?: boolean): Promise<CompactionCheckResult>;
217
- resolveContextPromotionTarget(currentModel: Model, contextWindow: number): Promise<Model | undefined>;
217
+ resolveContextPromotionTarget(currentModel: Model, contextWindow: number, signal?: AbortSignal): Promise<Model | undefined>;
218
218
  resolveCompactionModelCandidates(preferredModel: Model | null | undefined, availableModels: Model[], filter?: (model: Model) => boolean): Model[];
219
219
  /**
220
220
  * Internal: Run auto-compaction with events.
@@ -92,6 +92,11 @@ export declare class SessionManager {
92
92
  * session/new must create a discoverable file immediately).
93
93
  */
94
94
  ensureOnDisk(): Promise<void>;
95
+ /** Persist this session's transcript as a newly identified OMP session. */
96
+ persistCopy(options?: {
97
+ sessionDir?: string;
98
+ suppressBreadcrumb?: boolean;
99
+ }, storage?: SessionStorage): Promise<SessionManager>;
95
100
  /**
96
101
  * Stage a synchronous group of entry appends and publish the resulting full
97
102
  * journal with one atomic replace. A failed publish removes only the staged
@@ -236,6 +241,22 @@ export declare class SessionManager {
236
241
  appendTtsrInjection(ruleNames: string[]): string;
237
242
  /** All unique TTSR rule names injected on the current branch (root → leaf). */
238
243
  getInjectedTtsrRules(): string[];
244
+ /** Append a credential pin recording which OAuth account served `provider`. */
245
+ appendCredentialPin(provider: string, hash: string): string;
246
+ /**
247
+ * Latest credential pin per provider on the current branch (root → leaf),
248
+ * with the effective last-use time of the pinned account.
249
+ *
250
+ * Pins are appended only when the serving account *changes*, so a long
251
+ * session on one account carries a single old pin entry. Any assistant turn
252
+ * for the same provider after that pin was necessarily served by the pinned
253
+ * account, so its timestamp advances `lastUsedAt` — a resume seconds after
254
+ * the last turn seeds a warm sticky instead of a stale one.
255
+ */
256
+ getCredentialPins(): Map<string, {
257
+ hash: string;
258
+ lastUsedAt: number;
259
+ }>;
239
260
  getLeafId(): string | null;
240
261
  getLeafEntry(): SessionEntry | undefined;
241
262
  /**
@@ -86,6 +86,17 @@ export declare function collectMountedMCPToolRoutes(tools: Iterable<MountedMCPTo
86
86
  * rendered by the static MCP guidance prompt.
87
87
  */
88
88
  export declare function projectMountedMCPXdevGuidance(routes: Iterable<MountedMCPToolRoute>): MCPXdevGuidanceProjection;
89
+ /**
90
+ * Structured payload persisted on each {@link XDEV_MOUNT_NOTICE_MESSAGE_TYPE}
91
+ * custom message. Lets a resumed session reconstruct which dynamic devices the
92
+ * model has already been told about, so reconnecting hosts do not re-announce
93
+ * (and re-splice a redundant developer message that busts the provider
94
+ * prompt-cache prefix).
95
+ */
96
+ interface XdevMountNoticeDetails {
97
+ added: string[];
98
+ removed: string[];
99
+ }
89
100
  /** Owns tool registration, presentation, prompt rebuilding, skills, and permissions. */
90
101
  export declare class SessionTools {
91
102
  #private;
@@ -134,8 +145,21 @@ export declare class SessionTools {
134
145
  getSelectedMCPToolNames(): string[];
135
146
  /** Applies an enabled tool set and reconciles its `xd://` partition. */
136
147
  applyActiveToolsByName(toolNames: string[]): Promise<void>;
148
+ /**
149
+ * Forget the announced-mount baseline for a replaced transcript. Called when
150
+ * session history is swapped wholesale (`/new`, `switchSession`, `branch`): the
151
+ * previous transcript's persisted notices no longer apply, so the next notice
152
+ * re-seeds from the new history and a device reconnecting into it announces
153
+ * again.
154
+ *
155
+ * The pending delta is deliberately preserved: it holds mounts that are still
156
+ * live but not yet delivered to the model, and `branch()` does not rebuild the
157
+ * base system prompt, so dropping it would leave the branched transcript
158
+ * unaware of a still-mounted device that no later refresh would re-queue.
159
+ */
160
+ resetAnnouncedMounts(): void;
137
161
  /** Consumes the hidden notice for unannounced `xd://` mount changes. */
138
- takePendingXdevMountNotice(): CustomMessage | undefined;
162
+ takePendingXdevMountNotice(): CustomMessage<XdevMountNoticeDetails> | undefined;
139
163
  /** Rediscovers reloadable skills and refreshes prompt metadata. */
140
164
  refreshSkills(): Promise<void>;
141
165
  /** Selects enabled tools, ignoring names absent from the registry. */
@@ -42,6 +42,7 @@ export interface TurnRecoveryHost {
42
42
  }): void;
43
43
  waitForSessionMessagePersistence(message: AssistantMessage): Promise<void>;
44
44
  appendSessionMessage(message: AssistantMessage): void;
45
+ persistedAssistantEntryId(message: AssistantMessage): string | undefined;
45
46
  sessionMessageAlreadyPersisted(message: AssistantMessage): boolean;
46
47
  setModelWithProviderSessionReset(model: Model): Promise<void>;
47
48
  resetCurrentResponsesProviderSession(reason: string): void;
@@ -100,6 +101,12 @@ export declare class TurnRecovery {
100
101
  hardErrorFallback?: boolean;
101
102
  preserveFailedTurn?: boolean;
102
103
  }): Promise<boolean>;
104
+ /**
105
+ * Records a usage-limit failure before replay eligibility decides whether the
106
+ * failed turn may be discarded. Returns whether credential recovery switched
107
+ * the active account.
108
+ */
109
+ recordUsageLimitOutcome(message: AssistantMessage): Promise<boolean>;
103
110
  /** Prompts after transient overlap with a prior agent run. */
104
111
  promptAgentWithIdleRetry(messages: AgentMessage[], options?: {
105
112
  toolChoice?: ToolChoice;
@@ -176,8 +183,8 @@ export declare class TurnRecovery {
176
183
  * transient overload/5xx or a hard "router/model not found / unsupported" —
177
184
  * is worth retrying on the base id. Skips failures the base model shares:
178
185
  * context overflow (compaction's job), usage limits and auth errors (same
179
- * account/key), and turns that already emitted a tool call (replaying would
180
- * duplicate work). Requires the base model to exist in the registry.
186
+ * account/key), and turns that already emitted any replay-unsafe output.
187
+ * Requires the base model to exist in the registry.
181
188
  */
182
189
  isFireworksFastFallbackEligible(message: AssistantMessage): boolean;
183
190
  /**
@@ -188,8 +195,7 @@ export declare class TurnRecovery {
188
195
  * model switch cannot fix or must not replay: cancellations (abort-flavored
189
196
  * errors are not model faults), context overflow (compaction's job),
190
197
  * classifier refusals (chain consult is handled on the retryable path with
191
- * `pinFallback`), and turns that already emitted a tool call (replaying
192
- * could duplicate work).
198
+ * `pinFallback`), and turns that already emitted replay-unsafe output.
193
199
  */
194
200
  isHardErrorFallbackEligible(message: AssistantMessage): boolean;
195
201
  /**
@@ -0,0 +1,2 @@
1
+ import type { ParsedSlashCommand, SlashCommandResult, SlashCommandRuntime } from "../types.js";
2
+ export declare function handleSecurityCommand(command: ParsedSlashCommand, runtime: SlashCommandRuntime): Promise<SlashCommandResult>;
@@ -119,6 +119,8 @@ export interface BuildSystemPromptOptions {
119
119
  workspaceTree?: WorkspaceTree | Promise<WorkspaceTree>;
120
120
  /** Whether the local memory://root summary is active. */
121
121
  memoryRootEnabled?: boolean;
122
+ /** Whether the read-only security:// resource namespace is active. */
123
+ securityEnabled?: boolean;
122
124
  /** Active model identifier (e.g. "anthropic/claude-opus-4") used by prompt policy and optionally surfaced. */
123
125
  model?: string;
124
126
  /** Whether to surface `model` in the workstation block. Model-specific prompt policy still uses it. Default: true. */
@@ -131,10 +133,11 @@ export interface BuildSystemPromptOptions {
131
133
  renderMermaid?: boolean;
132
134
  /** Pre-resolved nested active repo context. Undefined resolves from cwd. */
133
135
  activeRepoContext?: ActiveRepoContext | null;
134
- /** Tools mounted under `xd://`; renders the protocol section when non-empty. */
136
+ /** Tools mounted under `xd://`; renders the protocol section when non-empty. `dynamic` marks external devices whose summary is third-party metadata. */
135
137
  xdevTools?: Array<{
136
138
  name: string;
137
139
  summary: string;
140
+ dynamic?: boolean;
138
141
  }>;
139
142
  /** Full docs + JSON schema for every `xd://`-mounted tool, inlined into the protocol section so no discovery `read` is needed. */
140
143
  xdevDocs?: string;
@@ -18,6 +18,7 @@ import type { LocalProtocolOptions } from "../internal-urls/index.js";
18
18
  import type { MCPManager } from "../mcp/manager.js";
19
19
  import type { MnemopiSessionState } from "../mnemopi/state.js";
20
20
  import { type AgentReviver } from "../registry/agent-lifecycle.js";
21
+ import { type CreateAgentSessionOptions } from "../sdk.js";
21
22
  import type { AgentSession } from "../session/agent-session.js";
22
23
  import type { ArtifactManager } from "../session/artifacts.js";
23
24
  import type { AuthStorage } from "../session/auth-storage.js";
@@ -34,10 +35,19 @@ export type { YieldItem } from "./types.js";
34
35
  * agent is driven to one forced final `yield` so partial findings come back
35
36
  * as a real report; only if it still refuses to yield within
36
37
  * {@link BUDGET_STOP_GRACE_REQUESTS} more requests is the run hard-aborted.
37
- * The `default` key applies to agents without an explicit entry and can be
38
- * overridden via the `task.softRequestBudget` setting (0 disables the guard).
38
+ * Entries are ceilings, not fixed values: the `default` key applies to agents
39
+ * without an explicit entry, and the `task.softRequestBudget` setting can only
40
+ * lower an agent's budget, never raise it above its bundled entry (0 disables
41
+ * the guard entirely).
39
42
  */
40
43
  export declare const SOFT_REQUEST_BUDGET: Record<string, number>;
44
+ /**
45
+ * Resolves the effective soft request budget for an agent. The configured
46
+ * `task.softRequestBudget` and the agent's bundled entry are both upper
47
+ * bounds, so the tighter one wins; a configured budget of 0 disables the
48
+ * guard regardless of the bundled entry.
49
+ */
50
+ export declare function resolveSoftRequestBudget(agentName: string, configuredBudget: number): number;
41
51
  /** Extra requests allowed after a budget stop for the forced yield to land before the run is hard-aborted. */
42
52
  export declare const BUDGET_STOP_GRACE_REQUESTS = 5;
43
53
  /** Steering notice injected when a subagent crosses its soft request budget. */
@@ -47,6 +57,8 @@ export interface ExecutorOptions {
47
57
  cwd: string;
48
58
  /** Additional workspace directories to seed on the subagent session (multi-root). */
49
59
  additionalDirectories?: string[];
60
+ /** Exact provider credential resolver inherited from the parent session. */
61
+ getApiKey?: CreateAgentSessionOptions["getApiKey"];
50
62
  worktree?: string;
51
63
  agent: AgentDefinition;
52
64
  task: string;
@@ -11,6 +11,13 @@ interface TaskRenderContext {
11
11
  * commit-eligible rows do not repaint after entering native scrollback.
12
12
  */
13
13
  frozen?: boolean;
14
+ /**
15
+ * Wall clock for time-derived rows (current-tool elapsed, retry countdown).
16
+ * The component freezes it once the block settles or any of its rows enter
17
+ * native scrollback, so identical-input rebuilds stay byte-identical with
18
+ * committed history. Absent: render with the live clock.
19
+ */
20
+ nowMs?: number;
14
21
  }
15
22
  type TaskRenderOptions = RenderResultOptions & {
16
23
  renderContext?: TaskRenderContext;
@@ -103,6 +103,12 @@ export declare function parseCliThinkingLevel(value: string | null | undefined):
103
103
  * above Low (falling back to the full supported set only when the model maxes
104
104
  * out below Low). Within that pool the request snaps to the highest level not
105
105
  * exceeding it, or the pool minimum when the request is below the pool.
106
+ * `ceiling` bounds the pool from above, so a policy ceiling survives the model
107
+ * clamp: a sparse ladder such as `["max"]` must not snap an `xhigh` request up
108
+ * to `max`. The Low floor is resolved against the model's own ladder *before*
109
+ * the ceiling applies — a ceiling that hides every tier at or above Low means
110
+ * there is nothing legal to pick (`undefined`), not a licence to fall through
111
+ * to a sub-Low tier the model happens to expose.
106
112
  *
107
113
  * Returns `undefined` for reasoning-capable models without a controllable
108
114
  * effort surface (`thinking.efforts` empty — e.g. devin-agent models, where
@@ -111,7 +117,7 @@ export declare function parseCliThinkingLevel(value: string | null | undefined):
111
117
  * forward a concrete effort that would then trip {@link requireSupportedEffort}
112
118
  * downstream.
113
119
  */
114
- export declare function clampAutoThinkingEffort(model: Model | undefined, effort: Effort): Effort | undefined;
120
+ export declare function clampAutoThinkingEffort(model: Model | undefined, effort: Effort, ceiling?: Effort): Effort | undefined;
115
121
  /** Coarse per-spawn effort selectors accepted by the task tool. */
116
122
  export declare const TASK_EFFORTS: readonly ["lo", "med", "hi"];
117
123
  /** Coarse task-spawn effort: the lowest, middle, or highest thinking level the target model supports. */
@@ -146,10 +152,16 @@ export declare function clampThinkingLevelToCeiling(model: Model | undefined, le
146
152
  export declare function modelSupportsEffortCeiling(model: Model, ceiling: Effort): boolean;
147
153
  /**
148
154
  * The provisional concrete level shown while `auto` is configured but before a
149
- * turn has been classified. Prefers the model's `defaultLevel`, otherwise High,
150
- * clamped into the auto range. Auto never provisions {@link Effort.Max} (the
151
- * classifier ceiling is XHigh; only an explicit user request reaches Max), so a
152
- * `defaultLevel` of `max` is capped at XHigh before clamping. Returns
153
- * `undefined` for non-reasoning models.
155
+ * turn has been classified, and the fallback when classification fails. Prefers
156
+ * the model's `defaultLevel`, otherwise High, clamped into the auto range.
157
+ *
158
+ * Deliberately stays below {@link Effort.Max}: the placeholder must not bill the
159
+ * top tier for a turn nobody classified, so XHigh is passed as a hard ceiling
160
+ * rather than only capping the preferred level — otherwise a sparse `["max"]`
161
+ * ladder would snap straight back up. A model whose ladder offers nothing at or
162
+ * below XHigh therefore has no provisional level, and `auto` leaves the current
163
+ * one in place. Classification itself may still resolve Max on models that
164
+ * expose the tier when the user opts in. Returns `undefined` for non-reasoning
165
+ * models.
154
166
  */
155
167
  export declare function resolveProvisionalAutoLevel(model: Model | undefined): Effort | undefined;