@phi-code-admin/phi-code 0.96.0 → 0.97.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/dist/cli/args.d.ts +1 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +43 -1
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/api-key-store.d.ts +20 -4
  7. package/dist/core/api-key-store.d.ts.map +1 -1
  8. package/dist/core/api-key-store.js +37 -7
  9. package/dist/core/api-key-store.js.map +1 -1
  10. package/dist/core/compaction/compaction.d.ts +16 -0
  11. package/dist/core/compaction/compaction.d.ts.map +1 -1
  12. package/dist/core/compaction/compaction.js +43 -19
  13. package/dist/core/compaction/compaction.js.map +1 -1
  14. package/dist/core/json-utils.d.ts +11 -0
  15. package/dist/core/json-utils.d.ts.map +1 -0
  16. package/dist/core/json-utils.js +15 -0
  17. package/dist/core/json-utils.js.map +1 -0
  18. package/dist/core/model-registry.d.ts +6 -1
  19. package/dist/core/model-registry.d.ts.map +1 -1
  20. package/dist/core/model-registry.js +10 -9
  21. package/dist/core/model-registry.js.map +1 -1
  22. package/dist/core/slash-commands.d.ts +13 -0
  23. package/dist/core/slash-commands.d.ts.map +1 -1
  24. package/dist/core/slash-commands.js +38 -0
  25. package/dist/core/slash-commands.js.map +1 -1
  26. package/dist/migrations.d.ts.map +1 -1
  27. package/dist/migrations.js +2 -2
  28. package/dist/migrations.js.map +1 -1
  29. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  30. package/dist/modes/interactive/interactive-mode.js +24 -4
  31. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  32. package/extensions/phi/benchmark.ts +43 -83
  33. package/extensions/phi/init.ts +86 -673
  34. package/extensions/phi/memory.ts +1 -1
  35. package/extensions/phi/models.ts +4 -3
  36. package/extensions/phi/providers/catalog.ts +133 -0
  37. package/extensions/phi/setup.ts +180 -280
  38. package/extensions/phi/smart-router.ts +0 -17
  39. package/package.json +5 -5
@@ -20,7 +20,8 @@
20
20
  import { access, mkdir, readFile, writeFile } from "node:fs/promises";
21
21
  import { homedir } from "node:os";
22
22
  import { join } from "node:path";
23
- import type { ExtensionAPI, ExtensionContext } from "phi-code";
23
+ import { type ExtensionAPI, type ExtensionContext, getApiKeyStore } from "phi-code";
24
+ import { getProviderCatalog } from "./providers/catalog.js";
24
25
 
25
26
  // ─── Types ───────────────────────────────────────────────────────────────
26
27
 
@@ -340,102 +341,61 @@ function extractCode(response: string): string {
340
341
  return match ? match[1].trim() : response.trim();
341
342
  }
342
343
 
343
- interface ProviderConfig {
344
- name: string;
345
- envVar: string;
346
- baseUrl: string;
347
- models: string[];
348
- }
349
-
350
- function getProviderConfigs(): ProviderConfig[] {
351
- return [
352
- {
353
- name: "alibaba-codingplan",
354
- envVar: "ALIBABA_CODING_PLAN_KEY",
355
- baseUrl: "https://coding-intl.dashscope.aliyuncs.com/v1",
356
- models: [
357
- "qwen3.5-plus",
358
- "qwen3-max-2026-01-23",
359
- "qwen3-coder-plus",
360
- "qwen3-coder-next",
361
- "kimi-k2.5",
362
- "glm-5",
363
- "glm-4.7",
364
- "MiniMax-M2.5",
365
- ],
366
- },
367
- {
368
- name: "openai",
369
- envVar: "OPENAI_API_KEY",
370
- baseUrl: "https://api.openai.com/v1",
371
- models: ["gpt-4o", "gpt-4o-mini"],
372
- },
373
- {
374
- name: "anthropic-openai",
375
- envVar: "ANTHROPIC_API_KEY",
376
- baseUrl: "https://api.anthropic.com/v1",
377
- models: [],
378
- },
379
- {
380
- name: "openrouter",
381
- envVar: "OPENROUTER_API_KEY",
382
- baseUrl: "https://openrouter.ai/api/v1",
383
- models: [],
384
- },
385
- {
386
- name: "groq",
387
- envVar: "GROQ_API_KEY",
388
- baseUrl: "https://api.groq.com/openai/v1",
389
- models: [],
390
- },
391
- ];
392
- }
344
+ // Provider list comes from the shared catalog (providers/catalog.ts) — the
345
+ // same source /setup and /phi-init use. Cloud entries expose `benchModels`
346
+ // (the subset /benchmark exercises); local servers are discovered separately.
393
347
 
394
348
  async function getAvailableModels(): Promise<Array<{ id: string; provider: string; baseUrl: string; apiKey: string }>> {
395
349
  const models: Array<{ id: string; provider: string; baseUrl: string; apiKey: string }> = [];
396
350
 
397
- // 1. Cloud providers via env vars
398
- for (const provider of getProviderConfigs()) {
399
- const apiKey = process.env[provider.envVar];
351
+ // 1. Cloud providers via env vars, falling back to keys stored in
352
+ // models.json via /setup or /keys (the store resolves env-var names and
353
+ // "!cmd" values the same way the model registry does at request time).
354
+ const store = getApiKeyStore();
355
+ for (const provider of getProviderCatalog()) {
356
+ if (provider.local) continue;
357
+ const benchModels = provider.benchModels ?? [];
358
+ let apiKey = process.env[provider.envVar];
359
+ if (!apiKey) {
360
+ try {
361
+ apiKey = store.getKey(provider.id);
362
+ } catch {
363
+ /* unreadable models.json — env-only behavior */
364
+ }
365
+ }
400
366
  if (!apiKey) continue;
401
367
 
402
- for (const modelId of provider.models) {
368
+ for (const modelId of benchModels) {
403
369
  models.push({
404
370
  id: modelId,
405
- provider: provider.name,
371
+ provider: provider.id,
406
372
  baseUrl: provider.baseUrl,
407
373
  apiKey,
408
374
  });
409
375
  }
410
376
  }
411
377
 
412
- // 2. Local providers (LM Studio, Ollama) — auto-detect via models.json
413
- const { join } = await import("node:path");
414
- const { homedir } = await import("node:os");
415
- const { readFileSync, existsSync } = await import("node:fs");
416
-
417
- const modelsJsonPath = join(homedir(), ".phi", "agent", "models.json");
418
- if (existsSync(modelsJsonPath)) {
419
- try {
420
- const config = JSON.parse(readFileSync(modelsJsonPath, "utf-8"));
421
- if (config.providers) {
422
- for (const [id, providerConfig] of Object.entries<any>(config.providers)) {
423
- const baseUrl = providerConfig.baseUrl || "";
424
- const apiKey = providerConfig.apiKey || "local";
425
- if (providerConfig.models?.length > 0) {
426
- for (const m of providerConfig.models) {
427
- const modelId = typeof m === "string" ? m : m.id;
428
- // Skip if already added from env vars
429
- if (!models.some((existing) => existing.id === modelId && existing.baseUrl === baseUrl)) {
430
- models.push({ id: modelId, provider: id, baseUrl, apiKey });
431
- }
432
- }
433
- }
378
+ // 2. Local providers (LM Studio, Ollama) — auto-detect via models.json,
379
+ // read through ApiKeyStore so // comments and trailing commas are
380
+ // tolerated and PHI_AGENT_DIR overrides are honored.
381
+ try {
382
+ for (const id of store.listProviders()) {
383
+ const providerConfig = store.getProvider(id);
384
+ if (!providerConfig) continue;
385
+ const baseUrl = providerConfig.baseUrl || "";
386
+ const apiKey = store.getKey(id) || "local";
387
+ if (!providerConfig.models || providerConfig.models.length === 0) continue;
388
+ for (const m of providerConfig.models) {
389
+ const modelId = typeof m === "string" ? m : (m as { id?: string }).id;
390
+ if (!modelId) continue;
391
+ // Skip if already added from env vars
392
+ if (!models.some((existing) => existing.id === modelId && existing.baseUrl === baseUrl)) {
393
+ models.push({ id: modelId, provider: id, baseUrl, apiKey });
434
394
  }
435
395
  }
436
- } catch {
437
- /* ignore parse errors */
438
396
  }
397
+ } catch {
398
+ /* ignore unreadable models.json */
439
399
  }
440
400
 
441
401
  // 3. Try to detect LM Studio (port 1234) and Ollama (port 11434) directly
@@ -740,12 +700,12 @@ Scoring: S (80+), A (65+), B (50+), C (35+), D (<35)`,
740
700
  // Get available models (validates API keys are non-empty and reasonable length)
741
701
  const available = await getAvailableModels();
742
702
  if (available.length === 0) {
743
- const providers = getProviderConfigs();
744
- const hint = providers
703
+ const hint = getProviderCatalog()
704
+ .filter((p) => !p.local)
745
705
  .map((p) => ` ${p.envVar}: ${process.env[p.envVar] ? "set but no models configured" : "not set"}`)
746
706
  .join("\n");
747
707
  ctx.ui.notify(
748
- `❌ No benchmarkable models found.\n\nProvider status:\n${hint}\n\nSet at least one API key with known models.`,
708
+ `❌ No benchmarkable models found.\n\nProvider status (env):\n${hint}\n\nSet at least one API key with known models (env var, /setup or /keys).`,
749
709
  "warning",
750
710
  );
751
711
  return;