@aigne/core 1.1.0-beta.2 → 1.1.0-beta.4
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 +17 -0
- package/lib/cjs/agents/agent.d.ts +2 -0
- package/lib/cjs/agents/agent.js +6 -12
- package/lib/cjs/agents/mcp-agent.js +4 -10
- package/lib/cjs/execution-engine/index.d.ts +1 -0
- package/lib/cjs/execution-engine/index.js +7 -1
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/utils/logger.d.ts +12 -4
- package/lib/cjs/utils/logger.js +58 -3
- package/lib/cjs/utils/run-chat-loop.d.ts +8 -0
- package/lib/cjs/utils/run-chat-loop.js +44 -0
- package/lib/dts/agents/agent.d.ts +2 -0
- package/lib/dts/execution-engine/index.d.ts +1 -0
- package/lib/dts/index.d.ts +1 -0
- package/lib/dts/utils/logger.d.ts +12 -4
- package/lib/dts/utils/run-chat-loop.d.ts +8 -0
- package/lib/esm/agents/agent.d.ts +2 -0
- package/lib/esm/agents/agent.js +7 -13
- package/lib/esm/agents/mcp-agent.js +4 -10
- package/lib/esm/execution-engine/index.d.ts +1 -0
- package/lib/esm/execution-engine/index.js +7 -1
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/utils/logger.d.ts +12 -4
- package/lib/esm/utils/logger.js +58 -3
- package/lib/esm/utils/run-chat-loop.d.ts +8 -0
- package/lib/esm/utils/run-chat-loop.js +38 -0
- package/package.json +13 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## 1.1.0-beta.4 (2025-3-12)
|
|
2
|
+
|
|
3
|
+
- feat: support run puppeteer example chat loop in terminal
|
|
4
|
+
|
|
5
|
+
## 1.1.0-beta.3 (2025-3-11)
|
|
6
|
+
|
|
7
|
+
- chore: set module type for core package
|
|
8
|
+
|
|
9
|
+
## 1.1.0-beta.2 (2025-3-11)
|
|
10
|
+
|
|
11
|
+
- feat: use PromptBuilder instead of string instructions
|
|
12
|
+
- refactor: use tools instead of skills
|
|
13
|
+
- chore(examples): add puppeteer-mcp-server example
|
|
14
|
+
|
|
15
|
+
## 1.1.0-beta.1 (2025-3-11)
|
|
16
|
+
|
|
17
|
+
- feat: add Agent FunctionAgent AIAgent MCPAgent and ExecutionEngine
|
|
@@ -19,6 +19,7 @@ export interface AgentOptions<I extends AgentInput = AgentInput, O extends Agent
|
|
|
19
19
|
}>;
|
|
20
20
|
includeInputInOutput?: boolean;
|
|
21
21
|
tools?: (Agent | FunctionAgentFn)[];
|
|
22
|
+
disableLogging?: boolean;
|
|
22
23
|
}
|
|
23
24
|
export declare class Agent<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput> extends EventEmitter {
|
|
24
25
|
static from<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput>(options: AgentOptions<I, O>): Agent<I, O>;
|
|
@@ -37,6 +38,7 @@ export declare class Agent<I extends AgentInput = AgentInput, O extends AgentOut
|
|
|
37
38
|
readonly tools: Agent<AgentInput, AgentOutput>[] & {
|
|
38
39
|
[key: string]: Agent<AgentInput, AgentOutput>;
|
|
39
40
|
};
|
|
41
|
+
private disableLogging?;
|
|
40
42
|
addTool<I extends AgentInput, O extends AgentOutput>(tool: Agent<I, O> | FunctionAgentFn<I, O>): void;
|
|
41
43
|
get isCallable(): boolean;
|
|
42
44
|
call(input: I | string, context?: Context): Promise<O>;
|
package/lib/cjs/agents/agent.js
CHANGED
|
@@ -26,6 +26,7 @@ class Agent extends node_events_1.default {
|
|
|
26
26
|
this.publishTopic = options.publishTopic;
|
|
27
27
|
if (options.tools?.length)
|
|
28
28
|
this.tools.push(...options.tools.map(functionToAgent));
|
|
29
|
+
this.disableLogging = options.disableLogging;
|
|
29
30
|
}
|
|
30
31
|
name;
|
|
31
32
|
description;
|
|
@@ -37,6 +38,7 @@ class Agent extends node_events_1.default {
|
|
|
37
38
|
tools = new Proxy([], {
|
|
38
39
|
get: (t, p, r) => Reflect.get(t, p, r) ?? t.find((t) => t.name === p),
|
|
39
40
|
});
|
|
41
|
+
disableLogging;
|
|
40
42
|
addTool(tool) {
|
|
41
43
|
this.tools.push(typeof tool === "function" ? functionToAgent(tool) : tool);
|
|
42
44
|
}
|
|
@@ -48,19 +50,11 @@ class Agent extends node_events_1.default {
|
|
|
48
50
|
throw new Error("Agent must implement process method");
|
|
49
51
|
const _input = typeof input === "string" ? (0, prompt_builder_1.userInput)(input) : input;
|
|
50
52
|
const parsedInput = this.inputSchema.passthrough().parse(_input);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const finalOutput = this.includeInputInOutput
|
|
55
|
-
? { ...parsedInput, ...parsedOutput }
|
|
56
|
-
: parsedOutput;
|
|
57
|
-
logger_1.logger.debug(`Call agent ${this.name} successfully`, {
|
|
58
|
-
...finalOutput,
|
|
59
|
-
...(finalOutput[types_1.transferAgentOutputKey]
|
|
60
|
-
? { [types_1.transferAgentOutputKey]: finalOutput[types_1.transferAgentOutputKey].agent.name }
|
|
61
|
-
: {}),
|
|
53
|
+
const result = this.process(parsedInput, context).then((output) => {
|
|
54
|
+
const parsedOutput = this.outputSchema.passthrough().parse(output);
|
|
55
|
+
return this.includeInputInOutput ? { ...parsedInput, ...parsedOutput } : parsedOutput;
|
|
62
56
|
});
|
|
63
|
-
return
|
|
57
|
+
return logger_1.logger.debug.spinner(result, `Call agent ${this.name}`, (output) => logger_1.logger.debug("%O", { input, output }), { disabled: this.disableLogging });
|
|
64
58
|
}
|
|
65
59
|
async shutdown() { }
|
|
66
60
|
}
|
|
@@ -10,7 +10,7 @@ const logger_1 = require("../utils/logger");
|
|
|
10
10
|
const agent_1 = require("./agent");
|
|
11
11
|
const MCP_AGENT_CLIENT_NAME = "MCPAgent";
|
|
12
12
|
const MCP_AGENT_CLIENT_VERSION = "0.0.1";
|
|
13
|
-
const debug = logger_1.logger.base.extend("mcp
|
|
13
|
+
const debug = logger_1.logger.base.extend("mcp");
|
|
14
14
|
function isSSEServerParameters(options) {
|
|
15
15
|
return "url" in options && typeof options.url === "string";
|
|
16
16
|
}
|
|
@@ -34,13 +34,9 @@ class MCPAgent extends agent_1.Agent {
|
|
|
34
34
|
name: MCP_AGENT_CLIENT_NAME,
|
|
35
35
|
version: MCP_AGENT_CLIENT_VERSION,
|
|
36
36
|
});
|
|
37
|
-
debug(
|
|
38
|
-
await client.connect(transport);
|
|
39
|
-
debug(`Connected to MCP server with transport ${transport.constructor.name}`);
|
|
37
|
+
await debug.spinner(client.connect(transport), "Connecting to MCP server");
|
|
40
38
|
const mcpServer = getMCPServerName(client);
|
|
41
|
-
debug(`Listing tools from ${mcpServer}
|
|
42
|
-
const { tools: mcpTools } = await client.listTools();
|
|
43
|
-
debug(`Listed tools from ${mcpServer}`, mcpTools.map((i) => i.name));
|
|
39
|
+
const { tools: mcpTools } = await debug.spinner(client.listTools(), `Listing tools from ${mcpServer}`, ({ tools }) => debug("%O", tools));
|
|
44
40
|
const tools = mcpTools.map((tool) => {
|
|
45
41
|
return new MCPTool({
|
|
46
42
|
client,
|
|
@@ -79,9 +75,7 @@ class MCPTool extends agent_1.Agent {
|
|
|
79
75
|
return getMCPServerName(this.client);
|
|
80
76
|
}
|
|
81
77
|
async process(input) {
|
|
82
|
-
debug(`
|
|
83
|
-
const result = await this.client.callTool({ name: this.name, arguments: input });
|
|
84
|
-
debug(`End call tool ${this.name} from ${this.mcpServer} with result`, result);
|
|
78
|
+
const result = await debug.spinner(this.client.callTool({ name: this.name, arguments: input }), `Call tool ${this.name} from ${this.mcpServer}`, (output) => debug("%O", { input, output }));
|
|
85
79
|
return result;
|
|
86
80
|
}
|
|
87
81
|
}
|
|
@@ -33,6 +33,7 @@ export declare class ExecutionEngine extends EventEmitter implements Context {
|
|
|
33
33
|
private runChatLoop;
|
|
34
34
|
private callAgent;
|
|
35
35
|
shutdown(): Promise<void>;
|
|
36
|
+
private initProcessExitHandler;
|
|
36
37
|
}
|
|
37
38
|
export declare class UserAgent<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput> extends Agent<I, O> {
|
|
38
39
|
options: AgentOptions<I, O> & {
|
|
@@ -18,6 +18,7 @@ class ExecutionEngine extends node_events_1.default {
|
|
|
18
18
|
this.tools = options?.tools ?? [];
|
|
19
19
|
if (options?.agents?.length)
|
|
20
20
|
this.addAgent(...options.agents);
|
|
21
|
+
this.initProcessExitHandler();
|
|
21
22
|
}
|
|
22
23
|
messageQueue = new message_queue_1.MessageQueue();
|
|
23
24
|
model;
|
|
@@ -175,12 +176,17 @@ class ExecutionEngine extends node_events_1.default {
|
|
|
175
176
|
await agent.shutdown();
|
|
176
177
|
}
|
|
177
178
|
}
|
|
179
|
+
initProcessExitHandler() {
|
|
180
|
+
const shutdownAndExit = () => this.shutdown().finally(() => process.exit(0));
|
|
181
|
+
process.on("SIGINT", shutdownAndExit);
|
|
182
|
+
process.on("exit", shutdownAndExit);
|
|
183
|
+
}
|
|
178
184
|
}
|
|
179
185
|
exports.ExecutionEngine = ExecutionEngine;
|
|
180
186
|
class UserAgent extends agent_1.Agent {
|
|
181
187
|
options;
|
|
182
188
|
constructor(options) {
|
|
183
|
-
super(options);
|
|
189
|
+
super({ ...options, disableLogging: true });
|
|
184
190
|
this.options = options;
|
|
185
191
|
}
|
|
186
192
|
process(input) {
|
package/lib/cjs/index.d.ts
CHANGED
package/lib/cjs/index.js
CHANGED
|
@@ -24,3 +24,4 @@ __exportStar(require("./models/chat"), exports);
|
|
|
24
24
|
__exportStar(require("./models/chat-openai"), exports);
|
|
25
25
|
__exportStar(require("./prompt/prompt-builder"), exports);
|
|
26
26
|
__exportStar(require("./prompt/template"), exports);
|
|
27
|
+
__exportStar(require("./utils/run-chat-loop"), exports);
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type Debugger } from "debug";
|
|
2
|
+
interface DebugWithSpinner extends Debugger {
|
|
3
|
+
spinner<T>(promise: Promise<T>, message?: string, callback?: (result: T) => void, options?: {
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
}): Promise<T>;
|
|
6
|
+
extend: (namespace: string) => DebugWithSpinner;
|
|
7
|
+
}
|
|
8
|
+
declare function spinner<T>(promise: Promise<T>, message?: string, callback?: (result: T) => void): Promise<T>;
|
|
2
9
|
export declare const logger: {
|
|
3
|
-
base:
|
|
4
|
-
debug:
|
|
5
|
-
|
|
10
|
+
base: DebugWithSpinner;
|
|
11
|
+
debug: DebugWithSpinner;
|
|
12
|
+
spinner: typeof spinner;
|
|
6
13
|
};
|
|
14
|
+
export {};
|
package/lib/cjs/utils/logger.js
CHANGED
|
@@ -5,8 +5,63 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.logger = void 0;
|
|
7
7
|
const debug_1 = __importDefault(require("debug"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
debug_1.default.log = (...args) => {
|
|
10
|
+
const { isSpinning } = globalSpinner;
|
|
11
|
+
if (isSpinning)
|
|
12
|
+
globalSpinner.stop();
|
|
13
|
+
console.log(...args);
|
|
14
|
+
if (isSpinning)
|
|
15
|
+
globalSpinner.start();
|
|
16
|
+
};
|
|
17
|
+
function createDebugger(namespace) {
|
|
18
|
+
const i = (0, debug_1.default)(namespace);
|
|
19
|
+
function overrideExtend(debug) {
|
|
20
|
+
const originalExtend = debug.extend;
|
|
21
|
+
debug.extend = (namespace) => {
|
|
22
|
+
const extended = originalExtend.call(debug, namespace);
|
|
23
|
+
overrideExtend(extended);
|
|
24
|
+
extended.spinner = async (promise, message, callback, options) => {
|
|
25
|
+
if (!extended.enabled || options?.disabled)
|
|
26
|
+
return promise;
|
|
27
|
+
return spinner(promise, message, callback);
|
|
28
|
+
};
|
|
29
|
+
return extended;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
overrideExtend(i);
|
|
33
|
+
return i;
|
|
34
|
+
}
|
|
35
|
+
const globalSpinner = (0, ora_1.default)();
|
|
36
|
+
async function spinner(promise, message, callback) {
|
|
37
|
+
const { isSpinning, text } = globalSpinner;
|
|
38
|
+
try {
|
|
39
|
+
globalSpinner.start(message || " ");
|
|
40
|
+
const result = await promise;
|
|
41
|
+
if (message)
|
|
42
|
+
globalSpinner.succeed(message);
|
|
43
|
+
else
|
|
44
|
+
globalSpinner.stop();
|
|
45
|
+
// NOTE: This is a workaround to make sure the spinner stops spinning before the next tick
|
|
46
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
47
|
+
callback?.(result);
|
|
48
|
+
// NOTE: This is a workaround to make sure the spinner stops spinning before the next tick
|
|
49
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
globalSpinner.fail(message || " ");
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
// Recover the spinner state
|
|
58
|
+
if (isSpinning)
|
|
59
|
+
globalSpinner.start(text || " ");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const base = createDebugger("aigne");
|
|
8
63
|
exports.logger = {
|
|
9
|
-
base
|
|
10
|
-
debug:
|
|
11
|
-
|
|
64
|
+
base,
|
|
65
|
+
debug: base.extend("core"),
|
|
66
|
+
spinner,
|
|
12
67
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentOutput } from "../agents/agent";
|
|
2
|
+
import type { UserAgent } from "../execution-engine";
|
|
3
|
+
export interface ChatLoopOptions {
|
|
4
|
+
welcome?: string;
|
|
5
|
+
defaultQuestion?: string;
|
|
6
|
+
onResponse?: (response: AgentOutput) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function runChatLoopInTerminal(userAgent: UserAgent, options?: ChatLoopOptions): Promise<void>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runChatLoopInTerminal = runChatLoopInTerminal;
|
|
7
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
+
const logger_1 = require("./logger");
|
|
9
|
+
async function runChatLoopInTerminal(userAgent, options) {
|
|
10
|
+
if (options?.welcome)
|
|
11
|
+
console.log(options.welcome);
|
|
12
|
+
for (let i = 0;; i++) {
|
|
13
|
+
const { question } = await inquirer_1.default.prompt([
|
|
14
|
+
{
|
|
15
|
+
type: "input",
|
|
16
|
+
name: "question",
|
|
17
|
+
message: ">",
|
|
18
|
+
default: i === 0 ? options?.defaultQuestion : undefined,
|
|
19
|
+
},
|
|
20
|
+
]);
|
|
21
|
+
if (!question.trim())
|
|
22
|
+
continue;
|
|
23
|
+
const cmd = COMMANDS[question.trim()];
|
|
24
|
+
if (cmd) {
|
|
25
|
+
await cmd();
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const response = await logger_1.logger.spinner(userAgent.call(question));
|
|
29
|
+
if (options?.onResponse)
|
|
30
|
+
options.onResponse(response);
|
|
31
|
+
else
|
|
32
|
+
console.log(response);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const COMMANDS = {
|
|
36
|
+
"/exit": () => process.exit(0),
|
|
37
|
+
"/help": () => {
|
|
38
|
+
console.log(`\
|
|
39
|
+
Commands:
|
|
40
|
+
/exit - exit the chat loop
|
|
41
|
+
/help - show this help message
|
|
42
|
+
`);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
@@ -19,6 +19,7 @@ export interface AgentOptions<I extends AgentInput = AgentInput, O extends Agent
|
|
|
19
19
|
}>;
|
|
20
20
|
includeInputInOutput?: boolean;
|
|
21
21
|
tools?: (Agent | FunctionAgentFn)[];
|
|
22
|
+
disableLogging?: boolean;
|
|
22
23
|
}
|
|
23
24
|
export declare class Agent<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput> extends EventEmitter {
|
|
24
25
|
static from<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput>(options: AgentOptions<I, O>): Agent<I, O>;
|
|
@@ -37,6 +38,7 @@ export declare class Agent<I extends AgentInput = AgentInput, O extends AgentOut
|
|
|
37
38
|
readonly tools: Agent<AgentInput, AgentOutput>[] & {
|
|
38
39
|
[key: string]: Agent<AgentInput, AgentOutput>;
|
|
39
40
|
};
|
|
41
|
+
private disableLogging?;
|
|
40
42
|
addTool<I extends AgentInput, O extends AgentOutput>(tool: Agent<I, O> | FunctionAgentFn<I, O>): void;
|
|
41
43
|
get isCallable(): boolean;
|
|
42
44
|
call(input: I | string, context?: Context): Promise<O>;
|
|
@@ -33,6 +33,7 @@ export declare class ExecutionEngine extends EventEmitter implements Context {
|
|
|
33
33
|
private runChatLoop;
|
|
34
34
|
private callAgent;
|
|
35
35
|
shutdown(): Promise<void>;
|
|
36
|
+
private initProcessExitHandler;
|
|
36
37
|
}
|
|
37
38
|
export declare class UserAgent<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput> extends Agent<I, O> {
|
|
38
39
|
options: AgentOptions<I, O> & {
|
package/lib/dts/index.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type Debugger } from "debug";
|
|
2
|
+
interface DebugWithSpinner extends Debugger {
|
|
3
|
+
spinner<T>(promise: Promise<T>, message?: string, callback?: (result: T) => void, options?: {
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
}): Promise<T>;
|
|
6
|
+
extend: (namespace: string) => DebugWithSpinner;
|
|
7
|
+
}
|
|
8
|
+
declare function spinner<T>(promise: Promise<T>, message?: string, callback?: (result: T) => void): Promise<T>;
|
|
2
9
|
export declare const logger: {
|
|
3
|
-
base:
|
|
4
|
-
debug:
|
|
5
|
-
|
|
10
|
+
base: DebugWithSpinner;
|
|
11
|
+
debug: DebugWithSpinner;
|
|
12
|
+
spinner: typeof spinner;
|
|
6
13
|
};
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentOutput } from "../agents/agent";
|
|
2
|
+
import type { UserAgent } from "../execution-engine";
|
|
3
|
+
export interface ChatLoopOptions {
|
|
4
|
+
welcome?: string;
|
|
5
|
+
defaultQuestion?: string;
|
|
6
|
+
onResponse?: (response: AgentOutput) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function runChatLoopInTerminal(userAgent: UserAgent, options?: ChatLoopOptions): Promise<void>;
|
|
@@ -19,6 +19,7 @@ export interface AgentOptions<I extends AgentInput = AgentInput, O extends Agent
|
|
|
19
19
|
}>;
|
|
20
20
|
includeInputInOutput?: boolean;
|
|
21
21
|
tools?: (Agent | FunctionAgentFn)[];
|
|
22
|
+
disableLogging?: boolean;
|
|
22
23
|
}
|
|
23
24
|
export declare class Agent<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput> extends EventEmitter {
|
|
24
25
|
static from<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput>(options: AgentOptions<I, O>): Agent<I, O>;
|
|
@@ -37,6 +38,7 @@ export declare class Agent<I extends AgentInput = AgentInput, O extends AgentOut
|
|
|
37
38
|
readonly tools: Agent<AgentInput, AgentOutput>[] & {
|
|
38
39
|
[key: string]: Agent<AgentInput, AgentOutput>;
|
|
39
40
|
};
|
|
41
|
+
private disableLogging?;
|
|
40
42
|
addTool<I extends AgentInput, O extends AgentOutput>(tool: Agent<I, O> | FunctionAgentFn<I, O>): void;
|
|
41
43
|
get isCallable(): boolean;
|
|
42
44
|
call(input: I | string, context?: Context): Promise<O>;
|
package/lib/esm/agents/agent.js
CHANGED
|
@@ -2,7 +2,7 @@ import EventEmitter from "node:events";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { userInput } from "../prompt/prompt-builder";
|
|
4
4
|
import { logger } from "../utils/logger";
|
|
5
|
-
import {
|
|
5
|
+
import { transferToAgentOutput } from "./types";
|
|
6
6
|
export class Agent extends EventEmitter {
|
|
7
7
|
static from(options) {
|
|
8
8
|
return new Agent(options);
|
|
@@ -20,6 +20,7 @@ export class Agent extends EventEmitter {
|
|
|
20
20
|
this.publishTopic = options.publishTopic;
|
|
21
21
|
if (options.tools?.length)
|
|
22
22
|
this.tools.push(...options.tools.map(functionToAgent));
|
|
23
|
+
this.disableLogging = options.disableLogging;
|
|
23
24
|
}
|
|
24
25
|
name;
|
|
25
26
|
description;
|
|
@@ -31,6 +32,7 @@ export class Agent extends EventEmitter {
|
|
|
31
32
|
tools = new Proxy([], {
|
|
32
33
|
get: (t, p, r) => Reflect.get(t, p, r) ?? t.find((t) => t.name === p),
|
|
33
34
|
});
|
|
35
|
+
disableLogging;
|
|
34
36
|
addTool(tool) {
|
|
35
37
|
this.tools.push(typeof tool === "function" ? functionToAgent(tool) : tool);
|
|
36
38
|
}
|
|
@@ -42,19 +44,11 @@ export class Agent extends EventEmitter {
|
|
|
42
44
|
throw new Error("Agent must implement process method");
|
|
43
45
|
const _input = typeof input === "string" ? userInput(input) : input;
|
|
44
46
|
const parsedInput = this.inputSchema.passthrough().parse(_input);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const finalOutput = this.includeInputInOutput
|
|
49
|
-
? { ...parsedInput, ...parsedOutput }
|
|
50
|
-
: parsedOutput;
|
|
51
|
-
logger.debug(`Call agent ${this.name} successfully`, {
|
|
52
|
-
...finalOutput,
|
|
53
|
-
...(finalOutput[transferAgentOutputKey]
|
|
54
|
-
? { [transferAgentOutputKey]: finalOutput[transferAgentOutputKey].agent.name }
|
|
55
|
-
: {}),
|
|
47
|
+
const result = this.process(parsedInput, context).then((output) => {
|
|
48
|
+
const parsedOutput = this.outputSchema.passthrough().parse(output);
|
|
49
|
+
return this.includeInputInOutput ? { ...parsedInput, ...parsedOutput } : parsedOutput;
|
|
56
50
|
});
|
|
57
|
-
return
|
|
51
|
+
return logger.debug.spinner(result, `Call agent ${this.name}`, (output) => logger.debug("%O", { input, output }), { disabled: this.disableLogging });
|
|
58
52
|
}
|
|
59
53
|
async shutdown() { }
|
|
60
54
|
}
|
|
@@ -7,7 +7,7 @@ import { logger } from "../utils/logger";
|
|
|
7
7
|
import { Agent } from "./agent";
|
|
8
8
|
const MCP_AGENT_CLIENT_NAME = "MCPAgent";
|
|
9
9
|
const MCP_AGENT_CLIENT_VERSION = "0.0.1";
|
|
10
|
-
const debug = logger.base.extend("mcp
|
|
10
|
+
const debug = logger.base.extend("mcp");
|
|
11
11
|
function isSSEServerParameters(options) {
|
|
12
12
|
return "url" in options && typeof options.url === "string";
|
|
13
13
|
}
|
|
@@ -31,13 +31,9 @@ export class MCPAgent extends Agent {
|
|
|
31
31
|
name: MCP_AGENT_CLIENT_NAME,
|
|
32
32
|
version: MCP_AGENT_CLIENT_VERSION,
|
|
33
33
|
});
|
|
34
|
-
debug(
|
|
35
|
-
await client.connect(transport);
|
|
36
|
-
debug(`Connected to MCP server with transport ${transport.constructor.name}`);
|
|
34
|
+
await debug.spinner(client.connect(transport), "Connecting to MCP server");
|
|
37
35
|
const mcpServer = getMCPServerName(client);
|
|
38
|
-
debug(`Listing tools from ${mcpServer}
|
|
39
|
-
const { tools: mcpTools } = await client.listTools();
|
|
40
|
-
debug(`Listed tools from ${mcpServer}`, mcpTools.map((i) => i.name));
|
|
36
|
+
const { tools: mcpTools } = await debug.spinner(client.listTools(), `Listing tools from ${mcpServer}`, ({ tools }) => debug("%O", tools));
|
|
41
37
|
const tools = mcpTools.map((tool) => {
|
|
42
38
|
return new MCPTool({
|
|
43
39
|
client,
|
|
@@ -75,9 +71,7 @@ export class MCPTool extends Agent {
|
|
|
75
71
|
return getMCPServerName(this.client);
|
|
76
72
|
}
|
|
77
73
|
async process(input) {
|
|
78
|
-
debug(`
|
|
79
|
-
const result = await this.client.callTool({ name: this.name, arguments: input });
|
|
80
|
-
debug(`End call tool ${this.name} from ${this.mcpServer} with result`, result);
|
|
74
|
+
const result = await debug.spinner(this.client.callTool({ name: this.name, arguments: input }), `Call tool ${this.name} from ${this.mcpServer}`, (output) => debug("%O", { input, output }));
|
|
81
75
|
return result;
|
|
82
76
|
}
|
|
83
77
|
}
|
|
@@ -33,6 +33,7 @@ export declare class ExecutionEngine extends EventEmitter implements Context {
|
|
|
33
33
|
private runChatLoop;
|
|
34
34
|
private callAgent;
|
|
35
35
|
shutdown(): Promise<void>;
|
|
36
|
+
private initProcessExitHandler;
|
|
36
37
|
}
|
|
37
38
|
export declare class UserAgent<I extends AgentInput = AgentInput, O extends AgentOutput = AgentOutput> extends Agent<I, O> {
|
|
38
39
|
options: AgentOptions<I, O> & {
|
|
@@ -12,6 +12,7 @@ export class ExecutionEngine extends EventEmitter {
|
|
|
12
12
|
this.tools = options?.tools ?? [];
|
|
13
13
|
if (options?.agents?.length)
|
|
14
14
|
this.addAgent(...options.agents);
|
|
15
|
+
this.initProcessExitHandler();
|
|
15
16
|
}
|
|
16
17
|
messageQueue = new MessageQueue();
|
|
17
18
|
model;
|
|
@@ -169,11 +170,16 @@ export class ExecutionEngine extends EventEmitter {
|
|
|
169
170
|
await agent.shutdown();
|
|
170
171
|
}
|
|
171
172
|
}
|
|
173
|
+
initProcessExitHandler() {
|
|
174
|
+
const shutdownAndExit = () => this.shutdown().finally(() => process.exit(0));
|
|
175
|
+
process.on("SIGINT", shutdownAndExit);
|
|
176
|
+
process.on("exit", shutdownAndExit);
|
|
177
|
+
}
|
|
172
178
|
}
|
|
173
179
|
export class UserAgent extends Agent {
|
|
174
180
|
options;
|
|
175
181
|
constructor(options) {
|
|
176
|
-
super(options);
|
|
182
|
+
super({ ...options, disableLogging: true });
|
|
177
183
|
this.options = options;
|
|
178
184
|
}
|
|
179
185
|
process(input) {
|
package/lib/esm/index.d.ts
CHANGED
package/lib/esm/index.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type Debugger } from "debug";
|
|
2
|
+
interface DebugWithSpinner extends Debugger {
|
|
3
|
+
spinner<T>(promise: Promise<T>, message?: string, callback?: (result: T) => void, options?: {
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
}): Promise<T>;
|
|
6
|
+
extend: (namespace: string) => DebugWithSpinner;
|
|
7
|
+
}
|
|
8
|
+
declare function spinner<T>(promise: Promise<T>, message?: string, callback?: (result: T) => void): Promise<T>;
|
|
2
9
|
export declare const logger: {
|
|
3
|
-
base:
|
|
4
|
-
debug:
|
|
5
|
-
|
|
10
|
+
base: DebugWithSpinner;
|
|
11
|
+
debug: DebugWithSpinner;
|
|
12
|
+
spinner: typeof spinner;
|
|
6
13
|
};
|
|
14
|
+
export {};
|
package/lib/esm/utils/logger.js
CHANGED
|
@@ -1,6 +1,61 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
debug.log = (...args) => {
|
|
4
|
+
const { isSpinning } = globalSpinner;
|
|
5
|
+
if (isSpinning)
|
|
6
|
+
globalSpinner.stop();
|
|
7
|
+
console.log(...args);
|
|
8
|
+
if (isSpinning)
|
|
9
|
+
globalSpinner.start();
|
|
10
|
+
};
|
|
11
|
+
function createDebugger(namespace) {
|
|
12
|
+
const i = debug(namespace);
|
|
13
|
+
function overrideExtend(debug) {
|
|
14
|
+
const originalExtend = debug.extend;
|
|
15
|
+
debug.extend = (namespace) => {
|
|
16
|
+
const extended = originalExtend.call(debug, namespace);
|
|
17
|
+
overrideExtend(extended);
|
|
18
|
+
extended.spinner = async (promise, message, callback, options) => {
|
|
19
|
+
if (!extended.enabled || options?.disabled)
|
|
20
|
+
return promise;
|
|
21
|
+
return spinner(promise, message, callback);
|
|
22
|
+
};
|
|
23
|
+
return extended;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
overrideExtend(i);
|
|
27
|
+
return i;
|
|
28
|
+
}
|
|
29
|
+
const globalSpinner = ora();
|
|
30
|
+
async function spinner(promise, message, callback) {
|
|
31
|
+
const { isSpinning, text } = globalSpinner;
|
|
32
|
+
try {
|
|
33
|
+
globalSpinner.start(message || " ");
|
|
34
|
+
const result = await promise;
|
|
35
|
+
if (message)
|
|
36
|
+
globalSpinner.succeed(message);
|
|
37
|
+
else
|
|
38
|
+
globalSpinner.stop();
|
|
39
|
+
// NOTE: This is a workaround to make sure the spinner stops spinning before the next tick
|
|
40
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
41
|
+
callback?.(result);
|
|
42
|
+
// NOTE: This is a workaround to make sure the spinner stops spinning before the next tick
|
|
43
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
globalSpinner.fail(message || " ");
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
// Recover the spinner state
|
|
52
|
+
if (isSpinning)
|
|
53
|
+
globalSpinner.start(text || " ");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const base = createDebugger("aigne");
|
|
2
57
|
export const logger = {
|
|
3
|
-
base
|
|
4
|
-
debug:
|
|
5
|
-
|
|
58
|
+
base,
|
|
59
|
+
debug: base.extend("core"),
|
|
60
|
+
spinner,
|
|
6
61
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentOutput } from "../agents/agent";
|
|
2
|
+
import type { UserAgent } from "../execution-engine";
|
|
3
|
+
export interface ChatLoopOptions {
|
|
4
|
+
welcome?: string;
|
|
5
|
+
defaultQuestion?: string;
|
|
6
|
+
onResponse?: (response: AgentOutput) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function runChatLoopInTerminal(userAgent: UserAgent, options?: ChatLoopOptions): Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
import { logger } from "./logger";
|
|
3
|
+
export async function runChatLoopInTerminal(userAgent, options) {
|
|
4
|
+
if (options?.welcome)
|
|
5
|
+
console.log(options.welcome);
|
|
6
|
+
for (let i = 0;; i++) {
|
|
7
|
+
const { question } = await inquirer.prompt([
|
|
8
|
+
{
|
|
9
|
+
type: "input",
|
|
10
|
+
name: "question",
|
|
11
|
+
message: ">",
|
|
12
|
+
default: i === 0 ? options?.defaultQuestion : undefined,
|
|
13
|
+
},
|
|
14
|
+
]);
|
|
15
|
+
if (!question.trim())
|
|
16
|
+
continue;
|
|
17
|
+
const cmd = COMMANDS[question.trim()];
|
|
18
|
+
if (cmd) {
|
|
19
|
+
await cmd();
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const response = await logger.spinner(userAgent.call(question));
|
|
23
|
+
if (options?.onResponse)
|
|
24
|
+
options.onResponse(response);
|
|
25
|
+
else
|
|
26
|
+
console.log(response);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const COMMANDS = {
|
|
30
|
+
"/exit": () => process.exit(0),
|
|
31
|
+
"/help": () => {
|
|
32
|
+
console.log(`\
|
|
33
|
+
Commands:
|
|
34
|
+
/exit - exit the chat loop
|
|
35
|
+
/help - show this help message
|
|
36
|
+
`);
|
|
37
|
+
},
|
|
38
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/core",
|
|
3
|
-
"version": "1.1.0-beta.
|
|
3
|
+
"version": "1.1.0-beta.4",
|
|
4
4
|
"description": "AIGNE core library",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -8,16 +8,24 @@
|
|
|
8
8
|
"author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
|
|
9
9
|
"homepage": "https://github.com/blocklet/ai-studio#readme",
|
|
10
10
|
"license": "ISC",
|
|
11
|
+
"type": "module",
|
|
11
12
|
"main": "./lib/cjs/index.js",
|
|
12
13
|
"module": "./lib/esm/index.js",
|
|
13
14
|
"types": "./lib/dts/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": "./lib/esm/index.js",
|
|
18
|
+
"require": "./lib/cjs/index.js",
|
|
19
|
+
"types": "./lib/dts/index.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
14
22
|
"files": [
|
|
15
23
|
"lib/cjs",
|
|
16
24
|
"lib/dts",
|
|
17
25
|
"lib/esm",
|
|
18
26
|
"LICENSE",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
27
|
+
"README.md",
|
|
28
|
+
"CHANGELOG.md"
|
|
21
29
|
],
|
|
22
30
|
"repository": {
|
|
23
31
|
"type": "git",
|
|
@@ -30,10 +38,12 @@
|
|
|
30
38
|
"@types/debug": "^4.1.12",
|
|
31
39
|
"@types/mustache": "^4.2.5",
|
|
32
40
|
"debug": "^4.4.0",
|
|
41
|
+
"inquirer": "^12.4.3",
|
|
33
42
|
"lodash": "^4.17.21",
|
|
34
43
|
"mustache": "^4.2.0",
|
|
35
44
|
"nanoid": "^5.1.3",
|
|
36
45
|
"openai": "^4.86.2",
|
|
46
|
+
"ora": "^8.2.0",
|
|
37
47
|
"zod": "^3.24.2",
|
|
38
48
|
"zod-to-json-schema": "^3.24.3"
|
|
39
49
|
},
|