@within-7/minto 0.3.10 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/dist/Tool.js.map +2 -2
  2. package/dist/commands/agents/AgentsCommand.js +2 -2
  3. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  4. package/dist/commands/ctx_viz.js +1 -1
  5. package/dist/commands/effort.js +87 -0
  6. package/dist/commands/effort.js.map +7 -0
  7. package/dist/commands/export.js +19 -9
  8. package/dist/commands/export.js.map +2 -2
  9. package/dist/commands/ide.js +18 -0
  10. package/dist/commands/ide.js.map +7 -0
  11. package/dist/commands/mcp-interactive.js +14 -8
  12. package/dist/commands/mcp-interactive.js.map +2 -2
  13. package/dist/commands/memory.js +168 -0
  14. package/dist/commands/memory.js.map +7 -0
  15. package/dist/commands/model.js +45 -2
  16. package/dist/commands/model.js.map +2 -2
  17. package/dist/commands/outputStyle.js +64 -0
  18. package/dist/commands/outputStyle.js.map +7 -0
  19. package/dist/commands/plugin/utils.js +33 -1
  20. package/dist/commands/plugin/utils.js.map +2 -2
  21. package/dist/commands/plugin.js +10 -1
  22. package/dist/commands/plugin.js.map +2 -2
  23. package/dist/commands/refreshCommands.js +2 -0
  24. package/dist/commands/refreshCommands.js.map +2 -2
  25. package/dist/commands/review.js +51 -0
  26. package/dist/commands/review.js.map +7 -0
  27. package/dist/commands/terminalSetup.js +6 -0
  28. package/dist/commands/terminalSetup.js.map +2 -2
  29. package/dist/commands/undo.js +8 -0
  30. package/dist/commands/undo.js.map +2 -2
  31. package/dist/commands/vim.js +22 -0
  32. package/dist/commands/vim.js.map +7 -0
  33. package/dist/commands.js +12 -0
  34. package/dist/commands.js.map +2 -2
  35. package/dist/components/HighlightedCode.js +1 -0
  36. package/dist/components/HighlightedCode.js.map +2 -2
  37. package/dist/components/ModelSelector/ModelSelector.js +250 -143
  38. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  39. package/dist/components/PromptInput.js +21 -6
  40. package/dist/components/PromptInput.js.map +2 -2
  41. package/dist/components/PulseLabel.js +44 -0
  42. package/dist/components/PulseLabel.js.map +7 -0
  43. package/dist/components/RequestStatusIndicator.js +1 -1
  44. package/dist/components/RequestStatusIndicator.js.map +1 -1
  45. package/dist/components/Spinner.js +12 -42
  46. package/dist/components/Spinner.js.map +3 -3
  47. package/dist/components/StartupStatus.js +57 -0
  48. package/dist/components/StartupStatus.js.map +7 -0
  49. package/dist/components/SubagentBlock.js +43 -6
  50. package/dist/components/SubagentBlock.js.map +2 -2
  51. package/dist/components/TabbedListView/TabBar.js +13 -8
  52. package/dist/components/TabbedListView/TabBar.js.map +2 -2
  53. package/dist/components/TabbedListView/TabbedListView.js +1 -1
  54. package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
  55. package/dist/components/TodoPanel.js +1 -1
  56. package/dist/components/TodoPanel.js.map +1 -1
  57. package/dist/components/ToolUseLoader.js +5 -0
  58. package/dist/components/ToolUseLoader.js.map +2 -2
  59. package/dist/components/TrustDialog.js +0 -2
  60. package/dist/components/TrustDialog.js.map +2 -2
  61. package/dist/components/messages/TaskInModuleView.js +1 -1
  62. package/dist/components/messages/TaskInModuleView.js.map +2 -2
  63. package/dist/components/messages/TaskToolMessage.js +1 -1
  64. package/dist/components/messages/TaskToolMessage.js.map +2 -2
  65. package/dist/components/messages/UserPromptMessage.js +6 -1
  66. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  67. package/dist/constants/modelCapabilities.js +103 -18
  68. package/dist/constants/modelCapabilities.js.map +2 -2
  69. package/dist/constants/product.js +2 -0
  70. package/dist/constants/product.js.map +2 -2
  71. package/dist/constants/prompts/agentPrompt.js +30 -0
  72. package/dist/constants/prompts/agentPrompt.js.map +7 -0
  73. package/dist/constants/prompts/codeConventions.js +27 -0
  74. package/dist/constants/prompts/codeConventions.js.map +7 -0
  75. package/dist/constants/prompts/doingTasks.js +15 -0
  76. package/dist/constants/prompts/doingTasks.js.map +7 -0
  77. package/dist/constants/prompts/envInfo.js +17 -0
  78. package/dist/constants/prompts/envInfo.js.map +7 -0
  79. package/dist/constants/prompts/executingWithCare.js +17 -0
  80. package/dist/constants/prompts/executingWithCare.js.map +7 -0
  81. package/dist/constants/prompts/identity.js +10 -0
  82. package/dist/constants/prompts/identity.js.map +7 -0
  83. package/dist/constants/prompts/index.js +78 -0
  84. package/dist/constants/prompts/index.js.map +7 -0
  85. package/dist/constants/prompts/taskManagement.js +60 -0
  86. package/dist/constants/prompts/taskManagement.js.map +7 -0
  87. package/dist/constants/prompts/toneAndStyle.js +62 -0
  88. package/dist/constants/prompts/toneAndStyle.js.map +7 -0
  89. package/dist/constants/prompts/toolUsagePolicy.js +38 -0
  90. package/dist/constants/prompts/toolUsagePolicy.js.map +7 -0
  91. package/dist/constants/prompts.js +5 -176
  92. package/dist/constants/prompts.js.map +2 -2
  93. package/dist/constants/providerRegistry.js +235 -0
  94. package/dist/constants/providerRegistry.js.map +7 -0
  95. package/dist/constants/providers.js +35 -0
  96. package/dist/constants/providers.js.map +7 -0
  97. package/dist/context/PermissionContext.js +0 -1
  98. package/dist/context/PermissionContext.js.map +2 -2
  99. package/dist/context.js +87 -31
  100. package/dist/context.js.map +2 -2
  101. package/dist/core/backupHook.js +2 -2
  102. package/dist/core/backupHook.js.map +2 -2
  103. package/dist/core/config/defaults.js +4 -1
  104. package/dist/core/config/defaults.js.map +2 -2
  105. package/dist/core/config/schema.js +7 -1
  106. package/dist/core/config/schema.js.map +2 -2
  107. package/dist/core/costTracker.js +18 -0
  108. package/dist/core/costTracker.js.map +2 -2
  109. package/dist/core/index.js +0 -1
  110. package/dist/core/index.js.map +2 -2
  111. package/dist/core/tokenStatsManager.js +22 -4
  112. package/dist/core/tokenStatsManager.js.map +2 -2
  113. package/dist/entrypoints/cli.js +65 -84
  114. package/dist/entrypoints/cli.js.map +2 -2
  115. package/dist/hooks/useAgentTokenStats.js +1 -1
  116. package/dist/hooks/useAgentTokenStats.js.map +2 -2
  117. package/dist/hooks/useAgentTranscripts.js +2 -1
  118. package/dist/hooks/useAgentTranscripts.js.map +2 -2
  119. package/dist/hooks/useBackgroundShells.js +29 -0
  120. package/dist/hooks/useBackgroundShells.js.map +7 -0
  121. package/dist/hooks/useCanUseTool.js +1 -1
  122. package/dist/hooks/useCanUseTool.js.map +2 -2
  123. package/dist/hooks/useDeferredLoading.js +64 -0
  124. package/dist/hooks/useDeferredLoading.js.map +7 -0
  125. package/dist/hooks/useHookStatus.js +1 -1
  126. package/dist/hooks/useHookStatus.js.map +2 -2
  127. package/dist/hooks/useSessionTracking.js +55 -0
  128. package/dist/hooks/useSessionTracking.js.map +7 -0
  129. package/dist/hooks/useTerminalSize.js +21 -0
  130. package/dist/hooks/useTerminalSize.js.map +2 -2
  131. package/dist/hooks/useTextInput.js +1 -0
  132. package/dist/hooks/useTextInput.js.map +2 -2
  133. package/dist/hooks/useUnifiedCompletion.js +3 -2
  134. package/dist/hooks/useUnifiedCompletion.js.map +2 -2
  135. package/dist/i18n/locales/en.js +8 -9
  136. package/dist/i18n/locales/en.js.map +2 -2
  137. package/dist/i18n/locales/zh-CN.js +8 -9
  138. package/dist/i18n/locales/zh-CN.js.map +2 -2
  139. package/dist/i18n/types.js.map +1 -1
  140. package/dist/messages.js +41 -17
  141. package/dist/messages.js.map +2 -2
  142. package/dist/permissions.js +94 -1
  143. package/dist/permissions.js.map +2 -2
  144. package/dist/query.js +27 -19
  145. package/dist/query.js.map +2 -2
  146. package/dist/screens/REPL.js +83 -74
  147. package/dist/screens/REPL.js.map +2 -2
  148. package/dist/services/adapters/responsesAPI.js +6 -0
  149. package/dist/services/adapters/responsesAPI.js.map +2 -2
  150. package/dist/services/agentTeams/index.js +35 -0
  151. package/dist/services/agentTeams/index.js.map +7 -0
  152. package/dist/services/agentTeams/mailbox.js +114 -0
  153. package/dist/services/agentTeams/mailbox.js.map +7 -0
  154. package/dist/services/agentTeams/teamManager.js +149 -0
  155. package/dist/services/agentTeams/teamManager.js.map +7 -0
  156. package/dist/services/agentTeams/teamTaskStore.js +114 -0
  157. package/dist/services/agentTeams/teamTaskStore.js.map +7 -0
  158. package/dist/services/agentTeams/teammateSpawner.js +80 -0
  159. package/dist/services/agentTeams/teammateSpawner.js.map +7 -0
  160. package/dist/services/checkpointManager.js +16 -3
  161. package/dist/services/checkpointManager.js.map +2 -2
  162. package/dist/services/claude.js +19 -1728
  163. package/dist/services/claude.js.map +3 -3
  164. package/dist/services/gpt5ConnectionTest.js +4 -2
  165. package/dist/services/gpt5ConnectionTest.js.map +2 -2
  166. package/dist/services/hookExecutor.js +411 -127
  167. package/dist/services/hookExecutor.js.map +2 -2
  168. package/dist/services/llm/anthropicProvider.js +807 -0
  169. package/dist/services/llm/anthropicProvider.js.map +7 -0
  170. package/dist/services/llm/dispatch.js +218 -0
  171. package/dist/services/llm/dispatch.js.map +7 -0
  172. package/dist/services/llm/index.js +44 -0
  173. package/dist/services/llm/index.js.map +7 -0
  174. package/dist/services/llm/mintoContext.js +69 -0
  175. package/dist/services/llm/mintoContext.js.map +7 -0
  176. package/dist/services/llm/openaiProvider.js +622 -0
  177. package/dist/services/llm/openaiProvider.js.map +7 -0
  178. package/dist/services/llm/types.js +157 -0
  179. package/dist/services/llm/types.js.map +7 -0
  180. package/dist/services/mcpClient.js +183 -33
  181. package/dist/services/mcpClient.js.map +2 -2
  182. package/dist/services/notifier.js +14 -0
  183. package/dist/services/notifier.js.map +2 -2
  184. package/dist/services/oauth.js +4 -2
  185. package/dist/services/oauth.js.map +2 -2
  186. package/dist/services/openai.js +66 -56
  187. package/dist/services/openai.js.map +3 -3
  188. package/dist/services/outputStyles.js +102 -21
  189. package/dist/services/outputStyles.js.map +2 -2
  190. package/dist/services/plugins/skillMarketplace.js +4 -1
  191. package/dist/services/plugins/skillMarketplace.js.map +2 -2
  192. package/dist/services/sentry.js +1 -1
  193. package/dist/services/sentry.js.map +2 -2
  194. package/dist/services/sessionMemory.js +16 -3
  195. package/dist/services/sessionMemory.js.map +2 -2
  196. package/dist/services/systemReminder.js +350 -3
  197. package/dist/services/systemReminder.js.map +2 -2
  198. package/dist/services/taskStore.js +19 -0
  199. package/dist/services/taskStore.js.map +2 -2
  200. package/dist/tools/ArchitectTool/ArchitectTool.js.map +1 -1
  201. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +1 -1
  202. package/dist/tools/BashOutputTool/BashOutputTool.js.map +1 -1
  203. package/dist/tools/BashTool/BashTool.js +28 -0
  204. package/dist/tools/BashTool/BashTool.js.map +2 -2
  205. package/dist/tools/FileEditTool/FileEditTool.js +1 -1
  206. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  207. package/dist/tools/FileReadTool/FileReadTool.js +14 -0
  208. package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
  209. package/dist/tools/FileWriteTool/FileWriteTool.js +3 -1
  210. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  211. package/dist/tools/GlobTool/GlobTool.js.map +1 -1
  212. package/dist/tools/GrepTool/GrepTool.js.map +1 -1
  213. package/dist/tools/KillShellTool/KillShellTool.js.map +1 -1
  214. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
  215. package/dist/tools/LspTool/LspTool.js +11 -2
  216. package/dist/tools/LspTool/LspTool.js.map +2 -2
  217. package/dist/tools/MCPTool/MCPTool.js.map +1 -1
  218. package/dist/tools/MemoryReadTool/MemoryReadTool.js +2 -1
  219. package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
  220. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +2 -1
  221. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
  222. package/dist/tools/MultiEditTool/MultiEditTool.js.map +1 -1
  223. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +1 -1
  224. package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +1 -1
  225. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +8 -2
  226. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
  227. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +2 -0
  228. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
  229. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +1 -1
  230. package/dist/tools/SlashCommandTool/SlashCommandTool.js +174 -18
  231. package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +3 -3
  232. package/dist/tools/TaskCreateTool/TaskCreateTool.js.map +1 -1
  233. package/dist/tools/TaskGetTool/TaskGetTool.js.map +1 -1
  234. package/dist/tools/TaskListTool/TaskListTool.js.map +1 -1
  235. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +1 -1
  236. package/dist/tools/TaskStopTool/TaskStopTool.js.map +1 -1
  237. package/dist/tools/TaskTool/TaskTool.js +75 -5
  238. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  239. package/dist/tools/TaskTool/prompt.js +12 -6
  240. package/dist/tools/TaskTool/prompt.js.map +2 -2
  241. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +1 -1
  242. package/dist/tools/ThinkTool/ThinkTool.js.map +1 -1
  243. package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +1 -1
  244. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +1 -1
  245. package/dist/tools/WebSearchTool/WebSearchTool.js.map +1 -1
  246. package/dist/tools/WebSearchTool/searchProviders.js +2 -1
  247. package/dist/tools/WebSearchTool/searchProviders.js.map +2 -2
  248. package/dist/tools/lsTool/lsTool.js.map +2 -2
  249. package/dist/tools/lsTool/prompt.js.map +1 -1
  250. package/dist/tools.js +14 -3
  251. package/dist/tools.js.map +2 -2
  252. package/dist/types/PermissionMode.js +21 -1
  253. package/dist/types/PermissionMode.js.map +2 -2
  254. package/dist/types/agentTeams.js +1 -0
  255. package/dist/types/agentTeams.js.map +7 -0
  256. package/dist/types/hooks.js +8 -2
  257. package/dist/types/hooks.js.map +2 -2
  258. package/dist/types/plugin.js +1 -1
  259. package/dist/types/plugin.js.map +2 -2
  260. package/dist/utils/agentLoader.js +25 -3
  261. package/dist/utils/agentLoader.js.map +2 -2
  262. package/dist/utils/animationManager.js +1 -1
  263. package/dist/utils/animationManager.js.map +2 -2
  264. package/dist/utils/ask.js +1 -1
  265. package/dist/utils/async.js +5 -1
  266. package/dist/utils/async.js.map +2 -2
  267. package/dist/utils/autoCompactCore.js +60 -0
  268. package/dist/utils/autoCompactCore.js.map +2 -2
  269. package/dist/utils/config.js +26 -128
  270. package/dist/utils/config.js.map +2 -2
  271. package/dist/utils/configSchema.js +227 -0
  272. package/dist/utils/configSchema.js.map +7 -0
  273. package/dist/utils/debugLogger.js.map +2 -2
  274. package/dist/utils/env.js +4 -3
  275. package/dist/utils/env.js.map +2 -2
  276. package/dist/utils/envConfig.js +34 -0
  277. package/dist/utils/envConfig.js.map +3 -3
  278. package/dist/utils/gpt5.js +146 -0
  279. package/dist/utils/gpt5.js.map +7 -0
  280. package/dist/utils/hookManager.js +374 -140
  281. package/dist/utils/hookManager.js.map +2 -2
  282. package/dist/utils/markdown.js +47 -0
  283. package/dist/utils/markdown.js.map +2 -2
  284. package/dist/utils/memoizeWithTTL.js +25 -0
  285. package/dist/utils/memoizeWithTTL.js.map +7 -0
  286. package/dist/utils/model.js +34 -9
  287. package/dist/utils/model.js.map +2 -2
  288. package/dist/utils/pluginInstaller.js +34 -5
  289. package/dist/utils/pluginInstaller.js.map +2 -2
  290. package/dist/utils/pluginLoader.js +201 -32
  291. package/dist/utils/pluginLoader.js.map +2 -2
  292. package/dist/utils/safeFetch.js +45 -0
  293. package/dist/utils/safeFetch.js.map +7 -0
  294. package/dist/utils/skillLoader.js +59 -6
  295. package/dist/utils/skillLoader.js.map +2 -2
  296. package/dist/utils/streamingState.js +52 -0
  297. package/dist/utils/streamingState.js.map +7 -0
  298. package/dist/utils/style.js +6 -3
  299. package/dist/utils/style.js.map +2 -2
  300. package/dist/utils/teamConfig.js +9 -3
  301. package/dist/utils/teamConfig.js.map +2 -2
  302. package/dist/utils/toolRiskClassification.js +0 -6
  303. package/dist/utils/toolRiskClassification.js.map +2 -2
  304. package/dist/version.js +2 -2
  305. package/dist/version.js.map +1 -1
  306. package/package.json +7 -6
@@ -1,10 +1,12 @@
1
1
  import { spawn } from "child_process";
2
+ import { existsSync, readFileSync } from "fs";
2
3
  import { EventEmitter } from "events";
3
4
  import {
4
5
  HookEvent
5
6
  } from "../types/hooks.js";
6
7
  import { getCwd } from "../utils/state.js";
7
8
  import { logError } from "../utils/log.js";
9
+ import { emitReminderEvent } from "./systemReminder.js";
8
10
  const logInfo = (msg) => {
9
11
  if (process.env.DEBUG) console.log(`[INFO] ${msg}`);
10
12
  };
@@ -12,132 +14,326 @@ const logDebug = (msg, ...args) => {
12
14
  if (process.env.DEBUG) console.log(`[DEBUG] ${msg}`, ...args);
13
15
  };
14
16
  const hookStatusEmitter = new EventEmitter();
17
+ const executedOnceHooks = /* @__PURE__ */ new Set();
18
+ function resetOnceHooks() {
19
+ executedOnceHooks.clear();
20
+ }
15
21
  function formatHookStatusMessage(event, toolName, hookName, success, errorMessage) {
16
22
  const eventPart = toolName ? `${event}:${toolName}` : event;
17
23
  const statusPart = success ? "succeeded" : "failed";
18
24
  const detailPart = success ? "Success" : errorMessage || "Error";
19
25
  return `${eventPart} hook ${statusPart}: ${detailPart}`;
20
26
  }
27
+ function emitStatusEvent(event, toolName, hookName, success, errorMessage) {
28
+ hookStatusEmitter.emit("status", {
29
+ event,
30
+ toolName,
31
+ success,
32
+ message: formatHookStatusMessage(
33
+ event,
34
+ toolName,
35
+ hookName,
36
+ success,
37
+ errorMessage
38
+ ),
39
+ timestamp: Date.now(),
40
+ hookName
41
+ });
42
+ }
43
+ function substituteArguments(command, input) {
44
+ if (!command.includes("$ARGUMENTS")) {
45
+ return command;
46
+ }
47
+ const inputJson = JSON.stringify(input);
48
+ const escaped = inputJson.replace(/'/g, "'\\''");
49
+ return command.replace(/\$ARGUMENTS/g, `'${escaped}'`);
50
+ }
21
51
  async function executeHook(hook, input, options) {
22
- if (hook.config.type !== "command" || !hook.config.command) {
23
- return {
24
- success: false,
25
- error: `Hook type "${hook.config.type}" not yet implemented`
26
- };
52
+ const hookType = hook.config.type || "command";
53
+ if (hook.config.once) {
54
+ const hookKey = `${hook.pluginName}:${hook.name}:${hook.event}`;
55
+ if (executedOnceHooks.has(hookKey)) {
56
+ logDebug(`Skipping once-hook (already executed): ${hookKey}`);
57
+ return { success: true };
58
+ }
59
+ executedOnceHooks.add(hookKey);
27
60
  }
28
- const timeout = hook.config.timeout || options.timeout || 3e4;
29
61
  const toolName = "tool_name" in input ? input.tool_name : void 0;
62
+ if (hook.config.async) {
63
+ executeHookAsync(hook, input, options, hookType, toolName).catch((err) => {
64
+ logDebug(`Async hook ${hook.name} error: ${err}`);
65
+ });
66
+ return { success: true };
67
+ }
68
+ switch (hookType) {
69
+ case "command":
70
+ return executeCommandHook(hook, input, options, toolName);
71
+ case "prompt":
72
+ return executePromptHook(hook, input, options, toolName);
73
+ case "agent":
74
+ return executeAgentHook(hook, input, options, toolName);
75
+ default:
76
+ return {
77
+ success: false,
78
+ error: `Unknown hook type: ${hookType}`
79
+ };
80
+ }
81
+ }
82
+ async function executeHookAsync(hook, input, options, hookType, toolName) {
83
+ try {
84
+ let result;
85
+ switch (hookType) {
86
+ case "command":
87
+ result = await executeCommandHook(hook, input, options, toolName);
88
+ break;
89
+ case "prompt":
90
+ result = await executePromptHook(hook, input, options, toolName);
91
+ break;
92
+ case "agent":
93
+ result = await executeAgentHook(hook, input, options, toolName);
94
+ break;
95
+ default:
96
+ return;
97
+ }
98
+ if (result.output?.systemMessage) {
99
+ hookStatusEmitter.emit("asyncResult", {
100
+ hookName: hook.name,
101
+ systemMessage: result.output.systemMessage
102
+ });
103
+ }
104
+ } catch {
105
+ }
106
+ }
107
+ async function executeCommandHook(hook, input, options, toolName) {
108
+ if (!hook.config.command) {
109
+ return { success: false, error: "Command hook missing command field" };
110
+ }
111
+ const timeout = (hook.config.timeout ? hook.config.timeout * 1e3 : void 0) || options.timeout || 3e4;
30
112
  try {
31
113
  logDebug(`Executing hook: ${hook.name}`);
32
- logDebug(`Command: ${hook.config.command}`);
33
- const result = await executeBashCommand(hook.config.command, input, {
114
+ const command = substituteArguments(hook.config.command, input);
115
+ logDebug(`Command: ${command}`);
116
+ const result = await executeBashCommand(command, input, {
34
117
  ...options,
35
118
  timeout,
36
119
  pluginRoot: options.pluginRoot
37
120
  });
38
121
  if (result.timedOut) {
39
- logError(`Hook ${hook.name} timed out after ${timeout}ms`);
40
122
  const errorMsg = `Hook execution timed out after ${timeout}ms`;
41
- hookStatusEmitter.emit("status", {
42
- event: hook.event,
43
- toolName,
44
- success: false,
45
- message: formatHookStatusMessage(
46
- hook.event,
47
- toolName,
48
- hook.name,
49
- false,
50
- errorMsg
51
- ),
52
- timestamp: Date.now(),
53
- hookName: hook.name
54
- });
55
- return {
56
- success: false,
57
- timedOut: true,
58
- error: errorMsg
59
- };
123
+ logError(`Hook ${hook.name} timed out after ${timeout}ms`);
124
+ emitStatusEvent(hook.event, toolName, hook.name, false, errorMsg);
125
+ return { success: false, timedOut: true, error: errorMsg };
60
126
  }
61
- if (result.error) {
62
- logError(`Hook ${hook.name} failed: ${result.error}`);
63
- hookStatusEmitter.emit("status", {
64
- event: hook.event,
65
- toolName,
66
- success: false,
67
- message: formatHookStatusMessage(
68
- hook.event,
69
- toolName,
70
- hook.name,
71
- false,
72
- result.error
73
- ),
74
- timestamp: Date.now(),
75
- hookName: hook.name
76
- });
127
+ if (result.exitCode === 2) {
128
+ const reason = result.stderr.trim() || "Blocked by hook";
129
+ logDebug(`Hook ${hook.name} exit code 2 (block): ${reason}`);
130
+ emitStatusEvent(hook.event, toolName, hook.name, true);
77
131
  return {
78
- success: false,
79
- error: result.error
132
+ success: true,
133
+ decision: "block",
134
+ blockedByExitCode2: true,
135
+ blockReason: reason,
136
+ output: {
137
+ decision: "block",
138
+ reason,
139
+ systemMessage: reason
140
+ }
80
141
  };
81
142
  }
82
- const output = parseHookOutput(result.stdout);
143
+ if (result.exitCode !== 0 && result.exitCode !== null) {
144
+ const errorMsg = `Command exited with code ${result.exitCode}: ${result.stderr}`;
145
+ logError(`Hook ${hook.name} failed: ${errorMsg}`);
146
+ emitStatusEvent(hook.event, toolName, hook.name, false, errorMsg);
147
+ return { success: false, error: errorMsg };
148
+ }
149
+ const output = parseHookOutput(result.stdout, input.hook_event_name);
83
150
  if (!output) {
84
- hookStatusEmitter.emit("status", {
85
- event: hook.event,
86
- toolName,
87
- success: true,
88
- message: formatHookStatusMessage(hook.event, toolName, hook.name, true),
89
- timestamp: Date.now(),
90
- hookName: hook.name
91
- });
92
- return {
93
- success: true
94
- };
151
+ emitStatusEvent(hook.event, toolName, hook.name, true);
152
+ return { success: true };
95
153
  }
96
154
  logDebug(`Hook ${hook.name} output:`, output);
97
- hookStatusEmitter.emit("status", {
98
- event: hook.event,
99
- toolName,
100
- success: true,
101
- message: formatHookStatusMessage(hook.event, toolName, hook.name, true),
102
- timestamp: Date.now(),
103
- hookName: hook.name
104
- });
105
- return {
106
- success: true,
107
- decision: output.decision,
108
- output
109
- };
155
+ emitStatusEvent(hook.event, toolName, hook.name, true);
156
+ const decision = resolveDecision(output);
157
+ return { success: true, decision, output };
110
158
  } catch (error) {
111
159
  const errorMsg = error instanceof Error ? error.message : String(error);
112
160
  logError(`Hook ${hook.name} execution error: ${errorMsg}`);
113
- hookStatusEmitter.emit("status", {
114
- event: hook.event,
115
- toolName,
116
- success: false,
117
- message: formatHookStatusMessage(
118
- hook.event,
119
- toolName,
120
- hook.name,
121
- false,
122
- errorMsg
123
- ),
124
- timestamp: Date.now(),
125
- hookName: hook.name
126
- });
127
- return {
128
- success: false,
129
- error: errorMsg
130
- };
161
+ emitStatusEvent(hook.event, toolName, hook.name, false, errorMsg);
162
+ return { success: false, error: errorMsg };
163
+ }
164
+ }
165
+ async function executePromptHook(hook, input, options, toolName) {
166
+ if (!hook.config.prompt) {
167
+ return { success: false, error: "Prompt hook missing prompt field" };
168
+ }
169
+ const timeout = (hook.config.timeout ? hook.config.timeout * 1e3 : void 0) || 3e4;
170
+ try {
171
+ const inputJson = JSON.stringify(input);
172
+ const prompt = hook.config.prompt.replace(/\$ARGUMENTS/g, inputJson);
173
+ logDebug(`Executing prompt hook: ${hook.name}`);
174
+ const { queryQuick } = await import("./claude.js");
175
+ const abortController = new AbortController();
176
+ const timer = setTimeout(() => abortController.abort(), timeout);
177
+ try {
178
+ const result = await queryQuick({
179
+ systemPrompt: [
180
+ 'You are a hook evaluator. Respond ONLY with JSON: { "ok": boolean, "reason": string }.',
181
+ "ok=true means allow the action, ok=false means block it."
182
+ ],
183
+ userPrompt: prompt,
184
+ signal: abortController.signal
185
+ });
186
+ clearTimeout(timer);
187
+ const text = result.message.content.filter((b) => b.type === "text").map((b) => b.text).join("");
188
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
189
+ if (jsonMatch) {
190
+ const parsed = JSON.parse(jsonMatch[0]);
191
+ const decision = parsed.ok ? "approve" : "block";
192
+ emitStatusEvent(hook.event, toolName, hook.name, true);
193
+ return {
194
+ success: true,
195
+ decision,
196
+ output: { decision, reason: parsed.reason }
197
+ };
198
+ }
199
+ } catch {
200
+ clearTimeout(timer);
201
+ }
202
+ logDebug(`Prompt hook ${hook.name}: parse failed, defaulting to allow`);
203
+ emitStatusEvent(hook.event, toolName, hook.name, true);
204
+ return { success: true, decision: "approve" };
205
+ } catch (error) {
206
+ const errorMsg = error instanceof Error ? error.message : String(error);
207
+ logError(`Prompt hook ${hook.name} error: ${errorMsg}`);
208
+ emitStatusEvent(hook.event, toolName, hook.name, false, errorMsg);
209
+ return { success: true, decision: "approve" };
131
210
  }
132
211
  }
212
+ async function executeAgentHook(hook, input, options, toolName) {
213
+ if (!hook.config.prompt) {
214
+ return { success: false, error: "Agent hook missing prompt field" };
215
+ }
216
+ const timeout = (hook.config.timeout ? hook.config.timeout * 1e3 : void 0) || 6e4;
217
+ try {
218
+ const inputJson = JSON.stringify(input);
219
+ const prompt = hook.config.prompt.replace(/\$ARGUMENTS/g, inputJson);
220
+ logDebug(`Executing agent hook: ${hook.name}`);
221
+ const { queryQuick } = await import("./claude.js");
222
+ const abortController = new AbortController();
223
+ const timer = setTimeout(() => abortController.abort(), timeout);
224
+ try {
225
+ const result = await queryQuick({
226
+ systemPrompt: [
227
+ "You are a hook agent evaluator. You have read-only access to the codebase.",
228
+ 'Evaluate the request and respond ONLY with JSON: { "ok": boolean, "reason": string }.',
229
+ "ok=true means allow the action, ok=false means block it."
230
+ ],
231
+ userPrompt: prompt,
232
+ signal: abortController.signal
233
+ });
234
+ clearTimeout(timer);
235
+ const text = result.message.content.filter((b) => b.type === "text").map((b) => b.text).join("");
236
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
237
+ if (jsonMatch) {
238
+ const parsed = JSON.parse(jsonMatch[0]);
239
+ const decision = parsed.ok ? "approve" : "block";
240
+ emitStatusEvent(hook.event, toolName, hook.name, true);
241
+ return {
242
+ success: true,
243
+ decision,
244
+ output: { decision, reason: parsed.reason }
245
+ };
246
+ }
247
+ } catch {
248
+ clearTimeout(timer);
249
+ }
250
+ logDebug(`Agent hook ${hook.name}: parse failed, defaulting to allow`);
251
+ emitStatusEvent(hook.event, toolName, hook.name, true);
252
+ return { success: true, decision: "approve" };
253
+ } catch (error) {
254
+ const errorMsg = error instanceof Error ? error.message : String(error);
255
+ logError(`Agent hook ${hook.name} error: ${errorMsg}`);
256
+ emitStatusEvent(hook.event, toolName, hook.name, false, errorMsg);
257
+ return { success: true, decision: "approve" };
258
+ }
259
+ }
260
+ function resolveDecision(output) {
261
+ if (output.hookSpecificOutput) {
262
+ const specific = output.hookSpecificOutput;
263
+ if (specific.permissionDecision) {
264
+ const mapping = {
265
+ allow: "approve",
266
+ deny: "block",
267
+ ask: "ask",
268
+ approve: "approve",
269
+ block: "block"
270
+ };
271
+ return mapping[specific.permissionDecision] ?? output.decision;
272
+ }
273
+ }
274
+ return output.decision;
275
+ }
276
+ let claudeEnvFilePath;
277
+ function loadEnvFile() {
278
+ const envFile = claudeEnvFilePath || process.env.CLAUDE_ENV_FILE;
279
+ if (!envFile || !existsSync(envFile)) return {};
280
+ try {
281
+ const content = readFileSync(envFile, "utf-8");
282
+ const vars = {};
283
+ for (const line of content.split("\n")) {
284
+ const trimmed = line.trim();
285
+ if (!trimmed || trimmed.startsWith("#")) continue;
286
+ const eqIdx = trimmed.indexOf("=");
287
+ if (eqIdx <= 0) continue;
288
+ const key = trimmed.slice(0, eqIdx).trim();
289
+ let value = trimmed.slice(eqIdx + 1).trim();
290
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
291
+ value = value.slice(1, -1);
292
+ }
293
+ vars[key] = value;
294
+ }
295
+ return vars;
296
+ } catch {
297
+ return {};
298
+ }
299
+ }
300
+ function extractFilePathsFromInput(toolInput) {
301
+ if (!toolInput) return "";
302
+ const paths = [];
303
+ if (typeof toolInput.file_path === "string") paths.push(toolInput.file_path);
304
+ if (typeof toolInput.path === "string") paths.push(toolInput.path);
305
+ if (typeof toolInput.notebook_path === "string")
306
+ paths.push(toolInput.notebook_path);
307
+ return paths.join(":");
308
+ }
133
309
  async function executeBashCommand(command, input, options) {
134
310
  return new Promise((resolve) => {
311
+ const envFileVars = loadEnvFile();
312
+ const toolName = "tool_name" in input ? input.tool_name : void 0;
313
+ const toolInput = "tool_input" in input ? input.tool_input : void 0;
314
+ const toolInputJson = toolInput ? JSON.stringify(toolInput) : "";
315
+ const filePaths = extractFilePathsFromInput(toolInput);
316
+ const shellCommand = toolName === "Bash" && toolInput?.command ? String(toolInput.command) : "";
317
+ const projectDir = getCwd();
135
318
  const env = {
136
319
  ...process.env,
320
+ ...envFileVars,
321
+ // CC-compatible env vars
137
322
  CLAUDE_PLUGIN_ROOT: options.pluginRoot,
138
323
  CLAUDE_SESSION_ID: options.sessionId,
139
- CLAUDE_CWD: getCwd(),
140
- CLAUDE_TRANSCRIPT_PATH: options.transcriptPath || ""
324
+ CLAUDE_CWD: projectDir,
325
+ CLAUDE_TRANSCRIPT_PATH: options.transcriptPath || "",
326
+ CLAUDE_PROJECT_DIR: projectDir,
327
+ CLAUDE_WORKSPACE_DIR: projectDir,
328
+ CLAUDE_TOOL_INPUT: toolInputJson,
329
+ CLAUDE_FILE_PATHS: filePaths,
330
+ CLAUDE_SHELL_COMMAND: shellCommand,
331
+ // Minto-prefixed duplicates
332
+ MINTO_PROJECT_DIR: projectDir,
333
+ MINTO_WORKSPACE_DIR: projectDir,
334
+ MINTO_TOOL_INPUT: toolInputJson,
335
+ MINTO_FILE_PATHS: filePaths,
336
+ MINTO_SHELL_COMMAND: shellCommand
141
337
  };
142
338
  const child = spawn("bash", ["-c", command], {
143
339
  env,
@@ -164,32 +360,17 @@ async function executeBashCommand(command, input, options) {
164
360
  child.on("close", (code) => {
165
361
  clearTimeout(timer);
166
362
  if (timedOut) {
167
- resolve({
168
- stdout: "",
169
- stderr: "",
170
- timedOut: true
171
- });
172
- return;
173
- }
174
- if (code !== 0 && code !== null) {
175
- resolve({
176
- stdout,
177
- stderr,
178
- error: `Command exited with code ${code}: ${stderr}`
179
- });
363
+ resolve({ stdout: "", stderr: "", exitCode: null, timedOut: true });
180
364
  return;
181
365
  }
182
- resolve({
183
- stdout,
184
- stderr
185
- });
366
+ resolve({ stdout, stderr, exitCode: code });
186
367
  });
187
368
  child.on("error", (error) => {
188
369
  clearTimeout(timer);
189
370
  resolve({
190
371
  stdout: "",
191
- stderr: "",
192
- error: `Failed to spawn process: ${error.message}`
372
+ stderr: error.message,
373
+ exitCode: 1
193
374
  });
194
375
  });
195
376
  try {
@@ -202,13 +383,13 @@ async function executeBashCommand(command, input, options) {
202
383
  child.kill();
203
384
  resolve({
204
385
  stdout: "",
205
- stderr: "",
206
- error: `Failed to write to stdin: ${error instanceof Error ? error.message : String(error)}`
386
+ stderr: `Failed to write to stdin: ${error instanceof Error ? error.message : String(error)}`,
387
+ exitCode: 1
207
388
  });
208
389
  }
209
390
  });
210
391
  }
211
- function parseHookOutput(stdout) {
392
+ function parseHookOutput(stdout, eventName) {
212
393
  if (!stdout.trim()) {
213
394
  return null;
214
395
  }
@@ -218,11 +399,45 @@ function parseHookOutput(stdout) {
218
399
  logDebug("No JSON found in hook output");
219
400
  return null;
220
401
  }
221
- const output = JSON.parse(jsonMatch[0]);
222
- if (output.decision) {
223
- if (!["approve", "block", "ask"].includes(output.decision)) {
224
- logError(`Invalid hook decision: ${output.decision}`);
225
- return null;
402
+ const raw = JSON.parse(jsonMatch[0]);
403
+ const output = {};
404
+ if (raw.continue !== void 0) output.continue = raw.continue;
405
+ if (raw.stopReason) output.stopReason = raw.stopReason;
406
+ if (raw.suppressOutput !== void 0)
407
+ output.suppressOutput = raw.suppressOutput;
408
+ if (raw.systemMessage) output.systemMessage = raw.systemMessage;
409
+ if (raw.decision) {
410
+ if (["approve", "block", "ask"].includes(raw.decision)) {
411
+ output.decision = raw.decision;
412
+ }
413
+ }
414
+ if (raw.reason) output.reason = raw.reason;
415
+ const specific = raw.hookSpecificOutput || raw;
416
+ if (eventName === HookEvent.PreToolUse) {
417
+ if (specific.permissionDecision || specific.updatedInput || specific.permissionDecisionReason) {
418
+ output.hookSpecificOutput = {
419
+ hookEventName: HookEvent.PreToolUse,
420
+ permissionDecision: specific.permissionDecision,
421
+ permissionDecisionReason: specific.permissionDecisionReason,
422
+ updatedInput: specific.updatedInput
423
+ };
424
+ }
425
+ } else if (eventName === HookEvent.PostToolUse || eventName === HookEvent.UserPromptSubmit || eventName === HookEvent.SessionStart) {
426
+ if (specific.additionalContext) {
427
+ output.hookSpecificOutput = {
428
+ hookEventName: eventName,
429
+ additionalContext: specific.additionalContext
430
+ };
431
+ }
432
+ if (eventName === HookEvent.SessionStart && specific.envFile) {
433
+ claudeEnvFilePath = specific.envFile;
434
+ process.env.CLAUDE_ENV_FILE = specific.envFile;
435
+ }
436
+ }
437
+ if (eventName === HookEvent.Notification) {
438
+ if (raw.suppressNotification !== void 0) {
439
+ ;
440
+ output.suppressNotification = raw.suppressNotification;
226
441
  }
227
442
  }
228
443
  return output;
@@ -239,18 +454,37 @@ async function executeHooksForEvent(event, hooks, input, options) {
239
454
  return [];
240
455
  }
241
456
  logInfo(`Executing ${matchingHooks.length} hook(s) for event: ${event}`);
242
- const results = await Promise.all(
457
+ const results = await Promise.allSettled(
243
458
  matchingHooks.map((hook) => executeHook(hook, input, options))
244
459
  );
245
- return results;
460
+ return results.map(
461
+ (r) => r.status === "fulfilled" ? r.value : { success: false, error: String(r.reason) }
462
+ );
246
463
  }
247
464
  function processHookDecisions(results) {
248
- const blockedResult = results.find((r) => r.success && r.decision === "block");
465
+ let additionalContext;
466
+ let updatedInput;
467
+ for (const r of results) {
468
+ if (!r.success || !r.output) continue;
469
+ const specific = r.output.hookSpecificOutput;
470
+ if (specific?.additionalContext) {
471
+ additionalContext = additionalContext ? `${additionalContext}
472
+ ${specific.additionalContext}` : specific.additionalContext;
473
+ }
474
+ if (specific?.updatedInput) {
475
+ updatedInput = { ...updatedInput || {}, ...specific.updatedInput };
476
+ }
477
+ }
478
+ const blockedResult = results.find(
479
+ (r) => r.success && r.decision === "block" || r.blockedByExitCode2
480
+ );
249
481
  if (blockedResult) {
482
+ const reason = blockedResult.blockReason || blockedResult.output?.reason || "Blocked by hook";
483
+ emitReminderEvent("hook:blocking_error", { hookName: "hook", reason });
250
484
  return {
251
485
  shouldContinue: false,
252
486
  shouldAskUser: false,
253
- reason: blockedResult.output?.reason || "Blocked by hook"
487
+ reason
254
488
  };
255
489
  }
256
490
  const askResult = results.find((r) => r.success && r.decision === "ask");
@@ -263,15 +497,25 @@ function processHookDecisions(results) {
263
497
  }
264
498
  const failedResult = results.find((r) => !r.success);
265
499
  if (failedResult) {
500
+ const reason = `Hook execution failed: ${failedResult.error}`;
501
+ emitReminderEvent("hook:stopped_continuation", { hookName: "hook", reason });
266
502
  return {
267
503
  shouldContinue: false,
268
504
  shouldAskUser: true,
269
- reason: `Hook execution failed: ${failedResult.error}`
505
+ reason
270
506
  };
271
507
  }
508
+ if (additionalContext) {
509
+ emitReminderEvent("hook:additional_context", {
510
+ hookName: "hook",
511
+ content: additionalContext
512
+ });
513
+ }
272
514
  return {
273
515
  shouldContinue: true,
274
- shouldAskUser: false
516
+ shouldAskUser: false,
517
+ updatedInput,
518
+ additionalContext
275
519
  };
276
520
  }
277
521
  function createPreToolUseInput(sessionId, transcriptPath, toolName, toolInput) {
@@ -387,14 +631,16 @@ function createSubagentStopInput(sessionId, transcriptPath, agentType, agentId,
387
631
  stop_hook_active: stopHookActive ?? false
388
632
  };
389
633
  }
390
- function createNotificationInput(sessionId, transcriptPath, message) {
634
+ function createNotificationInput(sessionId, transcriptPath, message, title, type) {
391
635
  return {
392
636
  hook_event_name: HookEvent.Notification,
393
637
  session_id: sessionId,
394
638
  transcript_path: transcriptPath,
395
639
  cwd: getCwd(),
396
640
  permission_mode: "default",
397
- message
641
+ message,
642
+ ...title ? { title } : {},
643
+ ...type ? { notification_type: type } : {}
398
644
  };
399
645
  }
400
646
  function createPreCompactInput(sessionId, transcriptPath, trigger, customInstructions) {
@@ -422,7 +668,42 @@ function createPostCompactInput(sessionId, transcriptPath, trigger, summary, com
422
668
  compressed_tokens: compressedTokens
423
669
  };
424
670
  }
671
+ function createConfigChangeInput(sessionId, transcriptPath, source, filePath) {
672
+ return {
673
+ hook_event_name: HookEvent.ConfigChange,
674
+ session_id: sessionId,
675
+ transcript_path: transcriptPath,
676
+ cwd: getCwd(),
677
+ permission_mode: "default",
678
+ source,
679
+ file_path: filePath
680
+ };
681
+ }
682
+ function createTaskCompletedInput(sessionId, transcriptPath, taskId, subject, description) {
683
+ return {
684
+ hook_event_name: HookEvent.TaskCompleted,
685
+ session_id: sessionId,
686
+ transcript_path: transcriptPath,
687
+ cwd: getCwd(),
688
+ permission_mode: "default",
689
+ task_id: taskId,
690
+ subject,
691
+ description
692
+ };
693
+ }
694
+ function createTeammateIdleInput(sessionId, transcriptPath, teammateName, teamName) {
695
+ return {
696
+ hook_event_name: HookEvent.TeammateIdle,
697
+ session_id: sessionId,
698
+ transcript_path: transcriptPath,
699
+ cwd: getCwd(),
700
+ permission_mode: "default",
701
+ teammate_name: teammateName,
702
+ team_name: teamName
703
+ };
704
+ }
425
705
  export {
706
+ createConfigChangeInput,
426
707
  createNotificationInput,
427
708
  createPermissionRequestInput,
428
709
  createPostCompactInput,
@@ -435,10 +716,13 @@ export {
435
716
  createStopInput,
436
717
  createSubagentStartInput,
437
718
  createSubagentStopInput,
719
+ createTaskCompletedInput,
720
+ createTeammateIdleInput,
438
721
  createUserPromptSubmitInput,
439
722
  executeHook,
440
723
  executeHooksForEvent,
441
724
  hookStatusEmitter,
442
- processHookDecisions
725
+ processHookDecisions,
726
+ resetOnceHooks
443
727
  };
444
728
  //# sourceMappingURL=hookExecutor.js.map