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
|
@@ -33,8 +33,11 @@ import {
|
|
|
33
33
|
toResponsesTools,
|
|
34
34
|
} from "../../../integrations/openai/responsesHelpers";
|
|
35
35
|
import { normalizeChatCompletionsBodyForProvider } from "../../../integrations/openai/providerBodyCompatibility";
|
|
36
|
-
import { fetchUpstreamWithGentleRetry } from "../chatUpstreamRetry";
|
|
37
|
-
import {
|
|
36
|
+
import { fetchUpstreamWithGentleRetry } from "../chatUpstreamRetry";
|
|
37
|
+
import type { ProviderCallStore } from "../../../ai/token/providerCallWriter";
|
|
38
|
+
import type { ProviderApiKeySource } from "../../../ai/token/providerCredential";
|
|
39
|
+
import { resolveRuntimeProviderCredential } from "../../../ai/token/providerCredentialRuntime";
|
|
40
|
+
import { executeToolOnServer } from "./toolExecutor";
|
|
38
41
|
import type {
|
|
39
42
|
AgentRunRuntimeContext,
|
|
40
43
|
ChatMessage,
|
|
@@ -161,21 +164,41 @@ async function hydrateApiKeyReferenceIfNeeded(
|
|
|
161
164
|
return {
|
|
162
165
|
...agentConfig,
|
|
163
166
|
apiKey,
|
|
167
|
+
apiKeySource: "agent_reference",
|
|
164
168
|
};
|
|
165
169
|
}
|
|
166
170
|
|
|
171
|
+
function resolveApiKeySource(agentConfig: any): ProviderApiKeySource {
|
|
172
|
+
if (agentConfig?.apiKeySource === "agent_reference") return "agent_reference";
|
|
173
|
+
if (agentConfig?.apiKey?.trim()) return "agent_secret";
|
|
174
|
+
return "platform_env";
|
|
175
|
+
}
|
|
176
|
+
|
|
167
177
|
async function fetchLoopUpstream(
|
|
168
|
-
endpoint: string,
|
|
169
|
-
agentConfig: any,
|
|
170
|
-
body: Record<string, any>,
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
endpoint: string,
|
|
179
|
+
agentConfig: any,
|
|
180
|
+
body: Record<string, any>,
|
|
181
|
+
providerCallContext?: {
|
|
182
|
+
userId?: string | null;
|
|
183
|
+
dialogId?: string | null;
|
|
184
|
+
agentId?: string | null;
|
|
185
|
+
},
|
|
186
|
+
providerCallStore?: ProviderCallStore,
|
|
187
|
+
): Promise<{
|
|
188
|
+
response: Response;
|
|
189
|
+
provider?: string;
|
|
190
|
+
model?: string;
|
|
191
|
+
inputPrice?: number;
|
|
192
|
+
outputPrice?: number;
|
|
193
|
+
providerCallIds?: string[];
|
|
194
|
+
}> {
|
|
195
|
+
const apiKey = getApiKey(agentConfig);
|
|
196
|
+
const credential = await resolveRuntimeProviderCredential({
|
|
197
|
+
provider: String(agentConfig?.provider || "unknown"),
|
|
198
|
+
apiKey,
|
|
199
|
+
apiKeySource: resolveApiKeySource(agentConfig),
|
|
200
|
+
registryStore: providerCallStore,
|
|
201
|
+
});
|
|
179
202
|
const llmRequestTimeoutMs = resolveLlmRequestTimeoutMs(agentConfig, endpoint);
|
|
180
203
|
const init: RequestInit = {
|
|
181
204
|
method: "POST",
|
|
@@ -243,10 +266,16 @@ async function fetchLoopUpstream(
|
|
|
243
266
|
const googleFallbackRequest =
|
|
244
267
|
shouldUseGoogleOpenRouterFallback && openRouterApiKey
|
|
245
268
|
? {
|
|
246
|
-
url: OPENROUTER_CHAT_COMPLETIONS_URL,
|
|
247
|
-
provider: "openrouter",
|
|
248
|
-
model: toOpenRouterGoogleModelName(agentConfig.model),
|
|
249
|
-
|
|
269
|
+
url: OPENROUTER_CHAT_COMPLETIONS_URL,
|
|
270
|
+
provider: "openrouter",
|
|
271
|
+
model: toOpenRouterGoogleModelName(agentConfig.model),
|
|
272
|
+
credential: await resolveRuntimeProviderCredential({
|
|
273
|
+
provider: "openrouter",
|
|
274
|
+
apiKey: openRouterApiKey,
|
|
275
|
+
apiKeySource: "platform_env",
|
|
276
|
+
registryStore: providerCallStore,
|
|
277
|
+
}),
|
|
278
|
+
init: {
|
|
250
279
|
method: "POST",
|
|
251
280
|
headers: buildUpstreamHeaders(
|
|
252
281
|
OPENROUTER_CHAT_COMPLETIONS_URL,
|
|
@@ -270,6 +299,12 @@ async function fetchLoopUpstream(
|
|
|
270
299
|
url: fireworksKimiFallbackUrl,
|
|
271
300
|
provider: "fireworks",
|
|
272
301
|
model: FIREWORKS_KIMI_CURRENT_MODEL,
|
|
302
|
+
credential: await resolveRuntimeProviderCredential({
|
|
303
|
+
provider: "fireworks",
|
|
304
|
+
apiKey: fireworksKimiFallbackApiKey,
|
|
305
|
+
apiKeySource: "platform_env",
|
|
306
|
+
registryStore: providerCallStore,
|
|
307
|
+
}),
|
|
273
308
|
init: {
|
|
274
309
|
method: "POST",
|
|
275
310
|
headers: buildUpstreamHeaders(
|
|
@@ -292,6 +327,12 @@ async function fetchLoopUpstream(
|
|
|
292
327
|
url: deepInfraKimiFallbackUrl,
|
|
293
328
|
provider: "deepinfra",
|
|
294
329
|
model: DEEPINFRA_KIMI_FALLBACK_MODEL,
|
|
330
|
+
credential: await resolveRuntimeProviderCredential({
|
|
331
|
+
provider: "deepinfra",
|
|
332
|
+
apiKey: deepInfraKimiFallbackApiKey,
|
|
333
|
+
apiKeySource: "platform_env",
|
|
334
|
+
registryStore: providerCallStore,
|
|
335
|
+
}),
|
|
295
336
|
init: {
|
|
296
337
|
method: "POST",
|
|
297
338
|
headers: buildUpstreamHeaders(
|
|
@@ -314,6 +355,12 @@ async function fetchLoopUpstream(
|
|
|
314
355
|
url: OPENROUTER_CHAT_COMPLETIONS_URL,
|
|
315
356
|
provider: "openrouter",
|
|
316
357
|
model: OPENROUTER_KIMI_FALLBACK_MODEL,
|
|
358
|
+
credential: await resolveRuntimeProviderCredential({
|
|
359
|
+
provider: "openrouter",
|
|
360
|
+
apiKey: openRouterKimiFallbackApiKey,
|
|
361
|
+
apiKeySource: "platform_env",
|
|
362
|
+
registryStore: providerCallStore,
|
|
363
|
+
}),
|
|
317
364
|
init: {
|
|
318
365
|
method: "POST",
|
|
319
366
|
headers: buildUpstreamHeaders(
|
|
@@ -337,9 +384,15 @@ async function fetchLoopUpstream(
|
|
|
337
384
|
shouldUseConfiguredFallback && configuredFallbackApiKey
|
|
338
385
|
? {
|
|
339
386
|
url: OPENROUTER_CHAT_COMPLETIONS_URL,
|
|
340
|
-
provider: "openrouter",
|
|
341
|
-
model: agentConfig.fallbackModel,
|
|
342
|
-
|
|
387
|
+
provider: "openrouter",
|
|
388
|
+
model: agentConfig.fallbackModel,
|
|
389
|
+
credential: await resolveRuntimeProviderCredential({
|
|
390
|
+
provider: "openrouter",
|
|
391
|
+
apiKey: configuredFallbackApiKey,
|
|
392
|
+
apiKeySource: "platform_env",
|
|
393
|
+
registryStore: providerCallStore,
|
|
394
|
+
}),
|
|
395
|
+
init: {
|
|
343
396
|
method: "POST",
|
|
344
397
|
headers: buildUpstreamHeaders(
|
|
345
398
|
OPENROUTER_CHAT_COMPLETIONS_URL,
|
|
@@ -408,9 +461,10 @@ async function fetchLoopUpstream(
|
|
|
408
461
|
? {
|
|
409
462
|
url: endpoint,
|
|
410
463
|
init,
|
|
411
|
-
provider: agentConfig.provider,
|
|
412
|
-
model: agentConfig.model,
|
|
413
|
-
|
|
464
|
+
provider: agentConfig.provider,
|
|
465
|
+
model: agentConfig.model,
|
|
466
|
+
credential,
|
|
467
|
+
log: console,
|
|
414
468
|
fallbackRequest: googleFallbackRequest,
|
|
415
469
|
fallbackOnStatuses:
|
|
416
470
|
String(agentConfig?.provider || "").toLowerCase() === "google"
|
|
@@ -423,6 +477,7 @@ async function fetchLoopUpstream(
|
|
|
423
477
|
init,
|
|
424
478
|
provider: agentConfig.provider,
|
|
425
479
|
model: agentConfig.model,
|
|
480
|
+
credential,
|
|
426
481
|
log: console,
|
|
427
482
|
fallbackRequests: kimiPlatformFallbackRequests,
|
|
428
483
|
fallbackOnStatuses: KIMI_PLATFORM_FALLBACK_STATUSES,
|
|
@@ -430,23 +485,36 @@ async function fetchLoopUpstream(
|
|
|
430
485
|
: configuredFallbackRequest
|
|
431
486
|
? {
|
|
432
487
|
url: endpoint,
|
|
433
|
-
init,
|
|
434
|
-
provider: agentConfig.provider,
|
|
435
|
-
model: agentConfig.model,
|
|
436
|
-
|
|
437
|
-
|
|
488
|
+
init,
|
|
489
|
+
provider: agentConfig.provider,
|
|
490
|
+
model: agentConfig.model,
|
|
491
|
+
credential,
|
|
492
|
+
log: console,
|
|
493
|
+
fallbackRequest: configuredFallbackRequest,
|
|
438
494
|
fallbackOnStatuses: FIREWORKS_OPENROUTER_FALLBACK_STATUSES,
|
|
439
495
|
}
|
|
440
496
|
: {
|
|
441
497
|
url: endpoint,
|
|
442
|
-
init,
|
|
443
|
-
provider: agentConfig.provider,
|
|
444
|
-
model: agentConfig.model,
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
498
|
+
init,
|
|
499
|
+
provider: agentConfig.provider,
|
|
500
|
+
model: agentConfig.model,
|
|
501
|
+
credential,
|
|
502
|
+
log: console,
|
|
503
|
+
};
|
|
504
|
+
const upstreamResponse = await fetchUpstreamWithGentleRetry({
|
|
505
|
+
...requestArgs,
|
|
506
|
+
...(providerCallStore && providerCallContext?.userId
|
|
507
|
+
? {
|
|
508
|
+
providerCallStore,
|
|
509
|
+
providerCallContext: {
|
|
510
|
+
userId: providerCallContext.userId,
|
|
511
|
+
dialogId: providerCallContext.dialogId ?? undefined,
|
|
512
|
+
agentId: providerCallContext.agentId ?? undefined,
|
|
513
|
+
endpoint: "agentRun",
|
|
514
|
+
},
|
|
515
|
+
}
|
|
516
|
+
: {}),
|
|
517
|
+
});
|
|
450
518
|
const actualProvider = upstreamResponse.provider;
|
|
451
519
|
const actualModel = upstreamResponse.model;
|
|
452
520
|
const actualModelConfig =
|
|
@@ -456,10 +524,11 @@ async function fetchLoopUpstream(
|
|
|
456
524
|
return {
|
|
457
525
|
response: upstreamResponse.response,
|
|
458
526
|
provider: actualProvider,
|
|
459
|
-
model: actualModel,
|
|
460
|
-
inputPrice: actualModelConfig?.price.input ?? agentConfig.inputPrice,
|
|
461
|
-
outputPrice: actualModelConfig?.price.output ?? agentConfig.outputPrice,
|
|
462
|
-
|
|
527
|
+
model: actualModel,
|
|
528
|
+
inputPrice: actualModelConfig?.price.input ?? agentConfig.inputPrice,
|
|
529
|
+
outputPrice: actualModelConfig?.price.output ?? agentConfig.outputPrice,
|
|
530
|
+
providerCallIds: upstreamResponse.providerCallIds,
|
|
531
|
+
};
|
|
463
532
|
} catch (error: any) {
|
|
464
533
|
if (error?.name === "TimeoutError" || error?.name === "AbortError") {
|
|
465
534
|
throw new Error(`LLM API timeout after ${llmRequestTimeoutMs}ms: ${endpoint}`);
|
|
@@ -1223,22 +1292,22 @@ async function runWereadGatewayPreflightIfNeeded(args: {
|
|
|
1223
1292
|
args.send?.({ type: "tool_start", calls: ["wereadGateway"] });
|
|
1224
1293
|
|
|
1225
1294
|
const startedAt = Date.now();
|
|
1226
|
-
const toolResult = await executeToolOnServer(
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1295
|
+
const toolResult = await executeToolOnServer(
|
|
1296
|
+
toolCall,
|
|
1297
|
+
args.serverBase,
|
|
1298
|
+
args.authToken,
|
|
1299
|
+
buildLoopToolExecutionOptions({
|
|
1300
|
+
agentConfig: args.agentConfig,
|
|
1301
|
+
messages: args.messages,
|
|
1302
|
+
runtimePolicy: args.runtimePolicy,
|
|
1303
|
+
runtimeState: args.runtimeState,
|
|
1304
|
+
userId: args.userId,
|
|
1305
|
+
dialogId: args.dialogId,
|
|
1306
|
+
currentSpaceId: args.currentSpaceId,
|
|
1307
|
+
userInput: args.userInput,
|
|
1308
|
+
runtimeContext: args.runtimeContext,
|
|
1309
|
+
}),
|
|
1310
|
+
);
|
|
1242
1311
|
const completedAt = Date.now();
|
|
1243
1312
|
args.messages.push({
|
|
1244
1313
|
role: "tool",
|
|
@@ -1323,8 +1392,116 @@ export function applyLoopStreamMode(body: Record<string, any>, stream: boolean)
|
|
|
1323
1392
|
}
|
|
1324
1393
|
return body;
|
|
1325
1394
|
}
|
|
1326
|
-
|
|
1327
|
-
function
|
|
1395
|
+
|
|
1396
|
+
function addNumericUsageField(
|
|
1397
|
+
target: Record<string, any>,
|
|
1398
|
+
field: string,
|
|
1399
|
+
next: Record<string, any>,
|
|
1400
|
+
) {
|
|
1401
|
+
if (typeof next[field] !== "number" || !Number.isFinite(next[field])) return;
|
|
1402
|
+
target[field] = (typeof target[field] === "number" && Number.isFinite(target[field]) ? target[field] : 0) + next[field];
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
function uniqueStringList(...values: unknown[]): string[] {
|
|
1406
|
+
return Array.from(
|
|
1407
|
+
new Set(
|
|
1408
|
+
values
|
|
1409
|
+
.flatMap((value) => Array.isArray(value) ? value : [value])
|
|
1410
|
+
.filter((item): item is string => typeof item === "string")
|
|
1411
|
+
.map((item) => item.trim())
|
|
1412
|
+
.filter(Boolean)
|
|
1413
|
+
)
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
function addStringListUsageField(
|
|
1418
|
+
target: Record<string, any>,
|
|
1419
|
+
field: string,
|
|
1420
|
+
next: Record<string, any>,
|
|
1421
|
+
) {
|
|
1422
|
+
const merged = uniqueStringList(target[field], next[field]);
|
|
1423
|
+
if (merged.length > 0) target[field] = merged;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
function buildProviderAuditUsageMetadata(
|
|
1427
|
+
response?: Response | null,
|
|
1428
|
+
payload?: any,
|
|
1429
|
+
): Record<string, any> | undefined {
|
|
1430
|
+
const providerRequestIds = uniqueStringList(
|
|
1431
|
+
response?.headers.get("x-request-id"),
|
|
1432
|
+
response?.headers.get("x-openai-request-id"),
|
|
1433
|
+
response?.headers.get("openai-request-id"),
|
|
1434
|
+
response?.headers.get("cf-ray"),
|
|
1435
|
+
);
|
|
1436
|
+
const providerResponseIds = uniqueStringList(
|
|
1437
|
+
typeof payload?.id === "string" ? payload.id : undefined,
|
|
1438
|
+
typeof payload?.response?.id === "string" ? payload.response.id : undefined,
|
|
1439
|
+
);
|
|
1440
|
+
if (providerRequestIds.length === 0 && providerResponseIds.length === 0) {
|
|
1441
|
+
return undefined;
|
|
1442
|
+
}
|
|
1443
|
+
return {
|
|
1444
|
+
...(providerRequestIds.length > 0 ? { provider_request_ids: providerRequestIds } : {}),
|
|
1445
|
+
...(providerResponseIds.length > 0 ? { provider_response_ids: providerResponseIds } : {}),
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
function addUsageTotal(
|
|
1450
|
+
current: Record<string, any> | undefined | null,
|
|
1451
|
+
next: Record<string, any> | undefined | null,
|
|
1452
|
+
): Record<string, any> | undefined {
|
|
1453
|
+
if (!next || typeof next !== "object") return current ?? undefined;
|
|
1454
|
+
if (!current || typeof current !== "object") return { ...next };
|
|
1455
|
+
|
|
1456
|
+
const merged: Record<string, any> = { ...current };
|
|
1457
|
+
for (const field of [
|
|
1458
|
+
"prompt_tokens",
|
|
1459
|
+
"completion_tokens",
|
|
1460
|
+
"total_tokens",
|
|
1461
|
+
"input_tokens",
|
|
1462
|
+
"output_tokens",
|
|
1463
|
+
"cache_creation_input_tokens",
|
|
1464
|
+
"cache_read_input_tokens",
|
|
1465
|
+
"prompt_cache_hit_tokens",
|
|
1466
|
+
"prompt_cache_miss_tokens",
|
|
1467
|
+
"cost",
|
|
1468
|
+
]) {
|
|
1469
|
+
addNumericUsageField(merged, field, next);
|
|
1470
|
+
}
|
|
1471
|
+
for (const field of ["provider_response_ids", "provider_request_ids"]) {
|
|
1472
|
+
addStringListUsageField(merged, field, next);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
for (const [key, value] of Object.entries(next)) {
|
|
1476
|
+
if (
|
|
1477
|
+
!(key in merged) &&
|
|
1478
|
+
typeof value !== "number" &&
|
|
1479
|
+
!["provider_response_ids", "provider_request_ids"].includes(key)
|
|
1480
|
+
) {
|
|
1481
|
+
merged[key] = value;
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
return merged;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
function mergeUsageSnapshot(
|
|
1488
|
+
current: Record<string, any> | undefined | null,
|
|
1489
|
+
next: Record<string, any> | undefined | null,
|
|
1490
|
+
): Record<string, any> | undefined {
|
|
1491
|
+
if (!next || typeof next !== "object") return current ?? undefined;
|
|
1492
|
+
const merged: Record<string, any> =
|
|
1493
|
+
current && typeof current === "object" ? { ...current, ...next } : { ...next };
|
|
1494
|
+
for (const field of ["provider_response_ids", "provider_request_ids"]) {
|
|
1495
|
+
const values = uniqueStringList(
|
|
1496
|
+
current && typeof current === "object" ? current[field] : undefined,
|
|
1497
|
+
next[field],
|
|
1498
|
+
);
|
|
1499
|
+
if (values.length > 0) merged[field] = values;
|
|
1500
|
+
}
|
|
1501
|
+
return merged;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
function buildAssistantMessageFromResponse(data: any): ChatMessage | null {
|
|
1328
1505
|
const toolCalls = extractToolCallsFromResponseOutput(data);
|
|
1329
1506
|
const contentText = extractTextFromResponseOutput(data);
|
|
1330
1507
|
const contentImages = extractImagePartsFromResponseOutput(data);
|
|
@@ -1352,10 +1529,10 @@ function extractTextFromResponseOutputItem(item: any): string {
|
|
|
1352
1529
|
.join("");
|
|
1353
1530
|
}
|
|
1354
1531
|
|
|
1355
|
-
function buildLatencyProfile(args: {
|
|
1356
|
-
startedAt: number;
|
|
1357
|
-
llmRequestCount: number;
|
|
1358
|
-
llmWaitMs: number;
|
|
1532
|
+
function buildLatencyProfile(args: {
|
|
1533
|
+
startedAt: number;
|
|
1534
|
+
llmRequestCount: number;
|
|
1535
|
+
llmWaitMs: number;
|
|
1359
1536
|
llmJsonParseMs: number;
|
|
1360
1537
|
toolExecutionMs: number;
|
|
1361
1538
|
firstAssistantAt?: number;
|
|
@@ -1374,11 +1551,210 @@ function buildLatencyProfile(args: {
|
|
|
1374
1551
|
...(typeof args.firstToolResultAt === "number"
|
|
1375
1552
|
? { timeToFirstToolResultMs: Math.max(0, args.firstToolResultAt - args.startedAt) }
|
|
1376
1553
|
: {}),
|
|
1377
|
-
endedAt,
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1554
|
+
endedAt,
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
function buildLoopCompletion(args: {
|
|
1559
|
+
content: string;
|
|
1560
|
+
model: string;
|
|
1561
|
+
provider?: string;
|
|
1562
|
+
inputPrice?: number;
|
|
1563
|
+
outputPrice?: number;
|
|
1564
|
+
usage?: Record<string, any>;
|
|
1565
|
+
trace: ChatMessage[];
|
|
1566
|
+
runtimeToolNames: string[];
|
|
1567
|
+
toolCallCount: number;
|
|
1568
|
+
runtimePolicy?: ResolvedRuntimePolicy;
|
|
1569
|
+
runtimeState: ToolPolicyRuntimeState;
|
|
1570
|
+
startedAt: number;
|
|
1571
|
+
llmRequestCount: number;
|
|
1572
|
+
llmWaitMs: number;
|
|
1573
|
+
llmJsonParseMs: number;
|
|
1574
|
+
toolExecutionMs: number;
|
|
1575
|
+
firstAssistantAt?: number;
|
|
1576
|
+
firstToolResultAt?: number;
|
|
1577
|
+
providerCallIds?: string[];
|
|
1578
|
+
}): LoopResult {
|
|
1579
|
+
return {
|
|
1580
|
+
content: args.content,
|
|
1581
|
+
model: args.model,
|
|
1582
|
+
provider: args.provider,
|
|
1583
|
+
inputPrice: args.inputPrice,
|
|
1584
|
+
outputPrice: args.outputPrice,
|
|
1585
|
+
usage: args.usage,
|
|
1586
|
+
...(args.providerCallIds && args.providerCallIds.length > 0
|
|
1587
|
+
? { providerCallIds: [...args.providerCallIds] }
|
|
1588
|
+
: {}),
|
|
1589
|
+
trace: args.trace,
|
|
1590
|
+
runtimeToolNames: args.runtimeToolNames,
|
|
1591
|
+
toolCallCount: args.toolCallCount,
|
|
1592
|
+
policyState: {
|
|
1593
|
+
autoKnowledgeCaptureCount:
|
|
1594
|
+
(args.runtimePolicy?.knowledgeCapture.currentAutoCreates ?? 0) +
|
|
1595
|
+
args.runtimeState.autoKnowledgeCaptureCountThisRun,
|
|
1596
|
+
autoSpaceReadCount:
|
|
1597
|
+
(args.runtimePolicy?.spaceContext.currentAutoReads ?? 0) +
|
|
1598
|
+
args.runtimeState.autoSpaceReadCountThisRun,
|
|
1599
|
+
updatedAt: Date.now(),
|
|
1600
|
+
},
|
|
1601
|
+
latencyProfile: buildLatencyProfile({
|
|
1602
|
+
startedAt: args.startedAt,
|
|
1603
|
+
llmRequestCount: args.llmRequestCount,
|
|
1604
|
+
llmWaitMs: args.llmWaitMs,
|
|
1605
|
+
llmJsonParseMs: args.llmJsonParseMs,
|
|
1606
|
+
toolExecutionMs: args.toolExecutionMs,
|
|
1607
|
+
firstAssistantAt: args.firstAssistantAt,
|
|
1608
|
+
firstToolResultAt: args.firstToolResultAt,
|
|
1609
|
+
}),
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
function buildStreamDoneEvent(args: {
|
|
1614
|
+
usage?: Record<string, any>;
|
|
1615
|
+
provider?: string;
|
|
1616
|
+
model?: string;
|
|
1617
|
+
inputPrice?: number;
|
|
1618
|
+
outputPrice?: number;
|
|
1619
|
+
elapsed?: number;
|
|
1620
|
+
providerCallIds?: string[];
|
|
1621
|
+
}) {
|
|
1622
|
+
return {
|
|
1623
|
+
type: "done" as const,
|
|
1624
|
+
...(args.usage ? { usage: args.usage } : {}),
|
|
1625
|
+
...(args.provider ? { provider: args.provider } : {}),
|
|
1626
|
+
...(args.model ? { model: args.model } : {}),
|
|
1627
|
+
...(typeof args.inputPrice === "number" ? { inputPrice: args.inputPrice } : {}),
|
|
1628
|
+
...(typeof args.outputPrice === "number" ? { outputPrice: args.outputPrice } : {}),
|
|
1629
|
+
...(typeof args.elapsed === "number" ? { elapsed: args.elapsed } : {}),
|
|
1630
|
+
...(args.providerCallIds?.length ? { providerCallIds: [...args.providerCallIds] } : {}),
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
function buildRepairRequestMessages(args: {
|
|
1635
|
+
messages: ChatMessage[];
|
|
1636
|
+
finalParallelSummaryRepairPending: boolean;
|
|
1637
|
+
emptyAssistantRepairPending: boolean;
|
|
1638
|
+
}): ChatMessage[] {
|
|
1639
|
+
if (args.finalParallelSummaryRepairPending) {
|
|
1640
|
+
return [
|
|
1641
|
+
...args.messages,
|
|
1642
|
+
{ role: "system", content: FINAL_PARALLEL_SUMMARY_REPAIR_PROMPT } satisfies ChatMessage,
|
|
1643
|
+
];
|
|
1644
|
+
}
|
|
1645
|
+
if (args.emptyAssistantRepairPending) {
|
|
1646
|
+
return [
|
|
1647
|
+
...args.messages,
|
|
1648
|
+
{ role: "system", content: EMPTY_ASSISTANT_REPAIR_PROMPT } satisfies ChatMessage,
|
|
1649
|
+
];
|
|
1650
|
+
}
|
|
1651
|
+
return args.messages;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
function resolveAssistantRepairDecision(args: {
|
|
1655
|
+
messages: ChatMessage[];
|
|
1656
|
+
assistantMsg: ChatMessage;
|
|
1657
|
+
finalParallelSummaryRepairUsed: boolean;
|
|
1658
|
+
emptyAssistantRepairUsed: boolean;
|
|
1659
|
+
}): "parallel-summary" | "empty-assistant" | null {
|
|
1660
|
+
const assistantText = extractAssistantText(args.assistantMsg).trim();
|
|
1661
|
+
if (
|
|
1662
|
+
!args.assistantMsg.tool_calls?.length &&
|
|
1663
|
+
!assistantText &&
|
|
1664
|
+
!args.finalParallelSummaryRepairUsed &&
|
|
1665
|
+
hasParallelBranchMessages(args.messages)
|
|
1666
|
+
) {
|
|
1667
|
+
return "parallel-summary";
|
|
1668
|
+
}
|
|
1669
|
+
if (
|
|
1670
|
+
!args.assistantMsg.tool_calls?.length &&
|
|
1671
|
+
!assistantText &&
|
|
1672
|
+
!args.emptyAssistantRepairUsed
|
|
1673
|
+
) {
|
|
1674
|
+
return "empty-assistant";
|
|
1675
|
+
}
|
|
1676
|
+
return null;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
async function requestLoopUpstreamTurn(args: {
|
|
1680
|
+
endpoint: string;
|
|
1681
|
+
agentConfig: any;
|
|
1682
|
+
messages: ChatMessage[];
|
|
1683
|
+
tools: ReturnType<typeof buildTools>;
|
|
1684
|
+
stream: boolean;
|
|
1685
|
+
finalParallelSummaryRepairPending: boolean;
|
|
1686
|
+
emptyAssistantRepairPending: boolean;
|
|
1687
|
+
resolvedProvider?: string;
|
|
1688
|
+
resolvedModel: string;
|
|
1689
|
+
resolvedInputPrice?: number;
|
|
1690
|
+
resolvedOutputPrice?: number;
|
|
1691
|
+
providerCallContext?: {
|
|
1692
|
+
userId?: string | null;
|
|
1693
|
+
dialogId?: string | null;
|
|
1694
|
+
agentId?: string | null;
|
|
1695
|
+
};
|
|
1696
|
+
providerCallStore?: ProviderCallStore;
|
|
1697
|
+
}): Promise<{
|
|
1698
|
+
response: Response;
|
|
1699
|
+
provider?: string;
|
|
1700
|
+
model: string;
|
|
1701
|
+
inputPrice?: number;
|
|
1702
|
+
outputPrice?: number;
|
|
1703
|
+
providerCallIds?: string[];
|
|
1704
|
+
}> {
|
|
1705
|
+
const requestMessages = buildRepairRequestMessages({
|
|
1706
|
+
messages: args.messages,
|
|
1707
|
+
finalParallelSummaryRepairPending: args.finalParallelSummaryRepairPending,
|
|
1708
|
+
emptyAssistantRepairPending: args.emptyAssistantRepairPending,
|
|
1709
|
+
});
|
|
1710
|
+
const body = buildLoopRequestBody(args.agentConfig, requestMessages, args.tools, args.stream);
|
|
1711
|
+
const upstreamResult = await fetchLoopUpstream(
|
|
1712
|
+
args.endpoint,
|
|
1713
|
+
args.agentConfig,
|
|
1714
|
+
body,
|
|
1715
|
+
args.providerCallContext,
|
|
1716
|
+
args.providerCallStore,
|
|
1717
|
+
);
|
|
1718
|
+
return {
|
|
1719
|
+
response: upstreamResult.response,
|
|
1720
|
+
provider: upstreamResult.provider ?? args.resolvedProvider,
|
|
1721
|
+
model: upstreamResult.model ?? args.resolvedModel,
|
|
1722
|
+
inputPrice: upstreamResult.inputPrice ?? args.resolvedInputPrice,
|
|
1723
|
+
outputPrice: upstreamResult.outputPrice ?? args.resolvedOutputPrice,
|
|
1724
|
+
providerCallIds: upstreamResult.providerCallIds,
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
function buildLoopToolExecutionOptions(args: {
|
|
1729
|
+
agentConfig: any;
|
|
1730
|
+
messages: ChatMessage[];
|
|
1731
|
+
runtimePolicy?: ResolvedRuntimePolicy;
|
|
1732
|
+
runtimeState: ToolPolicyRuntimeState;
|
|
1733
|
+
userId?: string | null;
|
|
1734
|
+
dialogId?: string | null;
|
|
1735
|
+
currentSpaceId?: string | null;
|
|
1736
|
+
userInput?: string | null;
|
|
1737
|
+
runtimeContext?: AgentRunRuntimeContext | null;
|
|
1738
|
+
}) {
|
|
1739
|
+
return {
|
|
1740
|
+
policy: args.runtimePolicy,
|
|
1741
|
+
runtimeState: args.runtimeState,
|
|
1742
|
+
userId: args.userId,
|
|
1743
|
+
agentKey:
|
|
1744
|
+
typeof args.agentConfig?.dbKey === "string" && args.agentConfig.dbKey.trim()
|
|
1745
|
+
? args.agentConfig.dbKey.trim()
|
|
1746
|
+
: typeof args.agentConfig?.id === "string" && args.agentConfig.id.trim()
|
|
1747
|
+
? args.agentConfig.id.trim()
|
|
1748
|
+
: null,
|
|
1749
|
+
dialogId: args.dialogId,
|
|
1750
|
+
currentSpaceId: args.currentSpaceId,
|
|
1751
|
+
userInput: args.userInput,
|
|
1752
|
+
runtimeContext: args.runtimeContext,
|
|
1753
|
+
imageUrls: collectLatestImageUrls(args.messages),
|
|
1754
|
+
};
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
// ── 非流式 ────────────────────────────────────────────────────────────────────
|
|
1382
1758
|
|
|
1383
1759
|
export async function runAgentLoop(
|
|
1384
1760
|
agentConfig: any,
|
|
@@ -1392,130 +1768,144 @@ export async function runAgentLoop(
|
|
|
1392
1768
|
currentSpaceId?: string | null,
|
|
1393
1769
|
userInput?: string | null,
|
|
1394
1770
|
runtimeContext?: AgentRunRuntimeContext | null,
|
|
1771
|
+
providerCallStore?: ProviderCallStore,
|
|
1395
1772
|
): Promise<LoopResult> {
|
|
1396
1773
|
const startTime = Date.now();
|
|
1397
1774
|
agentConfig = await hydrateApiKeyReferenceIfNeeded(agentConfig, serverBase, authToken);
|
|
1775
|
+
const dispatchCliLoop = async () => {
|
|
1776
|
+
// CLI 与普通 model 共享 prompt/model/最近历史,但这里有意保持“单次文本委托”的边界。
|
|
1777
|
+
const provider: CliProvider = (agentConfig.cliProvider ?? "copilot") as CliProvider;
|
|
1778
|
+
const taskPrompt = buildCliTaskPrompt(initialMessages, userInput);
|
|
1779
|
+
const fullPrompt = buildCliPrompt(agentConfig.prompt, taskPrompt);
|
|
1780
|
+
const result = await executeCli(provider, fullPrompt, {
|
|
1781
|
+
model: agentConfig.model || undefined,
|
|
1782
|
+
yolo: true,
|
|
1783
|
+
});
|
|
1784
|
+
|
|
1785
|
+
return buildLoopCompletion({
|
|
1786
|
+
content: result.text,
|
|
1787
|
+
model: agentConfig.model ?? "unknown",
|
|
1788
|
+
provider: agentConfig.provider ?? undefined,
|
|
1789
|
+
inputPrice: agentConfig.inputPrice,
|
|
1790
|
+
outputPrice: agentConfig.outputPrice,
|
|
1791
|
+
usage: undefined,
|
|
1792
|
+
trace: [
|
|
1793
|
+
{
|
|
1794
|
+
role: "assistant",
|
|
1795
|
+
content: result.text,
|
|
1796
|
+
},
|
|
1797
|
+
],
|
|
1798
|
+
runtimeToolNames: [],
|
|
1799
|
+
toolCallCount: 0,
|
|
1800
|
+
runtimePolicy,
|
|
1801
|
+
runtimeState: {
|
|
1802
|
+
autoKnowledgeCaptureCountThisRun: 0,
|
|
1803
|
+
autoSpaceReadCountThisRun: 0,
|
|
1804
|
+
},
|
|
1805
|
+
startedAt: startTime,
|
|
1806
|
+
llmRequestCount: 0,
|
|
1807
|
+
llmWaitMs: 0,
|
|
1808
|
+
llmJsonParseMs: 0,
|
|
1809
|
+
toolExecutionMs: 0,
|
|
1810
|
+
firstAssistantAt: startTime + Math.max(0, result.elapsed ?? 0),
|
|
1811
|
+
});
|
|
1812
|
+
};
|
|
1398
1813
|
if (agentConfig.apiSource === "cli") {
|
|
1399
|
-
|
|
1400
|
-
const provider: CliProvider = (agentConfig.cliProvider ?? "copilot") as CliProvider;
|
|
1401
|
-
const taskPrompt = buildCliTaskPrompt(initialMessages, userInput);
|
|
1402
|
-
const fullPrompt = buildCliPrompt(agentConfig.prompt, taskPrompt);
|
|
1403
|
-
const result = await executeCli(provider, fullPrompt, {
|
|
1404
|
-
model: agentConfig.model || undefined,
|
|
1405
|
-
yolo: true,
|
|
1406
|
-
});
|
|
1407
|
-
|
|
1408
|
-
return {
|
|
1409
|
-
content: result.text,
|
|
1410
|
-
model: agentConfig.model ?? "unknown",
|
|
1411
|
-
provider: agentConfig.provider ?? undefined,
|
|
1412
|
-
inputPrice: agentConfig.inputPrice,
|
|
1413
|
-
outputPrice: agentConfig.outputPrice,
|
|
1414
|
-
usage: undefined,
|
|
1415
|
-
trace: [
|
|
1416
|
-
{
|
|
1417
|
-
role: "assistant",
|
|
1418
|
-
content: result.text,
|
|
1419
|
-
},
|
|
1420
|
-
],
|
|
1421
|
-
runtimeToolNames: [],
|
|
1422
|
-
toolCallCount: 0,
|
|
1423
|
-
policyState: {
|
|
1424
|
-
autoKnowledgeCaptureCount:
|
|
1425
|
-
(runtimePolicy?.knowledgeCapture.currentAutoCreates ?? 0),
|
|
1426
|
-
autoSpaceReadCount:
|
|
1427
|
-
(runtimePolicy?.spaceContext.currentAutoReads ?? 0),
|
|
1428
|
-
updatedAt: Date.now(),
|
|
1429
|
-
},
|
|
1430
|
-
latencyProfile: buildLatencyProfile({
|
|
1431
|
-
startedAt: startTime,
|
|
1432
|
-
llmRequestCount: 0,
|
|
1433
|
-
llmWaitMs: 0,
|
|
1434
|
-
llmJsonParseMs: 0,
|
|
1435
|
-
toolExecutionMs: 0,
|
|
1436
|
-
firstAssistantAt: startTime + Math.max(0, result.elapsed ?? 0),
|
|
1437
|
-
}),
|
|
1438
|
-
};
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
const endpoint = getApiEndpoint(agentConfig);
|
|
1442
|
-
const tools = buildTools(agentConfig);
|
|
1443
|
-
const runtimeToolNames = getPreparedToolNames(tools);
|
|
1444
|
-
// maxRounds 仅为兼容旧请求字段保留;工具轮次不再做硬限制。
|
|
1445
|
-
// 后续如需控制,应改为基于成本/预算的策略,而不是轮次数量。
|
|
1446
|
-
void _maxRounds;
|
|
1447
|
-
|
|
1448
|
-
const messages: ChatMessage[] = [...initialMessages];
|
|
1449
|
-
const traceStartIndex = messages.length;
|
|
1450
|
-
let finalContent = "";
|
|
1451
|
-
let lastUsage: Record<string, any> | undefined;
|
|
1452
|
-
let lastResolvedProvider = agentConfig.provider ?? undefined;
|
|
1453
|
-
let lastResolvedModel = agentConfig.model ?? "unknown";
|
|
1454
|
-
let lastResolvedInputPrice = agentConfig.inputPrice;
|
|
1455
|
-
let lastResolvedOutputPrice = agentConfig.outputPrice;
|
|
1456
|
-
let toolCallCount = 0;
|
|
1457
|
-
let llmRequestCount = 0;
|
|
1458
|
-
let llmWaitMs = 0;
|
|
1459
|
-
let llmJsonParseMs = 0;
|
|
1460
|
-
let toolExecutionMs = 0;
|
|
1461
|
-
let firstAssistantAt: number | undefined;
|
|
1462
|
-
let firstToolResultAt: number | undefined;
|
|
1463
|
-
const runtimeState: ToolPolicyRuntimeState = {
|
|
1464
|
-
autoKnowledgeCaptureCountThisRun: 0,
|
|
1465
|
-
autoSpaceReadCountThisRun: 0,
|
|
1466
|
-
};
|
|
1467
|
-
let finalParallelSummaryRepairPending = false;
|
|
1468
|
-
let finalParallelSummaryRepairUsed = false;
|
|
1469
|
-
let emptyAssistantRepairPending = false;
|
|
1470
|
-
let emptyAssistantRepairUsed = false;
|
|
1471
|
-
|
|
1472
|
-
const wereadPreflight = await runWereadGatewayPreflightIfNeeded({
|
|
1473
|
-
agentConfig,
|
|
1474
|
-
tools,
|
|
1475
|
-
messages,
|
|
1476
|
-
serverBase,
|
|
1477
|
-
authToken,
|
|
1478
|
-
runtimePolicy,
|
|
1479
|
-
runtimeState,
|
|
1480
|
-
userId,
|
|
1481
|
-
dialogId,
|
|
1482
|
-
currentSpaceId,
|
|
1483
|
-
userInput,
|
|
1484
|
-
runtimeContext,
|
|
1485
|
-
});
|
|
1486
|
-
if (wereadPreflight.ran) {
|
|
1487
|
-
toolCallCount += 1;
|
|
1488
|
-
toolExecutionMs += wereadPreflight.elapsedMs;
|
|
1489
|
-
firstToolResultAt = wereadPreflight.completedAt;
|
|
1814
|
+
return await dispatchCliLoop();
|
|
1490
1815
|
}
|
|
1816
|
+
const dispatchModelLoop = async () => {
|
|
1817
|
+
|
|
1818
|
+
const endpoint = getApiEndpoint(agentConfig);
|
|
1819
|
+
const tools = buildTools(agentConfig);
|
|
1820
|
+
const runtimeToolNames = getPreparedToolNames(tools);
|
|
1821
|
+
// maxRounds 仅为兼容旧请求字段保留;工具轮次不再做硬限制。
|
|
1822
|
+
// 后续如需控制,应改为基于成本/预算的策略,而不是轮次数量。
|
|
1823
|
+
void _maxRounds;
|
|
1824
|
+
|
|
1825
|
+
const messages: ChatMessage[] = [...initialMessages];
|
|
1826
|
+
const traceStartIndex = messages.length;
|
|
1827
|
+
let finalContent = "";
|
|
1828
|
+
let lastUsage: Record<string, any> | undefined;
|
|
1829
|
+
let lastResolvedProvider = agentConfig.provider ?? undefined;
|
|
1830
|
+
let lastResolvedModel = agentConfig.model ?? "unknown";
|
|
1831
|
+
let lastResolvedInputPrice = agentConfig.inputPrice;
|
|
1832
|
+
let lastResolvedOutputPrice = agentConfig.outputPrice;
|
|
1833
|
+
const providerCallIds: string[] = [];
|
|
1834
|
+
let toolCallCount = 0;
|
|
1835
|
+
let llmRequestCount = 0;
|
|
1836
|
+
let llmWaitMs = 0;
|
|
1837
|
+
let llmJsonParseMs = 0;
|
|
1838
|
+
let toolExecutionMs = 0;
|
|
1839
|
+
let firstAssistantAt: number | undefined;
|
|
1840
|
+
let firstToolResultAt: number | undefined;
|
|
1841
|
+
const runtimeState: ToolPolicyRuntimeState = {
|
|
1842
|
+
autoKnowledgeCaptureCountThisRun: 0,
|
|
1843
|
+
autoSpaceReadCountThisRun: 0,
|
|
1844
|
+
};
|
|
1845
|
+
let finalParallelSummaryRepairPending = false;
|
|
1846
|
+
let finalParallelSummaryRepairUsed = false;
|
|
1847
|
+
let emptyAssistantRepairPending = false;
|
|
1848
|
+
let emptyAssistantRepairUsed = false;
|
|
1849
|
+
|
|
1850
|
+
const wereadPreflight = await runWereadGatewayPreflightIfNeeded({
|
|
1851
|
+
agentConfig,
|
|
1852
|
+
tools,
|
|
1853
|
+
messages,
|
|
1854
|
+
serverBase,
|
|
1855
|
+
authToken,
|
|
1856
|
+
runtimePolicy,
|
|
1857
|
+
runtimeState,
|
|
1858
|
+
userId,
|
|
1859
|
+
dialogId,
|
|
1860
|
+
currentSpaceId,
|
|
1861
|
+
userInput,
|
|
1862
|
+
runtimeContext,
|
|
1863
|
+
});
|
|
1864
|
+
if (wereadPreflight.ran) {
|
|
1865
|
+
toolCallCount += 1;
|
|
1866
|
+
toolExecutionMs += wereadPreflight.elapsedMs;
|
|
1867
|
+
firstToolResultAt = wereadPreflight.completedAt;
|
|
1868
|
+
}
|
|
1491
1869
|
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1870
|
+
for (;;) {
|
|
1871
|
+
if (Date.now() - startTime > MAX_TIME_MS) break;
|
|
1872
|
+
|
|
1873
|
+
const repairPendingState = {
|
|
1874
|
+
finalParallelSummaryRepairPending,
|
|
1875
|
+
emptyAssistantRepairPending,
|
|
1876
|
+
};
|
|
1877
|
+
const upstreamStartedAt = Date.now();
|
|
1878
|
+
const upstreamTurn = await requestLoopUpstreamTurn({
|
|
1879
|
+
endpoint,
|
|
1880
|
+
agentConfig,
|
|
1881
|
+
messages,
|
|
1882
|
+
tools,
|
|
1883
|
+
stream: false,
|
|
1884
|
+
finalParallelSummaryRepairPending: repairPendingState.finalParallelSummaryRepairPending,
|
|
1885
|
+
emptyAssistantRepairPending: repairPendingState.emptyAssistantRepairPending,
|
|
1886
|
+
resolvedProvider: lastResolvedProvider,
|
|
1887
|
+
resolvedModel: lastResolvedModel,
|
|
1888
|
+
resolvedInputPrice: lastResolvedInputPrice,
|
|
1889
|
+
resolvedOutputPrice: lastResolvedOutputPrice,
|
|
1890
|
+
providerCallContext: {
|
|
1891
|
+
userId,
|
|
1892
|
+
dialogId,
|
|
1893
|
+
agentId: agentConfig.dbKey ?? agentConfig.id ?? null,
|
|
1894
|
+
},
|
|
1895
|
+
providerCallStore,
|
|
1896
|
+
});
|
|
1897
|
+
finalParallelSummaryRepairPending = false;
|
|
1898
|
+
emptyAssistantRepairPending = false;
|
|
1899
|
+
const res = upstreamTurn.response;
|
|
1900
|
+
llmRequestCount += 1;
|
|
1901
|
+
llmWaitMs += Math.max(0, Date.now() - upstreamStartedAt);
|
|
1902
|
+
lastResolvedProvider = upstreamTurn.provider;
|
|
1903
|
+
lastResolvedModel = upstreamTurn.model;
|
|
1904
|
+
lastResolvedInputPrice = upstreamTurn.inputPrice;
|
|
1905
|
+
lastResolvedOutputPrice = upstreamTurn.outputPrice;
|
|
1906
|
+
if (upstreamTurn.providerCallIds?.length) {
|
|
1907
|
+
providerCallIds.push(...upstreamTurn.providerCallIds);
|
|
1908
|
+
}
|
|
1519
1909
|
|
|
1520
1910
|
if (!res.ok) throw new Error(`LLM API error (${res.status}): ${await res.text()}`);
|
|
1521
1911
|
|
|
@@ -1531,23 +1921,23 @@ export async function runAgentLoop(
|
|
|
1531
1921
|
firstAssistantAt = Date.now();
|
|
1532
1922
|
}
|
|
1533
1923
|
|
|
1534
|
-
lastUsage =
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1924
|
+
lastUsage = addUsageTotal(
|
|
1925
|
+
lastUsage,
|
|
1926
|
+
addUsageTotal(data.usage ?? data.response?.usage, buildProviderAuditUsageMetadata(res, data)),
|
|
1927
|
+
);
|
|
1928
|
+
const assistantText = extractAssistantText(assistantMsg).trim();
|
|
1929
|
+
const repairDecision = resolveAssistantRepairDecision({
|
|
1930
|
+
messages,
|
|
1931
|
+
assistantMsg,
|
|
1932
|
+
finalParallelSummaryRepairUsed,
|
|
1933
|
+
emptyAssistantRepairUsed,
|
|
1934
|
+
});
|
|
1935
|
+
if (repairDecision === "parallel-summary") {
|
|
1936
|
+
finalParallelSummaryRepairPending = true;
|
|
1543
1937
|
finalParallelSummaryRepairUsed = true;
|
|
1544
1938
|
continue;
|
|
1545
1939
|
}
|
|
1546
|
-
if (
|
|
1547
|
-
!assistantMsg.tool_calls?.length &&
|
|
1548
|
-
!assistantText &&
|
|
1549
|
-
!emptyAssistantRepairUsed
|
|
1550
|
-
) {
|
|
1940
|
+
if (repairDecision === "empty-assistant") {
|
|
1551
1941
|
emptyAssistantRepairPending = true;
|
|
1552
1942
|
emptyAssistantRepairUsed = true;
|
|
1553
1943
|
continue;
|
|
@@ -1562,22 +1952,22 @@ export async function runAgentLoop(
|
|
|
1562
1952
|
for (const tc of assistantMsg.tool_calls!) {
|
|
1563
1953
|
toolCallCount++;
|
|
1564
1954
|
const toolStartedAt = Date.now();
|
|
1565
|
-
const toolResult = await executeToolOnServer(
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1955
|
+
const toolResult = await executeToolOnServer(
|
|
1956
|
+
tc,
|
|
1957
|
+
serverBase,
|
|
1958
|
+
authToken,
|
|
1959
|
+
buildLoopToolExecutionOptions({
|
|
1960
|
+
agentConfig,
|
|
1961
|
+
messages,
|
|
1962
|
+
runtimePolicy,
|
|
1963
|
+
runtimeState,
|
|
1964
|
+
userId,
|
|
1965
|
+
dialogId,
|
|
1966
|
+
currentSpaceId,
|
|
1967
|
+
userInput,
|
|
1968
|
+
runtimeContext,
|
|
1969
|
+
}),
|
|
1970
|
+
);
|
|
1581
1971
|
toolExecutionMs += Math.max(0, Date.now() - toolStartedAt);
|
|
1582
1972
|
if (firstToolResultAt === undefined) {
|
|
1583
1973
|
firstToolResultAt = Date.now();
|
|
@@ -1588,125 +1978,103 @@ export async function runAgentLoop(
|
|
|
1588
1978
|
content: toolResult,
|
|
1589
1979
|
});
|
|
1590
1980
|
const directCompletion = buildDirectCompletionFromToolResult(tc.function.name, toolResult);
|
|
1591
|
-
if (directCompletion) {
|
|
1592
|
-
finalContent = directCompletion;
|
|
1593
|
-
messages.push({
|
|
1594
|
-
role: "assistant",
|
|
1595
|
-
content: directCompletion,
|
|
1596
|
-
});
|
|
1597
|
-
|
|
1598
|
-
content: finalContent,
|
|
1599
|
-
model: lastResolvedModel,
|
|
1600
|
-
provider: lastResolvedProvider,
|
|
1601
|
-
inputPrice: lastResolvedInputPrice,
|
|
1602
|
-
outputPrice: lastResolvedOutputPrice,
|
|
1603
|
-
usage: lastUsage,
|
|
1604
|
-
trace: messages.slice(traceStartIndex),
|
|
1605
|
-
runtimeToolNames,
|
|
1606
|
-
toolCallCount,
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
llmWaitMs,
|
|
1620
|
-
llmJsonParseMs,
|
|
1621
|
-
toolExecutionMs,
|
|
1622
|
-
firstAssistantAt,
|
|
1623
|
-
firstToolResultAt,
|
|
1624
|
-
}),
|
|
1625
|
-
};
|
|
1626
|
-
}
|
|
1981
|
+
if (directCompletion) {
|
|
1982
|
+
finalContent = directCompletion;
|
|
1983
|
+
messages.push({
|
|
1984
|
+
role: "assistant",
|
|
1985
|
+
content: directCompletion,
|
|
1986
|
+
});
|
|
1987
|
+
return buildLoopCompletion({
|
|
1988
|
+
content: finalContent,
|
|
1989
|
+
model: lastResolvedModel,
|
|
1990
|
+
provider: lastResolvedProvider,
|
|
1991
|
+
inputPrice: lastResolvedInputPrice,
|
|
1992
|
+
outputPrice: lastResolvedOutputPrice,
|
|
1993
|
+
usage: lastUsage,
|
|
1994
|
+
trace: messages.slice(traceStartIndex),
|
|
1995
|
+
runtimeToolNames,
|
|
1996
|
+
toolCallCount,
|
|
1997
|
+
runtimePolicy,
|
|
1998
|
+
runtimeState,
|
|
1999
|
+
startedAt: startTime,
|
|
2000
|
+
llmRequestCount,
|
|
2001
|
+
llmWaitMs,
|
|
2002
|
+
llmJsonParseMs,
|
|
2003
|
+
toolExecutionMs,
|
|
2004
|
+
firstAssistantAt,
|
|
2005
|
+
firstToolResultAt,
|
|
2006
|
+
providerCallIds,
|
|
2007
|
+
});
|
|
2008
|
+
}
|
|
1627
2009
|
if (["runStreamingAgent", "streamParallelAgents"].includes(canonicalizeToolName(tc.function.name))) {
|
|
1628
2010
|
const parsed = parseToolResult(toolResult);
|
|
1629
2011
|
if (canonicalizeToolName(tc.function.name) === "streamParallelAgents") {
|
|
1630
2012
|
appendParallelBranchMessages(messages, parsed);
|
|
1631
2013
|
}
|
|
1632
|
-
if (parsed?.handoff && typeof parsed.content === "string" && parsed.content.trim()) {
|
|
1633
|
-
finalContent = parsed.content;
|
|
1634
|
-
if (canonicalizeToolName(tc.function.name) !== "streamParallelAgents") {
|
|
1635
|
-
messages.push({
|
|
1636
|
-
role: "assistant",
|
|
1637
|
-
content: parsed.content,
|
|
1638
|
-
});
|
|
1639
|
-
}
|
|
1640
|
-
return {
|
|
1641
|
-
content: finalContent,
|
|
1642
|
-
model: parsed.model || lastResolvedModel,
|
|
1643
|
-
provider: parsed.provider || lastResolvedProvider,
|
|
1644
|
-
inputPrice:
|
|
1645
|
-
typeof parsed.inputPrice === "number"
|
|
2014
|
+
if (parsed?.handoff && typeof parsed.content === "string" && parsed.content.trim()) {
|
|
2015
|
+
finalContent = parsed.content;
|
|
2016
|
+
if (canonicalizeToolName(tc.function.name) !== "streamParallelAgents") {
|
|
2017
|
+
messages.push({
|
|
2018
|
+
role: "assistant",
|
|
2019
|
+
content: parsed.content,
|
|
2020
|
+
});
|
|
2021
|
+
}
|
|
2022
|
+
return buildLoopCompletion({
|
|
2023
|
+
content: finalContent,
|
|
2024
|
+
model: parsed.model || lastResolvedModel,
|
|
2025
|
+
provider: parsed.provider || lastResolvedProvider,
|
|
2026
|
+
inputPrice:
|
|
2027
|
+
typeof parsed.inputPrice === "number"
|
|
1646
2028
|
? parsed.inputPrice
|
|
1647
2029
|
: lastResolvedInputPrice,
|
|
1648
2030
|
outputPrice:
|
|
1649
2031
|
typeof parsed.outputPrice === "number"
|
|
1650
|
-
? parsed.outputPrice
|
|
1651
|
-
: lastResolvedOutputPrice,
|
|
1652
|
-
usage: parsed.usage ?? lastUsage,
|
|
1653
|
-
trace: messages.slice(traceStartIndex),
|
|
1654
|
-
runtimeToolNames,
|
|
1655
|
-
toolCallCount,
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
runtimeState.autoSpaceReadCountThisRun,
|
|
1697
|
-
updatedAt: Date.now(),
|
|
1698
|
-
},
|
|
1699
|
-
latencyProfile: buildLatencyProfile({
|
|
1700
|
-
startedAt: startTime,
|
|
1701
|
-
llmRequestCount,
|
|
1702
|
-
llmWaitMs,
|
|
1703
|
-
llmJsonParseMs,
|
|
1704
|
-
toolExecutionMs,
|
|
1705
|
-
firstAssistantAt,
|
|
1706
|
-
firstToolResultAt,
|
|
1707
|
-
}),
|
|
1708
|
-
};
|
|
1709
|
-
}
|
|
2032
|
+
? parsed.outputPrice
|
|
2033
|
+
: lastResolvedOutputPrice,
|
|
2034
|
+
usage: parsed.usage ?? lastUsage,
|
|
2035
|
+
trace: messages.slice(traceStartIndex),
|
|
2036
|
+
runtimeToolNames,
|
|
2037
|
+
toolCallCount,
|
|
2038
|
+
runtimePolicy,
|
|
2039
|
+
runtimeState,
|
|
2040
|
+
startedAt: startTime,
|
|
2041
|
+
llmRequestCount,
|
|
2042
|
+
llmWaitMs,
|
|
2043
|
+
llmJsonParseMs,
|
|
2044
|
+
toolExecutionMs,
|
|
2045
|
+
firstAssistantAt,
|
|
2046
|
+
firstToolResultAt,
|
|
2047
|
+
providerCallIds,
|
|
2048
|
+
});
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
return buildLoopCompletion({
|
|
2055
|
+
content: finalContent,
|
|
2056
|
+
model: lastResolvedModel,
|
|
2057
|
+
provider: lastResolvedProvider,
|
|
2058
|
+
inputPrice: lastResolvedInputPrice,
|
|
2059
|
+
outputPrice: lastResolvedOutputPrice,
|
|
2060
|
+
usage: lastUsage,
|
|
2061
|
+
trace: messages.slice(traceStartIndex),
|
|
2062
|
+
runtimeToolNames,
|
|
2063
|
+
toolCallCount,
|
|
2064
|
+
runtimePolicy,
|
|
2065
|
+
runtimeState,
|
|
2066
|
+
startedAt: startTime,
|
|
2067
|
+
llmRequestCount,
|
|
2068
|
+
llmWaitMs,
|
|
2069
|
+
llmJsonParseMs,
|
|
2070
|
+
toolExecutionMs,
|
|
2071
|
+
firstAssistantAt,
|
|
2072
|
+
firstToolResultAt,
|
|
2073
|
+
providerCallIds,
|
|
2074
|
+
});
|
|
2075
|
+
};
|
|
2076
|
+
return await dispatchModelLoop();
|
|
2077
|
+
}
|
|
1710
2078
|
|
|
1711
2079
|
// ── 流式(SSE)────────────────────────────────────────────────────────────────
|
|
1712
2080
|
|
|
@@ -1724,104 +2092,121 @@ export function buildSseStream(
|
|
|
1724
2092
|
currentSpaceId?: string | null,
|
|
1725
2093
|
userInput?: string | null,
|
|
1726
2094
|
runtimeContext?: AgentRunRuntimeContext | null,
|
|
2095
|
+
providerCallStore?: ProviderCallStore,
|
|
1727
2096
|
): ReadableStream {
|
|
1728
2097
|
const encoder = new TextEncoder();
|
|
1729
2098
|
|
|
1730
|
-
return new ReadableStream({
|
|
1731
|
-
async start(controller) {
|
|
1732
|
-
const send: Send = (data) =>
|
|
1733
|
-
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`));
|
|
1734
|
-
|
|
1735
|
-
try {
|
|
1736
|
-
if (agentConfig.apiSource === "cli") {
|
|
1737
|
-
// CLI 流式输出仅依赖 provider 自己的 stdout 语义,不合成本地 tool 事件。
|
|
1738
|
-
const provider: CliProvider = (agentConfig.cliProvider ?? "copilot") as CliProvider;
|
|
1739
|
-
const taskPrompt = buildCliTaskPrompt(initialMessages, userInput);
|
|
1740
|
-
const fullPrompt = buildCliPrompt(agentConfig.prompt, taskPrompt);
|
|
1741
|
-
|
|
1742
|
-
const result = await executeCliStreaming(provider, fullPrompt, {
|
|
1743
|
-
model: agentConfig.model || undefined,
|
|
1744
|
-
yolo: true,
|
|
1745
|
-
onChunk: (chunk: string) => {
|
|
1746
|
-
if (!chunk) return;
|
|
1747
|
-
send({ type: "text", content: chunk });
|
|
1748
|
-
},
|
|
1749
|
-
});
|
|
1750
|
-
|
|
1751
|
-
send({ type: "done", usage: undefined, elapsed: result.elapsed });
|
|
1752
|
-
controller.close();
|
|
1753
|
-
return;
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
const endpoint = getApiEndpoint(agentConfig);
|
|
1757
|
-
const tools = buildTools(agentConfig);
|
|
1758
|
-
// maxRounds 仅为兼容旧请求字段保留;工具轮次不再做硬限制。
|
|
1759
|
-
// 后续如需控制,应改为基于成本/预算的策略,而不是轮次数量。
|
|
1760
|
-
void _maxRounds;
|
|
1761
|
-
const messages: ChatMessage[] = [...initialMessages];
|
|
1762
|
-
const runtimeState: ToolPolicyRuntimeState = {
|
|
1763
|
-
autoKnowledgeCaptureCountThisRun: 0,
|
|
1764
|
-
autoSpaceReadCountThisRun: 0,
|
|
1765
|
-
};
|
|
1766
|
-
const startTime = Date.now();
|
|
1767
|
-
let lastUsage: Record<string, any> | undefined;
|
|
1768
|
-
let lastResolvedProvider = agentConfig.provider ?? undefined;
|
|
1769
|
-
let lastResolvedModel = agentConfig.model ?? "unknown";
|
|
1770
|
-
let lastResolvedInputPrice = agentConfig.inputPrice;
|
|
1771
|
-
let lastResolvedOutputPrice = agentConfig.outputPrice;
|
|
1772
|
-
let finalParallelSummaryRepairPending = false;
|
|
1773
|
-
let finalParallelSummaryRepairUsed = false;
|
|
1774
|
-
let emptyAssistantRepairPending = false;
|
|
1775
|
-
let emptyAssistantRepairUsed = false;
|
|
1776
|
-
|
|
1777
|
-
await runWereadGatewayPreflightIfNeeded({
|
|
1778
|
-
agentConfig,
|
|
1779
|
-
tools,
|
|
1780
|
-
messages,
|
|
1781
|
-
serverBase,
|
|
1782
|
-
authToken,
|
|
1783
|
-
runtimePolicy,
|
|
1784
|
-
runtimeState,
|
|
1785
|
-
userId,
|
|
1786
|
-
dialogId,
|
|
1787
|
-
currentSpaceId,
|
|
1788
|
-
userInput,
|
|
1789
|
-
runtimeContext,
|
|
1790
|
-
send,
|
|
1791
|
-
});
|
|
2099
|
+
return new ReadableStream({
|
|
2100
|
+
async start(controller) {
|
|
2101
|
+
const send: Send = (data) =>
|
|
2102
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`));
|
|
1792
2103
|
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
2104
|
+
try {
|
|
2105
|
+
const dispatchCliStreamingLoop = async () => {
|
|
2106
|
+
// CLI 流式输出仅依赖 provider 自己的 stdout 语义,不合成本地 tool 事件。
|
|
2107
|
+
const provider: CliProvider = (agentConfig.cliProvider ?? "copilot") as CliProvider;
|
|
2108
|
+
const taskPrompt = buildCliTaskPrompt(initialMessages, userInput);
|
|
2109
|
+
const fullPrompt = buildCliPrompt(agentConfig.prompt, taskPrompt);
|
|
2110
|
+
|
|
2111
|
+
const result = await executeCliStreaming(provider, fullPrompt, {
|
|
2112
|
+
model: agentConfig.model || undefined,
|
|
2113
|
+
yolo: true,
|
|
2114
|
+
onChunk: (chunk: string) => {
|
|
2115
|
+
if (!chunk) return;
|
|
2116
|
+
send({ type: "text", content: chunk });
|
|
2117
|
+
},
|
|
2118
|
+
});
|
|
2119
|
+
|
|
2120
|
+
send(buildStreamDoneEvent({ elapsed: result.elapsed }));
|
|
2121
|
+
controller.close();
|
|
2122
|
+
};
|
|
2123
|
+
if (agentConfig.apiSource === "cli") {
|
|
2124
|
+
return await dispatchCliStreamingLoop();
|
|
2125
|
+
}
|
|
2126
|
+
const dispatchModelStreamingLoop = async () => {
|
|
2127
|
+
|
|
2128
|
+
const endpoint = getApiEndpoint(agentConfig);
|
|
2129
|
+
const tools = buildTools(agentConfig);
|
|
2130
|
+
// maxRounds 仅为兼容旧请求字段保留;工具轮次不再做硬限制。
|
|
2131
|
+
// 后续如需控制,应改为基于成本/预算的策略,而不是轮次数量。
|
|
2132
|
+
void _maxRounds;
|
|
2133
|
+
const messages: ChatMessage[] = [...initialMessages];
|
|
2134
|
+
const runtimeState: ToolPolicyRuntimeState = {
|
|
2135
|
+
autoKnowledgeCaptureCountThisRun: 0,
|
|
2136
|
+
autoSpaceReadCountThisRun: 0,
|
|
2137
|
+
};
|
|
2138
|
+
const startTime = Date.now();
|
|
2139
|
+
let lastUsage: Record<string, any> | undefined;
|
|
2140
|
+
let lastResolvedProvider = agentConfig.provider ?? undefined;
|
|
2141
|
+
let lastResolvedModel = agentConfig.model ?? "unknown";
|
|
2142
|
+
let lastResolvedInputPrice = agentConfig.inputPrice;
|
|
2143
|
+
let lastResolvedOutputPrice = agentConfig.outputPrice;
|
|
2144
|
+
const providerCallIds: string[] = [];
|
|
2145
|
+
let finalParallelSummaryRepairPending = false;
|
|
2146
|
+
let finalParallelSummaryRepairUsed = false;
|
|
2147
|
+
let emptyAssistantRepairPending = false;
|
|
2148
|
+
let emptyAssistantRepairUsed = false;
|
|
2149
|
+
|
|
2150
|
+
await runWereadGatewayPreflightIfNeeded({
|
|
2151
|
+
agentConfig,
|
|
2152
|
+
tools,
|
|
2153
|
+
messages,
|
|
2154
|
+
serverBase,
|
|
2155
|
+
authToken,
|
|
2156
|
+
runtimePolicy,
|
|
2157
|
+
runtimeState,
|
|
2158
|
+
userId,
|
|
2159
|
+
dialogId,
|
|
2160
|
+
currentSpaceId,
|
|
2161
|
+
userInput,
|
|
2162
|
+
runtimeContext,
|
|
2163
|
+
send,
|
|
2164
|
+
});
|
|
2165
|
+
|
|
2166
|
+
for (;;) {
|
|
2167
|
+
if (Date.now() - startTime > MAX_TIME_MS) {
|
|
2168
|
+
send({ type: "error", message: "Max execution time exceeded" });
|
|
2169
|
+
break;
|
|
2170
|
+
}
|
|
2171
|
+
const repairPendingState = {
|
|
2172
|
+
finalParallelSummaryRepairPending,
|
|
2173
|
+
emptyAssistantRepairPending,
|
|
2174
|
+
};
|
|
1811
2175
|
finalParallelSummaryRepairPending = false;
|
|
1812
2176
|
emptyAssistantRepairPending = false;
|
|
1813
|
-
|
|
1814
|
-
let res: Response;
|
|
1815
|
-
try {
|
|
1816
|
-
const
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
2177
|
+
|
|
2178
|
+
let res: Response;
|
|
2179
|
+
try {
|
|
2180
|
+
const upstreamTurn = await requestLoopUpstreamTurn({
|
|
2181
|
+
endpoint,
|
|
2182
|
+
agentConfig,
|
|
2183
|
+
messages,
|
|
2184
|
+
tools,
|
|
2185
|
+
stream: true,
|
|
2186
|
+
finalParallelSummaryRepairPending: repairPendingState.finalParallelSummaryRepairPending,
|
|
2187
|
+
emptyAssistantRepairPending: repairPendingState.emptyAssistantRepairPending,
|
|
2188
|
+
resolvedProvider: lastResolvedProvider,
|
|
2189
|
+
resolvedModel: lastResolvedModel,
|
|
2190
|
+
resolvedInputPrice: lastResolvedInputPrice,
|
|
2191
|
+
resolvedOutputPrice: lastResolvedOutputPrice,
|
|
2192
|
+
providerCallContext: {
|
|
2193
|
+
userId,
|
|
2194
|
+
dialogId,
|
|
2195
|
+
agentId: agentConfig.dbKey ?? agentConfig.id ?? null,
|
|
2196
|
+
},
|
|
2197
|
+
providerCallStore,
|
|
2198
|
+
});
|
|
2199
|
+
res = upstreamTurn.response;
|
|
2200
|
+
lastResolvedProvider = upstreamTurn.provider;
|
|
2201
|
+
lastResolvedModel = upstreamTurn.model;
|
|
2202
|
+
lastResolvedInputPrice = upstreamTurn.inputPrice;
|
|
2203
|
+
lastResolvedOutputPrice = upstreamTurn.outputPrice;
|
|
2204
|
+
if (upstreamTurn.providerCallIds?.length) {
|
|
2205
|
+
providerCallIds.push(...upstreamTurn.providerCallIds);
|
|
2206
|
+
}
|
|
2207
|
+
} catch (error: any) {
|
|
2208
|
+
send({ type: "error", message: error?.message ?? "Unexpected error" });
|
|
2209
|
+
break;
|
|
1825
2210
|
}
|
|
1826
2211
|
if (!res.ok || !res.body) {
|
|
1827
2212
|
send({ type: "error", message: `LLM API error (${res.status}): ${await res.text()}` });
|
|
@@ -1839,7 +2224,10 @@ export function buildSseStream(
|
|
|
1839
2224
|
assistantContent,
|
|
1840
2225
|
reasoningContent,
|
|
1841
2226
|
} = streamResult;
|
|
1842
|
-
lastUsage =
|
|
2227
|
+
lastUsage = addUsageTotal(
|
|
2228
|
+
lastUsage,
|
|
2229
|
+
addUsageTotal(streamResult.lastUsage, buildProviderAuditUsageMetadata(res)),
|
|
2230
|
+
);
|
|
1843
2231
|
|
|
1844
2232
|
const assistantMsg: ChatMessage = {
|
|
1845
2233
|
role: "assistant",
|
|
@@ -1847,38 +2235,35 @@ export function buildSseStream(
|
|
|
1847
2235
|
...(reasoningContent ? { reasoning_content: reasoningContent } : {}),
|
|
1848
2236
|
...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),
|
|
1849
2237
|
};
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
)
|
|
1856
|
-
|
|
2238
|
+
const repairDecision = resolveAssistantRepairDecision({
|
|
2239
|
+
messages,
|
|
2240
|
+
assistantMsg,
|
|
2241
|
+
finalParallelSummaryRepairUsed,
|
|
2242
|
+
emptyAssistantRepairUsed,
|
|
2243
|
+
});
|
|
2244
|
+
if (repairDecision === "parallel-summary") {
|
|
2245
|
+
finalParallelSummaryRepairPending = true;
|
|
1857
2246
|
finalParallelSummaryRepairUsed = true;
|
|
1858
2247
|
continue;
|
|
1859
2248
|
}
|
|
1860
|
-
if (
|
|
1861
|
-
!hasToolCalls &&
|
|
1862
|
-
!extractAssistantText(assistantMsg).trim() &&
|
|
1863
|
-
!emptyAssistantRepairUsed
|
|
1864
|
-
) {
|
|
2249
|
+
if (repairDecision === "empty-assistant") {
|
|
1865
2250
|
emptyAssistantRepairPending = true;
|
|
1866
2251
|
emptyAssistantRepairUsed = true;
|
|
1867
2252
|
continue;
|
|
1868
2253
|
}
|
|
1869
2254
|
messages.push(assistantMsg);
|
|
1870
2255
|
|
|
1871
|
-
if (!hasToolCalls) {
|
|
1872
|
-
send({
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
});
|
|
1880
|
-
break;
|
|
1881
|
-
}
|
|
2256
|
+
if (!hasToolCalls) {
|
|
2257
|
+
send(buildStreamDoneEvent({
|
|
2258
|
+
usage: lastUsage,
|
|
2259
|
+
provider: lastResolvedProvider,
|
|
2260
|
+
model: lastResolvedModel,
|
|
2261
|
+
inputPrice: lastResolvedInputPrice,
|
|
2262
|
+
outputPrice: lastResolvedOutputPrice,
|
|
2263
|
+
providerCallIds,
|
|
2264
|
+
}));
|
|
2265
|
+
break;
|
|
2266
|
+
}
|
|
1882
2267
|
|
|
1883
2268
|
send({
|
|
1884
2269
|
type: "assistant_tool_calls",
|
|
@@ -1887,22 +2272,22 @@ export function buildSseStream(
|
|
|
1887
2272
|
});
|
|
1888
2273
|
send({ type: "tool_start", calls: toolCalls.map((t) => t.function.name) });
|
|
1889
2274
|
for (const tc of toolCalls) {
|
|
1890
|
-
const toolResult = await executeToolOnServer(
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
2275
|
+
const toolResult = await executeToolOnServer(
|
|
2276
|
+
tc,
|
|
2277
|
+
serverBase,
|
|
2278
|
+
authToken,
|
|
2279
|
+
buildLoopToolExecutionOptions({
|
|
2280
|
+
agentConfig,
|
|
2281
|
+
messages,
|
|
2282
|
+
runtimePolicy,
|
|
2283
|
+
runtimeState,
|
|
2284
|
+
userId,
|
|
2285
|
+
dialogId,
|
|
2286
|
+
currentSpaceId,
|
|
2287
|
+
userInput,
|
|
2288
|
+
runtimeContext,
|
|
2289
|
+
}),
|
|
2290
|
+
);
|
|
1906
2291
|
messages.push({
|
|
1907
2292
|
role: "tool",
|
|
1908
2293
|
tool_call_id: tc.id,
|
|
@@ -1916,46 +2301,46 @@ export function buildSseStream(
|
|
|
1916
2301
|
});
|
|
1917
2302
|
const directCompletion = buildDirectCompletionFromToolResult(tc.function.name, toolResult);
|
|
1918
2303
|
if (directCompletion) {
|
|
1919
|
-
messages.push({
|
|
1920
|
-
role: "assistant",
|
|
1921
|
-
content: directCompletion,
|
|
1922
|
-
});
|
|
1923
|
-
send({ type: "text", content: directCompletion });
|
|
1924
|
-
send({
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
});
|
|
1932
|
-
controller.close();
|
|
1933
|
-
return;
|
|
1934
|
-
}
|
|
2304
|
+
messages.push({
|
|
2305
|
+
role: "assistant",
|
|
2306
|
+
content: directCompletion,
|
|
2307
|
+
});
|
|
2308
|
+
send({ type: "text", content: directCompletion });
|
|
2309
|
+
send(buildStreamDoneEvent({
|
|
2310
|
+
usage: lastUsage,
|
|
2311
|
+
provider: lastResolvedProvider,
|
|
2312
|
+
model: lastResolvedModel,
|
|
2313
|
+
inputPrice: lastResolvedInputPrice,
|
|
2314
|
+
outputPrice: lastResolvedOutputPrice,
|
|
2315
|
+
providerCallIds,
|
|
2316
|
+
}));
|
|
2317
|
+
controller.close();
|
|
2318
|
+
return;
|
|
2319
|
+
}
|
|
1935
2320
|
if (["runStreamingAgent", "streamParallelAgents"].includes(canonicalizeToolName(tc.function.name))) {
|
|
1936
2321
|
const parsed = parseToolResult(toolResult);
|
|
1937
2322
|
if (canonicalizeToolName(tc.function.name) === "streamParallelAgents") {
|
|
1938
2323
|
appendParallelBranchMessages(messages, parsed);
|
|
1939
2324
|
}
|
|
1940
|
-
if (parsed?.handoff && typeof parsed.content === "string" && parsed.content.trim()) {
|
|
1941
|
-
send({ type: "text", content: parsed.content });
|
|
1942
|
-
send({
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
});
|
|
1956
|
-
controller.close();
|
|
1957
|
-
return;
|
|
1958
|
-
}
|
|
2325
|
+
if (parsed?.handoff && typeof parsed.content === "string" && parsed.content.trim()) {
|
|
2326
|
+
send({ type: "text", content: parsed.content });
|
|
2327
|
+
send(buildStreamDoneEvent({
|
|
2328
|
+
usage: parsed.usage ?? lastUsage,
|
|
2329
|
+
provider: parsed.provider || lastResolvedProvider,
|
|
2330
|
+
model: parsed.model || lastResolvedModel,
|
|
2331
|
+
inputPrice:
|
|
2332
|
+
typeof parsed.inputPrice === "number"
|
|
2333
|
+
? parsed.inputPrice
|
|
2334
|
+
: lastResolvedInputPrice,
|
|
2335
|
+
outputPrice:
|
|
2336
|
+
typeof parsed.outputPrice === "number"
|
|
2337
|
+
? parsed.outputPrice
|
|
2338
|
+
: lastResolvedOutputPrice,
|
|
2339
|
+
providerCallIds,
|
|
2340
|
+
}));
|
|
2341
|
+
controller.close();
|
|
2342
|
+
return;
|
|
2343
|
+
}
|
|
1959
2344
|
}
|
|
1960
2345
|
// 如果是创建文档类工具,解析结果并推送 doc_created 事件让前端感知
|
|
1961
2346
|
if (["createDoc", "createSkillDoc", "importSkill"].includes(canonicalizeToolName(tc.function.name))) {
|
|
@@ -1966,13 +2351,16 @@ export function buildSseStream(
|
|
|
1966
2351
|
}
|
|
1967
2352
|
} catch { /* 忽略解析失败 */ }
|
|
1968
2353
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
2354
|
+
}
|
|
2355
|
+
send({ type: "tool_end" });
|
|
2356
|
+
}
|
|
2357
|
+
controller.close();
|
|
2358
|
+
};
|
|
2359
|
+
return await dispatchModelStreamingLoop();
|
|
2360
|
+
} catch (e: any) {
|
|
2361
|
+
controller.enqueue(
|
|
2362
|
+
encoder.encode(`data: ${JSON.stringify({ type: "error", message: e.message ?? "Unexpected error" })}\n\n`)
|
|
2363
|
+
);
|
|
1976
2364
|
}
|
|
1977
2365
|
controller.close();
|
|
1978
2366
|
},
|
|
@@ -2028,8 +2416,15 @@ async function consumeSseStream(
|
|
|
2028
2416
|
let chunk: any;
|
|
2029
2417
|
try { chunk = JSON.parse(raw); } catch { continue; }
|
|
2030
2418
|
|
|
2031
|
-
const delta = chunk.choices?.[0]?.delta;
|
|
2032
|
-
|
|
2419
|
+
const delta = chunk.choices?.[0]?.delta;
|
|
2420
|
+
const chunkAuditUsage = buildProviderAuditUsageMetadata(null, chunk);
|
|
2421
|
+
if (!delta) {
|
|
2422
|
+
lastUsage = mergeUsageSnapshot(
|
|
2423
|
+
lastUsage,
|
|
2424
|
+
mergeUsageSnapshot(chunk.usage, chunkAuditUsage),
|
|
2425
|
+
) ?? null;
|
|
2426
|
+
continue;
|
|
2427
|
+
}
|
|
2033
2428
|
|
|
2034
2429
|
if (typeof delta.content === "string" && delta.content) {
|
|
2035
2430
|
appendTextPart(assistantContentParts, delta.content);
|
|
@@ -2064,8 +2459,11 @@ async function consumeSseStream(
|
|
|
2064
2459
|
}
|
|
2065
2460
|
}
|
|
2066
2461
|
|
|
2067
|
-
|
|
2068
|
-
|
|
2462
|
+
lastUsage = mergeUsageSnapshot(
|
|
2463
|
+
lastUsage,
|
|
2464
|
+
mergeUsageSnapshot(chunk.usage, chunkAuditUsage),
|
|
2465
|
+
) ?? null;
|
|
2466
|
+
}
|
|
2069
2467
|
}
|
|
2070
2468
|
|
|
2071
2469
|
const assistantContent = finalizeAssistantContent(assistantContentParts);
|
|
@@ -2115,7 +2513,15 @@ async function consumeResponsesSseStream(
|
|
|
2115
2513
|
continue;
|
|
2116
2514
|
}
|
|
2117
2515
|
|
|
2118
|
-
|
|
2516
|
+
const eventAuditUsage = buildProviderAuditUsageMetadata(null, event);
|
|
2517
|
+
const eventUsage =
|
|
2518
|
+
event?.type === "response.completed" && event.response?.usage
|
|
2519
|
+
? undefined
|
|
2520
|
+
: event?.usage;
|
|
2521
|
+
lastUsage = mergeUsageSnapshot(
|
|
2522
|
+
lastUsage,
|
|
2523
|
+
mergeUsageSnapshot(eventUsage, eventAuditUsage),
|
|
2524
|
+
) ?? null;
|
|
2119
2525
|
|
|
2120
2526
|
switch (event?.type) {
|
|
2121
2527
|
case "response.output_text.delta":
|
|
@@ -2183,10 +2589,16 @@ async function consumeResponsesSseStream(
|
|
|
2183
2589
|
acc.set(key, current);
|
|
2184
2590
|
break;
|
|
2185
2591
|
}
|
|
2186
|
-
case "response.completed":
|
|
2187
|
-
completedResponse = event.response ?? null;
|
|
2188
|
-
|
|
2189
|
-
|
|
2592
|
+
case "response.completed":
|
|
2593
|
+
completedResponse = event.response ?? null;
|
|
2594
|
+
lastUsage = mergeUsageSnapshot(
|
|
2595
|
+
lastUsage,
|
|
2596
|
+
mergeUsageSnapshot(
|
|
2597
|
+
event.response?.usage,
|
|
2598
|
+
buildProviderAuditUsageMetadata(null, event.response),
|
|
2599
|
+
),
|
|
2600
|
+
) ?? null;
|
|
2601
|
+
break;
|
|
2190
2602
|
default:
|
|
2191
2603
|
break;
|
|
2192
2604
|
}
|