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,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
- };