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

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 (130) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/{CHANGELOG-x9zt79k8.md → CHANGELOG-vt8ene9g.md} +58 -0
  3. package/dist/cli.js +4309 -7287
  4. package/dist/template-dys3vk5b.js +1671 -0
  5. package/dist/template-f8wx9vfn.css +1355 -0
  6. package/dist/template-qat058wr.html +55 -0
  7. package/dist/tool-views.generated-jdfmzwmn.js +35 -0
  8. package/dist/types/advisor/advise-tool.d.ts +0 -7
  9. package/dist/types/advisor/runtime.d.ts +0 -9
  10. package/dist/types/async/job-manager.d.ts +11 -0
  11. package/dist/types/cleanse/agent.d.ts +19 -0
  12. package/dist/types/cleanse/balance.d.ts +7 -0
  13. package/dist/types/cleanse/checkers.d.ts +13 -0
  14. package/dist/types/cleanse/index.d.ts +16 -0
  15. package/dist/types/cleanse/loop.d.ts +16 -0
  16. package/dist/types/cleanse/parsers.d.ts +13 -0
  17. package/dist/types/cleanse/progress.d.ts +14 -0
  18. package/dist/types/cleanse/types.d.ts +64 -0
  19. package/dist/types/commands/cleanse.d.ts +23 -0
  20. package/dist/types/config/settings-schema.d.ts +16 -1
  21. package/dist/types/cursor.d.ts +2 -1
  22. package/dist/types/export/html/index.d.ts +2 -0
  23. package/dist/types/extensibility/extensions/runner.d.ts +4 -0
  24. package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +27 -1
  25. package/dist/types/extensibility/shared-events.d.ts +18 -1
  26. package/dist/types/modes/components/custom-editor.d.ts +5 -0
  27. package/dist/types/modes/interactive-mode.d.ts +4 -3
  28. package/dist/types/session/agent-session-types.d.ts +5 -5
  29. package/dist/types/session/agent-session.d.ts +26 -1
  30. package/dist/types/session/async-job-delivery.d.ts +8 -0
  31. package/dist/types/session/model-controls.d.ts +4 -4
  32. package/dist/types/session/session-tools.d.ts +44 -6
  33. package/dist/types/session/streaming-output.d.ts +7 -2
  34. package/dist/types/session/turn-recovery.d.ts +1 -1
  35. package/dist/types/task/isolation-ownership.d.ts +34 -0
  36. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +1 -2
  37. package/dist/types/tools/browser/tab-worker.d.ts +1 -4
  38. package/dist/types/tools/index.d.ts +8 -3
  39. package/dist/types/tools/output-meta.d.ts +5 -0
  40. package/dist/types/tools/read.d.ts +9 -1
  41. package/dist/types/tools/xdev.d.ts +53 -67
  42. package/dist/types/tui/output-block.d.ts +5 -5
  43. package/dist/types/utils/cpuprofile.d.ts +51 -0
  44. package/dist/types/utils/inspect-image-mode.d.ts +29 -0
  45. package/dist/types/utils/profile-tree.d.ts +47 -0
  46. package/dist/types/utils/sample-profile.d.ts +67 -0
  47. package/package.json +16 -12
  48. package/scripts/bundle-dist.ts +3 -1
  49. package/src/advisor/advise-tool.ts +0 -11
  50. package/src/advisor/runtime.ts +0 -12
  51. package/src/async/job-manager.ts +30 -7
  52. package/src/cleanse/agent.ts +226 -0
  53. package/src/cleanse/balance.ts +79 -0
  54. package/src/cleanse/checkers.ts +996 -0
  55. package/src/cleanse/index.ts +190 -0
  56. package/src/cleanse/loop.ts +51 -0
  57. package/src/cleanse/parsers.ts +726 -0
  58. package/src/cleanse/progress.ts +50 -0
  59. package/src/cleanse/prompts/assignment.md +47 -0
  60. package/src/cleanse/types.ts +72 -0
  61. package/src/cli/update-cli.ts +3 -0
  62. package/src/cli/usage-cli.ts +29 -4
  63. package/src/cli/worktree-cli.ts +28 -11
  64. package/src/cli-commands.ts +1 -0
  65. package/src/cli.ts +2 -1
  66. package/src/commands/cleanse.ts +45 -0
  67. package/src/config/settings-schema.ts +15 -1
  68. package/src/config/settings.ts +35 -0
  69. package/src/cursor.ts +4 -3
  70. package/src/discovery/builtin-rules/index.ts +2 -0
  71. package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
  72. package/src/discovery/claude-plugins.ts +144 -34
  73. package/src/export/html/index.ts +17 -10
  74. package/src/extensibility/extensions/runner.ts +26 -0
  75. package/src/extensibility/extensions/wrapper.ts +74 -42
  76. package/src/extensibility/hooks/tool-wrapper.ts +11 -4
  77. package/src/extensibility/legacy-pi-ai-shim.ts +46 -1
  78. package/src/extensibility/shared-events.ts +18 -1
  79. package/src/launch/broker.ts +14 -4
  80. package/src/modes/acp/acp-agent.ts +12 -9
  81. package/src/modes/acp/acp-event-mapper.ts +38 -4
  82. package/src/modes/components/custom-editor.ts +39 -16
  83. package/src/modes/components/settings-selector.ts +9 -1
  84. package/src/modes/components/tips.txt +2 -1
  85. package/src/modes/components/tool-execution.ts +8 -7
  86. package/src/modes/controllers/extension-ui-controller.ts +4 -4
  87. package/src/modes/controllers/selector-controller.ts +7 -2
  88. package/src/modes/interactive-mode.ts +36 -47
  89. package/src/modes/prompt-action-autocomplete.ts +5 -3
  90. package/src/prompts/goals/guided-goal-interview.md +41 -6
  91. package/src/prompts/system/vibe-mode-active.md +4 -1
  92. package/src/prompts/tools/browser.md +1 -0
  93. package/src/prompts/tools/goal.md +1 -1
  94. package/src/sdk.ts +47 -50
  95. package/src/session/agent-session-types.ts +5 -5
  96. package/src/session/agent-session.ts +151 -11
  97. package/src/session/async-job-delivery.ts +8 -0
  98. package/src/session/model-controls.ts +9 -9
  99. package/src/session/session-advisors.ts +2 -7
  100. package/src/session/session-history-format.ts +31 -6
  101. package/src/session/session-listing.ts +66 -4
  102. package/src/session/session-tools.ts +158 -52
  103. package/src/session/streaming-output.ts +18 -6
  104. package/src/session/turn-recovery.ts +4 -4
  105. package/src/slash-commands/builtin-registry.ts +74 -2
  106. package/src/task/isolation-ownership.ts +106 -0
  107. package/src/task/worktree.ts +8 -0
  108. package/src/tools/ask.ts +3 -3
  109. package/src/tools/ast-edit.ts +9 -2
  110. package/src/tools/bash.ts +16 -9
  111. package/src/tools/browser/cmux/cmux-tab.ts +9 -14
  112. package/src/tools/browser/tab-worker.ts +12 -35
  113. package/src/tools/browser.ts +2 -2
  114. package/src/tools/gh-renderer.ts +3 -3
  115. package/src/tools/index.ts +46 -17
  116. package/src/tools/output-meta.ts +20 -0
  117. package/src/tools/read.ts +87 -13
  118. package/src/tools/write.ts +51 -7
  119. package/src/tools/xdev.ts +198 -210
  120. package/src/tui/code-cell.ts +4 -4
  121. package/src/tui/output-block.ts +25 -8
  122. package/src/utils/cpuprofile.ts +235 -0
  123. package/src/utils/inspect-image-mode.ts +39 -0
  124. package/src/utils/profile-tree.ts +111 -0
  125. package/src/utils/sample-profile.ts +437 -0
  126. package/src/utils/shell-snapshot-fn-env.sh +5 -2
  127. package/src/web/search/render.ts +2 -2
  128. package/dist/types/goals/guided-setup.d.ts +0 -30
  129. package/src/goals/guided-setup.ts +0 -171
  130. package/src/prompts/goals/guided-goal-system.md +0 -33
@@ -36,13 +36,6 @@ export declare function formatAdvisorBatchContent(notes: readonly AdvisorNote[])
36
36
  * and `blocker` interrupt; a plain `nit` queues.
37
37
  */
38
38
  export declare function isInterruptingSeverity(severity: AdvisorSeverity | undefined): boolean;
39
- /**
40
- * Append a staleness caveat to an advisor note when newer primary turns arrived
41
- * after the reviewed transcript window (i.e. `hasFreshBacklog` is true on the
42
- * advisor runtime at delivery time). Pure function — no session coupling — so it
43
- * can be unit-tested in isolation and called from `AgentSession#routeAdvice`.
44
- */
45
- export declare function annotateForStaleness(note: string, hasFreshBacklog: boolean): string;
46
39
  /** How an advisor note is routed to the primary. */
47
40
  export type AdvisorDeliveryChannel = "aside" | "steer" | "preserve";
48
41
  /** Half-open turn-count fence for the post-interrupt cooldown. */
@@ -95,15 +95,6 @@ export declare class AdvisorRuntime {
95
95
  get failureNotified(): boolean;
96
96
  /** True after the runtime hard-stopped on repeated or permanent failures. */
97
97
  get halted(): boolean;
98
- /**
99
- * True when `#pending` is non-empty while the drain loop is busy — i.e., newer
100
- * primary turns arrived after the current batch's transcript window was fixed
101
- * but before the advisor model finished processing it. The delivery path uses
102
- * this to annotate advice that was generated without seeing those newer turns.
103
- * Can be true during `agent.prompt()`, a `maintainContext` await, or a retry
104
- * sleep — any time `#drain` is busy and a concurrent `onTurnEnd` pushed.
105
- */
106
- get hasFreshBacklog(): boolean;
107
98
  /**
108
99
  * Called after each primary turn ends. Renders the incremental delta and
109
100
  * queues it for the advisor model.
@@ -129,6 +129,17 @@ export declare class AsyncJobManager {
129
129
  * (used by `dispose()` to nuke the manager's state).
130
130
  */
131
131
  cancelAll(filter?: AsyncJobFilter): void;
132
+ /**
133
+ * Immediately evict completed and failed jobs matching the filter instead of
134
+ * waiting for retention expiry, dropping every queued delivery so a prior
135
+ * session's result can never be injected into a later transcript. Returns the
136
+ * number of jobs evicted.
137
+ *
138
+ * A delivery whose sink call is already in flight (or drained onto a caller's
139
+ * yield queue) is guarded by the owner's delivery generation, not the per-id
140
+ * suppression marker — that marker is cleared when the id is reused.
141
+ */
142
+ evictCompletedJobs(filter?: AsyncJobFilter): number;
132
143
  waitForAll(): Promise<void>;
133
144
  /**
134
145
  * Route completions for jobs owned by `ownerId` to `sink`. Sessions register
@@ -0,0 +1,19 @@
1
+ import type { CleanseAgentOutcome, CleanseAssignment, CleanseDiagnosticReport, CleanseLoopResult } from "./types.js";
2
+ /** Hooks used by the standalone command to render subagent lifecycle progress. */
3
+ export interface CleanseAgentHooks {
4
+ onStart?(name: string, assignment: CleanseAssignment): void;
5
+ onFinish?(outcome: CleanseAgentOutcome, assignment: CleanseAssignment): void;
6
+ }
7
+ /** Persisted parent session that dispatches file-disjoint cleanse workers. */
8
+ export interface CleanseAgentRuntime {
9
+ readonly model: string;
10
+ readonly sessionFile: string;
11
+ dispatch(assignments: CleanseAssignment[], wave: number, report: CleanseDiagnosticReport, signal?: AbortSignal): Promise<CleanseAgentOutcome[]>;
12
+ close(result?: CleanseLoopResult): Promise<void>;
13
+ }
14
+ /** Resolve the requested model and create a fresh persisted cleanse session. */
15
+ export declare function createCleanseAgentRuntime(options: {
16
+ cwd?: string;
17
+ model: string;
18
+ hooks?: CleanseAgentHooks;
19
+ }): Promise<CleanseAgentRuntime>;
@@ -0,0 +1,7 @@
1
+ import type { CleanseAssignment, CleanseDiagnostic, CleanseFileIssues } from "./types.js";
2
+ /** Estimate repair burden from severity and available location/fix evidence. */
3
+ export declare function diagnosticWeight(diagnostic: CleanseDiagnostic): number;
4
+ /** Group diagnostics by file while keeping project-level failures together. */
5
+ export declare function groupDiagnosticsByFile(diagnostics: readonly CleanseDiagnostic[]): CleanseFileIssues[];
6
+ /** Balance whole-file workloads with longest-processing-time bin packing. */
7
+ export declare function balanceDiagnostics(diagnostics: readonly CleanseDiagnostic[], maxAgents: number): CleanseAssignment[];
@@ -0,0 +1,13 @@
1
+ import type { CleanseDiagnosticReport, SkippedCleanseCheck } from "./types.js";
2
+ /** Optional checker families enabled for a cleanse run. */
3
+ export interface CleanseDiagnosticSuiteOptions {
4
+ includeTests?: boolean;
5
+ }
6
+ /** Re-runnable checker set discovered from one project snapshot. */
7
+ export interface CleanseDiagnosticSuite {
8
+ readonly checkCount: number;
9
+ readonly skipped: readonly SkippedCleanseCheck[];
10
+ run(signal?: AbortSignal): Promise<CleanseDiagnosticReport>;
11
+ }
12
+ /** Discover configured language checkers without installing missing tools. */
13
+ export declare function discoverCleanseDiagnosticSuite(projectCwd: string, options?: CleanseDiagnosticSuiteOptions): Promise<CleanseDiagnosticSuite>;
@@ -0,0 +1,16 @@
1
+ import type { CleanseDiagnosticReport } from "./types.js";
2
+ /** User-facing options for `omp cleanse`. */
3
+ export interface CleanseCommandOptions {
4
+ maxAgents?: number;
5
+ model?: string;
6
+ includeTests?: boolean;
7
+ }
8
+ /** Observable completion state returned to the CLI adapter. */
9
+ export interface CleanseCommandResult {
10
+ exitCode: number;
11
+ status: "clean" | "unresolved" | "unsupported" | "cancelled";
12
+ report: CleanseDiagnosticReport;
13
+ sessionFile?: string;
14
+ }
15
+ /** Detect project diagnostics, dispatch one bounded repair batch, and verify it. */
16
+ export declare function runCleanseCommand(options?: CleanseCommandOptions): Promise<CleanseCommandResult>;
@@ -0,0 +1,16 @@
1
+ import type { CleanseAgentOutcome, CleanseAssignment, CleanseDiagnosticReport, CleanseLoopResult } from "./types.js";
2
+ /** Runtime seams for one bounded diagnose, dispatch, and verify pass. */
3
+ export interface CleanseLoopDependencies {
4
+ collect(signal?: AbortSignal): Promise<CleanseDiagnosticReport>;
5
+ dispatch(assignments: CleanseAssignment[], wave: number, report: CleanseDiagnosticReport, signal?: AbortSignal): Promise<CleanseAgentOutcome[]>;
6
+ onWave?(wave: number, assignments: readonly CleanseAssignment[]): void;
7
+ onReport?(wave: number, report: CleanseDiagnosticReport): void;
8
+ }
9
+ /** Inputs controlling one complete cleanse loop. */
10
+ export interface CleanseLoopOptions {
11
+ maxAgents: number;
12
+ initialReport: CleanseDiagnosticReport;
13
+ signal?: AbortSignal;
14
+ }
15
+ /** Dispatch at most `maxAgents` workers once, then verify their combined edits. */
16
+ export declare function runCleanseLoop(options: CleanseLoopOptions, dependencies: CleanseLoopDependencies): Promise<CleanseLoopResult>;
@@ -0,0 +1,13 @@
1
+ import type { CleanseDiagnostic } from "./types.js";
2
+ /** Machine and fallback output formats understood by cleanse. */
3
+ export type CleanseParserKind = "rust" | "rust-test" | "go" | "go-test" | "ruff" | "pyright" | "eslint" | "biome" | "rubocop" | "phpstan" | "psalm" | "swiftlint" | "dart" | "credo" | "shellcheck" | "hlint" | "terraform" | "tflint" | "generic";
4
+ /** Captured checker process output passed to a format parser. */
5
+ export interface CleanseParserInput {
6
+ checker: string;
7
+ projectCwd: string;
8
+ checkerCwd: string;
9
+ stdout: string;
10
+ stderr: string;
11
+ }
12
+ /** Parse one checker invocation into normalized, project-relative diagnostics. */
13
+ export declare function parseCleanseDiagnostics(kind: CleanseParserKind, input: CleanseParserInput): CleanseDiagnostic[];
@@ -0,0 +1,14 @@
1
+ /** Minimal output contract used by the interactive cleanse progress reporter. */
2
+ export interface CleanseProgressOutput {
3
+ isTTY?: boolean;
4
+ write(text: string): boolean;
5
+ }
6
+ /** Renders completed repair workers on one transient terminal line. */
7
+ export interface CleanseProgressReporter {
8
+ readonly interactive: boolean;
9
+ start(total: number): void;
10
+ complete(): void;
11
+ finish(): void;
12
+ }
13
+ /** Create the TTY-only worker completion reporter used by `omp cleanse`. */
14
+ export declare function createCleanseProgressReporter(output?: CleanseProgressOutput): CleanseProgressReporter;
@@ -0,0 +1,64 @@
1
+ /** Severity normalized across checker-specific output formats. */
2
+ export type CleanseSeverity = "error" | "warning" | "info";
3
+ /** One actionable problem reported by a project checker. */
4
+ export interface CleanseDiagnostic {
5
+ checker: string;
6
+ file?: string;
7
+ line?: number;
8
+ column?: number;
9
+ endLine?: number;
10
+ endColumn?: number;
11
+ code?: string;
12
+ severity: CleanseSeverity;
13
+ message: string;
14
+ suggestion?: string;
15
+ }
16
+ /** Result metadata for one checker invocation. */
17
+ export interface CleanseCheckResult {
18
+ id: string;
19
+ label: string;
20
+ language: string;
21
+ cwd: string;
22
+ command: string;
23
+ exitCode: number | null;
24
+ diagnostics: CleanseDiagnostic[];
25
+ }
26
+ /** Checker discovery result omitted because its required executable was unavailable. */
27
+ export interface SkippedCleanseCheck {
28
+ label: string;
29
+ language: string;
30
+ reason: string;
31
+ }
32
+ /** Aggregate diagnostics from every checker selected for a project. */
33
+ export interface CleanseDiagnosticReport {
34
+ checks: CleanseCheckResult[];
35
+ diagnostics: CleanseDiagnostic[];
36
+ skipped: SkippedCleanseCheck[];
37
+ }
38
+ /** All diagnostics attached to one file, which scheduling never splits across agents. */
39
+ export interface CleanseFileIssues {
40
+ file?: string;
41
+ diagnostics: CleanseDiagnostic[];
42
+ weight: number;
43
+ }
44
+ /** One weighted, file-disjoint workload handed to a subagent. */
45
+ export interface CleanseAssignment {
46
+ index: number;
47
+ groups: CleanseFileIssues[];
48
+ weight: number;
49
+ }
50
+ /** Settled result from one cleanse subagent. */
51
+ export interface CleanseAgentOutcome {
52
+ name: string;
53
+ success: boolean;
54
+ output: string;
55
+ error?: string;
56
+ resolvedModel?: string;
57
+ }
58
+ /** Final state after one bounded repair wave and verification pass. */
59
+ export interface CleanseLoopResult {
60
+ status: "clean" | "stalled" | "cancelled";
61
+ waves: number;
62
+ report: CleanseDiagnosticReport;
63
+ outcomes: CleanseAgentOutcome[];
64
+ }
@@ -0,0 +1,23 @@
1
+ import { Command } from "@oh-my-pi/pi-utils/cli";
2
+ export default class Cleanse extends Command {
3
+ static description: string;
4
+ static flags: {
5
+ agents: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"integer"> & {
6
+ char: string;
7
+ description: string;
8
+ default: number;
9
+ };
10
+ model: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
11
+ char: string;
12
+ description: string;
13
+ default: string;
14
+ };
15
+ tests: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
16
+ char: string;
17
+ description: string;
18
+ default: boolean;
19
+ };
20
+ };
21
+ static examples: string[];
22
+ run(): Promise<void>;
23
+ }
@@ -3941,11 +3941,26 @@ export declare const SETTINGS_SCHEMA: {
3941
3941
  readonly "inspect_image.enabled": {
3942
3942
  readonly type: "boolean";
3943
3943
  readonly default: false;
3944
+ };
3945
+ readonly "inspect_image.mode": {
3946
+ readonly type: "enum";
3947
+ readonly values: readonly ["auto", "on", "off"];
3948
+ readonly default: "auto";
3944
3949
  readonly ui: {
3945
3950
  readonly tab: "tools";
3946
3951
  readonly group: "Available Tools";
3947
3952
  readonly label: "Inspect Image";
3948
- readonly description: "Enable the inspect_image tool, delegating image understanding to a vision-capable model";
3953
+ readonly description: "Controls the inspect_image tool, which delegates image understanding to a vision-capable model. 'auto' exposes it only when the active model lacks native image input; 'on' always exposes it; 'off' never does.";
3954
+ readonly options: readonly [{
3955
+ readonly value: "auto";
3956
+ readonly label: "Auto (only for models without vision)";
3957
+ }, {
3958
+ readonly value: "on";
3959
+ readonly label: "On";
3960
+ }, {
3961
+ readonly value: "off";
3962
+ readonly label: "Off";
3963
+ }];
3949
3964
  };
3950
3965
  };
3951
3966
  readonly "computer.enabled": {
@@ -5,7 +5,8 @@ interface CursorExecBridgeOptions {
5
5
  cwd: string;
6
6
  getCwd?: () => string;
7
7
  tools: Map<string, AgentTool>;
8
- getTool?: (name: string) => AgentTool | undefined;
8
+ /** Resolves execution overrides (mounted-device permission wrappers) before the canonical map. */
9
+ getExecutableTool?: (name: string) => AgentTool | undefined;
9
10
  getToolContext?: () => AgentToolContext | undefined;
10
11
  emitEvent?: (event: AgentEvent) => void;
11
12
  /**
@@ -3,6 +3,8 @@ import type { SessionEntry, SessionHeader } from "../../session/session-entries.
3
3
  import { SessionManager } from "../../session/session-manager.js";
4
4
  import type { ExportThemeNames } from "./args.js";
5
5
  export { type ExportThemeNames, parseExportArgs } from "./args.js";
6
+ /** Resolve a Bun file-loader value without parsing Windows drive letters as URL schemes. */
7
+ export declare function resolveBundledHtmlAssetPath(assetPath: string, moduleDir?: string): string;
6
8
  /** Compose the standalone export template: minified CSS, tool renderers, and viewer JS inlined. */
7
9
  export declare function getTemplate(): string;
8
10
  export interface ExportOptions {
@@ -69,6 +69,10 @@ export declare class ExtensionRunner {
69
69
  private readonly modelRegistry;
70
70
  private readonly settings?;
71
71
  private readonly localProtocolOptions?;
72
+ /** Records that the loop already emitted `tool_call` for this dispatch. */
73
+ markToolCallEmitted(toolCallId: string, toolName: string): void;
74
+ /** Consumes a {@link markToolCallEmitted} marker; true when the loop already emitted. */
75
+ consumeToolCallEmitted(toolCallId: string, toolName: string): boolean;
72
76
  constructor(extensions: Extension[], runtime: ExtensionRuntime, cwd: string, sessionManager: SessionManager, modelRegistry: ModelRegistry, getMemory?: () => MemoryRuntimeContext | undefined, settings?: Settings | undefined, localProtocolOptions?: LocalProtocolOptions | undefined);
73
77
  initialize(actions: ExtensionActions, contextActions: ExtensionContextActions, commandContextActions?: ExtensionCommandContextActions, uiContext?: ExtensionUIContext): void;
74
78
  /**
@@ -19,7 +19,7 @@
19
19
  * `types.ts` via the `export *` below — pi-ai still exports both as types,
20
20
  * only the runtime `Type` builder and `StringEnum()` helper were removed.
21
21
  */
22
- import type { Api, Model } from "@oh-my-pi/pi-ai";
22
+ import type { Api, AssistantMessage, Model } from "@oh-my-pi/pi-ai";
23
23
  import type { Effort } from "@oh-my-pi/pi-catalog/effort";
24
24
  import { calculateCost, getBundledModel, getBundledModels, getBundledProviders, modelsAreEqual } from "@oh-my-pi/pi-catalog/models";
25
25
  import { type TSchema, Type } from "./typebox.js";
@@ -32,6 +32,15 @@ export interface StringEnumOptions<T extends string> {
32
32
  export declare function StringEnum<T extends string | number>(values: readonly T[] | Record<string, T>, options?: StringEnumOptions<any>): TSchema;
33
33
  /** Clamp a historical Pi thinking level against OMP's model metadata. */
34
34
  export declare function clampThinkingLevel<TApi extends Api>(model: Model<TApi>, level: Effort | "off"): Effort | "off";
35
+ /**
36
+ * Compatibility implementation of historical pi-ai's `isRetryableAssistantError`.
37
+ *
38
+ * Classifies whether a failed assistant message looks like a transient provider
39
+ * or transport error so legacy extensions can decide if the last assistant turn
40
+ * should be restarted. Account/quota limits are treated as non-retryable. This
41
+ * does not implement any retry policy; callers own budget, backoff, and reporting.
42
+ */
43
+ export declare function isRetryableAssistantError(message: AssistantMessage): boolean;
35
44
  export * from "@oh-my-pi/pi-ai";
36
45
  /**
37
46
  * Compatibility re-exports for catalog symbols that pi-ai historically exposed
@@ -45,3 +54,20 @@ export * from "@oh-my-pi/pi-ai";
45
54
  export { calculateCost, getBundledModel, getBundledModels, getBundledProviders, modelsAreEqual, Type };
46
55
  export declare const getModel: typeof getBundledModel;
47
56
  export declare const getModels: typeof getBundledModels;
57
+ /**
58
+ * Compatibility re-exports for runtime helpers that upstream
59
+ * `@earendil-works/pi-ai` exposed from its package root but omp's
60
+ * `@oh-my-pi/pi-ai` barrel no longer forwards. Each symbol still exists in the
61
+ * host graph — only its root re-export was dropped — so bridging it here keeps
62
+ * legacy extensions importing it from the pi-ai root resolving through Bun's
63
+ * static named-export check (e.g. `omp plugin install pi-blackhole`).
64
+ *
65
+ * This is the full set derived from an audit of the upstream root surface: the
66
+ * error-classification predicate `isContextOverflow` (now under
67
+ * `@oh-my-pi/pi-ai/error`) and the JSON-repair helpers that omp relocated to
68
+ * `@oh-my-pi/pi-utils`. Upstream root symbols with no omp equivalent are
69
+ * intentionally not shimmed — the package has diverged and there is nothing to
70
+ * forward.
71
+ */
72
+ export { isContextOverflow } from "@oh-my-pi/pi-ai/error";
73
+ export { parseJsonWithRepair, parseStreamingJson, repairJson } from "@oh-my-pi/pi-utils";
@@ -228,13 +228,30 @@ export interface TodoReminderEvent {
228
228
  }
229
229
  /**
230
230
  * Return type for `tool_call` handlers.
231
- * Allows handlers to block tool execution.
231
+ * Allows handlers to block tool execution or revise the input the tool runs with.
232
232
  */
233
233
  export interface ToolCallEventResult {
234
234
  /** If true, block the tool from executing */
235
235
  block?: boolean;
236
236
  /** Reason for blocking (returned to LLM as error) */
237
237
  reason?: string;
238
+ /**
239
+ * Replacement input the tool executes with, instead of the original arguments. Ignored when
240
+ * `block` is true. This is the raw execution input passed to the tool's `execute` (the handler
241
+ * owns its correctness) — not the normalized `event.input` view, which may carry derived
242
+ * gate-only fields (e.g. hashline `edit` `path`/`paths`) that are not real parameters. When
243
+ * multiple handlers set `input`, the last one wins; handlers do not observe each other's
244
+ * revisions (each sees the original `event.input`). Not applied to `computer` tool calls.
245
+ *
246
+ * For model-issued tool calls the event fires at arg-prep time in the agent loop, before
247
+ * concurrency scheduling, `tool_execution_start`, and the approval gate: the revision is
248
+ * revalidated against the tool schema and becomes what the loop schedules, displays, persists,
249
+ * and executes — the user always approves what actually runs. For dispatches the loop never
250
+ * sees (nested `write xd://` device calls, Cursor direct execution) the tool wrapper applies
251
+ * the revision before its own approval gate; a revised nested xd:// input forfeits the outer
252
+ * write gate's approval and faces the full prompt again.
253
+ */
254
+ input?: Record<string, unknown>;
238
255
  }
239
256
  /**
240
257
  * Return type for `tool_result` handlers.
@@ -103,6 +103,11 @@ export declare class CustomEditor extends Editor {
103
103
  * reset the editor text and all pending draft-image state. The shared tail of
104
104
  * every "message submitted" path; pass no argument for a plain discard. */
105
105
  clearDraft(historyText?: string): void;
106
+ /** Replace the composer draft with a restored historical prompt: sets the text and
107
+ * re-attaches the message's images so positional `[Image #N]` markers resolve on
108
+ * resubmit instead of degrading to literal text (esc-esc branch, `/tree`). Source
109
+ * links are unknown for restored drafts, so every link slot is `undefined`. */
110
+ setDraft(text: string, images?: readonly ImageContent[]): void;
106
111
  /** Treat image/paste markers as indivisible: a stray backspace deletes the whole token
107
112
  * instead of corrupting `[Paste #1, +30 lines]` into plain text. */
108
113
  atomicTokenPattern: RegExp;
@@ -257,9 +257,10 @@ export declare class InteractiveMode implements InteractiveModeContext {
257
257
  handlePlanModeCommand(initialPrompt?: string): Promise<void>;
258
258
  /**
259
259
  * `/vibe` toggle. Entering installs the ephemeral vibe tools, strips the
260
- * active toolset down to `read` plus those tools, and injects the director
261
- * context. Exiting unregisters them, restores the previous toolset, and kills
262
- * every worker session so workers cannot outlive the mode that directs them.
260
+ * active toolset down to `read`, optional parent-owned `todo`, plus those
261
+ * tools, and injects the director context. Exiting unregisters them, restores
262
+ * the previous toolset, and kills every worker session so workers cannot
263
+ * outlive the mode that directs them.
263
264
  */
264
265
  handleVibeModeCommand(initialPrompt?: string): Promise<void>;
265
266
  handleGoalModeCommand(rest?: string): Promise<void>;
@@ -15,7 +15,7 @@ import type { Skill, SkillWarning } from "../extensibility/skills.js";
15
15
  import type { FileSlashCommand } from "../extensibility/slash-commands.js";
16
16
  import type { SecretObfuscator } from "../secrets/obfuscator.js";
17
17
  import type { ConfiguredThinkingLevel } from "../thinking.js";
18
- import type { XdevRegistry } from "../tools/xdev.js";
18
+ import type { XdevState } from "../tools/xdev.js";
19
19
  import type { SessionManager } from "./session-manager.js";
20
20
  /** Maximum time the interactive shutdown path waits for Mnemopi consolidation. */
21
21
  export declare const SHUTDOWN_CONSOLIDATE_BUDGET_MS = 1500;
@@ -121,6 +121,8 @@ export interface AgentSessionConfig {
121
121
  createMemoryTools?: () => Promise<AgentTool[]>;
122
122
  /** Creates the built-in `computer` tool for session-scoped runtime enablement (see {@link AgentSession.setComputerToolEnabled}). */
123
123
  createComputerTool?: () => Promise<AgentTool | null>;
124
+ /** Creates the built-in `inspect_image` tool for session-scoped runtime enablement (see {@link AgentSession.setInspectImageMode}). */
125
+ createInspectImageTool?: () => Promise<AgentTool | null>;
124
126
  /** Model registry for API key resolution and model discovery. */
125
127
  modelRegistry: ModelRegistry;
126
128
  /** Tool registry for LSP and settings. */
@@ -164,10 +166,8 @@ export interface AgentSessionConfig {
164
166
  name: string;
165
167
  summary: string;
166
168
  }>;
167
- /** Session-owned `xd://` registry. */
168
- xdevRegistry?: XdevRegistry;
169
- /** Discoverable tools mounted under `xd://` in the initial enabled set. */
170
- initialMountedXdevToolNames?: string[];
169
+ /** `xd://` presentation state backed by the canonical tool map. */
170
+ xdev?: XdevState;
171
171
  /** Names pinned top-level during runtime repartitioning. */
172
172
  presentationPinnedToolNames?: ReadonlySet<string>;
173
173
  /** Accessor for live MCP server instructions. */
@@ -46,6 +46,7 @@ import { type AskToolDetails, type AskToolInput } from "../tools/ask.js";
46
46
  import type { CheckpointState, CompletedRewindState } from "../tools/checkpoint.js";
47
47
  import { type PlanProposalHandler } from "../tools/resolve.js";
48
48
  import type { TodoPhase } from "../tools/todo.js";
49
+ import type { InspectImageMode } from "../utils/inspect-image-mode.js";
49
50
  import type { VibeModeState } from "../vibe/state.js";
50
51
  import type { AgentSessionEventListener } from "./agent-session-events.js";
51
52
  import type { AgentSessionConfig, AgentSessionDisposeOptions, AsyncJobSnapshot, CommandMetadataChangedListener, ContextUsageBreakdown, FollowUpOptions, FreshSessionResult, HandoffResult, ModelCycleResult, Prewalk, PromptOptions, ResolvedRoleModel, RestoredQueuedMessage, RoleModelCycle, RoleModelCycleResult, SessionHandoffOptions, SessionOAuthAccountList, SessionStats, UsageFallbackConfirmation } from "./agent-session-types.js";
@@ -283,6 +284,26 @@ export declare class AgentSession {
283
284
  * tool (e.g. restricted child sessions have no factory).
284
285
  */
285
286
  setComputerToolEnabled(enabled: boolean): Promise<boolean>;
287
+ /**
288
+ * Session-scoped inspect_image mode (`/vision`). `auto` clears the override
289
+ * and returns to the persisted `inspect_image.mode` setting; `on`/`off`
290
+ * force the tool for this session only. See {@link SessionTools.setInspectImageMode}.
291
+ */
292
+ setInspectImageMode(mode: InspectImageMode): Promise<boolean>;
293
+ /** Effective inspect_image state for `/vision status`. */
294
+ inspectImageState(): {
295
+ mode: InspectImageMode;
296
+ active: boolean;
297
+ model: string | undefined;
298
+ };
299
+ /** Session-scoped `/vision` override; undefined means "follow the persisted setting". */
300
+ getInspectImageModeOverride(): InspectImageMode | undefined;
301
+ /**
302
+ * Reconciles the inspect_image tool set after the persisted
303
+ * `inspect_image.mode` setting changed (e.g. via the settings selector), so
304
+ * the new value takes effect immediately instead of on the next model switch.
305
+ */
306
+ applyInspectImageModeChange(): Promise<boolean>;
286
307
  /** Cancels the local rollout-memory startup owned by this session. */
287
308
  cancelLocalMemoryStartup(): void;
288
309
  /** Starts a new local rollout-memory generation and cancels its predecessor. */
@@ -766,10 +787,12 @@ export declare class AgentSession {
766
787
  * @param entryId ID of the entry to branch from
767
788
  * @returns Object with:
768
789
  * - selectedText: The text of the selected user message (for editor pre-fill)
790
+ * - selectedImages: Image attachments of the selected user message (for editor draft restore)
769
791
  * - cancelled: True if a hook cancelled the branch
770
792
  */
771
793
  branch(entryId: string): Promise<{
772
794
  selectedText: string;
795
+ selectedImages: ImageContent[];
773
796
  cancelled: boolean;
774
797
  }>;
775
798
  branchFromBtw(question: string, assistantMessage: AssistantMessage): Promise<{
@@ -783,7 +806,7 @@ export declare class AgentSession {
783
806
  * @param targetId The entry ID to navigate to
784
807
  * @param options.summarize Whether user wants to summarize abandoned branch
785
808
  * @param options.customInstructions Custom instructions for summarizer
786
- * @returns Result with editorText (if user message) and cancelled status
809
+ * @returns Result with editorText/editorImages (if user message) and cancelled status
787
810
  */
788
811
  navigateTree(targetId: string, options?: {
789
812
  summarize?: boolean;
@@ -810,6 +833,8 @@ export declare class AgentSession {
810
833
  reanswerAskResult?: AgentToolResult<AskToolDetails>;
811
834
  }): Promise<{
812
835
  editorText?: string;
836
+ /** Image attachments of the target user message, parallel to the positional `[Image #N]` markers in {@link editorText}. */
837
+ editorImages?: ImageContent[];
813
838
  cancelled: boolean;
814
839
  aborted?: boolean;
815
840
  summaryEntry?: BranchSummaryEntry;
@@ -14,6 +14,14 @@ export interface AsyncResultEntry {
14
14
  result: string;
15
15
  job: AsyncJob | undefined;
16
16
  durationMs: number | undefined;
17
+ /**
18
+ * Owning session's async-delivery generation at enqueue time. A session
19
+ * transition (`/new`, switch, handoff) bumps the generation, so an entry
20
+ * whose generation no longer matches belongs to a replaced transcript and
21
+ * is dropped at flush — even after its job id has been reused, which clears
22
+ * the manager's per-id suppression marker.
23
+ */
24
+ epoch: number;
17
25
  }
18
26
  type AsyncResultJobDetails = {
19
27
  jobId: string;
@@ -21,7 +21,7 @@ export interface ModelControlsHost {
21
21
  promptGeneration(): number;
22
22
  resolveActiveEditMode(): EditMode;
23
23
  syncAfterModelChange(previousEditMode: EditMode): Promise<void>;
24
- setModelWithProviderSessionReset(model: Model): void;
24
+ setModelWithProviderSessionReset(model: Model): Promise<void>;
25
25
  clearActiveRetryFallback(): void;
26
26
  clearInheritedProviderPromptCacheKey(): void;
27
27
  magicKeywordEnabled(keyword: "orchestrate" | "ultrathink" | "workflow"): boolean;
@@ -134,9 +134,9 @@ export declare class ModelControls {
134
134
  cycleThinkingLevel(): ConfiguredThinkingLevel | undefined;
135
135
  /**
136
136
  * Classify the current user turn and set the effective thinking level for it.
137
- * Bounded by a timeout + abort; on any failure (no smol model, timeout, parse
138
- * error) it falls back to the provisional concrete level and continues. Never
139
- * throws into the turn, and never clears `#autoThinking` (auto stays active).
137
+ * Bounded by a timeout + abort; on failure it preserves the last classified
138
+ * level, or uses the provisional concrete level before the first resolution.
139
+ * Never throws into the turn, and never clears `#autoThinking`.
140
140
  */
141
141
  applyAutoThinkingLevel(promptText: string, generation: number): Promise<void>;
142
142
  /**