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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export type BillingAdminAuditAction =
|
|
2
|
+
| "dry_run_viewed"
|
|
3
|
+
| "reconciliation_dry_run"
|
|
4
|
+
| "reconciliation_committed"
|
|
5
|
+
| "plan_marked_reviewed"
|
|
6
|
+
| "plan_abandoned";
|
|
7
|
+
|
|
8
|
+
export type BillingAdminAuditEvent = {
|
|
9
|
+
schemaVersion: 1;
|
|
10
|
+
recordType: "billing_admin_audit_event";
|
|
11
|
+
eventId: string;
|
|
12
|
+
actorId: string;
|
|
13
|
+
action: BillingAdminAuditAction;
|
|
14
|
+
anomalyId: string;
|
|
15
|
+
planId: string;
|
|
16
|
+
inputSetHash: string;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
reason?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const buildBillingAdminAuditEventKey = (eventId: string) =>
|
|
22
|
+
`billing-admin-audit-event-${eventId}`;
|
|
23
|
+
|
|
24
|
+
function assertIsoTimestamp(name: string, value: string) {
|
|
25
|
+
const time = Date.parse(value);
|
|
26
|
+
if (!Number.isFinite(time)) {
|
|
27
|
+
throw new Error(`${name} must be an ISO timestamp`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createBillingAdminAuditEvent({
|
|
32
|
+
eventId,
|
|
33
|
+
actorId,
|
|
34
|
+
action,
|
|
35
|
+
anomalyId,
|
|
36
|
+
planId,
|
|
37
|
+
inputSetHash,
|
|
38
|
+
createdAt,
|
|
39
|
+
reason,
|
|
40
|
+
}: {
|
|
41
|
+
eventId: string;
|
|
42
|
+
actorId: string;
|
|
43
|
+
action: BillingAdminAuditAction;
|
|
44
|
+
anomalyId: string;
|
|
45
|
+
planId: string;
|
|
46
|
+
inputSetHash: string;
|
|
47
|
+
createdAt: string;
|
|
48
|
+
reason?: string | null;
|
|
49
|
+
}): BillingAdminAuditEvent {
|
|
50
|
+
if (!eventId.trim()) throw new Error("eventId is required");
|
|
51
|
+
if (!actorId.trim()) throw new Error("actorId is required");
|
|
52
|
+
if (!anomalyId.trim()) throw new Error("anomalyId is required");
|
|
53
|
+
if (!planId.trim()) throw new Error("planId is required");
|
|
54
|
+
if (!inputSetHash.trim()) throw new Error("inputSetHash is required");
|
|
55
|
+
assertIsoTimestamp("createdAt", createdAt);
|
|
56
|
+
return {
|
|
57
|
+
schemaVersion: 1,
|
|
58
|
+
recordType: "billing_admin_audit_event",
|
|
59
|
+
eventId: eventId.trim(),
|
|
60
|
+
actorId: actorId.trim(),
|
|
61
|
+
action,
|
|
62
|
+
anomalyId: anomalyId.trim(),
|
|
63
|
+
planId: planId.trim(),
|
|
64
|
+
inputSetHash: inputSetHash.trim(),
|
|
65
|
+
createdAt,
|
|
66
|
+
...(reason?.trim() ? { reason: reason.trim() } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildBillingAdminAuditEventKey,
|
|
3
|
+
type BillingAdminAuditEvent,
|
|
4
|
+
} from "./billingAdminAuditEvent";
|
|
5
|
+
|
|
6
|
+
export type BillingAdminAuditEventStore = {
|
|
7
|
+
get(key: string): Promise<unknown>;
|
|
8
|
+
put(key: string, value: unknown): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const isMissingRecordError = (error: unknown) => {
|
|
12
|
+
if (!error || typeof error !== "object") return false;
|
|
13
|
+
const code = (error as { code?: unknown }).code;
|
|
14
|
+
const message = (error as { message?: unknown }).message;
|
|
15
|
+
return (
|
|
16
|
+
code === "LEVEL_NOT_FOUND" ||
|
|
17
|
+
code === "NOT_FOUND" ||
|
|
18
|
+
message === "NotFound"
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export async function writeBillingAdminAuditEvent({
|
|
23
|
+
store,
|
|
24
|
+
event,
|
|
25
|
+
}: {
|
|
26
|
+
store: BillingAdminAuditEventStore;
|
|
27
|
+
event: BillingAdminAuditEvent;
|
|
28
|
+
}): Promise<{ key: string }> {
|
|
29
|
+
const key = buildBillingAdminAuditEventKey(event.eventId);
|
|
30
|
+
let existing: unknown;
|
|
31
|
+
try {
|
|
32
|
+
existing = await store.get(key);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (!isMissingRecordError(error)) throw error;
|
|
35
|
+
}
|
|
36
|
+
if (existing) {
|
|
37
|
+
throw new Error(`billing admin audit event already exists: ${key}`);
|
|
38
|
+
}
|
|
39
|
+
await store.put(key, event);
|
|
40
|
+
return { key };
|
|
41
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export type BillingAnomalyKind =
|
|
2
|
+
| "provider_call_write_failed"
|
|
3
|
+
| "provider_credential_revoked_blocked"
|
|
4
|
+
| "provider_credential_revoked_used"
|
|
5
|
+
| "billable_event_write_failed"
|
|
6
|
+
| "rating_failed"
|
|
7
|
+
| "ledger_failed"
|
|
8
|
+
| "provider_call_pending_timeout"
|
|
9
|
+
| "provider_call_sent_unknown"
|
|
10
|
+
| "provider_reconciliation_diff"
|
|
11
|
+
| "usage_missing"
|
|
12
|
+
| "aggregate_usage_unallocated"
|
|
13
|
+
| "pricing_missing";
|
|
14
|
+
|
|
15
|
+
export type BillingAnomalySeverity = "low" | "medium" | "high" | "critical";
|
|
16
|
+
|
|
17
|
+
export type BillingAnomalyStage =
|
|
18
|
+
| "provider_call"
|
|
19
|
+
| "billable_event"
|
|
20
|
+
| "rating"
|
|
21
|
+
| "ledger"
|
|
22
|
+
| "usage"
|
|
23
|
+
| "pricing"
|
|
24
|
+
| "reconciliation";
|
|
25
|
+
|
|
26
|
+
export type BillingAnomalyStatus = "open" | "acknowledged" | "resolved" | "ignored";
|
|
27
|
+
|
|
28
|
+
export type BillingAnomaly = {
|
|
29
|
+
id: string;
|
|
30
|
+
kind: BillingAnomalyKind;
|
|
31
|
+
severity: BillingAnomalySeverity;
|
|
32
|
+
stage: BillingAnomalyStage;
|
|
33
|
+
status: BillingAnomalyStatus;
|
|
34
|
+
userId: string;
|
|
35
|
+
dialogId?: string;
|
|
36
|
+
agentId?: string;
|
|
37
|
+
provider: string;
|
|
38
|
+
model: string;
|
|
39
|
+
providerCallId?: string;
|
|
40
|
+
billableEventId?: string;
|
|
41
|
+
ratingResultId?: string;
|
|
42
|
+
riskPlatformCredits?: number;
|
|
43
|
+
message: string;
|
|
44
|
+
evidence: Record<string, unknown>;
|
|
45
|
+
createdAt: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type CreateBillingAnomalyInput = {
|
|
49
|
+
anomalyId: string;
|
|
50
|
+
kind: BillingAnomalyKind;
|
|
51
|
+
severity: BillingAnomalySeverity;
|
|
52
|
+
stage: BillingAnomalyStage;
|
|
53
|
+
userId: string;
|
|
54
|
+
dialogId?: string;
|
|
55
|
+
agentId?: string;
|
|
56
|
+
provider: string;
|
|
57
|
+
model: string;
|
|
58
|
+
providerCallId?: string;
|
|
59
|
+
billableEventId?: string;
|
|
60
|
+
ratingResultId?: string;
|
|
61
|
+
riskPlatformCredits?: number;
|
|
62
|
+
message: string;
|
|
63
|
+
evidence: Record<string, unknown>;
|
|
64
|
+
createdAt: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const buildBillingAnomalyKey = (anomalyId: string) =>
|
|
68
|
+
`billing-anomaly-${anomalyId}`;
|
|
69
|
+
|
|
70
|
+
export const createBillingAnomaly = (
|
|
71
|
+
input: CreateBillingAnomalyInput
|
|
72
|
+
): BillingAnomaly => ({
|
|
73
|
+
id: input.anomalyId,
|
|
74
|
+
kind: input.kind,
|
|
75
|
+
severity: input.severity,
|
|
76
|
+
stage: input.stage,
|
|
77
|
+
status: "open",
|
|
78
|
+
userId: input.userId,
|
|
79
|
+
dialogId: input.dialogId,
|
|
80
|
+
agentId: input.agentId,
|
|
81
|
+
provider: input.provider,
|
|
82
|
+
model: input.model,
|
|
83
|
+
providerCallId: input.providerCallId,
|
|
84
|
+
billableEventId: input.billableEventId,
|
|
85
|
+
ratingResultId: input.ratingResultId,
|
|
86
|
+
riskPlatformCredits: input.riskPlatformCredits,
|
|
87
|
+
message: input.message,
|
|
88
|
+
evidence: { ...input.evidence },
|
|
89
|
+
createdAt: input.createdAt,
|
|
90
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { BillingAnomalyStatus } from "./billingAnomaly";
|
|
2
|
+
|
|
3
|
+
export type BillingAnomalyLifecycleEvent = {
|
|
4
|
+
schemaVersion: 1;
|
|
5
|
+
recordType: "billing_anomaly_lifecycle_event";
|
|
6
|
+
anomalyId: string;
|
|
7
|
+
eventId: string;
|
|
8
|
+
status: BillingAnomalyStatus;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
actorId?: string;
|
|
11
|
+
reason?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const buildBillingAnomalyLifecycleEventKey = (
|
|
15
|
+
anomalyId: string,
|
|
16
|
+
eventId: string
|
|
17
|
+
) => `billing-anomaly-lifecycle-${anomalyId}-event-${eventId}`;
|
|
18
|
+
|
|
19
|
+
function assertIsoTimestamp(name: string, value: string) {
|
|
20
|
+
const time = Date.parse(value);
|
|
21
|
+
if (!Number.isFinite(time)) {
|
|
22
|
+
throw new Error(`${name} must be an ISO timestamp`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createBillingAnomalyLifecycleEvent({
|
|
27
|
+
anomalyId,
|
|
28
|
+
eventId,
|
|
29
|
+
status,
|
|
30
|
+
createdAt,
|
|
31
|
+
actorId,
|
|
32
|
+
reason,
|
|
33
|
+
}: {
|
|
34
|
+
anomalyId: string;
|
|
35
|
+
eventId: string;
|
|
36
|
+
status: BillingAnomalyStatus;
|
|
37
|
+
createdAt: string;
|
|
38
|
+
actorId?: string | null;
|
|
39
|
+
reason?: string | null;
|
|
40
|
+
}): BillingAnomalyLifecycleEvent {
|
|
41
|
+
if (!anomalyId.trim()) throw new Error("anomalyId is required");
|
|
42
|
+
if (!eventId.trim()) throw new Error("eventId is required");
|
|
43
|
+
assertIsoTimestamp("createdAt", createdAt);
|
|
44
|
+
return {
|
|
45
|
+
schemaVersion: 1,
|
|
46
|
+
recordType: "billing_anomaly_lifecycle_event",
|
|
47
|
+
anomalyId: anomalyId.trim(),
|
|
48
|
+
eventId: eventId.trim(),
|
|
49
|
+
status,
|
|
50
|
+
createdAt,
|
|
51
|
+
...(actorId?.trim() ? { actorId: actorId.trim() } : {}),
|
|
52
|
+
...(reason?.trim() ? { reason: reason.trim() } : {}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildBillingAnomalyLifecycleEventKey,
|
|
3
|
+
type BillingAnomalyLifecycleEvent,
|
|
4
|
+
} from "./billingAnomalyLifecycle";
|
|
5
|
+
|
|
6
|
+
export type BillingAnomalyLifecycleStore = {
|
|
7
|
+
get(key: string): Promise<unknown>;
|
|
8
|
+
put(key: string, value: unknown): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const isMissingRecordError = (error: unknown) => {
|
|
12
|
+
if (!error || typeof error !== "object") return false;
|
|
13
|
+
const code = (error as { code?: unknown }).code;
|
|
14
|
+
const message = (error as { message?: unknown }).message;
|
|
15
|
+
return (
|
|
16
|
+
code === "LEVEL_NOT_FOUND" ||
|
|
17
|
+
code === "NOT_FOUND" ||
|
|
18
|
+
message === "NotFound"
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export async function writeBillingAnomalyLifecycleEvent({
|
|
23
|
+
store,
|
|
24
|
+
event,
|
|
25
|
+
}: {
|
|
26
|
+
store: BillingAnomalyLifecycleStore;
|
|
27
|
+
event: BillingAnomalyLifecycleEvent;
|
|
28
|
+
}): Promise<{ key: string }> {
|
|
29
|
+
const key = buildBillingAnomalyLifecycleEventKey(
|
|
30
|
+
event.anomalyId,
|
|
31
|
+
event.eventId
|
|
32
|
+
);
|
|
33
|
+
let existing: unknown;
|
|
34
|
+
try {
|
|
35
|
+
existing = await store.get(key);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (!isMissingRecordError(error)) throw error;
|
|
38
|
+
}
|
|
39
|
+
if (existing) {
|
|
40
|
+
throw new Error(`billing anomaly lifecycle event already exists: ${key}`);
|
|
41
|
+
}
|
|
42
|
+
await store.put(key, event);
|
|
43
|
+
return { key };
|
|
44
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildBillingAnomalyKey,
|
|
3
|
+
type BillingAnomaly,
|
|
4
|
+
} from "./billingAnomaly";
|
|
5
|
+
|
|
6
|
+
export type BillingAnomalyStore = {
|
|
7
|
+
get(key: string): Promise<unknown>;
|
|
8
|
+
put(key: string, value: unknown): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const isMissingRecordError = (error: unknown) => {
|
|
12
|
+
if (!error || typeof error !== "object") return false;
|
|
13
|
+
const code = (error as { code?: unknown }).code;
|
|
14
|
+
const message = (error as { message?: unknown }).message;
|
|
15
|
+
return (
|
|
16
|
+
code === "LEVEL_NOT_FOUND" ||
|
|
17
|
+
code === "NOT_FOUND" ||
|
|
18
|
+
message === "NotFound"
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export async function writeBillingAnomaly({
|
|
23
|
+
store,
|
|
24
|
+
anomaly,
|
|
25
|
+
}: {
|
|
26
|
+
store: BillingAnomalyStore;
|
|
27
|
+
anomaly: BillingAnomaly;
|
|
28
|
+
}): Promise<{ key: string }> {
|
|
29
|
+
const key = buildBillingAnomalyKey(anomaly.id);
|
|
30
|
+
let existing: unknown;
|
|
31
|
+
try {
|
|
32
|
+
existing = await store.get(key);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (!isMissingRecordError(error)) throw error;
|
|
35
|
+
}
|
|
36
|
+
if (existing) {
|
|
37
|
+
throw new Error(`billing anomaly already exists: ${key}`);
|
|
38
|
+
}
|
|
39
|
+
await store.put(key, anomaly);
|
|
40
|
+
return { key };
|
|
41
|
+
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type OpenAIServiceTier,
|
|
10
10
|
resolveOpenAIServiceTier,
|
|
11
11
|
} from "../../integrations/openai/flexTier";
|
|
12
|
+
import { DEFAULT_COMMERCIAL_MULTIPLIER } from "../policy/commercialMultiplier";
|
|
12
13
|
|
|
13
14
|
// ==================== 接口定义 ====================
|
|
14
15
|
|
|
@@ -369,8 +370,8 @@ const calculateOpenRouterFallbackCost = (
|
|
|
369
370
|
};
|
|
370
371
|
|
|
371
372
|
// OpenRouter usage.cost 是按其账户 credit(USD 基准)返回,
|
|
372
|
-
//
|
|
373
|
-
const OPENROUTER_COST_MULTIPLIER =
|
|
373
|
+
// Provider USD cost converts to platform credits at the default *8 rule.
|
|
374
|
+
const OPENROUTER_COST_MULTIPLIER = DEFAULT_COMMERCIAL_MULTIPLIER;
|
|
374
375
|
|
|
375
376
|
const calculateOpenRouterCost = (usage: Usage): CostBreakdown => {
|
|
376
377
|
if (!usage || typeof usage.cost !== "number" || usage.cost <= 0) {
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { ProviderReconciliationBucketTotals } from "./providerReconciliation";
|
|
2
|
+
|
|
3
|
+
export type NormalizedOfficialProviderBucket = {
|
|
4
|
+
provider: string;
|
|
5
|
+
model?: string;
|
|
6
|
+
endpoint?: string;
|
|
7
|
+
bucketStart: string;
|
|
8
|
+
bucketEnd: string;
|
|
9
|
+
official: ProviderReconciliationBucketTotals;
|
|
10
|
+
evidence: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type DeepInfraUsageResponse = {
|
|
14
|
+
months?: Array<{
|
|
15
|
+
period?: string;
|
|
16
|
+
interval?: { fr?: number; to?: number };
|
|
17
|
+
items?: Array<{
|
|
18
|
+
model?: {
|
|
19
|
+
provider?: string;
|
|
20
|
+
model_name?: string;
|
|
21
|
+
task?: string;
|
|
22
|
+
};
|
|
23
|
+
units?: number;
|
|
24
|
+
rate?: number;
|
|
25
|
+
cost?: number;
|
|
26
|
+
pricing_type?: string;
|
|
27
|
+
interval?: { fr?: number; to?: number };
|
|
28
|
+
}>;
|
|
29
|
+
total_cost?: number;
|
|
30
|
+
invoice_id?: string;
|
|
31
|
+
}>;
|
|
32
|
+
initial_month?: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type DeepInfraRequestCostsResponse = {
|
|
36
|
+
requests?: Array<{
|
|
37
|
+
requestId?: string;
|
|
38
|
+
model?: string;
|
|
39
|
+
costNanoUsd?: number;
|
|
40
|
+
createdAt?: string;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const unixSecondsToIso = (value: unknown) => {
|
|
45
|
+
const seconds = typeof value === "number" ? value : NaN;
|
|
46
|
+
if (!Number.isFinite(seconds)) return undefined;
|
|
47
|
+
return new Date(seconds * 1000).toISOString();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export function normalizeDeepInfraUsageResponse(
|
|
51
|
+
response: DeepInfraUsageResponse
|
|
52
|
+
): NormalizedOfficialProviderBucket[] {
|
|
53
|
+
const buckets: NormalizedOfficialProviderBucket[] = [];
|
|
54
|
+
for (const month of response.months ?? []) {
|
|
55
|
+
for (const item of month.items ?? []) {
|
|
56
|
+
const bucketStart = unixSecondsToIso(item.interval?.fr ?? month.interval?.fr);
|
|
57
|
+
const bucketEnd = unixSecondsToIso(item.interval?.to ?? month.interval?.to);
|
|
58
|
+
if (!bucketStart || !bucketEnd) continue;
|
|
59
|
+
buckets.push({
|
|
60
|
+
provider: "deepinfra",
|
|
61
|
+
model: item.model?.model_name,
|
|
62
|
+
endpoint: item.model?.task,
|
|
63
|
+
bucketStart,
|
|
64
|
+
bucketEnd,
|
|
65
|
+
official: {
|
|
66
|
+
requestCount: 0,
|
|
67
|
+
inputTokens: 0,
|
|
68
|
+
outputTokens: 0,
|
|
69
|
+
rawProviderCostUsd:
|
|
70
|
+
typeof item.cost === "number" && Number.isFinite(item.cost)
|
|
71
|
+
? item.cost
|
|
72
|
+
: 0,
|
|
73
|
+
},
|
|
74
|
+
evidence: {
|
|
75
|
+
period: month.period,
|
|
76
|
+
pricingType: item.pricing_type,
|
|
77
|
+
units: item.units,
|
|
78
|
+
rate: item.rate,
|
|
79
|
+
invoiceId: month.invoice_id,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return buckets;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const startOfUtcDay = (iso: string) => {
|
|
88
|
+
const date = new Date(iso);
|
|
89
|
+
if (!Number.isFinite(date.getTime())) return undefined;
|
|
90
|
+
return new Date(
|
|
91
|
+
Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate())
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export function normalizeDeepInfraRequestCostsResponse(
|
|
96
|
+
response: DeepInfraRequestCostsResponse
|
|
97
|
+
): NormalizedOfficialProviderBucket[] {
|
|
98
|
+
const grouped = new Map<
|
|
99
|
+
string,
|
|
100
|
+
{
|
|
101
|
+
provider: "deepinfra";
|
|
102
|
+
model?: string;
|
|
103
|
+
bucketStart: string;
|
|
104
|
+
bucketEnd: string;
|
|
105
|
+
requestCount: number;
|
|
106
|
+
rawProviderCostUsd: number;
|
|
107
|
+
requestIds: string[];
|
|
108
|
+
}
|
|
109
|
+
>();
|
|
110
|
+
|
|
111
|
+
for (const request of response.requests ?? []) {
|
|
112
|
+
if (!request.createdAt) continue;
|
|
113
|
+
const start = startOfUtcDay(request.createdAt);
|
|
114
|
+
if (!start) continue;
|
|
115
|
+
const bucketStart = start.toISOString();
|
|
116
|
+
const bucketEnd = new Date(start.getTime() + 24 * 60 * 60 * 1000).toISOString();
|
|
117
|
+
const key = ["deepinfra", request.model ?? "", bucketStart, bucketEnd].join("\u0000");
|
|
118
|
+
const existing =
|
|
119
|
+
grouped.get(key) ??
|
|
120
|
+
{
|
|
121
|
+
provider: "deepinfra" as const,
|
|
122
|
+
model: request.model,
|
|
123
|
+
bucketStart,
|
|
124
|
+
bucketEnd,
|
|
125
|
+
requestCount: 0,
|
|
126
|
+
rawProviderCostUsd: 0,
|
|
127
|
+
requestIds: [],
|
|
128
|
+
};
|
|
129
|
+
existing.requestCount += 1;
|
|
130
|
+
if (typeof request.costNanoUsd === "number" && Number.isFinite(request.costNanoUsd)) {
|
|
131
|
+
existing.rawProviderCostUsd += request.costNanoUsd / 1_000_000_000;
|
|
132
|
+
}
|
|
133
|
+
if (request.requestId) existing.requestIds.push(request.requestId);
|
|
134
|
+
grouped.set(key, existing);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return [...grouped.values()].map((bucket) => ({
|
|
138
|
+
provider: bucket.provider,
|
|
139
|
+
model: bucket.model,
|
|
140
|
+
bucketStart: bucket.bucketStart,
|
|
141
|
+
bucketEnd: bucket.bucketEnd,
|
|
142
|
+
official: {
|
|
143
|
+
requestCount: bucket.requestCount,
|
|
144
|
+
inputTokens: 0,
|
|
145
|
+
outputTokens: 0,
|
|
146
|
+
rawProviderCostUsd: Number(bucket.rawProviderCostUsd.toFixed(12)),
|
|
147
|
+
},
|
|
148
|
+
evidence: {
|
|
149
|
+
source: "deepinfra_request_costs",
|
|
150
|
+
requestIds: bucket.requestIds,
|
|
151
|
+
},
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export type DeepInfraRequestIdStore = {
|
|
2
|
+
iterator(options: { gte?: string; lte?: string }): AsyncIterable<[string, unknown]>;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export type DeepInfraRequestIdQueryResult = {
|
|
6
|
+
requestIds: string[];
|
|
7
|
+
responseIds: string[];
|
|
8
|
+
scannedTokenRecords: number;
|
|
9
|
+
matchedTokenRecords: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const TOKEN_PREFIX = "token-";
|
|
13
|
+
const TOKEN_RANGE_END = `${TOKEN_PREFIX}\uffff`;
|
|
14
|
+
|
|
15
|
+
const isTokenRecordLike = (value: unknown) =>
|
|
16
|
+
Boolean(
|
|
17
|
+
value &&
|
|
18
|
+
typeof value === "object" &&
|
|
19
|
+
typeof (value as { provider?: unknown }).provider === "string" &&
|
|
20
|
+
typeof (value as { createdAt?: unknown }).createdAt === "number"
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const pushStrings = (target: Set<string>, value: unknown) => {
|
|
24
|
+
if (!Array.isArray(value)) return;
|
|
25
|
+
for (const item of value) {
|
|
26
|
+
if (typeof item !== "string") continue;
|
|
27
|
+
const trimmed = item.trim();
|
|
28
|
+
if (trimmed) target.add(trimmed);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export async function collectDeepInfraRequestIds({
|
|
33
|
+
store,
|
|
34
|
+
bucketStart,
|
|
35
|
+
bucketEnd,
|
|
36
|
+
}: {
|
|
37
|
+
store: DeepInfraRequestIdStore;
|
|
38
|
+
bucketStart: string;
|
|
39
|
+
bucketEnd: string;
|
|
40
|
+
}): Promise<DeepInfraRequestIdQueryResult> {
|
|
41
|
+
return collectProviderRequestIds({
|
|
42
|
+
store,
|
|
43
|
+
provider: "deepinfra",
|
|
44
|
+
bucketStart,
|
|
45
|
+
bucketEnd,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function collectProviderRequestIds({
|
|
50
|
+
store,
|
|
51
|
+
provider,
|
|
52
|
+
bucketStart,
|
|
53
|
+
bucketEnd,
|
|
54
|
+
}: {
|
|
55
|
+
store: DeepInfraRequestIdStore;
|
|
56
|
+
provider: string;
|
|
57
|
+
bucketStart: string;
|
|
58
|
+
bucketEnd: string;
|
|
59
|
+
}): Promise<DeepInfraRequestIdQueryResult> {
|
|
60
|
+
const startMs = Date.parse(bucketStart);
|
|
61
|
+
const endMs = Date.parse(bucketEnd);
|
|
62
|
+
const requestIds = new Set<string>();
|
|
63
|
+
const responseIds = new Set<string>();
|
|
64
|
+
let scannedTokenRecords = 0;
|
|
65
|
+
let matchedTokenRecords = 0;
|
|
66
|
+
|
|
67
|
+
for await (const [, value] of store.iterator({
|
|
68
|
+
gte: TOKEN_PREFIX,
|
|
69
|
+
lte: TOKEN_RANGE_END,
|
|
70
|
+
})) {
|
|
71
|
+
if (!isTokenRecordLike(value)) continue;
|
|
72
|
+
scannedTokenRecords += 1;
|
|
73
|
+
const record = value as {
|
|
74
|
+
provider: string;
|
|
75
|
+
createdAt: number;
|
|
76
|
+
provider_request_ids?: unknown;
|
|
77
|
+
provider_response_ids?: unknown;
|
|
78
|
+
};
|
|
79
|
+
if (record.provider !== provider) continue;
|
|
80
|
+
if (record.createdAt < startMs || record.createdAt >= endMs) continue;
|
|
81
|
+
matchedTokenRecords += 1;
|
|
82
|
+
pushStrings(requestIds, record.provider_request_ids);
|
|
83
|
+
pushStrings(responseIds, record.provider_response_ids);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
requestIds: [...requestIds],
|
|
88
|
+
responseIds: [...responseIds],
|
|
89
|
+
scannedTokenRecords,
|
|
90
|
+
matchedTokenRecords,
|
|
91
|
+
};
|
|
92
|
+
}
|