zelari-code 0.7.10 → 0.7.11

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 (94) hide show
  1. package/LICENSE +37 -37
  2. package/README.md +320 -320
  3. package/bin/zelari-code.js +62 -62
  4. package/dist/cli/components/SplashScreen.js +85 -85
  5. package/dist/cli/headless.js +10 -10
  6. package/dist/cli/keyStore.js +2 -2
  7. package/dist/cli/keyStore.js.map +1 -1
  8. package/dist/cli/main.bundled.js +249 -229
  9. package/dist/cli/main.bundled.js.map +4 -4
  10. package/dist/cli/main.js +1 -1
  11. package/dist/cli/modelDiscovery.js +42 -5
  12. package/dist/cli/modelDiscovery.js.map +1 -1
  13. package/dist/cli/provider/openai-compatible.js +4 -2
  14. package/dist/cli/provider/openai-compatible.js.map +1 -1
  15. package/dist/cli/slashCommands.js +2 -2
  16. package/dist/cli/slashHandlers/provider.js +1 -1
  17. package/dist/cli/slashHandlers/provider.js.map +1 -1
  18. package/package.json +2 -2
  19. package/dist/agents/advancedTools.js +0 -115
  20. package/dist/agents/advancedTools.js.map +0 -1
  21. package/dist/agents/councilApi.js +0 -375
  22. package/dist/agents/councilApi.js.map +0 -1
  23. package/dist/agents/councilDirectives.js +0 -100
  24. package/dist/agents/councilDirectives.js.map +0 -1
  25. package/dist/agents/promoteMember.js +0 -210
  26. package/dist/agents/promoteMember.js.map +0 -1
  27. package/dist/agents/promptModules.js +0 -139
  28. package/dist/agents/promptModules.js.map +0 -1
  29. package/dist/agents/roles.js +0 -299
  30. package/dist/agents/roles.js.map +0 -1
  31. package/dist/agents/skills/builtin/debugging.js +0 -248
  32. package/dist/agents/skills/builtin/debugging.js.map +0 -1
  33. package/dist/agents/skills/builtin/docs.js +0 -301
  34. package/dist/agents/skills/builtin/docs.js.map +0 -1
  35. package/dist/agents/skills/builtin/git-ops.js +0 -301
  36. package/dist/agents/skills/builtin/git-ops.js.map +0 -1
  37. package/dist/agents/skills/builtin/planning.js +0 -335
  38. package/dist/agents/skills/builtin/planning.js.map +0 -1
  39. package/dist/agents/skills/builtin/refactoring.js +0 -261
  40. package/dist/agents/skills/builtin/refactoring.js.map +0 -1
  41. package/dist/agents/skills/builtin/review.js +0 -302
  42. package/dist/agents/skills/builtin/review.js.map +0 -1
  43. package/dist/agents/skills/builtin/testing.js +0 -245
  44. package/dist/agents/skills/builtin/testing.js.map +0 -1
  45. package/dist/agents/skills.js +0 -272
  46. package/dist/agents/skills.js.map +0 -1
  47. package/dist/agents/systemPromptBuilder.js +0 -151
  48. package/dist/agents/systemPromptBuilder.js.map +0 -1
  49. package/dist/agents/toolSchemas.js +0 -249
  50. package/dist/agents/toolSchemas.js.map +0 -1
  51. package/dist/agents/tools.js +0 -196
  52. package/dist/agents/tools.js.map +0 -1
  53. package/dist/agents/vaultTools.js +0 -134
  54. package/dist/agents/vaultTools.js.map +0 -1
  55. package/dist/cli/components/CollapsibleToolOutput.js +0 -43
  56. package/dist/cli/components/CollapsibleToolOutput.js.map +0 -1
  57. package/dist/cli/components/Header.js +0 -38
  58. package/dist/cli/components/Header.js.map +0 -1
  59. package/dist/main/core/AgentHarness.js +0 -467
  60. package/dist/main/core/AgentHarness.js.map +0 -1
  61. package/dist/main/core/providerStream.js +0 -99
  62. package/dist/main/core/providerStream.js.map +0 -1
  63. package/dist/main/core/sessionJsonl.js +0 -99
  64. package/dist/main/core/sessionJsonl.js.map +0 -1
  65. package/dist/main/core/tools/auditLog.js +0 -26
  66. package/dist/main/core/tools/auditLog.js.map +0 -1
  67. package/dist/main/core/tools/builtin/filesystem.js +0 -110
  68. package/dist/main/core/tools/builtin/filesystem.js.map +0 -1
  69. package/dist/main/core/tools/builtin/listFiles.js +0 -86
  70. package/dist/main/core/tools/builtin/listFiles.js.map +0 -1
  71. package/dist/main/core/tools/builtin/search.js +0 -56
  72. package/dist/main/core/tools/builtin/search.js.map +0 -1
  73. package/dist/main/core/tools/builtin/shell.js +0 -51
  74. package/dist/main/core/tools/builtin/shell.js.map +0 -1
  75. package/dist/main/core/tools/registry.js +0 -71
  76. package/dist/main/core/tools/registry.js.map +0 -1
  77. package/dist/main/core/tools/toolTypes.js +0 -8
  78. package/dist/main/core/tools/toolTypes.js.map +0 -1
  79. package/dist/main/core/tools/zodBridge.js +0 -56
  80. package/dist/main/core/tools/zodBridge.js.map +0 -1
  81. package/dist/shared/eventBus.js +0 -104
  82. package/dist/shared/eventBus.js.map +0 -1
  83. package/dist/shared/events.js +0 -73
  84. package/dist/shared/events.js.map +0 -1
  85. package/dist/shared/index.js +0 -8
  86. package/dist/shared/index.js.map +0 -1
  87. package/dist/types/context.js +0 -3
  88. package/dist/types/context.js.map +0 -1
  89. package/dist/types/index.js +0 -2
  90. package/dist/types/index.js.map +0 -1
  91. package/dist/types/knowledge.js +0 -2
  92. package/dist/types/knowledge.js.map +0 -1
  93. package/dist/types/systemTypes.js +0 -10
  94. package/dist/types/systemTypes.js.map +0 -1
@@ -547,8 +547,8 @@ var init_keyStore = __esm({
547
547
  registerDefaultRefreshImpls();
548
548
  PROVIDERS = [
549
549
  { id: "openai-compatible", displayName: "OpenAI-compatible", envVar: "OPENAI_API_KEY" },
550
- { id: "minimax", displayName: "MiniMax", envVar: "MINIMAX_API_KEY", baseUrl: "https://api.MiniMax.chat/v1" },
551
- { id: "glm", displayName: "GLM / Z.AI", envVar: "GLM_API_KEY", baseUrl: "https://api.z.ai/v1" },
550
+ { id: "minimax", displayName: "MiniMax", envVar: "MINIMAX_API_KEY", baseUrl: "https://api.minimax.io/v1" },
551
+ { id: "glm", displayName: "GLM / Z.AI", envVar: "GLM_API_KEY", baseUrl: "https://api.z.ai/api/coding/paas/v4" },
552
552
  { id: "grok", displayName: "xAI Grok", envVar: "GROK_API_KEY", baseUrl: "https://api.x.ai/v1" }
553
553
  ];
554
554
  defaultRefreshImpl = async (providerId, refreshToken) => {
@@ -561,6 +561,185 @@ var init_keyStore = __esm({
561
561
  }
562
562
  });
563
563
 
564
+ // src/cli/providerConfig.ts
565
+ var providerConfig_exports = {};
566
+ __export(providerConfig_exports, {
567
+ clearCustomEndpoint: () => clearCustomEndpoint,
568
+ getActiveModel: () => getActiveModel,
569
+ getActiveProvider: () => getActiveProvider,
570
+ getCustomEndpoint: () => getCustomEndpoint,
571
+ getModelForProvider: () => getModelForProvider,
572
+ getProviderConfig: () => getProviderConfig,
573
+ getProviderConfigPath: () => getProviderConfigPath,
574
+ loadProviderConfig: () => loadProviderConfig,
575
+ setActiveProviderId: () => setActiveProviderId,
576
+ setCustomEndpoint: () => setCustomEndpoint,
577
+ setModelForProvider: () => setModelForProvider
578
+ });
579
+ import { promises as fs2, existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
580
+ import path3 from "node:path";
581
+ import os2 from "node:os";
582
+ function getProviderConfigPath() {
583
+ return process.env.ANATHEMA_PROVIDER_CONFIG_FILE ?? path3.join(os2.homedir(), ".tmp", "zelari-code", "provider.json");
584
+ }
585
+ function getProviderConfig() {
586
+ const envActive = process.env.ANATHEMA_ACTIVE_PROVIDER;
587
+ const envModel = process.env.OPENAI_MODEL;
588
+ const file2 = getProviderConfigPath();
589
+ let stored = null;
590
+ if (existsSync2(file2)) {
591
+ try {
592
+ const raw = readFileSync2(file2, "utf-8");
593
+ const parsed = JSON.parse(raw);
594
+ if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
595
+ stored = {
596
+ activeProviderId: parsed.activeProviderId,
597
+ modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
598
+ customEndpoints: mergeCustomEndpoints(parsed.customEndpoints)
599
+ };
600
+ }
601
+ } catch {
602
+ }
603
+ }
604
+ const base = stored ?? {
605
+ ...DEFAULTS,
606
+ modelByProvider: { ...DEFAULTS.modelByProvider },
607
+ customEndpoints: { ...DEFAULTS.customEndpoints }
608
+ };
609
+ if (envActive && PROVIDERS.some((p3) => p3.id === envActive)) {
610
+ base.activeProviderId = envActive;
611
+ }
612
+ if (envModel && envModel.trim().length > 0) {
613
+ base.modelByProvider[base.activeProviderId] = envModel;
614
+ }
615
+ return base;
616
+ }
617
+ function writeProviderConfig(config2) {
618
+ const file2 = getProviderConfigPath();
619
+ mkdirSync2(path3.dirname(file2), { recursive: true });
620
+ writeFileSync2(file2, JSON.stringify(config2, null, 2), { encoding: "utf-8", mode: 384 });
621
+ }
622
+ function mergeCustomEndpoints(raw) {
623
+ if (!raw || typeof raw !== "object") return {};
624
+ const result = {};
625
+ const validIds = new Set(PROVIDERS.map((p3) => p3.id));
626
+ for (const [key, value] of Object.entries(raw)) {
627
+ if (!validIds.has(key)) continue;
628
+ if (typeof value !== "string") continue;
629
+ const trimmed = value.trim();
630
+ if (trimmed.length === 0) continue;
631
+ result[key] = trimmed;
632
+ }
633
+ return result;
634
+ }
635
+ function getCustomEndpoint(id) {
636
+ return getProviderConfig().customEndpoints[id];
637
+ }
638
+ function setCustomEndpoint(id, url2) {
639
+ const spec = PROVIDERS.find((p3) => p3.id === id);
640
+ if (!spec) {
641
+ throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
642
+ }
643
+ const trimmed = url2.trim();
644
+ if (trimmed.length === 0) {
645
+ throw new Error("Custom endpoint URL cannot be empty. Use clearCustomEndpoint() to remove.");
646
+ }
647
+ try {
648
+ new URL(trimmed);
649
+ } catch {
650
+ throw new Error(`Invalid custom endpoint URL: "${url2}"`);
651
+ }
652
+ const config2 = getProviderConfig();
653
+ config2.customEndpoints[id] = trimmed;
654
+ writeProviderConfig(config2);
655
+ }
656
+ function clearCustomEndpoint(id) {
657
+ const spec = PROVIDERS.find((p3) => p3.id === id);
658
+ if (!spec) {
659
+ throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
660
+ }
661
+ const config2 = getProviderConfig();
662
+ if (!(id in config2.customEndpoints)) return;
663
+ delete config2.customEndpoints[id];
664
+ writeProviderConfig(config2);
665
+ }
666
+ function setActiveProviderId(id) {
667
+ const spec = PROVIDERS.find((p3) => p3.id === id);
668
+ if (!spec) {
669
+ throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
670
+ }
671
+ const config2 = getProviderConfig();
672
+ config2.activeProviderId = id;
673
+ if (!config2.modelByProvider[id]) {
674
+ config2.modelByProvider[id] = DEFAULTS.modelByProvider[id];
675
+ }
676
+ writeProviderConfig(config2);
677
+ }
678
+ function setModelForProvider(id, model) {
679
+ const spec = PROVIDERS.find((p3) => p3.id === id);
680
+ if (!spec) {
681
+ throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
682
+ }
683
+ if (!model || model.trim().length === 0) {
684
+ throw new Error("Model name cannot be empty.");
685
+ }
686
+ const config2 = getProviderConfig();
687
+ config2.modelByProvider[id] = model.trim();
688
+ writeProviderConfig(config2);
689
+ }
690
+ function getModelForProvider(id) {
691
+ const config2 = getProviderConfig();
692
+ return config2.modelByProvider[id] ?? DEFAULTS.modelByProvider[id] ?? "";
693
+ }
694
+ function getActiveProvider() {
695
+ const config2 = getProviderConfig();
696
+ const spec = PROVIDERS.find((p3) => p3.id === config2.activeProviderId);
697
+ if (!spec) throw new Error(`Invalid active provider id in config: ${config2.activeProviderId}`);
698
+ return spec;
699
+ }
700
+ function getActiveModel() {
701
+ const config2 = getProviderConfig();
702
+ return config2.modelByProvider[config2.activeProviderId] ?? DEFAULTS.modelByProvider[config2.activeProviderId] ?? "";
703
+ }
704
+ async function loadProviderConfig() {
705
+ const file2 = getProviderConfigPath();
706
+ try {
707
+ const raw = await fs2.readFile(file2, "utf-8");
708
+ const parsed = JSON.parse(raw);
709
+ if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
710
+ return {
711
+ activeProviderId: parsed.activeProviderId,
712
+ modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
713
+ customEndpoints: mergeCustomEndpoints(parsed.customEndpoints)
714
+ };
715
+ }
716
+ } catch {
717
+ }
718
+ return {
719
+ ...DEFAULTS,
720
+ modelByProvider: { ...DEFAULTS.modelByProvider },
721
+ customEndpoints: { ...DEFAULTS.customEndpoints }
722
+ };
723
+ }
724
+ var DEFAULTS;
725
+ var init_providerConfig = __esm({
726
+ "src/cli/providerConfig.ts"() {
727
+ "use strict";
728
+ init_keyStore();
729
+ DEFAULTS = {
730
+ activeProviderId: "openai-compatible",
731
+ modelByProvider: {
732
+ "openai-compatible": "grok-4",
733
+ "minimax": "MiniMax-M2.5",
734
+ "glm": "glm-4.6",
735
+ "grok": "grok-4",
736
+ "custom": ""
737
+ },
738
+ customEndpoints: {}
739
+ };
740
+ }
741
+ });
742
+
564
743
  // packages/core/dist/agents/skills.js
565
744
  function getSkillsByCategory(cat) {
566
745
  return SKILL_CATALOG.filter((s) => s.category === cat);
@@ -16269,8 +16448,8 @@ var init_toolTypes = __esm({
16269
16448
  });
16270
16449
 
16271
16450
  // packages/core/dist/core/tools/builtin/filesystem.js
16272
- import { promises as fs3 } from "node:fs";
16273
- import path4 from "node:path";
16451
+ import { promises as fs4 } from "node:fs";
16452
+ import path5 from "node:path";
16274
16453
  var ReadFileArgsSchema, readFileTool, WriteFileArgsSchema, writeFileTool, EditFileArgsSchema, editFileTool;
16275
16454
  var init_filesystem = __esm({
16276
16455
  "packages/core/dist/core/tools/builtin/filesystem.js"() {
@@ -16291,8 +16470,8 @@ var init_filesystem = __esm({
16291
16470
  inputSchema: ReadFileArgsSchema,
16292
16471
  execute: async (args, ctx) => {
16293
16472
  try {
16294
- const absPath = path4.isAbsolute(args.path) ? args.path : path4.join(ctx.cwd, args.path);
16295
- const buf = await fs3.readFile(absPath, { encoding: "utf-8", signal: ctx.signal });
16473
+ const absPath = path5.isAbsolute(args.path) ? args.path : path5.join(ctx.cwd, args.path);
16474
+ const buf = await fs4.readFile(absPath, { encoding: "utf-8", signal: ctx.signal });
16296
16475
  const content = typeof buf === "string" ? buf : buf.toString("utf-8");
16297
16476
  const truncated = content.length > args.maxBytes ? content.slice(0, args.maxBytes) : content;
16298
16477
  const lines = truncated.split("\n");
@@ -16324,11 +16503,11 @@ var init_filesystem = __esm({
16324
16503
  inputSchema: WriteFileArgsSchema,
16325
16504
  execute: async (args, ctx) => {
16326
16505
  try {
16327
- const absPath = path4.isAbsolute(args.path) ? args.path : path4.join(ctx.cwd, args.path);
16506
+ const absPath = path5.isAbsolute(args.path) ? args.path : path5.join(ctx.cwd, args.path);
16328
16507
  if (args.createDirs) {
16329
- await fs3.mkdir(path4.dirname(absPath), { recursive: true });
16508
+ await fs4.mkdir(path5.dirname(absPath), { recursive: true });
16330
16509
  }
16331
- await fs3.writeFile(absPath, args.content, { encoding: "utf-8", signal: ctx.signal });
16510
+ await fs4.writeFile(absPath, args.content, { encoding: "utf-8", signal: ctx.signal });
16332
16511
  return typedOk({ path: absPath, bytesWritten: args.content.length });
16333
16512
  } catch (err) {
16334
16513
  return typedErr(err instanceof Error ? err.message : String(err));
@@ -16349,8 +16528,8 @@ var init_filesystem = __esm({
16349
16528
  inputSchema: EditFileArgsSchema,
16350
16529
  execute: async (args, ctx) => {
16351
16530
  try {
16352
- const absPath = path4.isAbsolute(args.path) ? args.path : path4.join(ctx.cwd, args.path);
16353
- const content = await fs3.readFile(absPath, { encoding: "utf-8", signal: ctx.signal });
16531
+ const absPath = path5.isAbsolute(args.path) ? args.path : path5.join(ctx.cwd, args.path);
16532
+ const content = await fs4.readFile(absPath, { encoding: "utf-8", signal: ctx.signal });
16354
16533
  const text = typeof content === "string" ? content : content.toString("utf-8");
16355
16534
  let occurrences = 0;
16356
16535
  let newContent;
@@ -16369,7 +16548,7 @@ var init_filesystem = __esm({
16369
16548
  }
16370
16549
  }
16371
16550
  if (occurrences > 0) {
16372
- await fs3.writeFile(absPath, newContent, { encoding: "utf-8", signal: ctx.signal });
16551
+ await fs4.writeFile(absPath, newContent, { encoding: "utf-8", signal: ctx.signal });
16373
16552
  }
16374
16553
  return typedOk({ path: absPath, occurrencesReplaced: occurrences });
16375
16554
  } catch (err) {
@@ -16381,7 +16560,7 @@ var init_filesystem = __esm({
16381
16560
  });
16382
16561
 
16383
16562
  // packages/core/dist/core/tools/builtin/shellResolver.js
16384
- import { existsSync as existsSync3 } from "node:fs";
16563
+ import { existsSync as existsSync4 } from "node:fs";
16385
16564
  import { spawnSync } from "node:child_process";
16386
16565
  function resolveShell(forceReResolve = false) {
16387
16566
  if (memoized && !forceReResolve)
@@ -16428,7 +16607,7 @@ function resolveBashWindows() {
16428
16607
  }
16429
16608
  function existsSyncSafe(p3) {
16430
16609
  try {
16431
- return existsSync3(p3);
16610
+ return existsSync4(p3);
16432
16611
  } catch {
16433
16612
  return false;
16434
16613
  }
@@ -16535,8 +16714,8 @@ var init_shell = __esm({
16535
16714
  });
16536
16715
 
16537
16716
  // packages/core/dist/core/tools/builtin/_walk.js
16538
- import { promises as fs4 } from "node:fs";
16539
- import path5 from "node:path";
16717
+ import { promises as fs5 } from "node:fs";
16718
+ import path6 from "node:path";
16540
16719
  function escapeRegex2(p3) {
16541
16720
  return p3.replace(REGEX_ESCAPE, "\\$&");
16542
16721
  }
@@ -16587,7 +16766,7 @@ async function walk(dir, baseRel, depth, maxDepth, exclude, entries, signal) {
16587
16766
  return;
16588
16767
  let dirents;
16589
16768
  try {
16590
- dirents = await fs4.readdir(dir, { withFileTypes: true });
16769
+ dirents = await fs5.readdir(dir, { withFileTypes: true });
16591
16770
  } catch {
16592
16771
  return;
16593
16772
  }
@@ -16603,7 +16782,7 @@ async function walk(dir, baseRel, depth, maxDepth, exclude, entries, signal) {
16603
16782
  type: isDir ? "directory" : dirent.isFile() ? "file" : "other"
16604
16783
  });
16605
16784
  if (isDir && depth < maxDepth) {
16606
- await walk(path5.join(dir, dirent.name), rel2, depth + 1, maxDepth, exclude, entries, signal);
16785
+ await walk(path6.join(dir, dirent.name), rel2, depth + 1, maxDepth, exclude, entries, signal);
16607
16786
  }
16608
16787
  }
16609
16788
  }
@@ -16641,12 +16820,12 @@ var init_walk = __esm({
16641
16820
  });
16642
16821
 
16643
16822
  // packages/core/dist/core/tools/builtin/search.js
16644
- import { promises as fs5 } from "node:fs";
16645
- import path6 from "node:path";
16823
+ import { promises as fs6 } from "node:fs";
16824
+ import path7 from "node:path";
16646
16825
  async function searchFile(absPath, relPath, regex, contextLines, remainingSlots) {
16647
16826
  let buf;
16648
16827
  try {
16649
- buf = await fs5.readFile(absPath, "utf-8");
16828
+ buf = await fs6.readFile(absPath, "utf-8");
16650
16829
  } catch {
16651
16830
  return { matches: [], total: 0, truncated: false };
16652
16831
  }
@@ -16680,7 +16859,7 @@ async function searchFile(absPath, relPath, regex, contextLines, remainingSlots)
16680
16859
  }
16681
16860
  async function isDirectory(p3) {
16682
16861
  try {
16683
- const stat = await fs5.stat(p3);
16862
+ const stat = await fs6.stat(p3);
16684
16863
  return stat.isDirectory();
16685
16864
  } catch {
16686
16865
  return false;
@@ -16723,7 +16902,7 @@ var init_search = __esm({
16723
16902
  inputSchema: GrepContentArgsSchema,
16724
16903
  execute: async (args, ctx) => {
16725
16904
  try {
16726
- const absRoot = path6.isAbsolute(args.path) ? args.path : path6.join(ctx.cwd, args.path);
16905
+ const absRoot = path7.isAbsolute(args.path) ? args.path : path7.join(ctx.cwd, args.path);
16727
16906
  const regex = new RegExp(args.pattern, "gm");
16728
16907
  if (!await isDirectory(absRoot)) {
16729
16908
  const single = await searchFile(absRoot, args.path, regex, args.contextLines, args.maxMatches);
@@ -16749,7 +16928,7 @@ var init_search = __esm({
16749
16928
  truncated = true;
16750
16929
  break;
16751
16930
  }
16752
- const absFile = path6.join(absRoot, entry.name);
16931
+ const absFile = path7.join(absRoot, entry.name);
16753
16932
  const result = await searchFile(absFile, entry.name, regex, args.contextLines, args.maxMatches - allMatches.length);
16754
16933
  filesSearched++;
16755
16934
  totalMatches += result.total;
@@ -16773,7 +16952,7 @@ var init_search = __esm({
16773
16952
  });
16774
16953
 
16775
16954
  // packages/core/dist/core/tools/builtin/listFiles.js
16776
- import path7 from "node:path";
16955
+ import path8 from "node:path";
16777
16956
  var ListFilesArgsSchema, listFilesTool;
16778
16957
  var init_listFiles = __esm({
16779
16958
  "packages/core/dist/core/tools/builtin/listFiles.js"() {
@@ -16797,7 +16976,7 @@ var init_listFiles = __esm({
16797
16976
  inputSchema: ListFilesArgsSchema,
16798
16977
  execute: async (args, ctx) => {
16799
16978
  try {
16800
- const target = args.path ? path7.isAbsolute(args.path) ? args.path : path7.join(ctx.cwd, args.path) : ctx.cwd;
16979
+ const target = args.path ? path8.isAbsolute(args.path) ? args.path : path8.join(ctx.cwd, args.path) : ctx.cwd;
16801
16980
  const entries = [];
16802
16981
  await walk(target, "", 0, args.maxDepth - 1, args.exclude, entries, ctx.signal);
16803
16982
  entries.sort((a, b) => {
@@ -16819,8 +16998,8 @@ var init_listFiles = __esm({
16819
16998
  });
16820
16999
 
16821
17000
  // packages/core/dist/core/tools/builtin/diff.js
16822
- import { promises as fs6 } from "node:fs";
16823
- import path8 from "node:path";
17001
+ import { promises as fs7 } from "node:fs";
17002
+ import path9 from "node:path";
16824
17003
  function lcsTable(a, b) {
16825
17004
  const m = a.length;
16826
17005
  const n = b.length;
@@ -16990,10 +17169,10 @@ var init_diff = __esm({
16990
17169
  inputSchema: ShowDiffArgsSchema,
16991
17170
  execute: async (args, ctx) => {
16992
17171
  try {
16993
- const absPath = path8.isAbsolute(args.path) ? args.path : path8.join(ctx.cwd, args.path);
17172
+ const absPath = path9.isAbsolute(args.path) ? args.path : path9.join(ctx.cwd, args.path);
16994
17173
  let current = "";
16995
17174
  try {
16996
- current = await fs6.readFile(absPath, "utf-8");
17175
+ current = await fs7.readFile(absPath, "utf-8");
16997
17176
  } catch (err) {
16998
17177
  if (err.code !== "ENOENT") {
16999
17178
  return typedErr(err instanceof Error ? err.message : String(err));
@@ -17113,10 +17292,10 @@ var init_diff = __esm({
17113
17292
  inputSchema: ApplyDiffArgsSchema,
17114
17293
  execute: async (args, ctx) => {
17115
17294
  try {
17116
- const absPath = path8.isAbsolute(args.path) ? args.path : path8.join(ctx.cwd, args.path);
17295
+ const absPath = path9.isAbsolute(args.path) ? args.path : path9.join(ctx.cwd, args.path);
17117
17296
  let current = "";
17118
17297
  try {
17119
- current = await fs6.readFile(absPath, "utf-8");
17298
+ current = await fs7.readFile(absPath, "utf-8");
17120
17299
  } catch (err) {
17121
17300
  if (err.code !== "ENOENT") {
17122
17301
  return typedErr(err instanceof Error ? err.message : String(err));
@@ -17136,8 +17315,8 @@ var init_diff = __esm({
17136
17315
  const finalContent = result.lines.join("\n");
17137
17316
  const ok = result.hunksSkipped === 0;
17138
17317
  if (ok && !args.dryRun) {
17139
- await fs6.mkdir(path8.dirname(absPath), { recursive: true });
17140
- await fs6.writeFile(absPath, finalContent, "utf-8");
17318
+ await fs7.mkdir(path9.dirname(absPath), { recursive: true });
17319
+ await fs7.writeFile(absPath, finalContent, "utf-8");
17141
17320
  }
17142
17321
  return typedOk({
17143
17322
  path: absPath,
@@ -17875,185 +18054,6 @@ var init_skills2 = __esm({
17875
18054
  }
17876
18055
  });
17877
18056
 
17878
- // src/cli/providerConfig.ts
17879
- var providerConfig_exports = {};
17880
- __export(providerConfig_exports, {
17881
- clearCustomEndpoint: () => clearCustomEndpoint,
17882
- getActiveModel: () => getActiveModel,
17883
- getActiveProvider: () => getActiveProvider,
17884
- getCustomEndpoint: () => getCustomEndpoint,
17885
- getModelForProvider: () => getModelForProvider,
17886
- getProviderConfig: () => getProviderConfig,
17887
- getProviderConfigPath: () => getProviderConfigPath,
17888
- loadProviderConfig: () => loadProviderConfig,
17889
- setActiveProviderId: () => setActiveProviderId,
17890
- setCustomEndpoint: () => setCustomEndpoint,
17891
- setModelForProvider: () => setModelForProvider
17892
- });
17893
- import { promises as fs7, existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
17894
- import path9 from "node:path";
17895
- import os2 from "node:os";
17896
- function getProviderConfigPath() {
17897
- return process.env.ANATHEMA_PROVIDER_CONFIG_FILE ?? path9.join(os2.homedir(), ".tmp", "zelari-code", "provider.json");
17898
- }
17899
- function getProviderConfig() {
17900
- const envActive = process.env.ANATHEMA_ACTIVE_PROVIDER;
17901
- const envModel = process.env.OPENAI_MODEL;
17902
- const file2 = getProviderConfigPath();
17903
- let stored = null;
17904
- if (existsSync4(file2)) {
17905
- try {
17906
- const raw = readFileSync3(file2, "utf-8");
17907
- const parsed = JSON.parse(raw);
17908
- if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
17909
- stored = {
17910
- activeProviderId: parsed.activeProviderId,
17911
- modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
17912
- customEndpoints: mergeCustomEndpoints(parsed.customEndpoints)
17913
- };
17914
- }
17915
- } catch {
17916
- }
17917
- }
17918
- const base = stored ?? {
17919
- ...DEFAULTS,
17920
- modelByProvider: { ...DEFAULTS.modelByProvider },
17921
- customEndpoints: { ...DEFAULTS.customEndpoints }
17922
- };
17923
- if (envActive && PROVIDERS.some((p3) => p3.id === envActive)) {
17924
- base.activeProviderId = envActive;
17925
- }
17926
- if (envModel && envModel.trim().length > 0) {
17927
- base.modelByProvider[base.activeProviderId] = envModel;
17928
- }
17929
- return base;
17930
- }
17931
- function writeProviderConfig(config2) {
17932
- const file2 = getProviderConfigPath();
17933
- mkdirSync3(path9.dirname(file2), { recursive: true });
17934
- writeFileSync3(file2, JSON.stringify(config2, null, 2), { encoding: "utf-8", mode: 384 });
17935
- }
17936
- function mergeCustomEndpoints(raw) {
17937
- if (!raw || typeof raw !== "object") return {};
17938
- const result = {};
17939
- const validIds = new Set(PROVIDERS.map((p3) => p3.id));
17940
- for (const [key, value] of Object.entries(raw)) {
17941
- if (!validIds.has(key)) continue;
17942
- if (typeof value !== "string") continue;
17943
- const trimmed = value.trim();
17944
- if (trimmed.length === 0) continue;
17945
- result[key] = trimmed;
17946
- }
17947
- return result;
17948
- }
17949
- function getCustomEndpoint(id) {
17950
- return getProviderConfig().customEndpoints[id];
17951
- }
17952
- function setCustomEndpoint(id, url2) {
17953
- const spec = PROVIDERS.find((p3) => p3.id === id);
17954
- if (!spec) {
17955
- throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
17956
- }
17957
- const trimmed = url2.trim();
17958
- if (trimmed.length === 0) {
17959
- throw new Error("Custom endpoint URL cannot be empty. Use clearCustomEndpoint() to remove.");
17960
- }
17961
- try {
17962
- new URL(trimmed);
17963
- } catch {
17964
- throw new Error(`Invalid custom endpoint URL: "${url2}"`);
17965
- }
17966
- const config2 = getProviderConfig();
17967
- config2.customEndpoints[id] = trimmed;
17968
- writeProviderConfig(config2);
17969
- }
17970
- function clearCustomEndpoint(id) {
17971
- const spec = PROVIDERS.find((p3) => p3.id === id);
17972
- if (!spec) {
17973
- throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
17974
- }
17975
- const config2 = getProviderConfig();
17976
- if (!(id in config2.customEndpoints)) return;
17977
- delete config2.customEndpoints[id];
17978
- writeProviderConfig(config2);
17979
- }
17980
- function setActiveProviderId(id) {
17981
- const spec = PROVIDERS.find((p3) => p3.id === id);
17982
- if (!spec) {
17983
- throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
17984
- }
17985
- const config2 = getProviderConfig();
17986
- config2.activeProviderId = id;
17987
- if (!config2.modelByProvider[id]) {
17988
- config2.modelByProvider[id] = DEFAULTS.modelByProvider[id];
17989
- }
17990
- writeProviderConfig(config2);
17991
- }
17992
- function setModelForProvider(id, model) {
17993
- const spec = PROVIDERS.find((p3) => p3.id === id);
17994
- if (!spec) {
17995
- throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
17996
- }
17997
- if (!model || model.trim().length === 0) {
17998
- throw new Error("Model name cannot be empty.");
17999
- }
18000
- const config2 = getProviderConfig();
18001
- config2.modelByProvider[id] = model.trim();
18002
- writeProviderConfig(config2);
18003
- }
18004
- function getModelForProvider(id) {
18005
- const config2 = getProviderConfig();
18006
- return config2.modelByProvider[id] ?? DEFAULTS.modelByProvider[id] ?? "";
18007
- }
18008
- function getActiveProvider() {
18009
- const config2 = getProviderConfig();
18010
- const spec = PROVIDERS.find((p3) => p3.id === config2.activeProviderId);
18011
- if (!spec) throw new Error(`Invalid active provider id in config: ${config2.activeProviderId}`);
18012
- return spec;
18013
- }
18014
- function getActiveModel() {
18015
- const config2 = getProviderConfig();
18016
- return config2.modelByProvider[config2.activeProviderId] ?? DEFAULTS.modelByProvider[config2.activeProviderId] ?? "";
18017
- }
18018
- async function loadProviderConfig() {
18019
- const file2 = getProviderConfigPath();
18020
- try {
18021
- const raw = await fs7.readFile(file2, "utf-8");
18022
- const parsed = JSON.parse(raw);
18023
- if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
18024
- return {
18025
- activeProviderId: parsed.activeProviderId,
18026
- modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
18027
- customEndpoints: mergeCustomEndpoints(parsed.customEndpoints)
18028
- };
18029
- }
18030
- } catch {
18031
- }
18032
- return {
18033
- ...DEFAULTS,
18034
- modelByProvider: { ...DEFAULTS.modelByProvider },
18035
- customEndpoints: { ...DEFAULTS.customEndpoints }
18036
- };
18037
- }
18038
- var DEFAULTS;
18039
- var init_providerConfig = __esm({
18040
- "src/cli/providerConfig.ts"() {
18041
- "use strict";
18042
- init_keyStore();
18043
- DEFAULTS = {
18044
- activeProviderId: "openai-compatible",
18045
- modelByProvider: {
18046
- "openai-compatible": "grok-4",
18047
- "minimax": "MiniMax-M2.5",
18048
- "glm": "glm-4.6",
18049
- "grok": "grok-4",
18050
- "custom": ""
18051
- },
18052
- customEndpoints: {}
18053
- };
18054
- }
18055
- });
18056
-
18057
18057
  // packages/core/dist/shared/events.js
18058
18058
  function createBrainEvent(type, sessionId, data) {
18059
18059
  return {
@@ -23162,25 +23162,37 @@ function FileRow({ file: file2, pathWidth }) {
23162
23162
  }
23163
23163
 
23164
23164
  // src/cli/modelDiscovery.ts
23165
- import { promises as fs2, existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
23165
+ import { promises as fs3, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
23166
23166
  import { homedir } from "node:os";
23167
- import path3 from "node:path";
23167
+ import path4 from "node:path";
23168
23168
  var PROVIDER_BASE_URLS = {
23169
23169
  "grok": "https://api.x.ai/v1",
23170
- "glm": "https://api.z.ai/api/paas/v4",
23171
- "minimax": "https://api.minimaxi.chat/v1",
23172
- "openai-compatible": "https://api.openai.com/v1"
23170
+ // Must match PROVIDER_ENDPOINTS in provider/openai-compatible.ts (chat host).
23171
+ "glm": "https://api.z.ai/api/coding/paas/v4",
23172
+ "minimax": "https://api.minimax.io/v1",
23173
+ "openai-compatible": "https://api.x.ai/v1"
23173
23174
  };
23175
+ async function resolveDiscoveryBaseUrl(provider, options) {
23176
+ if (options.baseUrl) return options.baseUrl;
23177
+ const { getCustomEndpoint: getCustomEndpoint2 } = await Promise.resolve().then(() => (init_providerConfig(), providerConfig_exports));
23178
+ const custom2 = getCustomEndpoint2(provider);
23179
+ if (custom2) return custom2;
23180
+ if (provider === "openai-compatible") {
23181
+ const envBase = process.env.OPENAI_BASE_URL;
23182
+ if (envBase && envBase.trim().length > 0) return envBase;
23183
+ }
23184
+ return PROVIDER_BASE_URLS[provider];
23185
+ }
23174
23186
  function defaultModelsFilePath() {
23175
- return process.env.ANATHEMA_MODELS_FILE ?? path3.join(homedir(), ".tmp", "zelari-code", "models.json");
23187
+ return process.env.ANATHEMA_MODELS_FILE ?? path4.join(homedir(), ".tmp", "zelari-code", "models.json");
23176
23188
  }
23177
23189
  function getModelsFilePath() {
23178
23190
  return defaultModelsFilePath();
23179
23191
  }
23180
23192
  function loadModelsRegistry(file2 = getModelsFilePath()) {
23181
- if (!existsSync2(file2)) return {};
23193
+ if (!existsSync3(file2)) return {};
23182
23194
  try {
23183
- const raw = readFileSync2(file2, "utf-8");
23195
+ const raw = readFileSync3(file2, "utf-8");
23184
23196
  const parsed = JSON.parse(raw);
23185
23197
  if (!parsed || typeof parsed !== "object") return {};
23186
23198
  return parsed;
@@ -23207,10 +23219,10 @@ async function readModifyWriteRegistry(mutator, file2 = getModelsFilePath()) {
23207
23219
  return withRegistryLock(async () => {
23208
23220
  const onDisk = loadModelsRegistry(file2);
23209
23221
  const merged = mutator(onDisk);
23210
- await fs2.mkdir(path3.dirname(file2), { recursive: true });
23222
+ await fs3.mkdir(path4.dirname(file2), { recursive: true });
23211
23223
  const tmp = `${file2}.tmp-${process.pid}-${Date.now()}`;
23212
- await fs2.writeFile(tmp, JSON.stringify(merged, null, 2), "utf-8");
23213
- await fs2.rename(tmp, file2);
23224
+ await fs3.writeFile(tmp, JSON.stringify(merged, null, 2), "utf-8");
23225
+ await fs3.rename(tmp, file2);
23214
23226
  return merged;
23215
23227
  });
23216
23228
  }
@@ -23242,7 +23254,13 @@ function parseOpenAIModelsResponse(json2, baseUrl) {
23242
23254
  return models;
23243
23255
  }
23244
23256
  async function discoverModelsForProvider(provider, options = {}) {
23245
- const baseUrl = options.baseUrl ?? PROVIDER_BASE_URLS[provider];
23257
+ const baseUrl = await resolveDiscoveryBaseUrl(provider, options);
23258
+ if (!baseUrl || baseUrl.trim().length === 0) {
23259
+ throw new ModelDiscoveryError(
23260
+ `No base URL for provider "${provider}" \u2014 set one with /provider custom <url> before discovering models`,
23261
+ "no_base_url"
23262
+ );
23263
+ }
23246
23264
  const url2 = `${baseUrl.replace(/\/$/, "")}/models`;
23247
23265
  const authToken = await resolveAuthToken(provider, options);
23248
23266
  const fetchImpl = options.fetchImpl ?? fetch;
@@ -25970,8 +25988,10 @@ init_keyStore();
25970
25988
  init_providerConfig();
25971
25989
  var PROVIDER_ENDPOINTS = {
25972
25990
  "openai-compatible": "https://api.x.ai/v1",
25973
- "minimax": "https://api.MiniMax.chat/v1",
25974
- "glm": "https://api.z.ai/v1",
25991
+ "minimax": "https://api.minimax.io/v1",
25992
+ // GLM defaults to the Coding Plan endpoint (flat-rate coding subscription).
25993
+ // Pay-per-token API users can override with `/provider custom https://api.z.ai/api/paas/v4`.
25994
+ "glm": "https://api.z.ai/api/coding/paas/v4",
25975
25995
  "grok": "https://api.x.ai/v1",
25976
25996
  "custom": ""
25977
25997
  };
@@ -28534,7 +28554,7 @@ async function handleLoginKey(ctx, providerId, key) {
28534
28554
  `[login] ${displayName} key stored (${maskKey(key)}). Active provider switched to ${displayName} \u2014 try a prompt now.`
28535
28555
  );
28536
28556
  const discoveryProvider = providerId;
28537
- if (["grok", "glm", "minimax", "openai-compatible"].includes(discoveryProvider)) {
28557
+ if (DISCOVERABLE_PROVIDERS.includes(discoveryProvider)) {
28538
28558
  discoverModelsInBackground(discoveryProvider, {
28539
28559
  onError: (err) => appendSystem(
28540
28560
  ctx.setMessages,
@@ -30190,7 +30210,7 @@ function loadSkillMdSkills(projectRoot = process.cwd(), options = {}) {
30190
30210
 
30191
30211
  // src/cli/main.ts
30192
30212
  init_skills2();
30193
- var VERSION = "0.7.10";
30213
+ var VERSION = "0.7.11";
30194
30214
  async function backgroundUpdateCheck() {
30195
30215
  if (process.env.ANATHEMA_DEV === "1") return;
30196
30216
  await new Promise((resolve) => setTimeout(resolve, 3e3));