@agentfare/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @agentfare/cli
2
+
3
+ AgentFare 命令行工具。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install -g @agentfare/cli
9
+ # 或
10
+ pnpm add -g @agentfare/cli
11
+ ```
12
+
13
+ ## 命令
14
+
15
+ ### `agentfare init`
16
+
17
+ 检测已安装的 CLI 工具(Claude、Codex)并配置环境。
18
+
19
+ ### `agentfare cost`
20
+
21
+ 查看成本报告。
22
+
23
+ ```bash
24
+ agentfare cost # 最近 30 天
25
+ agentfare cost --last 7d # 最近 7 天
26
+ agentfare cost --json # JSON 输出
27
+ ```
28
+
29
+ ### `agentfare config`
30
+
31
+ 管理配置项。
32
+
33
+ ```bash
34
+ agentfare config set routing.strategy tiered
35
+ agentfare config get routing.strategy
36
+ ```
37
+
38
+ ### `agentfare models`
39
+
40
+ 模型管理。
41
+
42
+ ```bash
43
+ agentfare models list # 列出所有模型
44
+ agentfare models list --provider openai # 按 provider 过滤
45
+ agentfare models update # 拉取最新模型数据
46
+ ```
47
+
48
+ ### `agentfare optimize`
49
+
50
+ 运行路由优化。
51
+
52
+ ## License
53
+
54
+ MIT
@@ -0,0 +1,4 @@
1
+ import { Command } from "commander";
2
+ export declare const configCommand: Command;
3
+ export declare function setNestedValue(obj: Record<string, unknown>, key: string, value: string): void;
4
+ //# sourceMappingURL=config-cmd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-cmd.d.ts","sourceRoot":"","sources":["../../src/commands/config-cmd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,aAAa,SAEzB,CAAC;AAqCF,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,IAAI,CAiBN"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.configCommand = void 0;
37
+ exports.setNestedValue = setNestedValue;
38
+ const commander_1 = require("commander");
39
+ const fs = __importStar(require("node:fs"));
40
+ const path = __importStar(require("node:path"));
41
+ const os = __importStar(require("node:os"));
42
+ exports.configCommand = new commander_1.Command("config").description("管理配置");
43
+ exports.configCommand
44
+ .command("set <key> <value>")
45
+ .description("设置配置项")
46
+ .action((key, value) => {
47
+ const configPath = path.join(os.homedir(), ".agentfare", "config.json");
48
+ let config = {};
49
+ if (fs.existsSync(configPath))
50
+ config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
51
+ setNestedValue(config, key, value);
52
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
53
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
54
+ console.log(`set ${key}`);
55
+ });
56
+ exports.configCommand
57
+ .command("get <key>")
58
+ .description("查看配置项")
59
+ .action((key) => {
60
+ const configPath = path.join(os.homedir(), ".agentfare", "config.json");
61
+ if (!fs.existsSync(configPath)) {
62
+ console.log("config file not found");
63
+ return;
64
+ }
65
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
66
+ const value = key
67
+ .split(".")
68
+ .reduce((o, k) => o?.[k], config);
69
+ console.log(value !== undefined ? JSON.stringify(value) : "not found");
70
+ });
71
+ // ISSUE-054: exported for testing — validates and sets a nested config value.
72
+ function setNestedValue(obj, key, value) {
73
+ const UNSAFE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
74
+ const SAFE_KEY = /^[a-zA-Z0-9_-]+$/;
75
+ const parts = key.split(".");
76
+ if (parts.some(p => UNSAFE_KEYS.has(p) || !SAFE_KEY.test(p))) {
77
+ throw new Error(`Invalid config key: ${key} (each segment must match ${SAFE_KEY.source})`);
78
+ }
79
+ let current = obj;
80
+ for (let i = 0; i < parts.length - 1; i++) {
81
+ if (!current[parts[i]])
82
+ current[parts[i]] = {};
83
+ current = current[parts[i]];
84
+ }
85
+ try {
86
+ current[parts[parts.length - 1]] = JSON.parse(value);
87
+ }
88
+ catch {
89
+ current[parts[parts.length - 1]] = value;
90
+ }
91
+ }
92
+ //# sourceMappingURL=config-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-cmd.js","sourceRoot":"","sources":["../../src/commands/config-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const costCommand: Command;
3
+ //# sourceMappingURL=cost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/commands/cost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,WAAW,SAsCpB,CAAC"}
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.costCommand = void 0;
37
+ const commander_1 = require("commander");
38
+ const core_1 = require("@agentfare/core");
39
+ const path = __importStar(require("node:path"));
40
+ const os = __importStar(require("node:os"));
41
+ exports.costCommand = new commander_1.Command("cost")
42
+ .description("查看成本报告")
43
+ .option("--last <period>", "时间范围 (1d, 7d, 30d)", "30d")
44
+ .option("--json", "JSON 格式输出", false)
45
+ .action((opts) => {
46
+ const dbPath = path.join(os.homedir(), ".agentfare", "data.db");
47
+ let db;
48
+ try {
49
+ db = new core_1.TrackingDatabase(dbPath);
50
+ const summary = db.getCostSummary(opts.last);
51
+ const pct = summary.totalOriginalCost > 0
52
+ ? ((summary.totalSavings / summary.totalOriginalCost) * 100).toFixed(1)
53
+ : "0.0";
54
+ if (opts.json) {
55
+ console.log(JSON.stringify(summary, null, 2));
56
+ }
57
+ else {
58
+ console.log(`\n AgentFare Cost Report`);
59
+ console.log(` ${"─".repeat(40)}`);
60
+ console.log(` Total requests: ${summary.totalRequests}`);
61
+ console.log(` Original cost: $${summary.totalOriginalCost.toFixed(2)}`);
62
+ console.log(` Actual cost: $${summary.totalActualCost.toFixed(2)}`);
63
+ console.log(` Savings: $${summary.totalSavings.toFixed(2)} (${pct}%)\n`);
64
+ }
65
+ }
66
+ catch (err) {
67
+ console.error(`无法打开数据库: ${err.message}`);
68
+ process.exit(1);
69
+ }
70
+ finally {
71
+ db?.close?.();
72
+ }
73
+ });
74
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/commands/cost.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,0CAAmD;AACnD,gDAAkC;AAClC,4CAA8B;AAEjB,QAAA,WAAW,GAAG,IAAI,mBAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,QAAQ,CAAC;KACrB,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,KAAK,CAAC;KACtD,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC;KACpC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IACf,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;IAChE,IAAI,EAAgC,CAAC;IACrC,IAAI,CAAC;QACH,EAAE,GAAG,IAAI,uBAAgB,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,GAAG,GACP,OAAO,CAAC,iBAAiB,GAAG,CAAC;YAC3B,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAChE,CAAC,CACF;YACH,CAAC,CAAC,KAAK,CAAC;QACZ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,wBAAwB,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;YAC7D,OAAO,CAAC,GAAG,CACT,yBAAyB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAChE,CAAC;YACF,OAAO,CAAC,GAAG,CACT,yBAAyB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAC9D,CAAC;YACF,OAAO,CAAC,GAAG,CACT,yBAAyB,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CACvE,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,YAAa,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;YAAS,CAAC;QACT,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;IAChB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const initCommand: Command;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,eAAO,MAAM,WAAW,SA+BpB,CAAC"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ exports.initCommand = new commander_1.Command("init")
6
+ .description("初始化 AgentFare")
7
+ .option("--tool <tool>", "只配置指定工具")
8
+ .action(async (opts) => {
9
+ // ISSUE-049: merged two dynamic imports into one
10
+ const { detectTools, generateShellFunctions, writeShellConfig } = await import("@agentfare/setup");
11
+ // ISSUE-031: ensure loader.js is generated
12
+ const { ensureLoaderScript } = await import("@agentfare/loader");
13
+ let tools = detectTools();
14
+ if (opts.tool) {
15
+ tools = tools.filter((t) => t.name === opts.tool || t.name === opts.tool.replace("claude-code", "claude"));
16
+ }
17
+ if (tools.length === 0) {
18
+ console.error("未检测到指定工具");
19
+ process.exit(1);
20
+ }
21
+ // Generate loader.js before writing shell config
22
+ const loaderPath = ensureLoaderScript();
23
+ console.log(`loader script generated: ${loaderPath}`);
24
+ const content = generateShellFunctions(tools);
25
+ const rcPath = writeShellConfig(content);
26
+ console.log(`已配置 ${tools.map((t) => t.name).join(", ")} -> ${rcPath}`);
27
+ console.log(`请运行 source ${rcPath} 或重新打开终端。`);
28
+ });
29
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AAEvB,QAAA,WAAW,GAAG,IAAI,mBAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,eAAe,CAAC;KAC5B,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,iDAAiD;IACjD,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACnG,2CAA2C;IAC3C,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAEjE,IAAI,KAAK,GAA4B,WAAW,EAAE,CAAC;IACnD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,KAAK,GAAG,KAAK,CAAC,MAAM,CAClB,CAAC,CAAmB,EAAE,EAAE,CACtB,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,CAChF,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,iDAAiD;IACjD,MAAM,UAAU,GAAG,kBAAkB,EAAE,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAC;IAEtD,MAAM,OAAO,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CACT,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,MAAM,EAAE,CAC5E,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,WAAW,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const modelsCommand: Command;
3
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,aAAa,SAEzB,CAAC"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.modelsCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const models_1 = require("@agentfare/models");
6
+ exports.modelsCommand = new commander_1.Command("models").description("模型管理");
7
+ exports.modelsCommand
8
+ .command("list")
9
+ .description("列出所有可用模型")
10
+ .option("--provider <provider>", "按 provider 过滤")
11
+ .option("--tier <tier>", "按 tier 过滤")
12
+ .action((opts) => {
13
+ const registry = new models_1.ModelRegistry();
14
+ let models = registry.getAll();
15
+ if (opts.provider)
16
+ models = models.filter((m) => m.provider === opts.provider);
17
+ if (opts.tier)
18
+ models = models.filter((m) => m.tier === opts.tier);
19
+ for (const m of models) {
20
+ console.log(`${m.id.padEnd(35)} tier=${m.tier.padEnd(10)} in=$${m.pricing.inputPerMillion}/MTok out=$${m.pricing.outputPerMillion}/MTok`);
21
+ }
22
+ });
23
+ exports.modelsCommand
24
+ .command("update")
25
+ .description("手动拉取最新模型数据")
26
+ .action(async () => {
27
+ try {
28
+ const remote = await (0, models_1.fetchRemoteModels)();
29
+ if (remote.length === 0) {
30
+ console.log("没有可用的远程模型更新");
31
+ return;
32
+ }
33
+ const merged = (0, models_1.mergeRemoteModels)(models_1.BUILTIN_MODELS, remote);
34
+ (0, models_1.saveRemoteModels)(merged);
35
+ console.log(`更新完成: ${remote.length} 个模型已更新`);
36
+ }
37
+ catch (err) {
38
+ console.error(`远程更新失败: ${err.message}`);
39
+ process.exit(1);
40
+ }
41
+ });
42
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,8CAA0H;AAE7G,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAC5D,MAAM,CACP,CAAC;AAEF,qBAAa;KACV,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,UAAU,CAAC;KACvB,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;KAChD,MAAM,CAAC,eAAe,EAAE,WAAW,CAAC;KACpC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IACf,MAAM,QAAQ,GAAG,IAAI,sBAAa,EAAE,CAAC;IACrC,IAAI,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC/B,IAAI,IAAI,CAAC,QAAQ;QACf,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9D,IAAI,IAAI,CAAC,IAAI;QAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;IACnE,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,eAAe,eAAe,CAAC,CAAC,OAAO,CAAC,gBAAgB,OAAO,CAC9H,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,qBAAa;KACV,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,YAAY,CAAC;KACzB,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAiB,GAAE,CAAC;QACzC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC3B,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,IAAA,0BAAiB,EAAC,uBAAc,EAAE,MAAM,CAAC,CAAC;QACzD,IAAA,yBAAgB,EAAC,MAAM,CAAC,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,WAAY,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const optimizeCommand: Command;
3
+ //# sourceMappingURL=optimize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimize.d.ts","sourceRoot":"","sources":["../../src/commands/optimize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,eAAe,SAsExB,CAAC"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.optimizeCommand = void 0;
37
+ const commander_1 = require("commander");
38
+ const core_1 = require("@agentfare/core");
39
+ const models_1 = require("@agentfare/models");
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ exports.optimizeCommand = new commander_1.Command("optimize")
43
+ .description("基于历史数据自动搜索最优模型组合")
44
+ .option("--pipeline <file>", "指定 pipeline 定义文件 (YAML)")
45
+ .option("--algorithm <algo>", "搜索算法 (brute_force | epsilon_lucb | arm_elimination | hill_climbing)", "epsilon_lucb")
46
+ .option("--max-evals <n>", "最大评估次数", "50")
47
+ .action(async (opts) => {
48
+ if (!opts.pipeline) {
49
+ console.error("请指定 pipeline 文件:--pipeline ./my-pipeline.yaml");
50
+ process.exit(1);
51
+ }
52
+ const yaml = fs.readFileSync(opts.pipeline, "utf-8");
53
+ const pipeline = (0, core_1.parsePipelineYAML)(yaml);
54
+ const registry = new models_1.ModelRegistry();
55
+ const costFn = (combo) => Object.values(combo).reduce((sum, m) => {
56
+ const entry = registry.get(m);
57
+ if (!entry)
58
+ return sum + 10;
59
+ return sum + entry.pricing.inputPerMillion + entry.pricing.outputPerMillion;
60
+ }, 0);
61
+ let results;
62
+ switch (opts.algorithm) {
63
+ case "brute_force":
64
+ results = (0, core_1.bruteForceSearch)(pipeline, costFn);
65
+ break;
66
+ case "arm_elimination":
67
+ results = (0, core_1.armEliminationSearch)(pipeline, costFn);
68
+ break;
69
+ case "hill_climbing":
70
+ results = (0, core_1.hillClimbingSearch)(pipeline, costFn);
71
+ break;
72
+ case "epsilon_lucb":
73
+ default:
74
+ results = (0, core_1.epsilonLucbSearch)(pipeline, costFn);
75
+ break;
76
+ }
77
+ console.log(`\n优化结果 (${pipeline.name})`);
78
+ console.log(`${"─".repeat(50)}`);
79
+ for (const combo of results.slice(0, 5)) {
80
+ console.log(`\n Rank #${combo.rank}:`);
81
+ for (const [step, model] of Object.entries(combo.models))
82
+ console.log(` ${step}: ${model}`);
83
+ console.log(` 预估成本: $${combo.estimatedCost.toFixed(2)}`);
84
+ }
85
+ const outputPath = path.join(process.cwd(), "agentfare-optimized.json");
86
+ fs.writeFileSync(outputPath, JSON.stringify({
87
+ pipeline: pipeline.name,
88
+ optimizedAt: new Date().toISOString(),
89
+ algorithm: opts.algorithm,
90
+ topCombo: results[0]?.models,
91
+ allResults: results,
92
+ }, null, 2));
93
+ console.log(`\n结果已写入 ${outputPath}`);
94
+ });
95
+ //# sourceMappingURL=optimize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../src/commands/optimize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_js_1 = require("./commands/init.js");
6
+ const cost_js_1 = require("./commands/cost.js");
7
+ const config_cmd_js_1 = require("./commands/config-cmd.js");
8
+ const models_js_1 = require("./commands/models.js");
9
+ const optimize_js_1 = require("./commands/optimize.js");
10
+ // ISSUE-051: global error handling
11
+ process.on("unhandledRejection", (err) => {
12
+ console.error("agentfare: unexpected error");
13
+ console.error(err instanceof Error ? err.message : String(err));
14
+ process.exit(1);
15
+ });
16
+ const program = new commander_1.Command();
17
+ program
18
+ .name("agentfare")
19
+ .description("AI Agent 智能模型路由 — 成本优化工具")
20
+ .version("0.1.0")
21
+ .exitOverride(); // throw instead of calling process.exit for wrong flags
22
+ program.addCommand(init_js_1.initCommand);
23
+ program.addCommand(cost_js_1.costCommand);
24
+ program.addCommand(config_cmd_js_1.configCommand);
25
+ program.addCommand(models_js_1.modelsCommand);
26
+ program.addCommand(optimize_js_1.optimizeCommand);
27
+ program.parse();
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,gDAAiD;AACjD,gDAAiD;AACjD,4DAAyD;AACzD,oDAAqD;AACrD,wDAAyD;AAEzD,mCAAmC;AACnC,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,GAAG,EAAE,EAAE;IACvC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,0BAA0B,CAAC;KACvC,OAAO,CAAC,OAAO,CAAC;KAChB,YAAY,EAAE,CAAC,CAAC,wDAAwD;AAE3E,OAAO,CAAC,UAAU,CAAC,qBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,qBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,6BAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,yBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,6BAAe,CAAC,CAAC;AAEpC,OAAO,CAAC,KAAK,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@agentfare/cli",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": ["dist"],
8
+ "bin": {
9
+ "agentfare": "dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest"
15
+ },
16
+ "dependencies": {
17
+ "@agentfare/core": "workspace:*",
18
+ "@agentfare/loader": "workspace:*",
19
+ "@agentfare/models": "workspace:*",
20
+ "@agentfare/setup": "workspace:*",
21
+ "commander": "^13.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "^22.0.0",
25
+ "typescript": "^5.8",
26
+ "vitest": "^3.2"
27
+ }
28
+ }