nolo-cli 0.1.30 → 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.
- package/agent-runtime/agentRecordConfig.ts +0 -2
- package/agent-runtime/hostAdapter.ts +0 -1
- package/agent-runtime/hostRuntimeCapabilities.ts +7 -0
- package/agent-runtime/hostRuntimeConfig.ts +86 -0
- package/agent-runtime/index.ts +13 -0
- package/agent-runtime/localToolPolicy.ts +13 -6
- package/agent-runtime/localWorkspaceTools.ts +333 -30
- package/agent-runtime/platformChatProvider.ts +4 -1
- package/agent-runtime/runtimeToolPolicy.ts +32 -47
- package/agent-runtime/shellCommandPolicy.ts +117 -0
- package/agent-runtime/toolGate.ts +38 -0
- package/agentRecordCommands.ts +1 -1
- package/agentRecordHelpers.ts +35 -20
- package/agentRunParsing.ts +18 -5
- package/agentRuntimeLocal.ts +10 -0
- package/ai/agent/agentRunDialogLineage.ts +56 -0
- package/ai/agent/agentSlice.ts +45 -10
- package/ai/agent/avatarUtils.ts +1 -1
- package/ai/agent/buildSystemPrompt.ts +1 -2
- package/ai/agent/cliExecutor.ts +330 -19
- package/ai/agent/createAgentSchema.ts +22 -0
- package/ai/agent/hooks/fetchPublicAgents.ts +14 -39
- package/ai/agent/hooks/usePublicAgents.ts +90 -192
- package/ai/agent/publicAgentCatalog.ts +359 -0
- package/ai/agent/publicAgentIdentity.ts +76 -0
- package/ai/agent/server/fetchPublicAgents.ts +21 -46
- package/ai/agent/serverOrigin.ts +7 -0
- package/ai/agent/streamAgentChatTurn.ts +23 -21
- package/ai/agent/streamAgentChatTurnUtils.ts +292 -6
- package/ai/agent/types.ts +2 -0
- package/ai/agent/web/agentDisplayUtils.ts +171 -0
- package/ai/agent/web/useAgentModelAvatarComponent.ts +32 -0
- package/ai/ai.locale.ts +8 -0
- package/ai/chat/sendOpenAICompletionsRequest.native.ts +15 -0
- package/ai/chat/sendOpenAICompletionsRequest.ts +93 -1
- package/ai/chat/sendOpenAIResponseRequest.ts +86 -9
- package/ai/chat/updateTotalUsage.ts +7 -0
- package/ai/llm/deepinfra.ts +30 -15
- package/ai/llm/mistral.ts +3 -4
- package/ai/llm/providers.ts +2 -0
- package/ai/llm/types.ts +15 -0
- package/ai/memory/capture.ts +3 -3
- package/ai/memory/consolidate.ts +2 -2
- package/ai/memory/delete.ts +4 -3
- package/ai/memory/query.ts +3 -3
- package/ai/memory/remember.ts +2 -2
- package/ai/memory/store.ts +3 -3
- package/ai/memory/storeShared.ts +3 -2
- package/ai/policy/commercialMultiplier.ts +16 -0
- package/ai/token/billingAdminAuditEvent.ts +68 -0
- package/ai/token/billingAdminAuditEventWriter.ts +41 -0
- package/ai/token/billingAnomaly.ts +90 -0
- package/ai/token/billingAnomalyLifecycle.ts +54 -0
- package/ai/token/billingAnomalyLifecycleWriter.ts +44 -0
- package/ai/token/billingAnomalyWriter.ts +41 -0
- package/ai/token/calculatePrice.ts +3 -2
- package/ai/token/deepinfraReconciliation.ts +153 -0
- package/ai/token/deepinfraRequestIdQuery.ts +92 -0
- package/ai/token/externalToolCost.ts +54 -41
- package/ai/token/missingUsageEstimate.ts +12 -3
- package/ai/token/normalizeUsage.ts +45 -5
- package/ai/token/openaiReconciliation.ts +188 -0
- package/ai/token/providerBillableEvent.ts +84 -0
- package/ai/token/providerBillableEventWriter.ts +36 -0
- package/ai/token/providerBillingAnomalyDrilldown.ts +308 -0
- package/ai/token/providerBillingDrilldown.ts +361 -0
- package/ai/token/providerBillingHealthReport.ts +366 -0
- package/ai/token/providerCall.ts +144 -0
- package/ai/token/providerCallSweeper.ts +168 -0
- package/ai/token/providerCallWriter.ts +33 -0
- package/ai/token/providerCredential.ts +89 -0
- package/ai/token/providerCredentialAnomaly.ts +154 -0
- package/ai/token/providerCredentialLifecycle.ts +59 -0
- package/ai/token/providerCredentialLifecycleWriter.ts +44 -0
- package/ai/token/providerCredentialRegistry.ts +83 -0
- package/ai/token/providerCredentialRegistryCommand.ts +97 -0
- package/ai/token/providerCredentialRegistryList.ts +124 -0
- package/ai/token/providerCredentialRegistryResolver.ts +150 -0
- package/ai/token/providerCredentialRegistryWriter.ts +41 -0
- package/ai/token/providerCredentialRotationCommand.ts +102 -0
- package/ai/token/providerCredentialRuntime.ts +56 -0
- package/ai/token/providerDispatchIntent.ts +67 -0
- package/ai/token/providerDispatchIntentWriter.ts +36 -0
- package/ai/token/providerGateway.ts +260 -0
- package/ai/token/providerReconciliation.ts +148 -0
- package/ai/token/providerReconciliationLocal.ts +97 -0
- package/ai/token/providerReconciliationRunner.ts +165 -0
- package/ai/token/providerReconciliationWriter.ts +41 -0
- package/ai/token/ratingResult.ts +202 -0
- package/ai/token/ratingResultWriter.ts +33 -0
- package/ai/token/serverDialogProjection.ts +5 -3
- package/ai/token/serverTokenWriter.ts +11 -3
- package/ai/token/types.ts +10 -0
- package/ai/tools/agent/callAgentTool.ts +3 -4
- package/ai/tools/agent/presets/appBuilderPreset.ts +5 -7
- package/ai/tools/agent/runStreamingAgentTool.ts +1 -2
- package/ai/tools/agent/streamParallelAgentsTool.ts +2 -3
- package/ai/tools/readXPostTool.ts +1 -5
- package/app/admin/adminPages.ts +9 -0
- package/app/i18n/i18n.config.ts +5 -0
- package/app/i18n/translations/pricing.locale.ts +397 -0
- package/app/utils/desktopAgentRuntimeStatusClient.ts +5 -4
- package/app/utils/desktopAgentRuntimeTurnClient.ts +4 -1
- package/app/utils/imageUtils.ts +64 -34
- package/auth/adminPermissions.ts +18 -0
- package/auth/authSlice.ts +26 -12
- package/auth/hooks/useFetchUsers.ts +3 -0
- package/auth/routes.ts +46 -0
- package/auth/server/accessActivity.ts +4 -3
- package/auth/server/adminPermissions.ts +43 -0
- package/auth/server/adminUsageReport.ts +375 -0
- package/auth/server/billingAnomalies.ts +235 -0
- package/auth/server/billingUsageReport.ts +41 -2
- package/auth/server/creatorEarningCreditConversion.ts +10 -2
- package/auth/server/deduct.ts +14 -7
- package/auth/server/delete.ts +10 -2
- package/auth/server/disable.ts +4 -3
- package/auth/server/emailAutomation.ts +7 -5
- package/auth/server/emailDbConfig.ts +4 -2
- package/auth/server/emailDelivery.ts +24 -20
- package/auth/server/emailDeliveryGuards.ts +10 -7
- package/auth/server/emailPreferences.ts +6 -4
- package/auth/server/emailReport.ts +6 -4
- package/auth/server/emailRuntimeConfig.ts +3 -3
- package/auth/server/emailScenarioNotifications.ts +9 -8
- package/auth/server/enable.ts +4 -3
- package/auth/server/getRechargeHistory.ts +3 -2
- package/auth/server/getUser.ts +3 -2
- package/auth/server/gptProAccess.ts +44 -0
- package/auth/server/inviteReward.ts +10 -7
- package/auth/server/listusers.ts +6 -4
- package/auth/server/login.ts +2 -2
- package/auth/server/productEntitlements.ts +7 -4
- package/auth/server/productPurchase.ts +10 -2
- package/auth/server/providerBillingDrilldown.ts +47 -0
- package/auth/server/providerBillingHealth.ts +71 -0
- package/auth/server/providerCredentials.ts +136 -0
- package/auth/server/recharge.ts +14 -8
- package/auth/server/revokeSessions.ts +4 -3
- package/auth/server/route.ts +77 -0
- package/auth/server/sendEmail.ts +5 -4
- package/auth/server/signup.ts +10 -3
- package/auth/server/token.ts +53 -55
- package/auth/server/tokenUsageBilling.ts +18 -7
- package/auth/server/usageManagementAccess.ts +43 -0
- package/auth/server/usageReport.ts +59 -0
- package/auth/types.ts +12 -0
- package/auth/utils.ts +24 -22
- package/authCommands.ts +36 -2
- package/buildPublish.ts +3 -1
- package/buildPublishArtifactAssembly.ts +62 -1
- package/buildPublishImportAnalysis.ts +21 -16
- package/chat/dialog/dialogLaunchScope.ts +32 -0
- package/chat/dialog/objectAssistantRegistry.ts +2 -2
- package/chat/dialog/useCreateDialog.ts +1 -1
- package/chat/hooks/useChatInput.ts +41 -10
- package/chat/messages/messageSlice.ts +5 -1
- package/chat/messages/pendingAttachmentParts.ts +28 -2
- package/chat/messages/sendFirstMessage.ts +76 -79
- package/chat/messages/types.ts +9 -0
- package/chat/messages/web/streamingMarkdownModel.ts +41 -0
- package/chat/messages/web/useStreamingReveal.ts +91 -0
- package/chat/web/messageInputAgentUi.ts +94 -6
- package/cliEnvHelpers.ts +8 -0
- package/cliRuntimeDoctorReport.ts +193 -0
- package/client/agentConfigResolver.test.ts +0 -2
- package/client/agentRun.test.ts +171 -10
- package/client/agentRun.ts +44 -637
- package/client/agentRunInput.ts +10 -0
- package/client/agentRunLocalExecutor.ts +179 -0
- package/client/agentRunServerTransport.ts +394 -0
- package/client/agentRunTaskRunRecorder.ts +176 -0
- package/client/localRuntimeAdapter.test.ts +236 -9
- package/client/localRuntimeAdapter.ts +221 -23
- package/client/localToolPolicy.test.ts +28 -4
- package/connector-experimental/daemonLauncher.ts +38 -4
- package/connectorRunArtifact.ts +34 -10
- package/connectorWebSocketTarget.ts +9 -5
- package/core/builtinAgents.ts +155 -11
- package/create/space/contentLabels.ts +1 -1
- package/create/space/contentTypeMeta.ts +3 -2
- package/create/space/sidebarVisibleTypes.ts +27 -0
- package/create/space/space.locale.ts +76 -4
- package/database/actions/agentReadResolution.ts +2 -8
- package/database/actions/read.ts +11 -9
- package/database/actions/readAndWait.ts +10 -5
- package/database/server/agentDelegation.ts +3 -2
- package/database/server/authorityStoreConformance.ts +209 -0
- package/database/server/authorityStoreTypes.ts +31 -0
- package/database/server/coreDataProxy.ts +1 -1
- package/database/server/dataHandlers.ts +13 -5
- package/database/server/db.ts +15 -34
- package/database/server/delete.ts +88 -71
- package/database/server/emailRepository.ts +11 -9
- package/database/server/fileService.ts +2 -1
- package/database/server/legacyServerDb.ts +58 -0
- package/database/server/levelAuthorityStore.ts +75 -0
- package/database/server/memoryAuthorityStore.ts +133 -0
- package/database/server/patch.ts +13 -12
- package/database/server/query.ts +3 -2
- package/database/server/read.ts +33 -30
- package/database/server/resourceAccess.ts +7 -5
- package/database/server/serverStoreFactory.ts +124 -0
- package/database/server/spaceMemberAuthority.ts +3 -2
- package/database/server/storeBatchCompat.ts +37 -0
- package/database/server/testAuthorityStore.ts +76 -0
- package/database/server/write.ts +29 -27
- package/integrations/anthropic/anthropicModels.ts +12 -12
- package/integrations/deepseek/models.ts +67 -67
- package/integrations/google/models.ts +111 -53
- package/integrations/openai/models.ts +22 -22
- package/integrations/xai/models.ts +1 -1
- package/localRuntimeDb.ts +39 -2
- package/machineCommandPrompts.ts +2 -0
- package/machineCommands.ts +193 -63
- package/machineWsRunDispatch.ts +80 -15
- package/machineWsSession.ts +39 -2
- package/noloReadBridgePrompt.ts +16 -0
- package/package.json +99 -6
- package/render/layout/mainLayoutViewMode.ts +25 -0
- package/render/page/server/createPage.ts +3 -1
- package/render/page/server/handleCreatePage.ts +2 -11
- package/runtimeDoctorCommands.ts +15 -66
- package/server/api/methods.ts +34 -12
- package/server/api/tableHandlers.ts +6 -3
- package/server/authenticateToken.ts +47 -2
- package/server/billingLedgerRoutes.ts +15 -0
- package/server/buildManifest.ts +54 -0
- package/server/coreReadiness.ts +34 -25
- package/server/coreRuntime.ts +15 -10
- package/server/handlers/activityStatsHandler.ts +5 -2
- package/server/handlers/agentEmailRegistrationE2EHandler.ts +25 -23
- package/server/handlers/agentRun/agentLookup.ts +1 -7
- package/server/handlers/agentRun/autonomousRuntime.ts +11 -10
- package/server/handlers/agentRun/builtinAgents.ts +12 -88
- package/server/handlers/agentRun/continueDialogContext.ts +15 -3
- package/server/handlers/agentRun/{inheritedDialogPrompt.ts → conversationReference.ts} +3 -3
- package/server/handlers/agentRun/dialogLookup.ts +4 -3
- package/server/handlers/agentRun/index.ts +864 -404
- package/server/handlers/agentRun/localRuntimeBootstrap.ts +17 -1
- package/server/handlers/agentRun/loop.ts +920 -508
- package/server/handlers/agentRun/machineConnector.ts +56 -8
- package/server/handlers/agentRun/machineRunAudit.ts +3 -2
- package/server/handlers/agentRun/modelUsageToolHandlers.ts +13 -10
- package/server/handlers/agentRun/requestContext.ts +12 -8
- package/server/handlers/agentRun/runtimeExecutionContext.ts +15 -3
- package/server/handlers/agentRun/runtimePreparation.ts +26 -24
- package/server/handlers/agentRun/runtimeRouting.ts +25 -40
- package/server/handlers/agentRun/runtimeSystemMessages.ts +65 -0
- package/server/handlers/agentRun/saveDialog.ts +97 -87
- package/server/handlers/agentRun/taskRunToolHandler.ts +9 -7
- package/server/handlers/agentRun/toolExecutor.ts +42 -78
- package/server/handlers/agentRun/types.ts +2 -1
- package/server/handlers/appDeployStatusStore.ts +17 -10
- package/server/handlers/appDomainHandler.ts +21 -15
- package/server/handlers/appLegacyInfraCleanup.ts +5 -2
- package/server/handlers/appSandboxHandler.ts +29 -8
- package/server/handlers/appSpaceAccess.ts +15 -8
- package/server/handlers/chatHandler.ts +22 -2
- package/server/handlers/chatUpstreamRetry.ts +225 -2
- package/server/handlers/connector/connectorConnectionRegistry.ts +55 -7
- package/server/handlers/connector/connectorWebSocket.ts +14 -10
- package/server/handlers/desktopAgentRuntimeAdapter.ts +4 -4
- package/server/handlers/desktopAgentRuntimeHostCapabilities.ts +25 -0
- package/server/handlers/desktopAgentRuntimeReadiness.ts +62 -0
- package/server/handlers/desktopAgentRuntimeStatusHandler.ts +38 -30
- package/server/handlers/desktopAgentRuntimeTurnHandler.ts +7 -3
- package/server/handlers/desktopAgentRuntimeTurnService.ts +39 -45
- package/server/handlers/desktopLlamaRuntimeHandler.ts +85 -51
- package/server/handlers/desktopUpdaterHandler.ts +132 -24
- package/server/handlers/favoriteHandlers.ts +8 -2
- package/server/handlers/getDialogBillingHandler.ts +4 -3
- package/server/handlers/getTransactionsHandler.ts +5 -2
- package/server/handlers/machines/machineBinding.ts +1 -0
- package/server/handlers/machines/machineHandlers.ts +0 -14
- package/server/handlers/machines/machineInstallAssets.ts +4 -2
- package/server/handlers/notificationEmitter.ts +5 -3
- package/server/handlers/notificationsHandler.ts +5 -2
- package/server/handlers/providerCallsRecentHandler.ts +234 -0
- package/server/handlers/providerReconciliationRunHandler.ts +180 -0
- package/server/handlers/providerRequestIdsHandler.ts +105 -0
- package/server/handlers/tableAccess.ts +6 -2
- package/server/handlers/tableToolHandlers.ts +28 -14
- package/server/handlers/userSecretsHandler.ts +17 -6
- package/server/handlers/versionHandler.ts +9 -4
- package/server/handlers/versionStore.ts +18 -10
- package/server/html/ssrPreload.ts +5 -3
- package/server/payments/crypto/cryptoUsdcBasePaymentProvider.ts +11 -8
- package/server/payments/crypto/cryptoUsdcBaseScanner.ts +12 -7
- package/server/payments/crypto/cryptoUsdtTronPaymentProvider.ts +11 -8
- package/server/payments/crypto/cryptoUsdtTronScanner.ts +9 -7
- package/server/payments/waffo/waffoPaymentProvider.ts +12 -9
- package/server/runtimeRole.ts +15 -0
- package/server/scheduler/scheduledTaskRuntime.ts +4 -2
- package/server/scheduler/schedulerService.ts +2 -2
- package/server/taskRunBridgeRoutes.ts +8 -5
- package/share/server/fetchCommunityShares.ts +1 -1
- package/share/server/helpers.ts +19 -17
- package/share/server/importShare.ts +9 -13
- package/share/server/listCommunityShares.ts +4 -4
- package/share/server/purchaseDoc.ts +8 -16
- package/share/server/readCommunityShareCover.ts +3 -2
- package/share/server/readSharedTable.ts +14 -13
- package/share/server/tableReplication.ts +42 -39
- package/spaceAttachCommands.ts +135 -0
- package/spaceInternalCommandEntries.ts +2 -0
- package/ai/agent/runtimeServerBase.ts +0 -37
- package/server/handlers/desktopAgentRuntimeHostFacts.ts +0 -40
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ulid } from "ulid";
|
|
2
|
-
import
|
|
2
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
3
3
|
import { DB_PREFIX } from "../../database/keys";
|
|
4
4
|
import {
|
|
5
5
|
emailProviderSupportsMarketingBroadcast,
|
|
@@ -120,9 +120,9 @@ const hasUniformBatchContent = (payloads: ManagedEmailPayload[]) => {
|
|
|
120
120
|
};
|
|
121
121
|
|
|
122
122
|
const readMarketingSegmentMembers = async (segmentId: string) => {
|
|
123
|
-
const raw = (await
|
|
124
|
-
|
|
125
|
-
| null;
|
|
123
|
+
const raw = (await getServerAuthorityStore()
|
|
124
|
+
.get(getMarketingSegmentMembersKey(segmentId))
|
|
125
|
+
.catch(() => null)) as { emails?: unknown } | null;
|
|
126
126
|
if (!raw || !Array.isArray(raw.emails)) return [];
|
|
127
127
|
return Array.from(
|
|
128
128
|
new Set(
|
|
@@ -137,7 +137,7 @@ const writeMarketingSegmentMembers = async (segmentId: string, emails: string[])
|
|
|
137
137
|
const normalizedEmails = Array.from(
|
|
138
138
|
new Set(emails.map((email) => normalizeEmailAddress(email)).filter(Boolean))
|
|
139
139
|
);
|
|
140
|
-
await
|
|
140
|
+
await getServerAuthorityStore().put(getMarketingSegmentMembersKey(segmentId), {
|
|
141
141
|
emails: normalizedEmails,
|
|
142
142
|
updatedAt: Date.now(),
|
|
143
143
|
});
|
|
@@ -226,13 +226,14 @@ const incrementStats = async (
|
|
|
226
226
|
) => {
|
|
227
227
|
const statsKey = getStatsKey(dayKey, tag);
|
|
228
228
|
const statsLock = balanceLockManager.getLock(`email-stats:${statsKey}`);
|
|
229
|
+
const store = getServerAuthorityStore();
|
|
229
230
|
await statsLock.runExclusive(async () => {
|
|
230
|
-
const currentRaw = await
|
|
231
|
+
const currentRaw = await store.get(statsKey).catch(() => null);
|
|
231
232
|
const current =
|
|
232
233
|
currentRaw && typeof currentRaw === "object" && !Array.isArray(currentRaw)
|
|
233
234
|
? (currentRaw as Record<string, any>)
|
|
234
235
|
: {};
|
|
235
|
-
await
|
|
236
|
+
await store.put(statsKey, {
|
|
236
237
|
...current,
|
|
237
238
|
dayKey,
|
|
238
239
|
tag,
|
|
@@ -246,21 +247,22 @@ const incrementStats = async (
|
|
|
246
247
|
};
|
|
247
248
|
|
|
248
249
|
const writeDeliveryRecord = async (record: EmailDeliveryRecord) => {
|
|
249
|
-
await
|
|
250
|
+
await getServerAuthorityStore().put(`${EMAIL_RECORD_PREFIX}${record.id}`, record);
|
|
250
251
|
};
|
|
251
252
|
|
|
252
253
|
const enqueueRetryJob = async (job: RetryJob) => {
|
|
253
|
-
await
|
|
254
|
+
await getServerAuthorityStore().put(getRetryKey(job.nextRetryAt, job.retryId), job);
|
|
254
255
|
await incrementStats(getDayKey(job.updatedAt), job.payload.tag, { queued: 1 });
|
|
255
256
|
};
|
|
256
257
|
|
|
257
258
|
const markWelcomeEmailSent = async (userId: string, sentAt: number) => {
|
|
258
259
|
const lock = balanceLockManager.getLock(userId);
|
|
260
|
+
const store = getServerAuthorityStore();
|
|
259
261
|
await lock.runExclusive(async () => {
|
|
260
262
|
const key = `${DB_PREFIX.USER}${userId}`;
|
|
261
|
-
const current = await
|
|
263
|
+
const current = await store.get(key).catch(() => null);
|
|
262
264
|
if (!current || typeof current !== "object") return;
|
|
263
|
-
await
|
|
265
|
+
await store.put(key, {
|
|
264
266
|
...current,
|
|
265
267
|
welcomeEmailSentAt: sentAt,
|
|
266
268
|
});
|
|
@@ -745,8 +747,9 @@ export async function processEmailRetryQueue() {
|
|
|
745
747
|
const retryConfig = getRetryConfig();
|
|
746
748
|
const now = Date.now();
|
|
747
749
|
const jobs: Array<{ key: string; job: RetryJob }> = [];
|
|
750
|
+
const store = getServerAuthorityStore();
|
|
748
751
|
|
|
749
|
-
const iter =
|
|
752
|
+
const iter = store.iterator({
|
|
750
753
|
gt: EMAIL_RETRY_PREFIX,
|
|
751
754
|
lt: `${EMAIL_RETRY_PREFIX}\xFF`,
|
|
752
755
|
});
|
|
@@ -760,7 +763,7 @@ export async function processEmailRetryQueue() {
|
|
|
760
763
|
if (jobs.length >= retryConfig.retryBatchSize) break;
|
|
761
764
|
}
|
|
762
765
|
} finally {
|
|
763
|
-
await iter.close();
|
|
766
|
+
await (iter as any).close?.();
|
|
764
767
|
}
|
|
765
768
|
|
|
766
769
|
let retried = 0;
|
|
@@ -768,7 +771,7 @@ export async function processEmailRetryQueue() {
|
|
|
768
771
|
let failed = 0;
|
|
769
772
|
|
|
770
773
|
for (const item of jobs) {
|
|
771
|
-
await
|
|
774
|
+
await store.del(item.key).catch(() => undefined);
|
|
772
775
|
const result = await sendManagedEmail(item.job.payload, {
|
|
773
776
|
attempt: item.job.attempt + 1,
|
|
774
777
|
maxAttempts: item.job.maxAttempts,
|
|
@@ -835,7 +838,7 @@ export function stopEmailRetryScheduler() {
|
|
|
835
838
|
|
|
836
839
|
const listPendingRetryCount = async () => {
|
|
837
840
|
let count = 0;
|
|
838
|
-
const iter =
|
|
841
|
+
const iter = getServerAuthorityStore().iterator({
|
|
839
842
|
gt: EMAIL_RETRY_PREFIX,
|
|
840
843
|
lt: `${EMAIL_RETRY_PREFIX}\xFF`,
|
|
841
844
|
});
|
|
@@ -844,7 +847,7 @@ const listPendingRetryCount = async () => {
|
|
|
844
847
|
count += 1;
|
|
845
848
|
}
|
|
846
849
|
} finally {
|
|
847
|
-
await iter.close();
|
|
850
|
+
await (iter as any).close?.();
|
|
848
851
|
}
|
|
849
852
|
return count;
|
|
850
853
|
};
|
|
@@ -870,8 +873,9 @@ export async function getEmailDeliveryReport(days: number = 7, recentLimit: numb
|
|
|
870
873
|
retried: number;
|
|
871
874
|
queued: number;
|
|
872
875
|
}> = [];
|
|
876
|
+
const store = getServerAuthorityStore();
|
|
873
877
|
|
|
874
|
-
const statsIter =
|
|
878
|
+
const statsIter = store.iterator({
|
|
875
879
|
gt: EMAIL_STATS_PREFIX,
|
|
876
880
|
lt: `${EMAIL_STATS_PREFIX}\xFF`,
|
|
877
881
|
});
|
|
@@ -891,7 +895,7 @@ export async function getEmailDeliveryReport(days: number = 7, recentLimit: numb
|
|
|
891
895
|
});
|
|
892
896
|
}
|
|
893
897
|
} finally {
|
|
894
|
-
await statsIter.close();
|
|
898
|
+
await (statsIter as any).close?.();
|
|
895
899
|
}
|
|
896
900
|
|
|
897
901
|
stats.sort((a, b) =>
|
|
@@ -911,7 +915,7 @@ export async function getEmailDeliveryReport(days: number = 7, recentLimit: numb
|
|
|
911
915
|
|
|
912
916
|
const recent: EmailDeliveryRecord[] = [];
|
|
913
917
|
const recentFailures: EmailDeliveryRecord[] = [];
|
|
914
|
-
const recordIter =
|
|
918
|
+
const recordIter = store.iterator({
|
|
915
919
|
gt: EMAIL_RECORD_PREFIX,
|
|
916
920
|
lt: `${EMAIL_RECORD_PREFIX}\xFF`,
|
|
917
921
|
reverse: true,
|
|
@@ -941,7 +945,7 @@ export async function getEmailDeliveryReport(days: number = 7, recentLimit: numb
|
|
|
941
945
|
}
|
|
942
946
|
}
|
|
943
947
|
} finally {
|
|
944
|
-
await recordIter.close();
|
|
948
|
+
await (recordIter as any).close?.();
|
|
945
949
|
}
|
|
946
950
|
|
|
947
951
|
const pendingRetryCount = await listPendingRetryCount();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import
|
|
2
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
3
3
|
import { balanceLockManager } from "./locks";
|
|
4
4
|
import { shouldRunSchedulerOnThisInstance } from "./emailAutomationConfig";
|
|
5
5
|
|
|
@@ -192,6 +192,7 @@ export const reserveIdempotency = async (
|
|
|
192
192
|
const idempotencyKey = built.key;
|
|
193
193
|
const lock = balanceLockManager.getLock(getIdempotencyLockKey(idempotencyKey));
|
|
194
194
|
const pendingTtlMs = getIdempotencyPendingTtlMs();
|
|
195
|
+
const store = getServerAuthorityStore();
|
|
195
196
|
|
|
196
197
|
let decision:
|
|
197
198
|
| { allowed: true; reservation: EmailIdempotencyReservation | null }
|
|
@@ -201,7 +202,7 @@ export const reserveIdempotency = async (
|
|
|
201
202
|
};
|
|
202
203
|
|
|
203
204
|
await lock.runExclusive(async () => {
|
|
204
|
-
const existing = (await
|
|
205
|
+
const existing = (await store.get(idempotencyKey).catch(() => null)) as
|
|
205
206
|
| EmailIdempotencyRecord
|
|
206
207
|
| null;
|
|
207
208
|
|
|
@@ -222,7 +223,7 @@ export const reserveIdempotency = async (
|
|
|
222
223
|
? Math.max(built.expireAt, pendingExpireAt)
|
|
223
224
|
: pendingExpireAt;
|
|
224
225
|
|
|
225
|
-
await
|
|
226
|
+
await store.put(idempotencyKey, {
|
|
226
227
|
status: "pending",
|
|
227
228
|
createdAt: Number(existing?.createdAt || now),
|
|
228
229
|
updatedAt: now,
|
|
@@ -251,13 +252,14 @@ export const confirmIdempotencySent = async (
|
|
|
251
252
|
if (!reservation) return;
|
|
252
253
|
const lock = balanceLockManager.getLock(getIdempotencyLockKey(reservation.key));
|
|
253
254
|
const now = Date.now();
|
|
255
|
+
const store = getServerAuthorityStore();
|
|
254
256
|
|
|
255
257
|
await lock.runExclusive(async () => {
|
|
256
|
-
const current = (await
|
|
258
|
+
const current = (await store.get(reservation.key).catch(() => null)) as
|
|
257
259
|
| EmailIdempotencyRecord
|
|
258
260
|
| null;
|
|
259
261
|
if (!current) return;
|
|
260
|
-
await
|
|
262
|
+
await store.put(reservation.key, {
|
|
261
263
|
...current,
|
|
262
264
|
status: "sent",
|
|
263
265
|
updatedAt: now,
|
|
@@ -271,12 +273,13 @@ export const releaseIdempotency = async (
|
|
|
271
273
|
) => {
|
|
272
274
|
if (!reservation) return;
|
|
273
275
|
const lock = balanceLockManager.getLock(getIdempotencyLockKey(reservation.key));
|
|
276
|
+
const store = getServerAuthorityStore();
|
|
274
277
|
await lock.runExclusive(async () => {
|
|
275
|
-
const current = (await
|
|
278
|
+
const current = (await store.get(reservation.key).catch(() => null)) as
|
|
276
279
|
| EmailIdempotencyRecord
|
|
277
280
|
| null;
|
|
278
281
|
if (current?.status === "pending") {
|
|
279
|
-
await
|
|
282
|
+
await store.del(reservation.key).catch(() => undefined);
|
|
280
283
|
}
|
|
281
284
|
});
|
|
282
285
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
2
2
|
import { DB_PREFIX } from "../../database/keys";
|
|
3
3
|
import {
|
|
4
4
|
createErrorResponse,
|
|
@@ -33,6 +33,7 @@ const getEmailPreferencePayload = (userData: any) => ({
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
export async function handleGetEmailPreferences(req: Request) {
|
|
36
|
+
const store = getServerAuthorityStore();
|
|
36
37
|
if (req.method === "OPTIONS") {
|
|
37
38
|
return handleOptionsRequest();
|
|
38
39
|
}
|
|
@@ -43,7 +44,7 @@ export async function handleGetEmailPreferences(req: Request) {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
const key = `${USER_PREFIX}${user.userId}`;
|
|
46
|
-
const userData = await
|
|
47
|
+
const userData = await store.get(key).catch(() => null);
|
|
47
48
|
if (!userData) {
|
|
48
49
|
return createErrorResponse("User not found", 404);
|
|
49
50
|
}
|
|
@@ -52,6 +53,7 @@ export async function handleGetEmailPreferences(req: Request) {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export async function handleUpdateEmailPreferences(req: Request) {
|
|
56
|
+
const store = getServerAuthorityStore();
|
|
55
57
|
if (req.method === "OPTIONS") {
|
|
56
58
|
return handleOptionsRequest();
|
|
57
59
|
}
|
|
@@ -92,12 +94,12 @@ export async function handleUpdateEmailPreferences(req: Request) {
|
|
|
92
94
|
let nextUser: any;
|
|
93
95
|
try {
|
|
94
96
|
await lock.runExclusive(async () => {
|
|
95
|
-
const current = await
|
|
97
|
+
const current = await store.get(key).catch(() => null);
|
|
96
98
|
if (!current) {
|
|
97
99
|
throw new Error("User not found");
|
|
98
100
|
}
|
|
99
101
|
nextUser = { ...current, ...updates };
|
|
100
|
-
await
|
|
102
|
+
await store.put(key, nextUser);
|
|
101
103
|
});
|
|
102
104
|
} catch (error: any) {
|
|
103
105
|
if (error?.message === "User not found") {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DB_PREFIX } from "../../database/keys";
|
|
2
|
-
import
|
|
2
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
3
3
|
import {
|
|
4
4
|
checkAdminPermission,
|
|
5
5
|
createErrorResponse,
|
|
@@ -161,12 +161,13 @@ const buildReplayUserPatch = (
|
|
|
161
161
|
const markReplayDeliveryByTag = async (userId: string, tag: string, deliveredAt: number) => {
|
|
162
162
|
const key = `${DB_PREFIX.USER}${userId}`;
|
|
163
163
|
const lock = balanceLockManager.getLock(userId);
|
|
164
|
+
const store = getServerAuthorityStore();
|
|
164
165
|
await lock.runExclusive(async () => {
|
|
165
|
-
const user = (await
|
|
166
|
+
const user = (await store.get(key).catch(() => null)) as UserEmailRecord | null;
|
|
166
167
|
if (!user || typeof user !== "object") return;
|
|
167
168
|
const patch = buildReplayUserPatch(tag, user, deliveredAt);
|
|
168
169
|
if (!patch) return;
|
|
169
|
-
await
|
|
170
|
+
await store.put(key, {
|
|
170
171
|
...user,
|
|
171
172
|
...patch,
|
|
172
173
|
});
|
|
@@ -243,6 +244,7 @@ export async function handleReplayFailedAutomationEmails(req: Request) {
|
|
|
243
244
|
)
|
|
244
245
|
: null;
|
|
245
246
|
const report = await getEmailDeliveryReport(days, recentLimit);
|
|
247
|
+
const store = getServerAuthorityStore();
|
|
246
248
|
const config = getReengagementConfig();
|
|
247
249
|
const broadcastBatchSize = Math.min(
|
|
248
250
|
100,
|
|
@@ -326,7 +328,7 @@ export async function handleReplayFailedAutomationEmails(req: Request) {
|
|
|
326
328
|
continue;
|
|
327
329
|
}
|
|
328
330
|
|
|
329
|
-
const userRecord = (await
|
|
331
|
+
const userRecord = (await store.get(`${DB_PREFIX.USER}${userId}`).catch(() => null)) as
|
|
330
332
|
| UserEmailRecord
|
|
331
333
|
| null;
|
|
332
334
|
if (!userRecord || typeof userRecord !== "object") {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
2
2
|
import {
|
|
3
3
|
checkAdminPermission,
|
|
4
4
|
createErrorResponse,
|
|
@@ -46,6 +46,7 @@ export async function handleGetEmailRuntimeConfig(req: Request) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export async function handleUpdateEmailRuntimeConfig(req: Request) {
|
|
49
|
+
const store = getServerAuthorityStore();
|
|
49
50
|
if (req.method === "OPTIONS") return handleOptionsRequest();
|
|
50
51
|
|
|
51
52
|
const user = (req as any).user;
|
|
@@ -73,7 +74,7 @@ export async function handleUpdateEmailRuntimeConfig(req: Request) {
|
|
|
73
74
|
next[key] = value;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
await
|
|
77
|
+
await store.put(EMAIL_RUNTIME_CONFIG_KEY, next);
|
|
77
78
|
const { appliedKeys } = await applyEmailRuntimeConfigFromDb();
|
|
78
79
|
|
|
79
80
|
return createSuccessResponse({
|
|
@@ -83,4 +84,3 @@ export async function handleUpdateEmailRuntimeConfig(req: Request) {
|
|
|
83
84
|
appliedKeys,
|
|
84
85
|
});
|
|
85
86
|
}
|
|
86
|
-
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ulid } from "ulid";
|
|
2
|
-
import
|
|
2
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
3
3
|
import { DB_PREFIX } from "../../database/keys";
|
|
4
4
|
import { canSendEmailToUser } from "./emailPolicy";
|
|
5
5
|
import { sendManagedEmail } from "./emailDelivery";
|
|
@@ -84,7 +84,7 @@ const joinPublicUrl = (baseUrl: string, path: string) => {
|
|
|
84
84
|
const getUserById = async (userId: string): Promise<NotificationUserRecord | null> => {
|
|
85
85
|
if (!userId) return null;
|
|
86
86
|
const key = `${DB_PREFIX.USER}${userId}`;
|
|
87
|
-
const user = await
|
|
87
|
+
const user = await getServerAuthorityStore().get(key).catch(() => null);
|
|
88
88
|
if (!user || typeof user !== "object") return null;
|
|
89
89
|
return user as NotificationUserRecord;
|
|
90
90
|
};
|
|
@@ -222,7 +222,7 @@ export async function clearTodayLoginFailureCounter(userId: string) {
|
|
|
222
222
|
if (!userId) return;
|
|
223
223
|
const dayKey = getDayKey();
|
|
224
224
|
const countKey = `${LOGIN_FAIL_KEY_PREFIX}${userId}:${dayKey}`;
|
|
225
|
-
await
|
|
225
|
+
await getServerAuthorityStore().del(countKey).catch(() => undefined);
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
export async function recordLoginFailureAndMaybeNotify(params: {
|
|
@@ -237,17 +237,18 @@ export async function recordLoginFailureAndMaybeNotify(params: {
|
|
|
237
237
|
const dayKey = getDayKey(now);
|
|
238
238
|
const countKey = `${LOGIN_FAIL_KEY_PREFIX}${params.userId}:${dayKey}`;
|
|
239
239
|
const lock = balanceLockManager.getLock(`login-fail:${params.userId}:${dayKey}`);
|
|
240
|
+
const store = getServerAuthorityStore();
|
|
240
241
|
|
|
241
242
|
let shouldNotify = false;
|
|
242
243
|
let failCount = 0;
|
|
243
244
|
|
|
244
245
|
await lock.runExclusive(async () => {
|
|
245
|
-
const currentCount = Number((await
|
|
246
|
+
const currentCount = Number((await store.get(countKey).catch(() => 0)) || 0);
|
|
246
247
|
failCount = currentCount + 1;
|
|
247
|
-
await
|
|
248
|
+
await store.put(countKey, failCount);
|
|
248
249
|
|
|
249
250
|
const alertDayKey = getDayKey(now - (securityConfig.alertCooldownDays - 1) * DAY_MS);
|
|
250
|
-
const alertIter =
|
|
251
|
+
const alertIter = store.iterator({
|
|
251
252
|
gt: `${LOGIN_ALERT_KEY_PREFIX}${params.userId}:${alertDayKey}`,
|
|
252
253
|
lt: `${LOGIN_ALERT_KEY_PREFIX}${params.userId}:\xFF`,
|
|
253
254
|
reverse: true,
|
|
@@ -260,12 +261,12 @@ export async function recordLoginFailureAndMaybeNotify(params: {
|
|
|
260
261
|
break;
|
|
261
262
|
}
|
|
262
263
|
} finally {
|
|
263
|
-
await alertIter.close();
|
|
264
|
+
await (alertIter as any).close?.();
|
|
264
265
|
}
|
|
265
266
|
|
|
266
267
|
if (failCount >= securityConfig.failThreshold && !alreadyNotified) {
|
|
267
268
|
const alertKey = `${LOGIN_ALERT_KEY_PREFIX}${params.userId}:${dayKey}:${ulid(now)}`;
|
|
268
|
-
await
|
|
269
|
+
await store.put(alertKey, {
|
|
269
270
|
userId: params.userId,
|
|
270
271
|
dayKey,
|
|
271
272
|
failCount,
|
package/auth/server/enable.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// auth/server/enable.ts
|
|
2
|
-
import
|
|
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 enableUser(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
|
|
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 enableUser(userId: string) {
|
|
|
26
27
|
isDisabled: false,
|
|
27
28
|
enabledAt: new Date().toISOString(), // 记录启用时间,可选
|
|
28
29
|
};
|
|
29
|
-
await
|
|
30
|
+
await store.put(userKey, updatedUserData);
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { authenticateRequest } from "../utils";
|
|
4
4
|
import { createTransactionKey } from "../../database/keys";
|
|
5
|
-
import
|
|
5
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
6
6
|
import {
|
|
7
7
|
checkAdminPermission,
|
|
8
8
|
createErrorResponse,
|
|
@@ -18,6 +18,7 @@ export const handleGetRechargeHistory = async (
|
|
|
18
18
|
req: Request,
|
|
19
19
|
params?: { userId?: string }
|
|
20
20
|
) => {
|
|
21
|
+
const store = getServerAuthorityStore();
|
|
21
22
|
try {
|
|
22
23
|
// Step 1: Authenticate request
|
|
23
24
|
const authResult = await authenticateRequest(req);
|
|
@@ -59,7 +60,7 @@ export const handleGetRechargeHistory = async (
|
|
|
59
60
|
|
|
60
61
|
// Step 6: Query database and filter for recharge records. Transaction keys
|
|
61
62
|
// are keyed by txId, so sort by persisted timestamp instead of key order.
|
|
62
|
-
const iterator =
|
|
63
|
+
const iterator = store.iterator(queryOptions);
|
|
63
64
|
const records = [];
|
|
64
65
|
|
|
65
66
|
for await (const [, value] of iterator) {
|
package/auth/server/getUser.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// auth/server/getUser.ts
|
|
2
|
-
import
|
|
2
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
3
3
|
import {
|
|
4
4
|
createErrorResponse,
|
|
5
5
|
createSuccessResponse,
|
|
@@ -27,10 +27,11 @@ function canViewUserProfile(
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export async function getUser(userId: string): Promise<User | null> {
|
|
30
|
+
const store = getServerAuthorityStore();
|
|
30
31
|
const key = `${DB_PREFIX.USER}${userId}`;
|
|
31
32
|
|
|
32
33
|
try {
|
|
33
|
-
const userData = await
|
|
34
|
+
const userData = await store.get(key);
|
|
34
35
|
if (!userData) return null;
|
|
35
36
|
|
|
36
37
|
return {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const GPT_PRO_REQUIRED_BALANCE = 199;
|
|
2
|
+
|
|
3
|
+
const isOpenAiProModel = (normalizedProvider: string, normalizedModel: string): boolean =>
|
|
4
|
+
normalizedProvider === "openai" &&
|
|
5
|
+
/^gpt-[a-z0-9.]+-pro(?:-|$)/.test(normalizedModel);
|
|
6
|
+
|
|
7
|
+
const isClaudeOpusModel = (normalizedProvider: string, normalizedModel: string): boolean =>
|
|
8
|
+
normalizedProvider === "deepinfra" &&
|
|
9
|
+
normalizedModel === "anthropic/claude-opus-4-7";
|
|
10
|
+
|
|
11
|
+
export function isGptProModel(provider: unknown, model: unknown): boolean {
|
|
12
|
+
const normalizedProvider = String(provider || "").trim().toLowerCase();
|
|
13
|
+
const normalizedModel = String(model || "").trim().toLowerCase();
|
|
14
|
+
return (
|
|
15
|
+
isOpenAiProModel(normalizedProvider, normalizedModel) ||
|
|
16
|
+
isClaudeOpusModel(normalizedProvider, normalizedModel)
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function hasGptProBalance(balance: unknown): boolean {
|
|
21
|
+
const numericAmount = Number(balance);
|
|
22
|
+
return (
|
|
23
|
+
Number.isFinite(numericAmount) &&
|
|
24
|
+
numericAmount >= GPT_PRO_REQUIRED_BALANCE
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function hasGptProTierAccess({
|
|
29
|
+
userData,
|
|
30
|
+
}: {
|
|
31
|
+
userData: unknown;
|
|
32
|
+
}):
|
|
33
|
+
| {
|
|
34
|
+
allowed: true;
|
|
35
|
+
source: "balance";
|
|
36
|
+
balance: number;
|
|
37
|
+
}
|
|
38
|
+
| { allowed: false }
|
|
39
|
+
{
|
|
40
|
+
const balance = Number((userData as any)?.balance);
|
|
41
|
+
return hasGptProBalance(balance)
|
|
42
|
+
? { allowed: true, source: "balance", balance }
|
|
43
|
+
: { allowed: false };
|
|
44
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
2
2
|
import { DB_PREFIX } from "../../database/keys";
|
|
3
3
|
import { rechargeUserBalance } from "../server/recharge";
|
|
4
4
|
import { balanceLockManager } from "./locks";
|
|
@@ -107,7 +107,9 @@ async function getInviteRewardEmailState(
|
|
|
107
107
|
): Promise<InviteRewardEmailState | null> {
|
|
108
108
|
try {
|
|
109
109
|
return normalizeInviteRewardEmailState(
|
|
110
|
-
await
|
|
110
|
+
await getServerAuthorityStore().get(
|
|
111
|
+
getInviteRewardEmailStateKey(inviterId, inviteeUserId)
|
|
112
|
+
)
|
|
111
113
|
);
|
|
112
114
|
} catch (err: any) {
|
|
113
115
|
if (!isDbNotFoundError(err)) throw err;
|
|
@@ -120,7 +122,7 @@ async function markInviteRewardEmailState(
|
|
|
120
122
|
inviteeUserId: string,
|
|
121
123
|
status: InviteRewardEmailState["status"]
|
|
122
124
|
) {
|
|
123
|
-
await
|
|
125
|
+
await getServerAuthorityStore().put(getInviteRewardEmailStateKey(inviterId, inviteeUserId), {
|
|
124
126
|
status,
|
|
125
127
|
updatedAt: Date.now(),
|
|
126
128
|
});
|
|
@@ -132,6 +134,7 @@ async function trySendInviteRewardEmail(
|
|
|
132
134
|
logger: InviteLogger
|
|
133
135
|
) {
|
|
134
136
|
const lock = balanceLockManager.getLock(`invite-email:${inviterId}:${inviteeUserId}`);
|
|
137
|
+
const store = getServerAuthorityStore();
|
|
135
138
|
await lock.runExclusive(async () => {
|
|
136
139
|
// 只要已有状态(queued/sent),就不再重复触发邮件流程。
|
|
137
140
|
const existingState = await getInviteRewardEmailState(inviterId, inviteeUserId);
|
|
@@ -141,7 +144,7 @@ async function trySendInviteRewardEmail(
|
|
|
141
144
|
|
|
142
145
|
let inviter: any = null;
|
|
143
146
|
try {
|
|
144
|
-
inviter = await
|
|
147
|
+
inviter = await store.get(DB_PREFIX.USER + inviterId);
|
|
145
148
|
} catch (err: any) {
|
|
146
149
|
if (!isDbNotFoundError(err)) {
|
|
147
150
|
logger.warn({ inviterId, inviteeUserId, err }, "Failed to read inviter.");
|
|
@@ -156,7 +159,7 @@ async function trySendInviteRewardEmail(
|
|
|
156
159
|
|
|
157
160
|
let inviteeName = inviteeUserId;
|
|
158
161
|
try {
|
|
159
|
-
const invitee = await
|
|
162
|
+
const invitee = await store.get(DB_PREFIX.USER + inviteeUserId);
|
|
160
163
|
if (typeof invitee?.username === "string" && invitee.username.trim()) {
|
|
161
164
|
inviteeName = invitee.username;
|
|
162
165
|
}
|
|
@@ -212,7 +215,7 @@ export async function resolveValidInviterId(
|
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
try {
|
|
215
|
-
const inviter = await
|
|
218
|
+
const inviter = await getServerAuthorityStore().get(DB_PREFIX.USER + inviterId);
|
|
216
219
|
if (!inviter) {
|
|
217
220
|
logger.warn({ inviterId, newUserId }, "Inviter not found.");
|
|
218
221
|
return undefined;
|
|
@@ -240,7 +243,7 @@ export async function creditInviterReward(
|
|
|
240
243
|
|
|
241
244
|
let inviteeCreatedAt = 0;
|
|
242
245
|
try {
|
|
243
|
-
const invitee = await
|
|
246
|
+
const invitee = await getServerAuthorityStore().get(DB_PREFIX.USER + inviteeUserId);
|
|
244
247
|
inviteeCreatedAt =
|
|
245
248
|
typeof invitee?.createdAt === "number" ? invitee.createdAt : 0;
|
|
246
249
|
} catch (err: any) {
|
package/auth/server/listusers.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// auth/server/listusers.ts
|
|
2
|
-
import
|
|
2
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
3
3
|
import {
|
|
4
4
|
createErrorResponse,
|
|
5
5
|
createSuccessResponse,
|
|
@@ -29,11 +29,12 @@ async function listUsers({
|
|
|
29
29
|
pageSize = 10,
|
|
30
30
|
search,
|
|
31
31
|
}: ListUsersOptions = {}) {
|
|
32
|
+
const store = getServerAuthorityStore();
|
|
32
33
|
const prefix = DB_PREFIX.USER;
|
|
33
34
|
let users: User[] = [];
|
|
34
35
|
|
|
35
36
|
// 1. 全量读取到内存
|
|
36
|
-
const iter =
|
|
37
|
+
const iter = store.iterator({
|
|
37
38
|
gt: prefix,
|
|
38
39
|
lt: prefix + "\xFF",
|
|
39
40
|
});
|
|
@@ -50,7 +51,7 @@ async function listUsers({
|
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
53
|
} finally {
|
|
53
|
-
await iter.close();
|
|
54
|
+
await (iter as any).close?.();
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
// 2. 按创建时间降序
|
|
@@ -93,6 +94,7 @@ export async function handleListUsers(req: Request) {
|
|
|
93
94
|
if (permissionError) return permissionError;
|
|
94
95
|
|
|
95
96
|
try {
|
|
97
|
+
const store = getServerAuthorityStore();
|
|
96
98
|
const url = new URL(req.url);
|
|
97
99
|
// 1. 解析并限制分页参数
|
|
98
100
|
const page = Math.max(1, parseInt(url.searchParams.get("page") || "1", 10));
|
|
@@ -110,7 +112,7 @@ export async function handleListUsers(req: Request) {
|
|
|
110
112
|
// 3. 如果指定了 userId,直接单条查询
|
|
111
113
|
if (userIdParam) {
|
|
112
114
|
try {
|
|
113
|
-
const value = await
|
|
115
|
+
const value = await store.get(prefix + userIdParam);
|
|
114
116
|
const user: User = {
|
|
115
117
|
id: userIdParam,
|
|
116
118
|
username: value.username,
|
package/auth/server/login.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// auth/server/login.ts
|
|
2
2
|
|
|
3
3
|
import { verifyToken } from "../token";
|
|
4
|
-
import
|
|
4
|
+
import { getServerAuthorityStore } from "../../database/server/db";
|
|
5
5
|
import { DB_PREFIX } from "../../database/keys";
|
|
6
6
|
import i18nServer from "../../app/i18n/i18n.server";
|
|
7
7
|
import {
|
|
@@ -68,7 +68,7 @@ export async function handleLogin(req: Request) {
|
|
|
68
68
|
|
|
69
69
|
let user;
|
|
70
70
|
try {
|
|
71
|
-
user = await
|
|
71
|
+
user = await getServerAuthorityStore().get(DB_PREFIX.USER + userId);
|
|
72
72
|
logger.debug({
|
|
73
73
|
event: "user_fetched",
|
|
74
74
|
userId,
|