pi-ui-extend 1.0.40 → 1.0.42

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 (186) hide show
  1. package/README.md +10 -2
  2. package/dist/app/app.d.ts +3 -0
  3. package/dist/app/app.js +26 -0
  4. package/dist/app/commands/command-host.d.ts +1 -0
  5. package/dist/app/commands/command-model-actions.js +6 -1
  6. package/dist/app/commands/command-registry.js +3 -3
  7. package/dist/app/commands/command-session-actions.d.ts +0 -1
  8. package/dist/app/commands/command-session-actions.js +30 -15
  9. package/dist/app/commands/reload-context-inventory.d.ts +11 -0
  10. package/dist/app/commands/reload-context-inventory.js +59 -0
  11. package/dist/app/extensions/extension-actions-controller.d.ts +1 -0
  12. package/dist/app/extensions/extension-actions-controller.js +6 -0
  13. package/dist/app/extensions/subagent-catalog-state.d.ts +9 -0
  14. package/dist/app/extensions/subagent-catalog-state.js +23 -0
  15. package/dist/app/icons.d.ts +14 -0
  16. package/dist/app/icons.js +33 -0
  17. package/dist/app/rendering/conversation-tool-renderer.js +2 -2
  18. package/dist/app/rendering/dcp-stats.d.ts +6 -1
  19. package/dist/app/rendering/dcp-stats.js +214 -46
  20. package/dist/app/rendering/editor-panels.js +17 -8
  21. package/dist/app/session/lazy-session-manager.js +12 -1
  22. package/dist/app/session/session-lifecycle-controller.d.ts +1 -0
  23. package/dist/app/session/session-lifecycle-controller.js +6 -0
  24. package/dist/app/session/tabs-controller.d.ts +3 -5
  25. package/dist/app/session/tabs-controller.js +31 -22
  26. package/dist/app/subagents/subagents-files.js +60 -1
  27. package/dist/app/subagents/subagents-model.d.ts +15 -1
  28. package/dist/app/subagents/subagents-model.js +52 -17
  29. package/dist/app/types.d.ts +7 -0
  30. package/dist/bundled-extensions/session-title/config.js +1 -1
  31. package/dist/default-pix-config.js +10 -0
  32. package/dist/markdown-format.js +27 -9
  33. package/dist/schemas/index.d.ts +1 -0
  34. package/dist/schemas/index.js +1 -0
  35. package/dist/schemas/pi-tools-suite-schema.d.ts +106 -71
  36. package/dist/schemas/pi-tools-suite-schema.js +68 -88
  37. package/dist/schemas/pix-schema.d.ts +7 -0
  38. package/dist/schemas/pix-schema.js +14 -0
  39. package/dist/schemas/tasks-schema.d.ts +18 -0
  40. package/dist/schemas/tasks-schema.js +41 -0
  41. package/docs/concurrency.md +6 -0
  42. package/docs/desktop-mvp.md +12 -1
  43. package/docs/desktop-task-manager.md +93 -82
  44. package/external/pi-tools-suite/README.md +192 -72
  45. package/external/pi-tools-suite/docs/browser-qa-subagent.md +50 -21
  46. package/external/pi-tools-suite/docs/context-gateway-p00-adr.md +216 -0
  47. package/external/pi-tools-suite/docs/context-gateway-p01n-gate-review.md +122 -0
  48. package/external/pi-tools-suite/docs/context-gateway-p01n-measurement.md +133 -0
  49. package/external/pi-tools-suite/docs/context-gateway-p01r-ra-evidence.md +111 -0
  50. package/external/pi-tools-suite/docs/context-gateway-p01r-rb-evidence.md +100 -0
  51. package/external/pi-tools-suite/docs/context-gateway-p01r-rc-evidence.md +69 -0
  52. package/external/pi-tools-suite/docs/context-gateway-p01r-rd-evidence.md +100 -0
  53. package/external/pi-tools-suite/docs/context-gateway-p01r-re-evidence.md +74 -0
  54. package/external/pi-tools-suite/docs/context-gateway-p01r-rf-evidence.md +153 -0
  55. package/external/pi-tools-suite/docs/context-gateway-p01r-rg-evidence.md +235 -0
  56. package/external/pi-tools-suite/docs/evals.md +1 -1
  57. package/external/pi-tools-suite/docs/session-recovery.md +40 -14
  58. package/external/pi-tools-suite/docs/subagent-model-pools.md +120 -0
  59. package/external/pi-tools-suite/package.json +3 -0
  60. package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/scripts/browser-qa-runner.mjs +82 -1
  61. package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/SKILL.md → agents/browser-qa.md} +261 -12
  62. package/external/pi-tools-suite/src/async-subagents/agents/frontier-review.md +23 -0
  63. package/external/pi-tools-suite/src/async-subagents/agents/implement.md +20 -0
  64. package/external/pi-tools-suite/src/async-subagents/agents/oracle.md +16 -0
  65. package/external/pi-tools-suite/src/async-subagents/agents/presets.jsonc +16 -0
  66. package/external/pi-tools-suite/src/async-subagents/agents/research.md +20 -0
  67. package/external/pi-tools-suite/src/async-subagents/agents/verify.md +18 -0
  68. package/external/pi-tools-suite/src/async-subagents/commands.ts +20 -72
  69. package/external/pi-tools-suite/src/async-subagents/core/activity.ts +33 -0
  70. package/external/pi-tools-suite/src/async-subagents/core/agent-catalog.ts +42 -0
  71. package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +13 -93
  72. package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +499 -0
  73. package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +9 -0
  74. package/external/pi-tools-suite/src/async-subagents/core/config.ts +284 -417
  75. package/external/pi-tools-suite/src/async-subagents/core/model-fallback.ts +1 -1
  76. package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +54 -0
  77. package/external/pi-tools-suite/src/async-subagents/core/prompt.ts +7 -6
  78. package/external/pi-tools-suite/src/async-subagents/core/routing.ts +65 -45
  79. package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +18 -6
  80. package/external/pi-tools-suite/src/async-subagents/core/state.ts +40 -0
  81. package/external/pi-tools-suite/src/async-subagents/core/types.ts +7 -0
  82. package/external/pi-tools-suite/src/async-subagents/index.ts +77 -3
  83. package/external/pi-tools-suite/src/async-subagents/lib.ts +12 -9
  84. package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +54 -22
  85. package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +6 -4
  86. package/external/pi-tools-suite/src/async-subagents/types.ts +3 -0
  87. package/external/pi-tools-suite/src/config.ts +42 -2
  88. package/external/pi-tools-suite/src/context-gateway/accounting.ts +151 -0
  89. package/external/pi-tools-suite/src/context-gateway/config.ts +120 -0
  90. package/external/pi-tools-suite/src/context-gateway/enforcement.ts +102 -0
  91. package/external/pi-tools-suite/src/context-gateway/index.ts +214 -0
  92. package/external/pi-tools-suite/src/context-gateway/metadata-normalization.ts +88 -0
  93. package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +89 -0
  94. package/external/pi-tools-suite/src/context-gateway/telemetry.ts +502 -0
  95. package/external/pi-tools-suite/src/context-gateway/test-output-parser.ts +326 -0
  96. package/external/pi-tools-suite/src/context-gateway/types.ts +158 -0
  97. package/external/pi-tools-suite/src/context-inventory.ts +99 -0
  98. package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +106 -0
  99. package/external/pi-tools-suite/src/dcp/auto-compress.ts +892 -136
  100. package/external/pi-tools-suite/src/dcp/commands.ts +82 -139
  101. package/external/pi-tools-suite/src/dcp/compress-tool.ts +533 -74
  102. package/external/pi-tools-suite/src/dcp/compression-blocks.ts +488 -94
  103. package/external/pi-tools-suite/src/dcp/compression-preview.ts +122 -0
  104. package/external/pi-tools-suite/src/dcp/compression-progress.ts +70 -0
  105. package/external/pi-tools-suite/src/dcp/config.ts +86 -68
  106. package/external/pi-tools-suite/src/dcp/conversation-index.ts +421 -0
  107. package/external/pi-tools-suite/src/dcp/debug-log.ts +7 -5
  108. package/external/pi-tools-suite/src/dcp/index.ts +617 -203
  109. package/external/pi-tools-suite/src/dcp/journal.ts +566 -0
  110. package/external/pi-tools-suite/src/dcp/progress-controller.ts +244 -0
  111. package/external/pi-tools-suite/src/dcp/prompts.ts +83 -189
  112. package/external/pi-tools-suite/src/dcp/protected-continuity.ts +175 -0
  113. package/external/pi-tools-suite/src/dcp/provider-tool-results.ts +189 -0
  114. package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +299 -79
  115. package/external/pi-tools-suite/src/dcp/pruner-compression-blocks.ts +173 -281
  116. package/external/pi-tools-suite/src/dcp/pruner-emergency.ts +2 -4
  117. package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +23 -15
  118. package/external/pi-tools-suite/src/dcp/pruner-metadata.ts +11 -1
  119. package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +30 -82
  120. package/external/pi-tools-suite/src/dcp/pruner-tools.ts +28 -136
  121. package/external/pi-tools-suite/src/dcp/pruner.ts +18 -33
  122. package/external/pi-tools-suite/src/dcp/recovery.ts +129 -0
  123. package/external/pi-tools-suite/src/dcp/shadow-plan.ts +127 -0
  124. package/external/pi-tools-suite/src/dcp/state-transaction.ts +102 -0
  125. package/external/pi-tools-suite/src/dcp/state.ts +158 -580
  126. package/external/pi-tools-suite/src/dcp/ui.ts +1 -0
  127. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +36 -214
  128. package/external/pi-tools-suite/src/index.ts +16 -1
  129. package/external/pi-tools-suite/src/model-tools/index.ts +76 -42
  130. package/external/pi-tools-suite/src/repo-discovery/index.ts +84 -18
  131. package/external/pi-tools-suite/src/repo-discovery/native-compact.ts +458 -0
  132. package/external/pi-tools-suite/src/resource-registry/index.ts +2290 -0
  133. package/external/pi-tools-suite/src/session-recovery/index.ts +189 -43
  134. package/external/pi-tools-suite/src/shell-command-policy.ts +219 -0
  135. package/external/pi-tools-suite/src/tool-descriptions.ts +41 -38
  136. package/external/pi-tools-suite/src/truncation-metadata-normalizer/index.ts +17 -0
  137. package/package.json +6 -3
  138. package/schemas/pi-tools-suite.json +540 -312
  139. package/schemas/pix.json +24 -0
  140. package/schemas/tasks.json +132 -0
  141. package/skills/spec-wiki/SKILL.md +55 -0
  142. package/skills/spec-wiki/evals/evals.json +132 -0
  143. package/skills/spec-wiki/evals/files/bootstrap/architecture/rfc-007.md +14 -0
  144. package/skills/spec-wiki/evals/files/bootstrap/docs/how-to-pay.md +4 -0
  145. package/skills/spec-wiki/evals/files/bootstrap/docs/overview.md +9 -0
  146. package/skills/spec-wiki/evals/files/bootstrap/requirements/payment-behavior.md +17 -0
  147. package/skills/spec-wiki/evals/files/bootstrap/src/payments.ts +12 -0
  148. package/skills/spec-wiki/evals/files/bootstrap/tests/payments.test.ts +11 -0
  149. package/skills/spec-wiki/evals/files/focused/src/session.ts +5 -0
  150. package/skills/spec-wiki/evals/files/focused/tests/session.test.ts +17 -0
  151. package/skills/spec-wiki/evals/files/maintenance/low-signal/incoming/capture.txt +2 -0
  152. package/skills/spec-wiki/evals/files/maintenance/low-signal/src/capture.ts +3 -0
  153. package/skills/spec-wiki/evals/files/maintenance/move/docs/old-job-contract.md +18 -0
  154. package/skills/spec-wiki/evals/files/maintenance/move/src/job.ts +5 -0
  155. package/skills/spec-wiki/evals/files/maintenance/new-relation/docs/session-refresh.md +24 -0
  156. package/skills/spec-wiki/evals/files/maintenance/new-relation/incoming/refresh-worker.ts +7 -0
  157. package/skills/spec-wiki/evals/files/maintenance/new-relation/src/session.ts +7 -0
  158. package/skills/spec-wiki/evals/files/maintenance/no-impact/docs/auth-contract.md +17 -0
  159. package/skills/spec-wiki/evals/files/maintenance/no-impact/incoming/telemetry-format.ts +3 -0
  160. package/skills/spec-wiki/evals/files/maintenance/no-impact/src/auth.ts +3 -0
  161. package/skills/spec-wiki/evals/files/query/docs/how-to-run-jobs.md +4 -0
  162. package/skills/spec-wiki/evals/files/query/docs/spec-overview.md +9 -0
  163. package/skills/spec-wiki/evals/files/query/features/jobs/cancellation-contract.md +15 -0
  164. package/skills/spec-wiki/evals/files/query/features/jobs/retry-spec.md +6 -0
  165. package/skills/spec-wiki/evals/maintenance_regression.py +311 -0
  166. package/skills/spec-wiki/evals/retrieval-eval.md +37 -0
  167. package/skills/spec-wiki/evals/retrieval-evals.json +37 -0
  168. package/skills/spec-wiki/evals/trigger-evals.json +94 -0
  169. package/skills/spec-wiki/references/bootstrap.md +100 -0
  170. package/skills/spec-wiki/references/focused-spec.md +117 -0
  171. package/skills/spec-wiki/references/index-schema.md +330 -0
  172. package/skills/spec-wiki/references/maintenance.md +134 -0
  173. package/skills/spec-wiki/references/query.md +74 -0
  174. package/skills/spec-wiki/scripts/spec_wiki.py +2076 -0
  175. package/docs/desktop-markdown-media.md +0 -77
  176. package/external/pi-tools-suite/docs/dcp-emergency-current-turn.md +0 -102
  177. package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +0 -270
  178. package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/auth-scaffold-spec.md +0 -78
  179. package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/qa-design.md +0 -223
  180. package/external/pi-tools-suite/src/dcp/state-persistence.ts +0 -195
  181. package/external/pi-tools-suite/src/skill-installer/index.ts +0 -333
  182. package/skills/spec-lite/SKILL.md +0 -140
  183. /package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/references → agents/browser-qa/examples}/qa-auth.example.jsonc +0 -0
  184. /package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/references → agents/browser-qa/examples}/qa-flow.example.jsonc +0 -0
  185. /package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/vendor/fflate.LICENSE +0 -0
  186. /package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/vendor/fflate.mjs +0 -0
@@ -1,7 +1,8 @@
1
- import { readFile, readdir, realpath, stat } from "node:fs/promises";
1
+ import { open, readFile, readdir, realpath, stat } from "node:fs/promises";
2
2
  import { join, resolve } from "node:path";
3
3
  import { SUBAGENT_PARENT_SESSION_FILE, SUBAGENTS_REGISTRY_FILE, SUBAGENTS_RUN_ROOT } from "../constants.js";
4
4
  import { isSubagentRegistry } from "./subagents-model.js";
5
+ const LAST_ACTIVITY_TAIL_BYTES = 64 * 1024;
5
6
  export function subagentsRegistryPath(cwd) {
6
7
  return join(cwd, SUBAGENTS_RUN_ROOT, SUBAGENTS_REGISTRY_FILE);
7
8
  }
@@ -110,6 +111,9 @@ async function readSubagentAgentState(runDir, agentId, options) {
110
111
  const finishedAt = await readTrimmedFile(join(agentDir, "finished_at"));
111
112
  if (finishedAt)
112
113
  state.finishedAt = finishedAt;
114
+ const lastActivity = await readLastActivity(join(agentDir, "progress.jsonl"));
115
+ if (lastActivity)
116
+ state.lastActivity = lastActivity;
113
117
  const retryPending = await fileExists(join(agentDir, "retry_pending"));
114
118
  const stopRequested = await fileExists(join(agentDir, "stop_requested"));
115
119
  if (retryPending && !stopRequested && state.status !== "running" && state.status !== "done") {
@@ -179,6 +183,61 @@ async function readNumberFile(filePath) {
179
183
  const value = Number.parseInt(raw, 10);
180
184
  return Number.isFinite(value) ? value : undefined;
181
185
  }
186
+ async function readLastActivity(filePath) {
187
+ let handle;
188
+ try {
189
+ handle = await open(filePath, "r");
190
+ const size = (await handle.stat()).size;
191
+ if (size <= 0)
192
+ return undefined;
193
+ const start = Math.max(0, size - LAST_ACTIVITY_TAIL_BYTES);
194
+ const buffer = Buffer.allocUnsafe(size - start);
195
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, start);
196
+ if (bytesRead <= 0)
197
+ return undefined;
198
+ const lines = buffer.toString("utf8", 0, bytesRead).split(/\r?\n/);
199
+ if (start > 0) {
200
+ const previousByte = Buffer.allocUnsafe(1);
201
+ const previousRead = await handle.read(previousByte, 0, 1, start - 1);
202
+ if (previousRead.bytesRead === 1 && previousByte[0] !== 0x0a)
203
+ lines.shift();
204
+ }
205
+ for (let index = lines.length - 1; index >= 0; index--) {
206
+ const line = lines[index]?.trim();
207
+ if (!line)
208
+ continue;
209
+ try {
210
+ const value = JSON.parse(line);
211
+ if (!isProgressActivityRecord(value))
212
+ continue;
213
+ const toolName = typeof value.toolName === "string" ? value.toolName.trim() : "";
214
+ if (toolName)
215
+ return { label: toolName, at: value.at };
216
+ if (value.type === "message_start" || value.type === "message_end")
217
+ return { label: "Thinking", at: value.at };
218
+ }
219
+ catch {
220
+ // Ignore malformed or partially written tail lines and keep scanning.
221
+ }
222
+ }
223
+ }
224
+ catch {
225
+ return undefined;
226
+ }
227
+ finally {
228
+ await handle?.close().catch(() => undefined);
229
+ }
230
+ return undefined;
231
+ }
232
+ function isProgressActivityRecord(value) {
233
+ if (typeof value !== "object" || value === null || Array.isArray(value))
234
+ return false;
235
+ const record = value;
236
+ return record.stage === "rpc_event"
237
+ && typeof record.at === "string"
238
+ && record.at.trim().length > 0
239
+ && typeof record.type === "string";
240
+ }
182
241
  async function countFileLines(filePath) {
183
242
  try {
184
243
  const content = await readFile(filePath, "utf8");
@@ -11,7 +11,20 @@ export declare function isSubagentsLiveStateEvent(value: unknown): value is Suba
11
11
  export declare function isSubagentRegistryRun(runId: string, value: unknown): value is SubagentRegistryRun;
12
12
  export declare function isSubagentRegistryAgent(agentId: string, value: unknown): value is SubagentRegistryAgent;
13
13
  export declare function isSubagentRegistry(value: unknown): value is SubagentRegistry;
14
- export declare function subagentStatusIcon(status: SubagentStatus): string;
14
+ /**
15
+ * Agent icon names accepted in sub-agent `icon:` frontmatter (both bundled
16
+ * agents and `.pi/agents/*.md`). Keys mirror APP_ICONS entries and the Pix
17
+ * Desktop lucide mapping (desktop/src/lib/agent-icons.ts); status is conveyed
18
+ * by color, not by the glyph.
19
+ */
20
+ export declare const SUBAGENT_ICON_NAMES: readonly ["agent", "search", "code", "flask", "globe", "sparkles", "brain", "wrench", "terminal", "bug", "book", "eye", "zap", "rocket"];
21
+ export type SubagentIconName = (typeof SUBAGENT_ICON_NAMES)[number];
22
+ export declare function isSubagentIconName(value: string): value is SubagentIconName;
23
+ /**
24
+ * Resolve the per-agent icon glyph from the task preview. Unknown or missing
25
+ * icon names fall back to the neutral agent glyph.
26
+ */
27
+ export declare function subagentIcon(preview: SubagentTaskPreview | undefined): string;
15
28
  export declare function formatSubagentsPanelStats(agents: readonly SubagentAgentState[]): string;
16
29
  export declare function subagentModelThinkingLabel(preview: SubagentTaskPreview | undefined): string;
17
30
  export declare function activeSubagentStates(agents: readonly SubagentAgentState[]): SubagentAgentState[];
@@ -19,5 +32,6 @@ export declare function allSubagentStatesTerminal(agents: readonly SubagentAgent
19
32
  export declare function taskPreviewMap(tasks: readonly SubagentTaskPreview[] | undefined): Map<string, SubagentTaskPreview>;
20
33
  export declare function formatSubagentTimestamp(value: string | undefined): string | undefined;
21
34
  export declare function formatElapsedSince(value: string | undefined, now?: number): string;
35
+ export declare function formatSubagentLastActivity(activity: SubagentAgentState["lastActivity"]): string | undefined;
22
36
  export declare function subagentRunName(runDir: string): string;
23
37
  export declare function resolveSubagentRunDir(cwd: string, runDir: string): string;
@@ -43,6 +43,14 @@ export function isSubagentAgentState(value) {
43
43
  return false;
44
44
  if (value.retryCount !== undefined && typeof value.retryCount !== "number")
45
45
  return false;
46
+ if (value.lastActivity !== undefined) {
47
+ if (!isRecord(value.lastActivity))
48
+ return false;
49
+ if (typeof value.lastActivity.label !== "string" || !value.lastActivity.label.trim())
50
+ return false;
51
+ if (typeof value.lastActivity.at !== "string" || !value.lastActivity.at.trim())
52
+ return false;
53
+ }
46
54
  return true;
47
55
  }
48
56
  export function isSubagentTaskPreview(value) {
@@ -60,6 +68,8 @@ export function isSubagentTaskPreview(value) {
60
68
  return false;
61
69
  if (value.thinkingLevel !== undefined && typeof value.thinkingLevel !== "string")
62
70
  return false;
71
+ if (value.icon !== undefined && typeof value.icon !== "string")
72
+ return false;
63
73
  return true;
64
74
  }
65
75
  export function isSubagentRunRenderDetails(value) {
@@ -148,21 +158,38 @@ export function isSubagentRegistry(value) {
148
158
  return Object.entries(value.runs).every(([runId, run]) => isSubagentRegistryRun(runId, run))
149
159
  && Object.entries(value.agents).every(([agentId, agent]) => isSubagentRegistryAgent(agentId, agent));
150
160
  }
151
- export function subagentStatusIcon(status) {
152
- switch (status) {
153
- case "planned":
154
- return APP_ICONS.circleOutline;
155
- case "running":
156
- return APP_ICONS.timerSand;
157
- case "retrying":
158
- return APP_ICONS.refresh;
159
- case "done":
160
- return APP_ICONS.checkCircle;
161
- case "failed":
162
- return APP_ICONS.closeCircle;
163
- case "stopped":
164
- return APP_ICONS.stopCircle;
165
- }
161
+ /**
162
+ * Agent icon names accepted in sub-agent `icon:` frontmatter (both bundled
163
+ * agents and `.pi/agents/*.md`). Keys mirror APP_ICONS entries and the Pix
164
+ * Desktop lucide mapping (desktop/src/lib/agent-icons.ts); status is conveyed
165
+ * by color, not by the glyph.
166
+ */
167
+ export const SUBAGENT_ICON_NAMES = [
168
+ "agent",
169
+ "search",
170
+ "code",
171
+ "flask",
172
+ "globe",
173
+ "sparkles",
174
+ "brain",
175
+ "wrench",
176
+ "terminal",
177
+ "bug",
178
+ "book",
179
+ "eye",
180
+ "zap",
181
+ "rocket",
182
+ ];
183
+ export function isSubagentIconName(value) {
184
+ return SUBAGENT_ICON_NAMES.includes(value);
185
+ }
186
+ /**
187
+ * Resolve the per-agent icon glyph from the task preview. Unknown or missing
188
+ * icon names fall back to the neutral agent glyph.
189
+ */
190
+ export function subagentIcon(preview) {
191
+ const name = preview?.icon?.trim();
192
+ return name && isSubagentIconName(name) ? APP_ICONS[name] : APP_ICONS.agent;
166
193
  }
167
194
  export function formatSubagentsPanelStats(agents) {
168
195
  const stats = [
@@ -200,11 +227,19 @@ export function formatSubagentTimestamp(value) {
200
227
  return new Date(time).toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit", second: "2-digit" });
201
228
  }
202
229
  export function formatElapsedSince(value, now = Date.now()) {
230
+ return formatDurationSince(value, now) ?? "elapsed:—";
231
+ }
232
+ export function formatSubagentLastActivity(activity) {
233
+ if (!activity)
234
+ return undefined;
235
+ return activity.label.trim() || undefined;
236
+ }
237
+ function formatDurationSince(value, now) {
203
238
  if (!value)
204
- return "elapsed:—";
239
+ return undefined;
205
240
  const started = Date.parse(value);
206
241
  if (!Number.isFinite(started))
207
- return "elapsed:—";
242
+ return undefined;
208
243
  const seconds = Math.max(0, Math.floor((now - started) / 1000));
209
244
  if (seconds < 60)
210
245
  return `${seconds}s`;
@@ -139,6 +139,10 @@ export type SubagentStatus = (typeof SUBAGENT_STATUSES)[number];
139
139
  export type SubagentActiveStatus = (typeof SUBAGENT_ACTIVE_STATUSES)[number];
140
140
  export type SubagentTerminalStatus = (typeof SUBAGENT_TERMINAL_STATUSES)[number];
141
141
  export type SubagentRenderMode = (typeof SUBAGENT_RENDER_MODES)[number];
142
+ export type SubagentActivity = {
143
+ label: string;
144
+ at: string;
145
+ };
142
146
  export type SubagentAgentState = {
143
147
  id: string;
144
148
  status: SubagentStatus;
@@ -151,6 +155,7 @@ export type SubagentAgentState = {
151
155
  stderrLines?: number;
152
156
  eventLines?: number;
153
157
  retryCount?: number;
158
+ lastActivity?: SubagentActivity;
154
159
  };
155
160
  export type SubagentTaskPreview = {
156
161
  id: string;
@@ -159,6 +164,8 @@ export type SubagentTaskPreview = {
159
164
  model?: string;
160
165
  thinking?: string;
161
166
  thinkingLevel?: string;
167
+ /** Agent icon name from the subagentType profile; resolved via APP_ICONS. */
168
+ icon?: string;
162
169
  };
163
170
  export type SubagentRunRenderDetails = {
164
171
  runDir: string;
@@ -4,7 +4,7 @@ import { dirname, join, parse, resolve } from "node:path";
4
4
  import { parse as parseJsonc } from "jsonc-parser";
5
5
  const DEFAULT_CONFIG = {
6
6
  enabled: true,
7
- model: "zai/glm-4.5-air",
7
+ model: "zai/glm-5-turbo",
8
8
  fallbackModels: [],
9
9
  maxInputChars: 2000,
10
10
  maxTitleChars: 80,
@@ -6,6 +6,16 @@ export const DEFAULT_PIX_CONFIG_JSONC = String.raw `{
6
6
  "ignoreContextFiles": false,
7
7
  // Maximum pi session JSONL files to retain per project. 0 disables automatic deletion.
8
8
  "maxProjectSessions": 0,
9
+ "desktop": {
10
+ // External editor used by Pix Desktop's Project explorer: zed, code/vscode, cursor, subl, idea, webstorm, or an executable path/name.
11
+ "externalEditor": "zed",
12
+ "git": {
13
+ // LLM used for Source Control code review.
14
+ "reviewModelRef": "openai-codex/gpt-5.6-luna:medium",
15
+ // LLM used to generate commit messages from staged changes.
16
+ "commitMessageModelRef": "openai-codex/gpt-5.6-luna:minimal"
17
+ }
18
+ },
9
19
 
10
20
  "toolRenderer": {
11
21
  "default": { "previewLines": 0, "direction": "head", "color": "toolTitle" },
@@ -944,23 +944,41 @@ export function stripDcpControlMetadata(text) {
944
944
  return text;
945
945
  const lines = text.split("\n");
946
946
  const kept = [];
947
- let inMessageIds = false;
947
+ let candidate;
948
+ let inFence;
948
949
  let touched = false;
949
950
  for (const line of lines) {
950
- if (inMessageIds) {
951
- touched = true;
952
- if (/<\/dcp-message-ids>\s*$/i.test(line))
953
- inMessageIds = false;
951
+ if (candidate) {
952
+ candidate.push(line);
953
+ if (/<\/dcp-message-ids>\s*$/i.test(line)) {
954
+ candidate = undefined;
955
+ touched = true;
956
+ }
954
957
  continue;
955
958
  }
956
- if (/^\s*<dcp-message-ids>/i.test(line)) {
957
- touched = true;
958
- if (!/<\/dcp-message-ids>\s*$/i.test(line))
959
- inMessageIds = true;
959
+ const quoteLine = /^\s{0,3}>/.test(line);
960
+ if (!quoteLine) {
961
+ const fence = markdownFence(line);
962
+ if (fence) {
963
+ if (!inFence)
964
+ inFence = { marker: fence.marker, length: fence.length };
965
+ else if (fence.marker === inFence.marker && fence.length >= inFence.length)
966
+ inFence = undefined;
967
+ }
968
+ }
969
+ if (!inFence && !quoteLine && /^\s*<dcp-message-ids>/i.test(line)) {
970
+ if (/<\/dcp-message-ids>\s*$/i.test(line)) {
971
+ touched = true;
972
+ }
973
+ else {
974
+ candidate = [line];
975
+ }
960
976
  continue;
961
977
  }
962
978
  kept.push(line);
963
979
  }
980
+ if (candidate)
981
+ kept.push(...candidate);
964
982
  return touched ? kept.join("\n").trimEnd() : text;
965
983
  }
966
984
  function isHiddenMarkdownMetadataLine(line) {
@@ -3,3 +3,4 @@
3
3
  */
4
4
  export { PixConfigSchema } from "./pix-schema.js";
5
5
  export { PiToolsSuiteConfigSchema } from "./pi-tools-suite-schema.js";
6
+ export { ProjectTasksSchema } from "./tasks-schema.js";
@@ -3,3 +3,4 @@
3
3
  */
4
4
  export { PixConfigSchema } from "./pix-schema.js";
5
5
  export { PiToolsSuiteConfigSchema } from "./pi-tools-suite-schema.js";
6
+ export { ProjectTasksSchema } from "./tasks-schema.js";
@@ -21,6 +21,10 @@ export declare const PiToolsSuiteConfigSchema: Type.TObject<{
21
21
  chatId: Type.TOptional<Type.TString>;
22
22
  }>>;
23
23
  }>>;
24
+ commentChecker: Type.TOptional<Type.TObject<{
25
+ enabled: Type.TOptional<Type.TBoolean>;
26
+ strictness: Type.TOptional<Type.TUnion<[Type.TLiteral<"conservative">, Type.TLiteral<"balanced">, Type.TLiteral<"aggressive">]>>;
27
+ }>>;
24
28
  dcp: Type.TOptional<Type.TObject<{
25
29
  enabled: Type.TOptional<Type.TBoolean>;
26
30
  debug: Type.TOptional<Type.TBoolean>;
@@ -30,13 +34,13 @@ export declare const PiToolsSuiteConfigSchema: Type.TObject<{
30
34
  }>>;
31
35
  manualMode: Type.TOptional<Type.TObject<{
32
36
  enabled: Type.TOptional<Type.TBoolean>;
33
- automaticStrategies: Type.TOptional<Type.TBoolean>;
37
+ automaticStrategies: Type.TOptional<Type.TNever>;
34
38
  }>>;
35
39
  compress: Type.TOptional<Type.TObject<{
36
40
  maxContextPercent: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TString]>>;
37
41
  minContextPercent: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TString]>>;
38
- modelMaxContextPercent: Type.TOptional<Type.TRecord<"^.*$", Type.TNumber>>;
39
- modelMinContextPercent: Type.TOptional<Type.TRecord<"^.*$", Type.TNumber>>;
42
+ modelMaxContextPercent: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TNumber, Type.TString]>>>;
43
+ modelMinContextPercent: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TNumber, Type.TString]>>>;
40
44
  maxContextLimit: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TString]>>;
41
45
  minContextLimit: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TString]>>;
42
46
  modelMaxContextLimits: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TNumber, Type.TString]>>>;
@@ -63,85 +67,97 @@ export declare const PiToolsSuiteConfigSchema: Type.TObject<{
63
67
  highTokens: Type.TOptional<Type.TNumber>;
64
68
  maxSuggestions: Type.TOptional<Type.TNumber>;
65
69
  }>>;
66
- }>>;
67
- strategies: Type.TOptional<Type.TObject<{
68
- deduplication: Type.TOptional<Type.TObject<{
69
- enabled: Type.TOptional<Type.TBoolean>;
70
- protectedTools: Type.TOptional<Type.TArray<Type.TString>>;
71
- }>>;
72
- purgeErrors: Type.TOptional<Type.TObject<{
70
+ autoCompress: Type.TOptional<Type.TObject<{
73
71
  enabled: Type.TOptional<Type.TBoolean>;
74
- turns: Type.TOptional<Type.TNumber>;
75
- protectedTools: Type.TOptional<Type.TArray<Type.TString>>;
72
+ patience: Type.TOptional<Type.TNumber>;
73
+ summarizerModel: Type.TOptional<Type.TArray<Type.TString>>;
74
+ timeoutMs: Type.TOptional<Type.TNumber>;
76
75
  }>>;
77
- autoToolPruning: Type.TOptional<Type.TObject<{
76
+ }>>;
77
+ strategies: Type.TOptional<Type.TObject<{
78
+ emergencyCurrentTurnPruning: Type.TOptional<Type.TObject<{
78
79
  enabled: Type.TOptional<Type.TBoolean>;
79
- maxOutputTokens: Type.TOptional<Type.TNumber>;
80
- keepRecentTurns: Type.TOptional<Type.TNumber>;
81
- readLikeTools: Type.TOptional<Type.TArray<Type.TString>>;
82
- readLikeTurns: Type.TOptional<Type.TNumber>;
80
+ hardContextPercent: Type.TOptional<Type.TNumber>;
81
+ targetContextPercent: Type.TOptional<Type.TNumber>;
82
+ patience: Type.TOptional<Type.TNumber>;
83
+ keepRecentToolPairs: Type.TOptional<Type.TNumber>;
84
+ minOutputTokens: Type.TOptional<Type.TNumber>;
85
+ maxSuggestions: Type.TOptional<Type.TNumber>;
83
86
  protectedTools: Type.TOptional<Type.TArray<Type.TString>>;
84
87
  }>>;
88
+ deduplication: Type.TOptional<Type.TNever>;
89
+ purgeErrors: Type.TOptional<Type.TNever>;
90
+ autoToolPruning: Type.TOptional<Type.TNever>;
85
91
  }>>;
86
92
  protectedFilePatterns: Type.TOptional<Type.TArray<Type.TString>>;
87
- pruneNotification: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"detailed">]>>;
88
- }>>;
89
- asyncSubagents: Type.TOptional<Type.TObject<{
90
- defaultType: Type.TOptional<Type.TString>;
91
- routing: Type.TOptional<Type.TObject<{
93
+ modelOverrides: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
92
94
  enabled: Type.TOptional<Type.TBoolean>;
93
- model: Type.TOptional<Type.TString>;
94
- fallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
95
- maxTaskChars: Type.TOptional<Type.TNumber>;
96
- maxTokens: Type.TOptional<Type.TNumber>;
97
- maxRetries: Type.TOptional<Type.TNumber>;
98
- timeoutMs: Type.TOptional<Type.TNumber>;
99
95
  debug: Type.TOptional<Type.TBoolean>;
100
- }>>;
101
- vision: Type.TOptional<Type.TObject<{
102
- blindModelPatterns: Type.TOptional<Type.TArray<Type.TString>>;
103
- }>>;
104
- presets: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
105
- description: Type.TOptional<Type.TString>;
106
- model: Type.TOptional<Type.TString>;
107
- fallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
108
- thinking: Type.TOptional<Type.TString>;
109
- extraArgs: Type.TOptional<Type.TArray<Type.TString>>;
110
- timeoutMs: Type.TOptional<Type.TNumber>;
111
- types: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
112
- model: Type.TOptional<Type.TString>;
113
- fallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
114
- thinking: Type.TOptional<Type.TString>;
115
- extraArgs: Type.TOptional<Type.TArray<Type.TString>>;
116
- timeoutMs: Type.TOptional<Type.TNumber>;
117
- }>>>;
118
- }>>>;
119
- types: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
120
- description: Type.TOptional<Type.TString>;
121
- model: Type.TOptional<Type.TString>;
122
- fallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
123
- thinking: Type.TOptional<Type.TString>;
124
- tools: Type.TOptional<Type.TArray<Type.TString>>;
125
- isolatedSkills: Type.TOptional<Type.TArray<Type.TString>>;
126
- extraArgs: Type.TOptional<Type.TArray<Type.TString>>;
127
- promptAppend: Type.TOptional<Type.TString>;
128
- promptOverride: Type.TOptional<Type.TString>;
129
- retry: Type.TOptional<Type.TObject<{
130
- maxRetries: Type.TOptional<Type.TNumber>;
131
- backoffMs: Type.TOptional<Type.TNumber>;
132
- retryableExitCodes: Type.TOptional<Type.TArray<Type.TNumber>>;
96
+ debugLog: Type.TOptional<Type.TObject<{
97
+ maxBytes: Type.TOptional<Type.TNumber>;
98
+ maxBackups: Type.TOptional<Type.TNumber>;
99
+ }>>;
100
+ manualMode: Type.TOptional<Type.TObject<{
101
+ enabled: Type.TOptional<Type.TBoolean>;
102
+ automaticStrategies: Type.TOptional<Type.TNever>;
133
103
  }>>;
134
- maxResultBytes: Type.TOptional<Type.TNumber>;
135
- timeoutMs: Type.TOptional<Type.TNumber>;
104
+ compress: Type.TOptional<Type.TObject<{
105
+ maxContextPercent: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TString]>>;
106
+ minContextPercent: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TString]>>;
107
+ modelMaxContextPercent: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TNumber, Type.TString]>>>;
108
+ modelMinContextPercent: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TNumber, Type.TString]>>>;
109
+ maxContextLimit: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TString]>>;
110
+ minContextLimit: Type.TOptional<Type.TUnion<[Type.TNumber, Type.TString]>>;
111
+ modelMaxContextLimits: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TNumber, Type.TString]>>>;
112
+ modelMinContextLimits: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TNumber, Type.TString]>>>;
113
+ summaryBuffer: Type.TOptional<Type.TBoolean>;
114
+ nudgeFrequency: Type.TOptional<Type.TNumber>;
115
+ iterationNudgeThreshold: Type.TOptional<Type.TNumber>;
116
+ nudgeForce: Type.TOptional<Type.TUnion<[Type.TLiteral<"strong">, Type.TLiteral<"soft">]>>;
117
+ protectedTools: Type.TOptional<Type.TArray<Type.TString>>;
118
+ protectTags: Type.TOptional<Type.TBoolean>;
119
+ protectUserMessages: Type.TOptional<Type.TBoolean>;
120
+ autoCandidates: Type.TOptional<Type.TObject<{
121
+ enabled: Type.TOptional<Type.TBoolean>;
122
+ minContextPercent: Type.TOptional<Type.TNumber>;
123
+ keepRecentTurns: Type.TOptional<Type.TNumber>;
124
+ minMessages: Type.TOptional<Type.TNumber>;
125
+ minTokens: Type.TOptional<Type.TNumber>;
126
+ }>>;
127
+ messageMode: Type.TOptional<Type.TObject<{
128
+ enabled: Type.TOptional<Type.TBoolean>;
129
+ minContextPercent: Type.TOptional<Type.TNumber>;
130
+ keepRecentTurns: Type.TOptional<Type.TNumber>;
131
+ mediumTokens: Type.TOptional<Type.TNumber>;
132
+ highTokens: Type.TOptional<Type.TNumber>;
133
+ maxSuggestions: Type.TOptional<Type.TNumber>;
134
+ }>>;
135
+ autoCompress: Type.TOptional<Type.TObject<{
136
+ enabled: Type.TOptional<Type.TBoolean>;
137
+ patience: Type.TOptional<Type.TNumber>;
138
+ summarizerModel: Type.TOptional<Type.TArray<Type.TString>>;
139
+ timeoutMs: Type.TOptional<Type.TNumber>;
140
+ }>>;
141
+ }>>;
142
+ strategies: Type.TOptional<Type.TObject<{
143
+ emergencyCurrentTurnPruning: Type.TOptional<Type.TObject<{
144
+ enabled: Type.TOptional<Type.TBoolean>;
145
+ hardContextPercent: Type.TOptional<Type.TNumber>;
146
+ targetContextPercent: Type.TOptional<Type.TNumber>;
147
+ patience: Type.TOptional<Type.TNumber>;
148
+ keepRecentToolPairs: Type.TOptional<Type.TNumber>;
149
+ minOutputTokens: Type.TOptional<Type.TNumber>;
150
+ maxSuggestions: Type.TOptional<Type.TNumber>;
151
+ protectedTools: Type.TOptional<Type.TArray<Type.TString>>;
152
+ }>>;
153
+ deduplication: Type.TOptional<Type.TNever>;
154
+ purgeErrors: Type.TOptional<Type.TNever>;
155
+ autoToolPruning: Type.TOptional<Type.TNever>;
156
+ }>>;
157
+ protectedFilePatterns: Type.TOptional<Type.TArray<Type.TString>>;
158
+ pruneNotification: Type.TOptional<Type.TNever>;
136
159
  }>>>;
137
- maxConcurrent: Type.TOptional<Type.TNumber>;
138
- retry: Type.TOptional<Type.TObject<{
139
- maxRetries: Type.TOptional<Type.TNumber>;
140
- backoffMs: Type.TOptional<Type.TNumber>;
141
- retryableExitCodes: Type.TOptional<Type.TArray<Type.TNumber>>;
142
- }>>;
143
- maxResultBytes: Type.TOptional<Type.TNumber>;
144
- timeoutMs: Type.TOptional<Type.TNumber>;
160
+ pruneNotification: Type.TOptional<Type.TNever>;
145
161
  }>>;
146
162
  toolRenderer: Type.TOptional<Type.TObject<{
147
163
  default: Type.TOptional<Type.TObject<{
@@ -171,6 +187,24 @@ export declare const PiToolsSuiteConfigSchema: Type.TObject<{
171
187
  sessionHygiene: Type.TOptional<Type.TBoolean>;
172
188
  notify: Type.TOptional<Type.TBoolean>;
173
189
  }>>;
190
+ contextGateway: Type.TOptional<Type.TObject<{
191
+ mode: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"observe">, Type.TLiteral<"enforce">]>>;
192
+ budgets: Type.TOptional<Type.TObject<{
193
+ maxInlineBytes: Type.TOptional<Type.TInteger>;
194
+ maxResultBytes: Type.TOptional<Type.TInteger>;
195
+ maxExactReadBytes: Type.TOptional<Type.TInteger>;
196
+ maxSearchBytes: Type.TOptional<Type.TInteger>;
197
+ maxSearchMatches: Type.TOptional<Type.TInteger>;
198
+ }>>;
199
+ }>>;
200
+ repoDiscovery: Type.TOptional<Type.TObject<{
201
+ profile: Type.TOptional<Type.TUnion<[Type.TLiteral<"baseline">, Type.TLiteral<"native-compact">]>>;
202
+ }>>;
203
+ resourceRegistry: Type.TOptional<Type.TObject<{
204
+ remote: Type.TOptional<Type.TString>;
205
+ branch: Type.TOptional<Type.TString>;
206
+ projectKey: Type.TOptional<Type.TString>;
207
+ }>>;
174
208
  lsp: Type.TOptional<Type.TObject<{
175
209
  servers: Type.TOptional<Type.TArray<Type.TObject<{
176
210
  id: Type.TString;
@@ -193,5 +227,6 @@ export declare const PiToolsSuiteConfigSchema: Type.TObject<{
193
227
  settings: Type.TOptional<Type.TUnknown>;
194
228
  }>>>;
195
229
  }>>;
230
+ asyncSubagents: Type.TOptional<Type.TNever>;
196
231
  }>;
197
232
  export type PiToolsSuiteConfigSchemaType = Static<typeof PiToolsSuiteConfigSchema>;