@aigne/cli 1.48.4-beta.5 → 1.49.0-beta.10
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 +116 -0
- package/dist/commands/aigne.js +2 -0
- package/dist/commands/app.d.ts +29 -15
- package/dist/commands/app.js +111 -106
- package/dist/commands/eval.d.ts +11 -0
- package/dist/commands/eval.js +109 -0
- package/dist/commands/run.js +4 -3
- package/dist/tracer/terminal.js +7 -6
- package/dist/utils/evaluation/core.d.ts +8 -0
- package/dist/utils/evaluation/core.js +80 -0
- package/dist/utils/evaluation/dataset.d.ts +15 -0
- package/dist/utils/evaluation/dataset.js +61 -0
- package/dist/utils/evaluation/evaluator.d.ts +9 -0
- package/dist/utils/evaluation/evaluator.js +107 -0
- package/dist/utils/evaluation/reporter.d.ts +28 -0
- package/dist/utils/evaluation/reporter.js +221 -0
- package/dist/utils/evaluation/runner.d.ts +16 -0
- package/dist/utils/evaluation/runner.js +129 -0
- package/dist/utils/evaluation/type.d.ts +68 -0
- package/dist/utils/load-aigne.d.ts +2 -1
- package/dist/utils/load-aigne.js +7 -7
- package/dist/utils/workers/run-aigne-in-child-process-worker.d.ts +18 -0
- package/dist/utils/workers/run-aigne-in-child-process-worker.js +72 -0
- package/dist/utils/workers/run-aigne-in-child-process.d.ts +14 -0
- package/dist/utils/workers/run-aigne-in-child-process.js +30 -0
- package/dist/utils/yargs.d.ts +1 -1
- package/package.json +12 -9
- package/dist/utils/workers/load-aigne-worker.js +0 -13
- package/dist/utils/workers/load-aigne.d.ts +0 -2
- package/dist/utils/workers/load-aigne.js +0 -27
- /package/dist/utils/{workers/load-aigne-worker.d.ts → evaluation/type.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,121 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.49.0-beta.10](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.9...cli-v1.49.0-beta.10) (2025-09-27)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **cli:** resolve input schema not working for run command ([#557](https://github.com/AIGNE-io/aigne-framework/issues/557)) ([6fa12b3](https://github.com/AIGNE-io/aigne-framework/commit/6fa12b3e068aaec28cf204c3a3f7c471bd2827ae))
|
|
9
|
+
|
|
10
|
+
## [1.49.0-beta.9](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.8...cli-v1.49.0-beta.9) (2025-09-26)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **cli:** add `--beta` `--target-version` `--force` options for `upgrade` command ([#555](https://github.com/AIGNE-io/aigne-framework/issues/555)) ([f9f0471](https://github.com/AIGNE-io/aigne-framework/commit/f9f04719020cca00bc3adbe8169c42422201df49))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **blocklet:** observability blocklet start failure ([#554](https://github.com/AIGNE-io/aigne-framework/issues/554)) ([8431d4d](https://github.com/AIGNE-io/aigne-framework/commit/8431d4d89a4b96f735f23e774e9545bbe1fd811c))
|
|
21
|
+
* **blocklet:** observability blocklet start failure ([#554](https://github.com/AIGNE-io/aigne-framework/issues/554)) ([8431d4d](https://github.com/AIGNE-io/aigne-framework/commit/8431d4d89a4b96f735f23e774e9545bbe1fd811c))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Dependencies
|
|
25
|
+
|
|
26
|
+
* The following workspace dependencies were updated
|
|
27
|
+
* dependencies
|
|
28
|
+
* @aigne/agent-library bumped to 1.21.46-beta.9
|
|
29
|
+
* @aigne/agentic-memory bumped to 1.0.46-beta.9
|
|
30
|
+
* @aigne/aigne-hub bumped to 0.10.0-beta.9
|
|
31
|
+
* @aigne/core bumped to 1.61.0-beta.8
|
|
32
|
+
* @aigne/default-memory bumped to 1.2.9-beta.9
|
|
33
|
+
* @aigne/observability-api bumped to 0.11.0-beta.1
|
|
34
|
+
* @aigne/openai bumped to 0.16.0-beta.9
|
|
35
|
+
* devDependencies
|
|
36
|
+
* @aigne/test-utils bumped to 0.5.53-beta.8
|
|
37
|
+
|
|
38
|
+
## [1.49.0-beta.8](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.7...cli-v1.49.0-beta.8) (2025-09-26)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### Dependencies
|
|
42
|
+
|
|
43
|
+
* The following workspace dependencies were updated
|
|
44
|
+
* dependencies
|
|
45
|
+
* @aigne/agent-library bumped to 1.21.46-beta.8
|
|
46
|
+
* @aigne/agentic-memory bumped to 1.0.46-beta.8
|
|
47
|
+
* @aigne/aigne-hub bumped to 0.10.0-beta.8
|
|
48
|
+
* @aigne/core bumped to 1.61.0-beta.7
|
|
49
|
+
* @aigne/default-memory bumped to 1.2.9-beta.8
|
|
50
|
+
* @aigne/openai bumped to 0.16.0-beta.8
|
|
51
|
+
* devDependencies
|
|
52
|
+
* @aigne/test-utils bumped to 0.5.53-beta.7
|
|
53
|
+
|
|
54
|
+
## [1.49.0-beta.7](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.6...cli-v1.49.0-beta.7) (2025-09-26)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### Bug Fixes
|
|
58
|
+
|
|
59
|
+
* **cli:** options.prompts should always available ([44ca0a6](https://github.com/AIGNE-io/aigne-framework/commit/44ca0a65d910fbd327b89d2f3dfe38ab7d1be7df))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
### Dependencies
|
|
63
|
+
|
|
64
|
+
* The following workspace dependencies were updated
|
|
65
|
+
* dependencies
|
|
66
|
+
* @aigne/agent-library bumped to 1.21.46-beta.7
|
|
67
|
+
* @aigne/agentic-memory bumped to 1.0.46-beta.7
|
|
68
|
+
* @aigne/aigne-hub bumped to 0.10.0-beta.7
|
|
69
|
+
* @aigne/core bumped to 1.61.0-beta.6
|
|
70
|
+
* @aigne/default-memory bumped to 1.2.9-beta.7
|
|
71
|
+
* @aigne/openai bumped to 0.16.0-beta.7
|
|
72
|
+
* devDependencies
|
|
73
|
+
* @aigne/test-utils bumped to 0.5.53-beta.6
|
|
74
|
+
|
|
75
|
+
## [1.49.0-beta.6](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.5...cli-v1.49.0-beta.6) (2025-09-25)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
### Features
|
|
79
|
+
|
|
80
|
+
* **blocklet:** add token and cost summary for tracing list ([#543](https://github.com/AIGNE-io/aigne-framework/issues/543)) ([5e78919](https://github.com/AIGNE-io/aigne-framework/commit/5e789199b8183cf9c48339ec8163faec001ca64c))
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
### Dependencies
|
|
84
|
+
|
|
85
|
+
* The following workspace dependencies were updated
|
|
86
|
+
* dependencies
|
|
87
|
+
* @aigne/agent-library bumped to 1.21.46-beta.6
|
|
88
|
+
* @aigne/agentic-memory bumped to 1.0.46-beta.6
|
|
89
|
+
* @aigne/aigne-hub bumped to 0.10.0-beta.6
|
|
90
|
+
* @aigne/core bumped to 1.61.0-beta.5
|
|
91
|
+
* @aigne/default-memory bumped to 1.2.9-beta.6
|
|
92
|
+
* @aigne/observability-api bumped to 0.11.0-beta
|
|
93
|
+
* @aigne/openai bumped to 0.16.0-beta.6
|
|
94
|
+
* devDependencies
|
|
95
|
+
* @aigne/test-utils bumped to 0.5.53-beta.5
|
|
96
|
+
|
|
97
|
+
## [1.49.0-beta.5](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.48.4-beta.5...cli-v1.49.0-beta.5) (2025-09-25)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
### Features
|
|
101
|
+
|
|
102
|
+
* **cli:** add new eval command for assessing AI agent performance using custom datasets ([#535](https://github.com/AIGNE-io/aigne-framework/issues/535)) ([9da967b](https://github.com/AIGNE-io/aigne-framework/commit/9da967b01ef9eeee4c5e1242934cf08e14815753))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
### Dependencies
|
|
106
|
+
|
|
107
|
+
* The following workspace dependencies were updated
|
|
108
|
+
* dependencies
|
|
109
|
+
* @aigne/agent-library bumped to 1.21.46-beta.5
|
|
110
|
+
* @aigne/agentic-memory bumped to 1.0.46-beta.5
|
|
111
|
+
* @aigne/aigne-hub bumped to 0.10.0-beta.5
|
|
112
|
+
* @aigne/core bumped to 1.61.0-beta.4
|
|
113
|
+
* @aigne/default-memory bumped to 1.2.9-beta.5
|
|
114
|
+
* @aigne/observability-api bumped to 0.10.5-beta
|
|
115
|
+
* @aigne/openai bumped to 0.16.0-beta.5
|
|
116
|
+
* devDependencies
|
|
117
|
+
* @aigne/test-utils bumped to 0.5.53-beta.4
|
|
118
|
+
|
|
3
119
|
## [1.48.4-beta.5](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.48.4-beta.4...cli-v1.48.4-beta.5) (2025-09-24)
|
|
4
120
|
|
|
5
121
|
|
package/dist/commands/aigne.js
CHANGED
|
@@ -4,6 +4,7 @@ import { asciiLogo } from "../utils/ascii-logo.js";
|
|
|
4
4
|
import { createAppCommands } from "./app.js";
|
|
5
5
|
import { createCreateCommand } from "./create.js";
|
|
6
6
|
import { createDeployCommands } from "./deploy.js";
|
|
7
|
+
import { createEvalCommand } from "./eval.js";
|
|
7
8
|
import { createHubCommand } from "./hub.js";
|
|
8
9
|
import { createObservabilityCommand } from "./observe.js";
|
|
9
10
|
import { createRunCommand } from "./run.js";
|
|
@@ -15,6 +16,7 @@ export function createAIGNECommand(options) {
|
|
|
15
16
|
.usage(`${asciiLogo}\n$0 <command> [options]`)
|
|
16
17
|
.version(AIGNE_CLI_VERSION)
|
|
17
18
|
.command(createRunCommand(options))
|
|
19
|
+
.command(createEvalCommand(options))
|
|
18
20
|
.command(createTestCommand(options))
|
|
19
21
|
.command(createCreateCommand())
|
|
20
22
|
.command(createServeMCPCommand(options))
|
package/dist/commands/app.d.ts
CHANGED
|
@@ -1,27 +1,41 @@
|
|
|
1
|
-
import type { Agent, AIGNE, Message } from "@aigne/core";
|
|
2
1
|
import type { CommandModule } from "yargs";
|
|
2
|
+
import { type AgentInChildProcess, type LoadAIGNEInChildProcessResult } from "../utils/workers/run-aigne-in-child-process.js";
|
|
3
3
|
import { type AgentRunCommonOptions } from "../utils/yargs.js";
|
|
4
4
|
export declare function createAppCommands(): CommandModule[];
|
|
5
5
|
export declare const agentCommandModule: ({ dir, agent, }: {
|
|
6
6
|
dir: string;
|
|
7
|
-
agent:
|
|
7
|
+
agent: AgentInChildProcess;
|
|
8
8
|
}) => CommandModule<unknown, AgentRunCommonOptions>;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
agent: string;
|
|
12
|
-
input: Message & AgentRunCommonOptions;
|
|
13
|
-
}): Promise<void>;
|
|
14
|
-
export declare function loadApplication({ name, dir, forceUpgrade, }: {
|
|
15
|
-
name: string;
|
|
16
|
-
dir?: string;
|
|
17
|
-
forceUpgrade?: boolean;
|
|
18
|
-
}): Promise<{
|
|
19
|
-
aigne: AIGNE;
|
|
9
|
+
interface LoadApplicationOptions {
|
|
10
|
+
packageName: string;
|
|
20
11
|
dir: string;
|
|
12
|
+
install?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface LoadApplicationResult {
|
|
15
|
+
aigne: LoadAIGNEInChildProcessResult;
|
|
21
16
|
version: string;
|
|
22
17
|
isCache?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function loadApplication(options: LoadApplicationOptions & {
|
|
20
|
+
install: true;
|
|
21
|
+
}): Promise<LoadApplicationResult>;
|
|
22
|
+
export declare function loadApplication(options: LoadApplicationOptions & {
|
|
23
|
+
install?: false;
|
|
24
|
+
}): Promise<LoadApplicationResult | null>;
|
|
25
|
+
export declare function installApp({ dir, packageName, beta, version, }: {
|
|
26
|
+
dir: string;
|
|
27
|
+
packageName: string;
|
|
28
|
+
beta?: boolean;
|
|
29
|
+
version?: string;
|
|
30
|
+
}): Promise<{
|
|
31
|
+
url: string;
|
|
32
|
+
version: string;
|
|
23
33
|
}>;
|
|
24
|
-
export declare function getNpmTgzInfo(name: string
|
|
34
|
+
export declare function getNpmTgzInfo(name: string, { version, beta }?: {
|
|
35
|
+
version?: string;
|
|
36
|
+
beta?: boolean;
|
|
37
|
+
}): Promise<{
|
|
25
38
|
version: string;
|
|
26
|
-
url:
|
|
39
|
+
url: string;
|
|
27
40
|
}>;
|
|
41
|
+
export {};
|
package/dist/commands/app.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
1
|
import { spawn } from "node:child_process";
|
|
3
2
|
import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
4
3
|
import { homedir } from "node:os";
|
|
5
4
|
import { join } from "node:path";
|
|
6
5
|
import { logger } from "@aigne/core/utils/logger.js";
|
|
6
|
+
import { jsonSchemaToZod } from "@aigne/json-schema-to-zod";
|
|
7
7
|
import { Listr, PRESET_TIMER } from "@aigne/listr2";
|
|
8
8
|
import { joinURL } from "ufo";
|
|
9
9
|
import { downloadAndExtract } from "../utils/download.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { safeLoadAIGNE } from "../utils/workers/load-aigne.js";
|
|
13
|
-
import { parseAgentInput, withAgentInputSchema, } from "../utils/yargs.js";
|
|
10
|
+
import { runAIGNEInChildProcess, } from "../utils/workers/run-aigne-in-child-process.js";
|
|
11
|
+
import { withAgentInputSchema } from "../utils/yargs.js";
|
|
14
12
|
import { serveMCPServerFromDir } from "./serve-mcp.js";
|
|
15
13
|
const NPM_PACKAGE_CACHE_TIME_MS = 1000 * 60 * 60 * 24; // 1 day
|
|
16
14
|
/**
|
|
@@ -23,11 +21,13 @@ function shouldUseBetaApps() {
|
|
|
23
21
|
const builtinApps = [
|
|
24
22
|
{
|
|
25
23
|
name: "doc-smith",
|
|
24
|
+
packageName: "@aigne/doc-smith",
|
|
26
25
|
describe: "Generate and maintain project docs — powered by agents.",
|
|
27
26
|
aliases: ["docsmith", "doc"],
|
|
28
27
|
},
|
|
29
28
|
{
|
|
30
29
|
name: "web-smith",
|
|
30
|
+
packageName: "@aigne/web-smith",
|
|
31
31
|
describe: "Generate and maintain project website pages — powered by agents.",
|
|
32
32
|
aliases: ["websmith", "web"],
|
|
33
33
|
},
|
|
@@ -38,30 +38,28 @@ export function createAppCommands() {
|
|
|
38
38
|
describe: app.describe,
|
|
39
39
|
aliases: app.aliases,
|
|
40
40
|
builder: async (yargs) => {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
yargs
|
|
45
|
-
.option("model", {
|
|
46
|
-
type: "string",
|
|
47
|
-
description: "Model to use for the application, example: openai:gpt-4.1 or google:gemini-2.5-flash",
|
|
48
|
-
})
|
|
49
|
-
.command(serveMcpCommandModule({ name: app.name, dir }))
|
|
50
|
-
.command(upgradeCommandModule({
|
|
51
|
-
name: app.name,
|
|
41
|
+
const dir = join(homedir(), ".aigne", "registry.npmjs.org", app.packageName);
|
|
42
|
+
const { aigne, version } = await loadApplication({
|
|
52
43
|
dir,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
})
|
|
56
|
-
if (aigne.cli
|
|
44
|
+
packageName: app.packageName,
|
|
45
|
+
install: true,
|
|
46
|
+
});
|
|
47
|
+
if (aigne.cli?.chat) {
|
|
57
48
|
yargs.command({
|
|
58
49
|
...agentCommandModule({ dir, agent: aigne.cli.chat }),
|
|
59
50
|
command: "$0",
|
|
60
51
|
});
|
|
61
52
|
}
|
|
62
|
-
for (const agent of aigne.cli
|
|
53
|
+
for (const agent of aigne.cli?.agents ?? []) {
|
|
63
54
|
yargs.command(agentCommandModule({ dir, agent }));
|
|
64
55
|
}
|
|
56
|
+
yargs
|
|
57
|
+
.option("model", {
|
|
58
|
+
type: "string",
|
|
59
|
+
description: "Model to use for the application, example: openai:gpt-4.1 or google:gemini-2.5-flash",
|
|
60
|
+
})
|
|
61
|
+
.command(serveMcpCommandModule({ name: app.name, dir }))
|
|
62
|
+
.command(upgradeCommandModule({ packageName: app.packageName, dir }));
|
|
65
63
|
yargs.version(`${app.name} v${version}`).alias("version", "v");
|
|
66
64
|
return yargs.demandCommand();
|
|
67
65
|
},
|
|
@@ -92,18 +90,39 @@ const serveMcpCommandModule = ({ name, dir, }) => ({
|
|
|
92
90
|
await serveMCPServerFromDir({ ...options, dir });
|
|
93
91
|
},
|
|
94
92
|
});
|
|
95
|
-
const upgradeCommandModule = ({
|
|
93
|
+
const upgradeCommandModule = ({ packageName, dir, }) => ({
|
|
96
94
|
command: "upgrade",
|
|
97
|
-
describe: `Upgrade ${
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
95
|
+
describe: `Upgrade ${packageName} to the latest version`,
|
|
96
|
+
builder: (argv) => {
|
|
97
|
+
return argv
|
|
98
|
+
.option("beta", {
|
|
99
|
+
type: "boolean",
|
|
100
|
+
describe: "Use beta versions if available",
|
|
101
|
+
})
|
|
102
|
+
.option("target-version", {
|
|
103
|
+
type: "string",
|
|
104
|
+
describe: "Specify a version to upgrade to (default is latest)",
|
|
105
|
+
alias: ["to", "target"],
|
|
106
|
+
})
|
|
107
|
+
.option("force", {
|
|
108
|
+
type: "boolean",
|
|
109
|
+
describe: "Force upgrade even if already at latest version",
|
|
110
|
+
default: false,
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
handler: async ({ beta, targetVersion, force }) => {
|
|
114
|
+
beta ??= shouldUseBetaApps();
|
|
115
|
+
let app = await loadApplication({ packageName, dir });
|
|
116
|
+
const npm = await getNpmTgzInfo(packageName, { beta, version: targetVersion });
|
|
117
|
+
if (!app || force || npm.version !== app.version) {
|
|
118
|
+
if (force)
|
|
119
|
+
await rm(dir, { force: true, recursive: true });
|
|
120
|
+
await installApp({ packageName, dir, beta, version: targetVersion });
|
|
121
|
+
app = await loadApplication({ dir, packageName, install: true });
|
|
122
|
+
console.log(`\n✅ Upgraded ${packageName} to version ${app.version}`);
|
|
123
|
+
return;
|
|
105
124
|
}
|
|
106
|
-
console.log(`\n✅ ${
|
|
125
|
+
console.log(`\n✅ ${packageName} is already at the latest version (${app.version})`);
|
|
107
126
|
},
|
|
108
127
|
});
|
|
109
128
|
export const agentCommandModule = ({ dir, agent, }) => {
|
|
@@ -111,76 +130,76 @@ export const agentCommandModule = ({ dir, agent, }) => {
|
|
|
111
130
|
command: agent.name,
|
|
112
131
|
aliases: agent.alias || [],
|
|
113
132
|
describe: agent.description || "",
|
|
114
|
-
builder: async (yargs) =>
|
|
133
|
+
builder: async (yargs) => {
|
|
134
|
+
return withAgentInputSchema(yargs, { inputSchema: jsonSchemaToZod(agent.inputSchema) });
|
|
135
|
+
},
|
|
115
136
|
handler: async (options) => {
|
|
116
137
|
if (options.logLevel)
|
|
117
138
|
logger.level = options.logLevel;
|
|
118
|
-
await invokeCLIAgentFromDir
|
|
139
|
+
await runAIGNEInChildProcess("invokeCLIAgentFromDir", {
|
|
140
|
+
dir,
|
|
141
|
+
agent: agent.name,
|
|
142
|
+
input: options,
|
|
143
|
+
});
|
|
119
144
|
process.exit(0);
|
|
120
145
|
},
|
|
121
146
|
};
|
|
122
147
|
};
|
|
123
|
-
export async function
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const { chat } = aigne.cli;
|
|
130
|
-
const agent = chat && chat.name === options.agent
|
|
131
|
-
? chat
|
|
132
|
-
: aigne.cli.agents[options.agent] ||
|
|
133
|
-
aigne.agents[options.agent] ||
|
|
134
|
-
aigne.skills[options.agent] ||
|
|
135
|
-
aigne.mcpServer.agents[options.agent];
|
|
136
|
-
assert(agent, `Agent ${options.agent} not found in ${options.dir}`);
|
|
137
|
-
const input = await parseAgentInput(options.input, agent);
|
|
138
|
-
await runAgentWithAIGNE(aigne, agent, {
|
|
139
|
-
...options.input,
|
|
140
|
-
input,
|
|
141
|
-
chat: agent === chat || options.input.chat,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
finally {
|
|
145
|
-
await aigne.shutdown();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
export async function loadApplication({ name, dir, forceUpgrade = false, }) {
|
|
149
|
-
name = `@aigne/${name}`;
|
|
150
|
-
dir ??= join(homedir(), ".aigne", "registry.npmjs.org", name);
|
|
151
|
-
let check = forceUpgrade ? undefined : await isInstallationAvailable(dir);
|
|
152
|
-
if (check?.available) {
|
|
153
|
-
const aigne = await safeLoadAIGNE(dir).catch((error) => {
|
|
154
|
-
console.warn(`⚠️ Failed to load ${name}, trying to reinstall:`, error.message);
|
|
148
|
+
export async function loadApplication(options) {
|
|
149
|
+
const { dir, packageName } = options;
|
|
150
|
+
const check = await checkInstallation(dir);
|
|
151
|
+
if (check && !check.expired) {
|
|
152
|
+
const aigne = await runAIGNEInChildProcess("loadAIGNE", dir).catch((error) => {
|
|
153
|
+
console.warn(`⚠️ Failed to load ${packageName}, trying to reinstall:`, error.message);
|
|
155
154
|
});
|
|
156
155
|
if (aigne) {
|
|
157
|
-
return {
|
|
158
|
-
aigne,
|
|
159
|
-
dir,
|
|
160
|
-
version: check.version,
|
|
161
|
-
isCache: true,
|
|
162
|
-
};
|
|
156
|
+
return { aigne, version: check.version, isCache: true };
|
|
163
157
|
}
|
|
164
|
-
check = undefined;
|
|
165
158
|
}
|
|
166
|
-
|
|
159
|
+
if (!options.install)
|
|
160
|
+
return null;
|
|
161
|
+
const result = await installApp({ dir, packageName, beta: check?.version?.includes("beta") });
|
|
162
|
+
return {
|
|
163
|
+
aigne: await runAIGNEInChildProcess("loadAIGNE", dir),
|
|
164
|
+
version: result.version,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
async function readInstallationMetadata(dir) {
|
|
168
|
+
return safeParseJSON(await readFile(join(dir, ".aigne-cli.json"), "utf-8").catch(() => "{}"));
|
|
169
|
+
}
|
|
170
|
+
async function writeInstallationMetadata(dir, metadata) {
|
|
171
|
+
await writeFile(join(dir, ".aigne-cli.json"), JSON.stringify(metadata, null, 2));
|
|
172
|
+
}
|
|
173
|
+
async function checkInstallation(dir, { cacheTimeMs = NPM_PACKAGE_CACHE_TIME_MS } = {}) {
|
|
174
|
+
const s = await stat(join(dir, "package.json")).catch(() => null);
|
|
175
|
+
if (!s)
|
|
176
|
+
return null;
|
|
177
|
+
const version = safeParseJSON(await readFile(join(dir, "package.json"), "utf-8"))?.version;
|
|
178
|
+
if (!version)
|
|
179
|
+
return null;
|
|
180
|
+
const installedAt = (await readInstallationMetadata(dir))?.installedAt;
|
|
181
|
+
if (!installedAt)
|
|
182
|
+
return null;
|
|
183
|
+
const now = Date.now();
|
|
184
|
+
const expired = now - installedAt > cacheTimeMs;
|
|
185
|
+
return { version, expired };
|
|
186
|
+
}
|
|
187
|
+
export async function installApp({ dir, packageName, beta, version, }) {
|
|
188
|
+
return await new Listr([
|
|
167
189
|
{
|
|
168
|
-
title: `Fetching ${
|
|
190
|
+
title: `Fetching ${packageName} metadata`,
|
|
169
191
|
task: async (ctx, task) => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const useBeta = shouldUseBetaApps();
|
|
173
|
-
if (useBeta && ctx.version.includes("beta")) {
|
|
174
|
-
task.title = `Fetching ${name} metadata (using beta version)`;
|
|
192
|
+
if (beta) {
|
|
193
|
+
task.title = `Fetching ${packageName} metadata (using beta version)`;
|
|
175
194
|
}
|
|
195
|
+
const info = await getNpmTgzInfo(packageName, { beta, version });
|
|
196
|
+
Object.assign(ctx, info);
|
|
176
197
|
},
|
|
177
198
|
},
|
|
178
199
|
{
|
|
179
|
-
title: `Downloading ${
|
|
180
|
-
skip: (ctx) => ctx.version === check?.version,
|
|
200
|
+
title: `Downloading ${packageName}`,
|
|
181
201
|
task: async (ctx, task) => {
|
|
182
|
-
task.title = `Downloading ${
|
|
183
|
-
await rm(dir, { force: true, recursive: true });
|
|
202
|
+
task.title = `Downloading ${packageName} (v${ctx.version})`;
|
|
184
203
|
await mkdir(dir, { recursive: true });
|
|
185
204
|
await downloadAndExtract(ctx.url, dir, { strip: 1 });
|
|
186
205
|
},
|
|
@@ -195,6 +214,7 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
|
|
|
195
214
|
task.output = last;
|
|
196
215
|
},
|
|
197
216
|
});
|
|
217
|
+
await writeInstallationMetadata(dir, { installedAt: Date.now() });
|
|
198
218
|
},
|
|
199
219
|
},
|
|
200
220
|
], {
|
|
@@ -204,25 +224,6 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
|
|
|
204
224
|
timer: PRESET_TIMER,
|
|
205
225
|
},
|
|
206
226
|
}).run();
|
|
207
|
-
return {
|
|
208
|
-
aigne: await safeLoadAIGNE(dir),
|
|
209
|
-
dir,
|
|
210
|
-
version: result.version,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
async function isInstallationAvailable(dir, { cacheTimeMs = NPM_PACKAGE_CACHE_TIME_MS } = {}) {
|
|
214
|
-
const s = await stat(join(dir, "package.json")).catch(() => null);
|
|
215
|
-
if (!s)
|
|
216
|
-
return null;
|
|
217
|
-
const version = safeParseJSON(await readFile(join(dir, "package.json"), "utf-8"))?.version;
|
|
218
|
-
if (!version)
|
|
219
|
-
return null;
|
|
220
|
-
const installedAt = safeParseJSON(await readFile(join(dir, ".aigne-cli.json"), "utf-8").catch(() => "{}"))?.installedAt;
|
|
221
|
-
if (!installedAt)
|
|
222
|
-
return null;
|
|
223
|
-
const now = Date.now();
|
|
224
|
-
const available = installedAt ? now - installedAt < cacheTimeMs : false;
|
|
225
|
-
return { version, available };
|
|
226
227
|
}
|
|
227
228
|
async function installDependencies(dir, { log } = {}) {
|
|
228
229
|
await new Promise((resolve, reject) => {
|
|
@@ -250,16 +251,20 @@ async function installDependencies(dir, { log } = {}) {
|
|
|
250
251
|
}
|
|
251
252
|
});
|
|
252
253
|
});
|
|
253
|
-
await writeFile(join(dir, ".aigne-cli.json"), JSON.stringify({ installedAt: Date.now() }, null, 2));
|
|
254
254
|
}
|
|
255
|
-
export async function getNpmTgzInfo(name) {
|
|
255
|
+
export async function getNpmTgzInfo(name, { version, beta } = {}) {
|
|
256
256
|
const res = await fetch(joinURL("https://registry.npmjs.org", name));
|
|
257
257
|
if (!res.ok)
|
|
258
258
|
throw new Error(`Failed to fetch package info for ${name}: ${res.statusText}`);
|
|
259
259
|
const data = await res.json();
|
|
260
|
-
const useBeta = shouldUseBetaApps();
|
|
261
260
|
let targetVersion;
|
|
262
|
-
if (
|
|
261
|
+
if (version) {
|
|
262
|
+
if (!data.versions[version]) {
|
|
263
|
+
throw new Error(`Version ${version} of package ${name} not found`);
|
|
264
|
+
}
|
|
265
|
+
targetVersion = version;
|
|
266
|
+
}
|
|
267
|
+
else if (beta && data["dist-tags"].beta) {
|
|
263
268
|
// Use beta version if available and beta flag is set
|
|
264
269
|
targetVersion = data["dist-tags"].beta;
|
|
265
270
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CommandModule } from "yargs";
|
|
2
|
+
export declare function createEvalCommand({ aigneFilePath, }?: {
|
|
3
|
+
aigneFilePath?: string;
|
|
4
|
+
}): CommandModule<unknown, {
|
|
5
|
+
path?: string;
|
|
6
|
+
agent?: string;
|
|
7
|
+
dataset?: string;
|
|
8
|
+
evaluator?: string;
|
|
9
|
+
concurrency?: number;
|
|
10
|
+
output?: string;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from "node:path";
|
|
2
|
+
import { exists } from "@aigne/agent-library/utils/fs.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { runEvaluationPipeline } from "../utils/evaluation/core.js";
|
|
5
|
+
import { FileDataset } from "../utils/evaluation/dataset.js";
|
|
6
|
+
import { LLMEvaluator } from "../utils/evaluation/evaluator.js";
|
|
7
|
+
import { ConsoleReporter, CsvReporter } from "../utils/evaluation/reporter.js";
|
|
8
|
+
import { DefaultRunnerWithConcurrency } from "../utils/evaluation/runner.js";
|
|
9
|
+
import { loadAIGNE } from "../utils/load-aigne.js";
|
|
10
|
+
const schema = z.object({
|
|
11
|
+
path: z.string().optional(),
|
|
12
|
+
agent: z.string(),
|
|
13
|
+
dataset: z.string(),
|
|
14
|
+
evaluator: z.string().optional(),
|
|
15
|
+
concurrency: z.number().optional(),
|
|
16
|
+
output: z.string().optional(),
|
|
17
|
+
});
|
|
18
|
+
const getResolvePath = (path) => {
|
|
19
|
+
return isAbsolute(path) ? path : resolve(process.cwd(), path);
|
|
20
|
+
};
|
|
21
|
+
export function createEvalCommand({ aigneFilePath, } = {}) {
|
|
22
|
+
return {
|
|
23
|
+
command: "eval [path] [agent]",
|
|
24
|
+
describe: "Evaluate AIGNE for the specified path",
|
|
25
|
+
builder: async (yargs) => {
|
|
26
|
+
return yargs
|
|
27
|
+
.positional("path", {
|
|
28
|
+
type: "string",
|
|
29
|
+
describe: "Path to the agents directory or URL to an aigne project",
|
|
30
|
+
default: ".",
|
|
31
|
+
})
|
|
32
|
+
.positional("agent", {
|
|
33
|
+
type: "string",
|
|
34
|
+
describe: "Name of the agent to evaluate",
|
|
35
|
+
})
|
|
36
|
+
.positional("dataset", {
|
|
37
|
+
type: "string",
|
|
38
|
+
describe: "Path to the dataset file",
|
|
39
|
+
})
|
|
40
|
+
.positional("evaluator", {
|
|
41
|
+
type: "string",
|
|
42
|
+
describe: "Name of the evaluator to use",
|
|
43
|
+
})
|
|
44
|
+
.positional("output", {
|
|
45
|
+
alias: "o",
|
|
46
|
+
type: "string",
|
|
47
|
+
describe: "Path to the output file",
|
|
48
|
+
})
|
|
49
|
+
.positional("concurrency", {
|
|
50
|
+
type: "number",
|
|
51
|
+
describe: "Concurrency level",
|
|
52
|
+
default: 1,
|
|
53
|
+
})
|
|
54
|
+
.help(false)
|
|
55
|
+
.version(false)
|
|
56
|
+
.strict(false);
|
|
57
|
+
},
|
|
58
|
+
handler: async (options) => {
|
|
59
|
+
const parsedOptions = await schema.safeParseAsync(options);
|
|
60
|
+
if (!parsedOptions.success) {
|
|
61
|
+
throw new Error(`Invalid options: ${JSON.stringify(parsedOptions.error.format())}`);
|
|
62
|
+
}
|
|
63
|
+
const { agent: entryAgent, dataset: datasetPath, evaluator: evaluatorName, concurrency, } = parsedOptions.data;
|
|
64
|
+
const path = parsedOptions.data?.path;
|
|
65
|
+
const aigne = await loadAIGNE({ path: aigneFilePath || path || "." });
|
|
66
|
+
const resolvedDatasetPath = getResolvePath(datasetPath);
|
|
67
|
+
if (!(await exists(resolvedDatasetPath))) {
|
|
68
|
+
throw new Error("Dataset file does not exist");
|
|
69
|
+
}
|
|
70
|
+
const { chat } = aigne.cli;
|
|
71
|
+
const agent = chat && chat.name === entryAgent
|
|
72
|
+
? chat
|
|
73
|
+
: aigne.cli.agents[entryAgent] ||
|
|
74
|
+
aigne.agents[entryAgent] ||
|
|
75
|
+
aigne.skills[entryAgent] ||
|
|
76
|
+
aigne.mcpServer.agents[entryAgent];
|
|
77
|
+
if (!agent)
|
|
78
|
+
throw new Error("Entry agent does not exist");
|
|
79
|
+
agent.model = agent.model ?? aigne.model;
|
|
80
|
+
let evaluatorAgent;
|
|
81
|
+
if (evaluatorName) {
|
|
82
|
+
evaluatorAgent =
|
|
83
|
+
aigne.cli.agents[evaluatorName] ||
|
|
84
|
+
aigne.agents[evaluatorName] ||
|
|
85
|
+
aigne.skills[evaluatorName] ||
|
|
86
|
+
aigne.mcpServer.agents[evaluatorName];
|
|
87
|
+
}
|
|
88
|
+
if (evaluatorAgent) {
|
|
89
|
+
evaluatorAgent.model = evaluatorAgent.model ?? aigne.model;
|
|
90
|
+
}
|
|
91
|
+
const dataset = new FileDataset(resolvedDatasetPath);
|
|
92
|
+
const runner = new DefaultRunnerWithConcurrency(agent, aigne);
|
|
93
|
+
const evaluator = new LLMEvaluator(aigne, evaluatorAgent);
|
|
94
|
+
const reporters = [new ConsoleReporter()];
|
|
95
|
+
if (options.output) {
|
|
96
|
+
const resolvedReporterPath = getResolvePath(options.output);
|
|
97
|
+
const reporter = new CsvReporter(resolvedReporterPath);
|
|
98
|
+
reporters.push(reporter);
|
|
99
|
+
}
|
|
100
|
+
await runEvaluationPipeline({
|
|
101
|
+
dataset,
|
|
102
|
+
runner,
|
|
103
|
+
evaluators: [evaluator],
|
|
104
|
+
reporters: reporters,
|
|
105
|
+
options: { concurrency },
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
package/dist/commands/run.js
CHANGED
|
@@ -10,6 +10,7 @@ import { isV1Package, toAIGNEPackage } from "../utils/agent-v1.js";
|
|
|
10
10
|
import { downloadAndExtract } from "../utils/download.js";
|
|
11
11
|
import { loadAIGNE } from "../utils/load-aigne.js";
|
|
12
12
|
import { isUrl } from "../utils/url.js";
|
|
13
|
+
import { serializeAgent } from "../utils/workers/run-aigne-in-child-process.js";
|
|
13
14
|
import { agentCommandModule } from "./app.js";
|
|
14
15
|
export function createRunCommand({ aigneFilePath, } = {}) {
|
|
15
16
|
return {
|
|
@@ -41,14 +42,14 @@ export function createRunCommand({ aigneFilePath, } = {}) {
|
|
|
41
42
|
const subYargs = yargs().scriptName("").usage("aigne run <path> <agent> [...options]");
|
|
42
43
|
if (aigne.cli.chat) {
|
|
43
44
|
subYargs.command({
|
|
44
|
-
...agentCommandModule({ dir: path, agent: aigne.cli.chat }),
|
|
45
|
+
...agentCommandModule({ dir: path, agent: serializeAgent(aigne.cli.chat) }),
|
|
45
46
|
command: "$0",
|
|
46
47
|
});
|
|
47
48
|
}
|
|
48
49
|
// Allow user to run all of agents in the AIGNE instances
|
|
49
50
|
const allAgents = flat(aigne.cli.agents, aigne.agents, aigne.skills, aigne.cli.chat, aigne.mcpServer.agents);
|
|
50
51
|
for (const agent of allAgents) {
|
|
51
|
-
subYargs.command(agentCommandModule({ dir: path, agent }));
|
|
52
|
+
subYargs.command(agentCommandModule({ dir: path, agent: serializeAgent(agent) }));
|
|
52
53
|
}
|
|
53
54
|
const argv = process.argv.slice(aigneFilePath ? 3 : 2);
|
|
54
55
|
if (argv[0] === "run")
|
|
@@ -102,7 +103,7 @@ async function loadApplication(path) {
|
|
|
102
103
|
}
|
|
103
104
|
// Load env files in the aigne directory
|
|
104
105
|
config({ path: dir, silent: true });
|
|
105
|
-
const aigne = await loadAIGNE({ path: dir });
|
|
106
|
+
const aigne = await loadAIGNE({ path: dir, printTips: false });
|
|
106
107
|
return { aigne, path: dir };
|
|
107
108
|
}
|
|
108
109
|
async function downloadPackage(url, cacheDir) {
|