kimiflare 0.36.1 → 0.37.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
@@ -559,9 +559,11 @@ function validateModelId(model) {
559
559
  function buildKimiRequestTarget(opts2) {
560
560
  validateModelId(opts2.model);
561
561
  if (opts2.cloudMode) {
562
+ const headers2 = opts2.cloudToken ? { Authorization: `Bearer ${opts2.cloudToken}` } : {};
563
+ if (opts2.cloudDeviceId) headers2["X-Device-ID"] = opts2.cloudDeviceId;
562
564
  return {
563
565
  url: "https://api.kimiflare.com/v1/chat",
564
- headers: opts2.cloudToken ? { Authorization: `Bearer ${opts2.cloudToken}` } : {}
566
+ headers: headers2
565
567
  };
566
568
  }
567
569
  if (!opts2.gateway?.id) {
@@ -1760,7 +1762,8 @@ Use console.log() to return results. Only console.log output will be sent back t
1760
1762
  sessionId: opts2.sessionId,
1761
1763
  gateway: opts2.gateway,
1762
1764
  cloudMode: opts2.cloudMode,
1763
- cloudToken: opts2.cloudToken
1765
+ cloudToken: opts2.cloudToken,
1766
+ cloudDeviceId: opts2.cloudDeviceId
1764
1767
  });
1765
1768
  for await (const ev of events) {
1766
1769
  switch (ev.type) {
@@ -4664,24 +4667,30 @@ function generateCode() {
4664
4667
  }
4665
4668
  return out;
4666
4669
  }
4670
+ function generateDeviceId() {
4671
+ const arr = new Uint8Array(16);
4672
+ crypto.getRandomValues(arr);
4673
+ return Array.from(arr, (b) => b.toString(16).padStart(2, "0")).join("");
4674
+ }
4667
4675
  function generateDeviceCodes() {
4668
4676
  const deviceCode = `device-${generateCode()}-${Date.now()}`;
4669
4677
  const userCode = `${generateCode()}-${generateCode()}`;
4670
4678
  const authUrl = `${CLOUD_API_URL}/auth/github?code=${encodeURIComponent(userCode)}`;
4671
- return { deviceCode, userCode, authUrl };
4679
+ const deviceId = generateDeviceId();
4680
+ return { deviceCode, userCode, authUrl, deviceId };
4672
4681
  }
4673
4682
  async function registerDevice(codes) {
4674
4683
  const registerRes = await fetch(`${CLOUD_API_URL}/auth/device`, {
4675
4684
  method: "POST",
4676
4685
  headers: { "Content-Type": "application/json" },
4677
- body: JSON.stringify({ device_code: codes.deviceCode, user_code: codes.userCode })
4686
+ body: JSON.stringify({ device_code: codes.deviceCode, user_code: codes.userCode, device_id: codes.deviceId })
4678
4687
  });
4679
4688
  if (!registerRes.ok) {
4680
4689
  const err = await registerRes.json().catch(() => ({}));
4681
4690
  throw new Error(`Failed to register device: ${err.error || registerRes.statusText}`);
4682
4691
  }
4683
4692
  }
4684
- async function pollForToken(deviceCode) {
4693
+ async function pollForToken(deviceCode, deviceId) {
4685
4694
  const pollRes = await fetch(`${CLOUD_API_URL}/auth/poll`, {
4686
4695
  method: "POST",
4687
4696
  headers: { "Content-Type": "application/json" },
@@ -4692,18 +4701,19 @@ async function pollForToken(deviceCode) {
4692
4701
  if (pollData.status === "approved" && pollData.access_token) {
4693
4702
  const creds = {
4694
4703
  accessToken: pollData.access_token,
4695
- expiresAt: Math.floor(Date.now() / 1e3) + 7 * 24 * 60 * 60
4704
+ expiresAt: Math.floor(Date.now() / 1e3) + 7 * 24 * 60 * 60,
4696
4705
  // 7 days
4706
+ deviceId
4697
4707
  };
4698
4708
  await saveCloudCredentials(creds);
4699
4709
  return creds;
4700
4710
  }
4701
4711
  return null;
4702
4712
  }
4703
- async function fetchCloudUsage(token) {
4704
- const res = await fetch(`${CLOUD_API_URL}/v1/usage`, {
4705
- headers: { Authorization: `Bearer ${token}` }
4706
- });
4713
+ async function fetchCloudUsage(token, deviceId) {
4714
+ const headers = { Authorization: `Bearer ${token}` };
4715
+ if (deviceId) headers["X-Device-ID"] = deviceId;
4716
+ const res = await fetch(`${CLOUD_API_URL}/v1/usage`, { headers });
4707
4717
  if (!res.ok) return null;
4708
4718
  const data = await res.json();
4709
4719
  if (typeof data.remaining !== "number" || typeof data.input_token_limit !== "number" || typeof data.input_tokens_used !== "number" || typeof data.expires_at !== "string") {
@@ -4720,7 +4730,7 @@ async function loadCloudCredentials() {
4720
4730
  try {
4721
4731
  const raw = await readFile11(cloudCredPath(), "utf8");
4722
4732
  const parsed = JSON.parse(raw);
4723
- if (parsed.expiresAt && parsed.expiresAt > Date.now() / 1e3) {
4733
+ if (parsed.expiresAt && parsed.expiresAt > Date.now() / 1e3 && parsed.accessToken) {
4724
4734
  return parsed;
4725
4735
  }
4726
4736
  } catch {
@@ -4746,7 +4756,7 @@ async function authenticateDevice(onStatus) {
4746
4756
  while (Date.now() - startTime < POLL_TIMEOUT_MS) {
4747
4757
  await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
4748
4758
  onStatus({ url: codes.authUrl, userCode: codes.userCode, polling: true });
4749
- const creds = await pollForToken(codes.deviceCode);
4759
+ const creds = await pollForToken(codes.deviceCode, codes.deviceId);
4750
4760
  if (creds) return creds;
4751
4761
  }
4752
4762
  throw new Error("Authentication timed out. Please try again.");
@@ -6868,9 +6878,9 @@ function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta, cloudMo
6868
6878
  parts.push(`out ${sessionUsage.completionTokens}`);
6869
6879
  parts.push(`ctx ${pct}%`);
6870
6880
  if (cloudMode) {
6871
- parts.push(`\x1B[9m${sessionUsage.cost.toFixed(5)}\x1B[29m`);
6881
+ parts.push(`\x1B[9m$${sessionUsage.cost.toFixed(5)}\x1B[29m`);
6872
6882
  } else {
6873
- parts.push(`${sessionUsage.cost.toFixed(5)}`);
6883
+ parts.push(`$${sessionUsage.cost.toFixed(5)}`);
6874
6884
  }
6875
6885
  } else {
6876
6886
  const cached = usage.prompt_tokens_details?.cached_tokens ?? 0;
@@ -6879,9 +6889,9 @@ function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta, cloudMo
6879
6889
  parts.push(`out ${usage.completion_tokens}`);
6880
6890
  parts.push(`ctx ${pct}%`);
6881
6891
  if (cloudMode) {
6882
- parts.push(`\x1B[9m${cost.total.toFixed(5)}\x1B[29m`);
6892
+ parts.push(`\x1B[9m$${cost.total.toFixed(5)}\x1B[29m`);
6883
6893
  } else {
6884
- parts.push(`${cost.total.toFixed(5)}`);
6894
+ parts.push(`$${cost.total.toFixed(5)}`);
6885
6895
  }
6886
6896
  }
6887
6897
  if (cloudMode && cloudBudget) {
@@ -6892,6 +6902,7 @@ function buildRightParts(usage, contextLimit, sessionUsage, gatewayMeta, cloudMo
6892
6902
  return parts;
6893
6903
  }
6894
6904
  function formatTokens(n) {
6905
+ if (n >= 1e9) return `${(n / 1e9).toFixed(1)}B`;
6895
6906
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
6896
6907
  if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
6897
6908
  return String(n);
@@ -7978,9 +7989,9 @@ function Onboarding({ onDone, onCancel }) {
7978
7989
  return;
7979
7990
  }
7980
7991
  try {
7981
- const creds = await pollForToken(cloudAuth.codes.deviceCode);
7992
+ const creds = await pollForToken(cloudAuth.codes.deviceCode, cloudAuth.codes.deviceId);
7982
7993
  if (creds && !cancelled) {
7983
- const usage = await fetchCloudUsage(creds.accessToken);
7994
+ const usage = await fetchCloudUsage(creds.accessToken, creds.deviceId);
7984
7995
  if (usage && !cancelled) {
7985
7996
  setCloudAuth({
7986
7997
  phase: "success",
@@ -12983,13 +12994,15 @@ function App({
12983
12994
  initialUpdateResult,
12984
12995
  initialLspScope,
12985
12996
  initialLspProjectPath,
12986
- initialCloudToken
12997
+ initialCloudToken,
12998
+ initialCloudDeviceId
12987
12999
  }) {
12988
13000
  const { exit } = useApp();
12989
13001
  const [cfg, setCfg] = useState10(initialCfg);
12990
13002
  const [lspScope, setLspScope] = useState10(initialLspScope);
12991
13003
  const [lspProjectPath, setLspProjectPath] = useState10(initialLspProjectPath);
12992
13004
  const [cloudToken, setCloudToken] = useState10(initialCloudToken);
13005
+ const [cloudDeviceId, setCloudDeviceId] = useState10(initialCloudDeviceId);
12993
13006
  const [events, setRawEvents] = useState10([]);
12994
13007
  const setEvents = useCallback2(
12995
13008
  (updater) => {
@@ -13043,7 +13056,7 @@ function App({
13043
13056
  let cancelled = false;
13044
13057
  const fetchBudget = async () => {
13045
13058
  const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
13046
- const usage2 = await fetchCloudUsage2(initialCloudToken);
13059
+ const usage2 = await fetchCloudUsage2(initialCloudToken, cloudDeviceId ?? initialCloudDeviceId);
13047
13060
  if (usage2 && !cancelled) {
13048
13061
  setCloudBudget({ remaining: usage2.remaining, limit: usage2.input_token_limit });
13049
13062
  }
@@ -13967,6 +13980,7 @@ function App({
13967
13980
  codeMode: effectiveCodeMode,
13968
13981
  cloudMode: cfg.cloudMode,
13969
13982
  cloudToken: cloudToken ?? initialCloudToken,
13983
+ cloudDeviceId: cloudDeviceId ?? initialCloudDeviceId,
13970
13984
  onIterationEnd,
13971
13985
  onFileChange: (path, content) => {
13972
13986
  if (content) {
@@ -14034,6 +14048,17 @@ function App({
14034
14048
  const sid = ensureSessionId();
14035
14049
  void recordUsage(sid, u, gatewayUsageLookupFromConfig(cfg, meta ?? gatewayMetaRef.current));
14036
14050
  void getCostReport(sid).then((report) => setSessionUsage(report.session));
14051
+ if (cfg?.cloudMode && (cloudToken ?? initialCloudToken)) {
14052
+ const token = cloudToken ?? initialCloudToken;
14053
+ const did = cloudDeviceId ?? initialCloudDeviceId;
14054
+ void (async () => {
14055
+ const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
14056
+ const usage2 = await fetchCloudUsage2(token, did);
14057
+ if (usage2) {
14058
+ setCloudBudget({ remaining: usage2.remaining, limit: usage2.input_token_limit });
14059
+ }
14060
+ })();
14061
+ }
14037
14062
  },
14038
14063
  onGatewayMeta: updateGatewayMeta,
14039
14064
  askPermission: (req) => new Promise((resolve2) => {
@@ -15113,6 +15138,17 @@ ${lines.join("\n")}` }]);
15113
15138
  const sid = ensureSessionId();
15114
15139
  void recordUsage(sid, u, gatewayUsageLookupFromConfig(cfg, meta ?? gatewayMetaRef.current));
15115
15140
  void getCostReport(sid).then((report) => setSessionUsage(report.session));
15141
+ if (cfg?.cloudMode && (cloudToken ?? initialCloudToken)) {
15142
+ const token = cloudToken ?? initialCloudToken;
15143
+ const did = cloudDeviceId ?? initialCloudDeviceId;
15144
+ void (async () => {
15145
+ const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
15146
+ const usage2 = await fetchCloudUsage2(token, did);
15147
+ if (usage2) {
15148
+ setCloudBudget({ remaining: usage2.remaining, limit: usage2.input_token_limit });
15149
+ }
15150
+ })();
15151
+ }
15116
15152
  },
15117
15153
  onGatewayMeta: updateGatewayMeta,
15118
15154
  onTasks: (nextTasks) => {
@@ -15177,6 +15213,7 @@ ${lines.join("\n")}` }]);
15177
15213
  codeMode: effectiveCodeMode,
15178
15214
  cloudMode: cfg.cloudMode,
15179
15215
  cloudToken: cloudToken ?? initialCloudToken,
15216
+ cloudDeviceId: cloudDeviceId ?? initialCloudDeviceId,
15180
15217
  onIterationEnd,
15181
15218
  intentClassification: classification,
15182
15219
  onFileChange: (path, content2) => {
@@ -15678,7 +15715,7 @@ ${lines.join("\n")}` }]);
15678
15715
  ] })
15679
15716
  ] }) });
15680
15717
  }
15681
- async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null, cloudToken) {
15718
+ async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null, cloudToken, cloudDeviceId) {
15682
15719
  const instance = render(
15683
15720
  /* @__PURE__ */ jsx23(
15684
15721
  App,
@@ -15687,7 +15724,8 @@ async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath
15687
15724
  initialUpdateResult: updateResult,
15688
15725
  initialLspScope: lspScope,
15689
15726
  initialLspProjectPath: lspProjectPath,
15690
- initialCloudToken: cloudToken
15727
+ initialCloudToken: cloudToken,
15728
+ initialCloudDeviceId: cloudDeviceId
15691
15729
  }
15692
15730
  ),
15693
15731
  {
@@ -15901,7 +15939,7 @@ program.command("usage").description("Show Kimiflare Cloud token usage (requires
15901
15939
  process.exit(1);
15902
15940
  }
15903
15941
  const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
15904
- const usage = await fetchCloudUsage2(creds.accessToken);
15942
+ const usage = await fetchCloudUsage2(creds.accessToken, creds.deviceId);
15905
15943
  if (!usage) {
15906
15944
  console.error("Failed to fetch usage: invalid response from server");
15907
15945
  process.exit(1);
@@ -15944,7 +15982,7 @@ Kimiflare Cloud Authentication`);
15944
15982
  });
15945
15983
  console.log(`Authenticated! Token expires at ${new Date(creds.expiresAt * 1e3).toISOString()}`);
15946
15984
  const { fetchCloudUsage: fetchCloudUsage2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
15947
- const usage = await fetchCloudUsage2(creds.accessToken);
15985
+ const usage = await fetchCloudUsage2(creds.accessToken, creds.deviceId);
15948
15986
  if (usage) {
15949
15987
  console.log(`
15950
15988
  Token budget: ${usage.remaining.toLocaleString()} / ${usage.input_token_limit.toLocaleString()} remaining`);
@@ -15979,6 +16017,7 @@ async function main() {
15979
16017
  }
15980
16018
  const cloudMode = opts.cloud ?? cfg?.cloudMode ?? false;
15981
16019
  let cloudToken;
16020
+ let cloudDeviceId;
15982
16021
  if (cloudMode) {
15983
16022
  const { loadCloudCredentials: loadCloudCredentials2, authenticateDevice: authenticateDevice2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
15984
16023
  let cloudCreds = await loadCloudCredentials2();
@@ -15987,6 +16026,7 @@ async function main() {
15987
16026
  process.exit(2);
15988
16027
  }
15989
16028
  cloudToken = cloudCreds.accessToken;
16029
+ cloudDeviceId = cloudCreds.deviceId;
15990
16030
  cfg = {
15991
16031
  ...cfg ?? { accountId: "", apiToken: "", model: DEFAULT_MODEL },
15992
16032
  cloudMode: true
@@ -16008,6 +16048,7 @@ async function main() {
16008
16048
  showReasoning: !!opts.reasoning,
16009
16049
  codeMode: cfg.codeMode,
16010
16050
  cloudToken,
16051
+ cloudDeviceId,
16011
16052
  continueOnLimit: !!opts.continueOnLimit,
16012
16053
  maxInputTokens: opts.maxInputTokens,
16013
16054
  updateResult
@@ -16023,9 +16064,9 @@ async function main() {
16023
16064
  const { renderApp: renderApp2 } = await Promise.resolve().then(() => (init_app(), app_exports));
16024
16065
  if (cfg) {
16025
16066
  const model = opts.model ?? cfg.model ?? DEFAULT_MODEL;
16026
- await renderApp2({ ...cfg, model }, updateResult, lspScope, lspProjectPath, cloudToken);
16067
+ await renderApp2({ ...cfg, model }, updateResult, lspScope, lspProjectPath, cloudToken, cloudDeviceId);
16027
16068
  } else {
16028
- await renderApp2(null, updateResult, lspScope, lspProjectPath, cloudToken);
16069
+ await renderApp2(null, updateResult, lspScope, lspProjectPath, cloudToken, cloudDeviceId);
16029
16070
  }
16030
16071
  }
16031
16072
  function gatewayFromPrintOpts(opts2) {
@@ -16077,6 +16118,7 @@ async function runPrintMode(opts2) {
16077
16118
  maxInputTokens: opts2.maxInputTokens,
16078
16119
  cloudMode: opts2.cloudMode,
16079
16120
  cloudToken: opts2.cloudToken,
16121
+ cloudDeviceId: opts2.cloudDeviceId,
16080
16122
  coauthor: opts2.coauthor !== false ? { name: opts2.coauthorName || "kimiflare", email: opts2.coauthorEmail || "kimiflare@proton.me" } : void 0,
16081
16123
  callbacks: {
16082
16124
  onReasoningDelta: opts2.showReasoning ? (delta) => {