aemeathcli 1.0.10 → 1.0.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.
- package/LICENSE +21 -0
- package/README.md +609 -608
- package/dist/App-YAHJUWCX.js +4274 -0
- package/dist/App-YAHJUWCX.js.map +1 -0
- package/dist/agent-store/architect.md +32 -0
- package/dist/agent-store/debugger.md +32 -0
- package/dist/agent-store/developer.md +29 -0
- package/dist/agent-store/documenter.md +30 -0
- package/dist/agent-store/researcher.md +31 -0
- package/dist/agent-store/reviewer.md +28 -0
- package/dist/agent-store/supervisor.md +37 -0
- package/dist/agent-store/tester.md +30 -0
- package/dist/api-key-fallback-UN3TJEOO.js +11 -0
- package/dist/{api-key-fallback-YQQBOQIL.js.map → api-key-fallback-UN3TJEOO.js.map} +1 -1
- package/dist/auth-status-EIM5A5KL.js +13 -0
- package/dist/auth-status-EIM5A5KL.js.map +1 -0
- package/dist/{chunk-UY2SYSEZ.js → chunk-25UNNEHN.js} +32 -103
- package/dist/chunk-25UNNEHN.js.map +1 -0
- package/dist/{chunk-CYQNBB25.js → chunk-2GKOK6T7.js} +28 -5
- package/dist/chunk-2GKOK6T7.js.map +1 -0
- package/dist/{chunk-MFBHNWGV.js → chunk-2LF7ALGR.js} +12 -20
- package/dist/chunk-2LF7ALGR.js.map +1 -0
- package/dist/{chunk-H66O5Z2V.js → chunk-2NWNIKBK.js} +42 -7
- package/dist/chunk-2NWNIKBK.js.map +1 -0
- package/dist/chunk-3TSPZRGM.js +26 -0
- package/dist/chunk-3TSPZRGM.js.map +1 -0
- package/dist/{chunk-ZGOHARPV.js → chunk-473JN6M5.js} +2 -2
- package/dist/chunk-473JN6M5.js.map +1 -0
- package/dist/{chunk-IYW62KKR.js → chunk-5XFSV6PF.js} +66 -23
- package/dist/chunk-5XFSV6PF.js.map +1 -0
- package/dist/{chunk-HCIHOHLX.js → chunk-62HSGYQD.js} +2 -2
- package/dist/chunk-62HSGYQD.js.map +1 -0
- package/dist/{chunk-I5PZ4JTS.js → chunk-6GUD7QIM.js} +4 -4
- package/dist/chunk-6GUD7QIM.js.map +1 -0
- package/dist/{chunk-4IJD72YB.js → chunk-AQ23TYSQ.js} +7 -7
- package/dist/chunk-AQ23TYSQ.js.map +1 -0
- package/dist/{chunk-NBR3GHMT.js → chunk-BY4DAKUU.js} +39 -7
- package/dist/chunk-BY4DAKUU.js.map +1 -0
- package/dist/chunk-CC7MGWYY.js +12 -0
- package/dist/chunk-CC7MGWYY.js.map +1 -0
- package/dist/chunk-CTFZTARK.js +155 -0
- package/dist/chunk-CTFZTARK.js.map +1 -0
- package/dist/chunk-FIC7AK4Q.js +232 -0
- package/dist/chunk-FIC7AK4Q.js.map +1 -0
- package/dist/chunk-GU33WKPG.js +140 -0
- package/dist/chunk-GU33WKPG.js.map +1 -0
- package/dist/{chunk-DMBPX3RG.js → chunk-H2SYKIMI.js} +10 -10
- package/dist/chunk-H2SYKIMI.js.map +1 -0
- package/dist/{chunk-JAXXTYID.js → chunk-HEKFAKVH.js} +2 -2
- package/dist/chunk-HEKFAKVH.js.map +1 -0
- package/dist/chunk-IARA5XYP.js +186 -0
- package/dist/chunk-IARA5XYP.js.map +1 -0
- package/dist/{chunk-HMJRPNPZ.js → chunk-LCYH4T6N.js} +95 -23
- package/dist/chunk-LCYH4T6N.js.map +1 -0
- package/dist/{chunk-CARHU3DO.js → chunk-LDVY5ELP.js} +66 -18
- package/dist/chunk-LDVY5ELP.js.map +1 -0
- package/dist/chunk-OCJPQFOR.js +88 -0
- package/dist/chunk-OCJPQFOR.js.map +1 -0
- package/dist/chunk-ODBY7S4X.js +141 -0
- package/dist/chunk-ODBY7S4X.js.map +1 -0
- package/dist/{chunk-DAHGLHNR.js → chunk-ONQ4WCUI.js} +7 -142
- package/dist/chunk-ONQ4WCUI.js.map +1 -0
- package/dist/{chunk-WPP3PEDE.js → chunk-P5TKZM3T.js} +32 -107
- package/dist/chunk-P5TKZM3T.js.map +1 -0
- package/dist/{chunk-RWCNNAL7.js → chunk-P66WDACW.js} +23 -22
- package/dist/chunk-P66WDACW.js.map +1 -0
- package/dist/{chunk-LSOYPSAT.js → chunk-QCRK4QEL.js} +4 -4
- package/dist/chunk-QCRK4QEL.js.map +1 -0
- package/dist/{chunk-YL5XFHR3.js → chunk-ROJPFPJ7.js} +2 -2
- package/dist/chunk-ROJPFPJ7.js.map +1 -0
- package/dist/chunk-RP2TAL3J.js +71 -0
- package/dist/chunk-RP2TAL3J.js.map +1 -0
- package/dist/{chunk-6PDJ45T4.js → chunk-RYOB3TLZ.js} +51 -26
- package/dist/chunk-RYOB3TLZ.js.map +1 -0
- package/dist/{chunk-Y5XVD2CD.js → chunk-SOQFMNQC.js} +110 -83
- package/dist/chunk-SOQFMNQC.js.map +1 -0
- package/dist/{chunk-TEVZS4FA.js → chunk-TDFTX32B.js} +16 -9
- package/dist/chunk-TDFTX32B.js.map +1 -0
- package/dist/chunk-VBLLDY4R.js +38 -0
- package/dist/chunk-VBLLDY4R.js.map +1 -0
- package/dist/{chunk-CGEV3ARR.js → chunk-VJNQJALF.js} +4 -4
- package/dist/chunk-VJNQJALF.js.map +1 -0
- package/dist/chunk-WAYSJMPS.js +26 -0
- package/dist/chunk-WAYSJMPS.js.map +1 -0
- package/dist/chunk-WC72BRHR.js +241 -0
- package/dist/chunk-WC72BRHR.js.map +1 -0
- package/dist/{chunk-MXZSI3AY.js → chunk-YPFOE2QJ.js} +43 -11
- package/dist/chunk-YPFOE2QJ.js.map +1 -0
- package/dist/claude-adapter-6P4SJH7P.js +7 -0
- package/dist/{claude-adapter-QMLFMSP3.js.map → claude-adapter-6P4SJH7P.js.map} +1 -1
- package/dist/{claude-login-5WELXPKT.js → claude-login-IS5WTBMP.js} +10 -10
- package/dist/claude-login-IS5WTBMP.js.map +1 -0
- package/dist/cli.js +371 -172
- package/dist/cli.js.map +1 -1
- package/dist/{codex-login-GZIFXUWD.js → codex-login-GMPF64MR.js} +11 -11
- package/dist/codex-login-GMPF64MR.js.map +1 -0
- package/dist/config-store-POB6I37G.js +7 -0
- package/dist/{config-store-W6FBCQAQ.js.map → config-store-POB6I37G.js.map} +1 -1
- package/dist/conversation-store-PRBHWQMJ.js +4 -0
- package/dist/conversation-store-PRBHWQMJ.js.map +1 -0
- package/dist/detect-providers-C4SVQHFF.js +4 -0
- package/dist/detect-providers-C4SVQHFF.js.map +1 -0
- package/dist/executor-RUX7VK3T.js +4 -0
- package/dist/{executor-6RIKIGXK.js.map → executor-RUX7VK3T.js.map} +1 -1
- package/dist/first-run-GDEVRFPO.js +230 -0
- package/dist/first-run-GDEVRFPO.js.map +1 -0
- package/dist/gemini-adapter-MV3U4QFH.js +7 -0
- package/dist/{gemini-adapter-6JIHZ7WI.js.map → gemini-adapter-MV3U4QFH.js.map} +1 -1
- package/dist/{gemini-login-AZGL3CE7.js → gemini-login-KE224MSW.js} +10 -10
- package/dist/gemini-login-KE224MSW.js.map +1 -0
- package/dist/index.d.ts +47 -17
- package/dist/index.js +86 -471
- package/dist/index.js.map +1 -1
- package/dist/input-history-MIOO3FIW.js +57 -0
- package/dist/input-history-MIOO3FIW.js.map +1 -0
- package/dist/kimi-adapter-UODMNX6K.js +6 -0
- package/dist/{kimi-adapter-JN4HFFHU.js.map → kimi-adapter-UODMNX6K.js.map} +1 -1
- package/dist/{kimi-login-6LUWB7P6.js → kimi-login-DNT5YBKX.js} +10 -10
- package/dist/kimi-login-DNT5YBKX.js.map +1 -0
- package/dist/logger-PLPDWACQ.js +3 -0
- package/dist/logger-PLPDWACQ.js.map +1 -0
- package/dist/model-discovery-O64ZWPX5.js +6 -0
- package/dist/model-discovery-O64ZWPX5.js.map +1 -0
- package/dist/native-cli-adapters-JMZX2C2C.js +8 -0
- package/dist/{native-cli-adapters-OLW3XX57.js.map → native-cli-adapters-JMZX2C2C.js.map} +1 -1
- package/dist/ollama-adapter-GE67BNSS.js +5 -0
- package/dist/{ollama-adapter-OJQ3FKWK.js.map → ollama-adapter-GE67BNSS.js.map} +1 -1
- package/dist/openai-adapter-SHPLK77L.js +7 -0
- package/dist/{openai-adapter-XU46EN7B.js.map → openai-adapter-SHPLK77L.js.map} +1 -1
- package/dist/pathResolver-A6IXQQFE.js +3 -0
- package/dist/pathResolver-A6IXQQFE.js.map +1 -0
- package/dist/profile-loader-TNAXBLDX.js +162 -0
- package/dist/profile-loader-TNAXBLDX.js.map +1 -0
- package/dist/registry-3NHVCXCZ.js +6 -0
- package/dist/{registry-AZ2LOHHJ.js.map → registry-3NHVCXCZ.js.map} +1 -1
- package/dist/registry-7CQ3NCAD.js +5 -0
- package/dist/{registry-H7B3AHPQ.js.map → registry-7CQ3NCAD.js.map} +1 -1
- package/dist/server-manager-DES23IBQ.js +5 -0
- package/dist/{server-manager-PTGBHCLS.js.map → server-manager-DES23IBQ.js.map} +1 -1
- package/dist/session-manager-EHD7GWM2.js +12 -0
- package/dist/{session-manager-XOMDMC77.js.map → session-manager-EHD7GWM2.js.map} +1 -1
- package/dist/skills/built-in/code-review/SKILL.md +85 -0
- package/dist/skills/built-in/commit/SKILL.md +83 -0
- package/dist/skills/built-in/debug/SKILL.md +119 -0
- package/dist/skills/built-in/plan/SKILL.md +123 -0
- package/dist/skills/built-in/refactor/SKILL.md +132 -0
- package/dist/skills/built-in/test/SKILL.md +128 -0
- package/dist/sqlite-store-7ZIVOUNI.js +5 -0
- package/dist/sqlite-store-7ZIVOUNI.js.map +1 -0
- package/dist/team-manager-6DCNLGTC.js +11 -0
- package/dist/{team-manager-HC4XGCFY.js.map → team-manager-6DCNLGTC.js.map} +1 -1
- package/dist/team-state-R2D7DT5M.js +3 -0
- package/dist/team-state-R2D7DT5M.js.map +1 -0
- package/dist/tmux-manager-WBKHUHDT.js +6 -0
- package/dist/{tmux-manager-GPYZ3WQH.js.map → tmux-manager-WBKHUHDT.js.map} +1 -1
- package/dist/tools-I6XCTEZY.js +6 -0
- package/dist/{tools-TSMXMHIF.js.map → tools-I6XCTEZY.js.map} +1 -1
- package/package.json +93 -89
- package/dist/App-FKRSMFMB.js +0 -2789
- package/dist/App-FKRSMFMB.js.map +0 -1
- package/dist/api-key-fallback-YQQBOQIL.js +0 -11
- package/dist/chunk-4IJD72YB.js.map +0 -1
- package/dist/chunk-6PDJ45T4.js.map +0 -1
- package/dist/chunk-CARHU3DO.js.map +0 -1
- package/dist/chunk-CGEV3ARR.js.map +0 -1
- package/dist/chunk-CS5X3BWX.js +0 -27
- package/dist/chunk-CS5X3BWX.js.map +0 -1
- package/dist/chunk-CYQNBB25.js.map +0 -1
- package/dist/chunk-DAHGLHNR.js.map +0 -1
- package/dist/chunk-DMBPX3RG.js.map +0 -1
- package/dist/chunk-H66O5Z2V.js.map +0 -1
- package/dist/chunk-HCIHOHLX.js.map +0 -1
- package/dist/chunk-HMJRPNPZ.js.map +0 -1
- package/dist/chunk-I5PZ4JTS.js.map +0 -1
- package/dist/chunk-IYW62KKR.js.map +0 -1
- package/dist/chunk-JAXXTYID.js.map +0 -1
- package/dist/chunk-LSOYPSAT.js.map +0 -1
- package/dist/chunk-MFBHNWGV.js.map +0 -1
- package/dist/chunk-MXZSI3AY.js.map +0 -1
- package/dist/chunk-NBR3GHMT.js.map +0 -1
- package/dist/chunk-RWCNNAL7.js.map +0 -1
- package/dist/chunk-TEVZS4FA.js.map +0 -1
- package/dist/chunk-UY2SYSEZ.js.map +0 -1
- package/dist/chunk-WAHVZH7V.js +0 -260
- package/dist/chunk-WAHVZH7V.js.map +0 -1
- package/dist/chunk-WPP3PEDE.js.map +0 -1
- package/dist/chunk-Y5XVD2CD.js.map +0 -1
- package/dist/chunk-YL5XFHR3.js.map +0 -1
- package/dist/chunk-ZGOHARPV.js.map +0 -1
- package/dist/claude-adapter-QMLFMSP3.js +0 -6
- package/dist/claude-login-5WELXPKT.js.map +0 -1
- package/dist/codex-login-GZIFXUWD.js.map +0 -1
- package/dist/config-store-W6FBCQAQ.js +0 -6
- package/dist/executor-6RIKIGXK.js +0 -4
- package/dist/gemini-adapter-6JIHZ7WI.js +0 -6
- package/dist/gemini-login-AZGL3CE7.js.map +0 -1
- package/dist/kimi-adapter-JN4HFFHU.js +0 -6
- package/dist/kimi-login-6LUWB7P6.js.map +0 -1
- package/dist/native-cli-adapters-OLW3XX57.js +0 -6
- package/dist/ollama-adapter-OJQ3FKWK.js +0 -6
- package/dist/openai-adapter-XU46EN7B.js +0 -6
- package/dist/registry-AZ2LOHHJ.js +0 -6
- package/dist/registry-H7B3AHPQ.js +0 -5
- package/dist/server-manager-PTGBHCLS.js +0 -5
- package/dist/session-manager-XOMDMC77.js +0 -12
- package/dist/team-manager-HC4XGCFY.js +0 -11
- package/dist/tmux-manager-GPYZ3WQH.js +0 -6
- package/dist/tools-TSMXMHIF.js +0 -6
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { SUPPORTED_MODELS, PROVIDER_MODEL_ORDER } from './chunk-62HSGYQD.js';
|
|
2
|
+
import { logger } from './chunk-HEKFAKVH.js';
|
|
3
|
+
import { getAemeathHome } from './chunk-BY4DAKUU.js';
|
|
4
|
+
import { readFile } from 'fs/promises';
|
|
5
|
+
import { join, dirname } from 'path';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { execa } from 'execa';
|
|
9
|
+
|
|
10
|
+
var discoveryComplete = false;
|
|
11
|
+
var dynamicModels = {};
|
|
12
|
+
var dynamicDisplayOrder = {};
|
|
13
|
+
function makeModelInfo(id, name, provider, description, contextWindow) {
|
|
14
|
+
return {
|
|
15
|
+
id,
|
|
16
|
+
name,
|
|
17
|
+
provider,
|
|
18
|
+
contextWindow: contextWindow ?? 2e5,
|
|
19
|
+
maxOutputTokens: 16384,
|
|
20
|
+
inputPricePerMToken: 0,
|
|
21
|
+
outputPricePerMToken: 0,
|
|
22
|
+
supportsStreaming: true,
|
|
23
|
+
supportsToolCalling: true,
|
|
24
|
+
supportedRoles: ["coding"],
|
|
25
|
+
description
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async function discoverCodexModels() {
|
|
29
|
+
const configPath = join(homedir(), ".codex", "config.toml");
|
|
30
|
+
let currentModel;
|
|
31
|
+
try {
|
|
32
|
+
const raw = await readFile(configPath, "utf-8");
|
|
33
|
+
const match = raw.match(/^model\s*=\s*"([^"]+)"/m);
|
|
34
|
+
if (match?.[1]) {
|
|
35
|
+
currentModel = match[1];
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const { stdout } = await execa("codex", ["exec", "--help"], {
|
|
41
|
+
timeout: 5e3,
|
|
42
|
+
stdin: "ignore",
|
|
43
|
+
env: { ...process.env, NO_COLOR: "1" }
|
|
44
|
+
});
|
|
45
|
+
const modelRefs = stdout.matchAll(/model="([^"]+)"/g);
|
|
46
|
+
for (const m of modelRefs) {
|
|
47
|
+
const id = m[1];
|
|
48
|
+
if (id && !SUPPORTED_MODELS[id] && !dynamicModels[id]) {
|
|
49
|
+
addModel(id, id, "openai");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
if (currentModel && !SUPPORTED_MODELS[currentModel] && !dynamicModels[currentModel]) {
|
|
55
|
+
addModel(currentModel, currentModel, "openai", `User's current Codex model`);
|
|
56
|
+
}
|
|
57
|
+
const knownCodexModels = [
|
|
58
|
+
{ id: "gpt-5.4", name: "GPT-5.4", desc: "Latest frontier agentic coding model" },
|
|
59
|
+
{ id: "gpt-5.4-mini", name: "GPT-5.4 Mini", desc: "Smaller frontier agentic coding model" },
|
|
60
|
+
{ id: "o3", name: "o3", desc: "OpenAI o3 reasoning model" },
|
|
61
|
+
{ id: "o4-mini", name: "o4-mini", desc: "OpenAI o4-mini reasoning model" }
|
|
62
|
+
];
|
|
63
|
+
for (const m of knownCodexModels) {
|
|
64
|
+
if (!SUPPORTED_MODELS[m.id] && !dynamicModels[m.id]) {
|
|
65
|
+
addModel(m.id, m.name, "openai", m.desc);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function discoverGeminiModels() {
|
|
70
|
+
const geminiModelsPath = await findGeminiModelsFile();
|
|
71
|
+
if (geminiModelsPath) {
|
|
72
|
+
try {
|
|
73
|
+
const source = await readFile(geminiModelsPath, "utf-8");
|
|
74
|
+
const modelMatches = source.matchAll(/['"]([^'"]*gemini[^'"]+)['"]/g);
|
|
75
|
+
for (const m of modelMatches) {
|
|
76
|
+
const id = m[1];
|
|
77
|
+
if (id && !id.includes("embedding") && !id.includes("auto-") && !id.includes("customtools") && !SUPPORTED_MODELS[id] && !dynamicModels[id]) {
|
|
78
|
+
const name = id.replace(/-preview$/, " Preview").replace(/-lite$/, " Lite").split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" ");
|
|
79
|
+
addModel(id, name, "google", void 0, 2e6);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
logger.debug("Failed to read Gemini CLI models source");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const knownGeminiModels = [
|
|
87
|
+
{ id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro Preview", desc: "Latest Gemini Pro preview" },
|
|
88
|
+
{ id: "gemini-3.1-flash-lite-preview", name: "Gemini 3.1 Flash Lite Preview", desc: "Latest Flash Lite preview" },
|
|
89
|
+
{ id: "gemini-3-flash-preview", name: "Gemini 3 Flash Preview", desc: "Gemini 3 Flash preview" }
|
|
90
|
+
];
|
|
91
|
+
for (const m of knownGeminiModels) {
|
|
92
|
+
if (!SUPPORTED_MODELS[m.id] && !dynamicModels[m.id]) {
|
|
93
|
+
addModel(m.id, m.name, "google", m.desc, 2e6);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function findGeminiModelsFile() {
|
|
98
|
+
try {
|
|
99
|
+
const { stdout } = await execa("which", ["gemini"], {
|
|
100
|
+
stdin: "ignore",
|
|
101
|
+
timeout: 5e3,
|
|
102
|
+
env: { ...process.env, NO_COLOR: "1" }
|
|
103
|
+
});
|
|
104
|
+
const whichResult = stdout.trim();
|
|
105
|
+
if (whichResult) {
|
|
106
|
+
const binDir = dirname(whichResult);
|
|
107
|
+
const modelsPath = join(
|
|
108
|
+
binDir,
|
|
109
|
+
"..",
|
|
110
|
+
"lib",
|
|
111
|
+
"node_modules",
|
|
112
|
+
"@google",
|
|
113
|
+
"gemini-cli",
|
|
114
|
+
"node_modules",
|
|
115
|
+
"@google",
|
|
116
|
+
"gemini-cli-core",
|
|
117
|
+
"dist",
|
|
118
|
+
"src",
|
|
119
|
+
"config",
|
|
120
|
+
"models.js"
|
|
121
|
+
);
|
|
122
|
+
if (existsSync(modelsPath)) {
|
|
123
|
+
return modelsPath;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
async function discoverClaudeModels() {
|
|
131
|
+
try {
|
|
132
|
+
await execa("claude", ["--version"], {
|
|
133
|
+
timeout: 5e3,
|
|
134
|
+
stdin: "ignore",
|
|
135
|
+
env: { ...process.env, NO_COLOR: "1" }
|
|
136
|
+
});
|
|
137
|
+
} catch {
|
|
138
|
+
logger.debug("Claude CLI not available");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async function loadUserModels() {
|
|
142
|
+
const modelsPath = join(getAemeathHome(), "models.json");
|
|
143
|
+
try {
|
|
144
|
+
const raw = await readFile(modelsPath, "utf-8");
|
|
145
|
+
const parsed = JSON.parse(raw);
|
|
146
|
+
if (!Array.isArray(parsed)) return;
|
|
147
|
+
for (const entry of parsed) {
|
|
148
|
+
if (typeof entry === "object" && entry !== null && typeof entry.id === "string" && typeof entry.name === "string" && typeof entry.provider === "string") {
|
|
149
|
+
const e = entry;
|
|
150
|
+
addModel(
|
|
151
|
+
e.id,
|
|
152
|
+
e.name,
|
|
153
|
+
e.provider,
|
|
154
|
+
e.description,
|
|
155
|
+
e.contextWindow
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
} catch {
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function addModel(id, name, provider, description, contextWindow) {
|
|
163
|
+
dynamicModels[id] = makeModelInfo(id, name, provider, description, contextWindow);
|
|
164
|
+
if (!dynamicDisplayOrder[provider]) {
|
|
165
|
+
dynamicDisplayOrder[provider] = [];
|
|
166
|
+
}
|
|
167
|
+
if (!dynamicDisplayOrder[provider].some((e) => e.id === id)) {
|
|
168
|
+
dynamicDisplayOrder[provider].push({
|
|
169
|
+
id,
|
|
170
|
+
label: name,
|
|
171
|
+
description: description ?? ""
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function discoverModels() {
|
|
176
|
+
if (discoveryComplete) return;
|
|
177
|
+
await Promise.allSettled([
|
|
178
|
+
loadUserModels(),
|
|
179
|
+
discoverClaudeModels(),
|
|
180
|
+
discoverCodexModels(),
|
|
181
|
+
discoverGeminiModels()
|
|
182
|
+
]);
|
|
183
|
+
discoveryComplete = true;
|
|
184
|
+
const count = Object.keys(dynamicModels).length;
|
|
185
|
+
if (count > 0) {
|
|
186
|
+
logger.info({ count }, "Discovered additional models at runtime");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function registerModel(model) {
|
|
190
|
+
dynamicModels[model.id] = model;
|
|
191
|
+
const provider = model.provider;
|
|
192
|
+
if (!dynamicDisplayOrder[provider]) {
|
|
193
|
+
dynamicDisplayOrder[provider] = [];
|
|
194
|
+
}
|
|
195
|
+
if (!dynamicDisplayOrder[provider].some((e) => e.id === model.id)) {
|
|
196
|
+
dynamicDisplayOrder[provider].push({
|
|
197
|
+
id: model.id,
|
|
198
|
+
label: model.name,
|
|
199
|
+
description: model.description ?? ""
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function getModelInfo(modelId) {
|
|
204
|
+
return dynamicModels[modelId] ?? SUPPORTED_MODELS[modelId];
|
|
205
|
+
}
|
|
206
|
+
function getAllModels() {
|
|
207
|
+
return { ...SUPPORTED_MODELS, ...dynamicModels };
|
|
208
|
+
}
|
|
209
|
+
function getDisplayOrder() {
|
|
210
|
+
const result = {};
|
|
211
|
+
for (const [provider, entries] of Object.entries(PROVIDER_MODEL_ORDER)) {
|
|
212
|
+
result[provider] = [...entries];
|
|
213
|
+
}
|
|
214
|
+
for (const [provider, entries] of Object.entries(dynamicDisplayOrder)) {
|
|
215
|
+
if (!result[provider]) {
|
|
216
|
+
result[provider] = [];
|
|
217
|
+
}
|
|
218
|
+
for (const entry of entries) {
|
|
219
|
+
if (!result[provider].some((e) => e.id === entry.id)) {
|
|
220
|
+
result[provider].unshift(entry);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
function isKnownModel(modelId) {
|
|
227
|
+
return modelId in SUPPORTED_MODELS || modelId in dynamicModels;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export { discoverModels, getAllModels, getDisplayOrder, getModelInfo, isKnownModel, registerModel };
|
|
231
|
+
//# sourceMappingURL=chunk-FIC7AK4Q.js.map
|
|
232
|
+
//# sourceMappingURL=chunk-FIC7AK4Q.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/model-discovery.ts"],"names":[],"mappings":"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","file":"chunk-FIC7AK4Q.js","sourcesContent":["/**\r\n * Runtime model discovery — reads real model lists from provider CLIs\r\n * and user config. Merges with the hardcoded fallback registry.\r\n */\r\n\r\nimport { readFile } from \"node:fs/promises\";\r\nimport { dirname, join } from \"node:path\";\r\nimport { homedir } from \"node:os\";\r\nimport { existsSync } from \"node:fs\";\r\nimport { execa } from \"execa\";\r\nimport { logger } from \"../utils/logger.js\";\r\nimport { getAemeathHome } from \"../utils/pathResolver.js\";\r\nimport {\r\n SUPPORTED_MODELS,\r\n PROVIDER_MODEL_ORDER,\r\n type IModelInfo,\r\n type IModelDisplayEntry,\r\n type ProviderName,\r\n} from \"../types/model.js\";\r\n\r\n// ── Cache ────────────────────────────────────────────────────────────────\r\n\r\nlet discoveryComplete = false;\r\nconst dynamicModels: Record<string, IModelInfo> = {};\r\nconst dynamicDisplayOrder: Record<string, IModelDisplayEntry[]> = {};\r\n\r\n// ── Helper to create a model entry with defaults ────────────────────────\r\n\r\nfunction makeModelInfo(\r\n id: string,\r\n name: string,\r\n provider: ProviderName,\r\n description?: string,\r\n contextWindow?: number,\r\n): IModelInfo {\r\n return {\r\n id,\r\n name,\r\n provider,\r\n contextWindow: contextWindow ?? 200_000,\r\n maxOutputTokens: 16_384,\r\n inputPricePerMToken: 0,\r\n outputPricePerMToken: 0,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"coding\"],\r\n description,\r\n };\r\n}\r\n\r\n// ── Codex (OpenAI) discovery ────────────────────────────────────────────\r\n\r\nasync function discoverCodexModels(): Promise<void> {\r\n // 1. Read user's current model from ~/.codex/config.toml\r\n const configPath = join(homedir(), \".codex\", \"config.toml\");\r\n let currentModel: string | undefined;\r\n try {\r\n const raw = await readFile(configPath, \"utf-8\");\r\n const match = raw.match(/^model\\s*=\\s*\"([^\"]+)\"/m);\r\n if (match?.[1]) {\r\n currentModel = match[1];\r\n }\r\n } catch {\r\n // No config file\r\n }\r\n\r\n // 2. Try to get the interactive model list via `codex model` (needs TTY, may fail)\r\n // Fallback: run `codex exec --help` and extract model references\r\n try {\r\n const { stdout } = await execa(\"codex\", [\"exec\", \"--help\"], {\r\n timeout: 5000,\r\n stdin: \"ignore\",\r\n env: { ...process.env, NO_COLOR: \"1\" },\r\n });\r\n // Extract model IDs from help text (e.g. model=\"o3\")\r\n const modelRefs = stdout.matchAll(/model=\"([^\"]+)\"/g);\r\n for (const m of modelRefs) {\r\n const id = m[1];\r\n if (id && !SUPPORTED_MODELS[id] && !dynamicModels[id]) {\r\n addModel(id, id, \"openai\");\r\n }\r\n }\r\n } catch {\r\n // Codex not installed\r\n }\r\n\r\n // 3. If the user's current model isn't in our list, add it\r\n if (currentModel && !SUPPORTED_MODELS[currentModel] && !dynamicModels[currentModel]) {\r\n addModel(currentModel, currentModel, \"openai\", `User's current Codex model`);\r\n }\r\n\r\n // 4. Probe for known recent Codex models that may not be in our hardcoded list\r\n const knownCodexModels = [\r\n { id: \"gpt-5.4\", name: \"GPT-5.4\", desc: \"Latest frontier agentic coding model\" },\r\n { id: \"gpt-5.4-mini\", name: \"GPT-5.4 Mini\", desc: \"Smaller frontier agentic coding model\" },\r\n { id: \"o3\", name: \"o3\", desc: \"OpenAI o3 reasoning model\" },\r\n { id: \"o4-mini\", name: \"o4-mini\", desc: \"OpenAI o4-mini reasoning model\" },\r\n ];\r\n for (const m of knownCodexModels) {\r\n if (!SUPPORTED_MODELS[m.id] && !dynamicModels[m.id]) {\r\n addModel(m.id, m.name, \"openai\", m.desc);\r\n }\r\n }\r\n}\r\n\r\n// ── Gemini (Google) discovery ───────────────────────────────────────────\r\n\r\nasync function discoverGeminiModels(): Promise<void> {\r\n // 1. Read the Gemini CLI's models.js source for VALID_GEMINI_MODELS\r\n const geminiModelsPath = await findGeminiModelsFile();\r\n if (geminiModelsPath) {\r\n try {\r\n const source = await readFile(geminiModelsPath, \"utf-8\");\r\n\r\n // Extract model IDs from export const statements and Set entries\r\n const modelMatches = source.matchAll(/['\"]([^'\"]*gemini[^'\"]+)['\"]/g);\r\n for (const m of modelMatches) {\r\n const id = m[1];\r\n if (\r\n id &&\r\n !id.includes(\"embedding\") &&\r\n !id.includes(\"auto-\") &&\r\n !id.includes(\"customtools\") &&\r\n !SUPPORTED_MODELS[id] &&\r\n !dynamicModels[id]\r\n ) {\r\n const name = id\r\n .replace(/-preview$/, \" Preview\")\r\n .replace(/-lite$/, \" Lite\")\r\n .split(\"-\")\r\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\r\n .join(\" \");\r\n addModel(id, name, \"google\", undefined, 2_000_000);\r\n }\r\n }\r\n } catch {\r\n logger.debug(\"Failed to read Gemini CLI models source\");\r\n }\r\n }\r\n\r\n // 2. Fallback: probe known recent Gemini models\r\n const knownGeminiModels = [\r\n { id: \"gemini-3.1-pro-preview\", name: \"Gemini 3.1 Pro Preview\", desc: \"Latest Gemini Pro preview\" },\r\n { id: \"gemini-3.1-flash-lite-preview\", name: \"Gemini 3.1 Flash Lite Preview\", desc: \"Latest Flash Lite preview\" },\r\n { id: \"gemini-3-flash-preview\", name: \"Gemini 3 Flash Preview\", desc: \"Gemini 3 Flash preview\" },\r\n ];\r\n for (const m of knownGeminiModels) {\r\n if (!SUPPORTED_MODELS[m.id] && !dynamicModels[m.id]) {\r\n addModel(m.id, m.name, \"google\", m.desc, 2_000_000);\r\n }\r\n }\r\n}\r\n\r\n/** Find the Gemini CLI's models.js file in node_modules. */\r\nasync function findGeminiModelsFile(): Promise<string | undefined> {\r\n // Try to find via which gemini → resolve symlink → find models.js\r\n try {\r\n const { stdout } = await execa(\"which\", [\"gemini\"], {\r\n stdin: \"ignore\",\r\n timeout: 5_000,\r\n env: { ...process.env, NO_COLOR: \"1\" },\r\n });\r\n const whichResult = stdout.trim();\r\n if (whichResult) {\r\n // gemini binary is at e.g. /Users/x/.nvm/versions/node/v22.18.0/bin/gemini\r\n // models.js is at .../lib/node_modules/@google/gemini-cli/node_modules/@google/gemini-cli-core/dist/src/config/models.js\r\n const binDir = dirname(whichResult);\r\n const modelsPath = join(\r\n binDir,\r\n \"..\",\r\n \"lib\",\r\n \"node_modules\",\r\n \"@google\",\r\n \"gemini-cli\",\r\n \"node_modules\",\r\n \"@google\",\r\n \"gemini-cli-core\",\r\n \"dist\",\r\n \"src\",\r\n \"config\",\r\n \"models.js\",\r\n );\r\n if (existsSync(modelsPath)) {\r\n return modelsPath;\r\n }\r\n }\r\n } catch {\r\n // which not available or gemini not installed\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n// ── Claude (Anthropic) discovery ────────────────────────────────────────\r\n\r\nasync function discoverClaudeModels(): Promise<void> {\r\n // Claude models are well-known and change infrequently.\r\n // The hardcoded list is accurate. Just verify claude CLI exists.\r\n try {\r\n await execa(\"claude\", [\"--version\"], {\r\n timeout: 5000,\r\n stdin: \"ignore\",\r\n env: { ...process.env, NO_COLOR: \"1\" },\r\n });\r\n } catch {\r\n logger.debug(\"Claude CLI not available\");\r\n }\r\n}\r\n\r\n// ── User-defined models from ~/.aemeathcli/models.json ─────────────────\r\n\r\ninterface IUserModelEntry {\r\n readonly id: string;\r\n readonly name: string;\r\n readonly provider: string;\r\n readonly description?: string;\r\n readonly contextWindow?: number;\r\n}\r\n\r\nasync function loadUserModels(): Promise<void> {\r\n const modelsPath = join(getAemeathHome(), \"models.json\");\r\n try {\r\n const raw = await readFile(modelsPath, \"utf-8\");\r\n const parsed = JSON.parse(raw) as unknown;\r\n if (!Array.isArray(parsed)) return;\r\n\r\n for (const entry of parsed) {\r\n if (\r\n typeof entry === \"object\" &&\r\n entry !== null &&\r\n typeof (entry as IUserModelEntry).id === \"string\" &&\r\n typeof (entry as IUserModelEntry).name === \"string\" &&\r\n typeof (entry as IUserModelEntry).provider === \"string\"\r\n ) {\r\n const e = entry as IUserModelEntry;\r\n addModel(\r\n e.id,\r\n e.name,\r\n e.provider as ProviderName,\r\n e.description,\r\n e.contextWindow,\r\n );\r\n }\r\n }\r\n } catch {\r\n // File doesn't exist or invalid\r\n }\r\n}\r\n\r\n// ── Internal helpers ────────────────────────────────────────────────────\r\n\r\nfunction addModel(\r\n id: string,\r\n name: string,\r\n provider: ProviderName,\r\n description?: string,\r\n contextWindow?: number,\r\n): void {\r\n dynamicModels[id] = makeModelInfo(id, name, provider, description, contextWindow);\r\n\r\n if (!dynamicDisplayOrder[provider]) {\r\n dynamicDisplayOrder[provider] = [];\r\n }\r\n if (!dynamicDisplayOrder[provider].some((e) => e.id === id)) {\r\n dynamicDisplayOrder[provider].push({\r\n id,\r\n label: name,\r\n description: description ?? \"\",\r\n });\r\n }\r\n}\r\n\r\n// ── Public API ──────────────────────────────────────────────────────────\r\n\r\nexport async function discoverModels(): Promise<void> {\r\n if (discoveryComplete) return;\r\n\r\n await Promise.allSettled([\r\n loadUserModels(),\r\n discoverClaudeModels(),\r\n discoverCodexModels(),\r\n discoverGeminiModels(),\r\n ]);\r\n\r\n discoveryComplete = true;\r\n const count = Object.keys(dynamicModels).length;\r\n if (count > 0) {\r\n logger.info({ count }, \"Discovered additional models at runtime\");\r\n }\r\n}\r\n\r\nexport function registerModel(model: IModelInfo): void {\r\n dynamicModels[model.id] = model;\r\n const provider = model.provider;\r\n if (!dynamicDisplayOrder[provider]) {\r\n dynamicDisplayOrder[provider] = [];\r\n }\r\n if (!dynamicDisplayOrder[provider].some((e) => e.id === model.id)) {\r\n dynamicDisplayOrder[provider].push({\r\n id: model.id,\r\n label: model.name,\r\n description: model.description ?? \"\",\r\n });\r\n }\r\n}\r\n\r\nexport function getModelInfo(modelId: string): IModelInfo | undefined {\r\n return dynamicModels[modelId] ?? SUPPORTED_MODELS[modelId];\r\n}\r\n\r\nexport function getAllModels(): Record<string, IModelInfo> {\r\n return { ...SUPPORTED_MODELS, ...dynamicModels };\r\n}\r\n\r\nexport function getDisplayOrder(): Record<string, readonly IModelDisplayEntry[]> {\r\n const result: Record<string, IModelDisplayEntry[]> = {};\r\n\r\n for (const [provider, entries] of Object.entries(PROVIDER_MODEL_ORDER)) {\r\n result[provider] = [...entries];\r\n }\r\n\r\n // Prepend dynamic models to their provider group (new models show at top)\r\n for (const [provider, entries] of Object.entries(dynamicDisplayOrder)) {\r\n if (!result[provider]) {\r\n result[provider] = [];\r\n }\r\n for (const entry of entries) {\r\n if (!result[provider].some((e) => e.id === entry.id)) {\r\n result[provider].unshift(entry);\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport function isKnownModel(modelId: string): boolean {\r\n return modelId in SUPPORTED_MODELS || modelId in dynamicModels;\r\n}\r\n"]}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { ModelNotFoundError } from './chunk-473JN6M5.js';
|
|
2
|
+
import { SUPPORTED_MODELS } from './chunk-62HSGYQD.js';
|
|
3
|
+
import { logger } from './chunk-HEKFAKVH.js';
|
|
4
|
+
|
|
5
|
+
// src/core/model-router.ts
|
|
6
|
+
var ModelRouter = class {
|
|
7
|
+
config;
|
|
8
|
+
userOverride;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Set a temporary user override that takes highest priority.
|
|
14
|
+
*/
|
|
15
|
+
setUserOverride(modelId) {
|
|
16
|
+
if (modelId !== void 0) {
|
|
17
|
+
this.validateModel(modelId);
|
|
18
|
+
}
|
|
19
|
+
this.userOverride = modelId;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the best model for a given role through the priority pipeline.
|
|
23
|
+
*/
|
|
24
|
+
resolve(role) {
|
|
25
|
+
if (this.userOverride) {
|
|
26
|
+
const info = this.getModelInfo(this.userOverride);
|
|
27
|
+
return {
|
|
28
|
+
modelId: this.userOverride,
|
|
29
|
+
provider: info.provider,
|
|
30
|
+
source: "user_override",
|
|
31
|
+
role
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (role) {
|
|
35
|
+
const roleConfig = this.config.roles[role];
|
|
36
|
+
if (roleConfig) {
|
|
37
|
+
if (this.isModelAvailable(roleConfig.primary)) {
|
|
38
|
+
const info = this.getModelInfo(roleConfig.primary);
|
|
39
|
+
return {
|
|
40
|
+
modelId: roleConfig.primary,
|
|
41
|
+
provider: info.provider,
|
|
42
|
+
source: "role_config",
|
|
43
|
+
role
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
for (const fallbackModel of roleConfig.fallback) {
|
|
47
|
+
if (this.isModelAvailable(fallbackModel)) {
|
|
48
|
+
const info = this.getModelInfo(fallbackModel);
|
|
49
|
+
logger.info(
|
|
50
|
+
{ role, primary: roleConfig.primary, fallback: fallbackModel },
|
|
51
|
+
"Using fallback model for role"
|
|
52
|
+
);
|
|
53
|
+
return {
|
|
54
|
+
modelId: fallbackModel,
|
|
55
|
+
provider: info.provider,
|
|
56
|
+
source: "fallback_chain",
|
|
57
|
+
role
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const defaultModel = this.config.defaultModel;
|
|
64
|
+
if (this.isModelAvailable(defaultModel)) {
|
|
65
|
+
const info = this.getModelInfo(defaultModel);
|
|
66
|
+
return {
|
|
67
|
+
modelId: defaultModel,
|
|
68
|
+
provider: info.provider,
|
|
69
|
+
source: "system_default",
|
|
70
|
+
role
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const anyAvailable = this.getAvailableModels()[0];
|
|
74
|
+
if (anyAvailable) {
|
|
75
|
+
return {
|
|
76
|
+
modelId: anyAvailable.id,
|
|
77
|
+
provider: anyAvailable.provider,
|
|
78
|
+
source: "system_default",
|
|
79
|
+
role
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
throw new ModelNotFoundError(defaultModel);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check if a model is available (provider is enabled and model is known).
|
|
86
|
+
*/
|
|
87
|
+
isModelAvailable(modelId) {
|
|
88
|
+
const info = SUPPORTED_MODELS[modelId];
|
|
89
|
+
if (!info) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
return this.config.enabledProviders.includes(info.provider);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get model info by ID. Throws if not found.
|
|
96
|
+
*/
|
|
97
|
+
getModelInfo(modelId) {
|
|
98
|
+
const info = SUPPORTED_MODELS[modelId];
|
|
99
|
+
if (!info) {
|
|
100
|
+
throw new ModelNotFoundError(modelId);
|
|
101
|
+
}
|
|
102
|
+
return info;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get all available models (from enabled providers).
|
|
106
|
+
*/
|
|
107
|
+
getAvailableModels() {
|
|
108
|
+
return Object.values(SUPPORTED_MODELS).filter(
|
|
109
|
+
(model) => this.config.enabledProviders.includes(model.provider)
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* List models recommended for a specific role.
|
|
114
|
+
*/
|
|
115
|
+
getModelsForRole(role) {
|
|
116
|
+
return this.getAvailableModels().filter(
|
|
117
|
+
(model) => model.supportedRoles.includes(role)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Validate that a model ID exists. Throws ModelNotFoundError if not.
|
|
122
|
+
*/
|
|
123
|
+
validateModel(modelId) {
|
|
124
|
+
if (!SUPPORTED_MODELS[modelId]) {
|
|
125
|
+
throw new ModelNotFoundError(modelId);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
function createModelRouter(config) {
|
|
130
|
+
const enabledProviders = Object.entries(config.providers).filter(([, providerConfig]) => providerConfig.enabled).map(([name]) => name);
|
|
131
|
+
return new ModelRouter({
|
|
132
|
+
defaultModel: config.defaultModel,
|
|
133
|
+
roles: config.roles,
|
|
134
|
+
enabledProviders
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export { ModelRouter, createModelRouter };
|
|
139
|
+
//# sourceMappingURL=chunk-GU33WKPG.js.map
|
|
140
|
+
//# sourceMappingURL=chunk-GU33WKPG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/model-router.ts"],"names":[],"mappings":"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","file":"chunk-GU33WKPG.js","sourcesContent":["/**\r\n * Role-based model selection per PRD section 7.2\r\n * Resolution pipeline: user override → role config → fallback chain → system default\r\n */\r\n\r\nimport type {\r\n ModelRole,\r\n IModelResolution,\r\n IRoleConfig,\r\n IGlobalConfig,\r\n ProviderName,\r\n IModelInfo,\r\n} from \"../types/index.js\";\r\nimport { SUPPORTED_MODELS, ModelNotFoundError } from \"../types/index.js\";\r\nimport { logger } from \"../utils/index.js\";\r\n\r\nexport interface IModelRouterConfig {\r\n readonly defaultModel: string;\r\n readonly roles: Partial<Record<ModelRole, IRoleConfig>>;\r\n readonly enabledProviders: readonly ProviderName[];\r\n}\r\n\r\nexport class ModelRouter {\r\n private readonly config: IModelRouterConfig;\r\n private userOverride: string | undefined;\r\n\r\n constructor(config: IModelRouterConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Set a temporary user override that takes highest priority.\r\n */\r\n setUserOverride(modelId: string | undefined): void {\r\n if (modelId !== undefined) {\r\n this.validateModel(modelId);\r\n }\r\n this.userOverride = modelId;\r\n }\r\n\r\n /**\r\n * Resolve the best model for a given role through the priority pipeline.\r\n */\r\n resolve(role?: ModelRole): IModelResolution {\r\n // 1. User override (explicit flag: --model claude-opus-4-6)\r\n if (this.userOverride) {\r\n const info = this.getModelInfo(this.userOverride);\r\n return {\r\n modelId: this.userOverride,\r\n provider: info.provider,\r\n source: \"user_override\",\r\n role,\r\n };\r\n }\r\n\r\n // 2. Role config\r\n if (role) {\r\n const roleConfig = this.config.roles[role];\r\n if (roleConfig) {\r\n // Try primary model\r\n if (this.isModelAvailable(roleConfig.primary)) {\r\n const info = this.getModelInfo(roleConfig.primary);\r\n return {\r\n modelId: roleConfig.primary,\r\n provider: info.provider,\r\n source: \"role_config\",\r\n role,\r\n };\r\n }\r\n\r\n // 3. Fallback chain\r\n for (const fallbackModel of roleConfig.fallback) {\r\n if (this.isModelAvailable(fallbackModel)) {\r\n const info = this.getModelInfo(fallbackModel);\r\n logger.info(\r\n { role, primary: roleConfig.primary, fallback: fallbackModel },\r\n \"Using fallback model for role\",\r\n );\r\n return {\r\n modelId: fallbackModel,\r\n provider: info.provider,\r\n source: \"fallback_chain\",\r\n role,\r\n };\r\n }\r\n }\r\n }\r\n }\r\n\r\n // 4. System default\r\n const defaultModel = this.config.defaultModel;\r\n if (this.isModelAvailable(defaultModel)) {\r\n const info = this.getModelInfo(defaultModel);\r\n return {\r\n modelId: defaultModel,\r\n provider: info.provider,\r\n source: \"system_default\",\r\n role,\r\n };\r\n }\r\n\r\n // Last resort: find any available model\r\n const anyAvailable = this.getAvailableModels()[0];\r\n if (anyAvailable) {\r\n return {\r\n modelId: anyAvailable.id,\r\n provider: anyAvailable.provider,\r\n source: \"system_default\",\r\n role,\r\n };\r\n }\r\n\r\n throw new ModelNotFoundError(defaultModel);\r\n }\r\n\r\n /**\r\n * Check if a model is available (provider is enabled and model is known).\r\n */\r\n isModelAvailable(modelId: string): boolean {\r\n const info = SUPPORTED_MODELS[modelId];\r\n if (!info) {\r\n return false;\r\n }\r\n return this.config.enabledProviders.includes(info.provider);\r\n }\r\n\r\n /**\r\n * Get model info by ID. Throws if not found.\r\n */\r\n getModelInfo(modelId: string): IModelInfo {\r\n const info = SUPPORTED_MODELS[modelId];\r\n if (!info) {\r\n throw new ModelNotFoundError(modelId);\r\n }\r\n return info;\r\n }\r\n\r\n /**\r\n * Get all available models (from enabled providers).\r\n */\r\n getAvailableModels(): readonly IModelInfo[] {\r\n return Object.values(SUPPORTED_MODELS).filter((model) =>\r\n this.config.enabledProviders.includes(model.provider),\r\n );\r\n }\r\n\r\n /**\r\n * List models recommended for a specific role.\r\n */\r\n getModelsForRole(role: ModelRole): readonly IModelInfo[] {\r\n return this.getAvailableModels().filter((model) =>\r\n model.supportedRoles.includes(role),\r\n );\r\n }\r\n\r\n /**\r\n * Validate that a model ID exists. Throws ModelNotFoundError if not.\r\n */\r\n private validateModel(modelId: string): void {\r\n if (!SUPPORTED_MODELS[modelId]) {\r\n throw new ModelNotFoundError(modelId);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Create a ModelRouter from the global config.\r\n */\r\nexport function createModelRouter(config: IGlobalConfig): ModelRouter {\r\n const enabledProviders = Object.entries(config.providers)\r\n .filter(([, providerConfig]) => providerConfig.enabled)\r\n .map(([name]) => name as ProviderName);\r\n\r\n return new ModelRouter({\r\n defaultModel: config.defaultModel,\r\n roles: config.roles,\r\n enabledProviders,\r\n });\r\n}\r\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ApiKeyFallback } from './chunk-
|
|
2
|
-
import { CredentialStore } from './chunk-
|
|
3
|
-
import { AuthenticationError } from './chunk-
|
|
4
|
-
import { logger } from './chunk-
|
|
1
|
+
import { ApiKeyFallback } from './chunk-6GUD7QIM.js';
|
|
2
|
+
import { CredentialStore } from './chunk-AQ23TYSQ.js';
|
|
3
|
+
import { AuthenticationError } from './chunk-473JN6M5.js';
|
|
4
|
+
import { logger } from './chunk-HEKFAKVH.js';
|
|
5
5
|
|
|
6
6
|
// src/auth/session-manager.ts
|
|
7
7
|
var SessionManager = class {
|
|
@@ -124,19 +124,19 @@ var SessionManager = class {
|
|
|
124
124
|
try {
|
|
125
125
|
switch (provider) {
|
|
126
126
|
case "anthropic": {
|
|
127
|
-
const mod = await import('./claude-login-
|
|
127
|
+
const mod = await import('./claude-login-IS5WTBMP.js');
|
|
128
128
|
return new mod.ClaudeLogin(this.credentialStore);
|
|
129
129
|
}
|
|
130
130
|
case "openai": {
|
|
131
|
-
const mod = await import('./codex-login-
|
|
131
|
+
const mod = await import('./codex-login-GMPF64MR.js');
|
|
132
132
|
return new mod.CodexLogin(this.credentialStore);
|
|
133
133
|
}
|
|
134
134
|
case "google": {
|
|
135
|
-
const mod = await import('./gemini-login-
|
|
135
|
+
const mod = await import('./gemini-login-KE224MSW.js');
|
|
136
136
|
return new mod.GeminiLogin(this.credentialStore);
|
|
137
137
|
}
|
|
138
138
|
case "kimi": {
|
|
139
|
-
const mod = await import('./kimi-login-
|
|
139
|
+
const mod = await import('./kimi-login-DNT5YBKX.js');
|
|
140
140
|
return new mod.KimiLogin(this.credentialStore);
|
|
141
141
|
}
|
|
142
142
|
default:
|
|
@@ -177,5 +177,5 @@ var SessionManager = class {
|
|
|
177
177
|
};
|
|
178
178
|
|
|
179
179
|
export { SessionManager };
|
|
180
|
-
//# sourceMappingURL=chunk-
|
|
181
|
-
//# sourceMappingURL=chunk-
|
|
180
|
+
//# sourceMappingURL=chunk-H2SYKIMI.js.map
|
|
181
|
+
//# sourceMappingURL=chunk-H2SYKIMI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth/session-manager.ts"],"names":[],"mappings":"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","file":"chunk-H2SYKIMI.js","sourcesContent":["/**\r\n * Multi-provider session lifecycle per PRD section 13.5\r\n * Resolution priority: native login (CLI delegation) > API key > env variable > credential helper\r\n *\r\n * Credentials are obtained by delegating to official CLI tools:\r\n * - Claude Code CLI → macOS Keychain\r\n * - Codex CLI → ~/.codex/auth.json\r\n * - Gemini CLI → ~/.gemini/oauth_creds.json\r\n * - Kimi CLI → ~/.kimi/credentials/kimi-code.json\r\n */\r\n\r\nimport type { ProviderName, ICredential, AuthMethod } from \"../types/index.js\";\r\nimport { AuthenticationError } from \"../types/index.js\";\r\nimport { CredentialStore } from \"./credential-store.js\";\r\nimport { ApiKeyFallback } from \"./api-key-fallback.js\";\r\nimport { logger } from \"../utils/index.js\";\r\n\r\nexport class SessionManager {\r\n private readonly credentialStore: CredentialStore;\r\n private readonly apiKeyFallback: ApiKeyFallback;\r\n\r\n constructor(store?: CredentialStore) {\r\n this.credentialStore = store ?? new CredentialStore();\r\n this.apiKeyFallback = new ApiKeyFallback(this.credentialStore);\r\n }\r\n\r\n /**\r\n * Get the best available credential for a provider.\r\n * Follows resolution priority from PRD section 13.5.\r\n */\r\n async getActiveCredential(provider: ProviderName): Promise<ICredential> {\r\n // 1. Native account session (delegated CLI login — stored in our credential store)\r\n const nativeCredential = await this.credentialStore.get(provider);\r\n if (nativeCredential && nativeCredential.method === \"native_login\" && !this.isExpired(nativeCredential)) {\r\n return nativeCredential;\r\n }\r\n\r\n // 1b. If expired, try re-reading from the official CLI's cached tokens\r\n if (nativeCredential && nativeCredential.method === \"native_login\" && this.isExpired(nativeCredential)) {\r\n const refreshed = await this.refreshFromCliCache(provider);\r\n if (refreshed) {\r\n return refreshed;\r\n }\r\n }\r\n\r\n // 1c. Even if no native credential stored, check CLI caches directly\r\n if (!nativeCredential || nativeCredential.method !== \"native_login\") {\r\n const fromCli = await this.refreshFromCliCache(provider);\r\n if (fromCli) {\r\n return fromCli;\r\n }\r\n }\r\n\r\n // 2. API key set via auth set-key\r\n const apiKeyCredential = await this.apiKeyFallback.getCredential(provider);\r\n if (apiKeyCredential) {\r\n return apiKeyCredential;\r\n }\r\n\r\n // 3. Environment variable\r\n const envCredential = this.getFromEnvironment(provider);\r\n if (envCredential) {\r\n return envCredential;\r\n }\r\n\r\n throw new AuthenticationError(provider, `No credentials found for ${provider}`);\r\n }\r\n\r\n /**\r\n * Check if a provider has any available credential.\r\n */\r\n async isAuthenticated(provider: ProviderName): Promise<boolean> {\r\n try {\r\n await this.getActiveCredential(provider);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get status info for a provider.\r\n */\r\n async getStatus(provider: ProviderName): Promise<{\r\n loggedIn: boolean;\r\n method?: AuthMethod | undefined;\r\n email?: string | undefined;\r\n plan?: string | undefined;\r\n }> {\r\n try {\r\n const credential = await this.getActiveCredential(provider);\r\n return {\r\n loggedIn: true,\r\n method: credential.method,\r\n ...(credential.email !== undefined ? { email: credential.email } : {}),\r\n ...(credential.plan !== undefined ? { plan: credential.plan } : {}),\r\n };\r\n } catch {\r\n return { loggedIn: false };\r\n }\r\n }\r\n\r\n /**\r\n * Get the API key or token string for a provider.\r\n */\r\n async getToken(provider: ProviderName): Promise<string> {\r\n const credential = await this.getActiveCredential(provider);\r\n if (!credential.token) {\r\n throw new AuthenticationError(provider, \"Credential has no token\");\r\n }\r\n return credential.token;\r\n }\r\n\r\n /**\r\n * Re-read tokens from the official CLI's cached storage.\r\n * This is the \"refresh\" mechanism — instead of doing HTTP refresh ourselves,\r\n * we re-read from the CLI tool's cache which may have been refreshed by the CLI.\r\n */\r\n private async refreshFromCliCache(provider: ProviderName): Promise<ICredential | undefined> {\r\n try {\r\n const loginModule = await this.loadLoginModule(provider);\r\n if (!loginModule) {\r\n return undefined;\r\n }\r\n\r\n // Prefer direct cached credential extraction from the provider login module.\r\n if (typeof loginModule.getCachedCredential === \"function\") {\r\n const cached = await loginModule.getCachedCredential();\r\n if (cached) {\r\n await this.credentialStore.set(provider, cached);\r\n if (!this.isExpired(cached) || cached.refreshToken !== undefined) {\r\n logger.info({ provider }, \"Loaded credentials from provider CLI cache\");\r\n return cached;\r\n }\r\n }\r\n }\r\n\r\n const status = await loginModule.getStatus();\r\n if (!status.loggedIn) {\r\n return undefined;\r\n }\r\n\r\n // The login module reads from the CLI's cache, check if we can get a fresh credential\r\n const isStillLoggedIn = await loginModule.isLoggedIn();\r\n if (!isStillLoggedIn) {\r\n return undefined;\r\n }\r\n\r\n // Re-read by checking the stored credential in our store\r\n // The login modules update the credential store when they find valid tokens\r\n const credential = await this.credentialStore.get(provider);\r\n if (credential && !this.isExpired(credential)) {\r\n logger.info({ provider }, \"Refreshed credentials from CLI cache\");\r\n return credential;\r\n }\r\n\r\n return undefined;\r\n } catch (error: unknown) {\r\n const msg = error instanceof Error ? error.message : String(error);\r\n logger.debug({ provider, error: msg }, \"Failed to refresh from CLI cache\");\r\n return undefined;\r\n }\r\n }\r\n\r\n private async loadLoginModule(provider: ProviderName): Promise<{\r\n getStatus(): Promise<{ loggedIn: boolean; email?: string | undefined; plan?: string | undefined }>;\r\n isLoggedIn(): Promise<boolean>;\r\n getCachedCredential?(): Promise<ICredential | undefined>;\r\n } | undefined> {\r\n try {\r\n switch (provider) {\r\n case \"anthropic\": {\r\n const mod = await import(\"./providers/claude-login.js\");\r\n return new mod.ClaudeLogin(this.credentialStore);\r\n }\r\n case \"openai\": {\r\n const mod = await import(\"./providers/codex-login.js\");\r\n return new mod.CodexLogin(this.credentialStore);\r\n }\r\n case \"google\": {\r\n const mod = await import(\"./providers/gemini-login.js\");\r\n return new mod.GeminiLogin(this.credentialStore);\r\n }\r\n case \"kimi\": {\r\n const mod = await import(\"./providers/kimi-login.js\");\r\n return new mod.KimiLogin(this.credentialStore);\r\n }\r\n default:\r\n return undefined;\r\n }\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private isExpired(credential: ICredential): boolean {\r\n if (!credential.expiresAt) {\r\n return false;\r\n }\r\n return new Date() > credential.expiresAt;\r\n }\r\n\r\n private getFromEnvironment(provider: ProviderName): ICredential | undefined {\r\n const envMap: Record<ProviderName, string> = {\r\n anthropic: \"ANTHROPIC_API_KEY\",\r\n openai: \"OPENAI_API_KEY\",\r\n google: \"GOOGLE_API_KEY\",\r\n kimi: \"MOONSHOT_API_KEY\",\r\n ollama: \"\",\r\n };\r\n\r\n const envKey = envMap[provider];\r\n if (!envKey) {\r\n return undefined;\r\n }\r\n\r\n const token = process.env[envKey];\r\n if (!token) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n provider,\r\n method: \"env_variable\",\r\n token,\r\n };\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts"],"names":[],"mappings":";;;;;;AAUA,IAAM,OAAA,GAAU,IAAA,CAAK,OAAA,EAAQ,EAAG,eAAe,MAAM,CAAA;AAErD,SAAS,YAAA,GAAqB;AAC5B,EAAA,IAAI;AACF,IAAA,SAAA,CAAU,SAAS,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,KAAO,CAAA;AAAA,EACrD,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAGA,IAAM,YAAA,GAAe;AAAA,EACnB,OAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,gBAAA;AAAA,EACA,UAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA;AAEA,YAAA,EAAa;AAEb,IAAM,SAAS,IAAA,CAAK;AAAA,EAClB,IAAA,EAAM,YAAA;AAAA,EACN,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,sBAAsB,CAAA,IAAK,OAAA;AAAA,EAC9C,MAAA,EAAQ;AAAA,IACN,KAAA,EAAO,YAAA;AAAA,IACP,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,GAAI,OAAA,CAAQ,GAAA,CAAI,UAAU,MAAM,aAAA,GAC5B;AAAA,IACE,SAAA,EAAW;AAAA,MACT,MAAA,EAAQ,WAAA;AAAA,MACR,OAAA,EAAS,EAAE,WAAA,EAAa,IAAA,CAAK,SAAS,gBAAgB,CAAA,EAAG,OAAO,IAAA;AAAK;AACvE,MAEF,EAAC;AAAA,EACL,SAAA,EAAW,KAAK,gBAAA,CAAiB;AACnC,CAAC","file":"chunk-HEKFAKVH.js","sourcesContent":["/**\r\n * Structured logging via pino per PRD section 16.1\r\n * Automatic credential redaction per PRD section 14.1\r\n */\r\n\r\nimport pino from \"pino\";\r\nimport { homedir } from \"node:os\";\r\nimport { join } from \"node:path\";\r\nimport { mkdirSync } from \"node:fs\";\r\n\r\nconst LOG_DIR = join(homedir(), \".aemeathcli\", \"logs\");\r\n\r\nfunction ensureLogDir(): void {\r\n try {\r\n mkdirSync(LOG_DIR, { recursive: true, mode: 0o700 });\r\n } catch {\r\n // Log dir creation failed — fall back to stderr only\r\n }\r\n}\r\n\r\n// Redaction patterns for credentials (PRD section 14.2 REQ-CRED-04)\r\nconst REDACT_PATHS = [\r\n \"token\",\r\n \"refreshToken\",\r\n \"apiKey\",\r\n \"accessToken\",\r\n \"sessionToken\",\r\n \"password\",\r\n \"secret\",\r\n \"authorization\",\r\n \"cookie\",\r\n \"*.token\",\r\n \"*.refreshToken\",\r\n \"*.apiKey\",\r\n \"*.accessToken\",\r\n \"*.sessionToken\",\r\n \"*.password\",\r\n \"*.secret\",\r\n];\r\n\r\nensureLogDir();\r\n\r\nconst logger = pino({\r\n name: \"aemeathcli\",\r\n level: process.env[\"AEMEATHCLI_LOG_LEVEL\"] ?? \"error\",\r\n redact: {\r\n paths: REDACT_PATHS,\r\n censor: \"[REDACTED]\",\r\n },\r\n ...(process.env[\"NODE_ENV\"] === \"development\"\r\n ? {\r\n transport: {\r\n target: \"pino/file\",\r\n options: { destination: join(LOG_DIR, \"aemeathcli.log\"), mkdir: true },\r\n },\r\n }\r\n : {}),\r\n timestamp: pino.stdTimeFunctions.isoTime,\r\n});\r\n\r\nexport { logger };\r\n"]}
|