@esso0428/pi-subagents 0.15.5 → 0.15.7

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 (234) hide show
  1. package/CHANGELOG.md +10 -19
  2. package/README.md +5 -5
  3. package/dist/agent-history-list.d.ts +19 -0
  4. package/dist/agent-history-list.d.ts.map +1 -0
  5. package/dist/agent-history-list.js +69 -0
  6. package/dist/agent-history-list.js.map +1 -0
  7. package/dist/agent-history.d.ts +2 -1
  8. package/dist/agent-history.d.ts.map +1 -0
  9. package/dist/agent-history.js +32 -34
  10. package/dist/agent-history.js.map +1 -0
  11. package/dist/agent-manager.d.ts +24 -8
  12. package/dist/agent-manager.d.ts.map +1 -0
  13. package/dist/agent-manager.js +171 -93
  14. package/dist/agent-manager.js.map +1 -0
  15. package/dist/agent-runner.d.ts +1 -0
  16. package/dist/agent-runner.d.ts.map +1 -0
  17. package/dist/agent-runner.js +75 -86
  18. package/dist/agent-runner.js.map +1 -0
  19. package/dist/agent-types.d.ts +1 -0
  20. package/dist/agent-types.d.ts.map +1 -0
  21. package/dist/agent-types.js +28 -45
  22. package/dist/agent-types.js.map +1 -0
  23. package/dist/context.d.ts +1 -0
  24. package/dist/context.d.ts.map +1 -0
  25. package/dist/context.js +3 -6
  26. package/dist/context.js.map +1 -0
  27. package/dist/cross-extension-rpc.d.ts +1 -0
  28. package/dist/cross-extension-rpc.d.ts.map +1 -0
  29. package/dist/cross-extension-rpc.js +6 -9
  30. package/dist/cross-extension-rpc.js.map +1 -0
  31. package/dist/custom-agents.d.ts +1 -0
  32. package/dist/custom-agents.d.ts.map +1 -0
  33. package/dist/custom-agents.js +16 -18
  34. package/dist/custom-agents.js.map +1 -0
  35. package/dist/default-agents.d.ts +1 -0
  36. package/dist/default-agents.d.ts.map +1 -0
  37. package/dist/default-agents.js +2 -4
  38. package/dist/default-agents.js.map +1 -0
  39. package/dist/enabled-models.d.ts +1 -0
  40. package/dist/enabled-models.d.ts.map +1 -0
  41. package/dist/enabled-models.js +12 -16
  42. package/dist/enabled-models.js.map +1 -0
  43. package/dist/env.d.ts +1 -0
  44. package/dist/env.d.ts.map +1 -0
  45. package/dist/env.js +2 -4
  46. package/dist/env.js.map +1 -0
  47. package/dist/group-join.d.ts +1 -0
  48. package/dist/group-join.d.ts.map +1 -0
  49. package/dist/group-join.js +2 -5
  50. package/dist/group-join.js.map +1 -0
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +306 -292
  54. package/dist/index.js.map +1 -0
  55. package/dist/invocation-config.d.ts +1 -0
  56. package/dist/invocation-config.d.ts.map +1 -0
  57. package/dist/invocation-config.js +3 -6
  58. package/dist/invocation-config.js.map +1 -0
  59. package/dist/memory.d.ts +1 -0
  60. package/dist/memory.d.ts.map +1 -0
  61. package/dist/memory.js +25 -34
  62. package/dist/memory.js.map +1 -0
  63. package/dist/model-resolver.d.ts +1 -0
  64. package/dist/model-resolver.d.ts.map +1 -0
  65. package/dist/model-resolver.js +2 -4
  66. package/dist/model-resolver.js.map +1 -0
  67. package/dist/nico-overrides.d.ts +1 -0
  68. package/dist/nico-overrides.d.ts.map +1 -0
  69. package/dist/nico-overrides.js +15 -20
  70. package/dist/nico-overrides.js.map +1 -0
  71. package/dist/output-file.d.ts +1 -0
  72. package/dist/output-file.d.ts.map +1 -0
  73. package/dist/output-file.js +17 -22
  74. package/dist/output-file.js.map +1 -0
  75. package/dist/prompts.d.ts +1 -0
  76. package/dist/prompts.d.ts.map +1 -0
  77. package/dist/prompts.js +2 -4
  78. package/dist/prompts.js.map +1 -0
  79. package/dist/schedule-store.d.ts +1 -0
  80. package/dist/schedule-store.d.ts.map +1 -0
  81. package/dist/schedule-store.js +17 -21
  82. package/dist/schedule-store.js.map +1 -0
  83. package/dist/schedule.d.ts +1 -0
  84. package/dist/schedule.d.ts.map +1 -0
  85. package/dist/schedule.js +9 -12
  86. package/dist/schedule.js.map +1 -0
  87. package/dist/settings.d.ts +1 -0
  88. package/dist/settings.d.ts.map +1 -0
  89. package/dist/settings.js +16 -23
  90. package/dist/settings.js.map +1 -0
  91. package/dist/skill-loader.d.ts +1 -0
  92. package/dist/skill-loader.d.ts.map +1 -0
  93. package/dist/skill-loader.js +21 -23
  94. package/dist/skill-loader.js.map +1 -0
  95. package/dist/status-note.d.ts +1 -0
  96. package/dist/status-note.d.ts.map +1 -0
  97. package/dist/status-note.js +2 -4
  98. package/dist/status-note.js.map +1 -0
  99. package/dist/types.d.ts +5 -1
  100. package/dist/types.d.ts.map +1 -0
  101. package/dist/types.js +2 -4
  102. package/dist/types.js.map +1 -0
  103. package/dist/ui/agent-widget.d.ts +2 -5
  104. package/dist/ui/agent-widget.d.ts.map +1 -0
  105. package/dist/ui/agent-widget.js +29 -51
  106. package/dist/ui/agent-widget.js.map +1 -0
  107. package/dist/ui/ccstyle/diff/ansi-utils.d.ts +11 -0
  108. package/dist/ui/ccstyle/diff/ansi-utils.d.ts.map +1 -0
  109. package/dist/ui/ccstyle/diff/ansi-utils.js +145 -0
  110. package/dist/ui/ccstyle/diff/ansi-utils.js.map +1 -0
  111. package/dist/ui/ccstyle/diff/diff-presentation.d.ts +12 -0
  112. package/dist/ui/ccstyle/diff/diff-presentation.d.ts.map +1 -0
  113. package/dist/ui/ccstyle/diff/diff-presentation.js +49 -0
  114. package/dist/ui/ccstyle/diff/diff-presentation.js.map +1 -0
  115. package/dist/ui/ccstyle/diff/diff-renderer.d.ts +46 -0
  116. package/dist/ui/ccstyle/diff/diff-renderer.d.ts.map +1 -0
  117. package/dist/ui/ccstyle/diff/diff-renderer.js +2044 -0
  118. package/dist/ui/ccstyle/diff/diff-renderer.js.map +1 -0
  119. package/dist/ui/ccstyle/diff/line-width-safety.d.ts +12 -0
  120. package/dist/ui/ccstyle/diff/line-width-safety.d.ts.map +1 -0
  121. package/dist/ui/ccstyle/diff/line-width-safety.js +59 -0
  122. package/dist/ui/ccstyle/diff/line-width-safety.js.map +1 -0
  123. package/dist/ui/ccstyle/diff/render-utils.d.ts +6 -0
  124. package/dist/ui/ccstyle/diff/render-utils.d.ts.map +1 -0
  125. package/dist/ui/ccstyle/diff/render-utils.js +25 -0
  126. package/dist/ui/ccstyle/diff/render-utils.js.map +1 -0
  127. package/dist/ui/ccstyle/diff/types.d.ts +22 -0
  128. package/dist/ui/ccstyle/diff/types.d.ts.map +1 -0
  129. package/dist/ui/ccstyle/diff/types.js +10 -0
  130. package/dist/ui/ccstyle/diff/types.js.map +1 -0
  131. package/dist/ui/ccstyle/diff/write-display-utils.d.ts +2 -0
  132. package/dist/ui/ccstyle/diff/write-display-utils.d.ts.map +1 -0
  133. package/dist/ui/ccstyle/diff/write-display-utils.js +12 -0
  134. package/dist/ui/ccstyle/diff/write-display-utils.js.map +1 -0
  135. package/dist/ui/ccstyle/tool-renderer.d.ts +17 -0
  136. package/dist/ui/ccstyle/tool-renderer.d.ts.map +1 -0
  137. package/dist/ui/ccstyle/tool-renderer.js +58 -0
  138. package/dist/ui/ccstyle/tool-renderer.js.map +1 -0
  139. package/dist/ui/ccstyle/tool-result.d.ts +24 -0
  140. package/dist/ui/ccstyle/tool-result.d.ts.map +1 -0
  141. package/dist/ui/ccstyle/tool-result.js +193 -0
  142. package/dist/ui/ccstyle/tool-result.js.map +1 -0
  143. package/dist/ui/conversation-blocks.d.ts +46 -0
  144. package/dist/ui/conversation-blocks.d.ts.map +1 -0
  145. package/dist/ui/conversation-blocks.js +306 -0
  146. package/dist/ui/conversation-blocks.js.map +1 -0
  147. package/dist/ui/conversation-nvim.d.ts +8 -0
  148. package/dist/ui/conversation-nvim.d.ts.map +1 -0
  149. package/dist/ui/conversation-nvim.js +117 -0
  150. package/dist/ui/conversation-nvim.js.map +1 -0
  151. package/dist/ui/conversation-role.d.ts +13 -0
  152. package/dist/ui/conversation-role.d.ts.map +1 -0
  153. package/dist/ui/conversation-role.js +39 -0
  154. package/dist/ui/conversation-role.js.map +1 -0
  155. package/dist/ui/conversation-search.d.ts +39 -0
  156. package/dist/ui/conversation-search.d.ts.map +1 -0
  157. package/dist/ui/conversation-search.js +124 -0
  158. package/dist/ui/conversation-search.js.map +1 -0
  159. package/dist/ui/conversation-timeline.d.ts +62 -0
  160. package/dist/ui/conversation-timeline.d.ts.map +1 -0
  161. package/dist/ui/conversation-timeline.js +263 -0
  162. package/dist/ui/conversation-timeline.js.map +1 -0
  163. package/dist/ui/conversation-viewer.d.ts +62 -20
  164. package/dist/ui/conversation-viewer.d.ts.map +1 -0
  165. package/dist/ui/conversation-viewer.js +449 -224
  166. package/dist/ui/conversation-viewer.js.map +1 -0
  167. package/dist/ui/fleet-list.d.ts +24 -11
  168. package/dist/ui/fleet-list.d.ts.map +1 -0
  169. package/dist/ui/fleet-list.js +86 -78
  170. package/dist/ui/fleet-list.js.map +1 -0
  171. package/dist/ui/schedule-menu.d.ts +1 -0
  172. package/dist/ui/schedule-menu.d.ts.map +1 -0
  173. package/dist/ui/schedule-menu.js +2 -4
  174. package/dist/ui/schedule-menu.js.map +1 -0
  175. package/dist/ui/viewer-keys.d.ts +1 -0
  176. package/dist/ui/viewer-keys.d.ts.map +1 -0
  177. package/dist/ui/viewer-keys.js +8 -10
  178. package/dist/ui/viewer-keys.js.map +1 -0
  179. package/dist/usage.d.ts +1 -0
  180. package/dist/usage.d.ts.map +1 -0
  181. package/dist/usage.js +5 -10
  182. package/dist/usage.js.map +1 -0
  183. package/dist/worktree.d.ts +1 -0
  184. package/dist/worktree.d.ts.map +1 -0
  185. package/dist/worktree.js +27 -31
  186. package/dist/worktree.js.map +1 -0
  187. package/dist/write-execution.d.ts +42 -0
  188. package/dist/write-execution.d.ts.map +1 -0
  189. package/dist/write-execution.js +138 -0
  190. package/dist/write-execution.js.map +1 -0
  191. package/package.json +1 -1
  192. package/src/agent-history-list.ts +91 -0
  193. package/src/agent-history.ts +12 -17
  194. package/src/agent-manager.ts +169 -81
  195. package/src/agent-runner.ts +12 -13
  196. package/src/index.ts +117 -98
  197. package/src/output-file.ts +1 -1
  198. package/src/types.ts +4 -1
  199. package/src/ui/agent-widget.ts +3 -9
  200. package/src/ui/ccstyle/ATTRIBUTION.md +37 -0
  201. package/src/ui/ccstyle/diff/ansi-utils.ts +168 -0
  202. package/src/ui/ccstyle/diff/diff-presentation.ts +70 -0
  203. package/src/ui/ccstyle/diff/diff-renderer.ts +3148 -0
  204. package/src/ui/ccstyle/diff/line-width-safety.ts +92 -0
  205. package/src/ui/ccstyle/diff/render-utils.ts +32 -0
  206. package/src/ui/ccstyle/diff/types.ts +33 -0
  207. package/src/ui/ccstyle/diff/write-display-utils.ts +12 -0
  208. package/src/ui/ccstyle/tool-renderer.ts +71 -0
  209. package/src/ui/ccstyle/tool-result.ts +238 -0
  210. package/src/ui/conversation-blocks.ts +404 -0
  211. package/src/ui/conversation-nvim.ts +127 -0
  212. package/src/ui/conversation-role.ts +45 -0
  213. package/src/ui/conversation-search.ts +161 -0
  214. package/src/ui/conversation-timeline.ts +315 -0
  215. package/src/ui/conversation-viewer.ts +418 -210
  216. package/src/ui/fleet-list.ts +73 -52
  217. package/src/write-execution.ts +180 -0
  218. package/test/agent-history-list.test.ts +121 -0
  219. package/test/agent-manager-history.test.ts +59 -58
  220. package/test/agent-menu-history-navigation.test.ts +86 -0
  221. package/test/output-file-history.test.ts +50 -0
  222. package/test/ui/conversation-blocks.test.ts +103 -0
  223. package/test/ui/conversation-diff.test.ts +91 -0
  224. package/test/ui/conversation-search.test.ts +55 -0
  225. package/test/ui/conversation-viewer.test.ts +182 -0
  226. package/test/ui/fleet-list.test.ts +131 -0
  227. package/test/write-execution.test.ts +83 -0
  228. package/tsconfig.json +16 -0
  229. package/vitest.temp.config.mts +6 -0
  230. package/dist/ui/markdown-result.d.ts +0 -3
  231. package/dist/ui/markdown-result.js +0 -53
  232. package/src/ui/markdown-result.ts +0 -56
  233. package/test/agent-history.test.ts +0 -63
  234. package/test/ui/markdown-result.test.ts +0 -45
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * pi-agents — A pi extension providing Claude Code-style autonomous sub-agents.
4
3
  *
@@ -10,34 +9,31 @@
10
9
  * Commands:
11
10
  * /agents — Interactive agent management menu
12
11
  */
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.renderRunningAgentStatus = renderRunningAgentStatus;
15
- exports.default = default_1;
16
- const node_fs_1 = require("node:fs");
17
- const node_path_1 = require("node:path");
18
- const pi_coding_agent_1 = require("@earendil-works/pi-coding-agent");
19
- const pi_tui_1 = require("@earendil-works/pi-tui");
20
- const typebox_1 = require("@sinclair/typebox");
21
- const agent_manager_js_1 = require("./agent-manager.js");
22
- const agent_runner_js_1 = require("./agent-runner.js");
23
- const agent_types_js_1 = require("./agent-types.js");
24
- const cross_extension_rpc_js_1 = require("./cross-extension-rpc.js");
25
- const custom_agents_js_1 = require("./custom-agents.js");
26
- const enabled_models_js_1 = require("./enabled-models.js");
27
- const group_join_js_1 = require("./group-join.js");
28
- const invocation_config_js_1 = require("./invocation-config.js");
29
- const model_resolver_js_1 = require("./model-resolver.js");
30
- const agent_history_js_1 = require("./agent-history.js");
31
- const output_file_js_1 = require("./output-file.js");
32
- const schedule_js_1 = require("./schedule.js");
33
- const schedule_store_js_1 = require("./schedule-store.js");
34
- const settings_js_1 = require("./settings.js");
35
- const status_note_js_1 = require("./status-note.js");
36
- const agent_widget_js_1 = require("./ui/agent-widget.js");
37
- const fleet_list_js_1 = require("./ui/fleet-list.js");
38
- const markdown_result_js_1 = require("./ui/markdown-result.js");
39
- const schedule_menu_js_1 = require("./ui/schedule-menu.js");
40
- const usage_js_1 = require("./usage.js");
12
+ import { existsSync, mkdirSync, readFileSync, unlinkSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { defineTool, getAgentDir, getSettingsListTheme } from "@earendil-works/pi-coding-agent";
15
+ import { Container, Key, matchesKey, SettingsList, Spacer, Text } from "@earendil-works/pi-tui";
16
+ import { Type } from "@sinclair/typebox";
17
+ import { AgentManager } from "./agent-manager.js";
18
+ import { getAgentConversation, getDefaultMaxTurns, getGraceTurns, normalizeMaxTurns, SUBAGENT_TOOL_NAMES, setDefaultMaxTurns, setGraceTurns, steerAgent } from "./agent-runner.js";
19
+ import { applyNicoOverrides, BUILTIN_TOOL_NAMES, getAgentConfig, getAllTypes, getAvailableTypes, isDefaultsDisabled, registerAgents, resolveType, setDefaultsDisabled } from "./agent-types.js";
20
+ import { registerRpcHandlers } from "./cross-extension-rpc.js";
21
+ import { loadCustomAgents } from "./custom-agents.js";
22
+ import { isModelInScope, readEnabledModels, resolveEnabledModels } from "./enabled-models.js";
23
+ import { GroupJoinManager } from "./group-join.js";
24
+ import { resolveAgentInvocationConfig, resolveJoinMode } from "./invocation-config.js";
25
+ import { resolveModel } from "./model-resolver.js";
26
+ import { agentHistoryLocator, createAgentHistoryPath, readAgentHistory } from "./agent-history.js";
27
+ import { buildAgentStatusMenuEntries, canOpenActiveAgent, canOpenAgentHistory, formatAgentHistoryOption, splitAgentRecords } from "./agent-history-list.js";
28
+ import { createOutputFilePath, streamToOutputFile, writeInitialEntry } from "./output-file.js";
29
+ import { SubagentScheduler } from "./schedule.js";
30
+ import { resolveStorePath, ScheduleStore } from "./schedule-store.js";
31
+ import { applyAndEmitLoaded, saveAndEmitChanged } from "./settings.js";
32
+ import { getStatusNote } from "./status-note.js";
33
+ import { AgentWidget, buildInvocationTags, describeActivity, fgPreservingNestedStyles, formatDuration, formatMs, formatTokens, formatTurns, getDisplayName, getPromptModeLabel, SPINNER, } from "./ui/agent-widget.js";
34
+ import { FleetList } from "./ui/fleet-list.js";
35
+ import { showSchedulesMenu } from "./ui/schedule-menu.js";
36
+ import { addUsage, getLifetimeTotal, getSessionContextPercent } from "./usage.js";
41
37
  // ---- Shared helpers ----
42
38
  /** Tool execute return value for a text response. */
43
39
  function textResult(msg, details) {
@@ -75,16 +71,16 @@ function abortable(promise, signal) {
75
71
  });
76
72
  });
77
73
  }
78
- function renderRunningAgentStatus(frame, statsText, activity, theme) {
79
- const container = new pi_tui_1.Container();
80
- container.addChild(new pi_tui_1.Text(theme.fg("accent", frame) + (statsText ? " " + statsText : ""), 0, 0));
81
- container.addChild(new pi_tui_1.Text(theme.fg("dim", ` ⎿ ${activity}`), 0, 0));
74
+ export function renderRunningAgentStatus(frame, statsText, activity, theme) {
75
+ const container = new Container();
76
+ container.addChild(new Text(theme.fg("accent", frame) + (statsText ? " " + statsText : ""), 0, 0));
77
+ container.addChild(new Text(theme.fg("dim", ` ⎿ ${activity}`), 0, 0));
82
78
  return container;
83
79
  }
84
80
  /** Format an agent's lifetime token total, or "" when zero. */
85
81
  function formatLifetimeTokens(o) {
86
- const t = (0, usage_js_1.getLifetimeTotal)(o.lifetimeUsage);
87
- return t > 0 ? (0, agent_widget_js_1.formatTokens)(t) : "";
82
+ const t = getLifetimeTotal(o.lifetimeUsage);
83
+ return t > 0 ? formatTokens(t) : "";
88
84
  }
89
85
  /**
90
86
  * Create an AgentActivity state and spawn callbacks for tracking tool usage.
@@ -128,7 +124,7 @@ function createActivityTracker(maxTurns, onStreamUpdate) {
128
124
  state.session = session;
129
125
  },
130
126
  onAssistantUsage: (usage) => {
131
- (0, usage_js_1.addUsage)(state.lifetimeUsage, usage);
127
+ addUsage(state.lifetimeUsage, usage);
132
128
  onStreamUpdate?.();
133
129
  },
134
130
  };
@@ -169,8 +165,8 @@ function escapeXml(s) {
169
165
  function formatTaskNotification(record, resultMaxLen) {
170
166
  const status = getStatusLabel(record.status, record.error);
171
167
  const durationMs = record.completedAt ? record.completedAt - record.startedAt : 0;
172
- const totalTokens = (0, usage_js_1.getLifetimeTotal)(record.lifetimeUsage);
173
- const contextPercent = (0, usage_js_1.getSessionContextPercent)(record.session);
168
+ const totalTokens = getLifetimeTotal(record.lifetimeUsage);
169
+ const contextPercent = getSessionContextPercent(record.session);
174
170
  const ctxXml = contextPercent !== null ? `<context_percent>${Math.round(contextPercent)}</context_percent>` : "";
175
171
  const compactXml = record.compactionCount ? `<compactions>${record.compactionCount}</compactions>` : "";
176
172
  const resultPreview = record.result
@@ -184,7 +180,7 @@ function formatTaskNotification(record, resultMaxLen) {
184
180
  record.toolCallId ? `<tool-use-id>${escapeXml(record.toolCallId)}</tool-use-id>` : null,
185
181
  record.outputFile ? `<output-file>${escapeXml(record.outputFile)}</output-file>` : null,
186
182
  `<status>${escapeXml(status)}</status>`,
187
- `<summary>Agent "${escapeXml(record.description)}" ${record.status}${(0, status_note_js_1.getStatusNote)(record.status)}</summary>`,
183
+ `<summary>Agent "${escapeXml(record.description)}" ${record.status}${getStatusNote(record.status)}</summary>`,
188
184
  `<result>${escapeXml(resultPreview)}</result>`,
189
185
  `<usage><total_tokens>${totalTokens}</total_tokens><tool_uses>${record.toolUses}</tool_uses>${ctxXml}${compactXml}<duration_ms>${durationMs}</duration_ms></usage>`,
190
186
  `</task-notification>`,
@@ -205,11 +201,9 @@ function buildDetails(base, record, activity, overrides) {
205
201
  ...overrides,
206
202
  };
207
203
  }
208
- /** Maximum expanded notification body retained in message details. */
209
- const MAX_NOTIFICATION_RESULT_TEXT_LENGTH = 20_000;
210
204
  /** Build notification details for the custom message renderer. */
211
205
  function buildNotificationDetails(record, resultMaxLen, activity) {
212
- const totalTokens = (0, usage_js_1.getLifetimeTotal)(record.lifetimeUsage);
206
+ const totalTokens = getLifetimeTotal(record.lifetimeUsage);
213
207
  return {
214
208
  id: record.id,
215
209
  description: record.description,
@@ -221,11 +215,6 @@ function buildNotificationDetails(record, resultMaxLen, activity) {
221
215
  durationMs: record.completedAt ? record.completedAt - record.startedAt : 0,
222
216
  outputFile: record.outputFile,
223
217
  error: record.error,
224
- resultText: record.result
225
- ? record.result.length > MAX_NOTIFICATION_RESULT_TEXT_LENGTH
226
- ? record.result.slice(0, MAX_NOTIFICATION_RESULT_TEXT_LENGTH) + "…"
227
- : record.result
228
- : undefined,
229
218
  resultPreview: record.result
230
219
  ? record.result.length > resultMaxLen
231
220
  ? record.result.slice(0, resultMaxLen) + "…"
@@ -233,7 +222,7 @@ function buildNotificationDetails(record, resultMaxLen, activity) {
233
222
  : "No output.",
234
223
  };
235
224
  }
236
- function default_1(pi) {
225
+ export default function (pi) {
237
226
  // ---- Register custom notification renderer ----
238
227
  pi.registerMessageRenderer("subagent-notification", (message, { expanded }, theme) => {
239
228
  const d = message.details;
@@ -250,49 +239,40 @@ function default_1(pi) {
250
239
  // Line 2: stats
251
240
  const parts = [];
252
241
  if (d.turnCount > 0)
253
- parts.push((0, agent_widget_js_1.formatTurns)(d.turnCount, d.maxTurns));
242
+ parts.push(formatTurns(d.turnCount, d.maxTurns));
254
243
  if (d.toolUses > 0)
255
244
  parts.push(`${d.toolUses} tool use${d.toolUses === 1 ? "" : "s"}`);
256
245
  if (d.totalTokens > 0)
257
- parts.push((0, agent_widget_js_1.formatTokens)(d.totalTokens));
246
+ parts.push(formatTokens(d.totalTokens));
258
247
  if (d.durationMs > 0)
259
- parts.push((0, agent_widget_js_1.formatMs)(d.durationMs));
248
+ parts.push(formatMs(d.durationMs));
260
249
  if (parts.length) {
261
250
  line += "\n " + parts.map(p => theme.fg("dim", p)).join(" " + theme.fg("dim", "·") + " ");
262
251
  }
263
- if (!expanded) {
264
- // Collapsed previews intentionally remain compact plain text.
252
+ // Line 3: result preview (collapsed) or full (expanded)
253
+ if (expanded) {
254
+ const lines = d.resultPreview.split("\n").slice(0, 30);
255
+ for (const l of lines)
256
+ line += "\n" + theme.fg("dim", ` ${l}`);
257
+ }
258
+ else {
265
259
  const preview = d.resultPreview.split("\n")[0]?.slice(0, 80) ?? "";
266
260
  line += "\n " + theme.fg("dim", `⎿ ${preview}`);
267
- if (d.outputFile) {
268
- line += "\n " + theme.fg("muted", `transcript: ${d.outputFile}`);
269
- }
270
- return line;
271
261
  }
272
- const container = new pi_tui_1.Container();
273
- container.addChild(new pi_tui_1.Text(line, 0, 0));
274
- container.addChild((0, markdown_result_js_1.createMarkdownResult)(d.resultText ?? d.resultPreview, theme, 30));
262
+ // Line 4: output file link (if present)
275
263
  if (d.outputFile) {
276
- container.addChild(new pi_tui_1.Text(theme.fg("muted", ` transcript: ${d.outputFile}`), 0, 0));
264
+ line += "\n " + theme.fg("muted", `transcript: ${d.outputFile}`);
277
265
  }
278
- return container;
266
+ return line;
279
267
  }
280
268
  const all = [d, ...(d.others ?? [])];
281
- if (!expanded)
282
- return new pi_tui_1.Text(all.map(renderOne).join("\n"), 0, 0);
283
- const container = new pi_tui_1.Container();
284
- all.forEach((item, index) => {
285
- if (index > 0)
286
- container.addChild(new pi_tui_1.Spacer(1));
287
- container.addChild(renderOne(item));
288
- });
289
- return container;
269
+ return new Text(all.map(renderOne).join("\n"), 0, 0);
290
270
  });
291
271
  /** Reload agents from project/global custom agent dirs and merge with defaults (called on init and each Agent invocation). */
292
272
  const reloadCustomAgents = () => {
293
- const userAgents = (0, custom_agents_js_1.loadCustomAgents)(process.cwd());
294
- (0, agent_types_js_1.registerAgents)(userAgents);
295
- (0, agent_types_js_1.applyNicoOverrides)();
273
+ const userAgents = loadCustomAgents(process.cwd());
274
+ registerAgents(userAgents);
275
+ applyNicoOverrides();
296
276
  };
297
277
  // Initial load
298
278
  reloadCustomAgents();
@@ -344,7 +324,7 @@ function default_1(pi) {
344
324
  widget.update();
345
325
  }
346
326
  // ---- Group join manager ----
347
- const groupJoin = new group_join_js_1.GroupJoinManager((records, partial) => {
327
+ const groupJoin = new GroupJoinManager((records, partial) => {
348
328
  for (const r of records) {
349
329
  agentActivity.delete(r.id);
350
330
  widget.markFinished(r.id);
@@ -384,7 +364,7 @@ function default_1(pi) {
384
364
  // tokens is omitted when nothing was ever produced (e.g. agent errored before
385
365
  // any message_end fired), preserving prior payload shape.
386
366
  const u = record.lifetimeUsage;
387
- const total = (0, usage_js_1.getLifetimeTotal)(u);
367
+ const total = getLifetimeTotal(u);
388
368
  const tokens = total > 0
389
369
  ? { input: u.input, output: u.output, total }
390
370
  : undefined;
@@ -401,7 +381,7 @@ function default_1(pi) {
401
381
  };
402
382
  }
403
383
  // Background completion: route through group join or send individual nudge
404
- const manager = new agent_manager_js_1.AgentManager((record) => {
384
+ const manager = new AgentManager((record) => {
405
385
  // Emit lifecycle event based on terminal status
406
386
  const isError = record.status === "error" || record.status === "stopped" || record.status === "aborted";
407
387
  const eventData = buildEventData(record);
@@ -411,13 +391,14 @@ function default_1(pi) {
411
391
  else {
412
392
  pi.events.emit("subagents:completed", eventData);
413
393
  }
414
- // Persist final record for cross-extension history reconstruction. Keep
415
- // the transcript body in a project-local file rather than inflating the
416
- // parent session JSONL; only its project-relative locator is persisted.
394
+ // Persist final record for cross-extension history reconstruction
417
395
  pi.appendEntry("subagents:record", {
418
396
  id: record.id, type: record.type, description: record.description,
419
397
  status: record.status, result: record.result, error: record.error,
420
398
  startedAt: record.startedAt, completedAt: record.completedAt,
399
+ toolUses: record.toolUses,
400
+ lifetimeUsage: record.lifetimeUsage,
401
+ invocation: record.invocation,
421
402
  transcriptPath: record.transcriptPath,
422
403
  });
423
404
  // Skip notification if result was already consumed via get_subagent_result
@@ -493,14 +474,14 @@ function default_1(pi) {
493
474
  // Session-scoped: store is constructed inside session_start once sessionId
494
475
  // is available. Mirrors pi-chonky-tasks's session-scoped task store —
495
476
  // schedules reset on /new, restore on /resume.
496
- const scheduler = new schedule_js_1.SubagentScheduler();
477
+ const scheduler = new SubagentScheduler();
497
478
  function startScheduler(ctx) {
498
479
  try {
499
480
  const sessionId = ctx.sessionManager?.getSessionId?.();
500
481
  if (!sessionId)
501
482
  return; // sessionId not yet available — try again on next event
502
- const path = (0, schedule_store_js_1.resolveStorePath)(ctx.cwd, sessionId);
503
- const store = new schedule_store_js_1.ScheduleStore(path);
483
+ const path = resolveStorePath(ctx.cwd, sessionId);
484
+ const store = new ScheduleStore(path);
504
485
  scheduler.start(pi, ctx, manager, store);
505
486
  pi.events.emit("subagents:scheduler_ready", { sessionId, jobCount: store.list().length });
506
487
  }
@@ -515,27 +496,15 @@ function default_1(pi) {
515
496
  // bound session_start, so a filtered-out activation never advertises (#142).
516
497
  pi.on("session_start", async (_event, ctx) => {
517
498
  currentCtx = ctx;
518
- try {
519
- (0, agent_history_js_1.ensureSubagentsGitignore)(ctx.cwd);
520
- }
521
- catch (err) {
522
- console.warn("[pi-subagents] Failed to protect project-local history:", err);
523
- }
524
499
  manager.clearCompleted(true);
525
- const historicalRecords = ctx.sessionManager
526
- .getBranch()
527
- .filter((entry) => entry?.type === "custom" && entry.customType === "subagents:record")
528
- .map((entry) => entry.data);
529
- manager.restoreCompleted(historicalRecords);
530
- // Bind the UI here as well as on tool execution so rehydrated terminal
531
- // records are immediately visible and openable from FleetView after reload.
532
- widget.setUICtx(ctx.ui);
533
- fleet.setUICtx(ctx.ui);
534
- fleet.update();
500
+ const branch = ctx.sessionManager?.getBranch?.() ?? [];
501
+ manager.restoreCompleted(branch
502
+ .filter((entry) => entry?.type === "custom" && entry?.customType === "subagents:record")
503
+ .map((entry) => entry.data));
535
504
  // Guard mirrors the `!scheduler.isActive()` pattern below: session_start
536
505
  // fires once per activation, but a double-bind must not leak listeners.
537
506
  if (!rpcHandle) {
538
- rpcHandle = (0, cross_extension_rpc_js_1.registerRpcHandlers)({
507
+ rpcHandle = registerRpcHandlers({
539
508
  events: pi.events,
540
509
  pi,
541
510
  getCtx: () => currentCtx,
@@ -581,10 +550,10 @@ function default_1(pi) {
581
550
  // everything else; "off" = hide the widget entirely. Read live at render time.
582
551
  let widgetMode = "background";
583
552
  function getWidgetMode() { return widgetMode; }
584
- const widget = new agent_widget_js_1.AgentWidget(manager, agentActivity, getWidgetMode, () => currentCtx?.cwd);
553
+ const widget = new AgentWidget(manager, agentActivity, getWidgetMode);
585
554
  function setWidgetMode(m) { widgetMode = m; widget.update(); }
586
555
  // Claude Code-style FleetView: navigable list of main + subagents below the editor.
587
- const fleet = new fleet_list_js_1.FleetList(manager, agentActivity, () => currentCtx?.cwd);
556
+ const fleet = new FleetList(manager, agentActivity, () => currentCtx?.cwd, pi, () => currentCtx);
588
557
  let fleetViewEnabled = true;
589
558
  function isFleetViewEnabled() { return fleetViewEnabled; }
590
559
  function setFleetViewEnabled(b) { fleetViewEnabled = b; fleet.setEnabled(b); }
@@ -625,7 +594,7 @@ function default_1(pi) {
625
594
  // State lives in agent-types.ts (isDefaultsDisabled) because registerAgents
626
595
  // needs it; this wrapper just re-registers after flipping it.
627
596
  function setDisableDefaultAgents(b) {
628
- (0, agent_types_js_1.setDefaultsDisabled)(b);
597
+ setDefaultsDisabled(b);
629
598
  reloadCustomAgents(); // re-register with new setting
630
599
  }
631
600
  // ---- Agent tool description mode ----
@@ -688,15 +657,15 @@ function default_1(pi) {
688
657
  const tools = cfg?.builtinToolNames;
689
658
  if (!tools || tools.length === 0)
690
659
  return "*";
691
- const isFullSet = tools.length === agent_types_js_1.BUILTIN_TOOL_NAMES.length
692
- && agent_types_js_1.BUILTIN_TOOL_NAMES.every((t) => tools.includes(t));
660
+ const isFullSet = tools.length === BUILTIN_TOOL_NAMES.length
661
+ && BUILTIN_TOOL_NAMES.every((t) => tools.includes(t));
693
662
  return isFullSet ? "*" : tools.join(", ");
694
663
  };
695
664
  /** Build the full type list text dynamically from available agents only. */
696
665
  const buildTypeListText = () => {
697
- const available = (0, agent_types_js_1.getAvailableTypes)();
666
+ const available = getAvailableTypes();
698
667
  return available.map((name) => {
699
- const cfg = (0, agent_types_js_1.getAgentConfig)(name);
668
+ const cfg = getAgentConfig(name);
700
669
  const modelSuffix = cfg?.model ? ` (${getModelLabelFromConfig(cfg.model)})` : "";
701
670
  const toolsSuffix = ` (Tools: ${formatToolsSuffix(cfg)})`;
702
671
  return `- ${name}: ${cfg?.description ?? name}${modelSuffix}${toolsSuffix}`;
@@ -708,8 +677,8 @@ function default_1(pi) {
708
677
  return (match ? match[0] : text).replace(/\s+/g, " ").trim();
709
678
  };
710
679
  /** Compact type list: one line per agent, first sentence only. */
711
- const buildCompactTypeListText = () => (0, agent_types_js_1.getAvailableTypes)().map((name) => {
712
- const cfg = (0, agent_types_js_1.getAgentConfig)(name);
680
+ const buildCompactTypeListText = () => getAvailableTypes().map((name) => {
681
+ const cfg = getAgentConfig(name);
713
682
  return `- ${name}: ${firstSentence(cfg?.description ?? name)} (Tools: ${formatToolsSuffix(cfg)})`;
714
683
  }).join("\n");
715
684
  /** Derive a short model label from a model string. */
@@ -722,10 +691,10 @@ function default_1(pi) {
722
691
  // Apply persisted settings on startup and emit `subagents:settings_loaded`.
723
692
  // Global + project merged; missing → defaults; corrupt file emits a warning
724
693
  // to stderr and falls back to defaults.
725
- (0, settings_js_1.applyAndEmitLoaded)({
694
+ applyAndEmitLoaded({
726
695
  setMaxConcurrent: (n) => manager.setMaxConcurrent(n),
727
- setDefaultMaxTurns: agent_runner_js_1.setDefaultMaxTurns,
728
- setGraceTurns: agent_runner_js_1.setGraceTurns,
696
+ setDefaultMaxTurns,
697
+ setGraceTurns,
729
698
  setDefaultJoinMode,
730
699
  setSchedulingEnabled,
731
700
  setScopeModels: setScopeModelsEnabled,
@@ -742,7 +711,7 @@ function default_1(pi) {
742
711
  // preserves Type.Object's inference when present and produces a
743
712
  // `schedule`-free schema when absent — zero LLM-context cost in disabled mode.
744
713
  const scheduleParamShape = {
745
- schedule: typebox_1.Type.Optional(typebox_1.Type.String({
714
+ schedule: Type.Optional(Type.String({
746
715
  description: 'Opt-in only — fire later instead of now. Omit to run immediately (the default, almost always correct). ' +
747
716
  'Formats: 6-field cron ("0 0 9 * * 1" = 9am Mon), interval ("5m"/"1h"), one-shot ("+10m" or ISO). ' +
748
717
  'Forces run_in_background; incompatible with inherit_context and resume. Returns job ID.',
@@ -758,7 +727,7 @@ function default_1(pi) {
758
727
  const compactAgentToolDescription = `Launch an autonomous agent for complex, multi-step tasks. Agent types:
759
728
  ${buildCompactTypeListText()}
760
729
 
761
- Custom agents: .pi/agents/<name>.md (project) or ${(0, pi_coding_agent_1.getAgentDir)()}/agents/<name>.md (global).
730
+ Custom agents: .pi/agents/<name>.md (project) or ${getAgentDir()}/agents/<name>.md (global).
762
731
 
763
732
  Notes:
764
733
  - description: 3-5 words (shown in UI). Prompts must be self-contained — the agent has not seen this conversation.
@@ -771,7 +740,7 @@ Notes:
771
740
  Available agent types and the tools they have access to:
772
741
  ${buildTypeListText()}
773
742
 
774
- Custom agents can be defined in .pi/agents/<name>.md (project) or ${(0, pi_coding_agent_1.getAgentDir)()}/agents/<name>.md (global) — they are picked up automatically. Project-level agents override global ones. Creating a .md file with the same name as a default agent overrides it.
743
+ Custom agents can be defined in .pi/agents/<name>.md (project) or ${getAgentDir()}/agents/<name>.md (global) — they are picked up automatically. Project-level agents override global ones. Creating a .md file with the same name as a default agent overrides it.
775
744
 
776
745
  When using the Agent tool, specify a subagent_type parameter to select which agent type to use.
777
746
 
@@ -816,7 +785,7 @@ Terse command-style prompts produce shallow, generic work.
816
785
  const vars = {
817
786
  typeList: buildTypeListText,
818
787
  compactTypeList: buildCompactTypeListText,
819
- agentDir: pi_coding_agent_1.getAgentDir,
788
+ agentDir: getAgentDir,
820
789
  scheduleGuideline: () => scheduleGuideline,
821
790
  };
822
791
  // Replacement callback (not a string) — agent descriptions may contain `$&` etc.
@@ -829,13 +798,13 @@ Terse command-style prompts produce shallow, generic work.
829
798
  };
830
799
  const loadCustomToolDescription = () => {
831
800
  for (const path of [
832
- (0, node_path_1.join)(process.cwd(), ".pi", "agent-tool-description.md"),
833
- (0, node_path_1.join)((0, pi_coding_agent_1.getAgentDir)(), "agent-tool-description.md"),
801
+ join(process.cwd(), ".pi", "agent-tool-description.md"),
802
+ join(getAgentDir(), "agent-tool-description.md"),
834
803
  ]) {
835
804
  try {
836
- if (!(0, node_fs_1.existsSync)(path))
805
+ if (!existsSync(path))
837
806
  continue;
838
- const text = (0, node_fs_1.readFileSync)(path, "utf-8").trim();
807
+ const text = readFileSync(path, "utf-8").trim();
839
808
  if (text)
840
809
  return renderToolDescriptionTemplate(text);
841
810
  console.warn(`[pi-subagents] ${path} is empty — ignoring`);
@@ -858,8 +827,8 @@ Terse command-style prompts produce shallow, generic work.
858
827
  }
859
828
  return fullAgentToolDescription;
860
829
  })();
861
- pi.registerTool((0, pi_coding_agent_1.defineTool)({
862
- name: agent_runner_js_1.SUBAGENT_TOOL_NAMES.AGENT,
830
+ pi.registerTool(defineTool({
831
+ name: SUBAGENT_TOOL_NAMES.AGENT,
863
832
  label: "Agent",
864
833
  description: agentToolDescription,
865
834
  promptSnippet: "Launch autonomous sub-agents for complex multi-step tasks",
@@ -869,54 +838,54 @@ Terse command-style prompts produce shallow, generic work.
869
838
  "When an agent runs in the background, you will be notified on completion — do not poll or sleep waiting for it. Continue with other work instead.",
870
839
  "Trust but verify: an agent's summary describes intent, not outcome. When an agent writes or edits code, check the actual changes before reporting work as done.",
871
840
  ],
872
- parameters: typebox_1.Type.Object({
873
- prompt: typebox_1.Type.String({
841
+ parameters: Type.Object({
842
+ prompt: Type.String({
874
843
  description: "The task for the agent to perform.",
875
844
  }),
876
- description: typebox_1.Type.String({
845
+ description: Type.String({
877
846
  description: "A short (3-5 word) description of the task (shown in UI).",
878
847
  }),
879
- subagent_type: typebox_1.Type.String({
880
- description: `The type of specialized agent to use. Available types: ${(0, agent_types_js_1.getAvailableTypes)().join(", ")}. Custom agents from .pi/agents/*.md (project) or ${(0, pi_coding_agent_1.getAgentDir)()}/agents/*.md (global) are also available.`,
848
+ subagent_type: Type.String({
849
+ description: `The type of specialized agent to use. Available types: ${getAvailableTypes().join(", ")}. Custom agents from .pi/agents/*.md (project) or ${getAgentDir()}/agents/*.md (global) are also available.`,
881
850
  }),
882
- model: typebox_1.Type.Optional(typebox_1.Type.String({
851
+ model: Type.Optional(Type.String({
883
852
  description: 'Optional model override. Accepts "provider/modelId" or fuzzy name (e.g. "haiku", "sonnet"). Omit to use the agent type\'s default.',
884
853
  })),
885
- thinking: typebox_1.Type.Optional(typebox_1.Type.String({
854
+ thinking: Type.Optional(Type.String({
886
855
  description: `Thinking level: ${THINKING_LEVELS.join(", ")}. Overrides agent default.`,
887
856
  })),
888
- max_turns: typebox_1.Type.Optional(typebox_1.Type.Number({
857
+ max_turns: Type.Optional(Type.Number({
889
858
  description: "Maximum number of agentic turns before stopping. Omit for unlimited (default).",
890
859
  minimum: 1,
891
860
  })),
892
- run_in_background: typebox_1.Type.Optional(typebox_1.Type.Boolean({
861
+ run_in_background: Type.Optional(Type.Boolean({
893
862
  description: "Set to true to run in background. Returns agent ID immediately. You will be notified on completion.",
894
863
  })),
895
- resume: typebox_1.Type.Optional(typebox_1.Type.String({
864
+ resume: Type.Optional(Type.String({
896
865
  description: "Optional agent ID to resume from. Continues from previous context.",
897
866
  })),
898
- isolated: typebox_1.Type.Optional(typebox_1.Type.Boolean({
867
+ isolated: Type.Optional(Type.Boolean({
899
868
  description: "If true, agent gets no extension/MCP tools — only built-in tools.",
900
869
  })),
901
- inherit_context: typebox_1.Type.Optional(typebox_1.Type.Boolean({
870
+ inherit_context: Type.Optional(Type.Boolean({
902
871
  description: "If true, fork parent conversation into the agent. Default: false (fresh context).",
903
872
  })),
904
- isolation: typebox_1.Type.Optional(typebox_1.Type.Literal("worktree", {
873
+ isolation: Type.Optional(Type.Literal("worktree", {
905
874
  description: 'Set to "worktree" to run the agent in a temporary git worktree (isolated copy of the repo). Changes are saved to a branch on completion.',
906
875
  })),
907
876
  ...scheduleParam,
908
877
  }),
909
878
  // ---- Custom rendering: Claude Code style ----
910
879
  renderCall(args, theme) {
911
- const displayName = args.subagent_type ? (0, agent_widget_js_1.getDisplayName)(args.subagent_type) : "Agent";
880
+ const displayName = args.subagent_type ? getDisplayName(args.subagent_type) : "Agent";
912
881
  const desc = args.description ?? "";
913
- return new pi_tui_1.Text("▸ " + theme.fg("toolTitle", theme.bold(displayName)) + (desc ? " " + theme.fg("muted", desc) : ""), 0, 0);
882
+ return new Text("▸ " + theme.fg("toolTitle", theme.bold(displayName)) + (desc ? " " + theme.fg("muted", desc) : ""), 0, 0);
914
883
  },
915
884
  renderResult(result, { expanded, isPartial }, theme) {
916
885
  const details = result.details;
917
886
  if (!details) {
918
887
  const text = result.content[0]?.type === "text" ? result.content[0].text : "";
919
- return new pi_tui_1.Text(text, 0, 0);
888
+ return new Text(text, 0, 0);
920
889
  }
921
890
  // Helper: build "haiku · thinking: high · ↻5≤30 · 3 tool uses · 33.8k tokens" stats string
922
891
  const stats = (d) => {
@@ -926,27 +895,27 @@ Terse command-style prompts produce shallow, generic work.
926
895
  if (d.tags)
927
896
  parts.push(...d.tags);
928
897
  if (d.turnCount != null && d.turnCount > 0) {
929
- parts.push((0, agent_widget_js_1.formatTurns)(d.turnCount, d.maxTurns));
898
+ parts.push(formatTurns(d.turnCount, d.maxTurns));
930
899
  }
931
900
  if (d.toolUses > 0)
932
901
  parts.push(`${d.toolUses} tool use${d.toolUses === 1 ? "" : "s"}`);
933
902
  if (d.tokens)
934
903
  parts.push(d.tokens);
935
- return parts.map(p => (0, agent_widget_js_1.fgPreservingNestedStyles)(theme, "dim", p)).join(" " + theme.fg("dim", "·") + " ");
904
+ return parts.map(p => fgPreservingNestedStyles(theme, "dim", p)).join(" " + theme.fg("dim", "·") + " ");
936
905
  };
937
906
  // ---- While running (streaming) ----
938
907
  if (isPartial || details.status === "running") {
939
- const frame = agent_widget_js_1.SPINNER[details.spinnerFrame ?? 0];
908
+ const frame = SPINNER[details.spinnerFrame ?? 0];
940
909
  const s = stats(details);
941
910
  return renderRunningAgentStatus(frame, s, details.activity ?? "thinking…", theme);
942
911
  }
943
912
  // ---- Background agent launched ----
944
913
  if (details.status === "background") {
945
- return new pi_tui_1.Text(theme.fg("dim", ` ⎿ Running in background (ID: ${details.agentId})`), 0, 0);
914
+ return new Text(theme.fg("dim", ` ⎿ Running in background (ID: ${details.agentId})`), 0, 0);
946
915
  }
947
916
  // ---- Completed / Steered ----
948
917
  if (details.status === "completed" || details.status === "steered") {
949
- const duration = (0, agent_widget_js_1.formatMs)(details.durationMs);
918
+ const duration = formatMs(details.durationMs);
950
919
  const isSteered = details.status === "steered";
951
920
  const icon = isSteered ? theme.fg("warning", "✓") : theme.fg("success", "✓");
952
921
  const s = stats(details);
@@ -954,28 +923,28 @@ Terse command-style prompts produce shallow, generic work.
954
923
  line += " " + theme.fg("dim", "·") + " " + theme.fg("dim", duration);
955
924
  if (expanded) {
956
925
  const resultText = result.content[0]?.type === "text" ? result.content[0].text : "";
957
- const container = new pi_tui_1.Container();
958
- container.addChild(new pi_tui_1.Text(line, 0, 0));
959
926
  if (resultText) {
960
- container.addChild((0, markdown_result_js_1.createMarkdownResult)(resultText, theme, 50));
927
+ const lines = resultText.split("\n").slice(0, 50);
928
+ for (const l of lines) {
929
+ line += "\n" + theme.fg("dim", ` ${l}`);
930
+ }
961
931
  if (resultText.split("\n").length > 50) {
962
- container.addChild(new pi_tui_1.Text(theme.fg("muted", " ... (use get_subagent_result with verbose for full output)"), 0, 0));
932
+ line += "\n" + theme.fg("muted", " ... (use get_subagent_result with verbose for full output)");
963
933
  }
964
934
  }
965
- return container;
966
935
  }
967
936
  else {
968
937
  const doneText = isSteered ? "Wrapped up (turn limit)" : "Done";
969
938
  line += "\n" + theme.fg("dim", ` ⎿ ${doneText}`);
970
939
  }
971
- return new pi_tui_1.Text(line, 0, 0);
940
+ return new Text(line, 0, 0);
972
941
  }
973
942
  // ---- Stopped (user-initiated abort) ----
974
943
  if (details.status === "stopped") {
975
944
  const s = stats(details);
976
945
  let line = theme.fg("dim", "■") + (s ? " " + s : "");
977
946
  line += "\n" + theme.fg("dim", " ⎿ Stopped");
978
- return new pi_tui_1.Text(line, 0, 0);
947
+ return new Text(line, 0, 0);
979
948
  }
980
949
  // ---- Error / Aborted (hard max_turns) ----
981
950
  const s = stats(details);
@@ -986,7 +955,7 @@ Terse command-style prompts produce shallow, generic work.
986
955
  else {
987
956
  line += "\n" + theme.fg("warning", " ⎿ Aborted (max turns exceeded)");
988
957
  }
989
- return new pi_tui_1.Text(line, 0, 0);
958
+ return new Text(line, 0, 0);
990
959
  },
991
960
  // ---- Execute ----
992
961
  execute: async (toolCallId, params, signal, onUpdate, ctx) => {
@@ -995,17 +964,17 @@ Terse command-style prompts produce shallow, generic work.
995
964
  // Reload custom agents so new project/global .md files are picked up without restart
996
965
  reloadCustomAgents();
997
966
  const rawType = params.subagent_type;
998
- const resolved = (0, agent_types_js_1.resolveType)(rawType);
967
+ const resolved = resolveType(rawType);
999
968
  const subagentType = resolved ?? "general-purpose";
1000
969
  const fellBack = resolved === undefined;
1001
- const displayName = (0, agent_widget_js_1.getDisplayName)(subagentType);
970
+ const displayName = getDisplayName(subagentType);
1002
971
  // Get agent config (if any)
1003
- const customConfig = (0, agent_types_js_1.getAgentConfig)(subagentType);
1004
- const resolvedConfig = (0, invocation_config_js_1.resolveAgentInvocationConfig)(customConfig, params);
972
+ const customConfig = getAgentConfig(subagentType);
973
+ const resolvedConfig = resolveAgentInvocationConfig(customConfig, params);
1005
974
  // Resolve model from agent config first; tool-call params only fill gaps.
1006
975
  let model = ctx.model;
1007
976
  if (resolvedConfig.modelInput) {
1008
- const resolved = (0, model_resolver_js_1.resolveModel)(resolvedConfig.modelInput, ctx.modelRegistry);
977
+ const resolved = resolveModel(resolvedConfig.modelInput, ctx.modelRegistry);
1009
978
  if (typeof resolved === "string") {
1010
979
  if (resolvedConfig.modelFromParams)
1011
980
  return textResult(resolved);
@@ -1025,8 +994,8 @@ Terse command-style prompts produce shallow, generic work.
1025
994
  // user authored/installed this agent or chose the parent's model; trust it).
1026
995
  // See SubagentsSettings.scopeModels docstring for the full policy.
1027
996
  if (isScopeModelsEnabled() && model) {
1028
- const allowed = (0, enabled_models_js_1.resolveEnabledModels)((0, enabled_models_js_1.readEnabledModels)(ctx.cwd), ctx.modelRegistry, ctx.cwd);
1029
- if (allowed && !(0, enabled_models_js_1.isModelInScope)(model, allowed)) {
997
+ const allowed = resolveEnabledModels(readEnabledModels(ctx.cwd), ctx.modelRegistry, ctx.cwd);
998
+ if (allowed && !isModelInScope(model, allowed)) {
1030
999
  if (resolvedConfig.modelFromParams) {
1031
1000
  const list = [...allowed].sort().map(m => ` ${m}`).join("\n");
1032
1001
  return textResult(`Model not in scope: "${resolvedConfig.modelInput}".\n\n` +
@@ -1052,20 +1021,17 @@ Terse command-style prompts produce shallow, generic work.
1052
1021
  const attachTranscript = (rec, agentId) => {
1053
1022
  if (!rec || !outputTranscript)
1054
1023
  return;
1055
- rec.outputFile = (0, output_file_js_1.createOutputFilePath)(ctx.cwd, agentId, ctx.sessionManager.getSessionId());
1056
- (0, output_file_js_1.writeInitialEntry)(rec.outputFile, agentId, params.prompt, ctx.cwd);
1057
- // Keep the existing /tmp output for compatibility, while also writing a
1058
- // durable project-local copy for reload-safe, read-only history viewing.
1024
+ rec.outputFile = createOutputFilePath(ctx.cwd, agentId, ctx.sessionManager.getSessionId());
1025
+ writeInitialEntry(rec.outputFile, agentId, params.prompt, ctx.cwd);
1059
1026
  try {
1060
- rec.historyFile = (0, agent_history_js_1.createAgentHistoryPath)(ctx.cwd, agentId, subagentType);
1061
- rec.transcriptPath = (0, agent_history_js_1.agentHistoryLocator)(ctx.cwd, rec.historyFile);
1062
- (0, output_file_js_1.writeInitialEntry)(rec.historyFile, agentId, params.prompt, ctx.cwd);
1027
+ rec.historyFile = createAgentHistoryPath(ctx.cwd, agentId);
1028
+ rec.transcriptPath = agentHistoryLocator(ctx.cwd, rec.historyFile);
1029
+ writeInitialEntry(rec.historyFile, agentId, params.prompt, ctx.cwd);
1063
1030
  }
1064
1031
  catch (err) {
1065
- // History is best effort; never disable the existing output transcript.
1066
1032
  rec.historyFile = undefined;
1067
1033
  rec.transcriptPath = undefined;
1068
- console.warn("[pi-subagents] Failed to create durable transcript:", err);
1034
+ ctx.ui.notify(`Could not create durable transcript for agent ${agentId}: ${err instanceof Error ? err.message : String(err)}`, "warning");
1069
1035
  }
1070
1036
  };
1071
1037
  const parentModelId = ctx.model?.id;
@@ -1073,21 +1039,23 @@ Terse command-style prompts produce shallow, generic work.
1073
1039
  const modelName = effectiveModelId && effectiveModelId !== parentModelId
1074
1040
  ? (model?.name ?? effectiveModelId).replace(/^Claude\s+/i, "").toLowerCase()
1075
1041
  : undefined;
1076
- const effectiveMaxTurns = (0, agent_runner_js_1.normalizeMaxTurns)(resolvedConfig.maxTurns ?? (0, agent_runner_js_1.getDefaultMaxTurns)());
1042
+ const effectiveMaxTurns = normalizeMaxTurns(resolvedConfig.maxTurns ?? getDefaultMaxTurns());
1077
1043
  const agentInvocation = {
1078
1044
  modelName,
1045
+ effectiveModelName: model?.name ?? model?.id ?? ctx.model?.name ?? ctx.model?.id,
1079
1046
  thinking,
1047
+ effectiveThinking: thinking,
1080
1048
  // Explicit value only — the default fallback would just add noise.
1081
1049
  // Normalize so `0` (unlimited) doesn't surface as a misleading "max turns: 0".
1082
- maxTurns: (0, agent_runner_js_1.normalizeMaxTurns)(resolvedConfig.maxTurns),
1050
+ maxTurns: normalizeMaxTurns(resolvedConfig.maxTurns),
1083
1051
  isolated,
1084
1052
  inheritContext,
1085
1053
  runInBackground,
1086
1054
  isolation,
1087
1055
  };
1088
1056
  // Tool-result render shows the mode label too; viewer's header already does.
1089
- const modeLabel = (0, agent_widget_js_1.getPromptModeLabel)(subagentType);
1090
- const { tags: invocationTags } = (0, agent_widget_js_1.buildInvocationTags)(agentInvocation);
1057
+ const modeLabel = getPromptModeLabel(subagentType);
1058
+ const { tags: invocationTags } = buildInvocationTags(agentInvocation);
1091
1059
  const agentTags = modeLabel ? [modeLabel, ...invocationTags] : invocationTags;
1092
1060
  const detailBase = {
1093
1061
  displayName,
@@ -1167,7 +1135,7 @@ Terse command-style prompts produce shallow, generic work.
1167
1135
  origBgOnSession(session);
1168
1136
  const rec = manager.getRecord(id);
1169
1137
  if (rec?.outputFile) {
1170
- rec.outputCleanup = (0, output_file_js_1.streamToOutputFile)(session, rec.outputFile, id, ctx.cwd, rec.historyFile);
1138
+ rec.outputCleanup = streamToOutputFile(session, rec.outputFile, id, ctx.cwd, rec.historyFile);
1171
1139
  }
1172
1140
  };
1173
1141
  try {
@@ -1189,7 +1157,7 @@ Terse command-style prompts produce shallow, generic work.
1189
1157
  }
1190
1158
  // Set output file + join mode synchronously after spawn, before the
1191
1159
  // event loop yields — onSessionCreated is async so this is safe.
1192
- const joinMode = (0, invocation_config_js_1.resolveJoinMode)(defaultJoinMode, true);
1160
+ const joinMode = resolveJoinMode(defaultJoinMode, true);
1193
1161
  const record = manager.getRecord(id);
1194
1162
  if (record && joinMode) {
1195
1163
  record.joinMode = joinMode;
@@ -1244,8 +1212,8 @@ Terse command-style prompts produce shallow, generic work.
1244
1212
  maxTurns: fgState.maxTurns,
1245
1213
  durationMs: Date.now() - startedAt,
1246
1214
  status: "running",
1247
- activity: (0, agent_widget_js_1.describeActivity)(fgState.activeTools, fgState.responseText),
1248
- spinnerFrame: spinnerFrame % agent_widget_js_1.SPINNER.length,
1215
+ activity: describeActivity(fgState.activeTools, fgState.responseText),
1216
+ spinnerFrame: spinnerFrame % SPINNER.length,
1249
1217
  };
1250
1218
  onUpdate?.({
1251
1219
  content: [{ type: "text", text: `${fgState.toolUses} tool uses...` }],
@@ -1273,7 +1241,7 @@ Terse command-style prompts produce shallow, generic work.
1273
1241
  if (fgId) {
1274
1242
  const rec = manager.getRecord(fgId);
1275
1243
  if (rec?.outputFile) {
1276
- rec.outputCleanup = (0, output_file_js_1.streamToOutputFile)(session, rec.outputFile, fgId, ctx.cwd, rec.historyFile);
1244
+ rec.outputCleanup = streamToOutputFile(session, rec.outputFile, fgId, ctx.cwd, rec.historyFile);
1277
1245
  }
1278
1246
  }
1279
1247
  };
@@ -1321,7 +1289,7 @@ Terse command-style prompts produce shallow, generic work.
1321
1289
  // "general-purpose" may itself be unregistered (defaults disabled, no
1322
1290
  // user override) — getConfig then uses the hardcoded fallback config.
1323
1291
  const fallbackNote = fellBack
1324
- ? `Note: Unknown agent type "${rawType}" — using ${(0, agent_types_js_1.resolveType)("general-purpose") ? "general-purpose" : "the fallback agent config"}.\n\n`
1292
+ ? `Note: Unknown agent type "${rawType}" — using ${resolveType("general-purpose") ? "general-purpose" : "the fallback agent config"}.\n\n`
1325
1293
  : "";
1326
1294
  if (record.status === "error") {
1327
1295
  // Error headline + any partial output the run produced before failing.
@@ -1331,24 +1299,24 @@ Terse command-style prompts produce shallow, generic work.
1331
1299
  const statsParts = [`${record.toolUses} tool uses`];
1332
1300
  if (tokenText)
1333
1301
  statsParts.push(tokenText);
1334
- return textResult(`${fallbackNote}Agent completed in ${(0, agent_widget_js_1.formatMs)(durationMs)} (${statsParts.join(", ")})${(0, status_note_js_1.getStatusNote)(record.status)}.\n\n` +
1302
+ return textResult(`${fallbackNote}Agent completed in ${formatMs(durationMs)} (${statsParts.join(", ")})${getStatusNote(record.status)}.\n\n` +
1335
1303
  (record.result?.trim() || "No output."), details);
1336
1304
  },
1337
1305
  }));
1338
1306
  // ---- get_subagent_result tool ----
1339
- pi.registerTool((0, pi_coding_agent_1.defineTool)({
1340
- name: agent_runner_js_1.SUBAGENT_TOOL_NAMES.GET_RESULT,
1307
+ pi.registerTool(defineTool({
1308
+ name: SUBAGENT_TOOL_NAMES.GET_RESULT,
1341
1309
  label: "Get Agent Result",
1342
1310
  description: "Check status and retrieve results from a background agent. Use the agent ID returned by Agent with run_in_background.",
1343
1311
  promptSnippet: "Check status and retrieve results from a background agent",
1344
- parameters: typebox_1.Type.Object({
1345
- agent_id: typebox_1.Type.String({
1312
+ parameters: Type.Object({
1313
+ agent_id: Type.String({
1346
1314
  description: "The agent ID to check.",
1347
1315
  }),
1348
- wait: typebox_1.Type.Optional(typebox_1.Type.Boolean({
1316
+ wait: Type.Optional(Type.Boolean({
1349
1317
  description: "If true, wait for the agent to complete before returning. Default: false.",
1350
1318
  })),
1351
- verbose: typebox_1.Type.Optional(typebox_1.Type.Boolean({
1319
+ verbose: Type.Optional(Type.Boolean({
1352
1320
  description: "If true, include the agent's full conversation (messages + tool calls). Default: false.",
1353
1321
  })),
1354
1322
  }),
@@ -1369,10 +1337,10 @@ Terse command-style prompts produce shallow, generic work.
1369
1337
  if (record.promise)
1370
1338
  await abortable(record.promise, signal);
1371
1339
  }
1372
- const displayName = (0, agent_widget_js_1.getDisplayName)(record.type);
1373
- const duration = (0, agent_widget_js_1.formatDuration)(record.startedAt, record.completedAt);
1340
+ const displayName = getDisplayName(record.type);
1341
+ const duration = formatDuration(record.startedAt, record.completedAt);
1374
1342
  const tokens = formatLifetimeTokens(record);
1375
- const contextPercent = (0, usage_js_1.getSessionContextPercent)(record.session);
1343
+ const contextPercent = getSessionContextPercent(record.session);
1376
1344
  const statsParts = [`Tool uses: ${record.toolUses}`];
1377
1345
  if (tokens)
1378
1346
  statsParts.push(tokens);
@@ -1382,7 +1350,7 @@ Terse command-style prompts produce shallow, generic work.
1382
1350
  statsParts.push(`Compactions: ${record.compactionCount}`);
1383
1351
  statsParts.push(`Duration: ${duration}`);
1384
1352
  let output = `Agent: ${record.id}\n` +
1385
- `Type: ${displayName} | Status: ${record.status}${(0, status_note_js_1.getStatusNote)(record.status)} | ${statsParts.join(" | ")}\n` +
1353
+ `Type: ${displayName} | Status: ${record.status}${getStatusNote(record.status)} | ${statsParts.join(" | ")}\n` +
1386
1354
  `Description: ${record.description}\n\n`;
1387
1355
  if (record.status === "running") {
1388
1356
  output += "Agent is still running. Use wait: true or check back later.";
@@ -1400,7 +1368,7 @@ Terse command-style prompts produce shallow, generic work.
1400
1368
  }
1401
1369
  // Verbose: include full conversation
1402
1370
  if (params.verbose && record.session) {
1403
- const conversation = (0, agent_runner_js_1.getAgentConversation)(record.session);
1371
+ const conversation = getAgentConversation(record.session);
1404
1372
  if (conversation) {
1405
1373
  output += `\n\n--- Agent Conversation ---\n${conversation}`;
1406
1374
  }
@@ -1409,17 +1377,17 @@ Terse command-style prompts produce shallow, generic work.
1409
1377
  },
1410
1378
  }));
1411
1379
  // ---- steer_subagent tool ----
1412
- pi.registerTool((0, pi_coding_agent_1.defineTool)({
1413
- name: agent_runner_js_1.SUBAGENT_TOOL_NAMES.STEER,
1380
+ pi.registerTool(defineTool({
1381
+ name: SUBAGENT_TOOL_NAMES.STEER,
1414
1382
  label: "Steer Agent",
1415
1383
  description: "Send a steering message to a running agent. The message will interrupt the agent after its current tool execution " +
1416
1384
  "and be injected into its conversation, allowing you to redirect its work mid-run. Only works on running agents.",
1417
1385
  promptSnippet: "Send a steering message to redirect a running background agent",
1418
- parameters: typebox_1.Type.Object({
1419
- agent_id: typebox_1.Type.String({
1386
+ parameters: Type.Object({
1387
+ agent_id: Type.String({
1420
1388
  description: "The agent ID to steer (must be currently running).",
1421
1389
  }),
1422
- message: typebox_1.Type.String({
1390
+ message: Type.String({
1423
1391
  description: "The steering message to send. This will appear as a user message in the agent's conversation.",
1424
1392
  }),
1425
1393
  }),
@@ -1440,10 +1408,10 @@ Terse command-style prompts produce shallow, generic work.
1440
1408
  return textResult(`Steering message queued for agent ${record.id}. It will be delivered once the session initializes.`);
1441
1409
  }
1442
1410
  try {
1443
- await (0, agent_runner_js_1.steerAgent)(record.session, params.message);
1411
+ await steerAgent(record.session, params.message);
1444
1412
  pi.events.emit("subagents:steered", { id: record.id, message: params.message });
1445
1413
  const tokens = formatLifetimeTokens(record);
1446
- const contextPercent = (0, usage_js_1.getSessionContextPercent)(record.session);
1414
+ const contextPercent = getSessionContextPercent(record.session);
1447
1415
  const stateParts = [];
1448
1416
  if (tokens)
1449
1417
  stateParts.push(tokens);
@@ -1461,30 +1429,30 @@ Terse command-style prompts produce shallow, generic work.
1461
1429
  },
1462
1430
  }));
1463
1431
  // ---- /agents interactive menu ----
1464
- const projectAgentsDir = () => (0, node_path_1.join)(process.cwd(), ".pi", "agents");
1465
- const workspaceAgentsDir = () => (0, node_path_1.join)(process.cwd(), ".agents", "agents");
1466
- const personalAgentsDir = () => (0, node_path_1.join)((0, pi_coding_agent_1.getAgentDir)(), "agents");
1432
+ const projectAgentsDir = () => join(process.cwd(), ".pi", "agents");
1433
+ const workspaceAgentsDir = () => join(process.cwd(), ".agents", "agents");
1434
+ const personalAgentsDir = () => join(getAgentDir(), "agents");
1467
1435
  /** Find the file path of a custom agent by name, in discovery-precedence order (project, workspace, then global). */
1468
1436
  function findAgentFile(name) {
1469
- const projectPath = (0, node_path_1.join)(projectAgentsDir(), `${name}.md`);
1470
- if ((0, node_fs_1.existsSync)(projectPath))
1437
+ const projectPath = join(projectAgentsDir(), `${name}.md`);
1438
+ if (existsSync(projectPath))
1471
1439
  return { path: projectPath, location: "project" };
1472
- const workspacePath = (0, node_path_1.join)(workspaceAgentsDir(), `${name}.md`);
1473
- if ((0, node_fs_1.existsSync)(workspacePath))
1440
+ const workspacePath = join(workspaceAgentsDir(), `${name}.md`);
1441
+ if (existsSync(workspacePath))
1474
1442
  return { path: workspacePath, location: "workspace" };
1475
- const personalPath = (0, node_path_1.join)(personalAgentsDir(), `${name}.md`);
1476
- if ((0, node_fs_1.existsSync)(personalPath))
1443
+ const personalPath = join(personalAgentsDir(), `${name}.md`);
1444
+ if (existsSync(personalPath))
1477
1445
  return { path: personalPath, location: "personal" };
1478
1446
  return undefined;
1479
1447
  }
1480
1448
  function getModelLabel(type, registry) {
1481
- const cfg = (0, agent_types_js_1.getAgentConfig)(type);
1449
+ const cfg = getAgentConfig(type);
1482
1450
  if (!cfg?.model)
1483
1451
  return "inherit"; // no model configured → really inherits parent
1484
1452
  const label = getModelLabelFromConfig(cfg.model);
1485
1453
  if (!registry)
1486
1454
  return label;
1487
- const resolved = (0, model_resolver_js_1.resolveModel)(cfg.model, registry);
1455
+ const resolved = resolveModel(cfg.model, registry);
1488
1456
  // Configured but unresolvable: the runtime silently falls back to the parent
1489
1457
  // model, so flag it (and the fallback) rather than hiding the config.
1490
1458
  if (typeof resolved === "string")
@@ -1500,18 +1468,13 @@ Terse command-style prompts produce shallow, generic work.
1500
1468
  }
1501
1469
  async function showAgentsMenu(ctx) {
1502
1470
  reloadCustomAgents();
1503
- const allNames = (0, agent_types_js_1.getAllTypes)();
1471
+ const allNames = getAllTypes();
1504
1472
  // Build select options
1505
1473
  const options = [];
1506
- // Only advertise agents that can actually be opened. Reload-restored
1507
- // metadata without a live session or durable transcript is intentionally
1508
- // invisible here, matching FleetView and showRunningAgents below.
1509
- const agents = manager.listAgents().filter((record) => record.session !== undefined || (0, agent_history_js_1.hasAgentHistory)(ctx.cwd, record.transcriptPath));
1510
- if (agents.length > 0) {
1511
- const running = agents.filter(a => a.status === "running" || a.status === "queued").length;
1512
- const done = agents.filter(a => a.status === "completed" || a.status === "steered").length;
1513
- options.push(`Running agents (${agents.length}) — ${running} running, ${done} done`);
1514
- }
1474
+ // Keep active agents and terminal history in separate menu entries.
1475
+ const records = manager.listAgents();
1476
+ const { active, history } = splitAgentRecords(records, ctx.cwd);
1477
+ options.push(...buildAgentStatusMenuEntries(records, ctx.cwd));
1515
1478
  // Agent types list
1516
1479
  if (allNames.length > 0) {
1517
1480
  options.push(`Agent types (${allNames.length})`);
@@ -1524,7 +1487,7 @@ Terse command-style prompts produce shallow, generic work.
1524
1487
  // Actions
1525
1488
  options.push("Create new agent");
1526
1489
  options.push("Settings");
1527
- const noAgentsMsg = allNames.length === 0 && agents.length === 0
1490
+ const noAgentsMsg = allNames.length === 0 && active.length === 0 && history.length === 0
1528
1491
  ? "No agents found. Create specialized subagents that can be delegated to.\n\n" +
1529
1492
  "Each subagent has its own context window, custom system prompt, and specific tools.\n\n" +
1530
1493
  "Try creating: Code Reviewer, Security Auditor, Test Writer, or Documentation Writer.\n\n"
@@ -1539,12 +1502,16 @@ Terse command-style prompts produce shallow, generic work.
1539
1502
  await showRunningAgents(ctx);
1540
1503
  await showAgentsMenu(ctx);
1541
1504
  }
1505
+ else if (choice.startsWith("Agent history (")) {
1506
+ await showAgentHistory(ctx);
1507
+ await showAgentsMenu(ctx);
1508
+ }
1542
1509
  else if (choice.startsWith("Agent types (")) {
1543
1510
  await showAllAgentsList(ctx);
1544
1511
  await showAgentsMenu(ctx);
1545
1512
  }
1546
1513
  else if (choice.startsWith("Scheduled jobs (")) {
1547
- await (0, schedule_menu_js_1.showSchedulesMenu)(ctx, scheduler);
1514
+ await showSchedulesMenu(ctx, scheduler);
1548
1515
  await showAgentsMenu(ctx);
1549
1516
  }
1550
1517
  else if (choice === "Create new agent") {
@@ -1556,7 +1523,7 @@ Terse command-style prompts produce shallow, generic work.
1556
1523
  }
1557
1524
  }
1558
1525
  async function showAllAgentsList(ctx) {
1559
- const allNames = (0, agent_types_js_1.getAllTypes)();
1526
+ const allNames = getAllTypes();
1560
1527
  if (allNames.length === 0) {
1561
1528
  ctx.ui.notify("No agents.", "info");
1562
1529
  return;
@@ -1577,7 +1544,7 @@ Terse command-style prompts produce shallow, generic work.
1577
1544
  // full description renders below the highlighted row via SettingsList,
1578
1545
  // exactly like the Settings menu — so long descriptions never wrap the list.
1579
1546
  const items = allNames.map(name => {
1580
- const cfg = (0, agent_types_js_1.getAgentConfig)(name);
1547
+ const cfg = getAgentConfig(name);
1581
1548
  const disabled = cfg?.enabled === false;
1582
1549
  const model = getModelLabel(name, ctx.modelRegistry);
1583
1550
  return {
@@ -1590,22 +1557,22 @@ Terse command-style prompts produce shallow, generic work.
1590
1557
  values: [model],
1591
1558
  };
1592
1559
  });
1593
- const hasCustom = allNames.some(n => { const c = (0, agent_types_js_1.getAgentConfig)(n); return c && !c.isDefault && c.enabled !== false; });
1594
- const hasDisabled = allNames.some(n => (0, agent_types_js_1.getAgentConfig)(n)?.enabled === false);
1560
+ const hasCustom = allNames.some(n => { const c = getAgentConfig(n); return c && !c.isDefault && c.enabled !== false; });
1561
+ const hasDisabled = allNames.some(n => getAgentConfig(n)?.enabled === false);
1595
1562
  const legendParts = [];
1596
1563
  if (hasCustom)
1597
1564
  legendParts.push("• = project ◦ = global");
1598
1565
  if (hasDisabled)
1599
1566
  legendParts.push("✕ = disabled");
1600
1567
  const selected = await ctx.ui.custom((_tui, _theme, _kb, done) => {
1601
- const slTheme = (0, pi_coding_agent_1.getSettingsListTheme)();
1602
- const list = new pi_tui_1.SettingsList(items, Math.min(items.length, 12), slTheme, id => done(id), // Enter/Space on a row → return that agent's name
1568
+ const slTheme = getSettingsListTheme();
1569
+ const list = new SettingsList(items, Math.min(items.length, 12), slTheme, id => done(id), // Enter/Space on a row → return that agent's name
1603
1570
  () => done(undefined));
1604
- const container = new pi_tui_1.Container();
1605
- container.addChild(new pi_tui_1.Text("Agent types", 0, 0));
1571
+ const container = new Container();
1572
+ container.addChild(new Text("Agent types", 0, 0));
1606
1573
  if (legendParts.length)
1607
- container.addChild(new pi_tui_1.Text(slTheme.hint(legendParts.join(" ")), 0, 0));
1608
- container.addChild(new pi_tui_1.Spacer(1));
1574
+ container.addChild(new Text(slTheme.hint(legendParts.join(" ")), 0, 0));
1575
+ container.addChild(new Spacer(1));
1609
1576
  container.addChild(list);
1610
1577
  return {
1611
1578
  render: (w) => container.render(w),
@@ -1613,65 +1580,111 @@ Terse command-style prompts produce shallow, generic work.
1613
1580
  handleInput: (data) => list.handleInput?.(data),
1614
1581
  };
1615
1582
  });
1616
- if (selected && (0, agent_types_js_1.getAgentConfig)(selected)) {
1583
+ if (selected && getAgentConfig(selected)) {
1617
1584
  await showAgentDetail(ctx, selected);
1618
1585
  await showAllAgentsList(ctx);
1619
1586
  }
1620
1587
  }
1588
+ function makeUniqueAgentOptionLabels(pairs) {
1589
+ const counts = new Map();
1590
+ for (const pair of pairs)
1591
+ counts.set(pair.label, (counts.get(pair.label) ?? 0) + 1);
1592
+ const used = new Set();
1593
+ return pairs.map((pair) => {
1594
+ const { record, label } = pair;
1595
+ if ((counts.get(label) ?? 0) === 1) {
1596
+ used.add(label);
1597
+ return label;
1598
+ }
1599
+ const suffix = ` · #${record.id.slice(-8)}`;
1600
+ let candidate = `${label}${suffix}`;
1601
+ let n = 2;
1602
+ while (used.has(candidate))
1603
+ candidate = `${label}${suffix}-${n++}`;
1604
+ used.add(candidate);
1605
+ pair.label = candidate;
1606
+ return candidate;
1607
+ });
1608
+ }
1621
1609
  async function showRunningAgents(ctx) {
1622
- const agents = manager.listAgents().filter((record) => record.session !== undefined || (0, agent_history_js_1.hasAgentHistory)(ctx.cwd, record.transcriptPath));
1610
+ const { active: agents } = splitAgentRecords(manager.listAgents(), ctx.cwd);
1623
1611
  if (agents.length === 0) {
1624
1612
  ctx.ui.notify("No agents.", "info");
1625
1613
  return;
1626
1614
  }
1627
- const options = agents.map(a => {
1628
- const dn = (0, agent_widget_js_1.getDisplayName)(a.type);
1629
- const dur = (0, agent_widget_js_1.formatDuration)(a.startedAt, a.completedAt);
1630
- return `${dn} (${a.description}) · ${a.toolUses} tools · ${a.status} · ${dur}`;
1615
+ const pairs = agents.map((record) => {
1616
+ const dn = getDisplayName(record.type);
1617
+ const dur = formatDuration(record.startedAt, record.completedAt);
1618
+ return { record, label: `${dn} (${record.description}) · ${record.toolUses} tools · ${record.status} · ${dur}` };
1631
1619
  });
1620
+ const options = makeUniqueAgentOptionLabels(pairs);
1632
1621
  const choice = await ctx.ui.select("Running agents", options);
1633
1622
  if (!choice)
1634
1623
  return;
1635
- // Find the selected agent by matching the option index
1636
- const idx = options.indexOf(choice);
1637
- if (idx < 0)
1624
+ const record = pairs.find((pair) => pair.label === choice)?.record;
1625
+ if (!record)
1638
1626
  return;
1639
- const record = agents[idx];
1640
- await viewAgentConversation(ctx, record);
1627
+ await viewAgentConversation(ctx, record, "live");
1641
1628
  // Back-navigation: re-show the list
1642
1629
  await showRunningAgents(ctx);
1643
1630
  }
1644
- async function viewAgentConversation(ctx, record) {
1645
- if (!record.session) {
1646
- ctx.ui.notify(`Agent is ${record.status === "queued" ? "queued" : "expired"} — no session available.`, "info");
1631
+ async function showAgentHistory(ctx) {
1632
+ const { history } = splitAgentRecords(manager.listAgents(), ctx.cwd);
1633
+ if (history.length === 0) {
1634
+ ctx.ui.notify("No agent history.", "info");
1635
+ return;
1636
+ }
1637
+ const pairs = history.map((record) => ({ record, label: formatAgentHistoryOption(record, Date.now()) }));
1638
+ const options = makeUniqueAgentOptionLabels(pairs);
1639
+ const choice = await ctx.ui.select("Agent history", options);
1640
+ if (!choice)
1641
+ return;
1642
+ const record = pairs.find((pair) => pair.label === choice)?.record;
1643
+ if (!record)
1644
+ return;
1645
+ await viewAgentConversation(ctx, record, "history");
1646
+ }
1647
+ async function viewAgentConversation(ctx, record, mode) {
1648
+ if (mode === "live" && !canOpenActiveAgent(record)) {
1649
+ ctx.ui.notify(`Agent is ${record.status === "queued" ? "queued" : "expired"} — no history available.`, "info");
1650
+ return;
1651
+ }
1652
+ if (mode === "history" && !canOpenAgentHistory(record, ctx.cwd)) {
1653
+ ctx.ui.notify("No agent history.", "info");
1647
1654
  return;
1648
1655
  }
1649
1656
  const { ConversationViewer, VIEWPORT_HEIGHT_PCT, createStaticConversationSource } = await import("./ui/conversation-viewer.js");
1650
- const session = record.session ?? (record.transcriptPath
1651
- ? (() => {
1652
- const messages = (0, agent_history_js_1.readAgentHistory)(ctx.cwd, record.transcriptPath);
1653
- return messages ? createStaticConversationSource(messages) : undefined;
1654
- })()
1655
- : undefined);
1657
+ const session = mode === "live"
1658
+ ? record.session
1659
+ : (() => {
1660
+ const messages = record.transcriptPath
1661
+ ? readAgentHistory(ctx.cwd, record.transcriptPath)
1662
+ : undefined;
1663
+ return messages
1664
+ ? createStaticConversationSource(messages)
1665
+ : record.session
1666
+ ? createStaticConversationSource(record.session.messages)
1667
+ : undefined;
1668
+ })();
1656
1669
  if (!session) {
1657
- ctx.ui.notify(`Agent is ${record.status === "queued" ? "queued" : "expired"} — no history available.`, "info");
1670
+ ctx.ui.notify("No agent history.", "info");
1658
1671
  return;
1659
1672
  }
1660
1673
  const activity = agentActivity.get(record.id);
1661
- const isLive = record.session !== undefined;
1674
+ const isLive = mode === "live";
1662
1675
  await ctx.ui.custom((tui, theme, keybindings, done) => {
1663
1676
  return new ConversationViewer(tui, session, record, activity, theme, done, isLive ? () => {
1664
1677
  if (manager.abort(record.id)) {
1665
1678
  ctx.ui.notify(`Stopped "${record.description}".`, "info");
1666
1679
  }
1667
- } : undefined, keybindings, isLive ? (message) => manager.steer(record.id, message) : undefined);
1680
+ } : undefined, keybindings, isLive ? (message) => manager.steer(record.id, message) : undefined, mode === "history" ? { pi, ctx, readOnly: true } : { pi, ctx });
1668
1681
  }, {
1669
1682
  overlay: true,
1670
1683
  overlayOptions: { anchor: "center", width: "90%", maxHeight: `${VIEWPORT_HEIGHT_PCT}%` },
1671
1684
  });
1672
1685
  }
1673
1686
  async function showAgentDetail(ctx, name) {
1674
- const cfg = (0, agent_types_js_1.getAgentConfig)(name);
1687
+ const cfg = getAgentConfig(name);
1675
1688
  if (!cfg) {
1676
1689
  ctx.ui.notify(`Agent config not found for "${name}".`, "warning");
1677
1690
  return;
@@ -1702,7 +1715,7 @@ Terse command-style prompts produce shallow, generic work.
1702
1715
  if (!choice || choice === "Back")
1703
1716
  return;
1704
1717
  if (choice === "Edit" && file) {
1705
- const content = (0, node_fs_1.readFileSync)(file.path, "utf-8");
1718
+ const content = readFileSync(file.path, "utf-8");
1706
1719
  const edited = await ctx.ui.editor(`Edit ${name}`, content);
1707
1720
  if (edited !== undefined && edited !== content) {
1708
1721
  const { writeFileSync } = await import("node:fs");
@@ -1715,7 +1728,7 @@ Terse command-style prompts produce shallow, generic work.
1715
1728
  if (file) {
1716
1729
  const confirmed = await ctx.ui.confirm("Delete agent", `Delete ${name} from ${file.location} (${file.path})?`);
1717
1730
  if (confirmed) {
1718
- (0, node_fs_1.unlinkSync)(file.path);
1731
+ unlinkSync(file.path);
1719
1732
  reloadCustomAgents();
1720
1733
  ctx.ui.notify(`Deleted ${file.path}`, "info");
1721
1734
  }
@@ -1724,7 +1737,7 @@ Terse command-style prompts produce shallow, generic work.
1724
1737
  else if (choice === "Reset to default" && file) {
1725
1738
  const confirmed = await ctx.ui.confirm("Reset to default", `Delete override ${file.path} and restore embedded default?`);
1726
1739
  if (confirmed) {
1727
- (0, node_fs_1.unlinkSync)(file.path);
1740
+ unlinkSync(file.path);
1728
1741
  reloadCustomAgents();
1729
1742
  ctx.ui.notify(`Restored default ${name}`, "info");
1730
1743
  }
@@ -1748,9 +1761,9 @@ Terse command-style prompts produce shallow, generic work.
1748
1761
  if (!location)
1749
1762
  return;
1750
1763
  const targetDir = location.startsWith("Project") ? projectAgentsDir() : personalAgentsDir();
1751
- (0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
1752
- const targetPath = (0, node_path_1.join)(targetDir, `${name}.md`);
1753
- if ((0, node_fs_1.existsSync)(targetPath)) {
1764
+ mkdirSync(targetDir, { recursive: true });
1765
+ const targetPath = join(targetDir, `${name}.md`);
1766
+ if (existsSync(targetPath)) {
1754
1767
  const overwrite = await ctx.ui.confirm("Overwrite", `${targetPath} already exists. Overwrite?`);
1755
1768
  if (!overwrite)
1756
1769
  return;
@@ -1803,7 +1816,7 @@ Terse command-style prompts produce shallow, generic work.
1803
1816
  const file = findAgentFile(name);
1804
1817
  if (file) {
1805
1818
  // Existing file — set enabled: false in frontmatter (idempotent)
1806
- const content = (0, node_fs_1.readFileSync)(file.path, "utf-8");
1819
+ const content = readFileSync(file.path, "utf-8");
1807
1820
  if (content.includes("\nenabled: false\n")) {
1808
1821
  ctx.ui.notify(`${name} is already disabled.`, "info");
1809
1822
  return;
@@ -1823,8 +1836,8 @@ Terse command-style prompts produce shallow, generic work.
1823
1836
  if (!location)
1824
1837
  return;
1825
1838
  const targetDir = location.startsWith("Project") ? projectAgentsDir() : personalAgentsDir();
1826
- (0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
1827
- const targetPath = (0, node_path_1.join)(targetDir, `${name}.md`);
1839
+ mkdirSync(targetDir, { recursive: true });
1840
+ const targetPath = join(targetDir, `${name}.md`);
1828
1841
  const { writeFileSync } = await import("node:fs");
1829
1842
  writeFileSync(targetPath, "---\nenabled: false\n---\n", "utf-8");
1830
1843
  reloadCustomAgents();
@@ -1835,12 +1848,12 @@ Terse command-style prompts produce shallow, generic work.
1835
1848
  const file = findAgentFile(name);
1836
1849
  if (!file)
1837
1850
  return;
1838
- const content = (0, node_fs_1.readFileSync)(file.path, "utf-8");
1851
+ const content = readFileSync(file.path, "utf-8");
1839
1852
  const updated = content.replace(/^(---\n)enabled: false\n/, "$1");
1840
1853
  const { writeFileSync } = await import("node:fs");
1841
1854
  // If the file was just a stub ("---\n---\n"), delete it to restore the built-in default
1842
1855
  if (updated.trim() === "---\n---" || updated.trim() === "---\n---\n") {
1843
- (0, node_fs_1.unlinkSync)(file.path);
1856
+ unlinkSync(file.path);
1844
1857
  reloadCustomAgents();
1845
1858
  ctx.ui.notify(`Enabled ${name} (removed ${file.path})`, "info");
1846
1859
  }
@@ -1878,9 +1891,9 @@ Terse command-style prompts produce shallow, generic work.
1878
1891
  const name = await ctx.ui.input("Agent name (filename, no spaces)");
1879
1892
  if (!name)
1880
1893
  return;
1881
- (0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
1882
- const targetPath = (0, node_path_1.join)(targetDir, `${name}.md`);
1883
- if ((0, node_fs_1.existsSync)(targetPath)) {
1894
+ mkdirSync(targetDir, { recursive: true });
1895
+ const targetPath = join(targetDir, `${name}.md`);
1896
+ if (existsSync(targetPath)) {
1884
1897
  const overwrite = await ctx.ui.confirm("Overwrite", `${targetPath} already exists. Overwrite?`);
1885
1898
  if (!overwrite)
1886
1899
  return;
@@ -1934,7 +1947,7 @@ Write the file using the write tool. Only write the file, nothing else.`;
1934
1947
  return;
1935
1948
  }
1936
1949
  reloadCustomAgents();
1937
- if ((0, node_fs_1.existsSync)(targetPath)) {
1950
+ if (existsSync(targetPath)) {
1938
1951
  ctx.ui.notify(`Created ${targetPath}`, "info");
1939
1952
  }
1940
1953
  else {
@@ -1956,7 +1969,7 @@ Write the file using the write tool. Only write the file, nothing else.`;
1956
1969
  return;
1957
1970
  let tools;
1958
1971
  if (toolChoice === "all") {
1959
- tools = agent_types_js_1.BUILTIN_TOOL_NAMES.join(", ");
1972
+ tools = BUILTIN_TOOL_NAMES.join(", ");
1960
1973
  }
1961
1974
  else if (toolChoice === "none") {
1962
1975
  tools = "none";
@@ -1965,7 +1978,7 @@ Write the file using the write tool. Only write the file, nothing else.`;
1965
1978
  tools = "read, bash, grep, find, ls";
1966
1979
  }
1967
1980
  else {
1968
- const customTools = await ctx.ui.input("Tools (comma-separated)", agent_types_js_1.BUILTIN_TOOL_NAMES.join(", "));
1981
+ const customTools = await ctx.ui.input("Tools (comma-separated)", BUILTIN_TOOL_NAMES.join(", "));
1969
1982
  if (!customTools)
1970
1983
  return;
1971
1984
  tools = customTools;
@@ -2013,9 +2026,9 @@ prompt_mode: replace
2013
2026
 
2014
2027
  ${systemPrompt}
2015
2028
  `;
2016
- (0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
2017
- const targetPath = (0, node_path_1.join)(targetDir, `${name}.md`);
2018
- if ((0, node_fs_1.existsSync)(targetPath)) {
2029
+ mkdirSync(targetDir, { recursive: true });
2030
+ const targetPath = join(targetDir, `${name}.md`);
2031
+ if (existsSync(targetPath)) {
2019
2032
  const overwrite = await ctx.ui.confirm("Overwrite", `${targetPath} already exists. Overwrite?`);
2020
2033
  if (!overwrite)
2021
2034
  return;
@@ -2030,12 +2043,12 @@ ${systemPrompt}
2030
2043
  maxConcurrent: manager.getMaxConcurrent(),
2031
2044
  // 0 = unlimited — per SubagentsSettings.defaultMaxTurns docstring and
2032
2045
  // normalizeMaxTurns() in agent-runner.ts (which maps 0 → undefined).
2033
- defaultMaxTurns: (0, agent_runner_js_1.getDefaultMaxTurns)() ?? 0,
2034
- graceTurns: (0, agent_runner_js_1.getGraceTurns)(),
2046
+ defaultMaxTurns: getDefaultMaxTurns() ?? 0,
2047
+ graceTurns: getGraceTurns(),
2035
2048
  defaultJoinMode: getDefaultJoinMode(),
2036
2049
  schedulingEnabled: isSchedulingEnabled(),
2037
2050
  scopeModels: isScopeModelsEnabled(),
2038
- disableDefaultAgents: (0, agent_types_js_1.isDefaultsDisabled)(),
2051
+ disableDefaultAgents: isDefaultsDisabled(),
2039
2052
  toolDescriptionMode: getToolDescriptionMode(),
2040
2053
  fleetView: isFleetViewEnabled(),
2041
2054
  widgetMode: getWidgetMode(),
@@ -2046,8 +2059,8 @@ ${systemPrompt}
2046
2059
  async function showSettings(ctx) {
2047
2060
  function buildItems() {
2048
2061
  const mc = manager.getMaxConcurrent();
2049
- const dmt = (0, agent_runner_js_1.getDefaultMaxTurns)() ?? 0;
2050
- const gt = (0, agent_runner_js_1.getGraceTurns)();
2062
+ const dmt = getDefaultMaxTurns() ?? 0;
2063
+ const gt = getGraceTurns();
2051
2064
  return [
2052
2065
  {
2053
2066
  id: "maxConcurrent",
@@ -2095,7 +2108,7 @@ ${systemPrompt}
2095
2108
  id: "disableDefaultAgents",
2096
2109
  label: "Disable defaults",
2097
2110
  description: "Hide built-in agents (general-purpose, Explore, Plan) — custom agents are unaffected",
2098
- currentValue: (0, agent_types_js_1.isDefaultsDisabled)() ? "on" : "off",
2111
+ currentValue: isDefaultsDisabled() ? "on" : "off",
2099
2112
  values: ["on", "off"],
2100
2113
  },
2101
2114
  {
@@ -2139,18 +2152,18 @@ ${systemPrompt}
2139
2152
  else if (id === "defaultMaxTurns") {
2140
2153
  const n = parseInt(value, 10);
2141
2154
  if (n === 0) {
2142
- (0, agent_runner_js_1.setDefaultMaxTurns)(undefined);
2155
+ setDefaultMaxTurns(undefined);
2143
2156
  notifyApplied(ctx, "Default max turns set to unlimited");
2144
2157
  }
2145
2158
  else if (n >= 1) {
2146
- (0, agent_runner_js_1.setDefaultMaxTurns)(n);
2159
+ setDefaultMaxTurns(n);
2147
2160
  notifyApplied(ctx, `Default max turns set to ${n}`);
2148
2161
  }
2149
2162
  }
2150
2163
  else if (id === "graceTurns") {
2151
2164
  const n = parseInt(value, 10);
2152
2165
  if (n >= 1) {
2153
- (0, agent_runner_js_1.setGraceTurns)(n);
2166
+ setGraceTurns(n);
2154
2167
  notifyApplied(ctx, `Grace turns set to ${n}`);
2155
2168
  }
2156
2169
  }
@@ -2205,26 +2218,26 @@ ${systemPrompt}
2205
2218
  let currentIndex = 0;
2206
2219
  const result = await ctx.ui.custom((_tui, _theme, _kb, done) => {
2207
2220
  const items = buildItems();
2208
- list = new pi_tui_1.SettingsList(items, items.length + 2, (0, pi_coding_agent_1.getSettingsListTheme)(), (id, newValue) => {
2221
+ list = new SettingsList(items, items.length + 2, getSettingsListTheme(), (id, newValue) => {
2209
2222
  applyValue(id, newValue);
2210
2223
  }, () => done(undefined));
2211
- const container = new pi_tui_1.Container();
2212
- container.addChild(new pi_tui_1.Text("⚙ Subagent Settings", 0, 0));
2213
- container.addChild(new pi_tui_1.Spacer(1));
2224
+ const container = new Container();
2225
+ container.addChild(new Text("⚙ Subagent Settings", 0, 0));
2226
+ container.addChild(new Spacer(1));
2214
2227
  container.addChild(list);
2215
2228
  return {
2216
2229
  render: (w) => container.render(w),
2217
2230
  invalidate: () => container.invalidate(),
2218
2231
  handleInput: (data) => {
2219
2232
  // Track navigation so Enter knows the current field
2220
- if ((0, pi_tui_1.matchesKey)(data, "up")) {
2233
+ if (matchesKey(data, "up")) {
2221
2234
  currentIndex = Math.max(0, currentIndex - 1);
2222
2235
  }
2223
- else if ((0, pi_tui_1.matchesKey)(data, "down")) {
2236
+ else if (matchesKey(data, "down")) {
2224
2237
  currentIndex = Math.min(items.length - 1, currentIndex + 1);
2225
2238
  }
2226
2239
  // Enter on numeric field → close and prompt for typed input
2227
- if ((0, pi_tui_1.matchesKey)(data, pi_tui_1.Key.enter) && NUMERIC_IDS.has(items[currentIndex].id)) {
2240
+ if (matchesKey(data, Key.enter) && NUMERIC_IDS.has(items[currentIndex].id)) {
2228
2241
  done(items[currentIndex].id);
2229
2242
  return;
2230
2243
  }
@@ -2237,8 +2250,8 @@ ${systemPrompt}
2237
2250
  const current = result === "maxConcurrent"
2238
2251
  ? String(manager.getMaxConcurrent())
2239
2252
  : result === "defaultMaxTurns"
2240
- ? String((0, agent_runner_js_1.getDefaultMaxTurns)() ?? 0)
2241
- : String((0, agent_runner_js_1.getGraceTurns)());
2253
+ ? String(getDefaultMaxTurns() ?? 0)
2254
+ : String(getGraceTurns());
2242
2255
  const label = result === "maxConcurrent"
2243
2256
  ? "Max concurrency (1+)"
2244
2257
  : result === "defaultMaxTurns"
@@ -2265,7 +2278,7 @@ ${systemPrompt}
2265
2278
  // to warning so users aren't silently reverted on restart. Event fires regardless
2266
2279
  // of outcome so listeners see the in-memory change.
2267
2280
  function notifyApplied(ctx, successMsg) {
2268
- const { message, level } = (0, settings_js_1.saveAndEmitChanged)(snapshotSettings(), successMsg, (event, payload) => pi.events.emit(event, payload));
2281
+ const { message, level } = saveAndEmitChanged(snapshotSettings(), successMsg, (event, payload) => pi.events.emit(event, payload));
2269
2282
  ctx.ui.notify(message, level);
2270
2283
  }
2271
2284
  pi.registerCommand("agents", {
@@ -2273,3 +2286,4 @@ ${systemPrompt}
2273
2286
  handler: async (_args, ctx) => { await showAgentsMenu(ctx); },
2274
2287
  });
2275
2288
  }
2289
+ //# sourceMappingURL=index.js.map