nolo-cli 0.1.29 → 0.1.31

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 (329) hide show
  1. package/agent-runtime/agentRecordConfig.ts +0 -2
  2. package/agent-runtime/hostAdapter.ts +0 -1
  3. package/agent-runtime/hostRuntimeCapabilities.ts +7 -0
  4. package/agent-runtime/hostRuntimeConfig.ts +86 -0
  5. package/agent-runtime/index.ts +13 -0
  6. package/agent-runtime/localToolPolicy.ts +13 -6
  7. package/agent-runtime/localWorkspaceTools.ts +333 -30
  8. package/agent-runtime/platformChatProvider.ts +4 -1
  9. package/agent-runtime/runtimeToolPolicy.ts +32 -47
  10. package/agent-runtime/shellCommandPolicy.ts +117 -0
  11. package/agent-runtime/toolGate.ts +38 -0
  12. package/agentCreateCustomCommands.ts +9 -4
  13. package/agentDialogsCommands.ts +4 -3
  14. package/agentDoctorCommands.ts +3 -3
  15. package/agentListCommands.ts +3 -3
  16. package/agentMachineCommands.ts +6 -6
  17. package/agentPullCommand.ts +4 -12
  18. package/agentRecordCommands.ts +5 -3
  19. package/agentRecordHelpers.ts +42 -23
  20. package/agentRunCommand.ts +2 -6
  21. package/agentRunParsing.ts +18 -5
  22. package/agentRuntimeLocal.ts +10 -0
  23. package/agentUnpublishCommands.ts +3 -2
  24. package/ai/agent/agentRunDialogLineage.ts +56 -0
  25. package/ai/agent/agentSlice.ts +45 -10
  26. package/ai/agent/avatarUtils.ts +1 -1
  27. package/ai/agent/buildSystemPrompt.ts +1 -2
  28. package/ai/agent/cliExecutor.ts +330 -19
  29. package/ai/agent/createAgentSchema.ts +22 -0
  30. package/ai/agent/hooks/fetchPublicAgents.ts +14 -39
  31. package/ai/agent/hooks/usePublicAgents.ts +90 -192
  32. package/ai/agent/publicAgentCatalog.ts +359 -0
  33. package/ai/agent/publicAgentIdentity.ts +76 -0
  34. package/ai/agent/server/fetchPublicAgents.ts +21 -46
  35. package/ai/agent/serverOrigin.ts +7 -0
  36. package/ai/agent/streamAgentChatTurn.ts +23 -21
  37. package/ai/agent/streamAgentChatTurnUtils.ts +292 -6
  38. package/ai/agent/types.ts +2 -0
  39. package/ai/agent/web/agentDisplayUtils.ts +171 -0
  40. package/ai/agent/web/useAgentModelAvatarComponent.ts +32 -0
  41. package/ai/ai.locale.ts +8 -0
  42. package/ai/chat/sendOpenAICompletionsRequest.native.ts +15 -0
  43. package/ai/chat/sendOpenAICompletionsRequest.ts +93 -1
  44. package/ai/chat/sendOpenAIResponseRequest.ts +86 -9
  45. package/ai/chat/updateTotalUsage.ts +7 -0
  46. package/ai/llm/deepinfra.ts +30 -15
  47. package/ai/llm/mistral.ts +3 -4
  48. package/ai/llm/providers.ts +2 -0
  49. package/ai/llm/types.ts +15 -0
  50. package/ai/memory/capture.ts +3 -3
  51. package/ai/memory/consolidate.ts +2 -2
  52. package/ai/memory/delete.ts +4 -3
  53. package/ai/memory/query.ts +3 -3
  54. package/ai/memory/remember.ts +2 -2
  55. package/ai/memory/store.ts +3 -3
  56. package/ai/memory/storeShared.ts +3 -2
  57. package/ai/policy/commercialMultiplier.ts +16 -0
  58. package/ai/token/billingAdminAuditEvent.ts +68 -0
  59. package/ai/token/billingAdminAuditEventWriter.ts +41 -0
  60. package/ai/token/billingAnomaly.ts +90 -0
  61. package/ai/token/billingAnomalyLifecycle.ts +54 -0
  62. package/ai/token/billingAnomalyLifecycleWriter.ts +44 -0
  63. package/ai/token/billingAnomalyWriter.ts +41 -0
  64. package/ai/token/calculatePrice.ts +3 -2
  65. package/ai/token/deepinfraReconciliation.ts +153 -0
  66. package/ai/token/deepinfraRequestIdQuery.ts +92 -0
  67. package/ai/token/externalToolCost.ts +54 -41
  68. package/ai/token/missingUsageEstimate.ts +12 -3
  69. package/ai/token/normalizeUsage.ts +45 -5
  70. package/ai/token/openaiReconciliation.ts +188 -0
  71. package/ai/token/providerBillableEvent.ts +84 -0
  72. package/ai/token/providerBillableEventWriter.ts +36 -0
  73. package/ai/token/providerBillingAnomalyDrilldown.ts +308 -0
  74. package/ai/token/providerBillingDrilldown.ts +361 -0
  75. package/ai/token/providerBillingHealthReport.ts +366 -0
  76. package/ai/token/providerCall.ts +144 -0
  77. package/ai/token/providerCallSweeper.ts +168 -0
  78. package/ai/token/providerCallWriter.ts +33 -0
  79. package/ai/token/providerCredential.ts +89 -0
  80. package/ai/token/providerCredentialAnomaly.ts +154 -0
  81. package/ai/token/providerCredentialLifecycle.ts +59 -0
  82. package/ai/token/providerCredentialLifecycleWriter.ts +44 -0
  83. package/ai/token/providerCredentialRegistry.ts +83 -0
  84. package/ai/token/providerCredentialRegistryCommand.ts +97 -0
  85. package/ai/token/providerCredentialRegistryList.ts +124 -0
  86. package/ai/token/providerCredentialRegistryResolver.ts +150 -0
  87. package/ai/token/providerCredentialRegistryWriter.ts +41 -0
  88. package/ai/token/providerCredentialRotationCommand.ts +102 -0
  89. package/ai/token/providerCredentialRuntime.ts +56 -0
  90. package/ai/token/providerDispatchIntent.ts +67 -0
  91. package/ai/token/providerDispatchIntentWriter.ts +36 -0
  92. package/ai/token/providerGateway.ts +260 -0
  93. package/ai/token/providerReconciliation.ts +148 -0
  94. package/ai/token/providerReconciliationLocal.ts +97 -0
  95. package/ai/token/providerReconciliationRunner.ts +165 -0
  96. package/ai/token/providerReconciliationWriter.ts +41 -0
  97. package/ai/token/ratingResult.ts +202 -0
  98. package/ai/token/ratingResultWriter.ts +33 -0
  99. package/ai/token/serverDialogProjection.ts +5 -3
  100. package/ai/token/serverTokenWriter.ts +11 -3
  101. package/ai/token/types.ts +10 -0
  102. package/ai/tools/agent/callAgentTool.ts +3 -4
  103. package/ai/tools/agent/presets/appBuilderPreset.ts +5 -7
  104. package/ai/tools/agent/runStreamingAgentTool.ts +1 -2
  105. package/ai/tools/agent/streamParallelAgentsTool.ts +2 -3
  106. package/ai/tools/readXPostTool.ts +1 -5
  107. package/app/admin/adminPages.ts +9 -0
  108. package/app/i18n/i18n.config.ts +5 -0
  109. package/app/i18n/translations/pricing.locale.ts +397 -0
  110. package/app/utils/desktopAgentRuntimeStatusClient.ts +5 -4
  111. package/app/utils/desktopAgentRuntimeTurnClient.ts +4 -1
  112. package/app/utils/imageUtils.ts +64 -34
  113. package/auth/adminPermissions.ts +18 -0
  114. package/auth/authSlice.ts +26 -12
  115. package/auth/hooks/useFetchUsers.ts +3 -0
  116. package/auth/routes.ts +46 -0
  117. package/auth/server/accessActivity.ts +4 -3
  118. package/auth/server/adminPermissions.ts +43 -0
  119. package/auth/server/adminUsageReport.ts +375 -0
  120. package/auth/server/billingAnomalies.ts +235 -0
  121. package/auth/server/billingUsageReport.ts +41 -2
  122. package/auth/server/creatorEarningCreditConversion.ts +10 -2
  123. package/auth/server/deduct.ts +14 -7
  124. package/auth/server/delete.ts +10 -2
  125. package/auth/server/disable.ts +4 -3
  126. package/auth/server/emailAutomation.ts +7 -5
  127. package/auth/server/emailDbConfig.ts +4 -2
  128. package/auth/server/emailDelivery.ts +24 -20
  129. package/auth/server/emailDeliveryGuards.ts +10 -7
  130. package/auth/server/emailPreferences.ts +6 -4
  131. package/auth/server/emailReport.ts +6 -4
  132. package/auth/server/emailRuntimeConfig.ts +3 -3
  133. package/auth/server/emailScenarioNotifications.ts +9 -8
  134. package/auth/server/enable.ts +4 -3
  135. package/auth/server/getRechargeHistory.ts +3 -2
  136. package/auth/server/getUser.ts +3 -2
  137. package/auth/server/gptProAccess.ts +44 -0
  138. package/auth/server/inviteReward.ts +10 -7
  139. package/auth/server/listusers.ts +6 -4
  140. package/auth/server/login.ts +2 -2
  141. package/auth/server/productEntitlements.ts +7 -4
  142. package/auth/server/productPurchase.ts +10 -2
  143. package/auth/server/providerBillingDrilldown.ts +47 -0
  144. package/auth/server/providerBillingHealth.ts +71 -0
  145. package/auth/server/providerCredentials.ts +136 -0
  146. package/auth/server/recharge.ts +14 -8
  147. package/auth/server/revokeSessions.ts +4 -3
  148. package/auth/server/route.ts +77 -0
  149. package/auth/server/sendEmail.ts +5 -4
  150. package/auth/server/signup.ts +10 -3
  151. package/auth/server/token.ts +53 -55
  152. package/auth/server/tokenUsageBilling.ts +18 -7
  153. package/auth/server/usageManagementAccess.ts +43 -0
  154. package/auth/server/usageReport.ts +59 -0
  155. package/auth/types.ts +12 -0
  156. package/auth/utils.ts +24 -22
  157. package/authCommands.ts +36 -2
  158. package/buildPublish.ts +3 -1
  159. package/buildPublishArtifactAssembly.ts +62 -1
  160. package/buildPublishImportAnalysis.ts +21 -16
  161. package/chat/dialog/dialogLaunchScope.ts +32 -0
  162. package/chat/dialog/objectAssistantRegistry.ts +2 -2
  163. package/chat/dialog/useCreateDialog.ts +1 -1
  164. package/chat/hooks/useChatInput.ts +41 -10
  165. package/chat/messages/messageSlice.ts +5 -1
  166. package/chat/messages/pendingAttachmentParts.ts +28 -2
  167. package/chat/messages/sendFirstMessage.ts +76 -79
  168. package/chat/messages/types.ts +9 -0
  169. package/chat/messages/web/streamingMarkdownModel.ts +41 -0
  170. package/chat/messages/web/useStreamingReveal.ts +91 -0
  171. package/chat/web/messageInputAgentUi.ts +94 -6
  172. package/cliEnvHelpers.ts +68 -13
  173. package/cliRuntimeDoctorReport.ts +193 -0
  174. package/client/agentConfigResolver.test.ts +0 -2
  175. package/client/agentRun.test.ts +171 -10
  176. package/client/agentRun.ts +44 -637
  177. package/client/agentRunInput.ts +10 -0
  178. package/client/agentRunLocalExecutor.ts +179 -0
  179. package/client/agentRunServerTransport.ts +394 -0
  180. package/client/agentRunTaskRunRecorder.ts +176 -0
  181. package/client/localRuntimeAdapter.test.ts +236 -9
  182. package/client/localRuntimeAdapter.ts +221 -23
  183. package/client/localToolPolicy.test.ts +28 -4
  184. package/connector-experimental/daemonLauncher.ts +38 -4
  185. package/connectorRunArtifact.ts +34 -10
  186. package/connectorWebSocketTarget.ts +40 -15
  187. package/core/builtinAgents.ts +155 -11
  188. package/create/space/contentLabels.ts +1 -1
  189. package/create/space/contentTypeMeta.ts +3 -2
  190. package/create/space/sidebarVisibleTypes.ts +27 -0
  191. package/create/space/space.locale.ts +76 -4
  192. package/database/actions/agentReadResolution.ts +2 -8
  193. package/database/actions/read.ts +11 -9
  194. package/database/actions/readAndWait.ts +10 -5
  195. package/database/server/agentDelegation.ts +3 -2
  196. package/database/server/authorityStoreConformance.ts +209 -0
  197. package/database/server/authorityStoreTypes.ts +31 -0
  198. package/database/server/coreDataProxy.ts +1 -1
  199. package/database/server/dataHandlers.ts +13 -5
  200. package/database/server/db.ts +15 -34
  201. package/database/server/delete.ts +88 -71
  202. package/database/server/emailRepository.ts +11 -9
  203. package/database/server/fileService.ts +2 -1
  204. package/database/server/legacyServerDb.ts +58 -0
  205. package/database/server/levelAuthorityStore.ts +75 -0
  206. package/database/server/memoryAuthorityStore.ts +133 -0
  207. package/database/server/patch.ts +13 -12
  208. package/database/server/query.ts +3 -2
  209. package/database/server/read.ts +33 -30
  210. package/database/server/resourceAccess.ts +7 -5
  211. package/database/server/serverStoreFactory.ts +124 -0
  212. package/database/server/spaceMemberAuthority.ts +3 -2
  213. package/database/server/storeBatchCompat.ts +37 -0
  214. package/database/server/testAuthorityStore.ts +76 -0
  215. package/database/server/write.ts +29 -27
  216. package/dialogReadCommands.ts +2 -1
  217. package/dialogStatusCommands.ts +2 -1
  218. package/integrations/anthropic/anthropicModels.ts +12 -12
  219. package/integrations/deepseek/models.ts +67 -67
  220. package/integrations/google/models.ts +111 -53
  221. package/integrations/openai/models.ts +22 -22
  222. package/integrations/xai/models.ts +1 -1
  223. package/localRuntimeDb.ts +39 -2
  224. package/machineCommandPrompts.ts +2 -0
  225. package/machineCommands.ts +193 -62
  226. package/machineStatusCommands.ts +4 -12
  227. package/machineWsRunDispatch.ts +80 -15
  228. package/machineWsSession.ts +46 -2
  229. package/noloReadBridgePrompt.ts +16 -0
  230. package/package.json +114 -21
  231. package/pageCreateCommands.ts +2 -2
  232. package/pageDeleteCommands.ts +3 -3
  233. package/pageReadCommands.ts +3 -3
  234. package/pageUpdateCommands.ts +3 -3
  235. package/render/layout/mainLayoutViewMode.ts +25 -0
  236. package/render/page/server/createPage.ts +3 -1
  237. package/render/page/server/handleCreatePage.ts +2 -11
  238. package/runtimeDoctorCommands.ts +18 -69
  239. package/server/api/methods.ts +34 -12
  240. package/server/api/tableHandlers.ts +6 -3
  241. package/server/authenticateToken.ts +47 -2
  242. package/server/billingLedgerRoutes.ts +15 -0
  243. package/server/buildManifest.ts +54 -0
  244. package/server/coreReadiness.ts +34 -25
  245. package/server/coreRuntime.ts +15 -10
  246. package/server/handlers/activityStatsHandler.ts +5 -2
  247. package/server/handlers/agentEmailRegistrationE2EHandler.ts +25 -23
  248. package/server/handlers/agentRun/agentLookup.ts +1 -7
  249. package/server/handlers/agentRun/autonomousRuntime.ts +11 -10
  250. package/server/handlers/agentRun/builtinAgents.ts +12 -88
  251. package/server/handlers/agentRun/continueDialogContext.ts +15 -3
  252. package/server/handlers/agentRun/{inheritedDialogPrompt.ts → conversationReference.ts} +3 -3
  253. package/server/handlers/agentRun/dialogLookup.ts +4 -3
  254. package/server/handlers/agentRun/index.ts +864 -404
  255. package/server/handlers/agentRun/localRuntimeBootstrap.ts +17 -1
  256. package/server/handlers/agentRun/loop.ts +920 -508
  257. package/server/handlers/agentRun/machineConnector.ts +56 -8
  258. package/server/handlers/agentRun/machineRunAudit.ts +3 -2
  259. package/server/handlers/agentRun/modelUsageToolHandlers.ts +13 -10
  260. package/server/handlers/agentRun/requestContext.ts +12 -8
  261. package/server/handlers/agentRun/runtimeExecutionContext.ts +15 -3
  262. package/server/handlers/agentRun/runtimePreparation.ts +26 -24
  263. package/server/handlers/agentRun/runtimeRouting.ts +25 -40
  264. package/server/handlers/agentRun/runtimeSystemMessages.ts +65 -0
  265. package/server/handlers/agentRun/saveDialog.ts +97 -87
  266. package/server/handlers/agentRun/taskRunToolHandler.ts +9 -7
  267. package/server/handlers/agentRun/toolExecutor.ts +42 -78
  268. package/server/handlers/agentRun/types.ts +2 -1
  269. package/server/handlers/appDeployStatusStore.ts +17 -10
  270. package/server/handlers/appDomainHandler.ts +21 -15
  271. package/server/handlers/appLegacyInfraCleanup.ts +5 -2
  272. package/server/handlers/appSandboxHandler.ts +29 -8
  273. package/server/handlers/appSpaceAccess.ts +15 -8
  274. package/server/handlers/chatHandler.ts +22 -2
  275. package/server/handlers/chatUpstreamRetry.ts +225 -2
  276. package/server/handlers/connector/connectorConnectionRegistry.ts +55 -7
  277. package/server/handlers/connector/connectorWebSocket.ts +14 -10
  278. package/server/handlers/desktopAgentRuntimeAdapter.ts +4 -4
  279. package/server/handlers/desktopAgentRuntimeHostCapabilities.ts +25 -0
  280. package/server/handlers/desktopAgentRuntimeReadiness.ts +62 -0
  281. package/server/handlers/desktopAgentRuntimeStatusHandler.ts +38 -30
  282. package/server/handlers/desktopAgentRuntimeTurnHandler.ts +7 -3
  283. package/server/handlers/desktopAgentRuntimeTurnService.ts +39 -45
  284. package/server/handlers/desktopLlamaRuntimeHandler.ts +85 -51
  285. package/server/handlers/desktopUpdaterHandler.ts +132 -24
  286. package/server/handlers/favoriteHandlers.ts +8 -2
  287. package/server/handlers/getDialogBillingHandler.ts +4 -3
  288. package/server/handlers/getTransactionsHandler.ts +5 -2
  289. package/server/handlers/machines/machineBinding.ts +1 -0
  290. package/server/handlers/machines/machineHandlers.ts +0 -14
  291. package/server/handlers/machines/machineInstallAssets.ts +4 -2
  292. package/server/handlers/notificationEmitter.ts +5 -3
  293. package/server/handlers/notificationsHandler.ts +5 -2
  294. package/server/handlers/providerCallsRecentHandler.ts +234 -0
  295. package/server/handlers/providerReconciliationRunHandler.ts +180 -0
  296. package/server/handlers/providerRequestIdsHandler.ts +105 -0
  297. package/server/handlers/tableAccess.ts +6 -2
  298. package/server/handlers/tableToolHandlers.ts +28 -14
  299. package/server/handlers/userSecretsHandler.ts +17 -6
  300. package/server/handlers/versionHandler.ts +9 -4
  301. package/server/handlers/versionStore.ts +18 -10
  302. package/server/html/ssrPreload.ts +5 -3
  303. package/server/payments/crypto/cryptoUsdcBasePaymentProvider.ts +11 -8
  304. package/server/payments/crypto/cryptoUsdcBaseScanner.ts +12 -7
  305. package/server/payments/crypto/cryptoUsdtTronPaymentProvider.ts +11 -8
  306. package/server/payments/crypto/cryptoUsdtTronScanner.ts +9 -7
  307. package/server/payments/waffo/waffoPaymentProvider.ts +12 -9
  308. package/server/runtimeRole.ts +15 -0
  309. package/server/scheduler/scheduledTaskRuntime.ts +4 -2
  310. package/server/scheduler/schedulerService.ts +2 -2
  311. package/server/taskRunBridgeRoutes.ts +8 -5
  312. package/share/server/fetchCommunityShares.ts +1 -1
  313. package/share/server/helpers.ts +19 -17
  314. package/share/server/importShare.ts +9 -13
  315. package/share/server/listCommunityShares.ts +4 -4
  316. package/share/server/purchaseDoc.ts +8 -16
  317. package/share/server/readCommunityShareCover.ts +3 -2
  318. package/share/server/readSharedTable.ts +14 -13
  319. package/share/server/tableReplication.ts +42 -39
  320. package/spaceAttachCommands.ts +135 -0
  321. package/spaceCategoryCommands.ts +6 -6
  322. package/spaceCommands.ts +3 -3
  323. package/spaceDeleteCommands.ts +2 -2
  324. package/spaceInternalCommandEntries.ts +2 -0
  325. package/spaceReadCommands.ts +3 -3
  326. package/tableMetaCommands.ts +2 -2
  327. package/taskRunCommand.ts +11 -0
  328. package/ai/agent/runtimeServerBase.ts +0 -37
  329. package/server/handlers/desktopAgentRuntimeHostFacts.ts +0 -40
@@ -0,0 +1,235 @@
1
+ import {
2
+ createBillingAdminAuditEvent,
3
+ type BillingAdminAuditAction,
4
+ } from "../../ai/token/billingAdminAuditEvent";
5
+ import { writeBillingAdminAuditEvent } from "../../ai/token/billingAdminAuditEventWriter";
6
+ import type { BillingAnomalyStatus } from "../../ai/token/billingAnomaly";
7
+ import { createBillingAnomalyLifecycleEvent } from "../../ai/token/billingAnomalyLifecycle";
8
+ import { writeBillingAnomalyLifecycleEvent } from "../../ai/token/billingAnomalyLifecycleWriter";
9
+ import { buildProviderBillingAnomalyDrilldown } from "../../ai/token/providerBillingAnomalyDrilldown";
10
+ import { getServerAuthorityStore } from "../../database/server/db";
11
+ import { ulid } from "ulid";
12
+ import {
13
+ createErrorResponse,
14
+ createSuccessResponse,
15
+ handleOptionsRequest,
16
+ } from "./shared";
17
+ import { canManageUsageReportAccess } from "./usageManagementAccess";
18
+
19
+ const serverDb = getServerAuthorityStore();
20
+
21
+ const parseStatus = (value: unknown): BillingAnomalyStatus | undefined => {
22
+ if (
23
+ value === "open" ||
24
+ value === "acknowledged" ||
25
+ value === "resolved" ||
26
+ value === "ignored"
27
+ ) {
28
+ return value;
29
+ }
30
+ return undefined;
31
+ };
32
+
33
+ const parseAuditAction = (value: unknown): BillingAdminAuditAction | undefined => {
34
+ if (
35
+ value === "dry_run_viewed" ||
36
+ value === "plan_marked_reviewed" ||
37
+ value === "plan_abandoned"
38
+ ) {
39
+ return value;
40
+ }
41
+ return undefined;
42
+ };
43
+
44
+ const parseLimit = (value: string | null) => {
45
+ const parsed = Number(value);
46
+ if (!Number.isFinite(parsed)) return 50;
47
+ return Math.min(Math.max(Math.floor(parsed), 1), 200);
48
+ };
49
+
50
+ type BillingAnomalyLifecycleDeps = {
51
+ store?: Parameters<typeof writeBillingAnomalyLifecycleEvent>[0]["store"];
52
+ canManage?: (userId?: string | null) => Promise<boolean>;
53
+ now?: () => string;
54
+ createEventId?: () => string;
55
+ };
56
+
57
+ export async function handleUpdateBillingAnomalyLifecycle(
58
+ req: Request,
59
+ deps: BillingAnomalyLifecycleDeps = {}
60
+ ) {
61
+ if (req.method === "OPTIONS") {
62
+ return handleOptionsRequest();
63
+ }
64
+
65
+ const { userId: actionUserId } = req.user;
66
+ const canManage = deps.canManage ?? canManageUsageReportAccess;
67
+ if (!(await canManage(actionUserId))) {
68
+ return createErrorResponse("Unauthorized: Usage management access required", 403);
69
+ }
70
+
71
+ let body: Record<string, unknown>;
72
+ try {
73
+ body = (await req.json()) as Record<string, unknown>;
74
+ } catch {
75
+ return createErrorResponse("Invalid JSON body", 400);
76
+ }
77
+
78
+ const anomalyId =
79
+ typeof body.anomalyId === "string" ? body.anomalyId.trim() : "";
80
+ if (!anomalyId) return createErrorResponse("anomalyId is required", 400);
81
+
82
+ const status = parseStatus(body.status);
83
+ if (!status) {
84
+ return createErrorResponse(
85
+ "status must be open, acknowledged, resolved, or ignored",
86
+ 400
87
+ );
88
+ }
89
+
90
+ const now = deps.now?.() ?? new Date().toISOString();
91
+ const event = createBillingAnomalyLifecycleEvent({
92
+ anomalyId,
93
+ eventId:
94
+ typeof body.eventId === "string" && body.eventId.trim()
95
+ ? body.eventId.trim()
96
+ : deps.createEventId?.() ?? `evt_${ulid()}`,
97
+ status,
98
+ createdAt: now,
99
+ actorId: actionUserId,
100
+ reason: typeof body.reason === "string" ? body.reason : undefined,
101
+ });
102
+
103
+ try {
104
+ const result = await writeBillingAnomalyLifecycleEvent({
105
+ store: deps.store ?? serverDb,
106
+ event,
107
+ });
108
+ return createSuccessResponse({
109
+ success: true,
110
+ key: result.key,
111
+ event: {
112
+ anomalyId: event.anomalyId,
113
+ eventId: event.eventId,
114
+ status: event.status,
115
+ createdAt: event.createdAt,
116
+ actorId: event.actorId,
117
+ },
118
+ });
119
+ } catch {
120
+ return createErrorResponse("Internal server error");
121
+ }
122
+ }
123
+
124
+ type BillingAnomalyDrilldownDeps = {
125
+ store?: Parameters<typeof buildProviderBillingAnomalyDrilldown>[0]["store"];
126
+ canManage?: (userId?: string | null) => Promise<boolean>;
127
+ };
128
+
129
+ export async function handleGetBillingAnomalyDrilldown(
130
+ req: Request,
131
+ deps: BillingAnomalyDrilldownDeps = {}
132
+ ) {
133
+ if (req.method === "OPTIONS") {
134
+ return handleOptionsRequest();
135
+ }
136
+
137
+ const { userId: actionUserId } = req.user;
138
+ const canManage = deps.canManage ?? canManageUsageReportAccess;
139
+ if (!(await canManage(actionUserId))) {
140
+ return createErrorResponse("Unauthorized: Usage management access required", 403);
141
+ }
142
+
143
+ try {
144
+ const url = new URL(req.url);
145
+ const anomalyId = url.searchParams.get("anomalyId")?.trim();
146
+ if (!anomalyId) {
147
+ return createErrorResponse("Missing anomalyId", 400);
148
+ }
149
+ const drilldown = await buildProviderBillingAnomalyDrilldown({
150
+ store: deps.store ?? serverDb,
151
+ anomalyId,
152
+ limit: parseLimit(url.searchParams.get("limit")),
153
+ });
154
+ return createSuccessResponse({ success: true, drilldown });
155
+ } catch (error) {
156
+ if (
157
+ error instanceof Error &&
158
+ error.message.startsWith("billing anomaly not found:")
159
+ ) {
160
+ return createErrorResponse("Billing anomaly not found", 404);
161
+ }
162
+ return createErrorResponse("Internal server error");
163
+ }
164
+ }
165
+
166
+ type BillingAdminAuditDeps = {
167
+ store?: Parameters<typeof writeBillingAdminAuditEvent>[0]["store"];
168
+ canManage?: (userId?: string | null) => Promise<boolean>;
169
+ now?: () => string;
170
+ createEventId?: () => string;
171
+ };
172
+
173
+ export async function handleCreateBillingAdminAuditEvent(
174
+ req: Request,
175
+ deps: BillingAdminAuditDeps = {}
176
+ ) {
177
+ if (req.method === "OPTIONS") {
178
+ return handleOptionsRequest();
179
+ }
180
+
181
+ const { userId: actionUserId } = req.user;
182
+ const canManage = deps.canManage ?? canManageUsageReportAccess;
183
+ if (!(await canManage(actionUserId))) {
184
+ return createErrorResponse("Unauthorized: Usage management access required", 403);
185
+ }
186
+
187
+ let body: Record<string, unknown>;
188
+ try {
189
+ body = (await req.json()) as Record<string, unknown>;
190
+ } catch {
191
+ return createErrorResponse("Invalid JSON body", 400);
192
+ }
193
+ const action = parseAuditAction(body.action);
194
+ if (!action) {
195
+ return createErrorResponse(
196
+ "action must be dry_run_viewed, plan_marked_reviewed, or plan_abandoned",
197
+ 400
198
+ );
199
+ }
200
+ const event = createBillingAdminAuditEvent({
201
+ eventId:
202
+ typeof body.eventId === "string" && body.eventId.trim()
203
+ ? body.eventId.trim()
204
+ : deps.createEventId?.() ?? `evt_${ulid()}`,
205
+ actorId: actionUserId,
206
+ action,
207
+ anomalyId: typeof body.anomalyId === "string" ? body.anomalyId : "",
208
+ planId: typeof body.planId === "string" ? body.planId : "",
209
+ inputSetHash: typeof body.inputSetHash === "string" ? body.inputSetHash : "",
210
+ createdAt: deps.now?.() ?? new Date().toISOString(),
211
+ reason: typeof body.reason === "string" ? body.reason : undefined,
212
+ });
213
+
214
+ try {
215
+ const result = await writeBillingAdminAuditEvent({
216
+ store: deps.store ?? serverDb,
217
+ event,
218
+ });
219
+ return createSuccessResponse({
220
+ success: true,
221
+ key: result.key,
222
+ event: {
223
+ eventId: event.eventId,
224
+ actorId: event.actorId,
225
+ action: event.action,
226
+ anomalyId: event.anomalyId,
227
+ planId: event.planId,
228
+ inputSetHash: event.inputSetHash,
229
+ createdAt: event.createdAt,
230
+ },
231
+ });
232
+ } catch {
233
+ return createErrorResponse("Internal server error");
234
+ }
235
+ }
@@ -19,20 +19,31 @@ export type BillingUsageReport = {
19
19
  titleCostRatio: number;
20
20
  inputTokens: number;
21
21
  outputTokens: number;
22
+ cacheCreationInputTokens: number;
23
+ cacheReadInputTokens: number;
22
24
  };
23
25
  byCybot: BillingUsageGroup[];
26
+ byUser: BillingUsageGroup[];
27
+ byDialog: BillingUsageGroup[];
24
28
  byModel: BillingUsageGroup[];
25
29
  byProvider: BillingUsageGroup[];
30
+ byDay: BillingUsageGroup[];
26
31
  };
27
32
 
28
33
  export type BillingUsageGroup = {
29
34
  cybotId?: string;
35
+ userId?: string;
36
+ username?: string;
37
+ dialogId?: string;
30
38
  model?: string;
31
39
  provider?: string;
40
+ dateKey?: string;
32
41
  count: number;
33
42
  cost: number;
34
43
  inputTokens: number;
35
44
  outputTokens: number;
45
+ cacheCreationInputTokens: number;
46
+ cacheReadInputTokens: number;
36
47
  costRatio: number;
37
48
  };
38
49
 
@@ -40,11 +51,15 @@ type TokenRecord = {
40
51
  type?: string;
41
52
  userId?: string;
42
53
  cybotId?: string;
54
+ dialogId?: string;
43
55
  provider?: string;
44
56
  model?: string;
45
57
  input_tokens?: number;
46
58
  output_tokens?: number;
59
+ cache_creation_input_tokens?: number;
60
+ cache_read_input_tokens?: number;
47
61
  cost?: number;
62
+ dateKey?: string;
48
63
  timestamp?: number;
49
64
  createdAt?: string;
50
65
  };
@@ -85,6 +100,8 @@ const createAccumulator = () => ({
85
100
  cost: 0,
86
101
  inputTokens: 0,
87
102
  outputTokens: 0,
103
+ cacheCreationInputTokens: 0,
104
+ cacheReadInputTokens: 0,
88
105
  });
89
106
 
90
107
  type Accumulator = ReturnType<typeof createAccumulator>;
@@ -94,6 +111,8 @@ const addToAccumulator = (acc: Accumulator, record: TokenRecord) => {
94
111
  acc.cost += toFiniteNumber(record.cost);
95
112
  acc.inputTokens += toFiniteNumber(record.input_tokens);
96
113
  acc.outputTokens += toFiniteNumber(record.output_tokens);
114
+ acc.cacheCreationInputTokens += toFiniteNumber(record.cache_creation_input_tokens);
115
+ acc.cacheReadInputTokens += toFiniteNumber(record.cache_read_input_tokens);
97
116
  };
98
117
 
99
118
  const addGroupedRecord = (
@@ -107,7 +126,7 @@ const addGroupedRecord = (
107
126
  };
108
127
 
109
128
  const formatGroup = (
110
- keyName: "cybotId" | "model" | "provider",
129
+ keyName: "cybotId" | "userId" | "dialogId" | "model" | "provider" | "dateKey",
111
130
  totalCost: number,
112
131
  [key, acc]: [string, Accumulator]
113
132
  ): BillingUsageGroup => ({
@@ -116,11 +135,13 @@ const formatGroup = (
116
135
  cost: roundMetric(acc.cost),
117
136
  inputTokens: acc.inputTokens,
118
137
  outputTokens: acc.outputTokens,
138
+ cacheCreationInputTokens: acc.cacheCreationInputTokens,
139
+ cacheReadInputTokens: acc.cacheReadInputTokens,
119
140
  costRatio: totalCost > 0 ? roundMetric(acc.cost / totalCost) : 0,
120
141
  });
121
142
 
122
143
  const sortedGroups = (
123
- keyName: "cybotId" | "model" | "provider",
144
+ keyName: "cybotId" | "userId" | "dialogId" | "model" | "provider" | "dateKey",
124
145
  totalCost: number,
125
146
  groups: Map<string, Accumulator>
126
147
  ) =>
@@ -136,8 +157,11 @@ export async function buildBillingUsageReport(args: {
136
157
  }): Promise<BillingUsageReport> {
137
158
  const totals = createAccumulator();
138
159
  const byCybot = new Map<string, Accumulator>();
160
+ const byUser = new Map<string, Accumulator>();
161
+ const byDialog = new Map<string, Accumulator>();
139
162
  const byModel = new Map<string, Accumulator>();
140
163
  const byProvider = new Map<string, Accumulator>();
164
+ const byDay = new Map<string, Accumulator>();
141
165
  let recordsScanned = 0;
142
166
  let titleCost = 0;
143
167
  let titleCount = 0;
@@ -157,11 +181,19 @@ export async function buildBillingUsageReport(args: {
157
181
  addToAccumulator(totals, value);
158
182
 
159
183
  const cybotId = value.cybotId || "unknown";
184
+ const userId = value.userId || "unknown";
185
+ const dialogId = value.dialogId || "unknown";
160
186
  const model = value.model || "unknown";
161
187
  const provider = value.provider || "unknown";
188
+ const dateKey =
189
+ value.dateKey ||
190
+ (timestamp == null ? "unknown" : new Date(timestamp).toISOString().slice(0, 10));
162
191
  addGroupedRecord(byCybot, cybotId, value);
192
+ addGroupedRecord(byUser, userId, value);
193
+ addGroupedRecord(byDialog, dialogId, value);
163
194
  addGroupedRecord(byModel, model, value);
164
195
  addGroupedRecord(byProvider, provider, value);
196
+ addGroupedRecord(byDay, dateKey, value);
165
197
 
166
198
  if (cybotId === TITLE_CYBOT_ID) {
167
199
  titleCount += 1;
@@ -184,9 +216,16 @@ export async function buildBillingUsageReport(args: {
184
216
  titleCostRatio: totalCost > 0 ? roundMetric(roundedTitleCost / totalCost) : 0,
185
217
  inputTokens: totals.inputTokens,
186
218
  outputTokens: totals.outputTokens,
219
+ cacheCreationInputTokens: totals.cacheCreationInputTokens,
220
+ cacheReadInputTokens: totals.cacheReadInputTokens,
187
221
  },
188
222
  byCybot: sortedGroups("cybotId", totalCost, byCybot),
223
+ byUser: sortedGroups("userId", totalCost, byUser),
224
+ byDialog: sortedGroups("dialogId", totalCost, byDialog),
189
225
  byModel: sortedGroups("model", totalCost, byModel),
190
226
  byProvider: sortedGroups("provider", totalCost, byProvider),
227
+ byDay: sortedGroups("dateKey", totalCost, byDay).sort((a, b) =>
228
+ String(b.dateKey ?? "").localeCompare(String(a.dateKey ?? ""))
229
+ ),
191
230
  };
192
231
  }
@@ -1,7 +1,8 @@
1
1
  import { createHash } from "node:crypto";
2
2
 
3
3
  import { createTransactionKey, DB_PREFIX } from "../../database/keys";
4
- import serverDb from "../../database/server/db";
4
+ import { getServerAuthorityStore } from "../../database/server/db";
5
+ import { writeStoreOps } from "../../database/server/storeBatchCompat";
5
6
  import { ulid } from "ulid";
6
7
  import { balanceLockManager } from "./locks";
7
8
  import { withRetry } from "./utils";
@@ -31,6 +32,13 @@ export type CreatorEarningCreditConversionStore = {
31
32
  batch: (ops: StoreOperation[]) => Promise<void>;
32
33
  };
33
34
 
35
+ const createCreatorEarningCreditConversionStore = (
36
+ authorityStore = getServerAuthorityStore()
37
+ ): CreatorEarningCreditConversionStore => ({
38
+ get: (key) => authorityStore.get(key),
39
+ batch: (ops) => writeStoreOps(authorityStore, ops),
40
+ });
41
+
34
42
  type ConversionRecord = {
35
43
  kind: "creator_earning_credit_conversion";
36
44
  clusterId: string;
@@ -148,7 +156,7 @@ const defaultTxId = (clusterId: string, entryId: string) =>
148
156
  `creator-earning-credit-${clusterId}-${safeKeyPart(entryId)}`;
149
157
 
150
158
  export async function convertCreatorEarningToCredits({
151
- store = serverDb,
159
+ store = createCreatorEarningCreditConversionStore(getServerAuthorityStore()),
152
160
  runtime = getBillingLedgerRuntime(),
153
161
  creatorUserId,
154
162
  entryId,
@@ -1,6 +1,7 @@
1
1
  // auth/server/deduct.ts
2
2
  import { ulid } from "ulid";
3
- import serverDb from "../../database/server/db";
3
+ import { getServerAuthorityStore } from "../../database/server/db";
4
+ import { writeStoreOps } from "../../database/server/storeBatchCompat";
4
5
  import { createTransactionKey } from "../../database/keys";
5
6
  import { logger } from "../server/shared";
6
7
  import { balanceLockManager } from "./locks";
@@ -29,6 +30,12 @@ export async function deductUserBalance(
29
30
  txId: string = ulid()
30
31
  ): Promise<DeductResult> {
31
32
  const lock = balanceLockManager.getLock(userId);
33
+ const store = getServerAuthorityStore();
34
+ const ledgerStore = {
35
+ get: (key: string) => store.get(key),
36
+ batch: (ops: Array<{ type: "put"; key: string; value: unknown }>) =>
37
+ writeStoreOps(store, ops),
38
+ };
32
39
 
33
40
  return await lock.runExclusive(async () => {
34
41
  try {
@@ -54,7 +61,7 @@ export async function deductUserBalance(
54
61
  let existingTx = null;
55
62
 
56
63
  try {
57
- existingTx = await serverDb.get(txIndexKey);
64
+ existingTx = await store.get(txIndexKey);
58
65
  } catch (err) {
59
66
  if (!(err instanceof Error && "notFound" in err)) {
60
67
  throw err;
@@ -78,7 +85,7 @@ export async function deductUserBalance(
78
85
  let userData = null;
79
86
 
80
87
  try {
81
- userData = await serverDb.get(userKey);
88
+ userData = await store.get(userKey);
82
89
  } catch (err) {
83
90
  if (err instanceof Error && "notFound" in err) {
84
91
  logger.warn({
@@ -100,7 +107,7 @@ export async function deductUserBalance(
100
107
 
101
108
  const currentBalance = userData.balance;
102
109
  const ledgerAppend = await prepareLedgerTransactionAppend({
103
- store: serverDb,
110
+ store: ledgerStore,
104
111
  type: "usage_charge",
105
112
  reason,
106
113
  idempotencyKey: txId,
@@ -167,7 +174,7 @@ export async function deductUserBalance(
167
174
 
168
175
  await withRetry(
169
176
  async () => {
170
- await serverDb.batch([
177
+ await writeStoreOps(store, [
171
178
  ...ledgerAppend.operations,
172
179
  {
173
180
  type: "put",
@@ -229,7 +236,7 @@ export async function deductUserBalance(
229
236
  let txRecord = null;
230
237
 
231
238
  try {
232
- txRecord = await serverDb.get(txKey);
239
+ txRecord = await store.get(txKey);
233
240
  } catch (err) {
234
241
  if (!(err instanceof Error && "notFound" in err)) {
235
242
  throw err;
@@ -237,7 +244,7 @@ export async function deductUserBalance(
237
244
  }
238
245
 
239
246
  if (txRecord) {
240
- await serverDb.put(txKey, {
247
+ await store.put(txKey, {
241
248
  ...txRecord,
242
249
  status: "failed",
243
250
  });
@@ -1,6 +1,7 @@
1
1
  // 文件: auth/deleteUser.ts
2
2
 
3
- import serverDb from "../../database/server/db";
3
+ import { getServerAuthorityStore } from "../../database/server/db";
4
+ import { createStoreBatch } from "../../database/server/storeBatchCompat";
4
5
  import { authRoutes } from "../routes";
5
6
  import { NOLO_CLUSTER_SERVERS } from "../../database/config";
6
7
 
@@ -833,6 +834,13 @@ async function deleteUserRelatedData(
833
834
  }
834
835
  }
835
836
 
837
+ const createDeleteUserDb = (store = getServerAuthorityStore()) => ({
838
+ get: (key: string) => store.get(key),
839
+ del: (key: string) => store.del(key),
840
+ batch: () => createStoreBatch(store),
841
+ iterator: (options: { gte: string; lte: string }) => store.iterator(options),
842
+ });
843
+
836
844
  export async function deleteUser(
837
845
  db: any,
838
846
  userId: string,
@@ -856,7 +864,7 @@ export async function deleteUser(
856
864
  export async function handleDeleteUser(
857
865
  req: Request,
858
866
  userId: string,
859
- db: any = serverDb
867
+ db: any = createDeleteUserDb(getServerAuthorityStore())
860
868
  ) {
861
869
  if (req.method === "OPTIONS") {
862
870
  return handleOptionsRequest();
@@ -1,5 +1,5 @@
1
1
  // auth/server/disable.ts
2
- import serverDb from "../../database/server/db";
2
+ import { getServerAuthorityStore } from "../../database/server/db";
3
3
  import { DB_PREFIX } from "../../database/keys";
4
4
  import {
5
5
  createErrorResponse,
@@ -11,10 +11,11 @@ import { balanceLockManager } from "./locks";
11
11
  import { notifyAccountStatusChangeEmail } from "./emailScenarioNotifications";
12
12
 
13
13
  async function disableUser(userId: string) {
14
+ const store = getServerAuthorityStore();
14
15
  const lock = balanceLockManager.getLock(userId);
15
16
  await lock.runExclusive(async () => {
16
17
  const userKey = `${DB_PREFIX.USER}${userId}`;
17
- const userData = await serverDb.get(userKey).catch(() => null);
18
+ const userData = await store.get(userKey).catch(() => null);
18
19
 
19
20
  if (!userData) {
20
21
  throw new Error("User not found");
@@ -26,7 +27,7 @@ async function disableUser(userId: string) {
26
27
  isDisabled: true,
27
28
  disabledAt: new Date().toISOString(), // 记录停用时间,可选
28
29
  };
29
- await serverDb.put(userKey, updatedUserData);
30
+ await store.put(userKey, updatedUserData);
30
31
  });
31
32
  }
32
33
 
@@ -1,5 +1,5 @@
1
1
  import { DB_PREFIX } from "../../database/keys";
2
- import serverDb from "../../database/server/db";
2
+ import { getServerAuthorityStore } from "../../database/server/db";
3
3
  import { logger } from "./shared";
4
4
  import { balanceLockManager } from "./locks";
5
5
  import { canSendEmailToUser } from "./emailPolicy";
@@ -34,9 +34,10 @@ let reengagementRunning = false;
34
34
  const patchUserRecord = async (userId: string, patch: Record<string, any>) => {
35
35
  const key = `${USER_PREFIX}${userId}`;
36
36
  const lock = balanceLockManager.getLock(userId);
37
+ const store = getServerAuthorityStore();
37
38
  await lock.runExclusive(async () => {
38
- const current = (await serverDb.get(key)) as UserEmailRecord;
39
- await serverDb.put(key, { ...current, ...patch });
39
+ const current = (await store.get(key)) as UserEmailRecord;
40
+ await store.put(key, { ...current, ...patch });
40
41
  });
41
42
  };
42
43
 
@@ -115,8 +116,9 @@ export async function runReengagementSweep() {
115
116
  userId: string;
116
117
  user: UserEmailRecord;
117
118
  }> = [];
119
+ const store = getServerAuthorityStore();
118
120
 
119
- const iter = serverDb.iterator({
121
+ const iter = store.iterator({
120
122
  gt: USER_PREFIX,
121
123
  lt: USER_PREFIX + "\xFF",
122
124
  });
@@ -295,7 +297,7 @@ export async function runReengagementSweep() {
295
297
  }
296
298
  }
297
299
  } finally {
298
- await iter.close();
300
+ await (iter as any).close?.();
299
301
  reengagementRunning = false;
300
302
  }
301
303
 
@@ -1,4 +1,4 @@
1
- import serverDb from "../../database/server/db";
1
+ import { getServerAuthorityStore } from "../../database/server/db";
2
2
  import { logger } from "./shared";
3
3
 
4
4
  export const EMAIL_RUNTIME_CONFIG_KEY = "config:email:runtime";
@@ -109,7 +109,9 @@ export async function applyEmailRuntimeConfigFromDb() {
109
109
  }
110
110
 
111
111
  export async function readEmailRuntimeConfigFromDb() {
112
- const raw = await serverDb.get(EMAIL_RUNTIME_CONFIG_KEY).catch(() => null);
112
+ const raw = await getServerAuthorityStore()
113
+ .get(EMAIL_RUNTIME_CONFIG_KEY)
114
+ .catch(() => null);
113
115
  if (!isRecord(raw)) {
114
116
  return null;
115
117
  }