aemeathcli 1.0.10 → 1.0.12
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 +66 -54
- package/dist/App-JQ622M66.js +4431 -0
- package/dist/App-JQ622M66.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-RJLPM3KH.js +11 -0
- package/dist/{api-key-fallback-YQQBOQIL.js.map → api-key-fallback-RJLPM3KH.js.map} +1 -1
- package/dist/auth-status-JQJOKUPF.js +13 -0
- package/dist/auth-status-JQJOKUPF.js.map +1 -0
- package/dist/{chunk-RWCNNAL7.js → chunk-2KMA5RBC.js} +25 -48
- package/dist/chunk-2KMA5RBC.js.map +1 -0
- package/dist/{chunk-CYQNBB25.js → chunk-2Y7TR6BS.js} +28 -5
- package/dist/chunk-2Y7TR6BS.js.map +1 -0
- package/dist/{chunk-DAHGLHNR.js → chunk-2ZYK5IJG.js} +6 -141
- package/dist/chunk-2ZYK5IJG.js.map +1 -0
- package/dist/chunk-36RXCZOV.js +88 -0
- package/dist/chunk-36RXCZOV.js.map +1 -0
- package/dist/{chunk-DMBPX3RG.js → chunk-7EBLXPL4.js} +9 -9
- package/dist/{chunk-DMBPX3RG.js.map → chunk-7EBLXPL4.js.map} +1 -1
- package/dist/chunk-BIMQL4AG.js +186 -0
- package/dist/chunk-BIMQL4AG.js.map +1 -0
- package/dist/{chunk-NBR3GHMT.js → chunk-D275MCIH.js} +39 -7
- package/dist/chunk-D275MCIH.js.map +1 -0
- package/dist/{chunk-Y5XVD2CD.js → chunk-FFS4T7BZ.js} +109 -82
- package/dist/chunk-FFS4T7BZ.js.map +1 -0
- package/dist/{chunk-CARHU3DO.js → chunk-GXAJGP2T.js} +64 -16
- package/dist/chunk-GXAJGP2T.js.map +1 -0
- package/dist/{chunk-I5PZ4JTS.js → chunk-HESQLCLU.js} +4 -4
- package/dist/{chunk-I5PZ4JTS.js.map → chunk-HESQLCLU.js.map} +1 -1
- package/dist/{chunk-JAXXTYID.js → chunk-IR5HLBMH.js} +2 -2
- package/dist/{chunk-JAXXTYID.js.map → chunk-IR5HLBMH.js.map} +1 -1
- package/dist/{chunk-MFBHNWGV.js → chunk-K2FCMRXH.js} +11 -19
- package/dist/chunk-K2FCMRXH.js.map +1 -0
- package/dist/{chunk-H66O5Z2V.js → chunk-KIC7UI5U.js} +41 -6
- package/dist/chunk-KIC7UI5U.js.map +1 -0
- package/dist/{chunk-MXZSI3AY.js → chunk-KMOAJRDE.js} +42 -10
- package/dist/chunk-KMOAJRDE.js.map +1 -0
- package/dist/chunk-LQBALETG.js +71 -0
- package/dist/chunk-LQBALETG.js.map +1 -0
- package/dist/chunk-M3FPQSRU.js +12 -0
- package/dist/chunk-M3FPQSRU.js.map +1 -0
- package/dist/chunk-NQEUK763.js +26 -0
- package/dist/chunk-NQEUK763.js.map +1 -0
- package/dist/chunk-OPWAFS6Y.js +38 -0
- package/dist/chunk-OPWAFS6Y.js.map +1 -0
- package/dist/{chunk-6PDJ45T4.js → chunk-PS4WEFW6.js} +50 -25
- package/dist/chunk-PS4WEFW6.js.map +1 -0
- package/dist/{chunk-HMJRPNPZ.js → chunk-QK7TKNHV.js} +93 -21
- package/dist/chunk-QK7TKNHV.js.map +1 -0
- package/dist/{chunk-LSOYPSAT.js → chunk-RADJSEG5.js} +4 -4
- package/dist/chunk-RADJSEG5.js.map +1 -0
- package/dist/{chunk-4IJD72YB.js → chunk-SNWPI6XJ.js} +7 -7
- package/dist/chunk-SNWPI6XJ.js.map +1 -0
- package/dist/{chunk-TEVZS4FA.js → chunk-UM7MSLOV.js} +16 -9
- package/dist/chunk-UM7MSLOV.js.map +1 -0
- package/dist/chunk-VNZ3YTQD.js +232 -0
- package/dist/chunk-VNZ3YTQD.js.map +1 -0
- package/dist/{chunk-IYW62KKR.js → chunk-WXIN65UG.js} +66 -23
- package/dist/chunk-WXIN65UG.js.map +1 -0
- package/dist/chunk-XEXWX7C7.js +241 -0
- package/dist/chunk-XEXWX7C7.js.map +1 -0
- package/dist/{chunk-CGEV3ARR.js → chunk-YCCYXDW7.js} +3 -3
- package/dist/chunk-YCCYXDW7.js.map +1 -0
- package/dist/chunk-YPQ2MLAV.js +140 -0
- package/dist/chunk-YPQ2MLAV.js.map +1 -0
- package/dist/chunk-ZCOVMVK4.js +26 -0
- package/dist/chunk-ZCOVMVK4.js.map +1 -0
- package/dist/{claude-login-5WELXPKT.js → claude-login-AIFIWTYF.js} +9 -9
- package/dist/{claude-login-5WELXPKT.js.map → claude-login-AIFIWTYF.js.map} +1 -1
- package/dist/cli.js +370 -171
- package/dist/cli.js.map +1 -1
- package/dist/{codex-login-GZIFXUWD.js → codex-login-LW5X7GAM.js} +10 -10
- package/dist/codex-login-LW5X7GAM.js.map +1 -0
- package/dist/config-store-NF56VHFU.js +7 -0
- package/dist/{config-store-W6FBCQAQ.js.map → config-store-NF56VHFU.js.map} +1 -1
- package/dist/conversation-store-7GRDQZD2.js +4 -0
- package/dist/conversation-store-7GRDQZD2.js.map +1 -0
- package/dist/detect-providers-QICJ5U3R.js +4 -0
- package/dist/detect-providers-QICJ5U3R.js.map +1 -0
- package/dist/executor-FTABX2AW.js +4 -0
- package/dist/{executor-6RIKIGXK.js.map → executor-FTABX2AW.js.map} +1 -1
- package/dist/first-run-ADROZVYF.js +230 -0
- package/dist/first-run-ADROZVYF.js.map +1 -0
- package/dist/{gemini-login-AZGL3CE7.js → gemini-login-TST454MX.js} +9 -9
- package/dist/{gemini-login-AZGL3CE7.js.map → gemini-login-TST454MX.js.map} +1 -1
- package/dist/index.d.ts +46 -70
- package/dist/index.js +79 -468
- package/dist/index.js.map +1 -1
- package/dist/input-history-BEICE7PT.js +57 -0
- package/dist/input-history-BEICE7PT.js.map +1 -0
- package/dist/kimi-adapter-7FYOAKOI.js +6 -0
- package/dist/{kimi-adapter-JN4HFFHU.js.map → kimi-adapter-7FYOAKOI.js.map} +1 -1
- package/dist/{kimi-login-6LUWB7P6.js → kimi-login-3IGVOBJI.js} +9 -9
- package/dist/{kimi-login-6LUWB7P6.js.map → kimi-login-3IGVOBJI.js.map} +1 -1
- package/dist/logger-KGHUQ4VE.js +3 -0
- package/dist/logger-KGHUQ4VE.js.map +1 -0
- package/dist/model-discovery-AAJDHRFO.js +6 -0
- package/dist/model-discovery-AAJDHRFO.js.map +1 -0
- package/dist/native-cli-adapters-CLONTZOA.js +8 -0
- package/dist/{native-cli-adapters-OLW3XX57.js.map → native-cli-adapters-CLONTZOA.js.map} +1 -1
- package/dist/ollama-adapter-2N5OQIEV.js +5 -0
- package/dist/{ollama-adapter-OJQ3FKWK.js.map → ollama-adapter-2N5OQIEV.js.map} +1 -1
- package/dist/pathResolver-UVAB2FCW.js +3 -0
- package/dist/pathResolver-UVAB2FCW.js.map +1 -0
- package/dist/profile-loader-EMLV4J7S.js +162 -0
- package/dist/profile-loader-EMLV4J7S.js.map +1 -0
- package/dist/registry-LRURZVUL.js +5 -0
- package/dist/{registry-AZ2LOHHJ.js.map → registry-LRURZVUL.js.map} +1 -1
- package/dist/registry-MVNSXCEF.js +6 -0
- package/dist/{registry-H7B3AHPQ.js.map → registry-MVNSXCEF.js.map} +1 -1
- package/dist/server-manager-THGZBBZB.js +5 -0
- package/dist/{server-manager-PTGBHCLS.js.map → server-manager-THGZBBZB.js.map} +1 -1
- package/dist/session-manager-X3DXT53M.js +12 -0
- package/dist/{session-manager-XOMDMC77.js.map → session-manager-X3DXT53M.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-7OECRTXM.js +5 -0
- package/dist/sqlite-store-7OECRTXM.js.map +1 -0
- package/dist/team-manager-2VSMALAA.js +11 -0
- package/dist/{team-manager-HC4XGCFY.js.map → team-manager-2VSMALAA.js.map} +1 -1
- package/dist/team-state-HZNVMQHT.js +3 -0
- package/dist/team-state-HZNVMQHT.js.map +1 -0
- package/dist/tmux-manager-57QCUVHU.js +6 -0
- package/dist/{tmux-manager-GPYZ3WQH.js.map → tmux-manager-57QCUVHU.js.map} +1 -1
- package/dist/tools-KWFSYT56.js +6 -0
- package/dist/{tools-TSMXMHIF.js.map → tools-KWFSYT56.js.map} +1 -1
- package/package.json +11 -11
- 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-H66O5Z2V.js.map +0 -1
- package/dist/chunk-HMJRPNPZ.js.map +0 -1
- package/dist/chunk-IYW62KKR.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 +0 -211
- 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 +0 -234
- package/dist/chunk-WPP3PEDE.js.map +0 -1
- package/dist/chunk-Y5XVD2CD.js.map +0 -1
- package/dist/claude-adapter-QMLFMSP3.js +0 -6
- package/dist/claude-adapter-QMLFMSP3.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-adapter-6JIHZ7WI.js.map +0 -1
- package/dist/kimi-adapter-JN4HFFHU.js +0 -6
- 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/openai-adapter-XU46EN7B.js.map +0 -1
- 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,241 @@
|
|
|
1
|
+
import { logger } from './chunk-IR5HLBMH.js';
|
|
2
|
+
import { randomUUID } from 'crypto';
|
|
3
|
+
|
|
4
|
+
var ConversationStore = class {
|
|
5
|
+
store;
|
|
6
|
+
constructor(store) {
|
|
7
|
+
this.store = store;
|
|
8
|
+
}
|
|
9
|
+
createConversation(projectRoot, defaultModel, metadata) {
|
|
10
|
+
const id = randomUUID();
|
|
11
|
+
const metadataJson = JSON.stringify(metadata ?? {});
|
|
12
|
+
this.store.run(
|
|
13
|
+
`INSERT INTO conversations (id, project_root, default_model, metadata)
|
|
14
|
+
VALUES (?, ?, ?, ?)`,
|
|
15
|
+
id,
|
|
16
|
+
projectRoot,
|
|
17
|
+
defaultModel ?? null,
|
|
18
|
+
metadataJson
|
|
19
|
+
);
|
|
20
|
+
logger.info({ conversationId: id, projectRoot }, "Conversation created");
|
|
21
|
+
const row = this.store.get(
|
|
22
|
+
"SELECT * FROM conversations WHERE id = ?",
|
|
23
|
+
id
|
|
24
|
+
);
|
|
25
|
+
if (!row) {
|
|
26
|
+
throw new Error(`Failed to retrieve created conversation: ${id}`);
|
|
27
|
+
}
|
|
28
|
+
return this.mapConversationRow(row);
|
|
29
|
+
}
|
|
30
|
+
getConversation(id) {
|
|
31
|
+
const row = this.store.get(
|
|
32
|
+
"SELECT * FROM conversations WHERE id = ?",
|
|
33
|
+
id
|
|
34
|
+
);
|
|
35
|
+
return row ? this.mapConversationRow(row) : void 0;
|
|
36
|
+
}
|
|
37
|
+
listConversations(projectRoot) {
|
|
38
|
+
const rows = projectRoot ? this.store.all(
|
|
39
|
+
"SELECT * FROM conversations WHERE project_root = ? ORDER BY updated_at DESC",
|
|
40
|
+
projectRoot
|
|
41
|
+
) : this.store.all(
|
|
42
|
+
"SELECT * FROM conversations ORDER BY updated_at DESC"
|
|
43
|
+
);
|
|
44
|
+
return rows.map((row) => this.mapConversationRow(row));
|
|
45
|
+
}
|
|
46
|
+
deleteConversation(id) {
|
|
47
|
+
this.store.run("DELETE FROM conversations WHERE id = ?", id);
|
|
48
|
+
logger.info({ conversationId: id }, "Conversation deleted");
|
|
49
|
+
}
|
|
50
|
+
addMessage(params) {
|
|
51
|
+
const toolCallsJson = params.toolCalls ? JSON.stringify(params.toolCalls) : null;
|
|
52
|
+
const tokenUsageJson = params.tokenUsage ? JSON.stringify(params.tokenUsage) : null;
|
|
53
|
+
const result = this.store.run(
|
|
54
|
+
`INSERT INTO messages
|
|
55
|
+
(conversation_id, role, model, provider, content, tool_calls, token_usage)
|
|
56
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
57
|
+
params.conversationId,
|
|
58
|
+
params.role,
|
|
59
|
+
params.model ?? null,
|
|
60
|
+
params.provider ?? null,
|
|
61
|
+
params.content,
|
|
62
|
+
toolCallsJson,
|
|
63
|
+
tokenUsageJson
|
|
64
|
+
);
|
|
65
|
+
this.store.run(
|
|
66
|
+
"UPDATE conversations SET updated_at = datetime('now') WHERE id = ?",
|
|
67
|
+
params.conversationId
|
|
68
|
+
);
|
|
69
|
+
const row = this.store.get(
|
|
70
|
+
"SELECT * FROM messages WHERE id = ?",
|
|
71
|
+
result.lastInsertRowid
|
|
72
|
+
);
|
|
73
|
+
if (!row) {
|
|
74
|
+
throw new Error("Failed to retrieve created message");
|
|
75
|
+
}
|
|
76
|
+
return this.mapMessageRow(row);
|
|
77
|
+
}
|
|
78
|
+
getMessages(conversationId, pagination) {
|
|
79
|
+
const limit = pagination?.limit ?? 100;
|
|
80
|
+
const offset = pagination?.offset ?? 0;
|
|
81
|
+
const rows = this.store.all(
|
|
82
|
+
`SELECT * FROM messages
|
|
83
|
+
WHERE conversation_id = ?
|
|
84
|
+
ORDER BY created_at ASC
|
|
85
|
+
LIMIT ? OFFSET ?`,
|
|
86
|
+
conversationId,
|
|
87
|
+
limit,
|
|
88
|
+
offset
|
|
89
|
+
);
|
|
90
|
+
return rows.map((row) => this.mapMessageRow(row));
|
|
91
|
+
}
|
|
92
|
+
getMessageCount(conversationId) {
|
|
93
|
+
const result = this.store.get(
|
|
94
|
+
"SELECT COUNT(*) as count FROM messages WHERE conversation_id = ?",
|
|
95
|
+
conversationId
|
|
96
|
+
);
|
|
97
|
+
return result?.count ?? 0;
|
|
98
|
+
}
|
|
99
|
+
addFileContext(params) {
|
|
100
|
+
const result = this.store.run(
|
|
101
|
+
`INSERT INTO file_context
|
|
102
|
+
(conversation_id, file_path, content_hash, token_count)
|
|
103
|
+
VALUES (?, ?, ?, ?)`,
|
|
104
|
+
params.conversationId,
|
|
105
|
+
params.filePath,
|
|
106
|
+
params.contentHash ?? null,
|
|
107
|
+
params.tokenCount ?? null
|
|
108
|
+
);
|
|
109
|
+
const row = this.store.get(
|
|
110
|
+
"SELECT * FROM file_context WHERE id = ?",
|
|
111
|
+
result.lastInsertRowid
|
|
112
|
+
);
|
|
113
|
+
if (!row) {
|
|
114
|
+
throw new Error("Failed to retrieve created file context");
|
|
115
|
+
}
|
|
116
|
+
return this.mapFileContextRow(row);
|
|
117
|
+
}
|
|
118
|
+
getFileContext(conversationId) {
|
|
119
|
+
const rows = this.store.all(
|
|
120
|
+
"SELECT * FROM file_context WHERE conversation_id = ? ORDER BY added_at DESC",
|
|
121
|
+
conversationId
|
|
122
|
+
);
|
|
123
|
+
return rows.map((row) => this.mapFileContextRow(row));
|
|
124
|
+
}
|
|
125
|
+
removeFileContext(conversationId, filePath) {
|
|
126
|
+
this.store.run(
|
|
127
|
+
"DELETE FROM file_context WHERE conversation_id = ? AND file_path = ?",
|
|
128
|
+
conversationId,
|
|
129
|
+
filePath
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
addCost(params) {
|
|
133
|
+
const result = this.store.run(
|
|
134
|
+
`INSERT INTO cost_tracking
|
|
135
|
+
(conversation_id, provider, model, role, input_tokens, output_tokens, cost_usd)
|
|
136
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
137
|
+
params.conversationId,
|
|
138
|
+
params.provider,
|
|
139
|
+
params.model,
|
|
140
|
+
params.role ?? null,
|
|
141
|
+
params.inputTokens ?? null,
|
|
142
|
+
params.outputTokens ?? null,
|
|
143
|
+
params.costUsd ?? null
|
|
144
|
+
);
|
|
145
|
+
const row = this.store.get(
|
|
146
|
+
"SELECT * FROM cost_tracking WHERE id = ?",
|
|
147
|
+
result.lastInsertRowid
|
|
148
|
+
);
|
|
149
|
+
if (!row) {
|
|
150
|
+
throw new Error("Failed to retrieve created cost entry");
|
|
151
|
+
}
|
|
152
|
+
return this.mapCostRow(row);
|
|
153
|
+
}
|
|
154
|
+
getConversationCost(conversationId) {
|
|
155
|
+
const result = this.store.get(
|
|
156
|
+
"SELECT SUM(cost_usd) as total FROM cost_tracking WHERE conversation_id = ?",
|
|
157
|
+
conversationId
|
|
158
|
+
);
|
|
159
|
+
return result?.total ?? 0;
|
|
160
|
+
}
|
|
161
|
+
getCostBreakdown(conversationId) {
|
|
162
|
+
const rows = this.store.all(
|
|
163
|
+
"SELECT * FROM cost_tracking WHERE conversation_id = ? ORDER BY created_at ASC",
|
|
164
|
+
conversationId
|
|
165
|
+
);
|
|
166
|
+
return rows.map((row) => this.mapCostRow(row));
|
|
167
|
+
}
|
|
168
|
+
// ── Private row mappers ─────────────────────────────────────────────
|
|
169
|
+
mapConversationRow(row) {
|
|
170
|
+
let metadata = {};
|
|
171
|
+
try {
|
|
172
|
+
metadata = JSON.parse(row.metadata);
|
|
173
|
+
} catch {
|
|
174
|
+
metadata = {};
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
id: row.id,
|
|
178
|
+
projectRoot: row.project_root,
|
|
179
|
+
defaultModel: row.default_model,
|
|
180
|
+
createdAt: row.created_at,
|
|
181
|
+
updatedAt: row.updated_at,
|
|
182
|
+
metadata
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
mapMessageRow(row) {
|
|
186
|
+
let toolCalls = null;
|
|
187
|
+
if (row.tool_calls) {
|
|
188
|
+
try {
|
|
189
|
+
toolCalls = JSON.parse(row.tool_calls);
|
|
190
|
+
} catch {
|
|
191
|
+
toolCalls = null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
let tokenUsage = null;
|
|
195
|
+
if (row.token_usage) {
|
|
196
|
+
try {
|
|
197
|
+
tokenUsage = JSON.parse(row.token_usage);
|
|
198
|
+
} catch {
|
|
199
|
+
tokenUsage = null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
id: row.id,
|
|
204
|
+
conversationId: row.conversation_id,
|
|
205
|
+
role: row.role,
|
|
206
|
+
model: row.model,
|
|
207
|
+
provider: row.provider,
|
|
208
|
+
content: row.content,
|
|
209
|
+
toolCalls,
|
|
210
|
+
tokenUsage,
|
|
211
|
+
createdAt: row.created_at
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
mapFileContextRow(row) {
|
|
215
|
+
return {
|
|
216
|
+
id: row.id,
|
|
217
|
+
conversationId: row.conversation_id,
|
|
218
|
+
filePath: row.file_path,
|
|
219
|
+
contentHash: row.content_hash,
|
|
220
|
+
tokenCount: row.token_count,
|
|
221
|
+
addedAt: row.added_at
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
mapCostRow(row) {
|
|
225
|
+
return {
|
|
226
|
+
id: row.id,
|
|
227
|
+
conversationId: row.conversation_id,
|
|
228
|
+
provider: row.provider,
|
|
229
|
+
model: row.model,
|
|
230
|
+
role: row.role,
|
|
231
|
+
inputTokens: row.input_tokens,
|
|
232
|
+
outputTokens: row.output_tokens,
|
|
233
|
+
costUsd: row.cost_usd,
|
|
234
|
+
createdAt: row.created_at
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export { ConversationStore };
|
|
240
|
+
//# sourceMappingURL=chunk-XEXWX7C7.js.map
|
|
241
|
+
//# sourceMappingURL=chunk-XEXWX7C7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/storage/conversation-store.ts"],"names":[],"mappings":"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","file":"chunk-XEXWX7C7.js","sourcesContent":["/**\n * Conversation store — PRD section 17.1\n * CRUD for conversations, messages, file context, and cost tracking.\n * All queries use parameterized prepared statements.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { logger } from \"../utils/logger.js\";\nimport type { SqliteStore } from \"./sqlite-store.js\";\nimport type { MessageRole } from \"../types/message.js\";\nimport type { ProviderName } from \"../types/model.js\";\nimport type {\n IConversationRow,\n IMessageRow,\n IFileContextRow,\n ICostRow,\n IConversation,\n IMessage,\n IStoredTokenUsage,\n IFileContext,\n ICostEntry,\n IPaginationOptions,\n IAddMessageParams,\n IAddCostParams,\n IAddFileContextParams,\n} from \"./conversation-types.js\";\n\nexport type {\n IConversation,\n IMessage,\n IStoredTokenUsage,\n IFileContext,\n ICostEntry,\n IPaginationOptions,\n IAddMessageParams,\n IAddCostParams,\n IAddFileContextParams,\n} from \"./conversation-types.js\";\n\nexport class ConversationStore {\n private readonly store: SqliteStore;\n\n constructor(store: SqliteStore) {\n this.store = store;\n }\n\n createConversation(\n projectRoot: string,\n defaultModel?: string,\n metadata?: Record<string, unknown>,\n ): IConversation {\n const id = randomUUID();\n const metadataJson = JSON.stringify(metadata ?? {});\n\n this.store.run(\n `INSERT INTO conversations (id, project_root, default_model, metadata)\n VALUES (?, ?, ?, ?)`,\n id,\n projectRoot,\n defaultModel ?? null,\n metadataJson,\n );\n\n logger.info({ conversationId: id, projectRoot }, \"Conversation created\");\n\n const row = this.store.get(\n \"SELECT * FROM conversations WHERE id = ?\",\n id,\n ) as IConversationRow | undefined;\n\n if (!row) {\n throw new Error(`Failed to retrieve created conversation: ${id}`);\n }\n\n return this.mapConversationRow(row);\n }\n\n getConversation(id: string): IConversation | undefined {\n const row = this.store.get(\n \"SELECT * FROM conversations WHERE id = ?\",\n id,\n ) as IConversationRow | undefined;\n return row ? this.mapConversationRow(row) : undefined;\n }\n\n listConversations(projectRoot?: string): IConversation[] {\n const rows = projectRoot\n ? (this.store.all(\n \"SELECT * FROM conversations WHERE project_root = ? ORDER BY updated_at DESC\",\n projectRoot,\n ) as IConversationRow[])\n : (this.store.all(\n \"SELECT * FROM conversations ORDER BY updated_at DESC\",\n ) as IConversationRow[]);\n\n return rows.map((row) => this.mapConversationRow(row));\n }\n\n deleteConversation(id: string): void {\n this.store.run(\"DELETE FROM conversations WHERE id = ?\", id);\n logger.info({ conversationId: id }, \"Conversation deleted\");\n }\n\n addMessage(params: IAddMessageParams): IMessage {\n const toolCallsJson = params.toolCalls\n ? JSON.stringify(params.toolCalls)\n : null;\n const tokenUsageJson = params.tokenUsage\n ? JSON.stringify(params.tokenUsage)\n : null;\n\n const result = this.store.run(\n `INSERT INTO messages\n (conversation_id, role, model, provider, content, tool_calls, token_usage)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n params.conversationId,\n params.role,\n params.model ?? null,\n params.provider ?? null,\n params.content,\n toolCallsJson,\n tokenUsageJson,\n );\n\n this.store.run(\n \"UPDATE conversations SET updated_at = datetime('now') WHERE id = ?\",\n params.conversationId,\n );\n\n const row = this.store.get(\n \"SELECT * FROM messages WHERE id = ?\",\n result.lastInsertRowid,\n ) as IMessageRow | undefined;\n\n if (!row) {\n throw new Error(\"Failed to retrieve created message\");\n }\n\n return this.mapMessageRow(row);\n }\n\n getMessages(\n conversationId: string,\n pagination?: IPaginationOptions,\n ): IMessage[] {\n const limit = pagination?.limit ?? 100;\n const offset = pagination?.offset ?? 0;\n\n const rows = this.store.all(\n `SELECT * FROM messages\n WHERE conversation_id = ?\n ORDER BY created_at ASC\n LIMIT ? OFFSET ?`,\n conversationId,\n limit,\n offset,\n ) as IMessageRow[];\n\n return rows.map((row) => this.mapMessageRow(row));\n }\n\n getMessageCount(conversationId: string): number {\n const result = this.store.get(\n \"SELECT COUNT(*) as count FROM messages WHERE conversation_id = ?\",\n conversationId,\n ) as { count: number } | undefined;\n return result?.count ?? 0;\n }\n\n addFileContext(params: IAddFileContextParams): IFileContext {\n const result = this.store.run(\n `INSERT INTO file_context\n (conversation_id, file_path, content_hash, token_count)\n VALUES (?, ?, ?, ?)`,\n params.conversationId,\n params.filePath,\n params.contentHash ?? null,\n params.tokenCount ?? null,\n );\n\n const row = this.store.get(\n \"SELECT * FROM file_context WHERE id = ?\",\n result.lastInsertRowid,\n ) as IFileContextRow | undefined;\n\n if (!row) {\n throw new Error(\"Failed to retrieve created file context\");\n }\n\n return this.mapFileContextRow(row);\n }\n\n getFileContext(conversationId: string): IFileContext[] {\n const rows = this.store.all(\n \"SELECT * FROM file_context WHERE conversation_id = ? ORDER BY added_at DESC\",\n conversationId,\n ) as IFileContextRow[];\n return rows.map((row) => this.mapFileContextRow(row));\n }\n\n removeFileContext(conversationId: string, filePath: string): void {\n this.store.run(\n \"DELETE FROM file_context WHERE conversation_id = ? AND file_path = ?\",\n conversationId,\n filePath,\n );\n }\n\n addCost(params: IAddCostParams): ICostEntry {\n const result = this.store.run(\n `INSERT INTO cost_tracking\n (conversation_id, provider, model, role, input_tokens, output_tokens, cost_usd)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n params.conversationId,\n params.provider,\n params.model,\n params.role ?? null,\n params.inputTokens ?? null,\n params.outputTokens ?? null,\n params.costUsd ?? null,\n );\n\n const row = this.store.get(\n \"SELECT * FROM cost_tracking WHERE id = ?\",\n result.lastInsertRowid,\n ) as ICostRow | undefined;\n\n if (!row) {\n throw new Error(\"Failed to retrieve created cost entry\");\n }\n\n return this.mapCostRow(row);\n }\n\n getConversationCost(conversationId: string): number {\n const result = this.store.get(\n \"SELECT SUM(cost_usd) as total FROM cost_tracking WHERE conversation_id = ?\",\n conversationId,\n ) as { total: number | null } | undefined;\n return result?.total ?? 0;\n }\n\n getCostBreakdown(conversationId: string): ICostEntry[] {\n const rows = this.store.all(\n \"SELECT * FROM cost_tracking WHERE conversation_id = ? ORDER BY created_at ASC\",\n conversationId,\n ) as ICostRow[];\n return rows.map((row) => this.mapCostRow(row));\n }\n\n // ── Private row mappers ─────────────────────────────────────────────\n\n private mapConversationRow(row: IConversationRow): IConversation {\n let metadata: Record<string, unknown> = {};\n try {\n metadata = JSON.parse(row.metadata) as Record<string, unknown>;\n } catch {\n metadata = {};\n }\n\n return {\n id: row.id,\n projectRoot: row.project_root,\n defaultModel: row.default_model,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n metadata,\n };\n }\n\n private mapMessageRow(row: IMessageRow): IMessage {\n let toolCalls: unknown[] | null = null;\n if (row.tool_calls) {\n try {\n toolCalls = JSON.parse(row.tool_calls) as unknown[];\n } catch {\n toolCalls = null;\n }\n }\n\n let tokenUsage: IStoredTokenUsage | null = null;\n if (row.token_usage) {\n try {\n tokenUsage = JSON.parse(row.token_usage) as IStoredTokenUsage;\n } catch {\n tokenUsage = null;\n }\n }\n\n return {\n id: row.id,\n conversationId: row.conversation_id,\n role: row.role as MessageRole,\n model: row.model,\n provider: row.provider as ProviderName | null,\n content: row.content,\n toolCalls,\n tokenUsage,\n createdAt: row.created_at,\n };\n }\n\n private mapFileContextRow(row: IFileContextRow): IFileContext {\n return {\n id: row.id,\n conversationId: row.conversation_id,\n filePath: row.file_path,\n contentHash: row.content_hash,\n tokenCount: row.token_count,\n addedAt: row.added_at,\n };\n }\n\n private mapCostRow(row: ICostRow): ICostEntry {\n return {\n id: row.id,\n conversationId: row.conversation_id,\n provider: row.provider,\n model: row.model,\n role: row.role,\n inputTokens: row.input_tokens,\n outputTokens: row.output_tokens,\n costUsd: row.cost_usd,\n createdAt: row.created_at,\n };\n }\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SUPPORTED_MODELS } from './chunk-HCIHOHLX.js';
|
|
2
|
-
import { logger } from './chunk-
|
|
2
|
+
import { logger } from './chunk-IR5HLBMH.js';
|
|
3
3
|
|
|
4
4
|
// src/utils/tokenCounter.ts
|
|
5
5
|
function estimateTokenCount(text) {
|
|
@@ -76,5 +76,5 @@ function sleep(ms) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export { createTokenUsage, estimateTokenCount, formatCost, formatTokenCount, sleep, withRetry };
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
80
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
//# sourceMappingURL=chunk-YCCYXDW7.js.map
|
|
80
|
+
//# sourceMappingURL=chunk-YCCYXDW7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/tokenCounter.ts","../src/utils/retry.ts"],"names":[],"mappings":"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","file":"chunk-YCCYXDW7.js","sourcesContent":["/**\n * Multi-provider token estimation per PRD section 7.5\n * Uses a universal approximation since we don't bundle tokenizers for each provider.\n */\n\nimport type { ITokenUsage } from \"../types/index.js\";\nimport { SUPPORTED_MODELS } from \"../types/index.js\";\n\n/**\n * Approximate token count using the ~4 chars per token heuristic.\n * For production cost tracking, we rely on provider-reported usage in API responses.\n */\nexport function estimateTokenCount(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Calculate cost in USD based on token usage and model pricing.\n */\nexport function calculateCost(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n): number {\n const modelInfo = SUPPORTED_MODELS[modelId];\n if (!modelInfo) {\n return 0;\n }\n\n const inputCost = (inputTokens / 1_000_000) * modelInfo.inputPricePerMToken;\n const outputCost = (outputTokens / 1_000_000) * modelInfo.outputPricePerMToken;\n\n return Math.round((inputCost + outputCost) * 1_000_000) / 1_000_000;\n}\n\n/**\n * Create a token usage record with cost calculation.\n */\nexport function createTokenUsage(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n): ITokenUsage {\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUsd: calculateCost(modelId, inputTokens, outputTokens),\n };\n}\n\n/**\n * Format cost for display (e.g., \"$0.04\").\n */\nexport function formatCost(costUsd: number): string {\n if (costUsd < 0.01) {\n return `$${costUsd.toFixed(4)}`;\n }\n return `$${costUsd.toFixed(2)}`;\n}\n\n/**\n * Format token count for display (e.g., \"12.3K\").\n */\nexport function formatTokenCount(count: number): string {\n if (count < 1_000) {\n return String(count);\n }\n if (count < 1_000_000) {\n return `${(count / 1_000).toFixed(1)}K`;\n }\n return `${(count / 1_000_000).toFixed(1)}M`;\n}\n","/**\n * Retry with exponential backoff per PRD section 20.2\n * Provider failover: If primary model fails, auto-fallback to configured backup.\n */\n\nimport { logger } from \"./logger.js\";\n\nexport interface IRetryOptions {\n readonly maxRetries: number;\n readonly baseDelayMs: number;\n readonly maxDelayMs: number;\n readonly shouldRetry?: (error: unknown, attempt: number) => boolean;\n}\n\nconst DEFAULT_RETRY_OPTIONS: IRetryOptions = {\n maxRetries: 3,\n baseDelayMs: 1_000,\n maxDelayMs: 30_000,\n};\n\n/**\n * Execute a function with exponential backoff retry.\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options?: Partial<IRetryOptions>,\n): Promise<T> {\n const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error: unknown) {\n lastError = error;\n\n if (attempt === opts.maxRetries) {\n break;\n }\n\n if (opts.shouldRetry && !opts.shouldRetry(error, attempt)) {\n break;\n }\n\n const delay = Math.min(\n opts.baseDelayMs * Math.pow(2, attempt) + Math.random() * 1_000,\n opts.maxDelayMs,\n );\n\n logger.warn(\n { attempt: attempt + 1, maxRetries: opts.maxRetries, delayMs: delay },\n \"Retrying after error\",\n );\n\n await sleep(delay);\n }\n }\n\n throw lastError;\n}\n\n/**\n * Sleep for a specified duration.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Check if an error indicates a rate limit (should retry after delay).\n */\nexport function isRateLimitError(error: unknown): boolean {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n return message.includes(\"rate limit\") || message.includes(\"429\") || message.includes(\"too many requests\");\n }\n return false;\n}\n\n/**\n * Check if an error is transient (network issues, timeouts).\n */\nexport function isTransientError(error: unknown): boolean {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n return (\n message.includes(\"timeout\") ||\n message.includes(\"econnreset\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"socket hang up\") ||\n message.includes(\"503\") ||\n message.includes(\"502\")\n );\n }\n return false;\n}\n"]}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { ModelNotFoundError } from './chunk-ZGOHARPV.js';
|
|
2
|
+
import { SUPPORTED_MODELS } from './chunk-HCIHOHLX.js';
|
|
3
|
+
import { logger } from './chunk-IR5HLBMH.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-YPQ2MLAV.js.map
|
|
140
|
+
//# sourceMappingURL=chunk-YPQ2MLAV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/model-router.ts"],"names":[],"mappings":"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","file":"chunk-YPQ2MLAV.js","sourcesContent":["/**\n * Role-based model selection per PRD section 7.2\n * Resolution pipeline: user override → role config → fallback chain → system default\n */\n\nimport type {\n ModelRole,\n IModelResolution,\n IRoleConfig,\n IGlobalConfig,\n ProviderName,\n IModelInfo,\n} from \"../types/index.js\";\nimport { SUPPORTED_MODELS, ModelNotFoundError } from \"../types/index.js\";\nimport { logger } from \"../utils/index.js\";\n\nexport interface IModelRouterConfig {\n readonly defaultModel: string;\n readonly roles: Partial<Record<ModelRole, IRoleConfig>>;\n readonly enabledProviders: readonly ProviderName[];\n}\n\nexport class ModelRouter {\n private readonly config: IModelRouterConfig;\n private userOverride: string | undefined;\n\n constructor(config: IModelRouterConfig) {\n this.config = config;\n }\n\n /**\n * Set a temporary user override that takes highest priority.\n */\n setUserOverride(modelId: string | undefined): void {\n if (modelId !== undefined) {\n this.validateModel(modelId);\n }\n this.userOverride = modelId;\n }\n\n /**\n * Resolve the best model for a given role through the priority pipeline.\n */\n resolve(role?: ModelRole): IModelResolution {\n // 1. User override (explicit flag: --model claude-opus-4-6)\n if (this.userOverride) {\n const info = this.getModelInfo(this.userOverride);\n return {\n modelId: this.userOverride,\n provider: info.provider,\n source: \"user_override\",\n role,\n };\n }\n\n // 2. Role config\n if (role) {\n const roleConfig = this.config.roles[role];\n if (roleConfig) {\n // Try primary model\n if (this.isModelAvailable(roleConfig.primary)) {\n const info = this.getModelInfo(roleConfig.primary);\n return {\n modelId: roleConfig.primary,\n provider: info.provider,\n source: \"role_config\",\n role,\n };\n }\n\n // 3. Fallback chain\n for (const fallbackModel of roleConfig.fallback) {\n if (this.isModelAvailable(fallbackModel)) {\n const info = this.getModelInfo(fallbackModel);\n logger.info(\n { role, primary: roleConfig.primary, fallback: fallbackModel },\n \"Using fallback model for role\",\n );\n return {\n modelId: fallbackModel,\n provider: info.provider,\n source: \"fallback_chain\",\n role,\n };\n }\n }\n }\n }\n\n // 4. System default\n const defaultModel = this.config.defaultModel;\n if (this.isModelAvailable(defaultModel)) {\n const info = this.getModelInfo(defaultModel);\n return {\n modelId: defaultModel,\n provider: info.provider,\n source: \"system_default\",\n role,\n };\n }\n\n // Last resort: find any available model\n const anyAvailable = this.getAvailableModels()[0];\n if (anyAvailable) {\n return {\n modelId: anyAvailable.id,\n provider: anyAvailable.provider,\n source: \"system_default\",\n role,\n };\n }\n\n throw new ModelNotFoundError(defaultModel);\n }\n\n /**\n * Check if a model is available (provider is enabled and model is known).\n */\n isModelAvailable(modelId: string): boolean {\n const info = SUPPORTED_MODELS[modelId];\n if (!info) {\n return false;\n }\n return this.config.enabledProviders.includes(info.provider);\n }\n\n /**\n * Get model info by ID. Throws if not found.\n */\n getModelInfo(modelId: string): IModelInfo {\n const info = SUPPORTED_MODELS[modelId];\n if (!info) {\n throw new ModelNotFoundError(modelId);\n }\n return info;\n }\n\n /**\n * Get all available models (from enabled providers).\n */\n getAvailableModels(): readonly IModelInfo[] {\n return Object.values(SUPPORTED_MODELS).filter((model) =>\n this.config.enabledProviders.includes(model.provider),\n );\n }\n\n /**\n * List models recommended for a specific role.\n */\n getModelsForRole(role: ModelRole): readonly IModelInfo[] {\n return this.getAvailableModels().filter((model) =>\n model.supportedRoles.includes(role),\n );\n }\n\n /**\n * Validate that a model ID exists. Throws ModelNotFoundError if not.\n */\n private validateModel(modelId: string): void {\n if (!SUPPORTED_MODELS[modelId]) {\n throw new ModelNotFoundError(modelId);\n }\n }\n}\n\n/**\n * Create a ModelRouter from the global config.\n */\nexport function createModelRouter(config: IGlobalConfig): ModelRouter {\n const enabledProviders = Object.entries(config.providers)\n .filter(([, providerConfig]) => providerConfig.enabled)\n .map(([name]) => name as ProviderName);\n\n return new ModelRouter({\n defaultModel: config.defaultModel,\n roles: config.roles,\n enabledProviders,\n });\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/ui/team-state.ts
|
|
2
|
+
var activeTeamManager;
|
|
3
|
+
var activeTeamName;
|
|
4
|
+
var activeTmuxCleanup;
|
|
5
|
+
function getActiveTeamManager() {
|
|
6
|
+
return activeTeamManager;
|
|
7
|
+
}
|
|
8
|
+
function setActiveTeamManager(manager) {
|
|
9
|
+
activeTeamManager = manager;
|
|
10
|
+
}
|
|
11
|
+
function getActiveTeamName() {
|
|
12
|
+
return activeTeamName;
|
|
13
|
+
}
|
|
14
|
+
function setActiveTeamName(name) {
|
|
15
|
+
activeTeamName = name;
|
|
16
|
+
}
|
|
17
|
+
function getActiveTmuxCleanup() {
|
|
18
|
+
return activeTmuxCleanup;
|
|
19
|
+
}
|
|
20
|
+
function setActiveTmuxCleanup(cleanup) {
|
|
21
|
+
activeTmuxCleanup = cleanup;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { getActiveTeamManager, getActiveTeamName, getActiveTmuxCleanup, setActiveTeamManager, setActiveTeamName, setActiveTmuxCleanup };
|
|
25
|
+
//# sourceMappingURL=chunk-ZCOVMVK4.js.map
|
|
26
|
+
//# sourceMappingURL=chunk-ZCOVMVK4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/team-state.ts"],"names":[],"mappings":";AAOA,IAAI,iBAAA;AACJ,IAAI,cAAA;AACJ,IAAI,iBAAA;AAEG,SAAS,oBAAA,GAAgD;AAC9D,EAAA,OAAO,iBAAA;AACT;AAEO,SAAS,qBAAqB,OAAA,EAAwC;AAC3E,EAAA,iBAAA,GAAoB,OAAA;AACtB;AAEO,SAAS,iBAAA,GAAwC;AACtD,EAAA,OAAO,cAAA;AACT;AAEO,SAAS,kBAAkB,IAAA,EAAgC;AAChE,EAAA,cAAA,GAAiB,IAAA;AACnB;AAEO,SAAS,oBAAA,GAA0D;AACxE,EAAA,OAAO,iBAAA;AACT;AAEO,SAAS,qBAAqB,OAAA,EAAkD;AACrF,EAAA,iBAAA,GAAoB,OAAA;AACtB","file":"chunk-ZCOVMVK4.js","sourcesContent":["/**\n * Module-level active team state shared between team commands and team launcher.\n * Extracted from App.tsx to enforce the 300-line component limit (PRD 6.2).\n */\n\nimport type { TeamManager } from \"../teams/team-manager.js\";\n\nlet activeTeamManager: TeamManager | undefined;\nlet activeTeamName: string | undefined;\nlet activeTmuxCleanup: (() => Promise<void>) | undefined;\n\nexport function getActiveTeamManager(): TeamManager | undefined {\n return activeTeamManager;\n}\n\nexport function setActiveTeamManager(manager: TeamManager | undefined): void {\n activeTeamManager = manager;\n}\n\nexport function getActiveTeamName(): string | undefined {\n return activeTeamName;\n}\n\nexport function setActiveTeamName(name: string | undefined): void {\n activeTeamName = name;\n}\n\nexport function getActiveTmuxCleanup(): (() => Promise<void>) | undefined {\n return activeTmuxCleanup;\n}\n\nexport function setActiveTmuxCleanup(cleanup: (() => Promise<void>) | undefined): void {\n activeTmuxCleanup = cleanup;\n}\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { CredentialStore } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-NBR3GHMT.js';
|
|
5
|
-
import './chunk-CS5X3BWX.js';
|
|
6
|
-
import './chunk-HCIHOHLX.js';
|
|
1
|
+
import { CredentialStore } from './chunk-SNWPI6XJ.js';
|
|
2
|
+
import './chunk-YCCYXDW7.js';
|
|
3
|
+
import './chunk-OPWAFS6Y.js';
|
|
7
4
|
import { AuthenticationError } from './chunk-ZGOHARPV.js';
|
|
8
|
-
import
|
|
5
|
+
import './chunk-HCIHOHLX.js';
|
|
6
|
+
import './chunk-2Y7TR6BS.js';
|
|
7
|
+
import { logger } from './chunk-IR5HLBMH.js';
|
|
8
|
+
import './chunk-D275MCIH.js';
|
|
9
9
|
import { createServer } from 'http';
|
|
10
10
|
import { randomBytes, createHash } from 'crypto';
|
|
11
11
|
import { execFile } from 'child_process';
|
|
@@ -320,5 +320,5 @@ var ClaudeLogin = class {
|
|
|
320
320
|
};
|
|
321
321
|
|
|
322
322
|
export { ClaudeLogin };
|
|
323
|
-
//# sourceMappingURL=claude-login-
|
|
324
|
-
//# sourceMappingURL=claude-login-
|
|
323
|
+
//# sourceMappingURL=claude-login-AIFIWTYF.js.map
|
|
324
|
+
//# sourceMappingURL=claude-login-AIFIWTYF.js.map
|