@kenkaiiii/gg-core 4.4.0 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-USAVZGPP.js → chunk-74Z6I5V7.js} +34 -4
- package/dist/chunk-74Z6I5V7.js.map +1 -0
- package/dist/index.cjs +319 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -2
- package/dist/index.d.ts +66 -2
- package/dist/index.js +276 -7
- package/dist/index.js.map +1 -1
- package/dist/model-registry.cjs +35 -3
- package/dist/model-registry.cjs.map +1 -1
- package/dist/model-registry.d.cts +21 -1
- package/dist/model-registry.d.ts +21 -1
- package/dist/model-registry.js +5 -1
- package/package.json +2 -2
- package/dist/chunk-USAVZGPP.js.map +0 -1
|
@@ -98,6 +98,7 @@ var MODELS = [
|
|
|
98
98
|
supportsThinking: true,
|
|
99
99
|
supportsImages: true,
|
|
100
100
|
supportsVideo: true,
|
|
101
|
+
maxVideoBytes: 20 * 1024 * 1024,
|
|
101
102
|
costTier: "low",
|
|
102
103
|
maxThinkingLevel: "high"
|
|
103
104
|
},
|
|
@@ -110,6 +111,7 @@ var MODELS = [
|
|
|
110
111
|
supportsThinking: true,
|
|
111
112
|
supportsImages: true,
|
|
112
113
|
supportsVideo: true,
|
|
114
|
+
maxVideoBytes: 20 * 1024 * 1024,
|
|
113
115
|
costTier: "low",
|
|
114
116
|
maxThinkingLevel: "high"
|
|
115
117
|
},
|
|
@@ -123,6 +125,7 @@ var MODELS = [
|
|
|
123
125
|
supportsThinking: true,
|
|
124
126
|
supportsImages: true,
|
|
125
127
|
supportsVideo: true,
|
|
128
|
+
maxVideoBytes: 100 * 1024 * 1024,
|
|
126
129
|
costTier: "medium",
|
|
127
130
|
maxThinkingLevel: "high"
|
|
128
131
|
},
|
|
@@ -173,13 +176,16 @@ var MODELS = [
|
|
|
173
176
|
supportsThinking: true,
|
|
174
177
|
supportsImages: true,
|
|
175
178
|
supportsVideo: true,
|
|
179
|
+
maxVideoBytes: 50 * 1024 * 1024,
|
|
176
180
|
costTier: "medium",
|
|
177
181
|
maxThinkingLevel: "high"
|
|
178
182
|
},
|
|
179
183
|
// ── Xiaomi (MiMo) ──────────────────────────────────────
|
|
184
|
+
// Pro series: text-only coding/agentic flagship. The legacy mimo-v2-pro
|
|
185
|
+
// auto-routes to v2.5 on 2026-06-01 and is fully deprecated by 2026-06-30.
|
|
180
186
|
{
|
|
181
|
-
id: "mimo-v2-pro",
|
|
182
|
-
name: "MiMo-V2-Pro",
|
|
187
|
+
id: "mimo-v2.5-pro",
|
|
188
|
+
name: "MiMo-V2.5-Pro",
|
|
183
189
|
provider: "xiaomi",
|
|
184
190
|
contextWindow: 1e6,
|
|
185
191
|
maxOutputTokens: 131072,
|
|
@@ -189,6 +195,22 @@ var MODELS = [
|
|
|
189
195
|
costTier: "medium",
|
|
190
196
|
maxThinkingLevel: "high"
|
|
191
197
|
},
|
|
198
|
+
// Omni series: native full-modal understanding (image + audio + video).
|
|
199
|
+
// Video/image ride the OpenAI-compatible transport as base64 data URLs
|
|
200
|
+
// (`video_url`/`image_url`), which the shared transform already emits.
|
|
201
|
+
{
|
|
202
|
+
id: "mimo-v2.5",
|
|
203
|
+
name: "MiMo-V2.5",
|
|
204
|
+
provider: "xiaomi",
|
|
205
|
+
contextWindow: 1e6,
|
|
206
|
+
maxOutputTokens: 131072,
|
|
207
|
+
supportsThinking: true,
|
|
208
|
+
supportsImages: true,
|
|
209
|
+
supportsVideo: true,
|
|
210
|
+
maxVideoBytes: 36 * 1024 * 1024,
|
|
211
|
+
costTier: "medium",
|
|
212
|
+
maxThinkingLevel: "high"
|
|
213
|
+
},
|
|
192
214
|
// ── DeepSeek ───────────────────────────────────────────
|
|
193
215
|
{
|
|
194
216
|
id: "deepseek-v4-pro",
|
|
@@ -235,8 +257,14 @@ function getModel(id) {
|
|
|
235
257
|
function getModelsForProvider(provider) {
|
|
236
258
|
return MODELS.filter((m) => m.provider === provider);
|
|
237
259
|
}
|
|
260
|
+
var DEFAULT_MAX_VIDEO_BYTES = 20 * 1024 * 1024;
|
|
261
|
+
function getVideoByteLimit(modelId) {
|
|
262
|
+
const model = getModel(modelId);
|
|
263
|
+
if (!model?.supportsVideo) return void 0;
|
|
264
|
+
return model.maxVideoBytes ?? DEFAULT_MAX_VIDEO_BYTES;
|
|
265
|
+
}
|
|
238
266
|
function getDefaultModel(provider) {
|
|
239
|
-
if (provider === "xiaomi") return MODELS.find((m) => m.id === "mimo-v2-pro");
|
|
267
|
+
if (provider === "xiaomi") return MODELS.find((m) => m.id === "mimo-v2.5-pro");
|
|
240
268
|
if (provider === "openai") return MODELS.find((m) => m.id === "gpt-5.5");
|
|
241
269
|
if (provider === "gemini") return MODELS.find((m) => m.id === "gemini-3.1-flash-lite-preview");
|
|
242
270
|
if (provider === "glm") return MODELS.find((m) => m.id === "glm-5.1");
|
|
@@ -275,10 +303,12 @@ export {
|
|
|
275
303
|
MODELS,
|
|
276
304
|
getModel,
|
|
277
305
|
getModelsForProvider,
|
|
306
|
+
DEFAULT_MAX_VIDEO_BYTES,
|
|
307
|
+
getVideoByteLimit,
|
|
278
308
|
getDefaultModel,
|
|
279
309
|
usesOpenAICodexTransport,
|
|
280
310
|
getContextWindow,
|
|
281
311
|
getMaxThinkingLevel,
|
|
282
312
|
getSummaryModel
|
|
283
313
|
};
|
|
284
|
-
//# sourceMappingURL=chunk-
|
|
314
|
+
//# sourceMappingURL=chunk-74Z6I5V7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/model-registry.ts"],"sourcesContent":["import type { Provider, ThinkingLevel } from \"@kenkaiiii/gg-ai\";\n\nexport interface ModelInfo {\n id: string;\n name: string;\n provider: Provider;\n contextWindow: number;\n /**\n * ChatGPT Codex transport uses product-specific windows that can differ from\n * the public API model window. OpenAI OAuth requests include an accountId and\n * route through `/codex/responses`; API-key requests do not.\n */\n codexContextWindow?: number;\n maxOutputTokens: number;\n supportsThinking: boolean;\n supportsImages: boolean;\n supportsVideo: boolean;\n /**\n * Max video payload (bytes) this model's transport accepts, used to decide\n * when an attached/read video must be compressed before sending. Differs by\n * provider delivery mechanism:\n * - Moonshot/Kimi: 100 MB (file-service upload cap)\n * - MiniMax: 50 MB (Anthropic-compatible base64 inline cap)\n * - Gemini: 20 MB (inlineData per-request cap)\n * - Xiaomi (MiMo): ~36 MB raw — the API caps the base64 STRING at 50 MB,\n * and base64 inflates bytes by ~4/3, so 36 MB raw ≈ 48 MB encoded.\n * Only meaningful when `supportsVideo` is true.\n */\n maxVideoBytes?: number;\n costTier: \"low\" | \"medium\" | \"high\";\n /**\n * The top reasoning tier this model genuinely uses. Used when thinking is\n * enabled to pick the strongest setting per model:\n * - OpenAI GPT-5.5-era: `xhigh`\n * - OpenAI Pro/Codex/old: clamped to what the model accepts\n * - Claude Opus 4.8 / 4.7 / 4.6 and Sonnet 4.6: `max`\n * - Claude Haiku 4.5: `high` (no adaptive `max` tier)\n * - GLM / Moonshot / Xiaomi / MiniMax / Qwen: `high` — binary-thinking\n * providers ignore the level on the wire, so the value is cosmetic\n * - DeepSeek V4: `xhigh` (DeepSeek maps `xhigh` → its internal `max`)\n */\n maxThinkingLevel: ThinkingLevel;\n}\n\n// Provider display order — mirrors `PROVIDERS` in ui/login.tsx so the\n// /model selector and login selector sort models identically.\nexport const MODELS: ModelInfo[] = [\n // ── Anthropic ──────────────────────────────────────────\n {\n id: \"claude-opus-4-8\",\n name: \"Claude Opus 4.8\",\n provider: \"anthropic\",\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: false,\n costTier: \"high\",\n maxThinkingLevel: \"max\",\n },\n {\n id: \"claude-sonnet-4-6\",\n name: \"Claude Sonnet 4.6\",\n provider: \"anthropic\",\n contextWindow: 1_000_000,\n maxOutputTokens: 64_000,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: false,\n costTier: \"medium\",\n maxThinkingLevel: \"max\",\n },\n {\n id: \"claude-haiku-4-5-20251001\",\n name: \"Claude Haiku 4.5\",\n provider: \"anthropic\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: false,\n costTier: \"low\",\n maxThinkingLevel: \"high\",\n },\n // ── OpenAI (Codex) ─────────────────────────────────────\n {\n id: \"gpt-5.5\",\n name: \"GPT-5.5\",\n provider: \"openai\",\n contextWindow: 1_050_000,\n codexContextWindow: 272_000,\n maxOutputTokens: 128_000,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: false,\n costTier: \"high\",\n maxThinkingLevel: \"xhigh\",\n },\n {\n id: \"gpt-5.4\",\n name: \"GPT-5.4\",\n provider: \"openai\",\n contextWindow: 1_050_000,\n codexContextWindow: 272_000,\n maxOutputTokens: 128_000,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: false,\n costTier: \"high\",\n maxThinkingLevel: \"xhigh\",\n },\n {\n id: \"gpt-5.4-mini\",\n name: \"GPT-5.4 Mini\",\n provider: \"openai\",\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: false,\n costTier: \"low\",\n maxThinkingLevel: \"xhigh\",\n },\n {\n id: \"gpt-5.3-codex\",\n name: \"GPT-5.3 Codex\",\n provider: \"openai\",\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: false,\n costTier: \"high\",\n maxThinkingLevel: \"xhigh\",\n },\n // ── Gemini ─────────────────────────────────────────────\n {\n id: \"gemini-3.1-flash-lite-preview\",\n name: \"Gemini 3.1 Flash Lite Preview\",\n provider: \"gemini\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: true,\n maxVideoBytes: 20 * 1024 * 1024,\n costTier: \"low\",\n maxThinkingLevel: \"high\",\n },\n {\n id: \"gemini-3.5-flash\",\n name: \"Gemini 3.5 Flash\",\n provider: \"gemini\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: true,\n maxVideoBytes: 20 * 1024 * 1024,\n costTier: \"low\",\n maxThinkingLevel: \"high\",\n },\n // ── Moonshot (Kimi) ────────────────────────────────────\n {\n id: \"kimi-k2.6\",\n name: \"Kimi K2.6\",\n provider: \"moonshot\",\n contextWindow: 262_144,\n maxOutputTokens: 262_144,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: true,\n maxVideoBytes: 100 * 1024 * 1024,\n costTier: \"medium\",\n maxThinkingLevel: \"high\",\n },\n // ── Z.AI (GLM) ─────────────────────────────────────────\n {\n id: \"glm-5.1\",\n name: \"GLM-5.1\",\n provider: \"glm\",\n contextWindow: 204_800,\n maxOutputTokens: 131_072,\n supportsThinking: true,\n supportsImages: false,\n supportsVideo: false,\n costTier: \"medium\",\n maxThinkingLevel: \"high\",\n },\n {\n id: \"glm-4.7\",\n name: \"GLM-4.7\",\n provider: \"glm\",\n contextWindow: 200_000,\n maxOutputTokens: 131_072,\n supportsThinking: true,\n supportsImages: false,\n supportsVideo: false,\n costTier: \"low\",\n maxThinkingLevel: \"high\",\n },\n {\n id: \"glm-4.7-flash\",\n name: \"GLM-4.7 Flash\",\n provider: \"glm\",\n contextWindow: 200_000,\n maxOutputTokens: 131_072,\n supportsThinking: true,\n supportsImages: false,\n supportsVideo: false,\n costTier: \"low\",\n maxThinkingLevel: \"high\",\n },\n // ── MiniMax ────────────────────────────────────────────\n {\n id: \"MiniMax-M3\",\n name: \"MiniMax M3\",\n provider: \"minimax\",\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: true,\n maxVideoBytes: 50 * 1024 * 1024,\n costTier: \"medium\",\n maxThinkingLevel: \"high\",\n },\n // ── Xiaomi (MiMo) ──────────────────────────────────────\n // Pro series: text-only coding/agentic flagship. The legacy mimo-v2-pro\n // auto-routes to v2.5 on 2026-06-01 and is fully deprecated by 2026-06-30.\n {\n id: \"mimo-v2.5-pro\",\n name: \"MiMo-V2.5-Pro\",\n provider: \"xiaomi\",\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsThinking: true,\n supportsImages: false,\n supportsVideo: false,\n costTier: \"medium\",\n maxThinkingLevel: \"high\",\n },\n // Omni series: native full-modal understanding (image + audio + video).\n // Video/image ride the OpenAI-compatible transport as base64 data URLs\n // (`video_url`/`image_url`), which the shared transform already emits.\n {\n id: \"mimo-v2.5\",\n name: \"MiMo-V2.5\",\n provider: \"xiaomi\",\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsThinking: true,\n supportsImages: true,\n supportsVideo: true,\n maxVideoBytes: 36 * 1024 * 1024,\n costTier: \"medium\",\n maxThinkingLevel: \"high\",\n },\n // ── DeepSeek ───────────────────────────────────────────\n {\n id: \"deepseek-v4-pro\",\n name: \"DeepSeek V4 Pro\",\n provider: \"deepseek\",\n contextWindow: 1_048_576,\n maxOutputTokens: 384_000,\n supportsThinking: true,\n supportsImages: false,\n supportsVideo: false,\n costTier: \"high\",\n // DeepSeek V4 maps `xhigh` → its internal `max` tier.\n maxThinkingLevel: \"xhigh\",\n },\n {\n id: \"deepseek-v4-flash\",\n name: \"DeepSeek V4 Flash\",\n provider: \"deepseek\",\n contextWindow: 1_048_576,\n maxOutputTokens: 384_000,\n supportsThinking: true,\n supportsImages: false,\n supportsVideo: false,\n costTier: \"low\",\n maxThinkingLevel: \"xhigh\",\n },\n // ── OpenRouter ─────────────────────────────────────────\n {\n id: \"qwen/qwen3.6-plus\",\n name: \"Qwen3.6-Plus\",\n provider: \"openrouter\",\n contextWindow: 1_000_000,\n maxOutputTokens: 65_536,\n supportsThinking: true,\n supportsImages: false,\n supportsVideo: false,\n costTier: \"medium\",\n maxThinkingLevel: \"high\",\n },\n];\n\nexport function getModel(id: string): ModelInfo | undefined {\n return MODELS.find((m) => m.id === id);\n}\n\nexport function getModelsForProvider(provider: Provider): ModelInfo[] {\n return MODELS.filter((m) => m.provider === provider);\n}\n\n/** Default video payload cap (bytes) when a video model doesn't declare one. */\nexport const DEFAULT_MAX_VIDEO_BYTES = 20 * 1024 * 1024;\n\n/**\n * Max video payload (bytes) the given model's transport accepts before the clip\n * must be compressed. Returns `undefined` for models without video support, so\n * callers can skip the native-video path entirely.\n */\nexport function getVideoByteLimit(modelId: string): number | undefined {\n const model = getModel(modelId);\n if (!model?.supportsVideo) return undefined;\n return model.maxVideoBytes ?? DEFAULT_MAX_VIDEO_BYTES;\n}\n\nexport function getDefaultModel(provider: Provider): ModelInfo {\n if (provider === \"xiaomi\") return MODELS.find((m) => m.id === \"mimo-v2.5-pro\")!;\n if (provider === \"openai\") return MODELS.find((m) => m.id === \"gpt-5.5\")!;\n if (provider === \"gemini\") return MODELS.find((m) => m.id === \"gemini-3.1-flash-lite-preview\")!;\n if (provider === \"glm\") return MODELS.find((m) => m.id === \"glm-5.1\")!;\n if (provider === \"moonshot\") return MODELS.find((m) => m.id === \"kimi-k2.6\")!;\n if (provider === \"minimax\") return MODELS.find((m) => m.id === \"MiniMax-M3\")!;\n if (provider === \"deepseek\") return MODELS.find((m) => m.id === \"deepseek-v4-pro\")!;\n if (provider === \"openrouter\") return MODELS.find((m) => m.id === \"qwen/qwen3.6-plus\")!;\n return MODELS.find((m) => m.id === \"claude-sonnet-4-6\")!;\n}\n\nexport interface ContextWindowOptions {\n provider?: Provider;\n accountId?: string;\n}\n\nexport function usesOpenAICodexTransport(options?: ContextWindowOptions): boolean {\n return options?.provider === \"openai\" && Boolean(options.accountId);\n}\n\nexport function getContextWindow(modelId: string, options?: ContextWindowOptions): number {\n const model = getModel(modelId);\n if (!model) return 200_000;\n if (usesOpenAICodexTransport(options) && model.codexContextWindow) {\n return model.codexContextWindow;\n }\n return model.contextWindow;\n}\n\n/**\n * The strongest thinking level the given model genuinely uses. Falls back to\n * `\"high\"` for unknown models since every provider we ship accepts it.\n */\nexport function getMaxThinkingLevel(modelId: string): ThinkingLevel {\n return getModel(modelId)?.maxThinkingLevel ?? \"high\";\n}\n\n/**\n * Get the model to use for compaction summarization.\n * - Anthropic: always Sonnet 4.6\n * - OpenAI: cheapest (Codex Mini)\n * - Gemini: use the current model\n * - GLM: GLM-4.7 Flash (cheap alternative)\n * - Moonshot: use the current model (no cheap alternative)\n */\nexport function getSummaryModel(provider: Provider, currentModelId: string): ModelInfo {\n if (provider === \"anthropic\") {\n return MODELS.find((m) => m.id === \"claude-sonnet-4-6\")!;\n }\n if (provider === \"openai\" || provider === \"glm\" || provider === \"deepseek\") {\n const low = getModelsForProvider(provider).find((m) => m.costTier === \"low\");\n if (low) return low;\n }\n // Moonshot or fallback: use current model\n return getModel(currentModelId) ?? getDefaultModel(provider);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -31,7 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AuthStorage: () => AuthStorage,
|
|
34
|
+
DEFAULT_MAX_VIDEO_BYTES: () => DEFAULT_MAX_VIDEO_BYTES,
|
|
34
35
|
MODELS: () => MODELS,
|
|
36
|
+
MOONSHOT_OAUTH_KEY: () => MOONSHOT_OAUTH_KEY,
|
|
35
37
|
NotLoggedInError: () => NotLoggedInError,
|
|
36
38
|
TelegramBot: () => TelegramBot,
|
|
37
39
|
closeLogger: () => closeLogger,
|
|
@@ -51,16 +53,22 @@ __export(index_exports, {
|
|
|
51
53
|
getSessionId: () => getSessionId,
|
|
52
54
|
getSummaryModel: () => getSummaryModel,
|
|
53
55
|
getSupportedThinkingLevels: () => getSupportedThinkingLevels,
|
|
56
|
+
getVideoByteLimit: () => getVideoByteLimit,
|
|
57
|
+
isKimiCodingEndpoint: () => isKimiCodingEndpoint,
|
|
54
58
|
isLoggerOpen: () => isLoggerOpen,
|
|
55
59
|
isModelLoaded: () => isModelLoaded,
|
|
56
60
|
isThinkingLevelSupported: () => isThinkingLevelSupported,
|
|
61
|
+
kimiCodeBaseUrl: () => kimiCodeBaseUrl,
|
|
62
|
+
kimiCodingHeaders: () => kimiCodingHeaders,
|
|
57
63
|
log: () => log,
|
|
58
64
|
loginAnthropic: () => loginAnthropic,
|
|
59
65
|
loginGemini: () => loginGemini,
|
|
66
|
+
loginKimi: () => loginKimi,
|
|
60
67
|
loginOpenAI: () => loginOpenAI,
|
|
61
68
|
openLog: () => openLog,
|
|
62
69
|
refreshAnthropicToken: () => refreshAnthropicToken,
|
|
63
70
|
refreshGeminiToken: () => refreshGeminiToken,
|
|
71
|
+
refreshKimiToken: () => refreshKimiToken,
|
|
64
72
|
refreshOpenAIToken: () => refreshOpenAIToken,
|
|
65
73
|
registerLogCleanup: () => registerLogCleanup,
|
|
66
74
|
resample: () => resample,
|
|
@@ -171,6 +179,7 @@ var MODELS = [
|
|
|
171
179
|
supportsThinking: true,
|
|
172
180
|
supportsImages: true,
|
|
173
181
|
supportsVideo: true,
|
|
182
|
+
maxVideoBytes: 20 * 1024 * 1024,
|
|
174
183
|
costTier: "low",
|
|
175
184
|
maxThinkingLevel: "high"
|
|
176
185
|
},
|
|
@@ -183,6 +192,7 @@ var MODELS = [
|
|
|
183
192
|
supportsThinking: true,
|
|
184
193
|
supportsImages: true,
|
|
185
194
|
supportsVideo: true,
|
|
195
|
+
maxVideoBytes: 20 * 1024 * 1024,
|
|
186
196
|
costTier: "low",
|
|
187
197
|
maxThinkingLevel: "high"
|
|
188
198
|
},
|
|
@@ -196,6 +206,7 @@ var MODELS = [
|
|
|
196
206
|
supportsThinking: true,
|
|
197
207
|
supportsImages: true,
|
|
198
208
|
supportsVideo: true,
|
|
209
|
+
maxVideoBytes: 100 * 1024 * 1024,
|
|
199
210
|
costTier: "medium",
|
|
200
211
|
maxThinkingLevel: "high"
|
|
201
212
|
},
|
|
@@ -246,13 +257,16 @@ var MODELS = [
|
|
|
246
257
|
supportsThinking: true,
|
|
247
258
|
supportsImages: true,
|
|
248
259
|
supportsVideo: true,
|
|
260
|
+
maxVideoBytes: 50 * 1024 * 1024,
|
|
249
261
|
costTier: "medium",
|
|
250
262
|
maxThinkingLevel: "high"
|
|
251
263
|
},
|
|
252
264
|
// ── Xiaomi (MiMo) ──────────────────────────────────────
|
|
265
|
+
// Pro series: text-only coding/agentic flagship. The legacy mimo-v2-pro
|
|
266
|
+
// auto-routes to v2.5 on 2026-06-01 and is fully deprecated by 2026-06-30.
|
|
253
267
|
{
|
|
254
|
-
id: "mimo-v2-pro",
|
|
255
|
-
name: "MiMo-V2-Pro",
|
|
268
|
+
id: "mimo-v2.5-pro",
|
|
269
|
+
name: "MiMo-V2.5-Pro",
|
|
256
270
|
provider: "xiaomi",
|
|
257
271
|
contextWindow: 1e6,
|
|
258
272
|
maxOutputTokens: 131072,
|
|
@@ -262,6 +276,22 @@ var MODELS = [
|
|
|
262
276
|
costTier: "medium",
|
|
263
277
|
maxThinkingLevel: "high"
|
|
264
278
|
},
|
|
279
|
+
// Omni series: native full-modal understanding (image + audio + video).
|
|
280
|
+
// Video/image ride the OpenAI-compatible transport as base64 data URLs
|
|
281
|
+
// (`video_url`/`image_url`), which the shared transform already emits.
|
|
282
|
+
{
|
|
283
|
+
id: "mimo-v2.5",
|
|
284
|
+
name: "MiMo-V2.5",
|
|
285
|
+
provider: "xiaomi",
|
|
286
|
+
contextWindow: 1e6,
|
|
287
|
+
maxOutputTokens: 131072,
|
|
288
|
+
supportsThinking: true,
|
|
289
|
+
supportsImages: true,
|
|
290
|
+
supportsVideo: true,
|
|
291
|
+
maxVideoBytes: 36 * 1024 * 1024,
|
|
292
|
+
costTier: "medium",
|
|
293
|
+
maxThinkingLevel: "high"
|
|
294
|
+
},
|
|
265
295
|
// ── DeepSeek ───────────────────────────────────────────
|
|
266
296
|
{
|
|
267
297
|
id: "deepseek-v4-pro",
|
|
@@ -308,8 +338,14 @@ function getModel(id) {
|
|
|
308
338
|
function getModelsForProvider(provider) {
|
|
309
339
|
return MODELS.filter((m) => m.provider === provider);
|
|
310
340
|
}
|
|
341
|
+
var DEFAULT_MAX_VIDEO_BYTES = 20 * 1024 * 1024;
|
|
342
|
+
function getVideoByteLimit(modelId) {
|
|
343
|
+
const model = getModel(modelId);
|
|
344
|
+
if (!model?.supportsVideo) return void 0;
|
|
345
|
+
return model.maxVideoBytes ?? DEFAULT_MAX_VIDEO_BYTES;
|
|
346
|
+
}
|
|
311
347
|
function getDefaultModel(provider) {
|
|
312
|
-
if (provider === "xiaomi") return MODELS.find((m) => m.id === "mimo-v2-pro");
|
|
348
|
+
if (provider === "xiaomi") return MODELS.find((m) => m.id === "mimo-v2.5-pro");
|
|
313
349
|
if (provider === "openai") return MODELS.find((m) => m.id === "gpt-5.5");
|
|
314
350
|
if (provider === "gemini") return MODELS.find((m) => m.id === "gemini-3.1-flash-lite-preview");
|
|
315
351
|
if (provider === "glm") return MODELS.find((m) => m.id === "glm-5.1");
|
|
@@ -648,7 +684,7 @@ async function getClaudeCliUserAgent() {
|
|
|
648
684
|
|
|
649
685
|
// src/auth-storage.ts
|
|
650
686
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
651
|
-
var
|
|
687
|
+
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
652
688
|
|
|
653
689
|
// src/oauth/anthropic.ts
|
|
654
690
|
var import_node_crypto2 = __toESM(require("crypto"), 1);
|
|
@@ -1303,7 +1339,232 @@ function codeAssistHeaders(accessToken) {
|
|
|
1303
1339
|
};
|
|
1304
1340
|
}
|
|
1305
1341
|
|
|
1342
|
+
// src/oauth/kimi.ts
|
|
1343
|
+
var import_node_child_process = require("child_process");
|
|
1344
|
+
var import_node_crypto5 = require("crypto");
|
|
1345
|
+
var import_node_fs2 = require("fs");
|
|
1346
|
+
var import_node_os2 = require("os");
|
|
1347
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
1348
|
+
var CLIENT_ID3 = "17e5f671-d194-4dfb-9706-5516cb48c098";
|
|
1349
|
+
var DEFAULT_OAUTH_HOST = "https://auth.kimi.com";
|
|
1350
|
+
var DEFAULT_CODING_BASE_URL = "https://api.kimi.com/coding/v1";
|
|
1351
|
+
var KIMI_PLATFORM = "kimi_code_cli";
|
|
1352
|
+
var DEFAULT_KIMI_VERSION = "1.0.11";
|
|
1353
|
+
var DEVICE_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
1354
|
+
function oauthHost() {
|
|
1355
|
+
const host = process.env.KIMI_CODE_OAUTH_HOST ?? process.env.KIMI_OAUTH_HOST ?? DEFAULT_OAUTH_HOST;
|
|
1356
|
+
return host.replace(/\/+$/, "");
|
|
1357
|
+
}
|
|
1358
|
+
function kimiCodeBaseUrl() {
|
|
1359
|
+
return (process.env.KIMI_CODE_BASE_URL ?? DEFAULT_CODING_BASE_URL).replace(/\/+$/, "");
|
|
1360
|
+
}
|
|
1361
|
+
function kimiVersion() {
|
|
1362
|
+
const v = process.env.KIMI_CODE_VERSION ?? DEFAULT_KIMI_VERSION;
|
|
1363
|
+
return asciiHeader(v, DEFAULT_KIMI_VERSION);
|
|
1364
|
+
}
|
|
1365
|
+
function asciiHeader(value, fallback = "unknown") {
|
|
1366
|
+
const cleaned = value.replace(/[^\u0020-\u007E]/g, "").trim();
|
|
1367
|
+
return cleaned.length > 0 ? cleaned : fallback;
|
|
1368
|
+
}
|
|
1369
|
+
function macOsProductVersion() {
|
|
1370
|
+
try {
|
|
1371
|
+
const version = (0, import_node_child_process.execFileSync)("/usr/bin/sw_vers", ["-productVersion"], {
|
|
1372
|
+
encoding: "utf-8",
|
|
1373
|
+
timeout: 1e3
|
|
1374
|
+
}).trim();
|
|
1375
|
+
return version.length > 0 ? version : void 0;
|
|
1376
|
+
} catch {
|
|
1377
|
+
return void 0;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
function deviceModel() {
|
|
1381
|
+
const os2 = (0, import_node_os2.type)();
|
|
1382
|
+
const version = (0, import_node_os2.release)();
|
|
1383
|
+
const osArch = (0, import_node_os2.arch)();
|
|
1384
|
+
if (os2 === "Darwin") return `macOS ${macOsProductVersion() ?? version} ${osArch}`;
|
|
1385
|
+
if (os2 === "Windows_NT") return `Windows ${version} ${osArch}`;
|
|
1386
|
+
return `${os2} ${version} ${osArch}`.trim();
|
|
1387
|
+
}
|
|
1388
|
+
function deviceId() {
|
|
1389
|
+
const idPath = import_node_path4.default.join(getAppPaths().agentDir, "kimi_device_id");
|
|
1390
|
+
if ((0, import_node_fs2.existsSync)(idPath)) {
|
|
1391
|
+
try {
|
|
1392
|
+
const text = (0, import_node_fs2.readFileSync)(idPath, "utf-8").trim();
|
|
1393
|
+
if (text.length > 0) return text;
|
|
1394
|
+
} catch {
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
const id = (0, import_node_crypto5.randomUUID)();
|
|
1398
|
+
try {
|
|
1399
|
+
(0, import_node_fs2.mkdirSync)(getAppPaths().agentDir, { recursive: true, mode: 448 });
|
|
1400
|
+
(0, import_node_fs2.writeFileSync)(idPath, id, { encoding: "utf-8", mode: 384 });
|
|
1401
|
+
} catch {
|
|
1402
|
+
}
|
|
1403
|
+
return id;
|
|
1404
|
+
}
|
|
1405
|
+
function deviceHeaders() {
|
|
1406
|
+
return {
|
|
1407
|
+
"X-Msh-Platform": KIMI_PLATFORM,
|
|
1408
|
+
"X-Msh-Version": kimiVersion(),
|
|
1409
|
+
"X-Msh-Device-Name": asciiHeader((0, import_node_os2.hostname)()),
|
|
1410
|
+
"X-Msh-Device-Model": asciiHeader(deviceModel()),
|
|
1411
|
+
"X-Msh-Os-Version": asciiHeader((0, import_node_os2.release)()),
|
|
1412
|
+
"X-Msh-Device-Id": deviceId()
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
function kimiCodingHeaders() {
|
|
1416
|
+
return {
|
|
1417
|
+
"User-Agent": `kimi-code-cli/${kimiVersion()}`,
|
|
1418
|
+
...deviceHeaders()
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
function isKimiCodingEndpoint(baseUrl) {
|
|
1422
|
+
if (typeof baseUrl !== "string" || baseUrl.length === 0) return false;
|
|
1423
|
+
const normalized = baseUrl.replace(/\/+$/, "");
|
|
1424
|
+
return normalized === kimiCodeBaseUrl() || /(^|\.)kimi\.com/i.test(normalized);
|
|
1425
|
+
}
|
|
1426
|
+
async function postForm(endpoint, params) {
|
|
1427
|
+
const response = await fetch(`${oauthHost()}${endpoint}`, {
|
|
1428
|
+
method: "POST",
|
|
1429
|
+
headers: {
|
|
1430
|
+
...deviceHeaders(),
|
|
1431
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
1432
|
+
Accept: "application/json"
|
|
1433
|
+
},
|
|
1434
|
+
body: new URLSearchParams(params).toString()
|
|
1435
|
+
});
|
|
1436
|
+
let data = {};
|
|
1437
|
+
try {
|
|
1438
|
+
const parsed = await response.json();
|
|
1439
|
+
if (parsed && typeof parsed === "object") data = parsed;
|
|
1440
|
+
} catch {
|
|
1441
|
+
}
|
|
1442
|
+
return { status: response.status, data };
|
|
1443
|
+
}
|
|
1444
|
+
function errorDetail(data) {
|
|
1445
|
+
const desc = data.error_description ?? data.message ?? data.error;
|
|
1446
|
+
return typeof desc === "string" && desc.length > 0 ? desc : "unknown error";
|
|
1447
|
+
}
|
|
1448
|
+
function credsFromTokenResponse(data) {
|
|
1449
|
+
const accessToken = data.access_token;
|
|
1450
|
+
const refreshToken = data.refresh_token;
|
|
1451
|
+
const expiresIn = Number(data.expires_in);
|
|
1452
|
+
if (typeof accessToken !== "string" || accessToken.length === 0) {
|
|
1453
|
+
throw new Error("Kimi OAuth response missing access_token.");
|
|
1454
|
+
}
|
|
1455
|
+
if (typeof refreshToken !== "string" || refreshToken.length === 0) {
|
|
1456
|
+
throw new Error("Kimi OAuth response missing refresh_token.");
|
|
1457
|
+
}
|
|
1458
|
+
if (!Number.isFinite(expiresIn) || expiresIn <= 0) {
|
|
1459
|
+
throw new Error("Kimi OAuth response missing or invalid expires_in.");
|
|
1460
|
+
}
|
|
1461
|
+
return {
|
|
1462
|
+
accessToken,
|
|
1463
|
+
refreshToken,
|
|
1464
|
+
expiresAt: Date.now() + expiresIn * 1e3,
|
|
1465
|
+
baseUrl: kimiCodeBaseUrl()
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
async function requestDeviceAuthorization() {
|
|
1469
|
+
const { status, data } = await postForm("/api/oauth/device_authorization", {
|
|
1470
|
+
client_id: CLIENT_ID3
|
|
1471
|
+
});
|
|
1472
|
+
if (status !== 200) {
|
|
1473
|
+
throw new Error(`Kimi device authorization failed (${status}): ${errorDetail(data)}`);
|
|
1474
|
+
}
|
|
1475
|
+
const userCode = data.user_code;
|
|
1476
|
+
const deviceCode = data.device_code;
|
|
1477
|
+
const verificationUriComplete = data.verification_uri_complete;
|
|
1478
|
+
if (typeof userCode !== "string" || typeof deviceCode !== "string") {
|
|
1479
|
+
throw new Error("Kimi device authorization response missing user_code/device_code.");
|
|
1480
|
+
}
|
|
1481
|
+
return {
|
|
1482
|
+
userCode,
|
|
1483
|
+
deviceCode,
|
|
1484
|
+
verificationUri: typeof data.verification_uri === "string" ? data.verification_uri : "",
|
|
1485
|
+
verificationUriComplete: typeof verificationUriComplete === "string" ? verificationUriComplete : "",
|
|
1486
|
+
interval: Number(data.interval ?? 5) || 5
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
async function pollDeviceToken(deviceCode) {
|
|
1490
|
+
const { status, data } = await postForm("/api/oauth/token", {
|
|
1491
|
+
client_id: CLIENT_ID3,
|
|
1492
|
+
device_code: deviceCode,
|
|
1493
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
1494
|
+
});
|
|
1495
|
+
if (status === 200 && typeof data.access_token === "string") {
|
|
1496
|
+
return { kind: "success", creds: credsFromTokenResponse(data) };
|
|
1497
|
+
}
|
|
1498
|
+
if (status >= 500) {
|
|
1499
|
+
throw new Error(`Kimi token polling server error (${status}): ${errorDetail(data)}`);
|
|
1500
|
+
}
|
|
1501
|
+
const errorCode = typeof data.error === "string" ? data.error : "unknown_error";
|
|
1502
|
+
switch (errorCode) {
|
|
1503
|
+
case "authorization_pending":
|
|
1504
|
+
return { kind: "pending" };
|
|
1505
|
+
case "slow_down":
|
|
1506
|
+
return { kind: "slow_down" };
|
|
1507
|
+
case "expired_token":
|
|
1508
|
+
return { kind: "expired" };
|
|
1509
|
+
case "access_denied":
|
|
1510
|
+
return { kind: "denied" };
|
|
1511
|
+
default:
|
|
1512
|
+
throw new Error(`Kimi token polling failed (${status}): ${errorDetail(data)}`);
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
function sleep(ms) {
|
|
1516
|
+
return new Promise((resolve) => {
|
|
1517
|
+
setTimeout(resolve, ms);
|
|
1518
|
+
});
|
|
1519
|
+
}
|
|
1520
|
+
async function loginKimi(callbacks) {
|
|
1521
|
+
const auth = await requestDeviceAuthorization();
|
|
1522
|
+
callbacks.onStatus(
|
|
1523
|
+
`Visit ${auth.verificationUri || auth.verificationUriComplete} and enter code: ${auth.userCode}`
|
|
1524
|
+
);
|
|
1525
|
+
callbacks.onOpenUrl(auth.verificationUriComplete || auth.verificationUri);
|
|
1526
|
+
callbacks.onStatus("Waiting for you to authorize in the browser...");
|
|
1527
|
+
const deadline = Date.now() + DEVICE_TIMEOUT_MS;
|
|
1528
|
+
let interval = Math.max(auth.interval, 1);
|
|
1529
|
+
while (Date.now() < deadline) {
|
|
1530
|
+
await sleep(interval * 1e3);
|
|
1531
|
+
const result = await pollDeviceToken(auth.deviceCode);
|
|
1532
|
+
if (result.kind === "success") return result.creds;
|
|
1533
|
+
if (result.kind === "denied") {
|
|
1534
|
+
throw new Error("Kimi authorization was denied.");
|
|
1535
|
+
}
|
|
1536
|
+
if (result.kind === "expired") {
|
|
1537
|
+
throw new Error("Kimi device code expired. Please run login again.");
|
|
1538
|
+
}
|
|
1539
|
+
if (result.kind === "slow_down") {
|
|
1540
|
+
interval += 5;
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
throw new Error("Kimi login timed out. Please run login again.");
|
|
1544
|
+
}
|
|
1545
|
+
async function refreshKimiToken(refreshToken) {
|
|
1546
|
+
const { status, data } = await postForm("/api/oauth/token", {
|
|
1547
|
+
client_id: CLIENT_ID3,
|
|
1548
|
+
grant_type: "refresh_token",
|
|
1549
|
+
refresh_token: refreshToken
|
|
1550
|
+
});
|
|
1551
|
+
if (status === 200 && typeof data.access_token === "string") {
|
|
1552
|
+
return credsFromTokenResponse(data);
|
|
1553
|
+
}
|
|
1554
|
+
const errorCode = typeof data.error === "string" ? data.error : "";
|
|
1555
|
+
throw new Error(`Kimi token refresh failed (${status}): ${errorCode || errorDetail(data)}`);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1306
1558
|
// src/auth-storage.ts
|
|
1559
|
+
var MOONSHOT_OAUTH_KEY = "moonshot-oauth";
|
|
1560
|
+
var STATIC_API_KEY_PROVIDERS = /* @__PURE__ */ new Set([
|
|
1561
|
+
"glm",
|
|
1562
|
+
"moonshot",
|
|
1563
|
+
"xiaomi",
|
|
1564
|
+
"minimax",
|
|
1565
|
+
"deepseek",
|
|
1566
|
+
"openrouter"
|
|
1567
|
+
]);
|
|
1307
1568
|
var AuthStorage = class {
|
|
1308
1569
|
data = {};
|
|
1309
1570
|
filePath;
|
|
@@ -1327,6 +1588,30 @@ var AuthStorage = class {
|
|
|
1327
1588
|
await this.ensureLoaded();
|
|
1328
1589
|
return Boolean(this.data[provider]);
|
|
1329
1590
|
}
|
|
1591
|
+
/**
|
|
1592
|
+
* True if the user has any usable auth for the logical provider. For
|
|
1593
|
+
* `moonshot` this is satisfied by either the Kimi OAuth credential or the
|
|
1594
|
+
* Moonshot API key.
|
|
1595
|
+
*/
|
|
1596
|
+
async hasProviderAuth(provider) {
|
|
1597
|
+
await this.ensureLoaded();
|
|
1598
|
+
if (provider === "moonshot") {
|
|
1599
|
+
return Boolean(this.data[MOONSHOT_OAUTH_KEY] || this.data["moonshot"]);
|
|
1600
|
+
}
|
|
1601
|
+
return Boolean(this.data[provider]);
|
|
1602
|
+
}
|
|
1603
|
+
/**
|
|
1604
|
+
* True if the active credential for `provider` is a static API key with no
|
|
1605
|
+
* refresh mechanism. For `moonshot` this is only true when the Kimi OAuth
|
|
1606
|
+
* credential is absent (a present OAuth credential is refreshable).
|
|
1607
|
+
*/
|
|
1608
|
+
async isStaticApiKey(provider) {
|
|
1609
|
+
await this.ensureLoaded();
|
|
1610
|
+
if (provider === "moonshot" && this.data[MOONSHOT_OAUTH_KEY]) {
|
|
1611
|
+
return false;
|
|
1612
|
+
}
|
|
1613
|
+
return STATIC_API_KEY_PROVIDERS.has(provider);
|
|
1614
|
+
}
|
|
1330
1615
|
async load() {
|
|
1331
1616
|
await withFileLock(this.filePath, async () => {
|
|
1332
1617
|
try {
|
|
@@ -1381,11 +1666,21 @@ var AuthStorage = class {
|
|
|
1381
1666
|
*/
|
|
1382
1667
|
async resolveCredentials(provider, opts) {
|
|
1383
1668
|
await this.ensureLoaded();
|
|
1669
|
+
if (provider === "moonshot" && this.data[MOONSHOT_OAUTH_KEY]) {
|
|
1670
|
+
try {
|
|
1671
|
+
return await this.resolveCredentials(MOONSHOT_OAUTH_KEY, opts);
|
|
1672
|
+
} catch (err) {
|
|
1673
|
+
if (err instanceof NotLoggedInError && this.data["moonshot"]) {
|
|
1674
|
+
return this.data["moonshot"];
|
|
1675
|
+
}
|
|
1676
|
+
throw err;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1384
1679
|
const creds = this.data[provider];
|
|
1385
1680
|
if (!creds) {
|
|
1386
1681
|
throw new NotLoggedInError(provider);
|
|
1387
1682
|
}
|
|
1388
|
-
if (provider
|
|
1683
|
+
if (STATIC_API_KEY_PROVIDERS.has(provider)) {
|
|
1389
1684
|
return creds;
|
|
1390
1685
|
}
|
|
1391
1686
|
if (!opts?.forceRefresh && Date.now() < creds.expiresAt) {
|
|
@@ -1404,7 +1699,7 @@ var AuthStorage = class {
|
|
|
1404
1699
|
}
|
|
1405
1700
|
} catch {
|
|
1406
1701
|
}
|
|
1407
|
-
const refreshFn = provider === "anthropic" ? refreshAnthropicToken : provider === "gemini" ? refreshGeminiToken : refreshOpenAIToken;
|
|
1702
|
+
const refreshFn = provider === "anthropic" ? refreshAnthropicToken : provider === "gemini" ? refreshGeminiToken : provider === MOONSHOT_OAUTH_KEY ? refreshKimiToken : refreshOpenAIToken;
|
|
1408
1703
|
let refreshed;
|
|
1409
1704
|
try {
|
|
1410
1705
|
refreshed = await refreshFn(creds.refreshToken);
|
|
@@ -1450,7 +1745,7 @@ var AuthStorage = class {
|
|
|
1450
1745
|
}
|
|
1451
1746
|
};
|
|
1452
1747
|
async function atomicWriteFile(filePath, content) {
|
|
1453
|
-
const tmpPath = `${filePath}.${process.pid}.${Date.now()}.${
|
|
1748
|
+
const tmpPath = `${filePath}.${process.pid}.${Date.now()}.${import_node_crypto6.default.randomUUID().slice(0, 8)}.tmp`;
|
|
1454
1749
|
try {
|
|
1455
1750
|
await import_promises4.default.writeFile(tmpPath, content, { encoding: "utf-8", mode: 384 });
|
|
1456
1751
|
await import_promises4.default.rename(tmpPath, filePath);
|
|
@@ -1522,7 +1817,7 @@ var TelegramBot = class {
|
|
|
1522
1817
|
} catch (err) {
|
|
1523
1818
|
if (!this.running) break;
|
|
1524
1819
|
console.error(`[telegram] Poll error: ${err instanceof Error ? err.message : err}`);
|
|
1525
|
-
await
|
|
1820
|
+
await sleep2(3e3);
|
|
1526
1821
|
}
|
|
1527
1822
|
}
|
|
1528
1823
|
}
|
|
@@ -1692,7 +1987,7 @@ function splitMessage(text) {
|
|
|
1692
1987
|
}
|
|
1693
1988
|
return chunks;
|
|
1694
1989
|
}
|
|
1695
|
-
function
|
|
1990
|
+
function sleep2(ms) {
|
|
1696
1991
|
return new Promise((r) => setTimeout(r, ms));
|
|
1697
1992
|
}
|
|
1698
1993
|
|
|
@@ -1777,9 +2072,9 @@ async function transcribeVoice(fileUrl) {
|
|
|
1777
2072
|
}
|
|
1778
2073
|
|
|
1779
2074
|
// src/auto-update.ts
|
|
1780
|
-
var
|
|
1781
|
-
var
|
|
1782
|
-
var
|
|
2075
|
+
var import_node_child_process2 = require("child_process");
|
|
2076
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
2077
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
1783
2078
|
var CHECK_INTERVAL_MS = 60 * 60 * 1e3;
|
|
1784
2079
|
var FETCH_TIMEOUT_MS2 = 1e4;
|
|
1785
2080
|
function compareVersions(a, b) {
|
|
@@ -1794,7 +2089,7 @@ function compareVersions(a, b) {
|
|
|
1794
2089
|
function performUpdateInBackground(command) {
|
|
1795
2090
|
try {
|
|
1796
2091
|
const parts = command.split(" ");
|
|
1797
|
-
const child = (0,
|
|
2092
|
+
const child = (0, import_node_child_process2.spawn)(parts[0], parts.slice(1), {
|
|
1798
2093
|
detached: true,
|
|
1799
2094
|
stdio: "ignore",
|
|
1800
2095
|
env: { ...process.env, npm_config_loglevel: "silent" }
|
|
@@ -1812,7 +2107,7 @@ function createAutoUpdater(config) {
|
|
|
1812
2107
|
}
|
|
1813
2108
|
function readState() {
|
|
1814
2109
|
try {
|
|
1815
|
-
const raw =
|
|
2110
|
+
const raw = import_node_fs3.default.readFileSync(stateFilePath(), "utf-8");
|
|
1816
2111
|
return JSON.parse(raw);
|
|
1817
2112
|
} catch {
|
|
1818
2113
|
return null;
|
|
@@ -1821,8 +2116,8 @@ function createAutoUpdater(config) {
|
|
|
1821
2116
|
function writeState(state) {
|
|
1822
2117
|
try {
|
|
1823
2118
|
const filePath = stateFilePath();
|
|
1824
|
-
|
|
1825
|
-
|
|
2119
|
+
import_node_fs3.default.mkdirSync(import_node_path5.default.dirname(filePath), { recursive: true, mode: 448 });
|
|
2120
|
+
import_node_fs3.default.writeFileSync(filePath, JSON.stringify(state));
|
|
1826
2121
|
} catch {
|
|
1827
2122
|
}
|
|
1828
2123
|
}
|
|
@@ -1947,7 +2242,9 @@ function createAutoUpdater(config) {
|
|
|
1947
2242
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1948
2243
|
0 && (module.exports = {
|
|
1949
2244
|
AuthStorage,
|
|
2245
|
+
DEFAULT_MAX_VIDEO_BYTES,
|
|
1950
2246
|
MODELS,
|
|
2247
|
+
MOONSHOT_OAUTH_KEY,
|
|
1951
2248
|
NotLoggedInError,
|
|
1952
2249
|
TelegramBot,
|
|
1953
2250
|
closeLogger,
|
|
@@ -1967,16 +2264,22 @@ function createAutoUpdater(config) {
|
|
|
1967
2264
|
getSessionId,
|
|
1968
2265
|
getSummaryModel,
|
|
1969
2266
|
getSupportedThinkingLevels,
|
|
2267
|
+
getVideoByteLimit,
|
|
2268
|
+
isKimiCodingEndpoint,
|
|
1970
2269
|
isLoggerOpen,
|
|
1971
2270
|
isModelLoaded,
|
|
1972
2271
|
isThinkingLevelSupported,
|
|
2272
|
+
kimiCodeBaseUrl,
|
|
2273
|
+
kimiCodingHeaders,
|
|
1973
2274
|
log,
|
|
1974
2275
|
loginAnthropic,
|
|
1975
2276
|
loginGemini,
|
|
2277
|
+
loginKimi,
|
|
1976
2278
|
loginOpenAI,
|
|
1977
2279
|
openLog,
|
|
1978
2280
|
refreshAnthropicToken,
|
|
1979
2281
|
refreshGeminiToken,
|
|
2282
|
+
refreshKimiToken,
|
|
1980
2283
|
refreshOpenAIToken,
|
|
1981
2284
|
registerLogCleanup,
|
|
1982
2285
|
resample,
|