@oh-my-pi/pi-coding-agent 15.12.1 → 15.12.3
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 +14 -1
- package/dist/cli.js +28 -42
- package/dist/types/collab/protocol.d.ts +8 -2
- package/dist/types/config/settings-schema.d.ts +2 -2
- package/package.json +12 -12
- package/src/collab/host.ts +13 -1
- package/src/collab/protocol.ts +25 -16
- package/src/config/settings-schema.ts +2 -5
- package/src/internal-urls/docs-index.generated.ts +3 -3
- package/src/modes/controllers/input-controller.ts +7 -1
- package/src/session/agent-session.ts +23 -0
- package/src/tools/ast-edit.ts +12 -3
|
@@ -178,7 +178,12 @@ export class InputController {
|
|
|
178
178
|
} else if (this.ctx.session.isStreaming) {
|
|
179
179
|
this.ctx.notifyInterrupting();
|
|
180
180
|
void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
|
|
181
|
-
} else if (
|
|
181
|
+
} else if (this.ctx.editor.getText().trim()) {
|
|
182
|
+
// Esc with typed text clears the draft instead of (or before) any double-Esc action
|
|
183
|
+
this.ctx.editor.setText("");
|
|
184
|
+
this.ctx.ui.requestRender();
|
|
185
|
+
this.ctx.lastEscapeTime = 0;
|
|
186
|
+
} else {
|
|
182
187
|
// Double-interrupt with empty editor triggers /tree, /branch, or nothing based on setting
|
|
183
188
|
const action = settings.get("doubleEscapeAction");
|
|
184
189
|
if (action !== "none") {
|
|
@@ -189,6 +194,7 @@ export class InputController {
|
|
|
189
194
|
} else {
|
|
190
195
|
this.ctx.showUserMessageSelector();
|
|
191
196
|
}
|
|
197
|
+
this.ctx.ui.resetDisplay();
|
|
192
198
|
this.ctx.lastEscapeTime = 0;
|
|
193
199
|
} else {
|
|
194
200
|
this.ctx.lastEscapeTime = now;
|
|
@@ -1139,9 +1139,24 @@ export class AgentSession {
|
|
|
1139
1139
|
if (this.#promptInFlightCount === 0) {
|
|
1140
1140
|
this.#releasePowerAssertion();
|
|
1141
1141
|
this.#flushPendingAgentEnd();
|
|
1142
|
+
this.#drainStrandedQueuedMessages();
|
|
1142
1143
|
}
|
|
1143
1144
|
}
|
|
1144
1145
|
|
|
1146
|
+
/** A steer/follow-up can land after the agent loop's final queue poll but
|
|
1147
|
+
* before the prompt unwinds: #promptInFlightCount keeps isStreaming true
|
|
1148
|
+
* through post-prompt recovery, so senders (collab guests, skills) still
|
|
1149
|
+
* queue via agent.steer()/followUp() instead of starting a fresh prompt.
|
|
1150
|
+
* Without a drain those messages strand invisibly until the next manual
|
|
1151
|
+
* prompt. Runs when the session settles; the guard makes it a no-op when
|
|
1152
|
+
* the queue was consumed normally or a new turn already started. */
|
|
1153
|
+
#drainStrandedQueuedMessages(): void {
|
|
1154
|
+
if (!this.agent.hasQueuedMessages()) return;
|
|
1155
|
+
this.#scheduleAgentContinue({
|
|
1156
|
+
shouldContinue: () => this.#canAutoContinueForFollowUp() && this.agent.hasQueuedMessages(),
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1145
1160
|
#resetInFlight(): void {
|
|
1146
1161
|
this.#promptInFlightCount = 0;
|
|
1147
1162
|
this.#releasePowerAssertion();
|
|
@@ -5255,6 +5270,14 @@ export class AgentSession {
|
|
|
5255
5270
|
} else {
|
|
5256
5271
|
this.agent.steer(normalizedAppMessage);
|
|
5257
5272
|
}
|
|
5273
|
+
// The isStreaming check above can be stale: image normalization is
|
|
5274
|
+
// awaited, so the turn may have ended in between, leaving the message
|
|
5275
|
+
// queued on an idle agent. Mirror #queueSteer's idle-path delivery.
|
|
5276
|
+
if (this.#canAutoContinueForFollowUp()) {
|
|
5277
|
+
this.#scheduleAgentContinue({
|
|
5278
|
+
shouldContinue: () => this.#canAutoContinueForFollowUp() && this.agent.hasQueuedMessages(),
|
|
5279
|
+
});
|
|
5280
|
+
}
|
|
5258
5281
|
return;
|
|
5259
5282
|
}
|
|
5260
5283
|
|
package/src/tools/ast-edit.ts
CHANGED
|
@@ -512,6 +512,14 @@ function buildChangeBody(groups: string[][], expanded: boolean, budget: number,
|
|
|
512
512
|
return lines;
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
+
/** One-line header preview of an AST pattern. `renderStatusLine` only flattens
|
|
516
|
+
* CR/LF, so a multi-line tab-indented pattern would otherwise punch raw tabs
|
|
517
|
+
* into the status line; collapse all whitespace runs to single spaces. */
|
|
518
|
+
function patternPreview(pat: string | undefined): string | undefined {
|
|
519
|
+
const collapsed = pat?.replace(/\s+/g, " ").trim();
|
|
520
|
+
return collapsed || undefined;
|
|
521
|
+
}
|
|
522
|
+
|
|
515
523
|
export const astEditToolRenderer = {
|
|
516
524
|
inline: true,
|
|
517
525
|
renderCall(args: AstEditRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
|
|
@@ -520,7 +528,8 @@ export const astEditToolRenderer = {
|
|
|
520
528
|
const rewriteCount = args.ops?.length ?? 0;
|
|
521
529
|
if (rewriteCount > 1) meta.push(`${rewriteCount} rewrites`);
|
|
522
530
|
|
|
523
|
-
const description =
|
|
531
|
+
const description =
|
|
532
|
+
rewriteCount === 1 ? patternPreview(args.ops?.[0]?.pat) : rewriteCount ? `${rewriteCount} rewrites` : "?";
|
|
524
533
|
const header = renderStatusLine({ icon: "pending", title: "AST Edit", description, meta }, uiTheme);
|
|
525
534
|
// Pending call has no body yet — a lone status line is sleeker than an empty frame.
|
|
526
535
|
return new Text(header, 0, 0);
|
|
@@ -553,7 +562,7 @@ export const astEditToolRenderer = {
|
|
|
553
562
|
|
|
554
563
|
if (totalReplacements === 0) {
|
|
555
564
|
const rewriteCount = args?.ops?.length ?? 0;
|
|
556
|
-
const description = rewriteCount === 1 ? args?.ops?.[0]?.pat : undefined;
|
|
565
|
+
const description = rewriteCount === 1 ? patternPreview(args?.ops?.[0]?.pat) : undefined;
|
|
557
566
|
const meta = ["0 replacements"];
|
|
558
567
|
if (details?.scopePath) meta.push(`in ${details.scopePath}`);
|
|
559
568
|
if (filesSearched > 0) meta.push(`searched ${filesSearched}`);
|
|
@@ -578,7 +587,7 @@ export const astEditToolRenderer = {
|
|
|
578
587
|
meta.push(`searched ${filesSearched}`);
|
|
579
588
|
if (limitReached) meta.push(uiTheme.fg("warning", "limit reached"));
|
|
580
589
|
const rewriteCount = args?.ops?.length ?? 0;
|
|
581
|
-
const description = rewriteCount === 1 ? args?.ops?.[0]?.pat : undefined;
|
|
590
|
+
const description = rewriteCount === 1 ? patternPreview(args?.ops?.[0]?.pat) : undefined;
|
|
582
591
|
|
|
583
592
|
const textContent = result.details?.displayContent ?? result.content?.find(c => c.type === "text")?.text ?? "";
|
|
584
593
|
const allLines = textContent.split("\n");
|