nudge-ui 0.2.3 → 0.2.5

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 (264) hide show
  1. package/dist/cli/agentCommand.js +4 -28
  2. package/dist/client.mjs +870 -212
  3. package/dist/hosts/next/wrapper.js +1 -7
  4. package/dist/hosts/projectBridge.js +3 -17
  5. package/dist/inspector/agent/McpConnectionDialog.js +7 -3
  6. package/dist/inspector/agent/activity.d.ts +1 -1
  7. package/dist/inspector/agent/activity.js +3 -2
  8. package/dist/inspector/agent/client.d.ts +2 -2
  9. package/dist/inspector/agent/client.js +28 -29
  10. package/dist/inspector/agent/connectionStatus.d.ts +3 -1
  11. package/dist/inspector/agent/connectionStatus.js +25 -0
  12. package/dist/inspector/agent/httpTransport.js +31 -147
  13. package/dist/inspector/agent/protocol.d.ts +1 -1
  14. package/dist/inspector/agent/protocol.js +1 -1
  15. package/dist/inspector/agent/verification.d.ts +5 -7
  16. package/dist/inspector/agent/verification.js +67 -20
  17. package/dist/inspector/boot.d.ts +3 -0
  18. package/dist/inspector/boot.js +297 -0
  19. package/dist/inspector/canvas/AgentActivityOverlay.d.ts +2 -1
  20. package/dist/inspector/canvas/AgentActivityOverlay.js +6 -3
  21. package/dist/inspector/canvas/CanvasCard.js +23 -12
  22. package/dist/inspector/canvas/CanvasElementOverlay.js +97 -128
  23. package/dist/inspector/canvas/CanvasToolbar.js +2 -1
  24. package/dist/inspector/canvas/CanvasWorkspace.js +119 -162
  25. package/dist/inspector/canvas/LockedWorkspaceNotice.d.ts +3 -2
  26. package/dist/inspector/canvas/LockedWorkspaceNotice.js +10 -6
  27. package/dist/inspector/canvas/PageCard.d.ts +10 -0
  28. package/dist/inspector/canvas/PageCard.js +51 -0
  29. package/dist/inspector/canvas/SketchToolOptions.d.ts +5 -0
  30. package/dist/inspector/canvas/SketchToolOptions.js +86 -0
  31. package/dist/inspector/canvas/StaleChangeIndicator.d.ts +1 -1
  32. package/dist/inspector/canvas/StaleChangeIndicator.js +1 -1
  33. package/dist/inspector/canvas/ToolOptionsDrawer.d.ts +21 -0
  34. package/dist/inspector/canvas/ToolOptionsDrawer.js +77 -0
  35. package/dist/inspector/canvas/activeCanvasDocument.d.ts +3 -2
  36. package/dist/inspector/canvas/assets/eraser.svg +28 -0
  37. package/dist/inspector/canvas/assets/pen.svg +25 -0
  38. package/dist/inspector/canvas/canvasFrame.d.ts +16 -0
  39. package/dist/inspector/canvas/canvasFrame.js +10 -0
  40. package/dist/inspector/canvas/canvasGestures.d.ts +0 -1
  41. package/dist/inspector/canvas/canvasGestures.js +0 -6
  42. package/dist/inspector/canvas/canvasStore.d.ts +6 -0
  43. package/dist/inspector/canvas/canvasStore.js +36 -1
  44. package/dist/inspector/canvas/frameConnection.d.ts +48 -0
  45. package/dist/inspector/canvas/frameConnection.js +73 -0
  46. package/dist/inspector/canvas/frameProtocol.d.ts +18 -1
  47. package/dist/inspector/canvas/frameProtocol.js +36 -0
  48. package/dist/inspector/canvas/frameScrollbarStyles.d.ts +3 -0
  49. package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
  50. package/dist/inspector/canvas/pageSurface.d.ts +11 -0
  51. package/dist/inspector/canvas/pageSurface.js +34 -0
  52. package/dist/inspector/canvas/projection.d.ts +19 -9
  53. package/dist/inspector/canvas/projection.js +58 -31
  54. package/dist/inspector/canvas/rendererBootstrap.js +4 -1
  55. package/dist/inspector/canvas/rendererElementSelector.js +9 -1
  56. package/dist/inspector/canvas/rendererMessageRouter.d.ts +4 -5
  57. package/dist/inspector/canvas/rendererMessageRouter.js +12 -16
  58. package/dist/inspector/canvas/rendererSelectionProxy.d.ts +7 -1
  59. package/dist/inspector/canvas/rendererSelectionProxy.js +8 -36
  60. package/dist/inspector/canvas/rendererStylesheet.js +15 -0
  61. package/dist/inspector/canvas/sessionStore.d.ts +2 -2
  62. package/dist/inspector/canvas/sessionStore.js +12 -9
  63. package/dist/inspector/canvas/staleChangeDetector.d.ts +1 -1
  64. package/dist/inspector/canvas/staleChangeDetector.js +10 -22
  65. package/dist/inspector/changes/codecs.d.ts +2 -0
  66. package/dist/inspector/changes/codecs.js +27 -3
  67. package/dist/inspector/changes/draftPreview.d.ts +12 -0
  68. package/dist/inspector/changes/draftPreview.js +133 -0
  69. package/dist/inspector/changes/editModel.d.ts +18 -0
  70. package/dist/inspector/changes/editModel.js +16 -3
  71. package/dist/inspector/changes/managedStyleProjection.js +2 -1
  72. package/dist/inspector/changes/previewDiagnostics.js +1 -1
  73. package/dist/inspector/changes/types.d.ts +18 -1
  74. package/dist/inspector/comments/CommentsOverlay.js +18 -16
  75. package/dist/inspector/comments/element.js +10 -3
  76. package/dist/inspector/comments/store.js +3 -2
  77. package/dist/inspector/comments/verification.js +1 -1
  78. package/dist/inspector/componentSemantics/ComponentPropsSection.js +2 -1
  79. package/dist/inspector/componentSemantics/adapterRegistry.d.ts +6 -1
  80. package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
  81. package/dist/inspector/componentSemantics/changeAction.js +1 -1
  82. package/dist/inspector/componentSemantics/reactRuntime.d.ts +2 -1
  83. package/dist/inspector/componentSemantics/reactRuntime.js +38 -0
  84. package/dist/inspector/componentSemantics/runtimeBridge.d.ts +4 -2
  85. package/dist/inspector/componentSemantics/runtimeBridge.js +17 -0
  86. package/dist/inspector/componentSemantics/textBinding.d.ts +1 -2
  87. package/dist/inspector/componentSemantics/textBinding.js +4 -45
  88. package/dist/inspector/componentSemantics/types.d.ts +11 -0
  89. package/dist/inspector/drafts/draftStore.d.ts +109 -0
  90. package/dist/inspector/drafts/draftStore.js +451 -0
  91. package/dist/inspector/drafts/model.d.ts +9 -1
  92. package/dist/inspector/drafts/model.js +5 -1
  93. package/dist/inspector/drafts/store.d.ts +53 -15
  94. package/dist/inspector/drafts/store.js +143 -169
  95. package/dist/inspector/index.d.ts +2 -4
  96. package/dist/inspector/index.js +2 -264
  97. package/dist/inspector/inline-text/inlineTextEditor.d.ts +1 -1
  98. package/dist/inspector/inline-text/inlineTextEditor.js +1 -2
  99. package/dist/inspector/inline-text/textEditChange.d.ts +1 -1
  100. package/dist/inspector/inspection/bridge.d.ts +1 -1
  101. package/dist/inspector/inspection/bridge.js +2 -1
  102. package/dist/inspector/inspection/browserCssInspection.d.ts +8 -0
  103. package/dist/inspector/inspection/browserCssInspection.js +28 -6
  104. package/dist/inspector/inspection/inspectionSnapshot.d.ts +6 -0
  105. package/dist/inspector/inspection/inspectionSnapshot.js +10 -0
  106. package/dist/inspector/inspection/performanceDiagnostics.d.ts +18 -0
  107. package/dist/inspector/inspection/performanceDiagnostics.js +31 -0
  108. package/dist/inspector/inspection/useBrowserCssInspection.js +17 -38
  109. package/dist/inspector/iterations/capture.d.ts +2 -1
  110. package/dist/inspector/iterations/capture.js +2 -1
  111. package/dist/inspector/iterations/client.d.ts +2 -1
  112. package/dist/inspector/iterations/coordinator.d.ts +4 -3
  113. package/dist/inspector/iterations/coordinator.js +5 -3
  114. package/dist/inspector/iterations/prompt.js +9 -8
  115. package/dist/inspector/overlay/interactionStyles.js +17 -0
  116. package/dist/inspector/pageInspector.d.ts +42 -0
  117. package/dist/inspector/pageInspector.js +342 -0
  118. package/dist/inspector/projection/draftProjection.d.ts +10 -2
  119. package/dist/inspector/projection/draftProjection.js +9 -1
  120. package/dist/inspector/projection/managedStylesheet.js +24 -4
  121. package/dist/inspector/projection/renderedInstance.d.ts +15 -2
  122. package/dist/inspector/projection/renderedInstance.js +60 -7
  123. package/dist/inspector/projection/structuralProjection.d.ts +0 -9
  124. package/dist/inspector/projection/structuralProjection.js +16 -46
  125. package/dist/inspector/projection/textProjection.d.ts +8 -2
  126. package/dist/inspector/projection/textProjection.js +77 -24
  127. package/dist/inspector/prompt/clipboardHandoff.d.ts +14 -0
  128. package/dist/inspector/prompt/clipboardHandoff.js +47 -16
  129. package/dist/inspector/prompt/generatePrompt.d.ts +1 -1
  130. package/dist/inspector/prompt/generatePrompt.js +248 -148
  131. package/dist/inspector/prompt/promptDocument.d.ts +3 -0
  132. package/dist/inspector/prompt/promptDocument.js +8 -0
  133. package/dist/inspector/prompt/promptSettings.js +7 -5
  134. package/dist/inspector/runtime/inspectorStorage.d.ts +17 -0
  135. package/dist/inspector/runtime/inspectorStorage.js +42 -0
  136. package/dist/inspector/runtime/ownedStylesheets.d.ts +20 -0
  137. package/dist/inspector/runtime/ownedStylesheets.js +72 -0
  138. package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
  139. package/dist/inspector/runtime/runtimeConfig.js +10 -1
  140. package/dist/inspector/runtime/runtimeIdentityClaims.d.ts +29 -0
  141. package/dist/inspector/runtime/runtimeIdentityClaims.js +188 -0
  142. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +15 -0
  143. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +113 -29
  144. package/dist/inspector/selection/editScope.d.ts +1 -0
  145. package/dist/inspector/selection/editScope.js +13 -2
  146. package/dist/inspector/selection/sourceSite.d.ts +12 -0
  147. package/dist/inspector/selection/sourceSite.js +28 -0
  148. package/dist/inspector/shell/AgentStatusButton.js +2 -2
  149. package/dist/inspector/shell/AppShell.js +6 -2
  150. package/dist/inspector/shell/ChangesLog.js +27 -9
  151. package/dist/inspector/shell/CopyPromptButton.js +74 -26
  152. package/dist/inspector/shell/EmptyState.js +3 -3
  153. package/dist/inspector/shell/InspectorShell.d.ts +0 -3
  154. package/dist/inspector/shell/InspectorShell.js +21 -13
  155. package/dist/inspector/shell/PeekOriginalButton.js +3 -3
  156. package/dist/inspector/shell/interactionStatePreview.d.ts +9 -0
  157. package/dist/inspector/shell/interactionStatePreview.js +112 -0
  158. package/dist/inspector/shell/originalPreview.d.ts +3 -2
  159. package/dist/inspector/shell/originalPreview.js +10 -37
  160. package/dist/inspector/shell/stateValue.js +2 -3
  161. package/dist/inspector/sketch/SketchEditor.js +5 -4
  162. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +2 -1
  163. package/dist/inspector/sketch/SketchFrameOverlay.js +5 -4
  164. package/dist/inspector/sketch/SketchOverlay.d.ts +3 -5
  165. package/dist/inspector/sketch/SketchOverlay.js +139 -263
  166. package/dist/inspector/sketch/SketchPromptPanel.d.ts +1 -1
  167. package/dist/inspector/sketch/SketchPromptPanel.js +8 -1
  168. package/dist/inspector/sketch/SketchThumbnail.d.ts +5 -0
  169. package/dist/inspector/sketch/SketchThumbnail.js +18 -0
  170. package/dist/inspector/sketch/SketchWorkspace.d.ts +1 -2
  171. package/dist/inspector/sketch/SketchWorkspace.js +69 -34
  172. package/dist/inspector/sketch/capture.js +19 -3
  173. package/dist/inspector/sketch/copySketch.d.ts +10 -0
  174. package/dist/inspector/sketch/copySketch.js +52 -0
  175. package/dist/inspector/sketch/drawingTools.d.ts +17 -0
  176. package/dist/inspector/sketch/drawingTools.js +47 -0
  177. package/dist/inspector/sketch/frameHeading.d.ts +9 -0
  178. package/dist/inspector/sketch/frameHeading.js +30 -0
  179. package/dist/inspector/sketch/freehand.js +3 -3
  180. package/dist/inspector/sketch/geometry.d.ts +6 -0
  181. package/dist/inspector/sketch/geometry.js +19 -0
  182. package/dist/inspector/sketch/history.d.ts +30 -0
  183. package/dist/inspector/sketch/history.js +58 -0
  184. package/dist/inspector/sketch/interaction.d.ts +1 -3
  185. package/dist/inspector/sketch/interaction.js +6 -9
  186. package/dist/inspector/sketch/model.d.ts +35 -1
  187. package/dist/inspector/sketch/model.js +116 -61
  188. package/dist/inspector/sketch/persistence.d.ts +14 -0
  189. package/dist/inspector/sketch/persistence.js +63 -7
  190. package/dist/inspector/sketch/raster.d.ts +6 -2
  191. package/dist/inspector/sketch/raster.js +43 -17
  192. package/dist/inspector/sketch/store.d.ts +1 -1
  193. package/dist/inspector/sketch/store.js +1 -1
  194. package/dist/inspector/sketch/videoFrames.d.ts +6 -0
  195. package/dist/inspector/sketch/videoFrames.js +81 -0
  196. package/dist/inspector/styleEditors/BackgroundEditor.js +3 -2
  197. package/dist/inspector/styleEditors/BorderEditor.js +30 -130
  198. package/dist/inspector/styleEditors/BorderRadiusEditor.js +8 -3
  199. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +1 -1
  200. package/dist/inspector/styleEditors/LayoutSection.js +2 -2
  201. package/dist/inspector/styleEditors/borderModel.d.ts +42 -0
  202. package/dist/inspector/styleEditors/borderModel.js +114 -0
  203. package/dist/inspector/styleEditors/layoutValue.js +2 -3
  204. package/dist/inspector/tokens/TokenField.js +40 -7
  205. package/dist/inspector/tokens/TokensPanel.js +2 -1
  206. package/dist/inspector/tokens/editActions.d.ts +3 -3
  207. package/dist/inspector/tokens/editActions.js +15 -3
  208. package/dist/inspector/tokens/resolution/containerQueryEvaluator.d.ts +15 -0
  209. package/dist/inspector/tokens/resolution/containerQueryEvaluator.js +86 -0
  210. package/dist/inspector/tokens/resolution/cssomCollector.js +44 -9
  211. package/dist/inspector/tokens/resolution/nestedSelectors.d.ts +6 -0
  212. package/dist/inspector/tokens/resolution/nestedSelectors.js +67 -0
  213. package/dist/inspector/tokens/resolution/ruleMatching.js +23 -4
  214. package/dist/inspector/tokens/resolution.d.ts +6 -3
  215. package/dist/inspector/tokens/resolution.js +91 -112
  216. package/dist/inspector/tokens/tokenEdits.d.ts +1 -1
  217. package/dist/inspector/tokens/tokenEdits.js +1 -1
  218. package/dist/inspector/ui/InlineStyleWarning.js +2 -2
  219. package/dist/inspector/ui/InspectorStyle.d.ts +8 -0
  220. package/dist/inspector/ui/InspectorStyle.js +26 -0
  221. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  222. package/dist/inspector/ui/PopoverListbox.js +3 -3
  223. package/dist/inspector/ui/Toast.d.ts +14 -0
  224. package/dist/inspector/ui/Toast.js +30 -0
  225. package/dist/inspector/ui/assets/canvasIllustration.d.ts +2 -0
  226. package/dist/inspector/ui/assets/canvasIllustration.js +21 -0
  227. package/dist/inspector/ui/assets/gridIllustration.d.ts +2 -0
  228. package/dist/inspector/ui/assets/{grid.svg → gridIllustration.js} +3 -2
  229. package/dist/inspector/ui/customCursors.d.ts +5 -0
  230. package/dist/inspector/ui/customCursors.js +32 -6
  231. package/dist/inspector/ui/styles.js +12 -10
  232. package/dist/inspector/workspace/commands.js +1 -2
  233. package/dist/inspector/workspace/controller.js +1 -2
  234. package/dist/inspector/workspace/handoff.js +3 -2
  235. package/dist/inspector/workspace/sentItems.d.ts +16 -0
  236. package/dist/inspector/workspace/sentItems.js +33 -0
  237. package/dist/inspector/workspace/timeline.d.ts +24 -10
  238. package/dist/inspector/workspace/timeline.js +118 -96
  239. package/dist/internal/agent-protocol.d.ts +50 -13
  240. package/dist/internal/agent-protocol.js +145 -19
  241. package/dist/nudge-ui.mjs +81 -65
  242. package/dist/project/mcpPackage.d.ts +8 -0
  243. package/dist/project/mcpPackage.js +60 -0
  244. package/package.json +13 -3
  245. package/dist/inspector/canvas/measurementProjection.d.ts +0 -8
  246. package/dist/inspector/canvas/measurementProjection.js +0 -16
  247. package/dist/inspector/changes/changesLog.d.ts +0 -47
  248. package/dist/inspector/changes/changesLog.js +0 -247
  249. package/dist/inspector/changes/draftChanges.d.ts +0 -56
  250. package/dist/inspector/changes/draftChanges.js +0 -300
  251. package/dist/inspector/conformance/projection.d.ts +0 -2
  252. package/dist/inspector/conformance/projection.js +0 -3
  253. package/dist/inspector/inline-text/textChangeBoundary.d.ts +0 -6
  254. package/dist/inspector/inline-text/textChangeBoundary.js +0 -1
  255. package/dist/inspector/overlay/InspectorOverlay.d.ts +0 -5
  256. package/dist/inspector/overlay/InspectorOverlay.js +0 -332
  257. package/dist/inspector/overlay/elementSelector.d.ts +0 -1
  258. package/dist/inspector/overlay/elementSelector.js +0 -111
  259. package/dist/inspector/sketch/SketchChanges.d.ts +0 -2
  260. package/dist/inspector/sketch/SketchChanges.js +0 -72
  261. package/dist/inspector/sketch/SketchEntryButton.d.ts +0 -4
  262. package/dist/inspector/sketch/SketchEntryButton.js +0 -11
  263. package/dist/inspector/sketch/SketchLayersPanel.d.ts +0 -2
  264. package/dist/inspector/sketch/SketchLayersPanel.js +0 -71
@@ -1,108 +1,130 @@
1
- let undoStack = [];
2
- let redoStack = [];
3
- let activeGroup;
4
- const listeners = new Set();
5
- function notify() {
6
- for (const listener of listeners)
7
- listener();
8
- }
9
- function discardRedo() {
10
- const discarded = redoStack;
11
- redoStack = [];
12
- for (const entry of discarded)
13
- if (entry.kind === "canvas")
14
- entry.dispose();
15
- }
16
- export function subscribeTimeline(listener) {
17
- listeners.add(listener);
18
- return () => listeners.delete(listener);
19
- }
20
- export function timelineStatus() {
21
- return { canUndo: undoStack.length > 0, canRedo: redoStack.length > 0 };
22
- }
23
- export function recordEdit(entry, equal) {
24
- const previous = undoStack.at(-1);
25
- const grouped = activeGroup && previous?.kind === "edit" && previous.draftId === entry.draftId && previous.group === activeGroup;
26
- const next = { kind: "edit", ...entry, before: grouped ? previous.before : entry.before, group: activeGroup };
27
- if (grouped)
28
- undoStack.pop();
29
- if (!equal(next.before, next.after))
30
- undoStack.push(next);
31
- discardRedo();
32
- notify();
1
+ export function createTimeline() {
2
+ let undoStack = [];
3
+ let redoStack = [];
4
+ let activeGroup;
5
+ const listeners = new Set();
6
+ const notify = () => {
7
+ for (const listener of listeners)
8
+ listener();
9
+ };
10
+ const discardRedo = () => {
11
+ const discarded = redoStack;
12
+ redoStack = [];
13
+ for (const entry of discarded)
14
+ if (entry.kind === "canvas")
15
+ entry.dispose();
16
+ };
17
+ return {
18
+ subscribe(listener) {
19
+ listeners.add(listener);
20
+ return () => listeners.delete(listener);
21
+ },
22
+ status: () => ({ canUndo: undoStack.length > 0, canRedo: redoStack.length > 0 }),
23
+ recordEdit(entry, equal) {
24
+ const previous = undoStack.at(-1);
25
+ const grouped = activeGroup && previous?.kind === "edit" && previous.draftId === entry.draftId && previous.group === activeGroup;
26
+ const next = { kind: "edit", ...entry, before: grouped ? previous.before : entry.before, group: activeGroup };
27
+ if (grouped)
28
+ undoStack.pop();
29
+ if (!equal(next.before, next.after))
30
+ undoStack.push(next);
31
+ discardRedo();
32
+ notify();
33
+ },
34
+ recordCanvasChange(entry) {
35
+ discardRedo();
36
+ undoStack.push({ kind: "canvas", ...entry });
37
+ notify();
38
+ },
39
+ replay(direction, applyEdit) {
40
+ const source = direction === "undo" ? undoStack : redoStack;
41
+ const destination = direction === "undo" ? redoStack : undoStack;
42
+ const entry = source.pop();
43
+ if (!entry)
44
+ return false;
45
+ if (entry.kind === "edit")
46
+ applyEdit(entry, direction === "undo" ? entry.before : entry.after);
47
+ else
48
+ entry[direction]();
49
+ destination.push(entry);
50
+ notify();
51
+ return true;
52
+ },
53
+ pruneDraftHistory(draftId, retain, equal) {
54
+ const prune = (entries) => entries.flatMap((entry) => {
55
+ if (entry.kind !== "edit" || entry.draftId !== draftId)
56
+ return [entry];
57
+ const next = { ...entry, before: retain(entry.before), after: retain(entry.after) };
58
+ return equal(next.before, next.after) ? [] : [next];
59
+ });
60
+ undoStack = prune(undoStack);
61
+ redoStack = prune(redoStack);
62
+ notify();
63
+ },
64
+ discardDraftHistory(draftId) {
65
+ const retain = (entry) => entry.kind !== "edit" || entry.draftId !== draftId;
66
+ undoStack = undoStack.filter(retain);
67
+ redoStack = redoStack.filter(retain);
68
+ notify();
69
+ },
70
+ discardCanvasHistory(cardId) {
71
+ const retain = (entry) => entry.kind !== "canvas" || !entry.cardIds.includes(cardId);
72
+ undoStack = undoStack.filter(retain);
73
+ const discarded = redoStack.filter((entry) => !retain(entry));
74
+ redoStack = redoStack.filter(retain);
75
+ for (const entry of discarded)
76
+ if (entry.kind === "canvas")
77
+ entry.dispose();
78
+ notify();
79
+ },
80
+ clear() {
81
+ const discarded = [...undoStack, ...redoStack];
82
+ undoStack = [];
83
+ redoStack = [];
84
+ for (const entry of discarded)
85
+ if (entry.kind === "canvas")
86
+ entry.dispose();
87
+ notify();
88
+ },
89
+ releaseDetachedIterations() {
90
+ discardRedo();
91
+ for (const entry of undoStack)
92
+ if (entry.kind === "canvas")
93
+ entry.dispose();
94
+ notify();
95
+ },
96
+ createGroup() {
97
+ const group = Symbol("change-history-group");
98
+ return (update) => {
99
+ const previous = activeGroup;
100
+ activeGroup = group;
101
+ try {
102
+ update();
103
+ }
104
+ finally {
105
+ activeGroup = previous;
106
+ }
107
+ };
108
+ },
109
+ };
33
110
  }
111
+ /** The Workspace's session timeline. */
112
+ export const sessionTimeline = createTimeline();
34
113
  export function recordCanvasChange(entry) {
35
- discardRedo();
36
- undoStack.push({ kind: "canvas", ...entry });
37
- notify();
38
- }
39
- export function replayTimeline(direction, applyEdit) {
40
- const source = direction === "undo" ? undoStack : redoStack;
41
- const destination = direction === "undo" ? redoStack : undoStack;
42
- const entry = source.pop();
43
- if (!entry)
44
- return false;
45
- if (entry.kind === "edit")
46
- applyEdit(entry, direction === "undo" ? entry.before : entry.after);
47
- else
48
- entry[direction]();
49
- destination.push(entry);
50
- notify();
51
- return true;
114
+ sessionTimeline.recordCanvasChange(entry);
52
115
  }
53
- export function pruneDraftHistory(draftId, retain, equal) {
54
- const prune = (entries) => entries.flatMap((entry) => {
55
- if (entry.kind !== "edit" || entry.draftId !== draftId)
56
- return [entry];
57
- const next = { ...entry, before: retain(entry.before), after: retain(entry.after) };
58
- return equal(next.before, next.after) ? [] : [next];
59
- });
60
- undoStack = prune(undoStack);
61
- redoStack = prune(redoStack);
62
- notify();
116
+ export function discardCanvasHistory(cardId) {
117
+ sessionTimeline.discardCanvasHistory(cardId);
63
118
  }
64
119
  export function discardDraftHistory(draftId) {
65
- const retain = (entry) => entry.kind !== "edit" || entry.draftId !== draftId;
66
- undoStack = undoStack.filter(retain);
67
- redoStack = redoStack.filter(retain);
68
- notify();
69
- }
70
- export function discardCanvasHistory(cardId) {
71
- const retain = (entry) => entry.kind !== "canvas" || !entry.cardIds.includes(cardId);
72
- undoStack = undoStack.filter(retain);
73
- const discarded = redoStack.filter((entry) => !retain(entry));
74
- redoStack = redoStack.filter(retain);
75
- for (const entry of discarded)
76
- if (entry.kind === "canvas")
77
- entry.dispose();
78
- notify();
120
+ sessionTimeline.discardDraftHistory(draftId);
79
121
  }
80
122
  export function clearSessionUndoHistory() {
81
- const discarded = [...undoStack, ...redoStack];
82
- undoStack = [];
83
- redoStack = [];
84
- for (const entry of discarded)
85
- if (entry.kind === "canvas")
86
- entry.dispose();
87
- notify();
123
+ sessionTimeline.clear();
88
124
  }
89
125
  export function releaseDetachedIterations() {
90
- discardRedo();
91
- for (const entry of undoStack)
92
- if (entry.kind === "canvas")
93
- entry.dispose();
94
- notify();
126
+ sessionTimeline.releaseDetachedIterations();
95
127
  }
96
128
  export function createChangeHistoryGroup() {
97
- const group = Symbol("change-history-group");
98
- return (update) => {
99
- const previous = activeGroup;
100
- activeGroup = group;
101
- try {
102
- update();
103
- }
104
- finally {
105
- activeGroup = previous;
106
- }
107
- };
129
+ return sessionTimeline.createGroup();
108
130
  }
@@ -6,7 +6,7 @@
6
6
  * imports. Hosts can use the same validation and message shapes without
7
7
  * pulling the companion into a browser bundle.
8
8
  */
9
- export declare const AGENT_PROTOCOL_VERSION: 2;
9
+ export declare const AGENT_PROTOCOL_VERSION: 3;
10
10
  export declare const AGENT_PROTOCOL_LIMITS: {
11
11
  readonly projectId: 256;
12
12
  readonly workspaceRoot: 4096;
@@ -35,15 +35,8 @@ export declare const AGENT_PROTOCOL_LIMITS: {
35
35
  readonly routeTitle: 512;
36
36
  readonly routeCount: 64;
37
37
  readonly canvasCardCount: 128;
38
+ readonly agentClientName: 120;
38
39
  };
39
- /**
40
- * Returns the default project-specific loopback port used by the CLI.
41
- *
42
- * The value is deterministic so a browser can probe the companion without a
43
- * port file, while the range stays high enough to avoid common dev servers.
44
- * Callers may still override it with an explicit port when a collision occurs.
45
- */
46
- export declare function defaultBridgePort(projectId: string): number;
47
40
  export type AgentProtocolVersion = typeof AGENT_PROTOCOL_VERSION;
48
41
  /** A project identity is the pairing boundary for one companion process. */
49
42
  export interface AgentProjectIdentity {
@@ -164,14 +157,14 @@ export interface AgentSketchAttachment extends AgentSketchMetadata {
164
157
  export interface AgentDeliveredPrompt extends AgentPromptRequest {
165
158
  readonly attachments?: readonly AgentSketchAttachment[];
166
159
  }
167
- export type AgentRequestStatus = "working" | "completed" | "failed" | "interrupted";
160
+ export type AgentRequestStatus = "delivered" | "working" | "completed" | "failed" | "interrupted";
168
161
  export interface AgentRequestOutcome {
169
162
  readonly requestId: string;
170
- readonly status: AgentRequestStatus;
163
+ readonly status: Exclude<AgentRequestStatus, "delivered">;
171
164
  readonly summary?: string;
172
165
  readonly error?: string;
173
166
  }
174
- export type AgentConnectionState = "offline" | "listening" | "paired" | "working";
167
+ export type AgentConnectionState = "offline" | "listening" | "paired" | "delivered" | "working";
175
168
  export interface AgentStatusSnapshot {
176
169
  readonly protocolVersion: AgentProtocolVersion;
177
170
  readonly projectId: string;
@@ -269,7 +262,7 @@ export interface StatusEventRequest {
269
262
  }
270
263
  export interface AgentStatusUpdate {
271
264
  readonly requestId: string;
272
- readonly status: AgentRequestStatus;
265
+ readonly status: Exclude<AgentRequestStatus, "delivered">;
273
266
  readonly summary?: string;
274
267
  readonly error?: string;
275
268
  }
@@ -277,6 +270,29 @@ export interface ProtocolErrorShape {
277
270
  readonly code: string;
278
271
  readonly message: string;
279
272
  }
273
+ /** Options a development host passes to the optional project bridge. */
274
+ export interface ProjectBridgeStartOptions {
275
+ readonly appRoot: string;
276
+ readonly projectId: string;
277
+ readonly origin: string;
278
+ /** Other explicit browser origins, such as loopback aliases on the same port. */
279
+ readonly allowedOrigins?: readonly string[];
280
+ }
281
+ /** The started project bridge as seen by the development host that owns it. */
282
+ export interface ProjectBridgeHandle {
283
+ readonly browser: {
284
+ readonly projectId: string;
285
+ readonly origin: string;
286
+ readonly bridgeUrl: string;
287
+ };
288
+ close(): Promise<void>;
289
+ }
290
+ /**
291
+ * The `startProjectBridge` export of `@nudge-ui/mcp/project`. Hosts load it
292
+ * dynamically from the application's own dependencies, so this type is the
293
+ * only compile-time link between the two packages.
294
+ */
295
+ export type StartProjectBridge = (options: ProjectBridgeStartOptions) => Promise<ProjectBridgeHandle>;
280
296
  /**
281
297
  * Returns a canonical origin or null. Credentials, paths, and fragments are
282
298
  * rejected so the browser cannot broaden the pairing boundary accidentally.
@@ -309,5 +325,26 @@ export declare function isAgentStatusUpdate(value: unknown): value is AgentStatu
309
325
  export declare function isCanvasState(value: unknown): value is CanvasState;
310
326
  export declare function isCanvasGroup(value: unknown): value is CanvasGroup;
311
327
  export declare function isCanvasCommand(value: unknown): value is CanvasCommand;
328
+ export declare function isAgentDeliveredPrompt(value: unknown): value is AgentDeliveredPrompt;
329
+ /** A Canvas acknowledgement or result; a successful one never carries an error. */
330
+ export declare function isCanvasCommandResult(value: unknown): value is CanvasCommandResult;
331
+ /** The connection state shown for a pairing, a listener, and the current request. */
332
+ export declare function deriveConnectionState(status: Pick<AgentStatusSnapshot, "listenerActive" | "paired" | "request">): AgentConnectionState;
333
+ /**
334
+ * Decodes a status snapshot from any peer. Unknown fields are dropped and the
335
+ * connection state is recomputed, so a snapshot can never claim a state its
336
+ * own fields contradict.
337
+ */
338
+ export declare function decodeAgentStatusSnapshot(value: unknown): AgentStatusSnapshot | null;
339
+ /**
340
+ * Decodes the event inside a bridge envelope. A Canvas command is passed
341
+ * through as received: the Canvas controller validates it so a malformed
342
+ * command still receives an error acknowledgement instead of a timeout.
343
+ */
344
+ export declare function decodeBridgeEvent(value: unknown): BridgeEvent | null;
345
+ /** Decodes a pairing or takeover response for the exact project and origin requested. */
346
+ export declare function decodePairingResponse(value: unknown, expected: Pick<PairingRequest, "projectId" | "origin">): PairingResponse | null;
347
+ /** Decodes the accepted-prompt response for the project that dispatched it. */
348
+ export declare function decodePromptDispatchResponse(value: unknown, projectId: string): PromptDispatchResponse | null;
312
349
  /** Creates a stable protocol error shape without exposing thrown values. */
313
350
  export declare function protocolError(code: string, message: string): ProtocolErrorShape;
@@ -6,7 +6,7 @@
6
6
  * imports. Hosts can use the same validation and message shapes without
7
7
  * pulling the companion into a browser bundle.
8
8
  */
9
- export const AGENT_PROTOCOL_VERSION = 2;
9
+ export const AGENT_PROTOCOL_VERSION = 3;
10
10
  export const AGENT_PROTOCOL_LIMITS = {
11
11
  projectId: 256,
12
12
  workspaceRoot: 4096,
@@ -35,25 +35,8 @@ export const AGENT_PROTOCOL_LIMITS = {
35
35
  routeTitle: 512,
36
36
  routeCount: 64,
37
37
  canvasCardCount: 128,
38
+ agentClientName: 120,
38
39
  };
39
- /**
40
- * Returns the default project-specific loopback port used by the CLI.
41
- *
42
- * The value is deterministic so a browser can probe the companion without a
43
- * port file, while the range stays high enough to avoid common dev servers.
44
- * Callers may still override it with an explicit port when a collision occurs.
45
- */
46
- export function defaultBridgePort(projectId) {
47
- if (!nonEmptyString(projectId, AGENT_PROTOCOL_LIMITS.projectId)) {
48
- throw new TypeError("projectId must be a bounded non-empty string");
49
- }
50
- let hash = 2_166_136_261;
51
- for (let index = 0; index < projectId.length; index += 1) {
52
- hash ^= projectId.charCodeAt(index);
53
- hash = Math.imul(hash, 16_777_619);
54
- }
55
- return 30_000 + ((hash >>> 0) % 20_000);
56
- }
57
40
  export const CANVAS_COMMAND_TYPES = [
58
41
  "read-state",
59
42
  "present-routes",
@@ -421,6 +404,149 @@ export function isCanvasCommand(value) {
421
404
  return false;
422
405
  }
423
406
  }
407
+ export function isAgentDeliveredPrompt(value) {
408
+ if (!isRecord(value))
409
+ return false;
410
+ const { attachments, ...request } = value;
411
+ return isAgentPromptRequest(request)
412
+ && (attachments === undefined || (Array.isArray(attachments)
413
+ && attachments.length <= AGENT_PROTOCOL_LIMITS.sketchCount
414
+ && attachments.every(isAgentSketchAttachment)));
415
+ }
416
+ function isCanvasCommandError(value) {
417
+ return isRecord(value) && hasOnlyKeys(value, ["code", "message"])
418
+ && nonEmptyString(value.code, 128)
419
+ && typeof value.message === "string" && value.message.length <= AGENT_PROTOCOL_LIMITS.prompt;
420
+ }
421
+ /** A Canvas acknowledgement or result; a successful one never carries an error. */
422
+ export function isCanvasCommandResult(value) {
423
+ if (!isRecord(value) || !hasOnlyKeys(value, ["commandId", "ok", "state", "group", "error"]))
424
+ return false;
425
+ return nonEmptyString(value.commandId, AGENT_PROTOCOL_LIMITS.commandId)
426
+ && typeof value.ok === "boolean"
427
+ && (value.state === undefined || isCanvasState(value.state))
428
+ && (value.group === undefined || isCanvasGroup(value.group))
429
+ && (value.error === undefined || (!value.ok && isCanvasCommandError(value.error)));
430
+ }
431
+ /** The connection state shown for a pairing, a listener, and the current request. */
432
+ export function deriveConnectionState(status) {
433
+ if (status.request?.status === "delivered")
434
+ return "delivered";
435
+ if (status.request?.status === "working")
436
+ return "working";
437
+ if (status.paired)
438
+ return "paired";
439
+ if (status.listenerActive)
440
+ return "listening";
441
+ return "offline";
442
+ }
443
+ function isRequestStatus(value) {
444
+ return value === "delivered" || value === "working" || value === "completed" || value === "failed" || value === "interrupted";
445
+ }
446
+ function decodeStatusRequest(value) {
447
+ if (value === null || value === undefined)
448
+ return null;
449
+ if (!isRecord(value))
450
+ return undefined;
451
+ const { status, summary, error, ...request } = value;
452
+ if (!isRequestStatus(status) || !isAgentPromptRequest(request)
453
+ || !optionalString(summary, AGENT_PROTOCOL_LIMITS.prompt)
454
+ || !optionalString(error, AGENT_PROTOCOL_LIMITS.prompt))
455
+ return undefined;
456
+ return {
457
+ ...request,
458
+ status,
459
+ ...(summary === undefined ? {} : { summary }),
460
+ ...(error === undefined ? {} : { error }),
461
+ };
462
+ }
463
+ /**
464
+ * Decodes a status snapshot from any peer. Unknown fields are dropped and the
465
+ * connection state is recomputed, so a snapshot can never claim a state its
466
+ * own fields contradict.
467
+ */
468
+ export function decodeAgentStatusSnapshot(value) {
469
+ if (!isRecord(value)
470
+ || value.protocolVersion !== AGENT_PROTOCOL_VERSION
471
+ || !nonEmptyString(value.projectId, AGENT_PROTOCOL_LIMITS.projectId)
472
+ || (value.connection !== "offline" && value.connection !== "listening"
473
+ && value.connection !== "paired" && value.connection !== "delivered" && value.connection !== "working")
474
+ || typeof value.listenerActive !== "boolean"
475
+ || typeof value.paired !== "boolean"
476
+ || !(value.pageUrl === undefined || value.pageUrl === null
477
+ || nonEmptyString(value.pageUrl, AGENT_PROTOCOL_LIMITS.routeUrl)))
478
+ return null;
479
+ const request = decodeStatusRequest(value.request);
480
+ if (request === undefined)
481
+ return null;
482
+ const fields = { listenerActive: value.listenerActive, paired: value.paired, request };
483
+ return {
484
+ protocolVersion: AGENT_PROTOCOL_VERSION,
485
+ projectId: value.projectId,
486
+ connection: deriveConnectionState(fields),
487
+ ...fields,
488
+ ...(value.pageUrl === undefined ? {} : { pageUrl: value.pageUrl }),
489
+ ...(typeof value.agentClientName === "string" && value.agentClientName.length > 0
490
+ ? { agentClientName: value.agentClientName.slice(0, AGENT_PROTOCOL_LIMITS.agentClientName) }
491
+ : {}),
492
+ };
493
+ }
494
+ /**
495
+ * Decodes the event inside a bridge envelope. A Canvas command is passed
496
+ * through as received: the Canvas controller validates it so a malformed
497
+ * command still receives an error acknowledgement instead of a timeout.
498
+ */
499
+ export function decodeBridgeEvent(value) {
500
+ if (!isRecord(value))
501
+ return null;
502
+ switch (value.type) {
503
+ case "status":
504
+ case "connected": {
505
+ const status = decodeAgentStatusSnapshot(value.status);
506
+ return status ? { type: value.type, status } : null;
507
+ }
508
+ case "disconnected":
509
+ return {
510
+ type: "disconnected",
511
+ ...(nonEmptyString(value.reason, AGENT_PROTOCOL_LIMITS.prompt) ? { reason: value.reason } : {}),
512
+ };
513
+ case "activity":
514
+ return isAgentActivity(value.activity) ? { type: "activity", activity: value.activity } : null;
515
+ case "canvas-command":
516
+ // SAFETY: the Canvas controller validates the command before acting on it.
517
+ return isRecord(value.command) ? { type: "canvas-command", command: value.command } : null;
518
+ default:
519
+ return null;
520
+ }
521
+ }
522
+ /** Decodes a pairing or takeover response for the exact project and origin requested. */
523
+ export function decodePairingResponse(value, expected) {
524
+ if (!isRecord(value)
525
+ || value.protocolVersion !== AGENT_PROTOCOL_VERSION
526
+ || value.projectId !== expected.projectId
527
+ || value.origin !== expected.origin
528
+ || !nonEmptyString(value.sessionToken, AGENT_PROTOCOL_LIMITS.sessionToken)
529
+ || !(value.pageUrl === undefined || nonEmptyString(value.pageUrl, AGENT_PROTOCOL_LIMITS.routeUrl)))
530
+ return null;
531
+ const status = decodeAgentStatusSnapshot(value.status);
532
+ if (!status)
533
+ return null;
534
+ return {
535
+ protocolVersion: AGENT_PROTOCOL_VERSION,
536
+ projectId: expected.projectId,
537
+ origin: expected.origin,
538
+ sessionToken: value.sessionToken,
539
+ ...(value.pageUrl === undefined ? {} : { pageUrl: value.pageUrl }),
540
+ status,
541
+ };
542
+ }
543
+ /** Decodes the accepted-prompt response for the project that dispatched it. */
544
+ export function decodePromptDispatchResponse(value, projectId) {
545
+ if (!isRecord(value) || (value.status !== "delivered" && value.status !== "working") || !isAgentPromptRequest(value.request)
546
+ || value.request.projectId !== projectId)
547
+ return null;
548
+ return { request: value.request, status: value.status };
549
+ }
424
550
  /** Creates a stable protocol error shape without exposing thrown values. */
425
551
  export function protocolError(code, message) {
426
552
  if (!nonEmptyString(code, 128) || !nonEmptyString(message, AGENT_PROTOCOL_LIMITS.prompt)) {