nolo-cli 0.211.0 → 0.212.0-alpha.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 (158) hide show
  1. package/{_executeModel-VVQEOY3D.js → _executeModel-KE6MBNUJ.js} +51 -48
  2. package/{action-U235TV4P.js → action-DF5UYSJF.js} +4 -4
  3. package/{addContentAction-7C76J7ST.js → addContentAction-N2YC5IL3.js} +8 -8
  4. package/{addDialogAgentAction-KTYANUEC.js → addDialogAgentAction-3NKVQCEC.js} +15 -12
  5. package/{agentDeleteCommand-WHRU6VDJ.js → agentDeleteCommand-NWK7VU4N.js} +71 -67
  6. package/{agentEmailCommands-ALLHXPW3.js → agentEmailCommands-UZ4DHEX2.js} +77 -72
  7. package/{agentListCommands-POKMEKMS.js → agentListCommands-HE7L2A6L.js} +190 -77
  8. package/{agentMachineCommands-WJLZLBPI.js → agentMachineCommands-6TE4MBMP.js} +30 -29
  9. package/{agentProviderCommands-MN3ABDME.js → agentProviderCommands-Q5O33MED.js} +33 -4
  10. package/{agentRecordCommands-OULZW3KM.js → agentRecordCommands-L3QQ7HZ4.js} +66 -61
  11. package/{agentRunCommand-ZNG4LGNQ.js → agentRunCommand-2IFGQHCO.js} +68 -64
  12. package/{agentRunControl-AF7BMR22.js → agentRunControl-OI3LOENH.js} +7 -6
  13. package/{agentRuntimeLocal-YMUHFV5M.js → agentRuntimeLocal-HL526DNQ.js} +28 -25
  14. package/{agentSlice-WNGUIMQZ.js → agentSlice-TMYP2UEA.js} +12 -12
  15. package/{appDeleteCommands-6MXPLAVF.js → appDeleteCommands-ZERW4AXY.js} +30 -29
  16. package/{appDeployCommands-ERRSVASW.js → appDeployCommands-DUWSMYHL.js} +30 -29
  17. package/{appDeployStatusCommands-ULICISLI.js → appDeployStatusCommands-N2KIE4BF.js} +30 -29
  18. package/{appGetCommands-WYYYWROF.js → appGetCommands-YVR4NPVY.js} +30 -29
  19. package/{appListCommands-DFCUCRCV.js → appListCommands-JS6HOHZS.js} +30 -29
  20. package/{authCommand-ZJMWXFMA.js → authCommand-FE2C3ZUM.js} +14 -14
  21. package/{authCommands-WK6E42L2.js → authCommands-HV3EAU3V.js} +2 -2
  22. package/{builtinSkillRegistry-HH75G5J3.js → builtinSkillRegistry-3YOIGEF6.js} +5 -4
  23. package/{chunk-JKW6LERJ.js → chunk-22CIEBYO.js} +14 -14
  24. package/{chunk-6HVBI6TI.js → chunk-25JZEIXN.js} +1 -218
  25. package/{chunk-TRZP7JZ7.js → chunk-2QHFH3DR.js} +1 -0
  26. package/{chunk-4LEGTOSR.js → chunk-3AKFVZ2I.js} +1 -1
  27. package/{chunk-XE4Q46FF.js → chunk-3CGG2PAL.js} +1 -1
  28. package/{chunk-25M2K6OA.js → chunk-3FOQHGHN.js} +3 -3
  29. package/{chunk-BSISWVB4.js → chunk-4I7ERB7F.js} +1 -1
  30. package/{chunk-TCTSYFDM.js → chunk-4KH4J3G5.js} +19 -6
  31. package/{chunk-NEZGPBL7.js → chunk-5AQR3DGV.js} +2 -2
  32. package/{chunk-YLTLB5A7.js → chunk-5RYBGBQH.js} +7 -6
  33. package/{chunk-RIALQUSF.js → chunk-6NSSLV67.js} +5 -5
  34. package/{chunk-RXCCWVA2.js → chunk-6OQUPIQF.js} +3 -3
  35. package/chunk-6VLJ6YA7.js +11751 -0
  36. package/{chunk-27E2CBBY.js → chunk-7OCO4TDT.js} +1 -1
  37. package/chunk-7RFNTILS.js +2213 -0
  38. package/{chunk-4WCEC56C.js → chunk-AVTVGMDY.js} +1 -1
  39. package/{chunk-3J3U3KXB.js → chunk-B7NJ3T4A.js} +4 -4
  40. package/{chunk-UMEGDH6A.js → chunk-BFM34N54.js} +7 -7
  41. package/chunk-CJEIOP3E.js +0 -0
  42. package/{chunk-YXOBCDNW.js → chunk-CJRONOYL.js} +5 -5
  43. package/{chunk-LT3EAHJY.js → chunk-CQ46IRNN.js} +38 -36
  44. package/{chunk-NTSRCTUX.js → chunk-CTPXME7U.js} +2 -2
  45. package/{chunk-M4NTDZG3.js → chunk-D5RCRX4A.js} +134 -141
  46. package/{chunk-25OB36GU.js → chunk-DM6UMOEL.js} +4 -4
  47. package/{chunk-TPCDYNJK.js → chunk-EYUBHHFB.js} +1 -1
  48. package/{chunk-Y6M7KJOA.js → chunk-EZFQ6XRV.js} +2 -2
  49. package/{chunk-ZOO3WJIE.js → chunk-FHU44LN3.js} +711 -40
  50. package/chunk-FY7F4Q6X.js +127 -0
  51. package/chunk-G7MLNNEX.js +84 -0
  52. package/{chunk-RYWO5AKN.js → chunk-GNDJKC4B.js} +10 -10
  53. package/{chunk-V3M6IXQI.js → chunk-GPO7FCEZ.js} +187 -36
  54. package/{chunk-RQ22OZD7.js → chunk-H2TJUNCH.js} +1 -1
  55. package/{chunk-C2XZM3K4.js → chunk-HIRC32DV.js} +5 -24
  56. package/{chunk-QQM464AL.js → chunk-HPFCI4SK.js} +3 -3
  57. package/chunk-HRMJUN5J.js +26 -0
  58. package/{chunk-HD3WR3TD.js → chunk-IAPCBNEE.js} +1 -1
  59. package/{chunk-XDMGY5IU.js → chunk-IF45XG7K.js} +220 -9
  60. package/{chunk-NLT32XBZ.js → chunk-IIQ6JGRI.js} +2 -2
  61. package/{chunk-OP7PTBAJ.js → chunk-IJXYFTV7.js} +8 -8
  62. package/{chunk-IIHY4ZAI.js → chunk-INSBKSBB.js} +8 -4
  63. package/{chunk-PAFTGNWA.js → chunk-JIT6FSXJ.js} +1 -1
  64. package/{chunk-WTKYP6QO.js → chunk-JTDORD5P.js} +5 -5
  65. package/{chunk-ECX3NKRD.js → chunk-JY5NGFFH.js} +11 -0
  66. package/chunk-KC4XDTT3.js +227 -0
  67. package/{chunk-PLYWH7XM.js → chunk-KIM6CLW5.js} +7 -7
  68. package/{chunk-SCYQJPGA.js → chunk-M6RL5JCD.js} +147 -20
  69. package/chunk-MMA3LZ3W.js +105 -0
  70. package/{chunk-I5PBXF7O.js → chunk-MMNYUVLW.js} +1 -1
  71. package/{chunk-NHQKWPLP.js → chunk-NJR3WKVP.js} +24 -22
  72. package/{chunk-W5VC7F7V.js → chunk-NOMIGOST.js} +59 -60
  73. package/{chunk-WI6OGHXJ.js → chunk-NRFKLKRU.js} +5 -5
  74. package/{chunk-NXCGNS4N.js → chunk-OHNELDTO.js} +1 -1
  75. package/{chunk-7IYBN7IA.js → chunk-OOF4UPC5.js} +22 -13
  76. package/{chunk-UIOEHFF6.js → chunk-OQHIVPG4.js} +1 -0
  77. package/{chunk-X4F26D5K.js → chunk-P5L7CXOC.js} +58 -33
  78. package/{chunk-5ORJGHTL.js → chunk-PDGKOTO7.js} +5 -5
  79. package/{chunk-UCPAVEQB.js → chunk-PYRUW7XN.js} +1 -1
  80. package/{chunk-SU3QL7YG.js → chunk-QT6PKHYJ.js} +1 -1
  81. package/{chunk-SN5XE6GQ.js → chunk-RPQXPZZF.js} +4 -4
  82. package/{chunk-ZN5AH4BY.js → chunk-RU4SD66C.js} +6 -6
  83. package/{chunk-YKFP6UGT.js → chunk-SOHTHFV2.js} +14 -14
  84. package/{chunk-CKOO42G5.js → chunk-UHJGXRJ4.js} +4 -4
  85. package/{chunk-CVCRAO6Q.js → chunk-UTV2AYEG.js} +9 -7
  86. package/{chunk-DQLB4NQ3.js → chunk-VPAZOH2D.js} +2 -2
  87. package/{chunk-MBS6CTZB.js → chunk-VZKUKCA6.js} +236 -1993
  88. package/{chunk-LNYHAKBP.js → chunk-W4S457LU.js} +1 -1
  89. package/chunk-WPORQFYN.js +74 -0
  90. package/{chunk-ET2CWLIJ.js → chunk-WXYLV624.js} +3 -3
  91. package/chunk-XFYFMTOM.js +92 -0
  92. package/{chunk-NV572QM3.js → chunk-YJMRHHGY.js} +15 -15
  93. package/{chunk-JBOUVTZX.js → chunk-YOIW77S2.js} +13 -2
  94. package/{chunk-ADBWFYJD.js → chunk-YPD3VJZW.js} +9 -9
  95. package/{chunk-DA7CTWT4.js → chunk-YWSEPJ7C.js} +5 -5
  96. package/{chunk-3V2QMRNN.js → chunk-ZL5RAEEB.js} +3 -3
  97. package/cliAgentConfigHelpers-WJBZQTLW.js +41 -0
  98. package/{commandRegistry-FI2IOQ3U.js → commandRegistry-VVMTPFAX.js} +85 -81
  99. package/{contentThunks-5LKNNDGY.js → contentThunks-N52O67MI.js} +25 -24
  100. package/{createAgentAutomationAction-TI4QG4CY.js → createAgentAutomationAction-ZC57YRSV.js} +25 -24
  101. package/{createDialogAction-TJ3JKLO4.js → createDialogAction-VQW5WDYX.js} +27 -26
  102. package/{createPageAction-GKXT6WEH.js → createPageAction-M5VDA7SC.js} +26 -25
  103. package/{dbSlice-LPMZ2DGJ.js → dbSlice-HP7G4LX3.js} +7 -7
  104. package/{deleteFile-EPUQHKPA.js → deleteFile-7VQGLK2V.js} +3 -3
  105. package/{dialogCommands-IWPXIZ5P.js → dialogCommands-JHMR2N2Y.js} +32 -30
  106. package/{dialogSlice-ZWNNS7GZ.js → dialogSlice-GRSVGDTF.js} +23 -22
  107. package/{dialogUsageCommand-ZCPPHPJ5.js → dialogUsageCommand-7KCPYGHG.js} +1 -1
  108. package/{docCreateCommands-HFSPKJSI.js → docCreateCommands-F2K3UPSQ.js} +28 -27
  109. package/{docDeleteCommands-CRL62POH.js → docDeleteCommands-XGXB5RFT.js} +29 -28
  110. package/{docReadCommands-QOTOX3XW.js → docReadCommands-7HWZZV6J.js} +28 -27
  111. package/{docStore-WYLRB7ED.js → docStore-KNZK6Y2G.js} +10 -10
  112. package/{docUpdateCommands-7BMH4MCA.js → docUpdateCommands-OZZ7NQII.js} +28 -27
  113. package/{fetchMessages-YY4SATNR.js → fetchMessages-M3QU7ZCQ.js} +1 -1
  114. package/{getPricing-OQXBJ6VZ.js → getPricing-2MNMXEVG.js} +3 -3
  115. package/{handleSendMessageAction-P27YP2DQ.js → handleSendMessageAction-SHIH74GJ.js} +46 -44
  116. package/hostCredentialCreate-X64WK4JD.js +357 -0
  117. package/index.js +5 -5
  118. package/{keys-P4ZDOVJW.js → keys-BEGDOTRL.js} +3 -1
  119. package/{localDialogRead-5VCMQQZF.js → localDialogRead-XRLAH4CZ.js} +1 -1
  120. package/{localRuntimeAdapter-GP6ZSSO3.js → localRuntimeAdapter-A7K3ABA6.js} +73 -66
  121. package/{machineCommands-6Z6H4BFX.js → machineCommands-DE3MR7CJ.js} +65 -60
  122. package/{machineWsRunDispatch-F2ZIXMYM.js → machineWsRunDispatch-R26P5V36.js} +65 -60
  123. package/{memberThunks-YSEFJF47.js → memberThunks-7WJAY5V6.js} +8 -8
  124. package/package.json +1 -1
  125. package/{projectArchive-PIGEOX3D.js → projectArchive-GGL5HLMD.js} +26 -25
  126. package/{providerPresetApply-ZYMLQA46.js → providerPresetApply-YXGV6NXB.js} +4 -4
  127. package/{providerRegistry-E34XWDLJ.js → providerRegistry-S6UL6UNA.js} +4 -4
  128. package/{read-DIIQBOOO.js → read-4VZQODSN.js} +3 -3
  129. package/{readDocTool-HXYGOEA7.js → readDocTool-AVD32RUJ.js} +1 -1
  130. package/{readlineWorkspace-UG25G7KC.js → readlineWorkspace-XKYKNL2I.js} +157 -100
  131. package/{removeDialogAgentAction-ALJDUJ2E.js → removeDialogAgentAction-FKL4BYMR.js} +17 -14
  132. package/{runAgentClientLoop-IO5F7TCZ.js → runAgentClientLoop-V7E2WBVM.js} +49 -46
  133. package/{runtimeDoctorCommands-PGAA47G5.js → runtimeDoctorCommands-QAI3MBKQ.js} +6 -6
  134. package/{secretCommands-ZCZ4KVET.js → secretCommands-4QS3HCA2.js} +3 -3
  135. package/{setDialogExtraReferencesAction-O3SVMD5A.js → setDialogExtraReferencesAction-TLIOLWWI.js} +10 -10
  136. package/{setPrimaryDialogAgentAction-HE7RVFFF.js → setPrimaryDialogAgentAction-2OLWRFYR.js} +18 -15
  137. package/{settingThunks-BWWJQG4L.js → settingThunks-UGBPCNYF.js} +12 -11
  138. package/{spaceCommands-UAELIFEI.js → spaceCommands-4KSLKVNF.js} +28 -27
  139. package/{streamAgentChatTurn-VUKZQYJR.js → streamAgentChatTurn-7FR7X2NU.js} +57 -54
  140. package/{switchDialogAgentAction-3VZS7SOS.js → switchDialogAgentAction-UZSAG2N5.js} +15 -12
  141. package/{tools-VRXJAVYI.js → tools-ZLKCC25W.js} +43 -40
  142. package/{tuiSummaryLlmCaller-TGCHZLSW.js → tuiSummaryLlmCaller-WC54MVGP.js} +10 -10
  143. package/{updateCommands-Q6CYAEYJ.js → updateCommands-4744PL3P.js} +3 -1
  144. package/{updateDialogTitleAction-MULWCJCW.js → updateDialogTitleAction-U53ZT7PJ.js} +38 -70
  145. package/usageCommand-F4IPVMIZ.js +32 -0
  146. package/usageRebuildCommand-HAW2AD5N.js +626 -0
  147. package/chunk-4LCOCOR5.js +0 -50
  148. package/chunk-7AUQ3WCW.js +0 -51
  149. package/chunk-ZRAU6T47.js +0 -56
  150. package/{agentFavoriteCommands-GAFEXKKP.js → agentFavoriteCommands-EDK743YA.js} +1 -1
  151. package/{agentGrantCommands-V5FOQKFD.js → agentGrantCommands-RQWK2TEV.js} +1 -1
  152. package/{agentPullCommand-2JMJP5BS.js → agentPullCommand-6EM3URVK.js} +1 -1
  153. package/{chunk-BTYQAODF.js → chunk-CZM5YTZ7.js} +3 -3
  154. package/{chunk-A2ZMIRLN.js → chunk-INN4LTAJ.js} +5 -5
  155. package/{chunk-XPHZK3PJ.js → chunk-JNKSDZFS.js} +3 -3
  156. package/{chunk-PV6JJAUB.js → chunk-TCZHTTUU.js} +8 -8
  157. package/{chunk-AKE53VMW.js → chunk-ZCWRMUWT.js} +0 -0
  158. package/{tableCommands-D7WR4QSM.js → tableCommands-MP6VFSVT.js} +3 -3
@@ -0,0 +1,626 @@
1
+ import {
2
+ parseUsageArgs,
3
+ require_date_fns,
4
+ resolveDateWindow
5
+ } from "./chunk-6VLJ6YA7.js";
6
+ import "./chunk-FY7F4Q6X.js";
7
+ import {
8
+ applyTokenUsageToDayStats,
9
+ normalizeStats
10
+ } from "./chunk-7RFNTILS.js";
11
+ import "./chunk-WPORQFYN.js";
12
+ import "./chunk-MMA3LZ3W.js";
13
+ import {
14
+ getDefaultCliLocalRuntimeDb
15
+ } from "./chunk-AZMYUSVF.js";
16
+ import "./chunk-GLKOYSRU.js";
17
+ import {
18
+ isLevelNotFoundError
19
+ } from "./chunk-OW765XBU.js";
20
+ import {
21
+ createTokenKey,
22
+ createTokenStatsKey,
23
+ createUsageBackupKey
24
+ } from "./chunk-JY5NGFFH.js";
25
+ import "./chunk-XJWWBO34.js";
26
+ import "./chunk-I42VC5KR.js";
27
+ import "./chunk-U6VC4MU4.js";
28
+ import "./chunk-WWC7I6TA.js";
29
+ import "./chunk-3EUW3WEO.js";
30
+ import "./chunk-G3SUCT4W.js";
31
+ import {
32
+ __toESM
33
+ } from "./chunk-4VNS5WPM.js";
34
+
35
+ // packages/cli/usageRebuildCommand.ts
36
+ var import_date_fns = __toESM(require_date_fns(), 1);
37
+ async function writeRebuildOps(db, ops) {
38
+ if (typeof db.batchWrite === "function") return db.batchWrite(ops);
39
+ if (typeof db.batch === "function") return db.batch(ops);
40
+ throw new Error("rebuild db \u7F3A\u5C11\u6279\u91CF\u5199\u80FD\u529B\uFF1A\u65E2\u6CA1\u6709 batchWrite() \u4E5F\u6CA1\u6709 batch()");
41
+ }
42
+ var TOKEN_PREFIX = "token-";
43
+ function classifyDetailKey(key) {
44
+ if (!key.startsWith(TOKEN_PREFIX)) return { kind: "skip", reason: "not-token-prefix" };
45
+ if (key.startsWith("token-stats-")) return { kind: "skip", reason: "stats-namespace" };
46
+ if (key.startsWith("token-charge-stats-")) return { kind: "skip", reason: "stats-namespace" };
47
+ if (key.startsWith("idx-")) return { kind: "skip", reason: "foreign-namespace" };
48
+ return { kind: "candidate" };
49
+ }
50
+ var asNumber = (value, fallback = 0) => typeof value === "number" && Number.isFinite(value) ? value : fallback;
51
+ var asNonEmptyString = (value) => {
52
+ if (typeof value !== "string") return void 0;
53
+ const trimmed = value.trim();
54
+ return trimmed ? trimmed : void 0;
55
+ };
56
+ function userIdFromDetailKey(key) {
57
+ if (!key.startsWith(TOKEN_PREFIX)) return void 0;
58
+ const rest = key.slice(TOKEN_PREFIX.length);
59
+ const match = /^(.*)-(\d{10,13})(?:-.*)?$/.exec(rest);
60
+ return match ? match[1] : void 0;
61
+ }
62
+ function timestampFromDetailKey(key) {
63
+ const match = /-(\d{10,13})(?:-|$)/.exec(key);
64
+ if (!match) return void 0;
65
+ const parsed = Number.parseInt(match[1], 10);
66
+ return Number.isFinite(parsed) ? parsed : void 0;
67
+ }
68
+ function normalizeDetailRecord(key, value) {
69
+ if (!value || typeof value !== "object") return null;
70
+ const v = value;
71
+ const isTokenRecord = v.type === "token" || typeof v.input_tokens === "number";
72
+ if (!isTokenRecord) return null;
73
+ const userId = asNonEmptyString(v.userId) ?? userIdFromDetailKey(key);
74
+ if (!userId) return null;
75
+ const timestamp = asNumber(v.timestamp, asNumber(v.createdAt, Number.NaN)) || asNumber(timestampFromDetailKey(key), Number.NaN);
76
+ const dateKey = Number.isFinite(timestamp) && timestamp > 0 ? (0, import_date_fns.format)(new Date(timestamp), "yyyy-MM-dd") : asNonEmptyString(v.dateKey);
77
+ if (!dateKey || !/^\d{4}-\d{2}-\d{2}$/.test(dateKey)) return null;
78
+ const failed = v.status === "failed";
79
+ const agentRaw = asNonEmptyString(v.agentId) ?? asNonEmptyString(v.cybotId);
80
+ return {
81
+ userId,
82
+ dateKey,
83
+ input: asNumber(v.input_tokens),
84
+ output: asNumber(v.output_tokens),
85
+ cacheRead: asNumber(v.cache_read_input_tokens),
86
+ cacheCreation: asNumber(v.cache_creation_input_tokens),
87
+ cost: asNumber(v.cost),
88
+ model: asNonEmptyString(v.model),
89
+ provider: asNonEmptyString(v.provider),
90
+ agentId: agentRaw,
91
+ entryPath: asNonEmptyString(v.entry_path),
92
+ billable: v.billable === true,
93
+ // 只有明确的 true/false 才算已知;缺失、null、字符串 "true"、1 一律按未知处理。
94
+ billableUnknown: typeof v.billable !== "boolean",
95
+ failed
96
+ };
97
+ }
98
+ var detailGroupKey = (userId, dateKey) => `${userId}\0${dateKey}`;
99
+ function aggregateDetailsByDay(records) {
100
+ const byDay = /* @__PURE__ */ new Map();
101
+ let accepted = 0;
102
+ let missingAgent = 0;
103
+ let unknownBillable = 0;
104
+ const unknownBillableByDay = /* @__PURE__ */ new Map();
105
+ for (const record of records) {
106
+ const key = detailGroupKey(record.userId, record.dateKey);
107
+ const prev = byDay.get(key) ?? null;
108
+ if (!record.agentId) missingAgent++;
109
+ if (record.billableUnknown && !record.failed) {
110
+ unknownBillable++;
111
+ unknownBillableByDay.set(key, (unknownBillableByDay.get(key) ?? 0) + 1);
112
+ }
113
+ byDay.set(
114
+ key,
115
+ applyTokenUsageToDayStats(prev, {
116
+ userId: record.userId,
117
+ timeKey: record.dateKey,
118
+ model: record.model,
119
+ provider: record.provider,
120
+ input_tokens: record.input,
121
+ output_tokens: record.output,
122
+ cost: record.cost,
123
+ cache_read_input_tokens: record.cacheRead,
124
+ cache_creation_input_tokens: record.cacheCreation,
125
+ // 明细里没有 agentId 时**不传**:传了会让 applyTokenUsageToDayStats 建一个
126
+ // "unknown" 桶,把「这一维没记录」伪装成「确实有这么多未知 agent 用量」。
127
+ ...record.agentId ? { agentId: record.agentId } : {},
128
+ ...record.entryPath ? { entry_path: record.entryPath } : {},
129
+ ...record.failed ? { status: "failed" } : {},
130
+ // 与 client/localRuntimeDialog.ts 同一口径:(billable ?? false) ? platform : subscription
131
+ billingCategory: record.billable ? "platform" : "subscription"
132
+ })
133
+ );
134
+ accepted++;
135
+ }
136
+ return {
137
+ byDay,
138
+ accepted,
139
+ rejectedNonUsage: 0,
140
+ rejectedUnkeyed: 0,
141
+ missingAgent,
142
+ unknownBillable,
143
+ unknownBillableByDay
144
+ };
145
+ }
146
+ var TOKEN_METRICS = ["input", "output", "cacheRead", "cacheCreation"];
147
+ var DIMENSION_BUCKETS = [
148
+ "models",
149
+ "providers",
150
+ "agents",
151
+ "entryPaths",
152
+ "categories",
153
+ "modelCategories"
154
+ ];
155
+ var describeLoss = (before, after) => {
156
+ const diffs = [];
157
+ if (after.count < before.count) diffs.push(`count ${before.count}\u2192${after.count}`);
158
+ if (after.cost < before.cost) diffs.push(`cost ${before.cost}\u2192${after.cost}`);
159
+ for (const metric of TOKEN_METRICS) {
160
+ if (after.tokens[metric] < before.tokens[metric]) {
161
+ diffs.push(`${metric} ${before.tokens[metric]}\u2192${after.tokens[metric]}`);
162
+ }
163
+ }
164
+ return diffs;
165
+ };
166
+ function detectOverwriteRisks(existing, rebuilt) {
167
+ if (existing === null) return [];
168
+ const risks = [];
169
+ const before = normalizeStats(existing.total);
170
+ const after = normalizeStats(rebuilt.total);
171
+ const totalLosses = describeLoss(before, after);
172
+ if (totalLosses.length > 0) risks.push(`total \u51CF\u5C11: ${totalLosses.join(", ")}`);
173
+ for (const bucket of DIMENSION_BUCKETS) {
174
+ const beforeBucket = existing[bucket] ?? {};
175
+ const afterBucket = rebuilt[bucket] ?? {};
176
+ for (const [name, rawBefore] of Object.entries(beforeBucket)) {
177
+ const losses = describeLoss(normalizeStats(rawBefore), normalizeStats(afterBucket[name]));
178
+ if (losses.length === 0) continue;
179
+ const label = `${bucket}/${name}`;
180
+ risks.push(
181
+ afterBucket[name] === void 0 ? `${label} \u6876\u4F1A\u6574\u4F53\u6D88\u5931\uFF08${losses.join(", ")}\uFF09` : `${label} \u51CF\u5C11: ${losses.join(", ")}`
182
+ );
183
+ }
184
+ }
185
+ return risks;
186
+ }
187
+ function planRebuild(args) {
188
+ const plans = [];
189
+ for (const rebuilt of args.rebuiltByDay) {
190
+ const { userId, timeKey } = rebuilt;
191
+ const statsKey = createTokenStatsKey(userId, timeKey);
192
+ const groupKey = detailGroupKey(userId, timeKey);
193
+ const existing = args.existingByKey.get(groupKey) ?? null;
194
+ const existingTotal = normalizeStats(existing?.total);
195
+ const rebuiltTotal = normalizeStats(rebuilt.total);
196
+ const preservedFailed = Math.max(0, existingTotal.failedCount - rebuiltTotal.failedCount);
197
+ const merged = preservedFailed > 0 ? {
198
+ ...rebuilt,
199
+ total: { ...rebuilt.total, failedCount: rebuiltTotal.failedCount + preservedFailed }
200
+ } : rebuilt;
201
+ const unknownBillable = args.unknownBillableByDay?.get(groupKey) ?? 0;
202
+ const blocked = unknownBillable > 0;
203
+ const regressions = detectOverwriteRisks(existing, merged);
204
+ const skip = blocked || regressions.length > 0 && !args.force;
205
+ plans.push({
206
+ userId,
207
+ dateKey: timeKey,
208
+ statsKey,
209
+ rebuilt: merged,
210
+ existing,
211
+ existingCalls: existingTotal.count,
212
+ rebuiltCalls: rebuiltTotal.count,
213
+ existingFailed: existingTotal.failedCount,
214
+ rebuiltFailed: rebuiltTotal.failedCount,
215
+ preservedFailed,
216
+ unknownBillable,
217
+ blocked,
218
+ action: skip ? "skip" : existing === null ? "create" : "overwrite",
219
+ regressions,
220
+ ...skip ? {
221
+ skipReason: blocked ? `\u6709 ${unknownBillable} \u6761\u6210\u529F\u660E\u7EC6\u7684 billable \u7F3A\u5931\u6216\u975E\u5E03\u5C14\uFF0C\u6536\u8D39\u7C7B\u522B\u4E0E\u91D1\u989D\u65E0\u6CD5\u786E\u5B9A\uFF0C\u4E0D\u53EF\u91CD\u5EFA\uFF08--force \u4E5F\u4E0D\u89E3\u9664\uFF1B\u5148\u8865\u9F50\u660E\u7EC6\u518D\u91CD\u5EFA\uFF09` + (regressions.length > 0 ? `\u3002\u6B64\u5916\u8986\u76D6\u8FD8\u4F1A\u51CF\u5C11\u73B0\u6709\u6570\u636E\uFF1A${regressions.join("\uFF1B")}` : "") : `\u8986\u76D6\u4F1A\u51CF\u5C11\u73B0\u6709\u6570\u636E\uFF08\u73B0\u6709 ${existingTotal.count} \u6B21 / \u91CD\u5EFA ${rebuiltTotal.count} \u6B21\uFF09\uFF1A${regressions.join("\uFF1B")}\u3002\u5DF2\u8DF3\u8FC7\uFF1B\u786E\u8BA4\u8981\u8986\u76D6\u8BF7\u52A0 --force`
222
+ } : {}
223
+ });
224
+ }
225
+ return plans.sort((a, b) => a.dateKey.localeCompare(b.dateKey) || a.userId.localeCompare(b.userId));
226
+ }
227
+ function backupStatsKey(userId, dateKey, nowMs) {
228
+ return createUsageBackupKey(userId, dateKey, nowMs);
229
+ }
230
+ async function scanDetails(args) {
231
+ const range = args.userId ? createTokenKey.rangeOfUser(args.userId) : { start: TOKEN_PREFIX, end: `${TOKEN_PREFIX}\uFFFF` };
232
+ const byDay = /* @__PURE__ */ new Map();
233
+ let totalScanned = 0;
234
+ let skippedKeys = 0;
235
+ let accepted = 0;
236
+ let rejectedNonUsage = 0;
237
+ let rejectedUnkeyed = 0;
238
+ let missingAgent = 0;
239
+ let unknownBillable = 0;
240
+ const unknownBillableByDay = /* @__PURE__ */ new Map();
241
+ for await (const [rawKey, value] of args.db.iterator({ gte: range.start, lte: range.end })) {
242
+ const key = String(rawKey);
243
+ const verdict = classifyDetailKey(key);
244
+ if (verdict.kind === "skip") {
245
+ skippedKeys++;
246
+ continue;
247
+ }
248
+ totalScanned++;
249
+ const record = normalizeDetailRecord(key, value);
250
+ if (!record) {
251
+ if (value && typeof value === "object" && value.type === "token") rejectedUnkeyed++;
252
+ else rejectedNonUsage++;
253
+ continue;
254
+ }
255
+ if (args.userId && record.userId !== args.userId) {
256
+ rejectedUnkeyed++;
257
+ continue;
258
+ }
259
+ if (args.from && record.dateKey < args.from) continue;
260
+ if (args.to && record.dateKey > args.to) continue;
261
+ if (!record.agentId) missingAgent++;
262
+ const groupKey = detailGroupKey(record.userId, record.dateKey);
263
+ if (record.billableUnknown && !record.failed) {
264
+ unknownBillable++;
265
+ unknownBillableByDay.set(groupKey, (unknownBillableByDay.get(groupKey) ?? 0) + 1);
266
+ }
267
+ byDay.set(
268
+ groupKey,
269
+ applyTokenUsageToDayStats(byDay.get(groupKey) ?? null, {
270
+ userId: record.userId,
271
+ timeKey: record.dateKey,
272
+ model: record.model,
273
+ provider: record.provider,
274
+ input_tokens: record.input,
275
+ output_tokens: record.output,
276
+ cost: record.cost,
277
+ cache_read_input_tokens: record.cacheRead,
278
+ cache_creation_input_tokens: record.cacheCreation,
279
+ ...record.agentId ? { agentId: record.agentId } : {},
280
+ ...record.entryPath ? { entry_path: record.entryPath } : {},
281
+ ...record.failed ? { status: "failed" } : {},
282
+ billingCategory: record.billable ? "platform" : "subscription"
283
+ })
284
+ );
285
+ accepted++;
286
+ }
287
+ return {
288
+ byDay,
289
+ accepted,
290
+ rejectedNonUsage,
291
+ rejectedUnkeyed,
292
+ missingAgent,
293
+ unknownBillable,
294
+ unknownBillableByDay,
295
+ totalScanned,
296
+ skippedKeys
297
+ };
298
+ }
299
+ var hasFlag = (args, flag) => args.includes(flag);
300
+ function parseRebuildArgs(args) {
301
+ const base = parseUsageArgs(args);
302
+ if (base.days !== void 0) {
303
+ throw new Error("usage rebuild \u4E0D\u652F\u6301 --days\uFF1A\u91CD\u5EFA\u7A97\u53E3\u8981\u663E\u5F0F\u7ED9 --from/--to\uFF08\u6216\u7701\u7565\u8868\u793A\u5168\u90E8\u5386\u53F2\uFF09");
304
+ }
305
+ if (base.groupBy !== void 0 || base.agent || base.provider || base.model) {
306
+ throw new Error("usage rebuild \u4E0D\u63A5\u53D7 --by / --agent / --provider / --model\uFF1A\u5B83\u53EA\u91CD\u5EFA\u805A\u5408");
307
+ }
308
+ return { ...base, apply: hasFlag(args, "--apply"), force: hasFlag(args, "--force") };
309
+ }
310
+ var formatInt = (value) => value.toLocaleString("en-US");
311
+ var summarizeBuckets = (map) => {
312
+ const entries = Object.entries(map ?? {});
313
+ if (entries.length === 0) return "{}";
314
+ const shown = entries.slice(0, 4).map(([k, v]) => `${k}:${formatInt(normalizeStats(v).count)}`);
315
+ return `{${shown.join(", ")}${entries.length > 4 ? `, \u2026+${entries.length - 4}` : ""}}`;
316
+ };
317
+ var REBUILD_TEXT = [
318
+ "\u7528\u6CD5: nolo usage rebuild [\u9009\u9879]",
319
+ "",
320
+ " \u4ECE\u660E\u7EC6\u8BA1\u8D39\u8BB0\u5F55\uFF08token-<userId>-<timestamp>\u2026\uFF09\u91CD\u5EFA\u672C\u5730\u65E5\u805A\u5408 DayStats\uFF0C",
321
+ " \u8865\u56DE\u5386\u53F2\u4E0A\u7F3A\u5931\u7684 cacheRead / cacheCreation / agents / entryPaths \u7EF4\u5EA6\u3002",
322
+ "",
323
+ " \u9ED8\u8BA4 dry-run\uFF1A\u53EA\u6253\u5370\u5C06\u53D1\u751F\u7684\u53D8\u66F4\uFF0C\u4E0D\u5199\u5E93\u3002",
324
+ "",
325
+ "\u9009\u9879:",
326
+ " --from <date> \u53EA\u91CD\u5EFA\u8BE5\u65E5\u671F\u8D77\uFF08YYYY-MM-DD\uFF0C\u672C\u5730\u65E5\u671F\uFF09",
327
+ " --to <date> \u53EA\u91CD\u5EFA\u5230\u8BE5\u65E5\u671F\uFF08\u542B\uFF09",
328
+ " --all-users \u5904\u7406\u672C\u673A\u6240\u6709\u8D26\u53F7\uFF08\u9ED8\u8BA4\u53EA\u5904\u7406\u5F53\u524D\u767B\u5F55\u8D26\u53F7\uFF09",
329
+ " --apply \u771F\u6B63\u5199\u5E93\uFF08\u5148\u5907\u4EFD\u539F\u503C\uFF09",
330
+ " --force \u5141\u8BB8\u8986\u76D6\u300C\u73B0\u6709\u8C03\u7528\u6570 > \u91CD\u5EFA\u503C\u300D\u7684\u65E5\u671F",
331
+ " --json \u8F93\u51FA JSON",
332
+ " -h, --help \u663E\u793A\u672C\u5E2E\u52A9",
333
+ "",
334
+ "\u8BF4\u660E:",
335
+ " \xB7 \u91CD\u5EFA\u53EA\u4F9D\u8D56\u660E\u7EC6\u3002\u67D0\u5929\u73B0\u6709 total.calls \u5927\u4E8E\u91CD\u5EFA\u503C\u65F6\uFF0C\u8BF4\u660E\u8BE5\u5929\u6709\u660E\u7EC6\u4E4B\u5916\u7684\u6765\u6E90\uFF0C",
336
+ " \u9ED8\u8BA4\u8DF3\u8FC7\u5E76\u5728\u62A5\u544A\u91CC\u9010\u6761\u5217\u51FA\u300C\u73B0\u6709 N / \u91CD\u5EFA M\u300D\u3002",
337
+ " \xB7 \u73B0\u6709 failedCount \u9AD8\u4E8E\u91CD\u5EFA\u503C\u65F6\u4F1A\u4FDD\u7559\u73B0\u6709\u503C\uFF08\u5931\u8D25\u8BB0\u5F55\u662F\u540E\u52A0\u7EF4\u5EA6\uFF0C\u65E7\u6570\u636E\u65E0\u660E\u7EC6\u53EF\u4F9D\uFF09\u3002"
338
+ ].join("\n");
339
+ function buildReport(args) {
340
+ const days = args.plans.map((plan) => {
341
+ const existingTotal = normalizeStats(plan.existing?.total);
342
+ const rebuiltTotal = normalizeStats(plan.rebuilt.total);
343
+ return {
344
+ userId: plan.userId,
345
+ dateKey: plan.dateKey,
346
+ action: plan.action,
347
+ existingCalls: plan.existingCalls,
348
+ rebuiltCalls: plan.rebuiltCalls,
349
+ existingFailed: plan.existingFailed,
350
+ rebuiltFailed: plan.rebuiltFailed,
351
+ preservedFailed: plan.preservedFailed,
352
+ existingCacheRead: existingTotal.tokens.cacheRead,
353
+ rebuiltCacheRead: rebuiltTotal.tokens.cacheRead,
354
+ existingCacheCreation: existingTotal.tokens.cacheCreation,
355
+ rebuiltCacheCreation: rebuiltTotal.tokens.cacheCreation,
356
+ existingAgents: Object.keys(plan.existing?.agents ?? {}),
357
+ rebuiltAgents: Object.keys(plan.rebuilt.agents ?? {}),
358
+ unknownBillable: plan.unknownBillable,
359
+ blocked: plan.blocked,
360
+ ...plan.regressions.length > 0 ? { regressions: plan.regressions } : {},
361
+ ...plan.skipReason ? { skipReason: plan.skipReason } : {}
362
+ };
363
+ });
364
+ return {
365
+ scope: args.allUsers ? "all" : "user",
366
+ userId: args.userId,
367
+ applied: args.applied,
368
+ force: args.options.force === true,
369
+ window: args.window,
370
+ scanned: {
371
+ detailCandidates: args.scan.totalScanned,
372
+ skippedNonUserKeys: args.scan.skippedKeys,
373
+ accepted: args.scan.accepted,
374
+ rejectedNonUsage: args.scan.rejectedNonUsage,
375
+ rejectedUnkeyed: args.scan.rejectedUnkeyed,
376
+ missingAgent: args.scan.missingAgent,
377
+ unknownBillable: args.scan.unknownBillable
378
+ },
379
+ days,
380
+ written: args.plans.filter((p) => p.action !== "skip").length,
381
+ skipped: args.plans.filter((p) => p.action === "skip").length,
382
+ backups: args.backups
383
+ };
384
+ }
385
+ function formatRebuildReport(report) {
386
+ const lines = [];
387
+ const scopeLabel = report.scope === "all" ? "\u672C\u673A\u6240\u6709\u8D26\u53F7" : report.userId;
388
+ lines.push(
389
+ `\u8303\u56F4: ${scopeLabel} \u7A97\u53E3: ${report.window.from ?? "\u6700\u65E9"} \u2192 ${report.window.to ?? "\u4ECA\u5929"}`
390
+ );
391
+ lines.push(
392
+ `\u660E\u7EC6: \u5019\u9009 ${formatInt(report.scanned.detailCandidates)} \u6761\uFF08\u6536\u4E0B ${formatInt(report.scanned.accepted)}\uFF0C\u975E\u7528\u91CF ${formatInt(report.scanned.rejectedNonUsage)}\uFF0C\u53D6\u4E0D\u5230 userId/\u65E5\u671F ${formatInt(report.scanned.rejectedUnkeyed)}\uFF09`
393
+ );
394
+ if (report.scanned.missingAgent > 0) {
395
+ lines.push(
396
+ `\u6CE8\u610F: \u6709 ${formatInt(report.scanned.missingAgent)} \u6761\u660E\u7EC6\u6CA1\u6709 agentId/cybotId\uFF0C\u8FD9\u4E9B\u7528\u91CF\u4E0D\u4F1A\u8FDB agents \u7EF4\u5EA6\u3002`
397
+ );
398
+ }
399
+ if (report.scanned.unknownBillable > 0) {
400
+ lines.push(
401
+ `\u6CE8\u610F: \u6709 ${formatInt(report.scanned.unknownBillable)} \u6761\u6210\u529F\u660E\u7EC6\u7684 billable \u7F3A\u5931\u6216\u4E0D\u662F\u5E03\u5C14\u503C\uFF0C\u6536\u8D39\u7C7B\u522B\u4E0E\u91D1\u989D\u65E0\u6CD5\u786E\u5B9A \u2014\u2014 \u8FD9\u4E9B\u65E5\u671F\u4E0D\u53EF\u91CD\u5EFA\uFF08--force \u4E5F\u4E0D\u89E3\u9664\uFF1B\u8865\u9F50\u660E\u7EC6\u540E\u518D\u91CD\u5EFA\uFF09\u3002`
402
+ );
403
+ }
404
+ if (report.days.length === 0) {
405
+ lines.push("");
406
+ lines.push("\u6240\u9009\u7A97\u53E3\u5185\u6CA1\u6709\u53EF\u91CD\u5EFA\u7684\u660E\u7EC6\u3002");
407
+ return lines.join("\n");
408
+ }
409
+ lines.push("");
410
+ lines.push(report.applied ? "\u53D8\u66F4\uFF08\u5DF2\u5199\u5165\uFF09:" : "\u53D8\u66F4\uFF08dry-run\uFF0C\u672A\u5199\u5E93\uFF1B\u52A0 --apply \u624D\u4F1A\u5199\uFF09:");
411
+ for (const day of report.days) {
412
+ const head = ` ${day.dateKey} ${day.userId}`;
413
+ if (day.blocked) {
414
+ lines.push(
415
+ `${head} \u4E0D\u53EF\u91CD\u5EFA \u2014\u2014 ${formatInt(day.unknownBillable)} \u6761\u6210\u529F\u660E\u7EC6\u7684 billable \u672A\u77E5\uFF1B\u6536\u8D39\u7C7B\u522B/\u91D1\u989D\u65E0\u6CD5\u786E\u5B9A\uFF0C\u91CD\u5EFA\u503C\u4E0D\u7B97\u51C6\u786E\u7ED3\u679C\uFF0C\u6545\u4E0D\u5199\u5E93\uFF08--force \u4E5F\u4E0D\u8986\u76D6\uFF09`
416
+ );
417
+ if (day.skipReason) lines.push(` ${day.skipReason}`);
418
+ continue;
419
+ }
420
+ if (day.action === "skip") {
421
+ lines.push(`${head} \u8DF3\u8FC7 \u2014\u2014 \u73B0\u6709 ${formatInt(day.existingCalls)} / \u91CD\u5EFA ${formatInt(day.rebuiltCalls)} \u6B21\u8C03\u7528`);
422
+ if (day.skipReason) lines.push(` ${day.skipReason}`);
423
+ continue;
424
+ }
425
+ lines.push(
426
+ `${head} ${day.action === "create" ? "\u65B0\u5EFA" : "\u8986\u76D6"} \u8C03\u7528 ${formatInt(day.existingCalls)} \u2192 ${formatInt(day.rebuiltCalls)} \u7F13\u5B58\u8BFB ${formatInt(day.existingCacheRead)} \u2192 ${formatInt(day.rebuiltCacheRead)} \u7F13\u5B58\u5199 ${formatInt(day.existingCacheCreation)} \u2192 ${formatInt(day.rebuiltCacheCreation)}`
427
+ );
428
+ lines.push(
429
+ ` agent \u6876 ${day.existingAgents.length} \u2192 ${day.rebuiltAgents.length}` + (day.rebuiltAgents.length > 0 ? `\uFF08${day.rebuiltAgents.slice(0, 4).join(", ")}${day.rebuiltAgents.length > 4 ? ", \u2026" : ""}\uFF09` : "")
430
+ );
431
+ if (day.preservedFailed > 0) {
432
+ lines.push(
433
+ ` \u4FDD\u7559\u73B0\u6709 failedCount: \u73B0\u6709 ${formatInt(day.existingFailed)} / \u91CD\u5EFA ${formatInt(day.rebuiltFailed)}\uFF08\u4FDD\u7559 ${formatInt(day.preservedFailed)}\uFF09`
434
+ );
435
+ }
436
+ if (day.regressions && day.regressions.length > 0) {
437
+ lines.push(` \u26A0 \u5F3A\u5236\u8986\u76D6\u4F1A\u8BA9\u73B0\u6709\u6570\u636E\u53D8\u5C11: ${day.regressions.join("\uFF1B")}`);
438
+ }
439
+ }
440
+ lines.push("");
441
+ lines.push(`\u5408\u8BA1: \u5F85\u5199 ${formatInt(report.written)} \u5929\uFF0C\u8DF3\u8FC7 ${formatInt(report.skipped)} \u5929`);
442
+ const blockedDays = report.days.filter((day) => day.blocked).length;
443
+ if (blockedDays > 0) {
444
+ lines.push(`\u5176\u4E2D billable \u672A\u77E5\u4E0D\u53EF\u91CD\u5EFA ${formatInt(blockedDays)} \u5929\uFF08\u4E34\u65F6 0 \u4E0D\u4F5C\u4E3A\u51C6\u786E\u91CD\u5EFA\u7ED3\u679C\uFF0C\u672A\u5199\u5E93\uFF09`);
445
+ }
446
+ if (report.applied) {
447
+ const withOriginal = report.backups.filter((b) => b.hadOriginal).length;
448
+ lines.push(`\u5DF2\u5199\u5165 ${formatInt(report.written)} \u4E2A\u65E5\u805A\u5408\u952E\uFF1B\u5907\u4EFD ${formatInt(withOriginal)} \u4E2A\u539F\u503C\u952E`);
449
+ if (withOriginal > 0) {
450
+ lines.push("\u56DE\u6EDA\uFF1A\u628A backup-* \u952E\u7684\u503C\u5199\u56DE\u5BF9\u5E94\u65E5\u805A\u5408\u952E\u5373\u53EF\u3002");
451
+ }
452
+ } else if (report.skipped > 0) {
453
+ lines.push("\u88AB\u8DF3\u8FC7\u7684\u65E5\u671F\u8BF4\u660E\u8BE5\u5929\u5B58\u5728\u660E\u7EC6\u4E4B\u5916\u7684\u6765\u6E90\uFF1B\u786E\u8BA4\u540E\u53EF\u7528 --force \u8986\u76D6\u3002");
454
+ }
455
+ return lines.join("\n");
456
+ }
457
+ async function resolveRebuildUserId(env) {
458
+ const { resolveLocalUserId } = await import("./cliAgentConfigHelpers-WJBZQTLW.js");
459
+ return resolveLocalUserId(env);
460
+ }
461
+ async function runUsageRebuildCommand(args, deps) {
462
+ const output = deps.output ?? process.stdout;
463
+ const errorOutput = deps.errorOutput ?? process.stderr;
464
+ if (hasFlag(args, "-h") || hasFlag(args, "--help")) {
465
+ output.write(`${REBUILD_TEXT}
466
+ `);
467
+ return 0;
468
+ }
469
+ let options;
470
+ const window = {};
471
+ try {
472
+ options = parseRebuildArgs(args);
473
+ if (options.from !== void 0 || options.to !== void 0) {
474
+ const resolved = resolveDateWindow(options);
475
+ window.from = resolved.from;
476
+ window.to = resolved.to;
477
+ }
478
+ } catch (error) {
479
+ errorOutput.write(`[nolo] ${error instanceof Error ? error.message : String(error)}
480
+ `);
481
+ errorOutput.write(`${REBUILD_TEXT}
482
+ `);
483
+ return 1;
484
+ }
485
+ const userId = deps.userId?.trim() || await resolveRebuildUserId(deps.env);
486
+ const allUsers = options.allUsers === true;
487
+ const nowMs = deps.nowMs ?? (() => Date.now());
488
+ let db;
489
+ try {
490
+ db = deps.db ?? await getDefaultCliLocalRuntimeDb();
491
+ } catch (error) {
492
+ errorOutput.write(
493
+ `[nolo] \u6253\u5F00\u672C\u5730\u5E93\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}
494
+ `
495
+ );
496
+ return 1;
497
+ }
498
+ let scan;
499
+ try {
500
+ scan = await scanDetails({
501
+ db,
502
+ userId: allUsers ? void 0 : userId,
503
+ from: window.from,
504
+ to: window.to
505
+ });
506
+ } catch (error) {
507
+ errorOutput.write(
508
+ `[nolo] \u626B\u63CF\u660E\u7EC6\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}
509
+ `
510
+ );
511
+ return 1;
512
+ }
513
+ const existingByKey = /* @__PURE__ */ new Map();
514
+ for (const rebuilt of scan.byDay.values()) {
515
+ const statsKey = createTokenStatsKey(rebuilt.userId, rebuilt.timeKey);
516
+ let existing = null;
517
+ try {
518
+ const raw = await db.get(statsKey);
519
+ existing = raw && typeof raw === "object" ? raw : null;
520
+ } catch (error) {
521
+ if (!isLevelNotFoundError(error)) {
522
+ const reason = error instanceof Error ? error.message : String(error);
523
+ errorOutput.write(`[nolo] \u8BFB\u53D6\u73B0\u6709\u65E5\u805A\u5408\u5931\u8D25\uFF08${statsKey}\uFF09: ${reason}
524
+ `);
525
+ errorOutput.write(`[nolo] \u65E0\u6CD5\u786E\u8BA4\u8BE5\u952E\u662F\u5426\u771F\u7684\u4E0D\u5B58\u5728\uFF0C\u5DF2\u4E2D\u6B62\uFF1B\u672C\u6B21\u672A\u5199\u5165\u4EFB\u4F55\u65E5\u805A\u5408\u3002
526
+ `);
527
+ return 1;
528
+ }
529
+ existing = null;
530
+ }
531
+ existingByKey.set(detailGroupKey(rebuilt.userId, rebuilt.timeKey), existing);
532
+ }
533
+ const plans = planRebuild({
534
+ rebuiltByDay: scan.byDay.values(),
535
+ existingByKey,
536
+ unknownBillableByDay: scan.unknownBillableByDay,
537
+ force: options.force === true
538
+ });
539
+ const writable = plans.filter((plan) => plan.action !== "skip");
540
+ const backups = [];
541
+ let writeError = 0;
542
+ if (options.apply) {
543
+ const stamp = nowMs();
544
+ const backupOps = [];
545
+ for (const plan of writable) {
546
+ const backupKey = backupStatsKey(plan.userId, plan.dateKey, stamp);
547
+ backups.push({
548
+ userId: plan.userId,
549
+ dateKey: plan.dateKey,
550
+ backupKey,
551
+ hadOriginal: plan.existing !== null
552
+ });
553
+ if (plan.existing !== null) {
554
+ backupOps.push({ type: "put", key: backupKey, value: plan.existing });
555
+ }
556
+ }
557
+ if (backupOps.length > 0) {
558
+ try {
559
+ await writeRebuildOps(db, backupOps);
560
+ } catch (error) {
561
+ errorOutput.write(
562
+ `[nolo] \u5907\u4EFD\u539F\u503C\u5931\u8D25\uFF0C\u5DF2\u6574\u4F53\u4E2D\u6B62\u3001\u672A\u5199\u5165\u4EFB\u4F55\u65E5\u805A\u5408: ${error instanceof Error ? error.message : String(error)}
563
+ `
564
+ );
565
+ return 2;
566
+ }
567
+ }
568
+ const statsOps = writable.map((plan) => ({
569
+ type: "put",
570
+ key: plan.statsKey,
571
+ value: plan.rebuilt
572
+ }));
573
+ if (statsOps.length > 0) {
574
+ try {
575
+ await writeRebuildOps(db, statsOps);
576
+ } catch (error) {
577
+ errorOutput.write(
578
+ `[nolo] \u5199\u5165\u65E5\u805A\u5408\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}
579
+ `
580
+ );
581
+ errorOutput.write(`[nolo] \u539F\u503C\u5DF2\u5907\u4EFD\u5230 usage-backup-* \u952E\uFF0C\u53EF\u56DE\u6EDA\u3002
582
+ `);
583
+ writeError = 1;
584
+ }
585
+ }
586
+ }
587
+ const report = buildReport({
588
+ plans,
589
+ scan,
590
+ userId,
591
+ allUsers,
592
+ options,
593
+ window,
594
+ backups,
595
+ applied: options.apply === true && writeError === 0
596
+ });
597
+ if (options.json) {
598
+ output.write(`${JSON.stringify(report, null, 2)}
599
+ `);
600
+ return writeError;
601
+ }
602
+ if (allUsers) output.write("\u8303\u56F4: \u672C\u673A\u6240\u6709\u8D26\u53F7\n");
603
+ output.write(`${formatRebuildReport(report)}
604
+ `);
605
+ return writeError;
606
+ }
607
+ function describeDayStats(stats) {
608
+ const total = normalizeStats(stats.total);
609
+ return `calls=${total.count} failed=${total.failedCount} cacheRead=${total.tokens.cacheRead} cacheCreation=${total.tokens.cacheCreation} models=${summarizeBuckets(stats.models)} agents=${summarizeBuckets(stats.agents)}`;
610
+ }
611
+ export {
612
+ aggregateDetailsByDay,
613
+ backupStatsKey,
614
+ classifyDetailKey,
615
+ describeDayStats,
616
+ detailGroupKey,
617
+ detectOverwriteRisks,
618
+ normalizeDetailRecord,
619
+ parseRebuildArgs,
620
+ planRebuild,
621
+ runUsageRebuildCommand,
622
+ scanDetails,
623
+ timestampFromDetailKey,
624
+ userIdFromDetailKey,
625
+ writeRebuildOps
626
+ };
package/chunk-4LCOCOR5.js DELETED
@@ -1,50 +0,0 @@
1
- // node_modules/date-fns/esm/_lib/requiredArgs/index.js
2
- function requiredArgs(required, args) {
3
- if (args.length < required) {
4
- throw new TypeError(required + " argument" + (required > 1 ? "s" : "") + " required, but only " + args.length + " present");
5
- }
6
- }
7
-
8
- // node_modules/@babel/runtime/helpers/esm/typeof.js
9
- function _typeof(o) {
10
- "@babel/helpers - typeof";
11
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
12
- return typeof o2;
13
- } : function(o2) {
14
- return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
15
- }, _typeof(o);
16
- }
17
-
18
- // node_modules/date-fns/esm/toDate/index.js
19
- function toDate(argument) {
20
- requiredArgs(1, arguments);
21
- var argStr = Object.prototype.toString.call(argument);
22
- if (argument instanceof Date || _typeof(argument) === "object" && argStr === "[object Date]") {
23
- return new Date(argument.getTime());
24
- } else if (typeof argument === "number" || argStr === "[object Number]") {
25
- return new Date(argument);
26
- } else {
27
- if ((typeof argument === "string" || argStr === "[object String]") && typeof console !== "undefined") {
28
- console.warn("Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#string-arguments");
29
- console.warn(new Error().stack);
30
- }
31
- return /* @__PURE__ */ new Date(NaN);
32
- }
33
- }
34
-
35
- // node_modules/date-fns/esm/_lib/addLeadingZeros/index.js
36
- function addLeadingZeros(number, targetLength) {
37
- var sign = number < 0 ? "-" : "";
38
- var output = Math.abs(number).toString();
39
- while (output.length < targetLength) {
40
- output = "0" + output;
41
- }
42
- return sign + output;
43
- }
44
-
45
- export {
46
- _typeof,
47
- requiredArgs,
48
- toDate,
49
- addLeadingZeros
50
- };