wave-agent-sdk 0.14.0 → 0.14.2

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 (88) hide show
  1. package/builtin/skills/settings/HOOKS.md +69 -0
  2. package/builtin/skills/settings/PLUGINS.md +171 -0
  3. package/builtin/skills/settings/SKILL.md +8 -3
  4. package/dist/agent.d.ts +2 -2
  5. package/dist/agent.d.ts.map +1 -1
  6. package/dist/agent.js +12 -3
  7. package/dist/core/plugin.d.ts +2 -2
  8. package/dist/core/plugin.d.ts.map +1 -1
  9. package/dist/core/plugin.js +7 -7
  10. package/dist/managers/aiManager.d.ts +6 -6
  11. package/dist/managers/aiManager.d.ts.map +1 -1
  12. package/dist/managers/aiManager.js +122 -59
  13. package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
  14. package/dist/managers/backgroundTaskManager.js +28 -30
  15. package/dist/managers/hookManager.d.ts +16 -1
  16. package/dist/managers/hookManager.d.ts.map +1 -1
  17. package/dist/managers/hookManager.js +97 -8
  18. package/dist/managers/messageManager.d.ts +19 -4
  19. package/dist/managers/messageManager.d.ts.map +1 -1
  20. package/dist/managers/messageManager.js +63 -18
  21. package/dist/managers/pluginManager.d.ts.map +1 -1
  22. package/dist/managers/pluginManager.js +1 -1
  23. package/dist/prompts/index.d.ts +1 -1
  24. package/dist/prompts/index.d.ts.map +1 -1
  25. package/dist/prompts/index.js +1 -1
  26. package/dist/services/MarketplaceService.d.ts +42 -12
  27. package/dist/services/MarketplaceService.d.ts.map +1 -1
  28. package/dist/services/MarketplaceService.js +225 -105
  29. package/dist/services/aiService.d.ts +3 -3
  30. package/dist/services/aiService.d.ts.map +1 -1
  31. package/dist/services/aiService.js +7 -7
  32. package/dist/services/configurationService.d.ts +17 -1
  33. package/dist/services/configurationService.d.ts.map +1 -1
  34. package/dist/services/configurationService.js +104 -0
  35. package/dist/services/hook.d.ts.map +1 -1
  36. package/dist/services/hook.js +15 -0
  37. package/dist/services/initializationService.d.ts.map +1 -1
  38. package/dist/services/initializationService.js +24 -1
  39. package/dist/services/interactionService.js +1 -1
  40. package/dist/services/pluginLoader.d.ts.map +1 -1
  41. package/dist/services/pluginLoader.js +7 -1
  42. package/dist/services/session.d.ts +1 -1
  43. package/dist/services/session.js +7 -7
  44. package/dist/services/taskManager.d.ts +1 -1
  45. package/dist/services/taskManager.js +1 -1
  46. package/dist/types/configuration.d.ts +7 -0
  47. package/dist/types/configuration.d.ts.map +1 -1
  48. package/dist/types/core.d.ts +1 -1
  49. package/dist/types/core.d.ts.map +1 -1
  50. package/dist/types/hooks.d.ts +9 -1
  51. package/dist/types/hooks.d.ts.map +1 -1
  52. package/dist/types/hooks.js +2 -0
  53. package/dist/types/marketplace.d.ts +2 -0
  54. package/dist/types/marketplace.d.ts.map +1 -1
  55. package/dist/types/messaging.d.ts +3 -3
  56. package/dist/types/messaging.d.ts.map +1 -1
  57. package/dist/utils/convertMessagesForAPI.d.ts +1 -1
  58. package/dist/utils/convertMessagesForAPI.js +7 -7
  59. package/dist/utils/groupMessagesByApiRound.d.ts +1 -1
  60. package/dist/utils/groupMessagesByApiRound.js +6 -6
  61. package/dist/utils/messageOperations.d.ts.map +1 -1
  62. package/dist/utils/messageOperations.js +3 -3
  63. package/package.json +1 -1
  64. package/src/agent.ts +16 -3
  65. package/src/core/plugin.ts +13 -7
  66. package/src/managers/aiManager.ts +142 -63
  67. package/src/managers/backgroundTaskManager.ts +33 -42
  68. package/src/managers/hookManager.ts +125 -10
  69. package/src/managers/messageManager.ts +76 -22
  70. package/src/managers/pluginManager.ts +4 -1
  71. package/src/prompts/index.ts +1 -1
  72. package/src/services/MarketplaceService.ts +301 -111
  73. package/src/services/aiService.ts +11 -11
  74. package/src/services/configurationService.ts +131 -0
  75. package/src/services/hook.ts +17 -0
  76. package/src/services/initializationService.ts +33 -1
  77. package/src/services/interactionService.ts +1 -1
  78. package/src/services/pluginLoader.ts +7 -1
  79. package/src/services/session.ts +7 -7
  80. package/src/services/taskManager.ts +1 -1
  81. package/src/types/configuration.ts +8 -0
  82. package/src/types/core.ts +1 -1
  83. package/src/types/hooks.ts +16 -2
  84. package/src/types/marketplace.ts +2 -0
  85. package/src/types/messaging.ts +3 -3
  86. package/src/utils/convertMessagesForAPI.ts +8 -8
  87. package/src/utils/groupMessagesByApiRound.ts +6 -6
  88. package/src/utils/messageOperations.ts +3 -5
@@ -1 +1 @@
1
- {"version":3,"file":"messageOperations.d.ts","sourceRoot":"","sources":["../../src/utils/messageOperations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messageOperations.d.ts","sourceRoot":"","sources":["../../src/utils/messageOperations.ts"],"names":[],"mappings":"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"}
@@ -423,9 +423,9 @@ export function getMessageContent(message) {
423
423
  if (bangBlock && "command" in bangBlock) {
424
424
  return `!${bangBlock.command}`;
425
425
  }
426
- const compressBlock = message.blocks.find((block) => block.type === "compress");
427
- if (compressBlock && "content" in compressBlock) {
428
- return compressBlock.content;
426
+ const compactBlock = message.blocks.find((block) => block.type === "compact");
427
+ if (compactBlock && "content" in compactBlock) {
428
+ return compactBlock.content;
429
429
  }
430
430
  return "";
431
431
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.14.0",
3
+ "version": "0.14.2",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
package/src/agent.ts CHANGED
@@ -317,9 +317,9 @@ export class Agent {
317
317
  return this.aiManager.isLoading;
318
318
  }
319
319
 
320
- /** Get message compression status */
321
- public get isCompressing(): boolean {
322
- return this.aiManager.getIsCompressing();
320
+ /** Get message compaction status */
321
+ public get isCompacting(): boolean {
322
+ return this.aiManager.getIsCompacting();
323
323
  }
324
324
 
325
325
  /** Get bash command execution status */
@@ -633,6 +633,19 @@ export class Agent {
633
633
  this.pendingNotificationPromises = [];
634
634
  }
635
635
 
636
+ // Fire SessionEnd hooks (fire-and-forget, don't block shutdown)
637
+ try {
638
+ const sessionId = this.messageManager.getSessionId();
639
+ const transcriptPath = this.messageManager.getTranscriptPath();
640
+ await this.hookManager.executeSessionEndHooks(
641
+ "stop",
642
+ sessionId,
643
+ transcriptPath,
644
+ );
645
+ } catch (error) {
646
+ this.logger?.warn(`SessionEnd hooks failed: ${(error as Error).message}`);
647
+ }
648
+
636
649
  await this.messageManager.saveSession();
637
650
  this.abortAIMessage(); // This will abort tools including Agent tool (subagents)
638
651
  this.abortBashCommand();
@@ -30,7 +30,10 @@ export class PluginCore {
30
30
  this.workdir = workdir;
31
31
  this.container = new Container();
32
32
  this.configurationService = new ConfigurationService();
33
- this.marketplaceService = new MarketplaceService();
33
+ this.marketplaceService = new MarketplaceService(
34
+ this.workdir,
35
+ this.configurationService,
36
+ );
34
37
 
35
38
  // Wire up ConfigurationService in the container for PluginManager to use
36
39
  this.container.register("ConfigurationService", this.configurationService);
@@ -122,7 +125,7 @@ export class PluginCore {
122
125
  for (const m of marketplaces) {
123
126
  try {
124
127
  const manifest = await this.marketplaceService.loadMarketplaceManifest(
125
- this.marketplaceService.getMarketplacePath(m),
128
+ this.marketplaceService.getMarketplacePath(m.source),
126
129
  );
127
130
  manifest.plugins.forEach((p) => {
128
131
  const pluginId = `${p.name}@${m.name}`;
@@ -154,15 +157,18 @@ export class PluginCore {
154
157
  /**
155
158
  * Adds a new marketplace
156
159
  */
157
- async addMarketplace(input: string): Promise<KnownMarketplace> {
158
- return await this.marketplaceService.addMarketplace(input);
160
+ async addMarketplace(
161
+ input: string,
162
+ scope: Scope = "user",
163
+ ): Promise<KnownMarketplace> {
164
+ return await this.marketplaceService.addMarketplace(input, scope);
159
165
  }
160
166
 
161
167
  /**
162
168
  * Removes a marketplace by name
163
169
  */
164
- async removeMarketplace(name: string): Promise<void> {
165
- await this.marketplaceService.removeMarketplace(name);
170
+ async removeMarketplace(name: string, scope?: Scope): Promise<void> {
171
+ await this.marketplaceService.removeMarketplace(name, scope);
166
172
  }
167
173
 
168
174
  /**
@@ -208,7 +214,7 @@ export class PluginCore {
208
214
  * Resolves the local path for a marketplace
209
215
  */
210
216
  getMarketplacePath(marketplace: KnownMarketplace): string {
211
- return this.marketplaceService.getMarketplacePath(marketplace);
217
+ return this.marketplaceService.getMarketplacePath(marketplace.source);
212
218
  }
213
219
 
214
220
  /**
@@ -30,7 +30,7 @@ import type { NotificationQueue } from "./notificationQueue.js";
30
30
  import { logger } from "../utils/globalLogger.js";
31
31
 
32
32
  export interface AIManagerCallbacks {
33
- onCompressionStateChange?: (isCompressing: boolean) => void;
33
+ onCompactionStateChange?: (isCompacting: boolean) => void;
34
34
  onUsageAdded?: (usage: Usage) => void;
35
35
  onCwdChange?: (newCwd: string) => void;
36
36
  }
@@ -58,7 +58,7 @@ export class AIManager {
58
58
  private stream: boolean; // Streaming mode flag
59
59
  private modelOverride?: string;
60
60
  private _onCwdChange?: (newCwd: string) => void; // Store callback for CWD changes
61
- private consecutiveCompressionFailures: number = 0;
61
+ private consecutiveCompactionFailures: number = 0;
62
62
 
63
63
  // Service overrides
64
64
  constructor(
@@ -177,7 +177,7 @@ export class AIManager {
177
177
  this._onCwdChange = callback;
178
178
  }
179
179
 
180
- private isCompressing: boolean = false;
180
+ private isCompacting: boolean = false;
181
181
  private callbacks: AIManagerCallbacks;
182
182
 
183
183
  /**
@@ -253,8 +253,8 @@ export class AIManager {
253
253
  return "";
254
254
  }
255
255
 
256
- // Private method to handle token statistics and message compression
257
- private async handleTokenUsageAndCompression(
256
+ // Private method to handle token statistics and message compaction
257
+ private async handleTokenUsageAndCompaction(
258
258
  usage: Usage | undefined,
259
259
  abortController: AbortController,
260
260
  ): Promise<void> {
@@ -272,30 +272,30 @@ export class AIManager {
272
272
  this.getMaxInputTokens()
273
273
  ) {
274
274
  logger?.debug(
275
- `Token usage exceeded ${this.getMaxInputTokens()}, compressing messages...`,
275
+ `Token usage exceeded ${this.getMaxInputTokens()}, compacting messages...`,
276
276
  );
277
277
 
278
- // Check if messages need compression
279
- const messagesToCompress = this.messageManager.getMessages();
278
+ // Check if messages need compaction
279
+ const messagesToCompact = this.messageManager.getMessages();
280
280
 
281
- // If there are messages to compress, perform compression
282
- if (messagesToCompress.length > 0) {
283
- // Circuit breaker: skip compression after 3 consecutive failures
284
- if (this.consecutiveCompressionFailures >= 3) {
281
+ // If there are messages to compact, perform compaction
282
+ if (messagesToCompact.length > 0) {
283
+ // Circuit breaker: skip compaction after 3 consecutive failures
284
+ if (this.consecutiveCompactionFailures >= 3) {
285
285
  logger?.warn(
286
- `Skipping compression: ${this.consecutiveCompressionFailures} consecutive failures`,
286
+ `Skipping compaction: ${this.consecutiveCompactionFailures} consecutive failures`,
287
287
  );
288
288
  return;
289
289
  }
290
290
 
291
- const recentChatMessages = convertMessagesForAPI(messagesToCompress);
291
+ const recentChatMessages = convertMessagesForAPI(messagesToCompact);
292
292
 
293
- // Save session before compression to preserve original messages
293
+ // Save session before compaction to preserve original messages
294
294
  await this.messageManager.saveSession();
295
295
 
296
- this.setIsCompressing(true);
296
+ this.setIsCompacting(true);
297
297
  try {
298
- const compressionResult = await aiService.compressMessages({
298
+ const compactResult = await aiService.compactMessages({
299
299
  gatewayConfig: this.getGatewayConfig(),
300
300
  modelConfig: this.getModelConfig(),
301
301
  messages: recentChatMessages,
@@ -303,15 +303,15 @@ export class AIManager {
303
303
  model: this.getModelConfig().fastModel,
304
304
  });
305
305
 
306
- // Handle usage tracking for compression operations
307
- let compressionUsage: Usage | undefined;
308
- if (compressionResult.usage) {
309
- compressionUsage = {
310
- prompt_tokens: compressionResult.usage.prompt_tokens,
311
- completion_tokens: compressionResult.usage.completion_tokens,
312
- total_tokens: compressionResult.usage.total_tokens,
306
+ // Handle usage tracking for compaction operations
307
+ let compactUsage: Usage | undefined;
308
+ if (compactResult.usage) {
309
+ compactUsage = {
310
+ prompt_tokens: compactResult.usage.prompt_tokens,
311
+ completion_tokens: compactResult.usage.completion_tokens,
312
+ total_tokens: compactResult.usage.total_tokens,
313
313
  model: this.getModelConfig().fastModel,
314
- operation_type: "compress",
314
+ operation_type: "compact",
315
315
  };
316
316
  }
317
317
 
@@ -364,73 +364,152 @@ export class AIManager {
364
364
  }
365
365
  }
366
366
 
367
- // 4. Skills context
368
- const skills =
369
- this.skillManager
370
- ?.getAvailableSkills()
371
- .filter((s) => !s.disableModelInvocation) || [];
372
- if (skills.length > 0) {
373
- const skillList = skills
374
- .map((s) => `- ${s.name}: ${s.description || ""}`)
375
- .join("\n");
376
- contextParts.push(`\n\n[Available Skills]\n${skillList}`);
367
+ // 4. Invoked skills context (with token budget, matching Claude Code)
368
+ const POST_COMPACT_SKILLS_TOKEN_BUDGET = 25_000;
369
+ const POST_COMPACT_MAX_TOKENS_PER_SKILL = 5_000;
370
+ const invokedSkillNames =
371
+ this.messageManager.getInvokedSkillNames(10);
372
+ if (invokedSkillNames.length > 0 && this.skillManager) {
373
+ const invokedSkillParts: string[] = [];
374
+ let skillsUsedTokens = 0;
375
+ for (const skillName of invokedSkillNames) {
376
+ try {
377
+ const skill = await this.skillManager.loadSkill(skillName);
378
+ if (!skill) continue;
379
+
380
+ // Extract content after frontmatter (matching prepareSkillContent pattern)
381
+ const contentMatch = skill.content.match(
382
+ /^---\n[\s\S]*?\n---\n([\s\S]*)$/,
383
+ );
384
+ let skillContent = contentMatch
385
+ ? contentMatch[1].trim()
386
+ : skill.content;
387
+
388
+ // Per-skill token budget enforcement (~4 chars per token)
389
+ const maxSkillChars = POST_COMPACT_MAX_TOKENS_PER_SKILL * 4;
390
+ if (skillContent.length > maxSkillChars) {
391
+ skillContent =
392
+ skillContent.slice(0, maxSkillChars) +
393
+ "\n\n...[truncated]...";
394
+ }
395
+
396
+ const skillTokens = Math.ceil(skillContent.length / 4);
397
+ if (
398
+ skillsUsedTokens + skillTokens >
399
+ POST_COMPACT_SKILLS_TOKEN_BUDGET
400
+ )
401
+ break;
402
+ skillsUsedTokens += skillTokens;
403
+
404
+ invokedSkillParts.push(
405
+ `\n\n## ${skill.name}\n${skill.description ? `*${skill.description}*\n\n` : ""}\`\`\`\n${skillContent}\n\`\`\``,
406
+ );
407
+ } catch {
408
+ // Skip skills that can't be loaded
409
+ }
410
+ }
411
+ if (invokedSkillParts.length > 0) {
412
+ contextParts.push(
413
+ `\n\n[Invoked Skills]\n${invokedSkillParts.join("")}`,
414
+ );
415
+ }
377
416
  }
378
417
 
379
- // 5. Background agents status
380
- const agents = this.backgroundTaskManager?.getAllTasks() || [];
418
+ // 5. Background subagent status (shell tasks excluded, matching Claude Code's createAsyncAgentAttachmentsIfNeeded)
419
+ const agents =
420
+ this.backgroundTaskManager
421
+ ?.getAllTasks()
422
+ .filter((a) => a.type === "subagent") || [];
381
423
  if (agents.length > 0) {
382
- const agentList = agents
383
- .map((a) => `- Agent "${a.description}": ${a.status}`)
384
- .join("\n");
385
- contextParts.push(`\n\n[Background Tasks]\n${agentList}`);
424
+ const agentParts: string[] = [];
425
+ for (const a of agents) {
426
+ if (a.status === "killed") {
427
+ agentParts.push(
428
+ `Task "${a.description}" (${a.id}) was stopped by the user.`,
429
+ );
430
+ } else if (a.status === "running") {
431
+ const parts = [
432
+ `Background agent "${a.description}" (${a.id}) is still running.`,
433
+ `Do NOT spawn a duplicate. You will be notified when it completes.`,
434
+ ];
435
+ if (a.outputPath) {
436
+ parts.push(`You can read partial output at ${a.outputPath}.`);
437
+ }
438
+ agentParts.push(parts.join(" "));
439
+ } else {
440
+ // completed or failed
441
+ const parts = [
442
+ `Task ${a.id} (status: ${a.status}) (description: ${a.description}).`,
443
+ ];
444
+ const deltaText = a.status === "failed" ? a.stderr : a.stdout;
445
+ if (deltaText && deltaText.length > 0) {
446
+ const summary =
447
+ deltaText.length > 500
448
+ ? deltaText.slice(0, 500) + "..."
449
+ : deltaText;
450
+ parts.push(`Delta: ${summary}`);
451
+ }
452
+ if (a.outputPath) {
453
+ parts.push(
454
+ `Read the output file to retrieve the result: ${a.outputPath}.`,
455
+ );
456
+ }
457
+ agentParts.push(parts.join(" "));
458
+ }
459
+ }
460
+ if (agentParts.length > 0) {
461
+ contextParts.push(
462
+ `\n\n[Background Tasks]\n${agentParts.join("\n")}`,
463
+ );
464
+ }
386
465
  }
387
466
 
388
467
  // Merge context restoration into summary
389
468
  const enhancedSummary =
390
- compressionResult.content +
469
+ compactResult.content +
391
470
  (contextParts.length > 0
392
471
  ? `\n\n[Context Restoration]` + contextParts.join("")
393
472
  : "");
394
473
 
395
- // Execute message reconstruction and sessionId update after compression
396
- this.messageManager.compressMessagesAndUpdateSession(
474
+ // Execute message reconstruction and sessionId update after compaction
475
+ this.messageManager.compactMessagesAndUpdateSession(
397
476
  enhancedSummary,
398
- compressionUsage,
477
+ compactUsage,
399
478
  );
400
479
 
401
480
  // Notify Agent to add to usage tracking
402
- if (compressionUsage && this.callbacks?.onUsageAdded) {
403
- this.callbacks.onUsageAdded(compressionUsage);
481
+ if (compactUsage && this.callbacks?.onUsageAdded) {
482
+ this.callbacks.onUsageAdded(compactUsage);
404
483
  }
405
484
 
406
485
  logger?.debug(
407
- `Successfully compressed ${messagesToCompress.length} messages and updated session`,
486
+ `Successfully compacted ${messagesToCompact.length} messages and updated session`,
408
487
  );
409
- this.consecutiveCompressionFailures = 0;
410
- } catch (compressError) {
411
- this.consecutiveCompressionFailures++;
488
+ this.consecutiveCompactionFailures = 0;
489
+ } catch (compactError) {
490
+ this.consecutiveCompactionFailures++;
412
491
  logger?.error(
413
- `Failed to compress messages (${this.consecutiveCompressionFailures} consecutive):`,
414
- compressError,
492
+ `Failed to compact messages (${this.consecutiveCompactionFailures} consecutive):`,
493
+ compactError,
415
494
  );
416
495
  this.messageManager.addErrorBlock(
417
- `Failed to compress conversation history: ${compressError instanceof Error ? compressError.message : String(compressError)}. You may encounter context limit issues.`,
496
+ `Failed to compact conversation history: ${compactError instanceof Error ? compactError.message : String(compactError)}. You may encounter context limit issues.`,
418
497
  );
419
498
  } finally {
420
- this.setIsCompressing(false);
499
+ this.setIsCompacting(false);
421
500
  }
422
501
  }
423
502
  }
424
503
  }
425
504
 
426
- public getIsCompressing(): boolean {
427
- return this.isCompressing;
505
+ public getIsCompacting(): boolean {
506
+ return this.isCompacting;
428
507
  }
429
508
 
430
- public setIsCompressing(isCompressing: boolean): void {
431
- if (this.isCompressing !== isCompressing) {
432
- this.isCompressing = isCompressing;
433
- this.callbacks.onCompressionStateChange?.(isCompressing);
509
+ public setIsCompacting(isCompacting: boolean): void {
510
+ if (this.isCompacting !== isCompacting) {
511
+ this.isCompacting = isCompacting;
512
+ this.callbacks.onCompactionStateChange?.(isCompacting);
434
513
  }
435
514
  }
436
515
 
@@ -914,8 +993,8 @@ export class AIManager {
914
993
  await Promise.all(toolExecutionPromises);
915
994
  }
916
995
 
917
- // Handle token statistics and message compression
918
- await this.handleTokenUsageAndCompression(result.usage, abortController);
996
+ // Handle token statistics and message compaction
997
+ await this.handleTokenUsageAndCompaction(result.usage, abortController);
919
998
 
920
999
  // Finalize text/reasoning blocks for the final response (no tools)
921
1000
  this.messageManager.finalizeStreamingBlocks();
@@ -2,11 +2,7 @@ import { spawn, type ChildProcess } from "child_process";
2
2
  import * as os from "os";
3
3
  import * as fs from "fs";
4
4
  import * as path from "path";
5
- import {
6
- BackgroundTask,
7
- BackgroundShell,
8
- BackgroundSubagent,
9
- } from "../types/processes.js";
5
+ import { BackgroundTask, BackgroundShell } from "../types/processes.js";
10
6
  import { stripAnsiColors } from "../utils/stringUtils.js";
11
7
  import { logger } from "../utils/globalLogger.js";
12
8
  import { Container } from "../utils/container.js";
@@ -157,22 +153,27 @@ export class BackgroundTaskManager {
157
153
  if (logStream.writable) {
158
154
  logStream.end();
159
155
  }
160
- shell.status = code === 0 ? "completed" : "failed";
156
+ const wasKilled = shell.status === "killed";
157
+ if (!wasKilled) {
158
+ shell.status = code === 0 ? "completed" : "failed";
159
+ }
161
160
  shell.exitCode = code ?? 0;
162
161
  shell.endTime = Date.now();
163
162
  shell.runtime = shell.endTime - startTime;
164
163
  this.notifyTasksChange();
165
164
 
166
- // Enqueue completion notification
167
- const notificationQueue = this.container.has("NotificationQueue")
168
- ? this.container.get<NotificationQueue>("NotificationQueue")
169
- : undefined;
170
- if (notificationQueue) {
171
- const statusStr = shell.status;
172
- const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
173
- notificationQueue.enqueue(
174
- `<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>${statusStr}</status>\n<summary>${summary}</summary>\n</task-notification>`,
175
- );
165
+ // Skip notification if task was manually killed (user/agent-initiated stop)
166
+ if (!wasKilled) {
167
+ const notificationQueue = this.container.has("NotificationQueue")
168
+ ? this.container.get<NotificationQueue>("NotificationQueue")
169
+ : undefined;
170
+ if (notificationQueue) {
171
+ const statusStr = shell.status;
172
+ const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
173
+ notificationQueue.enqueue(
174
+ `<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>${statusStr}</status>\n<summary>${summary}</summary>\n</task-notification>`,
175
+ );
176
+ }
176
177
  }
177
178
  };
178
179
 
@@ -305,22 +306,27 @@ export class BackgroundTaskManager {
305
306
  if (logStream.writable) {
306
307
  logStream.end();
307
308
  }
308
- shell.status = code === 0 ? "completed" : "failed";
309
+ const wasKilled = shell.status === "killed";
310
+ if (!wasKilled) {
311
+ shell.status = code === 0 ? "completed" : "failed";
312
+ }
309
313
  shell.exitCode = code ?? 0;
310
314
  shell.endTime = Date.now();
311
315
  shell.runtime = shell.endTime - startTime;
312
316
  this.notifyTasksChange();
313
317
 
314
- // Enqueue completion notification
315
- const notificationQueue = this.container.has("NotificationQueue")
316
- ? this.container.get<NotificationQueue>("NotificationQueue")
317
- : undefined;
318
- if (notificationQueue) {
319
- const statusStr = shell.status;
320
- const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
321
- notificationQueue.enqueue(
322
- `<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>${statusStr}</status>\n<summary>${summary}</summary>\n</task-notification>`,
323
- );
318
+ // Skip notification if task was manually killed (user/agent-initiated stop)
319
+ if (!wasKilled) {
320
+ const notificationQueue = this.container.has("NotificationQueue")
321
+ ? this.container.get<NotificationQueue>("NotificationQueue")
322
+ : undefined;
323
+ if (notificationQueue) {
324
+ const statusStr = shell.status;
325
+ const summary = `Command "${command}" ${statusStr} with exit code ${code ?? 0}`;
326
+ notificationQueue.enqueue(
327
+ `<task-notification>\n<task-id>${id}</task-id>\n<task-type>shell</task-type>\n<output-file>${logPath}</output-file>\n<status>${statusStr}</status>\n<summary>${summary}</summary>\n</task-notification>`,
328
+ );
329
+ }
324
330
  }
325
331
  });
326
332
 
@@ -427,21 +433,6 @@ export class BackgroundTaskManager {
427
433
  task.runtime = task.endTime - task.startTime;
428
434
  this.notifyTasksChange();
429
435
 
430
- // Enqueue killed notification
431
- const notificationQueue = this.container.has("NotificationQueue")
432
- ? this.container.get<NotificationQueue>("NotificationQueue")
433
- : undefined;
434
- if (notificationQueue) {
435
- const description = (task as BackgroundSubagent).description || "";
436
- const command = (task as BackgroundShell).command || "";
437
- const summary =
438
- task.type === "subagent"
439
- ? `Agent task "${description}" was stopped`
440
- : `Command "${command}" was stopped`;
441
- notificationQueue.enqueue(
442
- `<task-notification>\n<task-id>${id}</task-id>\n<task-type>${task.type}</task-type>\n<status>killed</status>\n<summary>${summary}</summary>\n</task-notification>`,
443
- );
444
- }
445
436
  return true;
446
437
  }
447
438