@dotobokuri/fleet-console 1.44.1 → 1.46.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 (69) hide show
  1. package/dist/cli.d.ts +5 -1
  2. package/dist/cli.mjs +3297 -3831
  3. package/dist/client/assets/{_baseUniq-DfRTNtWd.js → _baseUniq-CaqaUUIT.js} +1 -1
  4. package/dist/client/assets/{arc-Ds9vyD8n.js → arc-B4MjkR5w.js} +1 -1
  5. package/dist/client/assets/{architectureDiagram-Q4EWVU46-pZ_1tCpx.js → architectureDiagram-Q4EWVU46-wP-4WWY-.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-DXYQGD6D-nntXWaQ9.js → blockDiagram-DXYQGD6D-D5Y2AdkX.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-AHTNJAMY-AHAd4NjZ.js → c4Diagram-AHTNJAMY-hKNJrUod.js} +1 -1
  8. package/dist/client/assets/channel-Cy7Wdt-y.js +1 -0
  9. package/dist/client/assets/{chunk-4BX2VUAB-BNfWXMb-.js → chunk-4BX2VUAB-RdaAserw.js} +1 -1
  10. package/dist/client/assets/{chunk-4TB4RGXK-B5MiBj0N.js → chunk-4TB4RGXK-BVvGheRq.js} +1 -1
  11. package/dist/client/assets/{chunk-55IACEB6-9vJ9AfWn.js → chunk-55IACEB6-BKBu793s.js} +1 -1
  12. package/dist/client/assets/{chunk-EDXVE4YY-CpxmITfr.js → chunk-EDXVE4YY-CF6P1HJI.js} +1 -1
  13. package/dist/client/assets/{chunk-FMBD7UC4-BoUi1EcN.js → chunk-FMBD7UC4-DYrffXxC.js} +1 -1
  14. package/dist/client/assets/{chunk-OYMX7WX6-s7qMNTfq.js → chunk-OYMX7WX6-ggkv39bf.js} +1 -1
  15. package/dist/client/assets/{chunk-QZHKN3VN-Bdgo-JE9.js → chunk-QZHKN3VN-DfsoMKS1.js} +1 -1
  16. package/dist/client/assets/{chunk-YZCP3GAM-C9RCb0eu.js → chunk-YZCP3GAM-nK3fd1vK.js} +1 -1
  17. package/dist/client/assets/classDiagram-6PBFFD2Q-BXKZy3mo.js +1 -0
  18. package/dist/client/assets/classDiagram-v2-HSJHXN6E-BXKZy3mo.js +1 -0
  19. package/dist/client/assets/clone-BaDkZwuY.js +1 -0
  20. package/dist/client/assets/{cose-bilkent-S5V4N54A-Mr2xbCPD.js → cose-bilkent-S5V4N54A-BXTuHPIj.js} +1 -1
  21. package/dist/client/assets/{dagre-KV5264BT-xIfrxsrb.js → dagre-KV5264BT-Bz4nIBUS.js} +1 -1
  22. package/dist/client/assets/{diagram-5BDNPKRD-BM49JRbq.js → diagram-5BDNPKRD-ByqgG2sy.js} +1 -1
  23. package/dist/client/assets/{diagram-G4DWMVQ6-uMduxuqy.js → diagram-G4DWMVQ6-D6Bh5CCC.js} +1 -1
  24. package/dist/client/assets/{diagram-MMDJMWI5-BfCnnu9a.js → diagram-MMDJMWI5-CfDQLuVW.js} +1 -1
  25. package/dist/client/assets/{diagram-TYMM5635-DTVL_WEx.js → diagram-TYMM5635-KI98IUyc.js} +1 -1
  26. package/dist/client/assets/{erDiagram-SMLLAGMA-BUQDjGU2.js → erDiagram-SMLLAGMA-CqprUEiC.js} +1 -1
  27. package/dist/client/assets/{flowDiagram-DWJPFMVM-RZ85tRp5.js → flowDiagram-DWJPFMVM-ABvSPDqG.js} +1 -1
  28. package/dist/client/assets/{ganttDiagram-T4ZO3ILL-CenzFyys.js → ganttDiagram-T4ZO3ILL-Dsx-U_Nn.js} +1 -1
  29. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-BpkFTm7f.js → gitGraphDiagram-UUTBAWPF-BSUFEUnR.js} +1 -1
  30. package/dist/client/assets/{graph-BlyDgw2r.js → graph-CzNfjcWq.js} +1 -1
  31. package/dist/client/assets/index-DJz5h6Wn.js +482 -0
  32. package/dist/client/assets/index-DuMyAui7.css +1 -0
  33. package/dist/client/assets/{infoDiagram-42DDH7IO-ZB4pKXQT.js → infoDiagram-42DDH7IO-Ds0ENS7R.js} +1 -1
  34. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-BfXl0ksQ.js → ishikawaDiagram-UXIWVN3A-B18YRUdD.js} +1 -1
  35. package/dist/client/assets/{journeyDiagram-VCZTEJTY-DCSluqxm.js → journeyDiagram-VCZTEJTY-BupFc-Zd.js} +1 -1
  36. package/dist/client/assets/{kanban-definition-6JOO6SKY-5X3OxziR.js → kanban-definition-6JOO6SKY-BSLofAt_.js} +1 -1
  37. package/dist/client/assets/{layout-C2Jxamqz.js → layout-Dv50_a5m.js} +1 -1
  38. package/dist/client/assets/{linear-DgO5otCG.js → linear-BrKghOcX.js} +1 -1
  39. package/dist/client/assets/{mermaid.core-CqKupZd5.js → mermaid.core-CxEBNiNY.js} +4 -4
  40. package/dist/client/assets/{min-B9jNVA7s.js → min-CCGzVC9y.js} +1 -1
  41. package/dist/client/assets/{mindmap-definition-QFDTVHPH-B_Clh0rq.js → mindmap-definition-QFDTVHPH-BrgndQgy.js} +1 -1
  42. package/dist/client/assets/{pieDiagram-DEJITSTG-D1rR7mwo.js → pieDiagram-DEJITSTG-DaQb845q.js} +1 -1
  43. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-CGnU5k3k.js → quadrantDiagram-34T5L4WZ-BKqKJrUA.js} +1 -1
  44. package/dist/client/assets/{requirementDiagram-MS252O5E-BDFOsklw.js → requirementDiagram-MS252O5E-DDEiXfFB.js} +1 -1
  45. package/dist/client/assets/{sankeyDiagram-XADWPNL6-DT-8dpb6.js → sankeyDiagram-XADWPNL6-Bz8ZuIVc.js} +1 -1
  46. package/dist/client/assets/{sequenceDiagram-FGHM5R23-3IY8NxLM.js → sequenceDiagram-FGHM5R23-DIKllaFC.js} +1 -1
  47. package/dist/client/assets/{stateDiagram-FHFEXIEX-DqaGlW3D.js → stateDiagram-FHFEXIEX-DVGXi05S.js} +1 -1
  48. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-BpjJbYdv.js +1 -0
  49. package/dist/client/assets/{timeline-definition-GMOUNBTQ-DmOlxq0r.js → timeline-definition-GMOUNBTQ-BysxZqEH.js} +1 -1
  50. package/dist/client/assets/{vennDiagram-DHZGUBPP-UsUm6iWZ.js → vennDiagram-DHZGUBPP-zKrKFH0U.js} +1 -1
  51. package/dist/client/assets/{wardley-RL74JXVD-C0JK7zQx.js → wardley-RL74JXVD-Bfs1dQE_.js} +1 -1
  52. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-pFHz6DzF.js → wardleyDiagram-NUSXRM2D-9Nv_Fl4e.js} +1 -1
  53. package/dist/client/assets/{xychartDiagram-5P7HB3ND-Cgy9Igjb.js → xychartDiagram-5P7HB3ND-BxnDNWHU.js} +1 -1
  54. package/dist/client/index.html +2 -2
  55. package/dist/fleet-plugins/file-explorer/routes.mjs +647 -648
  56. package/dist/fleet-plugins/ledger/routes.mjs +46 -110
  57. package/dist/fleet-plugins/quota/routes.mjs +590 -187
  58. package/dist/fleet-plugins/repository/routes.mjs +26 -11
  59. package/dist/fleet-plugins/scuttlebutt/routes.mjs +150 -707
  60. package/dist/fleet-plugins/skills/routes.mjs +46 -110
  61. package/dist/fleet-plugins/terminal/routes.mjs +6599 -7096
  62. package/package.json +1 -1
  63. package/dist/client/assets/channel-D_VyV3Fr.js +0 -1
  64. package/dist/client/assets/classDiagram-6PBFFD2Q-TBLL_03g.js +0 -1
  65. package/dist/client/assets/classDiagram-v2-HSJHXN6E-TBLL_03g.js +0 -1
  66. package/dist/client/assets/clone-CYDDwEhh.js +0 -1
  67. package/dist/client/assets/index-BAMerP8r.js +0 -452
  68. package/dist/client/assets/index-BmGY-BNs.css +0 -1
  69. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-2tlPZvTx.js +0 -1
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import * as fs5 from 'fs';
3
- import { constants } from 'fs';
4
- import * as path9 from 'path';
5
- import path9__default from 'path';
6
- import * as os3 from 'os';
7
- import os3__default from 'os';
8
2
  import { execFile } from 'child_process';
9
- import fs8 from 'fs/promises';
3
+ import * as fs5 from 'fs';
4
+ import fs5__default, { constants } from 'fs';
5
+ import fs from 'fs/promises';
6
+ import * as os4 from 'os';
7
+ import os4__default from 'os';
8
+ import * as path from 'path';
9
+ import path__default from 'path';
10
10
  import { promisify } from 'util';
11
11
 
12
12
  var __defProp = Object.defineProperty;
@@ -19,12 +19,12 @@ var __export = (target, all) => {
19
19
  function definePlugin(definition) {
20
20
  return definition;
21
21
  }
22
- function registerRouter(ctx, path10, handler) {
23
- ctx.registerRouter(normalizePath(path10), handler);
22
+ function registerRouter(ctx, path12, handler) {
23
+ ctx.registerRouter(normalizePath(path12), handler);
24
24
  }
25
- function normalizePath(path10) {
26
- if (path10.length === 0 || path10 === "/") return "/";
27
- return path10;
25
+ function normalizePath(path12) {
26
+ if (path12.length === 0 || path12 === "/") return "/";
27
+ return path12;
28
28
  }
29
29
 
30
30
  // ../fleet-plugins/quota/server/handlers.ts
@@ -840,10 +840,10 @@ function mergeDefs(...defs) {
840
840
  function cloneDef(schema) {
841
841
  return mergeDefs(schema._zod.def);
842
842
  }
843
- function getElementAtPath(obj, path10) {
844
- if (!path10)
843
+ function getElementAtPath(obj, path12) {
844
+ if (!path12)
845
845
  return obj;
846
- return path10.reduce((acc, key) => acc?.[key], obj);
846
+ return path12.reduce((acc, key) => acc?.[key], obj);
847
847
  }
848
848
  function promiseAllObject(promisesObj) {
849
849
  const keys = Object.keys(promisesObj);
@@ -1252,11 +1252,11 @@ function explicitlyAborted(x, startIndex = 0) {
1252
1252
  }
1253
1253
  return false;
1254
1254
  }
1255
- function prefixIssues(path10, issues) {
1255
+ function prefixIssues(path12, issues) {
1256
1256
  return issues.map((iss) => {
1257
1257
  var _a3;
1258
1258
  (_a3 = iss).path ?? (_a3.path = []);
1259
- iss.path.unshift(path10);
1259
+ iss.path.unshift(path12);
1260
1260
  return iss;
1261
1261
  });
1262
1262
  }
@@ -1403,16 +1403,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1403
1403
  }
1404
1404
  function formatError(error51, mapper = (issue2) => issue2.message) {
1405
1405
  const fieldErrors = { _errors: [] };
1406
- const processError = (error52, path10 = []) => {
1406
+ const processError = (error52, path12 = []) => {
1407
1407
  for (const issue2 of error52.issues) {
1408
1408
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1409
- issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
1409
+ issue2.errors.map((issues) => processError({ issues }, [...path12, ...issue2.path]));
1410
1410
  } else if (issue2.code === "invalid_key") {
1411
- processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
1411
+ processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
1412
1412
  } else if (issue2.code === "invalid_element") {
1413
- processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
1413
+ processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
1414
1414
  } else {
1415
- const fullpath = [...path10, ...issue2.path];
1415
+ const fullpath = [...path12, ...issue2.path];
1416
1416
  if (fullpath.length === 0) {
1417
1417
  fieldErrors._errors.push(mapper(issue2));
1418
1418
  } else {
@@ -1439,17 +1439,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1439
1439
  }
1440
1440
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1441
1441
  const result = { errors: [] };
1442
- const processError = (error52, path10 = []) => {
1442
+ const processError = (error52, path12 = []) => {
1443
1443
  var _a3, _b;
1444
1444
  for (const issue2 of error52.issues) {
1445
1445
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1446
- issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
1446
+ issue2.errors.map((issues) => processError({ issues }, [...path12, ...issue2.path]));
1447
1447
  } else if (issue2.code === "invalid_key") {
1448
- processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
1448
+ processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
1449
1449
  } else if (issue2.code === "invalid_element") {
1450
- processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
1450
+ processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
1451
1451
  } else {
1452
- const fullpath = [...path10, ...issue2.path];
1452
+ const fullpath = [...path12, ...issue2.path];
1453
1453
  if (fullpath.length === 0) {
1454
1454
  result.errors.push(mapper(issue2));
1455
1455
  continue;
@@ -1481,8 +1481,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1481
1481
  }
1482
1482
  function toDotPath(_path) {
1483
1483
  const segs = [];
1484
- const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1485
- for (const seg of path10) {
1484
+ const path12 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1485
+ for (const seg of path12) {
1486
1486
  if (typeof seg === "number")
1487
1487
  segs.push(`[${seg}]`);
1488
1488
  else if (typeof seg === "symbol")
@@ -14146,13 +14146,13 @@ function resolveRef(ref, ctx) {
14146
14146
  if (!ref.startsWith("#")) {
14147
14147
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14148
14148
  }
14149
- const path10 = ref.slice(1).split("/").filter(Boolean);
14150
- if (path10.length === 0) {
14149
+ const path12 = ref.slice(1).split("/").filter(Boolean);
14150
+ if (path12.length === 0) {
14151
14151
  return ctx.rootSchema;
14152
14152
  }
14153
14153
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14154
- if (path10[0] === defsKey) {
14155
- const key = path10[1];
14154
+ if (path12[0] === defsKey) {
14155
+ const key = path12[1];
14156
14156
  if (!key || !ctx.defs[key]) {
14157
14157
  throw new Error(`Reference not found: ${ref}`);
14158
14158
  }
@@ -17140,8 +17140,8 @@ function bootEnumDescriptorProto(init) {
17140
17140
  }
17141
17141
 
17142
17142
  // ../../node_modules/.pnpm/@bufbuild+protobuf@2.13.0/node_modules/@bufbuild/protobuf/dist/esm/codegenv2/message.js
17143
- function messageDesc(file2, path10, ...paths) {
17144
- return paths.reduce((acc, cur) => acc.nestedMessages[cur], file2.messages[path10]);
17143
+ function messageDesc(file2, path12, ...paths) {
17144
+ return paths.reduce((acc, cur) => acc.nestedMessages[cur], file2.messages[path12]);
17145
17145
  }
17146
17146
 
17147
17147
  // ../../node_modules/.pnpm/@bufbuild+protobuf@2.13.0/node_modules/@bufbuild/protobuf/dist/esm/wkt/gen/google/protobuf/descriptor_pb.js
@@ -17497,8 +17497,6 @@ function fileDesc(b64, imports) {
17497
17497
  const reg = createFileRegistry(root, (protoFileName) => void 0 );
17498
17498
  return reg.getFile(root.name);
17499
17499
  }
17500
-
17501
- // ../../packages/core-ai-gateway/dist/index.js
17502
17500
  var REASONING_EFFORTS = [
17503
17501
  "minimal",
17504
17502
  "low",
@@ -17513,7 +17511,7 @@ new Map(
17513
17511
  );
17514
17512
  var models_default = {
17515
17513
  version: 1,
17516
- updatedAt: "2026-08-01T00:00:00Z",
17514
+ updatedAt: "2026-08-03T00:00:00Z",
17517
17515
  providers: {
17518
17516
  codex: {
17519
17517
  name: "Codex",
@@ -17798,10 +17796,162 @@ var models_default = {
17798
17796
  ]
17799
17797
  }
17800
17798
  ]
17799
+ },
17800
+ opencode: {
17801
+ name: "OpenCode",
17802
+ defaultModel: "minimax-m3",
17803
+ source: "live GET https://opencode.ai/zen/go/v1/models + per-model wire probes on /messages, /responses, /chat/completions (2026-08-03); contextWindow cross-checked against models.dev api.json opencode-go entries and oh-my-pi packages/catalog/src/models.json (2026-08-03, both agree). Excluded: mimo-v2-pro/mimo-v2-omni (upstream server_error), hy3-preview (listed but Router.ModelNotFound)",
17804
+ models: [
17805
+ {
17806
+ modelId: "minimax-m3",
17807
+ name: "MiniMax-M3",
17808
+ contextWindow: 1e6
17809
+ },
17810
+ {
17811
+ modelId: "minimax-m2.7",
17812
+ name: "MiniMax-M2.7",
17813
+ contextWindow: 204800
17814
+ },
17815
+ {
17816
+ modelId: "minimax-m2.5",
17817
+ name: "MiniMax-M2.5",
17818
+ contextWindow: 204800
17819
+ },
17820
+ {
17821
+ modelId: "qwen3.8-max",
17822
+ name: "Qwen3.8-Max",
17823
+ contextWindow: 1e6
17824
+ },
17825
+ {
17826
+ modelId: "qwen3.7-max",
17827
+ name: "Qwen3.7-Max",
17828
+ contextWindow: 1e6
17829
+ },
17830
+ {
17831
+ modelId: "qwen3.7-plus",
17832
+ name: "Qwen3.7-Plus",
17833
+ contextWindow: 1e6
17834
+ },
17835
+ {
17836
+ modelId: "qwen3.6-plus",
17837
+ name: "Qwen3.6-Plus",
17838
+ contextWindow: 1e6
17839
+ },
17840
+ {
17841
+ modelId: "qwen3.5-plus",
17842
+ name: "Qwen3.5-Plus",
17843
+ contextWindow: 262144
17844
+ },
17845
+ {
17846
+ modelId: "gpt-5.6-luna",
17847
+ name: "GPT-5.6-Luna",
17848
+ wire: "responses",
17849
+ contextWindow: 105e4,
17850
+ effort: {
17851
+ supported: true,
17852
+ levels: [
17853
+ "low",
17854
+ "medium",
17855
+ "high",
17856
+ "xhigh",
17857
+ "max"
17858
+ ]
17859
+ }
17860
+ },
17861
+ {
17862
+ modelId: "grok-4.5",
17863
+ name: "Grok-4.5",
17864
+ wire: "responses",
17865
+ contextWindow: 5e5,
17866
+ effort: {
17867
+ supported: true,
17868
+ levels: [
17869
+ "low",
17870
+ "medium",
17871
+ "high"
17872
+ ]
17873
+ }
17874
+ },
17875
+ {
17876
+ modelId: "deepseek-v4-flash",
17877
+ name: "DeepSeek-V4-Flash",
17878
+ wire: "chat-completions",
17879
+ contextWindow: 1e6
17880
+ },
17881
+ {
17882
+ modelId: "deepseek-v4-pro",
17883
+ name: "DeepSeek-V4-Pro",
17884
+ wire: "chat-completions",
17885
+ contextWindow: 1e6
17886
+ },
17887
+ {
17888
+ modelId: "glm-5.2",
17889
+ name: "GLM-5.2",
17890
+ wire: "chat-completions",
17891
+ contextWindow: 1e6
17892
+ },
17893
+ {
17894
+ modelId: "glm-5.1",
17895
+ name: "GLM-5.1",
17896
+ wire: "chat-completions",
17897
+ contextWindow: 202752
17898
+ },
17899
+ {
17900
+ modelId: "glm-5",
17901
+ name: "GLM-5",
17902
+ wire: "chat-completions",
17903
+ contextWindow: 202752
17904
+ },
17905
+ {
17906
+ modelId: "kimi-k3",
17907
+ name: "Kimi-K3",
17908
+ wire: "chat-completions",
17909
+ contextWindow: 1048576
17910
+ },
17911
+ {
17912
+ modelId: "kimi-k2.7-code",
17913
+ name: "Kimi-K2.7-Code",
17914
+ wire: "chat-completions",
17915
+ contextWindow: 262144
17916
+ },
17917
+ {
17918
+ modelId: "kimi-k2.6",
17919
+ name: "Kimi-K2.6",
17920
+ wire: "chat-completions",
17921
+ contextWindow: 262144
17922
+ },
17923
+ {
17924
+ modelId: "kimi-k2.5",
17925
+ name: "Kimi-K2.5",
17926
+ wire: "chat-completions",
17927
+ contextWindow: 262144
17928
+ },
17929
+ {
17930
+ modelId: "mimo-v2.5-pro",
17931
+ name: "MiMo-V2.5-Pro",
17932
+ wire: "chat-completions",
17933
+ contextWindow: 1048576
17934
+ },
17935
+ {
17936
+ modelId: "mimo-v2.5",
17937
+ name: "MiMo-V2.5",
17938
+ wire: "chat-completions",
17939
+ contextWindow: 1e6
17940
+ },
17941
+ {
17942
+ modelId: "hy3",
17943
+ name: "HY3",
17944
+ wire: "chat-completions",
17945
+ contextWindow: 256e3
17946
+ }
17947
+ ]
17801
17948
  }
17802
17949
  }
17803
17950
  };
17804
- var GATEWAY_PROVIDERS = ["codex", "cursor", "kimi"];
17951
+ var KIMI_AUTH_PROVIDER_ID = "Claude Code with Moonshot Kimi";
17952
+ var KIMI_CODE_API_BASE_URL = "https://api.kimi.com/coding";
17953
+ var GATEWAY_PROVIDERS = ["codex", "cursor", "kimi", "opencode"];
17954
+ var GATEWAY_MODEL_WIRES = ["anthropic", "responses", "chat-completions"];
17805
17955
  var GATEWAY_REASONING_EFFORTS = [
17806
17956
  "low",
17807
17957
  "medium",
@@ -17834,6 +17984,7 @@ var GatewayModelEntrySchema = external_exports.object({
17834
17984
  serviceTier: external_exports.literal("priority").optional(),
17835
17985
  cursorMaxMode: external_exports.literal(true).optional(),
17836
17986
  quotaScope: external_exports.enum(GATEWAY_QUOTA_SCOPES).optional(),
17987
+ wire: external_exports.enum(GATEWAY_MODEL_WIRES).optional(),
17837
17988
  aliases: external_exports.array(external_exports.string().min(1)).optional(),
17838
17989
  contextWindow: external_exports.number().int().positive().optional(),
17839
17990
  effort: GatewayModelEffortSchema.optional()
@@ -17850,7 +18001,8 @@ var GatewayModelsRegistrySchema = external_exports.object({
17850
18001
  providers: external_exports.object({
17851
18002
  codex: GatewayProviderSchema,
17852
18003
  cursor: GatewayProviderSchema,
17853
- kimi: GatewayProviderSchema
18004
+ kimi: GatewayProviderSchema,
18005
+ opencode: GatewayProviderSchema
17854
18006
  }).strict()
17855
18007
  }).strict();
17856
18008
  var UNSUPPORTED_GATEWAY_MODEL_EFFORT = Object.freeze({ supported: false });
@@ -17875,6 +18027,7 @@ var GATEWAY_MODELS = Object.freeze(
17875
18027
  providerModels("codex");
17876
18028
  providerModels("cursor");
17877
18029
  providerModels("kimi");
18030
+ providerModels("opencode");
17878
18031
  function upstreamModelId(model) {
17879
18032
  return model.upstreamId ?? model.id;
17880
18033
  }
@@ -17900,6 +18053,7 @@ function toGatewayModel(provider, providerName, entry) {
17900
18053
  ...entry.serviceTier ? { serviceTier: entry.serviceTier } : {},
17901
18054
  ...entry.cursorMaxMode ? { cursorMaxMode: entry.cursorMaxMode } : {},
17902
18055
  ...entry.quotaScope ? { quotaScope: entry.quotaScope } : {},
18056
+ ...entry.wire ? { wire: entry.wire } : {},
17903
18057
  ...entry.description ? { description: entry.description } : {},
17904
18058
  ...entry.contextWindow ? { contextWindow: entry.contextWindow } : {},
17905
18059
  effort: freezeGatewayModelEffort(entry.effort),
@@ -17934,6 +18088,9 @@ function validateRegistry(value) {
17934
18088
  if (model.quotaScope && provider !== "cursor") {
17935
18089
  throw new Error(`Gateway quota scope is only supported by Cursor: ${provider}/${model.modelId}`);
17936
18090
  }
18091
+ if (model.wire && provider !== "opencode") {
18092
+ throw new Error(`Gateway model wire is only supported by OpenCode: ${provider}/${model.modelId}`);
18093
+ }
17937
18094
  if (model.effort?.supported) {
17938
18095
  if (new Set(model.effort.levels).size !== model.effort.levels.length) {
17939
18096
  throw new Error(`Gateway effort levels contain duplicates: ${provider}/${model.modelId}`);
@@ -18761,11 +18918,123 @@ messageDesc(cursorAgentFile, 119);
18761
18918
  messageDesc(cursorAgentFile, 53);
18762
18919
  messageDesc(cursorAgentFile, 63);
18763
18920
  messageDesc(cursorAgentFile, 70);
18764
- var KIMI_AUTH_PROVIDER_ID = "Claude Code with Moonshot Kimi";
18765
- var KIMI_CODE_API_BASE_URL = "https://api.kimi.com/coding";
18921
+ var execFileAsync = promisify(execFile);
18922
+ var MAX_CREDENTIAL_BYTES = 65536;
18923
+ var CREDENTIAL_OPEN_FLAGS = process.platform === "win32" ? constants.O_RDONLY : constants.O_RDONLY | constants.O_NONBLOCK;
18924
+ async function readBoundedFile(filePath, maxBytes) {
18925
+ const handle = await fs.open(filePath, CREDENTIAL_OPEN_FLAGS);
18926
+ try {
18927
+ const stat = await handle.stat();
18928
+ if (!stat.isFile() || stat.size > maxBytes) return null;
18929
+ const buffer = Buffer.allocUnsafe(maxBytes + 1);
18930
+ let totalBytes = 0;
18931
+ while (totalBytes < buffer.byteLength) {
18932
+ const { bytesRead } = await handle.read(
18933
+ buffer,
18934
+ totalBytes,
18935
+ buffer.byteLength - totalBytes,
18936
+ totalBytes
18937
+ );
18938
+ if (bytesRead === 0) break;
18939
+ totalBytes += bytesRead;
18940
+ }
18941
+ return totalBytes > maxBytes ? null : buffer.subarray(0, totalBytes).toString("utf8");
18942
+ } finally {
18943
+ await handle.close();
18944
+ }
18945
+ }
18946
+ var defaultCredentialDeps = {
18947
+ platform: process.platform,
18948
+ homedir: os4__default.homedir,
18949
+ env: process.env,
18950
+ readBounded: readBoundedFile,
18951
+ execFile: async (file2, args, options) => {
18952
+ const result = await execFileAsync(file2, [...args], options);
18953
+ return result.stdout;
18954
+ }
18955
+ };
18956
+ function credentialRecord(value) {
18957
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
18958
+ }
18959
+ function optionalNonEmptyString(value) {
18960
+ return typeof value === "string" && value.length > 0 ? value : void 0;
18961
+ }
18962
+ function optionalTrimmedString(value) {
18963
+ if (typeof value !== "string") return void 0;
18964
+ const trimmed = value.trim();
18965
+ return trimmed.length > 0 ? trimmed : void 0;
18966
+ }
18967
+ function parseCursorCredentialJson(raw, method) {
18968
+ if (raw.length > MAX_CREDENTIAL_BYTES) return null;
18969
+ try {
18970
+ const parsed = credentialRecord(JSON.parse(raw));
18971
+ if (!parsed) return null;
18972
+ const tokens = credentialRecord(parsed.tokens);
18973
+ const cursorAuth = credentialRecord(parsed.cursorAuth);
18974
+ const accessToken = [
18975
+ parsed.accessToken,
18976
+ parsed.access_token,
18977
+ tokens?.accessToken,
18978
+ tokens?.access_token,
18979
+ cursorAuth?.accessToken,
18980
+ cursorAuth?.access_token
18981
+ ].map(optionalTrimmedString).find((value) => value !== void 0);
18982
+ return accessToken ? { accessToken, method } : null;
18983
+ } catch {
18984
+ return null;
18985
+ }
18986
+ }
18987
+ function cursorAuthFilePath(deps) {
18988
+ const home = deps.homedir();
18989
+ if (deps.platform === "win32") {
18990
+ return path__default.join(deps.env.APPDATA || path__default.join(home, "AppData", "Roaming"), "Cursor", "auth.json");
18991
+ }
18992
+ if (deps.platform === "darwin") {
18993
+ return path__default.join(home, ".cursor", "auth.json");
18994
+ }
18995
+ return path__default.join(deps.env.XDG_CONFIG_HOME || path__default.join(home, ".config"), "cursor", "auth.json");
18996
+ }
18997
+ async function resolveCursorCredentials(deps) {
18998
+ if (deps.platform === "darwin") {
18999
+ try {
19000
+ const raw = await deps.execFile(
19001
+ "security",
19002
+ ["find-generic-password", "-s", "cursor-access-token", "-a", "cursor-user", "-w"],
19003
+ { timeout: 5e3 }
19004
+ );
19005
+ const accessToken = raw.length <= MAX_CREDENTIAL_BYTES ? optionalTrimmedString(raw) : void 0;
19006
+ if (accessToken) return { accessToken, method: "keychain" };
19007
+ } catch {
19008
+ }
19009
+ }
19010
+ try {
19011
+ const raw = await deps.readBounded(cursorAuthFilePath(deps), MAX_CREDENTIAL_BYTES);
19012
+ return raw === null || raw.length > MAX_CREDENTIAL_BYTES ? null : parseCursorCredentialJson(raw, "file");
19013
+ } catch {
19014
+ return null;
19015
+ }
19016
+ }
19017
+ function codexAuthFilePath(deps) {
19018
+ return path__default.join(deps.env.CODEX_HOME || path__default.join(deps.homedir(), ".codex"), "auth.json");
19019
+ }
19020
+ async function resolveCodexCredentials(deps) {
19021
+ try {
19022
+ const raw = await deps.readBounded(codexAuthFilePath(deps), MAX_CREDENTIAL_BYTES);
19023
+ if (raw === null || raw.length > MAX_CREDENTIAL_BYTES) return null;
19024
+ const parsed = credentialRecord(JSON.parse(raw));
19025
+ const tokens = credentialRecord(parsed?.tokens);
19026
+ const accessToken = optionalNonEmptyString(tokens?.access_token);
19027
+ if (!accessToken) return null;
19028
+ const accountId = optionalNonEmptyString(tokens?.account_id);
19029
+ return accountId === void 0 ? { accessToken } : { accessToken, accountId };
19030
+ } catch {
19031
+ return null;
19032
+ }
19033
+ }
19034
+ var OPENCODE_AUTH_PROVIDER_ID = "Claude Code with OpenCode Go";
18766
19035
  var FLEET_DATA_DIR_NAME = ".fleet";
18767
19036
  function getFleetDataDir() {
18768
- return path9.join(os3.homedir(), FLEET_DATA_DIR_NAME);
19037
+ return path.join(os4.homedir(), FLEET_DATA_DIR_NAME);
18769
19038
  }
18770
19039
  var SECURE_DIR_MODE = 448;
18771
19040
  var SECURE_FILE_MODE = 384;
@@ -18801,7 +19070,7 @@ function ensureSafeDirectory(dirPath) {
18801
19070
  var DEFAULT_MAX_ATTEMPTS = 10;
18802
19071
  var IGNORED_FSYNC_ERROR_CODES = /* @__PURE__ */ new Set(["EPERM", "EINVAL", "ENOSYS"]);
18803
19072
  function buildTempPath(filePath) {
18804
- const suffix = `${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.${os3.hostname()}`;
19073
+ const suffix = `${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.${os4.hostname()}`;
18805
19074
  return `${filePath}.${suffix}.tmp`;
18806
19075
  }
18807
19076
  function writeAtomicSync(filePath, content, options = {}) {
@@ -18934,10 +19203,10 @@ function buildQuarantinePath(lockDir) {
18934
19203
  function writeLockOwner(lockDir, ownerFileName, startedAt) {
18935
19204
  const owner = {
18936
19205
  pid: process.pid,
18937
- hostname: os3.hostname(),
19206
+ hostname: os4.hostname(),
18938
19207
  startedAt
18939
19208
  };
18940
- const ownerPath = path9.join(lockDir, ownerFileName);
19209
+ const ownerPath = path.join(lockDir, ownerFileName);
18941
19210
  try {
18942
19211
  fs5.writeFileSync(ownerPath, JSON.stringify(owner), { encoding: "utf-8", mode: 384 });
18943
19212
  } catch (error51) {
@@ -18946,7 +19215,7 @@ function writeLockOwner(lockDir, ownerFileName, startedAt) {
18946
19215
  }
18947
19216
  }
18948
19217
  function readLockOwner(lockDir, ownerFileName) {
18949
- const ownerPath = path9.join(lockDir, ownerFileName);
19218
+ const ownerPath = path.join(lockDir, ownerFileName);
18950
19219
  try {
18951
19220
  return sanitizeLockOwner(JSON.parse(fs5.readFileSync(ownerPath, "utf-8")));
18952
19221
  } catch (error51) {
@@ -18956,7 +19225,7 @@ function readLockOwner(lockDir, ownerFileName) {
18956
19225
  }
18957
19226
  }
18958
19227
  function isRecoverableOwner(owner, now, staleLockMs) {
18959
- if (owner.hostname !== os3.hostname()) return false;
19228
+ if (owner.hostname !== os4.hostname()) return false;
18960
19229
  if (now() - owner.startedAt < staleLockMs) return false;
18961
19230
  return !isProcessAlive(owner.pid);
18962
19231
  }
@@ -18986,10 +19255,10 @@ function isProcessAlive(pid) {
18986
19255
  }
18987
19256
  function sanitizeLockOwner(value) {
18988
19257
  if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
18989
- const record3 = value;
18990
- const pid = record3.pid;
18991
- const hostname5 = record3.hostname;
18992
- const startedAt = record3.startedAt;
19258
+ const record2 = value;
19259
+ const pid = record2.pid;
19260
+ const hostname5 = record2.hostname;
19261
+ const startedAt = record2.startedAt;
18993
19262
  if (!Number.isInteger(pid) || pid <= 0) return null;
18994
19263
  if (typeof hostname5 !== "string" || !hostname5) return null;
18995
19264
  if (!Number.isFinite(startedAt) || startedAt <= 0) return null;
@@ -19002,6 +19271,11 @@ function sanitizeLockOwner(value) {
19002
19271
  function sleepSync(ms) {
19003
19272
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
19004
19273
  }
19274
+
19275
+ // ../../packages/core-infra/src/auth/auth-storage.ts
19276
+ var DEFAULT_AUTH_PATH = path.join(getFleetDataDir(), "auth.json");
19277
+ var AUTH_LOCK_OWNER_FILE_NAME = "owner.json";
19278
+ var AUTH_LOCK_TIMEOUT_MS = 5e3;
19005
19279
  function readAuthStoreFile(filePath) {
19006
19280
  let fd;
19007
19281
  try {
@@ -19021,11 +19295,6 @@ function readAuthStoreFile(filePath) {
19021
19295
  }
19022
19296
  }
19023
19297
  }
19024
-
19025
- // ../../packages/core-infra/src/auth/auth-storage.ts
19026
- var DEFAULT_AUTH_PATH = path9.join(getFleetDataDir(), "auth.json");
19027
- var AUTH_LOCK_OWNER_FILE_NAME = "owner.json";
19028
- var AUTH_LOCK_TIMEOUT_MS = 5e3;
19029
19298
  function createAuthService(deps = {}) {
19030
19299
  const authPath = deps.authPath ?? DEFAULT_AUTH_PATH;
19031
19300
  const lockDir = `${authPath}.lock`;
@@ -19079,7 +19348,7 @@ function createAuthService(deps = {}) {
19079
19348
  }
19080
19349
  },
19081
19350
  async setApiKey(providerId, key) {
19082
- const dir = path9.dirname(authPath);
19351
+ const dir = path.dirname(authPath);
19083
19352
  ensureSafeDirectory(dir);
19084
19353
  withAuthLock(authPath, lockDir, () => {
19085
19354
  const data = fs5.existsSync(authPath) ? readAuthStoreFile(authPath) : {};
@@ -19109,61 +19378,18 @@ function writeAuthData(authPath, data) {
19109
19378
  fsync: true
19110
19379
  });
19111
19380
  }
19112
- var execFileAsync = promisify(execFile);
19113
- var MAX_CREDENTIAL_BYTES = 65536;
19114
- var CREDENTIAL_OPEN_FLAGS = process.platform === "win32" ? constants.O_RDONLY : constants.O_RDONLY | constants.O_NONBLOCK;
19115
- async function readBoundedFile(filePath, maxBytes) {
19116
- const handle = await fs8.open(filePath, CREDENTIAL_OPEN_FLAGS);
19117
- try {
19118
- const stat = await handle.stat();
19119
- if (!stat.isFile() || stat.size > maxBytes) return null;
19120
- const buffer = Buffer.allocUnsafe(maxBytes + 1);
19121
- let totalBytes = 0;
19122
- while (totalBytes < buffer.byteLength) {
19123
- const { bytesRead } = await handle.read(
19124
- buffer,
19125
- totalBytes,
19126
- buffer.byteLength - totalBytes,
19127
- totalBytes
19128
- );
19129
- if (bytesRead === 0) break;
19130
- totalBytes += bytesRead;
19131
- }
19132
- return totalBytes > maxBytes ? null : buffer.subarray(0, totalBytes).toString("utf8");
19133
- } finally {
19134
- await handle.close();
19135
- }
19136
- }
19137
- var defaultCredentialDeps = {
19138
- platform: process.platform,
19139
- homedir: os3__default.homedir,
19140
- env: process.env,
19141
- readBounded: readBoundedFile,
19142
- execFile: async (file2, args, options) => {
19143
- const result = await execFileAsync(file2, [...args], options);
19144
- return result.stdout;
19145
- }
19146
- };
19147
- function record2(value) {
19148
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
19149
- }
19150
19381
  function optionalString(value) {
19151
19382
  return typeof value === "string" && value.length > 0 ? value : void 0;
19152
19383
  }
19153
- function optionalTrimmedString(value) {
19154
- if (typeof value !== "string") return void 0;
19155
- const trimmed = value.trim();
19156
- return trimmed.length > 0 ? trimmed : void 0;
19157
- }
19158
19384
  function optionalEpoch(value) {
19159
19385
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
19160
19386
  }
19161
19387
  function parseClaudeCredentialJson(raw, method) {
19162
19388
  if (raw.length > MAX_CREDENTIAL_BYTES) return null;
19163
19389
  try {
19164
- const parsed = record2(JSON.parse(raw));
19390
+ const parsed = credentialRecord(JSON.parse(raw));
19165
19391
  if (!parsed) return null;
19166
- const oauth = record2(parsed.claudeAiOauth);
19392
+ const oauth = credentialRecord(parsed.claudeAiOauth);
19167
19393
  const accessToken = optionalString(oauth?.accessToken ?? parsed.accessToken);
19168
19394
  if (!accessToken) return null;
19169
19395
  return {
@@ -19189,69 +19415,186 @@ async function resolveClaudeCredentials(deps) {
19189
19415
  } catch {
19190
19416
  }
19191
19417
  }
19192
- const configDir = deps.env.CLAUDE_CONFIG_DIR || path9__default.join(deps.homedir(), ".claude");
19418
+ const configDir = deps.env.CLAUDE_CONFIG_DIR || path__default.join(deps.homedir(), ".claude");
19193
19419
  try {
19194
- const raw = await deps.readBounded(path9__default.join(configDir, ".credentials.json"), MAX_CREDENTIAL_BYTES);
19420
+ const raw = await deps.readBounded(path__default.join(configDir, ".credentials.json"), MAX_CREDENTIAL_BYTES);
19195
19421
  return raw === null || raw.length > MAX_CREDENTIAL_BYTES ? null : parseClaudeCredentialJson(raw, "file");
19196
19422
  } catch {
19197
19423
  return null;
19198
19424
  }
19199
19425
  }
19200
- async function resolveCodexCredentials(deps) {
19201
- const home = deps.env.CODEX_HOME || path9__default.join(deps.homedir(), ".codex");
19202
- try {
19203
- const raw = await deps.readBounded(path9__default.join(home, "auth.json"), MAX_CREDENTIAL_BYTES);
19204
- if (raw === null || raw.length > MAX_CREDENTIAL_BYTES) return null;
19205
- const parsed = record2(JSON.parse(raw));
19206
- const tokens = record2(parsed?.tokens);
19207
- const accessToken = optionalString(tokens?.access_token);
19208
- if (!accessToken) return null;
19209
- return { accessToken, accountId: optionalString(tokens?.account_id) };
19210
- } catch {
19211
- return null;
19212
- }
19213
- }
19214
- function parseCursorCredentialJson(raw, method) {
19215
- if (raw.length > MAX_CREDENTIAL_BYTES) return null;
19426
+ var OPENCODE_GO_SESSION_CAP_USD = 12;
19427
+ var OPENCODE_GO_WEEKLY_CAP_USD = 30;
19428
+ var OPENCODE_GO_MONTHLY_CAP_USD = 60;
19429
+ var SESSION_MS = 5 * 36e5;
19430
+ var WEEK_MS = 7 * 864e5;
19431
+ var SCAN_DAYS_BACK = 33;
19432
+ function resolveOpencodeDataDir(env = process.env, homeDir = os4__default.homedir()) {
19433
+ const override = env.OPENCODE_DATA_DIR?.trim();
19434
+ if (override) return expandHome(override, homeDir).replace(/\/+$/, "");
19435
+ const xdg = env.XDG_DATA_HOME?.trim();
19436
+ if (xdg) return `${expandHome(xdg, homeDir).replace(/\/+$/, "")}/opencode`;
19437
+ return path__default.join(homeDir, ".local", "share", "opencode");
19438
+ }
19439
+ function listOpencodeDatabases(dataDir) {
19440
+ let names;
19216
19441
  try {
19217
- const parsed = record2(JSON.parse(raw));
19218
- if (!parsed) return null;
19219
- const tokens = record2(parsed.tokens);
19220
- const cursorAuth = record2(parsed.cursorAuth);
19221
- const accessToken = [
19222
- parsed.accessToken,
19223
- parsed.access_token,
19224
- tokens?.accessToken,
19225
- tokens?.access_token,
19226
- cursorAuth?.accessToken,
19227
- cursorAuth?.access_token
19228
- ].map(optionalTrimmedString).find((value) => value !== void 0);
19229
- return accessToken ? { accessToken, method } : null;
19230
- } catch {
19231
- return null;
19442
+ names = fs5__default.readdirSync(dataDir);
19443
+ } catch (error51) {
19444
+ if (!fs5__default.existsSync(dataDir)) return [];
19445
+ throw error51;
19232
19446
  }
19233
- }
19234
- async function resolveCursorCredentials(deps) {
19235
- if (deps.platform === "darwin") {
19447
+ return names.filter((name) => name.startsWith("opencode") && name.endsWith(".db")).sort().map((name) => path__default.join(dataDir, name));
19448
+ }
19449
+ async function scanOpencodeGoWindows(deps = {}) {
19450
+ const nowMs = (deps.now ?? Date.now)();
19451
+ const dataDir = resolveOpencodeDataDir(deps.env ?? process.env, deps.homeDir ?? os4__default.homedir());
19452
+ const databases = listOpencodeDatabases(dataDir);
19453
+ if (databases.length === 0) return null;
19454
+ const { DatabaseSync } = await import('sqlite');
19455
+ const cutoffMs = nowMs - SCAN_DAYS_BACK * 864e5;
19456
+ const costs = [];
19457
+ let anchorMs;
19458
+ let failures = 0;
19459
+ for (const databasePath of databases) {
19460
+ let db;
19236
19461
  try {
19237
- const raw = await deps.execFile(
19238
- "security",
19239
- ["find-generic-password", "-s", "cursor-access-token", "-a", "cursor-user", "-w"],
19240
- { timeout: 5e3 }
19241
- );
19242
- const accessToken = raw.length <= MAX_CREDENTIAL_BYTES ? optionalTrimmedString(raw) : void 0;
19243
- if (accessToken) return { accessToken, method: "keychain" };
19462
+ db = new DatabaseSync(databasePath, { readOnly: true });
19463
+ const rows = db.prepare(
19464
+ `SELECT time_created AS ms, json_extract(data,'$.cost') AS cost
19465
+ FROM message
19466
+ WHERE time_created >= ?
19467
+ AND json_valid(data)
19468
+ AND json_extract(data,'$.role') = 'assistant'
19469
+ AND json_extract(data,'$.providerID') = 'opencode-go'
19470
+ AND json_type(data,'$.cost') IN ('integer','real')`
19471
+ ).all(cutoffMs);
19472
+ for (const row of rows) {
19473
+ if (typeof row.ms !== "number" || typeof row.cost !== "number" || row.cost < 0) continue;
19474
+ costs.push({ ms: row.ms, cost: row.cost });
19475
+ }
19476
+ const anchorRow = db.prepare(
19477
+ `SELECT MIN(time_created) AS ms FROM message
19478
+ WHERE json_valid(data)
19479
+ AND json_extract(data,'$.role') = 'assistant'
19480
+ AND json_extract(data,'$.providerID') = 'opencode-go'
19481
+ AND json_type(data,'$.cost') IN ('integer','real')`
19482
+ ).get();
19483
+ if (typeof anchorRow?.ms === "number") {
19484
+ anchorMs = anchorMs === void 0 ? anchorRow.ms : Math.min(anchorMs, anchorRow.ms);
19485
+ }
19244
19486
  } catch {
19245
- }
19246
- }
19247
- const home = deps.homedir();
19248
- const authFile = deps.platform === "win32" ? path9__default.join(deps.env.APPDATA || path9__default.join(home, "AppData", "Roaming"), "Cursor", "auth.json") : deps.platform === "darwin" ? path9__default.join(home, ".cursor", "auth.json") : path9__default.join(deps.env.XDG_CONFIG_HOME || path9__default.join(home, ".config"), "cursor", "auth.json");
19249
- try {
19250
- const raw = await deps.readBounded(authFile, MAX_CREDENTIAL_BYTES);
19251
- return raw === null || raw.length > MAX_CREDENTIAL_BYTES ? null : parseCursorCredentialJson(raw, "file");
19252
- } catch {
19253
- return null;
19487
+ failures += 1;
19488
+ } finally {
19489
+ db?.close();
19490
+ }
19491
+ }
19492
+ if (failures === databases.length) {
19493
+ throw new Error("Every OpenCode database exists but could not be read");
19494
+ }
19495
+ return computeOpencodeGoWindows(costs, anchorMs, nowMs);
19496
+ }
19497
+ function computeOpencodeGoWindows(costs, anchorMs, nowMs) {
19498
+ const sessionStart = nowMs - SESSION_MS;
19499
+ const sessionSpend = sumRange(costs, sessionStart, nowMs);
19500
+ const oldestInSession = costs.filter((row) => row.ms >= sessionStart && row.ms < nowMs).reduce((min, row) => min === void 0 ? row.ms : Math.min(min, row.ms), void 0);
19501
+ const sessionResetsAt = (oldestInSession ?? nowMs) + SESSION_MS;
19502
+ const weekStart = startOfUtcWeek(nowMs);
19503
+ const weekEnd = weekStart + WEEK_MS;
19504
+ const weeklySpend = sumRange(costs, weekStart, weekEnd);
19505
+ const month = anchoredMonthBounds(nowMs, anchorMs);
19506
+ const monthlySpend = sumRange(costs, month.start, month.end);
19507
+ return {
19508
+ windows: [
19509
+ {
19510
+ id: "session",
19511
+ usedPercent: percent(sessionSpend, OPENCODE_GO_SESSION_CAP_USD),
19512
+ resetsAt: sessionResetsAt,
19513
+ period: {
19514
+ durationMs: SESSION_MS,
19515
+ durationBasis: "catalog",
19516
+ startsAt: sessionResetsAt - SESSION_MS,
19517
+ startsAtBasis: "derived"
19518
+ }
19519
+ },
19520
+ {
19521
+ id: "weekly",
19522
+ usedPercent: percent(weeklySpend, OPENCODE_GO_WEEKLY_CAP_USD),
19523
+ resetsAt: weekEnd,
19524
+ period: {
19525
+ durationMs: WEEK_MS,
19526
+ durationBasis: "catalog",
19527
+ startsAt: weekStart,
19528
+ startsAtBasis: "derived"
19529
+ }
19530
+ },
19531
+ {
19532
+ id: "cycle",
19533
+ usedPercent: percent(monthlySpend, OPENCODE_GO_MONTHLY_CAP_USD),
19534
+ resetsAt: month.end,
19535
+ period: {
19536
+ durationMs: month.end - month.start,
19537
+ durationBasis: "catalog",
19538
+ startsAt: month.start,
19539
+ startsAtBasis: "derived"
19540
+ }
19541
+ }
19542
+ ],
19543
+ cycleDays: Math.round((month.end - month.start) / 864e5)
19544
+ };
19545
+ }
19546
+ function percent(spend, cap) {
19547
+ return Math.max(0, Math.min(100, Math.round(spend / cap * 100)));
19548
+ }
19549
+ function sumRange(costs, start, end) {
19550
+ const total = costs.reduce(
19551
+ (partial2, row) => row.ms >= start && row.ms < end ? partial2 + row.cost : partial2,
19552
+ 0
19553
+ );
19554
+ return Math.round(total * 1e4) / 1e4;
19555
+ }
19556
+ function startOfUtcWeek(nowMs) {
19557
+ const now = new Date(nowMs);
19558
+ const dayStart = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
19559
+ const daysSinceMonday = (new Date(dayStart).getUTCDay() + 6) % 7;
19560
+ return dayStart - daysSinceMonday * 864e5;
19561
+ }
19562
+ function anchoredMonthBounds(nowMs, anchorMs) {
19563
+ const now = new Date(nowMs);
19564
+ if (anchorMs === void 0 || !Number.isFinite(anchorMs)) {
19565
+ return {
19566
+ start: Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1),
19567
+ end: Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1)
19568
+ };
19254
19569
  }
19570
+ const anchor = new Date(anchorMs);
19571
+ let year = now.getUTCFullYear();
19572
+ let month = now.getUTCMonth();
19573
+ let start = anchoredMonthStart(year, month, anchor);
19574
+ if (start > nowMs) {
19575
+ month -= 1;
19576
+ start = anchoredMonthStart(year, month, anchor);
19577
+ }
19578
+ const end = anchoredMonthStart(year, month + 1, anchor);
19579
+ return { start, end };
19580
+ }
19581
+ function anchoredMonthStart(year, month, anchor) {
19582
+ const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
19583
+ const day = Math.min(anchor.getUTCDate(), daysInMonth);
19584
+ return Date.UTC(
19585
+ year,
19586
+ month,
19587
+ day,
19588
+ anchor.getUTCHours(),
19589
+ anchor.getUTCMinutes(),
19590
+ anchor.getUTCSeconds(),
19591
+ anchor.getUTCMilliseconds()
19592
+ );
19593
+ }
19594
+ function expandHome(value, homeDir) {
19595
+ if (value === "~") return homeDir;
19596
+ if (value.startsWith("~/")) return path__default.join(homeDir, value.slice(2));
19597
+ return value;
19255
19598
  }
19256
19599
 
19257
19600
  // ../fleet-plugins/quota/server/providers.ts
@@ -19259,6 +19602,20 @@ var REQUEST_TIMEOUT_MS = 1e4;
19259
19602
  var MAX_RESPONSE_BYTES = 262144;
19260
19603
  var MAX_WINDOWS = 8;
19261
19604
  var MAX_CREDIT_ENTRIES = 256;
19605
+ var HOUR_MS = 36e5;
19606
+ var WEEK_MS2 = 7 * 24 * HOUR_MS;
19607
+ var CLAUDE_SESSION_MS = 5 * HOUR_MS;
19608
+ var MAX_WINDOW_DURATION_MS = 400 * 24 * HOUR_MS;
19609
+ function windowPeriod(durationMs, durationBasis, resetsAt) {
19610
+ if (!Number.isFinite(durationMs) || durationMs <= 0 || durationMs > MAX_WINDOW_DURATION_MS) return void 0;
19611
+ const rounded = Math.round(durationMs);
19612
+ const startsAt = resetsAt !== void 0 && resetsAt > rounded ? resetsAt - rounded : void 0;
19613
+ return {
19614
+ durationMs: rounded,
19615
+ durationBasis,
19616
+ ...startsAt !== void 0 ? { startsAt, startsAtBasis: "derived" } : {}
19617
+ };
19618
+ }
19262
19619
  var sharedAuthService;
19263
19620
  function authServiceFor(deps) {
19264
19621
  return deps.authService ?? (sharedAuthService ??= createAuthService({ authPath: DEFAULT_AUTH_PATH }));
@@ -19298,7 +19655,7 @@ function safeTimestamp(value) {
19298
19655
  const rounded = Math.round(result);
19299
19656
  return Number.isSafeInteger(rounded) ? rounded : void 0;
19300
19657
  }
19301
- function percent(value) {
19658
+ function percent2(value) {
19302
19659
  if (typeof value !== "number" || !Number.isFinite(value)) return 0;
19303
19660
  return Math.min(100, Math.max(0, Math.round(value)));
19304
19661
  }
@@ -19323,27 +19680,29 @@ function modelLabel(value) {
19323
19680
  function firstClaudePercent(row) {
19324
19681
  for (const key of ["percent", "used_percentage", "utilization"]) {
19325
19682
  const value = row[key];
19326
- if (typeof value === "number" && Number.isFinite(value)) return percent(value);
19683
+ if (typeof value === "number" && Number.isFinite(value)) return percent2(value);
19327
19684
  }
19328
19685
  return void 0;
19329
19686
  }
19330
- function claudeWindow(id, source, label) {
19687
+ function claudeWindow(id, source, durationMs, label) {
19331
19688
  const row = object2(source);
19332
19689
  if (!row) return null;
19333
19690
  const usedPercent = firstClaudePercent(row);
19334
19691
  if (usedPercent === void 0) return null;
19335
19692
  const resetsAt = safeTimestamp(row.resets_at);
19693
+ const period = windowPeriod(durationMs, "catalog", resetsAt);
19336
19694
  return {
19337
19695
  id,
19338
19696
  ...label ? { label } : {},
19339
19697
  usedPercent,
19340
- ...resetsAt !== void 0 ? { resetsAt } : {}
19698
+ ...resetsAt !== void 0 ? { resetsAt } : {},
19699
+ ...period ? { period } : {}
19341
19700
  };
19342
19701
  }
19343
19702
  function parseClaudeUsage(payload) {
19344
19703
  const root = object2(payload) ?? {};
19345
- const namedSession = claudeWindow("session", root.five_hour);
19346
- const namedWeekly = claudeWindow("weekly", root.seven_day);
19704
+ const namedSession = claudeWindow("session", root.five_hour, CLAUDE_SESSION_MS);
19705
+ const namedWeekly = claudeWindow("weekly", root.seven_day, WEEK_MS2);
19347
19706
  let fallbackSession = null;
19348
19707
  let fallbackWeekly = null;
19349
19708
  const modelWindows = [];
@@ -19353,22 +19712,22 @@ function parseClaudeUsage(payload) {
19353
19712
  const limit = object2(item);
19354
19713
  if (!limit) continue;
19355
19714
  if (limit.kind === "session" && !namedSession && !fallbackSession) {
19356
- fallbackSession = claudeWindow("session", limit);
19715
+ fallbackSession = claudeWindow("session", limit, CLAUDE_SESSION_MS);
19357
19716
  continue;
19358
19717
  }
19359
19718
  if (limit.kind === "weekly_all" && !namedWeekly && !fallbackWeekly) {
19360
- fallbackWeekly = claudeWindow("weekly", limit);
19719
+ fallbackWeekly = claudeWindow("weekly", limit, WEEK_MS2);
19361
19720
  continue;
19362
19721
  }
19363
19722
  if (limit.kind === "weekly_scoped" && modelWindows.length < MAX_WINDOWS) {
19364
19723
  const model = object2(object2(limit.scope)?.model);
19365
- const row = claudeWindow("model", limit, modelLabel(model?.display_name));
19724
+ const row = claudeWindow("model", limit, WEEK_MS2, modelLabel(model?.display_name));
19366
19725
  if (row) modelWindows.push(row);
19367
19726
  }
19368
19727
  }
19369
19728
  if (modelWindows.length === 0) {
19370
19729
  for (const alias of [root.fable_weekly, root.fable_seven_day, root.seven_day_fable]) {
19371
- const row = claudeWindow("model", alias, "Fable");
19730
+ const row = claudeWindow("model", alias, WEEK_MS2, "Fable");
19372
19731
  if (row) {
19373
19732
  modelWindows.push(row);
19374
19733
  break;
@@ -19385,13 +19744,16 @@ function parseClaudeUsage(payload) {
19385
19744
  function codexWindow(source, fallbackId) {
19386
19745
  const row = object2(source);
19387
19746
  if (!row) return null;
19388
- const seconds = typeof row.limit_window_seconds === "number" ? row.limit_window_seconds : 0;
19747
+ const seconds = typeof row.limit_window_seconds === "number" && Number.isFinite(row.limit_window_seconds) ? row.limit_window_seconds : 0;
19389
19748
  const minutes = seconds / 60;
19390
19749
  const id = minutes >= 240 && minutes <= 360 ? "session" : minutes >= 8064 && minutes <= 12096 ? "weekly" : fallbackId;
19750
+ const resetsAt = safeTimestamp(row.reset_at);
19751
+ const period = seconds > 0 ? windowPeriod(seconds * 1e3, "upstream", resetsAt) : void 0;
19391
19752
  return {
19392
19753
  id,
19393
- usedPercent: percent(row.used_percent),
19394
- ...safeTimestamp(row.reset_at) !== void 0 ? { resetsAt: safeTimestamp(row.reset_at) } : {}
19754
+ usedPercent: percent2(row.used_percent),
19755
+ ...resetsAt !== void 0 ? { resetsAt } : {},
19756
+ ...period ? { period } : {}
19395
19757
  };
19396
19758
  }
19397
19759
  function parseCodexUsage(payload) {
@@ -19410,6 +19772,21 @@ function parseCursorUsage(payload) {
19410
19772
  const planUsage = object2(root?.planUsage);
19411
19773
  if (root?.enabled === false || !planUsage) return { status: "no_subscription" };
19412
19774
  const resetsAt = safeTimestamp(root?.billingCycleEnd);
19775
+ const cycleStart = safeTimestamp(root?.billingCycleStart);
19776
+ let cycleDays;
19777
+ let period;
19778
+ if (cycleStart !== void 0 && resetsAt !== void 0 && resetsAt > cycleStart) {
19779
+ const days = Math.round((resetsAt - cycleStart) / 864e5);
19780
+ if (days >= 1 && days <= 400) {
19781
+ cycleDays = days;
19782
+ period = {
19783
+ durationMs: resetsAt - cycleStart,
19784
+ durationBasis: "upstream",
19785
+ startsAt: cycleStart,
19786
+ startsAtBasis: "upstream"
19787
+ };
19788
+ }
19789
+ }
19413
19790
  const windows = [];
19414
19791
  for (const [value, scope, label] of [
19415
19792
  [planUsage.totalPercentUsed, void 0, void 0],
@@ -19421,21 +19798,16 @@ function parseCursorUsage(payload) {
19421
19798
  id: "cycle",
19422
19799
  ...scope ? { scope } : {},
19423
19800
  ...label ? { label } : {},
19424
- usedPercent: percent(value),
19425
- ...resetsAt !== void 0 ? { resetsAt } : {}
19801
+ usedPercent: percent2(value),
19802
+ ...resetsAt !== void 0 ? { resetsAt } : {},
19803
+ ...period ? { period } : {}
19426
19804
  });
19427
19805
  }
19428
19806
  if (windows.length === 0) return { status: "no_subscription" };
19429
- const cycleStart = safeTimestamp(root?.billingCycleStart);
19430
- const cycleEnd = safeTimestamp(root?.billingCycleEnd);
19431
- let cycleDays;
19432
- if (cycleStart !== void 0 && cycleEnd !== void 0 && cycleEnd > cycleStart) {
19433
- const days = Math.round((cycleEnd - cycleStart) / 864e5);
19434
- if (days >= 1 && days <= 400) cycleDays = days;
19435
- }
19807
+ const taggedWindows = windows.some((window) => window.scope !== void 0) ? windows.map((window) => window.scope === void 0 ? { ...window, isAggregate: true } : window) : windows;
19436
19808
  return {
19437
19809
  status: "ok",
19438
- windows,
19810
+ windows: taggedWindows,
19439
19811
  ...cycleDays !== void 0 ? { cycleDays } : {}
19440
19812
  };
19441
19813
  }
@@ -19456,7 +19828,7 @@ var KIMI_WINDOW_BY_MINUTES = {
19456
19828
  300: "session",
19457
19829
  10080: "weekly"
19458
19830
  };
19459
- function kimiWindow(id, detail) {
19831
+ function kimiWindow(id, detail, duration3) {
19460
19832
  const row = object2(detail);
19461
19833
  if (!row) return null;
19462
19834
  const limit = numeric(row.limit);
@@ -19465,10 +19837,15 @@ function kimiWindow(id, detail) {
19465
19837
  const used = numeric(row.used) ?? (remaining === void 0 ? void 0 : limit - remaining);
19466
19838
  if (used === void 0) return null;
19467
19839
  const resetsAt = safeTimestamp(row.resetTime ?? row.resetAt);
19840
+ const period = duration3 ? windowPeriod(duration3.ms, duration3.basis, resetsAt) : void 0;
19468
19841
  return {
19469
19842
  id,
19470
- usedPercent: percent(used / limit * 100),
19471
- ...resetsAt !== void 0 ? { resetsAt } : {}
19843
+ usedPercent: percent2(used / limit * 100),
19844
+ ...resetsAt !== void 0 ? { resetsAt } : {},
19845
+ ...period ? { period } : {},
19846
+ // Kimi quantifies in plain counts, never money, so the absolute figures may
19847
+ // ship; they are what lets a consumer size one more run against the bucket.
19848
+ amounts: { used: String(Math.max(0, used)), limit: String(limit) }
19472
19849
  };
19473
19850
  }
19474
19851
  function kimiPlan(payload) {
@@ -19485,7 +19862,7 @@ function parseKimiUsage(payload) {
19485
19862
  const root = object2(payload);
19486
19863
  if (!root) return { status: "no_subscription" };
19487
19864
  const windows = [];
19488
- const cycle = kimiWindow("cycle", root.usage);
19865
+ const cycle = kimiWindow("cycle", root.usage, { ms: WEEK_MS2, basis: "catalog" });
19489
19866
  if (cycle) windows.push(cycle);
19490
19867
  const limits = array2(root.limits);
19491
19868
  for (let index = 0; index < limits.length && windows.length < MAX_WINDOWS; index += 1) {
@@ -19496,7 +19873,7 @@ function parseKimiUsage(payload) {
19496
19873
  if (duration3 === void 0 || unit === void 0) continue;
19497
19874
  const id = KIMI_WINDOW_BY_MINUTES[duration3 * unit];
19498
19875
  if (!id || windows.some((window2) => window2.id === id)) continue;
19499
- const window = kimiWindow(id, entry?.detail);
19876
+ const window = kimiWindow(id, entry?.detail, { ms: duration3 * unit * 6e4, basis: "upstream" });
19500
19877
  if (window) windows.push(window);
19501
19878
  }
19502
19879
  if (windows.length === 0) return { status: "no_subscription" };
@@ -19706,6 +20083,30 @@ async function fetchKimiUsage(deps = {}) {
19706
20083
  throw error51;
19707
20084
  }
19708
20085
  }
20086
+ async function fetchOpencodeUsage(deps = {}) {
20087
+ const apiKey = await authServiceFor(deps).getApiKey(OPENCODE_AUTH_PROVIDER_ID);
20088
+ if (!apiKey) return { status: "signed_out" };
20089
+ const now = deps.now ?? Date.now;
20090
+ try {
20091
+ const scan = await (deps.scanOpencodeGoWindows ?? (() => scanOpencodeGoWindows({ now })))();
20092
+ if (scan !== null) {
20093
+ return {
20094
+ status: "ok",
20095
+ plan: "Go",
20096
+ cycleDays: scan.cycleDays,
20097
+ windows: scan.windows,
20098
+ fetchedAt: now()
20099
+ };
20100
+ }
20101
+ } catch {
20102
+ }
20103
+ return {
20104
+ status: "ok",
20105
+ plan: "Go",
20106
+ windows: [],
20107
+ fetchedAt: now()
20108
+ };
20109
+ }
19709
20110
  function sanitizeProviderError(error51) {
19710
20111
  if (error51 instanceof ProviderResponseTooLargeError) return "Provider response too large";
19711
20112
  if (error51 instanceof DOMException && error51.name === "AbortError") return "Provider request timed out";
@@ -19727,7 +20128,8 @@ function createQuotaService(deps) {
19727
20128
  claude: deps.fetchClaude ?? (() => fetchClaudeUsage()),
19728
20129
  codex: deps.fetchCodex ?? (() => fetchCodexUsage()),
19729
20130
  cursor: deps.fetchCursor ?? (() => fetchCursorUsage()),
19730
- kimi: deps.fetchKimi ?? (() => fetchKimiUsage())
20131
+ kimi: deps.fetchKimi ?? (() => fetchKimiUsage()),
20132
+ opencode: deps.fetchOpencode ?? (() => fetchOpencodeUsage())
19731
20133
  };
19732
20134
  const cache = /* @__PURE__ */ new Map();
19733
20135
  const lastGood = /* @__PURE__ */ new Map();
@@ -19762,13 +20164,14 @@ function createQuotaService(deps) {
19762
20164
  }
19763
20165
  return {
19764
20166
  async getSummary(options = {}) {
19765
- const [claude, codex, cursor, kimi] = await Promise.all([
20167
+ const [claude, codex, cursor, kimi, opencode] = await Promise.all([
19766
20168
  load("claude", options.force === true || options.forceProvider === "claude"),
19767
20169
  load("codex", options.force === true || options.forceProvider === "codex"),
19768
20170
  load("cursor", options.force === true || options.forceProvider === "cursor"),
19769
- load("kimi", options.force === true || options.forceProvider === "kimi")
20171
+ load("kimi", options.force === true || options.forceProvider === "kimi"),
20172
+ load("opencode", options.force === true || options.forceProvider === "opencode")
19770
20173
  ]);
19771
- return { providers: { claude, codex, cursor, kimi } };
20174
+ return { providers: { claude, codex, cursor, kimi, opencode } };
19772
20175
  }
19773
20176
  };
19774
20177
  }