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
package/dist/agent.js
CHANGED
|
@@ -1,17 +1,61 @@
|
|
|
1
1
|
import { MessageManager, } from "./managers/messageManager.js";
|
|
2
2
|
import { AIManager } from "./managers/aiManager.js";
|
|
3
3
|
import { ToolManager } from "./managers/toolManager.js";
|
|
4
|
-
import { SubagentManager } from "./managers/subagentManager.js";
|
|
4
|
+
import { SubagentManager, } from "./managers/subagentManager.js";
|
|
5
5
|
import * as memory from "./services/memory.js";
|
|
6
6
|
import { McpManager } from "./managers/mcpManager.js";
|
|
7
|
+
import { LspManager } from "./managers/lspManager.js";
|
|
7
8
|
import { BashManager } from "./managers/bashManager.js";
|
|
8
9
|
import { BackgroundBashManager, } from "./managers/backgroundBashManager.js";
|
|
9
10
|
import { SlashCommandManager } from "./managers/slashCommandManager.js";
|
|
11
|
+
import { PermissionManager } from "./managers/permissionManager.js";
|
|
10
12
|
import { HookManager } from "./managers/hookManager.js";
|
|
11
|
-
import {
|
|
13
|
+
import { LiveConfigManager } from "./managers/liveConfigManager.js";
|
|
12
14
|
import { configValidator } from "./utils/configValidator.js";
|
|
13
15
|
import { SkillManager } from "./managers/skillManager.js";
|
|
16
|
+
import { loadSessionFromJsonl, handleSessionRestoration, } from "./services/session.js";
|
|
17
|
+
import { setGlobalLogger } from "./utils/globalLogger.js";
|
|
18
|
+
import { ConfigurationService } from "./services/configurationService.js";
|
|
19
|
+
import * as fs from "fs/promises";
|
|
20
|
+
import path from "path";
|
|
21
|
+
import os from "os";
|
|
14
22
|
export class Agent {
|
|
23
|
+
// Dynamic configuration getter methods
|
|
24
|
+
getGatewayConfig() {
|
|
25
|
+
return this.configurationService.resolveGatewayConfig(this.options.apiKey, this.options.baseURL, this.options.defaultHeaders, this.options.fetchOptions, this.options.fetch);
|
|
26
|
+
}
|
|
27
|
+
getModelConfig() {
|
|
28
|
+
return this.configurationService.resolveModelConfig(this.options.agentModel, this.options.fastModel);
|
|
29
|
+
}
|
|
30
|
+
getTokenLimit() {
|
|
31
|
+
return this.configurationService.resolveTokenLimit(this.options.tokenLimit);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Update agent configuration dynamically
|
|
35
|
+
*
|
|
36
|
+
* @param config - Configuration updates for gateway, model, and token limit
|
|
37
|
+
*/
|
|
38
|
+
updateConfig(config) {
|
|
39
|
+
if (config.gateway) {
|
|
40
|
+
this.options.apiKey = config.gateway.apiKey ?? this.options.apiKey;
|
|
41
|
+
this.options.baseURL = config.gateway.baseURL ?? this.options.baseURL;
|
|
42
|
+
this.options.defaultHeaders =
|
|
43
|
+
config.gateway.defaultHeaders ?? this.options.defaultHeaders;
|
|
44
|
+
this.options.fetchOptions =
|
|
45
|
+
config.gateway.fetchOptions ?? this.options.fetchOptions;
|
|
46
|
+
this.options.fetch = config.gateway.fetch ?? this.options.fetch;
|
|
47
|
+
}
|
|
48
|
+
if (config.model) {
|
|
49
|
+
this.options.agentModel =
|
|
50
|
+
config.model.agentModel ?? this.options.agentModel;
|
|
51
|
+
this.options.fastModel = config.model.fastModel ?? this.options.fastModel;
|
|
52
|
+
}
|
|
53
|
+
if (config.tokenLimit !== undefined) {
|
|
54
|
+
this.options.tokenLimit = config.tokenLimit;
|
|
55
|
+
}
|
|
56
|
+
// Re-validate configuration after update
|
|
57
|
+
this.resolveAndValidateConfig();
|
|
58
|
+
}
|
|
15
59
|
/**
|
|
16
60
|
* Agent constructor - handles configuration resolution and validation
|
|
17
61
|
*
|
|
@@ -20,54 +64,115 @@ export class Agent {
|
|
|
20
64
|
* Agent.create() to maintain API consistency.
|
|
21
65
|
*
|
|
22
66
|
* @param options - Configuration options for the Agent instance
|
|
23
|
-
* @param options.sessionDir - Optional custom directory for session storage
|
|
24
67
|
*/
|
|
25
68
|
constructor(options) {
|
|
26
69
|
this.bashManager = null;
|
|
27
70
|
this._usages = []; // Usage tracking array
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
configValidator.validateModelConfig(modelConfig.agentModel, modelConfig.fastModel);
|
|
71
|
+
// Memory content storage
|
|
72
|
+
this._projectMemoryContent = "";
|
|
73
|
+
this._userMemoryContent = "";
|
|
74
|
+
const { callbacks = {}, logger, workdir, systemPrompt, stream = true, } = options;
|
|
75
|
+
// Set working directory early as we need it for loading configuration
|
|
76
|
+
this.workdir = workdir || process.cwd();
|
|
77
|
+
// Initialize configuration service
|
|
78
|
+
this.configurationService = new ConfigurationService();
|
|
37
79
|
this.logger = logger; // Save the passed logger
|
|
38
|
-
this.workdir = workdir || process.cwd(); // Set working directory, default to current working directory
|
|
39
80
|
this.systemPrompt = systemPrompt; // Save custom system prompt
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
this.tokenLimit = tokenLimit;
|
|
81
|
+
this.stream = stream; // Save streaming mode flag
|
|
82
|
+
// Store options for dynamic configuration resolution
|
|
83
|
+
this.options = options;
|
|
44
84
|
this.backgroundBashManager = new BackgroundBashManager({
|
|
45
85
|
callbacks,
|
|
46
86
|
workdir: this.workdir,
|
|
47
87
|
});
|
|
48
88
|
this.mcpManager = new McpManager({ callbacks, logger: this.logger }); // Initialize MCP manager
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
89
|
+
this.lspManager =
|
|
90
|
+
options.lspManager || new LspManager({ logger: this.logger }); // Initialize LSP manager
|
|
91
|
+
// Initialize permission manager
|
|
92
|
+
this.permissionManager = new PermissionManager({ logger: this.logger });
|
|
93
|
+
this.permissionManager.setOnConfiguredDefaultModeChange((mode) => {
|
|
94
|
+
this.options.callbacks?.onPermissionModeChange?.(mode);
|
|
95
|
+
});
|
|
96
|
+
// Initialize configuration service and hooks manager
|
|
53
97
|
this.hookManager = new HookManager(this.workdir, undefined, this.logger); // Initialize hooks manager
|
|
54
98
|
// Initialize MessageManager
|
|
55
99
|
this.messageManager = new MessageManager({
|
|
56
100
|
callbacks,
|
|
57
101
|
workdir: this.workdir,
|
|
58
102
|
logger: this.logger,
|
|
59
|
-
sessionDir,
|
|
60
103
|
});
|
|
104
|
+
// Create a wrapper for canUseTool that triggers notification hooks
|
|
105
|
+
const canUseToolWithNotification = options.canUseTool
|
|
106
|
+
? async (context) => {
|
|
107
|
+
try {
|
|
108
|
+
// Trigger notification hooks before calling the original callback
|
|
109
|
+
const notificationMessage = `Claude needs your permission to use ${context.toolName}`;
|
|
110
|
+
await this.hookManager.executeHooks("Notification", {
|
|
111
|
+
event: "Notification",
|
|
112
|
+
projectDir: this.workdir,
|
|
113
|
+
timestamp: new Date(),
|
|
114
|
+
sessionId: this.sessionId,
|
|
115
|
+
transcriptPath: this.messageManager.getTranscriptPath(),
|
|
116
|
+
cwd: this.workdir,
|
|
117
|
+
message: notificationMessage,
|
|
118
|
+
notificationType: "permission_prompt",
|
|
119
|
+
env: this.configurationService.getEnvironmentVars(), // Include configuration environment variables
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
this.logger?.warn("Failed to execute notification hooks", {
|
|
124
|
+
toolName: context.toolName,
|
|
125
|
+
error: error instanceof Error ? error.message : String(error),
|
|
126
|
+
});
|
|
127
|
+
// Continue with permission check even if hooks fail
|
|
128
|
+
}
|
|
129
|
+
// Call the original callback
|
|
130
|
+
const decision = await options.canUseTool(context);
|
|
131
|
+
// Handle state changes from decision
|
|
132
|
+
if (decision.newPermissionMode) {
|
|
133
|
+
this.setPermissionMode(decision.newPermissionMode);
|
|
134
|
+
}
|
|
135
|
+
if (decision.newPermissionRule) {
|
|
136
|
+
await this.addPermissionRule(decision.newPermissionRule);
|
|
137
|
+
}
|
|
138
|
+
return decision;
|
|
139
|
+
}
|
|
140
|
+
: undefined;
|
|
141
|
+
// Initialize tool manager with permission context
|
|
142
|
+
this.toolManager = new ToolManager({
|
|
143
|
+
mcpManager: this.mcpManager,
|
|
144
|
+
lspManager: this.lspManager,
|
|
145
|
+
logger: this.logger,
|
|
146
|
+
permissionManager: this.permissionManager,
|
|
147
|
+
permissionMode: options.permissionMode, // Let PermissionManager handle defaultMode resolution
|
|
148
|
+
canUseToolCallback: canUseToolWithNotification,
|
|
149
|
+
}); // Initialize tool registry with permission support
|
|
150
|
+
this.liveConfigManager = new LiveConfigManager({
|
|
151
|
+
workdir: this.workdir,
|
|
152
|
+
logger: this.logger,
|
|
153
|
+
hookManager: this.hookManager,
|
|
154
|
+
permissionManager: this.permissionManager,
|
|
155
|
+
configurationService: this.configurationService,
|
|
156
|
+
}); // Initialize live configuration manager
|
|
61
157
|
// Initialize subagent manager with all dependencies in constructor
|
|
62
158
|
// IMPORTANT: Must be initialized AFTER MessageManager
|
|
63
159
|
this.subagentManager = new SubagentManager({
|
|
64
160
|
workdir: this.workdir,
|
|
65
161
|
parentToolManager: this.toolManager,
|
|
66
162
|
parentMessageManager: this.messageManager,
|
|
163
|
+
callbacks: {
|
|
164
|
+
onSubagentUserMessageAdded: callbacks.onSubagentUserMessageAdded,
|
|
165
|
+
onSubagentAssistantMessageAdded: callbacks.onSubagentAssistantMessageAdded,
|
|
166
|
+
onSubagentAssistantContentUpdated: callbacks.onSubagentAssistantContentUpdated,
|
|
167
|
+
onSubagentAssistantReasoningUpdated: callbacks.onSubagentAssistantReasoningUpdated,
|
|
168
|
+
onSubagentToolBlockUpdated: callbacks.onSubagentToolBlockUpdated,
|
|
169
|
+
onSubagentMessagesChange: callbacks.onSubagentMessagesChange,
|
|
170
|
+
}, // Pass subagent callbacks for forwarding
|
|
67
171
|
logger: this.logger,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
172
|
+
getGatewayConfig: () => this.getGatewayConfig(),
|
|
173
|
+
getModelConfig: () => this.getModelConfig(),
|
|
174
|
+
getTokenLimit: () => this.getTokenLimit(),
|
|
175
|
+
hookManager: this.hookManager,
|
|
71
176
|
onUsageAdded: (usage) => this.addUsage(usage),
|
|
72
177
|
});
|
|
73
178
|
// Initialize AI manager with resolved configuration
|
|
@@ -85,9 +190,11 @@ export class Agent {
|
|
|
85
190
|
},
|
|
86
191
|
workdir: this.workdir,
|
|
87
192
|
systemPrompt: this.systemPrompt,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
193
|
+
stream: this.stream, // Pass streaming mode flag
|
|
194
|
+
getGatewayConfig: () => this.getGatewayConfig(),
|
|
195
|
+
getModelConfig: () => this.getModelConfig(),
|
|
196
|
+
getTokenLimit: () => this.getTokenLimit(),
|
|
197
|
+
getEnvironmentVars: () => this.configurationService.getEnvironmentVars(), // Provide access to configuration environment variables
|
|
91
198
|
});
|
|
92
199
|
// Initialize command manager
|
|
93
200
|
this.slashCommandManager = new SlashCommandManager({
|
|
@@ -119,9 +226,9 @@ export class Agent {
|
|
|
119
226
|
* Rebuild usage array from messages containing usage metadata
|
|
120
227
|
* Called during session restoration to reconstruct usage tracking
|
|
121
228
|
*/
|
|
122
|
-
rebuildUsageFromMessages() {
|
|
229
|
+
rebuildUsageFromMessages(messages) {
|
|
123
230
|
this._usages = [];
|
|
124
|
-
|
|
231
|
+
messages.forEach((message) => {
|
|
125
232
|
if (message.role === "assistant" && message.usage) {
|
|
126
233
|
this._usages.push(message.usage);
|
|
127
234
|
}
|
|
@@ -147,6 +254,28 @@ export class Agent {
|
|
|
147
254
|
get workingDirectory() {
|
|
148
255
|
return this.workdir;
|
|
149
256
|
}
|
|
257
|
+
/** Get project memory content */
|
|
258
|
+
get projectMemory() {
|
|
259
|
+
return this._projectMemoryContent;
|
|
260
|
+
}
|
|
261
|
+
/** Get user memory content */
|
|
262
|
+
get userMemory() {
|
|
263
|
+
return this._userMemoryContent;
|
|
264
|
+
}
|
|
265
|
+
/** Get combined memory content (project + user) */
|
|
266
|
+
get combinedMemory() {
|
|
267
|
+
let combined = "";
|
|
268
|
+
if (this._projectMemoryContent.trim()) {
|
|
269
|
+
combined += this._projectMemoryContent;
|
|
270
|
+
}
|
|
271
|
+
if (this._userMemoryContent.trim()) {
|
|
272
|
+
if (combined) {
|
|
273
|
+
combined += "\n\n";
|
|
274
|
+
}
|
|
275
|
+
combined += this._userMemoryContent;
|
|
276
|
+
}
|
|
277
|
+
return combined;
|
|
278
|
+
}
|
|
150
279
|
/** Get AI loading status */
|
|
151
280
|
get isLoading() {
|
|
152
281
|
return this.aiManager.isLoading;
|
|
@@ -185,9 +314,9 @@ export class Agent {
|
|
|
185
314
|
* @param options - Configuration options for the Agent instance
|
|
186
315
|
* @param options.apiKey - API key for the AI service (or set WAVE_API_KEY env var)
|
|
187
316
|
* @param options.baseURL - Base URL for the AI service (or set WAVE_BASE_URL env var)
|
|
188
|
-
* @param options.
|
|
189
|
-
*
|
|
190
|
-
*
|
|
317
|
+
* @param options.defaultHeaders - Optional HTTP headers to pass to the AI service
|
|
318
|
+
* @param options.fetchOptions - Optional fetch options to pass to the AI service
|
|
319
|
+
* @param options.fetch - Optional custom fetch implementation
|
|
191
320
|
* @param options.callbacks - Optional callbacks for various Agent events
|
|
192
321
|
* @param options.restoreSessionId - Optional session ID to restore from
|
|
193
322
|
* @param options.continueLastSession - Whether to continue the last session automatically
|
|
@@ -199,22 +328,15 @@ export class Agent {
|
|
|
199
328
|
*
|
|
200
329
|
* @example
|
|
201
330
|
* ```typescript
|
|
202
|
-
* // Basic usage
|
|
331
|
+
* // Basic usage
|
|
203
332
|
* const agent = await Agent.create({
|
|
204
333
|
* apiKey: 'your-api-key',
|
|
205
334
|
* baseURL: 'https://api.example.com'
|
|
206
335
|
* });
|
|
207
|
-
*
|
|
208
|
-
* // Custom session directory
|
|
209
|
-
* const agent = await Agent.create({
|
|
210
|
-
* apiKey: 'your-api-key',
|
|
211
|
-
* baseURL: 'https://api.example.com',
|
|
212
|
-
* sessionDir: './app-sessions'
|
|
213
|
-
* });
|
|
214
336
|
* ```
|
|
215
337
|
*/
|
|
216
338
|
static async create(options) {
|
|
217
|
-
// Create Agent instance
|
|
339
|
+
// Create Agent instance
|
|
218
340
|
const instance = new Agent(options);
|
|
219
341
|
await instance.initialize({
|
|
220
342
|
restoreSessionId: options.restoreSessionId,
|
|
@@ -223,12 +345,31 @@ export class Agent {
|
|
|
223
345
|
});
|
|
224
346
|
return instance;
|
|
225
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Resolve and validate configuration from constructor args, environment variables,
|
|
350
|
+
* and loaded settings.json.
|
|
351
|
+
*
|
|
352
|
+
* This is called during initialization after settings.json has been loaded.
|
|
353
|
+
*/
|
|
354
|
+
resolveAndValidateConfig() {
|
|
355
|
+
// Resolve configuration from constructor args and environment variables (including settings.json)
|
|
356
|
+
const gatewayConfig = this.getGatewayConfig();
|
|
357
|
+
const modelConfig = this.getModelConfig();
|
|
358
|
+
const tokenLimit = this.getTokenLimit();
|
|
359
|
+
// Validate resolved configuration
|
|
360
|
+
configValidator.validateGatewayConfig(gatewayConfig);
|
|
361
|
+
configValidator.validateTokenLimit(tokenLimit);
|
|
362
|
+
configValidator.validateModelConfig(modelConfig.agentModel, modelConfig.fastModel);
|
|
363
|
+
}
|
|
226
364
|
/** Private initialization method, handles async initialization logic */
|
|
227
365
|
async initialize(options) {
|
|
228
366
|
// Initialize managers first
|
|
229
367
|
try {
|
|
230
368
|
// Initialize SkillManager
|
|
231
|
-
const skillManager = new SkillManager({
|
|
369
|
+
const skillManager = new SkillManager({
|
|
370
|
+
logger: this.logger,
|
|
371
|
+
workdir: this.workdir,
|
|
372
|
+
});
|
|
232
373
|
await skillManager.initialize();
|
|
233
374
|
// Initialize SubagentManager (load and cache configurations)
|
|
234
375
|
await this.subagentManager.initialize();
|
|
@@ -245,6 +386,9 @@ export class Agent {
|
|
|
245
386
|
// Initialize MCP servers with auto-connect
|
|
246
387
|
try {
|
|
247
388
|
await this.mcpManager.initialize(this.workdir, true);
|
|
389
|
+
if (this.lspManager instanceof LspManager) {
|
|
390
|
+
await this.lspManager.initialize(this.workdir);
|
|
391
|
+
}
|
|
248
392
|
}
|
|
249
393
|
catch (error) {
|
|
250
394
|
this.logger?.error("Failed to initialize MCP servers:", error);
|
|
@@ -252,29 +396,185 @@ export class Agent {
|
|
|
252
396
|
}
|
|
253
397
|
// Initialize hooks configuration
|
|
254
398
|
try {
|
|
255
|
-
// Load hooks configuration
|
|
399
|
+
// Load hooks configuration using ConfigurationService
|
|
256
400
|
this.logger?.debug("Loading hooks configuration...");
|
|
257
|
-
this.
|
|
401
|
+
const configResult = await this.configurationService.loadMergedConfiguration(this.workdir);
|
|
402
|
+
this.hookManager.loadConfigurationFromWaveConfig(configResult.configuration);
|
|
258
403
|
this.logger?.debug("Hooks system initialized successfully");
|
|
259
404
|
}
|
|
260
405
|
catch (error) {
|
|
261
406
|
this.logger?.error("Failed to initialize hooks system:", error);
|
|
262
407
|
// Don't throw error to prevent app startup failure
|
|
263
408
|
}
|
|
409
|
+
// Resolve and validate configuration after loading settings.json
|
|
410
|
+
this.resolveAndValidateConfig();
|
|
411
|
+
// Set global logger for SDK-wide access after validation
|
|
412
|
+
setGlobalLogger(this.logger || null);
|
|
413
|
+
// Initialize live configuration reload
|
|
414
|
+
try {
|
|
415
|
+
this.logger?.debug("Initializing live configuration reload...");
|
|
416
|
+
await this.liveConfigManager.initialize();
|
|
417
|
+
this.logger?.debug("Live configuration reload initialized successfully");
|
|
418
|
+
// Update permission manager with configuration-based defaultMode
|
|
419
|
+
const currentConfig = this.liveConfigManager.getCurrentConfiguration();
|
|
420
|
+
if (currentConfig?.defaultMode) {
|
|
421
|
+
this.logger?.debug("Applying configured defaultMode to PermissionManager", {
|
|
422
|
+
defaultMode: currentConfig.defaultMode,
|
|
423
|
+
});
|
|
424
|
+
this.permissionManager.updateConfiguredDefaultMode(currentConfig.defaultMode);
|
|
425
|
+
}
|
|
426
|
+
// Update permission manager with configuration-based allowed rules
|
|
427
|
+
if (currentConfig?.permissions?.allow) {
|
|
428
|
+
this.logger?.debug("Applying configured allowed rules to PermissionManager", {
|
|
429
|
+
count: currentConfig.permissions.allow.length,
|
|
430
|
+
});
|
|
431
|
+
this.permissionManager.updateAllowedRules(currentConfig.permissions.allow);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
this.logger?.error("Failed to initialize live configuration reload:", error);
|
|
436
|
+
// Don't throw error to prevent app startup failure - continue without live reload
|
|
437
|
+
}
|
|
438
|
+
// Load memory files during initialization
|
|
439
|
+
try {
|
|
440
|
+
this.logger?.debug("Loading memory files...");
|
|
441
|
+
// Load project memory from AGENTS.md (bypass memory store for direct file access)
|
|
442
|
+
try {
|
|
443
|
+
const projectMemoryPath = path.join(this.workdir, "AGENTS.md");
|
|
444
|
+
this._projectMemoryContent = await fs.readFile(projectMemoryPath, "utf-8");
|
|
445
|
+
this.logger?.debug("Project memory loaded successfully");
|
|
446
|
+
}
|
|
447
|
+
catch (error) {
|
|
448
|
+
this._projectMemoryContent = "";
|
|
449
|
+
this.logger?.debug("Project memory file not found or unreadable, using empty content:", error instanceof Error ? error.message : String(error));
|
|
450
|
+
}
|
|
451
|
+
// Load user memory (bypass memory store for direct file access)
|
|
452
|
+
try {
|
|
453
|
+
const userMemoryPath = path.join(os.homedir(), ".wave", "AGENTS.md");
|
|
454
|
+
this._userMemoryContent = await fs.readFile(userMemoryPath, "utf-8");
|
|
455
|
+
this.logger?.debug("User memory loaded successfully");
|
|
456
|
+
}
|
|
457
|
+
catch (error) {
|
|
458
|
+
this._userMemoryContent = "";
|
|
459
|
+
this.logger?.debug("User memory file not found or unreadable, using empty content:", error instanceof Error ? error.message : String(error));
|
|
460
|
+
}
|
|
461
|
+
this.logger?.debug("Memory initialization completed");
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
// Ensure memory is always initialized even if loading fails
|
|
465
|
+
this._projectMemoryContent = "";
|
|
466
|
+
this._userMemoryContent = "";
|
|
467
|
+
this.logger?.error("Failed to load memory files:", error);
|
|
468
|
+
// Don't throw error to prevent app startup failure
|
|
469
|
+
}
|
|
264
470
|
// Handle session restoration or set provided messages
|
|
265
471
|
if (options?.messages) {
|
|
266
472
|
// If messages are provided, use them directly (useful for testing)
|
|
267
473
|
this.messageManager.setMessages(options.messages);
|
|
268
474
|
// Rebuild usage array from restored messages
|
|
269
|
-
this.rebuildUsageFromMessages();
|
|
475
|
+
this.rebuildUsageFromMessages(options.messages);
|
|
270
476
|
}
|
|
271
477
|
else {
|
|
272
478
|
// Otherwise, handle session restoration
|
|
273
|
-
await
|
|
479
|
+
const sessionToRestore = await handleSessionRestoration(options?.restoreSessionId, options?.continueLastSession, this.messageManager.getWorkdir());
|
|
274
480
|
// Rebuild usage array from restored messages
|
|
275
|
-
this.rebuildUsageFromMessages();
|
|
481
|
+
this.rebuildUsageFromMessages(sessionToRestore?.messages || []);
|
|
482
|
+
// After main session is restored, restore any associated subagent sessions
|
|
483
|
+
await this.restoreSubagentSessions(sessionToRestore?.messages || []);
|
|
484
|
+
if (sessionToRestore)
|
|
485
|
+
this.messageManager.initializeFromSession(sessionToRestore);
|
|
276
486
|
}
|
|
277
487
|
}
|
|
488
|
+
/**
|
|
489
|
+
* Restore subagent sessions associated with the current main session
|
|
490
|
+
* This method is called after the main session is restored to load any subagent sessions
|
|
491
|
+
*/
|
|
492
|
+
async restoreSubagentSessions(messages) {
|
|
493
|
+
try {
|
|
494
|
+
// Only attempt to restore subagent sessions if we have messages (session was restored)
|
|
495
|
+
if (messages.length === 0) {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
// Extract sessionId -> subagentId mapping from SubagentBlocks
|
|
499
|
+
const subagentBlockMap = new Map(); // sessionId -> { subagentId, configuration }
|
|
500
|
+
for (const message of messages) {
|
|
501
|
+
if (message.role === "assistant" && message.blocks) {
|
|
502
|
+
for (const block of message.blocks) {
|
|
503
|
+
if (block.type === "subagent" &&
|
|
504
|
+
block.sessionId &&
|
|
505
|
+
block.subagentId &&
|
|
506
|
+
block.configuration) {
|
|
507
|
+
subagentBlockMap.set(block.sessionId, {
|
|
508
|
+
subagentId: block.subagentId,
|
|
509
|
+
configuration: block.configuration,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (subagentBlockMap.size === 0) {
|
|
516
|
+
return; // No subagent blocks found
|
|
517
|
+
}
|
|
518
|
+
// Load subagent sessions using sessionIds
|
|
519
|
+
const subagentSessions = [];
|
|
520
|
+
for (const [sessionId, blockData] of subagentBlockMap) {
|
|
521
|
+
try {
|
|
522
|
+
const sessionData = await loadSessionFromJsonl(sessionId, this.messageManager.getWorkdir(), "subagent");
|
|
523
|
+
if (sessionData) {
|
|
524
|
+
subagentSessions.push({
|
|
525
|
+
sessionData,
|
|
526
|
+
subagentId: blockData.subagentId, // Use the subagentId from SubagentBlock
|
|
527
|
+
configuration: blockData.configuration, // Include configuration
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
catch (error) {
|
|
532
|
+
this.logger?.warn(`Failed to load subagent session ${sessionId}:`, error);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (subagentSessions.length > 0) {
|
|
536
|
+
this.logger?.debug(`Found ${subagentSessions.length} subagent sessions to restore`);
|
|
537
|
+
// Restore subagent sessions through the SubagentManager
|
|
538
|
+
await this.subagentManager.restoreSubagentSessions(subagentSessions);
|
|
539
|
+
this.logger?.debug("Subagent sessions restored successfully");
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
catch (error) {
|
|
543
|
+
this.logger?.warn("Failed to restore subagent sessions:", error);
|
|
544
|
+
// Don't throw error to prevent app startup failure
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Restore a session by ID, switching to the target session without destroying the Agent instance
|
|
549
|
+
* @param sessionId - The ID of the session to restore
|
|
550
|
+
*/
|
|
551
|
+
async restoreSession(sessionId) {
|
|
552
|
+
// 1. Validation
|
|
553
|
+
if (!sessionId || sessionId === this.sessionId) {
|
|
554
|
+
return; // No-op if session ID is invalid or already current
|
|
555
|
+
}
|
|
556
|
+
// 2. Auto-save current session
|
|
557
|
+
try {
|
|
558
|
+
await this.messageManager.saveSession();
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
this.logger?.warn("Failed to save current session before restore:", error);
|
|
562
|
+
// Continue with restoration even if save fails
|
|
563
|
+
}
|
|
564
|
+
// 3. Load target session
|
|
565
|
+
const sessionData = await loadSessionFromJsonl(sessionId, this.messageManager.getWorkdir());
|
|
566
|
+
if (!sessionData) {
|
|
567
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
568
|
+
}
|
|
569
|
+
// 4. Clean current state
|
|
570
|
+
this.abortMessage(); // Abort any running operations
|
|
571
|
+
this.subagentManager.cleanup(); // Clean up active subagents
|
|
572
|
+
// 5. Rebuild usage and restore subagents (in correct order)
|
|
573
|
+
this.rebuildUsageFromMessages(sessionData.messages);
|
|
574
|
+
await this.restoreSubagentSessions(sessionData.messages);
|
|
575
|
+
// 6. Initialize session state last
|
|
576
|
+
this.messageManager.initializeFromSession(sessionData);
|
|
577
|
+
}
|
|
278
578
|
abortAIMessage() {
|
|
279
579
|
this.aiManager.abortAIMessage();
|
|
280
580
|
}
|
|
@@ -316,9 +616,47 @@ export class Agent {
|
|
|
316
616
|
this.backgroundBashManager.cleanup();
|
|
317
617
|
// Cleanup MCP connections
|
|
318
618
|
await this.mcpManager.cleanup();
|
|
619
|
+
// Cleanup LSP connections
|
|
620
|
+
if (this.lspManager instanceof LspManager) {
|
|
621
|
+
await this.lspManager.cleanup();
|
|
622
|
+
}
|
|
319
623
|
// Cleanup subagent manager
|
|
320
624
|
this.subagentManager.cleanup();
|
|
625
|
+
// Cleanup live configuration reload
|
|
626
|
+
try {
|
|
627
|
+
await this.liveConfigManager.shutdown();
|
|
628
|
+
}
|
|
629
|
+
catch (error) {
|
|
630
|
+
this.logger?.error("Error shutting down live configuration reload:", error);
|
|
631
|
+
}
|
|
632
|
+
// Cleanup memory store
|
|
321
633
|
}
|
|
634
|
+
/**
|
|
635
|
+
* Send a message to the AI agent with optional images
|
|
636
|
+
*
|
|
637
|
+
* @param content - The text content of the message to send
|
|
638
|
+
* @param images - Optional array of images to include with the message
|
|
639
|
+
* @param images[].path - File path to the image or base64 encoded image data
|
|
640
|
+
* @param images[].mimeType - MIME type of the image (e.g., 'image/png', 'image/jpeg')
|
|
641
|
+
* @returns Promise that resolves when the message has been processed
|
|
642
|
+
*
|
|
643
|
+
* @example
|
|
644
|
+
* ```typescript
|
|
645
|
+
* // Send a text message
|
|
646
|
+
* await agent.sendMessage("Hello, how are you?");
|
|
647
|
+
*
|
|
648
|
+
* // Send a message with images using file paths
|
|
649
|
+
* await agent.sendMessage("What do you see in these images?", [
|
|
650
|
+
* { path: "/path/to/image.png", mimeType: "image/png" },
|
|
651
|
+
* { path: "/path/to/photo.jpg", mimeType: "image/jpeg" }
|
|
652
|
+
* ]);
|
|
653
|
+
*
|
|
654
|
+
* // Send a message with base64 encoded image
|
|
655
|
+
* await agent.sendMessage("Analyze this image", [
|
|
656
|
+
* { path: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...", mimeType: "image/png" }
|
|
657
|
+
* ]);
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
322
660
|
async sendMessage(content, images) {
|
|
323
661
|
try {
|
|
324
662
|
// Handle slash command - check if it's a slash command (starts with /)
|
|
@@ -361,6 +699,7 @@ export class Agent {
|
|
|
361
699
|
transcriptPath: this.messageManager.getTranscriptPath(),
|
|
362
700
|
cwd: this.workdir,
|
|
363
701
|
userPrompt: content,
|
|
702
|
+
env: this.configurationService.getEnvironmentVars(), // Include configuration environment variables
|
|
364
703
|
});
|
|
365
704
|
// Process hook results and determine if we should continue
|
|
366
705
|
const processResult = this.hookManager.processHookResults("UserPromptSubmit", hookResults, this.messageManager);
|
|
@@ -386,23 +725,33 @@ export class Agent {
|
|
|
386
725
|
/** Save memory to project or user memory file */
|
|
387
726
|
async saveMemory(message, type) {
|
|
388
727
|
try {
|
|
728
|
+
// Ensure the message starts with # for memory functions
|
|
729
|
+
const formattedMessage = message.startsWith("#")
|
|
730
|
+
? message
|
|
731
|
+
: `#${message}`;
|
|
389
732
|
if (type === "project") {
|
|
390
|
-
await memory.addMemory(
|
|
733
|
+
await memory.addMemory(formattedMessage, this.workdir);
|
|
734
|
+
// Update internal state after successful save
|
|
735
|
+
this._projectMemoryContent = await memory.readMemoryFile(this.workdir);
|
|
391
736
|
}
|
|
392
737
|
else {
|
|
393
|
-
await memory.addUserMemory(
|
|
738
|
+
await memory.addUserMemory(formattedMessage);
|
|
739
|
+
// Update internal state after successful save
|
|
740
|
+
this._userMemoryContent = await memory.getUserMemoryContent();
|
|
394
741
|
}
|
|
395
742
|
// Add successful MemoryBlock to the last assistant message
|
|
396
743
|
const memoryText = message.substring(1).trim();
|
|
397
744
|
const typeLabel = type === "project" ? "Project Memory" : "User Memory";
|
|
398
|
-
const storagePath =
|
|
745
|
+
const storagePath = "AGENTS.md";
|
|
399
746
|
this.messageManager.addMemoryBlock(`${typeLabel}: ${memoryText}`, true, type, storagePath);
|
|
400
747
|
}
|
|
401
748
|
catch (error) {
|
|
402
749
|
// Add failed MemoryBlock to the last assistant message
|
|
750
|
+
const memoryText = message.substring(1).trim();
|
|
403
751
|
const typeLabel = type === "project" ? "Project Memory" : "User Memory";
|
|
404
|
-
const storagePath =
|
|
405
|
-
|
|
752
|
+
const storagePath = "AGENTS.md";
|
|
753
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
754
|
+
this.messageManager.addMemoryBlock(`${typeLabel}: ${memoryText} - Error: ${errorMessage}`, false, type, storagePath);
|
|
406
755
|
}
|
|
407
756
|
}
|
|
408
757
|
// ========== MCP Management Methods ==========
|
|
@@ -439,4 +788,40 @@ export class Agent {
|
|
|
439
788
|
getCustomCommands() {
|
|
440
789
|
return this.slashCommandManager.getCustomCommands();
|
|
441
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* Get the current permission mode
|
|
793
|
+
*/
|
|
794
|
+
getPermissionMode() {
|
|
795
|
+
return this.toolManager.getPermissionMode();
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Set the permission mode
|
|
799
|
+
* @param mode - The new permission mode
|
|
800
|
+
*/
|
|
801
|
+
setPermissionMode(mode) {
|
|
802
|
+
this.toolManager.setPermissionMode(mode);
|
|
803
|
+
this.options.callbacks?.onPermissionModeChange?.(mode);
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Add a persistent permission rule
|
|
807
|
+
* @param rule - The rule to add (e.g., "Bash(ls)")
|
|
808
|
+
*/
|
|
809
|
+
async addPermissionRule(rule) {
|
|
810
|
+
// 1. Update PermissionManager state
|
|
811
|
+
const currentRules = this.permissionManager.getAllowedRules();
|
|
812
|
+
if (!currentRules.includes(rule)) {
|
|
813
|
+
this.permissionManager.updateAllowedRules([...currentRules, rule]);
|
|
814
|
+
// 2. Persist to settings.local.json
|
|
815
|
+
try {
|
|
816
|
+
await this.configurationService.addAllowedRule(this.workdir, rule);
|
|
817
|
+
this.logger?.debug("Persistent permission rule added", { rule });
|
|
818
|
+
}
|
|
819
|
+
catch (error) {
|
|
820
|
+
this.logger?.error("Failed to persist permission rule", {
|
|
821
|
+
rule,
|
|
822
|
+
error: error instanceof Error ? error.message : String(error),
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
442
827
|
}
|