nolo-cli 0.1.9 → 0.1.11

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 (240) hide show
  1. package/README.md +0 -32
  2. package/agentRuntimeCommands.ts +3 -3
  3. package/commandRegistry.ts +2 -2
  4. package/machineCommands.ts +31 -6
  5. package/package.json +6 -8
  6. package/ai/agent/_executeModel.ts +0 -118
  7. package/ai/agent/agentSlice.ts +0 -525
  8. package/ai/agent/appWorkingMemory.ts +0 -126
  9. package/ai/agent/avatarUtils.ts +0 -24
  10. package/ai/agent/buildEditingContext.ts +0 -373
  11. package/ai/agent/buildSystemPrompt.ts +0 -532
  12. package/ai/agent/cleanAgentMessages.ts +0 -140
  13. package/ai/agent/cliChatClient.ts +0 -119
  14. package/ai/agent/cliExecutor.ts +0 -733
  15. package/ai/agent/cliPrompt.ts +0 -10
  16. package/ai/agent/contextCompiler.ts +0 -107
  17. package/ai/agent/contextLayerContract.ts +0 -44
  18. package/ai/agent/createAgentSchema.ts +0 -234
  19. package/ai/agent/executeToolCall.ts +0 -58
  20. package/ai/agent/fetchAgentContexts.ts +0 -42
  21. package/ai/agent/generatePrompt.ts +0 -3
  22. package/ai/agent/getFullChatContextKeys.ts +0 -168
  23. package/ai/agent/hooks/fetchPublicAgents.ts +0 -133
  24. package/ai/agent/hooks/useAgentConfig.ts +0 -61
  25. package/ai/agent/hooks/useAgentDialog.ts +0 -35
  26. package/ai/agent/hooks/useAgentFormValidation.ts +0 -202
  27. package/ai/agent/hooks/usePublicAgents.ts +0 -473
  28. package/ai/agent/machineRunPermissions.ts +0 -95
  29. package/ai/agent/persistMessageWithFixedId.ts +0 -37
  30. package/ai/agent/planSlice.ts +0 -259
  31. package/ai/agent/referenceUtils.ts +0 -229
  32. package/ai/agent/runAgentBackground.ts +0 -238
  33. package/ai/agent/runAgentClientLoop.ts +0 -138
  34. package/ai/agent/runtimeGuidance.ts +0 -97
  35. package/ai/agent/runtimeServerBase.ts +0 -37
  36. package/ai/agent/server/fetchPublicAgents.ts +0 -128
  37. package/ai/agent/startParallelAgentStreams.ts +0 -424
  38. package/ai/agent/startupProtocol.ts +0 -53
  39. package/ai/agent/streamAgentChatTurn.ts +0 -1278
  40. package/ai/agent/streamAgentChatTurnUtils.ts +0 -738
  41. package/ai/agent/types.ts +0 -71
  42. package/ai/agent/utils/imageOutput.ts +0 -33
  43. package/ai/agent/utils/sortUtils.ts +0 -250
  44. package/ai/agent/web/referencePickerUtils.ts +0 -146
  45. package/ai/ai.locale.ts +0 -1075
  46. package/ai/chat/accumulateToolCallChunks.ts +0 -95
  47. package/ai/chat/fetchUtils.native.ts +0 -276
  48. package/ai/chat/fetchUtils.ts +0 -153
  49. package/ai/chat/parseApiError.ts +0 -64
  50. package/ai/chat/parseMultilineSSE.ts +0 -95
  51. package/ai/chat/sendOpenAICompletionsRequest.native.ts +0 -682
  52. package/ai/chat/sendOpenAICompletionsRequest.ts +0 -703
  53. package/ai/chat/sendOpenAIResponseRequest.ts +0 -491
  54. package/ai/chat/shouldUseServerProxy.ts +0 -18
  55. package/ai/chat/sseClient.native.ts +0 -91
  56. package/ai/chat/sseClient.ts +0 -67
  57. package/ai/chat/streamReader.native.ts +0 -31
  58. package/ai/chat/streamReader.ts +0 -62
  59. package/ai/chat/updateTotalUsage.ts +0 -72
  60. package/ai/context/buildReferenceContext.ts +0 -437
  61. package/ai/context/calculateContextUsage.ts +0 -133
  62. package/ai/context/retention.ts +0 -165
  63. package/ai/context/tokenUtils.ts +0 -78
  64. package/ai/index.ts +0 -1
  65. package/ai/llm/calculateGeminiImageTokens.ts +0 -57
  66. package/ai/llm/deepinfra.ts +0 -28
  67. package/ai/llm/fireworks.ts +0 -50
  68. package/ai/llm/generateRequestBody.ts +0 -165
  69. package/ai/llm/getModelContextWindow.ts +0 -84
  70. package/ai/llm/getNoloKey.ts +0 -31
  71. package/ai/llm/getPricing.ts +0 -199
  72. package/ai/llm/hooks/useModelPricing.ts +0 -75
  73. package/ai/llm/imagePricing.ts +0 -40
  74. package/ai/llm/isResponseAPIModel.ts +0 -13
  75. package/ai/llm/mimo.ts +0 -71
  76. package/ai/llm/mistral.ts +0 -22
  77. package/ai/llm/modelAvatar.ts +0 -427
  78. package/ai/llm/models.ts +0 -45
  79. package/ai/llm/openrouterModels.ts +0 -269
  80. package/ai/llm/providers.ts +0 -306
  81. package/ai/llm/reasoningModels.ts +0 -28
  82. package/ai/llm/types.ts +0 -59
  83. package/ai/llm/usageRequestOptions.ts +0 -59
  84. package/ai/memory/capture.ts +0 -148
  85. package/ai/memory/consolidate.ts +0 -104
  86. package/ai/memory/delete.ts +0 -147
  87. package/ai/memory/overlay.ts +0 -84
  88. package/ai/memory/query.ts +0 -38
  89. package/ai/memory/queryShared.ts +0 -160
  90. package/ai/memory/rank.ts +0 -105
  91. package/ai/memory/recentRelationshipRecap.ts +0 -249
  92. package/ai/memory/remember.ts +0 -167
  93. package/ai/memory/runtime.ts +0 -76
  94. package/ai/memory/store.ts +0 -20
  95. package/ai/memory/storeShared.ts +0 -76
  96. package/ai/memory/types.ts +0 -46
  97. package/ai/memory/understanding.ts +0 -349
  98. package/ai/memory/understandingGreeting.ts +0 -264
  99. package/ai/messages/type.ts +0 -20
  100. package/ai/policy/personalizationDialog.ts +0 -333
  101. package/ai/policy/runtimePolicy.ts +0 -440
  102. package/ai/policy/selfUpdateFields.ts +0 -48
  103. package/ai/policy/types.ts +0 -64
  104. package/ai/skills/referenceRuntime.ts +0 -274
  105. package/ai/skills/skillDiagnostics.ts +0 -251
  106. package/ai/skills/skillDocBuilder.ts +0 -139
  107. package/ai/skills/skillDocProtocol.ts +0 -434
  108. package/ai/skills/skillReferenceSummary.ts +0 -63
  109. package/ai/skills/skillSummaryMarker.ts +0 -26
  110. package/ai/token/calculatePrice.ts +0 -544
  111. package/ai/token/db.ts +0 -98
  112. package/ai/token/externalToolCost.ts +0 -330
  113. package/ai/token/hooks/useRecords.ts +0 -65
  114. package/ai/token/missingUsageEstimate.ts +0 -42
  115. package/ai/token/modelUsageQuery.ts +0 -252
  116. package/ai/token/normalizeUsage.ts +0 -84
  117. package/ai/token/openaiImageGenerationUsage.ts +0 -56
  118. package/ai/token/prepareTokenUsageData.ts +0 -88
  119. package/ai/token/query.ts +0 -88
  120. package/ai/token/queryUserTokens.ts +0 -59
  121. package/ai/token/resolveBillingTarget.ts +0 -52
  122. package/ai/token/saveTokenRecord.ts +0 -53
  123. package/ai/token/serverDialogProjection.ts +0 -78
  124. package/ai/token/serverTokenWriter.ts +0 -143
  125. package/ai/token/stats.ts +0 -21
  126. package/ai/token/tokenThunks.ts +0 -24
  127. package/ai/token/types.ts +0 -93
  128. package/ai/tools/agent/agentTools.ts +0 -176
  129. package/ai/tools/agent/agentUpdateShared.ts +0 -311
  130. package/ai/tools/agent/callAgentTool.ts +0 -139
  131. package/ai/tools/agent/createAgentTool.ts +0 -512
  132. package/ai/tools/agent/createDialogTool.ts +0 -69
  133. package/ai/tools/agent/createSkillAgentTool.ts +0 -62
  134. package/ai/tools/agent/parallelBudget.ts +0 -221
  135. package/ai/tools/agent/presets/appBuilderPreset.ts +0 -145
  136. package/ai/tools/agent/runLlmTool.ts +0 -96
  137. package/ai/tools/agent/runStreamingAgentTool.ts +0 -73
  138. package/ai/tools/agent/skillAgentArgs.ts +0 -106
  139. package/ai/tools/agent/skillAgentPreset.ts +0 -89
  140. package/ai/tools/agent/streamParallelAgentsTool.ts +0 -122
  141. package/ai/tools/agent/updateAgentTool.ts +0 -96
  142. package/ai/tools/agent/updateSelfTool.ts +0 -113
  143. package/ai/tools/amazonProductScraperTool.ts +0 -86
  144. package/ai/tools/apifyActorClient.ts +0 -45
  145. package/ai/tools/appEditGuard.ts +0 -372
  146. package/ai/tools/appReadSnapshot.ts +0 -153
  147. package/ai/tools/appTools.ts +0 -1549
  148. package/ai/tools/applyEditTool.ts +0 -256
  149. package/ai/tools/applyLineEditsTool.ts +0 -312
  150. package/ai/tools/browserTools/click.ts +0 -33
  151. package/ai/tools/browserTools/closeSession.ts +0 -29
  152. package/ai/tools/browserTools/common.ts +0 -27
  153. package/ai/tools/browserTools/openSession.ts +0 -48
  154. package/ai/tools/browserTools/readContent.ts +0 -38
  155. package/ai/tools/browserTools/selectOption.ts +0 -46
  156. package/ai/tools/browserTools/typeText.ts +0 -42
  157. package/ai/tools/category/createCategoryTool.ts +0 -66
  158. package/ai/tools/category/queryContentsByCategoryTool.ts +0 -69
  159. package/ai/tools/category/updateContentCategoryTool.ts +0 -75
  160. package/ai/tools/cfBrowserTools.ts +0 -319
  161. package/ai/tools/cfSpeechToTextTool.ts +0 -49
  162. package/ai/tools/checkEnvTool.ts +0 -65
  163. package/ai/tools/cloudflareCrawlTool.ts +0 -289
  164. package/ai/tools/codeSearchTool.ts +0 -111
  165. package/ai/tools/codeTools.ts +0 -101
  166. package/ai/tools/createDocTool.ts +0 -132
  167. package/ai/tools/createPlanTool.ts +0 -999
  168. package/ai/tools/createSkillDocTool.ts +0 -155
  169. package/ai/tools/createWorkflowTool.ts +0 -154
  170. package/ai/tools/deepseekOcrTool.ts +0 -34
  171. package/ai/tools/delayTool.ts +0 -31
  172. package/ai/tools/deleteSpacesTool.ts +0 -325
  173. package/ai/tools/deleteSpacesToolModel.ts +0 -159
  174. package/ai/tools/devReloadUtils.ts +0 -29
  175. package/ai/tools/dialogMessageSearch.ts +0 -137
  176. package/ai/tools/doctorSkillTool.ts +0 -72
  177. package/ai/tools/ecommerceScraperTool.ts +0 -86
  178. package/ai/tools/emailTools.ts +0 -549
  179. package/ai/tools/evalSkillTool.ts +0 -92
  180. package/ai/tools/exaSearchTool.ts +0 -64
  181. package/ai/tools/execBashTool.ts +0 -379
  182. package/ai/tools/executeSqlTool.ts +0 -192
  183. package/ai/tools/fetchWebpageSupport.ts +0 -309
  184. package/ai/tools/fetchWebpageTool.ts +0 -84
  185. package/ai/tools/geminiImagePreviewTool.ts +0 -361
  186. package/ai/tools/generateDocxTool.ts +0 -215
  187. package/ai/tools/googleSearchScraperTool.ts +0 -106
  188. package/ai/tools/importDataTool.ts +0 -133
  189. package/ai/tools/importSkillTool.ts +0 -162
  190. package/ai/tools/index.ts +0 -1858
  191. package/ai/tools/listFilesTool.ts +0 -82
  192. package/ai/tools/listUserSpacesTool.ts +0 -113
  193. package/ai/tools/modelUsageTools.ts +0 -142
  194. package/ai/tools/olmOcrTool.ts +0 -34
  195. package/ai/tools/openaiImageTool.ts +0 -218
  196. package/ai/tools/paddleOcrTool.ts +0 -34
  197. package/ai/tools/prepareTools.ts +0 -23
  198. package/ai/tools/readDocTool.ts +0 -84
  199. package/ai/tools/readFileTool.ts +0 -211
  200. package/ai/tools/readTool.ts +0 -163
  201. package/ai/tools/readXPostTool.ts +0 -233
  202. package/ai/tools/rememberMemoryTool.ts +0 -84
  203. package/ai/tools/remotionVideoTool.ts +0 -151
  204. package/ai/tools/searchDialogMessagesTool.ts +0 -222
  205. package/ai/tools/searchRepoTool.ts +0 -115
  206. package/ai/tools/searchWorkspaceTool.ts +0 -259
  207. package/ai/tools/skillFollowup.ts +0 -86
  208. package/ai/tools/surfWeatherTool.ts +0 -169
  209. package/ai/tools/table/addTableRowTool.ts +0 -217
  210. package/ai/tools/table/createTableTool.ts +0 -315
  211. package/ai/tools/table/rowTools.ts +0 -366
  212. package/ai/tools/table/schemaTools.ts +0 -244
  213. package/ai/tools/table/shareTableTool.ts +0 -148
  214. package/ai/tools/table/toolShared.ts +0 -129
  215. package/ai/tools/toolApiClient.ts +0 -198
  216. package/ai/tools/toolNameAliases.ts +0 -57
  217. package/ai/tools/toolResultError.ts +0 -42
  218. package/ai/tools/toolRunSlice.ts +0 -303
  219. package/ai/tools/toolSchemaCompatibility.ts +0 -53
  220. package/ai/tools/toolVisibility.ts +0 -4
  221. package/ai/tools/types.ts +0 -20
  222. package/ai/tools/uiAskChoiceTool.ts +0 -104
  223. package/ai/tools/updateContentTitleTool.ts +0 -84
  224. package/ai/tools/updateDocTool.ts +0 -105
  225. package/ai/tools/updateUserPreferenceProfileTool.ts +0 -145
  226. package/ai/tools/whisperTool.ts +0 -77
  227. package/ai/tools/writeFileTool.ts +0 -210
  228. package/ai/tools/youtubeScraperTool.ts +0 -116
  229. package/ai/tools/ziweiChartTool.ts +0 -678
  230. package/ai/types.ts +0 -55
  231. package/ai/workflow/workflowExecutor.ts +0 -323
  232. package/ai/workflow/workflowSlice.ts +0 -73
  233. package/ai/workflow/workflowTypes.ts +0 -106
  234. package/client/compactDialog.ts +0 -222
  235. package/connector-experimental/capabilities.ts +0 -73
  236. package/connector-experimental/codexBinary.ts +0 -41
  237. package/connector-experimental/heartbeatLoop.ts +0 -22
  238. package/connector-experimental/index.ts +0 -5
  239. package/connector-experimental/machineInfo.ts +0 -46
  240. package/connector-experimental/protocol.ts +0 -54
@@ -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
- }