@aigne/core 1.1.0-beta.5 → 1.3.0

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.
Files changed (105) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/lib/cjs/agents/agent.d.ts +37 -33
  3. package/lib/cjs/agents/agent.js +68 -28
  4. package/lib/cjs/agents/ai-agent.d.ts +8 -12
  5. package/lib/cjs/agents/ai-agent.js +17 -35
  6. package/lib/cjs/agents/mcp-agent.d.ts +25 -9
  7. package/lib/cjs/agents/mcp-agent.js +61 -14
  8. package/lib/cjs/agents/memory.d.ts +26 -0
  9. package/lib/cjs/agents/memory.js +38 -0
  10. package/lib/cjs/agents/types.d.ts +4 -3
  11. package/lib/cjs/agents/types.js +11 -1
  12. package/lib/cjs/agents/user-agent.d.ts +24 -0
  13. package/lib/cjs/agents/user-agent.js +62 -0
  14. package/lib/cjs/execution-engine/context.d.ts +35 -5
  15. package/lib/cjs/execution-engine/execution-engine.d.ts +64 -0
  16. package/lib/cjs/execution-engine/execution-engine.js +136 -0
  17. package/lib/cjs/execution-engine/index.d.ts +4 -46
  18. package/lib/cjs/execution-engine/index.js +17 -193
  19. package/lib/cjs/execution-engine/message-queue.d.ts +17 -2
  20. package/lib/cjs/execution-engine/message-queue.js +37 -1
  21. package/lib/cjs/execution-engine/utils.d.ts +4 -0
  22. package/lib/cjs/execution-engine/utils.js +32 -0
  23. package/lib/cjs/index.d.ts +14 -11
  24. package/lib/cjs/index.js +14 -11
  25. package/lib/{dts/models/chat.d.ts → cjs/models/chat-model.d.ts} +15 -12
  26. package/lib/cjs/models/{chat.js → chat-model.js} +5 -5
  27. package/lib/cjs/models/claude-chat-model.d.ts +17 -0
  28. package/lib/cjs/models/claude-chat-model.js +199 -0
  29. package/lib/cjs/models/{chat-openai.d.ts → openai-chat-model.d.ts} +2 -2
  30. package/lib/cjs/models/{chat-openai.js → openai-chat-model.js} +8 -8
  31. package/lib/cjs/prompt/prompt-builder.d.ts +14 -14
  32. package/lib/cjs/prompt/prompt-builder.js +62 -67
  33. package/lib/cjs/prompt/template.d.ts +9 -21
  34. package/lib/cjs/prompt/template.js +3 -5
  35. package/lib/cjs/utils/json-schema.d.ts +3 -0
  36. package/lib/cjs/utils/json-schema.js +23 -0
  37. package/lib/cjs/utils/mcp-utils.d.ts +3 -2
  38. package/lib/cjs/utils/mcp-utils.js +29 -17
  39. package/lib/cjs/utils/run-chat-loop.d.ts +5 -4
  40. package/lib/cjs/utils/run-chat-loop.js +25 -4
  41. package/lib/cjs/utils/type-utils.d.ts +3 -0
  42. package/lib/cjs/utils/type-utils.js +8 -8
  43. package/lib/dts/agents/agent.d.ts +37 -33
  44. package/lib/dts/agents/ai-agent.d.ts +8 -12
  45. package/lib/dts/agents/mcp-agent.d.ts +25 -9
  46. package/lib/dts/agents/memory.d.ts +26 -0
  47. package/lib/dts/agents/types.d.ts +4 -3
  48. package/lib/dts/agents/user-agent.d.ts +24 -0
  49. package/lib/dts/execution-engine/context.d.ts +35 -5
  50. package/lib/dts/execution-engine/execution-engine.d.ts +64 -0
  51. package/lib/dts/execution-engine/index.d.ts +4 -46
  52. package/lib/dts/execution-engine/message-queue.d.ts +17 -2
  53. package/lib/dts/execution-engine/utils.d.ts +4 -0
  54. package/lib/dts/index.d.ts +14 -11
  55. package/lib/{esm/models/chat.d.ts → dts/models/chat-model.d.ts} +15 -12
  56. package/lib/dts/models/claude-chat-model.d.ts +17 -0
  57. package/lib/dts/models/{chat-openai.d.ts → openai-chat-model.d.ts} +2 -2
  58. package/lib/dts/prompt/prompt-builder.d.ts +14 -14
  59. package/lib/dts/prompt/template.d.ts +9 -21
  60. package/lib/dts/utils/json-schema.d.ts +3 -0
  61. package/lib/dts/utils/mcp-utils.d.ts +3 -2
  62. package/lib/dts/utils/run-chat-loop.d.ts +5 -4
  63. package/lib/dts/utils/type-utils.d.ts +3 -0
  64. package/lib/esm/agents/agent.d.ts +37 -33
  65. package/lib/esm/agents/agent.js +67 -24
  66. package/lib/esm/agents/ai-agent.d.ts +8 -12
  67. package/lib/esm/agents/ai-agent.js +13 -31
  68. package/lib/esm/agents/mcp-agent.d.ts +25 -9
  69. package/lib/esm/agents/mcp-agent.js +54 -8
  70. package/lib/esm/agents/memory.d.ts +26 -0
  71. package/lib/esm/agents/memory.js +34 -0
  72. package/lib/esm/agents/types.d.ts +4 -3
  73. package/lib/esm/agents/types.js +10 -1
  74. package/lib/esm/agents/user-agent.d.ts +24 -0
  75. package/lib/esm/agents/user-agent.js +58 -0
  76. package/lib/esm/execution-engine/context.d.ts +35 -5
  77. package/lib/esm/execution-engine/execution-engine.d.ts +64 -0
  78. package/lib/esm/execution-engine/execution-engine.js +129 -0
  79. package/lib/esm/execution-engine/index.d.ts +4 -46
  80. package/lib/esm/execution-engine/index.js +4 -188
  81. package/lib/esm/execution-engine/message-queue.d.ts +17 -2
  82. package/lib/esm/execution-engine/message-queue.js +37 -1
  83. package/lib/esm/execution-engine/utils.d.ts +4 -0
  84. package/lib/esm/execution-engine/utils.js +28 -0
  85. package/lib/esm/index.d.ts +14 -11
  86. package/lib/esm/index.js +14 -11
  87. package/lib/{cjs/models/chat.d.ts → esm/models/chat-model.d.ts} +15 -12
  88. package/lib/esm/models/{chat.js → chat-model.js} +4 -4
  89. package/lib/esm/models/claude-chat-model.d.ts +17 -0
  90. package/lib/esm/models/claude-chat-model.js +192 -0
  91. package/lib/esm/models/{chat-openai.d.ts → openai-chat-model.d.ts} +2 -2
  92. package/lib/esm/models/{chat-openai.js → openai-chat-model.js} +5 -5
  93. package/lib/esm/prompt/prompt-builder.d.ts +14 -14
  94. package/lib/esm/prompt/prompt-builder.js +56 -58
  95. package/lib/esm/prompt/template.d.ts +9 -21
  96. package/lib/esm/prompt/template.js +3 -5
  97. package/lib/esm/utils/json-schema.d.ts +3 -0
  98. package/lib/esm/utils/json-schema.js +20 -0
  99. package/lib/esm/utils/mcp-utils.d.ts +3 -2
  100. package/lib/esm/utils/mcp-utils.js +26 -15
  101. package/lib/esm/utils/run-chat-loop.d.ts +5 -4
  102. package/lib/esm/utils/run-chat-loop.js +25 -4
  103. package/lib/esm/utils/type-utils.d.ts +3 -0
  104. package/lib/esm/utils/type-utils.js +4 -2
  105. package/package.json +31 -30
@@ -1,9 +1,9 @@
1
1
  import { nanoid } from "nanoid";
2
2
  import OpenAI from "openai";
3
- import { isNonNullable } from "../utils/type-utils";
4
- import { ChatModel, } from "./chat";
3
+ import { isNonNullable } from "../utils/type-utils.js";
4
+ import { ChatModel, } from "./chat-model.js";
5
5
  const CHAT_MODEL_OPENAI_DEFAULT_MODEL = "gpt-4o-mini";
6
- export class ChatModelOpenAI extends ChatModel {
6
+ export class OpenAIChatModel extends ChatModel {
7
7
  config;
8
8
  constructor(config) {
9
9
  super();
@@ -12,7 +12,7 @@ export class ChatModelOpenAI extends ChatModel {
12
12
  _client;
13
13
  get client() {
14
14
  if (!this.config?.apiKey)
15
- throw new Error("Api Key is required for ChatModelOpenAI");
15
+ throw new Error("Api Key is required for OpenAIChatModel");
16
16
  this._client ??= new OpenAI({ apiKey: this.config.apiKey });
17
17
  return this._client;
18
18
  }
@@ -62,7 +62,7 @@ export class ChatModelOpenAI extends ChatModel {
62
62
  text += choice.delta.content;
63
63
  }
64
64
  const result = {};
65
- if (input.responseFormat?.type === "json_schema") {
65
+ if (input.responseFormat?.type === "json_schema" && text) {
66
66
  result.json = JSON.parse(text);
67
67
  }
68
68
  else {
@@ -1,22 +1,24 @@
1
- import type { GetPromptResult } from "@modelcontextprotocol/sdk/types";
2
- import { Agent, type AgentInput } from "../agents/agent";
3
- import type { AIAgent } from "../agents/ai-agent";
4
- import type { Context } from "../execution-engine/context";
5
- import type { ChatModel, ChatModelInput, ChatModelInputMessage } from "../models/chat";
6
- import { ChatMessagesTemplate } from "./template";
7
- export declare const USER_INPUT_MESSAGE_KEY = "$user_input_message";
8
- export declare function userInput(message: string | object): AgentInput;
9
- export declare function addMessagesToInput(input: AgentInput, messages: ChatModelInputMessage[]): AgentInput;
1
+ import type { GetPromptResult } from "@modelcontextprotocol/sdk/types.js";
2
+ import { Agent, type AgentOptions, type Message } from "../agents/agent.js";
3
+ import type { AIAgent } from "../agents/ai-agent.js";
4
+ import type { AgentMemory } from "../agents/memory.js";
5
+ import type { Context } from "../execution-engine/context.js";
6
+ import type { ChatModel, ChatModelInput } from "../models/chat-model.js";
7
+ import { ChatMessagesTemplate } from "./template.js";
8
+ export declare const MESSAGE_KEY = "$message";
9
+ export declare const DEFAULT_MAX_HISTORY_MESSAGES = 10;
10
+ export declare function createMessage(message: string | object): Message;
11
+ export declare function getMessage(input: Message): string | undefined;
10
12
  export interface PromptBuilderOptions {
11
13
  instructions?: string | ChatMessagesTemplate;
12
14
  }
13
15
  export interface PromptBuilderBuildOptions {
14
- enableHistory?: boolean;
15
- maxHistoryMessages?: number;
16
+ memory?: AgentMemory;
16
17
  context?: Context;
17
18
  agent?: AIAgent;
18
- input?: AgentInput;
19
+ input?: Message;
19
20
  model?: ChatModel;
21
+ outputSchema?: AgentOptions["outputSchema"];
20
22
  }
21
23
  export declare class PromptBuilder {
22
24
  static from(instructions: string): PromptBuilder;
@@ -31,8 +33,6 @@ export declare class PromptBuilder {
31
33
  private static fromMCPPromptResult;
32
34
  constructor(options?: PromptBuilderOptions);
33
35
  instructions?: string | ChatMessagesTemplate;
34
- histories: ChatModelInputMessage[];
35
- addHistory(...messages: ChatModelInputMessage[]): void;
36
36
  build(options: PromptBuilderBuildOptions): Promise<ChatModelInput & {
37
37
  toolAgents?: Agent[];
38
38
  }>;
@@ -1,31 +1,21 @@
1
1
  import { readFile } from "node:fs/promises";
2
- import { isNil } from "lodash";
2
+ import { isNil } from "lodash-es";
3
3
  import { ZodObject } from "zod";
4
- import zodToJsonSchema from "zod-to-json-schema";
5
- import { Agent } from "../agents/agent";
6
- import { AgentMessageTemplate, ChatMessagesTemplate, SystemMessageTemplate, UserMessageTemplate, parseChatMessages, } from "./template";
7
- export const USER_INPUT_MESSAGE_KEY = "$user_input_message";
8
- export function userInput(message) {
9
- return { [USER_INPUT_MESSAGE_KEY]: message };
4
+ import { Agent } from "../agents/agent.js";
5
+ import { outputSchemaToResponseFormatSchema } from "../utils/json-schema.js";
6
+ import { AgentMessageTemplate, ChatMessagesTemplate, SystemMessageTemplate, UserMessageTemplate, } from "./template.js";
7
+ export const MESSAGE_KEY = "$message";
8
+ export const DEFAULT_MAX_HISTORY_MESSAGES = 10;
9
+ export function createMessage(message) {
10
+ return { [MESSAGE_KEY]: message };
10
11
  }
11
- export function addMessagesToInput(input, messages) {
12
- const originalUserInputMessages = input[USER_INPUT_MESSAGE_KEY];
13
- const newMessages = [];
14
- if (typeof originalUserInputMessages === "string") {
15
- newMessages.push({ role: "user", content: originalUserInputMessages });
16
- }
17
- else {
18
- const messages = parseChatMessages(originalUserInputMessages);
19
- if (messages)
20
- newMessages.push(...messages);
21
- else
22
- newMessages.push({
23
- role: "user",
24
- content: JSON.stringify(originalUserInputMessages),
25
- });
26
- }
27
- newMessages.push(...messages);
28
- return { ...input, [USER_INPUT_MESSAGE_KEY]: newMessages };
12
+ export function getMessage(input) {
13
+ const userInputMessage = input[MESSAGE_KEY];
14
+ if (typeof userInputMessage === "string")
15
+ return userInputMessage;
16
+ if (!isNil(userInputMessage))
17
+ return JSON.stringify(userInputMessage);
18
+ return undefined;
29
19
  }
30
20
  export class PromptBuilder {
31
21
  static from(instructions) {
@@ -44,12 +34,27 @@ export class PromptBuilder {
44
34
  static fromMCPPromptResult(result) {
45
35
  return new PromptBuilder({
46
36
  instructions: ChatMessagesTemplate.from(result.messages.map((i) => {
47
- if (i.content.type !== "text")
37
+ let content;
38
+ if (i.content.type === "text")
39
+ content = i.content.text;
40
+ else if (i.content.type === "resource") {
41
+ const { resource } = i.content;
42
+ if (typeof resource.text === "string") {
43
+ content = resource.text;
44
+ }
45
+ else if (typeof resource.blob === "string") {
46
+ content = [{ type: "image_url", url: resource.blob }];
47
+ }
48
+ }
49
+ else if (i.content.type === "image") {
50
+ content = [{ type: "image_url", url: i.content.data }];
51
+ }
52
+ if (!content)
48
53
  throw new Error(`Unsupported content type ${i.content.type}`);
49
54
  if (i.role === "user")
50
- return UserMessageTemplate.from(i.content.text);
55
+ return UserMessageTemplate.from(content);
51
56
  if (i.role === "assistant")
52
- return AgentMessageTemplate.from(i.content.text);
57
+ return AgentMessageTemplate.from(content);
53
58
  throw new Error(`Unsupported role ${i.role}`);
54
59
  })),
55
60
  });
@@ -58,10 +63,6 @@ export class PromptBuilder {
58
63
  this.instructions = options?.instructions;
59
64
  }
60
65
  instructions;
61
- histories = [];
62
- addHistory(...messages) {
63
- this.histories.push(...messages);
64
- }
65
66
  async build(options) {
66
67
  return {
67
68
  messages: this.buildMessages(options),
@@ -74,35 +75,26 @@ export class PromptBuilder {
74
75
  const messages = (typeof this.instructions === "string"
75
76
  ? ChatMessagesTemplate.from([SystemMessageTemplate.from(this.instructions)])
76
77
  : this.instructions)?.format(options.input) ?? [];
77
- if (options.enableHistory) {
78
- messages.push(...(options.maxHistoryMessages
79
- ? this.histories.slice(-options.maxHistoryMessages)
80
- : this.histories));
81
- }
82
- const userMessages = [];
83
- const userInputMessage = input?.[USER_INPUT_MESSAGE_KEY];
84
- // Parse messages from the user input with the key $user_input_message
85
- if (!isNil(userInputMessage)) {
86
- if (typeof userInputMessage === "string") {
87
- userMessages.push(UserMessageTemplate.from(userInputMessage).format());
88
- }
89
- else {
90
- const messages = parseChatMessages(userInputMessage);
91
- if (messages)
92
- userMessages.push(...messages.map((i) => i.format()));
93
- else
94
- userMessages.push(UserMessageTemplate.from(JSON.stringify(userInputMessage)).format());
95
- }
78
+ const memory = options.memory ?? options.agent?.memory;
79
+ if (memory?.enabled) {
80
+ const k = memory.maxMemoriesInChat ?? DEFAULT_MAX_HISTORY_MESSAGES;
81
+ const histories = memory.memories.slice(-k);
82
+ if (histories?.length)
83
+ messages.push(...histories.map((i) => ({
84
+ role: i.role,
85
+ content: convertMessageToContent(i.content),
86
+ name: i.source,
87
+ })));
96
88
  }
97
- if (userMessages.length) {
98
- if (options.enableHistory)
99
- this.addHistory(...userMessages);
100
- messages.push(...userMessages);
89
+ const content = input && getMessage(input);
90
+ // add user input if it's not the same as the last message
91
+ if (content && messages.at(-1)?.content !== content) {
92
+ messages.push({ role: "user", content });
101
93
  }
102
94
  return messages;
103
95
  }
104
96
  buildResponseFormat(options) {
105
- const outputSchema = options.agent?.outputSchema;
97
+ const outputSchema = options.outputSchema || options.agent?.outputSchema;
106
98
  if (!outputSchema)
107
99
  return undefined;
108
100
  const isJsonOutput = !isEmptyObjectType(outputSchema);
@@ -111,7 +103,7 @@ export class PromptBuilder {
111
103
  type: "json_schema",
112
104
  jsonSchema: {
113
105
  name: "output",
114
- schema: zodToJsonSchema(outputSchema),
106
+ schema: outputSchemaToResponseFormatSchema(outputSchema),
115
107
  strict: true,
116
108
  },
117
109
  }
@@ -127,7 +119,9 @@ export class PromptBuilder {
127
119
  function: {
128
120
  name: i.name,
129
121
  description: i.description,
130
- parameters: !isEmptyObjectType(i.inputSchema) ? zodToJsonSchema(i.inputSchema) : {},
122
+ parameters: !isEmptyObjectType(i.inputSchema)
123
+ ? outputSchemaToResponseFormatSchema(i.inputSchema)
124
+ : {},
131
125
  },
132
126
  }));
133
127
  let toolChoice;
@@ -170,3 +164,7 @@ function isFromPath(value) {
170
164
  function isEmptyObjectType(schema) {
171
165
  return schema instanceof ZodObject && Object.keys(schema.shape).length === 0;
172
166
  }
167
+ function convertMessageToContent(i) {
168
+ const str = i[MESSAGE_KEY];
169
+ return !isNil(str) ? (typeof str === "string" ? str : JSON.stringify(str)) : JSON.stringify(i);
170
+ }
@@ -1,4 +1,4 @@
1
- import type { ChatModelInputMessage, ChatModelOutputToolCall } from "../models/chat";
1
+ import type { ChatModelInputMessage, ChatModelInputMessageContent, ChatModelOutputToolCall } from "../models/chat-model.js";
2
2
  export declare class PromptTemplate {
3
3
  template: string;
4
4
  static from(template: string): PromptTemplate;
@@ -16,22 +16,16 @@ export declare class SystemMessageTemplate extends ChatMessageTemplate {
16
16
  static from(content: string, name?: string): SystemMessageTemplate;
17
17
  }
18
18
  export declare class UserMessageTemplate extends ChatMessageTemplate {
19
- static from(template: NonNullable<ChatModelInputMessage["content"]>, name?: string): UserMessageTemplate;
19
+ static from(template: ChatModelInputMessageContent, name?: string): UserMessageTemplate;
20
20
  }
21
21
  export declare class AgentMessageTemplate extends ChatMessageTemplate {
22
22
  toolCalls?: ChatModelOutputToolCall[] | undefined;
23
- static from(template: string | ChatModelOutputToolCall[], name?: string): AgentMessageTemplate;
24
- constructor(content?: string, toolCalls?: ChatModelOutputToolCall[] | undefined, name?: string);
23
+ static from(template?: ChatModelInputMessage["content"], toolCalls?: ChatModelOutputToolCall[], name?: string): AgentMessageTemplate;
24
+ constructor(content?: ChatModelInputMessage["content"], toolCalls?: ChatModelOutputToolCall[] | undefined, name?: string);
25
25
  format(variables?: Record<string, unknown>): {
26
26
  toolCalls: ChatModelOutputToolCall[] | undefined;
27
- role: import("../models/chat").Role;
28
- content?: string | ({
29
- type: "text";
30
- text: string;
31
- } | {
32
- type: "image_url";
33
- url: string;
34
- })[];
27
+ role: import("../models/chat-model.js").Role;
28
+ content?: ChatModelInputMessageContent;
35
29
  toolCallId?: string;
36
30
  name?: string;
37
31
  };
@@ -42,20 +36,14 @@ export declare class ToolMessageTemplate extends ChatMessageTemplate {
42
36
  constructor(content: object | string, toolCallId: string, name?: string);
43
37
  format(variables?: Record<string, unknown>): {
44
38
  toolCallId: string;
45
- role: import("../models/chat").Role;
46
- content?: string | ({
47
- type: "text";
48
- text: string;
49
- } | {
50
- type: "image_url";
51
- url: string;
52
- })[];
39
+ role: import("../models/chat-model.js").Role;
40
+ content?: ChatModelInputMessageContent;
53
41
  toolCalls?: {
54
42
  id: string;
55
43
  type: "function";
56
44
  function: {
57
45
  name: string;
58
- arguments: import("..").AgentInput;
46
+ arguments: import("../index.js").Message;
59
47
  };
60
48
  }[];
61
49
  name?: string;
@@ -56,10 +56,8 @@ export class UserMessageTemplate extends ChatMessageTemplate {
56
56
  }
57
57
  export class AgentMessageTemplate extends ChatMessageTemplate {
58
58
  toolCalls;
59
- static from(template, name) {
60
- return typeof template === "string"
61
- ? new AgentMessageTemplate(template, undefined, name)
62
- : new AgentMessageTemplate(undefined, template, name);
59
+ static from(template, toolCalls, name) {
60
+ return new AgentMessageTemplate(template, toolCalls, name);
63
61
  }
64
62
  constructor(content, toolCalls, name) {
65
63
  super("agent", content, name);
@@ -150,7 +148,7 @@ export function parseChatMessages(messages) {
150
148
  case "user":
151
149
  return UserMessageTemplate.from(message.content, message.name);
152
150
  case "agent":
153
- return new AgentMessageTemplate(message.content, message.toolCalls, message.name);
151
+ return AgentMessageTemplate.from(message.content, message.toolCalls, message.name);
154
152
  case "tool":
155
153
  return ToolMessageTemplate.from(message.content, message.toolCallId, message.name);
156
154
  }
@@ -0,0 +1,3 @@
1
+ import type { ZodType } from "zod";
2
+ import type { Message } from "../agents/agent.js";
3
+ export declare function outputSchemaToResponseFormatSchema(agentOutput: ZodType<Message>): Record<string, unknown>;
@@ -0,0 +1,20 @@
1
+ import { isObject } from "lodash-es";
2
+ import { zodToJsonSchema } from "zod-to-json-schema";
3
+ export function outputSchemaToResponseFormatSchema(agentOutput) {
4
+ return setAdditionPropertiesDeep(zodToJsonSchema(agentOutput), false);
5
+ }
6
+ function setAdditionPropertiesDeep(schema, additionalProperties) {
7
+ if (Array.isArray(schema)) {
8
+ return schema.map((s) => setAdditionPropertiesDeep(s, additionalProperties));
9
+ }
10
+ if (isObject(schema)) {
11
+ return Object.entries(schema).reduce((acc, [key, value]) => {
12
+ acc[key] = setAdditionPropertiesDeep(value, additionalProperties);
13
+ if (acc.type === "object") {
14
+ acc.additionalProperties = additionalProperties;
15
+ }
16
+ return acc;
17
+ }, {});
18
+ }
19
+ return schema;
20
+ }
@@ -1,5 +1,6 @@
1
1
  import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
- import type { ListPromptsResult, ListToolsResult } from "@modelcontextprotocol/sdk/types";
3
- import { MCPPrompt, MCPTool } from "../agents/mcp-agent";
2
+ import { type ListPromptsResult, type ListResourceTemplatesResult, type ListResourcesResult, type ListToolsResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import { MCPPrompt, MCPResource, MCPTool } from "../agents/mcp-agent.js";
4
4
  export declare function toolFromMCPTool(client: Client, tool: ListToolsResult["tools"][number]): MCPTool;
5
5
  export declare function promptFromMCPPrompt(client: Client, prompt: ListPromptsResult["prompts"][number]): MCPPrompt;
6
+ export declare function resourceFromMCPResource(client: Client, resource: ListResourcesResult["resources"][number] | ListResourceTemplatesResult["resourceTemplates"][number]): MCPResource;
@@ -1,19 +1,15 @@
1
- import { jsonSchemaToZod } from "@n8n/json-schema-to-zod";
1
+ import { jsonSchemaToZod } from "@aigne/json-schema-to-zod";
2
+ import { UriTemplate } from "@modelcontextprotocol/sdk/shared/uriTemplate.js";
3
+ import { CallToolResultSchema, GetPromptResultSchema, ReadResourceResultSchema, } from "@modelcontextprotocol/sdk/types.js";
2
4
  import { z } from "zod";
3
- import { MCPPrompt, MCPTool } from "../agents/mcp-agent";
5
+ import { MCPPrompt, MCPResource, MCPTool } from "../agents/mcp-agent.js";
4
6
  export function toolFromMCPTool(client, tool) {
5
7
  return new MCPTool({
6
8
  client,
7
9
  name: tool.name,
8
10
  description: tool.description,
9
11
  inputSchema: jsonSchemaToZod(tool.inputSchema),
10
- outputSchema: z
11
- .object({
12
- _meta: z.record(z.unknown()).optional(),
13
- content: z.array(z.record(z.unknown())),
14
- isError: z.boolean().optional(),
15
- })
16
- .passthrough(),
12
+ outputSchema: CallToolResultSchema,
17
13
  });
18
14
  }
19
15
  export function promptFromMCPPrompt(client, prompt) {
@@ -27,11 +23,26 @@ export function promptFromMCPPrompt(client, prompt) {
27
23
  Object.fromEntries(prompt.arguments.map((i) => [i.name, { type: "string", description: i.description }])),
28
24
  required: prompt.arguments?.filter((i) => i.required).map((i) => i.name),
29
25
  }),
30
- outputSchema: z
31
- .object({
32
- description: z.string().optional(),
33
- messages: z.array(z.record(z.unknown())),
34
- })
35
- .passthrough(),
26
+ outputSchema: GetPromptResultSchema,
36
27
  });
37
28
  }
29
+ export function resourceFromMCPResource(client, resource) {
30
+ const [uri, variables] = isResourceTemplate(resource)
31
+ ? [
32
+ resource.uriTemplate,
33
+ // TODO: use template.variableNames when it's available https://github.com/modelcontextprotocol/typescript-sdk/pull/188
34
+ new UriTemplate(resource.uriTemplate).parts.flatMap((i) => (typeof i === "object" ? i.names : [])),
35
+ ]
36
+ : [resource.uri, []];
37
+ return new MCPResource({
38
+ client,
39
+ name: resource.name,
40
+ uri,
41
+ description: resource.description,
42
+ inputSchema: z.object(Object.fromEntries(variables.map((i) => [i, z.string()]))),
43
+ outputSchema: ReadResourceResultSchema,
44
+ });
45
+ }
46
+ function isResourceTemplate(resource) {
47
+ return typeof resource.uriTemplate === "string";
48
+ }
@@ -1,10 +1,11 @@
1
- import type { AgentInput, AgentOutput } from "../agents/agent";
2
- import type { UserAgent } from "../execution-engine";
1
+ import type { Message } from "../agents/agent.js";
2
+ import type { UserAgent } from "../agents/user-agent.js";
3
3
  export interface ChatLoopOptions {
4
4
  log?: typeof console.log;
5
- initialCall?: AgentInput | string;
5
+ initialCall?: Message | string;
6
6
  welcome?: string;
7
7
  defaultQuestion?: string;
8
- onResponse?: (response: AgentOutput) => void;
8
+ onResponse?: (response: Message) => void;
9
+ inputKey?: string;
9
10
  }
10
11
  export declare function runChatLoopInTerminal(userAgent: UserAgent, { log, ...options }?: ChatLoopOptions): Promise<void>;
@@ -1,13 +1,26 @@
1
1
  import inquirer from "inquirer";
2
- import { logger } from "./logger";
2
+ import { logger } from "./logger.js";
3
3
  export async function runChatLoopInTerminal(userAgent, { log = console.log.bind(console), ...options } = {}) {
4
+ let isLoopExited = false;
5
+ let prompt;
4
6
  if (options?.welcome)
5
7
  log(options.welcome);
6
8
  if (options?.initialCall) {
7
9
  await callAgent(userAgent, options.initialCall, { ...options, log });
8
10
  }
11
+ (async () => {
12
+ for await (const output of userAgent.stream) {
13
+ if (isLoopExited)
14
+ return;
15
+ if (options?.onResponse)
16
+ options.onResponse(output);
17
+ else
18
+ log(output);
19
+ prompt?.ui.close();
20
+ }
21
+ })();
9
22
  for (let i = 0;; i++) {
10
- const { question } = await inquirer.prompt([
23
+ prompt = inquirer.prompt([
11
24
  {
12
25
  type: "input",
13
26
  name: "question",
@@ -15,7 +28,14 @@ export async function runChatLoopInTerminal(userAgent, { log = console.log.bind(
15
28
  default: i === 0 ? options?.defaultQuestion : undefined,
16
29
  },
17
30
  ]);
18
- if (!question.trim())
31
+ let question;
32
+ try {
33
+ question = (await prompt).question;
34
+ }
35
+ catch {
36
+ // ignore abort error from inquirer
37
+ }
38
+ if (!question?.trim())
19
39
  continue;
20
40
  const cmd = COMMANDS[question.trim()];
21
41
  if (cmd) {
@@ -28,9 +48,10 @@ export async function runChatLoopInTerminal(userAgent, { log = console.log.bind(
28
48
  }
29
49
  await callAgent(userAgent, question, { ...options, log });
30
50
  }
51
+ isLoopExited = true;
31
52
  }
32
53
  async function callAgent(agent, input, options) {
33
- const response = await logger.spinner(agent.call(input), "🤖");
54
+ const response = await logger.spinner(agent.call(options.inputKey && typeof input === "string" ? { [options.inputKey]: input } : input), "🤖");
34
55
  if (options?.onResponse)
35
56
  options.onResponse(response);
36
57
  else
@@ -1,4 +1,7 @@
1
+ export type PromiseOrValue<T> = T | Promise<T>;
2
+ export type Nullish<T> = T | null | undefined;
1
3
  export declare function isNonNullable<T>(value: T): value is NonNullable<T>;
4
+ export declare function isNotEmpty<T>(arr: T[]): arr is [T, ...T[]];
2
5
  export declare function orArrayToArray<T>(value?: T | T[]): T[];
3
6
  export declare function get(obj: unknown, path: string | string[], type?: undefined): unknown | undefined;
4
7
  export declare function get(obj: unknown, path: string | string[], type: "string"): string | undefined;
@@ -1,8 +1,10 @@
1
- import { get as _get } from "lodash";
2
- import isNil from "lodash/isNil";
1
+ import { get as _get, isNil } from "lodash-es";
3
2
  export function isNonNullable(value) {
4
3
  return !isNil(value);
5
4
  }
5
+ export function isNotEmpty(arr) {
6
+ return arr.length > 0;
7
+ }
6
8
  export function orArrayToArray(value) {
7
9
  if (isNil(value))
8
10
  return [];
package/package.json CHANGED
@@ -1,13 +1,25 @@
1
1
  {
2
2
  "name": "@aigne/core",
3
- "version": "1.1.0-beta.5",
4
- "description": "AIGNE core library",
3
+ "version": "1.3.0",
4
+ "description": "AIGNE core library for building AI-powered applications",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
9
- "homepage": "https://github.com/blocklet/ai-studio#readme",
9
+ "homepage": "https://github.com/AIGNE-io/aigne-framework",
10
10
  "license": "ISC",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/AIGNE-io/aigne-framework"
14
+ },
15
+ "files": [
16
+ "lib/cjs",
17
+ "lib/dts",
18
+ "lib/esm",
19
+ "LICENSE",
20
+ "README.md",
21
+ "CHANGELOG.md"
22
+ ],
11
23
  "type": "module",
12
24
  "main": "./lib/cjs/index.js",
13
25
  "module": "./lib/esm/index.js",
@@ -19,51 +31,40 @@
19
31
  "types": "./lib/dts/index.d.ts"
20
32
  }
21
33
  },
22
- "files": [
23
- "lib/cjs",
24
- "lib/dts",
25
- "lib/esm",
26
- "LICENSE",
27
- "README.md",
28
- "CHANGELOG.md"
29
- ],
30
- "repository": {
31
- "type": "git",
32
- "url": "git+https://github.com/blocklet/ai-studio.git"
33
- },
34
34
  "dependencies": {
35
- "@google/generative-ai": "^0.24.0",
36
- "@modelcontextprotocol/sdk": "^1.6.1",
37
- "@n8n/json-schema-to-zod": "^1.1.0",
35
+ "@aigne/json-schema-to-zod": "^1.3.2",
36
+ "@modelcontextprotocol/sdk": "^1.7.0",
38
37
  "@types/debug": "^4.1.12",
39
38
  "@types/mustache": "^4.2.5",
40
39
  "debug": "^4.4.0",
41
- "inquirer": "^12.4.3",
42
- "lodash": "^4.17.21",
40
+ "inquirer": "^12.5.0",
41
+ "lodash-es": "^4.17.21",
43
42
  "mustache": "^4.2.0",
44
- "nanoid": "^5.1.3",
45
- "openai": "^4.86.2",
43
+ "nanoid": "^5.1.5",
46
44
  "ora": "^8.2.0",
47
45
  "zod": "^3.24.2",
48
- "zod-to-json-schema": "^3.24.3"
46
+ "zod-to-json-schema": "^3.24.5"
49
47
  },
50
48
  "peerDependencies": {
51
- "@google/generative-ai": "^0.21.0",
52
- "openai": "^4.79.1"
49
+ "@anthropic-ai/sdk": "^0.39.0",
50
+ "@google/generative-ai": "^0.24.0",
51
+ "openai": "^4.87.3"
53
52
  },
54
53
  "devDependencies": {
55
- "@types/bun": "^1.2.4",
56
- "@types/lodash": "^4.17.16",
54
+ "@anthropic-ai/sdk": "^0.39.0",
55
+ "@google/generative-ai": "^0.24.0",
56
+ "@types/bun": "^1.2.5",
57
+ "@types/lodash-es": "^4.17.12",
57
58
  "npm-run-all": "^4.1.5",
59
+ "openai": "^4.89.0",
58
60
  "rimraf": "^6.0.1",
59
61
  "typescript": "^5.8.2"
60
62
  },
61
63
  "scripts": {
62
- "lint": "biome check",
63
- "lint:fix": "biome check --write",
64
+ "lint": "tsc --noEmit",
64
65
  "build": "tsc --build scripts/tsconfig.build.json",
65
66
  "clean": "rimraf lib coverage",
66
67
  "test": "bun test",
67
- "test:coverage": "bun test --coverage --coverage-reporter lcov"
68
+ "test:coverage": "bun test --coverage --coverage-reporter=lcov --coverage-reporter=text"
68
69
  }
69
70
  }