@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.mjs CHANGED
@@ -4649,516 +4649,241 @@ var createReactAgentSchema = (schema) => {
4649
4649
  // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
4650
4650
  import { createAgent } from "langchain";
4651
4651
 
4652
- // src/deep_agent_new/backends/sandboxFiles.ts
4653
- import { SandboxClient as SandboxClient2 } from "@agent-infra/sandbox";
4654
- import * as path2 from "path";
4655
- var SandboxFilesystem = class {
4656
- /**
4657
- * Create a new SandboxFilesystem instance.
4658
- *
4659
- * @param options - Configuration options
4660
- * @param options.baseURL - Base URL of the sandbox service (default: 'http://localhost:8080')
4661
- * @param options.maxFileSizeMb - Maximum file size in MB (default: 10)
4662
- * @param options.sandboxInstance - Optional Sandbox instance (if provided, baseURL is ignored)
4663
- */
4664
- constructor(options = {}) {
4665
- const {
4666
- baseURL = "http://localhost:8080",
4667
- workingDirectory = "/",
4668
- maxFileSizeMb = 10,
4669
- sandboxInstance
4670
- } = options;
4671
- this.sandbox = sandboxInstance || new SandboxClient2({ baseUrl: baseURL, environment: "" });
4672
- this.sandbox.mcp.listMcpServers().then((servers) => {
4673
- });
4674
- this.sandbox.mcp.listMcpTools("browser").then((tools) => {
4652
+ // src/middlewares/codeEvalMiddleware.ts
4653
+ import { createMiddleware } from "langchain";
4654
+
4655
+ // src/middlewares/contextSchema.ts
4656
+ import z40 from "zod";
4657
+ var contextSchema = z40.object({
4658
+ runConfig: z40.any()
4659
+ });
4660
+
4661
+ // src/middlewares/codeEvalMiddleware.ts
4662
+ function createCodeEvalMiddleware(params = { isolatedLevel: "global" }) {
4663
+ const codeEvalTool = createCodeEvalTool({ isolatedLevel: params.isolatedLevel });
4664
+ const codeExecuteFileTool = createCodeExecuteFileTool({ isolatedLevel: params.isolatedLevel });
4665
+ return createMiddleware({
4666
+ name: "codeEvalMiddleware",
4667
+ contextSchema,
4668
+ tools: [codeEvalTool, codeExecuteFileTool, getToolClient("convert_to_markdown")]
4669
+ });
4670
+ }
4671
+
4672
+ // src/middlewares/browserMiddleware.ts
4673
+ import { createMiddleware as createMiddleware2 } from "langchain";
4674
+ function createBrowserMiddleware(params = { isolatedLevel: "global" }) {
4675
+ const isolatedLevel = params.isolatedLevel || "global";
4676
+ const tools = [
4677
+ createBrowserNavigateTool({ isolatedLevel }),
4678
+ createBrowserClickTool({ isolatedLevel }),
4679
+ createBrowserGetTextTool({ isolatedLevel }),
4680
+ createBrowserGetMarkdownTool({ isolatedLevel }),
4681
+ createBrowserEvaluateTool({ isolatedLevel }),
4682
+ createBrowserScreenshotTool({ isolatedLevel }),
4683
+ createBrowserScrollTool({ isolatedLevel }),
4684
+ createBrowserFormInputFillTool({ isolatedLevel }),
4685
+ createBrowserSelectTool({ isolatedLevel }),
4686
+ createBrowserHoverTool({ isolatedLevel }),
4687
+ createBrowserGoBackTool({ isolatedLevel }),
4688
+ createBrowserGoForwardTool({ isolatedLevel }),
4689
+ createBrowserNewTabTool({ isolatedLevel }),
4690
+ createBrowserTabListTool({ isolatedLevel }),
4691
+ createBrowserSwitchTabTool({ isolatedLevel }),
4692
+ createBrowserCloseTabTool({ isolatedLevel }),
4693
+ createBrowserCloseTool({ isolatedLevel }),
4694
+ createBrowserPressKeyTool({ isolatedLevel }),
4695
+ createBrowserReadLinksTool({ isolatedLevel }),
4696
+ createBrowserGetClickableElementsTool({ isolatedLevel }),
4697
+ createBrowserGetDownloadListTool({ isolatedLevel }),
4698
+ createBrowserGetInfoTool({ isolatedLevel })
4699
+ ];
4700
+ return createMiddleware2({
4701
+ name: "browserMiddleware",
4702
+ contextSchema,
4703
+ tools
4704
+ });
4705
+ }
4706
+
4707
+ // src/middlewares/sqlMiddleware.ts
4708
+ import { createMiddleware as createMiddleware3 } from "langchain";
4709
+ function createSqlMiddleware(params) {
4710
+ const { databaseKeys, databaseDescriptions } = params;
4711
+ if (!databaseKeys || databaseKeys.length === 0) {
4712
+ return createMiddleware3({
4713
+ name: "sqlMiddleware",
4714
+ tools: []
4675
4715
  });
4676
- this.baseURL = baseURL;
4677
- this.maxFileSizeBytes = maxFileSizeMb * 1024 * 1024;
4678
- this.workingDirectory = workingDirectory;
4679
- this.homeDir = "/home/gem";
4680
- }
4681
- resolvePath(virtualPath) {
4682
- return path2.join(this.homeDir, this.workingDirectory, virtualPath);
4683
4716
  }
4684
- /**
4685
- * Convert a real filesystem path to a virtual path.
4686
- *
4687
- * @param realPath - Real filesystem path
4688
- * @returns Virtual path starting with /
4689
- */
4690
- toVirtualPath(realPath) {
4691
- const rootPath = path2.join(this.homeDir, this.workingDirectory);
4692
- const relative4 = path2.relative(rootPath, realPath);
4693
- const normalized = relative4.split(path2.sep).join("/");
4694
- return "/" + normalized;
4717
+ const toolParams = {
4718
+ databaseKeys,
4719
+ databaseDescriptions
4720
+ };
4721
+ return createMiddleware3({
4722
+ name: "sqlMiddleware",
4723
+ contextSchema,
4724
+ tools: [
4725
+ createListTablesSqlTool(toolParams),
4726
+ createInfoSqlTool(toolParams),
4727
+ createQueryCheckerSqlTool(toolParams),
4728
+ createQuerySqlTool(toolParams)
4729
+ ]
4730
+ });
4731
+ }
4732
+
4733
+ // src/middlewares/skillMiddleware.ts
4734
+ import { createMiddleware as createMiddleware4 } from "langchain";
4735
+
4736
+ // src/store_lattice/InMemoryThreadStore.ts
4737
+ var InMemoryThreadStore = class {
4738
+ constructor() {
4739
+ // Map<tenantId, Map<assistantId, Map<threadId, Thread>>>
4740
+ this.threads = /* @__PURE__ */ new Map();
4695
4741
  }
4696
4742
  /**
4697
- * List files and directories in the specified directory (non-recursive).
4698
- *
4699
- * @param dirPath - Virtual directory path (must start with /)
4700
- * @returns List of FileInfo objects for files and directories directly in the directory.
4701
- * Directories have a trailing / in their path and is_dir=true.
4743
+ * Get all threads for a specific tenant and assistant
4702
4744
  */
4703
- async lsInfo(dirPath) {
4704
- try {
4705
- const resolvedPath = this.resolvePath(dirPath);
4706
- const result = await this.sandbox.file.listPath({
4707
- path: resolvedPath,
4708
- recursive: false,
4709
- show_hidden: false,
4710
- max_depth: 0,
4711
- include_size: false,
4712
- include_permissions: false,
4713
- sort_by: "name",
4714
- sort_desc: false
4715
- });
4716
- if (!result.ok) {
4717
- throw result.error;
4718
- }
4719
- const files = result.body?.data?.files?.map((file) => ({
4720
- path: this.toVirtualPath(file.path),
4721
- is_dir: file.is_directory,
4722
- size: file.size,
4723
- modified_at: file.modified_time
4724
- })) || [];
4725
- return files;
4726
- } catch (e) {
4727
- console.error(`Error listing files in ${dirPath}:`, e);
4745
+ async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
4746
+ const tenantThreads = this.threads.get(tenantId);
4747
+ if (!tenantThreads) {
4748
+ return [];
4749
+ }
4750
+ const assistantThreads = tenantThreads.get(assistantId);
4751
+ if (!assistantThreads) {
4728
4752
  return [];
4729
4753
  }
4754
+ let threads = Array.from(assistantThreads.values());
4755
+ if (metadataFilter && Object.keys(metadataFilter).length > 0) {
4756
+ threads = threads.filter(
4757
+ (thread) => Object.entries(metadataFilter).every(
4758
+ ([key, value]) => thread.metadata?.[key] === value
4759
+ )
4760
+ );
4761
+ }
4762
+ return threads;
4730
4763
  }
4731
4764
  /**
4732
- * Read file content with line numbers.
4733
- *
4734
- * @param filePath - Virtual file path (must start with /)
4735
- * @param offset - Line offset to start reading from (0-indexed)
4736
- * @param limit - Maximum number of lines to read
4737
- * @returns Formatted file content with line numbers, or error message
4765
+ * Get a thread by ID for a specific tenant
4738
4766
  */
4739
- async read(filePath, offset = 0, limit = 1e4) {
4740
- try {
4741
- const resolvedPath = this.resolvePath(filePath);
4742
- let content;
4743
- const result = await this.sandbox.file.readFile({
4744
- file: resolvedPath,
4745
- start_line: offset,
4746
- end_line: limit
4747
- });
4748
- if (!result.ok) {
4749
- throw result.error;
4767
+ async getThreadById(tenantId, threadId) {
4768
+ const tenantThreads = this.threads.get(tenantId);
4769
+ if (!tenantThreads) {
4770
+ return void 0;
4771
+ }
4772
+ for (const assistantThreads of tenantThreads.values()) {
4773
+ const thread = assistantThreads.get(threadId);
4774
+ if (thread) {
4775
+ return thread;
4750
4776
  }
4751
- content = result.body?.data?.content || "";
4752
- return content;
4753
- } catch (e) {
4754
- return `Error: File '${filePath}' not found`;
4755
4777
  }
4778
+ return void 0;
4756
4779
  }
4757
4780
  /**
4758
- * Read file content as raw FileData.
4759
- *
4760
- * @param filePath - Virtual file path (must start with /)
4761
- * @returns Raw file content as FileData
4781
+ * Create a new thread for a tenant and assistant
4762
4782
  */
4763
- async readRaw(filePath) {
4764
- try {
4765
- const content = await this.read(filePath);
4766
- return {
4767
- content: content.split("\n"),
4768
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
4769
- modified_at: (/* @__PURE__ */ new Date()).toISOString()
4770
- };
4771
- } catch (e) {
4772
- throw new Error(`Error reading file '${filePath}': ${e.message}`);
4783
+ async createThread(tenantId, assistantId, threadId, data) {
4784
+ const now = /* @__PURE__ */ new Date();
4785
+ const thread = {
4786
+ id: threadId,
4787
+ tenantId,
4788
+ assistantId,
4789
+ metadata: data.metadata || {},
4790
+ createdAt: now,
4791
+ updatedAt: now
4792
+ };
4793
+ if (!this.threads.has(tenantId)) {
4794
+ this.threads.set(tenantId, /* @__PURE__ */ new Map());
4795
+ }
4796
+ const tenantThreads = this.threads.get(tenantId);
4797
+ if (!tenantThreads.has(assistantId)) {
4798
+ tenantThreads.set(assistantId, /* @__PURE__ */ new Map());
4773
4799
  }
4800
+ const assistantThreads = tenantThreads.get(assistantId);
4801
+ assistantThreads.set(threadId, thread);
4802
+ return thread;
4774
4803
  }
4775
4804
  /**
4776
- * Create a new file with content.
4777
- * Returns WriteResult. External storage sets filesUpdate=null.
4778
- *
4779
- * @param filePath - Virtual file path (must start with /)
4780
- * @param content - File content as string
4781
- * @returns WriteResult with error populated on failure
4805
+ * Update an existing thread
4782
4806
  */
4783
- async write(filePath, content) {
4784
- try {
4785
- const resolvedPath = this.resolvePath(filePath);
4786
- const result = await this.sandbox.file.writeFile({
4787
- file: resolvedPath,
4788
- content,
4789
- "encoding": "utf-8",
4790
- "append": false
4791
- // sudo: true
4792
- });
4793
- if (!result.ok) {
4794
- console.error(result.error);
4795
- throw result.error;
4807
+ async updateThread(tenantId, threadId, updates) {
4808
+ const tenantThreads = this.threads.get(tenantId);
4809
+ if (!tenantThreads) {
4810
+ return null;
4811
+ }
4812
+ for (const assistantThreads of tenantThreads.values()) {
4813
+ const existing = assistantThreads.get(threadId);
4814
+ if (existing) {
4815
+ const updated = {
4816
+ ...existing,
4817
+ metadata: {
4818
+ ...existing.metadata,
4819
+ ...updates.metadata || {}
4820
+ },
4821
+ updatedAt: /* @__PURE__ */ new Date()
4822
+ };
4823
+ assistantThreads.set(threadId, updated);
4824
+ return updated;
4796
4825
  }
4797
- return {
4798
- path: filePath,
4799
- filesUpdate: {
4800
- [filePath]: {
4801
- content: content.split("\n"),
4802
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
4803
- modified_at: (/* @__PURE__ */ new Date()).toISOString()
4804
- }
4805
- }
4806
- };
4807
- } catch (e) {
4808
- throw new Error(`Error writing file '${filePath}': ${e.message}`);
4809
4826
  }
4827
+ return null;
4810
4828
  }
4811
4829
  /**
4812
- * Edit a file by replacing string occurrences.
4813
- * Returns EditResult. External storage sets filesUpdate=null.
4814
- *
4815
- * @param filePath - Virtual file path (must start with /)
4816
- * @param oldString - String to find and replace
4817
- * @param newString - Replacement string
4818
- * @param replaceAll - If true, replace all occurrences (default: false)
4819
- * @returns EditResult with error, path, filesUpdate, and occurrences
4830
+ * Delete a thread by ID
4820
4831
  */
4821
- async edit(filePath, oldString, newString, replaceAll = false) {
4822
- try {
4823
- const resolvedPath = this.resolvePath(filePath);
4824
- const result = await this.sandbox.file.strReplaceEditor({
4825
- command: "str_replace",
4826
- path: resolvedPath,
4827
- old_str: oldString,
4828
- new_str: newString,
4829
- replace_mode: replaceAll ? "ALL" : "FIRST"
4830
- });
4831
- if (!result.ok) {
4832
- throw result.error;
4832
+ async deleteThread(tenantId, threadId) {
4833
+ const tenantThreads = this.threads.get(tenantId);
4834
+ if (!tenantThreads) {
4835
+ return false;
4836
+ }
4837
+ for (const assistantThreads of tenantThreads.values()) {
4838
+ if (assistantThreads.has(threadId)) {
4839
+ return assistantThreads.delete(threadId);
4833
4840
  }
4834
- return {
4835
- path: filePath,
4836
- filesUpdate: null
4837
- };
4838
- } catch (e) {
4839
- throw new Error(`Error editing file '${filePath}': ${e.message}`);
4840
4841
  }
4842
+ return false;
4841
4843
  }
4842
4844
  /**
4843
- * Structured search results or error string for invalid input.
4844
- *
4845
- * Searches file contents for a regex pattern within the sandbox.
4846
- *
4847
- * @param pattern - Regex pattern to search for
4848
- * @param searchPath - Base path to search from (default: "/")
4849
- * @param glob - Optional glob pattern to filter files (e.g., "*.py")
4850
- * @returns List of GrepMatch objects or error string for invalid regex
4845
+ * Check if thread exists
4851
4846
  */
4852
- async grepRaw(pattern, searchPath = "/", glob = null) {
4853
- let baseFull;
4854
- baseFull = this.resolvePath(searchPath || "/");
4855
- const result = await this.sandbox.file.findFiles({
4856
- path: baseFull,
4857
- glob: glob || "**/*"
4858
- });
4859
- if (!result.ok) {
4860
- throw result.error;
4847
+ async hasThread(tenantId, threadId) {
4848
+ const tenantThreads = this.threads.get(tenantId);
4849
+ if (!tenantThreads) {
4850
+ return false;
4861
4851
  }
4862
- const filePaths = result.body?.data?.files || [];
4863
- const matches = [];
4864
- for (const absolutePath of filePaths) {
4865
- const fileData = await this.sandbox.file.searchInFile({
4866
- file: absolutePath,
4867
- regex: pattern
4868
- });
4869
- if (!fileData.ok) {
4870
- continue;
4852
+ for (const assistantThreads of tenantThreads.values()) {
4853
+ if (assistantThreads.has(threadId)) {
4854
+ return true;
4871
4855
  }
4872
- const matchesData = fileData.body?.data?.matches || [];
4873
- const matchLines = fileData.body?.data?.line_numbers || [];
4874
- matchesData.forEach((match, index) => {
4875
- matches.push({
4876
- path: this.toVirtualPath(absolutePath),
4877
- line: matchLines[index],
4878
- text: match
4879
- });
4880
- });
4881
4856
  }
4882
- return matches;
4857
+ return false;
4883
4858
  }
4884
4859
  /**
4885
- * Structured glob matching returning FileInfo objects.
4886
- *
4887
- * @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
4888
- * @param searchPath - Base path to search from (default: "/")
4889
- * @returns List of FileInfo objects matching the pattern
4860
+ * Clear all threads for a tenant (useful for testing)
4890
4861
  */
4891
- async globInfo(pattern, searchPath = "/") {
4892
- if (pattern.startsWith("/")) {
4893
- pattern = pattern.substring(1);
4894
- }
4895
- const resolvedSearchPath = this.resolvePath(searchPath);
4896
- const result = await this.sandbox.file.findFiles({
4897
- path: resolvedSearchPath,
4898
- glob: pattern || "**/*"
4899
- });
4900
- if (!result.ok) {
4901
- throw result.error;
4862
+ clear(tenantId) {
4863
+ if (tenantId) {
4864
+ this.threads.delete(tenantId);
4865
+ } else {
4866
+ this.threads.clear();
4902
4867
  }
4903
- const results = [];
4904
- for (const filePath of result.body?.data?.files || []) {
4905
- const fileInfo = await this.sandbox.file.listPath({
4906
- path: filePath,
4907
- recursive: false,
4908
- show_hidden: false,
4909
- max_depth: 1,
4910
- include_size: false,
4911
- include_permissions: false
4912
- });
4913
- if (!fileInfo.ok) {
4914
- continue;
4868
+ }
4869
+ /**
4870
+ * Get all threads for all assistants (useful for debugging)
4871
+ */
4872
+ getAllThreads() {
4873
+ const allThreads = [];
4874
+ for (const tenantThreads of this.threads.values()) {
4875
+ for (const assistantThreads of tenantThreads.values()) {
4876
+ allThreads.push(...Array.from(assistantThreads.values()));
4915
4877
  }
4916
- results.push({
4917
- path: this.toVirtualPath(filePath),
4918
- is_dir: false,
4919
- size: fileInfo.body?.data?.files?.[0]?.size,
4920
- modified_at: fileInfo.body?.data?.files?.[0]?.modified_time
4921
- });
4922
4878
  }
4923
- return results;
4879
+ return allThreads;
4924
4880
  }
4925
4881
  };
4926
4882
 
4927
- // src/middlewares/codeEvalMiddleware.ts
4928
- import { createMiddleware } from "langchain";
4929
-
4930
- // src/middlewares/contextSchema.ts
4931
- import z40 from "zod";
4932
- var contextSchema = z40.object({
4933
- runConfig: z40.any()
4934
- });
4935
-
4936
- // src/middlewares/codeEvalMiddleware.ts
4937
- function createCodeEvalMiddleware(params = { isolatedLevel: "global" }) {
4938
- const codeEvalTool = createCodeEvalTool({ isolatedLevel: params.isolatedLevel });
4939
- const codeExecuteFileTool = createCodeExecuteFileTool({ isolatedLevel: params.isolatedLevel });
4940
- return createMiddleware({
4941
- name: "codeEvalMiddleware",
4942
- contextSchema,
4943
- tools: [codeEvalTool, codeExecuteFileTool, getToolClient("convert_to_markdown")]
4944
- });
4945
- }
4946
-
4947
- // src/middlewares/browserMiddleware.ts
4948
- import { createMiddleware as createMiddleware2 } from "langchain";
4949
- function createBrowserMiddleware(params = { isolatedLevel: "global" }) {
4950
- const isolatedLevel = params.isolatedLevel || "global";
4951
- const tools = [
4952
- createBrowserNavigateTool({ isolatedLevel }),
4953
- createBrowserClickTool({ isolatedLevel }),
4954
- createBrowserGetTextTool({ isolatedLevel }),
4955
- createBrowserGetMarkdownTool({ isolatedLevel }),
4956
- createBrowserEvaluateTool({ isolatedLevel }),
4957
- createBrowserScreenshotTool({ isolatedLevel }),
4958
- createBrowserScrollTool({ isolatedLevel }),
4959
- createBrowserFormInputFillTool({ isolatedLevel }),
4960
- createBrowserSelectTool({ isolatedLevel }),
4961
- createBrowserHoverTool({ isolatedLevel }),
4962
- createBrowserGoBackTool({ isolatedLevel }),
4963
- createBrowserGoForwardTool({ isolatedLevel }),
4964
- createBrowserNewTabTool({ isolatedLevel }),
4965
- createBrowserTabListTool({ isolatedLevel }),
4966
- createBrowserSwitchTabTool({ isolatedLevel }),
4967
- createBrowserCloseTabTool({ isolatedLevel }),
4968
- createBrowserCloseTool({ isolatedLevel }),
4969
- createBrowserPressKeyTool({ isolatedLevel }),
4970
- createBrowserReadLinksTool({ isolatedLevel }),
4971
- createBrowserGetClickableElementsTool({ isolatedLevel }),
4972
- createBrowserGetDownloadListTool({ isolatedLevel }),
4973
- createBrowserGetInfoTool({ isolatedLevel })
4974
- ];
4975
- return createMiddleware2({
4976
- name: "browserMiddleware",
4977
- contextSchema,
4978
- tools
4979
- });
4980
- }
4981
-
4982
- // src/middlewares/sqlMiddleware.ts
4983
- import { createMiddleware as createMiddleware3 } from "langchain";
4984
- function createSqlMiddleware(params) {
4985
- const { databaseKeys, databaseDescriptions } = params;
4986
- if (!databaseKeys || databaseKeys.length === 0) {
4987
- return createMiddleware3({
4988
- name: "sqlMiddleware",
4989
- tools: []
4990
- });
4991
- }
4992
- const toolParams = {
4993
- databaseKeys,
4994
- databaseDescriptions
4995
- };
4996
- return createMiddleware3({
4997
- name: "sqlMiddleware",
4998
- contextSchema,
4999
- tools: [
5000
- createListTablesSqlTool(toolParams),
5001
- createInfoSqlTool(toolParams),
5002
- createQueryCheckerSqlTool(toolParams),
5003
- createQuerySqlTool(toolParams)
5004
- ]
5005
- });
5006
- }
5007
-
5008
- // src/middlewares/skillMiddleware.ts
5009
- import { createMiddleware as createMiddleware4 } from "langchain";
5010
-
5011
- // src/store_lattice/InMemoryThreadStore.ts
5012
- var InMemoryThreadStore = class {
4883
+ // src/store_lattice/InMemoryAssistantStore.ts
4884
+ var InMemoryAssistantStore = class {
5013
4885
  constructor() {
5014
- // Map<tenantId, Map<assistantId, Map<threadId, Thread>>>
5015
- this.threads = /* @__PURE__ */ new Map();
5016
- }
5017
- /**
5018
- * Get all threads for a specific tenant and assistant
5019
- */
5020
- async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
5021
- const tenantThreads = this.threads.get(tenantId);
5022
- if (!tenantThreads) {
5023
- return [];
5024
- }
5025
- const assistantThreads = tenantThreads.get(assistantId);
5026
- if (!assistantThreads) {
5027
- return [];
5028
- }
5029
- let threads = Array.from(assistantThreads.values());
5030
- if (metadataFilter && Object.keys(metadataFilter).length > 0) {
5031
- threads = threads.filter(
5032
- (thread) => Object.entries(metadataFilter).every(
5033
- ([key, value]) => thread.metadata?.[key] === value
5034
- )
5035
- );
5036
- }
5037
- return threads;
5038
- }
5039
- /**
5040
- * Get a thread by ID for a specific tenant
5041
- */
5042
- async getThreadById(tenantId, threadId) {
5043
- const tenantThreads = this.threads.get(tenantId);
5044
- if (!tenantThreads) {
5045
- return void 0;
5046
- }
5047
- for (const assistantThreads of tenantThreads.values()) {
5048
- const thread = assistantThreads.get(threadId);
5049
- if (thread) {
5050
- return thread;
5051
- }
5052
- }
5053
- return void 0;
5054
- }
5055
- /**
5056
- * Create a new thread for a tenant and assistant
5057
- */
5058
- async createThread(tenantId, assistantId, threadId, data) {
5059
- const now = /* @__PURE__ */ new Date();
5060
- const thread = {
5061
- id: threadId,
5062
- tenantId,
5063
- assistantId,
5064
- metadata: data.metadata || {},
5065
- createdAt: now,
5066
- updatedAt: now
5067
- };
5068
- if (!this.threads.has(tenantId)) {
5069
- this.threads.set(tenantId, /* @__PURE__ */ new Map());
5070
- }
5071
- const tenantThreads = this.threads.get(tenantId);
5072
- if (!tenantThreads.has(assistantId)) {
5073
- tenantThreads.set(assistantId, /* @__PURE__ */ new Map());
5074
- }
5075
- const assistantThreads = tenantThreads.get(assistantId);
5076
- assistantThreads.set(threadId, thread);
5077
- return thread;
5078
- }
5079
- /**
5080
- * Update an existing thread
5081
- */
5082
- async updateThread(tenantId, threadId, updates) {
5083
- const tenantThreads = this.threads.get(tenantId);
5084
- if (!tenantThreads) {
5085
- return null;
5086
- }
5087
- for (const assistantThreads of tenantThreads.values()) {
5088
- const existing = assistantThreads.get(threadId);
5089
- if (existing) {
5090
- const updated = {
5091
- ...existing,
5092
- metadata: {
5093
- ...existing.metadata,
5094
- ...updates.metadata || {}
5095
- },
5096
- updatedAt: /* @__PURE__ */ new Date()
5097
- };
5098
- assistantThreads.set(threadId, updated);
5099
- return updated;
5100
- }
5101
- }
5102
- return null;
5103
- }
5104
- /**
5105
- * Delete a thread by ID
5106
- */
5107
- async deleteThread(tenantId, threadId) {
5108
- const tenantThreads = this.threads.get(tenantId);
5109
- if (!tenantThreads) {
5110
- return false;
5111
- }
5112
- for (const assistantThreads of tenantThreads.values()) {
5113
- if (assistantThreads.has(threadId)) {
5114
- return assistantThreads.delete(threadId);
5115
- }
5116
- }
5117
- return false;
5118
- }
5119
- /**
5120
- * Check if thread exists
5121
- */
5122
- async hasThread(tenantId, threadId) {
5123
- const tenantThreads = this.threads.get(tenantId);
5124
- if (!tenantThreads) {
5125
- return false;
5126
- }
5127
- for (const assistantThreads of tenantThreads.values()) {
5128
- if (assistantThreads.has(threadId)) {
5129
- return true;
5130
- }
5131
- }
5132
- return false;
5133
- }
5134
- /**
5135
- * Clear all threads for a tenant (useful for testing)
5136
- */
5137
- clear(tenantId) {
5138
- if (tenantId) {
5139
- this.threads.delete(tenantId);
5140
- } else {
5141
- this.threads.clear();
5142
- }
5143
- }
5144
- /**
5145
- * Get all threads for all assistants (useful for debugging)
5146
- */
5147
- getAllThreads() {
5148
- const allThreads = [];
5149
- for (const tenantThreads of this.threads.values()) {
5150
- for (const assistantThreads of tenantThreads.values()) {
5151
- allThreads.push(...Array.from(assistantThreads.values()));
5152
- }
5153
- }
5154
- return allThreads;
5155
- }
5156
- };
5157
-
5158
- // src/store_lattice/InMemoryAssistantStore.ts
5159
- var InMemoryAssistantStore = class {
5160
- constructor() {
5161
- this.assistants = /* @__PURE__ */ new Map();
4886
+ this.assistants = /* @__PURE__ */ new Map();
5162
4887
  }
5163
4888
  /**
5164
4889
  * Get all assistants for a tenant
@@ -5250,7 +4975,7 @@ var InMemoryAssistantStore = class {
5250
4975
 
5251
4976
  // src/store_lattice/FileSystemSkillStore.ts
5252
4977
  import * as fs from "fs/promises";
5253
- import * as path3 from "path";
4978
+ import * as path2 from "path";
5254
4979
 
5255
4980
  // src/skill_lattice/skillNameValidator.ts
5256
4981
  var SKILL_NAME_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
@@ -5423,10 +5148,10 @@ var FileSystemSkillStore = class {
5423
5148
  constructor(options = {}) {
5424
5149
  const defaultPath = "lattice_store/skills";
5425
5150
  const providedPath = options.rootDir || defaultPath;
5426
- if (path3.isAbsolute(providedPath)) {
5151
+ if (path2.isAbsolute(providedPath)) {
5427
5152
  this.rootDir = providedPath;
5428
5153
  } else {
5429
- this.rootDir = path3.resolve(process.cwd(), providedPath);
5154
+ this.rootDir = path2.resolve(process.cwd(), providedPath);
5430
5155
  }
5431
5156
  this.ensureDirectoryExists().catch((error) => {
5432
5157
  console.error("Failed to initialize FileSystemSkillStore:", error);
@@ -5450,14 +5175,14 @@ var FileSystemSkillStore = class {
5450
5175
  if (name.includes("..") || name.includes("/") || name.includes("\\")) {
5451
5176
  throw new Error(`Invalid skill name: ${name} (contains invalid characters)`);
5452
5177
  }
5453
- return path3.join(this.rootDir, name);
5178
+ return path2.join(this.rootDir, name);
5454
5179
  }
5455
5180
  /**
5456
5181
  * Get file path for a skill name
5457
5182
  * File is always named SKILL.md inside the name directory
5458
5183
  */
5459
5184
  getSkillFilePath(name) {
5460
- return path3.join(this.getSkillDirectoryPath(name), "SKILL.md");
5185
+ return path2.join(this.getSkillDirectoryPath(name), "SKILL.md");
5461
5186
  }
5462
5187
  /**
5463
5188
  * Read skill from file
@@ -5744,14 +5469,14 @@ ${body}` : `${frontmatter}
5744
5469
  */
5745
5470
  async listSkillResources(_tenantId, skillName) {
5746
5471
  const skillDir = this.getSkillDirectoryPath(skillName);
5747
- const resourcesDir = path3.join(skillDir, "resources");
5472
+ const resourcesDir = path2.join(skillDir, "resources");
5748
5473
  try {
5749
5474
  const entries = await fs.readdir(resourcesDir, { withFileTypes: true, recursive: true });
5750
5475
  const resources = [];
5751
5476
  for (const entry of entries) {
5752
5477
  if (!entry.isDirectory()) {
5753
- const fullPath = path3.join(entry.path, entry.name);
5754
- const relativePath = path3.relative(resourcesDir, fullPath);
5478
+ const fullPath = path2.join(entry.path, entry.name);
5479
+ const relativePath = path2.relative(resourcesDir, fullPath);
5755
5480
  resources.push(relativePath.replace(/\\/g, "/"));
5756
5481
  }
5757
5482
  }
@@ -5772,10 +5497,10 @@ ${body}` : `${frontmatter}
5772
5497
  */
5773
5498
  async loadSkillResource(_tenantId, skillName, resourcePath) {
5774
5499
  const skillDir = this.getSkillDirectoryPath(skillName);
5775
- const resourcesDir = path3.join(skillDir, "resources");
5776
- const fullPath = path3.join(resourcesDir, resourcePath);
5777
- const resolvedPath = path3.resolve(fullPath);
5778
- const resolvedResourcesDir = path3.resolve(resourcesDir);
5500
+ const resourcesDir = path2.join(skillDir, "resources");
5501
+ const fullPath = path2.join(resourcesDir, resourcePath);
5502
+ const resolvedPath = path2.resolve(fullPath);
5503
+ const resolvedResourcesDir = path2.resolve(resourcesDir);
5779
5504
  if (!resolvedPath.startsWith(resolvedResourcesDir)) {
5780
5505
  throw new Error(`Invalid resource path: ${resourcePath}`);
5781
5506
  }
@@ -9311,22 +9036,19 @@ import { createMiddleware as createMiddleware10 } from "langchain";
9311
9036
 
9312
9037
  // src/deep_agent_new/middleware/AGENTS_MD.ts
9313
9038
  var AGENTS_MD = `
9314
- # AGENTS.md - Your Workspace
9315
-
9316
- This folder is home. Treat it that way.
9317
9039
 
9318
9040
  ## First Run
9319
9041
 
9320
- 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.
9042
+ 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.
9321
9043
 
9322
9044
  ## Every Session
9323
9045
 
9324
9046
  Before doing anything else:
9325
9047
 
9326
- 1. Read \`SOUL.md\` \u2014 this is who you are
9327
- 2. Read \`USER.md\` \u2014 this is who you're helping
9048
+ 1. Read \`/agent/SOUL.md\` \u2014 this is who you are
9049
+ 2. Read \`/agent/USER.md\` \u2014 this is who you're helping
9328
9050
  3. Read \`memory/YYYY-MM-DD.md\` (today + yesterday) for recent context
9329
- 4. **If in MAIN SESSION** (direct chat with your human): Also read \`MEMORY.md\`
9051
+ 4. **If in MAIN SESSION** (direct chat with your human): Also read \`/agent/MEMORY.md\`
9330
9052
 
9331
9053
  Don't ask permission. Just do it.
9332
9054
 
@@ -9334,17 +9056,18 @@ Don't ask permission. Just do it.
9334
9056
 
9335
9057
  You wake up fresh each session. These files are your continuity:
9336
9058
 
9337
- - **Daily notes:** \`memory/YYYY-MM-DD.md\` (create \`memory/\` if needed) \u2014 raw logs of what happened
9338
- - **Long-term:** \`MEMORY.md\` \u2014 your curated memories, like a human's long-term memory
9059
+ - **agent Long-term:** \`/agent/MEMORY.md\` \u2014 your curated memories, like a human's long-term memory
9060
+ - **Project Memory**: \`/PROJECT.md\` - Loaded from project root if available - Project-specific instructions
9061
+ - **Daily Project notes:** \`/daily/YYYY-MM-DD.md\` (create \`daily/\` if needed) \u2014 raw logs of what happened
9339
9062
 
9340
9063
  Capture what matters. Decisions, context, things to remember. Skip the secrets unless asked to keep them.
9341
9064
 
9342
- ### \u{1F9E0} MEMORY.md - Your Long-Term Memory
9065
+ ### \u{1F9E0} /agent/MEMORY.md - Your Long-Term Memory
9343
9066
 
9344
9067
  - **ONLY load in main session** (direct chats with your human)
9345
9068
  - **DO NOT load in shared contexts** (Discord, group chats, sessions with other people)
9346
9069
  - This is for **security** \u2014 contains personal context that shouldn't leak to strangers
9347
- - You can **read, edit, and update** MEMORY.md freely in main sessions
9070
+ - You can **read, edit, and update** /agent/MEMORY.md freely in main sessions
9348
9071
  - Write significant events, thoughts, decisions, opinions, lessons learned
9349
9072
  - This is your curated memory \u2014 the distilled essence, not raw logs
9350
9073
  - Over time, review your daily files and update MEMORY.md with what's worth keeping
@@ -9353,11 +9076,42 @@ Capture what matters. Decisions, context, things to remember. Skip the secrets u
9353
9076
 
9354
9077
  - **Memory is limited** \u2014 if you want to remember something, WRITE IT TO A FILE
9355
9078
  - "Mental notes" don't survive session restarts. Files do.
9356
- - When someone says "remember this" \u2192 update \`memory/YYYY-MM-DD.md\` or relevant file
9357
- - When you learn a lesson \u2192 update AGENTS.md, TOOLS.md, or the relevant skill
9079
+ - When someone says "remember this" \u2192 update \`/daily/YYYY-MM-DD.md\` or relevant file
9080
+ - When you learn a lesson \u2192 update /agent/AGENTS.md, /agent/TOOLS.md, or the relevant skill
9358
9081
  - When you make a mistake \u2192 document it so future-you doesn't repeat it
9359
9082
  - **Text > Brain** \u{1F4DD}
9360
9083
 
9084
+ ### Project Memory File: \`/PROJECT.md\`
9085
+ \u2192 Describes **how this specific project works** and **how the agent should behave here only.**
9086
+
9087
+ **Store here:**
9088
+ - Project-specific architecture and design patterns
9089
+ - Coding conventions specific to this codebase
9090
+ - Project structure and organization
9091
+ - Testing strategies for this project
9092
+ - Deployment processes and workflows
9093
+ - Team conventions and guidelines
9094
+
9095
+ **Examples:**
9096
+ - "This project uses FastAPI with SQLAlchemy"
9097
+ - "Tests go in tests/ directory mirroring src/ structure"
9098
+ - "All API changes require updating OpenAPI spec"
9099
+
9100
+ ### Project Memory Files: \`{project_deepagents_dir}/*.md\`
9101
+ \u2192 Use for **project-specific reference information** and structured notes.
9102
+
9103
+ **Store here:**
9104
+ - API design documentation
9105
+ - Architecture decisions and rationale
9106
+ - Deployment procedures
9107
+ - Common debugging patterns
9108
+ - Onboarding information
9109
+
9110
+ **Examples:**
9111
+ - \`{project_deepagents_dir}/api-design.md\` - REST API patterns used
9112
+ - \`{project_deepagents_dir}/architecture.md\` - System architecture overview
9113
+ - \`{project_deepagents_dir}/deployment.md\` - How to deploy this project
9114
+
9361
9115
  ## Safety
9362
9116
 
9363
9117
  - Don't exfiltrate private data. Ever.
@@ -9529,10 +9283,10 @@ Offer suggestions if they're stuck. Have fun with it.
9529
9283
 
9530
9284
  Update these files with what you learned:
9531
9285
 
9532
- - \`IDENTITY.md\` \u2014 your name, creature, vibe, emoji
9533
- - \`USER.md\` \u2014 their name, how to address them, timezone, notes
9286
+ - \`/agent/IDENTITY.md\` \u2014 your name, creature, vibe, emoji
9287
+ - \`/agent/USER.md\` \u2014 their name, how to address them, timezone, notes
9534
9288
 
9535
- Then open \`SOUL.md\` together and talk about:
9289
+ Then open \`/agent/SOUL.md\` together and talk about:
9536
9290
 
9537
9291
  - What matters to them
9538
9292
  - How they want you to behave
@@ -9665,12 +9419,12 @@ async function getBackend2(backend, stateAndStore) {
9665
9419
  return backend;
9666
9420
  }
9667
9421
  var BOOTSTRAP_FILE_NAMES = {
9668
- agents: "AGENTS.md",
9669
- soul: "SOUL.md",
9670
- identity: "IDENTITY.md",
9671
- user: "USER.md",
9672
- tools: "TOOLS.md",
9673
- bootstrap: "BOOTSTRAP.md"
9422
+ agents: "/agent/AGENTS.md",
9423
+ soul: "/agent/SOUL.md",
9424
+ identity: "/agent/IDENTITY.md",
9425
+ user: "/agent/USER.md",
9426
+ tools: "/agent/TOOLS.md",
9427
+ bootstrap: "/agent/BOOTSTRAP.md"
9674
9428
  };
9675
9429
  var BOOTSTRAP_SECTION_HEADERS = {
9676
9430
  agents: "## Operating Instructions",
@@ -9693,14 +9447,14 @@ Document available tools and their usage notes here.`,
9693
9447
  async function createBootstrapFiles(config, backend, stateAndStore) {
9694
9448
  const resolvedBackend = await getBackend2(backend, stateAndStore);
9695
9449
  try {
9696
- const agentsContent = await resolvedBackend.read("/AGENTS.md", 0, 1);
9450
+ const agentsContent = await resolvedBackend.read("/agent/AGENTS.md", 0, 1);
9697
9451
  if (!agentsContent.includes("Error:")) {
9698
9452
  return;
9699
9453
  }
9700
9454
  } catch (error) {
9701
9455
  }
9702
9456
  for (const [key, filename] of Object.entries(BOOTSTRAP_FILE_NAMES)) {
9703
- const filePath = "/" + filename;
9457
+ const filePath = filename;
9704
9458
  try {
9705
9459
  const content = config[key] || DEFAULT_BOOTSTRAP_CONTENT[key];
9706
9460
  await resolvedBackend.write(filePath, content);
@@ -9714,7 +9468,7 @@ async function buildBootstrapPromptSections(backend, stateAndStore) {
9714
9468
  const sections = [];
9715
9469
  const fileOrder = ["agents", "soul", "identity", "user", "tools", "bootstrap"];
9716
9470
  for (const key of fileOrder) {
9717
- const filePath = "/" + BOOTSTRAP_FILE_NAMES[key];
9471
+ const filePath = BOOTSTRAP_FILE_NAMES[key];
9718
9472
  try {
9719
9473
  const content = await resolvedBackend.read(filePath);
9720
9474
  if (content && !content.includes("Error:") && content.trim()) {
@@ -9750,14 +9504,13 @@ function createClawMiddleware(options = {}) {
9750
9504
  if (injectBootstrapFiles && backend) {
9751
9505
  const stateAndStore = {
9752
9506
  state: request.state || {},
9753
- store: request.store
9507
+ store: request.store,
9508
+ ...request.runtime.context.runConfig
9754
9509
  };
9755
9510
  const bootstrapSections = await buildBootstrapPromptSections(backend, stateAndStore);
9756
9511
  if (bootstrapSections.length > 0) {
9757
9512
  const bootstrapContext = `
9758
9513
 
9759
-
9760
-
9761
9514
  ${bootstrapSections.join("\n\n")}
9762
9515
 
9763
9516
  `;
@@ -9959,14 +9712,18 @@ ${currentSystemPrompt}` : dateContext;
9959
9712
  }
9960
9713
 
9961
9714
  // src/agent_lattice/builders/commonMiddleware.ts
9962
- async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
9715
+ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
9963
9716
  const middlewares = [];
9964
9717
  middlewares.push(createUnknownToolHandlerMiddleware());
9965
9718
  middlewares.push(createModelSelectorMiddleware());
9966
9719
  const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
9967
- if (filesystemConfig?.enabled && filesystemBackend) {
9968
- const options = { backend: filesystemBackend };
9969
- middlewares.push(createFilesystemMiddleware(options));
9720
+ const clawConfig = middlewareConfigs.find((m) => m.type === "claw");
9721
+ const needsFilesystemBackend = filesystemConfig?.enabled || clawConfig?.enabled;
9722
+ if (needsFilesystemBackend && filesystemBackend) {
9723
+ if (!fsIsExised) {
9724
+ const options = { backend: filesystemBackend };
9725
+ middlewares.push(createFilesystemMiddleware(options));
9726
+ }
9970
9727
  }
9971
9728
  for (const config of middlewareConfigs) {
9972
9729
  if (!config.enabled || config.type === "filesystem") continue;
@@ -10014,12 +9771,14 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
10014
9771
  break;
10015
9772
  case "claw":
10016
9773
  if (filesystemBackend) {
10017
- const clawConfig = config.config;
9774
+ const clawMiddlewareConfig = config.config;
10018
9775
  middlewares.push(createClawMiddleware({
10019
9776
  backend: filesystemBackend,
10020
- injectBootstrapFiles: clawConfig.injectBootstrapFiles ?? true,
10021
- bootstrapFiles: clawConfig.bootstrapFiles ?? {}
9777
+ injectBootstrapFiles: clawMiddlewareConfig.injectBootstrapFiles ?? true,
9778
+ bootstrapFiles: clawMiddlewareConfig.bootstrapFiles ?? {}
10022
9779
  }));
9780
+ } else {
9781
+ console.warn("[claw middleware] Filesystem backend not available. Claw middleware requires filesystem backend to function.");
10023
9782
  }
10024
9783
  break;
10025
9784
  case "date":
@@ -10027,45 +9786,516 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
10027
9786
  break;
10028
9787
  }
10029
9788
  }
10030
- return middlewares;
10031
- }
9789
+ return middlewares;
9790
+ }
9791
+
9792
+ // src/deep_agent_new/backends/sandboxFiles.ts
9793
+ import { SandboxClient as SandboxClient2 } from "@agent-infra/sandbox";
9794
+ import * as path3 from "path";
9795
+ var SandboxFilesystem = class {
9796
+ /**
9797
+ * Create a new SandboxFilesystem instance.
9798
+ *
9799
+ * @param options - Configuration options
9800
+ * @param options.baseURL - Base URL of the sandbox service (default: 'http://localhost:8080')
9801
+ * @param options.maxFileSizeMb - Maximum file size in MB (default: 10)
9802
+ * @param options.sandboxInstance - Optional Sandbox instance (if provided, baseURL is ignored)
9803
+ */
9804
+ constructor(options = {}) {
9805
+ const {
9806
+ baseURL = "http://localhost:8080",
9807
+ workingDirectory = "/",
9808
+ maxFileSizeMb = 10,
9809
+ sandboxInstance
9810
+ } = options;
9811
+ this.sandbox = sandboxInstance || new SandboxClient2({ baseUrl: baseURL, environment: "" });
9812
+ this.sandbox.mcp.listMcpServers().then((servers) => {
9813
+ });
9814
+ this.sandbox.mcp.listMcpTools("browser").then((tools) => {
9815
+ });
9816
+ this.baseURL = baseURL;
9817
+ this.maxFileSizeBytes = maxFileSizeMb * 1024 * 1024;
9818
+ this.workingDirectory = workingDirectory;
9819
+ this.homeDir = "/home/gem";
9820
+ }
9821
+ resolvePath(virtualPath) {
9822
+ return path3.join(this.homeDir, this.workingDirectory, virtualPath);
9823
+ }
9824
+ /**
9825
+ * Convert a real filesystem path to a virtual path.
9826
+ *
9827
+ * @param realPath - Real filesystem path
9828
+ * @returns Virtual path starting with /
9829
+ */
9830
+ toVirtualPath(realPath) {
9831
+ const rootPath = path3.join(this.homeDir, this.workingDirectory);
9832
+ const relative4 = path3.relative(rootPath, realPath);
9833
+ const normalized = relative4.split(path3.sep).join("/");
9834
+ return "/" + normalized;
9835
+ }
9836
+ /**
9837
+ * List files and directories in the specified directory (non-recursive).
9838
+ *
9839
+ * @param dirPath - Virtual directory path (must start with /)
9840
+ * @returns List of FileInfo objects for files and directories directly in the directory.
9841
+ * Directories have a trailing / in their path and is_dir=true.
9842
+ */
9843
+ async lsInfo(dirPath) {
9844
+ try {
9845
+ const resolvedPath = this.resolvePath(dirPath);
9846
+ const result = await this.sandbox.file.listPath({
9847
+ path: resolvedPath,
9848
+ recursive: false,
9849
+ show_hidden: false,
9850
+ max_depth: 0,
9851
+ include_size: false,
9852
+ include_permissions: false,
9853
+ sort_by: "name",
9854
+ sort_desc: false
9855
+ });
9856
+ if (!result.ok) {
9857
+ throw result.error;
9858
+ }
9859
+ const files = result.body?.data?.files?.map((file) => ({
9860
+ path: this.toVirtualPath(file.path),
9861
+ is_dir: file.is_directory,
9862
+ size: file.size,
9863
+ modified_at: file.modified_time
9864
+ })) || [];
9865
+ return files;
9866
+ } catch (e) {
9867
+ console.error(`Error listing files in ${dirPath}:`, e);
9868
+ return [];
9869
+ }
9870
+ }
9871
+ /**
9872
+ * Read file content with line numbers.
9873
+ *
9874
+ * @param filePath - Virtual file path (must start with /)
9875
+ * @param offset - Line offset to start reading from (0-indexed)
9876
+ * @param limit - Maximum number of lines to read
9877
+ * @returns Formatted file content with line numbers, or error message
9878
+ */
9879
+ async read(filePath, offset = 0, limit = 1e4) {
9880
+ try {
9881
+ const resolvedPath = this.resolvePath(filePath);
9882
+ let content;
9883
+ const result = await this.sandbox.file.readFile({
9884
+ file: resolvedPath,
9885
+ start_line: offset,
9886
+ end_line: limit
9887
+ });
9888
+ if (!result.ok) {
9889
+ throw result.error;
9890
+ }
9891
+ content = result.body?.data?.content || "";
9892
+ return content;
9893
+ } catch (e) {
9894
+ return `Error: File '${filePath}' not found`;
9895
+ }
9896
+ }
9897
+ /**
9898
+ * Read file content as raw FileData.
9899
+ *
9900
+ * @param filePath - Virtual file path (must start with /)
9901
+ * @returns Raw file content as FileData
9902
+ */
9903
+ async readRaw(filePath) {
9904
+ try {
9905
+ const content = await this.read(filePath);
9906
+ return {
9907
+ content: content.split("\n"),
9908
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
9909
+ modified_at: (/* @__PURE__ */ new Date()).toISOString()
9910
+ };
9911
+ } catch (e) {
9912
+ throw new Error(`Error reading file '${filePath}': ${e.message}`);
9913
+ }
9914
+ }
9915
+ /**
9916
+ * Create a new file with content.
9917
+ * Returns WriteResult. External storage sets filesUpdate=null.
9918
+ *
9919
+ * @param filePath - Virtual file path (must start with /)
9920
+ * @param content - File content as string
9921
+ * @returns WriteResult with error populated on failure
9922
+ */
9923
+ async write(filePath, content) {
9924
+ try {
9925
+ const resolvedPath = this.resolvePath(filePath);
9926
+ const result = await this.sandbox.file.writeFile({
9927
+ file: resolvedPath,
9928
+ content,
9929
+ "encoding": "utf-8",
9930
+ "append": false
9931
+ // sudo: true
9932
+ });
9933
+ if (!result.ok) {
9934
+ console.error(result.error);
9935
+ throw result.error;
9936
+ }
9937
+ return {
9938
+ path: filePath,
9939
+ filesUpdate: {
9940
+ [filePath]: {
9941
+ content: content.split("\n"),
9942
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
9943
+ modified_at: (/* @__PURE__ */ new Date()).toISOString()
9944
+ }
9945
+ }
9946
+ };
9947
+ } catch (e) {
9948
+ throw new Error(`Error writing file '${filePath}': ${e.message}`);
9949
+ }
9950
+ }
9951
+ /**
9952
+ * Edit a file by replacing string occurrences.
9953
+ * Returns EditResult. External storage sets filesUpdate=null.
9954
+ *
9955
+ * @param filePath - Virtual file path (must start with /)
9956
+ * @param oldString - String to find and replace
9957
+ * @param newString - Replacement string
9958
+ * @param replaceAll - If true, replace all occurrences (default: false)
9959
+ * @returns EditResult with error, path, filesUpdate, and occurrences
9960
+ */
9961
+ async edit(filePath, oldString, newString, replaceAll = false) {
9962
+ try {
9963
+ const resolvedPath = this.resolvePath(filePath);
9964
+ const result = await this.sandbox.file.strReplaceEditor({
9965
+ command: "str_replace",
9966
+ path: resolvedPath,
9967
+ old_str: oldString,
9968
+ new_str: newString,
9969
+ replace_mode: replaceAll ? "ALL" : "FIRST"
9970
+ });
9971
+ if (!result.ok) {
9972
+ throw result.error;
9973
+ }
9974
+ return {
9975
+ path: filePath,
9976
+ filesUpdate: null
9977
+ };
9978
+ } catch (e) {
9979
+ throw new Error(`Error editing file '${filePath}': ${e.message}`);
9980
+ }
9981
+ }
9982
+ /**
9983
+ * Structured search results or error string for invalid input.
9984
+ *
9985
+ * Searches file contents for a regex pattern within the sandbox.
9986
+ *
9987
+ * @param pattern - Regex pattern to search for
9988
+ * @param searchPath - Base path to search from (default: "/")
9989
+ * @param glob - Optional glob pattern to filter files (e.g., "*.py")
9990
+ * @returns List of GrepMatch objects or error string for invalid regex
9991
+ */
9992
+ async grepRaw(pattern, searchPath = "/", glob = null) {
9993
+ let baseFull;
9994
+ baseFull = this.resolvePath(searchPath || "/");
9995
+ const result = await this.sandbox.file.findFiles({
9996
+ path: baseFull,
9997
+ glob: glob || "**/*"
9998
+ });
9999
+ if (!result.ok) {
10000
+ throw result.error;
10001
+ }
10002
+ const filePaths = result.body?.data?.files || [];
10003
+ const matches = [];
10004
+ for (const absolutePath of filePaths) {
10005
+ const fileData = await this.sandbox.file.searchInFile({
10006
+ file: absolutePath,
10007
+ regex: pattern
10008
+ });
10009
+ if (!fileData.ok) {
10010
+ continue;
10011
+ }
10012
+ const matchesData = fileData.body?.data?.matches || [];
10013
+ const matchLines = fileData.body?.data?.line_numbers || [];
10014
+ matchesData.forEach((match, index) => {
10015
+ matches.push({
10016
+ path: this.toVirtualPath(absolutePath),
10017
+ line: matchLines[index],
10018
+ text: match
10019
+ });
10020
+ });
10021
+ }
10022
+ return matches;
10023
+ }
10024
+ /**
10025
+ * Structured glob matching returning FileInfo objects.
10026
+ *
10027
+ * @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
10028
+ * @param searchPath - Base path to search from (default: "/")
10029
+ * @returns List of FileInfo objects matching the pattern
10030
+ */
10031
+ async globInfo(pattern, searchPath = "/") {
10032
+ if (pattern.startsWith("/")) {
10033
+ pattern = pattern.substring(1);
10034
+ }
10035
+ const resolvedSearchPath = this.resolvePath(searchPath);
10036
+ const result = await this.sandbox.file.findFiles({
10037
+ path: resolvedSearchPath,
10038
+ glob: pattern || "**/*"
10039
+ });
10040
+ if (!result.ok) {
10041
+ throw result.error;
10042
+ }
10043
+ const results = [];
10044
+ for (const filePath of result.body?.data?.files || []) {
10045
+ const fileInfo = await this.sandbox.file.listPath({
10046
+ path: filePath,
10047
+ recursive: false,
10048
+ show_hidden: false,
10049
+ max_depth: 1,
10050
+ include_size: false,
10051
+ include_permissions: false
10052
+ });
10053
+ if (!fileInfo.ok) {
10054
+ continue;
10055
+ }
10056
+ results.push({
10057
+ path: this.toVirtualPath(filePath),
10058
+ is_dir: false,
10059
+ size: fileInfo.body?.data?.files?.[0]?.size,
10060
+ modified_at: fileInfo.body?.data?.files?.[0]?.modified_time
10061
+ });
10062
+ }
10063
+ return results;
10064
+ }
10065
+ };
10066
+
10067
+ // src/deep_agent_new/backends/composite.ts
10068
+ var CompositeBackend = class {
10069
+ constructor(defaultBackend, routes) {
10070
+ this.default = defaultBackend;
10071
+ this.routes = routes;
10072
+ this.sortedRoutes = Object.entries(routes).sort(
10073
+ (a, b) => b[0].length - a[0].length
10074
+ );
10075
+ }
10076
+ /**
10077
+ * Determine which backend handles this key and strip prefix.
10078
+ *
10079
+ * @param key - Original file path
10080
+ * @returns Tuple of [backend, stripped_key] where stripped_key has the route
10081
+ * prefix removed (but keeps leading slash).
10082
+ */
10083
+ getBackendAndKey(key) {
10084
+ for (const [prefix, backend] of this.sortedRoutes) {
10085
+ if (key.startsWith(prefix)) {
10086
+ const suffix = key.substring(prefix.length);
10087
+ const strippedKey = suffix ? "/" + suffix : "/";
10088
+ return [backend, strippedKey];
10089
+ }
10090
+ }
10091
+ return [this.default, key];
10092
+ }
10093
+ /**
10094
+ * List files and directories in the specified directory (non-recursive).
10095
+ *
10096
+ * @param path - Absolute path to directory
10097
+ * @returns List of FileInfo objects with route prefixes added, for files and directories
10098
+ * directly in the directory. Directories have a trailing / in their path and is_dir=true.
10099
+ */
10100
+ async lsInfo(path5) {
10101
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10102
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10103
+ const suffix = path5.substring(routePrefix.length);
10104
+ const searchPath = suffix ? "/" + suffix : "/";
10105
+ const infos = await backend.lsInfo(searchPath);
10106
+ const prefixed = [];
10107
+ for (const fi of infos) {
10108
+ prefixed.push({
10109
+ ...fi,
10110
+ path: routePrefix.slice(0, -1) + fi.path
10111
+ });
10112
+ }
10113
+ return prefixed;
10114
+ }
10115
+ }
10116
+ if (path5 === "/") {
10117
+ const results = [];
10118
+ const defaultInfos = await this.default.lsInfo(path5);
10119
+ results.push(...defaultInfos);
10120
+ for (const [routePrefix] of this.sortedRoutes) {
10121
+ results.push({
10122
+ path: routePrefix,
10123
+ is_dir: true,
10124
+ size: 0,
10125
+ modified_at: ""
10126
+ });
10127
+ }
10128
+ results.sort((a, b) => a.path.localeCompare(b.path));
10129
+ return results;
10130
+ }
10131
+ return await this.default.lsInfo(path5);
10132
+ }
10133
+ /**
10134
+ * Read file content, routing to appropriate backend.
10135
+ *
10136
+ * @param filePath - Absolute file path
10137
+ * @param offset - Line offset to start reading from (0-indexed)
10138
+ * @param limit - Maximum number of lines to read
10139
+ * @returns Formatted file content with line numbers, or error message
10140
+ */
10141
+ async read(filePath, offset = 0, limit = 2e3) {
10142
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10143
+ return await backend.read(strippedKey, offset, limit);
10144
+ }
10145
+ /**
10146
+ * Read file content as raw FileData.
10147
+ *
10148
+ * @param filePath - Absolute file path
10149
+ * @returns Raw file content as FileData
10150
+ */
10151
+ async readRaw(filePath) {
10152
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10153
+ return await backend.readRaw(strippedKey);
10154
+ }
10155
+ /**
10156
+ * Structured search results or error string for invalid input.
10157
+ */
10158
+ async grepRaw(pattern, path5 = "/", glob = null) {
10159
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10160
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10161
+ const searchPath = path5.substring(routePrefix.length - 1);
10162
+ const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
10163
+ if (typeof raw === "string") {
10164
+ return raw;
10165
+ }
10166
+ return raw.map((m) => ({
10167
+ ...m,
10168
+ path: routePrefix.slice(0, -1) + m.path
10169
+ }));
10170
+ }
10171
+ }
10172
+ const allMatches = [];
10173
+ const rawDefault = await this.default.grepRaw(pattern, path5, glob);
10174
+ if (typeof rawDefault === "string") {
10175
+ return rawDefault;
10176
+ }
10177
+ allMatches.push(...rawDefault);
10178
+ for (const [routePrefix, backend] of Object.entries(this.routes)) {
10179
+ const raw = await backend.grepRaw(pattern, "/", glob);
10180
+ if (typeof raw === "string") {
10181
+ return raw;
10182
+ }
10183
+ allMatches.push(
10184
+ ...raw.map((m) => ({
10185
+ ...m,
10186
+ path: routePrefix.slice(0, -1) + m.path
10187
+ }))
10188
+ );
10189
+ }
10190
+ return allMatches;
10191
+ }
10192
+ /**
10193
+ * Structured glob matching returning FileInfo objects.
10194
+ */
10195
+ async globInfo(pattern, path5 = "/") {
10196
+ const results = [];
10197
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10198
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10199
+ const searchPath = path5.substring(routePrefix.length - 1);
10200
+ const infos = await backend.globInfo(pattern, searchPath || "/");
10201
+ return infos.map((fi) => ({
10202
+ ...fi,
10203
+ path: routePrefix.slice(0, -1) + fi.path
10204
+ }));
10205
+ }
10206
+ }
10207
+ const defaultInfos = await this.default.globInfo(pattern, path5);
10208
+ results.push(...defaultInfos);
10209
+ for (const [routePrefix, backend] of Object.entries(this.routes)) {
10210
+ const infos = await backend.globInfo(pattern, "/");
10211
+ results.push(
10212
+ ...infos.map((fi) => ({
10213
+ ...fi,
10214
+ path: routePrefix.slice(0, -1) + fi.path
10215
+ }))
10216
+ );
10217
+ }
10218
+ results.sort((a, b) => a.path.localeCompare(b.path));
10219
+ return results;
10220
+ }
10221
+ /**
10222
+ * Create a new file, routing to appropriate backend.
10223
+ *
10224
+ * @param filePath - Absolute file path
10225
+ * @param content - File content as string
10226
+ * @returns WriteResult with path or error
10227
+ */
10228
+ async write(filePath, content) {
10229
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10230
+ return await backend.write(strippedKey, content);
10231
+ }
10232
+ /**
10233
+ * Edit a file, routing to appropriate backend.
10234
+ *
10235
+ * @param filePath - Absolute file path
10236
+ * @param oldString - String to find and replace
10237
+ * @param newString - Replacement string
10238
+ * @param replaceAll - If true, replace all occurrences
10239
+ * @returns EditResult with path, occurrences, or error
10240
+ */
10241
+ async edit(filePath, oldString, newString, replaceAll = false) {
10242
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10243
+ return await backend.edit(strippedKey, oldString, newString, replaceAll);
10244
+ }
10245
+ };
10032
10246
 
10033
- // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
10034
- var ReActAgentGraphBuilder = class {
10035
- createFilesystemBackendFactory(middlewareConfigs, agentLattice) {
10036
- const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
10037
- if (!filesystemConfig || !filesystemConfig.enabled) {
10038
- return void 0;
10247
+ // src/agent_lattice/builders/filesystemBackend.ts
10248
+ function createFilesystemBackendFactory(middlewareConfigs, defualtRootLevel = "project", routesLevelConfig = {
10249
+ "/agent/": "agent"
10250
+ //默认配置 agent目录就是agent级别的
10251
+ }) {
10252
+ const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
10253
+ if (!filesystemConfig || !filesystemConfig.enabled) {
10254
+ return void 0;
10255
+ }
10256
+ const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
10257
+ return async (stateAndStore) => {
10258
+ const { tenantId, workspaceId, projectId, assistant_id } = stateAndStore;
10259
+ let sandboxName = "global";
10260
+ if (isolatedLevel === "agent") {
10261
+ sandboxName = "agent";
10262
+ } else if (isolatedLevel === "thread") {
10263
+ sandboxName = "thread";
10039
10264
  }
10040
- const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
10041
- const agentTenantId = agentLattice.config.tenantId;
10042
- return async (stateAndStore) => {
10043
- const { tenantId: runtimeTenantId, workspaceId, projectId } = stateAndStore;
10044
- const tenantId = runtimeTenantId || agentTenantId;
10045
- let sandboxName = "global";
10046
- if (isolatedLevel === "agent") {
10047
- sandboxName = "agent";
10048
- } else if (isolatedLevel === "thread") {
10049
- sandboxName = "thread";
10050
- }
10051
- const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
10052
- if (!sandboxManager) {
10053
- throw new Error("Sandbox manager not found");
10054
- }
10055
- let workingDirectory = "/";
10056
- if (workspaceId && projectId) {
10057
- if (tenantId) {
10058
- workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
10059
- } else {
10060
- workingDirectory = `/${workspaceId}/${projectId}`;
10061
- }
10265
+ const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
10266
+ if (!sandboxManager) {
10267
+ throw new Error("Sandbox manager not found");
10268
+ }
10269
+ const getWS = (rootLevel) => {
10270
+ let workingDirectory = `/tenants/${tenantId}`;
10271
+ if (assistant_id && rootLevel === "agent") {
10272
+ workingDirectory = `/tenants/${tenantId}/agents/${assistant_id}`;
10273
+ } else if (workspaceId && projectId && rootLevel === "project") {
10274
+ workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
10062
10275
  }
10063
- return new SandboxFilesystem({
10064
- sandboxInstance: await sandboxManager.createSandbox(sandboxName),
10065
- workingDirectory
10066
- });
10276
+ return workingDirectory;
10067
10277
  };
10068
- }
10278
+ const sandboxInstance = await sandboxManager.createSandbox(sandboxName);
10279
+ const sandboxfs = new SandboxFilesystem({
10280
+ sandboxInstance,
10281
+ workingDirectory: getWS(defualtRootLevel)
10282
+ });
10283
+ const routers = Object.keys(routesLevelConfig).reduce((pre, curr) => ({
10284
+ ...pre,
10285
+ [curr]: new SandboxFilesystem({
10286
+ sandboxInstance,
10287
+ workingDirectory: getWS(routesLevelConfig[curr])
10288
+ })
10289
+ }), {});
10290
+ const compositeBackend = new CompositeBackend(sandboxfs, {
10291
+ ...routers
10292
+ });
10293
+ return compositeBackend;
10294
+ };
10295
+ }
10296
+
10297
+ // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
10298
+ var ReActAgentGraphBuilder = class {
10069
10299
  async createMiddlewares(middlewareConfigs) {
10070
10300
  return await createCommonMiddlewares(middlewareConfigs);
10071
10301
  }
@@ -10083,7 +10313,7 @@ var ReActAgentGraphBuilder = class {
10083
10313
  }).filter((tool51) => tool51 !== void 0);
10084
10314
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
10085
10315
  const middlewareConfigs = params.middleware || [];
10086
- const filesystemBackend = this.createFilesystemBackendFactory(middlewareConfigs, agentLattice);
10316
+ const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
10087
10317
  const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend);
10088
10318
  return createAgent({
10089
10319
  model: params.model,
@@ -11731,186 +11961,6 @@ var FilesystemBackend = class {
11731
11961
  }
11732
11962
  };
11733
11963
 
11734
- // src/deep_agent_new/backends/composite.ts
11735
- var CompositeBackend = class {
11736
- constructor(defaultBackend, routes) {
11737
- this.default = defaultBackend;
11738
- this.routes = routes;
11739
- this.sortedRoutes = Object.entries(routes).sort(
11740
- (a, b) => b[0].length - a[0].length
11741
- );
11742
- }
11743
- /**
11744
- * Determine which backend handles this key and strip prefix.
11745
- *
11746
- * @param key - Original file path
11747
- * @returns Tuple of [backend, stripped_key] where stripped_key has the route
11748
- * prefix removed (but keeps leading slash).
11749
- */
11750
- getBackendAndKey(key) {
11751
- for (const [prefix, backend] of this.sortedRoutes) {
11752
- if (key.startsWith(prefix)) {
11753
- const suffix = key.substring(prefix.length);
11754
- const strippedKey = suffix ? "/" + suffix : "/";
11755
- return [backend, strippedKey];
11756
- }
11757
- }
11758
- return [this.default, key];
11759
- }
11760
- /**
11761
- * List files and directories in the specified directory (non-recursive).
11762
- *
11763
- * @param path - Absolute path to directory
11764
- * @returns List of FileInfo objects with route prefixes added, for files and directories
11765
- * directly in the directory. Directories have a trailing / in their path and is_dir=true.
11766
- */
11767
- async lsInfo(path5) {
11768
- for (const [routePrefix, backend] of this.sortedRoutes) {
11769
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11770
- const suffix = path5.substring(routePrefix.length);
11771
- const searchPath = suffix ? "/" + suffix : "/";
11772
- const infos = await backend.lsInfo(searchPath);
11773
- const prefixed = [];
11774
- for (const fi of infos) {
11775
- prefixed.push({
11776
- ...fi,
11777
- path: routePrefix.slice(0, -1) + fi.path
11778
- });
11779
- }
11780
- return prefixed;
11781
- }
11782
- }
11783
- if (path5 === "/") {
11784
- const results = [];
11785
- const defaultInfos = await this.default.lsInfo(path5);
11786
- results.push(...defaultInfos);
11787
- for (const [routePrefix] of this.sortedRoutes) {
11788
- results.push({
11789
- path: routePrefix,
11790
- is_dir: true,
11791
- size: 0,
11792
- modified_at: ""
11793
- });
11794
- }
11795
- results.sort((a, b) => a.path.localeCompare(b.path));
11796
- return results;
11797
- }
11798
- return await this.default.lsInfo(path5);
11799
- }
11800
- /**
11801
- * Read file content, routing to appropriate backend.
11802
- *
11803
- * @param filePath - Absolute file path
11804
- * @param offset - Line offset to start reading from (0-indexed)
11805
- * @param limit - Maximum number of lines to read
11806
- * @returns Formatted file content with line numbers, or error message
11807
- */
11808
- async read(filePath, offset = 0, limit = 2e3) {
11809
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11810
- return await backend.read(strippedKey, offset, limit);
11811
- }
11812
- /**
11813
- * Read file content as raw FileData.
11814
- *
11815
- * @param filePath - Absolute file path
11816
- * @returns Raw file content as FileData
11817
- */
11818
- async readRaw(filePath) {
11819
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11820
- return await backend.readRaw(strippedKey);
11821
- }
11822
- /**
11823
- * Structured search results or error string for invalid input.
11824
- */
11825
- async grepRaw(pattern, path5 = "/", glob = null) {
11826
- for (const [routePrefix, backend] of this.sortedRoutes) {
11827
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11828
- const searchPath = path5.substring(routePrefix.length - 1);
11829
- const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
11830
- if (typeof raw === "string") {
11831
- return raw;
11832
- }
11833
- return raw.map((m) => ({
11834
- ...m,
11835
- path: routePrefix.slice(0, -1) + m.path
11836
- }));
11837
- }
11838
- }
11839
- const allMatches = [];
11840
- const rawDefault = await this.default.grepRaw(pattern, path5, glob);
11841
- if (typeof rawDefault === "string") {
11842
- return rawDefault;
11843
- }
11844
- allMatches.push(...rawDefault);
11845
- for (const [routePrefix, backend] of Object.entries(this.routes)) {
11846
- const raw = await backend.grepRaw(pattern, "/", glob);
11847
- if (typeof raw === "string") {
11848
- return raw;
11849
- }
11850
- allMatches.push(
11851
- ...raw.map((m) => ({
11852
- ...m,
11853
- path: routePrefix.slice(0, -1) + m.path
11854
- }))
11855
- );
11856
- }
11857
- return allMatches;
11858
- }
11859
- /**
11860
- * Structured glob matching returning FileInfo objects.
11861
- */
11862
- async globInfo(pattern, path5 = "/") {
11863
- const results = [];
11864
- for (const [routePrefix, backend] of this.sortedRoutes) {
11865
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11866
- const searchPath = path5.substring(routePrefix.length - 1);
11867
- const infos = await backend.globInfo(pattern, searchPath || "/");
11868
- return infos.map((fi) => ({
11869
- ...fi,
11870
- path: routePrefix.slice(0, -1) + fi.path
11871
- }));
11872
- }
11873
- }
11874
- const defaultInfos = await this.default.globInfo(pattern, path5);
11875
- results.push(...defaultInfos);
11876
- for (const [routePrefix, backend] of Object.entries(this.routes)) {
11877
- const infos = await backend.globInfo(pattern, "/");
11878
- results.push(
11879
- ...infos.map((fi) => ({
11880
- ...fi,
11881
- path: routePrefix.slice(0, -1) + fi.path
11882
- }))
11883
- );
11884
- }
11885
- results.sort((a, b) => a.path.localeCompare(b.path));
11886
- return results;
11887
- }
11888
- /**
11889
- * Create a new file, routing to appropriate backend.
11890
- *
11891
- * @param filePath - Absolute file path
11892
- * @param content - File content as string
11893
- * @returns WriteResult with path or error
11894
- */
11895
- async write(filePath, content) {
11896
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11897
- return await backend.write(strippedKey, content);
11898
- }
11899
- /**
11900
- * Edit a file, routing to appropriate backend.
11901
- *
11902
- * @param filePath - Absolute file path
11903
- * @param oldString - String to find and replace
11904
- * @param newString - Replacement string
11905
- * @param replaceAll - If true, replace all occurrences
11906
- * @returns EditResult with path, occurrences, or error
11907
- */
11908
- async edit(filePath, oldString, newString, replaceAll = false) {
11909
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11910
- return await backend.edit(strippedKey, oldString, newString, replaceAll);
11911
- }
11912
- };
11913
-
11914
11964
  // src/deep_agent_new/backends/memory.ts
11915
11965
  var MemoryBackend = class {
11916
11966
  constructor(files) {
@@ -12382,50 +12432,8 @@ ${BASE_PROMPT}` : BASE_PROMPT;
12382
12432
  });
12383
12433
  }
12384
12434
 
12385
- // src/agent_lattice/builders/filesystemBackend.ts
12386
- function createFilesystemBackendFactory(middlewareConfigs) {
12387
- const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
12388
- if (!filesystemConfig || !filesystemConfig.enabled) {
12389
- return void 0;
12390
- }
12391
- const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
12392
- return async (stateAndStore) => {
12393
- const { tenantId, workspaceId, projectId } = stateAndStore;
12394
- let sandboxName = "global";
12395
- if (isolatedLevel === "agent") {
12396
- sandboxName = "agent";
12397
- } else if (isolatedLevel === "thread") {
12398
- sandboxName = "thread";
12399
- }
12400
- const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
12401
- if (!sandboxManager) {
12402
- throw new Error("Sandbox manager not found");
12403
- }
12404
- let workingDirectory = "/";
12405
- if (workspaceId && projectId) {
12406
- if (tenantId) {
12407
- workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
12408
- } else {
12409
- workingDirectory = `/workspaces/${workspaceId}/${projectId}`;
12410
- }
12411
- }
12412
- const sandboxfs = new SandboxFilesystem({
12413
- sandboxInstance: await sandboxManager.createSandbox(sandboxName),
12414
- workingDirectory
12415
- });
12416
- const compositeBackend = new CompositeBackend(sandboxfs, {});
12417
- return compositeBackend;
12418
- };
12419
- }
12420
-
12421
12435
  // src/agent_lattice/builders/DeepAgentGraphBuilder.ts
12422
12436
  var DeepAgentGraphBuilder = class {
12423
- /**
12424
- * 根据 middleware 配置创建 middlewares
12425
- */
12426
- async createMiddlewares(middlewareConfigs) {
12427
- return await createCommonMiddlewares(middlewareConfigs);
12428
- }
12429
12437
  /**
12430
12438
  * 构建Deep Agent Graph
12431
12439
  *
@@ -12460,7 +12468,7 @@ var DeepAgentGraphBuilder = class {
12460
12468
  }));
12461
12469
  const middlewareConfigs = params.middleware || [];
12462
12470
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
12463
- const middlewares = await this.createMiddlewares(middlewareConfigs);
12471
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true);
12464
12472
  const deepAgent = createDeepAgent({
12465
12473
  tools,
12466
12474
  model: params.model,