@oh-my-pi/pi-coding-agent 15.0.0 → 15.0.1
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 +41 -0
- package/examples/extensions/plan-mode.ts +0 -1
- package/package.json +9 -9
- package/scripts/build-binary.ts +5 -0
- package/src/autoresearch/helpers.ts +17 -0
- package/src/autoresearch/tools/log-experiment.ts +9 -17
- package/src/autoresearch/tools/run-experiment.ts +2 -17
- package/src/capability/skill.ts +7 -0
- package/src/cli/list-models.ts +1 -1
- package/src/cli/shell-cli.ts +3 -13
- package/src/cli/update-cli.ts +1 -1
- package/src/cli.ts +10 -29
- package/src/commit/agentic/tools/propose-changelog.ts +8 -1
- package/src/commit/analysis/conventional.ts +8 -66
- package/src/commit/map-reduce/reduce-phase.ts +6 -65
- package/src/commit/pipeline.ts +2 -2
- package/src/commit/shared-llm.ts +89 -0
- package/src/config/config-file.ts +210 -0
- package/src/config/model-equivalence.ts +8 -11
- package/src/config/model-registry.ts +13 -2
- package/src/config/model-resolver.ts +1 -4
- package/src/config/settings-schema.ts +71 -1
- package/src/config/settings.ts +1 -1
- package/src/config.ts +3 -219
- package/src/edit/renderer.ts +7 -1
- package/src/eval/js/executor.ts +3 -0
- package/src/eval/js/shared/rewrite-imports.ts +2 -2
- package/src/eval/py/executor.ts +5 -0
- package/src/exa/factory.ts +2 -2
- package/src/exa/mcp-client.ts +74 -1
- package/src/exec/bash-executor.ts +5 -1
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +0 -11
- package/src/extensibility/extensions/runner.ts +1 -1
- package/src/extensibility/extensions/types.ts +89 -223
- package/src/extensibility/hooks/types.ts +89 -314
- package/src/extensibility/shared-events.ts +343 -0
- package/src/extensibility/skills.ts +9 -0
- package/src/goals/index.ts +3 -0
- package/src/goals/runtime.ts +500 -0
- package/src/goals/state.ts +37 -0
- package/src/goals/tools/goal-tool.ts +237 -0
- package/src/hashline/anchors.ts +2 -2
- package/src/hindsight/mental-models.ts +1 -1
- package/src/internal-urls/agent-protocol.ts +1 -20
- package/src/internal-urls/artifact-protocol.ts +1 -19
- package/src/internal-urls/docs-index.generated.ts +5 -6
- package/src/internal-urls/registry-helpers.ts +25 -0
- package/src/main.ts +11 -2
- package/src/mcp/oauth-flow.ts +20 -0
- package/src/modes/acp/acp-agent.ts +79 -45
- package/src/modes/components/assistant-message.ts +14 -8
- package/src/modes/components/bash-execution.ts +24 -63
- package/src/modes/components/custom-message.ts +14 -40
- package/src/modes/components/eval-execution.ts +27 -57
- package/src/modes/components/execution-shared.ts +102 -0
- package/src/modes/components/hook-message.ts +17 -49
- package/src/modes/components/mcp-add-wizard.ts +26 -5
- package/src/modes/components/message-frame.ts +88 -0
- package/src/modes/components/model-selector.ts +1 -1
- package/src/modes/components/session-observer-overlay.ts +6 -2
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/status-line/segments.ts +55 -4
- package/src/modes/components/status-line/types.ts +4 -0
- package/src/modes/components/status-line.ts +28 -10
- package/src/modes/components/tool-execution.ts +7 -8
- package/src/modes/controllers/command-controller-shared.ts +108 -0
- package/src/modes/controllers/command-controller.ts +13 -4
- package/src/modes/controllers/event-controller.ts +36 -7
- package/src/modes/controllers/input-controller.ts +13 -0
- package/src/modes/controllers/mcp-command-controller.ts +56 -61
- package/src/modes/controllers/ssh-command-controller.ts +18 -57
- package/src/modes/interactive-mode.ts +624 -52
- package/src/modes/print-mode.ts +16 -86
- package/src/modes/rpc/rpc-mode.ts +14 -87
- package/src/modes/runtime-init.ts +115 -0
- package/src/modes/theme/defaults/dark-poimandres.json +2 -0
- package/src/modes/theme/defaults/light-poimandres.json +2 -0
- package/src/modes/theme/theme.ts +18 -6
- package/src/modes/types.ts +14 -3
- package/src/modes/utils/context-usage.ts +13 -13
- package/src/modes/utils/ui-helpers.ts +10 -3
- package/src/plan-mode/approved-plan.ts +35 -1
- package/src/prompts/goals/goal-budget-limit.md +16 -0
- package/src/prompts/goals/goal-continuation.md +28 -0
- package/src/prompts/goals/goal-mode-active.md +23 -0
- package/src/prompts/system/plan-mode-active.md +5 -5
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
- package/src/prompts/tools/bash.md +6 -0
- package/src/prompts/tools/goal.md +13 -0
- package/src/prompts/tools/hashline.md +102 -114
- package/src/prompts/tools/read.md +1 -0
- package/src/prompts/tools/resolve.md +6 -5
- package/src/sdk.ts +12 -5
- package/src/session/agent-session.ts +428 -106
- package/src/session/blob-store.ts +36 -3
- package/src/session/messages.ts +67 -2
- package/src/session/session-manager.ts +131 -12
- package/src/session/session-storage.ts +33 -15
- package/src/session/streaming-output.ts +309 -13
- package/src/slash-commands/builtin-registry.ts +18 -0
- package/src/ssh/ssh-executor.ts +5 -0
- package/src/system-prompt.ts +4 -2
- package/src/task/executor.ts +17 -7
- package/src/task/index.ts +3 -0
- package/src/task/render.ts +21 -15
- package/src/task/types.ts +4 -0
- package/src/tools/ast-edit.ts +21 -120
- package/src/tools/ast-grep.ts +21 -119
- package/src/tools/bash-interactive.ts +9 -1
- package/src/tools/bash.ts +27 -4
- package/src/tools/browser/attach.ts +3 -3
- package/src/tools/browser/launch.ts +81 -18
- package/src/tools/browser/registry.ts +1 -5
- package/src/tools/browser/tab-supervisor.ts +51 -14
- package/src/tools/conflict-detect.ts +15 -4
- package/src/tools/eval.ts +3 -1
- package/src/tools/find.ts +20 -38
- package/src/tools/gh.ts +7 -6
- package/src/tools/index.ts +22 -11
- package/src/tools/inspect-image.ts +3 -10
- package/src/tools/output-meta.ts +176 -37
- package/src/tools/path-utils.ts +125 -2
- package/src/tools/read.ts +516 -233
- package/src/tools/render-utils.ts +92 -0
- package/src/tools/renderers.ts +2 -0
- package/src/tools/resolve.ts +72 -44
- package/src/tools/search.ts +120 -186
- package/src/tools/write.ts +44 -9
- package/src/utils/file-mentions.ts +1 -1
- package/src/utils/image-loading.ts +7 -3
- package/src/utils/image-resize.ts +32 -43
- package/src/vim/parser.ts +0 -17
- package/src/vim/render.ts +1 -1
- package/src/vim/types.ts +1 -1
- package/src/web/search/providers/gemini.ts +35 -95
- package/src/prompts/tools/exit-plan-mode.md +0 -6
- package/src/tools/exit-plan-mode.ts +0 -97
- package/src/utils/fuzzy.ts +0 -108
- package/src/utils/image-convert.ts +0 -27
|
@@ -180,7 +180,7 @@ export function rewriteImports(code: string): string {
|
|
|
180
180
|
* Nested declarations (inside functions, blocks, classes) are left alone \u2014 they're
|
|
181
181
|
* scoped to their enclosing function/block regardless of `var` vs `let`/`const`.
|
|
182
182
|
*/
|
|
183
|
-
|
|
183
|
+
function demoteTopLevelLexicals(code: string): string {
|
|
184
184
|
if (!/\b(?:const|let|class)\b/.test(code)) return code;
|
|
185
185
|
|
|
186
186
|
const ast = parseProgram(code);
|
|
@@ -248,7 +248,7 @@ function returnFinalExpression(code: string): { source: string; returned: boolea
|
|
|
248
248
|
* common case avoids an extra transpile pass. We detect "looks like TS" with a cheap regex
|
|
249
249
|
* before invoking the transpiler.
|
|
250
250
|
*/
|
|
251
|
-
|
|
251
|
+
function stripTypeScript(code: string): string {
|
|
252
252
|
if (!LOOKS_LIKE_TS.test(code)) return code;
|
|
253
253
|
try {
|
|
254
254
|
return new Bun.Transpiler({ loader: "ts" }).transformSync(code);
|
package/src/eval/py/executor.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getProjectDir, logger } from "@oh-my-pi/pi-utils";
|
|
2
|
+
import { Settings } from "../../config/settings";
|
|
2
3
|
import { OutputSink } from "../../session/streaming-output";
|
|
3
4
|
import type { ToolSession } from "../../tools";
|
|
5
|
+
import { resolveOutputMaxColumns, resolveOutputSinkHeadBytes } from "../../tools/output-meta";
|
|
4
6
|
import type { JsStatusEvent } from "../js/shared/types";
|
|
5
7
|
import type { KernelDisplayOutput } from "./display";
|
|
6
8
|
import {
|
|
@@ -815,10 +817,13 @@ async function executeWithKernel(
|
|
|
815
817
|
code: string,
|
|
816
818
|
options: PythonExecutorOptions | undefined,
|
|
817
819
|
): Promise<PythonResult> {
|
|
820
|
+
const settings = await Settings.init();
|
|
818
821
|
const sink = new OutputSink({
|
|
819
822
|
onChunk: options?.onChunk,
|
|
820
823
|
artifactPath: options?.artifactPath,
|
|
821
824
|
artifactId: options?.artifactId,
|
|
825
|
+
headBytes: resolveOutputSinkHeadBytes(settings),
|
|
826
|
+
maxColumns: resolveOutputMaxColumns(settings),
|
|
822
827
|
});
|
|
823
828
|
const displayOutputs: KernelDisplayOutput[] = [];
|
|
824
829
|
const deadlineMs = getExecutionDeadlineMs(options);
|
package/src/exa/factory.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { TObject, TProperties } from "@sinclair/typebox";
|
|
5
5
|
import type { CustomTool } from "../extensibility/custom-tools/types";
|
|
6
|
-
import { callExaTool, findApiKey, formatSearchResults, isSearchResponse } from "./mcp-client";
|
|
6
|
+
import { callExaTool, findApiKey, formatGenericResponse, formatSearchResults, isSearchResponse } from "./mcp-client";
|
|
7
7
|
import type { ExaRenderDetails } from "./types";
|
|
8
8
|
|
|
9
9
|
/** Creates an Exa tool with standardized API key handling, error wrapping, and optional search response formatting. */
|
|
@@ -44,7 +44,7 @@ export function createExaTool(
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
return {
|
|
47
|
-
content: [{ type: "text" as const, text:
|
|
47
|
+
content: [{ type: "text" as const, text: formatGenericResponse(response) }],
|
|
48
48
|
details: { raw: response, toolName: name },
|
|
49
49
|
};
|
|
50
50
|
} catch (error) {
|
package/src/exa/mcp-client.ts
CHANGED
|
@@ -174,6 +174,79 @@ export function formatSearchResults(data: ExaSearchResponse): string {
|
|
|
174
174
|
|
|
175
175
|
return output.trim();
|
|
176
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Format a non-search MCP response as human-readable text.
|
|
179
|
+
* Handles objects, arrays, primitives, and common MCP response shapes.
|
|
180
|
+
*/
|
|
181
|
+
export function formatGenericResponse(data: unknown): string {
|
|
182
|
+
if (data === null || data === undefined) return "No result.";
|
|
183
|
+
if (typeof data === "string") return data;
|
|
184
|
+
if (typeof data === "number" || typeof data === "boolean") return String(data);
|
|
185
|
+
|
|
186
|
+
if (Array.isArray(data)) {
|
|
187
|
+
if (data.length === 0) return "(empty)";
|
|
188
|
+
const parts: string[] = [];
|
|
189
|
+
for (let i = 0; i < data.length; i++) {
|
|
190
|
+
const item = data[i];
|
|
191
|
+
if (typeof item === "object" && item !== null) {
|
|
192
|
+
const record = item as Record<string, unknown>;
|
|
193
|
+
const title = (record.title ?? record.name ?? record.id ?? `Item ${i + 1}`) as string;
|
|
194
|
+
parts.push(`\n### ${title}`);
|
|
195
|
+
for (const [k, v] of Object.entries(record)) {
|
|
196
|
+
if (["title", "name", "id"].includes(k)) continue;
|
|
197
|
+
parts.push(`- **${k}:** ${formatValue(v)}`);
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
parts.push(`- ${formatValue(item)}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return parts.join("\n");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (typeof data === "object") {
|
|
207
|
+
const record = data as Record<string, unknown>;
|
|
208
|
+
if (record.content && Array.isArray(record.content)) {
|
|
209
|
+
// MCP-style content array — extract text blocks
|
|
210
|
+
const texts = record.content
|
|
211
|
+
.filter(
|
|
212
|
+
(c: unknown): c is { type: string; text?: string } =>
|
|
213
|
+
typeof c === "object" && c !== null && (c as Record<string, unknown>)?.type === "text",
|
|
214
|
+
)
|
|
215
|
+
.map(c => c.text ?? "")
|
|
216
|
+
.filter(Boolean);
|
|
217
|
+
if (texts.length > 0) return texts.join("\n");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const lines: string[] = [];
|
|
221
|
+
for (const [k, v] of Object.entries(record)) {
|
|
222
|
+
if (k === "content") continue; // handled above
|
|
223
|
+
if (v === null || v === undefined) continue;
|
|
224
|
+
if (typeof v === "object") {
|
|
225
|
+
const formatted = formatGenericResponse(v);
|
|
226
|
+
if (formatted) lines.push(`- **${k}:**\n${indent(formatted, 2)}`);
|
|
227
|
+
} else {
|
|
228
|
+
lines.push(`- **${k}:** ${formatValue(v)}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return lines.join("\n") || "(empty)";
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return String(data);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function formatValue(v: unknown): string {
|
|
238
|
+
if (v === null || v === undefined) return "—";
|
|
239
|
+
if (typeof v === "object") return JSON.stringify(v);
|
|
240
|
+
return String(v);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function indent(text: string, spaces: number): string {
|
|
244
|
+
const pad = " ".repeat(spaces);
|
|
245
|
+
return text
|
|
246
|
+
.split("\n")
|
|
247
|
+
.map(line => pad + line)
|
|
248
|
+
.join("\n");
|
|
249
|
+
}
|
|
177
250
|
|
|
178
251
|
/** Check if result is a search response */
|
|
179
252
|
export function isSearchResponse(data: unknown): data is ExaSearchResponse {
|
|
@@ -260,7 +333,7 @@ export class MCPWrappedTool implements CustomTool<TSchema, ExaRenderDetails> {
|
|
|
260
333
|
}
|
|
261
334
|
|
|
262
335
|
return {
|
|
263
|
-
content: [{ type: "text" as const, text:
|
|
336
|
+
content: [{ type: "text" as const, text: formatGenericResponse(response) }],
|
|
264
337
|
details: { raw: response, toolName: this.config.name },
|
|
265
338
|
};
|
|
266
339
|
} catch (error) {
|
|
@@ -7,6 +7,7 @@ import * as fs from "node:fs/promises";
|
|
|
7
7
|
import { executeShell, type MinimizerOptions, Shell } from "@oh-my-pi/pi-natives";
|
|
8
8
|
import { Settings, type ShellMinimizerSettings } from "../config/settings";
|
|
9
9
|
import { OutputSink } from "../session/streaming-output";
|
|
10
|
+
import { resolveOutputMaxColumns, resolveOutputSinkHeadBytes } from "../tools/output-meta";
|
|
10
11
|
import { getOrCreateSnapshot } from "../utils/shell-snapshot";
|
|
11
12
|
import { NON_INTERACTIVE_ENV } from "./non-interactive-env";
|
|
12
13
|
|
|
@@ -64,7 +65,8 @@ async function resolveShellCwd(cwd: string | undefined): Promise<string | undefi
|
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
/** Translate `ShellMinimizerSettings` into native `MinimizerOptions`, or `undefined` when disabled. */
|
|
69
|
+
export function buildMinimizerOptions(group: ShellMinimizerSettings): MinimizerOptions | undefined {
|
|
68
70
|
if (!group.enabled) return undefined;
|
|
69
71
|
return {
|
|
70
72
|
enabled: true,
|
|
@@ -94,6 +96,8 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
94
96
|
onChunk: options?.onChunk,
|
|
95
97
|
artifactPath: options?.artifactPath,
|
|
96
98
|
artifactId: options?.artifactId,
|
|
99
|
+
headBytes: resolveOutputSinkHeadBytes(settings),
|
|
100
|
+
maxColumns: resolveOutputMaxColumns(settings),
|
|
97
101
|
// Throttle the streaming preview callback to avoid saturating the
|
|
98
102
|
// event loop when commands produce massive output (e.g. seq 1 50M).
|
|
99
103
|
chunkThrottleMs: options?.onChunk ? 50 : 0,
|