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.
- package/dist/bin/anantham.js +10 -1
- package/dist/bin/anantham.js.map +1 -1
- package/dist/cli/command-registry.d.ts +8 -0
- package/dist/cli/command-registry.d.ts.map +1 -1
- package/dist/cli/command-registry.js +363 -89
- package/dist/cli/command-registry.js.map +1 -1
- package/dist/domain/tui.d.ts +1 -1
- package/dist/domain/tui.d.ts.map +1 -1
- package/dist/domain/tui.js +1 -0
- package/dist/domain/tui.js.map +1 -1
- package/dist/models/adapters/openai-compatible-adapter.d.ts.map +1 -1
- package/dist/models/adapters/openai-compatible-adapter.js +2 -1
- package/dist/models/adapters/openai-compatible-adapter.js.map +1 -1
- package/dist/models/provider-registry.d.ts +2 -2
- package/dist/persistence/index.d.ts +2 -0
- package/dist/persistence/index.d.ts.map +1 -1
- package/dist/persistence/index.js +2 -0
- package/dist/persistence/index.js.map +1 -1
- package/dist/persistence/model-catalog-cache.d.ts +86 -0
- package/dist/persistence/model-catalog-cache.d.ts.map +1 -0
- package/dist/persistence/model-catalog-cache.js +398 -0
- package/dist/persistence/model-catalog-cache.js.map +1 -0
- package/dist/persistence/token-metrics-manager.d.ts +88 -0
- package/dist/persistence/token-metrics-manager.d.ts.map +1 -0
- package/dist/persistence/token-metrics-manager.js +272 -0
- package/dist/persistence/token-metrics-manager.js.map +1 -0
- package/dist/persistence/user-config-manager.d.ts +8 -0
- package/dist/persistence/user-config-manager.d.ts.map +1 -1
- package/dist/persistence/user-config-manager.js +50 -1
- package/dist/persistence/user-config-manager.js.map +1 -1
- package/dist/tui/ansi-gradient.d.ts +43 -0
- package/dist/tui/ansi-gradient.d.ts.map +1 -0
- package/dist/tui/ansi-gradient.js +131 -0
- package/dist/tui/ansi-gradient.js.map +1 -0
- package/dist/tui/command-palette.d.ts +20 -0
- package/dist/tui/command-palette.d.ts.map +1 -0
- package/dist/tui/command-palette.js +241 -0
- package/dist/tui/command-palette.js.map +1 -0
- package/dist/tui/model-accordion-browser.d.ts +80 -0
- package/dist/tui/model-accordion-browser.d.ts.map +1 -0
- package/dist/tui/model-accordion-browser.js +487 -0
- package/dist/tui/model-accordion-browser.js.map +1 -0
- package/dist/tui/terminal-layout.d.ts +4 -0
- package/dist/tui/terminal-layout.d.ts.map +1 -1
- package/dist/tui/terminal-layout.js +30 -0
- package/dist/tui/terminal-layout.js.map +1 -1
- package/dist/tui/terminal-logo-renderer.d.ts +63 -0
- package/dist/tui/terminal-logo-renderer.d.ts.map +1 -0
- package/dist/tui/terminal-logo-renderer.js +300 -0
- package/dist/tui/terminal-logo-renderer.js.map +1 -0
- package/dist/tui/token-dashboard-renderer.d.ts +6 -0
- package/dist/tui/token-dashboard-renderer.d.ts.map +1 -0
- package/dist/tui/token-dashboard-renderer.js +115 -0
- package/dist/tui/token-dashboard-renderer.js.map +1 -0
- package/dist/tui/tui-controller.d.ts +14 -0
- package/dist/tui/tui-controller.d.ts.map +1 -1
- package/dist/tui/tui-controller.js +192 -7
- package/dist/tui/tui-controller.js.map +1 -1
- package/dist/tui/tui-renderer.d.ts +7 -1
- package/dist/tui/tui-renderer.d.ts.map +1 -1
- package/dist/tui/tui-renderer.js +52 -10
- package/dist/tui/tui-renderer.js.map +1 -1
- package/dist/tui/tui-sanitizer.d.ts +4 -0
- package/dist/tui/tui-sanitizer.d.ts.map +1 -1
- package/dist/tui/tui-sanitizer.js +6 -0
- package/dist/tui/tui-sanitizer.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/anantham.js
CHANGED
|
@@ -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.
|
|
86
|
+
console.log("2.0.4");
|
|
78
87
|
process.exit(0);
|
|
79
88
|
}
|
|
80
89
|
else if (!arg.startsWith("-") && !executeCmd) {
|
package/dist/bin/anantham.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anantham.js","sourceRoot":"","sources":["../../src/bin/anantham.ts"],"names":[],"mappings":";AAEA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE1E,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;YAC9C,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,IAAI,CAAC;QACH,iBAAiB,CAAC,WAAW,EAAE,CAAC,mBAAmB,EAAE,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAClE,IAAI,UAAU,GAAkB,MAAM,CAAC;IACvC,IAAI,UAA8B,CAAC;IACnC,IAAI,gBAAoC,CAAC;IACzC,IAAI,gBAAoC,CAAC;IACzC,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,UAAU,GAAG,IAAI,CAAC;IAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAClC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAE,CAAC;QACtB,CAAC;aAAM,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YAC3B,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;aAAM,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YAC9B,YAAY,GAAG,IAAI,CAAC;QACtB,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC3C,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;QACxC,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,UAAU,GAAG,MAAM,CAAC;QACtB,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,UAAU,GAAG,OAAO,CAAC;QACvB,CAAC;aAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5C,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACzB,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC9C,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/B,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC9C,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/B,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC
|
|
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;
|
|
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
|
-
|
|
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.
|
|
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.
|
|
631
|
+
message: "Anantham V2 v2.0.4",
|
|
534
632
|
data: {
|
|
535
|
-
version: "2.0.
|
|
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: "
|
|
643
|
-
description: "Display or
|
|
644
|
-
aliases: ["m"],
|
|
645
|
-
usage: "/
|
|
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
|
-
|
|
650
|
-
|
|
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
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
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: "
|
|
663
|
-
message:
|
|
664
|
-
data:
|
|
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
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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:
|
|
674
|
-
message:
|
|
675
|
-
data: { model:
|
|
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
|
-
//
|
|
948
|
+
// /usage — Real-time Token Usage Matrix & Cost Attribution
|
|
680
949
|
this.registerCommand({
|
|
681
|
-
name: "
|
|
682
|
-
description: "
|
|
683
|
-
aliases: ["
|
|
684
|
-
usage: "/
|
|
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
|
-
}, (
|
|
687
|
-
const
|
|
688
|
-
const
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
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: "
|
|
744
|
-
message:
|
|
745
|
-
data:
|
|
1017
|
+
commandName: "clear",
|
|
1018
|
+
message: "",
|
|
1019
|
+
data: {},
|
|
746
1020
|
exitRequested: false,
|
|
747
1021
|
};
|
|
748
1022
|
});
|