@axiom-lattice/core 2.1.45 → 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
@@ -648,11 +648,11 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
648
648
  * @param key Lattice键名
649
649
  * @param tool 已有的StructuredTool实例
650
650
  */
651
- registerExistingTool(key, tool50) {
651
+ registerExistingTool(key, tool51) {
652
652
  const config = {
653
- name: tool50.name,
654
- description: tool50.description,
655
- schema: tool50.schema,
653
+ name: tool51.name,
654
+ description: tool51.description,
655
+ schema: tool51.schema,
656
656
  // StructuredTool的schema已经是Zod兼容的
657
657
  needUserApprove: false
658
658
  // MCP工具默认不需要用户批准
@@ -660,7 +660,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
660
660
  const toolLattice = {
661
661
  key,
662
662
  config,
663
- client: tool50
663
+ client: tool51
664
664
  };
665
665
  this.register(key, toolLattice);
666
666
  }
@@ -686,7 +686,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
686
686
  };
687
687
  var toolLatticeManager = ToolLatticeManager.getInstance();
688
688
  var registerToolLattice = (key, config, executor) => toolLatticeManager.registerLattice(key, config, executor);
689
- var registerExistingTool = (key, tool50) => toolLatticeManager.registerExistingTool(key, tool50);
689
+ var registerExistingTool = (key, tool51) => toolLatticeManager.registerExistingTool(key, tool51);
690
690
  var getToolLattice = (key) => toolLatticeManager.getToolLattice(key);
691
691
  var getToolDefinition = (key) => toolLatticeManager.getToolDefinition(key);
692
692
  var getToolClient = (key) => toolLatticeManager.getToolClient(key);
@@ -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
  }
@@ -9239,7 +8964,7 @@ function createShowWidgetTool() {
9239
8964
  },
9240
8965
  {
9241
8966
  name: "show_widget",
9242
- description: "Render an interactive HTML widget or SVG diagram visible to the user. Use for: charts, dashboards, calculators, forms, diagrams, timers, games, visualizations. The widget appears in a panel next to the chat. Users can interact with it and send data back via window.sendToAgent(data). IMPORTANT: Always call load_guidelines before your first show_widget.",
8967
+ description: "Render an interactive HTML widget or SVG diagram visible to the user. Use for: charts, dashboards, calculators, forms, diagrams, timers, games, visualizations. The widget appears in a panel next to the chat. Users can interact with it and send data back via window.sendPrompt(data). IMPORTANT: Always call load_guidelines before your first show_widget.",
9243
8968
  schema: ShowWidgetInputSchema
9244
8969
  }
9245
8970
  );
@@ -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
  `;
@@ -9767,113 +9520,782 @@ ${bootstrapSections.join("\n\n")}
9767
9520
  }
9768
9521
  return handler(request);
9769
9522
  }
9770
- });
9771
- }
9523
+ });
9524
+ }
9525
+
9526
+ // src/middlewares/unknownToolHandlerMiddleware.ts
9527
+ import { createMiddleware as createMiddleware11 } from "langchain";
9528
+ import { AIMessage as AIMessage2, ToolMessage as ToolMessage3 } from "@langchain/core/messages";
9529
+ function createUnknownToolHandlerMiddleware(config = {}) {
9530
+ const {
9531
+ strategy = "error",
9532
+ errorMessageTemplate = (name, tools) => `Error: Tool "${name}" does not exist.
9533
+
9534
+ Available tools:
9535
+ ` + tools.map((t) => ` - ${t}`).join("\n") + `
9536
+
9537
+ Please select a valid tool from the list above.`
9538
+ } = config;
9539
+ return createMiddleware11({
9540
+ name: "UnknownToolHandlerMiddleware",
9541
+ /**
9542
+ * wrapModelCall hook
9543
+ *
9544
+ * The only place to access request.tools (all available tools).
9545
+ * Identifies unknown tools and stores error info in metadata.
9546
+ *
9547
+ * Key: Preserve all tool_calls in original AIMessage, including unknown ones.
9548
+ * This allows the model to see what it selected in the next round.
9549
+ */
9550
+ wrapModelCall: async (request, handler) => {
9551
+ const availableTools = request.tools || [];
9552
+ const availableToolNames = availableTools.map((t) => t.name);
9553
+ const availableToolSet = new Set(availableToolNames);
9554
+ const aiResponse = await handler(request);
9555
+ if (!aiResponse.tool_calls || aiResponse.tool_calls.length === 0) {
9556
+ return aiResponse;
9557
+ }
9558
+ const unknownToolCalls = [];
9559
+ for (const toolCall of aiResponse.tool_calls) {
9560
+ if (!availableToolSet.has(toolCall.name)) {
9561
+ unknownToolCalls.push(toolCall);
9562
+ }
9563
+ }
9564
+ if (unknownToolCalls.length === 0) {
9565
+ return aiResponse;
9566
+ }
9567
+ if (strategy === "strict") {
9568
+ const unknownNames = unknownToolCalls.map((t) => t.name).join(", ");
9569
+ throw new Error(
9570
+ `Unknown tools detected: ${unknownNames}. Available tools: ${availableToolNames.join(", ")}`
9571
+ );
9572
+ }
9573
+ const unknownToolErrors = unknownToolCalls.map((toolCall) => ({
9574
+ toolName: toolCall.name,
9575
+ toolCallId: toolCall.id,
9576
+ errorMessage: errorMessageTemplate(toolCall.name, availableToolNames)
9577
+ }));
9578
+ const modifiedResponse = new AIMessage2({
9579
+ content: aiResponse.content,
9580
+ tool_calls: aiResponse.tool_calls,
9581
+ // Key: preserve all tool_calls, don't delete unknown
9582
+ response_metadata: {
9583
+ ...aiResponse.response_metadata,
9584
+ _unknownToolErrors: unknownToolErrors
9585
+ }
9586
+ });
9587
+ if (aiResponse.id) {
9588
+ modifiedResponse.id = aiResponse.id;
9589
+ }
9590
+ return modifiedResponse;
9591
+ },
9592
+ /**
9593
+ * afterModel hook
9594
+ *
9595
+ * Processes unknown tool errors stored in metadata.
9596
+ * Generates error ToolMessages and jumps back to model.
9597
+ *
9598
+ * Key: Uses jumpTo: "model" to form agent loop.
9599
+ * Without jumpTo, the graph would end after ToolNode without returning to model.
9600
+ */
9601
+ afterModel: {
9602
+ canJumpTo: ["model"],
9603
+ hook: async (state) => {
9604
+ const { messages } = state;
9605
+ if (!messages || messages.length === 0) {
9606
+ return;
9607
+ }
9608
+ const lastMessage = messages[messages.length - 1];
9609
+ if (!AIMessage2.isInstance(lastMessage)) {
9610
+ return;
9611
+ }
9612
+ const unknownToolErrors = lastMessage.response_metadata?._unknownToolErrors;
9613
+ if (!unknownToolErrors || !Array.isArray(unknownToolErrors) || unknownToolErrors.length === 0) {
9614
+ return;
9615
+ }
9616
+ const errorToolMessages = unknownToolErrors.map(
9617
+ (error) => new ToolMessage3({
9618
+ content: error.errorMessage,
9619
+ name: error.toolName,
9620
+ tool_call_id: error.toolCallId,
9621
+ status: "error"
9622
+ })
9623
+ );
9624
+ delete lastMessage.response_metadata._unknownToolErrors;
9625
+ return {
9626
+ messages: errorToolMessages,
9627
+ jumpTo: "model"
9628
+ };
9629
+ }
9630
+ }
9631
+ });
9632
+ }
9633
+
9634
+ // src/deep_agent_new/middleware/date.ts
9635
+ import { createMiddleware as createMiddleware12, tool as tool46 } from "langchain";
9636
+ import { z as z47 } from "zod";
9637
+ function formatCurrentDate(timezone = "UTC") {
9638
+ const now = /* @__PURE__ */ new Date();
9639
+ let validTimezone = timezone;
9640
+ try {
9641
+ Intl.DateTimeFormat(void 0, { timeZone: timezone });
9642
+ } catch {
9643
+ validTimezone = "UTC";
9644
+ }
9645
+ const dateFormatOptions = {
9646
+ timeZone: validTimezone,
9647
+ year: "numeric",
9648
+ month: "2-digit",
9649
+ day: "2-digit"
9650
+ };
9651
+ return new Intl.DateTimeFormat("en-US", dateFormatOptions).format(now);
9652
+ }
9653
+ function generateDateContext(timezone = "UTC") {
9654
+ const formattedDate = formatCurrentDate(timezone);
9655
+ if (timezone === "UTC") {
9656
+ return `Current Date: ${formattedDate}`;
9657
+ }
9658
+ const utcDate = formatCurrentDate("UTC");
9659
+ return `Current Date: ${formattedDate} (UTC: ${utcDate})`;
9660
+ }
9661
+ function createDateMiddleware(options = {}) {
9662
+ const timezone = options.timezone || "UTC";
9663
+ const dateContext = generateDateContext(timezone);
9664
+ return createMiddleware12({
9665
+ name: "DateMiddleware",
9666
+ tools: [
9667
+ tool46(
9668
+ async () => {
9669
+ const now = /* @__PURE__ */ new Date();
9670
+ let validTimezone = timezone;
9671
+ try {
9672
+ Intl.DateTimeFormat(void 0, { timeZone: timezone });
9673
+ } catch {
9674
+ validTimezone = "UTC";
9675
+ }
9676
+ const localTimeOptions = {
9677
+ timeZone: validTimezone,
9678
+ year: "numeric",
9679
+ month: "2-digit",
9680
+ day: "2-digit",
9681
+ hour: "2-digit",
9682
+ minute: "2-digit",
9683
+ second: "2-digit",
9684
+ hour12: false
9685
+ };
9686
+ const localTime = new Intl.DateTimeFormat("en-US", localTimeOptions).format(now);
9687
+ return JSON.stringify({
9688
+ local_time: `${localTime} (${validTimezone})`,
9689
+ iso_date: now.toISOString().split("T")[0],
9690
+ timestamp: now.toISOString(),
9691
+ timezone: validTimezone
9692
+ });
9693
+ },
9694
+ {
9695
+ name: "get_current_date_time",
9696
+ description: "Get the exact current date and time at the moment of invocation. Use this when the user asks about the current time (e.g., 'what time is it', '\u51E0\u70B9\u4E86', '\u73B0\u5728\u51E0\u70B9'), or when you need to know the precise time for scheduling, deadlines, or time-sensitive operations.",
9697
+ schema: z47.object({})
9698
+ }
9699
+ )
9700
+ ],
9701
+ wrapModelCall: async (request, handler) => {
9702
+ const currentSystemPrompt = request.systemPrompt || "";
9703
+ const newSystemPrompt = currentSystemPrompt ? `${dateContext}
9704
+
9705
+ ${currentSystemPrompt}` : dateContext;
9706
+ return handler({
9707
+ ...request,
9708
+ systemPrompt: newSystemPrompt
9709
+ });
9710
+ }
9711
+ });
9712
+ }
9713
+
9714
+ // src/agent_lattice/builders/commonMiddleware.ts
9715
+ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
9716
+ const middlewares = [];
9717
+ middlewares.push(createUnknownToolHandlerMiddleware());
9718
+ middlewares.push(createModelSelectorMiddleware());
9719
+ const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
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
+ }
9727
+ }
9728
+ for (const config of middlewareConfigs) {
9729
+ if (!config.enabled || config.type === "filesystem") continue;
9730
+ switch (config.type) {
9731
+ case "code_eval":
9732
+ middlewares.push(createCodeEvalMiddleware(config.config));
9733
+ break;
9734
+ case "browser":
9735
+ middlewares.push(createBrowserMiddleware(config.config));
9736
+ break;
9737
+ case "sql":
9738
+ {
9739
+ const sqlConfig = config.config;
9740
+ if (sqlConfig.databaseKeys && sqlConfig.databaseKeys.length > 0) {
9741
+ const databaseConfigs = global.__DATABASE_CONFIGS__ || [];
9742
+ const descriptions = {};
9743
+ for (const db of databaseConfigs) {
9744
+ if (db.key && sqlConfig.databaseKeys.includes(db.key)) {
9745
+ descriptions[db.key] = db.description || db.name || "";
9746
+ }
9747
+ }
9748
+ middlewares.push(createSqlMiddleware({
9749
+ databaseKeys: sqlConfig.databaseKeys,
9750
+ databaseDescriptions: descriptions
9751
+ }));
9752
+ }
9753
+ }
9754
+ break;
9755
+ case "skill":
9756
+ middlewares.push(createSkillMiddleware(config.config));
9757
+ break;
9758
+ case "metrics":
9759
+ {
9760
+ const metricsConfig = config.config;
9761
+ if (metricsConfig.connectAll || metricsConfig.serverKeys && metricsConfig.serverKeys.length > 0) {
9762
+ middlewares.push(createMetricsMiddleware(metricsConfig));
9763
+ }
9764
+ }
9765
+ break;
9766
+ case "ask_user_to_clarify":
9767
+ middlewares.push(createAskUserClarifyMiddleware());
9768
+ break;
9769
+ case "widget":
9770
+ middlewares.push(createWidgetMiddleware());
9771
+ break;
9772
+ case "claw":
9773
+ if (filesystemBackend) {
9774
+ const clawMiddlewareConfig = config.config;
9775
+ middlewares.push(createClawMiddleware({
9776
+ backend: filesystemBackend,
9777
+ injectBootstrapFiles: clawMiddlewareConfig.injectBootstrapFiles ?? true,
9778
+ bootstrapFiles: clawMiddlewareConfig.bootstrapFiles ?? {}
9779
+ }));
9780
+ } else {
9781
+ console.warn("[claw middleware] Filesystem backend not available. Claw middleware requires filesystem backend to function.");
9782
+ }
9783
+ break;
9784
+ case "date":
9785
+ middlewares.push(createDateMiddleware(config.config));
9786
+ break;
9787
+ }
9788
+ }
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
+ };
9772
10246
 
9773
- // src/agent_lattice/builders/commonMiddleware.ts
9774
- async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
9775
- const middlewares = [];
9776
- middlewares.push(createModelSelectorMiddleware());
10247
+ // src/agent_lattice/builders/filesystemBackend.ts
10248
+ function createFilesystemBackendFactory(middlewareConfigs, defualtRootLevel = "project", routesLevelConfig = {
10249
+ "/agent/": "agent"
10250
+ //默认配置 agent目录就是agent级别的
10251
+ }) {
9777
10252
  const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
9778
- if (filesystemConfig?.enabled && filesystemBackend) {
9779
- const options = { backend: filesystemBackend };
9780
- middlewares.push(createFilesystemMiddleware(options));
10253
+ if (!filesystemConfig || !filesystemConfig.enabled) {
10254
+ return void 0;
9781
10255
  }
9782
- for (const config of middlewareConfigs) {
9783
- if (!config.enabled || config.type === "filesystem") continue;
9784
- switch (config.type) {
9785
- case "code_eval":
9786
- middlewares.push(createCodeEvalMiddleware(config.config));
9787
- break;
9788
- case "browser":
9789
- middlewares.push(createBrowserMiddleware(config.config));
9790
- break;
9791
- case "sql":
9792
- {
9793
- const sqlConfig = config.config;
9794
- if (sqlConfig.databaseKeys && sqlConfig.databaseKeys.length > 0) {
9795
- const databaseConfigs = global.__DATABASE_CONFIGS__ || [];
9796
- const descriptions = {};
9797
- for (const db of databaseConfigs) {
9798
- if (db.key && sqlConfig.databaseKeys.includes(db.key)) {
9799
- descriptions[db.key] = db.description || db.name || "";
9800
- }
9801
- }
9802
- middlewares.push(createSqlMiddleware({
9803
- databaseKeys: sqlConfig.databaseKeys,
9804
- databaseDescriptions: descriptions
9805
- }));
9806
- }
9807
- }
9808
- break;
9809
- case "skill":
9810
- middlewares.push(createSkillMiddleware(config.config));
9811
- break;
9812
- case "metrics":
9813
- {
9814
- const metricsConfig = config.config;
9815
- if (metricsConfig.connectAll || metricsConfig.serverKeys && metricsConfig.serverKeys.length > 0) {
9816
- middlewares.push(createMetricsMiddleware(metricsConfig));
9817
- }
9818
- }
9819
- break;
9820
- case "ask_user_to_clarify":
9821
- middlewares.push(createAskUserClarifyMiddleware());
9822
- break;
9823
- case "widget":
9824
- middlewares.push(createWidgetMiddleware());
9825
- break;
9826
- case "claw":
9827
- if (filesystemBackend) {
9828
- const clawConfig = config.config;
9829
- middlewares.push(createClawMiddleware({
9830
- backend: filesystemBackend,
9831
- injectBootstrapFiles: clawConfig.injectBootstrapFiles ?? true,
9832
- bootstrapFiles: clawConfig.bootstrapFiles ?? {}
9833
- }));
9834
- }
9835
- break;
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";
9836
10264
  }
9837
- }
9838
- return middlewares;
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}`;
10275
+ }
10276
+ return workingDirectory;
10277
+ };
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
+ };
9839
10295
  }
9840
10296
 
9841
10297
  // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
9842
10298
  var ReActAgentGraphBuilder = class {
9843
- createFilesystemBackendFactory(middlewareConfigs, agentLattice) {
9844
- const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
9845
- if (!filesystemConfig || !filesystemConfig.enabled) {
9846
- return void 0;
9847
- }
9848
- const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
9849
- const agentTenantId = agentLattice.config.tenantId;
9850
- return async (stateAndStore) => {
9851
- const { tenantId: runtimeTenantId, workspaceId, projectId } = stateAndStore;
9852
- const tenantId = runtimeTenantId || agentTenantId;
9853
- let sandboxName = "global";
9854
- if (isolatedLevel === "agent") {
9855
- sandboxName = "agent";
9856
- } else if (isolatedLevel === "thread") {
9857
- sandboxName = "thread";
9858
- }
9859
- const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
9860
- if (!sandboxManager) {
9861
- throw new Error("Sandbox manager not found");
9862
- }
9863
- let workingDirectory = "/";
9864
- if (workspaceId && projectId) {
9865
- if (tenantId) {
9866
- workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
9867
- } else {
9868
- workingDirectory = `/${workspaceId}/${projectId}`;
9869
- }
9870
- }
9871
- return new SandboxFilesystem({
9872
- sandboxInstance: await sandboxManager.createSandbox(sandboxName),
9873
- workingDirectory
9874
- });
9875
- };
9876
- }
9877
10299
  async createMiddlewares(middlewareConfigs) {
9878
10300
  return await createCommonMiddlewares(middlewareConfigs);
9879
10301
  }
@@ -9886,12 +10308,12 @@ var ReActAgentGraphBuilder = class {
9886
10308
  */
9887
10309
  async build(agentLattice, params) {
9888
10310
  const tools = params.tools.map((t) => {
9889
- const tool50 = getToolClient(t.key);
9890
- return tool50;
9891
- }).filter((tool50) => tool50 !== void 0);
10311
+ const tool51 = getToolClient(t.key);
10312
+ return tool51;
10313
+ }).filter((tool51) => tool51 !== void 0);
9892
10314
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
9893
10315
  const middlewareConfigs = params.middleware || [];
9894
- const filesystemBackend = this.createFilesystemBackendFactory(middlewareConfigs, agentLattice);
10316
+ const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
9895
10317
  const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend);
9896
10318
  return createAgent({
9897
10319
  model: params.model,
@@ -9914,12 +10336,12 @@ import {
9914
10336
  } from "langchain";
9915
10337
 
9916
10338
  // src/deep_agent_new/middleware/subagents.ts
9917
- import { z as z47 } from "zod/v3";
10339
+ import { z as z48 } from "zod/v3";
9918
10340
  import {
9919
- createMiddleware as createMiddleware11,
10341
+ createMiddleware as createMiddleware13,
9920
10342
  createAgent as createAgent2,
9921
- tool as tool46,
9922
- ToolMessage as ToolMessage3,
10343
+ tool as tool47,
10344
+ ToolMessage as ToolMessage4,
9923
10345
  humanInTheLoopMiddleware
9924
10346
  } from "langchain";
9925
10347
  import { Command as Command2, getCurrentTaskInput as getCurrentTaskInput2, GraphInterrupt as GraphInterrupt3 } from "@langchain/langgraph";
@@ -10490,7 +10912,7 @@ function returnCommandWithStateUpdate(result, toolCallId) {
10490
10912
  update: {
10491
10913
  ...stateUpdate,
10492
10914
  messages: [
10493
- new ToolMessage3({
10915
+ new ToolMessage4({
10494
10916
  content: lastMessage?.content || "Task Failed to complete",
10495
10917
  tool_call_id: toolCallId,
10496
10918
  name: "task"
@@ -10572,7 +10994,7 @@ function createTaskTool(options) {
10572
10994
  generalPurposeAgent
10573
10995
  });
10574
10996
  const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
10575
- return tool46(
10997
+ return tool47(
10576
10998
  async (input, config) => {
10577
10999
  const { description, subagent_type } = input;
10578
11000
  let assistant_id = subagent_type;
@@ -10626,7 +11048,7 @@ function createTaskTool(options) {
10626
11048
  return new Command2({
10627
11049
  update: {
10628
11050
  messages: [
10629
- new ToolMessage3({
11051
+ new ToolMessage4({
10630
11052
  content: error instanceof Error ? error.message : "Task Failed to complete",
10631
11053
  tool_call_id: config.toolCall.id,
10632
11054
  name: "task"
@@ -10639,9 +11061,9 @@ function createTaskTool(options) {
10639
11061
  {
10640
11062
  name: "task",
10641
11063
  description: finalTaskDescription,
10642
- schema: z47.object({
10643
- description: z47.string().describe("The task to execute with the selected agent"),
10644
- subagent_type: z47.string().describe(
11064
+ schema: z48.object({
11065
+ description: z48.string().describe("The task to execute with the selected agent"),
11066
+ subagent_type: z48.string().describe(
10645
11067
  `Name of the agent to use. Available: ${Object.keys(
10646
11068
  subagentGraphs
10647
11069
  ).join(", ")}`
@@ -10670,7 +11092,7 @@ function createSubAgentMiddleware(options) {
10670
11092
  generalPurposeAgent,
10671
11093
  taskDescription
10672
11094
  });
10673
- return createMiddleware11({
11095
+ return createMiddleware13({
10674
11096
  name: "subAgentMiddleware",
10675
11097
  tools: [taskTool],
10676
11098
  wrapModelCall: async (request, handler) => {
@@ -10691,14 +11113,14 @@ ${systemPrompt}` : systemPrompt;
10691
11113
 
10692
11114
  // src/deep_agent_new/middleware/patch_tool_calls.ts
10693
11115
  import {
10694
- createMiddleware as createMiddleware12,
10695
- ToolMessage as ToolMessage4,
10696
- AIMessage as AIMessage2
11116
+ createMiddleware as createMiddleware14,
11117
+ ToolMessage as ToolMessage5,
11118
+ AIMessage as AIMessage3
10697
11119
  } from "langchain";
10698
11120
  import { RemoveMessage } from "@langchain/core/messages";
10699
11121
  import { REMOVE_ALL_MESSAGES } from "@langchain/langgraph";
10700
11122
  function createPatchToolCallsMiddleware() {
10701
- return createMiddleware12({
11123
+ return createMiddleware14({
10702
11124
  name: "patchToolCallsMiddleware",
10703
11125
  beforeAgent: async (state) => {
10704
11126
  const messages = state.messages;
@@ -10709,15 +11131,15 @@ function createPatchToolCallsMiddleware() {
10709
11131
  for (let i = 0; i < messages.length; i++) {
10710
11132
  const msg = messages[i];
10711
11133
  patchedMessages.push(msg);
10712
- if (AIMessage2.isInstance(msg) && msg.tool_calls != null) {
11134
+ if (AIMessage3.isInstance(msg) && msg.tool_calls != null) {
10713
11135
  for (const toolCall of msg.tool_calls) {
10714
11136
  const correspondingToolMsg = messages.slice(i).find(
10715
- (m) => ToolMessage4.isInstance(m) && m.tool_call_id === toolCall.id
11137
+ (m) => ToolMessage5.isInstance(m) && m.tool_call_id === toolCall.id
10716
11138
  );
10717
11139
  if (!correspondingToolMsg) {
10718
11140
  const toolMsg = `Tool call ${toolCall.name} with id ${toolCall.id} was cancelled - another message came in before it could be completed.`;
10719
11141
  patchedMessages.push(
10720
- new ToolMessage4({
11142
+ new ToolMessage5({
10721
11143
  content: toolMsg,
10722
11144
  name: toolCall.name,
10723
11145
  tool_call_id: toolCall.id
@@ -11462,261 +11884,81 @@ var FilesystemBackend = class {
11462
11884
  virtPath = fp;
11463
11885
  }
11464
11886
  if (!results[virtPath]) {
11465
- results[virtPath] = [];
11466
- }
11467
- results[virtPath].push([i + 1, line]);
11468
- }
11469
- }
11470
- } catch {
11471
- continue;
11472
- }
11473
- }
11474
- return results;
11475
- }
11476
- /**
11477
- * Structured glob matching returning FileInfo objects.
11478
- */
11479
- async globInfo(pattern, searchPath = "/") {
11480
- if (pattern.startsWith("/")) {
11481
- pattern = pattern.substring(1);
11482
- }
11483
- const resolvedSearchPath = searchPath === "/" ? this.cwd : this.resolvePath(searchPath);
11484
- try {
11485
- const stat3 = await fs2.stat(resolvedSearchPath);
11486
- if (!stat3.isDirectory()) {
11487
- return [];
11488
- }
11489
- } catch {
11490
- return [];
11491
- }
11492
- const results = [];
11493
- try {
11494
- const matches = await fg(pattern, {
11495
- cwd: resolvedSearchPath,
11496
- absolute: true,
11497
- onlyFiles: true,
11498
- dot: true
11499
- });
11500
- for (const matchedPath of matches) {
11501
- try {
11502
- const stat3 = await fs2.stat(matchedPath);
11503
- if (!stat3.isFile()) continue;
11504
- const normalizedPath = matchedPath.split("/").join(path4.sep);
11505
- if (!this.virtualMode) {
11506
- results.push({
11507
- path: normalizedPath,
11508
- is_dir: false,
11509
- size: stat3.size,
11510
- modified_at: stat3.mtime.toISOString()
11511
- });
11512
- } else {
11513
- const cwdStr = this.cwd.endsWith(path4.sep) ? this.cwd : this.cwd + path4.sep;
11514
- let relativePath;
11515
- if (normalizedPath.startsWith(cwdStr)) {
11516
- relativePath = normalizedPath.substring(cwdStr.length);
11517
- } else if (normalizedPath.startsWith(this.cwd)) {
11518
- relativePath = normalizedPath.substring(this.cwd.length).replace(/^[/\\]/, "");
11519
- } else {
11520
- relativePath = normalizedPath;
11521
- }
11522
- relativePath = relativePath.split(path4.sep).join("/");
11523
- const virt = "/" + relativePath;
11524
- results.push({
11525
- path: virt,
11526
- is_dir: false,
11527
- size: stat3.size,
11528
- modified_at: stat3.mtime.toISOString()
11529
- });
11530
- }
11531
- } catch {
11532
- continue;
11533
- }
11534
- }
11535
- } catch {
11536
- }
11537
- results.sort((a, b) => a.path.localeCompare(b.path));
11538
- return results;
11539
- }
11540
- };
11541
-
11542
- // src/deep_agent_new/backends/composite.ts
11543
- var CompositeBackend = class {
11544
- constructor(defaultBackend, routes) {
11545
- this.default = defaultBackend;
11546
- this.routes = routes;
11547
- this.sortedRoutes = Object.entries(routes).sort(
11548
- (a, b) => b[0].length - a[0].length
11549
- );
11550
- }
11551
- /**
11552
- * Determine which backend handles this key and strip prefix.
11553
- *
11554
- * @param key - Original file path
11555
- * @returns Tuple of [backend, stripped_key] where stripped_key has the route
11556
- * prefix removed (but keeps leading slash).
11557
- */
11558
- getBackendAndKey(key) {
11559
- for (const [prefix, backend] of this.sortedRoutes) {
11560
- if (key.startsWith(prefix)) {
11561
- const suffix = key.substring(prefix.length);
11562
- const strippedKey = suffix ? "/" + suffix : "/";
11563
- return [backend, strippedKey];
11564
- }
11565
- }
11566
- return [this.default, key];
11567
- }
11568
- /**
11569
- * List files and directories in the specified directory (non-recursive).
11570
- *
11571
- * @param path - Absolute path to directory
11572
- * @returns List of FileInfo objects with route prefixes added, for files and directories
11573
- * directly in the directory. Directories have a trailing / in their path and is_dir=true.
11574
- */
11575
- async lsInfo(path5) {
11576
- for (const [routePrefix, backend] of this.sortedRoutes) {
11577
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11578
- const suffix = path5.substring(routePrefix.length);
11579
- const searchPath = suffix ? "/" + suffix : "/";
11580
- const infos = await backend.lsInfo(searchPath);
11581
- const prefixed = [];
11582
- for (const fi of infos) {
11583
- prefixed.push({
11584
- ...fi,
11585
- path: routePrefix.slice(0, -1) + fi.path
11586
- });
11887
+ results[virtPath] = [];
11888
+ }
11889
+ results[virtPath].push([i + 1, line]);
11890
+ }
11587
11891
  }
11588
- return prefixed;
11589
- }
11590
- }
11591
- if (path5 === "/") {
11592
- const results = [];
11593
- const defaultInfos = await this.default.lsInfo(path5);
11594
- results.push(...defaultInfos);
11595
- for (const [routePrefix] of this.sortedRoutes) {
11596
- results.push({
11597
- path: routePrefix,
11598
- is_dir: true,
11599
- size: 0,
11600
- modified_at: ""
11601
- });
11892
+ } catch {
11893
+ continue;
11602
11894
  }
11603
- results.sort((a, b) => a.path.localeCompare(b.path));
11604
- return results;
11605
11895
  }
11606
- return await this.default.lsInfo(path5);
11607
- }
11608
- /**
11609
- * Read file content, routing to appropriate backend.
11610
- *
11611
- * @param filePath - Absolute file path
11612
- * @param offset - Line offset to start reading from (0-indexed)
11613
- * @param limit - Maximum number of lines to read
11614
- * @returns Formatted file content with line numbers, or error message
11615
- */
11616
- async read(filePath, offset = 0, limit = 2e3) {
11617
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11618
- return await backend.read(strippedKey, offset, limit);
11619
- }
11620
- /**
11621
- * Read file content as raw FileData.
11622
- *
11623
- * @param filePath - Absolute file path
11624
- * @returns Raw file content as FileData
11625
- */
11626
- async readRaw(filePath) {
11627
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11628
- return await backend.readRaw(strippedKey);
11896
+ return results;
11629
11897
  }
11630
11898
  /**
11631
- * Structured search results or error string for invalid input.
11899
+ * Structured glob matching returning FileInfo objects.
11632
11900
  */
11633
- async grepRaw(pattern, path5 = "/", glob = null) {
11634
- for (const [routePrefix, backend] of this.sortedRoutes) {
11635
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11636
- const searchPath = path5.substring(routePrefix.length - 1);
11637
- const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
11638
- if (typeof raw === "string") {
11639
- return raw;
11640
- }
11641
- return raw.map((m) => ({
11642
- ...m,
11643
- path: routePrefix.slice(0, -1) + m.path
11644
- }));
11645
- }
11646
- }
11647
- const allMatches = [];
11648
- const rawDefault = await this.default.grepRaw(pattern, path5, glob);
11649
- if (typeof rawDefault === "string") {
11650
- return rawDefault;
11901
+ async globInfo(pattern, searchPath = "/") {
11902
+ if (pattern.startsWith("/")) {
11903
+ pattern = pattern.substring(1);
11651
11904
  }
11652
- allMatches.push(...rawDefault);
11653
- for (const [routePrefix, backend] of Object.entries(this.routes)) {
11654
- const raw = await backend.grepRaw(pattern, "/", glob);
11655
- if (typeof raw === "string") {
11656
- return raw;
11905
+ const resolvedSearchPath = searchPath === "/" ? this.cwd : this.resolvePath(searchPath);
11906
+ try {
11907
+ const stat3 = await fs2.stat(resolvedSearchPath);
11908
+ if (!stat3.isDirectory()) {
11909
+ return [];
11657
11910
  }
11658
- allMatches.push(
11659
- ...raw.map((m) => ({
11660
- ...m,
11661
- path: routePrefix.slice(0, -1) + m.path
11662
- }))
11663
- );
11911
+ } catch {
11912
+ return [];
11664
11913
  }
11665
- return allMatches;
11666
- }
11667
- /**
11668
- * Structured glob matching returning FileInfo objects.
11669
- */
11670
- async globInfo(pattern, path5 = "/") {
11671
11914
  const results = [];
11672
- for (const [routePrefix, backend] of this.sortedRoutes) {
11673
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11674
- const searchPath = path5.substring(routePrefix.length - 1);
11675
- const infos = await backend.globInfo(pattern, searchPath || "/");
11676
- return infos.map((fi) => ({
11677
- ...fi,
11678
- path: routePrefix.slice(0, -1) + fi.path
11679
- }));
11915
+ try {
11916
+ const matches = await fg(pattern, {
11917
+ cwd: resolvedSearchPath,
11918
+ absolute: true,
11919
+ onlyFiles: true,
11920
+ dot: true
11921
+ });
11922
+ for (const matchedPath of matches) {
11923
+ try {
11924
+ const stat3 = await fs2.stat(matchedPath);
11925
+ if (!stat3.isFile()) continue;
11926
+ const normalizedPath = matchedPath.split("/").join(path4.sep);
11927
+ if (!this.virtualMode) {
11928
+ results.push({
11929
+ path: normalizedPath,
11930
+ is_dir: false,
11931
+ size: stat3.size,
11932
+ modified_at: stat3.mtime.toISOString()
11933
+ });
11934
+ } else {
11935
+ const cwdStr = this.cwd.endsWith(path4.sep) ? this.cwd : this.cwd + path4.sep;
11936
+ let relativePath;
11937
+ if (normalizedPath.startsWith(cwdStr)) {
11938
+ relativePath = normalizedPath.substring(cwdStr.length);
11939
+ } else if (normalizedPath.startsWith(this.cwd)) {
11940
+ relativePath = normalizedPath.substring(this.cwd.length).replace(/^[/\\]/, "");
11941
+ } else {
11942
+ relativePath = normalizedPath;
11943
+ }
11944
+ relativePath = relativePath.split(path4.sep).join("/");
11945
+ const virt = "/" + relativePath;
11946
+ results.push({
11947
+ path: virt,
11948
+ is_dir: false,
11949
+ size: stat3.size,
11950
+ modified_at: stat3.mtime.toISOString()
11951
+ });
11952
+ }
11953
+ } catch {
11954
+ continue;
11955
+ }
11680
11956
  }
11681
- }
11682
- const defaultInfos = await this.default.globInfo(pattern, path5);
11683
- results.push(...defaultInfos);
11684
- for (const [routePrefix, backend] of Object.entries(this.routes)) {
11685
- const infos = await backend.globInfo(pattern, "/");
11686
- results.push(
11687
- ...infos.map((fi) => ({
11688
- ...fi,
11689
- path: routePrefix.slice(0, -1) + fi.path
11690
- }))
11691
- );
11957
+ } catch {
11692
11958
  }
11693
11959
  results.sort((a, b) => a.path.localeCompare(b.path));
11694
11960
  return results;
11695
11961
  }
11696
- /**
11697
- * Create a new file, routing to appropriate backend.
11698
- *
11699
- * @param filePath - Absolute file path
11700
- * @param content - File content as string
11701
- * @returns WriteResult with path or error
11702
- */
11703
- async write(filePath, content) {
11704
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11705
- return await backend.write(strippedKey, content);
11706
- }
11707
- /**
11708
- * Edit a file, routing to appropriate backend.
11709
- *
11710
- * @param filePath - Absolute file path
11711
- * @param oldString - String to find and replace
11712
- * @param newString - Replacement string
11713
- * @param replaceAll - If true, replace all occurrences
11714
- * @returns EditResult with path, occurrences, or error
11715
- */
11716
- async edit(filePath, oldString, newString, replaceAll = false) {
11717
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11718
- return await backend.edit(strippedKey, oldString, newString, replaceAll);
11719
- }
11720
11962
  };
11721
11963
 
11722
11964
  // src/deep_agent_new/backends/memory.ts
@@ -11834,8 +12076,8 @@ var MemoryBackend = class {
11834
12076
 
11835
12077
  // src/deep_agent_new/middleware/todos.ts
11836
12078
  import { Command as Command3 } from "@langchain/langgraph";
11837
- import { z as z48 } from "zod";
11838
- import { createMiddleware as createMiddleware13, tool as tool47, ToolMessage as ToolMessage5 } from "langchain";
12079
+ import { z as z49 } from "zod";
12080
+ import { createMiddleware as createMiddleware15, tool as tool48, ToolMessage as ToolMessage6 } from "langchain";
11839
12081
  var WRITE_TODOS_DESCRIPTION = `Use this tool to create and manage a structured task list for your current work session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
11840
12082
  It also helps the user understand the progress of the task and overall progress of their requests.
11841
12083
  Only use this tool if you think it will be helpful in staying organized. If the user's request is trivial and takes less than 3 steps, it is better to NOT use this tool and just do the taks directly.
@@ -12062,20 +12304,20 @@ Writing todos takes time and tokens, use it when it is helpful for managing comp
12062
12304
  ## Important To-Do List Usage Notes to Remember
12063
12305
  - The \`write_todos\` tool should never be called multiple times in parallel.
12064
12306
  - Don't be afraid to revise the To-Do list as you go. New information may reveal new tasks that need to be done, or old tasks that are irrelevant.`;
12065
- var TodoStatus = z48.enum(["pending", "in_progress", "completed"]).describe("Status of the todo");
12066
- var TodoSchema = z48.object({
12067
- content: z48.string().describe("Content of the todo item"),
12307
+ var TodoStatus = z49.enum(["pending", "in_progress", "completed"]).describe("Status of the todo");
12308
+ var TodoSchema = z49.object({
12309
+ content: z49.string().describe("Content of the todo item"),
12068
12310
  status: TodoStatus
12069
12311
  });
12070
- var stateSchema = z48.object({ todos: z48.array(TodoSchema).default([]) });
12312
+ var stateSchema = z49.object({ todos: z49.array(TodoSchema).default([]) });
12071
12313
  function todoListMiddleware(options) {
12072
- const writeTodos = tool47(
12314
+ const writeTodos = tool48(
12073
12315
  ({ todos }, config) => {
12074
12316
  return new Command3({
12075
12317
  update: {
12076
12318
  todos,
12077
12319
  messages: [
12078
- new ToolMessage5({
12320
+ new ToolMessage6({
12079
12321
  content: genUIMarkdown("todo_list", todos),
12080
12322
  tool_call_id: config.toolCall?.id
12081
12323
  })
@@ -12086,12 +12328,12 @@ function todoListMiddleware(options) {
12086
12328
  {
12087
12329
  name: "write_todos",
12088
12330
  description: options?.toolDescription ?? WRITE_TODOS_DESCRIPTION,
12089
- schema: z48.object({
12090
- todos: z48.array(TodoSchema).describe("List of todo items to update")
12331
+ schema: z49.object({
12332
+ todos: z49.array(TodoSchema).describe("List of todo items to update")
12091
12333
  })
12092
12334
  }
12093
12335
  );
12094
- return createMiddleware13({
12336
+ return createMiddleware15({
12095
12337
  name: "todoListMiddleware",
12096
12338
  stateSchema,
12097
12339
  tools: [writeTodos],
@@ -12190,50 +12432,8 @@ ${BASE_PROMPT}` : BASE_PROMPT;
12190
12432
  });
12191
12433
  }
12192
12434
 
12193
- // src/agent_lattice/builders/filesystemBackend.ts
12194
- function createFilesystemBackendFactory(middlewareConfigs) {
12195
- const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
12196
- if (!filesystemConfig || !filesystemConfig.enabled) {
12197
- return void 0;
12198
- }
12199
- const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
12200
- return async (stateAndStore) => {
12201
- const { tenantId, workspaceId, projectId } = stateAndStore;
12202
- let sandboxName = "global";
12203
- if (isolatedLevel === "agent") {
12204
- sandboxName = "agent";
12205
- } else if (isolatedLevel === "thread") {
12206
- sandboxName = "thread";
12207
- }
12208
- const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
12209
- if (!sandboxManager) {
12210
- throw new Error("Sandbox manager not found");
12211
- }
12212
- let workingDirectory = "/";
12213
- if (workspaceId && projectId) {
12214
- if (tenantId) {
12215
- workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
12216
- } else {
12217
- workingDirectory = `/workspaces/${workspaceId}/${projectId}`;
12218
- }
12219
- }
12220
- const sandboxfs = new SandboxFilesystem({
12221
- sandboxInstance: await sandboxManager.createSandbox(sandboxName),
12222
- workingDirectory
12223
- });
12224
- const compositeBackend = new CompositeBackend(sandboxfs, {});
12225
- return compositeBackend;
12226
- };
12227
- }
12228
-
12229
12435
  // src/agent_lattice/builders/DeepAgentGraphBuilder.ts
12230
12436
  var DeepAgentGraphBuilder = class {
12231
- /**
12232
- * 根据 middleware 配置创建 middlewares
12233
- */
12234
- async createMiddlewares(middlewareConfigs) {
12235
- return await createCommonMiddlewares(middlewareConfigs);
12236
- }
12237
12437
  /**
12238
12438
  * 构建Deep Agent Graph
12239
12439
  *
@@ -12245,7 +12445,7 @@ var DeepAgentGraphBuilder = class {
12245
12445
  const tools = params.tools.map((t) => {
12246
12446
  const toolClient = getToolClient(t.key);
12247
12447
  return toolClient;
12248
- }).filter((tool50) => tool50 !== void 0);
12448
+ }).filter((tool51) => tool51 !== void 0);
12249
12449
  const subagents = await Promise.all(params.subAgents.map(async (sa) => {
12250
12450
  if (sa.client) {
12251
12451
  return {
@@ -12268,7 +12468,7 @@ var DeepAgentGraphBuilder = class {
12268
12468
  }));
12269
12469
  const middlewareConfigs = params.middleware || [];
12270
12470
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
12271
- const middlewares = await this.createMiddlewares(middlewareConfigs);
12471
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true);
12272
12472
  const deepAgent = createDeepAgent({
12273
12473
  tools,
12274
12474
  model: params.model,
@@ -12285,7 +12485,7 @@ var DeepAgentGraphBuilder = class {
12285
12485
  };
12286
12486
 
12287
12487
  // src/agent_team/agent_team.ts
12288
- import { z as z51 } from "zod/v3";
12488
+ import { z as z52 } from "zod/v3";
12289
12489
  import { createAgent as createAgent5 } from "langchain";
12290
12490
 
12291
12491
  // src/agent_team/types.ts
@@ -12721,14 +12921,14 @@ var InMemoryMailboxStore = class {
12721
12921
  };
12722
12922
 
12723
12923
  // src/agent_team/middleware/team.ts
12724
- import { z as z50 } from "zod/v3";
12725
- import { createMiddleware as createMiddleware14, createAgent as createAgent4, tool as tool49, ToolMessage as ToolMessage7 } from "langchain";
12924
+ import { z as z51 } from "zod/v3";
12925
+ import { createMiddleware as createMiddleware16, createAgent as createAgent4, tool as tool50, ToolMessage as ToolMessage8 } from "langchain";
12726
12926
  import { Command as Command5, getCurrentTaskInput as getCurrentTaskInput3 } from "@langchain/langgraph";
12727
12927
  import { v4 as uuidv4 } from "uuid";
12728
12928
 
12729
12929
  // src/agent_team/middleware/teammate_tools.ts
12730
- import { z as z49 } from "zod/v3";
12731
- import { tool as tool48, ToolMessage as ToolMessage6 } from "langchain";
12930
+ import { z as z50 } from "zod/v3";
12931
+ import { tool as tool49, ToolMessage as ToolMessage7 } from "langchain";
12732
12932
  import { Command as Command4 } from "@langchain/langgraph";
12733
12933
 
12734
12934
  // src/agent_team/middleware/formatMessages.ts
@@ -12753,7 +12953,7 @@ ${meta}${body}`;
12753
12953
  // src/agent_team/middleware/teammate_tools.ts
12754
12954
  function createTeammateTools(options) {
12755
12955
  const { teamId, agentId, taskListStore, mailboxStore } = options;
12756
- const claimTaskTool = tool48(
12956
+ const claimTaskTool = tool49(
12757
12957
  async (input) => {
12758
12958
  const task = await taskListStore.claimTaskById(
12759
12959
  teamId,
@@ -12778,12 +12978,12 @@ function createTeammateTools(options) {
12778
12978
  {
12779
12979
  name: "claim_task",
12780
12980
  description: "Pick a task to work on by task_id. Use check_tasks first to see all tasks; then call this with the task_id you choose. The task's assignee is set to you and you should focus on that task until you complete_task or fail_task it.",
12781
- schema: z49.object({
12782
- task_id: z49.string().describe("ID of the task to claim (e.g. task-01). Use check_tasks to see IDs.")
12981
+ schema: z50.object({
12982
+ task_id: z50.string().describe("ID of the task to claim (e.g. task-01). Use check_tasks to see IDs.")
12783
12983
  })
12784
12984
  }
12785
12985
  );
12786
- const completeTaskTool = tool48(
12986
+ const completeTaskTool = tool49(
12787
12987
  async (input) => {
12788
12988
  const task = await taskListStore.completeTask(
12789
12989
  teamId,
@@ -12804,13 +13004,13 @@ function createTeammateTools(options) {
12804
13004
  {
12805
13005
  name: "complete_task",
12806
13006
  description: "Mark a claimed task as completed with a result summary. Call this after you have finished working on a task.",
12807
- schema: z49.object({
12808
- task_id: z49.string().describe("ID of the task to complete"),
12809
- result: z49.string().describe("Summary of the task result")
13007
+ schema: z50.object({
13008
+ task_id: z50.string().describe("ID of the task to complete"),
13009
+ result: z50.string().describe("Summary of the task result")
12810
13010
  })
12811
13011
  }
12812
13012
  );
12813
- const failTaskTool = tool48(
13013
+ const failTaskTool = tool49(
12814
13014
  async (input) => {
12815
13015
  const task = await taskListStore.failTask(
12816
13016
  teamId,
@@ -12831,13 +13031,13 @@ function createTeammateTools(options) {
12831
13031
  {
12832
13032
  name: "fail_task",
12833
13033
  description: "Mark a claimed task as failed with an error description. Call this if you cannot complete the task.",
12834
- schema: z49.object({
12835
- task_id: z49.string().describe("ID of the task to fail"),
12836
- error: z49.string().describe("Description of why the task failed")
13034
+ schema: z50.object({
13035
+ task_id: z50.string().describe("ID of the task to fail"),
13036
+ error: z50.string().describe("Description of why the task failed")
12837
13037
  })
12838
13038
  }
12839
13039
  );
12840
- const sendMessageTool = tool48(
13040
+ const sendMessageTool = tool49(
12841
13041
  async (input) => {
12842
13042
  await mailboxStore.sendMessage(
12843
13043
  teamId,
@@ -12851,11 +13051,11 @@ function createTeammateTools(options) {
12851
13051
  {
12852
13052
  name: "send_message",
12853
13053
  description: 'Send a message to the team lead or another teammate via the mailbox. Use "team_lead" to message the team lead. Use this to report discoveries, request guidance, or suggest new tasks.',
12854
- schema: z49.object({
12855
- to: z49.string().describe(
13054
+ schema: z50.object({
13055
+ to: z50.string().describe(
12856
13056
  'Recipient agent name (e.g. "team_lead" or a teammate name)'
12857
13057
  ),
12858
- content: z49.string().describe("Message content")
13058
+ content: z50.string().describe("Message content")
12859
13059
  })
12860
13060
  }
12861
13061
  );
@@ -12875,7 +13075,7 @@ function createTeammateTools(options) {
12875
13075
  read: msg.read
12876
13076
  }));
12877
13077
  };
12878
- const readMessagesTool = tool48(
13078
+ const readMessagesTool = tool49(
12879
13079
  async (input, config) => {
12880
13080
  const formatAndMarkAsRead = async (msgs2) => {
12881
13081
  for (const msg of msgs2) {
@@ -12887,7 +13087,7 @@ function createTeammateTools(options) {
12887
13087
  if (msgs.length > 0) {
12888
13088
  const formatted2 = await formatAndMarkAsRead(msgs);
12889
13089
  const relevantMsgs2 = await getRelevantMessagesForState();
12890
- const toolMessage2 = new ToolMessage6({
13090
+ const toolMessage2 = new ToolMessage7({
12891
13091
  content: formatted2,
12892
13092
  tool_call_id: config.toolCall?.id,
12893
13093
  name: "read_messages"
@@ -12912,7 +13112,7 @@ function createTeammateTools(options) {
12912
13112
  });
12913
13113
  const relevantMsgs = await getRelevantMessagesForState();
12914
13114
  if (msgs.length === 0) {
12915
- const toolMessage2 = new ToolMessage6({
13115
+ const toolMessage2 = new ToolMessage7({
12916
13116
  content: "No unread messages.",
12917
13117
  tool_call_id: config.toolCall?.id,
12918
13118
  name: "read_messages"
@@ -12922,7 +13122,7 @@ function createTeammateTools(options) {
12922
13122
  });
12923
13123
  }
12924
13124
  const formatted = await formatAndMarkAsRead(msgs);
12925
- const toolMessage = new ToolMessage6({
13125
+ const toolMessage = new ToolMessage7({
12926
13126
  content: formatted,
12927
13127
  tool_call_id: config.toolCall?.id,
12928
13128
  name: "read_messages"
@@ -12934,10 +13134,10 @@ function createTeammateTools(options) {
12934
13134
  {
12935
13135
  name: "read_messages",
12936
13136
  description: "Read unread messages from the mailbox. Returns immediately if messages exist, otherwise waits for up to 3 minutes for new messages.",
12937
- schema: z49.object({})
13137
+ schema: z50.object({})
12938
13138
  }
12939
13139
  );
12940
- const checkTasksTool = tool48(
13140
+ const checkTasksTool = tool49(
12941
13141
  async () => {
12942
13142
  const tasks = await taskListStore.getAllTasks(teamId);
12943
13143
  return formatTaskSummary(tasks);
@@ -12945,10 +13145,10 @@ function createTeammateTools(options) {
12945
13145
  {
12946
13146
  name: "check_tasks",
12947
13147
  description: "Use this tool to get the current status of all tasks in a team. This is your primary way to monitor task progress.",
12948
- schema: z49.object({})
13148
+ schema: z50.object({})
12949
13149
  }
12950
13150
  );
12951
- const broadcastMessageTool = tool48(
13151
+ const broadcastMessageTool = tool49(
12952
13152
  async (input) => {
12953
13153
  const allAgents = await mailboxStore.getRegisteredAgents(teamId);
12954
13154
  const recipients = allAgents.filter((a) => a !== agentId);
@@ -12967,8 +13167,8 @@ function createTeammateTools(options) {
12967
13167
  {
12968
13168
  name: "broadcast_message",
12969
13169
  description: "Send a message to everyone in the team except yourself. Use this to share updates or information with all teammates and the team lead at once.",
12970
- schema: z49.object({
12971
- content: z49.string().describe("Message content to broadcast to others")
13170
+ schema: z50.object({
13171
+ content: z50.string().describe("Message content to broadcast to others")
12972
13172
  })
12973
13173
  }
12974
13174
  );
@@ -13202,12 +13402,12 @@ async function spawnTeammate(options) {
13202
13402
  function createTeamMiddleware(options) {
13203
13403
  const { teamConfig, taskListStore, mailboxStore, tenantId } = options;
13204
13404
  const defaultModel = teamConfig.model ?? "claude-sonnet-4-5-20250929";
13205
- const createTeamTool = tool49(
13405
+ const createTeamTool = tool50(
13206
13406
  async (input, config) => {
13207
13407
  const state = getCurrentTaskInput3();
13208
13408
  if (state?.team?.teamId) {
13209
13409
  const existingId = state.team.teamId;
13210
- const msg = new ToolMessage7({
13410
+ const msg = new ToolMessage8({
13211
13411
  content: `A team is already active (id: ${existingId}). Use this team_id for \`check_tasks\`, \`read_messages\`, \`add_tasks\`, \`send_message\`, \`assign_task\`, \`set_task_status\`, and \`set_task_dependencies\`. Do not call \`create_team\` again unless you need a fresh team for a new objective.`,
13212
13412
  tool_call_id: config.toolCall?.id,
13213
13413
  name: "create_team"
@@ -13296,7 +13496,7 @@ Teammates are now working in the background. Keep calling \`check_tasks\` and \`
13296
13496
  \`\`\`json
13297
13497
  ${teamJson}
13298
13498
  \`\`\``;
13299
- const toolMessage = new ToolMessage7({
13499
+ const toolMessage = new ToolMessage8({
13300
13500
  content: summary,
13301
13501
  tool_call_id: config.toolCall?.id,
13302
13502
  name: "create_team"
@@ -13357,20 +13557,20 @@ After calling create_team, you MUST:
13357
13557
  2. When messages indicate task changes, call check_tasks to get full task status
13358
13558
  3. Continue until all tasks show "completed" or "failed"
13359
13559
  4. Do NOT assume tasks are done - always verify with check_tasks`,
13360
- schema: z50.object({
13361
- tasks: z50.array(
13362
- z50.object({
13363
- id: z50.string().describe("Task ID in format task-01, task-02, etc."),
13364
- title: z50.string().describe("Short task title"),
13365
- description: z50.string().describe("Detailed task description - what exactly needs to be done"),
13366
- dependencies: z50.array(z50.string()).optional().default([]).describe('Array of task IDs that must complete before this task (e.g. ["task-01"])')
13560
+ schema: z51.object({
13561
+ tasks: z51.array(
13562
+ z51.object({
13563
+ id: z51.string().describe("Task ID in format task-01, task-02, etc."),
13564
+ title: z51.string().describe("Short task title"),
13565
+ description: z51.string().describe("Detailed task description - what exactly needs to be done"),
13566
+ dependencies: z51.array(z51.string()).optional().default([]).describe('Array of task IDs that must complete before this task (e.g. ["task-01"])')
13367
13567
  })
13368
13568
  ).describe("List of tasks for teammates to work on. Each task needs unique ID (task-01, task-02, etc.)."),
13369
- teammates: z50.array(
13370
- z50.object({
13371
- name: z50.string().describe("Teammate name (must match a pre-configured teammate type)"),
13372
- role: z50.string().describe("Role category (e.g. researcher, writer, coder, reviewer)"),
13373
- description: z50.string().describe("What this teammate will focus on - specific instructions for their work")
13569
+ teammates: z51.array(
13570
+ z51.object({
13571
+ name: z51.string().describe("Teammate name (must match a pre-configured teammate type)"),
13572
+ role: z51.string().describe("Role category (e.g. researcher, writer, coder, reviewer)"),
13573
+ description: z51.string().describe("What this teammate will focus on - specific instructions for their work")
13374
13574
  })
13375
13575
  ).describe("Teammate agents to create. Each should have a clear role and focus.")
13376
13576
  })
@@ -13381,7 +13581,7 @@ After calling create_team, you MUST:
13381
13581
  if (state?.team?.teamId) return state.team.teamId;
13382
13582
  throw new Error("No team_id provided and no team in state. Call create_team first.");
13383
13583
  };
13384
- const addTasksTool = tool49(
13584
+ const addTasksTool = tool50(
13385
13585
  async (input, config) => {
13386
13586
  const teamId = resolveTeamId();
13387
13587
  const created = await taskListStore.addTasks(
@@ -13395,7 +13595,7 @@ After calling create_team, you MUST:
13395
13595
  }))
13396
13596
  );
13397
13597
  const summary = created.map((t) => `- ${t.id}: "${t.title}"`).join("\n");
13398
- return new ToolMessage7({
13598
+ return new ToolMessage8({
13399
13599
  content: `Added ${created.length} task(s) to team ${teamId}:
13400
13600
  ${summary}
13401
13601
  Sleeping teammates will wake up and claim these.`,
@@ -13433,33 +13633,33 @@ IMPORTANT: Dependencies
13433
13633
 
13434
13634
  IMPORTANT: Assigning to a specific teammate
13435
13635
  - When you need a particular teammate to do the work, set assignee to that teammate's name (e.g. assignee: "researcher"). They can then claim or see the task as assigned to them.`,
13436
- schema: z50.object({
13437
- tasks: z50.array(
13438
- z50.object({
13439
- id: z50.string().describe("Task ID in format task-01, task-02, etc. Must be unique."),
13440
- title: z50.string().describe("Short task title"),
13441
- description: z50.string().describe("Detailed task description - what needs to be done"),
13442
- assignee: z50.string().optional().describe("Teammate name to assign this task to (use when you need that person to do the work)"),
13443
- dependencies: z50.array(z50.string()).optional().default([]).describe("Array of task IDs that must complete before this task")
13636
+ schema: z51.object({
13637
+ tasks: z51.array(
13638
+ z51.object({
13639
+ id: z51.string().describe("Task ID in format task-01, task-02, etc. Must be unique."),
13640
+ title: z51.string().describe("Short task title"),
13641
+ description: z51.string().describe("Detailed task description - what needs to be done"),
13642
+ assignee: z51.string().optional().describe("Teammate name to assign this task to (use when you need that person to do the work)"),
13643
+ dependencies: z51.array(z51.string()).optional().default([]).describe("Array of task IDs that must complete before this task")
13444
13644
  })
13445
13645
  ).describe("New tasks to add to the team")
13446
13646
  })
13447
13647
  }
13448
13648
  );
13449
- const assignTaskTool = tool49(
13649
+ const assignTaskTool = tool50(
13450
13650
  async (input, config) => {
13451
13651
  const teamId = resolveTeamId();
13452
13652
  const task = await taskListStore.updateTask(teamId, input.task_id, {
13453
13653
  assignee: input.assignee
13454
13654
  });
13455
13655
  if (!task) {
13456
- return new ToolMessage7({
13656
+ return new ToolMessage8({
13457
13657
  content: `Task ${input.task_id} not found in team ${teamId}.`,
13458
13658
  tool_call_id: config.toolCall?.id,
13459
13659
  name: "assign_task"
13460
13660
  });
13461
13661
  }
13462
- return new ToolMessage7({
13662
+ return new ToolMessage8({
13463
13663
  content: `Task "${task.title}" (${task.id}) assigned to ${input.assignee}.`,
13464
13664
  tool_call_id: config.toolCall?.id,
13465
13665
  name: "assign_task"
@@ -13468,26 +13668,26 @@ IMPORTANT: Assigning to a specific teammate
13468
13668
  {
13469
13669
  name: "assign_task",
13470
13670
  description: "Assign a task to a specific teammate. Use when you need to reassign work to a different teammate. Omit team_id to use the active team from state.",
13471
- schema: z50.object({
13472
- task_id: z50.string().describe("Task ID to assign"),
13473
- assignee: z50.string().describe("Teammate name to assign this task to")
13671
+ schema: z51.object({
13672
+ task_id: z51.string().describe("Task ID to assign"),
13673
+ assignee: z51.string().describe("Teammate name to assign this task to")
13474
13674
  })
13475
13675
  }
13476
13676
  );
13477
- const setTaskStatusTool = tool49(
13677
+ const setTaskStatusTool = tool50(
13478
13678
  async (input, config) => {
13479
13679
  const teamId = resolveTeamId();
13480
13680
  const task = await taskListStore.updateTask(teamId, input.task_id, {
13481
13681
  status: input.status
13482
13682
  });
13483
13683
  if (!task) {
13484
- return new ToolMessage7({
13684
+ return new ToolMessage8({
13485
13685
  content: `Task ${input.task_id} not found in team ${teamId}.`,
13486
13686
  tool_call_id: config.toolCall?.id,
13487
13687
  name: "set_task_status"
13488
13688
  });
13489
13689
  }
13490
- return new ToolMessage7({
13690
+ return new ToolMessage8({
13491
13691
  content: `Task "${task.title}" (${task.id}) status set to ${input.status}.`,
13492
13692
  tool_call_id: config.toolCall?.id,
13493
13693
  name: "set_task_status"
@@ -13496,26 +13696,26 @@ IMPORTANT: Assigning to a specific teammate
13496
13696
  {
13497
13697
  name: "set_task_status",
13498
13698
  description: "Set a task's status. Use to reopen a task (set to pending), mark as failed, or correct status. Values: pending, claimed, in_progress, completed, failed. Omit team_id to use the active team from state.",
13499
- schema: z50.object({
13500
- task_id: z50.string().describe("Task ID to update"),
13501
- status: z50.enum(["pending", "claimed", "in_progress", "completed", "failed"]).describe("New status for the task")
13699
+ schema: z51.object({
13700
+ task_id: z51.string().describe("Task ID to update"),
13701
+ status: z51.enum(["pending", "claimed", "in_progress", "completed", "failed"]).describe("New status for the task")
13502
13702
  })
13503
13703
  }
13504
13704
  );
13505
- const setTaskDependenciesTool = tool49(
13705
+ const setTaskDependenciesTool = tool50(
13506
13706
  async (input, config) => {
13507
13707
  const teamId = resolveTeamId();
13508
13708
  const task = await taskListStore.updateTask(teamId, input.task_id, {
13509
13709
  dependencies: input.dependencies
13510
13710
  });
13511
13711
  if (!task) {
13512
- return new ToolMessage7({
13712
+ return new ToolMessage8({
13513
13713
  content: `Task ${input.task_id} not found in team ${teamId}.`,
13514
13714
  tool_call_id: config.toolCall?.id,
13515
13715
  name: "set_task_dependencies"
13516
13716
  });
13517
13717
  }
13518
- return new ToolMessage7({
13718
+ return new ToolMessage8({
13519
13719
  content: `Task "${task.title}" (${task.id}) dependencies set to [${input.dependencies.join(", ")}].`,
13520
13720
  tool_call_id: config.toolCall?.id,
13521
13721
  name: "set_task_dependencies"
@@ -13524,13 +13724,13 @@ IMPORTANT: Assigning to a specific teammate
13524
13724
  {
13525
13725
  name: "set_task_dependencies",
13526
13726
  description: 'Set which task IDs must complete before this task can be claimed. Pass an array of task IDs (e.g. ["task-01", "task-02"]). Use to fix task order or add/remove dependencies. Omit team_id to use the active team from state.',
13527
- schema: z50.object({
13528
- task_id: z50.string().describe("Task ID to update"),
13529
- dependencies: z50.array(z50.string()).describe("Task IDs that must complete before this task can be claimed")
13727
+ schema: z51.object({
13728
+ task_id: z51.string().describe("Task ID to update"),
13729
+ dependencies: z51.array(z51.string()).describe("Task IDs that must complete before this task can be claimed")
13530
13730
  })
13531
13731
  }
13532
13732
  );
13533
- const checkTasksTool = tool49(
13733
+ const checkTasksTool = tool50(
13534
13734
  async (input, config) => {
13535
13735
  const teamId = resolveTeamId();
13536
13736
  const tasks = await taskListStore.getAllTasks(teamId);
@@ -13539,7 +13739,7 @@ IMPORTANT: Assigning to a specific teammate
13539
13739
  update: {
13540
13740
  tasks: tasksSnapshot,
13541
13741
  messages: [
13542
- new ToolMessage7({
13742
+ new ToolMessage8({
13543
13743
  content: formatTaskSummary(tasks),
13544
13744
  tool_call_id: config.toolCall?.id,
13545
13745
  name: "check_tasks"
@@ -13570,12 +13770,12 @@ Task Status Values:
13570
13770
  - in_progress: Teammate is actively working on this task
13571
13771
  - completed: Task finished successfully
13572
13772
  - failed: Task encountered an error`,
13573
- schema: z50.object({
13574
- team_id: z50.string().optional().describe("Team ID (omit to use active team)")
13773
+ schema: z51.object({
13774
+ team_id: z51.string().optional().describe("Team ID (omit to use active team)")
13575
13775
  })
13576
13776
  }
13577
13777
  );
13578
- const sendMessageTool = tool49(
13778
+ const sendMessageTool = tool50(
13579
13779
  async (input, config) => {
13580
13780
  const teamId = resolveTeamId();
13581
13781
  await mailboxStore.sendMessage(
@@ -13585,7 +13785,7 @@ Task Status Values:
13585
13785
  input.content,
13586
13786
  "direct_message" /* DIRECT_MESSAGE */
13587
13787
  );
13588
- return new ToolMessage7({
13788
+ return new ToolMessage8({
13589
13789
  content: `Message sent to ${input.to}.`,
13590
13790
  tool_call_id: config.toolCall?.id,
13591
13791
  name: "send_message"
@@ -13594,13 +13794,13 @@ Task Status Values:
13594
13794
  {
13595
13795
  name: "send_message",
13596
13796
  description: "Send a message to a specific teammate in the team. Omit team_id to use the active team from state.",
13597
- schema: z50.object({
13598
- to: z50.string().describe("Recipient teammate name"),
13599
- content: z50.string().describe("Message content")
13797
+ schema: z51.object({
13798
+ to: z51.string().describe("Recipient teammate name"),
13799
+ content: z51.string().describe("Message content")
13600
13800
  })
13601
13801
  }
13602
13802
  );
13603
- const readMessagesTool = tool49(
13803
+ const readMessagesTool = tool50(
13604
13804
  async (input, config) => {
13605
13805
  const teamId = resolveTeamId();
13606
13806
  const formatAndMarkAsRead = async (msgs2) => {
@@ -13628,7 +13828,7 @@ Task Status Values:
13628
13828
  if (msgs.length > 0) {
13629
13829
  const formatted2 = await formatAndMarkAsRead(msgs);
13630
13830
  const allTeamMessages2 = await getAllTeamMessagesForState();
13631
- const toolMessage2 = new ToolMessage7({
13831
+ const toolMessage2 = new ToolMessage8({
13632
13832
  content: formatted2,
13633
13833
  tool_call_id: config.toolCall?.id,
13634
13834
  name: "read_messages"
@@ -13660,7 +13860,7 @@ Task Status Values:
13660
13860
  );
13661
13861
  const allTeamMessages = await getAllTeamMessagesForState();
13662
13862
  if (msgs.length === 0) {
13663
- const toolMessage2 = new ToolMessage7({
13863
+ const toolMessage2 = new ToolMessage8({
13664
13864
  content: "No unread messages from teammates.",
13665
13865
  tool_call_id: config.toolCall?.id,
13666
13866
  name: "read_messages"
@@ -13670,7 +13870,7 @@ Task Status Values:
13670
13870
  });
13671
13871
  }
13672
13872
  const formatted = await formatAndMarkAsRead(msgs);
13673
- const toolMessage = new ToolMessage7({
13873
+ const toolMessage = new ToolMessage8({
13674
13874
  content: formatted,
13675
13875
  tool_call_id: config.toolCall?.id,
13676
13876
  name: "read_messages"
@@ -13682,12 +13882,12 @@ Task Status Values:
13682
13882
  {
13683
13883
  name: "read_messages",
13684
13884
  description: "Read unread messages from teammates. Returns immediately if messages exist, otherwise waits for up to 3 minutes for new messages.",
13685
- schema: z50.object({
13686
- team_id: z50.string().optional().describe("Team ID (omit to use active team)")
13885
+ schema: z51.object({
13886
+ team_id: z51.string().optional().describe("Team ID (omit to use active team)")
13687
13887
  })
13688
13888
  }
13689
13889
  );
13690
- const disbandTeamTool = tool49(
13890
+ const disbandTeamTool = tool50(
13691
13891
  async (input, config) => {
13692
13892
  const teamId = resolveTeamId();
13693
13893
  await mailboxStore.broadcastMessage(
@@ -13697,7 +13897,7 @@ Task Status Values:
13697
13897
  "shutdown_request" /* SHUTDOWN_REQUEST */
13698
13898
  );
13699
13899
  await new Promise((r) => setTimeout(r, 2e3));
13700
- return new ToolMessage7({
13900
+ return new ToolMessage8({
13701
13901
  content: `Team ${teamId} has been disbanded. All teammates notified and resources cleaned up.`,
13702
13902
  tool_call_id: config.toolCall?.id,
13703
13903
  name: "disband_team"
@@ -13708,7 +13908,7 @@ Task Status Values:
13708
13908
  description: "Disband a team when all work is done. Before calling: (1) Call check_tasks to verify no tasks are still pending/in_progress; (2) if any are, discuss with the team via read_messages and broadcast_message/send_message whether to continue or stop/cancel them; (3) only after alignment (all tasks completed/failed or explicitly stopped), then call this tool. This will: 1) Send a shutdown message to all teammates, 2) Wait briefly for them to clean up, 3) Clear all tasks and messages. Omit team_id to use the active team from state."
13709
13909
  }
13710
13910
  );
13711
- const broadcastMessageTool = tool49(
13911
+ const broadcastMessageTool = tool50(
13712
13912
  async (input, config) => {
13713
13913
  const teamId = resolveTeamId();
13714
13914
  await mailboxStore.broadcastMessage(
@@ -13717,7 +13917,7 @@ Task Status Values:
13717
13917
  input.content,
13718
13918
  "broadcast" /* BROADCAST */
13719
13919
  );
13720
- return new ToolMessage7({
13920
+ return new ToolMessage8({
13721
13921
  content: `Broadcast message sent to all teammates.`,
13722
13922
  tool_call_id: config.toolCall?.id,
13723
13923
  name: "broadcast_message"
@@ -13726,12 +13926,12 @@ Task Status Values:
13726
13926
  {
13727
13927
  name: "broadcast_message",
13728
13928
  description: "Send a message to all teammates at once. Use this to communicate with everyone in the team. Omit team_id to use the active team from state.",
13729
- schema: z50.object({
13730
- content: z50.string().describe("Message content to broadcast to all teammates")
13929
+ schema: z51.object({
13930
+ content: z51.string().describe("Message content to broadcast to all teammates")
13731
13931
  })
13732
13932
  }
13733
13933
  );
13734
- return createMiddleware14({
13934
+ return createMiddleware16({
13735
13935
  name: "teamMiddleware",
13736
13936
  tools: [
13737
13937
  createTeamTool,
@@ -13759,37 +13959,37 @@ ${TEAM_SYSTEM_PROMPT}` : TEAM_SYSTEM_PROMPT;
13759
13959
  }
13760
13960
 
13761
13961
  // src/agent_team/agent_team.ts
13762
- var TeammateInfoSchema = z51.object({
13763
- name: z51.string().describe("Teammate name"),
13764
- role: z51.string().describe("Role category (e.g. research, writing, review)"),
13765
- description: z51.string().describe("What this teammate focuses on")
13962
+ var TeammateInfoSchema = z52.object({
13963
+ name: z52.string().describe("Teammate name"),
13964
+ role: z52.string().describe("Role category (e.g. research, writing, review)"),
13965
+ description: z52.string().describe("What this teammate focuses on")
13766
13966
  });
13767
- var TeamTaskInfoSchema = z51.object({
13768
- id: z51.string(),
13769
- title: z51.string(),
13770
- description: z51.string(),
13771
- status: z51.string().optional()
13967
+ var TeamTaskInfoSchema = z52.object({
13968
+ id: z52.string(),
13969
+ title: z52.string(),
13970
+ description: z52.string(),
13971
+ status: z52.string().optional()
13772
13972
  });
13773
- var MailboxMessageSchema = z51.object({
13774
- id: z51.string().describe("Unique message identifier"),
13775
- from: z51.string().describe("Sender agent name"),
13776
- to: z51.string().describe("Recipient agent name"),
13777
- content: z51.string().describe("Message content"),
13778
- timestamp: z51.string().describe("ISO timestamp when the message was sent"),
13779
- type: z51.nativeEnum(MessageType).describe("Message type"),
13780
- read: z51.boolean().describe("Whether the recipient has read this message")
13973
+ var MailboxMessageSchema = z52.object({
13974
+ id: z52.string().describe("Unique message identifier"),
13975
+ from: z52.string().describe("Sender agent name"),
13976
+ to: z52.string().describe("Recipient agent name"),
13977
+ content: z52.string().describe("Message content"),
13978
+ timestamp: z52.string().describe("ISO timestamp when the message was sent"),
13979
+ type: z52.nativeEnum(MessageType).describe("Message type"),
13980
+ read: z52.boolean().describe("Whether the recipient has read this message")
13781
13981
  });
13782
- var TeamInfoSchema = z51.object({
13783
- teamId: z51.string().describe("Unique team identifier"),
13784
- teamLeadId: z51.string().default("team_lead").describe("Team lead agent ID"),
13785
- teammates: z51.array(TeammateInfoSchema).describe("Active teammates in this team"),
13786
- tasks: z51.array(TeamTaskInfoSchema).optional().describe("Initial tasks snapshot"),
13787
- createdAt: z51.string().optional().describe("ISO timestamp when team was created")
13982
+ var TeamInfoSchema = z52.object({
13983
+ teamId: z52.string().describe("Unique team identifier"),
13984
+ teamLeadId: z52.string().default("team_lead").describe("Team lead agent ID"),
13985
+ teammates: z52.array(TeammateInfoSchema).describe("Active teammates in this team"),
13986
+ tasks: z52.array(TeamTaskInfoSchema).optional().describe("Initial tasks snapshot"),
13987
+ createdAt: z52.string().optional().describe("ISO timestamp when team was created")
13788
13988
  });
13789
- var TEAM_STATE_SCHEMA = z51.object({
13989
+ var TEAM_STATE_SCHEMA = z52.object({
13790
13990
  team: TeamInfoSchema.optional().describe("Team info: teamId, teamLeadId, teammates, tasks. Set when create_team succeeds."),
13791
- tasks: z51.array(TeamTaskInfoSchema).optional().describe("Current tasks snapshot from check_tasks. Updated on each check."),
13792
- team_mailbox: z51.array(MailboxMessageSchema).optional().describe("All team mailbox messages for display")
13991
+ tasks: z52.array(TeamTaskInfoSchema).optional().describe("Current tasks snapshot from check_tasks. Updated on each check."),
13992
+ team_mailbox: z52.array(MailboxMessageSchema).optional().describe("All team mailbox messages for display")
13793
13993
  });
13794
13994
  var TEAM_LEAD_BASE_PROMPT = `You are a team lead that coordinates a team of specialized agents. In order to complete the objective that the user asks of you, you will need to:
13795
13995
 
@@ -13870,7 +14070,7 @@ var TeamAgentGraphBuilder = class {
13870
14070
  const tools = params.tools.map((t) => {
13871
14071
  const toolClient = getToolClient(t.key);
13872
14072
  return toolClient;
13873
- }).filter((tool50) => tool50 !== void 0);
14073
+ }).filter((tool51) => tool51 !== void 0);
13874
14074
  const teammates = params.subAgents.map((sa) => {
13875
14075
  const baseConfig = sa.config;
13876
14076
  return {
@@ -14603,6 +14803,9 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
14603
14803
  buffer2.expiresAt = Date.now() + this.config.ttl;
14604
14804
  buffer2.status = "active" /* ACTIVE */;
14605
14805
  }
14806
+ async ensureThread(threadId) {
14807
+ this.getOrCreateBuffer(threadId);
14808
+ }
14606
14809
  async completeThread(threadId) {
14607
14810
  const buffer2 = this.getBufferIfValid(threadId);
14608
14811
  if (buffer2) {
@@ -16756,10 +16959,10 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
16756
16959
  }
16757
16960
  const tools = await this.getAllTools();
16758
16961
  console.log(`[MCP] Registering ${tools.length} tools to Tool Lattice...`);
16759
- for (const tool50 of tools) {
16760
- const toolKey = prefix ? `${prefix}_${tool50.name}` : tool50.name;
16761
- tool50.name = toolKey;
16762
- toolLatticeManager.registerExistingTool(toolKey, tool50);
16962
+ for (const tool51 of tools) {
16963
+ const toolKey = prefix ? `${prefix}_${tool51.name}` : tool51.name;
16964
+ tool51.name = toolKey;
16965
+ toolLatticeManager.registerExistingTool(toolKey, tool51);
16763
16966
  console.log(`[MCP] Registered tool: ${toolKey}`);
16764
16967
  }
16765
16968
  console.log(`[MCP] Successfully registered ${tools.length} tools to Tool Lattice`);
@@ -17366,6 +17569,7 @@ var Agent = class {
17366
17569
  id: messageId
17367
17570
  });
17368
17571
  }
17572
+ await this.chunkBuffer.ensureThread(this.thread_id);
17369
17573
  this.startQueueProcessorIfNeeded().catch((err) => {
17370
17574
  console.error("Failed to start queue processor:", err);
17371
17575
  });
@@ -17499,12 +17703,16 @@ var Agent = class {
17499
17703
  /**
17500
17704
  * Abort the current agent execution
17501
17705
  * This will cancel any ongoing invoke or stream operations
17706
+ * and clear all queued messages (pending + processing)
17502
17707
  */
17503
- abort() {
17708
+ async abort() {
17504
17709
  if (this.abortController) {
17505
17710
  this.abortController.abort();
17506
17711
  this.abortController = null;
17507
17712
  }
17713
+ await this.chunkBuffer.abortThread(this.thread_id);
17714
+ const store = this.getQueueStore();
17715
+ await store.clearMessages(this.thread_id);
17508
17716
  }
17509
17717
  /**
17510
17718
  * Check if the agent is currently being aborted
@@ -17812,6 +18020,7 @@ export {
17812
18020
  createQueryTablesListTool,
17813
18021
  createTeamMiddleware,
17814
18022
  createTeammateTools,
18023
+ createUnknownToolHandlerMiddleware,
17815
18024
  createWidgetMiddleware,
17816
18025
  decrypt,
17817
18026
  describeCronExpression,