wave-agent-sdk 0.8.4 → 0.9.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/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +5 -8
- package/dist/managers/aiManager.d.ts +6 -10
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +38 -13
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +15 -1
- package/dist/managers/messageManager.d.ts +1 -0
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +8 -2
- package/dist/managers/subagentManager.d.ts +2 -11
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +4 -53
- package/dist/prompts/autoMemory.d.ts +2 -0
- package/dist/prompts/autoMemory.d.ts.map +1 -0
- package/dist/prompts/autoMemory.js +33 -0
- package/dist/prompts/index.d.ts +4 -0
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +7 -0
- package/dist/services/aiService.js +6 -7
- package/dist/services/configurationService.d.ts +28 -16
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +87 -28
- package/dist/services/hook.js +2 -2
- package/dist/services/initializationService.d.ts.map +1 -1
- package/dist/services/initializationService.js +20 -9
- package/dist/services/memory.d.ts +22 -4
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +132 -73
- package/dist/types/configuration.d.ts +2 -0
- package/dist/types/configuration.d.ts.map +1 -1
- package/dist/types/history.d.ts +2 -0
- package/dist/types/history.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +2 -0
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +17 -7
- package/dist/utils/containerSetup.d.ts +0 -5
- package/dist/utils/containerSetup.d.ts.map +1 -1
- package/dist/utils/containerSetup.js +11 -24
- package/dist/utils/fileSearch.d.ts +1 -6
- package/dist/utils/fileSearch.d.ts.map +1 -1
- package/dist/utils/fileSearch.js +104 -75
- package/dist/utils/gitUtils.d.ts +6 -0
- package/dist/utils/gitUtils.d.ts.map +1 -1
- package/dist/utils/gitUtils.js +18 -0
- package/dist/utils/promptHistory.d.ts +3 -3
- package/dist/utils/promptHistory.d.ts.map +1 -1
- package/dist/utils/promptHistory.js +12 -6
- package/package.json +2 -1
- package/src/agent.ts +7 -18
- package/src/managers/aiManager.ts +73 -28
- package/src/managers/hookManager.ts +22 -1
- package/src/managers/messageManager.ts +12 -2
- package/src/managers/subagentManager.ts +7 -69
- package/src/prompts/autoMemory.ts +33 -0
- package/src/prompts/index.ts +12 -0
- package/src/services/aiService.ts +8 -8
- package/src/services/configurationService.ts +100 -28
- package/src/services/hook.ts +2 -2
- package/src/services/initializationService.ts +24 -12
- package/src/services/memory.ts +144 -82
- package/src/types/configuration.ts +2 -0
- package/src/types/history.ts +2 -0
- package/src/types/hooks.ts +25 -9
- package/src/utils/containerSetup.ts +11 -33
- package/src/utils/fileSearch.ts +112 -80
- package/src/utils/gitUtils.ts +18 -0
- package/src/utils/promptHistory.ts +20 -6
package/dist/services/memory.js
CHANGED
|
@@ -1,91 +1,150 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from "path";
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
3
4
|
import { USER_MEMORY_FILE, DATA_DIRECTORY } from "../utils/constants.js";
|
|
4
5
|
import { logger } from "../utils/globalLogger.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
import { getGitCommonDir } from "../utils/gitUtils.js";
|
|
7
|
+
import { pathEncoder } from "../utils/pathEncoder.js";
|
|
8
|
+
export class MemoryService {
|
|
9
|
+
constructor(container) {
|
|
10
|
+
this.container = container;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get the project-specific auto-memory directory.
|
|
14
|
+
* Uses the git common directory to ensure worktrees share the same memory.
|
|
15
|
+
*/
|
|
16
|
+
getAutoMemoryDirectory(workdir) {
|
|
17
|
+
const projectRoot = getGitCommonDir(workdir);
|
|
18
|
+
const encodedName = pathEncoder.encodeSync(projectRoot);
|
|
19
|
+
return path.join(homedir(), ".wave", "projects", encodedName, "memory");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Ensure the auto-memory directory and initial MEMORY.md exist.
|
|
23
|
+
*/
|
|
24
|
+
async ensureAutoMemoryDirectory(workdir) {
|
|
25
|
+
const memoryDir = this.getAutoMemoryDirectory(workdir);
|
|
26
|
+
const memoryFile = path.join(memoryDir, "MEMORY.md");
|
|
27
|
+
try {
|
|
28
|
+
await fs.mkdir(memoryDir, { recursive: true });
|
|
29
|
+
try {
|
|
30
|
+
await fs.access(memoryFile);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error.code === "ENOENT") {
|
|
34
|
+
const initialContent = "# Project Memory\n\nThis file serves as an index for the project's auto-memory. Wave uses this to track knowledge across sessions.\n\n";
|
|
35
|
+
await fs.writeFile(memoryFile, initialContent, "utf-8");
|
|
36
|
+
logger.debug(`Created auto-memory file: ${memoryFile}`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
logger.error("Failed to ensure auto-memory directory:", error);
|
|
45
|
+
throw new Error(`Failed to ensure auto-memory directory: ${error.message}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the first 200 lines of MEMORY.md.
|
|
50
|
+
*/
|
|
51
|
+
async getAutoMemoryContent(workdir) {
|
|
52
|
+
const memoryDir = this.getAutoMemoryDirectory(workdir);
|
|
53
|
+
const memoryFile = path.join(memoryDir, "MEMORY.md");
|
|
12
54
|
try {
|
|
13
|
-
await fs.
|
|
55
|
+
const content = await fs.readFile(memoryFile, "utf-8");
|
|
56
|
+
const lines = content.split("\n").slice(0, 200);
|
|
57
|
+
return lines.join("\n");
|
|
14
58
|
}
|
|
15
59
|
catch (error) {
|
|
16
|
-
// File does not exist, create new file
|
|
17
60
|
if (error.code === "ENOENT") {
|
|
18
|
-
|
|
19
|
-
userMemoryFile: USER_MEMORY_FILE,
|
|
20
|
-
});
|
|
21
|
-
const initialContent = "# User Memory\n\nThis is the user-level memory file, recording important information and context across projects.\n\n";
|
|
22
|
-
await fs.writeFile(USER_MEMORY_FILE, initialContent, "utf-8");
|
|
23
|
-
logger.debug(`Created user memory file: ${USER_MEMORY_FILE}`);
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
throw error;
|
|
61
|
+
return "";
|
|
27
62
|
}
|
|
63
|
+
logger.error("Failed to read auto-memory content:", error);
|
|
64
|
+
return "";
|
|
28
65
|
}
|
|
29
66
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
67
|
+
async ensureUserMemoryFile() {
|
|
68
|
+
try {
|
|
69
|
+
// Ensure data directory exists
|
|
70
|
+
await fs.mkdir(DATA_DIRECTORY, { recursive: true });
|
|
71
|
+
// Check if user memory file exists
|
|
72
|
+
try {
|
|
73
|
+
await fs.access(USER_MEMORY_FILE);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
// File does not exist, create new file
|
|
77
|
+
if (error.code === "ENOENT") {
|
|
78
|
+
logger.info("Creating new user memory file", {
|
|
79
|
+
userMemoryFile: USER_MEMORY_FILE,
|
|
80
|
+
});
|
|
81
|
+
const initialContent = "# User Memory\n\nThis is the user-level memory file, recording important information and context across projects.\n\n";
|
|
82
|
+
await fs.writeFile(USER_MEMORY_FILE, initialContent, "utf-8");
|
|
83
|
+
logger.debug(`Created user memory file: ${USER_MEMORY_FILE}`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
logger.error("Failed to ensure user memory file:", error);
|
|
92
|
+
throw new Error(`Failed to ensure user memory file: ${error.message}`);
|
|
93
|
+
}
|
|
48
94
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
95
|
+
async getUserMemoryContent() {
|
|
96
|
+
try {
|
|
97
|
+
await this.ensureUserMemoryFile();
|
|
98
|
+
const content = await fs.readFile(USER_MEMORY_FILE, "utf-8");
|
|
99
|
+
logger.debug("User memory content read successfully", {
|
|
100
|
+
userMemoryFile: USER_MEMORY_FILE,
|
|
101
|
+
contentLength: content.length,
|
|
102
|
+
});
|
|
103
|
+
return content;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
logger.error("Failed to read user memory:", error);
|
|
107
|
+
return "";
|
|
108
|
+
}
|
|
61
109
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
110
|
+
async readMemoryFile(workdir) {
|
|
111
|
+
const memoryFilePath = path.join(workdir, "AGENTS.md");
|
|
112
|
+
// Direct file access
|
|
113
|
+
try {
|
|
114
|
+
const content = await fs.readFile(memoryFilePath, "utf-8");
|
|
115
|
+
logger.debug("Memory file read successfully via direct file access", {
|
|
65
116
|
memoryFilePath,
|
|
117
|
+
contentLength: content.length,
|
|
66
118
|
});
|
|
119
|
+
return content;
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
if (error.code === "ENOENT") {
|
|
123
|
+
logger.debug("Memory file does not exist, returning empty content", {
|
|
124
|
+
memoryFilePath,
|
|
125
|
+
});
|
|
126
|
+
return "";
|
|
127
|
+
}
|
|
128
|
+
logger.error("Failed to read memory file", { memoryFilePath, error });
|
|
67
129
|
return "";
|
|
68
130
|
}
|
|
69
|
-
logger.error("Failed to read memory file", { memoryFilePath, error });
|
|
70
|
-
return "";
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
// Get merged memory content (project memory + user memory)
|
|
74
|
-
export const getCombinedMemoryContent = async (workdir) => {
|
|
75
|
-
// Read memory file content
|
|
76
|
-
const memoryContent = await readMemoryFile(workdir);
|
|
77
|
-
// Read user-level memory content
|
|
78
|
-
const userMemoryContent = await getUserMemoryContent();
|
|
79
|
-
// Merge project memory and user memory
|
|
80
|
-
let combinedMemory = "";
|
|
81
|
-
if (memoryContent.trim()) {
|
|
82
|
-
combinedMemory += memoryContent;
|
|
83
131
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
132
|
+
async getCombinedMemoryContent(workdir) {
|
|
133
|
+
// Read memory file content
|
|
134
|
+
const memoryContent = await this.readMemoryFile(workdir);
|
|
135
|
+
// Read user-level memory content
|
|
136
|
+
const userMemoryContent = await this.getUserMemoryContent();
|
|
137
|
+
// Merge project memory and user memory
|
|
138
|
+
let combinedMemory = "";
|
|
139
|
+
if (memoryContent.trim()) {
|
|
140
|
+
combinedMemory += memoryContent;
|
|
141
|
+
}
|
|
142
|
+
if (userMemoryContent.trim()) {
|
|
143
|
+
if (combinedMemory) {
|
|
144
|
+
combinedMemory += "\n\n";
|
|
145
|
+
}
|
|
146
|
+
combinedMemory += userMemoryContent;
|
|
87
147
|
}
|
|
88
|
-
combinedMemory
|
|
148
|
+
return combinedMemory;
|
|
89
149
|
}
|
|
90
|
-
|
|
91
|
-
};
|
|
150
|
+
}
|
|
@@ -29,6 +29,8 @@ export interface WaveConfiguration {
|
|
|
29
29
|
enabledPlugins?: Record<string, boolean>;
|
|
30
30
|
/** Preferred language for agent communication */
|
|
31
31
|
language?: string;
|
|
32
|
+
/** Whether auto-memory is enabled */
|
|
33
|
+
autoMemoryEnabled?: boolean;
|
|
32
34
|
}
|
|
33
35
|
/**
|
|
34
36
|
* Legacy alias for backward compatibility - will be deprecated
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../src/types/configuration.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,2CAA2C;IAC3C,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,WAAW,CAAC,EAAE,cAAc,CAAC;QAC7B;;;WAGG;QACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;KAClC,CAAC;IACF,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../src/types/configuration.ts"],"names":[],"mappings":"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"}
|
package/dist/types/history.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/types/history.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/types/history.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC"}
|
package/dist/types/hooks.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAG5B,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,aAAa,GACb,kBAAkB,GAClB,MAAM,GACN,cAAc,GACd,cAAc,GACd,gBAAgB,CAAC;AAGrB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/types/hooks.js
CHANGED
|
@@ -36,13 +36,23 @@ export function isValidHookEvent(event) {
|
|
|
36
36
|
].includes(event);
|
|
37
37
|
}
|
|
38
38
|
export function isValidHookCommand(cmd) {
|
|
39
|
-
|
|
40
|
-
cmd
|
|
41
|
-
"type" in cmd
|
|
42
|
-
cmd.type
|
|
43
|
-
"command" in cmd
|
|
44
|
-
typeof cmd.command
|
|
45
|
-
cmd.command.length
|
|
39
|
+
if (typeof cmd !== "object" ||
|
|
40
|
+
cmd === null ||
|
|
41
|
+
!("type" in cmd) ||
|
|
42
|
+
cmd.type !== "command" ||
|
|
43
|
+
!("command" in cmd) ||
|
|
44
|
+
typeof cmd.command !== "string" ||
|
|
45
|
+
cmd.command.length === 0) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const hookCmd = cmd;
|
|
49
|
+
if ("async" in hookCmd && typeof hookCmd.async !== "boolean") {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if ("timeout" in hookCmd && typeof hookCmd.timeout !== "number") {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
46
56
|
}
|
|
47
57
|
export function isValidHookEventConfig(config) {
|
|
48
58
|
if (typeof config !== "object" || config === null)
|
|
@@ -2,7 +2,6 @@ import { Container } from "./container.js";
|
|
|
2
2
|
import { ConfigurationService } from "../services/configurationService.js";
|
|
3
3
|
import type { AgentOptions } from "../types/index.js";
|
|
4
4
|
import type { PermissionMode, Usage, Task, BackgroundTask } from "../types/index.js";
|
|
5
|
-
import type { GatewayConfig, ModelConfig } from "../types/config.js";
|
|
6
5
|
export interface AgentContainerSetupOptions {
|
|
7
6
|
options: AgentOptions;
|
|
8
7
|
workdir: string;
|
|
@@ -16,10 +15,6 @@ export interface AgentContainerSetupOptions {
|
|
|
16
15
|
setPermissionMode: (mode: PermissionMode) => void;
|
|
17
16
|
addPermissionRule: (rule: string) => Promise<void>;
|
|
18
17
|
addUsage: (usage: Usage) => void;
|
|
19
|
-
getGatewayConfig: () => GatewayConfig;
|
|
20
|
-
getModelConfig: () => ModelConfig;
|
|
21
|
-
getMaxInputTokens: () => number;
|
|
22
|
-
getLanguage: () => string | undefined;
|
|
23
18
|
}
|
|
24
19
|
export declare function setupAgentContainer(setupOptions: AgentContainerSetupOptions): Container;
|
|
25
20
|
//# sourceMappingURL=containerSetup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAoB3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAG3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAI3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,CAiNX"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as fs from "fs/promises";
|
|
2
1
|
import { Container } from "./container.js";
|
|
3
2
|
import { ForegroundTaskManager } from "../managers/foregroundTaskManager.js";
|
|
4
3
|
import { BackgroundTaskManager } from "../managers/backgroundTaskManager.js";
|
|
@@ -20,14 +19,17 @@ import { ReversionManager } from "../managers/reversionManager.js";
|
|
|
20
19
|
import { SubagentManager } from "../managers/subagentManager.js";
|
|
21
20
|
import { LiveConfigManager } from "../managers/liveConfigManager.js";
|
|
22
21
|
import { ReversionService } from "../services/reversionService.js";
|
|
22
|
+
import { MemoryService } from "../services/memory.js";
|
|
23
23
|
import { logger } from "./globalLogger.js";
|
|
24
24
|
export function setupAgentContainer(setupOptions) {
|
|
25
|
-
const { options, workdir, configurationService, systemPrompt, stream, onBackgroundTasksChange, onTasksChange, onPermissionModeChange, handlePlanModeTransition, setPermissionMode, addPermissionRule, addUsage,
|
|
25
|
+
const { options, workdir, configurationService, systemPrompt, stream, onBackgroundTasksChange, onTasksChange, onPermissionModeChange, handlePlanModeTransition, setPermissionMode, addPermissionRule, addUsage, } = setupOptions;
|
|
26
26
|
const callbacks = options.callbacks || {};
|
|
27
27
|
const container = new Container();
|
|
28
28
|
const foregroundTaskManager = new ForegroundTaskManager(container);
|
|
29
29
|
container.register("ForegroundTaskManager", foregroundTaskManager);
|
|
30
30
|
container.register("ConfigurationService", configurationService);
|
|
31
|
+
const memoryService = new MemoryService(container);
|
|
32
|
+
container.register("MemoryService", memoryService);
|
|
31
33
|
const memoryRuleManager = new MemoryRuleManager(container, { workdir });
|
|
32
34
|
container.register("MemoryRuleManager", memoryRuleManager);
|
|
33
35
|
const messageManager = new MessageManager(container, {
|
|
@@ -74,6 +76,10 @@ export function setupAgentContainer(setupOptions) {
|
|
|
74
76
|
const lspManager = options.lspManager || new LspManager(container);
|
|
75
77
|
container.register("LspManager", lspManager);
|
|
76
78
|
const permissionManager = new PermissionManager(container, { workdir });
|
|
79
|
+
if (configurationService.resolveAutoMemoryEnabled()) {
|
|
80
|
+
const autoMemoryDir = memoryService.getAutoMemoryDirectory(workdir);
|
|
81
|
+
permissionManager.updateAdditionalDirectories([autoMemoryDir]);
|
|
82
|
+
}
|
|
77
83
|
container.register("PermissionManager", permissionManager);
|
|
78
84
|
permissionManager.setOnConfiguredDefaultModeChange((mode) => {
|
|
79
85
|
handlePlanModeTransition(mode);
|
|
@@ -121,18 +127,9 @@ export function setupAgentContainer(setupOptions) {
|
|
|
121
127
|
if (decision.clearContext) {
|
|
122
128
|
messageManager.clearMessages();
|
|
123
129
|
if (planFilePath) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
content: `Implement the following plan:\n\n${planContent}`,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
catch (error) {
|
|
131
|
-
logger.warn("Failed to read plan file for context clearing", {
|
|
132
|
-
planFilePath,
|
|
133
|
-
error: error instanceof Error ? error.message : String(error),
|
|
134
|
-
});
|
|
135
|
-
}
|
|
130
|
+
messageManager.addUserMessage({
|
|
131
|
+
content: `Implement the plan at ${planFilePath}`,
|
|
132
|
+
});
|
|
136
133
|
}
|
|
137
134
|
}
|
|
138
135
|
return decision;
|
|
@@ -161,11 +158,6 @@ export function setupAgentContainer(setupOptions) {
|
|
|
161
158
|
onSubagentMessagesChange: callbacks.onSubagentMessagesChange,
|
|
162
159
|
onSubagentLatestTotalTokensChange: callbacks.onSubagentLatestTotalTokensChange,
|
|
163
160
|
},
|
|
164
|
-
getGatewayConfig,
|
|
165
|
-
getModelConfig,
|
|
166
|
-
getMaxInputTokens,
|
|
167
|
-
getLanguage,
|
|
168
|
-
getEnvironmentVars: () => configurationService.getEnvironmentVars(),
|
|
169
161
|
onUsageAdded: (usage) => addUsage(usage),
|
|
170
162
|
});
|
|
171
163
|
container.register("SubagentManager", subagentManager);
|
|
@@ -177,11 +169,6 @@ export function setupAgentContainer(setupOptions) {
|
|
|
177
169
|
workdir,
|
|
178
170
|
systemPrompt,
|
|
179
171
|
stream,
|
|
180
|
-
getGatewayConfig,
|
|
181
|
-
getModelConfig,
|
|
182
|
-
getMaxInputTokens,
|
|
183
|
-
getLanguage,
|
|
184
|
-
getEnvironmentVars: () => configurationService.getEnvironmentVars(),
|
|
185
172
|
});
|
|
186
173
|
container.register("AIManager", aiManager);
|
|
187
174
|
const slashCommandManager = new SlashCommandManager(container, { workdir });
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import { type Path } from "glob";
|
|
2
1
|
import type { FileItem } from "../types/fileSearch.js";
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
export declare const convertPathsToFileItems: (paths: Path[]) => FileItem[];
|
|
7
|
-
/**
|
|
8
|
-
* Search files and directories using glob patterns
|
|
3
|
+
* Search files and directories using fuzzy matching
|
|
9
4
|
*/
|
|
10
5
|
export declare const searchFiles: (query: string, options?: {
|
|
11
6
|
maxResults?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileSearch.d.ts","sourceRoot":"","sources":["../../src/utils/fileSearch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fileSearch.d.ts","sourceRoot":"","sources":["../../src/utils/fileSearch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAqEvD;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,MAAM,EACb,UAAU;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,KACA,OAAO,CAAC,QAAQ,EAAE,CA+DpB,CAAC"}
|
package/dist/utils/fileSearch.js
CHANGED
|
@@ -1,95 +1,124 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { rgPath } from "@vscode/ripgrep";
|
|
3
|
+
import fuzzysort from "fuzzysort";
|
|
2
4
|
import { getGlobIgnorePatterns } from "./fileFilter.js";
|
|
5
|
+
import { logger } from "./globalLogger.js";
|
|
3
6
|
/**
|
|
4
|
-
*
|
|
7
|
+
* Execute ripgrep to get all file paths
|
|
5
8
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
async function getAllFiles(workingDirectory) {
|
|
10
|
+
if (!rgPath) {
|
|
11
|
+
throw new Error("ripgrep is not available");
|
|
12
|
+
}
|
|
13
|
+
const ignorePatterns = getGlobIgnorePatterns(workingDirectory);
|
|
14
|
+
const rgArgs = ["--files", "--color=never", "--hidden"];
|
|
15
|
+
for (const pattern of ignorePatterns) {
|
|
16
|
+
rgArgs.push("--glob", `!${pattern}`);
|
|
17
|
+
}
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
const child = spawn(rgPath, rgArgs, {
|
|
20
|
+
cwd: workingDirectory,
|
|
21
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
22
|
+
});
|
|
23
|
+
let stdout = "";
|
|
24
|
+
let stderr = "";
|
|
25
|
+
child.stdout?.on("data", (data) => {
|
|
26
|
+
stdout += data.toString();
|
|
27
|
+
});
|
|
28
|
+
child.stderr?.on("data", (data) => {
|
|
29
|
+
stderr += data.toString();
|
|
30
|
+
});
|
|
31
|
+
child.on("close", (code) => {
|
|
32
|
+
if (code !== 0 && code !== 1) {
|
|
33
|
+
reject(new Error(`ripgrep failed: ${stderr}`));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const files = stdout
|
|
37
|
+
.trim()
|
|
38
|
+
.split("\n")
|
|
39
|
+
.filter((f) => f.length > 0)
|
|
40
|
+
.map((f) => f.replace(/\\/g, "/")); // Normalize to forward slashes
|
|
41
|
+
resolve(files);
|
|
42
|
+
});
|
|
43
|
+
child.on("error", (err) => {
|
|
44
|
+
reject(err);
|
|
45
|
+
});
|
|
17
46
|
});
|
|
18
|
-
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Derive directory paths from file paths
|
|
50
|
+
*/
|
|
51
|
+
function deriveDirectories(files) {
|
|
52
|
+
const dirs = new Set();
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
const parts = file.split("/");
|
|
55
|
+
// Add all parent directories
|
|
56
|
+
for (let i = 1; i < parts.length; i++) {
|
|
57
|
+
const dir = parts.slice(0, i).join("/") + "/";
|
|
58
|
+
dirs.add(dir);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return Array.from(dirs);
|
|
62
|
+
}
|
|
19
63
|
/**
|
|
20
|
-
* Search files and directories using
|
|
64
|
+
* Search files and directories using fuzzy matching
|
|
21
65
|
*/
|
|
22
66
|
export const searchFiles = async (query, options) => {
|
|
23
67
|
const { maxResults = 10, workingDirectory = process.cwd() } = options || {};
|
|
24
68
|
try {
|
|
25
|
-
const
|
|
26
|
-
ignore: getGlobIgnorePatterns(workingDirectory),
|
|
27
|
-
maxDepth: 10,
|
|
28
|
-
nocase: true, // Case insensitive
|
|
29
|
-
dot: true, // Include hidden files and directories
|
|
30
|
-
cwd: workingDirectory, // Specify search root directory
|
|
31
|
-
withFileTypes: true, // Get Path objects instead of strings
|
|
32
|
-
};
|
|
33
|
-
// Build glob patterns based on query
|
|
34
|
-
let patterns = [];
|
|
69
|
+
const files = await getAllFiles(workingDirectory);
|
|
35
70
|
if (!query.trim()) {
|
|
36
|
-
// When query is empty, show some common file types and directories
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const collectedPaths = [];
|
|
57
|
-
const seenPaths = new Set();
|
|
58
|
-
// Process each pattern sequentially
|
|
59
|
-
for (const pattern of patterns) {
|
|
60
|
-
if (collectedPaths.length >= maxResults) {
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
// Use globIterate to get results one by one
|
|
64
|
-
const iterator = globIterate(pattern, globOptions);
|
|
65
|
-
for await (const pathObj of iterator) {
|
|
66
|
-
if (collectedPaths.length >= maxResults) {
|
|
67
|
-
// Stop the iterator when we have enough results
|
|
68
|
-
break;
|
|
71
|
+
// When query is empty, show some common file types and top-level directories
|
|
72
|
+
const commonExtensions = new Set([
|
|
73
|
+
"ts",
|
|
74
|
+
"tsx",
|
|
75
|
+
"js",
|
|
76
|
+
"jsx",
|
|
77
|
+
"json",
|
|
78
|
+
"py",
|
|
79
|
+
"java",
|
|
80
|
+
]);
|
|
81
|
+
const results = [];
|
|
82
|
+
const seenDirs = new Set();
|
|
83
|
+
for (const file of files) {
|
|
84
|
+
const parts = file.split("/");
|
|
85
|
+
if (parts.length > 1) {
|
|
86
|
+
const topDir = parts[0] + "/";
|
|
87
|
+
if (!seenDirs.has(topDir)) {
|
|
88
|
+
seenDirs.add(topDir);
|
|
89
|
+
results.push({ path: topDir, type: "directory" });
|
|
90
|
+
}
|
|
69
91
|
}
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
collectedPaths.push(pathObj);
|
|
92
|
+
const ext = file.split(".").pop();
|
|
93
|
+
if (ext && commonExtensions.has(ext)) {
|
|
94
|
+
results.push({ path: file, type: "file" });
|
|
74
95
|
}
|
|
75
96
|
}
|
|
97
|
+
// Sort: directories first, then files, then alphabetically
|
|
98
|
+
return results
|
|
99
|
+
.sort((a, b) => {
|
|
100
|
+
if (a.type === "directory" && b.type === "file")
|
|
101
|
+
return -1;
|
|
102
|
+
if (a.type === "file" && b.type === "directory")
|
|
103
|
+
return 1;
|
|
104
|
+
return a.path.localeCompare(b.path);
|
|
105
|
+
})
|
|
106
|
+
.slice(0, maxResults);
|
|
76
107
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
108
|
+
const directories = deriveDirectories(files);
|
|
109
|
+
const allItems = [
|
|
110
|
+
...files.map((f) => ({ path: f, type: "file" })),
|
|
111
|
+
...directories.map((d) => ({ path: d, type: "directory" })),
|
|
112
|
+
];
|
|
113
|
+
const fuzzyResults = fuzzysort.go(query, allItems, {
|
|
114
|
+
key: "path",
|
|
115
|
+
limit: maxResults,
|
|
116
|
+
threshold: 0,
|
|
86
117
|
});
|
|
87
|
-
|
|
88
|
-
const fileItems = convertPathsToFileItems(collectedPaths);
|
|
89
|
-
return fileItems;
|
|
118
|
+
return fuzzyResults.map((res) => res.obj);
|
|
90
119
|
}
|
|
91
120
|
catch (error) {
|
|
92
|
-
|
|
121
|
+
logger.error("Fuzzy search error:", error);
|
|
93
122
|
return [];
|
|
94
123
|
}
|
|
95
124
|
};
|