nolo-cli 0.1.10 → 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 -22
  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 -1079
  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,372 +0,0 @@
1
- type AppSourceFile = { name: string; code: string };
2
-
3
- type AppSourceSnapshot = {
4
- code?: string | null;
5
- files?: Array<{ name?: string | null; code?: string | null }> | null;
6
- };
7
-
8
- const TOKEN_FILE_PATTERN = /(tokens|theme|design-?system)\.(t|j)sx?$/i;
9
- const SMALL_VISUAL_RE =
10
- /(font|typography|text size|text bigger|font size|color|spacing|padding|margin|radius|shadow|line-height|letter-spacing|字号|字体|字重|颜色|配色|圆角|阴影|间距|留白)/i;
11
- const BROAD_CHANGE_RE =
12
- /(redesign|rewrite|refactor|new page|new feature|layout overhaul|full rebuild|重做|改版|重构|新页面|新功能|整体改|整个页面)/i;
13
- const LOGIC_MARKERS = [
14
- "useEffect(",
15
- "useState(",
16
- "fetch(",
17
- "axios.",
18
- "dispatch(",
19
- "navigate(",
20
- "createBrowserRouter(",
21
- "addEventListener(",
22
- "removeEventListener(",
23
- "setInterval(",
24
- "setTimeout(",
25
- ];
26
-
27
- export type SmallVisualEditGuardResult =
28
- | {
29
- ok: true;
30
- reason: "not-applicable";
31
- }
32
- | {
33
- ok: false;
34
- summary: string;
35
- displayData: string;
36
- rawData: {
37
- success: false;
38
- ok: false;
39
- error: true;
40
- code: "SMALL_VISUAL_SCOPE_EXCEEDED";
41
- summary: string;
42
- requestType: "small-visual-edit";
43
- issueCodes: string[];
44
- evidence: string[];
45
- retryable: true;
46
- repairPlan: {
47
- strategy: "targeted-repair";
48
- scope: "existing-files";
49
- mode: "preflight-first";
50
- summary: string;
51
- steps: Array<{ action: string; reason: string }>;
52
- issueCodes: string[];
53
- suggestedFiles: string[];
54
- keepFiles?: string[];
55
- revertFiles?: string[];
56
- preferTokenFiles?: string[];
57
- targetStyleFields?: string[];
58
- targetElements?: string[];
59
- rerun: ["appPreflight", "appDeploy"];
60
- };
61
- };
62
- };
63
-
64
- const toNormalizedFiles = (input: AppSourceSnapshot): AppSourceFile[] => {
65
- const files = Array.isArray(input.files)
66
- ? input.files
67
- .filter(
68
- (file): file is { name: string; code: string } =>
69
- !!file &&
70
- typeof file.name === "string" &&
71
- typeof file.code === "string"
72
- )
73
- .map((file) => ({ name: file.name, code: file.code }))
74
- : [];
75
- if (files.length > 0) return files;
76
-
77
- const code = typeof input.code === "string" ? input.code : "";
78
- if (!code.trim()) return [];
79
- return [{ name: "worker.ts", code }];
80
- };
81
-
82
- const buildFileMap = (files: AppSourceFile[]) =>
83
- new Map(files.map((file) => [file.name, file.code]));
84
-
85
- const extractJsxTagCounts = (code: string): Map<string, number> => {
86
- const counts = new Map<string, number>();
87
- const matches = code.matchAll(/<([A-Za-z][\w.-]*)\b/g);
88
- for (const match of matches) {
89
- const tag = match[1];
90
- if (!tag) continue;
91
- counts.set(tag, (counts.get(tag) ?? 0) + 1);
92
- }
93
- return counts;
94
- };
95
-
96
- const hasLargeStructureChange = (previousCode: string, nextCode: string): boolean => {
97
- const previousTags = extractJsxTagCounts(previousCode);
98
- const nextTags = extractJsxTagCounts(nextCode);
99
- if (previousTags.size === 0 && nextTags.size === 0) return false;
100
-
101
- const tagNames = new Set([...previousTags.keys(), ...nextTags.keys()]);
102
- let totalDelta = 0;
103
- let changedKinds = 0;
104
- for (const tag of tagNames) {
105
- const delta = Math.abs((previousTags.get(tag) ?? 0) - (nextTags.get(tag) ?? 0));
106
- if (delta > 0) changedKinds += 1;
107
- totalDelta += delta;
108
- }
109
-
110
- const previousLines = previousCode.split("\n").length;
111
- const nextLines = nextCode.split("\n").length;
112
- const lineDelta = Math.abs(previousLines - nextLines);
113
-
114
- return totalDelta > 4 || changedKinds > 3 || lineDelta > Math.max(25, Math.round(previousLines * 0.35));
115
- };
116
-
117
- const hasLogicMarkerChange = (previousCode: string, nextCode: string): boolean =>
118
- LOGIC_MARKERS.some((marker) => previousCode.includes(marker) !== nextCode.includes(marker));
119
-
120
- const STYLE_FIELDS = [
121
- "fontSize",
122
- "fontWeight",
123
- "lineHeight",
124
- "letterSpacing",
125
- "color",
126
- "backgroundColor",
127
- "padding",
128
- "margin",
129
- "gap",
130
- "borderRadius",
131
- "boxShadow",
132
- ] as const;
133
-
134
- const FIELD_TRIGGER_MAP: Array<{ field: string; re: RegExp }> = [
135
- { field: "fontSize", re: /(font|text size|font size|字号|字体|字大|字小)/i },
136
- { field: "fontWeight", re: /(font weight|字重|加粗|粗一点)/i },
137
- { field: "lineHeight", re: /(line-height|line height|行高)/i },
138
- { field: "letterSpacing", re: /(letter-spacing|letter spacing|字距)/i },
139
- { field: "color", re: /(color|颜色|配色)/i },
140
- { field: "backgroundColor", re: /(background|背景|底色)/i },
141
- { field: "padding", re: /(padding|内边距)/i },
142
- { field: "margin", re: /(margin|外边距|留白|间距)/i },
143
- { field: "gap", re: /(gap|间距)/i },
144
- { field: "borderRadius", re: /(radius|圆角)/i },
145
- { field: "boxShadow", re: /(shadow|阴影)/i },
146
- ];
147
-
148
- const extractStyleFields = (code: string): string[] => {
149
- const found = new Set<string>();
150
- for (const field of STYLE_FIELDS) {
151
- if (code.includes(`${field}:`)) found.add(field);
152
- }
153
- return [...found];
154
- };
155
-
156
- const ELEMENT_TRIGGER_MAP: Array<{ element: string; re: RegExp; aliases: string[] }> = [
157
- { element: "button", re: /(button|按钮)/i, aliases: ["button"] },
158
- { element: "body-text", re: /(正文|body text|paragraph|段落)/i, aliases: ["p"] },
159
- { element: "title", re: /(title|headline|标题)/i, aliases: ["h1", "h2", "h3"] },
160
- {
161
- element: "container",
162
- re: /(card|container|panel|section|卡片|容器|面板)/i,
163
- aliases: ["section", "main", "div", "article"],
164
- },
165
- ];
166
-
167
- const inferRequestedElements = (userInput: string | null | undefined): string[] => {
168
- const text = typeof userInput === "string" ? userInput : "";
169
- const found = new Set<string>();
170
- for (const rule of ELEMENT_TRIGGER_MAP) {
171
- if (!rule.re.test(text)) continue;
172
- for (const alias of rule.aliases) found.add(alias);
173
- }
174
- return [...found];
175
- };
176
-
177
- const extractStyledTagSignatures = (code: string): Map<string, string[]> => {
178
- const result = new Map<string, string[]>();
179
- const matches = code.matchAll(/<([A-Za-z][\w.-]*)\b[^>]*style=\{\{([\s\S]*?)\}\}[^>]*>/g);
180
- for (const match of matches) {
181
- const tag = match[1];
182
- const style = match[2];
183
- if (!tag || !style) continue;
184
- const list = result.get(tag) ?? [];
185
- list.push(style.replace(/\s+/g, " ").trim());
186
- result.set(tag, list);
187
- }
188
- return result;
189
- };
190
-
191
- const inferRequestedStyleFields = (userInput: string | null | undefined): string[] => {
192
- const text = typeof userInput === "string" ? userInput : "";
193
- const found = new Set<string>();
194
- for (const rule of FIELD_TRIGGER_MAP) {
195
- if (rule.re.test(text)) found.add(rule.field);
196
- }
197
- return [...found];
198
- };
199
-
200
- export const isSmallVisualEditRequest = (input: string | null | undefined): boolean => {
201
- const text = typeof input === "string" ? input.trim() : "";
202
- if (!text) return false;
203
- return SMALL_VISUAL_RE.test(text) && !BROAD_CHANGE_RE.test(text);
204
- };
205
-
206
- export const evaluateSmallVisualEditGuard = (params: {
207
- userInput?: string | null;
208
- previousSource: AppSourceSnapshot;
209
- nextSource: AppSourceSnapshot;
210
- }): SmallVisualEditGuardResult => {
211
- if (!isSmallVisualEditRequest(params.userInput)) {
212
- return { ok: true, reason: "not-applicable" };
213
- }
214
-
215
- const previousFiles = toNormalizedFiles(params.previousSource);
216
- const nextFiles = toNormalizedFiles(params.nextSource);
217
- if (previousFiles.length === 0 || nextFiles.length === 0) {
218
- return { ok: true, reason: "not-applicable" };
219
- }
220
-
221
- const previousByName = buildFileMap(previousFiles);
222
- const nextByName = buildFileMap(nextFiles);
223
- const previousNames = new Set(previousByName.keys());
224
- const nextNames = new Set(nextByName.keys());
225
-
226
- const addedFiles = [...nextNames].filter((name) => !previousNames.has(name));
227
- const deletedFiles = [...previousNames].filter((name) => !nextNames.has(name));
228
- const changedFiles = [...nextNames].filter(
229
- (name) => previousByName.has(name) && previousByName.get(name) !== nextByName.get(name)
230
- );
231
-
232
- const evidence: string[] = [];
233
- const issueCodes: string[] = [];
234
- const tokenFiles = [...nextNames].filter((name) => TOKEN_FILE_PATTERN.test(name));
235
- const targetStyleFields = inferRequestedStyleFields(params.userInput);
236
- const targetElements = inferRequestedElements(params.userInput);
237
-
238
- if (deletedFiles.length > 0) {
239
- issueCodes.push("deleted-files");
240
- evidence.push(`删除了文件:${deletedFiles.join(", ")}`);
241
- }
242
-
243
- const nonTokenAddedFiles = addedFiles.filter((name) => !TOKEN_FILE_PATTERN.test(name));
244
- if (nonTokenAddedFiles.length > 0) {
245
- issueCodes.push("added-non-token-files");
246
- evidence.push(`新增了非 token 文件:${nonTokenAddedFiles.join(", ")}`);
247
- }
248
-
249
- if (changedFiles.length + addedFiles.length > 4) {
250
- issueCodes.push("too-many-files");
251
- evidence.push(
252
- `命中了过多文件:修改 ${changedFiles.length} 个,新增 ${addedFiles.length} 个`
253
- );
254
- }
255
-
256
- for (const fileName of changedFiles) {
257
- if (TOKEN_FILE_PATTERN.test(fileName)) continue;
258
- const previousCode = previousByName.get(fileName) ?? "";
259
- const nextCode = nextByName.get(fileName) ?? "";
260
-
261
- if (hasLogicMarkerChange(previousCode, nextCode)) {
262
- issueCodes.push("logic-change");
263
- evidence.push(`文件 ${fileName} 出现了逻辑层标记变化`);
264
- }
265
-
266
- if (hasLargeStructureChange(previousCode, nextCode)) {
267
- issueCodes.push("jsx-structure-change");
268
- evidence.push(`文件 ${fileName} 的 JSX 结构变化过大`);
269
- }
270
-
271
- if (targetElements.length > 0) {
272
- const previousTags = extractStyledTagSignatures(previousCode);
273
- const nextTags = extractStyledTagSignatures(nextCode);
274
- const tagNames = new Set([...previousTags.keys(), ...nextTags.keys()]);
275
- const unauthorizedTags = [...tagNames].filter((tag) => {
276
- const previousSignature = JSON.stringify(previousTags.get(tag) ?? []);
277
- const nextSignature = JSON.stringify(nextTags.get(tag) ?? []);
278
- if (previousSignature === nextSignature) return false;
279
- return !targetElements.includes(tag);
280
- });
281
- if (unauthorizedTags.length > 0) {
282
- issueCodes.push("non-target-element-change");
283
- evidence.push(
284
- `文件 ${fileName} 改到了未点名元素:${unauthorizedTags.join(", ")}`
285
- );
286
- }
287
- }
288
- }
289
-
290
- if (issueCodes.length === 0) {
291
- return { ok: true, reason: "not-applicable" };
292
- }
293
-
294
- const suggestedFiles = [...new Set([...changedFiles, ...addedFiles])];
295
- const revertFiles = [...new Set([...deletedFiles, ...nonTokenAddedFiles])];
296
- const keepFiles = [
297
- ...new Set([
298
- ...changedFiles.filter((name) => !revertFiles.includes(name)),
299
- ...tokenFiles,
300
- ]),
301
- ];
302
- const observedStyleFields = [
303
- ...new Set(
304
- changedFiles.flatMap((fileName) => extractStyleFields(nextByName.get(fileName) ?? ""))
305
- ),
306
- ];
307
- const scopedStyleFields = targetStyleFields.length > 0 ? targetStyleFields : observedStyleFields;
308
- const summary =
309
- "这次请求更像“小范围视觉微调”,但当前改动超出了安全范围,先不要直接部署。请收敛到 token / 命中的局部样式,再重新预检和部署。";
310
- const displayData = [
311
- "⚠️ 小视觉修改守卫已拦截本次部署。",
312
- summary,
313
- "",
314
- "超范围证据:",
315
- ...evidence.map((item) => `- ${item}`),
316
- "",
317
- "修复建议:",
318
- "- 保留字体 / 颜色 / 间距 / 圆角 / 阴影相关改动。",
319
- "- 不要新增非 token 文件,不要删除现有文件。",
320
- "- 不要改布局结构、组件树、事件逻辑、数据流或路由。",
321
- "- 如需统一样式,可新增一个最小 tokens/theme 文件,并只让命中的组件消费它。",
322
- ...(keepFiles.length > 0 ? [`- 优先保留文件:${keepFiles.join(", ")}`] : []),
323
- ...(revertFiles.length > 0 ? [`- 优先回退文件:${revertFiles.join(", ")}`] : []),
324
- ...(scopedStyleFields.length > 0
325
- ? [`- 这轮只允许继续调整这些视觉字段:${scopedStyleFields.join(", ")}`]
326
- : []),
327
- ...(targetElements.length > 0
328
- ? [`- 这轮只允许继续调整这些元素:${targetElements.join(", ")}`]
329
- : []),
330
- ].join("\n");
331
-
332
- return {
333
- ok: false,
334
- summary,
335
- displayData,
336
- rawData: {
337
- success: false,
338
- ok: false,
339
- error: true,
340
- code: "SMALL_VISUAL_SCOPE_EXCEEDED",
341
- summary,
342
- requestType: "small-visual-edit",
343
- issueCodes,
344
- evidence,
345
- retryable: true,
346
- repairPlan: {
347
- strategy: "targeted-repair",
348
- scope: "existing-files",
349
- mode: "preflight-first",
350
- summary,
351
- steps: [
352
- {
353
- action: "回退超出视觉范围的结构与逻辑修改",
354
- reason: "当前请求只要求小范围视觉微调,不应顺带重写页面结构或行为逻辑",
355
- },
356
- {
357
- action: "把视觉参数收敛到命中的局部组件或最小 token 层",
358
- reason: "这样可以保留局部改动并避免继续散落新的硬编码",
359
- },
360
- ],
361
- issueCodes,
362
- suggestedFiles,
363
- ...(keepFiles.length > 0 ? { keepFiles } : {}),
364
- ...(revertFiles.length > 0 ? { revertFiles } : {}),
365
- ...(tokenFiles.length > 0 ? { preferTokenFiles: tokenFiles } : {}),
366
- ...(scopedStyleFields.length > 0 ? { targetStyleFields: scopedStyleFields } : {}),
367
- ...(targetElements.length > 0 ? { targetElements } : {}),
368
- rerun: ["appPreflight", "appDeploy"],
369
- },
370
- },
371
- };
372
- };
@@ -1,153 +0,0 @@
1
- type AppReadSnapshotInput = {
2
- code?: string | null;
3
- files?: Array<{ name?: string | null; code?: string | null }> | null;
4
- };
5
-
6
- export type AppReadSnapshotKind =
7
- | "source-files"
8
- | "single-file-source"
9
- | "compiled-artifact";
10
-
11
- export type AppStyleSystemStatus =
12
- | "design-system"
13
- | "hardcoded-inline-styles"
14
- | "unknown";
15
-
16
- const COMPILED_ARTIFACT_PATTERNS = [
17
- "<!DOCTYPE html>",
18
- '<script type="importmap">',
19
- "react-dom/client",
20
- "createRoot(",
21
- "esm.sh/",
22
- "__toESM(",
23
- ];
24
-
25
- export const classifyAppReadSnapshot = (
26
- input: AppReadSnapshotInput
27
- ): AppReadSnapshotKind => {
28
- const files = Array.isArray(input.files)
29
- ? input.files.filter(
30
- (file) =>
31
- !!file &&
32
- typeof file.name === "string" &&
33
- typeof file.code === "string" &&
34
- file.code.trim().length > 0
35
- )
36
- : [];
37
-
38
- if (files.length > 0) {
39
- return "source-files";
40
- }
41
-
42
- const code = typeof input.code === "string" ? input.code.trim() : "";
43
- if (!code) {
44
- return "single-file-source";
45
- }
46
-
47
- const looksCompiled = COMPILED_ARTIFACT_PATTERNS.some((pattern) =>
48
- code.includes(pattern)
49
- );
50
-
51
- return looksCompiled ? "compiled-artifact" : "single-file-source";
52
- };
53
-
54
- export const buildAppReadSnapshotWarning = (
55
- kind: AppReadSnapshotKind
56
- ): string | null => {
57
- if (kind !== "compiled-artifact") return null;
58
-
59
- return [
60
- "⚠️ 检测到当前读到的更像“部署产物 / 打包 bundle”,不是原始可维护源码文件。",
61
- "这类结果通常只适合理解现状,不适合在未告知用户的情况下做局部增量修改。",
62
- "如果用户只想改一小部分,必须先明确说明当前缺少原始源码快照;未经用户确认,不要直接整站重写后 appDeploy。",
63
- ].join("\n");
64
- };
65
-
66
- const STYLE_SYSTEM_FILE_PATTERN = /(tokens|theme|design-?system)\.(t|j)sx?$/i;
67
- const STYLE_SYSTEM_EXPORT_PATTERN =
68
- /\b(?:export\s+const|const)\s+(tokens|theme|designSystem)\b/;
69
- const INLINE_STYLE_PATTERN = /style=\{\{/g;
70
- const HARD_CODED_STYLE_VALUE_PATTERN =
71
- /\b(fontSize|color|backgroundColor|padding|margin|gap|borderRadius|boxShadow|lineHeight)\s*:\s*['"`#0-9a-zA-Z.(]/g;
72
-
73
- export const analyzeAppStyleSystem = (input: AppReadSnapshotInput): {
74
- status: AppStyleSystemStatus;
75
- legacyMigrationRecommended: boolean;
76
- evidence: string[];
77
- } => {
78
- const files = Array.isArray(input.files)
79
- ? input.files.filter(
80
- (file): file is { name: string; code: string } =>
81
- !!file &&
82
- typeof file.name === "string" &&
83
- typeof file.code === "string"
84
- )
85
- : [];
86
-
87
- const combinedSource = (
88
- files.length > 0
89
- ? files.map((file) => `${file.name}\n${file.code}`).join("\n\n")
90
- : typeof input.code === "string"
91
- ? input.code
92
- : ""
93
- ).trim();
94
-
95
- const evidence: string[] = [];
96
-
97
- if (
98
- files.some((file) => STYLE_SYSTEM_FILE_PATTERN.test(file.name)) ||
99
- STYLE_SYSTEM_EXPORT_PATTERN.test(combinedSource)
100
- ) {
101
- if (files.some((file) => STYLE_SYSTEM_FILE_PATTERN.test(file.name))) {
102
- evidence.push("发现 tokens/theme/design-system 文件");
103
- }
104
- if (STYLE_SYSTEM_EXPORT_PATTERN.test(combinedSource)) {
105
- evidence.push("发现 tokens/theme/designSystem 导出");
106
- }
107
- return {
108
- status: "design-system",
109
- legacyMigrationRecommended: false,
110
- evidence,
111
- };
112
- }
113
-
114
- const inlineStyleMatches = combinedSource.match(INLINE_STYLE_PATTERN)?.length ?? 0;
115
- const hardcodedStyleMatches =
116
- combinedSource.match(HARD_CODED_STYLE_VALUE_PATTERN)?.length ?? 0;
117
-
118
- if (inlineStyleMatches >= 1 && hardcodedStyleMatches >= 4) {
119
- evidence.push(`检测到 ${inlineStyleMatches} 处内联 style`);
120
- evidence.push(`检测到 ${hardcodedStyleMatches} 处硬编码视觉值`);
121
- return {
122
- status: "hardcoded-inline-styles",
123
- legacyMigrationRecommended: true,
124
- evidence,
125
- };
126
- }
127
-
128
- return {
129
- status: "unknown",
130
- legacyMigrationRecommended: false,
131
- evidence,
132
- };
133
- };
134
-
135
- export const buildAppStyleSystemHint = (
136
- analysis: ReturnType<typeof analyzeAppStyleSystem>
137
- ): string | null => {
138
- if (analysis.status === "design-system") {
139
- return [
140
- "🧩 检测到当前应用已经有设计系统 / token 层。",
141
- "后续视觉微调应优先改这层共享 token,而不是把新数字继续散落回组件。",
142
- ].join("\n");
143
- }
144
-
145
- if (analysis.status === "hardcoded-inline-styles") {
146
- return [
147
- "🧩 检测到当前应用更像旧式硬编码样式:多个视觉值直接散落在组件内联 style 中。",
148
- "如果用户这次只是调字体、颜色、间距、圆角、阴影,默认建议先做一次最小 token 迁移(如新增 tokens.ts / theme 对象),再在 token 层完成修改。",
149
- ].join("\n");
150
- }
151
-
152
- return null;
153
- };