@oh-my-pi/pi-coding-agent 15.10.11 → 15.10.12
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 +44 -0
- package/dist/cli.js +5349 -5328
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli-commands.d.ts +12 -0
- package/dist/types/commands/launch.d.ts +4 -0
- package/dist/types/config/api-key-resolver.d.ts +3 -0
- package/dist/types/config/model-registry.d.ts +1 -0
- package/dist/types/config/model-resolver.d.ts +18 -0
- package/dist/types/config/settings-schema.d.ts +29 -1
- package/dist/types/config/settings.d.ts +7 -0
- package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
- package/dist/types/eval/py/executor.d.ts +5 -0
- package/dist/types/eval/py/kernel.d.ts +6 -1
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/extensibility/extensions/runner.d.ts +3 -2
- package/dist/types/extensibility/extensions/types.d.ts +3 -0
- package/dist/types/memory-backend/index.d.ts +1 -0
- package/dist/types/memory-backend/runtime.d.ts +4 -0
- package/dist/types/memory-backend/types.d.ts +66 -1
- package/dist/types/modes/index.d.ts +3 -3
- package/dist/types/modes/interactive-mode.d.ts +7 -2
- package/dist/types/modes/oauth-manual-input.d.ts +7 -0
- package/dist/types/modes/rpc/rpc-client.d.ts +39 -2
- package/dist/types/modes/rpc/rpc-mode.d.ts +31 -2
- package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +75 -1
- package/dist/types/modes/setup-wizard/index.d.ts +5 -1
- package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/secrets/index.d.ts +1 -1
- package/dist/types/secrets/obfuscator.d.ts +8 -2
- package/dist/types/session/agent-session.d.ts +14 -2
- package/dist/types/session/streaming-output.d.ts +23 -0
- package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +1 -0
- package/dist/types/slash-commands/types.d.ts +1 -1
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/task/index.d.ts +2 -2
- package/dist/types/task/types.d.ts +8 -0
- package/dist/types/thinking.d.ts +4 -0
- package/dist/types/tiny/title-client.d.ts +11 -0
- package/dist/types/tiny/title-protocol.d.ts +1 -0
- package/dist/types/tools/index.d.ts +6 -0
- package/dist/types/utils/git.d.ts +15 -2
- package/dist/types/utils/title-generator.d.ts +3 -2
- package/package.json +10 -10
- package/src/auto-thinking/classifier.ts +1 -0
- package/src/cli/args.ts +3 -0
- package/src/cli-commands.ts +29 -0
- package/src/cli.ts +8 -9
- package/src/commands/launch.ts +4 -0
- package/src/commit/model-selection.ts +3 -2
- package/src/config/api-key-resolver.ts +8 -6
- package/src/config/model-registry.ts +97 -30
- package/src/config/model-resolver.ts +60 -0
- package/src/config/settings-schema.ts +43 -15
- package/src/config/settings.ts +61 -3
- package/src/edit/hashline/execute.ts +39 -2
- package/src/edit/hashline/noop-loop-guard.ts +99 -0
- package/src/eval/completion-bridge.ts +1 -0
- package/src/eval/py/executor.ts +29 -7
- package/src/eval/py/index.ts +6 -1
- package/src/eval/py/kernel.ts +31 -11
- package/src/eval/py/runtime.ts +37 -0
- package/src/exec/bash-executor.ts +82 -3
- package/src/extensibility/extensions/get-commands-handler.ts +2 -1
- package/src/extensibility/extensions/runner.ts +6 -1
- package/src/extensibility/extensions/types.ts +3 -0
- package/src/hindsight/bank.ts +17 -2
- package/src/internal-urls/docs-index.generated.ts +3 -3
- package/src/main.ts +18 -6
- package/src/memories/index.ts +2 -0
- package/src/memory-backend/index.ts +1 -0
- package/src/memory-backend/local-backend.ts +9 -0
- package/src/memory-backend/off-backend.ts +9 -0
- package/src/memory-backend/runtime.ts +66 -0
- package/src/memory-backend/types.ts +81 -1
- package/src/mnemopi/backend.ts +151 -4
- package/src/modes/acp/acp-agent.ts +119 -11
- package/src/modes/components/assistant-message.ts +19 -21
- package/src/modes/components/footer.ts +3 -1
- package/src/modes/components/status-line/component.ts +118 -34
- package/src/modes/controllers/command-controller.ts +1 -1
- package/src/modes/controllers/input-controller.ts +1 -0
- package/src/modes/controllers/mcp-command-controller.ts +38 -3
- package/src/modes/index.ts +3 -21
- package/src/modes/interactive-mode.ts +39 -9
- package/src/modes/oauth-manual-input.ts +30 -3
- package/src/modes/rpc/rpc-client.ts +154 -3
- package/src/modes/rpc/rpc-mode.ts +97 -12
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +81 -1
- package/src/modes/setup-wizard/index.ts +12 -2
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/types.ts +2 -0
- package/src/sdk.ts +8 -1
- package/src/secrets/index.ts +8 -1
- package/src/secrets/obfuscator.ts +39 -18
- package/src/session/agent-session.ts +179 -54
- package/src/session/streaming-output.ts +166 -10
- package/src/slash-commands/acp-builtins.ts +24 -0
- package/src/slash-commands/builtin-registry.ts +20 -0
- package/src/slash-commands/types.ts +1 -1
- package/src/system-prompt.ts +14 -0
- package/src/task/executor.ts +13 -12
- package/src/task/index.ts +9 -8
- package/src/task/render.ts +18 -3
- package/src/task/types.ts +9 -0
- package/src/thinking.ts +7 -0
- package/src/tiny/title-client.ts +34 -5
- package/src/tiny/title-protocol.ts +1 -1
- package/src/tiny/worker.ts +6 -4
- package/src/tools/bash.ts +46 -5
- package/src/tools/image-gen.ts +11 -4
- package/src/tools/index.ts +13 -1
- package/src/tools/inspect-image.ts +1 -0
- package/src/utils/commit-message-generator.ts +1 -0
- package/src/utils/git.ts +267 -13
- package/src/utils/title-generator.ts +24 -5
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import * as fs from "node:fs/promises";
|
|
7
7
|
import { ExponentialYield } from "@oh-my-pi/pi-agent-core/utils/yield";
|
|
8
8
|
import { executeShell, type MinimizerOptions, Shell, type ShellRunResult } from "@oh-my-pi/pi-natives";
|
|
9
|
+
import { isExecutable, type ShellConfig } from "@oh-my-pi/pi-utils/procmgr";
|
|
9
10
|
import { Settings, type ShellMinimizerSettings } from "../config/settings";
|
|
10
11
|
import { OutputSink } from "../session/streaming-output";
|
|
11
12
|
import { resolveOutputMaxColumns, resolveOutputSinkHeadBytes } from "../tools/output-meta";
|
|
@@ -22,6 +23,8 @@ export interface BashExecutorOptions {
|
|
|
22
23
|
sessionKey?: string;
|
|
23
24
|
/** Additional environment variables to inject */
|
|
24
25
|
env?: Record<string, string>;
|
|
26
|
+
/** Run through the configured user shell instead of brush parsing directly. */
|
|
27
|
+
useUserShell?: boolean;
|
|
25
28
|
/** Artifact path/id for full output storage */
|
|
26
29
|
artifactPath?: string;
|
|
27
30
|
artifactId?: string;
|
|
@@ -95,13 +98,86 @@ export function buildMinimizerOptions(group: ShellMinimizerSettings): MinimizerO
|
|
|
95
98
|
only: group.only.length > 0 ? group.only : undefined,
|
|
96
99
|
except: group.except.length > 0 ? group.except : undefined,
|
|
97
100
|
maxCaptureBytes: group.maxCaptureBytes,
|
|
101
|
+
sourceOutlineLevel: group.sourceOutlineLevel === "default" ? undefined : group.sourceOutlineLevel,
|
|
102
|
+
legacyFilters: group.legacyFilters,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function shellBasename(shell: string): string {
|
|
107
|
+
return shell.replace(/\\/g, "/").split("/").pop()?.toLowerCase() ?? "";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function isBashShell(shell: string): boolean {
|
|
111
|
+
const basename = shellBasename(shell);
|
|
112
|
+
return basename.includes("bash");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function needsInteractiveShellArg(shell: string): boolean {
|
|
116
|
+
const basename = shellBasename(shell);
|
|
117
|
+
return basename.includes("zsh");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function supportsAutoUserShell(shell: string): boolean {
|
|
121
|
+
const basename = shellBasename(shell);
|
|
122
|
+
return basename.includes("bash") || basename.includes("zsh") || basename.includes("fish");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function hasInteractiveShellArg(args: string[]): boolean {
|
|
126
|
+
return args.some(arg => arg === "--interactive" || /^-[^-]*i/.test(arg));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function ensureInteractiveShellArgs(shell: string, args: string[]): string[] {
|
|
130
|
+
if (!needsInteractiveShellArg(shell) || hasInteractiveShellArg(args)) return args;
|
|
131
|
+
|
|
132
|
+
const commandIndex = args.findIndex(arg => arg === "-c" || arg === "--command");
|
|
133
|
+
if (commandIndex !== -1) {
|
|
134
|
+
return [...args.slice(0, commandIndex), "-i", ...args.slice(commandIndex)];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const compactCommandIndex = args.findIndex(arg => /^-[^-]*c[^-]*$/.test(arg));
|
|
138
|
+
if (compactCommandIndex !== -1) {
|
|
139
|
+
return args.map((arg, index) => (index === compactCommandIndex ? arg.replace("c", "ic") : arg));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return [...args, "-i"];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function quoteShellArg(value: string): string {
|
|
146
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function buildUserShellCommand(shell: string, args: string[], command: string): string {
|
|
150
|
+
return [shell, ...ensureInteractiveShellArgs(shell, args), command].map(quoteShellArg).join(" ");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function resolveUserShellConfig(settings: Settings, baseConfig: ShellConfig): ShellConfig {
|
|
154
|
+
const customShellPath = settings.get("shellPath");
|
|
155
|
+
const envShell = Bun.env.SHELL;
|
|
156
|
+
if (customShellPath || process.platform === "win32" || !envShell || envShell === baseConfig.shell) {
|
|
157
|
+
return baseConfig;
|
|
158
|
+
}
|
|
159
|
+
if (!supportsAutoUserShell(envShell) || !isExecutable(envShell)) {
|
|
160
|
+
return baseConfig;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
...baseConfig,
|
|
165
|
+
shell: envShell,
|
|
166
|
+
env: {
|
|
167
|
+
...baseConfig.env,
|
|
168
|
+
SHELL: envShell,
|
|
169
|
+
},
|
|
98
170
|
};
|
|
99
171
|
}
|
|
100
172
|
|
|
101
173
|
export async function executeBash(command: string, options?: BashExecutorOptions): Promise<BashResult> {
|
|
102
174
|
const settings = await Settings.init();
|
|
103
|
-
const
|
|
104
|
-
const
|
|
175
|
+
const baseShellConfig = settings.getShellConfig();
|
|
176
|
+
const shellConfig =
|
|
177
|
+
options?.useUserShell === true ? resolveUserShellConfig(settings, baseShellConfig) : baseShellConfig;
|
|
178
|
+
const { shell, args, env: shellEnv, prefix } = shellConfig;
|
|
179
|
+
const bashShell = isBashShell(shell);
|
|
180
|
+
const snapshotPath = bashShell ? await getOrCreateSnapshot(shell, shellEnv) : null;
|
|
105
181
|
|
|
106
182
|
const minimizer = buildMinimizerOptions(settings.getGroup("shellMinimizer"));
|
|
107
183
|
|
|
@@ -110,7 +186,10 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
110
186
|
|
|
111
187
|
// Apply command prefix if configured
|
|
112
188
|
const prefixedCommand = prefix ? `${prefix} ${command}` : command;
|
|
113
|
-
const finalCommand =
|
|
189
|
+
const finalCommand =
|
|
190
|
+
options?.useUserShell === true && !bashShell
|
|
191
|
+
? buildUserShellCommand(shell, args, prefixedCommand)
|
|
192
|
+
: prefixedCommand;
|
|
114
193
|
|
|
115
194
|
// Create output sink for truncation and artifact handling
|
|
116
195
|
const sink = new OutputSink({
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* themselves. Each frontend (interactive-mode, ACP) prepends its own builtins.
|
|
16
16
|
*/
|
|
17
17
|
import type { SkillsSettings } from "../../config/settings";
|
|
18
|
+
import { BUILTIN_SLASH_COMMAND_RESERVED_NAMES } from "../../slash-commands/builtin-registry";
|
|
18
19
|
import type { CustomCommandSource, LoadedCustomCommand } from "../custom-commands";
|
|
19
20
|
import { getSkillSlashCommandName, type Skill } from "../skills";
|
|
20
21
|
import type { SlashCommandInfo, SlashCommandLocation } from "../slash-commands";
|
|
@@ -32,7 +33,7 @@ export function getSessionSlashCommands(session: CommandsCapableSession): SlashC
|
|
|
32
33
|
|
|
33
34
|
const runner = session.extensionRunner;
|
|
34
35
|
if (runner) {
|
|
35
|
-
for (const cmd of runner.getRegisteredCommands()) {
|
|
36
|
+
for (const cmd of runner.getRegisteredCommands(BUILTIN_SLASH_COMMAND_RESERVED_NAMES)) {
|
|
36
37
|
out.push({
|
|
37
38
|
name: cmd.name,
|
|
38
39
|
description: cmd.description,
|
|
@@ -6,6 +6,7 @@ import type { CredentialDisabledEvent, ImageContent, Model, ProviderResponseMeta
|
|
|
6
6
|
import type { KeyId } from "@oh-my-pi/pi-tui";
|
|
7
7
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
8
8
|
import type { ModelRegistry } from "../../config/model-registry";
|
|
9
|
+
import type { MemoryRuntimeContext } from "../../memory-backend";
|
|
9
10
|
import { type Theme, theme } from "../../modes/theme/theme";
|
|
10
11
|
import type { SessionManager } from "../../session/session-manager";
|
|
11
12
|
import type {
|
|
@@ -187,6 +188,7 @@ export class ExtensionRunner {
|
|
|
187
188
|
#switchSessionHandler: SwitchSessionHandler = async () => ({ cancelled: false });
|
|
188
189
|
#reloadHandler: () => Promise<void> = async () => {};
|
|
189
190
|
#shutdownHandler: ShutdownHandler = () => {};
|
|
191
|
+
#getMemoryFn?: () => MemoryRuntimeContext | undefined;
|
|
190
192
|
#commandDiagnostics: Array<{ type: string; message: string; path: string }> = [];
|
|
191
193
|
#initialized = false;
|
|
192
194
|
/**
|
|
@@ -204,8 +206,10 @@ export class ExtensionRunner {
|
|
|
204
206
|
private readonly cwd: string,
|
|
205
207
|
private readonly sessionManager: SessionManager,
|
|
206
208
|
private readonly modelRegistry: ModelRegistry,
|
|
209
|
+
getMemory?: () => MemoryRuntimeContext | undefined,
|
|
207
210
|
) {
|
|
208
211
|
this.#uiContext = noOpUIContext;
|
|
212
|
+
this.#getMemoryFn = getMemory;
|
|
209
213
|
}
|
|
210
214
|
|
|
211
215
|
initialize(
|
|
@@ -427,7 +431,7 @@ export class ExtensionRunner {
|
|
|
427
431
|
return this.extensions.flatMap(ext => ext.assistantThinkingRenderers);
|
|
428
432
|
}
|
|
429
433
|
|
|
430
|
-
getRegisteredCommands(reserved?:
|
|
434
|
+
getRegisteredCommands(reserved?: ReadonlySet<string>): RegisteredCommand[] {
|
|
431
435
|
this.#commandDiagnostics = [];
|
|
432
436
|
|
|
433
437
|
const commands = new Map<string, RegisteredCommand>();
|
|
@@ -480,6 +484,7 @@ export class ExtensionRunner {
|
|
|
480
484
|
hasPendingMessages: () => this.#hasPendingMessagesFn(),
|
|
481
485
|
shutdown: () => this.#shutdownHandler(),
|
|
482
486
|
getSystemPrompt: () => this.#getSystemPromptFn(),
|
|
487
|
+
memory: this.#getMemoryFn?.(),
|
|
483
488
|
};
|
|
484
489
|
}
|
|
485
490
|
|
|
@@ -40,6 +40,7 @@ import type { EditToolDetails } from "../../edit";
|
|
|
40
40
|
import type { PythonResult } from "../../eval/py/executor";
|
|
41
41
|
import type { BashResult } from "../../exec/bash-executor";
|
|
42
42
|
import type { ExecOptions, ExecResult } from "../../exec/exec";
|
|
43
|
+
import type { MemoryRuntimeContext } from "../../memory-backend";
|
|
43
44
|
import type { CustomEditor } from "../../modes/components/custom-editor";
|
|
44
45
|
import type { Theme } from "../../modes/theme/theme";
|
|
45
46
|
import type { CustomMessage } from "../../session/messages";
|
|
@@ -319,6 +320,8 @@ export interface ExtensionContext {
|
|
|
319
320
|
shutdown(): void;
|
|
320
321
|
/** Get the current effective system prompt. */
|
|
321
322
|
getSystemPrompt(): string[];
|
|
323
|
+
/** Structured memory runtime for status/search/save across the configured backend. */
|
|
324
|
+
memory?: MemoryRuntimeContext;
|
|
322
325
|
}
|
|
323
326
|
|
|
324
327
|
/**
|
package/src/hindsight/bank.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
import * as path from "node:path";
|
|
24
24
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
25
|
+
import * as git from "../utils/git";
|
|
25
26
|
import type { HindsightApi } from "./client";
|
|
26
27
|
import type { HindsightConfig } from "./config";
|
|
27
28
|
|
|
@@ -53,10 +54,24 @@ function baseBankId(config: HindsightConfig): string {
|
|
|
53
54
|
return prefix ? `${prefix}-${base}` : base;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* Best-effort project label from a working-directory path.
|
|
59
|
+
*
|
|
60
|
+
* When `directory` lives inside a git repository we resolve the primary
|
|
61
|
+
* checkout root (or the shared common dir for bare-repo worktrees) via
|
|
62
|
+
* {@link git.repo.primaryRootSync} and basename that, so every linked
|
|
63
|
+
* worktree of one repo shares the same `project:<name>` tag.
|
|
64
|
+
* Outside a repo (or when resolution fails), fall back to the cwd basename.
|
|
65
|
+
*
|
|
66
|
+
* Sync only: this runs on the hot path of `computeBankScope`, which is
|
|
67
|
+
* exposed as a sync API to callers like `backend.ts` and must stay sync.
|
|
68
|
+
* `git.repo.primaryRootSync` walks `.git`/`commondir` with sync file reads —
|
|
69
|
+
* no subprocess — so the cost is one or two `stat`s and a small `readFile`.
|
|
70
|
+
*/
|
|
57
71
|
function projectLabel(directory: string): string {
|
|
58
72
|
if (!directory) return UNKNOWN_PROJECT;
|
|
59
|
-
|
|
73
|
+
const primary = git.repo.primaryRootSync(directory);
|
|
74
|
+
return path.basename(primary ?? directory) || UNKNOWN_PROJECT;
|
|
60
75
|
}
|
|
61
76
|
|
|
62
77
|
/**
|