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,128 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { USER_MEMORY_FILE, DATA_DIRECTORY } from "../utils/constants.js";
|
|
4
|
+
// Project memory related methods
|
|
5
|
+
export const isMemoryMessage = (message) => {
|
|
6
|
+
return message.trim().startsWith("#");
|
|
7
|
+
};
|
|
8
|
+
export const addMemory = async (message, workdir) => {
|
|
9
|
+
if (!isMemoryMessage(message)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const memoryFilePath = path.join(workdir, "WAVE.md");
|
|
14
|
+
// Format memory entry, starting with -, no timestamp
|
|
15
|
+
const memoryEntry = `- ${message.substring(1).trim()}\n`;
|
|
16
|
+
// Check if file exists
|
|
17
|
+
let existingContent = "";
|
|
18
|
+
try {
|
|
19
|
+
existingContent = await fs.readFile(memoryFilePath, "utf-8");
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
// File does not exist, create new file
|
|
23
|
+
if (error.code === "ENOENT") {
|
|
24
|
+
existingContent =
|
|
25
|
+
"# Memory\n\nThis is the AI assistant's memory file, recording important information and context.\n\n";
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Append new memory entry to the end of the file
|
|
32
|
+
const updatedContent = existingContent + memoryEntry;
|
|
33
|
+
// Write file
|
|
34
|
+
await fs.writeFile(memoryFilePath, updatedContent, "utf-8");
|
|
35
|
+
// logger.info(`Memory added to ${memoryFilePath}:`, message);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// logger.error("Failed to add memory:", error);
|
|
39
|
+
throw new Error(`Failed to add memory: ${error.message}`);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
// User memory related methods
|
|
43
|
+
export const ensureUserMemoryFile = async () => {
|
|
44
|
+
try {
|
|
45
|
+
// Ensure data directory exists
|
|
46
|
+
await fs.mkdir(DATA_DIRECTORY, { recursive: true });
|
|
47
|
+
// Check if user memory file exists
|
|
48
|
+
try {
|
|
49
|
+
await fs.access(USER_MEMORY_FILE);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
// File does not exist, create new file
|
|
53
|
+
if (error.code === "ENOENT") {
|
|
54
|
+
const initialContent = "# User Memory\n\nThis is the user-level memory file, recording important information and context across projects.\n\n";
|
|
55
|
+
await fs.writeFile(USER_MEMORY_FILE, initialContent, "utf-8");
|
|
56
|
+
// logger.info(`Created user memory file: ${USER_MEMORY_FILE}`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
// logger.error("Failed to ensure user memory file:", error);
|
|
65
|
+
throw new Error(`Failed to ensure user memory file: ${error.message}`);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
export const addUserMemory = async (message) => {
|
|
69
|
+
try {
|
|
70
|
+
// Ensure user memory file exists
|
|
71
|
+
await ensureUserMemoryFile();
|
|
72
|
+
// Format memory entry, starting with -
|
|
73
|
+
const memoryEntry = `- ${message.substring(1).trim()}\n`;
|
|
74
|
+
// Read existing content
|
|
75
|
+
const existingContent = await fs.readFile(USER_MEMORY_FILE, "utf-8");
|
|
76
|
+
// Append new memory entry to the end of the file
|
|
77
|
+
const updatedContent = existingContent + memoryEntry;
|
|
78
|
+
// Write file
|
|
79
|
+
await fs.writeFile(USER_MEMORY_FILE, updatedContent, "utf-8");
|
|
80
|
+
// logger.info(`User memory added to ${USER_MEMORY_FILE}:`, message);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
// logger.error("Failed to add user memory:", error);
|
|
84
|
+
throw new Error(`Failed to add user memory: ${error.message}`);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
export const getUserMemoryContent = async () => {
|
|
88
|
+
try {
|
|
89
|
+
await ensureUserMemoryFile();
|
|
90
|
+
return await fs.readFile(USER_MEMORY_FILE, "utf-8");
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// logger.error("Failed to read user memory:", error);
|
|
94
|
+
return "";
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
// Read project memory file content
|
|
98
|
+
export const readMemoryFile = async (workdir) => {
|
|
99
|
+
try {
|
|
100
|
+
const memoryFilePath = path.join(workdir, "WAVE.md");
|
|
101
|
+
return await fs.readFile(memoryFilePath, "utf-8");
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error.code === "ENOENT") {
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
// Get merged memory content (project memory + user memory)
|
|
111
|
+
export const getCombinedMemoryContent = async (workdir) => {
|
|
112
|
+
// Read memory file content
|
|
113
|
+
const memoryContent = await readMemoryFile(workdir);
|
|
114
|
+
// Read user-level memory content
|
|
115
|
+
const userMemoryContent = await getUserMemoryContent();
|
|
116
|
+
// Merge project memory and user memory
|
|
117
|
+
let combinedMemory = "";
|
|
118
|
+
if (memoryContent.trim()) {
|
|
119
|
+
combinedMemory += memoryContent;
|
|
120
|
+
}
|
|
121
|
+
if (userMemoryContent.trim()) {
|
|
122
|
+
if (combinedMemory) {
|
|
123
|
+
combinedMemory += "\n\n";
|
|
124
|
+
}
|
|
125
|
+
combinedMemory += userMemoryContent;
|
|
126
|
+
}
|
|
127
|
+
return combinedMemory;
|
|
128
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Message } from "../types.js";
|
|
2
|
+
export interface SessionData {
|
|
3
|
+
id: string;
|
|
4
|
+
timestamp: string;
|
|
5
|
+
version: string;
|
|
6
|
+
messages: Message[];
|
|
7
|
+
metadata: {
|
|
8
|
+
workdir: string;
|
|
9
|
+
startedAt: string;
|
|
10
|
+
lastActiveAt: string;
|
|
11
|
+
latestTotalTokens: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface SessionMetadata {
|
|
15
|
+
id: string;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
workdir: string;
|
|
18
|
+
startedAt: string;
|
|
19
|
+
lastActiveAt: string;
|
|
20
|
+
latestTotalTokens: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Generate session file path
|
|
24
|
+
*/
|
|
25
|
+
export declare function getSessionFilePath(sessionId: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Save session data
|
|
28
|
+
*/
|
|
29
|
+
export declare function saveSession(sessionId: string, messages: Message[], workdir: string, latestTotalTokens?: number, startedAt?: string): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Load session data
|
|
32
|
+
*/
|
|
33
|
+
export declare function loadSession(sessionId: string): Promise<SessionData | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Get most recent session
|
|
36
|
+
*/
|
|
37
|
+
export declare function getLatestSession(workdir: string): Promise<SessionData | null>;
|
|
38
|
+
/**
|
|
39
|
+
* List all sessions
|
|
40
|
+
*/
|
|
41
|
+
export declare function listSessions(workdir: string, includeAllWorkdirs?: boolean): Promise<SessionMetadata[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Delete session
|
|
44
|
+
*/
|
|
45
|
+
export declare function deleteSession(sessionId: string): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Clean up expired sessions
|
|
48
|
+
*/
|
|
49
|
+
export declare function cleanupExpiredSessions(workdir: string): Promise<number>;
|
|
50
|
+
/**
|
|
51
|
+
* Check if session exists
|
|
52
|
+
*/
|
|
53
|
+
export declare function sessionExists(sessionId: string): Promise<boolean>;
|
|
54
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/services/session.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAkBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG5D;AAcD;;GAEG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,MAAM,EACf,iBAAiB,GAAE,MAAU,EAC7B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmB7B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAa7B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,kBAAkB,UAAQ,GACzB,OAAO,CAAC,eAAe,EAAE,CAAC,CA2C5B;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4B7E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASvE"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
// Constants
|
|
5
|
+
const SESSION_DIR = join(homedir(), ".wave", "sessions");
|
|
6
|
+
const VERSION = "1.0.0";
|
|
7
|
+
const MAX_SESSION_AGE_DAYS = 30;
|
|
8
|
+
/**
|
|
9
|
+
* Ensure session directory exists
|
|
10
|
+
*/
|
|
11
|
+
async function ensureSessionDir() {
|
|
12
|
+
try {
|
|
13
|
+
await fs.mkdir(SESSION_DIR, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
throw new Error(`Failed to create session directory: ${error}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generate session file path
|
|
21
|
+
*/
|
|
22
|
+
export function getSessionFilePath(sessionId) {
|
|
23
|
+
const shortId = sessionId.split("_")[2] || sessionId.slice(-8);
|
|
24
|
+
return join(SESSION_DIR, `session_${shortId}.json`);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Filter out diff blocks from messages to avoid saving unimportant data
|
|
28
|
+
*/
|
|
29
|
+
function filterDiffBlocks(messages) {
|
|
30
|
+
return messages
|
|
31
|
+
.map((message) => ({
|
|
32
|
+
...message,
|
|
33
|
+
blocks: message.blocks.filter((block) => block.type !== "diff"),
|
|
34
|
+
}))
|
|
35
|
+
.filter((message) => message.blocks.length > 0);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Save session data
|
|
39
|
+
*/
|
|
40
|
+
export async function saveSession(sessionId, messages, workdir, latestTotalTokens = 0, startedAt) {
|
|
41
|
+
// Do not save session files in test environment
|
|
42
|
+
if (process.env.NODE_ENV === "test") {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
await ensureSessionDir();
|
|
46
|
+
// Filter out diff blocks before saving
|
|
47
|
+
const filteredMessages = filterDiffBlocks(messages);
|
|
48
|
+
const now = new Date().toISOString();
|
|
49
|
+
const sessionData = {
|
|
50
|
+
id: sessionId,
|
|
51
|
+
timestamp: now,
|
|
52
|
+
version: VERSION,
|
|
53
|
+
messages: filteredMessages,
|
|
54
|
+
metadata: {
|
|
55
|
+
workdir: workdir,
|
|
56
|
+
startedAt: startedAt || now,
|
|
57
|
+
lastActiveAt: now,
|
|
58
|
+
latestTotalTokens,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
const filePath = getSessionFilePath(sessionId);
|
|
62
|
+
try {
|
|
63
|
+
await fs.writeFile(filePath, JSON.stringify(sessionData, null, 2), "utf-8");
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw new Error(`Failed to save session ${sessionId}: ${error}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Load session data
|
|
71
|
+
*/
|
|
72
|
+
export async function loadSession(sessionId) {
|
|
73
|
+
const filePath = getSessionFilePath(sessionId);
|
|
74
|
+
try {
|
|
75
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
76
|
+
const sessionData = JSON.parse(content);
|
|
77
|
+
// Validate session data format
|
|
78
|
+
if (!sessionData.id || !sessionData.messages || !sessionData.metadata) {
|
|
79
|
+
throw new Error("Invalid session data format");
|
|
80
|
+
}
|
|
81
|
+
return sessionData;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error.code === "ENOENT") {
|
|
85
|
+
return null; // Session file does not exist
|
|
86
|
+
}
|
|
87
|
+
throw new Error(`Failed to load session ${sessionId}: ${error}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get most recent session
|
|
92
|
+
*/
|
|
93
|
+
export async function getLatestSession(workdir) {
|
|
94
|
+
const sessions = await listSessions(workdir);
|
|
95
|
+
if (sessions.length === 0) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
// Sort by last active time, return the latest
|
|
99
|
+
const latestSession = sessions.sort((a, b) => new Date(b.lastActiveAt).getTime() - new Date(a.lastActiveAt).getTime())[0];
|
|
100
|
+
return loadSession(latestSession.id);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* List all sessions
|
|
104
|
+
*/
|
|
105
|
+
export async function listSessions(workdir, includeAllWorkdirs = false) {
|
|
106
|
+
try {
|
|
107
|
+
await ensureSessionDir();
|
|
108
|
+
const files = await fs.readdir(SESSION_DIR);
|
|
109
|
+
const sessions = [];
|
|
110
|
+
for (const file of files) {
|
|
111
|
+
if (!file.startsWith("session_") || !file.endsWith(".json")) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const filePath = join(SESSION_DIR, file);
|
|
116
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
117
|
+
const sessionData = JSON.parse(content);
|
|
118
|
+
// Only return sessions for the current working directory, unless includeAllWorkdirs is true
|
|
119
|
+
if (!includeAllWorkdirs && sessionData.metadata.workdir !== workdir) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
sessions.push({
|
|
123
|
+
id: sessionData.id,
|
|
124
|
+
timestamp: sessionData.timestamp,
|
|
125
|
+
workdir: sessionData.metadata.workdir,
|
|
126
|
+
startedAt: sessionData.metadata.startedAt,
|
|
127
|
+
lastActiveAt: sessionData.metadata.lastActiveAt,
|
|
128
|
+
latestTotalTokens: sessionData.metadata.latestTotalTokens,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// Ignore corrupted session files
|
|
133
|
+
console.warn(`Skipping corrupted session file: ${file}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return sessions.sort((a, b) => new Date(b.lastActiveAt).getTime() - new Date(a.lastActiveAt).getTime());
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
throw new Error(`Failed to list sessions: ${error}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Delete session
|
|
144
|
+
*/
|
|
145
|
+
export async function deleteSession(sessionId) {
|
|
146
|
+
const filePath = getSessionFilePath(sessionId);
|
|
147
|
+
try {
|
|
148
|
+
await fs.unlink(filePath);
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error.code === "ENOENT") {
|
|
153
|
+
return false; // File does not exist
|
|
154
|
+
}
|
|
155
|
+
throw new Error(`Failed to delete session ${sessionId}: ${error}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Clean up expired sessions
|
|
160
|
+
*/
|
|
161
|
+
export async function cleanupExpiredSessions(workdir) {
|
|
162
|
+
// Do not perform cleanup operations in test environment
|
|
163
|
+
if (process.env.NODE_ENV === "test") {
|
|
164
|
+
return 0;
|
|
165
|
+
}
|
|
166
|
+
const sessions = await listSessions(workdir, true);
|
|
167
|
+
const now = new Date();
|
|
168
|
+
const maxAge = MAX_SESSION_AGE_DAYS * 24 * 60 * 60 * 1000; // Convert to milliseconds
|
|
169
|
+
let deletedCount = 0;
|
|
170
|
+
for (const session of sessions) {
|
|
171
|
+
const sessionAge = now.getTime() - new Date(session.lastActiveAt).getTime();
|
|
172
|
+
if (sessionAge > maxAge) {
|
|
173
|
+
try {
|
|
174
|
+
await deleteSession(session.id);
|
|
175
|
+
deletedCount++;
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
console.warn(`Failed to delete expired session ${session.id}: ${error}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return deletedCount;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Check if session exists
|
|
186
|
+
*/
|
|
187
|
+
export async function sessionExists(sessionId) {
|
|
188
|
+
const filePath = getSessionFilePath(sessionId);
|
|
189
|
+
try {
|
|
190
|
+
await fs.access(filePath);
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ToolPlugin } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Bash command execution tool - supports both foreground and background execution
|
|
4
|
+
*/
|
|
5
|
+
export declare const bashTool: ToolPlugin;
|
|
6
|
+
/**
|
|
7
|
+
* BashOutput tool - retrieves output from background bash shells
|
|
8
|
+
*/
|
|
9
|
+
export declare const bashOutputTool: ToolPlugin;
|
|
10
|
+
/**
|
|
11
|
+
* KillBash tool - kills a running background bash shell
|
|
12
|
+
*/
|
|
13
|
+
export declare const killBashTool: ToolPlugin;
|
|
14
|
+
//# sourceMappingURL=bashTool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA2NtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,UAwF5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,UA8E1B,CAAC"}
|