@within-7/minto 0.3.10 → 0.4.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.
- package/dist/Tool.js.map +2 -2
- package/dist/commands/agents/AgentsCommand.js +2 -2
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/ctx_viz.js +1 -1
- package/dist/commands/effort.js +87 -0
- package/dist/commands/effort.js.map +7 -0
- package/dist/commands/export.js +19 -9
- package/dist/commands/export.js.map +2 -2
- package/dist/commands/ide.js +18 -0
- package/dist/commands/ide.js.map +7 -0
- package/dist/commands/mcp-interactive.js +14 -8
- package/dist/commands/mcp-interactive.js.map +2 -2
- package/dist/commands/memory.js +168 -0
- package/dist/commands/memory.js.map +7 -0
- package/dist/commands/model.js +45 -2
- package/dist/commands/model.js.map +2 -2
- package/dist/commands/outputStyle.js +64 -0
- package/dist/commands/outputStyle.js.map +7 -0
- package/dist/commands/plugin/utils.js +33 -1
- package/dist/commands/plugin/utils.js.map +2 -2
- package/dist/commands/plugin.js +10 -1
- package/dist/commands/plugin.js.map +2 -2
- package/dist/commands/refreshCommands.js +2 -0
- package/dist/commands/refreshCommands.js.map +2 -2
- package/dist/commands/review.js +51 -0
- package/dist/commands/review.js.map +7 -0
- package/dist/commands/terminalSetup.js +6 -0
- package/dist/commands/terminalSetup.js.map +2 -2
- package/dist/commands/undo.js +8 -0
- package/dist/commands/undo.js.map +2 -2
- package/dist/commands/vim.js +22 -0
- package/dist/commands/vim.js.map +7 -0
- package/dist/commands.js +12 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/HighlightedCode.js +1 -0
- package/dist/components/HighlightedCode.js.map +2 -2
- package/dist/components/ModelSelector/ModelSelector.js +250 -143
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/PromptInput.js +21 -6
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/PulseLabel.js +44 -0
- package/dist/components/PulseLabel.js.map +7 -0
- package/dist/components/RequestStatusIndicator.js +1 -1
- package/dist/components/RequestStatusIndicator.js.map +1 -1
- package/dist/components/Spinner.js +12 -42
- package/dist/components/Spinner.js.map +3 -3
- package/dist/components/StartupStatus.js +57 -0
- package/dist/components/StartupStatus.js.map +7 -0
- package/dist/components/SubagentBlock.js +43 -6
- package/dist/components/SubagentBlock.js.map +2 -2
- package/dist/components/TabbedListView/TabBar.js +13 -8
- package/dist/components/TabbedListView/TabBar.js.map +2 -2
- package/dist/components/TabbedListView/TabbedListView.js +1 -1
- package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
- package/dist/components/TodoPanel.js +1 -1
- package/dist/components/TodoPanel.js.map +1 -1
- package/dist/components/ToolUseLoader.js +5 -0
- package/dist/components/ToolUseLoader.js.map +2 -2
- package/dist/components/TrustDialog.js +0 -2
- package/dist/components/TrustDialog.js.map +2 -2
- package/dist/components/messages/TaskInModuleView.js +1 -1
- package/dist/components/messages/TaskInModuleView.js.map +2 -2
- package/dist/components/messages/TaskToolMessage.js +1 -1
- package/dist/components/messages/TaskToolMessage.js.map +2 -2
- package/dist/components/messages/UserPromptMessage.js +6 -1
- package/dist/components/messages/UserPromptMessage.js.map +2 -2
- package/dist/constants/modelCapabilities.js +103 -18
- package/dist/constants/modelCapabilities.js.map +2 -2
- package/dist/constants/product.js +2 -0
- package/dist/constants/product.js.map +2 -2
- package/dist/constants/prompts/agentPrompt.js +30 -0
- package/dist/constants/prompts/agentPrompt.js.map +7 -0
- package/dist/constants/prompts/codeConventions.js +27 -0
- package/dist/constants/prompts/codeConventions.js.map +7 -0
- package/dist/constants/prompts/doingTasks.js +15 -0
- package/dist/constants/prompts/doingTasks.js.map +7 -0
- package/dist/constants/prompts/envInfo.js +17 -0
- package/dist/constants/prompts/envInfo.js.map +7 -0
- package/dist/constants/prompts/executingWithCare.js +17 -0
- package/dist/constants/prompts/executingWithCare.js.map +7 -0
- package/dist/constants/prompts/identity.js +10 -0
- package/dist/constants/prompts/identity.js.map +7 -0
- package/dist/constants/prompts/index.js +78 -0
- package/dist/constants/prompts/index.js.map +7 -0
- package/dist/constants/prompts/taskManagement.js +60 -0
- package/dist/constants/prompts/taskManagement.js.map +7 -0
- package/dist/constants/prompts/toneAndStyle.js +62 -0
- package/dist/constants/prompts/toneAndStyle.js.map +7 -0
- package/dist/constants/prompts/toolUsagePolicy.js +38 -0
- package/dist/constants/prompts/toolUsagePolicy.js.map +7 -0
- package/dist/constants/prompts.js +5 -176
- package/dist/constants/prompts.js.map +2 -2
- package/dist/constants/providerRegistry.js +235 -0
- package/dist/constants/providerRegistry.js.map +7 -0
- package/dist/constants/providers.js +35 -0
- package/dist/constants/providers.js.map +7 -0
- package/dist/context/PermissionContext.js +0 -1
- package/dist/context/PermissionContext.js.map +2 -2
- package/dist/context.js +87 -31
- package/dist/context.js.map +2 -2
- package/dist/core/backupHook.js +2 -2
- package/dist/core/backupHook.js.map +2 -2
- package/dist/core/config/defaults.js +4 -1
- package/dist/core/config/defaults.js.map +2 -2
- package/dist/core/config/schema.js +7 -1
- package/dist/core/config/schema.js.map +2 -2
- package/dist/core/costTracker.js +18 -0
- package/dist/core/costTracker.js.map +2 -2
- package/dist/core/index.js +0 -1
- package/dist/core/index.js.map +2 -2
- package/dist/core/tokenStatsManager.js +22 -4
- package/dist/core/tokenStatsManager.js.map +2 -2
- package/dist/entrypoints/cli.js +65 -84
- package/dist/entrypoints/cli.js.map +2 -2
- package/dist/hooks/useAgentTokenStats.js +1 -1
- package/dist/hooks/useAgentTokenStats.js.map +2 -2
- package/dist/hooks/useAgentTranscripts.js +2 -1
- package/dist/hooks/useAgentTranscripts.js.map +2 -2
- package/dist/hooks/useBackgroundShells.js +29 -0
- package/dist/hooks/useBackgroundShells.js.map +7 -0
- package/dist/hooks/useCanUseTool.js +1 -1
- package/dist/hooks/useCanUseTool.js.map +2 -2
- package/dist/hooks/useDeferredLoading.js +64 -0
- package/dist/hooks/useDeferredLoading.js.map +7 -0
- package/dist/hooks/useHookStatus.js +1 -1
- package/dist/hooks/useHookStatus.js.map +2 -2
- package/dist/hooks/useSessionTracking.js +55 -0
- package/dist/hooks/useSessionTracking.js.map +7 -0
- package/dist/hooks/useTerminalSize.js +21 -0
- package/dist/hooks/useTerminalSize.js.map +2 -2
- package/dist/hooks/useTextInput.js +1 -0
- package/dist/hooks/useTextInput.js.map +2 -2
- package/dist/hooks/useUnifiedCompletion.js +3 -2
- package/dist/hooks/useUnifiedCompletion.js.map +2 -2
- package/dist/i18n/locales/en.js +8 -9
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +8 -9
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/messages.js +41 -17
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js +94 -1
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +27 -19
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +83 -74
- package/dist/screens/REPL.js.map +2 -2
- package/dist/services/adapters/responsesAPI.js +6 -0
- package/dist/services/adapters/responsesAPI.js.map +2 -2
- package/dist/services/agentTeams/index.js +35 -0
- package/dist/services/agentTeams/index.js.map +7 -0
- package/dist/services/agentTeams/mailbox.js +114 -0
- package/dist/services/agentTeams/mailbox.js.map +7 -0
- package/dist/services/agentTeams/teamManager.js +149 -0
- package/dist/services/agentTeams/teamManager.js.map +7 -0
- package/dist/services/agentTeams/teamTaskStore.js +114 -0
- package/dist/services/agentTeams/teamTaskStore.js.map +7 -0
- package/dist/services/agentTeams/teammateSpawner.js +80 -0
- package/dist/services/agentTeams/teammateSpawner.js.map +7 -0
- package/dist/services/checkpointManager.js +16 -3
- package/dist/services/checkpointManager.js.map +2 -2
- package/dist/services/claude.js +19 -1728
- package/dist/services/claude.js.map +3 -3
- package/dist/services/gpt5ConnectionTest.js +4 -2
- package/dist/services/gpt5ConnectionTest.js.map +2 -2
- package/dist/services/hookExecutor.js +411 -127
- package/dist/services/hookExecutor.js.map +2 -2
- package/dist/services/llm/anthropicProvider.js +807 -0
- package/dist/services/llm/anthropicProvider.js.map +7 -0
- package/dist/services/llm/dispatch.js +218 -0
- package/dist/services/llm/dispatch.js.map +7 -0
- package/dist/services/llm/index.js +44 -0
- package/dist/services/llm/index.js.map +7 -0
- package/dist/services/llm/mintoContext.js +69 -0
- package/dist/services/llm/mintoContext.js.map +7 -0
- package/dist/services/llm/openaiProvider.js +622 -0
- package/dist/services/llm/openaiProvider.js.map +7 -0
- package/dist/services/llm/types.js +157 -0
- package/dist/services/llm/types.js.map +7 -0
- package/dist/services/mcpClient.js +183 -33
- package/dist/services/mcpClient.js.map +2 -2
- package/dist/services/notifier.js +14 -0
- package/dist/services/notifier.js.map +2 -2
- package/dist/services/oauth.js +4 -2
- package/dist/services/oauth.js.map +2 -2
- package/dist/services/openai.js +66 -56
- package/dist/services/openai.js.map +3 -3
- package/dist/services/outputStyles.js +102 -21
- package/dist/services/outputStyles.js.map +2 -2
- package/dist/services/plugins/skillMarketplace.js +4 -1
- package/dist/services/plugins/skillMarketplace.js.map +2 -2
- package/dist/services/sentry.js +1 -1
- package/dist/services/sentry.js.map +2 -2
- package/dist/services/sessionMemory.js +16 -3
- package/dist/services/sessionMemory.js.map +2 -2
- package/dist/services/systemReminder.js +350 -3
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/services/taskStore.js +19 -0
- package/dist/services/taskStore.js.map +2 -2
- package/dist/tools/ArchitectTool/ArchitectTool.js.map +1 -1
- package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +1 -1
- package/dist/tools/BashOutputTool/BashOutputTool.js.map +1 -1
- package/dist/tools/BashTool/BashTool.js +28 -0
- package/dist/tools/BashTool/BashTool.js.map +2 -2
- package/dist/tools/FileEditTool/FileEditTool.js +1 -1
- package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
- package/dist/tools/FileReadTool/FileReadTool.js +14 -0
- package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
- package/dist/tools/FileWriteTool/FileWriteTool.js +3 -1
- package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
- package/dist/tools/GlobTool/GlobTool.js.map +1 -1
- package/dist/tools/GrepTool/GrepTool.js.map +1 -1
- package/dist/tools/KillShellTool/KillShellTool.js.map +1 -1
- package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
- package/dist/tools/LspTool/LspTool.js +11 -2
- package/dist/tools/LspTool/LspTool.js.map +2 -2
- package/dist/tools/MCPTool/MCPTool.js.map +1 -1
- package/dist/tools/MemoryReadTool/MemoryReadTool.js +2 -1
- package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
- package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +2 -1
- package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
- package/dist/tools/MultiEditTool/MultiEditTool.js.map +1 -1
- package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +1 -1
- package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +1 -1
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js +8 -2
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js +2 -0
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
- package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +1 -1
- package/dist/tools/SlashCommandTool/SlashCommandTool.js +174 -18
- package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +3 -3
- package/dist/tools/TaskCreateTool/TaskCreateTool.js.map +1 -1
- package/dist/tools/TaskGetTool/TaskGetTool.js.map +1 -1
- package/dist/tools/TaskListTool/TaskListTool.js.map +1 -1
- package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +1 -1
- package/dist/tools/TaskStopTool/TaskStopTool.js.map +1 -1
- package/dist/tools/TaskTool/TaskTool.js +75 -5
- package/dist/tools/TaskTool/TaskTool.js.map +2 -2
- package/dist/tools/TaskTool/prompt.js +12 -6
- package/dist/tools/TaskTool/prompt.js.map +2 -2
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +1 -1
- package/dist/tools/ThinkTool/ThinkTool.js.map +1 -1
- package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +1 -1
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +1 -1
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +1 -1
- package/dist/tools/WebSearchTool/searchProviders.js +2 -1
- package/dist/tools/WebSearchTool/searchProviders.js.map +2 -2
- package/dist/tools/lsTool/lsTool.js.map +2 -2
- package/dist/tools/lsTool/prompt.js.map +1 -1
- package/dist/tools.js +14 -3
- package/dist/tools.js.map +2 -2
- package/dist/types/PermissionMode.js +21 -1
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/agentTeams.js +1 -0
- package/dist/types/agentTeams.js.map +7 -0
- package/dist/types/hooks.js +8 -2
- package/dist/types/hooks.js.map +2 -2
- package/dist/types/plugin.js +1 -1
- package/dist/types/plugin.js.map +2 -2
- package/dist/utils/agentLoader.js +25 -3
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/animationManager.js +1 -1
- package/dist/utils/animationManager.js.map +2 -2
- package/dist/utils/ask.js +1 -1
- package/dist/utils/async.js +5 -1
- package/dist/utils/async.js.map +2 -2
- package/dist/utils/autoCompactCore.js +60 -0
- package/dist/utils/autoCompactCore.js.map +2 -2
- package/dist/utils/config.js +26 -128
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configSchema.js +227 -0
- package/dist/utils/configSchema.js.map +7 -0
- package/dist/utils/debugLogger.js.map +2 -2
- package/dist/utils/env.js +4 -3
- package/dist/utils/env.js.map +2 -2
- package/dist/utils/envConfig.js +34 -0
- package/dist/utils/envConfig.js.map +3 -3
- package/dist/utils/gpt5.js +146 -0
- package/dist/utils/gpt5.js.map +7 -0
- package/dist/utils/hookManager.js +374 -140
- package/dist/utils/hookManager.js.map +2 -2
- package/dist/utils/markdown.js +47 -0
- package/dist/utils/markdown.js.map +2 -2
- package/dist/utils/memoizeWithTTL.js +25 -0
- package/dist/utils/memoizeWithTTL.js.map +7 -0
- package/dist/utils/model.js +34 -9
- package/dist/utils/model.js.map +2 -2
- package/dist/utils/pluginInstaller.js +34 -5
- package/dist/utils/pluginInstaller.js.map +2 -2
- package/dist/utils/pluginLoader.js +201 -32
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/safeFetch.js +45 -0
- package/dist/utils/safeFetch.js.map +7 -0
- package/dist/utils/skillLoader.js +59 -6
- package/dist/utils/skillLoader.js.map +2 -2
- package/dist/utils/streamingState.js +52 -0
- package/dist/utils/streamingState.js.map +7 -0
- package/dist/utils/style.js +6 -3
- package/dist/utils/style.js.map +2 -2
- package/dist/utils/teamConfig.js +9 -3
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/toolRiskClassification.js +0 -6
- package/dist/utils/toolRiskClassification.js.map +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,27 +1,80 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import { HookEvent, HooksConfigSchema } from "../types/hooks.js";
|
|
5
|
+
import { emitReminderEvent } from "../services/systemReminder.js";
|
|
2
6
|
import {
|
|
3
7
|
executeHooksForEvent,
|
|
4
8
|
processHookDecisions,
|
|
5
9
|
createPreToolUseInput,
|
|
6
10
|
createPostToolUseInput,
|
|
11
|
+
createPostToolUseFailureInput,
|
|
12
|
+
createPermissionRequestInput,
|
|
7
13
|
createUserPromptSubmitInput,
|
|
8
14
|
createSessionStartInput,
|
|
9
|
-
createSessionEndInput
|
|
15
|
+
createSessionEndInput,
|
|
16
|
+
createStopInput,
|
|
17
|
+
createSubagentStartInput,
|
|
18
|
+
createSubagentStopInput,
|
|
19
|
+
createNotificationInput,
|
|
20
|
+
createPreCompactInput,
|
|
21
|
+
createPostCompactInput,
|
|
22
|
+
createConfigChangeInput,
|
|
23
|
+
createTaskCompletedInput,
|
|
24
|
+
createTeammateIdleInput,
|
|
25
|
+
resetOnceHooks
|
|
10
26
|
} from "../services/hookExecutor.js";
|
|
27
|
+
import { safeParseJSON } from "./json.js";
|
|
28
|
+
import { getCwd } from "./state.js";
|
|
11
29
|
const logInfo = (msg) => {
|
|
12
30
|
if (process.env.DEBUG) console.log(`[INFO] ${msg}`);
|
|
13
31
|
};
|
|
14
32
|
const logDebug = (msg, ...args) => {
|
|
15
33
|
if (process.env.DEBUG) console.log(`[DEBUG] ${msg}`, ...args);
|
|
16
34
|
};
|
|
35
|
+
function matchHook(hook, toolName, toolInput) {
|
|
36
|
+
if (hook.matcher) {
|
|
37
|
+
if (hook.matcher !== "*" && hook.matcher !== "") {
|
|
38
|
+
try {
|
|
39
|
+
const regex = new RegExp(hook.matcher);
|
|
40
|
+
if (!regex.test(toolName)) return false;
|
|
41
|
+
} catch {
|
|
42
|
+
if (hook.matcher !== toolName) return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const hookConfig = hook.config;
|
|
47
|
+
if (hookConfig.toolInput && toolInput) {
|
|
48
|
+
for (const [field, pattern] of Object.entries(
|
|
49
|
+
hookConfig.toolInput
|
|
50
|
+
)) {
|
|
51
|
+
const fieldValue = String(toolInput[field] ?? "");
|
|
52
|
+
try {
|
|
53
|
+
const regex = new RegExp(pattern);
|
|
54
|
+
if (!regex.test(fieldValue)) return false;
|
|
55
|
+
} catch {
|
|
56
|
+
if (fieldValue !== pattern) return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
const ALLOW_RESULT = {
|
|
63
|
+
shouldContinue: true,
|
|
64
|
+
shouldAskUser: false
|
|
65
|
+
};
|
|
17
66
|
class HookManager {
|
|
18
67
|
plugins = [];
|
|
68
|
+
settingsHooks = [];
|
|
69
|
+
managedHooks = [];
|
|
19
70
|
sessionId;
|
|
20
71
|
transcriptPath;
|
|
21
72
|
enabled = true;
|
|
73
|
+
disableAllHooks = false;
|
|
22
74
|
constructor(sessionId, transcriptPath) {
|
|
23
75
|
this.sessionId = sessionId;
|
|
24
76
|
this.transcriptPath = transcriptPath;
|
|
77
|
+
resetOnceHooks();
|
|
25
78
|
}
|
|
26
79
|
/**
|
|
27
80
|
* Register plugins with hooks
|
|
@@ -33,6 +86,94 @@ class HookManager {
|
|
|
33
86
|
`HookManager: Registered ${plugins.length} plugin(s) with ${totalHooks} hook(s)`
|
|
34
87
|
);
|
|
35
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Load hooks from settings.json files
|
|
91
|
+
* Priority (high to low): managed > .minto/settings.json > .claude/settings.json >
|
|
92
|
+
* .minto/settings.local.json > ~/.minto/settings.json > ~/.claude/settings.json
|
|
93
|
+
*/
|
|
94
|
+
loadSettingsHooks() {
|
|
95
|
+
const cwd = getCwd();
|
|
96
|
+
const home = homedir();
|
|
97
|
+
const settingsPaths = [
|
|
98
|
+
join(home, ".claude", "settings.json"),
|
|
99
|
+
join(home, ".minto", "settings.json"),
|
|
100
|
+
join(cwd, ".minto", "settings.local.json"),
|
|
101
|
+
join(cwd, ".claude", "settings.json"),
|
|
102
|
+
join(cwd, ".minto", "settings.json")
|
|
103
|
+
];
|
|
104
|
+
const allHooks = [];
|
|
105
|
+
for (const settingsPath of settingsPaths) {
|
|
106
|
+
try {
|
|
107
|
+
if (!existsSync(settingsPath)) continue;
|
|
108
|
+
const content = readFileSync(settingsPath, "utf-8");
|
|
109
|
+
const settings = safeParseJSON(content);
|
|
110
|
+
if (!settings || typeof settings !== "object") continue;
|
|
111
|
+
const hooksConfig = settings.hooks;
|
|
112
|
+
if (!hooksConfig || typeof hooksConfig !== "object") continue;
|
|
113
|
+
const parsed = HooksConfigSchema.safeParse({ hooks: hooksConfig });
|
|
114
|
+
if (!parsed.success) {
|
|
115
|
+
logDebug(`Invalid hooks in ${settingsPath}: ${parsed.error.message}`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const hooks = parsed.data.hooks;
|
|
119
|
+
if (!hooks) continue;
|
|
120
|
+
for (const [eventName, matchers] of Object.entries(hooks)) {
|
|
121
|
+
const event = eventName;
|
|
122
|
+
for (const matcher of matchers) {
|
|
123
|
+
for (let i = 0; i < matcher.hooks.length; i++) {
|
|
124
|
+
const hookDef = matcher.hooks[i];
|
|
125
|
+
allHooks.push({
|
|
126
|
+
name: `settings:${eventName}:${i}`,
|
|
127
|
+
filePath: settingsPath,
|
|
128
|
+
config: {
|
|
129
|
+
event,
|
|
130
|
+
matcher: matcher.matcher,
|
|
131
|
+
type: hookDef.type,
|
|
132
|
+
command: hookDef.command,
|
|
133
|
+
timeout: hookDef.timeout,
|
|
134
|
+
once: hookDef.once,
|
|
135
|
+
async: hookDef.async
|
|
136
|
+
},
|
|
137
|
+
pluginName: "settings",
|
|
138
|
+
event,
|
|
139
|
+
matcher: matcher.matcher
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch (err) {
|
|
145
|
+
logDebug(`Error loading hooks from ${settingsPath}: ${err}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
this.settingsHooks = allHooks;
|
|
149
|
+
try {
|
|
150
|
+
const localSettings = join(cwd, ".minto", "settings.json");
|
|
151
|
+
const globalSettings = join(home, ".minto", "settings.json");
|
|
152
|
+
for (const p of [localSettings, globalSettings]) {
|
|
153
|
+
if (existsSync(p)) {
|
|
154
|
+
const content = safeParseJSON(readFileSync(p, "utf-8"));
|
|
155
|
+
if (content && content.disableAllHooks) {
|
|
156
|
+
this.disableAllHooks = true;
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
163
|
+
logInfo(`HookManager: Loaded ${allHooks.length} hook(s) from settings`);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Dynamically add temporary hooks (e.g., skill-level hooks)
|
|
167
|
+
* Returns a cleanup function to remove them
|
|
168
|
+
*/
|
|
169
|
+
addHooks(hooks) {
|
|
170
|
+
this.settingsHooks.push(...hooks);
|
|
171
|
+
logDebug(`HookManager: Added ${hooks.length} temporary hook(s)`);
|
|
172
|
+
return () => {
|
|
173
|
+
this.settingsHooks = this.settingsHooks.filter((h) => !hooks.includes(h));
|
|
174
|
+
logDebug(`HookManager: Removed ${hooks.length} temporary hook(s)`);
|
|
175
|
+
};
|
|
176
|
+
}
|
|
36
177
|
/**
|
|
37
178
|
* Enable or disable hook execution
|
|
38
179
|
*/
|
|
@@ -41,80 +182,117 @@ class HookManager {
|
|
|
41
182
|
logDebug(`HookManager: ${enabled ? "Enabled" : "Disabled"}`);
|
|
42
183
|
}
|
|
43
184
|
/**
|
|
44
|
-
*
|
|
185
|
+
* Get all hooks (plugins + settings), respecting disableAllHooks
|
|
45
186
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
187
|
+
getAllHooks() {
|
|
188
|
+
const managed = this.managedHooks;
|
|
189
|
+
if (this.disableAllHooks) {
|
|
190
|
+
return managed;
|
|
49
191
|
}
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
192
|
+
const pluginHooks = this.plugins.flatMap((p) => p.hooks);
|
|
193
|
+
return [...pluginHooks, ...this.settingsHooks, ...managed];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get matching hooks for a tool-based event
|
|
197
|
+
*/
|
|
198
|
+
getMatchingToolHooks(event, toolName, toolInput) {
|
|
199
|
+
const allHooks = this.getAllHooks();
|
|
200
|
+
const matching = allHooks.filter((hook) => {
|
|
201
|
+
if (hook.event !== event) return false;
|
|
202
|
+
return matchHook(hook, toolName, toolInput);
|
|
61
203
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
204
|
+
return { hooks: matching, plugins: this.plugins };
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get matching hooks for a non-tool event
|
|
208
|
+
*/
|
|
209
|
+
getMatchingEventHooks(event) {
|
|
210
|
+
return this.getAllHooks().filter((hook) => hook.event === event);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Find plugin root for a hook
|
|
214
|
+
*/
|
|
215
|
+
getPluginRoot(hook) {
|
|
216
|
+
const plugin = this.plugins.find((p) => p.manifest.name === hook.pluginName);
|
|
217
|
+
return plugin?.location || getCwd();
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Execute hooks for a tool-based event (PreToolUse, PostToolUse, etc.)
|
|
221
|
+
*/
|
|
222
|
+
async executeToolEvent(event, toolName, input, toolInput) {
|
|
223
|
+
if (!this.enabled) return ALLOW_RESULT;
|
|
224
|
+
const { hooks } = this.getMatchingToolHooks(event, toolName, toolInput);
|
|
225
|
+
if (hooks.length === 0) return ALLOW_RESULT;
|
|
226
|
+
logDebug(`${event}: ${hooks.length} hook(s) matched for tool: ${toolName}`);
|
|
74
227
|
const results = [];
|
|
75
|
-
for (const hook of
|
|
76
|
-
const plugin = this.plugins.find((p) => p.manifest.name === hook.pluginName);
|
|
77
|
-
if (!plugin) continue;
|
|
228
|
+
for (const hook of hooks) {
|
|
78
229
|
const options = {
|
|
79
230
|
sessionId: this.sessionId,
|
|
80
231
|
transcriptPath: this.transcriptPath,
|
|
81
|
-
pluginRoot:
|
|
232
|
+
pluginRoot: this.getPluginRoot(hook)
|
|
82
233
|
};
|
|
83
|
-
const result = await executeHooksForEvent(
|
|
84
|
-
HookEvent.PreToolUse,
|
|
85
|
-
[hook],
|
|
86
|
-
input,
|
|
87
|
-
options
|
|
88
|
-
);
|
|
234
|
+
const result = await executeHooksForEvent(event, [hook], input, options);
|
|
89
235
|
results.push(...result);
|
|
90
236
|
}
|
|
91
237
|
return processHookDecisions(results);
|
|
92
238
|
}
|
|
93
239
|
/**
|
|
94
|
-
* Execute
|
|
240
|
+
* Execute hooks for a non-tool event (fire-and-forget)
|
|
95
241
|
*/
|
|
96
|
-
async
|
|
97
|
-
if (!this.enabled)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
242
|
+
async executeFireAndForget(event, input) {
|
|
243
|
+
if (!this.enabled) return;
|
|
244
|
+
const hooks = this.getMatchingEventHooks(event);
|
|
245
|
+
if (hooks.length === 0) return;
|
|
246
|
+
logDebug(`${event}: ${hooks.length} hook(s)`);
|
|
247
|
+
await Promise.allSettled(
|
|
248
|
+
hooks.map((hook) => {
|
|
249
|
+
const options = {
|
|
250
|
+
sessionId: this.sessionId,
|
|
251
|
+
transcriptPath: this.transcriptPath,
|
|
252
|
+
pluginRoot: this.getPluginRoot(hook)
|
|
253
|
+
};
|
|
254
|
+
return executeHooksForEvent(event, [hook], input, options);
|
|
255
|
+
})
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Execute hooks for a blockable non-tool event
|
|
260
|
+
*/
|
|
261
|
+
async executeBlockableEvent(event, input) {
|
|
262
|
+
if (!this.enabled) return ALLOW_RESULT;
|
|
263
|
+
const hooks = this.getMatchingEventHooks(event);
|
|
264
|
+
if (hooks.length === 0) return ALLOW_RESULT;
|
|
265
|
+
logDebug(`${event}: ${hooks.length} hook(s)`);
|
|
266
|
+
const results = [];
|
|
267
|
+
for (const hook of hooks) {
|
|
268
|
+
const options = {
|
|
269
|
+
sessionId: this.sessionId,
|
|
270
|
+
transcriptPath: this.transcriptPath,
|
|
271
|
+
pluginRoot: this.getPluginRoot(hook)
|
|
272
|
+
};
|
|
273
|
+
const result = await executeHooksForEvent(event, [hook], input, options);
|
|
274
|
+
results.push(...result);
|
|
114
275
|
}
|
|
115
|
-
|
|
116
|
-
|
|
276
|
+
return processHookDecisions(results);
|
|
277
|
+
}
|
|
278
|
+
// ========================================================================
|
|
279
|
+
// Public event methods
|
|
280
|
+
// ========================================================================
|
|
281
|
+
async executePreToolUse(toolName, toolInput) {
|
|
282
|
+
const input = createPreToolUseInput(
|
|
283
|
+
this.sessionId,
|
|
284
|
+
this.transcriptPath,
|
|
285
|
+
toolName,
|
|
286
|
+
toolInput
|
|
287
|
+
);
|
|
288
|
+
return this.executeToolEvent(
|
|
289
|
+
HookEvent.PreToolUse,
|
|
290
|
+
toolName,
|
|
291
|
+
input,
|
|
292
|
+
toolInput
|
|
117
293
|
);
|
|
294
|
+
}
|
|
295
|
+
async executePostToolUse(toolName, toolInput, toolOutput) {
|
|
118
296
|
const input = createPostToolUseInput(
|
|
119
297
|
this.sessionId,
|
|
120
298
|
this.transcriptPath,
|
|
@@ -122,119 +300,175 @@ class HookManager {
|
|
|
122
300
|
toolInput,
|
|
123
301
|
toolOutput
|
|
124
302
|
);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
303
|
+
await this.executeFireAndForget(HookEvent.PostToolUse, input);
|
|
304
|
+
}
|
|
305
|
+
async executePostToolUseFailure(toolName, toolInput, error, errorType) {
|
|
306
|
+
const input = createPostToolUseFailureInput(
|
|
307
|
+
this.sessionId,
|
|
308
|
+
this.transcriptPath,
|
|
309
|
+
toolName,
|
|
310
|
+
toolInput,
|
|
311
|
+
error,
|
|
312
|
+
errorType
|
|
313
|
+
);
|
|
314
|
+
await this.executeFireAndForget(HookEvent.PostToolUseFailure, input);
|
|
315
|
+
emitReminderEvent("diagnostics:new", {
|
|
316
|
+
source: toolName,
|
|
317
|
+
count: 1
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
async executePermissionRequest(toolName, toolInput, permissionType, description) {
|
|
321
|
+
const input = createPermissionRequestInput(
|
|
322
|
+
this.sessionId,
|
|
323
|
+
this.transcriptPath,
|
|
324
|
+
toolName,
|
|
325
|
+
toolInput,
|
|
326
|
+
permissionType,
|
|
327
|
+
description
|
|
328
|
+
);
|
|
329
|
+
return this.executeBlockableEvent(HookEvent.PermissionRequest, input);
|
|
135
330
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Execute UserPromptSubmit hooks
|
|
138
|
-
*/
|
|
139
331
|
async executeUserPromptSubmit(userPrompt) {
|
|
140
|
-
|
|
141
|
-
|
|
332
|
+
const input = createUserPromptSubmitInput(
|
|
333
|
+
this.sessionId,
|
|
334
|
+
this.transcriptPath,
|
|
335
|
+
userPrompt
|
|
336
|
+
);
|
|
337
|
+
return this.executeBlockableEvent(HookEvent.UserPromptSubmit, input);
|
|
338
|
+
}
|
|
339
|
+
async executeSessionStart() {
|
|
340
|
+
const input = createSessionStartInput(this.sessionId, this.transcriptPath);
|
|
341
|
+
await this.executeFireAndForget(HookEvent.SessionStart, input);
|
|
342
|
+
}
|
|
343
|
+
async executeSessionEnd(reason = "other") {
|
|
344
|
+
const input = createSessionEndInput(
|
|
345
|
+
this.sessionId,
|
|
346
|
+
this.transcriptPath,
|
|
347
|
+
reason
|
|
348
|
+
);
|
|
349
|
+
await this.executeFireAndForget(HookEvent.SessionEnd, input);
|
|
350
|
+
}
|
|
351
|
+
async executeStop(lastAssistantMessage) {
|
|
352
|
+
const input = createStopInput(this.sessionId, this.transcriptPath, true);
|
|
353
|
+
if (lastAssistantMessage) {
|
|
354
|
+
;
|
|
355
|
+
input.last_assistant_message = lastAssistantMessage;
|
|
142
356
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
357
|
+
return this.executeBlockableEvent(HookEvent.Stop, input);
|
|
358
|
+
}
|
|
359
|
+
async executeSubagentStart(agentType, agentDescription, runInBackground) {
|
|
360
|
+
const input = createSubagentStartInput(
|
|
361
|
+
this.sessionId,
|
|
362
|
+
this.transcriptPath,
|
|
363
|
+
agentType,
|
|
364
|
+
agentDescription,
|
|
365
|
+
runInBackground
|
|
366
|
+
);
|
|
367
|
+
await this.executeFireAndForget(HookEvent.SubagentStart, input);
|
|
368
|
+
}
|
|
369
|
+
async executeSubagentStop(agentType, agentId, transcriptPath, lastMessage) {
|
|
370
|
+
const input = createSubagentStopInput(
|
|
371
|
+
this.sessionId,
|
|
372
|
+
this.transcriptPath,
|
|
373
|
+
agentType,
|
|
374
|
+
agentId
|
|
146
375
|
);
|
|
147
|
-
if (
|
|
148
|
-
|
|
376
|
+
if (transcriptPath) {
|
|
377
|
+
;
|
|
378
|
+
input.agent_transcript_path = transcriptPath;
|
|
149
379
|
}
|
|
150
|
-
|
|
151
|
-
|
|
380
|
+
if (lastMessage) {
|
|
381
|
+
;
|
|
382
|
+
input.last_message = lastMessage;
|
|
383
|
+
}
|
|
384
|
+
return this.executeBlockableEvent(HookEvent.SubagentStop, input);
|
|
385
|
+
}
|
|
386
|
+
async executeNotification(message, title, type) {
|
|
387
|
+
if (!this.enabled) return {};
|
|
388
|
+
const input = createNotificationInput(
|
|
152
389
|
this.sessionId,
|
|
153
390
|
this.transcriptPath,
|
|
154
|
-
|
|
391
|
+
message,
|
|
392
|
+
title,
|
|
393
|
+
type
|
|
155
394
|
);
|
|
395
|
+
const hooks = this.getMatchingEventHooks(HookEvent.Notification);
|
|
396
|
+
if (hooks.length === 0) return {};
|
|
156
397
|
const results = [];
|
|
157
|
-
for (const hook of
|
|
158
|
-
const plugin = this.plugins.find((p) => p.manifest.name === hook.pluginName);
|
|
159
|
-
if (!plugin) continue;
|
|
398
|
+
for (const hook of hooks) {
|
|
160
399
|
const options = {
|
|
161
400
|
sessionId: this.sessionId,
|
|
162
401
|
transcriptPath: this.transcriptPath,
|
|
163
|
-
pluginRoot:
|
|
402
|
+
pluginRoot: this.getPluginRoot(hook)
|
|
164
403
|
};
|
|
165
404
|
const result = await executeHooksForEvent(
|
|
166
|
-
HookEvent.
|
|
405
|
+
HookEvent.Notification,
|
|
167
406
|
[hook],
|
|
168
407
|
input,
|
|
169
408
|
options
|
|
170
409
|
);
|
|
171
410
|
results.push(...result);
|
|
172
411
|
}
|
|
173
|
-
|
|
412
|
+
const suppress = results.some(
|
|
413
|
+
(r) => r.success && r.output?.suppressNotification
|
|
414
|
+
);
|
|
415
|
+
return { suppressNotification: suppress };
|
|
174
416
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
const allHooks = this.plugins.flatMap((p) => p.hooks);
|
|
183
|
-
const matchingHooks = allHooks.filter(
|
|
184
|
-
(hook) => hook.event === HookEvent.SessionStart
|
|
417
|
+
async executePreCompact(trigger, customInstructions) {
|
|
418
|
+
const input = createPreCompactInput(
|
|
419
|
+
this.sessionId,
|
|
420
|
+
this.transcriptPath,
|
|
421
|
+
trigger,
|
|
422
|
+
customInstructions || ""
|
|
185
423
|
);
|
|
186
|
-
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
logInfo(`SessionStart: Executing ${matchingHooks.length} hook(s)`);
|
|
190
|
-
const input = createSessionStartInput(this.sessionId, this.transcriptPath);
|
|
191
|
-
for (const hook of matchingHooks) {
|
|
192
|
-
const plugin = this.plugins.find((p) => p.manifest.name === hook.pluginName);
|
|
193
|
-
if (!plugin) continue;
|
|
194
|
-
const options = {
|
|
195
|
-
sessionId: this.sessionId,
|
|
196
|
-
transcriptPath: this.transcriptPath,
|
|
197
|
-
pluginRoot: plugin.location
|
|
198
|
-
};
|
|
199
|
-
await executeHooksForEvent(HookEvent.SessionStart, [hook], input, options);
|
|
200
|
-
}
|
|
424
|
+
await this.executeFireAndForget(HookEvent.PreCompact, input);
|
|
201
425
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
(hook) => hook.event === HookEvent.SessionEnd
|
|
426
|
+
async executePostCompact(trigger, summary, compressionRatio, originalTokens, compressedTokens) {
|
|
427
|
+
const input = createPostCompactInput(
|
|
428
|
+
this.sessionId,
|
|
429
|
+
this.transcriptPath,
|
|
430
|
+
trigger,
|
|
431
|
+
summary,
|
|
432
|
+
compressionRatio,
|
|
433
|
+
originalTokens,
|
|
434
|
+
compressedTokens
|
|
212
435
|
);
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const input = createSessionEndInput(
|
|
436
|
+
await this.executeFireAndForget(HookEvent.PostCompact, input);
|
|
437
|
+
}
|
|
438
|
+
async executeConfigChange(source, filePath) {
|
|
439
|
+
const input = createConfigChangeInput(
|
|
218
440
|
this.sessionId,
|
|
219
441
|
this.transcriptPath,
|
|
220
|
-
|
|
442
|
+
source,
|
|
443
|
+
filePath
|
|
221
444
|
);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
445
|
+
return this.executeBlockableEvent(HookEvent.ConfigChange, input);
|
|
446
|
+
}
|
|
447
|
+
async executeTaskCompleted(taskId, subject, description) {
|
|
448
|
+
const input = createTaskCompletedInput(
|
|
449
|
+
this.sessionId,
|
|
450
|
+
this.transcriptPath,
|
|
451
|
+
taskId,
|
|
452
|
+
subject,
|
|
453
|
+
description
|
|
454
|
+
);
|
|
455
|
+
return this.executeBlockableEvent(HookEvent.TaskCompleted, input);
|
|
456
|
+
}
|
|
457
|
+
async executeTeammateIdle(teammateName, teamName) {
|
|
458
|
+
const input = createTeammateIdleInput(
|
|
459
|
+
this.sessionId,
|
|
460
|
+
this.transcriptPath,
|
|
461
|
+
teammateName,
|
|
462
|
+
teamName
|
|
463
|
+
);
|
|
464
|
+
return this.executeBlockableEvent(HookEvent.TeammateIdle, input);
|
|
232
465
|
}
|
|
233
466
|
}
|
|
234
467
|
let globalHookManager = null;
|
|
235
468
|
function initializeHookManager(sessionId, transcriptPath, plugins) {
|
|
236
469
|
globalHookManager = new HookManager(sessionId, transcriptPath);
|
|
237
470
|
globalHookManager.registerPlugins(plugins);
|
|
471
|
+
globalHookManager.loadSettingsHooks();
|
|
238
472
|
return globalHookManager;
|
|
239
473
|
}
|
|
240
474
|
function getHookManager() {
|