@oh-my-pi/pi-coding-agent 16.1.21 → 16.1.23
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 +36 -1
- package/dist/cli.js +3659 -3517
- package/dist/types/cli/gc-cli.d.ts +58 -0
- package/dist/types/commands/gc.d.ts +37 -0
- package/dist/types/config/settings-schema.d.ts +54 -0
- package/dist/types/config/settings.d.ts +11 -0
- package/dist/types/mcp/transports/stdio.d.ts +25 -1
- package/dist/types/mcp/transports/stdio.test.d.ts +1 -0
- package/dist/types/modes/theme/mermaid-rendering.test.d.ts +1 -0
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/session/session-listing.d.ts +10 -1
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/tools/plan-mode-guard.d.ts +7 -0
- package/package.json +12 -12
- package/scripts/bench-guard.ts +1 -1
- package/src/cli/gc-cli.ts +939 -0
- package/src/cli-commands.ts +1 -0
- package/src/commands/gc.ts +46 -0
- package/src/config/settings-schema.ts +45 -0
- package/src/config/settings.ts +44 -6
- package/src/edit/hashline/filesystem.ts +11 -6
- package/src/eval/__tests__/julia-prelude.test.ts +18 -0
- package/src/eval/jl/runner.jl +7 -1
- package/src/extensibility/plugins/legacy-pi-bundled-keys.ts +2 -0
- package/src/extensibility/plugins/legacy-pi-bundled-registry.ts +6 -0
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/lsp/index.ts +8 -1
- package/src/mcp/oauth-discovery.ts +62 -15
- package/src/mcp/transports/stdio.test.ts +45 -0
- package/src/mcp/transports/stdio.ts +46 -12
- package/src/modes/controllers/input-controller.ts +2 -2
- package/src/modes/controllers/selector-controller.ts +10 -0
- package/src/modes/interactive-mode.ts +26 -9
- package/src/modes/theme/mermaid-rendering.test.ts +53 -0
- package/src/modes/theme/theme.ts +33 -14
- package/src/prompts/system/plan-mode-active.md +9 -0
- package/src/prompts/system/system-prompt.md +2 -0
- package/src/sdk.ts +43 -4
- package/src/session/agent-session.ts +323 -62
- package/src/session/session-listing.ts +35 -2
- package/src/slash-commands/builtin-registry.ts +20 -2
- package/src/system-prompt.ts +4 -0
- package/src/tools/acp-bridge.ts +6 -1
- package/src/tools/plan-mode-guard.ts +26 -13
- package/src/utils/edit-mode.ts +19 -2
- package/src/utils/shell-snapshot.ts +1 -1
package/src/tools/acp-bridge.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import type { ToolSession } from ".";
|
|
11
11
|
import { invalidateFsScanAfterWrite } from "./fs-cache-invalidation";
|
|
12
12
|
import { isInternalUrlPath } from "./path-utils";
|
|
13
|
-
import { resolvePlanPath } from "./plan-mode-guard";
|
|
13
|
+
import { resolvePlanPath, targetsLocalSandbox } from "./plan-mode-guard";
|
|
14
14
|
import { ToolError } from "./tool-errors";
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -26,6 +26,11 @@ export function shouldRouteWriteThroughBridge(
|
|
|
26
26
|
absolutePath: string,
|
|
27
27
|
): boolean {
|
|
28
28
|
if (isInternalUrlPath(requestedPath)) return false;
|
|
29
|
+
// OMP-owned session artifacts (plan files, scratch notes) must stay off the
|
|
30
|
+
// editor buffer even when addressed by their absolute sandbox path — e.g.
|
|
31
|
+
// after tag-based path recovery rebinds a bare `plan.md#tag` onto the
|
|
32
|
+
// `local://` artifact, `requestedPath` is the absolute path, not the URL.
|
|
33
|
+
if (targetsLocalSandbox(session, absolutePath)) return false;
|
|
29
34
|
|
|
30
35
|
const state = session.getPlanModeState?.();
|
|
31
36
|
if (!state?.enabled || !isInternalUrlPath(state.planFilePath)) return true;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { HL_FILE_HASH_LENGTH, HL_FILE_HASH_SEP, HL_FILE_PREFIX, HL_FILE_SUFFIX } from "@oh-my-pi/hashline";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
type LocalProtocolOptions,
|
|
6
|
+
resolveLocalRoot,
|
|
7
|
+
resolveLocalUrlToPath,
|
|
8
|
+
resolveVaultUrlToPath,
|
|
9
|
+
} from "../internal-urls";
|
|
5
10
|
import type { ToolSession } from ".";
|
|
6
11
|
import { normalizeLocalScheme, resolveToCwd } from "./path-utils";
|
|
7
12
|
import { ToolError } from "./tool-errors";
|
|
@@ -10,16 +15,27 @@ const VAULT_SCHEME_PREFIX = "vault:";
|
|
|
10
15
|
const LOCAL_SCHEME_PREFIX = "local:";
|
|
11
16
|
const HL_TRAILING_TAG_RE = new RegExp(`${HL_FILE_HASH_SEP}[0-9A-Fa-f]{${HL_FILE_HASH_LENGTH}}$`);
|
|
12
17
|
|
|
18
|
+
/** Resolve the `local://` options the session uses, preferring its own
|
|
19
|
+
* {@link LocalProtocolOptions} (the mapping `read`/`write`/`eval` resolve
|
|
20
|
+
* through) over the bare `getArtifactsDir`/`getSessionId` pair. Subagents and
|
|
21
|
+
* multi-session hosts (cmux/ACP, embedded SDK) pin `local://` to a parent/foreign
|
|
22
|
+
* root via `localProtocolOptions`; the sandbox root the plan-mode guard derives
|
|
23
|
+
* must match where the artifact actually lives, or it rejects a legitimate plan
|
|
24
|
+
* edit (and tag-based path recovery onto the sandbox would miss it). */
|
|
25
|
+
function planLocalProtocolOptions(session: ToolSession): LocalProtocolOptions {
|
|
26
|
+
return (
|
|
27
|
+
session.localProtocolOptions ?? {
|
|
28
|
+
getArtifactsDir: () => session.getArtifactsDir?.() ?? null,
|
|
29
|
+
getSessionId: () => session.getSessionId?.() ?? null,
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
13
34
|
/** Resolve the absolute path of the session's `local://` artifact sandbox.
|
|
14
35
|
* Returns `null` when the session has no artifact wiring (e.g. tests). */
|
|
15
36
|
function localSandboxRoot(session: ToolSession): string | null {
|
|
16
37
|
try {
|
|
17
|
-
return path.resolve(
|
|
18
|
-
resolveLocalRoot({
|
|
19
|
-
getArtifactsDir: session.getArtifactsDir,
|
|
20
|
-
getSessionId: session.getSessionId,
|
|
21
|
-
}),
|
|
22
|
-
);
|
|
38
|
+
return path.resolve(resolveLocalRoot(planLocalProtocolOptions(session)));
|
|
23
39
|
} catch {
|
|
24
40
|
return null;
|
|
25
41
|
}
|
|
@@ -62,8 +78,8 @@ export function unwrapHashlineHeaderPath(targetPath: string): string {
|
|
|
62
78
|
* always agree on the absolute target (including bracketed hashline headers,
|
|
63
79
|
* `local://` URLs, and bare absolute paths). Files inside the sandbox are not
|
|
64
80
|
* part of the working tree, so plan mode treats them as freely writable
|
|
65
|
-
* scratch/plan space. */
|
|
66
|
-
function targetsLocalSandbox(session: ToolSession, targetPath: string): boolean {
|
|
81
|
+
* scratch/plan space — and tag-based path recovery may rebind onto them. */
|
|
82
|
+
export function targetsLocalSandbox(session: ToolSession, targetPath: string): boolean {
|
|
67
83
|
const root = localSandboxRoot(session);
|
|
68
84
|
if (!root) return false;
|
|
69
85
|
let resolved: string;
|
|
@@ -99,10 +115,7 @@ export function resolvePlanPath(session: ToolSession, targetPath: string): strin
|
|
|
99
115
|
const unwrapped = unwrapHashlineHeaderPath(targetPath);
|
|
100
116
|
const normalized = normalizeLocalScheme(unwrapped);
|
|
101
117
|
if (normalized.startsWith(LOCAL_SCHEME_PREFIX)) {
|
|
102
|
-
return resolveLocalUrlToPath(normalized,
|
|
103
|
-
getArtifactsDir: session.getArtifactsDir,
|
|
104
|
-
getSessionId: session.getSessionId,
|
|
105
|
-
});
|
|
118
|
+
return resolveLocalUrlToPath(normalized, planLocalProtocolOptions(session));
|
|
106
119
|
}
|
|
107
120
|
|
|
108
121
|
if (normalized.startsWith(VAULT_SCHEME_PREFIX)) {
|
package/src/utils/edit-mode.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $env } from "@oh-my-pi/pi-utils";
|
|
1
|
+
import { $env, $flag } from "@oh-my-pi/pi-utils";
|
|
2
2
|
|
|
3
3
|
export type EditMode = "replace" | "patch" | "hashline" | "apply_patch";
|
|
4
4
|
|
|
@@ -13,6 +13,19 @@ const EDIT_MODE_IDS = {
|
|
|
13
13
|
|
|
14
14
|
export const EDIT_MODES = Object.keys(EDIT_MODE_IDS) as EditMode[];
|
|
15
15
|
|
|
16
|
+
const HASHLINE_EXCLUDED_MODEL_MODES: Array<{ pattern: string; mode: EditMode }> = [
|
|
17
|
+
{ pattern: "kimi", mode: "replace" },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
function resolveHashlineExcludedModelMode(model: string | undefined): EditMode | null {
|
|
21
|
+
if (!model) return null;
|
|
22
|
+
const modelLower = model.toLowerCase();
|
|
23
|
+
for (const entry of HASHLINE_EXCLUDED_MODEL_MODES) {
|
|
24
|
+
if (modelLower.includes(entry.pattern)) return entry.mode;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
export function normalizeEditMode(mode?: string | null): EditMode | undefined {
|
|
17
30
|
if (!mode) return undefined;
|
|
18
31
|
return EDIT_MODE_IDS[mode as keyof typeof EDIT_MODE_IDS];
|
|
@@ -37,5 +50,9 @@ export function resolveEditMode(session: EditModeSessionLike): EditMode {
|
|
|
37
50
|
if (envMode) return envMode;
|
|
38
51
|
|
|
39
52
|
const settingsMode = normalizeEditMode(String(session.settings.get("edit.mode") ?? ""));
|
|
40
|
-
|
|
53
|
+
const mode = settingsMode ?? DEFAULT_EDIT_MODE;
|
|
54
|
+
if (mode === "hashline" && !$flag("PI_STRICT_EDIT_MODE")) {
|
|
55
|
+
return resolveHashlineExcludedModelMode(activeModel) ?? mode;
|
|
56
|
+
}
|
|
57
|
+
return mode;
|
|
41
58
|
}
|
|
@@ -17,7 +17,7 @@ const SNAPSHOT_TIMEOUT_MS = 2_000;
|
|
|
17
17
|
/**
|
|
18
18
|
* Characters that force brush's primitive alias expander down a path it does
|
|
19
19
|
* not implement. brush-core resolves aliases via `value.split_ascii_whitespace()`
|
|
20
|
-
* (`crates/brush-core
|
|
20
|
+
* (`crates/vendor/brush-core/src/interp.rs:1500`, tracking
|
|
21
21
|
* https://github.com/reubeno/brush/issues/57): the resulting pieces are dropped
|
|
22
22
|
* into argv verbatim instead of going through the shell parser. Any alias body
|
|
23
23
|
* containing subshells `(...)`, pipes `|`, redirections `<` `>`, separators
|