kimiflare 0.33.0 → 0.34.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
@@ -9,6 +9,15 @@ var __export = (target, all) => {
9
9
  };
10
10
 
11
11
  // src/config.ts
12
+ var config_exports = {};
13
+ __export(config_exports, {
14
+ DEFAULT_MODEL: () => DEFAULT_MODEL,
15
+ DEFAULT_REASONING_EFFORT: () => DEFAULT_REASONING_EFFORT,
16
+ EFFORTS: () => EFFORTS,
17
+ configPath: () => configPath,
18
+ loadConfig: () => loadConfig,
19
+ saveConfig: () => saveConfig
20
+ });
12
21
  import { readFile, mkdir, writeFile, chmod } from "fs/promises";
13
22
  import { homedir } from "os";
14
23
  import { join } from "path";
@@ -933,7 +942,10 @@ async function logTurnDebug(ctx) {
933
942
  toolSavingsPct: toolTotalRaw > 0 ? Math.round((toolTotalRaw - toolTotalReduced) / toolTotalRaw * 100) : 0,
934
943
  cacheDiagnostics,
935
944
  compaction: ctx.compaction,
936
- shadowStrip: ctx.shadowStrip
945
+ shadowStrip: ctx.shadowStrip,
946
+ durationMs: ctx.durationMs,
947
+ intentClassification: ctx.intentClassification,
948
+ codeMode: ctx.codeMode
937
949
  });
938
950
  }
939
951
  var LOG_VERSION;
@@ -1356,6 +1368,7 @@ var init_code_mode = __esm({
1356
1368
 
1357
1369
  // src/agent/loop.ts
1358
1370
  async function runAgentTurn(opts2) {
1371
+ const turnStart = performance.now();
1359
1372
  const max = opts2.maxToolIterations ?? 50;
1360
1373
  const codeMode = opts2.codeMode ?? false;
1361
1374
  let toolDefs;
@@ -1728,6 +1741,10 @@ ${sandboxResult.output}` : sandboxResult.output;
1728
1741
  if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
1729
1742
  }
1730
1743
  }
1744
+ if (opts2.onIterationEnd) {
1745
+ opts2.messages = await opts2.onIterationEnd(opts2.messages, opts2.signal);
1746
+ if (opts2.signal.aborted) throw new DOMException("aborted", "AbortError");
1747
+ }
1731
1748
  if (opts2.sessionId && lastUsage) {
1732
1749
  void logTurnDebug({
1733
1750
  sessionId: opts2.sessionId,
@@ -1736,7 +1753,10 @@ ${sandboxResult.output}` : sandboxResult.output;
1736
1753
  previousMessages,
1737
1754
  toolResults,
1738
1755
  usage: lastUsage,
1739
- shadowStrip: shadowStripMetrics
1756
+ shadowStrip: shadowStripMetrics,
1757
+ durationMs: Math.round(performance.now() - turnStart),
1758
+ intentClassification: opts2.intentClassification,
1759
+ codeMode: opts2.codeMode
1740
1760
  });
1741
1761
  }
1742
1762
  if (budgetExhausted) {
@@ -3531,6 +3551,229 @@ var init_update_check = __esm({
3531
3551
  }
3532
3552
  });
3533
3553
 
3554
+ // src/remote/session-store.ts
3555
+ import { readFile as readFile8, writeFile as writeFile6, mkdir as mkdir6, readdir as readdir2 } from "fs/promises";
3556
+ import { homedir as homedir6 } from "os";
3557
+ import { join as join9 } from "path";
3558
+ function remoteDir() {
3559
+ const xdg = process.env.XDG_DATA_HOME || join9(homedir6(), ".config");
3560
+ return join9(xdg, "kimiflare", "remote");
3561
+ }
3562
+ async function saveRemoteSession(session) {
3563
+ const dir = remoteDir();
3564
+ await mkdir6(dir, { recursive: true });
3565
+ const path = join9(dir, `${session.sessionId}.json`);
3566
+ await writeFile6(path, JSON.stringify(session, null, 2) + "\n", "utf8");
3567
+ }
3568
+ async function loadRemoteSession(sessionId) {
3569
+ try {
3570
+ const path = join9(remoteDir(), `${sessionId}.json`);
3571
+ const raw = await readFile8(path, "utf8");
3572
+ return JSON.parse(raw);
3573
+ } catch {
3574
+ return null;
3575
+ }
3576
+ }
3577
+ async function listRemoteSessions() {
3578
+ const dir = remoteDir();
3579
+ try {
3580
+ const files = await readdir2(dir);
3581
+ const sessions = [];
3582
+ for (const file of files) {
3583
+ if (!file.endsWith(".json")) continue;
3584
+ try {
3585
+ const raw = await readFile8(join9(dir, file), "utf8");
3586
+ sessions.push(JSON.parse(raw));
3587
+ } catch {
3588
+ }
3589
+ }
3590
+ return sessions.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
3591
+ } catch {
3592
+ return [];
3593
+ }
3594
+ }
3595
+ async function getMostRecentRemoteSession() {
3596
+ const sessions = await listRemoteSessions();
3597
+ return sessions[0] ?? null;
3598
+ }
3599
+ var init_session_store = __esm({
3600
+ "src/remote/session-store.ts"() {
3601
+ "use strict";
3602
+ }
3603
+ });
3604
+
3605
+ // src/remote/deploy.ts
3606
+ import { execSync } from "child_process";
3607
+ import { join as join10, dirname as dirname5 } from "path";
3608
+ import { fileURLToPath as fileURLToPath3 } from "url";
3609
+ import { randomBytes } from "crypto";
3610
+ function generateSecret() {
3611
+ return randomBytes(32).toString("hex");
3612
+ }
3613
+ function runCapture(cmd, cwd) {
3614
+ return execSync(cmd, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
3615
+ }
3616
+ async function* deployForTui() {
3617
+ yield { message: "Checking prerequisites..." };
3618
+ try {
3619
+ runCapture("wrangler --version");
3620
+ } catch {
3621
+ yield { message: "wrangler not found. Install: npm install -g wrangler", error: true };
3622
+ yield { message: "Then run: wrangler login", error: true };
3623
+ throw new Error("wrangler not installed");
3624
+ }
3625
+ yield { message: "wrangler OK" };
3626
+ try {
3627
+ runCapture("wrangler whoami");
3628
+ } catch {
3629
+ yield { message: "wrangler not authenticated. Run: wrangler login", error: true };
3630
+ throw new Error("wrangler not authenticated");
3631
+ }
3632
+ yield { message: "wrangler authenticated" };
3633
+ try {
3634
+ runCapture("docker --version");
3635
+ } catch {
3636
+ yield { message: "Docker not found. Install: https://docs.docker.com/get-docker/", error: true };
3637
+ throw new Error("docker not installed");
3638
+ }
3639
+ yield { message: "Docker OK" };
3640
+ yield { message: "Building remote agent bundle..." };
3641
+ try {
3642
+ runCapture("npm run build:remote-agent", join10(REMOTE_DIR, ".."));
3643
+ yield { message: "Agent bundle built" };
3644
+ } catch (err) {
3645
+ yield { message: `Build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
3646
+ throw err;
3647
+ }
3648
+ yield { message: "Deploying Worker to Cloudflare..." };
3649
+ try {
3650
+ runCapture("wrangler deploy", WORKER_DIR);
3651
+ yield { message: "Worker deployed" };
3652
+ } catch (err) {
3653
+ yield { message: `Deploy failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
3654
+ throw err;
3655
+ }
3656
+ let workerUrl;
3657
+ try {
3658
+ const info = runCapture("wrangler info", WORKER_DIR);
3659
+ const match = info.match(/https:\/\/[^\s]+\.workers\.dev/);
3660
+ if (match) workerUrl = match[0];
3661
+ } catch {
3662
+ }
3663
+ if (!workerUrl) {
3664
+ yield { message: "Could not auto-detect Worker URL", error: true };
3665
+ throw new Error("Worker URL not found");
3666
+ }
3667
+ yield { message: `Worker URL: ${workerUrl}` };
3668
+ const authSecret = generateSecret();
3669
+ const cfg = await loadConfig();
3670
+ const cfToken = process.env.CF_API_TOKEN ?? cfg?.apiToken;
3671
+ if (!cfToken) {
3672
+ yield { message: "CF_API_TOKEN not found. Set CF_API_TOKEN env var or apiToken in config", error: true };
3673
+ throw new Error("CF_API_TOKEN missing");
3674
+ }
3675
+ yield { message: "Setting Worker secrets..." };
3676
+ try {
3677
+ execSync(`wrangler secret put REMOTE_AUTH_SECRET`, {
3678
+ cwd: WORKER_DIR,
3679
+ input: authSecret,
3680
+ stdio: ["pipe", "pipe", "pipe"]
3681
+ });
3682
+ execSync(`wrangler secret put CF_API_TOKEN`, {
3683
+ cwd: WORKER_DIR,
3684
+ input: cfToken,
3685
+ stdio: ["pipe", "pipe", "pipe"]
3686
+ });
3687
+ yield { message: "Secrets set" };
3688
+ } catch (err) {
3689
+ yield { message: `Secret setup failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
3690
+ throw err;
3691
+ }
3692
+ const imageTag = "ghcr.io/sinameraji/kimiflare-remote-agent:latest";
3693
+ yield { message: "Building container image..." };
3694
+ try {
3695
+ runCapture(`docker build -t ${imageTag} .`, REMOTE_DIR);
3696
+ yield { message: "Image built" };
3697
+ } catch (err) {
3698
+ yield { message: `Image build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
3699
+ throw err;
3700
+ }
3701
+ yield { message: `Pushing ${imageTag}...` };
3702
+ try {
3703
+ runCapture(`docker push ${imageTag}`, REMOTE_DIR);
3704
+ yield { message: "Image pushed" };
3705
+ } catch (err) {
3706
+ yield { message: `Push failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
3707
+ yield { message: "Make sure you're logged into ghcr.io: docker login ghcr.io -u USERNAME -p GITHUB_TOKEN", error: true };
3708
+ throw err;
3709
+ }
3710
+ const nextCfg = {
3711
+ ...cfg ?? { accountId: "", apiToken: "", model: "@cf/moonshotai/kimi-k2.6" },
3712
+ remoteWorkerUrl: workerUrl,
3713
+ remoteAuthSecret: authSecret
3714
+ };
3715
+ await saveConfig(nextCfg);
3716
+ yield { message: "Config saved" };
3717
+ yield { message: "Remote infrastructure ready!", done: true };
3718
+ return { workerUrl, authSecret };
3719
+ }
3720
+ async function runDeploy() {
3721
+ console.log("kimiflare remote deploy\n");
3722
+ try {
3723
+ for await (const step of deployForTui()) {
3724
+ console.log(step.message);
3725
+ if (step.done) break;
3726
+ if (step.error) process.exit(1);
3727
+ }
3728
+ console.log("\nDeploy complete!");
3729
+ } catch (err) {
3730
+ console.error(`Deploy failed: ${err instanceof Error ? err.message : String(err)}`);
3731
+ process.exit(1);
3732
+ }
3733
+ }
3734
+ async function checkDeployStatus() {
3735
+ let wrangler = false;
3736
+ let wranglerAuth = false;
3737
+ let docker = false;
3738
+ let workerUrl;
3739
+ try {
3740
+ execSync("wrangler --version", { stdio: "pipe" });
3741
+ wrangler = true;
3742
+ } catch {
3743
+ }
3744
+ if (wrangler) {
3745
+ try {
3746
+ execSync("wrangler whoami", { stdio: "pipe" });
3747
+ wranglerAuth = true;
3748
+ } catch {
3749
+ }
3750
+ }
3751
+ try {
3752
+ execSync("docker --version", { stdio: "pipe" });
3753
+ docker = true;
3754
+ } catch {
3755
+ }
3756
+ const cfg = await loadConfig();
3757
+ if (cfg?.remoteWorkerUrl) {
3758
+ try {
3759
+ const res = await fetch(`${cfg.remoteWorkerUrl}/health`, { signal: AbortSignal.timeout(5e3) });
3760
+ if (res.ok) workerUrl = cfg.remoteWorkerUrl;
3761
+ } catch {
3762
+ }
3763
+ }
3764
+ return { wrangler, wranglerAuth, docker, workerUrl };
3765
+ }
3766
+ var __dirname, REMOTE_DIR, WORKER_DIR;
3767
+ var init_deploy = __esm({
3768
+ "src/remote/deploy.ts"() {
3769
+ "use strict";
3770
+ init_config();
3771
+ __dirname = dirname5(fileURLToPath3(import.meta.url));
3772
+ REMOTE_DIR = join10(__dirname, "..", "..", "..", "remote");
3773
+ WORKER_DIR = join10(REMOTE_DIR, "worker");
3774
+ }
3775
+ });
3776
+
3534
3777
  // src/cost-attribution/types.ts
3535
3778
  var ALL_CATEGORIES;
3536
3779
  var init_types = __esm({
@@ -3950,12 +4193,12 @@ var init_heuristic = __esm({
3950
4193
  });
3951
4194
 
3952
4195
  // src/cost-attribution/classify-from-session.ts
3953
- import { readFile as readFile8 } from "fs/promises";
3954
- import { join as join9 } from "path";
3955
- import { homedir as homedir6 } from "os";
4196
+ import { readFile as readFile9 } from "fs/promises";
4197
+ import { join as join11 } from "path";
4198
+ import { homedir as homedir7 } from "os";
3956
4199
  function sessionsDir() {
3957
- const xdg = process.env.XDG_DATA_HOME || join9(homedir6(), ".local", "share");
3958
- return join9(xdg, "kimiflare", "sessions");
4200
+ const xdg = process.env.XDG_DATA_HOME || join11(homedir7(), ".local", "share");
4201
+ return join11(xdg, "kimiflare", "sessions");
3959
4202
  }
3960
4203
  function parseToolCalls(calls) {
3961
4204
  return calls.map((c) => {
@@ -3969,7 +4212,7 @@ function parseToolCalls(calls) {
3969
4212
  }
3970
4213
  async function classifyFromSessionFile(sessionId) {
3971
4214
  try {
3972
- const raw = await readFile8(join9(sessionsDir(), `${sessionId}.json`), "utf8");
4215
+ const raw = await readFile9(join11(sessionsDir(), `${sessionId}.json`), "utf8");
3973
4216
  const session = JSON.parse(raw);
3974
4217
  const messages = session.messages ?? [];
3975
4218
  const turns = [];
@@ -4002,15 +4245,15 @@ var cli_exports = {};
4002
4245
  __export(cli_exports, {
4003
4246
  runCostCommand: () => runCostCommand
4004
4247
  });
4005
- import { readFile as readFile9 } from "fs/promises";
4006
- import { join as join10 } from "path";
4007
- import { homedir as homedir7 } from "os";
4248
+ import { readFile as readFile10 } from "fs/promises";
4249
+ import { join as join12 } from "path";
4250
+ import { homedir as homedir8 } from "os";
4008
4251
  function usageDir() {
4009
- const xdg = process.env.XDG_DATA_HOME || join10(homedir7(), ".local", "share");
4010
- return join10(xdg, "kimiflare");
4252
+ const xdg = process.env.XDG_DATA_HOME || join12(homedir8(), ".local", "share");
4253
+ return join12(xdg, "kimiflare");
4011
4254
  }
4012
4255
  function usagePath() {
4013
- return join10(usageDir(), "usage.json");
4256
+ return join12(usageDir(), "usage.json");
4014
4257
  }
4015
4258
  function today() {
4016
4259
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -4022,7 +4265,7 @@ function daysAgo(n) {
4022
4265
  }
4023
4266
  async function loadLog() {
4024
4267
  try {
4025
- const raw = await readFile9(usagePath(), "utf8");
4268
+ const raw = await readFile10(usagePath(), "utf8");
4026
4269
  return JSON.parse(raw);
4027
4270
  } catch {
4028
4271
  return { version: 1, days: [], sessions: [] };
@@ -4108,6 +4351,94 @@ var init_cli = __esm({
4108
4351
  }
4109
4352
  });
4110
4353
 
4354
+ // src/remote/tui-auth.ts
4355
+ var tui_auth_exports = {};
4356
+ __export(tui_auth_exports, {
4357
+ authGitHubForTui: () => authGitHubForTui
4358
+ });
4359
+ function sleep2(ms) {
4360
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
4361
+ }
4362
+ async function* authGitHubForTui() {
4363
+ yield { message: "Starting GitHub OAuth device flow..." };
4364
+ const deviceRes = await fetch(GITHUB_DEVICE_AUTH_URL, {
4365
+ method: "POST",
4366
+ headers: {
4367
+ Accept: "application/json",
4368
+ "Content-Type": "application/x-www-form-urlencoded"
4369
+ },
4370
+ body: new URLSearchParams({ client_id: CLIENT_ID, scope: "repo" })
4371
+ });
4372
+ if (!deviceRes.ok) {
4373
+ yield { message: `Failed to request device code: ${deviceRes.status}`, error: true };
4374
+ throw new Error("Device code request failed");
4375
+ }
4376
+ const deviceData = await deviceRes.json();
4377
+ yield {
4378
+ message: `Open ${deviceData.verification_uri} and enter code: ${deviceData.user_code}`,
4379
+ url: deviceData.verification_uri,
4380
+ code: deviceData.user_code
4381
+ };
4382
+ const startTime = Date.now();
4383
+ const expiresIn = deviceData.expires_in * 1e3;
4384
+ const interval = deviceData.interval * 1e3;
4385
+ while (Date.now() - startTime < expiresIn) {
4386
+ await sleep2(interval);
4387
+ const tokenRes = await fetch(GITHUB_ACCESS_TOKEN_URL, {
4388
+ method: "POST",
4389
+ headers: {
4390
+ Accept: "application/json",
4391
+ "Content-Type": "application/x-www-form-urlencoded"
4392
+ },
4393
+ body: new URLSearchParams({
4394
+ client_id: CLIENT_ID,
4395
+ device_code: deviceData.device_code,
4396
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code"
4397
+ })
4398
+ });
4399
+ if (!tokenRes.ok) continue;
4400
+ const tokenData = await tokenRes.json();
4401
+ if (tokenData.error === "authorization_pending") {
4402
+ continue;
4403
+ }
4404
+ if (tokenData.error === "slow_down") {
4405
+ await sleep2(interval * 2);
4406
+ continue;
4407
+ }
4408
+ if (tokenData.error) {
4409
+ yield { message: `OAuth error: ${tokenData.error}`, error: true };
4410
+ throw new Error(tokenData.error);
4411
+ }
4412
+ if (tokenData.access_token) {
4413
+ const cfg = await loadConfig() ?? {
4414
+ accountId: "",
4415
+ apiToken: "",
4416
+ model: "@cf/moonshotai/kimi-k2.6"
4417
+ };
4418
+ await saveConfig({
4419
+ ...cfg,
4420
+ githubOAuthToken: tokenData.access_token,
4421
+ githubRefreshToken: tokenData.refresh_token,
4422
+ githubTokenExpiry: tokenData.expires_in ? Date.now() + tokenData.expires_in * 1e3 : void 0
4423
+ });
4424
+ yield { message: "GitHub authentication successful!", done: true };
4425
+ return;
4426
+ }
4427
+ }
4428
+ yield { message: "Device flow expired. Please try again.", error: true };
4429
+ throw new Error("Device flow expired");
4430
+ }
4431
+ var GITHUB_DEVICE_AUTH_URL, GITHUB_ACCESS_TOKEN_URL, CLIENT_ID;
4432
+ var init_tui_auth = __esm({
4433
+ "src/remote/tui-auth.ts"() {
4434
+ "use strict";
4435
+ init_config();
4436
+ GITHUB_DEVICE_AUTH_URL = "https://github.com/login/device/code";
4437
+ GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
4438
+ CLIENT_ID = process.env.KIMIFLARE_GITHUB_CLIENT_ID ?? "Ov23liM7lJX1xE2V1sVK";
4439
+ }
4440
+ });
4441
+
4111
4442
  // src/agent/compact.ts
4112
4443
  function indexOfNthUserFromEnd(messages, n) {
4113
4444
  let seen = 0;
@@ -4929,12 +5260,12 @@ var init_connection = __esm({
4929
5260
  });
4930
5261
 
4931
5262
  // src/lsp/protocol.ts
4932
- import { pathToFileURL, fileURLToPath as fileURLToPath3 } from "url";
5263
+ import { pathToFileURL, fileURLToPath as fileURLToPath4 } from "url";
4933
5264
  function toUri(path) {
4934
5265
  return pathToFileURL(path).href;
4935
5266
  }
4936
5267
  function fromUri(uri) {
4937
- return fileURLToPath3(uri);
5268
+ return fileURLToPath4(uri);
4938
5269
  }
4939
5270
  function symbolKindName(kind) {
4940
5271
  const names = {
@@ -7569,6 +7900,355 @@ var init_help_menu = __esm({
7569
7900
  }
7570
7901
  });
7571
7902
 
7903
+ // src/remote/worker-client.ts
7904
+ var worker_client_exports = {};
7905
+ __export(worker_client_exports, {
7906
+ cancelRemoteSession: () => cancelRemoteSession,
7907
+ getRemoteStatus: () => getRemoteStatus,
7908
+ startRemoteSession: () => startRemoteSession,
7909
+ streamRemoteProgress: () => streamRemoteProgress
7910
+ });
7911
+ async function startRemoteSession(opts2) {
7912
+ const workerUrl = opts2.cfg.remoteWorkerUrl;
7913
+ if (!workerUrl) {
7914
+ throw new Error("Remote worker URL not configured. Set remoteWorkerUrl in config.");
7915
+ }
7916
+ const githubToken = opts2.cfg.githubOAuthToken;
7917
+ if (!githubToken) {
7918
+ throw new Error("GitHub token not found. Run `kimiflare auth github` first.");
7919
+ }
7920
+ const res = await fetch(`${workerUrl}/remote/start`, {
7921
+ method: "POST",
7922
+ headers: {
7923
+ "Content-Type": "application/json",
7924
+ Authorization: `Bearer ${opts2.cfg.remoteAuthSecret ?? ""}`
7925
+ },
7926
+ body: JSON.stringify({
7927
+ prompt: opts2.prompt,
7928
+ repo: opts2.repo,
7929
+ githubToken,
7930
+ accountId: opts2.cfg.accountId,
7931
+ apiToken: opts2.cfg.apiToken,
7932
+ model: opts2.cfg.model,
7933
+ reasoningEffort: opts2.cfg.reasoningEffort,
7934
+ ttlMinutes: opts2.ttlMinutes ?? opts2.cfg.remoteTtlMinutes,
7935
+ tokensBudget: opts2.tokensBudget ?? opts2.cfg.remoteMaxInputTokens
7936
+ })
7937
+ });
7938
+ if (!res.ok) {
7939
+ const text = await res.text();
7940
+ throw new Error(`Failed to start remote session: ${res.status} ${text}`);
7941
+ }
7942
+ const data = await res.json();
7943
+ await saveRemoteSession({
7944
+ sessionId: data.sessionId,
7945
+ prompt: opts2.prompt,
7946
+ repo: `${opts2.repo.owner}/${opts2.repo.name}`,
7947
+ workerUrl,
7948
+ status: "running",
7949
+ branch: `kimiflare/remote/${data.sessionId}`,
7950
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
7951
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
7952
+ });
7953
+ return data;
7954
+ }
7955
+ async function* streamRemoteProgress(workerUrl, sessionId, signal) {
7956
+ const res = await fetch(`${workerUrl}/remote/stream/${sessionId}`, { signal });
7957
+ if (!res.ok) {
7958
+ throw new Error(`Failed to connect to stream: ${res.status}`);
7959
+ }
7960
+ if (!res.body) {
7961
+ throw new Error("No response body");
7962
+ }
7963
+ for await (const line of readSSE(res.body, signal)) {
7964
+ try {
7965
+ yield JSON.parse(line);
7966
+ } catch {
7967
+ }
7968
+ }
7969
+ }
7970
+ async function getRemoteStatus(workerUrl, sessionId, authSecret) {
7971
+ const res = await fetch(`${workerUrl}/remote/status/${sessionId}`, {
7972
+ headers: authSecret ? { Authorization: `Bearer ${authSecret}` } : {}
7973
+ });
7974
+ if (!res.ok) {
7975
+ const text = await res.text();
7976
+ throw new Error(`Failed to get status: ${res.status} ${text}`);
7977
+ }
7978
+ return res.json();
7979
+ }
7980
+ async function cancelRemoteSession(workerUrl, sessionId, authSecret) {
7981
+ const res = await fetch(`${workerUrl}/remote/cancel/${sessionId}`, {
7982
+ method: "POST",
7983
+ headers: authSecret ? { Authorization: `Bearer ${authSecret}` } : {}
7984
+ });
7985
+ if (!res.ok) {
7986
+ const text = await res.text();
7987
+ throw new Error(`Failed to cancel session: ${res.status} ${text}`);
7988
+ }
7989
+ }
7990
+ var init_worker_client = __esm({
7991
+ "src/remote/worker-client.ts"() {
7992
+ "use strict";
7993
+ init_session_store();
7994
+ init_sse();
7995
+ }
7996
+ });
7997
+
7998
+ // src/remote/tui-deploy.ts
7999
+ var init_tui_deploy = __esm({
8000
+ "src/remote/tui-deploy.ts"() {
8001
+ "use strict";
8002
+ init_deploy();
8003
+ }
8004
+ });
8005
+
8006
+ // src/ui/remote-dashboard.tsx
8007
+ import { useEffect as useEffect4, useState as useState7 } from "react";
8008
+ import { Box as Box12, Text as Text13, useInput as useInput3 } from "ink";
8009
+ import SelectInput4 from "ink-select-input";
8010
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
8011
+ function RemoteDashboard({ onSelect, onCancel }) {
8012
+ const theme = useTheme();
8013
+ const [sessions, setSessions] = useState7([]);
8014
+ const [loading, setLoading] = useState7(true);
8015
+ const [error, setError] = useState7(null);
8016
+ const [refreshing, setRefreshing] = useState7(false);
8017
+ useEffect4(() => {
8018
+ loadSessions();
8019
+ }, []);
8020
+ async function loadSessions() {
8021
+ try {
8022
+ setRefreshing(true);
8023
+ const list = await listRemoteSessions();
8024
+ const updated = await Promise.all(
8025
+ list.map(async (s) => {
8026
+ if (s.status === "running" || s.status === "pending") {
8027
+ try {
8028
+ const status = await getRemoteStatus(s.workerUrl, s.sessionId);
8029
+ return {
8030
+ ...s,
8031
+ status: status.status,
8032
+ prUrl: status.prUrl ?? s.prUrl,
8033
+ tokensUsed: status.tokensUsed ?? s.tokensUsed,
8034
+ tokensBudget: status.tokensBudget ?? s.tokensBudget,
8035
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
8036
+ };
8037
+ } catch {
8038
+ return s;
8039
+ }
8040
+ }
8041
+ return s;
8042
+ })
8043
+ );
8044
+ setSessions(updated.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()));
8045
+ setError(null);
8046
+ } catch (err) {
8047
+ setError(err instanceof Error ? err.message : String(err));
8048
+ } finally {
8049
+ setLoading(false);
8050
+ setRefreshing(false);
8051
+ }
8052
+ }
8053
+ useInput3((input, key) => {
8054
+ if (input === "r" || input === "R") {
8055
+ void loadSessions();
8056
+ }
8057
+ if (key.escape && onCancel) {
8058
+ onCancel();
8059
+ }
8060
+ });
8061
+ const items = sessions.map((s) => ({
8062
+ label: formatSessionLine(s),
8063
+ value: s.sessionId
8064
+ }));
8065
+ if (loading) {
8066
+ return /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "Loading remote sessions..." }) });
8067
+ }
8068
+ if (error) {
8069
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
8070
+ /* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
8071
+ "Error: ",
8072
+ error
8073
+ ] }),
8074
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press R to retry, Esc to close" })
8075
+ ] });
8076
+ }
8077
+ if (sessions.length === 0) {
8078
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
8079
+ /* @__PURE__ */ jsx14(Text13, { color: theme.accent, children: "No remote sessions yet." }),
8080
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Type /remote <prompt> to start one." }),
8081
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Press Esc to close" })
8082
+ ] });
8083
+ }
8084
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
8085
+ /* @__PURE__ */ jsxs12(Text13, { bold: true, color: theme.accent, children: [
8086
+ "Recent remote tasks ",
8087
+ refreshing ? "(refreshing...)" : ""
8088
+ ] }),
8089
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
8090
+ SelectInput4,
8091
+ {
8092
+ items,
8093
+ onSelect: (item) => {
8094
+ const session = sessions.find((s) => s.sessionId === item.value);
8095
+ if (session) onSelect?.(session);
8096
+ }
8097
+ }
8098
+ ) }),
8099
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 R refresh \u2022 Esc close" }) })
8100
+ ] });
8101
+ }
8102
+ function formatSessionLine(s) {
8103
+ const icon = s.status === "done" ? "\u2705" : s.status === "error" ? "\u274C" : s.status === "cancelled" ? "\u23F9\uFE0F" : s.status === "running" ? "\u23F3" : "\u23F8";
8104
+ const ago = formatAgo(new Date(s.updatedAt));
8105
+ const prompt = s.prompt.slice(0, 30) + (s.prompt.length > 30 ? "\u2026" : "");
8106
+ const outcome = s.prUrl ? `PR ${s.prUrl.split("/").pop()}` : s.status;
8107
+ const cost = s.tokensUsed && s.tokensBudget ? ` (${formatTokens2(s.tokensUsed)}/${formatTokens2(s.tokensBudget)})` : s.tokensUsed ? ` (${formatTokens2(s.tokensUsed)})` : "";
8108
+ return `${icon} ${prompt} \u2192 ${outcome} ${ago}${cost}`;
8109
+ }
8110
+ function formatAgo(date) {
8111
+ const ms = Date.now() - date.getTime();
8112
+ const minutes = Math.floor(ms / 6e4);
8113
+ const hours = Math.floor(minutes / 60);
8114
+ const days = Math.floor(hours / 24);
8115
+ if (days > 0) return `${days}d ago`;
8116
+ if (hours > 0) return `${hours}h ago`;
8117
+ if (minutes > 0) return `${minutes}m ago`;
8118
+ return "just now";
8119
+ }
8120
+ function formatTokens2(n) {
8121
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
8122
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
8123
+ return String(n);
8124
+ }
8125
+ function RemoteSessionDetail({
8126
+ session,
8127
+ onBack,
8128
+ onCancel
8129
+ }) {
8130
+ const theme = useTheme();
8131
+ const [cancelling, setCancelling] = useState7(false);
8132
+ useInput3((input, key) => {
8133
+ if (key.escape) {
8134
+ onBack();
8135
+ }
8136
+ if ((input === "c" || input === "C") && onCancel && (session.status === "running" || session.status === "pending")) {
8137
+ void handleCancel();
8138
+ }
8139
+ });
8140
+ async function handleCancel() {
8141
+ if (!onCancel) return;
8142
+ setCancelling(true);
8143
+ try {
8144
+ await cancelRemoteSession(session.workerUrl, session.sessionId);
8145
+ onCancel(session);
8146
+ } catch {
8147
+ } finally {
8148
+ setCancelling(false);
8149
+ }
8150
+ }
8151
+ const isRunning = session.status === "running" || session.status === "pending";
8152
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", padding: 1, children: [
8153
+ /* @__PURE__ */ jsx14(Text13, { bold: true, color: theme.accent, children: "Remote Session" }),
8154
+ /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
8155
+ /* @__PURE__ */ jsxs12(Text13, { children: [
8156
+ "ID: ",
8157
+ session.sessionId
8158
+ ] }),
8159
+ /* @__PURE__ */ jsxs12(Text13, { children: [
8160
+ "Repo: ",
8161
+ session.repo
8162
+ ] }),
8163
+ /* @__PURE__ */ jsxs12(Text13, { children: [
8164
+ "Status: ",
8165
+ session.status
8166
+ ] }),
8167
+ /* @__PURE__ */ jsxs12(Text13, { children: [
8168
+ "Prompt: ",
8169
+ session.prompt
8170
+ ] }),
8171
+ session.prUrl && /* @__PURE__ */ jsxs12(Text13, { children: [
8172
+ "PR: ",
8173
+ session.prUrl
8174
+ ] }),
8175
+ session.errorMessage && /* @__PURE__ */ jsxs12(Text13, { color: theme.error, children: [
8176
+ "Error: ",
8177
+ session.errorMessage
8178
+ ] }),
8179
+ session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs12(Text13, { children: [
8180
+ "Tokens: ",
8181
+ formatTokens2(session.tokensUsed),
8182
+ session.tokensBudget ? ` / ${formatTokens2(session.tokensBudget)}` : ""
8183
+ ] }),
8184
+ /* @__PURE__ */ jsxs12(Text13, { children: [
8185
+ "Created: ",
8186
+ new Date(session.createdAt).toLocaleString()
8187
+ ] }),
8188
+ session.finishedAt && /* @__PURE__ */ jsxs12(Text13, { children: [
8189
+ "Finished: ",
8190
+ new Date(session.finishedAt).toLocaleString()
8191
+ ] })
8192
+ ] }),
8193
+ /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "row", gap: 2, children: [
8194
+ isRunning && onCancel && /* @__PURE__ */ jsx14(Text13, { color: theme.error, children: cancelling ? "Cancelling..." : "[C] Cancel session" }),
8195
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "Esc back" })
8196
+ ] })
8197
+ ] });
8198
+ }
8199
+ var init_remote_dashboard = __esm({
8200
+ "src/ui/remote-dashboard.tsx"() {
8201
+ "use strict";
8202
+ init_theme_context();
8203
+ init_session_store();
8204
+ init_worker_client();
8205
+ }
8206
+ });
8207
+
8208
+ // src/intent/classify.ts
8209
+ function classifyIntent(prompt) {
8210
+ let intentScore = 0;
8211
+ let matchedIntent = "other";
8212
+ for (const [intent, pattern] of Object.entries(INTENT_PATTERNS)) {
8213
+ const matches = (prompt.match(pattern) || []).length;
8214
+ if (matches > intentScore) {
8215
+ intentScore = matches;
8216
+ matchedIntent = intent;
8217
+ }
8218
+ }
8219
+ const hasFileMentions = (prompt.match(/@\w+|\b[\w/-]+\.(ts|tsx|js|jsx|py|go|rs)\b/g) || []).length;
8220
+ const hasMutatingVerb = /\b(add|create|write|edit|delete|remove|rename|migrate|implement)\b/i.test(prompt);
8221
+ const isQuestion = prompt.trim().endsWith("?") || /\b(what|how|why|is|does|can)\b/i.test(prompt.split(" ")[0] || "");
8222
+ const rawScore = Math.min(
8223
+ 1,
8224
+ intentScore * 0.25 + (hasFileMentions > 2 ? 0.3 : hasFileMentions * 0.1) + (hasMutatingVerb ? 0.25 : 0) + (isQuestion ? 0 : 0.1)
8225
+ );
8226
+ const tier = rawScore < 0.3 ? "light" : rawScore < 0.65 ? "medium" : "heavy";
8227
+ return {
8228
+ intent: matchedIntent,
8229
+ rawScore,
8230
+ tier,
8231
+ confidence: 0.5 + (intentScore > 0 ? 0.3 : 0) + (hasFileMentions > 0 ? 0.1 : 0)
8232
+ };
8233
+ }
8234
+ var INTENT_PATTERNS;
8235
+ var init_classify = __esm({
8236
+ "src/intent/classify.ts"() {
8237
+ "use strict";
8238
+ INTENT_PATTERNS = {
8239
+ qa: /\b(what|how|why|explain|describe|what's|what is)\b/i,
8240
+ diagnose: /\b(broken|failing|error|bug|crash|why.*fail|not working)\b/i,
8241
+ verify: /\b(correct|right|verify|review|check|is this|does this)\b/i,
8242
+ polish: /\b(rename|refactor|extract|move|clean|lint|format)\b/i,
8243
+ small_edit: /\b(add|change|update|fix|remove|delete)\b.+\b(line|here|this|variable|function)\b/i,
8244
+ feature_bounded: /\b(add|implement|create|support)\b.+\b(flag|option|param|arg|field)\b/i,
8245
+ feature_exploratory: /\b(add|implement|migrate|integrate|build)\b.+\b(module|system|auth|oauth|framework|service)\b/i,
8246
+ explore: /\b(how.*work|architecture|structure|where.*used|find.*all|understand)\b/i,
8247
+ meta: /\b(plan|design|strategy|ontology|roadmap|approach)\b/i
8248
+ };
8249
+ }
8250
+ });
8251
+
7572
8252
  // src/sessions.ts
7573
8253
  var sessions_exports = {};
7574
8254
  __export(sessions_exports, {
@@ -7578,12 +8258,12 @@ __export(sessions_exports, {
7578
8258
  pruneSessions: () => pruneSessions,
7579
8259
  saveSession: () => saveSession
7580
8260
  });
7581
- import { readFile as readFile10, writeFile as writeFile6, mkdir as mkdir6, readdir as readdir2, stat as stat3 } from "fs/promises";
7582
- import { homedir as homedir8 } from "os";
7583
- import { join as join11 } from "path";
8261
+ import { readFile as readFile11, writeFile as writeFile7, mkdir as mkdir7, readdir as readdir3, stat as stat4 } from "fs/promises";
8262
+ import { homedir as homedir9 } from "os";
8263
+ import { join as join13 } from "path";
7584
8264
  function sessionsDir2() {
7585
- const xdg = process.env.XDG_DATA_HOME || join11(homedir8(), ".local", "share");
7586
- return join11(xdg, "kimiflare", "sessions");
8265
+ const xdg = process.env.XDG_DATA_HOME || join13(homedir9(), ".local", "share");
8266
+ return join13(xdg, "kimiflare", "sessions");
7587
8267
  }
7588
8268
  function sanitize(text) {
7589
8269
  return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
@@ -7595,9 +8275,9 @@ function makeSessionId(firstPrompt) {
7595
8275
  }
7596
8276
  async function saveSession(file) {
7597
8277
  const dir = sessionsDir2();
7598
- await mkdir6(dir, { recursive: true });
7599
- const path = join11(dir, `${file.id}.json`);
7600
- await writeFile6(path, JSON.stringify(file, null, 2), "utf8");
8278
+ await mkdir7(dir, { recursive: true });
8279
+ const path = join13(dir, `${file.id}.json`);
8280
+ await writeFile7(path, JSON.stringify(file, null, 2), "utf8");
7601
8281
  return path;
7602
8282
  }
7603
8283
  async function pruneSessions() {
@@ -7605,21 +8285,22 @@ async function pruneSessions() {
7605
8285
  const files = await listFilesByMtime(dir, /\.json$/);
7606
8286
  return pruneFiles(files, RETENTION.sessionMaxAgeDays, RETENTION.sessionMaxCount);
7607
8287
  }
7608
- async function listSessions(limit = 30) {
8288
+ async function listSessions(limit = 30, cwd) {
7609
8289
  const dir = sessionsDir2();
7610
8290
  let entries;
7611
8291
  try {
7612
- entries = await readdir2(dir);
8292
+ entries = await readdir3(dir);
7613
8293
  } catch {
7614
8294
  return [];
7615
8295
  }
7616
8296
  const summaries = [];
7617
8297
  for (const name of entries) {
7618
8298
  if (!name.endsWith(".json")) continue;
7619
- const path = join11(dir, name);
8299
+ const path = join13(dir, name);
7620
8300
  try {
7621
- const [s, raw] = await Promise.all([stat3(path), readFile10(path, "utf8")]);
8301
+ const [s, raw] = await Promise.all([stat4(path), readFile11(path, "utf8")]);
7622
8302
  const parsed = JSON.parse(raw);
8303
+ if (cwd && parsed.cwd !== cwd) continue;
7623
8304
  const firstUser = parsed.messages.find((m) => m.role === "user");
7624
8305
  const firstPrompt = typeof firstUser?.content === "string" ? firstUser.content : firstUser?.content ? firstUser.content.find((p) => p.type === "text")?.text ?? "(no prompt)" : "(no prompt)";
7625
8306
  summaries.push({
@@ -7637,7 +8318,7 @@ async function listSessions(limit = 30) {
7637
8318
  return summaries.slice(0, limit);
7638
8319
  }
7639
8320
  async function loadSession(filePath) {
7640
- const raw = await readFile10(filePath, "utf8");
8321
+ const raw = await readFile11(filePath, "utf8");
7641
8322
  return JSON.parse(raw);
7642
8323
  }
7643
8324
  var init_sessions = __esm({
@@ -7648,10 +8329,10 @@ var init_sessions = __esm({
7648
8329
  });
7649
8330
 
7650
8331
  // src/util/image.ts
7651
- import { readFile as readFile11 } from "fs/promises";
8332
+ import { readFile as readFile12 } from "fs/promises";
7652
8333
  import { basename as basename3 } from "path";
7653
8334
  async function encodeImageFile(filePath) {
7654
- const buf = await readFile11(filePath);
8335
+ const buf = await readFile12(filePath);
7655
8336
  if (buf.byteLength > MAX_IMAGE_BYTES) {
7656
8337
  throw new Error(
7657
8338
  `image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
@@ -7687,15 +8368,15 @@ var init_image = __esm({
7687
8368
  });
7688
8369
 
7689
8370
  // src/usage-tracker.ts
7690
- import { readFile as readFile12, writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
7691
- import { homedir as homedir9 } from "os";
7692
- import { join as join12 } from "path";
8371
+ import { readFile as readFile13, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
8372
+ import { homedir as homedir10 } from "os";
8373
+ import { join as join14 } from "path";
7693
8374
  function usageDir2() {
7694
- const xdg = process.env.XDG_DATA_HOME || join12(homedir9(), ".local", "share");
7695
- return join12(xdg, "kimiflare");
8375
+ const xdg = process.env.XDG_DATA_HOME || join14(homedir10(), ".local", "share");
8376
+ return join14(xdg, "kimiflare");
7696
8377
  }
7697
8378
  function usagePath2() {
7698
- return join12(usageDir2(), "usage.json");
8379
+ return join14(usageDir2(), "usage.json");
7699
8380
  }
7700
8381
  function today2() {
7701
8382
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -7706,7 +8387,7 @@ function cutoffDate(daysBack) {
7706
8387
  }
7707
8388
  async function loadLog2() {
7708
8389
  try {
7709
- const raw = await readFile12(usagePath2(), "utf8");
8390
+ const raw = await readFile13(usagePath2(), "utf8");
7710
8391
  const parsed = JSON.parse(raw);
7711
8392
  if (parsed.version === LOG_VERSION2) return parsed;
7712
8393
  } catch {
@@ -7714,8 +8395,8 @@ async function loadLog2() {
7714
8395
  return { version: LOG_VERSION2, days: [], sessions: [] };
7715
8396
  }
7716
8397
  async function saveLog(log) {
7717
- await mkdir7(usageDir2(), { recursive: true });
7718
- await writeFile7(usagePath2(), JSON.stringify(log, null, 2), "utf8");
8398
+ await mkdir8(usageDir2(), { recursive: true });
8399
+ await writeFile8(usagePath2(), JSON.stringify(log, null, 2), "utf8");
7719
8400
  }
7720
8401
  function getOrCreateDay(log, date) {
7721
8402
  let day = log.days.find((d) => d.date === date);
@@ -7921,7 +8602,7 @@ __export(db_exports, {
7921
8602
  updateMemoryEmbedding: () => updateMemoryEmbedding
7922
8603
  });
7923
8604
  import Database from "better-sqlite3";
7924
- import { dirname as dirname5 } from "path";
8605
+ import { dirname as dirname6 } from "path";
7925
8606
  import { mkdirSync, statSync as statSync2 } from "fs";
7926
8607
  function initSchema(db) {
7927
8608
  db.exec(`
@@ -8006,7 +8687,7 @@ function openMemoryDb(dbPath) {
8006
8687
  if (dbInstance) {
8007
8688
  dbInstance.close();
8008
8689
  }
8009
- mkdirSync(dirname5(dbPath), { recursive: true });
8690
+ mkdirSync(dirname6(dbPath), { recursive: true });
8010
8691
  dbInstance = new Database(dbPath);
8011
8692
  dbInstance.pragma("journal_mode = WAL");
8012
8693
  dbInstance.pragma("foreign_keys = ON");
@@ -8300,7 +8981,7 @@ function truncateForEmbedding(text) {
8300
8981
  if (text.length <= MAX_EMBED_CHARS) return text;
8301
8982
  return text.slice(0, MAX_EMBED_CHARS);
8302
8983
  }
8303
- async function sleep2(ms) {
8984
+ async function sleep3(ms) {
8304
8985
  return new Promise((resolve2) => setTimeout(resolve2, ms));
8305
8986
  }
8306
8987
  async function fetchWithRetry(url, init, retries = 3) {
@@ -8311,7 +8992,7 @@ async function fetchWithRetry(url, init, retries = 3) {
8311
8992
  if (res.ok) return res;
8312
8993
  if (res.status === 429 || res.status >= 500) {
8313
8994
  const delay = 1e3 * 2 ** i;
8314
- await sleep2(delay);
8995
+ await sleep3(delay);
8315
8996
  continue;
8316
8997
  }
8317
8998
  const errText = await res.text().catch(() => "unknown error");
@@ -8319,7 +9000,7 @@ async function fetchWithRetry(url, init, retries = 3) {
8319
9000
  } catch (e) {
8320
9001
  lastError = e;
8321
9002
  if (i < retries - 1) {
8322
- await sleep2(1e3 * 2 ** i);
9003
+ await sleep3(1e3 * 2 ** i);
8323
9004
  }
8324
9005
  }
8325
9006
  }
@@ -8933,16 +9614,16 @@ Context: This memory was explicitly provided by the user during a conversation.`
8933
9614
  });
8934
9615
 
8935
9616
  // src/util/state.ts
8936
- import { readFile as readFile13, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
8937
- import { homedir as homedir10 } from "os";
8938
- import { join as join14 } from "path";
9617
+ import { readFile as readFile14, writeFile as writeFile9, mkdir as mkdir9 } from "fs/promises";
9618
+ import { homedir as homedir11 } from "os";
9619
+ import { join as join16 } from "path";
8939
9620
  function statePath() {
8940
- const xdg = process.env.XDG_CONFIG_HOME || join14(homedir10(), ".config");
8941
- return join14(xdg, "kimiflare", "state.json");
9621
+ const xdg = process.env.XDG_CONFIG_HOME || join16(homedir11(), ".config");
9622
+ return join16(xdg, "kimiflare", "state.json");
8942
9623
  }
8943
9624
  async function readState() {
8944
9625
  try {
8945
- const raw = await readFile13(statePath(), "utf8");
9626
+ const raw = await readFile14(statePath(), "utf8");
8946
9627
  return JSON.parse(raw);
8947
9628
  } catch {
8948
9629
  return {};
@@ -8950,8 +9631,8 @@ async function readState() {
8950
9631
  }
8951
9632
  async function writeState(state) {
8952
9633
  const path = statePath();
8953
- await mkdir8(join14(path, ".."), { recursive: true });
8954
- await writeFile8(path, JSON.stringify(state, null, 2) + "\n", "utf8");
9634
+ await mkdir9(join16(path, ".."), { recursive: true });
9635
+ await writeFile9(path, JSON.stringify(state, null, 2) + "\n", "utf8");
8955
9636
  }
8956
9637
  async function markCreatorMessageSeen(version) {
8957
9638
  const state = await readState();
@@ -9024,15 +9705,15 @@ var init_frontmatter = __esm({
9024
9705
 
9025
9706
  // src/commands/loader.ts
9026
9707
  import { open, realpath } from "fs/promises";
9027
- import { homedir as homedir11 } from "os";
9028
- import { join as join15, relative as relative4, sep as sep2 } from "path";
9708
+ import { homedir as homedir12 } from "os";
9709
+ import { join as join17, relative as relative4, sep as sep2 } from "path";
9029
9710
  import fg3 from "fast-glob";
9030
9711
  function projectCommandsDir(cwd = process.cwd()) {
9031
- return join15(cwd, ".kimiflare", "commands");
9712
+ return join17(cwd, ".kimiflare", "commands");
9032
9713
  }
9033
9714
  function globalCommandsDir() {
9034
- const xdg = process.env.XDG_CONFIG_HOME || join15(homedir11(), ".config");
9035
- return join15(xdg, "kimiflare", "commands");
9715
+ const xdg = process.env.XDG_CONFIG_HOME || join17(homedir12(), ".config");
9716
+ return join17(xdg, "kimiflare", "commands");
9036
9717
  }
9037
9718
  async function loadCustomCommands(cwd = process.cwd()) {
9038
9719
  const warnings = [];
@@ -9394,6 +10075,7 @@ var init_builtins = __esm({
9394
10075
  { name: "compact", description: "Summarize old turns to free context", source: "builtin" },
9395
10076
  { name: "clear", description: "Clear current conversation", source: "builtin" },
9396
10077
  { name: "init", description: "Scan repo and write KIMI.md", source: "builtin" },
10078
+ { name: "remote", argHint: "<prompt>", description: "Run a remote session on Cloudflare", source: "builtin" },
9397
10079
  { name: "update", description: "Check for updates", source: "builtin" },
9398
10080
  { name: "hello", description: "Send a voice note to the creator", source: "builtin" },
9399
10081
  { name: "logout", description: "Clear stored credentials", source: "builtin" },
@@ -9407,8 +10089,8 @@ var init_builtins = __esm({
9407
10089
  });
9408
10090
 
9409
10091
  // src/commands/save.ts
9410
- import { mkdir as mkdir9, writeFile as writeFile9, unlink as unlink2 } from "fs/promises";
9411
- import { dirname as dirname6 } from "path";
10092
+ import { mkdir as mkdir10, writeFile as writeFile10, unlink as unlink2 } from "fs/promises";
10093
+ import { dirname as dirname7 } from "path";
9412
10094
  async function saveCustomCommand(opts2) {
9413
10095
  const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
9414
10096
  const filepath = `${dir}/${opts2.name}.md`;
@@ -9419,8 +10101,8 @@ async function saveCustomCommand(opts2) {
9419
10101
  if (opts2.effort) data.effort = opts2.effort;
9420
10102
  const frontmatter = serializeFrontmatter(data);
9421
10103
  const content = frontmatter + opts2.template;
9422
- await mkdir9(dirname6(filepath), { recursive: true });
9423
- await writeFile9(filepath, content, "utf8");
10104
+ await mkdir10(dirname7(filepath), { recursive: true });
10105
+ await writeFile10(filepath, content, "utf8");
9424
10106
  return { filepath };
9425
10107
  }
9426
10108
  async function deleteCustomCommand(cmd) {
@@ -9435,21 +10117,21 @@ var init_save = __esm({
9435
10117
  });
9436
10118
 
9437
10119
  // src/ui/command-wizard.tsx
9438
- import { useState as useState7 } from "react";
9439
- import { Box as Box12, Text as Text13, useInput as useInput3, useWindowSize as useWindowSize2 } from "ink";
9440
- import SelectInput4 from "ink-select-input";
9441
- import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
10120
+ import { useState as useState8 } from "react";
10121
+ import { Box as Box13, Text as Text14, useInput as useInput4, useWindowSize as useWindowSize2 } from "ink";
10122
+ import SelectInput5 from "ink-select-input";
10123
+ import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
9442
10124
  function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onSave }) {
9443
10125
  const theme = useTheme();
9444
- const [step, setStep] = useState7("name");
9445
- const [name, setName] = useState7(initial?.name ?? "");
9446
- const [description, setDescription] = useState7(initial?.description ?? "");
9447
- const [template, setTemplate] = useState7(initial?.template ?? "");
9448
- const [cmdMode, setCmdMode] = useState7(initial?.mode);
9449
- const [cmdEffort, setCmdEffort] = useState7(initial?.effort);
9450
- const [cmdModel, setCmdModel] = useState7(initial?.model);
9451
- const [source, setSource] = useState7(initial?.source ?? "project");
9452
- const [error, setError] = useState7(null);
10126
+ const [step, setStep] = useState8("name");
10127
+ const [name, setName] = useState8(initial?.name ?? "");
10128
+ const [description, setDescription] = useState8(initial?.description ?? "");
10129
+ const [template, setTemplate] = useState8(initial?.template ?? "");
10130
+ const [cmdMode, setCmdMode] = useState8(initial?.mode);
10131
+ const [cmdEffort, setCmdEffort] = useState8(initial?.effort);
10132
+ const [cmdModel, setCmdModel] = useState8(initial?.model);
10133
+ const [source, setSource] = useState8(initial?.source ?? "project");
10134
+ const [error, setError] = useState8(null);
9453
10135
  const { columns } = useWindowSize2();
9454
10136
  const totalSteps = 5;
9455
10137
  const stepIndex = step === "name" ? 1 : step === "description" ? 2 : step === "template" ? 3 : step === "advanced" || step === "mode" || step === "effort" || step === "model" ? 4 : step === "location" ? 4 : 5;
@@ -9462,7 +10144,7 @@ function CommandWizard({ mode, initial, existingNames, builtinNames, onDone, onS
9462
10144
  if (existingNames.includes(trimmed) && !isEditingSelf(trimmed)) return `/${trimmed} already exists`;
9463
10145
  return null;
9464
10146
  };
9465
- useInput3((_input, key) => {
10147
+ useInput4((_input, key) => {
9466
10148
  if (key.escape) {
9467
10149
  onDone();
9468
10150
  }
@@ -9562,8 +10244,8 @@ ${template}`;
9562
10244
  const renderStep = () => {
9563
10245
  switch (step) {
9564
10246
  case "name":
9565
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9566
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10247
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10248
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9567
10249
  mode === "create" ? "Create" : "Edit",
9568
10250
  " custom command \u2014 Name (",
9569
10251
  stepIndex,
@@ -9571,8 +10253,8 @@ ${template}`;
9571
10253
  totalSteps,
9572
10254
  ")"
9573
10255
  ] }),
9574
- error && /* @__PURE__ */ jsx14(Text13, { color: theme.error, children: error }),
9575
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
10256
+ error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
10257
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
9576
10258
  CustomTextInput,
9577
10259
  {
9578
10260
  value: name,
@@ -9581,11 +10263,11 @@ ${template}`;
9581
10263
  focus: true
9582
10264
  }
9583
10265
  ) }),
9584
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
10266
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "letters, numbers, _ - / only; must start with a letter" })
9585
10267
  ] });
9586
10268
  case "description":
9587
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9588
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10269
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10270
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9589
10271
  mode === "create" ? "Create" : "Edit",
9590
10272
  " custom command \u2014 Description (",
9591
10273
  stepIndex,
@@ -9593,7 +10275,7 @@ ${template}`;
9593
10275
  totalSteps,
9594
10276
  ")"
9595
10277
  ] }),
9596
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
10278
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
9597
10279
  CustomTextInput,
9598
10280
  {
9599
10281
  value: description,
@@ -9602,49 +10284,49 @@ ${template}`;
9602
10284
  focus: true
9603
10285
  }
9604
10286
  ) }),
9605
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "Press Enter to skip" })
10287
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
9606
10288
  ] });
9607
10289
  case "template": {
9608
- const guide = /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingLeft: 1, children: [
9609
- /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "What is this?" }),
9610
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
9611
- /* @__PURE__ */ jsxs12(Text13, { color: theme.info.color, children: [
10290
+ const guide = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingLeft: 1, children: [
10291
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "What is this?" }),
10292
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "A prompt template \u2014 instructions to the AI." }),
10293
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
9612
10294
  "When you type /",
9613
10295
  name || "yourcommand",
9614
10296
  " later, this gets sent to the model."
9615
10297
  ] }),
9616
- /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
9617
- /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Variables" }),
9618
- /* @__PURE__ */ jsxs12(Text13, { color: theme.info.color, children: [
10298
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
10299
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Variables" }),
10300
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
9619
10301
  " ",
9620
10302
  "$1, $2 ... \u2192 arguments you type"
9621
10303
  ] }),
9622
- /* @__PURE__ */ jsxs12(Text13, { color: theme.info.color, children: [
10304
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
9623
10305
  " ",
9624
10306
  "$ARGUMENTS \u2192 everything after the command"
9625
10307
  ] })
9626
10308
  ] }),
9627
- /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
9628
- /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
9629
- /* @__PURE__ */ jsxs12(Text13, { color: theme.info.color, children: [
10309
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
10310
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
10311
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
9630
10312
  " ",
9631
10313
  "!`git diff` \u2192 shell output inlined"
9632
10314
  ] }),
9633
- /* @__PURE__ */ jsxs12(Text13, { color: theme.info.color, children: [
10315
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
9634
10316
  " ",
9635
10317
  "@README.md \u2192 file contents inlined"
9636
10318
  ] })
9637
10319
  ] }),
9638
- /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
9639
- /* @__PURE__ */ jsx14(Text13, { color: theme.accent, bold: true, children: "Example" }),
9640
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "Review this PR diff:" }),
9641
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
9642
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "Focus on: $1" })
10320
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
10321
+ /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "Example" }),
10322
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Review this PR diff:" }),
10323
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "!`git diff main...HEAD`" }),
10324
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Focus on: $1" })
9643
10325
  ] })
9644
10326
  ] });
9645
- const inputArea = /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", flexGrow: 1, children: [
9646
- error && /* @__PURE__ */ jsx14(Text13, { color: theme.error, children: error }),
9647
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
10327
+ const inputArea = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", flexGrow: 1, children: [
10328
+ error && /* @__PURE__ */ jsx15(Text14, { color: theme.error, children: error }),
10329
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
9648
10330
  CustomTextInput,
9649
10331
  {
9650
10332
  value: template,
@@ -9654,13 +10336,13 @@ ${template}`;
9654
10336
  enablePaste: true
9655
10337
  }
9656
10338
  ) }),
9657
- columns < 100 && /* @__PURE__ */ jsxs12(Fragment2, { children: [
9658
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
9659
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
10339
+ columns < 100 && /* @__PURE__ */ jsxs13(Fragment2, { children: [
10340
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Paste multi-line templates with Ctrl+V." }),
10341
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
9660
10342
  ] })
9661
10343
  ] });
9662
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9663
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10344
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10345
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9664
10346
  mode === "create" ? "Create" : "Edit",
9665
10347
  " custom command \u2014 Template (",
9666
10348
  stepIndex,
@@ -9668,10 +10350,10 @@ ${template}`;
9668
10350
  totalSteps,
9669
10351
  ")"
9670
10352
  ] }),
9671
- columns >= 100 ? /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", marginTop: 1, children: [
9672
- /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", width: "50%", children: inputArea }),
9673
- /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", width: "50%", children: guide })
9674
- ] }) : /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", marginTop: 1, children: inputArea })
10353
+ columns >= 100 ? /* @__PURE__ */ jsxs13(Box13, { flexDirection: "row", marginTop: 1, children: [
10354
+ /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: inputArea }),
10355
+ /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", width: "50%", children: guide })
10356
+ ] }) : /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", marginTop: 1, children: inputArea })
9675
10357
  ] });
9676
10358
  }
9677
10359
  case "advanced": {
@@ -9680,8 +10362,8 @@ ${template}`;
9680
10362
  { label: "Skip", value: "skip", key: "skip" },
9681
10363
  { label: "\u2190 Cancel", value: "cancel", key: "cancel" }
9682
10364
  ];
9683
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9684
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10365
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10366
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9685
10367
  mode === "create" ? "Create" : "Edit",
9686
10368
  " custom command \u2014 Options (",
9687
10369
  stepIndex,
@@ -9689,8 +10371,8 @@ ${template}`;
9689
10371
  totalSteps,
9690
10372
  ")"
9691
10373
  ] }),
9692
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
9693
- SelectInput4,
10374
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10375
+ SelectInput5,
9694
10376
  {
9695
10377
  items,
9696
10378
  onSelect: (item) => {
@@ -9709,17 +10391,17 @@ ${template}`;
9709
10391
  { label: cmdMode === "auto" ? "auto \xB7 current" : "auto", value: "auto", key: "auto" },
9710
10392
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
9711
10393
  ];
9712
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9713
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10394
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10395
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9714
10396
  "Mode override (",
9715
10397
  stepIndex,
9716
10398
  "/",
9717
10399
  totalSteps,
9718
10400
  ")"
9719
10401
  ] }),
9720
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
9721
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
9722
- SelectInput4,
10402
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Saved to file but not yet enforced at runtime" }),
10403
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10404
+ SelectInput5,
9723
10405
  {
9724
10406
  items,
9725
10407
  onSelect: (item) => {
@@ -9738,16 +10420,16 @@ ${template}`;
9738
10420
  { label: cmdEffort === "high" ? "high \xB7 current" : "high", value: "high", key: "high" },
9739
10421
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
9740
10422
  ];
9741
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9742
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10423
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10424
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9743
10425
  "Reasoning effort (",
9744
10426
  stepIndex,
9745
10427
  "/",
9746
10428
  totalSteps,
9747
10429
  ")"
9748
10430
  ] }),
9749
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
9750
- SelectInput4,
10431
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10432
+ SelectInput5,
9751
10433
  {
9752
10434
  items,
9753
10435
  onSelect: (item) => {
@@ -9759,15 +10441,15 @@ ${template}`;
9759
10441
  ] });
9760
10442
  }
9761
10443
  case "model":
9762
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9763
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10444
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10445
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9764
10446
  "Model override (",
9765
10447
  stepIndex,
9766
10448
  "/",
9767
10449
  totalSteps,
9768
10450
  ")"
9769
10451
  ] }),
9770
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
10452
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
9771
10453
  CustomTextInput,
9772
10454
  {
9773
10455
  value: cmdModel ?? "",
@@ -9776,7 +10458,7 @@ ${template}`;
9776
10458
  focus: true
9777
10459
  }
9778
10460
  ) }),
9779
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "Press Enter to skip" })
10461
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Press Enter to skip" })
9780
10462
  ] });
9781
10463
  case "location": {
9782
10464
  const items = [
@@ -9784,16 +10466,16 @@ ${template}`;
9784
10466
  { label: source === "global" ? "Global \xB7 current" : "Global", value: "global", key: "global" },
9785
10467
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
9786
10468
  ];
9787
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9788
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10469
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10470
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9789
10471
  "Save location (",
9790
10472
  stepIndex,
9791
10473
  "/",
9792
10474
  totalSteps,
9793
10475
  ")"
9794
10476
  ] }),
9795
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
9796
- SelectInput4,
10477
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10478
+ SelectInput5,
9797
10479
  {
9798
10480
  items,
9799
10481
  onSelect: (item) => {
@@ -9802,7 +10484,7 @@ ${template}`;
9802
10484
  }
9803
10485
  }
9804
10486
  ) }),
9805
- /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
10487
+ /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
9806
10488
  ] });
9807
10489
  }
9808
10490
  case "confirm": {
@@ -9810,8 +10492,8 @@ ${template}`;
9810
10492
  { label: "Save", value: "save", key: "save" },
9811
10493
  { label: "Cancel", value: "cancel", key: "cancel" }
9812
10494
  ];
9813
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
9814
- /* @__PURE__ */ jsxs12(Text13, { color: theme.accent, bold: true, children: [
10495
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
10496
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
9815
10497
  mode === "create" ? "Create" : "Edit",
9816
10498
  " custom command \u2014 Confirm (",
9817
10499
  stepIndex,
@@ -9819,14 +10501,14 @@ ${template}`;
9819
10501
  totalSteps,
9820
10502
  ")"
9821
10503
  ] }),
9822
- /* @__PURE__ */ jsxs12(Text13, { color: theme.info.color, children: [
10504
+ /* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, children: [
9823
10505
  source === "project" ? ".kimiflare/commands/" : "~/.config/kimiflare/commands/",
9824
10506
  name,
9825
10507
  ".md"
9826
10508
  ] }),
9827
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx14(Text13, { color: theme.info.color, children: line || " " }, i)) }),
9828
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(
9829
- SelectInput4,
10509
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, children: line || " " }, i)) }),
10510
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
10511
+ SelectInput5,
9830
10512
  {
9831
10513
  items,
9832
10514
  onSelect: (item) => handleConfirm(item.value)
@@ -9836,7 +10518,7 @@ ${template}`;
9836
10518
  }
9837
10519
  }
9838
10520
  };
9839
- return /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
10521
+ return /* @__PURE__ */ jsx15(Box13, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
9840
10522
  }
9841
10523
  var NAME_RE;
9842
10524
  var init_command_wizard = __esm({
@@ -9849,9 +10531,9 @@ var init_command_wizard = __esm({
9849
10531
  });
9850
10532
 
9851
10533
  // src/ui/command-picker.tsx
9852
- import { Box as Box13, Text as Text14 } from "ink";
9853
- import SelectInput5 from "ink-select-input";
9854
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
10534
+ import { Box as Box14, Text as Text15 } from "ink";
10535
+ import SelectInput6 from "ink-select-input";
10536
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
9855
10537
  function CommandPicker({ commands, title, onPick }) {
9856
10538
  const theme = useTheme();
9857
10539
  const items = commands.map((cmd) => ({
@@ -9860,11 +10542,11 @@ function CommandPicker({ commands, title, onPick }) {
9860
10542
  key: cmd.name
9861
10543
  }));
9862
10544
  items.push({ label: "\u2190 Cancel", value: null, key: "__cancel__" });
9863
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
9864
- /* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: title }),
9865
- /* @__PURE__ */ jsx15(Text14, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
9866
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(
9867
- SelectInput5,
10545
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10546
+ /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: title }),
10547
+ /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
10548
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(
10549
+ SelectInput6,
9868
10550
  {
9869
10551
  items,
9870
10552
  onSelect: (item) => {
@@ -9886,64 +10568,64 @@ var init_command_picker = __esm({
9886
10568
  });
9887
10569
 
9888
10570
  // src/ui/command-list.tsx
9889
- import { Box as Box14, Text as Text15, useInput as useInput4 } from "ink";
9890
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
10571
+ import { Box as Box15, Text as Text16, useInput as useInput5 } from "ink";
10572
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
9891
10573
  function CommandList({ commands, onDone }) {
9892
10574
  const theme = useTheme();
9893
- useInput4((_input, key) => {
10575
+ useInput5((_input, key) => {
9894
10576
  if (key.escape) {
9895
10577
  onDone();
9896
10578
  }
9897
10579
  });
9898
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
9899
- /* @__PURE__ */ jsx16(Text15, { color: theme.accent, bold: true, children: "Custom commands" }),
9900
- /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
9901
- /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
9902
- commands.length === 0 && /* @__PURE__ */ jsx16(Text15, { color: theme.info.color, children: "No custom commands found." }),
9903
- commands.map((cmd) => /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginBottom: 1, children: [
9904
- /* @__PURE__ */ jsxs14(Text15, { color: theme.accent, bold: true, children: [
10580
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10581
+ /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Custom commands" }),
10582
+ /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
10583
+ /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
10584
+ commands.length === 0 && /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "No custom commands found." }),
10585
+ commands.map((cmd) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginBottom: 1, children: [
10586
+ /* @__PURE__ */ jsxs15(Text16, { color: theme.accent, bold: true, children: [
9905
10587
  "/",
9906
10588
  cmd.name
9907
10589
  ] }),
9908
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10590
+ /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9909
10591
  " ",
9910
10592
  "source: ",
9911
10593
  cmd.source
9912
10594
  ] }),
9913
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10595
+ /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9914
10596
  " ",
9915
10597
  "path: ",
9916
10598
  cmd.filepath
9917
10599
  ] }),
9918
- cmd.description && /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10600
+ cmd.description && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9919
10601
  " ",
9920
10602
  "desc: ",
9921
10603
  cmd.description
9922
10604
  ] }),
9923
- cmd.mode && /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10605
+ cmd.mode && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9924
10606
  " ",
9925
10607
  "mode: ",
9926
10608
  cmd.mode
9927
10609
  ] }),
9928
- cmd.effort && /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10610
+ cmd.effort && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9929
10611
  " ",
9930
10612
  "effort: ",
9931
10613
  cmd.effort
9932
10614
  ] }),
9933
- cmd.model && /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10615
+ cmd.model && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9934
10616
  " ",
9935
10617
  "model: ",
9936
10618
  cmd.model
9937
10619
  ] }),
9938
- /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10620
+ /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9939
10621
  " ",
9940
10622
  "template:"
9941
10623
  ] }),
9942
- cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10624
+ cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9943
10625
  " ",
9944
10626
  line || " "
9945
10627
  ] }, i)),
9946
- cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs14(Text15, { color: theme.info.color, children: [
10628
+ cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, children: [
9947
10629
  " ",
9948
10630
  "..."
9949
10631
  ] })
@@ -9959,20 +10641,20 @@ var init_command_list = __esm({
9959
10641
  });
9960
10642
 
9961
10643
  // src/ui/lsp-wizard.tsx
9962
- import { useState as useState8 } from "react";
9963
- import { Box as Box15, Text as Text16 } from "ink";
9964
- import SelectInput6 from "ink-select-input";
10644
+ import { useState as useState9 } from "react";
10645
+ import { Box as Box16, Text as Text17 } from "ink";
10646
+ import SelectInput7 from "ink-select-input";
9965
10647
  import { spawn as spawn3 } from "child_process";
9966
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
10648
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
9967
10649
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
9968
10650
  const theme = useTheme();
9969
- const [page, setPage] = useState8("main");
9970
- const [selectedPreset, setSelectedPreset] = useState8(null);
9971
- const [customName, setCustomName] = useState8("");
9972
- const [customCommand, setCustomCommand] = useState8("");
9973
- const [installState, setInstallState] = useState8({ status: "idle", output: "" });
9974
- const [pendingServers, setPendingServers] = useState8(null);
9975
- const [pendingEnabled, setPendingEnabled] = useState8(true);
10651
+ const [page, setPage] = useState9("main");
10652
+ const [selectedPreset, setSelectedPreset] = useState9(null);
10653
+ const [customName, setCustomName] = useState9("");
10654
+ const [customCommand, setCustomCommand] = useState9("");
10655
+ const [installState, setInstallState] = useState9({ status: "idle", output: "" });
10656
+ const [pendingServers, setPendingServers] = useState9(null);
10657
+ const [pendingEnabled, setPendingEnabled] = useState9(true);
9976
10658
  const runInstall = (command) => {
9977
10659
  setInstallState({ status: "running", output: "Installing..." });
9978
10660
  const child = spawn3("bash", ["-lc", command], {
@@ -10074,11 +10756,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10074
10756
  { label: "(close)", value: "__close__", key: "__close__" }
10075
10757
  ];
10076
10758
  if (page === "main") {
10077
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10078
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "LSP Servers" }),
10079
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
10080
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10081
- SelectInput6,
10759
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10760
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "LSP Servers" }),
10761
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
10762
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10763
+ SelectInput7,
10082
10764
  {
10083
10765
  items: mainItems,
10084
10766
  onSelect: (item) => {
@@ -10105,11 +10787,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10105
10787
  }),
10106
10788
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
10107
10789
  ];
10108
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10109
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Add LSP Server" }),
10110
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
10111
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10112
- SelectInput6,
10790
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10791
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Add LSP Server" }),
10792
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a language server to configure." }),
10793
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10794
+ SelectInput7,
10113
10795
  {
10114
10796
  items,
10115
10797
  onSelect: (item) => {
@@ -10136,19 +10818,19 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10136
10818
  { label: isSuccess ? "Save to config \u2713" : "Save anyway", value: "save", key: "save" },
10137
10819
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
10138
10820
  ];
10139
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10140
- /* @__PURE__ */ jsxs15(Text16, { color: theme.accent, bold: true, children: [
10821
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10822
+ /* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
10141
10823
  "Install ",
10142
10824
  selectedPreset.name
10143
10825
  ] }),
10144
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
10145
- /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
10146
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Command:" }),
10147
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
10826
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: selectedPreset.installHint }),
10827
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
10828
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Command:" }),
10829
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: selectedPreset.installCommand || "(none required)" })
10148
10830
  ] }),
10149
- installState.output && /* @__PURE__ */ jsx17(Box15, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx17(Text16, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
10150
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10151
- SelectInput6,
10831
+ installState.output && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx18(Text17, { color: isSuccess ? theme.accent : theme.error, children: installState.output.slice(-500) }) }),
10832
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10833
+ SelectInput7,
10152
10834
  {
10153
10835
  items,
10154
10836
  onSelect: (item) => {
@@ -10165,16 +10847,16 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10165
10847
  }
10166
10848
  }
10167
10849
  ) }),
10168
- isSuccess && /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text16, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
10850
+ isSuccess && /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "Server saved. Run /lsp reload to start it." }) })
10169
10851
  ] });
10170
10852
  }
10171
10853
  if (page === "custom-name") {
10172
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10173
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
10174
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
10175
- /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, children: [
10176
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, children: "\u203A " }),
10177
- /* @__PURE__ */ jsx17(
10854
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10855
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Name" }),
10856
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter a name for this server (e.g., my-server)." }),
10857
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
10858
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
10859
+ /* @__PURE__ */ jsx18(
10178
10860
  CustomTextInput,
10179
10861
  {
10180
10862
  value: customName,
@@ -10188,8 +10870,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10188
10870
  }
10189
10871
  )
10190
10872
  ] }),
10191
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10192
- SelectInput6,
10873
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10874
+ SelectInput7,
10193
10875
  {
10194
10876
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
10195
10877
  onSelect: () => setPage("add")
@@ -10198,12 +10880,12 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10198
10880
  ] });
10199
10881
  }
10200
10882
  if (page === "custom-command") {
10201
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10202
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
10203
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
10204
- /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, children: [
10205
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, children: "\u203A " }),
10206
- /* @__PURE__ */ jsx17(
10883
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10884
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Custom LSP Server \u2014 Command" }),
10885
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Enter the command to start the server (space-separated)." }),
10886
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
10887
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, children: "\u203A " }),
10888
+ /* @__PURE__ */ jsx18(
10207
10889
  CustomTextInput,
10208
10890
  {
10209
10891
  value: customCommand,
@@ -10217,8 +10899,8 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10217
10899
  }
10218
10900
  )
10219
10901
  ] }),
10220
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10221
- SelectInput6,
10902
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10903
+ SelectInput7,
10222
10904
  {
10223
10905
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
10224
10906
  onSelect: () => setPage("custom-name")
@@ -10241,11 +10923,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10241
10923
  },
10242
10924
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
10243
10925
  ];
10244
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10245
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Save LSP Config" }),
10246
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
10247
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10248
- SelectInput6,
10926
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10927
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Save LSP Config" }),
10928
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Where should this server configuration be saved?" }),
10929
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10930
+ SelectInput7,
10249
10931
  {
10250
10932
  items,
10251
10933
  onSelect: (item) => {
@@ -10263,11 +10945,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10263
10945
  if (page === "edit") {
10264
10946
  const keys = Object.keys(servers);
10265
10947
  if (keys.length === 0) {
10266
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10267
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
10268
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "No servers configured." }),
10269
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10270
- SelectInput6,
10948
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10949
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
10950
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
10951
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10952
+ SelectInput7,
10271
10953
  {
10272
10954
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
10273
10955
  onSelect: () => setPage("main")
@@ -10287,11 +10969,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10287
10969
  }),
10288
10970
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
10289
10971
  ];
10290
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10291
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
10292
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
10293
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10294
- SelectInput6,
10972
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10973
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Edit LSP Server" }),
10974
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to toggle enabled/disabled." }),
10975
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10976
+ SelectInput7,
10295
10977
  {
10296
10978
  items,
10297
10979
  onSelect: (item) => {
@@ -10308,11 +10990,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10308
10990
  if (page === "delete") {
10309
10991
  const keys = Object.keys(servers);
10310
10992
  if (keys.length === 0) {
10311
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10312
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
10313
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "No servers configured." }),
10314
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10315
- SelectInput6,
10993
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10994
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
10995
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }),
10996
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10997
+ SelectInput7,
10316
10998
  {
10317
10999
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
10318
11000
  onSelect: () => setPage("main")
@@ -10328,11 +11010,11 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10328
11010
  })),
10329
11011
  { label: "\u2190 Back", value: "__back__", key: "__back__" }
10330
11012
  ];
10331
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10332
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
10333
- /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
10334
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10335
- SelectInput6,
11013
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11014
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Delete LSP Server" }),
11015
+ /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, dimColor: false, children: "Select a server to remove from config." }),
11016
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11017
+ SelectInput7,
10336
11018
  {
10337
11019
  items,
10338
11020
  onSelect: (item) => {
@@ -10348,15 +11030,15 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
10348
11030
  }
10349
11031
  if (page === "list") {
10350
11032
  const keys = Object.keys(servers);
10351
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10352
- /* @__PURE__ */ jsx17(Text16, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
10353
- keys.length === 0 ? /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: "No servers configured." }) : /* @__PURE__ */ jsx17(Box15, { marginTop: 1, flexDirection: "column", children: keys.map((k) => {
11033
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11034
+ /* @__PURE__ */ jsx18(Text17, { color: theme.accent, bold: true, children: "Configured LSP Servers" }),
11035
+ keys.length === 0 ? /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: "No servers configured." }) : /* @__PURE__ */ jsx18(Box16, { marginTop: 1, flexDirection: "column", children: keys.map((k) => {
10354
11036
  const s = servers[k];
10355
11037
  const status = s.enabled !== false ? "enabled" : "disabled";
10356
- return /* @__PURE__ */ jsx17(Text16, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
11038
+ return /* @__PURE__ */ jsx18(Text17, { color: theme.info.color, children: ` ${k.padEnd(16)} ${status} ${s.command.join(" ")}` }, k);
10357
11039
  }) }),
10358
- /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(
10359
- SelectInput6,
11040
+ /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
11041
+ SelectInput7,
10360
11042
  {
10361
11043
  items: [{ label: "\u2190 Back", value: "__back__", key: "__back__" }],
10362
11044
  onSelect: () => setPage("main")
@@ -10482,9 +11164,9 @@ var init_lsp_wizard = __esm({
10482
11164
  });
10483
11165
 
10484
11166
  // src/ui/theme-picker.tsx
10485
- import { Box as Box16, Text as Text17 } from "ink";
10486
- import SelectInput7 from "ink-select-input";
10487
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
11167
+ import { Box as Box17, Text as Text18 } from "ink";
11168
+ import SelectInput8 from "ink-select-input";
11169
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
10488
11170
  function PaletteSwatches({ palette }) {
10489
11171
  const colors = [
10490
11172
  palette.primary,
@@ -10492,7 +11174,7 @@ function PaletteSwatches({ palette }) {
10492
11174
  palette.success,
10493
11175
  palette.error
10494
11176
  ];
10495
- return /* @__PURE__ */ jsx18(Box16, { children: colors.map((c, i) => /* @__PURE__ */ jsx18(Text17, { color: c, children: "\u2588" }, i)) });
11177
+ return /* @__PURE__ */ jsx19(Box17, { children: colors.map((c, i) => /* @__PURE__ */ jsx19(Text18, { color: c, children: "\u2588" }, i)) });
10496
11178
  }
10497
11179
  function ThemePicker({ themes, onPick, onPreview }) {
10498
11180
  const current = useTheme();
@@ -10500,10 +11182,10 @@ function ThemePicker({ themes, onPick, onPreview }) {
10500
11182
  ...themes.map((t) => ({ label: t.label, value: t.name })),
10501
11183
  { label: "< Back", value: "__back__" }
10502
11184
  ];
10503
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
10504
- /* @__PURE__ */ jsx18(Text17, { color: current.accent, bold: true, children: "Pick a theme" }),
10505
- /* @__PURE__ */ jsx18(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx18(
10506
- SelectInput7,
11185
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: current.accent, paddingX: 1, children: [
11186
+ /* @__PURE__ */ jsx19(Text18, { color: current.accent, bold: true, children: "Pick a theme" }),
11187
+ /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(
11188
+ SelectInput8,
10507
11189
  {
10508
11190
  items,
10509
11191
  onHighlight: (item) => {
@@ -10522,9 +11204,9 @@ function ThemePicker({ themes, onPick, onPreview }) {
10522
11204
  itemComponent: ({ label, isSelected }) => {
10523
11205
  const t = themes.find((x) => x.label === label);
10524
11206
  const color = t?.accent ?? current.accent;
10525
- return /* @__PURE__ */ jsxs16(Box16, { children: [
10526
- /* @__PURE__ */ jsx18(Text17, { color, bold: isSelected, dimColor: !isSelected, children: label }),
10527
- t && /* @__PURE__ */ jsx18(Box16, { marginLeft: 1, children: /* @__PURE__ */ jsx18(PaletteSwatches, { palette: t.palette }) })
11207
+ return /* @__PURE__ */ jsxs17(Box17, { children: [
11208
+ /* @__PURE__ */ jsx19(Text18, { color, bold: isSelected, dimColor: !isSelected, children: label }),
11209
+ t && /* @__PURE__ */ jsx19(Box17, { marginLeft: 1, children: /* @__PURE__ */ jsx19(PaletteSwatches, { palette: t.palette }) })
10528
11210
  ] });
10529
11211
  }
10530
11212
  }
@@ -10668,8 +11350,8 @@ var init_lsp_nudge = __esm({
10668
11350
  });
10669
11351
 
10670
11352
  // src/ui/file-picker.tsx
10671
- import { Box as Box17, Text as Text18 } from "ink";
10672
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
11353
+ import { Box as Box18, Text as Text19 } from "ink";
11354
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
10673
11355
  function FilePicker({ items, selectedIndex, query }) {
10674
11356
  const theme = useTheme();
10675
11357
  let startIndex = 0;
@@ -10679,12 +11361,12 @@ function FilePicker({ items, selectedIndex, query }) {
10679
11361
  const visible = items.slice(startIndex, startIndex + VISIBLE_LIMIT);
10680
11362
  const hasMoreAbove = startIndex > 0;
10681
11363
  const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT;
10682
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10683
- /* @__PURE__ */ jsx19(Text18, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
10684
- /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
10685
- /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, flexDirection: "column", children: [
10686
- visible.length === 0 && /* @__PURE__ */ jsx19(Text18, { color: theme.info.color, children: "No matches" }),
10687
- hasMoreAbove && /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, children: [
11364
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11365
+ /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: query ? `Files matching "${query}"` : "Mention a file" }),
11366
+ /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
11367
+ /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
11368
+ visible.length === 0 && /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "No matches" }),
11369
+ hasMoreAbove && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
10688
11370
  "\u2026 ",
10689
11371
  startIndex,
10690
11372
  " more above"
@@ -10693,12 +11375,12 @@ function FilePicker({ items, selectedIndex, query }) {
10693
11375
  const actualIndex = startIndex + i;
10694
11376
  const isSelected = actualIndex === selectedIndex;
10695
11377
  const label = item.isDirectory ? `${item.name}/` : item.name;
10696
- return /* @__PURE__ */ jsxs17(Text18, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
11378
+ return /* @__PURE__ */ jsxs18(Text19, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
10697
11379
  isSelected ? "\u203A " : " ",
10698
11380
  label
10699
11381
  ] }, item.name);
10700
11382
  }),
10701
- hasMoreBelow && /* @__PURE__ */ jsxs17(Text18, { color: theme.info.color, children: [
11383
+ hasMoreBelow && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
10702
11384
  "\u2026 ",
10703
11385
  items.length - (startIndex + VISIBLE_LIMIT),
10704
11386
  " more below"
@@ -10716,8 +11398,8 @@ var init_file_picker = __esm({
10716
11398
  });
10717
11399
 
10718
11400
  // src/ui/slash-picker.tsx
10719
- import { Box as Box18, Text as Text19 } from "ink";
10720
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
11401
+ import { Box as Box19, Text as Text20 } from "ink";
11402
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
10721
11403
  function sourceBadge(source) {
10722
11404
  if (source === "builtin") return "";
10723
11405
  if (source === "project") return "project";
@@ -10737,12 +11419,12 @@ function SlashPicker({ items, selectedIndex, query }) {
10737
11419
  const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT2;
10738
11420
  const longestLabel = visible.reduce((m, it) => Math.max(m, commandLabel(it).length), 0);
10739
11421
  const nameColWidth = Math.max(NAME_COL_MIN_WIDTH, longestLabel + NAME_DESC_GAP);
10740
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
10741
- /* @__PURE__ */ jsx20(Text19, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
10742
- /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
10743
- /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
10744
- visible.length === 0 && /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, children: "No matches" }),
10745
- hasMoreAbove && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
11422
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
11423
+ /* @__PURE__ */ jsx21(Text20, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
11424
+ /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
11425
+ /* @__PURE__ */ jsxs19(Box19, { marginTop: 1, flexDirection: "column", children: [
11426
+ visible.length === 0 && /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: "No matches" }),
11427
+ hasMoreAbove && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
10746
11428
  "\u2026 ",
10747
11429
  startIndex,
10748
11430
  " more above"
@@ -10752,16 +11434,16 @@ function SlashPicker({ items, selectedIndex, query }) {
10752
11434
  const isSelected = actualIndex === selectedIndex;
10753
11435
  const nameCol = commandLabel(item).padEnd(nameColWidth);
10754
11436
  const badge = sourceBadge(item.source);
10755
- return /* @__PURE__ */ jsxs18(Text19, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
11437
+ return /* @__PURE__ */ jsxs19(Text20, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
10756
11438
  isSelected ? "\u203A " : " ",
10757
11439
  nameCol,
10758
- /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
11440
+ /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
10759
11441
  item.description,
10760
11442
  badge && ` [${badge}]`
10761
11443
  ] })
10762
11444
  ] }, item.name);
10763
11445
  }),
10764
- hasMoreBelow && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, children: [
11446
+ hasMoreBelow && /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
10765
11447
  "\u2026 ",
10766
11448
  items.length - (startIndex + VISIBLE_LIMIT2),
10767
11449
  " more below"
@@ -10841,15 +11523,15 @@ var tui_report_exports = {};
10841
11523
  __export(tui_report_exports, {
10842
11524
  getCategoryReportText: () => getCategoryReportText
10843
11525
  });
10844
- import { readFile as readFile14 } from "fs/promises";
10845
- import { join as join16 } from "path";
10846
- import { homedir as homedir12 } from "os";
11526
+ import { readFile as readFile15 } from "fs/promises";
11527
+ import { join as join18 } from "path";
11528
+ import { homedir as homedir13 } from "os";
10847
11529
  function usageDir3() {
10848
- const xdg = process.env.XDG_DATA_HOME || join16(homedir12(), ".local", "share");
10849
- return join16(xdg, "kimiflare");
11530
+ const xdg = process.env.XDG_DATA_HOME || join18(homedir13(), ".local", "share");
11531
+ return join18(xdg, "kimiflare");
10850
11532
  }
10851
11533
  function usagePath3() {
10852
- return join16(usageDir3(), "usage.json");
11534
+ return join18(usageDir3(), "usage.json");
10853
11535
  }
10854
11536
  function today3() {
10855
11537
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -10861,7 +11543,7 @@ function daysAgo2(n) {
10861
11543
  }
10862
11544
  async function loadLog3() {
10863
11545
  try {
10864
- const raw = await readFile14(usagePath3(), "utf8");
11546
+ const raw = await readFile15(usagePath3(), "utf8");
10865
11547
  return JSON.parse(raw);
10866
11548
  } catch {
10867
11549
  return { version: 1, days: [], sessions: [] };
@@ -10927,17 +11609,18 @@ __export(app_exports, {
10927
11609
  shouldOpenMentionPicker: () => shouldOpenMentionPicker,
10928
11610
  shouldOpenSlashPicker: () => shouldOpenSlashPicker
10929
11611
  });
10930
- import React13, { useState as useState9, useRef as useRef3, useEffect as useEffect4, useCallback } from "react";
10931
- import { Box as Box19, Text as Text20, useApp, useInput as useInput5, render } from "ink";
10932
- import SelectInput8 from "ink-select-input";
11612
+ import React14, { useState as useState10, useRef as useRef3, useEffect as useEffect5, useCallback } from "react";
11613
+ import { Box as Box20, Text as Text21, useApp, useInput as useInput6, render } from "ink";
11614
+ import SelectInput9 from "ink-select-input";
10933
11615
  import { existsSync as existsSync2, statSync as statSync3 } from "fs";
10934
- import { join as join17 } from "path";
11616
+ import { join as join19 } from "path";
10935
11617
  import { unlink as unlink3 } from "fs/promises";
11618
+ import { execSync as execSync2 } from "child_process";
10936
11619
  import { spawn as spawn4 } from "child_process";
10937
11620
  import { platform as platform2 } from "os";
10938
11621
  import fg4 from "fast-glob";
10939
11622
  import { readFileSync as readFileSync3 } from "fs";
10940
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
11623
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
10941
11624
  function buildFilePickerIgnoreList(cwd) {
10942
11625
  const hardcoded = [
10943
11626
  // Dependencies
@@ -11008,7 +11691,7 @@ function buildFilePickerIgnoreList(cwd) {
11008
11691
  ];
11009
11692
  const gitignorePatterns = [];
11010
11693
  try {
11011
- const gitignorePath = join17(cwd, ".gitignore");
11694
+ const gitignorePath = join19(cwd, ".gitignore");
11012
11695
  const stats = statSync3(gitignorePath);
11013
11696
  if (stats.size > MAX_GITIGNORE_SIZE) {
11014
11697
  return hardcoded;
@@ -11082,6 +11765,26 @@ function openBrowser(url) {
11082
11765
  const child = spawn4(cmd, [url], { detached: true, stdio: "ignore" });
11083
11766
  child.unref();
11084
11767
  }
11768
+ function detectGitHubRepo(cachedRepo) {
11769
+ if (cachedRepo) {
11770
+ const parts = cachedRepo.split("/");
11771
+ if (parts.length === 2) return { owner: parts[0], name: parts[1] };
11772
+ }
11773
+ try {
11774
+ const remoteUrl = execSync2("git remote get-url origin", { cwd: process.cwd(), encoding: "utf8" }).trim();
11775
+ const httpsMatch = remoteUrl.match(/github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
11776
+ if (httpsMatch) return { owner: httpsMatch[1], name: httpsMatch[2] };
11777
+ const sshMatch = remoteUrl.match(/github\.com:([^\/]+)\/([^\/]+?)(?:\.git)?$/);
11778
+ if (sshMatch) return { owner: sshMatch[1], name: sshMatch[2] };
11779
+ } catch {
11780
+ }
11781
+ return null;
11782
+ }
11783
+ function formatTokens3(n) {
11784
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
11785
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
11786
+ return String(n);
11787
+ }
11085
11788
  function capEvents(prev) {
11086
11789
  if (prev.length <= MAX_EVENTS) return prev;
11087
11790
  return prev.slice(prev.length - MAX_EVENTS);
@@ -11144,10 +11847,10 @@ function App({
11144
11847
  initialLspProjectPath
11145
11848
  }) {
11146
11849
  const { exit } = useApp();
11147
- const [cfg, setCfg] = useState9(initialCfg);
11148
- const [lspScope, setLspScope] = useState9(initialLspScope);
11149
- const [lspProjectPath, setLspProjectPath] = useState9(initialLspProjectPath);
11150
- const [events, setRawEvents] = useState9([]);
11850
+ const [cfg, setCfg] = useState10(initialCfg);
11851
+ const [lspScope, setLspScope] = useState10(initialLspScope);
11852
+ const [lspProjectPath, setLspProjectPath] = useState10(initialLspProjectPath);
11853
+ const [events, setRawEvents] = useState10([]);
11151
11854
  const setEvents = useCallback(
11152
11855
  (updater) => {
11153
11856
  setRawEvents((prev) => {
@@ -11157,45 +11860,47 @@ function App({
11157
11860
  },
11158
11861
  []
11159
11862
  );
11160
- const [input, setInput] = useState9("");
11161
- const [busy, setBusy] = useState9(false);
11162
- const [usage, setUsage] = useState9(null);
11163
- const [sessionUsage, setSessionUsage] = useState9(null);
11164
- const [gatewayMeta, setGatewayMeta] = useState9(null);
11165
- const [showReasoning, setShowReasoning] = useState9(false);
11166
- const [perm, setPerm] = useState9(null);
11167
- const [queue, setQueue] = useState9([]);
11168
- const [history, setHistory] = useState9([]);
11169
- const [historyIndex, setHistoryIndex] = useState9(-1);
11170
- const [draftInput, setDraftInput] = useState9("");
11171
- const [mode, setMode] = useState9("edit");
11172
- const [codeMode, setCodeMode] = useState9(initialCfg?.codeMode ?? false);
11863
+ const [input, setInput] = useState10("");
11864
+ const [busy, setBusy] = useState10(false);
11865
+ const [usage, setUsage] = useState10(null);
11866
+ const [sessionUsage, setSessionUsage] = useState10(null);
11867
+ const [gatewayMeta, setGatewayMeta] = useState10(null);
11868
+ const [showReasoning, setShowReasoning] = useState10(false);
11869
+ const [perm, setPerm] = useState10(null);
11870
+ const [queue, setQueue] = useState10([]);
11871
+ const [history, setHistory] = useState10([]);
11872
+ const [historyIndex, setHistoryIndex] = useState10(-1);
11873
+ const [draftInput, setDraftInput] = useState10("");
11874
+ const [mode, setMode] = useState10("edit");
11875
+ const [codeMode, setCodeMode] = useState10(false);
11173
11876
  const filePickerEnabled = initialCfg?.filePicker ?? true;
11174
- const [effort, setEffort] = useState9(
11877
+ const [effort, setEffort] = useState10(
11175
11878
  initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
11176
11879
  );
11177
- const [resumeSessions, setResumeSessions] = useState9(null);
11178
- const [showHelpMenu, setShowHelpMenu] = useState9(false);
11179
- const [commandWizard, setCommandWizard] = useState9(null);
11180
- const [commandPicker, setCommandPicker] = useState9(null);
11181
- const [commandToDelete, setCommandToDelete] = useState9(null);
11182
- const [showCommandList, setShowCommandList] = useState9(false);
11183
- const [showLspWizard, setShowLspWizard] = useState9(false);
11184
- const [tasks, setTasks] = useState9([]);
11185
- const [tasksStartedAt, setTasksStartedAt] = useState9(null);
11186
- const [tasksStartTokens, setTasksStartTokens] = useState9(0);
11187
- const [turnStartedAt, setTurnStartedAt] = useState9(null);
11188
- const [verbose, setVerbose] = useState9(false);
11189
- const [hasUpdate, setHasUpdate] = useState9(initialUpdateResult?.hasUpdate ?? false);
11190
- const [latestVersion, setLatestVersion] = useState9(initialUpdateResult?.latestVersion ?? null);
11191
- const [theme, setTheme] = useState9(resolveTheme(initialCfg?.theme));
11192
- const [showThemePicker, setShowThemePicker] = useState9(false);
11193
- const [originalTheme, setOriginalTheme] = useState9(null);
11194
- const [cursorOffset, setCursorOffset] = useState9(0);
11195
- const [activePicker, setActivePicker] = useState9(null);
11196
- const [filePickerItems, setFilePickerItems] = useState9([]);
11880
+ const [resumeSessions, setResumeSessions] = useState10(null);
11881
+ const [showHelpMenu, setShowHelpMenu] = useState10(false);
11882
+ const [commandWizard, setCommandWizard] = useState10(null);
11883
+ const [commandPicker, setCommandPicker] = useState10(null);
11884
+ const [commandToDelete, setCommandToDelete] = useState10(null);
11885
+ const [showCommandList, setShowCommandList] = useState10(false);
11886
+ const [showLspWizard, setShowLspWizard] = useState10(false);
11887
+ const [showRemoteDashboard, setShowRemoteDashboard] = useState10(false);
11888
+ const [selectedRemoteSession, setSelectedRemoteSession] = useState10(null);
11889
+ const [tasks, setTasks] = useState10([]);
11890
+ const [tasksStartedAt, setTasksStartedAt] = useState10(null);
11891
+ const [tasksStartTokens, setTasksStartTokens] = useState10(0);
11892
+ const [turnStartedAt, setTurnStartedAt] = useState10(null);
11893
+ const [verbose, setVerbose] = useState10(false);
11894
+ const [hasUpdate, setHasUpdate] = useState10(initialUpdateResult?.hasUpdate ?? false);
11895
+ const [latestVersion, setLatestVersion] = useState10(initialUpdateResult?.latestVersion ?? null);
11896
+ const [theme, setTheme] = useState10(resolveTheme(initialCfg?.theme));
11897
+ const [showThemePicker, setShowThemePicker] = useState10(false);
11898
+ const [originalTheme, setOriginalTheme] = useState10(null);
11899
+ const [cursorOffset, setCursorOffset] = useState10(0);
11900
+ const [activePicker, setActivePicker] = useState10(null);
11901
+ const [filePickerItems, setFilePickerItems] = useState10([]);
11197
11902
  const filePickerLoadedRef = useRef3(false);
11198
- const [customCommandsVersion, setCustomCommandsVersion] = useState9(0);
11903
+ const [customCommandsVersion, setCustomCommandsVersion] = useState10(0);
11199
11904
  const cacheStableRef = useRef3(initialCfg?.cacheStablePrompts !== false);
11200
11905
  const messagesRef = useRef3(
11201
11906
  makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
@@ -11233,15 +11938,15 @@ function App({
11233
11938
  const pickerCancelRef = useRef3(null);
11234
11939
  const pickerAnchor = activePicker?.anchor ?? null;
11235
11940
  const pickerKind = activePicker?.kind ?? null;
11236
- const pickerQuery = React13.useMemo(() => {
11941
+ const pickerQuery = React14.useMemo(() => {
11237
11942
  if (pickerAnchor === null) return null;
11238
11943
  return input.slice(pickerAnchor + 1, cursorOffset);
11239
11944
  }, [input, cursorOffset, pickerAnchor]);
11240
- const filteredFileItems = React13.useMemo(() => {
11945
+ const filteredFileItems = React14.useMemo(() => {
11241
11946
  if (pickerKind !== "file" || pickerQuery === null) return [];
11242
11947
  return filterPickerItems(filePickerItems, pickerQuery);
11243
11948
  }, [pickerKind, filePickerItems, pickerQuery]);
11244
- const allSlashCommands = React13.useMemo(() => {
11949
+ const allSlashCommands = React14.useMemo(() => {
11245
11950
  const customs = customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({
11246
11951
  name: c.name,
11247
11952
  description: c.description ?? "",
@@ -11249,11 +11954,11 @@ function App({
11249
11954
  }));
11250
11955
  return [...BUILTIN_COMMANDS, ...customs];
11251
11956
  }, [customCommandsVersion]);
11252
- const filteredSlashItems = React13.useMemo(() => {
11957
+ const filteredSlashItems = React14.useMemo(() => {
11253
11958
  if (pickerKind !== "slash" || pickerQuery === null) return [];
11254
11959
  return fuzzyFilter(allSlashCommands, pickerQuery, (c) => c.name).slice(0, 50);
11255
11960
  }, [pickerKind, allSlashCommands, pickerQuery]);
11256
- useEffect4(() => {
11961
+ useEffect5(() => {
11257
11962
  if (activePicker !== null) {
11258
11963
  const trigger = activePicker.kind === "file" ? "@" : "/";
11259
11964
  if (cursorOffset < activePicker.anchor) {
@@ -11310,14 +12015,14 @@ function App({
11310
12015
  return;
11311
12016
  }
11312
12017
  }, [input, cursorOffset, activePicker, filePickerEnabled]);
11313
- useEffect4(() => {
12018
+ useEffect5(() => {
11314
12019
  if (activePicker?.kind !== "file") return;
11315
12020
  const max = Math.max(0, filteredFileItems.length - 1);
11316
12021
  if (activePicker.selected > max) {
11317
12022
  setActivePicker({ ...activePicker, selected: max });
11318
12023
  }
11319
12024
  }, [filteredFileItems.length, activePicker]);
11320
- useEffect4(() => {
12025
+ useEffect5(() => {
11321
12026
  if (activePicker?.kind !== "slash") return;
11322
12027
  const max = Math.max(0, filteredSlashItems.length - 1);
11323
12028
  if (activePicker.selected > max) {
@@ -11361,7 +12066,7 @@ function App({
11361
12066
  pickerCancelRef.current = cursorOffset;
11362
12067
  setActivePicker(null);
11363
12068
  }, [cursorOffset]);
11364
- useEffect4(() => {
12069
+ useEffect5(() => {
11365
12070
  const modalActive = showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null;
11366
12071
  if (modalActive && activePicker !== null) {
11367
12072
  setActivePicker(null);
@@ -11377,7 +12082,7 @@ function App({
11377
12082
  perm,
11378
12083
  activePicker
11379
12084
  ]);
11380
- useEffect4(() => {
12085
+ useEffect5(() => {
11381
12086
  if (!cfg) return;
11382
12087
  void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
11383
12088
  ({ pruneSessions: pruneSessions2 }) => pruneSessions2().then((removed) => {
@@ -11403,7 +12108,7 @@ function App({
11403
12108
  }
11404
12109
  });
11405
12110
  if (cfg.memoryEnabled) {
11406
- const dbPath = cfg.memoryDbPath ?? join17(process.cwd(), ".kimiflare", "memory.db");
12111
+ const dbPath = cfg.memoryDbPath ?? join19(process.cwd(), ".kimiflare", "memory.db");
11407
12112
  const manager = new MemoryManager({
11408
12113
  dbPath,
11409
12114
  accountId: cfg.accountId,
@@ -11470,7 +12175,7 @@ function App({
11470
12175
  }
11471
12176
  });
11472
12177
  }, [cfg, setEvents]);
11473
- useEffect4(() => {
12178
+ useEffect5(() => {
11474
12179
  const id = setInterval(() => {
11475
12180
  try {
11476
12181
  performance.clearMarks();
@@ -11495,7 +12200,7 @@ function App({
11495
12200
  ]);
11496
12201
  }
11497
12202
  }, [setEvents]);
11498
- useEffect4(() => {
12203
+ useEffect5(() => {
11499
12204
  if (!cfg || updateCheckedRef.current) return;
11500
12205
  updateCheckedRef.current = true;
11501
12206
  if (initialUpdateResult) {
@@ -11546,7 +12251,7 @@ function App({
11546
12251
  }
11547
12252
  });
11548
12253
  }, [cfg, initialUpdateResult]);
11549
- useEffect4(() => {
12254
+ useEffect5(() => {
11550
12255
  modeRef.current = mode;
11551
12256
  if (cacheStableRef.current) {
11552
12257
  messagesRef.current[1] = {
@@ -11573,10 +12278,10 @@ function App({
11573
12278
  executorRef.current.clearSessionPermissions();
11574
12279
  }
11575
12280
  }, [mode, cfg?.model]);
11576
- useEffect4(() => {
12281
+ useEffect5(() => {
11577
12282
  effortRef.current = effort;
11578
12283
  }, [effort]);
11579
- useEffect4(() => {
12284
+ useEffect5(() => {
11580
12285
  if (!cfg) return;
11581
12286
  const id = setInterval(() => {
11582
12287
  void checkForUpdate().then((result) => {
@@ -11731,7 +12436,7 @@ function App({
11731
12436
  ]);
11732
12437
  }
11733
12438
  }, [cfg]);
11734
- useEffect4(() => {
12439
+ useEffect5(() => {
11735
12440
  if (cfg && !mcpInitRef.current) {
11736
12441
  void initMcp();
11737
12442
  }
@@ -11769,7 +12474,85 @@ function App({
11769
12474
  } catch {
11770
12475
  }
11771
12476
  }, [cfg, ensureSessionId]);
11772
- useInput5((inputChar, key) => {
12477
+ const onIterationEnd = useCallback(
12478
+ async (messages, signal) => {
12479
+ if (signal.aborted) return messages;
12480
+ if (!shouldCompact({ messages })) return messages;
12481
+ if (compiledContextRef.current) {
12482
+ const store = artifactStoreRef.current;
12483
+ const result = compactMessages2({
12484
+ messages,
12485
+ state: sessionStateRef.current,
12486
+ store
12487
+ });
12488
+ if (result.metrics.rawTurnsRemoved > 0) {
12489
+ sessionStateRef.current = result.newState;
12490
+ setEvents((e) => [
12491
+ ...e,
12492
+ {
12493
+ kind: "info",
12494
+ key: mkKey(),
12495
+ text: `auto-compacted: ${result.metrics.estimatedTokensBefore} \u2192 ${result.metrics.estimatedTokensAfter} tokens (${result.metrics.archivedArtifacts} artifacts)`
12496
+ }
12497
+ ]);
12498
+ await saveSessionSafe();
12499
+ }
12500
+ const manager = memoryManagerRef.current;
12501
+ if (manager && !signal.aborted) {
12502
+ try {
12503
+ const cwd = process.cwd();
12504
+ const queryText = sessionStateRef.current.task || cwd;
12505
+ const results = await manager.recall({ text: queryText, repoPath: cwd, limit: 5 });
12506
+ if (results.length > 0 && !signal.aborted) {
12507
+ const text = await manager.synthesizeRecalled(results);
12508
+ const lastSystemIdx = result.newMessages.findLastIndex((m) => m.role === "system");
12509
+ const insertIdx = lastSystemIdx >= 0 ? lastSystemIdx + 1 : result.newMessages.length;
12510
+ result.newMessages.splice(insertIdx, 0, { role: "system", content: text });
12511
+ setEvents((e) => [
12512
+ ...e,
12513
+ {
12514
+ kind: "memory",
12515
+ key: mkKey(),
12516
+ text: `recalled ${results.length} memory${results.length === 1 ? "" : "ies"} after compaction`
12517
+ }
12518
+ ]);
12519
+ await saveSessionSafe();
12520
+ }
12521
+ } catch {
12522
+ }
12523
+ }
12524
+ return result.newMessages;
12525
+ }
12526
+ if (cfg && !signal.aborted) {
12527
+ try {
12528
+ const result = await compactMessages({
12529
+ accountId: cfg.accountId,
12530
+ apiToken: cfg.apiToken,
12531
+ model: cfg.model,
12532
+ messages,
12533
+ signal,
12534
+ gateway: gatewayFromConfig(cfg)
12535
+ });
12536
+ if (result.replacedCount > 0) {
12537
+ setEvents((e) => [
12538
+ ...e,
12539
+ {
12540
+ kind: "info",
12541
+ key: mkKey(),
12542
+ text: `auto-compacted: ${result.replacedCount} messages summarized`
12543
+ }
12544
+ ]);
12545
+ await saveSessionSafe();
12546
+ }
12547
+ return result.newMessages;
12548
+ } catch {
12549
+ }
12550
+ }
12551
+ return messages;
12552
+ },
12553
+ [cfg]
12554
+ );
12555
+ useInput6((inputChar, key) => {
11773
12556
  if (key.ctrl && inputChar === "c") {
11774
12557
  const hadPerm = permResolveRef.current !== null;
11775
12558
  if (hadPerm) {
@@ -11812,10 +12595,6 @@ function App({
11812
12595
  setVerbose((v) => !v);
11813
12596
  return;
11814
12597
  }
11815
- if (key.ctrl && inputChar === "m") {
11816
- setCodeMode((c) => !c);
11817
- return;
11818
- }
11819
12598
  });
11820
12599
  const flushAssistantUpdates = useCallback(() => {
11821
12600
  flushTimeoutRef.current = null;
@@ -11967,7 +12746,7 @@ function App({
11967
12746
  }
11968
12747
  }, [cfg, busy, saveSessionSafe]);
11969
12748
  const openResumePicker = useCallback(async () => {
11970
- const sessions = await listSessions(200);
12749
+ const sessions = await listSessions(200, process.cwd());
11971
12750
  setResumeSessions(sessions);
11972
12751
  }, []);
11973
12752
  const runInit = useCallback(async () => {
@@ -11977,7 +12756,7 @@ function App({
11977
12756
  return;
11978
12757
  }
11979
12758
  const cwd = process.cwd();
11980
- const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(join17(cwd, n)));
12759
+ const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find((n) => existsSync2(join19(cwd, n)));
11981
12760
  const isRefresh = existingName !== void 0;
11982
12761
  const promptParts = [
11983
12762
  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.",
@@ -12002,6 +12781,15 @@ function App({
12002
12781
  setTurnStartedAt(Date.now());
12003
12782
  const controller = new AbortController();
12004
12783
  activeControllerRef.current = controller;
12784
+ const initClassification = classifyIntent(prompt);
12785
+ const initEffortForTier = {
12786
+ light: "low",
12787
+ medium: "medium",
12788
+ heavy: "high"
12789
+ };
12790
+ const initReasoningEffort = initEffortForTier[initClassification.tier] ?? effortRef.current;
12791
+ const effectiveCodeMode = initClassification.tier === "heavy";
12792
+ setCodeMode(effectiveCodeMode);
12005
12793
  try {
12006
12794
  await runAgentTurn({
12007
12795
  accountId: cfg.accountId,
@@ -12013,17 +12801,21 @@ function App({
12013
12801
  executor: executorRef.current,
12014
12802
  cwd,
12015
12803
  signal: controller.signal,
12016
- reasoningEffort: effortRef.current,
12804
+ reasoningEffort: initReasoningEffort,
12805
+ intentClassification: initClassification,
12017
12806
  coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
12018
12807
  sessionId: ensureSessionId(),
12019
12808
  memoryManager: memoryManagerRef.current,
12020
- codeMode,
12809
+ codeMode: effectiveCodeMode,
12810
+ maxInputTokens: effectiveCodeMode ? 2e5 : void 0,
12811
+ continueOnLimit: effectiveCodeMode ? true : void 0,
12812
+ onIterationEnd,
12021
12813
  onFileChange: (path, content) => {
12022
12814
  if (content) {
12023
12815
  lspManagerRef.current.notifyChange(path, content);
12024
12816
  } else {
12025
12817
  void import("fs/promises").then(
12026
- ({ readFile: readFile15 }) => readFile15(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
12818
+ ({ readFile: readFile16 }) => readFile16(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
12027
12819
  })
12028
12820
  );
12029
12821
  }
@@ -12117,7 +12909,7 @@ function App({
12117
12909
  })
12118
12910
  }
12119
12911
  });
12120
- if (existsSync2(join17(cwd, "KIMI.md"))) {
12912
+ if (existsSync2(join19(cwd, "KIMI.md"))) {
12121
12913
  if (cacheStableRef.current) {
12122
12914
  messagesRef.current[1] = {
12123
12915
  role: "system",
@@ -12164,6 +12956,7 @@ function App({
12164
12956
  ]);
12165
12957
  }
12166
12958
  } finally {
12959
+ setCodeMode(false);
12167
12960
  const asstId = activeAsstIdRef.current;
12168
12961
  if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
12169
12962
  setBusy(false);
@@ -12774,13 +13567,177 @@ ${lines.join("\n")}` }]);
12774
13567
  ]);
12775
13568
  return true;
12776
13569
  }
13570
+ if (c === "/remote") {
13571
+ if (arg === "status" || arg === "cancel") {
13572
+ setEvents((e) => [
13573
+ ...e,
13574
+ { kind: "info", key: mkKey(), text: `Use \`kimiflare remote ${arg}\` from your shell.` }
13575
+ ]);
13576
+ return true;
13577
+ }
13578
+ const prompt = rest.join(" ").trim();
13579
+ if (!prompt) {
13580
+ setShowRemoteDashboard(true);
13581
+ return true;
13582
+ }
13583
+ const repo = detectGitHubRepo(cfg?.githubRepo);
13584
+ if (!repo) {
13585
+ setEvents((e) => [
13586
+ ...e,
13587
+ { kind: "info", key: mkKey(), text: "Could not detect GitHub repo. Run from a repo with a GitHub remote, or set githubRepo in config." }
13588
+ ]);
13589
+ return true;
13590
+ }
13591
+ (async () => {
13592
+ if (!cfg?.remoteWorkerUrl) {
13593
+ setEvents((e) => [
13594
+ ...e,
13595
+ { kind: "info", key: mkKey(), text: "Remote infrastructure not deployed yet. Setting up now (~2 min)..." }
13596
+ ]);
13597
+ try {
13598
+ for await (const step of deployForTui()) {
13599
+ setEvents((e) => [
13600
+ ...e,
13601
+ { kind: step.error ? "error" : "info", key: mkKey(), text: step.message }
13602
+ ]);
13603
+ if (step.done) break;
13604
+ }
13605
+ } catch {
13606
+ setEvents((e) => [
13607
+ ...e,
13608
+ { kind: "error", key: mkKey(), text: "Deploy failed. Fix the issue above and try /remote again." }
13609
+ ]);
13610
+ return;
13611
+ }
13612
+ const { loadConfig: reloadConfig } = await Promise.resolve().then(() => (init_config(), config_exports));
13613
+ const newCfg = await reloadConfig();
13614
+ if (newCfg) setCfg(newCfg);
13615
+ }
13616
+ const currentCfg = cfg ?? await loadConfig();
13617
+ if (!currentCfg?.remoteWorkerUrl) {
13618
+ setEvents((e) => [
13619
+ ...e,
13620
+ { kind: "error", key: mkKey(), text: "Deploy seemed to succeed but config wasn't saved. Try again." }
13621
+ ]);
13622
+ return;
13623
+ }
13624
+ if (!currentCfg.githubOAuthToken) {
13625
+ setEvents((e) => [
13626
+ ...e,
13627
+ { kind: "info", key: mkKey(), text: "GitHub not authenticated. Starting OAuth device flow..." }
13628
+ ]);
13629
+ try {
13630
+ for await (const step of authGitHubForTui()) {
13631
+ setEvents((e) => [
13632
+ ...e,
13633
+ { kind: step.error ? "error" : "info", key: mkKey(), text: step.message }
13634
+ ]);
13635
+ if (step.done) break;
13636
+ }
13637
+ } catch {
13638
+ setEvents((e) => [
13639
+ ...e,
13640
+ { kind: "error", key: mkKey(), text: "GitHub auth failed. Try `kimiflare auth github` from shell." }
13641
+ ]);
13642
+ return;
13643
+ }
13644
+ const { loadConfig: reloadConfig } = await Promise.resolve().then(() => (init_config(), config_exports));
13645
+ const newCfg = await reloadConfig();
13646
+ if (newCfg) setCfg(newCfg);
13647
+ }
13648
+ const finalCfg = await loadConfig() ?? currentCfg;
13649
+ const ttl = finalCfg.remoteTtlMinutes ?? 30;
13650
+ const budget = finalCfg.remoteMaxInputTokens ?? 5e6;
13651
+ setEvents((e) => [
13652
+ ...e,
13653
+ { kind: "info", key: mkKey(), text: `Starting remote session for ${repo.owner}/${repo.name}...` },
13654
+ { kind: "info", key: mkKey(), text: `Budget: ${formatTokens3(budget)} tokens. TTL: ${ttl} min.` }
13655
+ ]);
13656
+ try {
13657
+ const data = await startRemoteSession({
13658
+ prompt,
13659
+ repo,
13660
+ cfg: finalCfg,
13661
+ ttlMinutes: finalCfg.remoteTtlMinutes,
13662
+ tokensBudget: finalCfg.remoteMaxInputTokens
13663
+ });
13664
+ setEvents((e) => [
13665
+ ...e,
13666
+ { kind: "info", key: mkKey(), text: `Session started: ${data.sessionId}` }
13667
+ ]);
13668
+ for await (const ev of streamRemoteProgress(
13669
+ finalCfg.remoteWorkerUrl,
13670
+ data.sessionId,
13671
+ activeControllerRef.current?.signal
13672
+ )) {
13673
+ const event = ev;
13674
+ if (event.type === "text_delta") {
13675
+ setEvents((e) => [
13676
+ ...e,
13677
+ { kind: "info", key: mkKey(), text: String(event.text ?? "") }
13678
+ ]);
13679
+ } else if (event.type === "tool_call") {
13680
+ setEvents((e) => [
13681
+ ...e,
13682
+ { kind: "info", key: mkKey(), text: `\u2192 ${String(event.name ?? "")}` }
13683
+ ]);
13684
+ } else if (event.type === "done") {
13685
+ const prUrl = event.prUrl;
13686
+ const tokensUsed = event.tokensUsed;
13687
+ const tokensBudget = event.tokensBudget;
13688
+ setEvents((e) => [
13689
+ ...e,
13690
+ { kind: "info", key: mkKey(), text: prUrl ? `Done \u2014 PR: ${prUrl}` : "Done" }
13691
+ ]);
13692
+ await saveRemoteSession({
13693
+ sessionId: data.sessionId,
13694
+ prompt,
13695
+ repo: `${repo.owner}/${repo.name}`,
13696
+ workerUrl: finalCfg.remoteWorkerUrl,
13697
+ status: "done",
13698
+ prUrl,
13699
+ tokensUsed,
13700
+ tokensBudget,
13701
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
13702
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
13703
+ });
13704
+ } else if (event.type === "error") {
13705
+ const message2 = String(event.message ?? "");
13706
+ const category = event.category;
13707
+ setEvents((e) => [
13708
+ ...e,
13709
+ { kind: "error", key: mkKey(), text: `Remote error: ${message2}` }
13710
+ ]);
13711
+ await saveRemoteSession({
13712
+ sessionId: data.sessionId,
13713
+ prompt,
13714
+ repo: `${repo.owner}/${repo.name}`,
13715
+ workerUrl: finalCfg.remoteWorkerUrl,
13716
+ status: "error",
13717
+ errorCategory: category ?? "unknown",
13718
+ errorSummary: message2,
13719
+ errorMessage: message2,
13720
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
13721
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
13722
+ });
13723
+ }
13724
+ }
13725
+ } catch (err) {
13726
+ setEvents((e) => [
13727
+ ...e,
13728
+ { kind: "error", key: mkKey(), text: `Failed: ${err instanceof Error ? err.message : String(err)}` }
13729
+ ]);
13730
+ }
13731
+ })();
13732
+ return true;
13733
+ }
12777
13734
  if (c === "/help") {
12778
13735
  setShowHelpMenu(true);
12779
13736
  return true;
12780
13737
  }
12781
13738
  return false;
12782
13739
  },
12783
- [cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg]
13740
+ [cfg, exit, usage, effort, theme, mode, openResumePicker, runCompact, runInit, initMcp, setCfg, setShowRemoteDashboard, setSelectedRemoteSession]
12784
13741
  );
12785
13742
  const handleHelpCommand = useCallback(
12786
13743
  (command) => {
@@ -12923,6 +13880,15 @@ ${lines.join("\n")}` }]);
12923
13880
  gatewayMetaRef.current = null;
12924
13881
  setGatewayMeta(null);
12925
13882
  setTurnStartedAt(Date.now());
13883
+ const classification = classifyIntent(trimmed);
13884
+ const effortForTier = {
13885
+ light: "low",
13886
+ medium: "medium",
13887
+ heavy: "high"
13888
+ };
13889
+ const turnReasoningEffort = overrideEffort ?? effortForTier[classification.tier] ?? effortRef.current;
13890
+ const effectiveCodeMode = classification.tier === "heavy";
13891
+ setCodeMode(effectiveCodeMode);
12926
13892
  const controller = new AbortController();
12927
13893
  activeControllerRef.current = controller;
12928
13894
  const sharedCallbacks = {
@@ -13036,18 +14002,22 @@ ${lines.join("\n")}` }]);
13036
14002
  executor: executorRef.current,
13037
14003
  cwd: process.cwd(),
13038
14004
  signal: controller.signal,
13039
- reasoningEffort: overrideEffort ?? effortRef.current,
14005
+ reasoningEffort: turnReasoningEffort,
13040
14006
  coauthor: cfg.coauthor !== false ? { name: cfg.coauthorName || "kimiflare", email: cfg.coauthorEmail || "kimiflare@proton.me" } : void 0,
13041
14007
  sessionId: ensureSessionId(),
13042
14008
  memoryManager: memoryManagerRef.current,
13043
14009
  keepLastImageTurns: cfg.imageHistoryTurns ?? 2,
13044
- codeMode,
14010
+ codeMode: effectiveCodeMode,
14011
+ maxInputTokens: effectiveCodeMode ? 2e5 : void 0,
14012
+ continueOnLimit: effectiveCodeMode ? true : void 0,
14013
+ onIterationEnd,
14014
+ intentClassification: classification,
13045
14015
  onFileChange: (path, content2) => {
13046
14016
  if (content2) {
13047
14017
  lspManagerRef.current.notifyChange(path, content2);
13048
14018
  } else {
13049
14019
  void import("fs/promises").then(
13050
- ({ readFile: readFile15 }) => readFile15(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
14020
+ ({ readFile: readFile16 }) => readFile16(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
13051
14021
  })
13052
14022
  );
13053
14023
  }
@@ -13169,6 +14139,7 @@ ${lines.join("\n")}` }]);
13169
14139
  }
13170
14140
  }
13171
14141
  } finally {
14142
+ setCodeMode(false);
13172
14143
  const asstId = activeAsstIdRef.current;
13173
14144
  if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
13174
14145
  setBusy(false);
@@ -13181,7 +14152,7 @@ ${lines.join("\n")}` }]);
13181
14152
  },
13182
14153
  [cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta]
13183
14154
  );
13184
- useEffect4(() => {
14155
+ useEffect5(() => {
13185
14156
  if (!busy && queue.length > 0) {
13186
14157
  const next = queue[0];
13187
14158
  setQueue((q) => q.slice(1));
@@ -13209,7 +14180,7 @@ ${lines.join("\n")}` }]);
13209
14180
  [busy, processMessage]
13210
14181
  );
13211
14182
  submitRef.current = submit;
13212
- useEffect4(() => {
14183
+ useEffect5(() => {
13213
14184
  if (compactSuggestedRef.current) return;
13214
14185
  if (usage && usage.prompt_tokens / CONTEXT_LIMIT >= AUTO_COMPACT_SUGGEST_PCT) {
13215
14186
  compactSuggestedRef.current = true;
@@ -13224,7 +14195,7 @@ ${lines.join("\n")}` }]);
13224
14195
  }
13225
14196
  }, [usage]);
13226
14197
  if (!cfg) {
13227
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsx21(
14198
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(
13228
14199
  Onboarding,
13229
14200
  {
13230
14201
  onDone: (newCfg) => {
@@ -13238,10 +14209,42 @@ ${lines.join("\n")}` }]);
13238
14209
  ) });
13239
14210
  }
13240
14211
  if (resumeSessions !== null) {
13241
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx21(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
14212
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
14213
+ }
14214
+ if (showRemoteDashboard) {
14215
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx22(
14216
+ RemoteSessionDetail,
14217
+ {
14218
+ session: selectedRemoteSession,
14219
+ onBack: () => setSelectedRemoteSession(null),
14220
+ onCancel: async (session) => {
14221
+ try {
14222
+ const { cancelRemoteSession: cancelRemoteSession2 } = await Promise.resolve().then(() => (init_worker_client(), worker_client_exports));
14223
+ await cancelRemoteSession2(session.workerUrl, session.sessionId);
14224
+ setEvents((e) => [
14225
+ ...e,
14226
+ { kind: "info", key: mkKey(), text: `Cancelled session ${session.sessionId}` }
14227
+ ]);
14228
+ } catch (err) {
14229
+ setEvents((e) => [
14230
+ ...e,
14231
+ { kind: "error", key: mkKey(), text: `Failed to cancel: ${err instanceof Error ? err.message : String(err)}` }
14232
+ ]);
14233
+ }
14234
+ setSelectedRemoteSession(null);
14235
+ setShowRemoteDashboard(false);
14236
+ }
14237
+ }
14238
+ ) : /* @__PURE__ */ jsx22(
14239
+ RemoteDashboard,
14240
+ {
14241
+ onSelect: (session) => setSelectedRemoteSession(session),
14242
+ onCancel: () => setShowRemoteDashboard(false)
14243
+ }
14244
+ ) }) });
13242
14245
  }
13243
14246
  if (showHelpMenu) {
13244
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx21(
14247
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
13245
14248
  HelpMenu,
13246
14249
  {
13247
14250
  customCommands: customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({ name: c.name, description: c.description })),
@@ -13252,12 +14255,12 @@ ${lines.join("\n")}` }]);
13252
14255
  ) }) });
13253
14256
  }
13254
14257
  if (showLspWizard) {
13255
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx21(
14258
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
13256
14259
  LspWizard,
13257
14260
  {
13258
14261
  servers: cfg?.lspServers ?? {},
13259
14262
  currentScope: lspScope,
13260
- hasProjectDir: existsSync2(join17(process.cwd(), ".kimiflare")),
14263
+ hasProjectDir: existsSync2(join19(process.cwd(), ".kimiflare")),
13261
14264
  onDone: () => setShowLspWizard(false),
13262
14265
  onSave: (servers, enabled, scope) => {
13263
14266
  setCfg((c) => c ? { ...c, lspEnabled: enabled, lspServers: servers } : c);
@@ -13289,7 +14292,7 @@ ${lines.join("\n")}` }]);
13289
14292
  ) }) });
13290
14293
  }
13291
14294
  if (commandWizard) {
13292
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx21(
14295
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
13293
14296
  CommandWizard,
13294
14297
  {
13295
14298
  mode: commandWizard.mode,
@@ -13302,7 +14305,7 @@ ${lines.join("\n")}` }]);
13302
14305
  ) }) });
13303
14306
  }
13304
14307
  if (commandPicker) {
13305
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx21(
14308
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
13306
14309
  CommandPicker,
13307
14310
  {
13308
14311
  commands: customCommandsRef.current,
@@ -13320,15 +14323,15 @@ ${lines.join("\n")}` }]);
13320
14323
  ) }) });
13321
14324
  }
13322
14325
  if (commandToDelete) {
13323
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
13324
- /* @__PURE__ */ jsxs19(Text20, { color: theme.accent, bold: true, children: [
14326
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
14327
+ /* @__PURE__ */ jsxs20(Text21, { color: theme.accent, bold: true, children: [
13325
14328
  "Delete /",
13326
14329
  commandToDelete.name,
13327
14330
  "?"
13328
14331
  ] }),
13329
- /* @__PURE__ */ jsx21(Text20, { color: theme.info.color, children: commandToDelete.filepath }),
13330
- /* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(
13331
- SelectInput8,
14332
+ /* @__PURE__ */ jsx22(Text21, { color: theme.info.color, children: commandToDelete.filepath }),
14333
+ /* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(
14334
+ SelectInput9,
13332
14335
  {
13333
14336
  items: [
13334
14337
  { label: "Yes, delete", value: "yes", key: "yes" },
@@ -13346,7 +14349,7 @@ ${lines.join("\n")}` }]);
13346
14349
  ] }) });
13347
14350
  }
13348
14351
  if (showCommandList) {
13349
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx21(
14352
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
13350
14353
  CommandList,
13351
14354
  {
13352
14355
  commands: customCommandsRef.current,
@@ -13355,12 +14358,12 @@ ${lines.join("\n")}` }]);
13355
14358
  ) }) });
13356
14359
  }
13357
14360
  if (showThemePicker) {
13358
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx21(ThemePicker, { themes: themeList(), onPick: handleThemePick, onPreview: (t) => setTheme(t) }) }) });
14361
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", children: /* @__PURE__ */ jsx22(ThemePicker, { themes: themeList(), onPick: handleThemePick, onPreview: (t) => setTheme(t) }) }) });
13359
14362
  }
13360
14363
  const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
13361
- return /* @__PURE__ */ jsx21(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
13362
- !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx21(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx21(ChatView, { events, showReasoning, verbose }),
13363
- perm ? /* @__PURE__ */ jsx21(
14364
+ return /* @__PURE__ */ jsx22(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
14365
+ !hasConversation && events.length === 0 ? /* @__PURE__ */ jsx22(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx22(ChatView, { events, showReasoning, verbose }),
14366
+ perm ? /* @__PURE__ */ jsx22(
13364
14367
  PermissionModal,
13365
14368
  {
13366
14369
  tool: perm.tool,
@@ -13371,8 +14374,8 @@ ${lines.join("\n")}` }]);
13371
14374
  setPerm(null);
13372
14375
  }
13373
14376
  }
13374
- ) : /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
13375
- tasks.length > 0 && /* @__PURE__ */ jsx21(
14377
+ ) : /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, children: [
14378
+ tasks.length > 0 && /* @__PURE__ */ jsx22(
13376
14379
  TaskList,
13377
14380
  {
13378
14381
  tasks,
@@ -13380,11 +14383,11 @@ ${lines.join("\n")}` }]);
13380
14383
  tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
13381
14384
  }
13382
14385
  ),
13383
- queue.length > 0 && /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs19(Text20, { color: theme.info.color, children: [
14386
+ queue.length > 0 && /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs20(Text21, { color: theme.info.color, children: [
13384
14387
  "\u23F3 ",
13385
14388
  q.display
13386
14389
  ] }, `queue_${i}`)) }),
13387
- /* @__PURE__ */ jsx21(
14390
+ /* @__PURE__ */ jsx22(
13388
14391
  StatusBar,
13389
14392
  {
13390
14393
  model: cfg.model,
@@ -13401,7 +14404,7 @@ ${lines.join("\n")}` }]);
13401
14404
  codeMode
13402
14405
  }
13403
14406
  ),
13404
- activePicker?.kind === "file" && /* @__PURE__ */ jsx21(
14407
+ activePicker?.kind === "file" && /* @__PURE__ */ jsx22(
13405
14408
  FilePicker,
13406
14409
  {
13407
14410
  items: filteredFileItems,
@@ -13409,7 +14412,7 @@ ${lines.join("\n")}` }]);
13409
14412
  query: pickerQuery ?? ""
13410
14413
  }
13411
14414
  ),
13412
- activePicker?.kind === "slash" && /* @__PURE__ */ jsx21(
14415
+ activePicker?.kind === "slash" && /* @__PURE__ */ jsx22(
13413
14416
  SlashPicker,
13414
14417
  {
13415
14418
  items: filteredSlashItems,
@@ -13417,9 +14420,9 @@ ${lines.join("\n")}` }]);
13417
14420
  query: pickerQuery ?? ""
13418
14421
  }
13419
14422
  ),
13420
- /* @__PURE__ */ jsxs19(Box19, { marginTop: 1, children: [
13421
- /* @__PURE__ */ jsx21(Text20, { color: "#d699b6", children: "\u203A " }),
13422
- /* @__PURE__ */ jsx21(
14423
+ /* @__PURE__ */ jsxs20(Box20, { marginTop: 1, children: [
14424
+ /* @__PURE__ */ jsx22(Text21, { color: "#d699b6", children: "\u203A " }),
14425
+ /* @__PURE__ */ jsx22(
13423
14426
  CustomTextInput,
13424
14427
  {
13425
14428
  value: input,
@@ -13476,7 +14479,7 @@ ${lines.join("\n")}` }]);
13476
14479
  }
13477
14480
  async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null) {
13478
14481
  const instance = render(
13479
- /* @__PURE__ */ jsx21(
14482
+ /* @__PURE__ */ jsx22(
13480
14483
  App,
13481
14484
  {
13482
14485
  initialCfg: cfg,
@@ -13517,7 +14520,13 @@ var init_app = __esm({
13517
14520
  init_welcome();
13518
14521
  init_help_menu();
13519
14522
  init_config();
14523
+ init_worker_client();
14524
+ init_session_store();
14525
+ init_tui_deploy();
14526
+ init_tui_auth();
14527
+ init_remote_dashboard();
13520
14528
  init_mode();
14529
+ init_classify();
13521
14530
  init_sessions();
13522
14531
  init_image();
13523
14532
  init_usage_tracker();
@@ -13566,8 +14575,107 @@ init_system_prompt();
13566
14575
  init_executor();
13567
14576
  init_update_check();
13568
14577
  init_version();
14578
+ import { Command as Command2 } from "commander";
14579
+
14580
+ // src/remote/cli.ts
14581
+ init_config();
14582
+ init_session_store();
14583
+ init_deploy();
13569
14584
  import { Command } from "commander";
13570
- var program = new Command();
14585
+ function createRemoteCommand() {
14586
+ const remote = new Command("remote").description("Manage remote sessions");
14587
+ remote.command("deploy").description("Deploy the remote Worker and container image to Cloudflare").action(async () => {
14588
+ await runDeploy();
14589
+ });
14590
+ remote.command("setup").description("Check remote deployment status and prerequisites").action(async () => {
14591
+ const status = await checkDeployStatus();
14592
+ console.log("Remote deployment status:\n");
14593
+ console.log(` wrangler CLI: ${status.wrangler ? "yes" : "no"}`);
14594
+ console.log(` wrangler auth: ${status.wranglerAuth ? "yes" : "no"}`);
14595
+ console.log(` Docker: ${status.docker ? "yes" : "no"}`);
14596
+ console.log(` Worker URL: ${status.workerUrl ?? "not deployed"}`);
14597
+ console.log("\nRun `kimiflare remote deploy` to deploy.");
14598
+ });
14599
+ remote.command("list").description("List remote sessions").action(async () => {
14600
+ const sessions = await listRemoteSessions();
14601
+ if (sessions.length === 0) {
14602
+ console.log("No remote sessions found.");
14603
+ return;
14604
+ }
14605
+ console.log(`Remote sessions (${sessions.length} total):
14606
+ `);
14607
+ for (const s of sessions.slice(0, 20)) {
14608
+ const date = new Date(s.createdAt).toLocaleString();
14609
+ const statusIcon = s.status === "done" ? "\u2705" : s.status === "error" ? "\u274C" : s.status === "running" ? "\u23F3" : "\u23F9\uFE0F";
14610
+ console.log(` ${statusIcon} ${s.sessionId.slice(0, 8)}\u2026 ${s.status.padEnd(10)} ${date} ${s.prompt.slice(0, 50)}`);
14611
+ if (s.prUrl) {
14612
+ console.log(` PR: ${s.prUrl}`);
14613
+ }
14614
+ }
14615
+ });
14616
+ remote.command("status").description("Show remote session status").argument("[session-id]", "Session ID (defaults to most recent)").action(async (sessionId) => {
14617
+ const session = sessionId ? await loadRemoteSession(sessionId) : await getMostRecentRemoteSession();
14618
+ if (!session) {
14619
+ console.log(sessionId ? `Session ${sessionId} not found.` : "No remote sessions found.");
14620
+ return;
14621
+ }
14622
+ const cfg = await loadConfig();
14623
+ const workerUrl = cfg?.remoteWorkerUrl;
14624
+ if (!workerUrl) {
14625
+ console.log("Remote worker not configured.");
14626
+ return;
14627
+ }
14628
+ try {
14629
+ const res = await fetch(`${workerUrl}/remote/status/${session.sessionId}`, {
14630
+ headers: {
14631
+ Authorization: `Bearer ${cfg.remoteAuthSecret ?? ""}`
14632
+ }
14633
+ });
14634
+ if (!res.ok) {
14635
+ console.log(`Failed to fetch status: ${res.status}`);
14636
+ return;
14637
+ }
14638
+ const data = await res.json();
14639
+ console.log(`Session: ${data.sessionId}`);
14640
+ console.log(`Status: ${data.status}`);
14641
+ console.log(`Prompt: ${data.prompt}`);
14642
+ console.log(`Repo: ${data.repo?.owner}/${data.repo?.name}`);
14643
+ console.log(`Branch: ${data.branch}`);
14644
+ console.log(`Turns: ${data.currentTurn} / ${data.maxTurns}`);
14645
+ if (data.prUrl) console.log(`PR: ${data.prUrl}`);
14646
+ if (data.errorMessage) console.log(`Error: ${data.errorMessage}`);
14647
+ } catch (err) {
14648
+ console.log(`Error: ${err instanceof Error ? err.message : String(err)}`);
14649
+ }
14650
+ });
14651
+ remote.command("cancel").description("Cancel a remote session").argument("<session-id>", "Session ID").action(async (sessionId) => {
14652
+ const cfg = await loadConfig();
14653
+ const workerUrl = cfg?.remoteWorkerUrl;
14654
+ if (!workerUrl) {
14655
+ console.log("Remote worker not configured.");
14656
+ return;
14657
+ }
14658
+ try {
14659
+ const res = await fetch(`${workerUrl}/remote/cancel/${sessionId}`, {
14660
+ method: "POST",
14661
+ headers: {
14662
+ Authorization: `Bearer ${cfg.remoteAuthSecret ?? ""}`
14663
+ }
14664
+ });
14665
+ if (!res.ok) {
14666
+ console.log(`Failed to cancel: ${res.status}`);
14667
+ return;
14668
+ }
14669
+ console.log(`Session ${sessionId} cancelled.`);
14670
+ } catch (err) {
14671
+ console.log(`Error: ${err instanceof Error ? err.message : String(err)}`);
14672
+ }
14673
+ });
14674
+ return remote;
14675
+ }
14676
+
14677
+ // src/index.tsx
14678
+ var program = new Command2();
13571
14679
  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));
13572
14680
  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) => {
13573
14681
  const cfg = await loadConfig();
@@ -13581,6 +14689,23 @@ program.command("cost").description("Show cost attribution by task type (require
13581
14689
  const { runCostCommand: runCostCommand2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
13582
14690
  await runCostCommand2({ ...cmdOpts, config: cfg });
13583
14691
  });
14692
+ program.addCommand(createRemoteCommand());
14693
+ program.command("auth").description("Authenticate with external services").addCommand(
14694
+ new Command2("github").description("Authenticate with GitHub via OAuth device flow").action(async () => {
14695
+ const { authGitHubForTui: authGitHubForTui2 } = await Promise.resolve().then(() => (init_tui_auth(), tui_auth_exports));
14696
+ for await (const step of authGitHubForTui2()) {
14697
+ console.log(step.message);
14698
+ if (step.url && step.code) {
14699
+ console.log(`
14700
+ Open: ${step.url}`);
14701
+ console.log(`Code: ${step.code}
14702
+ `);
14703
+ }
14704
+ if (step.done) break;
14705
+ if (step.error) process.exit(1);
14706
+ }
14707
+ })
14708
+ );
13584
14709
  program.action(async () => {
13585
14710
  await main();
13586
14711
  });