@oh-my-pi/pi-coding-agent 16.0.3 → 16.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 (75) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/cli.js +697 -337
  3. package/dist/types/advisor/advise-tool.d.ts +9 -0
  4. package/dist/types/cli/args.d.ts +2 -0
  5. package/dist/types/cli/bench-cli.d.ts +6 -0
  6. package/dist/types/commands/launch.d.ts +6 -0
  7. package/dist/types/config/settings-schema.d.ts +92 -3
  8. package/dist/types/edit/file-snapshot-store.d.ts +2 -0
  9. package/dist/types/extensibility/extensions/runner.d.ts +5 -2
  10. package/dist/types/extensibility/extensions/types.d.ts +8 -7
  11. package/dist/types/extensibility/shared-events.d.ts +22 -1
  12. package/dist/types/main.d.ts +1 -0
  13. package/dist/types/modes/components/status-line/component.d.ts +1 -1
  14. package/dist/types/modes/components/status-line/context-thresholds.d.ts +0 -1
  15. package/dist/types/modes/rpc/rpc-types.d.ts +1 -1
  16. package/dist/types/modes/utils/context-usage.d.ts +12 -0
  17. package/dist/types/sdk.d.ts +3 -1
  18. package/dist/types/session/agent-session.d.ts +20 -0
  19. package/dist/types/session/session-persistence.d.ts +4 -0
  20. package/dist/types/tools/read.d.ts +1 -0
  21. package/dist/types/tui/code-cell.d.ts +2 -0
  22. package/dist/types/utils/image-vision-fallback.d.ts +28 -0
  23. package/dist/types/web/search/providers/base.d.ts +1 -0
  24. package/dist/types/web/search/providers/gemini.d.ts +1 -0
  25. package/package.json +12 -12
  26. package/src/advisor/__tests__/advisor.test.ts +59 -0
  27. package/src/advisor/advise-tool.ts +13 -0
  28. package/src/cli/args.ts +4 -0
  29. package/src/cli/bench-cli.ts +30 -7
  30. package/src/cli/flag-tables.ts +9 -0
  31. package/src/collab/host.ts +2 -2
  32. package/src/commands/launch.ts +6 -0
  33. package/src/config/settings-schema.ts +85 -3
  34. package/src/edit/file-snapshot-store.ts +12 -3
  35. package/src/eval/py/runner.py +44 -0
  36. package/src/extensibility/extensions/runner.ts +20 -2
  37. package/src/extensibility/extensions/types.ts +16 -5
  38. package/src/extensibility/shared-events.ts +24 -0
  39. package/src/internal-urls/docs-index.generated.ts +81 -81
  40. package/src/main.ts +18 -9
  41. package/src/modes/components/branch-summary-message.ts +1 -0
  42. package/src/modes/components/collab-prompt-message.ts +9 -7
  43. package/src/modes/components/compaction-summary-message.ts +1 -0
  44. package/src/modes/components/custom-message.ts +1 -0
  45. package/src/modes/components/footer.ts +6 -5
  46. package/src/modes/components/hook-message.ts +1 -0
  47. package/src/modes/components/read-tool-group.ts +9 -3
  48. package/src/modes/components/skill-message.ts +1 -0
  49. package/src/modes/components/status-line/component.ts +131 -14
  50. package/src/modes/components/status-line/context-thresholds.ts +0 -1
  51. package/src/modes/components/tips.txt +2 -1
  52. package/src/modes/components/todo-reminder.ts +1 -0
  53. package/src/modes/components/ttsr-notification.ts +1 -0
  54. package/src/modes/components/user-message.ts +6 -6
  55. package/src/modes/controllers/event-controller.ts +2 -7
  56. package/src/modes/controllers/selector-controller.ts +10 -3
  57. package/src/modes/interactive-mode.ts +4 -2
  58. package/src/modes/rpc/rpc-types.ts +1 -1
  59. package/src/modes/utils/context-usage.ts +28 -15
  60. package/src/prompts/system/system-prompt.md +2 -0
  61. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  62. package/src/prompts/tools/image-attachment-describe.md +10 -0
  63. package/src/sdk.ts +14 -18
  64. package/src/session/agent-session.ts +571 -235
  65. package/src/session/session-loader.ts +19 -32
  66. package/src/session/session-persistence.ts +27 -11
  67. package/src/ssh/connection-manager.ts +3 -2
  68. package/src/task/executor.ts +1 -1
  69. package/src/tools/image-gen.ts +67 -25
  70. package/src/tools/read.ts +54 -6
  71. package/src/tui/code-cell.ts +44 -3
  72. package/src/utils/image-vision-fallback.ts +197 -0
  73. package/src/web/search/index.ts +12 -0
  74. package/src/web/search/providers/base.ts +1 -0
  75. package/src/web/search/providers/gemini.ts +56 -18
@@ -39,6 +39,12 @@ export declare function formatAdvisorBatchContent(notes: readonly AdvisorNote[])
39
39
  export declare function isInterruptingSeverity(severity: AdvisorSeverity | undefined): boolean;
40
40
  /** How an advisor note is routed to the primary. */
41
41
  export type AdvisorDeliveryChannel = "aside" | "steer" | "preserve";
42
+ /** Half-open turn-count fence for the post-interrupt cooldown. */
43
+ export declare function isAdvisorInterruptImmuneTurnActive(opts: {
44
+ completedTurns: number;
45
+ immuneTurnStart: number | undefined;
46
+ immuneTurns: number;
47
+ }): boolean;
42
48
  /**
43
49
  * Decide how one advisor note reaches the primary agent.
44
50
  *
@@ -54,12 +60,15 @@ export type AdvisorDeliveryChannel = "aside" | "steer" | "preserve";
54
60
  * auto-resume anything, so it is delivered live. Parking it during an active
55
61
  * run instead strands it (it never reaches the running agent) and the withheld
56
62
  * notes dump as one burst at the next user prompt — the bug this guards.
63
+ * - During the post-interrupt immune-turn window, further `concern`/`blocker`
64
+ * notes are downgraded to asides; suppression preservation still wins.
57
65
  */
58
66
  export declare function resolveAdvisorDeliveryChannel(opts: {
59
67
  severity: AdvisorSeverity | undefined;
60
68
  autoResumeSuppressed: boolean;
61
69
  streaming: boolean;
62
70
  aborting: boolean;
71
+ interruptImmuneTurnActive?: boolean;
63
72
  }): AdvisorDeliveryChannel;
64
73
  /**
65
74
  * Side-effect-free investigation tools handed to the advisor agent so it can
@@ -14,11 +14,13 @@ export interface Args {
14
14
  smol?: string;
15
15
  slow?: string;
16
16
  plan?: string;
17
+ maxTime?: number;
17
18
  apiKey?: string;
18
19
  systemPrompt?: string;
19
20
  appendSystemPrompt?: string;
20
21
  thinking?: Effort;
21
22
  hideThinking?: boolean;
23
+ advisor?: boolean;
22
24
  continue?: boolean;
23
25
  resume?: string | true;
24
26
  help?: boolean;
@@ -73,6 +73,12 @@ export interface BenchDependencies {
73
73
  now?: () => number;
74
74
  stdoutIsTTY?: boolean;
75
75
  }
76
+ /**
77
+ * Tokens/s over the generation window (duration minus TTFT) so queue/prefill
78
+ * latency does not dilute throughput. Falls back to total duration when the
79
+ * response arrived as a single chunk (TTFT ~ duration).
80
+ */
81
+ export declare function computeTokensPerSecond(outputTokens: number, durationMs: number, ttftMs: number, deltaChunkCount: number): number;
76
82
  export declare function formatBenchTable(summary: BenchSummary): string;
77
83
  export declare function runBenchCommand(command: BenchCommandArgs, deps?: BenchDependencies): Promise<BenchSummary>;
78
84
  export {};
@@ -97,6 +97,9 @@ export default class Index extends Command {
97
97
  "hide-thinking": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
98
98
  description: string;
99
99
  };
100
+ advisor: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
101
+ description: string;
102
+ };
100
103
  hook: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
101
104
  description: string;
102
105
  multiple: true;
@@ -124,6 +127,9 @@ export default class Index extends Command {
124
127
  "no-title": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
125
128
  description: string;
126
129
  };
130
+ "max-time": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
131
+ description: string;
132
+ };
127
133
  "auto-approve": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
128
134
  aliases: string[];
129
135
  description: string;
@@ -209,10 +209,51 @@ export declare const SETTINGS_SCHEMA: {
209
209
  readonly description: "Pause the main agent for up to 30 seconds if the advisor falls behind by this many turns. Off disables catch-up delays.";
210
210
  };
211
211
  };
212
+ readonly "advisor.immuneTurns": {
213
+ readonly type: "number";
214
+ readonly default: 1;
215
+ readonly ui: {
216
+ readonly tab: "model";
217
+ readonly group: "Advisor";
218
+ readonly label: "Advisor Immune Turns";
219
+ readonly description: "After an advisor concern or blocker interrupts, route further concerns/blockers non-interruptingly for this many primary turns.";
220
+ readonly options: readonly [{
221
+ readonly value: "0";
222
+ readonly label: "0 turns";
223
+ readonly description: "Allow every concern/blocker to interrupt.";
224
+ }, {
225
+ readonly value: "1";
226
+ readonly label: "1 turn";
227
+ readonly description: "Default.";
228
+ }, {
229
+ readonly value: "2";
230
+ readonly label: "2 turns";
231
+ }, {
232
+ readonly value: "3";
233
+ readonly label: "3 turns";
234
+ }, {
235
+ readonly value: "4";
236
+ readonly label: "4 turns";
237
+ }, {
238
+ readonly value: "5";
239
+ readonly label: "5 turns";
240
+ }];
241
+ };
242
+ };
212
243
  readonly shellPath: {
213
244
  readonly type: "string";
214
245
  readonly default: undefined;
215
246
  };
247
+ readonly "git.enabled": {
248
+ readonly type: "boolean";
249
+ readonly default: true;
250
+ readonly ui: {
251
+ readonly tab: "interaction";
252
+ readonly group: "Git";
253
+ readonly label: "Enable Git Integration";
254
+ readonly description: "Show git branch, status, and PR information in the TUI and watch repository metadata.";
255
+ };
256
+ };
216
257
  readonly extensions: {
217
258
  readonly type: "array";
218
259
  readonly default: string[];
@@ -678,6 +719,16 @@ export declare const SETTINGS_SCHEMA: {
678
719
  readonly description: "Prevent images from being sent to LLM providers";
679
720
  };
680
721
  };
722
+ readonly "images.describeForTextModels": {
723
+ readonly type: "boolean";
724
+ readonly default: true;
725
+ readonly ui: {
726
+ readonly tab: "model";
727
+ readonly group: "Vision";
728
+ readonly label: "Describe Images for Text Models";
729
+ readonly description: "When an image is attached to a model without vision support, save it under local:// and inject a description from a vision-capable model instead of dropping it";
730
+ };
731
+ };
681
732
  readonly "tui.maxInlineImageColumns": {
682
733
  readonly type: "number";
683
734
  readonly default: 100;
@@ -714,6 +765,16 @@ export declare const SETTINGS_SCHEMA: {
714
765
  readonly description: "Wrap paths and URLs in OSC 8 hyperlinks for terminal-native click-to-open (auto: detect support; off: never; always: unconditional)";
715
766
  };
716
767
  };
768
+ readonly "tui.tight": {
769
+ readonly type: "boolean";
770
+ readonly default: false;
771
+ readonly ui: {
772
+ readonly tab: "appearance";
773
+ readonly group: "Display";
774
+ readonly label: "Tight Layout";
775
+ readonly description: "Remove the 1-character horizontal padding from the left and right of the terminal output";
776
+ };
777
+ };
717
778
  readonly "display.tabWidth": {
718
779
  readonly type: "number";
719
780
  readonly default: 3;
@@ -1550,7 +1611,7 @@ export declare const SETTINGS_SCHEMA: {
1550
1611
  };
1551
1612
  readonly "contextPromotion.enabled": {
1552
1613
  readonly type: "boolean";
1553
- readonly default: true;
1614
+ readonly default: false;
1554
1615
  readonly ui: {
1555
1616
  readonly tab: "context";
1556
1617
  readonly group: "General";
@@ -1875,7 +1936,7 @@ export declare const SETTINGS_SCHEMA: {
1875
1936
  };
1876
1937
  readonly "tools.format": {
1877
1938
  readonly type: "enum";
1878
- readonly values: readonly ["auto", "native", "glm", "hermes", "kimi", "xml", "anthropic", "deepseek", "harmony", "pi", "qwen3", "gemini", "gemma"];
1939
+ readonly values: readonly ["auto", "native", "glm", "hermes", "kimi", "xml", "anthropic", "deepseek", "harmony", "pi", "qwen3", "gemini", "gemma", "minimax"];
1879
1940
  readonly default: "auto";
1880
1941
  readonly ui: {
1881
1942
  readonly tab: "context";
@@ -1934,6 +1995,10 @@ export declare const SETTINGS_SCHEMA: {
1934
1995
  readonly value: "gemma";
1935
1996
  readonly label: "Gemma";
1936
1997
  readonly description: "Use the Gemma owned dialect.";
1998
+ }, {
1999
+ readonly value: "minimax";
2000
+ readonly label: "MiniMax";
2001
+ readonly description: "Use the MiniMax owned dialect.";
1937
2002
  }];
1938
2003
  };
1939
2004
  };
@@ -2846,7 +2911,7 @@ export declare const SETTINGS_SCHEMA: {
2846
2911
  readonly tab: "files";
2847
2912
  readonly group: "Read Summaries";
2848
2913
  readonly label: "Read Summary Unfold Ceiling";
2849
- readonly description: "Hard ceiling on summary size while BFS-unfolding. An unfold that would exceed this is reverted and unfolding stops.";
2914
+ readonly description: "Hard ceiling on summary size while BFS-unfolding. An unfold whose revealed lines would exceed this is skipped (that span stays folded) and unfolding continues with the remaining spans.";
2850
2915
  };
2851
2916
  };
2852
2917
  readonly "read.toolResultPreview": {
@@ -4132,6 +4197,30 @@ export declare const SETTINGS_SCHEMA: {
4132
4197
  readonly description: "Providers that web_search should never use, even as fallbacks";
4133
4198
  };
4134
4199
  };
4200
+ readonly "providers.antigravityEndpoint": {
4201
+ readonly type: "enum";
4202
+ readonly values: readonly ["auto", "production", "sandbox"];
4203
+ readonly default: "auto";
4204
+ readonly ui: {
4205
+ readonly tab: "providers";
4206
+ readonly group: "Services";
4207
+ readonly label: "Antigravity Endpoint Mode";
4208
+ readonly description: "Endpoint routing strategy for google-antigravity providers (chat, search, image, discovery)";
4209
+ readonly options: readonly [{
4210
+ readonly value: "auto";
4211
+ readonly label: "Auto";
4212
+ readonly description: "Try production endpoint, fail over to sandbox on 5xx/429";
4213
+ }, {
4214
+ readonly value: "production";
4215
+ readonly label: "Production Only";
4216
+ readonly description: "Force production endpoint only";
4217
+ }, {
4218
+ readonly value: "sandbox";
4219
+ readonly label: "Sandbox Only";
4220
+ readonly description: "Force sandbox endpoint only";
4221
+ }];
4222
+ };
4223
+ };
4135
4224
  readonly "providers.image": {
4136
4225
  readonly type: "enum";
4137
4226
  readonly values: readonly ["auto", "openai", "antigravity", "xai", "gemini", "openrouter"];
@@ -52,6 +52,8 @@ export declare function recordFileSnapshot(session: FileSnapshotStoreOwner, abso
52
52
  * the elided interior was never shown, so editing inside it must be rejected.
53
53
  */
54
54
  export declare function parseSeenLinesFromHashlineBody(body: string): number[];
55
+ /** Merge explicit 1-indexed displayed lines into a recorded hashline snapshot. */
56
+ export declare function recordSeenLines(session: FileSnapshotStoreOwner, absolutePath: string, tag: string, lines: readonly number[]): void;
55
57
  /**
56
58
  * Attach the lines a read displayed to the snapshot it minted, so the patcher
57
59
  * can reject edits anchored on lines the model never saw. Best-effort: a no-op
@@ -8,7 +8,7 @@ import type { ModelRegistry } from "../../config/model-registry";
8
8
  import type { Settings } from "../../config/settings";
9
9
  import type { MemoryRuntimeContext } from "../../memory-backend";
10
10
  import type { SessionManager } from "../../session/session-manager";
11
- import type { AfterProviderResponseEvent, AssistantThinkingRenderer, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types";
11
+ import type { AfterProviderResponseEvent, AssistantThinkingRenderer, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, SessionStopEvent, SessionStopEventResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types";
12
12
  /** Combined result from all before_agent_start handlers */
13
13
  interface BeforeAgentStartCombinedResult {
14
14
  messages?: NonNullable<BeforeAgentStartEventResult["message"]>[];
@@ -43,7 +43,9 @@ type RunnerEmitResult<TEvent extends RunnerEmitEvent> = TEvent extends {
43
43
  type: "session_before_tree";
44
44
  } ? SessionBeforeTreeResult | undefined : TEvent extends {
45
45
  type: "session.compacting";
46
- } ? SessionCompactingResult | undefined : undefined;
46
+ } ? SessionCompactingResult | undefined : TEvent extends {
47
+ type: "session_stop";
48
+ } ? SessionStopEventResult | undefined : undefined;
47
49
  export type NewSessionHandler = (options?: {
48
50
  parentSession?: string;
49
51
  setup?: (sessionManager: SessionManager) => Promise<void>;
@@ -92,6 +94,7 @@ export declare class ExtensionRunner {
92
94
  * {@link onError} via {@link emit}'s normal isolation.
93
95
  */
94
96
  emitCredentialDisabled(event: CredentialDisabledEvent): Promise<void>;
97
+ emitSessionStop(event: Omit<SessionStopEvent, "type">): Promise<SessionStopEventResult | undefined>;
95
98
  getUIContext(): ExtensionUIContext;
96
99
  hasUI(): boolean;
97
100
  getExtensionPaths(): string[];
@@ -29,7 +29,7 @@ import type { ReadonlySessionManager, SessionManager } from "../../session/sessi
29
29
  import type { BashToolDetails, BashToolInput, FindToolDetails, FindToolInput, ReadToolDetails, ReadToolInput, SearchToolDetails, SearchToolInput, WriteToolInput } from "../../tools";
30
30
  import type { ApprovalMode } from "../../tools/approval";
31
31
  import type { EventBus } from "../../utils/event-bus";
32
- import type { AgentEndEvent, AgentStartEvent, AutoCompactionEndEvent, AutoCompactionStartEvent, AutoRetryEndEvent, AutoRetryStartEvent, ContextEvent, GoalUpdatedEvent, SessionBeforeBranchEvent, SessionBeforeBranchResult, SessionBeforeCompactEvent, SessionBeforeCompactResult, SessionBeforeSwitchEvent, SessionBeforeSwitchResult, SessionBeforeTreeEvent, SessionBeforeTreeResult, SessionBranchEvent, SessionCompactEvent, SessionCompactingEvent, SessionCompactingResult, SessionEvent, SessionShutdownEvent, SessionStartEvent, SessionSwitchEvent, SessionTreeEvent, TodoReminderEvent, ToolCallEventResult, ToolResultEventResult, TtsrTriggeredEvent, TurnEndEvent, TurnStartEvent } from "../shared-events";
32
+ import type { AgentEndEvent, AgentStartEvent, AutoCompactionEndEvent, AutoCompactionStartEvent, AutoRetryEndEvent, AutoRetryStartEvent, ContextEvent, GoalUpdatedEvent, SessionBeforeBranchEvent, SessionBeforeBranchResult, SessionBeforeCompactEvent, SessionBeforeCompactResult, SessionBeforeSwitchEvent, SessionBeforeSwitchResult, SessionBeforeTreeEvent, SessionBeforeTreeResult, SessionBranchEvent, SessionCompactEvent, SessionCompactingEvent, SessionCompactingResult, SessionEvent, SessionShutdownEvent, SessionStartEvent, SessionStopEvent, SessionStopEventResult, SessionSwitchEvent, SessionTreeEvent, TodoReminderEvent, ToolCallEventResult, ToolResultEventResult, TtsrTriggeredEvent, TurnEndEvent, TurnStartEvent } from "../shared-events";
33
33
  import type { SlashCommandInfo } from "../slash-commands";
34
34
  import type * as TypeBox from "../typebox";
35
35
  export type { AppKeybinding, KeybindingsManager } from "../../config/keybindings";
@@ -161,11 +161,11 @@ export interface ExtensionUIContext {
161
161
  setToolsExpanded(expanded: boolean): void;
162
162
  }
163
163
  export interface ContextUsage {
164
- /** Estimated context tokens, or null if unknown (e.g. right after compaction, before next LLM response). */
165
- tokens: number | null;
164
+ /** Estimated context tokens. */
165
+ tokens: number;
166
166
  contextWindow: number;
167
- /** Context usage as percentage of context window, or null if tokens is unknown. */
168
- percent: number | null;
167
+ /** Context usage as percentage of context window. */
168
+ percent: number;
169
169
  }
170
170
  export interface CompactOptions {
171
171
  onComplete?: (result: CompactionResult) => void;
@@ -347,7 +347,7 @@ export interface BeforeAgentStartEvent {
347
347
  images?: ImageContent[];
348
348
  systemPrompt: string[];
349
349
  }
350
- export type { AgentEndEvent, AgentStartEvent, TurnEndEvent, TurnStartEvent } from "../shared-events";
350
+ export type { AgentEndEvent, AgentStartEvent, SessionStopEvent, SessionStopEventResult, TurnEndEvent, TurnStartEvent, } from "../shared-events";
351
351
  /** Fired when a message starts (user, assistant, or toolResult) */
352
352
  export interface MessageStartEvent {
353
353
  type: "message_start";
@@ -542,7 +542,7 @@ export declare function isToolCallEventType<TName extends string, TInput extends
542
542
  input: TInput;
543
543
  };
544
544
  /** Union of all event types */
545
- export type ExtensionEvent = ResourcesDiscoverEvent | SessionEvent | ContextEvent | BeforeProviderRequestEvent | AfterProviderResponseEvent | BeforeAgentStartEvent | AgentStartEvent | AgentEndEvent | TurnStartEvent | TurnEndEvent | MessageStartEvent | MessageUpdateEvent | MessageEndEvent | ToolExecutionStartEvent | ToolExecutionUpdateEvent | ToolExecutionEndEvent | AutoCompactionStartEvent | AutoCompactionEndEvent | AutoRetryStartEvent | AutoRetryEndEvent | TtsrTriggeredEvent | TodoReminderEvent | GoalUpdatedEvent | CredentialDisabledEvent | UserBashEvent | UserPythonEvent | InputEvent | ToolCallEvent | ToolResultEvent | ToolApprovalRequestedEvent | ToolApprovalResolvedEvent;
545
+ export type ExtensionEvent = ResourcesDiscoverEvent | SessionEvent | ContextEvent | BeforeProviderRequestEvent | AfterProviderResponseEvent | BeforeAgentStartEvent | AgentStartEvent | AgentEndEvent | SessionStopEvent | TurnStartEvent | TurnEndEvent | MessageStartEvent | MessageUpdateEvent | MessageEndEvent | ToolExecutionStartEvent | ToolExecutionUpdateEvent | ToolExecutionEndEvent | AutoCompactionStartEvent | AutoCompactionEndEvent | AutoRetryStartEvent | AutoRetryEndEvent | TtsrTriggeredEvent | TodoReminderEvent | GoalUpdatedEvent | CredentialDisabledEvent | UserBashEvent | UserPythonEvent | InputEvent | ToolCallEvent | ToolResultEvent | ToolApprovalRequestedEvent | ToolApprovalResolvedEvent;
546
546
  export interface ContextEventResult {
547
547
  messages?: AgentMessage[];
548
548
  }
@@ -623,6 +623,7 @@ export interface ExtensionAPI {
623
623
  on(event: "before_agent_start", handler: ExtensionHandler<BeforeAgentStartEvent, BeforeAgentStartEventResult>): void;
624
624
  on(event: "agent_start", handler: ExtensionHandler<AgentStartEvent>): void;
625
625
  on(event: "agent_end", handler: ExtensionHandler<AgentEndEvent>): void;
626
+ on(event: "session_stop", handler: ExtensionHandler<SessionStopEvent, SessionStopEventResult>): void;
626
627
  on(event: "turn_start", handler: ExtensionHandler<TurnStartEvent>): void;
627
628
  on(event: "turn_end", handler: ExtensionHandler<TurnEndEvent>): void;
628
629
  on(event: "message_start", handler: ExtensionHandler<MessageStartEvent>): void;
@@ -79,6 +79,16 @@ export interface SessionCompactEvent {
79
79
  export interface SessionShutdownEvent {
80
80
  type: "session_shutdown";
81
81
  }
82
+ /** Fired when a main-agent turn is about to settle; handlers may request one continuation turn. */
83
+ export interface SessionStopEvent {
84
+ type: "session_stop";
85
+ messages: AgentMessage[];
86
+ turn_id: number;
87
+ last_assistant_message?: AgentMessage;
88
+ session_id: string;
89
+ session_file?: string;
90
+ stop_hook_active: boolean;
91
+ }
82
92
  /** Preparation data for tree navigation (used by session_before_tree event) */
83
93
  export interface TreePreparation {
84
94
  /** Node being switched to */
@@ -118,7 +128,7 @@ export interface GoalUpdatedEvent {
118
128
  goal: Goal | null;
119
129
  state?: GoalModeState;
120
130
  }
121
- export type SessionEvent = SessionStartEvent | SessionBeforeSwitchEvent | SessionSwitchEvent | SessionBeforeBranchEvent | SessionBranchEvent | SessionBeforeCompactEvent | SessionCompactingEvent | SessionCompactEvent | SessionShutdownEvent | SessionBeforeTreeEvent | SessionTreeEvent | GoalUpdatedEvent;
131
+ export type SessionEvent = SessionStartEvent | SessionBeforeSwitchEvent | SessionSwitchEvent | SessionBeforeBranchEvent | SessionBranchEvent | SessionBeforeCompactEvent | SessionCompactingEvent | SessionCompactEvent | SessionStopEvent | SessionShutdownEvent | SessionBeforeTreeEvent | SessionTreeEvent | GoalUpdatedEvent;
122
132
  /**
123
133
  * Fired before each LLM call.
124
134
  *
@@ -264,6 +274,17 @@ export interface SessionCompactingResult {
264
274
  /** Custom data to store in compaction entry */
265
275
  preserveData?: Record<string, unknown>;
266
276
  }
277
+ /** Return type for `session_stop` handlers */
278
+ export interface SessionStopEventResult {
279
+ /** Continue the main session with additional context before settling */
280
+ continue?: boolean;
281
+ /** OMP-native model-visible context for the continuation */
282
+ additionalContext?: string;
283
+ /** Claude/Codex-compatible block decision; maps to a continuation */
284
+ decision?: "block";
285
+ /** Claude/Codex-compatible model-visible continuation reason */
286
+ reason?: string;
287
+ }
267
288
  /** Return type for `session_before_tree` handlers */
268
289
  export interface SessionBeforeTreeResult {
269
290
  /** If true, cancel the navigation entirely */
@@ -10,6 +10,7 @@ import type { AuthStorage } from "./session/auth-storage";
10
10
  import { type SessionInfo } from "./session/session-listing";
11
11
  import { SessionManager } from "./session/session-manager";
12
12
  type RunAcpMode = (createSession: AcpSessionFactory) => Promise<never>;
13
+ export declare function writeStartupNotice(parsedArgs: Pick<Args, "mode">, text: string): void;
13
14
  export interface InteractiveModeNotify {
14
15
  kind: "warn" | "error" | "info";
15
16
  message: string;
@@ -50,7 +50,7 @@ export declare class StatusLineComponent implements Component {
50
50
  * for unit tests and the collab host's state broadcast.
51
51
  */
52
52
  getCachedContextBreakdown(): {
53
- usedTokens: number | null;
53
+ usedTokens: number;
54
54
  contextWindow: number;
55
55
  };
56
56
  getTopBorder(width: number): {
@@ -4,7 +4,6 @@ export declare function getContextUsageLevel(contextPercent: number, contextWind
4
4
  /**
5
5
  * Format context usage as `<percent>%/<window>` (e.g. `5.1%/1M`), matching the
6
6
  * status line's context gauge so subagent and footer renderers stay in sync.
7
- * A `null`/`undefined` percent (unknown, e.g. right after compaction) renders as `?`.
8
7
  */
9
8
  export declare function formatContextUsage(contextPercent: number | null | undefined, contextWindow: number): string;
10
9
  export declare function getContextUsageThemeColor(level: ContextUsageLevel): ThemeColor;
@@ -188,7 +188,7 @@ export interface RpcSessionState {
188
188
  parameters: unknown;
189
189
  examples?: readonly ToolExample[];
190
190
  }>;
191
- /** Current context window usage. Null tokens/percent when unknown (e.g. right after compaction). */
191
+ /** Current context window usage. */
192
192
  contextUsage?: ContextUsage;
193
193
  }
194
194
  export interface RpcAvailableSlashCommand {
@@ -37,6 +37,18 @@ export declare function estimateToolSchemaTokens(tools: ReadonlyArray<Pick<Tool,
37
37
  * messages walked incrementally as new entries append.
38
38
  */
39
39
  export declare function computeNonMessageTokens(session: AgentSession): number;
40
+ /**
41
+ * Shared helper for the four non-message token totals used by
42
+ * `computeContextBreakdown` (/context panel). Keep this category split stable:
43
+ * the status-line fast path intentionally uses the equivalent collapsed total
44
+ * in `computeNonMessageTokens`.
45
+ */
46
+ export declare function computeNonMessageBreakdown(session: AgentSession): {
47
+ skillsTokens: number;
48
+ toolsTokens: number;
49
+ systemContextTokens: number;
50
+ systemPromptTokens: number;
51
+ };
40
52
  /**
41
53
  * Compute a breakdown of estimated context usage by category for the active
42
54
  * session and model.
@@ -55,6 +55,8 @@ export interface CreateAgentSessionOptions {
55
55
  providerSessionId?: string;
56
56
  /** Optional provider-facing prompt cache key, distinct from request lineage. */
57
57
  providerPromptCacheKey?: string;
58
+ /** Absolute wall-clock deadline in Unix epoch milliseconds. */
59
+ deadline?: number;
58
60
  /** Custom tools to register (in addition to built-in tools). Accepts both CustomTool and ToolDefinition. */
59
61
  customTools?: (CustomTool | ToolDefinition)[];
60
62
  /** Inline extensions (merged with discovery). */
@@ -193,7 +195,7 @@ export interface CreateAgentSessionResult {
193
195
  eventBus: EventBus;
194
196
  }
195
197
  export type DialectFormat = "auto" | "native" | Dialect;
196
- export declare function resolveDialect(format: DialectFormat, model: Pick<Model, "supportsTools"> | undefined): Dialect | undefined;
198
+ export declare function resolveDialect(format: DialectFormat, model: (Pick<Model, "supportsTools"> & Partial<Pick<Model, "id">>) | undefined): Dialect | undefined;
197
199
  export type { PromptTemplate } from "./config/prompt-templates";
198
200
  export { Settings, type SkillsSettings } from "./config/settings";
199
201
  export type { CustomCommand, CustomCommandFactory } from "./extensibility/custom-commands/types";
@@ -297,6 +297,16 @@ export interface RoleModelCycle {
297
297
  models: ResolvedRoleModel[];
298
298
  currentIndex: number;
299
299
  }
300
+ export interface ContextUsageBreakdown {
301
+ contextWindow: number;
302
+ anchored: boolean;
303
+ usedTokens: number;
304
+ systemPromptTokens: number;
305
+ systemToolsTokens: number;
306
+ systemContextTokens: number;
307
+ skillsTokens: number;
308
+ messagesTokens: number;
309
+ }
300
310
  /** Session statistics for /session command */
301
311
  export interface SessionStats {
302
312
  sessionFile: string | undefined;
@@ -1102,9 +1112,19 @@ export declare class AgentSession {
1102
1112
  * Uses the last assistant message's usage data when available,
1103
1113
  * otherwise estimates tokens for all messages.
1104
1114
  */
1115
+ getContextBreakdown(options?: {
1116
+ contextWindow?: number;
1117
+ pendingMessages?: AgentMessage[];
1118
+ }): ContextUsageBreakdown | undefined;
1105
1119
  getContextUsage(options?: {
1106
1120
  contextWindow?: number;
1107
1121
  }): ContextUsage | undefined;
1122
+ /**
1123
+ * Monotonic counter that changes whenever the in-flight pending context
1124
+ * snapshot is set or cleared. Status-line context memoization keys on this so
1125
+ * a value computed mid-turn cannot persist after the turn ends/aborts.
1126
+ */
1127
+ get contextUsageRevision(): number;
1108
1128
  fetchUsageReports(signal?: AbortSignal): Promise<UsageReport[] | null>;
1109
1129
  /**
1110
1130
  * Redeem one saved Codex rate-limit reset for a specific account, injecting
@@ -5,4 +5,8 @@ export declare function isImageBlock(value: unknown): value is {
5
5
  data: string;
6
6
  mimeType?: string;
7
7
  };
8
+ export declare function isImageDataPayload(value: unknown): value is {
9
+ data: string;
10
+ mimeType?: string;
11
+ };
8
12
  export declare function prepareEntryForPersistence(entry: FileEntry, blobStore: BlobStore): FileEntry;
@@ -31,6 +31,7 @@ export interface ReadToolDetails {
31
31
  displayContent?: {
32
32
  text: string;
33
33
  startLine: number;
34
+ lineNumbers?: Array<number | null>;
34
35
  };
35
36
  summary?: {
36
37
  lines: number;
@@ -19,6 +19,8 @@ export interface CodeCellOptions {
19
19
  codeTail?: boolean;
20
20
  expanded?: boolean;
21
21
  width: number;
22
+ codeStartLine?: number;
23
+ codeLineNumbers?: Array<number | null>;
22
24
  }
23
25
  export declare function renderCodeCell(options: CodeCellOptions, theme: Theme): string[];
24
26
  export interface MarkdownCellOptions {
@@ -0,0 +1,28 @@
1
+ import { type AgentTelemetryConfig } from "@oh-my-pi/pi-agent-core";
2
+ import type { Api, completeSimple, ImageContent, Model, TextContent } from "@oh-my-pi/pi-ai";
3
+ import type { ModelRegistry } from "../config/model-registry";
4
+ import type { Settings } from "../config/settings";
5
+ import { type LocalProtocolOptions } from "../internal-urls";
6
+ /** Registry surface needed to resolve a vision model and authorize requests. */
7
+ export type VisionFallbackRegistry = Pick<ModelRegistry, "getAvailable" | "getApiKey" | "resolver"> & Partial<Pick<ModelRegistry, "resolveCanonicalModel" | "getCanonicalVariants" | "getCanonicalId">>;
8
+ export interface DescribeAttachedImagesDeps {
9
+ /** Active (text-only) model the prompt is destined for. */
10
+ activeModel: Model<Api>;
11
+ modelRegistry: VisionFallbackRegistry;
12
+ settings: Settings;
13
+ /** Inputs for resolving the session-scoped `local://` root. */
14
+ localProtocolOptions: LocalProtocolOptions;
15
+ /** `provider/id` of the active model; a last-resort vision-model candidate (filtered to image-capable). */
16
+ activeModelString?: string;
17
+ telemetryConfig?: AgentTelemetryConfig;
18
+ sessionId?: string;
19
+ /** Test seam: overrides the underlying completeSimple call. */
20
+ completeImpl?: typeof completeSimple;
21
+ }
22
+ /**
23
+ * Save each attached image under `local://` and replace it with a descriptive
24
+ * text block. Returns one {@link TextContent} per input image, in order. Never
25
+ * throws for an individual image: a failed description falls back to a note while
26
+ * the saved-path block is still emitted.
27
+ */
28
+ export declare function describeAttachedImagesForTextModel(images: readonly ImageContent[], deps: DescribeAttachedImagesDeps, signal?: AbortSignal): Promise<TextContent[]>;
@@ -50,6 +50,7 @@ export interface SearchParams {
50
50
  * caller's agent session when available; otherwise omit.
51
51
  */
52
52
  sessionId?: string;
53
+ antigravityEndpointMode?: "auto" | "production" | "sandbox";
53
54
  }
54
55
  /** Base class for web search providers. */
55
56
  export declare abstract class SearchProvider {
@@ -31,6 +31,7 @@ export interface GeminiSearchParams extends GeminiToolParams {
31
31
  authStorage: AuthStorage;
32
32
  sessionId?: string;
33
33
  fetch?: FetchImpl;
34
+ antigravityEndpointMode?: "auto" | "production" | "sandbox";
34
35
  }
35
36
  export declare function buildGeminiRequestTools(params: GeminiToolParams): Array<Record<string, Record<string, unknown>>>;
36
37
  /** First configured Gemini OAuth provider plus its pre-resolved access. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "16.0.3",
4
+ "version": "16.0.5",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -47,17 +47,17 @@
47
47
  "@agentclientprotocol/sdk": "0.25.0",
48
48
  "@babel/parser": "^7.29.7",
49
49
  "@mozilla/readability": "^0.6.0",
50
- "@oh-my-pi/hashline": "16.0.3",
51
- "@oh-my-pi/omp-stats": "16.0.3",
52
- "@oh-my-pi/pi-agent-core": "16.0.3",
53
- "@oh-my-pi/pi-ai": "16.0.3",
54
- "@oh-my-pi/pi-catalog": "16.0.3",
55
- "@oh-my-pi/pi-mnemopi": "16.0.3",
56
- "@oh-my-pi/pi-natives": "16.0.3",
57
- "@oh-my-pi/pi-tui": "16.0.3",
58
- "@oh-my-pi/pi-utils": "16.0.3",
59
- "@oh-my-pi/pi-wire": "16.0.3",
60
- "@oh-my-pi/snapcompact": "16.0.3",
50
+ "@oh-my-pi/hashline": "16.0.5",
51
+ "@oh-my-pi/omp-stats": "16.0.5",
52
+ "@oh-my-pi/pi-agent-core": "16.0.5",
53
+ "@oh-my-pi/pi-ai": "16.0.5",
54
+ "@oh-my-pi/pi-catalog": "16.0.5",
55
+ "@oh-my-pi/pi-mnemopi": "16.0.5",
56
+ "@oh-my-pi/pi-natives": "16.0.5",
57
+ "@oh-my-pi/pi-tui": "16.0.5",
58
+ "@oh-my-pi/pi-utils": "16.0.5",
59
+ "@oh-my-pi/pi-wire": "16.0.5",
60
+ "@oh-my-pi/snapcompact": "16.0.5",
61
61
  "@opentelemetry/api": "^1.9.1",
62
62
  "@opentelemetry/context-async-hooks": "^2.7.1",
63
63
  "@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",