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