@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 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>;
@@ -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
- logger_1.logger.debug(`Call agent ${this.name} start`, parsedInput);
52
- const output = await this.process(parsedInput, context);
53
- const parsedOutput = this.outputSchema.passthrough().parse(output);
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 finalOutput;
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-agent:debug", "/");
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(`Connecting to MCP server with transport ${transport.constructor.name}`);
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(`Start call tool ${this.name} from ${this.mcpServer} with input`, input);
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) {
@@ -8,3 +8,4 @@ export * from "./models/chat";
8
8
  export * from "./models/chat-openai";
9
9
  export * from "./prompt/prompt-builder";
10
10
  export * from "./prompt/template";
11
+ export * from "./utils/run-chat-loop";
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 debug from "debug";
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: debug.Debugger;
4
- debug: debug.Debugger;
5
- error: debug.Debugger;
10
+ base: DebugWithSpinner;
11
+ debug: DebugWithSpinner;
12
+ spinner: typeof spinner;
6
13
  };
14
+ export {};
@@ -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: (0, debug_1.default)("@aigne/core"),
10
- debug: (0, debug_1.default)("@aigne/core:debug"),
11
- error: (0, debug_1.default)("@aigne/core:error"),
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> & {
@@ -8,3 +8,4 @@ export * from "./models/chat";
8
8
  export * from "./models/chat-openai";
9
9
  export * from "./prompt/prompt-builder";
10
10
  export * from "./prompt/template";
11
+ export * from "./utils/run-chat-loop";
@@ -1,6 +1,14 @@
1
- import debug from "debug";
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: debug.Debugger;
4
- debug: debug.Debugger;
5
- error: debug.Debugger;
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>;
@@ -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 { transferAgentOutputKey, transferToAgentOutput } from "./types";
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
- logger.debug(`Call agent ${this.name} start`, parsedInput);
46
- const output = await this.process(parsedInput, context);
47
- const parsedOutput = this.outputSchema.passthrough().parse(output);
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 finalOutput;
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-agent:debug", "/");
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(`Connecting to MCP server with transport ${transport.constructor.name}`);
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(`Start call tool ${this.name} from ${this.mcpServer} with input`, input);
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) {
@@ -8,3 +8,4 @@ export * from "./models/chat";
8
8
  export * from "./models/chat-openai";
9
9
  export * from "./prompt/prompt-builder";
10
10
  export * from "./prompt/template";
11
+ export * from "./utils/run-chat-loop";
package/lib/esm/index.js CHANGED
@@ -8,3 +8,4 @@ export * from "./models/chat";
8
8
  export * from "./models/chat-openai";
9
9
  export * from "./prompt/prompt-builder";
10
10
  export * from "./prompt/template";
11
+ export * from "./utils/run-chat-loop";
@@ -1,6 +1,14 @@
1
- import debug from "debug";
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: debug.Debugger;
4
- debug: debug.Debugger;
5
- error: debug.Debugger;
10
+ base: DebugWithSpinner;
11
+ debug: DebugWithSpinner;
12
+ spinner: typeof spinner;
6
13
  };
14
+ export {};
@@ -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: debug("@aigne/core"),
4
- debug: debug("@aigne/core:debug"),
5
- error: debug("@aigne/core:error"),
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.2",
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
- "package.json",
20
- "README.md"
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
  },