wave-agent-sdk 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/dist/agent.d.ts +23 -1
  2. package/dist/agent.js +34 -4
  3. package/dist/managers/aiManager.d.ts +36 -0
  4. package/dist/managers/aiManager.js +240 -8
  5. package/dist/managers/messageManager.d.ts +1 -3
  6. package/dist/managers/messageManager.js +19 -9
  7. package/dist/managers/slashCommandManager.js +28 -0
  8. package/dist/managers/subagentManager.d.ts +0 -2
  9. package/dist/services/session.js +2 -9
  10. package/dist/telemetry/instrumentation.d.ts +1 -1
  11. package/dist/telemetry/instrumentation.js +57 -28
  12. package/dist/tools/bashTool.js +16 -6
  13. package/dist/tools/grepTool.js +11 -3
  14. package/dist/types/index.d.ts +3 -0
  15. package/dist/types/messaging.d.ts +2 -0
  16. package/dist/utils/containerSetup.js +0 -3
  17. package/dist/utils/messageOperations.d.ts +10 -1
  18. package/dist/utils/messageOperations.js +19 -1
  19. package/dist/utils/notificationXml.js +5 -0
  20. package/dist/utils/ripgrep.d.ts +4 -4
  21. package/dist/utils/ripgrep.js +4 -27
  22. package/package.json +20 -8
  23. package/bin/rg +0 -79
  24. package/dist/managers/forkedAgentManager.d.ts +0 -50
  25. package/dist/managers/forkedAgentManager.js +0 -130
  26. package/scripts/install_ripgrep.js +0 -111
  27. package/scripts/postinstall.js +0 -38
  28. package/src/agent.ts +0 -1271
  29. package/src/constants/subagents.ts +0 -4
  30. package/src/constants/toolLimits.ts +0 -15
  31. package/src/constants/tools.ts +0 -24
  32. package/src/core/plugin.ts +0 -237
  33. package/src/core/session.ts +0 -9
  34. package/src/index.ts +0 -38
  35. package/src/managers/MemoryRuleManager.ts +0 -198
  36. package/src/managers/aiManager.ts +0 -2429
  37. package/src/managers/backgroundTaskManager.ts +0 -480
  38. package/src/managers/bangManager.ts +0 -119
  39. package/src/managers/cronManager.ts +0 -401
  40. package/src/managers/foregroundTaskManager.ts +0 -30
  41. package/src/managers/forkedAgentManager.ts +0 -216
  42. package/src/managers/hookManager.ts +0 -1089
  43. package/src/managers/liveConfigManager.ts +0 -445
  44. package/src/managers/lspManager.ts +0 -470
  45. package/src/managers/mcpManager.ts +0 -1010
  46. package/src/managers/messageManager.ts +0 -1180
  47. package/src/managers/messageQueue.ts +0 -157
  48. package/src/managers/permissionManager.ts +0 -1140
  49. package/src/managers/planManager.ts +0 -112
  50. package/src/managers/pluginManager.ts +0 -330
  51. package/src/managers/pluginScopeManager.ts +0 -124
  52. package/src/managers/reversionManager.ts +0 -178
  53. package/src/managers/skillManager.ts +0 -578
  54. package/src/managers/slashCommandManager.ts +0 -564
  55. package/src/managers/subagentManager.ts +0 -915
  56. package/src/managers/toolManager.ts +0 -489
  57. package/src/managers/workflowManager.ts +0 -493
  58. package/src/prompts/autoMemory.ts +0 -33
  59. package/src/prompts/autoMemoryExtraction.ts +0 -146
  60. package/src/prompts/index.ts +0 -506
  61. package/src/prompts/planModeReminders.ts +0 -126
  62. package/src/services/GitService.ts +0 -131
  63. package/src/services/MarketplaceService.ts +0 -1052
  64. package/src/services/MemoryRuleService.ts +0 -71
  65. package/src/services/aiService.ts +0 -919
  66. package/src/services/authService.ts +0 -565
  67. package/src/services/autoMemoryService.ts +0 -280
  68. package/src/services/configurationService.ts +0 -1520
  69. package/src/services/fileWatcher.ts +0 -319
  70. package/src/services/hook.ts +0 -348
  71. package/src/services/initializationService.ts +0 -357
  72. package/src/services/interactionService.ts +0 -229
  73. package/src/services/jsonlHandler.ts +0 -295
  74. package/src/services/memory.ts +0 -234
  75. package/src/services/pluginLoader.ts +0 -252
  76. package/src/services/remoteSettingsService.ts +0 -366
  77. package/src/services/reversionService.ts +0 -122
  78. package/src/services/session.ts +0 -922
  79. package/src/services/taskManager.ts +0 -321
  80. package/src/telemetry/events.ts +0 -65
  81. package/src/telemetry/instrumentation.ts +0 -499
  82. package/src/telemetry/sessionTracing.ts +0 -348
  83. package/src/tools/agentTool.ts +0 -322
  84. package/src/tools/askUserQuestion.ts +0 -160
  85. package/src/tools/bashTool.ts +0 -621
  86. package/src/tools/buildTool.ts +0 -61
  87. package/src/tools/cronCreateTool.ts +0 -161
  88. package/src/tools/cronDeleteTool.ts +0 -51
  89. package/src/tools/cronListTool.ts +0 -47
  90. package/src/tools/editTool.ts +0 -313
  91. package/src/tools/enterPlanMode.ts +0 -124
  92. package/src/tools/enterWorktreeTool.ts +0 -190
  93. package/src/tools/exitPlanMode.ts +0 -139
  94. package/src/tools/exitWorktreeTool.ts +0 -236
  95. package/src/tools/globTool.ts +0 -167
  96. package/src/tools/grepTool.ts +0 -399
  97. package/src/tools/lspTool.ts +0 -883
  98. package/src/tools/readTool.ts +0 -426
  99. package/src/tools/skillTool.ts +0 -248
  100. package/src/tools/taskManagementTools.ts +0 -574
  101. package/src/tools/taskStopTool.ts +0 -78
  102. package/src/tools/types.ts +0 -137
  103. package/src/tools/webFetchTool.ts +0 -373
  104. package/src/tools/workflowTool.ts +0 -205
  105. package/src/tools/writeTool.ts +0 -267
  106. package/src/types/agent.ts +0 -128
  107. package/src/types/auth.ts +0 -19
  108. package/src/types/commands.ts +0 -30
  109. package/src/types/config.ts +0 -43
  110. package/src/types/configuration.ts +0 -168
  111. package/src/types/core.ts +0 -105
  112. package/src/types/cron.ts +0 -13
  113. package/src/types/environment.ts +0 -106
  114. package/src/types/fileSearch.ts +0 -4
  115. package/src/types/history.ts +0 -7
  116. package/src/types/hooks.ts +0 -256
  117. package/src/types/index.ts +0 -41
  118. package/src/types/lsp.ts +0 -98
  119. package/src/types/marketplace.ts +0 -71
  120. package/src/types/mcp.ts +0 -43
  121. package/src/types/memoryRule.ts +0 -31
  122. package/src/types/messaging.ts +0 -114
  123. package/src/types/permissions.ts +0 -80
  124. package/src/types/plugins.ts +0 -39
  125. package/src/types/processes.ts +0 -99
  126. package/src/types/reversion.ts +0 -29
  127. package/src/types/session.ts +0 -12
  128. package/src/types/skills.ts +0 -108
  129. package/src/types/tasks.ts +0 -13
  130. package/src/types/telemetry.ts +0 -98
  131. package/src/types/tools.ts +0 -44
  132. package/src/types/workflow.ts +0 -6
  133. package/src/utils/abortUtils.ts +0 -118
  134. package/src/utils/atomicWrite.ts +0 -61
  135. package/src/utils/bashParser.ts +0 -899
  136. package/src/utils/cacheControlUtils.ts +0 -426
  137. package/src/utils/commandArgumentParser.ts +0 -161
  138. package/src/utils/commandPathResolver.ts +0 -88
  139. package/src/utils/configPaths.ts +0 -220
  140. package/src/utils/configValidator.ts +0 -100
  141. package/src/utils/constants.ts +0 -39
  142. package/src/utils/container.ts +0 -92
  143. package/src/utils/containerSetup.ts +0 -371
  144. package/src/utils/convertMessagesForAPI.ts +0 -326
  145. package/src/utils/cronTasks.ts +0 -128
  146. package/src/utils/cronTasksLock.ts +0 -182
  147. package/src/utils/cronToHuman.ts +0 -99
  148. package/src/utils/customCommands.ts +0 -95
  149. package/src/utils/editUtils.ts +0 -20
  150. package/src/utils/fileFormat.ts +0 -40
  151. package/src/utils/fileSearch.ts +0 -151
  152. package/src/utils/fileUtils.ts +0 -223
  153. package/src/utils/gitUtils.ts +0 -315
  154. package/src/utils/globalLogger.ts +0 -128
  155. package/src/utils/groupMessagesByApiRound.ts +0 -121
  156. package/src/utils/hookMatcher.ts +0 -176
  157. package/src/utils/markdownParser.ts +0 -317
  158. package/src/utils/mcpUtils.ts +0 -138
  159. package/src/utils/messageOperations.ts +0 -641
  160. package/src/utils/modelCapabilities.ts +0 -30
  161. package/src/utils/nameGenerator.ts +0 -99
  162. package/src/utils/notificationXml.ts +0 -57
  163. package/src/utils/openaiClient.ts +0 -251
  164. package/src/utils/parseCronExpression.ts +0 -78
  165. package/src/utils/path.ts +0 -72
  166. package/src/utils/pathEncoder.ts +0 -400
  167. package/src/utils/pathSafety.ts +0 -40
  168. package/src/utils/promptHistory.ts +0 -168
  169. package/src/utils/ripgrep.ts +0 -35
  170. package/src/utils/shellResolver.ts +0 -190
  171. package/src/utils/skillParser.ts +0 -246
  172. package/src/utils/stringUtils.ts +0 -156
  173. package/src/utils/subagentParser.ts +0 -279
  174. package/src/utils/taskReminder.ts +0 -96
  175. package/src/utils/tokenCalculation.ts +0 -43
  176. package/src/utils/tokenEstimate.ts +0 -34
  177. package/src/utils/toolResultStorage.ts +0 -117
  178. package/src/utils/worktreeSession.ts +0 -26
  179. package/src/utils/worktreeUtils.ts +0 -786
  180. package/src/workflow/budgetTracker.ts +0 -34
  181. package/src/workflow/concurrencyLimiter.ts +0 -47
  182. package/src/workflow/journal.ts +0 -95
  183. package/src/workflow/progressReporter.ts +0 -141
  184. package/src/workflow/runState.ts +0 -65
  185. package/src/workflow/scriptRuntime.ts +0 -274
  186. package/src/workflow/structuredOutput.ts +0 -123
  187. package/src/workflow/types.ts +0 -101
  188. package/src/workflow/workflowApis.ts +0 -410
  189. package/vendor/ripgrep/linux-aarch64/rg +0 -0
  190. package/vendor/ripgrep/linux-x86_64/rg +0 -0
  191. package/vendor/ripgrep/macos-aarch64/rg +0 -0
  192. package/vendor/ripgrep/macos-x86_64/rg +0 -0
  193. package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
  194. package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
@@ -1,321 +0,0 @@
1
- import { promises as fs } from "fs";
2
- import { join } from "path";
3
- import { homedir } from "os";
4
- import { EventEmitter } from "events";
5
- import { Task } from "../types/tasks.js";
6
- import { logger } from "../utils/globalLogger.js";
7
- import { Container } from "../utils/container.js";
8
- import type { MessageManager } from "../managers/messageManager.js";
9
- import type { ConfigurationService } from "./configurationService.js";
10
-
11
- function byIdAsc(a: Task, b: Task) {
12
- const aNum = parseInt(a.id, 10);
13
- const bNum = parseInt(b.id, 10);
14
- if (!isNaN(aNum) && !isNaN(bNum)) return aNum - bNum;
15
- return a.id.localeCompare(b.id);
16
- }
17
-
18
- export class TaskManager extends EventEmitter {
19
- private readonly baseDir: string;
20
- private taskListId: string;
21
-
22
- constructor(
23
- private container: Container,
24
- taskListId: string,
25
- ) {
26
- super();
27
- this.taskListId = taskListId;
28
- this.baseDir = join(homedir(), ".wave", "tasks");
29
- }
30
-
31
- public getTaskListId(): string {
32
- return this.taskListId;
33
- }
34
-
35
- public setTaskListId(taskListId: string): void {
36
- this.taskListId = taskListId;
37
- }
38
-
39
- /**
40
- * Syncs the task list ID with the current session's root session ID.
41
- * This is typically called when the session is cleared or compacted.
42
- */
43
- public async syncWithSession(): Promise<void> {
44
- const messageManager = this.container.get<MessageManager>("MessageManager");
45
- if (!messageManager) return;
46
-
47
- const rootSessionId = messageManager.getRootSessionId();
48
- // Read the per-session snapshot (not process.env) so multiple sessions in
49
- // one `wave --stdio` process don't cross-pollute this flag.
50
- const envSnap =
51
- this.container
52
- .get<ConfigurationService>("ConfigurationService")
53
- ?.getEnvSnapshot() ?? {};
54
- const pinnedTaskListId =
55
- envSnap.WAVE_TASK_LIST_ID ?? process.env.WAVE_TASK_LIST_ID;
56
- if (this.taskListId !== rootSessionId && !pinnedTaskListId) {
57
- this.setTaskListId(rootSessionId);
58
- await this.refreshTasks();
59
- }
60
- }
61
-
62
- private getSessionDir(): string {
63
- return join(this.baseDir, this.taskListId);
64
- }
65
-
66
- public getTaskPath(taskId: string): string {
67
- return join(this.getSessionDir(), `${taskId}.json`);
68
- }
69
-
70
- private getLockPath(): string {
71
- return join(this.getSessionDir(), `.lock`);
72
- }
73
-
74
- async ensureSessionDir(): Promise<void> {
75
- await fs.mkdir(this.getSessionDir(), { recursive: true });
76
- }
77
-
78
- private async withLock<T>(operation: () => Promise<T>): Promise<T> {
79
- const lockPath = this.getLockPath();
80
- let lockHandle;
81
- const maxRetries = 100;
82
- const retryDelay = process.env.NODE_ENV === "test" ? 1 : 100;
83
- const staleThreshold = 10000;
84
-
85
- await this.ensureSessionDir();
86
-
87
- for (let i = 0; i < maxRetries; i++) {
88
- try {
89
- lockHandle = await fs.open(lockPath, "wx");
90
- break;
91
- } catch (error) {
92
- const code = (error as NodeJS.ErrnoException).code;
93
-
94
- // Only EEXIST (lock held) and EPERM (Windows pending-delete window)
95
- // are transient lock-contention errors. EACCES/ENOENT are real failures
96
- // and must not be retried as lock competition.
97
- if (code !== "EEXIST" && code !== "EPERM") {
98
- throw error;
99
- }
100
-
101
- if (i === maxRetries - 1) {
102
- throw new Error(
103
- `Could not acquire lock for task list ${this.taskListId} after ${maxRetries} retries`,
104
- );
105
- }
106
-
107
- // Stale recovery: if the lock holder crashed without releasing, the
108
- // lock file remains forever. Check mtime — if older than the threshold,
109
- // remove it. Aligns with proper-lockfile's default 10s stale detection.
110
- // The lock file is empty (no PID content), so mtime is the only signal.
111
- if (
112
- code === "EEXIST" &&
113
- (await this.isLockStale(lockPath, staleThreshold))
114
- ) {
115
- logger.warn(
116
- `TaskManager: removing stale lock for task list ${this.taskListId}`,
117
- );
118
- try {
119
- await fs.unlink(lockPath);
120
- } catch {
121
- // Another waiter may have already removed it — retry anyway
122
- }
123
- continue;
124
- }
125
-
126
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
127
- }
128
- }
129
-
130
- try {
131
- return await operation();
132
- } finally {
133
- if (lockHandle) {
134
- await lockHandle.close();
135
- }
136
- try {
137
- await fs.unlink(lockPath);
138
- } catch (error) {
139
- logger.error(
140
- `Failed to release lock for task list ${this.taskListId}:`,
141
- error,
142
- );
143
- }
144
- }
145
- }
146
-
147
- private async isLockStale(
148
- lockPath: string,
149
- threshold: number,
150
- ): Promise<boolean> {
151
- try {
152
- const stats = await fs.stat(lockPath);
153
- return Date.now() - stats.mtimeMs > threshold;
154
- } catch {
155
- // Lock was removed between our EEXIST and stat — not stale, just retry
156
- return false;
157
- }
158
- }
159
-
160
- private validateTask(task: Task): void {
161
- if (!task.id || typeof task.id !== "string")
162
- throw new Error("Invalid task ID");
163
- if (!task.subject || typeof task.subject !== "string")
164
- throw new Error("Invalid task subject");
165
- if (!task.description || typeof task.description !== "string")
166
- throw new Error("Invalid task description");
167
- if (
168
- !task.status ||
169
- !["pending", "in_progress", "completed", "deleted"].includes(task.status)
170
- ) {
171
- throw new Error(`Invalid task status: ${task.status}`);
172
- }
173
- }
174
-
175
- async createTask(task: Omit<Task, "id">): Promise<string> {
176
- return await this.withLock(async () => {
177
- const taskId = await this.getNextTaskId();
178
- const fullTask: Task = { ...task, id: taskId };
179
- this.validateTask(fullTask);
180
- const taskPath = this.getTaskPath(taskId);
181
- const content = JSON.stringify(fullTask, null, 2);
182
- await fs.writeFile(taskPath, content, "utf8");
183
- this.emit("tasksChange", this.taskListId);
184
- logger.debug(`Task ${taskId} created in task list ${this.taskListId}`);
185
- return taskId;
186
- });
187
- }
188
-
189
- async getTask(taskId: string): Promise<Task | null> {
190
- const taskPath = this.getTaskPath(taskId);
191
- try {
192
- const content = await fs.readFile(taskPath, "utf8");
193
- try {
194
- return JSON.parse(content.trim()) as Task;
195
- } catch (parseError) {
196
- logger.error(`Failed to parse task file ${taskPath}:`, parseError);
197
- logger.error(`Corrupted content: ${content}`);
198
- throw parseError;
199
- }
200
- } catch (error) {
201
- if ((error as NodeJS.ErrnoException).code === "ENOENT") {
202
- return null;
203
- }
204
- throw error;
205
- }
206
- }
207
-
208
- async updateTask(task: Task): Promise<void> {
209
- this.validateTask(task);
210
- await this.withLock(async () => {
211
- const taskPath = this.getTaskPath(task.id);
212
- const content = JSON.stringify(task, null, 2);
213
- await fs.writeFile(taskPath, content, "utf8");
214
- this.emit("tasksChange", this.taskListId);
215
- logger.debug(`Task ${task.id} updated in task list ${this.taskListId}`);
216
- });
217
- }
218
-
219
- async deleteTask(taskId: string): Promise<void> {
220
- await this.withLock(async () => {
221
- const taskPath = this.getTaskPath(taskId);
222
- try {
223
- await fs.unlink(taskPath);
224
- this.emit("tasksChange", this.taskListId);
225
- logger.debug(
226
- `Task ${taskId} deleted from task list ${this.taskListId}`,
227
- );
228
- } catch (error) {
229
- if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
230
- throw error;
231
- }
232
- }
233
- });
234
- }
235
-
236
- async cleanupOldTaskLists(days: number = 30): Promise<void> {
237
- const threshold = Date.now() - days * 24 * 60 * 60 * 1000;
238
- try {
239
- const dirs = await fs.readdir(this.baseDir);
240
- for (const dir of dirs) {
241
- if (dir === this.taskListId) continue;
242
-
243
- const dirPath = join(this.baseDir, dir);
244
- const stats = await fs.stat(dirPath);
245
- if (!stats.isDirectory()) continue;
246
-
247
- // Check mtime of the directory and its contents
248
- let latestMtime = stats.mtimeMs;
249
- const files = await fs.readdir(dirPath);
250
- for (const file of files) {
251
- const filePath = join(dirPath, file);
252
- const fileStats = await fs.stat(filePath);
253
- if (fileStats.mtimeMs > latestMtime) {
254
- latestMtime = fileStats.mtimeMs;
255
- }
256
- }
257
-
258
- if (latestMtime < threshold) {
259
- logger.info(`Cleaning up old task list directory: ${dirPath}`);
260
- await fs.rm(dirPath, { recursive: true, force: true });
261
- }
262
- }
263
- } catch (error) {
264
- if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
265
- logger.error("Failed to cleanup old task lists:", error);
266
- }
267
- }
268
- }
269
-
270
- async listTasks(): Promise<Task[]> {
271
- const sessionDir = this.getSessionDir();
272
- try {
273
- const files = await fs.readdir(sessionDir);
274
- const taskFiles = files.filter((f) => f.endsWith(".json"));
275
-
276
- const tasks = await Promise.all(
277
- taskFiles.map(async (file) => {
278
- const taskPath = join(sessionDir, file);
279
- try {
280
- const content = await fs.readFile(taskPath, "utf8");
281
- return JSON.parse(content.trim()) as Task;
282
- } catch (error) {
283
- logger.error(
284
- `Failed to read or parse task file ${taskPath}:`,
285
- error,
286
- );
287
- return null;
288
- }
289
- }),
290
- );
291
-
292
- return tasks.filter((t): t is Task => t !== null).sort(byIdAsc);
293
- } catch (error) {
294
- if ((error as NodeJS.ErrnoException).code === "ENOENT") {
295
- return [];
296
- }
297
- throw error;
298
- }
299
- }
300
-
301
- async getNextTaskId(): Promise<string> {
302
- const tasks = await this.listTasks();
303
- if (tasks.length === 0) {
304
- return "1";
305
- }
306
- const ids = tasks.map((t) => parseInt(t.id, 10)).filter((id) => !isNaN(id));
307
-
308
- if (ids.length === 0) {
309
- return (tasks.length + 1).toString();
310
- }
311
-
312
- return (Math.max(...ids) + 1).toString();
313
- }
314
-
315
- /**
316
- * Refreshes the task list by re-reading tasks from disk and emitting a change event.
317
- */
318
- public async refreshTasks(): Promise<void> {
319
- this.emit("tasksChange", this.taskListId);
320
- }
321
- }
@@ -1,65 +0,0 @@
1
- /**
2
- * OpenTelemetry Event Logging
3
- *
4
- * Provides the `logOTelEvent` API for structured session lifecycle events
5
- * with PII gates.
6
- */
7
-
8
- import type { OTelEventName } from "../types/telemetry.js";
9
- import {
10
- isInitialized,
11
- getCurrentConfig,
12
- getTelemetryAttributes,
13
- } from "./instrumentation.js";
14
-
15
- interface OTelLogger {
16
- emit: (logRecord: {
17
- body?: unknown;
18
- attributes?: Record<string, unknown>;
19
- }) => void;
20
- }
21
-
22
- let cachedLogger: OTelLogger | undefined;
23
-
24
- async function getOTelLogger(): Promise<OTelLogger | undefined> {
25
- if (cachedLogger) return cachedLogger;
26
- try {
27
- const { logs } = await import("@opentelemetry/api-logs");
28
- cachedLogger = logs.getLogger("wave") as OTelLogger;
29
- return cachedLogger;
30
- } catch {
31
- return undefined;
32
- }
33
- }
34
-
35
- /**
36
- * Logs a structured event via the OTEL logs API. Respects PII gates.
37
- */
38
- export async function logOTelEvent(
39
- eventName: OTelEventName,
40
- metadata: Record<string, string | undefined>,
41
- ): Promise<void> {
42
- if (!isInitialized()) return;
43
-
44
- const log = await getOTelLogger();
45
- if (!log) return;
46
-
47
- // PII gate: strip prompt text if logUserPrompts is false
48
- const attributes: Record<string, string> = {};
49
- const config = getCurrentConfig();
50
-
51
- for (const [key, value] of Object.entries(metadata)) {
52
- if (value === undefined) continue;
53
- if (key === "prompt" && !config?.logUserPrompts) continue;
54
- attributes[key] = value;
55
- }
56
-
57
- log.emit({
58
- body: eventName,
59
- attributes: {
60
- "event.name": eventName,
61
- ...getTelemetryAttributes(),
62
- ...attributes,
63
- },
64
- });
65
- }