@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.d.mts +58 -2
- package/dist/index.d.ts +58 -2
- package/dist/index.js +1089 -879
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1267 -1058
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
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: () =>
|
|
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,
|
|
849
|
+
registerExistingTool(key, tool51) {
|
|
849
850
|
const config = {
|
|
850
|
-
name:
|
|
851
|
-
description:
|
|
852
|
-
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:
|
|
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,
|
|
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
|
|
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
|
|
4834
|
+
var import_langchain55 = require("langchain");
|
|
4834
4835
|
|
|
4835
|
-
// src/
|
|
4836
|
-
var
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
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
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
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
|
-
*
|
|
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
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
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
|
-
*
|
|
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
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
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
|
-
*
|
|
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
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
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
|
-
*
|
|
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
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
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
|
-
*
|
|
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
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
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
|
-
*
|
|
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
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
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
|
|
5046
|
-
|
|
5047
|
-
|
|
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
|
|
5041
|
+
return false;
|
|
5066
5042
|
}
|
|
5067
5043
|
/**
|
|
5068
|
-
*
|
|
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
|
-
|
|
5075
|
-
if (
|
|
5076
|
-
|
|
5077
|
-
}
|
|
5078
|
-
|
|
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
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
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
|
|
5063
|
+
return allThreads;
|
|
5107
5064
|
}
|
|
5108
5065
|
};
|
|
5109
5066
|
|
|
5110
|
-
// src/
|
|
5111
|
-
var
|
|
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
|
|
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 (
|
|
5335
|
+
if (path2.isAbsolute(providedPath)) {
|
|
5610
5336
|
this.rootDir = providedPath;
|
|
5611
5337
|
} else {
|
|
5612
|
-
this.rootDir =
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
5937
|
-
const relativePath =
|
|
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 =
|
|
5959
|
-
const fullPath =
|
|
5960
|
-
const resolvedPath =
|
|
5961
|
-
const resolvedResourcesDir =
|
|
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.
|
|
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
|
|
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
|
|
9510
|
-
2. Read
|
|
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
|
|
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
|
-
- **
|
|
9521
|
-
- **
|
|
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
|
|
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
|
-
-
|
|
9716
|
-
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
9962
|
-
|
|
9963
|
-
|
|
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
|
|
9958
|
+
const clawMiddlewareConfig = config.config;
|
|
10012
9959
|
middlewares.push(createClawMiddleware({
|
|
10013
9960
|
backend: filesystemBackend,
|
|
10014
|
-
injectBootstrapFiles:
|
|
10015
|
-
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
|
-
|
|
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
|
|
10073
|
-
return
|
|
10074
|
-
}).filter((
|
|
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 =
|
|
10500
|
+
const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
|
|
10078
10501
|
const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend);
|
|
10079
|
-
return (0,
|
|
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
|
|
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
|
|
10519
|
+
var import_langchain56 = require("langchain");
|
|
10097
10520
|
var import_langgraph7 = require("@langchain/langgraph");
|
|
10098
|
-
var
|
|
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
|
|
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,
|
|
11106
|
+
(0, import_langchain56.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
|
|
10684
11107
|
);
|
|
10685
11108
|
}
|
|
10686
|
-
const generalPurposeSubagent = (0,
|
|
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,
|
|
10710
|
-
agents[agentParams.key] = (0,
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
10859
|
-
var
|
|
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,
|
|
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 (
|
|
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) =>
|
|
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
|
|
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
|
|
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
|
|
11999
|
-
var
|
|
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 =
|
|
12227
|
-
var TodoSchema =
|
|
12228
|
-
content:
|
|
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 =
|
|
12474
|
+
var stateSchema = import_zod50.z.object({ todos: import_zod50.z.array(TodoSchema).default([]) });
|
|
12232
12475
|
function todoListMiddleware(options) {
|
|
12233
|
-
const writeTodos = (0,
|
|
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
|
|
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:
|
|
12251
|
-
todos:
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
12581
|
+
middleware.push((0, import_langchain59.humanInTheLoopMiddleware)({ interruptOn }));
|
|
12339
12582
|
}
|
|
12340
12583
|
middleware.push(...customMiddleware);
|
|
12341
|
-
return (0,
|
|
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((
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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((
|
|
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
|
|
16904
|
-
const toolKey = prefix ? `${prefix}_${
|
|
16905
|
-
|
|
16906
|
-
toolLatticeManager.registerExistingTool(toolKey,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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,
|