wave-agent-sdk 0.0.1
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/README.md +32 -0
- package/dist/agent.d.ts +96 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +286 -0
- package/dist/hooks/executor.d.ts +56 -0
- package/dist/hooks/executor.d.ts.map +1 -0
- package/dist/hooks/executor.js +312 -0
- package/dist/hooks/index.d.ts +17 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +14 -0
- package/dist/hooks/manager.d.ts +90 -0
- package/dist/hooks/manager.d.ts.map +1 -0
- package/dist/hooks/manager.js +395 -0
- package/dist/hooks/matcher.d.ts +49 -0
- package/dist/hooks/matcher.d.ts.map +1 -0
- package/dist/hooks/matcher.js +147 -0
- package/dist/hooks/settings.d.ts +46 -0
- package/dist/hooks/settings.d.ts.map +1 -0
- package/dist/hooks/settings.js +100 -0
- package/dist/hooks/types.d.ts +80 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +59 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/managers/aiManager.d.ts +61 -0
- package/dist/managers/aiManager.d.ts.map +1 -0
- package/dist/managers/aiManager.js +415 -0
- package/dist/managers/backgroundBashManager.d.ts +27 -0
- package/dist/managers/backgroundBashManager.d.ts.map +1 -0
- package/dist/managers/backgroundBashManager.js +166 -0
- package/dist/managers/bashManager.d.ts +20 -0
- package/dist/managers/bashManager.d.ts.map +1 -0
- package/dist/managers/bashManager.js +66 -0
- package/dist/managers/mcpManager.d.ts +63 -0
- package/dist/managers/mcpManager.d.ts.map +1 -0
- package/dist/managers/mcpManager.js +378 -0
- package/dist/managers/messageManager.d.ts +85 -0
- package/dist/managers/messageManager.d.ts.map +1 -0
- package/dist/managers/messageManager.js +265 -0
- package/dist/managers/skillManager.d.ts +59 -0
- package/dist/managers/skillManager.d.ts.map +1 -0
- package/dist/managers/skillManager.js +317 -0
- package/dist/managers/slashCommandManager.d.ts +77 -0
- package/dist/managers/slashCommandManager.d.ts.map +1 -0
- package/dist/managers/slashCommandManager.js +208 -0
- package/dist/managers/toolManager.d.ts +23 -0
- package/dist/managers/toolManager.d.ts.map +1 -0
- package/dist/managers/toolManager.js +79 -0
- package/dist/services/aiService.d.ts +28 -0
- package/dist/services/aiService.d.ts.map +1 -0
- package/dist/services/aiService.js +180 -0
- package/dist/services/memory.d.ts +8 -0
- package/dist/services/memory.d.ts.map +1 -0
- package/dist/services/memory.js +128 -0
- package/dist/services/session.d.ts +54 -0
- package/dist/services/session.d.ts.map +1 -0
- package/dist/services/session.js +196 -0
- package/dist/tools/bashTool.d.ts +14 -0
- package/dist/tools/bashTool.d.ts.map +1 -0
- package/dist/tools/bashTool.js +351 -0
- package/dist/tools/deleteFileTool.d.ts +6 -0
- package/dist/tools/deleteFileTool.d.ts.map +1 -0
- package/dist/tools/deleteFileTool.js +67 -0
- package/dist/tools/editTool.d.ts +6 -0
- package/dist/tools/editTool.d.ts.map +1 -0
- package/dist/tools/editTool.js +168 -0
- package/dist/tools/globTool.d.ts +6 -0
- package/dist/tools/globTool.d.ts.map +1 -0
- package/dist/tools/globTool.js +113 -0
- package/dist/tools/grepTool.d.ts +6 -0
- package/dist/tools/grepTool.d.ts.map +1 -0
- package/dist/tools/grepTool.js +268 -0
- package/dist/tools/lsTool.d.ts +6 -0
- package/dist/tools/lsTool.d.ts.map +1 -0
- package/dist/tools/lsTool.js +160 -0
- package/dist/tools/multiEditTool.d.ts +6 -0
- package/dist/tools/multiEditTool.d.ts.map +1 -0
- package/dist/tools/multiEditTool.js +222 -0
- package/dist/tools/readTool.d.ts +6 -0
- package/dist/tools/readTool.d.ts.map +1 -0
- package/dist/tools/readTool.js +136 -0
- package/dist/tools/types.d.ts +35 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +4 -0
- package/dist/tools/writeTool.d.ts +6 -0
- package/dist/tools/writeTool.d.ts.map +1 -0
- package/dist/tools/writeTool.js +138 -0
- package/dist/types.d.ts +212 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/utils/bashHistory.d.ts +46 -0
- package/dist/utils/bashHistory.d.ts.map +1 -0
- package/dist/utils/bashHistory.js +236 -0
- package/dist/utils/commandArgumentParser.d.ts +34 -0
- package/dist/utils/commandArgumentParser.d.ts.map +1 -0
- package/dist/utils/commandArgumentParser.js +123 -0
- package/dist/utils/constants.d.ts +27 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +28 -0
- package/dist/utils/convertMessagesForAPI.d.ts +9 -0
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -0
- package/dist/utils/convertMessagesForAPI.js +189 -0
- package/dist/utils/customCommands.d.ts +14 -0
- package/dist/utils/customCommands.d.ts.map +1 -0
- package/dist/utils/customCommands.js +71 -0
- package/dist/utils/fileFilter.d.ts +26 -0
- package/dist/utils/fileFilter.d.ts.map +1 -0
- package/dist/utils/fileFilter.js +177 -0
- package/dist/utils/markdownParser.d.ts +27 -0
- package/dist/utils/markdownParser.d.ts.map +1 -0
- package/dist/utils/markdownParser.js +109 -0
- package/dist/utils/mcpUtils.d.ts +24 -0
- package/dist/utils/mcpUtils.d.ts.map +1 -0
- package/dist/utils/mcpUtils.js +51 -0
- package/dist/utils/messageOperations.d.ts +118 -0
- package/dist/utils/messageOperations.d.ts.map +1 -0
- package/dist/utils/messageOperations.js +334 -0
- package/dist/utils/path.d.ts +25 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +109 -0
- package/dist/utils/skillParser.d.ts +18 -0
- package/dist/utils/skillParser.d.ts.map +1 -0
- package/dist/utils/skillParser.js +147 -0
- package/dist/utils/stringUtils.d.ts +13 -0
- package/dist/utils/stringUtils.d.ts.map +1 -0
- package/dist/utils/stringUtils.js +44 -0
- package/package.json +51 -0
- package/src/agent.ts +405 -0
- package/src/hooks/executor.ts +440 -0
- package/src/hooks/index.ts +52 -0
- package/src/hooks/manager.ts +618 -0
- package/src/hooks/matcher.ts +187 -0
- package/src/hooks/settings.ts +129 -0
- package/src/hooks/types.ts +169 -0
- package/src/index.ts +24 -0
- package/src/managers/aiManager.ts +573 -0
- package/src/managers/backgroundBashManager.ts +203 -0
- package/src/managers/bashManager.ts +97 -0
- package/src/managers/mcpManager.ts +493 -0
- package/src/managers/messageManager.ts +415 -0
- package/src/managers/skillManager.ts +404 -0
- package/src/managers/slashCommandManager.ts +293 -0
- package/src/managers/toolManager.ts +106 -0
- package/src/services/aiService.ts +252 -0
- package/src/services/memory.ts +149 -0
- package/src/services/session.ts +265 -0
- package/src/tools/bashTool.ts +402 -0
- package/src/tools/deleteFileTool.ts +81 -0
- package/src/tools/editTool.ts +192 -0
- package/src/tools/globTool.ts +135 -0
- package/src/tools/grepTool.ts +326 -0
- package/src/tools/lsTool.ts +187 -0
- package/src/tools/multiEditTool.ts +268 -0
- package/src/tools/readTool.ts +165 -0
- package/src/tools/types.ts +47 -0
- package/src/tools/writeTool.ts +163 -0
- package/src/types.ts +260 -0
- package/src/utils/bashHistory.ts +303 -0
- package/src/utils/commandArgumentParser.ts +153 -0
- package/src/utils/constants.ts +37 -0
- package/src/utils/convertMessagesForAPI.ts +236 -0
- package/src/utils/customCommands.ts +85 -0
- package/src/utils/fileFilter.ts +202 -0
- package/src/utils/markdownParser.ts +156 -0
- package/src/utils/mcpUtils.ts +81 -0
- package/src/utils/messageOperations.ts +506 -0
- package/src/utils/path.ts +118 -0
- package/src/utils/skillParser.ts +188 -0
- package/src/utils/stringUtils.ts +50 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
/**
|
|
3
|
+
* Parse YAML frontmatter from markdown content
|
|
4
|
+
*/
|
|
5
|
+
function parseFrontmatter(content) {
|
|
6
|
+
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
7
|
+
const match = content.match(frontmatterRegex);
|
|
8
|
+
if (!match) {
|
|
9
|
+
return { content };
|
|
10
|
+
}
|
|
11
|
+
const [, frontmatterStr, bodyContent] = match;
|
|
12
|
+
try {
|
|
13
|
+
// Simple YAML parser for our use case (only supports key: value pairs)
|
|
14
|
+
const frontmatter = {};
|
|
15
|
+
const lines = frontmatterStr.split("\n");
|
|
16
|
+
for (const line of lines) {
|
|
17
|
+
const trimmedLine = line.trim();
|
|
18
|
+
if (!trimmedLine || trimmedLine.startsWith("#"))
|
|
19
|
+
continue;
|
|
20
|
+
const colonIndex = trimmedLine.indexOf(":");
|
|
21
|
+
if (colonIndex === -1)
|
|
22
|
+
continue;
|
|
23
|
+
const key = trimmedLine.slice(0, colonIndex).trim();
|
|
24
|
+
const value = trimmedLine.slice(colonIndex + 1).trim();
|
|
25
|
+
// Handle array values for allowed-tools
|
|
26
|
+
if (key === "allowed-tools" && value) {
|
|
27
|
+
// Simple array parsing: "tool1, tool2, tool3" or "[tool1, tool2]"
|
|
28
|
+
let arrayValue = value;
|
|
29
|
+
if (arrayValue.startsWith("[") && arrayValue.endsWith("]")) {
|
|
30
|
+
arrayValue = arrayValue.slice(1, -1);
|
|
31
|
+
}
|
|
32
|
+
frontmatter[key] = arrayValue
|
|
33
|
+
.split(",")
|
|
34
|
+
.map((s) => s.trim())
|
|
35
|
+
.filter(Boolean);
|
|
36
|
+
}
|
|
37
|
+
else if (value) {
|
|
38
|
+
frontmatter[key] = value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { frontmatter, content: bodyContent };
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// If parsing fails, just return the content without frontmatter
|
|
45
|
+
return { content };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse markdown file and extract config and content
|
|
50
|
+
*/
|
|
51
|
+
export function parseMarkdownFile(filePath) {
|
|
52
|
+
try {
|
|
53
|
+
const fileContent = readFileSync(filePath, "utf-8");
|
|
54
|
+
const { frontmatter, content } = parseFrontmatter(fileContent);
|
|
55
|
+
let config;
|
|
56
|
+
if (frontmatter) {
|
|
57
|
+
config = {};
|
|
58
|
+
if (frontmatter["allowed-tools"] &&
|
|
59
|
+
Array.isArray(frontmatter["allowed-tools"])) {
|
|
60
|
+
config.allowedTools = frontmatter["allowed-tools"];
|
|
61
|
+
}
|
|
62
|
+
if (frontmatter.model && typeof frontmatter.model === "string") {
|
|
63
|
+
config.model = frontmatter.model;
|
|
64
|
+
}
|
|
65
|
+
if (frontmatter.description &&
|
|
66
|
+
typeof frontmatter.description === "string") {
|
|
67
|
+
config.description = frontmatter.description;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
content: content.trim(),
|
|
72
|
+
config,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw new Error(`Failed to parse markdown file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function parseBashCommands(content) {
|
|
80
|
+
const bashCommandRegex = /!`([^`]+)`/g;
|
|
81
|
+
const commands = [];
|
|
82
|
+
let match;
|
|
83
|
+
// Extract all bash commands
|
|
84
|
+
while ((match = bashCommandRegex.exec(content)) !== null) {
|
|
85
|
+
commands.push(match[1]);
|
|
86
|
+
}
|
|
87
|
+
// For now, return the content as-is. The actual command execution
|
|
88
|
+
// will be handled by the slash command manager
|
|
89
|
+
return {
|
|
90
|
+
commands,
|
|
91
|
+
processedContent: content,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Replace bash command placeholders with their outputs
|
|
96
|
+
*/
|
|
97
|
+
export function replaceBashCommandsWithOutput(content, results) {
|
|
98
|
+
const bashCommandRegex = /!`([^`]+)`/g;
|
|
99
|
+
let processedContent = content;
|
|
100
|
+
let commandIndex = 0;
|
|
101
|
+
processedContent = processedContent.replace(bashCommandRegex, (match) => {
|
|
102
|
+
if (commandIndex < results.length) {
|
|
103
|
+
const result = results[commandIndex++];
|
|
104
|
+
return `\`\`\`\n$ ${result.command}\n${result.output}\n\`\`\``;
|
|
105
|
+
}
|
|
106
|
+
return match;
|
|
107
|
+
});
|
|
108
|
+
return processedContent;
|
|
109
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ChatCompletionFunctionTool } from "openai/resources.js";
|
|
2
|
+
import type { ToolPlugin } from "../tools/types.js";
|
|
3
|
+
import type { McpTool, McpServerStatus } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Convert MCP tool to OpenAI function tool format
|
|
6
|
+
*/
|
|
7
|
+
export declare function mcpToolToOpenAITool(mcpTool: McpTool, serverName: string): ChatCompletionFunctionTool;
|
|
8
|
+
/**
|
|
9
|
+
* Create a tool plugin wrapper for an MCP tool
|
|
10
|
+
*/
|
|
11
|
+
export declare function createMcpToolPlugin(mcpTool: McpTool, serverName: string, executeTool: (name: string, args: Record<string, unknown>) => Promise<{
|
|
12
|
+
success: boolean;
|
|
13
|
+
content: string;
|
|
14
|
+
serverName?: string;
|
|
15
|
+
images?: Array<{
|
|
16
|
+
data: string;
|
|
17
|
+
mediaType?: string;
|
|
18
|
+
}>;
|
|
19
|
+
}>): ToolPlugin;
|
|
20
|
+
/**
|
|
21
|
+
* Find which server a tool belongs to
|
|
22
|
+
*/
|
|
23
|
+
export declare function findToolServer(toolName: string, servers: McpServerStatus[]): McpServerStatus | undefined;
|
|
24
|
+
//# sourceMappingURL=mcpUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpUtils.d.ts","sourceRoot":"","sources":["../../src/utils/mcpUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,mBAAmB,CAAC;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE5D;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,GACjB,0BAA0B,CAa5B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,CACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtD,CAAC,GACD,UAAU,CA2BZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,eAAe,EAAE,GACzB,eAAe,GAAG,SAAS,CAK7B"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert MCP tool to OpenAI function tool format
|
|
3
|
+
*/
|
|
4
|
+
export function mcpToolToOpenAITool(mcpTool, serverName) {
|
|
5
|
+
// Remove $schema field if it exists, as OpenAI API doesn't accept it
|
|
6
|
+
const cleanInputSchema = { ...mcpTool.inputSchema };
|
|
7
|
+
delete cleanInputSchema.$schema;
|
|
8
|
+
return {
|
|
9
|
+
type: "function",
|
|
10
|
+
function: {
|
|
11
|
+
name: mcpTool.name,
|
|
12
|
+
description: `${mcpTool.description || `Tool from MCP server ${serverName}`} (MCP: ${serverName})`,
|
|
13
|
+
parameters: cleanInputSchema,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a tool plugin wrapper for an MCP tool
|
|
19
|
+
*/
|
|
20
|
+
export function createMcpToolPlugin(mcpTool, serverName, executeTool) {
|
|
21
|
+
return {
|
|
22
|
+
name: mcpTool.name,
|
|
23
|
+
config: mcpToolToOpenAITool(mcpTool, serverName),
|
|
24
|
+
async execute(args, context) {
|
|
25
|
+
try {
|
|
26
|
+
// Context is available for future use when MCP tools need execution context
|
|
27
|
+
if (context) {
|
|
28
|
+
// Future: Could pass working directory or other context to MCP tools
|
|
29
|
+
}
|
|
30
|
+
const result = await executeTool(mcpTool.name, args);
|
|
31
|
+
return {
|
|
32
|
+
success: true,
|
|
33
|
+
content: result.content || `Executed ${mcpTool.name}`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
content: "",
|
|
40
|
+
error: error instanceof Error ? error.message : String(error),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Find which server a tool belongs to
|
|
48
|
+
*/
|
|
49
|
+
export function findToolServer(toolName, servers) {
|
|
50
|
+
return servers.find((s) => s.status === "connected" && s.tools?.some((t) => t.name === toolName));
|
|
51
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Message } from "../types.js";
|
|
2
|
+
import { ChatCompletionMessageFunctionToolCall } from "openai/resources.js";
|
|
3
|
+
export interface AddUserMessageParams {
|
|
4
|
+
messages: Message[];
|
|
5
|
+
content: string;
|
|
6
|
+
images?: Array<{
|
|
7
|
+
path: string;
|
|
8
|
+
mimeType: string;
|
|
9
|
+
}>;
|
|
10
|
+
customCommandBlock?: {
|
|
11
|
+
type: "custom_command";
|
|
12
|
+
commandName: string;
|
|
13
|
+
content: string;
|
|
14
|
+
originalInput?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface UpdateToolBlockParams {
|
|
18
|
+
messages: Message[];
|
|
19
|
+
id: string;
|
|
20
|
+
parameters: string;
|
|
21
|
+
result?: string;
|
|
22
|
+
success?: boolean;
|
|
23
|
+
error?: string;
|
|
24
|
+
isRunning?: boolean;
|
|
25
|
+
name?: string;
|
|
26
|
+
shortResult?: string;
|
|
27
|
+
images?: Array<{
|
|
28
|
+
data: string;
|
|
29
|
+
mediaType?: string;
|
|
30
|
+
}>;
|
|
31
|
+
compactParams?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface AgentToolBlockUpdateParams {
|
|
34
|
+
toolId: string;
|
|
35
|
+
args?: string;
|
|
36
|
+
result?: string;
|
|
37
|
+
success?: boolean;
|
|
38
|
+
error?: string;
|
|
39
|
+
isRunning?: boolean;
|
|
40
|
+
name?: string;
|
|
41
|
+
shortResult?: string;
|
|
42
|
+
compactParams?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface AddDiffBlockParams {
|
|
45
|
+
messages: Message[];
|
|
46
|
+
path: string;
|
|
47
|
+
diffResult: Array<{
|
|
48
|
+
value: string;
|
|
49
|
+
added?: boolean;
|
|
50
|
+
removed?: boolean;
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
export interface AddErrorBlockParams {
|
|
54
|
+
messages: Message[];
|
|
55
|
+
error: string;
|
|
56
|
+
}
|
|
57
|
+
export interface AddMemoryBlockParams {
|
|
58
|
+
messages: Message[];
|
|
59
|
+
content: string;
|
|
60
|
+
isSuccess: boolean;
|
|
61
|
+
memoryType?: "project" | "user";
|
|
62
|
+
storagePath?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface AddCommandOutputParams {
|
|
65
|
+
messages: Message[];
|
|
66
|
+
command: string;
|
|
67
|
+
}
|
|
68
|
+
export interface UpdateCommandOutputParams {
|
|
69
|
+
messages: Message[];
|
|
70
|
+
command: string;
|
|
71
|
+
output: string;
|
|
72
|
+
}
|
|
73
|
+
export interface CompleteCommandParams {
|
|
74
|
+
messages: Message[];
|
|
75
|
+
command: string;
|
|
76
|
+
exitCode: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Extract text content from user messages in the messages array
|
|
80
|
+
*/
|
|
81
|
+
export declare const extractUserInputHistory: (messages: Message[]) => string[];
|
|
82
|
+
/**
|
|
83
|
+
* Convert image file path to base64 format
|
|
84
|
+
* @param imagePath Image file path
|
|
85
|
+
* @returns base64 format image data URL
|
|
86
|
+
*/
|
|
87
|
+
export declare const convertImageToBase64: (imagePath: string) => string;
|
|
88
|
+
export declare const addUserMessageToMessages: ({ messages, content, images, customCommandBlock, }: AddUserMessageParams) => Message[];
|
|
89
|
+
export declare const addAssistantMessageToMessages: (messages: Message[], content?: string, toolCalls?: ChatCompletionMessageFunctionToolCall[]) => Message[];
|
|
90
|
+
export declare const addDiffBlockToMessage: ({ messages, path, diffResult, }: AddDiffBlockParams) => Message[];
|
|
91
|
+
export declare const updateToolBlockInMessage: ({ messages, id, parameters, result, success, error, isRunning, name, shortResult, images, compactParams, }: UpdateToolBlockParams) => Message[];
|
|
92
|
+
export declare const addErrorBlockToMessage: ({ messages, error, }: AddErrorBlockParams) => Message[];
|
|
93
|
+
export declare const addMemoryBlockToMessage: ({ messages, content, isSuccess, memoryType, storagePath, }: AddMemoryBlockParams) => Message[];
|
|
94
|
+
/**
|
|
95
|
+
* Count valid blocks from the end
|
|
96
|
+
* Only text, image, and tool type blocks are counted
|
|
97
|
+
* @param messages Message array
|
|
98
|
+
* @param targetCount Number of valid blocks to count
|
|
99
|
+
* @returns { messageIndex: number, blockCount: number } Message index and actual counted block count
|
|
100
|
+
*/
|
|
101
|
+
export declare const countValidBlocksFromEnd: (messages: Message[], targetCount: number) => {
|
|
102
|
+
messageIndex: number;
|
|
103
|
+
blockCount: number;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Get messages to be compressed and insertion position
|
|
107
|
+
* @param messages Message array
|
|
108
|
+
* @param keepLastCount Keep the last few valid blocks uncompressed
|
|
109
|
+
* @returns { messagesToCompress: Message[], insertIndex: number }
|
|
110
|
+
*/
|
|
111
|
+
export declare const getMessagesToCompress: (messages: Message[], keepLastCount?: number) => {
|
|
112
|
+
messagesToCompress: Message[];
|
|
113
|
+
insertIndex: number;
|
|
114
|
+
};
|
|
115
|
+
export declare const addCommandOutputMessage: ({ messages, command, }: AddCommandOutputParams) => Message[];
|
|
116
|
+
export declare const updateCommandOutputInMessage: ({ messages, command, output, }: UpdateCommandOutputParams) => Message[];
|
|
117
|
+
export declare const completeCommandInMessage: ({ messages, command, exitCode, }: CompleteCommandParams) => Message[];
|
|
118
|
+
//# sourceMappingURL=messageOperations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messageOperations.d.ts","sourceRoot":"","sources":["../../src/utils/messageOperations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { extname } from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Extract text content from user messages in the messages array
|
|
5
|
+
*/
|
|
6
|
+
export const extractUserInputHistory = (messages) => {
|
|
7
|
+
return messages
|
|
8
|
+
.filter((message) => message.role === "user")
|
|
9
|
+
.map((message) => {
|
|
10
|
+
// Extract all text block content and merge
|
|
11
|
+
const textBlocks = message.blocks.filter((block) => block.type === "text");
|
|
12
|
+
return textBlocks
|
|
13
|
+
.map((block) => block.content)
|
|
14
|
+
.join(" ")
|
|
15
|
+
.trim();
|
|
16
|
+
})
|
|
17
|
+
.filter((text) => text.length > 0); // Filter out empty text
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Convert image file path to base64 format
|
|
21
|
+
* @param imagePath Image file path
|
|
22
|
+
* @returns base64 format image data URL
|
|
23
|
+
*/
|
|
24
|
+
export const convertImageToBase64 = (imagePath) => {
|
|
25
|
+
try {
|
|
26
|
+
const imageBuffer = readFileSync(imagePath);
|
|
27
|
+
const ext = extname(imagePath).toLowerCase().substring(1);
|
|
28
|
+
// Determine MIME type based on file extension
|
|
29
|
+
let mimeType = "image/png"; // Default
|
|
30
|
+
switch (ext) {
|
|
31
|
+
case "jpg":
|
|
32
|
+
case "jpeg":
|
|
33
|
+
mimeType = "image/jpeg";
|
|
34
|
+
break;
|
|
35
|
+
case "png":
|
|
36
|
+
mimeType = "image/png";
|
|
37
|
+
break;
|
|
38
|
+
case "gif":
|
|
39
|
+
mimeType = "image/gif";
|
|
40
|
+
break;
|
|
41
|
+
case "webp":
|
|
42
|
+
mimeType = "image/webp";
|
|
43
|
+
break;
|
|
44
|
+
case "bmp":
|
|
45
|
+
mimeType = "image/bmp";
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
mimeType = "image/png";
|
|
49
|
+
}
|
|
50
|
+
const base64String = imageBuffer.toString("base64");
|
|
51
|
+
return `data:${mimeType};base64,${base64String}`;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// logger.error(`Failed to convert image to base64: ${imagePath}`, error);
|
|
55
|
+
// Return an error placeholder or throw error
|
|
56
|
+
return `data:image/png;base64,`; // Empty base64, avoid program crash
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
// Add user message
|
|
60
|
+
export const addUserMessageToMessages = ({ messages, content, images, customCommandBlock, }) => {
|
|
61
|
+
const blocks = [];
|
|
62
|
+
// If there's a custom command block, use it instead of text content
|
|
63
|
+
if (customCommandBlock) {
|
|
64
|
+
blocks.push(customCommandBlock);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
blocks.push({ type: "text", content });
|
|
68
|
+
}
|
|
69
|
+
// If there are images, add image block
|
|
70
|
+
if (images && images.length > 0) {
|
|
71
|
+
const imageUrls = images.map((img) => img.path);
|
|
72
|
+
blocks.push({
|
|
73
|
+
type: "image",
|
|
74
|
+
imageUrls,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const userMessage = {
|
|
78
|
+
role: "user",
|
|
79
|
+
blocks,
|
|
80
|
+
};
|
|
81
|
+
return [...messages, userMessage];
|
|
82
|
+
};
|
|
83
|
+
// Add assistant message (support one-time addition of answer and tool calls)
|
|
84
|
+
export const addAssistantMessageToMessages = (messages, content, toolCalls) => {
|
|
85
|
+
const blocks = [];
|
|
86
|
+
// If there's answer content, add text block
|
|
87
|
+
if (content) {
|
|
88
|
+
blocks.push({ type: "text", content: content });
|
|
89
|
+
}
|
|
90
|
+
// If there are tool calls, add tool blocks
|
|
91
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
92
|
+
toolCalls.forEach((toolCall) => {
|
|
93
|
+
blocks.push({
|
|
94
|
+
type: "tool",
|
|
95
|
+
parameters: toolCall.function.arguments || "",
|
|
96
|
+
result: "",
|
|
97
|
+
id: toolCall.id || "",
|
|
98
|
+
name: toolCall.function?.name || "",
|
|
99
|
+
isRunning: false,
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const initialAssistantMessage = {
|
|
104
|
+
role: "assistant",
|
|
105
|
+
blocks,
|
|
106
|
+
};
|
|
107
|
+
return [...messages, initialAssistantMessage];
|
|
108
|
+
};
|
|
109
|
+
// Update File Operation Block of the last assistant message
|
|
110
|
+
export const addDiffBlockToMessage = ({ messages, path, diffResult, }) => {
|
|
111
|
+
const newMessages = [...messages];
|
|
112
|
+
// Find the last assistant message
|
|
113
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
114
|
+
if (newMessages[i].role === "assistant") {
|
|
115
|
+
// Directly add diff block instead of replacing existing blocks
|
|
116
|
+
newMessages[i].blocks.push({
|
|
117
|
+
type: "diff",
|
|
118
|
+
path: path,
|
|
119
|
+
diffResult: diffResult,
|
|
120
|
+
});
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return newMessages;
|
|
125
|
+
};
|
|
126
|
+
// Update Tool Block of the last assistant message
|
|
127
|
+
export const updateToolBlockInMessage = ({ messages, id, parameters, result, success, error, isRunning, name, shortResult, images, compactParams, }) => {
|
|
128
|
+
const newMessages = [...messages];
|
|
129
|
+
// Find the last assistant message
|
|
130
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
131
|
+
if (newMessages[i].role === "assistant") {
|
|
132
|
+
const toolBlockIndex = newMessages[i].blocks.findIndex((block) => block.type === "tool" && block.id === id);
|
|
133
|
+
if (toolBlockIndex !== -1) {
|
|
134
|
+
const toolBlock = newMessages[i].blocks[toolBlockIndex];
|
|
135
|
+
if (toolBlock.type === "tool") {
|
|
136
|
+
toolBlock.parameters = parameters;
|
|
137
|
+
if (result !== undefined)
|
|
138
|
+
toolBlock.result = result;
|
|
139
|
+
if (shortResult !== undefined)
|
|
140
|
+
toolBlock.shortResult = shortResult;
|
|
141
|
+
toolBlock.images = images; // Add image data update
|
|
142
|
+
if (success !== undefined)
|
|
143
|
+
toolBlock.success = success;
|
|
144
|
+
if (error !== undefined)
|
|
145
|
+
toolBlock.error = error;
|
|
146
|
+
if (isRunning !== undefined)
|
|
147
|
+
toolBlock.isRunning = isRunning;
|
|
148
|
+
if (compactParams !== undefined)
|
|
149
|
+
toolBlock.compactParams = compactParams;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (result !== undefined) {
|
|
153
|
+
// If existing block not found, create new one
|
|
154
|
+
newMessages[i].blocks.push({
|
|
155
|
+
type: "tool",
|
|
156
|
+
parameters: parameters,
|
|
157
|
+
result: result,
|
|
158
|
+
shortResult: shortResult,
|
|
159
|
+
images: images, // Add image data
|
|
160
|
+
id: id,
|
|
161
|
+
name: name || "unknown",
|
|
162
|
+
success: success,
|
|
163
|
+
error: error,
|
|
164
|
+
isRunning: isRunning ?? false,
|
|
165
|
+
compactParams: compactParams,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return newMessages;
|
|
172
|
+
};
|
|
173
|
+
// Add Error Block to the last assistant message
|
|
174
|
+
export const addErrorBlockToMessage = ({ messages, error, }) => {
|
|
175
|
+
const newMessages = [...messages];
|
|
176
|
+
// Find the last assistant message
|
|
177
|
+
let assistantMessageFound = false;
|
|
178
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
179
|
+
if (newMessages[i].role === "assistant") {
|
|
180
|
+
newMessages[i].blocks = [
|
|
181
|
+
...newMessages[i].blocks,
|
|
182
|
+
{
|
|
183
|
+
type: "error",
|
|
184
|
+
content: error,
|
|
185
|
+
},
|
|
186
|
+
];
|
|
187
|
+
assistantMessageFound = true;
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// If no assistant message found, create a new assistant message with only error block
|
|
192
|
+
if (!assistantMessageFound) {
|
|
193
|
+
newMessages.push({
|
|
194
|
+
role: "assistant",
|
|
195
|
+
blocks: [
|
|
196
|
+
{
|
|
197
|
+
type: "error",
|
|
198
|
+
content: error,
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
return newMessages;
|
|
204
|
+
};
|
|
205
|
+
// Add Memory Block as new assistant message
|
|
206
|
+
export const addMemoryBlockToMessage = ({ messages, content, isSuccess, memoryType, storagePath, }) => {
|
|
207
|
+
const newMessages = [...messages];
|
|
208
|
+
// Create new assistant message containing MemoryBlock
|
|
209
|
+
const memoryMessage = {
|
|
210
|
+
role: "assistant",
|
|
211
|
+
blocks: [
|
|
212
|
+
{
|
|
213
|
+
type: "memory",
|
|
214
|
+
content,
|
|
215
|
+
isSuccess,
|
|
216
|
+
memoryType,
|
|
217
|
+
storagePath,
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
};
|
|
221
|
+
// Add to end of message list
|
|
222
|
+
newMessages.push(memoryMessage);
|
|
223
|
+
return newMessages;
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* Count valid blocks from the end
|
|
227
|
+
* Only text, image, and tool type blocks are counted
|
|
228
|
+
* @param messages Message array
|
|
229
|
+
* @param targetCount Number of valid blocks to count
|
|
230
|
+
* @returns { messageIndex: number, blockCount: number } Message index and actual counted block count
|
|
231
|
+
*/
|
|
232
|
+
export const countValidBlocksFromEnd = (messages, targetCount) => {
|
|
233
|
+
let validBlockCount = 0;
|
|
234
|
+
// Iterate messages from end to beginning
|
|
235
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
236
|
+
const message = messages[i];
|
|
237
|
+
// Iterate through all blocks of current message
|
|
238
|
+
for (const block of message.blocks) {
|
|
239
|
+
// Only count valid block types
|
|
240
|
+
if (block.type === "text" ||
|
|
241
|
+
block.type === "image" ||
|
|
242
|
+
block.type === "tool") {
|
|
243
|
+
validBlockCount++;
|
|
244
|
+
// If target count reached, return current message index
|
|
245
|
+
if (validBlockCount >= targetCount) {
|
|
246
|
+
return { messageIndex: i, blockCount: validBlockCount };
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// If target count not reached, return index 0
|
|
252
|
+
return { messageIndex: 0, blockCount: validBlockCount };
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* Get messages to be compressed and insertion position
|
|
256
|
+
* @param messages Message array
|
|
257
|
+
* @param keepLastCount Keep the last few valid blocks uncompressed
|
|
258
|
+
* @returns { messagesToCompress: Message[], insertIndex: number }
|
|
259
|
+
*/
|
|
260
|
+
export const getMessagesToCompress = (messages, keepLastCount = 7) => {
|
|
261
|
+
// Calculate message position to keep from end to beginning
|
|
262
|
+
const { messageIndex } = countValidBlocksFromEnd(messages, keepLastCount);
|
|
263
|
+
// Find the last message containing compression block
|
|
264
|
+
let lastCompressIndex = -1;
|
|
265
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
266
|
+
const hasCompressBlock = messages[i].blocks.some((block) => block.type === "compress");
|
|
267
|
+
if (hasCompressBlock) {
|
|
268
|
+
lastCompressIndex = i;
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Determine compression start position
|
|
273
|
+
// If compression block exists, start from compression block position (include compression block)
|
|
274
|
+
// If no compression block, start from beginning
|
|
275
|
+
const startIndex = lastCompressIndex >= 0 ? lastCompressIndex : 0;
|
|
276
|
+
// Messages to compress are all messages from start position to before calculated position
|
|
277
|
+
const messagesToCompress = messages.slice(startIndex, messageIndex);
|
|
278
|
+
// Change insertion position to negative number, indicating position from end
|
|
279
|
+
const insertIndex = messageIndex - messages.length;
|
|
280
|
+
return { messagesToCompress, insertIndex };
|
|
281
|
+
};
|
|
282
|
+
// Add command output block to message list
|
|
283
|
+
export const addCommandOutputMessage = ({ messages, command, }) => {
|
|
284
|
+
const outputMessage = {
|
|
285
|
+
role: "assistant",
|
|
286
|
+
blocks: [
|
|
287
|
+
{
|
|
288
|
+
type: "command_output",
|
|
289
|
+
command,
|
|
290
|
+
output: "",
|
|
291
|
+
isRunning: true,
|
|
292
|
+
exitCode: null,
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
};
|
|
296
|
+
return [...messages, outputMessage];
|
|
297
|
+
};
|
|
298
|
+
// Update output content of command output block
|
|
299
|
+
export const updateCommandOutputInMessage = ({ messages, command, output, }) => {
|
|
300
|
+
const newMessages = [...messages];
|
|
301
|
+
// Find the last assistant message with a command_output block for this command
|
|
302
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
303
|
+
const msg = newMessages[i];
|
|
304
|
+
if (msg.role === "assistant") {
|
|
305
|
+
const commandBlock = msg.blocks.find((block) => block.type === "command_output" &&
|
|
306
|
+
block.command === command &&
|
|
307
|
+
block.isRunning);
|
|
308
|
+
if (commandBlock && commandBlock.type === "command_output") {
|
|
309
|
+
commandBlock.output = output.trim();
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return newMessages;
|
|
315
|
+
};
|
|
316
|
+
// Complete command execution, update exit status
|
|
317
|
+
export const completeCommandInMessage = ({ messages, command, exitCode, }) => {
|
|
318
|
+
const newMessages = [...messages];
|
|
319
|
+
// Find the last assistant message with a command_output block for this command
|
|
320
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
321
|
+
const msg = newMessages[i];
|
|
322
|
+
if (msg.role === "assistant") {
|
|
323
|
+
const commandBlock = msg.blocks.find((block) => block.type === "command_output" &&
|
|
324
|
+
block.command === command &&
|
|
325
|
+
block.isRunning);
|
|
326
|
+
if (commandBlock && commandBlock.type === "command_output") {
|
|
327
|
+
commandBlock.isRunning = false;
|
|
328
|
+
commandBlock.exitCode = exitCode;
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return newMessages;
|
|
334
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handle paths, supporting ~ expansion
|
|
3
|
+
* @param filePath File path
|
|
4
|
+
* @param workdir Working directory
|
|
5
|
+
* @returns Resolved absolute path
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolvePath(filePath: string, workdir: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Binary file extension list
|
|
10
|
+
*/
|
|
11
|
+
export declare const binaryExtensions: readonly ["png", "jpg", "jpeg", "gif", "bmp", "ico", "webp", "svg", "sketch", "mp3", "wav", "ogg", "aac", "mp4", "webm", "avi", "mov", "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "zip", "rar", "7z", "tar", "gz", "ttf", "otf", "woff", "woff2", "eot", "exe", "dll", "so", "dylib", "bin"];
|
|
12
|
+
/**
|
|
13
|
+
* Check if a file is a binary file
|
|
14
|
+
* @param filename File name
|
|
15
|
+
* @returns Whether it is a binary file
|
|
16
|
+
*/
|
|
17
|
+
export declare const isBinary: (filename: string) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Get relative path for display, use relative path if shorter and not in parent directory
|
|
20
|
+
* @param filePath Absolute path
|
|
21
|
+
* @param workdir Working directory
|
|
22
|
+
* @returns Path for display (relative or absolute)
|
|
23
|
+
*/
|
|
24
|
+
export declare function getDisplayPath(filePath: string, workdir: string): string;
|
|
25
|
+
//# sourceMappingURL=path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAarE;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,uSA+CnB,CAAC;AACX;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAU,MAAM,KAAG,OAI3C,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAwBxE"}
|