@aigne/core 1.72.0-beta.6 → 1.72.0-beta.7
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/agents/agent.d.ts +35 -20
- package/lib/cjs/agents/agent.js +17 -4
- package/lib/cjs/agents/ai-agent.js +28 -38
- package/lib/cjs/agents/chat-model.d.ts +1 -0
- package/lib/cjs/loader/agent-yaml.d.ts +2 -1
- package/lib/cjs/loader/agent-yaml.js +8 -0
- package/lib/cjs/prompt/context/afs/history.d.ts +5 -1
- package/lib/cjs/prompt/context/afs/history.js +2 -1
- package/lib/cjs/prompt/context/afs/index.js +8 -1
- package/lib/cjs/prompt/prompt-builder.d.ts +11 -7
- package/lib/cjs/prompt/prompt-builder.js +64 -48
- package/lib/dts/agents/agent.d.ts +35 -20
- package/lib/dts/agents/chat-model.d.ts +1 -0
- package/lib/dts/loader/agent-yaml.d.ts +2 -1
- package/lib/dts/prompt/context/afs/history.d.ts +5 -1
- package/lib/dts/prompt/prompt-builder.d.ts +11 -7
- package/lib/esm/agents/agent.d.ts +35 -20
- package/lib/esm/agents/agent.js +17 -4
- package/lib/esm/agents/ai-agent.js +28 -38
- package/lib/esm/agents/chat-model.d.ts +1 -0
- package/lib/esm/loader/agent-yaml.d.ts +2 -1
- package/lib/esm/loader/agent-yaml.js +8 -0
- package/lib/esm/prompt/context/afs/history.d.ts +5 -1
- package/lib/esm/prompt/context/afs/history.js +2 -1
- package/lib/esm/prompt/context/afs/index.js +8 -1
- package/lib/esm/prompt/prompt-builder.d.ts +11 -7
- package/lib/esm/prompt/prompt-builder.js +64 -48
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.72.0-beta.7](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.72.0-beta.6...core-v1.72.0-beta.7) (2025-12-26)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **core:** add session history support ([#858](https://github.com/AIGNE-io/aigne-framework/issues/858)) ([28a070e](https://github.com/AIGNE-io/aigne-framework/commit/28a070ed33b821d1fd344b899706d817ca992b9f))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @aigne/afs bumped to 1.4.0-beta.4
|
|
16
|
+
* @aigne/afs-history bumped to 1.2.0-beta.4
|
|
17
|
+
|
|
3
18
|
## [1.72.0-beta.6](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.72.0-beta.5...core-v1.72.0-beta.6) (2025-12-25)
|
|
4
19
|
|
|
5
20
|
|
|
@@ -9,7 +9,7 @@ import type { Memory, MemoryAgent } from "../memory/memory.js";
|
|
|
9
9
|
import type { MemoryRecorderInput } from "../memory/recorder.js";
|
|
10
10
|
import type { MemoryRetrieverInput } from "../memory/retriever.js";
|
|
11
11
|
import { type Nullish, type PromiseOrValue, type XOr } from "../utils/type-utils.js";
|
|
12
|
-
import type { ChatModel } from "./chat-model.js";
|
|
12
|
+
import type { ChatModel, ChatModelInputMessage } from "./chat-model.js";
|
|
13
13
|
import type { GuideRailAgent, GuideRailAgentOutput } from "./guide-rail-agent.js";
|
|
14
14
|
import type { ImageModel } from "./image-model.js";
|
|
15
15
|
import { type GetterSchema, type TransferAgentOutput } from "./types.js";
|
|
@@ -350,7 +350,20 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
350
350
|
*/
|
|
351
351
|
private disableEvents?;
|
|
352
352
|
historyConfig?: {
|
|
353
|
-
|
|
353
|
+
/**
|
|
354
|
+
* Whether to enable history recording and injection
|
|
355
|
+
* @default false
|
|
356
|
+
*/
|
|
357
|
+
enabled?: boolean;
|
|
358
|
+
/**
|
|
359
|
+
* Whether to record history entries, default to enabled when history is enabled
|
|
360
|
+
*/
|
|
361
|
+
record?: boolean;
|
|
362
|
+
/**
|
|
363
|
+
* Whether to inject history entries into the context, default to enabled when history is enabled
|
|
364
|
+
*/
|
|
365
|
+
inject?: boolean;
|
|
366
|
+
useOldMemory?: boolean;
|
|
354
367
|
maxTokens?: number;
|
|
355
368
|
maxItems?: number;
|
|
356
369
|
};
|
|
@@ -455,7 +468,9 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
455
468
|
* @param options Invocation options
|
|
456
469
|
* @returns Final processed output
|
|
457
470
|
*/
|
|
458
|
-
protected processAgentOutput(input: I, output: Exclude<AgentResponse<O>, AgentResponseStream<O>>, options: AgentInvokeOptions
|
|
471
|
+
protected processAgentOutput(input: I, output: Exclude<AgentResponse<O>, AgentResponseStream<O>>, { messages, ...options }: AgentInvokeOptions & {
|
|
472
|
+
messages?: ChatModelInputMessage[];
|
|
473
|
+
}): Promise<O>;
|
|
459
474
|
/**
|
|
460
475
|
* Process errors that occur during agent execution
|
|
461
476
|
*
|
|
@@ -785,29 +800,29 @@ export interface AgentResponseProgress {
|
|
|
785
800
|
error: Error;
|
|
786
801
|
} | {
|
|
787
802
|
event: "message";
|
|
788
|
-
|
|
789
|
-
message: ({
|
|
790
|
-
type: "text";
|
|
791
|
-
content: string;
|
|
792
|
-
} | {
|
|
793
|
-
type: "thinking";
|
|
794
|
-
thoughts: string;
|
|
795
|
-
} | {
|
|
796
|
-
type: "tool_use";
|
|
797
|
-
toolUseId: string;
|
|
798
|
-
name: string;
|
|
799
|
-
input: unknown;
|
|
800
|
-
} | {
|
|
801
|
-
type: "tool_result";
|
|
802
|
-
toolUseId: string;
|
|
803
|
-
content: unknown;
|
|
804
|
-
})[];
|
|
803
|
+
message: ChatModelInputMessage;
|
|
805
804
|
}) & Omit<AgentEvent, "agent"> & {
|
|
806
805
|
agent: {
|
|
807
806
|
name: string;
|
|
808
807
|
};
|
|
809
808
|
};
|
|
810
809
|
}
|
|
810
|
+
export type AgentResponseProgressMessageItem = {
|
|
811
|
+
type: "text";
|
|
812
|
+
content: string;
|
|
813
|
+
} | {
|
|
814
|
+
type: "thinking";
|
|
815
|
+
thoughts: string;
|
|
816
|
+
} | {
|
|
817
|
+
type: "tool_use";
|
|
818
|
+
toolUseId: string;
|
|
819
|
+
name: string;
|
|
820
|
+
input: unknown;
|
|
821
|
+
} | {
|
|
822
|
+
type: "tool_result";
|
|
823
|
+
toolUseId: string;
|
|
824
|
+
content: unknown;
|
|
825
|
+
};
|
|
811
826
|
export declare function isAgentResponseProgress<T>(chunk: AgentResponseChunk<T>): chunk is AgentResponseProgress;
|
|
812
827
|
/**
|
|
813
828
|
* Creates a text delta for streaming responses
|
package/lib/cjs/agents/agent.js
CHANGED
|
@@ -463,11 +463,15 @@ class Agent {
|
|
|
463
463
|
: (0, stream_utils_js_1.isAsyncGenerator)(response)
|
|
464
464
|
? (0, stream_utils_js_1.asyncGeneratorToReadableStream)(response)
|
|
465
465
|
: (0, stream_utils_js_1.objectToAgentResponseStream)(response);
|
|
466
|
+
const messages = [];
|
|
466
467
|
for await (const chunk of stream) {
|
|
467
468
|
(0, stream_utils_js_1.mergeAgentResponseChunk)(output, chunk);
|
|
468
469
|
yield chunk;
|
|
470
|
+
if (isAgentResponseProgress(chunk) && chunk.progress.event === "message") {
|
|
471
|
+
messages.push(chunk.progress.message);
|
|
472
|
+
}
|
|
469
473
|
}
|
|
470
|
-
let result = await this.processAgentOutput(input, output, options);
|
|
474
|
+
let result = await this.processAgentOutput(input, output, { ...options, messages });
|
|
471
475
|
if (attempt > 0) {
|
|
472
476
|
result = { ...result, $meta: { ...result.$meta, retries: attempt } };
|
|
473
477
|
}
|
|
@@ -564,7 +568,7 @@ class Agent {
|
|
|
564
568
|
* @param options Invocation options
|
|
565
569
|
* @returns Final processed output
|
|
566
570
|
*/
|
|
567
|
-
async processAgentOutput(input, output, options) {
|
|
571
|
+
async processAgentOutput(input, output, { messages, ...options }) {
|
|
568
572
|
const { context } = options;
|
|
569
573
|
if (!(0, type_utils_js_1.isRecord)(output)) {
|
|
570
574
|
throw new Error(`expect to return a record type such as {result: ...}, but got (${typeof output}): ${output}`);
|
|
@@ -576,8 +580,17 @@ class Agent {
|
|
|
576
580
|
const o = await this.callHooks(["onSuccess", "onEnd"], { input, output: finalOutput }, options);
|
|
577
581
|
if (o?.output)
|
|
578
582
|
finalOutput = o.output;
|
|
579
|
-
if (this.historyConfig?.
|
|
580
|
-
this.
|
|
583
|
+
if (this.historyConfig?.record === true ||
|
|
584
|
+
(this.historyConfig?.record !== false && this.historyConfig?.enabled)) {
|
|
585
|
+
this.afs?.emit("agentSucceed", {
|
|
586
|
+
agentId: this.name,
|
|
587
|
+
userId: context.userContext.userId,
|
|
588
|
+
sessionId: context.userContext.sessionId,
|
|
589
|
+
input,
|
|
590
|
+
output: finalOutput,
|
|
591
|
+
messages,
|
|
592
|
+
});
|
|
593
|
+
}
|
|
581
594
|
if (!this.disableEvents)
|
|
582
595
|
context.emit("agentSucceed", { agent: this, output: finalOutput });
|
|
583
596
|
return finalOutput;
|
|
@@ -349,8 +349,10 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
349
349
|
yield {
|
|
350
350
|
progress: {
|
|
351
351
|
event: "message",
|
|
352
|
-
|
|
353
|
-
|
|
352
|
+
message: {
|
|
353
|
+
role: "user",
|
|
354
|
+
content: [{ type: "text", text: inputMessage }],
|
|
355
|
+
},
|
|
354
356
|
},
|
|
355
357
|
};
|
|
356
358
|
}
|
|
@@ -379,15 +381,22 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
379
381
|
}
|
|
380
382
|
}
|
|
381
383
|
const { toolCalls, json, text, thoughts, files } = modelOutput;
|
|
382
|
-
if (text) {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
384
|
+
if (text || thoughts) {
|
|
385
|
+
const content = [];
|
|
386
|
+
if (thoughts) {
|
|
387
|
+
content.push({ type: "text", text: thoughts, isThinking: true });
|
|
388
|
+
}
|
|
389
|
+
if (text) {
|
|
390
|
+
content.push({ type: "text", text });
|
|
391
|
+
}
|
|
392
|
+
if (content.length) {
|
|
393
|
+
yield {
|
|
394
|
+
progress: {
|
|
395
|
+
event: "message",
|
|
396
|
+
message: { role: "agent", content },
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
}
|
|
391
400
|
}
|
|
392
401
|
if (toolCalls?.length) {
|
|
393
402
|
if (this.keepTextInToolUses !== true) {
|
|
@@ -419,25 +428,14 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
419
428
|
queue.killAndDrain();
|
|
420
429
|
}
|
|
421
430
|
}, this.toolCallsConcurrency || 1);
|
|
431
|
+
yield {
|
|
432
|
+
progress: { event: "message", message: { role: "agent", toolCalls } },
|
|
433
|
+
};
|
|
422
434
|
// Execute tools
|
|
423
435
|
for (const call of toolCalls) {
|
|
424
436
|
const tool = toolsMap.get(call.function.name);
|
|
425
437
|
if (!tool)
|
|
426
438
|
throw new Error(`Tool not found: ${call.function.name}`);
|
|
427
|
-
yield {
|
|
428
|
-
progress: {
|
|
429
|
-
event: "message",
|
|
430
|
-
role: "agent",
|
|
431
|
-
message: [
|
|
432
|
-
{
|
|
433
|
-
type: "tool_use",
|
|
434
|
-
name: call.function.name,
|
|
435
|
-
input: call.function.arguments,
|
|
436
|
-
toolUseId: call.id,
|
|
437
|
-
},
|
|
438
|
-
],
|
|
439
|
-
},
|
|
440
|
-
};
|
|
441
439
|
queue.push({ tool, call });
|
|
442
440
|
}
|
|
443
441
|
await queue.drained();
|
|
@@ -449,14 +447,11 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
449
447
|
yield {
|
|
450
448
|
progress: {
|
|
451
449
|
event: "message",
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
content: output,
|
|
458
|
-
},
|
|
459
|
-
],
|
|
450
|
+
message: {
|
|
451
|
+
role: "tool",
|
|
452
|
+
toolCallId: call.id,
|
|
453
|
+
content: JSON.stringify(output),
|
|
454
|
+
},
|
|
460
455
|
},
|
|
461
456
|
};
|
|
462
457
|
}
|
|
@@ -480,11 +475,6 @@ class AIAgent extends agent_js_1.Agent {
|
|
|
480
475
|
if (!(0, type_utils_js_1.isEmpty)(result)) {
|
|
481
476
|
yield { delta: { json: result } };
|
|
482
477
|
}
|
|
483
|
-
if (text) {
|
|
484
|
-
yield {
|
|
485
|
-
progress: { event: "message", role: "agent", message: [{ type: "text", content: text }] },
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
478
|
return;
|
|
489
479
|
}
|
|
490
480
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AFSOptions } from "@aigne/afs";
|
|
2
2
|
import { type ZodType, z } from "zod";
|
|
3
|
-
import type { AgentHooks, TaskRenderMode } from "../agents/agent.js";
|
|
3
|
+
import type { Agent, AgentHooks, TaskRenderMode } from "../agents/agent.js";
|
|
4
4
|
import type { LoadOptions } from "./index.js";
|
|
5
5
|
import { chatModelSchema, imageModelSchema } from "./schema.js";
|
|
6
6
|
export interface HooksSchema {
|
|
@@ -65,6 +65,7 @@ export interface AgentSchema {
|
|
|
65
65
|
context?: AFSContextSchema;
|
|
66
66
|
});
|
|
67
67
|
shareAFS?: boolean;
|
|
68
|
+
historyConfig?: Agent["historyConfig"];
|
|
68
69
|
[key: string]: unknown;
|
|
69
70
|
}
|
|
70
71
|
export declare function parseAgentFile(path: string, data: any, options: LoadOptions): Promise<AgentSchema>;
|
|
@@ -100,6 +100,14 @@ const getAgentSchema = ({ filepath }) => {
|
|
|
100
100
|
})),
|
|
101
101
|
])),
|
|
102
102
|
shareAFS: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
|
|
103
|
+
historyConfig: (0, schema_js_1.camelizeSchema)((0, schema_js_1.optionalize)(zod_1.z.object({
|
|
104
|
+
enabled: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
|
|
105
|
+
record: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
|
|
106
|
+
inject: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
|
|
107
|
+
use_old_memory: (0, schema_js_1.optionalize)(zod_1.z.boolean()),
|
|
108
|
+
maxTokens: (0, schema_js_1.optionalize)(zod_1.z.number().int().positive()),
|
|
109
|
+
maxItems: (0, schema_js_1.optionalize)(zod_1.z.number().int().positive()),
|
|
110
|
+
}))),
|
|
103
111
|
});
|
|
104
112
|
return (0, schema_js_1.camelizeSchema)(baseAgentSchema.passthrough());
|
|
105
113
|
});
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import type { AFSListOptions } from "@aigne/afs";
|
|
1
2
|
import type { Agent } from "../../../agents/agent.js";
|
|
2
|
-
export declare function getHistories(agent
|
|
3
|
+
export declare function getHistories({ filter, agent, }: {
|
|
4
|
+
filter: AFSListOptions["filter"];
|
|
5
|
+
agent: Agent;
|
|
6
|
+
}): Promise<{
|
|
3
7
|
role: "user" | "agent";
|
|
4
8
|
content: unknown;
|
|
5
9
|
}[]>;
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getHistories = getHistories;
|
|
4
4
|
const afs_history_1 = require("@aigne/afs-history");
|
|
5
5
|
const type_utils_js_1 = require("../../../utils/type-utils.js");
|
|
6
|
-
async function getHistories(agent) {
|
|
6
|
+
async function getHistories({ filter, agent, }) {
|
|
7
7
|
const afs = agent?.afs;
|
|
8
8
|
if (!afs)
|
|
9
9
|
return [];
|
|
@@ -11,6 +11,7 @@ async function getHistories(agent) {
|
|
|
11
11
|
if (!historyModule)
|
|
12
12
|
return [];
|
|
13
13
|
const history = (await afs.list(historyModule.path, {
|
|
14
|
+
filter,
|
|
14
15
|
limit: agent.historyConfig?.maxItems || 10,
|
|
15
16
|
orderBy: [["createdAt", "desc"]],
|
|
16
17
|
})).data;
|
|
@@ -20,7 +20,14 @@ function createAFSContext(agent, context) {
|
|
|
20
20
|
get histories() {
|
|
21
21
|
if (!agent)
|
|
22
22
|
return Promise.resolve([]);
|
|
23
|
-
return (0, history_js_1.getHistories)(
|
|
23
|
+
return (0, history_js_1.getHistories)({
|
|
24
|
+
agent,
|
|
25
|
+
filter: {
|
|
26
|
+
agentId: agent.name,
|
|
27
|
+
userId: context?.userContext.userId,
|
|
28
|
+
sessionId: context?.userContext.sessionId,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
24
31
|
},
|
|
25
32
|
get skills() {
|
|
26
33
|
const afs = agent?.afs;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { GetPromptResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
import { Agent, type
|
|
2
|
+
import { Agent, type Message } from "../agents/agent.js";
|
|
3
3
|
import { type AIAgent } from "../agents/ai-agent.js";
|
|
4
|
-
import type
|
|
4
|
+
import { type ChatModel, type ChatModelInput, type ChatModelInputMessage } from "../agents/chat-model.js";
|
|
5
5
|
import { type FileUnionContent } from "../agents/model.js";
|
|
6
|
+
import type { Context } from "../aigne/context.js";
|
|
6
7
|
import { ChatMessagesTemplate } from "./template.js";
|
|
7
8
|
export interface PromptBuilderOptions {
|
|
8
9
|
instructions?: string | ChatMessagesTemplate;
|
|
9
10
|
workingDir?: string;
|
|
10
11
|
}
|
|
11
|
-
export interface PromptBuildOptions
|
|
12
|
+
export interface PromptBuildOptions {
|
|
13
|
+
context?: Context;
|
|
12
14
|
agent?: AIAgent;
|
|
13
15
|
input?: Message;
|
|
14
16
|
model?: ChatModel;
|
|
@@ -37,10 +39,12 @@ export declare class PromptBuilder {
|
|
|
37
39
|
}>;
|
|
38
40
|
private getTemplateVariables;
|
|
39
41
|
private buildMessages;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
protected deprecatedMemories(message: string | undefined, options: PromptBuildOptions): Promise<ChatModelInputMessage[]>;
|
|
43
|
+
getHistories({ agentId, userId, sessionId, ...options }: PromptBuildOptions & {
|
|
44
|
+
agentId?: string;
|
|
45
|
+
userId?: string;
|
|
46
|
+
sessionId?: string;
|
|
47
|
+
}): Promise<ChatModelInputMessage[]>;
|
|
44
48
|
private refineMessages;
|
|
45
49
|
private convertMemoriesToMessages;
|
|
46
50
|
private buildResponseFormat;
|
|
@@ -8,6 +8,7 @@ const zod_1 = require("zod");
|
|
|
8
8
|
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
9
9
|
const agent_js_1 = require("../agents/agent.js");
|
|
10
10
|
const ai_agent_js_1 = require("../agents/ai-agent.js");
|
|
11
|
+
const chat_model_js_1 = require("../agents/chat-model.js");
|
|
11
12
|
const model_js_1 = require("../agents/model.js");
|
|
12
13
|
const schema_js_1 = require("../loader/schema.js");
|
|
13
14
|
const json_schema_js_1 = require("../utils/json-schema.js");
|
|
@@ -100,6 +101,9 @@ class PromptBuilder {
|
|
|
100
101
|
}
|
|
101
102
|
async buildMessages(options) {
|
|
102
103
|
const { input } = options;
|
|
104
|
+
const agentId = options.agent?.name;
|
|
105
|
+
const userId = options.context?.userContext.userId;
|
|
106
|
+
const sessionId = options.context?.userContext.sessionId;
|
|
103
107
|
const inputKey = options.agent?.inputKey;
|
|
104
108
|
const message = inputKey && typeof input?.[inputKey] === "string" ? input[inputKey] : undefined;
|
|
105
109
|
const [messages, otherCustomMessages] = (0, type_utils_js_1.partition)((await (typeof this.instructions === "string"
|
|
@@ -109,6 +113,50 @@ class PromptBuilder {
|
|
|
109
113
|
const files = (0, type_utils_js_1.flat)(inputFileKey
|
|
110
114
|
? (0, type_utils_js_1.checkArguments)("Check input files", (0, schema_js_1.optionalize)(model_js_1.fileUnionContentsSchema), input?.[inputFileKey])
|
|
111
115
|
: null);
|
|
116
|
+
const historyConfig = options.agent?.historyConfig;
|
|
117
|
+
const injectHistory = historyConfig?.inject === true || (historyConfig?.inject !== false && historyConfig?.enabled);
|
|
118
|
+
if (injectHistory) {
|
|
119
|
+
if (historyConfig.useOldMemory) {
|
|
120
|
+
messages.push(...(await this.deprecatedMemories(message, options)));
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const history = await this.getHistories({ ...options, agentId, userId, sessionId });
|
|
124
|
+
messages.push(...history);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// if the agent is using structured stream mode, add the instructions
|
|
128
|
+
const { structuredStreamMode, outputSchema } = options.agent || {};
|
|
129
|
+
if (structuredStreamMode && outputSchema) {
|
|
130
|
+
const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
|
|
131
|
+
PromptBuilder.from(structured_stream_instructions_js_1.STRUCTURED_STREAM_INSTRUCTIONS.instructions);
|
|
132
|
+
messages.push(...(await instructions.buildMessages({
|
|
133
|
+
input: {
|
|
134
|
+
...input,
|
|
135
|
+
outputJsonSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(outputSchema),
|
|
136
|
+
},
|
|
137
|
+
})));
|
|
138
|
+
}
|
|
139
|
+
messages.push(...otherCustomMessages);
|
|
140
|
+
if (message || files.length) {
|
|
141
|
+
const content = [];
|
|
142
|
+
if (message &&
|
|
143
|
+
// avoid duplicate user messages: developer may have already included the message in the messages
|
|
144
|
+
!otherCustomMessages.some((i) => i.role === "user" &&
|
|
145
|
+
(typeof i.content === "string"
|
|
146
|
+
? i.content.includes(message)
|
|
147
|
+
: i.content?.some((c) => c.type === "text" && c.text.includes(message))))) {
|
|
148
|
+
content.push({ type: "text", text: message });
|
|
149
|
+
}
|
|
150
|
+
if (files.length)
|
|
151
|
+
content.push(...files);
|
|
152
|
+
if (content.length) {
|
|
153
|
+
messages.push({ role: "user", content });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return this.refineMessages(options, messages);
|
|
157
|
+
}
|
|
158
|
+
async deprecatedMemories(message, options) {
|
|
159
|
+
const messages = [];
|
|
112
160
|
const memories = [];
|
|
113
161
|
if (options.agent && options.context) {
|
|
114
162
|
memories.push(...(await options.agent.retrieveMemories({ search: message }, { context: options.context })));
|
|
@@ -117,7 +165,7 @@ class PromptBuilder {
|
|
|
117
165
|
memories.push(...options.context.memories);
|
|
118
166
|
}
|
|
119
167
|
const afs = options.agent?.afs;
|
|
120
|
-
if (afs && options.agent?.historyConfig?.
|
|
168
|
+
if (afs && options.agent?.historyConfig?.enabled) {
|
|
121
169
|
const historyModule = (await afs.listModules()).find((m) => m.module instanceof afs_history_1.AFSHistory);
|
|
122
170
|
if (historyModule) {
|
|
123
171
|
const history = await afs.list(historyModule.path, {
|
|
@@ -163,38 +211,9 @@ class PromptBuilder {
|
|
|
163
211
|
}
|
|
164
212
|
if (memories.length)
|
|
165
213
|
messages.push(...(await this.convertMemoriesToMessages(memories, options)));
|
|
166
|
-
|
|
167
|
-
const { structuredStreamMode, outputSchema } = options.agent || {};
|
|
168
|
-
if (structuredStreamMode && outputSchema) {
|
|
169
|
-
const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
|
|
170
|
-
PromptBuilder.from(structured_stream_instructions_js_1.STRUCTURED_STREAM_INSTRUCTIONS.instructions);
|
|
171
|
-
messages.push(...(await instructions.buildMessages({
|
|
172
|
-
input: {
|
|
173
|
-
...input,
|
|
174
|
-
outputJsonSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(outputSchema),
|
|
175
|
-
},
|
|
176
|
-
})));
|
|
177
|
-
}
|
|
178
|
-
if (message || files.length) {
|
|
179
|
-
const content = [];
|
|
180
|
-
if (message &&
|
|
181
|
-
// avoid duplicate user messages: developer may have already included the message in the custom user messages
|
|
182
|
-
!otherCustomMessages.some((i) => i.role === "user" &&
|
|
183
|
-
(typeof i.content === "string"
|
|
184
|
-
? i.content.includes(message)
|
|
185
|
-
: i.content?.some((c) => c.type === "text" && c.text.includes(message))))) {
|
|
186
|
-
content.push({ type: "text", text: message });
|
|
187
|
-
}
|
|
188
|
-
if (files.length)
|
|
189
|
-
content.push(...files);
|
|
190
|
-
if (content.length) {
|
|
191
|
-
messages.push({ role: "user", content });
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
messages.push(...otherCustomMessages);
|
|
195
|
-
return this.refineMessages(options, messages);
|
|
214
|
+
return messages;
|
|
196
215
|
}
|
|
197
|
-
async getHistories(options) {
|
|
216
|
+
async getHistories({ agentId, userId, sessionId, ...options }) {
|
|
198
217
|
const { agent } = options;
|
|
199
218
|
const afs = agent?.afs;
|
|
200
219
|
if (!afs)
|
|
@@ -203,24 +222,21 @@ class PromptBuilder {
|
|
|
203
222
|
if (!historyModule)
|
|
204
223
|
return [];
|
|
205
224
|
const history = (await afs.list(historyModule.path, {
|
|
225
|
+
filter: { agentId, userId, sessionId },
|
|
206
226
|
limit: agent.historyConfig?.maxItems || 10,
|
|
207
227
|
orderBy: [["createdAt", "desc"]],
|
|
208
|
-
})).data;
|
|
209
|
-
return history
|
|
210
|
-
.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const { input, output } = i.content;
|
|
215
|
-
if (
|
|
216
|
-
return;
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
];
|
|
221
|
-
})
|
|
222
|
-
.filter(type_utils_js_1.isNonNullable)
|
|
223
|
-
.flat();
|
|
228
|
+
})).data.reverse();
|
|
229
|
+
return (await Promise.all(history.map(async (i) => {
|
|
230
|
+
if (Array.isArray(i.content?.messages) &&
|
|
231
|
+
i.content.messages.every((m) => chat_model_js_1.roleSchema.parse(m?.role))) {
|
|
232
|
+
return i.content.messages;
|
|
233
|
+
}
|
|
234
|
+
const { input, output } = i.content || {};
|
|
235
|
+
if (input && output) {
|
|
236
|
+
return await this.convertMemoriesToMessages([{ content: { input, output } }], options);
|
|
237
|
+
}
|
|
238
|
+
return [];
|
|
239
|
+
}))).flat();
|
|
224
240
|
}
|
|
225
241
|
refineMessages(options, messages) {
|
|
226
242
|
const { autoReorderSystemMessages, autoMergeSystemMessages } = options.agent ?? {};
|
|
@@ -9,7 +9,7 @@ import type { Memory, MemoryAgent } from "../memory/memory.js";
|
|
|
9
9
|
import type { MemoryRecorderInput } from "../memory/recorder.js";
|
|
10
10
|
import type { MemoryRetrieverInput } from "../memory/retriever.js";
|
|
11
11
|
import { type Nullish, type PromiseOrValue, type XOr } from "../utils/type-utils.js";
|
|
12
|
-
import type { ChatModel } from "./chat-model.js";
|
|
12
|
+
import type { ChatModel, ChatModelInputMessage } from "./chat-model.js";
|
|
13
13
|
import type { GuideRailAgent, GuideRailAgentOutput } from "./guide-rail-agent.js";
|
|
14
14
|
import type { ImageModel } from "./image-model.js";
|
|
15
15
|
import { type GetterSchema, type TransferAgentOutput } from "./types.js";
|
|
@@ -350,7 +350,20 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
350
350
|
*/
|
|
351
351
|
private disableEvents?;
|
|
352
352
|
historyConfig?: {
|
|
353
|
-
|
|
353
|
+
/**
|
|
354
|
+
* Whether to enable history recording and injection
|
|
355
|
+
* @default false
|
|
356
|
+
*/
|
|
357
|
+
enabled?: boolean;
|
|
358
|
+
/**
|
|
359
|
+
* Whether to record history entries, default to enabled when history is enabled
|
|
360
|
+
*/
|
|
361
|
+
record?: boolean;
|
|
362
|
+
/**
|
|
363
|
+
* Whether to inject history entries into the context, default to enabled when history is enabled
|
|
364
|
+
*/
|
|
365
|
+
inject?: boolean;
|
|
366
|
+
useOldMemory?: boolean;
|
|
354
367
|
maxTokens?: number;
|
|
355
368
|
maxItems?: number;
|
|
356
369
|
};
|
|
@@ -455,7 +468,9 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
455
468
|
* @param options Invocation options
|
|
456
469
|
* @returns Final processed output
|
|
457
470
|
*/
|
|
458
|
-
protected processAgentOutput(input: I, output: Exclude<AgentResponse<O>, AgentResponseStream<O>>, options: AgentInvokeOptions
|
|
471
|
+
protected processAgentOutput(input: I, output: Exclude<AgentResponse<O>, AgentResponseStream<O>>, { messages, ...options }: AgentInvokeOptions & {
|
|
472
|
+
messages?: ChatModelInputMessage[];
|
|
473
|
+
}): Promise<O>;
|
|
459
474
|
/**
|
|
460
475
|
* Process errors that occur during agent execution
|
|
461
476
|
*
|
|
@@ -785,29 +800,29 @@ export interface AgentResponseProgress {
|
|
|
785
800
|
error: Error;
|
|
786
801
|
} | {
|
|
787
802
|
event: "message";
|
|
788
|
-
|
|
789
|
-
message: ({
|
|
790
|
-
type: "text";
|
|
791
|
-
content: string;
|
|
792
|
-
} | {
|
|
793
|
-
type: "thinking";
|
|
794
|
-
thoughts: string;
|
|
795
|
-
} | {
|
|
796
|
-
type: "tool_use";
|
|
797
|
-
toolUseId: string;
|
|
798
|
-
name: string;
|
|
799
|
-
input: unknown;
|
|
800
|
-
} | {
|
|
801
|
-
type: "tool_result";
|
|
802
|
-
toolUseId: string;
|
|
803
|
-
content: unknown;
|
|
804
|
-
})[];
|
|
803
|
+
message: ChatModelInputMessage;
|
|
805
804
|
}) & Omit<AgentEvent, "agent"> & {
|
|
806
805
|
agent: {
|
|
807
806
|
name: string;
|
|
808
807
|
};
|
|
809
808
|
};
|
|
810
809
|
}
|
|
810
|
+
export type AgentResponseProgressMessageItem = {
|
|
811
|
+
type: "text";
|
|
812
|
+
content: string;
|
|
813
|
+
} | {
|
|
814
|
+
type: "thinking";
|
|
815
|
+
thoughts: string;
|
|
816
|
+
} | {
|
|
817
|
+
type: "tool_use";
|
|
818
|
+
toolUseId: string;
|
|
819
|
+
name: string;
|
|
820
|
+
input: unknown;
|
|
821
|
+
} | {
|
|
822
|
+
type: "tool_result";
|
|
823
|
+
toolUseId: string;
|
|
824
|
+
content: unknown;
|
|
825
|
+
};
|
|
811
826
|
export declare function isAgentResponseProgress<T>(chunk: AgentResponseChunk<T>): chunk is AgentResponseProgress;
|
|
812
827
|
/**
|
|
813
828
|
* Creates a text delta for streaming responses
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AFSOptions } from "@aigne/afs";
|
|
2
2
|
import { type ZodType, z } from "zod";
|
|
3
|
-
import type { AgentHooks, TaskRenderMode } from "../agents/agent.js";
|
|
3
|
+
import type { Agent, AgentHooks, TaskRenderMode } from "../agents/agent.js";
|
|
4
4
|
import type { LoadOptions } from "./index.js";
|
|
5
5
|
import { chatModelSchema, imageModelSchema } from "./schema.js";
|
|
6
6
|
export interface HooksSchema {
|
|
@@ -65,6 +65,7 @@ export interface AgentSchema {
|
|
|
65
65
|
context?: AFSContextSchema;
|
|
66
66
|
});
|
|
67
67
|
shareAFS?: boolean;
|
|
68
|
+
historyConfig?: Agent["historyConfig"];
|
|
68
69
|
[key: string]: unknown;
|
|
69
70
|
}
|
|
70
71
|
export declare function parseAgentFile(path: string, data: any, options: LoadOptions): Promise<AgentSchema>;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import type { AFSListOptions } from "@aigne/afs";
|
|
1
2
|
import type { Agent } from "../../../agents/agent.js";
|
|
2
|
-
export declare function getHistories(agent
|
|
3
|
+
export declare function getHistories({ filter, agent, }: {
|
|
4
|
+
filter: AFSListOptions["filter"];
|
|
5
|
+
agent: Agent;
|
|
6
|
+
}): Promise<{
|
|
3
7
|
role: "user" | "agent";
|
|
4
8
|
content: unknown;
|
|
5
9
|
}[]>;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { GetPromptResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
import { Agent, type
|
|
2
|
+
import { Agent, type Message } from "../agents/agent.js";
|
|
3
3
|
import { type AIAgent } from "../agents/ai-agent.js";
|
|
4
|
-
import type
|
|
4
|
+
import { type ChatModel, type ChatModelInput, type ChatModelInputMessage } from "../agents/chat-model.js";
|
|
5
5
|
import { type FileUnionContent } from "../agents/model.js";
|
|
6
|
+
import type { Context } from "../aigne/context.js";
|
|
6
7
|
import { ChatMessagesTemplate } from "./template.js";
|
|
7
8
|
export interface PromptBuilderOptions {
|
|
8
9
|
instructions?: string | ChatMessagesTemplate;
|
|
9
10
|
workingDir?: string;
|
|
10
11
|
}
|
|
11
|
-
export interface PromptBuildOptions
|
|
12
|
+
export interface PromptBuildOptions {
|
|
13
|
+
context?: Context;
|
|
12
14
|
agent?: AIAgent;
|
|
13
15
|
input?: Message;
|
|
14
16
|
model?: ChatModel;
|
|
@@ -37,10 +39,12 @@ export declare class PromptBuilder {
|
|
|
37
39
|
}>;
|
|
38
40
|
private getTemplateVariables;
|
|
39
41
|
private buildMessages;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
protected deprecatedMemories(message: string | undefined, options: PromptBuildOptions): Promise<ChatModelInputMessage[]>;
|
|
43
|
+
getHistories({ agentId, userId, sessionId, ...options }: PromptBuildOptions & {
|
|
44
|
+
agentId?: string;
|
|
45
|
+
userId?: string;
|
|
46
|
+
sessionId?: string;
|
|
47
|
+
}): Promise<ChatModelInputMessage[]>;
|
|
44
48
|
private refineMessages;
|
|
45
49
|
private convertMemoriesToMessages;
|
|
46
50
|
private buildResponseFormat;
|
|
@@ -9,7 +9,7 @@ import type { Memory, MemoryAgent } from "../memory/memory.js";
|
|
|
9
9
|
import type { MemoryRecorderInput } from "../memory/recorder.js";
|
|
10
10
|
import type { MemoryRetrieverInput } from "../memory/retriever.js";
|
|
11
11
|
import { type Nullish, type PromiseOrValue, type XOr } from "../utils/type-utils.js";
|
|
12
|
-
import type { ChatModel } from "./chat-model.js";
|
|
12
|
+
import type { ChatModel, ChatModelInputMessage } from "./chat-model.js";
|
|
13
13
|
import type { GuideRailAgent, GuideRailAgentOutput } from "./guide-rail-agent.js";
|
|
14
14
|
import type { ImageModel } from "./image-model.js";
|
|
15
15
|
import { type GetterSchema, type TransferAgentOutput } from "./types.js";
|
|
@@ -350,7 +350,20 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
350
350
|
*/
|
|
351
351
|
private disableEvents?;
|
|
352
352
|
historyConfig?: {
|
|
353
|
-
|
|
353
|
+
/**
|
|
354
|
+
* Whether to enable history recording and injection
|
|
355
|
+
* @default false
|
|
356
|
+
*/
|
|
357
|
+
enabled?: boolean;
|
|
358
|
+
/**
|
|
359
|
+
* Whether to record history entries, default to enabled when history is enabled
|
|
360
|
+
*/
|
|
361
|
+
record?: boolean;
|
|
362
|
+
/**
|
|
363
|
+
* Whether to inject history entries into the context, default to enabled when history is enabled
|
|
364
|
+
*/
|
|
365
|
+
inject?: boolean;
|
|
366
|
+
useOldMemory?: boolean;
|
|
354
367
|
maxTokens?: number;
|
|
355
368
|
maxItems?: number;
|
|
356
369
|
};
|
|
@@ -455,7 +468,9 @@ export declare abstract class Agent<I extends Message = any, O extends Message =
|
|
|
455
468
|
* @param options Invocation options
|
|
456
469
|
* @returns Final processed output
|
|
457
470
|
*/
|
|
458
|
-
protected processAgentOutput(input: I, output: Exclude<AgentResponse<O>, AgentResponseStream<O>>, options: AgentInvokeOptions
|
|
471
|
+
protected processAgentOutput(input: I, output: Exclude<AgentResponse<O>, AgentResponseStream<O>>, { messages, ...options }: AgentInvokeOptions & {
|
|
472
|
+
messages?: ChatModelInputMessage[];
|
|
473
|
+
}): Promise<O>;
|
|
459
474
|
/**
|
|
460
475
|
* Process errors that occur during agent execution
|
|
461
476
|
*
|
|
@@ -785,29 +800,29 @@ export interface AgentResponseProgress {
|
|
|
785
800
|
error: Error;
|
|
786
801
|
} | {
|
|
787
802
|
event: "message";
|
|
788
|
-
|
|
789
|
-
message: ({
|
|
790
|
-
type: "text";
|
|
791
|
-
content: string;
|
|
792
|
-
} | {
|
|
793
|
-
type: "thinking";
|
|
794
|
-
thoughts: string;
|
|
795
|
-
} | {
|
|
796
|
-
type: "tool_use";
|
|
797
|
-
toolUseId: string;
|
|
798
|
-
name: string;
|
|
799
|
-
input: unknown;
|
|
800
|
-
} | {
|
|
801
|
-
type: "tool_result";
|
|
802
|
-
toolUseId: string;
|
|
803
|
-
content: unknown;
|
|
804
|
-
})[];
|
|
803
|
+
message: ChatModelInputMessage;
|
|
805
804
|
}) & Omit<AgentEvent, "agent"> & {
|
|
806
805
|
agent: {
|
|
807
806
|
name: string;
|
|
808
807
|
};
|
|
809
808
|
};
|
|
810
809
|
}
|
|
810
|
+
export type AgentResponseProgressMessageItem = {
|
|
811
|
+
type: "text";
|
|
812
|
+
content: string;
|
|
813
|
+
} | {
|
|
814
|
+
type: "thinking";
|
|
815
|
+
thoughts: string;
|
|
816
|
+
} | {
|
|
817
|
+
type: "tool_use";
|
|
818
|
+
toolUseId: string;
|
|
819
|
+
name: string;
|
|
820
|
+
input: unknown;
|
|
821
|
+
} | {
|
|
822
|
+
type: "tool_result";
|
|
823
|
+
toolUseId: string;
|
|
824
|
+
content: unknown;
|
|
825
|
+
};
|
|
811
826
|
export declare function isAgentResponseProgress<T>(chunk: AgentResponseChunk<T>): chunk is AgentResponseProgress;
|
|
812
827
|
/**
|
|
813
828
|
* Creates a text delta for streaming responses
|
package/lib/esm/agents/agent.js
CHANGED
|
@@ -415,11 +415,15 @@ export class Agent {
|
|
|
415
415
|
: isAsyncGenerator(response)
|
|
416
416
|
? asyncGeneratorToReadableStream(response)
|
|
417
417
|
: objectToAgentResponseStream(response);
|
|
418
|
+
const messages = [];
|
|
418
419
|
for await (const chunk of stream) {
|
|
419
420
|
mergeAgentResponseChunk(output, chunk);
|
|
420
421
|
yield chunk;
|
|
422
|
+
if (isAgentResponseProgress(chunk) && chunk.progress.event === "message") {
|
|
423
|
+
messages.push(chunk.progress.message);
|
|
424
|
+
}
|
|
421
425
|
}
|
|
422
|
-
let result = await this.processAgentOutput(input, output, options);
|
|
426
|
+
let result = await this.processAgentOutput(input, output, { ...options, messages });
|
|
423
427
|
if (attempt > 0) {
|
|
424
428
|
result = { ...result, $meta: { ...result.$meta, retries: attempt } };
|
|
425
429
|
}
|
|
@@ -516,7 +520,7 @@ export class Agent {
|
|
|
516
520
|
* @param options Invocation options
|
|
517
521
|
* @returns Final processed output
|
|
518
522
|
*/
|
|
519
|
-
async processAgentOutput(input, output, options) {
|
|
523
|
+
async processAgentOutput(input, output, { messages, ...options }) {
|
|
520
524
|
const { context } = options;
|
|
521
525
|
if (!isRecord(output)) {
|
|
522
526
|
throw new Error(`expect to return a record type such as {result: ...}, but got (${typeof output}): ${output}`);
|
|
@@ -528,8 +532,17 @@ export class Agent {
|
|
|
528
532
|
const o = await this.callHooks(["onSuccess", "onEnd"], { input, output: finalOutput }, options);
|
|
529
533
|
if (o?.output)
|
|
530
534
|
finalOutput = o.output;
|
|
531
|
-
if (this.historyConfig?.
|
|
532
|
-
this.
|
|
535
|
+
if (this.historyConfig?.record === true ||
|
|
536
|
+
(this.historyConfig?.record !== false && this.historyConfig?.enabled)) {
|
|
537
|
+
this.afs?.emit("agentSucceed", {
|
|
538
|
+
agentId: this.name,
|
|
539
|
+
userId: context.userContext.userId,
|
|
540
|
+
sessionId: context.userContext.sessionId,
|
|
541
|
+
input,
|
|
542
|
+
output: finalOutput,
|
|
543
|
+
messages,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
533
546
|
if (!this.disableEvents)
|
|
534
547
|
context.emit("agentSucceed", { agent: this, output: finalOutput });
|
|
535
548
|
return finalOutput;
|
|
@@ -313,8 +313,10 @@ export class AIAgent extends Agent {
|
|
|
313
313
|
yield {
|
|
314
314
|
progress: {
|
|
315
315
|
event: "message",
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
message: {
|
|
317
|
+
role: "user",
|
|
318
|
+
content: [{ type: "text", text: inputMessage }],
|
|
319
|
+
},
|
|
318
320
|
},
|
|
319
321
|
};
|
|
320
322
|
}
|
|
@@ -343,15 +345,22 @@ export class AIAgent extends Agent {
|
|
|
343
345
|
}
|
|
344
346
|
}
|
|
345
347
|
const { toolCalls, json, text, thoughts, files } = modelOutput;
|
|
346
|
-
if (text) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
348
|
+
if (text || thoughts) {
|
|
349
|
+
const content = [];
|
|
350
|
+
if (thoughts) {
|
|
351
|
+
content.push({ type: "text", text: thoughts, isThinking: true });
|
|
352
|
+
}
|
|
353
|
+
if (text) {
|
|
354
|
+
content.push({ type: "text", text });
|
|
355
|
+
}
|
|
356
|
+
if (content.length) {
|
|
357
|
+
yield {
|
|
358
|
+
progress: {
|
|
359
|
+
event: "message",
|
|
360
|
+
message: { role: "agent", content },
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
355
364
|
}
|
|
356
365
|
if (toolCalls?.length) {
|
|
357
366
|
if (this.keepTextInToolUses !== true) {
|
|
@@ -383,25 +392,14 @@ export class AIAgent extends Agent {
|
|
|
383
392
|
queue.killAndDrain();
|
|
384
393
|
}
|
|
385
394
|
}, this.toolCallsConcurrency || 1);
|
|
395
|
+
yield {
|
|
396
|
+
progress: { event: "message", message: { role: "agent", toolCalls } },
|
|
397
|
+
};
|
|
386
398
|
// Execute tools
|
|
387
399
|
for (const call of toolCalls) {
|
|
388
400
|
const tool = toolsMap.get(call.function.name);
|
|
389
401
|
if (!tool)
|
|
390
402
|
throw new Error(`Tool not found: ${call.function.name}`);
|
|
391
|
-
yield {
|
|
392
|
-
progress: {
|
|
393
|
-
event: "message",
|
|
394
|
-
role: "agent",
|
|
395
|
-
message: [
|
|
396
|
-
{
|
|
397
|
-
type: "tool_use",
|
|
398
|
-
name: call.function.name,
|
|
399
|
-
input: call.function.arguments,
|
|
400
|
-
toolUseId: call.id,
|
|
401
|
-
},
|
|
402
|
-
],
|
|
403
|
-
},
|
|
404
|
-
};
|
|
405
403
|
queue.push({ tool, call });
|
|
406
404
|
}
|
|
407
405
|
await queue.drained();
|
|
@@ -413,14 +411,11 @@ export class AIAgent extends Agent {
|
|
|
413
411
|
yield {
|
|
414
412
|
progress: {
|
|
415
413
|
event: "message",
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
content: output,
|
|
422
|
-
},
|
|
423
|
-
],
|
|
414
|
+
message: {
|
|
415
|
+
role: "tool",
|
|
416
|
+
toolCallId: call.id,
|
|
417
|
+
content: JSON.stringify(output),
|
|
418
|
+
},
|
|
424
419
|
},
|
|
425
420
|
};
|
|
426
421
|
}
|
|
@@ -444,11 +439,6 @@ export class AIAgent extends Agent {
|
|
|
444
439
|
if (!isEmpty(result)) {
|
|
445
440
|
yield { delta: { json: result } };
|
|
446
441
|
}
|
|
447
|
-
if (text) {
|
|
448
|
-
yield {
|
|
449
|
-
progress: { event: "message", role: "agent", message: [{ type: "text", content: text }] },
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
442
|
return;
|
|
453
443
|
}
|
|
454
444
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AFSOptions } from "@aigne/afs";
|
|
2
2
|
import { type ZodType, z } from "zod";
|
|
3
|
-
import type { AgentHooks, TaskRenderMode } from "../agents/agent.js";
|
|
3
|
+
import type { Agent, AgentHooks, TaskRenderMode } from "../agents/agent.js";
|
|
4
4
|
import type { LoadOptions } from "./index.js";
|
|
5
5
|
import { chatModelSchema, imageModelSchema } from "./schema.js";
|
|
6
6
|
export interface HooksSchema {
|
|
@@ -65,6 +65,7 @@ export interface AgentSchema {
|
|
|
65
65
|
context?: AFSContextSchema;
|
|
66
66
|
});
|
|
67
67
|
shareAFS?: boolean;
|
|
68
|
+
historyConfig?: Agent["historyConfig"];
|
|
68
69
|
[key: string]: unknown;
|
|
69
70
|
}
|
|
70
71
|
export declare function parseAgentFile(path: string, data: any, options: LoadOptions): Promise<AgentSchema>;
|
|
@@ -95,6 +95,14 @@ export const getAgentSchema = ({ filepath }) => {
|
|
|
95
95
|
})),
|
|
96
96
|
])),
|
|
97
97
|
shareAFS: optionalize(z.boolean()),
|
|
98
|
+
historyConfig: camelizeSchema(optionalize(z.object({
|
|
99
|
+
enabled: optionalize(z.boolean()),
|
|
100
|
+
record: optionalize(z.boolean()),
|
|
101
|
+
inject: optionalize(z.boolean()),
|
|
102
|
+
use_old_memory: optionalize(z.boolean()),
|
|
103
|
+
maxTokens: optionalize(z.number().int().positive()),
|
|
104
|
+
maxItems: optionalize(z.number().int().positive()),
|
|
105
|
+
}))),
|
|
98
106
|
});
|
|
99
107
|
return camelizeSchema(baseAgentSchema.passthrough());
|
|
100
108
|
});
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import type { AFSListOptions } from "@aigne/afs";
|
|
1
2
|
import type { Agent } from "../../../agents/agent.js";
|
|
2
|
-
export declare function getHistories(agent
|
|
3
|
+
export declare function getHistories({ filter, agent, }: {
|
|
4
|
+
filter: AFSListOptions["filter"];
|
|
5
|
+
agent: Agent;
|
|
6
|
+
}): Promise<{
|
|
3
7
|
role: "user" | "agent";
|
|
4
8
|
content: unknown;
|
|
5
9
|
}[]>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AFSHistory } from "@aigne/afs-history";
|
|
2
2
|
import { isNonNullable } from "../../../utils/type-utils.js";
|
|
3
|
-
export async function getHistories(agent) {
|
|
3
|
+
export async function getHistories({ filter, agent, }) {
|
|
4
4
|
const afs = agent?.afs;
|
|
5
5
|
if (!afs)
|
|
6
6
|
return [];
|
|
@@ -8,6 +8,7 @@ export async function getHistories(agent) {
|
|
|
8
8
|
if (!historyModule)
|
|
9
9
|
return [];
|
|
10
10
|
const history = (await afs.list(historyModule.path, {
|
|
11
|
+
filter,
|
|
11
12
|
limit: agent.historyConfig?.maxItems || 10,
|
|
12
13
|
orderBy: [["createdAt", "desc"]],
|
|
13
14
|
})).data;
|
|
@@ -17,7 +17,14 @@ export function createAFSContext(agent, context) {
|
|
|
17
17
|
get histories() {
|
|
18
18
|
if (!agent)
|
|
19
19
|
return Promise.resolve([]);
|
|
20
|
-
return getHistories(
|
|
20
|
+
return getHistories({
|
|
21
|
+
agent,
|
|
22
|
+
filter: {
|
|
23
|
+
agentId: agent.name,
|
|
24
|
+
userId: context?.userContext.userId,
|
|
25
|
+
sessionId: context?.userContext.sessionId,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
21
28
|
},
|
|
22
29
|
get skills() {
|
|
23
30
|
const afs = agent?.afs;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { GetPromptResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
import { Agent, type
|
|
2
|
+
import { Agent, type Message } from "../agents/agent.js";
|
|
3
3
|
import { type AIAgent } from "../agents/ai-agent.js";
|
|
4
|
-
import type
|
|
4
|
+
import { type ChatModel, type ChatModelInput, type ChatModelInputMessage } from "../agents/chat-model.js";
|
|
5
5
|
import { type FileUnionContent } from "../agents/model.js";
|
|
6
|
+
import type { Context } from "../aigne/context.js";
|
|
6
7
|
import { ChatMessagesTemplate } from "./template.js";
|
|
7
8
|
export interface PromptBuilderOptions {
|
|
8
9
|
instructions?: string | ChatMessagesTemplate;
|
|
9
10
|
workingDir?: string;
|
|
10
11
|
}
|
|
11
|
-
export interface PromptBuildOptions
|
|
12
|
+
export interface PromptBuildOptions {
|
|
13
|
+
context?: Context;
|
|
12
14
|
agent?: AIAgent;
|
|
13
15
|
input?: Message;
|
|
14
16
|
model?: ChatModel;
|
|
@@ -37,10 +39,12 @@ export declare class PromptBuilder {
|
|
|
37
39
|
}>;
|
|
38
40
|
private getTemplateVariables;
|
|
39
41
|
private buildMessages;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
protected deprecatedMemories(message: string | undefined, options: PromptBuildOptions): Promise<ChatModelInputMessage[]>;
|
|
43
|
+
getHistories({ agentId, userId, sessionId, ...options }: PromptBuildOptions & {
|
|
44
|
+
agentId?: string;
|
|
45
|
+
userId?: string;
|
|
46
|
+
sessionId?: string;
|
|
47
|
+
}): Promise<ChatModelInputMessage[]>;
|
|
44
48
|
private refineMessages;
|
|
45
49
|
private convertMemoriesToMessages;
|
|
46
50
|
private buildResponseFormat;
|
|
@@ -5,6 +5,7 @@ import { ZodObject } from "zod";
|
|
|
5
5
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
6
6
|
import { Agent } from "../agents/agent.js";
|
|
7
7
|
import { DEFAULT_OUTPUT_FILE_KEY, DEFAULT_OUTPUT_KEY } from "../agents/ai-agent.js";
|
|
8
|
+
import { roleSchema, } from "../agents/chat-model.js";
|
|
8
9
|
import { fileUnionContentsSchema } from "../agents/model.js";
|
|
9
10
|
import { optionalize } from "../loader/schema.js";
|
|
10
11
|
import { outputSchemaToResponseFormatSchema } from "../utils/json-schema.js";
|
|
@@ -97,6 +98,9 @@ export class PromptBuilder {
|
|
|
97
98
|
}
|
|
98
99
|
async buildMessages(options) {
|
|
99
100
|
const { input } = options;
|
|
101
|
+
const agentId = options.agent?.name;
|
|
102
|
+
const userId = options.context?.userContext.userId;
|
|
103
|
+
const sessionId = options.context?.userContext.sessionId;
|
|
100
104
|
const inputKey = options.agent?.inputKey;
|
|
101
105
|
const message = inputKey && typeof input?.[inputKey] === "string" ? input[inputKey] : undefined;
|
|
102
106
|
const [messages, otherCustomMessages] = partition((await (typeof this.instructions === "string"
|
|
@@ -106,6 +110,50 @@ export class PromptBuilder {
|
|
|
106
110
|
const files = flat(inputFileKey
|
|
107
111
|
? checkArguments("Check input files", optionalize(fileUnionContentsSchema), input?.[inputFileKey])
|
|
108
112
|
: null);
|
|
113
|
+
const historyConfig = options.agent?.historyConfig;
|
|
114
|
+
const injectHistory = historyConfig?.inject === true || (historyConfig?.inject !== false && historyConfig?.enabled);
|
|
115
|
+
if (injectHistory) {
|
|
116
|
+
if (historyConfig.useOldMemory) {
|
|
117
|
+
messages.push(...(await this.deprecatedMemories(message, options)));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const history = await this.getHistories({ ...options, agentId, userId, sessionId });
|
|
121
|
+
messages.push(...history);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// if the agent is using structured stream mode, add the instructions
|
|
125
|
+
const { structuredStreamMode, outputSchema } = options.agent || {};
|
|
126
|
+
if (structuredStreamMode && outputSchema) {
|
|
127
|
+
const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
|
|
128
|
+
PromptBuilder.from(STRUCTURED_STREAM_INSTRUCTIONS.instructions);
|
|
129
|
+
messages.push(...(await instructions.buildMessages({
|
|
130
|
+
input: {
|
|
131
|
+
...input,
|
|
132
|
+
outputJsonSchema: zodToJsonSchema(outputSchema),
|
|
133
|
+
},
|
|
134
|
+
})));
|
|
135
|
+
}
|
|
136
|
+
messages.push(...otherCustomMessages);
|
|
137
|
+
if (message || files.length) {
|
|
138
|
+
const content = [];
|
|
139
|
+
if (message &&
|
|
140
|
+
// avoid duplicate user messages: developer may have already included the message in the messages
|
|
141
|
+
!otherCustomMessages.some((i) => i.role === "user" &&
|
|
142
|
+
(typeof i.content === "string"
|
|
143
|
+
? i.content.includes(message)
|
|
144
|
+
: i.content?.some((c) => c.type === "text" && c.text.includes(message))))) {
|
|
145
|
+
content.push({ type: "text", text: message });
|
|
146
|
+
}
|
|
147
|
+
if (files.length)
|
|
148
|
+
content.push(...files);
|
|
149
|
+
if (content.length) {
|
|
150
|
+
messages.push({ role: "user", content });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return this.refineMessages(options, messages);
|
|
154
|
+
}
|
|
155
|
+
async deprecatedMemories(message, options) {
|
|
156
|
+
const messages = [];
|
|
109
157
|
const memories = [];
|
|
110
158
|
if (options.agent && options.context) {
|
|
111
159
|
memories.push(...(await options.agent.retrieveMemories({ search: message }, { context: options.context })));
|
|
@@ -114,7 +162,7 @@ export class PromptBuilder {
|
|
|
114
162
|
memories.push(...options.context.memories);
|
|
115
163
|
}
|
|
116
164
|
const afs = options.agent?.afs;
|
|
117
|
-
if (afs && options.agent?.historyConfig?.
|
|
165
|
+
if (afs && options.agent?.historyConfig?.enabled) {
|
|
118
166
|
const historyModule = (await afs.listModules()).find((m) => m.module instanceof AFSHistory);
|
|
119
167
|
if (historyModule) {
|
|
120
168
|
const history = await afs.list(historyModule.path, {
|
|
@@ -160,38 +208,9 @@ export class PromptBuilder {
|
|
|
160
208
|
}
|
|
161
209
|
if (memories.length)
|
|
162
210
|
messages.push(...(await this.convertMemoriesToMessages(memories, options)));
|
|
163
|
-
|
|
164
|
-
const { structuredStreamMode, outputSchema } = options.agent || {};
|
|
165
|
-
if (structuredStreamMode && outputSchema) {
|
|
166
|
-
const instructions = options.agent?.customStructuredStreamInstructions?.instructions ||
|
|
167
|
-
PromptBuilder.from(STRUCTURED_STREAM_INSTRUCTIONS.instructions);
|
|
168
|
-
messages.push(...(await instructions.buildMessages({
|
|
169
|
-
input: {
|
|
170
|
-
...input,
|
|
171
|
-
outputJsonSchema: zodToJsonSchema(outputSchema),
|
|
172
|
-
},
|
|
173
|
-
})));
|
|
174
|
-
}
|
|
175
|
-
if (message || files.length) {
|
|
176
|
-
const content = [];
|
|
177
|
-
if (message &&
|
|
178
|
-
// avoid duplicate user messages: developer may have already included the message in the custom user messages
|
|
179
|
-
!otherCustomMessages.some((i) => i.role === "user" &&
|
|
180
|
-
(typeof i.content === "string"
|
|
181
|
-
? i.content.includes(message)
|
|
182
|
-
: i.content?.some((c) => c.type === "text" && c.text.includes(message))))) {
|
|
183
|
-
content.push({ type: "text", text: message });
|
|
184
|
-
}
|
|
185
|
-
if (files.length)
|
|
186
|
-
content.push(...files);
|
|
187
|
-
if (content.length) {
|
|
188
|
-
messages.push({ role: "user", content });
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
messages.push(...otherCustomMessages);
|
|
192
|
-
return this.refineMessages(options, messages);
|
|
211
|
+
return messages;
|
|
193
212
|
}
|
|
194
|
-
async getHistories(options) {
|
|
213
|
+
async getHistories({ agentId, userId, sessionId, ...options }) {
|
|
195
214
|
const { agent } = options;
|
|
196
215
|
const afs = agent?.afs;
|
|
197
216
|
if (!afs)
|
|
@@ -200,24 +219,21 @@ export class PromptBuilder {
|
|
|
200
219
|
if (!historyModule)
|
|
201
220
|
return [];
|
|
202
221
|
const history = (await afs.list(historyModule.path, {
|
|
222
|
+
filter: { agentId, userId, sessionId },
|
|
203
223
|
limit: agent.historyConfig?.maxItems || 10,
|
|
204
224
|
orderBy: [["createdAt", "desc"]],
|
|
205
|
-
})).data;
|
|
206
|
-
return history
|
|
207
|
-
.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const { input, output } = i.content;
|
|
212
|
-
if (
|
|
213
|
-
return;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
];
|
|
218
|
-
})
|
|
219
|
-
.filter(isNonNullable)
|
|
220
|
-
.flat();
|
|
225
|
+
})).data.reverse();
|
|
226
|
+
return (await Promise.all(history.map(async (i) => {
|
|
227
|
+
if (Array.isArray(i.content?.messages) &&
|
|
228
|
+
i.content.messages.every((m) => roleSchema.parse(m?.role))) {
|
|
229
|
+
return i.content.messages;
|
|
230
|
+
}
|
|
231
|
+
const { input, output } = i.content || {};
|
|
232
|
+
if (input && output) {
|
|
233
|
+
return await this.convertMemoriesToMessages([{ content: { input, output } }], options);
|
|
234
|
+
}
|
|
235
|
+
return [];
|
|
236
|
+
}))).flat();
|
|
221
237
|
}
|
|
222
238
|
refineMessages(options, messages) {
|
|
223
239
|
const { autoReorderSystemMessages, autoMergeSystemMessages } = options.agent ?? {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/core",
|
|
3
|
-
"version": "1.72.0-beta.
|
|
3
|
+
"version": "1.72.0-beta.7",
|
|
4
4
|
"description": "The functional core of agentic AI",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -93,10 +93,10 @@
|
|
|
93
93
|
"zod": "^3.25.67",
|
|
94
94
|
"zod-from-json-schema": "^0.0.5",
|
|
95
95
|
"zod-to-json-schema": "^3.24.6",
|
|
96
|
-
"@aigne/afs": "^1.4.0-beta.
|
|
97
|
-
"@aigne/afs-history": "^1.2.0-beta.
|
|
98
|
-
"@aigne/
|
|
99
|
-
"@aigne/
|
|
96
|
+
"@aigne/afs": "^1.4.0-beta.4",
|
|
97
|
+
"@aigne/afs-history": "^1.2.0-beta.4",
|
|
98
|
+
"@aigne/observability-api": "^0.11.14-beta.1",
|
|
99
|
+
"@aigne/platform-helpers": "^0.6.7-beta"
|
|
100
100
|
},
|
|
101
101
|
"devDependencies": {
|
|
102
102
|
"@types/bun": "^1.2.22",
|