ilse-design 0.3.0-beta.7 → 0.3.0

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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -74
  3. package/dist/agent/executor.d.ts.map +1 -1
  4. package/dist/agent/executor.js +137 -46
  5. package/dist/agent/executor.js.map +1 -1
  6. package/dist/bridge/augment.d.ts +1 -0
  7. package/dist/bridge/augment.d.ts.map +1 -1
  8. package/dist/bridge/augment.js +52 -3
  9. package/dist/bridge/augment.js.map +1 -1
  10. package/dist/bridge/ws-server.d.ts +6 -0
  11. package/dist/bridge/ws-server.d.ts.map +1 -1
  12. package/dist/bridge/ws-server.js +10 -2
  13. package/dist/bridge/ws-server.js.map +1 -1
  14. package/dist/cli/default.d.ts.map +1 -1
  15. package/dist/cli/default.js +66 -40
  16. package/dist/cli/default.js.map +1 -1
  17. package/dist/cli/index.js +24 -16
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/cli/listen.d.ts.map +1 -1
  20. package/dist/cli/listen.js +9 -8
  21. package/dist/cli/listen.js.map +1 -1
  22. package/dist/cli/login.d.ts.map +1 -1
  23. package/dist/cli/login.js +41 -26
  24. package/dist/cli/login.js.map +1 -1
  25. package/dist/config/user-config.d.ts +1 -0
  26. package/dist/config/user-config.d.ts.map +1 -1
  27. package/dist/config/user-config.js.map +1 -1
  28. package/dist/i18n/index.d.ts +23 -0
  29. package/dist/i18n/index.d.ts.map +1 -0
  30. package/dist/i18n/index.js +53 -0
  31. package/dist/i18n/index.js.map +1 -0
  32. package/dist/i18n/messages.d.ts +483 -0
  33. package/dist/i18n/messages.d.ts.map +1 -0
  34. package/dist/i18n/messages.js +490 -0
  35. package/dist/i18n/messages.js.map +1 -0
  36. package/dist/mcp/server.js +4 -1
  37. package/dist/mcp/server.js.map +1 -1
  38. package/dist/react/analyze.d.ts +46 -0
  39. package/dist/react/analyze.d.ts.map +1 -0
  40. package/dist/react/analyze.js +421 -0
  41. package/dist/react/analyze.js.map +1 -0
  42. package/dist/react/image-input.d.ts +13 -5
  43. package/dist/react/image-input.d.ts.map +1 -1
  44. package/dist/react/image-input.js +47 -39
  45. package/dist/react/image-input.js.map +1 -1
  46. package/dist/react/toolbar.d.ts.map +1 -1
  47. package/dist/react/toolbar.js +899 -71
  48. package/dist/react/toolbar.js.map +1 -1
  49. package/dist/setup/token-detect.d.ts +17 -0
  50. package/dist/setup/token-detect.d.ts.map +1 -0
  51. package/dist/setup/token-detect.js +169 -0
  52. package/dist/setup/token-detect.js.map +1 -0
  53. package/dist/types.d.ts +2 -1
  54. package/dist/types.d.ts.map +1 -1
  55. package/package.json +1 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Iverson Dantas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # Ilse
2
2
 
3
- **Olho do designer dentro do agente de código.**
3
+ **The designer's eye inside the code agent.**
4
4
 
5
- Aponte o que está errado na UI. Seu agente corrige.
5
+ Point at what's wrong in the UI. Your agent fixes it.
6
6
 
7
7
  ```bash
8
- npm install @iversondantas/ilse@beta
8
+ npm install ilse-design
9
9
  ```
10
10
 
11
11
  ```tsx
12
12
  // app/layout.tsx
13
- import { Ilse } from "@iversondantas/ilse/react";
13
+ import { Ilse } from "ilse-design/react";
14
14
 
15
15
  export default function Layout({ children }) {
16
16
  return (
@@ -24,24 +24,24 @@ export default function Layout({ children }) {
24
24
  }
25
25
  ```
26
26
 
27
- Em dev, aparece uma toolbar flutuante. Em prod, desaparece automaticamente.
27
+ In dev, a floating toolbar appears. In production, it disappears automatically.
28
28
 
29
29
  ---
30
30
 
31
- ## Setup completo (3 passos)
31
+ ## Setup (3 steps)
32
32
 
33
- ### 1. Instalar
33
+ ### 1. Install
34
34
 
35
35
  ```bash
36
- npm install @iversondantas/ilse@beta --legacy-peer-deps
36
+ npm install ilse-design
37
37
  ```
38
38
 
39
- ### 2. Adicionar o componente no layout
39
+ ### 2. Add the component to your layout
40
40
 
41
41
  **Next.js (App Router):**
42
42
  ```tsx
43
43
  // app/layout.tsx
44
- import { Ilse } from "@iversondantas/ilse/react";
44
+ import { Ilse } from "ilse-design/react";
45
45
 
46
46
  export default function RootLayout({ children }) {
47
47
  return (
@@ -57,8 +57,8 @@ export default function RootLayout({ children }) {
57
57
 
58
58
  **Vite / CRA / Remix / Astro:**
59
59
  ```tsx
60
- // App.tsx ou equivalente
61
- import { Ilse } from "@iversondantas/ilse/react";
60
+ // App.tsx or equivalent
61
+ import { Ilse } from "ilse-design/react";
62
62
 
63
63
  function App() {
64
64
  return (
@@ -70,115 +70,108 @@ function App() {
70
70
  }
71
71
  ```
72
72
 
73
- ### 3. Conectar ao seu agente (opcional)
73
+ ### 3. Start the CLI
74
74
 
75
- Para o Claude Code corrigir automaticamente:
76
75
  ```bash
77
- npx @iversondantas/ilse@beta setup
76
+ npx ilse
78
77
  ```
79
78
 
80
- Isso registra o MCP server no Claude Code. Reinicie o Claude Code.
81
-
82
- Para outros agentes (Cursor, VS Code, Codex, ChatGPT): funciona via clipboard automaticamente. Sem setup.
79
+ First run: choose automatic mode (recommended) or clipboard. The CLI detects your agent (Claude, Codex, Cursor, Gemini) and connects automatically.
83
80
 
84
81
  ---
85
82
 
86
- ## Como usar
83
+ ## How it works
87
84
 
88
- 1. Rode seu projeto (`npm run dev`)
89
- 2. Abre no browser — você verá uma toolbar pixelada no canto
90
- 3. Clica no toolbar → escolhe modo (elemento, texto, área)
91
- 4. Clica no que está errado na UI
92
- 5. Escreve o que precisa mudar ("botão torto", "cor errada")
93
- 6. Clica enviar
85
+ 1. Run your project (`npm run dev`)
86
+ 2. Open in browser — you'll see a small toolbar at the bottom
87
+ 3. Click the toolbar → selection mode activates
88
+ 4. Click any element, select text, or draw an area
89
+ 5. Describe what needs to change
90
+ 6. Attach reference images (paste with Ctrl+V or click +)
91
+ 7. Send
94
92
 
95
- **Se o MCP está conectado:** a anotação vai direto pro seu agente.
96
- **Se não está:** copia automático pro clipboard. Cola no chat do agente (Cmd+V).
93
+ **Automatic mode:** the annotation goes straight to your agent, which reads the code, fixes it, and resolves.
97
94
 
98
- No Claude Code:
99
- ```
100
- /ilse
101
- ```
102
- Uma palavra. O agente lê todas as anotações pendentes, corrige cada uma, e marca como resolvido.
95
+ **Clipboard mode:** copies to clipboard. Paste in your agent's chat (Cmd+V).
103
96
 
104
97
  ---
105
98
 
106
- ## O que a Ilse captura
99
+ ## What Ilse captures
107
100
 
108
- Quando você anota um elemento, o agente recebe:
101
+ When you annotate an element, the agent receives:
109
102
 
110
- - **Seletor CSS** (`button.cta-primary`)
111
- - **Nome do componente React** (via React fiber)
112
- - **Componente stack** (hierarquia)
113
- - **Grep pattern** (pra encontrar no código)
114
- - **Full DOM path**
115
- - **Styles relevantes** (filtrados por intent se você disse "cor errada", manda cores)
116
- - **Parent context** (flex, gap, layout)
117
- - **Viewport, URL, DPR** (contexto da página)
118
- - **Imagem de referência** (se colar com Cmd+V no textarea)
103
+ - **Contextual label** `button: "Submit"`, `heading: "Product Designer..."`
104
+ - **CSS selector** `button.cta-primary`
105
+ - **React component name** — via React fiber (dev mode)
106
+ - **Component stack** parent hierarchy
107
+ - **Grep pattern** — to find it in code
108
+ - **Relevant styles** filtered by intent (if you said "wrong color", only sends colors)
109
+ - **Parent context** flex, gap, layout
110
+ - **Reference images** — paste from Figma, screenshot, or upload
111
+ - **Viewport, URL, DPR** page context
119
112
 
120
- O agente não precisa adivinhar tem tudo que precisa pra agir.
113
+ The agent doesn't guessit has everything it needs to act.
121
114
 
122
115
  ---
123
116
 
124
117
  ## Features
125
118
 
126
- - **3 modos de captura** — click em elemento, seleção de texto, arrastar área
127
- - **Imagem de referência** — Cole screenshot do Figma direto no textarea (Cmd+V)
128
- - **Animation pause** — Congela animações pra anotar tooltips, toasts, dropdowns
129
- - **Envio individual ou batch** — anota várias, envia de uma vez
130
- - **Smart augmentation** — filtra styles por intent (layout, cor, spacing, tipografia)
131
- - **Fallback inteligente** — MCP clipboard modal
132
- - **Análise estática** (bônus) `ilse check` detecta tokens hardcoded, a11y, consistência
119
+ - **3 capture modes** — click element, select text, draw area
120
+ - **Reference images** — paste screenshots or upload. Inline badges with hover preview
121
+ - **Suggestions** — static analysis (contrast, a11y, touch targets, DS tokens) + AI analysis on demand
122
+ - **Design intelligence** — auto-detects design tokens from tailwind.config, tokens.json, CSS variables
123
+ - **Chat mode** — free-text instructions without selecting an element
124
+ - **Page scan** — full-page design audit with categorized issues
125
+ - **Resize & snap** — drag handles with snap-to-grid (8px default, configurable)
126
+ - **Animation freeze** — pause animations to annotate tooltips, toasts, dropdowns
127
+ - **Batch send** — annotate multiple elements, send all at once
128
+ - **Smart augmentation** — filters styles by intent (layout, color, spacing, typography)
129
+ - **Session resume** — agent keeps context between annotations
130
+ - **Stream progress** — see each fix resolve in real-time
131
+ - **i18n** — auto-detects system language (English / Portuguese), switchable in settings
133
132
 
134
133
  ---
135
134
 
136
135
  ## CLI
137
136
 
138
- A Ilse também tem CLI pra análise estática:
139
-
140
137
  ```bash
141
- npx @iversondantas/ilse@beta init # setup interativo
142
- npx @iversondantas/ilse@beta check # análise estática
143
- npx @iversondantas/ilse@beta listen # debug mode (WS server)
138
+ ilse # start (first-run setup + listen mode)
139
+ ilse listen # manual mode (no auto-execute)
140
+ ilse annotations # list annotations
141
+ ilse resolve <id> # resolve an annotation
142
+ ilse setup # register MCP server in Claude Code
143
+ ilse --reset # reset setup
144
144
  ```
145
145
 
146
146
  ---
147
147
 
148
- ## Filosofia
149
-
150
- IA liberou designers do gargalo de execução, mas craft ainda exige esforço humano.
151
-
152
- A Ilse existe para potencializar o uso de IA no craft. Não é craft vs. IA — pelo contrário. O designer aponta o que o olho vê. O agente faz o que a mão faria.
153
-
154
- > "Design é uma ferramenta para melhorar a humanidade." — Ilse Crawford
155
-
156
- ---
157
-
158
- ## Compatibilidade
148
+ ## Agent compatibility
159
149
 
160
150
  | Framework | Status |
161
151
  |---|---|
162
- | Next.js 13+ | ✓ |
152
+ | Next.js 13+ (App & Pages Router) | ✓ |
163
153
  | Vite + React | ✓ |
164
154
  | Create React App | ✓ |
165
155
  | Remix | ✓ |
166
156
  | Astro + React | ✓ |
167
157
 
168
- | Agente | Integração |
158
+ | Agent | Integration |
169
159
  |---|---|
170
- | Claude Code | MCP nativo + skill `/ilse` |
160
+ | Claude Code | MCP native + auto-execute |
171
161
  | Cursor | MCP |
172
162
  | VS Code (Copilot/Continue) | MCP |
173
- | Codex, ChatGPT, Gemini | Clipboard automático |
163
+ | Codex, Gemini | Auto-execute via CLI |
164
+ | Any other | Clipboard fallback |
174
165
 
175
166
  ---
176
167
 
177
- ## Status
168
+ ## Philosophy
169
+
170
+ AI freed designers from the execution bottleneck, but craft still demands human judgment.
178
171
 
179
- Beta público. `0.2.0-beta.x`em desenvolvimento ativo.
172
+ Ilse is the designer's eye inside the agent: you point at what's wrong, the agent fixes it, you approve. Magic but in control.
180
173
 
181
- Quer reportar bug ou sugerir feature? Abre uma issue: github.com/idantas/ilse
174
+ > "Design is a tool for improving humanity." Ilse Crawford
182
175
 
183
176
  ---
184
177
 
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/agent/executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAM9C,wBAAgB,sBAAsB,IAAI,IAAI,CAK7C;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,cAAc,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEhF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAqBD,wBAAgB,WAAW,IAAI,cAAc,CAM5C;AAkED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CA4DjG;AAID,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,eAAe,CAAC,CA8E1B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,UAAU,EAAE,EACzB,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACf,GACL,OAAO,CAAC,oBAAoB,CAAC,CA+I/B"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/agent/executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAM9C,wBAAgB,sBAAsB,IAAI,IAAI,CAK7C;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,cAAc,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEhF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAqBD,wBAAgB,WAAW,IAAI,cAAc,CAM5C;AAwHD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAwGjG;AAID,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,eAAe,CAAC,CA8E1B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,UAAU,EAAE,EACzB,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACf,GACL,OAAO,CAAC,oBAAoB,CAAC,CAgL/B"}
@@ -41,44 +41,61 @@ export function detectAgent() {
41
41
  // ── Prompt formatting ───────────────────────────────────────────────────────
42
42
  function buildPrompt(annotation) {
43
43
  const augmented = augmentAnnotation(annotation);
44
+ const isChat = annotation.intent === 'chat';
44
45
  const isMove = annotation.intent === 'move' && annotation.rearrangeData;
45
46
  const isCreate = annotation.intent === 'create';
46
47
  const instructions = [];
47
- if (isMove) {
48
+ const isAnalyze = annotation.intent === 'analyze';
49
+ if (isAnalyze) {
50
+ instructions.push('Ilse detected issues on this element. Perform a design review.', '', 'Element context:', augmented.context, '', 'INSTRUCTIONS:', '1. Read the component source file (use the grep pattern or component name)', '2. Check REUSE: is there a reusable component in the project (e.g. components/ui/Button) that should be used instead of inline classes? List the path.', '3. Check CONSISTENCY: does this element follow the same pattern as similar ones? (font-weight, padding, colors)', '4. Check DS: if there are design tokens in the project (tailwind.config, tokens.json, theme), does the element use the correct tokens?', '5. List issues in 1-3 short, direct bullet points.', '6. Do NOT make edits. Only analyze and report.');
51
+ }
52
+ else if (annotation.intent === 'resize') {
53
+ const orig = annotation.rearrangeData?.originalRect;
54
+ const curr = annotation.rearrangeData?.currentRect;
55
+ instructions.push('The designer RESIZED this element. You must change the size in the code.', '', ...(orig && curr ? [
56
+ `Original size: ${orig.width}×${orig.height}px`,
57
+ `Desired size: ${curr.width}×${curr.height}px`,
58
+ `Delta: Δw=${curr.width - orig.width}px, Δh=${curr.height - orig.height}px`,
59
+ ] : []), '', 'HOW TO RESIZE:', '1. Find the element in the code using the grep pattern or selector', '2. Analyze how the size is defined (width/height, padding, min/max, flex)', '3. Apply the appropriate change for the context:', ' - If it has explicit width/height: adjust the values', ' - If padding/margin defines the size: adjust the padding', ' - If flex/grid: adjust flex-basis, min-width, or content', '4. Respect the existing layout — do not break responsiveness');
60
+ }
61
+ else if (isChat) {
62
+ instructions.push('The designer sent a direct instruction. EXECUTE — do not analyze, do not ask, do not request confirmation.', '', 'Instruction:', '"""', augmented.note, '"""', '', 'RULES:', '- APPLY the requested change. Read the files, edit, save.', '- If it is a question: answer in 1-2 direct sentences.', '- Do NOT analyze. Do NOT ask "confirm?". Do NOT say "this annotation is of type X". Just do it.', '- Be surgical — edit only what is necessary.');
63
+ }
64
+ else if (isMove) {
48
65
  const { originalRect: o, currentRect: c } = annotation.rearrangeData;
49
66
  const dx = c.x - o.x;
50
67
  const dy = c.y - o.y;
51
- instructions.push('O designer ARRASTOU este elemento para uma nova posição. Você deve mover o elemento no código.', '', `Direção do movimento: ${dx > 0 ? 'para a direita' : dx < 0 ? 'para a esquerda' : 'sem deslocamento horizontal'} (${dx}px), ${dy > 0 ? 'para baixo' : dy < 0 ? 'para cima' : 'sem deslocamento vertical'} (${dy}px)`, '', 'COMO MOVER:', '1. Encontre o elemento no código usando o grep pattern ou selector', '2. Analise o layout atual (flex, grid, static, absolute)', '3. Aplique a mudança adequada ao contexto:', ' - Flexbox/Grid: mude a order, mova o elemento no JSX, ou ajuste align-self/justify-self', ' - Se precisa mudar a ORDEM entre irmãos: reordene os elementos no JSX/HTML', ' - Position absolute/fixed: ajuste top/left/right/bottom', ' - Static: use margin ou mude a posição no DOM', '4. NÃO adicione position:absolute para moverrespeite o layout existente', '5. Se o delta é pequeno (< 20px), pode ser ajuste de margin/padding', '6. Se o delta é grande, pode significar reordenação de elementos');
68
+ instructions.push('The designer DRAGGED this element to a new position. You must move the element in the code.', '', `Movement direction: ${dx > 0 ? 'right' : dx < 0 ? 'left' : 'no horizontal displacement'} (${dx}px), ${dy > 0 ? 'down' : dy < 0 ? 'up' : 'no vertical displacement'} (${dy}px)`, '', 'HOW TO MOVE:', '1. Find the element in the code using the grep pattern or selector', '2. Analyze the current layout (flex, grid, static, absolute)', '3. Apply the appropriate change for the context:', ' - Flexbox/Grid: change order, reorder the element in JSX, or adjust align-self/justify-self', ' - If you need to change ORDER among siblings: reorder elements in JSX/HTML', ' - Position absolute/fixed: adjust top/left/right/bottom', ' - Static: use margin or change position in DOM', '4. Do NOT add position:absolute just to moverespect the existing layout', '5. If delta is small (< 20px), it may be a margin/padding adjustment', '6. If delta is large, it may mean element reordering');
52
69
  }
53
70
  else if (isCreate) {
54
- instructions.push('O designer marcou uma ÁREA VAZIA onde quer que você CRIE conteúdo novo.', '', 'COMO CRIAR:', '1. Encontre o container mais próximo usando o selector ou parent', '2. Crie o elemento descrito na nota do designer', '3. Posicione dentro do container existente, no local mais lógico', '4. Siga o padrão visual e de código dos componentes vizinhos');
71
+ instructions.push('The designer marked an EMPTY AREA where you should CREATE new content.', '', 'HOW TO CREATE:', '1. Find the nearest container using the selector or parent', '2. Create the element described in the designer\'s note', '3. Position it inside the existing container, in the most logical spot', '4. Follow the visual and code patterns of neighboring components');
55
72
  }
56
73
  else {
57
- instructions.push('1. Analise se o problema está na DEFINIÇÃO do componente ou na INSTÂNCIA específica', '2. Se é um problema de estilo padrão, corrija no componente base', '3. Se é específico dessa instância, corrija no uso', '4. Se o mesmo problema pode existir em outras ocorrências, procure com o grep pattern e corrija todas', '5. Seja cirúrgicoedite apenas o necessário');
74
+ instructions.push('1. Analyze whether the issue is in the component DEFINITION or the specific INSTANCE', '2. If it is a default style issue, fix it in the base component', '3. If it is specific to this instance, fix only the usage', '4. If the same issue may exist in other occurrences, search with the grep pattern and fix all', '5. Be surgicaledit only what is necessary');
58
75
  }
59
76
  return [
60
- 'Você recebeu uma anotação visual do designer via Ilse (visual feedback tool).',
77
+ 'You received a visual annotation from the designer via Ilse (visual feedback tool).',
61
78
  '',
62
- 'Contexto do elemento:',
79
+ 'Element context:',
63
80
  augmented.context,
64
81
  '',
65
- 'INSTRUÇÕES:',
82
+ 'INSTRUCTIONS:',
66
83
  ...instructions,
67
84
  '',
68
- 'Após aplicar as mudanças, responda em UMA linha (máximo 15 palavras) o que você mudou.',
69
- 'Exemplo: "Ajustei align-items do Button em components/Button.tsx"',
85
+ 'After applying changes, respond in ONE line (max 15 words) describing what you changed.',
86
+ 'Example: "Adjusted align-items on Button in components/Button.tsx"',
70
87
  ].join('\n');
71
88
  }
72
89
  export function buildBatchPrompt(annotations, opts) {
73
90
  const sections = annotations.map((ann, i) => {
74
91
  const augmented = augmentAnnotation(ann);
75
- return `### Anotação #${i + 1} (id: ${ann.id})\n${augmented.context}`;
92
+ return `### Annotation #${i + 1} (id: ${ann.id})\n${augmented.context}`;
76
93
  });
77
94
  // Resumed session: agent already has instructions, just send the new annotation(s)
78
95
  if (opts?.isResume) {
79
96
  const count = annotations.length;
80
97
  return [
81
- `Nova${count > 1 ? 's' : ''} ${count === 1 ? 'anotação' : `${count} anotações`} do designer. Mesmas regras de antes.`,
98
+ `New ${count === 1 ? 'annotation' : `${count} annotations`} from the designer. Same rules as before.`,
82
99
  '',
83
100
  ...sections,
84
101
  ].join('\n');
@@ -86,45 +103,86 @@ export function buildBatchPrompt(annotations, opts) {
86
103
  // First invocation: full instructions
87
104
  const hasMove = annotations.some(a => a.intent === 'move' && a.rearrangeData);
88
105
  const hasCreate = annotations.some(a => a.intent === 'create');
106
+ const hasChat = annotations.some(a => a.intent === 'chat');
107
+ const allChat = annotations.every(a => a.intent === 'chat');
108
+ const allAnalyze = annotations.every(a => a.intent === 'analyze');
89
109
  const count = annotations.length;
110
+ // Pure analyze batch — design review mode
111
+ if (allAnalyze) {
112
+ return [
113
+ `Analyze ${count === 1 ? 'this element' : `these ${count} elements`} from a design perspective.`,
114
+ '',
115
+ 'RULES:',
116
+ '- Read the source code of each element (use grep pattern or component name)',
117
+ '- Check REUSE: is there a reusable component (e.g. components/ui/Button) that should be used?',
118
+ '- Check CONSISTENCY: does the element follow the same pattern as similar ones in the project?',
119
+ '- Check DS: if there are tokens (tailwind.config, tokens.json, theme), does the element use the correct ones?',
120
+ '- Do NOT make edits. Only analyze and report in short bullet points.',
121
+ '',
122
+ ...sections,
123
+ '',
124
+ 'OUTPUT BEHAVIOR:',
125
+ '- For each element, print one line:',
126
+ ' #<id>: <analysis in max 20 words>',
127
+ ].join('\n');
128
+ }
129
+ // Pure chat batch — simplified preamble
130
+ if (allChat) {
131
+ return [
132
+ `Direct instruction from the designer. EXECUTE — do not analyze, do not ask for confirmation.`,
133
+ '',
134
+ 'RULES:',
135
+ '- APPLY the requested change. Read the files, edit, save.',
136
+ '- If it is a question: answer in 1-2 direct sentences.',
137
+ '- Do NOT analyze. Do NOT ask "confirm?". Just do it.',
138
+ '- Be surgical — edit only what is necessary.',
139
+ '',
140
+ ...sections,
141
+ '',
142
+ 'OUTPUT BEHAVIOR:',
143
+ '- Before each action, briefly state (1 short sentence) what you are doing.',
144
+ '- After finishing EACH message individually, IMMEDIATELY print a line in this format:',
145
+ ' #<id>: <what you did in max 15 words>',
146
+ ].join('\n');
147
+ }
90
148
  return [
91
- `Você recebeu ${count} ${count === 1 ? 'anotação visual' : 'anotações visuais'} do designer via Ilse (visual feedback tool).`,
149
+ `You received ${count} visual ${count === 1 ? 'annotation' : 'annotations'} from the designer via Ilse (visual feedback tool).`,
92
150
  ...(count > 1 ? [
93
- 'Corrija TODAS em uma única passada. Analise o conjunto antes de agir:',
151
+ 'Fix ALL in a single pass. Analyze the set before acting:',
94
152
  ] : [
95
- 'Corrija esta anotação:',
153
+ 'Fix this annotation:',
96
154
  ]),
97
- '- Se duas anotações são no mesmo elemento, consolide',
98
- '- Se um mesmo padrão aparece em várias, corrija no componente base',
99
- '- Se o mesmo problema pode existir em outras ocorrências fora das anotações, procure com grep e corrija',
100
- '- Seja cirúrgicoedite apenas o necessário',
155
+ '- If two annotations are on the same element, consolidate',
156
+ '- If the same pattern appears in several, fix it in the base component',
157
+ '- If the same issue may exist in other occurrences outside the annotations, search with grep and fix all',
158
+ '- Be surgicaledit only what is necessary',
101
159
  ...(hasMove ? [
102
160
  '',
103
- 'ANOTAÇÕES DE MOVER (intent: move):',
104
- '- O designer ARRASTOU elementos para novas posições. O campo **Move** mostra o delta em pixels.',
105
- '- Para mover: analise o layout (flex/grid/static) e aplique a mudança adequada:',
106
- ' flexbox/grid → mude order, reordene JSX, ou ajuste align-self',
107
- ' position absolute → ajuste top/left',
108
- ' static → ajuste margin ou reordene no DOM',
109
- '- NÃO adicione position:absolute para moverrespeite o layout existente',
110
- '- Delta pequeno (< 20px) = ajuste de margin/padding. Delta grande = reordenação.',
161
+ 'MOVE ANNOTATIONS (intent: move):',
162
+ '- The designer DRAGGED elements to new positions. The **Move** field shows the delta in pixels.',
163
+ '- To move: analyze the layout (flex/grid/static) and apply the appropriate change:',
164
+ ' flexbox/grid → change order, reorder JSX, or adjust align-self',
165
+ ' position absolute → adjust top/left',
166
+ ' static → adjust margin or reorder in DOM',
167
+ '- Do NOT add position:absolute just to moverespect the existing layout',
168
+ '- Small delta (< 20px) = margin/padding adjustment. Large delta = element reordering.',
111
169
  ] : []),
112
170
  ...(hasCreate ? [
113
171
  '',
114
- 'ANOTAÇÕES DE CRIAR (intent: create):',
115
- '- O designer marcou áreas vazias onde quer conteúdo novo.',
116
- '- Crie o elemento descrito na nota, dentro do container mais próximo.',
117
- '- Siga o padrão visual e de código dos componentes vizinhos.',
172
+ 'CREATE ANNOTATIONS (intent: create):',
173
+ '- The designer marked empty areas where new content is needed.',
174
+ '- Create the element described in the note, inside the nearest container.',
175
+ '- Follow the visual and code patterns of neighboring components.',
118
176
  ] : []),
119
177
  '',
120
178
  ...sections,
121
179
  '',
122
- 'COMPORTAMENTO DE OUTPUT:',
123
- '- Antes de cada ação, fale brevemente (1 frase curta em pt-BR) o que você está fazendo.',
124
- ' Ex: "Vou ler o Header pra entender o layout", "Procurando o componente Button", "Ajustando o alinhamento".',
125
- '- Após terminar CADA anotação individualmente (não no final), imprima IMEDIATAMENTE uma linha no formato:',
126
- ' #<id>: <o que fez em no máximo 15 palavras>',
127
- '- Não acumule resumos pro final. Reporte um por um, em ordem, assim que terminar cada edição.',
180
+ 'OUTPUT BEHAVIOR:',
181
+ '- Before each action, briefly state (1 short sentence) what you are doing.',
182
+ ' E.g.: "Reading the Header to understand the layout", "Searching for the Button component", "Adjusting alignment".',
183
+ '- After finishing EACH annotation individually (not at the end), IMMEDIATELY print a line in this format:',
184
+ ' #<id>: <what you did in max 15 words>',
185
+ '- Do not accumulate summaries for the end. Report one by one, in order, as soon as you finish each edit.',
128
186
  ].join('\n');
129
187
  }
130
188
  export async function executeAnnotation(annotation, agent, options = {}) {
@@ -228,7 +286,8 @@ export async function executeBatch(annotations, agent, options = {}) {
228
286
  let timedOut = false;
229
287
  let sessionId;
230
288
  const summaries = new Map();
231
- let resolvedIndex = 0; // next annotation to resolve via tool_use order
289
+ let resolvedIndex = 0; // fallback: resolve by order when file_path matching fails
290
+ const resolvedIds = new Set(); // track which annotations have been resolved
232
291
  const proc = spawn(agent.command, args, {
233
292
  cwd,
234
293
  env: process.env,
@@ -263,13 +322,44 @@ export async function executeBatch(annotations, agent, options = {}) {
263
322
  // Parse stream-json events
264
323
  try {
265
324
  const event = JSON.parse(trimmed);
266
- handleStreamEvent(event, annotations, summaries, () => {
267
- if (resolvedIndex < annotations.length) {
268
- const ann = annotations[resolvedIndex++];
269
- const summary = `Editando ${ann.component ?? ann.element}`;
270
- if (!summaries.has(ann.id)) {
271
- summaries.set(ann.id, summary);
272
- options.onProgress?.(ann.id, summary);
325
+ handleStreamEvent(event, annotations, summaries, (filePath) => {
326
+ // Try to match by file_path first
327
+ let matched = false;
328
+ if (filePath) {
329
+ const basename = filePath.split('/').pop() ?? '';
330
+ for (const ann of annotations) {
331
+ if (resolvedIds.has(ann.id))
332
+ continue;
333
+ // Match if grepPattern contains the filename or component name
334
+ const grep = ann.grepPattern ?? '';
335
+ const comp = ann.component ?? '';
336
+ if ((grep && filePath.includes(grep.split(/[:\s]/)[0])) ||
337
+ (comp && basename.toLowerCase().includes(comp.toLowerCase())) ||
338
+ (basename && grep.toLowerCase().includes(basename.toLowerCase()))) {
339
+ resolvedIds.add(ann.id);
340
+ const summary = `Editando ${basename}`;
341
+ if (!summaries.has(ann.id)) {
342
+ summaries.set(ann.id, summary);
343
+ options.onProgress?.(ann.id, summary);
344
+ }
345
+ matched = true;
346
+ break;
347
+ }
348
+ }
349
+ }
350
+ // Fallback: resolve by order
351
+ if (!matched) {
352
+ while (resolvedIndex < annotations.length && resolvedIds.has(annotations[resolvedIndex].id)) {
353
+ resolvedIndex++;
354
+ }
355
+ if (resolvedIndex < annotations.length) {
356
+ const ann = annotations[resolvedIndex++];
357
+ resolvedIds.add(ann.id);
358
+ const summary = `Editando ${ann.component ?? ann.element}`;
359
+ if (!summaries.has(ann.id)) {
360
+ summaries.set(ann.id, summary);
361
+ options.onProgress?.(ann.id, summary);
362
+ }
273
363
  }
274
364
  }
275
365
  }, (id) => { sessionId = id; }, (thinking) => options.onThinking?.(thinking));
@@ -356,7 +446,8 @@ function handleStreamEvent(event, annotations, summaries, onToolUse, onSessionId
356
446
  if (thinking)
357
447
  onThinking(thinking);
358
448
  if (toolName && ['Edit', 'Write', 'MultiEdit', 'Update'].includes(toolName)) {
359
- onToolUse();
449
+ const filePath = typeof input?.file_path === 'string' ? input.file_path : undefined;
450
+ onToolUse(filePath);
360
451
  }
361
452
  }
362
453
  // Text blocks: emit as thinking (cleaned up), also parse "#<id>:" summary pattern
@@ -432,7 +523,7 @@ function parseBatchSummaries(stdout, annotations) {
432
523
  result.set(match[1], match[2].trim());
433
524
  }
434
525
  }
435
- // Fill missing summaries with fallback
526
+ // Fill missing summaries with fallback (skip analyze — those should have real analysis)
436
527
  for (const ann of annotations) {
437
528
  if (!result.has(ann.id)) {
438
529
  result.set(ann.id, 'Corrigido');