@axiom-lattice/core 2.1.46 → 2.1.47

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/index.js CHANGED
@@ -4833,516 +4833,241 @@ var createReactAgentSchema = (schema) => {
4833
4833
  // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
4834
4834
  var import_langchain55 = require("langchain");
4835
4835
 
4836
- // src/deep_agent_new/backends/sandboxFiles.ts
4837
- var import_sandbox2 = require("@agent-infra/sandbox");
4838
- var path2 = __toESM(require("path"));
4839
- var SandboxFilesystem = class {
4840
- /**
4841
- * Create a new SandboxFilesystem instance.
4842
- *
4843
- * @param options - Configuration options
4844
- * @param options.baseURL - Base URL of the sandbox service (default: 'http://localhost:8080')
4845
- * @param options.maxFileSizeMb - Maximum file size in MB (default: 10)
4846
- * @param options.sandboxInstance - Optional Sandbox instance (if provided, baseURL is ignored)
4847
- */
4848
- constructor(options = {}) {
4849
- const {
4850
- baseURL = "http://localhost:8080",
4851
- workingDirectory = "/",
4852
- maxFileSizeMb = 10,
4853
- sandboxInstance
4854
- } = options;
4855
- this.sandbox = sandboxInstance || new import_sandbox2.SandboxClient({ baseUrl: baseURL, environment: "" });
4856
- this.sandbox.mcp.listMcpServers().then((servers) => {
4857
- });
4858
- this.sandbox.mcp.listMcpTools("browser").then((tools) => {
4836
+ // src/middlewares/codeEvalMiddleware.ts
4837
+ var import_langchain37 = require("langchain");
4838
+
4839
+ // src/middlewares/contextSchema.ts
4840
+ var import_zod41 = __toESM(require("zod"));
4841
+ var contextSchema = import_zod41.default.object({
4842
+ runConfig: import_zod41.default.any()
4843
+ });
4844
+
4845
+ // src/middlewares/codeEvalMiddleware.ts
4846
+ function createCodeEvalMiddleware(params = { isolatedLevel: "global" }) {
4847
+ const codeEvalTool = createCodeEvalTool({ isolatedLevel: params.isolatedLevel });
4848
+ const codeExecuteFileTool = createCodeExecuteFileTool({ isolatedLevel: params.isolatedLevel });
4849
+ return (0, import_langchain37.createMiddleware)({
4850
+ name: "codeEvalMiddleware",
4851
+ contextSchema,
4852
+ tools: [codeEvalTool, codeExecuteFileTool, getToolClient("convert_to_markdown")]
4853
+ });
4854
+ }
4855
+
4856
+ // src/middlewares/browserMiddleware.ts
4857
+ var import_langchain38 = require("langchain");
4858
+ function createBrowserMiddleware(params = { isolatedLevel: "global" }) {
4859
+ const isolatedLevel = params.isolatedLevel || "global";
4860
+ const tools = [
4861
+ createBrowserNavigateTool({ isolatedLevel }),
4862
+ createBrowserClickTool({ isolatedLevel }),
4863
+ createBrowserGetTextTool({ isolatedLevel }),
4864
+ createBrowserGetMarkdownTool({ isolatedLevel }),
4865
+ createBrowserEvaluateTool({ isolatedLevel }),
4866
+ createBrowserScreenshotTool({ isolatedLevel }),
4867
+ createBrowserScrollTool({ isolatedLevel }),
4868
+ createBrowserFormInputFillTool({ isolatedLevel }),
4869
+ createBrowserSelectTool({ isolatedLevel }),
4870
+ createBrowserHoverTool({ isolatedLevel }),
4871
+ createBrowserGoBackTool({ isolatedLevel }),
4872
+ createBrowserGoForwardTool({ isolatedLevel }),
4873
+ createBrowserNewTabTool({ isolatedLevel }),
4874
+ createBrowserTabListTool({ isolatedLevel }),
4875
+ createBrowserSwitchTabTool({ isolatedLevel }),
4876
+ createBrowserCloseTabTool({ isolatedLevel }),
4877
+ createBrowserCloseTool({ isolatedLevel }),
4878
+ createBrowserPressKeyTool({ isolatedLevel }),
4879
+ createBrowserReadLinksTool({ isolatedLevel }),
4880
+ createBrowserGetClickableElementsTool({ isolatedLevel }),
4881
+ createBrowserGetDownloadListTool({ isolatedLevel }),
4882
+ createBrowserGetInfoTool({ isolatedLevel })
4883
+ ];
4884
+ return (0, import_langchain38.createMiddleware)({
4885
+ name: "browserMiddleware",
4886
+ contextSchema,
4887
+ tools
4888
+ });
4889
+ }
4890
+
4891
+ // src/middlewares/sqlMiddleware.ts
4892
+ var import_langchain39 = require("langchain");
4893
+ function createSqlMiddleware(params) {
4894
+ const { databaseKeys, databaseDescriptions } = params;
4895
+ if (!databaseKeys || databaseKeys.length === 0) {
4896
+ return (0, import_langchain39.createMiddleware)({
4897
+ name: "sqlMiddleware",
4898
+ tools: []
4859
4899
  });
4860
- this.baseURL = baseURL;
4861
- this.maxFileSizeBytes = maxFileSizeMb * 1024 * 1024;
4862
- this.workingDirectory = workingDirectory;
4863
- this.homeDir = "/home/gem";
4864
- }
4865
- resolvePath(virtualPath) {
4866
- return path2.join(this.homeDir, this.workingDirectory, virtualPath);
4867
4900
  }
4868
- /**
4869
- * Convert a real filesystem path to a virtual path.
4870
- *
4871
- * @param realPath - Real filesystem path
4872
- * @returns Virtual path starting with /
4873
- */
4874
- toVirtualPath(realPath) {
4875
- const rootPath = path2.join(this.homeDir, this.workingDirectory);
4876
- const relative4 = path2.relative(rootPath, realPath);
4877
- const normalized = relative4.split(path2.sep).join("/");
4878
- return "/" + normalized;
4901
+ const toolParams = {
4902
+ databaseKeys,
4903
+ databaseDescriptions
4904
+ };
4905
+ return (0, import_langchain39.createMiddleware)({
4906
+ name: "sqlMiddleware",
4907
+ contextSchema,
4908
+ tools: [
4909
+ createListTablesSqlTool(toolParams),
4910
+ createInfoSqlTool(toolParams),
4911
+ createQueryCheckerSqlTool(toolParams),
4912
+ createQuerySqlTool(toolParams)
4913
+ ]
4914
+ });
4915
+ }
4916
+
4917
+ // src/middlewares/skillMiddleware.ts
4918
+ var import_langchain43 = require("langchain");
4919
+
4920
+ // src/store_lattice/InMemoryThreadStore.ts
4921
+ var InMemoryThreadStore = class {
4922
+ constructor() {
4923
+ // Map<tenantId, Map<assistantId, Map<threadId, Thread>>>
4924
+ this.threads = /* @__PURE__ */ new Map();
4879
4925
  }
4880
4926
  /**
4881
- * List files and directories in the specified directory (non-recursive).
4882
- *
4883
- * @param dirPath - Virtual directory path (must start with /)
4884
- * @returns List of FileInfo objects for files and directories directly in the directory.
4885
- * Directories have a trailing / in their path and is_dir=true.
4927
+ * Get all threads for a specific tenant and assistant
4886
4928
  */
4887
- async lsInfo(dirPath) {
4888
- try {
4889
- const resolvedPath = this.resolvePath(dirPath);
4890
- const result = await this.sandbox.file.listPath({
4891
- path: resolvedPath,
4892
- recursive: false,
4893
- show_hidden: false,
4894
- max_depth: 0,
4895
- include_size: false,
4896
- include_permissions: false,
4897
- sort_by: "name",
4898
- sort_desc: false
4899
- });
4900
- if (!result.ok) {
4901
- throw result.error;
4902
- }
4903
- const files = result.body?.data?.files?.map((file) => ({
4904
- path: this.toVirtualPath(file.path),
4905
- is_dir: file.is_directory,
4906
- size: file.size,
4907
- modified_at: file.modified_time
4908
- })) || [];
4909
- return files;
4910
- } catch (e) {
4911
- console.error(`Error listing files in ${dirPath}:`, e);
4929
+ async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
4930
+ const tenantThreads = this.threads.get(tenantId);
4931
+ if (!tenantThreads) {
4932
+ return [];
4933
+ }
4934
+ const assistantThreads = tenantThreads.get(assistantId);
4935
+ if (!assistantThreads) {
4912
4936
  return [];
4913
4937
  }
4938
+ let threads = Array.from(assistantThreads.values());
4939
+ if (metadataFilter && Object.keys(metadataFilter).length > 0) {
4940
+ threads = threads.filter(
4941
+ (thread) => Object.entries(metadataFilter).every(
4942
+ ([key, value]) => thread.metadata?.[key] === value
4943
+ )
4944
+ );
4945
+ }
4946
+ return threads;
4914
4947
  }
4915
4948
  /**
4916
- * Read file content with line numbers.
4917
- *
4918
- * @param filePath - Virtual file path (must start with /)
4919
- * @param offset - Line offset to start reading from (0-indexed)
4920
- * @param limit - Maximum number of lines to read
4921
- * @returns Formatted file content with line numbers, or error message
4949
+ * Get a thread by ID for a specific tenant
4922
4950
  */
4923
- async read(filePath, offset = 0, limit = 1e4) {
4924
- try {
4925
- const resolvedPath = this.resolvePath(filePath);
4926
- let content;
4927
- const result = await this.sandbox.file.readFile({
4928
- file: resolvedPath,
4929
- start_line: offset,
4930
- end_line: limit
4931
- });
4932
- if (!result.ok) {
4933
- throw result.error;
4951
+ async getThreadById(tenantId, threadId) {
4952
+ const tenantThreads = this.threads.get(tenantId);
4953
+ if (!tenantThreads) {
4954
+ return void 0;
4955
+ }
4956
+ for (const assistantThreads of tenantThreads.values()) {
4957
+ const thread = assistantThreads.get(threadId);
4958
+ if (thread) {
4959
+ return thread;
4934
4960
  }
4935
- content = result.body?.data?.content || "";
4936
- return content;
4937
- } catch (e) {
4938
- return `Error: File '${filePath}' not found`;
4939
4961
  }
4962
+ return void 0;
4940
4963
  }
4941
4964
  /**
4942
- * Read file content as raw FileData.
4943
- *
4944
- * @param filePath - Virtual file path (must start with /)
4945
- * @returns Raw file content as FileData
4965
+ * Create a new thread for a tenant and assistant
4946
4966
  */
4947
- async readRaw(filePath) {
4948
- try {
4949
- const content = await this.read(filePath);
4950
- return {
4951
- content: content.split("\n"),
4952
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
4953
- modified_at: (/* @__PURE__ */ new Date()).toISOString()
4954
- };
4955
- } catch (e) {
4956
- throw new Error(`Error reading file '${filePath}': ${e.message}`);
4967
+ async createThread(tenantId, assistantId, threadId, data) {
4968
+ const now = /* @__PURE__ */ new Date();
4969
+ const thread = {
4970
+ id: threadId,
4971
+ tenantId,
4972
+ assistantId,
4973
+ metadata: data.metadata || {},
4974
+ createdAt: now,
4975
+ updatedAt: now
4976
+ };
4977
+ if (!this.threads.has(tenantId)) {
4978
+ this.threads.set(tenantId, /* @__PURE__ */ new Map());
4979
+ }
4980
+ const tenantThreads = this.threads.get(tenantId);
4981
+ if (!tenantThreads.has(assistantId)) {
4982
+ tenantThreads.set(assistantId, /* @__PURE__ */ new Map());
4957
4983
  }
4984
+ const assistantThreads = tenantThreads.get(assistantId);
4985
+ assistantThreads.set(threadId, thread);
4986
+ return thread;
4958
4987
  }
4959
4988
  /**
4960
- * Create a new file with content.
4961
- * Returns WriteResult. External storage sets filesUpdate=null.
4962
- *
4963
- * @param filePath - Virtual file path (must start with /)
4964
- * @param content - File content as string
4965
- * @returns WriteResult with error populated on failure
4989
+ * Update an existing thread
4966
4990
  */
4967
- async write(filePath, content) {
4968
- try {
4969
- const resolvedPath = this.resolvePath(filePath);
4970
- const result = await this.sandbox.file.writeFile({
4971
- file: resolvedPath,
4972
- content,
4973
- "encoding": "utf-8",
4974
- "append": false
4975
- // sudo: true
4976
- });
4977
- if (!result.ok) {
4978
- console.error(result.error);
4979
- throw result.error;
4991
+ async updateThread(tenantId, threadId, updates) {
4992
+ const tenantThreads = this.threads.get(tenantId);
4993
+ if (!tenantThreads) {
4994
+ return null;
4995
+ }
4996
+ for (const assistantThreads of tenantThreads.values()) {
4997
+ const existing = assistantThreads.get(threadId);
4998
+ if (existing) {
4999
+ const updated = {
5000
+ ...existing,
5001
+ metadata: {
5002
+ ...existing.metadata,
5003
+ ...updates.metadata || {}
5004
+ },
5005
+ updatedAt: /* @__PURE__ */ new Date()
5006
+ };
5007
+ assistantThreads.set(threadId, updated);
5008
+ return updated;
4980
5009
  }
4981
- return {
4982
- path: filePath,
4983
- filesUpdate: {
4984
- [filePath]: {
4985
- content: content.split("\n"),
4986
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
4987
- modified_at: (/* @__PURE__ */ new Date()).toISOString()
4988
- }
4989
- }
4990
- };
4991
- } catch (e) {
4992
- throw new Error(`Error writing file '${filePath}': ${e.message}`);
4993
5010
  }
5011
+ return null;
4994
5012
  }
4995
5013
  /**
4996
- * Edit a file by replacing string occurrences.
4997
- * Returns EditResult. External storage sets filesUpdate=null.
4998
- *
4999
- * @param filePath - Virtual file path (must start with /)
5000
- * @param oldString - String to find and replace
5001
- * @param newString - Replacement string
5002
- * @param replaceAll - If true, replace all occurrences (default: false)
5003
- * @returns EditResult with error, path, filesUpdate, and occurrences
5014
+ * Delete a thread by ID
5004
5015
  */
5005
- async edit(filePath, oldString, newString, replaceAll = false) {
5006
- try {
5007
- const resolvedPath = this.resolvePath(filePath);
5008
- const result = await this.sandbox.file.strReplaceEditor({
5009
- command: "str_replace",
5010
- path: resolvedPath,
5011
- old_str: oldString,
5012
- new_str: newString,
5013
- replace_mode: replaceAll ? "ALL" : "FIRST"
5014
- });
5015
- if (!result.ok) {
5016
- throw result.error;
5016
+ async deleteThread(tenantId, threadId) {
5017
+ const tenantThreads = this.threads.get(tenantId);
5018
+ if (!tenantThreads) {
5019
+ return false;
5020
+ }
5021
+ for (const assistantThreads of tenantThreads.values()) {
5022
+ if (assistantThreads.has(threadId)) {
5023
+ return assistantThreads.delete(threadId);
5017
5024
  }
5018
- return {
5019
- path: filePath,
5020
- filesUpdate: null
5021
- };
5022
- } catch (e) {
5023
- throw new Error(`Error editing file '${filePath}': ${e.message}`);
5024
5025
  }
5026
+ return false;
5025
5027
  }
5026
5028
  /**
5027
- * Structured search results or error string for invalid input.
5028
- *
5029
- * Searches file contents for a regex pattern within the sandbox.
5030
- *
5031
- * @param pattern - Regex pattern to search for
5032
- * @param searchPath - Base path to search from (default: "/")
5033
- * @param glob - Optional glob pattern to filter files (e.g., "*.py")
5034
- * @returns List of GrepMatch objects or error string for invalid regex
5029
+ * Check if thread exists
5035
5030
  */
5036
- async grepRaw(pattern, searchPath = "/", glob = null) {
5037
- let baseFull;
5038
- baseFull = this.resolvePath(searchPath || "/");
5039
- const result = await this.sandbox.file.findFiles({
5040
- path: baseFull,
5041
- glob: glob || "**/*"
5042
- });
5043
- if (!result.ok) {
5044
- throw result.error;
5031
+ async hasThread(tenantId, threadId) {
5032
+ const tenantThreads = this.threads.get(tenantId);
5033
+ if (!tenantThreads) {
5034
+ return false;
5045
5035
  }
5046
- const filePaths = result.body?.data?.files || [];
5047
- const matches = [];
5048
- for (const absolutePath of filePaths) {
5049
- const fileData = await this.sandbox.file.searchInFile({
5050
- file: absolutePath,
5051
- regex: pattern
5052
- });
5053
- if (!fileData.ok) {
5054
- continue;
5036
+ for (const assistantThreads of tenantThreads.values()) {
5037
+ if (assistantThreads.has(threadId)) {
5038
+ return true;
5055
5039
  }
5056
- const matchesData = fileData.body?.data?.matches || [];
5057
- const matchLines = fileData.body?.data?.line_numbers || [];
5058
- matchesData.forEach((match, index) => {
5059
- matches.push({
5060
- path: this.toVirtualPath(absolutePath),
5061
- line: matchLines[index],
5062
- text: match
5063
- });
5064
- });
5065
5040
  }
5066
- return matches;
5041
+ return false;
5067
5042
  }
5068
5043
  /**
5069
- * Structured glob matching returning FileInfo objects.
5070
- *
5071
- * @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
5072
- * @param searchPath - Base path to search from (default: "/")
5073
- * @returns List of FileInfo objects matching the pattern
5044
+ * Clear all threads for a tenant (useful for testing)
5074
5045
  */
5075
- async globInfo(pattern, searchPath = "/") {
5076
- if (pattern.startsWith("/")) {
5077
- pattern = pattern.substring(1);
5078
- }
5079
- const resolvedSearchPath = this.resolvePath(searchPath);
5080
- const result = await this.sandbox.file.findFiles({
5081
- path: resolvedSearchPath,
5082
- glob: pattern || "**/*"
5083
- });
5084
- if (!result.ok) {
5085
- throw result.error;
5046
+ clear(tenantId) {
5047
+ if (tenantId) {
5048
+ this.threads.delete(tenantId);
5049
+ } else {
5050
+ this.threads.clear();
5086
5051
  }
5087
- const results = [];
5088
- for (const filePath of result.body?.data?.files || []) {
5089
- const fileInfo = await this.sandbox.file.listPath({
5090
- path: filePath,
5091
- recursive: false,
5092
- show_hidden: false,
5093
- max_depth: 1,
5094
- include_size: false,
5095
- include_permissions: false
5096
- });
5097
- if (!fileInfo.ok) {
5098
- continue;
5052
+ }
5053
+ /**
5054
+ * Get all threads for all assistants (useful for debugging)
5055
+ */
5056
+ getAllThreads() {
5057
+ const allThreads = [];
5058
+ for (const tenantThreads of this.threads.values()) {
5059
+ for (const assistantThreads of tenantThreads.values()) {
5060
+ allThreads.push(...Array.from(assistantThreads.values()));
5099
5061
  }
5100
- results.push({
5101
- path: this.toVirtualPath(filePath),
5102
- is_dir: false,
5103
- size: fileInfo.body?.data?.files?.[0]?.size,
5104
- modified_at: fileInfo.body?.data?.files?.[0]?.modified_time
5105
- });
5106
5062
  }
5107
- return results;
5063
+ return allThreads;
5108
5064
  }
5109
5065
  };
5110
5066
 
5111
- // src/middlewares/codeEvalMiddleware.ts
5112
- var import_langchain37 = require("langchain");
5113
-
5114
- // src/middlewares/contextSchema.ts
5115
- var import_zod41 = __toESM(require("zod"));
5116
- var contextSchema = import_zod41.default.object({
5117
- runConfig: import_zod41.default.any()
5118
- });
5119
-
5120
- // src/middlewares/codeEvalMiddleware.ts
5121
- function createCodeEvalMiddleware(params = { isolatedLevel: "global" }) {
5122
- const codeEvalTool = createCodeEvalTool({ isolatedLevel: params.isolatedLevel });
5123
- const codeExecuteFileTool = createCodeExecuteFileTool({ isolatedLevel: params.isolatedLevel });
5124
- return (0, import_langchain37.createMiddleware)({
5125
- name: "codeEvalMiddleware",
5126
- contextSchema,
5127
- tools: [codeEvalTool, codeExecuteFileTool, getToolClient("convert_to_markdown")]
5128
- });
5129
- }
5130
-
5131
- // src/middlewares/browserMiddleware.ts
5132
- var import_langchain38 = require("langchain");
5133
- function createBrowserMiddleware(params = { isolatedLevel: "global" }) {
5134
- const isolatedLevel = params.isolatedLevel || "global";
5135
- const tools = [
5136
- createBrowserNavigateTool({ isolatedLevel }),
5137
- createBrowserClickTool({ isolatedLevel }),
5138
- createBrowserGetTextTool({ isolatedLevel }),
5139
- createBrowserGetMarkdownTool({ isolatedLevel }),
5140
- createBrowserEvaluateTool({ isolatedLevel }),
5141
- createBrowserScreenshotTool({ isolatedLevel }),
5142
- createBrowserScrollTool({ isolatedLevel }),
5143
- createBrowserFormInputFillTool({ isolatedLevel }),
5144
- createBrowserSelectTool({ isolatedLevel }),
5145
- createBrowserHoverTool({ isolatedLevel }),
5146
- createBrowserGoBackTool({ isolatedLevel }),
5147
- createBrowserGoForwardTool({ isolatedLevel }),
5148
- createBrowserNewTabTool({ isolatedLevel }),
5149
- createBrowserTabListTool({ isolatedLevel }),
5150
- createBrowserSwitchTabTool({ isolatedLevel }),
5151
- createBrowserCloseTabTool({ isolatedLevel }),
5152
- createBrowserCloseTool({ isolatedLevel }),
5153
- createBrowserPressKeyTool({ isolatedLevel }),
5154
- createBrowserReadLinksTool({ isolatedLevel }),
5155
- createBrowserGetClickableElementsTool({ isolatedLevel }),
5156
- createBrowserGetDownloadListTool({ isolatedLevel }),
5157
- createBrowserGetInfoTool({ isolatedLevel })
5158
- ];
5159
- return (0, import_langchain38.createMiddleware)({
5160
- name: "browserMiddleware",
5161
- contextSchema,
5162
- tools
5163
- });
5164
- }
5165
-
5166
- // src/middlewares/sqlMiddleware.ts
5167
- var import_langchain39 = require("langchain");
5168
- function createSqlMiddleware(params) {
5169
- const { databaseKeys, databaseDescriptions } = params;
5170
- if (!databaseKeys || databaseKeys.length === 0) {
5171
- return (0, import_langchain39.createMiddleware)({
5172
- name: "sqlMiddleware",
5173
- tools: []
5174
- });
5175
- }
5176
- const toolParams = {
5177
- databaseKeys,
5178
- databaseDescriptions
5179
- };
5180
- return (0, import_langchain39.createMiddleware)({
5181
- name: "sqlMiddleware",
5182
- contextSchema,
5183
- tools: [
5184
- createListTablesSqlTool(toolParams),
5185
- createInfoSqlTool(toolParams),
5186
- createQueryCheckerSqlTool(toolParams),
5187
- createQuerySqlTool(toolParams)
5188
- ]
5189
- });
5190
- }
5191
-
5192
- // src/middlewares/skillMiddleware.ts
5193
- var import_langchain43 = require("langchain");
5194
-
5195
- // src/store_lattice/InMemoryThreadStore.ts
5196
- var InMemoryThreadStore = class {
5067
+ // src/store_lattice/InMemoryAssistantStore.ts
5068
+ var InMemoryAssistantStore = class {
5197
5069
  constructor() {
5198
- // Map<tenantId, Map<assistantId, Map<threadId, Thread>>>
5199
- this.threads = /* @__PURE__ */ new Map();
5200
- }
5201
- /**
5202
- * Get all threads for a specific tenant and assistant
5203
- */
5204
- async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
5205
- const tenantThreads = this.threads.get(tenantId);
5206
- if (!tenantThreads) {
5207
- return [];
5208
- }
5209
- const assistantThreads = tenantThreads.get(assistantId);
5210
- if (!assistantThreads) {
5211
- return [];
5212
- }
5213
- let threads = Array.from(assistantThreads.values());
5214
- if (metadataFilter && Object.keys(metadataFilter).length > 0) {
5215
- threads = threads.filter(
5216
- (thread) => Object.entries(metadataFilter).every(
5217
- ([key, value]) => thread.metadata?.[key] === value
5218
- )
5219
- );
5220
- }
5221
- return threads;
5222
- }
5223
- /**
5224
- * Get a thread by ID for a specific tenant
5225
- */
5226
- async getThreadById(tenantId, threadId) {
5227
- const tenantThreads = this.threads.get(tenantId);
5228
- if (!tenantThreads) {
5229
- return void 0;
5230
- }
5231
- for (const assistantThreads of tenantThreads.values()) {
5232
- const thread = assistantThreads.get(threadId);
5233
- if (thread) {
5234
- return thread;
5235
- }
5236
- }
5237
- return void 0;
5238
- }
5239
- /**
5240
- * Create a new thread for a tenant and assistant
5241
- */
5242
- async createThread(tenantId, assistantId, threadId, data) {
5243
- const now = /* @__PURE__ */ new Date();
5244
- const thread = {
5245
- id: threadId,
5246
- tenantId,
5247
- assistantId,
5248
- metadata: data.metadata || {},
5249
- createdAt: now,
5250
- updatedAt: now
5251
- };
5252
- if (!this.threads.has(tenantId)) {
5253
- this.threads.set(tenantId, /* @__PURE__ */ new Map());
5254
- }
5255
- const tenantThreads = this.threads.get(tenantId);
5256
- if (!tenantThreads.has(assistantId)) {
5257
- tenantThreads.set(assistantId, /* @__PURE__ */ new Map());
5258
- }
5259
- const assistantThreads = tenantThreads.get(assistantId);
5260
- assistantThreads.set(threadId, thread);
5261
- return thread;
5262
- }
5263
- /**
5264
- * Update an existing thread
5265
- */
5266
- async updateThread(tenantId, threadId, updates) {
5267
- const tenantThreads = this.threads.get(tenantId);
5268
- if (!tenantThreads) {
5269
- return null;
5270
- }
5271
- for (const assistantThreads of tenantThreads.values()) {
5272
- const existing = assistantThreads.get(threadId);
5273
- if (existing) {
5274
- const updated = {
5275
- ...existing,
5276
- metadata: {
5277
- ...existing.metadata,
5278
- ...updates.metadata || {}
5279
- },
5280
- updatedAt: /* @__PURE__ */ new Date()
5281
- };
5282
- assistantThreads.set(threadId, updated);
5283
- return updated;
5284
- }
5285
- }
5286
- return null;
5287
- }
5288
- /**
5289
- * Delete a thread by ID
5290
- */
5291
- async deleteThread(tenantId, threadId) {
5292
- const tenantThreads = this.threads.get(tenantId);
5293
- if (!tenantThreads) {
5294
- return false;
5295
- }
5296
- for (const assistantThreads of tenantThreads.values()) {
5297
- if (assistantThreads.has(threadId)) {
5298
- return assistantThreads.delete(threadId);
5299
- }
5300
- }
5301
- return false;
5302
- }
5303
- /**
5304
- * Check if thread exists
5305
- */
5306
- async hasThread(tenantId, threadId) {
5307
- const tenantThreads = this.threads.get(tenantId);
5308
- if (!tenantThreads) {
5309
- return false;
5310
- }
5311
- for (const assistantThreads of tenantThreads.values()) {
5312
- if (assistantThreads.has(threadId)) {
5313
- return true;
5314
- }
5315
- }
5316
- return false;
5317
- }
5318
- /**
5319
- * Clear all threads for a tenant (useful for testing)
5320
- */
5321
- clear(tenantId) {
5322
- if (tenantId) {
5323
- this.threads.delete(tenantId);
5324
- } else {
5325
- this.threads.clear();
5326
- }
5327
- }
5328
- /**
5329
- * Get all threads for all assistants (useful for debugging)
5330
- */
5331
- getAllThreads() {
5332
- const allThreads = [];
5333
- for (const tenantThreads of this.threads.values()) {
5334
- for (const assistantThreads of tenantThreads.values()) {
5335
- allThreads.push(...Array.from(assistantThreads.values()));
5336
- }
5337
- }
5338
- return allThreads;
5339
- }
5340
- };
5341
-
5342
- // src/store_lattice/InMemoryAssistantStore.ts
5343
- var InMemoryAssistantStore = class {
5344
- constructor() {
5345
- this.assistants = /* @__PURE__ */ new Map();
5070
+ this.assistants = /* @__PURE__ */ new Map();
5346
5071
  }
5347
5072
  /**
5348
5073
  * Get all assistants for a tenant
@@ -5434,7 +5159,7 @@ var InMemoryAssistantStore = class {
5434
5159
 
5435
5160
  // src/store_lattice/FileSystemSkillStore.ts
5436
5161
  var fs = __toESM(require("fs/promises"));
5437
- var path3 = __toESM(require("path"));
5162
+ var path2 = __toESM(require("path"));
5438
5163
 
5439
5164
  // src/skill_lattice/skillNameValidator.ts
5440
5165
  var SKILL_NAME_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
@@ -5607,10 +5332,10 @@ var FileSystemSkillStore = class {
5607
5332
  constructor(options = {}) {
5608
5333
  const defaultPath = "lattice_store/skills";
5609
5334
  const providedPath = options.rootDir || defaultPath;
5610
- if (path3.isAbsolute(providedPath)) {
5335
+ if (path2.isAbsolute(providedPath)) {
5611
5336
  this.rootDir = providedPath;
5612
5337
  } else {
5613
- this.rootDir = path3.resolve(process.cwd(), providedPath);
5338
+ this.rootDir = path2.resolve(process.cwd(), providedPath);
5614
5339
  }
5615
5340
  this.ensureDirectoryExists().catch((error) => {
5616
5341
  console.error("Failed to initialize FileSystemSkillStore:", error);
@@ -5634,14 +5359,14 @@ var FileSystemSkillStore = class {
5634
5359
  if (name.includes("..") || name.includes("/") || name.includes("\\")) {
5635
5360
  throw new Error(`Invalid skill name: ${name} (contains invalid characters)`);
5636
5361
  }
5637
- return path3.join(this.rootDir, name);
5362
+ return path2.join(this.rootDir, name);
5638
5363
  }
5639
5364
  /**
5640
5365
  * Get file path for a skill name
5641
5366
  * File is always named SKILL.md inside the name directory
5642
5367
  */
5643
5368
  getSkillFilePath(name) {
5644
- return path3.join(this.getSkillDirectoryPath(name), "SKILL.md");
5369
+ return path2.join(this.getSkillDirectoryPath(name), "SKILL.md");
5645
5370
  }
5646
5371
  /**
5647
5372
  * Read skill from file
@@ -5928,14 +5653,14 @@ ${body}` : `${frontmatter}
5928
5653
  */
5929
5654
  async listSkillResources(_tenantId, skillName) {
5930
5655
  const skillDir = this.getSkillDirectoryPath(skillName);
5931
- const resourcesDir = path3.join(skillDir, "resources");
5656
+ const resourcesDir = path2.join(skillDir, "resources");
5932
5657
  try {
5933
5658
  const entries = await fs.readdir(resourcesDir, { withFileTypes: true, recursive: true });
5934
5659
  const resources = [];
5935
5660
  for (const entry of entries) {
5936
5661
  if (!entry.isDirectory()) {
5937
- const fullPath = path3.join(entry.path, entry.name);
5938
- const relativePath = path3.relative(resourcesDir, fullPath);
5662
+ const fullPath = path2.join(entry.path, entry.name);
5663
+ const relativePath = path2.relative(resourcesDir, fullPath);
5939
5664
  resources.push(relativePath.replace(/\\/g, "/"));
5940
5665
  }
5941
5666
  }
@@ -5956,10 +5681,10 @@ ${body}` : `${frontmatter}
5956
5681
  */
5957
5682
  async loadSkillResource(_tenantId, skillName, resourcePath) {
5958
5683
  const skillDir = this.getSkillDirectoryPath(skillName);
5959
- const resourcesDir = path3.join(skillDir, "resources");
5960
- const fullPath = path3.join(resourcesDir, resourcePath);
5961
- const resolvedPath = path3.resolve(fullPath);
5962
- const resolvedResourcesDir = path3.resolve(resourcesDir);
5684
+ const resourcesDir = path2.join(skillDir, "resources");
5685
+ const fullPath = path2.join(resourcesDir, resourcePath);
5686
+ const resolvedPath = path2.resolve(fullPath);
5687
+ const resolvedResourcesDir = path2.resolve(resourcesDir);
5963
5688
  if (!resolvedPath.startsWith(resolvedResourcesDir)) {
5964
5689
  throw new Error(`Invalid resource path: ${resourcePath}`);
5965
5690
  }
@@ -9495,22 +9220,19 @@ var import_langchain52 = require("langchain");
9495
9220
 
9496
9221
  // src/deep_agent_new/middleware/AGENTS_MD.ts
9497
9222
  var AGENTS_MD = `
9498
- # AGENTS.md - Your Workspace
9499
-
9500
- This folder is home. Treat it that way.
9501
9223
 
9502
9224
  ## First Run
9503
9225
 
9504
- If \`BOOTSTRAP.md\` exists, that's your birth certificate. Follow it, figure out who you are, then delete it. You won't need it again.
9226
+ If \`/agent/BOOTSTRAP.md\` exists, that's your birth certificate. Follow it, figure out who you are, then delete it. You won't need it again.
9505
9227
 
9506
9228
  ## Every Session
9507
9229
 
9508
9230
  Before doing anything else:
9509
9231
 
9510
- 1. Read \`SOUL.md\` \u2014 this is who you are
9511
- 2. Read \`USER.md\` \u2014 this is who you're helping
9232
+ 1. Read \`/agent/SOUL.md\` \u2014 this is who you are
9233
+ 2. Read \`/agent/USER.md\` \u2014 this is who you're helping
9512
9234
  3. Read \`memory/YYYY-MM-DD.md\` (today + yesterday) for recent context
9513
- 4. **If in MAIN SESSION** (direct chat with your human): Also read \`MEMORY.md\`
9235
+ 4. **If in MAIN SESSION** (direct chat with your human): Also read \`/agent/MEMORY.md\`
9514
9236
 
9515
9237
  Don't ask permission. Just do it.
9516
9238
 
@@ -9518,17 +9240,18 @@ Don't ask permission. Just do it.
9518
9240
 
9519
9241
  You wake up fresh each session. These files are your continuity:
9520
9242
 
9521
- - **Daily notes:** \`memory/YYYY-MM-DD.md\` (create \`memory/\` if needed) \u2014 raw logs of what happened
9522
- - **Long-term:** \`MEMORY.md\` \u2014 your curated memories, like a human's long-term memory
9243
+ - **agent Long-term:** \`/agent/MEMORY.md\` \u2014 your curated memories, like a human's long-term memory
9244
+ - **Project Memory**: \`/PROJECT.md\` - Loaded from project root if available - Project-specific instructions
9245
+ - **Daily Project notes:** \`/daily/YYYY-MM-DD.md\` (create \`daily/\` if needed) \u2014 raw logs of what happened
9523
9246
 
9524
9247
  Capture what matters. Decisions, context, things to remember. Skip the secrets unless asked to keep them.
9525
9248
 
9526
- ### \u{1F9E0} MEMORY.md - Your Long-Term Memory
9249
+ ### \u{1F9E0} /agent/MEMORY.md - Your Long-Term Memory
9527
9250
 
9528
9251
  - **ONLY load in main session** (direct chats with your human)
9529
9252
  - **DO NOT load in shared contexts** (Discord, group chats, sessions with other people)
9530
9253
  - This is for **security** \u2014 contains personal context that shouldn't leak to strangers
9531
- - You can **read, edit, and update** MEMORY.md freely in main sessions
9254
+ - You can **read, edit, and update** /agent/MEMORY.md freely in main sessions
9532
9255
  - Write significant events, thoughts, decisions, opinions, lessons learned
9533
9256
  - This is your curated memory \u2014 the distilled essence, not raw logs
9534
9257
  - Over time, review your daily files and update MEMORY.md with what's worth keeping
@@ -9537,11 +9260,42 @@ Capture what matters. Decisions, context, things to remember. Skip the secrets u
9537
9260
 
9538
9261
  - **Memory is limited** \u2014 if you want to remember something, WRITE IT TO A FILE
9539
9262
  - "Mental notes" don't survive session restarts. Files do.
9540
- - When someone says "remember this" \u2192 update \`memory/YYYY-MM-DD.md\` or relevant file
9541
- - When you learn a lesson \u2192 update AGENTS.md, TOOLS.md, or the relevant skill
9263
+ - When someone says "remember this" \u2192 update \`/daily/YYYY-MM-DD.md\` or relevant file
9264
+ - When you learn a lesson \u2192 update /agent/AGENTS.md, /agent/TOOLS.md, or the relevant skill
9542
9265
  - When you make a mistake \u2192 document it so future-you doesn't repeat it
9543
9266
  - **Text > Brain** \u{1F4DD}
9544
9267
 
9268
+ ### Project Memory File: \`/PROJECT.md\`
9269
+ \u2192 Describes **how this specific project works** and **how the agent should behave here only.**
9270
+
9271
+ **Store here:**
9272
+ - Project-specific architecture and design patterns
9273
+ - Coding conventions specific to this codebase
9274
+ - Project structure and organization
9275
+ - Testing strategies for this project
9276
+ - Deployment processes and workflows
9277
+ - Team conventions and guidelines
9278
+
9279
+ **Examples:**
9280
+ - "This project uses FastAPI with SQLAlchemy"
9281
+ - "Tests go in tests/ directory mirroring src/ structure"
9282
+ - "All API changes require updating OpenAPI spec"
9283
+
9284
+ ### Project Memory Files: \`{project_deepagents_dir}/*.md\`
9285
+ \u2192 Use for **project-specific reference information** and structured notes.
9286
+
9287
+ **Store here:**
9288
+ - API design documentation
9289
+ - Architecture decisions and rationale
9290
+ - Deployment procedures
9291
+ - Common debugging patterns
9292
+ - Onboarding information
9293
+
9294
+ **Examples:**
9295
+ - \`{project_deepagents_dir}/api-design.md\` - REST API patterns used
9296
+ - \`{project_deepagents_dir}/architecture.md\` - System architecture overview
9297
+ - \`{project_deepagents_dir}/deployment.md\` - How to deploy this project
9298
+
9545
9299
  ## Safety
9546
9300
 
9547
9301
  - Don't exfiltrate private data. Ever.
@@ -9713,10 +9467,10 @@ Offer suggestions if they're stuck. Have fun with it.
9713
9467
 
9714
9468
  Update these files with what you learned:
9715
9469
 
9716
- - \`IDENTITY.md\` \u2014 your name, creature, vibe, emoji
9717
- - \`USER.md\` \u2014 their name, how to address them, timezone, notes
9470
+ - \`/agent/IDENTITY.md\` \u2014 your name, creature, vibe, emoji
9471
+ - \`/agent/USER.md\` \u2014 their name, how to address them, timezone, notes
9718
9472
 
9719
- Then open \`SOUL.md\` together and talk about:
9473
+ Then open \`/agent/SOUL.md\` together and talk about:
9720
9474
 
9721
9475
  - What matters to them
9722
9476
  - How they want you to behave
@@ -9849,12 +9603,12 @@ async function getBackend2(backend, stateAndStore) {
9849
9603
  return backend;
9850
9604
  }
9851
9605
  var BOOTSTRAP_FILE_NAMES = {
9852
- agents: "AGENTS.md",
9853
- soul: "SOUL.md",
9854
- identity: "IDENTITY.md",
9855
- user: "USER.md",
9856
- tools: "TOOLS.md",
9857
- bootstrap: "BOOTSTRAP.md"
9606
+ agents: "/agent/AGENTS.md",
9607
+ soul: "/agent/SOUL.md",
9608
+ identity: "/agent/IDENTITY.md",
9609
+ user: "/agent/USER.md",
9610
+ tools: "/agent/TOOLS.md",
9611
+ bootstrap: "/agent/BOOTSTRAP.md"
9858
9612
  };
9859
9613
  var BOOTSTRAP_SECTION_HEADERS = {
9860
9614
  agents: "## Operating Instructions",
@@ -9877,14 +9631,14 @@ Document available tools and their usage notes here.`,
9877
9631
  async function createBootstrapFiles(config, backend, stateAndStore) {
9878
9632
  const resolvedBackend = await getBackend2(backend, stateAndStore);
9879
9633
  try {
9880
- const agentsContent = await resolvedBackend.read("/AGENTS.md", 0, 1);
9634
+ const agentsContent = await resolvedBackend.read("/agent/AGENTS.md", 0, 1);
9881
9635
  if (!agentsContent.includes("Error:")) {
9882
9636
  return;
9883
9637
  }
9884
9638
  } catch (error) {
9885
9639
  }
9886
9640
  for (const [key, filename] of Object.entries(BOOTSTRAP_FILE_NAMES)) {
9887
- const filePath = "/" + filename;
9641
+ const filePath = filename;
9888
9642
  try {
9889
9643
  const content = config[key] || DEFAULT_BOOTSTRAP_CONTENT[key];
9890
9644
  await resolvedBackend.write(filePath, content);
@@ -9898,7 +9652,7 @@ async function buildBootstrapPromptSections(backend, stateAndStore) {
9898
9652
  const sections = [];
9899
9653
  const fileOrder = ["agents", "soul", "identity", "user", "tools", "bootstrap"];
9900
9654
  for (const key of fileOrder) {
9901
- const filePath = "/" + BOOTSTRAP_FILE_NAMES[key];
9655
+ const filePath = BOOTSTRAP_FILE_NAMES[key];
9902
9656
  try {
9903
9657
  const content = await resolvedBackend.read(filePath);
9904
9658
  if (content && !content.includes("Error:") && content.trim()) {
@@ -9934,14 +9688,13 @@ function createClawMiddleware(options = {}) {
9934
9688
  if (injectBootstrapFiles && backend) {
9935
9689
  const stateAndStore = {
9936
9690
  state: request.state || {},
9937
- store: request.store
9691
+ store: request.store,
9692
+ ...request.runtime.context.runConfig
9938
9693
  };
9939
9694
  const bootstrapSections = await buildBootstrapPromptSections(backend, stateAndStore);
9940
9695
  if (bootstrapSections.length > 0) {
9941
9696
  const bootstrapContext = `
9942
9697
 
9943
-
9944
-
9945
9698
  ${bootstrapSections.join("\n\n")}
9946
9699
 
9947
9700
  `;
@@ -10143,14 +9896,18 @@ ${currentSystemPrompt}` : dateContext;
10143
9896
  }
10144
9897
 
10145
9898
  // src/agent_lattice/builders/commonMiddleware.ts
10146
- async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
9899
+ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
10147
9900
  const middlewares = [];
10148
9901
  middlewares.push(createUnknownToolHandlerMiddleware());
10149
9902
  middlewares.push(createModelSelectorMiddleware());
10150
9903
  const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
10151
- if (filesystemConfig?.enabled && filesystemBackend) {
10152
- const options = { backend: filesystemBackend };
10153
- middlewares.push(createFilesystemMiddleware(options));
9904
+ const clawConfig = middlewareConfigs.find((m) => m.type === "claw");
9905
+ const needsFilesystemBackend = filesystemConfig?.enabled || clawConfig?.enabled;
9906
+ if (needsFilesystemBackend && filesystemBackend) {
9907
+ if (!fsIsExised) {
9908
+ const options = { backend: filesystemBackend };
9909
+ middlewares.push(createFilesystemMiddleware(options));
9910
+ }
10154
9911
  }
10155
9912
  for (const config of middlewareConfigs) {
10156
9913
  if (!config.enabled || config.type === "filesystem") continue;
@@ -10198,12 +9955,14 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
10198
9955
  break;
10199
9956
  case "claw":
10200
9957
  if (filesystemBackend) {
10201
- const clawConfig = config.config;
9958
+ const clawMiddlewareConfig = config.config;
10202
9959
  middlewares.push(createClawMiddleware({
10203
9960
  backend: filesystemBackend,
10204
- injectBootstrapFiles: clawConfig.injectBootstrapFiles ?? true,
10205
- bootstrapFiles: clawConfig.bootstrapFiles ?? {}
9961
+ injectBootstrapFiles: clawMiddlewareConfig.injectBootstrapFiles ?? true,
9962
+ bootstrapFiles: clawMiddlewareConfig.bootstrapFiles ?? {}
10206
9963
  }));
9964
+ } else {
9965
+ console.warn("[claw middleware] Filesystem backend not available. Claw middleware requires filesystem backend to function.");
10207
9966
  }
10208
9967
  break;
10209
9968
  case "date":
@@ -10211,45 +9970,516 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
10211
9970
  break;
10212
9971
  }
10213
9972
  }
10214
- return middlewares;
10215
- }
9973
+ return middlewares;
9974
+ }
9975
+
9976
+ // src/deep_agent_new/backends/sandboxFiles.ts
9977
+ var import_sandbox2 = require("@agent-infra/sandbox");
9978
+ var path3 = __toESM(require("path"));
9979
+ var SandboxFilesystem = class {
9980
+ /**
9981
+ * Create a new SandboxFilesystem instance.
9982
+ *
9983
+ * @param options - Configuration options
9984
+ * @param options.baseURL - Base URL of the sandbox service (default: 'http://localhost:8080')
9985
+ * @param options.maxFileSizeMb - Maximum file size in MB (default: 10)
9986
+ * @param options.sandboxInstance - Optional Sandbox instance (if provided, baseURL is ignored)
9987
+ */
9988
+ constructor(options = {}) {
9989
+ const {
9990
+ baseURL = "http://localhost:8080",
9991
+ workingDirectory = "/",
9992
+ maxFileSizeMb = 10,
9993
+ sandboxInstance
9994
+ } = options;
9995
+ this.sandbox = sandboxInstance || new import_sandbox2.SandboxClient({ baseUrl: baseURL, environment: "" });
9996
+ this.sandbox.mcp.listMcpServers().then((servers) => {
9997
+ });
9998
+ this.sandbox.mcp.listMcpTools("browser").then((tools) => {
9999
+ });
10000
+ this.baseURL = baseURL;
10001
+ this.maxFileSizeBytes = maxFileSizeMb * 1024 * 1024;
10002
+ this.workingDirectory = workingDirectory;
10003
+ this.homeDir = "/home/gem";
10004
+ }
10005
+ resolvePath(virtualPath) {
10006
+ return path3.join(this.homeDir, this.workingDirectory, virtualPath);
10007
+ }
10008
+ /**
10009
+ * Convert a real filesystem path to a virtual path.
10010
+ *
10011
+ * @param realPath - Real filesystem path
10012
+ * @returns Virtual path starting with /
10013
+ */
10014
+ toVirtualPath(realPath) {
10015
+ const rootPath = path3.join(this.homeDir, this.workingDirectory);
10016
+ const relative4 = path3.relative(rootPath, realPath);
10017
+ const normalized = relative4.split(path3.sep).join("/");
10018
+ return "/" + normalized;
10019
+ }
10020
+ /**
10021
+ * List files and directories in the specified directory (non-recursive).
10022
+ *
10023
+ * @param dirPath - Virtual directory path (must start with /)
10024
+ * @returns List of FileInfo objects for files and directories directly in the directory.
10025
+ * Directories have a trailing / in their path and is_dir=true.
10026
+ */
10027
+ async lsInfo(dirPath) {
10028
+ try {
10029
+ const resolvedPath = this.resolvePath(dirPath);
10030
+ const result = await this.sandbox.file.listPath({
10031
+ path: resolvedPath,
10032
+ recursive: false,
10033
+ show_hidden: false,
10034
+ max_depth: 0,
10035
+ include_size: false,
10036
+ include_permissions: false,
10037
+ sort_by: "name",
10038
+ sort_desc: false
10039
+ });
10040
+ if (!result.ok) {
10041
+ throw result.error;
10042
+ }
10043
+ const files = result.body?.data?.files?.map((file) => ({
10044
+ path: this.toVirtualPath(file.path),
10045
+ is_dir: file.is_directory,
10046
+ size: file.size,
10047
+ modified_at: file.modified_time
10048
+ })) || [];
10049
+ return files;
10050
+ } catch (e) {
10051
+ console.error(`Error listing files in ${dirPath}:`, e);
10052
+ return [];
10053
+ }
10054
+ }
10055
+ /**
10056
+ * Read file content with line numbers.
10057
+ *
10058
+ * @param filePath - Virtual file path (must start with /)
10059
+ * @param offset - Line offset to start reading from (0-indexed)
10060
+ * @param limit - Maximum number of lines to read
10061
+ * @returns Formatted file content with line numbers, or error message
10062
+ */
10063
+ async read(filePath, offset = 0, limit = 1e4) {
10064
+ try {
10065
+ const resolvedPath = this.resolvePath(filePath);
10066
+ let content;
10067
+ const result = await this.sandbox.file.readFile({
10068
+ file: resolvedPath,
10069
+ start_line: offset,
10070
+ end_line: limit
10071
+ });
10072
+ if (!result.ok) {
10073
+ throw result.error;
10074
+ }
10075
+ content = result.body?.data?.content || "";
10076
+ return content;
10077
+ } catch (e) {
10078
+ return `Error: File '${filePath}' not found`;
10079
+ }
10080
+ }
10081
+ /**
10082
+ * Read file content as raw FileData.
10083
+ *
10084
+ * @param filePath - Virtual file path (must start with /)
10085
+ * @returns Raw file content as FileData
10086
+ */
10087
+ async readRaw(filePath) {
10088
+ try {
10089
+ const content = await this.read(filePath);
10090
+ return {
10091
+ content: content.split("\n"),
10092
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
10093
+ modified_at: (/* @__PURE__ */ new Date()).toISOString()
10094
+ };
10095
+ } catch (e) {
10096
+ throw new Error(`Error reading file '${filePath}': ${e.message}`);
10097
+ }
10098
+ }
10099
+ /**
10100
+ * Create a new file with content.
10101
+ * Returns WriteResult. External storage sets filesUpdate=null.
10102
+ *
10103
+ * @param filePath - Virtual file path (must start with /)
10104
+ * @param content - File content as string
10105
+ * @returns WriteResult with error populated on failure
10106
+ */
10107
+ async write(filePath, content) {
10108
+ try {
10109
+ const resolvedPath = this.resolvePath(filePath);
10110
+ const result = await this.sandbox.file.writeFile({
10111
+ file: resolvedPath,
10112
+ content,
10113
+ "encoding": "utf-8",
10114
+ "append": false
10115
+ // sudo: true
10116
+ });
10117
+ if (!result.ok) {
10118
+ console.error(result.error);
10119
+ throw result.error;
10120
+ }
10121
+ return {
10122
+ path: filePath,
10123
+ filesUpdate: {
10124
+ [filePath]: {
10125
+ content: content.split("\n"),
10126
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
10127
+ modified_at: (/* @__PURE__ */ new Date()).toISOString()
10128
+ }
10129
+ }
10130
+ };
10131
+ } catch (e) {
10132
+ throw new Error(`Error writing file '${filePath}': ${e.message}`);
10133
+ }
10134
+ }
10135
+ /**
10136
+ * Edit a file by replacing string occurrences.
10137
+ * Returns EditResult. External storage sets filesUpdate=null.
10138
+ *
10139
+ * @param filePath - Virtual file path (must start with /)
10140
+ * @param oldString - String to find and replace
10141
+ * @param newString - Replacement string
10142
+ * @param replaceAll - If true, replace all occurrences (default: false)
10143
+ * @returns EditResult with error, path, filesUpdate, and occurrences
10144
+ */
10145
+ async edit(filePath, oldString, newString, replaceAll = false) {
10146
+ try {
10147
+ const resolvedPath = this.resolvePath(filePath);
10148
+ const result = await this.sandbox.file.strReplaceEditor({
10149
+ command: "str_replace",
10150
+ path: resolvedPath,
10151
+ old_str: oldString,
10152
+ new_str: newString,
10153
+ replace_mode: replaceAll ? "ALL" : "FIRST"
10154
+ });
10155
+ if (!result.ok) {
10156
+ throw result.error;
10157
+ }
10158
+ return {
10159
+ path: filePath,
10160
+ filesUpdate: null
10161
+ };
10162
+ } catch (e) {
10163
+ throw new Error(`Error editing file '${filePath}': ${e.message}`);
10164
+ }
10165
+ }
10166
+ /**
10167
+ * Structured search results or error string for invalid input.
10168
+ *
10169
+ * Searches file contents for a regex pattern within the sandbox.
10170
+ *
10171
+ * @param pattern - Regex pattern to search for
10172
+ * @param searchPath - Base path to search from (default: "/")
10173
+ * @param glob - Optional glob pattern to filter files (e.g., "*.py")
10174
+ * @returns List of GrepMatch objects or error string for invalid regex
10175
+ */
10176
+ async grepRaw(pattern, searchPath = "/", glob = null) {
10177
+ let baseFull;
10178
+ baseFull = this.resolvePath(searchPath || "/");
10179
+ const result = await this.sandbox.file.findFiles({
10180
+ path: baseFull,
10181
+ glob: glob || "**/*"
10182
+ });
10183
+ if (!result.ok) {
10184
+ throw result.error;
10185
+ }
10186
+ const filePaths = result.body?.data?.files || [];
10187
+ const matches = [];
10188
+ for (const absolutePath of filePaths) {
10189
+ const fileData = await this.sandbox.file.searchInFile({
10190
+ file: absolutePath,
10191
+ regex: pattern
10192
+ });
10193
+ if (!fileData.ok) {
10194
+ continue;
10195
+ }
10196
+ const matchesData = fileData.body?.data?.matches || [];
10197
+ const matchLines = fileData.body?.data?.line_numbers || [];
10198
+ matchesData.forEach((match, index) => {
10199
+ matches.push({
10200
+ path: this.toVirtualPath(absolutePath),
10201
+ line: matchLines[index],
10202
+ text: match
10203
+ });
10204
+ });
10205
+ }
10206
+ return matches;
10207
+ }
10208
+ /**
10209
+ * Structured glob matching returning FileInfo objects.
10210
+ *
10211
+ * @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
10212
+ * @param searchPath - Base path to search from (default: "/")
10213
+ * @returns List of FileInfo objects matching the pattern
10214
+ */
10215
+ async globInfo(pattern, searchPath = "/") {
10216
+ if (pattern.startsWith("/")) {
10217
+ pattern = pattern.substring(1);
10218
+ }
10219
+ const resolvedSearchPath = this.resolvePath(searchPath);
10220
+ const result = await this.sandbox.file.findFiles({
10221
+ path: resolvedSearchPath,
10222
+ glob: pattern || "**/*"
10223
+ });
10224
+ if (!result.ok) {
10225
+ throw result.error;
10226
+ }
10227
+ const results = [];
10228
+ for (const filePath of result.body?.data?.files || []) {
10229
+ const fileInfo = await this.sandbox.file.listPath({
10230
+ path: filePath,
10231
+ recursive: false,
10232
+ show_hidden: false,
10233
+ max_depth: 1,
10234
+ include_size: false,
10235
+ include_permissions: false
10236
+ });
10237
+ if (!fileInfo.ok) {
10238
+ continue;
10239
+ }
10240
+ results.push({
10241
+ path: this.toVirtualPath(filePath),
10242
+ is_dir: false,
10243
+ size: fileInfo.body?.data?.files?.[0]?.size,
10244
+ modified_at: fileInfo.body?.data?.files?.[0]?.modified_time
10245
+ });
10246
+ }
10247
+ return results;
10248
+ }
10249
+ };
10250
+
10251
+ // src/deep_agent_new/backends/composite.ts
10252
+ var CompositeBackend = class {
10253
+ constructor(defaultBackend, routes) {
10254
+ this.default = defaultBackend;
10255
+ this.routes = routes;
10256
+ this.sortedRoutes = Object.entries(routes).sort(
10257
+ (a, b) => b[0].length - a[0].length
10258
+ );
10259
+ }
10260
+ /**
10261
+ * Determine which backend handles this key and strip prefix.
10262
+ *
10263
+ * @param key - Original file path
10264
+ * @returns Tuple of [backend, stripped_key] where stripped_key has the route
10265
+ * prefix removed (but keeps leading slash).
10266
+ */
10267
+ getBackendAndKey(key) {
10268
+ for (const [prefix, backend] of this.sortedRoutes) {
10269
+ if (key.startsWith(prefix)) {
10270
+ const suffix = key.substring(prefix.length);
10271
+ const strippedKey = suffix ? "/" + suffix : "/";
10272
+ return [backend, strippedKey];
10273
+ }
10274
+ }
10275
+ return [this.default, key];
10276
+ }
10277
+ /**
10278
+ * List files and directories in the specified directory (non-recursive).
10279
+ *
10280
+ * @param path - Absolute path to directory
10281
+ * @returns List of FileInfo objects with route prefixes added, for files and directories
10282
+ * directly in the directory. Directories have a trailing / in their path and is_dir=true.
10283
+ */
10284
+ async lsInfo(path5) {
10285
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10286
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10287
+ const suffix = path5.substring(routePrefix.length);
10288
+ const searchPath = suffix ? "/" + suffix : "/";
10289
+ const infos = await backend.lsInfo(searchPath);
10290
+ const prefixed = [];
10291
+ for (const fi of infos) {
10292
+ prefixed.push({
10293
+ ...fi,
10294
+ path: routePrefix.slice(0, -1) + fi.path
10295
+ });
10296
+ }
10297
+ return prefixed;
10298
+ }
10299
+ }
10300
+ if (path5 === "/") {
10301
+ const results = [];
10302
+ const defaultInfos = await this.default.lsInfo(path5);
10303
+ results.push(...defaultInfos);
10304
+ for (const [routePrefix] of this.sortedRoutes) {
10305
+ results.push({
10306
+ path: routePrefix,
10307
+ is_dir: true,
10308
+ size: 0,
10309
+ modified_at: ""
10310
+ });
10311
+ }
10312
+ results.sort((a, b) => a.path.localeCompare(b.path));
10313
+ return results;
10314
+ }
10315
+ return await this.default.lsInfo(path5);
10316
+ }
10317
+ /**
10318
+ * Read file content, routing to appropriate backend.
10319
+ *
10320
+ * @param filePath - Absolute file path
10321
+ * @param offset - Line offset to start reading from (0-indexed)
10322
+ * @param limit - Maximum number of lines to read
10323
+ * @returns Formatted file content with line numbers, or error message
10324
+ */
10325
+ async read(filePath, offset = 0, limit = 2e3) {
10326
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10327
+ return await backend.read(strippedKey, offset, limit);
10328
+ }
10329
+ /**
10330
+ * Read file content as raw FileData.
10331
+ *
10332
+ * @param filePath - Absolute file path
10333
+ * @returns Raw file content as FileData
10334
+ */
10335
+ async readRaw(filePath) {
10336
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10337
+ return await backend.readRaw(strippedKey);
10338
+ }
10339
+ /**
10340
+ * Structured search results or error string for invalid input.
10341
+ */
10342
+ async grepRaw(pattern, path5 = "/", glob = null) {
10343
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10344
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10345
+ const searchPath = path5.substring(routePrefix.length - 1);
10346
+ const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
10347
+ if (typeof raw === "string") {
10348
+ return raw;
10349
+ }
10350
+ return raw.map((m) => ({
10351
+ ...m,
10352
+ path: routePrefix.slice(0, -1) + m.path
10353
+ }));
10354
+ }
10355
+ }
10356
+ const allMatches = [];
10357
+ const rawDefault = await this.default.grepRaw(pattern, path5, glob);
10358
+ if (typeof rawDefault === "string") {
10359
+ return rawDefault;
10360
+ }
10361
+ allMatches.push(...rawDefault);
10362
+ for (const [routePrefix, backend] of Object.entries(this.routes)) {
10363
+ const raw = await backend.grepRaw(pattern, "/", glob);
10364
+ if (typeof raw === "string") {
10365
+ return raw;
10366
+ }
10367
+ allMatches.push(
10368
+ ...raw.map((m) => ({
10369
+ ...m,
10370
+ path: routePrefix.slice(0, -1) + m.path
10371
+ }))
10372
+ );
10373
+ }
10374
+ return allMatches;
10375
+ }
10376
+ /**
10377
+ * Structured glob matching returning FileInfo objects.
10378
+ */
10379
+ async globInfo(pattern, path5 = "/") {
10380
+ const results = [];
10381
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10382
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10383
+ const searchPath = path5.substring(routePrefix.length - 1);
10384
+ const infos = await backend.globInfo(pattern, searchPath || "/");
10385
+ return infos.map((fi) => ({
10386
+ ...fi,
10387
+ path: routePrefix.slice(0, -1) + fi.path
10388
+ }));
10389
+ }
10390
+ }
10391
+ const defaultInfos = await this.default.globInfo(pattern, path5);
10392
+ results.push(...defaultInfos);
10393
+ for (const [routePrefix, backend] of Object.entries(this.routes)) {
10394
+ const infos = await backend.globInfo(pattern, "/");
10395
+ results.push(
10396
+ ...infos.map((fi) => ({
10397
+ ...fi,
10398
+ path: routePrefix.slice(0, -1) + fi.path
10399
+ }))
10400
+ );
10401
+ }
10402
+ results.sort((a, b) => a.path.localeCompare(b.path));
10403
+ return results;
10404
+ }
10405
+ /**
10406
+ * Create a new file, routing to appropriate backend.
10407
+ *
10408
+ * @param filePath - Absolute file path
10409
+ * @param content - File content as string
10410
+ * @returns WriteResult with path or error
10411
+ */
10412
+ async write(filePath, content) {
10413
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10414
+ return await backend.write(strippedKey, content);
10415
+ }
10416
+ /**
10417
+ * Edit a file, routing to appropriate backend.
10418
+ *
10419
+ * @param filePath - Absolute file path
10420
+ * @param oldString - String to find and replace
10421
+ * @param newString - Replacement string
10422
+ * @param replaceAll - If true, replace all occurrences
10423
+ * @returns EditResult with path, occurrences, or error
10424
+ */
10425
+ async edit(filePath, oldString, newString, replaceAll = false) {
10426
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10427
+ return await backend.edit(strippedKey, oldString, newString, replaceAll);
10428
+ }
10429
+ };
10216
10430
 
10217
- // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
10218
- var ReActAgentGraphBuilder = class {
10219
- createFilesystemBackendFactory(middlewareConfigs, agentLattice) {
10220
- const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
10221
- if (!filesystemConfig || !filesystemConfig.enabled) {
10222
- return void 0;
10431
+ // src/agent_lattice/builders/filesystemBackend.ts
10432
+ function createFilesystemBackendFactory(middlewareConfigs, defualtRootLevel = "project", routesLevelConfig = {
10433
+ "/agent/": "agent"
10434
+ //默认配置 agent目录就是agent级别的
10435
+ }) {
10436
+ const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
10437
+ if (!filesystemConfig || !filesystemConfig.enabled) {
10438
+ return void 0;
10439
+ }
10440
+ const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
10441
+ return async (stateAndStore) => {
10442
+ const { tenantId, workspaceId, projectId, assistant_id } = stateAndStore;
10443
+ let sandboxName = "global";
10444
+ if (isolatedLevel === "agent") {
10445
+ sandboxName = "agent";
10446
+ } else if (isolatedLevel === "thread") {
10447
+ sandboxName = "thread";
10223
10448
  }
10224
- const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
10225
- const agentTenantId = agentLattice.config.tenantId;
10226
- return async (stateAndStore) => {
10227
- const { tenantId: runtimeTenantId, workspaceId, projectId } = stateAndStore;
10228
- const tenantId = runtimeTenantId || agentTenantId;
10229
- let sandboxName = "global";
10230
- if (isolatedLevel === "agent") {
10231
- sandboxName = "agent";
10232
- } else if (isolatedLevel === "thread") {
10233
- sandboxName = "thread";
10234
- }
10235
- const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
10236
- if (!sandboxManager) {
10237
- throw new Error("Sandbox manager not found");
10238
- }
10239
- let workingDirectory = "/";
10240
- if (workspaceId && projectId) {
10241
- if (tenantId) {
10242
- workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
10243
- } else {
10244
- workingDirectory = `/${workspaceId}/${projectId}`;
10245
- }
10449
+ const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
10450
+ if (!sandboxManager) {
10451
+ throw new Error("Sandbox manager not found");
10452
+ }
10453
+ const getWS = (rootLevel) => {
10454
+ let workingDirectory = `/tenants/${tenantId}`;
10455
+ if (assistant_id && rootLevel === "agent") {
10456
+ workingDirectory = `/tenants/${tenantId}/agents/${assistant_id}`;
10457
+ } else if (workspaceId && projectId && rootLevel === "project") {
10458
+ workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
10246
10459
  }
10247
- return new SandboxFilesystem({
10248
- sandboxInstance: await sandboxManager.createSandbox(sandboxName),
10249
- workingDirectory
10250
- });
10460
+ return workingDirectory;
10251
10461
  };
10252
- }
10462
+ const sandboxInstance = await sandboxManager.createSandbox(sandboxName);
10463
+ const sandboxfs = new SandboxFilesystem({
10464
+ sandboxInstance,
10465
+ workingDirectory: getWS(defualtRootLevel)
10466
+ });
10467
+ const routers = Object.keys(routesLevelConfig).reduce((pre, curr) => ({
10468
+ ...pre,
10469
+ [curr]: new SandboxFilesystem({
10470
+ sandboxInstance,
10471
+ workingDirectory: getWS(routesLevelConfig[curr])
10472
+ })
10473
+ }), {});
10474
+ const compositeBackend = new CompositeBackend(sandboxfs, {
10475
+ ...routers
10476
+ });
10477
+ return compositeBackend;
10478
+ };
10479
+ }
10480
+
10481
+ // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
10482
+ var ReActAgentGraphBuilder = class {
10253
10483
  async createMiddlewares(middlewareConfigs) {
10254
10484
  return await createCommonMiddlewares(middlewareConfigs);
10255
10485
  }
@@ -10267,7 +10497,7 @@ var ReActAgentGraphBuilder = class {
10267
10497
  }).filter((tool51) => tool51 !== void 0);
10268
10498
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
10269
10499
  const middlewareConfigs = params.middleware || [];
10270
- const filesystemBackend = this.createFilesystemBackendFactory(middlewareConfigs, agentLattice);
10500
+ const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
10271
10501
  const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend);
10272
10502
  return (0, import_langchain55.createAgent)({
10273
10503
  model: params.model,
@@ -11893,186 +12123,6 @@ var FilesystemBackend = class {
11893
12123
  }
11894
12124
  };
11895
12125
 
11896
- // src/deep_agent_new/backends/composite.ts
11897
- var CompositeBackend = class {
11898
- constructor(defaultBackend, routes) {
11899
- this.default = defaultBackend;
11900
- this.routes = routes;
11901
- this.sortedRoutes = Object.entries(routes).sort(
11902
- (a, b) => b[0].length - a[0].length
11903
- );
11904
- }
11905
- /**
11906
- * Determine which backend handles this key and strip prefix.
11907
- *
11908
- * @param key - Original file path
11909
- * @returns Tuple of [backend, stripped_key] where stripped_key has the route
11910
- * prefix removed (but keeps leading slash).
11911
- */
11912
- getBackendAndKey(key) {
11913
- for (const [prefix, backend] of this.sortedRoutes) {
11914
- if (key.startsWith(prefix)) {
11915
- const suffix = key.substring(prefix.length);
11916
- const strippedKey = suffix ? "/" + suffix : "/";
11917
- return [backend, strippedKey];
11918
- }
11919
- }
11920
- return [this.default, key];
11921
- }
11922
- /**
11923
- * List files and directories in the specified directory (non-recursive).
11924
- *
11925
- * @param path - Absolute path to directory
11926
- * @returns List of FileInfo objects with route prefixes added, for files and directories
11927
- * directly in the directory. Directories have a trailing / in their path and is_dir=true.
11928
- */
11929
- async lsInfo(path5) {
11930
- for (const [routePrefix, backend] of this.sortedRoutes) {
11931
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11932
- const suffix = path5.substring(routePrefix.length);
11933
- const searchPath = suffix ? "/" + suffix : "/";
11934
- const infos = await backend.lsInfo(searchPath);
11935
- const prefixed = [];
11936
- for (const fi of infos) {
11937
- prefixed.push({
11938
- ...fi,
11939
- path: routePrefix.slice(0, -1) + fi.path
11940
- });
11941
- }
11942
- return prefixed;
11943
- }
11944
- }
11945
- if (path5 === "/") {
11946
- const results = [];
11947
- const defaultInfos = await this.default.lsInfo(path5);
11948
- results.push(...defaultInfos);
11949
- for (const [routePrefix] of this.sortedRoutes) {
11950
- results.push({
11951
- path: routePrefix,
11952
- is_dir: true,
11953
- size: 0,
11954
- modified_at: ""
11955
- });
11956
- }
11957
- results.sort((a, b) => a.path.localeCompare(b.path));
11958
- return results;
11959
- }
11960
- return await this.default.lsInfo(path5);
11961
- }
11962
- /**
11963
- * Read file content, routing to appropriate backend.
11964
- *
11965
- * @param filePath - Absolute file path
11966
- * @param offset - Line offset to start reading from (0-indexed)
11967
- * @param limit - Maximum number of lines to read
11968
- * @returns Formatted file content with line numbers, or error message
11969
- */
11970
- async read(filePath, offset = 0, limit = 2e3) {
11971
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11972
- return await backend.read(strippedKey, offset, limit);
11973
- }
11974
- /**
11975
- * Read file content as raw FileData.
11976
- *
11977
- * @param filePath - Absolute file path
11978
- * @returns Raw file content as FileData
11979
- */
11980
- async readRaw(filePath) {
11981
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11982
- return await backend.readRaw(strippedKey);
11983
- }
11984
- /**
11985
- * Structured search results or error string for invalid input.
11986
- */
11987
- async grepRaw(pattern, path5 = "/", glob = null) {
11988
- for (const [routePrefix, backend] of this.sortedRoutes) {
11989
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11990
- const searchPath = path5.substring(routePrefix.length - 1);
11991
- const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
11992
- if (typeof raw === "string") {
11993
- return raw;
11994
- }
11995
- return raw.map((m) => ({
11996
- ...m,
11997
- path: routePrefix.slice(0, -1) + m.path
11998
- }));
11999
- }
12000
- }
12001
- const allMatches = [];
12002
- const rawDefault = await this.default.grepRaw(pattern, path5, glob);
12003
- if (typeof rawDefault === "string") {
12004
- return rawDefault;
12005
- }
12006
- allMatches.push(...rawDefault);
12007
- for (const [routePrefix, backend] of Object.entries(this.routes)) {
12008
- const raw = await backend.grepRaw(pattern, "/", glob);
12009
- if (typeof raw === "string") {
12010
- return raw;
12011
- }
12012
- allMatches.push(
12013
- ...raw.map((m) => ({
12014
- ...m,
12015
- path: routePrefix.slice(0, -1) + m.path
12016
- }))
12017
- );
12018
- }
12019
- return allMatches;
12020
- }
12021
- /**
12022
- * Structured glob matching returning FileInfo objects.
12023
- */
12024
- async globInfo(pattern, path5 = "/") {
12025
- const results = [];
12026
- for (const [routePrefix, backend] of this.sortedRoutes) {
12027
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
12028
- const searchPath = path5.substring(routePrefix.length - 1);
12029
- const infos = await backend.globInfo(pattern, searchPath || "/");
12030
- return infos.map((fi) => ({
12031
- ...fi,
12032
- path: routePrefix.slice(0, -1) + fi.path
12033
- }));
12034
- }
12035
- }
12036
- const defaultInfos = await this.default.globInfo(pattern, path5);
12037
- results.push(...defaultInfos);
12038
- for (const [routePrefix, backend] of Object.entries(this.routes)) {
12039
- const infos = await backend.globInfo(pattern, "/");
12040
- results.push(
12041
- ...infos.map((fi) => ({
12042
- ...fi,
12043
- path: routePrefix.slice(0, -1) + fi.path
12044
- }))
12045
- );
12046
- }
12047
- results.sort((a, b) => a.path.localeCompare(b.path));
12048
- return results;
12049
- }
12050
- /**
12051
- * Create a new file, routing to appropriate backend.
12052
- *
12053
- * @param filePath - Absolute file path
12054
- * @param content - File content as string
12055
- * @returns WriteResult with path or error
12056
- */
12057
- async write(filePath, content) {
12058
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
12059
- return await backend.write(strippedKey, content);
12060
- }
12061
- /**
12062
- * Edit a file, routing to appropriate backend.
12063
- *
12064
- * @param filePath - Absolute file path
12065
- * @param oldString - String to find and replace
12066
- * @param newString - Replacement string
12067
- * @param replaceAll - If true, replace all occurrences
12068
- * @returns EditResult with path, occurrences, or error
12069
- */
12070
- async edit(filePath, oldString, newString, replaceAll = false) {
12071
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
12072
- return await backend.edit(strippedKey, oldString, newString, replaceAll);
12073
- }
12074
- };
12075
-
12076
12126
  // src/deep_agent_new/backends/memory.ts
12077
12127
  var MemoryBackend = class {
12078
12128
  constructor(files) {
@@ -12544,50 +12594,8 @@ ${BASE_PROMPT}` : BASE_PROMPT;
12544
12594
  });
12545
12595
  }
12546
12596
 
12547
- // src/agent_lattice/builders/filesystemBackend.ts
12548
- function createFilesystemBackendFactory(middlewareConfigs) {
12549
- const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
12550
- if (!filesystemConfig || !filesystemConfig.enabled) {
12551
- return void 0;
12552
- }
12553
- const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
12554
- return async (stateAndStore) => {
12555
- const { tenantId, workspaceId, projectId } = stateAndStore;
12556
- let sandboxName = "global";
12557
- if (isolatedLevel === "agent") {
12558
- sandboxName = "agent";
12559
- } else if (isolatedLevel === "thread") {
12560
- sandboxName = "thread";
12561
- }
12562
- const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
12563
- if (!sandboxManager) {
12564
- throw new Error("Sandbox manager not found");
12565
- }
12566
- let workingDirectory = "/";
12567
- if (workspaceId && projectId) {
12568
- if (tenantId) {
12569
- workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
12570
- } else {
12571
- workingDirectory = `/workspaces/${workspaceId}/${projectId}`;
12572
- }
12573
- }
12574
- const sandboxfs = new SandboxFilesystem({
12575
- sandboxInstance: await sandboxManager.createSandbox(sandboxName),
12576
- workingDirectory
12577
- });
12578
- const compositeBackend = new CompositeBackend(sandboxfs, {});
12579
- return compositeBackend;
12580
- };
12581
- }
12582
-
12583
12597
  // src/agent_lattice/builders/DeepAgentGraphBuilder.ts
12584
12598
  var DeepAgentGraphBuilder = class {
12585
- /**
12586
- * 根据 middleware 配置创建 middlewares
12587
- */
12588
- async createMiddlewares(middlewareConfigs) {
12589
- return await createCommonMiddlewares(middlewareConfigs);
12590
- }
12591
12599
  /**
12592
12600
  * 构建Deep Agent Graph
12593
12601
  *
@@ -12622,7 +12630,7 @@ var DeepAgentGraphBuilder = class {
12622
12630
  }));
12623
12631
  const middlewareConfigs = params.middleware || [];
12624
12632
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
12625
- const middlewares = await this.createMiddlewares(middlewareConfigs);
12633
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true);
12626
12634
  const deepAgent = createDeepAgent({
12627
12635
  tools,
12628
12636
  model: params.model,