wave-agent-sdk 0.13.2 → 0.13.3

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 (66) hide show
  1. package/dist/agent.d.ts +7 -0
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +37 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/managers/aiManager.d.ts.map +1 -1
  8. package/dist/managers/aiManager.js +65 -33
  9. package/dist/managers/backgroundTaskManager.d.ts +1 -0
  10. package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
  11. package/dist/managers/backgroundTaskManager.js +49 -0
  12. package/dist/managers/forkedAgentManager.d.ts +49 -0
  13. package/dist/managers/forkedAgentManager.d.ts.map +1 -0
  14. package/dist/managers/forkedAgentManager.js +111 -0
  15. package/dist/managers/messageManager.d.ts +8 -1
  16. package/dist/managers/messageManager.d.ts.map +1 -1
  17. package/dist/managers/messageManager.js +14 -1
  18. package/dist/managers/notificationQueue.d.ts +8 -0
  19. package/dist/managers/notificationQueue.d.ts.map +1 -0
  20. package/dist/managers/notificationQueue.js +17 -0
  21. package/dist/managers/permissionManager.d.ts.map +1 -1
  22. package/dist/managers/permissionManager.js +2 -0
  23. package/dist/managers/subagentManager.d.ts +0 -10
  24. package/dist/managers/subagentManager.d.ts.map +1 -1
  25. package/dist/managers/subagentManager.js +60 -20
  26. package/dist/services/autoMemoryService.d.ts +1 -1
  27. package/dist/services/autoMemoryService.d.ts.map +1 -1
  28. package/dist/services/autoMemoryService.js +7 -9
  29. package/dist/services/interactionService.d.ts.map +1 -1
  30. package/dist/services/interactionService.js +12 -0
  31. package/dist/types/agent.d.ts +1 -0
  32. package/dist/types/agent.d.ts.map +1 -1
  33. package/dist/types/messaging.d.ts +9 -1
  34. package/dist/types/messaging.d.ts.map +1 -1
  35. package/dist/utils/containerSetup.d.ts.map +1 -1
  36. package/dist/utils/containerSetup.js +6 -0
  37. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  38. package/dist/utils/convertMessagesForAPI.js +8 -0
  39. package/dist/utils/messageOperations.d.ts +9 -0
  40. package/dist/utils/messageOperations.d.ts.map +1 -1
  41. package/dist/utils/messageOperations.js +17 -0
  42. package/dist/utils/notificationXml.d.ts +4 -0
  43. package/dist/utils/notificationXml.d.ts.map +1 -0
  44. package/dist/utils/notificationXml.js +40 -0
  45. package/dist/utils/pathEncoder.d.ts +0 -1
  46. package/dist/utils/pathEncoder.d.ts.map +1 -1
  47. package/dist/utils/pathEncoder.js +1 -5
  48. package/package.json +1 -1
  49. package/src/agent.ts +44 -0
  50. package/src/index.ts +1 -0
  51. package/src/managers/aiManager.ts +76 -41
  52. package/src/managers/backgroundTaskManager.ts +72 -1
  53. package/src/managers/forkedAgentManager.ts +193 -0
  54. package/src/managers/messageManager.ts +25 -0
  55. package/src/managers/notificationQueue.ts +19 -0
  56. package/src/managers/permissionManager.ts +2 -0
  57. package/src/managers/subagentManager.ts +86 -42
  58. package/src/services/autoMemoryService.ts +11 -18
  59. package/src/services/interactionService.ts +18 -0
  60. package/src/types/agent.ts +1 -0
  61. package/src/types/messaging.ts +11 -1
  62. package/src/utils/containerSetup.ts +8 -0
  63. package/src/utils/convertMessagesForAPI.ts +9 -0
  64. package/src/utils/messageOperations.ts +42 -1
  65. package/src/utils/notificationXml.ts +52 -0
  66. package/src/utils/pathEncoder.ts +1 -6
@@ -0,0 +1,19 @@
1
+ export class NotificationQueue {
2
+ private queue: string[] = [];
3
+ onNotificationsEnqueued?: () => void;
4
+
5
+ enqueue(notification: string): void {
6
+ this.queue.push(notification);
7
+ this.onNotificationsEnqueued?.();
8
+ }
9
+
10
+ dequeueAll(): string[] {
11
+ const items = [...this.queue];
12
+ this.queue = [];
13
+ return items;
14
+ }
15
+
16
+ hasPending(): boolean {
17
+ return this.queue.length > 0;
18
+ }
19
+ }
@@ -50,6 +50,7 @@ const SAFE_COMMANDS = [
50
50
  "wc",
51
51
  "sleep",
52
52
  "find",
53
+ "sort",
53
54
  ];
54
55
 
55
56
  const DEFAULT_ALLOWED_RULES = [
@@ -867,6 +868,7 @@ export class PermissionManager {
867
868
  cmd === "tail" ||
868
869
  cmd === "wc" ||
869
870
  cmd === "sleep" ||
871
+ cmd === "sort" ||
870
872
  (cmd === "find" && !isDangerousFind(part))
871
873
  ) {
872
874
  return true;
@@ -13,6 +13,7 @@ import {
13
13
  createAbortPromise,
14
14
  } from "../utils/abortUtils.js";
15
15
  import { BackgroundTaskManager } from "./backgroundTaskManager.js";
16
+ import { NotificationQueue } from "./notificationQueue.js";
16
17
  import { logger } from "../utils/globalLogger.js";
17
18
  import {
18
19
  UserMessageParams,
@@ -220,6 +221,23 @@ export class SubagentManager {
220
221
  // Create a child container for the subagent to isolate its managers
221
222
  const subagentContainer = this.container.createChild();
222
223
 
224
+ // Register a modified AgentOptions without onLoadingChange to prevent subagent loading
225
+ // from affecting the parent agent's loading state
226
+ const parentOptions =
227
+ this.container.get<import("../types/agent.js").AgentOptions>(
228
+ "AgentOptions",
229
+ );
230
+ if (parentOptions) {
231
+ const subagentOptions: import("../types/agent.js").AgentOptions = {
232
+ ...parentOptions,
233
+ callbacks: {
234
+ ...parentOptions.callbacks,
235
+ onLoadingChange: undefined,
236
+ },
237
+ };
238
+ subagentContainer.register("AgentOptions", subagentOptions);
239
+ }
240
+
223
241
  // Create isolated PermissionManager for the subagent
224
242
  const { PermissionManager } = await import("./permissionManager.js");
225
243
  const parentPermissionManager =
@@ -289,6 +307,22 @@ export class SubagentManager {
289
307
  });
290
308
  subagentContainer.register("AIManager", aiManager);
291
309
 
310
+ // Create isolated NotificationQueue for the subagent/forked agent
311
+ const subagentNotificationQueue = new NotificationQueue();
312
+ subagentContainer.register("NotificationQueue", subagentNotificationQueue);
313
+
314
+ // Create isolated BackgroundTaskManager for the subagent/forked agent
315
+ const subagentBackgroundTaskManager = new BackgroundTaskManager(
316
+ subagentContainer,
317
+ {
318
+ workdir: this.workdir,
319
+ },
320
+ );
321
+ subagentContainer.register(
322
+ "BackgroundTaskManager",
323
+ subagentBackgroundTaskManager,
324
+ );
325
+
292
326
  const instance: SubagentInstance = {
293
327
  subagentId,
294
328
  configuration,
@@ -310,43 +344,6 @@ export class SubagentManager {
310
344
  return instance;
311
345
  }
312
346
 
313
- /**
314
- * Create a new subagent instance initialized with a copy of the current message history.
315
- * This is used for background tasks like auto-memory extraction.
316
- */
317
- async forkAgent(
318
- subagentType: string,
319
- messages: Message[],
320
- parameters: {
321
- description: string;
322
- allowedTools?: string[];
323
- model?: string;
324
- permissionModeOverride?: PermissionMode;
325
- },
326
- onUpdate?: () => void,
327
- ): Promise<SubagentInstance> {
328
- const configuration = await this.findSubagent(subagentType);
329
- if (!configuration) {
330
- throw new Error(`Subagent type ${subagentType} not found`);
331
- }
332
-
333
- const instance = await this.createInstance(
334
- configuration,
335
- {
336
- ...parameters,
337
- subagent_type: subagentType,
338
- prompt: "", // Forked agents start with history
339
- },
340
- false,
341
- onUpdate,
342
- );
343
-
344
- // Initialize the message manager with provided messages
345
- instance.messageManager.setMessages(messages);
346
-
347
- return instance;
348
- }
349
-
350
347
  /**
351
348
  * Execute agent using subagent instance
352
349
  *
@@ -416,6 +413,17 @@ export class SubagentManager {
416
413
  task.endTime = Date.now();
417
414
  task.runtime = task.endTime - startTime;
418
415
  }
416
+
417
+ // Enqueue completion notification
418
+ const notificationQueue = this.container.has("NotificationQueue")
419
+ ? this.container.get<NotificationQueue>("NotificationQueue")
420
+ : undefined;
421
+ if (notificationQueue) {
422
+ const summary = `Agent task "${instance.description}" completed`;
423
+ notificationQueue.enqueue(
424
+ `<task-notification>\n<task-id>${taskId}</task-id>\n<task-type>agent</task-type>\n<status>completed</status>\n<summary>${summary}</summary>\n</task-notification>`,
425
+ );
426
+ }
419
427
  } catch (error) {
420
428
  const task = backgroundTaskManager?.getTask(taskId);
421
429
  if (task) {
@@ -425,6 +433,19 @@ export class SubagentManager {
425
433
  task.endTime = Date.now();
426
434
  task.runtime = task.endTime - startTime;
427
435
  }
436
+
437
+ // Enqueue error notification
438
+ const notificationQueue = this.container.has("NotificationQueue")
439
+ ? this.container.get<NotificationQueue>("NotificationQueue")
440
+ : undefined;
441
+ if (notificationQueue) {
442
+ const errorMsg =
443
+ error instanceof Error ? error.message : String(error);
444
+ const summary = `Agent task "${instance.description}" failed: ${errorMsg}`;
445
+ notificationQueue.enqueue(
446
+ `<task-notification>\n<task-id>${taskId}</task-id>\n<task-type>agent</task-type>\n<status>failed</status>\n<summary>${summary}</summary>\n</task-notification>`,
447
+ );
448
+ }
428
449
  }
429
450
  })();
430
451
 
@@ -568,6 +589,17 @@ export class SubagentManager {
568
589
  task.runtime = task.endTime - task.startTime;
569
590
  }
570
591
  }
592
+
593
+ // Enqueue completion notification
594
+ const notificationQueue = this.container.has("NotificationQueue")
595
+ ? this.container.get<NotificationQueue>("NotificationQueue")
596
+ : undefined;
597
+ if (notificationQueue) {
598
+ const summary = `Agent task "${instance.description}" completed`;
599
+ notificationQueue.enqueue(
600
+ `<task-notification>\n<task-id>${instance.backgroundTaskId}</task-id>\n<task-type>agent</task-type>\n<status>completed</status>\n<summary>${summary}</summary>\n</task-notification>`,
601
+ );
602
+ }
571
603
  }
572
604
 
573
605
  return response || "Agent completed with no text response";
@@ -592,6 +624,19 @@ export class SubagentManager {
592
624
  task.runtime = task.endTime - task.startTime;
593
625
  }
594
626
  }
627
+
628
+ // Enqueue error notification
629
+ const notificationQueue = this.container.has("NotificationQueue")
630
+ ? this.container.get<NotificationQueue>("NotificationQueue")
631
+ : undefined;
632
+ if (notificationQueue) {
633
+ const errorMsg =
634
+ error instanceof Error ? error.message : String(error);
635
+ const summary = `Agent task "${instance.description}" failed: ${errorMsg}`;
636
+ notificationQueue.enqueue(
637
+ `<task-notification>\n<task-id>${instance.backgroundTaskId}</task-id>\n<task-type>agent</task-type>\n<status>failed</status>\n<summary>${summary}</summary>\n</task-notification>`,
638
+ );
639
+ }
595
640
  }
596
641
  throw error;
597
642
  } finally {
@@ -721,12 +766,11 @@ export class SubagentManager {
721
766
 
722
767
  // Log tool execution to file
723
768
  if (instance.logStream) {
724
- const compactParams = (params.parameters || "{}").substring(
725
- 0,
726
- 100,
727
- );
769
+ const displayParams =
770
+ params.compactParams ||
771
+ (params.parameters || "{}").substring(0, 100);
728
772
  instance.logStream.write(
729
- `[${new Date().toISOString()}] Running tool: ${params.name} with params: ${compactParams}${compactParams.length >= 100 ? "..." : ""}\n`,
773
+ `[${new Date().toISOString()}] ${params.name}${displayParams ? ` ${displayParams}` : ""}\n`,
730
774
  );
731
775
  }
732
776
  }
@@ -2,7 +2,7 @@ import * as path from "node:path";
2
2
  import * as fs from "node:fs/promises";
3
3
  import { Container } from "../utils/container.js";
4
4
  import { MessageManager } from "../managers/messageManager.js";
5
- import { SubagentManager } from "../managers/subagentManager.js";
5
+ import { ForkedAgentManager } from "../managers/forkedAgentManager.js";
6
6
  import { MemoryService } from "./memory.js";
7
7
  import { ConfigurationService } from "./configurationService.js";
8
8
  import { logger } from "../utils/globalLogger.js";
@@ -24,8 +24,8 @@ export class AutoMemoryService {
24
24
  return this.container.get<MessageManager>("MessageManager")!;
25
25
  }
26
26
 
27
- private get subagentManager(): SubagentManager {
28
- return this.container.get<SubagentManager>("SubagentManager")!;
27
+ private get forkedAgentManager(): ForkedAgentManager {
28
+ return this.container.get<ForkedAgentManager>("ForkedAgentManager")!;
29
29
  }
30
30
 
31
31
  private get memoryService(): MemoryService {
@@ -143,8 +143,13 @@ export class AutoMemoryService {
143
143
  }
144
144
  }
145
145
 
146
- // Fork the general-purpose agent with restricted tool access
147
- const instance = await this.subagentManager.forkAgent(
146
+ const prompt = buildAutoMemoryExtractionPrompt(
147
+ newMessageCount,
148
+ existingMemoriesManifest,
149
+ );
150
+
151
+ // Execute the forked agent in background (fire-and-forget, decoupled from BackgroundTaskManager)
152
+ await this.forkedAgentManager.forkAndExecute(
148
153
  "general-purpose",
149
154
  messages,
150
155
  {
@@ -157,21 +162,9 @@ export class AutoMemoryService {
157
162
  `Edit(${memoryDir}/**/*)`,
158
163
  ],
159
164
  model: "fastModel", // Use fast model for background tasks to reduce latency and cost
160
- permissionModeOverride: "default", // Force default mode to prevent acceptEdits bypass
165
+ permissionModeOverride: "dontAsk", // Auto-deny out-of-scope writes without prompting user
161
166
  },
162
- );
163
-
164
- const prompt = buildAutoMemoryExtractionPrompt(
165
- newMessageCount,
166
- existingMemoriesManifest,
167
- );
168
-
169
- // Execute in background so it doesn't block the main conversation flow
170
- await this.subagentManager.executeAgent(
171
- instance,
172
167
  `${prompt}\n\nThe memory directory for this project is: ${memoryDir}`,
173
- undefined,
174
- true, // runInBackground
175
168
  );
176
169
 
177
170
  logger.debug("Auto-memory extraction started in background.");
@@ -7,6 +7,7 @@ import type { ConfigurationService } from "./configurationService.js";
7
7
  import type { AIManager } from "../managers/aiManager.js";
8
8
  import type { SubagentManager } from "../managers/subagentManager.js";
9
9
  import type { TaskManager } from "./taskManager.js";
10
+ import type { NotificationQueue } from "../managers/notificationQueue.js";
10
11
 
11
12
  export interface InteractionContext {
12
13
  messageManager: MessageManager;
@@ -58,6 +59,23 @@ export class InteractionService {
58
59
  // Don't add to history, let normal message processing logic below handle it
59
60
  }
60
61
 
62
+ // Inject pending notifications from background tasks
63
+ const notificationQueue = context.aiManager["container"].has(
64
+ "NotificationQueue",
65
+ )
66
+ ? context.aiManager["container"].get<NotificationQueue>(
67
+ "NotificationQueue",
68
+ )
69
+ : undefined;
70
+ if (notificationQueue && notificationQueue.hasPending()) {
71
+ const notifications = notificationQueue.dequeueAll();
72
+ for (const notification of notifications) {
73
+ messageManager.addUserMessage({
74
+ content: notification,
75
+ });
76
+ }
77
+ }
78
+
61
79
  // Handle normal AI message
62
80
  // Add user message first, will automatically sync to UI
63
81
  messageManager.addUserMessage({
@@ -95,4 +95,5 @@ export interface AgentCallbacks
95
95
  onBackgroundCurrentTask?: () => void;
96
96
  onModelChange?: (model: string) => void;
97
97
  onConfiguredModelsChange?: (models: string[]) => void;
98
+ onLoadingChange?: (loading: boolean) => void;
98
99
  }
@@ -27,7 +27,8 @@ export type MessageBlock =
27
27
  | BangBlock
28
28
  | CompressBlock
29
29
  | ReasoningBlock
30
- | FileHistoryBlock;
30
+ | FileHistoryBlock
31
+ | TaskNotificationBlock;
31
32
 
32
33
  export interface TextBlock {
33
34
  type: "text";
@@ -99,3 +100,12 @@ export interface FileHistoryBlock {
99
100
  type: "file_history";
100
101
  snapshots: import("./reversion.js").FileSnapshot[];
101
102
  }
103
+
104
+ export interface TaskNotificationBlock {
105
+ type: "task_notification";
106
+ taskId: string;
107
+ taskType: "shell" | "agent";
108
+ status: "completed" | "failed" | "killed";
109
+ summary: string;
110
+ outputFile?: string;
111
+ }
@@ -1,6 +1,7 @@
1
1
  import { Container } from "./container.js";
2
2
  import { ForegroundTaskManager } from "../managers/foregroundTaskManager.js";
3
3
  import { BackgroundTaskManager } from "../managers/backgroundTaskManager.js";
4
+ import { NotificationQueue } from "../managers/notificationQueue.js";
4
5
  import { TaskManager } from "../services/taskManager.js";
5
6
  import { MessageManager } from "../managers/messageManager.js";
6
7
  import { AIManager } from "../managers/aiManager.js";
@@ -18,6 +19,7 @@ import { CronManager } from "../managers/cronManager.js";
18
19
  import { MemoryRuleManager } from "../managers/MemoryRuleManager.js";
19
20
  import { ReversionManager } from "../managers/reversionManager.js";
20
21
  import { SubagentManager } from "../managers/subagentManager.js";
22
+ import { ForkedAgentManager } from "../managers/forkedAgentManager.js";
21
23
  import { LiveConfigManager } from "../managers/liveConfigManager.js";
22
24
  import { ConfigurationService } from "../services/configurationService.js";
23
25
  import { ReversionService } from "../services/reversionService.js";
@@ -75,6 +77,9 @@ export function setupAgentContainer(
75
77
  const container = new Container();
76
78
  container.register("AgentOptions", options);
77
79
 
80
+ const notificationQueue = new NotificationQueue();
81
+ container.register("NotificationQueue", notificationQueue);
82
+
78
83
  const foregroundTaskManager = new ForegroundTaskManager(container);
79
84
  container.register("ForegroundTaskManager", foregroundTaskManager);
80
85
  container.register("ConfigurationService", configurationService);
@@ -283,6 +288,9 @@ export function setupAgentContainer(
283
288
  });
284
289
  container.register("SubagentManager", subagentManager);
285
290
 
291
+ const forkedAgentManager = new ForkedAgentManager(container);
292
+ container.register("ForkedAgentManager", forkedAgentManager);
293
+
286
294
  const aiManager = new AIManager(container, {
287
295
  callbacks: {
288
296
  ...callbacks,
@@ -1,5 +1,6 @@
1
1
  import type { Message } from "../types/index.js";
2
2
  import { convertImageToBase64 } from "./messageOperations.js";
3
+ import { taskNotificationToXml } from "./notificationXml.js";
3
4
  import { ChatCompletionMessageToolCall } from "openai/resources";
4
5
  import { stripAnsiColors } from "./stringUtils.js";
5
6
  import {
@@ -239,6 +240,14 @@ export function convertMessagesForAPI(
239
240
  text: `<local-command-stdout>\n${stripAnsiColors(block.result)}\n</local-command-stdout>`,
240
241
  });
241
242
  }
243
+
244
+ // If there is a task notification block, convert it back to XML
245
+ if (block.type === "task_notification") {
246
+ contentParts.push({
247
+ type: "text",
248
+ text: taskNotificationToXml(block),
249
+ });
250
+ }
242
251
  });
243
252
 
244
253
  // Only add user message if there is meaningful content
@@ -1,5 +1,10 @@
1
1
  import { randomUUID } from "crypto";
2
- import type { Message, Usage, ToolBlock } from "../types/index.js";
2
+ import type {
3
+ Message,
4
+ Usage,
5
+ ToolBlock,
6
+ TaskNotificationBlock,
7
+ } from "../types/index.js";
3
8
  import { MessageSource } from "../types/index.js";
4
9
  import { readFileSync } from "fs";
5
10
  import { extname } from "path";
@@ -135,6 +140,7 @@ export const addUserMessageToMessages = ({
135
140
  const textBlock = {
136
141
  type: "text" as const,
137
142
  content,
143
+ stage: "end" as const,
138
144
  ...(customCommandContent && { customCommandContent }),
139
145
  ...(source && { source }),
140
146
  };
@@ -584,3 +590,38 @@ export function getMessageContent(message: Message): string {
584
590
 
585
591
  return "";
586
592
  }
593
+
594
+ export interface AddNotificationMessageParams {
595
+ messages: Message[];
596
+ taskId: string;
597
+ taskType: "shell" | "agent";
598
+ status: "completed" | "failed" | "killed";
599
+ summary: string;
600
+ outputFile?: string;
601
+ }
602
+
603
+ export const addNotificationMessageToMessages = ({
604
+ messages,
605
+ taskId,
606
+ taskType,
607
+ status,
608
+ summary,
609
+ outputFile,
610
+ }: AddNotificationMessageParams): Message[] => {
611
+ const block: TaskNotificationBlock = {
612
+ type: "task_notification",
613
+ taskId,
614
+ taskType,
615
+ status,
616
+ summary,
617
+ ...(outputFile !== undefined && { outputFile }),
618
+ };
619
+
620
+ const notificationMessage: Message = {
621
+ id: generateMessageId(),
622
+ role: "user",
623
+ blocks: [block],
624
+ };
625
+
626
+ return [...messages, notificationMessage];
627
+ };
@@ -0,0 +1,52 @@
1
+ import type { TaskNotificationBlock } from "../types/messaging.js";
2
+
3
+ export function taskNotificationToXml(block: TaskNotificationBlock): string {
4
+ let xml = `<task-notification>\n`;
5
+ xml += `<task-id>${block.taskId}</task-id>\n`;
6
+ xml += `<task-type>${block.taskType}</task-type>\n`;
7
+ if (block.outputFile) {
8
+ xml += `<output-file>${block.outputFile}</output-file>\n`;
9
+ }
10
+ xml += `<status>${block.status}</status>\n`;
11
+ xml += `<summary>${block.summary}</summary>\n`;
12
+ xml += `</task-notification>`;
13
+ return xml;
14
+ }
15
+
16
+ function extractTag(xml: string, tag: string): string | null {
17
+ const regex = new RegExp(`<${tag}>(.*?)</${tag}>`, "s");
18
+ const match = xml.match(regex);
19
+ return match ? match[1] : null;
20
+ }
21
+
22
+ export function parseTaskNotificationXml(
23
+ xml: string,
24
+ ): TaskNotificationBlock | null {
25
+ try {
26
+ const taskId = extractTag(xml, "task-id");
27
+ const taskType = extractTag(xml, "task-type") as "shell" | "agent" | null;
28
+ const status = extractTag(xml, "status") as
29
+ | "completed"
30
+ | "failed"
31
+ | "killed"
32
+ | null;
33
+ const summary = extractTag(xml, "summary");
34
+
35
+ if (!taskId || !taskType || !status || !summary) {
36
+ return null;
37
+ }
38
+
39
+ const outputFile = extractTag(xml, "output-file") || undefined;
40
+
41
+ return {
42
+ type: "task_notification",
43
+ taskId,
44
+ taskType,
45
+ status,
46
+ summary,
47
+ ...(outputFile && { outputFile }),
48
+ };
49
+ } catch {
50
+ return null;
51
+ }
52
+ }
@@ -27,7 +27,6 @@ export interface PathEncodingOptions {
27
27
  pathSeparatorReplacement?: string; // Default: '-'
28
28
  spaceReplacement?: string; // Default: '_'
29
29
  invalidCharReplacement?: string; // Default: '_'
30
- preserveCase?: boolean; // Default: false (convert to lowercase)
31
30
  hashLength?: number; // Default: 8 characters
32
31
  }
33
32
 
@@ -65,7 +64,6 @@ export class PathEncoder {
65
64
  pathSeparatorReplacement: options.pathSeparatorReplacement ?? "-",
66
65
  spaceReplacement: options.spaceReplacement ?? "_",
67
66
  invalidCharReplacement: options.invalidCharReplacement ?? "_",
68
- preserveCase: options.preserveCase ?? false,
69
67
  hashLength: options.hashLength ?? 8,
70
68
  };
71
69
  this.constraints = this.getFilesystemConstraints();
@@ -109,10 +107,7 @@ export class PathEncoder {
109
107
  this.options.invalidCharReplacement,
110
108
  );
111
109
 
112
- // Convert to lowercase unless preserveCase is true
113
- if (!this.options.preserveCase) {
114
- encoded = encoded.toLowerCase();
115
- }
110
+ // Case is preserved
116
111
 
117
112
  // Handle length limit with hash
118
113
  if (encoded.length > this.options.maxLength) {