@oh-my-pi/pi-coding-agent 13.3.2 → 13.3.4

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 CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [13.3.3] - 2026-02-26
6
+ ### Added
7
+
8
+ - Support for `move` parameter in `computeHashlineDiff` to enable file move operations alongside content edits
9
+
10
+ ### Changed
11
+
12
+ - Modified no-op detection logic to allow move-only operations when file content remains unchanged
13
+
5
14
  ## [13.3.1] - 2026-02-26
6
15
 
7
16
  ### Added
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "13.3.2",
4
+ "version": "13.3.4",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/can1357/oh-my-pi",
7
7
  "author": "Can Boluk",
@@ -41,12 +41,12 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@mozilla/readability": "^0.6",
44
- "@oh-my-pi/omp-stats": "13.3.2",
45
- "@oh-my-pi/pi-agent-core": "13.3.2",
46
- "@oh-my-pi/pi-ai": "13.3.2",
47
- "@oh-my-pi/pi-natives": "13.3.2",
48
- "@oh-my-pi/pi-tui": "13.3.2",
49
- "@oh-my-pi/pi-utils": "13.3.2",
44
+ "@oh-my-pi/omp-stats": "13.3.4",
45
+ "@oh-my-pi/pi-agent-core": "13.3.4",
46
+ "@oh-my-pi/pi-ai": "13.3.4",
47
+ "@oh-my-pi/pi-natives": "13.3.4",
48
+ "@oh-my-pi/pi-tui": "13.3.4",
49
+ "@oh-my-pi/pi-utils": "13.3.4",
50
50
  "@sinclair/typebox": "^0.34",
51
51
  "@xterm/headless": "^6.0",
52
52
  "ajv": "^8.18",
package/src/cursor.ts CHANGED
@@ -198,7 +198,7 @@ export class CursorExecHandlers implements ICursorExecHandlers {
198
198
  const timeoutSeconds = args.timeout && args.timeout > 0 ? args.timeout : undefined;
199
199
  const toolResultMessage = await executeTool(this.options, "bash", toolCallId, {
200
200
  command: args.command,
201
- workdir: args.workingDirectory || undefined,
201
+ cwd: args.workingDirectory || undefined,
202
202
  timeout: timeoutSeconds,
203
203
  });
204
204
  return toolResultMessage;
@@ -204,12 +204,13 @@ export class ToolExecutionComponent extends Container {
204
204
  return;
205
205
  }
206
206
  const edits = this.#args?.edits;
207
+ const move = this.#args?.move;
207
208
  if (path && Array.isArray(edits)) {
208
- const argsKey = JSON.stringify({ path, edits });
209
+ const argsKey = JSON.stringify({ path, edits, move });
209
210
  if (this.#editDiffArgsKey === argsKey) return;
210
211
  this.#editDiffArgsKey = argsKey;
211
212
 
212
- computeHashlineDiff({ path, edits }, this.#cwd).then(result => {
213
+ computeHashlineDiff({ path, edits, move }, this.#cwd).then(result => {
213
214
  if (this.#editDiffArgsKey === argsKey) {
214
215
  this.#editDiffPreview = result;
215
216
  this.#updateDisplay();
package/src/patch/diff.ts CHANGED
@@ -386,10 +386,10 @@ export async function computePatchDiff(
386
386
  * Used for preview rendering in the TUI before hashline-mode edits execute.
387
387
  */
388
388
  export async function computeHashlineDiff(
389
- input: { path: string; edits: HashlineEdit[] },
389
+ input: { path: string; edits: HashlineEdit[]; move?: string },
390
390
  cwd: string,
391
391
  ): Promise<DiffResult | DiffError> {
392
- const { path, edits } = input;
392
+ const { path, edits, move } = input;
393
393
  const absolutePath = resolveToCwd(path, cwd);
394
394
 
395
395
  try {
@@ -414,7 +414,7 @@ export async function computeHashlineDiff(
414
414
  const normalizedContent = normalizeToLF(content);
415
415
 
416
416
  const result = applyHashlineEdits(normalizedContent, edits);
417
- if (normalizedContent === result.lines) {
417
+ if (normalizedContent === result.lines && !move) {
418
418
  return { error: `No changes would be made to ${path}. The edits produce identical content.` };
419
419
  }
420
420
 
@@ -22,7 +22,20 @@ Returns the output, and an exit code from command execution.
22
22
  </output>
23
23
 
24
24
  <critical>
25
+ You **MUST** use specialized tools instead of bash for ALL file operations:
26
+
27
+ |Instead of (WRONG)|Use (CORRECT)|
28
+ |---|---|
29
+ |`cat file`, `head -n N file`|`read(path="file", limit=N)`|
30
+ |`cat -n file \|sed -n '50,150p'`|`read(path="file", offset=50, limit=100)`|
31
+ |`grep -A 20 'pat' file`|`grep(pattern="pat", path="file", post=20)`|
32
+ |`grep -rn 'pat' dir/`|`grep(pattern="pat", path="dir/")`|
33
+ |`rg 'pattern' dir/`|`grep(pattern="pattern", path="dir/")`|
34
+ |`find dir -name '*.ts'`|`find(pattern="dir/**/*.ts")`|
35
+ |`ls dir/`|`read(path="dir/")`|
36
+ |`cat <<'EOF' > file`|`write(path="file", content="...")`|
37
+ |`sed -i 's/old/new/' file`|`edit(path="file", edits=[...])`|
25
38
  - You **MUST NOT** use Bash for these operations like read, grep, find, edit, write, where specialized tools exist.
26
- - You **MUST NOT** use `2>&1` pattern, stdout and stderr are already merged.
39
+ - You **MUST NOT** use `2>&1` | `2>/dev/null` pattern, stdout and stderr are already merged.
27
40
  - You **MUST NOT** use `| head -n 50` or `| tail -n 100` pattern, use `head` and `tail` parameters instead.
28
41
  </critical>
@@ -18,4 +18,11 @@ Reads files from local filesystem or internal URLs.
18
18
  <output>
19
19
  - Returns file content as text; images return visual content; PDFs return extracted text
20
20
  - Missing files: returns closest filename matches for correction
21
- </output>
21
+ </output>
22
+
23
+ <critical>
24
+ - You **MUST** use `read` instead of bash for ALL file reading: `cat`, `head`, `tail`, `less`, `more` are FORBIDDEN.
25
+ - You **MUST** use `read(path="dir/")` instead of `ls dir/` for directory listings.
26
+ - You **MUST** always include the `path` parameter — NEVER call `read` with empty arguments `{}`.
27
+ - When reading specific line ranges, use `offset` and `limit`: `read(path="file", offset=50, limit=100)` not `cat -n file | sed`.
28
+ </critical>
@@ -92,12 +92,12 @@ function buildCommonArgs(host: SSHConnectionTarget): string[] {
92
92
  }
93
93
 
94
94
  async function runSshSync(args: string[]): Promise<{ exitCode: number | null; stderr: string }> {
95
- const result = await $`ssh ${args}`.nothrow();
95
+ const result = await $`ssh ${args}`.quiet().nothrow();
96
96
  return { exitCode: result.exitCode, stderr: result.stderr.toString().trim() };
97
97
  }
98
98
 
99
99
  async function runSshCaptureSync(args: string[]): Promise<{ exitCode: number | null; stdout: string; stderr: string }> {
100
- const result = await $`ssh ${args}`.nothrow();
100
+ const result = await $`ssh ${args}`.quiet().nothrow();
101
101
  return {
102
102
  exitCode: result.exitCode,
103
103
  stdout: result.stdout.toString().trim(),
@@ -79,6 +79,7 @@ export async function executeSSH(
79
79
  using child = ptree.spawn(["ssh", ...(await buildRemoteCommand(host, resolvedCommand))], {
80
80
  signal: options?.signal,
81
81
  timeout: options?.timeout,
82
+ stdin: "pipe",
82
83
  stderr: "full",
83
84
  });
84
85