@1agh/maude 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +6 -6
  2. package/apps/studio/acp/bridge.ts +285 -0
  3. package/apps/studio/acp/env.ts +48 -0
  4. package/apps/studio/acp/index.ts +132 -0
  5. package/apps/studio/acp/probe.ts +112 -0
  6. package/apps/studio/acp/transcript.ts +149 -0
  7. package/apps/studio/ai-banner.tsx +0 -1
  8. package/apps/studio/annotations-align.ts +149 -0
  9. package/apps/studio/annotations-bindings.ts +197 -0
  10. package/apps/studio/annotations-context-toolbar.tsx +436 -186
  11. package/apps/studio/annotations-groups.ts +270 -0
  12. package/apps/studio/annotations-layer.tsx +1714 -1661
  13. package/apps/studio/annotations-model.ts +2077 -0
  14. package/apps/studio/annotations-snap.ts +125 -0
  15. package/apps/studio/api.ts +433 -182
  16. package/apps/studio/bin/_png-playwright.mjs +1 -1
  17. package/apps/studio/bin/annotate.mjs +732 -0
  18. package/apps/studio/bin/annotate.sh +17 -0
  19. package/apps/studio/bin/chat-open.sh +44 -0
  20. package/apps/studio/bin/read-annotations.mjs +152 -17
  21. package/apps/studio/build.ts +1 -1
  22. package/apps/studio/canvas-arrowheads.ts +78 -9
  23. package/apps/studio/canvas-cursors.ts +2 -0
  24. package/apps/studio/canvas-edit.ts +257 -7
  25. package/apps/studio/canvas-icons.tsx +105 -0
  26. package/apps/studio/canvas-lib.tsx +112 -19
  27. package/apps/studio/canvas-list-watch.ts +177 -0
  28. package/apps/studio/canvas-shell.tsx +326 -9
  29. package/apps/studio/client/app.jsx +3579 -250
  30. package/apps/studio/client/canvas-url.js +5 -0
  31. package/apps/studio/client/github.js +99 -0
  32. package/apps/studio/client/index.html +1 -1
  33. package/apps/studio/client/panels/ChatPanel.jsx +770 -0
  34. package/apps/studio/client/panels/CollabModelInfographic.jsx +71 -0
  35. package/apps/studio/client/panels/CreateProject.jsx +334 -0
  36. package/apps/studio/client/panels/DiffView.jsx +590 -0
  37. package/apps/studio/client/panels/GitPanel.jsx +767 -0
  38. package/apps/studio/client/panels/IdentityBar.jsx +294 -0
  39. package/apps/studio/client/panels/OnboardingWizard.jsx +563 -0
  40. package/apps/studio/client/panels/RepoBranchSwitcher.jsx +349 -0
  41. package/apps/studio/client/panels/acp-runtime.js +286 -0
  42. package/apps/studio/client/panels/chat-markdown.jsx +138 -0
  43. package/apps/studio/client/panels/git-grouping.js +86 -0
  44. package/apps/studio/client/styles/0-reset.css +4 -0
  45. package/apps/studio/client/styles/3-shell-maude.css +1326 -14
  46. package/apps/studio/client/styles/4-components.css +39 -0
  47. package/apps/studio/client/styles/5-maude-overrides.css +41 -2
  48. package/apps/studio/client/styles/6-acp-chat.css +771 -0
  49. package/apps/studio/client/styles/_index.css +2 -0
  50. package/apps/studio/client/tour/collab-tour.js +61 -0
  51. package/apps/studio/client/tour/overlay.jsx +116 -18
  52. package/apps/studio/client/tour/usage-tour.js +23 -10
  53. package/apps/studio/client/whats-new.jsx +25 -10
  54. package/apps/studio/collab/registry.ts +13 -0
  55. package/apps/studio/collab/room.ts +36 -0
  56. package/apps/studio/commands/annotation-strokes-command.ts +1 -1
  57. package/apps/studio/commands/move-artboards-command.ts +1 -1
  58. package/apps/studio/comments-overlay.tsx +7 -5
  59. package/apps/studio/context-menu.tsx +4 -3
  60. package/apps/studio/contextual-toolbar.tsx +14 -0
  61. package/apps/studio/cursors-overlay.tsx +37 -21
  62. package/apps/studio/dist/client.bundle.js +31795 -1829
  63. package/apps/studio/dist/comment-mount.js +97 -9
  64. package/apps/studio/dist/styles.css +7938 -1599
  65. package/apps/studio/dom-selection.ts +115 -0
  66. package/apps/studio/export-dialog.tsx +3 -3
  67. package/apps/studio/git/endpoints.ts +338 -0
  68. package/apps/studio/git/service.ts +1334 -0
  69. package/apps/studio/git/watch.ts +97 -0
  70. package/apps/studio/github/endpoints.ts +358 -0
  71. package/apps/studio/github/service.ts +231 -0
  72. package/apps/studio/github/token.ts +53 -0
  73. package/apps/studio/history.ts +20 -3
  74. package/apps/studio/hmr-broadcast.ts +9 -2
  75. package/apps/studio/http.ts +508 -6
  76. package/apps/studio/input-router.tsx +7 -0
  77. package/apps/studio/inspect.ts +37 -8
  78. package/apps/studio/participants-chrome.tsx +70 -16
  79. package/apps/studio/paths.ts +12 -0
  80. package/apps/studio/scaffold-design.ts +57 -0
  81. package/apps/studio/server.ts +70 -4
  82. package/apps/studio/sync/agent.ts +311 -57
  83. package/apps/studio/sync/codec.ts +69 -0
  84. package/apps/studio/sync/cold-start.ts +198 -0
  85. package/apps/studio/sync/connection-state.ts +58 -2
  86. package/apps/studio/sync/hub-link.ts +137 -0
  87. package/apps/studio/sync/index.ts +563 -221
  88. package/apps/studio/sync/journal.ts +190 -0
  89. package/apps/studio/sync/migrate-seed.ts +202 -44
  90. package/apps/studio/sync/projection.ts +22 -3
  91. package/apps/studio/sync/status.ts +15 -4
  92. package/apps/studio/test/acp-bridge.test.ts +127 -0
  93. package/apps/studio/test/acp-env.test.ts +65 -0
  94. package/apps/studio/test/acp-origin-gate.test.ts +78 -0
  95. package/apps/studio/test/acp-transcript.test.ts +112 -0
  96. package/apps/studio/test/activity.test.ts +1 -7
  97. package/apps/studio/test/annotate-write.test.ts +184 -0
  98. package/apps/studio/test/annotations-align.test.ts +88 -0
  99. package/apps/studio/test/annotations-bindings.test.ts +124 -0
  100. package/apps/studio/test/annotations-groups.test.ts +231 -0
  101. package/apps/studio/test/annotations-snap.test.ts +79 -0
  102. package/apps/studio/test/canvas-create-api.test.ts +72 -0
  103. package/apps/studio/test/canvas-edit.test.ts +181 -1
  104. package/apps/studio/test/canvas-list-watch.test.ts +322 -0
  105. package/apps/studio/test/canvas-meta-api.test.ts +161 -27
  106. package/apps/studio/test/canvas-origin-gate.test.ts +43 -0
  107. package/apps/studio/test/chat-markdown.test.tsx +58 -0
  108. package/apps/studio/test/collab-bridge.test.ts +0 -2
  109. package/apps/studio/test/collab-room.test.ts +2 -7
  110. package/apps/studio/test/collab-session-survival.test.tsx +176 -0
  111. package/apps/studio/test/csp-canvas-shell.test.ts +5 -0
  112. package/apps/studio/test/csrf-write-guard.test.ts +78 -0
  113. package/apps/studio/test/editing-presence.test.ts +103 -0
  114. package/apps/studio/test/figjam-v3-model.test.ts +342 -0
  115. package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +1 -0
  116. package/apps/studio/test/fixtures/mock-acp-agent.mjs +45 -0
  117. package/apps/studio/test/git-api.test.ts +0 -0
  118. package/apps/studio/test/git-branches.test.ts +106 -0
  119. package/apps/studio/test/git-grouping.test.ts +106 -0
  120. package/apps/studio/test/git-watch.test.ts +97 -0
  121. package/apps/studio/test/github-api.test.ts +465 -0
  122. package/apps/studio/test/hub-link.test.ts +69 -0
  123. package/apps/studio/test/participants-chrome.test.ts +36 -1
  124. package/apps/studio/test/shared-doc-migrate.test.ts +224 -14
  125. package/apps/studio/test/sync-agent.test.ts +272 -2
  126. package/apps/studio/test/sync-codec.test.ts +65 -0
  127. package/apps/studio/test/sync-cold-seed-dedup.test.ts +187 -0
  128. package/apps/studio/test/sync-cold-start.test.ts +304 -0
  129. package/apps/studio/test/sync-connection-state.test.ts +68 -0
  130. package/apps/studio/test/sync-hardening.test.ts +0 -8
  131. package/apps/studio/test/sync-hubs-config.test.ts +0 -1
  132. package/apps/studio/test/sync-incident-replay.test.ts +211 -0
  133. package/apps/studio/test/sync-journal.test.ts +176 -0
  134. package/apps/studio/test/sync-runtime.test.ts +360 -5
  135. package/apps/studio/test/sync-status.test.ts +66 -0
  136. package/apps/studio/test/tour-overlay.test.tsx +18 -0
  137. package/apps/studio/test/use-annotation-resize.test.ts +159 -0
  138. package/apps/studio/test/use-artboard-drag.test.ts +0 -1
  139. package/apps/studio/test/use-collab.test.ts +0 -0
  140. package/apps/studio/test/use-tool-mode.test.tsx +5 -2
  141. package/apps/studio/tool-palette.tsx +30 -11
  142. package/apps/studio/undo-hud.tsx +0 -1
  143. package/apps/studio/use-agent-presence.tsx +4 -2
  144. package/apps/studio/use-annotation-resize.tsx +484 -54
  145. package/apps/studio/use-annotation-selection.tsx +16 -4
  146. package/apps/studio/use-canvas-activity.tsx +2 -2
  147. package/apps/studio/use-chrome-visibility.tsx +66 -0
  148. package/apps/studio/use-collab.tsx +434 -202
  149. package/apps/studio/use-selection-set.tsx +9 -0
  150. package/apps/studio/use-tool-mode.tsx +5 -1
  151. package/apps/studio/whats-new.json +208 -10
  152. package/apps/studio/whats-new.schema.json +18 -2
  153. package/apps/studio/ws.ts +44 -1
  154. package/cli/commands/design-link.test.mjs +84 -0
  155. package/cli/commands/design.mjs +3 -1
  156. package/cli/commands/design.test.mjs +5 -1
  157. package/cli/lib/design-link.mjs +51 -1
  158. package/cli/lib/gitignore-block.mjs +16 -3
  159. package/cli/lib/gitignore-block.test.mjs +13 -1
  160. package/package.json +11 -9
  161. package/plugins/design/dependencies.json +17 -0
  162. package/plugins/design/templates/_shell.html +58 -12
@@ -0,0 +1,53 @@
1
+ // github/token.ts — fetch the GitHub access token from the Tauri shell's
2
+ // loopback bridge at request time (Phase 28 / DDR-108).
3
+ //
4
+ // The token lives ONLY in the OS keychain, owned by the Tauri shell. The dev-server
5
+ // is a separate process and can't read the keychain, so it fetches the token over
6
+ // loopback (keychain.rs → GET /_tauri/github-token, 127.0.0.1-only, per-launch key).
7
+ // The endpoint + key arrive as env from the shell at spawn (sidecar.rs):
8
+ // MAUDE_TOKEN_ENDPOINT=http://127.0.0.1:<port>/_tauri/github-token
9
+ // MAUDE_TOKEN_KEY=<per-launch hex>
10
+ //
11
+ // In non-Tauri mode (`maude design serve` in a browser) those envs are absent →
12
+ // this returns null → the /_api/github/* endpoints degrade to "sign in via the
13
+ // desktop app". The token is never logged, persisted, or returned to the canvas.
14
+
15
+ let warnedNoBridge = false;
16
+
17
+ /**
18
+ * Resolve the current GitHub token from the loopback bridge, or null when not
19
+ * running under the Tauri shell / not signed in. NEVER cache the token (it can be
20
+ * revoked / rotated; the keychain is the single source of truth).
21
+ */
22
+ export async function getGithubToken(): Promise<string | null> {
23
+ const endpoint = process.env.MAUDE_TOKEN_ENDPOINT;
24
+ const key = process.env.MAUDE_TOKEN_KEY;
25
+ if (!endpoint || !key) {
26
+ if (!warnedNoBridge) {
27
+ warnedNoBridge = true;
28
+ // One-time, non-secret: explains why github endpoints 401 outside the app.
29
+ console.error(
30
+ '[maude:github] no token bridge (not the desktop app) — GitHub features disabled'
31
+ );
32
+ }
33
+ return null;
34
+ }
35
+ try {
36
+ const res = await fetch(endpoint, {
37
+ headers: { 'X-Maude-Token-Key': key },
38
+ // The bridge is local + instant; don't hang a request on it.
39
+ signal: AbortSignal.timeout(3000),
40
+ });
41
+ if (res.status !== 200) return null; // 404 = not signed in; 403 = bad key
42
+ const token = (await res.text()).trim();
43
+ return token.length > 0 ? token : null;
44
+ } catch {
45
+ // Bridge unreachable (shell quit mid-request, etc.) — treat as signed out.
46
+ return null;
47
+ }
48
+ }
49
+
50
+ /** Whether the token bridge is configured at all (i.e. running under the shell). */
51
+ export function tokenBridgeAvailable(): boolean {
52
+ return Boolean(process.env.MAUDE_TOKEN_ENDPOINT && process.env.MAUDE_TOKEN_KEY);
53
+ }
@@ -5,6 +5,7 @@
5
5
  // from the WS layer and from a future server-driven auto-snapshot hook.
6
6
 
7
7
  import type { Dirent } from 'node:fs';
8
+ import { existsSync } from 'node:fs';
8
9
  import { readdir } from 'node:fs/promises';
9
10
  import path from 'node:path';
10
11
 
@@ -37,10 +38,14 @@ function fileSlug(file: string, designRel: string): string {
37
38
  }
38
39
  const prefix = `${designRel.replace(/^\/+|\/+$/g, '')}/`;
39
40
  if (p.startsWith(prefix)) p = p.slice(prefix.length);
41
+ // Extension strip mirrors bin/slug.sh (the canonical `_history/<slug>/`
42
+ // recipe) — previously only `.html` was stripped, so `.tsx` canvases got a
43
+ // `ui-foo.tsx` history dir that /design:rollback (slug.sh: `ui-foo`) could
44
+ // never find. DDR-102 conflict snapshots rely on the dirs matching.
40
45
  return p
41
46
  .replace(/\//g, '-')
42
47
  .replace(/\s+/g, '_')
43
- .replace(/\.html$/i, '')
48
+ .replace(/\.(tsx|jsx|html?|css|json|md)$/i, '')
44
49
  .replace(/^\.+/, '')
45
50
  .toLowerCase();
46
51
  }
@@ -60,8 +65,20 @@ export function createHistory(ctx: Context): History {
60
65
 
61
66
  async function writeSnapshot(file: string, contentBytes: Uint8Array | string, reason: string) {
62
67
  const slug = fileSlug(file, ctx.paths.designRel);
63
- const ts = new Date().toISOString();
64
- const contentPath = snapshotPath(slug, ts);
68
+ // Snapshot blob keeps the source file's extension (a `.tsx` body snapshot
69
+ // is a `.tsx` blob); unknown/absent extension falls back to `.html`.
70
+ const extMatch = /\.(tsx|jsx|html?|css|json|svg|md)$/i.exec(file);
71
+ const ext = extMatch ? extMatch[0].toLowerCase() : '.html';
72
+ // Two snapshots can land within the same millisecond (the DDR-102 dual
73
+ // pre-sync pair does) — toISOString() would collide and the second blob
74
+ // would overwrite the first. Bump by 1 ms until the slot is free.
75
+ let tsMs = Date.now();
76
+ let ts = new Date(tsMs).toISOString();
77
+ while (existsSync(snapshotPath(slug, ts, ext)) || existsSync(metaPath(slug, ts))) {
78
+ tsMs += 1;
79
+ ts = new Date(tsMs).toISOString();
80
+ }
81
+ const contentPath = snapshotPath(slug, ts, ext);
65
82
  const meta: Snapshot = {
66
83
  slug,
67
84
  ts,
@@ -6,8 +6,15 @@
6
6
  //
7
7
  // - `mode: "css"` → swap <link> href with a cache-bust query (no module
8
8
  // reload, no React state loss). Sub-150ms latency.
9
- // - `mode: "module"` → location.reload() of the canvas iframe. State is lost
10
- // but the change always picks up. <250ms latency.
9
+ // - `mode: "module"` → in-place hot-swap of the canvas module when the canvas
10
+ // runtime is mounted (re-import + remount only the canvas
11
+ // content; the iframe — and the live CollabProvider +
12
+ // presence — stay mounted, so a cross-peer synced edit
13
+ // updates seamlessly without a presence blink — Phase 30
14
+ // / F4). Falls back to location.reload() with no runtime
15
+ // (gallery thumbnails) or on a re-import with no usable
16
+ // default export. State (scroll / tool / undo) survives
17
+ // the hot-swap path.
11
18
  // - `mode: "hard"` → location.reload() (used when canvas-lib.tsx or any
12
19
  // `_lib/**` file changes — every open canvas needs to
13
20
  // re-bundle).