wave-agent-sdk 0.0.4 → 0.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 (155) hide show
  1. package/dist/agent.d.ts +63 -9
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +103 -27
  4. package/dist/index.d.ts +3 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +3 -3
  7. package/dist/managers/aiManager.d.ts +5 -2
  8. package/dist/managers/aiManager.d.ts.map +1 -1
  9. package/dist/managers/aiManager.js +121 -53
  10. package/dist/managers/backgroundBashManager.d.ts +1 -1
  11. package/dist/managers/backgroundBashManager.d.ts.map +1 -1
  12. package/dist/{hooks/manager.d.ts → managers/hookManager.d.ts} +26 -7
  13. package/dist/managers/hookManager.d.ts.map +1 -0
  14. package/dist/{hooks/manager.js → managers/hookManager.js} +108 -18
  15. package/dist/managers/mcpManager.d.ts +1 -1
  16. package/dist/managers/mcpManager.d.ts.map +1 -1
  17. package/dist/managers/mcpManager.js +5 -5
  18. package/dist/managers/messageManager.d.ts +29 -5
  19. package/dist/managers/messageManager.d.ts.map +1 -1
  20. package/dist/managers/messageManager.js +33 -12
  21. package/dist/managers/skillManager.d.ts +1 -1
  22. package/dist/managers/skillManager.d.ts.map +1 -1
  23. package/dist/managers/skillManager.js +3 -3
  24. package/dist/managers/slashCommandManager.d.ts +1 -1
  25. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  26. package/dist/managers/slashCommandManager.js +1 -1
  27. package/dist/managers/subagentManager.d.ts +9 -12
  28. package/dist/managers/subagentManager.d.ts.map +1 -1
  29. package/dist/managers/subagentManager.js +43 -45
  30. package/dist/managers/toolManager.d.ts +1 -1
  31. package/dist/managers/toolManager.d.ts.map +1 -1
  32. package/dist/services/aiService.d.ts +10 -2
  33. package/dist/services/aiService.d.ts.map +1 -1
  34. package/dist/services/aiService.js +25 -4
  35. package/dist/services/hook.d.ts +56 -0
  36. package/dist/services/hook.d.ts.map +1 -0
  37. package/dist/services/hook.js +276 -0
  38. package/dist/services/memory.js +3 -3
  39. package/dist/services/session.d.ts +65 -16
  40. package/dist/services/session.d.ts.map +1 -1
  41. package/dist/services/session.js +85 -34
  42. package/dist/tools/bashTool.js +2 -2
  43. package/dist/tools/deleteFileTool.js +1 -1
  44. package/dist/tools/editTool.js +1 -1
  45. package/dist/tools/multiEditTool.js +2 -2
  46. package/dist/tools/taskTool.d.ts.map +1 -1
  47. package/dist/tools/taskTool.js +7 -3
  48. package/dist/tools/writeTool.js +1 -1
  49. package/dist/types/commands.d.ts +24 -0
  50. package/dist/types/commands.d.ts.map +1 -0
  51. package/dist/types/commands.js +5 -0
  52. package/dist/types/config.d.ts +13 -0
  53. package/dist/types/config.d.ts.map +1 -0
  54. package/dist/types/config.js +5 -0
  55. package/dist/types/core.d.ts +38 -0
  56. package/dist/types/core.d.ts.map +1 -0
  57. package/dist/{types.js → types/core.js} +4 -13
  58. package/dist/{hooks/types.d.ts → types/hooks.d.ts} +2 -1
  59. package/dist/types/hooks.d.ts.map +1 -0
  60. package/dist/types/index.d.ts +20 -0
  61. package/dist/types/index.d.ts.map +1 -0
  62. package/dist/types/index.js +21 -0
  63. package/dist/types/mcp.d.ts +28 -0
  64. package/dist/types/mcp.d.ts.map +1 -0
  65. package/dist/types/mcp.js +5 -0
  66. package/dist/types/messaging.d.ts +80 -0
  67. package/dist/types/messaging.d.ts.map +1 -0
  68. package/dist/types/messaging.js +5 -0
  69. package/dist/types/processes.d.ts +17 -0
  70. package/dist/types/processes.d.ts.map +1 -0
  71. package/dist/types/processes.js +5 -0
  72. package/dist/types/skills.d.ts +78 -0
  73. package/dist/types/skills.d.ts.map +1 -0
  74. package/dist/types/skills.js +17 -0
  75. package/dist/utils/configResolver.d.ts +1 -1
  76. package/dist/utils/configResolver.d.ts.map +1 -1
  77. package/dist/utils/configResolver.js +1 -1
  78. package/dist/utils/configValidator.d.ts +1 -1
  79. package/dist/utils/configValidator.d.ts.map +1 -1
  80. package/dist/utils/configValidator.js +1 -1
  81. package/dist/utils/convertMessagesForAPI.d.ts +1 -1
  82. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  83. package/dist/utils/customCommands.d.ts +1 -1
  84. package/dist/utils/customCommands.d.ts.map +1 -1
  85. package/dist/{hooks/matcher.d.ts → utils/hookMatcher.d.ts} +1 -1
  86. package/dist/utils/hookMatcher.d.ts.map +1 -0
  87. package/dist/utils/markdownParser.d.ts +1 -1
  88. package/dist/utils/markdownParser.d.ts.map +1 -1
  89. package/dist/utils/mcpUtils.d.ts +1 -1
  90. package/dist/utils/mcpUtils.d.ts.map +1 -1
  91. package/dist/utils/messageOperations.d.ts +7 -2
  92. package/dist/utils/messageOperations.d.ts.map +1 -1
  93. package/dist/utils/messageOperations.js +18 -1
  94. package/dist/utils/skillParser.d.ts +1 -1
  95. package/dist/utils/skillParser.d.ts.map +1 -1
  96. package/package.json +1 -1
  97. package/src/agent.ts +150 -50
  98. package/src/index.ts +3 -4
  99. package/src/managers/aiManager.ts +282 -164
  100. package/src/managers/backgroundBashManager.ts +1 -1
  101. package/src/{hooks/manager.ts → managers/hookManager.ts} +163 -28
  102. package/src/managers/mcpManager.ts +6 -6
  103. package/src/managers/messageManager.ts +69 -10
  104. package/src/managers/skillManager.ts +4 -4
  105. package/src/managers/slashCommandManager.ts +6 -2
  106. package/src/managers/subagentManager.ts +58 -53
  107. package/src/managers/toolManager.ts +1 -1
  108. package/src/services/aiService.ts +37 -7
  109. package/src/services/hook.ts +360 -0
  110. package/src/services/memory.ts +3 -3
  111. package/src/services/session.ts +99 -33
  112. package/src/tools/bashTool.ts +2 -2
  113. package/src/tools/deleteFileTool.ts +1 -1
  114. package/src/tools/editTool.ts +1 -1
  115. package/src/tools/multiEditTool.ts +2 -2
  116. package/src/tools/taskTool.ts +13 -5
  117. package/src/tools/writeTool.ts +1 -1
  118. package/src/types/commands.ts +26 -0
  119. package/src/types/config.ts +14 -0
  120. package/src/types/core.ts +49 -0
  121. package/src/{hooks/types.ts → types/hooks.ts} +1 -0
  122. package/src/types/index.ts +23 -0
  123. package/src/{types.ts → types/index.ts.backup} +13 -0
  124. package/src/types/mcp.ts +31 -0
  125. package/src/types/messaging.ts +103 -0
  126. package/src/types/processes.ts +18 -0
  127. package/src/types/skills.ts +91 -0
  128. package/src/utils/configResolver.ts +1 -1
  129. package/src/utils/configValidator.ts +5 -1
  130. package/src/utils/convertMessagesForAPI.ts +1 -1
  131. package/src/utils/customCommands.ts +1 -1
  132. package/src/utils/markdownParser.ts +1 -1
  133. package/src/utils/mcpUtils.ts +1 -1
  134. package/src/utils/messageOperations.ts +22 -1
  135. package/src/utils/skillParser.ts +1 -1
  136. package/dist/hooks/executor.d.ts +0 -56
  137. package/dist/hooks/executor.d.ts.map +0 -1
  138. package/dist/hooks/executor.js +0 -312
  139. package/dist/hooks/index.d.ts +0 -17
  140. package/dist/hooks/index.d.ts.map +0 -1
  141. package/dist/hooks/index.js +0 -14
  142. package/dist/hooks/manager.d.ts.map +0 -1
  143. package/dist/hooks/matcher.d.ts.map +0 -1
  144. package/dist/hooks/settings.d.ts +0 -46
  145. package/dist/hooks/settings.d.ts.map +0 -1
  146. package/dist/hooks/settings.js +0 -100
  147. package/dist/hooks/types.d.ts.map +0 -1
  148. package/dist/types.d.ts +0 -276
  149. package/dist/types.d.ts.map +0 -1
  150. package/src/hooks/executor.ts +0 -440
  151. package/src/hooks/index.ts +0 -52
  152. package/src/hooks/settings.ts +0 -129
  153. /package/dist/{hooks/types.js → types/hooks.js} +0 -0
  154. /package/dist/{hooks/matcher.js → utils/hookMatcher.js} +0 -0
  155. /package/src/{hooks/matcher.ts → utils/hookMatcher.ts} +0 -0
package/src/agent.ts CHANGED
@@ -13,15 +13,16 @@ import {
13
13
  type BackgroundBashManagerCallbacks,
14
14
  } from "./managers/backgroundBashManager.js";
15
15
  import { SlashCommandManager } from "./managers/slashCommandManager.js";
16
- import type { SlashCommand, CustomSlashCommand } from "./types.js";
16
+ import type { SlashCommand, CustomSlashCommand } from "./types/index.js";
17
17
  import type {
18
18
  Message,
19
19
  Logger,
20
20
  McpServerStatus,
21
21
  GatewayConfig,
22
22
  ModelConfig,
23
- } from "./types.js";
24
- import { HookManager } from "./hooks/index.js";
23
+ Usage,
24
+ } from "./types/index.js";
25
+ import { HookManager } from "./managers/hookManager.js";
25
26
  import { configResolver } from "./utils/configResolver.js";
26
27
  import { configValidator } from "./utils/configValidator.js";
27
28
  import { SkillManager } from "./managers/skillManager.js";
@@ -51,6 +52,14 @@ export interface AgentOptions {
51
52
  workdir?: string;
52
53
  /**Optional custom system prompt - if provided, replaces default system prompt */
53
54
  systemPrompt?: string;
55
+
56
+ // New: Session directory configuration
57
+ /**
58
+ * Optional custom directory for session file storage
59
+ * @default join(homedir(), ".wave", "sessions")
60
+ * @example "/path/to/custom/sessions"
61
+ */
62
+ sessionDir?: string;
54
63
  }
55
64
 
56
65
  export interface AgentCallbacks
@@ -72,6 +81,7 @@ export class Agent {
72
81
  private hookManager: HookManager; // Add hooks manager instance
73
82
  private workdir: string; // Working directory
74
83
  private systemPrompt?: string; // Custom system prompt
84
+ private _usages: Usage[] = []; // Usage tracking array
75
85
 
76
86
  // Configuration properties
77
87
  private gatewayConfig: GatewayConfig;
@@ -81,13 +91,21 @@ export class Agent {
81
91
  /**
82
92
  * Agent constructor - handles configuration resolution and validation
83
93
  *
84
- * IMPORTANT: Keep this constructor's signature exactly the same as Agent.create()
85
- * to maintain API consistency. Both methods should accept the same AgentOptions.
94
+ * IMPORTANT: This constructor is private. Use Agent.create() instead for proper
95
+ * async initialization. Keep this constructor's signature exactly the same as
96
+ * Agent.create() to maintain API consistency.
86
97
  *
87
98
  * @param options - Configuration options for the Agent instance
99
+ * @param options.sessionDir - Optional custom directory for session storage
88
100
  */
89
- constructor(options: AgentOptions) {
90
- const { callbacks = {}, logger, workdir, systemPrompt } = options;
101
+ private constructor(options: AgentOptions) {
102
+ const {
103
+ callbacks = {},
104
+ logger,
105
+ workdir,
106
+ systemPrompt,
107
+ sessionDir,
108
+ } = options;
91
109
 
92
110
  // Resolve configuration from constructor args and environment variables
93
111
  const gatewayConfig = configResolver.resolveGatewayConfig(
@@ -127,18 +145,14 @@ export class Agent {
127
145
  logger: this.logger,
128
146
  }); // Initialize tool registry, pass MCP manager
129
147
 
130
- this.hookManager = new HookManager(
131
- this.workdir,
132
- undefined,
133
- undefined,
134
- this.logger,
135
- ); // Initialize hooks manager
148
+ this.hookManager = new HookManager(this.workdir, undefined, this.logger); // Initialize hooks manager
136
149
 
137
150
  // Initialize MessageManager
138
151
  this.messageManager = new MessageManager({
139
152
  callbacks,
140
153
  workdir: this.workdir,
141
154
  logger: this.logger,
155
+ sessionDir,
142
156
  });
143
157
 
144
158
  // Initialize subagent manager with all dependencies in constructor
@@ -151,6 +165,7 @@ export class Agent {
151
165
  gatewayConfig,
152
166
  modelConfig,
153
167
  tokenLimit,
168
+ onUsageAdded: (usage) => this.addUsage(usage),
154
169
  });
155
170
 
156
171
  // Initialize AI manager with resolved configuration
@@ -160,7 +175,12 @@ export class Agent {
160
175
  logger: this.logger,
161
176
  backgroundBashManager: this.backgroundBashManager,
162
177
  hookManager: this.hookManager,
163
- callbacks,
178
+ callbacks: {
179
+ ...callbacks,
180
+ onUsageAdded: (usage: Usage) => {
181
+ this.addUsage(usage);
182
+ },
183
+ },
164
184
  workdir: this.workdir,
165
185
  systemPrompt: this.systemPrompt,
166
186
  gatewayConfig: this.gatewayConfig,
@@ -192,6 +212,38 @@ export class Agent {
192
212
  return this.messageManager.getMessages();
193
213
  }
194
214
 
215
+ public get usages(): Usage[] {
216
+ return [...this._usages]; // Return copy to prevent external modification
217
+ }
218
+
219
+ public get sessionFilePath(): string {
220
+ return this.messageManager.getTranscriptPath();
221
+ }
222
+
223
+ /**
224
+ * Rebuild usage array from messages containing usage metadata
225
+ * Called during session restoration to reconstruct usage tracking
226
+ */
227
+ private rebuildUsageFromMessages(): void {
228
+ this._usages = [];
229
+ this.messages.forEach((message) => {
230
+ if (message.role === "assistant" && message.usage) {
231
+ this._usages.push(message.usage);
232
+ }
233
+ });
234
+ // Trigger callback after rebuilding usage array
235
+ this.messageManager.triggerUsageChange();
236
+ }
237
+
238
+ /**
239
+ * Add usage data to the tracking array and trigger callbacks
240
+ * @param usage Usage data from AI operations
241
+ */
242
+ private addUsage(usage: Usage): void {
243
+ this._usages.push(usage);
244
+ this.messageManager.triggerUsageChange();
245
+ }
246
+
195
247
  public get latestTotalTokens(): number {
196
248
  return this.messageManager.getlatestTotalTokens();
197
249
  }
@@ -242,6 +294,43 @@ export class Agent {
242
294
  * @param options - Same AgentOptions interface used by constructor
243
295
  * @returns Promise<Agent> - Fully initialized Agent instance
244
296
  */
297
+ /**
298
+ * Create a new Agent instance with async initialization
299
+ *
300
+ * This is the recommended way to create Agent instances. The constructor is private
301
+ * to ensure proper async initialization of all components.
302
+ *
303
+ * @param options - Configuration options for the Agent instance
304
+ * @param options.apiKey - API key for the AI service (or set WAVE_API_KEY env var)
305
+ * @param options.baseURL - Base URL for the AI service (or set WAVE_BASE_URL env var)
306
+ * @param options.sessionDir - Optional custom directory for session file storage.
307
+ * If not provided, defaults to ~/.wave/sessions/. Can be relative or absolute path.
308
+ * Examples: "./app-sessions", "/var/myapp/sessions", "~/Documents/sessions"
309
+ * @param options.callbacks - Optional callbacks for various Agent events
310
+ * @param options.restoreSessionId - Optional session ID to restore from
311
+ * @param options.continueLastSession - Whether to continue the last session automatically
312
+ * @param options.logger - Optional custom logger implementation
313
+ * @param options.messages - Optional initial messages for testing convenience
314
+ * @param options.workdir - Working directory (defaults to process.cwd())
315
+ * @param options.systemPrompt - Optional custom system prompt
316
+ * @returns Promise that resolves to initialized Agent instance
317
+ *
318
+ * @example
319
+ * ```typescript
320
+ * // Basic usage with default session directory
321
+ * const agent = await Agent.create({
322
+ * apiKey: 'your-api-key',
323
+ * baseURL: 'https://api.example.com'
324
+ * });
325
+ *
326
+ * // Custom session directory
327
+ * const agent = await Agent.create({
328
+ * apiKey: 'your-api-key',
329
+ * baseURL: 'https://api.example.com',
330
+ * sessionDir: './app-sessions'
331
+ * });
332
+ * ```
333
+ */
245
334
  static async create(options: AgentOptions): Promise<Agent> {
246
335
  // Create Agent instance - configuration resolution and validation now happens in constructor
247
336
  const instance = new Agent(options);
@@ -289,7 +378,7 @@ export class Agent {
289
378
  // Initialize hooks configuration
290
379
  try {
291
380
  // Load hooks configuration from user and project settings
292
- this.logger?.info("Loading hooks configuration...");
381
+ this.logger?.debug("Loading hooks configuration...");
293
382
  this.hookManager.loadConfigurationFromSettings();
294
383
  this.logger?.debug("Hooks system initialized successfully");
295
384
  } catch (error) {
@@ -301,12 +390,16 @@ export class Agent {
301
390
  if (options?.messages) {
302
391
  // If messages are provided, use them directly (useful for testing)
303
392
  this.messageManager.setMessages(options.messages);
393
+ // Rebuild usage array from restored messages
394
+ this.rebuildUsageFromMessages();
304
395
  } else {
305
396
  // Otherwise, handle session restoration
306
397
  await this.messageManager.handleSessionRestoration(
307
398
  options?.restoreSessionId,
308
399
  options?.continueLastSession,
309
400
  );
401
+ // Rebuild usage array from restored messages
402
+ this.rebuildUsageFromMessages();
310
403
  }
311
404
  }
312
405
 
@@ -328,10 +421,9 @@ export class Agent {
328
421
 
329
422
  /** Unified interrupt method, interrupts both AI messages and command execution */
330
423
  public abortMessage(): void {
331
- this.abortAIMessage();
424
+ this.abortAIMessage(); // This will abort tools including Task tool (subagents)
332
425
  this.abortBashCommand();
333
426
  this.abortSlashCommand();
334
- this.abortSubagents();
335
427
  }
336
428
 
337
429
  /** Add to input history */
@@ -349,23 +441,12 @@ export class Agent {
349
441
  this.slashCommandManager.abortCurrentCommand();
350
442
  }
351
443
 
352
- /** Interrupt all subagent execution */
353
- public abortSubagents(): void {
354
- this.subagentManager.abortAllInstances();
355
- }
356
-
357
- /** Interrupt specific subagent execution */
358
- public abortSubagent(subagentId: string): boolean {
359
- return this.subagentManager.abortInstance(subagentId);
360
- }
361
-
362
444
  /** Destroy managers, clean up resources */
363
445
  public async destroy(): Promise<void> {
364
- this.messageManager.saveSession();
365
- this.abortAIMessage();
446
+ await this.messageManager.saveSession();
447
+ this.abortAIMessage(); // This will abort tools including Task tool (subagents)
366
448
  this.abortBashCommand();
367
449
  this.abortSlashCommand();
368
- this.abortSubagents();
369
450
  // Cleanup background bash manager
370
451
  this.backgroundBashManager.cleanup();
371
452
  // Cleanup MCP connections
@@ -405,26 +486,7 @@ export class Agent {
405
486
  // Add user message to history
406
487
  this.addToInputHistory(content);
407
488
 
408
- // Execute UserPromptSubmit hooks before processing the prompt
409
- if (this.hookManager) {
410
- try {
411
- await this.hookManager.executeHooks("UserPromptSubmit", {
412
- event: "UserPromptSubmit",
413
- projectDir: this.workdir,
414
- timestamp: new Date(),
415
- // UserPromptSubmit doesn't need toolName
416
- sessionId: this.sessionId,
417
- transcriptPath: this.messageManager.getTranscriptPath(),
418
- cwd: this.workdir,
419
- userPrompt: content,
420
- });
421
- } catch (error) {
422
- this.logger?.warn("UserPromptSubmit hooks execution failed:", error);
423
- // Continue processing even if hooks fail
424
- }
425
- }
426
-
427
- // Add user message, will automatically sync to UI
489
+ // Add user message first, will automatically sync to UI
428
490
  this.messageManager.addUserMessage(
429
491
  content,
430
492
  images?.map((img) => ({
@@ -433,6 +495,44 @@ export class Agent {
433
495
  })),
434
496
  );
435
497
 
498
+ // Execute UserPromptSubmit hooks after adding the user message
499
+ if (this.hookManager) {
500
+ try {
501
+ const hookResults = await this.hookManager.executeHooks(
502
+ "UserPromptSubmit",
503
+ {
504
+ event: "UserPromptSubmit",
505
+ projectDir: this.workdir,
506
+ timestamp: new Date(),
507
+ // UserPromptSubmit doesn't need toolName
508
+ sessionId: this.sessionId,
509
+ transcriptPath: this.messageManager.getTranscriptPath(),
510
+ cwd: this.workdir,
511
+ userPrompt: content,
512
+ },
513
+ );
514
+
515
+ // Process hook results and determine if we should continue
516
+ const processResult = this.hookManager.processHookResults(
517
+ "UserPromptSubmit",
518
+ hookResults,
519
+ this.messageManager,
520
+ );
521
+
522
+ // If hook processing indicates we should block (exit code 2), stop here
523
+ if (processResult.shouldBlock) {
524
+ this.logger?.info(
525
+ "UserPromptSubmit hook blocked prompt processing with error:",
526
+ processResult.errorMessage,
527
+ );
528
+ return; // Don't send to AI
529
+ }
530
+ } catch (error) {
531
+ this.logger?.warn("UserPromptSubmit hooks execution failed:", error);
532
+ // Continue processing even if hooks fail
533
+ }
534
+ }
535
+
436
536
  // Send AI message
437
537
  await this.aiManager.sendAIMessage();
438
538
  } catch (error) {
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  export * from "./services/aiService.js";
3
3
  export * from "./services/memory.js";
4
4
  export * from "./services/session.js";
5
+ export * from "./services/hook.js";
5
6
 
6
7
  // Export main agent
7
8
  export * from "./agent.js";
@@ -15,9 +16,7 @@ export * from "./utils/messageOperations.js";
15
16
  export * from "./utils/path.js";
16
17
  export * from "./utils/stringUtils.js";
17
18
  export * from "./utils/customCommands.js";
18
-
19
- // Export hooks system
20
- export * from "./hooks/index.js";
19
+ export * from "./utils/hookMatcher.js";
21
20
 
22
21
  // Export types
23
- export * from "./types.js";
22
+ export * from "./types/index.js";