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
@@ -1,7 +1,7 @@
1
1
  import { authenticateRequest, CORS_HEADERS_AUTH } from "../../auth/utils";
2
2
  import { DataType } from "../../create/types";
3
3
  import { createKey, createTokenKey } from "../../database/keys";
4
- import serverDb from "../../database/server/db";
4
+ import { getServerAuthorityStore } from "../../database/server/db";
5
5
 
6
6
  const json = (data: any, status = 200) =>
7
7
  new Response(JSON.stringify(data), {
@@ -32,6 +32,7 @@ const toNumber = (value: unknown) =>
32
32
  typeof value === "number" && Number.isFinite(value) ? value : 0;
33
33
 
34
34
  export const handleGetDialogBilling = async (req: any) => {
35
+ const store = getServerAuthorityStore();
35
36
  const authResult = await authenticateRequest(req);
36
37
  if (authResult instanceof Response) return authResult;
37
38
 
@@ -54,7 +55,7 @@ export const handleGetDialogBilling = async (req: any) => {
54
55
 
55
56
  let dialog: any;
56
57
  try {
57
- dialog = await serverDb.get(dialogKey);
58
+ dialog = await store.get(dialogKey);
58
59
  } catch {
59
60
  return json(
60
61
  {
@@ -78,7 +79,7 @@ export const handleGetDialogBilling = async (req: any) => {
78
79
  const { start, end } = createTokenKey.rangeOfUser(userId);
79
80
  const records: BillingRecord[] = [];
80
81
 
81
- for await (const [, value] of serverDb.iterator({
82
+ for await (const [, value] of store.iterator({
82
83
  gte: start,
83
84
  lte: end,
84
85
  reverse: true,
@@ -2,11 +2,13 @@
2
2
 
3
3
  import { authenticateRequest } from "../../auth/utils";
4
4
  import { createTransactionKey } from "../../database/keys";
5
- import serverDb from "../../database/server/db";
5
+ import { getServerAuthorityStore } from "../../database/server/db";
6
6
  import pino from "pino";
7
7
 
8
8
  const logger = pino({ name: "getTransactions" });
9
9
 
10
+ const getTransactionsStore = () => getServerAuthorityStore();
11
+
10
12
  // 定义通用的 CORS 头
11
13
  const CORS_HEADERS = {
12
14
  "Access-Control-Allow-Origin": "*",
@@ -36,6 +38,7 @@ const createJsonResponse = (data: any, status: number = 200): Response => {
36
38
  */
37
39
  export const handleGetTransactions = async (req: Request) => {
38
40
  try {
41
+ const store = getTransactionsStore();
39
42
  // 步骤 1: 验证用户身份
40
43
  const authResult = await authenticateRequest(req);
41
44
  if (authResult instanceof Response) {
@@ -73,7 +76,7 @@ export const handleGetTransactions = async (req: Request) => {
73
76
  }
74
77
 
75
78
  // 步骤 4: 查询数据库
76
- const iterator = serverDb.iterator(queryOptions);
79
+ const iterator = store.iterator(queryOptions);
77
80
  const transactions = [];
78
81
  for await (const [, value] of iterator) {
79
82
  transactions.push(value);
@@ -2,6 +2,7 @@ import type { MachineSummary } from "./machineRegistry";
2
2
 
3
3
  export type RuntimeBinding = {
4
4
  machineId?: string | null;
5
+ ownerUserId?: string | null;
5
6
  requiredCapabilities?: string[] | null;
6
7
  };
7
8
 
@@ -34,14 +34,6 @@ type MachineHandlerDeps = {
34
34
 
35
35
  type SmokeCliProvider = "codex" | "copilot" | "claude" | "agy" | "gemini";
36
36
 
37
- const SMOKE_CAPABILITY_BY_PROVIDER: Record<SmokeCliProvider, string> = {
38
- codex: "codex-cli",
39
- copilot: "copilot-cli",
40
- claude: "claude-code",
41
- agy: "agy-cli",
42
- gemini: "gemini-cli",
43
- };
44
-
45
37
  function normalizeSmokeProvider(value: unknown): SmokeCliProvider | null {
46
38
  if (
47
39
  value === "codex" ||
@@ -230,12 +222,6 @@ export function createMachineHandlers(deps: MachineHandlerDeps = {}) {
230
222
  if (!connectorRegistry.hasConnection(auth.userId, machineId)) {
231
223
  return json({ error: "Machine connector is not connected" }, 409);
232
224
  }
233
-
234
- const requiredCapability = SMOKE_CAPABILITY_BY_PROVIDER[cliProvider];
235
- if (!machine.capabilities.includes(requiredCapability)) {
236
- return json({ error: `Machine is missing capability: ${requiredCapability}` }, 409);
237
- }
238
-
239
225
  try {
240
226
  const result = await connectorRegistry.sendAgentRun(auth.userId, machineId, {
241
227
  agentKey: `machine-smoke-${cliProvider}`,
@@ -331,13 +331,15 @@ function runCopilot(prompt, options) {
331
331
  }
332
332
 
333
333
  function runClaude(prompt, options) {
334
- const args = ["-p", prompt, "--permission-mode", "bypassPermissions"];
335
- if (options.model) args.push("--model", options.model);
334
+ const args = ["--add-dir", process.cwd(), "-p", prompt, "--permission-mode", "bypassPermissions"];
335
+ if (options.model && process.env.NOLO_CLAUDE_CLI_ALLOW_MODEL === "1") args.push("--model", options.model);
336
336
  return runProcess("claude", args, options);
337
337
  }
338
338
 
339
339
  function runAgy(prompt, options) {
340
340
  return runProcess("agy", [
341
+ "--add-dir",
342
+ process.cwd(),
341
343
  "--print",
342
344
  prompt,
343
345
  "--print-timeout",
@@ -1,4 +1,4 @@
1
- import serverDb from "../../database/server/db";
1
+ import { getServerAuthorityStore } from "../../database/server/db";
2
2
  import { parseSpaceMemberKey } from "../../database/server/spaceMemberAuthority";
3
3
  import {
4
4
  type NotificationRecord,
@@ -69,14 +69,16 @@ const mergePreservedFields = (
69
69
  };
70
70
  };
71
71
 
72
+ const getNotificationStore = () => getServerAuthorityStore();
73
+
72
74
  const upsertNotificationRecord = async (
73
75
  notification: NotificationRecord
74
76
  ): Promise<NotificationRecord> => {
75
- const existing = (await serverDb
77
+ const existing = (await getNotificationStore()
76
78
  .get(notification.dbKey)
77
79
  .catch(() => null)) as NotificationRecord | null;
78
80
  const merged = mergePreservedFields(notification, existing);
79
- await serverDb.put(merged.dbKey, merged);
81
+ await getNotificationStore().put(merged.dbKey, merged);
80
82
  pushEvent(`user-${merged.userId}`, {
81
83
  type: "notification.upsert",
82
84
  notification: merged,
@@ -1,6 +1,6 @@
1
1
  import { authenticateRequest, CORS_HEADERS_AUTH } from "../../auth/utils";
2
2
  import { createNotificationKey } from "../../database/keys";
3
- import serverDb, { ensureServerDbOpen } from "../../database/server/db";
3
+ import { ensureServerDbOpen, getServerAuthorityStore } from "../../database/server/db";
4
4
  import type { NotificationRecord } from "../../app/notifications/model";
5
5
 
6
6
  const JSON_HEADERS = {
@@ -27,6 +27,8 @@ const isLevelLifecycleError = (error: unknown) => {
27
27
  return code === "LEVEL_DATABASE_NOT_OPEN" || code === "LEVEL_ITERATOR_NOT_OPEN";
28
28
  };
29
29
 
30
+ const getNotificationsStore = () => getServerAuthorityStore();
31
+
30
32
  export const handleNotifications = async (req: Request): Promise<Response> => {
31
33
  if (req.method === "OPTIONS") {
32
34
  return new Response(null, { status: 204, headers: CORS_HEADERS_AUTH });
@@ -57,9 +59,10 @@ export const handleNotifications = async (req: Request): Promise<Response> => {
57
59
 
58
60
  const { start, end } = createNotificationKey.rangeOfUser(auth.userId);
59
61
  const notifications: NotificationRecord[] = [];
62
+ const store = getNotificationsStore();
60
63
 
61
64
  try {
62
- for await (const [key, value] of serverDb.iterator({ gte: start, lte: end })) {
65
+ for await (const [key, value] of store.iterator({ gte: start, lte: end })) {
63
66
  const record = value as NotificationRecord | null;
64
67
  if (!record || typeof record !== "object") continue;
65
68
  if (record.deletedAt) continue;
@@ -0,0 +1,234 @@
1
+ import type { ProviderCallEvent } from "../../ai/token/providerCall";
2
+ import type { ProviderDispatchIntent } from "../../ai/token/providerDispatchIntent";
3
+
4
+ const JSON_HEADERS = {
5
+ "content-type": "application/json; charset=utf-8",
6
+ };
7
+
8
+ type ProviderCallsRecentEnv = NodeJS.ProcessEnv & {
9
+ BILLING_LEDGER_AUDIT_SECRET?: string;
10
+ };
11
+
12
+ export type ProviderCallsRecentStore = {
13
+ iterator(options: { gte?: string; lte?: string }): AsyncIterable<[string, unknown]>;
14
+ };
15
+
16
+ const PROVIDER_CALL_PREFIX = "provider-call-";
17
+ const PROVIDER_CALL_RANGE_END = `${PROVIDER_CALL_PREFIX}\uffff`;
18
+ const PROVIDER_DISPATCH_INTENT_PREFIX = "provider-dispatch-intent-";
19
+ const PROVIDER_DISPATCH_INTENT_RANGE_END = `${PROVIDER_DISPATCH_INTENT_PREFIX}\uffff`;
20
+
21
+ const json = (body: unknown, status = 200) =>
22
+ new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });
23
+
24
+ const parseOptionalTimestamp = (value: string | null) => {
25
+ if (!value) return null;
26
+ const trimmed = value.trim();
27
+ if (!trimmed) return null;
28
+ if (/^\d+$/.test(trimmed)) return Number(trimmed);
29
+ const parsed = Date.parse(trimmed);
30
+ if (!Number.isFinite(parsed)) {
31
+ throw new Error(`invalid timestamp: ${value}`);
32
+ }
33
+ return parsed;
34
+ };
35
+
36
+ const parseLimit = (value: string | null) => {
37
+ const parsed = Number(value);
38
+ if (!Number.isFinite(parsed)) return 50;
39
+ return Math.min(Math.max(Math.floor(parsed), 1), 500);
40
+ };
41
+
42
+ const eventTimestamp = (event: ProviderCallEvent) => {
43
+ if (event.status === "completed") return Date.parse(event.completedAt);
44
+ if (event.status === "failed") return Date.parse(event.failedAt);
45
+ return Date.parse(event.startedAt);
46
+ };
47
+
48
+ const isProviderCallEvent = (value: unknown): value is ProviderCallEvent =>
49
+ Boolean(
50
+ value &&
51
+ typeof value === "object" &&
52
+ typeof (value as { providerCallId?: unknown }).providerCallId === "string" &&
53
+ typeof (value as { eventId?: unknown }).eventId === "string" &&
54
+ typeof (value as { status?: unknown }).status === "string"
55
+ );
56
+
57
+ const isProviderDispatchIntent = (value: unknown): value is ProviderDispatchIntent =>
58
+ Boolean(
59
+ value &&
60
+ typeof value === "object" &&
61
+ typeof (value as { providerCallId?: unknown }).providerCallId === "string" &&
62
+ typeof (value as { intentId?: unknown }).intentId === "string" &&
63
+ (value as { status?: unknown }).status === "dispatching"
64
+ );
65
+
66
+ const resolveDefaultStore = async (): Promise<ProviderCallsRecentStore> => {
67
+ const dbModule = await import("../../database/server/db");
68
+ return dbModule.default as ProviderCallsRecentStore;
69
+ };
70
+
71
+ export async function buildProviderCallsRecentReport({
72
+ store,
73
+ sinceMs,
74
+ untilMs,
75
+ limit,
76
+ dialogId,
77
+ provider,
78
+ model,
79
+ }: {
80
+ store: ProviderCallsRecentStore;
81
+ sinceMs: number;
82
+ untilMs: number;
83
+ limit: number;
84
+ dialogId?: string;
85
+ provider?: string;
86
+ model?: string;
87
+ }) {
88
+ const byCall = new Map<
89
+ string,
90
+ {
91
+ events: ProviderCallEvent[];
92
+ dispatchIntents: ProviderDispatchIntent[];
93
+ }
94
+ >();
95
+
96
+ for await (const [, value] of store.iterator({
97
+ gte: PROVIDER_CALL_PREFIX,
98
+ lte: PROVIDER_CALL_RANGE_END,
99
+ })) {
100
+ if (!isProviderCallEvent(value)) continue;
101
+ const timestamp = eventTimestamp(value);
102
+ if (!Number.isFinite(timestamp) || timestamp < sinceMs || timestamp > untilMs) continue;
103
+ if (dialogId && value.dialogId !== dialogId) continue;
104
+ if (provider && value.provider !== provider) continue;
105
+ if (model && value.model !== model) continue;
106
+ const existing = byCall.get(value.providerCallId) ?? {
107
+ events: [],
108
+ dispatchIntents: [],
109
+ };
110
+ existing.events.push(value);
111
+ byCall.set(value.providerCallId, existing);
112
+ }
113
+
114
+ for await (const [, value] of store.iterator({
115
+ gte: PROVIDER_DISPATCH_INTENT_PREFIX,
116
+ lte: PROVIDER_DISPATCH_INTENT_RANGE_END,
117
+ })) {
118
+ if (!isProviderDispatchIntent(value)) continue;
119
+ const existing = byCall.get(value.providerCallId);
120
+ if (!existing) continue;
121
+ existing.dispatchIntents.push(value);
122
+ }
123
+
124
+ const rows = Array.from(byCall.entries())
125
+ .map(([providerCallId, state]) => {
126
+ const sortedEvents = [...state.events].sort(
127
+ (a, b) => eventTimestamp(a) - eventTimestamp(b)
128
+ );
129
+ const first = sortedEvents[0];
130
+ const last = sortedEvents[sortedEvents.length - 1];
131
+ return {
132
+ providerCallId,
133
+ userId: first.userId,
134
+ dialogId: first.dialogId,
135
+ agentId: first.agentId,
136
+ provider: first.provider,
137
+ model: first.model,
138
+ endpoint: first.endpoint,
139
+ serviceTier: first.serviceTier,
140
+ credential: first.credential,
141
+ startedAt: first.startedAt,
142
+ lastEventAt: new Date(eventTimestamp(last)).toISOString(),
143
+ statuses: sortedEvents.map((event) => event.status),
144
+ billingStatus:
145
+ last.status === "completed" || last.status === "failed"
146
+ ? last.billingStatus
147
+ : undefined,
148
+ events: sortedEvents.map((event) => ({
149
+ eventId: event.eventId,
150
+ status: event.status,
151
+ timestamp: new Date(eventTimestamp(event)).toISOString(),
152
+ })),
153
+ dispatchIntents: state.dispatchIntents
154
+ .sort((a, b) => Date.parse(a.createdAt) - Date.parse(b.createdAt))
155
+ .map((intent) => ({
156
+ intentId: intent.intentId,
157
+ createdAt: intent.createdAt,
158
+ credential: intent.credential,
159
+ request: {
160
+ url: intent.request.url,
161
+ method: intent.request.method,
162
+ bodyHash: intent.request.bodyHash,
163
+ },
164
+ })),
165
+ };
166
+ })
167
+ .sort((a, b) => Date.parse(b.lastEventAt) - Date.parse(a.lastEventAt))
168
+ .slice(0, limit);
169
+
170
+ return {
171
+ sinceMs,
172
+ untilMs,
173
+ summary: {
174
+ providerCallCount: rows.length,
175
+ eventCount: rows.reduce((sum, row) => sum + row.events.length, 0),
176
+ dispatchIntentCount: rows.reduce(
177
+ (sum, row) => sum + row.dispatchIntents.length,
178
+ 0
179
+ ),
180
+ },
181
+ providerCalls: rows,
182
+ };
183
+ }
184
+
185
+ export function createProviderCallsRecentHandler({
186
+ store,
187
+ env = process.env,
188
+ nowMs,
189
+ }: {
190
+ store?: ProviderCallsRecentStore;
191
+ env?: Partial<ProviderCallsRecentEnv>;
192
+ nowMs?: number;
193
+ } = {}) {
194
+ return async function handleProviderCallsRecent(req: Request) {
195
+ const expectedSecret = String(env.BILLING_LEDGER_AUDIT_SECRET || "").trim();
196
+ if (!expectedSecret) {
197
+ return new Response("Not Found", { status: 404 });
198
+ }
199
+
200
+ const providedSecret =
201
+ req.headers.get("x-billing-ledger-audit-secret")?.trim() || "";
202
+ if (providedSecret !== expectedSecret) {
203
+ return json({ success: false, error: "Unauthorized" }, 401);
204
+ }
205
+
206
+ try {
207
+ const url = new URL(req.url);
208
+ const now = nowMs ?? Date.now();
209
+ const untilMs = parseOptionalTimestamp(url.searchParams.get("until")) ?? now;
210
+ const sinceMs =
211
+ parseOptionalTimestamp(url.searchParams.get("since")) ?? untilMs - 3600_000;
212
+ const report = await buildProviderCallsRecentReport({
213
+ store: store ?? (await resolveDefaultStore()),
214
+ sinceMs,
215
+ untilMs,
216
+ limit: parseLimit(url.searchParams.get("limit")),
217
+ dialogId: url.searchParams.get("dialogId")?.trim() || undefined,
218
+ provider: url.searchParams.get("provider")?.trim() || undefined,
219
+ model: url.searchParams.get("model")?.trim() || undefined,
220
+ });
221
+ return json({ success: true, report });
222
+ } catch (error) {
223
+ return json(
224
+ {
225
+ success: false,
226
+ error: error instanceof Error ? error.message : String(error),
227
+ },
228
+ 400
229
+ );
230
+ }
231
+ };
232
+ }
233
+
234
+ export const handleProviderCallsRecent = createProviderCallsRecentHandler();
@@ -0,0 +1,180 @@
1
+ import { createHash } from "node:crypto";
2
+ import {
3
+ createBillingAdminAuditEvent,
4
+ type BillingAdminAuditAction,
5
+ } from "../../ai/token/billingAdminAuditEvent";
6
+ import { writeBillingAdminAuditEvent } from "../../ai/token/billingAdminAuditEventWriter";
7
+ import type { NormalizedOfficialProviderBucket } from "../../ai/token/deepinfraReconciliation";
8
+ import { runProviderReconciliation } from "../../ai/token/providerReconciliationRunner";
9
+ import { ulid } from "ulid";
10
+
11
+ const JSON_HEADERS = {
12
+ "content-type": "application/json; charset=utf-8",
13
+ };
14
+
15
+ type ProviderReconciliationRunEnv = NodeJS.ProcessEnv & {
16
+ BILLING_LEDGER_AUDIT_SECRET?: string;
17
+ };
18
+
19
+ type ProviderReconciliationRunStore = Parameters<typeof runProviderReconciliation>[0]["store"];
20
+
21
+ const json = (body: unknown, status = 200) =>
22
+ new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });
23
+
24
+ const resolveDefaultStore = async (): Promise<ProviderReconciliationRunStore> => {
25
+ const dbModule = await import("../../database/server/db");
26
+ return dbModule.default as ProviderReconciliationRunStore;
27
+ };
28
+
29
+ const ALLOWED_PROVIDERS = new Set(["deepinfra", "openai"]);
30
+
31
+ const stableStringify = (value: unknown): string => {
32
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
33
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
34
+ const record = value as Record<string, unknown>;
35
+ return `{${Object.keys(record)
36
+ .sort()
37
+ .map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`)
38
+ .join(",")}}`;
39
+ };
40
+
41
+ const buildInputHash = (officialBuckets: NormalizedOfficialProviderBucket[]) =>
42
+ `sha256:${createHash("sha256")
43
+ .update(stableStringify(officialBuckets))
44
+ .digest("hex")}`;
45
+
46
+ const isOfficialBucket = (value: unknown): value is NormalizedOfficialProviderBucket => {
47
+ if (!value || typeof value !== "object") return false;
48
+ const bucket = value as NormalizedOfficialProviderBucket;
49
+ return (
50
+ typeof bucket.provider === "string" &&
51
+ typeof bucket.bucketStart === "string" &&
52
+ typeof bucket.bucketEnd === "string" &&
53
+ Boolean(bucket.official) &&
54
+ typeof bucket.official.rawProviderCostUsd === "number" &&
55
+ typeof bucket.official.inputTokens === "number" &&
56
+ typeof bucket.official.outputTokens === "number" &&
57
+ typeof bucket.official.requestCount === "number"
58
+ );
59
+ };
60
+
61
+ export function createProviderReconciliationRunHandler({
62
+ store,
63
+ env = process.env,
64
+ now = () => new Date().toISOString(),
65
+ createEventId = () => `evt_${ulid()}`,
66
+ }: {
67
+ store?: ProviderReconciliationRunStore;
68
+ env?: Partial<ProviderReconciliationRunEnv>;
69
+ now?: () => string;
70
+ createEventId?: () => string;
71
+ } = {}) {
72
+ return async function handleProviderReconciliationRun(req: Request) {
73
+ const expectedSecret = String(env.BILLING_LEDGER_AUDIT_SECRET || "").trim();
74
+ if (!expectedSecret) {
75
+ return new Response("Not Found", { status: 404 });
76
+ }
77
+
78
+ const providedSecret =
79
+ req.headers.get("x-billing-ledger-audit-secret")?.trim() || "";
80
+ if (providedSecret !== expectedSecret) {
81
+ return json({ success: false, error: "Unauthorized" }, 401);
82
+ }
83
+
84
+ if (req.method !== "POST") {
85
+ return json({ success: false, error: "Method Not Allowed" }, 405);
86
+ }
87
+
88
+ try {
89
+ const payload = await req.json();
90
+ const officialBuckets = Array.isArray(payload?.officialBuckets)
91
+ ? payload.officialBuckets
92
+ : [];
93
+ if (officialBuckets.length === 0) {
94
+ throw new Error("officialBuckets must be a non-empty array");
95
+ }
96
+ if (!officialBuckets.every(isOfficialBucket)) {
97
+ throw new Error("officialBuckets contains invalid bucket records");
98
+ }
99
+ const provider = typeof payload.provider === "string" ? payload.provider.trim() : "";
100
+ if (!provider || !ALLOWED_PROVIDERS.has(provider)) {
101
+ throw new Error("provider must be one of: deepinfra, openai");
102
+ }
103
+ if (!officialBuckets.every((bucket) => bucket.provider === provider)) {
104
+ throw new Error("officialBuckets provider must match provider");
105
+ }
106
+
107
+ const inputHash = buildInputHash(officialBuckets);
108
+ const targetStore = store ?? (await resolveDefaultStore());
109
+ const dryRun = payload.dryRun === true;
110
+ const createdAt = typeof payload.createdAt === "string" ? payload.createdAt : now();
111
+ const preview = await runProviderReconciliation({
112
+ store: targetStore,
113
+ officialBuckets,
114
+ createdAt,
115
+ dryRun: true,
116
+ });
117
+
118
+ if (!dryRun) {
119
+ if (payload.confirmCommit !== true) {
120
+ throw new Error("confirmCommit must be true for non-dry-run reconciliation");
121
+ }
122
+ if (payload.inputHash !== inputHash) {
123
+ throw new Error("inputHash must match the officialBuckets hash");
124
+ }
125
+ const maxRiskCredits = Number(payload.maxRiskCredits);
126
+ if (!Number.isFinite(maxRiskCredits) || maxRiskCredits < 0) {
127
+ throw new Error("maxRiskCredits must be a non-negative number");
128
+ }
129
+ if (preview.riskPlatformCreditsProposed > maxRiskCredits) {
130
+ throw new Error("maxRiskCredits is below projected reconciliation risk");
131
+ }
132
+ }
133
+
134
+ const result = dryRun
135
+ ? preview
136
+ : await runProviderReconciliation({
137
+ store: targetStore,
138
+ officialBuckets,
139
+ createdAt,
140
+ dryRun: false,
141
+ });
142
+ const action: BillingAdminAuditAction = dryRun
143
+ ? "reconciliation_dry_run"
144
+ : "reconciliation_committed";
145
+ await writeBillingAdminAuditEvent({
146
+ store: targetStore,
147
+ event: createBillingAdminAuditEvent({
148
+ eventId: createEventId(),
149
+ actorId:
150
+ typeof payload.actorId === "string" && payload.actorId.trim()
151
+ ? payload.actorId
152
+ : "billing-admin-api",
153
+ action,
154
+ anomalyId: "provider-reconciliation",
155
+ planId: `provider-reconciliation:${provider}`,
156
+ inputSetHash: inputHash,
157
+ createdAt,
158
+ reason: JSON.stringify({
159
+ provider,
160
+ dryRun,
161
+ bucketCount: officialBuckets.length,
162
+ riskPlatformCreditsProposed: preview.riskPlatformCreditsProposed,
163
+ }),
164
+ }),
165
+ });
166
+
167
+ return json({ success: true, inputHash, result });
168
+ } catch (error) {
169
+ return json(
170
+ {
171
+ success: false,
172
+ error: error instanceof Error ? error.message : String(error),
173
+ },
174
+ 400
175
+ );
176
+ }
177
+ };
178
+ }
179
+
180
+ export const handleProviderReconciliationRun = createProviderReconciliationRunHandler();