@agentskit/cli 0.13.34 → 0.13.36

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 CHANGED
@@ -20,7 +20,7 @@ Chat with any LLM, scaffold projects, and run agents — all from your terminal.
20
20
  ## Verified proof
21
21
 
22
22
  - Package metadata and tests live under `packages/cli/`.
23
- - Package guide: https://www.agentskit.io/docs/packages/cli
23
+ - Package guide: https://www.agentskit.io/docs/reference/packages/cli
24
24
  - Stability map: [docs/STABILITY.md](../../docs/STABILITY.md)
25
25
 
26
26
  ## How this fits the ecosystem
@@ -32,14 +32,14 @@ Chat with any LLM, scaffold projects, and run agents — all from your terminal.
32
32
  - **Playbook**: learn the production patterns behind this layer at [playbook.agentskit.io](https://playbook.agentskit.io).
33
33
  - **AKOS**: run the same concepts with enterprise deployment, governance, and observability at [akos.agentskit.io](https://akos.agentskit.io).
34
34
 
35
- Docs: [package guide](https://www.agentskit.io/docs/packages/cli) · [agent handoff](https://github.com/AgentsKit-io/agentskit/blob/main/llms.txt)
35
+ Docs: [package guide](https://www.agentskit.io/docs/reference/packages/cli) · [agent handoff](https://github.com/AgentsKit-io/agentskit/blob/main/llms.txt)
36
36
 
37
37
  ## Why cli
38
38
 
39
39
  - **Zero setup for prototyping** — go from idea to running conversation in under a minute; no boilerplate, no config files to write
40
40
  - **Scaffold production-ready projects** — generate a React chat app or terminal agent with the right structure so you skip the boring setup
41
41
  - **Script and automate** — pipe inputs, use env vars for keys, and compose with other Unix tools for lightweight agent scripting
42
- - **Every provider, one command** — switch between OpenAI, Anthropic, Ollama (local), and more with a single flag
42
+ - **Every provider, one command** — switch between OpenAI, Anthropic, Groq, OpenRouter, Ollama (local), and more with a single flag
43
43
 
44
44
  ## Install
45
45
 
@@ -57,6 +57,13 @@ ANTHROPIC_API_KEY=... agentskit chat --provider anthropic --model claude-sonnet-
57
57
  # Chat with a local model (no API key needed)
58
58
  agentskit chat --provider ollama --model llama3.1
59
59
 
60
+ # Chat through DeepSeek, Grok, Kimi, Groq, or OpenRouter
61
+ DEEPSEEK_API_KEY=... agentskit chat --provider deepseek
62
+ XAI_API_KEY=... agentskit chat --provider grok
63
+ KIMI_API_KEY=... agentskit chat --provider kimi
64
+ GROQ_API_KEY=... agentskit chat --provider groq
65
+ OPENROUTER_API_KEY=... agentskit chat --provider openrouter
66
+
60
67
  # Scaffold a new React chat app
61
68
  agentskit init --template react --dir my-app
62
69
 
@@ -84,8 +91,10 @@ agentskit run --help
84
91
  - **Extensibility** — plugins (slash commands, tools, skills, providers, hooks, MCP servers), permission policy with modes, lifecycle hooks (shell or JS), MCP stdio bridge, session rename + fork, `/usage` + `/cost`
85
92
  - Provider flags: `--provider`, `--model`, `--system`, `--skill`, `--memory`, `--mode`, `--plugin-dir`
86
93
  - Env-var based key injection — works seamlessly in CI and scripts
94
+ - Built-in live providers include OpenAI, Anthropic, Gemini, DeepSeek, Grok, Kimi, Groq, and OpenRouter; Ollama remains local and keyless
95
+ - `agentskit init --provider deepseek|grok|kimi|groq|openrouter` — scaffold a starter already wired to the selected provider
87
96
 
88
- Full reference: [docs/infrastructure/cli](https://www.agentskit.io/docs/infrastructure/cli) · [ARCHITECTURE.md](./ARCHITECTURE.md)
97
+ Full reference: [docs/production/cli](https://www.agentskit.io/docs/production/cli) · [ARCHITECTURE.md](./ARCHITECTURE.md)
89
98
 
90
99
  ### agentskit doctor
91
100
 
package/dist/bin.cjs CHANGED
@@ -105,12 +105,12 @@ var providers = {
105
105
  anthropic: {
106
106
  label: "Anthropic",
107
107
  envKeys: ["ANTHROPIC_API_KEY"],
108
- defaultModel: "claude-3-5-sonnet-latest",
108
+ defaultModel: "claude-sonnet-4-6",
109
109
  factory: (c) => adapters.anthropic(c)
110
110
  },
111
111
  gemini: {
112
112
  label: "Gemini",
113
- envKeys: ["GEMINI_API_KEY"],
113
+ envKeys: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
114
114
  defaultModel: "gemini-2.5-flash",
115
115
  factory: (c) => adapters.gemini(c)
116
116
  },
@@ -129,14 +129,26 @@ var providers = {
129
129
  grok: {
130
130
  label: "xAI Grok",
131
131
  envKeys: ["XAI_API_KEY"],
132
- requiresModel: true,
132
+ defaultModel: "grok-4.20-0309-non-reasoning",
133
133
  factory: (c) => adapters.grok(c)
134
134
  },
135
135
  kimi: {
136
136
  label: "Kimi",
137
137
  envKeys: ["KIMI_API_KEY", "MOONSHOT_API_KEY"],
138
- requiresModel: true,
138
+ defaultModel: "kimi-k2-0711-preview",
139
139
  factory: (c) => adapters.kimi(c)
140
+ },
141
+ groq: {
142
+ label: "Groq",
143
+ envKeys: ["GROQ_API_KEY"],
144
+ defaultModel: "openai/gpt-oss-120b",
145
+ factory: (c) => adapters.groq(c)
146
+ },
147
+ openrouter: {
148
+ label: "OpenRouter",
149
+ envKeys: ["OPENROUTER_API_KEY"],
150
+ defaultModel: "~anthropic/claude-haiku-latest",
151
+ factory: (c) => adapters.openrouter(c)
140
152
  }
141
153
  };
142
154
  function createDemoAdapter(provider, model) {
@@ -429,7 +441,7 @@ ${lines.join("\n")}`, "info");
429
441
  {
430
442
  name: "provider",
431
443
  description: "Switch the adapter provider.",
432
- usage: "/provider openai|anthropic|gemini|ollama|deepseek|grok|kimi|demo",
444
+ usage: "/provider openai|anthropic|gemini|ollama|deepseek|grok|kimi|groq|openrouter|demo",
433
445
  run(ctx, args) {
434
446
  const value = args.trim();
435
447
  if (!value) {
@@ -1695,17 +1707,29 @@ function registerRunCommand(program) {
1695
1707
  }
1696
1708
  });
1697
1709
  }
1710
+
1711
+ // src/init-providers.ts
1698
1712
  var PROVIDER_IMPORT = {
1699
1713
  openai: "openai",
1700
1714
  anthropic: "anthropic",
1701
1715
  gemini: "gemini",
1702
- ollama: "ollama"
1716
+ ollama: "ollama",
1717
+ deepseek: "deepseek",
1718
+ grok: "grok",
1719
+ kimi: "kimi",
1720
+ groq: "groq",
1721
+ openrouter: "openrouter"
1703
1722
  };
1704
1723
  var PROVIDER_DEFAULT_MODEL = {
1705
1724
  openai: "gpt-4o-mini",
1706
1725
  anthropic: "claude-sonnet-4-6",
1707
1726
  gemini: "gemini-2.5-flash",
1708
1727
  ollama: "llama3.1",
1728
+ deepseek: "deepseek-chat",
1729
+ grok: "grok-4.20-0309-non-reasoning",
1730
+ kimi: "kimi-k2-0711-preview",
1731
+ groq: "openai/gpt-oss-120b",
1732
+ openrouter: "~anthropic/claude-haiku-latest",
1709
1733
  demo: "demo"
1710
1734
  };
1711
1735
  var PROVIDER_ENV_KEY = {
@@ -1713,8 +1737,15 @@ var PROVIDER_ENV_KEY = {
1713
1737
  anthropic: "ANTHROPIC_API_KEY",
1714
1738
  gemini: "GEMINI_API_KEY",
1715
1739
  ollama: null,
1740
+ deepseek: "DEEPSEEK_API_KEY",
1741
+ grok: "XAI_API_KEY",
1742
+ kimi: "KIMI_API_KEY",
1743
+ groq: "GROQ_API_KEY",
1744
+ openrouter: "OPENROUTER_API_KEY",
1716
1745
  demo: null
1717
1746
  };
1747
+
1748
+ // src/init.ts
1718
1749
  function adapterCall(provider, prefix = "process.env") {
1719
1750
  const model = PROVIDER_DEFAULT_MODEL[provider];
1720
1751
  if (provider === "demo") return `demoAdapter()`;
@@ -1722,6 +1753,11 @@ function adapterCall(provider, prefix = "process.env") {
1722
1753
  const envKey = PROVIDER_ENV_KEY[provider];
1723
1754
  return `${PROVIDER_IMPORT[provider]}({ apiKey: ${prefix}.${envKey} ?? '', model: '${model}' })`;
1724
1755
  }
1756
+ function denoAdapterCall(provider) {
1757
+ if (provider === "demo") return "demoAdapter()";
1758
+ if (provider === "ollama") return `ollama({ model: '${PROVIDER_DEFAULT_MODEL[provider]}' })`;
1759
+ return `${PROVIDER_IMPORT[provider]}({ apiKey: Deno.env.get('${PROVIDER_ENV_KEY[provider]}') ?? '', model: '${PROVIDER_DEFAULT_MODEL[provider]}' })`;
1760
+ }
1725
1761
  function viteAdapterCall(provider) {
1726
1762
  if (provider === "demo") return `demoAdapter()`;
1727
1763
  if (provider === "ollama") return `ollama({ model: '${PROVIDER_DEFAULT_MODEL[provider]}' })`;
@@ -2402,7 +2438,7 @@ function cloudflareWorkersStarter(ctx) {
2402
2438
  "itty-router": "^5.0.0"
2403
2439
  };
2404
2440
  if (ctx.provider !== "demo") deps["@agentskit/adapters"] = "^0.4.0";
2405
- const adapterCallEdge = ctx.provider === "demo" ? "demoAdapter()" : ctx.provider === "ollama" ? `ollama({ model: '${PROVIDER_DEFAULT_MODEL[ctx.provider]}' })` : `${PROVIDER_IMPORT[ctx.provider]}({ apiKey: env.${PROVIDER_ENV_KEY[ctx.provider]} ?? '', model: '${PROVIDER_DEFAULT_MODEL[ctx.provider]}' })`;
2441
+ const adapterCallEdge = adapterCall(ctx.provider, "env");
2406
2442
  const adapterImport2 = buildAdapterServerImport(ctx.provider);
2407
2443
  const demoSnippet = ctx.provider === "demo" ? demoAdapterSnippet() : "";
2408
2444
  const envKey = PROVIDER_ENV_KEY[ctx.provider];
@@ -2885,7 +2921,7 @@ export const useAuth = () => useContext(AuthCtx)
2885
2921
  };
2886
2922
  }
2887
2923
  function denoDeployStarter(ctx) {
2888
- const adapterCallEdge = ctx.provider === "demo" ? "demoAdapter()" : ctx.provider === "ollama" ? `ollama({ model: '${PROVIDER_DEFAULT_MODEL[ctx.provider]}' })` : `${PROVIDER_IMPORT[ctx.provider]}({ apiKey: Deno.env.get('${PROVIDER_ENV_KEY[ctx.provider]}') ?? '', model: '${PROVIDER_DEFAULT_MODEL[ctx.provider]}' })`;
2924
+ const adapterCallEdge = denoAdapterCall(ctx.provider);
2889
2925
  const adapterImport2 = ctx.provider === "demo" ? "" : `import { ${PROVIDER_IMPORT[ctx.provider]} } from 'npm:@agentskit/adapters'
2890
2926
  `;
2891
2927
  const demoSnippet = ctx.provider === "demo" ? demoAdapterSnippet() : "";
@@ -3070,8 +3106,8 @@ ${runCmd}
3070
3106
  ## Next steps
3071
3107
 
3072
3108
  - Open the AgentsKit docs at https://www.agentskit.io/docs
3073
- - Add a custom skill: https://www.agentskit.io/docs/concepts/skill
3074
- - Wire up RAG: https://www.agentskit.io/docs/recipes/rag-chat
3109
+ - Add a custom skill: https://www.agentskit.io/docs/get-started/concepts/skill
3110
+ - Wire up RAG: https://www.agentskit.io/docs/reference/recipes/rag-chat
3075
3111
 
3076
3112
  ## License
3077
3113
 
@@ -3154,7 +3190,12 @@ ${kleur__default.default.bold().green("\u25B2")} ${kleur__default.default.bold("
3154
3190
  { name: "OpenAI", value: "openai" },
3155
3191
  { name: "Anthropic", value: "anthropic" },
3156
3192
  { name: "Gemini", value: "gemini" },
3157
- { name: "Ollama (local, no key)", value: "ollama" }
3193
+ { name: "Ollama (local, no key)", value: "ollama" },
3194
+ { name: "DeepSeek", value: "deepseek" },
3195
+ { name: "xAI Grok", value: "grok" },
3196
+ { name: "Kimi", value: "kimi" },
3197
+ { name: "Groq", value: "groq" },
3198
+ { name: "OpenRouter", value: "openrouter" }
3158
3199
  ]
3159
3200
  });
3160
3201
  let tools = [];
@@ -3253,7 +3294,7 @@ function printNextSteps(options) {
3253
3294
 
3254
3295
  // src/commands/init.ts
3255
3296
  function registerInitCommand(program) {
3256
- program.command("init").description("Generate a starter project. Run with no flags for interactive mode.").option("--template <template>", "Starter template (react|nextjs|sveltekit|nuxt|ink|vite-ink|cloudflare-workers|bun|deno-deploy|expo|angular|runtime|multi-agent)").option("--dir <directory>", "Target directory", "agentskit-app").option("--provider <provider>", "LLM provider (openai|anthropic|gemini|ollama|demo)").option("--tools <tools>", "Comma-separated tools (web_search,filesystem,shell)").option("--memory <backend>", "Memory backend (none|file|sqlite)").option("--pm <packageManager>", "Package manager (pnpm|npm|yarn|bun)").option("-y, --yes", "Skip interactive prompts; use flag values + defaults").action(async (rawOptions) => {
3297
+ program.command("init").description("Generate a starter project. Run with no flags for interactive mode.").option("--template <template>", "Starter template (react|nextjs|sveltekit|nuxt|ink|vite-ink|cloudflare-workers|bun|deno-deploy|expo|angular|runtime|multi-agent)").option("--dir <directory>", "Target directory", "agentskit-app").option("--provider <provider>", "LLM provider (openai|anthropic|gemini|ollama|deepseek|grok|kimi|groq|openrouter|demo)").option("--tools <tools>", "Comma-separated tools (web_search,filesystem,shell)").option("--memory <backend>", "Memory backend (none|file|sqlite)").option("--pm <packageManager>", "Package manager (pnpm|npm|yarn|bun)").option("-y, --yes", "Skip interactive prompts; use flag values + defaults").action(async (rawOptions) => {
3257
3298
  const isCi = !process.stdout.isTTY || rawOptions.yes || rawOptions.template;
3258
3299
  let resolved;
3259
3300
  if (isCi) {
@@ -3288,20 +3329,206 @@ function registerInitCommand(program) {
3288
3329
  }
3289
3330
  });
3290
3331
  }
3291
- var PROVIDER_ENV_KEYS = {
3292
- openai: "OPENAI_API_KEY",
3293
- anthropic: "ANTHROPIC_API_KEY",
3294
- gemini: "GEMINI_API_KEY",
3295
- deepseek: "DEEPSEEK_API_KEY",
3296
- grok: "XAI_API_KEY",
3297
- kimi: "KIMI_API_KEY"
3298
- };
3299
- var PROVIDER_REACH_URLS = {
3300
- openai: "https://api.openai.com/v1/models",
3301
- anthropic: "https://api.anthropic.com/v1/messages",
3302
- gemini: "https://generativelanguage.googleapis.com/v1beta/models",
3303
- ollama: "http://localhost:11434/api/tags"
3304
- };
3332
+
3333
+ // src/provider-registry.ts
3334
+ var PROVIDER_REGISTRY = [
3335
+ {
3336
+ id: "demo",
3337
+ label: "Demo",
3338
+ runtime: "local",
3339
+ env: { status: "not-required", reason: "Demo adapter does not use provider credentials." },
3340
+ reachability: { status: "unsupported", reason: "Demo adapter has no upstream endpoint." },
3341
+ defaultModel: { status: "known", id: "demo" }
3342
+ },
3343
+ {
3344
+ id: "openai",
3345
+ label: "OpenAI",
3346
+ runtime: "cli",
3347
+ catalogId: "openai",
3348
+ env: { status: "required", keys: ["OPENAI_API_KEY"] },
3349
+ reachability: { status: "supported", url: "https://api.openai.com/v1/models" },
3350
+ defaultModel: { status: "known", id: "gpt-4o-mini" },
3351
+ doctorDefault: true
3352
+ },
3353
+ {
3354
+ id: "anthropic",
3355
+ label: "Anthropic",
3356
+ runtime: "cli",
3357
+ catalogId: "anthropic",
3358
+ env: { status: "required", keys: ["ANTHROPIC_API_KEY"] },
3359
+ reachability: { status: "supported", url: "https://api.anthropic.com/v1/messages" },
3360
+ defaultModel: { status: "known", id: "claude-sonnet-4-6" },
3361
+ doctorDefault: true
3362
+ },
3363
+ {
3364
+ id: "gemini",
3365
+ label: "Gemini",
3366
+ runtime: "cli",
3367
+ catalogId: "google",
3368
+ env: { status: "required", keys: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"] },
3369
+ reachability: { status: "supported", url: "https://generativelanguage.googleapis.com/v1beta/models" },
3370
+ defaultModel: { status: "known", id: "gemini-2.5-flash" },
3371
+ doctorDefault: true
3372
+ },
3373
+ {
3374
+ id: "ollama",
3375
+ label: "Ollama",
3376
+ runtime: "local",
3377
+ env: { status: "not-required", reason: "Ollama runs locally and does not require an API key." },
3378
+ reachability: { status: "supported", url: "http://localhost:11434/api/tags" },
3379
+ defaultModel: { status: "known", id: "llama3.1" },
3380
+ doctorDefault: true
3381
+ },
3382
+ {
3383
+ id: "deepseek",
3384
+ label: "DeepSeek",
3385
+ runtime: "cli",
3386
+ catalogId: "deepseek",
3387
+ env: { status: "required", keys: ["DEEPSEEK_API_KEY"] },
3388
+ reachability: { status: "supported", url: "https://api.deepseek.com/models" },
3389
+ defaultModel: { status: "known", id: "deepseek-chat" }
3390
+ },
3391
+ {
3392
+ id: "grok",
3393
+ label: "xAI Grok",
3394
+ runtime: "cli",
3395
+ catalogId: "xai",
3396
+ env: { status: "required", keys: ["XAI_API_KEY"] },
3397
+ reachability: { status: "supported", url: "https://api.x.ai/v1/models" },
3398
+ defaultModel: { status: "known", id: "grok-4.20-0309-non-reasoning" }
3399
+ },
3400
+ {
3401
+ id: "kimi",
3402
+ label: "Kimi",
3403
+ runtime: "cli",
3404
+ catalogId: "moonshotai",
3405
+ env: { status: "required", keys: ["KIMI_API_KEY", "MOONSHOT_API_KEY"] },
3406
+ reachability: { status: "supported", url: "https://api.moonshot.ai/v1/models" },
3407
+ defaultModel: { status: "known", id: "kimi-k2-0711-preview" }
3408
+ },
3409
+ {
3410
+ id: "groq",
3411
+ label: "Groq",
3412
+ runtime: "cli",
3413
+ catalogId: "groq",
3414
+ env: { status: "required", keys: ["GROQ_API_KEY"] },
3415
+ reachability: { status: "supported", url: "https://api.groq.com/openai/v1/models" },
3416
+ defaultModel: { status: "known", id: "openai/gpt-oss-120b" }
3417
+ },
3418
+ {
3419
+ id: "openrouter",
3420
+ label: "OpenRouter",
3421
+ runtime: "cli",
3422
+ catalogId: "openrouter",
3423
+ env: { status: "required", keys: ["OPENROUTER_API_KEY"] },
3424
+ reachability: { status: "supported", url: "https://openrouter.ai/api/v1/models" },
3425
+ defaultModel: { status: "known", id: "~anthropic/claude-haiku-latest" }
3426
+ },
3427
+ {
3428
+ id: "mistral",
3429
+ label: "Mistral",
3430
+ runtime: "adapter-only",
3431
+ catalogId: "mistral",
3432
+ env: { status: "required", keys: ["MISTRAL_API_KEY"] },
3433
+ reachability: { status: "supported", url: "https://api.mistral.ai/v1/models" },
3434
+ defaultModel: { status: "known", id: "codestral-latest" }
3435
+ },
3436
+ {
3437
+ id: "cohere",
3438
+ label: "Cohere",
3439
+ runtime: "adapter-only",
3440
+ catalogId: "cohere",
3441
+ env: { status: "required", keys: ["COHERE_API_KEY"] },
3442
+ reachability: { status: "supported", url: "https://api.cohere.com/v1/models" },
3443
+ defaultModel: { status: "known", id: "c4ai-aya-expanse-32b" }
3444
+ },
3445
+ {
3446
+ id: "together",
3447
+ label: "Together",
3448
+ runtime: "adapter-only",
3449
+ catalogId: "togetherai",
3450
+ env: { status: "required", keys: ["TOGETHER_API_KEY"] },
3451
+ reachability: { status: "supported", url: "https://api.together.xyz/v1/models" },
3452
+ defaultModel: { status: "known", id: "deepseek-ai/DeepSeek-R1" }
3453
+ },
3454
+ {
3455
+ id: "fireworks",
3456
+ label: "Fireworks",
3457
+ runtime: "adapter-only",
3458
+ catalogId: "fireworks-ai",
3459
+ env: { status: "required", keys: ["FIREWORKS_API_KEY"] },
3460
+ reachability: { status: "supported", url: "https://api.fireworks.ai/inference/v1/models" },
3461
+ defaultModel: { status: "known", id: "accounts/fireworks/models/deepseek-v4-flash" }
3462
+ },
3463
+ {
3464
+ id: "huggingface",
3465
+ label: "Hugging Face",
3466
+ runtime: "adapter-only",
3467
+ catalogId: "huggingface",
3468
+ env: { status: "required", keys: ["HF_TOKEN"] },
3469
+ reachability: { status: "supported", url: "https://router.huggingface.co/v1/models" },
3470
+ defaultModel: { status: "known", id: "deepseek-ai/DeepSeek-R1-0528" }
3471
+ },
3472
+ {
3473
+ id: "lmstudio",
3474
+ label: "LM Studio",
3475
+ runtime: "local",
3476
+ catalogId: "lmstudio",
3477
+ env: { status: "not-required", reason: "LM Studio runs locally and does not require a provider key." },
3478
+ reachability: { status: "supported", url: "http://127.0.0.1:1234/v1/models" },
3479
+ defaultModel: { status: "known", id: "openai/gpt-oss-20b" }
3480
+ },
3481
+ {
3482
+ id: "vllm",
3483
+ label: "vLLM",
3484
+ runtime: "local",
3485
+ env: { status: "not-required", reason: "vLLM is a local server and does not require a provider key." },
3486
+ reachability: { status: "supported", url: "http://localhost:8000/v1/models" },
3487
+ defaultModel: { status: "known", id: "meta-llama/Llama-3.1-8B-Instruct" }
3488
+ },
3489
+ {
3490
+ id: "llamacpp",
3491
+ label: "llama.cpp",
3492
+ runtime: "local",
3493
+ env: { status: "not-required", reason: "llama.cpp is a local server and does not require a provider key." },
3494
+ reachability: { status: "supported", url: "http://localhost:8080/v1/models" },
3495
+ defaultModel: { status: "known", id: "local-model" }
3496
+ },
3497
+ {
3498
+ id: "cerebras",
3499
+ label: "Cerebras",
3500
+ runtime: "adapter-only",
3501
+ catalogId: "cerebras",
3502
+ env: { status: "required", keys: ["CEREBRAS_API_KEY"] },
3503
+ reachability: { status: "supported", url: "https://api.cerebras.ai/v1/models" },
3504
+ defaultModel: { status: "known", id: "gpt-oss-120b" }
3505
+ }
3506
+ ];
3507
+ var DEFAULT_DOCTOR_PROVIDERS = PROVIDER_REGISTRY.filter((entry) => "doctorDefault" in entry && entry.doctorDefault === true).map((entry) => entry.id);
3508
+ function getProviderRegistryEntry(provider) {
3509
+ return PROVIDER_REGISTRY.find((entry) => entry.id === provider.toLowerCase());
3510
+ }
3511
+ function resolveProviderRegistryEntry(provider) {
3512
+ return getProviderRegistryEntry(provider) ?? {
3513
+ id: provider,
3514
+ label: provider,
3515
+ runtime: "adapter-only",
3516
+ env: { status: "unsupported", reason: "Provider is not in the CLI doctor registry." },
3517
+ reachability: { status: "unsupported", reason: "Provider is not in the CLI doctor registry." },
3518
+ defaultModel: { status: "unsupported", reason: "Provider is not in the CLI doctor registry." }
3519
+ };
3520
+ }
3521
+
3522
+ // src/doctor.ts
3523
+ function providerReachabilityFix(entry) {
3524
+ if (entry.id === "ollama") {
3525
+ return "Start Ollama: `ollama serve` (or install from https://ollama.com)";
3526
+ }
3527
+ if (entry.runtime === "local") {
3528
+ return `Start ${entry.label} server and verify its local endpoint`;
3529
+ }
3530
+ return "Check network / firewall / VPN settings";
3531
+ }
3305
3532
  async function checkNodeVersion() {
3306
3533
  const major = Number(process.versions.node.split(".")[0]);
3307
3534
  if (Number.isNaN(major)) {
@@ -3380,17 +3607,22 @@ async function checkPackageJson() {
3380
3607
  }
3381
3608
  }
3382
3609
  async function checkProviderEnv(provider) {
3383
- const envKey = PROVIDER_ENV_KEYS[provider];
3384
- if (!envKey) {
3385
- return { status: "skip", name: `${provider} API key`, detail: "No env-key requirement for this provider" };
3610
+ const entry = resolveProviderRegistryEntry(provider);
3611
+ if (entry.env.status === "unsupported") {
3612
+ return { status: "skip", name: `${provider} API key`, detail: entry.env.reason };
3613
+ }
3614
+ if (entry.env.status === "not-required") {
3615
+ return { status: "skip", name: `${provider} API key`, detail: entry.env.reason };
3386
3616
  }
3387
- const value = process.env[envKey];
3617
+ const envKey = entry.env.keys.find((key) => process.env[key]);
3618
+ const expectedKeys = entry.env.keys.join(" or ");
3619
+ const value = envKey ? process.env[envKey] : void 0;
3388
3620
  if (!value) {
3389
3621
  return {
3390
3622
  status: "skip",
3391
3623
  name: `${provider} API key`,
3392
- detail: `${envKey} not set`,
3393
- fix: `export ${envKey}=... (only needed if you use ${provider})`
3624
+ detail: `${expectedKeys} not set`,
3625
+ fix: `export ${entry.env.keys[0]}=... (only needed if you use ${provider})`
3394
3626
  };
3395
3627
  }
3396
3628
  if (value.length < 16) {
@@ -3404,12 +3636,12 @@ async function checkProviderEnv(provider) {
3404
3636
  return { status: "pass", name: `${provider} API key`, detail: `${envKey} set (${value.length} chars)` };
3405
3637
  }
3406
3638
  async function checkProviderReachable(provider, fetchImpl = fetch, timeoutMs = 4e3) {
3407
- const url = PROVIDER_REACH_URLS[provider];
3408
- if (!url) {
3409
- return { status: "skip", name: `${provider} reachable`, detail: "No reachability check configured" };
3639
+ const entry = resolveProviderRegistryEntry(provider);
3640
+ if (entry.reachability.status === "unsupported") {
3641
+ return { status: "skip", name: `${provider} reachable`, detail: entry.reachability.reason };
3410
3642
  }
3411
- const envKey = PROVIDER_ENV_KEYS[provider];
3412
- if (envKey && !process.env[envKey]) {
3643
+ const url = entry.reachability.url;
3644
+ if (entry.env.status === "required" && !entry.env.keys.some((key) => process.env[key])) {
3413
3645
  return { status: "skip", name: `${provider} reachable`, detail: "Skipped \u2014 no API key configured" };
3414
3646
  }
3415
3647
  const controller = new AbortController();
@@ -3437,12 +3669,23 @@ async function checkProviderReachable(provider, fetchImpl = fetch, timeoutMs = 4
3437
3669
  status: "fail",
3438
3670
  name: `${provider} reachable`,
3439
3671
  detail: `${url} \u2192 ${reason}`,
3440
- fix: provider === "ollama" ? "Start Ollama: `ollama serve` (or install from https://ollama.com)" : "Check network / firewall / VPN settings"
3672
+ fix: providerReachabilityFix(entry)
3441
3673
  };
3442
3674
  } finally {
3443
3675
  clearTimeout(timer);
3444
3676
  }
3445
3677
  }
3678
+ async function checkProviderDefaultModel(provider) {
3679
+ const entry = resolveProviderRegistryEntry(provider);
3680
+ if (entry.defaultModel.status === "unsupported") {
3681
+ return { status: "skip", name: `${provider} default model`, detail: entry.defaultModel.reason };
3682
+ }
3683
+ return {
3684
+ status: "pass",
3685
+ name: `${provider} default model`,
3686
+ detail: entry.defaultModel.id
3687
+ };
3688
+ }
3446
3689
  async function checkConfig() {
3447
3690
  try {
3448
3691
  const config = await loadConfig();
@@ -3463,7 +3706,7 @@ async function checkConfig() {
3463
3706
  }
3464
3707
  }
3465
3708
  async function runDoctor(options = {}) {
3466
- const providers2 = options.providers ?? ["openai", "anthropic", "gemini", "ollama"];
3709
+ const providers2 = options.providers ?? DEFAULT_DOCTOR_PROVIDERS;
3467
3710
  const fetchImpl = options.fetchImpl ?? fetch;
3468
3711
  const checks = [
3469
3712
  checkNodeVersion(),
@@ -3473,6 +3716,7 @@ async function runDoctor(options = {}) {
3473
3716
  ];
3474
3717
  for (const provider of providers2) {
3475
3718
  checks.push(checkProviderEnv(provider));
3719
+ checks.push(checkProviderDefaultModel(provider));
3476
3720
  if (!options.noNetwork) {
3477
3721
  checks.push(checkProviderReachable(provider, fetchImpl));
3478
3722
  }
@@ -3558,7 +3802,7 @@ function renderReport(report, opts = {}) {
3558
3802
  function registerDoctorCommand(program) {
3559
3803
  program.command("doctor").description("Diagnose your AgentsKit environment.").option("--no-network", "Skip provider reachability checks").option(
3560
3804
  "--providers <providers>",
3561
- "Comma-separated providers to check (default: openai,anthropic,gemini,ollama)"
3805
+ `Comma-separated providers to check (default: ${DEFAULT_DOCTOR_PROVIDERS.join(",")})`
3562
3806
  ).option("--json", "Emit JSON instead of formatted output").action(async (options) => {
3563
3807
  const providers2 = options.providers ? options.providers.split(",").map((p) => p.trim()).filter(Boolean) : void 0;
3564
3808
  const report = await runDoctor({
@@ -5554,7 +5798,7 @@ async function tryComponentAdd(name, options) {
5554
5798
  function registerAddCommand(program) {
5555
5799
  program.command("add <name>").description(
5556
5800
  'Add a ready-made agent or UI component from the AgentsKit registry (registry.agentskit.io). Auto-detects which: a component is scanned/validated against your project and installed transactionally; an agent is copied into ./agents. You own the code. e.g. `agentskit add docs-chat` (component) or `agentskit add research --run "\u2026"` (agent).'
5557
- ).option("--out <dir>", "Directory to install into (component: the port dir; agent: ./agents)").option("-f, --force", "Overwrite existing files").option("--registry <url>", "Registry base URL override (component install)").option("--run <task>", "Run the agent on this task right after adding it").option("--provider <provider>", "Provider for --run (openai, anthropic, gemini, ollama, demo)", "demo").option("--model <model>", "Model for --run").option("--api-key <key>", "API key for --run (else read from the provider env var)").action(
5801
+ ).option("--out <dir>", "Directory to install into (component: the port dir; agent: ./agents)").option("-f, --force", "Overwrite existing files").option("--registry <url>", "Registry base URL override (component install)").option("--run <task>", "Run the agent on this task right after adding it").option("--provider <provider>", "Provider for --run (openai, anthropic, gemini, ollama, groq, openrouter, demo)", "demo").option("--model <model>", "Model for --run").option("--api-key <key>", "API key for --run (else read from the provider env var)").action(
5558
5802
  async (agent, options) => {
5559
5803
  try {
5560
5804
  const outcome = await tryComponentAdd(agent, {