@dotobokuri/fleet-console 1.57.2 → 1.58.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.
Files changed (66) hide show
  1. package/dist/cli.mjs +30 -5
  2. package/dist/client/assets/{_baseUniq-dvybACFL.js → _baseUniq-DJ4C0UQF.js} +1 -1
  3. package/dist/client/assets/{arc-BM1EQJ5i.js → arc-DkQKttnC.js} +1 -1
  4. package/dist/client/assets/{architectureDiagram-Q4EWVU46-C5NpB_9B.js → architectureDiagram-Q4EWVU46-BpuET3uK.js} +1 -1
  5. package/dist/client/assets/{blockDiagram-DXYQGD6D-BemCHdjP.js → blockDiagram-DXYQGD6D-CatlulZp.js} +1 -1
  6. package/dist/client/assets/{c4Diagram-AHTNJAMY-BB7Qe4id.js → c4Diagram-AHTNJAMY-BPfWevDh.js} +1 -1
  7. package/dist/client/assets/channel-DDcyY5eB.js +1 -0
  8. package/dist/client/assets/{chunk-4BX2VUAB-CqmbYj1h.js → chunk-4BX2VUAB-a7lkla2P.js} +1 -1
  9. package/dist/client/assets/{chunk-4TB4RGXK-DY8csFL8.js → chunk-4TB4RGXK-Bh-20OVN.js} +1 -1
  10. package/dist/client/assets/{chunk-55IACEB6-Bc2JNsBB.js → chunk-55IACEB6-DiPm-_AS.js} +1 -1
  11. package/dist/client/assets/{chunk-EDXVE4YY-B7fkHilr.js → chunk-EDXVE4YY-BcGep4mz.js} +1 -1
  12. package/dist/client/assets/{chunk-FMBD7UC4-CKS1kchI.js → chunk-FMBD7UC4-Cn0A6Wm1.js} +1 -1
  13. package/dist/client/assets/{chunk-OYMX7WX6-BoSMhV9B.js → chunk-OYMX7WX6-DNTIDjw4.js} +1 -1
  14. package/dist/client/assets/{chunk-QZHKN3VN-B6NI5Nv8.js → chunk-QZHKN3VN-cji_BhbG.js} +1 -1
  15. package/dist/client/assets/{chunk-YZCP3GAM-DDwSQ8RI.js → chunk-YZCP3GAM-B6I5kLlB.js} +1 -1
  16. package/dist/client/assets/classDiagram-6PBFFD2Q-CqqUqRwS.js +1 -0
  17. package/dist/client/assets/classDiagram-v2-HSJHXN6E-CqqUqRwS.js +1 -0
  18. package/dist/client/assets/clone-CjMEm_X8.js +1 -0
  19. package/dist/client/assets/{cose-bilkent-S5V4N54A-VjTSxeFA.js → cose-bilkent-S5V4N54A-_Xmui3Dj.js} +1 -1
  20. package/dist/client/assets/{dagre-KV5264BT-BQSQIPKP.js → dagre-KV5264BT-BI_m6tGN.js} +1 -1
  21. package/dist/client/assets/{diagram-5BDNPKRD-C6e_Ovvo.js → diagram-5BDNPKRD-JDBqcRRR.js} +1 -1
  22. package/dist/client/assets/{diagram-G4DWMVQ6-D6vqaIMN.js → diagram-G4DWMVQ6-CdIHKaZT.js} +1 -1
  23. package/dist/client/assets/{diagram-MMDJMWI5-DFxtu5Sa.js → diagram-MMDJMWI5-CULX6wM5.js} +1 -1
  24. package/dist/client/assets/{diagram-TYMM5635-BcYaszXB.js → diagram-TYMM5635-C1JXiI2W.js} +1 -1
  25. package/dist/client/assets/{erDiagram-SMLLAGMA-DLSCg-9y.js → erDiagram-SMLLAGMA-RJI8bZrW.js} +1 -1
  26. package/dist/client/assets/{flowDiagram-DWJPFMVM-_kx-OfzH.js → flowDiagram-DWJPFMVM-CSrF7U0E.js} +1 -1
  27. package/dist/client/assets/{ganttDiagram-T4ZO3ILL-DluEefPv.js → ganttDiagram-T4ZO3ILL-CHp3LObA.js} +1 -1
  28. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-BDHypYJk.js → gitGraphDiagram-UUTBAWPF-BEeoTjqh.js} +1 -1
  29. package/dist/client/assets/{graph-CHPq19s3.js → graph-DNvMdh3j.js} +1 -1
  30. package/dist/client/assets/index-BG857Idy.css +1 -0
  31. package/dist/client/assets/index-CCNdSGui.js +483 -0
  32. package/dist/client/assets/{infoDiagram-42DDH7IO-BhntKSlv.js → infoDiagram-42DDH7IO-31kh8JMu.js} +1 -1
  33. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-Vo0lWYeZ.js → ishikawaDiagram-UXIWVN3A-DZgEgolJ.js} +1 -1
  34. package/dist/client/assets/{journeyDiagram-VCZTEJTY-B-jydfQ3.js → journeyDiagram-VCZTEJTY-DfZ3i3Bu.js} +1 -1
  35. package/dist/client/assets/{kanban-definition-6JOO6SKY-CR7_O2tt.js → kanban-definition-6JOO6SKY-giivFfnv.js} +1 -1
  36. package/dist/client/assets/{layout-C7qyIJFE.js → layout-DdVRNrH8.js} +1 -1
  37. package/dist/client/assets/{linear-ClKfz3Xw.js → linear-3cmeYdGh.js} +1 -1
  38. package/dist/client/assets/{mermaid.core-eHgX1dDu.js → mermaid.core-Cjqy_Y5Z.js} +4 -4
  39. package/dist/client/assets/{min-CBcfPH4t.js → min-Cgsd0one.js} +1 -1
  40. package/dist/client/assets/{mindmap-definition-QFDTVHPH-BrjeA0rz.js → mindmap-definition-QFDTVHPH-PfuGubxC.js} +1 -1
  41. package/dist/client/assets/{pieDiagram-DEJITSTG-Bx3gB3ns.js → pieDiagram-DEJITSTG-B9O6H439.js} +1 -1
  42. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-Y_8L8YCa.js → quadrantDiagram-34T5L4WZ-DJH7RQzs.js} +1 -1
  43. package/dist/client/assets/{requirementDiagram-MS252O5E-BByFdhc4.js → requirementDiagram-MS252O5E-BZHTYV2q.js} +1 -1
  44. package/dist/client/assets/{sankeyDiagram-XADWPNL6-Du7m7fuy.js → sankeyDiagram-XADWPNL6-B5aGVyLG.js} +1 -1
  45. package/dist/client/assets/{sequenceDiagram-FGHM5R23-DovViawI.js → sequenceDiagram-FGHM5R23-D2890FYU.js} +1 -1
  46. package/dist/client/assets/{stateDiagram-FHFEXIEX-7fVJHvbx.js → stateDiagram-FHFEXIEX-DWmhZMWZ.js} +1 -1
  47. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-DoQKtZ4H.js +1 -0
  48. package/dist/client/assets/{timeline-definition-GMOUNBTQ-Dgsxq4-O.js → timeline-definition-GMOUNBTQ-B0pTOfcD.js} +1 -1
  49. package/dist/client/assets/{vennDiagram-DHZGUBPP-D2tu5aMx.js → vennDiagram-DHZGUBPP-D-S4XLnE.js} +1 -1
  50. package/dist/client/assets/{wardley-RL74JXVD-C4IVs_k4.js → wardley-RL74JXVD-ClPA8Fc3.js} +1 -1
  51. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-DCVn_9G_.js → wardleyDiagram-NUSXRM2D-JJgj7CxJ.js} +1 -1
  52. package/dist/client/assets/{xychartDiagram-5P7HB3ND-D1TZkyWh.js → xychartDiagram-5P7HB3ND-BBIy9-Kq.js} +1 -1
  53. package/dist/client/index.html +2 -2
  54. package/dist/fleet-plugins/ledger/routes.mjs +35 -0
  55. package/dist/fleet-plugins/quota/routes.mjs +422 -61
  56. package/dist/fleet-plugins/scuttlebutt/routes.mjs +30 -5
  57. package/dist/fleet-plugins/terminal/routes.mjs +1317 -541
  58. package/dist/fleet.mjs +1541 -674
  59. package/package.json +1 -1
  60. package/dist/client/assets/channel-t207uO3V.js +0 -1
  61. package/dist/client/assets/classDiagram-6PBFFD2Q-Dg0z8qFh.js +0 -1
  62. package/dist/client/assets/classDiagram-v2-HSJHXN6E-Dg0z8qFh.js +0 -1
  63. package/dist/client/assets/clone-B47TzRxK.js +0 -1
  64. package/dist/client/assets/index-D6_LDhkV.css +0 -1
  65. package/dist/client/assets/index-DeiAnv0J.js +0 -483
  66. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-CQPjJLLI.js +0 -1
@@ -2,7 +2,7 @@
2
2
  import { execFile } from 'node:child_process';
3
3
  import * as fs4 from 'node:fs';
4
4
  import fs4__default, { constants } from 'node:fs';
5
- import fs5 from 'node:fs/promises';
5
+ import fs32 from 'node:fs/promises';
6
6
  import * as os3 from 'node:os';
7
7
  import os3__default from 'node:os';
8
8
  import { promisify } from 'node:util';
@@ -19,16 +19,16 @@ var __export = (target, all) => {
19
19
  function definePlugin(definition) {
20
20
  return definition;
21
21
  }
22
- function registerRouter(ctx, path5, handler, catalog) {
22
+ function registerRouter(ctx, path6, handler, catalog) {
23
23
  if (catalog) {
24
- ctx.registerRouter(normalizePath(path5), handler, catalog);
24
+ ctx.registerRouter(normalizePath(path6), handler, catalog);
25
25
  return;
26
26
  }
27
- ctx.registerRouter(normalizePath(path5), handler);
27
+ ctx.registerRouter(normalizePath(path6), handler);
28
28
  }
29
- function normalizePath(path5) {
30
- if (path5.length === 0 || path5 === "/") return "/";
31
- return path5;
29
+ function normalizePath(path6) {
30
+ if (path6.length === 0 || path6 === "/") return "/";
31
+ return path6;
32
32
  }
33
33
 
34
34
  // ../../node_modules/.pnpm/zod@4.4.1/node_modules/zod/v4/classic/external.js
@@ -793,10 +793,10 @@ function mergeDefs(...defs) {
793
793
  function cloneDef(schema) {
794
794
  return mergeDefs(schema._zod.def);
795
795
  }
796
- function getElementAtPath(obj, path5) {
797
- if (!path5)
796
+ function getElementAtPath(obj, path6) {
797
+ if (!path6)
798
798
  return obj;
799
- return path5.reduce((acc, key) => acc?.[key], obj);
799
+ return path6.reduce((acc, key) => acc?.[key], obj);
800
800
  }
801
801
  function promiseAllObject(promisesObj) {
802
802
  const keys = Object.keys(promisesObj);
@@ -1205,11 +1205,11 @@ function explicitlyAborted(x, startIndex = 0) {
1205
1205
  }
1206
1206
  return false;
1207
1207
  }
1208
- function prefixIssues(path5, issues) {
1208
+ function prefixIssues(path6, issues) {
1209
1209
  return issues.map((iss) => {
1210
1210
  var _a3;
1211
1211
  (_a3 = iss).path ?? (_a3.path = []);
1212
- iss.path.unshift(path5);
1212
+ iss.path.unshift(path6);
1213
1213
  return iss;
1214
1214
  });
1215
1215
  }
@@ -1356,16 +1356,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1356
1356
  }
1357
1357
  function formatError(error51, mapper = (issue2) => issue2.message) {
1358
1358
  const fieldErrors = { _errors: [] };
1359
- const processError = (error52, path5 = []) => {
1359
+ const processError = (error52, path6 = []) => {
1360
1360
  for (const issue2 of error52.issues) {
1361
1361
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1362
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
1362
+ issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
1363
1363
  } else if (issue2.code === "invalid_key") {
1364
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
1364
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
1365
1365
  } else if (issue2.code === "invalid_element") {
1366
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
1366
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
1367
1367
  } else {
1368
- const fullpath = [...path5, ...issue2.path];
1368
+ const fullpath = [...path6, ...issue2.path];
1369
1369
  if (fullpath.length === 0) {
1370
1370
  fieldErrors._errors.push(mapper(issue2));
1371
1371
  } else {
@@ -1392,17 +1392,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1392
1392
  }
1393
1393
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1394
1394
  const result = { errors: [] };
1395
- const processError = (error52, path5 = []) => {
1395
+ const processError = (error52, path6 = []) => {
1396
1396
  var _a3, _b;
1397
1397
  for (const issue2 of error52.issues) {
1398
1398
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1399
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
1399
+ issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
1400
1400
  } else if (issue2.code === "invalid_key") {
1401
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
1401
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
1402
1402
  } else if (issue2.code === "invalid_element") {
1403
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
1403
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
1404
1404
  } else {
1405
- const fullpath = [...path5, ...issue2.path];
1405
+ const fullpath = [...path6, ...issue2.path];
1406
1406
  if (fullpath.length === 0) {
1407
1407
  result.errors.push(mapper(issue2));
1408
1408
  continue;
@@ -1434,8 +1434,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1434
1434
  }
1435
1435
  function toDotPath(_path) {
1436
1436
  const segs = [];
1437
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1438
- for (const seg of path5) {
1437
+ const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1438
+ for (const seg of path6) {
1439
1439
  if (typeof seg === "number")
1440
1440
  segs.push(`[${seg}]`);
1441
1441
  else if (typeof seg === "symbol")
@@ -14099,13 +14099,13 @@ function resolveRef(ref, ctx) {
14099
14099
  if (!ref.startsWith("#")) {
14100
14100
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14101
14101
  }
14102
- const path5 = ref.slice(1).split("/").filter(Boolean);
14103
- if (path5.length === 0) {
14102
+ const path6 = ref.slice(1).split("/").filter(Boolean);
14103
+ if (path6.length === 0) {
14104
14104
  return ctx.rootSchema;
14105
14105
  }
14106
14106
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14107
- if (path5[0] === defsKey) {
14108
- const key = path5[1];
14107
+ if (path6[0] === defsKey) {
14108
+ const key = path6[1];
14109
14109
  if (!key || !ctx.defs[key]) {
14110
14110
  throw new Error(`Reference not found: ${ref}`);
14111
14111
  }
@@ -17093,8 +17093,8 @@ function bootEnumDescriptorProto(init) {
17093
17093
  }
17094
17094
 
17095
17095
  // ../../node_modules/.pnpm/@bufbuild+protobuf@2.13.0/node_modules/@bufbuild/protobuf/dist/esm/codegenv2/message.js
17096
- function messageDesc(file2, path5, ...paths) {
17097
- return paths.reduce((acc, cur) => acc.nestedMessages[cur], file2.messages[path5]);
17096
+ function messageDesc(file2, path6, ...paths) {
17097
+ return paths.reduce((acc, cur) => acc.nestedMessages[cur], file2.messages[path6]);
17098
17098
  }
17099
17099
 
17100
17100
  // ../../node_modules/.pnpm/@bufbuild+protobuf@2.13.0/node_modules/@bufbuild/protobuf/dist/esm/wkt/gen/google/protobuf/descriptor_pb.js
@@ -18011,7 +18011,7 @@ var benchmarks_default = {
18011
18011
  };
18012
18012
  var models_default = {
18013
18013
  version: 1,
18014
- updatedAt: "2026-08-13T00:00:00Z",
18014
+ updatedAt: "2026-08-14T00:00:00Z",
18015
18015
  providers: {
18016
18016
  codex: {
18017
18017
  name: "Codex",
@@ -18396,12 +18396,36 @@ var models_default = {
18396
18396
  contextWindow: 256e3
18397
18397
  }
18398
18398
  ]
18399
+ },
18400
+ xai: {
18401
+ name: "xAI",
18402
+ defaultModel: "grok-4.6",
18403
+ source: "official Grok CLI 1.0.3 ~/.grok/models_cache.json from GET https://cli-chat-proxy.grok.com/v1/models (observed 2026-08-13)",
18404
+ models: [
18405
+ {
18406
+ modelId: "grok-4.6",
18407
+ name: "Grok-4.6",
18408
+ capabilityClass: "flagship",
18409
+ wire: "responses",
18410
+ contextWindow: 5e5,
18411
+ effort: {
18412
+ supported: true,
18413
+ levels: [
18414
+ "low",
18415
+ "medium",
18416
+ "high",
18417
+ "xhigh"
18418
+ ]
18419
+ },
18420
+ benchmarkKey: "grok-4.6"
18421
+ }
18422
+ ]
18399
18423
  }
18400
18424
  }
18401
18425
  };
18402
18426
  var KIMI_AUTH_PROVIDER_ID = "Claude Code with Moonshot Kimi";
18403
18427
  var KIMI_CODE_API_BASE_URL = "https://api.kimi.com/coding";
18404
- var GATEWAY_PROVIDERS = ["codex", "cursor", "kimi", "opencode"];
18428
+ var GATEWAY_PROVIDERS = ["codex", "xai", "cursor", "opencode", "kimi"];
18405
18429
  var GATEWAY_MODEL_WIRES = ["anthropic", "responses", "chat-completions"];
18406
18430
  var GATEWAY_REASONING_EFFORTS = [
18407
18431
  "low",
@@ -18489,7 +18513,8 @@ var GatewayModelsRegistrySchema = external_exports.object({
18489
18513
  codex: GatewayProviderSchema,
18490
18514
  cursor: GatewayProviderSchema,
18491
18515
  kimi: GatewayProviderSchema,
18492
- opencode: GatewayProviderSchema
18516
+ opencode: GatewayProviderSchema,
18517
+ xai: GatewayProviderSchema
18493
18518
  }).strict()
18494
18519
  }).strict();
18495
18520
  var UNSUPPORTED_GATEWAY_MODEL_EFFORT = Object.freeze({ supported: false });
@@ -18676,8 +18701,8 @@ function validateRegistry(value) {
18676
18701
  if (model.quotaScope && provider !== "cursor") {
18677
18702
  throw new Error(`Gateway quota scope is only supported by Cursor: ${provider}/${model.modelId}`);
18678
18703
  }
18679
- if (model.wire && provider !== "opencode") {
18680
- throw new Error(`Gateway model wire is only supported by OpenCode: ${provider}/${model.modelId}`);
18704
+ if (model.wire && provider !== "opencode" && provider !== "xai") {
18705
+ throw new Error(`Gateway model wire is not supported by provider: ${provider}/${model.modelId}`);
18681
18706
  }
18682
18707
  if (model.effort?.supported) {
18683
18708
  if (new Set(model.effort.levels).size !== model.effort.levels.length) {
@@ -18973,7 +18998,7 @@ var execFileAsync = promisify(execFile);
18973
18998
  var MAX_CREDENTIAL_BYTES = 65536;
18974
18999
  var CREDENTIAL_OPEN_FLAGS = process.platform === "win32" ? constants.O_RDONLY : constants.O_RDONLY | constants.O_NONBLOCK;
18975
19000
  async function readBoundedFile(filePath, maxBytes) {
18976
- const handle = await fs5.open(filePath, CREDENTIAL_OPEN_FLAGS);
19001
+ const handle = await fs32.open(filePath, CREDENTIAL_OPEN_FLAGS);
18977
19002
  try {
18978
19003
  const stat2 = await handle.stat();
18979
19004
  if (!stat2.isFile() || stat2.size > maxBytes) return null;
@@ -19205,9 +19230,9 @@ function parseResetCredits(payload) {
19205
19230
  for (let index = 0; index < credits.length && index < MAX_CREDIT_ENTRIES; index += 1) {
19206
19231
  const credit = object2(credits[index]);
19207
19232
  if (credit?.status !== "available") continue;
19208
- const expiry = safeTimestamp(credit.expires_at);
19209
- if (expiry !== void 0 && (nextExpiresAt === void 0 || expiry < nextExpiresAt)) {
19210
- nextExpiresAt = expiry;
19233
+ const expiry2 = safeTimestamp(credit.expires_at);
19234
+ if (expiry2 !== void 0 && (nextExpiresAt === void 0 || expiry2 < nextExpiresAt)) {
19235
+ nextExpiresAt = expiry2;
19211
19236
  }
19212
19237
  }
19213
19238
  return {
@@ -19227,7 +19252,7 @@ async function fetchCodexUsage(deps = {}) {
19227
19252
  if (credentials.accountId) headers["ChatGPT-Account-Id"] = credentials.accountId;
19228
19253
  try {
19229
19254
  const fetchImpl = deps.fetch ?? fetch;
19230
- const usage3 = parseCodexUsage(await getJson(fetchImpl, "https://chatgpt.com/backend-api/wham/usage", headers));
19255
+ const usage4 = parseCodexUsage(await getJson(fetchImpl, "https://chatgpt.com/backend-api/wham/usage", headers));
19231
19256
  let credits;
19232
19257
  try {
19233
19258
  credits = parseResetCredits(await getJson(
@@ -19240,8 +19265,8 @@ async function fetchCodexUsage(deps = {}) {
19240
19265
  }
19241
19266
  return {
19242
19267
  status: "ok",
19243
- plan: usage3.plan,
19244
- windows: usage3.windows,
19268
+ plan: usage4.plan,
19269
+ windows: usage4.windows,
19245
19270
  ...credits ? { credits } : {},
19246
19271
  fetchedAt: (deps.now ?? Date.now)()
19247
19272
  };
@@ -19355,12 +19380,12 @@ async function fetchCursorUsage(deps = {}) {
19355
19380
  };
19356
19381
  try {
19357
19382
  const fetchImpl = deps.fetch ?? fetch;
19358
- const usage3 = parseCursorUsage(await postJson(
19383
+ const usage4 = parseCursorUsage(await postJson(
19359
19384
  fetchImpl,
19360
19385
  "https://api2.cursor.sh/aiserver.v1.DashboardService/GetCurrentPeriodUsage",
19361
19386
  headers
19362
19387
  ));
19363
- if (usage3.status === "no_subscription") return { status: "no_subscription", method: credentials.method };
19388
+ if (usage4.status === "no_subscription") return { status: "no_subscription", method: credentials.method };
19364
19389
  let plan;
19365
19390
  try {
19366
19391
  const planRoot = object2(await postJson(
@@ -19376,8 +19401,8 @@ async function fetchCursorUsage(deps = {}) {
19376
19401
  status: "ok",
19377
19402
  method: credentials.method,
19378
19403
  ...plan ? { plan } : {},
19379
- ...usage3.cycleDays !== void 0 ? { cycleDays: usage3.cycleDays } : {},
19380
- windows: usage3.windows,
19404
+ ...usage4.cycleDays !== void 0 ? { cycleDays: usage4.cycleDays } : {},
19405
+ windows: usage4.windows,
19381
19406
  fetchedAt: (deps.now ?? Date.now)()
19382
19407
  };
19383
19408
  } catch (error51) {
@@ -19462,16 +19487,16 @@ async function fetchKimiUsage(deps = {}) {
19462
19487
  const apiKey = await deps.authService.getApiKey(KIMI_AUTH_PROVIDER_ID);
19463
19488
  if (!apiKey) return { status: "signed_out" };
19464
19489
  try {
19465
- const usage3 = parseKimiUsage(await getJson(
19490
+ const usage4 = parseKimiUsage(await getJson(
19466
19491
  deps.fetch ?? fetch,
19467
19492
  `${KIMI_CODE_API_BASE_URL}/v1/usages`,
19468
19493
  { Authorization: `Bearer ${apiKey}`, Accept: "application/json" }
19469
19494
  ));
19470
- if (usage3.status === "no_subscription") return { status: "no_subscription" };
19495
+ if (usage4.status === "no_subscription") return { status: "no_subscription" };
19471
19496
  return {
19472
19497
  status: "ok",
19473
- ...usage3.plan ? { plan: usage3.plan } : {},
19474
- windows: usage3.windows,
19498
+ ...usage4.plan ? { plan: usage4.plan } : {},
19499
+ windows: usage4.windows,
19475
19500
  fetchedAt: (deps.now ?? Date.now)()
19476
19501
  };
19477
19502
  } catch (error51) {
@@ -19681,6 +19706,268 @@ async function fetchOpencodeUsage(deps = {}) {
19681
19706
  fetchedAt: now()
19682
19707
  };
19683
19708
  }
19709
+ var XAI_OIDC_ISSUER = "https://auth.x.ai";
19710
+ var XAI_CLI_REFRESH_URL = "https://auth.x.ai/oauth2/token";
19711
+ var XAI_CLI_DEFAULT_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
19712
+ var XAI_CLI_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
19713
+ var REFRESH_TIMEOUT_MS = 15e3;
19714
+ var FALLBACK_ACCESS_TOKEN_TTL_MS = 36e5;
19715
+ function xaiCliAuthFilePath(deps) {
19716
+ return path32__default.join(deps.env.GROK_HOME || path32__default.join(deps.homedir(), ".grok"), "auth.json");
19717
+ }
19718
+ function expiry(value) {
19719
+ if (typeof value !== "string" && typeof value !== "number") return void 0;
19720
+ const parsed = typeof value === "number" ? value : Date.parse(value);
19721
+ if (!Number.isFinite(parsed)) return void 0;
19722
+ return parsed < 1e12 ? Math.round(parsed * 1e3) : Math.round(parsed);
19723
+ }
19724
+ function jwtExpiry(token) {
19725
+ const parts = token.split(".");
19726
+ if (parts.length < 2) return void 0;
19727
+ try {
19728
+ const payload = JSON.parse(Buffer.from(parts[1] ?? "", "base64url").toString("utf8"));
19729
+ const record4 = credentialRecord(payload);
19730
+ const exp = record4?.exp;
19731
+ if (typeof exp !== "number" || !Number.isFinite(exp)) return void 0;
19732
+ return Math.round(exp * 1e3);
19733
+ } catch {
19734
+ return void 0;
19735
+ }
19736
+ }
19737
+ function effectiveExpiry(entry, accessToken) {
19738
+ const fromEntry = expiry(entry.expires_at) ?? expiry(entry.expires);
19739
+ const fromJwt = jwtExpiry(accessToken);
19740
+ if (fromEntry !== void 0 && fromJwt !== void 0) return Math.min(fromEntry, fromJwt);
19741
+ return fromEntry ?? fromJwt;
19742
+ }
19743
+ function clientId(entryKey, entry) {
19744
+ const fromEntry = optionalTrimmedString(entry.oidc_client_id);
19745
+ if (fromEntry) return fromEntry;
19746
+ const suffix = optionalTrimmedString(entryKey.split("::").at(-1));
19747
+ return suffix ?? XAI_CLI_DEFAULT_CLIENT_ID;
19748
+ }
19749
+ function refreshToken(entry) {
19750
+ return optionalTrimmedString(entry.refresh_token) ?? optionalTrimmedString(entry.refresh);
19751
+ }
19752
+ async function defaultWriteAuthFile(filePath, contents) {
19753
+ const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
19754
+ try {
19755
+ await fs32.writeFile(tmpPath, contents, { encoding: "utf8", mode: 384 });
19756
+ await fs32.rename(tmpPath, filePath);
19757
+ } catch (error51) {
19758
+ await fs32.unlink(tmpPath).catch(() => void 0);
19759
+ throw error51;
19760
+ }
19761
+ }
19762
+ async function persistRefreshedEntry(deps, filePath, entryKey, expected, patch, writeAuthFile) {
19763
+ const raw = await deps.readBounded(filePath, MAX_CREDENTIAL_BYTES);
19764
+ if (raw === null) return;
19765
+ const auth = credentialRecord(JSON.parse(raw));
19766
+ if (!auth) return;
19767
+ const current = credentialRecord(auth[entryKey]);
19768
+ if (!current) return;
19769
+ if (optionalTrimmedString(current.key) !== expected.accessToken) return;
19770
+ if (expected.refreshToken !== void 0 && refreshToken(current) !== expected.refreshToken) return;
19771
+ auth[entryKey] = { ...current, ...patch };
19772
+ await writeAuthFile(filePath, `${JSON.stringify(auth, null, 2)}
19773
+ `);
19774
+ }
19775
+ async function refreshAccessToken(entryKey, entry, fetchImpl, now) {
19776
+ const token = refreshToken(entry);
19777
+ if (!token) return null;
19778
+ const controller = new AbortController();
19779
+ const timer = setTimeout(() => controller.abort(), REFRESH_TIMEOUT_MS);
19780
+ try {
19781
+ const body = new URLSearchParams({
19782
+ grant_type: "refresh_token",
19783
+ client_id: clientId(entryKey, entry),
19784
+ refresh_token: token
19785
+ });
19786
+ const response = await fetchImpl(XAI_CLI_REFRESH_URL, {
19787
+ method: "POST",
19788
+ headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json" },
19789
+ body,
19790
+ signal: controller.signal
19791
+ });
19792
+ if (!response.ok) return null;
19793
+ const payload = credentialRecord(await response.json());
19794
+ const accessToken = optionalTrimmedString(payload?.access_token);
19795
+ if (!accessToken) return null;
19796
+ const expiresIn = payload?.expires_in;
19797
+ const expiresAt = typeof expiresIn === "number" && Number.isFinite(expiresIn) && expiresIn > 0 ? now() + Math.round(expiresIn * 1e3) : jwtExpiry(accessToken) ?? now() + FALLBACK_ACCESS_TOKEN_TTL_MS;
19798
+ const rotated = optionalTrimmedString(payload?.refresh_token);
19799
+ return {
19800
+ accessToken,
19801
+ expiresAt,
19802
+ ...rotated === void 0 ? {} : { refreshToken: rotated }
19803
+ };
19804
+ } catch {
19805
+ return null;
19806
+ } finally {
19807
+ clearTimeout(timer);
19808
+ }
19809
+ }
19810
+ async function resolveXaiCliAuth(deps, options = {}) {
19811
+ const now = options.now ?? Date.now;
19812
+ const fetchImpl = options.fetch ?? fetch;
19813
+ const writeAuthFile = options.writeAuthFile ?? defaultWriteAuthFile;
19814
+ const filePath = xaiCliAuthFilePath(deps);
19815
+ try {
19816
+ const raw = await deps.readBounded(filePath, MAX_CREDENTIAL_BYTES);
19817
+ if (raw === null || raw.length > MAX_CREDENTIAL_BYTES) return { status: "signed_out" };
19818
+ const auth = credentialRecord(JSON.parse(raw));
19819
+ if (!auth) return { status: "signed_out" };
19820
+ let sawExpired = false;
19821
+ for (const [entryKey, value] of Object.entries(auth)) {
19822
+ if (!entryKey.startsWith(`${XAI_OIDC_ISSUER}::`)) continue;
19823
+ const entry = credentialRecord(value);
19824
+ const issuer = optionalTrimmedString(entry?.oidc_issuer);
19825
+ const accessToken = optionalTrimmedString(entry?.key);
19826
+ if (!entry || issuer !== XAI_OIDC_ISSUER || !accessToken) continue;
19827
+ const expiresAt = effectiveExpiry(entry, accessToken);
19828
+ const expired2 = expiresAt !== void 0 && expiresAt <= now();
19829
+ const needsRefresh = options.forceRefresh === true || expiresAt !== void 0 && expiresAt - now() <= XAI_CLI_REFRESH_BUFFER_MS;
19830
+ if (needsRefresh) {
19831
+ const refreshed = await refreshAccessToken(entryKey, entry, fetchImpl, now);
19832
+ if (refreshed) {
19833
+ const userId2 = optionalTrimmedString(entry.user_id) ?? optionalTrimmedString(entry.principal_id);
19834
+ const patch = {
19835
+ key: refreshed.accessToken,
19836
+ expires_at: new Date(refreshed.expiresAt).toISOString()
19837
+ };
19838
+ if (refreshed.refreshToken !== void 0) patch.refresh_token = refreshed.refreshToken;
19839
+ try {
19840
+ await persistRefreshedEntry(
19841
+ deps,
19842
+ filePath,
19843
+ entryKey,
19844
+ { accessToken, refreshToken: refreshToken(entry) },
19845
+ patch,
19846
+ writeAuthFile
19847
+ );
19848
+ } catch {
19849
+ }
19850
+ return {
19851
+ status: "ok",
19852
+ credentials: {
19853
+ accessToken: refreshed.accessToken,
19854
+ expiresAt: refreshed.expiresAt,
19855
+ ...userId2 === void 0 ? {} : { userId: userId2 }
19856
+ }
19857
+ };
19858
+ }
19859
+ if (options.forceRefresh === true || expired2) {
19860
+ sawExpired = true;
19861
+ continue;
19862
+ }
19863
+ } else if (expired2) {
19864
+ sawExpired = true;
19865
+ continue;
19866
+ }
19867
+ const userId = optionalTrimmedString(entry.user_id) ?? optionalTrimmedString(entry.principal_id);
19868
+ return {
19869
+ status: "ok",
19870
+ credentials: {
19871
+ accessToken,
19872
+ ...expiresAt === void 0 ? {} : { expiresAt },
19873
+ ...userId === void 0 ? {} : { userId }
19874
+ }
19875
+ };
19876
+ }
19877
+ return { status: sawExpired ? "expired" : "signed_out" };
19878
+ } catch {
19879
+ return { status: "signed_out" };
19880
+ }
19881
+ }
19882
+ var XAI_CLI_CREDITS_URL = "https://cli-chat-proxy.grok.com/v1/billing?format=credits";
19883
+ var WEEKLY_PERIOD = "USAGE_PERIOD_TYPE_WEEKLY";
19884
+ function parseXaiCredits(payload) {
19885
+ const root = object2(payload);
19886
+ const config2 = object2(root?.config);
19887
+ const period = object2(config2?.currentPeriod);
19888
+ const periodType = typeof period?.type === "string" ? period.type.trim() : "";
19889
+ if (!config2 || !period || periodType.length === 0) return null;
19890
+ const startsAt = safeTimestamp(period.start);
19891
+ const resetsAt = safeTimestamp(period.end);
19892
+ if (startsAt === void 0 || resetsAt === void 0 || resetsAt <= startsAt) return null;
19893
+ if (periodType !== WEEKLY_PERIOD) return { status: "other" };
19894
+ let usedPercent = 0;
19895
+ if (config2.creditUsagePercent !== void 0) {
19896
+ if (typeof config2.creditUsagePercent !== "number" || !Number.isFinite(config2.creditUsagePercent)) {
19897
+ return null;
19898
+ }
19899
+ usedPercent = percent(config2.creditUsagePercent);
19900
+ }
19901
+ return {
19902
+ status: "weekly",
19903
+ window: {
19904
+ id: "weekly",
19905
+ usedPercent,
19906
+ resetsAt,
19907
+ period: {
19908
+ durationMs: resetsAt - startsAt,
19909
+ durationBasis: "upstream",
19910
+ startsAt,
19911
+ startsAtBasis: "upstream"
19912
+ }
19913
+ }
19914
+ };
19915
+ }
19916
+ function creditsHeaders(credentials) {
19917
+ const headers = {
19918
+ Accept: "application/json",
19919
+ Authorization: `Bearer ${credentials.accessToken}`,
19920
+ "X-XAI-Token-Auth": "xai-grok-cli"
19921
+ };
19922
+ if (credentials.userId) headers["x-userid"] = credentials.userId;
19923
+ return headers;
19924
+ }
19925
+ async function fetchXaiUsage(deps = {}) {
19926
+ const credentialDeps = deps.credentials ?? defaultCredentialDeps;
19927
+ const now = deps.now ?? Date.now;
19928
+ const fetchImpl = deps.fetch ?? fetch;
19929
+ const auth = await resolveXaiCliAuth(credentialDeps, { now, fetch: fetchImpl });
19930
+ if (auth.status !== "ok") return { status: auth.status };
19931
+ const load = (credentials) => getJson(
19932
+ fetchImpl,
19933
+ XAI_CLI_CREDITS_URL,
19934
+ creditsHeaders(credentials)
19935
+ );
19936
+ try {
19937
+ let credentials = auth.credentials;
19938
+ let payload;
19939
+ try {
19940
+ payload = await load(credentials);
19941
+ } catch (error51) {
19942
+ if (!expired(error51)) throw error51;
19943
+ const retried = await resolveXaiCliAuth(credentialDeps, {
19944
+ now,
19945
+ fetch: fetchImpl,
19946
+ forceRefresh: true
19947
+ });
19948
+ if (retried.status !== "ok") return { status: "expired" };
19949
+ credentials = retried.credentials;
19950
+ try {
19951
+ payload = await load(credentials);
19952
+ } catch (retryError) {
19953
+ const result = expired(retryError);
19954
+ if (result) return result;
19955
+ throw retryError;
19956
+ }
19957
+ }
19958
+ const parsed = parseXaiCredits(payload);
19959
+ if (!parsed) throw new Error("Grok returned an unsupported quota response");
19960
+ return {
19961
+ status: "ok",
19962
+ windows: parsed.status === "weekly" ? [parsed.window] : [],
19963
+ fetchedAt: now()
19964
+ };
19965
+ } catch (error51) {
19966
+ const result = expired(error51);
19967
+ if (result) return result;
19968
+ throw error51;
19969
+ }
19970
+ }
19684
19971
  var CACHE_TTL_MS = 12e4;
19685
19972
  var STALE_TTL_MS = 18e5;
19686
19973
  function createAiGatewayQuotaCollectors(deps) {
@@ -19696,7 +19983,8 @@ function createAiGatewayQuotaCollectors(deps) {
19696
19983
  fetchCodex: () => fetchCodexUsage(providerDeps),
19697
19984
  fetchCursor: () => fetchCursorUsage(providerDeps),
19698
19985
  fetchKimi: () => fetchKimiUsage(providerDeps),
19699
- fetchOpencode: () => fetchOpencodeUsage(providerDeps)
19986
+ fetchOpencode: () => fetchOpencodeUsage(providerDeps),
19987
+ fetchXai: () => fetchXaiUsage(providerDeps)
19700
19988
  };
19701
19989
  }
19702
19990
  function isProviderSuccess(value) {
@@ -19709,7 +19997,8 @@ function createQuotaService(deps) {
19709
19997
  codex: deps.fetchCodex,
19710
19998
  cursor: deps.fetchCursor,
19711
19999
  kimi: deps.fetchKimi,
19712
- opencode: deps.fetchOpencode
20000
+ opencode: deps.fetchOpencode,
20001
+ xai: deps.fetchXai ?? (async () => ({ status: "signed_out" }))
19713
20002
  };
19714
20003
  const cache = /* @__PURE__ */ new Map();
19715
20004
  const lastGood = /* @__PURE__ */ new Map();
@@ -19752,12 +20041,13 @@ function createQuotaService(deps) {
19752
20041
  }
19753
20042
  return {
19754
20043
  async getSummary(options = {}) {
19755
- const [claude, codex, cursor, kimi, opencode] = await Promise.all([
20044
+ const [claude, codex, cursor, kimi, opencode, xai] = await Promise.all([
19756
20045
  load("claude", options.force === true || options.forceProvider === "claude"),
19757
20046
  load("codex", options.force === true || options.forceProvider === "codex"),
19758
20047
  load("cursor", options.force === true || options.forceProvider === "cursor"),
19759
20048
  load("kimi", options.force === true || options.forceProvider === "kimi"),
19760
- load("opencode", options.force === true || options.forceProvider === "opencode")
20049
+ load("opencode", options.force === true || options.forceProvider === "opencode"),
20050
+ load("xai", options.force === true || options.forceProvider === "xai")
19761
20051
  ]);
19762
20052
  return {
19763
20053
  providers: {
@@ -19765,7 +20055,8 @@ function createQuotaService(deps) {
19765
20055
  codex: withRisk(codex),
19766
20056
  cursor: withRisk(cursor),
19767
20057
  kimi: withRisk(kimi),
19768
- opencode: withRisk(opencode)
20058
+ opencode: withRisk(opencode),
20059
+ xai: withRisk(xai)
19769
20060
  }
19770
20061
  };
19771
20062
  }
@@ -20628,7 +20919,36 @@ messageDesc(cursorAgentFile, 63);
20628
20919
  messageDesc(cursorAgentFile, 70);
20629
20920
  new Set(REASONING_EFFORTS);
20630
20921
 
20922
+ // ../fleet-plugins/quota/provider-order.ts
20923
+ var PROVIDER_ORDER_DEFAULT = ["claude", "codex", "xai", "cursor", "opencode", "kimi"];
20924
+ function isProviderId(value) {
20925
+ return PROVIDER_ORDER_DEFAULT.includes(value);
20926
+ }
20927
+ function sanitizeProviderOrder(value) {
20928
+ const order = [];
20929
+ if (Array.isArray(value)) {
20930
+ for (const entry of value) {
20931
+ if (isProviderId(entry) && !order.includes(entry)) order.push(entry);
20932
+ }
20933
+ }
20934
+ for (const id of PROVIDER_ORDER_DEFAULT) {
20935
+ if (!order.includes(id)) order.push(id);
20936
+ }
20937
+ return order;
20938
+ }
20939
+
20631
20940
  // ../fleet-plugins/quota/server/handlers.ts
20941
+ async function readStoredSettings(ctx) {
20942
+ const stored = await ctx.host.storage.readJson("quota", "settings");
20943
+ return stored !== null && typeof stored === "object" && !Array.isArray(stored) ? stored : {};
20944
+ }
20945
+ function retainedSettings(settings) {
20946
+ return {
20947
+ ...typeof settings.claudeConnected === "boolean" ? { claudeConnected: settings.claudeConnected } : {},
20948
+ ...typeof settings.cursorConnected === "boolean" ? { cursorConnected: settings.cursorConnected } : {},
20949
+ ...Array.isArray(settings.providerOrder) ? { providerOrder: sanitizeProviderOrder(settings.providerOrder) } : {}
20950
+ };
20951
+ }
20632
20952
  async function handleSummary(req, res, ctx, service) {
20633
20953
  if (req.method !== "GET") {
20634
20954
  ctx.host.http.writeJson(res, 405, { error: "method_not_allowed" });
@@ -20639,7 +20959,9 @@ async function handleSummary(req, res, ctx, service) {
20639
20959
  return;
20640
20960
  }
20641
20961
  const url2 = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
20642
- ctx.host.http.writeJson(res, 200, await service.getSummary({ force: url2.searchParams.get("force") === "1" }));
20962
+ const summary = await service.getSummary({ force: url2.searchParams.get("force") === "1" });
20963
+ const providerOrder = sanitizeProviderOrder((await readStoredSettings(ctx)).providerOrder);
20964
+ ctx.host.http.writeJson(res, 200, { ...summary, providerOrder });
20643
20965
  }
20644
20966
  async function handleConnect(req, res, ctx, service, serializeSettings) {
20645
20967
  if (req.method !== "POST") {
@@ -20667,16 +20989,51 @@ async function handleConnect(req, res, ctx, service, serializeSettings) {
20667
20989
  return;
20668
20990
  }
20669
20991
  await serializeSettings(async () => {
20670
- const stored = await ctx.host.storage.readJson("quota", "settings");
20671
- const settings = stored !== null && typeof stored === "object" && !Array.isArray(stored) ? stored : {};
20672
20992
  const next = {
20673
- ...typeof settings.claudeConnected === "boolean" ? { claudeConnected: settings.claudeConnected } : {},
20674
- ...typeof settings.cursorConnected === "boolean" ? { cursorConnected: settings.cursorConnected } : {},
20993
+ ...retainedSettings(await readStoredSettings(ctx)),
20675
20994
  ...body.provider === "claude" ? { claudeConnected: body.connected } : { cursorConnected: body.connected }
20676
20995
  };
20677
20996
  await ctx.host.storage.writeJson("quota", "settings", next);
20678
20997
  });
20679
- ctx.host.http.writeJson(res, 200, await service.getSummary({ forceProvider: body.provider }));
20998
+ const summary = await service.getSummary({ forceProvider: body.provider });
20999
+ const providerOrder = sanitizeProviderOrder((await readStoredSettings(ctx)).providerOrder);
21000
+ ctx.host.http.writeJson(res, 200, { ...summary, providerOrder });
21001
+ }
21002
+ async function handleOrder(req, res, ctx, serializeSettings) {
21003
+ if (req.method !== "POST") {
21004
+ ctx.host.http.writeJson(res, 405, { error: "method_not_allowed" });
21005
+ return;
21006
+ }
21007
+ if (!ctx.host.security.isTerminalAuthorized(req)) {
21008
+ ctx.host.http.writeJson(res, 401, { error: "unauthorized" });
21009
+ return;
21010
+ }
21011
+ const contentType = req.headers["content-type"];
21012
+ const mediaType = typeof contentType === "string" ? contentType.split(";", 1)[0]?.trim().toLowerCase() : void 0;
21013
+ if (mediaType !== "application/json") {
21014
+ ctx.host.http.writeJson(res, 415, { error: "unsupported_media_type" });
21015
+ return;
21016
+ }
21017
+ let body;
21018
+ try {
21019
+ body = await ctx.host.http.readJsonBody(req);
21020
+ } catch {
21021
+ body = null;
21022
+ }
21023
+ const order = body?.order;
21024
+ if (!body || Object.keys(body).length !== 1 || !Array.isArray(order) || order.length !== PROVIDER_ORDER_DEFAULT.length || !order.every(isProviderId) || new Set(order).size !== order.length) {
21025
+ ctx.host.http.writeJson(res, 400, { error: "invalid_order_request" });
21026
+ return;
21027
+ }
21028
+ const providerOrder = order;
21029
+ await serializeSettings(async () => {
21030
+ const next = {
21031
+ ...retainedSettings(await readStoredSettings(ctx)),
21032
+ providerOrder
21033
+ };
21034
+ await ctx.host.storage.writeJson("quota", "settings", next);
21035
+ });
21036
+ ctx.host.http.writeJson(res, 200, { providerOrder });
20680
21037
  }
20681
21038
 
20682
21039
  // ../fleet-plugins/quota/routes.ts
@@ -20709,6 +21066,10 @@ var routes_default = definePlugin({
20709
21066
  await handleConnect(req, res, ctx, service, serializeSettings);
20710
21067
  return true;
20711
21068
  }, { method: "POST", path: "", summary: "Update provider quota connection state.", category: "Quota Plugin", gate: "origin-write", transport: "http" });
21069
+ registerRouter(ctx, "order", async ({ req, res }) => {
21070
+ await handleOrder(req, res, ctx, serializeSettings);
21071
+ return true;
21072
+ }, { method: "POST", path: "", summary: "Persist the provider card order.", category: "Quota Plugin", gate: "origin-write", transport: "http" });
20712
21073
  }
20713
21074
  });
20714
21075