anantham-v2 2.0.2 → 2.0.4

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 (67) hide show
  1. package/dist/bin/anantham.js +10 -1
  2. package/dist/bin/anantham.js.map +1 -1
  3. package/dist/cli/command-registry.d.ts +8 -0
  4. package/dist/cli/command-registry.d.ts.map +1 -1
  5. package/dist/cli/command-registry.js +363 -89
  6. package/dist/cli/command-registry.js.map +1 -1
  7. package/dist/domain/tui.d.ts +1 -1
  8. package/dist/domain/tui.d.ts.map +1 -1
  9. package/dist/domain/tui.js +1 -0
  10. package/dist/domain/tui.js.map +1 -1
  11. package/dist/models/adapters/openai-compatible-adapter.d.ts.map +1 -1
  12. package/dist/models/adapters/openai-compatible-adapter.js +2 -1
  13. package/dist/models/adapters/openai-compatible-adapter.js.map +1 -1
  14. package/dist/models/provider-registry.d.ts +2 -2
  15. package/dist/persistence/index.d.ts +2 -0
  16. package/dist/persistence/index.d.ts.map +1 -1
  17. package/dist/persistence/index.js +2 -0
  18. package/dist/persistence/index.js.map +1 -1
  19. package/dist/persistence/model-catalog-cache.d.ts +86 -0
  20. package/dist/persistence/model-catalog-cache.d.ts.map +1 -0
  21. package/dist/persistence/model-catalog-cache.js +398 -0
  22. package/dist/persistence/model-catalog-cache.js.map +1 -0
  23. package/dist/persistence/token-metrics-manager.d.ts +88 -0
  24. package/dist/persistence/token-metrics-manager.d.ts.map +1 -0
  25. package/dist/persistence/token-metrics-manager.js +272 -0
  26. package/dist/persistence/token-metrics-manager.js.map +1 -0
  27. package/dist/persistence/user-config-manager.d.ts +8 -0
  28. package/dist/persistence/user-config-manager.d.ts.map +1 -1
  29. package/dist/persistence/user-config-manager.js +50 -1
  30. package/dist/persistence/user-config-manager.js.map +1 -1
  31. package/dist/tui/ansi-gradient.d.ts +43 -0
  32. package/dist/tui/ansi-gradient.d.ts.map +1 -0
  33. package/dist/tui/ansi-gradient.js +131 -0
  34. package/dist/tui/ansi-gradient.js.map +1 -0
  35. package/dist/tui/command-palette.d.ts +20 -0
  36. package/dist/tui/command-palette.d.ts.map +1 -0
  37. package/dist/tui/command-palette.js +241 -0
  38. package/dist/tui/command-palette.js.map +1 -0
  39. package/dist/tui/model-accordion-browser.d.ts +80 -0
  40. package/dist/tui/model-accordion-browser.d.ts.map +1 -0
  41. package/dist/tui/model-accordion-browser.js +487 -0
  42. package/dist/tui/model-accordion-browser.js.map +1 -0
  43. package/dist/tui/terminal-layout.d.ts +4 -0
  44. package/dist/tui/terminal-layout.d.ts.map +1 -1
  45. package/dist/tui/terminal-layout.js +30 -0
  46. package/dist/tui/terminal-layout.js.map +1 -1
  47. package/dist/tui/terminal-logo-renderer.d.ts +63 -0
  48. package/dist/tui/terminal-logo-renderer.d.ts.map +1 -0
  49. package/dist/tui/terminal-logo-renderer.js +300 -0
  50. package/dist/tui/terminal-logo-renderer.js.map +1 -0
  51. package/dist/tui/token-dashboard-renderer.d.ts +6 -0
  52. package/dist/tui/token-dashboard-renderer.d.ts.map +1 -0
  53. package/dist/tui/token-dashboard-renderer.js +115 -0
  54. package/dist/tui/token-dashboard-renderer.js.map +1 -0
  55. package/dist/tui/tui-controller.d.ts +14 -0
  56. package/dist/tui/tui-controller.d.ts.map +1 -1
  57. package/dist/tui/tui-controller.js +192 -7
  58. package/dist/tui/tui-controller.js.map +1 -1
  59. package/dist/tui/tui-renderer.d.ts +7 -1
  60. package/dist/tui/tui-renderer.d.ts.map +1 -1
  61. package/dist/tui/tui-renderer.js +52 -10
  62. package/dist/tui/tui-renderer.js.map +1 -1
  63. package/dist/tui/tui-sanitizer.d.ts +4 -0
  64. package/dist/tui/tui-sanitizer.d.ts.map +1 -1
  65. package/dist/tui/tui-sanitizer.js +6 -0
  66. package/dist/tui/tui-sanitizer.js.map +1 -1
  67. package/package.json +1 -1
@@ -53,6 +53,14 @@ async function main() {
53
53
  else if (arg === "--session" && args[i + 1]) {
54
54
  initialSessionId = args[++i];
55
55
  }
56
+ else if (arg === "--logo" && args[i + 1]) {
57
+ const customLogo = args[++i];
58
+ process.env.ANANTHAM_LOGO_PATH = customLogo;
59
+ try {
60
+ UserConfigManager.getInstance().setLogoPath(customLogo);
61
+ }
62
+ catch { }
63
+ }
56
64
  else if (arg === "--help" || arg === "-h") {
57
65
  console.log(`
58
66
  Anantham V2 — Programmable AI Agent Operating Environment
@@ -68,13 +76,14 @@ Options:
68
76
  -e, --eval <cmd> Execute single slash command and exit
69
77
  --project <id> Initial active project ID
70
78
  --session <id> Initial active session ID
79
+ --logo <path> Custom logo image path (PNG/Sixel/ANSI)
71
80
  -h, --help Show this help message
72
81
  -v, --version Show runtime version
73
82
  `);
74
83
  process.exit(0);
75
84
  }
76
85
  else if (arg === "--version" || arg === "-v") {
77
- console.log("2.0.2");
86
+ console.log("2.0.4");
78
87
  process.exit(0);
79
88
  }
80
89
  else if (!arg.startsWith("-") && !executeCmd) {
@@ -1 +1 @@
1
- {"version":3,"file":"anantham.js","sourceRoot":"","sources":["../../src/bin/anantham.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"anantham.js","sourceRoot":"","sources":["../../src/bin/anantham.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import { SessionResumeEngine } from "../resume/session-resume-engine.js";
10
10
  import { ToolRegistry } from "../tools/tool-registry.js";
11
11
  import { PolicyEngine } from "../policy/policy-engine.js";
12
12
  import { TaskClaimManager } from "../tasks/task-claim-manager.js";
13
+ import { UserConfigManager } from "../persistence/user-config-manager.js";
13
14
  export type CommandHandler = (cmd: ParsedCommand, controller: SessionController) => Promise<CommandExecutionResult> | CommandExecutionResult;
14
15
  export interface CommandRegistryOptions {
15
16
  sessionController: SessionController;
@@ -24,6 +25,13 @@ export interface CommandRegistryOptions {
24
25
  claimManager?: TaskClaimManager;
25
26
  errorHandler?: CliErrorHandler;
26
27
  }
28
+ export interface ModelEntry {
29
+ id: string;
30
+ provider: string;
31
+ isCustom?: boolean;
32
+ }
33
+ export declare const CURATED_MODELS_BY_PROVIDER: Record<string, string[]>;
34
+ export declare function getNumberedModelList(configMgr: UserConfigManager): ModelEntry[];
27
35
  /**
28
36
  * Command Registry & Execution Dispatcher.
29
37
  * PRD Part 2 Section 170–175.
@@ -1 +1 @@
1
- {"version":3,"file":"command-registry.d.ts","sourceRoot":"","sources":["../../src/cli/command-registry.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAMlE,MAAM,MAAM,cAAc,GAAG,CAC3B,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,iBAAiB,KAC1B,OAAO,CAAC,sBAAsB,CAAC,GAAG,sBAAsB,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,WAAW,EAAE,iBAAiB,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAA6C;IAChE,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoB;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAmB;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;gBAEnC,OAAO,EAAE,sBAAsB;IAgBpC,eAAe,CAAC,UAAU,EAAE,iBAAiB,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAS7E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAI1D,eAAe,IAAI,iBAAiB,EAAE;IAI7C;;OAEG;IACU,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAgBzE;;OAEG;IACH,OAAO,CAAC,uBAAuB;CA6wBhC"}
1
+ {"version":3,"file":"command-registry.d.ts","sourceRoot":"","sources":["../../src/cli/command-registry.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,96 @@ import { ProjectDeletionSafetyManager } from "../workspace/project-deletion-safe
4
4
  import { SlashMigrateCommand } from "./slash-migrate.js";
5
5
  import { maskSecret } from "../models/secret-store.js";
6
6
  import { UserConfigManager } from "../persistence/user-config-manager.js";
7
+ import { TokenMetricsManager } from "../persistence/token-metrics-manager.js";
8
+ import { ModelCatalogCache } from "../persistence/model-catalog-cache.js";
9
+ export const CURATED_MODELS_BY_PROVIDER = {
10
+ openrouter: [
11
+ "openrouter/anthropic/claude-3.5-sonnet",
12
+ "openrouter/deepseek/deepseek-r1",
13
+ "openrouter/openai/gpt-4o",
14
+ "openrouter/google/gemini-2.5-pro",
15
+ "openrouter/meta-llama/llama-3.3-70b-instruct",
16
+ "openrouter/qwen/qwen-2.5-coder-32b-instruct",
17
+ ],
18
+ anthropic: [
19
+ "claude-3-5-sonnet-20241022",
20
+ "claude-3-5-haiku-20241022",
21
+ "claude-3-opus-20240229",
22
+ ],
23
+ openai: [
24
+ "gpt-4o",
25
+ "gpt-4o-mini",
26
+ "o1",
27
+ "o3-mini",
28
+ ],
29
+ gemini: [
30
+ "gemini-2.5-pro",
31
+ "gemini-2.5-flash",
32
+ "gemini-2.0-flash-thinking-exp",
33
+ ],
34
+ groq: [
35
+ "groq/llama-3.3-70b-versatile",
36
+ "groq/deepseek-r1-distill-llama-70b",
37
+ ],
38
+ deepseek: [
39
+ "deepseek-chat",
40
+ "deepseek-reasoner",
41
+ ],
42
+ ollama: [
43
+ "ollama/llama3.2",
44
+ "ollama/mistral",
45
+ "ollama/qwen2.5-coder",
46
+ ],
47
+ };
48
+ export function getNumberedModelList(configMgr) {
49
+ const result = [];
50
+ const configuredProviders = configMgr
51
+ .listKeys()
52
+ .filter((k) => k.configured)
53
+ .map((k) => k.provider);
54
+ // 1. Prioritize models for configured providers
55
+ for (const prov of configuredProviders) {
56
+ const list = CURATED_MODELS_BY_PROVIDER[prov] || [];
57
+ for (const id of list) {
58
+ if (!result.some((r) => r.id === id)) {
59
+ result.push({ id, provider: prov });
60
+ }
61
+ }
62
+ }
63
+ // 2. Custom models
64
+ for (const customId of configMgr.getCustomModels()) {
65
+ if (!result.some((r) => r.id === customId)) {
66
+ result.push({ id: customId, provider: "custom", isCustom: true });
67
+ }
68
+ }
69
+ // 3. Cached models from ModelCatalogCache (if any and not already present)
70
+ try {
71
+ const cached = ModelCatalogCache.getInstance().getCachedModels();
72
+ if (cached && cached.length > 0) {
73
+ for (const m of cached) {
74
+ if (!result.some((r) => r.id === m.id)) {
75
+ result.push({ id: m.id, provider: m.provider });
76
+ }
77
+ }
78
+ }
79
+ }
80
+ catch {
81
+ // safe fallback
82
+ }
83
+ // 4. Fallback default models if no keys configured
84
+ if (result.length === 0) {
85
+ const defaultOrder = ["openrouter", "gemini", "anthropic", "openai"];
86
+ for (const prov of defaultOrder) {
87
+ const list = CURATED_MODELS_BY_PROVIDER[prov] || [];
88
+ for (const id of list.slice(0, 2)) {
89
+ if (!result.some((r) => r.id === id)) {
90
+ result.push({ id, provider: prov });
91
+ }
92
+ }
93
+ }
94
+ }
95
+ return result;
96
+ }
7
97
  /**
8
98
  * Command Registry & Execution Dispatcher.
9
99
  * PRD Part 2 Section 170–175.
@@ -44,7 +134,15 @@ export class CommandRegistry {
44
134
  }
45
135
  }
46
136
  getDescriptor(name) {
47
- return this.descriptors.get(name.toLowerCase());
137
+ const direct = this.descriptors.get(name.toLowerCase());
138
+ if (direct)
139
+ return direct;
140
+ for (const desc of this.descriptors.values()) {
141
+ if (desc.aliases.some((a) => a.toLowerCase() === name.toLowerCase())) {
142
+ return desc;
143
+ }
144
+ }
145
+ return undefined;
48
146
  }
49
147
  listDescriptors() {
50
148
  return Array.from(this.descriptors.values());
@@ -78,7 +176,7 @@ export class CommandRegistry {
78
176
  }, (cmd) => {
79
177
  if (cmd.args.length > 0) {
80
178
  const target = cmd.args[0].replace(/^\//, "").toLowerCase();
81
- const desc = this.descriptors.get(target);
179
+ const desc = this.getDescriptor(target);
82
180
  if (!desc) {
83
181
  return {
84
182
  success: false,
@@ -530,9 +628,9 @@ export class CommandRegistry {
530
628
  return {
531
629
  success: true,
532
630
  commandName: "version",
533
- message: "Anantham V2 v2.0.2",
631
+ message: "Anantham V2 v2.0.4",
534
632
  data: {
535
- version: "2.0.2",
633
+ version: "2.0.4",
536
634
  releaseChannel: "release",
537
635
  },
538
636
  exitRequested: false,
@@ -637,112 +735,288 @@ export class CommandRegistry {
637
735
  }
638
736
  throw new Error(`Unknown key subcommand '${sub}'. Use 'list', 'set <provider> <key>', or 'remove <provider>'.`);
639
737
  });
640
- // 15. /model
738
+ // 15. /models (Unified Model Command aliased to /model, /m, /model-list)
641
739
  this.registerCommand({
642
- name: "model",
643
- description: "Display or switch the active LLM model",
644
- aliases: ["m"],
645
- usage: "/model [modelId]",
740
+ name: "models",
741
+ description: "Display, switch, search, or browse AI models (aliased to /model)",
742
+ aliases: ["model", "m", "model-list"],
743
+ usage: "/models [<number> | <modelId> | <provider> | add <id> | remove <id> | search <query> | all]",
646
744
  options: [],
647
- }, (cmd, ctrl) => {
745
+ }, async (cmd, ctrl) => {
648
746
  const configMgr = UserConfigManager.getInstance();
649
- if (cmd.args.length > 0) {
650
- const modelId = cmd.args[0];
747
+ const cmdName = cmd.name.toLowerCase();
748
+ const activeProjectId = ctrl.getContext().activeProjectId;
749
+ const proj = activeProjectId ? this.projectRepo.findById(activeProjectId) : null;
750
+ const currentModel = proj?.modelProfile || configMgr.getDefaultModel();
751
+ // 1. If run without arguments:
752
+ if (cmd.args.length === 0) {
753
+ if (cmdName === "model") {
754
+ const list = getNumberedModelList(configMgr);
755
+ const customModels = configMgr.getCustomModels();
756
+ const customInfo = customModels.length > 0 ? `\nCustom models: ${customModels.join(", ")}` : "";
757
+ return {
758
+ success: true,
759
+ commandName: "model",
760
+ message: `Current active model: ${currentModel}\n\nQuick switch: /model <number> (e.g. /model 1)\nAdd custom: /model add <modelId>\nList models: /models${customInfo}`,
761
+ data: { model: currentModel, models: list, interactiveModal: true },
762
+ exitRequested: false,
763
+ };
764
+ }
765
+ const configuredKeys = configMgr.listKeys().filter((k) => k.configured);
766
+ const list = getNumberedModelList(configMgr);
767
+ let listBody;
768
+ if (configuredKeys.length > 0) {
769
+ const provNames = configuredKeys.map((k) => k.provider.toUpperCase()).join(", ");
770
+ const rows = list.map((item, idx) => {
771
+ const num = `[${idx + 1}]`.padEnd(4);
772
+ const isActive = item.id === currentModel ? " (ACTIVE)" : "";
773
+ const customTag = item.isCustom ? " [Custom]" : "";
774
+ return ` ${num} ${item.id}${customTag}${isActive}`;
775
+ });
776
+ listBody = `Available Models for Configured Providers (${provNames}):\n${rows.join("\n")}\n\nSwitch: /model <number> (e.g. /model 1) | /model <modelId>\nCustom: /model add <id> | Search: /models search <query>`;
777
+ }
778
+ else {
779
+ const fallbackRows = list.map((item, idx) => {
780
+ const num = `[${idx + 1}]`.padEnd(4);
781
+ const isActive = item.id === currentModel ? " (ACTIVE)" : "";
782
+ return ` ${num} ${item.id} [${item.provider}]${isActive}`;
783
+ });
784
+ listBody = `Curated AI Models (No API keys configured yet):\n${fallbackRows.join("\n")}\n\nConnect OpenRouter or other keys via:\n /key set openrouter <your-api-key>\nSwitch: /model <number> | View all: /models all`;
785
+ }
786
+ return {
787
+ success: true,
788
+ commandName: "models",
789
+ message: `Current active model: ${currentModel}\n\n${listBody}`,
790
+ data: {
791
+ model: currentModel,
792
+ activeModel: currentModel,
793
+ models: list,
794
+ interactiveModal: true,
795
+ },
796
+ exitRequested: false,
797
+ };
798
+ }
799
+ const sub = cmd.args[0].toLowerCase();
800
+ // 2. /model add <modelId>
801
+ if (sub === "add") {
802
+ const modelId = cmd.args[1]?.trim();
803
+ if (!modelId) {
804
+ throw new Error("Usage: /model add <modelId> (e.g. /model add openrouter/mistralai/mistral-large)");
805
+ }
806
+ configMgr.addCustomModel(modelId);
651
807
  configMgr.setDefaultModel(modelId);
652
- const activeProjectId = ctrl.getContext().activeProjectId;
653
- if (activeProjectId) {
654
- const proj = this.projectRepo.findById(activeProjectId);
655
- if (proj) {
656
- proj.modelProfile = modelId;
657
- this.projectRepo.save(proj);
808
+ if (proj) {
809
+ proj.modelProfile = modelId;
810
+ this.projectRepo.save(proj);
811
+ }
812
+ return {
813
+ success: true,
814
+ commandName: cmdName,
815
+ message: `✔ Added custom model '${modelId}' and switched to it.\n Saved to ~/.anantham/config.json and active project.`,
816
+ data: { model: modelId, custom: true },
817
+ exitRequested: false,
818
+ };
819
+ }
820
+ // 3. /model remove <modelId> or delete
821
+ if (sub === "remove" || sub === "delete") {
822
+ const modelId = cmd.args[1]?.trim();
823
+ if (!modelId) {
824
+ throw new Error("Usage: /model remove <modelId>");
825
+ }
826
+ const removed = configMgr.removeCustomModel(modelId);
827
+ return {
828
+ success: true,
829
+ commandName: cmdName,
830
+ message: removed
831
+ ? `✔ Removed custom model '${modelId}'.`
832
+ : `Model '${modelId}' was not in custom models list.`,
833
+ data: { model: modelId, removed },
834
+ exitRequested: false,
835
+ };
836
+ }
837
+ // 4. /models search <query> or /models fetch
838
+ if (sub === "search" || sub === "fetch") {
839
+ const query = cmd.args.slice(1).join(" ").toLowerCase();
840
+ const orKey = configMgr.getApiKey("openrouter");
841
+ if (!orKey) {
842
+ throw new Error("OpenRouter API key required to search live models. Connect it with: /key set openrouter <key>");
843
+ }
844
+ try {
845
+ const res = await fetch("https://openrouter.ai/api/v1/models", {
846
+ headers: { Authorization: `Bearer ${orKey}` },
847
+ signal: AbortSignal.timeout(6000),
848
+ });
849
+ if (!res.ok) {
850
+ throw new Error(`OpenRouter API responded with HTTP ${res.status}`);
851
+ }
852
+ const data = (await res.json());
853
+ let items = data.data || [];
854
+ if (query) {
855
+ items = items.filter((m) => m.id.toLowerCase().includes(query) || (m.name && m.name.toLowerCase().includes(query)));
658
856
  }
857
+ const matched = items.slice(0, 8);
858
+ if (matched.length === 0) {
859
+ return {
860
+ success: true,
861
+ commandName: "models",
862
+ message: `No OpenRouter models found matching '${query}'.`,
863
+ data: [],
864
+ exitRequested: false,
865
+ };
866
+ }
867
+ const lines = matched.map((m) => ` • ${m.id} (${m.context_length ? `${Math.round(m.context_length / 1000)}k ctx` : "std"})`);
868
+ return {
869
+ success: true,
870
+ commandName: "models",
871
+ message: `OpenRouter Live Models${query ? ` (search: '${query}')` : " (top)"}:\n${lines.join("\n")}\n\nTo use: /model <modelId> or /model add <modelId>`,
872
+ data: matched.map((m) => m.id),
873
+ exitRequested: false,
874
+ };
875
+ }
876
+ catch (err) {
877
+ throw new Error(`Failed to query OpenRouter live models: ${err.message}`);
878
+ }
879
+ }
880
+ // 5. /models all
881
+ if (sub === "all") {
882
+ const sections = [];
883
+ for (const [provider, models] of Object.entries(CURATED_MODELS_BY_PROVIDER)) {
884
+ sections.push(`[${provider.toUpperCase()}]:\n` + models.slice(0, 3).map((m) => ` • ${m}`).join("\n"));
659
885
  }
660
886
  return {
661
887
  success: true,
662
- commandName: "model",
663
- message: `✔ Active model switched to '${modelId}' (persisted to config & project).`,
664
- data: { model: modelId },
888
+ commandName: "models",
889
+ message: `Curated AI Models Catalog:\n\n${sections.join("\n\n")}\n\nSwitch via: /model <modelId>`,
890
+ data: CURATED_MODELS_BY_PROVIDER,
665
891
  exitRequested: false,
666
892
  };
667
893
  }
668
- const activeProjectId = ctrl.getContext().activeProjectId;
669
- const proj = activeProjectId ? this.projectRepo.findById(activeProjectId) : null;
670
- const currentModel = proj?.modelProfile || configMgr.getDefaultModel();
894
+ // 6. Specific provider e.g. /models anthropic or /models openrouter
895
+ if (CURATED_MODELS_BY_PROVIDER[sub]) {
896
+ const list = CURATED_MODELS_BY_PROVIDER[sub].map((m) => {
897
+ const activeTag = m === currentModel ? " (ACTIVE)" : "";
898
+ return ` • ${m}${activeTag}`;
899
+ }).join("\n");
900
+ return {
901
+ success: true,
902
+ commandName: cmdName,
903
+ message: `Models for [${sub.toUpperCase()}]:\n${list}\n\nSwitch via: /model <modelId>`,
904
+ data: CURATED_MODELS_BY_PROVIDER[sub],
905
+ exitRequested: false,
906
+ };
907
+ }
908
+ // 7. Numeric selection (e.g. /model 1 or /model 2)
909
+ let targetModel = cmd.args[0].trim();
910
+ if (/^\d+$/.test(targetModel)) {
911
+ const num = parseInt(targetModel, 10);
912
+ const list = getNumberedModelList(configMgr);
913
+ if (num < 1 || num > list.length) {
914
+ throw new Error(`Invalid model index [${num}]. Run '/models' to view available numbers (1-${list.length}).`);
915
+ }
916
+ targetModel = list[num - 1].id;
917
+ }
918
+ else if (cmdName === "models" && !targetModel.includes("/")) {
919
+ // If invoked as /models with an unknown provider argument, fall back gracefully to Curated AI Models list
920
+ const list = getNumberedModelList(configMgr);
921
+ const fallbackRows = list.map((item, idx) => {
922
+ const num = `[${idx + 1}]`.padEnd(4);
923
+ const isActive = item.id === currentModel ? " (ACTIVE)" : "";
924
+ return ` ${num} ${item.id} [${item.provider}]${isActive}`;
925
+ });
926
+ return {
927
+ success: true,
928
+ commandName: "models",
929
+ message: `Curated AI Models (Unknown provider '${cmd.args[0]}'):\n${fallbackRows.join("\n")}\n\nSwitch: /model <number> | View all: /models all`,
930
+ data: list,
931
+ exitRequested: false,
932
+ };
933
+ }
934
+ // 8. Model ID switch (e.g. /model gpt-4o or /model openrouter/anthropic/claude-3.5-sonnet)
935
+ configMgr.setDefaultModel(targetModel);
936
+ if (proj) {
937
+ proj.modelProfile = targetModel;
938
+ this.projectRepo.save(proj);
939
+ }
671
940
  return {
672
941
  success: true,
673
- commandName: "model",
674
- message: `Current active model: ${currentModel}\nType '/models' to view curated popular models or '/model <id>' to switch.`,
675
- data: { model: currentModel },
942
+ commandName: cmdName,
943
+ message: `✔ Active model switched to '${targetModel}' (persisted to config & project).`,
944
+ data: { model: targetModel },
676
945
  exitRequested: false,
677
946
  };
678
947
  });
679
- // 16. /models
948
+ // /usage — Real-time Token Usage Matrix & Cost Attribution
680
949
  this.registerCommand({
681
- name: "models",
682
- description: "List curated popular LLM models across providers",
683
- aliases: ["model-list"],
684
- usage: "/models [openrouter | anthropic | openai | gemini | groq | deepseek | ollama]",
950
+ name: "usage",
951
+ description: "Display real-time token usage matrix, model leaderboard and cost attribution",
952
+ aliases: ["tokens", "metrics", "cost"],
953
+ usage: "/usage [today | mtd | models | trend]",
685
954
  options: [],
686
- }, (cmd) => {
687
- const target = cmd.args[0]?.toLowerCase();
688
- const curated = {
689
- openrouter: [
690
- "openrouter/anthropic/claude-3.5-sonnet",
691
- "openrouter/deepseek/deepseek-r1",
692
- "openrouter/openai/gpt-4o",
693
- "openrouter/google/gemini-2.5-pro",
694
- "openrouter/meta-llama/llama-3.3-70b-instruct",
695
- "openrouter/qwen/qwen-2.5-coder-32b-instruct",
696
- ],
697
- anthropic: [
698
- "claude-3-5-sonnet-20241022",
699
- "claude-3-5-haiku-20241022",
700
- "claude-3-opus-20240229",
701
- ],
702
- openai: [
703
- "gpt-4o",
704
- "gpt-4o-mini",
705
- "o1",
706
- "o3-mini",
707
- ],
708
- gemini: [
709
- "gemini-2.5-pro",
710
- "gemini-2.5-flash",
711
- "gemini-2.0-flash-thinking-exp",
712
- ],
713
- groq: [
714
- "groq/llama-3.3-70b-versatile",
715
- "groq/deepseek-r1-distill-llama-70b",
716
- ],
717
- deepseek: [
718
- "deepseek-chat",
719
- "deepseek-reasoner",
720
- ],
721
- ollama: [
722
- "ollama/llama3.2",
723
- "ollama/mistral",
724
- "ollama/qwen2.5-coder",
725
- ],
726
- };
727
- if (target && curated[target]) {
728
- const list = curated[target].map((m) => ` • ${m}`).join("\n");
729
- return {
730
- success: true,
731
- commandName: "models",
732
- message: `Models for [${target.toUpperCase()}]:\n${list}\n\nSwitch via: /model <modelId>`,
733
- data: curated[target],
734
- exitRequested: false,
735
- };
736
- }
737
- const sections = [];
738
- for (const [provider, models] of Object.entries(curated)) {
739
- sections.push(`[${provider.toUpperCase()}]:\n` + models.slice(0, 3).map((m) => ` • ${m}`).join("\n"));
955
+ }, () => {
956
+ const metrics = TokenMetricsManager.getInstance();
957
+ const today = metrics.getDailySummary();
958
+ const mtd = metrics.getMtdSummary();
959
+ const budget = metrics.getMonthlyBudget();
960
+ const topModels = metrics.getTopModels(4);
961
+ const lines = [
962
+ "Token Usage Matrix & Cost Analytics:",
963
+ ` Today's Tokens : ${today.totalTokens.toLocaleString()} (In: ${today.totalInputTokens.toLocaleString()} | Out: ${today.totalOutputTokens.toLocaleString()} | Cached: ${today.totalCachedTokens.toLocaleString()})`,
964
+ ` Today's Cost : $${today.totalCostUsd.toFixed(4)} USD (${today.requestCount} requests)`,
965
+ ` Month-to-Date : ${mtd.totalTokens.toLocaleString()} tokens | $${mtd.totalCostUsd.toFixed(2)} / $${budget.toFixed(0)} USD budget`,
966
+ "",
967
+ "Top Consuming Models:",
968
+ ];
969
+ for (const m of topModels) {
970
+ lines.push(` • ${m.modelId.padEnd(34)} : ${m.totalTokens.toLocaleString().padStart(10)} tokens | $${m.costUsd.toFixed(2)} (${m.percentage}%)`);
740
971
  }
972
+ lines.push("");
973
+ lines.push("Interactive TUI: Run 'anantham --tui' and type '/usage' to view the full graphical matrix with neon sparklines.");
974
+ return {
975
+ success: true,
976
+ commandName: "usage",
977
+ message: lines.join("\n"),
978
+ data: { today, mtd, budget, topModels },
979
+ exitRequested: false,
980
+ };
981
+ });
982
+ // /teamwork-preview — Autonomous multi-worker preview harness
983
+ this.registerCommand({
984
+ name: "teamwork-preview",
985
+ description: "Autonomous agent multi-worker teamwork preview harness",
986
+ aliases: ["preview", "teamwork"],
987
+ usage: "/teamwork-preview [status | run]",
988
+ options: [],
989
+ }, () => {
990
+ return {
991
+ success: true,
992
+ commandName: "teamwork-preview",
993
+ message: [
994
+ "❖ Teamwork Preview Harness Status: ONLINE",
995
+ " Engine : Anantham V2 Autonomous Agent Coordinator",
996
+ " Parallel Workers : 4 active worker execution slots",
997
+ " Task Partitioning: Wave DAG with generation-fenced leases",
998
+ " Durability : SQLite WAL (synchronous = FULL, RPO-0)",
999
+ " Safety Boundary : ToolGateway sandboxed capability routing",
1000
+ "",
1001
+ "Autonomous team preview ready. Submit prompt tasks via interactive CLI or TUI.",
1002
+ ].join("\n"),
1003
+ data: { status: "ONLINE", workers: 4, mode: "wave_dag" },
1004
+ exitRequested: false,
1005
+ };
1006
+ });
1007
+ // /clear — Clear viewport
1008
+ this.registerCommand({
1009
+ name: "clear",
1010
+ description: "Clear terminal viewport and command output buffer",
1011
+ aliases: ["cls"],
1012
+ usage: "/clear",
1013
+ options: [],
1014
+ }, () => {
741
1015
  return {
742
1016
  success: true,
743
- commandName: "models",
744
- message: `Curated AI Models:\n\n${sections.join("\n\n")}\n\nRun '/models <provider>' for more or '/model <id>' to select.`,
745
- data: curated,
1017
+ commandName: "clear",
1018
+ message: "",
1019
+ data: {},
746
1020
  exitRequested: false,
747
1021
  };
748
1022
  });