wave-agent-sdk 0.0.1

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.
Files changed (170) hide show
  1. package/README.md +32 -0
  2. package/dist/agent.d.ts +96 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +286 -0
  5. package/dist/hooks/executor.d.ts +56 -0
  6. package/dist/hooks/executor.d.ts.map +1 -0
  7. package/dist/hooks/executor.js +312 -0
  8. package/dist/hooks/index.d.ts +17 -0
  9. package/dist/hooks/index.d.ts.map +1 -0
  10. package/dist/hooks/index.js +14 -0
  11. package/dist/hooks/manager.d.ts +90 -0
  12. package/dist/hooks/manager.d.ts.map +1 -0
  13. package/dist/hooks/manager.js +395 -0
  14. package/dist/hooks/matcher.d.ts +49 -0
  15. package/dist/hooks/matcher.d.ts.map +1 -0
  16. package/dist/hooks/matcher.js +147 -0
  17. package/dist/hooks/settings.d.ts +46 -0
  18. package/dist/hooks/settings.d.ts.map +1 -0
  19. package/dist/hooks/settings.js +100 -0
  20. package/dist/hooks/types.d.ts +80 -0
  21. package/dist/hooks/types.d.ts.map +1 -0
  22. package/dist/hooks/types.js +59 -0
  23. package/dist/index.d.ts +16 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +20 -0
  26. package/dist/managers/aiManager.d.ts +61 -0
  27. package/dist/managers/aiManager.d.ts.map +1 -0
  28. package/dist/managers/aiManager.js +415 -0
  29. package/dist/managers/backgroundBashManager.d.ts +27 -0
  30. package/dist/managers/backgroundBashManager.d.ts.map +1 -0
  31. package/dist/managers/backgroundBashManager.js +166 -0
  32. package/dist/managers/bashManager.d.ts +20 -0
  33. package/dist/managers/bashManager.d.ts.map +1 -0
  34. package/dist/managers/bashManager.js +66 -0
  35. package/dist/managers/mcpManager.d.ts +63 -0
  36. package/dist/managers/mcpManager.d.ts.map +1 -0
  37. package/dist/managers/mcpManager.js +378 -0
  38. package/dist/managers/messageManager.d.ts +85 -0
  39. package/dist/managers/messageManager.d.ts.map +1 -0
  40. package/dist/managers/messageManager.js +265 -0
  41. package/dist/managers/skillManager.d.ts +59 -0
  42. package/dist/managers/skillManager.d.ts.map +1 -0
  43. package/dist/managers/skillManager.js +317 -0
  44. package/dist/managers/slashCommandManager.d.ts +77 -0
  45. package/dist/managers/slashCommandManager.d.ts.map +1 -0
  46. package/dist/managers/slashCommandManager.js +208 -0
  47. package/dist/managers/toolManager.d.ts +23 -0
  48. package/dist/managers/toolManager.d.ts.map +1 -0
  49. package/dist/managers/toolManager.js +79 -0
  50. package/dist/services/aiService.d.ts +28 -0
  51. package/dist/services/aiService.d.ts.map +1 -0
  52. package/dist/services/aiService.js +180 -0
  53. package/dist/services/memory.d.ts +8 -0
  54. package/dist/services/memory.d.ts.map +1 -0
  55. package/dist/services/memory.js +128 -0
  56. package/dist/services/session.d.ts +54 -0
  57. package/dist/services/session.d.ts.map +1 -0
  58. package/dist/services/session.js +196 -0
  59. package/dist/tools/bashTool.d.ts +14 -0
  60. package/dist/tools/bashTool.d.ts.map +1 -0
  61. package/dist/tools/bashTool.js +351 -0
  62. package/dist/tools/deleteFileTool.d.ts +6 -0
  63. package/dist/tools/deleteFileTool.d.ts.map +1 -0
  64. package/dist/tools/deleteFileTool.js +67 -0
  65. package/dist/tools/editTool.d.ts +6 -0
  66. package/dist/tools/editTool.d.ts.map +1 -0
  67. package/dist/tools/editTool.js +168 -0
  68. package/dist/tools/globTool.d.ts +6 -0
  69. package/dist/tools/globTool.d.ts.map +1 -0
  70. package/dist/tools/globTool.js +113 -0
  71. package/dist/tools/grepTool.d.ts +6 -0
  72. package/dist/tools/grepTool.d.ts.map +1 -0
  73. package/dist/tools/grepTool.js +268 -0
  74. package/dist/tools/lsTool.d.ts +6 -0
  75. package/dist/tools/lsTool.d.ts.map +1 -0
  76. package/dist/tools/lsTool.js +160 -0
  77. package/dist/tools/multiEditTool.d.ts +6 -0
  78. package/dist/tools/multiEditTool.d.ts.map +1 -0
  79. package/dist/tools/multiEditTool.js +222 -0
  80. package/dist/tools/readTool.d.ts +6 -0
  81. package/dist/tools/readTool.d.ts.map +1 -0
  82. package/dist/tools/readTool.js +136 -0
  83. package/dist/tools/types.d.ts +35 -0
  84. package/dist/tools/types.d.ts.map +1 -0
  85. package/dist/tools/types.js +4 -0
  86. package/dist/tools/writeTool.d.ts +6 -0
  87. package/dist/tools/writeTool.d.ts.map +1 -0
  88. package/dist/tools/writeTool.js +138 -0
  89. package/dist/types.d.ts +212 -0
  90. package/dist/types.d.ts.map +1 -0
  91. package/dist/types.js +13 -0
  92. package/dist/utils/bashHistory.d.ts +46 -0
  93. package/dist/utils/bashHistory.d.ts.map +1 -0
  94. package/dist/utils/bashHistory.js +236 -0
  95. package/dist/utils/commandArgumentParser.d.ts +34 -0
  96. package/dist/utils/commandArgumentParser.d.ts.map +1 -0
  97. package/dist/utils/commandArgumentParser.js +123 -0
  98. package/dist/utils/constants.d.ts +27 -0
  99. package/dist/utils/constants.d.ts.map +1 -0
  100. package/dist/utils/constants.js +28 -0
  101. package/dist/utils/convertMessagesForAPI.d.ts +9 -0
  102. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -0
  103. package/dist/utils/convertMessagesForAPI.js +189 -0
  104. package/dist/utils/customCommands.d.ts +14 -0
  105. package/dist/utils/customCommands.d.ts.map +1 -0
  106. package/dist/utils/customCommands.js +71 -0
  107. package/dist/utils/fileFilter.d.ts +26 -0
  108. package/dist/utils/fileFilter.d.ts.map +1 -0
  109. package/dist/utils/fileFilter.js +177 -0
  110. package/dist/utils/markdownParser.d.ts +27 -0
  111. package/dist/utils/markdownParser.d.ts.map +1 -0
  112. package/dist/utils/markdownParser.js +109 -0
  113. package/dist/utils/mcpUtils.d.ts +24 -0
  114. package/dist/utils/mcpUtils.d.ts.map +1 -0
  115. package/dist/utils/mcpUtils.js +51 -0
  116. package/dist/utils/messageOperations.d.ts +118 -0
  117. package/dist/utils/messageOperations.d.ts.map +1 -0
  118. package/dist/utils/messageOperations.js +334 -0
  119. package/dist/utils/path.d.ts +25 -0
  120. package/dist/utils/path.d.ts.map +1 -0
  121. package/dist/utils/path.js +109 -0
  122. package/dist/utils/skillParser.d.ts +18 -0
  123. package/dist/utils/skillParser.d.ts.map +1 -0
  124. package/dist/utils/skillParser.js +147 -0
  125. package/dist/utils/stringUtils.d.ts +13 -0
  126. package/dist/utils/stringUtils.d.ts.map +1 -0
  127. package/dist/utils/stringUtils.js +44 -0
  128. package/package.json +51 -0
  129. package/src/agent.ts +405 -0
  130. package/src/hooks/executor.ts +440 -0
  131. package/src/hooks/index.ts +52 -0
  132. package/src/hooks/manager.ts +618 -0
  133. package/src/hooks/matcher.ts +187 -0
  134. package/src/hooks/settings.ts +129 -0
  135. package/src/hooks/types.ts +169 -0
  136. package/src/index.ts +24 -0
  137. package/src/managers/aiManager.ts +573 -0
  138. package/src/managers/backgroundBashManager.ts +203 -0
  139. package/src/managers/bashManager.ts +97 -0
  140. package/src/managers/mcpManager.ts +493 -0
  141. package/src/managers/messageManager.ts +415 -0
  142. package/src/managers/skillManager.ts +404 -0
  143. package/src/managers/slashCommandManager.ts +293 -0
  144. package/src/managers/toolManager.ts +106 -0
  145. package/src/services/aiService.ts +252 -0
  146. package/src/services/memory.ts +149 -0
  147. package/src/services/session.ts +265 -0
  148. package/src/tools/bashTool.ts +402 -0
  149. package/src/tools/deleteFileTool.ts +81 -0
  150. package/src/tools/editTool.ts +192 -0
  151. package/src/tools/globTool.ts +135 -0
  152. package/src/tools/grepTool.ts +326 -0
  153. package/src/tools/lsTool.ts +187 -0
  154. package/src/tools/multiEditTool.ts +268 -0
  155. package/src/tools/readTool.ts +165 -0
  156. package/src/tools/types.ts +47 -0
  157. package/src/tools/writeTool.ts +163 -0
  158. package/src/types.ts +260 -0
  159. package/src/utils/bashHistory.ts +303 -0
  160. package/src/utils/commandArgumentParser.ts +153 -0
  161. package/src/utils/constants.ts +37 -0
  162. package/src/utils/convertMessagesForAPI.ts +236 -0
  163. package/src/utils/customCommands.ts +85 -0
  164. package/src/utils/fileFilter.ts +202 -0
  165. package/src/utils/markdownParser.ts +156 -0
  166. package/src/utils/mcpUtils.ts +81 -0
  167. package/src/utils/messageOperations.ts +506 -0
  168. package/src/utils/path.ts +118 -0
  169. package/src/utils/skillParser.ts +188 -0
  170. package/src/utils/stringUtils.ts +50 -0
@@ -0,0 +1,66 @@
1
+ import { spawn } from "child_process";
2
+ import { addBashCommandToHistory } from "../utils/bashHistory.js";
3
+ export class BashManager {
4
+ constructor(options) {
5
+ this.isCommandRunning = false;
6
+ this.currentProcess = null;
7
+ this.workdir = options.workdir;
8
+ this.messageManager = options.messageManager;
9
+ }
10
+ setCommandRunning(isRunning) {
11
+ this.isCommandRunning = isRunning;
12
+ }
13
+ async executeCommand(command) {
14
+ if (this.isCommandRunning) {
15
+ throw new Error("Command already running");
16
+ }
17
+ this.setCommandRunning(true);
18
+ // Add command output placeholder
19
+ this.messageManager.addCommandOutputMessage(command);
20
+ return new Promise((resolve) => {
21
+ const child = spawn(command, {
22
+ shell: true,
23
+ stdio: "pipe",
24
+ cwd: this.workdir,
25
+ env: {
26
+ ...process.env,
27
+ },
28
+ });
29
+ this.currentProcess = child;
30
+ let outputBuffer = "";
31
+ const updateOutput = (newData) => {
32
+ outputBuffer += newData;
33
+ this.messageManager.updateCommandOutputMessage(command, outputBuffer);
34
+ };
35
+ child.stdout?.on("data", (data) => {
36
+ updateOutput(data.toString());
37
+ });
38
+ child.stderr?.on("data", (data) => {
39
+ updateOutput(data.toString());
40
+ });
41
+ child.on("exit", (code, signal) => {
42
+ const exitCode = code === null && signal ? 130 : (code ?? 0);
43
+ // Add command to bash history
44
+ addBashCommandToHistory(command, this.workdir);
45
+ this.messageManager.completeCommandMessage(command, exitCode);
46
+ this.setCommandRunning(false);
47
+ this.currentProcess = null;
48
+ resolve(exitCode);
49
+ });
50
+ child.on("error", (error) => {
51
+ updateOutput(`\nError: ${error.message}\n`);
52
+ this.messageManager.completeCommandMessage(command, 1);
53
+ this.setCommandRunning(false);
54
+ this.currentProcess = null;
55
+ resolve(1);
56
+ });
57
+ });
58
+ }
59
+ abortCommand() {
60
+ if (this.currentProcess && this.isCommandRunning) {
61
+ this.currentProcess.kill("SIGKILL");
62
+ this.currentProcess = null;
63
+ this.isCommandRunning = false;
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,63 @@
1
+ import { ChatCompletionFunctionTool } from "openai/resources.js";
2
+ import type { ToolPlugin, ToolResult, ToolContext } from "../tools/types.js";
3
+ import type { Logger, McpServerConfig, McpConfig, McpTool, McpServerStatus } from "../types.js";
4
+ export interface McpManagerCallbacks {
5
+ onServersChange?: (servers: McpServerStatus[]) => void;
6
+ }
7
+ export interface McpManagerOptions {
8
+ callbacks?: McpManagerCallbacks;
9
+ logger?: Logger;
10
+ }
11
+ export declare class McpManager {
12
+ private config;
13
+ private servers;
14
+ private connections;
15
+ private configPath;
16
+ private workdir;
17
+ private callbacks;
18
+ private logger?;
19
+ constructor(options?: McpManagerOptions);
20
+ /**
21
+ * Initialize MCP manager with working directory and optionally auto-connect
22
+ */
23
+ initialize(workdir: string, autoConnect?: boolean): Promise<void>;
24
+ ensureConfigLoaded(): Promise<McpConfig | null>;
25
+ loadConfig(): Promise<McpConfig | null>;
26
+ saveConfig(config: McpConfig): Promise<boolean>;
27
+ getConfig(): McpConfig | null;
28
+ getAllServers(): McpServerStatus[];
29
+ getServer(name: string): McpServerStatus | undefined;
30
+ updateServerStatus(name: string, updates: Partial<McpServerStatus>): void;
31
+ addServer(name: string, config: McpServerConfig): boolean;
32
+ removeServer(name: string): boolean;
33
+ connectServer(name: string): Promise<boolean>;
34
+ disconnectServer(name: string): Promise<boolean>;
35
+ getAllConnectedTools(): McpTool[];
36
+ executeMcpTool(toolName: string, args: Record<string, unknown>): Promise<{
37
+ success: boolean;
38
+ content: string;
39
+ serverName?: string;
40
+ images?: Array<{
41
+ data: string;
42
+ mediaType?: string;
43
+ }>;
44
+ }>;
45
+ cleanup(): Promise<void>;
46
+ /**
47
+ * Get all currently available MCP tools as plugins
48
+ */
49
+ getMcpToolPlugins(): ToolPlugin[];
50
+ /**
51
+ * Get all currently available MCP tools as OpenAI function tools
52
+ */
53
+ getMcpToolsConfig(): ChatCompletionFunctionTool[];
54
+ /**
55
+ * Execute an MCP tool by name (registry version)
56
+ */
57
+ executeMcpToolByRegistry(name: string, args: Record<string, unknown>, context: ToolContext): Promise<ToolResult>;
58
+ /**
59
+ * Check if a tool name belongs to an MCP tool
60
+ */
61
+ isMcpTool(name: string): boolean;
62
+ }
63
+ //# sourceMappingURL=mcpManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpManager.d.ts","sourceRoot":"","sources":["../../src/managers/mcpManager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,SAAS,EACT,OAAO,EACP,eAAe,EAChB,MAAM,aAAa,CAAC;AAQrB,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,OAAO,GAAE,iBAAsB;IAK3C;;OAEG;IACG,UAAU,CACd,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,OAAe,GAC3B,OAAO,CAAC,IAAI,CAAC;IA4CV,kBAAkB,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAO/C,UAAU,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA0CvC,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrD,SAAS,IAAI,SAAS,GAAG,IAAI;IAI7B,aAAa,IAAI,eAAe,EAAE;IAIlC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIpD,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IASzE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO;IAyBzD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAgB7B,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA4F7C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BtD,oBAAoB,IAAI,OAAO,EAAE;IAW3B,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACtD,CAAC;IAoEI,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACH,iBAAiB,IAAI,UAAU,EAAE;IAuBjC;;OAEG;IACH,iBAAiB,IAAI,0BAA0B,EAAE;IAIjD;;OAEG;IACG,wBAAwB,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC;IActB;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAIjC"}
@@ -0,0 +1,378 @@
1
+ import { promises as fs } from "fs";
2
+ import { join } from "path";
3
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
5
+ import { createMcpToolPlugin, findToolServer } from "../utils/mcpUtils.js";
6
+ export class McpManager {
7
+ constructor(options = {}) {
8
+ this.config = null;
9
+ this.servers = new Map();
10
+ this.connections = new Map();
11
+ this.configPath = "";
12
+ this.workdir = "";
13
+ this.callbacks = options.callbacks || {};
14
+ this.logger = options.logger;
15
+ }
16
+ /**
17
+ * Initialize MCP manager with working directory and optionally auto-connect
18
+ */
19
+ async initialize(workdir, autoConnect = false) {
20
+ this.configPath = join(workdir, ".mcp.json");
21
+ this.workdir = workdir;
22
+ if (autoConnect) {
23
+ this.logger?.info("Initializing MCP servers...");
24
+ // Ensure MCP configuration is loaded
25
+ const config = await this.ensureConfigLoaded();
26
+ if (config && config.mcpServers) {
27
+ // Connect to all configured servers
28
+ const connectionPromises = Object.keys(config.mcpServers).map(async (serverName) => {
29
+ try {
30
+ this.logger?.info(`Connecting to MCP server: ${serverName}`);
31
+ const success = await this.connectServer(serverName);
32
+ if (success) {
33
+ this.logger?.info(`Successfully connected to MCP server: ${serverName}`);
34
+ }
35
+ else {
36
+ this.logger?.warn(`Failed to connect to MCP server: ${serverName}`);
37
+ }
38
+ }
39
+ catch {
40
+ this.logger?.error(`Error connecting to MCP server ${serverName}`);
41
+ }
42
+ });
43
+ // Wait for all connection attempts to complete
44
+ await Promise.all(connectionPromises);
45
+ }
46
+ this.logger?.info("MCP servers initialization completed");
47
+ // Trigger state change callback after initialization
48
+ this.callbacks.onServersChange?.(this.getAllServers());
49
+ }
50
+ }
51
+ async ensureConfigLoaded() {
52
+ if (!this.config) {
53
+ return this.loadConfig();
54
+ }
55
+ return this.config;
56
+ }
57
+ async loadConfig() {
58
+ if (!this.configPath) {
59
+ this.logger?.warn("MCP config path not set. Call initialize() first.");
60
+ return null;
61
+ }
62
+ try {
63
+ const configContent = await fs.readFile(this.configPath, "utf-8");
64
+ this.config = JSON.parse(configContent);
65
+ // Initialize server statuses (preserve existing status for already known servers)
66
+ if (this.config) {
67
+ for (const [name, config] of Object.entries(this.config.mcpServers)) {
68
+ const existingServer = this.servers.get(name);
69
+ if (existingServer) {
70
+ // Update config but preserve status and other runtime info
71
+ this.servers.set(name, {
72
+ ...existingServer,
73
+ config, // Update config in case it changed
74
+ });
75
+ }
76
+ else {
77
+ // New server, initialize with disconnected status
78
+ this.servers.set(name, {
79
+ name,
80
+ config,
81
+ status: "disconnected",
82
+ });
83
+ }
84
+ }
85
+ }
86
+ return this.config;
87
+ }
88
+ catch (error) {
89
+ // Only log error if it's not a "file not found" error
90
+ if (error.code !== "ENOENT") {
91
+ this.logger?.error("Failed to load .mcp.json:", error);
92
+ }
93
+ return null;
94
+ }
95
+ }
96
+ async saveConfig(config) {
97
+ try {
98
+ await fs.writeFile(this.configPath, JSON.stringify(config, null, 2));
99
+ this.config = config;
100
+ return true;
101
+ }
102
+ catch (error) {
103
+ this.logger?.error("Failed to save .mcp.json:", error);
104
+ return false;
105
+ }
106
+ }
107
+ getConfig() {
108
+ return this.config;
109
+ }
110
+ getAllServers() {
111
+ return Array.from(this.servers.values());
112
+ }
113
+ getServer(name) {
114
+ return this.servers.get(name);
115
+ }
116
+ updateServerStatus(name, updates) {
117
+ const server = this.servers.get(name);
118
+ if (server) {
119
+ this.servers.set(name, { ...server, ...updates });
120
+ // Trigger state change callback
121
+ this.callbacks.onServersChange?.(this.getAllServers());
122
+ }
123
+ }
124
+ addServer(name, config) {
125
+ if (this.servers.has(name)) {
126
+ return false;
127
+ }
128
+ const newServer = {
129
+ name,
130
+ config,
131
+ status: "disconnected",
132
+ };
133
+ this.servers.set(name, newServer);
134
+ // Update config
135
+ if (this.config) {
136
+ this.config.mcpServers[name] = config;
137
+ }
138
+ else {
139
+ this.config = {
140
+ mcpServers: { [name]: config },
141
+ };
142
+ }
143
+ return true;
144
+ }
145
+ removeServer(name) {
146
+ // Disconnect if connected
147
+ if (this.connections.has(name)) {
148
+ this.disconnectServer(name);
149
+ }
150
+ const removed = this.servers.delete(name);
151
+ if (removed && this.config) {
152
+ delete this.config.mcpServers[name];
153
+ }
154
+ return removed;
155
+ }
156
+ // Real MCP connection implementation
157
+ async connectServer(name) {
158
+ const server = this.servers.get(name);
159
+ if (!server)
160
+ return false;
161
+ // Already connected
162
+ if (this.connections.has(name))
163
+ return true;
164
+ this.updateServerStatus(name, { status: "connecting" });
165
+ try {
166
+ // Create transport - it will manage the process
167
+ const transport = new StdioClientTransport({
168
+ command: server.config.command,
169
+ args: server.config.args || [],
170
+ env: server.config.env || {},
171
+ cwd: this.workdir, // Use the agent's workdir as the process working directory
172
+ });
173
+ // Create client
174
+ const client = new Client({
175
+ name: "wave-code",
176
+ version: "1.0.0",
177
+ }, {
178
+ capabilities: {
179
+ tools: {},
180
+ },
181
+ });
182
+ // Handle transport errors
183
+ transport.onerror = (error) => {
184
+ this.logger?.error(`MCP Server ${name} transport error:`, error);
185
+ this.updateServerStatus(name, {
186
+ status: "error",
187
+ error: error.message,
188
+ });
189
+ };
190
+ transport.onclose = () => {
191
+ this.logger?.info(`MCP Server ${name} transport closed`);
192
+ this.connections.delete(name);
193
+ this.updateServerStatus(name, {
194
+ status: "disconnected",
195
+ tools: [],
196
+ toolCount: 0,
197
+ });
198
+ };
199
+ // Connect to transport
200
+ await client.connect(transport);
201
+ // List available tools
202
+ const toolsResponse = await client.listTools();
203
+ const tools = toolsResponse.tools?.map((tool) => ({
204
+ name: tool.name,
205
+ description: tool.description,
206
+ inputSchema: tool.inputSchema,
207
+ })) || [];
208
+ // Store connection (we don't have direct process access with StdioClientTransport)
209
+ this.connections.set(name, {
210
+ client,
211
+ transport,
212
+ process: null, // StdioClientTransport manages the process internally
213
+ });
214
+ // Update status
215
+ this.updateServerStatus(name, {
216
+ status: "connected",
217
+ tools,
218
+ toolCount: tools.length,
219
+ capabilities: ["tools"],
220
+ lastConnected: Date.now(),
221
+ error: undefined,
222
+ });
223
+ return true;
224
+ }
225
+ catch (error) {
226
+ this.logger?.error(`Failed to connect to MCP server ${name}:`, error);
227
+ // updateServerStatus will trigger the callback
228
+ this.updateServerStatus(name, {
229
+ status: "error",
230
+ error: error instanceof Error ? error.message : String(error),
231
+ });
232
+ return false;
233
+ }
234
+ }
235
+ async disconnectServer(name) {
236
+ const connection = this.connections.get(name);
237
+ if (!connection)
238
+ return false;
239
+ try {
240
+ // Close client connection and transport
241
+ await connection.client.close();
242
+ await connection.transport.close();
243
+ // Remove connection
244
+ this.connections.delete(name);
245
+ // updateServerStatus will trigger the callback
246
+ this.updateServerStatus(name, {
247
+ status: "disconnected",
248
+ tools: [],
249
+ toolCount: 0,
250
+ });
251
+ return true;
252
+ }
253
+ catch (error) {
254
+ this.logger?.error(`Error disconnecting from MCP server ${name}:`, error);
255
+ return false;
256
+ }
257
+ }
258
+ // Get all tools from connected servers
259
+ getAllConnectedTools() {
260
+ const allTools = [];
261
+ for (const server of this.servers.values()) {
262
+ if (server.status === "connected" && server.tools) {
263
+ allTools.push(...server.tools);
264
+ }
265
+ }
266
+ return allTools;
267
+ }
268
+ // Execute MCP tool
269
+ async executeMcpTool(toolName, args) {
270
+ // Find which server has this tool
271
+ for (const [serverName, server] of this.servers.entries()) {
272
+ if (server.status === "connected" && server.tools) {
273
+ const tool = server.tools.find((t) => t.name === toolName);
274
+ if (tool) {
275
+ const connection = this.connections.get(serverName);
276
+ if (connection) {
277
+ try {
278
+ const result = await connection.client.callTool({
279
+ name: toolName,
280
+ arguments: args,
281
+ });
282
+ // Separate text content and image data
283
+ const textContent = [];
284
+ const images = [];
285
+ if (Array.isArray(result.content)) {
286
+ result.content.forEach((c) => {
287
+ if (c.type === "text") {
288
+ textContent.push(c.text || "");
289
+ }
290
+ else if (c.type === "image" && c.data) {
291
+ images.push({
292
+ data: c.data,
293
+ mediaType: "image/png", // Default to PNG, can be adjusted according to actual situation
294
+ });
295
+ }
296
+ else if (c.type === "resource") {
297
+ textContent.push(`[Resource: ${c.resource?.uri || ""}]`);
298
+ }
299
+ else {
300
+ textContent.push(JSON.stringify(c));
301
+ }
302
+ });
303
+ }
304
+ else if (result.content) {
305
+ textContent.push(String(result.content));
306
+ }
307
+ return {
308
+ success: true,
309
+ content: textContent.length > 0
310
+ ? textContent.join("\n")
311
+ : "No content",
312
+ images: images.length > 0 ? images : undefined,
313
+ serverName,
314
+ };
315
+ }
316
+ catch (error) {
317
+ throw new Error(`Tool execution failed: ${error instanceof Error ? error.message : String(error)}`);
318
+ }
319
+ }
320
+ }
321
+ }
322
+ }
323
+ throw new Error(`Tool ${toolName} not found on any connected MCP server`);
324
+ }
325
+ // Cleanup all connections
326
+ async cleanup() {
327
+ const disconnectPromises = Array.from(this.connections.keys()).map((name) => this.disconnectServer(name));
328
+ await Promise.all(disconnectPromises);
329
+ }
330
+ // ========== Tools Registry Methods ==========
331
+ /**
332
+ * Get all currently available MCP tools as plugins
333
+ */
334
+ getMcpToolPlugins() {
335
+ const mcpTools = new Map();
336
+ // Get all connected MCP tools
337
+ const connectedTools = this.getAllConnectedTools();
338
+ const servers = this.getAllServers();
339
+ // Find server name for each tool and create plugins
340
+ for (const tool of connectedTools) {
341
+ // Find which server this tool belongs to
342
+ const server = findToolServer(tool.name, servers);
343
+ if (server) {
344
+ const plugin = createMcpToolPlugin(tool, server.name, (name, args) => this.executeMcpTool(name, args));
345
+ mcpTools.set(tool.name, plugin);
346
+ }
347
+ }
348
+ return Array.from(mcpTools.values());
349
+ }
350
+ /**
351
+ * Get all currently available MCP tools as OpenAI function tools
352
+ */
353
+ getMcpToolsConfig() {
354
+ return this.getMcpToolPlugins().map((tool) => tool.config);
355
+ }
356
+ /**
357
+ * Execute an MCP tool by name (registry version)
358
+ */
359
+ async executeMcpToolByRegistry(name, args, context) {
360
+ const plugins = this.getMcpToolPlugins();
361
+ const tool = plugins.find((plugin) => plugin.name === name);
362
+ if (!tool) {
363
+ return {
364
+ success: false,
365
+ content: "",
366
+ error: `MCP tool '${name}' not found or server disconnected`,
367
+ };
368
+ }
369
+ return tool.execute(args, context);
370
+ }
371
+ /**
372
+ * Check if a tool name belongs to an MCP tool
373
+ */
374
+ isMcpTool(name) {
375
+ const connectedTools = this.getAllConnectedTools();
376
+ return connectedTools.some((tool) => tool.name === name);
377
+ }
378
+ }
@@ -0,0 +1,85 @@
1
+ import { type AgentToolBlockUpdateParams } from "../utils/messageOperations.js";
2
+ import type { Logger, Message } from "../types.js";
3
+ import { ChatCompletionMessageFunctionToolCall } from "openai/resources.js";
4
+ export interface MessageManagerCallbacks {
5
+ onMessagesChange?: (messages: Message[]) => void;
6
+ onSessionIdChange?: (sessionId: string) => void;
7
+ onLatestTotalTokensChange?: (latestTotalTokens: number) => void;
8
+ onUserInputHistoryChange?: (history: string[]) => void;
9
+ onUserMessageAdded?: (content: string, images?: Array<{
10
+ path: string;
11
+ mimeType: string;
12
+ }>) => void;
13
+ onAssistantMessageAdded?: (content?: string, toolCalls?: ChatCompletionMessageFunctionToolCall[]) => void;
14
+ onToolBlockUpdated?: (params: AgentToolBlockUpdateParams) => void;
15
+ onDiffBlockAdded?: (filePath: string, diffResult: string) => void;
16
+ onErrorBlockAdded?: (error: string) => void;
17
+ onCompressBlockAdded?: (insertIndex: number, content: string) => void;
18
+ onCompressionStateChange?: (isCompressing: boolean) => void;
19
+ onMemoryBlockAdded?: (content: string, success: boolean, type: "project" | "user", storagePath: string) => void;
20
+ onAddCommandOutputMessage?: (command: string) => void;
21
+ onUpdateCommandOutputMessage?: (command: string, output: string) => void;
22
+ onCompleteCommandMessage?: (command: string, exitCode: number) => void;
23
+ }
24
+ export interface MessageManagerOptions {
25
+ callbacks: MessageManagerCallbacks;
26
+ workdir: string;
27
+ logger?: Logger;
28
+ }
29
+ export declare class MessageManager {
30
+ private sessionId;
31
+ private messages;
32
+ private latestTotalTokens;
33
+ private userInputHistory;
34
+ private sessionStartTime;
35
+ private workdir;
36
+ private logger?;
37
+ private callbacks;
38
+ constructor(options: MessageManagerOptions);
39
+ getSessionId(): string;
40
+ getMessages(): Message[];
41
+ getlatestTotalTokens(): number;
42
+ getUserInputHistory(): string[];
43
+ getTranscriptPath(): string;
44
+ setSessionId(sessionId: string): void;
45
+ setMessages(messages: Message[]): void;
46
+ /**
47
+ * Save current session
48
+ */
49
+ saveSession(): Promise<void>;
50
+ /**
51
+ * Handle session restoration logic
52
+ */
53
+ handleSessionRestoration(restoreSessionId?: string, continueLastSession?: boolean): Promise<void>;
54
+ setlatestTotalTokens(latestTotalTokens: number): void;
55
+ setUserInputHistory(userInputHistory: string[]): void;
56
+ /**
57
+ * Clear messages and input history
58
+ */
59
+ clearMessages(): void;
60
+ initializeFromSession(sessionId: string, messages: Message[], latestTotalTokens: number): void;
61
+ addToInputHistory(input: string): void;
62
+ clearInputHistory(): void;
63
+ addUserMessage(content: string, images?: Array<{
64
+ path: string;
65
+ mimeType: string;
66
+ }>): void;
67
+ addCustomCommandMessage(commandName: string, content: string, originalInput?: string): void;
68
+ addAssistantMessage(content?: string, toolCalls?: ChatCompletionMessageFunctionToolCall[]): void;
69
+ updateToolBlock(params: AgentToolBlockUpdateParams): void;
70
+ addDiffBlock(filePath: string, diffResult: Array<{
71
+ value: string;
72
+ added?: boolean;
73
+ removed?: boolean;
74
+ }>): void;
75
+ addErrorBlock(error: string): void;
76
+ /**
77
+ * Compress messages and update session, delete compressed messages, only keep compressed messages and subsequent messages
78
+ */
79
+ compressMessagesAndUpdateSession(insertIndex: number, compressedContent: string): void;
80
+ addMemoryBlock(content: string, success: boolean, type: "project" | "user", storagePath: string): void;
81
+ addCommandOutputMessage(command: string): void;
82
+ updateCommandOutputMessage(command: string, output: string): void;
83
+ completeCommandMessage(command: string, exitCode: number): void;
84
+ }
85
+ //# sourceMappingURL=messageManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messageManager.d.ts","sourceRoot":"","sources":["../../src/managers/messageManager.ts"],"names":[],"mappings":"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"}