@1agh/maude 0.26.0 → 0.28.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/cli/commands/design-link.test.mjs +46 -0
- package/cli/commands/doctor.mjs +110 -5
- package/cli/commands/doctor.test.mjs +52 -0
- package/cli/lib/design-link.mjs +38 -8
- package/package.json +8 -8
- package/plugins/design/dev-server/activity.ts +256 -0
- package/plugins/design/dev-server/ai-banner.tsx +4 -0
- package/plugins/design/dev-server/artboard-activity-overlay.tsx +67 -0
- package/plugins/design/dev-server/canvas-comment-mount.tsx +164 -9
- package/plugins/design/dev-server/canvas-lib.tsx +62 -15
- package/plugins/design/dev-server/config.schema.json +2 -1
- package/plugins/design/dev-server/dist/client.bundle.js +18 -18
- package/plugins/design/dev-server/dist/comment-mount.js +82 -4
- package/plugins/design/dev-server/inspect.ts +31 -1
- package/plugins/design/dev-server/participants-chrome.tsx +86 -1
- package/plugins/design/dev-server/server.ts +10 -1
- package/plugins/design/dev-server/sync/agent.ts +23 -8
- package/plugins/design/dev-server/sync/index.ts +24 -19
- package/plugins/design/dev-server/test/activity.test.ts +195 -0
- package/plugins/design/dev-server/test/artboard-activity-overlay.test.tsx +56 -0
- package/plugins/design/dev-server/test/canvas-hmr-runtime.test.tsx +114 -0
- package/plugins/design/dev-server/test/sync-agent.test.ts +28 -0
- package/plugins/design/dev-server/test/sync-runtime.test.ts +34 -6
- package/plugins/design/dev-server/test/use-agent-presence.test.tsx +114 -0
- package/plugins/design/dev-server/test/use-canvas-activity.test.tsx +206 -0
- package/plugins/design/dev-server/use-agent-presence.tsx +244 -0
- package/plugins/design/dev-server/use-canvas-activity.tsx +252 -0
- package/plugins/design/dev-server/ws.ts +21 -2
- package/plugins/design/templates/_shell.html +108 -3
|
@@ -110,6 +110,10 @@
|
|
|
110
110
|
/* HUDs + banners */
|
|
111
111
|
.dc-ai-banner,
|
|
112
112
|
.dc-undo-hud,
|
|
113
|
+
/* Activity overlay — live "agent works here" chrome (Phase 13 / DDR-029) */
|
|
114
|
+
.dc-activity-rim,
|
|
115
|
+
/* HMR "holding last good" toast (Phase 13.1 / DDR-077) */
|
|
116
|
+
.dc-hmr-holding,
|
|
113
117
|
/* Artboard title/label button (editor affordance, not design content) */
|
|
114
118
|
.dc-artboard-label,
|
|
115
119
|
/* Generic opt-in hooks for any future floating overlay */
|
|
@@ -162,6 +166,52 @@
|
|
|
162
166
|
const tokensRel = stripDesignPrefix(params.get('tokens') || '');
|
|
163
167
|
const componentsRel = stripDesignPrefix(params.get('components') || '');
|
|
164
168
|
const layoutRel = stripDesignPrefix(params.get('layout') || '');
|
|
169
|
+
|
|
170
|
+
// Phase 13.1 / DDR-077 — error-resilient HMR while an agent edits. Hoisted
|
|
171
|
+
// here so the HMR client (below) can soft-reload the canvas module instead
|
|
172
|
+
// of location.reload()-ing into a half-saved (broken) build.
|
|
173
|
+
const canvasUrl = canvasRel ? ('/' + designRel + '/' + canvasRel) : null;
|
|
174
|
+
const myFileKey = canvasRel ? (designRel + '/' + canvasRel) : null;
|
|
175
|
+
// True while an `ai-activity` entry is live for THIS canvas (an agent is
|
|
176
|
+
// running /design:edit|new on it). Mirrors ai-banner's gate: parent relays
|
|
177
|
+
// ai-activity via postMessage when embedded; the own-WS path (standalone /
|
|
178
|
+
// same-origin inspector socket) is handled in connectHmr below.
|
|
179
|
+
let agentEditing = false;
|
|
180
|
+
window.addEventListener('message', function (e) {
|
|
181
|
+
// DDR-078 security follow-up: only the trusted embedding parent relays
|
|
182
|
+
// ai-activity. Reject canvas self-posts (which could flip the HMR gate)
|
|
183
|
+
// and any non-parent source. Standalone gets it via its own WS below.
|
|
184
|
+
if (e.source !== window.parent || window.parent === window) return;
|
|
185
|
+
const m = e && e.data;
|
|
186
|
+
if (!m || typeof m !== 'object' || m.dgn !== 'ai-activity') return;
|
|
187
|
+
if (myFileKey && m.file === myFileKey) agentEditing = !!m.entry;
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Soft reload — re-import the canvas module (cache-busted) and swap it in
|
|
191
|
+
// via the runtime, holding the last good render on a build/import error
|
|
192
|
+
// (no white flash). Only used when an agent is editing; manual edits keep
|
|
193
|
+
// the plain location.reload() below.
|
|
194
|
+
function softReload(version) {
|
|
195
|
+
if (!canvasUrl) { location.reload(); return; }
|
|
196
|
+
const rt = window.__maudeCanvasRuntime;
|
|
197
|
+
if (!rt || !rt.remount) { location.reload(); return; }
|
|
198
|
+
import(canvasUrl + '?v=' + (version || Date.now()))
|
|
199
|
+
.then(function (mod) {
|
|
200
|
+
if (mod && typeof mod.default === 'function') {
|
|
201
|
+
rt.remount(mod.default);
|
|
202
|
+
if (rt.setHolding) rt.setHolding(false);
|
|
203
|
+
} else {
|
|
204
|
+
// No usable default export (rare) — fall back to a hard reload.
|
|
205
|
+
location.reload();
|
|
206
|
+
}
|
|
207
|
+
})
|
|
208
|
+
.catch(function (err) {
|
|
209
|
+
// Build/transpile/import error → keep the current render, surface a
|
|
210
|
+
// non-destructive "holding" toast. Next good build swaps it in.
|
|
211
|
+
if (rt.setHolding) rt.setHolding(true, (err && (err.message || String(err))) || 'build error');
|
|
212
|
+
console.warn('[canvas-shell] soft-reload held last good (build error):', err);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
165
215
|
// Phase 6.5 — exporters pass ?hide-chrome=1 to flip the export-mode
|
|
166
216
|
// stylesheet from `media="not all"` to `media="all"`, hiding the
|
|
167
217
|
// dev-server overlays during capture. See `<style id="canvas-hide-chrome">`.
|
|
@@ -192,7 +242,55 @@
|
|
|
192
242
|
ws.addEventListener('message', (ev) => {
|
|
193
243
|
try {
|
|
194
244
|
const msg = JSON.parse(ev.data);
|
|
195
|
-
if (!msg
|
|
245
|
+
if (!msg) return;
|
|
246
|
+
// Phase 13.1 / DDR-077 — own-WS path for the agent-active gate (this
|
|
247
|
+
// socket is the inspector channel in standalone / same-origin mode;
|
|
248
|
+
// embedded canvas-hmr sockets get ai-activity via the parent's
|
|
249
|
+
// postMessage relay handled above).
|
|
250
|
+
if (msg.type === 'ai-activity') {
|
|
251
|
+
if (myFileKey && msg.file === myFileKey) agentEditing = !!msg.entry;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
// Phase 13 / DDR-029 — canvas activity overlay. The server pushes
|
|
255
|
+
// `{ type:'activity', file, status, artboard_ids, ts }` as edits land
|
|
256
|
+
// + go idle; the injected runtime (use-canvas-activity.tsx) listens
|
|
257
|
+
// for the `maude:activity` document event. Same-document bridge — no
|
|
258
|
+
// second socket. The `snapshot` seed re-plays the activity map for a
|
|
259
|
+
// tab that opens mid-edit (inspector-origin only).
|
|
260
|
+
if (msg.type === 'activity') {
|
|
261
|
+
// Maintain a running activity seed (shape matches the snapshot's
|
|
262
|
+
// `activity.state`: camelCase artboardIds). Load-bearing for the
|
|
263
|
+
// Phase 13.1 soft-reload: a soft remount resets the activity
|
|
264
|
+
// provider WITHOUT a page reload (so no fresh snapshot), and the
|
|
265
|
+
// provider re-seeds from this map — without it the overlay would
|
|
266
|
+
// vanish on every agent .tsx save.
|
|
267
|
+
if (!window.__maude_activity_seed__) window.__maude_activity_seed__ = {};
|
|
268
|
+
if (msg.status === 'active') {
|
|
269
|
+
window.__maude_activity_seed__[msg.file] = {
|
|
270
|
+
status: 'active', artboardIds: msg.artboard_ids || null, ts: msg.ts,
|
|
271
|
+
};
|
|
272
|
+
} else {
|
|
273
|
+
delete window.__maude_activity_seed__[msg.file];
|
|
274
|
+
}
|
|
275
|
+
document.dispatchEvent(new CustomEvent('maude:activity', { detail: msg }));
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
if (msg.type === 'snapshot' && msg.activity && typeof msg.activity === 'object') {
|
|
279
|
+
// Stash so the provider can seed on mount even if it isn't listening
|
|
280
|
+
// yet (the snapshot can arrive before React mounts — a real race
|
|
281
|
+
// after the HMR reload that a canvas edit triggers). Also dispatch
|
|
282
|
+
// for any provider that IS already mounted (same-origin live case).
|
|
283
|
+
window.__maude_activity_seed__ = msg.activity;
|
|
284
|
+
for (const file in msg.activity) {
|
|
285
|
+
const e = msg.activity[file];
|
|
286
|
+
if (!e) continue;
|
|
287
|
+
document.dispatchEvent(new CustomEvent('maude:activity', {
|
|
288
|
+
detail: { type: 'activity', file: file, status: e.status, artboard_ids: e.artboardIds || null, ts: e.ts },
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (msg.type !== 'canvas-hmr') return;
|
|
196
294
|
if (msg.mode === 'css') {
|
|
197
295
|
const v = msg.version || Date.now();
|
|
198
296
|
// Match by exact filename when we have one; otherwise refresh all.
|
|
@@ -222,7 +320,14 @@
|
|
|
222
320
|
} else if (msg.mode === 'module' || msg.mode === 'hard') {
|
|
223
321
|
// Only reload when the change touches *this* canvas (or `_lib`).
|
|
224
322
|
if (msg.mode === 'hard' || !msg.file || (canvasRel && msg.file === canvasRel)) {
|
|
225
|
-
|
|
323
|
+
// Phase 13.1 / DDR-077 — when an agent is live-editing, soft-
|
|
324
|
+
// reload (hold last good on a broken intermediate). Manual edits
|
|
325
|
+
// (or no runtime yet) keep the plain, immediate hard reload.
|
|
326
|
+
if (agentEditing && window.__maudeCanvasRuntime && window.__maudeCanvasRuntime.remount) {
|
|
327
|
+
softReload(msg.version);
|
|
328
|
+
} else {
|
|
329
|
+
location.reload();
|
|
330
|
+
}
|
|
226
331
|
}
|
|
227
332
|
} else if (msg.mode === 'meta') {
|
|
228
333
|
// Phase 8 — canvas-meta sidecar changed. Filter to our own canvas:
|
|
@@ -276,7 +381,7 @@
|
|
|
276
381
|
document.head.appendChild(layoutLink);
|
|
277
382
|
}
|
|
278
383
|
|
|
279
|
-
|
|
384
|
+
// canvasUrl is hoisted above (Phase 13.1) so the HMR soft-reload can use it.
|
|
280
385
|
// Phase 4 T5 — read the canvas's sibling .meta.json and stash it on
|
|
281
386
|
// window so DesignCanvas can seed `layout` + `viewport` synchronously.
|
|
282
387
|
// The fetch runs in parallel with imports; failure is non-fatal (the
|