wave-agent-sdk 1.0.4 → 1.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.
- package/dist/agent.d.ts +23 -1
- package/dist/agent.js +34 -4
- package/dist/managers/aiManager.d.ts +36 -0
- package/dist/managers/aiManager.js +240 -8
- package/dist/managers/messageManager.d.ts +1 -3
- package/dist/managers/messageManager.js +19 -9
- package/dist/managers/slashCommandManager.js +28 -0
- package/dist/managers/subagentManager.d.ts +0 -2
- package/dist/services/session.js +2 -9
- package/dist/telemetry/instrumentation.d.ts +1 -1
- package/dist/telemetry/instrumentation.js +57 -28
- package/dist/tools/bashTool.js +16 -6
- package/dist/tools/grepTool.js +11 -3
- package/dist/types/index.d.ts +3 -0
- package/dist/types/messaging.d.ts +2 -0
- package/dist/utils/containerSetup.js +0 -3
- package/dist/utils/messageOperations.d.ts +10 -1
- package/dist/utils/messageOperations.js +19 -1
- package/dist/utils/notificationXml.js +5 -0
- package/dist/utils/ripgrep.d.ts +4 -4
- package/dist/utils/ripgrep.js +4 -27
- package/package.json +20 -8
- package/bin/rg +0 -79
- package/dist/managers/forkedAgentManager.d.ts +0 -50
- package/dist/managers/forkedAgentManager.js +0 -130
- package/scripts/install_ripgrep.js +0 -111
- package/scripts/postinstall.js +0 -38
- package/src/agent.ts +0 -1271
- package/src/constants/subagents.ts +0 -4
- package/src/constants/toolLimits.ts +0 -15
- package/src/constants/tools.ts +0 -24
- package/src/core/plugin.ts +0 -237
- package/src/core/session.ts +0 -9
- package/src/index.ts +0 -38
- package/src/managers/MemoryRuleManager.ts +0 -198
- package/src/managers/aiManager.ts +0 -2429
- package/src/managers/backgroundTaskManager.ts +0 -480
- package/src/managers/bangManager.ts +0 -119
- package/src/managers/cronManager.ts +0 -401
- package/src/managers/foregroundTaskManager.ts +0 -30
- package/src/managers/forkedAgentManager.ts +0 -216
- package/src/managers/hookManager.ts +0 -1089
- package/src/managers/liveConfigManager.ts +0 -445
- package/src/managers/lspManager.ts +0 -470
- package/src/managers/mcpManager.ts +0 -1010
- package/src/managers/messageManager.ts +0 -1180
- package/src/managers/messageQueue.ts +0 -157
- package/src/managers/permissionManager.ts +0 -1140
- package/src/managers/planManager.ts +0 -112
- package/src/managers/pluginManager.ts +0 -330
- package/src/managers/pluginScopeManager.ts +0 -124
- package/src/managers/reversionManager.ts +0 -178
- package/src/managers/skillManager.ts +0 -578
- package/src/managers/slashCommandManager.ts +0 -564
- package/src/managers/subagentManager.ts +0 -915
- package/src/managers/toolManager.ts +0 -489
- package/src/managers/workflowManager.ts +0 -493
- package/src/prompts/autoMemory.ts +0 -33
- package/src/prompts/autoMemoryExtraction.ts +0 -146
- package/src/prompts/index.ts +0 -506
- package/src/prompts/planModeReminders.ts +0 -126
- package/src/services/GitService.ts +0 -131
- package/src/services/MarketplaceService.ts +0 -1052
- package/src/services/MemoryRuleService.ts +0 -71
- package/src/services/aiService.ts +0 -919
- package/src/services/authService.ts +0 -565
- package/src/services/autoMemoryService.ts +0 -280
- package/src/services/configurationService.ts +0 -1520
- package/src/services/fileWatcher.ts +0 -319
- package/src/services/hook.ts +0 -348
- package/src/services/initializationService.ts +0 -357
- package/src/services/interactionService.ts +0 -229
- package/src/services/jsonlHandler.ts +0 -295
- package/src/services/memory.ts +0 -234
- package/src/services/pluginLoader.ts +0 -252
- package/src/services/remoteSettingsService.ts +0 -366
- package/src/services/reversionService.ts +0 -122
- package/src/services/session.ts +0 -922
- package/src/services/taskManager.ts +0 -321
- package/src/telemetry/events.ts +0 -65
- package/src/telemetry/instrumentation.ts +0 -499
- package/src/telemetry/sessionTracing.ts +0 -348
- package/src/tools/agentTool.ts +0 -322
- package/src/tools/askUserQuestion.ts +0 -160
- package/src/tools/bashTool.ts +0 -621
- package/src/tools/buildTool.ts +0 -61
- package/src/tools/cronCreateTool.ts +0 -161
- package/src/tools/cronDeleteTool.ts +0 -51
- package/src/tools/cronListTool.ts +0 -47
- package/src/tools/editTool.ts +0 -313
- package/src/tools/enterPlanMode.ts +0 -124
- package/src/tools/enterWorktreeTool.ts +0 -190
- package/src/tools/exitPlanMode.ts +0 -139
- package/src/tools/exitWorktreeTool.ts +0 -236
- package/src/tools/globTool.ts +0 -167
- package/src/tools/grepTool.ts +0 -399
- package/src/tools/lspTool.ts +0 -883
- package/src/tools/readTool.ts +0 -426
- package/src/tools/skillTool.ts +0 -248
- package/src/tools/taskManagementTools.ts +0 -574
- package/src/tools/taskStopTool.ts +0 -78
- package/src/tools/types.ts +0 -137
- package/src/tools/webFetchTool.ts +0 -373
- package/src/tools/workflowTool.ts +0 -205
- package/src/tools/writeTool.ts +0 -267
- package/src/types/agent.ts +0 -128
- package/src/types/auth.ts +0 -19
- package/src/types/commands.ts +0 -30
- package/src/types/config.ts +0 -43
- package/src/types/configuration.ts +0 -168
- package/src/types/core.ts +0 -105
- package/src/types/cron.ts +0 -13
- package/src/types/environment.ts +0 -106
- package/src/types/fileSearch.ts +0 -4
- package/src/types/history.ts +0 -7
- package/src/types/hooks.ts +0 -256
- package/src/types/index.ts +0 -41
- package/src/types/lsp.ts +0 -98
- package/src/types/marketplace.ts +0 -71
- package/src/types/mcp.ts +0 -43
- package/src/types/memoryRule.ts +0 -31
- package/src/types/messaging.ts +0 -114
- package/src/types/permissions.ts +0 -80
- package/src/types/plugins.ts +0 -39
- package/src/types/processes.ts +0 -99
- package/src/types/reversion.ts +0 -29
- package/src/types/session.ts +0 -12
- package/src/types/skills.ts +0 -108
- package/src/types/tasks.ts +0 -13
- package/src/types/telemetry.ts +0 -98
- package/src/types/tools.ts +0 -44
- package/src/types/workflow.ts +0 -6
- package/src/utils/abortUtils.ts +0 -118
- package/src/utils/atomicWrite.ts +0 -61
- package/src/utils/bashParser.ts +0 -899
- package/src/utils/cacheControlUtils.ts +0 -426
- package/src/utils/commandArgumentParser.ts +0 -161
- package/src/utils/commandPathResolver.ts +0 -88
- package/src/utils/configPaths.ts +0 -220
- package/src/utils/configValidator.ts +0 -100
- package/src/utils/constants.ts +0 -39
- package/src/utils/container.ts +0 -92
- package/src/utils/containerSetup.ts +0 -371
- package/src/utils/convertMessagesForAPI.ts +0 -326
- package/src/utils/cronTasks.ts +0 -128
- package/src/utils/cronTasksLock.ts +0 -182
- package/src/utils/cronToHuman.ts +0 -99
- package/src/utils/customCommands.ts +0 -95
- package/src/utils/editUtils.ts +0 -20
- package/src/utils/fileFormat.ts +0 -40
- package/src/utils/fileSearch.ts +0 -151
- package/src/utils/fileUtils.ts +0 -223
- package/src/utils/gitUtils.ts +0 -315
- package/src/utils/globalLogger.ts +0 -128
- package/src/utils/groupMessagesByApiRound.ts +0 -121
- package/src/utils/hookMatcher.ts +0 -176
- package/src/utils/markdownParser.ts +0 -317
- package/src/utils/mcpUtils.ts +0 -138
- package/src/utils/messageOperations.ts +0 -641
- package/src/utils/modelCapabilities.ts +0 -30
- package/src/utils/nameGenerator.ts +0 -99
- package/src/utils/notificationXml.ts +0 -57
- package/src/utils/openaiClient.ts +0 -251
- package/src/utils/parseCronExpression.ts +0 -78
- package/src/utils/path.ts +0 -72
- package/src/utils/pathEncoder.ts +0 -400
- package/src/utils/pathSafety.ts +0 -40
- package/src/utils/promptHistory.ts +0 -168
- package/src/utils/ripgrep.ts +0 -35
- package/src/utils/shellResolver.ts +0 -190
- package/src/utils/skillParser.ts +0 -246
- package/src/utils/stringUtils.ts +0 -156
- package/src/utils/subagentParser.ts +0 -279
- package/src/utils/taskReminder.ts +0 -96
- package/src/utils/tokenCalculation.ts +0 -43
- package/src/utils/tokenEstimate.ts +0 -34
- package/src/utils/toolResultStorage.ts +0 -117
- package/src/utils/worktreeSession.ts +0 -26
- package/src/utils/worktreeUtils.ts +0 -786
- package/src/workflow/budgetTracker.ts +0 -34
- package/src/workflow/concurrencyLimiter.ts +0 -47
- package/src/workflow/journal.ts +0 -95
- package/src/workflow/progressReporter.ts +0 -141
- package/src/workflow/runState.ts +0 -65
- package/src/workflow/scriptRuntime.ts +0 -274
- package/src/workflow/structuredOutput.ts +0 -123
- package/src/workflow/types.ts +0 -101
- package/src/workflow/workflowApis.ts +0 -410
- package/vendor/ripgrep/linux-aarch64/rg +0 -0
- package/vendor/ripgrep/linux-x86_64/rg +0 -0
- package/vendor/ripgrep/macos-aarch64/rg +0 -0
- package/vendor/ripgrep/macos-x86_64/rg +0 -0
- package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
- package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
|
-
import { exec } from "child_process";
|
|
3
|
-
import { promisify } from "util";
|
|
4
|
-
import { join } from "path";
|
|
5
|
-
import { tmpdir } from "os";
|
|
6
|
-
import type { CustomSlashCommandConfig } from "../types/index.js";
|
|
7
|
-
import {
|
|
8
|
-
SKILL_BASH_MAX_OUTPUT_CHARS,
|
|
9
|
-
PREVIEW_SIZE_BYTES,
|
|
10
|
-
} from "../constants/toolLimits.js";
|
|
11
|
-
import { logger } from "./globalLogger.js";
|
|
12
|
-
|
|
13
|
-
const execAsync = promisify(exec);
|
|
14
|
-
|
|
15
|
-
interface ParsedMarkdownFile {
|
|
16
|
-
content: string;
|
|
17
|
-
config?: CustomSlashCommandConfig;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Parse YAML frontmatter from markdown content
|
|
22
|
-
*/
|
|
23
|
-
export function parseFrontmatter(content: string): {
|
|
24
|
-
frontmatter?: Record<string, unknown>;
|
|
25
|
-
content: string;
|
|
26
|
-
} {
|
|
27
|
-
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
28
|
-
const match = content.match(frontmatterRegex);
|
|
29
|
-
|
|
30
|
-
if (!match) {
|
|
31
|
-
return { content };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const [, frontmatterStr, bodyContent] = match;
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
// Simple YAML parser for our use case (supports key: value and list items)
|
|
38
|
-
const frontmatter: Record<string, unknown> = {};
|
|
39
|
-
const lines = frontmatterStr.split("\n");
|
|
40
|
-
let currentKey: string | null = null;
|
|
41
|
-
|
|
42
|
-
for (const line of lines) {
|
|
43
|
-
const trimmedLine = line.trim();
|
|
44
|
-
if (!trimmedLine || trimmedLine.startsWith("#")) continue;
|
|
45
|
-
|
|
46
|
-
// Check if it's a list item
|
|
47
|
-
if (trimmedLine.startsWith("-") && currentKey) {
|
|
48
|
-
let value = trimmedLine.slice(1).trim();
|
|
49
|
-
if (value) {
|
|
50
|
-
// Remove surrounding quotes if present
|
|
51
|
-
if (
|
|
52
|
-
(value.startsWith('"') && value.endsWith('"')) ||
|
|
53
|
-
(value.startsWith("'") && value.endsWith("'"))
|
|
54
|
-
) {
|
|
55
|
-
value = value.slice(1, -1);
|
|
56
|
-
}
|
|
57
|
-
if (!Array.isArray(frontmatter[currentKey])) {
|
|
58
|
-
frontmatter[currentKey] = [];
|
|
59
|
-
}
|
|
60
|
-
(frontmatter[currentKey] as unknown[]).push(value);
|
|
61
|
-
}
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const colonIndex = trimmedLine.indexOf(":");
|
|
66
|
-
if (colonIndex === -1) continue;
|
|
67
|
-
|
|
68
|
-
const key = trimmedLine.slice(0, colonIndex).trim();
|
|
69
|
-
const value = trimmedLine.slice(colonIndex + 1).trim();
|
|
70
|
-
|
|
71
|
-
currentKey = key;
|
|
72
|
-
if (value) {
|
|
73
|
-
// Remove surrounding quotes if present
|
|
74
|
-
const unquotedValue =
|
|
75
|
-
(value.startsWith('"') && value.endsWith('"')) ||
|
|
76
|
-
(value.startsWith("'") && value.endsWith("'"))
|
|
77
|
-
? value.slice(1, -1)
|
|
78
|
-
: value;
|
|
79
|
-
frontmatter[key] = unquotedValue;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return { frontmatter, content: bodyContent };
|
|
84
|
-
} catch {
|
|
85
|
-
// If parsing fails, just return the content without frontmatter
|
|
86
|
-
return { content };
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Parse markdown file and extract config and content
|
|
92
|
-
*/
|
|
93
|
-
export function parseMarkdownFile(filePath: string): ParsedMarkdownFile {
|
|
94
|
-
try {
|
|
95
|
-
const fileContent = readFileSync(filePath, "utf-8");
|
|
96
|
-
const { frontmatter, content } = parseFrontmatter(fileContent);
|
|
97
|
-
|
|
98
|
-
let config: CustomSlashCommandConfig | undefined;
|
|
99
|
-
|
|
100
|
-
if (frontmatter) {
|
|
101
|
-
config = {};
|
|
102
|
-
|
|
103
|
-
if (frontmatter.model && typeof frontmatter.model === "string") {
|
|
104
|
-
config.model = frontmatter.model;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
frontmatter.description &&
|
|
109
|
-
typeof frontmatter.description === "string"
|
|
110
|
-
) {
|
|
111
|
-
config.description = frontmatter.description;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (frontmatter["allowed-tools"]) {
|
|
115
|
-
if (Array.isArray(frontmatter["allowed-tools"])) {
|
|
116
|
-
config.allowedTools = frontmatter["allowed-tools"].filter(
|
|
117
|
-
(item): item is string => typeof item === "string",
|
|
118
|
-
);
|
|
119
|
-
} else if (typeof frontmatter["allowed-tools"] === "string") {
|
|
120
|
-
config.allowedTools = frontmatter["allowed-tools"]
|
|
121
|
-
.split(",")
|
|
122
|
-
.map((s) => s.trim())
|
|
123
|
-
.filter((s) => s.length > 0);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
content: content.trim(),
|
|
130
|
-
config,
|
|
131
|
-
};
|
|
132
|
-
} catch (error) {
|
|
133
|
-
throw new Error(
|
|
134
|
-
`Failed to parse markdown file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Parse and execute bash commands in markdown content
|
|
141
|
-
*/
|
|
142
|
-
export interface BashCommandResult {
|
|
143
|
-
command: string;
|
|
144
|
-
output: string;
|
|
145
|
-
exitCode: number;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Block syntax pattern: ```! command ```
|
|
150
|
-
*/
|
|
151
|
-
const BLOCK_BASH_REGEX = /```!\s*\n?([\s\S]*?)\n?```/g;
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Inline syntax pattern: !`command`
|
|
155
|
-
*/
|
|
156
|
-
const INLINE_BASH_REGEX = /!`([^`]+)`/g;
|
|
157
|
-
|
|
158
|
-
export function parseBashCommands(content: string): {
|
|
159
|
-
commands: string[];
|
|
160
|
-
processedContent: string;
|
|
161
|
-
} {
|
|
162
|
-
// Performance gate: skip expensive regex if no bash pattern exists
|
|
163
|
-
// Covers the common case where 93% of skills have no bash substitution
|
|
164
|
-
if (!content.includes("!`") && !content.includes("```!")) {
|
|
165
|
-
return { commands: [], processedContent: content };
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const commands: string[] = [];
|
|
169
|
-
|
|
170
|
-
// Extract block commands
|
|
171
|
-
let blockMatch;
|
|
172
|
-
const blockRegex = new RegExp(
|
|
173
|
-
BLOCK_BASH_REGEX.source,
|
|
174
|
-
BLOCK_BASH_REGEX.flags,
|
|
175
|
-
);
|
|
176
|
-
while ((blockMatch = blockRegex.exec(content)) !== null) {
|
|
177
|
-
const cmd = blockMatch[1].trim();
|
|
178
|
-
if (cmd) {
|
|
179
|
-
commands.push(cmd);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Extract inline commands
|
|
184
|
-
let inlineMatch;
|
|
185
|
-
const inlineRegex = new RegExp(
|
|
186
|
-
INLINE_BASH_REGEX.source,
|
|
187
|
-
INLINE_BASH_REGEX.flags,
|
|
188
|
-
);
|
|
189
|
-
while ((inlineMatch = inlineRegex.exec(content)) !== null) {
|
|
190
|
-
const cmd = inlineMatch[1].trim();
|
|
191
|
-
if (cmd) {
|
|
192
|
-
commands.push(cmd);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// For now, return the content as-is. The actual command execution
|
|
197
|
-
// will be handled by the slash command manager
|
|
198
|
-
return {
|
|
199
|
-
commands,
|
|
200
|
-
processedContent: content,
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Truncate output if it exceeds the size limit.
|
|
206
|
-
* Writes to a temp file and returns a preview + file path if truncated.
|
|
207
|
-
*/
|
|
208
|
-
export function truncateOutput(output: string): string {
|
|
209
|
-
if (output.length <= SKILL_BASH_MAX_OUTPUT_CHARS) {
|
|
210
|
-
return output;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const preview = output.slice(0, PREVIEW_SIZE_BYTES);
|
|
214
|
-
const tempDir = join(tmpdir(), "wave-skill-bash");
|
|
215
|
-
mkdirSync(tempDir, { recursive: true });
|
|
216
|
-
|
|
217
|
-
const tempFile = join(
|
|
218
|
-
tempDir,
|
|
219
|
-
`output-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.txt`,
|
|
220
|
-
);
|
|
221
|
-
writeFileSync(tempFile, output, "utf-8");
|
|
222
|
-
|
|
223
|
-
return `${preview}\n\n[Output truncated (${output.length} chars). Full output saved to: ${tempFile}]`;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Format a bash command result for inclusion in skill content.
|
|
228
|
-
* Failed commands (non-zero exit code) are wrapped with an error indicator.
|
|
229
|
-
*/
|
|
230
|
-
function formatBashResult(result: BashCommandResult): string {
|
|
231
|
-
const output = truncateOutput(result.output);
|
|
232
|
-
if (result.exitCode !== 0) {
|
|
233
|
-
return `<error>Command failed (exit code ${result.exitCode}): ${output}</error>`;
|
|
234
|
-
}
|
|
235
|
-
return output;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Replace bash command placeholders with their outputs.
|
|
240
|
-
* Uses function replacer to avoid $$, $&, $' corruption in shell output.
|
|
241
|
-
* Handles both inline (!`cmd`) and block (```! cmd ```) syntax.
|
|
242
|
-
*/
|
|
243
|
-
export function replaceBashCommandsWithOutput(
|
|
244
|
-
content: string,
|
|
245
|
-
results: BashCommandResult[],
|
|
246
|
-
): string {
|
|
247
|
-
let processedContent = content;
|
|
248
|
-
let commandIndex = 0;
|
|
249
|
-
|
|
250
|
-
// Replace block syntax first: ```! command ```
|
|
251
|
-
processedContent = processedContent.replace(BLOCK_BASH_REGEX, () => {
|
|
252
|
-
if (commandIndex < results.length) {
|
|
253
|
-
const result = results[commandIndex++];
|
|
254
|
-
return formatBashResult(result);
|
|
255
|
-
}
|
|
256
|
-
return "";
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// Replace inline syntax: !`command`
|
|
260
|
-
processedContent = processedContent.replace(INLINE_BASH_REGEX, () => {
|
|
261
|
-
if (commandIndex < results.length) {
|
|
262
|
-
const result = results[commandIndex++];
|
|
263
|
-
return formatBashResult(result);
|
|
264
|
-
}
|
|
265
|
-
return "";
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
return processedContent;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Execute bash commands and return results
|
|
273
|
-
*/
|
|
274
|
-
export async function executeBashCommands(
|
|
275
|
-
commands: string[],
|
|
276
|
-
workdir: string,
|
|
277
|
-
timeout: number = 30000,
|
|
278
|
-
): Promise<BashCommandResult[]> {
|
|
279
|
-
const results: BashCommandResult[] = [];
|
|
280
|
-
|
|
281
|
-
for (const command of commands) {
|
|
282
|
-
try {
|
|
283
|
-
const { stdout, stderr } = await execAsync(command, {
|
|
284
|
-
cwd: workdir,
|
|
285
|
-
timeout,
|
|
286
|
-
});
|
|
287
|
-
results.push({
|
|
288
|
-
command,
|
|
289
|
-
output: (stdout + (stderr || "")).trim(),
|
|
290
|
-
exitCode: 0,
|
|
291
|
-
});
|
|
292
|
-
} catch (error: unknown) {
|
|
293
|
-
const execError = error as {
|
|
294
|
-
stdout?: string;
|
|
295
|
-
stderr?: string;
|
|
296
|
-
message?: string;
|
|
297
|
-
code?: number;
|
|
298
|
-
};
|
|
299
|
-
const errorOutput = (
|
|
300
|
-
(execError.stdout || "") +
|
|
301
|
-
(execError.stderr || "") +
|
|
302
|
-
(execError.message || "")
|
|
303
|
-
).trim();
|
|
304
|
-
const exitCode = execError.code || 1;
|
|
305
|
-
logger?.warn(
|
|
306
|
-
`[Skill bash] Command failed (exit code ${exitCode}): ${command}\n${errorOutput}`,
|
|
307
|
-
);
|
|
308
|
-
results.push({
|
|
309
|
-
command,
|
|
310
|
-
output: errorOutput,
|
|
311
|
-
exitCode,
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return results;
|
|
317
|
-
}
|
package/src/utils/mcpUtils.ts
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { ChatCompletionFunctionTool } from "openai/resources.js";
|
|
2
|
-
import type { ToolPlugin, ToolResult, ToolContext } from "../tools/types.js";
|
|
3
|
-
import type { McpTool, McpServerStatus } from "../types/index.js";
|
|
4
|
-
import { processToolResult } from "./toolResultStorage.js";
|
|
5
|
-
import { DEFAULT_MAX_RESULT_SIZE_CHARS } from "../constants/toolLimits.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Recursively clean schema to remove unsupported fields
|
|
9
|
-
*/
|
|
10
|
-
function cleanSchema(schema: unknown): unknown {
|
|
11
|
-
if (typeof schema !== "object" || schema === null) {
|
|
12
|
-
return schema;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (Array.isArray(schema)) {
|
|
16
|
-
return schema.map(cleanSchema);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const newSchema: Record<string, unknown> = {};
|
|
20
|
-
const obj = schema as Record<string, unknown>;
|
|
21
|
-
|
|
22
|
-
for (const key in obj) {
|
|
23
|
-
// Remove $schema as OpenAI API doesn't accept it
|
|
24
|
-
// Remove exclusiveMinimum/exclusiveMaximum as some models (e.g. Gemini) don't support them
|
|
25
|
-
if (
|
|
26
|
-
key === "$schema" ||
|
|
27
|
-
key === "exclusiveMinimum" ||
|
|
28
|
-
key === "exclusiveMaximum"
|
|
29
|
-
) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Handle type as an array (e.g. ["string", "null"])
|
|
34
|
-
if (key === "type" && Array.isArray(obj[key])) {
|
|
35
|
-
const types = obj[key] as string[];
|
|
36
|
-
const nonNullTypes = types.filter((t) => t !== "null");
|
|
37
|
-
if (nonNullTypes.length > 0) {
|
|
38
|
-
newSchema["type"] = nonNullTypes[0];
|
|
39
|
-
}
|
|
40
|
-
if (types.includes("null")) {
|
|
41
|
-
newSchema["nullable"] = true;
|
|
42
|
-
}
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
newSchema[key] = cleanSchema(obj[key]);
|
|
47
|
-
}
|
|
48
|
-
return newSchema;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Convert MCP tool to OpenAI function tool format
|
|
53
|
-
*/
|
|
54
|
-
export function mcpToolToOpenAITool(
|
|
55
|
-
mcpTool: McpTool,
|
|
56
|
-
serverName: string,
|
|
57
|
-
): ChatCompletionFunctionTool {
|
|
58
|
-
const cleanInputSchema = cleanSchema(mcpTool.inputSchema) as Record<
|
|
59
|
-
string,
|
|
60
|
-
unknown
|
|
61
|
-
>;
|
|
62
|
-
|
|
63
|
-
const prefixedName = `mcp__${serverName}__${mcpTool.name}`;
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
type: "function",
|
|
67
|
-
function: {
|
|
68
|
-
name: prefixedName,
|
|
69
|
-
description: `${mcpTool.description || `Tool from MCP server ${serverName}`} (MCP: ${serverName})`,
|
|
70
|
-
parameters: cleanInputSchema,
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Create a tool plugin wrapper for an MCP tool
|
|
77
|
-
*/
|
|
78
|
-
export function createMcpToolPlugin(
|
|
79
|
-
mcpTool: McpTool,
|
|
80
|
-
serverName: string,
|
|
81
|
-
executeTool: (
|
|
82
|
-
name: string,
|
|
83
|
-
args: Record<string, unknown>,
|
|
84
|
-
context?: ToolContext,
|
|
85
|
-
) => Promise<{
|
|
86
|
-
success: boolean;
|
|
87
|
-
content: string;
|
|
88
|
-
serverName?: string;
|
|
89
|
-
images?: Array<{ data: string; mediaType?: string }>;
|
|
90
|
-
}>,
|
|
91
|
-
): ToolPlugin {
|
|
92
|
-
const prefixedName = `mcp__${serverName}__${mcpTool.name}`;
|
|
93
|
-
return {
|
|
94
|
-
name: prefixedName,
|
|
95
|
-
config: mcpToolToOpenAITool(mcpTool, serverName),
|
|
96
|
-
async execute(
|
|
97
|
-
args: Record<string, unknown>,
|
|
98
|
-
context?: ToolContext,
|
|
99
|
-
): Promise<ToolResult> {
|
|
100
|
-
try {
|
|
101
|
-
const result = await executeTool(prefixedName, args, context);
|
|
102
|
-
|
|
103
|
-
// Process content for size limits — only text content, not images
|
|
104
|
-
const processedContent = processToolResult(
|
|
105
|
-
result.content || `Executed ${mcpTool.name}`,
|
|
106
|
-
DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
107
|
-
`mcp_${serverName}_${mcpTool.name}`,
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
success: true,
|
|
112
|
-
content: processedContent,
|
|
113
|
-
images: result.images,
|
|
114
|
-
};
|
|
115
|
-
} catch (error) {
|
|
116
|
-
return {
|
|
117
|
-
success: false,
|
|
118
|
-
content: "",
|
|
119
|
-
error: error instanceof Error ? error.message : String(error),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Find which server a tool belongs to
|
|
128
|
-
*/
|
|
129
|
-
export function findToolServer(
|
|
130
|
-
toolName: string,
|
|
131
|
-
servers: McpServerStatus[],
|
|
132
|
-
): McpServerStatus | undefined {
|
|
133
|
-
return servers.find(
|
|
134
|
-
(s) =>
|
|
135
|
-
(s.status === "connected" || s.status === "reconnecting") &&
|
|
136
|
-
s.tools?.some((t) => t.name === toolName),
|
|
137
|
-
);
|
|
138
|
-
}
|