wave-agent-sdk 0.19.7 → 0.19.9
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/builtin/plugins/sdd/.wave-plugin/plugin.json +8 -0
- package/builtin/plugins/sdd/hooks/hooks.json +14 -0
- package/builtin/plugins/sdd/scripts/session-start.js +24 -0
- package/builtin/plugins/sdd/scripts/spec-count.js +77 -0
- package/builtin/plugins/sdd/skills/specify/SKILL.md +48 -0
- package/builtin/plugins/sdd/skills/specify/templates/spec-template.md +47 -0
- package/dist/agent.d.ts +8 -0
- package/dist/agent.js +30 -10
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/managers/aiManager.d.ts +18 -0
- package/dist/managers/aiManager.js +155 -46
- package/dist/managers/permissionManager.d.ts +7 -0
- package/dist/managers/permissionManager.js +102 -142
- package/dist/managers/pluginManager.d.ts +7 -0
- package/dist/managers/pluginManager.js +31 -0
- package/dist/managers/subagentManager.js +6 -0
- package/dist/prompts/index.d.ts +12 -1
- package/dist/prompts/index.js +133 -45
- package/dist/services/aiService.d.ts +1 -17
- package/dist/services/aiService.js +3 -85
- package/dist/services/configurationService.d.ts +6 -0
- package/dist/services/configurationService.js +31 -0
- package/dist/services/remoteSettingsService.js +2 -0
- package/dist/services/session.d.ts +3 -1
- package/dist/services/session.js +12 -4
- package/dist/services/taskManager.d.ts +1 -0
- package/dist/services/taskManager.js +34 -5
- package/dist/tools/editTool.js +24 -10
- package/dist/tools/enterWorktreeTool.js +2 -1
- package/dist/tools/grepTool.js +8 -2
- package/dist/tools/writeTool.js +36 -0
- package/dist/types/configuration.d.ts +5 -0
- package/dist/types/permissions.d.ts +0 -2
- package/dist/types/processes.d.ts +27 -0
- package/dist/types/workflow.d.ts +1 -1
- package/dist/utils/bashParser.d.ts +25 -0
- package/dist/utils/bashParser.js +103 -0
- package/dist/utils/configPaths.d.ts +4 -0
- package/dist/utils/configPaths.js +6 -0
- package/dist/utils/containerSetup.js +0 -9
- package/dist/utils/fileSearch.js +4 -2
- package/dist/utils/worktreeSession.d.ts +1 -1
- package/dist/utils/worktreeSession.js +1 -1
- package/dist/utils/worktreeUtils.d.ts +7 -1
- package/dist/utils/worktreeUtils.js +10 -4
- package/dist/workflow/types.d.ts +5 -0
- package/package.json +1 -1
- package/src/agent.ts +29 -10
- package/src/index.ts +1 -0
- package/src/managers/aiManager.ts +219 -61
- package/src/managers/permissionManager.ts +116 -168
- package/src/managers/pluginManager.ts +29 -0
- package/src/managers/subagentManager.ts +6 -0
- package/src/prompts/index.ts +144 -37
- package/src/services/aiService.ts +9 -128
- package/src/services/configurationService.ts +37 -0
- package/src/services/remoteSettingsService.ts +1 -0
- package/src/services/session.ts +18 -4
- package/src/services/taskManager.ts +46 -7
- package/src/tools/editTool.ts +29 -11
- package/src/tools/enterWorktreeTool.ts +2 -1
- package/src/tools/grepTool.ts +11 -2
- package/src/tools/writeTool.ts +43 -0
- package/src/types/configuration.ts +5 -0
- package/src/types/permissions.ts +0 -2
- package/src/types/processes.ts +29 -0
- package/src/types/workflow.ts +1 -0
- package/src/utils/bashParser.ts +106 -0
- package/src/utils/configPaths.ts +7 -0
- package/src/utils/containerSetup.ts +0 -11
- package/src/utils/fileSearch.ts +6 -2
- package/src/utils/worktreeSession.ts +1 -1
- package/src/utils/worktreeUtils.ts +14 -4
- package/src/workflow/types.ts +6 -0
package/src/utils/bashParser.ts
CHANGED
|
@@ -476,6 +476,77 @@ export const DANGEROUS_COMMANDS = [
|
|
|
476
476
|
"netcat",
|
|
477
477
|
];
|
|
478
478
|
|
|
479
|
+
/**
|
|
480
|
+
* Read-only command set: commands that only read/transform data and write to stdout.
|
|
481
|
+
* When a command in this set is used without write redirections, command substitution,
|
|
482
|
+
* or dangerous flags (e.g. sed -i), it is auto-allowed without a confirmation dialog.
|
|
483
|
+
* Aligned with Claude Code's SEMANTIC_READ_ONLY_COMMANDS, excluding interactive pagers
|
|
484
|
+
* (less, more, man, info), command executors (xargs), and infinite-output generators (yes).
|
|
485
|
+
* FR-019.2 through FR-019.7 in tool-permission-system.md.
|
|
486
|
+
*/
|
|
487
|
+
export const READ_ONLY_COMMANDS = [
|
|
488
|
+
"ls",
|
|
489
|
+
"cat",
|
|
490
|
+
"head",
|
|
491
|
+
"tail",
|
|
492
|
+
"wc",
|
|
493
|
+
"sort",
|
|
494
|
+
"uniq",
|
|
495
|
+
"grep",
|
|
496
|
+
"egrep",
|
|
497
|
+
"fgrep",
|
|
498
|
+
"rg",
|
|
499
|
+
"find",
|
|
500
|
+
"which",
|
|
501
|
+
"whereis",
|
|
502
|
+
"file",
|
|
503
|
+
"stat",
|
|
504
|
+
"du",
|
|
505
|
+
"df",
|
|
506
|
+
"free",
|
|
507
|
+
"uptime",
|
|
508
|
+
"uname",
|
|
509
|
+
"hostname",
|
|
510
|
+
"whoami",
|
|
511
|
+
"id",
|
|
512
|
+
"groups",
|
|
513
|
+
"env",
|
|
514
|
+
"printenv",
|
|
515
|
+
"echo",
|
|
516
|
+
"printf",
|
|
517
|
+
"date",
|
|
518
|
+
"true",
|
|
519
|
+
"false",
|
|
520
|
+
"pwd",
|
|
521
|
+
"tree",
|
|
522
|
+
"diff",
|
|
523
|
+
"cmp",
|
|
524
|
+
"md5sum",
|
|
525
|
+
"sha256sum",
|
|
526
|
+
"sha1sum",
|
|
527
|
+
"xxd",
|
|
528
|
+
"od",
|
|
529
|
+
"hexdump",
|
|
530
|
+
"strings",
|
|
531
|
+
"readlink",
|
|
532
|
+
"realpath",
|
|
533
|
+
"basename",
|
|
534
|
+
"dirname",
|
|
535
|
+
"seq",
|
|
536
|
+
"column",
|
|
537
|
+
"jq",
|
|
538
|
+
"yq",
|
|
539
|
+
"cut",
|
|
540
|
+
"paste",
|
|
541
|
+
"tr",
|
|
542
|
+
"awk",
|
|
543
|
+
"sed",
|
|
544
|
+
"test",
|
|
545
|
+
"expr",
|
|
546
|
+
"bc",
|
|
547
|
+
"sleep",
|
|
548
|
+
];
|
|
549
|
+
|
|
479
550
|
/**
|
|
480
551
|
* Registry of commands and their expected subcommand depth for smart prefix extraction.
|
|
481
552
|
* For example, 'git: 2' means 'git commit' is a valid prefix, but 'git' alone is not.
|
|
@@ -634,6 +705,41 @@ export function isDangerousFind(command: string): boolean {
|
|
|
634
705
|
});
|
|
635
706
|
}
|
|
636
707
|
|
|
708
|
+
/**
|
|
709
|
+
* Detects command substitution $(...) or backticks `...` in a command string.
|
|
710
|
+
* Commands with substitution are never auto-allowed because the substituted
|
|
711
|
+
* command may be dangerous (e.g. cat $(rm x)). FR-019.6.
|
|
712
|
+
*/
|
|
713
|
+
export function hasCommandSubstitution(command: string): boolean {
|
|
714
|
+
// Remove quoted strings first so $() or backticks inside quotes don't trigger
|
|
715
|
+
const stripped = command
|
|
716
|
+
.replace(/"(?:[^"\\]|\\.)*"/g, '""')
|
|
717
|
+
.replace(/'(?:[^'\\]|\\.)*'/g, "''");
|
|
718
|
+
return /\$\([^)]*\)/.test(stripped) || /`[^`]*`/.test(stripped);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* Detects process substitution <(...) or >(...) in a command string.
|
|
723
|
+
* These can execute side effects and are never auto-allowed. FR-019.6.
|
|
724
|
+
*/
|
|
725
|
+
export function hasProcessSubstitution(command: string): boolean {
|
|
726
|
+
const stripped = command
|
|
727
|
+
.replace(/"(?:[^"\\]|\\.)*"/g, '""')
|
|
728
|
+
.replace(/'(?:[^'\\]|\\.)*'/g, "''");
|
|
729
|
+
return /[<>]\([^)]*\)/.test(stripped);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Detects sed in-place edit flag (-i, with optional backup suffix like -i.bak).
|
|
734
|
+
* sed -i modifies files in place and must NOT be auto-allowed. FR-019.5.
|
|
735
|
+
*/
|
|
736
|
+
export function hasSedInPlace(command: string): boolean {
|
|
737
|
+
const stripped = stripRedirections(stripEnvVars(command));
|
|
738
|
+
const tokens = stripped.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || [];
|
|
739
|
+
if (tokens.length === 0 || tokens[0] !== "sed") return false;
|
|
740
|
+
return tokens.some((token) => /^-i(\..*)?$/.test(token));
|
|
741
|
+
}
|
|
742
|
+
|
|
637
743
|
/**
|
|
638
744
|
* Extracts a "smart prefix" from a bash command based on common developer tools.
|
|
639
745
|
* Returns null if the command is blacklisted or cannot be safely prefix-matched.
|
package/src/utils/configPaths.ts
CHANGED
|
@@ -51,6 +51,13 @@ export function getBuiltinSubagentsDir(): string {
|
|
|
51
51
|
return join(getPackageRoot(), "builtin", "subagents");
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Get the builtin plugins directory path
|
|
56
|
+
*/
|
|
57
|
+
export function getBuiltinPluginsDir(): string {
|
|
58
|
+
return join(getPackageRoot(), "builtin", "plugins");
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
/**
|
|
55
62
|
* Get the user-specific configuration file path (legacy function)
|
|
56
63
|
* @deprecated Use getUserConfigPaths() for better priority support
|
|
@@ -256,8 +256,6 @@ export function setupAgentContainer(
|
|
|
256
256
|
|
|
257
257
|
const decision = await options.canUseTool!(context);
|
|
258
258
|
|
|
259
|
-
const planFilePath = permissionManager.getPlanFilePath();
|
|
260
|
-
|
|
261
259
|
if (decision.newPermissionMode) {
|
|
262
260
|
setPermissionMode(decision.newPermissionMode);
|
|
263
261
|
}
|
|
@@ -266,15 +264,6 @@ export function setupAgentContainer(
|
|
|
266
264
|
await addPermissionRule(decision.newPermissionRule);
|
|
267
265
|
}
|
|
268
266
|
|
|
269
|
-
if (decision.clearContext) {
|
|
270
|
-
messageManager.clearMessages();
|
|
271
|
-
if (planFilePath) {
|
|
272
|
-
messageManager.addUserMessage({
|
|
273
|
-
content: `Implement the plan at ${planFilePath}`,
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
267
|
return decision;
|
|
279
268
|
}
|
|
280
269
|
: undefined;
|
package/src/utils/fileSearch.ts
CHANGED
|
@@ -34,9 +34,13 @@ async function getAllFiles(workingDirectory: string): Promise<string[]> {
|
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
child.on("close", (code) => {
|
|
37
|
+
// Exit 2 = some files were unreadable (e.g. device-name files like
|
|
38
|
+
// "nul" on Windows); stdout still holds usable partial results.
|
|
39
|
+
// Spawn failures surface via the 'error' listener instead.
|
|
37
40
|
if (code !== 0 && code !== 1) {
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
logger.warn(
|
|
42
|
+
`ripgrep exited with code ${code}, keeping partial results: ${stderr.trim()}`,
|
|
43
|
+
);
|
|
40
44
|
}
|
|
41
45
|
const files = stdout
|
|
42
46
|
.trim()
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* "WorktreeSession" container slot registered in containerSetup.ts and accessed via
|
|
6
6
|
* AIManager.getWorktreeSession()/setWorktreeSession()). This keeps worktree state
|
|
7
7
|
* isolated per session in stdio multi-agent mode — a process-level singleton would
|
|
8
|
-
* leak state across concurrent sessions (see specs/
|
|
8
|
+
* leak state across concurrent sessions (see docs/specs/multi-agent/worktree.md FR-042).
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
export interface WorktreeSession {
|
|
@@ -93,8 +93,16 @@ export function getHeadCommit(cwd: string): string {
|
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
95
|
* Create a git worktree for use during a session.
|
|
96
|
+
* @param name Worktree name
|
|
97
|
+
* @param cwd Current working directory (will be resolved to main repo root)
|
|
98
|
+
* @param options Optional creation options
|
|
99
|
+
* @param options.baseRef "fresh" (default, origin/<default-branch>) | "head" (local HEAD)
|
|
96
100
|
*/
|
|
97
|
-
export function createWorktree(
|
|
101
|
+
export function createWorktree(
|
|
102
|
+
name: string,
|
|
103
|
+
cwd: string,
|
|
104
|
+
options?: { baseRef?: "fresh" | "head" },
|
|
105
|
+
): WorktreeInfo {
|
|
98
106
|
const repoRoot = getGitMainRepoRoot(cwd);
|
|
99
107
|
if (!repoRoot) {
|
|
100
108
|
throw new Error(
|
|
@@ -107,7 +115,8 @@ export function createWorktree(name: string, cwd: string): WorktreeInfo {
|
|
|
107
115
|
|
|
108
116
|
const worktreePath = path.join(repoRoot, ".wave", "worktrees", name);
|
|
109
117
|
const branchName = `worktree-${name}`;
|
|
110
|
-
const
|
|
118
|
+
const useHead = options?.baseRef === "head";
|
|
119
|
+
const baseBranch = useHead ? "HEAD" : getDefaultRemoteBranch(cwd);
|
|
111
120
|
|
|
112
121
|
// Ensure Wave runtime files are git-excluded in this repo
|
|
113
122
|
ensureWaveRuntimeFilesExcluded(cwd);
|
|
@@ -183,8 +192,9 @@ export function createWorktree(name: string, cwd: string): WorktreeInfo {
|
|
|
183
192
|
}
|
|
184
193
|
}
|
|
185
194
|
if (
|
|
186
|
-
|
|
187
|
-
stderr.includes("
|
|
195
|
+
!useHead &&
|
|
196
|
+
(stderr.includes("not a valid object name") ||
|
|
197
|
+
stderr.includes("unknown revision"))
|
|
188
198
|
) {
|
|
189
199
|
// Base branch not fetched yet — try fetching then retrying
|
|
190
200
|
const branchNameOnly = baseBranch.split("/").pop()!;
|
package/src/workflow/types.ts
CHANGED
|
@@ -42,6 +42,12 @@ export interface WorkflowRun {
|
|
|
42
42
|
failedAgentError?: string;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Serializable workflow run for stdio transport, with the non-serializable
|
|
47
|
+
* `completionPromise` stripped. Returned by the `getWorkflowRuns` RPC.
|
|
48
|
+
*/
|
|
49
|
+
export type SerializableWorkflowRun = Omit<WorkflowRun, "completionPromise">;
|
|
50
|
+
|
|
45
51
|
export interface JournalEntry {
|
|
46
52
|
agentIndex: number;
|
|
47
53
|
prompt: string;
|