@codewithdan/zingit 0.13.0 → 0.14.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.
- package/AGENTS.md +113 -25
- package/README.md +70 -24
- package/client/dist/zingit-client.js +41 -6
- package/package.json +1 -1
- package/server/dist/handlers/messageHandlers.js +3 -0
package/AGENTS.md
CHANGED
|
@@ -2,10 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Project Overview
|
|
4
4
|
|
|
5
|
-
ZingIt is a browser-based annotation tool that allows users to click on webpage elements and add notes/instructions. These annotations are then sent to an AI agent (Claude Code or
|
|
5
|
+
ZingIt is a browser-based annotation tool that allows users to click on webpage elements and add notes/instructions. These annotations are then sent to an AI agent (Claude Code, GitHub Copilot CLI, or OpenAI Codex) which can automatically implement the requested changes.
|
|
6
6
|
|
|
7
7
|
**Use case**: Point-and-click UI feedback that gets automatically implemented by AI.
|
|
8
8
|
|
|
9
|
+
**Key Features**:
|
|
10
|
+
- Visual element selection with annotation
|
|
11
|
+
- Multi-agent support (Claude, Copilot, Codex)
|
|
12
|
+
- Automatic screenshot capture
|
|
13
|
+
- Change history tracking
|
|
14
|
+
- Remote/local URL detection with warnings
|
|
15
|
+
- Keyboard shortcuts for fast workflow
|
|
16
|
+
|
|
9
17
|
## Architecture
|
|
10
18
|
|
|
11
19
|
```
|
|
@@ -13,17 +21,18 @@ ZingIt is a browser-based annotation tool that allows users to click on webpage
|
|
|
13
21
|
│ Browser │
|
|
14
22
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
15
23
|
│ │ ZingIt Client │ │
|
|
16
|
-
│ │ (Lit Web Components
|
|
24
|
+
│ │ (Lit Web Components - ?zingit URL parameter) │ │
|
|
17
25
|
│ └──────────────────────┬──────────────────────────────┘ │
|
|
18
26
|
└─────────────────────────┼───────────────────────────────────┘
|
|
19
27
|
│ WebSocket
|
|
20
28
|
▼
|
|
21
29
|
┌─────────────────────────────────────────────────────────────┐
|
|
22
30
|
│ ZingIt Server │
|
|
23
|
-
│ ┌─────────────┐ ┌─────────────┐
|
|
24
|
-
│ │ WebSocket │───▶│ Agent │───▶│ Claude Code
|
|
25
|
-
│ │ Handler │ │ Registry │ │
|
|
26
|
-
│
|
|
31
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │
|
|
32
|
+
│ │ WebSocket │───▶│ Agent │───▶│ Claude Code │ │
|
|
33
|
+
│ │ Handler │ │ Registry │ │ Copilot │ │
|
|
34
|
+
│ │ │ │ │ │ Codex │ │
|
|
35
|
+
│ └─────────────┘ └─────────────┘ └──────────────┘ │
|
|
27
36
|
└─────────────────────────────────────────────────────────────┘
|
|
28
37
|
```
|
|
29
38
|
|
|
@@ -42,7 +51,10 @@ zingit/
|
|
|
42
51
|
│ │ │ ├── settings.ts # Configuration panel
|
|
43
52
|
│ │ │ ├── response.ts # Agent response display
|
|
44
53
|
│ │ │ ├── toast.ts # Notification toasts
|
|
45
|
-
│ │ │
|
|
54
|
+
│ │ │ ├── help.ts # Keyboard shortcuts overlay
|
|
55
|
+
│ │ │ ├── history.ts # Change history panel
|
|
56
|
+
│ │ │ ├── site-header.ts # Demo site navigation
|
|
57
|
+
│ │ │ └── site-footer.ts # Demo site footer
|
|
46
58
|
│ │ ├── services/
|
|
47
59
|
│ │ │ ├── selector.ts # CSS selector generation
|
|
48
60
|
│ │ │ ├── storage.ts # localStorage persistence
|
|
@@ -57,14 +69,22 @@ zingit/
|
|
|
57
69
|
│ ├── about.html # Test page
|
|
58
70
|
│ ├── contact.html # Test page
|
|
59
71
|
│ ├── styles.css # Shared styles for test pages
|
|
60
|
-
│
|
|
72
|
+
│ ├── deploy/ # Build output for GitHub Pages
|
|
73
|
+
│ │ ├── index.html # Static version of demo site
|
|
74
|
+
│ │ └── styles.css # Copied styles
|
|
75
|
+
│ ├── scripts/
|
|
76
|
+
│ │ └── prepare-deploy.js # Prepares deploy folder
|
|
77
|
+
│ └── vite.config.ts # Build config
|
|
61
78
|
│
|
|
62
79
|
├── server/ # Node.js WebSocket server
|
|
63
80
|
│ └── src/
|
|
64
81
|
│ ├── agents/
|
|
65
82
|
│ │ ├── base.ts # Abstract base agent class
|
|
66
83
|
│ │ ├── claude.ts # Claude Code CLI integration
|
|
67
|
-
│ │
|
|
84
|
+
│ │ ├── copilot.ts # GitHub Copilot SDK integration
|
|
85
|
+
│ │ └── codex.ts # OpenAI Codex integration
|
|
86
|
+
│ ├── handlers/
|
|
87
|
+
│ │ └── messageHandlers.ts # WebSocket message handlers
|
|
68
88
|
│ ├── types.ts # Server-side TypeScript interfaces
|
|
69
89
|
│ └── index.ts # WebSocket server entry point
|
|
70
90
|
│
|
|
@@ -80,11 +100,12 @@ zingit/
|
|
|
80
100
|
- **Shadow DOM** - Style isolation (critical for bookmarklet injection)
|
|
81
101
|
|
|
82
102
|
### Server
|
|
83
|
-
- **Node.js** - Runtime
|
|
103
|
+
- **Node.js** - Runtime (>=22.0.0)
|
|
84
104
|
- **ws** - WebSocket library
|
|
85
105
|
- **tsx** - TypeScript execution
|
|
86
106
|
- **@anthropic-ai/claude-agent-sdk** - Claude Code integration
|
|
87
107
|
- **@github/copilot-sdk** - GitHub Copilot integration
|
|
108
|
+
- **@openai/codex-sdk** - OpenAI Codex integration
|
|
88
109
|
|
|
89
110
|
## Key Concepts
|
|
90
111
|
|
|
@@ -98,16 +119,24 @@ An annotation captures:
|
|
|
98
119
|
- `parentContext` - Parent element path for context
|
|
99
120
|
- `textContent` - Plain text content
|
|
100
121
|
|
|
122
|
+
### Change History
|
|
123
|
+
The history component tracks all changes made by the AI agent:
|
|
124
|
+
- Displays a chronological list of modifications
|
|
125
|
+
- Shows file paths and change summaries
|
|
126
|
+
- Allows users to review what was changed
|
|
127
|
+
- Accessible via the clock icon in the toolbar
|
|
128
|
+
|
|
101
129
|
### WebSocket Messages
|
|
102
130
|
- **Client → Server**: `batch` (send annotations), `message` (follow-up), `reset` (clear session)
|
|
103
131
|
- **Server → Client**: `connected`, `processing`, `delta` (streaming), `tool_start`/`tool_end`, `idle`, `error`
|
|
104
132
|
|
|
105
133
|
### Agent System
|
|
106
134
|
The server uses a pluggable agent architecture:
|
|
107
|
-
- Set `AGENT=claude` or `AGENT=
|
|
135
|
+
- Set `AGENT=claude`, `AGENT=copilot`, or `AGENT=codex` environment variable
|
|
108
136
|
- Agents implement `Agent` interface with `createSession()` and `formatPrompt()`
|
|
109
137
|
- Claude agent spawns `claude --print` CLI process
|
|
110
138
|
- Copilot agent uses the GitHub Copilot SDK
|
|
139
|
+
- Codex agent uses the OpenAI Codex SDK
|
|
111
140
|
|
|
112
141
|
## Development Commands
|
|
113
142
|
|
|
@@ -116,26 +145,36 @@ The server uses a pluggable agent architecture:
|
|
|
116
145
|
cd client
|
|
117
146
|
npm install
|
|
118
147
|
npm run dev # Start Vite dev server (http://localhost:5200)
|
|
119
|
-
npm run build # Build for production
|
|
148
|
+
npm run build # Build for production
|
|
149
|
+
npm run deploy # Prepare and deploy to GitHub Pages
|
|
120
150
|
npm run typecheck # Type check without emitting
|
|
121
151
|
npm run typecheck:watch # Watch mode type checking
|
|
122
152
|
```
|
|
123
153
|
|
|
154
|
+
**Note**: The deploy script (`npm run deploy`) runs `prepare-deploy.js` which copies files to the `deploy/` folder, then uses `gh-pages` to publish to GitHub Pages.
|
|
155
|
+
|
|
124
156
|
### Server
|
|
125
157
|
```bash
|
|
126
158
|
cd server
|
|
127
159
|
npm install
|
|
128
|
-
AGENT=claude npm run dev # Start with Claude Code agent
|
|
129
|
-
AGENT=copilot npm run dev # Start with GitHub Copilot agent
|
|
130
|
-
npm run
|
|
131
|
-
npm run typecheck
|
|
160
|
+
npx cross-env AGENT=claude npm run dev # Start with Claude Code agent
|
|
161
|
+
npx cross-env AGENT=copilot npm run dev # Start with GitHub Copilot agent
|
|
162
|
+
npx cross-env AGENT=codex npm run dev # Start with OpenAI Codex agent
|
|
163
|
+
npm run typecheck # Type check
|
|
164
|
+
npm run typecheck:watch # Watch mode type checking
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Running the Published Package
|
|
168
|
+
```bash
|
|
169
|
+
# For external users
|
|
170
|
+
npx cross-env PROJECT_DIR=/path/to/your/project npx @codewithdan/zingit
|
|
132
171
|
```
|
|
133
172
|
|
|
134
173
|
## Keyboard Shortcuts
|
|
135
174
|
|
|
136
175
|
| Key | Action |
|
|
137
176
|
|-----|--------|
|
|
138
|
-
| `
|
|
177
|
+
| `Z` | Toggle annotation mode on/off |
|
|
139
178
|
| `Ctrl/Cmd+Z` | Undo last annotation |
|
|
140
179
|
| `?` | Show help overlay |
|
|
141
180
|
| `` ` `` | Toggle ZingIt visibility |
|
|
@@ -151,8 +190,15 @@ The client persists state to `localStorage`:
|
|
|
151
190
|
|
|
152
191
|
## Important Implementation Details
|
|
153
192
|
|
|
193
|
+
### Remote URL Detection
|
|
194
|
+
ZingIt detects when you're editing a published/remote site versus local development:
|
|
195
|
+
- **Local** (localhost, 127.0.0.1, etc.) - Changes appear immediately on refresh
|
|
196
|
+
- **Remote** (published sites) - Shows warning toast that changes are saved locally only
|
|
197
|
+
- Badge displayed in toolbar: "💻 Local" or "🌐 Remote"
|
|
198
|
+
- Warning can be dismissed but persists until user understands the limitation
|
|
199
|
+
|
|
154
200
|
### Shadow DOM
|
|
155
|
-
All components use Shadow DOM for style isolation. This is critical because ZingIt is injected
|
|
201
|
+
All components use Shadow DOM for style isolation. This is critical because ZingIt is injected into arbitrary pages - styles must not leak in or out.
|
|
156
202
|
|
|
157
203
|
### Viewport Coordinates
|
|
158
204
|
The highlight and marker positioning uses viewport coordinates (not page coordinates) because the main `zing-ui` component is `position: fixed`. Use `getElementViewportRect()` from `geometry.ts`.
|
|
@@ -163,6 +209,15 @@ The WebSocket client implements exponential backoff reconnection:
|
|
|
163
209
|
- Max 10 attempts before showing "Reconnect" button
|
|
164
210
|
- Call `forceReconnect()` to manually retry
|
|
165
211
|
|
|
212
|
+
### Toast Notifications
|
|
213
|
+
The toast system supports multiple types with different styling:
|
|
214
|
+
- **success** - Green background for successful operations
|
|
215
|
+
- **error** - Red background for failures
|
|
216
|
+
- **info** - Dark gray with subtle border
|
|
217
|
+
- **warning** - Dark gray with orange left border (for remote URL warnings)
|
|
218
|
+
|
|
219
|
+
Persistent toasts (duration=0) show a close button in the top-right corner.
|
|
220
|
+
|
|
166
221
|
### Component Communication
|
|
167
222
|
Components communicate via custom events that bubble through Shadow DOM:
|
|
168
223
|
```typescript
|
|
@@ -173,6 +228,18 @@ this.dispatchEvent(new CustomEvent('save', {
|
|
|
173
228
|
}));
|
|
174
229
|
```
|
|
175
230
|
|
|
231
|
+
### Server Logging
|
|
232
|
+
Request boundaries are logged for debugging:
|
|
233
|
+
```
|
|
234
|
+
[Batch] ===== Request started =====
|
|
235
|
+
[Batch] Prompt preview: Change the background color to blue...
|
|
236
|
+
[Batch] Image count: 2
|
|
237
|
+
... processing logs ...
|
|
238
|
+
[Batch] ===== Request completed =====
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
This makes it easy to track multiple concurrent requests and debug issues.
|
|
242
|
+
|
|
176
243
|
## Common Tasks
|
|
177
244
|
|
|
178
245
|
### Adding a New Component
|
|
@@ -194,21 +261,42 @@ Edit `client/src/components/toolbar.ts`:
|
|
|
194
261
|
- Create handler method that dispatches event
|
|
195
262
|
- Wire up event in `zing-ui.ts`
|
|
196
263
|
|
|
264
|
+
**Note**: Icons use SVG (not emoticons) for professional appearance and better rendering across platforms. The local/remote badge uses inline SVG icons with `currentColor` for theming.
|
|
265
|
+
|
|
197
266
|
## Testing
|
|
198
267
|
|
|
199
|
-
|
|
200
|
-
|
|
268
|
+
### Demo Site
|
|
269
|
+
The main demo site (`client/index.html`) showcases ZingIt with:
|
|
270
|
+
- Hero section with features
|
|
271
|
+
- Installation instructions
|
|
272
|
+
- Toolbar icon reference table
|
|
273
|
+
- Try it with demo section
|
|
274
|
+
- Try it with your website section
|
|
275
|
+
|
|
276
|
+
### Test Pages
|
|
277
|
+
Additional test pages are available:
|
|
201
278
|
- `http://localhost:5200/products.html` - Product cards
|
|
202
279
|
- `http://localhost:5200/about.html` - About page with stats/timeline
|
|
203
280
|
- `http://localhost:5200/contact.html` - Contact form and FAQ
|
|
204
281
|
|
|
282
|
+
Add `?zingit` to any URL to activate the annotation tool.
|
|
283
|
+
|
|
205
284
|
## Build Output
|
|
206
285
|
|
|
207
286
|
The Vite build produces:
|
|
208
|
-
- `dist/zingit.
|
|
209
|
-
- `dist/zingit.iife.js` - IIFE for bookmarklet injection
|
|
287
|
+
- `dist/zingit-client.js` - Bundled client code
|
|
210
288
|
|
|
211
|
-
|
|
212
|
-
```
|
|
213
|
-
|
|
289
|
+
Published to npm as `@codewithdan/zingit` and available via CDN:
|
|
290
|
+
```html
|
|
291
|
+
<script src="https://cdn.jsdelivr.net/npm/@codewithdan/zingit@latest/dist/zingit-client.js"></script>
|
|
214
292
|
```
|
|
293
|
+
|
|
294
|
+
Users activate ZingIt by adding `?zingit` to any URL: `http://localhost:5200/?zingit`
|
|
295
|
+
|
|
296
|
+
## GitHub Actions Workflow
|
|
297
|
+
|
|
298
|
+
Automated release and deployment on commits starting with "release:":
|
|
299
|
+
1. Runs `npm run release` - versions, builds, and publishes to npm
|
|
300
|
+
2. Runs `npm run deploy` - deploys demo site to GitHub Pages
|
|
301
|
+
|
|
302
|
+
Requires `NPM_TOKEN` secret in repository settings.
|
package/README.md
CHANGED
|
@@ -11,57 +11,97 @@ Streamline how you share UI changes with your AI assistant. Select elements, ann
|
|
|
11
11
|
- **Real-time Streaming** - Watch the AI work in real-time
|
|
12
12
|
- **Smart Selectors** - Auto-generates CSS selectors for precise targeting
|
|
13
13
|
- **Screenshot Capture** - Automatically capture annotated elements to provide visual context to agents
|
|
14
|
+
- **Change History** - Track all modifications made by your AI assistant
|
|
15
|
+
- **Remote/Local Detection** - Warns when editing published sites vs local development
|
|
14
16
|
|
|
15
17
|
## Quick Start
|
|
16
18
|
|
|
17
|
-
### Option 1:
|
|
19
|
+
### Option 1: Clone the Repo and Run Locally
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
1. **Install an AI agent** - Install and login to one of these AI agents on your dev machine:
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
- [Claude Code](https://github.com/anthropics/claude-code)
|
|
24
|
+
- [GitHub Copilot CLI](https://github.com/github/copilot-cli)
|
|
25
|
+
- [OpenAI Codex](https://github.com/openai/codex)
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
2. **Clone and setup**:
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- [GitHub Copilot CLI](https://github.com/github/copilot-cli)
|
|
29
|
-
- [OpenAI Codex](https://github.com/openai/codex)
|
|
29
|
+
```bash
|
|
30
|
+
git clone https://github.com/danwahlin/zingit.git
|
|
31
|
+
```
|
|
30
32
|
|
|
31
|
-
3. Start the server:
|
|
33
|
+
3. **Start the ZingIt server** (in one terminal):
|
|
32
34
|
|
|
33
35
|
```bash
|
|
34
|
-
|
|
36
|
+
cd zingit/server
|
|
37
|
+
npm install
|
|
38
|
+
npx cross-env PROJECT_DIR=../client npm run dev
|
|
35
39
|
```
|
|
36
40
|
|
|
37
41
|
Server runs on `ws://localhost:3000`
|
|
38
42
|
|
|
39
|
-
4.
|
|
43
|
+
4. **Run the demo site** (in another terminal):
|
|
40
44
|
|
|
41
45
|
```bash
|
|
42
|
-
cd client
|
|
46
|
+
cd zingit/client
|
|
47
|
+
npm install
|
|
43
48
|
npm run dev
|
|
44
49
|
```
|
|
45
50
|
|
|
46
|
-
5. Visit [http://localhost:5200
|
|
51
|
+
5. Visit [http://localhost:5200/?zingit](http://localhost:5200/?zingit) to see ZingIt in action!
|
|
47
52
|
|
|
48
|
-
6.
|
|
53
|
+
6. You'll be prompted to select an AI agent. Start annotating!
|
|
49
54
|
|
|
50
|
-
### Option
|
|
55
|
+
### Option 2: Add to Your Website
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
1. **Start the ZingIt server**:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx cross-env PROJECT_DIR=/path/to/your/project npx @codewithdan/zingit
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Replace `/path/to/your/project` with your project path.
|
|
64
|
+
|
|
65
|
+
2. **Add the ZingIt script** to your HTML pages just before the closing `</body>` tag:
|
|
53
66
|
|
|
54
67
|
```html
|
|
55
|
-
<script src="https://cdn.jsdelivr.net/npm/@codewithdan/zingit@latest/
|
|
56
|
-
<script>ZingIt.connect('ws://localhost:3000');</script>
|
|
68
|
+
<script src="https://cdn.jsdelivr.net/npm/@codewithdan/zingit@latest/dist/zingit-client.js"></script>
|
|
57
69
|
```
|
|
58
70
|
|
|
71
|
+
3. **Run your website's dev server** and visit it with `?zingit` added to the URL.
|
|
72
|
+
|
|
73
|
+
Example: `http://localhost:5200/?zingit`
|
|
74
|
+
|
|
59
75
|
## Usage
|
|
60
76
|
|
|
61
|
-
1. **Press `Z`** to toggle annotation mode
|
|
62
|
-
2. **Click elements** to annotate them
|
|
63
|
-
3. **Click the sparkle icon** (✨) to send to your AI agent
|
|
64
|
-
4. **Watch the agent work** in the response panel
|
|
77
|
+
1. **Press `Z`** to toggle annotation mode on/off
|
|
78
|
+
2. **Click elements** on your page to annotate them - add notes about changes you want
|
|
79
|
+
3. **Click the sparkle icon** (✨) in the toolbar to send annotations to your AI agent
|
|
80
|
+
4. **Watch the agent work** in real-time - the response panel shows streaming updates
|
|
81
|
+
|
|
82
|
+
### Toolbar Icons
|
|
83
|
+
|
|
84
|
+
| Icon | Description |
|
|
85
|
+
|------|-------------|
|
|
86
|
+
| **ON/OFF** | Toggle annotation mode |
|
|
87
|
+
| **✨** (Sparkle) | Send annotations to AI agent |
|
|
88
|
+
| **🕒** (Clock) | View change history |
|
|
89
|
+
| **📋** (Copy) | Export annotations as Markdown |
|
|
90
|
+
| **🧹** (Broom) | Clear all annotations |
|
|
91
|
+
| **?** | View keyboard shortcuts |
|
|
92
|
+
| **⚙️** (Gear) | Open settings |
|
|
93
|
+
| **✕** | Close ZingIt toolbar |
|
|
94
|
+
|
|
95
|
+
### Keyboard Shortcuts
|
|
96
|
+
|
|
97
|
+
| Key | Action |
|
|
98
|
+
|-----|--------|
|
|
99
|
+
| `Z` | Toggle annotation mode on/off |
|
|
100
|
+
| `Ctrl/Cmd+Z` | Undo last annotation |
|
|
101
|
+
| `?` | Show help overlay |
|
|
102
|
+
| `` ` `` | Toggle ZingIt visibility |
|
|
103
|
+
| `Esc` | Close current panel/modal |
|
|
104
|
+
| `Ctrl/Cmd+Enter` | Save annotation (in modal) |
|
|
65
105
|
|
|
66
106
|
## Configuration
|
|
67
107
|
|
|
@@ -89,8 +129,9 @@ zingit/
|
|
|
89
129
|
## Troubleshooting
|
|
90
130
|
|
|
91
131
|
**WebSocket not connected**
|
|
92
|
-
- Ensure server is running: `PROJECT_DIR=/path npx @codewithdan/zingit`
|
|
132
|
+
- Ensure server is running: `npx cross-env PROJECT_DIR=/path npx @codewithdan/zingit`
|
|
93
133
|
- Check WebSocket URL in settings (default: `ws://localhost:3000`)
|
|
134
|
+
- Make sure you've added `?zingit` to your URL
|
|
94
135
|
|
|
95
136
|
**Agent not responding**
|
|
96
137
|
- Verify AI agent is installed and authenticated
|
|
@@ -100,6 +141,11 @@ zingit/
|
|
|
100
141
|
- Annotations are URL-specific and stored in localStorage
|
|
101
142
|
- Changing pages clears annotations
|
|
102
143
|
|
|
144
|
+
**Changes not appearing on published site**
|
|
145
|
+
- If you see a "Remote" badge in the toolbar, you're editing a published site
|
|
146
|
+
- Changes are saved locally only - to see them, run the project locally or deploy the updated files
|
|
147
|
+
- For best experience, use ZingIt with local development (localhost)
|
|
148
|
+
|
|
103
149
|
## License
|
|
104
150
|
|
|
105
151
|
MIT
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
class="edit-mode-badge ${this.isRemoteUrl?"remote":"local"}"
|
|
26
26
|
title="${this.isRemoteUrl?"Changes saved locally - deploy to see on this URL":"Local development - changes appear on refresh"}"
|
|
27
27
|
>
|
|
28
|
-
${this.isRemoteUrl
|
|
28
|
+
${this.isRemoteUrl?$`<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 4px; vertical-align: middle;"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>Remote`:$`<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 4px; vertical-align: middle;"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>Local`}
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
<div class="divider"></div>
|
|
@@ -1758,8 +1758,16 @@
|
|
|
1758
1758
|
<div class="toast-container">
|
|
1759
1759
|
${this.toasts.map(A=>$`
|
|
1760
1760
|
<div class="toast ${A.type} ${this.exitingIds.has(A.id)?"exiting":""}">
|
|
1761
|
+
${0===A.duration?$`
|
|
1762
|
+
<button class="toast-close" @click=${()=>this.dismiss(A.id)} title="Dismiss">
|
|
1763
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1764
|
+
<line x1="18" y1="6" x2="6" y2="18"/>
|
|
1765
|
+
<line x1="6" y1="6" x2="18" y2="18"/>
|
|
1766
|
+
</svg>
|
|
1767
|
+
</button>
|
|
1768
|
+
`:""}
|
|
1761
1769
|
<div class="toast-content">
|
|
1762
|
-
<span>${A.message}</span>
|
|
1770
|
+
<span style="white-space: pre-line;">${A.message}</span>
|
|
1763
1771
|
${A.action?$`
|
|
1764
1772
|
<button class="toast-action" @click=${()=>this.handleAction(A)}>
|
|
1765
1773
|
${A.action.label}
|
|
@@ -1789,15 +1797,17 @@
|
|
|
1789
1797
|
}
|
|
1790
1798
|
|
|
1791
1799
|
.toast {
|
|
1792
|
-
|
|
1800
|
+
position: relative;
|
|
1801
|
+
padding: 12px 36px 12px 16px;
|
|
1793
1802
|
border-radius: 8px;
|
|
1794
1803
|
font-size: 13px;
|
|
1795
1804
|
font-weight: 500;
|
|
1796
1805
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
1797
1806
|
animation: slideUp 0.2s ease-out;
|
|
1798
1807
|
pointer-events: auto;
|
|
1799
|
-
max-width:
|
|
1800
|
-
text-align:
|
|
1808
|
+
max-width: 400px;
|
|
1809
|
+
text-align: left;
|
|
1810
|
+
line-height: 1.5;
|
|
1801
1811
|
}
|
|
1802
1812
|
|
|
1803
1813
|
.toast.success {
|
|
@@ -1816,6 +1826,12 @@
|
|
|
1816
1826
|
border: 1px solid #374151;
|
|
1817
1827
|
}
|
|
1818
1828
|
|
|
1829
|
+
.toast.warning {
|
|
1830
|
+
background: #1f2937;
|
|
1831
|
+
color: white;
|
|
1832
|
+
border-left: 4px solid #f59e0b;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1819
1835
|
.toast.exiting {
|
|
1820
1836
|
animation: slideDown 0.2s ease-in forwards;
|
|
1821
1837
|
}
|
|
@@ -1842,6 +1858,25 @@
|
|
|
1842
1858
|
background: rgba(255, 255, 255, 0.3);
|
|
1843
1859
|
}
|
|
1844
1860
|
|
|
1861
|
+
.toast-close {
|
|
1862
|
+
position: absolute;
|
|
1863
|
+
top: 8px;
|
|
1864
|
+
right: 8px;
|
|
1865
|
+
background: transparent;
|
|
1866
|
+
border: none;
|
|
1867
|
+
color: white;
|
|
1868
|
+
cursor: pointer;
|
|
1869
|
+
padding: 4px;
|
|
1870
|
+
display: flex;
|
|
1871
|
+
align-items: center;
|
|
1872
|
+
opacity: 0.6;
|
|
1873
|
+
transition: opacity 0.15s ease;
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
.toast-close:hover {
|
|
1877
|
+
opacity: 1;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1845
1880
|
@keyframes slideUp {
|
|
1846
1881
|
from {
|
|
1847
1882
|
opacity: 0;
|
|
@@ -2854,7 +2889,7 @@
|
|
|
2854
2889
|
font-family: inherit;
|
|
2855
2890
|
border: 1px solid #4b5563;
|
|
2856
2891
|
}
|
|
2857
|
-
`,ac([hA({type:Boolean})],cc.prototype,"visible",2),ac([hA({type:String})],cc.prototype,"message",2),ac([hA({type:Number})],cc.prototype,"filesModified",2),ac([hA({type:Number})],cc.prototype,"timeout",2),ac([gA()],cc.prototype,"remainingTime",2),cc=ac([cA("zing-undo-bar")],cc);var lc=Object.defineProperty,Bc=Object.getOwnPropertyDescriptor,hc=(A,e,t,n)=>{for(var s,r=n>1?void 0:n?Bc(e,t):e,o=A.length-1;o>=0;o--)(s=A[o])&&(r=(n?s(e,t,r):s(r))||r);return n&&r&&lc(e,t,r),r};let gc=class extends iA{constructor(){super(),this.annotations=[],this.settings=Qa(),this.wsConnected=!1,this.wsMaxAttemptsReached=!1,this.processing=!1,this.agentName="",this.agentModel="",this.serverProjectDir="",this.annotationActive=function(){try{const A=localStorage.getItem(ha);return null===A||JSON.parse(A)}catch{return!0}}(),this.availableAgents=[],this.agentPickerOpen=!1,this.agentPickerLoading=!1,this.agentPickerError="",this.isRemoteUrl=!1,this.currentPageUrl="",this.highlightVisible=!1,this.highlightRect={top:0,left:0,width:0,height:0},this.highlightLabel="",this.modalOpen=!1,this.modalEditMode=!1,this.modalAnnotationId="",this.modalSelector="",this.modalIdentifier="",this.modalSelectedText="",this.modalNotes="",this.pendingElement=null,this.modalCaptureScreenshot=!1,this.modalScreenshotPreview="",this.modalScreenshotLoading=!1,this.settingsOpen=!1,this.helpOpen=!1,this.isHidden=!1,this.responseOpen=!1,this.responseContent="",this.responseToolStatus="",this.responseError="",this.responseScreenshotCount=0,this.isFollowUpMessage=!1,this.undoStack=[],this.historyOpen=!1,this.historyCheckpoints=[],this.historyLoading=!1,this.undoBarVisible=!1,this.undoBarFilesModified=0,this.pendingAnnotationRemovals=new Set,this.undoInProgress=!1,this.recentlyDeletedAnnotation=null,this.deleteUndoTimeout=null,this.processingTimeout=null,this.PROCESSING_TIMEOUT_MS=6e4,this.toolbarPosition=function(){try{const A=localStorage.getItem(ga);return A?JSON.parse(A):null}catch{return null}}(),this.isDragging=!1,this.dragOffset={x:0,y:0},this.ws=null,this.clickHandler=this.handleDocumentClick.bind(this),this.mouseMoveHandler=this.handleDocumentMouseMove.bind(this),this.keydownHandler=this.handleDocumentKeydown.bind(this),this.dragMoveHandler=this.handleDragMove.bind(this),this.dragEndHandler=this.handleDragEnd.bind(this)}connectedCallback(){super.connectedCallback(),this.annotations=function(){try{const A=localStorage.getItem(la);if(!A)return[];const e=JSON.parse(A);return e.url!==window.location.href?[]:Array.isArray(e.annotations)?e.annotations:[]}catch{return[]}}();try{const A=this.annotations.filter(A=>{try{return null!==ca(A.selector)}catch(e){return console.warn(`[ZingIt] Invalid selector "${A.selector}":`,e),!1}});if(A.length<this.annotations.length){const e=this.annotations.length-A.length;console.log(`[ZingIt] Removed ${e} orphaned annotation(s) - elements no longer exist`),this.annotations=A,ua(this.annotations),this.updateComplete.then(()=>{this.toast?.info(`Removed ${e} stale annotation${e>1?"s":""}`)})}}catch(e){console.warn("[ZingIt] Error cleaning up orphaned annotations:",e)}const A=function(){try{const A=sessionStorage.getItem(da);return A?JSON.parse(A):null}catch{return null}}();A&&A.content&&(this.responseOpen=!0,this.responseContent=A.content,this.responseError=A.error,this.responseScreenshotCount=A.screenshotCount,function(){try{sessionStorage.removeItem(da)}catch(e){console.warn("ZingIt: Failed to clear response state",e)}}(),this.requestUpdate()),this.initWebSocket(),this.detectRemoteUrl(),document.addEventListener("click",this.clickHandler,!0),document.addEventListener("mousemove",this.mouseMoveHandler,!0),document.addEventListener("keydown",this.keydownHandler)}disconnectedCallback(){super.disconnectedCallback(),this.ws&&(this.ws.disconnect(),this.ws=null),this.deleteUndoTimeout&&(clearTimeout(this.deleteUndoTimeout),this.deleteUndoTimeout=null),this.processingTimeout&&(clearTimeout(this.processingTimeout),this.processingTimeout=null),document.removeEventListener("click",this.clickHandler,!0),document.removeEventListener("mousemove",this.mouseMoveHandler,!0),document.removeEventListener("keydown",this.keydownHandler)}initWebSocket(){this.ws=new ji(this.settings.wsUrl),this.ws.on("open",()=>{this.wsConnected=!0,this.wsMaxAttemptsReached=!1;this.annotations.some(A=>"processing"===A.status)?(console.log("[ZingIt] Reconnected with processing annotations - marking as completed"),this.annotations=this.annotations.map(A=>"processing"===A.status?{...A,status:"completed"}:A),ua(this.annotations),this.toast.success("Connected - changes completed")):this.toast.success("Connected to server"),this.ws?.requestAgents()}),this.ws.on("close",()=>{this.wsConnected=!1}),this.ws.on("max_attempts",()=>{this.wsMaxAttemptsReached=!0,this.toast.error("Connection failed - click Reconnect to retry")}),this.ws.on("message",A=>{this.handleWSMessage(A)}),this.ws.connect()}detectRemoteUrl(){this.currentPageUrl=window.location.href;const A=window.location.hostname;this.isRemoteUrl=!["localhost","127.0.0.1","::1"].includes(A)&&!A.endsWith(".local")&&""!==A,this.isRemoteUrl&&this.updateComplete.then(()=>{setTimeout(()=>this.showRemoteUrlWarning(),500)})}showRemoteUrlWarning(){if(!this.toast)return;const A=this.settings.projectDir||this.serverProjectDir;this.toast.show(`⚠️ Editing Remote Site\n\nYou're editing ${this.currentPageUrl}\n\nChanges will be saved locally to:\n${A}\n\nTo see changes, run the project locally or deploy.`,"warning",0)}handleWSMessage(A){switch(A.type){case"connected":this.agentName=A.agent||"",this.agentModel=A.model||"",this.serverProjectDir=A.projectDir||"",this.isRemoteUrl&&this.serverProjectDir&&this.detectRemoteUrl();break;case"processing":this.processing=!0,this.responseOpen=!0,this.isFollowUpMessage||(this.responseContent=""),this.responseError="",this.startProcessingTimeout();break;case"delta":this.responseContent+=A.content||"",this.settings.autoRefresh&&this.responseContent&&this.saveCurrentResponseState();break;case"tool_start":this.responseToolStatus=A.tool||"";break;case"tool_end":this.responseToolStatus="";break;case"idle":if(this.clearProcessingTimeout(),this.processing=!1,this.responseToolStatus="",this.isFollowUpMessage=!1,this.updateAnnotationStatuses("processing","completed"),this.settings.playSoundOnComplete&&this.playCompletionSound(),this.isRemoteUrl){const A=this.settings.projectDir||this.serverProjectDir;this.responseContent+=`\n\n---\n\n**💡 Important:** You're editing a published site.\n\nChanges have been saved locally to:\n\`${A}\`\n\n**To see your changes:**\n1. Run your project locally, or\n2. Deploy the changes to your hosting service\n\n**Need help?** Check the settings panel for your project directory.`}setTimeout(()=>{this.ws&&this.wsConnected&&this.ws.send({type:"get_history"})},500),this.settings.autoRefresh&&(this.saveCurrentResponseState(),this.toast.info("Refreshing page..."),setTimeout(()=>window.location.reload(),1e3));break;case"error":this.clearProcessingTimeout(),this.responseError=A.message||"Unknown error",this.processing=!1,this.responseToolStatus="",this.isFollowUpMessage=!1,this.undoInProgress=!1,this.pendingAnnotationRemovals.clear(),this.updateAnnotationStatuses("processing","pending"),this.toast.error(A.message||"An error occurred");break;case"reset_complete":this.responseContent="",this.responseError="";break;case"agents":if(this.availableAgents=A.agents||[],this.agentPickerLoading=!1,this.agentPickerError="",!this.agentName&&this.availableAgents.length>0)if(this.settings.selectedAgent){const A=this.availableAgents.find(A=>A.name===this.settings.selectedAgent);A?.available?this.ws?.selectAgent(this.settings.selectedAgent):this.agentPickerOpen=!0}else this.agentPickerOpen=!0;break;case"agent_selected":this.agentName=A.agent||"",this.agentModel=A.model||"",this.agentPickerOpen=!1,this.settings={...this.settings,selectedAgent:this.agentName},wa(this.settings),this.toast.success(`Using ${A.agent||"agent"}`);break;case"agent_error":this.agentPickerError=A.message||"Failed to select agent",this.toast.error(A.message||"Failed to select agent");break;case"checkpoint_created":if(A.checkpoint){const e=this.historyCheckpoints.findIndex(e=>e.id===A.checkpoint.id);this.historyCheckpoints=e>=0?[...this.historyCheckpoints.slice(0,e),A.checkpoint,...this.historyCheckpoints.slice(e+1)]:[...this.historyCheckpoints,A.checkpoint],"applied"===A.checkpoint.status&&A.checkpoint.filesModified>0&&this.settings.showUndoBar&&(this.undoBarFilesModified=A.checkpoint.filesModified,this.undoBarVisible=!0)}break;case"history":this.historyCheckpoints=A.checkpoints||[],this.historyLoading=!1;break;case"undo_complete":this.handleCheckpointRestored("Change undone");break;case"revert_complete":this.handleCheckpointRestored("Reverted to checkpoint");break;case"history_cleared":this.historyCheckpoints=[],this.toast.info("History cleared")}}handleDocumentClick(A){if(!this.annotationActive)return;if(!this.agentName)return;if(this.modalOpen||this.settingsOpen||this.agentPickerOpen||this.historyOpen)return;const e=this.getTargetElement(A);if(!e)return;A.preventDefault(),A.stopPropagation(),this.pendingElement=e,this.modalEditMode=!1,this.modalAnnotationId="",this.modalSelector=ea(e),this.modalIdentifier=na(e),this.modalNotes="",this.modalCaptureScreenshot=!1,this.modalScreenshotPreview="";const t=window.getSelection();this.modalSelectedText=t?.toString().trim()||"",this.modalOpen=!0}handleDocumentMouseMove(A){if(!this.annotationActive)return void(this.highlightVisible=!1);if(!this.agentName)return void(this.highlightVisible=!1);if(this.modalOpen||this.settingsOpen||this.agentPickerOpen)return void(this.highlightVisible=!1);const e=this.getTargetElement(A);if(!e)return void(this.highlightVisible=!1);const t=function(A,e){return{top:A.top-e,left:A.left-e,width:A.width+2*e,height:A.height+2*e,bottom:A.bottom+e,right:A.right+e}}(Ca(e),4);this.highlightRect=function(A){const e={top:4,left:4,bottom:window.innerHeight-8,right:window.innerWidth-20},t=A.top<e.top?e.top:A.top,n=A.left<e.left?e.left:A.left,s=A.bottom>e.bottom-30?e.bottom:A.bottom,r=A.right>e.right-30?e.right:A.right;return{top:t,left:n,width:Math.max(0,r-n),height:Math.max(0,s-t),bottom:s,right:r}}(t),this.highlightLabel=na(e),this.highlightVisible=!0}isEditableTarget(A){const e=A.composedPath();for(const t of e)if(t instanceof HTMLElement){const A=t.tagName?.toLowerCase();if("input"===A||"textarea"===A||t.isContentEditable)return!0}return!1}handleDocumentKeydown(A){if("Escape"===A.key&&(this.helpOpen?this.helpOpen=!1:this.modalOpen?this.modalOpen=!1:this.settingsOpen?this.settingsOpen=!1:this.historyOpen?this.historyOpen=!1:this.responseOpen?this.responseOpen=!1:this.undoBarVisible&&(this.undoBarVisible=!1)),this.isEditableTarget(A))return;const e=this.historyCheckpoints.some(A=>A.canUndo);(A.metaKey||A.ctrlKey)&&"z"===A.key&&!A.shiftKey&&(this.undoStack.length>0||e)&&(A.preventDefault(),this.handleUndo()),"z"!==A.key&&"Z"!==A.key||this.handleToggle(),"?"===A.key&&(this.helpOpen=!this.helpOpen),"`"===A.key&&(this.isHidden=!this.isHidden,this.isHidden||this.toast.info("ZingIt visible"))}isOwnElement(A){let e=A;for(;e;){if(e instanceof Element&&e.tagName?.toLowerCase().startsWith("zing-"))return!0;if(e instanceof Element&&e.parentElement)e=e.parentElement;else{const A=e.getRootNode();e=A instanceof ShadowRoot?A.host:null}}return!1}isEventFromOwnElement(A){const e=A.composedPath();for(const t of e)if(t instanceof Element&&t.tagName?.toLowerCase().startsWith("zing-"))return!0;return!1}getTargetElement(A){if(this.isEventFromOwnElement(A))return null;const e=A.composedPath();for(const n of e){if(!(n instanceof Element))continue;if("html"===n.tagName.toLowerCase())break;if(!this.isOwnElement(n))return n}const t=document.elementsFromPoint(A.clientX,A.clientY);for(const n of t){if("html"!==n.tagName.toLowerCase()&&!this.isOwnElement(n))return n}return null}render(){return this.isHidden?$`<zing-toast></zing-toast>`:$`
|
|
2892
|
+
`,ac([hA({type:Boolean})],cc.prototype,"visible",2),ac([hA({type:String})],cc.prototype,"message",2),ac([hA({type:Number})],cc.prototype,"filesModified",2),ac([hA({type:Number})],cc.prototype,"timeout",2),ac([gA()],cc.prototype,"remainingTime",2),cc=ac([cA("zing-undo-bar")],cc);var lc=Object.defineProperty,Bc=Object.getOwnPropertyDescriptor,hc=(A,e,t,n)=>{for(var s,r=n>1?void 0:n?Bc(e,t):e,o=A.length-1;o>=0;o--)(s=A[o])&&(r=(n?s(e,t,r):s(r))||r);return n&&r&&lc(e,t,r),r};let gc=class extends iA{constructor(){super(),this.annotations=[],this.settings=Qa(),this.wsConnected=!1,this.wsMaxAttemptsReached=!1,this.processing=!1,this.agentName="",this.agentModel="",this.serverProjectDir="",this.annotationActive=function(){try{const A=localStorage.getItem(ha);return null===A||JSON.parse(A)}catch{return!0}}(),this.availableAgents=[],this.agentPickerOpen=!1,this.agentPickerLoading=!1,this.agentPickerError="",this.isRemoteUrl=!1,this.currentPageUrl="",this.remoteWarningShown=!1,this.highlightVisible=!1,this.highlightRect={top:0,left:0,width:0,height:0},this.highlightLabel="",this.modalOpen=!1,this.modalEditMode=!1,this.modalAnnotationId="",this.modalSelector="",this.modalIdentifier="",this.modalSelectedText="",this.modalNotes="",this.pendingElement=null,this.modalCaptureScreenshot=!1,this.modalScreenshotPreview="",this.modalScreenshotLoading=!1,this.settingsOpen=!1,this.helpOpen=!1,this.isHidden=!1,this.responseOpen=!1,this.responseContent="",this.responseToolStatus="",this.responseError="",this.responseScreenshotCount=0,this.isFollowUpMessage=!1,this.undoStack=[],this.historyOpen=!1,this.historyCheckpoints=[],this.historyLoading=!1,this.undoBarVisible=!1,this.undoBarFilesModified=0,this.pendingAnnotationRemovals=new Set,this.undoInProgress=!1,this.recentlyDeletedAnnotation=null,this.deleteUndoTimeout=null,this.processingTimeout=null,this.PROCESSING_TIMEOUT_MS=6e4,this.toolbarPosition=function(){try{const A=localStorage.getItem(ga);return A?JSON.parse(A):null}catch{return null}}(),this.isDragging=!1,this.dragOffset={x:0,y:0},this.ws=null,this.clickHandler=this.handleDocumentClick.bind(this),this.mouseMoveHandler=this.handleDocumentMouseMove.bind(this),this.keydownHandler=this.handleDocumentKeydown.bind(this),this.dragMoveHandler=this.handleDragMove.bind(this),this.dragEndHandler=this.handleDragEnd.bind(this)}connectedCallback(){super.connectedCallback(),this.annotations=function(){try{const A=localStorage.getItem(la);if(!A)return[];const e=JSON.parse(A);return e.url!==window.location.href?[]:Array.isArray(e.annotations)?e.annotations:[]}catch{return[]}}();try{const A=this.annotations.filter(A=>{try{return null!==ca(A.selector)}catch(e){return console.warn(`[ZingIt] Invalid selector "${A.selector}":`,e),!1}});if(A.length<this.annotations.length){const e=this.annotations.length-A.length;console.log(`[ZingIt] Removed ${e} orphaned annotation(s) - elements no longer exist`),this.annotations=A,ua(this.annotations),this.updateComplete.then(()=>{this.toast?.info(`Removed ${e} stale annotation${e>1?"s":""}`)})}}catch(e){console.warn("[ZingIt] Error cleaning up orphaned annotations:",e)}const A=function(){try{const A=sessionStorage.getItem(da);return A?JSON.parse(A):null}catch{return null}}();A&&A.content&&(this.responseOpen=!0,this.responseContent=A.content,this.responseError=A.error,this.responseScreenshotCount=A.screenshotCount,function(){try{sessionStorage.removeItem(da)}catch(e){console.warn("ZingIt: Failed to clear response state",e)}}(),this.requestUpdate()),this.initWebSocket(),this.detectRemoteUrl(),document.addEventListener("click",this.clickHandler,!0),document.addEventListener("mousemove",this.mouseMoveHandler,!0),document.addEventListener("keydown",this.keydownHandler)}disconnectedCallback(){super.disconnectedCallback(),this.ws&&(this.ws.disconnect(),this.ws=null),this.deleteUndoTimeout&&(clearTimeout(this.deleteUndoTimeout),this.deleteUndoTimeout=null),this.processingTimeout&&(clearTimeout(this.processingTimeout),this.processingTimeout=null),document.removeEventListener("click",this.clickHandler,!0),document.removeEventListener("mousemove",this.mouseMoveHandler,!0),document.removeEventListener("keydown",this.keydownHandler)}initWebSocket(){this.ws=new ji(this.settings.wsUrl),this.ws.on("open",()=>{this.wsConnected=!0,this.wsMaxAttemptsReached=!1;this.annotations.some(A=>"processing"===A.status)?(console.log("[ZingIt] Reconnected with processing annotations - marking as completed"),this.annotations=this.annotations.map(A=>"processing"===A.status?{...A,status:"completed"}:A),ua(this.annotations),this.toast.success("Connected - changes completed")):this.toast.success("Connected to server"),this.ws?.requestAgents()}),this.ws.on("close",()=>{this.wsConnected=!1}),this.ws.on("max_attempts",()=>{this.wsMaxAttemptsReached=!0,this.toast.error("Connection failed - click Reconnect to retry")}),this.ws.on("message",A=>{this.handleWSMessage(A)}),this.ws.connect()}detectRemoteUrl(){this.currentPageUrl=window.location.href;const A=window.location.hostname;this.isRemoteUrl=!["localhost","127.0.0.1","::1"].includes(A)&&!A.endsWith(".local")&&""!==A,this.isRemoteUrl&&this.updateComplete.then(()=>{setTimeout(()=>this.showRemoteUrlWarning(),500)})}showRemoteUrlWarning(){this.toast&&!this.remoteWarningShown&&(this.remoteWarningShown=!0,this.toast.show("You're editing a published site.\nChanges will be saved locally only.\n\nTo see your changes:\n• Run the project locally, or\n• Deploy the updated files","warning",0))}handleWSMessage(A){switch(A.type){case"connected":this.agentName=A.agent||"",this.agentModel=A.model||"",this.serverProjectDir=A.projectDir||"",this.isRemoteUrl&&this.serverProjectDir&&this.detectRemoteUrl();break;case"processing":this.processing=!0,this.responseOpen=!0,this.isFollowUpMessage||(this.responseContent=""),this.responseError="",this.startProcessingTimeout();break;case"delta":this.responseContent+=A.content||"",this.settings.autoRefresh&&this.responseContent&&this.saveCurrentResponseState();break;case"tool_start":this.responseToolStatus=A.tool||"";break;case"tool_end":this.responseToolStatus="";break;case"idle":if(this.clearProcessingTimeout(),this.processing=!1,this.responseToolStatus="",this.isFollowUpMessage=!1,this.updateAnnotationStatuses("processing","completed"),this.settings.playSoundOnComplete&&this.playCompletionSound(),this.isRemoteUrl){const A=this.settings.projectDir||this.serverProjectDir;this.responseContent+=`\n\n---\n\n**💡 Important:** You're editing a published site.\n\nChanges have been saved locally to:\n\`${A}\`\n\n**To see your changes:**\n1. Run your project locally, or\n2. Deploy the changes to your hosting service\n\n**Need help?** Check the settings panel for your project directory.`}setTimeout(()=>{this.ws&&this.wsConnected&&this.ws.send({type:"get_history"})},500),this.settings.autoRefresh&&(this.saveCurrentResponseState(),this.toast.info("Refreshing page..."),setTimeout(()=>window.location.reload(),1e3));break;case"error":this.clearProcessingTimeout(),this.responseError=A.message||"Unknown error",this.processing=!1,this.responseToolStatus="",this.isFollowUpMessage=!1,this.undoInProgress=!1,this.pendingAnnotationRemovals.clear(),this.updateAnnotationStatuses("processing","pending"),this.toast.error(A.message||"An error occurred");break;case"reset_complete":this.responseContent="",this.responseError="";break;case"agents":if(this.availableAgents=A.agents||[],this.agentPickerLoading=!1,this.agentPickerError="",!this.agentName&&this.availableAgents.length>0)if(this.settings.selectedAgent){const A=this.availableAgents.find(A=>A.name===this.settings.selectedAgent);A?.available?this.ws?.selectAgent(this.settings.selectedAgent):this.agentPickerOpen=!0}else this.agentPickerOpen=!0;break;case"agent_selected":this.agentName=A.agent||"",this.agentModel=A.model||"",this.agentPickerOpen=!1,this.settings={...this.settings,selectedAgent:this.agentName},wa(this.settings),this.toast.success(`Using ${A.agent||"agent"}`);break;case"agent_error":this.agentPickerError=A.message||"Failed to select agent",this.toast.error(A.message||"Failed to select agent");break;case"checkpoint_created":if(A.checkpoint){const e=this.historyCheckpoints.findIndex(e=>e.id===A.checkpoint.id);this.historyCheckpoints=e>=0?[...this.historyCheckpoints.slice(0,e),A.checkpoint,...this.historyCheckpoints.slice(e+1)]:[...this.historyCheckpoints,A.checkpoint],"applied"===A.checkpoint.status&&A.checkpoint.filesModified>0&&this.settings.showUndoBar&&(this.undoBarFilesModified=A.checkpoint.filesModified,this.undoBarVisible=!0)}break;case"history":this.historyCheckpoints=A.checkpoints||[],this.historyLoading=!1;break;case"undo_complete":this.handleCheckpointRestored("Change undone");break;case"revert_complete":this.handleCheckpointRestored("Reverted to checkpoint");break;case"history_cleared":this.historyCheckpoints=[],this.toast.info("History cleared")}}handleDocumentClick(A){if(!this.annotationActive)return;if(!this.agentName)return;if(this.modalOpen||this.settingsOpen||this.agentPickerOpen||this.historyOpen)return;const e=this.getTargetElement(A);if(!e)return;A.preventDefault(),A.stopPropagation(),this.pendingElement=e,this.modalEditMode=!1,this.modalAnnotationId="",this.modalSelector=ea(e),this.modalIdentifier=na(e),this.modalNotes="",this.modalCaptureScreenshot=!1,this.modalScreenshotPreview="";const t=window.getSelection();this.modalSelectedText=t?.toString().trim()||"",this.modalOpen=!0}handleDocumentMouseMove(A){if(!this.annotationActive)return void(this.highlightVisible=!1);if(!this.agentName)return void(this.highlightVisible=!1);if(this.modalOpen||this.settingsOpen||this.agentPickerOpen)return void(this.highlightVisible=!1);const e=this.getTargetElement(A);if(!e)return void(this.highlightVisible=!1);const t=function(A,e){return{top:A.top-e,left:A.left-e,width:A.width+2*e,height:A.height+2*e,bottom:A.bottom+e,right:A.right+e}}(Ca(e),4);this.highlightRect=function(A){const e={top:4,left:4,bottom:window.innerHeight-8,right:window.innerWidth-20},t=A.top<e.top?e.top:A.top,n=A.left<e.left?e.left:A.left,s=A.bottom>e.bottom-30?e.bottom:A.bottom,r=A.right>e.right-30?e.right:A.right;return{top:t,left:n,width:Math.max(0,r-n),height:Math.max(0,s-t),bottom:s,right:r}}(t),this.highlightLabel=na(e),this.highlightVisible=!0}isEditableTarget(A){const e=A.composedPath();for(const t of e)if(t instanceof HTMLElement){const A=t.tagName?.toLowerCase();if("input"===A||"textarea"===A||t.isContentEditable)return!0}return!1}handleDocumentKeydown(A){if("Escape"===A.key&&(this.helpOpen?this.helpOpen=!1:this.modalOpen?this.modalOpen=!1:this.settingsOpen?this.settingsOpen=!1:this.historyOpen?this.historyOpen=!1:this.responseOpen?this.responseOpen=!1:this.undoBarVisible&&(this.undoBarVisible=!1)),this.isEditableTarget(A))return;const e=this.historyCheckpoints.some(A=>A.canUndo);(A.metaKey||A.ctrlKey)&&"z"===A.key&&!A.shiftKey&&(this.undoStack.length>0||e)&&(A.preventDefault(),this.handleUndo()),"z"!==A.key&&"Z"!==A.key||this.handleToggle(),"?"===A.key&&(this.helpOpen=!this.helpOpen),"`"===A.key&&(this.isHidden=!this.isHidden,this.isHidden||this.toast.info("ZingIt visible"))}isOwnElement(A){let e=A;for(;e;){if(e instanceof Element&&e.tagName?.toLowerCase().startsWith("zing-"))return!0;if(e instanceof Element&&e.parentElement)e=e.parentElement;else{const A=e.getRootNode();e=A instanceof ShadowRoot?A.host:null}}return!1}isEventFromOwnElement(A){const e=A.composedPath();for(const t of e)if(t instanceof Element&&t.tagName?.toLowerCase().startsWith("zing-"))return!0;return!1}getTargetElement(A){if(this.isEventFromOwnElement(A))return null;const e=A.composedPath();for(const n of e){if(!(n instanceof Element))continue;if("html"===n.tagName.toLowerCase())break;if(!this.isOwnElement(n))return n}const t=document.elementsFromPoint(A.clientX,A.clientY);for(const n of t){if("html"!==n.tagName.toLowerCase()&&!this.isOwnElement(n))return n}return null}render(){return this.isHidden?$`<zing-toast></zing-toast>`:$`
|
|
2858
2893
|
<zing-highlight
|
|
2859
2894
|
.top=${this.highlightRect.top}
|
|
2860
2895
|
.left=${this.highlightRect.left}
|
package/package.json
CHANGED
|
@@ -183,6 +183,9 @@ export async function handleBatch(ws, state, msg, deps) {
|
|
|
183
183
|
console.log('[Batch] Formatting prompt and extracting images...');
|
|
184
184
|
const prompt = state.agent.formatPrompt(batchData, projectDir);
|
|
185
185
|
const images = state.agent.extractImages(batchData);
|
|
186
|
+
// Log prompt preview to identify the request
|
|
187
|
+
const promptPreview = prompt.length > 150 ? prompt.substring(0, 150) + '...' : prompt;
|
|
188
|
+
console.log('[Batch] Prompt preview:', promptPreview);
|
|
186
189
|
console.log('[Batch] Image count:', images.length);
|
|
187
190
|
console.log('[Batch] Sending processing message to client');
|
|
188
191
|
sendMessage(ws, { type: 'processing' });
|