@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.mjs
CHANGED
|
@@ -648,11 +648,11 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
648
648
|
* @param key Lattice键名
|
|
649
649
|
* @param tool 已有的StructuredTool实例
|
|
650
650
|
*/
|
|
651
|
-
registerExistingTool(key,
|
|
651
|
+
registerExistingTool(key, tool51) {
|
|
652
652
|
const config = {
|
|
653
|
-
name:
|
|
654
|
-
description:
|
|
655
|
-
schema:
|
|
653
|
+
name: tool51.name,
|
|
654
|
+
description: tool51.description,
|
|
655
|
+
schema: tool51.schema,
|
|
656
656
|
// StructuredTool的schema已经是Zod兼容的
|
|
657
657
|
needUserApprove: false
|
|
658
658
|
// MCP工具默认不需要用户批准
|
|
@@ -660,7 +660,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
660
660
|
const toolLattice = {
|
|
661
661
|
key,
|
|
662
662
|
config,
|
|
663
|
-
client:
|
|
663
|
+
client: tool51
|
|
664
664
|
};
|
|
665
665
|
this.register(key, toolLattice);
|
|
666
666
|
}
|
|
@@ -686,7 +686,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
686
686
|
};
|
|
687
687
|
var toolLatticeManager = ToolLatticeManager.getInstance();
|
|
688
688
|
var registerToolLattice = (key, config, executor) => toolLatticeManager.registerLattice(key, config, executor);
|
|
689
|
-
var registerExistingTool = (key,
|
|
689
|
+
var registerExistingTool = (key, tool51) => toolLatticeManager.registerExistingTool(key, tool51);
|
|
690
690
|
var getToolLattice = (key) => toolLatticeManager.getToolLattice(key);
|
|
691
691
|
var getToolDefinition = (key) => toolLatticeManager.getToolDefinition(key);
|
|
692
692
|
var getToolClient = (key) => toolLatticeManager.getToolClient(key);
|
|
@@ -4649,516 +4649,241 @@ var createReactAgentSchema = (schema) => {
|
|
|
4649
4649
|
// src/agent_lattice/builders/ReActAgentGraphBuilder.ts
|
|
4650
4650
|
import { createAgent } from "langchain";
|
|
4651
4651
|
|
|
4652
|
-
// src/
|
|
4653
|
-
import {
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4652
|
+
// src/middlewares/codeEvalMiddleware.ts
|
|
4653
|
+
import { createMiddleware } from "langchain";
|
|
4654
|
+
|
|
4655
|
+
// src/middlewares/contextSchema.ts
|
|
4656
|
+
import z40 from "zod";
|
|
4657
|
+
var contextSchema = z40.object({
|
|
4658
|
+
runConfig: z40.any()
|
|
4659
|
+
});
|
|
4660
|
+
|
|
4661
|
+
// src/middlewares/codeEvalMiddleware.ts
|
|
4662
|
+
function createCodeEvalMiddleware(params = { isolatedLevel: "global" }) {
|
|
4663
|
+
const codeEvalTool = createCodeEvalTool({ isolatedLevel: params.isolatedLevel });
|
|
4664
|
+
const codeExecuteFileTool = createCodeExecuteFileTool({ isolatedLevel: params.isolatedLevel });
|
|
4665
|
+
return createMiddleware({
|
|
4666
|
+
name: "codeEvalMiddleware",
|
|
4667
|
+
contextSchema,
|
|
4668
|
+
tools: [codeEvalTool, codeExecuteFileTool, getToolClient("convert_to_markdown")]
|
|
4669
|
+
});
|
|
4670
|
+
}
|
|
4671
|
+
|
|
4672
|
+
// src/middlewares/browserMiddleware.ts
|
|
4673
|
+
import { createMiddleware as createMiddleware2 } from "langchain";
|
|
4674
|
+
function createBrowserMiddleware(params = { isolatedLevel: "global" }) {
|
|
4675
|
+
const isolatedLevel = params.isolatedLevel || "global";
|
|
4676
|
+
const tools = [
|
|
4677
|
+
createBrowserNavigateTool({ isolatedLevel }),
|
|
4678
|
+
createBrowserClickTool({ isolatedLevel }),
|
|
4679
|
+
createBrowserGetTextTool({ isolatedLevel }),
|
|
4680
|
+
createBrowserGetMarkdownTool({ isolatedLevel }),
|
|
4681
|
+
createBrowserEvaluateTool({ isolatedLevel }),
|
|
4682
|
+
createBrowserScreenshotTool({ isolatedLevel }),
|
|
4683
|
+
createBrowserScrollTool({ isolatedLevel }),
|
|
4684
|
+
createBrowserFormInputFillTool({ isolatedLevel }),
|
|
4685
|
+
createBrowserSelectTool({ isolatedLevel }),
|
|
4686
|
+
createBrowserHoverTool({ isolatedLevel }),
|
|
4687
|
+
createBrowserGoBackTool({ isolatedLevel }),
|
|
4688
|
+
createBrowserGoForwardTool({ isolatedLevel }),
|
|
4689
|
+
createBrowserNewTabTool({ isolatedLevel }),
|
|
4690
|
+
createBrowserTabListTool({ isolatedLevel }),
|
|
4691
|
+
createBrowserSwitchTabTool({ isolatedLevel }),
|
|
4692
|
+
createBrowserCloseTabTool({ isolatedLevel }),
|
|
4693
|
+
createBrowserCloseTool({ isolatedLevel }),
|
|
4694
|
+
createBrowserPressKeyTool({ isolatedLevel }),
|
|
4695
|
+
createBrowserReadLinksTool({ isolatedLevel }),
|
|
4696
|
+
createBrowserGetClickableElementsTool({ isolatedLevel }),
|
|
4697
|
+
createBrowserGetDownloadListTool({ isolatedLevel }),
|
|
4698
|
+
createBrowserGetInfoTool({ isolatedLevel })
|
|
4699
|
+
];
|
|
4700
|
+
return createMiddleware2({
|
|
4701
|
+
name: "browserMiddleware",
|
|
4702
|
+
contextSchema,
|
|
4703
|
+
tools
|
|
4704
|
+
});
|
|
4705
|
+
}
|
|
4706
|
+
|
|
4707
|
+
// src/middlewares/sqlMiddleware.ts
|
|
4708
|
+
import { createMiddleware as createMiddleware3 } from "langchain";
|
|
4709
|
+
function createSqlMiddleware(params) {
|
|
4710
|
+
const { databaseKeys, databaseDescriptions } = params;
|
|
4711
|
+
if (!databaseKeys || databaseKeys.length === 0) {
|
|
4712
|
+
return createMiddleware3({
|
|
4713
|
+
name: "sqlMiddleware",
|
|
4714
|
+
tools: []
|
|
4675
4715
|
});
|
|
4676
|
-
this.baseURL = baseURL;
|
|
4677
|
-
this.maxFileSizeBytes = maxFileSizeMb * 1024 * 1024;
|
|
4678
|
-
this.workingDirectory = workingDirectory;
|
|
4679
|
-
this.homeDir = "/home/gem";
|
|
4680
|
-
}
|
|
4681
|
-
resolvePath(virtualPath) {
|
|
4682
|
-
return path2.join(this.homeDir, this.workingDirectory, virtualPath);
|
|
4683
4716
|
}
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4717
|
+
const toolParams = {
|
|
4718
|
+
databaseKeys,
|
|
4719
|
+
databaseDescriptions
|
|
4720
|
+
};
|
|
4721
|
+
return createMiddleware3({
|
|
4722
|
+
name: "sqlMiddleware",
|
|
4723
|
+
contextSchema,
|
|
4724
|
+
tools: [
|
|
4725
|
+
createListTablesSqlTool(toolParams),
|
|
4726
|
+
createInfoSqlTool(toolParams),
|
|
4727
|
+
createQueryCheckerSqlTool(toolParams),
|
|
4728
|
+
createQuerySqlTool(toolParams)
|
|
4729
|
+
]
|
|
4730
|
+
});
|
|
4731
|
+
}
|
|
4732
|
+
|
|
4733
|
+
// src/middlewares/skillMiddleware.ts
|
|
4734
|
+
import { createMiddleware as createMiddleware4 } from "langchain";
|
|
4735
|
+
|
|
4736
|
+
// src/store_lattice/InMemoryThreadStore.ts
|
|
4737
|
+
var InMemoryThreadStore = class {
|
|
4738
|
+
constructor() {
|
|
4739
|
+
// Map<tenantId, Map<assistantId, Map<threadId, Thread>>>
|
|
4740
|
+
this.threads = /* @__PURE__ */ new Map();
|
|
4695
4741
|
}
|
|
4696
4742
|
/**
|
|
4697
|
-
*
|
|
4698
|
-
*
|
|
4699
|
-
* @param dirPath - Virtual directory path (must start with /)
|
|
4700
|
-
* @returns List of FileInfo objects for files and directories directly in the directory.
|
|
4701
|
-
* Directories have a trailing / in their path and is_dir=true.
|
|
4743
|
+
* Get all threads for a specific tenant and assistant
|
|
4702
4744
|
*/
|
|
4703
|
-
async
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
max_depth: 0,
|
|
4711
|
-
include_size: false,
|
|
4712
|
-
include_permissions: false,
|
|
4713
|
-
sort_by: "name",
|
|
4714
|
-
sort_desc: false
|
|
4715
|
-
});
|
|
4716
|
-
if (!result.ok) {
|
|
4717
|
-
throw result.error;
|
|
4718
|
-
}
|
|
4719
|
-
const files = result.body?.data?.files?.map((file) => ({
|
|
4720
|
-
path: this.toVirtualPath(file.path),
|
|
4721
|
-
is_dir: file.is_directory,
|
|
4722
|
-
size: file.size,
|
|
4723
|
-
modified_at: file.modified_time
|
|
4724
|
-
})) || [];
|
|
4725
|
-
return files;
|
|
4726
|
-
} catch (e) {
|
|
4727
|
-
console.error(`Error listing files in ${dirPath}:`, e);
|
|
4745
|
+
async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
|
|
4746
|
+
const tenantThreads = this.threads.get(tenantId);
|
|
4747
|
+
if (!tenantThreads) {
|
|
4748
|
+
return [];
|
|
4749
|
+
}
|
|
4750
|
+
const assistantThreads = tenantThreads.get(assistantId);
|
|
4751
|
+
if (!assistantThreads) {
|
|
4728
4752
|
return [];
|
|
4729
4753
|
}
|
|
4754
|
+
let threads = Array.from(assistantThreads.values());
|
|
4755
|
+
if (metadataFilter && Object.keys(metadataFilter).length > 0) {
|
|
4756
|
+
threads = threads.filter(
|
|
4757
|
+
(thread) => Object.entries(metadataFilter).every(
|
|
4758
|
+
([key, value]) => thread.metadata?.[key] === value
|
|
4759
|
+
)
|
|
4760
|
+
);
|
|
4761
|
+
}
|
|
4762
|
+
return threads;
|
|
4730
4763
|
}
|
|
4731
4764
|
/**
|
|
4732
|
-
*
|
|
4733
|
-
*
|
|
4734
|
-
* @param filePath - Virtual file path (must start with /)
|
|
4735
|
-
* @param offset - Line offset to start reading from (0-indexed)
|
|
4736
|
-
* @param limit - Maximum number of lines to read
|
|
4737
|
-
* @returns Formatted file content with line numbers, or error message
|
|
4765
|
+
* Get a thread by ID for a specific tenant
|
|
4738
4766
|
*/
|
|
4739
|
-
async
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
if (!result.ok) {
|
|
4749
|
-
throw result.error;
|
|
4767
|
+
async getThreadById(tenantId, threadId) {
|
|
4768
|
+
const tenantThreads = this.threads.get(tenantId);
|
|
4769
|
+
if (!tenantThreads) {
|
|
4770
|
+
return void 0;
|
|
4771
|
+
}
|
|
4772
|
+
for (const assistantThreads of tenantThreads.values()) {
|
|
4773
|
+
const thread = assistantThreads.get(threadId);
|
|
4774
|
+
if (thread) {
|
|
4775
|
+
return thread;
|
|
4750
4776
|
}
|
|
4751
|
-
content = result.body?.data?.content || "";
|
|
4752
|
-
return content;
|
|
4753
|
-
} catch (e) {
|
|
4754
|
-
return `Error: File '${filePath}' not found`;
|
|
4755
4777
|
}
|
|
4778
|
+
return void 0;
|
|
4756
4779
|
}
|
|
4757
4780
|
/**
|
|
4758
|
-
*
|
|
4759
|
-
*
|
|
4760
|
-
* @param filePath - Virtual file path (must start with /)
|
|
4761
|
-
* @returns Raw file content as FileData
|
|
4781
|
+
* Create a new thread for a tenant and assistant
|
|
4762
4782
|
*/
|
|
4763
|
-
async
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4783
|
+
async createThread(tenantId, assistantId, threadId, data) {
|
|
4784
|
+
const now = /* @__PURE__ */ new Date();
|
|
4785
|
+
const thread = {
|
|
4786
|
+
id: threadId,
|
|
4787
|
+
tenantId,
|
|
4788
|
+
assistantId,
|
|
4789
|
+
metadata: data.metadata || {},
|
|
4790
|
+
createdAt: now,
|
|
4791
|
+
updatedAt: now
|
|
4792
|
+
};
|
|
4793
|
+
if (!this.threads.has(tenantId)) {
|
|
4794
|
+
this.threads.set(tenantId, /* @__PURE__ */ new Map());
|
|
4795
|
+
}
|
|
4796
|
+
const tenantThreads = this.threads.get(tenantId);
|
|
4797
|
+
if (!tenantThreads.has(assistantId)) {
|
|
4798
|
+
tenantThreads.set(assistantId, /* @__PURE__ */ new Map());
|
|
4773
4799
|
}
|
|
4800
|
+
const assistantThreads = tenantThreads.get(assistantId);
|
|
4801
|
+
assistantThreads.set(threadId, thread);
|
|
4802
|
+
return thread;
|
|
4774
4803
|
}
|
|
4775
4804
|
/**
|
|
4776
|
-
*
|
|
4777
|
-
* Returns WriteResult. External storage sets filesUpdate=null.
|
|
4778
|
-
*
|
|
4779
|
-
* @param filePath - Virtual file path (must start with /)
|
|
4780
|
-
* @param content - File content as string
|
|
4781
|
-
* @returns WriteResult with error populated on failure
|
|
4805
|
+
* Update an existing thread
|
|
4782
4806
|
*/
|
|
4783
|
-
async
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4807
|
+
async updateThread(tenantId, threadId, updates) {
|
|
4808
|
+
const tenantThreads = this.threads.get(tenantId);
|
|
4809
|
+
if (!tenantThreads) {
|
|
4810
|
+
return null;
|
|
4811
|
+
}
|
|
4812
|
+
for (const assistantThreads of tenantThreads.values()) {
|
|
4813
|
+
const existing = assistantThreads.get(threadId);
|
|
4814
|
+
if (existing) {
|
|
4815
|
+
const updated = {
|
|
4816
|
+
...existing,
|
|
4817
|
+
metadata: {
|
|
4818
|
+
...existing.metadata,
|
|
4819
|
+
...updates.metadata || {}
|
|
4820
|
+
},
|
|
4821
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
4822
|
+
};
|
|
4823
|
+
assistantThreads.set(threadId, updated);
|
|
4824
|
+
return updated;
|
|
4796
4825
|
}
|
|
4797
|
-
return {
|
|
4798
|
-
path: filePath,
|
|
4799
|
-
filesUpdate: {
|
|
4800
|
-
[filePath]: {
|
|
4801
|
-
content: content.split("\n"),
|
|
4802
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4803
|
-
modified_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4804
|
-
}
|
|
4805
|
-
}
|
|
4806
|
-
};
|
|
4807
|
-
} catch (e) {
|
|
4808
|
-
throw new Error(`Error writing file '${filePath}': ${e.message}`);
|
|
4809
4826
|
}
|
|
4827
|
+
return null;
|
|
4810
4828
|
}
|
|
4811
4829
|
/**
|
|
4812
|
-
*
|
|
4813
|
-
* Returns EditResult. External storage sets filesUpdate=null.
|
|
4814
|
-
*
|
|
4815
|
-
* @param filePath - Virtual file path (must start with /)
|
|
4816
|
-
* @param oldString - String to find and replace
|
|
4817
|
-
* @param newString - Replacement string
|
|
4818
|
-
* @param replaceAll - If true, replace all occurrences (default: false)
|
|
4819
|
-
* @returns EditResult with error, path, filesUpdate, and occurrences
|
|
4830
|
+
* Delete a thread by ID
|
|
4820
4831
|
*/
|
|
4821
|
-
async
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
replace_mode: replaceAll ? "ALL" : "FIRST"
|
|
4830
|
-
});
|
|
4831
|
-
if (!result.ok) {
|
|
4832
|
-
throw result.error;
|
|
4832
|
+
async deleteThread(tenantId, threadId) {
|
|
4833
|
+
const tenantThreads = this.threads.get(tenantId);
|
|
4834
|
+
if (!tenantThreads) {
|
|
4835
|
+
return false;
|
|
4836
|
+
}
|
|
4837
|
+
for (const assistantThreads of tenantThreads.values()) {
|
|
4838
|
+
if (assistantThreads.has(threadId)) {
|
|
4839
|
+
return assistantThreads.delete(threadId);
|
|
4833
4840
|
}
|
|
4834
|
-
return {
|
|
4835
|
-
path: filePath,
|
|
4836
|
-
filesUpdate: null
|
|
4837
|
-
};
|
|
4838
|
-
} catch (e) {
|
|
4839
|
-
throw new Error(`Error editing file '${filePath}': ${e.message}`);
|
|
4840
4841
|
}
|
|
4842
|
+
return false;
|
|
4841
4843
|
}
|
|
4842
4844
|
/**
|
|
4843
|
-
*
|
|
4844
|
-
*
|
|
4845
|
-
* Searches file contents for a regex pattern within the sandbox.
|
|
4846
|
-
*
|
|
4847
|
-
* @param pattern - Regex pattern to search for
|
|
4848
|
-
* @param searchPath - Base path to search from (default: "/")
|
|
4849
|
-
* @param glob - Optional glob pattern to filter files (e.g., "*.py")
|
|
4850
|
-
* @returns List of GrepMatch objects or error string for invalid regex
|
|
4845
|
+
* Check if thread exists
|
|
4851
4846
|
*/
|
|
4852
|
-
async
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
path: baseFull,
|
|
4857
|
-
glob: glob || "**/*"
|
|
4858
|
-
});
|
|
4859
|
-
if (!result.ok) {
|
|
4860
|
-
throw result.error;
|
|
4847
|
+
async hasThread(tenantId, threadId) {
|
|
4848
|
+
const tenantThreads = this.threads.get(tenantId);
|
|
4849
|
+
if (!tenantThreads) {
|
|
4850
|
+
return false;
|
|
4861
4851
|
}
|
|
4862
|
-
const
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
const fileData = await this.sandbox.file.searchInFile({
|
|
4866
|
-
file: absolutePath,
|
|
4867
|
-
regex: pattern
|
|
4868
|
-
});
|
|
4869
|
-
if (!fileData.ok) {
|
|
4870
|
-
continue;
|
|
4852
|
+
for (const assistantThreads of tenantThreads.values()) {
|
|
4853
|
+
if (assistantThreads.has(threadId)) {
|
|
4854
|
+
return true;
|
|
4871
4855
|
}
|
|
4872
|
-
const matchesData = fileData.body?.data?.matches || [];
|
|
4873
|
-
const matchLines = fileData.body?.data?.line_numbers || [];
|
|
4874
|
-
matchesData.forEach((match, index) => {
|
|
4875
|
-
matches.push({
|
|
4876
|
-
path: this.toVirtualPath(absolutePath),
|
|
4877
|
-
line: matchLines[index],
|
|
4878
|
-
text: match
|
|
4879
|
-
});
|
|
4880
|
-
});
|
|
4881
4856
|
}
|
|
4882
|
-
return
|
|
4857
|
+
return false;
|
|
4883
4858
|
}
|
|
4884
4859
|
/**
|
|
4885
|
-
*
|
|
4886
|
-
*
|
|
4887
|
-
* @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
|
|
4888
|
-
* @param searchPath - Base path to search from (default: "/")
|
|
4889
|
-
* @returns List of FileInfo objects matching the pattern
|
|
4860
|
+
* Clear all threads for a tenant (useful for testing)
|
|
4890
4861
|
*/
|
|
4891
|
-
|
|
4892
|
-
if (
|
|
4893
|
-
|
|
4894
|
-
}
|
|
4895
|
-
|
|
4896
|
-
const result = await this.sandbox.file.findFiles({
|
|
4897
|
-
path: resolvedSearchPath,
|
|
4898
|
-
glob: pattern || "**/*"
|
|
4899
|
-
});
|
|
4900
|
-
if (!result.ok) {
|
|
4901
|
-
throw result.error;
|
|
4862
|
+
clear(tenantId) {
|
|
4863
|
+
if (tenantId) {
|
|
4864
|
+
this.threads.delete(tenantId);
|
|
4865
|
+
} else {
|
|
4866
|
+
this.threads.clear();
|
|
4902
4867
|
}
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
});
|
|
4913
|
-
if (!fileInfo.ok) {
|
|
4914
|
-
continue;
|
|
4868
|
+
}
|
|
4869
|
+
/**
|
|
4870
|
+
* Get all threads for all assistants (useful for debugging)
|
|
4871
|
+
*/
|
|
4872
|
+
getAllThreads() {
|
|
4873
|
+
const allThreads = [];
|
|
4874
|
+
for (const tenantThreads of this.threads.values()) {
|
|
4875
|
+
for (const assistantThreads of tenantThreads.values()) {
|
|
4876
|
+
allThreads.push(...Array.from(assistantThreads.values()));
|
|
4915
4877
|
}
|
|
4916
|
-
results.push({
|
|
4917
|
-
path: this.toVirtualPath(filePath),
|
|
4918
|
-
is_dir: false,
|
|
4919
|
-
size: fileInfo.body?.data?.files?.[0]?.size,
|
|
4920
|
-
modified_at: fileInfo.body?.data?.files?.[0]?.modified_time
|
|
4921
|
-
});
|
|
4922
4878
|
}
|
|
4923
|
-
return
|
|
4879
|
+
return allThreads;
|
|
4924
4880
|
}
|
|
4925
4881
|
};
|
|
4926
4882
|
|
|
4927
|
-
// src/
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
// src/middlewares/contextSchema.ts
|
|
4931
|
-
import z40 from "zod";
|
|
4932
|
-
var contextSchema = z40.object({
|
|
4933
|
-
runConfig: z40.any()
|
|
4934
|
-
});
|
|
4935
|
-
|
|
4936
|
-
// src/middlewares/codeEvalMiddleware.ts
|
|
4937
|
-
function createCodeEvalMiddleware(params = { isolatedLevel: "global" }) {
|
|
4938
|
-
const codeEvalTool = createCodeEvalTool({ isolatedLevel: params.isolatedLevel });
|
|
4939
|
-
const codeExecuteFileTool = createCodeExecuteFileTool({ isolatedLevel: params.isolatedLevel });
|
|
4940
|
-
return createMiddleware({
|
|
4941
|
-
name: "codeEvalMiddleware",
|
|
4942
|
-
contextSchema,
|
|
4943
|
-
tools: [codeEvalTool, codeExecuteFileTool, getToolClient("convert_to_markdown")]
|
|
4944
|
-
});
|
|
4945
|
-
}
|
|
4946
|
-
|
|
4947
|
-
// src/middlewares/browserMiddleware.ts
|
|
4948
|
-
import { createMiddleware as createMiddleware2 } from "langchain";
|
|
4949
|
-
function createBrowserMiddleware(params = { isolatedLevel: "global" }) {
|
|
4950
|
-
const isolatedLevel = params.isolatedLevel || "global";
|
|
4951
|
-
const tools = [
|
|
4952
|
-
createBrowserNavigateTool({ isolatedLevel }),
|
|
4953
|
-
createBrowserClickTool({ isolatedLevel }),
|
|
4954
|
-
createBrowserGetTextTool({ isolatedLevel }),
|
|
4955
|
-
createBrowserGetMarkdownTool({ isolatedLevel }),
|
|
4956
|
-
createBrowserEvaluateTool({ isolatedLevel }),
|
|
4957
|
-
createBrowserScreenshotTool({ isolatedLevel }),
|
|
4958
|
-
createBrowserScrollTool({ isolatedLevel }),
|
|
4959
|
-
createBrowserFormInputFillTool({ isolatedLevel }),
|
|
4960
|
-
createBrowserSelectTool({ isolatedLevel }),
|
|
4961
|
-
createBrowserHoverTool({ isolatedLevel }),
|
|
4962
|
-
createBrowserGoBackTool({ isolatedLevel }),
|
|
4963
|
-
createBrowserGoForwardTool({ isolatedLevel }),
|
|
4964
|
-
createBrowserNewTabTool({ isolatedLevel }),
|
|
4965
|
-
createBrowserTabListTool({ isolatedLevel }),
|
|
4966
|
-
createBrowserSwitchTabTool({ isolatedLevel }),
|
|
4967
|
-
createBrowserCloseTabTool({ isolatedLevel }),
|
|
4968
|
-
createBrowserCloseTool({ isolatedLevel }),
|
|
4969
|
-
createBrowserPressKeyTool({ isolatedLevel }),
|
|
4970
|
-
createBrowserReadLinksTool({ isolatedLevel }),
|
|
4971
|
-
createBrowserGetClickableElementsTool({ isolatedLevel }),
|
|
4972
|
-
createBrowserGetDownloadListTool({ isolatedLevel }),
|
|
4973
|
-
createBrowserGetInfoTool({ isolatedLevel })
|
|
4974
|
-
];
|
|
4975
|
-
return createMiddleware2({
|
|
4976
|
-
name: "browserMiddleware",
|
|
4977
|
-
contextSchema,
|
|
4978
|
-
tools
|
|
4979
|
-
});
|
|
4980
|
-
}
|
|
4981
|
-
|
|
4982
|
-
// src/middlewares/sqlMiddleware.ts
|
|
4983
|
-
import { createMiddleware as createMiddleware3 } from "langchain";
|
|
4984
|
-
function createSqlMiddleware(params) {
|
|
4985
|
-
const { databaseKeys, databaseDescriptions } = params;
|
|
4986
|
-
if (!databaseKeys || databaseKeys.length === 0) {
|
|
4987
|
-
return createMiddleware3({
|
|
4988
|
-
name: "sqlMiddleware",
|
|
4989
|
-
tools: []
|
|
4990
|
-
});
|
|
4991
|
-
}
|
|
4992
|
-
const toolParams = {
|
|
4993
|
-
databaseKeys,
|
|
4994
|
-
databaseDescriptions
|
|
4995
|
-
};
|
|
4996
|
-
return createMiddleware3({
|
|
4997
|
-
name: "sqlMiddleware",
|
|
4998
|
-
contextSchema,
|
|
4999
|
-
tools: [
|
|
5000
|
-
createListTablesSqlTool(toolParams),
|
|
5001
|
-
createInfoSqlTool(toolParams),
|
|
5002
|
-
createQueryCheckerSqlTool(toolParams),
|
|
5003
|
-
createQuerySqlTool(toolParams)
|
|
5004
|
-
]
|
|
5005
|
-
});
|
|
5006
|
-
}
|
|
5007
|
-
|
|
5008
|
-
// src/middlewares/skillMiddleware.ts
|
|
5009
|
-
import { createMiddleware as createMiddleware4 } from "langchain";
|
|
5010
|
-
|
|
5011
|
-
// src/store_lattice/InMemoryThreadStore.ts
|
|
5012
|
-
var InMemoryThreadStore = class {
|
|
4883
|
+
// src/store_lattice/InMemoryAssistantStore.ts
|
|
4884
|
+
var InMemoryAssistantStore = class {
|
|
5013
4885
|
constructor() {
|
|
5014
|
-
|
|
5015
|
-
this.threads = /* @__PURE__ */ new Map();
|
|
5016
|
-
}
|
|
5017
|
-
/**
|
|
5018
|
-
* Get all threads for a specific tenant and assistant
|
|
5019
|
-
*/
|
|
5020
|
-
async getThreadsByAssistantId(tenantId, assistantId, metadataFilter) {
|
|
5021
|
-
const tenantThreads = this.threads.get(tenantId);
|
|
5022
|
-
if (!tenantThreads) {
|
|
5023
|
-
return [];
|
|
5024
|
-
}
|
|
5025
|
-
const assistantThreads = tenantThreads.get(assistantId);
|
|
5026
|
-
if (!assistantThreads) {
|
|
5027
|
-
return [];
|
|
5028
|
-
}
|
|
5029
|
-
let threads = Array.from(assistantThreads.values());
|
|
5030
|
-
if (metadataFilter && Object.keys(metadataFilter).length > 0) {
|
|
5031
|
-
threads = threads.filter(
|
|
5032
|
-
(thread) => Object.entries(metadataFilter).every(
|
|
5033
|
-
([key, value]) => thread.metadata?.[key] === value
|
|
5034
|
-
)
|
|
5035
|
-
);
|
|
5036
|
-
}
|
|
5037
|
-
return threads;
|
|
5038
|
-
}
|
|
5039
|
-
/**
|
|
5040
|
-
* Get a thread by ID for a specific tenant
|
|
5041
|
-
*/
|
|
5042
|
-
async getThreadById(tenantId, threadId) {
|
|
5043
|
-
const tenantThreads = this.threads.get(tenantId);
|
|
5044
|
-
if (!tenantThreads) {
|
|
5045
|
-
return void 0;
|
|
5046
|
-
}
|
|
5047
|
-
for (const assistantThreads of tenantThreads.values()) {
|
|
5048
|
-
const thread = assistantThreads.get(threadId);
|
|
5049
|
-
if (thread) {
|
|
5050
|
-
return thread;
|
|
5051
|
-
}
|
|
5052
|
-
}
|
|
5053
|
-
return void 0;
|
|
5054
|
-
}
|
|
5055
|
-
/**
|
|
5056
|
-
* Create a new thread for a tenant and assistant
|
|
5057
|
-
*/
|
|
5058
|
-
async createThread(tenantId, assistantId, threadId, data) {
|
|
5059
|
-
const now = /* @__PURE__ */ new Date();
|
|
5060
|
-
const thread = {
|
|
5061
|
-
id: threadId,
|
|
5062
|
-
tenantId,
|
|
5063
|
-
assistantId,
|
|
5064
|
-
metadata: data.metadata || {},
|
|
5065
|
-
createdAt: now,
|
|
5066
|
-
updatedAt: now
|
|
5067
|
-
};
|
|
5068
|
-
if (!this.threads.has(tenantId)) {
|
|
5069
|
-
this.threads.set(tenantId, /* @__PURE__ */ new Map());
|
|
5070
|
-
}
|
|
5071
|
-
const tenantThreads = this.threads.get(tenantId);
|
|
5072
|
-
if (!tenantThreads.has(assistantId)) {
|
|
5073
|
-
tenantThreads.set(assistantId, /* @__PURE__ */ new Map());
|
|
5074
|
-
}
|
|
5075
|
-
const assistantThreads = tenantThreads.get(assistantId);
|
|
5076
|
-
assistantThreads.set(threadId, thread);
|
|
5077
|
-
return thread;
|
|
5078
|
-
}
|
|
5079
|
-
/**
|
|
5080
|
-
* Update an existing thread
|
|
5081
|
-
*/
|
|
5082
|
-
async updateThread(tenantId, threadId, updates) {
|
|
5083
|
-
const tenantThreads = this.threads.get(tenantId);
|
|
5084
|
-
if (!tenantThreads) {
|
|
5085
|
-
return null;
|
|
5086
|
-
}
|
|
5087
|
-
for (const assistantThreads of tenantThreads.values()) {
|
|
5088
|
-
const existing = assistantThreads.get(threadId);
|
|
5089
|
-
if (existing) {
|
|
5090
|
-
const updated = {
|
|
5091
|
-
...existing,
|
|
5092
|
-
metadata: {
|
|
5093
|
-
...existing.metadata,
|
|
5094
|
-
...updates.metadata || {}
|
|
5095
|
-
},
|
|
5096
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
5097
|
-
};
|
|
5098
|
-
assistantThreads.set(threadId, updated);
|
|
5099
|
-
return updated;
|
|
5100
|
-
}
|
|
5101
|
-
}
|
|
5102
|
-
return null;
|
|
5103
|
-
}
|
|
5104
|
-
/**
|
|
5105
|
-
* Delete a thread by ID
|
|
5106
|
-
*/
|
|
5107
|
-
async deleteThread(tenantId, threadId) {
|
|
5108
|
-
const tenantThreads = this.threads.get(tenantId);
|
|
5109
|
-
if (!tenantThreads) {
|
|
5110
|
-
return false;
|
|
5111
|
-
}
|
|
5112
|
-
for (const assistantThreads of tenantThreads.values()) {
|
|
5113
|
-
if (assistantThreads.has(threadId)) {
|
|
5114
|
-
return assistantThreads.delete(threadId);
|
|
5115
|
-
}
|
|
5116
|
-
}
|
|
5117
|
-
return false;
|
|
5118
|
-
}
|
|
5119
|
-
/**
|
|
5120
|
-
* Check if thread exists
|
|
5121
|
-
*/
|
|
5122
|
-
async hasThread(tenantId, threadId) {
|
|
5123
|
-
const tenantThreads = this.threads.get(tenantId);
|
|
5124
|
-
if (!tenantThreads) {
|
|
5125
|
-
return false;
|
|
5126
|
-
}
|
|
5127
|
-
for (const assistantThreads of tenantThreads.values()) {
|
|
5128
|
-
if (assistantThreads.has(threadId)) {
|
|
5129
|
-
return true;
|
|
5130
|
-
}
|
|
5131
|
-
}
|
|
5132
|
-
return false;
|
|
5133
|
-
}
|
|
5134
|
-
/**
|
|
5135
|
-
* Clear all threads for a tenant (useful for testing)
|
|
5136
|
-
*/
|
|
5137
|
-
clear(tenantId) {
|
|
5138
|
-
if (tenantId) {
|
|
5139
|
-
this.threads.delete(tenantId);
|
|
5140
|
-
} else {
|
|
5141
|
-
this.threads.clear();
|
|
5142
|
-
}
|
|
5143
|
-
}
|
|
5144
|
-
/**
|
|
5145
|
-
* Get all threads for all assistants (useful for debugging)
|
|
5146
|
-
*/
|
|
5147
|
-
getAllThreads() {
|
|
5148
|
-
const allThreads = [];
|
|
5149
|
-
for (const tenantThreads of this.threads.values()) {
|
|
5150
|
-
for (const assistantThreads of tenantThreads.values()) {
|
|
5151
|
-
allThreads.push(...Array.from(assistantThreads.values()));
|
|
5152
|
-
}
|
|
5153
|
-
}
|
|
5154
|
-
return allThreads;
|
|
5155
|
-
}
|
|
5156
|
-
};
|
|
5157
|
-
|
|
5158
|
-
// src/store_lattice/InMemoryAssistantStore.ts
|
|
5159
|
-
var InMemoryAssistantStore = class {
|
|
5160
|
-
constructor() {
|
|
5161
|
-
this.assistants = /* @__PURE__ */ new Map();
|
|
4886
|
+
this.assistants = /* @__PURE__ */ new Map();
|
|
5162
4887
|
}
|
|
5163
4888
|
/**
|
|
5164
4889
|
* Get all assistants for a tenant
|
|
@@ -5250,7 +4975,7 @@ var InMemoryAssistantStore = class {
|
|
|
5250
4975
|
|
|
5251
4976
|
// src/store_lattice/FileSystemSkillStore.ts
|
|
5252
4977
|
import * as fs from "fs/promises";
|
|
5253
|
-
import * as
|
|
4978
|
+
import * as path2 from "path";
|
|
5254
4979
|
|
|
5255
4980
|
// src/skill_lattice/skillNameValidator.ts
|
|
5256
4981
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
@@ -5423,10 +5148,10 @@ var FileSystemSkillStore = class {
|
|
|
5423
5148
|
constructor(options = {}) {
|
|
5424
5149
|
const defaultPath = "lattice_store/skills";
|
|
5425
5150
|
const providedPath = options.rootDir || defaultPath;
|
|
5426
|
-
if (
|
|
5151
|
+
if (path2.isAbsolute(providedPath)) {
|
|
5427
5152
|
this.rootDir = providedPath;
|
|
5428
5153
|
} else {
|
|
5429
|
-
this.rootDir =
|
|
5154
|
+
this.rootDir = path2.resolve(process.cwd(), providedPath);
|
|
5430
5155
|
}
|
|
5431
5156
|
this.ensureDirectoryExists().catch((error) => {
|
|
5432
5157
|
console.error("Failed to initialize FileSystemSkillStore:", error);
|
|
@@ -5450,14 +5175,14 @@ var FileSystemSkillStore = class {
|
|
|
5450
5175
|
if (name.includes("..") || name.includes("/") || name.includes("\\")) {
|
|
5451
5176
|
throw new Error(`Invalid skill name: ${name} (contains invalid characters)`);
|
|
5452
5177
|
}
|
|
5453
|
-
return
|
|
5178
|
+
return path2.join(this.rootDir, name);
|
|
5454
5179
|
}
|
|
5455
5180
|
/**
|
|
5456
5181
|
* Get file path for a skill name
|
|
5457
5182
|
* File is always named SKILL.md inside the name directory
|
|
5458
5183
|
*/
|
|
5459
5184
|
getSkillFilePath(name) {
|
|
5460
|
-
return
|
|
5185
|
+
return path2.join(this.getSkillDirectoryPath(name), "SKILL.md");
|
|
5461
5186
|
}
|
|
5462
5187
|
/**
|
|
5463
5188
|
* Read skill from file
|
|
@@ -5744,14 +5469,14 @@ ${body}` : `${frontmatter}
|
|
|
5744
5469
|
*/
|
|
5745
5470
|
async listSkillResources(_tenantId, skillName) {
|
|
5746
5471
|
const skillDir = this.getSkillDirectoryPath(skillName);
|
|
5747
|
-
const resourcesDir =
|
|
5472
|
+
const resourcesDir = path2.join(skillDir, "resources");
|
|
5748
5473
|
try {
|
|
5749
5474
|
const entries = await fs.readdir(resourcesDir, { withFileTypes: true, recursive: true });
|
|
5750
5475
|
const resources = [];
|
|
5751
5476
|
for (const entry of entries) {
|
|
5752
5477
|
if (!entry.isDirectory()) {
|
|
5753
|
-
const fullPath =
|
|
5754
|
-
const relativePath =
|
|
5478
|
+
const fullPath = path2.join(entry.path, entry.name);
|
|
5479
|
+
const relativePath = path2.relative(resourcesDir, fullPath);
|
|
5755
5480
|
resources.push(relativePath.replace(/\\/g, "/"));
|
|
5756
5481
|
}
|
|
5757
5482
|
}
|
|
@@ -5772,10 +5497,10 @@ ${body}` : `${frontmatter}
|
|
|
5772
5497
|
*/
|
|
5773
5498
|
async loadSkillResource(_tenantId, skillName, resourcePath) {
|
|
5774
5499
|
const skillDir = this.getSkillDirectoryPath(skillName);
|
|
5775
|
-
const resourcesDir =
|
|
5776
|
-
const fullPath =
|
|
5777
|
-
const resolvedPath =
|
|
5778
|
-
const resolvedResourcesDir =
|
|
5500
|
+
const resourcesDir = path2.join(skillDir, "resources");
|
|
5501
|
+
const fullPath = path2.join(resourcesDir, resourcePath);
|
|
5502
|
+
const resolvedPath = path2.resolve(fullPath);
|
|
5503
|
+
const resolvedResourcesDir = path2.resolve(resourcesDir);
|
|
5779
5504
|
if (!resolvedPath.startsWith(resolvedResourcesDir)) {
|
|
5780
5505
|
throw new Error(`Invalid resource path: ${resourcePath}`);
|
|
5781
5506
|
}
|
|
@@ -9239,7 +8964,7 @@ function createShowWidgetTool() {
|
|
|
9239
8964
|
},
|
|
9240
8965
|
{
|
|
9241
8966
|
name: "show_widget",
|
|
9242
|
-
description: "Render an interactive HTML widget or SVG diagram visible to the user. Use for: charts, dashboards, calculators, forms, diagrams, timers, games, visualizations. The widget appears in a panel next to the chat. Users can interact with it and send data back via window.
|
|
8967
|
+
description: "Render an interactive HTML widget or SVG diagram visible to the user. Use for: charts, dashboards, calculators, forms, diagrams, timers, games, visualizations. The widget appears in a panel next to the chat. Users can interact with it and send data back via window.sendPrompt(data). IMPORTANT: Always call load_guidelines before your first show_widget.",
|
|
9243
8968
|
schema: ShowWidgetInputSchema
|
|
9244
8969
|
}
|
|
9245
8970
|
);
|
|
@@ -9311,22 +9036,19 @@ import { createMiddleware as createMiddleware10 } from "langchain";
|
|
|
9311
9036
|
|
|
9312
9037
|
// src/deep_agent_new/middleware/AGENTS_MD.ts
|
|
9313
9038
|
var AGENTS_MD = `
|
|
9314
|
-
# AGENTS.md - Your Workspace
|
|
9315
|
-
|
|
9316
|
-
This folder is home. Treat it that way.
|
|
9317
9039
|
|
|
9318
9040
|
## First Run
|
|
9319
9041
|
|
|
9320
|
-
If
|
|
9042
|
+
If \`/agent/BOOTSTRAP.md\` exists, that's your birth certificate. Follow it, figure out who you are, then delete it. You won't need it again.
|
|
9321
9043
|
|
|
9322
9044
|
## Every Session
|
|
9323
9045
|
|
|
9324
9046
|
Before doing anything else:
|
|
9325
9047
|
|
|
9326
|
-
1. Read
|
|
9327
|
-
2. Read
|
|
9048
|
+
1. Read \`/agent/SOUL.md\` \u2014 this is who you are
|
|
9049
|
+
2. Read \`/agent/USER.md\` \u2014 this is who you're helping
|
|
9328
9050
|
3. Read \`memory/YYYY-MM-DD.md\` (today + yesterday) for recent context
|
|
9329
|
-
4. **If in MAIN SESSION** (direct chat with your human): Also read
|
|
9051
|
+
4. **If in MAIN SESSION** (direct chat with your human): Also read \`/agent/MEMORY.md\`
|
|
9330
9052
|
|
|
9331
9053
|
Don't ask permission. Just do it.
|
|
9332
9054
|
|
|
@@ -9334,17 +9056,18 @@ Don't ask permission. Just do it.
|
|
|
9334
9056
|
|
|
9335
9057
|
You wake up fresh each session. These files are your continuity:
|
|
9336
9058
|
|
|
9337
|
-
- **
|
|
9338
|
-
- **
|
|
9059
|
+
- **agent Long-term:** \`/agent/MEMORY.md\` \u2014 your curated memories, like a human's long-term memory
|
|
9060
|
+
- **Project Memory**: \`/PROJECT.md\` - Loaded from project root if available - Project-specific instructions
|
|
9061
|
+
- **Daily Project notes:** \`/daily/YYYY-MM-DD.md\` (create \`daily/\` if needed) \u2014 raw logs of what happened
|
|
9339
9062
|
|
|
9340
9063
|
Capture what matters. Decisions, context, things to remember. Skip the secrets unless asked to keep them.
|
|
9341
9064
|
|
|
9342
|
-
### \u{1F9E0} MEMORY.md - Your Long-Term Memory
|
|
9065
|
+
### \u{1F9E0} /agent/MEMORY.md - Your Long-Term Memory
|
|
9343
9066
|
|
|
9344
9067
|
- **ONLY load in main session** (direct chats with your human)
|
|
9345
9068
|
- **DO NOT load in shared contexts** (Discord, group chats, sessions with other people)
|
|
9346
9069
|
- This is for **security** \u2014 contains personal context that shouldn't leak to strangers
|
|
9347
|
-
- You can **read, edit, and update** MEMORY.md freely in main sessions
|
|
9070
|
+
- You can **read, edit, and update** /agent/MEMORY.md freely in main sessions
|
|
9348
9071
|
- Write significant events, thoughts, decisions, opinions, lessons learned
|
|
9349
9072
|
- This is your curated memory \u2014 the distilled essence, not raw logs
|
|
9350
9073
|
- Over time, review your daily files and update MEMORY.md with what's worth keeping
|
|
@@ -9353,11 +9076,42 @@ Capture what matters. Decisions, context, things to remember. Skip the secrets u
|
|
|
9353
9076
|
|
|
9354
9077
|
- **Memory is limited** \u2014 if you want to remember something, WRITE IT TO A FILE
|
|
9355
9078
|
- "Mental notes" don't survive session restarts. Files do.
|
|
9356
|
-
- When someone says "remember this" \u2192 update
|
|
9357
|
-
- When you learn a lesson \u2192 update AGENTS.md, TOOLS.md, or the relevant skill
|
|
9079
|
+
- When someone says "remember this" \u2192 update \`/daily/YYYY-MM-DD.md\` or relevant file
|
|
9080
|
+
- When you learn a lesson \u2192 update /agent/AGENTS.md, /agent/TOOLS.md, or the relevant skill
|
|
9358
9081
|
- When you make a mistake \u2192 document it so future-you doesn't repeat it
|
|
9359
9082
|
- **Text > Brain** \u{1F4DD}
|
|
9360
9083
|
|
|
9084
|
+
### Project Memory File: \`/PROJECT.md\`
|
|
9085
|
+
\u2192 Describes **how this specific project works** and **how the agent should behave here only.**
|
|
9086
|
+
|
|
9087
|
+
**Store here:**
|
|
9088
|
+
- Project-specific architecture and design patterns
|
|
9089
|
+
- Coding conventions specific to this codebase
|
|
9090
|
+
- Project structure and organization
|
|
9091
|
+
- Testing strategies for this project
|
|
9092
|
+
- Deployment processes and workflows
|
|
9093
|
+
- Team conventions and guidelines
|
|
9094
|
+
|
|
9095
|
+
**Examples:**
|
|
9096
|
+
- "This project uses FastAPI with SQLAlchemy"
|
|
9097
|
+
- "Tests go in tests/ directory mirroring src/ structure"
|
|
9098
|
+
- "All API changes require updating OpenAPI spec"
|
|
9099
|
+
|
|
9100
|
+
### Project Memory Files: \`{project_deepagents_dir}/*.md\`
|
|
9101
|
+
\u2192 Use for **project-specific reference information** and structured notes.
|
|
9102
|
+
|
|
9103
|
+
**Store here:**
|
|
9104
|
+
- API design documentation
|
|
9105
|
+
- Architecture decisions and rationale
|
|
9106
|
+
- Deployment procedures
|
|
9107
|
+
- Common debugging patterns
|
|
9108
|
+
- Onboarding information
|
|
9109
|
+
|
|
9110
|
+
**Examples:**
|
|
9111
|
+
- \`{project_deepagents_dir}/api-design.md\` - REST API patterns used
|
|
9112
|
+
- \`{project_deepagents_dir}/architecture.md\` - System architecture overview
|
|
9113
|
+
- \`{project_deepagents_dir}/deployment.md\` - How to deploy this project
|
|
9114
|
+
|
|
9361
9115
|
## Safety
|
|
9362
9116
|
|
|
9363
9117
|
- Don't exfiltrate private data. Ever.
|
|
@@ -9529,10 +9283,10 @@ Offer suggestions if they're stuck. Have fun with it.
|
|
|
9529
9283
|
|
|
9530
9284
|
Update these files with what you learned:
|
|
9531
9285
|
|
|
9532
|
-
-
|
|
9533
|
-
-
|
|
9286
|
+
- \`/agent/IDENTITY.md\` \u2014 your name, creature, vibe, emoji
|
|
9287
|
+
- \`/agent/USER.md\` \u2014 their name, how to address them, timezone, notes
|
|
9534
9288
|
|
|
9535
|
-
Then open
|
|
9289
|
+
Then open \`/agent/SOUL.md\` together and talk about:
|
|
9536
9290
|
|
|
9537
9291
|
- What matters to them
|
|
9538
9292
|
- How they want you to behave
|
|
@@ -9665,12 +9419,12 @@ async function getBackend2(backend, stateAndStore) {
|
|
|
9665
9419
|
return backend;
|
|
9666
9420
|
}
|
|
9667
9421
|
var BOOTSTRAP_FILE_NAMES = {
|
|
9668
|
-
agents: "AGENTS.md",
|
|
9669
|
-
soul: "SOUL.md",
|
|
9670
|
-
identity: "IDENTITY.md",
|
|
9671
|
-
user: "USER.md",
|
|
9672
|
-
tools: "TOOLS.md",
|
|
9673
|
-
bootstrap: "BOOTSTRAP.md"
|
|
9422
|
+
agents: "/agent/AGENTS.md",
|
|
9423
|
+
soul: "/agent/SOUL.md",
|
|
9424
|
+
identity: "/agent/IDENTITY.md",
|
|
9425
|
+
user: "/agent/USER.md",
|
|
9426
|
+
tools: "/agent/TOOLS.md",
|
|
9427
|
+
bootstrap: "/agent/BOOTSTRAP.md"
|
|
9674
9428
|
};
|
|
9675
9429
|
var BOOTSTRAP_SECTION_HEADERS = {
|
|
9676
9430
|
agents: "## Operating Instructions",
|
|
@@ -9693,14 +9447,14 @@ Document available tools and their usage notes here.`,
|
|
|
9693
9447
|
async function createBootstrapFiles(config, backend, stateAndStore) {
|
|
9694
9448
|
const resolvedBackend = await getBackend2(backend, stateAndStore);
|
|
9695
9449
|
try {
|
|
9696
|
-
const agentsContent = await resolvedBackend.read("/AGENTS.md", 0, 1);
|
|
9450
|
+
const agentsContent = await resolvedBackend.read("/agent/AGENTS.md", 0, 1);
|
|
9697
9451
|
if (!agentsContent.includes("Error:")) {
|
|
9698
9452
|
return;
|
|
9699
9453
|
}
|
|
9700
9454
|
} catch (error) {
|
|
9701
9455
|
}
|
|
9702
9456
|
for (const [key, filename] of Object.entries(BOOTSTRAP_FILE_NAMES)) {
|
|
9703
|
-
const filePath =
|
|
9457
|
+
const filePath = filename;
|
|
9704
9458
|
try {
|
|
9705
9459
|
const content = config[key] || DEFAULT_BOOTSTRAP_CONTENT[key];
|
|
9706
9460
|
await resolvedBackend.write(filePath, content);
|
|
@@ -9714,7 +9468,7 @@ async function buildBootstrapPromptSections(backend, stateAndStore) {
|
|
|
9714
9468
|
const sections = [];
|
|
9715
9469
|
const fileOrder = ["agents", "soul", "identity", "user", "tools", "bootstrap"];
|
|
9716
9470
|
for (const key of fileOrder) {
|
|
9717
|
-
const filePath =
|
|
9471
|
+
const filePath = BOOTSTRAP_FILE_NAMES[key];
|
|
9718
9472
|
try {
|
|
9719
9473
|
const content = await resolvedBackend.read(filePath);
|
|
9720
9474
|
if (content && !content.includes("Error:") && content.trim()) {
|
|
@@ -9750,14 +9504,13 @@ function createClawMiddleware(options = {}) {
|
|
|
9750
9504
|
if (injectBootstrapFiles && backend) {
|
|
9751
9505
|
const stateAndStore = {
|
|
9752
9506
|
state: request.state || {},
|
|
9753
|
-
store: request.store
|
|
9507
|
+
store: request.store,
|
|
9508
|
+
...request.runtime.context.runConfig
|
|
9754
9509
|
};
|
|
9755
9510
|
const bootstrapSections = await buildBootstrapPromptSections(backend, stateAndStore);
|
|
9756
9511
|
if (bootstrapSections.length > 0) {
|
|
9757
9512
|
const bootstrapContext = `
|
|
9758
9513
|
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
9514
|
${bootstrapSections.join("\n\n")}
|
|
9762
9515
|
|
|
9763
9516
|
`;
|
|
@@ -9767,113 +9520,782 @@ ${bootstrapSections.join("\n\n")}
|
|
|
9767
9520
|
}
|
|
9768
9521
|
return handler(request);
|
|
9769
9522
|
}
|
|
9770
|
-
});
|
|
9771
|
-
}
|
|
9523
|
+
});
|
|
9524
|
+
}
|
|
9525
|
+
|
|
9526
|
+
// src/middlewares/unknownToolHandlerMiddleware.ts
|
|
9527
|
+
import { createMiddleware as createMiddleware11 } from "langchain";
|
|
9528
|
+
import { AIMessage as AIMessage2, ToolMessage as ToolMessage3 } from "@langchain/core/messages";
|
|
9529
|
+
function createUnknownToolHandlerMiddleware(config = {}) {
|
|
9530
|
+
const {
|
|
9531
|
+
strategy = "error",
|
|
9532
|
+
errorMessageTemplate = (name, tools) => `Error: Tool "${name}" does not exist.
|
|
9533
|
+
|
|
9534
|
+
Available tools:
|
|
9535
|
+
` + tools.map((t) => ` - ${t}`).join("\n") + `
|
|
9536
|
+
|
|
9537
|
+
Please select a valid tool from the list above.`
|
|
9538
|
+
} = config;
|
|
9539
|
+
return createMiddleware11({
|
|
9540
|
+
name: "UnknownToolHandlerMiddleware",
|
|
9541
|
+
/**
|
|
9542
|
+
* wrapModelCall hook
|
|
9543
|
+
*
|
|
9544
|
+
* The only place to access request.tools (all available tools).
|
|
9545
|
+
* Identifies unknown tools and stores error info in metadata.
|
|
9546
|
+
*
|
|
9547
|
+
* Key: Preserve all tool_calls in original AIMessage, including unknown ones.
|
|
9548
|
+
* This allows the model to see what it selected in the next round.
|
|
9549
|
+
*/
|
|
9550
|
+
wrapModelCall: async (request, handler) => {
|
|
9551
|
+
const availableTools = request.tools || [];
|
|
9552
|
+
const availableToolNames = availableTools.map((t) => t.name);
|
|
9553
|
+
const availableToolSet = new Set(availableToolNames);
|
|
9554
|
+
const aiResponse = await handler(request);
|
|
9555
|
+
if (!aiResponse.tool_calls || aiResponse.tool_calls.length === 0) {
|
|
9556
|
+
return aiResponse;
|
|
9557
|
+
}
|
|
9558
|
+
const unknownToolCalls = [];
|
|
9559
|
+
for (const toolCall of aiResponse.tool_calls) {
|
|
9560
|
+
if (!availableToolSet.has(toolCall.name)) {
|
|
9561
|
+
unknownToolCalls.push(toolCall);
|
|
9562
|
+
}
|
|
9563
|
+
}
|
|
9564
|
+
if (unknownToolCalls.length === 0) {
|
|
9565
|
+
return aiResponse;
|
|
9566
|
+
}
|
|
9567
|
+
if (strategy === "strict") {
|
|
9568
|
+
const unknownNames = unknownToolCalls.map((t) => t.name).join(", ");
|
|
9569
|
+
throw new Error(
|
|
9570
|
+
`Unknown tools detected: ${unknownNames}. Available tools: ${availableToolNames.join(", ")}`
|
|
9571
|
+
);
|
|
9572
|
+
}
|
|
9573
|
+
const unknownToolErrors = unknownToolCalls.map((toolCall) => ({
|
|
9574
|
+
toolName: toolCall.name,
|
|
9575
|
+
toolCallId: toolCall.id,
|
|
9576
|
+
errorMessage: errorMessageTemplate(toolCall.name, availableToolNames)
|
|
9577
|
+
}));
|
|
9578
|
+
const modifiedResponse = new AIMessage2({
|
|
9579
|
+
content: aiResponse.content,
|
|
9580
|
+
tool_calls: aiResponse.tool_calls,
|
|
9581
|
+
// Key: preserve all tool_calls, don't delete unknown
|
|
9582
|
+
response_metadata: {
|
|
9583
|
+
...aiResponse.response_metadata,
|
|
9584
|
+
_unknownToolErrors: unknownToolErrors
|
|
9585
|
+
}
|
|
9586
|
+
});
|
|
9587
|
+
if (aiResponse.id) {
|
|
9588
|
+
modifiedResponse.id = aiResponse.id;
|
|
9589
|
+
}
|
|
9590
|
+
return modifiedResponse;
|
|
9591
|
+
},
|
|
9592
|
+
/**
|
|
9593
|
+
* afterModel hook
|
|
9594
|
+
*
|
|
9595
|
+
* Processes unknown tool errors stored in metadata.
|
|
9596
|
+
* Generates error ToolMessages and jumps back to model.
|
|
9597
|
+
*
|
|
9598
|
+
* Key: Uses jumpTo: "model" to form agent loop.
|
|
9599
|
+
* Without jumpTo, the graph would end after ToolNode without returning to model.
|
|
9600
|
+
*/
|
|
9601
|
+
afterModel: {
|
|
9602
|
+
canJumpTo: ["model"],
|
|
9603
|
+
hook: async (state) => {
|
|
9604
|
+
const { messages } = state;
|
|
9605
|
+
if (!messages || messages.length === 0) {
|
|
9606
|
+
return;
|
|
9607
|
+
}
|
|
9608
|
+
const lastMessage = messages[messages.length - 1];
|
|
9609
|
+
if (!AIMessage2.isInstance(lastMessage)) {
|
|
9610
|
+
return;
|
|
9611
|
+
}
|
|
9612
|
+
const unknownToolErrors = lastMessage.response_metadata?._unknownToolErrors;
|
|
9613
|
+
if (!unknownToolErrors || !Array.isArray(unknownToolErrors) || unknownToolErrors.length === 0) {
|
|
9614
|
+
return;
|
|
9615
|
+
}
|
|
9616
|
+
const errorToolMessages = unknownToolErrors.map(
|
|
9617
|
+
(error) => new ToolMessage3({
|
|
9618
|
+
content: error.errorMessage,
|
|
9619
|
+
name: error.toolName,
|
|
9620
|
+
tool_call_id: error.toolCallId,
|
|
9621
|
+
status: "error"
|
|
9622
|
+
})
|
|
9623
|
+
);
|
|
9624
|
+
delete lastMessage.response_metadata._unknownToolErrors;
|
|
9625
|
+
return {
|
|
9626
|
+
messages: errorToolMessages,
|
|
9627
|
+
jumpTo: "model"
|
|
9628
|
+
};
|
|
9629
|
+
}
|
|
9630
|
+
}
|
|
9631
|
+
});
|
|
9632
|
+
}
|
|
9633
|
+
|
|
9634
|
+
// src/deep_agent_new/middleware/date.ts
|
|
9635
|
+
import { createMiddleware as createMiddleware12, tool as tool46 } from "langchain";
|
|
9636
|
+
import { z as z47 } from "zod";
|
|
9637
|
+
function formatCurrentDate(timezone = "UTC") {
|
|
9638
|
+
const now = /* @__PURE__ */ new Date();
|
|
9639
|
+
let validTimezone = timezone;
|
|
9640
|
+
try {
|
|
9641
|
+
Intl.DateTimeFormat(void 0, { timeZone: timezone });
|
|
9642
|
+
} catch {
|
|
9643
|
+
validTimezone = "UTC";
|
|
9644
|
+
}
|
|
9645
|
+
const dateFormatOptions = {
|
|
9646
|
+
timeZone: validTimezone,
|
|
9647
|
+
year: "numeric",
|
|
9648
|
+
month: "2-digit",
|
|
9649
|
+
day: "2-digit"
|
|
9650
|
+
};
|
|
9651
|
+
return new Intl.DateTimeFormat("en-US", dateFormatOptions).format(now);
|
|
9652
|
+
}
|
|
9653
|
+
function generateDateContext(timezone = "UTC") {
|
|
9654
|
+
const formattedDate = formatCurrentDate(timezone);
|
|
9655
|
+
if (timezone === "UTC") {
|
|
9656
|
+
return `Current Date: ${formattedDate}`;
|
|
9657
|
+
}
|
|
9658
|
+
const utcDate = formatCurrentDate("UTC");
|
|
9659
|
+
return `Current Date: ${formattedDate} (UTC: ${utcDate})`;
|
|
9660
|
+
}
|
|
9661
|
+
function createDateMiddleware(options = {}) {
|
|
9662
|
+
const timezone = options.timezone || "UTC";
|
|
9663
|
+
const dateContext = generateDateContext(timezone);
|
|
9664
|
+
return createMiddleware12({
|
|
9665
|
+
name: "DateMiddleware",
|
|
9666
|
+
tools: [
|
|
9667
|
+
tool46(
|
|
9668
|
+
async () => {
|
|
9669
|
+
const now = /* @__PURE__ */ new Date();
|
|
9670
|
+
let validTimezone = timezone;
|
|
9671
|
+
try {
|
|
9672
|
+
Intl.DateTimeFormat(void 0, { timeZone: timezone });
|
|
9673
|
+
} catch {
|
|
9674
|
+
validTimezone = "UTC";
|
|
9675
|
+
}
|
|
9676
|
+
const localTimeOptions = {
|
|
9677
|
+
timeZone: validTimezone,
|
|
9678
|
+
year: "numeric",
|
|
9679
|
+
month: "2-digit",
|
|
9680
|
+
day: "2-digit",
|
|
9681
|
+
hour: "2-digit",
|
|
9682
|
+
minute: "2-digit",
|
|
9683
|
+
second: "2-digit",
|
|
9684
|
+
hour12: false
|
|
9685
|
+
};
|
|
9686
|
+
const localTime = new Intl.DateTimeFormat("en-US", localTimeOptions).format(now);
|
|
9687
|
+
return JSON.stringify({
|
|
9688
|
+
local_time: `${localTime} (${validTimezone})`,
|
|
9689
|
+
iso_date: now.toISOString().split("T")[0],
|
|
9690
|
+
timestamp: now.toISOString(),
|
|
9691
|
+
timezone: validTimezone
|
|
9692
|
+
});
|
|
9693
|
+
},
|
|
9694
|
+
{
|
|
9695
|
+
name: "get_current_date_time",
|
|
9696
|
+
description: "Get the exact current date and time at the moment of invocation. Use this when the user asks about the current time (e.g., 'what time is it', '\u51E0\u70B9\u4E86', '\u73B0\u5728\u51E0\u70B9'), or when you need to know the precise time for scheduling, deadlines, or time-sensitive operations.",
|
|
9697
|
+
schema: z47.object({})
|
|
9698
|
+
}
|
|
9699
|
+
)
|
|
9700
|
+
],
|
|
9701
|
+
wrapModelCall: async (request, handler) => {
|
|
9702
|
+
const currentSystemPrompt = request.systemPrompt || "";
|
|
9703
|
+
const newSystemPrompt = currentSystemPrompt ? `${dateContext}
|
|
9704
|
+
|
|
9705
|
+
${currentSystemPrompt}` : dateContext;
|
|
9706
|
+
return handler({
|
|
9707
|
+
...request,
|
|
9708
|
+
systemPrompt: newSystemPrompt
|
|
9709
|
+
});
|
|
9710
|
+
}
|
|
9711
|
+
});
|
|
9712
|
+
}
|
|
9713
|
+
|
|
9714
|
+
// src/agent_lattice/builders/commonMiddleware.ts
|
|
9715
|
+
async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
|
|
9716
|
+
const middlewares = [];
|
|
9717
|
+
middlewares.push(createUnknownToolHandlerMiddleware());
|
|
9718
|
+
middlewares.push(createModelSelectorMiddleware());
|
|
9719
|
+
const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
|
|
9720
|
+
const clawConfig = middlewareConfigs.find((m) => m.type === "claw");
|
|
9721
|
+
const needsFilesystemBackend = filesystemConfig?.enabled || clawConfig?.enabled;
|
|
9722
|
+
if (needsFilesystemBackend && filesystemBackend) {
|
|
9723
|
+
if (!fsIsExised) {
|
|
9724
|
+
const options = { backend: filesystemBackend };
|
|
9725
|
+
middlewares.push(createFilesystemMiddleware(options));
|
|
9726
|
+
}
|
|
9727
|
+
}
|
|
9728
|
+
for (const config of middlewareConfigs) {
|
|
9729
|
+
if (!config.enabled || config.type === "filesystem") continue;
|
|
9730
|
+
switch (config.type) {
|
|
9731
|
+
case "code_eval":
|
|
9732
|
+
middlewares.push(createCodeEvalMiddleware(config.config));
|
|
9733
|
+
break;
|
|
9734
|
+
case "browser":
|
|
9735
|
+
middlewares.push(createBrowserMiddleware(config.config));
|
|
9736
|
+
break;
|
|
9737
|
+
case "sql":
|
|
9738
|
+
{
|
|
9739
|
+
const sqlConfig = config.config;
|
|
9740
|
+
if (sqlConfig.databaseKeys && sqlConfig.databaseKeys.length > 0) {
|
|
9741
|
+
const databaseConfigs = global.__DATABASE_CONFIGS__ || [];
|
|
9742
|
+
const descriptions = {};
|
|
9743
|
+
for (const db of databaseConfigs) {
|
|
9744
|
+
if (db.key && sqlConfig.databaseKeys.includes(db.key)) {
|
|
9745
|
+
descriptions[db.key] = db.description || db.name || "";
|
|
9746
|
+
}
|
|
9747
|
+
}
|
|
9748
|
+
middlewares.push(createSqlMiddleware({
|
|
9749
|
+
databaseKeys: sqlConfig.databaseKeys,
|
|
9750
|
+
databaseDescriptions: descriptions
|
|
9751
|
+
}));
|
|
9752
|
+
}
|
|
9753
|
+
}
|
|
9754
|
+
break;
|
|
9755
|
+
case "skill":
|
|
9756
|
+
middlewares.push(createSkillMiddleware(config.config));
|
|
9757
|
+
break;
|
|
9758
|
+
case "metrics":
|
|
9759
|
+
{
|
|
9760
|
+
const metricsConfig = config.config;
|
|
9761
|
+
if (metricsConfig.connectAll || metricsConfig.serverKeys && metricsConfig.serverKeys.length > 0) {
|
|
9762
|
+
middlewares.push(createMetricsMiddleware(metricsConfig));
|
|
9763
|
+
}
|
|
9764
|
+
}
|
|
9765
|
+
break;
|
|
9766
|
+
case "ask_user_to_clarify":
|
|
9767
|
+
middlewares.push(createAskUserClarifyMiddleware());
|
|
9768
|
+
break;
|
|
9769
|
+
case "widget":
|
|
9770
|
+
middlewares.push(createWidgetMiddleware());
|
|
9771
|
+
break;
|
|
9772
|
+
case "claw":
|
|
9773
|
+
if (filesystemBackend) {
|
|
9774
|
+
const clawMiddlewareConfig = config.config;
|
|
9775
|
+
middlewares.push(createClawMiddleware({
|
|
9776
|
+
backend: filesystemBackend,
|
|
9777
|
+
injectBootstrapFiles: clawMiddlewareConfig.injectBootstrapFiles ?? true,
|
|
9778
|
+
bootstrapFiles: clawMiddlewareConfig.bootstrapFiles ?? {}
|
|
9779
|
+
}));
|
|
9780
|
+
} else {
|
|
9781
|
+
console.warn("[claw middleware] Filesystem backend not available. Claw middleware requires filesystem backend to function.");
|
|
9782
|
+
}
|
|
9783
|
+
break;
|
|
9784
|
+
case "date":
|
|
9785
|
+
middlewares.push(createDateMiddleware(config.config));
|
|
9786
|
+
break;
|
|
9787
|
+
}
|
|
9788
|
+
}
|
|
9789
|
+
return middlewares;
|
|
9790
|
+
}
|
|
9791
|
+
|
|
9792
|
+
// src/deep_agent_new/backends/sandboxFiles.ts
|
|
9793
|
+
import { SandboxClient as SandboxClient2 } from "@agent-infra/sandbox";
|
|
9794
|
+
import * as path3 from "path";
|
|
9795
|
+
var SandboxFilesystem = class {
|
|
9796
|
+
/**
|
|
9797
|
+
* Create a new SandboxFilesystem instance.
|
|
9798
|
+
*
|
|
9799
|
+
* @param options - Configuration options
|
|
9800
|
+
* @param options.baseURL - Base URL of the sandbox service (default: 'http://localhost:8080')
|
|
9801
|
+
* @param options.maxFileSizeMb - Maximum file size in MB (default: 10)
|
|
9802
|
+
* @param options.sandboxInstance - Optional Sandbox instance (if provided, baseURL is ignored)
|
|
9803
|
+
*/
|
|
9804
|
+
constructor(options = {}) {
|
|
9805
|
+
const {
|
|
9806
|
+
baseURL = "http://localhost:8080",
|
|
9807
|
+
workingDirectory = "/",
|
|
9808
|
+
maxFileSizeMb = 10,
|
|
9809
|
+
sandboxInstance
|
|
9810
|
+
} = options;
|
|
9811
|
+
this.sandbox = sandboxInstance || new SandboxClient2({ baseUrl: baseURL, environment: "" });
|
|
9812
|
+
this.sandbox.mcp.listMcpServers().then((servers) => {
|
|
9813
|
+
});
|
|
9814
|
+
this.sandbox.mcp.listMcpTools("browser").then((tools) => {
|
|
9815
|
+
});
|
|
9816
|
+
this.baseURL = baseURL;
|
|
9817
|
+
this.maxFileSizeBytes = maxFileSizeMb * 1024 * 1024;
|
|
9818
|
+
this.workingDirectory = workingDirectory;
|
|
9819
|
+
this.homeDir = "/home/gem";
|
|
9820
|
+
}
|
|
9821
|
+
resolvePath(virtualPath) {
|
|
9822
|
+
return path3.join(this.homeDir, this.workingDirectory, virtualPath);
|
|
9823
|
+
}
|
|
9824
|
+
/**
|
|
9825
|
+
* Convert a real filesystem path to a virtual path.
|
|
9826
|
+
*
|
|
9827
|
+
* @param realPath - Real filesystem path
|
|
9828
|
+
* @returns Virtual path starting with /
|
|
9829
|
+
*/
|
|
9830
|
+
toVirtualPath(realPath) {
|
|
9831
|
+
const rootPath = path3.join(this.homeDir, this.workingDirectory);
|
|
9832
|
+
const relative4 = path3.relative(rootPath, realPath);
|
|
9833
|
+
const normalized = relative4.split(path3.sep).join("/");
|
|
9834
|
+
return "/" + normalized;
|
|
9835
|
+
}
|
|
9836
|
+
/**
|
|
9837
|
+
* List files and directories in the specified directory (non-recursive).
|
|
9838
|
+
*
|
|
9839
|
+
* @param dirPath - Virtual directory path (must start with /)
|
|
9840
|
+
* @returns List of FileInfo objects for files and directories directly in the directory.
|
|
9841
|
+
* Directories have a trailing / in their path and is_dir=true.
|
|
9842
|
+
*/
|
|
9843
|
+
async lsInfo(dirPath) {
|
|
9844
|
+
try {
|
|
9845
|
+
const resolvedPath = this.resolvePath(dirPath);
|
|
9846
|
+
const result = await this.sandbox.file.listPath({
|
|
9847
|
+
path: resolvedPath,
|
|
9848
|
+
recursive: false,
|
|
9849
|
+
show_hidden: false,
|
|
9850
|
+
max_depth: 0,
|
|
9851
|
+
include_size: false,
|
|
9852
|
+
include_permissions: false,
|
|
9853
|
+
sort_by: "name",
|
|
9854
|
+
sort_desc: false
|
|
9855
|
+
});
|
|
9856
|
+
if (!result.ok) {
|
|
9857
|
+
throw result.error;
|
|
9858
|
+
}
|
|
9859
|
+
const files = result.body?.data?.files?.map((file) => ({
|
|
9860
|
+
path: this.toVirtualPath(file.path),
|
|
9861
|
+
is_dir: file.is_directory,
|
|
9862
|
+
size: file.size,
|
|
9863
|
+
modified_at: file.modified_time
|
|
9864
|
+
})) || [];
|
|
9865
|
+
return files;
|
|
9866
|
+
} catch (e) {
|
|
9867
|
+
console.error(`Error listing files in ${dirPath}:`, e);
|
|
9868
|
+
return [];
|
|
9869
|
+
}
|
|
9870
|
+
}
|
|
9871
|
+
/**
|
|
9872
|
+
* Read file content with line numbers.
|
|
9873
|
+
*
|
|
9874
|
+
* @param filePath - Virtual file path (must start with /)
|
|
9875
|
+
* @param offset - Line offset to start reading from (0-indexed)
|
|
9876
|
+
* @param limit - Maximum number of lines to read
|
|
9877
|
+
* @returns Formatted file content with line numbers, or error message
|
|
9878
|
+
*/
|
|
9879
|
+
async read(filePath, offset = 0, limit = 1e4) {
|
|
9880
|
+
try {
|
|
9881
|
+
const resolvedPath = this.resolvePath(filePath);
|
|
9882
|
+
let content;
|
|
9883
|
+
const result = await this.sandbox.file.readFile({
|
|
9884
|
+
file: resolvedPath,
|
|
9885
|
+
start_line: offset,
|
|
9886
|
+
end_line: limit
|
|
9887
|
+
});
|
|
9888
|
+
if (!result.ok) {
|
|
9889
|
+
throw result.error;
|
|
9890
|
+
}
|
|
9891
|
+
content = result.body?.data?.content || "";
|
|
9892
|
+
return content;
|
|
9893
|
+
} catch (e) {
|
|
9894
|
+
return `Error: File '${filePath}' not found`;
|
|
9895
|
+
}
|
|
9896
|
+
}
|
|
9897
|
+
/**
|
|
9898
|
+
* Read file content as raw FileData.
|
|
9899
|
+
*
|
|
9900
|
+
* @param filePath - Virtual file path (must start with /)
|
|
9901
|
+
* @returns Raw file content as FileData
|
|
9902
|
+
*/
|
|
9903
|
+
async readRaw(filePath) {
|
|
9904
|
+
try {
|
|
9905
|
+
const content = await this.read(filePath);
|
|
9906
|
+
return {
|
|
9907
|
+
content: content.split("\n"),
|
|
9908
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9909
|
+
modified_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
9910
|
+
};
|
|
9911
|
+
} catch (e) {
|
|
9912
|
+
throw new Error(`Error reading file '${filePath}': ${e.message}`);
|
|
9913
|
+
}
|
|
9914
|
+
}
|
|
9915
|
+
/**
|
|
9916
|
+
* Create a new file with content.
|
|
9917
|
+
* Returns WriteResult. External storage sets filesUpdate=null.
|
|
9918
|
+
*
|
|
9919
|
+
* @param filePath - Virtual file path (must start with /)
|
|
9920
|
+
* @param content - File content as string
|
|
9921
|
+
* @returns WriteResult with error populated on failure
|
|
9922
|
+
*/
|
|
9923
|
+
async write(filePath, content) {
|
|
9924
|
+
try {
|
|
9925
|
+
const resolvedPath = this.resolvePath(filePath);
|
|
9926
|
+
const result = await this.sandbox.file.writeFile({
|
|
9927
|
+
file: resolvedPath,
|
|
9928
|
+
content,
|
|
9929
|
+
"encoding": "utf-8",
|
|
9930
|
+
"append": false
|
|
9931
|
+
// sudo: true
|
|
9932
|
+
});
|
|
9933
|
+
if (!result.ok) {
|
|
9934
|
+
console.error(result.error);
|
|
9935
|
+
throw result.error;
|
|
9936
|
+
}
|
|
9937
|
+
return {
|
|
9938
|
+
path: filePath,
|
|
9939
|
+
filesUpdate: {
|
|
9940
|
+
[filePath]: {
|
|
9941
|
+
content: content.split("\n"),
|
|
9942
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9943
|
+
modified_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
9944
|
+
}
|
|
9945
|
+
}
|
|
9946
|
+
};
|
|
9947
|
+
} catch (e) {
|
|
9948
|
+
throw new Error(`Error writing file '${filePath}': ${e.message}`);
|
|
9949
|
+
}
|
|
9950
|
+
}
|
|
9951
|
+
/**
|
|
9952
|
+
* Edit a file by replacing string occurrences.
|
|
9953
|
+
* Returns EditResult. External storage sets filesUpdate=null.
|
|
9954
|
+
*
|
|
9955
|
+
* @param filePath - Virtual file path (must start with /)
|
|
9956
|
+
* @param oldString - String to find and replace
|
|
9957
|
+
* @param newString - Replacement string
|
|
9958
|
+
* @param replaceAll - If true, replace all occurrences (default: false)
|
|
9959
|
+
* @returns EditResult with error, path, filesUpdate, and occurrences
|
|
9960
|
+
*/
|
|
9961
|
+
async edit(filePath, oldString, newString, replaceAll = false) {
|
|
9962
|
+
try {
|
|
9963
|
+
const resolvedPath = this.resolvePath(filePath);
|
|
9964
|
+
const result = await this.sandbox.file.strReplaceEditor({
|
|
9965
|
+
command: "str_replace",
|
|
9966
|
+
path: resolvedPath,
|
|
9967
|
+
old_str: oldString,
|
|
9968
|
+
new_str: newString,
|
|
9969
|
+
replace_mode: replaceAll ? "ALL" : "FIRST"
|
|
9970
|
+
});
|
|
9971
|
+
if (!result.ok) {
|
|
9972
|
+
throw result.error;
|
|
9973
|
+
}
|
|
9974
|
+
return {
|
|
9975
|
+
path: filePath,
|
|
9976
|
+
filesUpdate: null
|
|
9977
|
+
};
|
|
9978
|
+
} catch (e) {
|
|
9979
|
+
throw new Error(`Error editing file '${filePath}': ${e.message}`);
|
|
9980
|
+
}
|
|
9981
|
+
}
|
|
9982
|
+
/**
|
|
9983
|
+
* Structured search results or error string for invalid input.
|
|
9984
|
+
*
|
|
9985
|
+
* Searches file contents for a regex pattern within the sandbox.
|
|
9986
|
+
*
|
|
9987
|
+
* @param pattern - Regex pattern to search for
|
|
9988
|
+
* @param searchPath - Base path to search from (default: "/")
|
|
9989
|
+
* @param glob - Optional glob pattern to filter files (e.g., "*.py")
|
|
9990
|
+
* @returns List of GrepMatch objects or error string for invalid regex
|
|
9991
|
+
*/
|
|
9992
|
+
async grepRaw(pattern, searchPath = "/", glob = null) {
|
|
9993
|
+
let baseFull;
|
|
9994
|
+
baseFull = this.resolvePath(searchPath || "/");
|
|
9995
|
+
const result = await this.sandbox.file.findFiles({
|
|
9996
|
+
path: baseFull,
|
|
9997
|
+
glob: glob || "**/*"
|
|
9998
|
+
});
|
|
9999
|
+
if (!result.ok) {
|
|
10000
|
+
throw result.error;
|
|
10001
|
+
}
|
|
10002
|
+
const filePaths = result.body?.data?.files || [];
|
|
10003
|
+
const matches = [];
|
|
10004
|
+
for (const absolutePath of filePaths) {
|
|
10005
|
+
const fileData = await this.sandbox.file.searchInFile({
|
|
10006
|
+
file: absolutePath,
|
|
10007
|
+
regex: pattern
|
|
10008
|
+
});
|
|
10009
|
+
if (!fileData.ok) {
|
|
10010
|
+
continue;
|
|
10011
|
+
}
|
|
10012
|
+
const matchesData = fileData.body?.data?.matches || [];
|
|
10013
|
+
const matchLines = fileData.body?.data?.line_numbers || [];
|
|
10014
|
+
matchesData.forEach((match, index) => {
|
|
10015
|
+
matches.push({
|
|
10016
|
+
path: this.toVirtualPath(absolutePath),
|
|
10017
|
+
line: matchLines[index],
|
|
10018
|
+
text: match
|
|
10019
|
+
});
|
|
10020
|
+
});
|
|
10021
|
+
}
|
|
10022
|
+
return matches;
|
|
10023
|
+
}
|
|
10024
|
+
/**
|
|
10025
|
+
* Structured glob matching returning FileInfo objects.
|
|
10026
|
+
*
|
|
10027
|
+
* @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
|
|
10028
|
+
* @param searchPath - Base path to search from (default: "/")
|
|
10029
|
+
* @returns List of FileInfo objects matching the pattern
|
|
10030
|
+
*/
|
|
10031
|
+
async globInfo(pattern, searchPath = "/") {
|
|
10032
|
+
if (pattern.startsWith("/")) {
|
|
10033
|
+
pattern = pattern.substring(1);
|
|
10034
|
+
}
|
|
10035
|
+
const resolvedSearchPath = this.resolvePath(searchPath);
|
|
10036
|
+
const result = await this.sandbox.file.findFiles({
|
|
10037
|
+
path: resolvedSearchPath,
|
|
10038
|
+
glob: pattern || "**/*"
|
|
10039
|
+
});
|
|
10040
|
+
if (!result.ok) {
|
|
10041
|
+
throw result.error;
|
|
10042
|
+
}
|
|
10043
|
+
const results = [];
|
|
10044
|
+
for (const filePath of result.body?.data?.files || []) {
|
|
10045
|
+
const fileInfo = await this.sandbox.file.listPath({
|
|
10046
|
+
path: filePath,
|
|
10047
|
+
recursive: false,
|
|
10048
|
+
show_hidden: false,
|
|
10049
|
+
max_depth: 1,
|
|
10050
|
+
include_size: false,
|
|
10051
|
+
include_permissions: false
|
|
10052
|
+
});
|
|
10053
|
+
if (!fileInfo.ok) {
|
|
10054
|
+
continue;
|
|
10055
|
+
}
|
|
10056
|
+
results.push({
|
|
10057
|
+
path: this.toVirtualPath(filePath),
|
|
10058
|
+
is_dir: false,
|
|
10059
|
+
size: fileInfo.body?.data?.files?.[0]?.size,
|
|
10060
|
+
modified_at: fileInfo.body?.data?.files?.[0]?.modified_time
|
|
10061
|
+
});
|
|
10062
|
+
}
|
|
10063
|
+
return results;
|
|
10064
|
+
}
|
|
10065
|
+
};
|
|
10066
|
+
|
|
10067
|
+
// src/deep_agent_new/backends/composite.ts
|
|
10068
|
+
var CompositeBackend = class {
|
|
10069
|
+
constructor(defaultBackend, routes) {
|
|
10070
|
+
this.default = defaultBackend;
|
|
10071
|
+
this.routes = routes;
|
|
10072
|
+
this.sortedRoutes = Object.entries(routes).sort(
|
|
10073
|
+
(a, b) => b[0].length - a[0].length
|
|
10074
|
+
);
|
|
10075
|
+
}
|
|
10076
|
+
/**
|
|
10077
|
+
* Determine which backend handles this key and strip prefix.
|
|
10078
|
+
*
|
|
10079
|
+
* @param key - Original file path
|
|
10080
|
+
* @returns Tuple of [backend, stripped_key] where stripped_key has the route
|
|
10081
|
+
* prefix removed (but keeps leading slash).
|
|
10082
|
+
*/
|
|
10083
|
+
getBackendAndKey(key) {
|
|
10084
|
+
for (const [prefix, backend] of this.sortedRoutes) {
|
|
10085
|
+
if (key.startsWith(prefix)) {
|
|
10086
|
+
const suffix = key.substring(prefix.length);
|
|
10087
|
+
const strippedKey = suffix ? "/" + suffix : "/";
|
|
10088
|
+
return [backend, strippedKey];
|
|
10089
|
+
}
|
|
10090
|
+
}
|
|
10091
|
+
return [this.default, key];
|
|
10092
|
+
}
|
|
10093
|
+
/**
|
|
10094
|
+
* List files and directories in the specified directory (non-recursive).
|
|
10095
|
+
*
|
|
10096
|
+
* @param path - Absolute path to directory
|
|
10097
|
+
* @returns List of FileInfo objects with route prefixes added, for files and directories
|
|
10098
|
+
* directly in the directory. Directories have a trailing / in their path and is_dir=true.
|
|
10099
|
+
*/
|
|
10100
|
+
async lsInfo(path5) {
|
|
10101
|
+
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
10102
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
10103
|
+
const suffix = path5.substring(routePrefix.length);
|
|
10104
|
+
const searchPath = suffix ? "/" + suffix : "/";
|
|
10105
|
+
const infos = await backend.lsInfo(searchPath);
|
|
10106
|
+
const prefixed = [];
|
|
10107
|
+
for (const fi of infos) {
|
|
10108
|
+
prefixed.push({
|
|
10109
|
+
...fi,
|
|
10110
|
+
path: routePrefix.slice(0, -1) + fi.path
|
|
10111
|
+
});
|
|
10112
|
+
}
|
|
10113
|
+
return prefixed;
|
|
10114
|
+
}
|
|
10115
|
+
}
|
|
10116
|
+
if (path5 === "/") {
|
|
10117
|
+
const results = [];
|
|
10118
|
+
const defaultInfos = await this.default.lsInfo(path5);
|
|
10119
|
+
results.push(...defaultInfos);
|
|
10120
|
+
for (const [routePrefix] of this.sortedRoutes) {
|
|
10121
|
+
results.push({
|
|
10122
|
+
path: routePrefix,
|
|
10123
|
+
is_dir: true,
|
|
10124
|
+
size: 0,
|
|
10125
|
+
modified_at: ""
|
|
10126
|
+
});
|
|
10127
|
+
}
|
|
10128
|
+
results.sort((a, b) => a.path.localeCompare(b.path));
|
|
10129
|
+
return results;
|
|
10130
|
+
}
|
|
10131
|
+
return await this.default.lsInfo(path5);
|
|
10132
|
+
}
|
|
10133
|
+
/**
|
|
10134
|
+
* Read file content, routing to appropriate backend.
|
|
10135
|
+
*
|
|
10136
|
+
* @param filePath - Absolute file path
|
|
10137
|
+
* @param offset - Line offset to start reading from (0-indexed)
|
|
10138
|
+
* @param limit - Maximum number of lines to read
|
|
10139
|
+
* @returns Formatted file content with line numbers, or error message
|
|
10140
|
+
*/
|
|
10141
|
+
async read(filePath, offset = 0, limit = 2e3) {
|
|
10142
|
+
const [backend, strippedKey] = this.getBackendAndKey(filePath);
|
|
10143
|
+
return await backend.read(strippedKey, offset, limit);
|
|
10144
|
+
}
|
|
10145
|
+
/**
|
|
10146
|
+
* Read file content as raw FileData.
|
|
10147
|
+
*
|
|
10148
|
+
* @param filePath - Absolute file path
|
|
10149
|
+
* @returns Raw file content as FileData
|
|
10150
|
+
*/
|
|
10151
|
+
async readRaw(filePath) {
|
|
10152
|
+
const [backend, strippedKey] = this.getBackendAndKey(filePath);
|
|
10153
|
+
return await backend.readRaw(strippedKey);
|
|
10154
|
+
}
|
|
10155
|
+
/**
|
|
10156
|
+
* Structured search results or error string for invalid input.
|
|
10157
|
+
*/
|
|
10158
|
+
async grepRaw(pattern, path5 = "/", glob = null) {
|
|
10159
|
+
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
10160
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
10161
|
+
const searchPath = path5.substring(routePrefix.length - 1);
|
|
10162
|
+
const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
|
|
10163
|
+
if (typeof raw === "string") {
|
|
10164
|
+
return raw;
|
|
10165
|
+
}
|
|
10166
|
+
return raw.map((m) => ({
|
|
10167
|
+
...m,
|
|
10168
|
+
path: routePrefix.slice(0, -1) + m.path
|
|
10169
|
+
}));
|
|
10170
|
+
}
|
|
10171
|
+
}
|
|
10172
|
+
const allMatches = [];
|
|
10173
|
+
const rawDefault = await this.default.grepRaw(pattern, path5, glob);
|
|
10174
|
+
if (typeof rawDefault === "string") {
|
|
10175
|
+
return rawDefault;
|
|
10176
|
+
}
|
|
10177
|
+
allMatches.push(...rawDefault);
|
|
10178
|
+
for (const [routePrefix, backend] of Object.entries(this.routes)) {
|
|
10179
|
+
const raw = await backend.grepRaw(pattern, "/", glob);
|
|
10180
|
+
if (typeof raw === "string") {
|
|
10181
|
+
return raw;
|
|
10182
|
+
}
|
|
10183
|
+
allMatches.push(
|
|
10184
|
+
...raw.map((m) => ({
|
|
10185
|
+
...m,
|
|
10186
|
+
path: routePrefix.slice(0, -1) + m.path
|
|
10187
|
+
}))
|
|
10188
|
+
);
|
|
10189
|
+
}
|
|
10190
|
+
return allMatches;
|
|
10191
|
+
}
|
|
10192
|
+
/**
|
|
10193
|
+
* Structured glob matching returning FileInfo objects.
|
|
10194
|
+
*/
|
|
10195
|
+
async globInfo(pattern, path5 = "/") {
|
|
10196
|
+
const results = [];
|
|
10197
|
+
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
10198
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
10199
|
+
const searchPath = path5.substring(routePrefix.length - 1);
|
|
10200
|
+
const infos = await backend.globInfo(pattern, searchPath || "/");
|
|
10201
|
+
return infos.map((fi) => ({
|
|
10202
|
+
...fi,
|
|
10203
|
+
path: routePrefix.slice(0, -1) + fi.path
|
|
10204
|
+
}));
|
|
10205
|
+
}
|
|
10206
|
+
}
|
|
10207
|
+
const defaultInfos = await this.default.globInfo(pattern, path5);
|
|
10208
|
+
results.push(...defaultInfos);
|
|
10209
|
+
for (const [routePrefix, backend] of Object.entries(this.routes)) {
|
|
10210
|
+
const infos = await backend.globInfo(pattern, "/");
|
|
10211
|
+
results.push(
|
|
10212
|
+
...infos.map((fi) => ({
|
|
10213
|
+
...fi,
|
|
10214
|
+
path: routePrefix.slice(0, -1) + fi.path
|
|
10215
|
+
}))
|
|
10216
|
+
);
|
|
10217
|
+
}
|
|
10218
|
+
results.sort((a, b) => a.path.localeCompare(b.path));
|
|
10219
|
+
return results;
|
|
10220
|
+
}
|
|
10221
|
+
/**
|
|
10222
|
+
* Create a new file, routing to appropriate backend.
|
|
10223
|
+
*
|
|
10224
|
+
* @param filePath - Absolute file path
|
|
10225
|
+
* @param content - File content as string
|
|
10226
|
+
* @returns WriteResult with path or error
|
|
10227
|
+
*/
|
|
10228
|
+
async write(filePath, content) {
|
|
10229
|
+
const [backend, strippedKey] = this.getBackendAndKey(filePath);
|
|
10230
|
+
return await backend.write(strippedKey, content);
|
|
10231
|
+
}
|
|
10232
|
+
/**
|
|
10233
|
+
* Edit a file, routing to appropriate backend.
|
|
10234
|
+
*
|
|
10235
|
+
* @param filePath - Absolute file path
|
|
10236
|
+
* @param oldString - String to find and replace
|
|
10237
|
+
* @param newString - Replacement string
|
|
10238
|
+
* @param replaceAll - If true, replace all occurrences
|
|
10239
|
+
* @returns EditResult with path, occurrences, or error
|
|
10240
|
+
*/
|
|
10241
|
+
async edit(filePath, oldString, newString, replaceAll = false) {
|
|
10242
|
+
const [backend, strippedKey] = this.getBackendAndKey(filePath);
|
|
10243
|
+
return await backend.edit(strippedKey, oldString, newString, replaceAll);
|
|
10244
|
+
}
|
|
10245
|
+
};
|
|
9772
10246
|
|
|
9773
|
-
// src/agent_lattice/builders/
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
|
|
10247
|
+
// src/agent_lattice/builders/filesystemBackend.ts
|
|
10248
|
+
function createFilesystemBackendFactory(middlewareConfigs, defualtRootLevel = "project", routesLevelConfig = {
|
|
10249
|
+
"/agent/": "agent"
|
|
10250
|
+
//默认配置 agent目录就是agent级别的
|
|
10251
|
+
}) {
|
|
9777
10252
|
const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
|
|
9778
|
-
if (filesystemConfig
|
|
9779
|
-
|
|
9780
|
-
middlewares.push(createFilesystemMiddleware(options));
|
|
10253
|
+
if (!filesystemConfig || !filesystemConfig.enabled) {
|
|
10254
|
+
return void 0;
|
|
9781
10255
|
}
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
break;
|
|
9791
|
-
case "sql":
|
|
9792
|
-
{
|
|
9793
|
-
const sqlConfig = config.config;
|
|
9794
|
-
if (sqlConfig.databaseKeys && sqlConfig.databaseKeys.length > 0) {
|
|
9795
|
-
const databaseConfigs = global.__DATABASE_CONFIGS__ || [];
|
|
9796
|
-
const descriptions = {};
|
|
9797
|
-
for (const db of databaseConfigs) {
|
|
9798
|
-
if (db.key && sqlConfig.databaseKeys.includes(db.key)) {
|
|
9799
|
-
descriptions[db.key] = db.description || db.name || "";
|
|
9800
|
-
}
|
|
9801
|
-
}
|
|
9802
|
-
middlewares.push(createSqlMiddleware({
|
|
9803
|
-
databaseKeys: sqlConfig.databaseKeys,
|
|
9804
|
-
databaseDescriptions: descriptions
|
|
9805
|
-
}));
|
|
9806
|
-
}
|
|
9807
|
-
}
|
|
9808
|
-
break;
|
|
9809
|
-
case "skill":
|
|
9810
|
-
middlewares.push(createSkillMiddleware(config.config));
|
|
9811
|
-
break;
|
|
9812
|
-
case "metrics":
|
|
9813
|
-
{
|
|
9814
|
-
const metricsConfig = config.config;
|
|
9815
|
-
if (metricsConfig.connectAll || metricsConfig.serverKeys && metricsConfig.serverKeys.length > 0) {
|
|
9816
|
-
middlewares.push(createMetricsMiddleware(metricsConfig));
|
|
9817
|
-
}
|
|
9818
|
-
}
|
|
9819
|
-
break;
|
|
9820
|
-
case "ask_user_to_clarify":
|
|
9821
|
-
middlewares.push(createAskUserClarifyMiddleware());
|
|
9822
|
-
break;
|
|
9823
|
-
case "widget":
|
|
9824
|
-
middlewares.push(createWidgetMiddleware());
|
|
9825
|
-
break;
|
|
9826
|
-
case "claw":
|
|
9827
|
-
if (filesystemBackend) {
|
|
9828
|
-
const clawConfig = config.config;
|
|
9829
|
-
middlewares.push(createClawMiddleware({
|
|
9830
|
-
backend: filesystemBackend,
|
|
9831
|
-
injectBootstrapFiles: clawConfig.injectBootstrapFiles ?? true,
|
|
9832
|
-
bootstrapFiles: clawConfig.bootstrapFiles ?? {}
|
|
9833
|
-
}));
|
|
9834
|
-
}
|
|
9835
|
-
break;
|
|
10256
|
+
const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
|
|
10257
|
+
return async (stateAndStore) => {
|
|
10258
|
+
const { tenantId, workspaceId, projectId, assistant_id } = stateAndStore;
|
|
10259
|
+
let sandboxName = "global";
|
|
10260
|
+
if (isolatedLevel === "agent") {
|
|
10261
|
+
sandboxName = "agent";
|
|
10262
|
+
} else if (isolatedLevel === "thread") {
|
|
10263
|
+
sandboxName = "thread";
|
|
9836
10264
|
}
|
|
9837
|
-
|
|
9838
|
-
|
|
10265
|
+
const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
|
|
10266
|
+
if (!sandboxManager) {
|
|
10267
|
+
throw new Error("Sandbox manager not found");
|
|
10268
|
+
}
|
|
10269
|
+
const getWS = (rootLevel) => {
|
|
10270
|
+
let workingDirectory = `/tenants/${tenantId}`;
|
|
10271
|
+
if (assistant_id && rootLevel === "agent") {
|
|
10272
|
+
workingDirectory = `/tenants/${tenantId}/agents/${assistant_id}`;
|
|
10273
|
+
} else if (workspaceId && projectId && rootLevel === "project") {
|
|
10274
|
+
workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
|
|
10275
|
+
}
|
|
10276
|
+
return workingDirectory;
|
|
10277
|
+
};
|
|
10278
|
+
const sandboxInstance = await sandboxManager.createSandbox(sandboxName);
|
|
10279
|
+
const sandboxfs = new SandboxFilesystem({
|
|
10280
|
+
sandboxInstance,
|
|
10281
|
+
workingDirectory: getWS(defualtRootLevel)
|
|
10282
|
+
});
|
|
10283
|
+
const routers = Object.keys(routesLevelConfig).reduce((pre, curr) => ({
|
|
10284
|
+
...pre,
|
|
10285
|
+
[curr]: new SandboxFilesystem({
|
|
10286
|
+
sandboxInstance,
|
|
10287
|
+
workingDirectory: getWS(routesLevelConfig[curr])
|
|
10288
|
+
})
|
|
10289
|
+
}), {});
|
|
10290
|
+
const compositeBackend = new CompositeBackend(sandboxfs, {
|
|
10291
|
+
...routers
|
|
10292
|
+
});
|
|
10293
|
+
return compositeBackend;
|
|
10294
|
+
};
|
|
9839
10295
|
}
|
|
9840
10296
|
|
|
9841
10297
|
// src/agent_lattice/builders/ReActAgentGraphBuilder.ts
|
|
9842
10298
|
var ReActAgentGraphBuilder = class {
|
|
9843
|
-
createFilesystemBackendFactory(middlewareConfigs, agentLattice) {
|
|
9844
|
-
const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
|
|
9845
|
-
if (!filesystemConfig || !filesystemConfig.enabled) {
|
|
9846
|
-
return void 0;
|
|
9847
|
-
}
|
|
9848
|
-
const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
|
|
9849
|
-
const agentTenantId = agentLattice.config.tenantId;
|
|
9850
|
-
return async (stateAndStore) => {
|
|
9851
|
-
const { tenantId: runtimeTenantId, workspaceId, projectId } = stateAndStore;
|
|
9852
|
-
const tenantId = runtimeTenantId || agentTenantId;
|
|
9853
|
-
let sandboxName = "global";
|
|
9854
|
-
if (isolatedLevel === "agent") {
|
|
9855
|
-
sandboxName = "agent";
|
|
9856
|
-
} else if (isolatedLevel === "thread") {
|
|
9857
|
-
sandboxName = "thread";
|
|
9858
|
-
}
|
|
9859
|
-
const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
|
|
9860
|
-
if (!sandboxManager) {
|
|
9861
|
-
throw new Error("Sandbox manager not found");
|
|
9862
|
-
}
|
|
9863
|
-
let workingDirectory = "/";
|
|
9864
|
-
if (workspaceId && projectId) {
|
|
9865
|
-
if (tenantId) {
|
|
9866
|
-
workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
|
|
9867
|
-
} else {
|
|
9868
|
-
workingDirectory = `/${workspaceId}/${projectId}`;
|
|
9869
|
-
}
|
|
9870
|
-
}
|
|
9871
|
-
return new SandboxFilesystem({
|
|
9872
|
-
sandboxInstance: await sandboxManager.createSandbox(sandboxName),
|
|
9873
|
-
workingDirectory
|
|
9874
|
-
});
|
|
9875
|
-
};
|
|
9876
|
-
}
|
|
9877
10299
|
async createMiddlewares(middlewareConfigs) {
|
|
9878
10300
|
return await createCommonMiddlewares(middlewareConfigs);
|
|
9879
10301
|
}
|
|
@@ -9886,12 +10308,12 @@ var ReActAgentGraphBuilder = class {
|
|
|
9886
10308
|
*/
|
|
9887
10309
|
async build(agentLattice, params) {
|
|
9888
10310
|
const tools = params.tools.map((t) => {
|
|
9889
|
-
const
|
|
9890
|
-
return
|
|
9891
|
-
}).filter((
|
|
10311
|
+
const tool51 = getToolClient(t.key);
|
|
10312
|
+
return tool51;
|
|
10313
|
+
}).filter((tool51) => tool51 !== void 0);
|
|
9892
10314
|
const stateSchema2 = createReactAgentSchema(params.stateSchema);
|
|
9893
10315
|
const middlewareConfigs = params.middleware || [];
|
|
9894
|
-
const filesystemBackend =
|
|
10316
|
+
const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
|
|
9895
10317
|
const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend);
|
|
9896
10318
|
return createAgent({
|
|
9897
10319
|
model: params.model,
|
|
@@ -9914,12 +10336,12 @@ import {
|
|
|
9914
10336
|
} from "langchain";
|
|
9915
10337
|
|
|
9916
10338
|
// src/deep_agent_new/middleware/subagents.ts
|
|
9917
|
-
import { z as
|
|
10339
|
+
import { z as z48 } from "zod/v3";
|
|
9918
10340
|
import {
|
|
9919
|
-
createMiddleware as
|
|
10341
|
+
createMiddleware as createMiddleware13,
|
|
9920
10342
|
createAgent as createAgent2,
|
|
9921
|
-
tool as
|
|
9922
|
-
ToolMessage as
|
|
10343
|
+
tool as tool47,
|
|
10344
|
+
ToolMessage as ToolMessage4,
|
|
9923
10345
|
humanInTheLoopMiddleware
|
|
9924
10346
|
} from "langchain";
|
|
9925
10347
|
import { Command as Command2, getCurrentTaskInput as getCurrentTaskInput2, GraphInterrupt as GraphInterrupt3 } from "@langchain/langgraph";
|
|
@@ -10490,7 +10912,7 @@ function returnCommandWithStateUpdate(result, toolCallId) {
|
|
|
10490
10912
|
update: {
|
|
10491
10913
|
...stateUpdate,
|
|
10492
10914
|
messages: [
|
|
10493
|
-
new
|
|
10915
|
+
new ToolMessage4({
|
|
10494
10916
|
content: lastMessage?.content || "Task Failed to complete",
|
|
10495
10917
|
tool_call_id: toolCallId,
|
|
10496
10918
|
name: "task"
|
|
@@ -10572,7 +10994,7 @@ function createTaskTool(options) {
|
|
|
10572
10994
|
generalPurposeAgent
|
|
10573
10995
|
});
|
|
10574
10996
|
const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
|
|
10575
|
-
return
|
|
10997
|
+
return tool47(
|
|
10576
10998
|
async (input, config) => {
|
|
10577
10999
|
const { description, subagent_type } = input;
|
|
10578
11000
|
let assistant_id = subagent_type;
|
|
@@ -10626,7 +11048,7 @@ function createTaskTool(options) {
|
|
|
10626
11048
|
return new Command2({
|
|
10627
11049
|
update: {
|
|
10628
11050
|
messages: [
|
|
10629
|
-
new
|
|
11051
|
+
new ToolMessage4({
|
|
10630
11052
|
content: error instanceof Error ? error.message : "Task Failed to complete",
|
|
10631
11053
|
tool_call_id: config.toolCall.id,
|
|
10632
11054
|
name: "task"
|
|
@@ -10639,9 +11061,9 @@ function createTaskTool(options) {
|
|
|
10639
11061
|
{
|
|
10640
11062
|
name: "task",
|
|
10641
11063
|
description: finalTaskDescription,
|
|
10642
|
-
schema:
|
|
10643
|
-
description:
|
|
10644
|
-
subagent_type:
|
|
11064
|
+
schema: z48.object({
|
|
11065
|
+
description: z48.string().describe("The task to execute with the selected agent"),
|
|
11066
|
+
subagent_type: z48.string().describe(
|
|
10645
11067
|
`Name of the agent to use. Available: ${Object.keys(
|
|
10646
11068
|
subagentGraphs
|
|
10647
11069
|
).join(", ")}`
|
|
@@ -10670,7 +11092,7 @@ function createSubAgentMiddleware(options) {
|
|
|
10670
11092
|
generalPurposeAgent,
|
|
10671
11093
|
taskDescription
|
|
10672
11094
|
});
|
|
10673
|
-
return
|
|
11095
|
+
return createMiddleware13({
|
|
10674
11096
|
name: "subAgentMiddleware",
|
|
10675
11097
|
tools: [taskTool],
|
|
10676
11098
|
wrapModelCall: async (request, handler) => {
|
|
@@ -10691,14 +11113,14 @@ ${systemPrompt}` : systemPrompt;
|
|
|
10691
11113
|
|
|
10692
11114
|
// src/deep_agent_new/middleware/patch_tool_calls.ts
|
|
10693
11115
|
import {
|
|
10694
|
-
createMiddleware as
|
|
10695
|
-
ToolMessage as
|
|
10696
|
-
AIMessage as
|
|
11116
|
+
createMiddleware as createMiddleware14,
|
|
11117
|
+
ToolMessage as ToolMessage5,
|
|
11118
|
+
AIMessage as AIMessage3
|
|
10697
11119
|
} from "langchain";
|
|
10698
11120
|
import { RemoveMessage } from "@langchain/core/messages";
|
|
10699
11121
|
import { REMOVE_ALL_MESSAGES } from "@langchain/langgraph";
|
|
10700
11122
|
function createPatchToolCallsMiddleware() {
|
|
10701
|
-
return
|
|
11123
|
+
return createMiddleware14({
|
|
10702
11124
|
name: "patchToolCallsMiddleware",
|
|
10703
11125
|
beforeAgent: async (state) => {
|
|
10704
11126
|
const messages = state.messages;
|
|
@@ -10709,15 +11131,15 @@ function createPatchToolCallsMiddleware() {
|
|
|
10709
11131
|
for (let i = 0; i < messages.length; i++) {
|
|
10710
11132
|
const msg = messages[i];
|
|
10711
11133
|
patchedMessages.push(msg);
|
|
10712
|
-
if (
|
|
11134
|
+
if (AIMessage3.isInstance(msg) && msg.tool_calls != null) {
|
|
10713
11135
|
for (const toolCall of msg.tool_calls) {
|
|
10714
11136
|
const correspondingToolMsg = messages.slice(i).find(
|
|
10715
|
-
(m) =>
|
|
11137
|
+
(m) => ToolMessage5.isInstance(m) && m.tool_call_id === toolCall.id
|
|
10716
11138
|
);
|
|
10717
11139
|
if (!correspondingToolMsg) {
|
|
10718
11140
|
const toolMsg = `Tool call ${toolCall.name} with id ${toolCall.id} was cancelled - another message came in before it could be completed.`;
|
|
10719
11141
|
patchedMessages.push(
|
|
10720
|
-
new
|
|
11142
|
+
new ToolMessage5({
|
|
10721
11143
|
content: toolMsg,
|
|
10722
11144
|
name: toolCall.name,
|
|
10723
11145
|
tool_call_id: toolCall.id
|
|
@@ -11462,261 +11884,81 @@ var FilesystemBackend = class {
|
|
|
11462
11884
|
virtPath = fp;
|
|
11463
11885
|
}
|
|
11464
11886
|
if (!results[virtPath]) {
|
|
11465
|
-
results[virtPath] = [];
|
|
11466
|
-
}
|
|
11467
|
-
results[virtPath].push([i + 1, line]);
|
|
11468
|
-
}
|
|
11469
|
-
}
|
|
11470
|
-
} catch {
|
|
11471
|
-
continue;
|
|
11472
|
-
}
|
|
11473
|
-
}
|
|
11474
|
-
return results;
|
|
11475
|
-
}
|
|
11476
|
-
/**
|
|
11477
|
-
* Structured glob matching returning FileInfo objects.
|
|
11478
|
-
*/
|
|
11479
|
-
async globInfo(pattern, searchPath = "/") {
|
|
11480
|
-
if (pattern.startsWith("/")) {
|
|
11481
|
-
pattern = pattern.substring(1);
|
|
11482
|
-
}
|
|
11483
|
-
const resolvedSearchPath = searchPath === "/" ? this.cwd : this.resolvePath(searchPath);
|
|
11484
|
-
try {
|
|
11485
|
-
const stat3 = await fs2.stat(resolvedSearchPath);
|
|
11486
|
-
if (!stat3.isDirectory()) {
|
|
11487
|
-
return [];
|
|
11488
|
-
}
|
|
11489
|
-
} catch {
|
|
11490
|
-
return [];
|
|
11491
|
-
}
|
|
11492
|
-
const results = [];
|
|
11493
|
-
try {
|
|
11494
|
-
const matches = await fg(pattern, {
|
|
11495
|
-
cwd: resolvedSearchPath,
|
|
11496
|
-
absolute: true,
|
|
11497
|
-
onlyFiles: true,
|
|
11498
|
-
dot: true
|
|
11499
|
-
});
|
|
11500
|
-
for (const matchedPath of matches) {
|
|
11501
|
-
try {
|
|
11502
|
-
const stat3 = await fs2.stat(matchedPath);
|
|
11503
|
-
if (!stat3.isFile()) continue;
|
|
11504
|
-
const normalizedPath = matchedPath.split("/").join(path4.sep);
|
|
11505
|
-
if (!this.virtualMode) {
|
|
11506
|
-
results.push({
|
|
11507
|
-
path: normalizedPath,
|
|
11508
|
-
is_dir: false,
|
|
11509
|
-
size: stat3.size,
|
|
11510
|
-
modified_at: stat3.mtime.toISOString()
|
|
11511
|
-
});
|
|
11512
|
-
} else {
|
|
11513
|
-
const cwdStr = this.cwd.endsWith(path4.sep) ? this.cwd : this.cwd + path4.sep;
|
|
11514
|
-
let relativePath;
|
|
11515
|
-
if (normalizedPath.startsWith(cwdStr)) {
|
|
11516
|
-
relativePath = normalizedPath.substring(cwdStr.length);
|
|
11517
|
-
} else if (normalizedPath.startsWith(this.cwd)) {
|
|
11518
|
-
relativePath = normalizedPath.substring(this.cwd.length).replace(/^[/\\]/, "");
|
|
11519
|
-
} else {
|
|
11520
|
-
relativePath = normalizedPath;
|
|
11521
|
-
}
|
|
11522
|
-
relativePath = relativePath.split(path4.sep).join("/");
|
|
11523
|
-
const virt = "/" + relativePath;
|
|
11524
|
-
results.push({
|
|
11525
|
-
path: virt,
|
|
11526
|
-
is_dir: false,
|
|
11527
|
-
size: stat3.size,
|
|
11528
|
-
modified_at: stat3.mtime.toISOString()
|
|
11529
|
-
});
|
|
11530
|
-
}
|
|
11531
|
-
} catch {
|
|
11532
|
-
continue;
|
|
11533
|
-
}
|
|
11534
|
-
}
|
|
11535
|
-
} catch {
|
|
11536
|
-
}
|
|
11537
|
-
results.sort((a, b) => a.path.localeCompare(b.path));
|
|
11538
|
-
return results;
|
|
11539
|
-
}
|
|
11540
|
-
};
|
|
11541
|
-
|
|
11542
|
-
// src/deep_agent_new/backends/composite.ts
|
|
11543
|
-
var CompositeBackend = class {
|
|
11544
|
-
constructor(defaultBackend, routes) {
|
|
11545
|
-
this.default = defaultBackend;
|
|
11546
|
-
this.routes = routes;
|
|
11547
|
-
this.sortedRoutes = Object.entries(routes).sort(
|
|
11548
|
-
(a, b) => b[0].length - a[0].length
|
|
11549
|
-
);
|
|
11550
|
-
}
|
|
11551
|
-
/**
|
|
11552
|
-
* Determine which backend handles this key and strip prefix.
|
|
11553
|
-
*
|
|
11554
|
-
* @param key - Original file path
|
|
11555
|
-
* @returns Tuple of [backend, stripped_key] where stripped_key has the route
|
|
11556
|
-
* prefix removed (but keeps leading slash).
|
|
11557
|
-
*/
|
|
11558
|
-
getBackendAndKey(key) {
|
|
11559
|
-
for (const [prefix, backend] of this.sortedRoutes) {
|
|
11560
|
-
if (key.startsWith(prefix)) {
|
|
11561
|
-
const suffix = key.substring(prefix.length);
|
|
11562
|
-
const strippedKey = suffix ? "/" + suffix : "/";
|
|
11563
|
-
return [backend, strippedKey];
|
|
11564
|
-
}
|
|
11565
|
-
}
|
|
11566
|
-
return [this.default, key];
|
|
11567
|
-
}
|
|
11568
|
-
/**
|
|
11569
|
-
* List files and directories in the specified directory (non-recursive).
|
|
11570
|
-
*
|
|
11571
|
-
* @param path - Absolute path to directory
|
|
11572
|
-
* @returns List of FileInfo objects with route prefixes added, for files and directories
|
|
11573
|
-
* directly in the directory. Directories have a trailing / in their path and is_dir=true.
|
|
11574
|
-
*/
|
|
11575
|
-
async lsInfo(path5) {
|
|
11576
|
-
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
11577
|
-
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
11578
|
-
const suffix = path5.substring(routePrefix.length);
|
|
11579
|
-
const searchPath = suffix ? "/" + suffix : "/";
|
|
11580
|
-
const infos = await backend.lsInfo(searchPath);
|
|
11581
|
-
const prefixed = [];
|
|
11582
|
-
for (const fi of infos) {
|
|
11583
|
-
prefixed.push({
|
|
11584
|
-
...fi,
|
|
11585
|
-
path: routePrefix.slice(0, -1) + fi.path
|
|
11586
|
-
});
|
|
11887
|
+
results[virtPath] = [];
|
|
11888
|
+
}
|
|
11889
|
+
results[virtPath].push([i + 1, line]);
|
|
11890
|
+
}
|
|
11587
11891
|
}
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
}
|
|
11591
|
-
if (path5 === "/") {
|
|
11592
|
-
const results = [];
|
|
11593
|
-
const defaultInfos = await this.default.lsInfo(path5);
|
|
11594
|
-
results.push(...defaultInfos);
|
|
11595
|
-
for (const [routePrefix] of this.sortedRoutes) {
|
|
11596
|
-
results.push({
|
|
11597
|
-
path: routePrefix,
|
|
11598
|
-
is_dir: true,
|
|
11599
|
-
size: 0,
|
|
11600
|
-
modified_at: ""
|
|
11601
|
-
});
|
|
11892
|
+
} catch {
|
|
11893
|
+
continue;
|
|
11602
11894
|
}
|
|
11603
|
-
results.sort((a, b) => a.path.localeCompare(b.path));
|
|
11604
|
-
return results;
|
|
11605
11895
|
}
|
|
11606
|
-
return
|
|
11607
|
-
}
|
|
11608
|
-
/**
|
|
11609
|
-
* Read file content, routing to appropriate backend.
|
|
11610
|
-
*
|
|
11611
|
-
* @param filePath - Absolute file path
|
|
11612
|
-
* @param offset - Line offset to start reading from (0-indexed)
|
|
11613
|
-
* @param limit - Maximum number of lines to read
|
|
11614
|
-
* @returns Formatted file content with line numbers, or error message
|
|
11615
|
-
*/
|
|
11616
|
-
async read(filePath, offset = 0, limit = 2e3) {
|
|
11617
|
-
const [backend, strippedKey] = this.getBackendAndKey(filePath);
|
|
11618
|
-
return await backend.read(strippedKey, offset, limit);
|
|
11619
|
-
}
|
|
11620
|
-
/**
|
|
11621
|
-
* Read file content as raw FileData.
|
|
11622
|
-
*
|
|
11623
|
-
* @param filePath - Absolute file path
|
|
11624
|
-
* @returns Raw file content as FileData
|
|
11625
|
-
*/
|
|
11626
|
-
async readRaw(filePath) {
|
|
11627
|
-
const [backend, strippedKey] = this.getBackendAndKey(filePath);
|
|
11628
|
-
return await backend.readRaw(strippedKey);
|
|
11896
|
+
return results;
|
|
11629
11897
|
}
|
|
11630
11898
|
/**
|
|
11631
|
-
* Structured
|
|
11899
|
+
* Structured glob matching returning FileInfo objects.
|
|
11632
11900
|
*/
|
|
11633
|
-
async
|
|
11634
|
-
|
|
11635
|
-
|
|
11636
|
-
const searchPath = path5.substring(routePrefix.length - 1);
|
|
11637
|
-
const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
|
|
11638
|
-
if (typeof raw === "string") {
|
|
11639
|
-
return raw;
|
|
11640
|
-
}
|
|
11641
|
-
return raw.map((m) => ({
|
|
11642
|
-
...m,
|
|
11643
|
-
path: routePrefix.slice(0, -1) + m.path
|
|
11644
|
-
}));
|
|
11645
|
-
}
|
|
11646
|
-
}
|
|
11647
|
-
const allMatches = [];
|
|
11648
|
-
const rawDefault = await this.default.grepRaw(pattern, path5, glob);
|
|
11649
|
-
if (typeof rawDefault === "string") {
|
|
11650
|
-
return rawDefault;
|
|
11901
|
+
async globInfo(pattern, searchPath = "/") {
|
|
11902
|
+
if (pattern.startsWith("/")) {
|
|
11903
|
+
pattern = pattern.substring(1);
|
|
11651
11904
|
}
|
|
11652
|
-
|
|
11653
|
-
|
|
11654
|
-
const
|
|
11655
|
-
if (
|
|
11656
|
-
return
|
|
11905
|
+
const resolvedSearchPath = searchPath === "/" ? this.cwd : this.resolvePath(searchPath);
|
|
11906
|
+
try {
|
|
11907
|
+
const stat3 = await fs2.stat(resolvedSearchPath);
|
|
11908
|
+
if (!stat3.isDirectory()) {
|
|
11909
|
+
return [];
|
|
11657
11910
|
}
|
|
11658
|
-
|
|
11659
|
-
|
|
11660
|
-
...m,
|
|
11661
|
-
path: routePrefix.slice(0, -1) + m.path
|
|
11662
|
-
}))
|
|
11663
|
-
);
|
|
11911
|
+
} catch {
|
|
11912
|
+
return [];
|
|
11664
11913
|
}
|
|
11665
|
-
return allMatches;
|
|
11666
|
-
}
|
|
11667
|
-
/**
|
|
11668
|
-
* Structured glob matching returning FileInfo objects.
|
|
11669
|
-
*/
|
|
11670
|
-
async globInfo(pattern, path5 = "/") {
|
|
11671
11914
|
const results = [];
|
|
11672
|
-
|
|
11673
|
-
|
|
11674
|
-
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
11679
|
-
|
|
11915
|
+
try {
|
|
11916
|
+
const matches = await fg(pattern, {
|
|
11917
|
+
cwd: resolvedSearchPath,
|
|
11918
|
+
absolute: true,
|
|
11919
|
+
onlyFiles: true,
|
|
11920
|
+
dot: true
|
|
11921
|
+
});
|
|
11922
|
+
for (const matchedPath of matches) {
|
|
11923
|
+
try {
|
|
11924
|
+
const stat3 = await fs2.stat(matchedPath);
|
|
11925
|
+
if (!stat3.isFile()) continue;
|
|
11926
|
+
const normalizedPath = matchedPath.split("/").join(path4.sep);
|
|
11927
|
+
if (!this.virtualMode) {
|
|
11928
|
+
results.push({
|
|
11929
|
+
path: normalizedPath,
|
|
11930
|
+
is_dir: false,
|
|
11931
|
+
size: stat3.size,
|
|
11932
|
+
modified_at: stat3.mtime.toISOString()
|
|
11933
|
+
});
|
|
11934
|
+
} else {
|
|
11935
|
+
const cwdStr = this.cwd.endsWith(path4.sep) ? this.cwd : this.cwd + path4.sep;
|
|
11936
|
+
let relativePath;
|
|
11937
|
+
if (normalizedPath.startsWith(cwdStr)) {
|
|
11938
|
+
relativePath = normalizedPath.substring(cwdStr.length);
|
|
11939
|
+
} else if (normalizedPath.startsWith(this.cwd)) {
|
|
11940
|
+
relativePath = normalizedPath.substring(this.cwd.length).replace(/^[/\\]/, "");
|
|
11941
|
+
} else {
|
|
11942
|
+
relativePath = normalizedPath;
|
|
11943
|
+
}
|
|
11944
|
+
relativePath = relativePath.split(path4.sep).join("/");
|
|
11945
|
+
const virt = "/" + relativePath;
|
|
11946
|
+
results.push({
|
|
11947
|
+
path: virt,
|
|
11948
|
+
is_dir: false,
|
|
11949
|
+
size: stat3.size,
|
|
11950
|
+
modified_at: stat3.mtime.toISOString()
|
|
11951
|
+
});
|
|
11952
|
+
}
|
|
11953
|
+
} catch {
|
|
11954
|
+
continue;
|
|
11955
|
+
}
|
|
11680
11956
|
}
|
|
11681
|
-
}
|
|
11682
|
-
const defaultInfos = await this.default.globInfo(pattern, path5);
|
|
11683
|
-
results.push(...defaultInfos);
|
|
11684
|
-
for (const [routePrefix, backend] of Object.entries(this.routes)) {
|
|
11685
|
-
const infos = await backend.globInfo(pattern, "/");
|
|
11686
|
-
results.push(
|
|
11687
|
-
...infos.map((fi) => ({
|
|
11688
|
-
...fi,
|
|
11689
|
-
path: routePrefix.slice(0, -1) + fi.path
|
|
11690
|
-
}))
|
|
11691
|
-
);
|
|
11957
|
+
} catch {
|
|
11692
11958
|
}
|
|
11693
11959
|
results.sort((a, b) => a.path.localeCompare(b.path));
|
|
11694
11960
|
return results;
|
|
11695
11961
|
}
|
|
11696
|
-
/**
|
|
11697
|
-
* Create a new file, routing to appropriate backend.
|
|
11698
|
-
*
|
|
11699
|
-
* @param filePath - Absolute file path
|
|
11700
|
-
* @param content - File content as string
|
|
11701
|
-
* @returns WriteResult with path or error
|
|
11702
|
-
*/
|
|
11703
|
-
async write(filePath, content) {
|
|
11704
|
-
const [backend, strippedKey] = this.getBackendAndKey(filePath);
|
|
11705
|
-
return await backend.write(strippedKey, content);
|
|
11706
|
-
}
|
|
11707
|
-
/**
|
|
11708
|
-
* Edit a file, routing to appropriate backend.
|
|
11709
|
-
*
|
|
11710
|
-
* @param filePath - Absolute file path
|
|
11711
|
-
* @param oldString - String to find and replace
|
|
11712
|
-
* @param newString - Replacement string
|
|
11713
|
-
* @param replaceAll - If true, replace all occurrences
|
|
11714
|
-
* @returns EditResult with path, occurrences, or error
|
|
11715
|
-
*/
|
|
11716
|
-
async edit(filePath, oldString, newString, replaceAll = false) {
|
|
11717
|
-
const [backend, strippedKey] = this.getBackendAndKey(filePath);
|
|
11718
|
-
return await backend.edit(strippedKey, oldString, newString, replaceAll);
|
|
11719
|
-
}
|
|
11720
11962
|
};
|
|
11721
11963
|
|
|
11722
11964
|
// src/deep_agent_new/backends/memory.ts
|
|
@@ -11834,8 +12076,8 @@ var MemoryBackend = class {
|
|
|
11834
12076
|
|
|
11835
12077
|
// src/deep_agent_new/middleware/todos.ts
|
|
11836
12078
|
import { Command as Command3 } from "@langchain/langgraph";
|
|
11837
|
-
import { z as
|
|
11838
|
-
import { createMiddleware as
|
|
12079
|
+
import { z as z49 } from "zod";
|
|
12080
|
+
import { createMiddleware as createMiddleware15, tool as tool48, ToolMessage as ToolMessage6 } from "langchain";
|
|
11839
12081
|
var WRITE_TODOS_DESCRIPTION = `Use this tool to create and manage a structured task list for your current work session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
|
|
11840
12082
|
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
11841
12083
|
Only use this tool if you think it will be helpful in staying organized. If the user's request is trivial and takes less than 3 steps, it is better to NOT use this tool and just do the taks directly.
|
|
@@ -12062,20 +12304,20 @@ Writing todos takes time and tokens, use it when it is helpful for managing comp
|
|
|
12062
12304
|
## Important To-Do List Usage Notes to Remember
|
|
12063
12305
|
- The \`write_todos\` tool should never be called multiple times in parallel.
|
|
12064
12306
|
- Don't be afraid to revise the To-Do list as you go. New information may reveal new tasks that need to be done, or old tasks that are irrelevant.`;
|
|
12065
|
-
var TodoStatus =
|
|
12066
|
-
var TodoSchema =
|
|
12067
|
-
content:
|
|
12307
|
+
var TodoStatus = z49.enum(["pending", "in_progress", "completed"]).describe("Status of the todo");
|
|
12308
|
+
var TodoSchema = z49.object({
|
|
12309
|
+
content: z49.string().describe("Content of the todo item"),
|
|
12068
12310
|
status: TodoStatus
|
|
12069
12311
|
});
|
|
12070
|
-
var stateSchema =
|
|
12312
|
+
var stateSchema = z49.object({ todos: z49.array(TodoSchema).default([]) });
|
|
12071
12313
|
function todoListMiddleware(options) {
|
|
12072
|
-
const writeTodos =
|
|
12314
|
+
const writeTodos = tool48(
|
|
12073
12315
|
({ todos }, config) => {
|
|
12074
12316
|
return new Command3({
|
|
12075
12317
|
update: {
|
|
12076
12318
|
todos,
|
|
12077
12319
|
messages: [
|
|
12078
|
-
new
|
|
12320
|
+
new ToolMessage6({
|
|
12079
12321
|
content: genUIMarkdown("todo_list", todos),
|
|
12080
12322
|
tool_call_id: config.toolCall?.id
|
|
12081
12323
|
})
|
|
@@ -12086,12 +12328,12 @@ function todoListMiddleware(options) {
|
|
|
12086
12328
|
{
|
|
12087
12329
|
name: "write_todos",
|
|
12088
12330
|
description: options?.toolDescription ?? WRITE_TODOS_DESCRIPTION,
|
|
12089
|
-
schema:
|
|
12090
|
-
todos:
|
|
12331
|
+
schema: z49.object({
|
|
12332
|
+
todos: z49.array(TodoSchema).describe("List of todo items to update")
|
|
12091
12333
|
})
|
|
12092
12334
|
}
|
|
12093
12335
|
);
|
|
12094
|
-
return
|
|
12336
|
+
return createMiddleware15({
|
|
12095
12337
|
name: "todoListMiddleware",
|
|
12096
12338
|
stateSchema,
|
|
12097
12339
|
tools: [writeTodos],
|
|
@@ -12190,50 +12432,8 @@ ${BASE_PROMPT}` : BASE_PROMPT;
|
|
|
12190
12432
|
});
|
|
12191
12433
|
}
|
|
12192
12434
|
|
|
12193
|
-
// src/agent_lattice/builders/filesystemBackend.ts
|
|
12194
|
-
function createFilesystemBackendFactory(middlewareConfigs) {
|
|
12195
|
-
const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
|
|
12196
|
-
if (!filesystemConfig || !filesystemConfig.enabled) {
|
|
12197
|
-
return void 0;
|
|
12198
|
-
}
|
|
12199
|
-
const isolatedLevel = filesystemConfig.config?.isolatedLevel || "global";
|
|
12200
|
-
return async (stateAndStore) => {
|
|
12201
|
-
const { tenantId, workspaceId, projectId } = stateAndStore;
|
|
12202
|
-
let sandboxName = "global";
|
|
12203
|
-
if (isolatedLevel === "agent") {
|
|
12204
|
-
sandboxName = "agent";
|
|
12205
|
-
} else if (isolatedLevel === "thread") {
|
|
12206
|
-
sandboxName = "thread";
|
|
12207
|
-
}
|
|
12208
|
-
const sandboxManager = sandboxLatticeManager.getSandboxLattice("default");
|
|
12209
|
-
if (!sandboxManager) {
|
|
12210
|
-
throw new Error("Sandbox manager not found");
|
|
12211
|
-
}
|
|
12212
|
-
let workingDirectory = "/";
|
|
12213
|
-
if (workspaceId && projectId) {
|
|
12214
|
-
if (tenantId) {
|
|
12215
|
-
workingDirectory = `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
|
|
12216
|
-
} else {
|
|
12217
|
-
workingDirectory = `/workspaces/${workspaceId}/${projectId}`;
|
|
12218
|
-
}
|
|
12219
|
-
}
|
|
12220
|
-
const sandboxfs = new SandboxFilesystem({
|
|
12221
|
-
sandboxInstance: await sandboxManager.createSandbox(sandboxName),
|
|
12222
|
-
workingDirectory
|
|
12223
|
-
});
|
|
12224
|
-
const compositeBackend = new CompositeBackend(sandboxfs, {});
|
|
12225
|
-
return compositeBackend;
|
|
12226
|
-
};
|
|
12227
|
-
}
|
|
12228
|
-
|
|
12229
12435
|
// src/agent_lattice/builders/DeepAgentGraphBuilder.ts
|
|
12230
12436
|
var DeepAgentGraphBuilder = class {
|
|
12231
|
-
/**
|
|
12232
|
-
* 根据 middleware 配置创建 middlewares
|
|
12233
|
-
*/
|
|
12234
|
-
async createMiddlewares(middlewareConfigs) {
|
|
12235
|
-
return await createCommonMiddlewares(middlewareConfigs);
|
|
12236
|
-
}
|
|
12237
12437
|
/**
|
|
12238
12438
|
* 构建Deep Agent Graph
|
|
12239
12439
|
*
|
|
@@ -12245,7 +12445,7 @@ var DeepAgentGraphBuilder = class {
|
|
|
12245
12445
|
const tools = params.tools.map((t) => {
|
|
12246
12446
|
const toolClient = getToolClient(t.key);
|
|
12247
12447
|
return toolClient;
|
|
12248
|
-
}).filter((
|
|
12448
|
+
}).filter((tool51) => tool51 !== void 0);
|
|
12249
12449
|
const subagents = await Promise.all(params.subAgents.map(async (sa) => {
|
|
12250
12450
|
if (sa.client) {
|
|
12251
12451
|
return {
|
|
@@ -12268,7 +12468,7 @@ var DeepAgentGraphBuilder = class {
|
|
|
12268
12468
|
}));
|
|
12269
12469
|
const middlewareConfigs = params.middleware || [];
|
|
12270
12470
|
const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
|
|
12271
|
-
const middlewares = await
|
|
12471
|
+
const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true);
|
|
12272
12472
|
const deepAgent = createDeepAgent({
|
|
12273
12473
|
tools,
|
|
12274
12474
|
model: params.model,
|
|
@@ -12285,7 +12485,7 @@ var DeepAgentGraphBuilder = class {
|
|
|
12285
12485
|
};
|
|
12286
12486
|
|
|
12287
12487
|
// src/agent_team/agent_team.ts
|
|
12288
|
-
import { z as
|
|
12488
|
+
import { z as z52 } from "zod/v3";
|
|
12289
12489
|
import { createAgent as createAgent5 } from "langchain";
|
|
12290
12490
|
|
|
12291
12491
|
// src/agent_team/types.ts
|
|
@@ -12721,14 +12921,14 @@ var InMemoryMailboxStore = class {
|
|
|
12721
12921
|
};
|
|
12722
12922
|
|
|
12723
12923
|
// src/agent_team/middleware/team.ts
|
|
12724
|
-
import { z as
|
|
12725
|
-
import { createMiddleware as
|
|
12924
|
+
import { z as z51 } from "zod/v3";
|
|
12925
|
+
import { createMiddleware as createMiddleware16, createAgent as createAgent4, tool as tool50, ToolMessage as ToolMessage8 } from "langchain";
|
|
12726
12926
|
import { Command as Command5, getCurrentTaskInput as getCurrentTaskInput3 } from "@langchain/langgraph";
|
|
12727
12927
|
import { v4 as uuidv4 } from "uuid";
|
|
12728
12928
|
|
|
12729
12929
|
// src/agent_team/middleware/teammate_tools.ts
|
|
12730
|
-
import { z as
|
|
12731
|
-
import { tool as
|
|
12930
|
+
import { z as z50 } from "zod/v3";
|
|
12931
|
+
import { tool as tool49, ToolMessage as ToolMessage7 } from "langchain";
|
|
12732
12932
|
import { Command as Command4 } from "@langchain/langgraph";
|
|
12733
12933
|
|
|
12734
12934
|
// src/agent_team/middleware/formatMessages.ts
|
|
@@ -12753,7 +12953,7 @@ ${meta}${body}`;
|
|
|
12753
12953
|
// src/agent_team/middleware/teammate_tools.ts
|
|
12754
12954
|
function createTeammateTools(options) {
|
|
12755
12955
|
const { teamId, agentId, taskListStore, mailboxStore } = options;
|
|
12756
|
-
const claimTaskTool =
|
|
12956
|
+
const claimTaskTool = tool49(
|
|
12757
12957
|
async (input) => {
|
|
12758
12958
|
const task = await taskListStore.claimTaskById(
|
|
12759
12959
|
teamId,
|
|
@@ -12778,12 +12978,12 @@ function createTeammateTools(options) {
|
|
|
12778
12978
|
{
|
|
12779
12979
|
name: "claim_task",
|
|
12780
12980
|
description: "Pick a task to work on by task_id. Use check_tasks first to see all tasks; then call this with the task_id you choose. The task's assignee is set to you and you should focus on that task until you complete_task or fail_task it.",
|
|
12781
|
-
schema:
|
|
12782
|
-
task_id:
|
|
12981
|
+
schema: z50.object({
|
|
12982
|
+
task_id: z50.string().describe("ID of the task to claim (e.g. task-01). Use check_tasks to see IDs.")
|
|
12783
12983
|
})
|
|
12784
12984
|
}
|
|
12785
12985
|
);
|
|
12786
|
-
const completeTaskTool =
|
|
12986
|
+
const completeTaskTool = tool49(
|
|
12787
12987
|
async (input) => {
|
|
12788
12988
|
const task = await taskListStore.completeTask(
|
|
12789
12989
|
teamId,
|
|
@@ -12804,13 +13004,13 @@ function createTeammateTools(options) {
|
|
|
12804
13004
|
{
|
|
12805
13005
|
name: "complete_task",
|
|
12806
13006
|
description: "Mark a claimed task as completed with a result summary. Call this after you have finished working on a task.",
|
|
12807
|
-
schema:
|
|
12808
|
-
task_id:
|
|
12809
|
-
result:
|
|
13007
|
+
schema: z50.object({
|
|
13008
|
+
task_id: z50.string().describe("ID of the task to complete"),
|
|
13009
|
+
result: z50.string().describe("Summary of the task result")
|
|
12810
13010
|
})
|
|
12811
13011
|
}
|
|
12812
13012
|
);
|
|
12813
|
-
const failTaskTool =
|
|
13013
|
+
const failTaskTool = tool49(
|
|
12814
13014
|
async (input) => {
|
|
12815
13015
|
const task = await taskListStore.failTask(
|
|
12816
13016
|
teamId,
|
|
@@ -12831,13 +13031,13 @@ function createTeammateTools(options) {
|
|
|
12831
13031
|
{
|
|
12832
13032
|
name: "fail_task",
|
|
12833
13033
|
description: "Mark a claimed task as failed with an error description. Call this if you cannot complete the task.",
|
|
12834
|
-
schema:
|
|
12835
|
-
task_id:
|
|
12836
|
-
error:
|
|
13034
|
+
schema: z50.object({
|
|
13035
|
+
task_id: z50.string().describe("ID of the task to fail"),
|
|
13036
|
+
error: z50.string().describe("Description of why the task failed")
|
|
12837
13037
|
})
|
|
12838
13038
|
}
|
|
12839
13039
|
);
|
|
12840
|
-
const sendMessageTool =
|
|
13040
|
+
const sendMessageTool = tool49(
|
|
12841
13041
|
async (input) => {
|
|
12842
13042
|
await mailboxStore.sendMessage(
|
|
12843
13043
|
teamId,
|
|
@@ -12851,11 +13051,11 @@ function createTeammateTools(options) {
|
|
|
12851
13051
|
{
|
|
12852
13052
|
name: "send_message",
|
|
12853
13053
|
description: 'Send a message to the team lead or another teammate via the mailbox. Use "team_lead" to message the team lead. Use this to report discoveries, request guidance, or suggest new tasks.',
|
|
12854
|
-
schema:
|
|
12855
|
-
to:
|
|
13054
|
+
schema: z50.object({
|
|
13055
|
+
to: z50.string().describe(
|
|
12856
13056
|
'Recipient agent name (e.g. "team_lead" or a teammate name)'
|
|
12857
13057
|
),
|
|
12858
|
-
content:
|
|
13058
|
+
content: z50.string().describe("Message content")
|
|
12859
13059
|
})
|
|
12860
13060
|
}
|
|
12861
13061
|
);
|
|
@@ -12875,7 +13075,7 @@ function createTeammateTools(options) {
|
|
|
12875
13075
|
read: msg.read
|
|
12876
13076
|
}));
|
|
12877
13077
|
};
|
|
12878
|
-
const readMessagesTool =
|
|
13078
|
+
const readMessagesTool = tool49(
|
|
12879
13079
|
async (input, config) => {
|
|
12880
13080
|
const formatAndMarkAsRead = async (msgs2) => {
|
|
12881
13081
|
for (const msg of msgs2) {
|
|
@@ -12887,7 +13087,7 @@ function createTeammateTools(options) {
|
|
|
12887
13087
|
if (msgs.length > 0) {
|
|
12888
13088
|
const formatted2 = await formatAndMarkAsRead(msgs);
|
|
12889
13089
|
const relevantMsgs2 = await getRelevantMessagesForState();
|
|
12890
|
-
const toolMessage2 = new
|
|
13090
|
+
const toolMessage2 = new ToolMessage7({
|
|
12891
13091
|
content: formatted2,
|
|
12892
13092
|
tool_call_id: config.toolCall?.id,
|
|
12893
13093
|
name: "read_messages"
|
|
@@ -12912,7 +13112,7 @@ function createTeammateTools(options) {
|
|
|
12912
13112
|
});
|
|
12913
13113
|
const relevantMsgs = await getRelevantMessagesForState();
|
|
12914
13114
|
if (msgs.length === 0) {
|
|
12915
|
-
const toolMessage2 = new
|
|
13115
|
+
const toolMessage2 = new ToolMessage7({
|
|
12916
13116
|
content: "No unread messages.",
|
|
12917
13117
|
tool_call_id: config.toolCall?.id,
|
|
12918
13118
|
name: "read_messages"
|
|
@@ -12922,7 +13122,7 @@ function createTeammateTools(options) {
|
|
|
12922
13122
|
});
|
|
12923
13123
|
}
|
|
12924
13124
|
const formatted = await formatAndMarkAsRead(msgs);
|
|
12925
|
-
const toolMessage = new
|
|
13125
|
+
const toolMessage = new ToolMessage7({
|
|
12926
13126
|
content: formatted,
|
|
12927
13127
|
tool_call_id: config.toolCall?.id,
|
|
12928
13128
|
name: "read_messages"
|
|
@@ -12934,10 +13134,10 @@ function createTeammateTools(options) {
|
|
|
12934
13134
|
{
|
|
12935
13135
|
name: "read_messages",
|
|
12936
13136
|
description: "Read unread messages from the mailbox. Returns immediately if messages exist, otherwise waits for up to 3 minutes for new messages.",
|
|
12937
|
-
schema:
|
|
13137
|
+
schema: z50.object({})
|
|
12938
13138
|
}
|
|
12939
13139
|
);
|
|
12940
|
-
const checkTasksTool =
|
|
13140
|
+
const checkTasksTool = tool49(
|
|
12941
13141
|
async () => {
|
|
12942
13142
|
const tasks = await taskListStore.getAllTasks(teamId);
|
|
12943
13143
|
return formatTaskSummary(tasks);
|
|
@@ -12945,10 +13145,10 @@ function createTeammateTools(options) {
|
|
|
12945
13145
|
{
|
|
12946
13146
|
name: "check_tasks",
|
|
12947
13147
|
description: "Use this tool to get the current status of all tasks in a team. This is your primary way to monitor task progress.",
|
|
12948
|
-
schema:
|
|
13148
|
+
schema: z50.object({})
|
|
12949
13149
|
}
|
|
12950
13150
|
);
|
|
12951
|
-
const broadcastMessageTool =
|
|
13151
|
+
const broadcastMessageTool = tool49(
|
|
12952
13152
|
async (input) => {
|
|
12953
13153
|
const allAgents = await mailboxStore.getRegisteredAgents(teamId);
|
|
12954
13154
|
const recipients = allAgents.filter((a) => a !== agentId);
|
|
@@ -12967,8 +13167,8 @@ function createTeammateTools(options) {
|
|
|
12967
13167
|
{
|
|
12968
13168
|
name: "broadcast_message",
|
|
12969
13169
|
description: "Send a message to everyone in the team except yourself. Use this to share updates or information with all teammates and the team lead at once.",
|
|
12970
|
-
schema:
|
|
12971
|
-
content:
|
|
13170
|
+
schema: z50.object({
|
|
13171
|
+
content: z50.string().describe("Message content to broadcast to others")
|
|
12972
13172
|
})
|
|
12973
13173
|
}
|
|
12974
13174
|
);
|
|
@@ -13202,12 +13402,12 @@ async function spawnTeammate(options) {
|
|
|
13202
13402
|
function createTeamMiddleware(options) {
|
|
13203
13403
|
const { teamConfig, taskListStore, mailboxStore, tenantId } = options;
|
|
13204
13404
|
const defaultModel = teamConfig.model ?? "claude-sonnet-4-5-20250929";
|
|
13205
|
-
const createTeamTool =
|
|
13405
|
+
const createTeamTool = tool50(
|
|
13206
13406
|
async (input, config) => {
|
|
13207
13407
|
const state = getCurrentTaskInput3();
|
|
13208
13408
|
if (state?.team?.teamId) {
|
|
13209
13409
|
const existingId = state.team.teamId;
|
|
13210
|
-
const msg = new
|
|
13410
|
+
const msg = new ToolMessage8({
|
|
13211
13411
|
content: `A team is already active (id: ${existingId}). Use this team_id for \`check_tasks\`, \`read_messages\`, \`add_tasks\`, \`send_message\`, \`assign_task\`, \`set_task_status\`, and \`set_task_dependencies\`. Do not call \`create_team\` again unless you need a fresh team for a new objective.`,
|
|
13212
13412
|
tool_call_id: config.toolCall?.id,
|
|
13213
13413
|
name: "create_team"
|
|
@@ -13296,7 +13496,7 @@ Teammates are now working in the background. Keep calling \`check_tasks\` and \`
|
|
|
13296
13496
|
\`\`\`json
|
|
13297
13497
|
${teamJson}
|
|
13298
13498
|
\`\`\``;
|
|
13299
|
-
const toolMessage = new
|
|
13499
|
+
const toolMessage = new ToolMessage8({
|
|
13300
13500
|
content: summary,
|
|
13301
13501
|
tool_call_id: config.toolCall?.id,
|
|
13302
13502
|
name: "create_team"
|
|
@@ -13357,20 +13557,20 @@ After calling create_team, you MUST:
|
|
|
13357
13557
|
2. When messages indicate task changes, call check_tasks to get full task status
|
|
13358
13558
|
3. Continue until all tasks show "completed" or "failed"
|
|
13359
13559
|
4. Do NOT assume tasks are done - always verify with check_tasks`,
|
|
13360
|
-
schema:
|
|
13361
|
-
tasks:
|
|
13362
|
-
|
|
13363
|
-
id:
|
|
13364
|
-
title:
|
|
13365
|
-
description:
|
|
13366
|
-
dependencies:
|
|
13560
|
+
schema: z51.object({
|
|
13561
|
+
tasks: z51.array(
|
|
13562
|
+
z51.object({
|
|
13563
|
+
id: z51.string().describe("Task ID in format task-01, task-02, etc."),
|
|
13564
|
+
title: z51.string().describe("Short task title"),
|
|
13565
|
+
description: z51.string().describe("Detailed task description - what exactly needs to be done"),
|
|
13566
|
+
dependencies: z51.array(z51.string()).optional().default([]).describe('Array of task IDs that must complete before this task (e.g. ["task-01"])')
|
|
13367
13567
|
})
|
|
13368
13568
|
).describe("List of tasks for teammates to work on. Each task needs unique ID (task-01, task-02, etc.)."),
|
|
13369
|
-
teammates:
|
|
13370
|
-
|
|
13371
|
-
name:
|
|
13372
|
-
role:
|
|
13373
|
-
description:
|
|
13569
|
+
teammates: z51.array(
|
|
13570
|
+
z51.object({
|
|
13571
|
+
name: z51.string().describe("Teammate name (must match a pre-configured teammate type)"),
|
|
13572
|
+
role: z51.string().describe("Role category (e.g. researcher, writer, coder, reviewer)"),
|
|
13573
|
+
description: z51.string().describe("What this teammate will focus on - specific instructions for their work")
|
|
13374
13574
|
})
|
|
13375
13575
|
).describe("Teammate agents to create. Each should have a clear role and focus.")
|
|
13376
13576
|
})
|
|
@@ -13381,7 +13581,7 @@ After calling create_team, you MUST:
|
|
|
13381
13581
|
if (state?.team?.teamId) return state.team.teamId;
|
|
13382
13582
|
throw new Error("No team_id provided and no team in state. Call create_team first.");
|
|
13383
13583
|
};
|
|
13384
|
-
const addTasksTool =
|
|
13584
|
+
const addTasksTool = tool50(
|
|
13385
13585
|
async (input, config) => {
|
|
13386
13586
|
const teamId = resolveTeamId();
|
|
13387
13587
|
const created = await taskListStore.addTasks(
|
|
@@ -13395,7 +13595,7 @@ After calling create_team, you MUST:
|
|
|
13395
13595
|
}))
|
|
13396
13596
|
);
|
|
13397
13597
|
const summary = created.map((t) => `- ${t.id}: "${t.title}"`).join("\n");
|
|
13398
|
-
return new
|
|
13598
|
+
return new ToolMessage8({
|
|
13399
13599
|
content: `Added ${created.length} task(s) to team ${teamId}:
|
|
13400
13600
|
${summary}
|
|
13401
13601
|
Sleeping teammates will wake up and claim these.`,
|
|
@@ -13433,33 +13633,33 @@ IMPORTANT: Dependencies
|
|
|
13433
13633
|
|
|
13434
13634
|
IMPORTANT: Assigning to a specific teammate
|
|
13435
13635
|
- When you need a particular teammate to do the work, set assignee to that teammate's name (e.g. assignee: "researcher"). They can then claim or see the task as assigned to them.`,
|
|
13436
|
-
schema:
|
|
13437
|
-
tasks:
|
|
13438
|
-
|
|
13439
|
-
id:
|
|
13440
|
-
title:
|
|
13441
|
-
description:
|
|
13442
|
-
assignee:
|
|
13443
|
-
dependencies:
|
|
13636
|
+
schema: z51.object({
|
|
13637
|
+
tasks: z51.array(
|
|
13638
|
+
z51.object({
|
|
13639
|
+
id: z51.string().describe("Task ID in format task-01, task-02, etc. Must be unique."),
|
|
13640
|
+
title: z51.string().describe("Short task title"),
|
|
13641
|
+
description: z51.string().describe("Detailed task description - what needs to be done"),
|
|
13642
|
+
assignee: z51.string().optional().describe("Teammate name to assign this task to (use when you need that person to do the work)"),
|
|
13643
|
+
dependencies: z51.array(z51.string()).optional().default([]).describe("Array of task IDs that must complete before this task")
|
|
13444
13644
|
})
|
|
13445
13645
|
).describe("New tasks to add to the team")
|
|
13446
13646
|
})
|
|
13447
13647
|
}
|
|
13448
13648
|
);
|
|
13449
|
-
const assignTaskTool =
|
|
13649
|
+
const assignTaskTool = tool50(
|
|
13450
13650
|
async (input, config) => {
|
|
13451
13651
|
const teamId = resolveTeamId();
|
|
13452
13652
|
const task = await taskListStore.updateTask(teamId, input.task_id, {
|
|
13453
13653
|
assignee: input.assignee
|
|
13454
13654
|
});
|
|
13455
13655
|
if (!task) {
|
|
13456
|
-
return new
|
|
13656
|
+
return new ToolMessage8({
|
|
13457
13657
|
content: `Task ${input.task_id} not found in team ${teamId}.`,
|
|
13458
13658
|
tool_call_id: config.toolCall?.id,
|
|
13459
13659
|
name: "assign_task"
|
|
13460
13660
|
});
|
|
13461
13661
|
}
|
|
13462
|
-
return new
|
|
13662
|
+
return new ToolMessage8({
|
|
13463
13663
|
content: `Task "${task.title}" (${task.id}) assigned to ${input.assignee}.`,
|
|
13464
13664
|
tool_call_id: config.toolCall?.id,
|
|
13465
13665
|
name: "assign_task"
|
|
@@ -13468,26 +13668,26 @@ IMPORTANT: Assigning to a specific teammate
|
|
|
13468
13668
|
{
|
|
13469
13669
|
name: "assign_task",
|
|
13470
13670
|
description: "Assign a task to a specific teammate. Use when you need to reassign work to a different teammate. Omit team_id to use the active team from state.",
|
|
13471
|
-
schema:
|
|
13472
|
-
task_id:
|
|
13473
|
-
assignee:
|
|
13671
|
+
schema: z51.object({
|
|
13672
|
+
task_id: z51.string().describe("Task ID to assign"),
|
|
13673
|
+
assignee: z51.string().describe("Teammate name to assign this task to")
|
|
13474
13674
|
})
|
|
13475
13675
|
}
|
|
13476
13676
|
);
|
|
13477
|
-
const setTaskStatusTool =
|
|
13677
|
+
const setTaskStatusTool = tool50(
|
|
13478
13678
|
async (input, config) => {
|
|
13479
13679
|
const teamId = resolveTeamId();
|
|
13480
13680
|
const task = await taskListStore.updateTask(teamId, input.task_id, {
|
|
13481
13681
|
status: input.status
|
|
13482
13682
|
});
|
|
13483
13683
|
if (!task) {
|
|
13484
|
-
return new
|
|
13684
|
+
return new ToolMessage8({
|
|
13485
13685
|
content: `Task ${input.task_id} not found in team ${teamId}.`,
|
|
13486
13686
|
tool_call_id: config.toolCall?.id,
|
|
13487
13687
|
name: "set_task_status"
|
|
13488
13688
|
});
|
|
13489
13689
|
}
|
|
13490
|
-
return new
|
|
13690
|
+
return new ToolMessage8({
|
|
13491
13691
|
content: `Task "${task.title}" (${task.id}) status set to ${input.status}.`,
|
|
13492
13692
|
tool_call_id: config.toolCall?.id,
|
|
13493
13693
|
name: "set_task_status"
|
|
@@ -13496,26 +13696,26 @@ IMPORTANT: Assigning to a specific teammate
|
|
|
13496
13696
|
{
|
|
13497
13697
|
name: "set_task_status",
|
|
13498
13698
|
description: "Set a task's status. Use to reopen a task (set to pending), mark as failed, or correct status. Values: pending, claimed, in_progress, completed, failed. Omit team_id to use the active team from state.",
|
|
13499
|
-
schema:
|
|
13500
|
-
task_id:
|
|
13501
|
-
status:
|
|
13699
|
+
schema: z51.object({
|
|
13700
|
+
task_id: z51.string().describe("Task ID to update"),
|
|
13701
|
+
status: z51.enum(["pending", "claimed", "in_progress", "completed", "failed"]).describe("New status for the task")
|
|
13502
13702
|
})
|
|
13503
13703
|
}
|
|
13504
13704
|
);
|
|
13505
|
-
const setTaskDependenciesTool =
|
|
13705
|
+
const setTaskDependenciesTool = tool50(
|
|
13506
13706
|
async (input, config) => {
|
|
13507
13707
|
const teamId = resolveTeamId();
|
|
13508
13708
|
const task = await taskListStore.updateTask(teamId, input.task_id, {
|
|
13509
13709
|
dependencies: input.dependencies
|
|
13510
13710
|
});
|
|
13511
13711
|
if (!task) {
|
|
13512
|
-
return new
|
|
13712
|
+
return new ToolMessage8({
|
|
13513
13713
|
content: `Task ${input.task_id} not found in team ${teamId}.`,
|
|
13514
13714
|
tool_call_id: config.toolCall?.id,
|
|
13515
13715
|
name: "set_task_dependencies"
|
|
13516
13716
|
});
|
|
13517
13717
|
}
|
|
13518
|
-
return new
|
|
13718
|
+
return new ToolMessage8({
|
|
13519
13719
|
content: `Task "${task.title}" (${task.id}) dependencies set to [${input.dependencies.join(", ")}].`,
|
|
13520
13720
|
tool_call_id: config.toolCall?.id,
|
|
13521
13721
|
name: "set_task_dependencies"
|
|
@@ -13524,13 +13724,13 @@ IMPORTANT: Assigning to a specific teammate
|
|
|
13524
13724
|
{
|
|
13525
13725
|
name: "set_task_dependencies",
|
|
13526
13726
|
description: 'Set which task IDs must complete before this task can be claimed. Pass an array of task IDs (e.g. ["task-01", "task-02"]). Use to fix task order or add/remove dependencies. Omit team_id to use the active team from state.',
|
|
13527
|
-
schema:
|
|
13528
|
-
task_id:
|
|
13529
|
-
dependencies:
|
|
13727
|
+
schema: z51.object({
|
|
13728
|
+
task_id: z51.string().describe("Task ID to update"),
|
|
13729
|
+
dependencies: z51.array(z51.string()).describe("Task IDs that must complete before this task can be claimed")
|
|
13530
13730
|
})
|
|
13531
13731
|
}
|
|
13532
13732
|
);
|
|
13533
|
-
const checkTasksTool =
|
|
13733
|
+
const checkTasksTool = tool50(
|
|
13534
13734
|
async (input, config) => {
|
|
13535
13735
|
const teamId = resolveTeamId();
|
|
13536
13736
|
const tasks = await taskListStore.getAllTasks(teamId);
|
|
@@ -13539,7 +13739,7 @@ IMPORTANT: Assigning to a specific teammate
|
|
|
13539
13739
|
update: {
|
|
13540
13740
|
tasks: tasksSnapshot,
|
|
13541
13741
|
messages: [
|
|
13542
|
-
new
|
|
13742
|
+
new ToolMessage8({
|
|
13543
13743
|
content: formatTaskSummary(tasks),
|
|
13544
13744
|
tool_call_id: config.toolCall?.id,
|
|
13545
13745
|
name: "check_tasks"
|
|
@@ -13570,12 +13770,12 @@ Task Status Values:
|
|
|
13570
13770
|
- in_progress: Teammate is actively working on this task
|
|
13571
13771
|
- completed: Task finished successfully
|
|
13572
13772
|
- failed: Task encountered an error`,
|
|
13573
|
-
schema:
|
|
13574
|
-
team_id:
|
|
13773
|
+
schema: z51.object({
|
|
13774
|
+
team_id: z51.string().optional().describe("Team ID (omit to use active team)")
|
|
13575
13775
|
})
|
|
13576
13776
|
}
|
|
13577
13777
|
);
|
|
13578
|
-
const sendMessageTool =
|
|
13778
|
+
const sendMessageTool = tool50(
|
|
13579
13779
|
async (input, config) => {
|
|
13580
13780
|
const teamId = resolveTeamId();
|
|
13581
13781
|
await mailboxStore.sendMessage(
|
|
@@ -13585,7 +13785,7 @@ Task Status Values:
|
|
|
13585
13785
|
input.content,
|
|
13586
13786
|
"direct_message" /* DIRECT_MESSAGE */
|
|
13587
13787
|
);
|
|
13588
|
-
return new
|
|
13788
|
+
return new ToolMessage8({
|
|
13589
13789
|
content: `Message sent to ${input.to}.`,
|
|
13590
13790
|
tool_call_id: config.toolCall?.id,
|
|
13591
13791
|
name: "send_message"
|
|
@@ -13594,13 +13794,13 @@ Task Status Values:
|
|
|
13594
13794
|
{
|
|
13595
13795
|
name: "send_message",
|
|
13596
13796
|
description: "Send a message to a specific teammate in the team. Omit team_id to use the active team from state.",
|
|
13597
|
-
schema:
|
|
13598
|
-
to:
|
|
13599
|
-
content:
|
|
13797
|
+
schema: z51.object({
|
|
13798
|
+
to: z51.string().describe("Recipient teammate name"),
|
|
13799
|
+
content: z51.string().describe("Message content")
|
|
13600
13800
|
})
|
|
13601
13801
|
}
|
|
13602
13802
|
);
|
|
13603
|
-
const readMessagesTool =
|
|
13803
|
+
const readMessagesTool = tool50(
|
|
13604
13804
|
async (input, config) => {
|
|
13605
13805
|
const teamId = resolveTeamId();
|
|
13606
13806
|
const formatAndMarkAsRead = async (msgs2) => {
|
|
@@ -13628,7 +13828,7 @@ Task Status Values:
|
|
|
13628
13828
|
if (msgs.length > 0) {
|
|
13629
13829
|
const formatted2 = await formatAndMarkAsRead(msgs);
|
|
13630
13830
|
const allTeamMessages2 = await getAllTeamMessagesForState();
|
|
13631
|
-
const toolMessage2 = new
|
|
13831
|
+
const toolMessage2 = new ToolMessage8({
|
|
13632
13832
|
content: formatted2,
|
|
13633
13833
|
tool_call_id: config.toolCall?.id,
|
|
13634
13834
|
name: "read_messages"
|
|
@@ -13660,7 +13860,7 @@ Task Status Values:
|
|
|
13660
13860
|
);
|
|
13661
13861
|
const allTeamMessages = await getAllTeamMessagesForState();
|
|
13662
13862
|
if (msgs.length === 0) {
|
|
13663
|
-
const toolMessage2 = new
|
|
13863
|
+
const toolMessage2 = new ToolMessage8({
|
|
13664
13864
|
content: "No unread messages from teammates.",
|
|
13665
13865
|
tool_call_id: config.toolCall?.id,
|
|
13666
13866
|
name: "read_messages"
|
|
@@ -13670,7 +13870,7 @@ Task Status Values:
|
|
|
13670
13870
|
});
|
|
13671
13871
|
}
|
|
13672
13872
|
const formatted = await formatAndMarkAsRead(msgs);
|
|
13673
|
-
const toolMessage = new
|
|
13873
|
+
const toolMessage = new ToolMessage8({
|
|
13674
13874
|
content: formatted,
|
|
13675
13875
|
tool_call_id: config.toolCall?.id,
|
|
13676
13876
|
name: "read_messages"
|
|
@@ -13682,12 +13882,12 @@ Task Status Values:
|
|
|
13682
13882
|
{
|
|
13683
13883
|
name: "read_messages",
|
|
13684
13884
|
description: "Read unread messages from teammates. Returns immediately if messages exist, otherwise waits for up to 3 minutes for new messages.",
|
|
13685
|
-
schema:
|
|
13686
|
-
team_id:
|
|
13885
|
+
schema: z51.object({
|
|
13886
|
+
team_id: z51.string().optional().describe("Team ID (omit to use active team)")
|
|
13687
13887
|
})
|
|
13688
13888
|
}
|
|
13689
13889
|
);
|
|
13690
|
-
const disbandTeamTool =
|
|
13890
|
+
const disbandTeamTool = tool50(
|
|
13691
13891
|
async (input, config) => {
|
|
13692
13892
|
const teamId = resolveTeamId();
|
|
13693
13893
|
await mailboxStore.broadcastMessage(
|
|
@@ -13697,7 +13897,7 @@ Task Status Values:
|
|
|
13697
13897
|
"shutdown_request" /* SHUTDOWN_REQUEST */
|
|
13698
13898
|
);
|
|
13699
13899
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
13700
|
-
return new
|
|
13900
|
+
return new ToolMessage8({
|
|
13701
13901
|
content: `Team ${teamId} has been disbanded. All teammates notified and resources cleaned up.`,
|
|
13702
13902
|
tool_call_id: config.toolCall?.id,
|
|
13703
13903
|
name: "disband_team"
|
|
@@ -13708,7 +13908,7 @@ Task Status Values:
|
|
|
13708
13908
|
description: "Disband a team when all work is done. Before calling: (1) Call check_tasks to verify no tasks are still pending/in_progress; (2) if any are, discuss with the team via read_messages and broadcast_message/send_message whether to continue or stop/cancel them; (3) only after alignment (all tasks completed/failed or explicitly stopped), then call this tool. This will: 1) Send a shutdown message to all teammates, 2) Wait briefly for them to clean up, 3) Clear all tasks and messages. Omit team_id to use the active team from state."
|
|
13709
13909
|
}
|
|
13710
13910
|
);
|
|
13711
|
-
const broadcastMessageTool =
|
|
13911
|
+
const broadcastMessageTool = tool50(
|
|
13712
13912
|
async (input, config) => {
|
|
13713
13913
|
const teamId = resolveTeamId();
|
|
13714
13914
|
await mailboxStore.broadcastMessage(
|
|
@@ -13717,7 +13917,7 @@ Task Status Values:
|
|
|
13717
13917
|
input.content,
|
|
13718
13918
|
"broadcast" /* BROADCAST */
|
|
13719
13919
|
);
|
|
13720
|
-
return new
|
|
13920
|
+
return new ToolMessage8({
|
|
13721
13921
|
content: `Broadcast message sent to all teammates.`,
|
|
13722
13922
|
tool_call_id: config.toolCall?.id,
|
|
13723
13923
|
name: "broadcast_message"
|
|
@@ -13726,12 +13926,12 @@ Task Status Values:
|
|
|
13726
13926
|
{
|
|
13727
13927
|
name: "broadcast_message",
|
|
13728
13928
|
description: "Send a message to all teammates at once. Use this to communicate with everyone in the team. Omit team_id to use the active team from state.",
|
|
13729
|
-
schema:
|
|
13730
|
-
content:
|
|
13929
|
+
schema: z51.object({
|
|
13930
|
+
content: z51.string().describe("Message content to broadcast to all teammates")
|
|
13731
13931
|
})
|
|
13732
13932
|
}
|
|
13733
13933
|
);
|
|
13734
|
-
return
|
|
13934
|
+
return createMiddleware16({
|
|
13735
13935
|
name: "teamMiddleware",
|
|
13736
13936
|
tools: [
|
|
13737
13937
|
createTeamTool,
|
|
@@ -13759,37 +13959,37 @@ ${TEAM_SYSTEM_PROMPT}` : TEAM_SYSTEM_PROMPT;
|
|
|
13759
13959
|
}
|
|
13760
13960
|
|
|
13761
13961
|
// src/agent_team/agent_team.ts
|
|
13762
|
-
var TeammateInfoSchema =
|
|
13763
|
-
name:
|
|
13764
|
-
role:
|
|
13765
|
-
description:
|
|
13962
|
+
var TeammateInfoSchema = z52.object({
|
|
13963
|
+
name: z52.string().describe("Teammate name"),
|
|
13964
|
+
role: z52.string().describe("Role category (e.g. research, writing, review)"),
|
|
13965
|
+
description: z52.string().describe("What this teammate focuses on")
|
|
13766
13966
|
});
|
|
13767
|
-
var TeamTaskInfoSchema =
|
|
13768
|
-
id:
|
|
13769
|
-
title:
|
|
13770
|
-
description:
|
|
13771
|
-
status:
|
|
13967
|
+
var TeamTaskInfoSchema = z52.object({
|
|
13968
|
+
id: z52.string(),
|
|
13969
|
+
title: z52.string(),
|
|
13970
|
+
description: z52.string(),
|
|
13971
|
+
status: z52.string().optional()
|
|
13772
13972
|
});
|
|
13773
|
-
var MailboxMessageSchema =
|
|
13774
|
-
id:
|
|
13775
|
-
from:
|
|
13776
|
-
to:
|
|
13777
|
-
content:
|
|
13778
|
-
timestamp:
|
|
13779
|
-
type:
|
|
13780
|
-
read:
|
|
13973
|
+
var MailboxMessageSchema = z52.object({
|
|
13974
|
+
id: z52.string().describe("Unique message identifier"),
|
|
13975
|
+
from: z52.string().describe("Sender agent name"),
|
|
13976
|
+
to: z52.string().describe("Recipient agent name"),
|
|
13977
|
+
content: z52.string().describe("Message content"),
|
|
13978
|
+
timestamp: z52.string().describe("ISO timestamp when the message was sent"),
|
|
13979
|
+
type: z52.nativeEnum(MessageType).describe("Message type"),
|
|
13980
|
+
read: z52.boolean().describe("Whether the recipient has read this message")
|
|
13781
13981
|
});
|
|
13782
|
-
var TeamInfoSchema =
|
|
13783
|
-
teamId:
|
|
13784
|
-
teamLeadId:
|
|
13785
|
-
teammates:
|
|
13786
|
-
tasks:
|
|
13787
|
-
createdAt:
|
|
13982
|
+
var TeamInfoSchema = z52.object({
|
|
13983
|
+
teamId: z52.string().describe("Unique team identifier"),
|
|
13984
|
+
teamLeadId: z52.string().default("team_lead").describe("Team lead agent ID"),
|
|
13985
|
+
teammates: z52.array(TeammateInfoSchema).describe("Active teammates in this team"),
|
|
13986
|
+
tasks: z52.array(TeamTaskInfoSchema).optional().describe("Initial tasks snapshot"),
|
|
13987
|
+
createdAt: z52.string().optional().describe("ISO timestamp when team was created")
|
|
13788
13988
|
});
|
|
13789
|
-
var TEAM_STATE_SCHEMA =
|
|
13989
|
+
var TEAM_STATE_SCHEMA = z52.object({
|
|
13790
13990
|
team: TeamInfoSchema.optional().describe("Team info: teamId, teamLeadId, teammates, tasks. Set when create_team succeeds."),
|
|
13791
|
-
tasks:
|
|
13792
|
-
team_mailbox:
|
|
13991
|
+
tasks: z52.array(TeamTaskInfoSchema).optional().describe("Current tasks snapshot from check_tasks. Updated on each check."),
|
|
13992
|
+
team_mailbox: z52.array(MailboxMessageSchema).optional().describe("All team mailbox messages for display")
|
|
13793
13993
|
});
|
|
13794
13994
|
var TEAM_LEAD_BASE_PROMPT = `You are a team lead that coordinates a team of specialized agents. In order to complete the objective that the user asks of you, you will need to:
|
|
13795
13995
|
|
|
@@ -13870,7 +14070,7 @@ var TeamAgentGraphBuilder = class {
|
|
|
13870
14070
|
const tools = params.tools.map((t) => {
|
|
13871
14071
|
const toolClient = getToolClient(t.key);
|
|
13872
14072
|
return toolClient;
|
|
13873
|
-
}).filter((
|
|
14073
|
+
}).filter((tool51) => tool51 !== void 0);
|
|
13874
14074
|
const teammates = params.subAgents.map((sa) => {
|
|
13875
14075
|
const baseConfig = sa.config;
|
|
13876
14076
|
return {
|
|
@@ -14603,6 +14803,9 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
|
|
|
14603
14803
|
buffer2.expiresAt = Date.now() + this.config.ttl;
|
|
14604
14804
|
buffer2.status = "active" /* ACTIVE */;
|
|
14605
14805
|
}
|
|
14806
|
+
async ensureThread(threadId) {
|
|
14807
|
+
this.getOrCreateBuffer(threadId);
|
|
14808
|
+
}
|
|
14606
14809
|
async completeThread(threadId) {
|
|
14607
14810
|
const buffer2 = this.getBufferIfValid(threadId);
|
|
14608
14811
|
if (buffer2) {
|
|
@@ -16756,10 +16959,10 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
|
|
|
16756
16959
|
}
|
|
16757
16960
|
const tools = await this.getAllTools();
|
|
16758
16961
|
console.log(`[MCP] Registering ${tools.length} tools to Tool Lattice...`);
|
|
16759
|
-
for (const
|
|
16760
|
-
const toolKey = prefix ? `${prefix}_${
|
|
16761
|
-
|
|
16762
|
-
toolLatticeManager.registerExistingTool(toolKey,
|
|
16962
|
+
for (const tool51 of tools) {
|
|
16963
|
+
const toolKey = prefix ? `${prefix}_${tool51.name}` : tool51.name;
|
|
16964
|
+
tool51.name = toolKey;
|
|
16965
|
+
toolLatticeManager.registerExistingTool(toolKey, tool51);
|
|
16763
16966
|
console.log(`[MCP] Registered tool: ${toolKey}`);
|
|
16764
16967
|
}
|
|
16765
16968
|
console.log(`[MCP] Successfully registered ${tools.length} tools to Tool Lattice`);
|
|
@@ -17366,6 +17569,7 @@ var Agent = class {
|
|
|
17366
17569
|
id: messageId
|
|
17367
17570
|
});
|
|
17368
17571
|
}
|
|
17572
|
+
await this.chunkBuffer.ensureThread(this.thread_id);
|
|
17369
17573
|
this.startQueueProcessorIfNeeded().catch((err) => {
|
|
17370
17574
|
console.error("Failed to start queue processor:", err);
|
|
17371
17575
|
});
|
|
@@ -17499,12 +17703,16 @@ var Agent = class {
|
|
|
17499
17703
|
/**
|
|
17500
17704
|
* Abort the current agent execution
|
|
17501
17705
|
* This will cancel any ongoing invoke or stream operations
|
|
17706
|
+
* and clear all queued messages (pending + processing)
|
|
17502
17707
|
*/
|
|
17503
|
-
abort() {
|
|
17708
|
+
async abort() {
|
|
17504
17709
|
if (this.abortController) {
|
|
17505
17710
|
this.abortController.abort();
|
|
17506
17711
|
this.abortController = null;
|
|
17507
17712
|
}
|
|
17713
|
+
await this.chunkBuffer.abortThread(this.thread_id);
|
|
17714
|
+
const store = this.getQueueStore();
|
|
17715
|
+
await store.clearMessages(this.thread_id);
|
|
17508
17716
|
}
|
|
17509
17717
|
/**
|
|
17510
17718
|
* Check if the agent is currently being aborted
|
|
@@ -17812,6 +18020,7 @@ export {
|
|
|
17812
18020
|
createQueryTablesListTool,
|
|
17813
18021
|
createTeamMiddleware,
|
|
17814
18022
|
createTeammateTools,
|
|
18023
|
+
createUnknownToolHandlerMiddleware,
|
|
17815
18024
|
createWidgetMiddleware,
|
|
17816
18025
|
decrypt,
|
|
17817
18026
|
describeCronExpression,
|