@oh-my-pi/pi-coding-agent 16.1.14 → 16.1.16
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.
- package/CHANGELOG.md +69 -0
- package/dist/cli.js +3705 -4015
- package/dist/types/advisor/runtime.d.ts +3 -0
- package/dist/types/cli/args.d.ts +2 -5
- package/dist/types/cli/flag-tables.d.ts +2 -2
- package/dist/types/cli/session-picker.d.ts +4 -2
- package/dist/types/commands/launch.d.ts +1 -1
- package/dist/types/config/settings-schema.d.ts +32 -1
- package/dist/types/eval/agent-bridge.d.ts +19 -0
- package/dist/types/eval/js/shared/helpers.d.ts +1 -13
- package/dist/types/eval/js/shared/types.d.ts +1 -1
- package/dist/types/eval/js/worker-protocol.d.ts +1 -1
- package/dist/types/eval/py/executor.d.ts +1 -1
- package/dist/types/export/share.d.ts +8 -1
- package/dist/types/internal-urls/local-protocol.d.ts +18 -1
- package/dist/types/main.d.ts +2 -0
- package/dist/types/mcp/transports/stdio.d.ts +12 -1
- package/dist/types/modes/components/plugin-settings.d.ts +5 -0
- package/dist/types/modes/components/session-selector.d.ts +25 -0
- package/dist/types/modes/components/status-line/context-thresholds.d.ts +4 -3
- package/dist/types/modes/components/status-line/types.d.ts +1 -0
- package/dist/types/secrets/obfuscator.d.ts +3 -3
- package/dist/types/task/isolation-runner.d.ts +128 -0
- package/dist/types/task/worktree.d.ts +14 -1
- package/dist/types/thinking.d.ts +15 -0
- package/dist/types/tools/eval-render.d.ts +3 -0
- package/dist/types/tools/eval.d.ts +11 -17
- package/dist/types/tools/todo.d.ts +26 -28
- package/dist/types/tui/output-block.d.ts +8 -0
- package/dist/types/utils/image-resize.d.ts +2 -0
- package/dist/types/utils/shell-snapshot.d.ts +10 -0
- package/dist/types/web/search/providers/exa.d.ts +2 -0
- package/dist/types/web/search/providers/perplexity.d.ts +17 -3
- package/package.json +12 -12
- package/scripts/build-binary.ts +18 -4
- package/src/advisor/__tests__/advisor.test.ts +114 -0
- package/src/advisor/runtime.ts +129 -1
- package/src/cli/args.ts +4 -5
- package/src/cli/flag-tables.ts +3 -3
- package/src/cli/gallery-fixtures/interaction.ts +6 -9
- package/src/cli/gallery-fixtures/shell.ts +15 -23
- package/src/cli/session-picker.ts +17 -3
- package/src/commands/launch.ts +3 -3
- package/src/config/model-registry.ts +12 -4
- package/src/config/settings-schema.ts +37 -1
- package/src/edit/renderer.ts +34 -12
- package/src/eval/__tests__/agent-bridge.test.ts +462 -3
- package/src/eval/__tests__/helpers-local-roots.test.ts +2 -5
- package/src/eval/__tests__/julia-prelude.test.ts +1 -30
- package/src/eval/__tests__/prelude-agent.test.ts +42 -8
- package/src/eval/agent-bridge.ts +301 -71
- package/src/eval/jl/prelude.jl +32 -227
- package/src/eval/jl/runner.jl +38 -12
- package/src/eval/js/shared/helpers.ts +1 -114
- package/src/eval/js/shared/prelude.txt +13 -27
- package/src/eval/js/shared/runtime.ts +0 -6
- package/src/eval/js/shared/types.ts +1 -1
- package/src/eval/js/worker-protocol.ts +1 -1
- package/src/eval/py/__tests__/prelude.test.ts +13 -0
- package/src/eval/py/executor.ts +1 -1
- package/src/eval/py/prelude.py +47 -105
- package/src/eval/py/runner.py +0 -6
- package/src/eval/rb/prelude.rb +21 -189
- package/src/eval/rb/runner.rb +116 -9
- package/src/exec/bash-executor.ts +44 -0
- package/src/export/html/tool-views.generated.js +29 -29
- package/src/export/share.ts +51 -28
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/internal-urls/local-protocol.ts +100 -53
- package/src/main.ts +15 -4
- package/src/mcp/transports/stdio.ts +20 -4
- package/src/modes/acp/acp-event-mapper.ts +7 -2
- package/src/modes/components/custom-editor.test.ts +22 -0
- package/src/modes/components/custom-editor.ts +10 -1
- package/src/modes/components/footer.ts +4 -3
- package/src/modes/components/plugin-settings.ts +7 -1
- package/src/modes/components/session-selector.ts +143 -29
- package/src/modes/components/status-line/component.ts +5 -1
- package/src/modes/components/status-line/context-thresholds.ts +11 -3
- package/src/modes/components/status-line/segments.ts +1 -1
- package/src/modes/components/status-line/types.ts +1 -0
- package/src/modes/controllers/command-controller.ts +6 -0
- package/src/modes/rpc/rpc-mode.ts +6 -0
- package/src/modes/utils/copy-targets.ts +7 -2
- package/src/prompts/system/system-prompt.md +6 -6
- package/src/prompts/system/workflow-notice.md +3 -3
- package/src/prompts/tools/bash.md +18 -2
- package/src/prompts/tools/eval.md +19 -19
- package/src/prompts/tools/search.md +1 -0
- package/src/prompts/tools/todo.md +1 -1
- package/src/secrets/obfuscator.ts +3 -9
- package/src/session/agent-session.ts +264 -52
- package/src/slash-commands/builtin-registry.ts +2 -1
- package/src/task/index.ts +61 -207
- package/src/task/isolation-runner.ts +354 -0
- package/src/task/worktree.ts +46 -9
- package/src/thinking.ts +20 -0
- package/src/tools/ask.ts +44 -38
- package/src/tools/bash.ts +9 -2
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/eval-render.ts +34 -27
- package/src/tools/eval.ts +100 -103
- package/src/tools/index.ts +8 -1
- package/src/tools/read.ts +136 -60
- package/src/tools/todo.ts +60 -64
- package/src/tui/code-cell.ts +1 -1
- package/src/tui/output-block.ts +11 -0
- package/src/utils/image-resize.ts +30 -0
- package/src/utils/shell-snapshot.ts +63 -1
- package/src/web/search/providers/exa.ts +85 -1
- package/src/web/search/providers/perplexity.ts +18 -6
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import { type SecretObfuscator } from "../secrets/obfuscator";
|
|
2
3
|
/** Minimal slice of `Agent` the runtime drives — satisfied by pi-agent-core `Agent`. */
|
|
3
4
|
export interface AdvisorAgent {
|
|
4
5
|
prompt(input: string): Promise<void>;
|
|
@@ -13,6 +14,8 @@ export interface AdvisorRuntimeHost {
|
|
|
13
14
|
snapshotMessages(): AgentMessage[];
|
|
14
15
|
/** Surface one advice note to the primary (enqueues into the session YieldQueue). */
|
|
15
16
|
enqueueAdvice(note: string, severity?: "nit" | "concern" | "blocker"): void;
|
|
17
|
+
/** Redact primary transcript bytes before they reach the advisor model. */
|
|
18
|
+
obfuscator?: SecretObfuscator;
|
|
16
19
|
/**
|
|
17
20
|
* Pre-prompt context maintenance for the advisor's own append-only context.
|
|
18
21
|
* Promotes the advisor model to a larger sibling when its context nears the
|
package/dist/types/cli/args.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* CLI argument parsing and help display
|
|
3
|
-
*/
|
|
4
|
-
import { type Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
1
|
+
import { type ConfiguredThinkingLevel } from "../thinking";
|
|
5
2
|
export type Mode = "text" | "json" | "rpc" | "acp" | "rpc-ui";
|
|
6
3
|
export interface Args {
|
|
7
4
|
cwd?: string;
|
|
@@ -18,7 +15,7 @@ export interface Args {
|
|
|
18
15
|
apiKey?: string;
|
|
19
16
|
systemPrompt?: string;
|
|
20
17
|
appendSystemPrompt?: string;
|
|
21
|
-
thinking?:
|
|
18
|
+
thinking?: ConfiguredThinkingLevel;
|
|
22
19
|
hideThinking?: boolean;
|
|
23
20
|
advisor?: boolean;
|
|
24
21
|
continue?: boolean;
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* tables), they're passed in through {@link ParseDeps} and `args.ts` wires the
|
|
30
30
|
* real implementations at the dispatch site.
|
|
31
31
|
*/
|
|
32
|
-
import type {
|
|
32
|
+
import type { ConfiguredThinkingLevel } from "../thinking";
|
|
33
33
|
import type { Args } from "./args";
|
|
34
34
|
/**
|
|
35
35
|
* Runtime dependencies injected into setters that need to validate input or
|
|
@@ -44,7 +44,7 @@ export interface ParseDeps {
|
|
|
44
44
|
logger: {
|
|
45
45
|
warn: (message: string, meta?: Record<string, unknown>) => void;
|
|
46
46
|
};
|
|
47
|
-
|
|
47
|
+
parseThinking: (value: string | null | undefined) => ConfiguredThinkingLevel | undefined;
|
|
48
48
|
builtinToolNames: readonly string[];
|
|
49
49
|
thinkingEfforts: readonly string[];
|
|
50
50
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { SessionInfo } from "../session/session-listing";
|
|
2
2
|
/**
|
|
3
3
|
* Show the TUI session selector and return the selected session, or null if
|
|
4
|
-
* cancelled.
|
|
5
|
-
*
|
|
4
|
+
* cancelled. Rendered as a fullscreen overlay on the terminal's alternate
|
|
5
|
+
* screen, so the list scrolls and rows are clickable with the mouse. Tab
|
|
6
|
+
* toggles between current-folder and all-projects scope; the all-projects list
|
|
7
|
+
* is loaded lazily via `SessionManager.listAll`.
|
|
6
8
|
*/
|
|
7
9
|
export declare function selectSession(sessions: SessionInfo[], options?: {
|
|
8
10
|
allSessions?: SessionInfo[];
|
|
@@ -92,7 +92,7 @@ export default class Index extends Command {
|
|
|
92
92
|
};
|
|
93
93
|
thinking: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
|
|
94
94
|
description: string;
|
|
95
|
-
options:
|
|
95
|
+
options: string[];
|
|
96
96
|
};
|
|
97
97
|
"hide-thinking": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
|
|
98
98
|
description: string;
|
|
@@ -1636,6 +1636,26 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
1636
1636
|
readonly description: "Share viewer/upload base used by /share (encrypted blob upload + viewer; links are <base>/<id>#<key>)";
|
|
1637
1637
|
};
|
|
1638
1638
|
};
|
|
1639
|
+
readonly "share.store": {
|
|
1640
|
+
readonly type: "enum";
|
|
1641
|
+
readonly values: readonly ["blob", "gist"];
|
|
1642
|
+
readonly default: "blob";
|
|
1643
|
+
readonly ui: {
|
|
1644
|
+
readonly tab: "interaction";
|
|
1645
|
+
readonly group: "Collab";
|
|
1646
|
+
readonly label: "Share Store";
|
|
1647
|
+
readonly description: "Where /share uploads the encrypted session blob";
|
|
1648
|
+
readonly options: readonly [{
|
|
1649
|
+
readonly value: "blob";
|
|
1650
|
+
readonly label: "Encrypted Blob";
|
|
1651
|
+
readonly description: "Upload to the share server (no GitHub account needed; avoids gist API rate limits)";
|
|
1652
|
+
}, {
|
|
1653
|
+
readonly value: "gist";
|
|
1654
|
+
readonly label: "GitHub Gist";
|
|
1655
|
+
readonly description: "Push to a secret gist (needs authenticated gh), falling back to the share server";
|
|
1656
|
+
}];
|
|
1657
|
+
};
|
|
1658
|
+
};
|
|
1639
1659
|
readonly "share.redactSecrets": {
|
|
1640
1660
|
readonly type: "boolean";
|
|
1641
1661
|
readonly default: true;
|
|
@@ -3706,7 +3726,7 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
3706
3726
|
readonly tab: "tools";
|
|
3707
3727
|
readonly group: "Discovery & MCP";
|
|
3708
3728
|
readonly label: "Essential Tools Override";
|
|
3709
|
-
readonly description: "Override the always-loaded built-in tools (default: read, bash, edit). Leave empty to use defaults.";
|
|
3729
|
+
readonly description: "Override the always-loaded built-in tools (default: read, bash, edit, write, find, eval). Leave empty to use defaults.";
|
|
3710
3730
|
};
|
|
3711
3731
|
};
|
|
3712
3732
|
readonly "mcp.enableProjectConfig": {
|
|
@@ -4915,6 +4935,16 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
4915
4935
|
readonly description: "Enable Exa basic search, deep search, code search, and crawl tools";
|
|
4916
4936
|
};
|
|
4917
4937
|
};
|
|
4938
|
+
readonly "exa.searchDelayMs": {
|
|
4939
|
+
readonly type: "number";
|
|
4940
|
+
readonly default: 1000;
|
|
4941
|
+
readonly ui: {
|
|
4942
|
+
readonly tab: "providers";
|
|
4943
|
+
readonly group: "Services";
|
|
4944
|
+
readonly label: "Exa Search Delay";
|
|
4945
|
+
readonly description: "Minimum delay between Exa web search requests in milliseconds; set 0 to disable pacing";
|
|
4946
|
+
};
|
|
4947
|
+
};
|
|
4918
4948
|
readonly "exa.enableResearcher": {
|
|
4919
4949
|
readonly type: "boolean";
|
|
4920
4950
|
readonly default: false;
|
|
@@ -5182,6 +5212,7 @@ export interface TtsrSettings {
|
|
|
5182
5212
|
export interface ExaSettings {
|
|
5183
5213
|
enabled: boolean;
|
|
5184
5214
|
enableSearch: boolean;
|
|
5215
|
+
searchDelayMs: number;
|
|
5185
5216
|
enableResearcher: boolean;
|
|
5186
5217
|
enableWebsets: boolean;
|
|
5187
5218
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type NestedRepoPatch } from "../task/worktree";
|
|
1
2
|
import type { ToolSession } from "../tools";
|
|
2
3
|
import type { JsStatusEvent } from "./js/shared/types";
|
|
3
4
|
import "../tools/review";
|
|
@@ -17,6 +18,24 @@ export interface EvalAgentResult {
|
|
|
17
18
|
id: string;
|
|
18
19
|
model?: string | string[];
|
|
19
20
|
structured: boolean;
|
|
21
|
+
/** True iff this run executed inside an isolation worktree. */
|
|
22
|
+
isolated?: boolean;
|
|
23
|
+
/** Captured patch artifact (patch mode) — surfaced regardless of `apply`. */
|
|
24
|
+
patchPath?: string;
|
|
25
|
+
/** Captured branch (branch mode) — surfaced regardless of `apply`. */
|
|
26
|
+
branchName?: string;
|
|
27
|
+
/** Captured nested repository patches — surfaced for isolated `apply=false` manual application. */
|
|
28
|
+
nestedPatches?: NestedRepoPatch[];
|
|
29
|
+
/**
|
|
30
|
+
* Tri-state apply outcome for isolated runs:
|
|
31
|
+
* - `true` — apply ran (or had nothing to do) and left the repo clean.
|
|
32
|
+
* - `false` — apply attempted and failed; artifacts preserved.
|
|
33
|
+
* - `null` — caller opted out via `apply=false`.
|
|
34
|
+
* Omitted for non-isolated runs.
|
|
35
|
+
*/
|
|
36
|
+
changesApplied?: boolean | null;
|
|
37
|
+
/** Human-readable isolation apply/merge summary; kept out of schema-backed `text`. */
|
|
38
|
+
isolationSummary?: string;
|
|
20
39
|
};
|
|
21
40
|
}
|
|
22
41
|
/**
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import type { JsStatusEvent } from "./types";
|
|
2
2
|
export interface HelperOptions {
|
|
3
|
-
path?: string;
|
|
4
|
-
hidden?: boolean;
|
|
5
|
-
maxDepth?: number;
|
|
6
3
|
limit?: number;
|
|
7
4
|
offset?: number;
|
|
8
|
-
reverse?: boolean;
|
|
9
|
-
unique?: boolean;
|
|
10
|
-
count?: boolean;
|
|
11
5
|
}
|
|
12
6
|
/**
|
|
13
7
|
* Inputs the helper factory needs from its host runtime. `cwd` is a getter so the runtime
|
|
@@ -27,18 +21,12 @@ export interface HelperContext {
|
|
|
27
21
|
}
|
|
28
22
|
/**
|
|
29
23
|
* The set of functions exposed to user code via `globalThis.__omp_helpers__`. The JS
|
|
30
|
-
* prelude reads from this bag and attaches short aliases (`read`, `write`, `
|
|
24
|
+
* prelude reads from this bag and attaches short aliases (`read`, `write`, `env`, ...)
|
|
31
25
|
* onto the global scope.
|
|
32
26
|
*/
|
|
33
27
|
export interface HelperBundle {
|
|
34
28
|
read(rawPath: string, options?: HelperOptions): Promise<string>;
|
|
35
29
|
writeFile(rawPath: string, data: unknown): Promise<string>;
|
|
36
|
-
append(rawPath: string, content: string): Promise<string>;
|
|
37
|
-
sortText(text: string, options?: HelperOptions): string;
|
|
38
|
-
uniqText(text: string, options?: HelperOptions): string | Array<[number, string]>;
|
|
39
|
-
counter(items: string | string[], options?: HelperOptions): Array<[number, string]>;
|
|
40
|
-
diff(rawA: string, rawB: string): Promise<string>;
|
|
41
|
-
tree(searchPath?: string, options?: HelperOptions): Promise<string>;
|
|
42
30
|
env(key?: string, value?: string): string | Record<string, string> | undefined;
|
|
43
31
|
}
|
|
44
32
|
export declare function createHelpers(ctx: HelperContext): HelperBundle;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Structured status payload emitted by helpers (`read`, `write`, `
|
|
2
|
+
* Structured status payload emitted by helpers (`read`, `write`, `env`, etc.) and the
|
|
3
3
|
* tool-call bridge. Surfaces to the model as part of `displays` so it has machine-readable
|
|
4
4
|
* context about what side effects happened.
|
|
5
5
|
*/
|
|
@@ -5,7 +5,7 @@ export interface SessionSnapshot {
|
|
|
5
5
|
sessionId: string;
|
|
6
6
|
/**
|
|
7
7
|
* On-disk roots the helpers substitute for internal-URL schemes
|
|
8
|
-
* (e.g. `{ local: "/…/artifacts/local" }`). Lets `read`/`write
|
|
8
|
+
* (e.g. `{ local: "/…/artifacts/local" }`). Lets `read`/`write`
|
|
9
9
|
* accept `local://…` paths instead of writing a literal `local:/` directory.
|
|
10
10
|
*/
|
|
11
11
|
localRoots?: Record<string, string>;
|
|
@@ -45,7 +45,7 @@ export interface PythonExecutorOptions {
|
|
|
45
45
|
artifactPath?: string;
|
|
46
46
|
artifactId?: string;
|
|
47
47
|
/**
|
|
48
|
-
* On-disk roots the prelude helpers (`read`/`write
|
|
48
|
+
* On-disk roots the prelude helpers (`read`/`write`) substitute for
|
|
49
49
|
* internal-URL schemes (e.g. `{ local: "/…/artifacts/local" }`). Exported to
|
|
50
50
|
* the kernel as `PI_EVAL_LOCAL_ROOTS` (JSON) so `write("local://x")` lands
|
|
51
51
|
* where `read local://x` resolves instead of a literal `local:/` directory.
|
|
@@ -6,9 +6,16 @@ import { type SessionData } from "./html";
|
|
|
6
6
|
export { DEFAULT_SHARE_URL };
|
|
7
7
|
/** Hard cap for blobs accepted by the share server (mirrors relay shareMaxBytes). */
|
|
8
8
|
export declare const SERVER_MAX_SEALED_BYTES = 1000000;
|
|
9
|
+
export type ShareStore = "blob" | "gist";
|
|
9
10
|
export interface ShareSessionOptions {
|
|
10
11
|
/** Share server/viewer base URL; defaults to {@link DEFAULT_SHARE_URL}. */
|
|
11
12
|
serverUrl?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Where to upload the sealed blob. `"blob"` (default) posts to the share
|
|
15
|
+
* server; `"gist"` pushes to a secret GitHub gist first (needs an
|
|
16
|
+
* authenticated `gh`) and falls back to the server.
|
|
17
|
+
*/
|
|
18
|
+
store?: ShareStore;
|
|
12
19
|
/** Agent state for system prompt + tool descriptions in the snapshot. */
|
|
13
20
|
state?: AgentState;
|
|
14
21
|
/**
|
|
@@ -36,7 +43,7 @@ export interface ShareSessionResult {
|
|
|
36
43
|
}
|
|
37
44
|
/** Build the snapshot that gets sealed and uploaded, redacted when an obfuscator is provided. */
|
|
38
45
|
export declare function buildShareSnapshot(sm: SessionManager, options?: ShareSessionOptions): SessionData;
|
|
39
|
-
/** Share the session;
|
|
46
|
+
/** Share the session; uploads to the share server unless `options.store` is `"gist"`. */
|
|
40
47
|
export declare function shareSession(sm: SessionManager, options?: ShareSessionOptions): Promise<ShareSessionResult>;
|
|
41
48
|
/** Strip trailing slashes so `<base>/<id>` composes cleanly. */
|
|
42
49
|
export declare function normalizeShareServerUrl(serverUrl?: string): string;
|
|
@@ -8,7 +8,7 @@ export declare function resolveLocalRoot(options: LocalProtocolOptions, platform
|
|
|
8
8
|
/** Resolve a local:// URL to an on-disk path under the active session's local root. */
|
|
9
9
|
export declare function resolveLocalUrlToPath(input: string | InternalUrl, options: LocalProtocolOptions, platform?: NodeJS.Platform): string;
|
|
10
10
|
/**
|
|
11
|
-
* On-disk roots the eval helpers (`read`/`write
|
|
11
|
+
* On-disk roots the eval helpers (`read`/`write`) substitute for
|
|
12
12
|
* internal-URL schemes so e.g. `write("local://x.md")` lands where a later
|
|
13
13
|
* `read local://x.md` resolves — instead of a literal `local:/` directory under
|
|
14
14
|
* the cwd (a stdlib `pathlib.Path`/`path.resolve` collapses `local://` to
|
|
@@ -17,6 +17,23 @@ export declare function resolveLocalUrlToPath(input: string | InternalUrl, optio
|
|
|
17
17
|
* re-plumbing the worker boundary.
|
|
18
18
|
*/
|
|
19
19
|
export declare function buildEvalUrlRoots(options: LocalProtocolOptions): Record<string, string>;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve a local:// URL to a regular on-disk file, applying the same
|
|
22
|
+
* realpath + containment guarantees as {@link LocalProtocolHandler.resolve}
|
|
23
|
+
* but WITHOUT reading or UTF-8-decoding its contents. Returns null when there
|
|
24
|
+
* is no active session or when the URL targets the root listing or a directory;
|
|
25
|
+
* throws the handler's not-found and "escapes local root" errors for missing
|
|
26
|
+
* files and symlink escapes.
|
|
27
|
+
*
|
|
28
|
+
* Options are resolved via {@link LocalProtocolHandler.resolveOptions} so the
|
|
29
|
+
* caller-options → override → registry order matches router resolution exactly.
|
|
30
|
+
* The read tool uses this to detect and emit image files from their real path
|
|
31
|
+
* before the text-only resource contract would decode the binary into mojibake.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveLocalUrlToFile(input: string | InternalUrl, context?: ResolveContext): Promise<{
|
|
34
|
+
path: string;
|
|
35
|
+
size: number;
|
|
36
|
+
} | null>;
|
|
20
37
|
/**
|
|
21
38
|
* Protocol handler for local:// URLs.
|
|
22
39
|
*
|
package/dist/types/main.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Args } from "./cli/args";
|
|
2
|
+
import { selectSession } from "./cli/session-picker";
|
|
2
3
|
import { ModelRegistry } from "./config/model-registry";
|
|
3
4
|
import { type ScopedModel } from "./config/model-resolver";
|
|
4
5
|
import { Settings } from "./config/settings";
|
|
@@ -59,6 +60,7 @@ export declare function applyResolvedSystemPromptInputs(options: CreateAgentSess
|
|
|
59
60
|
interface RunRootCommandDependencies {
|
|
60
61
|
createAgentSession?: typeof createAgentSession;
|
|
61
62
|
discoverAuthStorage?: typeof discoverAuthStorage;
|
|
63
|
+
selectSession?: typeof selectSession;
|
|
62
64
|
runAcpMode?: RunAcpMode;
|
|
63
65
|
settings?: Settings;
|
|
64
66
|
forceSetupWizard?: boolean;
|
|
@@ -16,7 +16,18 @@ export interface ResolveStdioSpawnOptions {
|
|
|
16
16
|
env: Record<string, string | undefined>;
|
|
17
17
|
platform?: NodeJS.Platform;
|
|
18
18
|
}
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the subprocess argv used to launch an MCP stdio server.
|
|
21
|
+
*
|
|
22
|
+
* On Windows, our PATH/PATHEXT walk may return `null` for a bare command
|
|
23
|
+
* (e.g. `npx`) — `Bun.env.PATH` empty under a restricted parent process,
|
|
24
|
+
* UNC/network mounts that reject `fs.access`, locked-down shells. The
|
|
25
|
+
* legacy fallback handed `Bun.spawn` the bare name, but `CreateProcess`
|
|
26
|
+
* only appends `.exe` for extensionless names — `.cmd`/`.bat` are never
|
|
27
|
+
* tried, so `npx` (which exists only as `npx.cmd` on Windows) crashes the
|
|
28
|
+
* subprocess immediately. When the resolver can't pin the command down,
|
|
29
|
+
* route through `cmd.exe /d /s /c` so Windows's own PATHEXT lookup runs.
|
|
30
|
+
*/
|
|
20
31
|
export declare function resolveStdioSpawnCommand(config: MCPStdioServerConfig, options: ResolveStdioSpawnOptions): Promise<StdioSpawnCommand>;
|
|
21
32
|
/** Minimal write surface of `Subprocess.stdin` we need for framed sends. */
|
|
22
33
|
interface FrameSink {
|
|
@@ -14,6 +14,11 @@ import type { InstalledPluginSummary } from "../../extensibility/plugins/marketp
|
|
|
14
14
|
import type { InstalledPlugin } from "../../extensibility/plugins/types";
|
|
15
15
|
/**
|
|
16
16
|
* Forwards a keystroke to `input`, but cancels via `onCancel` when the user presses Escape.
|
|
17
|
+
*
|
|
18
|
+
* Escape is decoded via `matchesKey` rather than a raw `\x1b` compare: inside the
|
|
19
|
+
* fullscreen settings overlay the kitty keyboard protocol is active (ghostty/kitty),
|
|
20
|
+
* where the Escape key arrives as the CSI-u sequence `\x1b[27u`, not a bare `\x1b`.
|
|
21
|
+
* The literal fallbacks preserve legacy single/double-escape on terminals without it.
|
|
17
22
|
*/
|
|
18
23
|
export declare function handleInputOrEscape(data: string, input: {
|
|
19
24
|
handleInput(data: string): void;
|
|
@@ -39,6 +39,12 @@ declare class SessionList implements Component {
|
|
|
39
39
|
/** Replace the visible dataset, e.g. when toggling folder/all-projects scope. */
|
|
40
40
|
setSessions(sessions: SessionInfo[], showCwd: boolean): void;
|
|
41
41
|
removeSession(sessionPath: string): void;
|
|
42
|
+
/** Resolve a list-local rendered-line index to a filtered-session index. */
|
|
43
|
+
hitTestSession(line: number): number | undefined;
|
|
44
|
+
/** Wheel notch: move the selection one step (clamped, no wrap). */
|
|
45
|
+
handleWheel(delta: -1 | 1): void;
|
|
46
|
+
/** Mouse click: select the session under the pointer and resume it. */
|
|
47
|
+
selectAndConfirm(index: number): void;
|
|
42
48
|
invalidate(): void;
|
|
43
49
|
render(width: number): readonly string[];
|
|
44
50
|
handleInput(keyData: string): void;
|
|
@@ -55,6 +61,13 @@ export interface SessionSelectorOptions {
|
|
|
55
61
|
* Omitted only in tests; defaults to a conservative 24 rows.
|
|
56
62
|
*/
|
|
57
63
|
getTerminalRows?: () => number;
|
|
64
|
+
/**
|
|
65
|
+
* Fill the whole viewport and pin the footer (hint + bottom border) to the
|
|
66
|
+
* last rows, so the footer stops drifting as the list window changes height.
|
|
67
|
+
* Set by the standalone `--resume` picker (fullscreen alternate screen); the
|
|
68
|
+
* in-editor selector leaves it off and renders compactly.
|
|
69
|
+
*/
|
|
70
|
+
fillHeight?: boolean;
|
|
58
71
|
}
|
|
59
72
|
/**
|
|
60
73
|
* Component that renders a session selector with optional confirmation dialog
|
|
@@ -63,6 +76,18 @@ export declare class SessionSelectorComponent extends Container {
|
|
|
63
76
|
#private;
|
|
64
77
|
constructor(sessions: SessionInfo[], onSelect: (session: SessionInfo) => void, onCancel: () => void, onExit: () => void, options?: SessionSelectorOptions);
|
|
65
78
|
setOnRequestRender(callback: () => void): void;
|
|
79
|
+
/**
|
|
80
|
+
* Concatenate the children's renders (like {@link Container}) while recording
|
|
81
|
+
* the line where the session list begins, so the fullscreen picker can hit-
|
|
82
|
+
* test mouse rows against the live list window. SessionList rebuilds its lines
|
|
83
|
+
* every frame, so Container's reference-memoization never applied here.
|
|
84
|
+
*
|
|
85
|
+
* In fill-height mode the body is padded (or, on a cramped terminal, trimmed)
|
|
86
|
+
* to leave exactly enough room for the footer at the screen bottom, so the
|
|
87
|
+
* footer is always visible and never drifts as the list window resizes. The
|
|
88
|
+
* in-editor selector just appends the footer directly.
|
|
89
|
+
*/
|
|
90
|
+
render(width: number): readonly string[];
|
|
66
91
|
handleInput(keyData: string): void;
|
|
67
92
|
getSessionList(): SessionList;
|
|
68
93
|
}
|
|
@@ -2,8 +2,9 @@ import type { ThemeColor } from "../../../modes/theme/theme";
|
|
|
2
2
|
export type ContextUsageLevel = "normal" | "warning" | "purple" | "error";
|
|
3
3
|
export declare function getContextUsageLevel(contextPercent: number, contextWindow: number): ContextUsageLevel;
|
|
4
4
|
/**
|
|
5
|
-
* Format context usage as `<percent>%/<window>`
|
|
6
|
-
*
|
|
5
|
+
* Format context usage as `<percent>%/<window>` when the model window is known.
|
|
6
|
+
* Unknown windows render as `<tokens>/?`, because `0.0%/0` suggests a real
|
|
7
|
+
* empty context instead of missing provider metadata.
|
|
7
8
|
*/
|
|
8
|
-
export declare function formatContextUsage(contextPercent: number | null | undefined, contextWindow: number): string;
|
|
9
|
+
export declare function formatContextUsage(contextPercent: number | null | undefined, contextWindow: number, usedTokens?: number): string;
|
|
9
10
|
export declare function getContextUsageThemeColor(level: ContextUsageLevel): ThemeColor;
|
|
@@ -72,6 +72,7 @@ export interface SegmentContext {
|
|
|
72
72
|
};
|
|
73
73
|
/** Context usage percent, or null when unknown (e.g. right after compaction). */
|
|
74
74
|
contextPercent: number | null;
|
|
75
|
+
contextTokens: number;
|
|
75
76
|
contextWindow: number;
|
|
76
77
|
autoCompactEnabled: boolean;
|
|
77
78
|
subagentCount: number;
|
|
@@ -34,9 +34,9 @@ export declare class SecretObfuscator {
|
|
|
34
34
|
export declare function deobfuscateSessionContext(sessionContext: SessionContext, obfuscator: SecretObfuscator | undefined): SessionContext;
|
|
35
35
|
export declare function deobfuscateAgentMessages(obfuscator: SecretObfuscator, messages: AgentMessage[]): AgentMessage[];
|
|
36
36
|
/**
|
|
37
|
-
* Restore placeholders in assistant content: visible text
|
|
38
|
-
*
|
|
39
|
-
*
|
|
37
|
+
* Restore placeholders in assistant content: visible text and tool-call
|
|
38
|
+
* arguments/intent/rawBlock. Thinking and signatures are opaque
|
|
39
|
+
* provider-replay/hidden-reasoning data and pass through byte-identical.
|
|
40
40
|
*/
|
|
41
41
|
export declare function deobfuscateAssistantContent(obfuscator: SecretObfuscator, content: AssistantMessage["content"]): AssistantMessage["content"];
|
|
42
42
|
/**
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type * as natives from "@oh-my-pi/pi-natives";
|
|
2
|
+
import type { ToolSession } from "../tools";
|
|
3
|
+
import type { ExecutorOptions } from "./executor";
|
|
4
|
+
import type { SingleResult } from "./types";
|
|
5
|
+
import { type WorktreeBaseline } from "./worktree";
|
|
6
|
+
type IsoBackendKind = natives.IsoBackendKind;
|
|
7
|
+
/** Resolved repo + baseline used by every isolated spawn in a single call. */
|
|
8
|
+
export interface IsolationContext {
|
|
9
|
+
repoRoot: string;
|
|
10
|
+
baseline: WorktreeBaseline;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the git repo root and capture the worktree baseline used to diff
|
|
14
|
+
* each isolated spawn against. Throws when the cwd is not inside a git
|
|
15
|
+
* repository; callers surface the error as a task-tool failure.
|
|
16
|
+
*/
|
|
17
|
+
export declare function prepareIsolationContext(cwd: string): Promise<IsolationContext>;
|
|
18
|
+
/** Build a commit-message callback for branch/nested commits; `undefined` ⇒ fall back to generic message. */
|
|
19
|
+
export type BuildCommitMessage = () => undefined | ((diff: string) => Promise<string | null>);
|
|
20
|
+
/**
|
|
21
|
+
* Construct the commit-message factory used by isolation branch commits and
|
|
22
|
+
* nested-repo patch commits. Returns a closure that, each time it's called,
|
|
23
|
+
* either yields an AI-backed `(diff) => Promise<string|null>` callback (when
|
|
24
|
+
* `task.isolation.commits === "ai"` and a model registry is available) or
|
|
25
|
+
* `undefined` so the caller falls back to a generic commit message.
|
|
26
|
+
*
|
|
27
|
+
* Centralized so `TaskTool` and the eval `agent()` bridge share one wiring;
|
|
28
|
+
* a drift here previously meant the two callers built subtly different
|
|
29
|
+
* generators for the same setting.
|
|
30
|
+
*/
|
|
31
|
+
export declare function makeIsolationCommitMessage(session: ToolSession): BuildCommitMessage;
|
|
32
|
+
export interface IsolatedRunOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Base run options handed to the subagent subprocess. This helper sets
|
|
35
|
+
* `worktree`, clears `preloadedExtensionPaths` / `preloadedCustomToolPaths`
|
|
36
|
+
* (isolated runs re-discover inside the worktree), and forwards everything
|
|
37
|
+
* else unchanged.
|
|
38
|
+
*/
|
|
39
|
+
baseOptions: ExecutorOptions;
|
|
40
|
+
/** Context returned by {@link prepareIsolationContext}. Baseline is cloned per spawn. */
|
|
41
|
+
context: IsolationContext;
|
|
42
|
+
/** PAL backend hint from `parseIsolationMode(...)` (undefined ⇒ resolver picks). */
|
|
43
|
+
preferredBackend: IsoBackendKind | undefined;
|
|
44
|
+
/** Stable id used as the isolation worktree namespace and as the branch suffix. */
|
|
45
|
+
agentId: string;
|
|
46
|
+
/** Merge mode driving how changes are captured ("branch" commits, "patch" diffs). */
|
|
47
|
+
mergeMode: "patch" | "branch";
|
|
48
|
+
/** Output dir for `${agentId}.patch` artifacts (patch mode). */
|
|
49
|
+
artifactsDir: string;
|
|
50
|
+
/** Human description carried onto the branch commit (branch mode). */
|
|
51
|
+
description?: string;
|
|
52
|
+
/** Build a commit-message callback (`task.isolation.commits === "ai"`). */
|
|
53
|
+
buildCommitMessage?: BuildCommitMessage;
|
|
54
|
+
/**
|
|
55
|
+
* Construct a `SingleResult` when isolation setup throws — the caller has
|
|
56
|
+
* the full metadata (index, agent, assignment, modelOverride) needed to
|
|
57
|
+
* build a result shape consistent with their non-isolated path.
|
|
58
|
+
*/
|
|
59
|
+
buildFailureResult: (err: unknown) => SingleResult;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Run a subagent inside an isolation worktree and capture its changes.
|
|
63
|
+
*
|
|
64
|
+
* Branch mode: on success, commits the diff onto `omp/task/${agentId}` and
|
|
65
|
+
* returns `branchName` + `nestedPatches`. On commit failure the branch is
|
|
66
|
+
* deleted and `result.error` carries the merge-failure message.
|
|
67
|
+
*
|
|
68
|
+
* Patch mode: on success, writes `${artifactsDir}/${agentId}.patch` and
|
|
69
|
+
* returns `patchPath` + `nestedPatches`.
|
|
70
|
+
*
|
|
71
|
+
* Failure paths preserve the underlying `SingleResult` whenever possible so
|
|
72
|
+
* the caller can still surface the subagent's output; only isolation setup
|
|
73
|
+
* itself routes through {@link IsolatedRunOptions.buildFailureResult}.
|
|
74
|
+
*
|
|
75
|
+
* The isolation handle is always torn down in `finally`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function runIsolatedSubprocess(opts: IsolatedRunOptions): Promise<SingleResult>;
|
|
78
|
+
export interface IsolationMergeOptions {
|
|
79
|
+
result: SingleResult;
|
|
80
|
+
repoRoot: string;
|
|
81
|
+
mergeMode: "patch" | "branch";
|
|
82
|
+
}
|
|
83
|
+
export interface IsolationMergeOutcome {
|
|
84
|
+
/** Trailing summary appended to the subagent's result text. May be empty. */
|
|
85
|
+
summary: string;
|
|
86
|
+
/**
|
|
87
|
+
* Tri-state apply outcome:
|
|
88
|
+
* - `true` — merge ran (or had nothing to apply) and left the repo clean.
|
|
89
|
+
* - `false` — merge attempted and failed; artifacts are preserved.
|
|
90
|
+
* - `null` — caller skipped the merge phase entirely (e.g. `apply=false`).
|
|
91
|
+
*/
|
|
92
|
+
changesApplied: boolean | null;
|
|
93
|
+
hadAnyChanges: boolean;
|
|
94
|
+
/** True iff the root branch actually merged — gates nested-repo patch application. */
|
|
95
|
+
mergedBranchForNestedPatches: boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Apply changes captured by {@link runIsolatedSubprocess} back to the parent
|
|
99
|
+
* repo: patch apply (patch mode) or cherry-pick + cleanup (branch mode).
|
|
100
|
+
*
|
|
101
|
+
* The caller decides whether to run this at all — eval `agent()` with
|
|
102
|
+
* `apply=False` skips this step and surfaces the patch artifact / branch name
|
|
103
|
+
* instead.
|
|
104
|
+
*/
|
|
105
|
+
export declare function mergeIsolatedChanges(opts: IsolationMergeOptions): Promise<IsolationMergeOutcome>;
|
|
106
|
+
export interface NestedPatchApplyOptions {
|
|
107
|
+
/** Subagent result carrying `nestedPatches`/`exitCode`/`aborted`. */
|
|
108
|
+
result: SingleResult;
|
|
109
|
+
repoRoot: string;
|
|
110
|
+
mergeMode: "patch" | "branch";
|
|
111
|
+
/** Parent merge outcome — patch mode skips nested apply when this is `false`. */
|
|
112
|
+
changesApplied: boolean | null;
|
|
113
|
+
/** Branch mode gates nested apply on whether the root branch merged. */
|
|
114
|
+
mergedBranchForNestedPatches: boolean;
|
|
115
|
+
/** Optional AI commit-message callback for nested commits; falls back to a generic message. */
|
|
116
|
+
commitMessage?: (diff: string) => Promise<string | null>;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Apply nested-repo patches after the parent merge phase. Centralizes the
|
|
120
|
+
* three-way gate (exitCode/aborted, patch-mode failed parent, branch-mode
|
|
121
|
+
* branch-merged) and the non-fatal failure handling so `TaskTool` and the
|
|
122
|
+
* eval `agent()` bridge use one implementation.
|
|
123
|
+
*
|
|
124
|
+
* Returns a system-notification suffix to append to the parent merge summary,
|
|
125
|
+
* or an empty string when nothing was applied or the nested apply succeeded.
|
|
126
|
+
*/
|
|
127
|
+
export declare function applyEligibleNestedPatches(opts: NestedPatchApplyOptions): Promise<string>;
|
|
128
|
+
export {};
|
|
@@ -33,10 +33,23 @@ export interface DeltaPatchResult {
|
|
|
33
33
|
export declare function captureDeltaPatch(isolationDir: string, baseline: WorktreeBaseline): Promise<DeltaPatchResult>;
|
|
34
34
|
/**
|
|
35
35
|
* Apply nested repo patches directly to their working directories after parent merge.
|
|
36
|
+
*
|
|
37
|
+
* Pre-existing dirty state in a nested repo is stashed before the patch is
|
|
38
|
+
* applied and popped back (with `--index` so staged WIP stays staged) after
|
|
39
|
+
* the commit, so unrelated user edits never get folded into the agent's
|
|
40
|
+
* commit. A failing `git stash pop` (e.g. user edits collide with the patched
|
|
41
|
+
* lines) leaves the stash entry intact, emits a `logger.warn`, and is
|
|
42
|
+
* returned to the caller as a human-readable warning string — the agent
|
|
43
|
+
* commit already landed, so this is a partial success the workflow needs to
|
|
44
|
+
* see, not a thrown failure.
|
|
45
|
+
*
|
|
46
|
+
* Returns the collected stash-restore warnings (empty when every nested repo
|
|
47
|
+
* was restored cleanly). Throws when the patch apply itself fails.
|
|
48
|
+
*
|
|
36
49
|
* @param commitMessage Optional async function to generate a commit message from the combined diff.
|
|
37
50
|
* If omitted or returns null, falls back to a generic message.
|
|
38
51
|
*/
|
|
39
|
-
export declare function applyNestedPatches(repoRoot: string, patches: NestedRepoPatch[], commitMessage?: (diff: string) => Promise<string | null>): Promise<
|
|
52
|
+
export declare function applyNestedPatches(repoRoot: string, patches: NestedRepoPatch[], commitMessage?: (diff: string) => Promise<string | null>): Promise<string[]>;
|
|
40
53
|
/**
|
|
41
54
|
* User-facing isolation mode names exposed by the `task.isolation.mode`
|
|
42
55
|
* setting. Mapped to a backend-kind hint via {@link parseIsolationMode};
|
package/dist/types/thinking.d.ts
CHANGED
|
@@ -55,6 +55,21 @@ export interface ConfiguredThinkingLevelMetadata {
|
|
|
55
55
|
export declare function parseConfiguredThinkingLevel(value: string | null | undefined): ConfiguredThinkingLevel | undefined;
|
|
56
56
|
/** Returns display metadata for a configured selector, including `auto`. */
|
|
57
57
|
export declare function getConfiguredThinkingLevelMetadata(level: ConfiguredThinkingLevel): ConfiguredThinkingLevelMetadata;
|
|
58
|
+
/**
|
|
59
|
+
* Thinking selectors accepted by the `--thinking` CLI flag, in display order:
|
|
60
|
+
* `off`, every concrete effort (`minimal`..`xhigh`), then `auto`. Single source
|
|
61
|
+
* for the flag's `options` list, shell completions, and the "invalid level"
|
|
62
|
+
* warning so all three stay in sync.
|
|
63
|
+
*/
|
|
64
|
+
export declare const CLI_THINKING_LEVELS: readonly string[];
|
|
65
|
+
/**
|
|
66
|
+
* Parses a `--thinking` CLI value. Accepts every {@link parseConfiguredThinkingLevel}
|
|
67
|
+
* selector (`off`, `auto`, `minimal`..`xhigh`, plus the `max` alias) but rejects
|
|
68
|
+
* `inherit`: an explicit `inherit` on the command line would suppress the
|
|
69
|
+
* settings/scoped-model fallback during startup resolution only to resolve back
|
|
70
|
+
* to the provider default, which is never what the user means.
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseCliThinkingLevel(value: string | null | undefined): ConfiguredThinkingLevel | undefined;
|
|
58
73
|
/**
|
|
59
74
|
* Resolves an auto-classified effort against the active model's supported
|
|
60
75
|
* range. Unlike {@link clampThinkingLevelForModel}, `auto` never resolves below
|