@oh-my-pi/pi-coding-agent 16.3.4 → 16.3.6

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 (88) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/cli.js +3522 -3485
  3. package/dist/types/edit/file-snapshot-store.d.ts +4 -2
  4. package/dist/types/edit/renderer.d.ts +0 -1
  5. package/dist/types/extensibility/custom-tools/types.d.ts +2 -0
  6. package/dist/types/extensibility/shared-events.d.ts +8 -1
  7. package/dist/types/hindsight/content.d.ts +4 -0
  8. package/dist/types/internal-urls/artifact-protocol.d.ts +8 -0
  9. package/dist/types/internal-urls/types.d.ts +10 -0
  10. package/dist/types/lsp/config.d.ts +4 -0
  11. package/dist/types/lsp/edits.d.ts +2 -0
  12. package/dist/types/mcp/oauth-discovery.d.ts +30 -0
  13. package/dist/types/modes/components/assistant-message.d.ts +15 -10
  14. package/dist/types/modes/components/bash-execution.d.ts +6 -0
  15. package/dist/types/modes/components/eval-execution.d.ts +6 -0
  16. package/dist/types/modes/components/login-dialog.d.ts +10 -2
  17. package/dist/types/modes/components/tool-execution.d.ts +3 -13
  18. package/dist/types/modes/components/transcript-container.d.ts +26 -29
  19. package/dist/types/modes/controllers/mcp-command-controller.d.ts +20 -3
  20. package/dist/types/modes/rpc/rpc-client.d.ts +7 -3
  21. package/dist/types/modes/rpc/rpc-types.d.ts +6 -0
  22. package/dist/types/modes/utils/transcript-render-helpers.d.ts +15 -6
  23. package/dist/types/session/agent-session.d.ts +2 -0
  24. package/dist/types/subprocess/worker-runtime.d.ts +11 -0
  25. package/dist/types/tools/bash-skill-urls.d.ts +2 -2
  26. package/dist/types/tools/bash.d.ts +0 -2
  27. package/dist/types/tools/browser/tab-supervisor.d.ts +10 -0
  28. package/dist/types/tools/eval-render.d.ts +0 -2
  29. package/dist/types/tools/renderers.d.ts +0 -20
  30. package/dist/types/tools/ssh.d.ts +0 -2
  31. package/dist/types/tools/write.d.ts +1 -1
  32. package/dist/types/utils/git.d.ts +16 -0
  33. package/package.json +12 -12
  34. package/src/cli/auth-broker-cli.ts +13 -2
  35. package/src/cli/tiny-models-cli.ts +12 -5
  36. package/src/edit/file-snapshot-store.ts +5 -2
  37. package/src/edit/renderer.ts +0 -5
  38. package/src/extensibility/custom-tools/types.ts +2 -0
  39. package/src/extensibility/shared-events.ts +9 -1
  40. package/src/hindsight/content.ts +31 -0
  41. package/src/internal-urls/artifact-protocol.ts +97 -53
  42. package/src/internal-urls/types.ts +10 -0
  43. package/src/lsp/config.ts +15 -0
  44. package/src/lsp/edits.ts +28 -7
  45. package/src/lsp/index.ts +46 -4
  46. package/src/mcp/oauth-discovery.ts +88 -18
  47. package/src/mnemopi/state.ts +26 -2
  48. package/src/modes/components/assistant-message.ts +134 -82
  49. package/src/modes/components/bash-execution.ts +9 -0
  50. package/src/modes/components/chat-transcript-builder.ts +8 -4
  51. package/src/modes/components/eval-execution.ts +9 -0
  52. package/src/modes/components/login-dialog.ts +16 -2
  53. package/src/modes/components/mcp-add-wizard.ts +9 -1
  54. package/src/modes/components/tool-execution.ts +4 -50
  55. package/src/modes/components/transcript-container.ts +82 -458
  56. package/src/modes/components/tree-selector.ts +9 -3
  57. package/src/modes/controllers/command-controller.ts +0 -3
  58. package/src/modes/controllers/event-controller.ts +74 -14
  59. package/src/modes/controllers/extension-ui-controller.ts +0 -1
  60. package/src/modes/controllers/input-controller.ts +4 -10
  61. package/src/modes/controllers/mcp-command-controller.ts +106 -29
  62. package/src/modes/controllers/selector-controller.ts +9 -1
  63. package/src/modes/interactive-mode.ts +12 -8
  64. package/src/modes/rpc/rpc-client.ts +8 -4
  65. package/src/modes/rpc/rpc-mode.ts +1 -0
  66. package/src/modes/rpc/rpc-types.ts +13 -1
  67. package/src/modes/setup-wizard/scenes/sign-in.ts +18 -0
  68. package/src/modes/utils/transcript-render-helpers.ts +40 -13
  69. package/src/modes/utils/ui-helpers.ts +12 -7
  70. package/src/prompts/tools/read.md +1 -1
  71. package/src/sdk.ts +1 -0
  72. package/src/session/agent-session.ts +148 -1
  73. package/src/session/session-context.ts +7 -0
  74. package/src/subprocess/worker-runtime.ts +219 -2
  75. package/src/task/worktree.ts +28 -6
  76. package/src/tiny/worker.ts +14 -4
  77. package/src/tools/bash-skill-urls.ts +3 -3
  78. package/src/tools/bash.ts +0 -4
  79. package/src/tools/browser/tab-supervisor.ts +47 -3
  80. package/src/tools/eval-render.ts +0 -20
  81. package/src/tools/grep.ts +19 -2
  82. package/src/tools/path-utils.ts +4 -0
  83. package/src/tools/read.ts +261 -21
  84. package/src/tools/renderers.ts +0 -20
  85. package/src/tools/ssh.ts +0 -16
  86. package/src/tools/write.ts +13 -6
  87. package/src/utils/git.ts +20 -0
  88. package/src/utils/open.ts +51 -6
@@ -42,9 +42,11 @@ export declare function canonicalSnapshotKey(absolutePath: string): string;
42
42
  * Producers that only displayed a slice of the file (range reads, search hits)
43
43
  * use this to mint a whole-file tag: the displayed lines stay partial, but the
44
44
  * tag fingerprints the entire file so a follow-up edit anchored at any line
45
- * validates whenever the live file is byte-identical to what was read.
45
+ * validates whenever the live file is byte-identical to what was read. Raw
46
+ * reads pass `seenLines` even though they do not emit a header, letting a prior
47
+ * or later same-content hashline tag inherit the raw range's provenance.
46
48
  */
47
- export declare function recordFileSnapshot(session: FileSnapshotStoreOwner, absolutePath: string): Promise<string | undefined>;
49
+ export declare function recordFileSnapshot(session: FileSnapshotStoreOwner, absolutePath: string, seenLines?: Iterable<number>): Promise<string | undefined>;
48
50
  /**
49
51
  * The 1-indexed file lines a hashline-formatted body actually displayed.
50
52
  * Single `NN:` rows contribute that line; a collapsed summary `NN-MM:` row
@@ -102,7 +102,6 @@ export interface EditRenderContext {
102
102
  }
103
103
  export declare const editToolRenderer: {
104
104
  mergeCallAndResult: boolean;
105
- provisionalPendingPreview: boolean;
106
105
  renderCall(args: EditRenderArgs, options: RenderResultOptions & {
107
106
  renderContext?: EditRenderContext;
108
107
  }, uiTheme: Theme): Component;
@@ -20,6 +20,7 @@ import type * as PiCodingAgent from "../../index";
20
20
  import type { Theme } from "../../modes/theme/theme";
21
21
  import type { ReadonlySessionManager } from "../../session/session-manager";
22
22
  import type { TodoItem } from "../../tools/todo";
23
+ import type { RecoveredRetryError } from "../shared-events";
23
24
  import type * as TypeBox from "../typebox";
24
25
  /** Alias for clarity */
25
26
  export type CustomToolUIContext = HookUIContext;
@@ -115,6 +116,7 @@ export type CustomToolSessionEvent = {
115
116
  success: boolean;
116
117
  attempt: number;
117
118
  finalError?: string;
119
+ recoveredErrors?: RecoveredRetryError[];
118
120
  } | {
119
121
  reason: "ttsr_triggered";
120
122
  rules: Rule[];
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
16
16
  import type { CompactionPreparation, CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
17
- import type { ImageContent, TextContent, ToolResultMessage } from "@oh-my-pi/pi-ai";
17
+ import type { AssistantRetryRecovery, ImageContent, TextContent, ToolResultMessage } from "@oh-my-pi/pi-ai";
18
18
  import type { Rule } from "../capability/rule";
19
19
  import type { Goal, GoalModeState } from "../goals/state";
20
20
  import type { BranchSummaryEntry, CompactionEntry, SessionEntry } from "../session/session-entries";
@@ -192,12 +192,19 @@ export interface AutoRetryStartEvent {
192
192
  errorMessage: string;
193
193
  errorId?: number;
194
194
  }
195
+ export interface RecoveredRetryError {
196
+ entryId: string;
197
+ persistenceKey?: string;
198
+ note: string;
199
+ retryRecovery: AssistantRetryRecovery;
200
+ }
195
201
  /** Fired when auto-retry ends */
196
202
  export interface AutoRetryEndEvent {
197
203
  type: "auto_retry_end";
198
204
  success: boolean;
199
205
  attempt: number;
200
206
  finalError?: string;
207
+ recoveredErrors?: RecoveredRetryError[];
201
208
  }
202
209
  /** Fired when TTSR rule matching interrupts generation */
203
210
  export interface TtsrTriggeredEvent {
@@ -64,6 +64,10 @@ export interface RetentionTranscript {
64
64
  transcript: string | null;
65
65
  messageCount: number;
66
66
  }
67
+ /** Remove retention framing lines from a stored coding-agent episode transcript. */
68
+ export declare function stripRetentionProtocolMarkers(content: string): string;
67
69
  export declare function prepareRetentionTranscript(messages: HindsightMessage[], retainFullWindow?: boolean): RetentionTranscript;
70
+ /** Format all retention messages without protocol markers for embedding, FTS, and recall display. */
71
+ export declare function prepareEmbeddableRetentionTranscript(messages: HindsightMessage[]): RetentionTranscript;
68
72
  /** Format only user-authored messages for memory fact/entity extraction. */
69
73
  export declare function prepareUserRetentionTranscript(messages: HindsightMessage[]): RetentionTranscript;
@@ -1,4 +1,12 @@
1
1
  import type { InternalResource, InternalUrl, ProtocolHandler, ResolveContext, UrlCompletion } from "./types";
2
+ /** Filesystem location for a session artifact, resolved without materializing its content. */
3
+ export interface ResolvedArtifactFile {
4
+ id: string;
5
+ path: string;
6
+ size: number;
7
+ }
8
+ /** Resolve an `artifact://` URL to its backing file without reading artifact bytes. */
9
+ export declare function resolveArtifactFile(url: InternalUrl, context?: ResolveContext): Promise<ResolvedArtifactFile>;
2
10
  export declare class ArtifactProtocolHandler implements ProtocolHandler {
3
11
  readonly scheme = "artifact";
4
12
  readonly immutable = true;
@@ -102,6 +102,16 @@ export interface ResolveContext {
102
102
  * reject directory resources, so they never need the listing.
103
103
  */
104
104
  skipDirectoryListing?: boolean;
105
+ /**
106
+ * When set, handlers that would otherwise materialize expensive content
107
+ * (e.g. reading a multi-MiB artifact into memory just to expose its
108
+ * `sourcePath`) may return the resource shape without content. Callers
109
+ * that only need `sourcePath` — search/grep, bash URL expansion — pass
110
+ * this so a large `artifact://` still resolves to its backing file
111
+ * without OOM risk. Handlers that cannot separate path from content
112
+ * ignore the flag.
113
+ */
114
+ pathOnly?: boolean;
105
115
  }
106
116
  /**
107
117
  * Caller context for write operations dispatched to host-owned URI handlers.
@@ -8,6 +8,10 @@ export interface LspConfig {
8
8
  * Check if any root marker file exists in the directory
9
9
  */
10
10
  export declare function hasRootMarkers(cwd: string, markers: string[]): boolean;
11
+ /**
12
+ * Check whether any ancestor directory of a file is an LSP project root.
13
+ */
14
+ export declare function hasRootMarkerAncestor(filePath: string, markers: string[]): boolean;
11
15
  /**
12
16
  * Resolve a command to an executable path.
13
17
  * Checks project-local bin directories first, then falls back to $PATH.
@@ -11,6 +11,8 @@ export declare function rangesOverlap(a: Range, b: Range): boolean;
11
11
  * Equal start positions tiebreak by original array index descending so that,
12
12
  * applied bottom-up, inserts at the same position land in array order
13
13
  * (LSP spec: the order of edits in the array defines the order in the result).
14
+ * Byte-identical non-empty range edits are idempotent, so duplicate server
15
+ * output is collapsed before overlap validation.
14
16
  */
15
17
  export declare function sortAndValidateTextEdits(edits: TextEdit[]): TextEdit[];
16
18
  /**
@@ -12,9 +12,26 @@ export interface AuthDetectionResult {
12
12
  oauth?: OAuthEndpoints;
13
13
  authServerUrl?: string;
14
14
  resourceMetadataUrl?: string;
15
+ /**
16
+ * OAuth scopes advertised by the challenge (RFC 6750 `scope=` on
17
+ * `WWW-Authenticate`) or by protected-resource metadata. Passed through
18
+ * `discoverOAuthEndpoints` as `protectedScopes` so the eventual
19
+ * authorization request carries them even when the auth-server metadata
20
+ * document itself omits `scopes_supported`.
21
+ */
22
+ scopes?: string;
15
23
  message?: string;
16
24
  }
17
25
  export declare function extractMcpAuthServerUrl(error: Error, serverUrl?: string): string | undefined;
26
+ /**
27
+ * Pull the `scope`/`scopes` parameter out of a `WWW-Authenticate` challenge
28
+ * embedded in the error message. RFC 6750 lets servers advertise the missing
29
+ * scopes when they reject a bearer token with `insufficient_scope`, and RFC
30
+ * 8414-adjacent MCP gateways sometimes list the required scopes there rather
31
+ * than in `scopes_supported`. Returns the raw space-separated value, or
32
+ * `undefined` when the challenge does not carry one.
33
+ */
34
+ export declare function extractOAuthChallengeScopes(error: Error): string | undefined;
18
35
  /**
19
36
  * Extract OAuth endpoints from error response.
20
37
  * Looks for WWW-Authenticate header format or JSON error bodies.
@@ -25,6 +42,18 @@ export declare function extractOAuthEndpoints(error: Error): OAuthEndpoints | nu
25
42
  * Returns structured info about what auth is needed.
26
43
  */
27
44
  export declare function analyzeAuthError(error: Error, serverUrl?: string): AuthDetectionResult;
45
+ /**
46
+ * Fetch the RFC 9728 protected-resource metadata document at
47
+ * {@link resourceMetadataUrl} and return any scopes it advertises. Used by
48
+ * `/mcp add` / `/mcp reauth` on the JSON-error-body path, where the caller
49
+ * already holds usable OAuth endpoints but the required scopes live only in
50
+ * the advertised protected-resource metadata — a case `discoverOAuthEndpoints`
51
+ * normally handles but that path is skipped when the body carried endpoints.
52
+ * Returns `undefined` on any error or when no scopes are advertised.
53
+ */
54
+ export declare function fetchResourceMetadataScopes(resourceMetadataUrl: string, opts?: {
55
+ fetch?: FetchImpl;
56
+ }): Promise<string | undefined>;
28
57
  /**
29
58
  * Try to discover OAuth endpoints by querying the server's well-known endpoints.
30
59
  * This is a fallback when error responses don't include OAuth metadata.
@@ -32,4 +61,5 @@ export declare function analyzeAuthError(error: Error, serverUrl?: string): Auth
32
61
  export declare function discoverOAuthEndpoints(serverUrl: string, authServerUrl?: string, resourceMetadataUrl?: string, opts?: {
33
62
  fetch?: FetchImpl;
34
63
  protectedResource?: string;
64
+ protectedScopes?: string;
35
65
  }): Promise<OAuthEndpoints | null>;
@@ -23,6 +23,7 @@ export declare class AssistantMessageComponent extends Container {
23
23
  */
24
24
  setCacheInvalidation(info: CacheInvalidation | undefined): void;
25
25
  invalidate(): void;
26
+ render(width: number): readonly string[];
26
27
  setHideThinkingBlock(hide: boolean): void;
27
28
  setProseOnlyThinking(proseOnly: boolean): void;
28
29
  dispose(): void;
@@ -33,19 +34,23 @@ export declare class AssistantMessageComponent extends Container {
33
34
  setErrorPinned(pinned: boolean): void;
34
35
  isTranscriptBlockFinalized(): boolean;
35
36
  /**
36
- * Whether this still-live block's scrolled-off rows may be committed to
37
- * immutable native scrollback (the {@link TranscriptContainer} durable-
38
- * snapshot path). Reflowing Markdown a streaming mermaid diagram or a GFM
39
- * table re-lays-out its body as source arrives (the diagram reshapes, the
40
- * table re-aligns its columns), so committing an intermediate layout strands
41
- * a stale fragment in native scrollback that only a full repaint (Ctrl+L) can
42
- * clear. While such content is still streaming the block therefore stays
43
- * wholly in the repaintable live region and commits once, at its final
44
- * layout, when the turn finalizes.
37
+ * Settled leading rows for mid-stream native-scrollback commits (see
38
+ * `FinalizableBlock.getTranscriptBlockSettledRows`). Completed content
39
+ * blocks render in final form (non-transient) and settle in full; the
40
+ * actively streaming markdown contributes its rendered frozen-token
41
+ * prefix. The walk stops at the first child that is not declared
42
+ * byte-stable (the animated thinking pulse, extension components, images,
43
+ * error rows), and a cache-invalidation marker above the content defers
44
+ * settling entirely. Mermaid anywhere defers wholesale its ASCII
45
+ * rendering resolves asynchronously and can re-layout settled-looking
46
+ * rows. Reads only L1-cached child renders at the width recorded by this
47
+ * frame's render().
45
48
  */
46
- isTranscriptBlockCommitStable(): boolean;
49
+ getTranscriptBlockSettledRows(): number;
47
50
  getTranscriptBlockVersion(): number;
48
51
  markTranscriptBlockFinalized(): void;
52
+ applyRetryRecovery(retryRecovery: AssistantMessage["retryRecovery"]): void;
53
+ messagePersistenceKey(): string | undefined;
49
54
  setToolResultImages(toolCallId: string, images: ImageContent[]): void;
50
55
  updateContent(message: AssistantMessage, opts?: {
51
56
  transient?: boolean;
@@ -7,6 +7,12 @@ export declare class BashExecutionComponent extends Container {
7
7
  #private;
8
8
  private readonly command;
9
9
  constructor(command: string, ui: TUI, excludeFromContext?: boolean);
10
+ /**
11
+ * Transcript finalization contract (see `FinalizableBlock`): the collapsed
12
+ * streaming preview rewrites its tail window every chunk, so the block must
13
+ * stay out of native scrollback until the command completes.
14
+ */
15
+ isTranscriptBlockFinalized(): boolean;
10
16
  /**
11
17
  * Set whether the output is expanded (shows full output) or collapsed (preview only).
12
18
  */
@@ -11,6 +11,12 @@ export declare class EvalExecutionComponent extends Container {
11
11
  private readonly excludeFromContext;
12
12
  private readonly language;
13
13
  constructor(code: string, ui: TUI, excludeFromContext?: boolean, language?: EvalExecutionLanguage);
14
+ /**
15
+ * Transcript finalization contract (see `FinalizableBlock`): the collapsed
16
+ * streaming preview rewrites its tail window every chunk, so the block must
17
+ * stay out of native scrollback until the cell completes.
18
+ */
19
+ isTranscriptBlockFinalized(): boolean;
14
20
  setExpanded(expanded: boolean): void;
15
21
  invalidate(): void;
16
22
  appendOutput(chunk: string): void;
@@ -8,9 +8,17 @@ export declare class LoginDialogComponent extends Container {
8
8
  constructor(tui: TUI, providerId: string, onComplete: (success: boolean, message?: string) => void);
9
9
  get signal(): AbortSignal;
10
10
  /**
11
- * Called by onAuth callback - show URL and optional instructions
11
+ * Called by the OAuth `onAuth` callback. Renders the full authorization URL
12
+ * as the primary copy target — that works from any machine, including
13
+ * SSH/WSL/headless sessions where the OMP-hosted `launchUrl` would resolve
14
+ * against the user's local browser and fail. When `launchUrl` is present it
15
+ * is offered as an additional local shortcut so narrow local terminals still
16
+ * have a truncation-safe copy target (viewport clipping on a long authorize
17
+ * URL silently drops trailing OAuth query parameters — e.g.
18
+ * `code_challenge_method=S256`). The OSC 8 hyperlink carries the full URL
19
+ * for terminals that support click-through.
12
20
  */
13
- showAuth(url: string, instructions?: string): void;
21
+ showAuth(url: string, instructions?: string, launchUrl?: string): void;
14
22
  /**
15
23
  * Show input for manual code/URL entry (for callback server providers)
16
24
  */
@@ -78,9 +78,9 @@ export declare class ToolExecutionComponent extends Container implements NativeS
78
78
  /**
79
79
  * Standalone harnesses may mount a tool component directly under `TUI`
80
80
  * instead of inside `TranscriptContainer`. In that shape the component must
81
- * report its own live-region seam for provisional previews, or the core
82
- * renderer treats it like shell output and commits tail-window edit/eval/bash
83
- * previews to immutable native scrollback before the result replaces them.
81
+ * report its own live-region seam while unfinalized, or the core renderer
82
+ * treats it like shell output and commits still-mutating preview rows to
83
+ * immutable native scrollback before the result replaces them.
84
84
  */
85
85
  getNativeScrollbackLiveRegionStart(): number | undefined;
86
86
  /**
@@ -92,16 +92,6 @@ export declare class ToolExecutionComponent extends Container implements NativeS
92
92
  * past, or an explicit {@link seal} flips it to `true`.
93
93
  */
94
94
  isTranscriptBlockFinalized(): boolean;
95
- /**
96
- * Whether this still-live block's settled rows may enter native scrollback
97
- * (see `FinalizableBlock.isTranscriptBlockCommitStable`). Renderers classify
98
- * pending views by durability instead of by tool name: a provisional view is
99
- * allowed to be useful on screen, but finalization may replace or re-anchor
100
- * it wholesale, so committing any of its rows would strand stale preview
101
- * bytes in immutable scrollback. Non-provisional views stream rows whose
102
- * committed prefix survives the remaining transitions.
103
- */
104
- isTranscriptBlockCommitStable(): boolean;
105
95
  /**
106
96
  * Mark the tool terminal even though no result arrived (the turn aborted or
107
97
  * abandoned it) and stop animating, so it can freeze and stops pinning the
@@ -1,18 +1,20 @@
1
1
  import { type Component, Container, type NativeScrollbackCommittedRows, type NativeScrollbackLiveRegion, type RenderStablePrefix, type ViewportTailProvider } from "@oh-my-pi/pi-tui";
2
2
  /**
3
3
  * Transcript container that renders every block's current content each frame
4
- * and reports the live-region seam (`NativeScrollbackLiveRegion`) that gates
5
- * the engine's append-only scrollback commits.
4
+ * and reports the native-scrollback exactness boundary
5
+ * (`NativeScrollbackLiveRegion`): the frame row below which every rendered
6
+ * row is final. The boundary covers the leading run of finalized blocks plus
7
+ * the first still-live block's declared settled rows
8
+ * ({@link FinalizableBlock.getTranscriptBlockSettledRows}). Rows below it
9
+ * commit to native scrollback as exact, audited content; rows above it that
10
+ * scroll off the window commit as frozen visual snapshots the engine never
11
+ * re-anchors or recommits (the tape records what was on screen).
6
12
  *
7
- * The engine never rewrites committed history: rows above the seam that have
8
- * entered the tape keep whatever bytes they were committed with ("let the
9
- * history be"), while the visible window always repaints from each block's
10
- * latest render — a late tool result, a post-finalize error pin, or an expand
11
- * toggle is always reflected on screen. Blocks that are still mutating (an
12
- * unfinalized tool, a streaming assistant message) stay below the seam so
13
- * their rows do not enter history while they can still change; a streaming
14
- * block whose render grows append-only deepens the seam through its settled
15
- * head so a long reply's scrolled-off rows still reach scrollback mid-stream.
13
+ * The engine never rewrites committed history: rows that have entered the
14
+ * tape keep whatever bytes they were committed with ("let the history be"),
15
+ * while the visible window always repaints from each block's latest render —
16
+ * a late tool result, a post-finalize error pin, or an expand toggle is
17
+ * always reflected on screen while it remains in the window.
16
18
  *
17
19
  * Assembly is incremental: the returned array is persistent and mutated in
18
20
  * place. Each block's render is still called every frame, but a block whose
@@ -29,29 +31,24 @@ export declare class TranscriptContainer extends Container implements NativeScro
29
31
  setNativeScrollbackCommittedRows(rows: number): void;
30
32
  getRenderStablePrefixRows(): number;
31
33
  getNativeScrollbackLiveRegionStart(): number | undefined;
32
- getNativeScrollbackCommitSafeEnd(): number | undefined;
33
- getNativeScrollbackSnapshotSafeEnd(): number | undefined;
34
- getNativeScrollbackOfferSafeEnd(): number | undefined;
35
34
  /**
36
- * Whether `component` sits below a still-mutating block i.e. inside the
37
- * live region, where its rows cannot have been committed to native
38
- * scrollback yet (commits are prefix-only and stop at the first
39
- * still-live block). Callers that retract ephemeral blocks (IRC cards)
40
- * must check this: removing a block whose rows may already be in history
41
- * is an interior deletion of the committed prefix, which the engine can
42
- * only repair by recommitting everything below it — duplication.
35
+ * Whether none of `component`'s rows (per the most recent render) have
36
+ * entered native scrollback. Callers that retract ephemeral blocks (IRC
37
+ * cards, displaceable todo/job snapshots) must check this: removing a
38
+ * block whose rows are already on the tape is an interior deletion of
39
+ * committed history the engine cannot express the block must be sealed
40
+ * in place as history instead. A component that has never rendered has no
41
+ * committed rows and is safely removable.
43
42
  */
44
- isWithinLiveRegion(component: Component): boolean;
43
+ isBlockUncommitted(component: Component): boolean;
45
44
  /**
46
45
  * Whether `component` is inside the live (repaintable) region exactly as
47
46
  * {@link render} computes it: at/after the first still-mutating block, or
48
- * the transcript tail when every block has finalized. Unlike
49
- * {@link isWithinLiveRegion} (strictly below a still-mutating block, i.e.
50
- * guaranteed-uncommitted), this also counts the trailing block that anchors
51
- * the live region. Self-animating finalized blocks (a detached task's
52
- * shimmering progress rows) poll this to stop animating — and settle on
53
- * static bytes — the moment they sit above the seam, where their rows
54
- * become commit-eligible native-scrollback history.
47
+ * the transcript tail when every block has finalized. Self-animating
48
+ * finalized blocks (a detached task's shimmering progress rows) poll this
49
+ * to stop animating and settle on static bytes — the moment they sit
50
+ * above the seam, where their rows become commit-eligible native-scrollback
51
+ * history.
55
52
  */
56
53
  isBlockInLiveRegion(component: Component): boolean;
57
54
  /**
@@ -1,11 +1,28 @@
1
1
  import { type Component } from "@oh-my-pi/pi-tui";
2
2
  import type { InteractiveModeContext } from "../types";
3
- /** Renders the MCP OAuth fallback URL without hard-wrapping the copy target. */
3
+ /**
4
+ * Renders the MCP OAuth fallback URL. Always shows the full authorization URL
5
+ * as the primary `Copy URL:` target — that works from any machine, including
6
+ * SSH/WSL/headless sessions where the OMP-hosted `/launch` loopback URL would
7
+ * resolve against the user's local browser and fail.
8
+ *
9
+ * The render is `width`-aware: on any viewport narrower than the composed row
10
+ * ({@link TUI#prepareLine} truncates anything wider with `Ellipsis.Omit`, no
11
+ * marker), the URL is hard-wrapped into width-fitted rows so the primary copy
12
+ * target can never silently lose trailing OAuth parameters — the failure mode
13
+ * that motivated #4418 in the first place. Browsers strip whitespace when a
14
+ * multi-row selection is pasted into the address bar, so the reassembled URL
15
+ * is byte-identical to what we rendered.
16
+ *
17
+ * When the flow's callback server hosts a short `launchUrl`, it is offered
18
+ * as an additional local shortcut for wide-terminal local users. The OSC 8
19
+ * hyperlink continues to carry the full URL for terminals that support it.
20
+ */
4
21
  export declare class MCPAuthorizationLinkPrompt implements Component {
5
22
  #private;
6
- constructor(url: string);
23
+ constructor(url: string, launchUrl?: string);
7
24
  invalidate(): void;
8
- render(_width: number): readonly string[];
25
+ render(width: number): readonly string[];
9
26
  }
10
27
  /**
11
28
  * Thrown by {@link MCPCommandController}'s OAuth handler when the user (or a
@@ -271,11 +271,15 @@ export declare class RpcClient {
271
271
  * The server will emit an `open_url` extension_ui_request for the auth URL.
272
272
  * Resolves when login completes or rejects on failure.
273
273
  *
274
- * @param onOpenUrl Called when the server emits the auth URL. The host must open
275
- * it in a browser for the callback-server OAuth flow to complete.
274
+ * @param onOpenUrl Called when the server emits the auth URL. The host must
275
+ * open `url` in a browser for the callback-server OAuth flow to complete.
276
+ * When the flow's callback server hosts a `/launch` redirect, `launchUrl`
277
+ * is a short loopback URL that 302s to `url` — hosts SHOULD surface it as
278
+ * the truncation-safe copy target so terminal viewport clipping cannot
279
+ * corrupt trailing OAuth query parameters (e.g. `code_challenge_method=S256`).
276
280
  */
277
281
  login(providerId: string, options?: {
278
- onOpenUrl?: (url: string, instructions?: string) => void;
282
+ onOpenUrl?: (url: string, instructions?: string, launchUrl?: string) => void;
279
283
  }): Promise<{
280
284
  providerId: string;
281
285
  }>;
@@ -599,6 +599,12 @@ export type RpcExtensionUIRequest = {
599
599
  id: string;
600
600
  method: "open_url";
601
601
  url: string;
602
+ /**
603
+ * Short loopback URL that 302-redirects to {@link url}. When present,
604
+ * hosts SHOULD surface it as the copy target so terminal viewport
605
+ * truncation cannot corrupt OAuth query parameters on the full URL.
606
+ */
607
+ launchUrl?: string;
602
608
  instructions?: string;
603
609
  };
604
610
  export interface RpcHostToolDefinition {
@@ -43,12 +43,21 @@ export declare function assistantHasVisibleContent(message: AssistantAgentMessag
43
43
  * array values to an empty object.
44
44
  */
45
45
  export declare function normalizeToolArgs(args: unknown): Record<string, unknown>;
46
+ export type AssistantErrorPresentation = {
47
+ kind: "none";
48
+ } | {
49
+ kind: "full";
50
+ text: string;
51
+ isError: true;
52
+ } | {
53
+ kind: "compact-recovered";
54
+ text: string;
55
+ isError: false;
56
+ };
46
57
  /**
47
- * Resolve the inline error label, if any, for a turn-ending assistant message.
48
- * Silent aborts yield no label. `retryAttempt` tunes the abort label wording.
58
+ * Resolve the turn-ending assistant error presentation, if any.
59
+ * Silent and user-interrupt aborts yield no label. Recovered auto-retry errors
60
+ * collapse to a single non-error note; terminal errors keep the full red presentation.
49
61
  */
50
- export declare function resolveAssistantErrorMessage(message: AssistantAgentMessage, retryAttempt?: number): {
51
- hasErrorStop: boolean;
52
- errorMessage: string | null;
53
- };
62
+ export declare function resolveAssistantErrorPresentation(message: AssistantAgentMessage, retryAttempt?: number): AssistantErrorPresentation;
54
63
  export {};
@@ -33,6 +33,7 @@ import type { LoadedCustomCommand } from "../extensibility/custom-commands";
33
33
  import type { CustomTool } from "../extensibility/custom-tools/types";
34
34
  import type { ExtensionRunner } from "../extensibility/extensions";
35
35
  import type { CompactOptions, ContextUsage } from "../extensibility/extensions/types";
36
+ import type { RecoveredRetryError } from "../extensibility/shared-events";
36
37
  import type { Skill, SkillWarning } from "../extensibility/skills";
37
38
  import { type FileSlashCommand } from "../extensibility/slash-commands";
38
39
  import { GoalRuntime } from "../goals/runtime";
@@ -80,6 +81,7 @@ export type AgentSessionEvent = AgentEvent | {
80
81
  success: boolean;
81
82
  attempt: number;
82
83
  finalError?: string;
84
+ recoveredErrors?: RecoveredRetryError[];
83
85
  } | {
84
86
  type: "retry_fallback_applied";
85
87
  from: string;
@@ -69,6 +69,11 @@ export declare function replayCachedReady<K, M>(cache: Map<K, Promise<M>>, model
69
69
  * runtime's `node_modules` directory.
70
70
  */
71
71
  export declare function installSharpStubResolver(runtimeDir: string): Promise<string>;
72
+ /**
73
+ * Repairs the compiled Transformers side runtime when CUDA was requested and
74
+ * Bun skipped `onnxruntime-node`'s NuGet sidecar install.
75
+ */
76
+ export declare function ensureOnnxRuntimeCudaProviders(runtimeDir: string, device?: string | undefined): Promise<void>;
72
77
  /**
73
78
  * Lazily resolve (and memoize) the transformers version spec. In the `catalog:`
74
79
  * case {@link resolveTransformersVersionSpec} `require`s the installed
@@ -88,6 +93,12 @@ interface ConfigurableTransformers {
88
93
  ERROR: unknown;
89
94
  };
90
95
  }
96
+ export interface TransformersRuntimeMetadata {
97
+ __ompRuntimeNodeModules?: string;
98
+ __ompTransformersEntry?: string;
99
+ __ompCudaRepairError?: string;
100
+ }
101
+ export declare function formatOnnxRuntimeCudaDiagnostics(metadata: TransformersRuntimeMetadata, requestedDevice: string, error: unknown): Promise<string | null>;
91
102
  /**
92
103
  * Memoize an async runtime load so it runs at most once per process, clearing
93
104
  * the cache on failure so a later call can retry. Each worker holds one
@@ -1,9 +1,9 @@
1
1
  import type { Skill } from "../extensibility/skills";
2
2
  import { type LocalProtocolOptions } from "../internal-urls";
3
- import type { InternalResource } from "../internal-urls/types";
3
+ import type { InternalResource, ResolveContext } from "../internal-urls/types";
4
4
  interface InternalUrlResolver {
5
5
  canHandle(input: string): boolean;
6
- resolve(input: string): Promise<InternalResource>;
6
+ resolve(input: string, context?: ResolveContext): Promise<InternalResource>;
7
7
  }
8
8
  export interface InternalUrlExpansionOptions {
9
9
  skills: readonly Skill[];
@@ -154,7 +154,6 @@ export declare function createShellRenderer<TArgs>(config: ShellRendererConfig<T
154
154
  }, uiTheme: Theme, args?: TArgs): Component;
155
155
  mergeCallAndResult: boolean;
156
156
  inline: boolean;
157
- provisionalPendingPreview: string;
158
157
  };
159
158
  export declare const bashToolRenderer: {
160
159
  renderCall(args: BashRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component;
@@ -170,6 +169,5 @@ export declare const bashToolRenderer: {
170
169
  }, uiTheme: Theme, args?: BashRenderArgs | undefined): Component;
171
170
  mergeCallAndResult: boolean;
172
171
  inline: boolean;
173
- provisionalPendingPreview: string;
174
172
  };
175
173
  export {};
@@ -16,6 +16,16 @@ export interface PendingRun {
16
16
  session: ToolSession;
17
17
  signal?: AbortSignal;
18
18
  toolCalls: Map<string, AbortController>;
19
+ /**
20
+ * Fires when `releaseTab` closes the tab out from under an in-flight run
21
+ * (sibling `browser close --all`, session-scoped reap, etc.). Composed
22
+ * into the cmux run's signal so `wait(...)`, cmux socket calls, and the
23
+ * facade proxies unwind promptly instead of blocking to the run's
24
+ * timeout. `pending.reject` still fires first so the awaiting caller
25
+ * sees the tab-close error immediately; `closeAc` propagates the
26
+ * cancellation into the still-running `runCmuxCode` body (issue #4499).
27
+ */
28
+ closeAc?: AbortController;
19
29
  }
20
30
  interface TabSessionBase<TBrowser extends BrowserHandle = BrowserHandle> {
21
31
  name: string;
@@ -54,7 +54,5 @@ export declare const evalToolRenderer: {
54
54
  }, uiTheme: Theme, _args?: EvalRenderArgs): Component;
55
55
  mergeCallAndResult: boolean;
56
56
  inline: boolean;
57
- provisionalPendingPreview: string;
58
- provisionalPartialResult: boolean;
59
57
  };
60
58
  export {};
@@ -21,26 +21,6 @@ export type ToolRenderer = {
21
21
  mergeCallAndResult?: boolean;
22
22
  /** Render without background box, inline in the response flow */
23
23
  inline?: boolean;
24
- /**
25
- * Whether pending-call rows are provisional: useful on screen while a tool is
26
- * streaming, but not durable transcript history. `true` means every pending
27
- * shape is provisional. `"collapsed"` means only the collapsed pending shape
28
- * is provisional; expanded rendering is top-anchored/append-shaped enough to
29
- * let the transcript commit its settled prefix. Absent = the pending preview
30
- * streams rows the result render preserves.
31
- */
32
- provisionalPendingPreview?: boolean | "collapsed";
33
- /**
34
- * Whether the partial-result render is provisional: chrome rows (header
35
- * glyph, frame state) that change between `options.isPartial === true` and
36
- * the final result render. When `true`, the block is treated as
37
- * commit-unstable while a partial result is in flight, so the
38
- * stable-prefix ratchet in `deriveLiveCommitState` cannot promote the
39
- * partial chrome to native scrollback only to have the final render strand
40
- * it above the settled frame. Absent = the partial render is byte-stable
41
- * with the final render and may commit like any settled stream.
42
- */
43
- provisionalPartialResult?: boolean;
44
24
  /**
45
25
  * Whether the renderer's pending-call path visibly consumes
46
26
  * `options.spinnerFrame`. Used to avoid scheduling repaint ticks for live
@@ -68,8 +68,6 @@ export declare const sshToolRenderer: {
68
68
  renderContext?: SshRenderContext;
69
69
  }, uiTheme: Theme, args?: SshRenderArgs): Component;
70
70
  mergeCallAndResult: boolean;
71
- provisionalPendingPreview: boolean;
72
- provisionalPartialResult: boolean;
73
71
  forceFirstResultViewportRepaint: boolean;
74
72
  forceResultViewportRepaintOnSettle: boolean;
75
73
  };
@@ -49,7 +49,7 @@ export declare class WriteTool implements AgentTool<typeof writeSchema, WriteToo
49
49
  interface WriteRenderArgs {
50
50
  path?: string;
51
51
  file_path?: string;
52
- content?: string;
52
+ content?: unknown;
53
53
  }
54
54
  export declare const writeToolRenderer: {
55
55
  renderCall(args: WriteRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component;