nudge-ui 0.2.2 → 0.2.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 (226) hide show
  1. package/README.md +164 -46
  2. package/dist/client.mjs +252 -61
  3. package/dist/css/value-semantics/colorSemantics.d.ts +4 -0
  4. package/dist/css/value-semantics/colorSemantics.js +17 -0
  5. package/dist/hosts/astro/astroRuntimeConfig.js +1 -0
  6. package/dist/hosts/astro/clientTransport.js +38 -32
  7. package/dist/hosts/astro/integration.js +5 -1
  8. package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
  9. package/dist/hosts/astro/markdownIdentity.js +81 -0
  10. package/dist/hosts/next/manifest.js +1 -1
  11. package/dist/hosts/next/sidecar.js +5 -1
  12. package/dist/hosts/static/manifest.js +1 -1
  13. package/dist/hosts/static/server.js +3 -0
  14. package/dist/hosts/vite/vite.d.ts +3 -0
  15. package/dist/hosts/vite/vite.js +24 -4
  16. package/dist/inspector/agent/McpConnectionDialog.js +13 -19
  17. package/dist/inspector/agent/activity.d.ts +18 -0
  18. package/dist/inspector/agent/activity.js +70 -0
  19. package/dist/inspector/agent/client.d.ts +2 -0
  20. package/dist/inspector/agent/client.js +29 -1
  21. package/dist/inspector/agent/connectionStatus.js +1 -1
  22. package/dist/inspector/agent/httpTransport.js +9 -2
  23. package/dist/inspector/agent/protocol.d.ts +6 -3
  24. package/dist/inspector/agent/protocol.js +1 -1
  25. package/dist/inspector/agent/verification.d.ts +11 -1
  26. package/dist/inspector/agent/verification.js +53 -25
  27. package/dist/inspector/canvas/AgentActivityOverlay.d.ts +13 -0
  28. package/dist/inspector/canvas/AgentActivityOverlay.js +111 -0
  29. package/dist/inspector/canvas/CanvasCard.d.ts +9 -2
  30. package/dist/inspector/canvas/CanvasCard.js +133 -38
  31. package/dist/inspector/canvas/CanvasElementOverlay.js +152 -16
  32. package/dist/inspector/canvas/CanvasToolIcons.d.ts +10 -0
  33. package/dist/inspector/canvas/CanvasToolIcons.js +20 -0
  34. package/dist/inspector/canvas/CanvasToolbar.js +8 -4
  35. package/dist/inspector/canvas/CanvasWorkspace.js +225 -57
  36. package/dist/inspector/canvas/StaleChangeIndicator.js +3 -13
  37. package/dist/inspector/canvas/agentPresentation.d.ts +8 -8
  38. package/dist/inspector/canvas/agentPresentation.js +64 -52
  39. package/dist/inspector/canvas/canvasGestures.d.ts +1 -1
  40. package/dist/inspector/canvas/canvasGestures.js +1 -1
  41. package/dist/inspector/canvas/canvasStore.d.ts +46 -82
  42. package/dist/inspector/canvas/canvasStore.js +251 -284
  43. package/dist/inspector/canvas/frameContent.d.ts +21 -0
  44. package/dist/inspector/canvas/frameContent.js +44 -0
  45. package/dist/inspector/canvas/frameProtocol.d.ts +21 -4
  46. package/dist/inspector/canvas/frameProtocol.js +3 -3
  47. package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -1
  48. package/dist/inspector/canvas/keyboardShortcuts.js +4 -4
  49. package/dist/inspector/canvas/layout.d.ts +52 -0
  50. package/dist/inspector/canvas/layout.js +106 -0
  51. package/dist/inspector/canvas/projection.d.ts +15 -5
  52. package/dist/inspector/canvas/projection.js +69 -13
  53. package/dist/inspector/canvas/rendererBootstrap.js +32 -4
  54. package/dist/inspector/canvas/rendererElementSelector.js +47 -6
  55. package/dist/inspector/canvas/rendererStylesheet.js +2 -2
  56. package/dist/inspector/canvas/resizeHandleScale.js +1 -1
  57. package/dist/inspector/canvas/sessionStore.d.ts +11 -26
  58. package/dist/inspector/canvas/sessionStore.js +43 -183
  59. package/dist/inspector/canvas/staleChangeDetector.js +9 -3
  60. package/dist/inspector/canvas/useCanvasLayoutAnimation.d.ts +5 -0
  61. package/dist/inspector/canvas/useCanvasLayoutAnimation.js +107 -0
  62. package/dist/inspector/canvas/viewStore.d.ts +38 -0
  63. package/dist/inspector/canvas/viewStore.js +104 -0
  64. package/dist/inspector/canvas/wheelPan.d.ts +8 -0
  65. package/dist/inspector/canvas/wheelPan.js +8 -0
  66. package/dist/inspector/changes/changesLog.d.ts +6 -5
  67. package/dist/inspector/changes/changesLog.js +40 -32
  68. package/dist/inspector/changes/draftChanges.d.ts +56 -0
  69. package/dist/inspector/changes/draftChanges.js +300 -0
  70. package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
  71. package/dist/inspector/changes/previewDiagnostics.js +11 -25
  72. package/dist/inspector/clientManifest.d.ts +1 -1
  73. package/dist/inspector/comments/CommentsOverlay.d.ts +2 -0
  74. package/dist/inspector/comments/CommentsOverlay.js +250 -0
  75. package/dist/inspector/comments/element.d.ts +6 -0
  76. package/dist/inspector/comments/element.js +47 -0
  77. package/dist/inspector/comments/store.d.ts +29 -0
  78. package/dist/inspector/comments/store.js +121 -0
  79. package/dist/inspector/comments/verification.d.ts +5 -0
  80. package/dist/inspector/comments/verification.js +52 -0
  81. package/dist/inspector/drafts/model.d.ts +35 -0
  82. package/dist/inspector/drafts/model.js +45 -0
  83. package/dist/inspector/drafts/store.d.ts +28 -0
  84. package/dist/inspector/drafts/store.js +231 -0
  85. package/dist/inspector/index.js +20 -27
  86. package/dist/inspector/inline-text/inlineTextEditor.js +7 -0
  87. package/dist/inspector/inspection/useBrowserCssInspection.js +15 -1
  88. package/dist/inspector/iterations/capture.d.ts +2 -0
  89. package/dist/inspector/iterations/capture.js +173 -0
  90. package/dist/inspector/iterations/client.d.ts +7 -0
  91. package/dist/inspector/iterations/client.js +52 -0
  92. package/dist/inspector/iterations/coordinator.d.ts +15 -0
  93. package/dist/inspector/iterations/coordinator.js +130 -0
  94. package/dist/inspector/iterations/prompt.d.ts +3 -0
  95. package/dist/inspector/iterations/prompt.js +26 -0
  96. package/dist/inspector/overlay/DomNavigator.js +21 -15
  97. package/dist/inspector/overlay/interactionStyles.js +3 -1
  98. package/dist/inspector/overlay/spacingGestures.d.ts +13 -1
  99. package/dist/inspector/overlay/spacingGestures.js +82 -5
  100. package/dist/inspector/projection/{workspaceProjection.d.ts → draftProjection.d.ts} +6 -6
  101. package/dist/inspector/projection/{workspaceProjection.js → draftProjection.js} +4 -4
  102. package/dist/inspector/projection/renderedInstance.d.ts +2 -1
  103. package/dist/inspector/projection/renderedInstance.js +9 -5
  104. package/dist/inspector/projection/structuralProjection.d.ts +2 -1
  105. package/dist/inspector/projection/structuralProjection.js +19 -15
  106. package/dist/inspector/projection/textProjection.d.ts +2 -1
  107. package/dist/inspector/projection/textProjection.js +8 -4
  108. package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
  109. package/dist/inspector/prompt/clipboardHandoff.d.ts +10 -18
  110. package/dist/inspector/prompt/clipboardHandoff.js +92 -143
  111. package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
  112. package/dist/inspector/prompt/generatePrompt.js +17 -16
  113. package/dist/inspector/runtime/runtimeConfig.d.ts +9 -0
  114. package/dist/inspector/runtime/runtimeConfig.js +24 -0
  115. package/dist/inspector/settings/SettingsDialog.js +21 -8
  116. package/dist/inspector/shell/AgentStatusButton.d.ts +11 -0
  117. package/dist/inspector/shell/AgentStatusButton.js +36 -0
  118. package/dist/inspector/shell/AppShell.js +4 -2
  119. package/dist/inspector/shell/ChangesLog.js +46 -26
  120. package/dist/inspector/shell/CopyPromptButton.js +138 -89
  121. package/dist/inspector/shell/EmptyState.js +9 -8
  122. package/dist/inspector/shell/InspectorShell.js +13 -21
  123. package/dist/inspector/shell/PeekOriginalButton.js +24 -23
  124. package/dist/inspector/shell/originalPreview.js +5 -5
  125. package/dist/inspector/shell/shortcuts.d.ts +3 -0
  126. package/dist/inspector/shell/shortcuts.js +11 -0
  127. package/dist/inspector/sketch/SketchEditor.js +14 -14
  128. package/dist/inspector/sketch/SketchEntryButton.js +1 -1
  129. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +3 -1
  130. package/dist/inspector/sketch/SketchFrameOverlay.js +11 -8
  131. package/dist/inspector/sketch/SketchLayersPanel.js +13 -5
  132. package/dist/inspector/sketch/SketchOverlay.js +7 -7
  133. package/dist/inspector/sketch/SketchWorkspace.js +18 -12
  134. package/dist/inspector/sketch/interaction.d.ts +1 -0
  135. package/dist/inspector/sketch/interaction.js +8 -4
  136. package/dist/inspector/sketch/model.d.ts +5 -0
  137. package/dist/inspector/sketch/model.js +6 -2
  138. package/dist/inspector/sketch/raster.d.ts +1 -2
  139. package/dist/inspector/sketch/raster.js +68 -4
  140. package/dist/inspector/styleEditors/BackgroundEditor.d.ts +4 -0
  141. package/dist/inspector/styleEditors/BackgroundEditor.js +195 -0
  142. package/dist/inspector/styleEditors/BorderEditor.js +49 -78
  143. package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -1
  144. package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +1 -2
  145. package/dist/inspector/styleEditors/BoxShadowEditor.js +132 -4
  146. package/dist/inspector/styleEditors/ColorPicker.d.ts +5 -1
  147. package/dist/inspector/styleEditors/ColorPicker.js +10 -4
  148. package/dist/inspector/styleEditors/GapField.js +3 -5
  149. package/dist/inspector/styleEditors/GridChildSection.d.ts +1 -1
  150. package/dist/inspector/styleEditors/GridChildSection.js +18 -9
  151. package/dist/inspector/styleEditors/GridPicker.d.ts +1 -1
  152. package/dist/inspector/styleEditors/GridPicker.js +8 -2
  153. package/dist/inspector/styleEditors/GridSection.js +1 -1
  154. package/dist/inspector/styleEditors/GridValueField.js +19 -14
  155. package/dist/inspector/styleEditors/ImageBackgroundEditor.d.ts +18 -0
  156. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +118 -0
  157. package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +2 -2
  158. package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +3 -3
  159. package/dist/inspector/styleEditors/LayoutComboField.js +6 -4
  160. package/dist/inspector/styleEditors/LayoutDropdown.js +6 -3
  161. package/dist/inspector/styleEditors/LayoutSection.js +32 -11
  162. package/dist/inspector/styleEditors/SpacingBox.js +7 -5
  163. package/dist/inspector/styleEditors/Typography.js +11 -3
  164. package/dist/inspector/styleEditors/backgroundLayers.d.ts +24 -0
  165. package/dist/inspector/styleEditors/backgroundLayers.js +51 -0
  166. package/dist/inspector/styleEditors/gradientValue.d.ts +17 -0
  167. package/dist/inspector/styleEditors/gradientValue.js +114 -0
  168. package/dist/inspector/styleEditors/inlineAuthored.d.ts +10 -0
  169. package/dist/inspector/styleEditors/inlineAuthored.js +114 -0
  170. package/dist/inspector/styleEditors/layoutValue.d.ts +0 -8
  171. package/dist/inspector/styleEditors/layoutValue.js +0 -42
  172. package/dist/inspector/styleEditors/nudgeValue.d.ts +2 -2
  173. package/dist/inspector/styleEditors/nudgeValue.js +36 -8
  174. package/dist/inspector/tokens/TokenField.d.ts +7 -0
  175. package/dist/inspector/tokens/TokenField.js +29 -21
  176. package/dist/inspector/tokens/TokenLabel.js +5 -14
  177. package/dist/inspector/tokens/editActions.d.ts +1 -1
  178. package/dist/inspector/tokens/editActions.js +1 -1
  179. package/dist/inspector/ui/AtRuleContext.js +4 -6
  180. package/dist/inspector/ui/Button.d.ts +6 -2
  181. package/dist/inspector/ui/Button.js +4 -3
  182. package/dist/inspector/ui/ControlSurface.d.ts +2 -2
  183. package/dist/inspector/ui/ControlSurface.js +4 -3
  184. package/dist/inspector/ui/InlineStyleWarning.d.ts +11 -0
  185. package/dist/inspector/ui/InlineStyleWarning.js +13 -0
  186. package/dist/inspector/ui/InspectorPopover.d.ts +2 -1
  187. package/dist/inspector/ui/InspectorPopover.js +4 -5
  188. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  189. package/dist/inspector/ui/PopoverListbox.js +8 -7
  190. package/dist/inspector/ui/SegmentedControl.d.ts +2 -1
  191. package/dist/inspector/ui/SegmentedControl.js +2 -2
  192. package/dist/inspector/ui/Select.d.ts +6 -1
  193. package/dist/inspector/ui/Select.js +7 -11
  194. package/dist/inspector/ui/SideValuesField.js +1 -1
  195. package/dist/inspector/ui/Tooltip.d.ts +26 -0
  196. package/dist/inspector/ui/Tooltip.js +32 -0
  197. package/dist/inspector/ui/classNames.d.ts +2 -0
  198. package/dist/inspector/ui/classNames.js +4 -0
  199. package/dist/inspector/ui/customCursors.d.ts +23 -0
  200. package/dist/inspector/ui/customCursors.js +122 -0
  201. package/dist/inspector/ui/dragCursor.d.ts +0 -2
  202. package/dist/inspector/ui/dragCursor.js +2 -10
  203. package/dist/inspector/ui/portalContainer.d.ts +2 -0
  204. package/dist/inspector/ui/portalContainer.js +6 -0
  205. package/dist/inspector/ui/styles.js +29 -21
  206. package/dist/inspector/workspace/commands.d.ts +9 -0
  207. package/dist/inspector/workspace/commands.js +82 -0
  208. package/dist/inspector/workspace/controller.d.ts +4 -0
  209. package/dist/inspector/workspace/controller.js +66 -0
  210. package/dist/inspector/workspace/handoff.d.ts +42 -0
  211. package/dist/inspector/workspace/handoff.js +115 -0
  212. package/dist/inspector/workspace/timeline.d.ts +30 -0
  213. package/dist/inspector/workspace/timeline.js +108 -0
  214. package/dist/internal/agent-protocol.d.ts +19 -2
  215. package/dist/internal/agent-protocol.js +13 -0
  216. package/dist/nudge-ui.mjs +558 -311
  217. package/dist/project/artifacts.d.ts +13 -0
  218. package/dist/project/artifacts.js +253 -0
  219. package/dist/transport/artifacts.d.ts +8 -0
  220. package/dist/transport/artifacts.js +9 -0
  221. package/dist/transport/editor.js +3 -1
  222. package/dist/transport/routes.d.ts +2 -0
  223. package/dist/transport/routes.js +2 -0
  224. package/package.json +6 -2
  225. package/dist/inspector/changes/workspaceChanges.d.ts +0 -47
  226. package/dist/inspector/changes/workspaceChanges.js +0 -265
@@ -1,3 +1,4 @@
1
+ import { reportAgentActivity, synchronizeAgentActivity } from "./activity.js";
1
2
  import { useEffect, useMemo, useSyncExternalStore } from "react";
2
3
  import { isNudgeUiDev } from "../runtime/devFlag.js";
3
4
  import { isDemoRuntime } from "../runtime/runtimeConfig.js";
@@ -153,6 +154,7 @@ export class AgentClient {
153
154
  started = false;
154
155
  connection = "offline";
155
156
  listenerActive = false;
157
+ agentClientName;
156
158
  companionReachable = false;
157
159
  paired = false;
158
160
  pairedElsewhere = false;
@@ -583,6 +585,10 @@ export class AgentClient {
583
585
  }, this.discoveryIntervalMs);
584
586
  }
585
587
  handleEvent(event) {
588
+ if (event.type === "activity") {
589
+ reportAgentActivity(this.projectId, event.activity);
590
+ return;
591
+ }
586
592
  if (event.type === "status" || event.type === "connected") {
587
593
  if (event.status.projectId !== this.projectId || event.status.protocolVersion !== AGENT_PROTOCOL_VERSION) {
588
594
  this.handleDisconnect("The agent bridge project or protocol does not match this page.");
@@ -649,6 +655,7 @@ export class AgentClient {
649
655
  this.companionReachable = true;
650
656
  this.lastError = undefined;
651
657
  this.listenerActive = status.listenerActive;
658
+ this.agentClientName = status.agentClientName;
652
659
  this.paired = status.paired;
653
660
  this.pairedElsewhere = pairedElsewhere;
654
661
  this.connection = statusForConnection(status);
@@ -754,6 +761,7 @@ export class AgentClient {
754
761
  state,
755
762
  connection: this.connection,
756
763
  listenerActive: this.listenerActive,
764
+ ...(this.agentClientName === undefined ? {} : { agentClientName: this.agentClientName }),
757
765
  companionReachable: this.companionReachable,
758
766
  paired: this.paired,
759
767
  pairedElsewhere: this.pairedElsewhere,
@@ -788,17 +796,20 @@ export class AgentClient {
788
796
  }
789
797
  publish(stateOverride) {
790
798
  this.snapshot = Object.freeze(this.makeSnapshot(stateOverride));
799
+ synchronizeAgentActivity(this.projectId, this.snapshot.request?.requestId, this.snapshot.paired && this.snapshot.request?.status === "working", this.snapshot.request?.clientDispatchId);
791
800
  for (const listener of this.listeners)
792
801
  listener();
793
802
  }
794
803
  }
795
804
  let configuredTransport;
796
805
  const clients = new Map();
806
+ const consumerCounts = new Map();
797
807
  /** Sets a host/test transport for subsequently created project clients. */
798
808
  export function configureAgentBridgeTransport(transport) {
799
809
  for (const client of clients.values())
800
810
  client.stop();
801
811
  clients.clear();
812
+ consumerCounts.clear();
802
813
  configuredTransport = transport;
803
814
  }
804
815
  /** Clears cached clients and their active streams. */
@@ -806,6 +817,22 @@ export function resetAgentClients() {
806
817
  for (const client of clients.values())
807
818
  client.stop();
808
819
  clients.clear();
820
+ consumerCounts.clear();
821
+ }
822
+ function retainAgentClient(client) {
823
+ consumerCounts.set(client, (consumerCounts.get(client) ?? 0) + 1);
824
+ }
825
+ function releaseAgentClient(client) {
826
+ const count = consumerCounts.get(client);
827
+ // A reset already stopped the client and dropped its consumers.
828
+ if (count === undefined)
829
+ return;
830
+ if (count > 1) {
831
+ consumerCounts.set(client, count - 1);
832
+ return;
833
+ }
834
+ consumerCounts.delete(client);
835
+ client.stop();
809
836
  }
810
837
  export function createAgentClient(options) {
811
838
  return new AgentClient({ ...options, transport: options.transport ?? configuredTransport });
@@ -824,8 +851,9 @@ export function getAgentClient(projectId, options = {}) {
824
851
  export function useAgentClient(projectId, suppliedClient) {
825
852
  const client = useMemo(() => suppliedClient ?? getAgentClient(projectId), [projectId, suppliedClient]);
826
853
  useEffect(() => {
854
+ retainAgentClient(client);
827
855
  client.start();
828
- return () => client.stop();
856
+ return () => releaseAgentClient(client);
829
857
  }, [client]);
830
858
  return useSyncExternalStore(client.subscribe, client.getSnapshot, client.getSnapshot);
831
859
  }
@@ -23,7 +23,7 @@ export function getAgentConnectionStatus(snapshot) {
23
23
  if (snapshot.paired && !snapshot.listenerActive) {
24
24
  return {
25
25
  kind: "connected-not-listening",
26
- label: "Project connected · Ask agent to listen",
26
+ label: "MCP Ready - Ask agent to listen",
27
27
  tone: "accent",
28
28
  };
29
29
  }
@@ -1,4 +1,4 @@
1
- import { AGENT_PROTOCOL_VERSION, defaultBridgePort, isAgentPromptRequest, } from "./protocol.js";
1
+ import { AGENT_PROTOCOL_VERSION, defaultBridgePort, isAgentPromptRequest, isAgentActivity, } from "./protocol.js";
2
2
  import { getActiveCanvasDocument } from "../canvas/activeCanvasDocument.js";
3
3
  function isRecord(value) {
4
4
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -168,6 +168,7 @@ function statusPayload(value) {
168
168
  projectId: status.projectId,
169
169
  connection: status.connection,
170
170
  listenerActive: status.listenerActive,
171
+ ...(typeof status.agentClientName === "string" ? { agentClientName: status.agentClientName.slice(0, 120) } : {}),
171
172
  paired: status.paired,
172
173
  request,
173
174
  };
@@ -189,6 +190,8 @@ function eventPayload(value) {
189
190
  if (type === "disconnected") {
190
191
  return { type: "disconnected", ...(stringValue(event.reason) ? { reason: stringValue(event.reason) } : {}) };
191
192
  }
193
+ if (type === "activity" && isAgentActivity(event.activity))
194
+ return { type: "activity", activity: event.activity };
192
195
  if (type === "canvas-command" && isRecord(event.command)) {
193
196
  // The Canvas controller owns command validation. Preserve the shared
194
197
  // shape here so the parent stage can consume this event without a second
@@ -322,7 +325,10 @@ export class HttpAgentBridgeTransport {
322
325
  const source = new EventSource(eventUrl.href);
323
326
  let closed = false;
324
327
  const handleMessage = (event) => {
325
- const parsed = eventPayload(eventData(event));
328
+ const value = eventData(event);
329
+ if (isRecord(value) && "event" in value && (value.protocolVersion !== AGENT_PROTOCOL_VERSION || value.projectId !== request.projectId || value.sessionToken !== request.sessionToken))
330
+ return;
331
+ const parsed = eventPayload(value);
326
332
  if (parsed)
327
333
  handlers.onEvent(parsed);
328
334
  };
@@ -330,6 +336,7 @@ export class HttpAgentBridgeTransport {
330
336
  source.addEventListener("status", handleMessage);
331
337
  source.addEventListener("connected", handleMessage);
332
338
  source.addEventListener("disconnected", handleMessage);
339
+ source.addEventListener("activity", handleMessage);
333
340
  source.addEventListener("canvas-command", handleMessage);
334
341
  source.onerror = () => {
335
342
  if (closed)
@@ -1,4 +1,4 @@
1
- import type { AgentStatusSnapshot, CanvasCommand, CanvasCommandAcknowledgement, CanvasCommandResult, AgentSketchAttachment, PairingResponse, PromptDispatchResponse } from "../../internal/agent-protocol.js";
1
+ import type { AgentActivity, AgentStatusSnapshot, CanvasCommand, CanvasCommandAcknowledgement, CanvasCommandResult, AgentSketchAttachment, PairingResponse, PromptDispatchResponse } from "../../internal/agent-protocol.js";
2
2
  /**
3
3
  * Browser transport port for the shared Nudge agent protocol.
4
4
  *
@@ -7,8 +7,8 @@ import type { AgentStatusSnapshot, CanvasCommand, CanvasCommandAcknowledgement,
7
7
  * boundary local lets inspector tests use a deterministic fake while the
8
8
  * companion remains the owner of MCP and Node-specific code.
9
9
  */
10
- export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, defaultBridgePort, CANVAS_COMMAND_TYPES, canonicalOrigin, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchAnnotation, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "../../internal/agent-protocol.js";
11
- export type { AgentConnectionState, AgentProjectIdentity, AgentPromptRequest, AgentDeliveredPrompt, AgentSketchAttachment, AgentSketchAnnotation, AgentSketchCaptureMetadata, AgentSketchMetadata, AgentRequestOutcome, AgentRequestStatus, AgentRoute, AgentStatusSnapshot, AgentStatusUpdate, BridgeCanvasCommandEvent, BridgeConnectedEvent, BridgeDisconnectedEvent, BridgeEnvelope, BridgeEvent, BridgeEventType, BridgeStatusEvent, CanvasCommand, CanvasCommandAcknowledgement, CanvasCommandError, CanvasCommandResult, CanvasGroup, CanvasGroupOwner, CanvasState, FitCanvasCommand, FocusCanvasGroupCommand, PairingRequest, PairingResponse, PresentRoutesCommand, PromptDispatchRequest, PromptDispatchResponse, ReadCanvasStateCommand, RemoveCanvasGroupCommand, StatusEventRequest, AgentProtocolVersion, } from "../../internal/agent-protocol.js";
10
+ export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, defaultBridgePort, CANVAS_COMMAND_TYPES, canonicalOrigin, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchAnnotation, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAgentActivity, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "../../internal/agent-protocol.js";
11
+ export type { AgentActivity, BridgeActivityEvent, AgentConnectionState, AgentProjectIdentity, AgentPromptRequest, AgentDeliveredPrompt, AgentSketchAttachment, AgentSketchAnnotation, AgentSketchCaptureMetadata, AgentSketchMetadata, AgentRequestOutcome, AgentRequestStatus, AgentRoute, AgentStatusSnapshot, AgentStatusUpdate, BridgeCanvasCommandEvent, BridgeConnectedEvent, BridgeDisconnectedEvent, BridgeEnvelope, BridgeEvent, BridgeEventType, BridgeStatusEvent, CanvasCommand, CanvasCommandAcknowledgement, CanvasCommandError, CanvasCommandResult, CanvasGroup, CanvasGroupOwner, CanvasState, FitCanvasCommand, FocusCanvasGroupCommand, PairingRequest, PairingResponse, PresentRoutesCommand, PromptDispatchRequest, PromptDispatchResponse, ReadCanvasStateCommand, RemoveCanvasGroupCommand, StatusEventRequest, AgentProtocolVersion, } from "../../internal/agent-protocol.js";
12
12
  export interface AgentBridgeEndpointConfig {
13
13
  readonly baseUrl?: string;
14
14
  readonly healthUrl?: string;
@@ -69,6 +69,9 @@ export interface AgentEventSubscription {
69
69
  }
70
70
  /** Events delivered by the companion's SSE stream. */
71
71
  export type AgentBridgeEvent = {
72
+ readonly type: "activity";
73
+ readonly activity: AgentActivity;
74
+ } | {
72
75
  readonly type: "status";
73
76
  readonly status: AgentStatusSnapshot;
74
77
  } | {
@@ -6,4 +6,4 @@
6
6
  * boundary local lets inspector tests use a deterministic fake while the
7
7
  * companion remains the owner of MCP and Node-specific code.
8
8
  */
9
- export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, defaultBridgePort, CANVAS_COMMAND_TYPES, canonicalOrigin, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchAnnotation, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "../../internal/agent-protocol.js";
9
+ export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, defaultBridgePort, CANVAS_COMMAND_TYPES, canonicalOrigin, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchAnnotation, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAgentActivity, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "../../internal/agent-protocol.js";
@@ -1,6 +1,15 @@
1
+ import { type DraftTarget } from "../drafts/model.js";
1
2
  import { type ChangeRecord } from "../changes/changesLog.js";
2
3
  import { type StructuralChange } from "../projection/structuralProjection.js";
4
+ export interface HandoffOwner {
5
+ readonly draftId: string;
6
+ readonly draftRevision: number;
7
+ readonly target: DraftTarget;
8
+ readonly frameIds: readonly string[];
9
+ }
10
+ export declare function captureHandoffOwner(cardId?: string | null): HandoffOwner;
3
11
  export interface HandoffSnapshot {
12
+ readonly owner: HandoffOwner;
4
13
  readonly changes: readonly ChangeRecord[];
5
14
  readonly structuralChanges: readonly StructuralChange[];
6
15
  }
@@ -22,7 +31,7 @@ export declare function handoffStructuralFingerprint(change: StructuralChange):
22
31
  */
23
32
  export declare function verifiedChangeKeys(sentChanges: readonly ChangeRecord[], doc?: Document): Set<string>;
24
33
  /** Captures the exact canonical edits associated with one dispatched prompt. */
25
- export declare function recordAgentDispatch(revision: number, changes: readonly ChangeRecord[], structuralChanges?: readonly StructuralChange[]): void;
34
+ export declare function recordAgentDispatch(revision: number, changes: readonly ChangeRecord[], structuralChanges?: readonly StructuralChange[], owner?: HandoffOwner): void;
26
35
  /** Drops a captured revision when the bridge rejects its dispatch. */
27
36
  export declare function discardAgentDispatch(revision: number): void;
28
37
  /** Returns how many canonical edits were in flight for one dispatch. */
@@ -33,6 +42,7 @@ export declare function getAgentDispatchSize(revision: number): number;
33
42
  * records are preserved.
34
43
  */
35
44
  export declare function verifyAndReconcileHandoff(snapshot: HandoffSnapshot, doc?: Document | null): Promise<number>;
45
+ export declare function documentBelongsToHandoff(doc: Document, owner: HandoffOwner): boolean;
36
46
  /** Reconciles the captured records for one completed connected-agent request. */
37
47
  export declare function verifyAndReconcileAgentDispatch(revision: number): Promise<number>;
38
48
  /** Test/session reset for in-memory dispatch snapshots. */
@@ -1,16 +1,24 @@
1
+ import { draftIdForCard } from "../drafts/store.js";
2
+ import { getCanvasCards } from "../canvas/canvasStore.js";
3
+ import { getRegisteredFrames, getCanvasCardIdForDocument } from "../canvas/projection.js";
4
+ import { applicationTarget, targetFromKey, targetKey } from "../drafts/model.js";
1
5
  import { changeKey, tokenReference } from "../changes/model.js";
2
6
  import { selectorForManagedChange } from "../changes/managedStyleProjection.js";
3
- import { getWorkspaceChanges } from "../changes/workspaceChanges.js";
4
- import { getChangesList, isComponentChange, isTextContentChange, isTokenChange, reconcileVerifiedWorkspaceChanges, } from "../changes/changesLog.js";
7
+ import { getActiveDraftChanges, getDraftChanges, reconcileDraftChanges } from "../changes/draftChanges.js";
8
+ import { isComponentChange, isTextContentChange, isTokenChange, } from "../changes/changesLog.js";
5
9
  import { verifyPreview } from "../projection/managedStylesheet.js";
6
10
  import { resolveRenderedInstance } from "../projection/renderedInstance.js";
7
- import { documentStateKey, getStructuralChanges, } from "../projection/structuralProjection.js";
11
+ import { documentStateKey, } from "../projection/structuralProjection.js";
8
12
  import { resolveTextProjectionTarget, resolveTextProjectionTextNode, } from "../projection/textProjection.js";
9
- import { applyHostWorkspaceProjection, compileWorkspaceProjection, } from "../projection/workspaceProjection.js";
10
- import { isCanvasProjectionRevisionCurrent, projectWorkspaceSnapshotToDocument, } from "../canvas/projection.js";
11
- import { getActiveCanvasDocument } from "../canvas/activeCanvasDocument.js";
12
- import { getSelectedElement } from "../selection/selectionStore.js";
13
+ import { applyHostDraftProjection, compileDraftProjection, } from "../projection/draftProjection.js";
14
+ import { isCanvasProjectionRevisionCurrent, restoreCanonicalFrameProjection, projectDraftToDocument, } from "../canvas/projection.js";
13
15
  import { isEditorShellDocument } from "../runtime/editorShell.js";
16
+ export function captureHandoffOwner(cardId) {
17
+ const draftId = (cardId && draftIdForCard(cardId)) || getActiveDraftChanges().draftId;
18
+ const workspace = getDraftChanges(draftId);
19
+ return { draftId, draftRevision: workspace.revision, target: targetFromKey(draftId) ?? applicationTarget(),
20
+ frameIds: getCanvasCards().filter((card) => draftIdForCard(card.id) === workspace.draftId).map((card) => card.id) };
21
+ }
14
22
  const dispatches = new Map();
15
23
  function stableJsonValue(value) {
16
24
  if (Array.isArray(value))
@@ -142,8 +150,9 @@ export function verifiedChangeKeys(sentChanges, doc = document) {
142
150
  return verified;
143
151
  }
144
152
  /** Captures the exact canonical edits associated with one dispatched prompt. */
145
- export function recordAgentDispatch(revision, changes, structuralChanges = []) {
153
+ export function recordAgentDispatch(revision, changes, structuralChanges = [], owner = captureHandoffOwner()) {
146
154
  dispatches.set(revision, {
155
+ owner: structuredClone(owner),
147
156
  changes: changes.map((change) => structuredClone(change)),
148
157
  structuralChanges: structuralChanges.map((change) => structuredClone(change)),
149
158
  });
@@ -186,32 +195,32 @@ function afterBrowserPaint(doc) {
186
195
  * observable after removing Nudge's own preview. Newer edits and ambiguous
187
196
  * records are preserved.
188
197
  */
189
- export async function verifyAndReconcileHandoff(snapshot, doc = activeVerificationDocument()) {
190
- if (!doc)
198
+ export async function verifyAndReconcileHandoff(snapshot, doc = handoffDocument(snapshot.owner)) {
199
+ if (!doc || !documentBelongsToHandoff(doc, snapshot.owner))
191
200
  return 0;
192
201
  const applyProjection = async (snapshot) => {
193
202
  if (doc === document && !isEditorShellDocument(doc)) {
194
- applyHostWorkspaceProjection(compileWorkspaceProjection(snapshot));
203
+ applyHostDraftProjection(compileDraftProjection(snapshot));
195
204
  return "host";
196
205
  }
197
206
  if (doc === document)
198
207
  return null;
199
- return projectWorkspaceSnapshotToDocument(doc, snapshot);
208
+ return projectDraftToDocument(doc, snapshot);
200
209
  };
201
210
  const sentByKey = new Map(snapshot.changes.map((change) => [changeKey(change), handoffChangeFingerprint(change)]));
202
- const current = getChangesList();
211
+ const current = getDraftChanges(snapshot.owner.draftId).changes;
203
212
  const eligible = current.filter((change) => sentByKey.get(changeKey(change)) === handoffChangeFingerprint(change));
204
213
  const eligibleKeys = new Set(eligible.map(changeKey));
205
214
  const remaining = current.filter((change) => !eligibleKeys.has(changeKey(change)));
206
215
  // The same "still unchanged" rule for structural intent: only canonical
207
216
  // records byte-identical to the dispatched snapshot may be reconciled.
208
217
  const sentStructural = new Map(snapshot.structuralChanges.map((change) => [change.id, handoffStructuralFingerprint(change)]));
209
- const currentStructural = getStructuralChanges();
218
+ const currentStructural = getDraftChanges(snapshot.owner.draftId).structuralChanges;
210
219
  const eligibleStructural = currentStructural.filter((change) => sentStructural.get(change.id) === handoffStructuralFingerprint(change));
211
220
  const eligibleStructuralIds = new Set(eligibleStructural.map((change) => change.id));
212
221
  const remainingStructural = currentStructural.filter((change) => !eligibleStructuralIds.has(change.id));
213
222
  try {
214
- const currentWorkspace = getWorkspaceChanges();
223
+ const currentWorkspace = getDraftChanges(snapshot.owner.draftId);
215
224
  const previewRevision = await applyProjection({
216
225
  revision: currentWorkspace.revision,
217
226
  changes: remaining,
@@ -220,6 +229,8 @@ export async function verifyAndReconcileHandoff(snapshot, doc = activeVerificati
220
229
  if (previewRevision === null)
221
230
  return 0;
222
231
  await afterBrowserPaint(doc);
232
+ if (!documentBelongsToHandoff(doc, snapshot.owner))
233
+ return 0;
223
234
  if (typeof previewRevision === "number"
224
235
  && !isCanvasProjectionRevisionCurrent(doc, previewRevision))
225
236
  return 0;
@@ -228,27 +239,44 @@ export async function verifyAndReconcileHandoff(snapshot, doc = activeVerificati
228
239
  // A user can make another inspector edit while the two-frame verification
229
240
  // window is open. Recheck byte identity immediately before reconciliation
230
241
  // so a newer value at the same key can never be removed.
231
- const currentByKey = new Map(getChangesList().map((change) => [changeKey(change), handoffChangeFingerprint(change)]));
242
+ const currentByKey = new Map(getDraftChanges(snapshot.owner.draftId).changes.map((change) => [changeKey(change), handoffChangeFingerprint(change)]));
232
243
  const stillVerified = new Set([...verified].filter((key) => currentByKey.get(key) === sentByKey.get(key)));
233
- const currentStructuralById = new Map(getStructuralChanges().map((change) => [change.id, handoffStructuralFingerprint(change)]));
244
+ const currentStructuralById = new Map(getDraftChanges(snapshot.owner.draftId).structuralChanges.map((change) => [change.id, handoffStructuralFingerprint(change)]));
234
245
  const stillVerifiedStructural = new Set([...verifiedStructural].filter((id) => currentStructuralById.get(id) === sentStructural.get(id)));
235
246
  if (typeof previewRevision === "number"
236
247
  && !isCanvasProjectionRevisionCurrent(doc, previewRevision))
237
248
  return 0;
238
- return reconcileVerifiedWorkspaceChanges(stillVerified, stillVerifiedStructural);
249
+ if (!documentBelongsToHandoff(doc, snapshot.owner))
250
+ return 0;
251
+ return reconcileDraftChanges(snapshot.owner.draftId, stillVerified, stillVerifiedStructural);
239
252
  }
240
253
  finally {
241
254
  // Reconciliation reapplies the canonical set. If it was unable to write
242
255
  // (for example, a read-only Canvas lease), restore the untouched set here.
243
- const canonicalWorkspace = getWorkspaceChanges();
244
- await applyProjection(canonicalWorkspace);
256
+ if (doc === document)
257
+ await applyProjection(getActiveDraftChanges());
258
+ else
259
+ restoreCanonicalFrameProjection(doc);
245
260
  }
246
261
  }
247
- function activeVerificationDocument() {
248
- const selectedDocument = getSelectedElement()?.domElement.ownerDocument;
249
- if (selectedDocument && selectedDocument !== document)
250
- return selectedDocument;
251
- return getActiveCanvasDocument() ?? (isEditorShellDocument() ? null : document);
262
+ export function documentBelongsToHandoff(doc, owner) {
263
+ if (owner.target.kind === "application"
264
+ && targetKey(applicationTarget(doc.location.href)) !== targetKey(owner.target))
265
+ return false;
266
+ if (doc === document)
267
+ return owner.target.kind === "application" && !isEditorShellDocument(doc);
268
+ const id = getCanvasCardIdForDocument(doc);
269
+ return !!id && draftIdForCard(id) === owner.draftId;
270
+ }
271
+ function handoffDocument(owner) {
272
+ for (const [id, frame] of getRegisteredFrames()) {
273
+ if (draftIdForCard(id) !== owner.draftId)
274
+ continue;
275
+ const doc = frame.contentDocument;
276
+ if (doc && documentBelongsToHandoff(doc, owner))
277
+ return doc;
278
+ }
279
+ return owner.target.kind === "application" && !isEditorShellDocument() ? document : null;
252
280
  }
253
281
  /** Reconciles the captured records for one completed connected-agent request. */
254
282
  export async function verifyAndReconcileAgentDispatch(revision) {
@@ -0,0 +1,13 @@
1
+ import { type ActivityFile } from "../agent/activity.js";
2
+ import { type FrameContent } from "./frameContent.js";
3
+ export interface ActivityAttribution {
4
+ files: readonly ActivityFile[];
5
+ elements: readonly Element[];
6
+ }
7
+ /** Reuses rendered source identities. Iteration provenance cannot target application source. */
8
+ export declare function attributeActivity(content: FrameContent, document: Document, files: readonly ActivityFile[]): ActivityAttribution;
9
+ export declare function AgentActivityOverlay({ cardId, content, iframe }: {
10
+ cardId: string;
11
+ content: FrameContent;
12
+ iframe: HTMLIFrameElement | null;
13
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,111 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const activityStyles = ".canvas-agent-activity {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 12;\n overflow: hidden;\n border-radius: 4px;\n}\n\n.canvas-agent-activity__label {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n position: absolute;\n top: 12px;\n right: 12px;\n max-width: 80%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding: 4px 10px 4px 4px;\n border-radius: 20px;\n background: #242424e8;\n color: #fff;\n font: 12px system-ui;\n box-shadow: 0 2px 12px #0003;\n}\n\n.canvas-agent-activity__label canvas {\n flex: 0 0 auto;\n}\n\n.canvas-agent-activity__label > span {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.canvas-agent-activity__shimmer {\n position: absolute;\n border-radius: 5px;\n background: linear-gradient(110deg, transparent 20%, rgb(212 212 212 / 0.18) 35%, rgb(212 212 212 / 0.35) 50%, rgb(212 212 212 / 0.18) 65%, transparent 80%);\n background-size: 250% 100%;\n animation: nudge-component-shimmer 2.4s ease-in-out infinite;\n}\n\n@keyframes nudge-component-shimmer {\n from { background-position: 150% 0; }\n to { background-position: -150% 0; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .canvas-agent-activity__shimmer {\n animation: none;\n }\n}\n";
3
+ import { useEffect, useState } from "react";
4
+ import { ThinkingOrb } from "thinking-orbs";
5
+ import { useAgentActivity } from "../agent/activity.js";
6
+ import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
7
+ import { parseDataSrc } from "../selection/resolveSelection.js";
8
+ import { targetKey } from "../drafts/model.js";
9
+ import { contentEditTarget } from "./frameContent.js";
10
+ /** Reuses rendered source identities. Iteration provenance cannot target application source. */
11
+ export function attributeActivity(content, document, files) {
12
+ const target = contentEditTarget(content);
13
+ if (target.kind === "html")
14
+ return { files: files.filter((file) => file.file === target.path), elements: [] };
15
+ const matched = new Set();
16
+ const elements = [];
17
+ for (const element of document.querySelectorAll("[data-src]")) {
18
+ const source = parseDataSrc(element.getAttribute("data-src") ?? "");
19
+ if (!source)
20
+ continue;
21
+ for (const file of files) {
22
+ if (source.file.replace(/^\.\//, "") !== file.file)
23
+ continue;
24
+ matched.add(file);
25
+ if (file.operation !== "edit" || (file.componentId && file.componentId !== element.getAttribute("data-cid")))
26
+ continue;
27
+ if (file.line !== undefined && (source.line < file.line || source.line > (file.endLine ?? file.line)))
28
+ continue;
29
+ elements.push(element);
30
+ }
31
+ }
32
+ // Highlight outer matches once when one component contains matching descendants.
33
+ return { files: [...matched], elements: [...new Set(elements)].filter((element, _index, all) => !all.some((parent) => parent !== element && parent.contains(element))) };
34
+ }
35
+ export function AgentActivityOverlay({ cardId, content, iframe }) {
36
+ const activity = useAgentActivity(getNudgeUiRuntimeConfig().projectId);
37
+ const [visual, setVisual] = useState({ files: [], highlights: [] });
38
+ useEffect(() => {
39
+ if (!activity.requestId || !iframe || !activity.files.length) {
40
+ setVisual({ files: [], highlights: [] });
41
+ return;
42
+ }
43
+ let detachDocument = () => { };
44
+ const attachDocument = () => {
45
+ detachDocument();
46
+ let document = null;
47
+ try {
48
+ document = iframe.contentDocument;
49
+ }
50
+ catch {
51
+ document = null;
52
+ }
53
+ if (!document?.defaultView) {
54
+ setVisual({ files: [], highlights: [] });
55
+ return;
56
+ }
57
+ const view = document.defaultView;
58
+ const ownedDocument = document;
59
+ let attribution = attributeActivity(content, ownedDocument, activity.files);
60
+ let frame = null;
61
+ let sourceChanged = false;
62
+ const measure = () => {
63
+ frame = null;
64
+ if (sourceChanged) {
65
+ attribution = attributeActivity(content, ownedDocument, activity.files);
66
+ sourceChanged = false;
67
+ }
68
+ const highlights = attribution.elements.slice(0, 64).map((element) => {
69
+ const rect = element.getBoundingClientRect();
70
+ return { x: rect.left, y: rect.top, width: rect.width, height: rect.height };
71
+ }).filter((rect) => rect.width > 0 && rect.height > 0);
72
+ setVisual((previous) => {
73
+ const sameFiles = previous.files.length === attribution.files.length && previous.files.every((file, index) => file === attribution.files[index]);
74
+ const sameRects = previous.highlights.length === highlights.length && previous.highlights.every((rect, index) => { const next = highlights[index]; return rect.x === next.x && rect.y === next.y && rect.width === next.width && rect.height === next.height; });
75
+ return sameFiles && sameRects ? previous : { files: attribution.files, highlights };
76
+ });
77
+ };
78
+ const schedule = () => { if (frame === null)
79
+ frame = view.requestAnimationFrame(measure); };
80
+ const mutations = new MutationObserver((records) => {
81
+ sourceChanged ||= records.some((record) => record.type === "childList" || record.attributeName === "data-src" || record.attributeName === "data-cid");
82
+ schedule();
83
+ });
84
+ mutations.observe(ownedDocument.documentElement, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ["data-src", "data-cid", "class", "style"] });
85
+ const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(schedule);
86
+ resize?.observe(ownedDocument.documentElement);
87
+ for (const element of attribution.elements.slice(0, 64))
88
+ resize?.observe(element);
89
+ view.addEventListener("scroll", schedule, true);
90
+ view.addEventListener("resize", schedule);
91
+ measure();
92
+ detachDocument = () => {
93
+ mutations.disconnect();
94
+ resize?.disconnect();
95
+ view.removeEventListener("scroll", schedule, true);
96
+ view.removeEventListener("resize", schedule);
97
+ if (frame !== null)
98
+ view.cancelAnimationFrame(frame);
99
+ };
100
+ };
101
+ attachDocument();
102
+ iframe.addEventListener("load", attachDocument);
103
+ return () => { iframe.removeEventListener("load", attachDocument); detachDocument(); };
104
+ }, [activity, content, iframe]);
105
+ const submitted = activity.requestId !== null && activity.targets.includes(cardId)
106
+ && (!activity.target || targetKey(activity.target) === targetKey(contentEditTarget(content)));
107
+ const working = activity.requestId !== null && (submitted || visual.files.length > 0);
108
+ if (!working)
109
+ return null;
110
+ return _jsxs("div", { className: "canvas-agent-activity", "data-test": `canvas-agent-activity-${cardId}`, children: [visual.highlights.map((rect, index) => _jsx("div", { className: "canvas-agent-activity__shimmer", "data-test": "canvas-agent-component-shimmer", style: { left: rect.x, top: rect.y, width: rect.width, height: rect.height } }, index)), _jsxs("span", { className: "canvas-agent-activity__label", role: "status", children: [_jsx(ThinkingOrb, { state: "solving", size: 20, theme: "dark", "aria-hidden": "true" }), _jsx("span", { children: "Agent working\u2026" })] }), _jsx("style", { children: activityStyles })] });
111
+ }
@@ -1,12 +1,19 @@
1
1
  import { type ReactElement } from "react";
2
- import { type CanvasCard, type CanvasPresentation } from "./canvasStore.js";
2
+ import { type CanvasCard } from "./canvasStore.js";
3
+ import { type CanvasPresentation } from "./viewStore.js";
3
4
  import type { InspectorSession } from "../session/sessionFactory.js";
4
5
  interface CanvasCardProps {
5
6
  card: CanvasCard;
6
7
  presentation?: CanvasPresentation;
7
8
  presentationCard?: boolean;
9
+ linkedToActive?: boolean;
8
10
  onShowFocus?: (cardId: string) => void;
11
+ onDuplicate?: (cardId: string) => void;
12
+ onCreateIteration?: (cardId: string, position?: {
13
+ x: number;
14
+ y: number;
15
+ }) => Promise<string>;
9
16
  documentOwner?: InspectorSession;
10
17
  }
11
- export declare function CanvasCard({ card, presentation, presentationCard, onShowFocus, documentOwner }: CanvasCardProps): ReactElement;
18
+ export declare function CanvasCard({ card, presentation, presentationCard, linkedToActive, onShowFocus, onDuplicate, onCreateIteration, documentOwner }: CanvasCardProps): ReactElement;
12
19
  export {};