wave-agent-sdk 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +9 -79
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +85 -302
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +20 -13
- package/dist/managers/backgroundTaskManager.d.ts +1 -1
- package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
- package/dist/managers/backgroundTaskManager.js +1 -1
- package/dist/managers/{bashManager.d.ts → bangManager.d.ts} +4 -4
- package/dist/managers/{bashManager.d.ts.map → bangManager.d.ts.map} +1 -1
- package/dist/managers/{bashManager.js → bangManager.js} +5 -6
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +12 -3
- package/dist/managers/messageManager.d.ts +18 -6
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +42 -20
- package/dist/managers/permissionManager.d.ts +22 -1
- package/dist/managers/permissionManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.js +106 -85
- package/dist/managers/planManager.d.ts +6 -0
- package/dist/managers/planManager.d.ts.map +1 -1
- package/dist/managers/planManager.js +21 -0
- package/dist/managers/skillManager.d.ts +7 -2
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +30 -10
- package/dist/managers/slashCommandManager.d.ts +7 -0
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +57 -45
- package/dist/managers/subagentManager.d.ts +4 -0
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +47 -13
- package/dist/managers/toolManager.d.ts +7 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +15 -2
- package/dist/prompts/index.d.ts +0 -4
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +0 -9
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +6 -6
- package/dist/services/configurationService.d.ts +2 -2
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +4 -4
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +6 -0
- package/dist/services/initializationService.d.ts +44 -0
- package/dist/services/initializationService.d.ts.map +1 -0
- package/dist/services/initializationService.js +170 -0
- package/dist/services/interactionService.d.ts +29 -0
- package/dist/services/interactionService.d.ts.map +1 -0
- package/dist/services/interactionService.js +97 -0
- package/dist/services/session.js +1 -1
- package/dist/services/taskManager.d.ts +5 -0
- package/dist/services/taskManager.d.ts.map +1 -1
- package/dist/services/taskManager.js +16 -2
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +7 -18
- package/dist/tools/editTool.js +1 -1
- package/dist/tools/exitPlanMode.js +1 -1
- package/dist/tools/lspTool.d.ts +2 -0
- package/dist/tools/lspTool.d.ts.map +1 -1
- package/dist/tools/lspTool.js +144 -52
- package/dist/tools/skillTool.d.ts.map +1 -1
- package/dist/tools/skillTool.js +97 -2
- package/dist/tools/taskManagementTools.d.ts.map +1 -1
- package/dist/tools/taskManagementTools.js +23 -2
- package/dist/tools/taskTool.d.ts.map +1 -1
- package/dist/tools/taskTool.js +9 -15
- package/dist/tools/types.d.ts +1 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.js +1 -1
- package/dist/types/agent.d.ts +64 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +1 -0
- package/dist/types/commands.d.ts +0 -4
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/config.d.ts +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +3 -1
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/messaging.d.ts +3 -3
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/skills.d.ts +13 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/utils/commandPathResolver.d.ts +3 -36
- package/dist/utils/commandPathResolver.d.ts.map +1 -1
- package/dist/utils/commandPathResolver.js +16 -93
- package/dist/utils/configValidator.d.ts +2 -2
- package/dist/utils/configValidator.d.ts.map +1 -1
- package/dist/utils/configValidator.js +4 -6
- package/dist/utils/containerSetup.d.ts +3 -4
- package/dist/utils/containerSetup.d.ts.map +1 -1
- package/dist/utils/containerSetup.js +14 -9
- package/dist/utils/customCommands.d.ts +2 -3
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/utils/customCommands.js +20 -60
- package/dist/utils/gitUtils.d.ts +25 -0
- package/dist/utils/gitUtils.d.ts.map +1 -1
- package/dist/utils/gitUtils.js +75 -0
- package/dist/utils/markdownParser.d.ts +4 -0
- package/dist/utils/markdownParser.d.ts.map +1 -1
- package/dist/utils/markdownParser.js +33 -0
- package/dist/utils/messageOperations.d.ts +16 -7
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +45 -20
- package/dist/utils/nameGenerator.d.ts +1 -1
- package/dist/utils/nameGenerator.d.ts.map +1 -1
- package/dist/utils/nameGenerator.js +10 -6
- package/dist/utils/skillParser.d.ts.map +1 -1
- package/dist/utils/skillParser.js +48 -0
- package/package.json +1 -1
- package/src/agent.ts +103 -458
- package/src/index.ts +2 -2
- package/src/managers/aiManager.ts +23 -17
- package/src/managers/backgroundTaskManager.ts +2 -2
- package/src/managers/{bashManager.ts → bangManager.ts} +11 -8
- package/src/managers/hookManager.ts +13 -3
- package/src/managers/messageManager.ts +55 -26
- package/src/managers/permissionManager.ts +121 -98
- package/src/managers/planManager.ts +26 -0
- package/src/managers/skillManager.ts +51 -14
- package/src/managers/slashCommandManager.ts +75 -55
- package/src/managers/subagentManager.ts +57 -13
- package/src/managers/toolManager.ts +22 -2
- package/src/prompts/index.ts +0 -15
- package/src/services/aiService.ts +9 -12
- package/src/services/configurationService.ts +4 -4
- package/src/services/hook.ts +7 -0
- package/src/services/initializationService.ts +291 -0
- package/src/services/interactionService.ts +171 -0
- package/src/services/session.ts +1 -1
- package/src/services/taskManager.ts +18 -2
- package/src/tools/bashTool.ts +8 -18
- package/src/tools/editTool.ts +1 -1
- package/src/tools/exitPlanMode.ts +1 -1
- package/src/tools/lsTool.ts +1 -1
- package/src/tools/lspTool.ts +184 -52
- package/src/tools/skillTool.ts +127 -2
- package/src/tools/taskManagementTools.ts +32 -2
- package/src/tools/taskTool.ts +13 -15
- package/src/tools/types.ts +1 -2
- package/src/tools/writeTool.ts +1 -1
- package/src/types/agent.ts +83 -0
- package/src/types/commands.ts +0 -6
- package/src/types/config.ts +1 -1
- package/src/types/hooks.ts +5 -1
- package/src/types/index.ts +1 -0
- package/src/types/messaging.ts +3 -3
- package/src/types/skills.ts +13 -0
- package/src/utils/commandPathResolver.ts +14 -117
- package/src/utils/configValidator.ts +5 -9
- package/src/utils/containerSetup.ts +17 -14
- package/src/utils/customCommands.ts +20 -83
- package/src/utils/gitUtils.ts +75 -0
- package/src/utils/markdownParser.ts +47 -0
- package/src/utils/messageOperations.ts +58 -28
- package/src/utils/nameGenerator.ts +10 -6
- package/src/utils/skillParser.ts +52 -0
- package/dist/managers/backgroundBashManager.d.ts +0 -27
- package/dist/managers/backgroundBashManager.d.ts.map +0 -1
- package/dist/managers/backgroundBashManager.js +0 -169
- package/src/managers/backgroundBashManager.ts +0 -206
package/src/utils/gitUtils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import * as fsSync from "node:fs";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Check if a directory is a git repository
|
|
@@ -22,3 +23,77 @@ export function isGitRepository(dirPath: string): string {
|
|
|
22
23
|
return "No";
|
|
23
24
|
}
|
|
24
25
|
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get the root directory of the git repository
|
|
29
|
+
* @param cwd Working directory
|
|
30
|
+
* @returns Repository root path
|
|
31
|
+
*/
|
|
32
|
+
export function getGitRepoRoot(cwd: string): string {
|
|
33
|
+
try {
|
|
34
|
+
return execSync("git rev-parse --show-toplevel", {
|
|
35
|
+
cwd,
|
|
36
|
+
encoding: "utf8",
|
|
37
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
38
|
+
}).trim();
|
|
39
|
+
} catch {
|
|
40
|
+
return cwd;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the default remote branch (e.g., origin/main)
|
|
46
|
+
* @param cwd Working directory
|
|
47
|
+
* @returns Default remote branch name
|
|
48
|
+
*/
|
|
49
|
+
export function getDefaultRemoteBranch(cwd: string): string {
|
|
50
|
+
try {
|
|
51
|
+
const head = execSync("git symbolic-ref refs/remotes/origin/HEAD", {
|
|
52
|
+
cwd,
|
|
53
|
+
encoding: "utf8",
|
|
54
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
55
|
+
}).trim();
|
|
56
|
+
return head.replace("refs/remotes/", "");
|
|
57
|
+
} catch {
|
|
58
|
+
// Fallback to origin/main if origin/HEAD is not set
|
|
59
|
+
return "origin/main";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Check if there are uncommitted changes in the working directory
|
|
65
|
+
* @param cwd Working directory
|
|
66
|
+
* @returns True if there are uncommitted changes
|
|
67
|
+
*/
|
|
68
|
+
export function hasUncommittedChanges(cwd: string): boolean {
|
|
69
|
+
try {
|
|
70
|
+
const status = execSync("git status --porcelain", {
|
|
71
|
+
cwd,
|
|
72
|
+
encoding: "utf8",
|
|
73
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
74
|
+
}).trim();
|
|
75
|
+
return status.length > 0;
|
|
76
|
+
} catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Check if there are new commits in the current branch that are not in the base branch
|
|
83
|
+
* @param cwd Working directory
|
|
84
|
+
* @param baseBranch Base branch name (e.g., origin/main)
|
|
85
|
+
* @returns True if there are new commits
|
|
86
|
+
*/
|
|
87
|
+
export function hasNewCommits(cwd: string, baseBranch?: string): boolean {
|
|
88
|
+
try {
|
|
89
|
+
const range = baseBranch ? `${baseBranch}..HEAD` : "@{u}..HEAD";
|
|
90
|
+
const log = execSync(`git log ${range} --oneline`, {
|
|
91
|
+
cwd,
|
|
92
|
+
encoding: "utf8",
|
|
93
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
94
|
+
}).trim();
|
|
95
|
+
return log.length > 0;
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { readFileSync } from "fs";
|
|
2
|
+
import { exec } from "child_process";
|
|
3
|
+
import { promisify } from "util";
|
|
2
4
|
import type { CustomSlashCommandConfig } from "../types/index.js";
|
|
3
5
|
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
|
|
4
8
|
interface ParsedMarkdownFile {
|
|
5
9
|
content: string;
|
|
6
10
|
config?: CustomSlashCommandConfig;
|
|
@@ -176,3 +180,46 @@ export function replaceBashCommandsWithOutput(
|
|
|
176
180
|
|
|
177
181
|
return processedContent;
|
|
178
182
|
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Execute bash commands and return results
|
|
186
|
+
*/
|
|
187
|
+
export async function executeBashCommands(
|
|
188
|
+
commands: string[],
|
|
189
|
+
workdir: string,
|
|
190
|
+
timeout: number = 30000,
|
|
191
|
+
): Promise<BashCommandResult[]> {
|
|
192
|
+
const results: BashCommandResult[] = [];
|
|
193
|
+
|
|
194
|
+
for (const command of commands) {
|
|
195
|
+
try {
|
|
196
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
197
|
+
cwd: workdir,
|
|
198
|
+
timeout,
|
|
199
|
+
});
|
|
200
|
+
results.push({
|
|
201
|
+
command,
|
|
202
|
+
output: (stdout + (stderr || "")).trim(),
|
|
203
|
+
exitCode: 0,
|
|
204
|
+
});
|
|
205
|
+
} catch (error: unknown) {
|
|
206
|
+
const execError = error as {
|
|
207
|
+
stdout?: string;
|
|
208
|
+
stderr?: string;
|
|
209
|
+
message?: string;
|
|
210
|
+
code?: number;
|
|
211
|
+
};
|
|
212
|
+
results.push({
|
|
213
|
+
command,
|
|
214
|
+
output: (
|
|
215
|
+
(execError.stdout || "") +
|
|
216
|
+
(execError.stderr || "") +
|
|
217
|
+
(execError.message || "")
|
|
218
|
+
).trim(),
|
|
219
|
+
exitCode: execError.code || 1,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return results;
|
|
225
|
+
}
|
|
@@ -53,21 +53,22 @@ export interface AddErrorBlockParams {
|
|
|
53
53
|
error: string;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export interface
|
|
56
|
+
export interface AddBangParams {
|
|
57
57
|
messages: Message[];
|
|
58
58
|
command: string;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export interface
|
|
61
|
+
export interface UpdateBangParams {
|
|
62
62
|
messages: Message[];
|
|
63
63
|
command: string;
|
|
64
64
|
output: string;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export interface
|
|
67
|
+
export interface CompleteBangParams {
|
|
68
68
|
messages: Message[];
|
|
69
69
|
command: string;
|
|
70
70
|
exitCode: number;
|
|
71
|
+
output?: string;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
/**
|
|
@@ -295,16 +296,16 @@ export const addErrorBlockToMessage = ({
|
|
|
295
296
|
return newMessages;
|
|
296
297
|
};
|
|
297
298
|
|
|
298
|
-
// Add
|
|
299
|
-
export const
|
|
299
|
+
// Add bang block to message list
|
|
300
|
+
export const addBangMessage = ({
|
|
300
301
|
messages,
|
|
301
302
|
command,
|
|
302
|
-
}:
|
|
303
|
+
}: AddBangParams): Message[] => {
|
|
303
304
|
const outputMessage: Message = {
|
|
304
305
|
role: "user",
|
|
305
306
|
blocks: [
|
|
306
307
|
{
|
|
307
|
-
type: "
|
|
308
|
+
type: "bang",
|
|
308
309
|
command,
|
|
309
310
|
output: "",
|
|
310
311
|
isRunning: true,
|
|
@@ -316,24 +317,22 @@ export const addCommandOutputMessage = ({
|
|
|
316
317
|
return [...messages, outputMessage];
|
|
317
318
|
};
|
|
318
319
|
|
|
319
|
-
// Update output content of
|
|
320
|
-
export const
|
|
320
|
+
// Update output content of bang block
|
|
321
|
+
export const updateBangInMessage = ({
|
|
321
322
|
messages,
|
|
322
323
|
command,
|
|
323
324
|
output,
|
|
324
|
-
}:
|
|
325
|
+
}: UpdateBangParams): Message[] => {
|
|
325
326
|
const newMessages = [...messages];
|
|
326
|
-
// Find the last user message with a
|
|
327
|
+
// Find the last user message with a bang block for this command
|
|
327
328
|
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
328
329
|
const msg = newMessages[i];
|
|
329
330
|
if (msg.role === "user") {
|
|
330
331
|
const commandBlock = msg.blocks.find(
|
|
331
332
|
(block) =>
|
|
332
|
-
block.type === "
|
|
333
|
-
block.command === command &&
|
|
334
|
-
block.isRunning,
|
|
333
|
+
block.type === "bang" && block.command === command && block.isRunning,
|
|
335
334
|
);
|
|
336
|
-
if (commandBlock && commandBlock.type === "
|
|
335
|
+
if (commandBlock && commandBlock.type === "bang") {
|
|
337
336
|
commandBlock.output = output.trim();
|
|
338
337
|
break;
|
|
339
338
|
}
|
|
@@ -342,26 +341,28 @@ export const updateCommandOutputInMessage = ({
|
|
|
342
341
|
return newMessages;
|
|
343
342
|
};
|
|
344
343
|
|
|
345
|
-
// Complete
|
|
346
|
-
export const
|
|
344
|
+
// Complete bang execution, update exit status
|
|
345
|
+
export const completeBangInMessage = ({
|
|
347
346
|
messages,
|
|
348
347
|
command,
|
|
349
348
|
exitCode,
|
|
350
|
-
|
|
349
|
+
output,
|
|
350
|
+
}: CompleteBangParams): Message[] => {
|
|
351
351
|
const newMessages = [...messages];
|
|
352
|
-
// Find the last user message with a
|
|
352
|
+
// Find the last user message with a bang block for this command
|
|
353
353
|
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
354
354
|
const msg = newMessages[i];
|
|
355
355
|
if (msg.role === "user") {
|
|
356
356
|
const commandBlock = msg.blocks.find(
|
|
357
357
|
(block) =>
|
|
358
|
-
block.type === "
|
|
359
|
-
block.command === command &&
|
|
360
|
-
block.isRunning,
|
|
358
|
+
block.type === "bang" && block.command === command && block.isRunning,
|
|
361
359
|
);
|
|
362
|
-
if (commandBlock && commandBlock.type === "
|
|
360
|
+
if (commandBlock && commandBlock.type === "bang") {
|
|
363
361
|
commandBlock.isRunning = false;
|
|
364
362
|
commandBlock.exitCode = exitCode;
|
|
363
|
+
if (output !== undefined) {
|
|
364
|
+
commandBlock.output = output.trim();
|
|
365
|
+
}
|
|
365
366
|
break;
|
|
366
367
|
}
|
|
367
368
|
}
|
|
@@ -370,20 +371,49 @@ export const completeCommandInMessage = ({
|
|
|
370
371
|
};
|
|
371
372
|
|
|
372
373
|
/**
|
|
373
|
-
*
|
|
374
|
+
* Helper to count tool blocks in messages
|
|
375
|
+
*/
|
|
376
|
+
export function countToolBlocks(messages: Message[]): number {
|
|
377
|
+
let toolCount = 0;
|
|
378
|
+
messages.forEach((msg) => {
|
|
379
|
+
msg.blocks.forEach((block) => {
|
|
380
|
+
if (block.type === "tool") {
|
|
381
|
+
toolCount++;
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
return toolCount;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Remove the last user message from the conversation
|
|
374
390
|
* Used for hook error handling when the user prompt needs to be erased
|
|
375
391
|
*/
|
|
376
392
|
export const removeLastUserMessage = (messages: Message[]): Message[] => {
|
|
377
393
|
const newMessages = [...messages];
|
|
378
|
-
|
|
379
|
-
// Find the index of the last user message
|
|
380
394
|
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
381
395
|
if (newMessages[i].role === "user") {
|
|
382
|
-
// Remove the user message at index i
|
|
383
396
|
newMessages.splice(i, 1);
|
|
384
397
|
break;
|
|
385
398
|
}
|
|
386
399
|
}
|
|
387
|
-
|
|
388
400
|
return newMessages;
|
|
389
401
|
};
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Helper to format tool and token summary
|
|
405
|
+
*/
|
|
406
|
+
export function formatToolTokenSummary(
|
|
407
|
+
toolCount: number,
|
|
408
|
+
tokens: number,
|
|
409
|
+
): string {
|
|
410
|
+
if (toolCount === 0) {
|
|
411
|
+
return "";
|
|
412
|
+
}
|
|
413
|
+
let summary = `(${toolCount} tools`;
|
|
414
|
+
if (tokens > 0) {
|
|
415
|
+
summary += ` | ${tokens.toLocaleString()} tokens`;
|
|
416
|
+
}
|
|
417
|
+
summary += ")";
|
|
418
|
+
return summary;
|
|
419
|
+
}
|
|
@@ -69,10 +69,11 @@ const nouns = [
|
|
|
69
69
|
];
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
* Generates a random English name (adjective-noun)
|
|
72
|
+
* Generates a random English name (adjective-adjective-noun)
|
|
73
73
|
*/
|
|
74
74
|
export function generateRandomName(seed?: string): string {
|
|
75
|
-
let
|
|
75
|
+
let adj1Index: number;
|
|
76
|
+
let adj2Index: number;
|
|
76
77
|
let nounIndex: number;
|
|
77
78
|
|
|
78
79
|
if (seed) {
|
|
@@ -82,14 +83,17 @@ export function generateRandomName(seed?: string): string {
|
|
|
82
83
|
hash = (hash << 5) - hash + seed.charCodeAt(i);
|
|
83
84
|
hash |= 0; // Convert to 32bit integer
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
+
adj1Index = Math.abs(hash) % adjectives.length;
|
|
87
|
+
adj2Index = Math.abs(hash >> 4) % adjectives.length;
|
|
86
88
|
nounIndex = Math.abs(hash >> 8) % nouns.length;
|
|
87
89
|
} else {
|
|
88
|
-
|
|
90
|
+
adj1Index = Math.floor(Math.random() * adjectives.length);
|
|
91
|
+
adj2Index = Math.floor(Math.random() * adjectives.length);
|
|
89
92
|
nounIndex = Math.floor(Math.random() * nouns.length);
|
|
90
93
|
}
|
|
91
94
|
|
|
92
|
-
const
|
|
95
|
+
const adj1 = adjectives[adj1Index];
|
|
96
|
+
const adj2 = adjectives[adj2Index];
|
|
93
97
|
const noun = nouns[nounIndex];
|
|
94
|
-
return `${
|
|
98
|
+
return `${adj1}-${adj2}-${noun}`;
|
|
95
99
|
}
|
package/src/utils/skillParser.ts
CHANGED
|
@@ -57,11 +57,40 @@ export function parseSkillFile(
|
|
|
57
57
|
? "project"
|
|
58
58
|
: "personal";
|
|
59
59
|
|
|
60
|
+
// Extract allowed tools
|
|
61
|
+
let allowedTools: string[] | undefined;
|
|
62
|
+
const rawAllowedTools = result.frontmatter["allowed-tools"];
|
|
63
|
+
if (Array.isArray(rawAllowedTools)) {
|
|
64
|
+
allowedTools = rawAllowedTools.map((t) => String(t).trim());
|
|
65
|
+
} else if (typeof rawAllowedTools === "string") {
|
|
66
|
+
allowedTools = rawAllowedTools
|
|
67
|
+
.split(",")
|
|
68
|
+
.map((t) => t.trim())
|
|
69
|
+
.filter((t) => t.length > 0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Extract disable-model-invocation
|
|
73
|
+
const disableModelInvocation =
|
|
74
|
+
result.frontmatter["disable-model-invocation"] === true ||
|
|
75
|
+
result.frontmatter["disable-model-invocation"] === "true";
|
|
76
|
+
|
|
77
|
+
// Extract user-invocable (default to true)
|
|
78
|
+
const userInvocable =
|
|
79
|
+
result.frontmatter["user-invocable"] === undefined ||
|
|
80
|
+
result.frontmatter["user-invocable"] === true ||
|
|
81
|
+
result.frontmatter["user-invocable"] === "true";
|
|
82
|
+
|
|
60
83
|
result.skillMetadata = {
|
|
61
84
|
name: result.frontmatter.name,
|
|
62
85
|
description: result.frontmatter.description,
|
|
63
86
|
type: skillType,
|
|
64
87
|
skillPath,
|
|
88
|
+
allowedTools,
|
|
89
|
+
context: result.frontmatter.context,
|
|
90
|
+
agent: result.frontmatter.agent,
|
|
91
|
+
model: result.frontmatter.model as string | undefined,
|
|
92
|
+
disableModelInvocation,
|
|
93
|
+
userInvocable,
|
|
65
94
|
};
|
|
66
95
|
|
|
67
96
|
// Validate metadata if requested
|
|
@@ -88,10 +117,29 @@ function parseYamlFrontmatter(yamlContent: string): SkillFrontmatter {
|
|
|
88
117
|
|
|
89
118
|
try {
|
|
90
119
|
const lines = yamlContent.split("\n");
|
|
120
|
+
let currentKey: string | null = null;
|
|
121
|
+
|
|
91
122
|
for (const line of lines) {
|
|
92
123
|
const trimmed = line.trim();
|
|
93
124
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
94
125
|
|
|
126
|
+
// Check for list item
|
|
127
|
+
if (trimmed.startsWith("-") && currentKey) {
|
|
128
|
+
const value = trimmed
|
|
129
|
+
.substring(1)
|
|
130
|
+
.trim()
|
|
131
|
+
.replace(/^["']|["']$/g, "");
|
|
132
|
+
if (value) {
|
|
133
|
+
const existing = frontmatter[currentKey];
|
|
134
|
+
if (Array.isArray(existing)) {
|
|
135
|
+
(existing as string[]).push(value);
|
|
136
|
+
} else {
|
|
137
|
+
frontmatter[currentKey] = [value];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
|
|
95
143
|
const colonIndex = trimmed.indexOf(":");
|
|
96
144
|
if (colonIndex === -1) continue;
|
|
97
145
|
|
|
@@ -101,8 +149,12 @@ function parseYamlFrontmatter(yamlContent: string): SkillFrontmatter {
|
|
|
101
149
|
.trim()
|
|
102
150
|
.replace(/^["']|["']$/g, "");
|
|
103
151
|
|
|
152
|
+
currentKey = key;
|
|
104
153
|
if (key && value) {
|
|
105
154
|
frontmatter[key] = value;
|
|
155
|
+
} else if (key) {
|
|
156
|
+
// Key with no value on the same line, might be a list
|
|
157
|
+
frontmatter[key] = [];
|
|
106
158
|
}
|
|
107
159
|
}
|
|
108
160
|
} catch {
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { BackgroundShell } from "../types/index.js";
|
|
2
|
-
export interface BackgroundBashManagerCallbacks {
|
|
3
|
-
onShellsChange?: (shells: BackgroundShell[]) => void;
|
|
4
|
-
}
|
|
5
|
-
export interface BackgroundBashManagerOptions {
|
|
6
|
-
callbacks?: BackgroundBashManagerCallbacks;
|
|
7
|
-
workdir: string;
|
|
8
|
-
}
|
|
9
|
-
export declare class BackgroundBashManager {
|
|
10
|
-
private shells;
|
|
11
|
-
private nextId;
|
|
12
|
-
private callbacks;
|
|
13
|
-
private workdir;
|
|
14
|
-
constructor(options: BackgroundBashManagerOptions);
|
|
15
|
-
private notifyShellsChange;
|
|
16
|
-
startShell(command: string, timeout?: number): string;
|
|
17
|
-
getShell(id: string): BackgroundShell | undefined;
|
|
18
|
-
getAllShells(): BackgroundShell[];
|
|
19
|
-
getOutput(id: string, filter?: string): {
|
|
20
|
-
stdout: string;
|
|
21
|
-
stderr: string;
|
|
22
|
-
status: string;
|
|
23
|
-
} | null;
|
|
24
|
-
killShell(id: string): boolean;
|
|
25
|
-
cleanup(): void;
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=backgroundBashManager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"backgroundBashManager.d.ts","sourceRoot":"","sources":["../../src/managers/backgroundBashManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,WAAW,8BAA8B;IAC7C,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,4BAA4B;IAC3C,SAAS,CAAC,EAAE,8BAA8B,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,4BAA4B;IAKjD,OAAO,CAAC,kBAAkB;IAInB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;IAuErD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIjD,YAAY,IAAI,eAAe,EAAE;IAIjC,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,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAmD9B,OAAO,IAAI,IAAI;CAUvB"}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { spawn } from "child_process";
|
|
2
|
-
import { logger } from "../utils/globalLogger.js";
|
|
3
|
-
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
4
|
-
export class BackgroundBashManager {
|
|
5
|
-
constructor(options) {
|
|
6
|
-
this.shells = new Map();
|
|
7
|
-
this.nextId = 1;
|
|
8
|
-
this.callbacks = options.callbacks || {};
|
|
9
|
-
this.workdir = options.workdir;
|
|
10
|
-
}
|
|
11
|
-
notifyShellsChange() {
|
|
12
|
-
this.callbacks.onShellsChange?.(Array.from(this.shells.values()));
|
|
13
|
-
}
|
|
14
|
-
startShell(command, timeout) {
|
|
15
|
-
const id = `bash_${this.nextId++}`;
|
|
16
|
-
const startTime = Date.now();
|
|
17
|
-
const child = spawn(command, {
|
|
18
|
-
shell: true,
|
|
19
|
-
stdio: "pipe",
|
|
20
|
-
cwd: this.workdir,
|
|
21
|
-
env: {
|
|
22
|
-
...process.env,
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
const shell = {
|
|
26
|
-
id,
|
|
27
|
-
type: "shell",
|
|
28
|
-
process: child,
|
|
29
|
-
command,
|
|
30
|
-
startTime,
|
|
31
|
-
status: "running",
|
|
32
|
-
stdout: "",
|
|
33
|
-
stderr: "",
|
|
34
|
-
};
|
|
35
|
-
this.shells.set(id, shell);
|
|
36
|
-
this.notifyShellsChange();
|
|
37
|
-
// Set up timeout if specified
|
|
38
|
-
let timeoutHandle;
|
|
39
|
-
if (timeout && timeout > 0) {
|
|
40
|
-
timeoutHandle = setTimeout(() => {
|
|
41
|
-
if (shell.status === "running") {
|
|
42
|
-
this.killShell(id);
|
|
43
|
-
}
|
|
44
|
-
}, timeout);
|
|
45
|
-
}
|
|
46
|
-
child.stdout?.on("data", (data) => {
|
|
47
|
-
shell.stdout += stripAnsiColors(data.toString());
|
|
48
|
-
this.notifyShellsChange();
|
|
49
|
-
});
|
|
50
|
-
child.stderr?.on("data", (data) => {
|
|
51
|
-
shell.stderr += stripAnsiColors(data.toString());
|
|
52
|
-
this.notifyShellsChange();
|
|
53
|
-
});
|
|
54
|
-
child.on("exit", (code) => {
|
|
55
|
-
if (timeoutHandle) {
|
|
56
|
-
clearTimeout(timeoutHandle);
|
|
57
|
-
}
|
|
58
|
-
shell.status = "completed";
|
|
59
|
-
shell.exitCode = code ?? 0;
|
|
60
|
-
shell.runtime = Date.now() - startTime;
|
|
61
|
-
this.notifyShellsChange();
|
|
62
|
-
});
|
|
63
|
-
child.on("error", (error) => {
|
|
64
|
-
if (timeoutHandle) {
|
|
65
|
-
clearTimeout(timeoutHandle);
|
|
66
|
-
}
|
|
67
|
-
shell.status = "completed";
|
|
68
|
-
shell.stderr += `\nProcess error: ${stripAnsiColors(error.message)}`;
|
|
69
|
-
shell.exitCode = 1;
|
|
70
|
-
shell.runtime = Date.now() - startTime;
|
|
71
|
-
this.notifyShellsChange();
|
|
72
|
-
});
|
|
73
|
-
return id;
|
|
74
|
-
}
|
|
75
|
-
getShell(id) {
|
|
76
|
-
return this.shells.get(id);
|
|
77
|
-
}
|
|
78
|
-
getAllShells() {
|
|
79
|
-
return Array.from(this.shells.values());
|
|
80
|
-
}
|
|
81
|
-
getOutput(id, filter) {
|
|
82
|
-
const shell = this.shells.get(id);
|
|
83
|
-
if (!shell) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
let stdout = shell.stdout;
|
|
87
|
-
let stderr = shell.stderr;
|
|
88
|
-
// Apply regex filter if provided
|
|
89
|
-
if (filter) {
|
|
90
|
-
try {
|
|
91
|
-
const regex = new RegExp(filter);
|
|
92
|
-
stdout = stdout
|
|
93
|
-
.split("\n")
|
|
94
|
-
.filter((line) => regex.test(line))
|
|
95
|
-
.join("\n");
|
|
96
|
-
stderr = stderr
|
|
97
|
-
.split("\n")
|
|
98
|
-
.filter((line) => regex.test(line))
|
|
99
|
-
.join("\n");
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
logger.warn(`Invalid filter regex: ${filter}`, error);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
stdout,
|
|
107
|
-
stderr,
|
|
108
|
-
status: shell.status,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
killShell(id) {
|
|
112
|
-
const shell = this.shells.get(id);
|
|
113
|
-
if (!shell || shell.status !== "running") {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
try {
|
|
117
|
-
// Try to kill process group first
|
|
118
|
-
if (shell.process.pid) {
|
|
119
|
-
process.kill(-shell.process.pid, "SIGTERM");
|
|
120
|
-
// Force kill after timeout
|
|
121
|
-
setTimeout(() => {
|
|
122
|
-
if (shell.status === "running" &&
|
|
123
|
-
shell.process.pid &&
|
|
124
|
-
!shell.process.killed) {
|
|
125
|
-
try {
|
|
126
|
-
process.kill(-shell.process.pid, "SIGKILL");
|
|
127
|
-
}
|
|
128
|
-
catch (error) {
|
|
129
|
-
logger.error("Failed to force kill process:", error);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}, 1000);
|
|
133
|
-
}
|
|
134
|
-
shell.status = "killed";
|
|
135
|
-
shell.runtime = Date.now() - shell.startTime;
|
|
136
|
-
this.notifyShellsChange();
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
// Fallback to direct process kill
|
|
141
|
-
try {
|
|
142
|
-
shell.process.kill("SIGTERM");
|
|
143
|
-
setTimeout(() => {
|
|
144
|
-
if (!shell.process.killed) {
|
|
145
|
-
shell.process.kill("SIGKILL");
|
|
146
|
-
}
|
|
147
|
-
}, 1000);
|
|
148
|
-
shell.status = "killed";
|
|
149
|
-
shell.runtime = Date.now() - shell.startTime;
|
|
150
|
-
this.notifyShellsChange();
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
catch (directKillError) {
|
|
154
|
-
logger.error("Failed to kill child process:", directKillError);
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
cleanup() {
|
|
160
|
-
// Kill all running shells
|
|
161
|
-
for (const [id, shell] of this.shells) {
|
|
162
|
-
if (shell.status === "running") {
|
|
163
|
-
this.killShell(id);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
this.shells.clear();
|
|
167
|
-
this.notifyShellsChange();
|
|
168
|
-
}
|
|
169
|
-
}
|