pi-ui-extend 0.1.35 → 0.1.37

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.
Files changed (80) hide show
  1. package/dist/app/app.d.ts +8 -0
  2. package/dist/app/app.js +48 -5
  3. package/dist/app/commands/command-controller.js +1 -0
  4. package/dist/app/commands/command-host.d.ts +1 -0
  5. package/dist/app/commands/command-model-actions.d.ts +1 -0
  6. package/dist/app/commands/command-model-actions.js +32 -0
  7. package/dist/app/commands/command-navigation-actions.js +3 -0
  8. package/dist/app/commands/command-registry.d.ts +1 -0
  9. package/dist/app/commands/command-registry.js +8 -0
  10. package/dist/app/commands/command-session-actions.d.ts +2 -0
  11. package/dist/app/commands/command-session-actions.js +81 -1
  12. package/dist/app/extensions/extension-actions-controller.d.ts +5 -1
  13. package/dist/app/extensions/extension-actions-controller.js +35 -2
  14. package/dist/app/input/input-controller.d.ts +2 -0
  15. package/dist/app/input/input-controller.js +50 -2
  16. package/dist/app/input/terminal-edit-shortcuts.d.ts +2 -0
  17. package/dist/app/input/terminal-edit-shortcuts.js +49 -0
  18. package/dist/app/input/voice-controller.js +1 -1
  19. package/dist/app/popup/popup-action-controller.d.ts +2 -3
  20. package/dist/app/popup/popup-action-controller.js +2 -5
  21. package/dist/app/rendering/message-content.js +4 -3
  22. package/dist/app/rendering/render-controller.js +21 -38
  23. package/dist/app/rendering/status-line-renderer.d.ts +1 -0
  24. package/dist/app/rendering/status-line-renderer.js +14 -2
  25. package/dist/app/runtime.js +12 -2
  26. package/dist/app/screen/mouse-controller.js +2 -0
  27. package/dist/app/session/session-event-controller.d.ts +7 -0
  28. package/dist/app/session/session-event-controller.js +10 -13
  29. package/dist/app/session/session-lifecycle-controller.d.ts +1 -0
  30. package/dist/app/session/session-lifecycle-controller.js +7 -0
  31. package/dist/app/session/tabs-controller.d.ts +1 -0
  32. package/dist/app/session/tabs-controller.js +1 -0
  33. package/dist/app/terminal/terminal-controller.js +1 -0
  34. package/dist/app/terminal/terminal-output-buffer.d.ts +8 -6
  35. package/dist/app/terminal/terminal-output-buffer.js +24 -16
  36. package/dist/app/workspace/workspace-actions-controller.d.ts +1 -0
  37. package/dist/app/workspace/workspace-actions-controller.js +1 -0
  38. package/dist/bundled-extensions/terminal-bell/index.js +118 -33
  39. package/dist/markdown-format.d.ts +1 -0
  40. package/dist/markdown-format.js +30 -16
  41. package/dist/schemas/pi-tools-suite-schema.d.ts +5 -0
  42. package/dist/schemas/pi-tools-suite-schema.js +5 -0
  43. package/dist/tool-renderers/apply-patch.js +6 -1
  44. package/dist/tool-renderers/patch-normalize.d.ts +24 -0
  45. package/dist/tool-renderers/patch-normalize.js +163 -0
  46. package/external/pi-tools-suite/README.md +3 -2
  47. package/external/pi-tools-suite/package.json +5 -5
  48. package/external/pi-tools-suite/src/antigravity-auth/index.ts +15 -2
  49. package/external/pi-tools-suite/src/antigravity-auth/status.ts +36 -19
  50. package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +5 -2
  51. package/external/pi-tools-suite/src/async-subagents/commands.ts +12 -2
  52. package/external/pi-tools-suite/src/async-subagents/core/config.ts +8 -3
  53. package/external/pi-tools-suite/src/async-subagents/core/routing.ts +63 -28
  54. package/external/pi-tools-suite/src/async-subagents/core/tool-guard.ts +9 -4
  55. package/external/pi-tools-suite/src/comment-checker/config.ts +98 -0
  56. package/external/pi-tools-suite/src/comment-checker/detect.ts +215 -0
  57. package/external/pi-tools-suite/src/comment-checker/index.ts +294 -0
  58. package/external/pi-tools-suite/src/dcp/commands.ts +29 -15
  59. package/external/pi-tools-suite/src/dcp/compress-tool.ts +111 -60
  60. package/external/pi-tools-suite/src/dcp/config.ts +10 -6
  61. package/external/pi-tools-suite/src/dcp/debug-log.ts +235 -0
  62. package/external/pi-tools-suite/src/dcp/index.ts +204 -27
  63. package/external/pi-tools-suite/src/dcp/prompts.ts +25 -28
  64. package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +6 -10
  65. package/external/pi-tools-suite/src/dcp/pruner-compression-blocks.ts +19 -1
  66. package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +36 -58
  67. package/external/pi-tools-suite/src/dcp/pruner-metadata.ts +18 -0
  68. package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +3 -3
  69. package/external/pi-tools-suite/src/dcp/pruner.ts +4 -2
  70. package/external/pi-tools-suite/src/dcp/state-persistence.ts +31 -2
  71. package/external/pi-tools-suite/src/dcp/state.ts +62 -4
  72. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +18 -0
  73. package/external/pi-tools-suite/src/index.ts +1 -0
  74. package/external/pi-tools-suite/src/model-tools/index.ts +11 -3
  75. package/external/pi-tools-suite/src/telegram-mirror/index.ts +1 -1
  76. package/external/pi-tools-suite/src/todo/index.ts +24 -0
  77. package/external/pi-tools-suite/src/tool-descriptions.ts +3 -3
  78. package/external/pi-tools-suite/src/usage/index.ts +18 -4
  79. package/package.json +4 -4
  80. package/schemas/pi-tools-suite.json +24 -0
@@ -429,12 +429,20 @@ export default function modelTools(pi: ExtensionAPI): void {
429
429
  let baseTools: string[] = [];
430
430
 
431
431
  pi.on("session_start", (_event, ctx) => {
432
- baseTools = pi.getActiveTools().filter((tool) => !MANAGED_TOOLS.has(tool));
433
- applyToolProfile(pi, ctx.model, baseTools);
432
+ try {
433
+ baseTools = pi.getActiveTools().filter((tool) => !MANAGED_TOOLS.has(tool));
434
+ applyToolProfile(pi, ctx.model, baseTools);
435
+ } catch (error) {
436
+ ignoreStaleExtensionContextError(error);
437
+ }
434
438
  });
435
439
 
436
440
  pi.on("model_select", (event) => {
437
- applyToolProfile(pi, event.model, baseTools);
441
+ try {
442
+ applyToolProfile(pi, event.model, baseTools);
443
+ } catch (error) {
444
+ ignoreStaleExtensionContextError(error);
445
+ }
438
446
  });
439
447
  }
440
448
 
@@ -362,7 +362,7 @@ export default function telegramMirror(pi: ExtensionAPI): void {
362
362
  try {
363
363
  switch (command) {
364
364
  case "sendUserMessage":
365
- sendUserMessageSafely(((args as { text?: string } | undefined)?.text ?? ""));
365
+ staleSafe(() => sendUserMessageSafely(((args as { text?: string } | undefined)?.text ?? "")));
366
366
  break;
367
367
  case "abort":
368
368
  mirrorCtx?.abort();
@@ -10,6 +10,16 @@ import { getState, replaceState } from "./state/store.js";
10
10
  import { activateTodoStateScope, DEFAULT_PROMPT_GUIDELINES, DEFAULT_PROMPT_SNIPPET, publishTodoState, registerTodosCommand, registerTodoTool } from "./todo.js";
11
11
  import type { Task, TaskMutationParams } from "./tool/types.js";
12
12
 
13
+ /**
14
+ * Renderer-relayed signal that the session is in an auto-retry cycle.
15
+ * Payload: `{ active: boolean }`. The SDK does not forward retry state to
16
+ * extensions, so the renderer emits this on the extension event bus. We use it
17
+ * to suppress the auto-nudge on intermediate retry agent_end events: nudging
18
+ * then races the pending retry continuation and surfaces a benign
19
+ * "Agent is already processing" extension error in other tabs.
20
+ */
21
+ const RETRY_ACTIVE_EVENT = "pix:retry-active";
22
+
13
23
  type AgentMessageLike = { role?: unknown; stopReason?: unknown; content?: unknown };
14
24
 
15
25
  const TODO_NUDGE_LIMIT = 8;
@@ -134,6 +144,10 @@ export default function (pi: ExtensionAPI) {
134
144
  const pendingAskUserToolCallIds = new Set<string>();
135
145
  let suppressNextNudgeForThinkingSwitch = false;
136
146
  let inProgressAtAgentStart = new Set<number>();
147
+ // True while the session is in an auto-retry cycle (relayed via the
148
+ // extension event bus). Suppresses the auto-nudge on intermediate retry
149
+ // agent_end events so it doesn't race the pending retry continuation.
150
+ let retryActive = false;
137
151
 
138
152
  function registerTodoToolWithCurrentPrompt(): void {
139
153
  const thinkingPrompt = todoThinkingEnabled ? buildThinkingPromptParts(currentModel) : {};
@@ -322,6 +336,9 @@ export default function (pi: ExtensionAPI) {
322
336
  const delayMs = attempt === 0 ? TODO_NUDGE_INITIAL_DELAY_MS : TODO_NUDGE_IDLE_RETRY_DELAY_MS;
323
337
  nudgeTimer = setTimeout(() => {
324
338
  nudgeTimer = undefined;
339
+ // A retry-start signal may have arrived after the agent_end that
340
+ // scheduled this nudge. Bail out so we don't nudge mid-retry.
341
+ if (retryActive) return;
325
342
  try {
326
343
  activateTodoStateScope(ctx);
327
344
  if (!ctx.isIdle()) {
@@ -396,6 +413,12 @@ export default function (pi: ExtensionAPI) {
396
413
  clearNudgeTimer();
397
414
  });
398
415
 
416
+ pi.events.on(RETRY_ACTIVE_EVENT, (data: unknown) => {
417
+ const active = data != null && typeof data === "object" && (data as { active?: unknown }).active === true;
418
+ retryActive = active;
419
+ if (active) clearNudgeTimer();
420
+ });
421
+
399
422
  pi.on("model_select", async (event) => {
400
423
  currentModel = event.model;
401
424
  if (todoThinkingEnabled) registerTodoToolWithCurrentPrompt();
@@ -416,6 +439,7 @@ export default function (pi: ExtensionAPI) {
416
439
  pi.on("agent_start", async (_event, ctx) => {
417
440
  activateTodoStateScope(ctx);
418
441
  pendingAskUserToolCallIds.clear();
442
+ retryActive = false;
419
443
  inProgressAtAgentStart = new Set(selectVisibleTasks(getState()).filter((task) => task.status === "in_progress").map((task) => task.id));
420
444
  });
421
445
 
@@ -27,10 +27,10 @@ export const COMPRESS_TOOL_DESCRIPTION: ToolDescription = {
27
27
  name: "compress",
28
28
  label: "Compress Context",
29
29
  description: COMPRESS_RANGE_DESCRIPTION,
30
- promptSnippet: "Compress closed conversation slices as steady context housekeeping; before any new search/read/test/web lookup, compress older completed work unless exact raw text is still needed.",
30
+ promptSnippet: "Use compress for context-pressure housekeeping: summarize closed, high-yield stale slices when context is meaningfully high or a DCP reminder gives concrete candidates; do not compress just because low-context work produced a small closed slice.",
31
31
  promptGuidelines: [
32
- "Treat completed implementation, verification, config/doc edits, answered exploration, dead ends, and log inspection as compression candidates immediately.",
33
- "Do not carry large stale shell/read/repo/web outputs, diffs, or passing logs across task boundaries; summarize their actionable result instead.",
32
+ "Treat completed implementation, verification, config/doc edits, answered exploration, dead ends, and log inspection as compression candidates when they are large, stale, or context pressure is meaningful.",
33
+ "Do not carry large stale shell/read/repo/web outputs, diffs, or passing logs across task boundaries when their exact text is no longer useful; summarize their actionable result instead.",
34
34
  "Keep active, still-needed context raw; compress only closed ranges whose exact content is unlikely to be needed next.",
35
35
  ],
36
36
  };
@@ -4,6 +4,7 @@ import { homedir } from "node:os";
4
4
  import { join } from "node:path";
5
5
 
6
6
  import { publishStartupSection } from "../startup-section";
7
+ import { ignoreStaleExtensionContextError } from "../context-usage";
7
8
  import { queryGoogleUsage } from "./lib/google";
8
9
  import { queryOpenAIUsage } from "./lib/openai";
9
10
  import { type AuthData, type QueryResult } from "./lib/types";
@@ -127,6 +128,14 @@ function sendStatusMessage(pi: ExtensionAPI, text: string): void {
127
128
  });
128
129
  }
129
130
 
131
+ async function staleSafe(action: () => void | Promise<void>): Promise<void> {
132
+ try {
133
+ await action();
134
+ } catch (error) {
135
+ ignoreStaleExtensionContextError(error);
136
+ }
137
+ }
138
+
130
139
  export default function usage(pi: ExtensionAPI) {
131
140
  publishStartupSection({
132
141
  id: "usage",
@@ -137,13 +146,18 @@ export default function usage(pi: ExtensionAPI) {
137
146
  async function showStatusFromCommand(ctx: ExtensionCommandContext): Promise<void> {
138
147
  const text = await queryUsage();
139
148
 
140
- if (ctx.hasUI) {
141
- ctx.ui.notify("usage: quota usage refreshed", "info");
142
- } else {
149
+ if (!ctx.hasUI) {
143
150
  console.log(text);
151
+ await staleSafe(() => {
152
+ sendStatusMessage(pi, text);
153
+ });
154
+ return;
144
155
  }
145
156
 
146
- sendStatusMessage(pi, text);
157
+ await staleSafe(async () => {
158
+ ctx.ui.notify("usage: quota usage refreshed", "info");
159
+ sendStatusMessage(pi, text);
160
+ });
147
161
  }
148
162
 
149
163
  pi.registerCommand("usage", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ui-extend",
3
- "version": "0.1.35",
3
+ "version": "0.1.37",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -64,9 +64,9 @@
64
64
  "prepublishOnly": "npm run check && npm run build:pix && npm run generate-schemas"
65
65
  },
66
66
  "dependencies": {
67
- "@earendil-works/pi-ai": "0.79.4",
68
- "@earendil-works/pi-coding-agent": "0.79.4",
69
- "@earendil-works/pi-tui": "0.79.4",
67
+ "@earendil-works/pi-ai": "0.79.5",
68
+ "@earendil-works/pi-coding-agent": "0.79.5",
69
+ "@earendil-works/pi-tui": "0.79.5",
70
70
  "@mariozechner/clipboard": "^0.3.9",
71
71
  "jsonc-parser": "3.3.1",
72
72
  "typebox": "1.1.38",
@@ -66,6 +66,22 @@
66
66
  "type": "boolean",
67
67
  "description": "Enable DCP debug logging."
68
68
  },
69
+ "debugLog": {
70
+ "type": "object",
71
+ "properties": {
72
+ "maxBytes": {
73
+ "type": "number",
74
+ "description": "Maximum size in bytes of the active debug log before it is rotated. Default 5242880 (5 MB).",
75
+ "minimum": 1024
76
+ },
77
+ "maxBackups": {
78
+ "type": "number",
79
+ "description": "Number of rotated backups to keep (.1 .. .N). Default 3, minimum 1.",
80
+ "minimum": 1
81
+ }
82
+ },
83
+ "description": "Debug log rotation. The JSONL log is written to ~/.pi/agent/dcp-debug.jsonl."
84
+ },
69
85
  "manualMode": {
70
86
  "type": "object",
71
87
  "properties": {
@@ -418,6 +434,14 @@
418
434
  "type": "string",
419
435
  "description": "Router model in provider/model form."
420
436
  },
437
+ "fallbackModels": {
438
+ "type": "array",
439
+ "items": {
440
+ "type": "string"
441
+ },
442
+ "uniqueItems": true,
443
+ "description": "Ordered router model fallbacks tried when the primary routing model is unavailable or fails. The current parent model is always tried last."
444
+ },
421
445
  "maxTaskChars": {
422
446
  "type": "number",
423
447
  "description": "Max task/scope characters sent to router.",