@oh-my-pi/pi-coding-agent 14.9.8 → 14.9.9

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.
@@ -1,13 +1,13 @@
1
1
  Your patch language is a compact, line-anchored edit format.
2
2
 
3
- A patch contains one or more file sections. The first non-blank line of every edit section **MUST** be `@PATH`.
3
+ A patch contains one or more file sections. The first non-blank line of every edit section **MUST** be `@@ PATH`.
4
4
  Operations reference lines in the file by their line number and hash, called "Anchors", e.g. `5th`, `123ab`.
5
5
  You **MUST** copy them verbatim from the latest output for the file you're editing.
6
6
 
7
7
  Purely textual format. The tool has NO awareness of language, indentation, brackets, fences, or table widths. Emit valid syntax in replacements/insertions.
8
8
 
9
9
  <ops>
10
- @PATH header: subsequent ops apply to PATH
10
+ @@ PATH header: subsequent ops apply to PATH
11
11
  + ANCHOR insert lines AFTER the anchored line (or EOF); payload follows as `{{hsep}}TEXT` lines
12
12
  < ANCHOR insert lines BEFORE the anchored line (or BOF); payload follows as `{{hsep}}TEXT` lines
13
13
  - A..B delete the line range (inclusive).
@@ -64,18 +64,18 @@ When your edit involves brace boundaries (`{` / `}`), prefer these shapes:
64
64
 
65
65
  <examples>
66
66
  # Replace one line (preserve the leading tab from the original)
67
- @a.ts
67
+ @@ a.ts
68
68
  = {{hrefr 5}}..{{hrefr 5}}
69
69
  {{hsep}} return clean.trim().toUpperCase();
70
70
 
71
71
  # Replace a contiguous range with multiple lines
72
- @a.ts
72
+ @@ a.ts
73
73
  = {{hrefr 4}}..{{hrefr 5}}
74
74
  {{hsep}} const clean = (name || DEF).trim();
75
75
  {{hsep}} return clean.length === 0 ? DEF : clean.toUpperCase();
76
76
 
77
77
  # Replace a full multiline destructuring/call statement
78
- @b.ts
78
+ @@ b.ts
79
79
  = {{hrefr 1}}..{{hrefr 8}}
80
80
  {{hsep}}const {
81
81
  {{hsep}} events,
@@ -88,32 +88,32 @@ When your edit involves brace boundaries (`{` / `}`), prefer these shapes:
88
88
  {{hsep}});
89
89
 
90
90
  # Insert BEFORE a line
91
- @a.ts
91
+ @@ a.ts
92
92
  < {{hrefr 5}}
93
93
  {{hsep}} const debug = false;
94
94
 
95
95
  # Insert AFTER a line
96
- @a.ts
96
+ @@ a.ts
97
97
  + {{hrefr 4}}
98
98
  {{hsep}} if (clean.length === 0) return DEF;
99
99
 
100
100
  # Append to end of file
101
- @a.ts
101
+ @@ a.ts
102
102
  + EOF
103
103
  {{hsep}}export const done = true;
104
104
 
105
105
  # Delete a single line
106
- @a.ts
106
+ @@ a.ts
107
107
  - {{hrefr 2}}..{{hrefr 2}}
108
108
 
109
109
  # Blank a line in place (no payload required)
110
- @a.ts
110
+ @@ a.ts
111
111
  = {{hrefr 2}}..{{hrefr 2}}
112
112
  </examples>
113
113
 
114
114
  <anti-pattern>
115
115
  # WRONG — replaces 5 lines just to add one. Use `+` at the boundary instead.
116
- @a.ts
116
+ @@ a.ts
117
117
  = {{hrefr 1}}..{{hrefr 5}}
118
118
  {{hsep}}const DEF = "guest";
119
119
  {{hsep}}const DEBUG = false;
@@ -123,12 +123,12 @@ When your edit involves brace boundaries (`{` / `}`), prefer these shapes:
123
123
  {{hsep}} return clean.trim();
124
124
 
125
125
  # RIGHT — same effect, one-line insert
126
- @a.ts
126
+ @@ a.ts
127
127
  + {{hrefr 1}}
128
128
  {{hsep}}const DEBUG = false;
129
129
 
130
130
  # WRONG — continuation-fragment payload from the middle of a larger statement.
131
- @b.ts
131
+ @@ b.ts
132
132
  = {{hrefr 5}}..{{hrefr 7}}
133
133
  {{hsep}}} = await getStreamResponse(
134
134
  {{hsep}} request,
@@ -136,7 +136,7 @@ When your edit involves brace boundaries (`{` / `}`), prefer these shapes:
136
136
  {{hsep}} onEvent,
137
137
 
138
138
  # RIGHT — widen to the full statement so the payload starts at a self-contained boundary.
139
- @b.ts
139
+ @@ b.ts
140
140
  = {{hrefr 1}}..{{hrefr 8}}
141
141
  {{hsep}}const {
142
142
  {{hsep}} events,
@@ -154,7 +154,7 @@ If your replacement payload would render with even one unchanged line in the dif
154
154
  <critical>
155
155
  - Always copy anchors exactly from tool output, but **NEVER** include line content after the `{{hsep}}` separator in the op line.
156
156
  - Every inserted/replacement content line **MUST** start with `{{hsep}}`; raw content lines are invalid.
157
- - Do not write unified diff syntax (`@@`, `-OLD`, `+NEW`).
157
+ - Do not write unified diff syntax (`@@ -X,Y +X,Y @@`, `-OLD`, `+NEW`). The header is `@@ PATH`; line ops are `<`/`+`/`-`/`=`.
158
158
  - `= A..B` deletes the range; payload is what's written. If a payload edge line already exists immediately outside `A..B`, widen the range to cover it — otherwise it duplicates.
159
159
  - Multiple ops in one patch are cheap. Prefer two narrow ops over one wide `=`.
160
160
  - Before choosing a `= A..B` range, mentally delete lines A through B. If that would split an unclosed bracket, paren, brace, or string/template from a line above A, or orphan a closing delimiter that belongs to an opener inside the range, you are bisecting a syntactic construct. Widen the range to a self-contained boundary, or use `+`/`-` instead.
package/src/task/index.ts CHANGED
@@ -36,7 +36,6 @@ import { generateCommitMessage } from "../utils/commit-message-generator";
36
36
  import * as git from "../utils/git";
37
37
  import { discoverAgents, getAgent } from "./discovery";
38
38
  import { runSubprocess } from "./executor";
39
- import { resolveIsolationBackendForTaskExecution } from "./isolation-backend";
40
39
  import { AgentOutputManager } from "./output-manager";
41
40
  import { mapWithConcurrencyLimit, Semaphore } from "./parallel";
42
41
  import { renderResult, renderCall as renderTaskCall } from "./render";
@@ -50,20 +49,17 @@ import {
50
49
  type TaskToolDetails,
51
50
  } from "./types";
52
51
  import {
53
- applyBaseline,
54
52
  applyNestedPatches,
55
53
  captureBaseline,
56
54
  captureDeltaPatch,
57
- cleanupFuseOverlay,
58
- cleanupProjfsOverlay,
55
+ cleanupIsolation,
59
56
  cleanupTaskBranches,
60
- cleanupWorktree,
61
57
  commitToBranch,
62
- ensureFuseOverlay,
63
- ensureProjfsOverlay,
64
- ensureWorktree,
58
+ ensureIsolation,
65
59
  getRepoRoot,
60
+ type IsolationHandle,
66
61
  mergeTaskBranches,
62
+ parseIsolationMode,
67
63
  type WorktreeBaseline,
68
64
  } from "./worktree";
69
65
 
@@ -530,7 +526,7 @@ export class TaskTool implements AgentTool<TSchema, TaskToolDetails, Theme> {
530
526
  content: [
531
527
  {
532
528
  type: "text",
533
- text: "Task isolation is disabled. Remove the isolated argument or set task.isolation.mode to 'worktree', 'fuse-overlay', or 'fuse-projfs'.",
529
+ text: "Task isolation is disabled.",
534
530
  },
535
531
  ],
536
532
  details: {
@@ -700,28 +696,7 @@ export class TaskTool implements AgentTool<TSchema, TaskToolDetails, Theme> {
700
696
  }
701
697
  }
702
698
 
703
- let effectiveIsolationMode = isolationMode;
704
- let isolationBackendWarning = "";
705
- try {
706
- const resolvedIsolation = await resolveIsolationBackendForTaskExecution(isolationMode, isIsolated, repoRoot);
707
- effectiveIsolationMode = resolvedIsolation.effectiveIsolationMode;
708
- isolationBackendWarning = resolvedIsolation.warning;
709
- } catch (err) {
710
- const message = err instanceof Error ? err.message : String(err);
711
- return {
712
- content: [
713
- {
714
- type: "text",
715
- text: message,
716
- },
717
- ],
718
- details: {
719
- projectAgentsDir,
720
- results: [],
721
- totalDurationMs: Date.now() - startTime,
722
- },
723
- };
724
- }
699
+ const preferredIsolationBackend = parseIsolationMode(isolationMode);
725
700
 
726
701
  // Derive artifacts directory
727
702
  const sessionFile = this.session.getSessionFile();
@@ -891,21 +866,15 @@ export class TaskTool implements AgentTool<TSchema, TaskToolDetails, Theme> {
891
866
  }
892
867
 
893
868
  const taskStart = Date.now();
894
- let isolationDir: string | undefined;
869
+ let isolationHandle: IsolationHandle | undefined;
895
870
  try {
896
871
  if (!repoRoot || !baseline) {
897
872
  throw new Error("Isolated task execution not initialized.");
898
873
  }
899
874
  const taskBaseline = structuredClone(baseline);
900
875
 
901
- if (effectiveIsolationMode === "fuse-overlay") {
902
- isolationDir = await ensureFuseOverlay(repoRoot, task.id);
903
- } else if (effectiveIsolationMode === "fuse-projfs") {
904
- isolationDir = await ensureProjfsOverlay(repoRoot, task.id);
905
- } else {
906
- isolationDir = await ensureWorktree(repoRoot, task.id);
907
- await applyBaseline(isolationDir, taskBaseline);
908
- }
876
+ isolationHandle = await ensureIsolation(repoRoot, task.id, preferredIsolationBackend);
877
+ const isolationDir = isolationHandle.mergedDir;
909
878
 
910
879
  const result = await runSubprocess({
911
880
  cwd: this.session.cwd,
@@ -1017,14 +986,8 @@ export class TaskTool implements AgentTool<TSchema, TaskToolDetails, Theme> {
1017
986
  error: message,
1018
987
  };
1019
988
  } finally {
1020
- if (isolationDir) {
1021
- if (effectiveIsolationMode === "fuse-overlay") {
1022
- await cleanupFuseOverlay(isolationDir);
1023
- } else if (effectiveIsolationMode === "fuse-projfs") {
1024
- await cleanupProjfsOverlay(isolationDir);
1025
- } else {
1026
- await cleanupWorktree(isolationDir);
1027
- }
989
+ if (isolationHandle) {
990
+ await cleanupIsolation(isolationHandle);
1028
991
  }
1029
992
  }
1030
993
  };
@@ -1256,7 +1219,6 @@ export class TaskTool implements AgentTool<TSchema, TaskToolDetails, Theme> {
1256
1219
  });
1257
1220
 
1258
1221
  const outputIds = results.filter(r => !r.aborted || r.output.trim()).map(r => `agent://${r.id}`);
1259
- const backendSummaryPrefix = isolationBackendWarning ? `\n\n${isolationBackendWarning}` : "";
1260
1222
  const summary = prompt.render(taskSummaryTemplate, {
1261
1223
  successCount,
1262
1224
  totalCount: results.length,
@@ -1266,7 +1228,7 @@ export class TaskTool implements AgentTool<TSchema, TaskToolDetails, Theme> {
1266
1228
  summaries,
1267
1229
  outputIds,
1268
1230
  agentName,
1269
- mergeSummary: `${backendSummaryPrefix}${mergeSummary}`,
1231
+ mergeSummary,
1270
1232
  });
1271
1233
 
1272
1234
  // Cleanup temp directory if used