@aigne/cli 1.7.0 → 1.8.1
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 +28 -0
- package/dist/commands/aigne.js +2 -2
- package/dist/commands/run.js +15 -15
- package/dist/commands/serve.js +11 -3
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/tracer/terminal.d.ts +1 -2
- package/dist/tracer/terminal.js +2 -2
- package/dist/utils/agent-v1.js +7 -7
- package/dist/utils/serve-mcp.d.ts +7 -3
- package/dist/utils/serve-mcp.js +69 -49
- package/package.json +2 -2
- package/templates/default/README.md +1 -1
- package/templates/default/chat.yaml +1 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.8.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.8.0...cli-v1.8.1) (2025-04-30)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Dependencies
|
|
7
|
+
|
|
8
|
+
* The following workspace dependencies were updated
|
|
9
|
+
* dependencies
|
|
10
|
+
* @aigne/core bumped to 1.13.0
|
|
11
|
+
|
|
12
|
+
## [1.8.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.7.0...cli-v1.8.0) (2025-04-27)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* support TeamAgent and finalize API naming ([#91](https://github.com/AIGNE-io/aigne-framework/issues/91)) ([033d1b6](https://github.com/AIGNE-io/aigne-framework/commit/033d1b6a7dc5460807476abb35a413ba89a2a664))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* upgrade to streamable api for serve mcp command ([#98](https://github.com/AIGNE-io/aigne-framework/issues/98)) ([ae32bda](https://github.com/AIGNE-io/aigne-framework/commit/ae32bda20e57c2a2eb8b49fad034b0b2a5ebb15e))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Dependencies
|
|
26
|
+
|
|
27
|
+
* The following workspace dependencies were updated
|
|
28
|
+
* dependencies
|
|
29
|
+
* @aigne/core bumped to 1.12.0
|
|
30
|
+
|
|
3
31
|
## [1.7.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.6.0...cli-v1.7.0) (2025-04-23)
|
|
4
32
|
|
|
5
33
|
|
package/dist/commands/aigne.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import
|
|
2
|
+
import { AIGNE_CLI_VERSION } from "../constants.js";
|
|
3
3
|
import { asciiLogo } from "../utils/ascii-logo.js";
|
|
4
4
|
import { createCreateCommand } from "./create.js";
|
|
5
5
|
import { createRunCommand } from "./run.js";
|
|
@@ -10,7 +10,7 @@ export function createAIGNECommand() {
|
|
|
10
10
|
return new Command()
|
|
11
11
|
.name("aigne")
|
|
12
12
|
.description("CLI for AIGNE framework")
|
|
13
|
-
.version(
|
|
13
|
+
.version(AIGNE_CLI_VERSION)
|
|
14
14
|
.addCommand(createRunCommand())
|
|
15
15
|
.addCommand(createTestCommand())
|
|
16
16
|
.addCommand(createCreateCommand())
|
package/dist/commands/run.js
CHANGED
|
@@ -2,7 +2,7 @@ import assert from "node:assert";
|
|
|
2
2
|
import { cp, mkdir, rm } from "node:fs/promises";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { isAbsolute, join, resolve } from "node:path";
|
|
5
|
-
import {
|
|
5
|
+
import { AIGNE } from "@aigne/core";
|
|
6
6
|
import { loadModel } from "@aigne/core/loader/index.js";
|
|
7
7
|
import { logger } from "@aigne/core/utils/logger.js";
|
|
8
8
|
import { isNonNullable } from "@aigne/core/utils/type-utils.js";
|
|
@@ -24,7 +24,7 @@ export function createRunCommand() {
|
|
|
24
24
|
if (options.verbose)
|
|
25
25
|
logger.enable("*");
|
|
26
26
|
const { downloadDir, dir } = prepareDirs(path, options);
|
|
27
|
-
const {
|
|
27
|
+
const { aigne, agent } = await new Listr([
|
|
28
28
|
{
|
|
29
29
|
title: "Prepare environment",
|
|
30
30
|
task: (_, task) => {
|
|
@@ -43,30 +43,30 @@ export function createRunCommand() {
|
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
|
-
title: "Initialize
|
|
46
|
+
title: "Initialize AIGNE",
|
|
47
47
|
task: async (ctx) => {
|
|
48
|
-
const
|
|
49
|
-
ctx.
|
|
48
|
+
const aigne = await loadAIGNE(dir, options);
|
|
49
|
+
ctx.aigne = aigne;
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
task: (ctx) => {
|
|
54
|
-
const {
|
|
55
|
-
assert(
|
|
54
|
+
const { aigne } = ctx;
|
|
55
|
+
assert(aigne);
|
|
56
56
|
let agent;
|
|
57
57
|
if (options.agent) {
|
|
58
|
-
agent =
|
|
58
|
+
agent = aigne.agents[options.agent];
|
|
59
59
|
if (!agent) {
|
|
60
60
|
console.error(`Agent "${options.agent}" not found in ${path}`);
|
|
61
61
|
console.log("Available agents:");
|
|
62
|
-
for (const agent of
|
|
62
|
+
for (const agent of aigne.agents) {
|
|
63
63
|
console.log(`- ${agent.name}`);
|
|
64
64
|
}
|
|
65
65
|
throw new Error(`Agent "${options.agent}" not found in ${path}`);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
69
|
-
agent =
|
|
69
|
+
agent = aigne.agents[0];
|
|
70
70
|
if (!agent)
|
|
71
71
|
throw new Error(`No agents found in ${path}`);
|
|
72
72
|
}
|
|
@@ -79,23 +79,23 @@ export function createRunCommand() {
|
|
|
79
79
|
timer: PRESET_TIMER,
|
|
80
80
|
},
|
|
81
81
|
}).run();
|
|
82
|
-
assert(
|
|
82
|
+
assert(aigne);
|
|
83
83
|
assert(agent);
|
|
84
|
-
const user =
|
|
84
|
+
const user = aigne.invoke(agent);
|
|
85
85
|
await runChatLoopInTerminal(user);
|
|
86
|
-
await
|
|
86
|
+
await aigne.shutdown();
|
|
87
87
|
})
|
|
88
88
|
.showHelpAfterError(true)
|
|
89
89
|
.showSuggestionAfterError(true);
|
|
90
90
|
}
|
|
91
|
-
async function
|
|
91
|
+
async function loadAIGNE(path, options) {
|
|
92
92
|
if (options.modelName && !options.modelProvider) {
|
|
93
93
|
throw new Error("please specify --model-provider when using the --model-name option");
|
|
94
94
|
}
|
|
95
95
|
const model = options.modelProvider
|
|
96
96
|
? await loadModel({ provider: options.modelProvider, name: options.modelName })
|
|
97
97
|
: undefined;
|
|
98
|
-
return await
|
|
98
|
+
return await AIGNE.load({ path, model });
|
|
99
99
|
}
|
|
100
100
|
async function downloadPackage(url, downloadDir) {
|
|
101
101
|
await rm(downloadDir, { recursive: true, force: true });
|
package/dist/commands/serve.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isAbsolute, resolve } from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { AIGNE } from "@aigne/core";
|
|
3
3
|
import { tryOrThrow } from "@aigne/core/utils/type-utils.js";
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import { serveMCPServer } from "../utils/serve-mcp.js";
|
|
@@ -17,15 +17,23 @@ export function createServeCommand() {
|
|
|
17
17
|
.description("Serve the agents in the specified directory as a MCP server")
|
|
18
18
|
.argument("[path]", "Path to the agents directory", ".")
|
|
19
19
|
.option("--mcp", "Serve the agents as a MCP server")
|
|
20
|
+
.option("--host <host>", "Host to run the MCP server on, use 0.0.0.0 to publicly expose the server", "localhost")
|
|
20
21
|
.option("--port <port>", "Port to run the MCP server on", (s) => Number.parseInt(s))
|
|
22
|
+
.option("--pathname <pathname>", "Pathname to the service", "/mcp")
|
|
21
23
|
.action(async (path, options) => {
|
|
22
24
|
const absolutePath = isAbsolute(path) ? path : resolve(process.cwd(), path);
|
|
23
25
|
const port = options.port || DEFAULT_PORT();
|
|
24
|
-
const
|
|
26
|
+
const aigne = await AIGNE.load({ path: absolutePath });
|
|
25
27
|
if (options.mcp)
|
|
26
|
-
await serveMCPServer({
|
|
28
|
+
await serveMCPServer({
|
|
29
|
+
aigne,
|
|
30
|
+
host: options.host,
|
|
31
|
+
port,
|
|
32
|
+
pathname: options.pathname,
|
|
33
|
+
});
|
|
27
34
|
else
|
|
28
35
|
throw new Error("Default server is not supported yet. Please use --mcp option");
|
|
36
|
+
console.log(`MCP server is running on http://${options.host}:${port}${options.pathname}`);
|
|
29
37
|
})
|
|
30
38
|
.showHelpAfterError(true)
|
|
31
39
|
.showSuggestionAfterError(true);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const AIGNE_CLI_VERSION: string;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { type Agent, type Context, MESSAGE_KEY, type Message } from "@aigne/core";
|
|
2
|
-
import type { ContextUsage } from "@aigne/core/execution-engine/usage";
|
|
1
|
+
import { type Agent, type Context, type ContextUsage, MESSAGE_KEY, type Message } from "@aigne/core";
|
|
3
2
|
import { type DefaultRenderer, Listr, type ListrRenderer, type ListrTaskWrapper } from "@aigne/listr2";
|
|
4
3
|
import { promiseWithResolvers } from "../utils/promise-with-resolvers.js";
|
|
5
4
|
export interface TerminalTracerOptions {
|
package/dist/tracer/terminal.js
CHANGED
|
@@ -99,7 +99,7 @@ export class TerminalTracer {
|
|
|
99
99
|
context.on("agentSucceed", onAgentSucceed);
|
|
100
100
|
context.on("agentFailed", onAgentFailed);
|
|
101
101
|
try {
|
|
102
|
-
const stream = await context.
|
|
102
|
+
const stream = await context.invoke(agent, input, { streaming: true });
|
|
103
103
|
const result = await listr.run(stream);
|
|
104
104
|
return { result, context };
|
|
105
105
|
}
|
|
@@ -129,7 +129,7 @@ export class TerminalTracer {
|
|
|
129
129
|
return chalk.grey(`[${parseDuration(duration)}]`);
|
|
130
130
|
}
|
|
131
131
|
formatTaskTitle(agent, { task, usage, time } = {}) {
|
|
132
|
-
let title = `
|
|
132
|
+
let title = `invoke agent ${agent.name}`;
|
|
133
133
|
if (usage && task?.usage)
|
|
134
134
|
title += ` ${this.formatTokenUsage(task.usage, task.extraTitleMetadata)}`;
|
|
135
135
|
if (time && task?.startTime && task.endTime)
|
package/dist/utils/agent-v1.js
CHANGED
|
@@ -43,15 +43,15 @@ async function loadAgentV1Package(path) {
|
|
|
43
43
|
return definition;
|
|
44
44
|
}
|
|
45
45
|
function assistantToAigneV2(agent, project) {
|
|
46
|
-
const converter =
|
|
46
|
+
const converter = AGENT_MAP[agent.type];
|
|
47
47
|
if (!converter)
|
|
48
|
-
throw new Error(`Unsupported
|
|
48
|
+
throw new Error(`Unsupported agent type: ${agent.type}`);
|
|
49
49
|
return converter(agent, project);
|
|
50
50
|
}
|
|
51
|
-
const
|
|
51
|
+
const AGENT_MAP = {
|
|
52
52
|
prompt: (agent) => {
|
|
53
53
|
if (agent.type !== "prompt")
|
|
54
|
-
throw new Error(`Expected
|
|
54
|
+
throw new Error(`Expected agent type 'prompt', but got '${agent.type}'`);
|
|
55
55
|
const obj = {
|
|
56
56
|
name: agent.name || agent.id,
|
|
57
57
|
description: agent.description,
|
|
@@ -68,7 +68,7 @@ const RUNNABLE_MAP = {
|
|
|
68
68
|
},
|
|
69
69
|
function: async (agent) => {
|
|
70
70
|
if (agent.type !== "function")
|
|
71
|
-
throw new Error(`Expected
|
|
71
|
+
throw new Error(`Expected agent type 'function', but got '${agent.type}'`);
|
|
72
72
|
const inputNames = agent.parameters?.map((i) => i.key).filter(Boolean) ?? [];
|
|
73
73
|
return {
|
|
74
74
|
content: await formatCode(`\
|
|
@@ -88,7 +88,7 @@ agent.output_schema = ${JSON.stringify(convertOutputSchema(agent))};
|
|
|
88
88
|
},
|
|
89
89
|
router: (agent, project) => {
|
|
90
90
|
if (agent.type !== "router")
|
|
91
|
-
throw new Error(`Expected
|
|
91
|
+
throw new Error(`Expected agent type 'router', but got '${agent.type}'`);
|
|
92
92
|
return {
|
|
93
93
|
content: stringify({
|
|
94
94
|
name: agent.name || agent.id,
|
|
@@ -96,7 +96,7 @@ agent.output_schema = ${JSON.stringify(convertOutputSchema(agent))};
|
|
|
96
96
|
instructions: agent.prompt,
|
|
97
97
|
input_schema: convertInputSchema(agent),
|
|
98
98
|
output_schema: convertOutputSchema(agent),
|
|
99
|
-
|
|
99
|
+
skills: agent.routes?.map((i) => {
|
|
100
100
|
const tool = project.agents.find((j) => j.id === i.id);
|
|
101
101
|
if (!tool)
|
|
102
102
|
throw new Error(`Tool ${i.id} not found in project definition`);
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { type AIGNE } from "@aigne/core";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
export declare function serveMCPServer({ pathname, aigne, host, port, }: {
|
|
4
|
+
pathname?: string;
|
|
5
|
+
aigne: AIGNE;
|
|
6
|
+
host?: string;
|
|
4
7
|
port: number;
|
|
5
8
|
}): Promise<import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>>;
|
|
9
|
+
export declare function createMcpServer(aigne: AIGNE): McpServer;
|
package/dist/utils/serve-mcp.js
CHANGED
|
@@ -1,23 +1,83 @@
|
|
|
1
1
|
import { getMessage } from "@aigne/core";
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
-
import {
|
|
4
|
-
import express from "express";
|
|
3
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
|
+
import express, { Router, json } from "express";
|
|
5
5
|
import { ZodObject } from "zod";
|
|
6
|
+
import { AIGNE_CLI_VERSION } from "../constants.js";
|
|
6
7
|
import { promiseWithResolvers } from "./promise-with-resolvers.js";
|
|
7
|
-
export async function serveMCPServer({
|
|
8
|
+
export async function serveMCPServer({ pathname = "/mcp", aigne, host = "localhost", port, }) {
|
|
9
|
+
const app = express();
|
|
10
|
+
app.use(json());
|
|
11
|
+
const router = Router();
|
|
12
|
+
app.use(router);
|
|
13
|
+
router.post(pathname, async (req, res) => {
|
|
14
|
+
try {
|
|
15
|
+
const server = createMcpServer(aigne);
|
|
16
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
17
|
+
await server.connect(transport);
|
|
18
|
+
await transport.handleRequest(req, res, req.body);
|
|
19
|
+
res.on("close", async () => {
|
|
20
|
+
await transport.close();
|
|
21
|
+
await server.close();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.error("Error handling MCP request:", error);
|
|
26
|
+
if (!res.headersSent) {
|
|
27
|
+
res.status(500).json({
|
|
28
|
+
jsonrpc: "2.0",
|
|
29
|
+
error: {
|
|
30
|
+
code: -32603,
|
|
31
|
+
message: error.message,
|
|
32
|
+
},
|
|
33
|
+
id: null,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
router.get(pathname, async (_, res) => {
|
|
39
|
+
res.writeHead(405).end(JSON.stringify({
|
|
40
|
+
jsonrpc: "2.0",
|
|
41
|
+
error: {
|
|
42
|
+
code: -32000,
|
|
43
|
+
message: "Method not allowed.",
|
|
44
|
+
},
|
|
45
|
+
id: null,
|
|
46
|
+
}));
|
|
47
|
+
});
|
|
48
|
+
router.delete(pathname, async (_, res) => {
|
|
49
|
+
res.writeHead(405).end(JSON.stringify({
|
|
50
|
+
jsonrpc: "2.0",
|
|
51
|
+
error: {
|
|
52
|
+
code: -32000,
|
|
53
|
+
message: "Method not allowed.",
|
|
54
|
+
},
|
|
55
|
+
id: null,
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
const { promise, resolve, reject } = promiseWithResolvers();
|
|
59
|
+
const httpServer = app.listen(port, host, (error) => {
|
|
60
|
+
if (error)
|
|
61
|
+
reject(error);
|
|
62
|
+
resolve();
|
|
63
|
+
});
|
|
64
|
+
await promise;
|
|
65
|
+
return httpServer;
|
|
66
|
+
}
|
|
67
|
+
export function createMcpServer(aigne) {
|
|
8
68
|
const server = new McpServer({
|
|
9
|
-
name:
|
|
10
|
-
version:
|
|
69
|
+
name: aigne.name || "aigne-mcp-server",
|
|
70
|
+
version: AIGNE_CLI_VERSION,
|
|
11
71
|
}, {
|
|
12
72
|
capabilities: { tools: {} },
|
|
13
|
-
instructions:
|
|
73
|
+
instructions: aigne.description,
|
|
14
74
|
});
|
|
15
|
-
for (const agent of
|
|
75
|
+
for (const agent of aigne.agents) {
|
|
16
76
|
const schema = agent.inputSchema;
|
|
17
77
|
if (!(schema instanceof ZodObject))
|
|
18
78
|
throw new Error("Agent input schema must be a ZodObject");
|
|
19
79
|
server.tool(agent.name, agent.description || "", schema.shape, async (input) => {
|
|
20
|
-
const result = await
|
|
80
|
+
const result = await aigne.invoke(agent, input);
|
|
21
81
|
return {
|
|
22
82
|
content: [
|
|
23
83
|
{
|
|
@@ -28,45 +88,5 @@ export async function serveMCPServer({ engine, port }) {
|
|
|
28
88
|
};
|
|
29
89
|
});
|
|
30
90
|
}
|
|
31
|
-
|
|
32
|
-
const transports = {};
|
|
33
|
-
app.get("/sse", async (req, res) => {
|
|
34
|
-
const transport = new SSEServerTransport("/messages", res);
|
|
35
|
-
transports[transport.sessionId] = transport;
|
|
36
|
-
req.on("close", () => {
|
|
37
|
-
delete transports[transport.sessionId];
|
|
38
|
-
});
|
|
39
|
-
await server.connect(transport);
|
|
40
|
-
});
|
|
41
|
-
app.post("/messages", async (req, res) => {
|
|
42
|
-
const sessionId = req.query.sessionId;
|
|
43
|
-
const transport = transports[sessionId];
|
|
44
|
-
if (transport) {
|
|
45
|
-
await transport.handlePostMessage(req, res);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
throw new HttpError(400, "No transport found for sessionId");
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
app.use(((error, _req, res, _next) => {
|
|
52
|
-
console.error("handle route error", { error });
|
|
53
|
-
res
|
|
54
|
-
.status(error instanceof HttpError ? error.status : 500)
|
|
55
|
-
.json({ error: { message: error.message } });
|
|
56
|
-
}));
|
|
57
|
-
const { promise, resolve, reject } = promiseWithResolvers();
|
|
58
|
-
const httpServer = app.listen(port, (error) => {
|
|
59
|
-
if (error)
|
|
60
|
-
reject(error);
|
|
61
|
-
resolve();
|
|
62
|
-
});
|
|
63
|
-
await promise;
|
|
64
|
-
return httpServer;
|
|
65
|
-
}
|
|
66
|
-
class HttpError extends Error {
|
|
67
|
-
status;
|
|
68
|
-
constructor(status, message) {
|
|
69
|
-
super(message);
|
|
70
|
-
this.status = status;
|
|
71
|
-
}
|
|
91
|
+
return server;
|
|
72
92
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "cli for AIGNE framework",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"pretty-error": "^4.0.0",
|
|
51
51
|
"tar": "^7.4.3",
|
|
52
52
|
"zod": "^3.24.2",
|
|
53
|
-
"@aigne/core": "^1.
|
|
53
|
+
"@aigne/core": "^1.13.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/archiver": "^6.0.3",
|
|
@@ -5,7 +5,7 @@ This is the default project template for the Aigne framework, providing a basic
|
|
|
5
5
|
## Template Structure
|
|
6
6
|
|
|
7
7
|
- `aigne.yaml` - Project configuration file that defines the chat model used and references to agents
|
|
8
|
-
- `chat.yaml` - Chat agent configuration, including agent instructions and
|
|
8
|
+
- `chat.yaml` - Chat agent configuration, including agent instructions and skills used
|
|
9
9
|
- `sandbox.js` - JavaScript code execution tool for running JavaScript code within conversations
|
|
10
10
|
- `sandbox.test.js` - Test file to verify the functionality of the code execution tool
|
|
11
11
|
|
|
@@ -3,8 +3,6 @@ description: Chat agent
|
|
|
3
3
|
instructions: |
|
|
4
4
|
You are a helpful assistant that can answer questions and provide information on a wide range of topics.
|
|
5
5
|
Your goal is to assist users in finding the information they need and to engage in friendly conversation.
|
|
6
|
-
memory:
|
|
7
|
-
subscribeTopic:
|
|
8
|
-
- chat
|
|
6
|
+
memory: true
|
|
9
7
|
tools:
|
|
10
8
|
- sandbox.js
|