@oh-my-pi/pi-coding-agent 14.2.1 → 14.3.0
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 +59 -0
- package/package.json +19 -19
- package/src/cli/args.ts +10 -1
- package/src/cli/shell-cli.ts +15 -3
- package/src/config/settings-schema.ts +60 -1
- package/src/debug/system-info.ts +6 -2
- package/src/discovery/claude.ts +58 -36
- package/src/discovery/opencode.ts +20 -2
- package/src/edit/index.ts +2 -1
- package/src/edit/modes/chunk.ts +132 -56
- package/src/edit/modes/hashline.ts +36 -11
- package/src/edit/renderer.ts +98 -133
- package/src/edit/streaming.ts +351 -0
- package/src/exec/bash-executor.ts +60 -5
- package/src/internal-urls/docs-index.generated.ts +5 -5
- package/src/internal-urls/pi-protocol.ts +0 -2
- package/src/lsp/client.ts +8 -1
- package/src/lsp/defaults.json +2 -1
- package/src/modes/acp/acp-agent.ts +76 -2
- package/src/modes/components/assistant-message.ts +1 -34
- package/src/modes/components/hook-editor.ts +1 -1
- package/src/modes/components/tool-execution.ts +111 -101
- package/src/modes/controllers/input-controller.ts +1 -1
- package/src/modes/interactive-mode.ts +0 -2
- package/src/modes/theme/mermaid-cache.ts +13 -52
- package/src/modes/theme/theme.ts +2 -2
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/tools/browser.md +1 -0
- package/src/prompts/tools/chunk-edit.md +25 -22
- package/src/prompts/tools/gh-pr-push.md +2 -1
- package/src/prompts/tools/grep.md +4 -3
- package/src/prompts/tools/lsp.md +6 -0
- package/src/prompts/tools/read-chunk.md +46 -7
- package/src/prompts/tools/read.md +7 -4
- package/src/sdk.ts +8 -5
- package/src/session/agent-session.ts +36 -20
- package/src/session/session-manager.ts +228 -57
- package/src/session/streaming-output.ts +11 -0
- package/src/system-prompt.ts +7 -2
- package/src/task/executor.ts +1 -0
- package/src/tools/bash.ts +13 -0
- package/src/tools/gh.ts +6 -16
- package/src/tools/sqlite-reader.ts +116 -3
- package/src/web/search/providers/codex.ts +129 -6
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Uses brush-core via native bindings for shell execution.
|
|
5
5
|
*/
|
|
6
6
|
import * as fs from "node:fs/promises";
|
|
7
|
-
import { executeShell, Shell } from "@oh-my-pi/pi-natives";
|
|
8
|
-
import { Settings } from "../config/settings";
|
|
7
|
+
import { executeShell, type MinimizerOptions, Shell } from "@oh-my-pi/pi-natives";
|
|
8
|
+
import { Settings, type ShellMinimizerSettings } from "../config/settings";
|
|
9
9
|
import { OutputSink } from "../session/streaming-output";
|
|
10
10
|
import { getOrCreateSnapshot } from "../utils/shell-snapshot";
|
|
11
11
|
import { NON_INTERACTIVE_ENV } from "./non-interactive-env";
|
|
@@ -22,6 +22,17 @@ export interface BashExecutorOptions {
|
|
|
22
22
|
/** Artifact path/id for full output storage */
|
|
23
23
|
artifactPath?: string;
|
|
24
24
|
artifactId?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Invoked when the native minimizer rewrote the command's output, giving
|
|
27
|
+
* the caller a chance to persist the lossless original capture (typically
|
|
28
|
+
* via the session's `ArtifactManager`). The returned id is spliced into
|
|
29
|
+
* the sink output as `artifact://<id>` so the agent can retrieve the raw
|
|
30
|
+
* bytes. Return `undefined` to skip the footer.
|
|
31
|
+
*/
|
|
32
|
+
onMinimizedSave?: (
|
|
33
|
+
originalText: string,
|
|
34
|
+
info: { filter: string; inputBytes: number; outputBytes: number },
|
|
35
|
+
) => Promise<string | undefined>;
|
|
25
36
|
}
|
|
26
37
|
|
|
27
38
|
export interface BashResult {
|
|
@@ -53,10 +64,24 @@ async function resolveShellCwd(cwd: string | undefined): Promise<string | undefi
|
|
|
53
64
|
}
|
|
54
65
|
}
|
|
55
66
|
|
|
67
|
+
function buildMinimizerOptions(group: ShellMinimizerSettings): MinimizerOptions | undefined {
|
|
68
|
+
if (!group.enabled) return undefined;
|
|
69
|
+
return {
|
|
70
|
+
enabled: true,
|
|
71
|
+
settingsPath: group.settingsPath || undefined,
|
|
72
|
+
only: group.only.length > 0 ? group.only : undefined,
|
|
73
|
+
except: group.except.length > 0 ? group.except : undefined,
|
|
74
|
+
maxCaptureBytes: group.maxCaptureBytes,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
56
78
|
export async function executeBash(command: string, options?: BashExecutorOptions): Promise<BashResult> {
|
|
57
79
|
const settings = await Settings.init();
|
|
58
80
|
const { shell, env: shellEnv, prefix } = settings.getShellConfig();
|
|
59
81
|
const snapshotPath = shell.includes("bash") ? await getOrCreateSnapshot(shell, shellEnv) : null;
|
|
82
|
+
|
|
83
|
+
const minimizer = buildMinimizerOptions(settings.getGroup("shellMinimizer"));
|
|
84
|
+
|
|
60
85
|
const commandCwd = await resolveShellCwd(options?.cwd);
|
|
61
86
|
const commandEnv = options?.env ? { ...NON_INTERACTIVE_ENV, ...options.env } : NON_INTERACTIVE_ENV;
|
|
62
87
|
|
|
@@ -89,7 +114,7 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
89
114
|
};
|
|
90
115
|
}
|
|
91
116
|
|
|
92
|
-
const sessionKey = buildSessionKey(shell, prefix, snapshotPath, shellEnv, options?.sessionKey);
|
|
117
|
+
const sessionKey = buildSessionKey(shell, prefix, snapshotPath, shellEnv, options?.sessionKey, minimizer);
|
|
93
118
|
const persistentSessionBroken = brokenShellSessions.has(sessionKey);
|
|
94
119
|
if (persistentSessionBroken) {
|
|
95
120
|
shellSessions.delete(sessionKey);
|
|
@@ -97,7 +122,11 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
97
122
|
|
|
98
123
|
let shellSession = persistentSessionBroken ? undefined : shellSessions.get(sessionKey);
|
|
99
124
|
if (!shellSession && !persistentSessionBroken) {
|
|
100
|
-
shellSession = new Shell({
|
|
125
|
+
shellSession = new Shell({
|
|
126
|
+
sessionEnv: shellEnv,
|
|
127
|
+
snapshotPath: snapshotPath ?? undefined,
|
|
128
|
+
minimizer,
|
|
129
|
+
});
|
|
101
130
|
shellSessions.set(sessionKey, shellSession);
|
|
102
131
|
}
|
|
103
132
|
const userSignal = options?.signal;
|
|
@@ -152,6 +181,7 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
152
181
|
env: commandEnv,
|
|
153
182
|
sessionEnv: shellEnv,
|
|
154
183
|
snapshotPath: snapshotPath ?? undefined,
|
|
184
|
+
minimizer,
|
|
155
185
|
timeoutMs: options?.timeout,
|
|
156
186
|
signal: runAbortController.signal,
|
|
157
187
|
},
|
|
@@ -204,6 +234,27 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
204
234
|
};
|
|
205
235
|
}
|
|
206
236
|
|
|
237
|
+
// When the native minimizer rewrote the output, swap the sink's accumulated
|
|
238
|
+
// raw stream for the minimized text, persist the original as a session
|
|
239
|
+
// artifact, and splice an `artifact://<id>` footer into the visible text so
|
|
240
|
+
// the agent can retrieve the raw bytes losslessly.
|
|
241
|
+
const minimized = winner.result.minimized;
|
|
242
|
+
if (minimized) {
|
|
243
|
+
sink.replace(minimized.text);
|
|
244
|
+
if (options?.onMinimizedSave) {
|
|
245
|
+
const artifactId = await options.onMinimizedSave(minimized.originalText, {
|
|
246
|
+
filter: minimized.filter,
|
|
247
|
+
inputBytes: minimized.inputBytes,
|
|
248
|
+
outputBytes: minimized.outputBytes,
|
|
249
|
+
});
|
|
250
|
+
if (artifactId) {
|
|
251
|
+
sink.push(
|
|
252
|
+
`\n… full output: artifact://${artifactId} (${minimized.inputBytes} → ${minimized.outputBytes} bytes)\n`,
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
207
258
|
// Normal completion
|
|
208
259
|
return {
|
|
209
260
|
exitCode: winner.result.exitCode,
|
|
@@ -232,9 +283,13 @@ function buildSessionKey(
|
|
|
232
283
|
snapshotPath: string | null,
|
|
233
284
|
env: Record<string, string>,
|
|
234
285
|
agentSessionKey?: string,
|
|
286
|
+
minimizer?: MinimizerOptions,
|
|
235
287
|
): string {
|
|
236
288
|
const entries = Object.entries(env);
|
|
237
289
|
entries.sort(([a], [b]) => a.localeCompare(b));
|
|
238
290
|
const envSerialized = entries.map(([key, value]) => `${key}=${value}`).join("\n");
|
|
239
|
-
|
|
291
|
+
const minimizerSerialized = minimizer ? JSON.stringify(minimizer) : "";
|
|
292
|
+
return [agentSessionKey ?? "", shell, prefix ?? "", snapshotPath ?? "", envSerialized, minimizerSerialized].join(
|
|
293
|
+
"\n",
|
|
294
|
+
);
|
|
240
295
|
}
|