wave-agent-sdk 0.11.4 → 0.11.6

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.
@@ -16,7 +16,7 @@ export class BackgroundTaskManager {
16
16
  this.callbacks.onBackgroundTasksChange?.(Array.from(this.tasks.values()));
17
17
  }
18
18
  generateId() {
19
- return `task_${this.nextId++}`;
19
+ return `task_${process.pid}_${this.nextId++}`;
20
20
  }
21
21
  addTask(task) {
22
22
  this.tasks.set(task.id, task);
@@ -41,7 +41,7 @@ export class BackgroundTaskManager {
41
41
  });
42
42
  // Create log file
43
43
  const logPath = path.join(os.tmpdir(), `wave-task-${id}.log`);
44
- const logStream = fs.createWriteStream(logPath, { flags: "a" });
44
+ const logStream = fs.createWriteStream(logPath, { flags: "w" });
45
45
  const shell = {
46
46
  id,
47
47
  type: "shell",
@@ -156,7 +156,7 @@ export class BackgroundTaskManager {
156
156
  const startTime = Date.now();
157
157
  // Create log file
158
158
  const logPath = path.join(os.tmpdir(), `wave-task-${id}.log`);
159
- const logStream = fs.createWriteStream(logPath, { flags: "a" });
159
+ const logStream = fs.createWriteStream(logPath, { flags: "w" });
160
160
  // Write initial output to log file
161
161
  if (initialStdout) {
162
162
  logStream.write(stripAnsiColors(initialStdout));
@@ -1 +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,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,SAAS,EACT,OAAO,EACP,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAQ3B,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;CACxD;AAID,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,UAAU;IASnB,OAAO,CAAC,SAAS;IARnB,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;gBAG7B,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,iBAAsB;IAKjC;;OAEG;IACG,UAAU,CACd,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,OAAe,GAC3B,OAAO,CAAC,IAAI,CAAC;IAwCV,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,EAC7B,OAAO,CAAC,EAAE,WAAW,GACpB,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;YAsDY,uBAAuB;IA8D/B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACH,iBAAiB,IAAI,UAAU,EAAE;IA6BjC;;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;CAcjC"}
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,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,SAAS,EACT,OAAO,EACP,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAQ3B,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;CACxD;AAID,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,UAAU;IASnB,OAAO,CAAC,SAAS;IARnB,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;gBAG7B,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,iBAAsB;IAKjC;;OAEG;IACG,UAAU,CACd,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,OAAe,GAC3B,OAAO,CAAC,IAAI,CAAC;IAuCV,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;IAqH7C,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,EAC7B,OAAO,CAAC,EAAE,WAAW,GACpB,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;YAsDY,uBAAuB;IA8D/B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACH,iBAAiB,IAAI,UAAU,EAAE;IA6BjC;;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;CAcjC"}
@@ -25,27 +25,25 @@ export class McpManager {
25
25
  // Ensure MCP configuration is loaded
26
26
  const config = await this.ensureConfigLoaded();
27
27
  if (config && config.mcpServers) {
28
- // Connect to all configured servers
29
- const connectionPromises = Object.keys(config.mcpServers).map(async (serverName) => {
30
- try {
31
- logger?.debug(`Connecting to MCP server: ${serverName}`);
32
- const success = await this.connectServer(serverName);
28
+ // Connect to all configured servers in background to avoid blocking agent initialization
29
+ Object.keys(config.mcpServers).forEach((serverName) => {
30
+ logger?.debug(`Connecting to MCP server: ${serverName}`);
31
+ this.connectServer(serverName)
32
+ .then((success) => {
33
33
  if (success) {
34
34
  logger?.debug(`Successfully connected to MCP server: ${serverName}`);
35
35
  }
36
36
  else {
37
37
  logger?.warn(`Failed to connect to MCP server: ${serverName}`);
38
38
  }
39
- }
40
- catch {
41
- logger?.error(`Error connecting to MCP server ${serverName}`);
42
- }
39
+ })
40
+ .catch((error) => {
41
+ logger?.error(`Background connection to MCP server ${serverName} failed:`, error);
42
+ });
43
43
  });
44
- // Wait for all connection attempts to complete
45
- await Promise.all(connectionPromises);
46
44
  }
47
- logger?.debug("MCP servers initialization completed");
48
- // Trigger state change callback after initialization
45
+ logger?.debug("MCP servers initialization started in background");
46
+ // Trigger state change callback after starting initialization
49
47
  this.callbacks.onServersChange?.(this.getAllServers());
50
48
  }
51
49
  }
@@ -168,9 +166,33 @@ export class McpManager {
168
166
  const transport = new StdioClientTransport({
169
167
  command: server.config.command,
170
168
  args: server.config.args || [],
171
- env: server.config.env || {},
169
+ env: {
170
+ ...process.env,
171
+ ...(server.config.env || {}),
172
+ },
172
173
  cwd: this.workdir, // Use the agent's workdir as the process working directory
174
+ stderr: "pipe", // Pipe stderr to capture it
173
175
  });
176
+ // Handle stderr output
177
+ const stderr = transport.stderr;
178
+ if (stderr) {
179
+ let buffer = "";
180
+ stderr.on("data", (chunk) => {
181
+ buffer += chunk.toString();
182
+ const lines = buffer.split("\n");
183
+ buffer = lines.pop() || "";
184
+ for (const line of lines) {
185
+ if (line.trim()) {
186
+ logger?.error(`[MCP Server ${name}] ${line}`);
187
+ }
188
+ }
189
+ });
190
+ stderr.on("end", () => {
191
+ if (buffer.trim()) {
192
+ logger?.error(`[MCP Server ${name}] ${buffer}`);
193
+ }
194
+ });
195
+ }
174
196
  // Create client
175
197
  const client = new Client({
176
198
  name: "wave-code",
@@ -1 +1 @@
1
- {"version":3,"file":"permissionManager.d.ts","sourceRoot":"","sources":["../../src/managers/permissionManager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAgBhD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AA4DlD,MAAM,WAAW,wBAAwB;IACvC,+CAA+C;IAC/C,wBAAwB,CAAC,EAAE,cAAc,CAAC;IAC1C,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,0DAA0D;IAC1D,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,yDAAyD;IACzD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,8DAA8D;IAC9D,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,iBAAiB;IAiB1B,OAAO,CAAC,SAAS;IAhBnB,OAAO,CAAC,wBAAwB,CAAC,CAAiB;IAClD,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,oBAAoB,CAAgB;IAC5C,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,qBAAqB,CAAgB;IAC7C,OAAO,CAAC,2BAA2B,CAAgB;IACnD,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,gCAAgC,CAAC,CAAiC;IAC1E,OAAO,CAAC,OAAO,CAAC,CAAS;gBAGf,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,wBAA6B;IAgBxC;;OAEG;IACI,mCAAmC,CACxC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,GACvC,IAAI;IAIP;;OAEG;IACH,8BAA8B,CAAC,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI;IAcrE;;OAEG;IACI,2BAA2B,IAAI,cAAc,GAAG,SAAS;IAIhE;;OAEG;IACI,eAAe,IAAI,MAAM,EAAE;IAIlC;;OAEG;IACI,cAAc,IAAI,MAAM,EAAE;IAIjC;;OAEG;IACI,uBAAuB,IAAI,MAAM,EAAE;IAI1C;;OAEG;IACI,sBAAsB,IAAI,MAAM,EAAE;IAIzC;;OAEG;IACI,wBAAwB,IAAI,MAAM,EAAE;IAI3C;;OAEG;IACI,sBAAsB,IAAI,MAAM,EAAE;IAIzC;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIzC;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIxC;;OAEG;IACI,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAI/C;;OAEG;IACI,mBAAmB,IAAI,IAAI;IAIlC;;OAEG;IACH,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI;IASxD;;OAEG;IACI,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAW5D;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIpC;;OAEG;IACI,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAItD;;OAEG;IACI,eAAe,IAAI,MAAM,GAAG,SAAS;IAI5C;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkCxB;;OAEG;IACH,uBAAuB,CAAC,iBAAiB,CAAC,EAAE,cAAc,GAAG,cAAc;IAI3E;;OAEG;IACH,8BAA8B,CAC5B,iBAAiB,CAAC,EAAE,cAAc,GACjC,cAAc;IAejB;;;OAGG;IACG,eAAe,CACnB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,kBAAkB,CAAC;IAsN9B;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAO3C;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAc9C;;OAEG;IACH,aAAa,CACX,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,QAAQ,CAAC,EAAE,kBAAkB,EAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,qBAAqB;IAoFxB;;OAEG;IACH,OAAO,CAAC,WAAW;IA0EnB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiHvB;;;;;;;OAOG;IACI,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IA8FjE;;;OAGG;IACU,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CA4C5D"}
1
+ {"version":3,"file":"permissionManager.d.ts","sourceRoot":"","sources":["../../src/managers/permissionManager.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@
8
8
  import path from "node:path";
9
9
  import { minimatch } from "minimatch";
10
10
  import { RESTRICTED_TOOLS } from "../types/permissions.js";
11
- import { splitBashCommand, stripEnvVars, stripRedirections, hasWriteRedirections, getSmartPrefix, DANGEROUS_COMMANDS, } from "../utils/bashParser.js";
11
+ import { splitBashCommand, stripEnvVars, stripRedirections, hasWriteRedirections, isBashHeredocWrite, getSmartPrefix, DANGEROUS_COMMANDS, } from "../utils/bashParser.js";
12
12
  import { isPathInside } from "../utils/pathSafety.js";
13
13
  import { BASH_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, READ_TOOL_NAME, } from "../constants/tools.js";
14
14
  const SAFE_COMMANDS = [
@@ -23,6 +23,7 @@ const SAFE_COMMANDS = [
23
23
  "head",
24
24
  "tail",
25
25
  "wc",
26
+ "sleep",
26
27
  ];
27
28
  const DEFAULT_ALLOWED_RULES = [
28
29
  "Bash(git status*)",
@@ -63,6 +64,7 @@ const DEFAULT_ALLOWED_RULES = [
63
64
  "Bash(head*)",
64
65
  "Bash(tail*)",
65
66
  "Bash(wc*)",
67
+ "Bash(sleep*)",
66
68
  ];
67
69
  import { logger } from "../utils/globalLogger.js";
68
70
  export class PermissionManager {
@@ -264,6 +266,34 @@ export class PermissionManager {
264
266
  * Called by individual tools after validation/diff, before real operation
265
267
  */
266
268
  async checkPermission(context) {
269
+ // 0. Intercept Bash EOF writing operations
270
+ if (context.toolName === BASH_TOOL_NAME && context.toolInput?.command) {
271
+ const command = String(context.toolInput.command);
272
+ if (isBashHeredocWrite(command)) {
273
+ // Check if this specific command is explicitly allowed by a rule that includes redirection
274
+ const isExplicitlyAllowed = [
275
+ ...this.instanceAllowedRules,
276
+ ...this.temporaryRules,
277
+ ...this.allowedRules,
278
+ ...DEFAULT_ALLOWED_RULES,
279
+ ].some((rule) => {
280
+ if (rule.startsWith("Bash(") && rule.endsWith(")")) {
281
+ const pattern = rule.substring(5, rule.length - 1);
282
+ // If the pattern itself has write redirections, we check if it matches
283
+ if (hasWriteRedirections(pattern)) {
284
+ return this.matchesRule(context, rule);
285
+ }
286
+ }
287
+ return false;
288
+ });
289
+ if (!isExplicitlyAllowed) {
290
+ return {
291
+ behavior: "deny",
292
+ message: "Bash-based file writing operations using heredocs (e.g., 'cat <<EOF > file') are not allowed. Please use the dedicated 'Write' or 'Edit' tools instead for file modifications.",
293
+ };
294
+ }
295
+ }
296
+ }
267
297
  // 0. Check instance-specific denied rules first - Deny always takes precedence
268
298
  for (const rule of this.instanceDeniedRules) {
269
299
  if (this.matchesRule(context, rule)) {
@@ -627,7 +657,8 @@ export class PermissionManager {
627
657
  cmd === "cat" ||
628
658
  cmd === "head" ||
629
659
  cmd === "tail" ||
630
- cmd === "wc") {
660
+ cmd === "wc" ||
661
+ cmd === "sleep") {
631
662
  return true;
632
663
  }
633
664
  if (workdir) {
@@ -715,7 +746,8 @@ export class PermissionManager {
715
746
  cmd === "cat" ||
716
747
  cmd === "head" ||
717
748
  cmd === "tail" ||
718
- cmd === "wc") {
749
+ cmd === "wc" ||
750
+ cmd === "sleep") {
719
751
  isSafe = true;
720
752
  }
721
753
  else {
@@ -15,6 +15,14 @@ export declare function stripRedirections(command: string): string;
15
15
  * Checks if a bash command contains any write redirections (>, >>, &>, 2>, >|).
16
16
  */
17
17
  export declare function hasWriteRedirections(command: string): boolean;
18
+ /**
19
+ * Checks if a bash command contains any heredocs (<<, <<-).
20
+ */
21
+ export declare function hasHeredoc(command: string): boolean;
22
+ /**
23
+ * Checks if a bash command is a heredoc write operation (e.g., cat <<EOF > file).
24
+ */
25
+ export declare function isBashHeredocWrite(command: string): boolean;
18
26
  /**
19
27
  * Blacklist of dangerous commands that should not be safely prefix-matched
20
28
  * and should not have persistent permissions.
@@ -1 +1 @@
1
- {"version":3,"file":"bashParser.d.ts","sourceRoot":"","sources":["../../src/utils/bashParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAmH1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA2CpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuHzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CA4F7D;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAa9B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8L7D"}
1
+ {"version":3,"file":"bashParser.d.ts","sourceRoot":"","sources":["../../src/utils/bashParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoH1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA2CpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuHzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAkG7D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsCnD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAa9B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8L7D"}
@@ -53,7 +53,7 @@ export function splitBashCommand(command) {
53
53
  opLen = 1;
54
54
  else if (char === "|")
55
55
  opLen = 1;
56
- else if (char === "&" && nextChar !== ">")
56
+ else if (char === "&" && nextChar !== ">" && command[i - 1] !== ">")
57
57
  opLen = 1;
58
58
  if (opLen > 0) {
59
59
  // Check if preceded by an odd number of backslashes
@@ -350,11 +350,56 @@ export function hasWriteRedirections(command) {
350
350
  i = k - 1; // Move the main loop index to the end of the target
351
351
  continue;
352
352
  }
353
+ // Ignore file descriptor redirections like 2>&1, >&2, etc.
354
+ if (target.startsWith("&") && /^\d+$/.test(target.substring(1))) {
355
+ i = k - 1;
356
+ continue;
357
+ }
358
+ return true;
359
+ }
360
+ }
361
+ return false;
362
+ }
363
+ /**
364
+ * Checks if a bash command contains any heredocs (<<, <<-).
365
+ */
366
+ export function hasHeredoc(command) {
367
+ let inSingleQuote = false;
368
+ let inDoubleQuote = false;
369
+ let escaped = false;
370
+ for (let i = 0; i < command.length; i++) {
371
+ const char = command[i];
372
+ if (escaped) {
373
+ escaped = false;
374
+ continue;
375
+ }
376
+ if (char === "\\") {
377
+ escaped = true;
378
+ continue;
379
+ }
380
+ if (char === "'" && !inDoubleQuote) {
381
+ inSingleQuote = !inSingleQuote;
382
+ continue;
383
+ }
384
+ if (char === '"' && !inSingleQuote) {
385
+ inDoubleQuote = !inDoubleQuote;
386
+ continue;
387
+ }
388
+ if (inSingleQuote || inDoubleQuote) {
389
+ continue;
390
+ }
391
+ if (char === "<" && command[i + 1] === "<") {
353
392
  return true;
354
393
  }
355
394
  }
356
395
  return false;
357
396
  }
397
+ /**
398
+ * Checks if a bash command is a heredoc write operation (e.g., cat <<EOF > file).
399
+ */
400
+ export function isBashHeredocWrite(command) {
401
+ return hasHeredoc(command) && hasWriteRedirections(command);
402
+ }
358
403
  /**
359
404
  * Blacklist of dangerous commands that should not be safely prefix-matched
360
405
  * and should not have persistent permissions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.11.4",
3
+ "version": "0.11.6",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
@@ -35,7 +35,7 @@ export class BackgroundTaskManager {
35
35
  }
36
36
 
37
37
  public generateId(): string {
38
- return `task_${this.nextId++}`;
38
+ return `task_${process.pid}_${this.nextId++}`;
39
39
  }
40
40
 
41
41
  public addTask(task: BackgroundTask): void {
@@ -69,7 +69,7 @@ export class BackgroundTaskManager {
69
69
 
70
70
  // Create log file
71
71
  const logPath = path.join(os.tmpdir(), `wave-task-${id}.log`);
72
- const logStream = fs.createWriteStream(logPath, { flags: "a" });
72
+ const logStream = fs.createWriteStream(logPath, { flags: "w" });
73
73
 
74
74
  const shell: BackgroundShell = {
75
75
  id,
@@ -198,7 +198,7 @@ export class BackgroundTaskManager {
198
198
 
199
199
  // Create log file
200
200
  const logPath = path.join(os.tmpdir(), `wave-task-${id}.log`);
201
- const logStream = fs.createWriteStream(logPath, { flags: "a" });
201
+ const logStream = fs.createWriteStream(logPath, { flags: "w" });
202
202
 
203
203
  // Write initial output to log file
204
204
  if (initialStdout) {
@@ -63,12 +63,11 @@ export class McpManager {
63
63
  const config = await this.ensureConfigLoaded();
64
64
 
65
65
  if (config && config.mcpServers) {
66
- // Connect to all configured servers
67
- const connectionPromises = Object.keys(config.mcpServers).map(
68
- async (serverName) => {
69
- try {
70
- logger?.debug(`Connecting to MCP server: ${serverName}`);
71
- const success = await this.connectServer(serverName);
66
+ // Connect to all configured servers in background to avoid blocking agent initialization
67
+ Object.keys(config.mcpServers).forEach((serverName) => {
68
+ logger?.debug(`Connecting to MCP server: ${serverName}`);
69
+ this.connectServer(serverName)
70
+ .then((success) => {
72
71
  if (success) {
73
72
  logger?.debug(
74
73
  `Successfully connected to MCP server: ${serverName}`,
@@ -76,18 +75,18 @@ export class McpManager {
76
75
  } else {
77
76
  logger?.warn(`Failed to connect to MCP server: ${serverName}`);
78
77
  }
79
- } catch {
80
- logger?.error(`Error connecting to MCP server ${serverName}`);
81
- }
82
- },
83
- );
84
-
85
- // Wait for all connection attempts to complete
86
- await Promise.all(connectionPromises);
78
+ })
79
+ .catch((error) => {
80
+ logger?.error(
81
+ `Background connection to MCP server ${serverName} failed:`,
82
+ error,
83
+ );
84
+ });
85
+ });
87
86
  }
88
87
 
89
- logger?.debug("MCP servers initialization completed");
90
- // Trigger state change callback after initialization
88
+ logger?.debug("MCP servers initialization started in background");
89
+ // Trigger state change callback after starting initialization
91
90
  this.callbacks.onServersChange?.(this.getAllServers());
92
91
  }
93
92
  }
@@ -228,10 +227,35 @@ export class McpManager {
228
227
  const transport = new StdioClientTransport({
229
228
  command: server.config.command,
230
229
  args: server.config.args || [],
231
- env: server.config.env || {},
230
+ env: {
231
+ ...(process.env as Record<string, string>),
232
+ ...(server.config.env || {}),
233
+ },
232
234
  cwd: this.workdir, // Use the agent's workdir as the process working directory
235
+ stderr: "pipe", // Pipe stderr to capture it
233
236
  });
234
237
 
238
+ // Handle stderr output
239
+ const stderr = transport.stderr;
240
+ if (stderr) {
241
+ let buffer = "";
242
+ stderr.on("data", (chunk: Buffer) => {
243
+ buffer += chunk.toString();
244
+ const lines = buffer.split("\n");
245
+ buffer = lines.pop() || "";
246
+ for (const line of lines) {
247
+ if (line.trim()) {
248
+ logger?.error(`[MCP Server ${name}] ${line}`);
249
+ }
250
+ }
251
+ });
252
+ stderr.on("end", () => {
253
+ if (buffer.trim()) {
254
+ logger?.error(`[MCP Server ${name}] ${buffer}`);
255
+ }
256
+ });
257
+ }
258
+
235
259
  // Create client
236
260
  const client = new Client(
237
261
  {
@@ -21,6 +21,7 @@ import {
21
21
  stripEnvVars,
22
22
  stripRedirections,
23
23
  hasWriteRedirections,
24
+ isBashHeredocWrite,
24
25
  getSmartPrefix,
25
26
  DANGEROUS_COMMANDS,
26
27
  } from "../utils/bashParser.js";
@@ -46,6 +47,7 @@ const SAFE_COMMANDS = [
46
47
  "head",
47
48
  "tail",
48
49
  "wc",
50
+ "sleep",
49
51
  ];
50
52
 
51
53
  const DEFAULT_ALLOWED_RULES = [
@@ -87,6 +89,7 @@ const DEFAULT_ALLOWED_RULES = [
87
89
  "Bash(head*)",
88
90
  "Bash(tail*)",
89
91
  "Bash(wc*)",
92
+ "Bash(sleep*)",
90
93
  ];
91
94
 
92
95
  import { logger } from "../utils/globalLogger.js";
@@ -367,6 +370,37 @@ export class PermissionManager {
367
370
  async checkPermission(
368
371
  context: ToolPermissionContext,
369
372
  ): Promise<PermissionDecision> {
373
+ // 0. Intercept Bash EOF writing operations
374
+ if (context.toolName === BASH_TOOL_NAME && context.toolInput?.command) {
375
+ const command = String(context.toolInput.command);
376
+ if (isBashHeredocWrite(command)) {
377
+ // Check if this specific command is explicitly allowed by a rule that includes redirection
378
+ const isExplicitlyAllowed = [
379
+ ...this.instanceAllowedRules,
380
+ ...this.temporaryRules,
381
+ ...this.allowedRules,
382
+ ...DEFAULT_ALLOWED_RULES,
383
+ ].some((rule) => {
384
+ if (rule.startsWith("Bash(") && rule.endsWith(")")) {
385
+ const pattern = rule.substring(5, rule.length - 1);
386
+ // If the pattern itself has write redirections, we check if it matches
387
+ if (hasWriteRedirections(pattern)) {
388
+ return this.matchesRule(context, rule);
389
+ }
390
+ }
391
+ return false;
392
+ });
393
+
394
+ if (!isExplicitlyAllowed) {
395
+ return {
396
+ behavior: "deny",
397
+ message:
398
+ "Bash-based file writing operations using heredocs (e.g., 'cat <<EOF > file') are not allowed. Please use the dedicated 'Write' or 'Edit' tools instead for file modifications.",
399
+ };
400
+ }
401
+ }
402
+ }
403
+
370
404
  // 0. Check instance-specific denied rules first - Deny always takes precedence
371
405
  for (const rule of this.instanceDeniedRules) {
372
406
  if (this.matchesRule(context, rule)) {
@@ -816,7 +850,8 @@ export class PermissionManager {
816
850
  cmd === "cat" ||
817
851
  cmd === "head" ||
818
852
  cmd === "tail" ||
819
- cmd === "wc"
853
+ cmd === "wc" ||
854
+ cmd === "sleep"
820
855
  ) {
821
856
  return true;
822
857
  }
@@ -929,7 +964,8 @@ export class PermissionManager {
929
964
  cmd === "cat" ||
930
965
  cmd === "head" ||
931
966
  cmd === "tail" ||
932
- cmd === "wc"
967
+ cmd === "wc" ||
968
+ cmd === "sleep"
933
969
  ) {
934
970
  isSafe = true;
935
971
  } else {
@@ -58,7 +58,8 @@ export function splitBashCommand(command: string): string[] {
58
58
  else if (char === "|" && nextChar === "&") opLen = 2;
59
59
  else if (char === ";") opLen = 1;
60
60
  else if (char === "|") opLen = 1;
61
- else if (char === "&" && nextChar !== ">") opLen = 1;
61
+ else if (char === "&" && nextChar !== ">" && command[i - 1] !== ">")
62
+ opLen = 1;
62
63
 
63
64
  if (opLen > 0) {
64
65
  // Check if preceded by an odd number of backslashes
@@ -381,6 +382,12 @@ export function hasWriteRedirections(command: string): boolean {
381
382
  continue;
382
383
  }
383
384
 
385
+ // Ignore file descriptor redirections like 2>&1, >&2, etc.
386
+ if (target.startsWith("&") && /^\d+$/.test(target.substring(1))) {
387
+ i = k - 1;
388
+ continue;
389
+ }
390
+
384
391
  return true;
385
392
  }
386
393
  }
@@ -388,6 +395,56 @@ export function hasWriteRedirections(command: string): boolean {
388
395
  return false;
389
396
  }
390
397
 
398
+ /**
399
+ * Checks if a bash command contains any heredocs (<<, <<-).
400
+ */
401
+ export function hasHeredoc(command: string): boolean {
402
+ let inSingleQuote = false;
403
+ let inDoubleQuote = false;
404
+ let escaped = false;
405
+
406
+ for (let i = 0; i < command.length; i++) {
407
+ const char = command[i];
408
+
409
+ if (escaped) {
410
+ escaped = false;
411
+ continue;
412
+ }
413
+
414
+ if (char === "\\") {
415
+ escaped = true;
416
+ continue;
417
+ }
418
+
419
+ if (char === "'" && !inDoubleQuote) {
420
+ inSingleQuote = !inSingleQuote;
421
+ continue;
422
+ }
423
+
424
+ if (char === '"' && !inSingleQuote) {
425
+ inDoubleQuote = !inDoubleQuote;
426
+ continue;
427
+ }
428
+
429
+ if (inSingleQuote || inDoubleQuote) {
430
+ continue;
431
+ }
432
+
433
+ if (char === "<" && command[i + 1] === "<") {
434
+ return true;
435
+ }
436
+ }
437
+
438
+ return false;
439
+ }
440
+
441
+ /**
442
+ * Checks if a bash command is a heredoc write operation (e.g., cat <<EOF > file).
443
+ */
444
+ export function isBashHeredocWrite(command: string): boolean {
445
+ return hasHeredoc(command) && hasWriteRedirections(command);
446
+ }
447
+
391
448
  /**
392
449
  * Blacklist of dangerous commands that should not be safely prefix-matched
393
450
  * and should not have persistent permissions.