kimiflare 0.34.1 → 0.35.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/index.js CHANGED
@@ -96,6 +96,31 @@ async function loadConfig() {
96
96
  const envCodeMode = readBooleanEnv("KIMIFLARE_CODE_MODE");
97
97
  const envCostAttribution = readBooleanEnv("KIMI_COST_ATTRIBUTION");
98
98
  const envFilePicker = readBooleanEnv("KIMIFLARE_FILE_PICKER");
99
+ const envCloudMode = readBooleanEnv("KIMIFLARE_CLOUD");
100
+ if (envCloudMode) {
101
+ return {
102
+ accountId: "",
103
+ apiToken: "",
104
+ model: envModel,
105
+ cloudMode: true,
106
+ reasoningEffort: envEffort,
107
+ coauthor: envCoauthor?.enabled ?? true,
108
+ coauthorName: envCoauthor?.name,
109
+ coauthorEmail: envCoauthor?.email,
110
+ cacheStablePrompts,
111
+ compiledContext,
112
+ imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? void 0 : imageHistoryTurns,
113
+ memoryEnabled: envMemoryEnabled,
114
+ memoryDbPath: envMemoryDbPath,
115
+ memoryMaxAgeDays: envMemoryMaxAgeDays,
116
+ memoryMaxEntries: envMemoryMaxEntries,
117
+ memoryEmbeddingModel: envMemoryEmbeddingModel,
118
+ plumbingModel: envPlumbingModel,
119
+ codeMode: envCodeMode,
120
+ costAttribution: envCostAttribution ?? false,
121
+ filePicker: envFilePicker ?? true
122
+ };
123
+ }
99
124
  if (envAccount && envToken) {
100
125
  return {
101
126
  accountId: envAccount,
@@ -128,6 +153,31 @@ async function loadConfig() {
128
153
  try {
129
154
  const raw = await readFile(configPath(), "utf8");
130
155
  const parsed = JSON.parse(raw);
156
+ if (parsed.cloudMode) {
157
+ return {
158
+ accountId: envAccount ?? parsed.accountId ?? "",
159
+ apiToken: envToken ?? parsed.apiToken ?? "",
160
+ model: envModel ?? parsed.model ?? DEFAULT_MODEL,
161
+ cloudMode: true,
162
+ reasoningEffort: envEffort ?? parsed.reasoningEffort,
163
+ coauthor: envCoauthor?.enabled ?? parsed.coauthor ?? true,
164
+ coauthorName: envCoauthor?.name ?? parsed.coauthorName,
165
+ coauthorEmail: envCoauthor?.email ?? parsed.coauthorEmail,
166
+ mcpServers: parsed.mcpServers,
167
+ cacheStablePrompts: parsed.cacheStablePrompts ?? cacheStablePrompts,
168
+ compiledContext: parsed.compiledContext ?? compiledContext,
169
+ imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? parsed.imageHistoryTurns : imageHistoryTurns,
170
+ memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled,
171
+ memoryDbPath: envMemoryDbPath ?? parsed.memoryDbPath,
172
+ memoryMaxAgeDays: envMemoryMaxAgeDays ?? parsed.memoryMaxAgeDays,
173
+ memoryMaxEntries: envMemoryMaxEntries ?? parsed.memoryMaxEntries,
174
+ memoryEmbeddingModel: envMemoryEmbeddingModel ?? parsed.memoryEmbeddingModel,
175
+ plumbingModel: envPlumbingModel ?? parsed.plumbingModel,
176
+ codeMode: envCodeMode ?? parsed.codeMode,
177
+ costAttribution: envCostAttribution ?? parsed.costAttribution ?? false,
178
+ filePicker: envFilePicker ?? parsed.filePicker ?? true
179
+ };
180
+ }
131
181
  if (parsed.accountId && parsed.apiToken) {
132
182
  return {
133
183
  accountId: envAccount ?? parsed.accountId,
@@ -155,7 +205,8 @@ async function loadConfig() {
155
205
  memoryExtractionModel: envMemoryExtractionModel ?? parsed.memoryExtractionModel,
156
206
  codeMode: envCodeMode ?? parsed.codeMode ?? true,
157
207
  costAttribution: envCostAttribution ?? parsed.costAttribution ?? true,
158
- filePicker: envFilePicker ?? parsed.filePicker ?? true
208
+ filePicker: envFilePicker ?? parsed.filePicker ?? true,
209
+ cloudMode: envCloudMode ?? parsed.cloudMode
159
210
  };
160
211
  }
161
212
  } catch {
@@ -443,7 +494,7 @@ async function* runKimi(opts2) {
443
494
  let res;
444
495
  try {
445
496
  const headers = {
446
- Authorization: `Bearer ${opts2.apiToken}`,
497
+ Authorization: `Bearer ${opts2.cloudMode && opts2.cloudToken ? opts2.cloudToken : opts2.apiToken}`,
447
498
  "Content-Type": "application/json",
448
499
  "User-Agent": getUserAgent(),
449
500
  ...gatewayHeaders
@@ -500,6 +551,12 @@ function validateModelId(model) {
500
551
  }
501
552
  function buildKimiRequestTarget(opts2) {
502
553
  validateModelId(opts2.model);
554
+ if (opts2.cloudMode) {
555
+ return {
556
+ url: "https://api.kimiflare.com/v1/chat",
557
+ headers: opts2.cloudToken ? { Authorization: `Bearer ${opts2.cloudToken}` } : {}
558
+ };
559
+ }
503
560
  if (!opts2.gateway?.id) {
504
561
  return {
505
562
  url: `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(opts2.accountId)}/ai/run/${opts2.model}`,
@@ -1326,6 +1383,8 @@ var init_api_generator = __esm({
1326
1383
  });
1327
1384
 
1328
1385
  // src/code-mode/sandbox.ts
1386
+ import { join as join6, dirname as dirname3 } from "path";
1387
+ import { pathToFileURL } from "url";
1329
1388
  function stripTypescript(code) {
1330
1389
  let js = code;
1331
1390
  js = js.replace(/interface\s+\w+\s*\{[\s\S]*?\n\}/g, "");
@@ -1342,6 +1401,36 @@ function stripTypescript(code) {
1342
1401
  js = js.replace(/\n{3,}/g, "\n\n");
1343
1402
  return js.trim();
1344
1403
  }
1404
+ async function loadTypescript(cwd) {
1405
+ let dir = cwd;
1406
+ while (dir !== dirname3(dir)) {
1407
+ try {
1408
+ const tsPath = join6(dir, "node_modules", "typescript", "lib", "typescript.js");
1409
+ return await import(pathToFileURL(tsPath).href);
1410
+ } catch {
1411
+ }
1412
+ dir = dirname3(dir);
1413
+ }
1414
+ return null;
1415
+ }
1416
+ async function transpileOrStrip(code, cwd) {
1417
+ const ts = await loadTypescript(cwd);
1418
+ if (ts) {
1419
+ const result = ts.transpileModule(code, {
1420
+ compilerOptions: {
1421
+ module: ts.ModuleKind.ES2022,
1422
+ target: ts.ScriptTarget.ES2022,
1423
+ esModuleInterop: true,
1424
+ isolatedModules: true
1425
+ }
1426
+ });
1427
+ return { js: result.outputText, warnings: [] };
1428
+ }
1429
+ return {
1430
+ js: stripTypescript(code),
1431
+ warnings: ["TypeScript not found in node_modules. Using fallback parser; install typescript for reliable transpilation."]
1432
+ };
1433
+ }
1345
1434
  async function runWithIsolatedVm(opts2) {
1346
1435
  const { Isolate } = await import("isolated-vm");
1347
1436
  const isolate = new Isolate({ memoryLimit: opts2.memoryLimitMB ?? 128 });
@@ -1389,7 +1478,7 @@ async function runWithIsolatedVm(opts2) {
1389
1478
  await context.eval(`var api = {
1390
1479
  ${apiMethods}
1391
1480
  };`);
1392
- const jsCode = stripTypescript(opts2.code);
1481
+ const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
1393
1482
  const wrapped = `(async function() {
1394
1483
  ${jsCode}
1395
1484
  })();`;
@@ -1400,11 +1489,11 @@ ${jsCode}
1400
1489
  await new Promise((r) => setTimeout(r, 10));
1401
1490
  } catch (err) {
1402
1491
  const message2 = err instanceof Error ? err.message : String(err);
1403
- return { output: "", logs, error: message2, toolCalls };
1492
+ return { output: "", logs, error: message2, toolCalls, warnings };
1404
1493
  } finally {
1405
1494
  isolate.dispose();
1406
1495
  }
1407
- return { output: logs.join("\n"), logs, toolCalls };
1496
+ return { output: logs.join("\n"), logs, toolCalls, warnings };
1408
1497
  }
1409
1498
  async function runWithNodeVm(opts2) {
1410
1499
  const { runInNewContext } = await import("vm");
@@ -1472,7 +1561,7 @@ async function runWithNodeVm(opts2) {
1472
1561
  return result.content;
1473
1562
  };
1474
1563
  }
1475
- const jsCode = stripTypescript(opts2.code);
1564
+ const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
1476
1565
  const wrapped = `"use strict";
1477
1566
  (async function() {
1478
1567
  ${jsCode}
@@ -1483,9 +1572,9 @@ ${jsCode}
1483
1572
  await new Promise((r) => setTimeout(r, 10));
1484
1573
  } catch (err) {
1485
1574
  const message2 = err instanceof Error ? err.message : String(err);
1486
- return { output: "", logs, error: message2, toolCalls };
1575
+ return { output: "", logs, error: message2, toolCalls, warnings };
1487
1576
  }
1488
- return { output: logs.join("\n"), logs, toolCalls };
1577
+ return { output: logs.join("\n"), logs, toolCalls, warnings };
1489
1578
  }
1490
1579
  async function runInSandbox(opts2) {
1491
1580
  try {
@@ -1646,7 +1735,9 @@ Use console.log() to return results. Only console.log output will be sent back t
1646
1735
  maxCompletionTokens: opts2.maxCompletionTokens,
1647
1736
  reasoningEffort: opts2.reasoningEffort,
1648
1737
  sessionId: opts2.sessionId,
1649
- gateway: opts2.gateway
1738
+ gateway: opts2.gateway,
1739
+ cloudMode: opts2.cloudMode,
1740
+ cloudToken: opts2.cloudToken
1650
1741
  });
1651
1742
  for await (const ev of events) {
1652
1743
  switch (ev.type) {
@@ -1825,10 +1916,13 @@ Use console.log() to return results. Only console.log output will be sent back t
1825
1916
  toolResults.push(toolResult);
1826
1917
  opts2.callbacks.onToolResult?.(toolResult);
1827
1918
  }
1828
- const resultContent = sandboxResult.error ? `Error: ${sandboxResult.error}
1919
+ const warningPrefix = sandboxResult.warnings?.length ? `Warning: ${sandboxResult.warnings.join(" ")}
1920
+
1921
+ ` : "";
1922
+ const resultContent = sandboxResult.error ? `${warningPrefix}Error: ${sandboxResult.error}
1829
1923
 
1830
1924
  Output:
1831
- ${sandboxResult.output}` : sandboxResult.output;
1925
+ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
1832
1926
  const result = {
1833
1927
  tool_call_id: tc.id,
1834
1928
  name: "execute_code",
@@ -2180,11 +2274,11 @@ var init_mode = __esm({
2180
2274
 
2181
2275
  // src/agent/system-prompt.ts
2182
2276
  import { platform, release, homedir as homedir3 } from "os";
2183
- import { basename, join as join6 } from "path";
2277
+ import { basename, join as join7 } from "path";
2184
2278
  import { readFileSync as readFileSync2, statSync } from "fs";
2185
2279
  function loadContextFile(cwd) {
2186
2280
  for (const name of CONTEXT_FILENAMES) {
2187
- const path = join6(cwd, name);
2281
+ const path = join7(cwd, name);
2188
2282
  try {
2189
2283
  const s = statSync(path);
2190
2284
  if (!s.isFile() || s.size > MAX_CONTEXT_BYTES) continue;
@@ -2339,7 +2433,7 @@ var init_read = __esm({
2339
2433
 
2340
2434
  // src/tools/write.ts
2341
2435
  import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
2342
- import { dirname as dirname3 } from "path";
2436
+ import { dirname as dirname4 } from "path";
2343
2437
  var writeTool;
2344
2438
  var init_write = __esm({
2345
2439
  "src/tools/write.ts"() {
@@ -2369,7 +2463,7 @@ var init_write = __esm({
2369
2463
  before = await readFile4(abs, "utf8");
2370
2464
  } catch {
2371
2465
  }
2372
- await mkdir4(dirname3(abs), { recursive: true });
2466
+ await mkdir4(dirname4(abs), { recursive: true });
2373
2467
  await writeFile3(abs, args.content, "utf8");
2374
2468
  const verb = before ? "Overwrote" : "Created";
2375
2469
  return `${verb} ${args.path} (${args.content.length} chars).`;
@@ -2436,7 +2530,7 @@ var init_edit = __esm({
2436
2530
  // src/tools/bash.ts
2437
2531
  import { spawn } from "child_process";
2438
2532
  import { tmpdir } from "os";
2439
- import { join as join7 } from "path";
2533
+ import { join as join8 } from "path";
2440
2534
  function formatBashTitle(raw) {
2441
2535
  let cmd = (raw ?? "").trim();
2442
2536
  const m = cmd.match(/^cd\s+([^\s&;]+)\s*(?:&&|;)\s*(.*)$/);
@@ -2454,7 +2548,7 @@ function injectCoauthor(command, coauthor) {
2454
2548
  const mentionsGit = /\bgit\b/.test(trimmed);
2455
2549
  if (!createsCommit && !isRebaseContinue && !mentionsGit) return command;
2456
2550
  if (movesHeadOnly) return command;
2457
- const tmpFile = join7(tmpdir(), `kf-coauthor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
2551
+ const tmpFile = join8(tmpdir(), `kf-coauthor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
2458
2552
  const amendBlock = `
2459
2553
  if ! git log -1 --pretty=%B 2>/dev/null | grep -qF "${trailer}"; then
2460
2554
  git log -1 --pretty=%B | git interpret-trailers --trailer "${trailer}" > "${tmpFile}" && git commit --amend -F "${tmpFile}" --no-edit && rm -f "${tmpFile}"
@@ -3618,16 +3712,16 @@ var init_executor = __esm({
3618
3712
  // src/util/update-check.ts
3619
3713
  import { readFile as readFile7, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
3620
3714
  import { homedir as homedir5 } from "os";
3621
- import { join as join8, dirname as dirname4 } from "path";
3715
+ import { join as join9, dirname as dirname5 } from "path";
3622
3716
  import { fileURLToPath as fileURLToPath2 } from "url";
3623
3717
  function cachePath() {
3624
- const xdg = process.env.XDG_CONFIG_HOME || join8(homedir5(), ".config");
3625
- return join8(xdg, "kimiflare", "update-check.json");
3718
+ const xdg = process.env.XDG_CONFIG_HOME || join9(homedir5(), ".config");
3719
+ return join9(xdg, "kimiflare", "update-check.json");
3626
3720
  }
3627
3721
  async function findPackageJson(startDir) {
3628
3722
  let dir = startDir;
3629
3723
  while (true) {
3630
- const candidate = join8(dir, "package.json");
3724
+ const candidate = join9(dir, "package.json");
3631
3725
  try {
3632
3726
  const raw = await readFile7(candidate, "utf8");
3633
3727
  const parsed = JSON.parse(raw);
@@ -3636,14 +3730,14 @@ async function findPackageJson(startDir) {
3636
3730
  }
3637
3731
  } catch {
3638
3732
  }
3639
- const parent = dirname4(dir);
3733
+ const parent = dirname5(dir);
3640
3734
  if (parent === dir) break;
3641
3735
  dir = parent;
3642
3736
  }
3643
3737
  return null;
3644
3738
  }
3645
3739
  async function readLocalVersion() {
3646
- const here = dirname4(fileURLToPath2(import.meta.url));
3740
+ const here = dirname5(fileURLToPath2(import.meta.url));
3647
3741
  const found = await findPackageJson(here);
3648
3742
  return found?.version ?? null;
3649
3743
  }
@@ -3660,7 +3754,7 @@ async function readCache() {
3660
3754
  }
3661
3755
  async function writeCache(entry) {
3662
3756
  const p = cachePath();
3663
- await mkdir5(dirname4(p), { recursive: true });
3757
+ await mkdir5(dirname5(p), { recursive: true });
3664
3758
  await writeFile5(p, JSON.stringify(entry), "utf8");
3665
3759
  }
3666
3760
  async function fetchLatestVersion() {
@@ -3720,20 +3814,20 @@ var init_update_check = __esm({
3720
3814
  // src/remote/session-store.ts
3721
3815
  import { readFile as readFile8, writeFile as writeFile6, mkdir as mkdir6, readdir as readdir2 } from "fs/promises";
3722
3816
  import { homedir as homedir6 } from "os";
3723
- import { join as join9 } from "path";
3817
+ import { join as join10 } from "path";
3724
3818
  function remoteDir() {
3725
- const xdg = process.env.XDG_DATA_HOME || join9(homedir6(), ".config");
3726
- return join9(xdg, "kimiflare", "remote");
3819
+ const xdg = process.env.XDG_DATA_HOME || join10(homedir6(), ".config");
3820
+ return join10(xdg, "kimiflare", "remote");
3727
3821
  }
3728
3822
  async function saveRemoteSession(session) {
3729
3823
  const dir = remoteDir();
3730
3824
  await mkdir6(dir, { recursive: true });
3731
- const path = join9(dir, `${session.sessionId}.json`);
3825
+ const path = join10(dir, `${session.sessionId}.json`);
3732
3826
  await writeFile6(path, JSON.stringify(session, null, 2) + "\n", "utf8");
3733
3827
  }
3734
3828
  async function loadRemoteSession(sessionId) {
3735
3829
  try {
3736
- const path = join9(remoteDir(), `${sessionId}.json`);
3830
+ const path = join10(remoteDir(), `${sessionId}.json`);
3737
3831
  const raw = await readFile8(path, "utf8");
3738
3832
  return JSON.parse(raw);
3739
3833
  } catch {
@@ -3748,7 +3842,7 @@ async function listRemoteSessions() {
3748
3842
  for (const file of files) {
3749
3843
  if (!file.endsWith(".json")) continue;
3750
3844
  try {
3751
- const raw = await readFile8(join9(dir, file), "utf8");
3845
+ const raw = await readFile8(join10(dir, file), "utf8");
3752
3846
  sessions.push(JSON.parse(raw));
3753
3847
  } catch {
3754
3848
  }
@@ -3770,7 +3864,7 @@ var init_session_store = __esm({
3770
3864
 
3771
3865
  // src/remote/deploy.ts
3772
3866
  import { execSync } from "child_process";
3773
- import { join as join10, dirname as dirname5 } from "path";
3867
+ import { join as join11, dirname as dirname6 } from "path";
3774
3868
  import { fileURLToPath as fileURLToPath3 } from "url";
3775
3869
  import { randomBytes } from "crypto";
3776
3870
  function generateSecret() {
@@ -3805,7 +3899,7 @@ async function* deployForTui() {
3805
3899
  yield { message: "Docker OK" };
3806
3900
  yield { message: "Building remote agent bundle..." };
3807
3901
  try {
3808
- runCapture("npm run build:remote-agent", join10(REMOTE_DIR, ".."));
3902
+ runCapture("npm run build:remote-agent", join11(REMOTE_DIR, ".."));
3809
3903
  yield { message: "Agent bundle built" };
3810
3904
  } catch (err) {
3811
3905
  yield { message: `Build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
@@ -3934,9 +4028,9 @@ var init_deploy = __esm({
3934
4028
  "src/remote/deploy.ts"() {
3935
4029
  "use strict";
3936
4030
  init_config();
3937
- __dirname = dirname5(fileURLToPath3(import.meta.url));
3938
- REMOTE_DIR = join10(__dirname, "..", "..", "..", "remote");
3939
- WORKER_DIR = join10(REMOTE_DIR, "worker");
4031
+ __dirname = dirname6(fileURLToPath3(import.meta.url));
4032
+ REMOTE_DIR = join11(__dirname, "..", "..", "..", "remote");
4033
+ WORKER_DIR = join11(REMOTE_DIR, "worker");
3940
4034
  }
3941
4035
  });
3942
4036
 
@@ -4360,11 +4454,11 @@ var init_heuristic = __esm({
4360
4454
 
4361
4455
  // src/cost-attribution/classify-from-session.ts
4362
4456
  import { readFile as readFile9 } from "fs/promises";
4363
- import { join as join11 } from "path";
4457
+ import { join as join12 } from "path";
4364
4458
  import { homedir as homedir7 } from "os";
4365
4459
  function sessionsDir() {
4366
- const xdg = process.env.XDG_DATA_HOME || join11(homedir7(), ".local", "share");
4367
- return join11(xdg, "kimiflare", "sessions");
4460
+ const xdg = process.env.XDG_DATA_HOME || join12(homedir7(), ".local", "share");
4461
+ return join12(xdg, "kimiflare", "sessions");
4368
4462
  }
4369
4463
  function parseToolCalls(calls) {
4370
4464
  return calls.map((c) => {
@@ -4378,7 +4472,7 @@ function parseToolCalls(calls) {
4378
4472
  }
4379
4473
  async function classifyFromSessionFile(sessionId) {
4380
4474
  try {
4381
- const raw = await readFile9(join11(sessionsDir(), `${sessionId}.json`), "utf8");
4475
+ const raw = await readFile9(join12(sessionsDir(), `${sessionId}.json`), "utf8");
4382
4476
  const session = JSON.parse(raw);
4383
4477
  const messages = session.messages ?? [];
4384
4478
  const turns = [];
@@ -4412,14 +4506,14 @@ __export(cli_exports, {
4412
4506
  runCostCommand: () => runCostCommand
4413
4507
  });
4414
4508
  import { readFile as readFile10 } from "fs/promises";
4415
- import { join as join12 } from "path";
4509
+ import { join as join13 } from "path";
4416
4510
  import { homedir as homedir8 } from "os";
4417
4511
  function usageDir() {
4418
- const xdg = process.env.XDG_DATA_HOME || join12(homedir8(), ".local", "share");
4419
- return join12(xdg, "kimiflare");
4512
+ const xdg = process.env.XDG_DATA_HOME || join13(homedir8(), ".local", "share");
4513
+ return join13(xdg, "kimiflare");
4420
4514
  }
4421
4515
  function usagePath() {
4422
- return join12(usageDir(), "usage.json");
4516
+ return join13(usageDir(), "usage.json");
4423
4517
  }
4424
4518
  function today() {
4425
4519
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -4517,6 +4611,98 @@ var init_cli = __esm({
4517
4611
  }
4518
4612
  });
4519
4613
 
4614
+ // src/cloud/auth.ts
4615
+ var auth_exports = {};
4616
+ __export(auth_exports, {
4617
+ authenticateDevice: () => authenticateDevice,
4618
+ clearCloudCredentials: () => clearCloudCredentials,
4619
+ loadCloudCredentials: () => loadCloudCredentials,
4620
+ saveCloudCredentials: () => saveCloudCredentials
4621
+ });
4622
+ import { readFile as readFile11, writeFile as writeFile7 } from "fs/promises";
4623
+ import { homedir as homedir9 } from "os";
4624
+ import { join as join14 } from "path";
4625
+ function cloudCredPath() {
4626
+ const xdg = process.env.XDG_CONFIG_HOME || join14(homedir9(), ".config");
4627
+ return join14(xdg, "kimiflare", "cloud.json");
4628
+ }
4629
+ function generateCode() {
4630
+ const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
4631
+ let out = "";
4632
+ for (let i = 0; i < 8; i++) {
4633
+ out += chars[Math.floor(Math.random() * chars.length)];
4634
+ }
4635
+ return out;
4636
+ }
4637
+ async function loadCloudCredentials() {
4638
+ try {
4639
+ const raw = await readFile11(cloudCredPath(), "utf8");
4640
+ const parsed = JSON.parse(raw);
4641
+ if (parsed.expiresAt && parsed.expiresAt > Date.now() / 1e3) {
4642
+ return parsed;
4643
+ }
4644
+ } catch {
4645
+ }
4646
+ return null;
4647
+ }
4648
+ async function saveCloudCredentials(creds) {
4649
+ const p = cloudCredPath();
4650
+ await writeFile7(p, JSON.stringify(creds, null, 2), "utf8");
4651
+ }
4652
+ async function clearCloudCredentials() {
4653
+ try {
4654
+ const { unlink: unlink4 } = await import("fs/promises");
4655
+ await unlink4(cloudCredPath());
4656
+ } catch {
4657
+ }
4658
+ }
4659
+ async function authenticateDevice(onStatus) {
4660
+ const deviceCode = `device-${generateCode()}-${Date.now()}`;
4661
+ const userCode = `${generateCode()}-${generateCode()}`;
4662
+ const registerRes = await fetch(`${CLOUD_API_URL}/auth/device`, {
4663
+ method: "POST",
4664
+ headers: { "Content-Type": "application/json" },
4665
+ body: JSON.stringify({ device_code: deviceCode, user_code: userCode })
4666
+ });
4667
+ if (!registerRes.ok) {
4668
+ const err = await registerRes.json().catch(() => ({}));
4669
+ throw new Error(`Failed to register device: ${err.error || registerRes.statusText}`);
4670
+ }
4671
+ const authUrl = `${CLOUD_API_URL}/auth/github?code=${encodeURIComponent(userCode)}`;
4672
+ onStatus({ url: authUrl, userCode, polling: false });
4673
+ const startTime = Date.now();
4674
+ while (Date.now() - startTime < POLL_TIMEOUT_MS) {
4675
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
4676
+ onStatus({ url: authUrl, userCode, polling: true });
4677
+ const pollRes = await fetch(`${CLOUD_API_URL}/auth/poll`, {
4678
+ method: "POST",
4679
+ headers: { "Content-Type": "application/json" },
4680
+ body: JSON.stringify({ device_code: deviceCode })
4681
+ });
4682
+ if (!pollRes.ok) continue;
4683
+ const pollData = await pollRes.json();
4684
+ if (pollData.status === "approved" && pollData.access_token) {
4685
+ const creds = {
4686
+ accessToken: pollData.access_token,
4687
+ expiresAt: Math.floor(Date.now() / 1e3) + 7 * 24 * 60 * 60
4688
+ // 7 days
4689
+ };
4690
+ await saveCloudCredentials(creds);
4691
+ return creds;
4692
+ }
4693
+ }
4694
+ throw new Error("Authentication timed out. Please try again.");
4695
+ }
4696
+ var CLOUD_API_URL, POLL_INTERVAL_MS, POLL_TIMEOUT_MS;
4697
+ var init_auth = __esm({
4698
+ "src/cloud/auth.ts"() {
4699
+ "use strict";
4700
+ CLOUD_API_URL = "https://api.kimiflare.com";
4701
+ POLL_INTERVAL_MS = 5e3;
4702
+ POLL_TIMEOUT_MS = 10 * 60 * 1e3;
4703
+ }
4704
+ });
4705
+
4520
4706
  // src/remote/tui-auth.ts
4521
4707
  var tui_auth_exports = {};
4522
4708
  __export(tui_auth_exports, {
@@ -5426,9 +5612,9 @@ var init_connection = __esm({
5426
5612
  });
5427
5613
 
5428
5614
  // src/lsp/protocol.ts
5429
- import { pathToFileURL, fileURLToPath as fileURLToPath4 } from "url";
5615
+ import { pathToFileURL as pathToFileURL2, fileURLToPath as fileURLToPath4 } from "url";
5430
5616
  function toUri(path) {
5431
- return pathToFileURL(path).href;
5617
+ return pathToFileURL2(path).href;
5432
5618
  }
5433
5619
  function fromUri(uri) {
5434
5620
  return fileURLToPath4(uri);
@@ -6568,7 +6754,7 @@ import { useEffect, useState } from "react";
6568
6754
  import { Box as Box5, Text as Text5 } from "ink";
6569
6755
  import Spinner3 from "ink-spinner";
6570
6756
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
6571
- function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode }) {
6757
+ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode }) {
6572
6758
  const theme = useTheme();
6573
6759
  const [now2, setNow] = useState(Date.now());
6574
6760
  const modeColor = mode === "plan" ? theme.modeBadge.plan : mode === "auto" ? theme.modeBadge.auto : theme.modeBadge.edit;
@@ -6580,6 +6766,7 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
6580
6766
  }, [thinking, turnStartedAt]);
6581
6767
  const elapsed = turnStartedAt !== null ? formatElapsed(now2 - turnStartedAt) : null;
6582
6768
  const leftParts = [`${shortModel(model)}`, effort];
6769
+ if (cloudMode) leftParts.push("CLOUD");
6583
6770
  if (codeMode) leftParts.push("CODE");
6584
6771
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
6585
6772
  /* @__PURE__ */ jsxs5(Box5, { children: [
@@ -7634,15 +7821,25 @@ var init_text_input = __esm({
7634
7821
  // src/ui/onboarding.tsx
7635
7822
  import { useState as useState5 } from "react";
7636
7823
  import { Box as Box9, Text as Text10 } from "ink";
7824
+ import SelectInput3 from "ink-select-input";
7637
7825
  import { Fragment, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
7638
7826
  function Onboarding({ onDone }) {
7639
7827
  const theme = useTheme();
7640
- const [step, setStep] = useState5("accountId");
7828
+ const [step, setStep] = useState5("mode");
7829
+ const [mode, setMode] = useState5("byok");
7641
7830
  const [accountId, setAccountId] = useState5("");
7642
7831
  const [apiToken, setApiToken] = useState5("");
7643
7832
  const [model, setModel] = useState5(DEFAULT_MODEL);
7644
7833
  const [savedPath, setSavedPath] = useState5(null);
7645
- const stepIndex = STEPS.indexOf(step) + 1;
7834
+ const handleModeSelect = (item) => {
7835
+ if (item.value === "cloud") {
7836
+ setMode("cloud");
7837
+ setStep("cloudDone");
7838
+ } else {
7839
+ setMode("byok");
7840
+ setStep("accountId");
7841
+ }
7842
+ };
7646
7843
  const handleAccountIdSubmit = (value) => {
7647
7844
  const trimmed = value.trim();
7648
7845
  if (!trimmed) return;
@@ -7661,7 +7858,17 @@ function Onboarding({ onDone }) {
7661
7858
  setStep("confirm");
7662
7859
  };
7663
7860
  const handleConfirm = async () => {
7664
- const cfg = { accountId, apiToken, model };
7861
+ const cfg = mode === "cloud" ? { accountId: "", apiToken: "", model, cloudMode: true } : { accountId, apiToken, model };
7862
+ try {
7863
+ const path = await saveConfig(cfg);
7864
+ setSavedPath(path);
7865
+ onDone(cfg);
7866
+ } catch (e) {
7867
+ setSavedPath(`error: ${e.message}`);
7868
+ }
7869
+ };
7870
+ const handleCloudSave = async () => {
7871
+ const cfg = { accountId: "", apiToken: "", model: DEFAULT_MODEL, cloudMode: true };
7665
7872
  try {
7666
7873
  const path = await saveConfig(cfg);
7667
7874
  setSavedPath(path);
@@ -7670,6 +7877,9 @@ function Onboarding({ onDone }) {
7670
7877
  setSavedPath(`error: ${e.message}`);
7671
7878
  }
7672
7879
  };
7880
+ const byokSteps = ["accountId", "apiToken", "model", "confirm"];
7881
+ const stepIndex = step === "mode" ? 1 : step === "cloudDone" ? 2 : byokSteps.indexOf(step) + 2;
7882
+ const totalSteps = mode === "cloud" ? 2 : byokSteps.length + 1;
7673
7883
  return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingY: 1, children: [
7674
7884
  /* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, children: [
7675
7885
  /* @__PURE__ */ jsx11(Text10, { bold: true, color: theme.palette.primary, children: "kimiflare" }),
@@ -7682,9 +7892,22 @@ function Onboarding({ onDone }) {
7682
7892
  "Step ",
7683
7893
  stepIndex,
7684
7894
  " of ",
7685
- STEPS.length
7895
+ totalSteps
7686
7896
  ] }),
7687
7897
  /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
7898
+ step === "mode" && /* @__PURE__ */ jsxs9(Fragment, { children: [
7899
+ /* @__PURE__ */ jsx11(Text10, { children: "How do you want to connect?" }),
7900
+ /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(
7901
+ SelectInput3,
7902
+ {
7903
+ items: [
7904
+ { label: "Cloud (managed) \u2014 no API key needed", value: "cloud" },
7905
+ { label: "BYOK \u2014 bring your own Cloudflare key", value: "byok" }
7906
+ ],
7907
+ onSelect: handleModeSelect
7908
+ }
7909
+ ) })
7910
+ ] }),
7688
7911
  step === "accountId" && /* @__PURE__ */ jsxs9(Fragment, { children: [
7689
7912
  /* @__PURE__ */ jsx11(Text10, { children: "Enter your Cloudflare Account ID" }),
7690
7913
  /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
@@ -7774,6 +7997,23 @@ function Onboarding({ onDone }) {
7774
7997
  )
7775
7998
  ] })
7776
7999
  ] }),
8000
+ step === "cloudDone" && /* @__PURE__ */ jsxs9(Fragment, { children: [
8001
+ /* @__PURE__ */ jsx11(Text10, { children: "Cloud mode selected" }),
8002
+ /* @__PURE__ */ jsx11(Text10, { color: theme.info.color, children: "No API key needed. Run `kimiflare auth cloud` to sign in." }),
8003
+ /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { children: "Press Enter to save, or Ctrl+C to cancel" }) }),
8004
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
8005
+ /* @__PURE__ */ jsx11(Text10, { color: theme.palette.primary, children: "\u203A " }),
8006
+ /* @__PURE__ */ jsx11(
8007
+ CustomTextInput,
8008
+ {
8009
+ value: "",
8010
+ onChange: () => {
8011
+ },
8012
+ onSubmit: handleCloudSave
8013
+ }
8014
+ )
8015
+ ] })
8016
+ ] }),
7777
8017
  savedPath && /* @__PURE__ */ jsxs9(Text10, { color: theme.palette.success, children: [
7778
8018
  "Config saved to ",
7779
8019
  savedPath
@@ -7781,14 +8021,12 @@ function Onboarding({ onDone }) {
7781
8021
  ] })
7782
8022
  ] });
7783
8023
  }
7784
- var STEPS;
7785
8024
  var init_onboarding = __esm({
7786
8025
  "src/ui/onboarding.tsx"() {
7787
8026
  "use strict";
7788
8027
  init_text_input();
7789
8028
  init_config();
7790
8029
  init_theme_context();
7791
- STEPS = ["accountId", "apiToken", "model", "confirm"];
7792
8030
  }
7793
8031
  });
7794
8032
 
@@ -7839,9 +8077,9 @@ var init_welcome = __esm({
7839
8077
  // src/ui/help-menu.tsx
7840
8078
  import { useState as useState6 } from "react";
7841
8079
  import { Box as Box11, Text as Text12, useInput as useInput2 } from "ink";
7842
- import SelectInput3 from "ink-select-input";
8080
+ import SelectInput4 from "ink-select-input";
7843
8081
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
7844
- function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand }) {
8082
+ function HelpMenu({ customCommands, costAttributionEnabled, cloudMode, onDone, onCommand }) {
7845
8083
  const theme = useTheme();
7846
8084
  const [page, setPage] = useState6("main");
7847
8085
  const customs = customCommands ?? [];
@@ -7858,8 +8096,9 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
7858
8096
  onCommand(command);
7859
8097
  onDone();
7860
8098
  };
8099
+ const categories = cloudMode ? CATEGORIES.filter((c) => c.key !== "gateway") : CATEGORIES;
7861
8100
  if (page === "main") {
7862
- const items2 = CATEGORIES.map((cat) => ({
8101
+ const items2 = categories.map((cat) => ({
7863
8102
  label: cat.label,
7864
8103
  value: cat.key,
7865
8104
  key: cat.key
@@ -7872,7 +8111,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
7872
8111
  /* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: "Help" }),
7873
8112
  /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to close." }),
7874
8113
  /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
7875
- SelectInput3,
8114
+ SelectInput4,
7876
8115
  {
7877
8116
  items: items2,
7878
8117
  onSelect: (item) => {
@@ -7899,7 +8138,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
7899
8138
  /* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: "Custom commands" }),
7900
8139
  /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: customs.length === 0 ? "no custom commands found in .kimiflare/commands/" : "Arrow keys to navigate, Enter to run, Esc to go back." }),
7901
8140
  /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
7902
- SelectInput3,
8141
+ SelectInput4,
7903
8142
  {
7904
8143
  items: items2,
7905
8144
  onSelect: (item) => {
@@ -7913,7 +8152,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
7913
8152
  ) })
7914
8153
  ] });
7915
8154
  }
7916
- const category = CATEGORIES.find((c) => c.key === page);
8155
+ const category = categories.find((c) => c.key === page);
7917
8156
  const selectable = category.commands.filter((cmd) => cmd.selectable !== false);
7918
8157
  const staticCmds = category.commands.filter((cmd) => cmd.selectable === false);
7919
8158
  const items = selectable.map((cmd) => ({
@@ -7926,7 +8165,7 @@ function HelpMenu({ customCommands, costAttributionEnabled, onDone, onCommand })
7926
8165
  /* @__PURE__ */ jsx13(Text12, { color: theme.accent, bold: true, children: category.label }),
7927
8166
  /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to execute, Esc to go back." }),
7928
8167
  /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
7929
- SelectInput3,
8168
+ SelectInput4,
7930
8169
  {
7931
8170
  items,
7932
8171
  onSelect: (item) => {
@@ -8172,7 +8411,7 @@ var init_tui_deploy = __esm({
8172
8411
  // src/ui/remote-dashboard.tsx
8173
8412
  import { useEffect as useEffect4, useState as useState7 } from "react";
8174
8413
  import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
8175
- import SelectInput4 from "ink-select-input";
8414
+ import SelectInput5 from "ink-select-input";
8176
8415
  import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
8177
8416
  function RemoteDashboard({ onSelect, onCancel }) {
8178
8417
  const theme = useTheme();
@@ -8253,7 +8492,7 @@ function RemoteDashboard({ onSelect, onCancel }) {
8253
8492
  refreshing ? "(refreshing...)" : ""
8254
8493
  ] }),
8255
8494
  /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8256
- SelectInput4,
8495
+ SelectInput5,
8257
8496
  {
8258
8497
  items,
8259
8498
  onSelect: (item) => {
@@ -8424,12 +8663,12 @@ __export(sessions_exports, {
8424
8663
  pruneSessions: () => pruneSessions,
8425
8664
  saveSession: () => saveSession
8426
8665
  });
8427
- import { readFile as readFile11, writeFile as writeFile7, mkdir as mkdir7, readdir as readdir3, stat as stat4 } from "fs/promises";
8428
- import { homedir as homedir9 } from "os";
8429
- import { join as join13 } from "path";
8666
+ import { readFile as readFile12, writeFile as writeFile8, mkdir as mkdir7, readdir as readdir3, stat as stat4 } from "fs/promises";
8667
+ import { homedir as homedir10 } from "os";
8668
+ import { join as join15 } from "path";
8430
8669
  function sessionsDir2() {
8431
- const xdg = process.env.XDG_DATA_HOME || join13(homedir9(), ".local", "share");
8432
- return join13(xdg, "kimiflare", "sessions");
8670
+ const xdg = process.env.XDG_DATA_HOME || join15(homedir10(), ".local", "share");
8671
+ return join15(xdg, "kimiflare", "sessions");
8433
8672
  }
8434
8673
  function sanitize(text) {
8435
8674
  return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
@@ -8442,8 +8681,8 @@ function makeSessionId(firstPrompt) {
8442
8681
  async function saveSession(file) {
8443
8682
  const dir = sessionsDir2();
8444
8683
  await mkdir7(dir, { recursive: true });
8445
- const path = join13(dir, `${file.id}.json`);
8446
- await writeFile7(path, JSON.stringify(file, null, 2), "utf8");
8684
+ const path = join15(dir, `${file.id}.json`);
8685
+ await writeFile8(path, JSON.stringify(file, null, 2), "utf8");
8447
8686
  return path;
8448
8687
  }
8449
8688
  async function pruneSessions() {
@@ -8462,9 +8701,9 @@ async function listSessions(limit = 30, cwd) {
8462
8701
  const summaries = [];
8463
8702
  for (const name of entries) {
8464
8703
  if (!name.endsWith(".json")) continue;
8465
- const path = join13(dir, name);
8704
+ const path = join15(dir, name);
8466
8705
  try {
8467
- const [s, raw] = await Promise.all([stat4(path), readFile11(path, "utf8")]);
8706
+ const [s, raw] = await Promise.all([stat4(path), readFile12(path, "utf8")]);
8468
8707
  const parsed = JSON.parse(raw);
8469
8708
  if (cwd && parsed.cwd !== cwd) continue;
8470
8709
  const firstUser = parsed.messages.find((m) => m.role === "user");
@@ -8484,7 +8723,7 @@ async function listSessions(limit = 30, cwd) {
8484
8723
  return summaries.slice(0, limit);
8485
8724
  }
8486
8725
  async function loadSession(filePath) {
8487
- const raw = await readFile11(filePath, "utf8");
8726
+ const raw = await readFile12(filePath, "utf8");
8488
8727
  return JSON.parse(raw);
8489
8728
  }
8490
8729
  var init_sessions = __esm({
@@ -8495,10 +8734,10 @@ var init_sessions = __esm({
8495
8734
  });
8496
8735
 
8497
8736
  // src/util/image.ts
8498
- import { readFile as readFile12 } from "fs/promises";
8737
+ import { readFile as readFile13 } from "fs/promises";
8499
8738
  import { basename as basename3 } from "path";
8500
8739
  async function encodeImageFile(filePath) {
8501
- const buf = await readFile12(filePath);
8740
+ const buf = await readFile13(filePath);
8502
8741
  if (buf.byteLength > MAX_IMAGE_BYTES) {
8503
8742
  throw new Error(
8504
8743
  `image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
@@ -8534,15 +8773,15 @@ var init_image = __esm({
8534
8773
  });
8535
8774
 
8536
8775
  // src/usage-tracker.ts
8537
- import { readFile as readFile13, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
8538
- import { homedir as homedir10 } from "os";
8539
- import { join as join14 } from "path";
8776
+ import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir8 } from "fs/promises";
8777
+ import { homedir as homedir11 } from "os";
8778
+ import { join as join16 } from "path";
8540
8779
  function usageDir2() {
8541
- const xdg = process.env.XDG_DATA_HOME || join14(homedir10(), ".local", "share");
8542
- return join14(xdg, "kimiflare");
8780
+ const xdg = process.env.XDG_DATA_HOME || join16(homedir11(), ".local", "share");
8781
+ return join16(xdg, "kimiflare");
8543
8782
  }
8544
8783
  function usagePath2() {
8545
- return join14(usageDir2(), "usage.json");
8784
+ return join16(usageDir2(), "usage.json");
8546
8785
  }
8547
8786
  function today2() {
8548
8787
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -8553,7 +8792,7 @@ function cutoffDate(daysBack) {
8553
8792
  }
8554
8793
  async function loadLog2() {
8555
8794
  try {
8556
- const raw = await readFile13(usagePath2(), "utf8");
8795
+ const raw = await readFile14(usagePath2(), "utf8");
8557
8796
  const parsed = JSON.parse(raw);
8558
8797
  if (parsed.version === LOG_VERSION2) return parsed;
8559
8798
  } catch {
@@ -8562,7 +8801,7 @@ async function loadLog2() {
8562
8801
  }
8563
8802
  async function saveLog(log) {
8564
8803
  await mkdir8(usageDir2(), { recursive: true });
8565
- await writeFile8(usagePath2(), JSON.stringify(log, null, 2), "utf8");
8804
+ await writeFile9(usagePath2(), JSON.stringify(log, null, 2), "utf8");
8566
8805
  }
8567
8806
  function getOrCreateDay(log, date) {
8568
8807
  let day = log.days.find((d) => d.date === date);
@@ -8768,7 +9007,7 @@ __export(db_exports, {
8768
9007
  updateMemoryEmbedding: () => updateMemoryEmbedding
8769
9008
  });
8770
9009
  import Database from "better-sqlite3";
8771
- import { dirname as dirname6 } from "path";
9010
+ import { dirname as dirname7 } from "path";
8772
9011
  import { mkdirSync, statSync as statSync2 } from "fs";
8773
9012
  function initSchema(db) {
8774
9013
  db.exec(`
@@ -8853,7 +9092,7 @@ function openMemoryDb(dbPath) {
8853
9092
  if (dbInstance) {
8854
9093
  dbInstance.close();
8855
9094
  }
8856
- mkdirSync(dirname6(dbPath), { recursive: true });
9095
+ mkdirSync(dirname7(dbPath), { recursive: true });
8857
9096
  dbInstance = new Database(dbPath);
8858
9097
  dbInstance.pragma("journal_mode = WAL");
8859
9098
  dbInstance.pragma("foreign_keys = ON");
@@ -9792,16 +10031,16 @@ Context: This memory was explicitly provided by the user during a conversation.`
9792
10031
  });
9793
10032
 
9794
10033
  // src/util/state.ts
9795
- import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir9 } from "fs/promises";
9796
- import { homedir as homedir11 } from "os";
9797
- import { join as join16 } from "path";
10034
+ import { readFile as readFile15, writeFile as writeFile10, mkdir as mkdir9 } from "fs/promises";
10035
+ import { homedir as homedir12 } from "os";
10036
+ import { join as join18 } from "path";
9798
10037
  function statePath() {
9799
- const xdg = process.env.XDG_CONFIG_HOME || join16(homedir11(), ".config");
9800
- return join16(xdg, "kimiflare", "state.json");
10038
+ const xdg = process.env.XDG_CONFIG_HOME || join18(homedir12(), ".config");
10039
+ return join18(xdg, "kimiflare", "state.json");
9801
10040
  }
9802
10041
  async function readState() {
9803
10042
  try {
9804
- const raw = await readFile14(statePath(), "utf8");
10043
+ const raw = await readFile15(statePath(), "utf8");
9805
10044
  return JSON.parse(raw);
9806
10045
  } catch {
9807
10046
  return {};
@@ -9809,8 +10048,8 @@ async function readState() {
9809
10048
  }
9810
10049
  async function writeState(state) {
9811
10050
  const path = statePath();
9812
- await mkdir9(join16(path, ".."), { recursive: true });
9813
- await writeFile9(path, JSON.stringify(state, null, 2) + "\n", "utf8");
10051
+ await mkdir9(join18(path, ".."), { recursive: true });
10052
+ await writeFile10(path, JSON.stringify(state, null, 2) + "\n", "utf8");
9814
10053
  }
9815
10054
  async function markCreatorMessageSeen(version) {
9816
10055
  const state = await readState();
@@ -9883,15 +10122,15 @@ var init_frontmatter = __esm({
9883
10122
 
9884
10123
  // src/commands/loader.ts
9885
10124
  import { open, realpath } from "fs/promises";
9886
- import { homedir as homedir12 } from "os";
9887
- import { join as join17, relative as relative4, sep as sep2 } from "path";
10125
+ import { homedir as homedir13 } from "os";
10126
+ import { join as join19, relative as relative4, sep as sep2 } from "path";
9888
10127
  import fg3 from "fast-glob";
9889
10128
  function projectCommandsDir(cwd = process.cwd()) {
9890
- return join17(cwd, ".kimiflare", "commands");
10129
+ return join19(cwd, ".kimiflare", "commands");
9891
10130
  }
9892
10131
  function globalCommandsDir() {
9893
- const xdg = process.env.XDG_CONFIG_HOME || join17(homedir12(), ".config");
9894
- return join17(xdg, "kimiflare", "commands");
10132
+ const xdg = process.env.XDG_CONFIG_HOME || join19(homedir13(), ".config");
10133
+ return join19(xdg, "kimiflare", "commands");
9895
10134
  }
9896
10135
  async function loadCustomCommands(cwd = process.cwd()) {
9897
10136
  const warnings = [];
@@ -10267,8 +10506,8 @@ var init_builtins = __esm({
10267
10506
  });
10268
10507
 
10269
10508
  // src/commands/save.ts
10270
- import { mkdir as mkdir10, writeFile as writeFile10, unlink as unlink2 } from "fs/promises";
10271
- import { dirname as dirname7 } from "path";
10509
+ import { mkdir as mkdir10, writeFile as writeFile11, unlink as unlink2 } from "fs/promises";
10510
+ import { dirname as dirname8 } from "path";
10272
10511
  async function saveCustomCommand(opts2) {
10273
10512
  const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
10274
10513
  const filepath = `${dir}/${opts2.name}.md`;
@@ -10279,8 +10518,8 @@ async function saveCustomCommand(opts2) {
10279
10518
  if (opts2.effort) data.effort = opts2.effort;
10280
10519
  const frontmatter = serializeFrontmatter(data);
10281
10520
  const content = frontmatter + opts2.template;
10282
- await mkdir10(dirname7(filepath), { recursive: true });
10283
- await writeFile10(filepath, content, "utf8");
10521
+ await mkdir10(dirname8(filepath), { recursive: true });
10522
+ await writeFile11(filepath, content, "utf8");
10284
10523
  return { filepath };
10285
10524
  }
10286
10525
  async function deleteCustomCommand(cmd) {
@@ -10297,7 +10536,7 @@ var init_save = __esm({
10297
10536
  // src/ui/command-wizard.tsx
10298
10537
  import { useState as useState8 } from "react";
10299
10538
  import { Box as Box13, Text as Text14, useInput as useInput4, useWindowSize as useWindowSize2 } from "ink";
10300
- import SelectInput5 from "ink-select-input";
10539
+ import SelectInput6 from "ink-select-input";
10301
10540
  import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
10302
10541
  function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
10303
10542
  const theme = useTheme();
@@ -10550,7 +10789,7 @@ ${template}`;
10550
10789
  ")"
10551
10790
  ] }),
10552
10791
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10553
- SelectInput5,
10792
+ SelectInput6,
10554
10793
  {
10555
10794
  items,
10556
10795
  onSelect: (item) => {
@@ -10579,7 +10818,7 @@ ${template}`;
10579
10818
  ] }),
10580
10819
  /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
10581
10820
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10582
- SelectInput5,
10821
+ SelectInput6,
10583
10822
  {
10584
10823
  items,
10585
10824
  onSelect: (item) => {
@@ -10607,7 +10846,7 @@ ${template}`;
10607
10846
  ")"
10608
10847
  ] }),
10609
10848
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10610
- SelectInput5,
10849
+ SelectInput6,
10611
10850
  {
10612
10851
  items,
10613
10852
  onSelect: (item) => {
@@ -10653,7 +10892,7 @@ ${template}`;
10653
10892
  ")"
10654
10893
  ] }),
10655
10894
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10656
- SelectInput5,
10895
+ SelectInput6,
10657
10896
  {
10658
10897
  items,
10659
10898
  onSelect: (item) => {
@@ -10686,7 +10925,7 @@ ${template}`;
10686
10925
  ] }),
10687
10926
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: line || " " }, i)) }),
10688
10927
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10689
- SelectInput5,
10928
+ SelectInput6,
10690
10929
  {
10691
10930
  items,
10692
10931
  onSelect: (item) => handleConfirm(item.value)
@@ -10710,7 +10949,7 @@ var init_command_wizard = __esm({
10710
10949
 
10711
10950
  // src/ui/command-picker.tsx
10712
10951
  import { Box as Box14, Text as Text15 } from "ink";
10713
- import SelectInput6 from "ink-select-input";
10952
+ import SelectInput7 from "ink-select-input";
10714
10953
  import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
10715
10954
  function CommandPicker({ commands, title, onPick }) {
10716
10955
  const theme = useTheme();
@@ -10724,7 +10963,7 @@ function CommandPicker({ commands, title, onPick }) {
10724
10963
  /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: title }),
10725
10964
  /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
10726
10965
  /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
10727
- SelectInput6,
10966
+ SelectInput7,
10728
10967
  {
10729
10968
  items,
10730
10969
  onSelect: (item) => {
@@ -10821,7 +11060,7 @@ var init_command_list = __esm({
10821
11060
  // src/ui/lsp-wizard.tsx
10822
11061
  import { useState as useState9 } from "react";
10823
11062
  import { Box as Box16, Text as Text17 } from "ink";
10824
- import SelectInput7 from "ink-select-input";
11063
+ import SelectInput8 from "ink-select-input";
10825
11064
  import { spawn as spawn3 } from "child_process";
10826
11065
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
10827
11066
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
@@ -10938,7 +11177,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10938
11177
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "LSP Servers" }),
10939
11178
  /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
10940
11179
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10941
- SelectInput7,
11180
+ SelectInput8,
10942
11181
  {
10943
11182
  items: mainItems,
10944
11183
  onSelect: (item) => {
@@ -10969,7 +11208,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10969
11208
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Add LSP Server" }),
10970
11209
  /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
10971
11210
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10972
- SelectInput7,
11211
+ SelectInput8,
10973
11212
  {
10974
11213
  items,
10975
11214
  onSelect: (item) => {
@@ -11008,7 +11247,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11008
11247
  ] }),
11009
11248
  installState.output && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx18(Text17, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
11010
11249
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11011
- SelectInput7,
11250
+ SelectInput8,
11012
11251
  {
11013
11252
  items,
11014
11253
  onSelect: (item) => {
@@ -11049,7 +11288,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11049
11288
  )
11050
11289
  ] }),
11051
11290
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11052
- SelectInput7,
11291
+ SelectInput8,
11053
11292
  {
11054
11293
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11055
11294
  onSelect: () => setPage("add")
@@ -11078,7 +11317,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11078
11317
  )
11079
11318
  ] }),
11080
11319
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11081
- SelectInput7,
11320
+ SelectInput8,
11082
11321
  {
11083
11322
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11084
11323
  onSelect: () => setPage("custom-name")
@@ -11105,7 +11344,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11105
11344
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Save LSP Config" }),
11106
11345
  /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
11107
11346
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11108
- SelectInput7,
11347
+ SelectInput8,
11109
11348
  {
11110
11349
  items,
11111
11350
  onSelect: (item) => {
@@ -11127,7 +11366,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11127
11366
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
11128
11367
  /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
11129
11368
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11130
- SelectInput7,
11369
+ SelectInput8,
11131
11370
  {
11132
11371
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11133
11372
  onSelect: () => setPage("main")
@@ -11151,7 +11390,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11151
11390
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
11152
11391
  /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
11153
11392
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11154
- SelectInput7,
11393
+ SelectInput8,
11155
11394
  {
11156
11395
  items,
11157
11396
  onSelect: (item) => {
@@ -11172,7 +11411,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11172
11411
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
11173
11412
  /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
11174
11413
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11175
- SelectInput7,
11414
+ SelectInput8,
11176
11415
  {
11177
11416
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11178
11417
  onSelect: () => setPage("main")
@@ -11192,7 +11431,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11192
11431
  /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
11193
11432
  /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
11194
11433
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11195
- SelectInput7,
11434
+ SelectInput8,
11196
11435
  {
11197
11436
  items,
11198
11437
  onSelect: (item) => {
@@ -11216,7 +11455,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
11216
11455
  return /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
11217
11456
  }) }),
11218
11457
  /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11219
- SelectInput7,
11458
+ SelectInput8,
11220
11459
  {
11221
11460
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
11222
11461
  onSelect: () => setPage("main")
@@ -11343,7 +11582,7 @@ var init_lsp_wizard = __esm({
11343
11582
 
11344
11583
  // src/ui/theme-picker.tsx
11345
11584
  import { Box as Box17, Text as Text18 } from "ink";
11346
- import SelectInput8 from "ink-select-input";
11585
+ import SelectInput9 from "ink-select-input";
11347
11586
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
11348
11587
  function PaletteSwatches({ palette }) {
11349
11588
  const colors = [
@@ -11363,7 +11602,7 @@ function ThemePicker({ themes, onPick, onPreview }) {
11363
11602
  return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
11364
11603
  /* @__PURE__ */ jsx19(Text18, { color: current.accent, bold: true, children: "Pick a theme" }),
11365
11604
  /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
11366
- SelectInput8,
11605
+ SelectInput9,
11367
11606
  {
11368
11607
  items,
11369
11608
  onHighlight: (item) => {
@@ -11701,15 +11940,15 @@ var tui_report_exports = {};
11701
11940
  __export(tui_report_exports, {
11702
11941
  getCategoryReportText: () => getCategoryReportText
11703
11942
  });
11704
- import { readFile as readFile15 } from "fs/promises";
11705
- import { join as join18 } from "path";
11706
- import { homedir as homedir13 } from "os";
11943
+ import { readFile as readFile16 } from "fs/promises";
11944
+ import { join as join20 } from "path";
11945
+ import { homedir as homedir14 } from "os";
11707
11946
  function usageDir3() {
11708
- const xdg = process.env.XDG_DATA_HOME || join18(homedir13(), ".local", "share");
11709
- return join18(xdg, "kimiflare");
11947
+ const xdg = process.env.XDG_DATA_HOME || join20(homedir14(), ".local", "share");
11948
+ return join20(xdg, "kimiflare");
11710
11949
  }
11711
11950
  function usagePath3() {
11712
- return join18(usageDir3(), "usage.json");
11951
+ return join20(usageDir3(), "usage.json");
11713
11952
  }
11714
11953
  function today3() {
11715
11954
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -11721,7 +11960,7 @@ function daysAgo2(n) {
11721
11960
  }
11722
11961
  async function loadLog3() {
11723
11962
  try {
11724
- const raw = await readFile15(usagePath3(), "utf8");
11963
+ const raw = await readFile16(usagePath3(), "utf8");
11725
11964
  return JSON.parse(raw);
11726
11965
  } catch {
11727
11966
  return { version: 1, days: [], sessions: [] };
@@ -11789,9 +12028,9 @@ __export(app_exports, {
11789
12028
  });
11790
12029
  import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect5, useCallback } from "react";
11791
12030
  import { Box as Box20, Text as Text21, useApp, useInput as useInput6, render } from "ink";
11792
- import SelectInput9 from "ink-select-input";
12031
+ import SelectInput10 from "ink-select-input";
11793
12032
  import { existsSync as existsSync2, statSync as statSync3 } from "fs";
11794
- import { join as join19 } from "path";
12033
+ import { join as join21 } from "path";
11795
12034
  import { unlink as unlink3 } from "fs/promises";
11796
12035
  import { execSync as execSync2 } from "child_process";
11797
12036
  import { spawn as spawn4 } from "child_process";
@@ -11869,7 +12108,7 @@ function buildFilePickerIgnoreList(cwd) {
11869
12108
  ];
11870
12109
  const gitignorePatterns = [];
11871
12110
  try {
11872
- const gitignorePath = join19(cwd, ".gitignore");
12111
+ const gitignorePath = join21(cwd, ".gitignore");
11873
12112
  const stats = statSync3(gitignorePath);
11874
12113
  if (stats.size > MAX_GITIGNORE_SIZE) {
11875
12114
  return hardcoded;
@@ -12022,7 +12261,8 @@ function App({
12022
12261
  initialCfg,
12023
12262
  initialUpdateResult,
12024
12263
  initialLspScope,
12025
- initialLspProjectPath
12264
+ initialLspProjectPath,
12265
+ initialCloudToken
12026
12266
  }) {
12027
12267
  const { exit } = useApp();
12028
12268
  const [cfg, setCfg] = useState10(initialCfg);
@@ -12286,7 +12526,7 @@ function App({
12286
12526
  }
12287
12527
  });
12288
12528
  if (cfg.memoryEnabled) {
12289
- const dbPath = cfg.memoryDbPath ?? join19(process.cwd(), ".kimiflare", "memory.db");
12529
+ const dbPath = cfg.memoryDbPath ?? join21(process.cwd(), ".kimiflare", "memory.db");
12290
12530
  const manager = new MemoryManager({
12291
12531
  dbPath,
12292
12532
  accountId: cfg.accountId,
@@ -12935,7 +13175,7 @@ function App({
12935
13175
  return;
12936
13176
  }
12937
13177
  const cwd = process.cwd();
12938
- const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(join19(cwd, n)));
13178
+ const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(join21(cwd, n)));
12939
13179
  const isRefresh = existingName !== void 0;
12940
13180
  const promptParts = [
12941
13181
  isRefresh ? `Regenerate ${existingName} at the repository root to refresh project context. If the file already exists, read it first and preserve anything still accurate, updating only what has changed.` : "Generate a KIMI.md at the repository root so future agents have project context.",
@@ -12986,13 +13226,15 @@ function App({
12986
13226
  sessionId: ensureSessionId(),
12987
13227
  memoryManager: memoryManagerRef.current,
12988
13228
  codeMode: effectiveCodeMode,
13229
+ cloudMode: cfg.cloudMode,
13230
+ cloudToken: initialCloudToken,
12989
13231
  onIterationEnd,
12990
13232
  onFileChange: (path, content) => {
12991
13233
  if (content) {
12992
13234
  lspManagerRef.current.notifyChange(path, content);
12993
13235
  } else {
12994
13236
  void import("fs/promises").then(
12995
- ({ readFile: readFile16 }) => readFile16(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
13237
+ ({ readFile: readFile17 }) => readFile17(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
12996
13238
  })
12997
13239
  );
12998
13240
  }
@@ -13086,7 +13328,7 @@ function App({
13086
13328
  })
13087
13329
  }
13088
13330
  });
13089
- if (existsSync2(join19(cwd, "KIMI.md"))) {
13331
+ if (existsSync2(join21(cwd, "KIMI.md"))) {
13090
13332
  if (cacheStableRef.current) {
13091
13333
  messagesRef.current[1] = {
13092
13334
  role: "system",
@@ -13315,6 +13557,10 @@ function App({
13315
13557
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "no config loaded" }]);
13316
13558
  return true;
13317
13559
  }
13560
+ if (cfg.cloudMode) {
13561
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "AI Gateway is managed by Kimiflare Cloud" }]);
13562
+ return true;
13563
+ }
13318
13564
  const sub = rest[0]?.toLowerCase() ?? "";
13319
13565
  const subArg = rest.slice(1).join(" ").trim();
13320
13566
  if (!sub || sub === "status") {
@@ -14185,6 +14431,8 @@ ${lines.join("\n")}` }]);
14185
14431
  memoryManager: memoryManagerRef.current,
14186
14432
  keepLastImageTurns: cfg.imageHistoryTurns ?? 2,
14187
14433
  codeMode: effectiveCodeMode,
14434
+ cloudMode: cfg.cloudMode,
14435
+ cloudToken: initialCloudToken,
14188
14436
  onIterationEnd,
14189
14437
  intentClassification: classification,
14190
14438
  onFileChange: (path, content2) => {
@@ -14192,7 +14440,7 @@ ${lines.join("\n")}` }]);
14192
14440
  lspManagerRef.current.notifyChange(path, content2);
14193
14441
  } else {
14194
14442
  void import("fs/promises").then(
14195
- ({ readFile: readFile16 }) => readFile16(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
14443
+ ({ readFile: readFile17 }) => readFile17(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
14196
14444
  })
14197
14445
  );
14198
14446
  }
@@ -14373,12 +14621,28 @@ ${lines.join("\n")}` }]);
14373
14621
  return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(
14374
14622
  Onboarding,
14375
14623
  {
14376
- onDone: (newCfg) => {
14624
+ onDone: async (newCfg) => {
14377
14625
  setCfg(newCfg);
14378
- setEvents((e) => [
14379
- ...e,
14380
- { kind: "info", key: mkKey(), text: "configuration saved \u2014 welcome to kimiflare!" }
14381
- ]);
14626
+ if (newCfg.cloudMode) {
14627
+ const { loadCloudCredentials: loadCloudCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
14628
+ const creds = await loadCloudCredentials2();
14629
+ if (creds) {
14630
+ setEvents((e) => [
14631
+ ...e,
14632
+ { kind: "info", key: mkKey(), text: "configuration saved \u2014 welcome to kimiflare! (cloud mode)" }
14633
+ ]);
14634
+ } else {
14635
+ setEvents((e) => [
14636
+ ...e,
14637
+ { kind: "info", key: mkKey(), text: "cloud mode configured \u2014 run `kimiflare auth cloud` to sign in" }
14638
+ ]);
14639
+ }
14640
+ } else {
14641
+ setEvents((e) => [
14642
+ ...e,
14643
+ { kind: "info", key: mkKey(), text: "configuration saved \u2014 welcome to kimiflare!" }
14644
+ ]);
14645
+ }
14382
14646
  }
14383
14647
  }
14384
14648
  ) });
@@ -14424,6 +14688,7 @@ ${lines.join("\n")}` }]);
14424
14688
  {
14425
14689
  customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
14426
14690
  costAttributionEnabled: cfg?.costAttribution,
14691
+ cloudMode: cfg?.cloudMode,
14427
14692
  onDone: () => setShowHelpMenu(false),
14428
14693
  onCommand: handleHelpCommand
14429
14694
  }
@@ -14435,7 +14700,7 @@ ${lines.join("\n")}` }]);
14435
14700
  {
14436
14701
  servers: cfg?.lspServers ?? {},
14437
14702
  currentScope: lspScope,
14438
- hasProjectDir: existsSync2(join19(process.cwd(), ".kimiflare")),
14703
+ hasProjectDir: existsSync2(join21(process.cwd(), ".kimiflare")),
14439
14704
  onDone: () => setShowLspWizard(false),
14440
14705
  onSave: (servers, enabled, scope) => {
14441
14706
  setCfg((c) => c ? { ...c, lspEnabled: enabled, lspServers: servers } : c);
@@ -14506,7 +14771,7 @@ ${lines.join("\n")}` }]);
14506
14771
  ] }),
14507
14772
  /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: commandToDelete.filepath }),
14508
14773
  /* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(
14509
- SelectInput9,
14774
+ SelectInput10,
14510
14775
  {
14511
14776
  items: [
14512
14777
  { label: "Yes, delete", value: "yes", key: "yes" },
@@ -14576,7 +14841,8 @@ ${lines.join("\n")}` }]);
14576
14841
  hasUpdate,
14577
14842
  latestVersion,
14578
14843
  gatewayMeta,
14579
- codeMode
14844
+ codeMode,
14845
+ cloudMode: cfg.cloudMode
14580
14846
  }
14581
14847
  ),
14582
14848
  activePicker?.kind === "file" && /* @__PURE__ */ jsx22(
@@ -14652,7 +14918,7 @@ ${lines.join("\n")}` }]);
14652
14918
  ] })
14653
14919
  ] }) });
14654
14920
  }
14655
- async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null) {
14921
+ async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null, cloudToken) {
14656
14922
  const instance = render(
14657
14923
  /* @__PURE__ */ jsx22(
14658
14924
  App,
@@ -14660,7 +14926,8 @@ async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath
14660
14926
  initialCfg: cfg,
14661
14927
  initialUpdateResult: updateResult,
14662
14928
  initialLspScope: lspScope,
14663
- initialLspProjectPath: lspProjectPath
14929
+ initialLspProjectPath: lspProjectPath,
14930
+ initialCloudToken: cloudToken
14664
14931
  }
14665
14932
  ),
14666
14933
  {
@@ -14851,7 +15118,7 @@ function createRemoteCommand() {
14851
15118
 
14852
15119
  // src/index.tsx
14853
15120
  var program = new Command2();
14854
- program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).option("-p, --print <prompt>", "one-shot mode: send prompt, stream reply to stdout, exit").option("-m, --model <id>", "model id (defaults to @cf/moonshotai/kimi-k2.6)").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").option("--continue-on-limit", "reset tool-call counter and continue when the 50-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10));
15121
+ program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).option("-p, --print <prompt>", "one-shot mode: send prompt, stream reply to stdout, exit").option("-m, --model <id>", "model id (defaults to @cf/moonshotai/kimi-k2.6)").option("--cloud", "use Kimiflare Cloud (api.kimiflare.com) instead of direct Workers AI").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").option("--continue-on-limit", "reset tool-call counter and continue when the 50-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10));
14855
15122
  program.command("cost").description("Show cost attribution by task type (requires costAttribution enabled)").option("-w, --week", "last 7 days (default)").option("-m, --month", "last 30 days").option("-d, --day", "today only").option("-s, --session <id>", "single session detail").option("-c, --category <name>", "filter by category").option("--json", "machine-readable output").option("--reclassify", "re-run classification on all sessions").option("--local-only", "skip Cloudflare reconciliation").action(async (cmdOpts) => {
14856
15123
  const cfg = await loadConfig();
14857
15124
  const enabled = cfg?.costAttribution ?? false;
@@ -14864,6 +15131,25 @@ program.command("cost").description("Show cost attribution by task type (require
14864
15131
  const { runCostCommand: runCostCommand2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
14865
15132
  await runCostCommand2({ ...cmdOpts, config: cfg });
14866
15133
  });
15134
+ program.command("usage").description("Show Kimiflare Cloud token usage (requires cloud authentication)").action(async () => {
15135
+ const { loadCloudCredentials: loadCloudCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
15136
+ const creds = await loadCloudCredentials2();
15137
+ if (!creds) {
15138
+ console.error("Not authenticated with Kimiflare Cloud. Run: kimiflare auth cloud");
15139
+ process.exit(1);
15140
+ }
15141
+ const res = await fetch("https://api.kimiflare.com/v1/usage", {
15142
+ headers: { Authorization: `Bearer ${creds.accessToken}` }
15143
+ });
15144
+ if (!res.ok) {
15145
+ console.error(`Failed to fetch usage: ${res.status} ${res.statusText}`);
15146
+ process.exit(1);
15147
+ }
15148
+ const usage = await res.json();
15149
+ console.log(`Token budget: ${usage.remaining.toLocaleString()} / ${usage.input_token_limit.toLocaleString()} remaining`);
15150
+ console.log(`Used: ${usage.input_tokens_used.toLocaleString()}`);
15151
+ console.log(`Grant expires: ${usage.expires_at}`);
15152
+ });
14867
15153
  program.addCommand(createRemoteCommand());
14868
15154
  program.command("auth").description("Authenticate with external services").addCommand(
14869
15155
  new Command2("github").description("Authenticate with GitHub via OAuth device flow").action(async () => {
@@ -14880,6 +15166,37 @@ Open: ${step.url}`);
14880
15166
  if (step.error) process.exit(1);
14881
15167
  }
14882
15168
  })
15169
+ ).addCommand(
15170
+ new Command2("cloud").description("Authenticate with Kimiflare Cloud").action(async () => {
15171
+ const { authenticateDevice: authenticateDevice2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
15172
+ try {
15173
+ const creds = await authenticateDevice2(({ url, userCode, polling }) => {
15174
+ if (!polling) {
15175
+ console.log(`
15176
+ Kimiflare Cloud Authentication`);
15177
+ console.log(`
15178
+ 1. Open this URL in your browser:`);
15179
+ console.log(` ${url}`);
15180
+ console.log(`
15181
+ 2. Sign in with GitHub
15182
+ `);
15183
+ }
15184
+ });
15185
+ console.log(`Authenticated! Token expires at ${new Date(creds.expiresAt * 1e3).toISOString()}`);
15186
+ const usageRes = await fetch("https://api.kimiflare.com/v1/usage", {
15187
+ headers: { Authorization: `Bearer ${creds.accessToken}` }
15188
+ });
15189
+ if (usageRes.ok) {
15190
+ const usage = await usageRes.json();
15191
+ console.log(`
15192
+ Token budget: ${usage.remaining.toLocaleString()} / ${usage.input_token_limit.toLocaleString()} remaining`);
15193
+ console.log(`Grant expires: ${usage.expires_at}`);
15194
+ }
15195
+ } catch (err) {
15196
+ console.error("Authentication failed:", err instanceof Error ? err.message : String(err));
15197
+ process.exit(1);
15198
+ }
15199
+ })
14883
15200
  );
14884
15201
  program.action(async () => {
14885
15202
  await main();
@@ -14902,10 +15219,25 @@ async function main() {
14902
15219
  lspScope = resolved.scope;
14903
15220
  lspProjectPath = resolved.projectPath;
14904
15221
  }
15222
+ const cloudMode = opts.cloud ?? cfg?.cloudMode ?? false;
15223
+ let cloudToken;
15224
+ if (cloudMode) {
15225
+ const { loadCloudCredentials: loadCloudCredentials2, authenticateDevice: authenticateDevice2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
15226
+ let cloudCreds = await loadCloudCredentials2();
15227
+ if (!cloudCreds) {
15228
+ console.error("kimiflare: cloud mode requires authentication.\nRun: kimiflare auth cloud\n");
15229
+ process.exit(2);
15230
+ }
15231
+ cloudToken = cloudCreds.accessToken;
15232
+ cfg = {
15233
+ ...cfg ?? { accountId: "", apiToken: "", model: DEFAULT_MODEL },
15234
+ cloudMode: true
15235
+ };
15236
+ }
14905
15237
  if (opts.print !== void 0) {
14906
15238
  if (!cfg) {
14907
15239
  console.error(
14908
- 'kimiflare: missing credentials.\nSet CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, or write them to\n ~/.config/kimiflare/config.json (chmod 600)\n { "accountId": "...", "apiToken": "...", "model": "@cf/moonshotai/kimi-k2.6" }'
15240
+ 'kimiflare: missing credentials.\nSet CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, or write them to\n ~/.config/kimiflare/config.json (chmod 600)\n { "accountId": "...", "apiToken": "...", "model": "@cf/moonshotai/kimi-k2.6" }\nOr use cloud mode: kimiflare --cloud -p "..."'
14909
15241
  );
14910
15242
  process.exit(2);
14911
15243
  }
@@ -14917,6 +15249,7 @@ async function main() {
14917
15249
  allowAll: !!opts.dangerouslyAllowAll,
14918
15250
  showReasoning: !!opts.reasoning,
14919
15251
  codeMode: cfg.codeMode,
15252
+ cloudToken,
14920
15253
  continueOnLimit: !!opts.continueOnLimit,
14921
15254
  maxInputTokens: opts.maxInputTokens,
14922
15255
  updateResult
@@ -14932,9 +15265,9 @@ async function main() {
14932
15265
  const { renderApp: renderApp2 } = await Promise.resolve().then(() => (init_app(), app_exports));
14933
15266
  if (cfg) {
14934
15267
  const model = opts.model ?? cfg.model ?? DEFAULT_MODEL;
14935
- await renderApp2({ ...cfg, model }, updateResult, lspScope, lspProjectPath);
15268
+ await renderApp2({ ...cfg, model }, updateResult, lspScope, lspProjectPath, cloudToken);
14936
15269
  } else {
14937
- await renderApp2(null, updateResult, lspScope, lspProjectPath);
15270
+ await renderApp2(null, updateResult, lspScope, lspProjectPath, cloudToken);
14938
15271
  }
14939
15272
  }
14940
15273
  function gatewayFromPrintOpts(opts2) {
@@ -14948,6 +15281,10 @@ function gatewayFromPrintOpts(opts2) {
14948
15281
  };
14949
15282
  }
14950
15283
  async function runPrintMode(opts2) {
15284
+ if (opts2.cloudMode) {
15285
+ process.stderr.write(`[cloud mode: api.kimiflare.com]
15286
+ `);
15287
+ }
14951
15288
  if (opts2.updateResult.hasUpdate) {
14952
15289
  process.stderr.write(
14953
15290
  `\x1B[33mkimiflare update available: ${opts2.updateResult.localVersion} \u2192 ${opts2.updateResult.latestVersion}\x1B[0m
@@ -14980,6 +15317,8 @@ async function runPrintMode(opts2) {
14980
15317
  codeMode: opts2.codeMode,
14981
15318
  continueOnLimit: opts2.continueOnLimit,
14982
15319
  maxInputTokens: opts2.maxInputTokens,
15320
+ cloudMode: opts2.cloudMode,
15321
+ cloudToken: opts2.cloudToken,
14983
15322
  coauthor: opts2.coauthor !== false ? { name: opts2.coauthorName || "kimiflare", email: opts2.coauthorEmail || "kimiflare@proton.me" } : void 0,
14984
15323
  callbacks: {
14985
15324
  onReasoningDelta: opts2.showReasoning ? (delta) => {