nolo-cli 0.1.10 → 0.1.12

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 (232) hide show
  1. package/README.md +0 -32
  2. package/agentRuntimeCommands.ts +1 -1
  3. package/client/compactDialog.ts +2 -5
  4. package/commandRegistry.ts +2 -2
  5. package/machineCommands.ts +28 -3
  6. package/package.json +5 -25
  7. package/ai/agent/_executeModel.ts +0 -118
  8. package/ai/agent/agentSlice.ts +0 -525
  9. package/ai/agent/appWorkingMemory.ts +0 -126
  10. package/ai/agent/avatarUtils.ts +0 -24
  11. package/ai/agent/buildEditingContext.ts +0 -373
  12. package/ai/agent/buildSystemPrompt.ts +0 -532
  13. package/ai/agent/cleanAgentMessages.ts +0 -140
  14. package/ai/agent/cliChatClient.ts +0 -119
  15. package/ai/agent/contextCompiler.ts +0 -107
  16. package/ai/agent/contextLayerContract.ts +0 -44
  17. package/ai/agent/createAgentSchema.ts +0 -234
  18. package/ai/agent/executeToolCall.ts +0 -58
  19. package/ai/agent/fetchAgentContexts.ts +0 -42
  20. package/ai/agent/generatePrompt.ts +0 -3
  21. package/ai/agent/getFullChatContextKeys.ts +0 -168
  22. package/ai/agent/hooks/fetchPublicAgents.ts +0 -133
  23. package/ai/agent/hooks/useAgentConfig.ts +0 -61
  24. package/ai/agent/hooks/useAgentDialog.ts +0 -35
  25. package/ai/agent/hooks/useAgentFormValidation.ts +0 -202
  26. package/ai/agent/hooks/usePublicAgents.ts +0 -473
  27. package/ai/agent/persistMessageWithFixedId.ts +0 -37
  28. package/ai/agent/planSlice.ts +0 -259
  29. package/ai/agent/referenceUtils.ts +0 -229
  30. package/ai/agent/runAgentBackground.ts +0 -238
  31. package/ai/agent/runAgentClientLoop.ts +0 -138
  32. package/ai/agent/runtimeGuidance.ts +0 -97
  33. package/ai/agent/runtimeServerBase.ts +0 -37
  34. package/ai/agent/server/fetchPublicAgents.ts +0 -128
  35. package/ai/agent/startParallelAgentStreams.ts +0 -424
  36. package/ai/agent/startupProtocol.ts +0 -53
  37. package/ai/agent/streamAgentChatTurn.ts +0 -1278
  38. package/ai/agent/streamAgentChatTurnUtils.ts +0 -738
  39. package/ai/agent/types.ts +0 -71
  40. package/ai/agent/utils/imageOutput.ts +0 -33
  41. package/ai/agent/utils/sortUtils.ts +0 -250
  42. package/ai/agent/web/referencePickerUtils.ts +0 -146
  43. package/ai/ai.locale.ts +0 -1079
  44. package/ai/chat/accumulateToolCallChunks.ts +0 -95
  45. package/ai/chat/fetchUtils.native.ts +0 -276
  46. package/ai/chat/fetchUtils.ts +0 -153
  47. package/ai/chat/parseApiError.ts +0 -64
  48. package/ai/chat/parseMultilineSSE.ts +0 -95
  49. package/ai/chat/sendOpenAICompletionsRequest.native.ts +0 -682
  50. package/ai/chat/sendOpenAICompletionsRequest.ts +0 -703
  51. package/ai/chat/sendOpenAIResponseRequest.ts +0 -491
  52. package/ai/chat/shouldUseServerProxy.ts +0 -18
  53. package/ai/chat/sseClient.native.ts +0 -91
  54. package/ai/chat/sseClient.ts +0 -67
  55. package/ai/chat/streamReader.native.ts +0 -31
  56. package/ai/chat/streamReader.ts +0 -62
  57. package/ai/chat/updateTotalUsage.ts +0 -72
  58. package/ai/context/buildReferenceContext.ts +0 -437
  59. package/ai/context/calculateContextUsage.ts +0 -133
  60. package/ai/context/retention.ts +0 -165
  61. package/ai/context/tokenUtils.ts +0 -78
  62. package/ai/index.ts +0 -1
  63. package/ai/llm/calculateGeminiImageTokens.ts +0 -57
  64. package/ai/llm/deepinfra.ts +0 -28
  65. package/ai/llm/fireworks.ts +0 -50
  66. package/ai/llm/generateRequestBody.ts +0 -165
  67. package/ai/llm/getModelContextWindow.ts +0 -84
  68. package/ai/llm/getNoloKey.ts +0 -31
  69. package/ai/llm/getPricing.ts +0 -199
  70. package/ai/llm/hooks/useModelPricing.ts +0 -75
  71. package/ai/llm/imagePricing.ts +0 -40
  72. package/ai/llm/isResponseAPIModel.ts +0 -13
  73. package/ai/llm/mimo.ts +0 -71
  74. package/ai/llm/mistral.ts +0 -22
  75. package/ai/llm/modelAvatar.ts +0 -427
  76. package/ai/llm/models.ts +0 -45
  77. package/ai/llm/openrouterModels.ts +0 -269
  78. package/ai/llm/providers.ts +0 -306
  79. package/ai/llm/reasoningModels.ts +0 -28
  80. package/ai/llm/types.ts +0 -59
  81. package/ai/llm/usageRequestOptions.ts +0 -59
  82. package/ai/memory/capture.ts +0 -148
  83. package/ai/memory/consolidate.ts +0 -104
  84. package/ai/memory/delete.ts +0 -147
  85. package/ai/memory/overlay.ts +0 -84
  86. package/ai/memory/query.ts +0 -38
  87. package/ai/memory/queryShared.ts +0 -160
  88. package/ai/memory/rank.ts +0 -105
  89. package/ai/memory/recentRelationshipRecap.ts +0 -249
  90. package/ai/memory/remember.ts +0 -167
  91. package/ai/memory/runtime.ts +0 -76
  92. package/ai/memory/store.ts +0 -20
  93. package/ai/memory/storeShared.ts +0 -76
  94. package/ai/memory/types.ts +0 -46
  95. package/ai/memory/understanding.ts +0 -349
  96. package/ai/memory/understandingGreeting.ts +0 -264
  97. package/ai/messages/type.ts +0 -20
  98. package/ai/policy/personalizationDialog.ts +0 -333
  99. package/ai/policy/runtimePolicy.ts +0 -440
  100. package/ai/policy/selfUpdateFields.ts +0 -48
  101. package/ai/policy/types.ts +0 -64
  102. package/ai/skills/referenceRuntime.ts +0 -274
  103. package/ai/skills/skillDiagnostics.ts +0 -251
  104. package/ai/skills/skillDocBuilder.ts +0 -139
  105. package/ai/skills/skillDocProtocol.ts +0 -434
  106. package/ai/skills/skillReferenceSummary.ts +0 -63
  107. package/ai/skills/skillSummaryMarker.ts +0 -26
  108. package/ai/token/calculatePrice.ts +0 -544
  109. package/ai/token/db.ts +0 -98
  110. package/ai/token/externalToolCost.ts +0 -330
  111. package/ai/token/hooks/useRecords.ts +0 -65
  112. package/ai/token/missingUsageEstimate.ts +0 -42
  113. package/ai/token/modelUsageQuery.ts +0 -252
  114. package/ai/token/normalizeUsage.ts +0 -84
  115. package/ai/token/openaiImageGenerationUsage.ts +0 -56
  116. package/ai/token/prepareTokenUsageData.ts +0 -88
  117. package/ai/token/query.ts +0 -88
  118. package/ai/token/queryUserTokens.ts +0 -59
  119. package/ai/token/resolveBillingTarget.ts +0 -52
  120. package/ai/token/saveTokenRecord.ts +0 -53
  121. package/ai/token/serverDialogProjection.ts +0 -78
  122. package/ai/token/serverTokenWriter.ts +0 -143
  123. package/ai/token/stats.ts +0 -21
  124. package/ai/token/tokenThunks.ts +0 -24
  125. package/ai/token/types.ts +0 -93
  126. package/ai/tools/agent/agentTools.ts +0 -176
  127. package/ai/tools/agent/agentUpdateShared.ts +0 -311
  128. package/ai/tools/agent/callAgentTool.ts +0 -139
  129. package/ai/tools/agent/createAgentTool.ts +0 -512
  130. package/ai/tools/agent/createDialogTool.ts +0 -69
  131. package/ai/tools/agent/createSkillAgentTool.ts +0 -62
  132. package/ai/tools/agent/parallelBudget.ts +0 -221
  133. package/ai/tools/agent/presets/appBuilderPreset.ts +0 -145
  134. package/ai/tools/agent/runLlmTool.ts +0 -96
  135. package/ai/tools/agent/runStreamingAgentTool.ts +0 -73
  136. package/ai/tools/agent/skillAgentArgs.ts +0 -106
  137. package/ai/tools/agent/skillAgentPreset.ts +0 -89
  138. package/ai/tools/agent/streamParallelAgentsTool.ts +0 -122
  139. package/ai/tools/agent/updateAgentTool.ts +0 -96
  140. package/ai/tools/agent/updateSelfTool.ts +0 -113
  141. package/ai/tools/amazonProductScraperTool.ts +0 -86
  142. package/ai/tools/apifyActorClient.ts +0 -45
  143. package/ai/tools/appEditGuard.ts +0 -372
  144. package/ai/tools/appReadSnapshot.ts +0 -153
  145. package/ai/tools/appTools.ts +0 -1549
  146. package/ai/tools/applyEditTool.ts +0 -256
  147. package/ai/tools/applyLineEditsTool.ts +0 -312
  148. package/ai/tools/browserTools/click.ts +0 -33
  149. package/ai/tools/browserTools/closeSession.ts +0 -29
  150. package/ai/tools/browserTools/common.ts +0 -27
  151. package/ai/tools/browserTools/openSession.ts +0 -48
  152. package/ai/tools/browserTools/readContent.ts +0 -38
  153. package/ai/tools/browserTools/selectOption.ts +0 -46
  154. package/ai/tools/browserTools/typeText.ts +0 -42
  155. package/ai/tools/category/createCategoryTool.ts +0 -66
  156. package/ai/tools/category/queryContentsByCategoryTool.ts +0 -69
  157. package/ai/tools/category/updateContentCategoryTool.ts +0 -75
  158. package/ai/tools/cfBrowserTools.ts +0 -319
  159. package/ai/tools/cfSpeechToTextTool.ts +0 -49
  160. package/ai/tools/checkEnvTool.ts +0 -65
  161. package/ai/tools/cloudflareCrawlTool.ts +0 -289
  162. package/ai/tools/codeSearchTool.ts +0 -111
  163. package/ai/tools/codeTools.ts +0 -101
  164. package/ai/tools/createDocTool.ts +0 -132
  165. package/ai/tools/createPlanTool.ts +0 -999
  166. package/ai/tools/createSkillDocTool.ts +0 -155
  167. package/ai/tools/createWorkflowTool.ts +0 -154
  168. package/ai/tools/deepseekOcrTool.ts +0 -34
  169. package/ai/tools/delayTool.ts +0 -31
  170. package/ai/tools/deleteSpacesTool.ts +0 -325
  171. package/ai/tools/deleteSpacesToolModel.ts +0 -159
  172. package/ai/tools/devReloadUtils.ts +0 -29
  173. package/ai/tools/dialogMessageSearch.ts +0 -137
  174. package/ai/tools/doctorSkillTool.ts +0 -72
  175. package/ai/tools/ecommerceScraperTool.ts +0 -86
  176. package/ai/tools/emailTools.ts +0 -549
  177. package/ai/tools/evalSkillTool.ts +0 -92
  178. package/ai/tools/exaSearchTool.ts +0 -64
  179. package/ai/tools/execBashTool.ts +0 -379
  180. package/ai/tools/executeSqlTool.ts +0 -192
  181. package/ai/tools/fetchWebpageSupport.ts +0 -309
  182. package/ai/tools/fetchWebpageTool.ts +0 -84
  183. package/ai/tools/geminiImagePreviewTool.ts +0 -361
  184. package/ai/tools/generateDocxTool.ts +0 -215
  185. package/ai/tools/googleSearchScraperTool.ts +0 -106
  186. package/ai/tools/importDataTool.ts +0 -133
  187. package/ai/tools/importSkillTool.ts +0 -162
  188. package/ai/tools/index.ts +0 -1858
  189. package/ai/tools/listFilesTool.ts +0 -82
  190. package/ai/tools/listUserSpacesTool.ts +0 -113
  191. package/ai/tools/modelUsageTools.ts +0 -142
  192. package/ai/tools/olmOcrTool.ts +0 -34
  193. package/ai/tools/openaiImageTool.ts +0 -218
  194. package/ai/tools/paddleOcrTool.ts +0 -34
  195. package/ai/tools/prepareTools.ts +0 -23
  196. package/ai/tools/readDocTool.ts +0 -84
  197. package/ai/tools/readFileTool.ts +0 -211
  198. package/ai/tools/readTool.ts +0 -163
  199. package/ai/tools/readXPostTool.ts +0 -233
  200. package/ai/tools/rememberMemoryTool.ts +0 -84
  201. package/ai/tools/remotionVideoTool.ts +0 -151
  202. package/ai/tools/searchDialogMessagesTool.ts +0 -222
  203. package/ai/tools/searchRepoTool.ts +0 -115
  204. package/ai/tools/searchWorkspaceTool.ts +0 -259
  205. package/ai/tools/skillFollowup.ts +0 -86
  206. package/ai/tools/surfWeatherTool.ts +0 -169
  207. package/ai/tools/table/addTableRowTool.ts +0 -217
  208. package/ai/tools/table/createTableTool.ts +0 -315
  209. package/ai/tools/table/rowTools.ts +0 -366
  210. package/ai/tools/table/schemaTools.ts +0 -244
  211. package/ai/tools/table/shareTableTool.ts +0 -148
  212. package/ai/tools/table/toolShared.ts +0 -129
  213. package/ai/tools/toolApiClient.ts +0 -198
  214. package/ai/tools/toolNameAliases.ts +0 -57
  215. package/ai/tools/toolResultError.ts +0 -42
  216. package/ai/tools/toolRunSlice.ts +0 -303
  217. package/ai/tools/toolSchemaCompatibility.ts +0 -53
  218. package/ai/tools/toolVisibility.ts +0 -4
  219. package/ai/tools/types.ts +0 -20
  220. package/ai/tools/uiAskChoiceTool.ts +0 -104
  221. package/ai/tools/updateContentTitleTool.ts +0 -84
  222. package/ai/tools/updateDocTool.ts +0 -105
  223. package/ai/tools/updateUserPreferenceProfileTool.ts +0 -145
  224. package/ai/tools/whisperTool.ts +0 -77
  225. package/ai/tools/writeFileTool.ts +0 -210
  226. package/ai/tools/youtubeScraperTool.ts +0 -116
  227. package/ai/tools/ziweiChartTool.ts +0 -678
  228. package/ai/types.ts +0 -55
  229. package/ai/workflow/workflowExecutor.ts +0 -323
  230. package/ai/workflow/workflowSlice.ts +0 -73
  231. package/ai/workflow/workflowTypes.ts +0 -106
  232. package/connector-experimental/index.ts +0 -5
@@ -1,145 +0,0 @@
1
- import { setSettings } from "app/settings/settingSlice";
2
- import type {
3
- KnowledgeCaptureLevel,
4
- SpaceContextLevel,
5
- TonePreset,
6
- } from "ai/policy/types";
7
- import {
8
- normalizeAgentUpdateFieldList,
9
- type AgentUpdateField,
10
- } from "ai/policy/selfUpdateFields";
11
-
12
- export interface UpdateUserPreferenceProfileArgs {
13
- userTonePreset?: TonePreset;
14
- knowledgeCaptureLevel?: KnowledgeCaptureLevel;
15
- spaceContextLevel?: SpaceContextLevel;
16
- autoApproveSelfUpdateFields?: AgentUpdateField[];
17
- globalPrompt?: string;
18
- defaultAgentId?: string;
19
- summary?: string;
20
- }
21
-
22
- export const updateUserPreferenceProfileFunctionSchema = {
23
- name: "updateUserPreferenceProfile",
24
- description: [
25
- "当你已经明确收集到用户的个性化偏好时,使用本工具把这些偏好保存到用户设置里。",
26
- "适用于保存 tone、knowledge capture、space context,以及用户的 global prompt / 自我介绍摘要。",
27
- "只有在用户已经明确表达或确认后才调用;不要在信息不充分时猜测。",
28
- "调用后,你应当用自然语言简要总结已保存的设置,并说明用户之后可以继续调整。",
29
- ].join("\n"),
30
- parameters: {
31
- type: "object",
32
- properties: {
33
- userTonePreset: {
34
- type: "string",
35
- enum: ["default", "direct", "pragmatic", "friendly", "professional"],
36
- description: "用户偏好的交流语气。",
37
- },
38
- knowledgeCaptureLevel: {
39
- type: "integer",
40
- enum: [1, 2, 3, 4],
41
- description: "知识沉淀级别:1 不主动创建;2 先问再创建;3 回答后建议;4 高价值结果可自动创建。",
42
- },
43
- spaceContextLevel: {
44
- type: "integer",
45
- enum: [1, 2, 3, 4],
46
- description: "空间上下文级别:1 不自动读取;2 只看结构和标题;3 轻量读取;4 自适应读取。",
47
- },
48
- autoApproveSelfUpdateFields: {
49
- type: "array",
50
- items: {
51
- type: "string",
52
- enum: [
53
- "name",
54
- "model",
55
- "provider",
56
- "prompt",
57
- "introduction",
58
- "greeting",
59
- "isPublic",
60
- "tags",
61
- "tools",
62
- "references",
63
- "temperature",
64
- "top_p",
65
- "frequency_penalty",
66
- "presence_penalty",
67
- "max_tokens",
68
- "reasoning_effort",
69
- ],
70
- },
71
- description: "哪些 updateSelf 字段以后不再询问用户,直接自动通过。",
72
- },
73
- globalPrompt: {
74
- type: "string",
75
- description: "可选:用户希望长期保留的一小段通用偏好说明。未明确确认时不要写。",
76
- },
77
- defaultAgentId: {
78
- type: "string",
79
- description: "可选:用户明确要求切换首页默认 agent 时才填写。",
80
- },
81
- summary: {
82
- type: "string",
83
- description: "给开发和日志看的简短总结,不会影响设置本身。",
84
- },
85
- },
86
- } as const,
87
- };
88
-
89
- export async function updateUserPreferenceProfileFunc(
90
- args: UpdateUserPreferenceProfileArgs,
91
- thunkApi: any
92
- ): Promise<{ rawData: unknown; displayData: string }> {
93
- const changes: Record<string, unknown> = {};
94
-
95
- if (args.userTonePreset) {
96
- changes.userTonePreset = args.userTonePreset;
97
- }
98
- if (typeof args.knowledgeCaptureLevel === "number") {
99
- changes.knowledgeCaptureLevel = args.knowledgeCaptureLevel;
100
- }
101
- if (typeof args.spaceContextLevel === "number") {
102
- changes.spaceContextLevel = args.spaceContextLevel;
103
- changes.enableReadCurrentSpace = args.spaceContextLevel > 1;
104
- }
105
- if (Array.isArray(args.autoApproveSelfUpdateFields)) {
106
- changes.autoApproveSelfUpdateFields = normalizeAgentUpdateFieldList(
107
- args.autoApproveSelfUpdateFields,
108
- []
109
- );
110
- }
111
- if (typeof args.globalPrompt === "string" && args.globalPrompt.trim()) {
112
- changes.globalPrompt = args.globalPrompt.trim();
113
- }
114
- if (typeof args.defaultAgentId === "string" && args.defaultAgentId.trim()) {
115
- changes.defaultAgentId = args.defaultAgentId.trim();
116
- }
117
-
118
- if (Object.keys(changes).length === 0) {
119
- throw new Error("没有可保存的用户偏好设置。");
120
- }
121
-
122
- await thunkApi.dispatch(setSettings(changes as any)).unwrap();
123
-
124
- const rawData = {
125
- success: true,
126
- updated: changes,
127
- summary: args.summary?.trim() || null,
128
- };
129
-
130
- const labels: string[] = [];
131
- if (changes.userTonePreset) labels.push(`语气=${changes.userTonePreset}`);
132
- if (changes.knowledgeCaptureLevel)
133
- labels.push(`知识沉淀=${changes.knowledgeCaptureLevel}`);
134
- if (changes.spaceContextLevel)
135
- labels.push(`空间读取=${changes.spaceContextLevel}`);
136
- if (changes.autoApproveSelfUpdateFields)
137
- labels.push("自我更新免询问字段已更新");
138
- if (changes.defaultAgentId) labels.push("默认助手已更新");
139
- if (changes.globalPrompt) labels.push("通用提示词已更新");
140
-
141
- return {
142
- rawData,
143
- displayData: `已保存用户偏好:${labels.join(",")}`,
144
- };
145
- }
@@ -1,77 +0,0 @@
1
- import { ToolDefinition } from ".";
2
- import { callToolApi } from "./toolApiClient";
3
-
4
- const SHARED_PARAMS = {
5
- type: "object",
6
- properties: {
7
- audioUrl: {
8
- type: "string",
9
- description:
10
- "音频来源:内部文件 ID (file-... 或 ULID)、公开 http/https URL,或 base64 data URI(data:audio/...;base64,...)。支持 mp3、wav、m4a、ogg、flac 等常见格式。",
11
- },
12
- language: {
13
- type: "string",
14
- description:
15
- "可选,指定音频语言以提升精度(如 'zh'、'en'、'ja')。不指定则自动检测。",
16
- },
17
- },
18
- required: ["audioUrl"],
19
- };
20
-
21
- // ── whisper-large-v3-turbo(快速、便宜)──────────────────
22
-
23
- export const whisperTurboSchema = {
24
- name: "whisper_turbo",
25
- description:
26
- "使用 openai/whisper-large-v3-turbo 对音频进行语音转文字(ASR)。速度快、价格低($0.0002/min),适合大多数场景的实时或批量转录。",
27
- parameters: SHARED_PARAMS,
28
- };
29
-
30
- export const whisperTurboFunc: ToolDefinition["executor"] = async (
31
- input: any,
32
- thunkApi
33
- ) => {
34
- const { audioUrl, language } = input;
35
- const data = await callToolApi(
36
- thunkApi,
37
- "/api/whisper-turbo",
38
- { audioUrl, language },
39
- { withAuth: true }
40
- );
41
- return {
42
- summary: "Transcription completed",
43
- text: data.text || "",
44
- language: data.language,
45
- duration: data.duration,
46
- rawData: data,
47
- };
48
- };
49
-
50
- // ── whisper-large-v3(高精度)────────────────────────────
51
-
52
- export const whisperV3Schema = {
53
- name: "whisper_v3",
54
- description:
55
- "使用 openai/whisper-large-v3 对音频进行高精度语音转文字(ASR)。精度更高(尤其多语言/中文),价格稍高($0.00045/min),适合对准确率要求严格的场景。",
56
- parameters: SHARED_PARAMS,
57
- };
58
-
59
- export const whisperV3Func: ToolDefinition["executor"] = async (
60
- input: any,
61
- thunkApi
62
- ) => {
63
- const { audioUrl, language } = input;
64
- const data = await callToolApi(
65
- thunkApi,
66
- "/api/whisper-v3",
67
- { audioUrl, language },
68
- { withAuth: true }
69
- );
70
- return {
71
- summary: "Transcription completed",
72
- text: data.text || "",
73
- language: data.language,
74
- duration: data.duration,
75
- rawData: data,
76
- };
77
- };
@@ -1,210 +0,0 @@
1
- // 文件路径: packages/ai/tools/writeFileTool.ts
2
-
3
- import { bumpDevReloadSuppressIfSelfEditing } from "./devReloadUtils";
4
- import { getToolBaseUrl } from "./toolApiClient";
5
-
6
- // ---- Types ----
7
-
8
- export type WriteFileArgs = {
9
- /**
10
- * 目标文件相对项目根目录(bun-nolo)的路径,例如:
11
- * - packages/chat/src/messages/web/NewComponent.tsx
12
- * - packages/server/some-script.ts
13
- */
14
- filePath: string;
15
- /**
16
- * 要写入文件的完整内容。
17
- * - 如果文件不存在:将创建新文件,并写入该内容;
18
- * - 如果文件已存在:
19
- * - overwrite = true:覆盖原有内容;
20
- * - overwrite 未设置或为 false:请求会失败。
21
- */
22
- content: string;
23
- overwrite?: boolean;
24
- };
25
-
26
- // ---- 工具 Schema,供 LLM 调用 ----
27
-
28
- export const writeFileFunctionSchema = {
29
- name: "writeFile",
30
- description: [
31
- "在后端服务器上写入一个完整文件的内容,可用于新建文件或覆盖已有文件。",
32
- "",
33
- "适用场景:",
34
- "- 新建一个全新的代码文件(例如新组件、新工具函数、配置文件等)",
35
- "- 覆盖一个文件的全部内容(当你需要重写整个文件时)",
36
- "",
37
- "行为约定:",
38
- "- 当目标文件不存在:直接创建新文件并写入 content。",
39
- "- 当目标文件已存在:",
40
- " - 如果 overwrite=true,则覆盖原文件内容;",
41
- " - 否则请求会失败,以避免意外覆盖。",
42
- "",
43
- "返回数据约定(rawData.response 中):",
44
- "- created / overwritten:指示本次操作是新建还是覆盖。",
45
- "- newContent:写入后的完整文件内容(统一使用 \\n 作为换行符),用于 UI 中的代码预览。",
46
- "- diff:如果文件原本存在,则返回基于旧内容与 newContent 的行级 diff(diffLines 结果),用于 UI 中的 Diff 视图。",
47
- "",
48
- "注意:",
49
- "- filePath 必须是相对项目根目录(bun-nolo)的相对路径,且不能越出项目根目录。",
50
- "- 建议只在“新建文件/全量重写”时使用本工具;修改部分内容时优先使用 applyEdit。",
51
- "- 如果用户给了 URL 或网页资料来驱动本次改动,先抓取网页并核对字段,再决定是否需要整文件覆盖。",
52
- ].join("\n"),
53
- parameters: {
54
- type: "object",
55
- properties: {
56
- filePath: {
57
- type: "string",
58
- description:
59
- "目标文件相对项目根目录(bun-nolo)的路径,例如: packages/chat/src/messages/web/NewComponent.tsx",
60
- },
61
- content: {
62
- type: "string",
63
- description:
64
- "要写入文件的完整内容。对于新建文件,就是文件的全部内容;对于覆盖已有文件,会用该内容替换原内容。",
65
- },
66
- overwrite: {
67
- type: "boolean",
68
- description:
69
- "是否允许覆盖已存在的文件。缺省或为 false 时,如果文件已存在将报错;true 时允许覆盖。",
70
- },
71
- },
72
- required: ["filePath", "content"],
73
- },
74
- };
75
-
76
- // ---- 预览执行:不写文件,只展示信息 ----
77
-
78
- export async function writeFilePreviewFunc(
79
- args: WriteFileArgs,
80
- _thunkApi: any
81
- ): Promise<{ rawData: any; displayData?: string }> {
82
- const { filePath, content, overwrite } = args;
83
-
84
- if (!filePath || typeof filePath !== "string") {
85
- throw new Error("writeFile 预览失败:必须提供有效的 filePath 字符串。");
86
- }
87
- if (typeof content !== "string") {
88
- throw new Error("writeFile 预览失败:content 必须是字符串。");
89
- }
90
-
91
- const mode = overwrite ? "允许覆盖(已存在则覆盖)" : "仅新建(已存在则报错)";
92
- const lengthInfo = `内容长度: ${content.length} 个字符`;
93
-
94
- return {
95
- rawData: {
96
- previewOnly: true,
97
- filePath,
98
- overwrite: !!overwrite,
99
- content,
100
- },
101
- displayData: `⏸️ 文件写入预览: ${filePath}(模式: ${mode},${lengthInfo})`,
102
- };
103
- }
104
-
105
- // ---- 真正执行:POST 到后端 /api/write-file ----
106
-
107
- export async function writeFileFunc(
108
- args: WriteFileArgs,
109
- thunkApi: any,
110
- context?: { parentMessageId?: string; signal?: AbortSignal }
111
- ): Promise<{ rawData: any; displayData?: string }> {
112
- const { filePath, content, overwrite } = args;
113
-
114
- if (!filePath || typeof filePath !== "string") {
115
- throw new Error("写入文件失败:必须提供有效的 filePath 字符串。");
116
- }
117
- if (typeof content !== "string") {
118
- throw new Error("写入文件失败:content 必须是字符串。");
119
- }
120
-
121
- try {
122
- const baseUrl = getToolBaseUrl(thunkApi);
123
-
124
- if (!baseUrl) {
125
- throw new Error("写入文件失败:无法获取 writeFile 服务器地址。");
126
- }
127
-
128
- const apiUrl = `${baseUrl.replace(/\/+$/, "")}/api/write-file`;
129
-
130
- // 自举写入前增加 reload 抑制
131
- bumpDevReloadSuppressIfSelfEditing(filePath);
132
-
133
- const response = await fetch(apiUrl, {
134
- method: "POST",
135
- headers: { "Content-Type": "application/json" },
136
- signal: context?.signal,
137
- body: JSON.stringify({ filePath, content, overwrite }),
138
- });
139
-
140
- const status = response.status;
141
- const textBody = await response.text();
142
- let data: any = {};
143
- try {
144
- data = textBody ? JSON.parse(textBody) : {};
145
- } catch {
146
- // 非 JSON 的情况忽略解析错误
147
- }
148
-
149
- // 409:文件已存在但未允许覆盖 → 视为“写入冲突”,不抛异常
150
- if (status === 409) {
151
- const serverMsg =
152
- data?.error ||
153
- "写入文件失败:目标文件已存在,且 overwrite 未设置为 true。";
154
-
155
- return {
156
- rawData: {
157
- applied: false,
158
- conflict: true,
159
- fileExists: true,
160
- filePath,
161
- overwrite: !!overwrite,
162
- serverMessage: serverMsg,
163
- },
164
- displayData: [
165
- "⏸️ 检测到目标文件已存在,暂未写入。",
166
- `- filePath: ${filePath}`,
167
- `- 服务器消息: ${serverMsg}`,
168
- "",
169
- "如需覆盖,请在下一次调用 writeFile 时显式设置 overwrite: true。",
170
- ].join("\n"),
171
- };
172
- }
173
-
174
- if (!response.ok || data?.error) {
175
- const errMsg =
176
- data?.error ||
177
- `writeFile API 请求失败,状态码: ${status}. 响应: ${textBody}`;
178
- console.error("writeFile API Error:", errMsg);
179
- throw new Error(errMsg);
180
- }
181
-
182
- const created: boolean | undefined = data?.created;
183
- const overwrittenFlag: boolean | undefined = data?.overwritten;
184
-
185
- let actionDesc = "写入";
186
- if (created === true) {
187
- actionDesc = "新建";
188
- } else if (overwrittenFlag === true) {
189
- actionDesc = "覆盖";
190
- }
191
-
192
- return {
193
- rawData: {
194
- applied: true,
195
- filePath,
196
- overwrite: !!overwrite,
197
- // 把这次写入的原始内容也附带上,方便调试
198
- content,
199
- // 服务端返回的详细结果(包括 newContent / diff 等)
200
- response: data,
201
- },
202
- displayData: `✅ 已成功${actionDesc}文件: ${filePath}`,
203
- };
204
- } catch (error: any) {
205
- console.error("执行 writeFile 时发生错误:", error);
206
- throw new Error(
207
- `写入文件 (${filePath}) 失败:${error?.message || String(error)}`
208
- );
209
- }
210
- }
@@ -1,116 +0,0 @@
1
- // /ai/tools/youtubeScraperTool.ts
2
-
3
- import { callApifyActor } from "./apifyActorClient";
4
-
5
- export const youtubeScraperFunctionSchema = {
6
- name: "youtubeScraper",
7
- description:
8
- "使用 Apify 的 YouTube Scraper 抓取 YouTube 视频、频道、播放列表等信息。支持 Direct URLs 或搜索关键词。",
9
- parameters: {
10
- type: "object",
11
- properties: {
12
- directUrls: {
13
- type: "array",
14
- description:
15
- "可选。视频/频道/播放列表等 URL 列表,将映射到 startUrls。",
16
- items: { type: "string" },
17
- },
18
- searchQueries: {
19
- type: "array",
20
- description: "可选。搜索关键词数组,将映射到 searchQueries。",
21
- items: { type: "string" },
22
- },
23
- maxResults: { type: "integer", minimum: 0 },
24
- maxResultsShorts: { type: "integer", minimum: 0 },
25
- maxResultStreams: { type: "integer", minimum: 0 },
26
- downloadSubtitles: { type: "boolean" },
27
- subtitlesLanguage: {
28
- type: "string",
29
- enum: [
30
- "any",
31
- "en",
32
- "de",
33
- "es",
34
- "fr",
35
- "it",
36
- "ja",
37
- "ko",
38
- "nl",
39
- "pt",
40
- "ru",
41
- ],
42
- },
43
- subtitlesFormat: {
44
- type: "string",
45
- enum: ["srt", "vtt", "xml", "plaintext"],
46
- },
47
- extraInput: {
48
- type: "object",
49
- description: "可选。直接透传给 Apify 的额外 input 字段,方便扩展。",
50
- },
51
- },
52
- required: [],
53
- },
54
- };
55
-
56
- export async function youtubeScraperFunc(
57
- args: {
58
- directUrls?: string[];
59
- searchQueries?: string[];
60
- maxResults?: number;
61
- maxResultsShorts?: number;
62
- maxResultStreams?: number;
63
- downloadSubtitles?: boolean;
64
- subtitlesLanguage?: string;
65
- subtitlesFormat?: string;
66
- extraInput?: Record<string, any>;
67
- },
68
- thunkApi: any
69
- ) {
70
- const {
71
- directUrls,
72
- searchQueries,
73
- maxResults,
74
- maxResultsShorts,
75
- maxResultStreams,
76
- downloadSubtitles,
77
- subtitlesLanguage,
78
- subtitlesFormat,
79
- extraInput = {},
80
- } = args;
81
-
82
- if (
83
- (!directUrls || directUrls.length === 0) &&
84
- (!searchQueries || searchQueries.length === 0)
85
- ) {
86
- throw new Error(
87
- "YouTube 抓取:至少提供 directUrls 或 searchQueries 之一。"
88
- );
89
- }
90
-
91
- const input: any = {
92
- ...extraInput,
93
- };
94
-
95
- if (searchQueries?.length) input.searchQueries = searchQueries;
96
- if (directUrls?.length) input.startUrls = directUrls.map((url) => ({ url }));
97
-
98
- if (typeof maxResults === "number") input.maxResults = maxResults;
99
- if (typeof maxResultsShorts === "number")
100
- input.maxResultsShorts = maxResultsShorts;
101
- if (typeof maxResultStreams === "number")
102
- input.maxResultStreams = maxResultStreams;
103
- if (typeof downloadSubtitles === "boolean")
104
- input.downloadSubtitles = downloadSubtitles;
105
- if (typeof subtitlesLanguage === "string")
106
- input.subtitlesLanguage = subtitlesLanguage;
107
- if (typeof subtitlesFormat === "string")
108
- input.subtitlesFormat = subtitlesFormat;
109
-
110
- return callApifyActor(thunkApi, {
111
- actorId: "streamers~youtube-scraper",
112
- input,
113
- resultType: "datasetItems",
114
- displayName: "YouTube Scraper",
115
- });
116
- }