@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.js CHANGED
@@ -48,7 +48,7 @@ __export(index_exports, {
48
48
  FileSystemSkillStore: () => FileSystemSkillStore,
49
49
  FilesystemBackend: () => FilesystemBackend,
50
50
  GraphBuildOptions: () => import_protocols.GraphBuildOptions,
51
- HumanMessage: () => import_messages3.HumanMessage,
51
+ HumanMessage: () => import_messages4.HumanMessage,
52
52
  InMemoryAssistantStore: () => InMemoryAssistantStore,
53
53
  InMemoryChunkBuffer: () => InMemoryChunkBuffer,
54
54
  InMemoryDatabaseConfigStore: () => InMemoryDatabaseConfigStore,
@@ -116,6 +116,7 @@ __export(index_exports, {
116
116
  createQueryTablesListTool: () => createQueryTablesListTool,
117
117
  createTeamMiddleware: () => createTeamMiddleware,
118
118
  createTeammateTools: () => createTeammateTools,
119
+ createUnknownToolHandlerMiddleware: () => createUnknownToolHandlerMiddleware,
119
120
  createWidgetMiddleware: () => createWidgetMiddleware,
120
121
  decrypt: () => decrypt,
121
122
  describeCronExpression: () => describeCronExpression,
@@ -845,11 +846,11 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
845
846
  * @param key Lattice键名
846
847
  * @param tool 已有的StructuredTool实例
847
848
  */
848
- registerExistingTool(key, tool50) {
849
+ registerExistingTool(key, tool51) {
849
850
  const config = {
850
- name: tool50.name,
851
- description: tool50.description,
852
- schema: tool50.schema,
851
+ name: tool51.name,
852
+ description: tool51.description,
853
+ schema: tool51.schema,
853
854
  // StructuredTool的schema已经是Zod兼容的
854
855
  needUserApprove: false
855
856
  // MCP工具默认不需要用户批准
@@ -857,7 +858,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
857
858
  const toolLattice = {
858
859
  key,
859
860
  config,
860
- client: tool50
861
+ client: tool51
861
862
  };
862
863
  this.register(key, toolLattice);
863
864
  }
@@ -883,7 +884,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
883
884
  };
884
885
  var toolLatticeManager = ToolLatticeManager.getInstance();
885
886
  var registerToolLattice = (key, config, executor) => toolLatticeManager.registerLattice(key, config, executor);
886
- var registerExistingTool = (key, tool50) => toolLatticeManager.registerExistingTool(key, tool50);
887
+ var registerExistingTool = (key, tool51) => toolLatticeManager.registerExistingTool(key, tool51);
887
888
  var getToolLattice = (key) => toolLatticeManager.getToolLattice(key);
888
889
  var getToolDefinition = (key) => toolLatticeManager.getToolDefinition(key);
889
890
  var getToolClient = (key) => toolLatticeManager.getToolClient(key);
@@ -4737,7 +4738,7 @@ var createBrowserGetInfoTool = ({ isolatedLevel }) => {
4737
4738
  };
4738
4739
 
4739
4740
  // src/index.ts
4740
- var import_messages3 = require("@langchain/core/messages");
4741
+ var import_messages4 = require("@langchain/core/messages");
4741
4742
 
4742
4743
  // src/agent_lattice/types.ts
4743
4744
  var import_protocols = require("@axiom-lattice/protocols");
@@ -4830,516 +4831,241 @@ var createReactAgentSchema = (schema) => {
4830
4831
  };
4831
4832
 
4832
4833
  // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
4833
- var import_langchain53 = require("langchain");
4834
+ var import_langchain55 = require("langchain");
4834
4835
 
4835
- // src/deep_agent_new/backends/sandboxFiles.ts
4836
- var import_sandbox2 = require("@agent-infra/sandbox");
4837
- var path2 = __toESM(require("path"));
4838
- var SandboxFilesystem = class {
4839
- /**
4840
- * Create a new SandboxFilesystem instance.
4841
- *
4842
- * @param options - Configuration options
4843
- * @param options.baseURL - Base URL of the sandbox service (default: 'http://localhost:8080')
4844
- * @param options.maxFileSizeMb - Maximum file size in MB (default: 10)
4845
- * @param options.sandboxInstance - Optional Sandbox instance (if provided, baseURL is ignored)
4846
- */
4847
- constructor(options = {}) {
4848
- const {
4849
- baseURL = "http://localhost:8080",
4850
- workingDirectory = "/",
4851
- maxFileSizeMb = 10,
4852
- sandboxInstance
4853
- } = options;
4854
- this.sandbox = sandboxInstance || new import_sandbox2.SandboxClient({ baseUrl: baseURL, environment: "" });
4855
- this.sandbox.mcp.listMcpServers().then((servers) => {
4856
- });
4857
- this.sandbox.mcp.listMcpTools("browser").then((tools) => {
4836
+ // src/middlewares/codeEvalMiddleware.ts
4837
+ var import_langchain37 = require("langchain");
4838
+
4839
+ // src/middlewares/contextSchema.ts
4840
+ var import_zod41 = __toESM(require("zod"));
4841
+ var contextSchema = import_zod41.default.object({
4842
+ runConfig: import_zod41.default.any()
4843
+ });
4844
+
4845
+ // src/middlewares/codeEvalMiddleware.ts
4846
+ function createCodeEvalMiddleware(params = { isolatedLevel: "global" }) {
4847
+ const codeEvalTool = createCodeEvalTool({ isolatedLevel: params.isolatedLevel });
4848
+ const codeExecuteFileTool = createCodeExecuteFileTool({ isolatedLevel: params.isolatedLevel });
4849
+ return (0, import_langchain37.createMiddleware)({
4850
+ name: "codeEvalMiddleware",
4851
+ contextSchema,
4852
+ tools: [codeEvalTool, codeExecuteFileTool, getToolClient("convert_to_markdown")]
4853
+ });
4854
+ }
4855
+
4856
+ // src/middlewares/browserMiddleware.ts
4857
+ var import_langchain38 = require("langchain");
4858
+ function createBrowserMiddleware(params = { isolatedLevel: "global" }) {
4859
+ const isolatedLevel = params.isolatedLevel || "global";
4860
+ const tools = [
4861
+ createBrowserNavigateTool({ isolatedLevel }),
4862
+ createBrowserClickTool({ isolatedLevel }),
4863
+ createBrowserGetTextTool({ isolatedLevel }),
4864
+ createBrowserGetMarkdownTool({ isolatedLevel }),
4865
+ createBrowserEvaluateTool({ isolatedLevel }),
4866
+ createBrowserScreenshotTool({ isolatedLevel }),
4867
+ createBrowserScrollTool({ isolatedLevel }),
4868
+ createBrowserFormInputFillTool({ isolatedLevel }),
4869
+ createBrowserSelectTool({ isolatedLevel }),
4870
+ createBrowserHoverTool({ isolatedLevel }),
4871
+ createBrowserGoBackTool({ isolatedLevel }),
4872
+ createBrowserGoForwardTool({ isolatedLevel }),
4873
+ createBrowserNewTabTool({ isolatedLevel }),
4874
+ createBrowserTabListTool({ isolatedLevel }),
4875
+ createBrowserSwitchTabTool({ isolatedLevel }),
4876
+ createBrowserCloseTabTool({ isolatedLevel }),
4877
+ createBrowserCloseTool({ isolatedLevel }),
4878
+ createBrowserPressKeyTool({ isolatedLevel }),
4879
+ createBrowserReadLinksTool({ isolatedLevel }),
4880
+ createBrowserGetClickableElementsTool({ isolatedLevel }),
4881
+ createBrowserGetDownloadListTool({ isolatedLevel }),
4882
+ createBrowserGetInfoTool({ isolatedLevel })
4883
+ ];
4884
+ return (0, import_langchain38.createMiddleware)({
4885
+ name: "browserMiddleware",
4886
+ contextSchema,
4887
+ tools
4888
+ });
4889
+ }
4890
+
4891
+ // src/middlewares/sqlMiddleware.ts
4892
+ var import_langchain39 = require("langchain");
4893
+ function createSqlMiddleware(params) {
4894
+ const { databaseKeys, databaseDescriptions } = params;
4895
+ if (!databaseKeys || databaseKeys.length === 0) {
4896
+ return (0, import_langchain39.createMiddleware)({
4897
+ name: "sqlMiddleware",
4898
+ tools: []
4858
4899
  });
4859
- this.baseURL = baseURL;
4860
- this.maxFileSizeBytes = maxFileSizeMb * 1024 * 1024;
4861
- this.workingDirectory = workingDirectory;
4862
- this.homeDir = "/home/gem";
4863
- }
4864
- resolvePath(virtualPath) {
4865
- return path2.join(this.homeDir, this.workingDirectory, virtualPath);
4866
4900
  }
4867
- /**
4868
- * Convert a real filesystem path to a virtual path.
4869
- *
4870
- * @param realPath - Real filesystem path
4871
- * @returns Virtual path starting with /
4872
- */
4873
- toVirtualPath(realPath) {
4874
- const rootPath = path2.join(this.homeDir, this.workingDirectory);
4875
- const relative4 = path2.relative(rootPath, realPath);
4876
- const normalized = relative4.split(path2.sep).join("/");
4877
- return "/" + normalized;
4901
+ const toolParams = {
4902
+ databaseKeys,
4903
+ databaseDescriptions
4904
+ };
4905
+ return (0, import_langchain39.createMiddleware)({
4906
+ name: "sqlMiddleware",
4907
+ contextSchema,
4908
+ tools: [
4909
+ createListTablesSqlTool(toolParams),
4910
+ createInfoSqlTool(toolParams),
4911
+ createQueryCheckerSqlTool(toolParams),
4912
+ createQuerySqlTool(toolParams)
4913
+ ]
4914
+ });
4915
+ }
4916
+
4917
+ // src/middlewares/skillMiddleware.ts
4918
+ var import_langchain43 = require("langchain");
4919
+
4920
+ // src/store_lattice/InMemoryThreadStore.ts
4921
+ var InMemoryThreadStore = class {
4922
+ constructor() {
4923
+ // Map<tenantId, Map<assistantId, Map<threadId, Thread>>>
4924
+ this.threads = /* @__PURE__ */ new Map();
4878
4925
  }
4879
4926
  /**
4880
- * List files and directories in the specified directory (non-recursive).
4881
- *
4882
- * @param dirPath - Virtual directory path (must start with /)
4883
- * @returns List of FileInfo objects for files and directories directly in the directory.
4884
- * Directories have a trailing / in their path and is_dir=true.
4927
+ * Get all threads for a specific tenant and assistant
4885
4928
  */
4886
- async lsInfo(dirPath) {
4887
- try {
4888
- const resolvedPath = this.resolvePath(dirPath);
4889
- const result = await this.sandbox.file.listPath({
4890
- path: resolvedPath,
4891
- recursive: false,
4892
- show_hidden: false,
4893
- max_depth: 0,
4894
- include_size: false,
4895
- include_permissions: false,
4896
- sort_by: "name",
4897
- sort_desc: false
4898
- });
4899
- if (!result.ok) {
4900
- throw result.error;
4901
- }
4902
- const files = result.body?.data?.files?.map((file) => ({
4903
- path: this.toVirtualPath(file.path),
4904
- is_dir: file.is_directory,
4905
- size: file.size,
4906
- modified_at: file.modified_time
4907
- })) || [];
4908
- return files;
4909
- } catch (e) {
4910
- console.error(`Error listing files in ${dirPath}:`, e);
4929
+ async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
4930
+ const tenantThreads = this.threads.get(tenantId);
4931
+ if (!tenantThreads) {
4932
+ return [];
4933
+ }
4934
+ const assistantThreads = tenantThreads.get(assistantId);
4935
+ if (!assistantThreads) {
4911
4936
  return [];
4912
4937
  }
4938
+ let threads = Array.from(assistantThreads.values());
4939
+ if (metadataFilter && Object.keys(metadataFilter).length > 0) {
4940
+ threads = threads.filter(
4941
+ (thread) => Object.entries(metadataFilter).every(
4942
+ ([key, value]) => thread.metadata?.[key] === value
4943
+ )
4944
+ );
4945
+ }
4946
+ return threads;
4913
4947
  }
4914
4948
  /**
4915
- * Read file content with line numbers.
4916
- *
4917
- * @param filePath - Virtual file path (must start with /)
4918
- * @param offset - Line offset to start reading from (0-indexed)
4919
- * @param limit - Maximum number of lines to read
4920
- * @returns Formatted file content with line numbers, or error message
4949
+ * Get a thread by ID for a specific tenant
4921
4950
  */
4922
- async read(filePath, offset = 0, limit = 1e4) {
4923
- try {
4924
- const resolvedPath = this.resolvePath(filePath);
4925
- let content;
4926
- const result = await this.sandbox.file.readFile({
4927
- file: resolvedPath,
4928
- start_line: offset,
4929
- end_line: limit
4930
- });
4931
- if (!result.ok) {
4932
- throw result.error;
4951
+ async getThreadById(tenantId, threadId) {
4952
+ const tenantThreads = this.threads.get(tenantId);
4953
+ if (!tenantThreads) {
4954
+ return void 0;
4955
+ }
4956
+ for (const assistantThreads of tenantThreads.values()) {
4957
+ const thread = assistantThreads.get(threadId);
4958
+ if (thread) {
4959
+ return thread;
4933
4960
  }
4934
- content = result.body?.data?.content || "";
4935
- return content;
4936
- } catch (e) {
4937
- return `Error: File '${filePath}' not found`;
4938
4961
  }
4962
+ return void 0;
4939
4963
  }
4940
4964
  /**
4941
- * Read file content as raw FileData.
4942
- *
4943
- * @param filePath - Virtual file path (must start with /)
4944
- * @returns Raw file content as FileData
4965
+ * Create a new thread for a tenant and assistant
4945
4966
  */
4946
- async readRaw(filePath) {
4947
- try {
4948
- const content = await this.read(filePath);
4949
- return {
4950
- content: content.split("\n"),
4951
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
4952
- modified_at: (/* @__PURE__ */ new Date()).toISOString()
4953
- };
4954
- } catch (e) {
4955
- throw new Error(`Error reading file '${filePath}': ${e.message}`);
4967
+ async createThread(tenantId, assistantId, threadId, data) {
4968
+ const now = /* @__PURE__ */ new Date();
4969
+ const thread = {
4970
+ id: threadId,
4971
+ tenantId,
4972
+ assistantId,
4973
+ metadata: data.metadata || {},
4974
+ createdAt: now,
4975
+ updatedAt: now
4976
+ };
4977
+ if (!this.threads.has(tenantId)) {
4978
+ this.threads.set(tenantId, /* @__PURE__ */ new Map());
4979
+ }
4980
+ const tenantThreads = this.threads.get(tenantId);
4981
+ if (!tenantThreads.has(assistantId)) {
4982
+ tenantThreads.set(assistantId, /* @__PURE__ */ new Map());
4956
4983
  }
4984
+ const assistantThreads = tenantThreads.get(assistantId);
4985
+ assistantThreads.set(threadId, thread);
4986
+ return thread;
4957
4987
  }
4958
4988
  /**
4959
- * Create a new file with content.
4960
- * Returns WriteResult. External storage sets filesUpdate=null.
4961
- *
4962
- * @param filePath - Virtual file path (must start with /)
4963
- * @param content - File content as string
4964
- * @returns WriteResult with error populated on failure
4989
+ * Update an existing thread
4965
4990
  */
4966
- async write(filePath, content) {
4967
- try {
4968
- const resolvedPath = this.resolvePath(filePath);
4969
- const result = await this.sandbox.file.writeFile({
4970
- file: resolvedPath,
4971
- content,
4972
- "encoding": "utf-8",
4973
- "append": false
4974
- // sudo: true
4975
- });
4976
- if (!result.ok) {
4977
- console.error(result.error);
4978
- throw result.error;
4991
+ async updateThread(tenantId, threadId, updates) {
4992
+ const tenantThreads = this.threads.get(tenantId);
4993
+ if (!tenantThreads) {
4994
+ return null;
4995
+ }
4996
+ for (const assistantThreads of tenantThreads.values()) {
4997
+ const existing = assistantThreads.get(threadId);
4998
+ if (existing) {
4999
+ const updated = {
5000
+ ...existing,
5001
+ metadata: {
5002
+ ...existing.metadata,
5003
+ ...updates.metadata || {}
5004
+ },
5005
+ updatedAt: /* @__PURE__ */ new Date()
5006
+ };
5007
+ assistantThreads.set(threadId, updated);
5008
+ return updated;
4979
5009
  }
4980
- return {
4981
- path: filePath,
4982
- filesUpdate: {
4983
- [filePath]: {
4984
- content: content.split("\n"),
4985
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
4986
- modified_at: (/* @__PURE__ */ new Date()).toISOString()
4987
- }
4988
- }
4989
- };
4990
- } catch (e) {
4991
- throw new Error(`Error writing file '${filePath}': ${e.message}`);
4992
5010
  }
5011
+ return null;
4993
5012
  }
4994
5013
  /**
4995
- * Edit a file by replacing string occurrences.
4996
- * Returns EditResult. External storage sets filesUpdate=null.
4997
- *
4998
- * @param filePath - Virtual file path (must start with /)
4999
- * @param oldString - String to find and replace
5000
- * @param newString - Replacement string
5001
- * @param replaceAll - If true, replace all occurrences (default: false)
5002
- * @returns EditResult with error, path, filesUpdate, and occurrences
5014
+ * Delete a thread by ID
5003
5015
  */
5004
- async edit(filePath, oldString, newString, replaceAll = false) {
5005
- try {
5006
- const resolvedPath = this.resolvePath(filePath);
5007
- const result = await this.sandbox.file.strReplaceEditor({
5008
- command: "str_replace",
5009
- path: resolvedPath,
5010
- old_str: oldString,
5011
- new_str: newString,
5012
- replace_mode: replaceAll ? "ALL" : "FIRST"
5013
- });
5014
- if (!result.ok) {
5015
- throw result.error;
5016
+ async deleteThread(tenantId, threadId) {
5017
+ const tenantThreads = this.threads.get(tenantId);
5018
+ if (!tenantThreads) {
5019
+ return false;
5020
+ }
5021
+ for (const assistantThreads of tenantThreads.values()) {
5022
+ if (assistantThreads.has(threadId)) {
5023
+ return assistantThreads.delete(threadId);
5016
5024
  }
5017
- return {
5018
- path: filePath,
5019
- filesUpdate: null
5020
- };
5021
- } catch (e) {
5022
- throw new Error(`Error editing file '${filePath}': ${e.message}`);
5023
5025
  }
5026
+ return false;
5024
5027
  }
5025
5028
  /**
5026
- * Structured search results or error string for invalid input.
5027
- *
5028
- * Searches file contents for a regex pattern within the sandbox.
5029
- *
5030
- * @param pattern - Regex pattern to search for
5031
- * @param searchPath - Base path to search from (default: "/")
5032
- * @param glob - Optional glob pattern to filter files (e.g., "*.py")
5033
- * @returns List of GrepMatch objects or error string for invalid regex
5029
+ * Check if thread exists
5034
5030
  */
5035
- async grepRaw(pattern, searchPath = "/", glob = null) {
5036
- let baseFull;
5037
- baseFull = this.resolvePath(searchPath || "/");
5038
- const result = await this.sandbox.file.findFiles({
5039
- path: baseFull,
5040
- glob: glob || "**/*"
5041
- });
5042
- if (!result.ok) {
5043
- throw result.error;
5031
+ async hasThread(tenantId, threadId) {
5032
+ const tenantThreads = this.threads.get(tenantId);
5033
+ if (!tenantThreads) {
5034
+ return false;
5044
5035
  }
5045
- const filePaths = result.body?.data?.files || [];
5046
- const matches = [];
5047
- for (const absolutePath of filePaths) {
5048
- const fileData = await this.sandbox.file.searchInFile({
5049
- file: absolutePath,
5050
- regex: pattern
5051
- });
5052
- if (!fileData.ok) {
5053
- continue;
5036
+ for (const assistantThreads of tenantThreads.values()) {
5037
+ if (assistantThreads.has(threadId)) {
5038
+ return true;
5054
5039
  }
5055
- const matchesData = fileData.body?.data?.matches || [];
5056
- const matchLines = fileData.body?.data?.line_numbers || [];
5057
- matchesData.forEach((match, index) => {
5058
- matches.push({
5059
- path: this.toVirtualPath(absolutePath),
5060
- line: matchLines[index],
5061
- text: match
5062
- });
5063
- });
5064
5040
  }
5065
- return matches;
5041
+ return false;
5066
5042
  }
5067
5043
  /**
5068
- * Structured glob matching returning FileInfo objects.
5069
- *
5070
- * @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
5071
- * @param searchPath - Base path to search from (default: "/")
5072
- * @returns List of FileInfo objects matching the pattern
5044
+ * Clear all threads for a tenant (useful for testing)
5073
5045
  */
5074
- async globInfo(pattern, searchPath = "/") {
5075
- if (pattern.startsWith("/")) {
5076
- pattern = pattern.substring(1);
5077
- }
5078
- const resolvedSearchPath = this.resolvePath(searchPath);
5079
- const result = await this.sandbox.file.findFiles({
5080
- path: resolvedSearchPath,
5081
- glob: pattern || "**/*"
5082
- });
5083
- if (!result.ok) {
5084
- throw result.error;
5046
+ clear(tenantId) {
5047
+ if (tenantId) {
5048
+ this.threads.delete(tenantId);
5049
+ } else {
5050
+ this.threads.clear();
5085
5051
  }
5086
- const results = [];
5087
- for (const filePath of result.body?.data?.files || []) {
5088
- const fileInfo = await this.sandbox.file.listPath({
5089
- path: filePath,
5090
- recursive: false,
5091
- show_hidden: false,
5092
- max_depth: 1,
5093
- include_size: false,
5094
- include_permissions: false
5095
- });
5096
- if (!fileInfo.ok) {
5097
- continue;
5052
+ }
5053
+ /**
5054
+ * Get all threads for all assistants (useful for debugging)
5055
+ */
5056
+ getAllThreads() {
5057
+ const allThreads = [];
5058
+ for (const tenantThreads of this.threads.values()) {
5059
+ for (const assistantThreads of tenantThreads.values()) {
5060
+ allThreads.push(...Array.from(assistantThreads.values()));
5098
5061
  }
5099
- results.push({
5100
- path: this.toVirtualPath(filePath),
5101
- is_dir: false,
5102
- size: fileInfo.body?.data?.files?.[0]?.size,
5103
- modified_at: fileInfo.body?.data?.files?.[0]?.modified_time
5104
- });
5105
5062
  }
5106
- return results;
5063
+ return allThreads;
5107
5064
  }
5108
5065
  };
5109
5066
 
5110
- // src/middlewares/codeEvalMiddleware.ts
5111
- var import_langchain37 = require("langchain");
5112
-
5113
- // src/middlewares/contextSchema.ts
5114
- var import_zod41 = __toESM(require("zod"));
5115
- var contextSchema = import_zod41.default.object({
5116
- runConfig: import_zod41.default.any()
5117
- });
5118
-
5119
- // src/middlewares/codeEvalMiddleware.ts
5120
- function createCodeEvalMiddleware(params = { isolatedLevel: "global" }) {
5121
- const codeEvalTool = createCodeEvalTool({ isolatedLevel: params.isolatedLevel });
5122
- const codeExecuteFileTool = createCodeExecuteFileTool({ isolatedLevel: params.isolatedLevel });
5123
- return (0, import_langchain37.createMiddleware)({
5124
- name: "codeEvalMiddleware",
5125
- contextSchema,
5126
- tools: [codeEvalTool, codeExecuteFileTool, getToolClient("convert_to_markdown")]
5127
- });
5128
- }
5129
-
5130
- // src/middlewares/browserMiddleware.ts
5131
- var import_langchain38 = require("langchain");
5132
- function createBrowserMiddleware(params = { isolatedLevel: "global" }) {
5133
- const isolatedLevel = params.isolatedLevel || "global";
5134
- const tools = [
5135
- createBrowserNavigateTool({ isolatedLevel }),
5136
- createBrowserClickTool({ isolatedLevel }),
5137
- createBrowserGetTextTool({ isolatedLevel }),
5138
- createBrowserGetMarkdownTool({ isolatedLevel }),
5139
- createBrowserEvaluateTool({ isolatedLevel }),
5140
- createBrowserScreenshotTool({ isolatedLevel }),
5141
- createBrowserScrollTool({ isolatedLevel }),
5142
- createBrowserFormInputFillTool({ isolatedLevel }),
5143
- createBrowserSelectTool({ isolatedLevel }),
5144
- createBrowserHoverTool({ isolatedLevel }),
5145
- createBrowserGoBackTool({ isolatedLevel }),
5146
- createBrowserGoForwardTool({ isolatedLevel }),
5147
- createBrowserNewTabTool({ isolatedLevel }),
5148
- createBrowserTabListTool({ isolatedLevel }),
5149
- createBrowserSwitchTabTool({ isolatedLevel }),
5150
- createBrowserCloseTabTool({ isolatedLevel }),
5151
- createBrowserCloseTool({ isolatedLevel }),
5152
- createBrowserPressKeyTool({ isolatedLevel }),
5153
- createBrowserReadLinksTool({ isolatedLevel }),
5154
- createBrowserGetClickableElementsTool({ isolatedLevel }),
5155
- createBrowserGetDownloadListTool({ isolatedLevel }),
5156
- createBrowserGetInfoTool({ isolatedLevel })
5157
- ];
5158
- return (0, import_langchain38.createMiddleware)({
5159
- name: "browserMiddleware",
5160
- contextSchema,
5161
- tools
5162
- });
5163
- }
5164
-
5165
- // src/middlewares/sqlMiddleware.ts
5166
- var import_langchain39 = require("langchain");
5167
- function createSqlMiddleware(params) {
5168
- const { databaseKeys, databaseDescriptions } = params;
5169
- if (!databaseKeys || databaseKeys.length === 0) {
5170
- return (0, import_langchain39.createMiddleware)({
5171
- name: "sqlMiddleware",
5172
- tools: []
5173
- });
5174
- }
5175
- const toolParams = {
5176
- databaseKeys,
5177
- databaseDescriptions
5178
- };
5179
- return (0, import_langchain39.createMiddleware)({
5180
- name: "sqlMiddleware",
5181
- contextSchema,
5182
- tools: [
5183
- createListTablesSqlTool(toolParams),
5184
- createInfoSqlTool(toolParams),
5185
- createQueryCheckerSqlTool(toolParams),
5186
- createQuerySqlTool(toolParams)
5187
- ]
5188
- });
5189
- }
5190
-
5191
- // src/middlewares/skillMiddleware.ts
5192
- var import_langchain43 = require("langchain");
5193
-
5194
- // src/store_lattice/InMemoryThreadStore.ts
5195
- var InMemoryThreadStore = class {
5196
- constructor() {
5197
- // Map<tenantId, Map<assistantId, Map<threadId, Thread>>>
5198
- this.threads = /* @__PURE__ */ new Map();
5199
- }
5200
- /**
5201
- * Get all threads for a specific tenant and assistant
5202
- */
5203
- async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
5204
- const tenantThreads = this.threads.get(tenantId);
5205
- if (!tenantThreads) {
5206
- return [];
5207
- }
5208
- const assistantThreads = tenantThreads.get(assistantId);
5209
- if (!assistantThreads) {
5210
- return [];
5211
- }
5212
- let threads = Array.from(assistantThreads.values());
5213
- if (metadataFilter && Object.keys(metadataFilter).length > 0) {
5214
- threads = threads.filter(
5215
- (thread) => Object.entries(metadataFilter).every(
5216
- ([key, value]) => thread.metadata?.[key] === value
5217
- )
5218
- );
5219
- }
5220
- return threads;
5221
- }
5222
- /**
5223
- * Get a thread by ID for a specific tenant
5224
- */
5225
- async getThreadById(tenantId, threadId) {
5226
- const tenantThreads = this.threads.get(tenantId);
5227
- if (!tenantThreads) {
5228
- return void 0;
5229
- }
5230
- for (const assistantThreads of tenantThreads.values()) {
5231
- const thread = assistantThreads.get(threadId);
5232
- if (thread) {
5233
- return thread;
5234
- }
5235
- }
5236
- return void 0;
5237
- }
5238
- /**
5239
- * Create a new thread for a tenant and assistant
5240
- */
5241
- async createThread(tenantId, assistantId, threadId, data) {
5242
- const now = /* @__PURE__ */ new Date();
5243
- const thread = {
5244
- id: threadId,
5245
- tenantId,
5246
- assistantId,
5247
- metadata: data.metadata || {},
5248
- createdAt: now,
5249
- updatedAt: now
5250
- };
5251
- if (!this.threads.has(tenantId)) {
5252
- this.threads.set(tenantId, /* @__PURE__ */ new Map());
5253
- }
5254
- const tenantThreads = this.threads.get(tenantId);
5255
- if (!tenantThreads.has(assistantId)) {
5256
- tenantThreads.set(assistantId, /* @__PURE__ */ new Map());
5257
- }
5258
- const assistantThreads = tenantThreads.get(assistantId);
5259
- assistantThreads.set(threadId, thread);
5260
- return thread;
5261
- }
5262
- /**
5263
- * Update an existing thread
5264
- */
5265
- async updateThread(tenantId, threadId, updates) {
5266
- const tenantThreads = this.threads.get(tenantId);
5267
- if (!tenantThreads) {
5268
- return null;
5269
- }
5270
- for (const assistantThreads of tenantThreads.values()) {
5271
- const existing = assistantThreads.get(threadId);
5272
- if (existing) {
5273
- const updated = {
5274
- ...existing,
5275
- metadata: {
5276
- ...existing.metadata,
5277
- ...updates.metadata || {}
5278
- },
5279
- updatedAt: /* @__PURE__ */ new Date()
5280
- };
5281
- assistantThreads.set(threadId, updated);
5282
- return updated;
5283
- }
5284
- }
5285
- return null;
5286
- }
5287
- /**
5288
- * Delete a thread by ID
5289
- */
5290
- async deleteThread(tenantId, threadId) {
5291
- const tenantThreads = this.threads.get(tenantId);
5292
- if (!tenantThreads) {
5293
- return false;
5294
- }
5295
- for (const assistantThreads of tenantThreads.values()) {
5296
- if (assistantThreads.has(threadId)) {
5297
- return assistantThreads.delete(threadId);
5298
- }
5299
- }
5300
- return false;
5301
- }
5302
- /**
5303
- * Check if thread exists
5304
- */
5305
- async hasThread(tenantId, threadId) {
5306
- const tenantThreads = this.threads.get(tenantId);
5307
- if (!tenantThreads) {
5308
- return false;
5309
- }
5310
- for (const assistantThreads of tenantThreads.values()) {
5311
- if (assistantThreads.has(threadId)) {
5312
- return true;
5313
- }
5314
- }
5315
- return false;
5316
- }
5317
- /**
5318
- * Clear all threads for a tenant (useful for testing)
5319
- */
5320
- clear(tenantId) {
5321
- if (tenantId) {
5322
- this.threads.delete(tenantId);
5323
- } else {
5324
- this.threads.clear();
5325
- }
5326
- }
5327
- /**
5328
- * Get all threads for all assistants (useful for debugging)
5329
- */
5330
- getAllThreads() {
5331
- const allThreads = [];
5332
- for (const tenantThreads of this.threads.values()) {
5333
- for (const assistantThreads of tenantThreads.values()) {
5334
- allThreads.push(...Array.from(assistantThreads.values()));
5335
- }
5336
- }
5337
- return allThreads;
5338
- }
5339
- };
5340
-
5341
- // src/store_lattice/InMemoryAssistantStore.ts
5342
- var InMemoryAssistantStore = class {
5067
+ // src/store_lattice/InMemoryAssistantStore.ts
5068
+ var InMemoryAssistantStore = class {
5343
5069
  constructor() {
5344
5070
  this.assistants = /* @__PURE__ */ new Map();
5345
5071
  }
@@ -5433,7 +5159,7 @@ var InMemoryAssistantStore = class {
5433
5159
 
5434
5160
  // src/store_lattice/FileSystemSkillStore.ts
5435
5161
  var fs = __toESM(require("fs/promises"));
5436
- var path3 = __toESM(require("path"));
5162
+ var path2 = __toESM(require("path"));
5437
5163
 
5438
5164
  // src/skill_lattice/skillNameValidator.ts
5439
5165
  var SKILL_NAME_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
@@ -5606,10 +5332,10 @@ var FileSystemSkillStore = class {
5606
5332
  constructor(options = {}) {
5607
5333
  const defaultPath = "lattice_store/skills";
5608
5334
  const providedPath = options.rootDir || defaultPath;
5609
- if (path3.isAbsolute(providedPath)) {
5335
+ if (path2.isAbsolute(providedPath)) {
5610
5336
  this.rootDir = providedPath;
5611
5337
  } else {
5612
- this.rootDir = path3.resolve(process.cwd(), providedPath);
5338
+ this.rootDir = path2.resolve(process.cwd(), providedPath);
5613
5339
  }
5614
5340
  this.ensureDirectoryExists().catch((error) => {
5615
5341
  console.error("Failed to initialize FileSystemSkillStore:", error);
@@ -5633,14 +5359,14 @@ var FileSystemSkillStore = class {
5633
5359
  if (name.includes("..") || name.includes("/") || name.includes("\\")) {
5634
5360
  throw new Error(`Invalid skill name: ${name} (contains invalid characters)`);
5635
5361
  }
5636
- return path3.join(this.rootDir, name);
5362
+ return path2.join(this.rootDir, name);
5637
5363
  }
5638
5364
  /**
5639
5365
  * Get file path for a skill name
5640
5366
  * File is always named SKILL.md inside the name directory
5641
5367
  */
5642
5368
  getSkillFilePath(name) {
5643
- return path3.join(this.getSkillDirectoryPath(name), "SKILL.md");
5369
+ return path2.join(this.getSkillDirectoryPath(name), "SKILL.md");
5644
5370
  }
5645
5371
  /**
5646
5372
  * Read skill from file
@@ -5927,14 +5653,14 @@ ${body}` : `${frontmatter}
5927
5653
  */
5928
5654
  async listSkillResources(_tenantId, skillName) {
5929
5655
  const skillDir = this.getSkillDirectoryPath(skillName);
5930
- const resourcesDir = path3.join(skillDir, "resources");
5656
+ const resourcesDir = path2.join(skillDir, "resources");
5931
5657
  try {
5932
5658
  const entries = await fs.readdir(resourcesDir, { withFileTypes: true, recursive: true });
5933
5659
  const resources = [];
5934
5660
  for (const entry of entries) {
5935
5661
  if (!entry.isDirectory()) {
5936
- const fullPath = path3.join(entry.path, entry.name);
5937
- const relativePath = path3.relative(resourcesDir, fullPath);
5662
+ const fullPath = path2.join(entry.path, entry.name);
5663
+ const relativePath = path2.relative(resourcesDir, fullPath);
5938
5664
  resources.push(relativePath.replace(/\\/g, "/"));
5939
5665
  }
5940
5666
  }
@@ -5955,10 +5681,10 @@ ${body}` : `${frontmatter}
5955
5681
  */
5956
5682
  async loadSkillResource(_tenantId, skillName, resourcePath) {
5957
5683
  const skillDir = this.getSkillDirectoryPath(skillName);
5958
- const resourcesDir = path3.join(skillDir, "resources");
5959
- const fullPath = path3.join(resourcesDir, resourcePath);
5960
- const resolvedPath = path3.resolve(fullPath);
5961
- const resolvedResourcesDir = path3.resolve(resourcesDir);
5684
+ const resourcesDir = path2.join(skillDir, "resources");
5685
+ const fullPath = path2.join(resourcesDir, resourcePath);
5686
+ const resolvedPath = path2.resolve(fullPath);
5687
+ const resolvedResourcesDir = path2.resolve(resourcesDir);
5962
5688
  if (!resolvedPath.startsWith(resolvedResourcesDir)) {
5963
5689
  throw new Error(`Invalid resource path: ${resourcePath}`);
5964
5690
  }
@@ -9422,7 +9148,7 @@ function createShowWidgetTool() {
9422
9148
  },
9423
9149
  {
9424
9150
  name: "show_widget",
9425
- 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.",
9151
+ 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.",
9426
9152
  schema: ShowWidgetInputSchema
9427
9153
  }
9428
9154
  );
@@ -9494,22 +9220,19 @@ var import_langchain52 = require("langchain");
9494
9220
 
9495
9221
  // src/deep_agent_new/middleware/AGENTS_MD.ts
9496
9222
  var AGENTS_MD = `
9497
- # AGENTS.md - Your Workspace
9498
-
9499
- This folder is home. Treat it that way.
9500
9223
 
9501
9224
  ## First Run
9502
9225
 
9503
- If \`BOOTSTRAP.md\` exists, that's your birth certificate. Follow it, figure out who you are, then delete it. You won't need it again.
9226
+ If \`/agent/BOOTSTRAP.md\` exists, that's your birth certificate. Follow it, figure out who you are, then delete it. You won't need it again.
9504
9227
 
9505
9228
  ## Every Session
9506
9229
 
9507
9230
  Before doing anything else:
9508
9231
 
9509
- 1. Read \`SOUL.md\` \u2014 this is who you are
9510
- 2. Read \`USER.md\` \u2014 this is who you're helping
9232
+ 1. Read \`/agent/SOUL.md\` \u2014 this is who you are
9233
+ 2. Read \`/agent/USER.md\` \u2014 this is who you're helping
9511
9234
  3. Read \`memory/YYYY-MM-DD.md\` (today + yesterday) for recent context
9512
- 4. **If in MAIN SESSION** (direct chat with your human): Also read \`MEMORY.md\`
9235
+ 4. **If in MAIN SESSION** (direct chat with your human): Also read \`/agent/MEMORY.md\`
9513
9236
 
9514
9237
  Don't ask permission. Just do it.
9515
9238
 
@@ -9517,17 +9240,18 @@ Don't ask permission. Just do it.
9517
9240
 
9518
9241
  You wake up fresh each session. These files are your continuity:
9519
9242
 
9520
- - **Daily notes:** \`memory/YYYY-MM-DD.md\` (create \`memory/\` if needed) \u2014 raw logs of what happened
9521
- - **Long-term:** \`MEMORY.md\` \u2014 your curated memories, like a human's long-term memory
9243
+ - **agent Long-term:** \`/agent/MEMORY.md\` \u2014 your curated memories, like a human's long-term memory
9244
+ - **Project Memory**: \`/PROJECT.md\` - Loaded from project root if available - Project-specific instructions
9245
+ - **Daily Project notes:** \`/daily/YYYY-MM-DD.md\` (create \`daily/\` if needed) \u2014 raw logs of what happened
9522
9246
 
9523
9247
  Capture what matters. Decisions, context, things to remember. Skip the secrets unless asked to keep them.
9524
9248
 
9525
- ### \u{1F9E0} MEMORY.md - Your Long-Term Memory
9249
+ ### \u{1F9E0} /agent/MEMORY.md - Your Long-Term Memory
9526
9250
 
9527
9251
  - **ONLY load in main session** (direct chats with your human)
9528
9252
  - **DO NOT load in shared contexts** (Discord, group chats, sessions with other people)
9529
9253
  - This is for **security** \u2014 contains personal context that shouldn't leak to strangers
9530
- - You can **read, edit, and update** MEMORY.md freely in main sessions
9254
+ - You can **read, edit, and update** /agent/MEMORY.md freely in main sessions
9531
9255
  - Write significant events, thoughts, decisions, opinions, lessons learned
9532
9256
  - This is your curated memory \u2014 the distilled essence, not raw logs
9533
9257
  - Over time, review your daily files and update MEMORY.md with what's worth keeping
@@ -9536,11 +9260,42 @@ Capture what matters. Decisions, context, things to remember. Skip the secrets u
9536
9260
 
9537
9261
  - **Memory is limited** \u2014 if you want to remember something, WRITE IT TO A FILE
9538
9262
  - "Mental notes" don't survive session restarts. Files do.
9539
- - When someone says "remember this" \u2192 update \`memory/YYYY-MM-DD.md\` or relevant file
9540
- - When you learn a lesson \u2192 update AGENTS.md, TOOLS.md, or the relevant skill
9263
+ - When someone says "remember this" \u2192 update \`/daily/YYYY-MM-DD.md\` or relevant file
9264
+ - When you learn a lesson \u2192 update /agent/AGENTS.md, /agent/TOOLS.md, or the relevant skill
9541
9265
  - When you make a mistake \u2192 document it so future-you doesn't repeat it
9542
9266
  - **Text > Brain** \u{1F4DD}
9543
9267
 
9268
+ ### Project Memory File: \`/PROJECT.md\`
9269
+ \u2192 Describes **how this specific project works** and **how the agent should behave here only.**
9270
+
9271
+ **Store here:**
9272
+ - Project-specific architecture and design patterns
9273
+ - Coding conventions specific to this codebase
9274
+ - Project structure and organization
9275
+ - Testing strategies for this project
9276
+ - Deployment processes and workflows
9277
+ - Team conventions and guidelines
9278
+
9279
+ **Examples:**
9280
+ - "This project uses FastAPI with SQLAlchemy"
9281
+ - "Tests go in tests/ directory mirroring src/ structure"
9282
+ - "All API changes require updating OpenAPI spec"
9283
+
9284
+ ### Project Memory Files: \`{project_deepagents_dir}/*.md\`
9285
+ \u2192 Use for **project-specific reference information** and structured notes.
9286
+
9287
+ **Store here:**
9288
+ - API design documentation
9289
+ - Architecture decisions and rationale
9290
+ - Deployment procedures
9291
+ - Common debugging patterns
9292
+ - Onboarding information
9293
+
9294
+ **Examples:**
9295
+ - \`{project_deepagents_dir}/api-design.md\` - REST API patterns used
9296
+ - \`{project_deepagents_dir}/architecture.md\` - System architecture overview
9297
+ - \`{project_deepagents_dir}/deployment.md\` - How to deploy this project
9298
+
9544
9299
  ## Safety
9545
9300
 
9546
9301
  - Don't exfiltrate private data. Ever.
@@ -9712,10 +9467,10 @@ Offer suggestions if they're stuck. Have fun with it.
9712
9467
 
9713
9468
  Update these files with what you learned:
9714
9469
 
9715
- - \`IDENTITY.md\` \u2014 your name, creature, vibe, emoji
9716
- - \`USER.md\` \u2014 their name, how to address them, timezone, notes
9470
+ - \`/agent/IDENTITY.md\` \u2014 your name, creature, vibe, emoji
9471
+ - \`/agent/USER.md\` \u2014 their name, how to address them, timezone, notes
9717
9472
 
9718
- Then open \`SOUL.md\` together and talk about:
9473
+ Then open \`/agent/SOUL.md\` together and talk about:
9719
9474
 
9720
9475
  - What matters to them
9721
9476
  - How they want you to behave
@@ -9848,12 +9603,12 @@ async function getBackend2(backend, stateAndStore) {
9848
9603
  return backend;
9849
9604
  }
9850
9605
  var BOOTSTRAP_FILE_NAMES = {
9851
- agents: "AGENTS.md",
9852
- soul: "SOUL.md",
9853
- identity: "IDENTITY.md",
9854
- user: "USER.md",
9855
- tools: "TOOLS.md",
9856
- bootstrap: "BOOTSTRAP.md"
9606
+ agents: "/agent/AGENTS.md",
9607
+ soul: "/agent/SOUL.md",
9608
+ identity: "/agent/IDENTITY.md",
9609
+ user: "/agent/USER.md",
9610
+ tools: "/agent/TOOLS.md",
9611
+ bootstrap: "/agent/BOOTSTRAP.md"
9857
9612
  };
9858
9613
  var BOOTSTRAP_SECTION_HEADERS = {
9859
9614
  agents: "## Operating Instructions",
@@ -9876,14 +9631,14 @@ Document available tools and their usage notes here.`,
9876
9631
  async function createBootstrapFiles(config, backend, stateAndStore) {
9877
9632
  const resolvedBackend = await getBackend2(backend, stateAndStore);
9878
9633
  try {
9879
- const agentsContent = await resolvedBackend.read("/AGENTS.md", 0, 1);
9634
+ const agentsContent = await resolvedBackend.read("/agent/AGENTS.md", 0, 1);
9880
9635
  if (!agentsContent.includes("Error:")) {
9881
9636
  return;
9882
9637
  }
9883
9638
  } catch (error) {
9884
9639
  }
9885
9640
  for (const [key, filename] of Object.entries(BOOTSTRAP_FILE_NAMES)) {
9886
- const filePath = "/" + filename;
9641
+ const filePath = filename;
9887
9642
  try {
9888
9643
  const content = config[key] || DEFAULT_BOOTSTRAP_CONTENT[key];
9889
9644
  await resolvedBackend.write(filePath, content);
@@ -9897,7 +9652,7 @@ async function buildBootstrapPromptSections(backend, stateAndStore) {
9897
9652
  const sections = [];
9898
9653
  const fileOrder = ["agents", "soul", "identity", "user", "tools", "bootstrap"];
9899
9654
  for (const key of fileOrder) {
9900
- const filePath = "/" + BOOTSTRAP_FILE_NAMES[key];
9655
+ const filePath = BOOTSTRAP_FILE_NAMES[key];
9901
9656
  try {
9902
9657
  const content = await resolvedBackend.read(filePath);
9903
9658
  if (content && !content.includes("Error:") && content.trim()) {
@@ -9933,14 +9688,13 @@ function createClawMiddleware(options = {}) {
9933
9688
  if (injectBootstrapFiles && backend) {
9934
9689
  const stateAndStore = {
9935
9690
  state: request.state || {},
9936
- store: request.store
9691
+ store: request.store,
9692
+ ...request.runtime.context.runConfig
9937
9693
  };
9938
9694
  const bootstrapSections = await buildBootstrapPromptSections(backend, stateAndStore);
9939
9695
  if (bootstrapSections.length > 0) {
9940
9696
  const bootstrapContext = `
9941
9697
 
9942
-
9943
-
9944
9698
  ${bootstrapSections.join("\n\n")}
9945
9699
 
9946
9700
  `;
@@ -9953,14 +9707,207 @@ ${bootstrapSections.join("\n\n")}
9953
9707
  });
9954
9708
  }
9955
9709
 
9710
+ // src/middlewares/unknownToolHandlerMiddleware.ts
9711
+ var import_langchain53 = require("langchain");
9712
+ var import_messages = require("@langchain/core/messages");
9713
+ function createUnknownToolHandlerMiddleware(config = {}) {
9714
+ const {
9715
+ strategy = "error",
9716
+ errorMessageTemplate = (name, tools) => `Error: Tool "${name}" does not exist.
9717
+
9718
+ Available tools:
9719
+ ` + tools.map((t) => ` - ${t}`).join("\n") + `
9720
+
9721
+ Please select a valid tool from the list above.`
9722
+ } = config;
9723
+ return (0, import_langchain53.createMiddleware)({
9724
+ name: "UnknownToolHandlerMiddleware",
9725
+ /**
9726
+ * wrapModelCall hook
9727
+ *
9728
+ * The only place to access request.tools (all available tools).
9729
+ * Identifies unknown tools and stores error info in metadata.
9730
+ *
9731
+ * Key: Preserve all tool_calls in original AIMessage, including unknown ones.
9732
+ * This allows the model to see what it selected in the next round.
9733
+ */
9734
+ wrapModelCall: async (request, handler) => {
9735
+ const availableTools = request.tools || [];
9736
+ const availableToolNames = availableTools.map((t) => t.name);
9737
+ const availableToolSet = new Set(availableToolNames);
9738
+ const aiResponse = await handler(request);
9739
+ if (!aiResponse.tool_calls || aiResponse.tool_calls.length === 0) {
9740
+ return aiResponse;
9741
+ }
9742
+ const unknownToolCalls = [];
9743
+ for (const toolCall of aiResponse.tool_calls) {
9744
+ if (!availableToolSet.has(toolCall.name)) {
9745
+ unknownToolCalls.push(toolCall);
9746
+ }
9747
+ }
9748
+ if (unknownToolCalls.length === 0) {
9749
+ return aiResponse;
9750
+ }
9751
+ if (strategy === "strict") {
9752
+ const unknownNames = unknownToolCalls.map((t) => t.name).join(", ");
9753
+ throw new Error(
9754
+ `Unknown tools detected: ${unknownNames}. Available tools: ${availableToolNames.join(", ")}`
9755
+ );
9756
+ }
9757
+ const unknownToolErrors = unknownToolCalls.map((toolCall) => ({
9758
+ toolName: toolCall.name,
9759
+ toolCallId: toolCall.id,
9760
+ errorMessage: errorMessageTemplate(toolCall.name, availableToolNames)
9761
+ }));
9762
+ const modifiedResponse = new import_messages.AIMessage({
9763
+ content: aiResponse.content,
9764
+ tool_calls: aiResponse.tool_calls,
9765
+ // Key: preserve all tool_calls, don't delete unknown
9766
+ response_metadata: {
9767
+ ...aiResponse.response_metadata,
9768
+ _unknownToolErrors: unknownToolErrors
9769
+ }
9770
+ });
9771
+ if (aiResponse.id) {
9772
+ modifiedResponse.id = aiResponse.id;
9773
+ }
9774
+ return modifiedResponse;
9775
+ },
9776
+ /**
9777
+ * afterModel hook
9778
+ *
9779
+ * Processes unknown tool errors stored in metadata.
9780
+ * Generates error ToolMessages and jumps back to model.
9781
+ *
9782
+ * Key: Uses jumpTo: "model" to form agent loop.
9783
+ * Without jumpTo, the graph would end after ToolNode without returning to model.
9784
+ */
9785
+ afterModel: {
9786
+ canJumpTo: ["model"],
9787
+ hook: async (state) => {
9788
+ const { messages } = state;
9789
+ if (!messages || messages.length === 0) {
9790
+ return;
9791
+ }
9792
+ const lastMessage = messages[messages.length - 1];
9793
+ if (!import_messages.AIMessage.isInstance(lastMessage)) {
9794
+ return;
9795
+ }
9796
+ const unknownToolErrors = lastMessage.response_metadata?._unknownToolErrors;
9797
+ if (!unknownToolErrors || !Array.isArray(unknownToolErrors) || unknownToolErrors.length === 0) {
9798
+ return;
9799
+ }
9800
+ const errorToolMessages = unknownToolErrors.map(
9801
+ (error) => new import_messages.ToolMessage({
9802
+ content: error.errorMessage,
9803
+ name: error.toolName,
9804
+ tool_call_id: error.toolCallId,
9805
+ status: "error"
9806
+ })
9807
+ );
9808
+ delete lastMessage.response_metadata._unknownToolErrors;
9809
+ return {
9810
+ messages: errorToolMessages,
9811
+ jumpTo: "model"
9812
+ };
9813
+ }
9814
+ }
9815
+ });
9816
+ }
9817
+
9818
+ // src/deep_agent_new/middleware/date.ts
9819
+ var import_langchain54 = require("langchain");
9820
+ var import_zod49 = require("zod");
9821
+ function formatCurrentDate(timezone = "UTC") {
9822
+ const now = /* @__PURE__ */ new Date();
9823
+ let validTimezone = timezone;
9824
+ try {
9825
+ Intl.DateTimeFormat(void 0, { timeZone: timezone });
9826
+ } catch {
9827
+ validTimezone = "UTC";
9828
+ }
9829
+ const dateFormatOptions = {
9830
+ timeZone: validTimezone,
9831
+ year: "numeric",
9832
+ month: "2-digit",
9833
+ day: "2-digit"
9834
+ };
9835
+ return new Intl.DateTimeFormat("en-US", dateFormatOptions).format(now);
9836
+ }
9837
+ function generateDateContext(timezone = "UTC") {
9838
+ const formattedDate = formatCurrentDate(timezone);
9839
+ if (timezone === "UTC") {
9840
+ return `Current Date: ${formattedDate}`;
9841
+ }
9842
+ const utcDate = formatCurrentDate("UTC");
9843
+ return `Current Date: ${formattedDate} (UTC: ${utcDate})`;
9844
+ }
9845
+ function createDateMiddleware(options = {}) {
9846
+ const timezone = options.timezone || "UTC";
9847
+ const dateContext = generateDateContext(timezone);
9848
+ return (0, import_langchain54.createMiddleware)({
9849
+ name: "DateMiddleware",
9850
+ tools: [
9851
+ (0, import_langchain54.tool)(
9852
+ async () => {
9853
+ const now = /* @__PURE__ */ new Date();
9854
+ let validTimezone = timezone;
9855
+ try {
9856
+ Intl.DateTimeFormat(void 0, { timeZone: timezone });
9857
+ } catch {
9858
+ validTimezone = "UTC";
9859
+ }
9860
+ const localTimeOptions = {
9861
+ timeZone: validTimezone,
9862
+ year: "numeric",
9863
+ month: "2-digit",
9864
+ day: "2-digit",
9865
+ hour: "2-digit",
9866
+ minute: "2-digit",
9867
+ second: "2-digit",
9868
+ hour12: false
9869
+ };
9870
+ const localTime = new Intl.DateTimeFormat("en-US", localTimeOptions).format(now);
9871
+ return JSON.stringify({
9872
+ local_time: `${localTime} (${validTimezone})`,
9873
+ iso_date: now.toISOString().split("T")[0],
9874
+ timestamp: now.toISOString(),
9875
+ timezone: validTimezone
9876
+ });
9877
+ },
9878
+ {
9879
+ name: "get_current_date_time",
9880
+ 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.",
9881
+ schema: import_zod49.z.object({})
9882
+ }
9883
+ )
9884
+ ],
9885
+ wrapModelCall: async (request, handler) => {
9886
+ const currentSystemPrompt = request.systemPrompt || "";
9887
+ const newSystemPrompt = currentSystemPrompt ? `${dateContext}
9888
+
9889
+ ${currentSystemPrompt}` : dateContext;
9890
+ return handler({
9891
+ ...request,
9892
+ systemPrompt: newSystemPrompt
9893
+ });
9894
+ }
9895
+ });
9896
+ }
9897
+
9956
9898
  // src/agent_lattice/builders/commonMiddleware.ts
9957
- async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
9899
+ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
9958
9900
  const middlewares = [];
9901
+ middlewares.push(createUnknownToolHandlerMiddleware());
9959
9902
  middlewares.push(createModelSelectorMiddleware());
9960
9903
  const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
9961
- if (filesystemConfig?.enabled && filesystemBackend) {
9962
- const options = { backend: filesystemBackend };
9963
- middlewares.push(createFilesystemMiddleware(options));
9904
+ const clawConfig = middlewareConfigs.find((m) => m.type === "claw");
9905
+ const needsFilesystemBackend = filesystemConfig?.enabled || clawConfig?.enabled;
9906
+ if (needsFilesystemBackend && filesystemBackend) {
9907
+ if (!fsIsExised) {
9908
+ const options = { backend: filesystemBackend };
9909
+ middlewares.push(createFilesystemMiddleware(options));
9910
+ }
9964
9911
  }
9965
9912
  for (const config of middlewareConfigs) {
9966
9913
  if (!config.enabled || config.type === "filesystem") continue;
@@ -10008,55 +9955,531 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend) {
10008
9955
  break;
10009
9956
  case "claw":
10010
9957
  if (filesystemBackend) {
10011
- const clawConfig = config.config;
9958
+ const clawMiddlewareConfig = config.config;
10012
9959
  middlewares.push(createClawMiddleware({
10013
9960
  backend: filesystemBackend,
10014
- injectBootstrapFiles: clawConfig.injectBootstrapFiles ?? true,
10015
- bootstrapFiles: clawConfig.bootstrapFiles ?? {}
9961
+ injectBootstrapFiles: clawMiddlewareConfig.injectBootstrapFiles ?? true,
9962
+ bootstrapFiles: clawMiddlewareConfig.bootstrapFiles ?? {}
10016
9963
  }));
9964
+ } else {
9965
+ console.warn("[claw middleware] Filesystem backend not available. Claw middleware requires filesystem backend to function.");
10017
9966
  }
10018
9967
  break;
9968
+ case "date":
9969
+ middlewares.push(createDateMiddleware(config.config));
9970
+ break;
9971
+ }
9972
+ }
9973
+ return middlewares;
9974
+ }
9975
+
9976
+ // src/deep_agent_new/backends/sandboxFiles.ts
9977
+ var import_sandbox2 = require("@agent-infra/sandbox");
9978
+ var path3 = __toESM(require("path"));
9979
+ var SandboxFilesystem = class {
9980
+ /**
9981
+ * Create a new SandboxFilesystem instance.
9982
+ *
9983
+ * @param options - Configuration options
9984
+ * @param options.baseURL - Base URL of the sandbox service (default: 'http://localhost:8080')
9985
+ * @param options.maxFileSizeMb - Maximum file size in MB (default: 10)
9986
+ * @param options.sandboxInstance - Optional Sandbox instance (if provided, baseURL is ignored)
9987
+ */
9988
+ constructor(options = {}) {
9989
+ const {
9990
+ baseURL = "http://localhost:8080",
9991
+ workingDirectory = "/",
9992
+ maxFileSizeMb = 10,
9993
+ sandboxInstance
9994
+ } = options;
9995
+ this.sandbox = sandboxInstance || new import_sandbox2.SandboxClient({ baseUrl: baseURL, environment: "" });
9996
+ this.sandbox.mcp.listMcpServers().then((servers) => {
9997
+ });
9998
+ this.sandbox.mcp.listMcpTools("browser").then((tools) => {
9999
+ });
10000
+ this.baseURL = baseURL;
10001
+ this.maxFileSizeBytes = maxFileSizeMb * 1024 * 1024;
10002
+ this.workingDirectory = workingDirectory;
10003
+ this.homeDir = "/home/gem";
10004
+ }
10005
+ resolvePath(virtualPath) {
10006
+ return path3.join(this.homeDir, this.workingDirectory, virtualPath);
10007
+ }
10008
+ /**
10009
+ * Convert a real filesystem path to a virtual path.
10010
+ *
10011
+ * @param realPath - Real filesystem path
10012
+ * @returns Virtual path starting with /
10013
+ */
10014
+ toVirtualPath(realPath) {
10015
+ const rootPath = path3.join(this.homeDir, this.workingDirectory);
10016
+ const relative4 = path3.relative(rootPath, realPath);
10017
+ const normalized = relative4.split(path3.sep).join("/");
10018
+ return "/" + normalized;
10019
+ }
10020
+ /**
10021
+ * List files and directories in the specified directory (non-recursive).
10022
+ *
10023
+ * @param dirPath - Virtual directory path (must start with /)
10024
+ * @returns List of FileInfo objects for files and directories directly in the directory.
10025
+ * Directories have a trailing / in their path and is_dir=true.
10026
+ */
10027
+ async lsInfo(dirPath) {
10028
+ try {
10029
+ const resolvedPath = this.resolvePath(dirPath);
10030
+ const result = await this.sandbox.file.listPath({
10031
+ path: resolvedPath,
10032
+ recursive: false,
10033
+ show_hidden: false,
10034
+ max_depth: 0,
10035
+ include_size: false,
10036
+ include_permissions: false,
10037
+ sort_by: "name",
10038
+ sort_desc: false
10039
+ });
10040
+ if (!result.ok) {
10041
+ throw result.error;
10042
+ }
10043
+ const files = result.body?.data?.files?.map((file) => ({
10044
+ path: this.toVirtualPath(file.path),
10045
+ is_dir: file.is_directory,
10046
+ size: file.size,
10047
+ modified_at: file.modified_time
10048
+ })) || [];
10049
+ return files;
10050
+ } catch (e) {
10051
+ console.error(`Error listing files in ${dirPath}:`, e);
10052
+ return [];
10053
+ }
10054
+ }
10055
+ /**
10056
+ * Read file content with line numbers.
10057
+ *
10058
+ * @param filePath - Virtual file path (must start with /)
10059
+ * @param offset - Line offset to start reading from (0-indexed)
10060
+ * @param limit - Maximum number of lines to read
10061
+ * @returns Formatted file content with line numbers, or error message
10062
+ */
10063
+ async read(filePath, offset = 0, limit = 1e4) {
10064
+ try {
10065
+ const resolvedPath = this.resolvePath(filePath);
10066
+ let content;
10067
+ const result = await this.sandbox.file.readFile({
10068
+ file: resolvedPath,
10069
+ start_line: offset,
10070
+ end_line: limit
10071
+ });
10072
+ if (!result.ok) {
10073
+ throw result.error;
10074
+ }
10075
+ content = result.body?.data?.content || "";
10076
+ return content;
10077
+ } catch (e) {
10078
+ return `Error: File '${filePath}' not found`;
10079
+ }
10080
+ }
10081
+ /**
10082
+ * Read file content as raw FileData.
10083
+ *
10084
+ * @param filePath - Virtual file path (must start with /)
10085
+ * @returns Raw file content as FileData
10086
+ */
10087
+ async readRaw(filePath) {
10088
+ try {
10089
+ const content = await this.read(filePath);
10090
+ return {
10091
+ content: content.split("\n"),
10092
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
10093
+ modified_at: (/* @__PURE__ */ new Date()).toISOString()
10094
+ };
10095
+ } catch (e) {
10096
+ throw new Error(`Error reading file '${filePath}': ${e.message}`);
10097
+ }
10098
+ }
10099
+ /**
10100
+ * Create a new file with content.
10101
+ * Returns WriteResult. External storage sets filesUpdate=null.
10102
+ *
10103
+ * @param filePath - Virtual file path (must start with /)
10104
+ * @param content - File content as string
10105
+ * @returns WriteResult with error populated on failure
10106
+ */
10107
+ async write(filePath, content) {
10108
+ try {
10109
+ const resolvedPath = this.resolvePath(filePath);
10110
+ const result = await this.sandbox.file.writeFile({
10111
+ file: resolvedPath,
10112
+ content,
10113
+ "encoding": "utf-8",
10114
+ "append": false
10115
+ // sudo: true
10116
+ });
10117
+ if (!result.ok) {
10118
+ console.error(result.error);
10119
+ throw result.error;
10120
+ }
10121
+ return {
10122
+ path: filePath,
10123
+ filesUpdate: {
10124
+ [filePath]: {
10125
+ content: content.split("\n"),
10126
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
10127
+ modified_at: (/* @__PURE__ */ new Date()).toISOString()
10128
+ }
10129
+ }
10130
+ };
10131
+ } catch (e) {
10132
+ throw new Error(`Error writing file '${filePath}': ${e.message}`);
10133
+ }
10134
+ }
10135
+ /**
10136
+ * Edit a file by replacing string occurrences.
10137
+ * Returns EditResult. External storage sets filesUpdate=null.
10138
+ *
10139
+ * @param filePath - Virtual file path (must start with /)
10140
+ * @param oldString - String to find and replace
10141
+ * @param newString - Replacement string
10142
+ * @param replaceAll - If true, replace all occurrences (default: false)
10143
+ * @returns EditResult with error, path, filesUpdate, and occurrences
10144
+ */
10145
+ async edit(filePath, oldString, newString, replaceAll = false) {
10146
+ try {
10147
+ const resolvedPath = this.resolvePath(filePath);
10148
+ const result = await this.sandbox.file.strReplaceEditor({
10149
+ command: "str_replace",
10150
+ path: resolvedPath,
10151
+ old_str: oldString,
10152
+ new_str: newString,
10153
+ replace_mode: replaceAll ? "ALL" : "FIRST"
10154
+ });
10155
+ if (!result.ok) {
10156
+ throw result.error;
10157
+ }
10158
+ return {
10159
+ path: filePath,
10160
+ filesUpdate: null
10161
+ };
10162
+ } catch (e) {
10163
+ throw new Error(`Error editing file '${filePath}': ${e.message}`);
10164
+ }
10165
+ }
10166
+ /**
10167
+ * Structured search results or error string for invalid input.
10168
+ *
10169
+ * Searches file contents for a regex pattern within the sandbox.
10170
+ *
10171
+ * @param pattern - Regex pattern to search for
10172
+ * @param searchPath - Base path to search from (default: "/")
10173
+ * @param glob - Optional glob pattern to filter files (e.g., "*.py")
10174
+ * @returns List of GrepMatch objects or error string for invalid regex
10175
+ */
10176
+ async grepRaw(pattern, searchPath = "/", glob = null) {
10177
+ let baseFull;
10178
+ baseFull = this.resolvePath(searchPath || "/");
10179
+ const result = await this.sandbox.file.findFiles({
10180
+ path: baseFull,
10181
+ glob: glob || "**/*"
10182
+ });
10183
+ if (!result.ok) {
10184
+ throw result.error;
10185
+ }
10186
+ const filePaths = result.body?.data?.files || [];
10187
+ const matches = [];
10188
+ for (const absolutePath of filePaths) {
10189
+ const fileData = await this.sandbox.file.searchInFile({
10190
+ file: absolutePath,
10191
+ regex: pattern
10192
+ });
10193
+ if (!fileData.ok) {
10194
+ continue;
10195
+ }
10196
+ const matchesData = fileData.body?.data?.matches || [];
10197
+ const matchLines = fileData.body?.data?.line_numbers || [];
10198
+ matchesData.forEach((match, index) => {
10199
+ matches.push({
10200
+ path: this.toVirtualPath(absolutePath),
10201
+ line: matchLines[index],
10202
+ text: match
10203
+ });
10204
+ });
10205
+ }
10206
+ return matches;
10207
+ }
10208
+ /**
10209
+ * Structured glob matching returning FileInfo objects.
10210
+ *
10211
+ * @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
10212
+ * @param searchPath - Base path to search from (default: "/")
10213
+ * @returns List of FileInfo objects matching the pattern
10214
+ */
10215
+ async globInfo(pattern, searchPath = "/") {
10216
+ if (pattern.startsWith("/")) {
10217
+ pattern = pattern.substring(1);
10218
+ }
10219
+ const resolvedSearchPath = this.resolvePath(searchPath);
10220
+ const result = await this.sandbox.file.findFiles({
10221
+ path: resolvedSearchPath,
10222
+ glob: pattern || "**/*"
10223
+ });
10224
+ if (!result.ok) {
10225
+ throw result.error;
10226
+ }
10227
+ const results = [];
10228
+ for (const filePath of result.body?.data?.files || []) {
10229
+ const fileInfo = await this.sandbox.file.listPath({
10230
+ path: filePath,
10231
+ recursive: false,
10232
+ show_hidden: false,
10233
+ max_depth: 1,
10234
+ include_size: false,
10235
+ include_permissions: false
10236
+ });
10237
+ if (!fileInfo.ok) {
10238
+ continue;
10239
+ }
10240
+ results.push({
10241
+ path: this.toVirtualPath(filePath),
10242
+ is_dir: false,
10243
+ size: fileInfo.body?.data?.files?.[0]?.size,
10244
+ modified_at: fileInfo.body?.data?.files?.[0]?.modified_time
10245
+ });
10246
+ }
10247
+ return results;
10248
+ }
10249
+ };
10250
+
10251
+ // src/deep_agent_new/backends/composite.ts
10252
+ var CompositeBackend = class {
10253
+ constructor(defaultBackend, routes) {
10254
+ this.default = defaultBackend;
10255
+ this.routes = routes;
10256
+ this.sortedRoutes = Object.entries(routes).sort(
10257
+ (a, b) => b[0].length - a[0].length
10258
+ );
10259
+ }
10260
+ /**
10261
+ * Determine which backend handles this key and strip prefix.
10262
+ *
10263
+ * @param key - Original file path
10264
+ * @returns Tuple of [backend, stripped_key] where stripped_key has the route
10265
+ * prefix removed (but keeps leading slash).
10266
+ */
10267
+ getBackendAndKey(key) {
10268
+ for (const [prefix, backend] of this.sortedRoutes) {
10269
+ if (key.startsWith(prefix)) {
10270
+ const suffix = key.substring(prefix.length);
10271
+ const strippedKey = suffix ? "/" + suffix : "/";
10272
+ return [backend, strippedKey];
10273
+ }
10274
+ }
10275
+ return [this.default, key];
10276
+ }
10277
+ /**
10278
+ * List files and directories in the specified directory (non-recursive).
10279
+ *
10280
+ * @param path - Absolute path to directory
10281
+ * @returns List of FileInfo objects with route prefixes added, for files and directories
10282
+ * directly in the directory. Directories have a trailing / in their path and is_dir=true.
10283
+ */
10284
+ async lsInfo(path5) {
10285
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10286
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10287
+ const suffix = path5.substring(routePrefix.length);
10288
+ const searchPath = suffix ? "/" + suffix : "/";
10289
+ const infos = await backend.lsInfo(searchPath);
10290
+ const prefixed = [];
10291
+ for (const fi of infos) {
10292
+ prefixed.push({
10293
+ ...fi,
10294
+ path: routePrefix.slice(0, -1) + fi.path
10295
+ });
10296
+ }
10297
+ return prefixed;
10298
+ }
10299
+ }
10300
+ if (path5 === "/") {
10301
+ const results = [];
10302
+ const defaultInfos = await this.default.lsInfo(path5);
10303
+ results.push(...defaultInfos);
10304
+ for (const [routePrefix] of this.sortedRoutes) {
10305
+ results.push({
10306
+ path: routePrefix,
10307
+ is_dir: true,
10308
+ size: 0,
10309
+ modified_at: ""
10310
+ });
10311
+ }
10312
+ results.sort((a, b) => a.path.localeCompare(b.path));
10313
+ return results;
10314
+ }
10315
+ return await this.default.lsInfo(path5);
10316
+ }
10317
+ /**
10318
+ * Read file content, routing to appropriate backend.
10319
+ *
10320
+ * @param filePath - Absolute file path
10321
+ * @param offset - Line offset to start reading from (0-indexed)
10322
+ * @param limit - Maximum number of lines to read
10323
+ * @returns Formatted file content with line numbers, or error message
10324
+ */
10325
+ async read(filePath, offset = 0, limit = 2e3) {
10326
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10327
+ return await backend.read(strippedKey, offset, limit);
10328
+ }
10329
+ /**
10330
+ * Read file content as raw FileData.
10331
+ *
10332
+ * @param filePath - Absolute file path
10333
+ * @returns Raw file content as FileData
10334
+ */
10335
+ async readRaw(filePath) {
10336
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10337
+ return await backend.readRaw(strippedKey);
10338
+ }
10339
+ /**
10340
+ * Structured search results or error string for invalid input.
10341
+ */
10342
+ async grepRaw(pattern, path5 = "/", glob = null) {
10343
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10344
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10345
+ const searchPath = path5.substring(routePrefix.length - 1);
10346
+ const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
10347
+ if (typeof raw === "string") {
10348
+ return raw;
10349
+ }
10350
+ return raw.map((m) => ({
10351
+ ...m,
10352
+ path: routePrefix.slice(0, -1) + m.path
10353
+ }));
10354
+ }
10355
+ }
10356
+ const allMatches = [];
10357
+ const rawDefault = await this.default.grepRaw(pattern, path5, glob);
10358
+ if (typeof rawDefault === "string") {
10359
+ return rawDefault;
10360
+ }
10361
+ allMatches.push(...rawDefault);
10362
+ for (const [routePrefix, backend] of Object.entries(this.routes)) {
10363
+ const raw = await backend.grepRaw(pattern, "/", glob);
10364
+ if (typeof raw === "string") {
10365
+ return raw;
10366
+ }
10367
+ allMatches.push(
10368
+ ...raw.map((m) => ({
10369
+ ...m,
10370
+ path: routePrefix.slice(0, -1) + m.path
10371
+ }))
10372
+ );
10373
+ }
10374
+ return allMatches;
10375
+ }
10376
+ /**
10377
+ * Structured glob matching returning FileInfo objects.
10378
+ */
10379
+ async globInfo(pattern, path5 = "/") {
10380
+ const results = [];
10381
+ for (const [routePrefix, backend] of this.sortedRoutes) {
10382
+ if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
10383
+ const searchPath = path5.substring(routePrefix.length - 1);
10384
+ const infos = await backend.globInfo(pattern, searchPath || "/");
10385
+ return infos.map((fi) => ({
10386
+ ...fi,
10387
+ path: routePrefix.slice(0, -1) + fi.path
10388
+ }));
10389
+ }
10390
+ }
10391
+ const defaultInfos = await this.default.globInfo(pattern, path5);
10392
+ results.push(...defaultInfos);
10393
+ for (const [routePrefix, backend] of Object.entries(this.routes)) {
10394
+ const infos = await backend.globInfo(pattern, "/");
10395
+ results.push(
10396
+ ...infos.map((fi) => ({
10397
+ ...fi,
10398
+ path: routePrefix.slice(0, -1) + fi.path
10399
+ }))
10400
+ );
10401
+ }
10402
+ results.sort((a, b) => a.path.localeCompare(b.path));
10403
+ return results;
10404
+ }
10405
+ /**
10406
+ * Create a new file, routing to appropriate backend.
10407
+ *
10408
+ * @param filePath - Absolute file path
10409
+ * @param content - File content as string
10410
+ * @returns WriteResult with path or error
10411
+ */
10412
+ async write(filePath, content) {
10413
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10414
+ return await backend.write(strippedKey, content);
10415
+ }
10416
+ /**
10417
+ * Edit a file, routing to appropriate backend.
10418
+ *
10419
+ * @param filePath - Absolute file path
10420
+ * @param oldString - String to find and replace
10421
+ * @param newString - Replacement string
10422
+ * @param replaceAll - If true, replace all occurrences
10423
+ * @returns EditResult with path, occurrences, or error
10424
+ */
10425
+ async edit(filePath, oldString, newString, replaceAll = false) {
10426
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
10427
+ return await backend.edit(strippedKey, oldString, newString, replaceAll);
10428
+ }
10429
+ };
10430
+
10431
+ // src/agent_lattice/builders/filesystemBackend.ts
10432
+ function createFilesystemBackendFactory(middlewareConfigs, defualtRootLevel = "project", routesLevelConfig = {
10433
+ "/agent/": "agent"
10434
+ //默认配置 agent目录就是agent级别的
10435
+ }) {
10436
+ const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
10437
+ if (!filesystemConfig || !filesystemConfig.enabled) {
10438
+ return void 0;
10439
+ }
10440
+ const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
10441
+ return async (stateAndStore) => {
10442
+ const { tenantId, workspaceId, projectId, assistant_id } = stateAndStore;
10443
+ let sandboxName = "global";
10444
+ if (isolatedLevel === "agent") {
10445
+ sandboxName = "agent";
10446
+ } else if (isolatedLevel === "thread") {
10447
+ sandboxName = "thread";
10448
+ }
10449
+ const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
10450
+ if (!sandboxManager) {
10451
+ throw new Error("Sandbox manager not found");
10019
10452
  }
10020
- }
10021
- return middlewares;
10453
+ const getWS = (rootLevel) => {
10454
+ let workingDirectory = `/tenants/${tenantId}`;
10455
+ if (assistant_id && rootLevel === "agent") {
10456
+ workingDirectory = `/tenants/${tenantId}/agents/${assistant_id}`;
10457
+ } else if (workspaceId && projectId && rootLevel === "project") {
10458
+ workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
10459
+ }
10460
+ return workingDirectory;
10461
+ };
10462
+ const sandboxInstance = await sandboxManager.createSandbox(sandboxName);
10463
+ const sandboxfs = new SandboxFilesystem({
10464
+ sandboxInstance,
10465
+ workingDirectory: getWS(defualtRootLevel)
10466
+ });
10467
+ const routers = Object.keys(routesLevelConfig).reduce((pre, curr) => ({
10468
+ ...pre,
10469
+ [curr]: new SandboxFilesystem({
10470
+ sandboxInstance,
10471
+ workingDirectory: getWS(routesLevelConfig[curr])
10472
+ })
10473
+ }), {});
10474
+ const compositeBackend = new CompositeBackend(sandboxfs, {
10475
+ ...routers
10476
+ });
10477
+ return compositeBackend;
10478
+ };
10022
10479
  }
10023
10480
 
10024
10481
  // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
10025
10482
  var ReActAgentGraphBuilder = class {
10026
- createFilesystemBackendFactory(middlewareConfigs, agentLattice) {
10027
- const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
10028
- if (!filesystemConfig || !filesystemConfig.enabled) {
10029
- return void 0;
10030
- }
10031
- const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
10032
- const agentTenantId = agentLattice.config.tenantId;
10033
- return async (stateAndStore) => {
10034
- const { tenantId: runtimeTenantId, workspaceId, projectId } = stateAndStore;
10035
- const tenantId = runtimeTenantId || agentTenantId;
10036
- let sandboxName = "global";
10037
- if (isolatedLevel === "agent") {
10038
- sandboxName = "agent";
10039
- } else if (isolatedLevel === "thread") {
10040
- sandboxName = "thread";
10041
- }
10042
- const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
10043
- if (!sandboxManager) {
10044
- throw new Error("Sandbox manager not found");
10045
- }
10046
- let workingDirectory = "/";
10047
- if (workspaceId && projectId) {
10048
- if (tenantId) {
10049
- workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
10050
- } else {
10051
- workingDirectory = `/${workspaceId}/${projectId}`;
10052
- }
10053
- }
10054
- return new SandboxFilesystem({
10055
- sandboxInstance: await sandboxManager.createSandbox(sandboxName),
10056
- workingDirectory
10057
- });
10058
- };
10059
- }
10060
10483
  async createMiddlewares(middlewareConfigs) {
10061
10484
  return await createCommonMiddlewares(middlewareConfigs);
10062
10485
  }
@@ -10069,14 +10492,14 @@ var ReActAgentGraphBuilder = class {
10069
10492
  */
10070
10493
  async build(agentLattice, params) {
10071
10494
  const tools = params.tools.map((t) => {
10072
- const tool50 = getToolClient(t.key);
10073
- return tool50;
10074
- }).filter((tool50) => tool50 !== void 0);
10495
+ const tool51 = getToolClient(t.key);
10496
+ return tool51;
10497
+ }).filter((tool51) => tool51 !== void 0);
10075
10498
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
10076
10499
  const middlewareConfigs = params.middleware || [];
10077
- const filesystemBackend = this.createFilesystemBackendFactory(middlewareConfigs, agentLattice);
10500
+ const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
10078
10501
  const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend);
10079
- return (0, import_langchain53.createAgent)({
10502
+ return (0, import_langchain55.createAgent)({
10080
10503
  model: params.model,
10081
10504
  tools,
10082
10505
  systemPrompt: params.prompt,
@@ -10089,13 +10512,13 @@ var ReActAgentGraphBuilder = class {
10089
10512
  };
10090
10513
 
10091
10514
  // src/deep_agent_new/agent.ts
10092
- var import_langchain57 = require("langchain");
10515
+ var import_langchain59 = require("langchain");
10093
10516
 
10094
10517
  // src/deep_agent_new/middleware/subagents.ts
10095
10518
  var import_v32 = require("zod/v3");
10096
- var import_langchain54 = require("langchain");
10519
+ var import_langchain56 = require("langchain");
10097
10520
  var import_langgraph7 = require("@langchain/langgraph");
10098
- var import_messages = require("@langchain/core/messages");
10521
+ var import_messages2 = require("@langchain/core/messages");
10099
10522
 
10100
10523
  // src/agent_worker/agent_worker_graph.ts
10101
10524
  var import_langgraph6 = require("@langchain/langgraph");
@@ -10655,7 +11078,7 @@ function returnCommandWithStateUpdate(result, toolCallId) {
10655
11078
  update: {
10656
11079
  ...stateUpdate,
10657
11080
  messages: [
10658
- new import_langchain54.ToolMessage({
11081
+ new import_langchain56.ToolMessage({
10659
11082
  content: lastMessage?.content || "Task Failed to complete",
10660
11083
  tool_call_id: toolCallId,
10661
11084
  name: "task"
@@ -10680,10 +11103,10 @@ function getSubagents(options) {
10680
11103
  const generalPurposeMiddleware = [...defaultSubagentMiddleware];
10681
11104
  if (defaultInterruptOn) {
10682
11105
  generalPurposeMiddleware.push(
10683
- (0, import_langchain54.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
11106
+ (0, import_langchain56.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
10684
11107
  );
10685
11108
  }
10686
- const generalPurposeSubagent = (0, import_langchain54.createAgent)({
11109
+ const generalPurposeSubagent = (0, import_langchain56.createAgent)({
10687
11110
  model: defaultModel,
10688
11111
  systemPrompt: DEFAULT_SUBAGENT_PROMPT,
10689
11112
  tools: defaultTools,
@@ -10706,8 +11129,8 @@ function getSubagents(options) {
10706
11129
  const middleware = agentParams.middleware ? [...defaultSubagentMiddleware, ...agentParams.middleware] : [...defaultSubagentMiddleware];
10707
11130
  const interruptOn = agentParams.interruptOn || defaultInterruptOn;
10708
11131
  if (interruptOn)
10709
- middleware.push((0, import_langchain54.humanInTheLoopMiddleware)({ interruptOn }));
10710
- agents[agentParams.key] = (0, import_langchain54.createAgent)({
11132
+ middleware.push((0, import_langchain56.humanInTheLoopMiddleware)({ interruptOn }));
11133
+ agents[agentParams.key] = (0, import_langchain56.createAgent)({
10711
11134
  model: agentParams.model ?? defaultModel,
10712
11135
  systemPrompt: agentParams.systemPrompt,
10713
11136
  tools: agentParams.tools ?? defaultTools,
@@ -10737,7 +11160,7 @@ function createTaskTool(options) {
10737
11160
  generalPurposeAgent
10738
11161
  });
10739
11162
  const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
10740
- return (0, import_langchain54.tool)(
11163
+ return (0, import_langchain56.tool)(
10741
11164
  async (input, config) => {
10742
11165
  const { description, subagent_type } = input;
10743
11166
  let assistant_id = subagent_type;
@@ -10767,7 +11190,7 @@ function createTaskTool(options) {
10767
11190
  }
10768
11191
  const currentState = (0, import_langgraph7.getCurrentTaskInput)();
10769
11192
  const subagentState = filterStateForSubagent(currentState);
10770
- subagentState.messages = [new import_messages.HumanMessage({ content: description })];
11193
+ subagentState.messages = [new import_messages2.HumanMessage({ content: description })];
10771
11194
  const subagent_thread_id = config.configurable?.thread_id + "____" + assistant_id + "_" + config.toolCall.id;
10772
11195
  const workerResult = await agentWorkerGraph.invoke({
10773
11196
  assistant_id,
@@ -10791,7 +11214,7 @@ function createTaskTool(options) {
10791
11214
  return new import_langgraph7.Command({
10792
11215
  update: {
10793
11216
  messages: [
10794
- new import_langchain54.ToolMessage({
11217
+ new import_langchain56.ToolMessage({
10795
11218
  content: error instanceof Error ? error.message : "Task Failed to complete",
10796
11219
  tool_call_id: config.toolCall.id,
10797
11220
  name: "task"
@@ -10835,7 +11258,7 @@ function createSubAgentMiddleware(options) {
10835
11258
  generalPurposeAgent,
10836
11259
  taskDescription
10837
11260
  });
10838
- return (0, import_langchain54.createMiddleware)({
11261
+ return (0, import_langchain56.createMiddleware)({
10839
11262
  name: "subAgentMiddleware",
10840
11263
  tools: [taskTool],
10841
11264
  wrapModelCall: async (request, handler) => {
@@ -10855,11 +11278,11 @@ ${systemPrompt}` : systemPrompt;
10855
11278
  }
10856
11279
 
10857
11280
  // src/deep_agent_new/middleware/patch_tool_calls.ts
10858
- var import_langchain55 = require("langchain");
10859
- var import_messages2 = require("@langchain/core/messages");
11281
+ var import_langchain57 = require("langchain");
11282
+ var import_messages3 = require("@langchain/core/messages");
10860
11283
  var import_langgraph8 = require("@langchain/langgraph");
10861
11284
  function createPatchToolCallsMiddleware() {
10862
- return (0, import_langchain55.createMiddleware)({
11285
+ return (0, import_langchain57.createMiddleware)({
10863
11286
  name: "patchToolCallsMiddleware",
10864
11287
  beforeAgent: async (state) => {
10865
11288
  const messages = state.messages;
@@ -10870,15 +11293,15 @@ function createPatchToolCallsMiddleware() {
10870
11293
  for (let i = 0; i < messages.length; i++) {
10871
11294
  const msg = messages[i];
10872
11295
  patchedMessages.push(msg);
10873
- if (import_langchain55.AIMessage.isInstance(msg) && msg.tool_calls != null) {
11296
+ if (import_langchain57.AIMessage.isInstance(msg) && msg.tool_calls != null) {
10874
11297
  for (const toolCall of msg.tool_calls) {
10875
11298
  const correspondingToolMsg = messages.slice(i).find(
10876
- (m) => import_langchain55.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id
11299
+ (m) => import_langchain57.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id
10877
11300
  );
10878
11301
  if (!correspondingToolMsg) {
10879
11302
  const toolMsg = `Tool call ${toolCall.name} with id ${toolCall.id} was cancelled - another message came in before it could be completed.`;
10880
11303
  patchedMessages.push(
10881
- new import_langchain55.ToolMessage({
11304
+ new import_langchain57.ToolMessage({
10882
11305
  content: toolMsg,
10883
11306
  name: toolCall.name,
10884
11307
  tool_call_id: toolCall.id
@@ -10890,7 +11313,7 @@ function createPatchToolCallsMiddleware() {
10890
11313
  }
10891
11314
  return {
10892
11315
  messages: [
10893
- new import_messages2.RemoveMessage({ id: import_langgraph8.REMOVE_ALL_MESSAGES }),
11316
+ new import_messages3.RemoveMessage({ id: import_langgraph8.REMOVE_ALL_MESSAGES }),
10894
11317
  ...patchedMessages
10895
11318
  ]
10896
11319
  };
@@ -11700,186 +12123,6 @@ var FilesystemBackend = class {
11700
12123
  }
11701
12124
  };
11702
12125
 
11703
- // src/deep_agent_new/backends/composite.ts
11704
- var CompositeBackend = class {
11705
- constructor(defaultBackend, routes) {
11706
- this.default = defaultBackend;
11707
- this.routes = routes;
11708
- this.sortedRoutes = Object.entries(routes).sort(
11709
- (a, b) => b[0].length - a[0].length
11710
- );
11711
- }
11712
- /**
11713
- * Determine which backend handles this key and strip prefix.
11714
- *
11715
- * @param key - Original file path
11716
- * @returns Tuple of [backend, stripped_key] where stripped_key has the route
11717
- * prefix removed (but keeps leading slash).
11718
- */
11719
- getBackendAndKey(key) {
11720
- for (const [prefix, backend] of this.sortedRoutes) {
11721
- if (key.startsWith(prefix)) {
11722
- const suffix = key.substring(prefix.length);
11723
- const strippedKey = suffix ? "/" + suffix : "/";
11724
- return [backend, strippedKey];
11725
- }
11726
- }
11727
- return [this.default, key];
11728
- }
11729
- /**
11730
- * List files and directories in the specified directory (non-recursive).
11731
- *
11732
- * @param path - Absolute path to directory
11733
- * @returns List of FileInfo objects with route prefixes added, for files and directories
11734
- * directly in the directory. Directories have a trailing / in their path and is_dir=true.
11735
- */
11736
- async lsInfo(path5) {
11737
- for (const [routePrefix, backend] of this.sortedRoutes) {
11738
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11739
- const suffix = path5.substring(routePrefix.length);
11740
- const searchPath = suffix ? "/" + suffix : "/";
11741
- const infos = await backend.lsInfo(searchPath);
11742
- const prefixed = [];
11743
- for (const fi of infos) {
11744
- prefixed.push({
11745
- ...fi,
11746
- path: routePrefix.slice(0, -1) + fi.path
11747
- });
11748
- }
11749
- return prefixed;
11750
- }
11751
- }
11752
- if (path5 === "/") {
11753
- const results = [];
11754
- const defaultInfos = await this.default.lsInfo(path5);
11755
- results.push(...defaultInfos);
11756
- for (const [routePrefix] of this.sortedRoutes) {
11757
- results.push({
11758
- path: routePrefix,
11759
- is_dir: true,
11760
- size: 0,
11761
- modified_at: ""
11762
- });
11763
- }
11764
- results.sort((a, b) => a.path.localeCompare(b.path));
11765
- return results;
11766
- }
11767
- return await this.default.lsInfo(path5);
11768
- }
11769
- /**
11770
- * Read file content, routing to appropriate backend.
11771
- *
11772
- * @param filePath - Absolute file path
11773
- * @param offset - Line offset to start reading from (0-indexed)
11774
- * @param limit - Maximum number of lines to read
11775
- * @returns Formatted file content with line numbers, or error message
11776
- */
11777
- async read(filePath, offset = 0, limit = 2e3) {
11778
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11779
- return await backend.read(strippedKey, offset, limit);
11780
- }
11781
- /**
11782
- * Read file content as raw FileData.
11783
- *
11784
- * @param filePath - Absolute file path
11785
- * @returns Raw file content as FileData
11786
- */
11787
- async readRaw(filePath) {
11788
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11789
- return await backend.readRaw(strippedKey);
11790
- }
11791
- /**
11792
- * Structured search results or error string for invalid input.
11793
- */
11794
- async grepRaw(pattern, path5 = "/", glob = null) {
11795
- for (const [routePrefix, backend] of this.sortedRoutes) {
11796
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11797
- const searchPath = path5.substring(routePrefix.length - 1);
11798
- const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
11799
- if (typeof raw === "string") {
11800
- return raw;
11801
- }
11802
- return raw.map((m) => ({
11803
- ...m,
11804
- path: routePrefix.slice(0, -1) + m.path
11805
- }));
11806
- }
11807
- }
11808
- const allMatches = [];
11809
- const rawDefault = await this.default.grepRaw(pattern, path5, glob);
11810
- if (typeof rawDefault === "string") {
11811
- return rawDefault;
11812
- }
11813
- allMatches.push(...rawDefault);
11814
- for (const [routePrefix, backend] of Object.entries(this.routes)) {
11815
- const raw = await backend.grepRaw(pattern, "/", glob);
11816
- if (typeof raw === "string") {
11817
- return raw;
11818
- }
11819
- allMatches.push(
11820
- ...raw.map((m) => ({
11821
- ...m,
11822
- path: routePrefix.slice(0, -1) + m.path
11823
- }))
11824
- );
11825
- }
11826
- return allMatches;
11827
- }
11828
- /**
11829
- * Structured glob matching returning FileInfo objects.
11830
- */
11831
- async globInfo(pattern, path5 = "/") {
11832
- const results = [];
11833
- for (const [routePrefix, backend] of this.sortedRoutes) {
11834
- if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
11835
- const searchPath = path5.substring(routePrefix.length - 1);
11836
- const infos = await backend.globInfo(pattern, searchPath || "/");
11837
- return infos.map((fi) => ({
11838
- ...fi,
11839
- path: routePrefix.slice(0, -1) + fi.path
11840
- }));
11841
- }
11842
- }
11843
- const defaultInfos = await this.default.globInfo(pattern, path5);
11844
- results.push(...defaultInfos);
11845
- for (const [routePrefix, backend] of Object.entries(this.routes)) {
11846
- const infos = await backend.globInfo(pattern, "/");
11847
- results.push(
11848
- ...infos.map((fi) => ({
11849
- ...fi,
11850
- path: routePrefix.slice(0, -1) + fi.path
11851
- }))
11852
- );
11853
- }
11854
- results.sort((a, b) => a.path.localeCompare(b.path));
11855
- return results;
11856
- }
11857
- /**
11858
- * Create a new file, routing to appropriate backend.
11859
- *
11860
- * @param filePath - Absolute file path
11861
- * @param content - File content as string
11862
- * @returns WriteResult with path or error
11863
- */
11864
- async write(filePath, content) {
11865
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11866
- return await backend.write(strippedKey, content);
11867
- }
11868
- /**
11869
- * Edit a file, routing to appropriate backend.
11870
- *
11871
- * @param filePath - Absolute file path
11872
- * @param oldString - String to find and replace
11873
- * @param newString - Replacement string
11874
- * @param replaceAll - If true, replace all occurrences
11875
- * @returns EditResult with path, occurrences, or error
11876
- */
11877
- async edit(filePath, oldString, newString, replaceAll = false) {
11878
- const [backend, strippedKey] = this.getBackendAndKey(filePath);
11879
- return await backend.edit(strippedKey, oldString, newString, replaceAll);
11880
- }
11881
- };
11882
-
11883
12126
  // src/deep_agent_new/backends/memory.ts
11884
12127
  var MemoryBackend = class {
11885
12128
  constructor(files) {
@@ -11995,8 +12238,8 @@ var MemoryBackend = class {
11995
12238
 
11996
12239
  // src/deep_agent_new/middleware/todos.ts
11997
12240
  var import_langgraph9 = require("@langchain/langgraph");
11998
- var import_zod49 = require("zod");
11999
- var import_langchain56 = require("langchain");
12241
+ var import_zod50 = require("zod");
12242
+ var import_langchain58 = require("langchain");
12000
12243
  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.
12001
12244
  It also helps the user understand the progress of the task and overall progress of their requests.
12002
12245
  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.
@@ -12223,20 +12466,20 @@ Writing todos takes time and tokens, use it when it is helpful for managing comp
12223
12466
  ## Important To-Do List Usage Notes to Remember
12224
12467
  - The \`write_todos\` tool should never be called multiple times in parallel.
12225
12468
  - 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.`;
12226
- var TodoStatus = import_zod49.z.enum(["pending", "in_progress", "completed"]).describe("Status of the todo");
12227
- var TodoSchema = import_zod49.z.object({
12228
- content: import_zod49.z.string().describe("Content of the todo item"),
12469
+ var TodoStatus = import_zod50.z.enum(["pending", "in_progress", "completed"]).describe("Status of the todo");
12470
+ var TodoSchema = import_zod50.z.object({
12471
+ content: import_zod50.z.string().describe("Content of the todo item"),
12229
12472
  status: TodoStatus
12230
12473
  });
12231
- var stateSchema = import_zod49.z.object({ todos: import_zod49.z.array(TodoSchema).default([]) });
12474
+ var stateSchema = import_zod50.z.object({ todos: import_zod50.z.array(TodoSchema).default([]) });
12232
12475
  function todoListMiddleware(options) {
12233
- const writeTodos = (0, import_langchain56.tool)(
12476
+ const writeTodos = (0, import_langchain58.tool)(
12234
12477
  ({ todos }, config) => {
12235
12478
  return new import_langgraph9.Command({
12236
12479
  update: {
12237
12480
  todos,
12238
12481
  messages: [
12239
- new import_langchain56.ToolMessage({
12482
+ new import_langchain58.ToolMessage({
12240
12483
  content: genUIMarkdown("todo_list", todos),
12241
12484
  tool_call_id: config.toolCall?.id
12242
12485
  })
@@ -12247,12 +12490,12 @@ function todoListMiddleware(options) {
12247
12490
  {
12248
12491
  name: "write_todos",
12249
12492
  description: options?.toolDescription ?? WRITE_TODOS_DESCRIPTION,
12250
- schema: import_zod49.z.object({
12251
- todos: import_zod49.z.array(TodoSchema).describe("List of todo items to update")
12493
+ schema: import_zod50.z.object({
12494
+ todos: import_zod50.z.array(TodoSchema).describe("List of todo items to update")
12252
12495
  })
12253
12496
  }
12254
12497
  );
12255
- return (0, import_langchain56.createMiddleware)({
12498
+ return (0, import_langchain58.createMiddleware)({
12256
12499
  name: "todoListMiddleware",
12257
12500
  stateSchema,
12258
12501
  tools: [writeTodos],
@@ -12304,13 +12547,13 @@ ${BASE_PROMPT}` : BASE_PROMPT;
12304
12547
  backend: filesystemBackend
12305
12548
  }),
12306
12549
  // Subagent middleware: Automatic conversation summarization when token limits are approached
12307
- (0, import_langchain57.summarizationMiddleware)({
12550
+ (0, import_langchain59.summarizationMiddleware)({
12308
12551
  model,
12309
12552
  trigger: { tokens: 17e4 },
12310
12553
  keep: { messages: 6 }
12311
12554
  }),
12312
12555
  // Subagent middleware: Anthropic prompt caching for improved performance
12313
- (0, import_langchain57.anthropicPromptCachingMiddleware)({
12556
+ (0, import_langchain59.anthropicPromptCachingMiddleware)({
12314
12557
  unsupportedModelBehavior: "ignore"
12315
12558
  }),
12316
12559
  // Subagent middleware: Patches tool calls for compatibility
@@ -12322,23 +12565,23 @@ ${BASE_PROMPT}` : BASE_PROMPT;
12322
12565
  generalPurposeAgent: true
12323
12566
  }),
12324
12567
  // Automatically summarizes conversation history when token limits are approached
12325
- (0, import_langchain57.summarizationMiddleware)({
12568
+ (0, import_langchain59.summarizationMiddleware)({
12326
12569
  model,
12327
12570
  trigger: { tokens: 17e4 },
12328
12571
  keep: { messages: 6 }
12329
12572
  }),
12330
12573
  // Enables Anthropic prompt caching for improved performance and reduced costs
12331
- (0, import_langchain57.anthropicPromptCachingMiddleware)({
12574
+ (0, import_langchain59.anthropicPromptCachingMiddleware)({
12332
12575
  unsupportedModelBehavior: "ignore"
12333
12576
  }),
12334
12577
  // Patches tool calls to ensure compatibility across different model providers
12335
12578
  createPatchToolCallsMiddleware()
12336
12579
  ];
12337
12580
  if (interruptOn) {
12338
- middleware.push((0, import_langchain57.humanInTheLoopMiddleware)({ interruptOn }));
12581
+ middleware.push((0, import_langchain59.humanInTheLoopMiddleware)({ interruptOn }));
12339
12582
  }
12340
12583
  middleware.push(...customMiddleware);
12341
- return (0, import_langchain57.createAgent)({
12584
+ return (0, import_langchain59.createAgent)({
12342
12585
  model,
12343
12586
  systemPrompt: finalSystemPrompt,
12344
12587
  tools,
@@ -12351,50 +12594,8 @@ ${BASE_PROMPT}` : BASE_PROMPT;
12351
12594
  });
12352
12595
  }
12353
12596
 
12354
- // src/agent_lattice/builders/filesystemBackend.ts
12355
- function createFilesystemBackendFactory(middlewareConfigs) {
12356
- const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
12357
- if (!filesystemConfig || !filesystemConfig.enabled) {
12358
- return void 0;
12359
- }
12360
- const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
12361
- return async (stateAndStore) => {
12362
- const { tenantId, workspaceId, projectId } = stateAndStore;
12363
- let sandboxName = "global";
12364
- if (isolatedLevel === "agent") {
12365
- sandboxName = "agent";
12366
- } else if (isolatedLevel === "thread") {
12367
- sandboxName = "thread";
12368
- }
12369
- const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
12370
- if (!sandboxManager) {
12371
- throw new Error("Sandbox manager not found");
12372
- }
12373
- let workingDirectory = "/";
12374
- if (workspaceId && projectId) {
12375
- if (tenantId) {
12376
- workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
12377
- } else {
12378
- workingDirectory = `/workspaces/${workspaceId}/${projectId}`;
12379
- }
12380
- }
12381
- const sandboxfs = new SandboxFilesystem({
12382
- sandboxInstance: await sandboxManager.createSandbox(sandboxName),
12383
- workingDirectory
12384
- });
12385
- const compositeBackend = new CompositeBackend(sandboxfs, {});
12386
- return compositeBackend;
12387
- };
12388
- }
12389
-
12390
12597
  // src/agent_lattice/builders/DeepAgentGraphBuilder.ts
12391
12598
  var DeepAgentGraphBuilder = class {
12392
- /**
12393
- * 根据 middleware 配置创建 middlewares
12394
- */
12395
- async createMiddlewares(middlewareConfigs) {
12396
- return await createCommonMiddlewares(middlewareConfigs);
12397
- }
12398
12599
  /**
12399
12600
  * 构建Deep Agent Graph
12400
12601
  *
@@ -12406,7 +12607,7 @@ var DeepAgentGraphBuilder = class {
12406
12607
  const tools = params.tools.map((t) => {
12407
12608
  const toolClient = getToolClient(t.key);
12408
12609
  return toolClient;
12409
- }).filter((tool50) => tool50 !== void 0);
12610
+ }).filter((tool51) => tool51 !== void 0);
12410
12611
  const subagents = await Promise.all(params.subAgents.map(async (sa) => {
12411
12612
  if (sa.client) {
12412
12613
  return {
@@ -12429,7 +12630,7 @@ var DeepAgentGraphBuilder = class {
12429
12630
  }));
12430
12631
  const middlewareConfigs = params.middleware || [];
12431
12632
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
12432
- const middlewares = await this.createMiddlewares(middlewareConfigs);
12633
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true);
12433
12634
  const deepAgent = createDeepAgent({
12434
12635
  tools,
12435
12636
  model: params.model,
@@ -12447,7 +12648,7 @@ var DeepAgentGraphBuilder = class {
12447
12648
 
12448
12649
  // src/agent_team/agent_team.ts
12449
12650
  var import_v35 = require("zod/v3");
12450
- var import_langchain60 = require("langchain");
12651
+ var import_langchain62 = require("langchain");
12451
12652
 
12452
12653
  // src/agent_team/types.ts
12453
12654
  var TaskStatus = /* @__PURE__ */ ((TaskStatus3) => {
@@ -12883,13 +13084,13 @@ var InMemoryMailboxStore = class {
12883
13084
 
12884
13085
  // src/agent_team/middleware/team.ts
12885
13086
  var import_v34 = require("zod/v3");
12886
- var import_langchain59 = require("langchain");
13087
+ var import_langchain61 = require("langchain");
12887
13088
  var import_langgraph11 = require("@langchain/langgraph");
12888
13089
  var import_uuid = require("uuid");
12889
13090
 
12890
13091
  // src/agent_team/middleware/teammate_tools.ts
12891
13092
  var import_v33 = require("zod/v3");
12892
- var import_langchain58 = require("langchain");
13093
+ var import_langchain60 = require("langchain");
12893
13094
  var import_langgraph10 = require("@langchain/langgraph");
12894
13095
 
12895
13096
  // src/agent_team/middleware/formatMessages.ts
@@ -12914,7 +13115,7 @@ ${meta}${body}`;
12914
13115
  // src/agent_team/middleware/teammate_tools.ts
12915
13116
  function createTeammateTools(options) {
12916
13117
  const { teamId, agentId, taskListStore, mailboxStore } = options;
12917
- const claimTaskTool = (0, import_langchain58.tool)(
13118
+ const claimTaskTool = (0, import_langchain60.tool)(
12918
13119
  async (input) => {
12919
13120
  const task = await taskListStore.claimTaskById(
12920
13121
  teamId,
@@ -12944,7 +13145,7 @@ function createTeammateTools(options) {
12944
13145
  })
12945
13146
  }
12946
13147
  );
12947
- const completeTaskTool = (0, import_langchain58.tool)(
13148
+ const completeTaskTool = (0, import_langchain60.tool)(
12948
13149
  async (input) => {
12949
13150
  const task = await taskListStore.completeTask(
12950
13151
  teamId,
@@ -12971,7 +13172,7 @@ function createTeammateTools(options) {
12971
13172
  })
12972
13173
  }
12973
13174
  );
12974
- const failTaskTool = (0, import_langchain58.tool)(
13175
+ const failTaskTool = (0, import_langchain60.tool)(
12975
13176
  async (input) => {
12976
13177
  const task = await taskListStore.failTask(
12977
13178
  teamId,
@@ -12998,7 +13199,7 @@ function createTeammateTools(options) {
12998
13199
  })
12999
13200
  }
13000
13201
  );
13001
- const sendMessageTool = (0, import_langchain58.tool)(
13202
+ const sendMessageTool = (0, import_langchain60.tool)(
13002
13203
  async (input) => {
13003
13204
  await mailboxStore.sendMessage(
13004
13205
  teamId,
@@ -13036,7 +13237,7 @@ function createTeammateTools(options) {
13036
13237
  read: msg.read
13037
13238
  }));
13038
13239
  };
13039
- const readMessagesTool = (0, import_langchain58.tool)(
13240
+ const readMessagesTool = (0, import_langchain60.tool)(
13040
13241
  async (input, config) => {
13041
13242
  const formatAndMarkAsRead = async (msgs2) => {
13042
13243
  for (const msg of msgs2) {
@@ -13048,7 +13249,7 @@ function createTeammateTools(options) {
13048
13249
  if (msgs.length > 0) {
13049
13250
  const formatted2 = await formatAndMarkAsRead(msgs);
13050
13251
  const relevantMsgs2 = await getRelevantMessagesForState();
13051
- const toolMessage2 = new import_langchain58.ToolMessage({
13252
+ const toolMessage2 = new import_langchain60.ToolMessage({
13052
13253
  content: formatted2,
13053
13254
  tool_call_id: config.toolCall?.id,
13054
13255
  name: "read_messages"
@@ -13073,7 +13274,7 @@ function createTeammateTools(options) {
13073
13274
  });
13074
13275
  const relevantMsgs = await getRelevantMessagesForState();
13075
13276
  if (msgs.length === 0) {
13076
- const toolMessage2 = new import_langchain58.ToolMessage({
13277
+ const toolMessage2 = new import_langchain60.ToolMessage({
13077
13278
  content: "No unread messages.",
13078
13279
  tool_call_id: config.toolCall?.id,
13079
13280
  name: "read_messages"
@@ -13083,7 +13284,7 @@ function createTeammateTools(options) {
13083
13284
  });
13084
13285
  }
13085
13286
  const formatted = await formatAndMarkAsRead(msgs);
13086
- const toolMessage = new import_langchain58.ToolMessage({
13287
+ const toolMessage = new import_langchain60.ToolMessage({
13087
13288
  content: formatted,
13088
13289
  tool_call_id: config.toolCall?.id,
13089
13290
  name: "read_messages"
@@ -13098,7 +13299,7 @@ function createTeammateTools(options) {
13098
13299
  schema: import_v33.z.object({})
13099
13300
  }
13100
13301
  );
13101
- const checkTasksTool = (0, import_langchain58.tool)(
13302
+ const checkTasksTool = (0, import_langchain60.tool)(
13102
13303
  async () => {
13103
13304
  const tasks = await taskListStore.getAllTasks(teamId);
13104
13305
  return formatTaskSummary(tasks);
@@ -13109,7 +13310,7 @@ function createTeammateTools(options) {
13109
13310
  schema: import_v33.z.object({})
13110
13311
  }
13111
13312
  );
13112
- const broadcastMessageTool = (0, import_langchain58.tool)(
13313
+ const broadcastMessageTool = (0, import_langchain60.tool)(
13113
13314
  async (input) => {
13114
13315
  const allAgents = await mailboxStore.getRegisteredAgents(teamId);
13115
13316
  const recipients = allAgents.filter((a) => a !== agentId);
@@ -13294,7 +13495,7 @@ You have access to these tools:
13294
13495
  - \`read_messages\`: Read messages from team_lead or teammates
13295
13496
  - \`check_tasks\`: Get current status of all tasks in the team`;
13296
13497
  const assistantId = getTeammateAssistantId(ctx.teamId, spec.name);
13297
- agent = (0, import_langchain59.createAgent)({
13498
+ agent = (0, import_langchain61.createAgent)({
13298
13499
  model: spec.model ?? ctx.defaultModel,
13299
13500
  systemPrompt: teammatePrompt,
13300
13501
  tools: allTools,
@@ -13363,12 +13564,12 @@ async function spawnTeammate(options) {
13363
13564
  function createTeamMiddleware(options) {
13364
13565
  const { teamConfig, taskListStore, mailboxStore, tenantId } = options;
13365
13566
  const defaultModel = teamConfig.model ?? "claude-sonnet-4-5-20250929";
13366
- const createTeamTool = (0, import_langchain59.tool)(
13567
+ const createTeamTool = (0, import_langchain61.tool)(
13367
13568
  async (input, config) => {
13368
13569
  const state = (0, import_langgraph11.getCurrentTaskInput)();
13369
13570
  if (state?.team?.teamId) {
13370
13571
  const existingId = state.team.teamId;
13371
- const msg = new import_langchain59.ToolMessage({
13572
+ const msg = new import_langchain61.ToolMessage({
13372
13573
  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.`,
13373
13574
  tool_call_id: config.toolCall?.id,
13374
13575
  name: "create_team"
@@ -13457,7 +13658,7 @@ Teammates are now working in the background. Keep calling \`check_tasks\` and \`
13457
13658
  \`\`\`json
13458
13659
  ${teamJson}
13459
13660
  \`\`\``;
13460
- const toolMessage = new import_langchain59.ToolMessage({
13661
+ const toolMessage = new import_langchain61.ToolMessage({
13461
13662
  content: summary,
13462
13663
  tool_call_id: config.toolCall?.id,
13463
13664
  name: "create_team"
@@ -13542,7 +13743,7 @@ After calling create_team, you MUST:
13542
13743
  if (state?.team?.teamId) return state.team.teamId;
13543
13744
  throw new Error("No team_id provided and no team in state. Call create_team first.");
13544
13745
  };
13545
- const addTasksTool = (0, import_langchain59.tool)(
13746
+ const addTasksTool = (0, import_langchain61.tool)(
13546
13747
  async (input, config) => {
13547
13748
  const teamId = resolveTeamId();
13548
13749
  const created = await taskListStore.addTasks(
@@ -13556,7 +13757,7 @@ After calling create_team, you MUST:
13556
13757
  }))
13557
13758
  );
13558
13759
  const summary = created.map((t) => `- ${t.id}: "${t.title}"`).join("\n");
13559
- return new import_langchain59.ToolMessage({
13760
+ return new import_langchain61.ToolMessage({
13560
13761
  content: `Added ${created.length} task(s) to team ${teamId}:
13561
13762
  ${summary}
13562
13763
  Sleeping teammates will wake up and claim these.`,
@@ -13607,20 +13808,20 @@ IMPORTANT: Assigning to a specific teammate
13607
13808
  })
13608
13809
  }
13609
13810
  );
13610
- const assignTaskTool = (0, import_langchain59.tool)(
13811
+ const assignTaskTool = (0, import_langchain61.tool)(
13611
13812
  async (input, config) => {
13612
13813
  const teamId = resolveTeamId();
13613
13814
  const task = await taskListStore.updateTask(teamId, input.task_id, {
13614
13815
  assignee: input.assignee
13615
13816
  });
13616
13817
  if (!task) {
13617
- return new import_langchain59.ToolMessage({
13818
+ return new import_langchain61.ToolMessage({
13618
13819
  content: `Task ${input.task_id} not found in team ${teamId}.`,
13619
13820
  tool_call_id: config.toolCall?.id,
13620
13821
  name: "assign_task"
13621
13822
  });
13622
13823
  }
13623
- return new import_langchain59.ToolMessage({
13824
+ return new import_langchain61.ToolMessage({
13624
13825
  content: `Task "${task.title}" (${task.id}) assigned to ${input.assignee}.`,
13625
13826
  tool_call_id: config.toolCall?.id,
13626
13827
  name: "assign_task"
@@ -13635,20 +13836,20 @@ IMPORTANT: Assigning to a specific teammate
13635
13836
  })
13636
13837
  }
13637
13838
  );
13638
- const setTaskStatusTool = (0, import_langchain59.tool)(
13839
+ const setTaskStatusTool = (0, import_langchain61.tool)(
13639
13840
  async (input, config) => {
13640
13841
  const teamId = resolveTeamId();
13641
13842
  const task = await taskListStore.updateTask(teamId, input.task_id, {
13642
13843
  status: input.status
13643
13844
  });
13644
13845
  if (!task) {
13645
- return new import_langchain59.ToolMessage({
13846
+ return new import_langchain61.ToolMessage({
13646
13847
  content: `Task ${input.task_id} not found in team ${teamId}.`,
13647
13848
  tool_call_id: config.toolCall?.id,
13648
13849
  name: "set_task_status"
13649
13850
  });
13650
13851
  }
13651
- return new import_langchain59.ToolMessage({
13852
+ return new import_langchain61.ToolMessage({
13652
13853
  content: `Task "${task.title}" (${task.id}) status set to ${input.status}.`,
13653
13854
  tool_call_id: config.toolCall?.id,
13654
13855
  name: "set_task_status"
@@ -13663,20 +13864,20 @@ IMPORTANT: Assigning to a specific teammate
13663
13864
  })
13664
13865
  }
13665
13866
  );
13666
- const setTaskDependenciesTool = (0, import_langchain59.tool)(
13867
+ const setTaskDependenciesTool = (0, import_langchain61.tool)(
13667
13868
  async (input, config) => {
13668
13869
  const teamId = resolveTeamId();
13669
13870
  const task = await taskListStore.updateTask(teamId, input.task_id, {
13670
13871
  dependencies: input.dependencies
13671
13872
  });
13672
13873
  if (!task) {
13673
- return new import_langchain59.ToolMessage({
13874
+ return new import_langchain61.ToolMessage({
13674
13875
  content: `Task ${input.task_id} not found in team ${teamId}.`,
13675
13876
  tool_call_id: config.toolCall?.id,
13676
13877
  name: "set_task_dependencies"
13677
13878
  });
13678
13879
  }
13679
- return new import_langchain59.ToolMessage({
13880
+ return new import_langchain61.ToolMessage({
13680
13881
  content: `Task "${task.title}" (${task.id}) dependencies set to [${input.dependencies.join(", ")}].`,
13681
13882
  tool_call_id: config.toolCall?.id,
13682
13883
  name: "set_task_dependencies"
@@ -13691,7 +13892,7 @@ IMPORTANT: Assigning to a specific teammate
13691
13892
  })
13692
13893
  }
13693
13894
  );
13694
- const checkTasksTool = (0, import_langchain59.tool)(
13895
+ const checkTasksTool = (0, import_langchain61.tool)(
13695
13896
  async (input, config) => {
13696
13897
  const teamId = resolveTeamId();
13697
13898
  const tasks = await taskListStore.getAllTasks(teamId);
@@ -13700,7 +13901,7 @@ IMPORTANT: Assigning to a specific teammate
13700
13901
  update: {
13701
13902
  tasks: tasksSnapshot,
13702
13903
  messages: [
13703
- new import_langchain59.ToolMessage({
13904
+ new import_langchain61.ToolMessage({
13704
13905
  content: formatTaskSummary(tasks),
13705
13906
  tool_call_id: config.toolCall?.id,
13706
13907
  name: "check_tasks"
@@ -13736,7 +13937,7 @@ Task Status Values:
13736
13937
  })
13737
13938
  }
13738
13939
  );
13739
- const sendMessageTool = (0, import_langchain59.tool)(
13940
+ const sendMessageTool = (0, import_langchain61.tool)(
13740
13941
  async (input, config) => {
13741
13942
  const teamId = resolveTeamId();
13742
13943
  await mailboxStore.sendMessage(
@@ -13746,7 +13947,7 @@ Task Status Values:
13746
13947
  input.content,
13747
13948
  "direct_message" /* DIRECT_MESSAGE */
13748
13949
  );
13749
- return new import_langchain59.ToolMessage({
13950
+ return new import_langchain61.ToolMessage({
13750
13951
  content: `Message sent to ${input.to}.`,
13751
13952
  tool_call_id: config.toolCall?.id,
13752
13953
  name: "send_message"
@@ -13761,7 +13962,7 @@ Task Status Values:
13761
13962
  })
13762
13963
  }
13763
13964
  );
13764
- const readMessagesTool = (0, import_langchain59.tool)(
13965
+ const readMessagesTool = (0, import_langchain61.tool)(
13765
13966
  async (input, config) => {
13766
13967
  const teamId = resolveTeamId();
13767
13968
  const formatAndMarkAsRead = async (msgs2) => {
@@ -13789,7 +13990,7 @@ Task Status Values:
13789
13990
  if (msgs.length > 0) {
13790
13991
  const formatted2 = await formatAndMarkAsRead(msgs);
13791
13992
  const allTeamMessages2 = await getAllTeamMessagesForState();
13792
- const toolMessage2 = new import_langchain59.ToolMessage({
13993
+ const toolMessage2 = new import_langchain61.ToolMessage({
13793
13994
  content: formatted2,
13794
13995
  tool_call_id: config.toolCall?.id,
13795
13996
  name: "read_messages"
@@ -13821,7 +14022,7 @@ Task Status Values:
13821
14022
  );
13822
14023
  const allTeamMessages = await getAllTeamMessagesForState();
13823
14024
  if (msgs.length === 0) {
13824
- const toolMessage2 = new import_langchain59.ToolMessage({
14025
+ const toolMessage2 = new import_langchain61.ToolMessage({
13825
14026
  content: "No unread messages from teammates.",
13826
14027
  tool_call_id: config.toolCall?.id,
13827
14028
  name: "read_messages"
@@ -13831,7 +14032,7 @@ Task Status Values:
13831
14032
  });
13832
14033
  }
13833
14034
  const formatted = await formatAndMarkAsRead(msgs);
13834
- const toolMessage = new import_langchain59.ToolMessage({
14035
+ const toolMessage = new import_langchain61.ToolMessage({
13835
14036
  content: formatted,
13836
14037
  tool_call_id: config.toolCall?.id,
13837
14038
  name: "read_messages"
@@ -13848,7 +14049,7 @@ Task Status Values:
13848
14049
  })
13849
14050
  }
13850
14051
  );
13851
- const disbandTeamTool = (0, import_langchain59.tool)(
14052
+ const disbandTeamTool = (0, import_langchain61.tool)(
13852
14053
  async (input, config) => {
13853
14054
  const teamId = resolveTeamId();
13854
14055
  await mailboxStore.broadcastMessage(
@@ -13858,7 +14059,7 @@ Task Status Values:
13858
14059
  "shutdown_request" /* SHUTDOWN_REQUEST */
13859
14060
  );
13860
14061
  await new Promise((r) => setTimeout(r, 2e3));
13861
- return new import_langchain59.ToolMessage({
14062
+ return new import_langchain61.ToolMessage({
13862
14063
  content: `Team ${teamId} has been disbanded. All teammates notified and resources cleaned up.`,
13863
14064
  tool_call_id: config.toolCall?.id,
13864
14065
  name: "disband_team"
@@ -13869,7 +14070,7 @@ Task Status Values:
13869
14070
  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."
13870
14071
  }
13871
14072
  );
13872
- const broadcastMessageTool = (0, import_langchain59.tool)(
14073
+ const broadcastMessageTool = (0, import_langchain61.tool)(
13873
14074
  async (input, config) => {
13874
14075
  const teamId = resolveTeamId();
13875
14076
  await mailboxStore.broadcastMessage(
@@ -13878,7 +14079,7 @@ Task Status Values:
13878
14079
  input.content,
13879
14080
  "broadcast" /* BROADCAST */
13880
14081
  );
13881
- return new import_langchain59.ToolMessage({
14082
+ return new import_langchain61.ToolMessage({
13882
14083
  content: `Broadcast message sent to all teammates.`,
13883
14084
  tool_call_id: config.toolCall?.id,
13884
14085
  name: "broadcast_message"
@@ -13892,7 +14093,7 @@ Task Status Values:
13892
14093
  })
13893
14094
  }
13894
14095
  );
13895
- return (0, import_langchain59.createMiddleware)({
14096
+ return (0, import_langchain61.createMiddleware)({
13896
14097
  name: "teamMiddleware",
13897
14098
  tools: [
13898
14099
  createTeamTool,
@@ -14001,7 +14202,7 @@ function createAgentTeam(config) {
14001
14202
  ];
14002
14203
  const systemPrompt = config.systemPrompt + "\n\n" + TEAM_LEAD_BASE_PROMPT;
14003
14204
  const stateSchema2 = createReactAgentSchema(TEAM_STATE_SCHEMA);
14004
- return (0, import_langchain60.createAgent)({
14205
+ return (0, import_langchain62.createAgent)({
14005
14206
  model: config.model ?? "claude-sonnet-4-5-20250929",
14006
14207
  systemPrompt,
14007
14208
  tools: [],
@@ -14031,7 +14232,7 @@ var TeamAgentGraphBuilder = class {
14031
14232
  const tools = params.tools.map((t) => {
14032
14233
  const toolClient = getToolClient(t.key);
14033
14234
  return toolClient;
14034
- }).filter((tool50) => tool50 !== void 0);
14235
+ }).filter((tool51) => tool51 !== void 0);
14035
14236
  const teammates = params.subAgents.map((sa) => {
14036
14237
  const baseConfig = sa.config;
14037
14238
  return {
@@ -14756,6 +14957,9 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
14756
14957
  buffer2.expiresAt = Date.now() + this.config.ttl;
14757
14958
  buffer2.status = "active" /* ACTIVE */;
14758
14959
  }
14960
+ async ensureThread(threadId) {
14961
+ this.getOrCreateBuffer(threadId);
14962
+ }
14759
14963
  async completeThread(threadId) {
14760
14964
  const buffer2 = this.getBufferIfValid(threadId);
14761
14965
  if (buffer2) {
@@ -16900,10 +17104,10 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
16900
17104
  }
16901
17105
  const tools = await this.getAllTools();
16902
17106
  console.log(`[MCP] Registering ${tools.length} tools to Tool Lattice...`);
16903
- for (const tool50 of tools) {
16904
- const toolKey = prefix ? `${prefix}_${tool50.name}` : tool50.name;
16905
- tool50.name = toolKey;
16906
- toolLatticeManager.registerExistingTool(toolKey, tool50);
17107
+ for (const tool51 of tools) {
17108
+ const toolKey = prefix ? `${prefix}_${tool51.name}` : tool51.name;
17109
+ tool51.name = toolKey;
17110
+ toolLatticeManager.registerExistingTool(toolKey, tool51);
16907
17111
  console.log(`[MCP] Registered tool: ${toolKey}`);
16908
17112
  }
16909
17113
  console.log(`[MCP] Successfully registered ${tools.length} tools to Tool Lattice`);
@@ -16921,7 +17125,7 @@ var QueueMode = /* @__PURE__ */ ((QueueMode2) => {
16921
17125
 
16922
17126
  // src/services/Agent.ts
16923
17127
  var import_langgraph12 = require("@langchain/langgraph");
16924
- var import_langchain61 = require("langchain");
17128
+ var import_langchain63 = require("langchain");
16925
17129
  var import_uuid2 = require("uuid");
16926
17130
  var ThreadStatus2 = /* @__PURE__ */ ((ThreadStatus3) => {
16927
17131
  ThreadStatus3["IDLE"] = "idle";
@@ -17127,7 +17331,7 @@ var Agent = class {
17127
17331
  });
17128
17332
  const humanContent = p.content;
17129
17333
  const input = {
17130
- messages: [new import_langchain61.HumanMessage({ id: humanContent.id, content: humanContent.message })]
17334
+ messages: [new import_langchain63.HumanMessage({ id: humanContent.id, content: humanContent.message })]
17131
17335
  };
17132
17336
  if (files) {
17133
17337
  input.files = files;
@@ -17193,7 +17397,7 @@ var Agent = class {
17193
17397
  remainingPendings.forEach((p) => {
17194
17398
  this.queueStore?.markProcessing(p.id);
17195
17399
  const humanContent = p.content;
17196
- userMessages.push(new import_langchain61.HumanMessage({ id: humanContent.id, content: humanContent.message }));
17400
+ userMessages.push(new import_langchain63.HumanMessage({ id: humanContent.id, content: humanContent.message }));
17197
17401
  this.publish("message:started", {
17198
17402
  type: "message:started",
17199
17403
  messageId: humanContent.id,
@@ -17267,7 +17471,7 @@ var Agent = class {
17267
17471
  if (signal?.aborted) break;
17268
17472
  await this.queueStore?.markProcessing(p.id);
17269
17473
  const humanContent = p.content;
17270
- const message = new import_langchain61.HumanMessage({ id: humanContent.id, content: humanContent.message });
17474
+ const message = new import_langchain63.HumanMessage({ id: humanContent.id, content: humanContent.message });
17271
17475
  const startTime = Date.now();
17272
17476
  this.publish("message:started", {
17273
17477
  type: "message:started",
@@ -17410,7 +17614,7 @@ var Agent = class {
17410
17614
  const messageId = (0, import_uuid2.v4)();
17411
17615
  const input = {
17412
17616
  ...queueMessage.input,
17413
- messages: [new import_langchain61.HumanMessage({ id: messageId, content: queueMessage.input.message })]
17617
+ messages: [new import_langchain63.HumanMessage({ id: messageId, content: queueMessage.input.message })]
17414
17618
  };
17415
17619
  const inputMessage = { ...queueMessage, input };
17416
17620
  return this.agentExecutor(inputMessage, signal);
@@ -17510,6 +17714,7 @@ var Agent = class {
17510
17714
  id: messageId
17511
17715
  });
17512
17716
  }
17717
+ await this.chunkBuffer.ensureThread(this.thread_id);
17513
17718
  this.startQueueProcessorIfNeeded().catch((err) => {
17514
17719
  console.error("Failed to start queue processor:", err);
17515
17720
  });
@@ -17584,7 +17789,7 @@ var Agent = class {
17584
17789
  async getCurrentMessages() {
17585
17790
  const state = await this.getCurrentState();
17586
17791
  const messages = state.values.messages || [];
17587
- const filteredMessages = (0, import_langchain61.filterMessages)(messages, {
17792
+ const filteredMessages = (0, import_langchain63.filterMessages)(messages, {
17588
17793
  includeTypes: ["ai", "human", "tool"]
17589
17794
  //["human", "ai", "tool"],
17590
17795
  });
@@ -17643,12 +17848,16 @@ var Agent = class {
17643
17848
  /**
17644
17849
  * Abort the current agent execution
17645
17850
  * This will cancel any ongoing invoke or stream operations
17851
+ * and clear all queued messages (pending + processing)
17646
17852
  */
17647
- abort() {
17853
+ async abort() {
17648
17854
  if (this.abortController) {
17649
17855
  this.abortController.abort();
17650
17856
  this.abortController = null;
17651
17857
  }
17858
+ await this.chunkBuffer.abortThread(this.thread_id);
17859
+ const store = this.getQueueStore();
17860
+ await store.clearMessages(this.thread_id);
17652
17861
  }
17653
17862
  /**
17654
17863
  * Check if the agent is currently being aborted
@@ -17957,6 +18166,7 @@ function clearEncryptionKeyCache() {
17957
18166
  createQueryTablesListTool,
17958
18167
  createTeamMiddleware,
17959
18168
  createTeammateTools,
18169
+ createUnknownToolHandlerMiddleware,
17960
18170
  createWidgetMiddleware,
17961
18171
  decrypt,
17962
18172
  describeCronExpression,