@aigne/core 1.63.0-beta.2 → 1.63.0-beta.3
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/CHANGELOG.md +15 -0
- package/lib/cjs/loader/agent-yaml.d.ts +8 -0
- package/lib/cjs/loader/agent-yaml.js +15 -0
- package/lib/cjs/loader/index.d.ts +7 -0
- package/lib/cjs/loader/index.js +22 -0
- package/lib/cjs/prompt/prompt-builder.js +9 -3
- package/lib/cjs/prompt/prompts/afs-builtin-prompt.d.ts +2 -0
- package/lib/cjs/prompt/prompts/afs-builtin-prompt.js +23 -0
- package/lib/cjs/prompt/skills/afs.d.ts +3 -0
- package/lib/cjs/prompt/skills/afs.js +75 -0
- package/lib/dts/loader/agent-yaml.d.ts +8 -0
- package/lib/dts/loader/index.d.ts +7 -0
- package/lib/dts/prompt/prompts/afs-builtin-prompt.d.ts +2 -0
- package/lib/dts/prompt/skills/afs.d.ts +3 -0
- package/lib/esm/loader/agent-yaml.d.ts +8 -0
- package/lib/esm/loader/agent-yaml.js +15 -0
- package/lib/esm/loader/index.d.ts +7 -0
- package/lib/esm/loader/index.js +22 -0
- package/lib/esm/prompt/prompt-builder.js +9 -3
- package/lib/esm/prompt/prompts/afs-builtin-prompt.d.ts +2 -0
- package/lib/esm/prompt/prompts/afs-builtin-prompt.js +20 -0
- package/lib/esm/prompt/skills/afs.d.ts +3 -0
- package/lib/esm/prompt/skills/afs.js +72 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.63.0-beta.3](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.63.0-beta.2...core-v1.63.0-beta.3) (2025-10-11)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **afs:** add module system fs for afs ([#594](https://github.com/AIGNE-io/aigne-framework/issues/594)) ([83c7b65](https://github.com/AIGNE-io/aigne-framework/commit/83c7b6555d21c606a5005eb05f6686882fb8ffa3))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @aigne/afs bumped to 1.1.0-beta
|
|
16
|
+
* @aigne/observability-api bumped to 0.11.2-beta.1
|
|
17
|
+
|
|
3
18
|
## [1.63.0-beta.2](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.63.0-beta.1...core-v1.63.0-beta.2) (2025-10-09)
|
|
4
19
|
|
|
5
20
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AFSOptions } from "@aigne/afs";
|
|
1
2
|
import { type ZodType, z } from "zod";
|
|
2
3
|
import type { AgentHooks, FunctionAgentFn, TaskRenderMode } from "../agents/agent.js";
|
|
3
4
|
import { AIAgentToolChoice } from "../agents/ai-agent.js";
|
|
@@ -19,6 +20,10 @@ export type NestAgentSchema = string | {
|
|
|
19
20
|
defaultInput?: Record<string, any>;
|
|
20
21
|
hooks?: HooksSchema | HooksSchema[];
|
|
21
22
|
} | AgentSchema;
|
|
23
|
+
export type AFSModuleSchema = string | {
|
|
24
|
+
module: string;
|
|
25
|
+
options?: Record<string, any>;
|
|
26
|
+
};
|
|
22
27
|
export interface BaseAgentSchema {
|
|
23
28
|
name?: string;
|
|
24
29
|
description?: string;
|
|
@@ -36,6 +41,9 @@ export interface BaseAgentSchema {
|
|
|
36
41
|
provider: string;
|
|
37
42
|
subscribeTopic?: string[];
|
|
38
43
|
};
|
|
44
|
+
afs?: boolean | (Omit<AFSOptions, "modules"> & {
|
|
45
|
+
modules?: AFSModuleSchema[];
|
|
46
|
+
});
|
|
39
47
|
}
|
|
40
48
|
export type Instructions = {
|
|
41
49
|
role: Exclude<Role, "tool">;
|
|
@@ -53,6 +53,21 @@ async function parseAgentFile(path, data) {
|
|
|
53
53
|
subscribeTopic: (0, schema_js_1.optionalize)(zod_1.z.array(zod_1.z.string())),
|
|
54
54
|
})),
|
|
55
55
|
])),
|
|
56
|
+
afs: (0, schema_js_1.optionalize)(zod_1.z.union([
|
|
57
|
+
zod_1.z.boolean(),
|
|
58
|
+
(0, schema_js_1.camelizeSchema)(zod_1.z.object({
|
|
59
|
+
storage: (0, schema_js_1.optionalize)(zod_1.z.object({
|
|
60
|
+
url: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
61
|
+
})),
|
|
62
|
+
modules: (0, schema_js_1.optionalize)(zod_1.z.array(zod_1.z.union([
|
|
63
|
+
zod_1.z.string(),
|
|
64
|
+
zod_1.z.object({
|
|
65
|
+
module: zod_1.z.string(),
|
|
66
|
+
options: (0, schema_js_1.optionalize)(zod_1.z.record(zod_1.z.any())),
|
|
67
|
+
}),
|
|
68
|
+
]))),
|
|
69
|
+
})),
|
|
70
|
+
])),
|
|
56
71
|
});
|
|
57
72
|
const instructionItemSchema = zod_1.z.union([
|
|
58
73
|
zod_1.z.object({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AFSModule } from "@aigne/afs";
|
|
1
2
|
import { type ZodType, z } from "zod";
|
|
2
3
|
import { Agent, type AgentOptions } from "../agents/agent.js";
|
|
3
4
|
import type { ChatModel } from "../agents/chat-model.js";
|
|
@@ -11,6 +12,12 @@ export interface LoadOptions {
|
|
|
11
12
|
}[];
|
|
12
13
|
model?: ChatModel | ((model?: z.infer<typeof aigneFileSchema>["model"]) => PromiseOrValue<ChatModel | undefined>);
|
|
13
14
|
imageModel?: ImageModel | ((model?: z.infer<typeof aigneFileSchema>["imageModel"]) => PromiseOrValue<ImageModel | undefined>);
|
|
15
|
+
afs?: {
|
|
16
|
+
availableModules?: {
|
|
17
|
+
module: string;
|
|
18
|
+
create: (options?: Record<string, any>) => PromiseOrValue<AFSModule>;
|
|
19
|
+
}[];
|
|
20
|
+
};
|
|
14
21
|
}
|
|
15
22
|
export declare function load(path: string, options?: LoadOptions): Promise<AIGNEOptions>;
|
|
16
23
|
export declare function loadAgent(path: string, options?: LoadOptions, agentOptions?: AgentOptions): Promise<Agent>;
|
package/lib/cjs/loader/index.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.load = load;
|
|
4
4
|
exports.loadAgent = loadAgent;
|
|
5
5
|
exports.loadAIGNEFile = loadAIGNEFile;
|
|
6
|
+
const afs_1 = require("@aigne/afs");
|
|
6
7
|
const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
|
|
7
8
|
const yaml_1 = require("yaml");
|
|
8
9
|
const zod_1 = require("zod");
|
|
@@ -112,6 +113,26 @@ async function parseAgent(path, agent, options, agentOptions) {
|
|
|
112
113
|
const memory = "memory" in agent && options?.memories?.length
|
|
113
114
|
? await loadMemory(options.memories, typeof agent.memory === "object" ? agent.memory.provider : undefined, typeof agent.memory === "object" ? agent.memory : {})
|
|
114
115
|
: undefined;
|
|
116
|
+
let afs;
|
|
117
|
+
if (typeof agent.afs === "boolean") {
|
|
118
|
+
if (agent.afs) {
|
|
119
|
+
afs = new afs_1.AFS();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else if (agent.afs) {
|
|
123
|
+
afs = new afs_1.AFS({
|
|
124
|
+
...agent.afs,
|
|
125
|
+
modules: agent.afs.modules &&
|
|
126
|
+
(await Promise.all(agent.afs.modules.map((m) => {
|
|
127
|
+
const mod = typeof m === "string"
|
|
128
|
+
? options?.afs?.availableModules?.find((mod) => mod.module === m)
|
|
129
|
+
: options?.afs?.availableModules?.find((mod) => mod.module === m.module);
|
|
130
|
+
if (!mod)
|
|
131
|
+
throw new Error(`AFS module not found: ${typeof m === "string" ? m : m.module}`);
|
|
132
|
+
return mod.create(typeof m === "string" ? {} : m.options);
|
|
133
|
+
}))),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
115
136
|
const model = agent.model && typeof options?.model === "function"
|
|
116
137
|
? await options.model(agent.model)
|
|
117
138
|
: undefined;
|
|
@@ -129,6 +150,7 @@ async function parseAgent(path, agent, options, agentOptions) {
|
|
|
129
150
|
...((await parseHooks(path, agent.hooks, options)) ?? []),
|
|
130
151
|
...[agentOptions?.hooks].flat().filter(type_utils_js_1.isNonNullable),
|
|
131
152
|
],
|
|
153
|
+
afs,
|
|
132
154
|
};
|
|
133
155
|
let instructions;
|
|
134
156
|
if ("instructions" in agent && agent.instructions) {
|
|
@@ -12,8 +12,10 @@ const model_js_1 = require("../agents/model.js");
|
|
|
12
12
|
const schema_js_1 = require("../loader/schema.js");
|
|
13
13
|
const json_schema_js_1 = require("../utils/json-schema.js");
|
|
14
14
|
const type_utils_js_1 = require("../utils/type-utils.js");
|
|
15
|
+
const afs_builtin_prompt_js_1 = require("./prompts/afs-builtin-prompt.js");
|
|
15
16
|
const memory_message_template_js_1 = require("./prompts/memory-message-template.js");
|
|
16
17
|
const structured_stream_instructions_js_1 = require("./prompts/structured-stream-instructions.js");
|
|
18
|
+
const afs_js_1 = require("./skills/afs.js");
|
|
17
19
|
const template_js_1 = require("./template.js");
|
|
18
20
|
class PromptBuilder {
|
|
19
21
|
static from(instructions, { workingDir } = {}) {
|
|
@@ -70,7 +72,7 @@ class PromptBuilder {
|
|
|
70
72
|
? undefined
|
|
71
73
|
: this.buildResponseFormat(options),
|
|
72
74
|
outputFileType: options.agent?.outputFileType,
|
|
73
|
-
...this.buildTools(options),
|
|
75
|
+
...(await this.buildTools(options)),
|
|
74
76
|
};
|
|
75
77
|
}
|
|
76
78
|
async buildImagePrompt(options) {
|
|
@@ -101,7 +103,7 @@ class PromptBuilder {
|
|
|
101
103
|
}
|
|
102
104
|
if (options.agent?.afs) {
|
|
103
105
|
const history = await options.agent.afs.list(afs_1.AFSHistory.Path, {
|
|
104
|
-
limit: options.agent.maxRetrieveMemoryCount
|
|
106
|
+
limit: options.agent.maxRetrieveMemoryCount ?? 10,
|
|
105
107
|
orderBy: [["createdAt", "desc"]],
|
|
106
108
|
});
|
|
107
109
|
if (message) {
|
|
@@ -110,6 +112,7 @@ class PromptBuilder {
|
|
|
110
112
|
memories.push(...ms);
|
|
111
113
|
}
|
|
112
114
|
memories.push(...history.list.filter((i) => (0, type_utils_js_1.isNonNullable)(i.content)));
|
|
115
|
+
messages.push(template_js_1.SystemMessageTemplate.from(await (0, afs_builtin_prompt_js_1.getAFSSystemPrompt)(options.agent.afs)));
|
|
113
116
|
}
|
|
114
117
|
if (memories.length)
|
|
115
118
|
messages.push(...(await this.convertMemoriesToMessages(memories, options)));
|
|
@@ -216,11 +219,14 @@ class PromptBuilder {
|
|
|
216
219
|
}
|
|
217
220
|
: undefined;
|
|
218
221
|
}
|
|
219
|
-
buildTools(options) {
|
|
222
|
+
async buildTools(options) {
|
|
220
223
|
const toolAgents = (0, type_utils_js_1.unique)((options.context?.skills ?? [])
|
|
221
224
|
.concat(options.agent?.skills ?? [])
|
|
222
225
|
.concat(options.agent?.memoryAgentsAsTools ? options.agent.memories : [])
|
|
223
226
|
.flatMap((i) => (i.isInvokable ? i : i.skills)), (i) => i.name);
|
|
227
|
+
if (options.agent?.afs) {
|
|
228
|
+
toolAgents.push(...(await (0, afs_js_1.getAFSSkills)(options.agent.afs)));
|
|
229
|
+
}
|
|
224
230
|
const tools = toolAgents.map((i) => ({
|
|
225
231
|
type: "function",
|
|
226
232
|
function: {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAFSSystemPrompt = getAFSSystemPrompt;
|
|
4
|
+
const yaml_1 = require("yaml");
|
|
5
|
+
async function getAFSSystemPrompt(afs) {
|
|
6
|
+
return `\
|
|
7
|
+
|
|
8
|
+
<afs_usage>
|
|
9
|
+
AFS (AIGNE File System) provides tools to interact with a virtual file system, allowing you to list, search, read, and write files. Use these tools to manage and retrieve files as needed.
|
|
10
|
+
|
|
11
|
+
Modules:
|
|
12
|
+
${(0, yaml_1.stringify)(await afs.listModules())}
|
|
13
|
+
|
|
14
|
+
Available Tools:
|
|
15
|
+
1. afs_list: Browse directory contents like filesystem ls/tree command - shows files and folders in a given path
|
|
16
|
+
2. afs_search: Find files by content keywords - use specific keywords related to what you're looking for
|
|
17
|
+
3. afs_read: Read file contents - path must be an exact file path from list or search results
|
|
18
|
+
4. afs_write: Write content to a file in the AFS
|
|
19
|
+
|
|
20
|
+
Workflow: Use afs_list to browse directories, afs_search to find specific content, then afs_read to access file contents.
|
|
21
|
+
</afs_usage>
|
|
22
|
+
`;
|
|
23
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAFSSkills = getAFSSkills;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const agent_js_1 = require("../../agents/agent.js");
|
|
6
|
+
async function getAFSSkills(afs) {
|
|
7
|
+
return [
|
|
8
|
+
agent_js_1.FunctionAgent.from({
|
|
9
|
+
name: "afs_list",
|
|
10
|
+
description: "Browse directory contents in the AFS like filesystem ls/tree command - shows files and folders in the specified path",
|
|
11
|
+
inputSchema: zod_1.z.object({
|
|
12
|
+
path: zod_1.z.string().describe("The directory path to browse (e.g., '/', '/docs', '/src')"),
|
|
13
|
+
options: zod_1.z
|
|
14
|
+
.object({
|
|
15
|
+
recursive: zod_1.z.boolean().optional().describe("Whether to list files recursively"),
|
|
16
|
+
maxDepth: zod_1.z.number().optional().describe("Maximum depth to list files"),
|
|
17
|
+
limit: zod_1.z.number().optional().describe("Maximum number of entries to return"),
|
|
18
|
+
})
|
|
19
|
+
.optional(),
|
|
20
|
+
}),
|
|
21
|
+
process: async (input) => {
|
|
22
|
+
return afs.list(input.path, input.options);
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
agent_js_1.FunctionAgent.from({
|
|
26
|
+
name: "afs_search",
|
|
27
|
+
description: "Find files by searching content using keywords - returns matching files with their paths",
|
|
28
|
+
inputSchema: zod_1.z.object({
|
|
29
|
+
path: zod_1.z.string().describe("The directory path to search in (e.g., '/', '/docs')"),
|
|
30
|
+
query: zod_1.z
|
|
31
|
+
.string()
|
|
32
|
+
.describe("Keywords to search for in file contents (e.g., 'function authentication', 'database config')"),
|
|
33
|
+
options: zod_1.z
|
|
34
|
+
.object({
|
|
35
|
+
limit: zod_1.z.number().optional().describe("Maximum number of entries to return"),
|
|
36
|
+
})
|
|
37
|
+
.optional(),
|
|
38
|
+
}),
|
|
39
|
+
process: async (input) => {
|
|
40
|
+
return afs.search(input.path, input.query, input.options);
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
agent_js_1.FunctionAgent.from({
|
|
44
|
+
name: "afs_read",
|
|
45
|
+
description: "Read file contents from the AFS - path must be an exact file path from list or search results",
|
|
46
|
+
inputSchema: zod_1.z.object({
|
|
47
|
+
path: zod_1.z
|
|
48
|
+
.string()
|
|
49
|
+
.describe("Exact file path from list or search results (e.g., '/docs/api.md', '/src/utils/helper.js')"),
|
|
50
|
+
}),
|
|
51
|
+
process: async (input) => {
|
|
52
|
+
const file = await afs.read(input.path);
|
|
53
|
+
return {
|
|
54
|
+
file,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
agent_js_1.FunctionAgent.from({
|
|
59
|
+
name: "afs_write",
|
|
60
|
+
description: "Create or update a file in the AFS with new content - overwrites existing files",
|
|
61
|
+
inputSchema: zod_1.z.object({
|
|
62
|
+
path: zod_1.z
|
|
63
|
+
.string()
|
|
64
|
+
.describe("Full file path where to write content (e.g., '/docs/new-file.md', '/src/component.js')"),
|
|
65
|
+
content: zod_1.z.string().describe("The text content to write to the file"),
|
|
66
|
+
}),
|
|
67
|
+
process: async (input) => {
|
|
68
|
+
const file = await afs.write(input.path, {
|
|
69
|
+
content: input.content,
|
|
70
|
+
});
|
|
71
|
+
return { file };
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
];
|
|
75
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AFSOptions } from "@aigne/afs";
|
|
1
2
|
import { type ZodType, z } from "zod";
|
|
2
3
|
import type { AgentHooks, FunctionAgentFn, TaskRenderMode } from "../agents/agent.js";
|
|
3
4
|
import { AIAgentToolChoice } from "../agents/ai-agent.js";
|
|
@@ -19,6 +20,10 @@ export type NestAgentSchema = string | {
|
|
|
19
20
|
defaultInput?: Record<string, any>;
|
|
20
21
|
hooks?: HooksSchema | HooksSchema[];
|
|
21
22
|
} | AgentSchema;
|
|
23
|
+
export type AFSModuleSchema = string | {
|
|
24
|
+
module: string;
|
|
25
|
+
options?: Record<string, any>;
|
|
26
|
+
};
|
|
22
27
|
export interface BaseAgentSchema {
|
|
23
28
|
name?: string;
|
|
24
29
|
description?: string;
|
|
@@ -36,6 +41,9 @@ export interface BaseAgentSchema {
|
|
|
36
41
|
provider: string;
|
|
37
42
|
subscribeTopic?: string[];
|
|
38
43
|
};
|
|
44
|
+
afs?: boolean | (Omit<AFSOptions, "modules"> & {
|
|
45
|
+
modules?: AFSModuleSchema[];
|
|
46
|
+
});
|
|
39
47
|
}
|
|
40
48
|
export type Instructions = {
|
|
41
49
|
role: Exclude<Role, "tool">;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AFSModule } from "@aigne/afs";
|
|
1
2
|
import { type ZodType, z } from "zod";
|
|
2
3
|
import { Agent, type AgentOptions } from "../agents/agent.js";
|
|
3
4
|
import type { ChatModel } from "../agents/chat-model.js";
|
|
@@ -11,6 +12,12 @@ export interface LoadOptions {
|
|
|
11
12
|
}[];
|
|
12
13
|
model?: ChatModel | ((model?: z.infer<typeof aigneFileSchema>["model"]) => PromiseOrValue<ChatModel | undefined>);
|
|
13
14
|
imageModel?: ImageModel | ((model?: z.infer<typeof aigneFileSchema>["imageModel"]) => PromiseOrValue<ImageModel | undefined>);
|
|
15
|
+
afs?: {
|
|
16
|
+
availableModules?: {
|
|
17
|
+
module: string;
|
|
18
|
+
create: (options?: Record<string, any>) => PromiseOrValue<AFSModule>;
|
|
19
|
+
}[];
|
|
20
|
+
};
|
|
14
21
|
}
|
|
15
22
|
export declare function load(path: string, options?: LoadOptions): Promise<AIGNEOptions>;
|
|
16
23
|
export declare function loadAgent(path: string, options?: LoadOptions, agentOptions?: AgentOptions): Promise<Agent>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AFSOptions } from "@aigne/afs";
|
|
1
2
|
import { type ZodType, z } from "zod";
|
|
2
3
|
import type { AgentHooks, FunctionAgentFn, TaskRenderMode } from "../agents/agent.js";
|
|
3
4
|
import { AIAgentToolChoice } from "../agents/ai-agent.js";
|
|
@@ -19,6 +20,10 @@ export type NestAgentSchema = string | {
|
|
|
19
20
|
defaultInput?: Record<string, any>;
|
|
20
21
|
hooks?: HooksSchema | HooksSchema[];
|
|
21
22
|
} | AgentSchema;
|
|
23
|
+
export type AFSModuleSchema = string | {
|
|
24
|
+
module: string;
|
|
25
|
+
options?: Record<string, any>;
|
|
26
|
+
};
|
|
22
27
|
export interface BaseAgentSchema {
|
|
23
28
|
name?: string;
|
|
24
29
|
description?: string;
|
|
@@ -36,6 +41,9 @@ export interface BaseAgentSchema {
|
|
|
36
41
|
provider: string;
|
|
37
42
|
subscribeTopic?: string[];
|
|
38
43
|
};
|
|
44
|
+
afs?: boolean | (Omit<AFSOptions, "modules"> & {
|
|
45
|
+
modules?: AFSModuleSchema[];
|
|
46
|
+
});
|
|
39
47
|
}
|
|
40
48
|
export type Instructions = {
|
|
41
49
|
role: Exclude<Role, "tool">;
|
|
@@ -49,6 +49,21 @@ export async function parseAgentFile(path, data) {
|
|
|
49
49
|
subscribeTopic: optionalize(z.array(z.string())),
|
|
50
50
|
})),
|
|
51
51
|
])),
|
|
52
|
+
afs: optionalize(z.union([
|
|
53
|
+
z.boolean(),
|
|
54
|
+
camelizeSchema(z.object({
|
|
55
|
+
storage: optionalize(z.object({
|
|
56
|
+
url: optionalize(z.string()),
|
|
57
|
+
})),
|
|
58
|
+
modules: optionalize(z.array(z.union([
|
|
59
|
+
z.string(),
|
|
60
|
+
z.object({
|
|
61
|
+
module: z.string(),
|
|
62
|
+
options: optionalize(z.record(z.any())),
|
|
63
|
+
}),
|
|
64
|
+
]))),
|
|
65
|
+
})),
|
|
66
|
+
])),
|
|
52
67
|
});
|
|
53
68
|
const instructionItemSchema = z.union([
|
|
54
69
|
z.object({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AFSModule } from "@aigne/afs";
|
|
1
2
|
import { type ZodType, z } from "zod";
|
|
2
3
|
import { Agent, type AgentOptions } from "../agents/agent.js";
|
|
3
4
|
import type { ChatModel } from "../agents/chat-model.js";
|
|
@@ -11,6 +12,12 @@ export interface LoadOptions {
|
|
|
11
12
|
}[];
|
|
12
13
|
model?: ChatModel | ((model?: z.infer<typeof aigneFileSchema>["model"]) => PromiseOrValue<ChatModel | undefined>);
|
|
13
14
|
imageModel?: ImageModel | ((model?: z.infer<typeof aigneFileSchema>["imageModel"]) => PromiseOrValue<ImageModel | undefined>);
|
|
15
|
+
afs?: {
|
|
16
|
+
availableModules?: {
|
|
17
|
+
module: string;
|
|
18
|
+
create: (options?: Record<string, any>) => PromiseOrValue<AFSModule>;
|
|
19
|
+
}[];
|
|
20
|
+
};
|
|
14
21
|
}
|
|
15
22
|
export declare function load(path: string, options?: LoadOptions): Promise<AIGNEOptions>;
|
|
16
23
|
export declare function loadAgent(path: string, options?: LoadOptions, agentOptions?: AgentOptions): Promise<Agent>;
|
package/lib/esm/loader/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AFS } from "@aigne/afs";
|
|
1
2
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
2
3
|
import { parse } from "yaml";
|
|
3
4
|
import { z } from "zod";
|
|
@@ -107,6 +108,26 @@ async function parseAgent(path, agent, options, agentOptions) {
|
|
|
107
108
|
const memory = "memory" in agent && options?.memories?.length
|
|
108
109
|
? await loadMemory(options.memories, typeof agent.memory === "object" ? agent.memory.provider : undefined, typeof agent.memory === "object" ? agent.memory : {})
|
|
109
110
|
: undefined;
|
|
111
|
+
let afs;
|
|
112
|
+
if (typeof agent.afs === "boolean") {
|
|
113
|
+
if (agent.afs) {
|
|
114
|
+
afs = new AFS();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (agent.afs) {
|
|
118
|
+
afs = new AFS({
|
|
119
|
+
...agent.afs,
|
|
120
|
+
modules: agent.afs.modules &&
|
|
121
|
+
(await Promise.all(agent.afs.modules.map((m) => {
|
|
122
|
+
const mod = typeof m === "string"
|
|
123
|
+
? options?.afs?.availableModules?.find((mod) => mod.module === m)
|
|
124
|
+
: options?.afs?.availableModules?.find((mod) => mod.module === m.module);
|
|
125
|
+
if (!mod)
|
|
126
|
+
throw new Error(`AFS module not found: ${typeof m === "string" ? m : m.module}`);
|
|
127
|
+
return mod.create(typeof m === "string" ? {} : m.options);
|
|
128
|
+
}))),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
110
131
|
const model = agent.model && typeof options?.model === "function"
|
|
111
132
|
? await options.model(agent.model)
|
|
112
133
|
: undefined;
|
|
@@ -124,6 +145,7 @@ async function parseAgent(path, agent, options, agentOptions) {
|
|
|
124
145
|
...((await parseHooks(path, agent.hooks, options)) ?? []),
|
|
125
146
|
...[agentOptions?.hooks].flat().filter(isNonNullable),
|
|
126
147
|
],
|
|
148
|
+
afs,
|
|
127
149
|
};
|
|
128
150
|
let instructions;
|
|
129
151
|
if ("instructions" in agent && agent.instructions) {
|
|
@@ -9,8 +9,10 @@ import { fileUnionContentsSchema } from "../agents/model.js";
|
|
|
9
9
|
import { optionalize } from "../loader/schema.js";
|
|
10
10
|
import { outputSchemaToResponseFormatSchema } from "../utils/json-schema.js";
|
|
11
11
|
import { checkArguments, flat, isNonNullable, isRecord, unique } from "../utils/type-utils.js";
|
|
12
|
+
import { getAFSSystemPrompt } from "./prompts/afs-builtin-prompt.js";
|
|
12
13
|
import { MEMORY_MESSAGE_TEMPLATE } from "./prompts/memory-message-template.js";
|
|
13
14
|
import { STRUCTURED_STREAM_INSTRUCTIONS } from "./prompts/structured-stream-instructions.js";
|
|
15
|
+
import { getAFSSkills } from "./skills/afs.js";
|
|
14
16
|
import { AgentMessageTemplate, ChatMessagesTemplate, PromptTemplate, SystemMessageTemplate, UserMessageTemplate, } from "./template.js";
|
|
15
17
|
export class PromptBuilder {
|
|
16
18
|
static from(instructions, { workingDir } = {}) {
|
|
@@ -67,7 +69,7 @@ export class PromptBuilder {
|
|
|
67
69
|
? undefined
|
|
68
70
|
: this.buildResponseFormat(options),
|
|
69
71
|
outputFileType: options.agent?.outputFileType,
|
|
70
|
-
...this.buildTools(options),
|
|
72
|
+
...(await this.buildTools(options)),
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
async buildImagePrompt(options) {
|
|
@@ -98,7 +100,7 @@ export class PromptBuilder {
|
|
|
98
100
|
}
|
|
99
101
|
if (options.agent?.afs) {
|
|
100
102
|
const history = await options.agent.afs.list(AFSHistory.Path, {
|
|
101
|
-
limit: options.agent.maxRetrieveMemoryCount
|
|
103
|
+
limit: options.agent.maxRetrieveMemoryCount ?? 10,
|
|
102
104
|
orderBy: [["createdAt", "desc"]],
|
|
103
105
|
});
|
|
104
106
|
if (message) {
|
|
@@ -107,6 +109,7 @@ export class PromptBuilder {
|
|
|
107
109
|
memories.push(...ms);
|
|
108
110
|
}
|
|
109
111
|
memories.push(...history.list.filter((i) => isNonNullable(i.content)));
|
|
112
|
+
messages.push(SystemMessageTemplate.from(await getAFSSystemPrompt(options.agent.afs)));
|
|
110
113
|
}
|
|
111
114
|
if (memories.length)
|
|
112
115
|
messages.push(...(await this.convertMemoriesToMessages(memories, options)));
|
|
@@ -213,11 +216,14 @@ export class PromptBuilder {
|
|
|
213
216
|
}
|
|
214
217
|
: undefined;
|
|
215
218
|
}
|
|
216
|
-
buildTools(options) {
|
|
219
|
+
async buildTools(options) {
|
|
217
220
|
const toolAgents = unique((options.context?.skills ?? [])
|
|
218
221
|
.concat(options.agent?.skills ?? [])
|
|
219
222
|
.concat(options.agent?.memoryAgentsAsTools ? options.agent.memories : [])
|
|
220
223
|
.flatMap((i) => (i.isInvokable ? i : i.skills)), (i) => i.name);
|
|
224
|
+
if (options.agent?.afs) {
|
|
225
|
+
toolAgents.push(...(await getAFSSkills(options.agent.afs)));
|
|
226
|
+
}
|
|
221
227
|
const tools = toolAgents.map((i) => ({
|
|
222
228
|
type: "function",
|
|
223
229
|
function: {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { stringify } from "yaml";
|
|
2
|
+
export async function getAFSSystemPrompt(afs) {
|
|
3
|
+
return `\
|
|
4
|
+
|
|
5
|
+
<afs_usage>
|
|
6
|
+
AFS (AIGNE File System) provides tools to interact with a virtual file system, allowing you to list, search, read, and write files. Use these tools to manage and retrieve files as needed.
|
|
7
|
+
|
|
8
|
+
Modules:
|
|
9
|
+
${stringify(await afs.listModules())}
|
|
10
|
+
|
|
11
|
+
Available Tools:
|
|
12
|
+
1. afs_list: Browse directory contents like filesystem ls/tree command - shows files and folders in a given path
|
|
13
|
+
2. afs_search: Find files by content keywords - use specific keywords related to what you're looking for
|
|
14
|
+
3. afs_read: Read file contents - path must be an exact file path from list or search results
|
|
15
|
+
4. afs_write: Write content to a file in the AFS
|
|
16
|
+
|
|
17
|
+
Workflow: Use afs_list to browse directories, afs_search to find specific content, then afs_read to access file contents.
|
|
18
|
+
</afs_usage>
|
|
19
|
+
`;
|
|
20
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { FunctionAgent } from "../../agents/agent.js";
|
|
3
|
+
export async function getAFSSkills(afs) {
|
|
4
|
+
return [
|
|
5
|
+
FunctionAgent.from({
|
|
6
|
+
name: "afs_list",
|
|
7
|
+
description: "Browse directory contents in the AFS like filesystem ls/tree command - shows files and folders in the specified path",
|
|
8
|
+
inputSchema: z.object({
|
|
9
|
+
path: z.string().describe("The directory path to browse (e.g., '/', '/docs', '/src')"),
|
|
10
|
+
options: z
|
|
11
|
+
.object({
|
|
12
|
+
recursive: z.boolean().optional().describe("Whether to list files recursively"),
|
|
13
|
+
maxDepth: z.number().optional().describe("Maximum depth to list files"),
|
|
14
|
+
limit: z.number().optional().describe("Maximum number of entries to return"),
|
|
15
|
+
})
|
|
16
|
+
.optional(),
|
|
17
|
+
}),
|
|
18
|
+
process: async (input) => {
|
|
19
|
+
return afs.list(input.path, input.options);
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
FunctionAgent.from({
|
|
23
|
+
name: "afs_search",
|
|
24
|
+
description: "Find files by searching content using keywords - returns matching files with their paths",
|
|
25
|
+
inputSchema: z.object({
|
|
26
|
+
path: z.string().describe("The directory path to search in (e.g., '/', '/docs')"),
|
|
27
|
+
query: z
|
|
28
|
+
.string()
|
|
29
|
+
.describe("Keywords to search for in file contents (e.g., 'function authentication', 'database config')"),
|
|
30
|
+
options: z
|
|
31
|
+
.object({
|
|
32
|
+
limit: z.number().optional().describe("Maximum number of entries to return"),
|
|
33
|
+
})
|
|
34
|
+
.optional(),
|
|
35
|
+
}),
|
|
36
|
+
process: async (input) => {
|
|
37
|
+
return afs.search(input.path, input.query, input.options);
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
FunctionAgent.from({
|
|
41
|
+
name: "afs_read",
|
|
42
|
+
description: "Read file contents from the AFS - path must be an exact file path from list or search results",
|
|
43
|
+
inputSchema: z.object({
|
|
44
|
+
path: z
|
|
45
|
+
.string()
|
|
46
|
+
.describe("Exact file path from list or search results (e.g., '/docs/api.md', '/src/utils/helper.js')"),
|
|
47
|
+
}),
|
|
48
|
+
process: async (input) => {
|
|
49
|
+
const file = await afs.read(input.path);
|
|
50
|
+
return {
|
|
51
|
+
file,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
FunctionAgent.from({
|
|
56
|
+
name: "afs_write",
|
|
57
|
+
description: "Create or update a file in the AFS with new content - overwrites existing files",
|
|
58
|
+
inputSchema: z.object({
|
|
59
|
+
path: z
|
|
60
|
+
.string()
|
|
61
|
+
.describe("Full file path where to write content (e.g., '/docs/new-file.md', '/src/component.js')"),
|
|
62
|
+
content: z.string().describe("The text content to write to the file"),
|
|
63
|
+
}),
|
|
64
|
+
process: async (input) => {
|
|
65
|
+
const file = await afs.write(input.path, {
|
|
66
|
+
content: input.content,
|
|
67
|
+
});
|
|
68
|
+
return { file };
|
|
69
|
+
},
|
|
70
|
+
}),
|
|
71
|
+
];
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/core",
|
|
3
|
-
"version": "1.63.0-beta.
|
|
3
|
+
"version": "1.63.0-beta.3",
|
|
4
4
|
"description": "The functional core of agentic AI",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
"zod": "^3.25.67",
|
|
93
93
|
"zod-from-json-schema": "^0.0.5",
|
|
94
94
|
"zod-to-json-schema": "^3.24.6",
|
|
95
|
-
"@aigne/
|
|
95
|
+
"@aigne/observability-api": "^0.11.2-beta.1",
|
|
96
96
|
"@aigne/platform-helpers": "^0.6.3",
|
|
97
|
-
"@aigne/
|
|
97
|
+
"@aigne/afs": "^1.1.0-beta"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@types/bun": "^1.2.22",
|