@aigne/core 1.67.0 → 1.68.0-beta
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 +20 -0
- package/lib/cjs/agents/agent.d.ts +22 -8
- package/lib/cjs/agents/agent.js +55 -2
- package/lib/cjs/aigne/aigne.js +1 -1
- package/lib/cjs/aigne/context.d.ts +1 -0
- package/lib/cjs/aigne/context.js +18 -0
- package/lib/cjs/loader/agent-yaml.d.ts +1 -2
- package/lib/cjs/loader/agent-yaml.js +2 -9
- package/lib/cjs/loader/index.d.ts +1 -0
- package/lib/cjs/loader/index.js +10 -14
- package/lib/cjs/prompt/prompt-builder.js +43 -13
- package/lib/cjs/prompt/prompts/afs-builtin-prompt.d.ts +1 -0
- package/lib/cjs/prompt/prompts/afs-builtin-prompt.js +16 -6
- package/lib/cjs/prompt/skills/afs.js +13 -0
- package/lib/dts/agents/agent.d.ts +22 -8
- package/lib/dts/aigne/context.d.ts +1 -0
- package/lib/dts/loader/agent-yaml.d.ts +1 -2
- package/lib/dts/loader/index.d.ts +1 -0
- package/lib/dts/prompt/prompts/afs-builtin-prompt.d.ts +1 -0
- package/lib/esm/agents/agent.d.ts +22 -8
- package/lib/esm/agents/agent.js +56 -3
- package/lib/esm/aigne/aigne.js +1 -1
- package/lib/esm/aigne/context.d.ts +1 -0
- package/lib/esm/aigne/context.js +18 -0
- package/lib/esm/loader/agent-yaml.d.ts +1 -2
- package/lib/esm/loader/agent-yaml.js +2 -9
- package/lib/esm/loader/index.d.ts +1 -0
- package/lib/esm/loader/index.js +10 -14
- package/lib/esm/prompt/prompt-builder.js +44 -14
- package/lib/esm/prompt/prompts/afs-builtin-prompt.d.ts +1 -0
- package/lib/esm/prompt/prompts/afs-builtin-prompt.js +15 -6
- package/lib/esm/prompt/skills/afs.js +13 -0
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.68.0-beta](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.67.0...core-v1.68.0-beta) (2025-11-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* support mount mcp agent into AFS ([#740](https://github.com/AIGNE-io/aigne-framework/issues/740)) ([6d474fc](https://github.com/AIGNE-io/aigne-framework/commit/6d474fc05845a15e2c3e8fa97727b409bdd70945))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* properly handle SIGINT to flush observability data before exit ([#739](https://github.com/AIGNE-io/aigne-framework/issues/739)) ([99b4503](https://github.com/AIGNE-io/aigne-framework/commit/99b45033d5f3bcc1f830b583f9cca7258b00606f))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Dependencies
|
|
17
|
+
|
|
18
|
+
* The following workspace dependencies were updated
|
|
19
|
+
* dependencies
|
|
20
|
+
* @aigne/afs bumped to 1.2.0-beta
|
|
21
|
+
* @aigne/afs-history bumped to 1.0.0
|
|
22
|
+
|
|
3
23
|
## [1.67.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.67.0-beta.4...core-v1.67.0) (2025-11-12)
|
|
4
24
|
|
|
5
25
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AFS, type AFSOptions } from "@aigne/afs";
|
|
1
|
+
import { AFS, type AFSEntry, type AFSListOptions, type AFSModule, type AFSOptions, type AFSSearchOptions } from "@aigne/afs";
|
|
2
2
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
3
3
|
import type * as prompts from "@inquirer/prompts";
|
|
4
4
|
import { type ZodObject, type ZodType } from "zod";
|
|
@@ -123,7 +123,6 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
|
|
|
123
123
|
*/
|
|
124
124
|
memory?: MemoryAgent | MemoryAgent[];
|
|
125
125
|
afs?: true | AFSOptions | AFS | ((afs: AFS) => AFS);
|
|
126
|
-
afsConfig?: AFSConfig;
|
|
127
126
|
asyncMemoryRecord?: boolean;
|
|
128
127
|
/**
|
|
129
128
|
* Maximum number of memory items to retrieve
|
|
@@ -132,10 +131,6 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
|
|
|
132
131
|
hooks?: AgentHooks<I, O> | AgentHooks<I, O>[];
|
|
133
132
|
retryOnError?: Agent<I, O>["retryOnError"] | boolean;
|
|
134
133
|
}
|
|
135
|
-
export interface AFSConfig {
|
|
136
|
-
injectHistory?: boolean;
|
|
137
|
-
historyWindowSize?: number;
|
|
138
|
-
}
|
|
139
134
|
export declare const agentOptionsSchema: ZodObject<{
|
|
140
135
|
[key in keyof AgentOptions]: ZodType<AgentOptions[key]>;
|
|
141
136
|
}>;
|
|
@@ -200,7 +195,7 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
|
|
|
200
195
|
* Here's an example of how to create a custom agent:
|
|
201
196
|
* {@includeCode ../../test/agents/agent.test.ts#example-custom-agent}
|
|
202
197
|
*/
|
|
203
|
-
export declare abstract class Agent<I extends Message = any, O extends Message = any> {
|
|
198
|
+
export declare abstract class Agent<I extends Message = any, O extends Message = any> implements AFSModule {
|
|
204
199
|
/**
|
|
205
200
|
* Custom object inspection behavior
|
|
206
201
|
*
|
|
@@ -218,7 +213,6 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
218
213
|
*/
|
|
219
214
|
readonly memories: MemoryAgent[];
|
|
220
215
|
afs?: AFS;
|
|
221
|
-
afsConfig?: AFSConfig;
|
|
222
216
|
asyncMemoryRecord?: boolean;
|
|
223
217
|
tag?: string;
|
|
224
218
|
/**
|
|
@@ -564,6 +558,26 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
564
558
|
* {@includeCode ../../test/agents/agent.test.ts#example-agent-shutdown-by-using}
|
|
565
559
|
*/
|
|
566
560
|
[Symbol.asyncDispose](): Promise<void>;
|
|
561
|
+
/** For AFSModule interface **/
|
|
562
|
+
private agentToAFSEntry;
|
|
563
|
+
private findAgentByAFSPath;
|
|
564
|
+
list(_path: string, _options?: AFSListOptions): Promise<{
|
|
565
|
+
list: AFSEntry[];
|
|
566
|
+
message?: string;
|
|
567
|
+
}>;
|
|
568
|
+
read(path: string): Promise<{
|
|
569
|
+
result?: AFSEntry;
|
|
570
|
+
message?: string;
|
|
571
|
+
}>;
|
|
572
|
+
search(path: string, _query: string, options?: AFSSearchOptions): Promise<{
|
|
573
|
+
list: AFSEntry[];
|
|
574
|
+
message?: string;
|
|
575
|
+
}>;
|
|
576
|
+
exec(path: string, args: Record<string, any>, options: {
|
|
577
|
+
context: Context;
|
|
578
|
+
}): Promise<{
|
|
579
|
+
result: Record<string, any>;
|
|
580
|
+
}>;
|
|
567
581
|
}
|
|
568
582
|
export type AgentInput<T extends Agent> = T extends Agent<infer I, any> ? I : never;
|
|
569
583
|
export type AgentOutput<T extends Agent> = T extends Agent<any, infer O> ? O : never;
|
package/lib/cjs/agents/agent.js
CHANGED
|
@@ -50,7 +50,9 @@ const afs_1 = require("@aigne/afs");
|
|
|
50
50
|
const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
|
|
51
51
|
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
|
|
52
52
|
const nunjucks_1 = __importDefault(require("nunjucks"));
|
|
53
|
+
const ufo_1 = require("ufo");
|
|
53
54
|
const zod_1 = require("zod");
|
|
55
|
+
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
54
56
|
const agent_utils_js_1 = require("../utils/agent-utils.js");
|
|
55
57
|
const json_schema_js_1 = require("../utils/json-schema.js");
|
|
56
58
|
const logger_js_1 = require("../utils/logger.js");
|
|
@@ -161,7 +163,6 @@ class Agent {
|
|
|
161
163
|
: options.afs instanceof afs_1.AFS
|
|
162
164
|
? options.afs
|
|
163
165
|
: new afs_1.AFS(options.afs);
|
|
164
|
-
this.afsConfig = options.afsConfig;
|
|
165
166
|
this.asyncMemoryRecord = options.asyncMemoryRecord;
|
|
166
167
|
this.maxRetrieveMemoryCount = options.maxRetrieveMemoryCount;
|
|
167
168
|
this.hooks = (0, type_utils_js_1.flat)(options.hooks);
|
|
@@ -180,7 +181,6 @@ class Agent {
|
|
|
180
181
|
*/
|
|
181
182
|
memories = [];
|
|
182
183
|
afs;
|
|
183
|
-
afsConfig;
|
|
184
184
|
asyncMemoryRecord;
|
|
185
185
|
tag;
|
|
186
186
|
/**
|
|
@@ -737,6 +737,59 @@ class Agent {
|
|
|
737
737
|
async [Symbol.asyncDispose]() {
|
|
738
738
|
await this.shutdown();
|
|
739
739
|
}
|
|
740
|
+
/** For AFSModule interface **/
|
|
741
|
+
agentToAFSEntry(agent) {
|
|
742
|
+
return {
|
|
743
|
+
id: `/${this.name}/${agent.name}`,
|
|
744
|
+
path: agent === this ? "/" : (0, ufo_1.joinURL)("/", agent.name),
|
|
745
|
+
summary: agent.description,
|
|
746
|
+
metadata: {
|
|
747
|
+
execute: agent.isInvokable
|
|
748
|
+
? {
|
|
749
|
+
name: agent.name,
|
|
750
|
+
description: agent.description,
|
|
751
|
+
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(agent.inputSchema),
|
|
752
|
+
outputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(agent.outputSchema),
|
|
753
|
+
}
|
|
754
|
+
: undefined,
|
|
755
|
+
},
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
findAgentByAFSPath(path) {
|
|
759
|
+
let agent;
|
|
760
|
+
if (path === "/") {
|
|
761
|
+
agent = this;
|
|
762
|
+
}
|
|
763
|
+
else {
|
|
764
|
+
const name = path.split("/")[1];
|
|
765
|
+
agent = this.skills.find((s) => s.name === name);
|
|
766
|
+
}
|
|
767
|
+
return agent;
|
|
768
|
+
}
|
|
769
|
+
// TODO: support list skills inside agent path, and use options to filter skills
|
|
770
|
+
async list(_path, _options) {
|
|
771
|
+
const agents = [this, ...this.skills];
|
|
772
|
+
return { list: agents.map((agent) => this.agentToAFSEntry(agent)) };
|
|
773
|
+
}
|
|
774
|
+
async read(path) {
|
|
775
|
+
const agent = this.findAgentByAFSPath(path);
|
|
776
|
+
if (!agent) {
|
|
777
|
+
return { message: `Agent not found at path: ${path}` };
|
|
778
|
+
}
|
|
779
|
+
return {
|
|
780
|
+
result: this.agentToAFSEntry(agent),
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
// TODO: implement search inside agent skills
|
|
784
|
+
async search(path, _query, options) {
|
|
785
|
+
return this.list(path, options);
|
|
786
|
+
}
|
|
787
|
+
async exec(path, args, options) {
|
|
788
|
+
const agent = this.findAgentByAFSPath(path);
|
|
789
|
+
if (!agent)
|
|
790
|
+
throw new Error(`Agent not found at path: ${path}`);
|
|
791
|
+
return { result: await options.context.invoke(agent, args) };
|
|
792
|
+
}
|
|
740
793
|
}
|
|
741
794
|
exports.Agent = Agent;
|
|
742
795
|
/**
|
package/lib/cjs/aigne/aigne.js
CHANGED
|
@@ -221,7 +221,7 @@ class AIGNE {
|
|
|
221
221
|
* This registers handlers for SIGINT and exit events to properly terminate all agents.
|
|
222
222
|
*/
|
|
223
223
|
initProcessExitHandler() {
|
|
224
|
-
const shutdownAndExit = () => this.shutdown()
|
|
224
|
+
const shutdownAndExit = () => this.shutdown();
|
|
225
225
|
process.on("SIGINT", shutdownAndExit);
|
|
226
226
|
process.on("exit", shutdownAndExit);
|
|
227
227
|
}
|
|
@@ -182,6 +182,7 @@ export declare class AIGNEContext implements Context {
|
|
|
182
182
|
subscribe: Context["subscribe"];
|
|
183
183
|
unsubscribe: Context["unsubscribe"];
|
|
184
184
|
emit<K extends keyof ContextEmitEventMap>(eventName: K, ...args: Args<K, ContextEmitEventMap>): boolean;
|
|
185
|
+
initProcessExitHandler(): void;
|
|
185
186
|
private trace;
|
|
186
187
|
on<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
|
|
187
188
|
once<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
|
package/lib/cjs/aigne/context.js
CHANGED
|
@@ -46,6 +46,7 @@ class AIGNEContext {
|
|
|
46
46
|
this.rootId = this.span?.spanContext?.().traceId ?? (0, uuid_1.v7)();
|
|
47
47
|
}
|
|
48
48
|
this.id = this.span?.spanContext()?.spanId ?? (0, uuid_1.v7)();
|
|
49
|
+
this.initProcessExitHandler();
|
|
49
50
|
}
|
|
50
51
|
id;
|
|
51
52
|
parentId;
|
|
@@ -201,6 +202,23 @@ class AIGNEContext {
|
|
|
201
202
|
this.trace(eventName, args, b);
|
|
202
203
|
return this.internal.events.emit(eventName, ...newArgs);
|
|
203
204
|
}
|
|
205
|
+
initProcessExitHandler() {
|
|
206
|
+
process.on("SIGINT", async () => {
|
|
207
|
+
try {
|
|
208
|
+
if (process.env.AIGNE_OBSERVABILITY_DISABLED)
|
|
209
|
+
return;
|
|
210
|
+
const span = this.span;
|
|
211
|
+
if (!span)
|
|
212
|
+
return;
|
|
213
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: "SIGINT" });
|
|
214
|
+
span.end();
|
|
215
|
+
await this.observer?.flush(span);
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
process.exit(0);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
204
222
|
async trace(eventName, args, b) {
|
|
205
223
|
if (process.env.AIGNE_OBSERVABILITY_DISABLED)
|
|
206
224
|
return;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AFSOptions } from "@aigne/afs";
|
|
2
2
|
import { type ZodType, z } from "zod";
|
|
3
|
-
import type {
|
|
3
|
+
import type { AgentHooks, FunctionAgentFn, TaskRenderMode } from "../agents/agent.js";
|
|
4
4
|
import { AIAgentToolChoice } from "../agents/ai-agent.js";
|
|
5
5
|
import { type Role } from "../agents/chat-model.js";
|
|
6
6
|
import { ProcessMode, type ReflectionMode } from "../agents/team-agent.js";
|
|
@@ -44,7 +44,6 @@ export interface BaseAgentSchema {
|
|
|
44
44
|
afs?: boolean | (Omit<AFSOptions, "modules"> & {
|
|
45
45
|
modules?: AFSModuleSchema[];
|
|
46
46
|
});
|
|
47
|
-
afsConfig?: AFSConfig;
|
|
48
47
|
}
|
|
49
48
|
export type Instructions = {
|
|
50
49
|
role: Exclude<Role, "tool">;
|
|
@@ -57,22 +57,15 @@ async function parseAgentFile(path, data) {
|
|
|
57
57
|
afs: (0, schema_js_1.optionalize)(zod_1.z.union([
|
|
58
58
|
zod_1.z.boolean(),
|
|
59
59
|
(0, schema_js_1.camelizeSchema)(zod_1.z.object({
|
|
60
|
-
storage: (0, schema_js_1.optionalize)(zod_1.z.object({
|
|
61
|
-
url: (0, schema_js_1.optionalize)(zod_1.z.string()),
|
|
62
|
-
})),
|
|
63
60
|
modules: (0, schema_js_1.optionalize)(zod_1.z.array(zod_1.z.union([
|
|
64
61
|
zod_1.z.string(),
|
|
65
|
-
zod_1.z.object({
|
|
62
|
+
(0, schema_js_1.camelizeSchema)(zod_1.z.object({
|
|
66
63
|
module: zod_1.z.string(),
|
|
67
64
|
options: (0, schema_js_1.optionalize)(zod_1.z.record(zod_1.z.any())),
|
|
68
|
-
}),
|
|
65
|
+
})),
|
|
69
66
|
]))),
|
|
70
67
|
})),
|
|
71
68
|
])),
|
|
72
|
-
afsConfig: (0, schema_js_1.optionalize)((0, schema_js_1.camelizeSchema)(zod_1.z.object({
|
|
73
|
-
injectHistory: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
|
|
74
|
-
historyWindowSize: (0, schema_js_1.optionalize)(zod_1.z.number().int().min(1)),
|
|
75
|
-
}))),
|
|
76
69
|
});
|
|
77
70
|
const instructionItemSchema = zod_1.z.union([
|
|
78
71
|
zod_1.z.object({
|
package/lib/cjs/loader/index.js
CHANGED
|
@@ -119,23 +119,19 @@ async function parseAgent(path, agent, options, agentOptions) {
|
|
|
119
119
|
: undefined;
|
|
120
120
|
let afs;
|
|
121
121
|
if (typeof agent.afs === "boolean") {
|
|
122
|
-
if (agent.afs)
|
|
122
|
+
if (agent.afs)
|
|
123
123
|
afs = new afs_1.AFS();
|
|
124
|
-
}
|
|
125
124
|
}
|
|
126
125
|
else if (agent.afs) {
|
|
127
|
-
afs = new afs_1.AFS(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return mod.create(typeof m === "string" ? {} : m.options);
|
|
137
|
-
}))),
|
|
138
|
-
});
|
|
126
|
+
afs = new afs_1.AFS();
|
|
127
|
+
for (const m of agent.afs.modules || []) {
|
|
128
|
+
const moduleName = typeof m === "string" ? m : m.module;
|
|
129
|
+
const mod = options?.afs?.availableModules?.find((mod) => mod.module === moduleName || mod.alias?.includes(moduleName));
|
|
130
|
+
if (!mod)
|
|
131
|
+
throw new Error(`AFS module not found: ${typeof m === "string" ? m : m.module}`);
|
|
132
|
+
const module = await mod.create(typeof m === "string" ? {} : m.options);
|
|
133
|
+
afs.mount(module);
|
|
134
|
+
}
|
|
139
135
|
}
|
|
140
136
|
const model = agent.model && typeof options?.model === "function"
|
|
141
137
|
? await options.model({ ...options.aigne?.model, ...(0, type_utils_js_1.omitBy)(agent.model, (v) => (0, type_utils_js_1.isNil)(v)) })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PromptBuilder = void 0;
|
|
4
|
-
const
|
|
4
|
+
const afs_history_1 = require("@aigne/afs-history");
|
|
5
5
|
const index_js_1 = require("@aigne/platform-helpers/nodejs/index.js");
|
|
6
6
|
const yaml_1 = require("yaml");
|
|
7
7
|
const zod_1 = require("zod");
|
|
@@ -113,21 +113,50 @@ class PromptBuilder {
|
|
|
113
113
|
if (options.agent?.useMemoriesFromContext && options.context?.memories?.length) {
|
|
114
114
|
memories.push(...options.context.memories);
|
|
115
115
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
const afs = options.agent?.afs;
|
|
117
|
+
if (afs) {
|
|
118
|
+
const historyModule = (await afs.listModules()).find((m) => m.module instanceof afs_history_1.AFSHistory);
|
|
119
|
+
messages.push(await template_js_1.SystemMessageTemplate.from(await (0, afs_builtin_prompt_js_1.getAFSSystemPrompt)(afs)).format({}));
|
|
120
|
+
if (historyModule) {
|
|
121
|
+
const history = await afs.list(historyModule.path, {
|
|
122
|
+
limit: options.agent?.maxRetrieveMemoryCount || 10,
|
|
121
123
|
orderBy: [["createdAt", "desc"]],
|
|
122
124
|
});
|
|
123
|
-
if (message) {
|
|
124
|
-
const result = await options.agent.afs.search("/", message);
|
|
125
|
-
const ms = result.list.map((entry) => ({ content: (0, yaml_1.stringify)(entry.content) }));
|
|
126
|
-
memories.push(...ms);
|
|
127
|
-
}
|
|
128
125
|
memories.push(...history.list
|
|
129
126
|
.reverse()
|
|
130
127
|
.filter((i) => (0, type_utils_js_1.isNonNullable)(i.content)));
|
|
128
|
+
if (message) {
|
|
129
|
+
const result = await afs.search("/", message);
|
|
130
|
+
const ms = result.list
|
|
131
|
+
.map((entry) => {
|
|
132
|
+
if (entry.metadata?.execute)
|
|
133
|
+
return null;
|
|
134
|
+
const content = entry.content || entry.summary;
|
|
135
|
+
if (!content)
|
|
136
|
+
return null;
|
|
137
|
+
return {
|
|
138
|
+
content,
|
|
139
|
+
description: entry.description,
|
|
140
|
+
};
|
|
141
|
+
})
|
|
142
|
+
.filter(type_utils_js_1.isNonNullable);
|
|
143
|
+
memories.push(...ms);
|
|
144
|
+
const executable = result.list.filter((i) => !!i.metadata?.execute);
|
|
145
|
+
if (executable.length) {
|
|
146
|
+
messages.push({
|
|
147
|
+
role: "system",
|
|
148
|
+
content: await template_js_1.PromptTemplate.from(afs_builtin_prompt_js_1.AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE).format({
|
|
149
|
+
tools: executable.map((entry) => ({
|
|
150
|
+
path: entry.path,
|
|
151
|
+
name: entry.metadata.execute.name,
|
|
152
|
+
description: entry.metadata.execute.description,
|
|
153
|
+
inputSchema: entry.metadata.execute.inputSchema,
|
|
154
|
+
outputSchema: entry.metadata.execute.outputSchema,
|
|
155
|
+
})),
|
|
156
|
+
}),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
131
160
|
}
|
|
132
161
|
}
|
|
133
162
|
if (memories.length)
|
|
@@ -232,7 +261,8 @@ class PromptBuilder {
|
|
|
232
261
|
result.push({ role: "agent", content: agentMessageContent });
|
|
233
262
|
return result;
|
|
234
263
|
};
|
|
235
|
-
for (const
|
|
264
|
+
for (const memory of memories) {
|
|
265
|
+
const { content } = memory;
|
|
236
266
|
if ((0, type_utils_js_1.isRecord)(content) &&
|
|
237
267
|
"input" in content &&
|
|
238
268
|
content.input &&
|
|
@@ -241,7 +271,7 @@ class PromptBuilder {
|
|
|
241
271
|
messages.push(...(await convertMemoryToMessage(content)));
|
|
242
272
|
}
|
|
243
273
|
else {
|
|
244
|
-
other.push(
|
|
274
|
+
other.push(memory);
|
|
245
275
|
}
|
|
246
276
|
}
|
|
247
277
|
if (other.length) {
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { AFS } from "@aigne/afs";
|
|
2
2
|
export declare function getAFSSystemPrompt(afs: AFS): Promise<string>;
|
|
3
|
+
export declare const AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE = "<afs_executable_tools>\nHere are the executable tools available in the AFS you can use:\n\n{{ tools | yaml.stringify }}\n</afs_executable_tools>\n";
|
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE = void 0;
|
|
3
4
|
exports.getAFSSystemPrompt = getAFSSystemPrompt;
|
|
4
5
|
const yaml_1 = require("yaml");
|
|
6
|
+
const type_utils_js_1 = require("../../utils/type-utils.js");
|
|
5
7
|
async function getAFSSystemPrompt(afs) {
|
|
6
8
|
return `\
|
|
7
9
|
|
|
8
10
|
<afs_usage>
|
|
9
|
-
AFS (
|
|
11
|
+
AFS (Agentic File System) provides tools to interact with a virtual file system,
|
|
12
|
+
allowing you to list, search, read, and write files, or execute a useful tool from the available modules.
|
|
13
|
+
Use these tools to manage and retrieve files as needed.
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
${(0, yaml_1.stringify)(await afs.listModules())}
|
|
15
|
+
Provided modules:
|
|
16
|
+
${(0, yaml_1.stringify)((await afs.listModules()).map((i) => (0, type_utils_js_1.pick)(i, ["name", "path", "description"])))}
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
Global tools to interact with the AFS:
|
|
15
19
|
1. afs_list: Browse directory contents like filesystem ls/tree command - shows files and folders in a given path
|
|
16
20
|
2. afs_search: Find files by content keywords - use specific keywords related to what you're looking for
|
|
17
21
|
3. afs_read: Read file contents - path must be an exact file path from list or search results
|
|
18
22
|
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.
|
|
23
|
+
5. afs_exec: Execute a executable tool from the available modules
|
|
21
24
|
</afs_usage>
|
|
22
25
|
`;
|
|
23
26
|
}
|
|
27
|
+
exports.AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE = `\
|
|
28
|
+
<afs_executable_tools>
|
|
29
|
+
Here are the executable tools available in the AFS you can use:
|
|
30
|
+
|
|
31
|
+
{{ tools | yaml.stringify }}
|
|
32
|
+
</afs_executable_tools>
|
|
33
|
+
`;
|
|
@@ -92,5 +92,18 @@ async function getAFSSkills(afs) {
|
|
|
92
92
|
};
|
|
93
93
|
},
|
|
94
94
|
}),
|
|
95
|
+
agent_js_1.FunctionAgent.from({
|
|
96
|
+
name: "afs_exec",
|
|
97
|
+
description: "Execute a function or command available in the AFS modules",
|
|
98
|
+
inputSchema: zod_1.z.object({
|
|
99
|
+
path: zod_1.z.string().describe("The exact path to the executable entry in AFS"),
|
|
100
|
+
args: zod_1.z
|
|
101
|
+
.string()
|
|
102
|
+
.describe("JSON stringified arguments to pass to the executable, must be an object matching the input schema of the executable"),
|
|
103
|
+
}),
|
|
104
|
+
process: async ({ path, args }, options) => {
|
|
105
|
+
return await afs.exec(path, JSON.parse(args), options);
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
95
108
|
];
|
|
96
109
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AFS, type AFSOptions } from "@aigne/afs";
|
|
1
|
+
import { AFS, type AFSEntry, type AFSListOptions, type AFSModule, type AFSOptions, type AFSSearchOptions } from "@aigne/afs";
|
|
2
2
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
3
3
|
import type * as prompts from "@inquirer/prompts";
|
|
4
4
|
import { type ZodObject, type ZodType } from "zod";
|
|
@@ -123,7 +123,6 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
|
|
|
123
123
|
*/
|
|
124
124
|
memory?: MemoryAgent | MemoryAgent[];
|
|
125
125
|
afs?: true | AFSOptions | AFS | ((afs: AFS) => AFS);
|
|
126
|
-
afsConfig?: AFSConfig;
|
|
127
126
|
asyncMemoryRecord?: boolean;
|
|
128
127
|
/**
|
|
129
128
|
* Maximum number of memory items to retrieve
|
|
@@ -132,10 +131,6 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
|
|
|
132
131
|
hooks?: AgentHooks<I, O> | AgentHooks<I, O>[];
|
|
133
132
|
retryOnError?: Agent<I, O>["retryOnError"] | boolean;
|
|
134
133
|
}
|
|
135
|
-
export interface AFSConfig {
|
|
136
|
-
injectHistory?: boolean;
|
|
137
|
-
historyWindowSize?: number;
|
|
138
|
-
}
|
|
139
134
|
export declare const agentOptionsSchema: ZodObject<{
|
|
140
135
|
[key in keyof AgentOptions]: ZodType<AgentOptions[key]>;
|
|
141
136
|
}>;
|
|
@@ -200,7 +195,7 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
|
|
|
200
195
|
* Here's an example of how to create a custom agent:
|
|
201
196
|
* {@includeCode ../../test/agents/agent.test.ts#example-custom-agent}
|
|
202
197
|
*/
|
|
203
|
-
export declare abstract class Agent<I extends Message = any, O extends Message = any> {
|
|
198
|
+
export declare abstract class Agent<I extends Message = any, O extends Message = any> implements AFSModule {
|
|
204
199
|
/**
|
|
205
200
|
* Custom object inspection behavior
|
|
206
201
|
*
|
|
@@ -218,7 +213,6 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
218
213
|
*/
|
|
219
214
|
readonly memories: MemoryAgent[];
|
|
220
215
|
afs?: AFS;
|
|
221
|
-
afsConfig?: AFSConfig;
|
|
222
216
|
asyncMemoryRecord?: boolean;
|
|
223
217
|
tag?: string;
|
|
224
218
|
/**
|
|
@@ -564,6 +558,26 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
564
558
|
* {@includeCode ../../test/agents/agent.test.ts#example-agent-shutdown-by-using}
|
|
565
559
|
*/
|
|
566
560
|
[Symbol.asyncDispose](): Promise<void>;
|
|
561
|
+
/** For AFSModule interface **/
|
|
562
|
+
private agentToAFSEntry;
|
|
563
|
+
private findAgentByAFSPath;
|
|
564
|
+
list(_path: string, _options?: AFSListOptions): Promise<{
|
|
565
|
+
list: AFSEntry[];
|
|
566
|
+
message?: string;
|
|
567
|
+
}>;
|
|
568
|
+
read(path: string): Promise<{
|
|
569
|
+
result?: AFSEntry;
|
|
570
|
+
message?: string;
|
|
571
|
+
}>;
|
|
572
|
+
search(path: string, _query: string, options?: AFSSearchOptions): Promise<{
|
|
573
|
+
list: AFSEntry[];
|
|
574
|
+
message?: string;
|
|
575
|
+
}>;
|
|
576
|
+
exec(path: string, args: Record<string, any>, options: {
|
|
577
|
+
context: Context;
|
|
578
|
+
}): Promise<{
|
|
579
|
+
result: Record<string, any>;
|
|
580
|
+
}>;
|
|
567
581
|
}
|
|
568
582
|
export type AgentInput<T extends Agent> = T extends Agent<infer I, any> ? I : never;
|
|
569
583
|
export type AgentOutput<T extends Agent> = T extends Agent<any, infer O> ? O : never;
|
|
@@ -182,6 +182,7 @@ export declare class AIGNEContext implements Context {
|
|
|
182
182
|
subscribe: Context["subscribe"];
|
|
183
183
|
unsubscribe: Context["unsubscribe"];
|
|
184
184
|
emit<K extends keyof ContextEmitEventMap>(eventName: K, ...args: Args<K, ContextEmitEventMap>): boolean;
|
|
185
|
+
initProcessExitHandler(): void;
|
|
185
186
|
private trace;
|
|
186
187
|
on<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
|
|
187
188
|
once<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AFSOptions } from "@aigne/afs";
|
|
2
2
|
import { type ZodType, z } from "zod";
|
|
3
|
-
import type {
|
|
3
|
+
import type { AgentHooks, FunctionAgentFn, TaskRenderMode } from "../agents/agent.js";
|
|
4
4
|
import { AIAgentToolChoice } from "../agents/ai-agent.js";
|
|
5
5
|
import { type Role } from "../agents/chat-model.js";
|
|
6
6
|
import { ProcessMode, type ReflectionMode } from "../agents/team-agent.js";
|
|
@@ -44,7 +44,6 @@ export interface BaseAgentSchema {
|
|
|
44
44
|
afs?: boolean | (Omit<AFSOptions, "modules"> & {
|
|
45
45
|
modules?: AFSModuleSchema[];
|
|
46
46
|
});
|
|
47
|
-
afsConfig?: AFSConfig;
|
|
48
47
|
}
|
|
49
48
|
export type Instructions = {
|
|
50
49
|
role: Exclude<Role, "tool">;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { AFS } from "@aigne/afs";
|
|
2
2
|
export declare function getAFSSystemPrompt(afs: AFS): Promise<string>;
|
|
3
|
+
export declare const AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE = "<afs_executable_tools>\nHere are the executable tools available in the AFS you can use:\n\n{{ tools | yaml.stringify }}\n</afs_executable_tools>\n";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AFS, type AFSOptions } from "@aigne/afs";
|
|
1
|
+
import { AFS, type AFSEntry, type AFSListOptions, type AFSModule, type AFSOptions, type AFSSearchOptions } from "@aigne/afs";
|
|
2
2
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
3
3
|
import type * as prompts from "@inquirer/prompts";
|
|
4
4
|
import { type ZodObject, type ZodType } from "zod";
|
|
@@ -123,7 +123,6 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
|
|
|
123
123
|
*/
|
|
124
124
|
memory?: MemoryAgent | MemoryAgent[];
|
|
125
125
|
afs?: true | AFSOptions | AFS | ((afs: AFS) => AFS);
|
|
126
|
-
afsConfig?: AFSConfig;
|
|
127
126
|
asyncMemoryRecord?: boolean;
|
|
128
127
|
/**
|
|
129
128
|
* Maximum number of memory items to retrieve
|
|
@@ -132,10 +131,6 @@ export interface AgentOptions<I extends Message = Message, O extends Message = M
|
|
|
132
131
|
hooks?: AgentHooks<I, O> | AgentHooks<I, O>[];
|
|
133
132
|
retryOnError?: Agent<I, O>["retryOnError"] | boolean;
|
|
134
133
|
}
|
|
135
|
-
export interface AFSConfig {
|
|
136
|
-
injectHistory?: boolean;
|
|
137
|
-
historyWindowSize?: number;
|
|
138
|
-
}
|
|
139
134
|
export declare const agentOptionsSchema: ZodObject<{
|
|
140
135
|
[key in keyof AgentOptions]: ZodType<AgentOptions[key]>;
|
|
141
136
|
}>;
|
|
@@ -200,7 +195,7 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
|
|
|
200
195
|
* Here's an example of how to create a custom agent:
|
|
201
196
|
* {@includeCode ../../test/agents/agent.test.ts#example-custom-agent}
|
|
202
197
|
*/
|
|
203
|
-
export declare abstract class Agent<I extends Message = any, O extends Message = any> {
|
|
198
|
+
export declare abstract class Agent<I extends Message = any, O extends Message = any> implements AFSModule {
|
|
204
199
|
/**
|
|
205
200
|
* Custom object inspection behavior
|
|
206
201
|
*
|
|
@@ -218,7 +213,6 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
218
213
|
*/
|
|
219
214
|
readonly memories: MemoryAgent[];
|
|
220
215
|
afs?: AFS;
|
|
221
|
-
afsConfig?: AFSConfig;
|
|
222
216
|
asyncMemoryRecord?: boolean;
|
|
223
217
|
tag?: string;
|
|
224
218
|
/**
|
|
@@ -564,6 +558,26 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
564
558
|
* {@includeCode ../../test/agents/agent.test.ts#example-agent-shutdown-by-using}
|
|
565
559
|
*/
|
|
566
560
|
[Symbol.asyncDispose](): Promise<void>;
|
|
561
|
+
/** For AFSModule interface **/
|
|
562
|
+
private agentToAFSEntry;
|
|
563
|
+
private findAgentByAFSPath;
|
|
564
|
+
list(_path: string, _options?: AFSListOptions): Promise<{
|
|
565
|
+
list: AFSEntry[];
|
|
566
|
+
message?: string;
|
|
567
|
+
}>;
|
|
568
|
+
read(path: string): Promise<{
|
|
569
|
+
result?: AFSEntry;
|
|
570
|
+
message?: string;
|
|
571
|
+
}>;
|
|
572
|
+
search(path: string, _query: string, options?: AFSSearchOptions): Promise<{
|
|
573
|
+
list: AFSEntry[];
|
|
574
|
+
message?: string;
|
|
575
|
+
}>;
|
|
576
|
+
exec(path: string, args: Record<string, any>, options: {
|
|
577
|
+
context: Context;
|
|
578
|
+
}): Promise<{
|
|
579
|
+
result: Record<string, any>;
|
|
580
|
+
}>;
|
|
567
581
|
}
|
|
568
582
|
export type AgentInput<T extends Agent> = T extends Agent<infer I, any> ? I : never;
|
|
569
583
|
export type AgentOutput<T extends Agent> = T extends Agent<any, infer O> ? O : never;
|
package/lib/esm/agents/agent.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { AFS } from "@aigne/afs";
|
|
1
|
+
import { AFS, } from "@aigne/afs";
|
|
2
2
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
3
3
|
import equal from "fast-deep-equal";
|
|
4
4
|
import nunjucks from "nunjucks";
|
|
5
|
+
import { joinURL } from "ufo";
|
|
5
6
|
import { z } from "zod";
|
|
7
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
6
8
|
import { sortHooks } from "../utils/agent-utils.js";
|
|
7
9
|
import { isZodSchema } from "../utils/json-schema.js";
|
|
8
10
|
import { logger } from "../utils/logger.js";
|
|
@@ -113,7 +115,6 @@ export class Agent {
|
|
|
113
115
|
: options.afs instanceof AFS
|
|
114
116
|
? options.afs
|
|
115
117
|
: new AFS(options.afs);
|
|
116
|
-
this.afsConfig = options.afsConfig;
|
|
117
118
|
this.asyncMemoryRecord = options.asyncMemoryRecord;
|
|
118
119
|
this.maxRetrieveMemoryCount = options.maxRetrieveMemoryCount;
|
|
119
120
|
this.hooks = flat(options.hooks);
|
|
@@ -132,7 +133,6 @@ export class Agent {
|
|
|
132
133
|
*/
|
|
133
134
|
memories = [];
|
|
134
135
|
afs;
|
|
135
|
-
afsConfig;
|
|
136
136
|
asyncMemoryRecord;
|
|
137
137
|
tag;
|
|
138
138
|
/**
|
|
@@ -689,6 +689,59 @@ export class Agent {
|
|
|
689
689
|
async [Symbol.asyncDispose]() {
|
|
690
690
|
await this.shutdown();
|
|
691
691
|
}
|
|
692
|
+
/** For AFSModule interface **/
|
|
693
|
+
agentToAFSEntry(agent) {
|
|
694
|
+
return {
|
|
695
|
+
id: `/${this.name}/${agent.name}`,
|
|
696
|
+
path: agent === this ? "/" : joinURL("/", agent.name),
|
|
697
|
+
summary: agent.description,
|
|
698
|
+
metadata: {
|
|
699
|
+
execute: agent.isInvokable
|
|
700
|
+
? {
|
|
701
|
+
name: agent.name,
|
|
702
|
+
description: agent.description,
|
|
703
|
+
inputSchema: zodToJsonSchema(agent.inputSchema),
|
|
704
|
+
outputSchema: zodToJsonSchema(agent.outputSchema),
|
|
705
|
+
}
|
|
706
|
+
: undefined,
|
|
707
|
+
},
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
findAgentByAFSPath(path) {
|
|
711
|
+
let agent;
|
|
712
|
+
if (path === "/") {
|
|
713
|
+
agent = this;
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
const name = path.split("/")[1];
|
|
717
|
+
agent = this.skills.find((s) => s.name === name);
|
|
718
|
+
}
|
|
719
|
+
return agent;
|
|
720
|
+
}
|
|
721
|
+
// TODO: support list skills inside agent path, and use options to filter skills
|
|
722
|
+
async list(_path, _options) {
|
|
723
|
+
const agents = [this, ...this.skills];
|
|
724
|
+
return { list: agents.map((agent) => this.agentToAFSEntry(agent)) };
|
|
725
|
+
}
|
|
726
|
+
async read(path) {
|
|
727
|
+
const agent = this.findAgentByAFSPath(path);
|
|
728
|
+
if (!agent) {
|
|
729
|
+
return { message: `Agent not found at path: ${path}` };
|
|
730
|
+
}
|
|
731
|
+
return {
|
|
732
|
+
result: this.agentToAFSEntry(agent),
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
// TODO: implement search inside agent skills
|
|
736
|
+
async search(path, _query, options) {
|
|
737
|
+
return this.list(path, options);
|
|
738
|
+
}
|
|
739
|
+
async exec(path, args, options) {
|
|
740
|
+
const agent = this.findAgentByAFSPath(path);
|
|
741
|
+
if (!agent)
|
|
742
|
+
throw new Error(`Agent not found at path: ${path}`);
|
|
743
|
+
return { result: await options.context.invoke(agent, args) };
|
|
744
|
+
}
|
|
692
745
|
}
|
|
693
746
|
/**
|
|
694
747
|
* Check if a response chunk is empty
|
package/lib/esm/aigne/aigne.js
CHANGED
|
@@ -218,7 +218,7 @@ export class AIGNE {
|
|
|
218
218
|
* This registers handlers for SIGINT and exit events to properly terminate all agents.
|
|
219
219
|
*/
|
|
220
220
|
initProcessExitHandler() {
|
|
221
|
-
const shutdownAndExit = () => this.shutdown()
|
|
221
|
+
const shutdownAndExit = () => this.shutdown();
|
|
222
222
|
process.on("SIGINT", shutdownAndExit);
|
|
223
223
|
process.on("exit", shutdownAndExit);
|
|
224
224
|
}
|
|
@@ -182,6 +182,7 @@ export declare class AIGNEContext implements Context {
|
|
|
182
182
|
subscribe: Context["subscribe"];
|
|
183
183
|
unsubscribe: Context["unsubscribe"];
|
|
184
184
|
emit<K extends keyof ContextEmitEventMap>(eventName: K, ...args: Args<K, ContextEmitEventMap>): boolean;
|
|
185
|
+
initProcessExitHandler(): void;
|
|
185
186
|
private trace;
|
|
186
187
|
on<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
|
|
187
188
|
once<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
|
package/lib/esm/aigne/context.js
CHANGED
|
@@ -40,6 +40,7 @@ export class AIGNEContext {
|
|
|
40
40
|
this.rootId = this.span?.spanContext?.().traceId ?? v7();
|
|
41
41
|
}
|
|
42
42
|
this.id = this.span?.spanContext()?.spanId ?? v7();
|
|
43
|
+
this.initProcessExitHandler();
|
|
43
44
|
}
|
|
44
45
|
id;
|
|
45
46
|
parentId;
|
|
@@ -195,6 +196,23 @@ export class AIGNEContext {
|
|
|
195
196
|
this.trace(eventName, args, b);
|
|
196
197
|
return this.internal.events.emit(eventName, ...newArgs);
|
|
197
198
|
}
|
|
199
|
+
initProcessExitHandler() {
|
|
200
|
+
process.on("SIGINT", async () => {
|
|
201
|
+
try {
|
|
202
|
+
if (process.env.AIGNE_OBSERVABILITY_DISABLED)
|
|
203
|
+
return;
|
|
204
|
+
const span = this.span;
|
|
205
|
+
if (!span)
|
|
206
|
+
return;
|
|
207
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: "SIGINT" });
|
|
208
|
+
span.end();
|
|
209
|
+
await this.observer?.flush(span);
|
|
210
|
+
}
|
|
211
|
+
finally {
|
|
212
|
+
process.exit(0);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
198
216
|
async trace(eventName, args, b) {
|
|
199
217
|
if (process.env.AIGNE_OBSERVABILITY_DISABLED)
|
|
200
218
|
return;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AFSOptions } from "@aigne/afs";
|
|
2
2
|
import { type ZodType, z } from "zod";
|
|
3
|
-
import type {
|
|
3
|
+
import type { AgentHooks, FunctionAgentFn, TaskRenderMode } from "../agents/agent.js";
|
|
4
4
|
import { AIAgentToolChoice } from "../agents/ai-agent.js";
|
|
5
5
|
import { type Role } from "../agents/chat-model.js";
|
|
6
6
|
import { ProcessMode, type ReflectionMode } from "../agents/team-agent.js";
|
|
@@ -44,7 +44,6 @@ export interface BaseAgentSchema {
|
|
|
44
44
|
afs?: boolean | (Omit<AFSOptions, "modules"> & {
|
|
45
45
|
modules?: AFSModuleSchema[];
|
|
46
46
|
});
|
|
47
|
-
afsConfig?: AFSConfig;
|
|
48
47
|
}
|
|
49
48
|
export type Instructions = {
|
|
50
49
|
role: Exclude<Role, "tool">;
|
|
@@ -53,22 +53,15 @@ export async function parseAgentFile(path, data) {
|
|
|
53
53
|
afs: optionalize(z.union([
|
|
54
54
|
z.boolean(),
|
|
55
55
|
camelizeSchema(z.object({
|
|
56
|
-
storage: optionalize(z.object({
|
|
57
|
-
url: optionalize(z.string()),
|
|
58
|
-
})),
|
|
59
56
|
modules: optionalize(z.array(z.union([
|
|
60
57
|
z.string(),
|
|
61
|
-
z.object({
|
|
58
|
+
camelizeSchema(z.object({
|
|
62
59
|
module: z.string(),
|
|
63
60
|
options: optionalize(z.record(z.any())),
|
|
64
|
-
}),
|
|
61
|
+
})),
|
|
65
62
|
]))),
|
|
66
63
|
})),
|
|
67
64
|
])),
|
|
68
|
-
afsConfig: optionalize(camelizeSchema(z.object({
|
|
69
|
-
injectHistory: optionalize(z.boolean()),
|
|
70
|
-
historyWindowSize: optionalize(z.number().int().min(1)),
|
|
71
|
-
}))),
|
|
72
65
|
});
|
|
73
66
|
const instructionItemSchema = z.union([
|
|
74
67
|
z.object({
|
package/lib/esm/loader/index.js
CHANGED
|
@@ -114,23 +114,19 @@ async function parseAgent(path, agent, options, agentOptions) {
|
|
|
114
114
|
: undefined;
|
|
115
115
|
let afs;
|
|
116
116
|
if (typeof agent.afs === "boolean") {
|
|
117
|
-
if (agent.afs)
|
|
117
|
+
if (agent.afs)
|
|
118
118
|
afs = new AFS();
|
|
119
|
-
}
|
|
120
119
|
}
|
|
121
120
|
else if (agent.afs) {
|
|
122
|
-
afs = new AFS(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return mod.create(typeof m === "string" ? {} : m.options);
|
|
132
|
-
}))),
|
|
133
|
-
});
|
|
121
|
+
afs = new AFS();
|
|
122
|
+
for (const m of agent.afs.modules || []) {
|
|
123
|
+
const moduleName = typeof m === "string" ? m : m.module;
|
|
124
|
+
const mod = options?.afs?.availableModules?.find((mod) => mod.module === moduleName || mod.alias?.includes(moduleName));
|
|
125
|
+
if (!mod)
|
|
126
|
+
throw new Error(`AFS module not found: ${typeof m === "string" ? m : m.module}`);
|
|
127
|
+
const module = await mod.create(typeof m === "string" ? {} : m.options);
|
|
128
|
+
afs.mount(module);
|
|
129
|
+
}
|
|
134
130
|
}
|
|
135
131
|
const model = agent.model && typeof options?.model === "function"
|
|
136
132
|
? await options.model({ ...options.aigne?.model, ...omitBy(agent.model, (v) => isNil(v)) })
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AFSHistory } from "@aigne/afs";
|
|
1
|
+
import { AFSHistory } from "@aigne/afs-history";
|
|
2
2
|
import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
|
|
3
3
|
import { stringify } from "yaml";
|
|
4
4
|
import { ZodObject } from "zod";
|
|
@@ -9,7 +9,7 @@ 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, partition, unique, } from "../utils/type-utils.js";
|
|
12
|
-
import { getAFSSystemPrompt } from "./prompts/afs-builtin-prompt.js";
|
|
12
|
+
import { AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE, getAFSSystemPrompt, } from "./prompts/afs-builtin-prompt.js";
|
|
13
13
|
import { MEMORY_MESSAGE_TEMPLATE } from "./prompts/memory-message-template.js";
|
|
14
14
|
import { STRUCTURED_STREAM_INSTRUCTIONS } from "./prompts/structured-stream-instructions.js";
|
|
15
15
|
import { getAFSSkills } from "./skills/afs.js";
|
|
@@ -110,21 +110,50 @@ export class PromptBuilder {
|
|
|
110
110
|
if (options.agent?.useMemoriesFromContext && options.context?.memories?.length) {
|
|
111
111
|
memories.push(...options.context.memories);
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
const afs = options.agent?.afs;
|
|
114
|
+
if (afs) {
|
|
115
|
+
const historyModule = (await afs.listModules()).find((m) => m.module instanceof AFSHistory);
|
|
116
|
+
messages.push(await SystemMessageTemplate.from(await getAFSSystemPrompt(afs)).format({}));
|
|
117
|
+
if (historyModule) {
|
|
118
|
+
const history = await afs.list(historyModule.path, {
|
|
119
|
+
limit: options.agent?.maxRetrieveMemoryCount || 10,
|
|
118
120
|
orderBy: [["createdAt", "desc"]],
|
|
119
121
|
});
|
|
120
|
-
if (message) {
|
|
121
|
-
const result = await options.agent.afs.search("/", message);
|
|
122
|
-
const ms = result.list.map((entry) => ({ content: stringify(entry.content) }));
|
|
123
|
-
memories.push(...ms);
|
|
124
|
-
}
|
|
125
122
|
memories.push(...history.list
|
|
126
123
|
.reverse()
|
|
127
124
|
.filter((i) => isNonNullable(i.content)));
|
|
125
|
+
if (message) {
|
|
126
|
+
const result = await afs.search("/", message);
|
|
127
|
+
const ms = result.list
|
|
128
|
+
.map((entry) => {
|
|
129
|
+
if (entry.metadata?.execute)
|
|
130
|
+
return null;
|
|
131
|
+
const content = entry.content || entry.summary;
|
|
132
|
+
if (!content)
|
|
133
|
+
return null;
|
|
134
|
+
return {
|
|
135
|
+
content,
|
|
136
|
+
description: entry.description,
|
|
137
|
+
};
|
|
138
|
+
})
|
|
139
|
+
.filter(isNonNullable);
|
|
140
|
+
memories.push(...ms);
|
|
141
|
+
const executable = result.list.filter((i) => !!i.metadata?.execute);
|
|
142
|
+
if (executable.length) {
|
|
143
|
+
messages.push({
|
|
144
|
+
role: "system",
|
|
145
|
+
content: await PromptTemplate.from(AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE).format({
|
|
146
|
+
tools: executable.map((entry) => ({
|
|
147
|
+
path: entry.path,
|
|
148
|
+
name: entry.metadata.execute.name,
|
|
149
|
+
description: entry.metadata.execute.description,
|
|
150
|
+
inputSchema: entry.metadata.execute.inputSchema,
|
|
151
|
+
outputSchema: entry.metadata.execute.outputSchema,
|
|
152
|
+
})),
|
|
153
|
+
}),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
128
157
|
}
|
|
129
158
|
}
|
|
130
159
|
if (memories.length)
|
|
@@ -229,7 +258,8 @@ export class PromptBuilder {
|
|
|
229
258
|
result.push({ role: "agent", content: agentMessageContent });
|
|
230
259
|
return result;
|
|
231
260
|
};
|
|
232
|
-
for (const
|
|
261
|
+
for (const memory of memories) {
|
|
262
|
+
const { content } = memory;
|
|
233
263
|
if (isRecord(content) &&
|
|
234
264
|
"input" in content &&
|
|
235
265
|
content.input &&
|
|
@@ -238,7 +268,7 @@ export class PromptBuilder {
|
|
|
238
268
|
messages.push(...(await convertMemoryToMessage(content)));
|
|
239
269
|
}
|
|
240
270
|
else {
|
|
241
|
-
other.push(
|
|
271
|
+
other.push(memory);
|
|
242
272
|
}
|
|
243
273
|
}
|
|
244
274
|
if (other.length) {
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { AFS } from "@aigne/afs";
|
|
2
2
|
export declare function getAFSSystemPrompt(afs: AFS): Promise<string>;
|
|
3
|
+
export declare const AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE = "<afs_executable_tools>\nHere are the executable tools available in the AFS you can use:\n\n{{ tools | yaml.stringify }}\n</afs_executable_tools>\n";
|
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import { stringify } from "yaml";
|
|
2
|
+
import { pick } from "../../utils/type-utils.js";
|
|
2
3
|
export async function getAFSSystemPrompt(afs) {
|
|
3
4
|
return `\
|
|
4
5
|
|
|
5
6
|
<afs_usage>
|
|
6
|
-
AFS (
|
|
7
|
+
AFS (Agentic File System) provides tools to interact with a virtual file system,
|
|
8
|
+
allowing you to list, search, read, and write files, or execute a useful tool from the available modules.
|
|
9
|
+
Use these tools to manage and retrieve files as needed.
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
${stringify(await afs.listModules())}
|
|
11
|
+
Provided modules:
|
|
12
|
+
${stringify((await afs.listModules()).map((i) => pick(i, ["name", "path", "description"])))}
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
Global tools to interact with the AFS:
|
|
12
15
|
1. afs_list: Browse directory contents like filesystem ls/tree command - shows files and folders in a given path
|
|
13
16
|
2. afs_search: Find files by content keywords - use specific keywords related to what you're looking for
|
|
14
17
|
3. afs_read: Read file contents - path must be an exact file path from list or search results
|
|
15
18
|
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.
|
|
19
|
+
5. afs_exec: Execute a executable tool from the available modules
|
|
18
20
|
</afs_usage>
|
|
19
21
|
`;
|
|
20
22
|
}
|
|
23
|
+
export const AFS_EXECUTABLE_TOOLS_PROMPT_TEMPLATE = `\
|
|
24
|
+
<afs_executable_tools>
|
|
25
|
+
Here are the executable tools available in the AFS you can use:
|
|
26
|
+
|
|
27
|
+
{{ tools | yaml.stringify }}
|
|
28
|
+
</afs_executable_tools>
|
|
29
|
+
`;
|
|
@@ -89,5 +89,18 @@ export async function getAFSSkills(afs) {
|
|
|
89
89
|
};
|
|
90
90
|
},
|
|
91
91
|
}),
|
|
92
|
+
FunctionAgent.from({
|
|
93
|
+
name: "afs_exec",
|
|
94
|
+
description: "Execute a function or command available in the AFS modules",
|
|
95
|
+
inputSchema: z.object({
|
|
96
|
+
path: z.string().describe("The exact path to the executable entry in AFS"),
|
|
97
|
+
args: z
|
|
98
|
+
.string()
|
|
99
|
+
.describe("JSON stringified arguments to pass to the executable, must be an object matching the input schema of the executable"),
|
|
100
|
+
}),
|
|
101
|
+
process: async ({ path, args }, options) => {
|
|
102
|
+
return await afs.exec(path, JSON.parse(args), options);
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
92
105
|
];
|
|
93
106
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.68.0-beta",
|
|
4
4
|
"description": "The functional core of agentic AI",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -92,9 +92,10 @@
|
|
|
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/afs-history": "^1.0.0",
|
|
96
96
|
"@aigne/platform-helpers": "^0.6.3",
|
|
97
|
-
"@aigne/afs": "^1.
|
|
97
|
+
"@aigne/afs": "^1.2.0-beta",
|
|
98
|
+
"@aigne/observability-api": "^0.11.6"
|
|
98
99
|
},
|
|
99
100
|
"devDependencies": {
|
|
100
101
|
"@types/bun": "^1.2.22",
|