@mariozechner/pi-coding-agent 0.34.2 → 0.35.0

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 (251) hide show
  1. package/CHANGELOG.md +204 -0
  2. package/README.md +233 -105
  3. package/dist/cli/args.d.ts +3 -4
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +13 -18
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/config.d.ts +2 -2
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +3 -3
  10. package/dist/config.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +39 -50
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +166 -197
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  16. package/dist/core/compaction/branch-summarization.js +3 -3
  17. package/dist/core/compaction/branch-summarization.js.map +1 -1
  18. package/dist/core/compaction/compaction.d.ts +1 -1
  19. package/dist/core/compaction/compaction.d.ts.map +1 -1
  20. package/dist/core/compaction/compaction.js +6 -5
  21. package/dist/core/compaction/compaction.js.map +1 -1
  22. package/dist/core/event-bus.d.ts +9 -0
  23. package/dist/core/event-bus.d.ts.map +1 -0
  24. package/dist/core/event-bus.js +25 -0
  25. package/dist/core/event-bus.js.map +1 -0
  26. package/dist/core/exec.d.ts +1 -1
  27. package/dist/core/exec.d.ts.map +1 -1
  28. package/dist/core/exec.js +1 -1
  29. package/dist/core/exec.js.map +1 -1
  30. package/dist/core/extensions/index.d.ts +10 -0
  31. package/dist/core/extensions/index.d.ts.map +1 -0
  32. package/dist/core/extensions/index.js +9 -0
  33. package/dist/core/extensions/index.js.map +1 -0
  34. package/dist/core/extensions/loader.d.ts +21 -0
  35. package/dist/core/extensions/loader.d.ts.map +1 -0
  36. package/dist/core/extensions/loader.js +400 -0
  37. package/dist/core/extensions/loader.js.map +1 -0
  38. package/dist/core/extensions/runner.d.ts +88 -0
  39. package/dist/core/extensions/runner.d.ts.map +1 -0
  40. package/dist/core/{hooks → extensions}/runner.js +52 -141
  41. package/dist/core/extensions/runner.js.map +1 -0
  42. package/dist/core/extensions/types.d.ts +461 -0
  43. package/dist/core/extensions/types.d.ts.map +1 -0
  44. package/dist/core/{hooks → extensions}/types.js +7 -4
  45. package/dist/core/extensions/types.js.map +1 -0
  46. package/dist/core/extensions/wrapper.d.ts +25 -0
  47. package/dist/core/extensions/wrapper.d.ts.map +1 -0
  48. package/dist/core/{hooks/tool-wrapper.js → extensions/wrapper.js} +39 -24
  49. package/dist/core/extensions/wrapper.js.map +1 -0
  50. package/dist/core/index.d.ts +2 -2
  51. package/dist/core/index.d.ts.map +1 -1
  52. package/dist/core/index.js +3 -2
  53. package/dist/core/index.js.map +1 -1
  54. package/dist/core/messages.d.ts +7 -7
  55. package/dist/core/messages.d.ts.map +1 -1
  56. package/dist/core/messages.js +4 -4
  57. package/dist/core/messages.js.map +1 -1
  58. package/dist/core/prompt-templates.d.ts +40 -0
  59. package/dist/core/prompt-templates.d.ts.map +1 -0
  60. package/dist/core/{slash-commands.js → prompt-templates.js} +31 -31
  61. package/dist/core/prompt-templates.js.map +1 -0
  62. package/dist/core/sdk.d.ts +29 -52
  63. package/dist/core/sdk.d.ts.map +1 -1
  64. package/dist/core/sdk.js +111 -211
  65. package/dist/core/sdk.js.map +1 -1
  66. package/dist/core/session-manager.d.ts +17 -17
  67. package/dist/core/session-manager.d.ts.map +1 -1
  68. package/dist/core/session-manager.js +25 -10
  69. package/dist/core/session-manager.js.map +1 -1
  70. package/dist/core/settings-manager.d.ts +3 -6
  71. package/dist/core/settings-manager.d.ts.map +1 -1
  72. package/dist/core/settings-manager.js +4 -11
  73. package/dist/core/settings-manager.js.map +1 -1
  74. package/dist/core/system-prompt.d.ts.map +1 -1
  75. package/dist/core/system-prompt.js +4 -2
  76. package/dist/core/system-prompt.js.map +1 -1
  77. package/dist/index.d.ts +4 -5
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +5 -6
  80. package/dist/index.js.map +1 -1
  81. package/dist/main.d.ts.map +1 -1
  82. package/dist/main.js +36 -33
  83. package/dist/main.js.map +1 -1
  84. package/dist/migrations.d.ts +7 -2
  85. package/dist/migrations.d.ts.map +1 -1
  86. package/dist/migrations.js +93 -4
  87. package/dist/migrations.js.map +1 -1
  88. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  89. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  90. package/dist/modes/interactive/components/bordered-loader.js +1 -1
  91. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  92. package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
  93. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  94. package/dist/modes/interactive/components/branch-summary-message.js +1 -1
  95. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  96. package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
  97. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  98. package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  99. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  100. package/dist/modes/interactive/components/custom-editor.d.ts +2 -2
  101. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  102. package/dist/modes/interactive/components/custom-editor.js +4 -4
  103. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  104. package/dist/modes/interactive/components/custom-message.d.ts +18 -0
  105. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
  106. package/dist/modes/interactive/components/{hook-message.js → custom-message.js} +3 -3
  107. package/dist/modes/interactive/components/custom-message.js.map +1 -0
  108. package/dist/modes/interactive/components/dynamic-border.d.ts +2 -2
  109. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  110. package/dist/modes/interactive/components/dynamic-border.js +2 -2
  111. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  112. package/dist/modes/interactive/components/{hook-editor.d.ts → extension-editor.d.ts} +3 -3
  113. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
  114. package/dist/modes/interactive/components/{hook-editor.js → extension-editor.js} +4 -4
  115. package/dist/modes/interactive/components/extension-editor.js.map +1 -0
  116. package/dist/modes/interactive/components/{hook-input.d.ts → extension-input.d.ts} +3 -3
  117. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
  118. package/dist/modes/interactive/components/{hook-input.js → extension-input.js} +3 -3
  119. package/dist/modes/interactive/components/extension-input.js.map +1 -0
  120. package/dist/modes/interactive/components/{hook-selector.d.ts → extension-selector.d.ts} +3 -3
  121. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
  122. package/dist/modes/interactive/components/{hook-selector.js → extension-selector.js} +3 -3
  123. package/dist/modes/interactive/components/extension-selector.js.map +1 -0
  124. package/dist/modes/interactive/components/footer.d.ts +3 -3
  125. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  126. package/dist/modes/interactive/components/footer.js +8 -8
  127. package/dist/modes/interactive/components/footer.js.map +1 -1
  128. package/dist/modes/interactive/components/tool-execution.d.ts +3 -3
  129. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/tool-execution.js +9 -9
  131. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  132. package/dist/modes/interactive/interactive-mode.d.ts +37 -44
  133. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  134. package/dist/modes/interactive/interactive-mode.js +143 -189
  135. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  136. package/dist/modes/print-mode.d.ts.map +1 -1
  137. package/dist/modes/print-mode.js +10 -33
  138. package/dist/modes/print-mode.js.map +1 -1
  139. package/dist/modes/rpc/rpc-client.d.ts +3 -3
  140. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  141. package/dist/modes/rpc/rpc-client.js +3 -3
  142. package/dist/modes/rpc/rpc-client.js.map +1 -1
  143. package/dist/modes/rpc/rpc-mode.d.ts +2 -2
  144. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  145. package/dist/modes/rpc/rpc-mode.js +33 -57
  146. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  147. package/dist/modes/rpc/rpc-types.d.ts +16 -16
  148. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  149. package/dist/modes/rpc/rpc-types.js.map +1 -1
  150. package/docs/extensions.md +1053 -0
  151. package/docs/rpc.md +4 -4
  152. package/docs/sdk.md +62 -93
  153. package/docs/session.md +22 -19
  154. package/docs/skills.md +1 -1
  155. package/docs/tui.md +1 -1
  156. package/examples/README.md +9 -15
  157. package/examples/extensions/README.md +141 -0
  158. package/examples/{hooks → extensions}/auto-commit-on-exit.ts +3 -3
  159. package/examples/extensions/chalk-logger.ts +26 -0
  160. package/examples/{hooks → extensions}/confirm-destructive.ts +3 -3
  161. package/examples/{hooks → extensions}/custom-compaction.ts +6 -6
  162. package/examples/{hooks → extensions}/dirty-repo-guard.ts +8 -4
  163. package/examples/{hooks → extensions}/file-trigger.ts +3 -3
  164. package/examples/{hooks → extensions}/git-checkpoint.ts +3 -3
  165. package/examples/{hooks → extensions}/handoff.ts +3 -3
  166. package/examples/extensions/hello.ts +25 -0
  167. package/examples/{hooks → extensions}/permission-gate.ts +3 -3
  168. package/examples/{hooks → extensions}/pirate.ts +5 -5
  169. package/examples/{hooks → extensions}/plan-mode.ts +6 -6
  170. package/examples/{hooks → extensions}/protected-paths.ts +3 -3
  171. package/examples/{hooks → extensions}/qna.ts +3 -3
  172. package/examples/{custom-tools/question/index.ts → extensions/question.ts} +13 -17
  173. package/examples/{hooks → extensions}/snake.ts +3 -3
  174. package/examples/{hooks → extensions}/status-line.ts +3 -3
  175. package/examples/{custom-tools → extensions}/subagent/README.md +15 -15
  176. package/examples/{custom-tools → extensions}/subagent/index.ts +22 -43
  177. package/examples/{custom-tools/todo/index.ts → extensions/todo.ts} +122 -39
  178. package/examples/{hooks → extensions}/tools.ts +5 -5
  179. package/examples/extensions/with-deps/index.ts +40 -0
  180. package/examples/extensions/with-deps/package-lock.json +31 -0
  181. package/examples/extensions/with-deps/package.json +16 -0
  182. package/examples/sdk/01-minimal.ts +1 -1
  183. package/examples/sdk/05-tools.ts +7 -41
  184. package/examples/sdk/06-extensions.ts +81 -0
  185. package/examples/sdk/08-prompt-templates.ts +42 -0
  186. package/examples/sdk/12-full-control.ts +10 -29
  187. package/examples/sdk/README.md +5 -5
  188. package/package.json +4 -4
  189. package/dist/core/custom-tools/index.d.ts +0 -7
  190. package/dist/core/custom-tools/index.d.ts.map +0 -1
  191. package/dist/core/custom-tools/index.js +0 -6
  192. package/dist/core/custom-tools/index.js.map +0 -1
  193. package/dist/core/custom-tools/loader.d.ts +0 -30
  194. package/dist/core/custom-tools/loader.d.ts.map +0 -1
  195. package/dist/core/custom-tools/loader.js +0 -276
  196. package/dist/core/custom-tools/loader.js.map +0 -1
  197. package/dist/core/custom-tools/types.d.ts +0 -144
  198. package/dist/core/custom-tools/types.d.ts.map +0 -1
  199. package/dist/core/custom-tools/types.js +0 -8
  200. package/dist/core/custom-tools/types.js.map +0 -1
  201. package/dist/core/custom-tools/wrapper.d.ts +0 -15
  202. package/dist/core/custom-tools/wrapper.d.ts.map +0 -1
  203. package/dist/core/custom-tools/wrapper.js +0 -23
  204. package/dist/core/custom-tools/wrapper.js.map +0 -1
  205. package/dist/core/hooks/index.d.ts +0 -6
  206. package/dist/core/hooks/index.d.ts.map +0 -1
  207. package/dist/core/hooks/index.js +0 -6
  208. package/dist/core/hooks/index.js.map +0 -1
  209. package/dist/core/hooks/loader.d.ts +0 -146
  210. package/dist/core/hooks/loader.d.ts.map +0 -1
  211. package/dist/core/hooks/loader.js +0 -275
  212. package/dist/core/hooks/loader.js.map +0 -1
  213. package/dist/core/hooks/runner.d.ts +0 -173
  214. package/dist/core/hooks/runner.d.ts.map +0 -1
  215. package/dist/core/hooks/runner.js.map +0 -1
  216. package/dist/core/hooks/tool-wrapper.d.ts +0 -17
  217. package/dist/core/hooks/tool-wrapper.d.ts.map +0 -1
  218. package/dist/core/hooks/tool-wrapper.js.map +0 -1
  219. package/dist/core/hooks/types.d.ts +0 -767
  220. package/dist/core/hooks/types.d.ts.map +0 -1
  221. package/dist/core/hooks/types.js.map +0 -1
  222. package/dist/core/slash-commands.d.ts +0 -40
  223. package/dist/core/slash-commands.d.ts.map +0 -1
  224. package/dist/core/slash-commands.js.map +0 -1
  225. package/dist/modes/interactive/components/hook-editor.d.ts.map +0 -1
  226. package/dist/modes/interactive/components/hook-editor.js.map +0 -1
  227. package/dist/modes/interactive/components/hook-input.d.ts.map +0 -1
  228. package/dist/modes/interactive/components/hook-input.js.map +0 -1
  229. package/dist/modes/interactive/components/hook-message.d.ts +0 -18
  230. package/dist/modes/interactive/components/hook-message.d.ts.map +0 -1
  231. package/dist/modes/interactive/components/hook-message.js.map +0 -1
  232. package/dist/modes/interactive/components/hook-selector.d.ts.map +0 -1
  233. package/dist/modes/interactive/components/hook-selector.js.map +0 -1
  234. package/docs/custom-tools.md +0 -514
  235. package/docs/extension-loading.md +0 -1004
  236. package/docs/hooks.md +0 -979
  237. package/docs/session-tree-plan.md +0 -441
  238. package/examples/custom-tools/README.md +0 -114
  239. package/examples/custom-tools/hello/index.ts +0 -21
  240. package/examples/hooks/README.md +0 -60
  241. package/examples/hooks/todo/index.ts +0 -134
  242. package/examples/sdk/06-hooks.ts +0 -61
  243. package/examples/sdk/08-slash-commands.ts +0 -42
  244. /package/examples/{custom-tools → extensions}/subagent/agents/planner.md +0 -0
  245. /package/examples/{custom-tools → extensions}/subagent/agents/reviewer.md +0 -0
  246. /package/examples/{custom-tools → extensions}/subagent/agents/scout.md +0 -0
  247. /package/examples/{custom-tools → extensions}/subagent/agents/worker.md +0 -0
  248. /package/examples/{custom-tools → extensions}/subagent/agents.ts +0 -0
  249. /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/implement-and-review.md +0 -0
  250. /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/implement.md +0 -0
  251. /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/scout-and-plan.md +0 -0
@@ -24,12 +24,12 @@ import { BorderedLoader } from "./components/bordered-loader.js";
24
24
  import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
25
25
  import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
26
26
  import { CustomEditor } from "./components/custom-editor.js";
27
+ import { CustomMessageComponent } from "./components/custom-message.js";
27
28
  import { DynamicBorder } from "./components/dynamic-border.js";
29
+ import { ExtensionEditorComponent } from "./components/extension-editor.js";
30
+ import { ExtensionInputComponent } from "./components/extension-input.js";
31
+ import { ExtensionSelectorComponent } from "./components/extension-selector.js";
28
32
  import { FooterComponent } from "./components/footer.js";
29
- import { HookEditorComponent } from "./components/hook-editor.js";
30
- import { HookInputComponent } from "./components/hook-input.js";
31
- import { HookMessageComponent } from "./components/hook-message.js";
32
- import { HookSelectorComponent } from "./components/hook-selector.js";
33
33
  import { ModelSelectorComponent } from "./components/model-selector.js";
34
34
  import { OAuthSelectorComponent } from "./components/oauth-selector.js";
35
35
  import { SessionSelectorComponent } from "./components/session-selector.js";
@@ -43,7 +43,7 @@ function isExpandable(obj) {
43
43
  return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
44
44
  }
45
45
  export class InteractiveMode {
46
- setToolUIContext;
46
+ setExtensionUIContext;
47
47
  session;
48
48
  ui;
49
49
  chatContainer;
@@ -86,15 +86,13 @@ export class InteractiveMode {
86
86
  // Auto-retry state
87
87
  retryLoader = undefined;
88
88
  retryEscapeHandler;
89
- // Hook UI state
90
- hookSelector = undefined;
91
- hookInput = undefined;
92
- hookEditor = undefined;
93
- // Hook widgets (components rendered above the editor)
94
- hookWidgets = new Map();
89
+ // Extension UI state
90
+ extensionSelector = undefined;
91
+ extensionInput = undefined;
92
+ extensionEditor = undefined;
93
+ // Extension widgets (components rendered above the editor)
94
+ extensionWidgets = new Map();
95
95
  widgetContainer;
96
- // Custom tools for custom rendering
97
- customTools;
98
96
  // Convenience accessors
99
97
  get agent() {
100
98
  return this.session.agent;
@@ -105,12 +103,11 @@ export class InteractiveMode {
105
103
  get settingsManager() {
106
104
  return this.session.settingsManager;
107
105
  }
108
- constructor(session, version, changelogMarkdown = undefined, customTools = [], setToolUIContext = () => { }, fdPath = undefined) {
109
- this.setToolUIContext = setToolUIContext;
106
+ constructor(session, version, changelogMarkdown = undefined, _extensions = [], setExtensionUIContext = () => { }, fdPath = undefined) {
107
+ this.setExtensionUIContext = setExtensionUIContext;
110
108
  this.session = session;
111
109
  this.version = version;
112
110
  this.changelogMarkdown = changelogMarkdown;
113
- this.customTools = new Map(customTools.map((ct) => [ct.tool.name, ct]));
114
111
  this.ui = new TUI(new ProcessTerminal());
115
112
  this.chatContainer = new Container();
116
113
  this.pendingMessagesContainer = new Container();
@@ -122,7 +119,7 @@ export class InteractiveMode {
122
119
  this.editorContainer.addChild(this.editor);
123
120
  this.footer = new FooterComponent(session);
124
121
  this.footer.setAutoCompactEnabled(session.autoCompactionEnabled);
125
- // Define slash commands for autocomplete
122
+ // Define commands for autocomplete
126
123
  const slashCommands = [
127
124
  { name: "settings", description: "Open settings menu" },
128
125
  { name: "model", description: "Select model (opens selector UI)" },
@@ -142,18 +139,18 @@ export class InteractiveMode {
142
139
  ];
143
140
  // Load hide thinking block setting
144
141
  this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
145
- // Convert file commands to SlashCommand format
146
- const fileSlashCommands = this.session.fileCommands.map((cmd) => ({
142
+ // Convert prompt templates to SlashCommand format for autocomplete
143
+ const templateCommands = this.session.promptTemplates.map((cmd) => ({
147
144
  name: cmd.name,
148
145
  description: cmd.description,
149
146
  }));
150
- // Convert hook commands to SlashCommand format
151
- const hookCommands = (this.session.hookRunner?.getRegisteredCommands() ?? []).map((cmd) => ({
147
+ // Convert extension commands to SlashCommand format
148
+ const extensionCommands = (this.session.extensionRunner?.getRegisteredCommands() ?? []).map((cmd) => ({
152
149
  name: cmd.name,
153
- description: cmd.description ?? "(hook command)",
150
+ description: cmd.description ?? "(extension command)",
154
151
  }));
155
152
  // Setup autocomplete
156
- const autocompleteProvider = new CombinedAutocompleteProvider([...slashCommands, ...fileSlashCommands, ...hookCommands], process.cwd(), fdPath);
153
+ const autocompleteProvider = new CombinedAutocompleteProvider([...slashCommands, ...templateCommands, ...extensionCommands], process.cwd(), fdPath);
157
154
  this.editor.setAutocompleteProvider(autocompleteProvider);
158
155
  }
159
156
  async init() {
@@ -268,8 +265,8 @@ export class InteractiveMode {
268
265
  // Set terminal title
269
266
  const cwdBasename = path.basename(process.cwd());
270
267
  this.ui.terminal.setTitle(`pi - ${cwdBasename}`);
271
- // Initialize hooks with TUI-based UI context
272
- await this.initHooksAndCustomTools();
268
+ // Initialize extensions with TUI-based UI context
269
+ await this.initExtensions();
273
270
  // Subscribe to agent events
274
271
  this.subscribeToAgent();
275
272
  // Set up theme file watcher
@@ -284,12 +281,12 @@ export class InteractiveMode {
284
281
  });
285
282
  }
286
283
  // =========================================================================
287
- // Hook System
284
+ // Extension System
288
285
  // =========================================================================
289
286
  /**
290
- * Initialize the hook system with TUI-based UI context.
287
+ * Initialize the extension system with TUI-based UI context.
291
288
  */
292
- async initHooksAndCustomTools() {
289
+ async initExtensions() {
293
290
  // Show loaded project context files
294
291
  const contextFiles = loadProjectContextFiles();
295
292
  if (contextFiles.length > 0) {
@@ -315,32 +312,19 @@ export class InteractiveMode {
315
312
  this.chatContainer.addChild(new Spacer(1));
316
313
  }
317
314
  }
318
- // Show loaded custom tools
319
- if (this.customTools.size > 0) {
320
- const toolList = Array.from(this.customTools.values())
321
- .map((ct) => theme.fg("dim", ` ${ct.tool.name} (${ct.path})`))
322
- .join("\n");
323
- this.chatContainer.addChild(new Text(theme.fg("muted", "Loaded custom tools:\n") + toolList, 0, 0));
324
- this.chatContainer.addChild(new Spacer(1));
315
+ // Create and set extension UI context
316
+ const uiContext = this.createExtensionUIContext();
317
+ this.setExtensionUIContext(uiContext, true);
318
+ const extensionRunner = this.session.extensionRunner;
319
+ if (!extensionRunner) {
320
+ return; // No extensions loaded
325
321
  }
326
- // Create and set hook & tool UI context
327
- const uiContext = this.createHookUIContext();
328
- this.setToolUIContext(uiContext, true);
329
- // Notify custom tools of session start
330
- await this.emitCustomToolSessionEvent({
331
- reason: "start",
332
- previousSessionFile: undefined,
333
- });
334
- const hookRunner = this.session.hookRunner;
335
- if (!hookRunner) {
336
- return; // No hooks loaded
337
- }
338
- hookRunner.initialize({
322
+ extensionRunner.initialize({
339
323
  getModel: () => this.session.model,
340
324
  sendMessageHandler: (message, options) => {
341
325
  const wasStreaming = this.session.isStreaming;
342
326
  this.session
343
- .sendHookMessage(message, options)
327
+ .sendCustomMessage(message, options)
344
328
  .then(() => {
345
329
  // For non-streaming cases with display=true, update UI
346
330
  // (streaming cases update via message_end event)
@@ -349,7 +333,7 @@ export class InteractiveMode {
349
333
  }
350
334
  })
351
335
  .catch((err) => {
352
- this.showError(`Hook sendMessage failed: ${err instanceof Error ? err.message : String(err)}`);
336
+ this.showError(`Extension sendMessage failed: ${err instanceof Error ? err.message : String(err)}`);
353
337
  });
354
338
  },
355
339
  appendEntryHandler: (customType, data) => {
@@ -420,66 +404,42 @@ export class InteractiveMode {
420
404
  uiContext,
421
405
  hasUI: true,
422
406
  });
423
- // Subscribe to hook errors
424
- hookRunner.onError((error) => {
425
- this.showHookError(error.hookPath, error.error, error.stack);
407
+ // Subscribe to extension errors
408
+ extensionRunner.onError((error) => {
409
+ this.showExtensionError(error.extensionPath, error.error, error.stack);
426
410
  });
427
- // Set up hook-registered shortcuts
428
- this.setupHookShortcuts(hookRunner);
429
- // Show loaded hooks
430
- const hookPaths = hookRunner.getHookPaths();
431
- if (hookPaths.length > 0) {
432
- const hookList = hookPaths.map((p) => theme.fg("dim", ` ${p}`)).join("\n");
433
- this.chatContainer.addChild(new Text(theme.fg("muted", "Loaded hooks:\n") + hookList, 0, 0));
411
+ // Set up extension-registered shortcuts
412
+ this.setupExtensionShortcuts(extensionRunner);
413
+ // Show loaded extensions
414
+ const extensionPaths = extensionRunner.getExtensionPaths();
415
+ if (extensionPaths.length > 0) {
416
+ const extList = extensionPaths.map((p) => theme.fg("dim", ` ${p}`)).join("\n");
417
+ this.chatContainer.addChild(new Text(theme.fg("muted", "Loaded extensions:\n") + extList, 0, 0));
434
418
  this.chatContainer.addChild(new Spacer(1));
435
419
  }
436
420
  // Emit session_start event
437
- await hookRunner.emit({
421
+ await extensionRunner.emit({
438
422
  type: "session_start",
439
423
  });
440
424
  }
441
425
  /**
442
- * Emit session event to all custom tools.
426
+ * Get a registered tool definition by name (for custom rendering).
443
427
  */
444
- async emitCustomToolSessionEvent(event) {
445
- for (const { tool } of this.customTools.values()) {
446
- if (tool.onSession) {
447
- try {
448
- await tool.onSession(event, {
449
- sessionManager: this.session.sessionManager,
450
- modelRegistry: this.session.modelRegistry,
451
- model: this.session.model,
452
- isIdle: () => !this.session.isStreaming,
453
- hasPendingMessages: () => this.session.pendingMessageCount > 0,
454
- abort: () => {
455
- this.session.abort();
456
- },
457
- });
458
- }
459
- catch (err) {
460
- this.showToolError(tool.name, err instanceof Error ? err.message : String(err));
461
- }
462
- }
463
- }
464
- }
465
- /**
466
- * Show a tool error in the chat.
467
- */
468
- showToolError(toolName, error) {
469
- const errorText = new Text(theme.fg("error", `Tool "${toolName}" error: ${error}`), 1, 0);
470
- this.chatContainer.addChild(errorText);
471
- this.ui.requestRender();
428
+ getRegisteredToolDefinition(toolName) {
429
+ const tools = this.session.extensionRunner?.getAllRegisteredTools() ?? [];
430
+ const registeredTool = tools.find((t) => t.definition.name === toolName);
431
+ return registeredTool?.definition;
472
432
  }
473
433
  /**
474
- * Set up keyboard shortcuts registered by hooks.
434
+ * Set up keyboard shortcuts registered by extensions.
475
435
  */
476
- setupHookShortcuts(hookRunner) {
477
- const shortcuts = hookRunner.getShortcuts();
436
+ setupExtensionShortcuts(extensionRunner) {
437
+ const shortcuts = extensionRunner.getShortcuts();
478
438
  if (shortcuts.size === 0)
479
439
  return;
480
440
  // Create a context for shortcut handlers
481
441
  const createContext = () => ({
482
- ui: this.createHookUIContext(),
442
+ ui: this.createExtensionUIContext(),
483
443
  hasUI: true,
484
444
  cwd: process.cwd(),
485
445
  sessionManager: this.sessionManager,
@@ -489,10 +449,10 @@ export class InteractiveMode {
489
449
  abort: () => this.session.abort(),
490
450
  hasPendingMessages: () => this.session.pendingMessageCount > 0,
491
451
  });
492
- // Set up the hook shortcut handler on the editor
493
- this.editor.onHookShortcut = (data) => {
452
+ // Set up the extension shortcut handler on the editor
453
+ this.editor.onExtensionShortcut = (data) => {
494
454
  for (const [shortcutStr, shortcut] of shortcuts) {
495
- // Cast to KeyId - hook shortcuts use the same format
455
+ // Cast to KeyId - extension shortcuts use the same format
496
456
  if (matchesKey(data, shortcutStr)) {
497
457
  // Run handler async, don't block input
498
458
  Promise.resolve(shortcut.handler(createContext())).catch((err) => {
@@ -505,22 +465,22 @@ export class InteractiveMode {
505
465
  };
506
466
  }
507
467
  /**
508
- * Set hook status text in the footer.
468
+ * Set extension status text in the footer.
509
469
  */
510
- setHookStatus(key, text) {
511
- this.footer.setHookStatus(key, text);
470
+ setExtensionStatus(key, text) {
471
+ this.footer.setExtensionStatus(key, text);
512
472
  this.ui.requestRender();
513
473
  }
514
474
  /**
515
- * Set a hook widget (string array or custom component).
475
+ * Set an extension widget (string array or custom component).
516
476
  */
517
- setHookWidget(key, content) {
477
+ setExtensionWidget(key, content) {
518
478
  // Dispose and remove existing widget
519
- const existing = this.hookWidgets.get(key);
479
+ const existing = this.extensionWidgets.get(key);
520
480
  if (existing?.dispose)
521
481
  existing.dispose();
522
482
  if (content === undefined) {
523
- this.hookWidgets.delete(key);
483
+ this.extensionWidgets.delete(key);
524
484
  }
525
485
  else if (Array.isArray(content)) {
526
486
  // Wrap string array in a Container with Text components
@@ -531,149 +491,149 @@ export class InteractiveMode {
531
491
  if (content.length > InteractiveMode.MAX_WIDGET_LINES) {
532
492
  container.addChild(new Text(theme.fg("muted", "... (widget truncated)"), 1, 0));
533
493
  }
534
- this.hookWidgets.set(key, container);
494
+ this.extensionWidgets.set(key, container);
535
495
  }
536
496
  else {
537
497
  // Factory function - create component
538
498
  const component = content(this.ui, theme);
539
- this.hookWidgets.set(key, component);
499
+ this.extensionWidgets.set(key, component);
540
500
  }
541
501
  this.renderWidgets();
542
502
  }
543
503
  // Maximum total widget lines to prevent viewport overflow
544
504
  static MAX_WIDGET_LINES = 10;
545
505
  /**
546
- * Render all hook widgets to the widget container.
506
+ * Render all extension widgets to the widget container.
547
507
  */
548
508
  renderWidgets() {
549
509
  if (!this.widgetContainer)
550
510
  return;
551
511
  this.widgetContainer.clear();
552
- if (this.hookWidgets.size === 0) {
512
+ if (this.extensionWidgets.size === 0) {
553
513
  this.ui.requestRender();
554
514
  return;
555
515
  }
556
- for (const [_key, component] of this.hookWidgets) {
516
+ for (const [_key, component] of this.extensionWidgets) {
557
517
  this.widgetContainer.addChild(component);
558
518
  }
559
519
  this.ui.requestRender();
560
520
  }
561
521
  /**
562
- * Create the HookUIContext for hooks and tools.
522
+ * Create the ExtensionUIContext for extensions.
563
523
  */
564
- createHookUIContext() {
524
+ createExtensionUIContext() {
565
525
  return {
566
- select: (title, options) => this.showHookSelector(title, options),
567
- confirm: (title, message) => this.showHookConfirm(title, message),
568
- input: (title, placeholder) => this.showHookInput(title, placeholder),
569
- notify: (message, type) => this.showHookNotify(message, type),
570
- setStatus: (key, text) => this.setHookStatus(key, text),
571
- setWidget: (key, content) => this.setHookWidget(key, content),
526
+ select: (title, options) => this.showExtensionSelector(title, options),
527
+ confirm: (title, message) => this.showExtensionConfirm(title, message),
528
+ input: (title, placeholder) => this.showExtensionInput(title, placeholder),
529
+ notify: (message, type) => this.showExtensionNotify(message, type),
530
+ setStatus: (key, text) => this.setExtensionStatus(key, text),
531
+ setWidget: (key, content) => this.setExtensionWidget(key, content),
572
532
  setTitle: (title) => this.ui.terminal.setTitle(title),
573
- custom: (factory) => this.showHookCustom(factory),
533
+ custom: (factory) => this.showExtensionCustom(factory),
574
534
  setEditorText: (text) => this.editor.setText(text),
575
535
  getEditorText: () => this.editor.getText(),
576
- editor: (title, prefill) => this.showHookEditor(title, prefill),
536
+ editor: (title, prefill) => this.showExtensionEditor(title, prefill),
577
537
  get theme() {
578
538
  return theme;
579
539
  },
580
540
  };
581
541
  }
582
542
  /**
583
- * Show a selector for hooks.
543
+ * Show a selector for extensions.
584
544
  */
585
- showHookSelector(title, options) {
545
+ showExtensionSelector(title, options) {
586
546
  return new Promise((resolve) => {
587
- this.hookSelector = new HookSelectorComponent(title, options, (option) => {
588
- this.hideHookSelector();
547
+ this.extensionSelector = new ExtensionSelectorComponent(title, options, (option) => {
548
+ this.hideExtensionSelector();
589
549
  resolve(option);
590
550
  }, () => {
591
- this.hideHookSelector();
551
+ this.hideExtensionSelector();
592
552
  resolve(undefined);
593
553
  });
594
554
  this.editorContainer.clear();
595
- this.editorContainer.addChild(this.hookSelector);
596
- this.ui.setFocus(this.hookSelector);
555
+ this.editorContainer.addChild(this.extensionSelector);
556
+ this.ui.setFocus(this.extensionSelector);
597
557
  this.ui.requestRender();
598
558
  });
599
559
  }
600
560
  /**
601
- * Hide the hook selector.
561
+ * Hide the extension selector.
602
562
  */
603
- hideHookSelector() {
563
+ hideExtensionSelector() {
604
564
  this.editorContainer.clear();
605
565
  this.editorContainer.addChild(this.editor);
606
- this.hookSelector = undefined;
566
+ this.extensionSelector = undefined;
607
567
  this.ui.setFocus(this.editor);
608
568
  this.ui.requestRender();
609
569
  }
610
570
  /**
611
- * Show a confirmation dialog for hooks.
571
+ * Show a confirmation dialog for extensions.
612
572
  */
613
- async showHookConfirm(title, message) {
614
- const result = await this.showHookSelector(`${title}\n${message}`, ["Yes", "No"]);
573
+ async showExtensionConfirm(title, message) {
574
+ const result = await this.showExtensionSelector(`${title}\n${message}`, ["Yes", "No"]);
615
575
  return result === "Yes";
616
576
  }
617
577
  /**
618
- * Show a text input for hooks.
578
+ * Show a text input for extensions.
619
579
  */
620
- showHookInput(title, placeholder) {
580
+ showExtensionInput(title, placeholder) {
621
581
  return new Promise((resolve) => {
622
- this.hookInput = new HookInputComponent(title, placeholder, (value) => {
623
- this.hideHookInput();
582
+ this.extensionInput = new ExtensionInputComponent(title, placeholder, (value) => {
583
+ this.hideExtensionInput();
624
584
  resolve(value);
625
585
  }, () => {
626
- this.hideHookInput();
586
+ this.hideExtensionInput();
627
587
  resolve(undefined);
628
588
  });
629
589
  this.editorContainer.clear();
630
- this.editorContainer.addChild(this.hookInput);
631
- this.ui.setFocus(this.hookInput);
590
+ this.editorContainer.addChild(this.extensionInput);
591
+ this.ui.setFocus(this.extensionInput);
632
592
  this.ui.requestRender();
633
593
  });
634
594
  }
635
595
  /**
636
- * Hide the hook input.
596
+ * Hide the extension input.
637
597
  */
638
- hideHookInput() {
598
+ hideExtensionInput() {
639
599
  this.editorContainer.clear();
640
600
  this.editorContainer.addChild(this.editor);
641
- this.hookInput = undefined;
601
+ this.extensionInput = undefined;
642
602
  this.ui.setFocus(this.editor);
643
603
  this.ui.requestRender();
644
604
  }
645
605
  /**
646
- * Show a multi-line editor for hooks (with Ctrl+G support).
606
+ * Show a multi-line editor for extensions (with Ctrl+G support).
647
607
  */
648
- showHookEditor(title, prefill) {
608
+ showExtensionEditor(title, prefill) {
649
609
  return new Promise((resolve) => {
650
- this.hookEditor = new HookEditorComponent(this.ui, title, prefill, (value) => {
651
- this.hideHookEditor();
610
+ this.extensionEditor = new ExtensionEditorComponent(this.ui, title, prefill, (value) => {
611
+ this.hideExtensionEditor();
652
612
  resolve(value);
653
613
  }, () => {
654
- this.hideHookEditor();
614
+ this.hideExtensionEditor();
655
615
  resolve(undefined);
656
616
  });
657
617
  this.editorContainer.clear();
658
- this.editorContainer.addChild(this.hookEditor);
659
- this.ui.setFocus(this.hookEditor);
618
+ this.editorContainer.addChild(this.extensionEditor);
619
+ this.ui.setFocus(this.extensionEditor);
660
620
  this.ui.requestRender();
661
621
  });
662
622
  }
663
623
  /**
664
- * Hide the hook editor.
624
+ * Hide the extension editor.
665
625
  */
666
- hideHookEditor() {
626
+ hideExtensionEditor() {
667
627
  this.editorContainer.clear();
668
628
  this.editorContainer.addChild(this.editor);
669
- this.hookEditor = undefined;
629
+ this.extensionEditor = undefined;
670
630
  this.ui.setFocus(this.editor);
671
631
  this.ui.requestRender();
672
632
  }
673
633
  /**
674
- * Show a notification for hooks.
634
+ * Show a notification for extensions.
675
635
  */
676
- showHookNotify(message, type) {
636
+ showExtensionNotify(message, type) {
677
637
  if (type === "error") {
678
638
  this.showError(message);
679
639
  }
@@ -687,7 +647,7 @@ export class InteractiveMode {
687
647
  /**
688
648
  * Show a custom component with keyboard focus.
689
649
  */
690
- async showHookCustom(factory) {
650
+ async showExtensionCustom(factory) {
691
651
  const savedText = this.editor.getText();
692
652
  return new Promise((resolve) => {
693
653
  let component;
@@ -710,10 +670,10 @@ export class InteractiveMode {
710
670
  });
711
671
  }
712
672
  /**
713
- * Show a hook error in the UI.
673
+ * Show an extension error in the UI.
714
674
  */
715
- showHookError(hookPath, error, stack) {
716
- const errorMsg = `Hook "${hookPath}" error: ${error}`;
675
+ showExtensionError(extensionPath, error, stack) {
676
+ const errorMsg = `Extension "${extensionPath}" error: ${error}`;
717
677
  const errorText = new Text(theme.fg("error", errorMsg), 1, 0);
718
678
  this.chatContainer.addChild(errorText);
719
679
  if (stack) {
@@ -729,10 +689,6 @@ export class InteractiveMode {
729
689
  }
730
690
  this.ui.requestRender();
731
691
  }
732
- /**
733
- * Handle pi.send() from hooks.
734
- * If streaming, queue the message. Otherwise, start a new agent loop.
735
- */
736
692
  // =========================================================================
737
693
  // Key Handlers
738
694
  // =========================================================================
@@ -827,7 +783,7 @@ export class InteractiveMode {
827
783
  text = text.trim();
828
784
  if (!text)
829
785
  return;
830
- // Handle slash commands
786
+ // Handle commands
831
787
  if (text === "/settings") {
832
788
  this.showSettingsSelector();
833
789
  this.editor.setText("");
@@ -947,7 +903,7 @@ export class InteractiveMode {
947
903
  return;
948
904
  }
949
905
  // If streaming, use prompt() with steer behavior
950
- // This handles hook commands (execute immediately), slash command expansion, and queueing
906
+ // This handles extension commands (execute immediately), prompt template expansion, and queueing
951
907
  if (this.session.isStreaming) {
952
908
  this.editor.addToHistory(text);
953
909
  this.editor.setText("");
@@ -986,7 +942,7 @@ export class InteractiveMode {
986
942
  this.ui.requestRender();
987
943
  break;
988
944
  case "message_start":
989
- if (event.message.role === "hookMessage") {
945
+ if (event.message.role === "custom") {
990
946
  this.addMessageToChat(event.message);
991
947
  this.ui.requestRender();
992
948
  }
@@ -1014,7 +970,7 @@ export class InteractiveMode {
1014
970
  this.chatContainer.addChild(new Text("", 0, 0));
1015
971
  const component = new ToolExecutionComponent(content.name, content.arguments, {
1016
972
  showImages: this.settingsManager.getShowImages(),
1017
- }, this.customTools.get(content.name)?.tool, this.ui);
973
+ }, this.getRegisteredToolDefinition(content.name), this.ui);
1018
974
  component.setExpanded(this.toolOutputExpanded);
1019
975
  this.chatContainer.addChild(component);
1020
976
  this.pendingTools.set(content.id, component);
@@ -1064,7 +1020,7 @@ export class InteractiveMode {
1064
1020
  if (!this.pendingTools.has(event.toolCallId)) {
1065
1021
  const component = new ToolExecutionComponent(event.toolName, event.args, {
1066
1022
  showImages: this.settingsManager.getShowImages(),
1067
- }, this.customTools.get(event.toolName)?.tool, this.ui);
1023
+ }, this.getRegisteredToolDefinition(event.toolName), this.ui);
1068
1024
  component.setExpanded(this.toolOutputExpanded);
1069
1025
  this.chatContainer.addChild(component);
1070
1026
  this.pendingTools.set(event.toolCallId, component);
@@ -1231,10 +1187,10 @@ export class InteractiveMode {
1231
1187
  this.chatContainer.addChild(component);
1232
1188
  break;
1233
1189
  }
1234
- case "hookMessage": {
1190
+ case "custom": {
1235
1191
  if (message.display) {
1236
- const renderer = this.session.hookRunner?.getMessageRenderer(message.customType);
1237
- this.chatContainer.addChild(new HookMessageComponent(message, renderer));
1192
+ const renderer = this.session.extensionRunner?.getMessageRenderer(message.customType);
1193
+ this.chatContainer.addChild(new CustomMessageComponent(message, renderer));
1238
1194
  }
1239
1195
  break;
1240
1196
  }
@@ -1296,7 +1252,7 @@ export class InteractiveMode {
1296
1252
  // Render tool call components
1297
1253
  for (const content of message.content) {
1298
1254
  if (content.type === "toolCall") {
1299
- const component = new ToolExecutionComponent(content.name, content.arguments, { showImages: this.settingsManager.getShowImages() }, this.customTools.get(content.name)?.tool, this.ui);
1255
+ const component = new ToolExecutionComponent(content.name, content.arguments, { showImages: this.settingsManager.getShowImages() }, this.getRegisteredToolDefinition(content.name), this.ui);
1300
1256
  component.setExpanded(this.toolOutputExpanded);
1301
1257
  this.chatContainer.addChild(component);
1302
1258
  if (message.stopReason === "aborted" || message.stopReason === "error") {
@@ -1372,18 +1328,16 @@ export class InteractiveMode {
1372
1328
  }
1373
1329
  /**
1374
1330
  * Gracefully shutdown the agent.
1375
- * Emits shutdown event to hooks and tools, then exits.
1331
+ * Emits shutdown event to extensions, then exits.
1376
1332
  */
1377
1333
  async shutdown() {
1378
- // Emit shutdown event to hooks
1379
- const hookRunner = this.session.hookRunner;
1380
- if (hookRunner?.hasHandlers("session_shutdown")) {
1381
- await hookRunner.emit({
1334
+ // Emit shutdown event to extensions
1335
+ const extensionRunner = this.session.extensionRunner;
1336
+ if (extensionRunner?.hasHandlers("session_shutdown")) {
1337
+ await extensionRunner.emit({
1382
1338
  type: "session_shutdown",
1383
1339
  });
1384
1340
  }
1385
- // Emit shutdown event to custom tools
1386
- await this.session.emitCustomToolSessionEvent("shutdown");
1387
1341
  this.stop();
1388
1342
  process.exit(0);
1389
1343
  }
@@ -1403,7 +1357,7 @@ export class InteractiveMode {
1403
1357
  if (!text)
1404
1358
  return;
1405
1359
  // Alt+Enter queues a follow-up message (waits until agent finishes)
1406
- // This handles hook commands (execute immediately), slash command expansion, and queueing
1360
+ // This handles extension commands (execute immediately), prompt template expansion, and queueing
1407
1361
  if (this.session.isStreaming) {
1408
1362
  this.editor.addToHistory(text);
1409
1363
  this.editor.setText("");
@@ -1701,7 +1655,7 @@ export class InteractiveMode {
1701
1655
  const selector = new UserMessageSelectorComponent(userMessages.map((m) => ({ id: m.entryId, text: m.text })), async (entryId) => {
1702
1656
  const result = await this.session.branch(entryId);
1703
1657
  if (result.cancelled) {
1704
- // Hook cancelled the branch
1658
+ // Extension cancelled the branch
1705
1659
  done();
1706
1660
  this.ui.requestRender();
1707
1661
  return;
@@ -1745,7 +1699,7 @@ export class InteractiveMode {
1745
1699
  }
1746
1700
  // Ask about summarization
1747
1701
  done(); // Close selector first
1748
- const wantsSummary = await this.showHookConfirm("Summarize branch?", "Create a summary of the branch you're leaving?");
1702
+ const wantsSummary = await this.showExtensionConfirm("Summarize branch?", "Create a summary of the branch you're leaving?");
1749
1703
  // Set up escape handler and loader if summarizing
1750
1704
  let summaryLoader;
1751
1705
  const originalOnEscape = this.editor.onEscape;
@@ -1825,7 +1779,7 @@ export class InteractiveMode {
1825
1779
  this.streamingComponent = undefined;
1826
1780
  this.streamingMessage = undefined;
1827
1781
  this.pendingTools.clear();
1828
- // Switch session via AgentSession (emits hook and tool session events)
1782
+ // Switch session via AgentSession (emits extension session events)
1829
1783
  await this.session.switchSession(sessionPath);
1830
1784
  // Clear and re-render the chat
1831
1785
  this.chatContainer.clear();
@@ -2176,18 +2130,18 @@ export class InteractiveMode {
2176
2130
  | \`/\` | Slash commands |
2177
2131
  | \`!\` | Run bash command |
2178
2132
  `;
2179
- // Add hook-registered shortcuts
2180
- const hookRunner = this.session.hookRunner;
2181
- if (hookRunner) {
2182
- const shortcuts = hookRunner.getShortcuts();
2133
+ // Add extension-registered shortcuts
2134
+ const extensionRunner = this.session.extensionRunner;
2135
+ if (extensionRunner) {
2136
+ const shortcuts = extensionRunner.getShortcuts();
2183
2137
  if (shortcuts.size > 0) {
2184
2138
  hotkeys += `
2185
- **Hooks**
2139
+ **Extensions**
2186
2140
  | Key | Action |
2187
2141
  |-----|--------|
2188
2142
  `;
2189
2143
  for (const [key, shortcut] of shortcuts) {
2190
- const description = shortcut.description ?? shortcut.hookPath;
2144
+ const description = shortcut.description ?? shortcut.extensionPath;
2191
2145
  hotkeys += `| \`${key}\` | ${description} |\n`;
2192
2146
  }
2193
2147
  }
@@ -2207,7 +2161,7 @@ export class InteractiveMode {
2207
2161
  this.loadingAnimation = undefined;
2208
2162
  }
2209
2163
  this.statusContainer.clear();
2210
- // New session via session (emits hook and tool session events)
2164
+ // New session via session (emits extension session events)
2211
2165
  await this.session.newSession();
2212
2166
  // Clear UI state
2213
2167
  this.chatContainer.clear();