@divlet/core 0.0.2 → 0.0.3

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 (43) hide show
  1. package/AGENTS.md +3 -2
  2. package/BACKLOG.md +3 -4
  3. package/CHANGELOG.md +11 -2
  4. package/README.md +16 -6
  5. package/dist/core/lib/acceptance.d.ts +18 -0
  6. package/dist/core/lib/acceptance.js +29 -0
  7. package/dist/core/lib/assets.js +1 -1
  8. package/dist/core/lib/browser-board.d.ts +41 -0
  9. package/dist/core/lib/browser-board.js +203 -0
  10. package/dist/core/lib/browser-mcp.d.ts +131 -0
  11. package/dist/core/lib/browser-mcp.js +448 -0
  12. package/dist/core/lib/browser-media-type.d.ts +4 -0
  13. package/dist/core/lib/browser-media-type.js +7 -0
  14. package/dist/core/lib/browser-runtime.d.ts +598 -0
  15. package/dist/core/lib/browser-runtime.js +674 -0
  16. package/dist/core/lib/codec.js +2 -1
  17. package/dist/core/lib/contract.d.ts +1 -152
  18. package/dist/core/lib/contract.js +3 -359
  19. package/dist/core/lib/diff.js +1 -1
  20. package/dist/core/lib/prepare.d.ts +27 -0
  21. package/dist/core/lib/prepare.js +41 -0
  22. package/dist/core/lib/project.js +3 -3
  23. package/dist/core/lib/render.d.ts +2 -9
  24. package/dist/core/lib/render.js +10 -35
  25. package/dist/core/lib/runtime.d.ts +1 -1
  26. package/dist/core/lib/runtime.js +1 -21
  27. package/dist/core/lib/tools.d.ts +154 -0
  28. package/dist/core/lib/tools.js +364 -0
  29. package/dist/core/lib/validation.d.ts +5 -0
  30. package/dist/core/lib/validation.js +21 -0
  31. package/dist/skills/divlet/SKILL.md +7 -1
  32. package/docs/README.md +1 -0
  33. package/docs/agents.md +11 -1
  34. package/docs/architecture.md +15 -7
  35. package/docs/board.md +1 -1
  36. package/docs/browser-mcp.md +108 -0
  37. package/docs/browser-runtime.md +6 -4
  38. package/docs/publishing.md +6 -6
  39. package/docs/testing.md +8 -1
  40. package/examples/README.md +2 -2
  41. package/examples/landing/landing.divlet +1 -1
  42. package/package.json +24 -5
  43. package/skills/divlet/SKILL.md +7 -1
@@ -0,0 +1,598 @@
1
+ import type { DocumentModel } from './model.ts';
2
+ import type { ProjectSettings } from './project.ts';
3
+ import type { FrameCompiler, PreparedFrame } from './prepare.ts';
4
+ /** Tools this writer runs. `open_divlet` belongs to hosts that can open files; `create_frame` is a hidden host route. */
5
+ export declare const BROWSER_TOOLS: readonly string[];
6
+ interface Entry extends PreparedFrame {
7
+ render: number;
8
+ savedVersion: number;
9
+ }
10
+ type Listener = (type: 'state' | 'change', value: unknown) => void;
11
+ export interface BrowserRuntimeOptions {
12
+ /** The project source (`.divlet` JSON text or the parsed object). */
13
+ readonly source: unknown;
14
+ /** A label for the project, shown where the Node host shows its file path. Never a filesystem path. */
15
+ readonly file: string;
16
+ /** A stable identifier for this browser copy of the project. */
17
+ readonly projectId: string;
18
+ readonly compiler: FrameCompiler;
19
+ /** Called after every accepted change with the serialized project; a rejection is reported as a diagnostic, never retried. */
20
+ readonly persist?: (text: string) => Promise<void> | void;
21
+ /** Capabilities the composition adds (for example `captureFonts: false`); merged into `project.capabilities`. */
22
+ readonly capabilities?: Record<string, unknown>;
23
+ }
24
+ export declare class BrowserRuntime {
25
+ #private;
26
+ readonly file: string;
27
+ readonly projectId: string;
28
+ settings: ProjectSettings;
29
+ documents: Map<string, Entry>;
30
+ diagnostics: Map<string, any>;
31
+ observations: Map<string, any>;
32
+ selection: {
33
+ ids: string[];
34
+ revision: number;
35
+ selectedNodes?: any;
36
+ };
37
+ revision: number;
38
+ stateVersion: number;
39
+ renderSeq: number;
40
+ history: any[];
41
+ seq: number;
42
+ undoStack: any[];
43
+ redoStack: any[];
44
+ groupCounter: number;
45
+ work: any[];
46
+ /** `conversation: false`: this host relays no board requests; agents reach it through its MCP tools. */
47
+ agent: {
48
+ connected: boolean;
49
+ busy: boolean;
50
+ activity: string | null;
51
+ since: string | null;
52
+ queued: number;
53
+ conversation: false;
54
+ };
55
+ closed: boolean;
56
+ url: string;
57
+ private constructor();
58
+ /** Validate and render a project source; any invalid frame refuses the whole open (there is no last working state yet). */
59
+ static open(options: BrowserRuntimeOptions): Promise<BrowserRuntime>;
60
+ subscribe(listener: Listener): () => void;
61
+ publish(): void;
62
+ newGroup(): string;
63
+ enqueue<T>(task: () => Promise<T> | T): Promise<T>;
64
+ usedBy(id: string, entries?: Map<string, Entry>): string[];
65
+ describe(entry: Entry): {
66
+ id: string;
67
+ name: string;
68
+ version: number;
69
+ render: number;
70
+ savedVersion: number;
71
+ artboard: import("./model.ts").Artboard;
72
+ metadata: import("./model.ts").Metadata;
73
+ components: string[];
74
+ instances: number;
75
+ uses: string[];
76
+ usedBy: string[];
77
+ };
78
+ historyHead(): {
79
+ seq: number;
80
+ pointId: string;
81
+ navigation: boolean;
82
+ canUndo: boolean;
83
+ canRedo: boolean;
84
+ undoLabel: any;
85
+ redoLabel: any;
86
+ };
87
+ info(): {
88
+ stateVersion: number;
89
+ projectId: string;
90
+ url: string;
91
+ revision: number;
92
+ project: {
93
+ file: string;
94
+ format: string;
95
+ capabilities: {
96
+ properties: boolean;
97
+ settings: boolean;
98
+ frames: boolean;
99
+ saveAs: boolean;
100
+ };
101
+ name: string;
102
+ version: number;
103
+ tokens: Record<string, string>;
104
+ css: string;
105
+ metadata: import("./model.ts").Metadata;
106
+ outputDir: string | null;
107
+ resources: never[];
108
+ };
109
+ documents: {
110
+ id: string;
111
+ name: string;
112
+ version: number;
113
+ render: number;
114
+ savedVersion: number;
115
+ artboard: import("./model.ts").Artboard;
116
+ metadata: import("./model.ts").Metadata;
117
+ components: string[];
118
+ instances: number;
119
+ uses: string[];
120
+ usedBy: string[];
121
+ }[];
122
+ diagnostics: any[];
123
+ selection: {
124
+ ids: string[];
125
+ revision: number;
126
+ selectedNodes?: any;
127
+ };
128
+ history: {
129
+ seq: number;
130
+ pointId: string;
131
+ navigation: boolean;
132
+ canUndo: boolean;
133
+ canRedo: boolean;
134
+ undoLabel: any;
135
+ redoLabel: any;
136
+ };
137
+ clients: number;
138
+ agent: {
139
+ connected: boolean;
140
+ busy: boolean;
141
+ activity: string | null;
142
+ since: string | null;
143
+ queued: number;
144
+ conversation: false;
145
+ };
146
+ work: any[];
147
+ site: null;
148
+ clientPlugins: never[];
149
+ };
150
+ getEntry(id: unknown): Entry;
151
+ components(): {
152
+ instances: string[];
153
+ ref: string;
154
+ frameId: import("./model.ts").NodeId;
155
+ nodeId: import("./model.ts").NodeId;
156
+ name: string;
157
+ tag: string;
158
+ texts: Array<{
159
+ id: import("./model.ts").NodeId;
160
+ content: string;
161
+ }>;
162
+ }[];
163
+ readTimeline(): import("./history.ts").HistoryTimeline;
164
+ readHistory({ since, limit, documentId, actor }?: any): {
165
+ timeline: import("./history.ts").HistoryTimeline;
166
+ truncated: boolean;
167
+ changes: any[];
168
+ seq: number;
169
+ pointId: string;
170
+ navigation: boolean;
171
+ canUndo: boolean;
172
+ canRedo: boolean;
173
+ undoLabel: any;
174
+ redoLabel: any;
175
+ };
176
+ read({ view, documentId, ids, query, depth, limit, route, since }?: any): DocumentModel | {
177
+ stateVersion: number;
178
+ projectId: string;
179
+ url: string;
180
+ revision: number;
181
+ project: {
182
+ file: string;
183
+ format: string;
184
+ capabilities: {
185
+ properties: boolean;
186
+ settings: boolean;
187
+ frames: boolean;
188
+ saveAs: boolean;
189
+ };
190
+ name: string;
191
+ version: number;
192
+ tokens: Record<string, string>;
193
+ css: string;
194
+ metadata: import("./model.ts").Metadata;
195
+ outputDir: string | null;
196
+ resources: never[];
197
+ };
198
+ documents: {
199
+ id: string;
200
+ name: string;
201
+ version: number;
202
+ render: number;
203
+ savedVersion: number;
204
+ artboard: import("./model.ts").Artboard;
205
+ metadata: import("./model.ts").Metadata;
206
+ components: string[];
207
+ instances: number;
208
+ uses: string[];
209
+ usedBy: string[];
210
+ }[];
211
+ diagnostics: any[];
212
+ selection: {
213
+ ids: string[];
214
+ revision: number;
215
+ selectedNodes?: any;
216
+ };
217
+ history: {
218
+ seq: number;
219
+ pointId: string;
220
+ navigation: boolean;
221
+ canUndo: boolean;
222
+ canRedo: boolean;
223
+ undoLabel: any;
224
+ redoLabel: any;
225
+ };
226
+ clients: number;
227
+ agent: {
228
+ connected: boolean;
229
+ busy: boolean;
230
+ activity: string | null;
231
+ since: string | null;
232
+ queued: number;
233
+ conversation: false;
234
+ };
235
+ work: any[];
236
+ site: null;
237
+ clientPlugins: never[];
238
+ } | {
239
+ timeline: import("./history.ts").HistoryTimeline;
240
+ truncated: boolean;
241
+ changes: any[];
242
+ seq: number;
243
+ pointId: string;
244
+ navigation: boolean;
245
+ canUndo: boolean;
246
+ canRedo: boolean;
247
+ undoLabel: any;
248
+ redoLabel: any;
249
+ } | {
250
+ projectVersion: number;
251
+ components: {
252
+ instances: string[];
253
+ ref: string;
254
+ frameId: import("./model.ts").NodeId;
255
+ nodeId: import("./model.ts").NodeId;
256
+ name: string;
257
+ tag: string;
258
+ texts: Array<{
259
+ id: import("./model.ts").NodeId;
260
+ content: string;
261
+ }>;
262
+ }[];
263
+ projectRevision?: undefined;
264
+ selection?: undefined;
265
+ revision?: undefined;
266
+ diagnostics?: undefined;
267
+ documentId?: undefined;
268
+ version?: undefined;
269
+ nodes?: undefined;
270
+ observation?: undefined;
271
+ } | {
272
+ projectRevision: number;
273
+ selection: {
274
+ ids: string[];
275
+ revision: number;
276
+ selectedNodes?: any;
277
+ };
278
+ projectVersion?: undefined;
279
+ components?: undefined;
280
+ revision?: undefined;
281
+ diagnostics?: undefined;
282
+ documentId?: undefined;
283
+ version?: undefined;
284
+ nodes?: undefined;
285
+ observation?: undefined;
286
+ } | {
287
+ revision: number;
288
+ diagnostics: any[];
289
+ projectVersion?: undefined;
290
+ components?: undefined;
291
+ projectRevision?: undefined;
292
+ selection?: undefined;
293
+ documentId?: undefined;
294
+ version?: undefined;
295
+ nodes?: undefined;
296
+ observation?: undefined;
297
+ } | {
298
+ documentId: string;
299
+ version: number;
300
+ nodes: import("./model.ts").InspectResult;
301
+ projectVersion?: undefined;
302
+ components?: undefined;
303
+ projectRevision?: undefined;
304
+ selection?: undefined;
305
+ revision?: undefined;
306
+ diagnostics?: undefined;
307
+ observation?: undefined;
308
+ } | {
309
+ documentId: string;
310
+ version: number;
311
+ observation: any;
312
+ projectVersion?: undefined;
313
+ components?: undefined;
314
+ projectRevision?: undefined;
315
+ selection?: undefined;
316
+ revision?: undefined;
317
+ diagnostics?: undefined;
318
+ nodes?: undefined;
319
+ };
320
+ /** The preview page of one frame (no bridge: the composition injects its own preview channel). */
321
+ render(id: string): {
322
+ documentId: string;
323
+ version: number;
324
+ render: number;
325
+ html: string;
326
+ };
327
+ /** Clean standalone HTML of a frame or of some of its nodes, as the Node host exports it (no embedded assets here). */
328
+ exportDocument(id: string, { nodeId, nodeIds, expectedVersion, expectedProjectVersion }?: any): {
329
+ html: string;
330
+ nodeId: any;
331
+ documentId: string;
332
+ version: number;
333
+ fileName?: undefined;
334
+ } | {
335
+ html: string;
336
+ nodeIds: any[];
337
+ documentId: string;
338
+ version: number;
339
+ fileName?: undefined;
340
+ } | {
341
+ documentId: string;
342
+ version: number;
343
+ html: string;
344
+ fileName: string;
345
+ };
346
+ /** The serialized project, as the Node host would write it to its `.divlet` file. */
347
+ source(): string;
348
+ prepare(input: unknown, { frames, settings }?: {
349
+ frames?: Map<string, DocumentModel>;
350
+ settings?: ProjectSettings;
351
+ }): Promise<PreparedFrame>;
352
+ entryFor(prepared: PreparedFrame, previous?: Entry): Entry;
353
+ dependentsOf(ids: string[], entries?: Map<string, Entry>): string[];
354
+ prepareAll(ids: string[], frames: Map<string, DocumentModel>, settings: ProjectSettings): Promise<Map<string, PreparedFrame>>;
355
+ /** Persist the candidate through the host. A failing store keeps the accepted state and reports a diagnostic. */
356
+ persist(next: Map<string, Entry>, settings: ProjectSettings): Promise<void>;
357
+ record({ actor, kind, documentId, name, fromVersion, toVersion, group, label, from, to, text }: any): any;
358
+ pushUndo(entry: any, { seq, firstSeq }?: {
359
+ seq?: number;
360
+ firstSeq?: number;
361
+ }): void;
362
+ create({ document, actor, group, label, undoable }: any): Promise<{
363
+ documentId: string;
364
+ version: number;
365
+ render: number;
366
+ revision: number;
367
+ seq: any;
368
+ saved: boolean;
369
+ }>;
370
+ _create({ document, actor, group, label, undoable, kind, text }: any): Promise<{
371
+ documentId: string;
372
+ version: number;
373
+ render: number;
374
+ revision: number;
375
+ seq: any;
376
+ saved: boolean;
377
+ }>;
378
+ _remove(documentId: string, { actor, group, label, expectedVersion, undoable, kind }: any): Promise<{
379
+ documentId: string;
380
+ seq: any;
381
+ revision: number;
382
+ }>;
383
+ patch({ documentId, expectedVersion, expectedRender, patch, actor, group, label, undoable }: any): Promise<{
384
+ warnings?: string[] | undefined;
385
+ documentId: any;
386
+ version: number;
387
+ render: number;
388
+ revision: number;
389
+ seq: any;
390
+ summary: any;
391
+ changedNodeIds: string[];
392
+ rerendered: string[];
393
+ saved: boolean;
394
+ }>;
395
+ _patch({ documentId, expectedVersion, expectedRender, patch, actor, group, label, undoable, kind }: any): Promise<{
396
+ warnings?: string[] | undefined;
397
+ documentId: any;
398
+ version: number;
399
+ render: number;
400
+ revision: number;
401
+ seq: any;
402
+ summary: any;
403
+ changedNodeIds: string[];
404
+ rerendered: string[];
405
+ saved: boolean;
406
+ }>;
407
+ patchProject({ expectedVersion, patch, actor, group, label, undoable }: any): Promise<{
408
+ project: boolean;
409
+ version: number;
410
+ revision: number;
411
+ seq: any;
412
+ summary: any;
413
+ saved: boolean;
414
+ }>;
415
+ _patchProject({ expectedVersion, patch, actor, group, label, undoable, kind }: any): Promise<{
416
+ project: boolean;
417
+ version: number;
418
+ revision: number;
419
+ seq: any;
420
+ summary: any;
421
+ saved: boolean;
422
+ }>;
423
+ edit({ documentId, expectedVersion, expectedRender, op, actor, group, label }: any): Promise<{
424
+ ids: any;
425
+ removed: any;
426
+ warnings?: string[] | undefined;
427
+ documentId: any;
428
+ version: number;
429
+ render: number;
430
+ revision: number;
431
+ seq: any;
432
+ summary: any;
433
+ changedNodeIds: string[];
434
+ rerendered: string[];
435
+ saved: boolean;
436
+ }>;
437
+ freeSpot(rect: any, gap?: number, extra?: any[]): any;
438
+ createArtboard({ name, width, height, x, y, from, expectedVersion, actor, group, label }?: any): Promise<{
439
+ documentId: string;
440
+ version: number;
441
+ render: number;
442
+ revision: number;
443
+ seq: any;
444
+ saved: boolean;
445
+ }>;
446
+ removeDocument({ documentId, expectedVersion, actor, group, label }: any): Promise<{
447
+ documentId: string;
448
+ seq: any;
449
+ revision: number;
450
+ }>;
451
+ _applyEntry(entry: any, direction: 'undo' | 'redo', actor: string): Promise<void>;
452
+ _replay(from: any[], to: any[], direction: 'undo' | 'redo', { documentId, actor, steps }?: any): Promise<{
453
+ label: any;
454
+ seq: number;
455
+ pointId: string;
456
+ navigation: boolean;
457
+ canUndo: boolean;
458
+ canRedo: boolean;
459
+ undoLabel: any;
460
+ redoLabel: any;
461
+ }>;
462
+ navigateHistory(options: any): Promise<{
463
+ changed: boolean;
464
+ seq: number;
465
+ pointId: string;
466
+ navigation: boolean;
467
+ canUndo: boolean;
468
+ canRedo: boolean;
469
+ undoLabel: any;
470
+ redoLabel: any;
471
+ } | {
472
+ changed: boolean;
473
+ label: any;
474
+ seq: number;
475
+ pointId: string;
476
+ navigation: boolean;
477
+ canUndo: boolean;
478
+ canRedo: boolean;
479
+ undoLabel: any;
480
+ redoLabel: any;
481
+ }>;
482
+ undo(options?: any): Promise<{
483
+ label: any;
484
+ seq: number;
485
+ pointId: string;
486
+ navigation: boolean;
487
+ canUndo: boolean;
488
+ canRedo: boolean;
489
+ undoLabel: any;
490
+ redoLabel: any;
491
+ }>;
492
+ redo(options?: any): Promise<{
493
+ label: any;
494
+ seq: number;
495
+ pointId: string;
496
+ navigation: boolean;
497
+ canUndo: boolean;
498
+ canRedo: boolean;
499
+ undoLabel: any;
500
+ redoLabel: any;
501
+ }>;
502
+ markWork({ documentId, nodeIds, note, add }?: any): {
503
+ marked: {
504
+ at: string;
505
+ note?: string | undefined;
506
+ documentId: any;
507
+ nodeIds: string[];
508
+ };
509
+ work: number;
510
+ };
511
+ clearWork({ documentId }?: any): {
512
+ cleared: number;
513
+ };
514
+ setSelection({ ids, nodes }: any): {
515
+ stateVersion: number;
516
+ projectId: string;
517
+ url: string;
518
+ revision: number;
519
+ project: {
520
+ file: string;
521
+ format: string;
522
+ capabilities: {
523
+ properties: boolean;
524
+ settings: boolean;
525
+ frames: boolean;
526
+ saveAs: boolean;
527
+ };
528
+ name: string;
529
+ version: number;
530
+ tokens: Record<string, string>;
531
+ css: string;
532
+ metadata: import("./model.ts").Metadata;
533
+ outputDir: string | null;
534
+ resources: never[];
535
+ };
536
+ documents: {
537
+ id: string;
538
+ name: string;
539
+ version: number;
540
+ render: number;
541
+ savedVersion: number;
542
+ artboard: import("./model.ts").Artboard;
543
+ metadata: import("./model.ts").Metadata;
544
+ components: string[];
545
+ instances: number;
546
+ uses: string[];
547
+ usedBy: string[];
548
+ }[];
549
+ diagnostics: any[];
550
+ selection: {
551
+ ids: string[];
552
+ revision: number;
553
+ selectedNodes?: any;
554
+ };
555
+ history: {
556
+ seq: number;
557
+ pointId: string;
558
+ navigation: boolean;
559
+ canUndo: boolean;
560
+ canRedo: boolean;
561
+ undoLabel: any;
562
+ redoLabel: any;
563
+ };
564
+ clients: number;
565
+ agent: {
566
+ connected: boolean;
567
+ busy: boolean;
568
+ activity: string | null;
569
+ since: string | null;
570
+ queued: number;
571
+ conversation: false;
572
+ };
573
+ work: any[];
574
+ site: null;
575
+ clientPlugins: never[];
576
+ };
577
+ setObservations({ documentId, version, nodes, contentHeight, scrollHeight }: any): {
578
+ ok: boolean;
579
+ };
580
+ /**
581
+ * What the board shows about an agent working through this page. Unlike the Node host, an idle agent keeps its work marks:
582
+ * stateless MCP calls carry no turn boundary, so marks end only by `mark_divlet { clear: true }` or replacement.
583
+ */
584
+ setAgent(patch?: Partial<BrowserRuntime['agent']>): {
585
+ connected: boolean;
586
+ busy: boolean;
587
+ activity: string | null;
588
+ since: string | null;
589
+ queued: number;
590
+ conversation: false;
591
+ };
592
+ /** Run one shared contract tool against this writer (the same `run` Pi, MCP and the CLI use). */
593
+ callTool(name: string, args: unknown): Promise<any>;
594
+ /** The shared tool descriptions this writer runs. */
595
+ tools(): import("./tools.ts").Tool[];
596
+ close(): Promise<void>;
597
+ }
598
+ export {};