Przeglądaj źródła

feat(cli): B17 add 'config list-models <service>' command with abilities tags

fanghanjun 6 miesięcy temu
rodzic
commit
229ae27f15
1 zmienionych plików z 34 dodań i 0 usunięć
  1. 34 0
      packages/cli/src/commands/config.ts

+ 34 - 0
packages/cli/src/commands/config.ts

@@ -2,6 +2,7 @@ import { Command } from "commander";
 import { readFile, writeFile, mkdir } from "node:fs/promises";
 import { readFile, writeFile, mkdir } from "node:fs/promises";
 import { join } from "node:path";
 import { join } from "node:path";
 import { findProjectRoot, log, logError, GLOBAL_CONFIG_DIR, GLOBAL_ENV_PATH } from "../utils.js";
 import { findProjectRoot, log, logError, GLOBAL_CONFIG_DIR, GLOBAL_ENV_PATH } from "../utils.js";
+import { listModelsForService } from "@actalk/inkos-core";
 
 
 export const configCommand = new Command("config")
 export const configCommand = new Command("config")
   .description("Manage project configuration");
   .description("Manage project configuration");
@@ -295,3 +296,36 @@ configCommand
       process.exit(1);
       process.exit(1);
     }
     }
   });
   });
+
+// B17: list-models 命令 —— 列出指定 service 的可用模型(含元数据)
+configCommand
+  .command("list-models <service>")
+  .description("List available models for a service (with maxOutput / contextWindow / abilities)")
+  .option("--api-key <key>", "API Key (also reads from INKOS_LLM_API_KEY env)")
+  .option("--base-url <url>", "Live /models probe baseUrl (for custom/newapi)")
+  .option("--json", "Output as JSON")
+  .action(async (service: string, opts: { apiKey?: string; baseUrl?: string; json?: boolean }) => {
+    const apiKey = opts.apiKey ?? process.env.INKOS_LLM_API_KEY;
+    const models = await listModelsForService(service, apiKey, opts.baseUrl);
+    if (models.length === 0) {
+      logError(`${service} 没有可用模型(可能需要 --api-key 和 --base-url)`);
+      process.exit(1);
+    }
+    if (opts.json) {
+      log(JSON.stringify(models, null, 2));
+      return;
+    }
+    log(`${service}:${models.length} 个模型\n`);
+    for (const m of models) {
+      const tags: string[] = [];
+      if (m.abilities?.reasoning) tags.push("R");
+      if (m.abilities?.vision) tags.push("V");
+      if (m.abilities?.functionCall) tags.push("F");
+      if (m.abilities?.search) tags.push("S");
+      const tagStr = tags.length ? ` [${tags.join("")}]` : "";
+      const maxOut = m.maxOutput ? `out=${m.maxOutput}` : "out=?";
+      const ctx = m.contextWindow > 0 ? `ctx=${m.contextWindow}` : "ctx=?";
+      log(`  ${m.id.padEnd(42)} ${maxOut.padEnd(14)} ${ctx}${tagStr}`);
+    }
+    log("\n标签:R=reasoning  V=vision  F=functionCall  S=search");
+  });