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.
Files changed (308) hide show
  1. package/agent-runtime/agentRecordConfig.ts +0 -2
  2. package/agent-runtime/hostAdapter.ts +0 -1
  3. package/agent-runtime/hostRuntimeCapabilities.ts +7 -0
  4. package/agent-runtime/hostRuntimeConfig.ts +86 -0
  5. package/agent-runtime/index.ts +13 -0
  6. package/agent-runtime/localToolPolicy.ts +13 -6
  7. package/agent-runtime/localWorkspaceTools.ts +333 -30
  8. package/agent-runtime/platformChatProvider.ts +4 -1
  9. package/agent-runtime/runtimeToolPolicy.ts +32 -47
  10. package/agent-runtime/shellCommandPolicy.ts +117 -0
  11. package/agent-runtime/toolGate.ts +38 -0
  12. package/agentRecordCommands.ts +1 -1
  13. package/agentRecordHelpers.ts +35 -20
  14. package/agentRunParsing.ts +18 -5
  15. package/agentRuntimeLocal.ts +10 -0
  16. package/ai/agent/agentRunDialogLineage.ts +56 -0
  17. package/ai/agent/agentSlice.ts +45 -10
  18. package/ai/agent/avatarUtils.ts +1 -1
  19. package/ai/agent/buildSystemPrompt.ts +1 -2
  20. package/ai/agent/cliExecutor.ts +330 -19
  21. package/ai/agent/createAgentSchema.ts +22 -0
  22. package/ai/agent/hooks/fetchPublicAgents.ts +14 -39
  23. package/ai/agent/hooks/usePublicAgents.ts +90 -192
  24. package/ai/agent/publicAgentCatalog.ts +359 -0
  25. package/ai/agent/publicAgentIdentity.ts +76 -0
  26. package/ai/agent/server/fetchPublicAgents.ts +21 -46
  27. package/ai/agent/serverOrigin.ts +7 -0
  28. package/ai/agent/streamAgentChatTurn.ts +23 -21
  29. package/ai/agent/streamAgentChatTurnUtils.ts +292 -6
  30. package/ai/agent/types.ts +2 -0
  31. package/ai/agent/web/agentDisplayUtils.ts +171 -0
  32. package/ai/agent/web/useAgentModelAvatarComponent.ts +32 -0
  33. package/ai/ai.locale.ts +8 -0
  34. package/ai/chat/sendOpenAICompletionsRequest.native.ts +15 -0
  35. package/ai/chat/sendOpenAICompletionsRequest.ts +93 -1
  36. package/ai/chat/sendOpenAIResponseRequest.ts +86 -9
  37. package/ai/chat/updateTotalUsage.ts +7 -0
  38. package/ai/llm/deepinfra.ts +30 -15
  39. package/ai/llm/mistral.ts +3 -4
  40. package/ai/llm/providers.ts +2 -0
  41. package/ai/llm/types.ts +15 -0
  42. package/ai/memory/capture.ts +3 -3
  43. package/ai/memory/consolidate.ts +2 -2
  44. package/ai/memory/delete.ts +4 -3
  45. package/ai/memory/query.ts +3 -3
  46. package/ai/memory/remember.ts +2 -2
  47. package/ai/memory/store.ts +3 -3
  48. package/ai/memory/storeShared.ts +3 -2
  49. package/ai/policy/commercialMultiplier.ts +16 -0
  50. package/ai/token/billingAdminAuditEvent.ts +68 -0
  51. package/ai/token/billingAdminAuditEventWriter.ts +41 -0
  52. package/ai/token/billingAnomaly.ts +90 -0
  53. package/ai/token/billingAnomalyLifecycle.ts +54 -0
  54. package/ai/token/billingAnomalyLifecycleWriter.ts +44 -0
  55. package/ai/token/billingAnomalyWriter.ts +41 -0
  56. package/ai/token/calculatePrice.ts +3 -2
  57. package/ai/token/deepinfraReconciliation.ts +153 -0
  58. package/ai/token/deepinfraRequestIdQuery.ts +92 -0
  59. package/ai/token/externalToolCost.ts +54 -41
  60. package/ai/token/missingUsageEstimate.ts +12 -3
  61. package/ai/token/normalizeUsage.ts +45 -5
  62. package/ai/token/openaiReconciliation.ts +188 -0
  63. package/ai/token/providerBillableEvent.ts +84 -0
  64. package/ai/token/providerBillableEventWriter.ts +36 -0
  65. package/ai/token/providerBillingAnomalyDrilldown.ts +308 -0
  66. package/ai/token/providerBillingDrilldown.ts +361 -0
  67. package/ai/token/providerBillingHealthReport.ts +366 -0
  68. package/ai/token/providerCall.ts +144 -0
  69. package/ai/token/providerCallSweeper.ts +168 -0
  70. package/ai/token/providerCallWriter.ts +33 -0
  71. package/ai/token/providerCredential.ts +89 -0
  72. package/ai/token/providerCredentialAnomaly.ts +154 -0
  73. package/ai/token/providerCredentialLifecycle.ts +59 -0
  74. package/ai/token/providerCredentialLifecycleWriter.ts +44 -0
  75. package/ai/token/providerCredentialRegistry.ts +83 -0
  76. package/ai/token/providerCredentialRegistryCommand.ts +97 -0
  77. package/ai/token/providerCredentialRegistryList.ts +124 -0
  78. package/ai/token/providerCredentialRegistryResolver.ts +150 -0
  79. package/ai/token/providerCredentialRegistryWriter.ts +41 -0
  80. package/ai/token/providerCredentialRotationCommand.ts +102 -0
  81. package/ai/token/providerCredentialRuntime.ts +56 -0
  82. package/ai/token/providerDispatchIntent.ts +67 -0
  83. package/ai/token/providerDispatchIntentWriter.ts +36 -0
  84. package/ai/token/providerGateway.ts +260 -0
  85. package/ai/token/providerReconciliation.ts +148 -0
  86. package/ai/token/providerReconciliationLocal.ts +97 -0
  87. package/ai/token/providerReconciliationRunner.ts +165 -0
  88. package/ai/token/providerReconciliationWriter.ts +41 -0
  89. package/ai/token/ratingResult.ts +202 -0
  90. package/ai/token/ratingResultWriter.ts +33 -0
  91. package/ai/token/serverDialogProjection.ts +5 -3
  92. package/ai/token/serverTokenWriter.ts +11 -3
  93. package/ai/token/types.ts +10 -0
  94. package/ai/tools/agent/callAgentTool.ts +3 -4
  95. package/ai/tools/agent/presets/appBuilderPreset.ts +5 -7
  96. package/ai/tools/agent/runStreamingAgentTool.ts +1 -2
  97. package/ai/tools/agent/streamParallelAgentsTool.ts +2 -3
  98. package/ai/tools/readXPostTool.ts +1 -5
  99. package/app/admin/adminPages.ts +9 -0
  100. package/app/i18n/i18n.config.ts +5 -0
  101. package/app/i18n/translations/pricing.locale.ts +397 -0
  102. package/app/utils/desktopAgentRuntimeStatusClient.ts +5 -4
  103. package/app/utils/desktopAgentRuntimeTurnClient.ts +4 -1
  104. package/app/utils/imageUtils.ts +64 -34
  105. package/auth/adminPermissions.ts +18 -0
  106. package/auth/authSlice.ts +26 -12
  107. package/auth/hooks/useFetchUsers.ts +3 -0
  108. package/auth/routes.ts +46 -0
  109. package/auth/server/accessActivity.ts +4 -3
  110. package/auth/server/adminPermissions.ts +43 -0
  111. package/auth/server/adminUsageReport.ts +375 -0
  112. package/auth/server/billingAnomalies.ts +235 -0
  113. package/auth/server/billingUsageReport.ts +41 -2
  114. package/auth/server/creatorEarningCreditConversion.ts +10 -2
  115. package/auth/server/deduct.ts +14 -7
  116. package/auth/server/delete.ts +10 -2
  117. package/auth/server/disable.ts +4 -3
  118. package/auth/server/emailAutomation.ts +7 -5
  119. package/auth/server/emailDbConfig.ts +4 -2
  120. package/auth/server/emailDelivery.ts +24 -20
  121. package/auth/server/emailDeliveryGuards.ts +10 -7
  122. package/auth/server/emailPreferences.ts +6 -4
  123. package/auth/server/emailReport.ts +6 -4
  124. package/auth/server/emailRuntimeConfig.ts +3 -3
  125. package/auth/server/emailScenarioNotifications.ts +9 -8
  126. package/auth/server/enable.ts +4 -3
  127. package/auth/server/getRechargeHistory.ts +3 -2
  128. package/auth/server/getUser.ts +3 -2
  129. package/auth/server/gptProAccess.ts +44 -0
  130. package/auth/server/inviteReward.ts +10 -7
  131. package/auth/server/listusers.ts +6 -4
  132. package/auth/server/login.ts +2 -2
  133. package/auth/server/productEntitlements.ts +7 -4
  134. package/auth/server/productPurchase.ts +10 -2
  135. package/auth/server/providerBillingDrilldown.ts +47 -0
  136. package/auth/server/providerBillingHealth.ts +71 -0
  137. package/auth/server/providerCredentials.ts +136 -0
  138. package/auth/server/recharge.ts +14 -8
  139. package/auth/server/revokeSessions.ts +4 -3
  140. package/auth/server/route.ts +77 -0
  141. package/auth/server/sendEmail.ts +5 -4
  142. package/auth/server/signup.ts +10 -3
  143. package/auth/server/token.ts +53 -55
  144. package/auth/server/tokenUsageBilling.ts +18 -7
  145. package/auth/server/usageManagementAccess.ts +43 -0
  146. package/auth/server/usageReport.ts +59 -0
  147. package/auth/types.ts +12 -0
  148. package/auth/utils.ts +24 -22
  149. package/authCommands.ts +36 -2
  150. package/buildPublish.ts +3 -1
  151. package/buildPublishArtifactAssembly.ts +62 -1
  152. package/buildPublishImportAnalysis.ts +21 -16
  153. package/chat/dialog/dialogLaunchScope.ts +32 -0
  154. package/chat/dialog/objectAssistantRegistry.ts +2 -2
  155. package/chat/dialog/useCreateDialog.ts +1 -1
  156. package/chat/hooks/useChatInput.ts +41 -10
  157. package/chat/messages/messageSlice.ts +5 -1
  158. package/chat/messages/pendingAttachmentParts.ts +28 -2
  159. package/chat/messages/sendFirstMessage.ts +76 -79
  160. package/chat/messages/types.ts +9 -0
  161. package/chat/messages/web/streamingMarkdownModel.ts +41 -0
  162. package/chat/messages/web/useStreamingReveal.ts +91 -0
  163. package/chat/web/messageInputAgentUi.ts +94 -6
  164. package/cliEnvHelpers.ts +8 -0
  165. package/cliRuntimeDoctorReport.ts +193 -0
  166. package/client/agentConfigResolver.test.ts +0 -2
  167. package/client/agentRun.test.ts +171 -10
  168. package/client/agentRun.ts +44 -637
  169. package/client/agentRunInput.ts +10 -0
  170. package/client/agentRunLocalExecutor.ts +179 -0
  171. package/client/agentRunServerTransport.ts +394 -0
  172. package/client/agentRunTaskRunRecorder.ts +176 -0
  173. package/client/localRuntimeAdapter.test.ts +236 -9
  174. package/client/localRuntimeAdapter.ts +221 -23
  175. package/client/localToolPolicy.test.ts +28 -4
  176. package/connector-experimental/daemonLauncher.ts +38 -4
  177. package/connectorRunArtifact.ts +34 -10
  178. package/connectorWebSocketTarget.ts +9 -5
  179. package/core/builtinAgents.ts +155 -11
  180. package/create/space/contentLabels.ts +1 -1
  181. package/create/space/contentTypeMeta.ts +3 -2
  182. package/create/space/sidebarVisibleTypes.ts +27 -0
  183. package/create/space/space.locale.ts +76 -4
  184. package/database/actions/agentReadResolution.ts +2 -8
  185. package/database/actions/read.ts +11 -9
  186. package/database/actions/readAndWait.ts +10 -5
  187. package/database/server/agentDelegation.ts +3 -2
  188. package/database/server/authorityStoreConformance.ts +209 -0
  189. package/database/server/authorityStoreTypes.ts +31 -0
  190. package/database/server/coreDataProxy.ts +1 -1
  191. package/database/server/dataHandlers.ts +13 -5
  192. package/database/server/db.ts +15 -34
  193. package/database/server/delete.ts +88 -71
  194. package/database/server/emailRepository.ts +11 -9
  195. package/database/server/fileService.ts +2 -1
  196. package/database/server/legacyServerDb.ts +58 -0
  197. package/database/server/levelAuthorityStore.ts +75 -0
  198. package/database/server/memoryAuthorityStore.ts +133 -0
  199. package/database/server/patch.ts +13 -12
  200. package/database/server/query.ts +3 -2
  201. package/database/server/read.ts +33 -30
  202. package/database/server/resourceAccess.ts +7 -5
  203. package/database/server/serverStoreFactory.ts +124 -0
  204. package/database/server/spaceMemberAuthority.ts +3 -2
  205. package/database/server/storeBatchCompat.ts +37 -0
  206. package/database/server/testAuthorityStore.ts +76 -0
  207. package/database/server/write.ts +29 -27
  208. package/integrations/anthropic/anthropicModels.ts +12 -12
  209. package/integrations/deepseek/models.ts +67 -67
  210. package/integrations/google/models.ts +111 -53
  211. package/integrations/openai/models.ts +22 -22
  212. package/integrations/xai/models.ts +1 -1
  213. package/localRuntimeDb.ts +39 -2
  214. package/machineCommandPrompts.ts +2 -0
  215. package/machineCommands.ts +193 -63
  216. package/machineWsRunDispatch.ts +80 -15
  217. package/machineWsSession.ts +39 -2
  218. package/noloReadBridgePrompt.ts +16 -0
  219. package/package.json +99 -6
  220. package/render/layout/mainLayoutViewMode.ts +25 -0
  221. package/render/page/server/createPage.ts +3 -1
  222. package/render/page/server/handleCreatePage.ts +2 -11
  223. package/runtimeDoctorCommands.ts +15 -66
  224. package/server/api/methods.ts +34 -12
  225. package/server/api/tableHandlers.ts +6 -3
  226. package/server/authenticateToken.ts +47 -2
  227. package/server/billingLedgerRoutes.ts +15 -0
  228. package/server/buildManifest.ts +54 -0
  229. package/server/coreReadiness.ts +34 -25
  230. package/server/coreRuntime.ts +15 -10
  231. package/server/handlers/activityStatsHandler.ts +5 -2
  232. package/server/handlers/agentEmailRegistrationE2EHandler.ts +25 -23
  233. package/server/handlers/agentRun/agentLookup.ts +1 -7
  234. package/server/handlers/agentRun/autonomousRuntime.ts +11 -10
  235. package/server/handlers/agentRun/builtinAgents.ts +12 -88
  236. package/server/handlers/agentRun/continueDialogContext.ts +15 -3
  237. package/server/handlers/agentRun/{inheritedDialogPrompt.ts → conversationReference.ts} +3 -3
  238. package/server/handlers/agentRun/dialogLookup.ts +4 -3
  239. package/server/handlers/agentRun/index.ts +864 -404
  240. package/server/handlers/agentRun/localRuntimeBootstrap.ts +17 -1
  241. package/server/handlers/agentRun/loop.ts +920 -508
  242. package/server/handlers/agentRun/machineConnector.ts +56 -8
  243. package/server/handlers/agentRun/machineRunAudit.ts +3 -2
  244. package/server/handlers/agentRun/modelUsageToolHandlers.ts +13 -10
  245. package/server/handlers/agentRun/requestContext.ts +12 -8
  246. package/server/handlers/agentRun/runtimeExecutionContext.ts +15 -3
  247. package/server/handlers/agentRun/runtimePreparation.ts +26 -24
  248. package/server/handlers/agentRun/runtimeRouting.ts +25 -40
  249. package/server/handlers/agentRun/runtimeSystemMessages.ts +65 -0
  250. package/server/handlers/agentRun/saveDialog.ts +97 -87
  251. package/server/handlers/agentRun/taskRunToolHandler.ts +9 -7
  252. package/server/handlers/agentRun/toolExecutor.ts +42 -78
  253. package/server/handlers/agentRun/types.ts +2 -1
  254. package/server/handlers/appDeployStatusStore.ts +17 -10
  255. package/server/handlers/appDomainHandler.ts +21 -15
  256. package/server/handlers/appLegacyInfraCleanup.ts +5 -2
  257. package/server/handlers/appSandboxHandler.ts +29 -8
  258. package/server/handlers/appSpaceAccess.ts +15 -8
  259. package/server/handlers/chatHandler.ts +22 -2
  260. package/server/handlers/chatUpstreamRetry.ts +225 -2
  261. package/server/handlers/connector/connectorConnectionRegistry.ts +55 -7
  262. package/server/handlers/connector/connectorWebSocket.ts +14 -10
  263. package/server/handlers/desktopAgentRuntimeAdapter.ts +4 -4
  264. package/server/handlers/desktopAgentRuntimeHostCapabilities.ts +25 -0
  265. package/server/handlers/desktopAgentRuntimeReadiness.ts +62 -0
  266. package/server/handlers/desktopAgentRuntimeStatusHandler.ts +38 -30
  267. package/server/handlers/desktopAgentRuntimeTurnHandler.ts +7 -3
  268. package/server/handlers/desktopAgentRuntimeTurnService.ts +39 -45
  269. package/server/handlers/desktopLlamaRuntimeHandler.ts +85 -51
  270. package/server/handlers/desktopUpdaterHandler.ts +132 -24
  271. package/server/handlers/favoriteHandlers.ts +8 -2
  272. package/server/handlers/getDialogBillingHandler.ts +4 -3
  273. package/server/handlers/getTransactionsHandler.ts +5 -2
  274. package/server/handlers/machines/machineBinding.ts +1 -0
  275. package/server/handlers/machines/machineHandlers.ts +0 -14
  276. package/server/handlers/machines/machineInstallAssets.ts +4 -2
  277. package/server/handlers/notificationEmitter.ts +5 -3
  278. package/server/handlers/notificationsHandler.ts +5 -2
  279. package/server/handlers/providerCallsRecentHandler.ts +234 -0
  280. package/server/handlers/providerReconciliationRunHandler.ts +180 -0
  281. package/server/handlers/providerRequestIdsHandler.ts +105 -0
  282. package/server/handlers/tableAccess.ts +6 -2
  283. package/server/handlers/tableToolHandlers.ts +28 -14
  284. package/server/handlers/userSecretsHandler.ts +17 -6
  285. package/server/handlers/versionHandler.ts +9 -4
  286. package/server/handlers/versionStore.ts +18 -10
  287. package/server/html/ssrPreload.ts +5 -3
  288. package/server/payments/crypto/cryptoUsdcBasePaymentProvider.ts +11 -8
  289. package/server/payments/crypto/cryptoUsdcBaseScanner.ts +12 -7
  290. package/server/payments/crypto/cryptoUsdtTronPaymentProvider.ts +11 -8
  291. package/server/payments/crypto/cryptoUsdtTronScanner.ts +9 -7
  292. package/server/payments/waffo/waffoPaymentProvider.ts +12 -9
  293. package/server/runtimeRole.ts +15 -0
  294. package/server/scheduler/scheduledTaskRuntime.ts +4 -2
  295. package/server/scheduler/schedulerService.ts +2 -2
  296. package/server/taskRunBridgeRoutes.ts +8 -5
  297. package/share/server/fetchCommunityShares.ts +1 -1
  298. package/share/server/helpers.ts +19 -17
  299. package/share/server/importShare.ts +9 -13
  300. package/share/server/listCommunityShares.ts +4 -4
  301. package/share/server/purchaseDoc.ts +8 -16
  302. package/share/server/readCommunityShareCover.ts +3 -2
  303. package/share/server/readSharedTable.ts +14 -13
  304. package/share/server/tableReplication.ts +42 -39
  305. package/spaceAttachCommands.ts +135 -0
  306. package/spaceInternalCommandEntries.ts +2 -0
  307. package/ai/agent/runtimeServerBase.ts +0 -37
  308. package/server/handlers/desktopAgentRuntimeHostFacts.ts +0 -40
@@ -0,0 +1,359 @@
1
+ import type { Agent } from "../../app/types";
2
+ import { getModelPricing } from "../llm/getPricing";
3
+ import { getModelConfig } from "../llm/providers";
4
+ import { supportsImageGeneration } from "../agent/utils/imageOutput";
5
+ import { buildSortMeta, sortAgents, toTimeMs, type MAgent } from "../agent/utils/sortUtils";
6
+ import {
7
+ getPublicAgentId,
8
+ getPublicAgentIdentifiers,
9
+ } from "../agent/publicAgentIdentity";
10
+ import { getRecordTimestamp } from "../../database/tombstones";
11
+ import {
12
+ normalizeBuiltinPublicAgentRecord,
13
+ shouldHideBuiltinAgentFromPublicPlaza,
14
+ } from "../../core/builtinAgents";
15
+
16
+ export type PublicAgentSortBy =
17
+ | "recommended"
18
+ | "newest"
19
+ | "popular"
20
+ | "rating"
21
+ | "outputPriceAsc"
22
+ | "outputPriceDesc"
23
+ | "favorite";
24
+
25
+ export interface PublicAgentFilterOptions {
26
+ searchName?: string;
27
+ userId?: string;
28
+ imageOutputOnly?: boolean;
29
+ toolName?: string;
30
+ }
31
+
32
+ export interface PublicAgentListOptions {
33
+ limit?: number;
34
+ sortBy?: PublicAgentSortBy;
35
+ }
36
+
37
+ export type PublicAgentQueryOptions = PublicAgentFilterOptions & PublicAgentListOptions;
38
+
39
+ type PublicAgentRecord = Partial<Agent> & Record<string, any>;
40
+
41
+ const GPT_IMAGE_TOOL_NAMES = new Set([
42
+ "openAIGptImage",
43
+ "openAIGptImageGenerate",
44
+ "openAIGptImageEdit",
45
+ ]);
46
+
47
+ const shouldUsePlatformPricing = (agent: PublicAgentRecord): boolean => {
48
+ const provider = typeof agent.provider === "string" ? agent.provider.trim() : "";
49
+ if (!provider) return false;
50
+ if (provider === "custom") return false;
51
+ const customProviderUrl =
52
+ typeof agent.customProviderUrl === "string" ? agent.customProviderUrl.trim() : "";
53
+ if (customProviderUrl) return false;
54
+ const apiSource = typeof agent.apiSource === "string" ? agent.apiSource.trim() : "";
55
+ return !apiSource || apiSource === "platform";
56
+ };
57
+
58
+ const shouldApplyPlatformPriceFloor = (agent: PublicAgentRecord): boolean => {
59
+ const provider = typeof agent.provider === "string" ? agent.provider.trim() : "";
60
+ if (!provider || provider === "custom") return false;
61
+ const apiSource = typeof agent.apiSource === "string" ? agent.apiSource.trim() : "";
62
+ const customProviderUrl =
63
+ typeof agent.customProviderUrl === "string" ? agent.customProviderUrl.trim() : "";
64
+ return apiSource === "custom" || !!customProviderUrl;
65
+ };
66
+
67
+ const maxNumber = (value: unknown, floor: number) =>
68
+ typeof value === "number" && Number.isFinite(value) ? Math.max(value, floor) : floor;
69
+
70
+ export function normalizePublicAgentPlatformPricing<T extends PublicAgentRecord>(
71
+ agent: T
72
+ ): T {
73
+ const provider = typeof agent.provider === "string" ? agent.provider.trim() : "";
74
+ const model = typeof agent.model === "string" ? agent.model.trim() : "";
75
+ if (!provider || !model) return agent;
76
+
77
+ const usePlatformPricing = shouldUsePlatformPricing(agent);
78
+ const applyPlatformPriceFloor = shouldApplyPlatformPriceFloor(agent);
79
+ if (!usePlatformPricing && !applyPlatformPriceFloor) return agent;
80
+
81
+ let next: PublicAgentRecord = agent;
82
+ try {
83
+ const pricing = getModelPricing(provider, model);
84
+ const modelConfig = getModelConfig(provider as any, model);
85
+ if (pricing && usePlatformPricing) {
86
+ next = {
87
+ ...next,
88
+ inputPrice: pricing.inputPrice,
89
+ outputPrice: pricing.outputPrice,
90
+ hasVision: agent.hasVision ?? !!modelConfig.hasVision,
91
+ };
92
+ } else if (pricing && applyPlatformPriceFloor) {
93
+ next = {
94
+ ...next,
95
+ inputPrice: maxNumber(agent.inputPrice, pricing.inputPrice),
96
+ outputPrice: maxNumber(agent.outputPrice, pricing.outputPrice),
97
+ };
98
+ }
99
+ } catch {
100
+ // Keep the persisted record when the provider/model is not in the platform registry.
101
+ }
102
+
103
+ const tools = Array.isArray(agent.tools) ? agent.tools : [];
104
+ const usesOpenAIImageTool = tools.some(
105
+ (tool) => typeof tool === "string" && GPT_IMAGE_TOOL_NAMES.has(tool)
106
+ );
107
+ const imageModel =
108
+ typeof agent.imageModel === "string" && agent.imageModel.trim()
109
+ ? agent.imageModel.trim()
110
+ : usesOpenAIImageTool
111
+ ? "gpt-image-2"
112
+ : "";
113
+
114
+ if (usePlatformPricing && provider === "openai" && imageModel === "gpt-image-2") {
115
+ next = {
116
+ ...next,
117
+ imageModel,
118
+ imageConfig: {
119
+ ...((agent.imageConfig && typeof agent.imageConfig === "object"
120
+ ? agent.imageConfig
121
+ : {}) as Record<string, unknown>),
122
+ enabled: true,
123
+ },
124
+ hasImageOutput: agent.hasImageOutput ?? true,
125
+ };
126
+ }
127
+
128
+ return next as T;
129
+ }
130
+
131
+ export function preparePublicAgentCatalogRecords(agents: Agent[]): Agent[] {
132
+ return agents
133
+ .map((agent) => normalizeBuiltinPublicAgentRecord(agent))
134
+ .map((agent) => normalizePublicAgentPlatformPricing(agent))
135
+ .filter((agent) => !shouldHideBuiltinAgentFromPublicPlaza(agent));
136
+ }
137
+
138
+ export function shouldPruneStalePublicAgentCache({
139
+ searchName,
140
+ }: {
141
+ searchName?: string;
142
+ }) {
143
+ return !searchName;
144
+ }
145
+
146
+ export function dedupeRemotePublicAgents(remoteAgents: Agent[]): Agent[] {
147
+ const remoteMap = new Map<string, Agent>();
148
+ for (const agent of remoteAgents) {
149
+ const logicalId = getPublicAgentId(agent) ?? String(agent.id ?? "");
150
+ if (!logicalId) continue;
151
+ const existing = remoteMap.get(logicalId);
152
+ if (!existing || getRecordTimestamp(agent) > getRecordTimestamp(existing)) {
153
+ remoteMap.set(logicalId, agent);
154
+ }
155
+ }
156
+ return Array.from(remoteMap.values());
157
+ }
158
+
159
+ export function maskRemoteAgentsByLocalTombstones(
160
+ remoteAgents: Agent[],
161
+ tombstones: Array<Record<string, any>>
162
+ ): Agent[] {
163
+ const tombstoneMap = new Map<string, Record<string, any>>();
164
+ for (const tombstone of tombstones) {
165
+ for (const identifier of getPublicAgentIdentifiers(tombstone)) {
166
+ const existing = tombstoneMap.get(identifier);
167
+ if (!existing || getRecordTimestamp(tombstone) > getRecordTimestamp(existing)) {
168
+ tombstoneMap.set(identifier, tombstone);
169
+ }
170
+ }
171
+ }
172
+
173
+ return remoteAgents.filter((agent) => {
174
+ const matchingTombstones = getPublicAgentIdentifiers(agent)
175
+ .map((identifier) => tombstoneMap.get(identifier))
176
+ .filter(Boolean) as Array<Record<string, any>>;
177
+ if (matchingTombstones.length === 0) return true;
178
+ const newestLocalTombstone = matchingTombstones.reduce((latest, current) =>
179
+ getRecordTimestamp(current) > getRecordTimestamp(latest) ? current : latest
180
+ );
181
+ return getRecordTimestamp(agent) > getRecordTimestamp(newestLocalTombstone);
182
+ });
183
+ }
184
+
185
+ export function mergePublicAgentSources(localData: Agent[], remoteData: Agent[]) {
186
+ const remoteById = new Map<string, Agent>();
187
+ for (const remote of remoteData) {
188
+ const logicalId = getPublicAgentId(remote);
189
+ if (logicalId) {
190
+ remoteById.set(logicalId, remote);
191
+ }
192
+ }
193
+
194
+ const merged: MAgent[] = [];
195
+ const toDeleteIds: string[] = [];
196
+
197
+ for (const local of localData) {
198
+ const logicalId = getPublicAgentId(local) ?? String(local.id ?? "");
199
+ if (!logicalId) continue;
200
+ const remote = remoteById.get(logicalId);
201
+
202
+ if (remote) {
203
+ const localTimestamp = getRecordTimestamp(local);
204
+ const remoteTimestamp = getRecordTimestamp(remote);
205
+ const newest =
206
+ remoteTimestamp >= localTimestamp
207
+ ? { ...(local as any), ...(remote as any) }
208
+ : { ...(remote as any), ...(local as any) };
209
+ merged.push({
210
+ ...newest,
211
+ __sort: buildSortMeta(local, remote),
212
+ });
213
+ continue;
214
+ }
215
+
216
+ toDeleteIds.push(logicalId);
217
+ merged.push({
218
+ ...(local as any),
219
+ __sort: buildSortMeta(local, undefined),
220
+ });
221
+ }
222
+
223
+ for (const remote of remoteData) {
224
+ const logicalId = getPublicAgentId(remote);
225
+ if (!logicalId) continue;
226
+ const exists = merged.some((agent) => getPublicAgentId(agent) === logicalId);
227
+ if (!exists) {
228
+ merged.push({ ...(remote as any), __sort: buildSortMeta(undefined, remote) });
229
+ }
230
+ }
231
+
232
+ return { merged, toDeleteIds };
233
+ }
234
+
235
+ export function planStalePublicAgentPrunes({
236
+ localAgents,
237
+ toDeleteIds,
238
+ currentUserId,
239
+ nowMs = Date.now(),
240
+ }: {
241
+ localAgents: Agent[];
242
+ toDeleteIds: string[];
243
+ currentUserId?: string | null;
244
+ nowMs?: number;
245
+ }) {
246
+ return toDeleteIds.filter((id) => {
247
+ const localItem = localAgents.find((agent) => getPublicAgentId(agent) === id) as
248
+ | PublicAgentRecord
249
+ | undefined;
250
+
251
+ if (currentUserId && localItem?.userId === currentUserId) return false;
252
+
253
+ const isRecentlyCreated = nowMs - toTimeMs(localItem?.createdAt) < 5 * 60 * 1000;
254
+ if (isRecentlyCreated) return false;
255
+
256
+ return localItem?.meta?.origin !== "local";
257
+ });
258
+ }
259
+
260
+ export function planPublicAgentCatalogView({
261
+ localAgents,
262
+ remoteAgents,
263
+ hasAuthoritativeRemoteResult,
264
+ currentUserId,
265
+ options = {},
266
+ }: {
267
+ localAgents: Agent[];
268
+ remoteAgents: Agent[];
269
+ hasAuthoritativeRemoteResult: boolean;
270
+ currentUserId?: string | null;
271
+ options?: PublicAgentQueryOptions;
272
+ }) {
273
+ const localFallbackAgents = buildPublicAgentCatalogList({
274
+ ...options,
275
+ agents: localAgents,
276
+ });
277
+ const { merged, toDeleteIds } = mergePublicAgentSources(localAgents, remoteAgents);
278
+ const staleIdsToHide = hasAuthoritativeRemoteResult ? toDeleteIds : [];
279
+ const staleIdsToHideSet = new Set(staleIdsToHide);
280
+ const visibleAgents = buildPublicAgentCatalogList({
281
+ ...options,
282
+ agents: (merged as Agent[]).filter(
283
+ (agent) => !staleIdsToHideSet.has(getPublicAgentId(agent) ?? "")
284
+ ),
285
+ });
286
+ const pruneIds = planStalePublicAgentPrunes({
287
+ localAgents,
288
+ toDeleteIds,
289
+ currentUserId,
290
+ });
291
+
292
+ return {
293
+ visibleAgents,
294
+ localFallbackAgents,
295
+ staleIdsToHide,
296
+ pruneIds,
297
+ };
298
+ }
299
+
300
+ export function filterPublicAgentRecords(
301
+ agents: Agent[],
302
+ {
303
+ searchName,
304
+ userId,
305
+ imageOutputOnly = false,
306
+ toolName,
307
+ }: PublicAgentFilterOptions = {}
308
+ ): Agent[] {
309
+ let results = [...agents];
310
+
311
+ if (searchName) {
312
+ const kw = searchName.toLowerCase();
313
+ results = results.filter((agent) => {
314
+ const nameMatch = agent.name?.toLowerCase().includes(kw);
315
+ const introMatch = agent.introduction?.toLowerCase().includes(kw);
316
+ const tagMatch = agent.tags?.some((tag) => tag.toLowerCase().includes(kw));
317
+ return nameMatch || introMatch || tagMatch;
318
+ });
319
+ }
320
+
321
+ if (userId) {
322
+ results = results.filter((agent) => agent.userId === userId);
323
+ }
324
+
325
+ if (imageOutputOnly) {
326
+ results = results.filter((agent) => supportsImageGeneration(agent));
327
+ }
328
+
329
+ if (toolName) {
330
+ const kw = toolName.toLowerCase();
331
+ results = results.filter((agent) =>
332
+ agent.tools?.some((tool) => tool.toLowerCase().includes(kw))
333
+ );
334
+ }
335
+
336
+ return results;
337
+ }
338
+
339
+ export function buildPublicAgentCatalogList({
340
+ agents,
341
+ sortBy = "recommended",
342
+ limit,
343
+ searchName,
344
+ userId,
345
+ imageOutputOnly = false,
346
+ toolName,
347
+ }: {
348
+ agents: Agent[];
349
+ } & PublicAgentFilterOptions &
350
+ PublicAgentListOptions) {
351
+ const filtered = filterPublicAgentRecords(preparePublicAgentCatalogRecords(agents), {
352
+ searchName,
353
+ userId,
354
+ imageOutputOnly,
355
+ toolName,
356
+ });
357
+ const sorted = sortAgents(filtered, sortBy);
358
+ return typeof limit === "number" ? sorted.slice(0, limit) : sorted;
359
+ }
@@ -0,0 +1,76 @@
1
+ import type { Agent } from "../../app/types";
2
+
3
+ const PUBLIC_AGENT_PREFIX = "agent-pub-";
4
+ const PUBLIC_CYBOT_PREFIX = "cybot-pub-";
5
+
6
+ type PublicAgentRecord = Partial<Agent> & Record<string, any>;
7
+
8
+ const toNonEmptyString = (value: unknown): string | undefined => {
9
+ if (typeof value !== "string") return undefined;
10
+ const normalized = value.trim();
11
+ return normalized || undefined;
12
+ };
13
+
14
+ const parsePublicDbKey = (value: unknown) => {
15
+ const text = toNonEmptyString(value);
16
+ if (!text) return null;
17
+ if (text.startsWith(PUBLIC_AGENT_PREFIX)) {
18
+ return {
19
+ dbKey: text,
20
+ id: text.slice(PUBLIC_AGENT_PREFIX.length),
21
+ type: "agent",
22
+ } as const;
23
+ }
24
+ if (text.startsWith(PUBLIC_CYBOT_PREFIX)) {
25
+ return {
26
+ dbKey: text,
27
+ id: text.slice(PUBLIC_CYBOT_PREFIX.length),
28
+ type: "cybot",
29
+ } as const;
30
+ }
31
+ return null;
32
+ };
33
+
34
+ const buildPublicDbKey = (type: unknown, id: string): string => {
35
+ if (type === "agent") return `${PUBLIC_AGENT_PREFIX}${id}`;
36
+ if (type === "cybot") return `${PUBLIC_CYBOT_PREFIX}${id}`;
37
+ return "";
38
+ };
39
+
40
+ export function getPublicAgentId(agent?: PublicAgentRecord | null): string | undefined {
41
+ const directId = toNonEmptyString(agent?.id);
42
+ if (directId) {
43
+ return parsePublicDbKey(directId)?.id ?? directId;
44
+ }
45
+ return parsePublicDbKey(agent?.dbKey)?.id;
46
+ }
47
+
48
+ export function getPublicAgentDbKey(agent?: PublicAgentRecord | null): string | undefined {
49
+ const directDbKey = toNonEmptyString(agent?.dbKey);
50
+ if (directDbKey) return directDbKey;
51
+
52
+ const idAsDbKey = parsePublicDbKey(agent?.id)?.dbKey;
53
+ if (idAsDbKey) return idAsDbKey;
54
+
55
+ const id = getPublicAgentId(agent);
56
+ if (!id) return undefined;
57
+ return buildPublicDbKey(agent?.type, id) || undefined;
58
+ }
59
+
60
+ export function getPublicAgentIdentifiers(agent?: PublicAgentRecord | null): string[] {
61
+ const identifiers = [getPublicAgentDbKey(agent), getPublicAgentId(agent)].filter(Boolean);
62
+ return Array.from(new Set(identifiers as string[]));
63
+ }
64
+
65
+ export function matchesPublicAgentIdentifiers(
66
+ agent: PublicAgentRecord | null | undefined,
67
+ identifiers: Set<string>
68
+ ): boolean {
69
+ return getPublicAgentIdentifiers(agent).some((identifier) => identifiers.has(identifier));
70
+ }
71
+
72
+ export function getPublicAgentPruneDbKey(
73
+ agent?: PublicAgentRecord | null
74
+ ): string | undefined {
75
+ return getPublicAgentDbKey(agent) ?? getPublicAgentId(agent);
76
+ }
@@ -1,25 +1,18 @@
1
- import serverDb from "../../../database/server/db";
1
+ import { getServerAuthorityStore } from "../../../database/server/db";
2
2
  import { pubAgentKeys } from "../../../database/keys";
3
3
  import { Agent } from "../../../app/types";
4
+ import {
5
+ filterPublicAgentRecords,
6
+ preparePublicAgentCatalogRecords,
7
+ type PublicAgentFilterOptions,
8
+ type PublicAgentListOptions,
9
+ } from "../../agent/publicAgentCatalog";
4
10
  import { sortAgents } from "../../agent/utils/sortUtils";
5
- import { supportsImageGeneration } from "../../agent/utils/imageOutput";
6
11
  import { isTombstoneRecord } from "../../../database/tombstones";
7
12
 
8
- export interface FetchPublicAgentsOptions {
9
- limit?: number;
10
- sortBy?:
11
- | "recommended"
12
- | "newest"
13
- | "popular"
14
- | "rating"
15
- | "outputPriceAsc"
16
- | "outputPriceDesc"
17
- | "favorite"; // 新增:按收藏排序
18
- searchName?: string;
19
- userId?: string;
20
- imageOutputOnly?: boolean;
21
- /** Filter agents that include this tool in their tools array */
22
- toolName?: string;
13
+ export interface FetchPublicAgentsOptions
14
+ extends PublicAgentFilterOptions,
15
+ PublicAgentListOptions {
23
16
  /** Return list-card metadata only. Full agent config is still available by key. */
24
17
  summary?: boolean;
25
18
  }
@@ -30,15 +23,16 @@ export interface FetchPublicAgentsResult {
30
23
  hasMore: boolean;
31
24
  }
32
25
 
33
- // 局部 helpers 已移除,使用 shared utils
26
+ const getFetchPublicAgentsStore = () => getServerAuthorityStore();
34
27
 
35
28
  async function dbList<T>(
29
+ store: ReturnType<typeof getServerAuthorityStore>,
36
30
  gte: string,
37
31
  lte: string,
38
32
  filter?: (v: T) => boolean
39
33
  ): Promise<T[]> {
40
34
  const res: T[] = [];
41
- for await (const [, value] of serverDb.iterator({ gte, lte })) {
35
+ for await (const [, value] of store.iterator({ gte, lte })) {
42
36
  if (!filter || filter(value as T)) res.push(value as T);
43
37
  }
44
38
  return res;
@@ -55,6 +49,7 @@ export function invalidatePublicAgentsCache() {
55
49
  }
56
50
 
57
51
  async function getPublicAgents(): Promise<Agent[]> {
52
+ const store = getFetchPublicAgentsStore();
58
53
  const now = Date.now();
59
54
  if (cachedPublicAgents && now - cachedPublicAgentsAt < PUBLIC_AGENTS_CACHE_TTL_MS) {
60
55
  return cachedPublicAgents;
@@ -65,6 +60,7 @@ async function getPublicAgents(): Promise<Agent[]> {
65
60
 
66
61
  for (const { start, end } of ranges) {
67
62
  const res = await dbList<Agent>(
63
+ store,
68
64
  start,
69
65
  end,
70
66
  (v) => (v as any).isPublic && !isTombstoneRecord(v)
@@ -145,33 +141,12 @@ export async function fetchPublicAgents(
145
141
  // 使用带缓存的获取函数
146
142
  const baseList = await getPublicAgents();
147
143
 
148
- // 注意不要修改缓存引用,后续操作都在拷贝/派生数组上做
149
- let list = baseList;
150
-
151
- if (searchName) {
152
- const kw = searchName.toLowerCase();
153
- list = list.filter((agent) => {
154
- const nameMatch = agent.name?.toLowerCase().includes(kw);
155
- const introMatch = agent.introduction?.toLowerCase().includes(kw);
156
- const tagMatch = agent.tags?.some((tag) => tag.toLowerCase().includes(kw));
157
- return nameMatch || introMatch || tagMatch;
158
- });
159
- }
160
-
161
- if (userId) {
162
- list = list.filter((agent) => agent.userId === userId);
163
- }
164
-
165
- if (imageOutputOnly) {
166
- list = list.filter((agent) => supportsImageGeneration(agent));
167
- }
168
-
169
- if (toolName) {
170
- const kw = toolName.toLowerCase();
171
- list = list.filter((agent) =>
172
- agent.tools?.some((t) => t.toLowerCase().includes(kw))
173
- );
174
- }
144
+ const list = filterPublicAgentRecords(preparePublicAgentCatalogRecords(baseList), {
145
+ searchName,
146
+ userId,
147
+ imageOutputOnly,
148
+ toolName,
149
+ });
175
150
 
176
151
  // 使用统一的排序逻辑
177
152
  const sorted = sortAgents(list, sortBy);
@@ -0,0 +1,7 @@
1
+ export const normalizeServerOrigin = (base: string): string | null => {
2
+ try {
3
+ return new URL(base).origin.replace(/\/+$/, "");
4
+ } catch {
5
+ return null;
6
+ }
7
+ };
@@ -50,6 +50,7 @@ import {
50
50
  mergeContexts,
51
51
  hasImageInMessages,
52
52
  mergeAgentToolsWithRuntime,
53
+ resolveImageGenerationStreamingState,
53
54
  trimMessagesWithSummary,
54
55
  validateAccessAndBalance,
55
56
  } from "./streamAgentChatTurnUtils";
@@ -65,10 +66,7 @@ import { selectCurrentToken, selectUserId } from "../../auth/authSlice";
65
66
  import { persistMessageWithFixedId } from "./persistMessageWithFixedId";
66
67
  import { updateTotalUsage } from "../chat/updateTotalUsage";
67
68
  import { createSSEParser } from "../chat/parseMultilineSSE";
68
- import {
69
- extractAgentRuntimeServerBase,
70
- normalizeServerOrigin,
71
- } from "./runtimeServerBase";
69
+ import { normalizeServerOrigin } from "./serverOrigin";
72
70
  import { getIsDesktopApp } from "../../app/utils/env";
73
71
  import { runDesktopAgentRuntimeTurn } from "../../app/utils/desktopAgentRuntimeTurnClient";
74
72
 
@@ -148,6 +146,9 @@ const formatMachineAgentRunError = async (response: Response): Promise<string> =
148
146
  if (reason === "bound_machine_unavailable") {
149
147
  return "绑定的电脑不在线。请确认这台电脑已开机并重新运行连接命令。";
150
148
  }
149
+ if (reason === "bound_machine_owner_mismatch") {
150
+ return "这台电脑是在线的,但当前账号和 Agent 绑定账号不一致。请重新绑定 Agent,或在绑定账号下重新连接这台电脑。";
151
+ }
151
152
  if (reason === "connector_offline") {
152
153
  return "电脑在线,但连接器未连接。请在这台电脑上重新运行连接命令后再试。";
153
154
  }
@@ -974,22 +975,17 @@ export const streamAgentChatTurnHandler = async (
974
975
  ? args.serverBase.trim()
975
976
  : null;
976
977
  const currentServer = selectCurrentServer(state);
977
- const declaredRuntimeServerBase = extractAgentRuntimeServerBase(agentConfig);
978
- const requestedServerBase =
979
- explicitServerBase ??
980
- declaredRuntimeServerBase ??
981
- null;
982
978
  const normalizedRequestedServerBase =
983
- requestedServerBase && normalizeServerOrigin(requestedServerBase);
979
+ explicitServerBase && normalizeServerOrigin(explicitServerBase);
984
980
  const normalizedCurrentServer = normalizeServerOrigin(
985
981
  currentServer,
986
982
  );
987
- const canAutoRouteRemotely =
983
+ const canProxyToExplicitServerBase =
988
984
  !Array.isArray(userInput) &&
989
985
  !runtimeOptions?.extraTools?.length &&
990
986
  !runtimeOptions?.editingTarget &&
991
987
  !runtimeOptions?.imageConfigOverride;
992
- if (requestedServerBase && canAutoRouteRemotely) {
988
+ if (explicitServerBase && canProxyToExplicitServerBase) {
993
989
  if (
994
990
  normalizedRequestedServerBase &&
995
991
  normalizedCurrentServer &&
@@ -1048,7 +1044,7 @@ export const streamAgentChatTurnHandler = async (
1048
1044
  return rejectWithValue(message);
1049
1045
  };
1050
1046
 
1051
- const remoteResponse = await fetch(`${requestedServerBase.replace(/\/+$/, "")}/api/agent/run`, {
1047
+ const remoteResponse = await fetch(`${explicitServerBase.replace(/\/+$/, "")}/api/agent/run`, {
1052
1048
  method: "POST",
1053
1049
  headers: {
1054
1050
  "Content-Type": "application/json",
@@ -1245,6 +1241,18 @@ export const streamAgentChatTurnHandler = async (
1245
1241
  const effectiveAgentConfig = dialogMaxTokens
1246
1242
  ? { ...agentConfigForCall, max_tokens: dialogMaxTokens }
1247
1243
  : agentConfigForCall;
1244
+ const initialImageGenerationState = resolveImageGenerationStreamingState(
1245
+ effectiveAgentConfig,
1246
+ );
1247
+ const streamingMessageMetadata = {
1248
+ ...buildParallelMessageMetadata(
1249
+ agentConfigForCall,
1250
+ runtimeOptions,
1251
+ ),
1252
+ ...(initialImageGenerationState
1253
+ ? { imageGenerationState: initialImageGenerationState }
1254
+ : {}),
1255
+ };
1248
1256
 
1249
1257
  const isRespModel = isResponseAPIModel(agentConfigForCall);
1250
1258
 
@@ -1453,10 +1461,7 @@ export const streamAgentChatTurnHandler = async (
1453
1461
  thunkApi,
1454
1462
  dialogKey,
1455
1463
  parentMessageId: currentParentMessageId,
1456
- messageMetadata: buildParallelMessageMetadata(
1457
- agentConfigForCall,
1458
- runtimeOptions,
1459
- ),
1464
+ messageMetadata: streamingMessageMetadata,
1460
1465
  quickChatPerfStartedAt,
1461
1466
  });
1462
1467
  logQuickChatPerfStage(quickChatPerfStartedAt, "stream-agent-model-request-finished", {
@@ -1752,10 +1757,7 @@ export const streamAgentChatTurnHandler = async (
1752
1757
  thunkApi,
1753
1758
  dialogKey,
1754
1759
  parentMessageId: currentParentMessageId,
1755
- messageMetadata: buildParallelMessageMetadata(
1756
- agentConfigForCall,
1757
- runtimeOptions,
1758
- ),
1760
+ messageMetadata: streamingMessageMetadata,
1759
1761
  disableToolsForThisRequest,
1760
1762
  quickChatPerfStartedAt,
1761
1763
  });