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
|
@@ -28,13 +28,41 @@
|
|
|
28
28
|
|
|
29
29
|
import { createHash } from "node:crypto";
|
|
30
30
|
import { ulid } from "ulid";
|
|
31
|
+
import { userActor } from "../../../auth/actor";
|
|
31
32
|
import { authenticateRequest } from "../../../auth/utils";
|
|
32
33
|
import { WEB_AUTH_TOKEN_COOKIE } from "../../../auth/tokenCookie";
|
|
33
34
|
import { getUser } from "../../../auth/server/getUser";
|
|
34
35
|
import { checkBasicBalance } from "../../../auth/billing";
|
|
36
|
+
import {
|
|
37
|
+
GPT_PRO_REQUIRED_BALANCE,
|
|
38
|
+
hasGptProTierAccess,
|
|
39
|
+
isGptProModel,
|
|
40
|
+
} from "../../../auth/server/gptProAccess";
|
|
35
41
|
import { chargeTokenUsageWithLedger } from "../../../auth/server/tokenUsageBilling";
|
|
36
42
|
import { writeServerTokenRecord } from "../../../ai/token/serverTokenWriter";
|
|
37
|
-
import
|
|
43
|
+
import {
|
|
44
|
+
createProviderCallCompletedEvent,
|
|
45
|
+
createProviderCallPendingEvent,
|
|
46
|
+
type ProviderCallEvent,
|
|
47
|
+
} from "../../../ai/token/providerCall";
|
|
48
|
+
import { writeProviderCallEvent } from "../../../ai/token/providerCallWriter";
|
|
49
|
+
import {
|
|
50
|
+
createProviderBillableEvent,
|
|
51
|
+
type ProviderBillableEvent,
|
|
52
|
+
} from "../../../ai/token/providerBillableEvent";
|
|
53
|
+
import { writeProviderBillableEvent } from "../../../ai/token/providerBillableEventWriter";
|
|
54
|
+
import { createRatingResult, type RatingResult } from "../../../ai/token/ratingResult";
|
|
55
|
+
import { writeRatingResult } from "../../../ai/token/ratingResultWriter";
|
|
56
|
+
import type { Usage } from "../../../ai/token/calculatePrice";
|
|
57
|
+
import {
|
|
58
|
+
createBillingAnomaly,
|
|
59
|
+
type BillingAnomaly,
|
|
60
|
+
type BillingAnomalyKind,
|
|
61
|
+
type BillingAnomalySeverity,
|
|
62
|
+
type BillingAnomalyStage,
|
|
63
|
+
} from "../../../ai/token/billingAnomaly";
|
|
64
|
+
import { writeBillingAnomaly } from "../../../ai/token/billingAnomalyWriter";
|
|
65
|
+
import { ensureServerDbOpen, getServerAuthorityStore } from "../../../database/server/db";
|
|
38
66
|
import { runAgentLoop, buildSseStream } from "./loop";
|
|
39
67
|
import { incActiveStream, decActiveStream } from "../../serverDrain";
|
|
40
68
|
import { saveRunAsDialog, createPendingDialog, finalizeDialog, appendToExistingDialog } from "./saveDialog";
|
|
@@ -71,7 +99,6 @@ import {
|
|
|
71
99
|
} from "./builtinAgents";
|
|
72
100
|
import { resolveAgentRunAgentConfig } from "./agentLookup";
|
|
73
101
|
import {
|
|
74
|
-
resolveAgentRunDelegation,
|
|
75
102
|
resolveMachineBindingPreflight,
|
|
76
103
|
} from "./runtimeRouting";
|
|
77
104
|
import {
|
|
@@ -83,7 +110,7 @@ import {
|
|
|
83
110
|
} from "./requestContext";
|
|
84
111
|
import { buildAgentRunDebugContext } from "./debugContext";
|
|
85
112
|
import { resolveAgentRunBilledUsage } from "./runBilling";
|
|
86
|
-
import {
|
|
113
|
+
import { buildConversationReferenceBlock } from "./conversationReference";
|
|
87
114
|
import { completeSyncAgentRunDialog } from "./syncRunDialog";
|
|
88
115
|
import {
|
|
89
116
|
AGENT_RUN_CORS_HEADERS as CORS,
|
|
@@ -94,6 +121,7 @@ import {
|
|
|
94
121
|
import { machineRegistry } from "../machines/machineRegistry";
|
|
95
122
|
import {
|
|
96
123
|
ConnectorOfflineError,
|
|
124
|
+
InvalidBoundMachineConfigError,
|
|
97
125
|
type MachineConnectorRunProgress,
|
|
98
126
|
resolveAgentRuntimeMachineId,
|
|
99
127
|
runViaMachineConnector,
|
|
@@ -112,6 +140,9 @@ type AgentRunBillingInput = Parameters<typeof resolveAgentRunBilledUsage>[0] & {
|
|
|
112
140
|
const DEFAULT_BACKGROUND_RUN_TIMEOUT_MS = 10 * 60_000;
|
|
113
141
|
const DEFAULT_RUNTIME_PROMPT_PAGE_THRESHOLD_BYTES = 32_000;
|
|
114
142
|
|
|
143
|
+
const getAgentRunStore = () => getServerAuthorityStore();
|
|
144
|
+
const serverDb = getAgentRunStore();
|
|
145
|
+
|
|
115
146
|
function byteLength(value: string) {
|
|
116
147
|
return Buffer.byteLength(value, "utf8");
|
|
117
148
|
}
|
|
@@ -209,7 +240,11 @@ async function withBackgroundRunTimeout<T>(
|
|
|
209
240
|
}
|
|
210
241
|
}
|
|
211
242
|
|
|
212
|
-
async function chargeAgentRunTokenCost(
|
|
243
|
+
async function chargeAgentRunTokenCost(
|
|
244
|
+
userId: string,
|
|
245
|
+
tokenWrite: AgentRunTokenWrite,
|
|
246
|
+
ledgerIdempotencyKey: string,
|
|
247
|
+
) {
|
|
213
248
|
return chargeTokenUsageWithLedger({
|
|
214
249
|
store: serverDb,
|
|
215
250
|
userId,
|
|
@@ -217,9 +252,193 @@ async function chargeAgentRunTokenCost(userId: string, tokenWrite: AgentRunToken
|
|
|
217
252
|
tokenRecord: tokenWrite.tokenRecord,
|
|
218
253
|
reason: "agent_run",
|
|
219
254
|
txId: `token-${tokenWrite.recordKey}`,
|
|
255
|
+
ledgerIdempotencyKey,
|
|
256
|
+
allowBuyerNegative: true,
|
|
220
257
|
});
|
|
221
258
|
}
|
|
222
259
|
|
|
260
|
+
function buildAggregateProviderCallLedgerIdempotencyKey(providerCallIds: string[]) {
|
|
261
|
+
const stableSource = [...new Set(providerCallIds)].sort().join("|");
|
|
262
|
+
const sourceHash = createHash("sha256").update(stableSource).digest("hex").slice(0, 16);
|
|
263
|
+
return `provider-call-group:sha256-${sourceHash}:charge:v1`;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async function writeProviderCallEventSafely(event: ProviderCallEvent) {
|
|
267
|
+
try {
|
|
268
|
+
await writeProviderCallEvent({ store: serverDb, event });
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.warn("[billing] Provider-call evidence write failed", {
|
|
271
|
+
providerCallId: event.providerCallId,
|
|
272
|
+
eventId: event.eventId,
|
|
273
|
+
status: event.status,
|
|
274
|
+
error: error instanceof Error ? error.message : String(error),
|
|
275
|
+
});
|
|
276
|
+
await writeBillingAnomalySafely(createAgentRunBillingAnomaly({
|
|
277
|
+
kind: "provider_call_write_failed",
|
|
278
|
+
severity: "high",
|
|
279
|
+
stage: "provider_call",
|
|
280
|
+
userId: event.userId,
|
|
281
|
+
dialogId: event.dialogId,
|
|
282
|
+
agentId: event.agentId,
|
|
283
|
+
provider: event.provider,
|
|
284
|
+
model: event.model,
|
|
285
|
+
providerCallId: event.providerCallId,
|
|
286
|
+
message: "Provider-call evidence write failed",
|
|
287
|
+
evidence: {
|
|
288
|
+
eventId: event.eventId,
|
|
289
|
+
eventStatus: event.status,
|
|
290
|
+
error: error instanceof Error ? error.message : String(error),
|
|
291
|
+
},
|
|
292
|
+
}));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async function writeBillingAnomalySafely(anomaly: BillingAnomaly) {
|
|
297
|
+
try {
|
|
298
|
+
await writeBillingAnomaly({ store: serverDb, anomaly });
|
|
299
|
+
} catch (error) {
|
|
300
|
+
console.warn("[billing] Billing anomaly write failed", {
|
|
301
|
+
anomalyId: anomaly.id,
|
|
302
|
+
kind: anomaly.kind,
|
|
303
|
+
providerCallId: anomaly.providerCallId,
|
|
304
|
+
error: error instanceof Error ? error.message : String(error),
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function createAgentRunBillingAnomaly(args: {
|
|
310
|
+
kind: BillingAnomalyKind;
|
|
311
|
+
severity: BillingAnomalySeverity;
|
|
312
|
+
stage: BillingAnomalyStage;
|
|
313
|
+
userId: string;
|
|
314
|
+
dialogId?: string;
|
|
315
|
+
agentId?: string;
|
|
316
|
+
provider: string;
|
|
317
|
+
model: string;
|
|
318
|
+
providerCallId?: string;
|
|
319
|
+
billableEventId?: string;
|
|
320
|
+
ratingResultId?: string;
|
|
321
|
+
riskPlatformCredits?: number;
|
|
322
|
+
message: string;
|
|
323
|
+
evidence: Record<string, unknown>;
|
|
324
|
+
}) {
|
|
325
|
+
return createBillingAnomaly({
|
|
326
|
+
anomalyId: `anom_${ulid()}`,
|
|
327
|
+
kind: args.kind,
|
|
328
|
+
severity: args.severity,
|
|
329
|
+
stage: args.stage,
|
|
330
|
+
userId: args.userId,
|
|
331
|
+
dialogId: args.dialogId,
|
|
332
|
+
agentId: args.agentId,
|
|
333
|
+
provider: args.provider,
|
|
334
|
+
model: args.model,
|
|
335
|
+
providerCallId: args.providerCallId,
|
|
336
|
+
billableEventId: args.billableEventId,
|
|
337
|
+
ratingResultId: args.ratingResultId,
|
|
338
|
+
riskPlatformCredits: args.riskPlatformCredits,
|
|
339
|
+
message: args.message,
|
|
340
|
+
evidence: args.evidence,
|
|
341
|
+
createdAt: new Date().toISOString(),
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
async function writeProviderBillableEventSafely(event: ProviderBillableEvent) {
|
|
346
|
+
try {
|
|
347
|
+
await writeProviderBillableEvent({ store: serverDb, event });
|
|
348
|
+
} catch (error) {
|
|
349
|
+
console.warn("[billing] Provider billable event write failed", {
|
|
350
|
+
billableEventId: event.id,
|
|
351
|
+
sourceProviderCallIds: event.sourceProviderCallIds,
|
|
352
|
+
provider: event.provider,
|
|
353
|
+
model: event.model,
|
|
354
|
+
error: error instanceof Error ? error.message : String(error),
|
|
355
|
+
});
|
|
356
|
+
await writeBillingAnomalySafely(createAgentRunBillingAnomaly({
|
|
357
|
+
kind: "billable_event_write_failed",
|
|
358
|
+
severity: "high",
|
|
359
|
+
stage: "billable_event",
|
|
360
|
+
userId: event.userId,
|
|
361
|
+
dialogId: event.dialogId,
|
|
362
|
+
agentId: event.agentId,
|
|
363
|
+
provider: event.provider,
|
|
364
|
+
model: event.model,
|
|
365
|
+
providerCallId: event.sourceProviderCallIds[0],
|
|
366
|
+
billableEventId: event.id,
|
|
367
|
+
message: "Provider billable event write failed",
|
|
368
|
+
evidence: {
|
|
369
|
+
sourceProviderCallIds: event.sourceProviderCallIds,
|
|
370
|
+
error: error instanceof Error ? error.message : String(error),
|
|
371
|
+
},
|
|
372
|
+
}));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async function writeRatingResultSafely(
|
|
377
|
+
rating: RatingResult,
|
|
378
|
+
context: {
|
|
379
|
+
userId: string;
|
|
380
|
+
dialogId?: string;
|
|
381
|
+
agentId?: string;
|
|
382
|
+
providerCallId?: string;
|
|
383
|
+
},
|
|
384
|
+
) {
|
|
385
|
+
try {
|
|
386
|
+
await writeRatingResult({ store: serverDb, rating });
|
|
387
|
+
} catch (error) {
|
|
388
|
+
console.warn("[billing] Rating result write failed", {
|
|
389
|
+
ratingId: rating.id,
|
|
390
|
+
billableEventId: rating.billableEventId,
|
|
391
|
+
provider: rating.provider,
|
|
392
|
+
model: rating.model,
|
|
393
|
+
error: error instanceof Error ? error.message : String(error),
|
|
394
|
+
});
|
|
395
|
+
await writeBillingAnomalySafely(createAgentRunBillingAnomaly({
|
|
396
|
+
kind: "rating_failed",
|
|
397
|
+
severity: "high",
|
|
398
|
+
stage: "rating",
|
|
399
|
+
userId: context.userId,
|
|
400
|
+
dialogId: context.dialogId,
|
|
401
|
+
agentId: context.agentId,
|
|
402
|
+
provider: rating.provider,
|
|
403
|
+
model: rating.model,
|
|
404
|
+
providerCallId: context.providerCallId,
|
|
405
|
+
billableEventId: rating.billableEventId,
|
|
406
|
+
ratingResultId: rating.id,
|
|
407
|
+
riskPlatformCredits: rating.platformCredits,
|
|
408
|
+
message: "Rating result write failed",
|
|
409
|
+
evidence: {
|
|
410
|
+
error: error instanceof Error ? error.message : String(error),
|
|
411
|
+
snapshot: rating.snapshot,
|
|
412
|
+
},
|
|
413
|
+
}));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function numberOrZero(value: unknown) {
|
|
418
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function normalizeAgentRunBillingUsage(rawUsage: Record<string, any>): Usage {
|
|
422
|
+
return {
|
|
423
|
+
input_tokens: numberOrZero(rawUsage.input_tokens ?? rawUsage.prompt_tokens),
|
|
424
|
+
output_tokens: numberOrZero(rawUsage.output_tokens ?? rawUsage.completion_tokens),
|
|
425
|
+
cache_creation_input_tokens: numberOrZero(rawUsage.cache_creation_input_tokens),
|
|
426
|
+
cache_read_input_tokens: numberOrZero(rawUsage.cache_read_input_tokens),
|
|
427
|
+
...(typeof rawUsage.cost === "number" ? { cost: rawUsage.cost } : {}),
|
|
428
|
+
...(typeof rawUsage.billing_service_tier === "string"
|
|
429
|
+
? { billing_service_tier: rawUsage.billing_service_tier }
|
|
430
|
+
: {}),
|
|
431
|
+
...(typeof rawUsage.image_generation_count === "number"
|
|
432
|
+
? { image_generation_count: rawUsage.image_generation_count }
|
|
433
|
+
: {}),
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function resolveEstimateReason(rawUsage: Record<string, any>) {
|
|
438
|
+
const reason = rawUsage.billing_estimate_reason ?? rawUsage.estimateReason ?? rawUsage.estimate_reason;
|
|
439
|
+
return typeof reason === "string" && reason.trim() ? reason.trim() : undefined;
|
|
440
|
+
}
|
|
441
|
+
|
|
223
442
|
async function projectBackgroundDialogActivity(args: {
|
|
224
443
|
dialogId: string;
|
|
225
444
|
dialogKey: string;
|
|
@@ -384,6 +603,43 @@ async function writeAgentRunBillingIfNeeded(args: AgentRunBillingInput) {
|
|
|
384
603
|
});
|
|
385
604
|
if (!args.userId || !billedUsage) return;
|
|
386
605
|
|
|
606
|
+
const rawUsage = billedUsage as any;
|
|
607
|
+
const physicalProviderCallIds = Array.isArray(args.result.providerCallIds)
|
|
608
|
+
? args.result.providerCallIds.filter((id): id is string => typeof id === "string" && id.trim().startsWith("call_"))
|
|
609
|
+
: [];
|
|
610
|
+
const hasAggregatePhysicalUsage = physicalProviderCallIds.length > 1;
|
|
611
|
+
const providerCallId = physicalProviderCallIds[physicalProviderCallIds.length - 1] ?? `call_${ulid()}`;
|
|
612
|
+
const providerCallStartedAt = new Date().toISOString();
|
|
613
|
+
const billingProvider =
|
|
614
|
+
rawUsage.billing_provider ??
|
|
615
|
+
billingAgentConfig.provider ??
|
|
616
|
+
args.result.provider ??
|
|
617
|
+
"unknown";
|
|
618
|
+
const billingModel =
|
|
619
|
+
rawUsage.billing_model ??
|
|
620
|
+
billingAgentConfig.model ??
|
|
621
|
+
args.result.model ??
|
|
622
|
+
"unknown";
|
|
623
|
+
const billingServiceTier =
|
|
624
|
+
rawUsage.billing_service_tier ??
|
|
625
|
+
billingAgentConfig.billingServiceTier ??
|
|
626
|
+
billingAgentConfig.serviceTier;
|
|
627
|
+
|
|
628
|
+
if (physicalProviderCallIds.length === 0) {
|
|
629
|
+
await writeProviderCallEventSafely(createProviderCallPendingEvent({
|
|
630
|
+
providerCallId,
|
|
631
|
+
eventId: `evt_${ulid()}`,
|
|
632
|
+
userId: args.userId,
|
|
633
|
+
dialogId: args.dialogId,
|
|
634
|
+
agentId: args.agentKey,
|
|
635
|
+
provider: billingProvider,
|
|
636
|
+
model: billingModel,
|
|
637
|
+
endpoint: "agentRun",
|
|
638
|
+
...(billingServiceTier ? { serviceTier: String(billingServiceTier) } : {}),
|
|
639
|
+
startedAt: providerCallStartedAt,
|
|
640
|
+
}));
|
|
641
|
+
}
|
|
642
|
+
|
|
387
643
|
const tokenWrite = await writeServerTokenRecord({
|
|
388
644
|
userId: args.userId,
|
|
389
645
|
agentKey: args.agentKey,
|
|
@@ -391,7 +647,120 @@ async function writeAgentRunBillingIfNeeded(args: AgentRunBillingInput) {
|
|
|
391
647
|
runId: args.dialogId,
|
|
392
648
|
rawUsage: billedUsage as any,
|
|
393
649
|
});
|
|
394
|
-
|
|
650
|
+
const normalizedBillingUsage = normalizeAgentRunBillingUsage(rawUsage);
|
|
651
|
+
if (!hasAggregatePhysicalUsage) {
|
|
652
|
+
await writeProviderCallEventSafely(createProviderCallCompletedEvent({
|
|
653
|
+
providerCallId,
|
|
654
|
+
eventId: `evt_${ulid()}`,
|
|
655
|
+
userId: args.userId,
|
|
656
|
+
dialogId: args.dialogId,
|
|
657
|
+
agentId: args.agentKey,
|
|
658
|
+
provider: billingProvider,
|
|
659
|
+
model: billingModel,
|
|
660
|
+
endpoint: "agentRun",
|
|
661
|
+
...(billingServiceTier ? { serviceTier: String(billingServiceTier) } : {}),
|
|
662
|
+
startedAt: providerCallStartedAt,
|
|
663
|
+
completedAt: new Date().toISOString(),
|
|
664
|
+
inputTokens: normalizedBillingUsage.input_tokens,
|
|
665
|
+
outputTokens: normalizedBillingUsage.output_tokens,
|
|
666
|
+
cacheCreationInputTokens: normalizedBillingUsage.cache_creation_input_tokens,
|
|
667
|
+
cacheReadInputTokens: normalizedBillingUsage.cache_read_input_tokens,
|
|
668
|
+
platformCredits: tokenWrite.cost,
|
|
669
|
+
pricingVersion: "model-registry-current",
|
|
670
|
+
billingStatus: tokenWrite.cost > 0 ? "pending_ledger" : "zero_policy",
|
|
671
|
+
}));
|
|
672
|
+
}
|
|
673
|
+
const billableEventId = `billable_${ulid()}`;
|
|
674
|
+
const ledgerIdempotencyKey = hasAggregatePhysicalUsage
|
|
675
|
+
? buildAggregateProviderCallLedgerIdempotencyKey(physicalProviderCallIds)
|
|
676
|
+
: `provider-call:${providerCallId}:charge:v1`;
|
|
677
|
+
const billableEvent = createProviderBillableEvent({
|
|
678
|
+
eventId: billableEventId,
|
|
679
|
+
operationId: args.dialogId,
|
|
680
|
+
sourceProviderCallIds: physicalProviderCallIds.length > 0
|
|
681
|
+
? [...physicalProviderCallIds]
|
|
682
|
+
: [providerCallId],
|
|
683
|
+
userId: args.userId,
|
|
684
|
+
dialogId: args.dialogId,
|
|
685
|
+
agentId: args.agentKey,
|
|
686
|
+
provider: billingProvider,
|
|
687
|
+
model: billingModel,
|
|
688
|
+
endpoint: "agentRun",
|
|
689
|
+
kind: "llm_tokens",
|
|
690
|
+
usage: {
|
|
691
|
+
inputTokens: normalizedBillingUsage.input_tokens,
|
|
692
|
+
outputTokens: normalizedBillingUsage.output_tokens,
|
|
693
|
+
cacheCreationInputTokens: normalizedBillingUsage.cache_creation_input_tokens,
|
|
694
|
+
cacheReadInputTokens: normalizedBillingUsage.cache_read_input_tokens,
|
|
695
|
+
},
|
|
696
|
+
estimated: rawUsage.billing_estimated === true,
|
|
697
|
+
estimateReason: resolveEstimateReason(rawUsage),
|
|
698
|
+
needsReconciliation: hasAggregatePhysicalUsage,
|
|
699
|
+
createdAt: new Date().toISOString(),
|
|
700
|
+
});
|
|
701
|
+
await writeProviderBillableEventSafely(billableEvent);
|
|
702
|
+
if (hasAggregatePhysicalUsage) {
|
|
703
|
+
await writeBillingAnomalySafely(createAgentRunBillingAnomaly({
|
|
704
|
+
kind: "aggregate_usage_unallocated",
|
|
705
|
+
severity: "medium",
|
|
706
|
+
stage: "usage",
|
|
707
|
+
userId: args.userId,
|
|
708
|
+
dialogId: args.dialogId,
|
|
709
|
+
agentId: args.agentKey,
|
|
710
|
+
provider: billingProvider,
|
|
711
|
+
model: billingModel,
|
|
712
|
+
providerCallId,
|
|
713
|
+
billableEventId,
|
|
714
|
+
riskPlatformCredits: tokenWrite.cost,
|
|
715
|
+
message: "Aggregate agent-run usage spans multiple physical provider calls and needs per-call allocation",
|
|
716
|
+
evidence: {
|
|
717
|
+
sourceProviderCallIds: physicalProviderCallIds,
|
|
718
|
+
ledgerIdempotencyKey,
|
|
719
|
+
usage: normalizedBillingUsage,
|
|
720
|
+
tokenKey: tokenWrite.recordKey,
|
|
721
|
+
},
|
|
722
|
+
}));
|
|
723
|
+
}
|
|
724
|
+
await writeRatingResultSafely(createRatingResult({
|
|
725
|
+
ratingId: `rating_${ulid()}`,
|
|
726
|
+
billableEventId,
|
|
727
|
+
provider: billingProvider,
|
|
728
|
+
model: billingModel,
|
|
729
|
+
...(billingServiceTier ? { serviceTier: String(billingServiceTier) } : {}),
|
|
730
|
+
usage: normalizedBillingUsage,
|
|
731
|
+
createdAt: new Date().toISOString(),
|
|
732
|
+
}), {
|
|
733
|
+
userId: args.userId,
|
|
734
|
+
dialogId: args.dialogId,
|
|
735
|
+
agentId: args.agentKey,
|
|
736
|
+
providerCallId,
|
|
737
|
+
});
|
|
738
|
+
if (tokenWrite.cost > 0) {
|
|
739
|
+
const ledgerResult = await chargeAgentRunTokenCost(args.userId, tokenWrite, ledgerIdempotencyKey);
|
|
740
|
+
if (!ledgerResult.success) {
|
|
741
|
+
await writeBillingAnomalySafely(createAgentRunBillingAnomaly({
|
|
742
|
+
kind: "ledger_failed",
|
|
743
|
+
severity: "critical",
|
|
744
|
+
stage: "ledger",
|
|
745
|
+
userId: args.userId,
|
|
746
|
+
dialogId: args.dialogId,
|
|
747
|
+
agentId: args.agentKey,
|
|
748
|
+
provider: billingProvider,
|
|
749
|
+
model: billingModel,
|
|
750
|
+
providerCallId,
|
|
751
|
+
billableEventId,
|
|
752
|
+
riskPlatformCredits: tokenWrite.cost,
|
|
753
|
+
message: "Provider-call ledger charge failed",
|
|
754
|
+
evidence: {
|
|
755
|
+
ledgerStatus: ledgerResult.status,
|
|
756
|
+
error: ledgerResult.error,
|
|
757
|
+
tokenKey: tokenWrite.recordKey,
|
|
758
|
+
txId: ledgerResult.txId,
|
|
759
|
+
ledgerIdempotencyKey,
|
|
760
|
+
},
|
|
761
|
+
}));
|
|
762
|
+
}
|
|
763
|
+
}
|
|
395
764
|
} catch (error) {
|
|
396
765
|
console.warn("[billing] Agent run billing write failed; preserving dialog result", {
|
|
397
766
|
dialogId: args.dialogId,
|
|
@@ -455,16 +824,11 @@ const extractAgentRunUserText = (userInput: AgentRunRequest["userInput"]): strin
|
|
|
455
824
|
const buildAgentRunUserMessageContent = (
|
|
456
825
|
userInput: AgentRunRequest["userInput"],
|
|
457
826
|
turnInstruction?: string | null,
|
|
458
|
-
prelude?: string | null,
|
|
459
827
|
): ChatMessage["content"] => {
|
|
460
828
|
const normalizedTurnInstruction =
|
|
461
829
|
typeof turnInstruction === "string" && turnInstruction.trim()
|
|
462
830
|
? turnInstruction.trim()
|
|
463
831
|
: "";
|
|
464
|
-
const normalizedPrelude =
|
|
465
|
-
typeof prelude === "string" && prelude.trim()
|
|
466
|
-
? prelude.trim()
|
|
467
|
-
: "";
|
|
468
832
|
const normalizedParts = normalizeAgentRunUserParts(userInput);
|
|
469
833
|
if (normalizedParts.length > 0) {
|
|
470
834
|
// Inject URL hints so the model uses original HTTPS URLs in tool calls
|
|
@@ -484,9 +848,6 @@ const buildAgentRunUserMessageContent = (
|
|
|
484
848
|
: null;
|
|
485
849
|
|
|
486
850
|
return [
|
|
487
|
-
...(normalizedPrelude
|
|
488
|
-
? [{ type: "text" as const, text: `${normalizedPrelude}\n\n--- User task ---` }]
|
|
489
|
-
: []),
|
|
490
851
|
...(normalizedTurnInstruction
|
|
491
852
|
? [{ type: "text" as const, text: `${normalizedTurnInstruction}\n\n--- User task ---` }]
|
|
492
853
|
: []),
|
|
@@ -503,14 +864,13 @@ const buildAgentRunUserMessageContent = (
|
|
|
503
864
|
}
|
|
504
865
|
|
|
505
866
|
const userText = extractAgentRunUserText(userInput);
|
|
506
|
-
|
|
507
|
-
if (!prefix) {
|
|
867
|
+
if (!normalizedTurnInstruction) {
|
|
508
868
|
return userText;
|
|
509
869
|
}
|
|
510
870
|
if (!userText) {
|
|
511
|
-
return
|
|
871
|
+
return normalizedTurnInstruction;
|
|
512
872
|
}
|
|
513
|
-
return [
|
|
873
|
+
return [normalizedTurnInstruction, "--- User task ---", userText].join("\n\n");
|
|
514
874
|
};
|
|
515
875
|
|
|
516
876
|
function resolveDirectSpecialistAgentKey(args: {
|
|
@@ -655,6 +1015,7 @@ function buildBillableForegroundSseStream(
|
|
|
655
1015
|
let lastInputPrice = context.agentConfig.inputPrice;
|
|
656
1016
|
let lastOutputPrice = context.agentConfig.outputPrice;
|
|
657
1017
|
let lastArtifacts: unknown;
|
|
1018
|
+
let lastProviderCallIds: string[] | undefined;
|
|
658
1019
|
let toolCallCount = 0;
|
|
659
1020
|
let sawDone = false;
|
|
660
1021
|
const trace: ChatMessage[] = [];
|
|
@@ -711,6 +1072,11 @@ function buildBillableForegroundSseStream(
|
|
|
711
1072
|
? payload.outputPrice
|
|
712
1073
|
: lastOutputPrice;
|
|
713
1074
|
lastArtifacts = payload.artifacts ?? lastArtifacts;
|
|
1075
|
+
if (Array.isArray(payload.providerCallIds)) {
|
|
1076
|
+
lastProviderCallIds = payload.providerCallIds.filter(
|
|
1077
|
+
(id: unknown): id is string => typeof id === "string" && id.trim()
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
714
1080
|
if (assistantText) {
|
|
715
1081
|
trace.push({ role: "assistant", content: assistantText });
|
|
716
1082
|
}
|
|
@@ -750,6 +1116,7 @@ function buildBillableForegroundSseStream(
|
|
|
750
1116
|
inputPrice: lastInputPrice,
|
|
751
1117
|
outputPrice: lastOutputPrice,
|
|
752
1118
|
usage: lastUsage,
|
|
1119
|
+
...(lastProviderCallIds?.length ? { providerCallIds: lastProviderCallIds } : {}),
|
|
753
1120
|
...(lastArtifacts ? { artifacts: lastArtifacts } : {}),
|
|
754
1121
|
trace,
|
|
755
1122
|
runtimeToolNames: [],
|
|
@@ -850,6 +1217,13 @@ function shouldBypassBalanceForLocalSmokeAgent(
|
|
|
850
1217
|
}
|
|
851
1218
|
|
|
852
1219
|
function resolveConnectorFailureResponse(error: any, agentConfig: any): Response | null {
|
|
1220
|
+
if (error instanceof InvalidBoundMachineConfigError) {
|
|
1221
|
+
return agentRunJson({
|
|
1222
|
+
error: "Invalid runtime binding",
|
|
1223
|
+
reason: error.reason,
|
|
1224
|
+
message: error.message,
|
|
1225
|
+
}, error.status);
|
|
1226
|
+
}
|
|
853
1227
|
if (error instanceof ConnectorOfflineError) {
|
|
854
1228
|
return agentRunJson({
|
|
855
1229
|
error: "Connector offline",
|
|
@@ -925,7 +1299,7 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
925
1299
|
const {
|
|
926
1300
|
requestedAgentKey,
|
|
927
1301
|
userInput,
|
|
928
|
-
|
|
1302
|
+
requestHistory,
|
|
929
1303
|
stream,
|
|
930
1304
|
runtimeContext,
|
|
931
1305
|
effectiveMaxRounds,
|
|
@@ -978,32 +1352,18 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
978
1352
|
try { await ensureServerDbOpen(); } catch (e: any) { return agentRunError(e.message, 500); }
|
|
979
1353
|
const agentLookup = await resolveAgentRunAgentConfig({
|
|
980
1354
|
agentKey,
|
|
981
|
-
getAgentRecord: (key) =>
|
|
1355
|
+
getAgentRecord: (key) => getAgentRunStore().get(key),
|
|
982
1356
|
});
|
|
983
1357
|
if (!agentLookup.ok) {
|
|
984
1358
|
return agentRunError(agentLookup.message, agentLookup.status);
|
|
985
1359
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
dbKey: agentConfig.dbKey ?? agentKey,
|
|
1360
|
+
const storedAgentConfig = {
|
|
1361
|
+
...agentLookup.agentConfig,
|
|
1362
|
+
dbKey: agentLookup.agentConfig.dbKey ?? agentKey,
|
|
990
1363
|
};
|
|
991
1364
|
|
|
992
|
-
const runtimeDelegation = resolveAgentRunDelegation({ agentConfig, serverBase });
|
|
993
|
-
if (!runtimeDelegation.ok) {
|
|
994
|
-
return agentRunError(runtimeDelegation.message, runtimeDelegation.status);
|
|
995
|
-
}
|
|
996
|
-
if (runtimeDelegation.route === "remote") {
|
|
997
|
-
return proxyAgentRunToRemote({
|
|
998
|
-
targetBase: runtimeDelegation.targetBase,
|
|
999
|
-
body,
|
|
1000
|
-
authToken,
|
|
1001
|
-
stream,
|
|
1002
|
-
});
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
1365
|
const machineBinding = resolveMachineBindingPreflight({
|
|
1006
|
-
agentConfig,
|
|
1366
|
+
agentConfig: storedAgentConfig,
|
|
1007
1367
|
userId,
|
|
1008
1368
|
listMachines: (ownerUserId) => machineRegistry.listMachines(ownerUserId),
|
|
1009
1369
|
});
|
|
@@ -1016,47 +1376,83 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1016
1376
|
authToken,
|
|
1017
1377
|
});
|
|
1018
1378
|
const taskRunPreflightPrompt = taskRunPreflight.prompt;
|
|
1019
|
-
|
|
1020
|
-
|
|
1379
|
+
const currentUserActor = userActor(userId);
|
|
1380
|
+
const fetchAuthorizedDialogMessages = (args: { dialogId: string; limit: number }) =>
|
|
1381
|
+
fetchConvMsgs(args, {
|
|
1382
|
+
userId,
|
|
1383
|
+
actor: currentUserActor,
|
|
1384
|
+
});
|
|
1385
|
+
if (continueDialogId && (body.inheritedFromDialogKey || body.parentDialogId)) {
|
|
1386
|
+
console.info("[agentRun] continue-history-overrides-inherited-reference", {
|
|
1387
|
+
continueDialogId,
|
|
1388
|
+
inheritedFromDialogKey: body.inheritedFromDialogKey ?? null,
|
|
1389
|
+
parentDialogId: body.parentDialogId ?? null,
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
const preparedRuntimeConfig = await prepareAgentRunRuntimeConfig({
|
|
1393
|
+
agentConfig: storedAgentConfig,
|
|
1021
1394
|
runtimeContext,
|
|
1022
1395
|
taskRunPreflightPrompt,
|
|
1023
1396
|
runtimeOptions,
|
|
1024
1397
|
parentDialogId,
|
|
1025
1398
|
inheritedFromDialogKey,
|
|
1399
|
+
includeConversationReference: !continueDialogId,
|
|
1026
1400
|
resolveReferenceRuntime: (references) =>
|
|
1027
1401
|
resolveServerReferenceRuntime({
|
|
1028
1402
|
references,
|
|
1029
1403
|
loadPage: async (identifier: string) => {
|
|
1030
1404
|
try {
|
|
1031
|
-
return await
|
|
1405
|
+
return await getAgentRunStore().get(identifier);
|
|
1032
1406
|
} catch {
|
|
1033
1407
|
return null;
|
|
1034
1408
|
}
|
|
1035
1409
|
},
|
|
1036
1410
|
}),
|
|
1037
|
-
|
|
1038
|
-
|
|
1411
|
+
buildConversationReferenceBlock: (args) =>
|
|
1412
|
+
buildConversationReferenceBlock({
|
|
1039
1413
|
...args,
|
|
1040
1414
|
getDialogRecord: async (dialogKey) => {
|
|
1041
1415
|
try {
|
|
1042
|
-
return await
|
|
1416
|
+
return await getAgentRunStore().get(dialogKey);
|
|
1043
1417
|
} catch {
|
|
1044
1418
|
return null;
|
|
1045
1419
|
}
|
|
1046
1420
|
},
|
|
1047
|
-
fetchConversationMessages:
|
|
1421
|
+
fetchConversationMessages: fetchAuthorizedDialogMessages,
|
|
1048
1422
|
}),
|
|
1049
1423
|
});
|
|
1424
|
+
const {
|
|
1425
|
+
runtimeEntrypointBlock,
|
|
1426
|
+
taskRunPreflightBlock,
|
|
1427
|
+
referenceRuntimeBlock,
|
|
1428
|
+
conversationReferenceBlock,
|
|
1429
|
+
editingContextBlock,
|
|
1430
|
+
...preparedAgentConfig
|
|
1431
|
+
} = preparedRuntimeConfig;
|
|
1432
|
+
const runtimePreparedAgentConfig = preparedAgentConfig;
|
|
1050
1433
|
const runtimeToolPolicySnapshot = resolveEffectiveRuntimeToolPolicy({
|
|
1051
|
-
agentConfig,
|
|
1052
|
-
taskRunControl: taskRunPreflight.control,
|
|
1053
|
-
host: "web",
|
|
1434
|
+
agentConfig: runtimePreparedAgentConfig,
|
|
1054
1435
|
});
|
|
1055
1436
|
|
|
1056
1437
|
// 余额检查(仅 JWT 登录用户)
|
|
1057
|
-
const bypassBalanceCheck = shouldBypassBalanceForLocalSmokeAgent(
|
|
1438
|
+
const bypassBalanceCheck = shouldBypassBalanceForLocalSmokeAgent(
|
|
1439
|
+
agentKey,
|
|
1440
|
+
runtimePreparedAgentConfig,
|
|
1441
|
+
serverBase,
|
|
1442
|
+
);
|
|
1058
1443
|
if (userId && !bypassBalanceCheck) {
|
|
1059
1444
|
const user = await getUser(userId);
|
|
1445
|
+
if (isGptProModel(runtimePreparedAgentConfig.provider, runtimePreparedAgentConfig.model)) {
|
|
1446
|
+
const gptProAccess = hasGptProTierAccess({ userData: user });
|
|
1447
|
+
if (!gptProAccess.allowed) {
|
|
1448
|
+
return agentRunJson({
|
|
1449
|
+
error: "GPT Pro requires 199 current balance",
|
|
1450
|
+
reason: "gpt_pro_tier_required",
|
|
1451
|
+
requiredBalance: GPT_PRO_REQUIRED_BALANCE,
|
|
1452
|
+
message: `GPT Pro 系列需要当前余额大于等于 ${GPT_PRO_REQUIRED_BALANCE}。`,
|
|
1453
|
+
}, 402);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1060
1456
|
const balanceCheck = checkBasicBalance(user?.balance ?? 0);
|
|
1061
1457
|
if (!balanceCheck.allowed) {
|
|
1062
1458
|
return agentRunJson({ error: balanceCheck.error }, 402);
|
|
@@ -1070,15 +1466,15 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1070
1466
|
continueDialogUserId,
|
|
1071
1467
|
} = await resolveContinueDialogContext({
|
|
1072
1468
|
continueDialogId,
|
|
1073
|
-
|
|
1469
|
+
requestHistoryFallback: requestHistory,
|
|
1074
1470
|
userId,
|
|
1075
1471
|
resolveExistingDialogRef,
|
|
1076
|
-
fetchConvMsgs,
|
|
1472
|
+
fetchConvMsgs: fetchAuthorizedDialogMessages,
|
|
1077
1473
|
summarizeMessagesForDebug,
|
|
1078
1474
|
});
|
|
1079
1475
|
|
|
1080
1476
|
const executionContext = await prepareAgentRunExecutionContext({
|
|
1081
|
-
agentConfig,
|
|
1477
|
+
agentConfig: runtimePreparedAgentConfig,
|
|
1082
1478
|
agentKey,
|
|
1083
1479
|
userId,
|
|
1084
1480
|
userInput,
|
|
@@ -1087,9 +1483,13 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1087
1483
|
spaceId,
|
|
1088
1484
|
runtimeProfile,
|
|
1089
1485
|
existingDialogRecord,
|
|
1090
|
-
|
|
1486
|
+
runtimeEntrypointBlock,
|
|
1487
|
+
taskRunPreflightBlock,
|
|
1488
|
+
referenceRuntimeBlock,
|
|
1489
|
+
conversationReferenceBlock,
|
|
1490
|
+
editingContextBlock,
|
|
1091
1491
|
loadUserSettings: (settingsUserId) =>
|
|
1092
|
-
|
|
1492
|
+
getAgentRunStore().get(createUserKey.settings(settingsUserId)),
|
|
1093
1493
|
resolveRuntimePolicy,
|
|
1094
1494
|
buildUserPolicyContext,
|
|
1095
1495
|
resolveMemoryRuntime,
|
|
@@ -1099,16 +1499,125 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1099
1499
|
canonicalizeToolNames,
|
|
1100
1500
|
prioritizeToolNames,
|
|
1101
1501
|
});
|
|
1102
|
-
|
|
1103
|
-
const
|
|
1502
|
+
const executionAgentConfig = executionContext.agentConfig;
|
|
1503
|
+
const executionRuntimePolicy = executionContext.runtimePolicy;
|
|
1104
1504
|
const effectiveRuntimeProfile = executionContext.effectiveRuntimeProfile;
|
|
1105
|
-
const
|
|
1106
|
-
const autonomousRuntime = executionContext.autonomousRuntime;
|
|
1505
|
+
const executionMemoryRuntime = executionContext.memoryRuntime;
|
|
1107
1506
|
const runtimeSystemMessageContext = executionContext.runtimeSystemMessageContext;
|
|
1108
|
-
const
|
|
1507
|
+
const executionMessages = executionContext.messages;
|
|
1508
|
+
const executionMachineId = resolveAgentRuntimeMachineId(executionAgentConfig);
|
|
1509
|
+
const buildExecutionWorkspaceLease = (
|
|
1510
|
+
connectorResult: ConnectorAgentRunResult | null | undefined,
|
|
1511
|
+
) =>
|
|
1512
|
+
buildWorkspaceLeaseFromConnectorResult({
|
|
1513
|
+
result: connectorResult,
|
|
1514
|
+
agentKey,
|
|
1515
|
+
machineId: executionMachineId,
|
|
1516
|
+
runtimeToolPolicySnapshot,
|
|
1517
|
+
});
|
|
1518
|
+
const runExecutionConnector = async (args: {
|
|
1519
|
+
userId: string;
|
|
1520
|
+
requestTimeoutMs?: number;
|
|
1521
|
+
runtimePromptPage?: Record<string, unknown> | null;
|
|
1522
|
+
onProgress?: (progress: MachineConnectorRunProgress) => Promise<void>;
|
|
1523
|
+
}) =>
|
|
1524
|
+
runViaMachineConnector({
|
|
1525
|
+
agentConfig: executionAgentConfig,
|
|
1526
|
+
agentKey,
|
|
1527
|
+
authToken,
|
|
1528
|
+
category,
|
|
1529
|
+
continueDialogId: continueDialogId ?? undefined,
|
|
1530
|
+
messages: executionMessages,
|
|
1531
|
+
runtimeContext,
|
|
1532
|
+
spaceId,
|
|
1533
|
+
userId: args.userId,
|
|
1534
|
+
userInput: userInputText,
|
|
1535
|
+
requestTimeoutMs: args.requestTimeoutMs,
|
|
1536
|
+
runtimeToolPolicySnapshot,
|
|
1537
|
+
...(args.runtimePromptPage ? { runtimePromptPage: args.runtimePromptPage } : {}),
|
|
1538
|
+
...(args.onProgress ? { onProgress: args.onProgress } : {}),
|
|
1539
|
+
});
|
|
1540
|
+
const runExecutionLoop = (args: {
|
|
1541
|
+
userId: string;
|
|
1542
|
+
dialogId?: string;
|
|
1543
|
+
spaceId?: string | null;
|
|
1544
|
+
}) =>
|
|
1545
|
+
runAgentLoopImpl(
|
|
1546
|
+
executionAgentConfig,
|
|
1547
|
+
executionMessages,
|
|
1548
|
+
effectiveMaxRounds,
|
|
1549
|
+
serverBase,
|
|
1550
|
+
authToken,
|
|
1551
|
+
executionRuntimePolicy,
|
|
1552
|
+
args.userId,
|
|
1553
|
+
args.dialogId,
|
|
1554
|
+
args.spaceId,
|
|
1555
|
+
userInputText,
|
|
1556
|
+
runtimeContext,
|
|
1557
|
+
serverDb,
|
|
1558
|
+
);
|
|
1559
|
+
const runExecutionResult = async (args: {
|
|
1560
|
+
userId: string;
|
|
1561
|
+
dialogId?: string;
|
|
1562
|
+
spaceId?: string | null;
|
|
1563
|
+
requestTimeoutMs?: number;
|
|
1564
|
+
runtimePromptPage?: Record<string, unknown> | null;
|
|
1565
|
+
onProgress?: (progress: MachineConnectorRunProgress) => Promise<void>;
|
|
1566
|
+
}) => {
|
|
1567
|
+
const connectorResult = await runExecutionConnector({
|
|
1568
|
+
userId: args.userId,
|
|
1569
|
+
requestTimeoutMs: args.requestTimeoutMs,
|
|
1570
|
+
runtimePromptPage: args.runtimePromptPage,
|
|
1571
|
+
onProgress: args.onProgress,
|
|
1572
|
+
});
|
|
1573
|
+
return {
|
|
1574
|
+
connectorResult,
|
|
1575
|
+
workspaceLease: buildExecutionWorkspaceLease(connectorResult),
|
|
1576
|
+
result: (connectorResult ?? await runExecutionLoop({
|
|
1577
|
+
userId: args.userId,
|
|
1578
|
+
dialogId: args.dialogId,
|
|
1579
|
+
spaceId: args.spaceId,
|
|
1580
|
+
})) as LoopResult,
|
|
1581
|
+
};
|
|
1582
|
+
};
|
|
1583
|
+
const buildExecutionSourceStream = (args: {
|
|
1584
|
+
userId: string;
|
|
1585
|
+
dialogId: string;
|
|
1586
|
+
spaceId?: string | null;
|
|
1587
|
+
}) =>
|
|
1588
|
+
buildSseStreamImpl(
|
|
1589
|
+
executionAgentConfig,
|
|
1590
|
+
executionMessages,
|
|
1591
|
+
effectiveMaxRounds,
|
|
1592
|
+
serverBase,
|
|
1593
|
+
authToken,
|
|
1594
|
+
executionRuntimePolicy,
|
|
1595
|
+
args.userId,
|
|
1596
|
+
args.dialogId,
|
|
1597
|
+
args.spaceId,
|
|
1598
|
+
userInputText,
|
|
1599
|
+
runtimeContext,
|
|
1600
|
+
serverDb,
|
|
1601
|
+
);
|
|
1602
|
+
const dialogLifecyclePersistenceContext = {
|
|
1603
|
+
userId,
|
|
1604
|
+
callerType,
|
|
1605
|
+
userInput: userInputText,
|
|
1606
|
+
spaceId,
|
|
1607
|
+
category,
|
|
1608
|
+
inheritedFromDialogKey,
|
|
1609
|
+
parentDialogId,
|
|
1610
|
+
runtimeProfile: effectiveRuntimeProfile,
|
|
1611
|
+
runtimeContext,
|
|
1612
|
+
runtimeToolPolicySnapshot,
|
|
1613
|
+
};
|
|
1614
|
+
const buildPendingDialogInput = (pendingAgentKey: string) => ({
|
|
1615
|
+
agentKey: pendingAgentKey,
|
|
1616
|
+
...dialogLifecyclePersistenceContext,
|
|
1617
|
+
});
|
|
1109
1618
|
|
|
1110
1619
|
try {
|
|
1111
|
-
await ensureLocalModelRuntimeIfNeeded(
|
|
1620
|
+
await ensureLocalModelRuntimeIfNeeded(executionAgentConfig);
|
|
1112
1621
|
} catch (e: any) {
|
|
1113
1622
|
if (isLocalRuntimeUnavailableError(e)) {
|
|
1114
1623
|
return agentRunJson({
|
|
@@ -1139,112 +1648,81 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1139
1648
|
continueDialogUserId,
|
|
1140
1649
|
fallbackSpaceId: spaceId,
|
|
1141
1650
|
createPendingDialog,
|
|
1142
|
-
pendingDialogInput:
|
|
1143
|
-
agentKey: dialogAgentKey,
|
|
1144
|
-
userId,
|
|
1145
|
-
callerType,
|
|
1146
|
-
userInput: userInputText,
|
|
1147
|
-
spaceId,
|
|
1148
|
-
category,
|
|
1149
|
-
inheritedFromDialogKey,
|
|
1150
|
-
parentDialogId,
|
|
1151
|
-
runtimeProfile: effectiveRuntimeProfile,
|
|
1152
|
-
runtimeContext,
|
|
1153
|
-
runtimeToolPolicySnapshot,
|
|
1154
|
-
},
|
|
1651
|
+
pendingDialogInput: buildPendingDialogInput(dialogAgentKey),
|
|
1155
1652
|
});
|
|
1156
1653
|
return {
|
|
1157
1654
|
...prepared,
|
|
1158
1655
|
persistDialog: true,
|
|
1159
1656
|
};
|
|
1160
1657
|
};
|
|
1658
|
+
const buildForegroundStreamLifecycleContext = (args: {
|
|
1659
|
+
streamDialog: Awaited<ReturnType<typeof prepareCurrentForegroundStreamDialog>>;
|
|
1660
|
+
startedAt: number;
|
|
1661
|
+
workspaceLease?: Record<string, unknown>;
|
|
1662
|
+
}) => ({
|
|
1663
|
+
agentConfig: executionAgentConfig,
|
|
1664
|
+
agentKey,
|
|
1665
|
+
dialogAgentKey,
|
|
1666
|
+
traceAgentKey,
|
|
1667
|
+
userId: args.streamDialog.effectiveUserId,
|
|
1668
|
+
dialogId: args.streamDialog.dialogId,
|
|
1669
|
+
dialogKey: args.streamDialog.dialogKey,
|
|
1670
|
+
userInputText,
|
|
1671
|
+
startedAt: args.startedAt,
|
|
1672
|
+
isContinue: Boolean(continueDialogId),
|
|
1673
|
+
spaceId: args.streamDialog.effectiveSpaceId,
|
|
1674
|
+
runtimeProfile: effectiveRuntimeProfile,
|
|
1675
|
+
runtimeToolPolicySnapshot,
|
|
1676
|
+
persistDialog: args.streamDialog.persistDialog,
|
|
1677
|
+
...(args.workspaceLease ? { workspaceLease: args.workspaceLease } : {}),
|
|
1678
|
+
});
|
|
1161
1679
|
|
|
1162
1680
|
if (stream) {
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
continueDialogId: continueDialogId ?? undefined,
|
|
1169
|
-
messages,
|
|
1170
|
-
runtimeContext,
|
|
1171
|
-
spaceId,
|
|
1172
|
-
userId,
|
|
1173
|
-
userInput: userInputText,
|
|
1174
|
-
requestTimeoutMs: effectiveAgentRunTimeoutMs,
|
|
1175
|
-
runtimeToolPolicySnapshot,
|
|
1176
|
-
});
|
|
1177
|
-
if (connectorResult) {
|
|
1178
|
-
const workspaceLease = buildWorkspaceLeaseFromConnectorResult({
|
|
1179
|
-
result: connectorResult,
|
|
1180
|
-
agentKey,
|
|
1181
|
-
machineId: resolveAgentRuntimeMachineId(agentConfig),
|
|
1182
|
-
runtimeToolPolicySnapshot,
|
|
1681
|
+
const dispatchForegroundStreamExecution = async () => {
|
|
1682
|
+
try {
|
|
1683
|
+
const connectorResult = await runExecutionConnector({
|
|
1684
|
+
userId,
|
|
1685
|
+
requestTimeoutMs: effectiveAgentRunTimeoutMs,
|
|
1183
1686
|
});
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
runtimeToolPolicySnapshot,
|
|
1202
|
-
workspaceLease,
|
|
1203
|
-
persistDialog: streamDialog.persistDialog,
|
|
1204
|
-
}
|
|
1205
|
-
));
|
|
1687
|
+
if (connectorResult) {
|
|
1688
|
+
const workspaceLease = buildExecutionWorkspaceLease(connectorResult);
|
|
1689
|
+
const streamDialog = await prepareCurrentForegroundStreamDialog();
|
|
1690
|
+
const startedAt = Date.now();
|
|
1691
|
+
return agentRunSse(buildBillableForegroundSseStream(
|
|
1692
|
+
buildMachineConnectorSseStream(connectorResult),
|
|
1693
|
+
buildForegroundStreamLifecycleContext({
|
|
1694
|
+
streamDialog,
|
|
1695
|
+
startedAt,
|
|
1696
|
+
workspaceLease,
|
|
1697
|
+
})
|
|
1698
|
+
));
|
|
1699
|
+
}
|
|
1700
|
+
} catch (e: any) {
|
|
1701
|
+
const connectorFailureResponse = resolveConnectorFailureResponse(e, executionAgentConfig);
|
|
1702
|
+
if (connectorFailureResponse) return connectorFailureResponse;
|
|
1703
|
+
throw e;
|
|
1206
1704
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
streamDialog.effectiveSpaceId,
|
|
1229
|
-
userInputText,
|
|
1230
|
-
runtimeContext,
|
|
1231
|
-
);
|
|
1232
|
-
return agentRunSse(buildBillableForegroundSseStream(sourceStream, {
|
|
1233
|
-
agentConfig,
|
|
1234
|
-
agentKey,
|
|
1235
|
-
dialogAgentKey,
|
|
1236
|
-
traceAgentKey,
|
|
1237
|
-
userId: streamDialog.effectiveUserId,
|
|
1238
|
-
dialogId: streamDialog.dialogId,
|
|
1239
|
-
dialogKey: streamDialog.dialogKey,
|
|
1240
|
-
userInputText,
|
|
1241
|
-
startedAt,
|
|
1242
|
-
isContinue: Boolean(continueDialogId),
|
|
1243
|
-
spaceId: streamDialog.effectiveSpaceId,
|
|
1244
|
-
runtimeProfile: effectiveRuntimeProfile,
|
|
1245
|
-
runtimeToolPolicySnapshot,
|
|
1246
|
-
persistDialog: streamDialog.persistDialog,
|
|
1247
|
-
}));
|
|
1705
|
+
let streamDialog: Awaited<ReturnType<typeof prepareForegroundStreamDialog>>;
|
|
1706
|
+
try {
|
|
1707
|
+
streamDialog = await prepareCurrentForegroundStreamDialog();
|
|
1708
|
+
} catch (e: any) {
|
|
1709
|
+
return agentRunError(e.message ?? "Failed to create dialog", e.status ?? 500);
|
|
1710
|
+
}
|
|
1711
|
+
const startedAt = Date.now();
|
|
1712
|
+
const sourceStream = buildExecutionSourceStream({
|
|
1713
|
+
userId: streamDialog.effectiveUserId,
|
|
1714
|
+
dialogId: streamDialog.dialogId,
|
|
1715
|
+
spaceId: streamDialog.effectiveSpaceId,
|
|
1716
|
+
});
|
|
1717
|
+
return agentRunSse(buildBillableForegroundSseStream(
|
|
1718
|
+
sourceStream,
|
|
1719
|
+
buildForegroundStreamLifecycleContext({
|
|
1720
|
+
streamDialog,
|
|
1721
|
+
startedAt,
|
|
1722
|
+
}),
|
|
1723
|
+
));
|
|
1724
|
+
};
|
|
1725
|
+
return await dispatchForegroundStreamExecution();
|
|
1248
1726
|
}
|
|
1249
1727
|
|
|
1250
1728
|
// ── background 模式:立即返回 dialogId,后台执行 ───────────────────────────
|
|
@@ -1256,19 +1734,7 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1256
1734
|
continueDialogUserId,
|
|
1257
1735
|
fallbackSpaceId: spaceId,
|
|
1258
1736
|
createPendingDialog,
|
|
1259
|
-
pendingDialogInput:
|
|
1260
|
-
agentKey,
|
|
1261
|
-
userId,
|
|
1262
|
-
callerType,
|
|
1263
|
-
userInput: userInputText,
|
|
1264
|
-
spaceId,
|
|
1265
|
-
category,
|
|
1266
|
-
inheritedFromDialogKey,
|
|
1267
|
-
parentDialogId,
|
|
1268
|
-
runtimeProfile: effectiveRuntimeProfile,
|
|
1269
|
-
runtimeContext,
|
|
1270
|
-
runtimeToolPolicySnapshot,
|
|
1271
|
-
},
|
|
1737
|
+
pendingDialogInput: buildPendingDialogInput(agentKey),
|
|
1272
1738
|
});
|
|
1273
1739
|
if (isBackgroundRunDialogError(backgroundDialog)) {
|
|
1274
1740
|
return agentRunError(backgroundDialog.error, backgroundDialog.status);
|
|
@@ -1279,150 +1745,112 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1279
1745
|
effectiveUserId: effectiveBackgroundUserId,
|
|
1280
1746
|
effectiveSpaceId: effectiveBackgroundSpaceId,
|
|
1281
1747
|
} = backgroundDialog;
|
|
1748
|
+
const backgroundDialogPersistenceContext = {
|
|
1749
|
+
dialogId,
|
|
1750
|
+
dialogKey,
|
|
1751
|
+
agentKey,
|
|
1752
|
+
parentDialogId,
|
|
1753
|
+
runtimeContext,
|
|
1754
|
+
spaceId: effectiveBackgroundSpaceId,
|
|
1755
|
+
};
|
|
1282
1756
|
const startedAt = Date.now();
|
|
1757
|
+
const persistBackgroundDialogRecord = async (args: {
|
|
1758
|
+
status: "running" | "failed";
|
|
1759
|
+
updatedAt: number;
|
|
1760
|
+
extraFields?: Record<string, unknown>;
|
|
1761
|
+
buildRuntimeCheckpoint: (existingDialog: any) => unknown;
|
|
1762
|
+
failureLogLabel: string;
|
|
1763
|
+
}) => {
|
|
1764
|
+
try {
|
|
1765
|
+
const store = getAgentRunStore();
|
|
1766
|
+
const existingDialog = await store.get(dialogKey);
|
|
1767
|
+
await store.put(dialogKey, {
|
|
1768
|
+
...existingDialog,
|
|
1769
|
+
status: args.status,
|
|
1770
|
+
updatedAt: new Date(args.updatedAt).toISOString(),
|
|
1771
|
+
...(args.extraFields ?? {}),
|
|
1772
|
+
runtimeCheckpoint: args.buildRuntimeCheckpoint(existingDialog),
|
|
1773
|
+
});
|
|
1774
|
+
return true;
|
|
1775
|
+
} catch (persistError) {
|
|
1776
|
+
console.error(
|
|
1777
|
+
`[background] dialog=${dialogId} ${args.failureLogLabel} persist failed:`,
|
|
1778
|
+
persistError,
|
|
1779
|
+
);
|
|
1780
|
+
return false;
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
const publishBackgroundDialogTransition = async (args: {
|
|
1784
|
+
status: "running" | "done" | "failed";
|
|
1785
|
+
projectActivity?: boolean;
|
|
1786
|
+
progress?: MachineConnectorRunProgress;
|
|
1787
|
+
content?: string;
|
|
1788
|
+
usage?: LoopResult["usage"];
|
|
1789
|
+
error?: string;
|
|
1790
|
+
}) => {
|
|
1791
|
+
if (args.projectActivity !== false) {
|
|
1792
|
+
await projectBackgroundDialogActivity({
|
|
1793
|
+
...backgroundDialogPersistenceContext,
|
|
1794
|
+
status: args.status,
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
if (args.progress) {
|
|
1798
|
+
pushEvent(`dialog-${dialogId}`, {
|
|
1799
|
+
type: "runtime.progress",
|
|
1800
|
+
progress: args.progress,
|
|
1801
|
+
});
|
|
1802
|
+
return;
|
|
1803
|
+
}
|
|
1804
|
+
if (args.status === "running") {
|
|
1805
|
+
pushEvent(`dialog-${dialogId}`, { type: "status", status: "running" });
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
if (args.status === "done") {
|
|
1809
|
+
pushEvent(`dialog-${dialogId}`, {
|
|
1810
|
+
type: "done",
|
|
1811
|
+
content: args.content,
|
|
1812
|
+
usage: args.usage,
|
|
1813
|
+
});
|
|
1814
|
+
if (effectiveBackgroundSpaceId) {
|
|
1815
|
+
pushEvent(`space-${effectiveBackgroundSpaceId}`, { type: "dialog.done", dialogId });
|
|
1816
|
+
}
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
pushEvent(`dialog-${dialogId}`, {
|
|
1820
|
+
type: "failed",
|
|
1821
|
+
error: args.error,
|
|
1822
|
+
});
|
|
1823
|
+
if (effectiveBackgroundSpaceId) {
|
|
1824
|
+
pushEvent(`space-${effectiveBackgroundSpaceId}`, { type: "dialog.failed", dialogId });
|
|
1825
|
+
}
|
|
1826
|
+
};
|
|
1283
1827
|
|
|
1284
1828
|
// 更新 status=running
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
startedAt,
|
|
1292
|
-
updatedAt: new Date(runningAt).toISOString(),
|
|
1293
|
-
runtimeCheckpoint: buildRunningRuntimeCheckpoint({
|
|
1294
|
-
dialogId,
|
|
1295
|
-
userInputText,
|
|
1296
|
-
updatedAt: runningAt,
|
|
1297
|
-
runtimeBinding: existingDialog?.runtimeBinding,
|
|
1298
|
-
}),
|
|
1299
|
-
});
|
|
1300
|
-
await projectBackgroundDialogActivity({
|
|
1829
|
+
const runningAt = Date.now();
|
|
1830
|
+
const persistedRunning = await persistBackgroundDialogRecord({
|
|
1831
|
+
status: "running",
|
|
1832
|
+
updatedAt: runningAt,
|
|
1833
|
+
extraFields: { startedAt },
|
|
1834
|
+
buildRuntimeCheckpoint: (existingDialog: any) => buildRunningRuntimeCheckpoint({
|
|
1301
1835
|
dialogId,
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1836
|
+
userInputText,
|
|
1837
|
+
updatedAt: runningAt,
|
|
1838
|
+
runtimeBinding: existingDialog?.runtimeBinding,
|
|
1839
|
+
}),
|
|
1840
|
+
failureLogLabel: "status update",
|
|
1841
|
+
});
|
|
1842
|
+
await publishBackgroundDialogTransition({
|
|
1843
|
+
status: "running",
|
|
1844
|
+
projectActivity: persistedRunning,
|
|
1845
|
+
});
|
|
1312
1846
|
|
|
1313
1847
|
// 后台执行(不阻塞响应)
|
|
1314
1848
|
incActiveStream();
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
const persistConnectorProgress = async (progress: MachineConnectorRunProgress) => {
|
|
1321
|
-
const progressAt = Date.now();
|
|
1322
|
-
try {
|
|
1323
|
-
const existingDialog = await serverDb.get(dialogKey);
|
|
1324
|
-
await serverDb.put(dialogKey, {
|
|
1325
|
-
...existingDialog,
|
|
1326
|
-
status: "running",
|
|
1327
|
-
updatedAt: new Date(progressAt).toISOString(),
|
|
1328
|
-
runtimeCheckpoint: buildProgressRuntimeCheckpoint({
|
|
1329
|
-
existingDialog,
|
|
1330
|
-
dialogId,
|
|
1331
|
-
userInputText,
|
|
1332
|
-
progress,
|
|
1333
|
-
updatedAt: progressAt,
|
|
1334
|
-
}),
|
|
1335
|
-
});
|
|
1336
|
-
await projectBackgroundDialogActivity({
|
|
1337
|
-
dialogId,
|
|
1338
|
-
dialogKey,
|
|
1339
|
-
agentKey,
|
|
1340
|
-
parentDialogId,
|
|
1341
|
-
runtimeContext,
|
|
1342
|
-
status: "running",
|
|
1343
|
-
});
|
|
1344
|
-
pushEvent(`dialog-${dialogId}`, {
|
|
1345
|
-
type: "runtime.progress",
|
|
1346
|
-
progress,
|
|
1347
|
-
});
|
|
1348
|
-
} catch (progressError) {
|
|
1349
|
-
console.error(`[background] dialog=${dialogId} progress persist failed:`, progressError);
|
|
1350
|
-
}
|
|
1351
|
-
};
|
|
1352
|
-
const runtimePromptPage = await createRuntimePromptPageIfLarge({
|
|
1353
|
-
agentConfig,
|
|
1354
|
-
agentKey,
|
|
1355
|
-
dialogId,
|
|
1356
|
-
runtimeContext,
|
|
1357
|
-
spaceId: effectiveBackgroundSpaceId,
|
|
1358
|
-
userId: effectiveBackgroundUserId,
|
|
1359
|
-
userInputText,
|
|
1360
|
-
}).catch((error) => {
|
|
1361
|
-
console.warn("[agentRun.background] runtime prompt page create failed", {
|
|
1362
|
-
dialogId,
|
|
1363
|
-
agentKey,
|
|
1364
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1365
|
-
});
|
|
1366
|
-
return null;
|
|
1367
|
-
});
|
|
1368
|
-
if (runtimePromptPage) {
|
|
1369
|
-
await persistConnectorProgress({
|
|
1370
|
-
message: "runtime-prompt-page-created",
|
|
1371
|
-
promptPageKey: runtimePromptPage.dbKey,
|
|
1372
|
-
promptPageHash: runtimePromptPage.promptHash,
|
|
1373
|
-
promptBytes: runtimePromptPage.contentBytes,
|
|
1374
|
-
updatedAt: Date.now(),
|
|
1375
|
-
});
|
|
1376
|
-
}
|
|
1377
|
-
const result = await withBackgroundRunTimeout((async () => {
|
|
1378
|
-
console.log("[agentRun.background] dispatch", {
|
|
1379
|
-
dialogId,
|
|
1380
|
-
agentKey,
|
|
1381
|
-
backgroundTimeoutMs,
|
|
1382
|
-
userInputBytes: byteLength(userInputText),
|
|
1383
|
-
runtimePromptPageKey: runtimePromptPage?.dbKey,
|
|
1384
|
-
});
|
|
1385
|
-
const connectorResult = await runViaMachineConnector({
|
|
1386
|
-
agentConfig,
|
|
1387
|
-
agentKey,
|
|
1388
|
-
category,
|
|
1389
|
-
continueDialogId: continueDialogId ?? undefined,
|
|
1390
|
-
messages,
|
|
1391
|
-
runtimeContext,
|
|
1392
|
-
spaceId,
|
|
1393
|
-
userId: effectiveBackgroundUserId,
|
|
1394
|
-
userInput: userInputText,
|
|
1395
|
-
requestTimeoutMs: backgroundTimeoutMs,
|
|
1396
|
-
runtimeToolPolicySnapshot,
|
|
1397
|
-
runtimePromptPage,
|
|
1398
|
-
onProgress: persistConnectorProgress,
|
|
1399
|
-
});
|
|
1400
|
-
console.log("[agentRun.background] connector-result", {
|
|
1401
|
-
dialogId,
|
|
1402
|
-
agentKey,
|
|
1403
|
-
usedMachineConnector: Boolean(connectorResult),
|
|
1404
|
-
contentBytes: byteLength(String(connectorResult?.content ?? "")),
|
|
1405
|
-
});
|
|
1406
|
-
workspaceLease = buildWorkspaceLeaseFromConnectorResult({
|
|
1407
|
-
result: connectorResult,
|
|
1408
|
-
agentKey,
|
|
1409
|
-
machineId: resolveAgentRuntimeMachineId(agentConfig),
|
|
1410
|
-
runtimeToolPolicySnapshot,
|
|
1411
|
-
});
|
|
1412
|
-
return (connectorResult ?? await runAgentLoopImpl(
|
|
1413
|
-
agentConfig,
|
|
1414
|
-
messages,
|
|
1415
|
-
effectiveMaxRounds,
|
|
1416
|
-
serverBase,
|
|
1417
|
-
authToken,
|
|
1418
|
-
runtimePolicy,
|
|
1419
|
-
effectiveBackgroundUserId,
|
|
1420
|
-
dialogId,
|
|
1421
|
-
effectiveBackgroundSpaceId,
|
|
1422
|
-
userInputText,
|
|
1423
|
-
runtimeContext,
|
|
1424
|
-
)) as LoopResult;
|
|
1425
|
-
})(), backgroundTimeoutMs);
|
|
1849
|
+
const dispatchBackgroundExecution = async () => {
|
|
1850
|
+
const settleBackgroundExecutionSuccess = async (args: {
|
|
1851
|
+
result: LoopResult;
|
|
1852
|
+
workspaceLease?: Record<string, unknown>;
|
|
1853
|
+
}) => {
|
|
1426
1854
|
if (continueDialogId) {
|
|
1427
1855
|
await appendToExistingDialog({
|
|
1428
1856
|
dialogId,
|
|
@@ -1430,20 +1858,20 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1430
1858
|
agentKey,
|
|
1431
1859
|
userId: effectiveBackgroundUserId,
|
|
1432
1860
|
userInput: userInputText,
|
|
1433
|
-
result,
|
|
1861
|
+
result: args.result,
|
|
1434
1862
|
durationMs: Date.now() - startedAt,
|
|
1435
1863
|
spaceId: effectiveBackgroundSpaceId,
|
|
1436
1864
|
runtimeProfile: effectiveRuntimeProfile,
|
|
1437
1865
|
runtimeContext,
|
|
1438
1866
|
runtimeToolPolicySnapshot,
|
|
1439
|
-
workspaceLease,
|
|
1867
|
+
workspaceLease: args.workspaceLease,
|
|
1440
1868
|
});
|
|
1441
1869
|
} else {
|
|
1442
1870
|
await finalizeDialog({
|
|
1443
1871
|
dialogId,
|
|
1444
1872
|
dialogKey,
|
|
1445
1873
|
agentKey,
|
|
1446
|
-
result,
|
|
1874
|
+
result: args.result,
|
|
1447
1875
|
startedAt,
|
|
1448
1876
|
status: "done",
|
|
1449
1877
|
userInput: userInputText,
|
|
@@ -1451,131 +1879,169 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1451
1879
|
spaceId,
|
|
1452
1880
|
runtimeContext,
|
|
1453
1881
|
runtimeToolPolicySnapshot,
|
|
1454
|
-
workspaceLease,
|
|
1882
|
+
workspaceLease: args.workspaceLease,
|
|
1455
1883
|
});
|
|
1456
1884
|
}
|
|
1457
|
-
await
|
|
1458
|
-
dialogId,
|
|
1459
|
-
dialogKey,
|
|
1460
|
-
agentKey,
|
|
1461
|
-
parentDialogId,
|
|
1462
|
-
runtimeContext,
|
|
1885
|
+
await publishBackgroundDialogTransition({
|
|
1463
1886
|
status: "done",
|
|
1887
|
+
content: args.result.content,
|
|
1888
|
+
usage: args.result.usage,
|
|
1464
1889
|
});
|
|
1465
|
-
pushEvent(`dialog-${dialogId}`, {
|
|
1466
|
-
type: "done",
|
|
1467
|
-
content: result.content,
|
|
1468
|
-
usage: result.usage,
|
|
1469
|
-
});
|
|
1470
|
-
if (effectiveBackgroundSpaceId) {
|
|
1471
|
-
pushEvent(`space-${effectiveBackgroundSpaceId}`, { type: "dialog.done", dialogId });
|
|
1472
|
-
}
|
|
1473
1890
|
await writeAgentRunBillingIfNeeded({
|
|
1474
|
-
agentConfig,
|
|
1891
|
+
agentConfig: executionAgentConfig,
|
|
1475
1892
|
agentKey,
|
|
1476
|
-
result,
|
|
1893
|
+
result: args.result,
|
|
1477
1894
|
dialogId,
|
|
1478
1895
|
mode: "background",
|
|
1479
1896
|
userId: effectiveBackgroundUserId,
|
|
1480
1897
|
});
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1898
|
+
};
|
|
1899
|
+
const settleBackgroundExecutionFailure = async (args: {
|
|
1900
|
+
error: unknown;
|
|
1901
|
+
}) => {
|
|
1483
1902
|
const failedAt = Date.now();
|
|
1484
|
-
const errorMessage =
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1903
|
+
const errorMessage =
|
|
1904
|
+
args.error instanceof Error ? args.error.message : String(args.error);
|
|
1905
|
+
await persistBackgroundDialogRecord({
|
|
1906
|
+
status: "failed",
|
|
1907
|
+
updatedAt: failedAt,
|
|
1908
|
+
extraFields: {
|
|
1490
1909
|
finishedAt: failedAt,
|
|
1491
1910
|
durationMs: Math.max(0, failedAt - startedAt),
|
|
1492
|
-
runtimeCheckpoint: {
|
|
1493
|
-
...buildFailedRuntimeCheckpoint({
|
|
1494
|
-
existingDialog: d,
|
|
1495
|
-
dialogId,
|
|
1496
|
-
userInputText,
|
|
1497
|
-
updatedAt: failedAt,
|
|
1498
|
-
errorMessage,
|
|
1499
|
-
}),
|
|
1500
|
-
errorMessage,
|
|
1501
|
-
},
|
|
1502
1911
|
errorMessage,
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1912
|
+
},
|
|
1913
|
+
buildRuntimeCheckpoint: (existingDialog: any) => buildFailedRuntimeCheckpoint({
|
|
1914
|
+
existingDialog,
|
|
1915
|
+
dialogId,
|
|
1916
|
+
userInputText,
|
|
1917
|
+
updatedAt: failedAt,
|
|
1918
|
+
errorMessage,
|
|
1919
|
+
}),
|
|
1920
|
+
failureLogLabel: "status",
|
|
1512
1921
|
});
|
|
1513
|
-
|
|
1514
|
-
|
|
1922
|
+
await publishBackgroundDialogTransition({
|
|
1923
|
+
status: "failed",
|
|
1515
1924
|
error: errorMessage,
|
|
1516
1925
|
});
|
|
1517
|
-
if (effectiveBackgroundSpaceId) {
|
|
1518
|
-
pushEvent(`space-${effectiveBackgroundSpaceId}`, { type: "dialog.failed", dialogId });
|
|
1519
|
-
}
|
|
1520
1926
|
const dialogTitle =
|
|
1521
1927
|
existingDialogRecord?.title ??
|
|
1522
1928
|
buildDialogFallbackTitleFromUserInput(userInputText);
|
|
1523
1929
|
await emitDialogStatusNotification({
|
|
1524
1930
|
userId: effectiveBackgroundUserId,
|
|
1525
|
-
|
|
1526
|
-
dialogKey,
|
|
1931
|
+
...backgroundDialogPersistenceContext,
|
|
1527
1932
|
dialogTitle,
|
|
1528
|
-
spaceId: effectiveBackgroundSpaceId,
|
|
1529
1933
|
status: "failed",
|
|
1530
1934
|
createdAt: failedAt,
|
|
1531
1935
|
errorMessage,
|
|
1532
1936
|
});
|
|
1937
|
+
};
|
|
1938
|
+
try {
|
|
1939
|
+
const backgroundTimeoutMs =
|
|
1940
|
+
effectiveAgentRunTimeoutMs ?? DEFAULT_BACKGROUND_RUN_TIMEOUT_MS;
|
|
1941
|
+
let workspaceLease: Record<string, unknown> | undefined;
|
|
1942
|
+
const prepareBackgroundProgressPhase = async () => {
|
|
1943
|
+
const persistConnectorProgress = async (progress: MachineConnectorRunProgress) => {
|
|
1944
|
+
const progressAt = Date.now();
|
|
1945
|
+
const persistedProgress = await persistBackgroundDialogRecord({
|
|
1946
|
+
status: "running",
|
|
1947
|
+
updatedAt: progressAt,
|
|
1948
|
+
buildRuntimeCheckpoint: (existingDialog: any) => buildProgressRuntimeCheckpoint({
|
|
1949
|
+
existingDialog,
|
|
1950
|
+
dialogId,
|
|
1951
|
+
userInputText,
|
|
1952
|
+
progress,
|
|
1953
|
+
updatedAt: progressAt,
|
|
1954
|
+
}),
|
|
1955
|
+
failureLogLabel: "progress",
|
|
1956
|
+
});
|
|
1957
|
+
if (persistedProgress) {
|
|
1958
|
+
await publishBackgroundDialogTransition({
|
|
1959
|
+
status: "running",
|
|
1960
|
+
progress,
|
|
1961
|
+
});
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
const maybeRuntimePromptPage = await createRuntimePromptPageIfLarge({
|
|
1965
|
+
agentConfig: executionAgentConfig,
|
|
1966
|
+
agentKey,
|
|
1967
|
+
dialogId,
|
|
1968
|
+
runtimeContext,
|
|
1969
|
+
spaceId: effectiveBackgroundSpaceId,
|
|
1970
|
+
userId: effectiveBackgroundUserId,
|
|
1971
|
+
userInputText,
|
|
1972
|
+
}).catch((error) => {
|
|
1973
|
+
console.warn("[agentRun.background] runtime prompt page create failed", {
|
|
1974
|
+
dialogId,
|
|
1975
|
+
agentKey,
|
|
1976
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1977
|
+
});
|
|
1978
|
+
return null;
|
|
1979
|
+
});
|
|
1980
|
+
if (maybeRuntimePromptPage) {
|
|
1981
|
+
await persistConnectorProgress({
|
|
1982
|
+
message: "runtime-prompt-page-created",
|
|
1983
|
+
promptPageKey: maybeRuntimePromptPage.dbKey,
|
|
1984
|
+
promptPageHash: maybeRuntimePromptPage.promptHash,
|
|
1985
|
+
promptBytes: maybeRuntimePromptPage.contentBytes,
|
|
1986
|
+
updatedAt: Date.now(),
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1989
|
+
return {
|
|
1990
|
+
persistConnectorProgress,
|
|
1991
|
+
runtimePromptPage: maybeRuntimePromptPage,
|
|
1992
|
+
};
|
|
1993
|
+
};
|
|
1994
|
+
const { persistConnectorProgress, runtimePromptPage } = await prepareBackgroundProgressPhase();
|
|
1995
|
+
const { result, workspaceLease: resolvedWorkspaceLease } = await withBackgroundRunTimeout((async () => {
|
|
1996
|
+
console.log("[agentRun.background] dispatch", {
|
|
1997
|
+
dialogId,
|
|
1998
|
+
agentKey,
|
|
1999
|
+
backgroundTimeoutMs,
|
|
2000
|
+
userInputBytes: byteLength(userInputText),
|
|
2001
|
+
runtimePromptPageKey: runtimePromptPage?.dbKey,
|
|
2002
|
+
});
|
|
2003
|
+
const executionRun = await runExecutionResult({
|
|
2004
|
+
userId: effectiveBackgroundUserId,
|
|
2005
|
+
dialogId,
|
|
2006
|
+
spaceId: effectiveBackgroundSpaceId,
|
|
2007
|
+
requestTimeoutMs: backgroundTimeoutMs,
|
|
2008
|
+
runtimePromptPage,
|
|
2009
|
+
onProgress: persistConnectorProgress,
|
|
2010
|
+
});
|
|
2011
|
+
console.log("[agentRun.background] connector-result", {
|
|
2012
|
+
dialogId,
|
|
2013
|
+
agentKey,
|
|
2014
|
+
usedMachineConnector: Boolean(executionRun.connectorResult),
|
|
2015
|
+
contentBytes: byteLength(String(executionRun.connectorResult?.content ?? "")),
|
|
2016
|
+
});
|
|
2017
|
+
return executionRun;
|
|
2018
|
+
})(), backgroundTimeoutMs);
|
|
2019
|
+
workspaceLease = resolvedWorkspaceLease;
|
|
2020
|
+
await settleBackgroundExecutionSuccess({ result, workspaceLease });
|
|
2021
|
+
} catch (e) {
|
|
2022
|
+
console.error(`[background] dialog=${dialogId} failed:`, e);
|
|
2023
|
+
await settleBackgroundExecutionFailure({ error: e });
|
|
1533
2024
|
} finally {
|
|
1534
2025
|
decActiveStream();
|
|
1535
2026
|
}
|
|
1536
|
-
}
|
|
2027
|
+
};
|
|
2028
|
+
dispatchBackgroundExecution().catch((e) => { console.error(`[background] unhandled rejection dialog=${dialogId}:`, e); });
|
|
1537
2029
|
|
|
1538
2030
|
return agentRunJson({ dialogId, status: "pending" }, 202);
|
|
1539
2031
|
}
|
|
1540
2032
|
|
|
1541
2033
|
// ── 前台同步模式 ───────────────────────────────────────────────────────────
|
|
1542
|
-
|
|
2034
|
+
const dispatchSyncExecution = async () => {
|
|
1543
2035
|
const startTime = Date.now();
|
|
1544
2036
|
// 注意:sync 新建 dialog 的首轮执行在 saveRunAsDialog 之前,runAgentLoop 此时还拿不到最终 dialogId。
|
|
1545
2037
|
// 这意味着首轮 server-side external tool charge 还无法稳定投影进 dialog.totalCost;
|
|
1546
2038
|
// continue/background 场景已有 dialogId,可正常回写。后续若要补齐这里,需要先拿稳定 dialogId 再执行工具链。
|
|
1547
|
-
const
|
|
1548
|
-
agentConfig,
|
|
1549
|
-
agentKey,
|
|
1550
|
-
category,
|
|
1551
|
-
continueDialogId: continueDialogId ?? undefined,
|
|
1552
|
-
messages,
|
|
1553
|
-
runtimeContext,
|
|
1554
|
-
spaceId,
|
|
2039
|
+
const { result, workspaceLease } = await runExecutionResult({
|
|
1555
2040
|
userId,
|
|
1556
|
-
userInput: userInputText,
|
|
1557
2041
|
requestTimeoutMs: effectiveAgentRunTimeoutMs,
|
|
1558
|
-
|
|
1559
|
-
});
|
|
1560
|
-
const workspaceLease = buildWorkspaceLeaseFromConnectorResult({
|
|
1561
|
-
result: connectorResult,
|
|
1562
|
-
agentKey,
|
|
1563
|
-
machineId: resolveAgentRuntimeMachineId(agentConfig),
|
|
1564
|
-
runtimeToolPolicySnapshot,
|
|
1565
|
-
});
|
|
1566
|
-
const result = (connectorResult ?? await runAgentLoopImpl(
|
|
1567
|
-
agentConfig,
|
|
1568
|
-
messages,
|
|
1569
|
-
effectiveMaxRounds,
|
|
1570
|
-
serverBase,
|
|
1571
|
-
authToken,
|
|
1572
|
-
runtimePolicy,
|
|
1573
|
-
userId,
|
|
1574
|
-
continueDialogId ?? undefined,
|
|
2042
|
+
dialogId: continueDialogId ?? undefined,
|
|
1575
2043
|
spaceId,
|
|
1576
|
-
|
|
1577
|
-
runtimeContext,
|
|
1578
|
-
)) as LoopResult;
|
|
2044
|
+
});
|
|
1579
2045
|
const durationMs = Date.now() - startTime;
|
|
1580
2046
|
|
|
1581
2047
|
const { dialogId, dialogKey } = await completeSyncAgentRunDialog({
|
|
@@ -1583,26 +2049,17 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1583
2049
|
existingDialogKey,
|
|
1584
2050
|
dialogAgentKey,
|
|
1585
2051
|
traceAgentKey,
|
|
1586
|
-
userId,
|
|
1587
2052
|
continueDialogUserId,
|
|
1588
|
-
callerType,
|
|
1589
|
-
userInput: userInputText,
|
|
1590
2053
|
result,
|
|
1591
2054
|
durationMs,
|
|
1592
|
-
spaceId,
|
|
1593
|
-
category,
|
|
1594
|
-
inheritedFromDialogKey,
|
|
1595
|
-
parentDialogId,
|
|
1596
|
-
runtimeProfile: effectiveRuntimeProfile,
|
|
1597
|
-
runtimeContext,
|
|
1598
|
-
runtimeToolPolicySnapshot,
|
|
1599
2055
|
workspaceLease,
|
|
1600
2056
|
appendToExistingDialog,
|
|
1601
2057
|
saveRunAsDialog,
|
|
1602
2058
|
summarizeMessagesForDebug,
|
|
2059
|
+
...dialogLifecyclePersistenceContext,
|
|
1603
2060
|
});
|
|
1604
2061
|
await writeAgentRunBillingIfNeeded({
|
|
1605
|
-
agentConfig,
|
|
2062
|
+
agentConfig: executionAgentConfig,
|
|
1606
2063
|
agentKey,
|
|
1607
2064
|
result,
|
|
1608
2065
|
dialogId,
|
|
@@ -1613,7 +2070,7 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1613
2070
|
const debugContext = buildAgentRunDebugContext({
|
|
1614
2071
|
enabled: debugContextLayers,
|
|
1615
2072
|
runtimeSystemMessageContext,
|
|
1616
|
-
selectedMemoryItems:
|
|
2073
|
+
selectedMemoryItems: executionMemoryRuntime.selectedItems,
|
|
1617
2074
|
});
|
|
1618
2075
|
|
|
1619
2076
|
return agentRunJson({
|
|
@@ -1622,8 +2079,11 @@ export async function handleAgentRun(req: Request): Promise<Response> {
|
|
|
1622
2079
|
dialogKey,
|
|
1623
2080
|
...(debugContext ? { debug: debugContext } : {}),
|
|
1624
2081
|
});
|
|
2082
|
+
};
|
|
2083
|
+
try {
|
|
2084
|
+
return await dispatchSyncExecution();
|
|
1625
2085
|
} catch (e: any) {
|
|
1626
|
-
const connectorFailureResponse = resolveConnectorFailureResponse(e,
|
|
2086
|
+
const connectorFailureResponse = resolveConnectorFailureResponse(e, executionAgentConfig);
|
|
1627
2087
|
if (connectorFailureResponse) return connectorFailureResponse;
|
|
1628
2088
|
return agentRunError(e.message ?? "Internal server error", 500);
|
|
1629
2089
|
}
|