@oh-my-pi/pi-coding-agent 14.9.9 → 15.0.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.
Files changed (230) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/examples/extensions/plan-mode.ts +0 -1
  3. package/package.json +9 -9
  4. package/scripts/build-binary.ts +5 -0
  5. package/scripts/format-prompts.ts +1 -1
  6. package/src/autoresearch/helpers.ts +17 -0
  7. package/src/autoresearch/tools/log-experiment.ts +9 -17
  8. package/src/autoresearch/tools/run-experiment.ts +2 -17
  9. package/src/capability/skill.ts +7 -0
  10. package/src/cli/args.ts +2 -2
  11. package/src/cli/list-models.ts +1 -1
  12. package/src/cli/shell-cli.ts +3 -13
  13. package/src/cli/update-cli.ts +1 -1
  14. package/src/cli.ts +11 -29
  15. package/src/commands/acp.ts +24 -0
  16. package/src/commands/launch.ts +6 -4
  17. package/src/commit/agentic/prompts/system.md +1 -1
  18. package/src/commit/agentic/tools/propose-changelog.ts +8 -1
  19. package/src/commit/analysis/conventional.ts +8 -66
  20. package/src/commit/map-reduce/reduce-phase.ts +6 -65
  21. package/src/commit/pipeline.ts +2 -2
  22. package/src/commit/shared-llm.ts +89 -0
  23. package/src/config/config-file.ts +210 -0
  24. package/src/config/model-equivalence.ts +8 -11
  25. package/src/config/model-registry.ts +13 -2
  26. package/src/config/model-resolver.ts +31 -4
  27. package/src/config/settings-schema.ts +102 -1
  28. package/src/config/settings.ts +1 -1
  29. package/src/config.ts +3 -219
  30. package/src/edit/index.ts +22 -1
  31. package/src/edit/modes/patch.ts +10 -0
  32. package/src/edit/modes/replace.ts +3 -0
  33. package/src/edit/renderer.ts +17 -1
  34. package/src/eval/js/context-manager.ts +1 -1
  35. package/src/eval/js/executor.ts +3 -0
  36. package/src/eval/js/shared/rewrite-imports.ts +122 -50
  37. package/src/eval/js/shared/runtime.ts +31 -4
  38. package/src/eval/js/tool-bridge.ts +43 -21
  39. package/src/eval/py/executor.ts +5 -0
  40. package/src/exa/factory.ts +2 -2
  41. package/src/exa/mcp-client.ts +74 -1
  42. package/src/exec/bash-executor.ts +5 -1
  43. package/src/export/html/template.generated.ts +1 -1
  44. package/src/export/html/template.js +0 -11
  45. package/src/extensibility/extensions/runner.ts +55 -2
  46. package/src/extensibility/extensions/types.ts +98 -221
  47. package/src/extensibility/hooks/types.ts +89 -314
  48. package/src/extensibility/shared-events.ts +343 -0
  49. package/src/extensibility/skills.ts +42 -1
  50. package/src/goals/index.ts +3 -0
  51. package/src/goals/runtime.ts +500 -0
  52. package/src/goals/state.ts +37 -0
  53. package/src/goals/tools/goal-tool.ts +237 -0
  54. package/src/hashline/anchors.ts +2 -2
  55. package/src/hindsight/mental-models.ts +1 -1
  56. package/src/internal-urls/agent-protocol.ts +1 -20
  57. package/src/internal-urls/artifact-protocol.ts +1 -19
  58. package/src/internal-urls/docs-index.generated.ts +9 -10
  59. package/src/internal-urls/index.ts +1 -0
  60. package/src/internal-urls/issue-pr-protocol.ts +577 -0
  61. package/src/internal-urls/registry-helpers.ts +25 -0
  62. package/src/internal-urls/router.ts +6 -3
  63. package/src/internal-urls/types.ts +22 -1
  64. package/src/main.ts +24 -11
  65. package/src/mcp/oauth-flow.ts +20 -0
  66. package/src/modes/acp/acp-agent.ts +412 -71
  67. package/src/modes/acp/acp-client-bridge.ts +152 -0
  68. package/src/modes/acp/acp-event-mapper.ts +180 -15
  69. package/src/modes/acp/terminal-auth.ts +37 -0
  70. package/src/modes/components/assistant-message.ts +14 -8
  71. package/src/modes/components/bash-execution.ts +24 -63
  72. package/src/modes/components/custom-message.ts +14 -40
  73. package/src/modes/components/eval-execution.ts +27 -57
  74. package/src/modes/components/execution-shared.ts +102 -0
  75. package/src/modes/components/hook-message.ts +17 -49
  76. package/src/modes/components/mcp-add-wizard.ts +26 -5
  77. package/src/modes/components/message-frame.ts +88 -0
  78. package/src/modes/components/model-selector.ts +1 -1
  79. package/src/modes/components/read-tool-group.ts +29 -1
  80. package/src/modes/components/session-observer-overlay.ts +6 -2
  81. package/src/modes/components/session-selector.ts +1 -1
  82. package/src/modes/components/status-line/segments.ts +55 -4
  83. package/src/modes/components/status-line/types.ts +4 -0
  84. package/src/modes/components/status-line.ts +28 -10
  85. package/src/modes/components/tool-execution.ts +7 -8
  86. package/src/modes/controllers/command-controller-shared.ts +108 -0
  87. package/src/modes/controllers/command-controller.ts +27 -10
  88. package/src/modes/controllers/event-controller.ts +60 -18
  89. package/src/modes/controllers/extension-ui-controller.ts +8 -2
  90. package/src/modes/controllers/input-controller.ts +85 -39
  91. package/src/modes/controllers/mcp-command-controller.ts +56 -61
  92. package/src/modes/controllers/ssh-command-controller.ts +18 -57
  93. package/src/modes/interactive-mode.ts +675 -39
  94. package/src/modes/print-mode.ts +16 -86
  95. package/src/modes/rpc/rpc-mode.ts +30 -88
  96. package/src/modes/runtime-init.ts +115 -0
  97. package/src/modes/theme/defaults/dark-poimandres.json +2 -0
  98. package/src/modes/theme/defaults/light-poimandres.json +2 -0
  99. package/src/modes/theme/theme.ts +18 -6
  100. package/src/modes/types.ts +20 -5
  101. package/src/modes/utils/context-usage.ts +13 -13
  102. package/src/modes/utils/ui-helpers.ts +25 -6
  103. package/src/plan-mode/approved-plan.ts +35 -1
  104. package/src/prompts/agents/designer.md +5 -5
  105. package/src/prompts/agents/explore.md +7 -7
  106. package/src/prompts/agents/init.md +9 -9
  107. package/src/prompts/agents/librarian.md +14 -14
  108. package/src/prompts/agents/plan.md +4 -4
  109. package/src/prompts/agents/reviewer.md +5 -5
  110. package/src/prompts/agents/task.md +10 -10
  111. package/src/prompts/commands/orchestrate.md +2 -2
  112. package/src/prompts/compaction/branch-summary.md +3 -3
  113. package/src/prompts/compaction/compaction-short-summary.md +7 -7
  114. package/src/prompts/compaction/compaction-summary-context.md +1 -1
  115. package/src/prompts/compaction/compaction-summary.md +5 -5
  116. package/src/prompts/compaction/compaction-turn-prefix.md +3 -3
  117. package/src/prompts/compaction/compaction-update-summary.md +11 -11
  118. package/src/prompts/goals/goal-budget-limit.md +16 -0
  119. package/src/prompts/goals/goal-continuation.md +28 -0
  120. package/src/prompts/goals/goal-mode-active.md +23 -0
  121. package/src/prompts/memories/consolidation.md +2 -2
  122. package/src/prompts/memories/read-path.md +1 -1
  123. package/src/prompts/memories/stage_one_input.md +1 -1
  124. package/src/prompts/memories/stage_one_system.md +5 -5
  125. package/src/prompts/review-request.md +4 -4
  126. package/src/prompts/system/agent-creation-architect.md +17 -17
  127. package/src/prompts/system/agent-creation-user.md +2 -2
  128. package/src/prompts/system/commit-message-system.md +2 -2
  129. package/src/prompts/system/custom-system-prompt.md +2 -2
  130. package/src/prompts/system/eager-todo.md +6 -6
  131. package/src/prompts/system/handoff-document.md +1 -1
  132. package/src/prompts/system/plan-mode-active.md +25 -24
  133. package/src/prompts/system/plan-mode-approved.md +4 -4
  134. package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
  135. package/src/prompts/system/plan-mode-reference.md +2 -2
  136. package/src/prompts/system/plan-mode-subagent.md +8 -8
  137. package/src/prompts/system/plan-mode-tool-decision-reminder.md +3 -3
  138. package/src/prompts/system/project-prompt.md +4 -4
  139. package/src/prompts/system/subagent-system-prompt.md +7 -7
  140. package/src/prompts/system/subagent-yield-reminder.md +4 -4
  141. package/src/prompts/system/system-prompt.md +72 -71
  142. package/src/prompts/system/ttsr-interrupt.md +1 -1
  143. package/src/prompts/tools/apply-patch.md +1 -1
  144. package/src/prompts/tools/ast-edit.md +3 -3
  145. package/src/prompts/tools/ast-grep.md +3 -3
  146. package/src/prompts/tools/bash.md +6 -0
  147. package/src/prompts/tools/browser.md +3 -3
  148. package/src/prompts/tools/checkpoint.md +3 -3
  149. package/src/prompts/tools/find.md +3 -3
  150. package/src/prompts/tools/github.md +2 -5
  151. package/src/prompts/tools/goal.md +13 -0
  152. package/src/prompts/tools/hashline.md +104 -116
  153. package/src/prompts/tools/image-gen.md +3 -3
  154. package/src/prompts/tools/irc.md +1 -1
  155. package/src/prompts/tools/lsp.md +2 -2
  156. package/src/prompts/tools/patch.md +6 -6
  157. package/src/prompts/tools/read.md +8 -7
  158. package/src/prompts/tools/replace.md +5 -5
  159. package/src/prompts/tools/resolve.md +6 -5
  160. package/src/prompts/tools/retain.md +1 -1
  161. package/src/prompts/tools/rewind.md +2 -2
  162. package/src/prompts/tools/search.md +2 -2
  163. package/src/prompts/tools/ssh.md +2 -2
  164. package/src/prompts/tools/task.md +12 -6
  165. package/src/prompts/tools/web-search.md +2 -2
  166. package/src/prompts/tools/write.md +3 -3
  167. package/src/sdk.ts +81 -17
  168. package/src/session/agent-session.ts +656 -125
  169. package/src/session/blob-store.ts +36 -3
  170. package/src/session/client-bridge.ts +81 -0
  171. package/src/session/compaction/errors.ts +31 -0
  172. package/src/session/compaction/index.ts +1 -0
  173. package/src/session/messages.ts +67 -2
  174. package/src/session/session-manager.ts +131 -12
  175. package/src/session/session-storage.ts +33 -15
  176. package/src/session/streaming-output.ts +309 -13
  177. package/src/slash-commands/acp-builtins.ts +46 -0
  178. package/src/slash-commands/builtin-registry.ts +717 -116
  179. package/src/slash-commands/helpers/context-report.ts +39 -0
  180. package/src/slash-commands/helpers/format.ts +23 -0
  181. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  182. package/src/slash-commands/helpers/mcp.ts +532 -0
  183. package/src/slash-commands/helpers/parse.ts +85 -0
  184. package/src/slash-commands/helpers/ssh.ts +193 -0
  185. package/src/slash-commands/helpers/todo.ts +279 -0
  186. package/src/slash-commands/helpers/usage-report.ts +91 -0
  187. package/src/slash-commands/types.ts +126 -0
  188. package/src/ssh/ssh-executor.ts +5 -0
  189. package/src/system-prompt.ts +4 -2
  190. package/src/task/executor.ts +27 -10
  191. package/src/task/index.ts +20 -1
  192. package/src/task/render.ts +27 -18
  193. package/src/task/types.ts +4 -0
  194. package/src/tools/ast-edit.ts +21 -120
  195. package/src/tools/ast-grep.ts +21 -119
  196. package/src/tools/bash-interactive.ts +9 -1
  197. package/src/tools/bash.ts +203 -6
  198. package/src/tools/browser/attach.ts +3 -3
  199. package/src/tools/browser/launch.ts +81 -18
  200. package/src/tools/browser/registry.ts +1 -5
  201. package/src/tools/browser/tab-supervisor.ts +51 -14
  202. package/src/tools/conflict-detect.ts +21 -10
  203. package/src/tools/eval.ts +3 -1
  204. package/src/tools/fetch.ts +15 -4
  205. package/src/tools/find.ts +39 -39
  206. package/src/tools/gh-renderer.ts +0 -12
  207. package/src/tools/gh.ts +689 -182
  208. package/src/tools/github-cache.ts +548 -0
  209. package/src/tools/index.ts +25 -11
  210. package/src/tools/inspect-image.ts +3 -10
  211. package/src/tools/output-meta.ts +176 -37
  212. package/src/tools/path-utils.ts +125 -2
  213. package/src/tools/read.ts +605 -239
  214. package/src/tools/render-utils.ts +92 -0
  215. package/src/tools/renderers.ts +2 -0
  216. package/src/tools/resolve.ts +72 -44
  217. package/src/tools/search.ts +120 -186
  218. package/src/tools/write.ts +67 -10
  219. package/src/tui/code-cell.ts +70 -2
  220. package/src/utils/file-mentions.ts +1 -1
  221. package/src/utils/image-loading.ts +7 -3
  222. package/src/utils/image-resize.ts +32 -43
  223. package/src/vim/parser.ts +0 -17
  224. package/src/vim/render.ts +1 -1
  225. package/src/vim/types.ts +1 -1
  226. package/src/web/search/providers/gemini.ts +35 -95
  227. package/src/prompts/tools/exit-plan-mode.md +0 -6
  228. package/src/tools/exit-plan-mode.ts +0 -97
  229. package/src/utils/fuzzy.ts +0 -108
  230. package/src/utils/image-convert.ts +0 -27
@@ -0,0 +1,237 @@
1
+ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
+ import type { Component } from "@oh-my-pi/pi-tui";
3
+ import { Text } from "@oh-my-pi/pi-tui";
4
+ import { formatNumber, prompt } from "@oh-my-pi/pi-utils";
5
+ import { type Static, Type } from "@sinclair/typebox";
6
+ import type { RenderResultOptions } from "../../extensibility/custom-tools/types";
7
+ import type { Theme, ThemeColor } from "../../modes/theme/theme";
8
+ import goalDescription from "../../prompts/tools/goal.md" with { type: "text" };
9
+ import { formatDuration } from "../../slash-commands/helpers/format";
10
+ import type { ToolSession } from "../../tools";
11
+ import { formatErrorMessage, TRUNCATE_LENGTHS } from "../../tools/render-utils";
12
+ import { ToolError } from "../../tools/tool-errors";
13
+ import { renderStatusLine, truncateToWidth } from "../../tui";
14
+ import { completionBudgetReport, remainingTokens } from "../runtime";
15
+ import type { Goal, GoalStatus, GoalToolDetails } from "../state";
16
+
17
+ const goalSchema = Type.Object({
18
+ op: Type.Union([Type.Literal("create"), Type.Literal("get"), Type.Literal("complete")], {
19
+ description: "Goal operation.",
20
+ }),
21
+ objective: Type.Optional(Type.String({ description: "Goal objective. Required when op=create." })),
22
+ token_budget: Type.Optional(
23
+ Type.Integer({
24
+ description: "Optional positive token budget. Only honored when op=create.",
25
+ }),
26
+ ),
27
+ });
28
+
29
+ export type GoalToolInput = Static<typeof goalSchema>;
30
+
31
+ export interface GoalToolResponse {
32
+ goal: Goal | null;
33
+ remainingTokens: number | null;
34
+ completionBudgetReport: string | null;
35
+ }
36
+
37
+ export function buildGoalToolResponse(
38
+ goal: Goal | null | undefined,
39
+ options?: { includeCompletionReport?: boolean },
40
+ ): GoalToolResponse {
41
+ const resolvedGoal = goal ?? null;
42
+ return {
43
+ goal: resolvedGoal,
44
+ remainingTokens: remainingTokens(resolvedGoal),
45
+ completionBudgetReport:
46
+ options?.includeCompletionReport && resolvedGoal?.status === "complete"
47
+ ? completionBudgetReport(resolvedGoal)
48
+ : null,
49
+ };
50
+ }
51
+
52
+ function validateCreateParams(params: GoalToolInput): { objective: string; tokenBudget?: number } {
53
+ const objective = params.objective?.trim();
54
+ if (!objective) {
55
+ throw new ToolError("objective is required when op=create");
56
+ }
57
+ const tokenBudget = params.token_budget;
58
+ if (tokenBudget !== undefined && (!Number.isInteger(tokenBudget) || tokenBudget <= 0)) {
59
+ throw new ToolError("token_budget must be a positive integer when provided");
60
+ }
61
+ return { objective, tokenBudget };
62
+ }
63
+
64
+ export class GoalTool implements AgentTool<typeof goalSchema, GoalToolDetails> {
65
+ readonly name = "goal";
66
+ readonly label = "Goal";
67
+ readonly description = prompt.render(goalDescription);
68
+ readonly parameters = goalSchema;
69
+ readonly strict = true;
70
+ readonly intent = "omit" as const;
71
+ readonly #session: ToolSession;
72
+
73
+ constructor(session: ToolSession) {
74
+ this.#session = session;
75
+ }
76
+
77
+ async execute(
78
+ _toolCallId: string,
79
+ params: GoalToolInput,
80
+ _signal?: AbortSignal,
81
+ _onUpdate?: AgentToolUpdateCallback<GoalToolDetails>,
82
+ _context?: AgentToolContext,
83
+ ): Promise<AgentToolResult<GoalToolDetails>> {
84
+ const runtime = this.#session.getGoalRuntime?.();
85
+ if (!runtime) {
86
+ throw new ToolError("Goal mode is not active.");
87
+ }
88
+
89
+ let response: GoalToolResponse;
90
+ if (params.op === "create") {
91
+ const created = await runtime.createGoal(validateCreateParams(params));
92
+ response = buildGoalToolResponse(created.goal);
93
+ } else if (params.op === "get") {
94
+ const state = this.#session.getGoalModeState?.();
95
+ response = buildGoalToolResponse(state?.enabled ? state.goal : null);
96
+ } else {
97
+ const completed = await runtime.completeGoalFromTool();
98
+ response = buildGoalToolResponse(completed, { includeCompletionReport: true });
99
+ }
100
+ let text: string;
101
+ if (response.goal) {
102
+ text = `Goal: ${response.goal.objective}\nStatus: ${response.goal.status}\nTokens: ${response.goal.tokensUsed} used`;
103
+ if (response.goal.tokenBudget !== undefined) {
104
+ text += ` / ${response.goal.tokenBudget} budget`;
105
+ }
106
+ if (response.remainingTokens !== null) {
107
+ text += `\nRemaining tokens: ${response.remainingTokens}`;
108
+ }
109
+ if (response.completionBudgetReport) {
110
+ text += `\n\n${response.completionBudgetReport}`;
111
+ }
112
+ } else {
113
+ text = "No active goal.";
114
+ }
115
+ return {
116
+ content: [{ type: "text", text }],
117
+ details: {
118
+ op: params.op,
119
+ goal: response.goal,
120
+ remainingTokens: response.remainingTokens,
121
+ completionBudgetReport: response.completionBudgetReport,
122
+ },
123
+ };
124
+ }
125
+ }
126
+
127
+ function describeOp(op: string | undefined): string {
128
+ switch (op) {
129
+ case "create":
130
+ return "set";
131
+ case "complete":
132
+ return "complete";
133
+ case "get":
134
+ return "check";
135
+ default:
136
+ return op ?? "?";
137
+ }
138
+ }
139
+
140
+ function goalBadgeColor(status: GoalStatus): ThemeColor {
141
+ switch (status) {
142
+ case "complete":
143
+ return "success";
144
+ case "budget-limited":
145
+ return "warning";
146
+ case "paused":
147
+ case "dropped":
148
+ return "muted";
149
+ default:
150
+ return "accent";
151
+ }
152
+ }
153
+
154
+ interface GoalRenderArgs {
155
+ op?: GoalToolInput["op"];
156
+ objective?: string;
157
+ token_budget?: number;
158
+ }
159
+
160
+ export const goalToolRenderer = {
161
+ renderCall(args: GoalRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
162
+ const description = describeOp(args.op);
163
+ const meta: string[] = [];
164
+ const trimmedObjective = args.objective?.trim();
165
+ if (args.op === "create" && trimmedObjective) {
166
+ const objective = truncateToWidth(trimmedObjective, TRUNCATE_LENGTHS.TITLE);
167
+ meta.push(uiTheme.italic(uiTheme.fg("muted", `"${objective}"`)));
168
+ }
169
+ if (args.op === "create" && args.token_budget !== undefined) {
170
+ meta.push(`budget ${formatNumber(args.token_budget)}`);
171
+ }
172
+ const text = renderStatusLine({ icon: "pending", title: "Goal", description, meta }, uiTheme);
173
+ return new Text(text, 0, 0);
174
+ },
175
+
176
+ renderResult(
177
+ result: { content: Array<{ type: string; text?: string }>; details?: GoalToolDetails; isError?: boolean },
178
+ _options: RenderResultOptions,
179
+ uiTheme: Theme,
180
+ args?: GoalRenderArgs,
181
+ ): Component {
182
+ const fallbackText = result.content?.find(c => c.type === "text")?.text ?? "";
183
+ const details = result.details;
184
+ const op = details?.op ?? args?.op;
185
+ const description = describeOp(op);
186
+
187
+ if (result.isError) {
188
+ const header = renderStatusLine({ icon: "error", title: "Goal", description }, uiTheme);
189
+ const body = formatErrorMessage(fallbackText || "Goal tool failed", uiTheme);
190
+ return new Text([header, body].join("\n"), 0, 0);
191
+ }
192
+
193
+ const goal = details?.goal ?? null;
194
+ if (!goal) {
195
+ const header = renderStatusLine({ icon: "warning", title: "Goal", description }, uiTheme);
196
+ const body = uiTheme.fg("muted", "No active goal.");
197
+ return new Text([header, body].join("\n"), 0, 0);
198
+ }
199
+
200
+ const lines: string[] = [];
201
+ lines.push(
202
+ renderStatusLine(
203
+ {
204
+ icon: "success",
205
+ title: "Goal",
206
+ description,
207
+ badge: { label: goal.status, color: goalBadgeColor(goal.status) },
208
+ },
209
+ uiTheme,
210
+ ),
211
+ );
212
+
213
+ const objectiveText = truncateToWidth(goal.objective.trim(), TRUNCATE_LENGTHS.LONG);
214
+ lines.push(` ${uiTheme.italic(uiTheme.fg("muted", `"${objectiveText}"`))}`);
215
+
216
+ const used = formatNumber(goal.tokensUsed);
217
+ const tokensLine =
218
+ goal.tokenBudget !== undefined
219
+ ? `${used} / ${formatNumber(goal.tokenBudget)} tokens (${formatNumber(Math.max(0, goal.tokenBudget - goal.tokensUsed))} left)`
220
+ : `${used} tokens`;
221
+ lines.push(` ${uiTheme.fg("dim", tokensLine)}`);
222
+
223
+ if (goal.timeUsedSeconds > 0) {
224
+ lines.push(` ${uiTheme.fg("dim", `${formatDuration(goal.timeUsedSeconds * 1000)} elapsed`)}`);
225
+ }
226
+
227
+ const report = details?.completionBudgetReport;
228
+ if (report) {
229
+ lines.push("");
230
+ lines.push(uiTheme.italic(uiTheme.fg("muted", report)));
231
+ }
232
+
233
+ return new Text(lines.join("\n"), 0, 0);
234
+ },
235
+
236
+ mergeCallAndResult: true,
237
+ };
@@ -63,9 +63,9 @@ export class HashlineMismatchError extends Error {
63
63
  }
64
64
 
65
65
  private static rejectionHeader(mismatches: HashMismatch[]): string[] {
66
- const noun = mismatches.length > 1 ? "lines have" : "line has";
66
+ const noun = mismatches.length > 1 ? "anchors do" : "anchor does";
67
67
  return [
68
- `Edit rejected: ${mismatches.length} ${noun} changed since the last read (marked *).`,
68
+ `Edit rejected: ${mismatches.length} ${noun} not match the current file (marked *).`,
69
69
  "The edit was NOT applied, please use the updated file content shown below, and issue another edit tool-call.",
70
70
  ];
71
71
  }
@@ -379,4 +379,4 @@ export const MENTAL_MODEL_FIRST_TURN_DEADLINE_MS = 1500;
379
379
  export const MENTAL_MODEL_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
380
380
 
381
381
  /** Need-only export of the raw seed list for tests. */
382
- export const __builtinSeedsForTest: ReadonlyArray<Readonly<RawSeed>> = BUILTIN_SEEDS;
382
+ export const builtinSeedsForTest: ReadonlyArray<Readonly<RawSeed>> = BUILTIN_SEEDS;
@@ -14,29 +14,10 @@
14
14
  import * as fs from "node:fs/promises";
15
15
  import * as path from "node:path";
16
16
  import { isEnoent } from "@oh-my-pi/pi-utils";
17
- import { AgentRegistry } from "../registry/agent-registry";
18
17
  import { applyQuery, pathToQuery } from "./json-query";
18
+ import { artifactsDirsFromRegistry } from "./registry-helpers";
19
19
  import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
20
20
 
21
- /**
22
- * Snapshot of artifacts dirs for every registered session, deduped.
23
- *
24
- * Prefers `sessionManager.getArtifactsDir()` because subagents adopt the
25
- * parent's manager and report the parent's dir there; dedup then collapses
26
- * the whole agent tree to one entry. Falls back to the raw session file
27
- * when no live session reference is attached.
28
- */
29
- function artifactsDirsFromRegistry(): string[] {
30
- const dirs: string[] = [];
31
- for (const ref of AgentRegistry.global().list()) {
32
- const dir =
33
- ref.session?.sessionManager.getArtifactsDir() ?? (ref.sessionFile ? ref.sessionFile.slice(0, -6) : null);
34
- if (!dir) continue;
35
- if (!dirs.includes(dir)) dirs.push(dir);
36
- }
37
- return dirs;
38
- }
39
-
40
21
  /**
41
22
  * Handler for agent:// URLs.
42
23
  *
@@ -12,27 +12,9 @@
12
12
  import * as fs from "node:fs/promises";
13
13
  import * as path from "node:path";
14
14
  import { isEnoent } from "@oh-my-pi/pi-utils";
15
- import { AgentRegistry } from "../registry/agent-registry";
15
+ import { artifactsDirsFromRegistry } from "./registry-helpers";
16
16
  import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
17
17
 
18
- /**
19
- * Snapshot of artifacts dirs across all registered sessions, deduped.
20
- *
21
- * Subagents adopt their parent's `ArtifactManager`, so their
22
- * `sessionManager.getArtifactsDir()` returns the parent's dir; dedup
23
- * collapses parent + N subagents to a single entry.
24
- */
25
- function artifactsDirsFromRegistry(): string[] {
26
- const dirs: string[] = [];
27
- for (const ref of AgentRegistry.global().list()) {
28
- const dir =
29
- ref.session?.sessionManager.getArtifactsDir() ?? (ref.sessionFile ? ref.sessionFile.slice(0, -6) : null);
30
- if (!dir) continue;
31
- if (!dirs.includes(dir)) dirs.push(dir);
32
- }
33
- return dirs;
34
- }
35
-
36
18
  export class ArtifactProtocolHandler implements ProtocolHandler {
37
19
  readonly scheme = "artifact";
38
20
  readonly immutable = true;