wave-agent-sdk 0.0.7 → 0.0.10
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/agent.d.ts +105 -24
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +438 -53
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/managers/aiManager.d.ts +18 -7
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +254 -142
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +11 -9
- package/dist/managers/hookManager.d.ts +6 -6
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +81 -39
- package/dist/managers/liveConfigManager.d.ts +95 -0
- package/dist/managers/liveConfigManager.d.ts.map +1 -0
- package/dist/managers/liveConfigManager.js +442 -0
- package/dist/managers/lspManager.d.ts +43 -0
- package/dist/managers/lspManager.d.ts.map +1 -0
- package/dist/managers/lspManager.js +326 -0
- package/dist/managers/messageManager.d.ts +41 -24
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +184 -73
- package/dist/managers/permissionManager.d.ts +66 -0
- package/dist/managers/permissionManager.d.ts.map +1 -0
- package/dist/managers/permissionManager.js +208 -0
- package/dist/managers/skillManager.d.ts +1 -0
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +2 -1
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +4 -2
- package/dist/managers/subagentManager.d.ts +42 -6
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +213 -62
- package/dist/managers/toolManager.d.ts +38 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +66 -2
- package/dist/services/aiService.d.ts +15 -5
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +446 -77
- package/dist/services/configurationService.d.ts +116 -0
- package/dist/services/configurationService.d.ts.map +1 -0
- package/dist/services/configurationService.js +585 -0
- package/dist/services/fileWatcher.d.ts +69 -0
- package/dist/services/fileWatcher.d.ts.map +1 -0
- package/dist/services/fileWatcher.js +212 -0
- package/dist/services/hook.d.ts +5 -40
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +47 -109
- package/dist/services/jsonlHandler.d.ts +71 -0
- package/dist/services/jsonlHandler.d.ts.map +1 -0
- package/dist/services/jsonlHandler.js +236 -0
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +33 -11
- package/dist/services/session.d.ts +116 -52
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +415 -143
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +77 -17
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +27 -1
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +33 -8
- package/dist/tools/lspTool.d.ts +6 -0
- package/dist/tools/lspTool.d.ts.map +1 -0
- package/dist/tools/lspTool.js +589 -0
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +30 -10
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +113 -3
- package/dist/tools/skillTool.js +2 -2
- package/dist/tools/todoWriteTool.d.ts.map +1 -1
- package/dist/tools/todoWriteTool.js +23 -0
- package/dist/tools/types.d.ts +11 -8
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +30 -15
- package/dist/types/commands.d.ts +4 -1
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/configuration.d.ts +69 -0
- package/dist/types/configuration.d.ts.map +1 -0
- package/dist/types/configuration.js +8 -0
- package/dist/types/core.d.ts +45 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +83 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/environment.js +21 -0
- package/dist/types/fileSearch.d.ts +5 -0
- package/dist/types/fileSearch.d.ts.map +1 -0
- package/dist/types/fileSearch.js +1 -0
- package/dist/types/hooks.d.ts +18 -3
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +8 -8
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +7 -0
- package/dist/types/lsp.d.ts +90 -0
- package/dist/types/lsp.d.ts.map +1 -0
- package/dist/types/lsp.js +4 -0
- package/dist/types/messaging.d.ts +19 -12
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/permissions.d.ts +35 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/permissions.js +12 -0
- package/dist/types/session.d.ts +15 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +7 -0
- package/dist/types/skills.d.ts +1 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/tools.d.ts +35 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +4 -0
- package/dist/utils/abortUtils.d.ts +34 -0
- package/dist/utils/abortUtils.d.ts.map +1 -0
- package/dist/utils/abortUtils.js +92 -0
- package/dist/utils/bashHistory.d.ts +4 -0
- package/dist/utils/bashHistory.d.ts.map +1 -1
- package/dist/utils/bashHistory.js +48 -30
- package/dist/utils/builtinSubagents.d.ts +7 -0
- package/dist/utils/builtinSubagents.d.ts.map +1 -0
- package/dist/utils/builtinSubagents.js +65 -0
- package/dist/utils/cacheControlUtils.d.ts +96 -0
- package/dist/utils/cacheControlUtils.d.ts.map +1 -0
- package/dist/utils/cacheControlUtils.js +324 -0
- package/dist/utils/commandPathResolver.d.ts +52 -0
- package/dist/utils/commandPathResolver.d.ts.map +1 -0
- package/dist/utils/commandPathResolver.js +145 -0
- package/dist/utils/configPaths.d.ts +85 -0
- package/dist/utils/configPaths.d.ts.map +1 -0
- package/dist/utils/configPaths.js +121 -0
- package/dist/utils/constants.d.ts +1 -13
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +2 -14
- package/dist/utils/convertMessagesForAPI.d.ts +2 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +39 -18
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/utils/customCommands.js +66 -21
- package/dist/utils/fileSearch.d.ts +14 -0
- package/dist/utils/fileSearch.d.ts.map +1 -0
- package/dist/utils/fileSearch.js +88 -0
- package/dist/utils/fileUtils.d.ts +27 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +145 -0
- package/dist/utils/globalLogger.d.ts +88 -0
- package/dist/utils/globalLogger.d.ts.map +1 -0
- package/dist/utils/globalLogger.js +120 -0
- package/dist/utils/largeOutputHandler.d.ts +15 -0
- package/dist/utils/largeOutputHandler.d.ts.map +1 -0
- package/dist/utils/largeOutputHandler.js +40 -0
- package/dist/utils/markdownParser.d.ts.map +1 -1
- package/dist/utils/markdownParser.js +1 -17
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +25 -3
- package/dist/utils/messageOperations.d.ts +20 -18
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +30 -38
- package/dist/utils/pathEncoder.d.ts +108 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -0
- package/dist/utils/pathEncoder.js +279 -0
- package/dist/utils/subagentParser.d.ts +2 -2
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +12 -8
- package/dist/utils/tokenCalculation.d.ts +26 -0
- package/dist/utils/tokenCalculation.d.ts.map +1 -0
- package/dist/utils/tokenCalculation.js +36 -0
- package/dist/utils/tokenEstimator.d.ts +39 -0
- package/dist/utils/tokenEstimator.d.ts.map +1 -0
- package/dist/utils/tokenEstimator.js +55 -0
- package/package.json +6 -6
- package/src/agent.ts +586 -78
- package/src/index.ts +4 -0
- package/src/managers/aiManager.ts +341 -192
- package/src/managers/backgroundBashManager.ts +11 -9
- package/src/managers/hookManager.ts +102 -54
- package/src/managers/liveConfigManager.ts +634 -0
- package/src/managers/lspManager.ts +434 -0
- package/src/managers/messageManager.ts +258 -121
- package/src/managers/permissionManager.ts +276 -0
- package/src/managers/skillManager.ts +3 -1
- package/src/managers/slashCommandManager.ts +5 -3
- package/src/managers/subagentManager.ts +295 -76
- package/src/managers/toolManager.ts +95 -3
- package/src/services/aiService.ts +656 -84
- package/src/services/configurationService.ts +762 -0
- package/src/services/fileWatcher.ts +300 -0
- package/src/services/hook.ts +54 -144
- package/src/services/jsonlHandler.ts +303 -0
- package/src/services/memory.ts +34 -11
- package/src/services/session.ts +522 -173
- package/src/tools/bashTool.ts +94 -20
- package/src/tools/deleteFileTool.ts +38 -1
- package/src/tools/editTool.ts +44 -9
- package/src/tools/lspTool.ts +760 -0
- package/src/tools/multiEditTool.ts +41 -11
- package/src/tools/readTool.ts +127 -3
- package/src/tools/skillTool.ts +2 -2
- package/src/tools/todoWriteTool.ts +33 -1
- package/src/tools/types.ts +15 -9
- package/src/tools/writeTool.ts +43 -16
- package/src/types/commands.ts +6 -1
- package/src/types/config.ts +5 -0
- package/src/types/configuration.ts +73 -0
- package/src/types/core.ts +55 -0
- package/src/types/environment.ts +104 -0
- package/src/types/fileSearch.ts +4 -0
- package/src/types/hooks.ts +32 -16
- package/src/types/index.ts +7 -0
- package/src/types/lsp.ts +96 -0
- package/src/types/messaging.ts +21 -14
- package/src/types/permissions.ts +48 -0
- package/src/types/session.ts +20 -0
- package/src/types/skills.ts +1 -0
- package/src/types/tools.ts +38 -0
- package/src/utils/abortUtils.ts +118 -0
- package/src/utils/bashHistory.ts +55 -31
- package/src/utils/builtinSubagents.ts +71 -0
- package/src/utils/cacheControlUtils.ts +475 -0
- package/src/utils/commandPathResolver.ts +189 -0
- package/src/utils/configPaths.ts +163 -0
- package/src/utils/constants.ts +2 -17
- package/src/utils/convertMessagesForAPI.ts +44 -18
- package/src/utils/customCommands.ts +90 -22
- package/src/utils/fileSearch.ts +107 -0
- package/src/utils/fileUtils.ts +160 -0
- package/src/utils/globalLogger.ts +128 -0
- package/src/utils/largeOutputHandler.ts +55 -0
- package/src/utils/markdownParser.ts +1 -19
- package/src/utils/mcpUtils.ts +34 -3
- package/src/utils/messageOperations.ts +47 -53
- package/src/utils/pathEncoder.ts +394 -0
- package/src/utils/subagentParser.ts +13 -9
- package/src/utils/tokenCalculation.ts +43 -0
- package/src/utils/tokenEstimator.ts +68 -0
- package/dist/utils/configResolver.d.ts +0 -38
- package/dist/utils/configResolver.d.ts.map +0 -1
- package/dist/utils/configResolver.js +0 -106
- package/src/utils/configResolver.ts +0 -142
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { addAssistantMessageToMessages, updateToolBlockInMessage, addErrorBlockToMessage, addUserMessageToMessages, extractUserInputHistory, addMemoryBlockToMessage, addCommandOutputMessage, updateCommandOutputInMessage, completeCommandInMessage, addSubagentBlockToMessage, updateSubagentBlockInMessage, removeLastUserMessage, } from "../utils/messageOperations.js";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { appendMessages, createSession, generateSessionId, SESSION_DIR, } from "../services/session.js";
|
|
4
|
+
import { pathEncoder } from "../utils/pathEncoder.js";
|
|
4
5
|
export class MessageManager {
|
|
5
6
|
constructor(options) {
|
|
6
|
-
this.sessionId =
|
|
7
|
+
this.sessionId = generateSessionId();
|
|
7
8
|
this.messages = [];
|
|
8
9
|
this.latestTotalTokens = 0;
|
|
9
10
|
this.userInputHistory = [];
|
|
10
|
-
this.sessionStartTime = new Date().toISOString();
|
|
11
11
|
this.workdir = options.workdir;
|
|
12
|
+
this.encodedWorkdir = pathEncoder.encodeSync(this.workdir); // Cache encoded workdir
|
|
12
13
|
this.callbacks = options.callbacks;
|
|
13
14
|
this.logger = options.logger;
|
|
14
|
-
this.
|
|
15
|
+
this.savedMessageCount = 0; // Initialize saved message count tracker
|
|
16
|
+
this.sessionType = options.sessionType || "main";
|
|
17
|
+
this.subagentType = options.subagentType;
|
|
18
|
+
// Compute and cache the transcript path
|
|
19
|
+
this.transcriptPath = this.computeTranscriptPath();
|
|
15
20
|
}
|
|
16
21
|
// Getter methods
|
|
17
22
|
getSessionId() {
|
|
@@ -26,70 +31,75 @@ export class MessageManager {
|
|
|
26
31
|
getUserInputHistory() {
|
|
27
32
|
return [...this.userInputHistory];
|
|
28
33
|
}
|
|
34
|
+
getWorkdir() {
|
|
35
|
+
return this.workdir;
|
|
36
|
+
}
|
|
37
|
+
getSessionDir() {
|
|
38
|
+
return SESSION_DIR;
|
|
39
|
+
}
|
|
29
40
|
getTranscriptPath() {
|
|
30
|
-
return
|
|
41
|
+
return this.transcriptPath;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Compute the transcript path using cached encoded workdir
|
|
45
|
+
* Called during construction and when sessionId changes
|
|
46
|
+
*/
|
|
47
|
+
computeTranscriptPath() {
|
|
48
|
+
const baseDir = join(SESSION_DIR, this.encodedWorkdir);
|
|
49
|
+
// All sessions now go in the same directory
|
|
50
|
+
// Session type is determined by metadata, not file path
|
|
51
|
+
return join(baseDir, `${this.sessionId}.jsonl`);
|
|
31
52
|
}
|
|
32
53
|
// Setter methods, will trigger callbacks
|
|
33
54
|
setSessionId(sessionId) {
|
|
34
55
|
if (this.sessionId !== sessionId) {
|
|
35
56
|
this.sessionId = sessionId;
|
|
57
|
+
// Reset saved message count for new session
|
|
58
|
+
this.savedMessageCount = 0;
|
|
59
|
+
// Recompute transcript path since session ID changed
|
|
60
|
+
this.transcriptPath = this.computeTranscriptPath();
|
|
36
61
|
this.callbacks.onSessionIdChange?.(sessionId);
|
|
37
62
|
}
|
|
38
63
|
}
|
|
39
|
-
setMessages(messages) {
|
|
40
|
-
this.messages = [...messages];
|
|
41
|
-
this.callbacks.onMessagesChange?.([...messages]);
|
|
42
|
-
}
|
|
43
64
|
/**
|
|
44
|
-
*
|
|
65
|
+
* Create session if needed (async helper)
|
|
45
66
|
*/
|
|
46
|
-
async
|
|
67
|
+
async createSessionIfNeeded() {
|
|
47
68
|
try {
|
|
48
|
-
await
|
|
69
|
+
await createSession(this.sessionId, this.workdir, this.sessionType);
|
|
49
70
|
}
|
|
50
71
|
catch (error) {
|
|
51
|
-
this.logger?.error("Failed to
|
|
72
|
+
this.logger?.error("Failed to create session:", error);
|
|
52
73
|
}
|
|
53
74
|
}
|
|
75
|
+
setMessages(messages) {
|
|
76
|
+
this.messages = [...messages];
|
|
77
|
+
this.callbacks.onMessagesChange?.([...messages]);
|
|
78
|
+
}
|
|
54
79
|
/**
|
|
55
|
-
*
|
|
80
|
+
* Save current session
|
|
56
81
|
*/
|
|
57
|
-
async
|
|
58
|
-
// Clean up expired sessions first
|
|
59
|
-
try {
|
|
60
|
-
await cleanupExpiredSessions(this.workdir, this.sessionDir);
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
this.logger?.warn("Failed to cleanup expired sessions:", error);
|
|
64
|
-
}
|
|
65
|
-
if (!restoreSessionId && !continueLastSession) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
82
|
+
async saveSession() {
|
|
68
83
|
try {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
process.exit(1);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
else if (continueLastSession) {
|
|
78
|
-
sessionToRestore = await getLatestSession(this.workdir, this.sessionDir);
|
|
79
|
-
if (!sessionToRestore) {
|
|
80
|
-
console.error(`No previous session found for workdir: ${this.workdir}`);
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
84
|
+
// Only save messages that haven't been saved yet
|
|
85
|
+
const unsavedMessages = this.messages.slice(this.savedMessageCount);
|
|
86
|
+
if (unsavedMessages.length === 0) {
|
|
87
|
+
// No new messages to save
|
|
88
|
+
return;
|
|
83
89
|
}
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
this.
|
|
90
|
+
// Create session if needed (only when we have messages to save)
|
|
91
|
+
if (this.savedMessageCount === 0) {
|
|
92
|
+
// This is the first time saving messages, so create the session
|
|
93
|
+
await this.createSessionIfNeeded();
|
|
88
94
|
}
|
|
95
|
+
// Use JSONL format for new sessions
|
|
96
|
+
await appendMessages(this.sessionId, unsavedMessages, // Only append new messages
|
|
97
|
+
this.workdir, this.sessionType);
|
|
98
|
+
// Update the saved message count
|
|
99
|
+
this.savedMessageCount = this.messages.length;
|
|
89
100
|
}
|
|
90
101
|
catch (error) {
|
|
91
|
-
|
|
92
|
-
process.exit(1);
|
|
102
|
+
this.logger?.error("Failed to save session:", error);
|
|
93
103
|
}
|
|
94
104
|
}
|
|
95
105
|
setlatestTotalTokens(latestTotalTokens) {
|
|
@@ -108,17 +118,20 @@ export class MessageManager {
|
|
|
108
118
|
clearMessages() {
|
|
109
119
|
this.setMessages([]);
|
|
110
120
|
this.setUserInputHistory([]);
|
|
111
|
-
this.setSessionId(
|
|
121
|
+
this.setSessionId(generateSessionId());
|
|
112
122
|
this.setlatestTotalTokens(0);
|
|
113
|
-
this.
|
|
123
|
+
this.savedMessageCount = 0; // Reset saved message count
|
|
114
124
|
}
|
|
115
125
|
// Initialize state from session data
|
|
116
|
-
initializeFromSession(
|
|
117
|
-
this.setSessionId(
|
|
118
|
-
this.setMessages([...messages]);
|
|
119
|
-
this.setlatestTotalTokens(latestTotalTokens);
|
|
126
|
+
initializeFromSession(sessionData) {
|
|
127
|
+
this.setSessionId(sessionData.id);
|
|
128
|
+
this.setMessages([...sessionData.messages]);
|
|
129
|
+
this.setlatestTotalTokens(sessionData.metadata.latestTotalTokens);
|
|
120
130
|
// Extract user input history from session messages
|
|
121
|
-
this.setUserInputHistory(extractUserInputHistory(messages));
|
|
131
|
+
this.setUserInputHistory(extractUserInputHistory(sessionData.messages));
|
|
132
|
+
// Set saved message count to the number of loaded messages since they're already saved
|
|
133
|
+
// This must be done after setSessionId which resets it to 0
|
|
134
|
+
this.savedMessageCount = sessionData.messages.length;
|
|
122
135
|
}
|
|
123
136
|
// Add to input history
|
|
124
137
|
addToInputHistory(input) {
|
|
@@ -142,11 +155,42 @@ export class MessageManager {
|
|
|
142
155
|
});
|
|
143
156
|
this.setMessages(newMessages);
|
|
144
157
|
this.callbacks.onUserMessageAdded?.(params);
|
|
158
|
+
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
145
159
|
}
|
|
146
|
-
addAssistantMessage(content, toolCalls, usage) {
|
|
147
|
-
const
|
|
160
|
+
addAssistantMessage(content, toolCalls, usage, additionalFields) {
|
|
161
|
+
const additionalFieldsRecord = additionalFields
|
|
162
|
+
? Object.fromEntries(Object.entries(additionalFields).filter(([, value]) => value !== undefined))
|
|
163
|
+
: undefined;
|
|
164
|
+
const newMessages = addAssistantMessageToMessages(this.messages, content, toolCalls, usage, additionalFieldsRecord);
|
|
148
165
|
this.setMessages(newMessages);
|
|
149
|
-
this.callbacks.onAssistantMessageAdded?.(
|
|
166
|
+
this.callbacks.onAssistantMessageAdded?.();
|
|
167
|
+
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
168
|
+
}
|
|
169
|
+
mergeAssistantAdditionalFields(additionalFields) {
|
|
170
|
+
if (!additionalFields || Object.keys(additionalFields).length === 0) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const newMessages = [...this.messages];
|
|
174
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
175
|
+
const message = newMessages[i];
|
|
176
|
+
if (message.role === "assistant") {
|
|
177
|
+
const mergedAdditionalFields = {
|
|
178
|
+
...(message.additionalFields || {}),
|
|
179
|
+
};
|
|
180
|
+
for (const [key, value] of Object.entries(additionalFields)) {
|
|
181
|
+
if (value === undefined) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
mergedAdditionalFields[key] = value;
|
|
185
|
+
}
|
|
186
|
+
if (Object.keys(mergedAdditionalFields).length === 0) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
message.additionalFields = mergedAdditionalFields;
|
|
190
|
+
this.setMessages(newMessages);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
150
194
|
}
|
|
151
195
|
updateToolBlock(params) {
|
|
152
196
|
const newMessages = updateToolBlockInMessage({
|
|
@@ -156,23 +200,16 @@ export class MessageManager {
|
|
|
156
200
|
result: params.result,
|
|
157
201
|
success: params.success,
|
|
158
202
|
error: params.error,
|
|
159
|
-
|
|
203
|
+
stage: params.stage,
|
|
160
204
|
name: params.name,
|
|
161
205
|
shortResult: params.shortResult,
|
|
162
206
|
images: params.images,
|
|
163
207
|
compactParams: params.compactParams,
|
|
208
|
+
parametersChunk: params.parametersChunk,
|
|
164
209
|
});
|
|
165
210
|
this.setMessages(newMessages);
|
|
166
211
|
this.callbacks.onToolBlockUpdated?.(params);
|
|
167
|
-
|
|
168
|
-
addDiffBlock(filePath, diffResult) {
|
|
169
|
-
const newMessages = addDiffBlockToMessage({
|
|
170
|
-
messages: this.messages,
|
|
171
|
-
path: filePath,
|
|
172
|
-
diffResult,
|
|
173
|
-
});
|
|
174
|
-
this.setMessages(newMessages);
|
|
175
|
-
this.callbacks.onDiffBlockAdded?.(filePath, JSON.stringify(diffResult));
|
|
212
|
+
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
176
213
|
}
|
|
177
214
|
addErrorBlock(error) {
|
|
178
215
|
const newMessages = addErrorBlockToMessage({
|
|
@@ -185,7 +222,7 @@ export class MessageManager {
|
|
|
185
222
|
/**
|
|
186
223
|
* Compress messages and update session, delete compressed messages, only keep compressed messages and subsequent messages
|
|
187
224
|
*/
|
|
188
|
-
compressMessagesAndUpdateSession(insertIndex, compressedContent) {
|
|
225
|
+
compressMessagesAndUpdateSession(insertIndex, compressedContent, usage) {
|
|
189
226
|
const currentMessages = this.messages;
|
|
190
227
|
// Create compressed message
|
|
191
228
|
const compressMessage = {
|
|
@@ -194,8 +231,10 @@ export class MessageManager {
|
|
|
194
231
|
{
|
|
195
232
|
type: "compress",
|
|
196
233
|
content: compressedContent,
|
|
234
|
+
sessionId: this.sessionId,
|
|
197
235
|
},
|
|
198
236
|
],
|
|
237
|
+
...(usage && { usage }),
|
|
199
238
|
};
|
|
200
239
|
// Convert negative index to positive index
|
|
201
240
|
const actualIndex = insertIndex < 0 ? currentMessages.length + insertIndex : insertIndex;
|
|
@@ -205,7 +244,7 @@ export class MessageManager {
|
|
|
205
244
|
...currentMessages.slice(actualIndex),
|
|
206
245
|
];
|
|
207
246
|
// Update sessionId
|
|
208
|
-
this.setSessionId(
|
|
247
|
+
this.setSessionId(generateSessionId());
|
|
209
248
|
// Set new message list
|
|
210
249
|
this.setMessages(newMessages);
|
|
211
250
|
// Trigger compression callback, insertIndex remains unchanged
|
|
@@ -250,13 +289,14 @@ export class MessageManager {
|
|
|
250
289
|
this.callbacks.onCompleteCommandMessage?.(command, exitCode);
|
|
251
290
|
}
|
|
252
291
|
// Subagent block methods
|
|
253
|
-
addSubagentBlock(subagentId, subagentName, status = "active",
|
|
292
|
+
addSubagentBlock(subagentId, subagentName, sessionId, configuration, status = "active", parameters) {
|
|
254
293
|
const params = {
|
|
255
294
|
messages: this.messages,
|
|
256
295
|
subagentId,
|
|
257
296
|
subagentName,
|
|
297
|
+
sessionId,
|
|
258
298
|
status,
|
|
259
|
-
|
|
299
|
+
configuration,
|
|
260
300
|
};
|
|
261
301
|
const updatedMessages = addSubagentBlockToMessage(params);
|
|
262
302
|
this.setMessages(updatedMessages);
|
|
@@ -269,9 +309,8 @@ export class MessageManager {
|
|
|
269
309
|
messages: this.messages,
|
|
270
310
|
subagentId,
|
|
271
311
|
status: updates.status || "active",
|
|
272
|
-
subagentMessages: updates.messages || [],
|
|
273
312
|
};
|
|
274
|
-
this.callbacks.onSubAgentBlockUpdated?.(params.subagentId, params.
|
|
313
|
+
this.callbacks.onSubAgentBlockUpdated?.(params.subagentId, params.status);
|
|
275
314
|
}
|
|
276
315
|
/**
|
|
277
316
|
* Trigger usage change callback with all usage data from assistant messages
|
|
@@ -285,6 +324,78 @@ export class MessageManager {
|
|
|
285
324
|
}
|
|
286
325
|
this.callbacks.onUsagesChange?.(usages);
|
|
287
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Update the current assistant message content during streaming
|
|
329
|
+
* This method updates the last assistant message's content without creating a new message
|
|
330
|
+
* FR-001: Tracks and provides both chunk (new content) and accumulated (total content)
|
|
331
|
+
*/
|
|
332
|
+
updateCurrentMessageContent(newAccumulatedContent) {
|
|
333
|
+
if (this.messages.length === 0)
|
|
334
|
+
return;
|
|
335
|
+
const lastMessage = this.messages[this.messages.length - 1];
|
|
336
|
+
if (lastMessage.role !== "assistant")
|
|
337
|
+
return;
|
|
338
|
+
// Get the current content to calculate the chunk
|
|
339
|
+
const textBlockIndex = lastMessage.blocks.findIndex((block) => block.type === "text");
|
|
340
|
+
const currentContent = textBlockIndex >= 0
|
|
341
|
+
? lastMessage.blocks[textBlockIndex].content || ""
|
|
342
|
+
: "";
|
|
343
|
+
// Calculate the chunk (new content since last update)
|
|
344
|
+
const chunk = newAccumulatedContent.slice(currentContent.length);
|
|
345
|
+
if (textBlockIndex >= 0) {
|
|
346
|
+
// Update existing text block
|
|
347
|
+
lastMessage.blocks[textBlockIndex] = {
|
|
348
|
+
type: "text",
|
|
349
|
+
content: newAccumulatedContent,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
// Add new text block if none exists
|
|
354
|
+
lastMessage.blocks.push({
|
|
355
|
+
type: "text",
|
|
356
|
+
content: newAccumulatedContent,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
// FR-001: Trigger callbacks with chunk and accumulated content
|
|
360
|
+
this.callbacks.onAssistantContentUpdated?.(chunk, newAccumulatedContent);
|
|
361
|
+
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
362
|
+
this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Update the current assistant message reasoning during streaming
|
|
366
|
+
* This method updates the last assistant message's reasoning content without creating a new message
|
|
367
|
+
*/
|
|
368
|
+
updateCurrentMessageReasoning(newAccumulatedReasoning) {
|
|
369
|
+
if (this.messages.length === 0)
|
|
370
|
+
return;
|
|
371
|
+
const lastMessage = this.messages[this.messages.length - 1];
|
|
372
|
+
if (lastMessage.role !== "assistant")
|
|
373
|
+
return;
|
|
374
|
+
// Get the current reasoning content to calculate the chunk
|
|
375
|
+
const reasoningBlockIndex = lastMessage.blocks.findIndex((block) => block.type === "reasoning");
|
|
376
|
+
const currentReasoning = reasoningBlockIndex >= 0
|
|
377
|
+
? lastMessage.blocks[reasoningBlockIndex].content || ""
|
|
378
|
+
: "";
|
|
379
|
+
// Calculate the chunk (new content since last update)
|
|
380
|
+
const chunk = newAccumulatedReasoning.slice(currentReasoning.length);
|
|
381
|
+
if (reasoningBlockIndex >= 0) {
|
|
382
|
+
// Update existing reasoning block
|
|
383
|
+
lastMessage.blocks[reasoningBlockIndex] = {
|
|
384
|
+
type: "reasoning",
|
|
385
|
+
content: newAccumulatedReasoning,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
// Add new reasoning block if none exists
|
|
390
|
+
lastMessage.blocks.push({
|
|
391
|
+
type: "reasoning",
|
|
392
|
+
content: newAccumulatedReasoning,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
// Trigger callbacks with chunk and accumulated reasoning content
|
|
396
|
+
this.callbacks.onAssistantReasoningUpdated?.(chunk, newAccumulatedReasoning);
|
|
397
|
+
this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
|
|
398
|
+
}
|
|
288
399
|
/**
|
|
289
400
|
* Remove the last user message from the conversation
|
|
290
401
|
* Used for hook error handling when the user prompt needs to be erased
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission Manager for handling tool permission checks
|
|
3
|
+
*
|
|
4
|
+
* This manager provides utilities for checking permissions before tool execution.
|
|
5
|
+
* It implements the permission logic for different modes (default vs bypass) and
|
|
6
|
+
* handles custom callback integration.
|
|
7
|
+
*/
|
|
8
|
+
import type { PermissionDecision, ToolPermissionContext, PermissionCallback, PermissionMode } from "../types/permissions.js";
|
|
9
|
+
import type { Logger } from "../types/index.js";
|
|
10
|
+
export interface PermissionManagerOptions {
|
|
11
|
+
/** Logger for debugging permission decisions */
|
|
12
|
+
logger?: Logger;
|
|
13
|
+
/** Configured default permission mode from settings */
|
|
14
|
+
configuredDefaultMode?: PermissionMode;
|
|
15
|
+
/** Allowed rules from settings */
|
|
16
|
+
allowedRules?: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare class PermissionManager {
|
|
19
|
+
private logger?;
|
|
20
|
+
private configuredDefaultMode?;
|
|
21
|
+
private allowedRules;
|
|
22
|
+
private onConfiguredDefaultModeChange?;
|
|
23
|
+
constructor(options?: PermissionManagerOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Set a callback to be notified when the effective permission mode changes due to configuration updates
|
|
26
|
+
*/
|
|
27
|
+
setOnConfiguredDefaultModeChange(callback: (mode: PermissionMode) => void): void;
|
|
28
|
+
/**
|
|
29
|
+
* Update the configured default mode (e.g., when configuration reloads)
|
|
30
|
+
*/
|
|
31
|
+
updateConfiguredDefaultMode(defaultMode?: PermissionMode): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get all currently allowed rules
|
|
34
|
+
*/
|
|
35
|
+
getAllowedRules(): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Update the allowed rules (e.g., when configuration reloads)
|
|
38
|
+
*/
|
|
39
|
+
updateAllowedRules(rules: string[]): void;
|
|
40
|
+
/**
|
|
41
|
+
* Get the current effective permission mode for tool execution context
|
|
42
|
+
*/
|
|
43
|
+
getCurrentEffectiveMode(cliPermissionMode?: PermissionMode): PermissionMode;
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the effective permission mode based on CLI override and configured default
|
|
46
|
+
*/
|
|
47
|
+
resolveEffectivePermissionMode(cliPermissionMode?: PermissionMode): PermissionMode;
|
|
48
|
+
/**
|
|
49
|
+
* Check if a tool execution requires permission and handle the authorization flow
|
|
50
|
+
* Called by individual tools after validation/diff, before real operation
|
|
51
|
+
*/
|
|
52
|
+
checkPermission(context: ToolPermissionContext): Promise<PermissionDecision>;
|
|
53
|
+
/**
|
|
54
|
+
* Determine if a tool requires permission checks based on its name
|
|
55
|
+
*/
|
|
56
|
+
isRestrictedTool(toolName: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Helper method to create a permission context for CLI integration
|
|
59
|
+
*/
|
|
60
|
+
createContext(toolName: string, permissionMode: PermissionMode, callback?: PermissionCallback, toolInput?: Record<string, unknown>): ToolPermissionContext;
|
|
61
|
+
/**
|
|
62
|
+
* Check if a tool call is allowed by persistent rules
|
|
63
|
+
*/
|
|
64
|
+
private isAllowedByRule;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=permissionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionManager.d.ts","sourceRoot":"","sources":["../../src/managers/permissionManager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,wBAAwB;IACvC,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,qBAAqB,CAAC,EAAE,cAAc,CAAC;IACvC,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,qBAAqB,CAAC,CAAiB;IAC/C,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,6BAA6B,CAAC,CAAiC;gBAE3D,OAAO,GAAE,wBAA6B;IAMlD;;OAEG;IACI,gCAAgC,CACrC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,GACvC,IAAI;IAIP;;OAEG;IACH,2BAA2B,CAAC,WAAW,CAAC,EAAE,cAAc,GAAG,IAAI;IAyB/D;;OAEG;IACI,eAAe,IAAI,MAAM,EAAE;IAIlC;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAOzC;;OAEG;IACH,uBAAuB,CAAC,iBAAiB,CAAC,EAAE,cAAc,GAAG,cAAc;IAI3E;;OAEG;IACH,8BAA8B,CAC5B,iBAAiB,CAAC,EAAE,cAAc,GACjC,cAAc;IAuBjB;;;OAGG;IACG,eAAe,CACnB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,kBAAkB,CAAC;IAqF9B;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAW3C;;OAEG;IACH,aAAa,CACX,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,QAAQ,CAAC,EAAE,kBAAkB,EAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,qBAAqB;IAkBxB;;OAEG;IACH,OAAO,CAAC,eAAe;CAcxB"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission Manager for handling tool permission checks
|
|
3
|
+
*
|
|
4
|
+
* This manager provides utilities for checking permissions before tool execution.
|
|
5
|
+
* It implements the permission logic for different modes (default vs bypass) and
|
|
6
|
+
* handles custom callback integration.
|
|
7
|
+
*/
|
|
8
|
+
import { RESTRICTED_TOOLS } from "../types/permissions.js";
|
|
9
|
+
export class PermissionManager {
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
this.allowedRules = [];
|
|
12
|
+
this.logger = options.logger;
|
|
13
|
+
this.configuredDefaultMode = options.configuredDefaultMode;
|
|
14
|
+
this.allowedRules = options.allowedRules || [];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Set a callback to be notified when the effective permission mode changes due to configuration updates
|
|
18
|
+
*/
|
|
19
|
+
setOnConfiguredDefaultModeChange(callback) {
|
|
20
|
+
this.onConfiguredDefaultModeChange = callback;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Update the configured default mode (e.g., when configuration reloads)
|
|
24
|
+
*/
|
|
25
|
+
updateConfiguredDefaultMode(defaultMode) {
|
|
26
|
+
const oldEffectiveMode = this.getCurrentEffectiveMode();
|
|
27
|
+
this.logger?.debug("Updating configured default permission mode", {
|
|
28
|
+
previous: this.configuredDefaultMode,
|
|
29
|
+
new: defaultMode,
|
|
30
|
+
});
|
|
31
|
+
this.configuredDefaultMode = defaultMode;
|
|
32
|
+
const newEffectiveMode = this.getCurrentEffectiveMode();
|
|
33
|
+
if (oldEffectiveMode !== newEffectiveMode &&
|
|
34
|
+
this.onConfiguredDefaultModeChange) {
|
|
35
|
+
this.logger?.debug("Effective permission mode changed due to configuration update", {
|
|
36
|
+
oldMode: oldEffectiveMode,
|
|
37
|
+
newMode: newEffectiveMode,
|
|
38
|
+
});
|
|
39
|
+
this.onConfiguredDefaultModeChange(newEffectiveMode);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get all currently allowed rules
|
|
44
|
+
*/
|
|
45
|
+
getAllowedRules() {
|
|
46
|
+
return [...this.allowedRules];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Update the allowed rules (e.g., when configuration reloads)
|
|
50
|
+
*/
|
|
51
|
+
updateAllowedRules(rules) {
|
|
52
|
+
this.logger?.debug("Updating allowed permission rules", {
|
|
53
|
+
count: rules.length,
|
|
54
|
+
});
|
|
55
|
+
this.allowedRules = rules;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get the current effective permission mode for tool execution context
|
|
59
|
+
*/
|
|
60
|
+
getCurrentEffectiveMode(cliPermissionMode) {
|
|
61
|
+
return this.resolveEffectivePermissionMode(cliPermissionMode);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Resolve the effective permission mode based on CLI override and configured default
|
|
65
|
+
*/
|
|
66
|
+
resolveEffectivePermissionMode(cliPermissionMode) {
|
|
67
|
+
// CLI override takes highest precedence
|
|
68
|
+
if (cliPermissionMode !== undefined) {
|
|
69
|
+
this.logger?.debug("Using CLI permission mode override", {
|
|
70
|
+
cliMode: cliPermissionMode,
|
|
71
|
+
configuredDefault: this.configuredDefaultMode,
|
|
72
|
+
});
|
|
73
|
+
return cliPermissionMode;
|
|
74
|
+
}
|
|
75
|
+
// Use configured default mode if available
|
|
76
|
+
if (this.configuredDefaultMode !== undefined) {
|
|
77
|
+
this.logger?.debug("Using configured default permission mode", {
|
|
78
|
+
configuredDefault: this.configuredDefaultMode,
|
|
79
|
+
});
|
|
80
|
+
return this.configuredDefaultMode;
|
|
81
|
+
}
|
|
82
|
+
// Fall back to system default
|
|
83
|
+
this.logger?.debug("Using system default permission mode");
|
|
84
|
+
return "default";
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if a tool execution requires permission and handle the authorization flow
|
|
88
|
+
* Called by individual tools after validation/diff, before real operation
|
|
89
|
+
*/
|
|
90
|
+
async checkPermission(context) {
|
|
91
|
+
this.logger?.debug("Checking permission for tool", {
|
|
92
|
+
toolName: context.toolName,
|
|
93
|
+
permissionMode: context.permissionMode,
|
|
94
|
+
hasCallback: !!context.canUseToolCallback,
|
|
95
|
+
});
|
|
96
|
+
// 1. If bypassPermissions mode, always allow
|
|
97
|
+
if (context.permissionMode === "bypassPermissions") {
|
|
98
|
+
this.logger?.debug("Permission bypassed for tool", {
|
|
99
|
+
toolName: context.toolName,
|
|
100
|
+
});
|
|
101
|
+
return { behavior: "allow" };
|
|
102
|
+
}
|
|
103
|
+
// 1.1 If acceptEdits mode, allow Edit, MultiEdit, Delete, Write
|
|
104
|
+
if (context.permissionMode === "acceptEdits") {
|
|
105
|
+
const autoAcceptedTools = ["Edit", "MultiEdit", "Delete", "Write"];
|
|
106
|
+
if (autoAcceptedTools.includes(context.toolName)) {
|
|
107
|
+
this.logger?.debug("Permission automatically accepted for tool in acceptEdits mode", {
|
|
108
|
+
toolName: context.toolName,
|
|
109
|
+
});
|
|
110
|
+
return { behavior: "allow" };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// 1.2 Check if tool call matches any allowed rule
|
|
114
|
+
if (this.isAllowedByRule(context)) {
|
|
115
|
+
this.logger?.debug("Permission allowed by persistent rule", {
|
|
116
|
+
toolName: context.toolName,
|
|
117
|
+
});
|
|
118
|
+
return { behavior: "allow" };
|
|
119
|
+
}
|
|
120
|
+
// 2. If not a restricted tool, always allow
|
|
121
|
+
if (!this.isRestrictedTool(context.toolName)) {
|
|
122
|
+
this.logger?.debug("Tool is not restricted, allowing", {
|
|
123
|
+
toolName: context.toolName,
|
|
124
|
+
});
|
|
125
|
+
return { behavior: "allow" };
|
|
126
|
+
}
|
|
127
|
+
// 3. If custom callback provided, call it and return result
|
|
128
|
+
if (context.canUseToolCallback) {
|
|
129
|
+
try {
|
|
130
|
+
this.logger?.debug("Calling custom permission callback for tool", {
|
|
131
|
+
toolName: context.toolName,
|
|
132
|
+
});
|
|
133
|
+
const decision = await context.canUseToolCallback(context);
|
|
134
|
+
this.logger?.debug("Custom callback returned decision", {
|
|
135
|
+
toolName: context.toolName,
|
|
136
|
+
decision,
|
|
137
|
+
});
|
|
138
|
+
return decision;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
142
|
+
this.logger?.error("Error in permission callback", {
|
|
143
|
+
toolName: context.toolName,
|
|
144
|
+
error: errorMessage,
|
|
145
|
+
});
|
|
146
|
+
return {
|
|
147
|
+
behavior: "deny",
|
|
148
|
+
message: "Error in permission callback",
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// 4. For default mode on restricted tools without callback, integrate with CLI confirmation
|
|
153
|
+
// Note: CLI confirmation integration will be implemented in Phase 2
|
|
154
|
+
this.logger?.warn("No permission callback provided for restricted tool in default mode", {
|
|
155
|
+
toolName: context.toolName,
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
behavior: "deny",
|
|
159
|
+
message: `Tool '${context.toolName}' requires permission approval. No permission callback configured.`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Determine if a tool requires permission checks based on its name
|
|
164
|
+
*/
|
|
165
|
+
isRestrictedTool(toolName) {
|
|
166
|
+
const isRestricted = RESTRICTED_TOOLS.includes(toolName);
|
|
167
|
+
this.logger?.debug("Checking if tool is restricted", {
|
|
168
|
+
toolName,
|
|
169
|
+
isRestricted,
|
|
170
|
+
});
|
|
171
|
+
return isRestricted;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Helper method to create a permission context for CLI integration
|
|
175
|
+
*/
|
|
176
|
+
createContext(toolName, permissionMode, callback, toolInput) {
|
|
177
|
+
const context = {
|
|
178
|
+
toolName,
|
|
179
|
+
permissionMode,
|
|
180
|
+
canUseToolCallback: callback,
|
|
181
|
+
toolInput,
|
|
182
|
+
};
|
|
183
|
+
this.logger?.debug("Created permission context", {
|
|
184
|
+
toolName,
|
|
185
|
+
permissionMode,
|
|
186
|
+
hasCallback: !!callback,
|
|
187
|
+
hasToolInput: !!toolInput,
|
|
188
|
+
});
|
|
189
|
+
return context;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Check if a tool call is allowed by persistent rules
|
|
193
|
+
*/
|
|
194
|
+
isAllowedByRule(context) {
|
|
195
|
+
if (context.toolName === "Bash" && context.toolInput?.command) {
|
|
196
|
+
const action = `Bash(${context.toolInput.command})`;
|
|
197
|
+
return this.allowedRules.some((rule) => {
|
|
198
|
+
if (rule.endsWith(":*)")) {
|
|
199
|
+
const prefix = rule.slice(0, -3);
|
|
200
|
+
return action.startsWith(prefix);
|
|
201
|
+
}
|
|
202
|
+
return action === rule;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// Add other tools if needed in the future
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EAEvB,MAAM,mBAAmB,CAAC;AAG3B;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAC,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,mBAAwB;
|
|
1
|
+
{"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EAEvB,MAAM,mBAAmB,CAAC;AAG3B;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,mBAAwB;IAQ7C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwCjC;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAQrC;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;OAEG;YACW,cAAc;IAkB5B;;OAEG;YACW,uBAAuB;IAiFrC;;OAEG;YACW,oBAAoB;IAkBlC;;OAEG;IACG,YAAY,CAChB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,sBAAsB,CAAA;KAAE,CAAC;IAqCjE;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAa9B"}
|