wave-agent-sdk 0.12.8 → 0.12.10

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 (43) hide show
  1. package/builtin/skills/settings/ENV.md +1 -0
  2. package/builtin/skills/settings/PERMISSIONS.md +57 -0
  3. package/builtin/skills/settings/SKILL.md +12 -3
  4. package/dist/managers/messageManager.d.ts +1 -5
  5. package/dist/managers/messageManager.d.ts.map +1 -1
  6. package/dist/managers/messageManager.js +1 -28
  7. package/dist/managers/permissionManager.d.ts +6 -0
  8. package/dist/managers/permissionManager.d.ts.map +1 -1
  9. package/dist/managers/permissionManager.js +9 -0
  10. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  11. package/dist/managers/slashCommandManager.js +31 -46
  12. package/dist/managers/subagentManager.d.ts.map +1 -1
  13. package/dist/managers/subagentManager.js +8 -0
  14. package/dist/services/aiService.js +4 -4
  15. package/dist/services/configurationService.d.ts.map +1 -1
  16. package/dist/services/configurationService.js +1 -0
  17. package/dist/services/initializationService.d.ts.map +1 -1
  18. package/dist/services/initializationService.js +2 -0
  19. package/dist/types/messaging.d.ts +1 -11
  20. package/dist/types/messaging.d.ts.map +1 -1
  21. package/dist/utils/cacheControlUtils.d.ts +8 -1
  22. package/dist/utils/cacheControlUtils.d.ts.map +1 -1
  23. package/dist/utils/cacheControlUtils.js +25 -8
  24. package/dist/utils/containerSetup.d.ts.map +1 -1
  25. package/dist/utils/containerSetup.js +2 -0
  26. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  27. package/dist/utils/convertMessagesForAPI.js +0 -15
  28. package/dist/utils/messageOperations.d.ts +0 -26
  29. package/dist/utils/messageOperations.d.ts.map +1 -1
  30. package/dist/utils/messageOperations.js +0 -80
  31. package/package.json +1 -1
  32. package/src/managers/messageManager.ts +0 -40
  33. package/src/managers/permissionManager.ts +12 -0
  34. package/src/managers/slashCommandManager.ts +33 -49
  35. package/src/managers/subagentManager.ts +15 -0
  36. package/src/services/aiService.ts +4 -4
  37. package/src/services/configurationService.ts +1 -0
  38. package/src/services/initializationService.ts +2 -0
  39. package/src/types/messaging.ts +0 -12
  40. package/src/utils/cacheControlUtils.ts +27 -8
  41. package/src/utils/containerSetup.ts +2 -0
  42. package/src/utils/convertMessagesForAPI.ts +0 -16
  43. package/src/utils/messageOperations.ts +0 -114
@@ -25,7 +25,6 @@ export type MessageBlock =
25
25
  | ToolBlock
26
26
  | ImageBlock
27
27
  | BangBlock
28
- | SlashBlock
29
28
  | CompressBlock
30
29
  | ReasoningBlock
31
30
  | FileHistoryBlock;
@@ -36,17 +35,6 @@ export interface TextBlock {
36
35
  source?: MessageSource;
37
36
  }
38
37
 
39
- export interface SlashBlock {
40
- type: "slash";
41
- command: string;
42
- args?: string;
43
- content?: string; // The expanded prompt (template + args + bash output)
44
- result?: string; // The final output (e.g., from a forked skill)
45
- stage: "running" | "success" | "error" | "aborted";
46
- error?: string;
47
- shortResult?: string; // Progress summary (e.g., "3 tools | 1,234 tokens")
48
- }
49
-
50
38
  export interface ErrorBlock {
51
39
  type: "error";
52
40
  content: string;
@@ -73,11 +73,11 @@ export interface ClaudeUsage extends CompletionUsage {
73
73
  // ============================================================================
74
74
 
75
75
  /**
76
- * Determines if a model supports cache control
76
+ * Determines if a model supports prompt caching
77
77
  * @param modelName - Model identifier
78
- * @returns True if model name contains 'claude' (case-insensitive)
78
+ * @returns True if model name matches the cache pattern (default: contains 'claude')
79
79
  */
80
- export function isClaudeModel(modelName: string): boolean {
80
+ export function supportsPromptCaching(modelName: string): boolean {
81
81
  // Handle null, undefined, and non-string inputs
82
82
  if (!modelName || typeof modelName !== "string") {
83
83
  return false;
@@ -89,9 +89,24 @@ export function isClaudeModel(modelName: string): boolean {
89
89
  return false;
90
90
  }
91
91
 
92
- return trimmed.toLowerCase().includes("claude");
92
+ const cachePattern = process.env.WAVE_PROMPT_CACHE_REGEX || "claude";
93
+ try {
94
+ const regex = new RegExp(cachePattern, "i");
95
+ return regex.test(trimmed);
96
+ } catch {
97
+ // If regex is invalid, fall back to simple includes check with default
98
+ return trimmed.toLowerCase().includes("claude");
99
+ }
93
100
  }
94
101
 
102
+ /**
103
+ * Determines if a model supports cache control
104
+ * @param modelName - Model identifier
105
+ * @returns True if model name contains 'claude' (case-insensitive)
106
+ * @deprecated Use supportsPromptCaching instead
107
+ */
108
+ export const isClaudeModel = supportsPromptCaching;
109
+
95
110
  /**
96
111
  * Validates cache control structure
97
112
  * @param control - Object to validate
@@ -308,8 +323,8 @@ export function transformMessagesForClaudeCache(
308
323
  return [];
309
324
  }
310
325
 
311
- // Only apply cache control for Claude models
312
- if (!isClaudeModel(modelName)) {
326
+ // Only apply cache control for models that support prompt caching
327
+ if (!supportsPromptCaching(modelName)) {
313
328
  return messages;
314
329
  }
315
330
 
@@ -352,11 +367,15 @@ export function transformMessagesForClaudeCache(
352
367
 
353
368
  // Interval-based message caching: cache message at latest interval position (sliding window)
354
369
  if (index === intervalMessageIndex) {
355
- // If the message is a tool role, add cache control directly to the message
370
+ // If the message is a tool role, add cache control to the content block
356
371
  if (message.role === "tool") {
372
+ const content =
373
+ typeof message.content === "string" ? message.content : "";
374
+ const transformedContent = addCacheControlToContent(content, true);
375
+
357
376
  return {
358
377
  ...message,
359
- cache_control: { type: "ephemeral" },
378
+ content: transformedContent,
360
379
  } as ChatCompletionMessageParam;
361
380
  }
362
381
  // If the message has tool calls, cache the last tool call instead of content
@@ -24,6 +24,7 @@ import { ReversionService } from "../services/reversionService.js";
24
24
  import { MemoryService } from "../services/memory.js";
25
25
  import { AutoMemoryService } from "../services/autoMemoryService.js";
26
26
  import { getGitMainRepoRoot } from "./gitUtils.js";
27
+ import { USER_MEMORY_FILE } from "./constants.js";
27
28
  import type { AgentOptions } from "../types/index.js";
28
29
  import type {
29
30
  PermissionMode,
@@ -150,6 +151,7 @@ export function setupAgentContainer(
150
151
  if (configurationService.resolveAutoMemoryEnabled()) {
151
152
  const autoMemoryDir = memoryService.getAutoMemoryDirectory(workdir);
152
153
  permissionManager.addSystemAdditionalDirectory(autoMemoryDir);
154
+ permissionManager.addSystemAdditionalDirectory(USER_MEMORY_FILE);
153
155
  }
154
156
  container.register("PermissionManager", permissionManager);
155
157
  permissionManager.setOnConfiguredPermissionModeChange((mode) => {
@@ -197,22 +197,6 @@ export function convertMessagesForAPI(
197
197
  });
198
198
  }
199
199
 
200
- // Handle SlashBlock
201
- if (block.type === "slash") {
202
- if (block.content && block.content.trim().length > 0) {
203
- contentParts.push({
204
- type: "text",
205
- text: block.content,
206
- });
207
- }
208
- if (block.result && block.result.trim().length > 0) {
209
- contentParts.push({
210
- type: "text",
211
- text: `<local-command-stdout>\n${stripAnsiColors(block.result)}\n</local-command-stdout>`,
212
- });
213
- }
214
- }
215
-
216
200
  // If there is an image, add image content
217
201
  if (
218
202
  block.type === "image" &&
@@ -20,26 +20,6 @@ export interface AddUserMessageParams extends UserMessageParams {
20
20
  id?: string;
21
21
  }
22
22
 
23
- export interface AddSlashParams {
24
- messages: Message[];
25
- command: string;
26
- args?: string;
27
- content?: string;
28
- id?: string;
29
- }
30
-
31
- export interface UpdateSlashParams {
32
- messages: Message[];
33
- command: string;
34
- messageId?: string;
35
- args?: string;
36
- content?: string;
37
- result?: string;
38
- stage?: "running" | "success" | "error" | "aborted";
39
- error?: string;
40
- shortResult?: string;
41
- }
42
-
43
23
  export interface UpdateToolBlockParams {
44
24
  messages: Message[];
45
25
  id: string;
@@ -175,95 +155,6 @@ export const addUserMessageToMessages = ({
175
155
  return [...messages, userMessage];
176
156
  };
177
157
 
178
- /**
179
- * Add a slash command message to the conversation.
180
- */
181
- export const addSlashMessageToMessages = ({
182
- messages,
183
- command,
184
- args,
185
- content,
186
- id,
187
- }: AddSlashParams): Message[] => {
188
- const slashMessage: Message = {
189
- id: id || generateMessageId(),
190
- role: "user",
191
- blocks: [
192
- {
193
- type: "slash",
194
- command,
195
- args,
196
- content,
197
- stage: "running",
198
- },
199
- ],
200
- };
201
- return [...messages, slashMessage];
202
- };
203
-
204
- /**
205
- * Update a slash block in a message.
206
- */
207
- export const updateSlashBlockInMessage = ({
208
- messages,
209
- command,
210
- messageId,
211
- args,
212
- content,
213
- result,
214
- stage,
215
- error,
216
- shortResult,
217
- }: UpdateSlashParams): Message[] => {
218
- const newMessages = [...messages];
219
-
220
- // If messageId is provided, target that specific message
221
- if (messageId) {
222
- const messageIndex = newMessages.findIndex((msg) => msg.id === messageId);
223
- if (messageIndex !== -1) {
224
- const slashBlockIndex = newMessages[messageIndex].blocks.findIndex(
225
- (block) => block.type === "slash" && block.command === command,
226
- );
227
-
228
- if (slashBlockIndex !== -1) {
229
- const slashBlock = newMessages[messageIndex].blocks[slashBlockIndex];
230
- if (slashBlock.type === "slash") {
231
- if (args !== undefined) slashBlock.args = args;
232
- if (content !== undefined) slashBlock.content = content;
233
- if (result !== undefined) slashBlock.result = result;
234
- if (stage !== undefined) slashBlock.stage = stage;
235
- if (error !== undefined) slashBlock.error = error;
236
- if (shortResult !== undefined) slashBlock.shortResult = shortResult;
237
- }
238
- }
239
- }
240
- return newMessages;
241
- }
242
-
243
- // Find the last user message with a slash block for this command
244
- for (let i = newMessages.length - 1; i >= 0; i--) {
245
- const msg = newMessages[i];
246
- if (msg.role === "user") {
247
- const slashBlockIndex = msg.blocks.findIndex(
248
- (block) => block.type === "slash" && block.command === command,
249
- );
250
- if (slashBlockIndex !== -1) {
251
- const slashBlock = msg.blocks[slashBlockIndex];
252
- if (slashBlock.type === "slash") {
253
- if (args !== undefined) slashBlock.args = args;
254
- if (content !== undefined) slashBlock.content = content;
255
- if (result !== undefined) slashBlock.result = result;
256
- if (stage !== undefined) slashBlock.stage = stage;
257
- if (error !== undefined) slashBlock.error = error;
258
- if (shortResult !== undefined) slashBlock.shortResult = shortResult;
259
- }
260
- break;
261
- }
262
- }
263
- }
264
- return newMessages;
265
- };
266
-
267
158
  /**
268
159
  * Update a user message's content by its ID.
269
160
  */
@@ -669,11 +560,6 @@ export function getMessageContent(message: Message): string {
669
560
  return textBlock.content;
670
561
  }
671
562
 
672
- const slashBlock = message.blocks.find((block) => block.type === "slash");
673
- if (slashBlock && "command" in slashBlock) {
674
- return `/${slashBlock.command}${slashBlock.args ? ` ${slashBlock.args}` : ""}`;
675
- }
676
-
677
563
  const bangBlock = message.blocks.find((block) => block.type === "bang");
678
564
  if (bangBlock && "command" in bangBlock) {
679
565
  return `!${bangBlock.command}`;