@oh-my-pi/pi-coding-agent 13.4.0 → 13.4.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
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [13.4.1] - 2026-03-01
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Pending resolve reminders now trigger as soon as a preview action is queued, before the next assistant turn, with regression coverage in `agent-session-resolve-reminder` tests
|
|
10
|
+
|
|
5
11
|
## [13.4.0] - 2026-03-01
|
|
6
12
|
|
|
7
13
|
### Breaking Changes
|
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.4.
|
|
4
|
+
"version": "13.4.1",
|
|
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.4.
|
|
45
|
-
"@oh-my-pi/pi-agent-core": "13.4.
|
|
46
|
-
"@oh-my-pi/pi-ai": "13.4.
|
|
47
|
-
"@oh-my-pi/pi-natives": "13.4.
|
|
48
|
-
"@oh-my-pi/pi-tui": "13.4.
|
|
49
|
-
"@oh-my-pi/pi-utils": "13.4.
|
|
44
|
+
"@oh-my-pi/omp-stats": "13.4.1",
|
|
45
|
+
"@oh-my-pi/pi-agent-core": "13.4.1",
|
|
46
|
+
"@oh-my-pi/pi-ai": "13.4.1",
|
|
47
|
+
"@oh-my-pi/pi-natives": "13.4.1",
|
|
48
|
+
"@oh-my-pi/pi-tui": "13.4.1",
|
|
49
|
+
"@oh-my-pi/pi-utils": "13.4.1",
|
|
50
50
|
"@sinclair/typebox": "^0.34",
|
|
51
51
|
"@xterm/headless": "^6.0",
|
|
52
52
|
"ajv": "^8.18",
|
|
@@ -4,22 +4,20 @@ Performs structural AST-aware rewrites via native ast-grep.
|
|
|
4
4
|
- Use for codemods and structural rewrites where plain text replace is unsafe
|
|
5
5
|
- Narrow scope with `path` before replacing (`path` accepts files, directories, or glob patterns)
|
|
6
6
|
- Default to language-scoped rewrites in mixed repositories: set `lang` and keep `path` narrow
|
|
7
|
-
- Always returns a preview; after reviewing, call `resolve` with `action: "apply"` or `action: "discard"`
|
|
8
7
|
- Treat parse issues as a scoping signal: tighten `path`/`lang` before retrying
|
|
9
8
|
- Metavariables captured in each rewrite pattern (`$A`, `$$$ARGS`) are substituted into that entry's rewrite template
|
|
10
9
|
- Each matched rewrite is a 1:1 structural substitution; you cannot split one capture into multiple nodes or merge multiple captures into one node
|
|
11
10
|
</instruction>
|
|
12
11
|
|
|
13
12
|
<output>
|
|
14
|
-
- Returns replacement summary, per-file replacement counts, and change
|
|
15
|
-
- Reports whether changes were applied or only previewed
|
|
13
|
+
- Returns replacement summary, per-file replacement counts, and change diffs
|
|
16
14
|
- Includes parse issues when files cannot be processed
|
|
17
15
|
</output>
|
|
18
16
|
|
|
19
17
|
<examples>
|
|
20
|
-
- Rename a call site across a directory
|
|
18
|
+
- Rename a call site across a directory:
|
|
21
19
|
`{"ops":[{"pat":"oldApi($$$ARGS)","out":"newApi($$$ARGS)"}],"lang":"typescript","path":"src/"}`
|
|
22
|
-
- Multi-op codemod
|
|
20
|
+
- Multi-op codemod:
|
|
23
21
|
`{"ops":[{"pat":"require($A)","out":"import $A"},{"pat":"module.exports = $E","out":"export default $E"}],"lang":"javascript","path":"src/"}`
|
|
24
22
|
- Swap two arguments using captures:
|
|
25
23
|
`{"ops":[{"pat":"assertEqual($A, $B)","out":"assertEqual($B, $A)"}],"lang":"typescript","path":"tests/"}`
|
|
@@ -28,6 +26,5 @@ Performs structural AST-aware rewrites via native ast-grep.
|
|
|
28
26
|
<critical>
|
|
29
27
|
- `ops` **MUST** contain at least one concrete `{ pat, out }` entry
|
|
30
28
|
- If the path pattern spans multiple languages, set `lang` explicitly for deterministic rewrites
|
|
31
|
-
- Review preview output, then use the `resolve` tool to apply or discard (with a reason)
|
|
32
29
|
- For one-off local text edits, prefer the Edit tool instead of AST edit
|
|
33
30
|
</critical>
|
|
@@ -43,6 +43,7 @@ Every edit has `op`, `pos`, and `lines`. Range replaces also have `end`. Both `p
|
|
|
43
43
|
3. **Range end tag (inclusive):** `end` is inclusive and **MUST** point to the final line being replaced.
|
|
44
44
|
- If `lines` includes a closing boundary token (`}`, `]`, `)`, `);`, `},`), `end` **MUST** include the original boundary line.
|
|
45
45
|
- You **MUST NOT** set `end` to an interior line and then re-add the boundary token in `lines`; that duplicates the next surviving line.
|
|
46
|
+
- To remove a line while keeping its neighbors, **delete** it (`lines: null`). You **MUST NOT** replace it with the content of an adjacent line — that line still exists and will be duplicated.
|
|
46
47
|
</rules>
|
|
47
48
|
|
|
48
49
|
<recovery>
|
|
@@ -291,6 +291,7 @@ export class AgentSession {
|
|
|
291
291
|
|
|
292
292
|
// Event subscription state
|
|
293
293
|
#unsubscribeAgent?: () => void;
|
|
294
|
+
#unsubscribePendingActionPush?: () => void;
|
|
294
295
|
#eventListeners: AgentSessionEventListener[] = [];
|
|
295
296
|
|
|
296
297
|
/** Tracks pending steering messages for UI display. Removed when delivered. */
|
|
@@ -397,6 +398,21 @@ export class AgentSession {
|
|
|
397
398
|
this.#obfuscator = config.obfuscator;
|
|
398
399
|
this.agent.providerSessionState = this.#providerSessionState;
|
|
399
400
|
this.#pendingActionStore = config.pendingActionStore;
|
|
401
|
+
this.#unsubscribePendingActionPush = this.#pendingActionStore?.subscribePush(action => {
|
|
402
|
+
const reminderText = [
|
|
403
|
+
"<system-reminder>",
|
|
404
|
+
"This is a preview. Call the `resolve` tool to apply or discard these changes.",
|
|
405
|
+
"</system-reminder>",
|
|
406
|
+
].join("\n");
|
|
407
|
+
this.agent.steer({
|
|
408
|
+
role: "custom",
|
|
409
|
+
customType: "resolve-reminder",
|
|
410
|
+
content: reminderText,
|
|
411
|
+
display: false,
|
|
412
|
+
details: { toolName: action.sourceToolName },
|
|
413
|
+
timestamp: Date.now(),
|
|
414
|
+
});
|
|
415
|
+
});
|
|
400
416
|
this.#syncTodoPhasesFromBranch();
|
|
401
417
|
|
|
402
418
|
// Always subscribe to agent events for internal handling
|
|
@@ -688,22 +704,6 @@ export class AgentSession {
|
|
|
688
704
|
{ deliverAs: "nextTurn" },
|
|
689
705
|
);
|
|
690
706
|
}
|
|
691
|
-
if (!isError && this.#pendingActionStore?.hasPending) {
|
|
692
|
-
const reminderText = [
|
|
693
|
-
"<system-reminder>",
|
|
694
|
-
"This is a preview. Call the `resolve` tool to apply or discard these changes.",
|
|
695
|
-
"</system-reminder>",
|
|
696
|
-
].join("\n");
|
|
697
|
-
await this.sendCustomMessage(
|
|
698
|
-
{
|
|
699
|
-
customType: "resolve-reminder",
|
|
700
|
-
content: reminderText,
|
|
701
|
-
display: false,
|
|
702
|
-
details: { toolName },
|
|
703
|
-
},
|
|
704
|
-
{ deliverAs: "nextTurn" },
|
|
705
|
-
);
|
|
706
|
-
}
|
|
707
707
|
}
|
|
708
708
|
}
|
|
709
709
|
|
|
@@ -1443,6 +1443,8 @@ export class AgentSession {
|
|
|
1443
1443
|
state.close();
|
|
1444
1444
|
}
|
|
1445
1445
|
this.#providerSessionState.clear();
|
|
1446
|
+
this.#unsubscribePendingActionPush?.();
|
|
1447
|
+
this.#unsubscribePendingActionPush = undefined;
|
|
1446
1448
|
this.#disconnectFromAgent();
|
|
1447
1449
|
this.#eventListeners = [];
|
|
1448
1450
|
}
|
|
@@ -10,9 +10,14 @@ export interface PendingAction {
|
|
|
10
10
|
|
|
11
11
|
export class PendingActionStore {
|
|
12
12
|
#actions: PendingAction[] = [];
|
|
13
|
+
#pushListeners = new Set<(action: PendingAction, count: number) => void>();
|
|
13
14
|
|
|
14
15
|
push(action: PendingAction): void {
|
|
15
16
|
this.#actions.push(action);
|
|
17
|
+
const count = this.#actions.length;
|
|
18
|
+
for (const listener of this.#pushListeners) {
|
|
19
|
+
listener(action, count);
|
|
20
|
+
}
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
peek(): PendingAction | null {
|
|
@@ -23,10 +28,21 @@ export class PendingActionStore {
|
|
|
23
28
|
return this.#actions.pop() ?? null;
|
|
24
29
|
}
|
|
25
30
|
|
|
31
|
+
subscribePush(listener: (action: PendingAction, count: number) => void): () => void {
|
|
32
|
+
this.#pushListeners.add(listener);
|
|
33
|
+
return () => {
|
|
34
|
+
this.#pushListeners.delete(listener);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
26
38
|
clear(): void {
|
|
27
39
|
this.#actions = [];
|
|
28
40
|
}
|
|
29
41
|
|
|
42
|
+
get count(): number {
|
|
43
|
+
return this.#actions.length;
|
|
44
|
+
}
|
|
45
|
+
|
|
30
46
|
get hasPending(): boolean {
|
|
31
47
|
return this.#actions.length > 0;
|
|
32
48
|
}
|