wave-agent-sdk 0.18.3 → 0.18.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/builtin/skills/settings/ENV.md +1 -1
  2. package/builtin/skills/settings/MEMORY.md +76 -0
  3. package/builtin/skills/settings/SKILL.md +4 -4
  4. package/dist/agent.d.ts.map +1 -1
  5. package/dist/agent.js +0 -2
  6. package/dist/managers/MemoryRuleManager.d.ts +9 -0
  7. package/dist/managers/MemoryRuleManager.d.ts.map +1 -1
  8. package/dist/managers/MemoryRuleManager.js +18 -0
  9. package/dist/managers/aiManager.d.ts +1 -1
  10. package/dist/managers/aiManager.d.ts.map +1 -1
  11. package/dist/managers/aiManager.js +370 -345
  12. package/dist/managers/mcpManager.d.ts.map +1 -1
  13. package/dist/managers/mcpManager.js +22 -15
  14. package/dist/managers/messageManager.d.ts +32 -13
  15. package/dist/managers/messageManager.d.ts.map +1 -1
  16. package/dist/managers/messageManager.js +82 -76
  17. package/dist/prompts/index.d.ts +10 -4
  18. package/dist/prompts/index.d.ts.map +1 -1
  19. package/dist/prompts/index.js +21 -20
  20. package/dist/services/aiService.d.ts +2 -1
  21. package/dist/services/aiService.d.ts.map +1 -1
  22. package/dist/services/aiService.js +37 -10
  23. package/dist/services/memory.d.ts +1 -0
  24. package/dist/services/memory.d.ts.map +1 -1
  25. package/dist/services/memory.js +35 -17
  26. package/dist/tools/agentTool.d.ts.map +1 -1
  27. package/dist/tools/agentTool.js +24 -2
  28. package/dist/tools/bashTool.d.ts.map +1 -1
  29. package/dist/tools/bashTool.js +17 -10
  30. package/dist/tools/editTool.d.ts.map +1 -1
  31. package/dist/tools/editTool.js +7 -6
  32. package/dist/tools/readTool.js +2 -2
  33. package/dist/tools/writeTool.js +2 -2
  34. package/dist/utils/constants.d.ts +1 -1
  35. package/dist/utils/constants.js +1 -1
  36. package/dist/utils/containerSetup.d.ts.map +1 -1
  37. package/dist/utils/containerSetup.js +1 -0
  38. package/dist/utils/gitUtils.js +6 -6
  39. package/dist/utils/openaiClient.d.ts.map +1 -1
  40. package/dist/utils/openaiClient.js +33 -32
  41. package/dist/utils/path.d.ts +7 -0
  42. package/dist/utils/path.d.ts.map +1 -1
  43. package/dist/utils/path.js +9 -0
  44. package/dist/utils/taskReminder.d.ts +2 -3
  45. package/dist/utils/taskReminder.d.ts.map +1 -1
  46. package/dist/utils/taskReminder.js +7 -18
  47. package/dist/utils/worktreeUtils.d.ts.map +1 -1
  48. package/dist/utils/worktreeUtils.js +19 -13
  49. package/package.json +1 -1
  50. package/scripts/install_ripgrep.js +21 -1
  51. package/src/agent.ts +0 -5
  52. package/src/managers/MemoryRuleManager.ts +23 -0
  53. package/src/managers/aiManager.ts +473 -434
  54. package/src/managers/mcpManager.ts +26 -15
  55. package/src/managers/messageManager.ts +99 -82
  56. package/src/prompts/index.ts +33 -24
  57. package/src/services/aiService.ts +39 -12
  58. package/src/services/memory.ts +34 -16
  59. package/src/tools/agentTool.ts +24 -2
  60. package/src/tools/bashTool.ts +18 -9
  61. package/src/tools/editTool.ts +7 -9
  62. package/src/tools/readTool.ts +2 -2
  63. package/src/tools/writeTool.ts +2 -2
  64. package/src/utils/constants.ts +1 -1
  65. package/src/utils/containerSetup.ts +1 -0
  66. package/src/utils/gitUtils.ts +6 -6
  67. package/src/utils/openaiClient.ts +40 -31
  68. package/src/utils/path.ts +10 -0
  69. package/src/utils/taskReminder.ts +7 -19
  70. package/src/utils/worktreeUtils.ts +46 -28
  71. package/builtin/skills/settings/MEMORY_RULES.md +0 -60
  72. package/vendor/ripgrep/linux-aarch64/rg +0 -0
  73. package/vendor/ripgrep/macos-aarch64/rg +0 -0
  74. package/vendor/ripgrep/macos-x86_64/rg +0 -0
  75. package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
  76. package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"taskReminder.d.ts","sourceRoot":"","sources":["../../src/utils/taskReminder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEtE,eAAO,MAAM,oBAAoB;;;CAGhC,CAAC;AAgBF,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG;IAC9D,4BAA4B,EAAE,MAAM,CAAC;IACrC,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAqCA;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAe3D;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,0BAA0B,EAAE,EACtC,UAAU,EAAE;IACV,4BAA4B,EAAE,MAAM,CAAC;IACrC,sBAAsB,EAAE,MAAM,CAAC;CAChC,EACD,KAAK,EAAE,IAAI,EAAE,GACZ,IAAI,CAkBN"}
1
+ {"version":3,"file":"taskReminder.d.ts","sourceRoot":"","sources":["../../src/utils/taskReminder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,eAAO,MAAM,oBAAoB;;;CAGhC,CAAC;AAWF,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG;IAC9D,4BAA4B,EAAE,MAAM,CAAC;IACrC,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAqCA;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAa3D;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE;IACV,4BAA4B,EAAE,MAAM,CAAC;IACrC,sBAAsB,EAAE,MAAM,CAAC;CAChC,EACD,KAAK,EAAE,IAAI,EAAE,GACZ,MAAM,GAAG,IAAI,CAef"}
@@ -2,12 +2,7 @@ export const TASK_REMINDER_CONFIG = {
2
2
  TURNS_SINCE_WRITE: 10,
3
3
  TURNS_BETWEEN_REMINDERS: 10,
4
4
  };
5
- const TASK_MANAGEMENT_TOOLS = new Set([
6
- "TaskCreate",
7
- "TaskUpdate",
8
- "TaskList",
9
- "TaskGet",
10
- ]);
5
+ const TASK_MANAGEMENT_TOOLS = new Set(["TaskCreate", "TaskUpdate"]);
11
6
  const TASK_REMINDER_MARKER = "<!-- task-reminder -->";
12
7
  function isQualifyingAssistantMessage(message) {
13
8
  if (message.role !== "assistant")
@@ -48,29 +43,23 @@ export function getTaskReminderTurnCounts(messages) {
48
43
  export function buildTaskReminderText(tasks) {
49
44
  let text = `${TASK_REMINDER_MARKER}\n`;
50
45
  text +=
51
- "Here is a gentle reminder about the task list. The user may not have explicitly asked for the following to be done, but you should check the task list to see if any tasks need attention.\n";
46
+ "The task tools haven't been used recently. If you're working on tasks that would benefit from tracking progress, consider using TaskCreate to add new tasks and TaskUpdate to update task status (set to in_progress when starting, completed when done). Also consider cleaning up the task list if it has become stale. Only use these if relevant to the current work. This is just a gentle reminder - ignore if not applicable. Make sure that you never mention this reminder to the user";
52
47
  if (tasks.length > 0) {
53
- text += "\n";
48
+ text += "\n\nHere are the existing tasks:\n";
54
49
  for (const task of tasks) {
55
50
  text += `#${task.id} [${task.status}] ${task.subject}\n`;
56
51
  }
57
52
  }
58
- else {
59
- text += "The task list is currently empty.\n";
60
- }
61
53
  return text;
62
54
  }
63
- export function maybeInjectTaskReminder(messages, turnCounts, tasks) {
55
+ export function maybeInjectTaskReminder(turnCounts, tasks) {
64
56
  if (turnCounts.turnsSinceLastTaskManagement <
65
57
  TASK_REMINDER_CONFIG.TURNS_SINCE_WRITE) {
66
- return;
58
+ return null;
67
59
  }
68
60
  if (turnCounts.turnsSinceLastReminder <
69
61
  TASK_REMINDER_CONFIG.TURNS_BETWEEN_REMINDERS) {
70
- return;
62
+ return null;
71
63
  }
72
- messages.push({
73
- role: "user",
74
- content: buildTaskReminderText(tasks),
75
- });
64
+ return buildTaskReminderText(tasks);
76
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"worktreeUtils.d.ts","sourceRoot":"","sources":["../../src/utils/worktreeUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CA6B7C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAuJtE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CA+DvD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,GAAG,SAAS,GACrC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA8BlD"}
1
+ {"version":3,"file":"worktreeUtils.d.ts","sourceRoot":"","sources":["../../src/utils/worktreeUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CA6B7C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CA6JtE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAmEvD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,GAAG,SAAS,GACrC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAsClD"}
@@ -2,7 +2,7 @@
2
2
  * Git worktree creation and removal utilities for the SDK.
3
3
  * Used by EnterWorktree and ExitWorktree tools.
4
4
  */
5
- import { execSync } from "node:child_process";
5
+ import { execFileSync } from "node:child_process";
6
6
  import * as path from "node:path";
7
7
  import * as fs from "node:fs";
8
8
  import { getGitMainRepoRoot, getDefaultRemoteBranch } from "./gitUtils.js";
@@ -61,7 +61,7 @@ export function generateWorktreeName() {
61
61
  * Get the current HEAD commit SHA.
62
62
  */
63
63
  export function getHeadCommit(cwd) {
64
- return execSync(`git -C "${cwd}" rev-parse HEAD`, {
64
+ return execFileSync("git", ["-C", cwd, "rev-parse", "HEAD"], {
65
65
  encoding: "utf8",
66
66
  stdio: ["ignore", "pipe", "ignore"],
67
67
  }).trim();
@@ -97,7 +97,7 @@ export function createWorktree(name, cwd) {
97
97
  }
98
98
  try {
99
99
  // Create worktree and branch
100
- execSync(`git worktree add -b ${branchName} "${worktreePath}" ${baseBranch}`, {
100
+ execFileSync("git", ["worktree", "add", "-b", branchName, worktreePath, baseBranch], {
101
101
  cwd: repoRoot,
102
102
  stdio: ["ignore", "pipe", "pipe"],
103
103
  env: {
@@ -120,7 +120,7 @@ export function createWorktree(name, cwd) {
120
120
  if (stderr.includes("already exists")) {
121
121
  // Branch exists but worktree doesn't — attach to existing branch
122
122
  try {
123
- execSync(`git worktree add "${worktreePath}" ${branchName}`, {
123
+ execFileSync("git", ["worktree", "add", worktreePath, branchName], {
124
124
  cwd: repoRoot,
125
125
  stdio: ["ignore", "pipe", "pipe"],
126
126
  env: {
@@ -147,7 +147,7 @@ export function createWorktree(name, cwd) {
147
147
  // Base branch not fetched yet — try fetching then retrying
148
148
  const branchNameOnly = baseBranch.split("/").pop();
149
149
  try {
150
- execSync(`git fetch origin ${branchNameOnly}`, {
150
+ execFileSync("git", ["fetch", "origin", branchNameOnly], {
151
151
  cwd: repoRoot,
152
152
  stdio: ["ignore", "pipe", "pipe"],
153
153
  env: {
@@ -156,7 +156,7 @@ export function createWorktree(name, cwd) {
156
156
  GIT_ASKPASS: "",
157
157
  },
158
158
  });
159
- execSync(`git worktree add -b ${branchName} "${worktreePath}" ${baseBranch}`, {
159
+ execFileSync("git", ["worktree", "add", "-b", branchName, worktreePath, baseBranch], {
160
160
  cwd: repoRoot,
161
161
  stdio: ["ignore", "pipe", "pipe"],
162
162
  env: {
@@ -177,7 +177,7 @@ export function createWorktree(name, cwd) {
177
177
  catch {
178
178
  // Fetch or retry failed — fall back to HEAD
179
179
  try {
180
- execSync(`git worktree add -b ${branchName} "${worktreePath}" HEAD`, {
180
+ execFileSync("git", ["worktree", "add", "-b", branchName, worktreePath, "HEAD"], {
181
181
  cwd: repoRoot,
182
182
  stdio: ["ignore", "pipe", "pipe"],
183
183
  env: {
@@ -212,7 +212,7 @@ export function removeWorktree(info) {
212
212
  // Get current branch in worktree before removing
213
213
  let currentBranch;
214
214
  try {
215
- currentBranch = execSync(`git rev-parse --abbrev-ref HEAD`, {
215
+ currentBranch = execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
216
216
  cwd: info.path,
217
217
  encoding: "utf8",
218
218
  stdio: ["ignore", "pipe", "ignore"],
@@ -222,13 +222,13 @@ export function removeWorktree(info) {
222
222
  // Ignore errors
223
223
  }
224
224
  // Remove worktree
225
- execSync(`git worktree remove --force "${info.path}"`, {
225
+ execFileSync("git", ["worktree", "remove", "--force", info.path], {
226
226
  cwd: repoRoot,
227
227
  stdio: ["ignore", "pipe", "pipe"],
228
228
  });
229
229
  // Delete worktree branch
230
230
  try {
231
- execSync(`git branch -D ${info.branch}`, {
231
+ execFileSync("git", ["branch", "-D", info.branch], {
232
232
  cwd: repoRoot,
233
233
  stdio: ["ignore", "pipe", "pipe"],
234
234
  });
@@ -246,7 +246,7 @@ export function removeWorktree(info) {
246
246
  currentBranch !== "main" &&
247
247
  currentBranch !== "master") {
248
248
  try {
249
- execSync(`git branch -D ${currentBranch}`, {
249
+ execFileSync("git", ["branch", "-D", currentBranch], {
250
250
  cwd: repoRoot,
251
251
  stdio: ["ignore", "pipe", "pipe"],
252
252
  });
@@ -271,7 +271,7 @@ export function removeWorktree(info) {
271
271
  */
272
272
  export function countWorktreeChanges(worktreePath, originalHeadCommit) {
273
273
  try {
274
- const statusOutput = execSync(`git -C "${worktreePath}" status --porcelain`, {
274
+ const statusOutput = execFileSync("git", ["-C", worktreePath, "status", "--porcelain"], {
275
275
  encoding: "utf8",
276
276
  stdio: ["ignore", "pipe", "ignore"],
277
277
  });
@@ -281,7 +281,13 @@ export function countWorktreeChanges(worktreePath, originalHeadCommit) {
281
281
  if (!originalHeadCommit) {
282
282
  return null;
283
283
  }
284
- const revListOutput = execSync(`git -C "${worktreePath}" rev-list --count ${originalHeadCommit}..HEAD`, {
284
+ const revListOutput = execFileSync("git", [
285
+ "-C",
286
+ worktreePath,
287
+ "rev-list",
288
+ "--count",
289
+ `${originalHeadCommit}..HEAD`,
290
+ ], {
285
291
  encoding: "utf8",
286
292
  stdio: ["ignore", "pipe", "ignore"],
287
293
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.18.3",
3
+ "version": "0.18.5",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
@@ -9,6 +9,18 @@ const __dirname = path.dirname(__filename);
9
9
  const MANIFEST_PATH = path.resolve(__dirname, "../bin/rg");
10
10
  const VENDOR_DIR = path.resolve(__dirname, "../vendor/ripgrep");
11
11
 
12
+ function getCurrentPlatform() {
13
+ const platform = process.platform;
14
+ const arch = process.arch;
15
+ if (platform === "darwin")
16
+ return `macos-${arch === "arm64" ? "aarch64" : "x86_64"}`;
17
+ if (platform === "linux")
18
+ return `linux-${arch === "arm64" ? "aarch64" : "x86_64"}`;
19
+ if (platform === "win32")
20
+ return `windows-${arch === "arm64" ? "aarch64" : "x86_64"}`;
21
+ return null;
22
+ }
23
+
12
24
  async function main() {
13
25
  if (!fs.existsSync(MANIFEST_PATH)) {
14
26
  console.error(`Manifest not found: ${MANIFEST_PATH}`);
@@ -18,7 +30,15 @@ async function main() {
18
30
  const manifestContent = fs.readFileSync(MANIFEST_PATH, "utf-8");
19
31
  const jsonContent = manifestContent.replace(/^#!.*\n/, "");
20
32
  const manifest = JSON.parse(jsonContent);
21
- const platforms = manifest.platforms;
33
+ const allPlatforms = manifest.platforms;
34
+
35
+ // In CI, only download for the current platform
36
+ const isCI = process.env.CI === "true";
37
+ const currentPlatform = isCI ? getCurrentPlatform() : null;
38
+ const platforms =
39
+ currentPlatform && currentPlatform in allPlatforms
40
+ ? { [currentPlatform]: allPlatforms[currentPlatform] }
41
+ : allPlatforms;
22
42
 
23
43
  if (!fs.existsSync(VENDOR_DIR)) {
24
44
  fs.mkdirSync(VENDOR_DIR, { recursive: true });
package/src/agent.ts CHANGED
@@ -709,11 +709,6 @@ export class Agent {
709
709
 
710
710
  // Clear messages and generate new session
711
711
  this.messageManager.clearMessages();
712
- const memoryService =
713
- this.container.get<import("./services/memory.js").MemoryService>(
714
- "MemoryService",
715
- );
716
- memoryService?.clearCache();
717
712
  await this.taskManager.syncWithSession();
718
713
 
719
714
  // Run SessionStart hooks (restore context for new session)
@@ -166,6 +166,29 @@ export class MemoryRuleManager {
166
166
  return activeRules;
167
167
  }
168
168
 
169
+ /**
170
+ * Returns rules split by type:
171
+ * - unconditional: rules with no `paths` metadata (always active)
172
+ * - conditional: rules with `paths` metadata that match filesInContext
173
+ */
174
+ getActiveRulesSplit(filesInContext: string[]): {
175
+ unconditional: MemoryRule[];
176
+ conditional: MemoryRule[];
177
+ } {
178
+ const unconditional: MemoryRule[] = [];
179
+ const conditional: MemoryRule[] = [];
180
+ for (const rule of Object.values(this.state.rules)) {
181
+ if (!rule.metadata.paths || rule.metadata.paths.length === 0) {
182
+ unconditional.push(rule);
183
+ } else if (
184
+ this.service.isRuleActive(rule, filesInContext, this.workdir)
185
+ ) {
186
+ conditional.push(rule);
187
+ }
188
+ }
189
+ return { unconditional, conditional };
190
+ }
191
+
169
192
  /**
170
193
  * Reloads rules from disk.
171
194
  */