@nicmeriano/spool-server 0.0.1

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.
@@ -0,0 +1,426 @@
1
+ /**
2
+ * Author - simple for MVP, extensible for future collaboration
3
+ */
4
+ interface Author {
5
+ id: string;
6
+ name: string;
7
+ avatar?: string;
8
+ }
9
+ /**
10
+ * Attachment for comments (images only for MVP)
11
+ */
12
+ interface Attachment {
13
+ id: string;
14
+ filename: string;
15
+ mimeType: 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp';
16
+ /** Size in bytes */
17
+ size: number;
18
+ /** Base64 data URL */
19
+ dataUrl: string;
20
+ createdAt: string;
21
+ }
22
+ /**
23
+ * Comment within an annotation thread
24
+ */
25
+ interface Comment {
26
+ id: string;
27
+ content: string;
28
+ author: Author;
29
+ createdAt: string;
30
+ /** Image attachments (optional) */
31
+ attachments?: Attachment[];
32
+ }
33
+ /**
34
+ * Annotation status
35
+ * - open (blue bubble): Annotation created, Claude should address when submitted
36
+ * - in_progress (spinner): Claude is actively working on it
37
+ * - done (green bubble): Claude has implemented the change
38
+ */
39
+ type AnnotationStatus = 'open' | 'in_progress' | 'done';
40
+ /**
41
+ * Element information captured during annotation
42
+ */
43
+ interface ElementInfo {
44
+ /** CSS selector that uniquely identifies the element */
45
+ selector: string;
46
+ /** HTML tag name (e.g., "button", "div") */
47
+ tagName: string;
48
+ /** CSS class names */
49
+ className: string;
50
+ /** Element ID if present */
51
+ id?: string;
52
+ /** Text content (truncated) */
53
+ textContent?: string;
54
+ /** React component name if available */
55
+ componentName?: string;
56
+ /** Source file path of the React component */
57
+ componentFile?: string;
58
+ /** Line number in the source file */
59
+ lineNumber?: number;
60
+ /** React component props (if available) */
61
+ props?: Record<string, unknown>;
62
+ }
63
+ /**
64
+ * Core annotation with thread support
65
+ */
66
+ interface Annotation {
67
+ id: string;
68
+ /** Primary CSS selector to find element (for backward compatibility) */
69
+ selector: string;
70
+ /** Additional CSS selectors for multi-element annotations */
71
+ selectors?: string[];
72
+ /** Viewport-relative anchor point */
73
+ position: {
74
+ x: number;
75
+ y: number;
76
+ };
77
+ /** 3-state workflow status */
78
+ status: AnnotationStatus;
79
+ createdAt: string;
80
+ createdBy: Author;
81
+ /** When Claude completed it */
82
+ doneAt?: string;
83
+ /** Claude marks this when done */
84
+ doneBy?: Author;
85
+ /** Git commit SHA for this annotation's changes (enables per-annotation revert) */
86
+ commitSha?: string;
87
+ /** Thread of comments */
88
+ comments: Comment[];
89
+ /** Primary element metadata (for backward compatibility) */
90
+ element: ElementInfo;
91
+ /** Additional element metadata for multi-element annotations */
92
+ elements?: ElementInfo[];
93
+ /** True for page-level comments (not tied to any element) */
94
+ isPageLevel?: boolean;
95
+ /** Exact click position for bubble placement (viewport + scroll offset) */
96
+ clickPosition?: {
97
+ x: number;
98
+ y: number;
99
+ };
100
+ }
101
+ /**
102
+ * Default author for Claude
103
+ */
104
+ declare const CLAUDE_AUTHOR: Author;
105
+ declare const CLAUDE_MODEL = "claude-opus-4-5-20251101";
106
+ /**
107
+ * Pending change status
108
+ */
109
+ type PendingChangeStatus = 'pending' | 'in_progress' | 'done' | 'error';
110
+ /**
111
+ * Base interface for all pending changes
112
+ */
113
+ interface PendingChangeBase {
114
+ id: string;
115
+ selector: string;
116
+ element: ElementInfo;
117
+ status: PendingChangeStatus;
118
+ createdAt: string;
119
+ errorMessage?: string;
120
+ }
121
+ /**
122
+ * Variant data
123
+ */
124
+ interface Variant {
125
+ html: string;
126
+ metadata?: Record<string, unknown>;
127
+ }
128
+ /**
129
+ * A pending variant change
130
+ */
131
+ interface VariantChange extends PendingChangeBase {
132
+ type: 'variant';
133
+ prompt: string;
134
+ variants: Variant[];
135
+ selectedVariantIndex: number;
136
+ originalHtml: string;
137
+ }
138
+ /**
139
+ * A pending style change
140
+ */
141
+ interface StyleChange extends PendingChangeBase {
142
+ type: 'style';
143
+ styles: Record<string, string>;
144
+ originalStyles: Record<string, string>;
145
+ }
146
+ /**
147
+ * A pending note change
148
+ */
149
+ interface NoteChange extends PendingChangeBase {
150
+ type: 'note';
151
+ content: string;
152
+ }
153
+ /**
154
+ * Union type for all pending changes
155
+ */
156
+ type PendingChange = VariantChange | StyleChange | NoteChange;
157
+ /**
158
+ * Page-specific annotation data
159
+ */
160
+ interface PageState {
161
+ url: string;
162
+ annotations: Annotation[];
163
+ pendingChanges?: PendingChange[];
164
+ lastModified: string;
165
+ }
166
+ /**
167
+ * Root state stored in .spool/state.json
168
+ */
169
+ interface SpoolState {
170
+ appId: string;
171
+ status: 'idle' | 'generating';
172
+ currentTaskId: string | null;
173
+ pages: Record<string, PageState>;
174
+ /** Chat messages persisted across hot reloads */
175
+ chatMessages?: ChatMessageData[];
176
+ /** App URL reported by the Vite plugin (dynamic port resolution) */
177
+ appUrl?: string;
178
+ }
179
+ /**
180
+ * Task payload for addressing annotations
181
+ */
182
+ interface TaskPayload {
183
+ action: 'address';
184
+ /** Optional: specific annotation IDs, or address all ready if omitted */
185
+ annotationIds?: string[];
186
+ /** Optional: additional user feedback/context */
187
+ feedback?: string;
188
+ }
189
+ /**
190
+ * Task result on completion
191
+ */
192
+ interface TaskResult {
193
+ success: boolean;
194
+ annotationsAddressed: number;
195
+ message?: string;
196
+ }
197
+ /**
198
+ * Error details
199
+ */
200
+ interface TaskError {
201
+ code: string;
202
+ message: string;
203
+ }
204
+ interface TaskSubmitMessage {
205
+ type: 'task:submit';
206
+ id: string;
207
+ payload: TaskPayload;
208
+ }
209
+ interface TaskCancelMessage {
210
+ type: 'task:cancel';
211
+ taskId: string;
212
+ }
213
+ interface AnnotationCreateMessage {
214
+ type: 'annotation:create';
215
+ url: string;
216
+ annotation: Annotation;
217
+ }
218
+ interface AnnotationUpdateMessage {
219
+ type: 'annotation:update';
220
+ id: string;
221
+ changes: Partial<Annotation>;
222
+ }
223
+ interface AnnotationDeleteMessage {
224
+ type: 'annotation:delete';
225
+ id: string;
226
+ }
227
+ interface AnnotationRevertMessage {
228
+ type: 'annotation:revert';
229
+ id: string;
230
+ }
231
+ interface ChangeAddMessage {
232
+ type: 'change:add';
233
+ url: string;
234
+ change: PendingChange;
235
+ }
236
+ interface ChangeRemoveMessage {
237
+ type: 'change:remove';
238
+ id: string;
239
+ }
240
+ interface ChangeApplyAllMessage {
241
+ type: 'change:apply_all';
242
+ url: string;
243
+ }
244
+ interface ChangeApplyMessage {
245
+ type: 'change:apply';
246
+ url: string;
247
+ changeId: string;
248
+ }
249
+ interface ChangeApplyDirectMessage {
250
+ type: 'change:apply_direct';
251
+ change: PendingChange;
252
+ }
253
+ interface VariantGenerateMessage {
254
+ type: 'variant:generate';
255
+ id: string;
256
+ payload: {
257
+ selector: string;
258
+ prompt: string;
259
+ elementHtml: string;
260
+ elementInfo: {
261
+ tagName: string;
262
+ componentName?: string;
263
+ componentFile?: string;
264
+ };
265
+ };
266
+ }
267
+ /**
268
+ * Element reference included in a chat message
269
+ */
270
+ interface ChatElementReference {
271
+ id: string;
272
+ selector: string;
273
+ element: ElementInfo;
274
+ }
275
+ /**
276
+ * Chat message data for server-side persistence
277
+ */
278
+ interface ChatMessageData {
279
+ id: string;
280
+ role: 'user' | 'assistant';
281
+ content: string;
282
+ elementRefs?: ChatElementReference[];
283
+ timestamp: string;
284
+ }
285
+ /**
286
+ * A message in the chat conversation
287
+ */
288
+ interface ChatMessageData {
289
+ id: string;
290
+ role: 'user' | 'assistant';
291
+ content: string;
292
+ elementRefs?: ChatElementReference[];
293
+ timestamp: string;
294
+ }
295
+ interface ChatSendMessage {
296
+ type: 'chat:send';
297
+ id: string;
298
+ content: string;
299
+ elementRefs: ChatElementReference[];
300
+ history: ChatMessageData[];
301
+ }
302
+ interface ChatCancelMessage {
303
+ type: 'chat:cancel';
304
+ messageId: string;
305
+ }
306
+ interface ChatHistoryUpdateMessage {
307
+ type: 'chat:history:update';
308
+ messages: ChatMessageData[];
309
+ }
310
+ type ClientMessage = TaskSubmitMessage | TaskCancelMessage | AnnotationCreateMessage | AnnotationUpdateMessage | AnnotationDeleteMessage | AnnotationRevertMessage | ChangeAddMessage | ChangeRemoveMessage | ChangeApplyAllMessage | ChangeApplyMessage | ChangeApplyDirectMessage | VariantGenerateMessage | ChatSendMessage | ChatCancelMessage | ChatHistoryUpdateMessage;
311
+ interface TaskAckMessage {
312
+ type: 'task:ack';
313
+ taskId: string;
314
+ status: 'started';
315
+ }
316
+ interface StreamTextMessage {
317
+ type: 'stream:text';
318
+ taskId: string;
319
+ content: string;
320
+ isPartial: boolean;
321
+ }
322
+ interface StreamToolCallMessage {
323
+ type: 'stream:tool_call';
324
+ taskId: string;
325
+ toolName: string;
326
+ toolInput: Record<string, unknown>;
327
+ }
328
+ interface StateUpdateMessage {
329
+ type: 'state:update';
330
+ taskId: string | null;
331
+ state: SpoolState;
332
+ }
333
+ interface TaskCompleteMessage {
334
+ type: 'task:complete';
335
+ taskId: string;
336
+ result: TaskResult;
337
+ }
338
+ interface TaskErrorMessage {
339
+ type: 'task:error';
340
+ taskId: string;
341
+ error: TaskError;
342
+ }
343
+ interface RevertResultMessage {
344
+ type: 'revert:result';
345
+ annotationId: string;
346
+ success: boolean;
347
+ error?: string;
348
+ }
349
+ interface AppUrlMessage {
350
+ type: 'app:url';
351
+ url: string;
352
+ }
353
+ interface ApplyProgressMessage {
354
+ type: 'apply:progress';
355
+ changeId: string;
356
+ status: 'in_progress' | 'done' | 'error';
357
+ error?: string;
358
+ }
359
+ interface ApplyCompleteMessage {
360
+ type: 'apply:complete';
361
+ success: boolean;
362
+ message?: string;
363
+ }
364
+ interface VariantResultMessage {
365
+ type: 'variant:result';
366
+ requestId: string;
367
+ variants: Variant[];
368
+ error?: string;
369
+ }
370
+ interface ChatAckMessage {
371
+ type: 'chat:ack';
372
+ messageId: string;
373
+ }
374
+ interface ChatStreamMessage {
375
+ type: 'chat:stream';
376
+ messageId: string;
377
+ content: string;
378
+ isPartial: boolean;
379
+ }
380
+ interface ChatToolCallMessage {
381
+ type: 'chat:tool_call';
382
+ messageId: string;
383
+ toolName: string;
384
+ toolInput: Record<string, unknown>;
385
+ }
386
+ interface ChatCompleteMessage {
387
+ type: 'chat:complete';
388
+ messageId: string;
389
+ success: boolean;
390
+ error?: string;
391
+ }
392
+ type ServerMessage = TaskAckMessage | StreamTextMessage | StreamToolCallMessage | StateUpdateMessage | TaskCompleteMessage | TaskErrorMessage | RevertResultMessage | ApplyProgressMessage | ApplyCompleteMessage | VariantResultMessage | ChatAckMessage | ChatStreamMessage | ChatToolCallMessage | ChatCompleteMessage | AppUrlMessage;
393
+ /**
394
+ * Create an empty state structure
395
+ */
396
+ declare function createEmptyState(appId: string): SpoolState;
397
+ /**
398
+ * Get all annotations from state, optionally filtered by status
399
+ */
400
+ declare function getAnnotationsFromState(state: SpoolState, filter?: {
401
+ status?: AnnotationStatus;
402
+ }): Annotation[];
403
+ /**
404
+ * Find an annotation by ID in state
405
+ */
406
+ declare function findAnnotationInState(state: SpoolState, annotationId: string): {
407
+ annotation: Annotation;
408
+ pageUrl: string;
409
+ } | null;
410
+ /**
411
+ * Update an annotation in state (returns new state, immutable)
412
+ */
413
+ declare function updateAnnotationInState(state: SpoolState, annotationId: string, updates: Partial<Annotation>): SpoolState;
414
+
415
+ /**
416
+ * Options for starting the server
417
+ */
418
+ interface ServerOptions {
419
+ /** Port to listen on (default: 3142) */
420
+ port?: number;
421
+ /** Working directory for state file and agent (default: process.cwd()) */
422
+ cwd?: string;
423
+ }
424
+ declare function startServer(options?: ServerOptions): Promise<void>;
425
+
426
+ export { type Annotation, type AnnotationCreateMessage, type AnnotationDeleteMessage, type AnnotationRevertMessage, type AnnotationStatus, type AnnotationUpdateMessage, type AppUrlMessage, type ApplyCompleteMessage, type ApplyProgressMessage, type Attachment, type Author, CLAUDE_AUTHOR, CLAUDE_MODEL, type ChangeAddMessage, type ChangeApplyAllMessage, type ChangeApplyDirectMessage, type ChangeApplyMessage, type ChangeRemoveMessage, type ChatAckMessage, type ChatCancelMessage, type ChatCompleteMessage, type ChatElementReference, type ChatHistoryUpdateMessage, type ChatMessageData, type ChatSendMessage, type ChatStreamMessage, type ChatToolCallMessage, type ClientMessage, type Comment, type ElementInfo, type NoteChange, type PageState, type PendingChange, type PendingChangeBase, type PendingChangeStatus, type RevertResultMessage, type ServerMessage, type ServerOptions, type SpoolState, type StateUpdateMessage, type StreamTextMessage, type StreamToolCallMessage, type StyleChange, type TaskAckMessage, type TaskCancelMessage, type TaskCompleteMessage, type TaskError, type TaskErrorMessage, type TaskPayload, type TaskResult, type TaskSubmitMessage, type Variant, type VariantChange, type VariantGenerateMessage, type VariantResultMessage, createEmptyState, findAnnotationInState, getAnnotationsFromState, startServer, updateAnnotationInState };