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.
Files changed (68) hide show
  1. package/dist/agent.d.ts.map +1 -1
  2. package/dist/agent.js +5 -8
  3. package/dist/managers/aiManager.d.ts +6 -10
  4. package/dist/managers/aiManager.d.ts.map +1 -1
  5. package/dist/managers/aiManager.js +38 -13
  6. package/dist/managers/hookManager.d.ts.map +1 -1
  7. package/dist/managers/hookManager.js +15 -1
  8. package/dist/managers/messageManager.d.ts +1 -0
  9. package/dist/managers/messageManager.d.ts.map +1 -1
  10. package/dist/managers/messageManager.js +8 -2
  11. package/dist/managers/subagentManager.d.ts +2 -11
  12. package/dist/managers/subagentManager.d.ts.map +1 -1
  13. package/dist/managers/subagentManager.js +4 -53
  14. package/dist/prompts/autoMemory.d.ts +2 -0
  15. package/dist/prompts/autoMemory.d.ts.map +1 -0
  16. package/dist/prompts/autoMemory.js +33 -0
  17. package/dist/prompts/index.d.ts +4 -0
  18. package/dist/prompts/index.d.ts.map +1 -1
  19. package/dist/prompts/index.js +7 -0
  20. package/dist/services/aiService.js +6 -7
  21. package/dist/services/configurationService.d.ts +28 -16
  22. package/dist/services/configurationService.d.ts.map +1 -1
  23. package/dist/services/configurationService.js +87 -28
  24. package/dist/services/hook.js +2 -2
  25. package/dist/services/initializationService.d.ts.map +1 -1
  26. package/dist/services/initializationService.js +20 -9
  27. package/dist/services/memory.d.ts +22 -4
  28. package/dist/services/memory.d.ts.map +1 -1
  29. package/dist/services/memory.js +132 -73
  30. package/dist/types/configuration.d.ts +2 -0
  31. package/dist/types/configuration.d.ts.map +1 -1
  32. package/dist/types/history.d.ts +2 -0
  33. package/dist/types/history.d.ts.map +1 -1
  34. package/dist/types/hooks.d.ts +2 -0
  35. package/dist/types/hooks.d.ts.map +1 -1
  36. package/dist/types/hooks.js +17 -7
  37. package/dist/utils/containerSetup.d.ts +0 -5
  38. package/dist/utils/containerSetup.d.ts.map +1 -1
  39. package/dist/utils/containerSetup.js +11 -24
  40. package/dist/utils/fileSearch.d.ts +1 -6
  41. package/dist/utils/fileSearch.d.ts.map +1 -1
  42. package/dist/utils/fileSearch.js +104 -75
  43. package/dist/utils/gitUtils.d.ts +6 -0
  44. package/dist/utils/gitUtils.d.ts.map +1 -1
  45. package/dist/utils/gitUtils.js +18 -0
  46. package/dist/utils/promptHistory.d.ts +3 -3
  47. package/dist/utils/promptHistory.d.ts.map +1 -1
  48. package/dist/utils/promptHistory.js +12 -6
  49. package/package.json +2 -1
  50. package/src/agent.ts +7 -18
  51. package/src/managers/aiManager.ts +73 -28
  52. package/src/managers/hookManager.ts +22 -1
  53. package/src/managers/messageManager.ts +12 -2
  54. package/src/managers/subagentManager.ts +7 -69
  55. package/src/prompts/autoMemory.ts +33 -0
  56. package/src/prompts/index.ts +12 -0
  57. package/src/services/aiService.ts +8 -8
  58. package/src/services/configurationService.ts +100 -28
  59. package/src/services/hook.ts +2 -2
  60. package/src/services/initializationService.ts +24 -12
  61. package/src/services/memory.ts +144 -82
  62. package/src/types/configuration.ts +2 -0
  63. package/src/types/history.ts +2 -0
  64. package/src/types/hooks.ts +25 -9
  65. package/src/utils/containerSetup.ts +11 -33
  66. package/src/utils/fileSearch.ts +112 -80
  67. package/src/utils/gitUtils.ts +18 -0
  68. package/src/utils/promptHistory.ts +20 -6
@@ -1,91 +1,150 @@
1
- import { promises as fs } from "fs";
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
- // Project memory related methods
6
- // User memory related methods
7
- export const ensureUserMemoryFile = async () => {
8
- try {
9
- // Ensure data directory exists
10
- await fs.mkdir(DATA_DIRECTORY, { recursive: true });
11
- // Check if user memory file exists
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.access(USER_MEMORY_FILE);
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
- logger.info("Creating new user memory file", {
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
- catch (error) {
31
- logger.error("Failed to ensure user memory file:", error);
32
- throw new Error(`Failed to ensure user memory file: ${error.message}`);
33
- }
34
- };
35
- export const getUserMemoryContent = async () => {
36
- try {
37
- await ensureUserMemoryFile();
38
- const content = await fs.readFile(USER_MEMORY_FILE, "utf-8");
39
- logger.debug("User memory content read successfully", {
40
- userMemoryFile: USER_MEMORY_FILE,
41
- contentLength: content.length,
42
- });
43
- return content;
44
- }
45
- catch (error) {
46
- logger.error("Failed to read user memory:", error);
47
- return "";
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
- // Read project memory file content
51
- export const readMemoryFile = async (workdir) => {
52
- const memoryFilePath = path.join(workdir, "AGENTS.md");
53
- // Direct file access
54
- try {
55
- const content = await fs.readFile(memoryFilePath, "utf-8");
56
- logger.debug("Memory file read successfully via direct file access", {
57
- memoryFilePath,
58
- contentLength: content.length,
59
- });
60
- return content;
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
- catch (error) {
63
- if (error.code === "ENOENT") {
64
- logger.debug("Memory file does not exist, returning empty content", {
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
- if (userMemoryContent.trim()) {
85
- if (combinedMemory) {
86
- combinedMemory += "\n\n";
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 += userMemoryContent;
148
+ return combinedMemory;
89
149
  }
90
- return combinedMemory;
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":"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"}
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;IAClB,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,OAAO,CAC5C,MAAM,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC,CACrC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACxC,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kEAAkE;IAClE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,UAAU,MAAM;IACd,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC"}
@@ -1,5 +1,7 @@
1
1
  export interface PromptEntry {
2
2
  prompt: string;
3
3
  timestamp: number;
4
+ sessionId?: string;
5
+ longTextMap?: Record<string, string>;
4
6
  }
5
7
  //# sourceMappingURL=history.d.ts.map
@@ -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;CACnB"}
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"}
@@ -9,6 +9,8 @@ export type HookEvent = "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Sto
9
9
  export interface HookCommand {
10
10
  type: "command";
11
11
  command: string;
12
+ async?: boolean;
13
+ timeout?: number;
12
14
  }
13
15
  export interface HookEventConfig {
14
16
  matcher?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"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"}
@@ -36,13 +36,23 @@ export function isValidHookEvent(event) {
36
36
  ].includes(event);
37
37
  }
38
38
  export function isValidHookCommand(cmd) {
39
- return (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);
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":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAoB3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIrE,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;IAGjC,gBAAgB,EAAE,MAAM,aAAa,CAAC;IACtC,cAAc,EAAE,MAAM,WAAW,CAAC;IAClC,iBAAiB,EAAE,MAAM,MAAM,CAAC;IAChC,WAAW,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,CAgOX"}
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, getGatewayConfig, getModelConfig, getMaxInputTokens, getLanguage, } = setupOptions;
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
- try {
125
- const planContent = await fs.readFile(planFilePath, "utf-8");
126
- messageManager.addUserMessage({
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
- * Convert Path objects to FileItem objects
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":"AAAA,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,MAAM,CAAC;AAE9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,OAAO,IAAI,EAAE,KAAG,QAAQ,EAY/D,CAAC;AAEF;;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,CAmFpB,CAAC"}
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"}
@@ -1,95 +1,124 @@
1
- import { globIterate } from "glob";
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
- * Convert Path objects to FileItem objects
7
+ * Execute ripgrep to get all file paths
5
8
  */
6
- export const convertPathsToFileItems = (paths) => {
7
- return paths.map((pathObj) => {
8
- const isDirectory = pathObj.isDirectory();
9
- let path = pathObj.relative();
10
- if (isDirectory && !path.endsWith("/")) {
11
- path += "/";
12
- }
13
- return {
14
- path,
15
- type: isDirectory ? "directory" : "file",
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 glob patterns
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 globOptions = {
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
- patterns = [
38
- "**/*.{ts,tsx,js,jsx,json,py,java}", // Combine common file extensions
39
- "*/", // First level directories
40
- ];
41
- }
42
- else {
43
- // Build multiple glob patterns to support more flexible search
44
- patterns = [
45
- // Match files with filenames containing query
46
- `**/*${query}*`,
47
- // Match files with query in path (match directory names)
48
- `**/${query}*/**/*`,
49
- // Match directory names containing query
50
- `**/*${query}*/`,
51
- // Match directories containing query in path
52
- `**/${query}*/`,
53
- ];
54
- }
55
- // Collect results until we reach maxResults
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 relativePath = pathObj.relative();
71
- if (!seenPaths.has(relativePath)) {
72
- seenPaths.add(relativePath);
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
- // Sort collected paths: directories first, then files
78
- collectedPaths.sort((a, b) => {
79
- const aIsDir = a.isDirectory();
80
- const bIsDir = b.isDirectory();
81
- if (aIsDir && !bIsDir)
82
- return -1;
83
- if (!aIsDir && bIsDir)
84
- return 1;
85
- return a.relative().localeCompare(b.relative());
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
- // Convert to FileItems
88
- const fileItems = convertPathsToFileItems(collectedPaths);
89
- return fileItems;
118
+ return fuzzyResults.map((res) => res.obj);
90
119
  }
91
120
  catch (error) {
92
- console.error("Glob search error:", error);
121
+ logger.error("Fuzzy search error:", error);
93
122
  return [];
94
123
  }
95
124
  };