nolo-cli 0.1.13 → 0.1.15

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 (321) hide show
  1. package/README.md +9 -2
  2. package/agent-runtime/hostAdapter.ts +53 -0
  3. package/agent-runtime/index.ts +28 -0
  4. package/agent-runtime/localLoop.ts +62 -0
  5. package/agent-runtime/runtimeDecision.ts +70 -0
  6. package/agent-runtime/types.ts +87 -0
  7. package/agentRunCommand.ts +104 -0
  8. package/agentRuntimeCommands.ts +139 -22
  9. package/agentRuntimeLocal.ts +7 -0
  10. package/ai/agent/_executeModel.ts +118 -0
  11. package/ai/agent/agentSlice.ts +544 -1
  12. package/ai/agent/appWorkingMemory.ts +126 -0
  13. package/ai/agent/avatarUtils.ts +24 -0
  14. package/ai/agent/buildEditingContext.ts +373 -0
  15. package/ai/agent/buildSystemPrompt.ts +532 -0
  16. package/ai/agent/cleanAgentMessages.ts +140 -0
  17. package/ai/agent/cliChatClient.ts +119 -0
  18. package/ai/agent/contextCompiler.ts +107 -0
  19. package/ai/agent/contextLayerContract.ts +44 -0
  20. package/ai/agent/createAgentSchema.ts +234 -0
  21. package/ai/agent/executeToolCall.ts +58 -0
  22. package/ai/agent/fetchAgentContexts.ts +42 -0
  23. package/ai/agent/generatePrompt.ts +3 -0
  24. package/ai/agent/getFullChatContextKeys.ts +168 -0
  25. package/ai/agent/hooks/fetchPublicAgents.ts +133 -0
  26. package/ai/agent/hooks/useAgentConfig.ts +61 -0
  27. package/ai/agent/hooks/useAgentDialog.ts +35 -0
  28. package/ai/agent/hooks/useAgentFormValidation.ts +202 -0
  29. package/ai/agent/hooks/usePublicAgents.ts +473 -0
  30. package/ai/agent/persistMessageWithFixedId.ts +37 -0
  31. package/ai/agent/planSlice.ts +259 -0
  32. package/ai/agent/referenceUtils.ts +229 -0
  33. package/ai/agent/runAgentBackground.ts +238 -0
  34. package/ai/agent/runAgentClientLoop.ts +138 -0
  35. package/ai/agent/runtimeGuidance.ts +97 -0
  36. package/ai/agent/runtimeServerBase.ts +37 -0
  37. package/ai/agent/server/fetchPublicAgents.ts +128 -0
  38. package/ai/agent/startParallelAgentStreams.ts +424 -0
  39. package/ai/agent/startupProtocol.ts +53 -0
  40. package/ai/agent/streamAgentChatTurn.ts +1299 -0
  41. package/ai/agent/streamAgentChatTurnUtils.ts +738 -0
  42. package/ai/agent/types.ts +71 -0
  43. package/ai/agent/utils/imageOutput.ts +39 -0
  44. package/ai/agent/utils/publicImageAgentMode.ts +26 -0
  45. package/ai/agent/utils/sortUtils.ts +250 -0
  46. package/ai/agent/web/referencePickerUtils.ts +146 -0
  47. package/ai/ai.locale.ts +1083 -0
  48. package/ai/chat/accumulateToolCallChunks.ts +95 -0
  49. package/ai/chat/fetchUtils.native.ts +276 -0
  50. package/ai/chat/fetchUtils.ts +153 -0
  51. package/ai/chat/inlineImageUrlsForCustomProvider.ts +117 -0
  52. package/ai/chat/parseApiError.ts +64 -0
  53. package/ai/chat/parseMultilineSSE.ts +95 -0
  54. package/ai/chat/sendOpenAICompletionsRequest.native.ts +682 -0
  55. package/ai/chat/sendOpenAICompletionsRequest.ts +712 -0
  56. package/ai/chat/sendOpenAIResponseRequest.ts +512 -0
  57. package/ai/chat/shouldUseServerProxy.ts +18 -0
  58. package/ai/chat/sseClient.native.ts +91 -0
  59. package/ai/chat/sseClient.ts +67 -0
  60. package/ai/chat/streamReader.native.ts +31 -0
  61. package/ai/chat/streamReader.ts +62 -0
  62. package/ai/chat/updateTotalUsage.ts +72 -0
  63. package/ai/context/buildReferenceContext.ts +437 -0
  64. package/ai/context/calculateContextUsage.ts +133 -0
  65. package/ai/context/retention.ts +165 -0
  66. package/ai/context/tokenUtils.ts +78 -0
  67. package/ai/index.ts +1 -1
  68. package/ai/llm/agentCapabilities.ts +74 -0
  69. package/ai/llm/calculateGeminiImageTokens.ts +57 -0
  70. package/ai/llm/deepinfra.ts +28 -0
  71. package/ai/llm/fireworks.ts +68 -0
  72. package/ai/llm/generateRequestBody.ts +165 -0
  73. package/ai/llm/getModelContextWindow.ts +84 -0
  74. package/ai/llm/getNoloKey.ts +37 -0
  75. package/ai/llm/getPricing.ts +232 -0
  76. package/ai/llm/hooks/useModelPricing.ts +75 -0
  77. package/ai/llm/imagePricing.ts +66 -0
  78. package/ai/llm/isResponseAPIModel.ts +13 -0
  79. package/ai/llm/kimi.ts +18 -0
  80. package/ai/llm/mimo.ts +71 -0
  81. package/ai/llm/mistral.ts +22 -0
  82. package/ai/llm/modelAvatar.ts +427 -0
  83. package/ai/llm/models.ts +45 -0
  84. package/ai/llm/openrouterModels.ts +141 -0
  85. package/ai/llm/providers.ts +307 -0
  86. package/ai/llm/reasoningModels.ts +28 -0
  87. package/ai/llm/types.ts +59 -0
  88. package/ai/llm/usageRequestOptions.ts +59 -0
  89. package/ai/memory/capture.ts +148 -0
  90. package/ai/memory/consolidate.ts +104 -0
  91. package/ai/memory/delete.ts +147 -0
  92. package/ai/memory/overlay.ts +84 -0
  93. package/ai/memory/query.ts +38 -0
  94. package/ai/memory/queryShared.ts +160 -0
  95. package/ai/memory/rank.ts +105 -0
  96. package/ai/memory/recentRelationshipRecap.ts +247 -0
  97. package/ai/memory/remember.ts +167 -0
  98. package/ai/memory/runtime.ts +76 -0
  99. package/ai/memory/store.ts +20 -0
  100. package/ai/memory/storeShared.ts +76 -0
  101. package/ai/memory/types.ts +46 -0
  102. package/ai/memory/understanding.ts +349 -0
  103. package/ai/memory/understandingGreeting.ts +264 -0
  104. package/ai/messages/type.ts +20 -0
  105. package/ai/policy/personalizationDialog.ts +333 -0
  106. package/ai/policy/runtimePolicy.ts +440 -0
  107. package/ai/policy/selfUpdateFields.ts +48 -0
  108. package/ai/policy/types.ts +64 -0
  109. package/ai/skills/referenceRuntime.ts +274 -0
  110. package/ai/skills/skillDiagnostics.ts +251 -0
  111. package/ai/skills/skillDocBuilder.ts +139 -0
  112. package/ai/skills/skillDocProtocol.ts +434 -0
  113. package/ai/skills/skillReferenceSummary.ts +63 -0
  114. package/ai/skills/skillSummaryMarker.ts +26 -0
  115. package/ai/token/calculatePrice.ts +546 -0
  116. package/ai/token/db.ts +98 -0
  117. package/ai/token/externalToolCost.ts +321 -0
  118. package/ai/token/hooks/useRecords.ts +65 -0
  119. package/ai/token/missingUsageEstimate.ts +42 -0
  120. package/ai/token/modelUsageQuery.ts +252 -0
  121. package/ai/token/normalizeUsage.ts +84 -0
  122. package/ai/token/openaiImageGenerationUsage.ts +56 -0
  123. package/ai/token/prepareTokenUsageData.ts +88 -0
  124. package/ai/token/query.ts +88 -0
  125. package/ai/token/queryUserTokens.ts +59 -0
  126. package/ai/token/resolveBillingTarget.ts +52 -0
  127. package/ai/token/saveTokenRecord.ts +53 -0
  128. package/ai/token/serverDialogProjection.ts +78 -0
  129. package/ai/token/serverTokenWriter.ts +143 -0
  130. package/ai/token/stats.ts +21 -0
  131. package/ai/token/tokenThunks.ts +24 -0
  132. package/ai/token/types.ts +93 -0
  133. package/ai/tools/agent/agentTools.ts +176 -0
  134. package/ai/tools/agent/agentUpdateShared.ts +311 -0
  135. package/ai/tools/agent/callAgentTool.ts +139 -0
  136. package/ai/tools/agent/createAgentTool.ts +512 -0
  137. package/ai/tools/agent/createDialogTool.ts +69 -0
  138. package/ai/tools/agent/createSkillAgentTool.ts +62 -0
  139. package/ai/tools/agent/parallelBudget.ts +221 -0
  140. package/ai/tools/agent/presets/appBuilderPreset.ts +147 -0
  141. package/ai/tools/agent/runLlmTool.ts +96 -0
  142. package/ai/tools/agent/runStreamingAgentTool.ts +73 -0
  143. package/ai/tools/agent/skillAgentArgs.ts +106 -0
  144. package/ai/tools/agent/skillAgentPreset.ts +89 -0
  145. package/ai/tools/agent/streamParallelAgentsTool.ts +122 -0
  146. package/ai/tools/agent/updateAgentTool.ts +96 -0
  147. package/ai/tools/agent/updateSelfTool.ts +113 -0
  148. package/ai/tools/amazonProductScraperTool.ts +86 -0
  149. package/ai/tools/apifyActorClient.ts +45 -0
  150. package/ai/tools/appEditGuard.ts +372 -0
  151. package/ai/tools/appReadSnapshot.ts +153 -0
  152. package/ai/tools/appTools.ts +1549 -0
  153. package/ai/tools/applyEditTool.ts +256 -0
  154. package/ai/tools/applyLineEditsTool.ts +312 -0
  155. package/ai/tools/browserTools/click.ts +33 -0
  156. package/ai/tools/browserTools/closeSession.ts +29 -0
  157. package/ai/tools/browserTools/common.ts +27 -0
  158. package/ai/tools/browserTools/openSession.ts +48 -0
  159. package/ai/tools/browserTools/readContent.ts +38 -0
  160. package/ai/tools/browserTools/selectOption.ts +46 -0
  161. package/ai/tools/browserTools/typeText.ts +42 -0
  162. package/ai/tools/category/createCategoryTool.ts +66 -0
  163. package/ai/tools/category/queryContentsByCategoryTool.ts +69 -0
  164. package/ai/tools/category/updateContentCategoryTool.ts +75 -0
  165. package/ai/tools/cfBrowserTools.ts +319 -0
  166. package/ai/tools/cfSpeechToTextTool.ts +49 -0
  167. package/ai/tools/checkEnvTool.ts +65 -0
  168. package/ai/tools/cloudflareCrawlTool.ts +289 -0
  169. package/ai/tools/codeSearchTool.ts +111 -0
  170. package/ai/tools/codeTools.ts +101 -0
  171. package/ai/tools/createDocTool.ts +132 -0
  172. package/ai/tools/createPlanTool.ts +999 -0
  173. package/ai/tools/createSkillDocTool.ts +155 -0
  174. package/ai/tools/createWorkflowTool.ts +154 -0
  175. package/ai/tools/deepseekOcrTool.ts +34 -0
  176. package/ai/tools/delayTool.ts +31 -0
  177. package/ai/tools/deleteSpacesTool.ts +325 -0
  178. package/ai/tools/deleteSpacesToolModel.ts +159 -0
  179. package/ai/tools/devReloadUtils.ts +29 -0
  180. package/ai/tools/dialogMessageSearch.ts +137 -0
  181. package/ai/tools/doctorSkillTool.ts +72 -0
  182. package/ai/tools/ecommerceScraperTool.ts +86 -0
  183. package/ai/tools/emailTools.ts +549 -0
  184. package/ai/tools/evalSkillTool.ts +92 -0
  185. package/ai/tools/exaSearchTool.ts +64 -0
  186. package/ai/tools/execBashTool.ts +379 -0
  187. package/ai/tools/executeSqlTool.ts +192 -0
  188. package/ai/tools/fetchWebpageSupport.ts +309 -0
  189. package/ai/tools/fetchWebpageTool.ts +84 -0
  190. package/ai/tools/geminiImagePreviewTool.ts +361 -0
  191. package/ai/tools/generateDocxTool.ts +215 -0
  192. package/ai/tools/googleSearchScraperTool.ts +106 -0
  193. package/ai/tools/importDataTool.ts +133 -0
  194. package/ai/tools/importSkillTool.ts +162 -0
  195. package/ai/tools/index.ts +1927 -0
  196. package/ai/tools/listFilesTool.ts +82 -0
  197. package/ai/tools/listUserSpacesTool.ts +113 -0
  198. package/ai/tools/modelUsageTools.ts +199 -0
  199. package/ai/tools/olmOcrTool.ts +34 -0
  200. package/ai/tools/openaiImageTool.ts +267 -0
  201. package/ai/tools/prepareTools.ts +23 -0
  202. package/ai/tools/readDocTool.ts +84 -0
  203. package/ai/tools/readFileTool.ts +211 -0
  204. package/ai/tools/readTool.ts +163 -0
  205. package/ai/tools/readXPostTool.ts +233 -0
  206. package/ai/tools/rememberMemoryTool.ts +84 -0
  207. package/ai/tools/remotionVideoTool.ts +151 -0
  208. package/ai/tools/searchDialogMessagesTool.ts +222 -0
  209. package/ai/tools/searchRepoTool.ts +115 -0
  210. package/ai/tools/searchWorkspaceTool.ts +259 -0
  211. package/ai/tools/skillFollowup.ts +86 -0
  212. package/ai/tools/surfWeatherTool.ts +169 -0
  213. package/ai/tools/table/addTableRowTool.ts +217 -0
  214. package/ai/tools/table/createTableTool.ts +315 -0
  215. package/ai/tools/table/rowTools.ts +366 -0
  216. package/ai/tools/table/schemaTools.ts +244 -0
  217. package/ai/tools/table/shareTableTool.ts +148 -0
  218. package/ai/tools/table/toolShared.ts +129 -0
  219. package/ai/tools/toolApiClient.ts +198 -0
  220. package/ai/tools/toolNameAliases.ts +57 -0
  221. package/ai/tools/toolResultError.ts +42 -0
  222. package/ai/tools/toolRunSlice.ts +303 -0
  223. package/ai/tools/toolSchemaCompatibility.ts +53 -0
  224. package/ai/tools/toolVisibility.ts +4 -0
  225. package/ai/tools/types.ts +20 -0
  226. package/ai/tools/uiAskChoiceTool.ts +104 -0
  227. package/ai/tools/updateContentTitleTool.ts +84 -0
  228. package/ai/tools/updateDocTool.ts +105 -0
  229. package/ai/tools/updateUserPreferenceProfileTool.ts +145 -0
  230. package/ai/tools/whisperTool.ts +77 -0
  231. package/ai/tools/writeFileTool.ts +210 -0
  232. package/ai/tools/youtubeScraperTool.ts +116 -0
  233. package/ai/tools/ziweiChartTool.ts +678 -0
  234. package/ai/types.ts +55 -0
  235. package/ai/workflow/workflowExecutor.ts +323 -0
  236. package/ai/workflow/workflowSlice.ts +73 -0
  237. package/ai/workflow/workflowTypes.ts +106 -0
  238. package/client/agentRun.test.ts +240 -0
  239. package/client/agentRun.ts +182 -19
  240. package/client/compactDialog.test.ts +238 -0
  241. package/client/localRuntimeAdapter.test.ts +135 -0
  242. package/client/localRuntimeAdapter.ts +244 -0
  243. package/client/profileConfig.test.ts +40 -0
  244. package/client/streamingOutput.test.ts +22 -0
  245. package/client/streamingOutput.ts +38 -0
  246. package/commandRegistry.ts +11 -2
  247. package/connector-experimental/index.ts +5 -0
  248. package/database/actions/cacheMergedUserData.ts +64 -0
  249. package/database/actions/common.ts +242 -0
  250. package/database/actions/deleteFile.ts +40 -0
  251. package/database/actions/fetchUserData.ts +16 -0
  252. package/database/actions/fileContent.ts +125 -0
  253. package/database/actions/patch.ts +155 -0
  254. package/database/actions/read.ts +337 -0
  255. package/database/actions/readAndWait.ts +224 -0
  256. package/database/actions/readRequestManager.ts +120 -0
  257. package/database/actions/remove.ts +94 -0
  258. package/database/actions/replication.ts +366 -0
  259. package/database/actions/upload.ts +174 -0
  260. package/database/actions/upsert.ts +56 -0
  261. package/database/actions/write.ts +126 -0
  262. package/database/client/db.native.ts +73 -0
  263. package/database/client/db.ts +51 -0
  264. package/database/client/fetchUserData.ts +61 -0
  265. package/database/client/handleError.ts +19 -0
  266. package/database/client/queryRequest.ts +21 -0
  267. package/database/config.ts +21 -0
  268. package/database/dbActionThunks.ts +1 -0
  269. package/database/dbSlice.ts +149 -0
  270. package/database/email.ts +42 -0
  271. package/database/fileRing.ts +51 -0
  272. package/database/fileSharding.ts +70 -0
  273. package/database/fileStorage.native.ts +92 -0
  274. package/database/fileStorage.ts +232 -0
  275. package/database/fileUrl.ts +34 -0
  276. package/database/hooks/useUserData.ts +489 -0
  277. package/database/index.ts +1 -0
  278. package/database/keys.ts +765 -0
  279. package/database/queryPrefixes.ts +14 -0
  280. package/database/requests.ts +443 -0
  281. package/database/runtimeServerContext.ts +35 -0
  282. package/database/server/MemoryDB.ts +76 -0
  283. package/database/server/actorAccess.ts +76 -0
  284. package/database/server/agentDelegation.ts +124 -0
  285. package/database/server/coreDataOwnership.ts +13 -0
  286. package/database/server/coreDataProxy.ts +76 -0
  287. package/database/server/cybotReadonly.ts +18 -0
  288. package/database/server/dataHandlers.ts +111 -0
  289. package/database/server/db.ts +118 -0
  290. package/database/server/dbPath.ts +20 -0
  291. package/database/server/delete.ts +499 -0
  292. package/database/server/emailRepository.ts +1480 -0
  293. package/database/server/ensureDbOpen.ts +12 -0
  294. package/database/server/fileRead.ts +337 -0
  295. package/database/server/fileService.ts +436 -0
  296. package/database/server/handleTransaction.ts +86 -0
  297. package/database/server/patch.ts +282 -0
  298. package/database/server/query.ts +138 -0
  299. package/database/server/read.ts +325 -0
  300. package/database/server/resourceAccess.ts +211 -0
  301. package/database/server/routes.ts +110 -0
  302. package/database/server/spaceMemberAuthority.ts +67 -0
  303. package/database/server/upload.ts +159 -0
  304. package/database/server/write.ts +494 -0
  305. package/database/server/writeAuthority.ts +133 -0
  306. package/database/sqliteDb.ts +46 -0
  307. package/database/table/deleteTable.ts +120 -0
  308. package/database/tenantPlacement.ts +57 -0
  309. package/database/tombstones.ts +52 -0
  310. package/database/userDataLoadDecision.ts +17 -0
  311. package/database/userDataMerge.ts +95 -0
  312. package/database/userPreferenceRegister.ts +108 -0
  313. package/database/utils/dbPath.ts +47 -0
  314. package/database/utils/ulid.native.ts +6 -0
  315. package/database/utils/ulid.ts +1 -0
  316. package/index.ts +37 -19
  317. package/localRuntimeDb.ts +28 -0
  318. package/package.json +17 -4
  319. package/runtimeModeArgs.ts +33 -0
  320. package/tui/readlineWorkspace.ts +1 -0
  321. package/tui/session.ts +22 -0
@@ -0,0 +1,69 @@
1
+ // 文件路径: ai/tools/agent/createDialogTool.ts
2
+
3
+ import type { RootState } from "app/store";
4
+ import { createDialogAction } from "chat/dialog/actions/createDialogAction";
5
+ import { streamAgentChatTurn } from "ai/agent/agentSlice";
6
+
7
+ export const createDialogFunctionSchema = {
8
+ name: "createDialog",
9
+ description:
10
+ "创建一个新的对话(Dialog),可以指定由哪个 Agent 来响应,并可选地发送第一条消息触发 Agent 立即执行。" +
11
+ "常用于:派生子任务对话、让某个专用 Agent 在后台处理问题、睡前布置任务等场景。" +
12
+ "返回 dialogId,可通过 read({ dbKey: dialogId }) 随时查看对话结果。",
13
+ parameters: {
14
+ type: "object",
15
+ properties: {
16
+ agentKey: {
17
+ type: "string",
18
+ description: "负责响应这个对话的 Agent ID(dbKey,格式如 agent-xxx)。",
19
+ },
20
+ firstMessage: {
21
+ type: "string",
22
+ description: "可选。创建对话后立即发送的第一条消息,Agent 会自动开始执行。如果不传则只创建空对话。",
23
+ },
24
+ title: {
25
+ type: "string",
26
+ description: "可选。对话标题,方便后续识别。",
27
+ },
28
+ },
29
+ required: ["agentKey"],
30
+ },
31
+ };
32
+
33
+ export const createDialogFunc = async (
34
+ args: { agentKey: string; firstMessage?: string; title?: string },
35
+ context: { getState: () => RootState; dispatch: any }
36
+ ) => {
37
+ const { agentKey, firstMessage, title } = args;
38
+ const { getState, dispatch } = context;
39
+
40
+ const dialogConfig = await createDialogAction(
41
+ {
42
+ // TODO: 后续改为 [agentKey, ...subAgents] 组合,支持多 Agent 协作
43
+ // 目前仅使用主 agentKey 作为 cybots[0]
44
+ cybots: [agentKey],
45
+ title: title ?? `Dialog with ${agentKey}`,
46
+ },
47
+ { getState, dispatch }
48
+ );
49
+
50
+ const dialogId = dialogConfig.id;
51
+
52
+ if (firstMessage) {
53
+ void dispatch(
54
+ streamAgentChatTurn({
55
+ agentKey,
56
+ userInput: firstMessage,
57
+ dialogKey: dialogConfig.dbKey,
58
+ })
59
+ );
60
+ }
61
+
62
+ return {
63
+ dialogId,
64
+ dialogKey: dialogConfig.dbKey,
65
+ message: firstMessage
66
+ ? `已创建对话并发送任务,Agent 正在后台执行。可通过 read({ dbKey: "${dialogConfig.dbKey}" }) 查看进度。`
67
+ : `已创建空对话。可通过 read({ dbKey: "${dialogConfig.dbKey}" }) 查看。`,
68
+ };
69
+ };
@@ -0,0 +1,62 @@
1
+ import { createAgentToolFunc } from "./createAgentTool";
2
+ import {
3
+ buildCreateSkillAgentArgs,
4
+ type CreateSkillAgentToolArgs,
5
+ } from "./skillAgentArgs";
6
+
7
+ export const createSkillAgentToolFunctionSchema = {
8
+ name: "createSkillAgent",
9
+ description:
10
+ "创建一个专门用于创建/评估 skill 文档协议的 Agent,支持 creator、evaluator 或二合一模式。",
11
+ parameters: {
12
+ type: "object",
13
+ properties: {
14
+ mode: {
15
+ type: "string",
16
+ enum: ["creator", "evaluator", "creator_evaluator"],
17
+ description: "要创建的 skill agent 类型。",
18
+ },
19
+ name: {
20
+ type: "string",
21
+ description: "可选:Agent 名称。",
22
+ },
23
+ model: {
24
+ type: "string",
25
+ description: "可选:覆盖默认模型。",
26
+ },
27
+ provider: {
28
+ type: "string",
29
+ description: "可选:覆盖默认 provider。",
30
+ },
31
+ isPublic: {
32
+ type: "boolean",
33
+ description: "可选:是否公开。",
34
+ },
35
+ references: {
36
+ type: "array",
37
+ description: "可选:创建后默认挂载的 references。",
38
+ items: {
39
+ type: "object",
40
+ properties: {
41
+ dbKey: { type: "string" },
42
+ title: { type: "string" },
43
+ type: { type: "string", enum: ["knowledge", "instruction", "page"] },
44
+ },
45
+ required: ["dbKey"],
46
+ },
47
+ },
48
+ linkedSpaces: {
49
+ type: "array",
50
+ items: { type: "string" },
51
+ description: "可选:额外挂载的 linked spaces。",
52
+ },
53
+ },
54
+ } as const,
55
+ };
56
+
57
+ export async function createSkillAgentToolFunc(
58
+ args: CreateSkillAgentToolArgs,
59
+ thunkApi: any
60
+ ): Promise<{ rawData: unknown; displayData: string }> {
61
+ return createAgentToolFunc(buildCreateSkillAgentArgs(args), thunkApi);
62
+ }
@@ -0,0 +1,221 @@
1
+ import { prepareTokenUsageData } from "ai/token/prepareTokenUsageData";
2
+ import type { RawUsage } from "ai/token/types";
3
+
4
+ const roundCredits = (value: number) => Number(value.toFixed(6));
5
+ const toRoundedFiniteNumber = (value: unknown): number | null =>
6
+ typeof value === "number" && Number.isFinite(value) ? roundCredits(value) : null;
7
+ const getUsageCost = (usage: unknown): number | null => {
8
+ if (!usage || typeof usage !== "object") {
9
+ return null;
10
+ }
11
+ const cost = (usage as { cost?: unknown }).cost;
12
+ return typeof cost === "number" && Number.isFinite(cost) && cost >= 0
13
+ ? roundCredits(cost)
14
+ : null;
15
+ };
16
+ const getUsageBillingServiceTier = (usage: unknown): string | null => {
17
+ if (!usage || typeof usage !== "object") {
18
+ return null;
19
+ }
20
+ const serviceTier = (usage as { billing_service_tier?: unknown }).billing_service_tier;
21
+ return typeof serviceTier === "string" && serviceTier.trim()
22
+ ? serviceTier.trim()
23
+ : null;
24
+ };
25
+
26
+ const normalizePositiveNumber = (value: unknown): number | undefined => {
27
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
28
+ return undefined;
29
+ }
30
+ return roundCredits(value);
31
+ };
32
+
33
+ export const normalizeBudgetCredits = (value: unknown): number | undefined =>
34
+ normalizePositiveNumber(value);
35
+
36
+ export interface ParallelBranchPricingInput {
37
+ usage?: unknown;
38
+ agentKey: string;
39
+ dialogId?: string | null;
40
+ agentConfig: {
41
+ id?: string;
42
+ model?: string | null;
43
+ provider?: string | null;
44
+ inputPrice?: number | null;
45
+ outputPrice?: number | null;
46
+ };
47
+ }
48
+
49
+ export interface ParallelBranchPricingResult {
50
+ spentCredits: number | null;
51
+ billedModel: string | null;
52
+ billedProvider: string | null;
53
+ billingServiceTier: string | null;
54
+ pricingError: string | null;
55
+ }
56
+
57
+ export const calculateParallelBranchPricing = (
58
+ input: ParallelBranchPricingInput
59
+ ): ParallelBranchPricingResult => {
60
+ if (!input.usage || typeof input.usage !== "object") {
61
+ return {
62
+ spentCredits: null,
63
+ billedModel: null,
64
+ billedProvider: null,
65
+ billingServiceTier: null,
66
+ pricingError: "missing usage",
67
+ };
68
+ }
69
+
70
+ const model =
71
+ typeof input.agentConfig.model === "string" && input.agentConfig.model.trim()
72
+ ? input.agentConfig.model.trim()
73
+ : null;
74
+ const provider =
75
+ typeof input.agentConfig.provider === "string" && input.agentConfig.provider.trim()
76
+ ? input.agentConfig.provider.trim()
77
+ : null;
78
+ const fallbackUsageCost = getUsageCost(input.usage);
79
+ const fallbackBillingServiceTier = getUsageBillingServiceTier(input.usage);
80
+ if (!model) {
81
+ return {
82
+ spentCredits: null,
83
+ billedModel: null,
84
+ billedProvider: null,
85
+ billingServiceTier: null,
86
+ pricingError: "missing model",
87
+ };
88
+ }
89
+
90
+ try {
91
+ const prepared = prepareTokenUsageData({
92
+ rawUsage: input.usage as RawUsage,
93
+ agentConfig: {
94
+ id: input.agentConfig.id ?? input.agentKey,
95
+ model,
96
+ ...(typeof input.agentConfig.provider === "string" &&
97
+ input.agentConfig.provider.trim()
98
+ ? { provider: input.agentConfig.provider.trim() }
99
+ : {}),
100
+ ...(typeof input.agentConfig.inputPrice === "number" &&
101
+ Number.isFinite(input.agentConfig.inputPrice)
102
+ ? { inputPrice: input.agentConfig.inputPrice }
103
+ : {}),
104
+ ...(typeof input.agentConfig.outputPrice === "number" &&
105
+ Number.isFinite(input.agentConfig.outputPrice)
106
+ ? { outputPrice: input.agentConfig.outputPrice }
107
+ : {}),
108
+ },
109
+ cybotId: input.agentKey,
110
+ dialogId: input.dialogId ?? `parallel-${input.agentKey}`,
111
+ });
112
+ const preparedCost = toRoundedFiniteNumber(prepared.tokenData.cost);
113
+ if (preparedCost != null) {
114
+ return {
115
+ spentCredits: preparedCost,
116
+ billedModel: prepared.billedModel,
117
+ billedProvider: prepared.recordProvider,
118
+ billingServiceTier: prepared.billedServiceTier ?? null,
119
+ pricingError: null,
120
+ };
121
+ }
122
+
123
+ if (fallbackUsageCost != null) {
124
+ return {
125
+ spentCredits: fallbackUsageCost,
126
+ billedModel: prepared.billedModel ?? model,
127
+ billedProvider: prepared.recordProvider ?? provider,
128
+ billingServiceTier:
129
+ prepared.billedServiceTier ?? fallbackBillingServiceTier ?? null,
130
+ pricingError: null,
131
+ };
132
+ }
133
+
134
+ return {
135
+ spentCredits: null,
136
+ billedModel: null,
137
+ billedProvider: null,
138
+ billingServiceTier: null,
139
+ pricingError: "invalid cost",
140
+ };
141
+ } catch (error: any) {
142
+ if (fallbackUsageCost != null) {
143
+ return {
144
+ spentCredits: fallbackUsageCost,
145
+ billedModel: model,
146
+ billedProvider: provider,
147
+ billingServiceTier: fallbackBillingServiceTier,
148
+ pricingError: null,
149
+ };
150
+ }
151
+ return {
152
+ spentCredits: null,
153
+ billedModel: null,
154
+ billedProvider: null,
155
+ billingServiceTier: null,
156
+ pricingError: error?.message || String(error),
157
+ };
158
+ }
159
+ };
160
+
161
+ export interface ParallelCostSummary {
162
+ spentCredits: number;
163
+ pricedBranches: number;
164
+ unpricedBranches: number;
165
+ }
166
+
167
+ export interface ParallelBudgetSummary extends ParallelCostSummary {
168
+ budgetCredits: number;
169
+ remainingCredits: number;
170
+ exhausted: boolean;
171
+ }
172
+
173
+ export const summarizeParallelCosts = (
174
+ results: Array<{ spentCredits?: number | null; ok?: boolean }>
175
+ ): ParallelCostSummary => {
176
+ const spentCredits = roundCredits(
177
+ results.reduce(
178
+ (sum, item) =>
179
+ sum +
180
+ (typeof item.spentCredits === "number" && Number.isFinite(item.spentCredits)
181
+ ? item.spentCredits
182
+ : 0),
183
+ 0
184
+ )
185
+ );
186
+
187
+ return {
188
+ spentCredits,
189
+ pricedBranches: results.filter(
190
+ (item) => typeof item.spentCredits === "number" && Number.isFinite(item.spentCredits)
191
+ ).length,
192
+ unpricedBranches: results.filter(
193
+ (item) =>
194
+ item.ok &&
195
+ (item.spentCredits == null ||
196
+ (typeof item.spentCredits === "number" && !Number.isFinite(item.spentCredits)))
197
+ ).length,
198
+ };
199
+ };
200
+
201
+ export const summarizeParallelBudget = (input: {
202
+ budgetCredits?: number;
203
+ results: Array<{ spentCredits?: number | null; ok?: boolean }>;
204
+ }): ParallelBudgetSummary | null => {
205
+ const budgetCredits = normalizePositiveNumber(input.budgetCredits);
206
+ if (budgetCredits === undefined) {
207
+ return null;
208
+ }
209
+
210
+ const costSummary = summarizeParallelCosts(input.results);
211
+ const remainingCredits = roundCredits(
212
+ Math.max(0, budgetCredits - costSummary.spentCredits)
213
+ );
214
+
215
+ return {
216
+ ...costSummary,
217
+ budgetCredits,
218
+ remainingCredits,
219
+ exhausted: remainingCredits <= 0,
220
+ };
221
+ };
@@ -0,0 +1,147 @@
1
+ /**
2
+ * App Builder 预设:面向非技术用户的网站型小应用构建助手配置
3
+ * 用途:在 AgentForm 中预填充,或通过 createAgent 工具一键创建
4
+ */
5
+ import { FIREWORKS_KIMI_LATEST_MODEL } from "ai/llm/kimi";
6
+
7
+ export const APP_BUILDER_PRESET = {
8
+ name: "App Builder",
9
+ introduction: "帮你把想法变成真正可以访问的网站型小应用,无需任何编程知识",
10
+ model: FIREWORKS_KIMI_LATEST_MODEL,
11
+ provider: "fireworks",
12
+ inputPrice: 7.6,
13
+ outputPrice: 32,
14
+ useServerProxy: true,
15
+ greeting:
16
+ `你好!我是 App Builder 🚀
17
+
18
+ **如果你想改这个应用**,直接告诉我要改什么就行——
19
+ • "把首页改得更温柔一点"
20
+ • "加一个预约入口"
21
+ • "让博客页更适合手机阅读"
22
+
23
+ 我会自动读取现有代码、修改并重新发布,你不需要动任何代码。
24
+
25
+ **如果你想新建一个应用**,直接描述你想做的网站或小应用,我来帮你构建并生成可访问的链接。
26
+
27
+ 比如:个人品牌站、博客 + AI 分身、咨询预约页、作品集站、轻互动工具……`,
28
+ tools: [
29
+ "appPreflight",
30
+ "appDeploy",
31
+ "appList",
32
+ "appDelete",
33
+ "appRead",
34
+ "openAIGptImage",
35
+ "createTable",
36
+ "addTableRow",
37
+ "addTableRows",
38
+ "queryTableRows",
39
+ "updateTableRow",
40
+ "deleteTableRow",
41
+ ],
42
+ prompt: `你是一个应用构建助手,专门帮助没有任何编程经验的用户创建和管理 Web 应用。
43
+
44
+ ## 工作方式
45
+
46
+ 1. **理解需求**:用简单的对话了解用户想要什么,最多问 1-2 个关键问题,不要追问太多技术细节
47
+ 2. **自动构建**:根据用户描述,自动生成代码并调用部署工具,用户不需要看到任何代码
48
+ 3. **给出结果**:部署成功后,立即告诉用户可以访问的链接
49
+ 4. **持续迭代**:用户说"帮我加个功能"或"改一下样式",先用 appList 找到目标应用,再用 appRead 读取现有代码;一旦拿到 appId,后续修改和重发都必须复用这个 appId
50
+ 5. **管理应用**:用户问"我有哪些应用",先调用 appList;用户说"删掉它"时,也先从 appList 确认目标 appId,再按 appId 删除,不要靠 name 兜底
51
+ 6. **先预检再部署**:生成或修改完代码后,先调用 \`appPreflight\` 看问题;只有预检通过后再调用 \`appDeploy\`
52
+ 7. **收到 repairPlan 就直接修**:如果 \`appPreflight\` 或 \`appDeploy\` 返回 \`repairPlan\` / \`issues\`,立即基于当前代码做定点修复并重新预检,不要先问用户要不要修,也不要整页重写
53
+ 8. **遇到通道异常就止损**:如果工具返回 HTML / 非 JSON / transport failure / \`retryable=false\`,停止自动部署重试;这代表当前是平台接口异常,不是代码问题
54
+ 9. **看到部署产物先止损**:如果 \`appRead\` 读出来的是 HTML 壳、importmap、压缩 bundle,或明显不像原始源码文件,说明当前拿到的更像部署产物而不是可维护源码。此时如果用户只是想“小改一处”,不要静默整站重写;必须先告诉用户“当前缺少原始源码快照,继续修改更像整体重建”,得到确认后再继续。
55
+ 10. **视觉微调默认走设计系统**:用户说“字大一点”“颜色柔和一点”“卡片圆一点”这类小改动时,优先修改现有主题 token / design system;如果当前应用还没有,就先补一层最小共享 token(颜色、字号层级、间距、圆角、阴影),再基于 token 调整,不要顺手重做整页结构。
56
+ 11. **项目素材直接出图**:如果用户要首页插画、海报、封面、功能配图、活动横幅、按钮图标草图等视觉素材,优先调用 \`openAIGptImage\` 生成或改图,再把产物接入当前应用;不要只给文案描述。
57
+
58
+ ## 对话风格
59
+
60
+ - 语气轻松友好,避免所有技术术语(不说 Worker、JavaScript、API、部署等词)
61
+ - 部署成功后,用 1-2 句话说明应用能做什么、怎么使用
62
+ - 如果用户描述模糊,举例说明你能做什么,让用户选择或细化
63
+ - **绝不把代码展示给用户**,除非用户明确说"我想看代码"
64
+ - 优先把需求收敛成“内容驱动的网站型小应用”:个人品牌站、博客 + AI 助手、咨询/预约站、作品集、知识站、轻互动工具
65
+
66
+ ## 技术规范(内部遵守,不暴露给用户)
67
+
68
+ 简单应用可以直接生成 \`export default { fetch }\`。
69
+ 复杂交互、图表、组件化界面优先使用 React SPA 模式:调用 \`appDeploy\` 时传 \`framework: "react-spa"\` 和 \`files\`,推荐至少包含 \`main.tsx\` 与 \`App.tsx\`。
70
+ 严禁把 React 组件直接塞进 \`code\` 字段当单文件 Worker 部署;只要出现 \`import React\`、\`react-dom/client\`、\`createRoot\`、JSX 组件树,就必须走 \`framework: "react-spa"\` + \`files\`。
71
+ 如果上游临时生成的是 \`pages\` 字段,可直接原样传给 \`appDeploy\`,系统会兼容成 \`files\`;但你在新回复里应优先自己使用 \`files\` 命名。
72
+ React SPA 当前优先支持这些内置依赖:\`react\`、\`react-dom/client\`、\`react-icons/lu\`、\`echarts\`、\`echarts-for-react\`、\`docx\`、\`@xyflow/react\`、\`three\`、\`@react-three/fiber\`、\`@react-three/drei\`、\`leaflet\`、\`react-leaflet\`、\`xlsx\`、\`d3\`、\`recharts\`、\`dayjs\`。
73
+ React SPA 暂不使用 CSS 文件 import;优先用内联样式、style 对象或组件内 style 标签。像 flow / three 这类库如果默认文档依赖外部 CSS,请直接在应用内补最小必要样式,不要写 \`import "./x.css"\`。leaflet 的 CSS 会由平台自动注入,无需手动 import。
74
+
75
+ **设计系统与小改动纪律**:
76
+ - 新建 React SPA 时,默认先建立一层轻量设计系统(如 \`theme\` / \`tokens\` / \`designSystem\` 对象),至少统一:\`colors\`、\`typography\`、\`spacing\`、\`radius\`、\`shadow\`。
77
+ - 如果现有应用已经有主题变量、token、共享样式常量或 design system,优先沿用和扩展,不要再平行创建第二套。
78
+ - 如果现有应用还是旧写法:样式值直接硬编码在多个组件 / 内联 style / 重复常量里,而用户需求又是字体、颜色、间距、圆角、阴影这类视觉微调,默认先做一次**最小设计系统迁移**:把这批视觉值抽到一层很薄的 \`tokens\` / \`theme\` 对象(必要时可新增 \`tokens.ts\`),再让当前页面消费它。除非用户明确要求“只改数字不要重构”,否则不要继续在旧代码上追加更多分散硬编码。
79
+ - 用户只要求调整字体大小、字重、颜色、圆角、阴影、间距等视觉参数时,优先改 token 或当前命中的局部组件;不要顺手改布局、组件树、文案、数据流、路由或整套页面结构。
80
+ - 如果只是局部视觉修改,尽量把改动收敛在命中的 1-3 个文件;非必要不要重命名组件、改文件结构或大面积重新格式化。
81
+ - 新增页面或模块时,也应消费同一套 token,避免不同页面各自写一套颜色和字号。
82
+
83
+ **react-icons/lu 图标使用规范(违反会部署失败)**:
84
+ - 只能使用 \`react-icons/lu\` 中实际存在的图标,如 \`LuCode\`、\`LuMap\`、\`LuChart\`、\`LuSearch\`、\`LuSettings\`、\`LuStar\`
85
+ - 常见错误:\`LuCode2\`(不存在,应用 \`LuCode\`)、\`LuGithub\`(不存在,用 \`LuGitBranch\`)
86
+ - 不确定时优先用基础图标:\`LuCircle\`、\`LuCheck\`、\`LuX\`、\`LuPlus\`、\`LuMinus\`、\`LuInfo\`、\`LuArrowRight\`
87
+ - 每次使用图标前确认名称已知存在,不要猜测或推断变体名称
88
+
89
+ 构建要求:
90
+ - 响应式设计,手机和电脑都正常显示
91
+ - 简洁现代的中文界面(用户未指定语言时默认中文)
92
+ - 对计算/工具类应用:优先产出可直接访问的页面;复杂页面优先 React SPA
93
+ - 对数据接口:返回规范 JSON,设置正确的 Content-Type
94
+ - 代码质量:干净、无注释堆砌、运行稳定
95
+
96
+ **大数据文件处理规范**:
97
+ - 绝对禁止把大型数据(JSON 数组、GeoJSON、CSV 解析结果等超过 50KB 的数据)直接内嵌到代码里作为常量
98
+ - 用户通过对话上传的文件已存储在 nolo.chat,必须通过运行时 fetch 加载,URL 格式为:\`https://nolo.chat/api/database/file/content/{fileKey}\`
99
+ - 对话中提到"用这个文件"/"用我上传的数据"时,先从消息历史或 appRead 里找 fileKey,用 fetch 加载,不要重新内嵌数据
100
+ - 示例:\`const data = await fetch("https://nolo.chat/api/database/file/content/file-b2e06f801f-01XXXXX").then(r => r.json())\`
101
+ - 此 URL 已开放 CORS,任何域名部署的应用都可以直接访问,无需鉴权
102
+
103
+ 部署时:
104
+ - name 参数使用简洁的英文或拼音(如 brand-home、tarot-blog)
105
+ - 默认发布到平台托管地址(nolo.chat/apps/{appId}/),这是用户分享给别人的链接
106
+ - 更新应用时必须传入 appId,避免重复创建新应用
107
+ - 读取和删除应用时必须使用 appId;如果还没有 appId,就先调用 appList 找到目标应用
108
+ - 一旦通过 appList / appRead / appDeploy 拿到 appId,就把它当成后续操作的主标识
109
+ - 如果现有应用是 React SPA,修改时继续沿用 React SPA + files,不要退回单文件 Worker
110
+ - 如果 \`appRead\` 结果更像部署后的 bundle / HTML 壳,而不是源文件,不要假装自己拿到了可维护源码;这种情况下默认先提示用户风险,而不是直接覆盖整个应用
111
+ - React SPA 首次部署前,先调用 \`appPreflight\`;重点检查:是否传了 \`files\`、是否包含 \`main.tsx\` 与 \`App.tsx\`、是否误用了 \`code\`
112
+ - 如果首次部署失败,尝试调整代码重新部署,给用户友好的提示
113
+ - 如果工具返回了 \`repairPlan\`:
114
+ - 严格按 repairPlan 只修改命中的文件 / 依赖 / 图标 / 入口,不要为了省事重建整个应用
115
+ - 默认继续在当前轮自动修复,不需要再次征求用户确认
116
+ - 修完后必须重新 \`appPreflight\`,通过后再 \`appDeploy\`
117
+ - 如果工具返回 HTML 页面、非 JSON、transport failure 或 \`retryable=false\`:
118
+ - 立即停止自动 \`appDeploy\` / \`appPreflight\` 重试
119
+ - 不要把这种错误误判成图标/依赖/入口问题
120
+ - 直接告诉用户当前是平台部署通道异常,建议稍后再试
121
+
122
+ 表单/提交类功能:
123
+ - 如果用户要做博客留言、联系表单、预约申请、订阅邮箱、反馈收集这类“收集记录”的功能,优先使用表工具,不要自己发明 JSON 文件存储结构。
124
+ - 先调用 \`createTable\` 创建表,再把返回结果中的 \`tenantId\` 和 \`tableId\` 记住,随后让应用代码直接调用现有表接口(如 \`/api/table/add-row\`、\`/api/table/query-rows\`)。
125
+ - 当前阶段允许把 \`tenantId\` 和 \`tableId\` 直接写进应用代码配置中;这是最小实现,目的是先把功能跑通。
126
+ - 但在生成代码时,**必须在这两个字段附近添加简短注释**,明确说明:
127
+ 1. 这里直接暴露了 \`tenantId/tableId\`,当前是最小实现;
128
+ 2. 后续应替换为更安全的服务端映射或 app 级数据接口;
129
+ 3. 当前表接口默认按用户自己可写模型工作,后续应补充额外权限控制。
130
+ - **不要**把现有表接口直接当成公开留言/公开评论入口;未登录访客提交、公开写入、限流和防滥用策略需要后续单独设计。
131
+ - 因此当前阶段更适合:用户自己管理的数据后台、登录后提交、站长自己录入或内部运营使用;不适合直接上线公开评论区。
132
+ - 如果是博客应用,优先支持这些轻数据能力:评论/留言、订阅邮箱、联系反馈;文章正文、封面图、插图等内容资产优先继续使用文件。
133
+
134
+ ## 示例应答模板
135
+
136
+ 部署成功后:
137
+ "✅ 你的应用已经好了!
138
+
139
+ 🔗 访问链接:[URL]
140
+
141
+ 这个应用可以帮你 [一句话功能描述],直接打开链接就能使用,也可以把链接分享给任何人。
142
+
143
+ 想要修改或添加功能,直接告诉我就行!"
144
+ `,
145
+ } as const;
146
+
147
+ export type AppBuilderPreset = typeof APP_BUILDER_PRESET;
@@ -0,0 +1,96 @@
1
+ // 文件路径: ai/tools/agent/runLlmTool.ts
2
+
3
+ /**
4
+ * runLlm 工具
5
+ *
6
+ * 单轮 LLM 调用,不加载 Agent 的 references(知识库),不触发多轮 tool loop。
7
+ * 工具列表和系统提示均可在调用时覆盖 Agent 的默认配置。
8
+ *
9
+ * 与 callAgent 的区别:
10
+ * - runLlm:1 轮回复,不加载知识库;可携带工具但不会循环调用,更快且可预期
11
+ * - callAgent:可能多轮(agent 内部有 tool loop),带完整 agent 上下文
12
+ */
13
+
14
+ import { runLlm } from "ai/agent/agentSlice";
15
+
16
+ export const runLlmFunctionSchema = {
17
+ name: "runLlm",
18
+ description:
19
+ "对指定模型发起一次单轮 LLM 调用并返回结果。" +
20
+ "不加载 Agent 知识库(references),适合摘要、分类、格式化、翻译等纯文本处理任务。" +
21
+ "可选择注入临时系统提示或覆盖工具列表。",
22
+ parameters: {
23
+ type: "object",
24
+ properties: {
25
+ agentKey: {
26
+ type: "string",
27
+ description:
28
+ "要使用的模型配置 ID。若不填,使用当前对话绑定的默认模型。",
29
+ },
30
+ userInput: {
31
+ type: "string",
32
+ description: "发送给模型的提示词或问题。",
33
+ },
34
+ systemPrompt: {
35
+ type: "string",
36
+ description:
37
+ "可选。临时系统提示,会覆盖 Agent 原有配置中的 prompt。适合临时调整模型行为或角色。",
38
+ },
39
+ tools: {
40
+ type: "array",
41
+ items: { type: "string" },
42
+ description:
43
+ "可选。工具 ID 列表,覆盖 Agent 默认配置的工具集。传空数组则禁用所有工具。",
44
+ },
45
+ },
46
+ required: ["userInput"],
47
+ },
48
+ };
49
+
50
+ interface RunLlmToolArgs {
51
+ agentKey?: string;
52
+ userInput: string;
53
+ systemPrompt?: string;
54
+ tools?: string[];
55
+ }
56
+
57
+ export async function runLlmToolFunc(
58
+ args: RunLlmToolArgs,
59
+ thunkApi: any,
60
+ _context?: { parentMessageId: string }
61
+ ): Promise<{ rawData: any; displayData?: string }> {
62
+ const { agentKey, userInput, systemPrompt, tools } = args;
63
+
64
+ if (!userInput?.trim()) {
65
+ throw new Error("runLlm: 缺少 userInput 参数。");
66
+ }
67
+
68
+ const { dispatch } = thunkApi;
69
+
70
+ try {
71
+ const result = await dispatch(
72
+ runLlm({
73
+ agentKey,
74
+ content: userInput,
75
+ isStreaming: false,
76
+ ...(systemPrompt !== undefined && { systemPromptOverride: systemPrompt }),
77
+ ...(tools !== undefined && { toolsOverride: tools }),
78
+ })
79
+ ).unwrap();
80
+
81
+ // 取前 60 字作为 header 摘要
82
+ const preview = typeof result === "string"
83
+ ? result.slice(0, 60) + (result.length > 60 ? "…" : "")
84
+ : "";
85
+
86
+ return {
87
+ rawData: { result, userInput },
88
+ displayData: preview || "✅ runLlm 完成",
89
+ };
90
+ } catch (e: any) {
91
+ const msg = e?.message || String(e);
92
+ throw new Error(`runLlm 调用失败: ${msg}`);
93
+ }
94
+ }
95
+
96
+
@@ -0,0 +1,73 @@
1
+ // 路径: ai/tools/agent/runStreamingAgentTool.ts
2
+
3
+ /**
4
+ * [Schema] 定义 'runStreamingAgent' 工具的结构,供 LLM 调用。
5
+ *
6
+ * 主要用于用户希望立刻看到回复的临时调用,无法后台运行。
7
+ * 调用后 Agent 的输出会以流式方式实时呈现给用户,适合需要即时反馈的场景。
8
+ *
9
+ * 注意:
10
+ * - 这里只是一个「数据工具」:返回要调用的 Agent 信息,不直接发起流式调用。
11
+ * - 真正的 streamAgentChatTurn 在 chat/messages/toolThunks.ts 的 handleToolCalls 里触发,
12
+ * 这样就可以做到:
13
+ * 1)先写标准的 tool 消息(符合 OpenAI 消息格式)
14
+ * 2)再启动一个生命周期独立的 streamAgentChatTurn
15
+ */
16
+ export const runStreamingAgentFunctionSchema = {
17
+ name: "runStreamingAgent",
18
+ description:
19
+ "准备调用一个指定的 Agent (智能代理),并以流式方式处理用户输入。该工具本身只返回要调用的 Agent 信息,实际流式调用由系统在工具执行后发起。",
20
+ parameters: {
21
+ type: "object",
22
+ properties: {
23
+ agentKey: {
24
+ type: "string",
25
+ description: "要运行的 Agent 的唯一标识符 (Key)。",
26
+ },
27
+ userInput: {
28
+ type: "string",
29
+ description: "要发送给该 Agent 的用户输入或问题。",
30
+ },
31
+ serverBase: {
32
+ type: "string",
33
+ description:
34
+ "可选。目标 Agent 所在的 nolo server origin,例如 Windows 机器通过 Cloudflare 暴露的 https://win.example.com。" +
35
+ "跨域目标必须由服务端 AGENT_TOOL_ALLOWED_SERVER_BASES 明确放行。" +
36
+ "如果目标 Agent 记录声明了 delegation.serverBase / runtimeServerBase,服务端会在未显式传入时自动路由。",
37
+ },
38
+ },
39
+ required: ["agentKey", "userInput"],
40
+ },
41
+ };
42
+
43
+ /**
44
+ * [Executor] 'runStreamingAgent' 工具执行函数。
45
+ *
46
+ * - 不直接发起 streamAgentChatTurn。
47
+ * - 返回 { agentKey, userInput },供上层在写完 tool 消息后再启动真正的流式 Agent 调用。
48
+ */
49
+ export async function runStreamingAgentFunc(
50
+ args: { agentKey: string; userInput: string; serverBase?: string },
51
+ _thunkApi: any,
52
+ _context?: { parentMessageId: string }
53
+ ): Promise<{ rawData: any; displayData: string }> {
54
+ const { agentKey, userInput, serverBase } = args;
55
+
56
+ if (!agentKey) {
57
+ throw new Error("调用 'runStreamingAgent' 失败:缺少 'agentKey' 参数。");
58
+ }
59
+ if (!userInput) {
60
+ throw new Error("调用 'runStreamingAgent' 失败:缺少 'userInput' 参数。");
61
+ }
62
+
63
+ // 这里只返回调用参数,由 handleToolCalls 决定何时真正发起流式调用
64
+ const rawData = {
65
+ agentKey,
66
+ userInput,
67
+ ...(serverBase ? { serverBase } : {}),
68
+ };
69
+
70
+ const displayData = `将调用 Agent(${agentKey}) 执行一轮流式对话`;
71
+
72
+ return { rawData, displayData };
73
+ }