wave-agent-sdk 0.0.8 → 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 +92 -23
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +340 -137
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/managers/aiManager.d.ts +14 -36
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +74 -77
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +4 -3
- package/dist/managers/hookManager.d.ts +3 -8
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +39 -29
- package/dist/managers/liveConfigManager.d.ts +55 -18
- package/dist/managers/liveConfigManager.d.ts.map +1 -1
- package/dist/managers/liveConfigManager.js +372 -90
- 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 +8 -16
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +52 -74
- 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 +0 -1
- package/dist/managers/subagentManager.d.ts +8 -23
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +97 -117
- 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 +3 -1
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +123 -30
- 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.map +1 -1
- package/dist/services/fileWatcher.js +5 -6
- package/dist/services/hook.d.ts +7 -124
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +46 -458
- package/dist/services/jsonlHandler.d.ts +24 -15
- package/dist/services/jsonlHandler.d.ts.map +1 -1
- package/dist/services/jsonlHandler.js +67 -88
- package/dist/services/memory.d.ts +0 -9
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +2 -49
- package/dist/services/session.d.ts +82 -33
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +275 -181
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +72 -13
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +25 -0
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +30 -6
- 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 +26 -7
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +111 -2
- 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 +25 -9
- package/dist/types/commands.d.ts +0 -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 +10 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +41 -0
- package/dist/types/environment.d.ts.map +1 -1
- 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 +11 -2
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +1 -7
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +5 -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 +6 -11
- 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 +1 -6
- package/dist/types/session.d.ts.map +1 -1
- 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 +21 -4
- 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 +8 -33
- package/dist/utils/cacheControlUtils.d.ts.map +1 -1
- package/dist/utils/cacheControlUtils.js +83 -126
- package/dist/utils/constants.d.ts +0 -12
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +1 -13
- package/dist/utils/convertMessagesForAPI.d.ts +2 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +33 -14
- 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 +14 -2
- package/dist/utils/fileUtils.d.ts.map +1 -1
- package/dist/utils/fileUtils.js +101 -17
- package/dist/utils/globalLogger.d.ts +0 -14
- package/dist/utils/globalLogger.d.ts.map +1 -1
- package/dist/utils/globalLogger.js +0 -16
- 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/messageOperations.d.ts +1 -11
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +7 -24
- package/dist/utils/pathEncoder.d.ts +4 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -1
- package/dist/utils/pathEncoder.js +16 -9
- package/dist/utils/subagentParser.d.ts +2 -2
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +10 -7
- 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 +5 -8
- package/src/agent.ts +460 -216
- package/src/index.ts +2 -0
- package/src/managers/aiManager.ts +107 -111
- package/src/managers/backgroundBashManager.ts +4 -3
- package/src/managers/hookManager.ts +44 -39
- package/src/managers/liveConfigManager.ts +524 -138
- package/src/managers/lspManager.ts +434 -0
- package/src/managers/messageManager.ts +73 -103
- package/src/managers/permissionManager.ts +276 -0
- package/src/managers/skillManager.ts +3 -1
- package/src/managers/slashCommandManager.ts +1 -2
- package/src/managers/subagentManager.ts +116 -159
- package/src/managers/toolManager.ts +95 -3
- package/src/services/aiService.ts +207 -26
- package/src/services/configurationService.ts +762 -0
- package/src/services/fileWatcher.ts +5 -6
- package/src/services/hook.ts +50 -631
- package/src/services/jsonlHandler.ts +84 -100
- package/src/services/memory.ts +2 -59
- package/src/services/session.ts +338 -213
- package/src/tools/bashTool.ts +89 -16
- package/src/tools/deleteFileTool.ts +36 -0
- package/src/tools/editTool.ts +41 -7
- package/src/tools/lspTool.ts +760 -0
- package/src/tools/multiEditTool.ts +37 -8
- package/src/tools/readTool.ts +125 -2
- 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 +36 -10
- package/src/types/commands.ts +0 -1
- package/src/types/config.ts +5 -0
- package/src/types/configuration.ts +73 -0
- package/src/types/core.ts +11 -0
- package/src/types/environment.ts +44 -0
- package/src/types/fileSearch.ts +4 -0
- package/src/types/hooks.ts +14 -11
- package/src/types/index.ts +5 -0
- package/src/types/lsp.ts +96 -0
- package/src/types/messaging.ts +8 -13
- package/src/types/permissions.ts +48 -0
- package/src/types/session.ts +3 -8
- 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 +28 -4
- package/src/utils/builtinSubagents.ts +71 -0
- package/src/utils/cacheControlUtils.ts +106 -171
- package/src/utils/constants.ts +1 -16
- package/src/utils/convertMessagesForAPI.ts +38 -14
- package/src/utils/fileSearch.ts +107 -0
- package/src/utils/fileUtils.ts +114 -19
- package/src/utils/globalLogger.ts +0 -17
- package/src/utils/largeOutputHandler.ts +55 -0
- package/src/utils/markdownParser.ts +1 -19
- package/src/utils/messageOperations.ts +7 -35
- package/src/utils/pathEncoder.ts +24 -9
- package/src/utils/subagentParser.ts +11 -8
- package/src/utils/tokenEstimator.ts +68 -0
- package/dist/constants/events.d.ts +0 -28
- package/dist/constants/events.d.ts.map +0 -1
- package/dist/constants/events.js +0 -27
- package/dist/services/configurationWatcher.d.ts +0 -120
- package/dist/services/configurationWatcher.d.ts.map +0 -1
- package/dist/services/configurationWatcher.js +0 -439
- package/dist/services/memoryStore.d.ts +0 -81
- package/dist/services/memoryStore.d.ts.map +0 -1
- package/dist/services/memoryStore.js +0 -200
- package/dist/types/memoryStore.d.ts +0 -82
- package/dist/types/memoryStore.d.ts.map +0 -1
- package/dist/types/memoryStore.js +0 -7
- package/dist/utils/configResolver.d.ts +0 -65
- package/dist/utils/configResolver.d.ts.map +0 -1
- package/dist/utils/configResolver.js +0 -210
- package/src/constants/events.ts +0 -38
- package/src/services/configurationWatcher.ts +0 -622
- package/src/services/memoryStore.ts +0 -279
- package/src/types/memoryStore.ts +0 -94
- package/src/utils/configResolver.ts +0 -302
package/dist/agent.js
CHANGED
|
@@ -4,19 +4,58 @@ import { ToolManager } from "./managers/toolManager.js";
|
|
|
4
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 { MemoryStoreService } from "./services/memoryStore.js";
|
|
12
|
-
import { initializeMemoryStore } from "./services/memory.js";
|
|
13
13
|
import { LiveConfigManager } from "./managers/liveConfigManager.js";
|
|
14
|
-
import { configResolver } from "./utils/configResolver.js";
|
|
15
14
|
import { configValidator } from "./utils/configValidator.js";
|
|
16
15
|
import { SkillManager } from "./managers/skillManager.js";
|
|
17
|
-
import { loadSessionFromJsonl } from "./services/session.js";
|
|
16
|
+
import { loadSessionFromJsonl, handleSessionRestoration, } from "./services/session.js";
|
|
18
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";
|
|
19
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
|
+
}
|
|
20
59
|
/**
|
|
21
60
|
* Agent constructor - handles configuration resolution and validation
|
|
22
61
|
*
|
|
@@ -29,82 +68,92 @@ export class Agent {
|
|
|
29
68
|
constructor(options) {
|
|
30
69
|
this.bashManager = null;
|
|
31
70
|
this._usages = []; // Usage tracking array
|
|
32
|
-
|
|
33
|
-
|
|
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
|
|
34
76
|
this.workdir = workdir || process.cwd();
|
|
35
|
-
//
|
|
36
|
-
this.
|
|
37
|
-
this.constructorBaseURL = options.baseURL;
|
|
38
|
-
this.constructorAgentModel = options.agentModel;
|
|
39
|
-
this.constructorFastModel = options.fastModel;
|
|
40
|
-
this.constructorTokenLimit = options.tokenLimit;
|
|
41
|
-
// Resolve configuration from constructor args and environment variables with live config support
|
|
42
|
-
const gatewayConfig = configResolver.resolveGatewayConfig(options.apiKey, options.baseURL, this.workdir);
|
|
43
|
-
const modelConfig = configResolver.resolveModelConfig(options.agentModel, options.fastModel, this.workdir);
|
|
44
|
-
const tokenLimit = configResolver.resolveTokenLimit(options.tokenLimit, this.workdir);
|
|
45
|
-
// Validate resolved configuration
|
|
46
|
-
configValidator.validateGatewayConfig(gatewayConfig);
|
|
47
|
-
configValidator.validateTokenLimit(tokenLimit);
|
|
48
|
-
configValidator.validateModelConfig(modelConfig.agentModel, modelConfig.fastModel);
|
|
77
|
+
// Initialize configuration service
|
|
78
|
+
this.configurationService = new ConfigurationService();
|
|
49
79
|
this.logger = logger; // Save the passed logger
|
|
50
80
|
this.systemPrompt = systemPrompt; // Save custom system prompt
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.gatewayConfig = gatewayConfig;
|
|
55
|
-
this.modelConfig = modelConfig;
|
|
56
|
-
this.tokenLimit = tokenLimit;
|
|
81
|
+
this.stream = stream; // Save streaming mode flag
|
|
82
|
+
// Store options for dynamic configuration resolution
|
|
83
|
+
this.options = options;
|
|
57
84
|
this.backgroundBashManager = new BackgroundBashManager({
|
|
58
85
|
callbacks,
|
|
59
86
|
workdir: this.workdir,
|
|
60
87
|
});
|
|
61
88
|
this.mcpManager = new McpManager({ callbacks, logger: this.logger }); // Initialize MCP manager
|
|
62
|
-
this.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
|
|
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
|
|
68
97
|
this.hookManager = new HookManager(this.workdir, undefined, this.logger); // Initialize hooks manager
|
|
69
|
-
|
|
98
|
+
// Initialize MessageManager
|
|
99
|
+
this.messageManager = new MessageManager({
|
|
100
|
+
callbacks,
|
|
70
101
|
workdir: this.workdir,
|
|
71
102
|
logger: this.logger,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
103
|
+
});
|
|
104
|
+
// Create a wrapper for canUseTool that triggers notification hooks
|
|
105
|
+
const canUseToolWithNotification = options.canUseTool
|
|
106
|
+
? async (context) => {
|
|
76
107
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
});
|
|
79
121
|
}
|
|
80
122
|
catch (error) {
|
|
81
|
-
this.logger?.
|
|
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
|
|
82
128
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
this.memoryStore.removeContent(filePath);
|
|
89
|
-
this.logger?.info("Live Config: Removed AGENTS.md from memory store due to file deletion");
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
// Update memory store content for add/change
|
|
93
|
-
await this.memoryStore.updateContent(filePath);
|
|
94
|
-
this.logger?.info("Live Config: Updated AGENTS.md content in memory store");
|
|
95
|
-
}
|
|
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);
|
|
96
134
|
}
|
|
97
|
-
|
|
98
|
-
this.
|
|
135
|
+
if (decision.newPermissionRule) {
|
|
136
|
+
await this.addPermissionRule(decision.newPermissionRule);
|
|
99
137
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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({
|
|
105
151
|
workdir: this.workdir,
|
|
106
152
|
logger: this.logger,
|
|
107
|
-
|
|
153
|
+
hookManager: this.hookManager,
|
|
154
|
+
permissionManager: this.permissionManager,
|
|
155
|
+
configurationService: this.configurationService,
|
|
156
|
+
}); // Initialize live configuration manager
|
|
108
157
|
// Initialize subagent manager with all dependencies in constructor
|
|
109
158
|
// IMPORTANT: Must be initialized AFTER MessageManager
|
|
110
159
|
this.subagentManager = new SubagentManager({
|
|
@@ -115,13 +164,14 @@ export class Agent {
|
|
|
115
164
|
onSubagentUserMessageAdded: callbacks.onSubagentUserMessageAdded,
|
|
116
165
|
onSubagentAssistantMessageAdded: callbacks.onSubagentAssistantMessageAdded,
|
|
117
166
|
onSubagentAssistantContentUpdated: callbacks.onSubagentAssistantContentUpdated,
|
|
167
|
+
onSubagentAssistantReasoningUpdated: callbacks.onSubagentAssistantReasoningUpdated,
|
|
118
168
|
onSubagentToolBlockUpdated: callbacks.onSubagentToolBlockUpdated,
|
|
119
169
|
onSubagentMessagesChange: callbacks.onSubagentMessagesChange,
|
|
120
170
|
}, // Pass subagent callbacks for forwarding
|
|
121
171
|
logger: this.logger,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
172
|
+
getGatewayConfig: () => this.getGatewayConfig(),
|
|
173
|
+
getModelConfig: () => this.getModelConfig(),
|
|
174
|
+
getTokenLimit: () => this.getTokenLimit(),
|
|
125
175
|
hookManager: this.hookManager,
|
|
126
176
|
onUsageAdded: (usage) => this.addUsage(usage),
|
|
127
177
|
});
|
|
@@ -140,9 +190,11 @@ export class Agent {
|
|
|
140
190
|
},
|
|
141
191
|
workdir: this.workdir,
|
|
142
192
|
systemPrompt: this.systemPrompt,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
|
146
198
|
});
|
|
147
199
|
// Initialize command manager
|
|
148
200
|
this.slashCommandManager = new SlashCommandManager({
|
|
@@ -174,9 +226,9 @@ export class Agent {
|
|
|
174
226
|
* Rebuild usage array from messages containing usage metadata
|
|
175
227
|
* Called during session restoration to reconstruct usage tracking
|
|
176
228
|
*/
|
|
177
|
-
rebuildUsageFromMessages() {
|
|
229
|
+
rebuildUsageFromMessages(messages) {
|
|
178
230
|
this._usages = [];
|
|
179
|
-
|
|
231
|
+
messages.forEach((message) => {
|
|
180
232
|
if (message.role === "assistant" && message.usage) {
|
|
181
233
|
this._usages.push(message.usage);
|
|
182
234
|
}
|
|
@@ -202,9 +254,27 @@ export class Agent {
|
|
|
202
254
|
get workingDirectory() {
|
|
203
255
|
return this.workdir;
|
|
204
256
|
}
|
|
205
|
-
/** Get
|
|
206
|
-
get
|
|
207
|
-
return this.
|
|
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;
|
|
208
278
|
}
|
|
209
279
|
/** Get AI loading status */
|
|
210
280
|
get isLoading() {
|
|
@@ -244,6 +314,9 @@ export class Agent {
|
|
|
244
314
|
* @param options - Configuration options for the Agent instance
|
|
245
315
|
* @param options.apiKey - API key for the AI service (or set WAVE_API_KEY env var)
|
|
246
316
|
* @param options.baseURL - Base URL for the AI service (or set WAVE_BASE_URL env var)
|
|
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
|
|
247
320
|
* @param options.callbacks - Optional callbacks for various Agent events
|
|
248
321
|
* @param options.restoreSessionId - Optional session ID to restore from
|
|
249
322
|
* @param options.continueLastSession - Whether to continue the last session automatically
|
|
@@ -263,7 +336,7 @@ export class Agent {
|
|
|
263
336
|
* ```
|
|
264
337
|
*/
|
|
265
338
|
static async create(options) {
|
|
266
|
-
// Create Agent instance
|
|
339
|
+
// Create Agent instance
|
|
267
340
|
const instance = new Agent(options);
|
|
268
341
|
await instance.initialize({
|
|
269
342
|
restoreSessionId: options.restoreSessionId,
|
|
@@ -272,12 +345,31 @@ export class Agent {
|
|
|
272
345
|
});
|
|
273
346
|
return instance;
|
|
274
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
|
+
}
|
|
275
364
|
/** Private initialization method, handles async initialization logic */
|
|
276
365
|
async initialize(options) {
|
|
277
366
|
// Initialize managers first
|
|
278
367
|
try {
|
|
279
368
|
// Initialize SkillManager
|
|
280
|
-
const skillManager = new SkillManager({
|
|
369
|
+
const skillManager = new SkillManager({
|
|
370
|
+
logger: this.logger,
|
|
371
|
+
workdir: this.workdir,
|
|
372
|
+
});
|
|
281
373
|
await skillManager.initialize();
|
|
282
374
|
// Initialize SubagentManager (load and cache configurations)
|
|
283
375
|
await this.subagentManager.initialize();
|
|
@@ -294,6 +386,9 @@ export class Agent {
|
|
|
294
386
|
// Initialize MCP servers with auto-connect
|
|
295
387
|
try {
|
|
296
388
|
await this.mcpManager.initialize(this.workdir, true);
|
|
389
|
+
if (this.lspManager instanceof LspManager) {
|
|
390
|
+
await this.lspManager.initialize(this.workdir);
|
|
391
|
+
}
|
|
297
392
|
}
|
|
298
393
|
catch (error) {
|
|
299
394
|
this.logger?.error("Failed to initialize MCP servers:", error);
|
|
@@ -301,54 +396,108 @@ export class Agent {
|
|
|
301
396
|
}
|
|
302
397
|
// Initialize hooks configuration
|
|
303
398
|
try {
|
|
304
|
-
// Load hooks configuration
|
|
399
|
+
// Load hooks configuration using ConfigurationService
|
|
305
400
|
this.logger?.debug("Loading hooks configuration...");
|
|
306
|
-
this.
|
|
401
|
+
const configResult = await this.configurationService.loadMergedConfiguration(this.workdir);
|
|
402
|
+
this.hookManager.loadConfigurationFromWaveConfig(configResult.configuration);
|
|
307
403
|
this.logger?.debug("Hooks system initialized successfully");
|
|
308
404
|
}
|
|
309
405
|
catch (error) {
|
|
310
406
|
this.logger?.error("Failed to initialize hooks system:", error);
|
|
311
407
|
// Don't throw error to prevent app startup failure
|
|
312
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);
|
|
313
413
|
// Initialize live configuration reload
|
|
314
414
|
try {
|
|
315
415
|
this.logger?.debug("Initializing live configuration reload...");
|
|
316
416
|
await this.liveConfigManager.initialize();
|
|
317
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
|
+
}
|
|
318
433
|
}
|
|
319
434
|
catch (error) {
|
|
320
435
|
this.logger?.error("Failed to initialize live configuration reload:", error);
|
|
321
436
|
// Don't throw error to prevent app startup failure - continue without live reload
|
|
322
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
|
+
}
|
|
323
470
|
// Handle session restoration or set provided messages
|
|
324
471
|
if (options?.messages) {
|
|
325
472
|
// If messages are provided, use them directly (useful for testing)
|
|
326
473
|
this.messageManager.setMessages(options.messages);
|
|
327
474
|
// Rebuild usage array from restored messages
|
|
328
|
-
this.rebuildUsageFromMessages();
|
|
475
|
+
this.rebuildUsageFromMessages(options.messages);
|
|
329
476
|
}
|
|
330
477
|
else {
|
|
331
478
|
// Otherwise, handle session restoration
|
|
332
|
-
await
|
|
479
|
+
const sessionToRestore = await handleSessionRestoration(options?.restoreSessionId, options?.continueLastSession, this.messageManager.getWorkdir());
|
|
333
480
|
// Rebuild usage array from restored messages
|
|
334
|
-
this.rebuildUsageFromMessages();
|
|
481
|
+
this.rebuildUsageFromMessages(sessionToRestore?.messages || []);
|
|
335
482
|
// After main session is restored, restore any associated subagent sessions
|
|
336
|
-
await this.restoreSubagentSessions();
|
|
483
|
+
await this.restoreSubagentSessions(sessionToRestore?.messages || []);
|
|
484
|
+
if (sessionToRestore)
|
|
485
|
+
this.messageManager.initializeFromSession(sessionToRestore);
|
|
337
486
|
}
|
|
338
487
|
}
|
|
339
488
|
/**
|
|
340
489
|
* Restore subagent sessions associated with the current main session
|
|
341
490
|
* This method is called after the main session is restored to load any subagent sessions
|
|
342
491
|
*/
|
|
343
|
-
async restoreSubagentSessions() {
|
|
492
|
+
async restoreSubagentSessions(messages) {
|
|
344
493
|
try {
|
|
345
494
|
// Only attempt to restore subagent sessions if we have messages (session was restored)
|
|
346
|
-
if (
|
|
495
|
+
if (messages.length === 0) {
|
|
347
496
|
return;
|
|
348
497
|
}
|
|
349
498
|
// Extract sessionId -> subagentId mapping from SubagentBlocks
|
|
350
499
|
const subagentBlockMap = new Map(); // sessionId -> { subagentId, configuration }
|
|
351
|
-
for (const message of
|
|
500
|
+
for (const message of messages) {
|
|
352
501
|
if (message.role === "assistant" && message.blocks) {
|
|
353
502
|
for (const block of message.blocks) {
|
|
354
503
|
if (block.type === "subagent" &&
|
|
@@ -370,7 +519,7 @@ export class Agent {
|
|
|
370
519
|
const subagentSessions = [];
|
|
371
520
|
for (const [sessionId, blockData] of subagentBlockMap) {
|
|
372
521
|
try {
|
|
373
|
-
const sessionData = await loadSessionFromJsonl(sessionId, this.messageManager.getWorkdir());
|
|
522
|
+
const sessionData = await loadSessionFromJsonl(sessionId, this.messageManager.getWorkdir(), "subagent");
|
|
374
523
|
if (sessionData) {
|
|
375
524
|
subagentSessions.push({
|
|
376
525
|
sessionData,
|
|
@@ -395,6 +544,37 @@ export class Agent {
|
|
|
395
544
|
// Don't throw error to prevent app startup failure
|
|
396
545
|
}
|
|
397
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
|
+
}
|
|
398
578
|
abortAIMessage() {
|
|
399
579
|
this.aiManager.abortAIMessage();
|
|
400
580
|
}
|
|
@@ -436,6 +616,10 @@ export class Agent {
|
|
|
436
616
|
this.backgroundBashManager.cleanup();
|
|
437
617
|
// Cleanup MCP connections
|
|
438
618
|
await this.mcpManager.cleanup();
|
|
619
|
+
// Cleanup LSP connections
|
|
620
|
+
if (this.lspManager instanceof LspManager) {
|
|
621
|
+
await this.lspManager.cleanup();
|
|
622
|
+
}
|
|
439
623
|
// Cleanup subagent manager
|
|
440
624
|
this.subagentManager.cleanup();
|
|
441
625
|
// Cleanup live configuration reload
|
|
@@ -446,14 +630,33 @@ export class Agent {
|
|
|
446
630
|
this.logger?.error("Error shutting down live configuration reload:", error);
|
|
447
631
|
}
|
|
448
632
|
// Cleanup memory store
|
|
449
|
-
try {
|
|
450
|
-
this.memoryStore.clear();
|
|
451
|
-
this.logger?.debug("Memory store cleared successfully");
|
|
452
|
-
}
|
|
453
|
-
catch (error) {
|
|
454
|
-
this.logger?.error("Error clearing memory store:", error);
|
|
455
|
-
}
|
|
456
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
|
+
*/
|
|
457
660
|
async sendMessage(content, images) {
|
|
458
661
|
try {
|
|
459
662
|
// Handle slash command - check if it's a slash command (starts with /)
|
|
@@ -496,6 +699,7 @@ export class Agent {
|
|
|
496
699
|
transcriptPath: this.messageManager.getTranscriptPath(),
|
|
497
700
|
cwd: this.workdir,
|
|
498
701
|
userPrompt: content,
|
|
702
|
+
env: this.configurationService.getEnvironmentVars(), // Include configuration environment variables
|
|
499
703
|
});
|
|
500
704
|
// Process hook results and determine if we should continue
|
|
501
705
|
const processResult = this.hookManager.processHookResults("UserPromptSubmit", hookResults, this.messageManager);
|
|
@@ -521,23 +725,33 @@ export class Agent {
|
|
|
521
725
|
/** Save memory to project or user memory file */
|
|
522
726
|
async saveMemory(message, type) {
|
|
523
727
|
try {
|
|
728
|
+
// Ensure the message starts with # for memory functions
|
|
729
|
+
const formattedMessage = message.startsWith("#")
|
|
730
|
+
? message
|
|
731
|
+
: `#${message}`;
|
|
524
732
|
if (type === "project") {
|
|
525
|
-
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);
|
|
526
736
|
}
|
|
527
737
|
else {
|
|
528
|
-
await memory.addUserMemory(
|
|
738
|
+
await memory.addUserMemory(formattedMessage);
|
|
739
|
+
// Update internal state after successful save
|
|
740
|
+
this._userMemoryContent = await memory.getUserMemoryContent();
|
|
529
741
|
}
|
|
530
742
|
// Add successful MemoryBlock to the last assistant message
|
|
531
743
|
const memoryText = message.substring(1).trim();
|
|
532
744
|
const typeLabel = type === "project" ? "Project Memory" : "User Memory";
|
|
533
|
-
const storagePath =
|
|
745
|
+
const storagePath = "AGENTS.md";
|
|
534
746
|
this.messageManager.addMemoryBlock(`${typeLabel}: ${memoryText}`, true, type, storagePath);
|
|
535
747
|
}
|
|
536
748
|
catch (error) {
|
|
537
749
|
// Add failed MemoryBlock to the last assistant message
|
|
750
|
+
const memoryText = message.substring(1).trim();
|
|
538
751
|
const typeLabel = type === "project" ? "Project Memory" : "User Memory";
|
|
539
|
-
const storagePath =
|
|
540
|
-
|
|
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);
|
|
541
755
|
}
|
|
542
756
|
}
|
|
543
757
|
// ========== MCP Management Methods ==========
|
|
@@ -574,51 +788,40 @@ export class Agent {
|
|
|
574
788
|
getCustomCommands() {
|
|
575
789
|
return this.slashCommandManager.getCustomCommands();
|
|
576
790
|
}
|
|
577
|
-
// ========== Live Configuration Management ==========
|
|
578
791
|
/**
|
|
579
|
-
*
|
|
580
|
-
* This method refreshes all configuration-dependent components with new values
|
|
581
|
-
* Note: Constructor values still take precedence over live configuration
|
|
792
|
+
* Get the current permission mode
|
|
582
793
|
*/
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
this.logger?.info("Live Config: Updating Agent configuration from live settings");
|
|
586
|
-
// Re-resolve configuration with current workdir, preserving constructor overrides
|
|
587
|
-
// We need to track what was explicitly provided in constructor vs. what should use live config
|
|
588
|
-
const newGatewayConfig = configResolver.resolveGatewayConfig(this.constructorApiKey, // Preserve constructor override if provided
|
|
589
|
-
this.constructorBaseURL, // Preserve constructor override if provided
|
|
590
|
-
this.workdir);
|
|
591
|
-
const newModelConfig = configResolver.resolveModelConfig(this.constructorAgentModel, // Preserve constructor override if provided
|
|
592
|
-
this.constructorFastModel, // Preserve constructor override if provided
|
|
593
|
-
this.workdir);
|
|
594
|
-
const newTokenLimit = configResolver.resolveTokenLimit(this.constructorTokenLimit, this.workdir);
|
|
595
|
-
// Validate new configuration
|
|
596
|
-
configValidator.validateGatewayConfig(newGatewayConfig);
|
|
597
|
-
configValidator.validateTokenLimit(newTokenLimit);
|
|
598
|
-
configValidator.validateModelConfig(newModelConfig.agentModel, newModelConfig.fastModel);
|
|
599
|
-
// Update stored configuration
|
|
600
|
-
this.gatewayConfig = newGatewayConfig;
|
|
601
|
-
this.modelConfig = newModelConfig;
|
|
602
|
-
this.tokenLimit = newTokenLimit;
|
|
603
|
-
// Update AIManager with new configuration
|
|
604
|
-
this.aiManager.updateConfiguration(newGatewayConfig, newModelConfig, newTokenLimit);
|
|
605
|
-
// Update SubagentManager with new configuration
|
|
606
|
-
this.subagentManager.updateConfiguration(newGatewayConfig, newModelConfig, newTokenLimit);
|
|
607
|
-
this.logger?.info(`Live Config: Agent configuration updated successfully - model: ${newModelConfig.agentModel}, tokenLimit: ${newTokenLimit}`);
|
|
608
|
-
}
|
|
609
|
-
catch (error) {
|
|
610
|
-
this.logger?.error(`Live Config: Failed to update Agent configuration: ${error.message}`);
|
|
611
|
-
// Don't throw - continue with previous configuration
|
|
612
|
-
}
|
|
794
|
+
getPermissionMode() {
|
|
795
|
+
return this.toolManager.getPermissionMode();
|
|
613
796
|
}
|
|
614
797
|
/**
|
|
615
|
-
*
|
|
798
|
+
* Set the permission mode
|
|
799
|
+
* @param mode - The new permission mode
|
|
616
800
|
*/
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
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
|
+
}
|
|
623
826
|
}
|
|
624
827
|
}
|