@dotobokuri/fleet-console 1.70.0 → 1.71.1

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 (68) hide show
  1. package/dist/cli.mjs +78 -14
  2. package/dist/client/assets/{_baseUniq-81Y5kFtp.js → _baseUniq-Bhd1wyKE.js} +1 -1
  3. package/dist/client/assets/{arc-d96Fgk-5.js → arc-Cu9FOmUr.js} +1 -1
  4. package/dist/client/assets/{architectureDiagram-Q4EWVU46-BBgIklLp.js → architectureDiagram-Q4EWVU46-Dq9FA5I3.js} +1 -1
  5. package/dist/client/assets/{blockDiagram-DXYQGD6D-BCjY9dJk.js → blockDiagram-DXYQGD6D-BDZkCLI1.js} +1 -1
  6. package/dist/client/assets/{c4Diagram-AHTNJAMY-BVJRdf8q.js → c4Diagram-AHTNJAMY-XBPYwanu.js} +1 -1
  7. package/dist/client/assets/channel-BTX-SvBb.js +1 -0
  8. package/dist/client/assets/{chunk-4BX2VUAB-CT7BCzBg.js → chunk-4BX2VUAB-BbTQSLs0.js} +1 -1
  9. package/dist/client/assets/{chunk-4TB4RGXK-DUbDaHiY.js → chunk-4TB4RGXK-DukpmkUz.js} +1 -1
  10. package/dist/client/assets/{chunk-55IACEB6-C7HDwq0R.js → chunk-55IACEB6-BFyIa1Ge.js} +1 -1
  11. package/dist/client/assets/{chunk-EDXVE4YY-Mh16Bf7t.js → chunk-EDXVE4YY-D7RHsfQm.js} +1 -1
  12. package/dist/client/assets/{chunk-FMBD7UC4-D3BjqAun.js → chunk-FMBD7UC4-Co64dt-k.js} +1 -1
  13. package/dist/client/assets/{chunk-OYMX7WX6-DmzxPT1k.js → chunk-OYMX7WX6-CdycD6Yh.js} +1 -1
  14. package/dist/client/assets/{chunk-QZHKN3VN-CaZdQK6Z.js → chunk-QZHKN3VN-CNvTB1xu.js} +1 -1
  15. package/dist/client/assets/{chunk-YZCP3GAM-Q2hrlgLY.js → chunk-YZCP3GAM-CY1_pTO2.js} +1 -1
  16. package/dist/client/assets/classDiagram-6PBFFD2Q-CixB9uB6.js +1 -0
  17. package/dist/client/assets/classDiagram-v2-HSJHXN6E-CixB9uB6.js +1 -0
  18. package/dist/client/assets/clone-DuMuKBBB.js +1 -0
  19. package/dist/client/assets/{cose-bilkent-S5V4N54A-CPdIsNiQ.js → cose-bilkent-S5V4N54A-PLhfHDPQ.js} +1 -1
  20. package/dist/client/assets/{dagre-KV5264BT-BYWdUXO0.js → dagre-KV5264BT-gJnGByq0.js} +1 -1
  21. package/dist/client/assets/{diagram-5BDNPKRD-BC8rqmOK.js → diagram-5BDNPKRD-y48OdlFp.js} +1 -1
  22. package/dist/client/assets/{diagram-G4DWMVQ6-CES6iBQQ.js → diagram-G4DWMVQ6-DSLYc2V1.js} +1 -1
  23. package/dist/client/assets/{diagram-MMDJMWI5-BfhQrSaN.js → diagram-MMDJMWI5-DWgtcwcn.js} +1 -1
  24. package/dist/client/assets/{diagram-TYMM5635-C2FgHNxP.js → diagram-TYMM5635-CLd83m-G.js} +1 -1
  25. package/dist/client/assets/{erDiagram-SMLLAGMA-KQgKZTcf.js → erDiagram-SMLLAGMA-CGP2g7Ug.js} +1 -1
  26. package/dist/client/assets/{flowDiagram-DWJPFMVM-7Ytk1sX_.js → flowDiagram-DWJPFMVM-BhKzXbma.js} +1 -1
  27. package/dist/client/assets/{ganttDiagram-T4ZO3ILL-C4yl6vGV.js → ganttDiagram-T4ZO3ILL-BdpBmhZF.js} +1 -1
  28. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-DyN7iLk4.js → gitGraphDiagram-UUTBAWPF-IylczS5r.js} +1 -1
  29. package/dist/client/assets/{graph-BsOHL3Ty.js → graph-xlKIIKKy.js} +1 -1
  30. package/dist/client/assets/index-DH7xHFza.js +467 -0
  31. package/dist/client/assets/index-DKMT7UVt.css +1 -0
  32. package/dist/client/assets/{infoDiagram-42DDH7IO-BIOEjyDP.js → infoDiagram-42DDH7IO-Dm9-Iqxb.js} +1 -1
  33. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-C18t-DEH.js → ishikawaDiagram-UXIWVN3A-0tPrKKU3.js} +1 -1
  34. package/dist/client/assets/{journeyDiagram-VCZTEJTY-BysZXCkq.js → journeyDiagram-VCZTEJTY-3wTioYxO.js} +1 -1
  35. package/dist/client/assets/{kanban-definition-6JOO6SKY-Zdulrt1W.js → kanban-definition-6JOO6SKY-DjVcpuse.js} +1 -1
  36. package/dist/client/assets/{layout-DhT9CiMw.js → layout-BZ0nnXEn.js} +1 -1
  37. package/dist/client/assets/{linear-DQna1rOZ.js → linear-DNdW4gLV.js} +1 -1
  38. package/dist/client/assets/{mermaid.core-C0sjt4NJ.js → mermaid.core-DpO6yFcA.js} +4 -4
  39. package/dist/client/assets/{min-Dyx0ykEh.js → min-xMtTJxkM.js} +1 -1
  40. package/dist/client/assets/{mindmap-definition-QFDTVHPH-BzEvAUNd.js → mindmap-definition-QFDTVHPH-8tcRIKM5.js} +1 -1
  41. package/dist/client/assets/{pieDiagram-DEJITSTG-Cd4ORVnw.js → pieDiagram-DEJITSTG-DOuWZGrv.js} +1 -1
  42. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-CvNxhBIm.js → quadrantDiagram-34T5L4WZ-BWPtgVdA.js} +1 -1
  43. package/dist/client/assets/{requirementDiagram-MS252O5E-CuGuie-o.js → requirementDiagram-MS252O5E-CkNpSYqR.js} +1 -1
  44. package/dist/client/assets/{sankeyDiagram-XADWPNL6-zn7buHsU.js → sankeyDiagram-XADWPNL6-DUPS39lN.js} +1 -1
  45. package/dist/client/assets/{sequenceDiagram-FGHM5R23-BxDReh8o.js → sequenceDiagram-FGHM5R23-B4n7l5jw.js} +1 -1
  46. package/dist/client/assets/{stateDiagram-FHFEXIEX-DtZ0UE1G.js → stateDiagram-FHFEXIEX-DBHsG7yj.js} +1 -1
  47. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2--18aeGq2.js +1 -0
  48. package/dist/client/assets/{timeline-definition-GMOUNBTQ-DfKveVha.js → timeline-definition-GMOUNBTQ-BLxUyg3R.js} +1 -1
  49. package/dist/client/assets/{vennDiagram-DHZGUBPP-CZe6StT_.js → vennDiagram-DHZGUBPP-27NkxCen.js} +1 -1
  50. package/dist/client/assets/{wardley-RL74JXVD-B10WfMsc.js → wardley-RL74JXVD-VNgEaZlH.js} +1 -1
  51. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-DzN04fy9.js → wardleyDiagram-NUSXRM2D-byIhDvPD.js} +1 -1
  52. package/dist/client/assets/{xychartDiagram-5P7HB3ND-CIgNRRNp.js → xychartDiagram-5P7HB3ND-D0amCilL.js} +1 -1
  53. package/dist/client/index.html +2 -2
  54. package/dist/fleet-plugins/file-explorer/routes.mjs +138 -96
  55. package/dist/fleet-plugins/ledger/routes.mjs +73 -12
  56. package/dist/fleet-plugins/quota/routes.mjs +73 -12
  57. package/dist/fleet-plugins/scuttlebutt/routes.mjs +74 -12
  58. package/dist/fleet-plugins/skills/routes.mjs +126 -60
  59. package/dist/fleet-plugins/terminal/routes.mjs +482 -69
  60. package/dist/fleet.mjs +479 -67
  61. package/package.json +1 -1
  62. package/dist/client/assets/channel-CiSQi5S5.js +0 -1
  63. package/dist/client/assets/classDiagram-6PBFFD2Q-Cy-ZC6xF.js +0 -1
  64. package/dist/client/assets/classDiagram-v2-HSJHXN6E-Cy-ZC6xF.js +0 -1
  65. package/dist/client/assets/clone-BAhE6Fq8.js +0 -1
  66. package/dist/client/assets/index-2049WCXu.css +0 -1
  67. package/dist/client/assets/index-DJcpFTNB.js +0 -466
  68. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-aYct9Owm.js +0 -1
@@ -276,7 +276,8 @@ async function readFileForTheater(theaterPath, relativePath) {
276
276
  content: chunk.toString("utf8"),
277
277
  lang: detectLang(realResolved),
278
278
  truncated: true,
279
- sizeBytes: stat.size
279
+ sizeBytes: stat.size,
280
+ mtimeMs: stat.mtimeMs
280
281
  };
281
282
  }
282
283
  const buffer = await fs2.promises.readFile(realResolved);
@@ -285,7 +286,8 @@ async function readFileForTheater(theaterPath, relativePath) {
285
286
  relativePath: path5.relative(realRoot, realResolved),
286
287
  content: buffer.toString("utf8"),
287
288
  lang: detectLang(realResolved),
288
- sizeBytes: stat.size
289
+ sizeBytes: stat.size,
290
+ mtimeMs: stat.mtimeMs
289
291
  };
290
292
  }
291
293
  function isWithinRoot(resolved, root) {
@@ -672,96 +674,28 @@ async function statDirectory(targetPath, stat) {
672
674
  async function collectContentsEntries(targetPath, theaterPath, opendir, stat, entries, hiddenVcs) {
673
675
  const directory = await openDirectory(targetPath, opendir);
674
676
  try {
675
- const pending = [];
676
- let truncated = false;
677
- const accept = (entry) => {
678
- if (entry === null) return false;
679
- if ("vcsInternal" in entry) {
680
- hiddenVcs.push(entry.vcsInternal);
681
- return false;
682
- }
683
- if (entries.length >= DIRECTORY_ENTRY_CAP) return true;
684
- entries.push(entry);
685
- return false;
686
- };
687
- const flushPending = async () => {
688
- while (pending.length > 0) {
689
- if (entries.length >= DIRECTORY_ENTRY_CAP) {
690
- pending.length = 0;
691
- return true;
692
- }
693
- const remaining = DIRECTORY_ENTRY_CAP - entries.length;
694
- const batch = pending.splice(0, Math.min(CLASSIFY_CONCURRENCY, remaining));
695
- const classified = await Promise.all(
696
- batch.map((item) => toContentsEntry(targetPath, theaterPath, item, stat))
697
- );
698
- let overflowed = false;
699
- for (const entry of classified) {
700
- if (overflowed) {
701
- if (entry && "vcsInternal" in entry) hiddenVcs.push(entry.vcsInternal);
702
- continue;
703
- }
704
- if (accept(entry)) overflowed = true;
705
- }
706
- if (overflowed) {
707
- pending.length = 0;
708
- return true;
709
- }
710
- }
711
- return false;
712
- };
713
- const finishCheapTail = async (first) => {
714
- pending.length = 0;
715
- let current = first;
716
- let omitted = false;
717
- while (current !== null) {
718
- if (VCS_INTERNAL_NAMES.has(current.name)) hiddenVcs.push(current.name);
719
- else {
720
- omitted = true;
721
- break;
722
- }
723
- current = await directory.read();
724
- }
725
- return omitted;
726
- };
727
- let dirent = await directory.read();
728
- while (dirent !== null) {
729
- if (VCS_INTERNAL_NAMES.has(dirent.name)) {
730
- hiddenVcs.push(dirent.name);
731
- dirent = await directory.read();
732
- continue;
733
- }
734
- if (entries.length >= DIRECTORY_ENTRY_CAP) {
735
- truncated = await finishCheapTail(dirent);
736
- dirent = null;
737
- break;
738
- }
739
- if (dirent.isDirectory() || dirent.isFile()) {
740
- if (pending.length > 0 && await flushPending()) {
741
- truncated = true;
742
- await finishCheapTail(dirent);
743
- dirent = null;
744
- break;
745
- }
746
- const rel = path5.relative(theaterPath, path5.join(targetPath, dirent.name));
747
- if (accept({ name: dirent.name, relativePath: rel, kind: dirent.isDirectory() ? "dir" : "file" })) {
748
- truncated = true;
749
- await finishCheapTail(await directory.read());
750
- dirent = null;
751
- break;
752
- }
753
- } else {
754
- pending.push(dirent);
755
- if (pending.length >= CLASSIFY_CONCURRENCY && await flushPending()) {
756
- truncated = true;
757
- await finishCheapTail(await directory.read());
758
- dirent = null;
759
- break;
677
+ const cheap = [];
678
+ for (let dirent = await directory.read(); dirent !== null; dirent = await directory.read()) {
679
+ if (VCS_INTERNAL_NAMES.has(dirent.name)) hiddenVcs.push(dirent.name);
680
+ else cheap.push(dirent);
681
+ }
682
+ cheap.sort((left, right) => left.name.localeCompare(right.name));
683
+ const truncated = cheap.length > DIRECTORY_ENTRY_CAP;
684
+ const kept = truncated ? cheap.slice(0, DIRECTORY_ENTRY_CAP) : cheap;
685
+ for (let start = 0; start < kept.length; start += CLASSIFY_CONCURRENCY) {
686
+ const batch = kept.slice(start, start + CLASSIFY_CONCURRENCY);
687
+ const classified = await Promise.all(
688
+ batch.map((item) => toContentsEntry(targetPath, theaterPath, item, stat))
689
+ );
690
+ for (const entry of classified) {
691
+ if (entry === null) continue;
692
+ if ("vcsInternal" in entry) {
693
+ hiddenVcs.push(entry.vcsInternal);
694
+ continue;
760
695
  }
696
+ entries.push(entry);
761
697
  }
762
- dirent = await directory.read();
763
698
  }
764
- if (!truncated && await flushPending()) truncated = true;
765
699
  return truncated;
766
700
  } catch (error) {
767
701
  throw mapFolderBrowserFsError(error);
@@ -969,16 +903,54 @@ function mapGitStatusFsError(error) {
969
903
  }
970
904
  var SEARCH_DIRECTORY_CAP = 500;
971
905
  var SEARCH_ENTRY_CAP = 25e3;
972
- async function searchTheaterFiles(theaterPath, query, limit) {
906
+ var SEARCH_LIMIT_MAX = 200;
907
+ var SEARCH_IGNORED_DIRECTORY_NAMES = /* @__PURE__ */ new Set([
908
+ "node_modules",
909
+ ".pnpm",
910
+ ".yarn",
911
+ "bower_components",
912
+ "dist",
913
+ "build",
914
+ "out",
915
+ "coverage",
916
+ "vendor",
917
+ "target",
918
+ ".next",
919
+ ".nuxt",
920
+ ".turbo",
921
+ ".cache",
922
+ ".parcel-cache",
923
+ ".svelte-kit",
924
+ ".angular",
925
+ ".venv",
926
+ "__pycache__",
927
+ ".gradle",
928
+ ".terraform"
929
+ ]);
930
+ async function searchTheaterFiles(theaterPath, query, limit, options = {}) {
973
931
  const realRoot = await fsp.realpath(theaterPath);
974
- const tokens = query.trim().toLocaleLowerCase().split(/\s+/).filter(Boolean);
932
+ const tokens = tokenizeSearchQuery(query);
975
933
  const pending = [{ absolutePath: realRoot, relativePath: "" }];
976
934
  const visited = /* @__PURE__ */ new Set();
977
935
  const matches = [];
978
936
  let directoryCount = 0;
979
937
  let entryCount = 0;
980
938
  let walkCapped = false;
939
+ let ignoredSkipped = false;
940
+ const signal = options.signal;
941
+ const honorIgnoreList = options.includeIgnored !== true;
942
+ const allowedKinds = options.kinds;
943
+ const includeHidden = options.includeHidden !== false;
944
+ const accepts = (relativePath, kind) => {
945
+ if (allowedKinds && !allowedKinds.includes(kind)) return false;
946
+ if (!includeHidden && relativePath.split("/").some((segment) => segment.startsWith("."))) return false;
947
+ return true;
948
+ };
949
+ if (tokens.length === 0) return { files: [], totalMatches: 0, ignoredSkipped: false };
981
950
  while (pending.length > 0) {
951
+ if (signal?.aborted) {
952
+ return { files: [], totalMatches: 0, ignoredSkipped };
953
+ }
982
954
  if (directoryCount >= SEARCH_DIRECTORY_CAP || entryCount >= SEARCH_ENTRY_CAP) {
983
955
  walkCapped = true;
984
956
  break;
@@ -995,17 +967,27 @@ async function searchTheaterFiles(theaterPath, query, limit) {
995
967
  }
996
968
  entries.sort((left, right) => left.name.localeCompare(right.name));
997
969
  for (const entry of entries) {
970
+ if (signal?.aborted) {
971
+ return { files: [], totalMatches: 0, ignoredSkipped };
972
+ }
998
973
  if (entryCount >= SEARCH_ENTRY_CAP) {
999
974
  walkCapped = true;
1000
975
  break;
1001
976
  }
1002
- entryCount += 1;
1003
977
  if (VCS_INTERNAL_NAMES.has(entry.name)) continue;
978
+ if (!includeHidden && entry.name.startsWith(".")) continue;
979
+ entryCount += 1;
1004
980
  const relativePath = directory.relativePath ? `${directory.relativePath}/${entry.name}` : entry.name;
1005
981
  const absolutePath = path5.join(directory.absolutePath, entry.name);
982
+ const ignoredName = honorIgnoreList && SEARCH_IGNORED_DIRECTORY_NAMES.has(entry.name);
1006
983
  let kind = entry.isDirectory() ? "dir" : entry.isFile() ? "file" : null;
1007
984
  let realPath = absolutePath;
1008
985
  if (entry.isSymbolicLink()) {
986
+ if (ignoredName) {
987
+ ignoredSkipped = true;
988
+ if (accepts(relativePath, "dir") && pathMatchesSearchTokens(relativePath, tokens)) matches.push({ relativePath, kind: "dir" });
989
+ continue;
990
+ }
1009
991
  try {
1010
992
  realPath = await fsp.realpath(absolutePath);
1011
993
  if (!isContained(realRoot, realPath)) continue;
@@ -1017,19 +999,28 @@ async function searchTheaterFiles(theaterPath, query, limit) {
1017
999
  }
1018
1000
  }
1019
1001
  if (kind === "dir") {
1002
+ if (accepts(relativePath, "dir") && pathMatchesSearchTokens(relativePath, tokens)) matches.push({ relativePath, kind: "dir" });
1003
+ if (ignoredName) {
1004
+ ignoredSkipped = true;
1005
+ continue;
1006
+ }
1007
+ if (!includeHidden && entry.name.startsWith(".")) continue;
1020
1008
  if (!visited.has(realPath)) pending.push({ absolutePath: realPath, relativePath });
1021
1009
  continue;
1022
1010
  }
1023
1011
  if (kind !== "file") continue;
1024
- const low = relativePath.toLocaleLowerCase();
1025
- if (tokens.every((token) => low.includes(token))) matches.push({ relativePath });
1012
+ if (accepts(relativePath, "file") && pathMatchesSearchTokens(relativePath, tokens)) matches.push({ relativePath, kind: "file" });
1026
1013
  }
1027
1014
  if (walkCapped) break;
1028
1015
  }
1016
+ if (signal?.aborted) {
1017
+ return { files: [], totalMatches: 0, ignoredSkipped };
1018
+ }
1029
1019
  const sorted = matches.sort((left, right) => compareFileSearchItem(left, right, query));
1030
1020
  return {
1031
1021
  files: sorted.slice(0, limit),
1032
1022
  totalMatches: sorted.length,
1023
+ ignoredSkipped,
1033
1024
  ...walkCapped ? { walkCapped: true } : {}
1034
1025
  };
1035
1026
  }
@@ -1043,26 +1034,77 @@ async function handleFilesSearch(req, res, ctx) {
1043
1034
  return;
1044
1035
  }
1045
1036
  const body = await ctx.host.http.readJsonBody(req);
1046
- if (!isPlainObject(body) || typeof body.theaterId !== "string" || typeof body.query !== "string" || body.query.trim() === "" || !Number.isInteger(body.limit) || body.limit < 1 || body.limit > 8) {
1037
+ if (!isPlainObject(body) || typeof body.theaterId !== "string" || typeof body.query !== "string" || body.query.trim() === "" || !Number.isInteger(body.limit) || body.limit < 1 || body.limit > SEARCH_LIMIT_MAX) {
1047
1038
  ctx.host.http.writeJson(res, 400, { error: "invalid_request" });
1048
1039
  return;
1049
1040
  }
1041
+ const kinds = parseSearchKinds(body.kinds);
1042
+ if (kinds === "invalid") {
1043
+ ctx.host.http.writeJson(res, 400, { error: "invalid_request" });
1044
+ return;
1045
+ }
1046
+ const includeHidden = body.includeHidden !== false;
1050
1047
  const theaterPath = ctx.host.paths.resolveTheaterPath(body.theaterId);
1051
1048
  if (!theaterPath) {
1052
1049
  ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
1053
1050
  return;
1054
1051
  }
1052
+ const abort = new AbortController();
1053
+ const onClose = () => {
1054
+ if (!res.writableEnded) abort.abort();
1055
+ };
1056
+ if (typeof res.on === "function") res.on("close", onClose);
1057
+ const detach = () => {
1058
+ if (typeof res.off === "function") res.off("close", onClose);
1059
+ };
1055
1060
  try {
1056
- const outcome = await searchTheaterFiles(theaterPath, body.query, body.limit);
1061
+ if (abort.signal.aborted) return;
1062
+ let outcome = await searchTheaterFiles(theaterPath, body.query, body.limit, {
1063
+ signal: abort.signal,
1064
+ ...kinds ? { kinds } : {},
1065
+ includeHidden
1066
+ });
1067
+ if (abort.signal.aborted) return;
1068
+ if (outcome.totalMatches === 0 && outcome.ignoredSkipped && !outcome.walkCapped) {
1069
+ const fallback = await searchTheaterFiles(theaterPath, body.query, body.limit, {
1070
+ signal: abort.signal,
1071
+ includeIgnored: true,
1072
+ ...kinds ? { kinds } : {},
1073
+ includeHidden
1074
+ });
1075
+ if (abort.signal.aborted) return;
1076
+ if (fallback.totalMatches > 0) outcome = { ...fallback, ignoredSkipped: false };
1077
+ }
1057
1078
  ctx.host.http.writeJson(res, 200, {
1058
1079
  files: outcome.files,
1059
1080
  totalMatches: outcome.totalMatches,
1081
+ ignoredSkipped: outcome.ignoredSkipped,
1060
1082
  ...outcome.walkCapped ? { walkCapped: true } : {}
1061
1083
  });
1062
1084
  } catch {
1085
+ if (abort.signal.aborted) return;
1063
1086
  ctx.host.http.writeJson(res, 500, { error: "search_failed" });
1087
+ } finally {
1088
+ detach();
1064
1089
  }
1065
1090
  }
1091
+ function parseSearchKinds(raw) {
1092
+ if (raw === void 0) return null;
1093
+ if (!Array.isArray(raw) || raw.length === 0) return "invalid";
1094
+ const kinds = [];
1095
+ for (const value of raw) {
1096
+ if (value !== "file" && value !== "dir") return "invalid";
1097
+ if (!kinds.includes(value)) kinds.push(value);
1098
+ }
1099
+ return kinds;
1100
+ }
1101
+ function tokenizeSearchQuery(query) {
1102
+ return query.trim().toLocaleLowerCase().split(/[\s/]+/).filter(Boolean);
1103
+ }
1104
+ function pathMatchesSearchTokens(relativePath, tokens) {
1105
+ const low = relativePath.toLocaleLowerCase();
1106
+ return tokens.every((token) => low.includes(token));
1107
+ }
1066
1108
  function compareFileSearchItem(left, right, query) {
1067
1109
  const lowQuery = query.trim().toLocaleLowerCase();
1068
1110
  const leftName = left.relativePath.split("/").at(-1)?.toLocaleLowerCase() ?? "";
@@ -18080,7 +18080,7 @@ var benchmarks_default = {
18080
18080
  };
18081
18081
  var models_default = {
18082
18082
  version: 1,
18083
- updatedAt: "2026-08-20T00:00:00Z",
18083
+ updatedAt: "2026-08-22T00:00:00Z",
18084
18084
  providers: {
18085
18085
  codex: {
18086
18086
  name: "Codex",
@@ -18491,7 +18491,7 @@ var models_default = {
18491
18491
  {
18492
18492
  modelId: "composer-2.5",
18493
18493
  name: "Composer-2.5",
18494
- capabilityClass: "flagship",
18494
+ capabilityClass: "standard",
18495
18495
  quotaScope: "auto",
18496
18496
  contextWindow: 2e5,
18497
18497
  benchmarkKey: "composer-2.5"
@@ -18499,9 +18499,11 @@ var models_default = {
18499
18499
  {
18500
18500
  modelId: "composer-2.5-fast",
18501
18501
  name: "Composer-2.5-Fast",
18502
- capabilityClass: "light",
18502
+ capabilityClass: "standard",
18503
+ variantOf: "composer-2.5",
18503
18504
  quotaScope: "auto",
18504
- contextWindow: 2e5
18505
+ contextWindow: 2e5,
18506
+ benchmarkKey: "composer-2.5"
18505
18507
  },
18506
18508
  {
18507
18509
  modelId: "grok-4.5",
@@ -18523,7 +18525,8 @@ var models_default = {
18523
18525
  {
18524
18526
  modelId: "grok-4.5-fast",
18525
18527
  name: "Grok-4.5-Fast",
18526
- capabilityClass: "light",
18528
+ capabilityClass: "flagship",
18529
+ variantOf: "grok-4.5",
18527
18530
  quotaScope: "auto",
18528
18531
  contextWindow: 256e3,
18529
18532
  effort: {
@@ -18534,7 +18537,8 @@ var models_default = {
18534
18537
  "high"
18535
18538
  ],
18536
18539
  upstreamModelIdTemplate: "cursor-grok-4.5-{effort}-fast"
18537
- }
18540
+ },
18541
+ benchmarkKey: "grok-4.5"
18538
18542
  },
18539
18543
  {
18540
18544
  modelId: "grok-4.6",
@@ -18557,7 +18561,8 @@ var models_default = {
18557
18561
  {
18558
18562
  modelId: "grok-4.6-fast",
18559
18563
  name: "Grok-4.6-Fast",
18560
- capabilityClass: "light",
18564
+ capabilityClass: "flagship",
18565
+ variantOf: "grok-4.6",
18561
18566
  quotaScope: "auto",
18562
18567
  contextWindow: 256e3,
18563
18568
  effort: {
@@ -18569,7 +18574,8 @@ var models_default = {
18569
18574
  "xhigh"
18570
18575
  ],
18571
18576
  upstreamModelIdTemplate: "cursor-grok-4.6-{effort}-fast"
18572
- }
18577
+ },
18578
+ benchmarkKey: "grok-4.6"
18573
18579
  },
18574
18580
  {
18575
18581
  modelId: "claude-opus-5",
@@ -18797,7 +18803,7 @@ var models_default = {
18797
18803
  opencode: {
18798
18804
  name: "OpenCode",
18799
18805
  defaultModel: "minimax-m3",
18800
- 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); superseded generations removed 2026-08-08 \u2014 the catalog keeps each lineup's current generation only",
18806
+ 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); superseded generations removed 2026-08-08 \u2014 the catalog keeps each lineup's current generation only; ox-alpha-free and muse-spark-1.2-contributor added 2026-08-21 from the same live list, each wire chosen by a streaming probe on that date (ox-alpha-free frames natively on /chat/completions and returns reasoning_content deltas; muse-spark-1.2-contributor frames natively on /responses and echoes its own reasoning block) and each effort ladder taken from the upstream's own rejection message (ox-alpha-free: low/high/max; muse-spark-1.2-contributor: none/minimal/low/medium/high/xhigh, so max is refused); their contextWindow comes from models.dev api.json opencode-go entries (2026-08-21). muse-spark-1.2-contributor's Responses backend accepts only tool_choice auto: named function choices, required, and none are refused with a 400 (2026-08-21), so a caller that forces a tool cannot use it",
18801
18807
  models: [
18802
18808
  {
18803
18809
  modelId: "minimax-m3",
@@ -18845,6 +18851,22 @@ var models_default = {
18845
18851
  },
18846
18852
  benchmarkKey: "grok-4.5"
18847
18853
  },
18854
+ {
18855
+ modelId: "muse-spark-1.2-contributor",
18856
+ name: "Muse-Spark-1.2-Contributor",
18857
+ capabilityClass: "flagship",
18858
+ wire: "responses",
18859
+ contextWindow: 1048576,
18860
+ effort: {
18861
+ supported: true,
18862
+ levels: [
18863
+ "low",
18864
+ "medium",
18865
+ "high",
18866
+ "xhigh"
18867
+ ]
18868
+ }
18869
+ },
18848
18870
  {
18849
18871
  modelId: "deepseek-v4-flash",
18850
18872
  name: "DeepSeek-V4-Flash",
@@ -18895,6 +18917,21 @@ var models_default = {
18895
18917
  capabilityClass: "flagship",
18896
18918
  wire: "chat-completions",
18897
18919
  contextWindow: 256e3
18920
+ },
18921
+ {
18922
+ modelId: "ox-alpha-free",
18923
+ name: "Ox-Alpha-Free",
18924
+ capabilityClass: "flagship",
18925
+ wire: "chat-completions",
18926
+ contextWindow: 1e6,
18927
+ effort: {
18928
+ supported: true,
18929
+ levels: [
18930
+ "low",
18931
+ "high",
18932
+ "max"
18933
+ ]
18934
+ }
18898
18935
  }
18899
18936
  ]
18900
18937
  },
@@ -18923,7 +18960,7 @@ var models_default = {
18923
18960
  {
18924
18961
  modelId: "grok-composer-2.5-fast",
18925
18962
  name: "Grok-Composer-2.5-Fast",
18926
- capabilityClass: "light",
18963
+ capabilityClass: "standard",
18927
18964
  wire: "responses",
18928
18965
  contextWindow: 2e5
18929
18966
  }
@@ -19118,6 +19155,14 @@ var GatewayModelEntrySchema = external_exports.object({
19118
19155
  benchmarkKey: external_exports.string().min(1).optional(),
19119
19156
  description: external_exports.string().min(1).optional(),
19120
19157
  providerModelId: external_exports.string().min(1).optional(),
19158
+ /**
19159
+ * The catalog entry this one is a serving variant of, when the provider gives
19160
+ * the variant its own wire id and `providerModelId` is therefore unavailable
19161
+ * as the lineage link. Pure provenance: it names a sibling `modelId` in the
19162
+ * same provider and never reaches a request, so the variant keeps sending its
19163
+ * own upstream id while inheriting the base's class and benchmark evidence.
19164
+ */
19165
+ variantOf: external_exports.string().min(1).optional(),
19121
19166
  serviceTier: external_exports.literal("priority").optional(),
19122
19167
  cursorMaxMode: external_exports.literal(true).optional(),
19123
19168
  quotaScope: external_exports.enum(GATEWAY_QUOTA_SCOPES).optional(),
@@ -19316,8 +19361,24 @@ function validateRegistry(value) {
19316
19361
  if (!isRoutingAlias && !model.capabilityClass) {
19317
19362
  throw new Error(`Gateway model is missing a capability class: ${provider}/${model.modelId}`);
19318
19363
  }
19319
- if (!isRoutingAlias && model.providerModelId) {
19320
- const base = definition.models.find((candidate) => candidate.modelId === model.providerModelId);
19364
+ const catalogEntry = (modelId) => modelId === void 0 ? void 0 : definition.models.find((candidate) => candidate.modelId === modelId);
19365
+ const providerLinkedBase = isRoutingAlias ? void 0 : catalogEntry(model.providerModelId);
19366
+ if (model.variantOf && providerLinkedBase && model.providerModelId !== model.variantOf) {
19367
+ throw new Error(`Gateway service-tier sibling names two different bases: ${provider}/${model.modelId}`);
19368
+ }
19369
+ if (model.variantOf === model.modelId) {
19370
+ throw new Error(`Gateway service-tier sibling names itself as its base: ${provider}/${model.modelId}`);
19371
+ }
19372
+ const baseModelId = isRoutingAlias ? void 0 : model.variantOf ?? model.providerModelId;
19373
+ if (baseModelId) {
19374
+ const base = catalogEntry(baseModelId);
19375
+ if (model.variantOf && !base) {
19376
+ throw new Error(`Gateway service-tier sibling names an unknown base: ${provider}/${model.modelId} -> ${model.variantOf}`);
19377
+ }
19378
+ const baseLink = base && base.modelId !== base.providerModelId ? base.variantOf ?? base.providerModelId : base?.variantOf;
19379
+ if (base && catalogEntry(baseLink)) {
19380
+ throw new Error(`Gateway service-tier sibling names another sibling as its base: ${provider}/${model.modelId}`);
19381
+ }
19321
19382
  if (base && base.capabilityClass !== model.capabilityClass) {
19322
19383
  throw new Error(`Gateway service-tier sibling class differs from its base: ${provider}/${model.modelId}`);
19323
19384
  }
@@ -18032,7 +18032,7 @@ var benchmarks_default = {
18032
18032
  };
18033
18033
  var models_default = {
18034
18034
  version: 1,
18035
- updatedAt: "2026-08-20T00:00:00Z",
18035
+ updatedAt: "2026-08-22T00:00:00Z",
18036
18036
  providers: {
18037
18037
  codex: {
18038
18038
  name: "Codex",
@@ -18443,7 +18443,7 @@ var models_default = {
18443
18443
  {
18444
18444
  modelId: "composer-2.5",
18445
18445
  name: "Composer-2.5",
18446
- capabilityClass: "flagship",
18446
+ capabilityClass: "standard",
18447
18447
  quotaScope: "auto",
18448
18448
  contextWindow: 2e5,
18449
18449
  benchmarkKey: "composer-2.5"
@@ -18451,9 +18451,11 @@ var models_default = {
18451
18451
  {
18452
18452
  modelId: "composer-2.5-fast",
18453
18453
  name: "Composer-2.5-Fast",
18454
- capabilityClass: "light",
18454
+ capabilityClass: "standard",
18455
+ variantOf: "composer-2.5",
18455
18456
  quotaScope: "auto",
18456
- contextWindow: 2e5
18457
+ contextWindow: 2e5,
18458
+ benchmarkKey: "composer-2.5"
18457
18459
  },
18458
18460
  {
18459
18461
  modelId: "grok-4.5",
@@ -18475,7 +18477,8 @@ var models_default = {
18475
18477
  {
18476
18478
  modelId: "grok-4.5-fast",
18477
18479
  name: "Grok-4.5-Fast",
18478
- capabilityClass: "light",
18480
+ capabilityClass: "flagship",
18481
+ variantOf: "grok-4.5",
18479
18482
  quotaScope: "auto",
18480
18483
  contextWindow: 256e3,
18481
18484
  effort: {
@@ -18486,7 +18489,8 @@ var models_default = {
18486
18489
  "high"
18487
18490
  ],
18488
18491
  upstreamModelIdTemplate: "cursor-grok-4.5-{effort}-fast"
18489
- }
18492
+ },
18493
+ benchmarkKey: "grok-4.5"
18490
18494
  },
18491
18495
  {
18492
18496
  modelId: "grok-4.6",
@@ -18509,7 +18513,8 @@ var models_default = {
18509
18513
  {
18510
18514
  modelId: "grok-4.6-fast",
18511
18515
  name: "Grok-4.6-Fast",
18512
- capabilityClass: "light",
18516
+ capabilityClass: "flagship",
18517
+ variantOf: "grok-4.6",
18513
18518
  quotaScope: "auto",
18514
18519
  contextWindow: 256e3,
18515
18520
  effort: {
@@ -18521,7 +18526,8 @@ var models_default = {
18521
18526
  "xhigh"
18522
18527
  ],
18523
18528
  upstreamModelIdTemplate: "cursor-grok-4.6-{effort}-fast"
18524
- }
18529
+ },
18530
+ benchmarkKey: "grok-4.6"
18525
18531
  },
18526
18532
  {
18527
18533
  modelId: "claude-opus-5",
@@ -18749,7 +18755,7 @@ var models_default = {
18749
18755
  opencode: {
18750
18756
  name: "OpenCode",
18751
18757
  defaultModel: "minimax-m3",
18752
- 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); superseded generations removed 2026-08-08 \u2014 the catalog keeps each lineup's current generation only",
18758
+ 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); superseded generations removed 2026-08-08 \u2014 the catalog keeps each lineup's current generation only; ox-alpha-free and muse-spark-1.2-contributor added 2026-08-21 from the same live list, each wire chosen by a streaming probe on that date (ox-alpha-free frames natively on /chat/completions and returns reasoning_content deltas; muse-spark-1.2-contributor frames natively on /responses and echoes its own reasoning block) and each effort ladder taken from the upstream's own rejection message (ox-alpha-free: low/high/max; muse-spark-1.2-contributor: none/minimal/low/medium/high/xhigh, so max is refused); their contextWindow comes from models.dev api.json opencode-go entries (2026-08-21). muse-spark-1.2-contributor's Responses backend accepts only tool_choice auto: named function choices, required, and none are refused with a 400 (2026-08-21), so a caller that forces a tool cannot use it",
18753
18759
  models: [
18754
18760
  {
18755
18761
  modelId: "minimax-m3",
@@ -18797,6 +18803,22 @@ var models_default = {
18797
18803
  },
18798
18804
  benchmarkKey: "grok-4.5"
18799
18805
  },
18806
+ {
18807
+ modelId: "muse-spark-1.2-contributor",
18808
+ name: "Muse-Spark-1.2-Contributor",
18809
+ capabilityClass: "flagship",
18810
+ wire: "responses",
18811
+ contextWindow: 1048576,
18812
+ effort: {
18813
+ supported: true,
18814
+ levels: [
18815
+ "low",
18816
+ "medium",
18817
+ "high",
18818
+ "xhigh"
18819
+ ]
18820
+ }
18821
+ },
18800
18822
  {
18801
18823
  modelId: "deepseek-v4-flash",
18802
18824
  name: "DeepSeek-V4-Flash",
@@ -18847,6 +18869,21 @@ var models_default = {
18847
18869
  capabilityClass: "flagship",
18848
18870
  wire: "chat-completions",
18849
18871
  contextWindow: 256e3
18872
+ },
18873
+ {
18874
+ modelId: "ox-alpha-free",
18875
+ name: "Ox-Alpha-Free",
18876
+ capabilityClass: "flagship",
18877
+ wire: "chat-completions",
18878
+ contextWindow: 1e6,
18879
+ effort: {
18880
+ supported: true,
18881
+ levels: [
18882
+ "low",
18883
+ "high",
18884
+ "max"
18885
+ ]
18886
+ }
18850
18887
  }
18851
18888
  ]
18852
18889
  },
@@ -18875,7 +18912,7 @@ var models_default = {
18875
18912
  {
18876
18913
  modelId: "grok-composer-2.5-fast",
18877
18914
  name: "Grok-Composer-2.5-Fast",
18878
- capabilityClass: "light",
18915
+ capabilityClass: "standard",
18879
18916
  wire: "responses",
18880
18917
  contextWindow: 2e5
18881
18918
  }
@@ -19072,6 +19109,14 @@ var GatewayModelEntrySchema = external_exports.object({
19072
19109
  benchmarkKey: external_exports.string().min(1).optional(),
19073
19110
  description: external_exports.string().min(1).optional(),
19074
19111
  providerModelId: external_exports.string().min(1).optional(),
19112
+ /**
19113
+ * The catalog entry this one is a serving variant of, when the provider gives
19114
+ * the variant its own wire id and `providerModelId` is therefore unavailable
19115
+ * as the lineage link. Pure provenance: it names a sibling `modelId` in the
19116
+ * same provider and never reaches a request, so the variant keeps sending its
19117
+ * own upstream id while inheriting the base's class and benchmark evidence.
19118
+ */
19119
+ variantOf: external_exports.string().min(1).optional(),
19075
19120
  serviceTier: external_exports.literal("priority").optional(),
19076
19121
  cursorMaxMode: external_exports.literal(true).optional(),
19077
19122
  quotaScope: external_exports.enum(GATEWAY_QUOTA_SCOPES).optional(),
@@ -19270,8 +19315,24 @@ function validateRegistry(value) {
19270
19315
  if (!isRoutingAlias && !model.capabilityClass) {
19271
19316
  throw new Error(`Gateway model is missing a capability class: ${provider}/${model.modelId}`);
19272
19317
  }
19273
- if (!isRoutingAlias && model.providerModelId) {
19274
- const base = definition.models.find((candidate) => candidate.modelId === model.providerModelId);
19318
+ const catalogEntry = (modelId) => modelId === void 0 ? void 0 : definition.models.find((candidate) => candidate.modelId === modelId);
19319
+ const providerLinkedBase = isRoutingAlias ? void 0 : catalogEntry(model.providerModelId);
19320
+ if (model.variantOf && providerLinkedBase && model.providerModelId !== model.variantOf) {
19321
+ throw new Error(`Gateway service-tier sibling names two different bases: ${provider}/${model.modelId}`);
19322
+ }
19323
+ if (model.variantOf === model.modelId) {
19324
+ throw new Error(`Gateway service-tier sibling names itself as its base: ${provider}/${model.modelId}`);
19325
+ }
19326
+ const baseModelId = isRoutingAlias ? void 0 : model.variantOf ?? model.providerModelId;
19327
+ if (baseModelId) {
19328
+ const base = catalogEntry(baseModelId);
19329
+ if (model.variantOf && !base) {
19330
+ throw new Error(`Gateway service-tier sibling names an unknown base: ${provider}/${model.modelId} -> ${model.variantOf}`);
19331
+ }
19332
+ const baseLink = base && base.modelId !== base.providerModelId ? base.variantOf ?? base.providerModelId : base?.variantOf;
19333
+ if (base && catalogEntry(baseLink)) {
19334
+ throw new Error(`Gateway service-tier sibling names another sibling as its base: ${provider}/${model.modelId}`);
19335
+ }
19275
19336
  if (base && base.capabilityClass !== model.capabilityClass) {
19276
19337
  throw new Error(`Gateway service-tier sibling class differs from its base: ${provider}/${model.modelId}`);
19277
19338
  }