nolo-cli 0.1.29 → 0.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-runtime/agentRecordConfig.ts +0 -2
- package/agent-runtime/hostAdapter.ts +0 -1
- package/agent-runtime/hostRuntimeCapabilities.ts +7 -0
- package/agent-runtime/hostRuntimeConfig.ts +86 -0
- package/agent-runtime/index.ts +13 -0
- package/agent-runtime/localToolPolicy.ts +13 -6
- package/agent-runtime/localWorkspaceTools.ts +333 -30
- package/agent-runtime/platformChatProvider.ts +4 -1
- package/agent-runtime/runtimeToolPolicy.ts +32 -47
- package/agent-runtime/shellCommandPolicy.ts +117 -0
- package/agent-runtime/toolGate.ts +38 -0
- package/agentCreateCustomCommands.ts +9 -4
- package/agentDialogsCommands.ts +4 -3
- package/agentDoctorCommands.ts +3 -3
- package/agentListCommands.ts +3 -3
- package/agentMachineCommands.ts +6 -6
- package/agentPullCommand.ts +4 -12
- package/agentRecordCommands.ts +5 -3
- package/agentRecordHelpers.ts +42 -23
- package/agentRunCommand.ts +2 -6
- package/agentRunParsing.ts +18 -5
- package/agentRuntimeLocal.ts +10 -0
- package/agentUnpublishCommands.ts +3 -2
- package/ai/agent/agentRunDialogLineage.ts +56 -0
- package/ai/agent/agentSlice.ts +45 -10
- package/ai/agent/avatarUtils.ts +1 -1
- package/ai/agent/buildSystemPrompt.ts +1 -2
- package/ai/agent/cliExecutor.ts +330 -19
- package/ai/agent/createAgentSchema.ts +22 -0
- package/ai/agent/hooks/fetchPublicAgents.ts +14 -39
- package/ai/agent/hooks/usePublicAgents.ts +90 -192
- package/ai/agent/publicAgentCatalog.ts +359 -0
- package/ai/agent/publicAgentIdentity.ts +76 -0
- package/ai/agent/server/fetchPublicAgents.ts +21 -46
- package/ai/agent/serverOrigin.ts +7 -0
- package/ai/agent/streamAgentChatTurn.ts +23 -21
- package/ai/agent/streamAgentChatTurnUtils.ts +292 -6
- package/ai/agent/types.ts +2 -0
- package/ai/agent/web/agentDisplayUtils.ts +171 -0
- package/ai/agent/web/useAgentModelAvatarComponent.ts +32 -0
- package/ai/ai.locale.ts +8 -0
- package/ai/chat/sendOpenAICompletionsRequest.native.ts +15 -0
- package/ai/chat/sendOpenAICompletionsRequest.ts +93 -1
- package/ai/chat/sendOpenAIResponseRequest.ts +86 -9
- package/ai/chat/updateTotalUsage.ts +7 -0
- package/ai/llm/deepinfra.ts +30 -15
- package/ai/llm/mistral.ts +3 -4
- package/ai/llm/providers.ts +2 -0
- package/ai/llm/types.ts +15 -0
- package/ai/memory/capture.ts +3 -3
- package/ai/memory/consolidate.ts +2 -2
- package/ai/memory/delete.ts +4 -3
- package/ai/memory/query.ts +3 -3
- package/ai/memory/remember.ts +2 -2
- package/ai/memory/store.ts +3 -3
- package/ai/memory/storeShared.ts +3 -2
- package/ai/policy/commercialMultiplier.ts +16 -0
- package/ai/token/billingAdminAuditEvent.ts +68 -0
- package/ai/token/billingAdminAuditEventWriter.ts +41 -0
- package/ai/token/billingAnomaly.ts +90 -0
- package/ai/token/billingAnomalyLifecycle.ts +54 -0
- package/ai/token/billingAnomalyLifecycleWriter.ts +44 -0
- package/ai/token/billingAnomalyWriter.ts +41 -0
- package/ai/token/calculatePrice.ts +3 -2
- package/ai/token/deepinfraReconciliation.ts +153 -0
- package/ai/token/deepinfraRequestIdQuery.ts +92 -0
- package/ai/token/externalToolCost.ts +54 -41
- package/ai/token/missingUsageEstimate.ts +12 -3
- package/ai/token/normalizeUsage.ts +45 -5
- package/ai/token/openaiReconciliation.ts +188 -0
- package/ai/token/providerBillableEvent.ts +84 -0
- package/ai/token/providerBillableEventWriter.ts +36 -0
- package/ai/token/providerBillingAnomalyDrilldown.ts +308 -0
- package/ai/token/providerBillingDrilldown.ts +361 -0
- package/ai/token/providerBillingHealthReport.ts +366 -0
- package/ai/token/providerCall.ts +144 -0
- package/ai/token/providerCallSweeper.ts +168 -0
- package/ai/token/providerCallWriter.ts +33 -0
- package/ai/token/providerCredential.ts +89 -0
- package/ai/token/providerCredentialAnomaly.ts +154 -0
- package/ai/token/providerCredentialLifecycle.ts +59 -0
- package/ai/token/providerCredentialLifecycleWriter.ts +44 -0
- package/ai/token/providerCredentialRegistry.ts +83 -0
- package/ai/token/providerCredentialRegistryCommand.ts +97 -0
- package/ai/token/providerCredentialRegistryList.ts +124 -0
- package/ai/token/providerCredentialRegistryResolver.ts +150 -0
- package/ai/token/providerCredentialRegistryWriter.ts +41 -0
- package/ai/token/providerCredentialRotationCommand.ts +102 -0
- package/ai/token/providerCredentialRuntime.ts +56 -0
- package/ai/token/providerDispatchIntent.ts +67 -0
- package/ai/token/providerDispatchIntentWriter.ts +36 -0
- package/ai/token/providerGateway.ts +260 -0
- package/ai/token/providerReconciliation.ts +148 -0
- package/ai/token/providerReconciliationLocal.ts +97 -0
- package/ai/token/providerReconciliationRunner.ts +165 -0
- package/ai/token/providerReconciliationWriter.ts +41 -0
- package/ai/token/ratingResult.ts +202 -0
- package/ai/token/ratingResultWriter.ts +33 -0
- package/ai/token/serverDialogProjection.ts +5 -3
- package/ai/token/serverTokenWriter.ts +11 -3
- package/ai/token/types.ts +10 -0
- package/ai/tools/agent/callAgentTool.ts +3 -4
- package/ai/tools/agent/presets/appBuilderPreset.ts +5 -7
- package/ai/tools/agent/runStreamingAgentTool.ts +1 -2
- package/ai/tools/agent/streamParallelAgentsTool.ts +2 -3
- package/ai/tools/readXPostTool.ts +1 -5
- package/app/admin/adminPages.ts +9 -0
- package/app/i18n/i18n.config.ts +5 -0
- package/app/i18n/translations/pricing.locale.ts +397 -0
- package/app/utils/desktopAgentRuntimeStatusClient.ts +5 -4
- package/app/utils/desktopAgentRuntimeTurnClient.ts +4 -1
- package/app/utils/imageUtils.ts +64 -34
- package/auth/adminPermissions.ts +18 -0
- package/auth/authSlice.ts +26 -12
- package/auth/hooks/useFetchUsers.ts +3 -0
- package/auth/routes.ts +46 -0
- package/auth/server/accessActivity.ts +4 -3
- package/auth/server/adminPermissions.ts +43 -0
- package/auth/server/adminUsageReport.ts +375 -0
- package/auth/server/billingAnomalies.ts +235 -0
- package/auth/server/billingUsageReport.ts +41 -2
- package/auth/server/creatorEarningCreditConversion.ts +10 -2
- package/auth/server/deduct.ts +14 -7
- package/auth/server/delete.ts +10 -2
- package/auth/server/disable.ts +4 -3
- package/auth/server/emailAutomation.ts +7 -5
- package/auth/server/emailDbConfig.ts +4 -2
- package/auth/server/emailDelivery.ts +24 -20
- package/auth/server/emailDeliveryGuards.ts +10 -7
- package/auth/server/emailPreferences.ts +6 -4
- package/auth/server/emailReport.ts +6 -4
- package/auth/server/emailRuntimeConfig.ts +3 -3
- package/auth/server/emailScenarioNotifications.ts +9 -8
- package/auth/server/enable.ts +4 -3
- package/auth/server/getRechargeHistory.ts +3 -2
- package/auth/server/getUser.ts +3 -2
- package/auth/server/gptProAccess.ts +44 -0
- package/auth/server/inviteReward.ts +10 -7
- package/auth/server/listusers.ts +6 -4
- package/auth/server/login.ts +2 -2
- package/auth/server/productEntitlements.ts +7 -4
- package/auth/server/productPurchase.ts +10 -2
- package/auth/server/providerBillingDrilldown.ts +47 -0
- package/auth/server/providerBillingHealth.ts +71 -0
- package/auth/server/providerCredentials.ts +136 -0
- package/auth/server/recharge.ts +14 -8
- package/auth/server/revokeSessions.ts +4 -3
- package/auth/server/route.ts +77 -0
- package/auth/server/sendEmail.ts +5 -4
- package/auth/server/signup.ts +10 -3
- package/auth/server/token.ts +53 -55
- package/auth/server/tokenUsageBilling.ts +18 -7
- package/auth/server/usageManagementAccess.ts +43 -0
- package/auth/server/usageReport.ts +59 -0
- package/auth/types.ts +12 -0
- package/auth/utils.ts +24 -22
- package/authCommands.ts +36 -2
- package/buildPublish.ts +3 -1
- package/buildPublishArtifactAssembly.ts +62 -1
- package/buildPublishImportAnalysis.ts +21 -16
- package/chat/dialog/dialogLaunchScope.ts +32 -0
- package/chat/dialog/objectAssistantRegistry.ts +2 -2
- package/chat/dialog/useCreateDialog.ts +1 -1
- package/chat/hooks/useChatInput.ts +41 -10
- package/chat/messages/messageSlice.ts +5 -1
- package/chat/messages/pendingAttachmentParts.ts +28 -2
- package/chat/messages/sendFirstMessage.ts +76 -79
- package/chat/messages/types.ts +9 -0
- package/chat/messages/web/streamingMarkdownModel.ts +41 -0
- package/chat/messages/web/useStreamingReveal.ts +91 -0
- package/chat/web/messageInputAgentUi.ts +94 -6
- package/cliEnvHelpers.ts +68 -13
- package/cliRuntimeDoctorReport.ts +193 -0
- package/client/agentConfigResolver.test.ts +0 -2
- package/client/agentRun.test.ts +171 -10
- package/client/agentRun.ts +44 -637
- package/client/agentRunInput.ts +10 -0
- package/client/agentRunLocalExecutor.ts +179 -0
- package/client/agentRunServerTransport.ts +394 -0
- package/client/agentRunTaskRunRecorder.ts +176 -0
- package/client/localRuntimeAdapter.test.ts +236 -9
- package/client/localRuntimeAdapter.ts +221 -23
- package/client/localToolPolicy.test.ts +28 -4
- package/connector-experimental/daemonLauncher.ts +38 -4
- package/connectorRunArtifact.ts +34 -10
- package/connectorWebSocketTarget.ts +40 -15
- package/core/builtinAgents.ts +155 -11
- package/create/space/contentLabels.ts +1 -1
- package/create/space/contentTypeMeta.ts +3 -2
- package/create/space/sidebarVisibleTypes.ts +27 -0
- package/create/space/space.locale.ts +76 -4
- package/database/actions/agentReadResolution.ts +2 -8
- package/database/actions/read.ts +11 -9
- package/database/actions/readAndWait.ts +10 -5
- package/database/server/agentDelegation.ts +3 -2
- package/database/server/authorityStoreConformance.ts +209 -0
- package/database/server/authorityStoreTypes.ts +31 -0
- package/database/server/coreDataProxy.ts +1 -1
- package/database/server/dataHandlers.ts +13 -5
- package/database/server/db.ts +15 -34
- package/database/server/delete.ts +88 -71
- package/database/server/emailRepository.ts +11 -9
- package/database/server/fileService.ts +2 -1
- package/database/server/legacyServerDb.ts +58 -0
- package/database/server/levelAuthorityStore.ts +75 -0
- package/database/server/memoryAuthorityStore.ts +133 -0
- package/database/server/patch.ts +13 -12
- package/database/server/query.ts +3 -2
- package/database/server/read.ts +33 -30
- package/database/server/resourceAccess.ts +7 -5
- package/database/server/serverStoreFactory.ts +124 -0
- package/database/server/spaceMemberAuthority.ts +3 -2
- package/database/server/storeBatchCompat.ts +37 -0
- package/database/server/testAuthorityStore.ts +76 -0
- package/database/server/write.ts +29 -27
- package/dialogReadCommands.ts +2 -1
- package/dialogStatusCommands.ts +2 -1
- package/integrations/anthropic/anthropicModels.ts +12 -12
- package/integrations/deepseek/models.ts +67 -67
- package/integrations/google/models.ts +111 -53
- package/integrations/openai/models.ts +22 -22
- package/integrations/xai/models.ts +1 -1
- package/localRuntimeDb.ts +39 -2
- package/machineCommandPrompts.ts +2 -0
- package/machineCommands.ts +193 -62
- package/machineStatusCommands.ts +4 -12
- package/machineWsRunDispatch.ts +80 -15
- package/machineWsSession.ts +46 -2
- package/noloReadBridgePrompt.ts +16 -0
- package/package.json +114 -21
- package/pageCreateCommands.ts +2 -2
- package/pageDeleteCommands.ts +3 -3
- package/pageReadCommands.ts +3 -3
- package/pageUpdateCommands.ts +3 -3
- package/render/layout/mainLayoutViewMode.ts +25 -0
- package/render/page/server/createPage.ts +3 -1
- package/render/page/server/handleCreatePage.ts +2 -11
- package/runtimeDoctorCommands.ts +18 -69
- package/server/api/methods.ts +34 -12
- package/server/api/tableHandlers.ts +6 -3
- package/server/authenticateToken.ts +47 -2
- package/server/billingLedgerRoutes.ts +15 -0
- package/server/buildManifest.ts +54 -0
- package/server/coreReadiness.ts +34 -25
- package/server/coreRuntime.ts +15 -10
- package/server/handlers/activityStatsHandler.ts +5 -2
- package/server/handlers/agentEmailRegistrationE2EHandler.ts +25 -23
- package/server/handlers/agentRun/agentLookup.ts +1 -7
- package/server/handlers/agentRun/autonomousRuntime.ts +11 -10
- package/server/handlers/agentRun/builtinAgents.ts +12 -88
- package/server/handlers/agentRun/continueDialogContext.ts +15 -3
- package/server/handlers/agentRun/{inheritedDialogPrompt.ts → conversationReference.ts} +3 -3
- package/server/handlers/agentRun/dialogLookup.ts +4 -3
- package/server/handlers/agentRun/index.ts +864 -404
- package/server/handlers/agentRun/localRuntimeBootstrap.ts +17 -1
- package/server/handlers/agentRun/loop.ts +920 -508
- package/server/handlers/agentRun/machineConnector.ts +56 -8
- package/server/handlers/agentRun/machineRunAudit.ts +3 -2
- package/server/handlers/agentRun/modelUsageToolHandlers.ts +13 -10
- package/server/handlers/agentRun/requestContext.ts +12 -8
- package/server/handlers/agentRun/runtimeExecutionContext.ts +15 -3
- package/server/handlers/agentRun/runtimePreparation.ts +26 -24
- package/server/handlers/agentRun/runtimeRouting.ts +25 -40
- package/server/handlers/agentRun/runtimeSystemMessages.ts +65 -0
- package/server/handlers/agentRun/saveDialog.ts +97 -87
- package/server/handlers/agentRun/taskRunToolHandler.ts +9 -7
- package/server/handlers/agentRun/toolExecutor.ts +42 -78
- package/server/handlers/agentRun/types.ts +2 -1
- package/server/handlers/appDeployStatusStore.ts +17 -10
- package/server/handlers/appDomainHandler.ts +21 -15
- package/server/handlers/appLegacyInfraCleanup.ts +5 -2
- package/server/handlers/appSandboxHandler.ts +29 -8
- package/server/handlers/appSpaceAccess.ts +15 -8
- package/server/handlers/chatHandler.ts +22 -2
- package/server/handlers/chatUpstreamRetry.ts +225 -2
- package/server/handlers/connector/connectorConnectionRegistry.ts +55 -7
- package/server/handlers/connector/connectorWebSocket.ts +14 -10
- package/server/handlers/desktopAgentRuntimeAdapter.ts +4 -4
- package/server/handlers/desktopAgentRuntimeHostCapabilities.ts +25 -0
- package/server/handlers/desktopAgentRuntimeReadiness.ts +62 -0
- package/server/handlers/desktopAgentRuntimeStatusHandler.ts +38 -30
- package/server/handlers/desktopAgentRuntimeTurnHandler.ts +7 -3
- package/server/handlers/desktopAgentRuntimeTurnService.ts +39 -45
- package/server/handlers/desktopLlamaRuntimeHandler.ts +85 -51
- package/server/handlers/desktopUpdaterHandler.ts +132 -24
- package/server/handlers/favoriteHandlers.ts +8 -2
- package/server/handlers/getDialogBillingHandler.ts +4 -3
- package/server/handlers/getTransactionsHandler.ts +5 -2
- package/server/handlers/machines/machineBinding.ts +1 -0
- package/server/handlers/machines/machineHandlers.ts +0 -14
- package/server/handlers/machines/machineInstallAssets.ts +4 -2
- package/server/handlers/notificationEmitter.ts +5 -3
- package/server/handlers/notificationsHandler.ts +5 -2
- package/server/handlers/providerCallsRecentHandler.ts +234 -0
- package/server/handlers/providerReconciliationRunHandler.ts +180 -0
- package/server/handlers/providerRequestIdsHandler.ts +105 -0
- package/server/handlers/tableAccess.ts +6 -2
- package/server/handlers/tableToolHandlers.ts +28 -14
- package/server/handlers/userSecretsHandler.ts +17 -6
- package/server/handlers/versionHandler.ts +9 -4
- package/server/handlers/versionStore.ts +18 -10
- package/server/html/ssrPreload.ts +5 -3
- package/server/payments/crypto/cryptoUsdcBasePaymentProvider.ts +11 -8
- package/server/payments/crypto/cryptoUsdcBaseScanner.ts +12 -7
- package/server/payments/crypto/cryptoUsdtTronPaymentProvider.ts +11 -8
- package/server/payments/crypto/cryptoUsdtTronScanner.ts +9 -7
- package/server/payments/waffo/waffoPaymentProvider.ts +12 -9
- package/server/runtimeRole.ts +15 -0
- package/server/scheduler/scheduledTaskRuntime.ts +4 -2
- package/server/scheduler/schedulerService.ts +2 -2
- package/server/taskRunBridgeRoutes.ts +8 -5
- package/share/server/fetchCommunityShares.ts +1 -1
- package/share/server/helpers.ts +19 -17
- package/share/server/importShare.ts +9 -13
- package/share/server/listCommunityShares.ts +4 -4
- package/share/server/purchaseDoc.ts +8 -16
- package/share/server/readCommunityShareCover.ts +3 -2
- package/share/server/readSharedTable.ts +14 -13
- package/share/server/tableReplication.ts +42 -39
- package/spaceAttachCommands.ts +135 -0
- package/spaceCategoryCommands.ts +6 -6
- package/spaceCommands.ts +3 -3
- package/spaceDeleteCommands.ts +2 -2
- package/spaceInternalCommandEntries.ts +2 -0
- package/spaceReadCommands.ts +3 -3
- package/tableMetaCommands.ts +2 -2
- package/taskRunCommand.ts +11 -0
- package/ai/agent/runtimeServerBase.ts +0 -37
- package/server/handlers/desktopAgentRuntimeHostFacts.ts +0 -40
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export type AgentRunDialogLineageInput = {
|
|
2
|
+
continueDialogId?: string | null;
|
|
3
|
+
inheritedFromDialogKey?: string | null;
|
|
4
|
+
parentDialogId?: string | null;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type NormalizedAgentRunDialogLineage = {
|
|
8
|
+
continueDialogId?: string;
|
|
9
|
+
inheritedFromDialogKey?: string;
|
|
10
|
+
parentDialogId?: string;
|
|
11
|
+
hasAuthoritativeContinueDialog: boolean;
|
|
12
|
+
hasConflictingLineage: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function pickOptionalString(value: unknown) {
|
|
16
|
+
if (typeof value !== "string") return undefined;
|
|
17
|
+
const normalized = value.trim();
|
|
18
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function hasAuthoritativeContinueDialogId(value: unknown) {
|
|
22
|
+
return pickOptionalString(value) !== undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function normalizeAgentRunDialogLineage(
|
|
26
|
+
input: AgentRunDialogLineageInput
|
|
27
|
+
): NormalizedAgentRunDialogLineage {
|
|
28
|
+
const continueDialogId = pickOptionalString(input.continueDialogId);
|
|
29
|
+
const inheritedFromDialogKey = pickOptionalString(input.inheritedFromDialogKey);
|
|
30
|
+
const parentDialogId = pickOptionalString(input.parentDialogId);
|
|
31
|
+
const hasAuthoritativeContinueDialog = hasAuthoritativeContinueDialogId(continueDialogId);
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
continueDialogId,
|
|
35
|
+
inheritedFromDialogKey: hasAuthoritativeContinueDialog ? undefined : inheritedFromDialogKey,
|
|
36
|
+
parentDialogId: hasAuthoritativeContinueDialog ? undefined : parentDialogId,
|
|
37
|
+
hasAuthoritativeContinueDialog,
|
|
38
|
+
hasConflictingLineage:
|
|
39
|
+
hasAuthoritativeContinueDialog && Boolean(inheritedFromDialogKey || parentDialogId),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function buildAgentRunDialogLineageFields(
|
|
44
|
+
input: AgentRunDialogLineageInput
|
|
45
|
+
): Pick<AgentRunDialogLineageInput, "continueDialogId" | "inheritedFromDialogKey" | "parentDialogId"> {
|
|
46
|
+
const normalized = normalizeAgentRunDialogLineage(input);
|
|
47
|
+
return {
|
|
48
|
+
...(hasAuthoritativeContinueDialogId(normalized.continueDialogId)
|
|
49
|
+
? { continueDialogId: normalized.continueDialogId }
|
|
50
|
+
: {}),
|
|
51
|
+
...(normalized.inheritedFromDialogKey
|
|
52
|
+
? { inheritedFromDialogKey: normalized.inheritedFromDialogKey }
|
|
53
|
+
: {}),
|
|
54
|
+
...(normalized.parentDialogId ? { parentDialogId: normalized.parentDialogId } : {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
package/ai/agent/agentSlice.ts
CHANGED
|
@@ -79,6 +79,24 @@ const normalizeAgentReferences = (references: any[]): ReferenceItem[] => {
|
|
|
79
79
|
}));
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
const isLocalProviderUrl = (value: unknown) => {
|
|
83
|
+
const normalized = typeof value === "string" ? value.trim() : "";
|
|
84
|
+
if (!normalized) return false;
|
|
85
|
+
try {
|
|
86
|
+
const hostname = new URL(normalized).hostname.toLowerCase();
|
|
87
|
+
return hostname === "127.0.0.1" || hostname === "localhost" || hostname === "::1";
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const shouldPersistMachineBinding = (args: {
|
|
94
|
+
apiSource?: string;
|
|
95
|
+
customProviderUrl?: unknown;
|
|
96
|
+
}) =>
|
|
97
|
+
args.apiSource === "cli" ||
|
|
98
|
+
(args.apiSource === "custom" && isLocalProviderUrl(args.customProviderUrl));
|
|
99
|
+
|
|
82
100
|
/**
|
|
83
101
|
* 创建场景:表单数据 -> 持久化数据(全量)
|
|
84
102
|
*/
|
|
@@ -104,7 +122,10 @@ const processAgentCreateForm = (formData: AgentFormData, userId: string) => {
|
|
|
104
122
|
};
|
|
105
123
|
|
|
106
124
|
delete result.machineId;
|
|
107
|
-
if (
|
|
125
|
+
if (machineId && shouldPersistMachineBinding({
|
|
126
|
+
apiSource: formData.apiSource,
|
|
127
|
+
customProviderUrl: formData.customProviderUrl,
|
|
128
|
+
})) {
|
|
108
129
|
const binding: AgentRuntimeBinding = {
|
|
109
130
|
...(result.runtimeBinding && typeof result.runtimeBinding === "object"
|
|
110
131
|
? result.runtimeBinding
|
|
@@ -165,14 +186,22 @@ const processAgentUpdateChanges = (
|
|
|
165
186
|
}
|
|
166
187
|
if ("machineId" in data) {
|
|
167
188
|
const machineId = String((data as any).machineId ?? "").trim();
|
|
168
|
-
|
|
169
|
-
// Determine effective
|
|
189
|
+
|
|
190
|
+
// Determine effective runtime source: prefer form data, fall back to previous agent config
|
|
170
191
|
const effectiveApiSource = data.apiSource ?? previousAgent?.apiSource;
|
|
171
|
-
|
|
192
|
+
const effectiveCustomProviderUrl =
|
|
193
|
+
data.customProviderUrl ?? previousAgent?.customProviderUrl;
|
|
194
|
+
|
|
172
195
|
if (machineId) {
|
|
173
|
-
// Persist runtimeBinding
|
|
174
|
-
// undefined
|
|
175
|
-
if (
|
|
196
|
+
// Persist runtimeBinding for CLI agents and localhost custom providers.
|
|
197
|
+
// undefined apiSource keeps backward compatibility for legacy partial updates.
|
|
198
|
+
if (
|
|
199
|
+
effectiveApiSource === undefined ||
|
|
200
|
+
shouldPersistMachineBinding({
|
|
201
|
+
apiSource: effectiveApiSource,
|
|
202
|
+
customProviderUrl: effectiveCustomProviderUrl,
|
|
203
|
+
})
|
|
204
|
+
) {
|
|
176
205
|
const binding: AgentRuntimeBinding = {
|
|
177
206
|
...((changes.runtimeBinding && typeof changes.runtimeBinding === "object")
|
|
178
207
|
? changes.runtimeBinding
|
|
@@ -182,10 +211,16 @@ const processAgentUpdateChanges = (
|
|
|
182
211
|
};
|
|
183
212
|
changes.runtimeBinding = binding;
|
|
184
213
|
}
|
|
185
|
-
// If apiSource is explicitly
|
|
214
|
+
// If apiSource is explicitly incompatible with machine binding, do not create binding
|
|
186
215
|
} else {
|
|
187
|
-
// CLEAR branch: clear runtimeBinding when
|
|
188
|
-
if (
|
|
216
|
+
// CLEAR branch: clear runtimeBinding when the effective runtime shape can be machine-bound.
|
|
217
|
+
if (
|
|
218
|
+
effectiveApiSource === undefined ||
|
|
219
|
+
shouldPersistMachineBinding({
|
|
220
|
+
apiSource: effectiveApiSource,
|
|
221
|
+
customProviderUrl: effectiveCustomProviderUrl,
|
|
222
|
+
})
|
|
223
|
+
) {
|
|
189
224
|
changes.runtimeBinding = null;
|
|
190
225
|
}
|
|
191
226
|
}
|
package/ai/agent/avatarUtils.ts
CHANGED
|
@@ -12,7 +12,7 @@ export function resolveAvatarUrl(
|
|
|
12
12
|
avatarFileId: string | undefined | null,
|
|
13
13
|
server: string | undefined | null
|
|
14
14
|
): string | null {
|
|
15
|
-
if (!avatarFileId) return null;
|
|
15
|
+
if (!avatarFileId || avatarFileId === "briefcase") return null;
|
|
16
16
|
if (avatarFileId.startsWith("http") || avatarFileId.startsWith("blob:")) {
|
|
17
17
|
return avatarFileId;
|
|
18
18
|
}
|
|
@@ -98,8 +98,7 @@ const AGENT_ORCHESTRATION_INSTRUCTIONS = `--- Agent 编排与协作 ---
|
|
|
98
98
|
你所在的系统支持多个子 Agent 和工作流工具,请把自己视为"总协调者":
|
|
99
99
|
|
|
100
100
|
1)子 Agent 协作
|
|
101
|
-
-
|
|
102
|
-
- 如果用户明确给了另一个可访问的 server origin(例如 Windows 机器的 Cloudflare 域名),可以在工具参数里传 serverBase 覆盖自动路由;不要臆造地址,也不要把普通 localhost 当成远端机器。
|
|
101
|
+
- 如果用户明确给了另一个可访问的 server origin(例如 Windows 机器的 Cloudflare 域名),可以在工具参数里显式传 serverBase 把调用发到那台 server;不要臆造地址,也不要把普通 localhost 当成远端机器。
|
|
103
102
|
- 当用户需要多视角分析或辩论时,你可以:
|
|
104
103
|
- 先用 callAgent 依次询问多个 Agent 对同一问题的看法;
|
|
105
104
|
- 在最后一条回复中,用你自己的话帮用户总结这些观点的异同,并给出综合结论。
|
package/ai/agent/cliExecutor.ts
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { exec, execSync, spawn } from "child_process";
|
|
17
|
-
import { randomUUID } from "node:crypto";
|
|
18
|
-
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
17
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
18
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
19
19
|
import { join } from "node:path";
|
|
20
20
|
import { tmpdir } from "node:os";
|
|
21
21
|
import { resolveLaunchableCodexCommand } from "../../connector-experimental/codexBinary";
|
|
@@ -50,6 +50,25 @@ export interface CliExecuteResult {
|
|
|
50
50
|
warnings?: string[];
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
type AgyDebugArtifact = {
|
|
54
|
+
dir: string;
|
|
55
|
+
promptHash: string;
|
|
56
|
+
promptBytes: number;
|
|
57
|
+
writeResult: (args: {
|
|
58
|
+
startedAt: string;
|
|
59
|
+
finishedAt: string;
|
|
60
|
+
elapsedMs: number;
|
|
61
|
+
cwd: string;
|
|
62
|
+
timeoutMs: number;
|
|
63
|
+
args: string[];
|
|
64
|
+
stdout: string;
|
|
65
|
+
stderr: string;
|
|
66
|
+
exitCode: number | null;
|
|
67
|
+
outcome: "succeeded" | "timed_out" | "spawn_error" | "failed";
|
|
68
|
+
errorMessage?: string;
|
|
69
|
+
}) => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
53
72
|
type CliSessionMessage = {
|
|
54
73
|
role: "user" | "assistant";
|
|
55
74
|
content: string;
|
|
@@ -171,6 +190,8 @@ function supportsNativeSystemPrompt(provider: CliProvider): boolean {
|
|
|
171
190
|
}
|
|
172
191
|
|
|
173
192
|
function supportsModel(provider: CliProvider): boolean {
|
|
193
|
+
// Antigravity CLI does not expose a model selection flag.
|
|
194
|
+
// Codex is handled separately so explicit opt-in can still pass --model through.
|
|
174
195
|
return provider !== "agy";
|
|
175
196
|
}
|
|
176
197
|
|
|
@@ -178,6 +199,13 @@ function supportsReasoningEffort(provider: CliProvider): boolean {
|
|
|
178
199
|
return provider === "claude" || provider === "copilot";
|
|
179
200
|
}
|
|
180
201
|
|
|
202
|
+
function shouldPassCodexModel(options: CliExecuteOptions): boolean {
|
|
203
|
+
return (options.env?.NOLO_CODEX_CLI_ALLOW_MODEL ?? process.env.NOLO_CODEX_CLI_ALLOW_MODEL) === "1";
|
|
204
|
+
}
|
|
205
|
+
function shouldPassClaudeModel(options: CliExecuteOptions): boolean {
|
|
206
|
+
return (options.env?.NOLO_CLAUDE_CLI_ALLOW_MODEL ?? process.env.NOLO_CLAUDE_CLI_ALLOW_MODEL) === "1";
|
|
207
|
+
}
|
|
208
|
+
|
|
181
209
|
function collectCliCapabilityWarnings(
|
|
182
210
|
provider: CliProvider,
|
|
183
211
|
options: CliExecuteOptions
|
|
@@ -189,7 +217,15 @@ function collectCliCapabilityWarnings(
|
|
|
189
217
|
warnings.push(`${label} does not support reasoning_effort; ignored.`);
|
|
190
218
|
}
|
|
191
219
|
|
|
192
|
-
if (options.model !== undefined && !
|
|
220
|
+
if (provider === "codex" && options.model !== undefined && !shouldPassCodexModel(options)) {
|
|
221
|
+
warnings.push(
|
|
222
|
+
"Codex CLI model selection is disabled by default because real Codex installs can reject --model with subscription/plan errors; set NOLO_CODEX_CLI_ALLOW_MODEL=1 to pass it through."
|
|
223
|
+
);
|
|
224
|
+
} else if (provider === "claude" && options.model !== undefined && !shouldPassClaudeModel(options)) {
|
|
225
|
+
warnings.push(
|
|
226
|
+
"Claude CLI model selection is disabled by default because current installs can reject --model; set NOLO_CLAUDE_CLI_ALLOW_MODEL=1 to pass it through."
|
|
227
|
+
);
|
|
228
|
+
} else if (options.model !== undefined && !supportsModel(provider)) {
|
|
193
229
|
warnings.push(`${label} does not support model selection; ignored.`);
|
|
194
230
|
}
|
|
195
231
|
|
|
@@ -218,16 +254,121 @@ function resolveCliExecution(
|
|
|
218
254
|
options: CliExecuteOptions
|
|
219
255
|
): { prompt: string; options: CliExecuteOptions; warnings: string[] } {
|
|
220
256
|
const warnings = collectCliCapabilityWarnings(provider, options);
|
|
221
|
-
|
|
222
|
-
|
|
257
|
+
const resolvedPrompt =
|
|
258
|
+
supportsNativeSystemPrompt(provider) || !options.systemPrompt?.trim()
|
|
259
|
+
? prompt
|
|
260
|
+
: buildCliPrompt(options.systemPrompt, prompt);
|
|
261
|
+
const resolvedOptions =
|
|
262
|
+
supportsNativeSystemPrompt(provider) || !options.systemPrompt?.trim()
|
|
263
|
+
? options
|
|
264
|
+
: {
|
|
265
|
+
...options,
|
|
266
|
+
systemPrompt: undefined,
|
|
267
|
+
};
|
|
268
|
+
const agyPrompt = provider === "agy" ? compactAgyPrompt(resolvedPrompt) : null;
|
|
269
|
+
return {
|
|
270
|
+
prompt: agyPrompt?.prompt ?? resolvedPrompt,
|
|
271
|
+
options: resolvedOptions,
|
|
272
|
+
warnings: [...warnings, ...(agyPrompt?.warnings ?? [])],
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const AGY_PRESERVED_PROMPT_BLOCK_HEADERS = [
|
|
277
|
+
"--- Nolo read-only CLI bridge ---",
|
|
278
|
+
"--- Nolo task-run tool bridge ---",
|
|
279
|
+
] as const;
|
|
280
|
+
const AGY_OPTIONAL_TASKRUN_GUIDANCE_HEADERS = [
|
|
281
|
+
"## TaskRun tool guidance (2026-05-17)",
|
|
282
|
+
"## TaskRun tool strictness (2026-05-17)",
|
|
283
|
+
"## TaskRun delegation boundary (2026-05-17)",
|
|
284
|
+
] as const;
|
|
285
|
+
|
|
286
|
+
function escapeRegExp(value: string) {
|
|
287
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function extractPromptBlock(source: string, header: string) {
|
|
291
|
+
const pattern = new RegExp(
|
|
292
|
+
`(?:^|\\n)(${escapeRegExp(header)}\\n[\\s\\S]*?)(?=\\n{2,}--- [^\\n]+ ---|\\n{2,}User task:|\\n{2,}--- User task ---|$)`,
|
|
293
|
+
);
|
|
294
|
+
const match = source.match(pattern);
|
|
295
|
+
if (!match) return null;
|
|
296
|
+
return {
|
|
297
|
+
block: match[1].trim(),
|
|
298
|
+
remaining: source.replace(pattern, "\n\n"),
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function stripMarkdownSection(source: string, header: string) {
|
|
303
|
+
const pattern = new RegExp(
|
|
304
|
+
`(?:^|\\n)${escapeRegExp(header)}\\n[\\s\\S]*?(?=\\n{2,}## [^\\n]+|\\n{2,}--- [^\\n]+ ---|\\n{2,}User task:|\\n{2,}--- User task ---|$)`,
|
|
305
|
+
);
|
|
306
|
+
return source.replace(pattern, "\n\n");
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function compactAgyPrompt(prompt: string): { prompt: string; warnings: string[] } {
|
|
310
|
+
let next = prompt;
|
|
311
|
+
let changed = false;
|
|
312
|
+
const preservedBlocks: string[] = [];
|
|
313
|
+
|
|
314
|
+
const stripBlock = (pattern: RegExp) => {
|
|
315
|
+
const updated = next.replace(pattern, "\n\n");
|
|
316
|
+
if (updated !== next) {
|
|
317
|
+
next = updated;
|
|
318
|
+
changed = true;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
for (const header of AGY_PRESERVED_PROMPT_BLOCK_HEADERS) {
|
|
323
|
+
const extracted = extractPromptBlock(next, header);
|
|
324
|
+
if (!extracted) continue;
|
|
325
|
+
next = extracted.remaining;
|
|
326
|
+
preservedBlocks.push(extracted.block);
|
|
327
|
+
changed = true;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Antigravity intermittently stalls on long runtime metadata tails. The
|
|
331
|
+
// connector already enforces permissions and owns dialog context, so trim
|
|
332
|
+
// these blocks before handing the prompt to agy.
|
|
333
|
+
stripBlock(/(?:^|\n)Conversation Reference:\n[\s\S]*?(?=\n{2,}--- Machine permission policy ---|\n{2,}--- User task ---|\n{2,}User task:|$)/);
|
|
334
|
+
stripBlock(/(?:^|\n)--- Machine permission policy ---\n[\s\S]*?(?=\n{2,}--- User task ---|\n{2,}User task:|$)/);
|
|
335
|
+
if (!preservedBlocks.some((block) => block.startsWith("--- Nolo task-run tool bridge ---"))) {
|
|
336
|
+
for (const header of AGY_OPTIONAL_TASKRUN_GUIDANCE_HEADERS) {
|
|
337
|
+
const updated = stripMarkdownSection(next, header);
|
|
338
|
+
if (updated !== next) {
|
|
339
|
+
next = updated;
|
|
340
|
+
changed = true;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
let normalized = next
|
|
346
|
+
.replace(/\n\n--- User task ---\n/g, "\n\nUser task:\n")
|
|
347
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
348
|
+
.trim();
|
|
349
|
+
if (preservedBlocks.length > 0) {
|
|
350
|
+
const reinjected = preservedBlocks.join("\n\n");
|
|
351
|
+
if (/^User task:\n/.test(normalized)) {
|
|
352
|
+
normalized = `${reinjected}\n\n${normalized}`;
|
|
353
|
+
} else if (/\n\nUser task:\n/.test(normalized)) {
|
|
354
|
+
normalized = normalized.replace(/\n\nUser task:\n/, `\n\n${reinjected}\n\nUser task:\n`);
|
|
355
|
+
} else {
|
|
356
|
+
normalized = `${normalized}\n\n${reinjected}`.trim();
|
|
357
|
+
}
|
|
223
358
|
}
|
|
359
|
+
if (normalized !== prompt) {
|
|
360
|
+
changed = true;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (!changed) {
|
|
364
|
+
return { prompt, warnings: [] };
|
|
365
|
+
}
|
|
366
|
+
|
|
224
367
|
return {
|
|
225
|
-
prompt:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
},
|
|
230
|
-
warnings,
|
|
368
|
+
prompt: normalized,
|
|
369
|
+
warnings: [
|
|
370
|
+
"Antigravity CLI prompt was compacted to avoid known timeout patterns in conversation-reference and machine-permission runtime blocks.",
|
|
371
|
+
],
|
|
231
372
|
};
|
|
232
373
|
}
|
|
233
374
|
|
|
@@ -416,7 +557,9 @@ function executeCodex(
|
|
|
416
557
|
"--cd",
|
|
417
558
|
cwd,
|
|
418
559
|
];
|
|
419
|
-
|
|
560
|
+
// Codex CLI accepts --model syntactically, but real desktop/subscription
|
|
561
|
+
// installs can fail with plan-gating errors. Keep default execution stable.
|
|
562
|
+
if (model && shouldPassCodexModel(options)) {
|
|
420
563
|
args.push("--model");
|
|
421
564
|
args.push(model);
|
|
422
565
|
}
|
|
@@ -496,8 +639,8 @@ function executeClaude(
|
|
|
496
639
|
} = options;
|
|
497
640
|
|
|
498
641
|
return new Promise((resolve, reject) => {
|
|
499
|
-
const args = ["-p", prompt];
|
|
500
|
-
if (model) {
|
|
642
|
+
const args = ["--add-dir", cwd, "-p", prompt];
|
|
643
|
+
if (model && shouldPassClaudeModel(options)) {
|
|
501
644
|
args.push("--model");
|
|
502
645
|
args.push(model);
|
|
503
646
|
}
|
|
@@ -564,9 +707,82 @@ function formatCliTimeout(timeoutMs: number) {
|
|
|
564
707
|
return `${Math.max(1, Math.ceil(timeoutMs / 1000))}s`;
|
|
565
708
|
}
|
|
566
709
|
|
|
567
|
-
function
|
|
710
|
+
function shortHash(value: string) {
|
|
711
|
+
return createHash("sha256").update(value).digest("hex").slice(0, 12);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function resolveAgyDebugDir(env?: Record<string, string | undefined>) {
|
|
715
|
+
const raw = env?.NOLO_AGY_DEBUG_DIR ?? process.env.NOLO_AGY_DEBUG_DIR ?? "";
|
|
716
|
+
return raw.trim();
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
function createAgyDebugArtifact(args: {
|
|
720
|
+
prompt: string;
|
|
721
|
+
attempt: number;
|
|
722
|
+
timeoutMs: number;
|
|
723
|
+
cwd: string;
|
|
724
|
+
env?: Record<string, string | undefined>;
|
|
725
|
+
}): AgyDebugArtifact | null {
|
|
726
|
+
const debugRoot = resolveAgyDebugDir(args.env);
|
|
727
|
+
if (!debugRoot) return null;
|
|
728
|
+
|
|
729
|
+
const promptHash = shortHash(args.prompt);
|
|
730
|
+
const promptBytes = Buffer.byteLength(args.prompt, "utf8");
|
|
731
|
+
const dir = join(debugRoot, `${Date.now()}-agy-${promptHash}-attempt-${args.attempt + 1}`);
|
|
732
|
+
mkdirSync(dir, { recursive: true });
|
|
733
|
+
writeFileSync(join(dir, "prompt.txt"), args.prompt, "utf8");
|
|
734
|
+
|
|
735
|
+
return {
|
|
736
|
+
dir,
|
|
737
|
+
promptHash,
|
|
738
|
+
promptBytes,
|
|
739
|
+
writeResult: (result) => {
|
|
740
|
+
writeFileSync(join(dir, "stdout.txt"), result.stdout, "utf8");
|
|
741
|
+
writeFileSync(join(dir, "stderr.txt"), result.stderr, "utf8");
|
|
742
|
+
writeFileSync(
|
|
743
|
+
join(dir, "meta.json"),
|
|
744
|
+
`${JSON.stringify({
|
|
745
|
+
promptHash,
|
|
746
|
+
promptBytes,
|
|
747
|
+
attempt: args.attempt + 1,
|
|
748
|
+
startedAt: result.startedAt,
|
|
749
|
+
finishedAt: result.finishedAt,
|
|
750
|
+
elapsedMs: result.elapsedMs,
|
|
751
|
+
cwd: result.cwd,
|
|
752
|
+
timeoutMs: result.timeoutMs,
|
|
753
|
+
args: result.args,
|
|
754
|
+
exitCode: result.exitCode,
|
|
755
|
+
outcome: result.outcome,
|
|
756
|
+
errorMessage: result.errorMessage ?? null,
|
|
757
|
+
stdoutBytes: Buffer.byteLength(result.stdout, "utf8"),
|
|
758
|
+
stderrBytes: Buffer.byteLength(result.stderr, "utf8"),
|
|
759
|
+
}, null, 2)}\n`,
|
|
760
|
+
"utf8"
|
|
761
|
+
);
|
|
762
|
+
},
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
function isAgyTimeoutError(error: unknown) {
|
|
767
|
+
return error instanceof Error && /Antigravity CLI timed out after \d+ms/.test(error.message);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
function resolveAgyTimeoutRetryCount(env?: Record<string, string | undefined>) {
|
|
771
|
+
const raw = env?.NOLO_AGY_TIMEOUT_RETRIES ?? process.env.NOLO_AGY_TIMEOUT_RETRIES ?? "2";
|
|
772
|
+
const parsed = Number.parseInt(raw, 10);
|
|
773
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 2;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
const AGY_PROCESS_TIMEOUT_BUFFER_MS = 10_000;
|
|
777
|
+
|
|
778
|
+
function isAgyUpstreamTimeoutText(stdout: string) {
|
|
779
|
+
return /^Error:\s+timed out waiting for response\b/i.test(stdout.trim());
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function executeAgyOnce(
|
|
568
783
|
prompt: string,
|
|
569
|
-
options: CliExecuteOptions
|
|
784
|
+
options: CliExecuteOptions,
|
|
785
|
+
attempt = 0
|
|
570
786
|
): Promise<CliExecuteResult> {
|
|
571
787
|
const {
|
|
572
788
|
timeout = 120_000,
|
|
@@ -576,6 +792,8 @@ function executeAgy(
|
|
|
576
792
|
|
|
577
793
|
return new Promise((resolve, reject) => {
|
|
578
794
|
const args = [
|
|
795
|
+
"--add-dir",
|
|
796
|
+
cwd,
|
|
579
797
|
"--print",
|
|
580
798
|
prompt,
|
|
581
799
|
"--print-timeout",
|
|
@@ -586,6 +804,14 @@ function executeAgy(
|
|
|
586
804
|
}
|
|
587
805
|
|
|
588
806
|
const start = Date.now();
|
|
807
|
+
const startedAt = new Date(start).toISOString();
|
|
808
|
+
const debugArtifact = createAgyDebugArtifact({
|
|
809
|
+
prompt,
|
|
810
|
+
attempt,
|
|
811
|
+
timeoutMs: timeout,
|
|
812
|
+
cwd,
|
|
813
|
+
env: options.env,
|
|
814
|
+
});
|
|
589
815
|
const proc = spawn("agy", args, {
|
|
590
816
|
cwd,
|
|
591
817
|
env: buildCliProcessEnv(options.env),
|
|
@@ -594,12 +820,40 @@ function executeAgy(
|
|
|
594
820
|
let stdout = "";
|
|
595
821
|
let stderr = "";
|
|
596
822
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
823
|
+
let timedOut = false;
|
|
824
|
+
|
|
825
|
+
const flushDebug = (result: {
|
|
826
|
+
exitCode: number | null;
|
|
827
|
+
outcome: "succeeded" | "timed_out" | "spawn_error" | "failed";
|
|
828
|
+
errorMessage?: string;
|
|
829
|
+
}) => {
|
|
830
|
+
debugArtifact?.writeResult({
|
|
831
|
+
startedAt,
|
|
832
|
+
finishedAt: new Date().toISOString(),
|
|
833
|
+
elapsedMs: Date.now() - start,
|
|
834
|
+
cwd,
|
|
835
|
+
timeoutMs: timeout,
|
|
836
|
+
args,
|
|
837
|
+
stdout,
|
|
838
|
+
stderr,
|
|
839
|
+
exitCode: result.exitCode,
|
|
840
|
+
outcome: result.outcome,
|
|
841
|
+
...(result.errorMessage ? { errorMessage: result.errorMessage } : {}),
|
|
842
|
+
});
|
|
843
|
+
};
|
|
597
844
|
|
|
598
845
|
if (timeout > 0) {
|
|
599
846
|
timer = setTimeout(() => {
|
|
847
|
+
timedOut = true;
|
|
600
848
|
proc.kill("SIGTERM");
|
|
601
|
-
|
|
602
|
-
|
|
849
|
+
const error = new Error(`Antigravity CLI timed out after ${timeout}ms`);
|
|
850
|
+
flushDebug({
|
|
851
|
+
exitCode: null,
|
|
852
|
+
outcome: "timed_out",
|
|
853
|
+
errorMessage: error.message,
|
|
854
|
+
});
|
|
855
|
+
reject(error);
|
|
856
|
+
}, timeout + AGY_PROCESS_TIMEOUT_BUFFER_MS);
|
|
603
857
|
}
|
|
604
858
|
|
|
605
859
|
proc.stdout.on("data", (data: Buffer) => {
|
|
@@ -612,11 +866,32 @@ function executeAgy(
|
|
|
612
866
|
|
|
613
867
|
proc.on("close", (code) => {
|
|
614
868
|
if (timer) clearTimeout(timer);
|
|
869
|
+
if (timedOut) return;
|
|
615
870
|
if (code !== 0 && code !== null) {
|
|
616
|
-
|
|
871
|
+
const error = new Error(`Antigravity CLI exited with code ${code}\nstderr: ${stderr}`);
|
|
872
|
+
flushDebug({
|
|
873
|
+
exitCode: code,
|
|
874
|
+
outcome: "failed",
|
|
875
|
+
errorMessage: error.message,
|
|
876
|
+
});
|
|
877
|
+
reject(error);
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
if (isAgyUpstreamTimeoutText(stdout)) {
|
|
881
|
+
const error = new Error(`Antigravity CLI timed out after ${timeout}ms`);
|
|
882
|
+
flushDebug({
|
|
883
|
+
exitCode: code,
|
|
884
|
+
outcome: "timed_out",
|
|
885
|
+
errorMessage: error.message,
|
|
886
|
+
});
|
|
887
|
+
reject(error);
|
|
617
888
|
return;
|
|
618
889
|
}
|
|
619
890
|
|
|
891
|
+
flushDebug({
|
|
892
|
+
exitCode: code,
|
|
893
|
+
outcome: "succeeded",
|
|
894
|
+
});
|
|
620
895
|
resolve({
|
|
621
896
|
text: stdout.trim(),
|
|
622
897
|
raw: stdout,
|
|
@@ -626,11 +901,47 @@ function executeAgy(
|
|
|
626
901
|
|
|
627
902
|
proc.on("error", (err) => {
|
|
628
903
|
if (timer) clearTimeout(timer);
|
|
904
|
+
flushDebug({
|
|
905
|
+
exitCode: null,
|
|
906
|
+
outcome: "spawn_error",
|
|
907
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
908
|
+
});
|
|
629
909
|
reject(err);
|
|
630
910
|
});
|
|
631
911
|
});
|
|
632
912
|
}
|
|
633
913
|
|
|
914
|
+
async function executeAgy(
|
|
915
|
+
prompt: string,
|
|
916
|
+
options: CliExecuteOptions
|
|
917
|
+
): Promise<CliExecuteResult> {
|
|
918
|
+
const maxRetries = resolveAgyTimeoutRetryCount(options.env);
|
|
919
|
+
let attempt = 0;
|
|
920
|
+
let lastError: unknown;
|
|
921
|
+
|
|
922
|
+
while (attempt <= maxRetries) {
|
|
923
|
+
try {
|
|
924
|
+
const result = await executeAgyOnce(prompt, options, attempt);
|
|
925
|
+
if (attempt === 0) return result;
|
|
926
|
+
return {
|
|
927
|
+
...result,
|
|
928
|
+
warnings: [
|
|
929
|
+
...(result.warnings ?? []),
|
|
930
|
+
`Antigravity CLI succeeded after ${attempt} timeout retr${attempt === 1 ? "y" : "ies"}.`,
|
|
931
|
+
],
|
|
932
|
+
};
|
|
933
|
+
} catch (error) {
|
|
934
|
+
lastError = error;
|
|
935
|
+
if (!isAgyTimeoutError(error) || attempt >= maxRetries) {
|
|
936
|
+
throw error;
|
|
937
|
+
}
|
|
938
|
+
attempt += 1;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
943
|
+
}
|
|
944
|
+
|
|
634
945
|
// ── 注册表(新增 CLI 工具时在这里加) ────────────────────────────────────────
|
|
635
946
|
|
|
636
947
|
const EXECUTORS: Record<
|
|
@@ -35,6 +35,17 @@ const referenceItemSchema = z
|
|
|
35
35
|
type: data.type === "page" ? "knowledge" : data.type,
|
|
36
36
|
}));
|
|
37
37
|
|
|
38
|
+
const isLocalProviderUrl = (value?: string | null) => {
|
|
39
|
+
const normalized = typeof value === "string" ? value.trim() : "";
|
|
40
|
+
if (!normalized) return false;
|
|
41
|
+
try {
|
|
42
|
+
const hostname = new URL(normalized).hostname.toLowerCase();
|
|
43
|
+
return hostname === "127.0.0.1" || hostname === "localhost" || hostname === "::1";
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
38
49
|
// --- 核心 schema ---
|
|
39
50
|
export const getCreateAgentSchema = (t: TFunction) =>
|
|
40
51
|
z
|
|
@@ -222,6 +233,17 @@ export const getCreateAgentSchema = (t: TFunction) =>
|
|
|
222
233
|
message: t("validation.modelRequired"),
|
|
223
234
|
path: ["model"],
|
|
224
235
|
}
|
|
236
|
+
)
|
|
237
|
+
.refine(
|
|
238
|
+
(data) => {
|
|
239
|
+
if (!data.machineId?.trim()) return true;
|
|
240
|
+
if (data.apiSource === "cli") return true;
|
|
241
|
+
return data.apiSource === "custom" && isLocalProviderUrl(data.customProviderUrl);
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
message: t("validation.machineBindingRequiresCliOrLocalCustom"),
|
|
245
|
+
path: ["machineId"],
|
|
246
|
+
}
|
|
225
247
|
);
|
|
226
248
|
|
|
227
249
|
export type FormData = z.infer<ReturnType<typeof getCreateAgentSchema>>;
|