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
@@ -5,7 +5,7 @@ import { format } from "date-fns";
5
5
  import { createPageKey } from "../../../database/keys";
6
6
  import { DataType } from "../../../create/types";
7
7
  import { markdownToSlate } from "../../../create/editor/transforms/markdownToSlate";
8
- import serverDb, { ensureServerDbOpen } from "../../../database/server/db";
8
+ import { ensureServerDbOpen, getServerAuthorityStore } from "../../../database/server/db";
9
9
  import type { PageData } from "../types";
10
10
  import {
11
11
  createEmptyParagraph,
@@ -15,6 +15,8 @@ import {
15
15
  import { slateToRenderMarkdown } from "../../../create/editor/transforms/slateToRenderMarkdown";
16
16
  import { parseSkillDocProtocol } from "../../../ai/skills/skillDocProtocol";
17
17
 
18
+ const serverDb = getServerAuthorityStore();
19
+
18
20
  export interface CreatePageServerArgs {
19
21
  userId: string;
20
22
  title?: string;
@@ -2,7 +2,7 @@
2
2
  // HTTP handler for createPage (Bun serve 兼容)
3
3
 
4
4
  import { createPageServer } from "./createPage";
5
- import { handleToken } from "../../../auth/server/token";
5
+ import { readUserFromRequest } from "../../../auth/server/token";
6
6
  import { logger } from "../../../auth/server/shared";
7
7
 
8
8
  const CORS_HEADERS = {
@@ -27,15 +27,7 @@ const CORS_HEADERS = {
27
27
  */
28
28
  export const handleCreatePage = async (req: Request): Promise<Response> => {
29
29
  try {
30
- // 鉴权:创建一个简化的 req 对象用于 handleToken
31
- const authReq: any = {
32
- headers: {
33
- get: (name: string) => req.headers.get(name),
34
- },
35
- };
36
- const authRes: any = {}; // handleToken 可能不需要 res
37
-
38
- const user = await handleToken(authReq, authRes);
30
+ const user = await readUserFromRequest(req);
39
31
  const userId = user?.userId;
40
32
 
41
33
  if (!userId) {
@@ -88,4 +80,3 @@ export const handleCreatePage = async (req: Request): Promise<Response> => {
88
80
  );
89
81
  }
90
82
  };
91
-
@@ -1,41 +1,22 @@
1
- import { resolveAgentRuntimeDecision } from "./agent-runtime/runtimeDecision";
2
1
  import {
3
2
  type AgentCommandDeps,
4
3
  type LocalRuntimeProbeResult,
5
4
  } from "./agentCommandSupport";
5
+ import {
6
+ buildCliRuntimeDoctorProbe,
7
+ buildCliRuntimeDoctorReport,
8
+ formatCliRuntimeDoctorReport,
9
+ } from "./cliRuntimeDoctorReport";
6
10
  import {
7
11
  resolveAuthToken,
8
12
  resolveServerUrl,
9
13
  type EnvLike,
10
14
  } from "./cliEnvHelpers";
11
15
 
12
- function detectLocalAgentConfig(env: EnvLike) {
13
- return Boolean(readLocalAgentKey(env) || env.NOLO_AGENT_CACHE_READY);
14
- }
15
-
16
16
  function readLocalAgentKey(env: EnvLike) {
17
17
  return env.NOLO_LOCAL_AGENT_KEY || env.NOLO_AGENT || "";
18
18
  }
19
19
 
20
- function detectLocalProvider(env: EnvLike) {
21
- return Boolean(
22
- env.OPENAI_API_KEY ||
23
- env.ANTHROPIC_API_KEY ||
24
- env.GOOGLE_API_KEY ||
25
- env.NOLO_LOCAL_OPENAI_BASE_URL ||
26
- env.OLLAMA_BASE_URL
27
- );
28
- }
29
-
30
- function detectProviderLabel(env: EnvLike) {
31
- if (env.NOLO_LOCAL_OPENAI_BASE_URL) return `openai-compatible endpoint ${env.NOLO_LOCAL_OPENAI_BASE_URL}`;
32
- if (env.OLLAMA_BASE_URL) return `ollama-compatible endpoint ${env.OLLAMA_BASE_URL}`;
33
- if (env.OPENAI_API_KEY) return "openai via env OPENAI_API_KEY";
34
- if (env.ANTHROPIC_API_KEY) return "anthropic via env ANTHROPIC_API_KEY";
35
- if (env.GOOGLE_API_KEY) return "google via env GOOGLE_API_KEY";
36
- return "missing";
37
- }
38
-
39
20
  async function defaultLocalRuntimeProbe(env: EnvLike): Promise<LocalRuntimeProbeResult> {
40
21
  const { resolveCliLocalRuntimeDbPath } = await import("./localRuntimeDb");
41
22
  const dbPath = resolveCliLocalRuntimeDbPath({ env });
@@ -64,55 +45,23 @@ async function defaultLocalRuntimeProbe(env: EnvLike): Promise<LocalRuntimeProbe
64
45
  }
65
46
 
66
47
  export async function runDoctorRuntimeCommand(
67
- _args: string[],
48
+ args: string[],
68
49
  deps: AgentCommandDeps = {}
69
50
  ) {
70
51
  const env = deps.env ?? process.env;
71
52
  const output = deps.output ?? process.stdout;
72
- const authToken = resolveAuthToken(env);
73
- const serverUrl = resolveServerUrl(env);
53
+ const authToken = resolveAuthToken(args, env);
54
+ const serverUrl = resolveServerUrl(args, env);
74
55
  const localProbe = await (deps.localRuntimeProbe ?? defaultLocalRuntimeProbe)(env);
75
- const hasLocalAgentConfig = detectLocalAgentConfig(env) && localProbe.ok && localProbe.agentFound;
76
- const hasLocalProvider = detectLocalProvider(env);
77
- const missingLocalCapabilities = [
78
- ...(localProbe.ok ? [] : ["leveldb"]),
79
- ...(hasLocalAgentConfig ? [] : ["agent-config"]),
80
- ...(hasLocalProvider ? [] : ["provider"]),
81
- ];
82
- const decision = resolveAgentRuntimeDecision({
83
- requestedMode: "auto",
84
- syncRequested: false,
85
- host: "cli",
86
- hasLocalAgentConfig,
87
- hasLocalProvider,
88
- hasLocalPersistence: true,
89
- missingLocalCapabilities,
90
- requiresServer: false,
91
- serverFallbackAvailable: Boolean(authToken || env.NOLO_SERVER || env.BASE_URL),
92
- });
93
-
94
- output.write(`Runtime: ${decision.mode}\n`);
95
- output.write(`Reason: ${decision.reason}\n`);
96
- output.write(`LevelDB: ${localProbe.ok ? "ok" : "failed"}\n`);
97
- output.write(`DB path: ${localProbe.dbPath}\n`);
98
- if (!localProbe.ok && localProbe.error) {
99
- output.write(`DB error: ${localProbe.error}\n`);
100
- }
101
- if (localProbe.agentKey) {
102
- output.write(`Agent config: ${localProbe.agentFound ? "found" : "missing"} (${localProbe.agentKey})\n`);
103
- } else {
104
- output.write("Agent config: missing (no local agent key)\n");
105
- }
106
- output.write(`Provider: ${hasLocalProvider ? "available" : "missing"} (${detectProviderLabel(env)})\n`);
107
- output.write("Persistence: LevelDB local store\n");
108
- output.write(`Sync: ${authToken ? "available" : "unavailable"}${authToken ? "" : " (not authenticated)"}\n`);
109
- output.write(`Server fallback: ${decision.runnable && decision.mode === "server" ? serverUrl : authToken || env.NOLO_SERVER || env.BASE_URL ? serverUrl : "unavailable"}\n`);
110
- if (decision.missingLocalCapabilities.length > 0) {
111
- output.write("Missing local capabilities:\n");
112
- for (const capability of decision.missingLocalCapabilities) {
113
- output.write(`- ${capability}\n`);
114
- }
115
- }
56
+ const report = buildCliRuntimeDoctorReport(
57
+ buildCliRuntimeDoctorProbe({
58
+ env,
59
+ localProbe,
60
+ authToken,
61
+ serverUrl,
62
+ })
63
+ );
64
+ output.write(formatCliRuntimeDoctorReport(report));
116
65
 
117
- return decision.runnable ? 0 : 1;
66
+ return report.decision.runnable ? 0 : 1;
118
67
  }
@@ -1,6 +1,6 @@
1
1
  // ai/server/apiMethods.ts
2
2
 
3
- import serverDb from "../../database/server/db";
3
+ import { getServerAuthorityStore } from "../../database/server/db";
4
4
  import { MemberRole, SpaceVisibility, SpaceMemberWithSpaceInfo } from "../../app/types";
5
5
  import { fetchMessages, MessageWithKey } from "../../chat/messages/fetchMessages";
6
6
  import type { Message } from "../../chat/messages/types";
@@ -23,14 +23,20 @@ import {
23
23
  updateEmailTags,
24
24
  } from "../../database/server/emailRepository";
25
25
  import { isTombstoneRecord } from "../../database/tombstones";
26
+
27
+ type ApiMethodsStore = ReturnType<typeof getServerAuthorityStore>;
28
+
29
+ const getApiMethodsStore = () => getServerAuthorityStore();
30
+
26
31
  // DB 列表迭代 (保留,因为 fetchUserSpaceMemberships 仍在使用)
27
32
  async function dbListEntries<T>(
33
+ store: ApiMethodsStore,
28
34
  gte: string,
29
35
  lte: string,
30
36
  filter?: (key: string, value: T) => boolean
31
37
  ): Promise<Array<{ key: string; value: T }>> {
32
38
  const res: Array<{ key: string; value: T }> = [];
33
- for await (const [key, value] of serverDb.iterator({ gte, lte })) {
39
+ for await (const [key, value] of store.iterator({ gte, lte })) {
34
40
  if (typeof key !== "string") continue;
35
41
  if (!filter || filter(key, value as T)) res.push({ key, value: value as T });
36
42
  }
@@ -88,6 +94,7 @@ const membershipFromSpace = (
88
94
  };
89
95
 
90
96
  const repairMissingMembershipsFromSpaces = async (
97
+ store: ApiMethodsStore,
91
98
  userId: string,
92
99
  existing: SpaceMemberWithSpaceInfo[],
93
100
  indexedSpaceIds: Set<string>
@@ -100,6 +107,7 @@ const repairMissingMembershipsFromSpaces = async (
100
107
  );
101
108
  const repaired: SpaceMemberWithSpaceInfo[] = [];
102
109
  const spaces = await dbListEntries<any>(
110
+ store,
103
111
  "space-",
104
112
  "space-\xff",
105
113
  (key, space) =>
@@ -116,13 +124,14 @@ const repairMissingMembershipsFromSpaces = async (
116
124
  if (bySpaceId.has(normalizedSpaceId)) continue;
117
125
  bySpaceId.set(normalizedSpaceId, membership);
118
126
  repaired.push(membership);
119
- await serverDb.put(membershipKey(userId, normalizedSpaceId), membership);
127
+ await store.put(membershipKey(userId, normalizedSpaceId), membership);
120
128
  }
121
129
 
122
130
  return [...existing, ...repaired];
123
131
  };
124
132
 
125
133
  const hasActiveSpaceMembership = async (
134
+ store: ApiMethodsStore,
126
135
  userId: string,
127
136
  memberKey: string,
128
137
  membership: SpaceMemberWithSpaceInfo
@@ -149,7 +158,7 @@ const hasActiveSpaceMembership = async (
149
158
  }
150
159
 
151
160
  try {
152
- const space = await serverDb.get(`space-${keySpaceId}`);
161
+ const space = await store.get(`space-${keySpaceId}`);
153
162
  if (!space || isTombstoneRecord(space)) return false;
154
163
  if (space.ownerId === userId) return true;
155
164
  return Array.isArray(space.members) && space.members.includes(userId);
@@ -162,11 +171,13 @@ export async function fetchUserSpaceMemberships(
162
171
  params: string | { userId: string },
163
172
  context?: ApiContext
164
173
  ): Promise<SpaceMemberWithSpaceInfo[]> {
174
+ const store = getApiMethodsStore();
165
175
  const userId =
166
176
  context?.userId || (typeof params === "string" ? params : params.userId);
167
177
  if (!userId) throw new Error("userId 必传");
168
178
  const prefix = `space-member-${userId}-`;
169
179
  const memberships = await dbListEntries<SpaceMemberWithSpaceInfo>(
180
+ store,
170
181
  prefix,
171
182
  prefix + "\xff",
172
183
  (_, membership) => !isTombstoneRecord(membership)
@@ -179,7 +190,7 @@ export async function fetchUserSpaceMemberships(
179
190
  );
180
191
  const activeMemberships = await Promise.all(
181
192
  memberships.map(async ({ key, value }) =>
182
- await hasActiveSpaceMembership(userId, key, value)
193
+ await hasActiveSpaceMembership(store, userId, key, value)
183
194
  ? value
184
195
  : null
185
196
  )
@@ -187,7 +198,12 @@ export async function fetchUserSpaceMemberships(
187
198
  const verifiedMemberships = activeMemberships.filter(
188
199
  (membership): membership is SpaceMemberWithSpaceInfo => !!membership
189
200
  );
190
- return repairMissingMembershipsFromSpaces(userId, verifiedMemberships, indexedSpaceIds);
201
+ return repairMissingMembershipsFromSpaces(
202
+ store,
203
+ userId,
204
+ verifiedMemberships,
205
+ indexedSpaceIds
206
+ );
191
207
  }
192
208
 
193
209
  interface FetchConvMsgsParams {
@@ -201,6 +217,7 @@ export async function fetchConvMsgs(
201
217
  params: string | FetchConvMsgsParams,
202
218
  context?: ApiContext
203
219
  ): Promise<Message[]> {
220
+ const store = getApiMethodsStore();
204
221
  let dialogId: string,
205
222
  dialogKey: string | undefined,
206
223
  limit: number | undefined,
@@ -226,7 +243,7 @@ export async function fetchConvMsgs(
226
243
  };
227
244
  }
228
245
 
229
- const dialogRecord = await findDialogRecord(dialogId, dialogKey);
246
+ const dialogRecord = await findDialogRecord(store, dialogId, dialogKey);
230
247
  if (!dialogRecord) {
231
248
  throw {
232
249
  code: "not_found",
@@ -247,7 +264,7 @@ export async function fetchConvMsgs(
247
264
  };
248
265
  }
249
266
 
250
- const msgs: MessageWithKey[] = await fetchMessages(serverDb, dialogId, {
267
+ const msgs: MessageWithKey[] = await fetchMessages(store, dialogId, {
251
268
  limit,
252
269
  beforeKey,
253
270
  throwOnError: true,
@@ -275,6 +292,7 @@ function isDialogRecordForId(record: any, dialogId: string): boolean {
275
292
  }
276
293
 
277
294
  async function readDialogRecordByKey(
295
+ store: ApiMethodsStore,
278
296
  dialogKey: string | undefined,
279
297
  dialogId: string
280
298
  ): Promise<{ dbKey: string; record: any } | null> {
@@ -282,7 +300,7 @@ async function readDialogRecordByKey(
282
300
  return null;
283
301
  }
284
302
  try {
285
- const record = await serverDb.get(dialogKey);
303
+ const record = await store.get(dialogKey);
286
304
  if (!isDialogRecordForId(record, dialogId)) return null;
287
305
  return { dbKey: dialogKey, record };
288
306
  } catch (error) {
@@ -291,15 +309,19 @@ async function readDialogRecordByKey(
291
309
  }
292
310
  }
293
311
 
294
- async function findDialogRecord(dialogId: string, dialogKey?: string): Promise<{
312
+ async function findDialogRecord(
313
+ store: ApiMethodsStore,
314
+ dialogId: string,
315
+ dialogKey?: string
316
+ ): Promise<{
295
317
  dbKey: string;
296
318
  record: any;
297
319
  } | null> {
298
- const directRecord = await readDialogRecordByKey(dialogKey, dialogId);
320
+ const directRecord = await readDialogRecordByKey(store, dialogKey, dialogId);
299
321
  if (directRecord) return directRecord;
300
322
 
301
323
  const suffix = `-${dialogId}`;
302
- for await (const [key, value] of serverDb.iterator({
324
+ for await (const [key, value] of store.iterator({
303
325
  gte: "dialog-",
304
326
  lte: "dialog-\uffff",
305
327
  })) {
@@ -1,10 +1,12 @@
1
1
  // server/api/tableHandlers.ts
2
- import serverDb from "../../database/server/db";
2
+ import { getServerAuthorityStore } from "../../database/server/db";
3
3
  import { metaKey, rowKey } from "../../database/keys";
4
4
  import { DataType } from "../../create/types";
5
5
  import type { ApiContext, ApiError } from "./types";
6
6
  import { assertCanReadTableRows } from "../handlers/tableAccess";
7
7
 
8
+ const getTableHandlersStore = () => getServerAuthorityStore();
9
+
8
10
  interface ListTableRowsParams {
9
11
  tenantId: string;
10
12
  tableId: string;
@@ -14,6 +16,7 @@ export async function listTableRows(
14
16
  params: ListTableRowsParams,
15
17
  context?: ApiContext
16
18
  ) {
19
+ const store = getTableHandlersStore();
17
20
  const { tenantId, tableId } = params || {};
18
21
  if (!tenantId || !tableId) {
19
22
  throw new Error("tenantId 和 tableId 必传");
@@ -24,7 +27,7 @@ export async function listTableRows(
24
27
  message: "Cannot list table rows for another tenant",
25
28
  } as ApiError;
26
29
  }
27
- const tableMeta = await serverDb.get(metaKey(tenantId, tableId)).catch(() => null);
30
+ const tableMeta = await store.get(metaKey(tenantId, tableId)).catch(() => null);
28
31
  try {
29
32
  await assertCanReadTableRows({
30
33
  userId: context.userId,
@@ -44,7 +47,7 @@ export async function listTableRows(
44
47
  const MAX_ROWS = 5000;
45
48
 
46
49
  const rows: any[] = [];
47
- for await (const [, value] of serverDb.iterator({ gte, lte })) {
50
+ for await (const [, value] of store.iterator({ gte, lte })) {
48
51
  if (value?.type === DataType.TABLE_ROW && !value?.deletedAt) {
49
52
  rows.push(value);
50
53
  if (rows.length >= MAX_ROWS) break;
@@ -1,7 +1,8 @@
1
1
  import { assertSessionTokenVersion } from "../auth/sessionTokenVersion";
2
2
  import { parseToken, verifyToken } from "../auth/token";
3
+ import { NOLO_CLUSTER_SERVERS, normalizeKnownServerOrigin } from "../database/config";
3
4
  import { DB_PREFIX } from "../database/keys";
4
- import serverDb from "../database/server/db";
5
+ import { getServerAuthorityStore } from "../database/server/db";
5
6
  import type { ApiError } from "./api/types";
6
7
 
7
8
  const unauthorized = (message: string): ApiError => ({
@@ -31,10 +32,46 @@ const isOutsideTokenWindow = (payload: any): boolean => {
31
32
  return false;
32
33
  };
33
34
 
35
+ const normalizeServerOrigin = (value: string | null | undefined): string | null => {
36
+ if (typeof value !== "string" || !value.trim()) return null;
37
+ return normalizeKnownServerOrigin(value);
38
+ };
39
+
40
+ const resolveAuthFallbackServers = (): string[] => {
41
+ const current = normalizeServerOrigin(process.env.APP_BASE_URL);
42
+ return NOLO_CLUSTER_SERVERS.filter((server) => normalizeServerOrigin(server) !== current);
43
+ };
44
+
45
+ const getAuthTokenStore = () => getServerAuthorityStore();
46
+
47
+ const readUserFromClusterPeer = async (userId: string, token: string): Promise<any | null> => {
48
+ const store = getAuthTokenStore();
49
+ for (const server of resolveAuthFallbackServers()) {
50
+ try {
51
+ const res = await fetch(`${server}/api/v1/users/${encodeURIComponent(userId)}`, {
52
+ method: "GET",
53
+ headers: { Authorization: `Bearer ${token}` },
54
+ });
55
+ if (!res.ok) continue;
56
+ const data = await res.json().catch(() => null);
57
+ if (!data || typeof data !== "object") continue;
58
+ const record = { ...(data as Record<string, unknown>) };
59
+ delete (record as Record<string, unknown>).id;
60
+ if (typeof record.publicKey !== "string" || !record.publicKey) continue;
61
+ await store.put(`${DB_PREFIX.USER}${userId}`, record);
62
+ return record;
63
+ } catch {
64
+ // Try the next peer.
65
+ }
66
+ }
67
+ return null;
68
+ };
69
+
34
70
  export async function authenticateToken(token?: string | null): Promise<{
35
71
  userId: string;
36
72
  payload: any;
37
73
  }> {
74
+ const store = getAuthTokenStore();
38
75
  if (!token) {
39
76
  throw unauthorized("Authentication required");
40
77
  }
@@ -47,8 +84,16 @@ export async function authenticateToken(token?: string | null): Promise<{
47
84
 
48
85
  let user: any;
49
86
  try {
50
- user = await serverDb.get(`${DB_PREFIX.USER}${userId}`);
87
+ user = await store.get(`${DB_PREFIX.USER}${userId}`);
51
88
  } catch {
89
+ user = null;
90
+ }
91
+
92
+ if (!user) {
93
+ user = await readUserFromClusterPeer(userId, token);
94
+ }
95
+
96
+ if (!user) {
52
97
  throw unauthorized("User not found");
53
98
  }
54
99
 
@@ -3,6 +3,9 @@ import { handleBillingLedgerWitness } from "./handlers/billingLedgerWitnessHandl
3
3
  import { handleBillingUsageReport } from "./handlers/billingUsageReportHandler";
4
4
  import { handleCreatorEarningsReport } from "./handlers/creatorEarningsReportHandler";
5
5
  import { handleCreatorSettlementReport } from "./handlers/creatorSettlementReportHandler";
6
+ import { handleProviderCallsRecent } from "./handlers/providerCallsRecentHandler";
7
+ import { handleProviderRequestIds } from "./handlers/providerRequestIdsHandler";
8
+ import { handleProviderReconciliationRun } from "./handlers/providerReconciliationRunHandler";
6
9
  import { handleRevenueShareReport } from "./handlers/revenueShareReportHandler";
7
10
 
8
11
  const CORS_HEADERS: Record<string, string> = {
@@ -33,6 +36,18 @@ export const billingLedgerRoutes: Record<string, any> = {
33
36
  GET: handleBillingUsageReport,
34
37
  OPTIONS: options,
35
38
  },
39
+ "/api/admin/provider-calls/recent": {
40
+ GET: handleProviderCallsRecent,
41
+ OPTIONS: options,
42
+ },
43
+ "/api/admin/provider-request-ids/recent": {
44
+ GET: handleProviderRequestIds,
45
+ OPTIONS: options,
46
+ },
47
+ "/api/admin/provider-reconciliation/run": {
48
+ POST: handleProviderReconciliationRun,
49
+ OPTIONS: options,
50
+ },
36
51
  "/api/admin/revenue-share/report": {
37
52
  GET: handleRevenueShareReport,
38
53
  OPTIONS: options,
@@ -0,0 +1,54 @@
1
+ import { readFileSync } from "node:fs";
2
+
3
+ import { resolvePublicPath } from "./publicPaths";
4
+
5
+ export type NoloBuildManifest = {
6
+ basePath: string | null;
7
+ timestamp: string | null;
8
+ buildSha: string | null;
9
+ buildTime: string | null;
10
+ };
11
+
12
+ export const EMPTY_BUILD_MANIFEST: NoloBuildManifest = {
13
+ basePath: null,
14
+ timestamp: null,
15
+ buildSha: null,
16
+ buildTime: null,
17
+ };
18
+
19
+ const readOptionalString = (value: unknown): string | null =>
20
+ typeof value === "string" && value.trim().length > 0 ? value : null;
21
+
22
+ export function parseBuildManifestFromJson(rawValue: string): NoloBuildManifest {
23
+ try {
24
+ const parsed = JSON.parse(rawValue);
25
+ return {
26
+ basePath: readOptionalString(parsed?.basePath),
27
+ timestamp: readOptionalString(parsed?.timestamp),
28
+ buildSha: readOptionalString(parsed?.buildSha),
29
+ buildTime: readOptionalString(parsed?.buildTime),
30
+ };
31
+ } catch {
32
+ return EMPTY_BUILD_MANIFEST;
33
+ }
34
+ }
35
+
36
+ export function readBuildManifestSync(): NoloBuildManifest {
37
+ try {
38
+ return parseBuildManifestFromJson(
39
+ readFileSync(resolvePublicPath("latest-assets.json"), "utf8")
40
+ );
41
+ } catch {
42
+ return EMPTY_BUILD_MANIFEST;
43
+ }
44
+ }
45
+
46
+ export async function readBuildManifest(): Promise<NoloBuildManifest> {
47
+ try {
48
+ return parseBuildManifestFromJson(
49
+ await Bun.file(resolvePublicPath("latest-assets.json")).text()
50
+ );
51
+ } catch {
52
+ return EMPTY_BUILD_MANIFEST;
53
+ }
54
+ }
@@ -1,13 +1,18 @@
1
- import { withServiceHeaders } from "./coreHeaders";
2
- import { getCoreRuntimeSnapshot } from "./coreRuntime";
3
-
4
- export function handleCoreReady(_req: Request) {
5
- const snapshot = getCoreRuntimeSnapshot();
6
- const body = {
7
- ok: snapshot.ready,
8
- ready: snapshot.ready,
9
- status: snapshot.status,
10
- };
1
+ import { withServiceHeaders } from "./coreHeaders";
2
+ import { readBuildManifestSync } from "./buildManifest";
3
+ import { getCoreRuntimeSnapshot } from "./coreRuntime";
4
+
5
+ export function handleCoreReady(_req: Request) {
6
+ const snapshot = getCoreRuntimeSnapshot();
7
+ const buildManifest = readBuildManifestSync();
8
+ const body = {
9
+ ok: snapshot.ready,
10
+ ready: snapshot.ready,
11
+ status: snapshot.status,
12
+ role: snapshot.role,
13
+ buildSha: buildManifest.buildSha,
14
+ buildTime: buildManifest.buildTime,
15
+ };
11
16
 
12
17
  return withServiceHeaders(
13
18
  Response.json(body, {
@@ -21,19 +26,23 @@ export function handleCoreReady(_req: Request) {
21
26
  );
22
27
  }
23
28
 
24
- export function handleCoreMeta(_req: Request) {
25
- const snapshot = getCoreRuntimeSnapshot();
26
-
27
- return withServiceHeaders(
28
- Response.json({
29
- service: "core",
30
- status: snapshot.status,
31
- ready: snapshot.ready,
32
- }),
33
- {
34
- service: "core",
35
- owner: "core-route",
36
- routeKind: "core",
37
- }
38
- );
29
+ export function handleCoreMeta(_req: Request) {
30
+ const snapshot = getCoreRuntimeSnapshot();
31
+ const buildManifest = readBuildManifestSync();
32
+
33
+ return withServiceHeaders(
34
+ Response.json({
35
+ service: "core",
36
+ status: snapshot.status,
37
+ ready: snapshot.ready,
38
+ role: snapshot.role,
39
+ buildSha: buildManifest.buildSha,
40
+ buildTime: buildManifest.buildTime,
41
+ }),
42
+ {
43
+ service: "core",
44
+ owner: "core-route",
45
+ routeKind: "core",
46
+ }
47
+ );
39
48
  }
@@ -26,22 +26,27 @@ import {
26
26
  startCryptoUsdtTronWatcher,
27
27
  stopCryptoUsdtTronWatcher,
28
28
  } from "./payments/crypto/cryptoUsdtTronWatcher";
29
-
30
- type CoreRuntimeStatus = "idle" | "starting" | "ready" | "stopping";
29
+ import { resolveRuntimeRole, shouldRunBackgroundWorkers } from "./runtimeRole";
30
+
31
+ type CoreRuntimeStatus = "idle" | "starting" | "ready" | "stopping";
31
32
 
32
33
  let status: CoreRuntimeStatus = "idle";
33
34
  let startPromise: Promise<void> | null = null;
34
35
  let stopPromise: Promise<void> | null = null;
35
36
 
37
+ const getRuntimeRole = () => resolveRuntimeRole(process.env);
38
+
36
39
  const backgroundWorkersDisabled = () =>
37
- process.env.NOLO_DISABLE_BACKGROUND_WORKERS === "1";
38
-
39
- export function getCoreRuntimeSnapshot() {
40
- return {
41
- status,
42
- ready: status === "ready",
43
- };
44
- }
40
+ process.env.NOLO_DISABLE_BACKGROUND_WORKERS === "1" ||
41
+ !shouldRunBackgroundWorkers(getRuntimeRole());
42
+
43
+ export function getCoreRuntimeSnapshot() {
44
+ return {
45
+ status,
46
+ ready: status === "ready",
47
+ role: getRuntimeRole(),
48
+ };
49
+ }
45
50
 
46
51
  export async function startCoreRuntime() {
47
52
  if (startPromise) return startPromise;
@@ -4,13 +4,15 @@
4
4
  //
5
5
  // GET /api/admin/activity-stats?days=30
6
6
 
7
- import serverDb from "../../database/server/db";
7
+ import { getServerAuthorityStore } from "../../database/server/db";
8
8
 
9
9
  const CORS = {
10
10
  "Access-Control-Allow-Origin": "*",
11
11
  "Content-Type": "application/json",
12
12
  };
13
13
 
14
+ const getActivityStatsStore = () => getServerAuthorityStore();
15
+
14
16
  export async function handleActivityStats(req: Request): Promise<Response> {
15
17
  if (req.method === "OPTIONS") return new Response(null, { status: 204, headers: CORS });
16
18
 
@@ -27,8 +29,9 @@ export async function handleActivityStats(req: Request): Promise<Response> {
27
29
  let skipped = 0;
28
30
 
29
31
  try {
32
+ const store = getActivityStatsStore();
30
33
  // 扫描所有以 "token-" 开头但不是 "token-stats-" 的记录
31
- const iter = serverDb.iterator({
34
+ const iter = store.iterator({
32
35
  gte: "token-",
33
36
  lte: "token-\uffff",
34
37
  });