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.
- 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/agentCreateCustomCommands.ts +9 -4
- package/agentDialogsCommands.ts +4 -3
- package/agentDoctorCommands.ts +3 -3
- package/agentListCommands.ts +3 -3
- package/agentMachineCommands.ts +6 -6
- package/agentPullCommand.ts +4 -12
- package/agentRecordCommands.ts +5 -3
- package/agentRecordHelpers.ts +42 -23
- package/agentRunCommand.ts +2 -6
- package/agentRunParsing.ts +18 -5
- package/agentRuntimeLocal.ts +10 -0
- package/agentUnpublishCommands.ts +3 -2
- 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 +68 -13
- 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 +40 -15
- 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/dialogReadCommands.ts +2 -1
- package/dialogStatusCommands.ts +2 -1
- 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 -62
- package/machineStatusCommands.ts +4 -12
- package/machineWsRunDispatch.ts +80 -15
- package/machineWsSession.ts +46 -2
- package/noloReadBridgePrompt.ts +16 -0
- package/package.json +114 -21
- package/pageCreateCommands.ts +2 -2
- package/pageDeleteCommands.ts +3 -3
- package/pageReadCommands.ts +3 -3
- package/pageUpdateCommands.ts +3 -3
- 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 +18 -69
- 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/spaceCategoryCommands.ts +6 -6
- package/spaceCommands.ts +3 -3
- package/spaceDeleteCommands.ts +2 -2
- package/spaceInternalCommandEntries.ts +2 -0
- package/spaceReadCommands.ts +3 -3
- package/tableMetaCommands.ts +2 -2
- package/taskRunCommand.ts +11 -0
- package/ai/agent/runtimeServerBase.ts +0 -37
- package/server/handlers/desktopAgentRuntimeHostFacts.ts +0 -40
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import type { AuthorityStore } from "./authorityStoreTypes";
|
|
4
|
+
|
|
5
|
+
type FakeLevelOp = { type: "put" | "del"; key: string; value?: unknown };
|
|
6
|
+
|
|
7
|
+
type FakeNotFoundError = Error & { notFound: true };
|
|
8
|
+
|
|
9
|
+
const createNotFoundError = (): FakeNotFoundError => {
|
|
10
|
+
const error = new Error("NotFound") as FakeNotFoundError;
|
|
11
|
+
error.notFound = true;
|
|
12
|
+
return error;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export class FakeAuthorityBacking {
|
|
16
|
+
location = "/tmp/authority-conformance";
|
|
17
|
+
status = "closed";
|
|
18
|
+
private readonly data = new Map<string, unknown>();
|
|
19
|
+
|
|
20
|
+
async open() {
|
|
21
|
+
this.status = "open";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async close() {
|
|
25
|
+
this.status = "closed";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async get(key: string) {
|
|
29
|
+
if (!this.data.has(key)) {
|
|
30
|
+
throw createNotFoundError();
|
|
31
|
+
}
|
|
32
|
+
return this.data.get(key);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async put(key: string, value: unknown) {
|
|
36
|
+
this.data.set(key, value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async del(key: string) {
|
|
40
|
+
this.data.delete(key);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
batch(ops?: FakeLevelOp[]) {
|
|
44
|
+
if (Array.isArray(ops)) {
|
|
45
|
+
return Promise.resolve().then(async () => {
|
|
46
|
+
for (const op of ops) {
|
|
47
|
+
if (op.type === "put") {
|
|
48
|
+
await this.put(op.key, op.value);
|
|
49
|
+
} else {
|
|
50
|
+
await this.del(op.key);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const buffered: FakeLevelOp[] = [];
|
|
57
|
+
return {
|
|
58
|
+
put: (key: string, value: unknown) => {
|
|
59
|
+
buffered.push({ type: "put", key, value });
|
|
60
|
+
},
|
|
61
|
+
del: (key: string) => {
|
|
62
|
+
buffered.push({ type: "del", key });
|
|
63
|
+
},
|
|
64
|
+
write: async () => {
|
|
65
|
+
await this.batch(buffered);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async *iterator(options: {
|
|
71
|
+
gte?: string;
|
|
72
|
+
lte?: string;
|
|
73
|
+
lt?: string;
|
|
74
|
+
reverse?: boolean;
|
|
75
|
+
} = {}) {
|
|
76
|
+
const keys = Array.from(this.data.keys()).sort();
|
|
77
|
+
if (options.reverse) keys.reverse();
|
|
78
|
+
for (const key of keys) {
|
|
79
|
+
if (options.gte && key < options.gte) continue;
|
|
80
|
+
if (options.lte && key > options.lte) continue;
|
|
81
|
+
if (options.lt && key >= options.lt) continue;
|
|
82
|
+
yield [key, this.data.get(key)] as [string, unknown];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
type CreateStore = () => Promise<{
|
|
88
|
+
backing: FakeAuthorityBacking;
|
|
89
|
+
store: AuthorityStore;
|
|
90
|
+
}>;
|
|
91
|
+
|
|
92
|
+
export function runAuthorityStoreConformanceSuite(
|
|
93
|
+
label: string,
|
|
94
|
+
createStore: CreateStore,
|
|
95
|
+
options: {
|
|
96
|
+
expectedLocation?: string;
|
|
97
|
+
} = {}
|
|
98
|
+
) {
|
|
99
|
+
const expectedLocation =
|
|
100
|
+
options.expectedLocation ?? "/tmp/authority-conformance";
|
|
101
|
+
|
|
102
|
+
describe(label, () => {
|
|
103
|
+
it("preserves open/close status, location, and NotFound semantics", async () => {
|
|
104
|
+
const { store } = await createStore();
|
|
105
|
+
|
|
106
|
+
expect(store.status).toBe("closed");
|
|
107
|
+
expect(store.location).toBe(expectedLocation);
|
|
108
|
+
|
|
109
|
+
await store.open();
|
|
110
|
+
expect(store.status).toBe("open");
|
|
111
|
+
|
|
112
|
+
await expect(store.get("missing")).rejects.toMatchObject({
|
|
113
|
+
message: "NotFound",
|
|
114
|
+
notFound: true,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
await store.close();
|
|
118
|
+
expect(store.status).toBe("closed");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("supports direct put/get/del writes", async () => {
|
|
122
|
+
const { store } = await createStore();
|
|
123
|
+
|
|
124
|
+
await store.put("alpha", { value: 1 });
|
|
125
|
+
await store.put("beta", { value: 2 });
|
|
126
|
+
|
|
127
|
+
expect(await store.get("alpha")).toEqual({ value: 1 });
|
|
128
|
+
expect(await store.get("beta")).toEqual({ value: 2 });
|
|
129
|
+
|
|
130
|
+
await store.del("alpha");
|
|
131
|
+
await expect(store.get("alpha")).rejects.toMatchObject({
|
|
132
|
+
message: "NotFound",
|
|
133
|
+
notFound: true,
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("supports array-style batchWrite with mixed put/del operations", async () => {
|
|
138
|
+
const { store } = await createStore();
|
|
139
|
+
|
|
140
|
+
await store.batchWrite([
|
|
141
|
+
{ type: "put", key: "alpha", value: 1 },
|
|
142
|
+
{ type: "put", key: "beta", value: 2 },
|
|
143
|
+
{ type: "del", key: "alpha" },
|
|
144
|
+
]);
|
|
145
|
+
|
|
146
|
+
await expect(store.get("alpha")).rejects.toMatchObject({
|
|
147
|
+
message: "NotFound",
|
|
148
|
+
notFound: true,
|
|
149
|
+
});
|
|
150
|
+
expect(await store.get("beta")).toBe(2);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("supports builder-style createBatch writes", async () => {
|
|
154
|
+
const { store } = await createStore();
|
|
155
|
+
|
|
156
|
+
await store.put("alpha", 1);
|
|
157
|
+
|
|
158
|
+
const batch = store.createBatch();
|
|
159
|
+
batch.put("beta", 2);
|
|
160
|
+
batch.del("alpha");
|
|
161
|
+
batch.put("gamma", 3);
|
|
162
|
+
await batch.write();
|
|
163
|
+
|
|
164
|
+
await expect(store.get("alpha")).rejects.toMatchObject({
|
|
165
|
+
message: "NotFound",
|
|
166
|
+
notFound: true,
|
|
167
|
+
});
|
|
168
|
+
expect(await store.get("beta")).toBe(2);
|
|
169
|
+
expect(await store.get("gamma")).toBe(3);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("preserves ordered iterator range semantics", async () => {
|
|
173
|
+
const { store } = await createStore();
|
|
174
|
+
|
|
175
|
+
await store.put("a", 1);
|
|
176
|
+
await store.put("b", 2);
|
|
177
|
+
await store.put("c", 3);
|
|
178
|
+
|
|
179
|
+
const scanned: Array<[string, unknown]> = [];
|
|
180
|
+
for await (const entry of store.iterator({ gte: "a", lt: "c" })) {
|
|
181
|
+
scanned.push(entry);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
expect(scanned).toEqual([
|
|
185
|
+
["a", 1],
|
|
186
|
+
["b", 2],
|
|
187
|
+
]);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("preserves reverse iterator semantics within a bounded range", async () => {
|
|
191
|
+
const { store } = await createStore();
|
|
192
|
+
|
|
193
|
+
await store.put("a", 1);
|
|
194
|
+
await store.put("b", 2);
|
|
195
|
+
await store.put("c", 3);
|
|
196
|
+
|
|
197
|
+
const scanned: string[] = [];
|
|
198
|
+
for await (const [key] of store.iterator({
|
|
199
|
+
gte: "a",
|
|
200
|
+
lte: "c",
|
|
201
|
+
reverse: true,
|
|
202
|
+
})) {
|
|
203
|
+
scanned.push(key);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
expect(scanned).toEqual(["c", "b", "a"]);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type AuthorityBatchOperation =
|
|
2
|
+
| { type: "put"; key: string; value: unknown }
|
|
3
|
+
| { type: "del"; key: string };
|
|
4
|
+
|
|
5
|
+
export type AuthorityIteratorOptions = {
|
|
6
|
+
gte?: string;
|
|
7
|
+
lte?: string;
|
|
8
|
+
lt?: string;
|
|
9
|
+
reverse?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export interface AuthorityBatchWriter {
|
|
13
|
+
put(key: string, value: unknown): void;
|
|
14
|
+
del(key: string): void;
|
|
15
|
+
write(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface AuthorityStore {
|
|
19
|
+
readonly location?: string;
|
|
20
|
+
readonly status?: string;
|
|
21
|
+
open(): Promise<void>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
get<T = any>(key: string): Promise<T>;
|
|
24
|
+
put(key: string, value: unknown): Promise<void>;
|
|
25
|
+
del(key: string): Promise<void>;
|
|
26
|
+
batchWrite(ops: AuthorityBatchOperation[]): Promise<void>;
|
|
27
|
+
createBatch(): AuthorityBatchWriter;
|
|
28
|
+
iterator(
|
|
29
|
+
options?: AuthorityIteratorOptions
|
|
30
|
+
): AsyncIterableIterator<[string, unknown]>;
|
|
31
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { pino } from "pino";
|
|
2
|
-
import
|
|
2
|
+
import { getServerAuthorityStore } from "./db";
|
|
3
|
+
import { writeStoreOps } from "./storeBatchCompat";
|
|
3
4
|
import { chargeTokenUsageWithLedger } from "../../auth/server/tokenUsageBilling";
|
|
4
5
|
|
|
5
6
|
const logger = pino({ name: "dataHandlers" });
|
|
@@ -11,12 +12,18 @@ export const handleToken = async (
|
|
|
11
12
|
customKey?: string,
|
|
12
13
|
actionUserId?: string,
|
|
13
14
|
) => {
|
|
15
|
+
const store = getServerAuthorityStore();
|
|
14
16
|
const isStatsKey = customKey.includes("token-stats");
|
|
15
|
-
await
|
|
17
|
+
await store.put(customKey, data);
|
|
16
18
|
|
|
17
19
|
if (!isStatsKey && data.cost && data.cost > 0) {
|
|
18
20
|
try {
|
|
19
21
|
const txId = `token-${customKey}`;
|
|
22
|
+
const billingStore = {
|
|
23
|
+
get: (key: string) => store.get(key),
|
|
24
|
+
batch: (ops: Array<{ type: "put"; key: string; value: unknown }>) =>
|
|
25
|
+
writeStoreOps(store, ops),
|
|
26
|
+
};
|
|
20
27
|
logger.info({
|
|
21
28
|
event: "token_split_ledger_charge_start",
|
|
22
29
|
userId: data.userId,
|
|
@@ -24,7 +31,7 @@ export const handleToken = async (
|
|
|
24
31
|
txId,
|
|
25
32
|
});
|
|
26
33
|
const chargeResult = await chargeTokenUsageWithLedger({
|
|
27
|
-
store:
|
|
34
|
+
store: billingStore,
|
|
28
35
|
userId: data.userId,
|
|
29
36
|
tokenKey: customKey,
|
|
30
37
|
tokenRecord: data,
|
|
@@ -77,9 +84,10 @@ export const handleToken = async (
|
|
|
77
84
|
};
|
|
78
85
|
|
|
79
86
|
export const handleCybot = async (data: any, res: any, customKey: string) => {
|
|
87
|
+
const store = getServerAuthorityStore();
|
|
80
88
|
try {
|
|
81
|
-
await
|
|
82
|
-
const savedData = await
|
|
89
|
+
await store.put(customKey, data);
|
|
90
|
+
const savedData = await store.get(customKey);
|
|
83
91
|
|
|
84
92
|
const isDataMatch = JSON.stringify(data) === JSON.stringify(savedData);
|
|
85
93
|
if (!isDataMatch) {
|
package/database/server/db.ts
CHANGED
|
@@ -1,37 +1,17 @@
|
|
|
1
1
|
// 文件路径: packages/database/server/db.ts
|
|
2
2
|
|
|
3
|
-
import { Level } from "level";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import fs from "fs";
|
|
6
3
|
import { ensureDbOpen } from "./ensureDbOpen";
|
|
7
4
|
import { resolveServerDbPath } from "./dbPath";
|
|
5
|
+
import type { LegacyServerDb } from "./legacyServerDb";
|
|
6
|
+
import type { AuthorityStore } from "./authorityStoreTypes";
|
|
7
|
+
import { getOrCreateServerStoreRuntime } from "./serverStoreFactory";
|
|
8
8
|
|
|
9
9
|
const DB_PATH = resolveServerDbPath();
|
|
10
10
|
|
|
11
|
-
// 确保目录存在
|
|
12
|
-
if (!fs.existsSync(path.dirname(DB_PATH))) {
|
|
13
|
-
fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
|
|
14
|
-
}
|
|
15
|
-
|
|
16
11
|
console.log("数据库配置:");
|
|
17
12
|
console.log("- 当前工作目录:", process.cwd());
|
|
18
13
|
console.log("- 数据库路径:", DB_PATH);
|
|
19
14
|
|
|
20
|
-
// 安全 JSON 编码:解码失败时返回 null 而非抛异常,防止损坏记录导致进程崩溃
|
|
21
|
-
const safeJsonEncoding = {
|
|
22
|
-
name: "safe-json",
|
|
23
|
-
format: "utf8" as const,
|
|
24
|
-
encode: (data: any) => JSON.stringify(data),
|
|
25
|
-
decode: (data: string) => {
|
|
26
|
-
try {
|
|
27
|
-
return JSON.parse(data);
|
|
28
|
-
} catch {
|
|
29
|
-
console.warn("[LevelDB] Corrupted value:", data?.substring?.(0, 60));
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
15
|
export function isServerDbLockError(error: unknown): boolean {
|
|
36
16
|
const queue: unknown[] = [error];
|
|
37
17
|
const seen = new Set<unknown>();
|
|
@@ -55,13 +35,11 @@ export function isServerDbLockError(error: unknown): boolean {
|
|
|
55
35
|
return false;
|
|
56
36
|
}
|
|
57
37
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
const serverDb: Level<string, any> = (globalThis as any).__serverDb;
|
|
38
|
+
const {
|
|
39
|
+
authorityStore,
|
|
40
|
+
serverDb,
|
|
41
|
+
}: { authorityStore: AuthorityStore; serverDb: LegacyServerDb } =
|
|
42
|
+
getOrCreateServerStoreRuntime(DB_PATH);
|
|
65
43
|
|
|
66
44
|
console.log("- LevelDB实际路径:", serverDb.location);
|
|
67
45
|
|
|
@@ -70,6 +48,9 @@ export default serverDb;
|
|
|
70
48
|
|
|
71
49
|
// 具名导出:需要的时候可以引用
|
|
72
50
|
export { serverDb };
|
|
51
|
+
export function getServerAuthorityStore() {
|
|
52
|
+
return authorityStore;
|
|
53
|
+
}
|
|
73
54
|
|
|
74
55
|
/**
|
|
75
56
|
* 确保数据库处于 open 状态。
|
|
@@ -77,11 +58,11 @@ export { serverDb };
|
|
|
77
58
|
* - 其他状态:尝试 open,一旦失败抛错
|
|
78
59
|
*/
|
|
79
60
|
export async function ensureServerDbOpen() {
|
|
80
|
-
const status =
|
|
61
|
+
const status = authorityStore.status;
|
|
81
62
|
if (status === "open") return;
|
|
82
63
|
|
|
83
64
|
try {
|
|
84
|
-
await ensureDbOpen(
|
|
65
|
+
await ensureDbOpen(authorityStore);
|
|
85
66
|
if (status !== "opening") {
|
|
86
67
|
console.log("✅ LevelDB 已打开");
|
|
87
68
|
}
|
|
@@ -106,11 +87,11 @@ export async function openServerDb() {
|
|
|
106
87
|
* 优雅关机时关闭 DB
|
|
107
88
|
*/
|
|
108
89
|
export async function closeServerDb() {
|
|
109
|
-
const status =
|
|
90
|
+
const status = authorityStore.status;
|
|
110
91
|
if (status !== "open") return;
|
|
111
92
|
|
|
112
93
|
try {
|
|
113
|
-
await
|
|
94
|
+
await authorityStore.close();
|
|
114
95
|
console.log("✅ LevelDB 已关闭");
|
|
115
96
|
} catch (err) {
|
|
116
97
|
console.error("❌ 关闭 LevelDB 失败:", err);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// 文件: database/server/delete.ts
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { getServerAuthorityStore } from "./db";
|
|
4
4
|
import { DataType } from "../../create/types";
|
|
5
5
|
import { deleteMessages } from "../../chat/messages/deleteMessages";
|
|
6
6
|
import { deleteTable } from "../table/deleteTable";
|
|
@@ -15,13 +15,14 @@ import {
|
|
|
15
15
|
} from "../keys";
|
|
16
16
|
import { buildTombstoneRecord, isTombstoneRecord } from "../tombstones";
|
|
17
17
|
import { canDeleteSpaceMemberRecord, parseSpaceMemberKey } from "./spaceMemberAuthority";
|
|
18
|
-
import {
|
|
19
|
-
bootstrapReplicatedTable,
|
|
20
|
-
findActiveLiveShareByTable,
|
|
21
|
-
isLiveTableShareRecord,
|
|
22
|
-
patchShareMeta,
|
|
23
|
-
replicateSharedTableMutation,
|
|
24
|
-
} from "../../share/server/tableReplication";
|
|
18
|
+
import {
|
|
19
|
+
bootstrapReplicatedTable,
|
|
20
|
+
findActiveLiveShareByTable,
|
|
21
|
+
isLiveTableShareRecord,
|
|
22
|
+
patchShareMeta,
|
|
23
|
+
replicateSharedTableMutation,
|
|
24
|
+
} from "../../share/server/tableReplication";
|
|
25
|
+
import { createStoreBatch, writeStoreOps } from "./storeBatchCompat";
|
|
25
26
|
|
|
26
27
|
type DeleteRequest = Request & {
|
|
27
28
|
// 视你的路由库而定,这里假定有 params.id
|
|
@@ -48,7 +49,7 @@ const getRequestOrigin = (req: Request): string => {
|
|
|
48
49
|
}
|
|
49
50
|
};
|
|
50
51
|
|
|
51
|
-
const getForwardHeaders = (req: any): Record<string, string> => {
|
|
52
|
+
const getForwardHeaders = (req: any): Record<string, string> => {
|
|
52
53
|
const headers: Record<string, string> = {
|
|
53
54
|
"Content-Type": "application/json",
|
|
54
55
|
};
|
|
@@ -62,14 +63,15 @@ const getForwardHeaders = (req: any): Record<string, string> => {
|
|
|
62
63
|
headers.Authorization = authHeader;
|
|
63
64
|
}
|
|
64
65
|
return headers;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const findLiveTableSharesByDbKey = async (tableDbKey: string) => {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const findLiveTableSharesByDbKey = async (tableDbKey: string) => {
|
|
69
|
+
const store = getServerAuthorityStore();
|
|
70
|
+
const shares: any[] = [];
|
|
71
|
+
for await (const [dbKey, value] of store.iterator({
|
|
72
|
+
gte: "share-",
|
|
73
|
+
lte: "share-\uffff",
|
|
74
|
+
})) {
|
|
73
75
|
if (
|
|
74
76
|
isLiveTableShareRecord(value, tableDbKey)
|
|
75
77
|
) {
|
|
@@ -135,18 +137,33 @@ const canSystemUserDeletePublicCybot = (
|
|
|
135
137
|
return isPublicCybotKey && isSystemUser;
|
|
136
138
|
};
|
|
137
139
|
|
|
138
|
-
const canSystemAdminDeleteCommunityShare = (
|
|
139
|
-
dbKey: string,
|
|
140
|
-
actionUserId: string | undefined,
|
|
141
|
-
data: any
|
|
140
|
+
const canSystemAdminDeleteCommunityShare = (
|
|
141
|
+
dbKey: string,
|
|
142
|
+
actionUserId: string | undefined,
|
|
143
|
+
data: any
|
|
142
144
|
): boolean => {
|
|
143
145
|
if (!isSystemAdmin(actionUserId)) return false;
|
|
144
|
-
if (!shareKey.isShareKey(dbKey)) return false;
|
|
145
|
-
return data?.meta?.visibility === "community";
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
if (!shareKey.isShareKey(dbKey)) return false;
|
|
147
|
+
return data?.meta?.visibility === "community";
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const createDeleteCompatDb = (store = getServerAuthorityStore()) => ({
|
|
151
|
+
batch: (
|
|
152
|
+
ops?: Array<{ type: "put" | "del"; key: string; value?: unknown }>
|
|
153
|
+
) => {
|
|
154
|
+
if (Array.isArray(ops)) {
|
|
155
|
+
return writeStoreOps(store, ops);
|
|
156
|
+
}
|
|
157
|
+
return createStoreBatch(store);
|
|
158
|
+
},
|
|
159
|
+
iterator: (options: { gte: string; lte: string }) => store.iterator(options),
|
|
160
|
+
del: (key: string) => store.del(key),
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
export const handleDelete = async (req: DeleteRequest) => {
|
|
164
|
+
const store = getServerAuthorityStore();
|
|
165
|
+
const deleteCompatDb = createDeleteCompatDb(store);
|
|
166
|
+
try {
|
|
150
167
|
const authResult = await authenticateRequest(req);
|
|
151
168
|
const actionUserId = authResult instanceof Response ? undefined : authResult.userId;
|
|
152
169
|
|
|
@@ -154,10 +171,10 @@ export const handleDelete = async (req: DeleteRequest) => {
|
|
|
154
171
|
const url = new URL(req.url);
|
|
155
172
|
const type = url.searchParams.get("type");
|
|
156
173
|
|
|
157
|
-
// 1. 删除消息的专用分支
|
|
158
|
-
if (type === "messages") {
|
|
159
|
-
try {
|
|
160
|
-
const result = await deleteMessages(
|
|
174
|
+
// 1. 删除消息的专用分支
|
|
175
|
+
if (type === "messages") {
|
|
176
|
+
try {
|
|
177
|
+
const result = await deleteMessages(deleteCompatDb, id);
|
|
161
178
|
return new Response(JSON.stringify(result), {
|
|
162
179
|
status: 200,
|
|
163
180
|
headers: CORS_HEADERS,
|
|
@@ -174,11 +191,11 @@ export const handleDelete = async (req: DeleteRequest) => {
|
|
|
174
191
|
}
|
|
175
192
|
|
|
176
193
|
// 1.5 删除整张表(meta + 所有行 + 所有索引)的专用分支
|
|
177
|
-
if (type === "table") {
|
|
178
|
-
// 先拿 meta 数据做权限校验
|
|
179
|
-
let meta;
|
|
180
|
-
try {
|
|
181
|
-
meta = await
|
|
194
|
+
if (type === "table") {
|
|
195
|
+
// 先拿 meta 数据做权限校验
|
|
196
|
+
let meta;
|
|
197
|
+
try {
|
|
198
|
+
meta = await store.get(id);
|
|
182
199
|
} catch (err: any) {
|
|
183
200
|
if (err.notFound) {
|
|
184
201
|
return new Response(JSON.stringify({ message: "Table already deleted", processingIds: [] }), {
|
|
@@ -209,10 +226,10 @@ export const handleDelete = async (req: DeleteRequest) => {
|
|
|
209
226
|
);
|
|
210
227
|
}
|
|
211
228
|
|
|
212
|
-
await propagateTableDeleteToReplicas(req, id);
|
|
213
|
-
|
|
214
|
-
// 真正执行整表删除
|
|
215
|
-
const { processingIds } = await deleteTable(
|
|
229
|
+
await propagateTableDeleteToReplicas(req, id);
|
|
230
|
+
|
|
231
|
+
// 真正执行整表删除
|
|
232
|
+
const { processingIds } = await deleteTable(deleteCompatDb, id);
|
|
216
233
|
|
|
217
234
|
return new Response(
|
|
218
235
|
JSON.stringify({
|
|
@@ -226,10 +243,10 @@ export const handleDelete = async (req: DeleteRequest) => {
|
|
|
226
243
|
);
|
|
227
244
|
}
|
|
228
245
|
|
|
229
|
-
// 2. 删除通用数据(单 key 删除)
|
|
230
|
-
let data;
|
|
231
|
-
try {
|
|
232
|
-
data = await
|
|
246
|
+
// 2. 删除通用数据(单 key 删除)
|
|
247
|
+
let data;
|
|
248
|
+
try {
|
|
249
|
+
data = await store.get(id);
|
|
233
250
|
} catch (err: any) {
|
|
234
251
|
if (err.notFound) {
|
|
235
252
|
return new Response(
|
|
@@ -287,16 +304,16 @@ export const handleDelete = async (req: DeleteRequest) => {
|
|
|
287
304
|
);
|
|
288
305
|
}
|
|
289
306
|
|
|
290
|
-
// Share 记录 → 物理删除(主记录 + 所有索引键);通用记录 → tombstone
|
|
291
|
-
if (isShareRecord) {
|
|
292
|
-
const indexes = shareKey.allIndexKeysFromShare(id, data);
|
|
293
|
-
const batch =
|
|
294
|
-
batch.del(id);
|
|
295
|
-
for (const ik of indexes) batch.del(ik);
|
|
296
|
-
await batch.write();
|
|
297
|
-
} else {
|
|
298
|
-
await
|
|
299
|
-
}
|
|
307
|
+
// Share 记录 → 物理删除(主记录 + 所有索引键);通用记录 → tombstone
|
|
308
|
+
if (isShareRecord) {
|
|
309
|
+
const indexes = shareKey.allIndexKeysFromShare(id, data);
|
|
310
|
+
const batch = store.createBatch();
|
|
311
|
+
batch.del(id);
|
|
312
|
+
for (const ik of indexes) batch.del(ik);
|
|
313
|
+
await batch.write();
|
|
314
|
+
} else {
|
|
315
|
+
await store.put(id, buildTombstoneRecord(data, new Date().toISOString()));
|
|
316
|
+
}
|
|
300
317
|
|
|
301
318
|
if (
|
|
302
319
|
data?.type === DataType.TABLE_ROW &&
|
|
@@ -411,15 +428,15 @@ export const handleDelete = async (req: DeleteRequest) => {
|
|
|
411
428
|
invalidatePublicAgentsCache();
|
|
412
429
|
}
|
|
413
430
|
|
|
414
|
-
// 如果被删除的是 Agent,则级联清理所有的收藏关系及统计
|
|
415
|
-
if (isAgentKey(id)) {
|
|
416
|
-
const { start, end } = createFavoriteKey.userRangeOfAgentKey(id);
|
|
417
|
-
const batch =
|
|
418
|
-
|
|
419
|
-
for await (const [reverseKey] of
|
|
420
|
-
gte: start,
|
|
421
|
-
lte: end,
|
|
422
|
-
})) {
|
|
431
|
+
// 如果被删除的是 Agent,则级联清理所有的收藏关系及统计
|
|
432
|
+
if (isAgentKey(id)) {
|
|
433
|
+
const { start, end } = createFavoriteKey.userRangeOfAgentKey(id);
|
|
434
|
+
const batch = store.createBatch();
|
|
435
|
+
|
|
436
|
+
for await (const [reverseKey] of store.iterator({
|
|
437
|
+
gte: start,
|
|
438
|
+
lte: end,
|
|
439
|
+
})) {
|
|
423
440
|
if (!reverseKey.startsWith(start)) continue;
|
|
424
441
|
|
|
425
442
|
// reverseKey: fav-agent-key-by-agent-{agentKey}-{userId}
|
|
@@ -439,14 +456,14 @@ export const handleDelete = async (req: DeleteRequest) => {
|
|
|
439
456
|
|
|
440
457
|
// 如果被删除的是 Dialog,则级联清理该对话下的所有消息
|
|
441
458
|
// Dialog Key 结构: dialog-{userId}-{dialogId} (3 parts)
|
|
442
|
-
const parts = id.split("-");
|
|
443
|
-
if (parts[0] === "dialog" && parts.length === 3) {
|
|
444
|
-
const dialogId = parts[2];
|
|
445
|
-
if (dialogId) {
|
|
446
|
-
console.log(`[Delete] Cascading messages for dialog: ${dialogId}`);
|
|
447
|
-
await deleteMessages(
|
|
448
|
-
}
|
|
449
|
-
}
|
|
459
|
+
const parts = id.split("-");
|
|
460
|
+
if (parts[0] === "dialog" && parts.length === 3) {
|
|
461
|
+
const dialogId = parts[2];
|
|
462
|
+
if (dialogId) {
|
|
463
|
+
console.log(`[Delete] Cascading messages for dialog: ${dialogId}`);
|
|
464
|
+
await deleteMessages(deleteCompatDb, dialogId);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
450
467
|
}
|
|
451
468
|
|
|
452
469
|
return new Response(
|
|
@@ -8,15 +8,17 @@ import type {
|
|
|
8
8
|
} from "../email";
|
|
9
9
|
import { emailKey } from "../keys";
|
|
10
10
|
import type { ApiContext, ApiError } from "../../server/api/types";
|
|
11
|
-
import {
|
|
12
|
-
type EmailProvider,
|
|
13
|
-
type EmailProviderSendResult,
|
|
14
|
-
} from "../../server/email/provider";
|
|
15
|
-
import { getEmailProvider } from "../../server/email/providerRegistry";
|
|
16
|
-
import { authorizeActorRecordAccess } from "./actorAccess";
|
|
17
|
-
import { agentDelegationKey } from "./agentDelegation";
|
|
18
|
-
import
|
|
19
|
-
import { resolveKeyOwnerId } from "./writeAuthority";
|
|
11
|
+
import {
|
|
12
|
+
type EmailProvider,
|
|
13
|
+
type EmailProviderSendResult,
|
|
14
|
+
} from "../../server/email/provider";
|
|
15
|
+
import { getEmailProvider } from "../../server/email/providerRegistry";
|
|
16
|
+
import { authorizeActorRecordAccess } from "./actorAccess";
|
|
17
|
+
import { agentDelegationKey } from "./agentDelegation";
|
|
18
|
+
import { getServerAuthorityStore } from "./db";
|
|
19
|
+
import { resolveKeyOwnerId } from "./writeAuthority";
|
|
20
|
+
|
|
21
|
+
const serverDb = getServerAuthorityStore();
|
|
20
22
|
|
|
21
23
|
type CreateEmailRecordInput = {
|
|
22
24
|
ownerId: string;
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { mkdir } from "node:fs/promises";
|
|
5
5
|
import { ulid } from "ulid";
|
|
6
|
-
import
|
|
6
|
+
import { getServerAuthorityStore } from "./db";
|
|
7
7
|
import { blobKey, fileKey, fileIdIndexKey, fileStatKey } from "../keys";
|
|
8
8
|
import { isTombstoneRecord } from "../tombstones";
|
|
9
9
|
import { DataType } from "../../create/types";
|
|
10
10
|
|
|
11
11
|
const UPLOAD_DIR = path.join(process.cwd(), "data", "uploads");
|
|
12
|
+
const serverDb = getServerAuthorityStore();
|
|
12
13
|
|
|
13
14
|
type JsonRecord = Record<string, any>;
|
|
14
15
|
|