wave-agent-sdk 0.11.6 → 0.11.7

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 (105) hide show
  1. package/builtin/skills/init/SKILL.md +2 -0
  2. package/builtin/skills/settings/SKILLS.md +3 -2
  3. package/builtin/skills/settings/SUBAGENTS.md +1 -3
  4. package/dist/agent.d.ts +6 -0
  5. package/dist/agent.d.ts.map +1 -1
  6. package/dist/agent.js +18 -1
  7. package/dist/constants/tools.d.ts +1 -1
  8. package/dist/constants/tools.d.ts.map +1 -1
  9. package/dist/constants/tools.js +1 -1
  10. package/dist/managers/MemoryRuleManager.d.ts.map +1 -1
  11. package/dist/managers/MemoryRuleManager.js +1 -9
  12. package/dist/managers/aiManager.d.ts.map +1 -1
  13. package/dist/managers/aiManager.js +22 -3
  14. package/dist/managers/messageManager.d.ts +13 -5
  15. package/dist/managers/messageManager.d.ts.map +1 -1
  16. package/dist/managers/messageManager.js +62 -34
  17. package/dist/managers/pluginManager.d.ts.map +1 -1
  18. package/dist/managers/pluginManager.js +4 -2
  19. package/dist/managers/slashCommandManager.d.ts +2 -0
  20. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  21. package/dist/managers/slashCommandManager.js +98 -4
  22. package/dist/managers/toolManager.d.ts.map +1 -1
  23. package/dist/managers/toolManager.js +8 -2
  24. package/dist/prompts/index.d.ts +2 -0
  25. package/dist/prompts/index.d.ts.map +1 -1
  26. package/dist/prompts/index.js +5 -0
  27. package/dist/services/GitService.d.ts +1 -0
  28. package/dist/services/GitService.d.ts.map +1 -1
  29. package/dist/services/GitService.js +16 -0
  30. package/dist/services/MarketplaceService.d.ts +7 -0
  31. package/dist/services/MarketplaceService.d.ts.map +1 -1
  32. package/dist/services/MarketplaceService.js +321 -252
  33. package/dist/services/aiService.d.ts +34 -0
  34. package/dist/services/aiService.d.ts.map +1 -1
  35. package/dist/services/aiService.js +124 -1
  36. package/dist/services/initializationService.d.ts.map +1 -1
  37. package/dist/services/initializationService.js +18 -0
  38. package/dist/tools/agentTool.js +3 -3
  39. package/dist/tools/bashTool.d.ts.map +1 -1
  40. package/dist/tools/bashTool.js +4 -4
  41. package/dist/tools/editTool.d.ts.map +1 -1
  42. package/dist/tools/editTool.js +2 -0
  43. package/dist/tools/globTool.d.ts.map +1 -1
  44. package/dist/tools/globTool.js +15 -3
  45. package/dist/tools/grepTool.d.ts.map +1 -1
  46. package/dist/tools/grepTool.js +38 -12
  47. package/dist/tools/readTool.d.ts.map +1 -1
  48. package/dist/tools/readTool.js +61 -0
  49. package/dist/tools/skillTool.js +2 -2
  50. package/dist/tools/types.d.ts +16 -0
  51. package/dist/tools/types.d.ts.map +1 -1
  52. package/dist/tools/webFetchTool.d.ts +3 -0
  53. package/dist/tools/webFetchTool.d.ts.map +1 -0
  54. package/dist/tools/webFetchTool.js +171 -0
  55. package/dist/tools/writeTool.d.ts.map +1 -1
  56. package/dist/tools/writeTool.js +2 -0
  57. package/dist/types/commands.d.ts +1 -1
  58. package/dist/types/commands.d.ts.map +1 -1
  59. package/dist/types/messaging.d.ts +1 -0
  60. package/dist/types/messaging.d.ts.map +1 -1
  61. package/dist/utils/bashParser.d.ts +14 -0
  62. package/dist/utils/bashParser.d.ts.map +1 -1
  63. package/dist/utils/bashParser.js +243 -142
  64. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  65. package/dist/utils/convertMessagesForAPI.js +7 -0
  66. package/dist/utils/fileUtils.d.ts +8 -0
  67. package/dist/utils/fileUtils.d.ts.map +1 -1
  68. package/dist/utils/fileUtils.js +52 -0
  69. package/dist/utils/messageOperations.d.ts +12 -3
  70. package/dist/utils/messageOperations.d.ts.map +1 -1
  71. package/dist/utils/messageOperations.js +77 -9
  72. package/package.json +4 -2
  73. package/src/agent.ts +19 -1
  74. package/src/constants/tools.ts +1 -1
  75. package/src/managers/MemoryRuleManager.ts +1 -10
  76. package/src/managers/aiManager.ts +23 -3
  77. package/src/managers/messageManager.ts +76 -38
  78. package/src/managers/pluginManager.ts +4 -2
  79. package/src/managers/slashCommandManager.ts +130 -4
  80. package/src/managers/toolManager.ts +11 -2
  81. package/src/prompts/index.ts +6 -0
  82. package/src/services/GitService.ts +20 -0
  83. package/src/services/MarketplaceService.ts +397 -324
  84. package/src/services/aiService.ts +197 -1
  85. package/src/services/initializationService.ts +38 -0
  86. package/src/tools/agentTool.ts +3 -3
  87. package/src/tools/bashTool.ts +3 -4
  88. package/src/tools/editTool.ts +3 -0
  89. package/src/tools/globTool.ts +16 -3
  90. package/src/tools/grepTool.ts +41 -13
  91. package/src/tools/readTool.ts +69 -0
  92. package/src/tools/skillTool.ts +2 -2
  93. package/src/tools/types.ts +13 -0
  94. package/src/tools/webFetchTool.ts +194 -0
  95. package/src/tools/writeTool.ts +3 -0
  96. package/src/types/commands.ts +1 -1
  97. package/src/types/messaging.ts +1 -0
  98. package/src/utils/bashParser.ts +268 -157
  99. package/src/utils/convertMessagesForAPI.ts +8 -0
  100. package/src/utils/fileUtils.ts +69 -0
  101. package/src/utils/messageOperations.ts +84 -9
  102. package/dist/tools/taskOutputTool.d.ts +0 -3
  103. package/dist/tools/taskOutputTool.d.ts.map +0 -1
  104. package/dist/tools/taskOutputTool.js +0 -198
  105. package/src/tools/taskOutputTool.ts +0 -222
@@ -1,5 +1,6 @@
1
1
  import { readFile, stat } from "fs/promises";
2
2
  import { extname } from "path";
3
+ import { createHash } from "crypto";
3
4
  import { logger } from "../utils/globalLogger.js";
4
5
  import { resolvePath, getDisplayPath } from "../utils/path.js";
5
6
  import { formatLineNumberPrefix } from "../utils/stringUtils.js";
@@ -99,6 +100,10 @@ async function processImageFile(filePath, context) {
99
100
  mediaType: mimeType,
100
101
  },
101
102
  ],
103
+ metadata: {
104
+ type: "image",
105
+ mimeType,
106
+ },
102
107
  };
103
108
  }
104
109
  catch (error) {
@@ -164,12 +169,18 @@ Usage:
164
169
  error: "file_path parameter is required and must be a string",
165
170
  };
166
171
  }
172
+ // Touch file to track it in context
173
+ context.messageManager?.touchFile(filePath);
167
174
  // Check for binary document formats
168
175
  if (isBinaryDocument(filePath)) {
176
+ const isPdf = filePath.toLowerCase().endsWith(".pdf");
169
177
  return {
170
178
  success: false,
171
179
  content: "",
172
180
  error: getBinaryDocumentError(filePath),
181
+ metadata: {
182
+ type: isPdf ? "pdf" : "binary",
183
+ },
173
184
  };
174
185
  }
175
186
  // Check permissions
@@ -194,7 +205,46 @@ Usage:
194
205
  const actualFilePath = filePath.startsWith("/")
195
206
  ? filePath
196
207
  : resolvePath(filePath, context.workdir);
208
+ const stats = await stat(actualFilePath);
209
+ // Deduplication
210
+ if (context.readFileState) {
211
+ const state = context.readFileState.get(actualFilePath);
212
+ if (state && state.mtime === stats.mtime.getTime()) {
213
+ return {
214
+ success: true,
215
+ content: `File ${filePath} has not changed since last read.`,
216
+ shortResult: "File unchanged",
217
+ metadata: {
218
+ type: "file_unchanged",
219
+ },
220
+ };
221
+ }
222
+ }
223
+ // Resource Limits
224
+ const maxSizeBytes = context.fileReadingLimits?.maxSizeBytes ?? 1024 * 1024; // Default 1MB
225
+ if (stats.size > maxSizeBytes &&
226
+ typeof offset !== "number" &&
227
+ typeof limit !== "number") {
228
+ return {
229
+ success: false,
230
+ content: "",
231
+ error: `File size (${(stats.size / 1024).toFixed(2)}KB) exceeds limit (${(maxSizeBytes / 1024).toFixed(2)}KB). Please use offset and limit to read a portion of the file.`,
232
+ metadata: {
233
+ type: "error_limit_exceeded",
234
+ size: stats.size,
235
+ limit: maxSizeBytes,
236
+ },
237
+ };
238
+ }
197
239
  const fileContent = await readFile(actualFilePath, "utf-8");
240
+ // Update readFileState
241
+ if (context.readFileState) {
242
+ const hash = createHash("sha256").update(fileContent).digest("hex");
243
+ context.readFileState.set(actualFilePath, {
244
+ mtime: stats.mtime.getTime(),
245
+ hash,
246
+ });
247
+ }
198
248
  // Check if file is empty
199
249
  if (fileContent.length === 0) {
200
250
  logger.warn(`File ${filePath} exists but has empty contents`);
@@ -202,6 +252,10 @@ Usage:
202
252
  success: true,
203
253
  content: "⚠️ System reminder: This file exists but has empty contents.",
204
254
  shortResult: "Empty file",
255
+ metadata: {
256
+ type: "text",
257
+ isEmpty: true,
258
+ },
205
259
  };
206
260
  }
207
261
  const allLines = fileContent.split("\n");
@@ -255,6 +309,13 @@ Usage:
255
309
  success: true,
256
310
  content,
257
311
  shortResult: `Read ${selectedLines.length} lines${totalLines > 2000 ? " (truncated)" : ""}`,
312
+ metadata: {
313
+ type: "text",
314
+ totalLines,
315
+ startLine,
316
+ endLine,
317
+ truncated: endLine < totalLines,
318
+ },
258
319
  };
259
320
  }
260
321
  catch (error) {
@@ -105,7 +105,7 @@ export const skillTool = {
105
105
  () => {
106
106
  // Update shortResult
107
107
  const messages = instance.messageManager.getMessages();
108
- const tokens = instance.messageManager.getlatestTotalTokens();
108
+ const tokens = instance.messageManager.getLatestTotalTokens();
109
109
  const lastTools = instance.lastTools;
110
110
  const toolCount = countToolBlocks(messages);
111
111
  const summary = formatToolTokenSummary(toolCount, tokens);
@@ -124,7 +124,7 @@ export const skillTool = {
124
124
  // Cleanup subagent instance after agent completion
125
125
  subagentManager.cleanupInstance(instance.subagentId);
126
126
  const messages = instance.messageManager.getMessages();
127
- const tokens = instance.messageManager.getlatestTotalTokens();
127
+ const tokens = instance.messageManager.getLatestTotalTokens();
128
128
  const toolCount = countToolBlocks(messages);
129
129
  const summary = formatToolTokenSummary(toolCount, tokens);
130
130
  return {
@@ -61,6 +61,12 @@ export interface ToolContext {
61
61
  skillManager?: import("../managers/skillManager.js").SkillManager;
62
62
  /** Cron manager instance for scheduling tasks */
63
63
  cronManager?: import("../managers/cronManager.js").CronManager;
64
+ /** AI manager instance for AI operations */
65
+ aiManager?: import("../managers/aiManager.js").AIManager;
66
+ /** AI service instance for AI operations */
67
+ aiService?: typeof import("../services/aiService.js");
68
+ /** Message manager instance for message operations */
69
+ messageManager?: import("../managers/messageManager.js").MessageManager;
64
70
  /** Current session ID */
65
71
  sessionId?: string;
66
72
  /** The ID of the current tool call */
@@ -69,5 +75,15 @@ export interface ToolContext {
69
75
  onShortResultUpdate?: (shortResult: string) => void;
70
76
  /** Callback to update the full result of the current tool block */
71
77
  onResultUpdate?: (result: string) => void;
78
+ /** Limits for file reading operations */
79
+ fileReadingLimits?: {
80
+ maxSizeBytes: number;
81
+ maxTokens: number;
82
+ };
83
+ /** State of files read in the current session for deduplication */
84
+ readFileState?: Map<string, {
85
+ mtime: number;
86
+ hash: string;
87
+ }>;
72
88
  }
73
89
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ToolPlugin } from "./types.js";
2
+ export declare const webFetchTool: ToolPlugin;
3
+ //# sourceMappingURL=webFetchTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webFetchTool.d.ts","sourceRoot":"","sources":["../../src/tools/webFetchTool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AA+BtE,eAAO,MAAM,YAAY,EAAE,UAgK1B,CAAC"}
@@ -0,0 +1,171 @@
1
+ import TurndownService from "turndown";
2
+ import { WEB_FETCH_TOOL_NAME } from "../constants/tools.js";
3
+ import { logger } from "../utils/globalLogger.js";
4
+ const CACHE_TTL = 15 * 60 * 1000; // 15 minutes
5
+ const cache = new Map();
6
+ function getFromCache(url) {
7
+ const cached = cache.get(url);
8
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
9
+ return cached.content;
10
+ }
11
+ if (cached) {
12
+ cache.delete(url);
13
+ }
14
+ return null;
15
+ }
16
+ function setToCache(url, content) {
17
+ cache.set(url, { content, timestamp: Date.now() });
18
+ }
19
+ // Clean up cache every 15 minutes
20
+ setInterval(() => {
21
+ const now = Date.now();
22
+ for (const [url, cached] of cache.entries()) {
23
+ if (now - cached.timestamp >= CACHE_TTL) {
24
+ cache.delete(url);
25
+ }
26
+ }
27
+ }, CACHE_TTL);
28
+ export const webFetchTool = {
29
+ name: WEB_FETCH_TOOL_NAME,
30
+ config: {
31
+ type: "function",
32
+ function: {
33
+ name: WEB_FETCH_TOOL_NAME,
34
+ description: `IMPORTANT: WebFetch WILL FAIL for authenticated or private URLs. Before using this tool, check if the URL points to an authenticated service (e.g. Google Docs, Confluence, Jira, GitHub). If so, look for a specialized MCP tool that provides authenticated access.
35
+
36
+ - Fetches content from a specified URL and processes it using an AI model
37
+ - Takes a URL and a prompt as input
38
+ - Fetches the URL content, converts HTML to markdown
39
+ - Processes the content with the prompt using a small, fast model
40
+ - Returns the model's response about the content
41
+ - Use this tool when you need to retrieve and analyze web content
42
+
43
+ Usage notes:
44
+ - IMPORTANT: If an MCP-provided web fetch tool is available, prefer using that tool instead of this one, as it may have fewer restrictions.
45
+ - The URL must be a fully-formed valid URL
46
+ - HTTP URLs will be automatically upgraded to HTTPS
47
+ - The prompt should describe what information you want to extract from the page
48
+ - This tool is read-only and does not modify any files
49
+ - Results may be summarized if the content is very large
50
+ - Includes a self-cleaning 15-minute cache for faster responses when repeatedly accessing the same URL
51
+ - When a URL redirects to a different host, the tool will inform you and provide the redirect URL in a special format. You should then make a new WebFetch request with the redirect URL to fetch the content.
52
+ - For GitHub URLs, prefer using the gh CLI via Bash instead (e.g., gh pr view, gh issue view, gh api).`,
53
+ parameters: {
54
+ type: "object",
55
+ properties: {
56
+ url: {
57
+ type: "string",
58
+ description: "The URL to fetch content from",
59
+ format: "uri",
60
+ },
61
+ prompt: {
62
+ type: "string",
63
+ description: "The prompt to run on the fetched content",
64
+ },
65
+ },
66
+ required: ["url", "prompt"],
67
+ additionalProperties: false,
68
+ },
69
+ },
70
+ },
71
+ execute: async (args, context) => {
72
+ let url = args.url;
73
+ const prompt = args.prompt;
74
+ if (!url || !prompt) {
75
+ return {
76
+ success: false,
77
+ content: "",
78
+ error: "Both url and prompt parameters are required",
79
+ };
80
+ }
81
+ // Upgrade HTTP to HTTPS
82
+ if (url.startsWith("http://")) {
83
+ url = "https://" + url.substring(7);
84
+ }
85
+ // Check for GitHub URLs
86
+ if (url.includes("github.com")) {
87
+ return {
88
+ success: false,
89
+ content: "",
90
+ error: "For GitHub URLs, please use the 'gh' CLI via the Bash tool instead (e.g., 'gh pr view', 'gh issue view', 'gh api').",
91
+ };
92
+ }
93
+ try {
94
+ let markdown = getFromCache(url);
95
+ if (!markdown) {
96
+ const response = await fetch(url, {
97
+ redirect: "manual",
98
+ headers: {
99
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
100
+ },
101
+ });
102
+ if (response.status >= 300 && response.status < 400) {
103
+ const location = response.headers.get("location");
104
+ if (location) {
105
+ const redirectUrl = new URL(location, url).toString();
106
+ const originalHost = new URL(url).host;
107
+ const redirectHost = new URL(redirectUrl).host;
108
+ if (originalHost !== redirectHost) {
109
+ return {
110
+ success: true,
111
+ content: `REDIRECT_TO: ${redirectUrl}\nThe URL redirected to a different host. Please make a new WebFetch request with this redirect URL if you wish to continue.`,
112
+ };
113
+ }
114
+ // If same host, we could follow it, but the requirement says "When a URL redirects to a different host, the tool will inform you".
115
+ // For simplicity and following the requirement strictly, let's just return the redirect for different hosts.
116
+ // If it's the same host, we can try to fetch again or just return it too.
117
+ return {
118
+ success: true,
119
+ content: `REDIRECT_TO: ${redirectUrl}\nThe URL redirected. Please make a new WebFetch request with this redirect URL.`,
120
+ };
121
+ }
122
+ }
123
+ if (!response.ok) {
124
+ return {
125
+ success: false,
126
+ content: "",
127
+ error: `Failed to fetch URL: ${response.status} ${response.statusText}`,
128
+ };
129
+ }
130
+ const html = await response.text();
131
+ const turndownService = new TurndownService();
132
+ markdown = turndownService.turndown(html);
133
+ setToCache(url, markdown);
134
+ }
135
+ // Process with AI
136
+ if (!context.aiManager || !context.aiService) {
137
+ return {
138
+ success: false,
139
+ content: markdown,
140
+ error: "AI Manager or AI Service not available for processing content",
141
+ };
142
+ }
143
+ const modelConfig = context.aiManager.getModelConfig();
144
+ const fastModel = modelConfig.fastModel;
145
+ const aiResponse = await context.aiService.processWebContent({
146
+ gatewayConfig: context.aiManager.getGatewayConfig(),
147
+ modelConfig: modelConfig,
148
+ content: markdown,
149
+ prompt: prompt,
150
+ model: fastModel,
151
+ abortSignal: context.abortSignal,
152
+ });
153
+ return {
154
+ success: true,
155
+ content: aiResponse.content || "",
156
+ shortResult: `Processed content from ${url}`,
157
+ };
158
+ }
159
+ catch (error) {
160
+ logger.error(`WebFetch failed for ${url}:`, error);
161
+ return {
162
+ success: false,
163
+ content: "",
164
+ error: `WebFetch failed: ${error instanceof Error ? error.message : String(error)}`,
165
+ };
166
+ }
167
+ },
168
+ formatCompactParams: (params) => {
169
+ return `Fetch ${params.url}`;
170
+ },
171
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"writeTool.d.ts","sourceRoot":"","sources":["../../src/tools/writeTool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,UAoMvB,CAAC"}
1
+ {"version":3,"file":"writeTool.d.ts","sourceRoot":"","sources":["../../src/tools/writeTool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,UAuMvB,CAAC"}
@@ -57,6 +57,8 @@ Usage:
57
57
  error: "content parameter is required and must be a string",
58
58
  };
59
59
  }
60
+ // Touch file to track it in context
61
+ context.messageManager?.touchFile(filePath);
60
62
  try {
61
63
  const resolvedPath = resolvePath(filePath, context.workdir);
62
64
  // Check if file already exists
@@ -6,7 +6,7 @@ export interface SlashCommand {
6
6
  id: string;
7
7
  name: string;
8
8
  description: string;
9
- handler: (args?: string) => Promise<void> | void;
9
+ handler: (args?: string, signal?: AbortSignal) => Promise<void> | void;
10
10
  }
11
11
  export interface CustomSlashCommandConfig {
12
12
  model?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/types/commands.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,wBAAwB,CAAC;CACnC"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/types/commands.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACxE;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,wBAAwB,CAAC;CACnC"}
@@ -13,6 +13,7 @@ export interface Message {
13
13
  blocks: MessageBlock[];
14
14
  usage?: Usage;
15
15
  additionalFields?: Record<string, unknown>;
16
+ isMeta?: boolean;
16
17
  }
17
18
  export type MessageBlock = TextBlock | ErrorBlock | ToolBlock | ImageBlock | BangBlock | CompressBlock | ReasoningBlock | FileHistoryBlock;
18
19
  export interface TextBlock {
@@ -1 +1 @@
1
- {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/types/messaging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,oBAAY,aAAa;IACvB,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5C;AAED,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,UAAU,GACV,SAAS,GACT,UAAU,GACV,SAAS,GACT,aAAa,GACb,cAAc,GACd,gBAAgB,CAAC;AAErB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,KAAK,CAAC;QAEb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,CAAC;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,OAAO,gBAAgB,EAAE,YAAY,EAAE,CAAC;CACpD"}
1
+ {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/types/messaging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,oBAAY,aAAa;IACvB,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,UAAU,GACV,SAAS,GACT,UAAU,GACV,SAAS,GACT,aAAa,GACb,cAAc,GACd,gBAAgB,CAAC;AAErB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,KAAK,CAAC;QAEb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,CAAC;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,OAAO,gBAAgB,EAAE,YAAY,EAAE,CAAC;CACpD"}
@@ -28,6 +28,20 @@ export declare function isBashHeredocWrite(command: string): boolean;
28
28
  * and should not have persistent permissions.
29
29
  */
30
30
  export declare const DANGEROUS_COMMANDS: string[];
31
+ /**
32
+ * Registry of commands and their expected subcommand depth for smart prefix extraction.
33
+ * For example, 'git: 2' means 'git commit' is a valid prefix, but 'git' alone is not.
34
+ * Multi-word keys can be used for more specific rules.
35
+ */
36
+ export interface ToolRule {
37
+ depth: number;
38
+ scopeFlags?: string[];
39
+ }
40
+ export declare const TOOL_RULES: Record<string, ToolRule>;
41
+ /**
42
+ * Registry of dangerous subcommands for specific tools.
43
+ */
44
+ export declare const DANGEROUS_SUBCOMMANDS: Record<string, string[]>;
31
45
  /**
32
46
  * Extracts a "smart prefix" from a bash command based on common developer tools.
33
47
  * Returns null if the command is blacklisted or cannot be safely prefix-matched.
@@ -1 +1 @@
1
- {"version":3,"file":"bashParser.d.ts","sourceRoot":"","sources":["../../src/utils/bashParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoH1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA2CpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuHzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAkG7D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsCnD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAa9B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8L7D"}
1
+ {"version":3,"file":"bashParser.d.ts","sourceRoot":"","sources":["../../src/utils/bashParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoH1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA2CpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuHzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAkG7D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsCnD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAyB9B,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAoD/C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAQ1D,CAAC;AA2DF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA2J7D"}