@oh-my-pi/pi-coding-agent 11.10.4 → 11.12.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 +73 -0
- package/package.json +8 -8
- package/src/config/model-resolver.ts +2 -0
- package/src/config/prompt-templates.ts +11 -0
- package/src/config/settings-schema.ts +1 -1
- package/src/debug/system-info.ts +22 -1
- package/src/mcp/tool-bridge.ts +7 -2
- package/src/patch/diff.ts +2 -1
- package/src/patch/hashline.ts +280 -235
- package/src/patch/index.ts +165 -47
- package/src/patch/shared.ts +35 -28
- package/src/patch/types.ts +4 -26
- package/src/prompts/system/system-prompt.md +113 -194
- package/src/prompts/tools/grep.md +1 -1
- package/src/prompts/tools/hashline.md +72 -59
- package/src/prompts/tools/read.md +9 -2
- package/src/sdk.ts +23 -7
- package/src/session/agent-session.ts +24 -5
- package/src/session/auth-storage.ts +29 -5
- package/src/system-prompt.ts +44 -50
- package/src/tools/ask.ts +4 -10
- package/src/tools/bash.ts +1 -7
- package/src/tools/browser.ts +21 -7
- package/src/tools/calculator.ts +2 -2
- package/src/tools/exit-plan-mode.ts +4 -2
- package/src/tools/grep.ts +13 -2
- package/src/tools/read.ts +20 -29
- package/src/tools/ssh.ts +2 -7
- package/src/tools/todo-write.ts +2 -2
- package/src/tools/write.ts +1 -1
- package/src/utils/file-display-mode.ts +27 -0
- package/src/utils/file-mentions.ts +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,79 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [11.12.0] - 2026-02-11
|
|
6
|
+
### Added
|
|
7
|
+
|
|
8
|
+
- Added `resolveFileDisplayMode` utility to centralize file display mode resolution across tools (read, grep, file mentions)
|
|
9
|
+
- Added automatic hashline formatting to @file mentions when hashline mode is active
|
|
10
|
+
- Added `replace` hashline edit operation for substr-style fuzzy text replacement without line references, with optional `all` flag for replace-all behavior
|
|
11
|
+
- Added `noopEdits` array to `applyHashlineEdits` return value to report edits that produced no changes, including edit index, location, and current content for diagnostics
|
|
12
|
+
- Added validation to detect and reject hashline edits using wrong-format fields (`old_text`/`new_text` from replace mode, `diff` from patch mode) with helpful error messages
|
|
13
|
+
- Added `additionalProperties: true` to all hashline edit schemas (`single`, `range`, `insertAfter`, and root) to tolerate extra fields from models
|
|
14
|
+
- Added whitespace normalization in line reference parsing to tolerate spaces around colons (e.g., `5 : ab` now parses as `5:ab`)
|
|
15
|
+
- Added `remaps` property to `HashlineMismatchError` providing quick-fix mapping of stale line references to corrected hashes
|
|
16
|
+
- Added warnings detection in `applyHashlineEdits` to alert users when edits affect significantly more lines than expected, indicating possible unintended reformatting
|
|
17
|
+
- Added diagnostic output showing target line content when an edit produces no changes, helping users identify hash mismatches or incorrect replacement content
|
|
18
|
+
- Added `{{hashline}}` Handlebars helper to compute accurate `LINE:HASH` references for prompt examples and documentation
|
|
19
|
+
- Added deduplication of identical hashline edits targeting the same line(s) in a single call
|
|
20
|
+
- Added `replacement` as accepted alias for `content` in `insertAfter` operations
|
|
21
|
+
- Added graceful degradation of `range` edits with missing `end` field to single-line edits
|
|
22
|
+
- Added `additionalProperties: true` to hashline edit schemas to tolerate extra fields from models
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Reverted hashline display format from `LINE:HASH content` (two spaces) back to `LINE:HASH|content` (pipe separator) for consistency with legacy format
|
|
27
|
+
- Changed hashline display format from `LINE:HASH| content` to `LINE:HASH content` (two spaces instead of pipe separator) for improved readability
|
|
28
|
+
- Removed `lines` and `hashes` parameters from `read` tool—file display mode (line numbers, hashlines) now determined automatically by settings and edit mode
|
|
29
|
+
- Simplified `read` tool prompt to reflect automatic display mode detection based on configuration
|
|
30
|
+
- Updated `grep` tool to respect file display mode settings, showing hashline-prefixed output when hashline mode is active
|
|
31
|
+
- Renamed hashline edit operation keys from `single`/`range`/`insertAfter` to `set_line`/`replace_lines`/`insert_after` for clearer semantics
|
|
32
|
+
- Renamed hashline edit fields: `loc` → `anchor`, `replacement` → `new_text`, `content` → `text` for consistency across all operation types
|
|
33
|
+
- Separated hashline anchor-based edits (`set_line`, `replace_lines`, `insert_after`) from content-replace edits (`replace`) in application pipeline
|
|
34
|
+
- Improved no-op edit diagnostics to use `noopEdits` array from `applyHashlineEdits`, providing precise line-by-line comparison when replacements match current content
|
|
35
|
+
- Enhanced error messages for wrong-format hashline edits to guide users toward correct operation syntax
|
|
36
|
+
- Strengthened hashline prompt guidance to emphasize that `replacement` must differ from current line content and clarify no-op error recovery procedures
|
|
37
|
+
- Improved hashline prompt to clarify atomicity: all edits in one call are validated against the original file state, with line numbers and hashes referring to the pre-edit state
|
|
38
|
+
- Added explicit instruction in hashline prompt to preserve exact whitespace and formatting when replacing lines, changing only the targeted token/expression
|
|
39
|
+
- Added guidance in hashline prompt for swap operations: use two `single` operations in one call rather than attempting to account for line number shifts
|
|
40
|
+
- Strengthened anti-reformatting instructions in hashline prompt to reduce formatting-only failures
|
|
41
|
+
- Improved no-op error recovery guidance in hashline prompt to prevent infinite retry loops
|
|
42
|
+
- Renamed hashline edit operation keys from `replaceLine`/`replaceLines` to `single`/`range` for clearer semantics
|
|
43
|
+
- Renamed hashline edit field `content` to `replacement` in `single` and `range` operations to distinguish from `insertAfter.content`
|
|
44
|
+
- Improved no-op edit diagnostics to show specific line-by-line comparisons when replacements match current content, helping users identify hash mismatches or formatting issues
|
|
45
|
+
- Enhanced no-op error messages to distinguish between literally identical replacements and content normalized back by heuristics
|
|
46
|
+
- Reverted hash algorithm from 3-character base-36 back to 2-character hexadecimal for line references
|
|
47
|
+
- Enhanced range validation during hashline edits to detect and reject relocations that change the scope of affected lines
|
|
48
|
+
- Improved wrapped-line restoration logic to only attempt merging when source lines exhibit continuation patterns
|
|
49
|
+
- Updated hashline tool documentation to emphasize direction-locking mutations and clarify recovery procedures for hash mismatches
|
|
50
|
+
- Changed `applyHashlineEdits` return type to include optional `warnings` array for reporting suspicious edit patterns
|
|
51
|
+
- Improved hash relocation logic to recompute touched lines after hash-based line number adjustments, preventing incorrect merge heuristics
|
|
52
|
+
- Enhanced error messages for no-op edits to include preview of target lines with their current hashes and content
|
|
53
|
+
- Changed hashline edit format from `src`/`dst` object structure to direct operation schemas (`replaceLine`, `replaceLines`, `insertAfter`)
|
|
54
|
+
- Changed hash algorithm from 2-character hexadecimal to 3-character base-36 alphanumeric for improved readability and collision resistance
|
|
55
|
+
- Improved hash mismatch handling to automatically relocate stale line references when the hash uniquely identifies a moved line
|
|
56
|
+
- Changed `HashlineEdit` from `src`/`dst` format to direct operation schemas: `replaceLine`, `replaceLines`, `insertAfter`
|
|
57
|
+
- Changed hash algorithm from hexadecimal (base-16) to base-36 alphanumeric for shorter, more readable line references
|
|
58
|
+
- Increased maximum wrapped-line restoration from 6 to 10 lines to handle longer reflowed statements
|
|
59
|
+
- Updated prompt examples to use `{{hashline}}` Handlebars helper for generating correct line references in tool instructions
|
|
60
|
+
|
|
61
|
+
### Removed
|
|
62
|
+
|
|
63
|
+
- Removed `insertBefore` hashline edit operation for inserting content before a line
|
|
64
|
+
- Removed `substr` hashline edit operation for substring-based line replacement
|
|
65
|
+
- Removed `insertBefore` and `substr` hashline edit variants
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
|
|
69
|
+
- Fixed `parseLineRef` to handle both legacy pipe-separator format (`LINE:HASH| content`) and new two-space format (`LINE:HASH content`) for backward compatibility
|
|
70
|
+
- Fixed resource leak in browser query handler by properly disposing owned proxy elements for non-winning candidates
|
|
71
|
+
- Fixed script evaluation to support async functions and await expressions in browser evaluate operations
|
|
72
|
+
- Fixed `range` edits with missing `end` field to gracefully degrade to single-line edits instead of crashing
|
|
73
|
+
- Fixed `insertAfter` operations to accept both `content` and `replacement` field names for consistency with other edit types
|
|
74
|
+
- Fixed deduplication logic to correctly identify and remove identical hashline edits targeting the same line(s) in a single call
|
|
75
|
+
- Fixed range-based edits to prevent invalid mutations when hash relocation changes the number of lines in the target range
|
|
76
|
+
- Fixed multi-edit application to use original file state for all anchor references, preventing incorrect line numbers when earlier edits change file length
|
|
77
|
+
|
|
5
78
|
## [11.10.4] - 2026-02-10
|
|
6
79
|
|
|
7
80
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.12.0",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"ompConfig": {
|
|
@@ -84,12 +84,12 @@
|
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
86
|
"@mozilla/readability": "0.6.0",
|
|
87
|
-
"@oh-my-pi/omp-stats": "11.
|
|
88
|
-
"@oh-my-pi/pi-agent-core": "11.
|
|
89
|
-
"@oh-my-pi/pi-ai": "11.
|
|
90
|
-
"@oh-my-pi/pi-natives": "11.
|
|
91
|
-
"@oh-my-pi/pi-tui": "11.
|
|
92
|
-
"@oh-my-pi/pi-utils": "11.
|
|
87
|
+
"@oh-my-pi/omp-stats": "11.12.0",
|
|
88
|
+
"@oh-my-pi/pi-agent-core": "11.12.0",
|
|
89
|
+
"@oh-my-pi/pi-ai": "11.12.0",
|
|
90
|
+
"@oh-my-pi/pi-natives": "11.12.0",
|
|
91
|
+
"@oh-my-pi/pi-tui": "11.12.0",
|
|
92
|
+
"@oh-my-pi/pi-utils": "11.12.0",
|
|
93
93
|
"@sinclair/typebox": "^0.34.48",
|
|
94
94
|
"ajv": "^8.17.1",
|
|
95
95
|
"chalk": "^5.6.2",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
109
|
"@types/ms": "^2.1.0",
|
|
110
|
-
"@types/bun": "^1.3.
|
|
110
|
+
"@types/bun": "^1.3.9",
|
|
111
111
|
"ms": "^2.1.3",
|
|
112
112
|
"@types/jsdom": "27.0.0"
|
|
113
113
|
},
|
|
@@ -29,6 +29,8 @@ export const defaultModelPerProvider: Record<KnownProvider, string> = {
|
|
|
29
29
|
zai: "glm-4.6",
|
|
30
30
|
mistral: "devstral-medium-latest",
|
|
31
31
|
minimax: "MiniMax-M2.1",
|
|
32
|
+
"minimax-code": "MiniMax-M2.1",
|
|
33
|
+
"minimax-code-cn": "MiniMax-M2.1",
|
|
32
34
|
opencode: "claude-opus-4-6",
|
|
33
35
|
"kimi-code": "kimi-k2.5",
|
|
34
36
|
};
|
|
@@ -3,6 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
4
4
|
import Handlebars from "handlebars";
|
|
5
5
|
import { CONFIG_DIR_NAME, getPromptsDir } from "../config";
|
|
6
|
+
import { computeLineHash } from "../patch/hashline";
|
|
6
7
|
import { jtdToTypeScript } from "../tools/jtd-to-typescript";
|
|
7
8
|
import { parseFrontmatter } from "../utils/frontmatter";
|
|
8
9
|
|
|
@@ -228,6 +229,16 @@ handlebars.registerHelper("jtdToTypeScript", (schema: unknown): string => jtdToT
|
|
|
228
229
|
|
|
229
230
|
handlebars.registerHelper("jsonStringify", (value: unknown): string => JSON.stringify(value));
|
|
230
231
|
|
|
232
|
+
/**
|
|
233
|
+
* {{hashline lineNum "content"}} — compute a real hashline ref for prompt examples.
|
|
234
|
+
* Returns `"lineNum:hash"` using the actual hash algorithm.
|
|
235
|
+
*/
|
|
236
|
+
handlebars.registerHelper("hashline", (lineNum: unknown, content: unknown): string => {
|
|
237
|
+
const num = typeof lineNum === "number" ? lineNum : Number.parseInt(String(lineNum), 10);
|
|
238
|
+
const str = typeof content === "string" ? content : String(content ?? "");
|
|
239
|
+
return `${num}:${computeLineHash(num, str)}`;
|
|
240
|
+
});
|
|
241
|
+
|
|
231
242
|
export function renderPromptTemplate(template: string, context: TemplateContext = {}): string {
|
|
232
243
|
const compiled = handlebars.compile(template, { noEscape: true, strict: false });
|
|
233
244
|
const rendered = compiled(context ?? {});
|
|
@@ -253,7 +253,7 @@ export const SETTINGS_SCHEMA = {
|
|
|
253
253
|
ui: {
|
|
254
254
|
tab: "config",
|
|
255
255
|
label: "Read hash lines",
|
|
256
|
-
description: "Include line hashes in read output for hashline edit mode (LINE:HASH|
|
|
256
|
+
description: "Include line hashes in read output for hashline edit mode (LINE:HASH|content)",
|
|
257
257
|
},
|
|
258
258
|
},
|
|
259
259
|
showHardwareCursor: {
|
package/src/debug/system-info.ts
CHANGED
|
@@ -22,6 +22,21 @@ export interface SystemInfo {
|
|
|
22
22
|
terminal: string | undefined;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/** Map Darwin kernel major version to macOS marketing name. */
|
|
26
|
+
function macosMarketingName(release: string): string | undefined {
|
|
27
|
+
const major = Number.parseInt(release.split(".")[0] ?? "", 10);
|
|
28
|
+
if (Number.isNaN(major)) return undefined;
|
|
29
|
+
const names: Record<number, string> = {
|
|
30
|
+
25: "Tahoe",
|
|
31
|
+
24: "Sequoia",
|
|
32
|
+
23: "Sonoma",
|
|
33
|
+
22: "Ventura",
|
|
34
|
+
21: "Monterey",
|
|
35
|
+
20: "Big Sur",
|
|
36
|
+
};
|
|
37
|
+
return names[major];
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
/** Collect system information */
|
|
26
41
|
export async function collectSystemInfo(): Promise<SystemInfo> {
|
|
27
42
|
const cpus = os.cpus();
|
|
@@ -31,8 +46,14 @@ export async function collectSystemInfo(): Promise<SystemInfo> {
|
|
|
31
46
|
const shell = Bun.env.SHELL ?? Bun.env.ComSpec ?? "unknown";
|
|
32
47
|
const terminal = Bun.env.TERM_PROGRAM ?? Bun.env.TERM ?? undefined;
|
|
33
48
|
|
|
49
|
+
let osStr = `${os.type()} ${os.release()} (${os.platform()})`;
|
|
50
|
+
if (os.platform() === "darwin") {
|
|
51
|
+
const name = macosMarketingName(os.release());
|
|
52
|
+
if (name) osStr = `${osStr} ${name}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
34
55
|
return {
|
|
35
|
-
os:
|
|
56
|
+
os: osStr,
|
|
36
57
|
arch: os.arch(),
|
|
37
58
|
cpu: cpuModel,
|
|
38
59
|
memory: {
|
package/src/mcp/tool-bridge.ts
CHANGED
|
@@ -53,10 +53,15 @@ export interface MCPToolDetails {
|
|
|
53
53
|
/**
|
|
54
54
|
* Convert JSON Schema from MCP to TypeBox-compatible schema.
|
|
55
55
|
* MCP uses standard JSON Schema, TypeBox uses a compatible subset.
|
|
56
|
+
*
|
|
57
|
+
* Also normalizes schemas to work around common issues:
|
|
58
|
+
* - Adds `properties: {}` to object schemas missing it (some LLM providers require this)
|
|
56
59
|
*/
|
|
57
60
|
function convertSchema(mcpSchema: MCPToolDefinition["inputSchema"]): TSchema {
|
|
58
|
-
//
|
|
59
|
-
|
|
61
|
+
// Normalize: object schemas must have properties field for some providers
|
|
62
|
+
if (mcpSchema.type === "object" && !("properties" in mcpSchema)) {
|
|
63
|
+
return { ...mcpSchema, properties: {} } as unknown as TSchema;
|
|
64
|
+
}
|
|
60
65
|
return mcpSchema as unknown as TSchema;
|
|
61
66
|
}
|
|
62
67
|
|
package/src/patch/diff.ts
CHANGED
|
@@ -9,8 +9,9 @@ import { resolveToCwd } from "../tools/path-utils";
|
|
|
9
9
|
import { previewPatch } from "./applicator";
|
|
10
10
|
import { DEFAULT_FUZZY_THRESHOLD, findMatch } from "./fuzzy";
|
|
11
11
|
import { applyHashlineEdits } from "./hashline";
|
|
12
|
+
import type { HashlineEdit } from "./index";
|
|
12
13
|
import { adjustIndentation, normalizeToLF, stripBom } from "./normalize";
|
|
13
|
-
import type { DiffError, DiffResult,
|
|
14
|
+
import type { DiffError, DiffResult, PatchInput } from "./types";
|
|
14
15
|
import { EditMatchError } from "./types";
|
|
15
16
|
|
|
16
17
|
// ═══════════════════════════════════════════════════════════════════════════
|