wave-agent-sdk 0.9.7 → 0.10.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/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
- package/dist/managers/backgroundTaskManager.js +59 -6
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +13 -1
- package/dist/managers/subagentManager.d.ts +2 -0
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +22 -0
- package/dist/tools/agentTool.d.ts.map +1 -1
- package/dist/tools/agentTool.js +7 -3
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +6 -2
- package/dist/tools/globTool.d.ts.map +1 -1
- package/dist/tools/globTool.js +9 -48
- package/dist/tools/grepTool.d.ts.map +1 -1
- package/dist/tools/grepTool.js +0 -6
- package/dist/types/processes.d.ts +4 -0
- package/dist/types/processes.d.ts.map +1 -1
- package/dist/utils/fileSearch.d.ts.map +1 -1
- package/dist/utils/fileSearch.js +0 -5
- package/dist/utils/openaiClient.d.ts.map +1 -1
- package/dist/utils/openaiClient.js +24 -7
- package/package.json +1 -1
- package/src/index.ts +0 -1
- package/src/managers/backgroundTaskManager.ts +62 -6
- package/src/managers/skillManager.ts +11 -1
- package/src/managers/subagentManager.ts +31 -0
- package/src/tools/agentTool.ts +9 -3
- package/src/tools/bashTool.ts +6 -2
- package/src/tools/globTool.ts +9 -61
- package/src/tools/grepTool.ts +0 -7
- package/src/types/processes.ts +4 -0
- package/src/utils/fileSearch.ts +0 -5
- package/src/utils/openaiClient.ts +23 -7
- package/dist/utils/fileFilter.d.ts +0 -15
- package/dist/utils/fileFilter.d.ts.map +0 -1
- package/dist/utils/fileFilter.js +0 -35
- package/src/utils/fileFilter.ts +0 -39
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ export * from "./agent.js";
|
|
|
4
4
|
export * from "./core/plugin.js";
|
|
5
5
|
export * from "./utils/bashParser.js";
|
|
6
6
|
export * from "./utils/convertMessagesForAPI.js";
|
|
7
|
-
export * from "./utils/fileFilter.js";
|
|
8
7
|
export * from "./utils/fileSearch.js";
|
|
9
8
|
export * from "./utils/globalLogger.js";
|
|
10
9
|
export * from "./utils/mcpUtils.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAC;AAGlC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AAGjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,uBAAuB,CAAC;AACtC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAC;AAGlC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AAGjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,6 @@ export * from "./core/plugin.js";
|
|
|
8
8
|
// Export all utilities
|
|
9
9
|
export * from "./utils/bashParser.js";
|
|
10
10
|
export * from "./utils/convertMessagesForAPI.js";
|
|
11
|
-
export * from "./utils/fileFilter.js";
|
|
12
11
|
export * from "./utils/fileSearch.js";
|
|
13
12
|
export * from "./utils/globalLogger.js";
|
|
14
13
|
export * from "./utils/mcpUtils.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backgroundTaskManager.d.ts","sourceRoot":"","sources":["../../src/managers/backgroundTaskManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"backgroundTaskManager.d.ts","sourceRoot":"","sources":["../../src/managers/backgroundTaskManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAIzD,OAAO,EAAE,cAAc,EAAmB,MAAM,uBAAuB,CAAC;AAGxE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,MAAM,WAAW,8BAA8B;IAC7C,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,4BAA4B;IAC3C,SAAS,CAAC,EAAE,8BAA8B,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,qBAAqB;IAO9B,OAAO,CAAC,SAAS;IANnB,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,OAAO,CAAS;gBAGd,SAAS,EAAE,SAAS,EAC5B,OAAO,EAAE,4BAA4B;IAMvC,OAAO,CAAC,iBAAiB;IAIlB,UAAU,IAAI,MAAM;IAIpB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAKnC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI/C,WAAW,IAAI,cAAc,EAAE;IAI/B,UAAU,CACf,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;IAqInD,YAAY,CACjB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,aAAa,GAAE,MAAW,EAC1B,aAAa,GAAE,MAAW,GACzB,MAAM;IAkGF,SAAS,CACd,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,MAAM,GACd;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAiCrD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IA+B7B,OAAO,IAAI,IAAI;CAUvB"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
2
5
|
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
3
6
|
import { logger } from "../utils/globalLogger.js";
|
|
4
7
|
export class BackgroundTaskManager {
|
|
@@ -36,6 +39,9 @@ export class BackgroundTaskManager {
|
|
|
36
39
|
...process.env,
|
|
37
40
|
},
|
|
38
41
|
});
|
|
42
|
+
// Create log file
|
|
43
|
+
const logPath = path.join(os.tmpdir(), `wave-task-${id}.log`);
|
|
44
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
39
45
|
const shell = {
|
|
40
46
|
id,
|
|
41
47
|
type: "shell",
|
|
@@ -45,8 +51,10 @@ export class BackgroundTaskManager {
|
|
|
45
51
|
status: "running",
|
|
46
52
|
stdout: "",
|
|
47
53
|
stderr: "",
|
|
54
|
+
outputPath: logPath,
|
|
48
55
|
onStop: () => {
|
|
49
56
|
try {
|
|
57
|
+
logStream.end();
|
|
50
58
|
if (child.pid) {
|
|
51
59
|
process.kill(-child.pid, "SIGTERM");
|
|
52
60
|
setTimeout(() => {
|
|
@@ -81,17 +89,28 @@ export class BackgroundTaskManager {
|
|
|
81
89
|
}, timeout);
|
|
82
90
|
}
|
|
83
91
|
const onStdout = (data) => {
|
|
84
|
-
|
|
92
|
+
const stripped = stripAnsiColors(data.toString());
|
|
93
|
+
shell.stdout += stripped;
|
|
94
|
+
if (logStream.writable) {
|
|
95
|
+
logStream.write(stripped);
|
|
96
|
+
}
|
|
85
97
|
this.notifyTasksChange();
|
|
86
98
|
};
|
|
87
99
|
const onStderr = (data) => {
|
|
88
|
-
|
|
100
|
+
const stripped = stripAnsiColors(data.toString());
|
|
101
|
+
shell.stderr += stripped;
|
|
102
|
+
if (logStream.writable) {
|
|
103
|
+
logStream.write(stripped);
|
|
104
|
+
}
|
|
89
105
|
this.notifyTasksChange();
|
|
90
106
|
};
|
|
91
107
|
const onExit = (code) => {
|
|
92
108
|
if (timeoutHandle) {
|
|
93
109
|
clearTimeout(timeoutHandle);
|
|
94
110
|
}
|
|
111
|
+
if (logStream.writable) {
|
|
112
|
+
logStream.end();
|
|
113
|
+
}
|
|
95
114
|
shell.status = code === 0 ? "completed" : "failed";
|
|
96
115
|
shell.exitCode = code ?? 0;
|
|
97
116
|
shell.endTime = Date.now();
|
|
@@ -102,8 +121,13 @@ export class BackgroundTaskManager {
|
|
|
102
121
|
if (timeoutHandle) {
|
|
103
122
|
clearTimeout(timeoutHandle);
|
|
104
123
|
}
|
|
124
|
+
const stripped = `\nProcess error: ${stripAnsiColors(error.message)}`;
|
|
105
125
|
shell.status = "failed";
|
|
106
|
-
shell.stderr +=
|
|
126
|
+
shell.stderr += stripped;
|
|
127
|
+
if (logStream.writable) {
|
|
128
|
+
logStream.write(stripped);
|
|
129
|
+
logStream.end();
|
|
130
|
+
}
|
|
107
131
|
shell.exitCode = 1;
|
|
108
132
|
shell.endTime = Date.now();
|
|
109
133
|
shell.runtime = shell.endTime - startTime;
|
|
@@ -121,6 +145,7 @@ export class BackgroundTaskManager {
|
|
|
121
145
|
if (timeoutHandle) {
|
|
122
146
|
clearTimeout(timeoutHandle);
|
|
123
147
|
}
|
|
148
|
+
logStream.end();
|
|
124
149
|
this.tasks.delete(id);
|
|
125
150
|
this.notifyTasksChange();
|
|
126
151
|
};
|
|
@@ -129,6 +154,16 @@ export class BackgroundTaskManager {
|
|
|
129
154
|
adoptProcess(child, command, initialStdout = "", initialStderr = "") {
|
|
130
155
|
const id = this.generateId();
|
|
131
156
|
const startTime = Date.now();
|
|
157
|
+
// Create log file
|
|
158
|
+
const logPath = path.join(os.tmpdir(), `wave-task-${id}.log`);
|
|
159
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
160
|
+
// Write initial output to log file
|
|
161
|
+
if (initialStdout) {
|
|
162
|
+
logStream.write(stripAnsiColors(initialStdout));
|
|
163
|
+
}
|
|
164
|
+
if (initialStderr) {
|
|
165
|
+
logStream.write(stripAnsiColors(initialStderr));
|
|
166
|
+
}
|
|
132
167
|
const shell = {
|
|
133
168
|
id,
|
|
134
169
|
type: "shell",
|
|
@@ -138,8 +173,10 @@ export class BackgroundTaskManager {
|
|
|
138
173
|
status: "running",
|
|
139
174
|
stdout: initialStdout,
|
|
140
175
|
stderr: initialStderr,
|
|
176
|
+
outputPath: logPath,
|
|
141
177
|
onStop: () => {
|
|
142
178
|
try {
|
|
179
|
+
logStream.end();
|
|
143
180
|
if (child.pid) {
|
|
144
181
|
process.kill(-child.pid, "SIGTERM");
|
|
145
182
|
setTimeout(() => {
|
|
@@ -165,14 +202,25 @@ export class BackgroundTaskManager {
|
|
|
165
202
|
this.tasks.set(id, shell);
|
|
166
203
|
this.notifyTasksChange();
|
|
167
204
|
child.stdout?.on("data", (data) => {
|
|
168
|
-
|
|
205
|
+
const stripped = stripAnsiColors(data.toString());
|
|
206
|
+
shell.stdout += stripped;
|
|
207
|
+
if (logStream.writable) {
|
|
208
|
+
logStream.write(stripped);
|
|
209
|
+
}
|
|
169
210
|
this.notifyTasksChange();
|
|
170
211
|
});
|
|
171
212
|
child.stderr?.on("data", (data) => {
|
|
172
|
-
|
|
213
|
+
const stripped = stripAnsiColors(data.toString());
|
|
214
|
+
shell.stderr += stripped;
|
|
215
|
+
if (logStream.writable) {
|
|
216
|
+
logStream.write(stripped);
|
|
217
|
+
}
|
|
173
218
|
this.notifyTasksChange();
|
|
174
219
|
});
|
|
175
220
|
child.on("exit", (code) => {
|
|
221
|
+
if (logStream.writable) {
|
|
222
|
+
logStream.end();
|
|
223
|
+
}
|
|
176
224
|
shell.status = code === 0 ? "completed" : "failed";
|
|
177
225
|
shell.exitCode = code ?? 0;
|
|
178
226
|
shell.endTime = Date.now();
|
|
@@ -180,8 +228,13 @@ export class BackgroundTaskManager {
|
|
|
180
228
|
this.notifyTasksChange();
|
|
181
229
|
});
|
|
182
230
|
child.on("error", (error) => {
|
|
231
|
+
const stripped = `\nProcess error: ${stripAnsiColors(error.message)}`;
|
|
183
232
|
shell.status = "failed";
|
|
184
|
-
shell.stderr +=
|
|
233
|
+
shell.stderr += stripped;
|
|
234
|
+
if (logStream.writable) {
|
|
235
|
+
logStream.write(stripped);
|
|
236
|
+
logStream.end();
|
|
237
|
+
}
|
|
185
238
|
shell.exitCode = 1;
|
|
186
239
|
shell.endTime = Date.now();
|
|
187
240
|
shell.runtime = shell.endTime - startTime;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;GAEG;AACH,qBAAa,YAAY;IAUrB,OAAO,CAAC,SAAS;IATnB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAS;gBAGlB,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,mBAAwB;IAQnC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCjC;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAQrC;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAQzD;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;OAEG;YACW,cAAc;IAkB5B;;OAEG;YACW,uBAAuB;IA8ErC;;OAEG;YACW,oBAAoB;
|
|
1
|
+
{"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;GAEG;AACH,qBAAa,YAAY;IAUrB,OAAO,CAAC,SAAS;IATnB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAS;gBAGlB,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,mBAAwB;IAQnC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCjC;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAQrC;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAQzD;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;OAEG;YACW,cAAc;IAkB5B;;OAEG;YACW,uBAAuB;IA8ErC;;OAEG;YACW,oBAAoB;IA4BlC;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,sBAAsB,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IA8BF;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAC5C;QACE,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,KAAK,CAAC;KACd,GACD;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CACzC;IA6BD;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkB3B;;OAEG;YACW,yBAAyB;IASvC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;CA0BhE"}
|
|
@@ -179,8 +179,20 @@ export class SkillManager {
|
|
|
179
179
|
try {
|
|
180
180
|
const entries = await readdir(skillsPath, { withFileTypes: true });
|
|
181
181
|
for (const entry of entries) {
|
|
182
|
+
const fullPath = join(skillsPath, entry.name);
|
|
182
183
|
if (entry.isDirectory()) {
|
|
183
|
-
directories.push(
|
|
184
|
+
directories.push(fullPath);
|
|
185
|
+
}
|
|
186
|
+
else if (entry.isSymbolicLink()) {
|
|
187
|
+
try {
|
|
188
|
+
const s = await stat(fullPath);
|
|
189
|
+
if (s.isDirectory()) {
|
|
190
|
+
directories.push(fullPath);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// Ignore broken symlinks or other errors
|
|
195
|
+
}
|
|
184
196
|
}
|
|
185
197
|
}
|
|
186
198
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
1
2
|
import type { SubagentConfiguration } from "../utils/subagentParser.js";
|
|
2
3
|
import type { Message, Usage } from "../types/index.js";
|
|
3
4
|
import { AIManager } from "./aiManager.js";
|
|
@@ -36,6 +37,7 @@ export interface SubagentInstance {
|
|
|
36
37
|
backgroundTaskId?: string;
|
|
37
38
|
onUpdate?: () => void;
|
|
38
39
|
model?: string;
|
|
40
|
+
logStream?: fs.WriteStream;
|
|
39
41
|
}
|
|
40
42
|
export interface SubagentManagerOptions {
|
|
41
43
|
workdir: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagentManager.d.ts","sourceRoot":"","sources":["../../src/managers/subagentManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"subagentManager.d.ts","sourceRoot":"","sources":["../../src/managers/subagentManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
2
5
|
import { AIManager } from "./aiManager.js";
|
|
3
6
|
import { MessageManager } from "./messageManager.js";
|
|
4
7
|
import { ToolManager } from "./toolManager.js";
|
|
@@ -142,6 +145,10 @@ export class SubagentManager {
|
|
|
142
145
|
if (runInBackground && backgroundTaskManager) {
|
|
143
146
|
const taskId = backgroundTaskManager.generateId();
|
|
144
147
|
const startTime = Date.now();
|
|
148
|
+
// Create log file
|
|
149
|
+
const logPath = path.join(os.tmpdir(), `wave-subagent-${taskId}.log`);
|
|
150
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
151
|
+
instance.logStream = logStream;
|
|
145
152
|
backgroundTaskManager.addTask({
|
|
146
153
|
id: taskId,
|
|
147
154
|
type: "subagent",
|
|
@@ -150,8 +157,10 @@ export class SubagentManager {
|
|
|
150
157
|
description: instance.description,
|
|
151
158
|
stdout: "",
|
|
152
159
|
stderr: "",
|
|
160
|
+
outputPath: logPath,
|
|
153
161
|
subagentId: instance.subagentId,
|
|
154
162
|
onStop: () => {
|
|
163
|
+
instance.logStream?.end();
|
|
155
164
|
instance.aiManager.abortAIMessage();
|
|
156
165
|
this.cleanupInstance(instance.subagentId);
|
|
157
166
|
},
|
|
@@ -202,6 +211,10 @@ export class SubagentManager {
|
|
|
202
211
|
}
|
|
203
212
|
const taskId = backgroundTaskManager.generateId();
|
|
204
213
|
const startTime = Date.now();
|
|
214
|
+
// Create log file
|
|
215
|
+
const logPath = path.join(os.tmpdir(), `wave-subagent-${taskId}.log`);
|
|
216
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
217
|
+
instance.logStream = logStream;
|
|
205
218
|
backgroundTaskManager.addTask({
|
|
206
219
|
id: taskId,
|
|
207
220
|
type: "subagent",
|
|
@@ -210,8 +223,10 @@ export class SubagentManager {
|
|
|
210
223
|
description: instance.description,
|
|
211
224
|
stdout: "",
|
|
212
225
|
stderr: "",
|
|
226
|
+
outputPath: logPath,
|
|
213
227
|
subagentId: instance.subagentId,
|
|
214
228
|
onStop: () => {
|
|
229
|
+
instance.logStream?.end();
|
|
215
230
|
instance.aiManager.abortAIMessage();
|
|
216
231
|
this.cleanupInstance(instance.subagentId);
|
|
217
232
|
},
|
|
@@ -285,6 +300,7 @@ export class SubagentManager {
|
|
|
285
300
|
: undefined;
|
|
286
301
|
// If this was transitioned to background, update the background task
|
|
287
302
|
if (instance.backgroundTaskId && backgroundTaskManager) {
|
|
303
|
+
instance.logStream?.end();
|
|
288
304
|
const task = backgroundTaskManager.getTask(instance.backgroundTaskId);
|
|
289
305
|
if (task) {
|
|
290
306
|
task.status = "completed";
|
|
@@ -303,6 +319,7 @@ export class SubagentManager {
|
|
|
303
319
|
: undefined;
|
|
304
320
|
// If this was transitioned to background, update the background task with error
|
|
305
321
|
if (instance.backgroundTaskId && backgroundTaskManager) {
|
|
322
|
+
instance.logStream?.end();
|
|
306
323
|
const task = backgroundTaskManager.getTask(instance.backgroundTaskId);
|
|
307
324
|
if (task) {
|
|
308
325
|
task.status = "failed";
|
|
@@ -412,6 +429,11 @@ export class SubagentManager {
|
|
|
412
429
|
instance.lastTools.shift();
|
|
413
430
|
}
|
|
414
431
|
instance.onUpdate?.();
|
|
432
|
+
// Log tool execution to file
|
|
433
|
+
if (instance.logStream) {
|
|
434
|
+
const compactParams = (params.parameters || "{}").substring(0, 100);
|
|
435
|
+
instance.logStream.write(`[${new Date().toISOString()}] Running tool: ${params.name} with params: ${compactParams}${compactParams.length >= 100 ? "..." : ""}\n`);
|
|
436
|
+
}
|
|
415
437
|
}
|
|
416
438
|
}
|
|
417
439
|
// Forward tool block updates to parent via SubagentManager callbacks
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentTool.d.ts","sourceRoot":"","sources":["../../src/tools/agentTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAStE;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"agentTool.d.ts","sourceRoot":"","sources":["../../src/tools/agentTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAStE;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,UAgQvB,CAAC"}
|
package/dist/tools/agentTool.js
CHANGED
|
@@ -149,10 +149,12 @@ When using the Agent tool, you must specify a subagent_type parameter to select
|
|
|
149
149
|
id: instance.subagentId,
|
|
150
150
|
backgroundHandler: async () => {
|
|
151
151
|
isBackgrounded = true;
|
|
152
|
-
await subagentManager.backgroundInstance(instance.subagentId);
|
|
152
|
+
const taskId = await subagentManager.backgroundInstance(instance.subagentId);
|
|
153
|
+
const task = context.backgroundTaskManager?.getTask(taskId);
|
|
154
|
+
const outputPath = task?.outputPath;
|
|
153
155
|
resolve({
|
|
154
156
|
success: true,
|
|
155
|
-
content:
|
|
157
|
+
content: `Agent backgrounded with ID: ${taskId}.${outputPath ? ` Real-time output: ${outputPath}` : ""}`,
|
|
156
158
|
shortResult: "Agent backgrounded",
|
|
157
159
|
isManuallyBackgrounded: true,
|
|
158
160
|
});
|
|
@@ -165,9 +167,11 @@ When using the Agent tool, you must specify a subagent_type parameter to select
|
|
|
165
167
|
return;
|
|
166
168
|
}
|
|
167
169
|
if (run_in_background) {
|
|
170
|
+
const task = context.backgroundTaskManager?.getTask(result);
|
|
171
|
+
const outputPath = task?.outputPath;
|
|
168
172
|
resolve({
|
|
169
173
|
success: true,
|
|
170
|
-
content: `Agent started in background with ID: ${result}`,
|
|
174
|
+
content: `Agent started in background with ID: ${result}.${outputPath ? ` Real-time output: ${outputPath}` : ""}`,
|
|
171
175
|
shortResult: `Agent started in background: ${result}`,
|
|
172
176
|
});
|
|
173
177
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AActE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AActE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA2XtB,CAAC"}
|
package/dist/tools/bashTool.js
CHANGED
|
@@ -148,9 +148,11 @@ Usage notes:
|
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
const { id: taskId } = backgroundTaskManager.startShell(command, timeout);
|
|
151
|
+
const task = backgroundTaskManager.getTask(taskId);
|
|
152
|
+
const outputPath = task?.outputPath;
|
|
151
153
|
return {
|
|
152
154
|
success: true,
|
|
153
|
-
content: `Command started in background with ID: ${taskId}
|
|
155
|
+
content: `Command started in background with ID: ${taskId}.${outputPath ? ` Real-time output: ${outputPath}` : ` Use TaskOutput tool with task_id="${taskId}" to monitor output.`}`,
|
|
154
156
|
shortResult: `Background process ${taskId} started`,
|
|
155
157
|
};
|
|
156
158
|
}
|
|
@@ -181,9 +183,11 @@ Usage notes:
|
|
|
181
183
|
const backgroundTaskManager = context.backgroundTaskManager;
|
|
182
184
|
if (backgroundTaskManager) {
|
|
183
185
|
const taskId = backgroundTaskManager.adoptProcess(child, command, outputBuffer, errorBuffer);
|
|
186
|
+
const task = backgroundTaskManager.getTask(taskId);
|
|
187
|
+
const outputPath = task?.outputPath;
|
|
184
188
|
resolve({
|
|
185
189
|
success: true,
|
|
186
|
-
content: `Command moved to background with ID: ${taskId}
|
|
190
|
+
content: `Command moved to background with ID: ${taskId}.${outputPath ? ` Real-time output: ${outputPath}` : ""}`,
|
|
187
191
|
shortResult: `Process ${taskId} backgrounded`,
|
|
188
192
|
isManuallyBackgrounded: true,
|
|
189
193
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globTool.d.ts","sourceRoot":"","sources":["../../src/tools/globTool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"globTool.d.ts","sourceRoot":"","sources":["../../src/tools/globTool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAStE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA2ItB,CAAC"}
|
package/dist/tools/globTool.js
CHANGED
|
@@ -1,55 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { rgPath } from "../utils/ripgrep.js";
|
|
1
|
+
import { glob } from "glob";
|
|
3
2
|
import { stat } from "fs/promises";
|
|
4
3
|
import { resolvePath, getDisplayPath } from "../utils/path.js";
|
|
5
|
-
import { getAllIgnorePatterns } from "../utils/fileFilter.js";
|
|
6
4
|
import { GLOB_TOOL_NAME } from "../constants/tools.js";
|
|
7
5
|
/**
|
|
8
6
|
* Maximum number of files returned by glob tool
|
|
9
7
|
*/
|
|
10
|
-
const MAX_GLOB_RESULTS =
|
|
11
|
-
/**
|
|
12
|
-
* Execute ripgrep to find files matching a pattern
|
|
13
|
-
*/
|
|
14
|
-
async function runRipgrep(pattern, workdir) {
|
|
15
|
-
if (!rgPath) {
|
|
16
|
-
throw new Error("ripgrep is not available");
|
|
17
|
-
}
|
|
18
|
-
const ignorePatterns = getAllIgnorePatterns();
|
|
19
|
-
const rgArgs = ["--files", "--color=never", "--hidden", "--glob", pattern];
|
|
20
|
-
for (const ignorePattern of ignorePatterns) {
|
|
21
|
-
rgArgs.push("--glob", `!${ignorePattern}`);
|
|
22
|
-
}
|
|
23
|
-
return new Promise((resolve, reject) => {
|
|
24
|
-
const child = spawn(rgPath, rgArgs, {
|
|
25
|
-
cwd: workdir,
|
|
26
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
27
|
-
});
|
|
28
|
-
let stdout = "";
|
|
29
|
-
let stderr = "";
|
|
30
|
-
child.stdout?.on("data", (data) => {
|
|
31
|
-
stdout += data.toString();
|
|
32
|
-
});
|
|
33
|
-
child.stderr?.on("data", (data) => {
|
|
34
|
-
stderr += data.toString();
|
|
35
|
-
});
|
|
36
|
-
child.on("close", (code) => {
|
|
37
|
-
if (code !== 0 && code !== 1) {
|
|
38
|
-
reject(new Error(`ripgrep failed with code ${code}: ${stderr || "Unknown error"}`));
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
const files = stdout
|
|
42
|
-
.trim()
|
|
43
|
-
.split("\n")
|
|
44
|
-
.filter((f) => f.length > 0)
|
|
45
|
-
.map((f) => f.replace(/\\/g, "/")); // Normalize to forward slashes
|
|
46
|
-
resolve(files);
|
|
47
|
-
});
|
|
48
|
-
child.on("error", (err) => {
|
|
49
|
-
reject(err);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
}
|
|
8
|
+
const MAX_GLOB_RESULTS = 100;
|
|
53
9
|
/**
|
|
54
10
|
* Glob Tool Plugin - Fast file pattern matching
|
|
55
11
|
*/
|
|
@@ -97,8 +53,13 @@ export const globTool = {
|
|
|
97
53
|
const workdir = searchPath
|
|
98
54
|
? resolvePath(searchPath, context.workdir)
|
|
99
55
|
: context.workdir;
|
|
100
|
-
// Execute glob search using
|
|
101
|
-
const matches = await
|
|
56
|
+
// Execute glob search using glob package
|
|
57
|
+
const matches = await glob(pattern, {
|
|
58
|
+
cwd: workdir,
|
|
59
|
+
nodir: true,
|
|
60
|
+
dot: true,
|
|
61
|
+
ignore: ["**/.git/**"],
|
|
62
|
+
});
|
|
102
63
|
if (matches.length === 0) {
|
|
103
64
|
return {
|
|
104
65
|
success: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grepTool.d.ts","sourceRoot":"","sources":["../../src/tools/grepTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"grepTool.d.ts","sourceRoot":"","sources":["../../src/tools/grepTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAUtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UAiRtB,CAAC"}
|
package/dist/tools/grepTool.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
|
-
import { getAllIgnorePatterns } from "../utils/fileFilter.js";
|
|
3
2
|
import { rgPath } from "../utils/ripgrep.js";
|
|
4
3
|
import { getDisplayPath } from "../utils/path.js";
|
|
5
4
|
import { GREP_TOOL_NAME, BASH_TOOL_NAME, AGENT_TOOL_NAME, } from "../constants/tools.js";
|
|
@@ -157,11 +156,6 @@ export const grepTool = {
|
|
|
157
156
|
if (globPattern) {
|
|
158
157
|
rgArgs.push("--glob", globPattern);
|
|
159
158
|
}
|
|
160
|
-
// Get common ignore rules
|
|
161
|
-
const ignorePatterns = getAllIgnorePatterns();
|
|
162
|
-
for (const exclude of ignorePatterns) {
|
|
163
|
-
rgArgs.push("--glob", `!${exclude}`);
|
|
164
|
-
}
|
|
165
159
|
// Add search pattern - use -e parameter to avoid patterns starting with - being mistaken as command line options
|
|
166
160
|
rgArgs.push("-e", pattern);
|
|
167
161
|
// Add search path
|
|
@@ -27,6 +27,10 @@ export interface BackgroundTaskBase {
|
|
|
27
27
|
* Used for cleanup when the task is stopped.
|
|
28
28
|
*/
|
|
29
29
|
subagentId?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Optional path to the real-time output log file.
|
|
32
|
+
*/
|
|
33
|
+
outputPath?: string;
|
|
30
34
|
}
|
|
31
35
|
export interface BackgroundShell extends BackgroundTaskBase {
|
|
32
36
|
type: "shell";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../src/types/processes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAC5B,SAAS,GACT,WAAW,GACX,QAAQ,GACR,QAAQ,CAAC;AACb,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,UAAU,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,kBAAkB,CAAC;IACzB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAgB,SAAQ,kBAAkB;IACzD,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACrC,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IACnD,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C"}
|
|
1
|
+
{"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../src/types/processes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAC5B,SAAS,GACT,WAAW,GACX,QAAQ,GACR,QAAQ,CAAC;AACb,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,UAAU,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,kBAAkB,CAAC;IACzB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAgB,SAAQ,kBAAkB;IACzD,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACrC,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IACnD,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileSearch.d.ts","sourceRoot":"","sources":["../../src/utils/fileSearch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fileSearch.d.ts","sourceRoot":"","sources":["../../src/utils/fileSearch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAiEvD;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,MAAM,EACb,UAAU;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,KACA,OAAO,CAAC,QAAQ,EAAE,CA+DpB,CAAC"}
|
package/dist/utils/fileSearch.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
import { rgPath } from "./ripgrep.js";
|
|
3
3
|
import fuzzysort from "fuzzysort";
|
|
4
|
-
import { getAllIgnorePatterns } from "./fileFilter.js";
|
|
5
4
|
import { logger } from "./globalLogger.js";
|
|
6
5
|
/**
|
|
7
6
|
* Execute ripgrep to get all file paths
|
|
@@ -10,11 +9,7 @@ async function getAllFiles(workingDirectory) {
|
|
|
10
9
|
if (!rgPath) {
|
|
11
10
|
throw new Error("ripgrep is not available");
|
|
12
11
|
}
|
|
13
|
-
const ignorePatterns = getAllIgnorePatterns();
|
|
14
12
|
const rgArgs = ["--files", "--color=never", "--hidden"];
|
|
15
|
-
for (const pattern of ignorePatterns) {
|
|
16
|
-
rgArgs.push("--glob", `!${pattern}`);
|
|
17
|
-
}
|
|
18
13
|
return new Promise((resolve, reject) => {
|
|
19
14
|
const child = spawn(rgPath, rgArgs, {
|
|
20
15
|
cwd: workingDirectory,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openaiClient.d.ts","sourceRoot":"","sources":["../../src/utils/openaiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sCAAsC,EACtC,mCAAmC,EACnC,mBAAmB,EACnB,cAAc,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,KAAK,YAAY,GACb,sCAAsC,GACtC,mCAAmC,CAAC;AAExC,UAAU,WAAW,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,UAAU,UAAU,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IACxC,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CACzC;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEzC,IAAI,IAAI;;qBAGO,CAAC,SAAS,YAAY,UACrB,CAAC,YACC;gBAAE,MAAM,CAAC,EAAE,WAAW,CAAA;aAAE,KACjC,UAAU,CACX,CAAC,SAAS,mCAAmC,GACzC,aAAa,CAAC,mBAAmB,CAAC,GAClC,cAAc,CACnB;;MA2BN;YAEa,OAAO;
|
|
1
|
+
{"version":3,"file":"openaiClient.d.ts","sourceRoot":"","sources":["../../src/utils/openaiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sCAAsC,EACtC,mCAAmC,EACnC,mBAAmB,EACnB,cAAc,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,KAAK,YAAY,GACb,sCAAsC,GACtC,mCAAmC,CAAC;AAExC,UAAU,WAAW,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,UAAU,UAAU,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IACxC,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CACzC;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEzC,IAAI,IAAI;;qBAGO,CAAC,SAAS,YAAY,UACrB,CAAC,YACC;gBAAE,MAAM,CAAC,EAAE,WAAW,CAAA;aAAE,KACjC,UAAU,CACX,CAAC,SAAS,mCAAmC,GACzC,aAAa,CAAC,mBAAmB,CAAC,GAClC,cAAc,CACnB;;MA2BN;YAEa,OAAO;YAgJN,oBAAoB;CAqCpC"}
|
|
@@ -38,13 +38,30 @@ export class OpenAIClient {
|
|
|
38
38
|
const delay = initialDelay * Math.pow(2, attempt - 1);
|
|
39
39
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
let response;
|
|
42
|
+
try {
|
|
43
|
+
response = await fetchFn(url, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers,
|
|
46
|
+
body: JSON.stringify(params),
|
|
47
|
+
signal: options?.signal,
|
|
48
|
+
...fetchOptions,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
53
|
+
throw e;
|
|
54
|
+
}
|
|
55
|
+
if (attempt < maxRetries) {
|
|
56
|
+
logger.warn("OpenAI API network error, retrying...", {
|
|
57
|
+
attempt: attempt + 1,
|
|
58
|
+
error: e,
|
|
59
|
+
});
|
|
60
|
+
lastError = e;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
throw e;
|
|
64
|
+
}
|
|
48
65
|
if (response.ok) {
|
|
49
66
|
if (params.stream) {
|
|
50
67
|
return {
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -11,7 +11,6 @@ export * from "./core/plugin.js";
|
|
|
11
11
|
// Export all utilities
|
|
12
12
|
export * from "./utils/bashParser.js";
|
|
13
13
|
export * from "./utils/convertMessagesForAPI.js";
|
|
14
|
-
export * from "./utils/fileFilter.js";
|
|
15
14
|
export * from "./utils/fileSearch.js";
|
|
16
15
|
export * from "./utils/globalLogger.js";
|
|
17
16
|
export * from "./utils/mcpUtils.js";
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { spawn, type ChildProcess } from "child_process";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
2
5
|
import { BackgroundTask, BackgroundShell } from "../types/processes.js";
|
|
3
6
|
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
4
7
|
import { logger } from "../utils/globalLogger.js";
|
|
@@ -64,6 +67,10 @@ export class BackgroundTaskManager {
|
|
|
64
67
|
},
|
|
65
68
|
});
|
|
66
69
|
|
|
70
|
+
// Create log file
|
|
71
|
+
const logPath = path.join(os.tmpdir(), `wave-task-${id}.log`);
|
|
72
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
73
|
+
|
|
67
74
|
const shell: BackgroundShell = {
|
|
68
75
|
id,
|
|
69
76
|
type: "shell",
|
|
@@ -73,8 +80,10 @@ export class BackgroundTaskManager {
|
|
|
73
80
|
status: "running",
|
|
74
81
|
stdout: "",
|
|
75
82
|
stderr: "",
|
|
83
|
+
outputPath: logPath,
|
|
76
84
|
onStop: () => {
|
|
77
85
|
try {
|
|
86
|
+
logStream.end();
|
|
78
87
|
if (child.pid) {
|
|
79
88
|
process.kill(-child.pid, "SIGTERM");
|
|
80
89
|
setTimeout(() => {
|
|
@@ -109,12 +118,20 @@ export class BackgroundTaskManager {
|
|
|
109
118
|
}
|
|
110
119
|
|
|
111
120
|
const onStdout = (data: Buffer | string) => {
|
|
112
|
-
|
|
121
|
+
const stripped = stripAnsiColors(data.toString());
|
|
122
|
+
shell.stdout += stripped;
|
|
123
|
+
if (logStream.writable) {
|
|
124
|
+
logStream.write(stripped);
|
|
125
|
+
}
|
|
113
126
|
this.notifyTasksChange();
|
|
114
127
|
};
|
|
115
128
|
|
|
116
129
|
const onStderr = (data: Buffer | string) => {
|
|
117
|
-
|
|
130
|
+
const stripped = stripAnsiColors(data.toString());
|
|
131
|
+
shell.stderr += stripped;
|
|
132
|
+
if (logStream.writable) {
|
|
133
|
+
logStream.write(stripped);
|
|
134
|
+
}
|
|
118
135
|
this.notifyTasksChange();
|
|
119
136
|
};
|
|
120
137
|
|
|
@@ -122,6 +139,9 @@ export class BackgroundTaskManager {
|
|
|
122
139
|
if (timeoutHandle) {
|
|
123
140
|
clearTimeout(timeoutHandle);
|
|
124
141
|
}
|
|
142
|
+
if (logStream.writable) {
|
|
143
|
+
logStream.end();
|
|
144
|
+
}
|
|
125
145
|
shell.status = code === 0 ? "completed" : "failed";
|
|
126
146
|
shell.exitCode = code ?? 0;
|
|
127
147
|
shell.endTime = Date.now();
|
|
@@ -133,8 +153,13 @@ export class BackgroundTaskManager {
|
|
|
133
153
|
if (timeoutHandle) {
|
|
134
154
|
clearTimeout(timeoutHandle);
|
|
135
155
|
}
|
|
156
|
+
const stripped = `\nProcess error: ${stripAnsiColors(error.message)}`;
|
|
136
157
|
shell.status = "failed";
|
|
137
|
-
shell.stderr +=
|
|
158
|
+
shell.stderr += stripped;
|
|
159
|
+
if (logStream.writable) {
|
|
160
|
+
logStream.write(stripped);
|
|
161
|
+
logStream.end();
|
|
162
|
+
}
|
|
138
163
|
shell.exitCode = 1;
|
|
139
164
|
shell.endTime = Date.now();
|
|
140
165
|
shell.runtime = shell.endTime - startTime;
|
|
@@ -154,6 +179,7 @@ export class BackgroundTaskManager {
|
|
|
154
179
|
if (timeoutHandle) {
|
|
155
180
|
clearTimeout(timeoutHandle);
|
|
156
181
|
}
|
|
182
|
+
logStream.end();
|
|
157
183
|
this.tasks.delete(id);
|
|
158
184
|
this.notifyTasksChange();
|
|
159
185
|
};
|
|
@@ -170,6 +196,18 @@ export class BackgroundTaskManager {
|
|
|
170
196
|
const id = this.generateId();
|
|
171
197
|
const startTime = Date.now();
|
|
172
198
|
|
|
199
|
+
// Create log file
|
|
200
|
+
const logPath = path.join(os.tmpdir(), `wave-task-${id}.log`);
|
|
201
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
202
|
+
|
|
203
|
+
// Write initial output to log file
|
|
204
|
+
if (initialStdout) {
|
|
205
|
+
logStream.write(stripAnsiColors(initialStdout));
|
|
206
|
+
}
|
|
207
|
+
if (initialStderr) {
|
|
208
|
+
logStream.write(stripAnsiColors(initialStderr));
|
|
209
|
+
}
|
|
210
|
+
|
|
173
211
|
const shell: BackgroundShell = {
|
|
174
212
|
id,
|
|
175
213
|
type: "shell",
|
|
@@ -179,8 +217,10 @@ export class BackgroundTaskManager {
|
|
|
179
217
|
status: "running",
|
|
180
218
|
stdout: initialStdout,
|
|
181
219
|
stderr: initialStderr,
|
|
220
|
+
outputPath: logPath,
|
|
182
221
|
onStop: () => {
|
|
183
222
|
try {
|
|
223
|
+
logStream.end();
|
|
184
224
|
if (child.pid) {
|
|
185
225
|
process.kill(-child.pid, "SIGTERM");
|
|
186
226
|
setTimeout(() => {
|
|
@@ -205,16 +245,27 @@ export class BackgroundTaskManager {
|
|
|
205
245
|
this.notifyTasksChange();
|
|
206
246
|
|
|
207
247
|
child.stdout?.on("data", (data) => {
|
|
208
|
-
|
|
248
|
+
const stripped = stripAnsiColors(data.toString());
|
|
249
|
+
shell.stdout += stripped;
|
|
250
|
+
if (logStream.writable) {
|
|
251
|
+
logStream.write(stripped);
|
|
252
|
+
}
|
|
209
253
|
this.notifyTasksChange();
|
|
210
254
|
});
|
|
211
255
|
|
|
212
256
|
child.stderr?.on("data", (data) => {
|
|
213
|
-
|
|
257
|
+
const stripped = stripAnsiColors(data.toString());
|
|
258
|
+
shell.stderr += stripped;
|
|
259
|
+
if (logStream.writable) {
|
|
260
|
+
logStream.write(stripped);
|
|
261
|
+
}
|
|
214
262
|
this.notifyTasksChange();
|
|
215
263
|
});
|
|
216
264
|
|
|
217
265
|
child.on("exit", (code) => {
|
|
266
|
+
if (logStream.writable) {
|
|
267
|
+
logStream.end();
|
|
268
|
+
}
|
|
218
269
|
shell.status = code === 0 ? "completed" : "failed";
|
|
219
270
|
shell.exitCode = code ?? 0;
|
|
220
271
|
shell.endTime = Date.now();
|
|
@@ -223,8 +274,13 @@ export class BackgroundTaskManager {
|
|
|
223
274
|
});
|
|
224
275
|
|
|
225
276
|
child.on("error", (error) => {
|
|
277
|
+
const stripped = `\nProcess error: ${stripAnsiColors(error.message)}`;
|
|
226
278
|
shell.status = "failed";
|
|
227
|
-
shell.stderr +=
|
|
279
|
+
shell.stderr += stripped;
|
|
280
|
+
if (logStream.writable) {
|
|
281
|
+
logStream.write(stripped);
|
|
282
|
+
logStream.end();
|
|
283
|
+
}
|
|
228
284
|
shell.exitCode = 1;
|
|
229
285
|
shell.endTime = Date.now();
|
|
230
286
|
shell.runtime = shell.endTime - startTime;
|
|
@@ -243,8 +243,18 @@ export class SkillManager {
|
|
|
243
243
|
const entries = await readdir(skillsPath, { withFileTypes: true });
|
|
244
244
|
|
|
245
245
|
for (const entry of entries) {
|
|
246
|
+
const fullPath = join(skillsPath, entry.name);
|
|
246
247
|
if (entry.isDirectory()) {
|
|
247
|
-
directories.push(
|
|
248
|
+
directories.push(fullPath);
|
|
249
|
+
} else if (entry.isSymbolicLink()) {
|
|
250
|
+
try {
|
|
251
|
+
const s = await stat(fullPath);
|
|
252
|
+
if (s.isDirectory()) {
|
|
253
|
+
directories.push(fullPath);
|
|
254
|
+
}
|
|
255
|
+
} catch {
|
|
256
|
+
// Ignore broken symlinks or other errors
|
|
257
|
+
}
|
|
248
258
|
}
|
|
249
259
|
}
|
|
250
260
|
} catch {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
2
5
|
import type { SubagentConfiguration } from "../utils/subagentParser.js";
|
|
3
6
|
import type { Message, Usage } from "../types/index.js";
|
|
4
7
|
import { AIManager } from "./aiManager.js";
|
|
@@ -70,6 +73,7 @@ export interface SubagentInstance {
|
|
|
70
73
|
backgroundTaskId?: string; // ID of the background task if transitioned
|
|
71
74
|
onUpdate?: () => void; // Optional callback for real-time updates
|
|
72
75
|
model?: string; // Optional model override
|
|
76
|
+
logStream?: fs.WriteStream; // Optional log stream for background tasks
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
export interface SubagentManagerOptions {
|
|
@@ -274,6 +278,11 @@ export class SubagentManager {
|
|
|
274
278
|
const taskId = backgroundTaskManager.generateId();
|
|
275
279
|
const startTime = Date.now();
|
|
276
280
|
|
|
281
|
+
// Create log file
|
|
282
|
+
const logPath = path.join(os.tmpdir(), `wave-subagent-${taskId}.log`);
|
|
283
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
284
|
+
instance.logStream = logStream;
|
|
285
|
+
|
|
277
286
|
backgroundTaskManager.addTask({
|
|
278
287
|
id: taskId,
|
|
279
288
|
type: "subagent",
|
|
@@ -282,8 +291,10 @@ export class SubagentManager {
|
|
|
282
291
|
description: instance.description,
|
|
283
292
|
stdout: "",
|
|
284
293
|
stderr: "",
|
|
294
|
+
outputPath: logPath,
|
|
285
295
|
subagentId: instance.subagentId,
|
|
286
296
|
onStop: () => {
|
|
297
|
+
instance.logStream?.end();
|
|
287
298
|
instance.aiManager.abortAIMessage();
|
|
288
299
|
this.cleanupInstance(instance.subagentId);
|
|
289
300
|
},
|
|
@@ -345,6 +356,11 @@ export class SubagentManager {
|
|
|
345
356
|
const taskId = backgroundTaskManager.generateId();
|
|
346
357
|
const startTime = Date.now();
|
|
347
358
|
|
|
359
|
+
// Create log file
|
|
360
|
+
const logPath = path.join(os.tmpdir(), `wave-subagent-${taskId}.log`);
|
|
361
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
362
|
+
instance.logStream = logStream;
|
|
363
|
+
|
|
348
364
|
backgroundTaskManager.addTask({
|
|
349
365
|
id: taskId,
|
|
350
366
|
type: "subagent",
|
|
@@ -353,8 +369,10 @@ export class SubagentManager {
|
|
|
353
369
|
description: instance.description,
|
|
354
370
|
stdout: "",
|
|
355
371
|
stderr: "",
|
|
372
|
+
outputPath: logPath,
|
|
356
373
|
subagentId: instance.subagentId,
|
|
357
374
|
onStop: () => {
|
|
375
|
+
instance.logStream?.end();
|
|
358
376
|
instance.aiManager.abortAIMessage();
|
|
359
377
|
this.cleanupInstance(instance.subagentId);
|
|
360
378
|
},
|
|
@@ -446,6 +464,7 @@ export class SubagentManager {
|
|
|
446
464
|
|
|
447
465
|
// If this was transitioned to background, update the background task
|
|
448
466
|
if (instance.backgroundTaskId && backgroundTaskManager) {
|
|
467
|
+
instance.logStream?.end();
|
|
449
468
|
const task = backgroundTaskManager.getTask(instance.backgroundTaskId);
|
|
450
469
|
if (task) {
|
|
451
470
|
task.status = "completed";
|
|
@@ -465,6 +484,7 @@ export class SubagentManager {
|
|
|
465
484
|
|
|
466
485
|
// If this was transitioned to background, update the background task with error
|
|
467
486
|
if (instance.backgroundTaskId && backgroundTaskManager) {
|
|
487
|
+
instance.logStream?.end();
|
|
468
488
|
const task = backgroundTaskManager.getTask(instance.backgroundTaskId);
|
|
469
489
|
if (task) {
|
|
470
490
|
task.status = "failed";
|
|
@@ -599,6 +619,17 @@ export class SubagentManager {
|
|
|
599
619
|
instance.lastTools.shift();
|
|
600
620
|
}
|
|
601
621
|
instance.onUpdate?.();
|
|
622
|
+
|
|
623
|
+
// Log tool execution to file
|
|
624
|
+
if (instance.logStream) {
|
|
625
|
+
const compactParams = (params.parameters || "{}").substring(
|
|
626
|
+
0,
|
|
627
|
+
100,
|
|
628
|
+
);
|
|
629
|
+
instance.logStream.write(
|
|
630
|
+
`[${new Date().toISOString()}] Running tool: ${params.name} with params: ${compactParams}${compactParams.length >= 100 ? "..." : ""}\n`,
|
|
631
|
+
);
|
|
632
|
+
}
|
|
602
633
|
}
|
|
603
634
|
}
|
|
604
635
|
|
package/src/tools/agentTool.ts
CHANGED
|
@@ -182,10 +182,14 @@ When using the Agent tool, you must specify a subagent_type parameter to select
|
|
|
182
182
|
id: instance.subagentId,
|
|
183
183
|
backgroundHandler: async () => {
|
|
184
184
|
isBackgrounded = true;
|
|
185
|
-
await subagentManager.backgroundInstance(
|
|
185
|
+
const taskId = await subagentManager.backgroundInstance(
|
|
186
|
+
instance.subagentId,
|
|
187
|
+
);
|
|
188
|
+
const task = context.backgroundTaskManager?.getTask(taskId);
|
|
189
|
+
const outputPath = task?.outputPath;
|
|
186
190
|
resolve({
|
|
187
191
|
success: true,
|
|
188
|
-
content:
|
|
192
|
+
content: `Agent backgrounded with ID: ${taskId}.${outputPath ? ` Real-time output: ${outputPath}` : ""}`,
|
|
189
193
|
shortResult: "Agent backgrounded",
|
|
190
194
|
isManuallyBackgrounded: true,
|
|
191
195
|
});
|
|
@@ -206,9 +210,11 @@ When using the Agent tool, you must specify a subagent_type parameter to select
|
|
|
206
210
|
}
|
|
207
211
|
|
|
208
212
|
if (run_in_background) {
|
|
213
|
+
const task = context.backgroundTaskManager?.getTask(result);
|
|
214
|
+
const outputPath = task?.outputPath;
|
|
209
215
|
resolve({
|
|
210
216
|
success: true,
|
|
211
|
-
content: `Agent started in background with ID: ${result}`,
|
|
217
|
+
content: `Agent started in background with ID: ${result}.${outputPath ? ` Real-time output: ${outputPath}` : ""}`,
|
|
212
218
|
shortResult: `Agent started in background: ${result}`,
|
|
213
219
|
});
|
|
214
220
|
return;
|
package/src/tools/bashTool.ts
CHANGED
|
@@ -177,9 +177,11 @@ Usage notes:
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
const { id: taskId } = backgroundTaskManager.startShell(command, timeout);
|
|
180
|
+
const task = backgroundTaskManager.getTask(taskId);
|
|
181
|
+
const outputPath = task?.outputPath;
|
|
180
182
|
return {
|
|
181
183
|
success: true,
|
|
182
|
-
content: `Command started in background with ID: ${taskId}
|
|
184
|
+
content: `Command started in background with ID: ${taskId}.${outputPath ? ` Real-time output: ${outputPath}` : ` Use TaskOutput tool with task_id="${taskId}" to monitor output.`}`,
|
|
183
185
|
shortResult: `Background process ${taskId} started`,
|
|
184
186
|
};
|
|
185
187
|
}
|
|
@@ -220,9 +222,11 @@ Usage notes:
|
|
|
220
222
|
outputBuffer,
|
|
221
223
|
errorBuffer,
|
|
222
224
|
);
|
|
225
|
+
const task = backgroundTaskManager.getTask(taskId);
|
|
226
|
+
const outputPath = task?.outputPath;
|
|
223
227
|
resolve({
|
|
224
228
|
success: true,
|
|
225
|
-
content: `Command moved to background with ID: ${taskId}
|
|
229
|
+
content: `Command moved to background with ID: ${taskId}.${outputPath ? ` Real-time output: ${outputPath}` : ""}`,
|
|
226
230
|
shortResult: `Process ${taskId} backgrounded`,
|
|
227
231
|
isManuallyBackgrounded: true,
|
|
228
232
|
});
|
package/src/tools/globTool.ts
CHANGED
|
@@ -1,70 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { rgPath } from "../utils/ripgrep.js";
|
|
1
|
+
import { glob } from "glob";
|
|
3
2
|
import { stat } from "fs/promises";
|
|
4
3
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
5
4
|
import { resolvePath, getDisplayPath } from "../utils/path.js";
|
|
6
|
-
import { getAllIgnorePatterns } from "../utils/fileFilter.js";
|
|
7
5
|
import { GLOB_TOOL_NAME } from "../constants/tools.js";
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* Maximum number of files returned by glob tool
|
|
11
9
|
*/
|
|
12
|
-
const MAX_GLOB_RESULTS =
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Execute ripgrep to find files matching a pattern
|
|
16
|
-
*/
|
|
17
|
-
async function runRipgrep(pattern: string, workdir: string): Promise<string[]> {
|
|
18
|
-
if (!rgPath) {
|
|
19
|
-
throw new Error("ripgrep is not available");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const ignorePatterns = getAllIgnorePatterns();
|
|
23
|
-
const rgArgs = ["--files", "--color=never", "--hidden", "--glob", pattern];
|
|
24
|
-
|
|
25
|
-
for (const ignorePattern of ignorePatterns) {
|
|
26
|
-
rgArgs.push("--glob", `!${ignorePattern}`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return new Promise<string[]>((resolve, reject) => {
|
|
30
|
-
const child = spawn(rgPath, rgArgs, {
|
|
31
|
-
cwd: workdir,
|
|
32
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
let stdout = "";
|
|
36
|
-
let stderr = "";
|
|
37
|
-
|
|
38
|
-
child.stdout?.on("data", (data) => {
|
|
39
|
-
stdout += data.toString();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
child.stderr?.on("data", (data) => {
|
|
43
|
-
stderr += data.toString();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
child.on("close", (code) => {
|
|
47
|
-
if (code !== 0 && code !== 1) {
|
|
48
|
-
reject(
|
|
49
|
-
new Error(
|
|
50
|
-
`ripgrep failed with code ${code}: ${stderr || "Unknown error"}`,
|
|
51
|
-
),
|
|
52
|
-
);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const files = stdout
|
|
56
|
-
.trim()
|
|
57
|
-
.split("\n")
|
|
58
|
-
.filter((f) => f.length > 0)
|
|
59
|
-
.map((f) => f.replace(/\\/g, "/")); // Normalize to forward slashes
|
|
60
|
-
resolve(files);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
child.on("error", (err) => {
|
|
64
|
-
reject(err);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
}
|
|
10
|
+
const MAX_GLOB_RESULTS = 100;
|
|
68
11
|
|
|
69
12
|
/**
|
|
70
13
|
* Glob Tool Plugin - Fast file pattern matching
|
|
@@ -122,8 +65,13 @@ export const globTool: ToolPlugin = {
|
|
|
122
65
|
? resolvePath(searchPath, context.workdir)
|
|
123
66
|
: context.workdir;
|
|
124
67
|
|
|
125
|
-
// Execute glob search using
|
|
126
|
-
const matches = await
|
|
68
|
+
// Execute glob search using glob package
|
|
69
|
+
const matches = await glob(pattern, {
|
|
70
|
+
cwd: workdir,
|
|
71
|
+
nodir: true,
|
|
72
|
+
dot: true,
|
|
73
|
+
ignore: ["**/.git/**"],
|
|
74
|
+
});
|
|
127
75
|
|
|
128
76
|
if (matches.length === 0) {
|
|
129
77
|
return {
|
package/src/tools/grepTool.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
2
2
|
import { spawn } from "child_process";
|
|
3
|
-
import { getAllIgnorePatterns } from "../utils/fileFilter.js";
|
|
4
3
|
import { rgPath } from "../utils/ripgrep.js";
|
|
5
4
|
import { getDisplayPath } from "../utils/path.js";
|
|
6
5
|
import {
|
|
@@ -188,12 +187,6 @@ export const grepTool: ToolPlugin = {
|
|
|
188
187
|
rgArgs.push("--glob", globPattern);
|
|
189
188
|
}
|
|
190
189
|
|
|
191
|
-
// Get common ignore rules
|
|
192
|
-
const ignorePatterns = getAllIgnorePatterns();
|
|
193
|
-
for (const exclude of ignorePatterns) {
|
|
194
|
-
rgArgs.push("--glob", `!${exclude}`);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
190
|
// Add search pattern - use -e parameter to avoid patterns starting with - being mistaken as command line options
|
|
198
191
|
rgArgs.push("-e", pattern);
|
|
199
192
|
|
package/src/types/processes.ts
CHANGED
|
@@ -34,6 +34,10 @@ export interface BackgroundTaskBase {
|
|
|
34
34
|
* Used for cleanup when the task is stopped.
|
|
35
35
|
*/
|
|
36
36
|
subagentId?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Optional path to the real-time output log file.
|
|
39
|
+
*/
|
|
40
|
+
outputPath?: string;
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
export interface BackgroundShell extends BackgroundTaskBase {
|
package/src/utils/fileSearch.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
import { rgPath } from "./ripgrep.js";
|
|
3
3
|
import fuzzysort from "fuzzysort";
|
|
4
|
-
import { getAllIgnorePatterns } from "./fileFilter.js";
|
|
5
4
|
import type { FileItem } from "../types/fileSearch.js";
|
|
6
5
|
import { logger } from "./globalLogger.js";
|
|
7
6
|
|
|
@@ -13,11 +12,7 @@ async function getAllFiles(workingDirectory: string): Promise<string[]> {
|
|
|
13
12
|
throw new Error("ripgrep is not available");
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
const ignorePatterns = getAllIgnorePatterns();
|
|
17
15
|
const rgArgs = ["--files", "--color=never", "--hidden"];
|
|
18
|
-
for (const pattern of ignorePatterns) {
|
|
19
|
-
rgArgs.push("--glob", `!${pattern}`);
|
|
20
|
-
}
|
|
21
16
|
|
|
22
17
|
return new Promise((resolve, reject) => {
|
|
23
18
|
const child = spawn(rgPath, rgArgs, {
|
|
@@ -97,13 +97,29 @@ export class OpenAIClient {
|
|
|
97
97
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
let response: Response;
|
|
101
|
+
try {
|
|
102
|
+
response = await fetchFn(url, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers,
|
|
105
|
+
body: JSON.stringify(params),
|
|
106
|
+
signal: options?.signal,
|
|
107
|
+
...(fetchOptions as RequestInit),
|
|
108
|
+
});
|
|
109
|
+
} catch (e) {
|
|
110
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
111
|
+
throw e;
|
|
112
|
+
}
|
|
113
|
+
if (attempt < maxRetries) {
|
|
114
|
+
logger.warn("OpenAI API network error, retrying...", {
|
|
115
|
+
attempt: attempt + 1,
|
|
116
|
+
error: e,
|
|
117
|
+
});
|
|
118
|
+
lastError = e as Error;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
throw e;
|
|
122
|
+
}
|
|
107
123
|
|
|
108
124
|
if (response.ok) {
|
|
109
125
|
if (params.stream) {
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Common ignore directory and file patterns
|
|
3
|
-
* Can be reused by multiple tools (glob, ripgrep, etc.)
|
|
4
|
-
*/
|
|
5
|
-
export declare const COMMON_IGNORE_PATTERNS: {
|
|
6
|
-
dependencies: string[];
|
|
7
|
-
cache: string[];
|
|
8
|
-
editor: string[];
|
|
9
|
-
os: string[];
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Get flat array of all common ignore patterns
|
|
13
|
-
*/
|
|
14
|
-
export declare const getAllIgnorePatterns: () => string[];
|
|
15
|
-
//# sourceMappingURL=fileFilter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fileFilter.d.ts","sourceRoot":"","sources":["../../src/utils/fileFilter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;CAsBlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAO,MAAM,EAO7C,CAAC"}
|
package/dist/utils/fileFilter.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Common ignore directory and file patterns
|
|
3
|
-
* Can be reused by multiple tools (glob, ripgrep, etc.)
|
|
4
|
-
*/
|
|
5
|
-
export const COMMON_IGNORE_PATTERNS = {
|
|
6
|
-
// Dependencies and build directories
|
|
7
|
-
dependencies: [
|
|
8
|
-
"node_modules/**",
|
|
9
|
-
".git/**",
|
|
10
|
-
"dist/**",
|
|
11
|
-
"build/**",
|
|
12
|
-
".next/**",
|
|
13
|
-
"coverage/**",
|
|
14
|
-
".nyc_output/**",
|
|
15
|
-
"tmp/**",
|
|
16
|
-
"temp/**",
|
|
17
|
-
],
|
|
18
|
-
// Cache and temporary files
|
|
19
|
-
cache: ["*.log", "*.cache", ".DS_Store", "Thumbs.db", "*~", "*.swp", "*.swo"],
|
|
20
|
-
// Editor and IDE files
|
|
21
|
-
editor: [".vscode/**", ".idea/**", "*.sublime-*"],
|
|
22
|
-
// Operating system related
|
|
23
|
-
os: [".DS_Store", "Thumbs.db", "desktop.ini"],
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Get flat array of all common ignore patterns
|
|
27
|
-
*/
|
|
28
|
-
export const getAllIgnorePatterns = () => {
|
|
29
|
-
return [
|
|
30
|
-
...COMMON_IGNORE_PATTERNS.dependencies,
|
|
31
|
-
...COMMON_IGNORE_PATTERNS.cache,
|
|
32
|
-
...COMMON_IGNORE_PATTERNS.editor,
|
|
33
|
-
...COMMON_IGNORE_PATTERNS.os,
|
|
34
|
-
];
|
|
35
|
-
};
|
package/src/utils/fileFilter.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Common ignore directory and file patterns
|
|
3
|
-
* Can be reused by multiple tools (glob, ripgrep, etc.)
|
|
4
|
-
*/
|
|
5
|
-
export const COMMON_IGNORE_PATTERNS = {
|
|
6
|
-
// Dependencies and build directories
|
|
7
|
-
dependencies: [
|
|
8
|
-
"node_modules/**",
|
|
9
|
-
".git/**",
|
|
10
|
-
"dist/**",
|
|
11
|
-
"build/**",
|
|
12
|
-
".next/**",
|
|
13
|
-
"coverage/**",
|
|
14
|
-
".nyc_output/**",
|
|
15
|
-
"tmp/**",
|
|
16
|
-
"temp/**",
|
|
17
|
-
],
|
|
18
|
-
|
|
19
|
-
// Cache and temporary files
|
|
20
|
-
cache: ["*.log", "*.cache", ".DS_Store", "Thumbs.db", "*~", "*.swp", "*.swo"],
|
|
21
|
-
|
|
22
|
-
// Editor and IDE files
|
|
23
|
-
editor: [".vscode/**", ".idea/**", "*.sublime-*"],
|
|
24
|
-
|
|
25
|
-
// Operating system related
|
|
26
|
-
os: [".DS_Store", "Thumbs.db", "desktop.ini"],
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Get flat array of all common ignore patterns
|
|
31
|
-
*/
|
|
32
|
-
export const getAllIgnorePatterns = (): string[] => {
|
|
33
|
-
return [
|
|
34
|
-
...COMMON_IGNORE_PATTERNS.dependencies,
|
|
35
|
-
...COMMON_IGNORE_PATTERNS.cache,
|
|
36
|
-
...COMMON_IGNORE_PATTERNS.editor,
|
|
37
|
-
...COMMON_IGNORE_PATTERNS.os,
|
|
38
|
-
];
|
|
39
|
-
};
|