wave-agent-sdk 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +8 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +49 -240
- package/dist/constants/tools.d.ts +0 -2
- package/dist/constants/tools.d.ts.map +1 -1
- package/dist/constants/tools.js +0 -2
- package/dist/core/plugin.d.ts +86 -0
- package/dist/core/plugin.d.ts.map +1 -0
- package/dist/core/plugin.js +164 -0
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -5
- package/dist/managers/MemoryRuleManager.d.ts +3 -1
- package/dist/managers/MemoryRuleManager.d.ts.map +1 -1
- package/dist/managers/MemoryRuleManager.js +2 -1
- package/dist/managers/aiManager.d.ts +13 -23
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +59 -32
- package/dist/managers/backgroundTaskManager.d.ts +3 -1
- package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
- package/dist/managers/backgroundTaskManager.js +2 -1
- package/dist/managers/bashManager.d.ts +4 -4
- package/dist/managers/bashManager.d.ts.map +1 -1
- package/dist/managers/bashManager.js +5 -2
- package/dist/managers/foregroundTaskManager.d.ts +3 -0
- package/dist/managers/foregroundTaskManager.d.ts.map +1 -1
- package/dist/managers/foregroundTaskManager.js +2 -1
- package/dist/managers/hookManager.d.ts +3 -3
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +20 -19
- package/dist/managers/liveConfigManager.d.ts +6 -13
- package/dist/managers/liveConfigManager.d.ts.map +1 -1
- package/dist/managers/liveConfigManager.js +50 -45
- package/dist/managers/lspManager.d.ts +4 -5
- package/dist/managers/lspManager.d.ts.map +1 -1
- package/dist/managers/lspManager.js +13 -12
- package/dist/managers/mcpManager.d.ts +3 -2
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/mcpManager.js +16 -15
- package/dist/managers/messageManager.d.ts +5 -7
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +12 -7
- package/dist/managers/permissionManager.d.ts +6 -4
- package/dist/managers/permissionManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.js +39 -63
- package/dist/managers/planManager.d.ts +4 -6
- package/dist/managers/planManager.d.ts.map +1 -1
- package/dist/managers/planManager.js +18 -4
- package/dist/managers/pluginManager.d.ts +10 -22
- package/dist/managers/pluginManager.d.ts.map +1 -1
- package/dist/managers/pluginManager.js +27 -14
- package/dist/managers/reversionManager.d.ts +4 -3
- package/dist/managers/reversionManager.d.ts.map +1 -1
- package/dist/managers/reversionManager.js +5 -2
- package/dist/managers/skillManager.d.ts +3 -2
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +15 -14
- package/dist/managers/slashCommandManager.d.ts +9 -16
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +21 -10
- package/dist/managers/subagentManager.d.ts +7 -17
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +41 -34
- package/dist/managers/toolManager.d.ts +15 -38
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +66 -56
- package/dist/prompts/index.d.ts +6 -3
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +8 -16
- package/dist/services/MarketplaceService.d.ts.map +1 -1
- package/dist/services/MarketplaceService.js +13 -0
- package/dist/services/aiService.d.ts +4 -0
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +47 -7
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +30 -11
- package/dist/services/taskManager.d.ts +3 -1
- package/dist/services/taskManager.d.ts.map +1 -1
- package/dist/services/taskManager.js +2 -1
- package/dist/tools/bashTool.js +2 -2
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +9 -1
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +2 -2
- package/dist/tools/skillTool.d.ts +2 -4
- package/dist/tools/skillTool.d.ts.map +1 -1
- package/dist/tools/skillTool.js +61 -61
- package/dist/tools/taskOutputTool.js +1 -1
- package/dist/tools/taskTool.d.ts +2 -4
- package/dist/tools/taskTool.d.ts.map +1 -1
- package/dist/tools/taskTool.js +192 -187
- package/dist/tools/types.d.ts +11 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +4 -2
- package/dist/types/marketplace.d.ts +8 -0
- package/dist/types/marketplace.d.ts.map +1 -1
- package/dist/types/permissions.d.ts +1 -1
- package/dist/types/permissions.d.ts.map +1 -1
- package/dist/types/permissions.js +1 -3
- package/dist/types/skills.d.ts +0 -2
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/tools.d.ts +0 -15
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/utils/container.d.ts +31 -0
- package/dist/utils/container.d.ts.map +1 -0
- package/dist/utils/container.js +79 -0
- package/dist/utils/containerSetup.d.ts +26 -0
- package/dist/utils/containerSetup.d.ts.map +1 -0
- package/dist/utils/containerSetup.js +165 -0
- package/dist/utils/editUtils.d.ts +0 -3
- package/dist/utils/editUtils.d.ts.map +1 -1
- package/dist/utils/editUtils.js +4 -3
- package/dist/utils/hookMatcher.d.ts +1 -1
- package/dist/utils/hookMatcher.d.ts.map +1 -1
- package/dist/utils/hookMatcher.js +2 -2
- package/dist/utils/openaiClient.js +2 -2
- package/dist/utils/stringUtils.d.ts +6 -0
- package/dist/utils/stringUtils.d.ts.map +1 -1
- package/dist/utils/stringUtils.js +8 -0
- package/package.json +1 -1
- package/src/agent.ts +60 -282
- package/src/constants/tools.ts +0 -2
- package/src/core/plugin.ts +224 -0
- package/src/index.ts +1 -6
- package/src/managers/MemoryRuleManager.ts +6 -1
- package/src/managers/aiManager.ts +83 -58
- package/src/managers/backgroundTaskManager.ts +5 -1
- package/src/managers/bashManager.ts +9 -4
- package/src/managers/foregroundTaskManager.ts +3 -0
- package/src/managers/hookManager.ts +21 -23
- package/src/managers/liveConfigManager.ts +57 -53
- package/src/managers/lspManager.ts +14 -19
- package/src/managers/mcpManager.ts +20 -20
- package/src/managers/messageManager.ts +19 -12
- package/src/managers/permissionManager.ts +45 -70
- package/src/managers/planManager.ts +26 -7
- package/src/managers/pluginManager.ts +37 -33
- package/src/managers/reversionManager.ts +5 -3
- package/src/managers/skillManager.ts +19 -20
- package/src/managers/slashCommandManager.ts +30 -25
- package/src/managers/subagentManager.ts +53 -53
- package/src/managers/toolManager.ts +91 -90
- package/src/prompts/index.ts +12 -24
- package/src/services/MarketplaceService.ts +13 -0
- package/src/services/aiService.ts +61 -15
- package/src/services/configurationService.ts +34 -13
- package/src/services/taskManager.ts +5 -1
- package/src/tools/bashTool.ts +2 -2
- package/src/tools/editTool.ts +9 -1
- package/src/tools/readTool.ts +2 -2
- package/src/tools/skillTool.ts +75 -71
- package/src/tools/taskOutputTool.ts +1 -1
- package/src/tools/taskTool.ts +224 -225
- package/src/tools/types.ts +12 -1
- package/src/tools/writeTool.ts +4 -2
- package/src/types/marketplace.ts +9 -0
- package/src/types/permissions.ts +0 -4
- package/src/types/skills.ts +0 -3
- package/src/types/tools.ts +0 -17
- package/src/utils/container.ts +92 -0
- package/src/utils/containerSetup.ts +256 -0
- package/src/utils/editUtils.ts +4 -3
- package/src/utils/hookMatcher.ts +2 -2
- package/src/utils/openaiClient.ts +2 -2
- package/src/utils/stringUtils.ts +9 -0
- package/dist/tools/deleteFileTool.d.ts +0 -6
- package/dist/tools/deleteFileTool.d.ts.map +0 -1
- package/dist/tools/deleteFileTool.js +0 -100
- package/dist/tools/multiEditTool.d.ts +0 -6
- package/dist/tools/multiEditTool.d.ts.map +0 -1
- package/dist/tools/multiEditTool.js +0 -246
- package/src/tools/deleteFileTool.ts +0 -127
- package/src/tools/multiEditTool.ts +0 -306
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { existsSync } from "fs";
|
|
11
|
-
import type { Logger } from "../types/index.js";
|
|
12
11
|
import type { PermissionMode } from "../types/permissions.js";
|
|
13
12
|
import type { Scope } from "../types/configuration.js";
|
|
14
13
|
import {
|
|
@@ -25,27 +24,22 @@ import type { HookValidationResult } from "../types/hooks.js";
|
|
|
25
24
|
import { isValidHookEvent, isValidHookEventConfig } from "../types/hooks.js";
|
|
26
25
|
import { ConfigurationService } from "../services/configurationService.js";
|
|
27
26
|
import { ensureGlobalGitIgnore } from "../utils/fileUtils.js";
|
|
27
|
+
import { Container } from "../utils/container.js";
|
|
28
28
|
|
|
29
29
|
import type {
|
|
30
30
|
ConfigurationLoadResult,
|
|
31
31
|
WaveConfiguration,
|
|
32
32
|
} from "../types/configuration.js";
|
|
33
33
|
|
|
34
|
+
import { logger } from "../utils/globalLogger.js";
|
|
35
|
+
|
|
34
36
|
export interface LiveConfigManagerOptions {
|
|
35
37
|
workdir: string;
|
|
36
|
-
logger?: Logger;
|
|
37
|
-
hookManager?: HookManager;
|
|
38
|
-
permissionManager?: PermissionManager;
|
|
39
|
-
configurationService?: ConfigurationService;
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
export class LiveConfigManager {
|
|
43
41
|
private readonly workdir: string;
|
|
44
|
-
private readonly logger?: Logger;
|
|
45
|
-
private readonly hookManager?: HookManager;
|
|
46
|
-
private readonly permissionManager?: PermissionManager;
|
|
47
42
|
private isInitialized: boolean = false;
|
|
48
|
-
private readonly configurationService: ConfigurationService;
|
|
49
43
|
|
|
50
44
|
// Configuration state
|
|
51
45
|
private currentConfiguration: WaveConfiguration | null = null;
|
|
@@ -58,17 +52,27 @@ export class LiveConfigManager {
|
|
|
58
52
|
private isWatching: boolean = false;
|
|
59
53
|
private reloadInProgress: boolean = false;
|
|
60
54
|
|
|
61
|
-
constructor(
|
|
55
|
+
constructor(
|
|
56
|
+
private container: Container,
|
|
57
|
+
options: LiveConfigManagerOptions,
|
|
58
|
+
) {
|
|
62
59
|
this.workdir = options.workdir;
|
|
63
|
-
this.
|
|
64
|
-
this.hookManager = options.hookManager;
|
|
65
|
-
this.permissionManager = options.permissionManager;
|
|
66
|
-
this.configurationService =
|
|
67
|
-
options.configurationService || new ConfigurationService();
|
|
68
|
-
this.fileWatcher = new FileWatcherService(this.logger);
|
|
60
|
+
this.fileWatcher = new FileWatcherService(logger);
|
|
69
61
|
this.setupFileWatcherEvents();
|
|
70
62
|
}
|
|
71
63
|
|
|
64
|
+
private get hookManager(): HookManager | undefined {
|
|
65
|
+
return this.container.get<HookManager>("HookManager");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private get permissionManager(): PermissionManager | undefined {
|
|
69
|
+
return this.container.get<PermissionManager>("PermissionManager");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private get configurationService(): ConfigurationService {
|
|
73
|
+
return this.container.get<ConfigurationService>("ConfigurationService")!;
|
|
74
|
+
}
|
|
75
|
+
|
|
72
76
|
/**
|
|
73
77
|
* Initialize configuration watching
|
|
74
78
|
* Maps to FR-004: System MUST watch settings.json files
|
|
@@ -79,7 +83,7 @@ export class LiveConfigManager {
|
|
|
79
83
|
projectPaths?: string[],
|
|
80
84
|
): Promise<void> {
|
|
81
85
|
try {
|
|
82
|
-
|
|
86
|
+
logger?.debug("Live Config: Initializing configuration watching...");
|
|
83
87
|
|
|
84
88
|
this.userConfigPaths = userPaths;
|
|
85
89
|
this.projectConfigPaths = projectPaths;
|
|
@@ -90,14 +94,14 @@ export class LiveConfigManager {
|
|
|
90
94
|
// Start watching user configs that exist
|
|
91
95
|
for (const userPath of userPaths) {
|
|
92
96
|
if (existsSync(userPath)) {
|
|
93
|
-
|
|
97
|
+
logger?.debug(
|
|
94
98
|
`Live Config: Starting to watch user config: ${userPath}`,
|
|
95
99
|
);
|
|
96
100
|
await this.fileWatcher.watchFile(userPath, (event) =>
|
|
97
101
|
this.handleFileChange(event, "user"),
|
|
98
102
|
);
|
|
99
103
|
} else {
|
|
100
|
-
|
|
104
|
+
logger?.debug(
|
|
101
105
|
`Live Config: User config file does not exist: ${userPath}`,
|
|
102
106
|
);
|
|
103
107
|
}
|
|
@@ -110,14 +114,14 @@ export class LiveConfigManager {
|
|
|
110
114
|
if (projectPath.endsWith("settings.local.json")) {
|
|
111
115
|
await ensureGlobalGitIgnore("**/.wave/settings.local.json");
|
|
112
116
|
}
|
|
113
|
-
|
|
117
|
+
logger?.debug(
|
|
114
118
|
`Live Config: Starting to watch project config: ${projectPath}`,
|
|
115
119
|
);
|
|
116
120
|
await this.fileWatcher.watchFile(projectPath, (event) =>
|
|
117
121
|
this.handleFileChange(event, "project"),
|
|
118
122
|
);
|
|
119
123
|
} else {
|
|
120
|
-
|
|
124
|
+
logger?.debug(
|
|
121
125
|
`Live Config: Project config file does not exist: ${projectPath}`,
|
|
122
126
|
);
|
|
123
127
|
}
|
|
@@ -125,12 +129,12 @@ export class LiveConfigManager {
|
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
this.isWatching = true;
|
|
128
|
-
|
|
132
|
+
logger?.debug(
|
|
129
133
|
"Live Config: Configuration watching initialized successfully",
|
|
130
134
|
);
|
|
131
135
|
} catch (error) {
|
|
132
136
|
const errorMessage = `Failed to initialize configuration watching: ${(error as Error).message}`;
|
|
133
|
-
|
|
137
|
+
logger?.error(`Live Config: ${errorMessage}`);
|
|
134
138
|
throw new Error(errorMessage);
|
|
135
139
|
}
|
|
136
140
|
}
|
|
@@ -147,7 +151,7 @@ export class LiveConfigManager {
|
|
|
147
151
|
*/
|
|
148
152
|
async initialize(): Promise<void> {
|
|
149
153
|
if (this.isInitialized) {
|
|
150
|
-
|
|
154
|
+
logger?.debug("Already initialized");
|
|
151
155
|
return;
|
|
152
156
|
}
|
|
153
157
|
|
|
@@ -159,11 +163,11 @@ export class LiveConfigManager {
|
|
|
159
163
|
await this.initializeWatching(userPaths, projectPaths);
|
|
160
164
|
|
|
161
165
|
this.isInitialized = true;
|
|
162
|
-
|
|
166
|
+
logger?.debug(
|
|
163
167
|
"Live configuration management initialized with file watching",
|
|
164
168
|
);
|
|
165
169
|
} catch (error) {
|
|
166
|
-
|
|
170
|
+
logger?.error(`Failed to initialize: ${(error as Error).message}`);
|
|
167
171
|
throw error;
|
|
168
172
|
}
|
|
169
173
|
}
|
|
@@ -177,7 +181,7 @@ export class LiveConfigManager {
|
|
|
177
181
|
}
|
|
178
182
|
|
|
179
183
|
try {
|
|
180
|
-
|
|
184
|
+
logger?.debug("Live Config: Shutting down configuration manager...");
|
|
181
185
|
|
|
182
186
|
this.isWatching = false;
|
|
183
187
|
|
|
@@ -189,9 +193,9 @@ export class LiveConfigManager {
|
|
|
189
193
|
this.lastValidConfiguration = null;
|
|
190
194
|
|
|
191
195
|
this.isInitialized = false;
|
|
192
|
-
|
|
196
|
+
logger?.debug("Live configuration management shutdown completed");
|
|
193
197
|
} catch (error) {
|
|
194
|
-
|
|
198
|
+
logger?.error(`Error during shutdown: ${(error as Error).message}`);
|
|
195
199
|
throw error;
|
|
196
200
|
}
|
|
197
201
|
}
|
|
@@ -202,14 +206,14 @@ export class LiveConfigManager {
|
|
|
202
206
|
*/
|
|
203
207
|
private async reloadConfiguration(): Promise<WaveConfiguration> {
|
|
204
208
|
if (this.reloadInProgress) {
|
|
205
|
-
|
|
209
|
+
logger?.debug("Live Config: Reload already in progress, skipping");
|
|
206
210
|
return this.currentConfiguration || {};
|
|
207
211
|
}
|
|
208
212
|
|
|
209
213
|
this.reloadInProgress = true;
|
|
210
214
|
|
|
211
215
|
try {
|
|
212
|
-
|
|
216
|
+
logger?.debug("Live Config: Reloading configuration from files...");
|
|
213
217
|
|
|
214
218
|
// Load merged configuration using ConfigurationService
|
|
215
219
|
const loadResult: ConfigurationLoadResult =
|
|
@@ -220,20 +224,20 @@ export class LiveConfigManager {
|
|
|
220
224
|
if (!loadResult.success) {
|
|
221
225
|
const errorMessage =
|
|
222
226
|
loadResult.error || "Configuration loading failed with unknown error";
|
|
223
|
-
|
|
227
|
+
logger?.error(
|
|
224
228
|
`Live Config: Configuration loading failed: ${errorMessage}`,
|
|
225
229
|
);
|
|
226
230
|
|
|
227
231
|
// Log warnings if any
|
|
228
232
|
if (loadResult.warnings && loadResult.warnings.length > 0) {
|
|
229
|
-
|
|
233
|
+
logger?.warn(
|
|
230
234
|
`Live Config: Configuration warnings: ${loadResult.warnings.join("; ")}`,
|
|
231
235
|
);
|
|
232
236
|
}
|
|
233
237
|
|
|
234
238
|
// Use fallback configuration if available
|
|
235
239
|
if (this.lastValidConfiguration) {
|
|
236
|
-
|
|
240
|
+
logger?.debug(
|
|
237
241
|
"Live Config: Using previous valid configuration due to loading errors",
|
|
238
242
|
);
|
|
239
243
|
this.currentConfiguration = this.lastValidConfiguration;
|
|
@@ -254,7 +258,7 @@ export class LiveConfigManager {
|
|
|
254
258
|
|
|
255
259
|
return this.currentConfiguration;
|
|
256
260
|
} else {
|
|
257
|
-
|
|
261
|
+
logger?.warn(
|
|
258
262
|
"Live Config: No previous valid configuration available, using empty config",
|
|
259
263
|
);
|
|
260
264
|
this.currentConfiguration = {};
|
|
@@ -264,25 +268,25 @@ export class LiveConfigManager {
|
|
|
264
268
|
|
|
265
269
|
// Log success with detailed information
|
|
266
270
|
if (newConfig) {
|
|
267
|
-
|
|
271
|
+
logger?.debug(
|
|
268
272
|
`Live Config: Configuration loaded successfully from ${loadResult.sourcePath || "merged sources"}`,
|
|
269
273
|
);
|
|
270
274
|
|
|
271
275
|
// Log detailed configuration info
|
|
272
276
|
const hookCount = Object.keys(newConfig.hooks || {}).length;
|
|
273
277
|
const envCount = Object.keys(newConfig.env || {}).length;
|
|
274
|
-
|
|
278
|
+
logger?.debug(
|
|
275
279
|
`Live Config: Loaded ${hookCount} hook events and ${envCount} environment variables`,
|
|
276
280
|
);
|
|
277
281
|
} else {
|
|
278
|
-
|
|
282
|
+
logger?.debug(
|
|
279
283
|
"Live Config: No configuration found (using empty configuration)",
|
|
280
284
|
);
|
|
281
285
|
}
|
|
282
286
|
|
|
283
287
|
// Log warnings from successful loading
|
|
284
288
|
if (loadResult.warnings && loadResult.warnings.length > 0) {
|
|
285
|
-
|
|
289
|
+
logger?.warn(
|
|
286
290
|
`Live Config: Configuration warnings: ${loadResult.warnings.join("; ")}`,
|
|
287
291
|
);
|
|
288
292
|
}
|
|
@@ -292,11 +296,11 @@ export class LiveConfigManager {
|
|
|
292
296
|
const validation = this.validateConfiguration(newConfig);
|
|
293
297
|
if (!validation.valid) {
|
|
294
298
|
const errorMessage = `Configuration validation failed: ${validation.errors.join(", ")}`;
|
|
295
|
-
|
|
299
|
+
logger?.error(`Live Config: ${errorMessage}`);
|
|
296
300
|
|
|
297
301
|
// Use previous valid configuration for error recovery
|
|
298
302
|
if (this.lastValidConfiguration) {
|
|
299
|
-
|
|
303
|
+
logger?.debug(
|
|
300
304
|
"Live Config: Using previous valid configuration due to validation errors",
|
|
301
305
|
);
|
|
302
306
|
this.currentConfiguration = this.lastValidConfiguration;
|
|
@@ -317,7 +321,7 @@ export class LiveConfigManager {
|
|
|
317
321
|
|
|
318
322
|
return this.currentConfiguration;
|
|
319
323
|
} else {
|
|
320
|
-
|
|
324
|
+
logger?.warn(
|
|
321
325
|
"Live Config: No previous valid configuration available, using empty config",
|
|
322
326
|
);
|
|
323
327
|
this.currentConfiguration = {};
|
|
@@ -335,7 +339,7 @@ export class LiveConfigManager {
|
|
|
335
339
|
// Save as last valid configuration if it's valid and not empty
|
|
336
340
|
if (newConfig && (newConfig.hooks || newConfig.env)) {
|
|
337
341
|
this.lastValidConfiguration = { ...newConfig };
|
|
338
|
-
|
|
342
|
+
logger?.debug(
|
|
339
343
|
"Live Config: Saved current configuration as last valid backup",
|
|
340
344
|
);
|
|
341
345
|
}
|
|
@@ -374,18 +378,18 @@ export class LiveConfigManager {
|
|
|
374
378
|
}
|
|
375
379
|
}
|
|
376
380
|
|
|
377
|
-
|
|
381
|
+
logger?.debug(
|
|
378
382
|
`Live Config: Configuration reload completed successfully with ${Object.keys(newConfig?.hooks || {}).length} event types and ${Object.keys(newConfig?.env || {}).length} environment variables`,
|
|
379
383
|
);
|
|
380
384
|
|
|
381
385
|
return this.currentConfiguration;
|
|
382
386
|
} catch (error) {
|
|
383
387
|
const errorMessage = `Configuration reload failed with exception: ${(error as Error).message}`;
|
|
384
|
-
|
|
388
|
+
logger?.error(`Live Config: ${errorMessage}`);
|
|
385
389
|
|
|
386
390
|
// Use previous valid configuration for error recovery
|
|
387
391
|
if (this.lastValidConfiguration) {
|
|
388
|
-
|
|
392
|
+
logger?.debug(
|
|
389
393
|
"Live Config: Using previous valid configuration due to reload exception",
|
|
390
394
|
);
|
|
391
395
|
this.currentConfiguration = this.lastValidConfiguration;
|
|
@@ -404,7 +408,7 @@ export class LiveConfigManager {
|
|
|
404
408
|
);
|
|
405
409
|
}
|
|
406
410
|
} else {
|
|
407
|
-
|
|
411
|
+
logger?.warn(
|
|
408
412
|
"Live Config: No previous valid configuration available, using empty config",
|
|
409
413
|
);
|
|
410
414
|
this.currentConfiguration = {};
|
|
@@ -420,7 +424,7 @@ export class LiveConfigManager {
|
|
|
420
424
|
* Reload configuration from files (public method)
|
|
421
425
|
*/
|
|
422
426
|
async reload(): Promise<WaveConfiguration> {
|
|
423
|
-
|
|
427
|
+
logger?.debug("Manually reloading configuration...");
|
|
424
428
|
return await this.reloadConfiguration();
|
|
425
429
|
}
|
|
426
430
|
|
|
@@ -452,7 +456,7 @@ export class LiveConfigManager {
|
|
|
452
456
|
|
|
453
457
|
private setupFileWatcherEvents(): void {
|
|
454
458
|
this.fileWatcher.on("watcherError", (error: Error) => {
|
|
455
|
-
|
|
459
|
+
logger?.error(`Live Config: File watcher error: ${error.message}`);
|
|
456
460
|
});
|
|
457
461
|
}
|
|
458
462
|
|
|
@@ -460,14 +464,14 @@ export class LiveConfigManager {
|
|
|
460
464
|
event: FileWatchEvent,
|
|
461
465
|
source: Scope,
|
|
462
466
|
): Promise<void> {
|
|
463
|
-
|
|
467
|
+
logger?.debug(
|
|
464
468
|
`Live Config: File ${event.type} detected for ${source} config: ${event.path}`,
|
|
465
469
|
);
|
|
466
470
|
|
|
467
471
|
try {
|
|
468
472
|
// Handle file deletion
|
|
469
473
|
if (event.type === "delete") {
|
|
470
|
-
|
|
474
|
+
logger?.debug(
|
|
471
475
|
`Live Config: ${source} config file deleted: ${event.path}`,
|
|
472
476
|
);
|
|
473
477
|
// Reload configuration without the deleted file
|
|
@@ -477,7 +481,7 @@ export class LiveConfigManager {
|
|
|
477
481
|
|
|
478
482
|
// Handle file creation or modification
|
|
479
483
|
if (event.type === "change" || event.type === "create") {
|
|
480
|
-
|
|
484
|
+
logger?.debug(
|
|
481
485
|
`Live Config: ${source} config file ${event.type}: ${event.path}`,
|
|
482
486
|
);
|
|
483
487
|
|
|
@@ -496,7 +500,7 @@ export class LiveConfigManager {
|
|
|
496
500
|
await this.reloadConfiguration();
|
|
497
501
|
}
|
|
498
502
|
} catch (error) {
|
|
499
|
-
|
|
503
|
+
logger?.error(
|
|
500
504
|
`Live Config: Error handling file change for ${source} config: ${(error as Error).message}`,
|
|
501
505
|
);
|
|
502
506
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ChildProcess, spawn } from "child_process";
|
|
2
2
|
import {
|
|
3
|
-
Logger,
|
|
4
3
|
LspConfig,
|
|
5
4
|
LspServerConfig,
|
|
6
5
|
ILspManager,
|
|
@@ -8,6 +7,7 @@ import {
|
|
|
8
7
|
} from "../types/index.js";
|
|
9
8
|
import { join, isAbsolute, extname } from "path";
|
|
10
9
|
import { promises as fs } from "fs";
|
|
10
|
+
import { Container } from "../utils/container.js";
|
|
11
11
|
|
|
12
12
|
interface LspProcess {
|
|
13
13
|
process: ChildProcess;
|
|
@@ -22,15 +22,14 @@ interface LspProcess {
|
|
|
22
22
|
openedFiles: Set<string>;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
import { logger } from "../utils/globalLogger.js";
|
|
26
|
+
|
|
25
27
|
export class LspManager implements ILspManager {
|
|
26
28
|
private processes: Map<string, LspProcess> = new Map();
|
|
27
29
|
private workdir: string = "";
|
|
28
|
-
private logger?: Logger;
|
|
29
30
|
private config: LspConfig = {};
|
|
30
31
|
|
|
31
|
-
constructor(
|
|
32
|
-
this.logger = options.logger;
|
|
33
|
-
}
|
|
32
|
+
constructor(private container: Container) {}
|
|
34
33
|
|
|
35
34
|
async initialize(workdir: string): Promise<void> {
|
|
36
35
|
this.workdir = workdir;
|
|
@@ -39,7 +38,7 @@ export class LspManager implements ILspManager {
|
|
|
39
38
|
|
|
40
39
|
registerServer(language: string, config: LspServerConfig): void {
|
|
41
40
|
this.config[language] = config;
|
|
42
|
-
|
|
41
|
+
logger?.debug(`Registered LSP server for ${language}`);
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
private async loadConfig(): Promise<void> {
|
|
@@ -48,10 +47,10 @@ export class LspManager implements ILspManager {
|
|
|
48
47
|
const content = await fs.readFile(lspJsonPath, "utf-8");
|
|
49
48
|
const newConfig = JSON.parse(content);
|
|
50
49
|
this.config = { ...this.config, ...newConfig };
|
|
51
|
-
|
|
50
|
+
logger?.debug(`Loaded LSP config from ${lspJsonPath}`);
|
|
52
51
|
} catch (error) {
|
|
53
52
|
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
54
|
-
|
|
53
|
+
logger?.error(`Failed to load .lsp.json: ${error}`);
|
|
55
54
|
}
|
|
56
55
|
}
|
|
57
56
|
}
|
|
@@ -86,7 +85,7 @@ export class LspManager implements ILspManager {
|
|
|
86
85
|
language: string,
|
|
87
86
|
config: LspServerConfig,
|
|
88
87
|
): Promise<LspProcess | null> {
|
|
89
|
-
|
|
88
|
+
logger?.info(
|
|
90
89
|
`Starting LSP server for ${language}: ${config.command} ${config.args?.join(" ") || ""}`,
|
|
91
90
|
);
|
|
92
91
|
|
|
@@ -139,7 +138,7 @@ export class LspManager implements ILspManager {
|
|
|
139
138
|
const message = JSON.parse(content);
|
|
140
139
|
this.handleMessage(lspProc, message);
|
|
141
140
|
} catch (e) {
|
|
142
|
-
|
|
141
|
+
logger?.error(`Failed to parse LSP message: ${e}`);
|
|
143
142
|
}
|
|
144
143
|
} else {
|
|
145
144
|
break;
|
|
@@ -148,13 +147,11 @@ export class LspManager implements ILspManager {
|
|
|
148
147
|
});
|
|
149
148
|
|
|
150
149
|
proc.stderr!.on("data", (data) => {
|
|
151
|
-
|
|
150
|
+
logger?.debug(`LSP [${language}] stderr: ${data}`);
|
|
152
151
|
});
|
|
153
152
|
|
|
154
153
|
proc.on("close", (code) => {
|
|
155
|
-
|
|
156
|
-
`LSP server for ${language} exited with code ${code}`,
|
|
157
|
-
);
|
|
154
|
+
logger?.info(`LSP server for ${language} exited with code ${code}`);
|
|
158
155
|
this.processes.delete(language);
|
|
159
156
|
});
|
|
160
157
|
|
|
@@ -175,9 +172,7 @@ export class LspManager implements ILspManager {
|
|
|
175
172
|
|
|
176
173
|
return lspProc;
|
|
177
174
|
} catch (error) {
|
|
178
|
-
|
|
179
|
-
`Failed to start LSP server for ${language}: ${error}`,
|
|
180
|
-
);
|
|
175
|
+
logger?.error(`Failed to start LSP server for ${language}: ${error}`);
|
|
181
176
|
return null;
|
|
182
177
|
}
|
|
183
178
|
}
|
|
@@ -292,7 +287,7 @@ export class LspManager implements ILspManager {
|
|
|
292
287
|
});
|
|
293
288
|
lspProc.openedFiles.add(absolutePath);
|
|
294
289
|
} catch (error) {
|
|
295
|
-
|
|
290
|
+
logger?.error(`Failed to read file for LSP didOpen: ${error}`);
|
|
296
291
|
}
|
|
297
292
|
}
|
|
298
293
|
|
|
@@ -422,7 +417,7 @@ export class LspManager implements ILspManager {
|
|
|
422
417
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
423
418
|
}
|
|
424
419
|
} catch (error) {
|
|
425
|
-
|
|
420
|
+
logger?.debug(
|
|
426
421
|
`Failed to gracefully shutdown LSP for ${language}: ${error}`,
|
|
427
422
|
);
|
|
428
423
|
} finally {
|
|
@@ -5,6 +5,7 @@ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"
|
|
|
5
5
|
import { ChatCompletionFunctionTool } from "openai/resources.js";
|
|
6
6
|
import { createMcpToolPlugin, findToolServer } from "../utils/mcpUtils.js";
|
|
7
7
|
import type { ToolPlugin, ToolResult, ToolContext } from "../tools/types.js";
|
|
8
|
+
import { Container } from "../utils/container.js";
|
|
8
9
|
import type {
|
|
9
10
|
Logger,
|
|
10
11
|
McpServerConfig,
|
|
@@ -23,6 +24,8 @@ export interface McpManagerCallbacks {
|
|
|
23
24
|
onServersChange?: (servers: McpServerStatus[]) => void;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
import { logger } from "../utils/globalLogger.js";
|
|
28
|
+
|
|
26
29
|
export interface McpManagerOptions {
|
|
27
30
|
callbacks?: McpManagerCallbacks;
|
|
28
31
|
logger?: Logger;
|
|
@@ -35,11 +38,12 @@ export class McpManager {
|
|
|
35
38
|
private configPath: string = "";
|
|
36
39
|
private workdir: string = "";
|
|
37
40
|
private callbacks: McpManagerCallbacks;
|
|
38
|
-
private logger?: Logger;
|
|
39
41
|
|
|
40
|
-
constructor(
|
|
42
|
+
constructor(
|
|
43
|
+
private container: Container,
|
|
44
|
+
options: McpManagerOptions = {},
|
|
45
|
+
) {
|
|
41
46
|
this.callbacks = options.callbacks || {};
|
|
42
|
-
this.logger = options.logger;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
/**
|
|
@@ -53,7 +57,7 @@ export class McpManager {
|
|
|
53
57
|
this.workdir = workdir;
|
|
54
58
|
|
|
55
59
|
if (autoConnect) {
|
|
56
|
-
|
|
60
|
+
logger?.debug("Initializing MCP servers...");
|
|
57
61
|
|
|
58
62
|
// Ensure MCP configuration is loaded
|
|
59
63
|
const config = await this.ensureConfigLoaded();
|
|
@@ -63,21 +67,17 @@ export class McpManager {
|
|
|
63
67
|
const connectionPromises = Object.keys(config.mcpServers).map(
|
|
64
68
|
async (serverName) => {
|
|
65
69
|
try {
|
|
66
|
-
|
|
70
|
+
logger?.debug(`Connecting to MCP server: ${serverName}`);
|
|
67
71
|
const success = await this.connectServer(serverName);
|
|
68
72
|
if (success) {
|
|
69
|
-
|
|
73
|
+
logger?.debug(
|
|
70
74
|
`Successfully connected to MCP server: ${serverName}`,
|
|
71
75
|
);
|
|
72
76
|
} else {
|
|
73
|
-
|
|
74
|
-
`Failed to connect to MCP server: ${serverName}`,
|
|
75
|
-
);
|
|
77
|
+
logger?.warn(`Failed to connect to MCP server: ${serverName}`);
|
|
76
78
|
}
|
|
77
79
|
} catch {
|
|
78
|
-
|
|
79
|
-
`Error connecting to MCP server ${serverName}`,
|
|
80
|
-
);
|
|
80
|
+
logger?.error(`Error connecting to MCP server ${serverName}`);
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
);
|
|
@@ -86,7 +86,7 @@ export class McpManager {
|
|
|
86
86
|
await Promise.all(connectionPromises);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
logger?.debug("MCP servers initialization completed");
|
|
90
90
|
// Trigger state change callback after initialization
|
|
91
91
|
this.callbacks.onServersChange?.(this.getAllServers());
|
|
92
92
|
}
|
|
@@ -101,7 +101,7 @@ export class McpManager {
|
|
|
101
101
|
|
|
102
102
|
async loadConfig(): Promise<McpConfig | null> {
|
|
103
103
|
if (!this.configPath) {
|
|
104
|
-
|
|
104
|
+
logger?.warn("MCP config path not set. Call initialize() first.");
|
|
105
105
|
return null;
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -135,7 +135,7 @@ export class McpManager {
|
|
|
135
135
|
} catch (error) {
|
|
136
136
|
// Only log error if it's not a "file not found" error
|
|
137
137
|
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
138
|
-
|
|
138
|
+
logger?.error("Failed to load .mcp.json:", error);
|
|
139
139
|
}
|
|
140
140
|
return null;
|
|
141
141
|
}
|
|
@@ -147,7 +147,7 @@ export class McpManager {
|
|
|
147
147
|
this.config = config;
|
|
148
148
|
return true;
|
|
149
149
|
} catch (error) {
|
|
150
|
-
|
|
150
|
+
logger?.error("Failed to save .mcp.json:", error);
|
|
151
151
|
return false;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
@@ -247,7 +247,7 @@ export class McpManager {
|
|
|
247
247
|
|
|
248
248
|
// Handle transport errors
|
|
249
249
|
transport.onerror = (error: Error) => {
|
|
250
|
-
|
|
250
|
+
logger?.error(`MCP Server ${name} transport error:`, error);
|
|
251
251
|
this.updateServerStatus(name, {
|
|
252
252
|
status: "error",
|
|
253
253
|
error: error.message,
|
|
@@ -255,7 +255,7 @@ export class McpManager {
|
|
|
255
255
|
};
|
|
256
256
|
|
|
257
257
|
transport.onclose = () => {
|
|
258
|
-
|
|
258
|
+
logger?.debug(`MCP Server ${name} transport closed`);
|
|
259
259
|
this.connections.delete(name);
|
|
260
260
|
this.updateServerStatus(name, {
|
|
261
261
|
status: "disconnected",
|
|
@@ -296,7 +296,7 @@ export class McpManager {
|
|
|
296
296
|
|
|
297
297
|
return true;
|
|
298
298
|
} catch (error) {
|
|
299
|
-
|
|
299
|
+
logger?.error(`Failed to connect to MCP server ${name}:`, error);
|
|
300
300
|
// updateServerStatus will trigger the callback
|
|
301
301
|
this.updateServerStatus(name, {
|
|
302
302
|
status: "error",
|
|
@@ -327,7 +327,7 @@ export class McpManager {
|
|
|
327
327
|
|
|
328
328
|
return true;
|
|
329
329
|
} catch (error) {
|
|
330
|
-
|
|
330
|
+
logger?.error(`Error disconnecting from MCP server ${name}:`, error);
|
|
331
331
|
return false;
|
|
332
332
|
}
|
|
333
333
|
}
|