nudge-ui 0.2.4 → 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.
- package/dist/cli/agentCommand.js +4 -28
- package/dist/client.mjs +863 -213
- package/dist/hosts/next/wrapper.js +1 -7
- package/dist/hosts/projectBridge.js +3 -17
- package/dist/inspector/agent/McpConnectionDialog.js +7 -3
- package/dist/inspector/agent/activity.d.ts +1 -1
- package/dist/inspector/agent/activity.js +3 -2
- package/dist/inspector/agent/client.d.ts +2 -2
- package/dist/inspector/agent/client.js +28 -29
- package/dist/inspector/agent/connectionStatus.d.ts +3 -1
- package/dist/inspector/agent/connectionStatus.js +25 -0
- package/dist/inspector/agent/httpTransport.js +31 -147
- package/dist/inspector/agent/protocol.d.ts +1 -1
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +1 -1
- package/dist/inspector/agent/verification.js +7 -4
- package/dist/inspector/boot.d.ts +3 -0
- package/dist/inspector/boot.js +297 -0
- package/dist/inspector/canvas/AgentActivityOverlay.d.ts +2 -1
- package/dist/inspector/canvas/AgentActivityOverlay.js +6 -3
- package/dist/inspector/canvas/CanvasCard.js +21 -12
- package/dist/inspector/canvas/CanvasElementOverlay.js +82 -127
- package/dist/inspector/canvas/CanvasToolbar.js +2 -1
- package/dist/inspector/canvas/CanvasWorkspace.js +74 -97
- package/dist/inspector/canvas/LockedWorkspaceNotice.d.ts +3 -2
- package/dist/inspector/canvas/LockedWorkspaceNotice.js +10 -6
- package/dist/inspector/canvas/PageCard.d.ts +10 -0
- package/dist/inspector/canvas/PageCard.js +51 -0
- package/dist/inspector/canvas/SketchToolOptions.d.ts +5 -0
- package/dist/inspector/canvas/SketchToolOptions.js +86 -0
- package/dist/inspector/canvas/StaleChangeIndicator.d.ts +1 -1
- package/dist/inspector/canvas/StaleChangeIndicator.js +1 -1
- package/dist/inspector/canvas/ToolOptionsDrawer.d.ts +21 -0
- package/dist/inspector/canvas/ToolOptionsDrawer.js +77 -0
- package/dist/inspector/canvas/activeCanvasDocument.d.ts +3 -2
- package/dist/inspector/canvas/assets/eraser.svg +28 -0
- package/dist/inspector/canvas/assets/pen.svg +25 -0
- package/dist/inspector/canvas/canvasFrame.d.ts +16 -0
- package/dist/inspector/canvas/canvasFrame.js +10 -0
- package/dist/inspector/canvas/canvasGestures.d.ts +0 -1
- package/dist/inspector/canvas/canvasGestures.js +0 -6
- package/dist/inspector/canvas/canvasStore.d.ts +6 -0
- package/dist/inspector/canvas/canvasStore.js +36 -1
- package/dist/inspector/canvas/frameConnection.d.ts +48 -0
- package/dist/inspector/canvas/frameConnection.js +73 -0
- package/dist/inspector/canvas/frameProtocol.d.ts +18 -1
- package/dist/inspector/canvas/frameProtocol.js +36 -0
- package/dist/inspector/canvas/pageSurface.d.ts +11 -0
- package/dist/inspector/canvas/pageSurface.js +34 -0
- package/dist/inspector/canvas/projection.d.ts +19 -9
- package/dist/inspector/canvas/projection.js +58 -31
- package/dist/inspector/canvas/rendererBootstrap.js +4 -1
- package/dist/inspector/canvas/rendererElementSelector.js +9 -1
- package/dist/inspector/canvas/rendererMessageRouter.d.ts +4 -5
- package/dist/inspector/canvas/rendererMessageRouter.js +12 -16
- package/dist/inspector/canvas/rendererSelectionProxy.d.ts +7 -1
- package/dist/inspector/canvas/rendererSelectionProxy.js +8 -36
- package/dist/inspector/canvas/rendererStylesheet.js +15 -0
- package/dist/inspector/canvas/sessionStore.d.ts +2 -2
- package/dist/inspector/canvas/sessionStore.js +12 -9
- package/dist/inspector/canvas/staleChangeDetector.d.ts +1 -1
- package/dist/inspector/canvas/staleChangeDetector.js +10 -22
- package/dist/inspector/changes/codecs.d.ts +1 -0
- package/dist/inspector/changes/codecs.js +20 -5
- package/dist/inspector/changes/draftPreview.d.ts +12 -0
- package/dist/inspector/changes/draftPreview.js +133 -0
- package/dist/inspector/changes/editModel.d.ts +8 -0
- package/dist/inspector/changes/editModel.js +8 -2
- package/dist/inspector/changes/managedStyleProjection.js +2 -1
- package/dist/inspector/changes/previewDiagnostics.js +1 -1
- package/dist/inspector/changes/types.d.ts +11 -1
- package/dist/inspector/comments/CommentsOverlay.js +18 -16
- package/dist/inspector/comments/store.js +3 -2
- package/dist/inspector/comments/verification.js +1 -1
- package/dist/inspector/componentSemantics/ComponentPropsSection.js +2 -1
- package/dist/inspector/componentSemantics/changeAction.js +1 -1
- package/dist/inspector/componentSemantics/textBinding.d.ts +1 -2
- package/dist/inspector/componentSemantics/textBinding.js +4 -45
- package/dist/inspector/drafts/draftStore.d.ts +109 -0
- package/dist/inspector/drafts/draftStore.js +451 -0
- package/dist/inspector/drafts/model.d.ts +9 -1
- package/dist/inspector/drafts/model.js +5 -1
- package/dist/inspector/drafts/store.d.ts +53 -15
- package/dist/inspector/drafts/store.js +143 -169
- package/dist/inspector/index.d.ts +2 -4
- package/dist/inspector/index.js +2 -264
- package/dist/inspector/inline-text/inlineTextEditor.d.ts +1 -1
- package/dist/inspector/inline-text/inlineTextEditor.js +1 -2
- package/dist/inspector/inline-text/textEditChange.d.ts +1 -1
- package/dist/inspector/inspection/bridge.d.ts +1 -1
- package/dist/inspector/inspection/bridge.js +2 -1
- package/dist/inspector/inspection/browserCssInspection.d.ts +8 -0
- package/dist/inspector/inspection/browserCssInspection.js +28 -6
- package/dist/inspector/inspection/inspectionSnapshot.d.ts +6 -0
- package/dist/inspector/inspection/inspectionSnapshot.js +10 -0
- package/dist/inspector/inspection/performanceDiagnostics.d.ts +18 -0
- package/dist/inspector/inspection/performanceDiagnostics.js +31 -0
- package/dist/inspector/inspection/useBrowserCssInspection.js +17 -38
- package/dist/inspector/iterations/capture.d.ts +2 -1
- package/dist/inspector/iterations/client.d.ts +2 -1
- package/dist/inspector/iterations/coordinator.d.ts +4 -3
- package/dist/inspector/iterations/coordinator.js +5 -3
- package/dist/inspector/iterations/prompt.js +9 -8
- package/dist/inspector/overlay/interactionStyles.js +17 -0
- package/dist/inspector/pageInspector.d.ts +42 -0
- package/dist/inspector/pageInspector.js +342 -0
- package/dist/inspector/projection/draftProjection.d.ts +10 -2
- package/dist/inspector/projection/draftProjection.js +9 -1
- package/dist/inspector/projection/managedStylesheet.js +24 -4
- package/dist/inspector/projection/renderedInstance.js +7 -1
- package/dist/inspector/projection/structuralProjection.d.ts +0 -9
- package/dist/inspector/projection/structuralProjection.js +14 -44
- package/dist/inspector/projection/textProjection.d.ts +8 -2
- package/dist/inspector/projection/textProjection.js +21 -13
- package/dist/inspector/prompt/clipboardHandoff.d.ts +9 -0
- package/dist/inspector/prompt/clipboardHandoff.js +42 -16
- package/dist/inspector/prompt/generatePrompt.d.ts +1 -1
- package/dist/inspector/prompt/generatePrompt.js +243 -147
- package/dist/inspector/prompt/promptDocument.d.ts +3 -0
- package/dist/inspector/prompt/promptDocument.js +8 -0
- package/dist/inspector/prompt/promptSettings.js +7 -5
- package/dist/inspector/runtime/inspectorStorage.d.ts +17 -0
- package/dist/inspector/runtime/inspectorStorage.js +42 -0
- package/dist/inspector/runtime/ownedStylesheets.d.ts +20 -0
- package/dist/inspector/runtime/ownedStylesheets.js +72 -0
- package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
- package/dist/inspector/runtime/runtimeConfig.js +10 -1
- package/dist/inspector/runtime/runtimeIdentityClaims.d.ts +29 -0
- package/dist/inspector/runtime/runtimeIdentityClaims.js +188 -0
- package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +15 -0
- package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +113 -29
- package/dist/inspector/selection/editScope.d.ts +1 -0
- package/dist/inspector/selection/editScope.js +13 -2
- package/dist/inspector/shell/AgentStatusButton.js +2 -2
- package/dist/inspector/shell/AppShell.js +6 -2
- package/dist/inspector/shell/ChangesLog.js +27 -9
- package/dist/inspector/shell/CopyPromptButton.js +60 -54
- package/dist/inspector/shell/EmptyState.js +3 -3
- package/dist/inspector/shell/InspectorShell.d.ts +0 -3
- package/dist/inspector/shell/InspectorShell.js +21 -13
- package/dist/inspector/shell/PeekOriginalButton.js +3 -3
- package/dist/inspector/shell/interactionStatePreview.d.ts +9 -0
- package/dist/inspector/shell/interactionStatePreview.js +112 -0
- package/dist/inspector/shell/originalPreview.d.ts +3 -2
- package/dist/inspector/shell/originalPreview.js +10 -37
- package/dist/inspector/shell/stateValue.js +2 -3
- package/dist/inspector/sketch/SketchEditor.js +5 -4
- package/dist/inspector/sketch/SketchFrameOverlay.d.ts +2 -1
- package/dist/inspector/sketch/SketchFrameOverlay.js +5 -4
- package/dist/inspector/sketch/SketchOverlay.d.ts +3 -5
- package/dist/inspector/sketch/SketchOverlay.js +139 -263
- package/dist/inspector/sketch/SketchPromptPanel.d.ts +1 -1
- package/dist/inspector/sketch/SketchPromptPanel.js +8 -1
- package/dist/inspector/sketch/SketchThumbnail.d.ts +5 -0
- package/dist/inspector/sketch/SketchThumbnail.js +18 -0
- package/dist/inspector/sketch/SketchWorkspace.d.ts +1 -2
- package/dist/inspector/sketch/SketchWorkspace.js +69 -34
- package/dist/inspector/sketch/capture.js +19 -3
- package/dist/inspector/sketch/copySketch.d.ts +10 -0
- package/dist/inspector/sketch/copySketch.js +52 -0
- package/dist/inspector/sketch/drawingTools.d.ts +17 -0
- package/dist/inspector/sketch/drawingTools.js +47 -0
- package/dist/inspector/sketch/frameHeading.d.ts +9 -0
- package/dist/inspector/sketch/frameHeading.js +30 -0
- package/dist/inspector/sketch/freehand.js +3 -3
- package/dist/inspector/sketch/geometry.d.ts +6 -0
- package/dist/inspector/sketch/geometry.js +19 -0
- package/dist/inspector/sketch/history.d.ts +30 -0
- package/dist/inspector/sketch/history.js +58 -0
- package/dist/inspector/sketch/interaction.d.ts +1 -3
- package/dist/inspector/sketch/interaction.js +6 -9
- package/dist/inspector/sketch/model.d.ts +35 -1
- package/dist/inspector/sketch/model.js +116 -61
- package/dist/inspector/sketch/persistence.d.ts +14 -0
- package/dist/inspector/sketch/persistence.js +63 -7
- package/dist/inspector/sketch/raster.d.ts +6 -2
- package/dist/inspector/sketch/raster.js +43 -17
- package/dist/inspector/sketch/store.d.ts +1 -1
- package/dist/inspector/sketch/store.js +1 -1
- package/dist/inspector/sketch/videoFrames.d.ts +6 -0
- package/dist/inspector/sketch/videoFrames.js +81 -0
- package/dist/inspector/styleEditors/BackgroundEditor.js +2 -1
- package/dist/inspector/styleEditors/BorderEditor.js +30 -130
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +8 -3
- package/dist/inspector/styleEditors/ImageBackgroundEditor.js +1 -1
- package/dist/inspector/styleEditors/LayoutSection.js +2 -2
- package/dist/inspector/styleEditors/borderModel.d.ts +42 -0
- package/dist/inspector/styleEditors/borderModel.js +114 -0
- package/dist/inspector/styleEditors/layoutValue.js +2 -3
- package/dist/inspector/tokens/TokenField.js +34 -3
- package/dist/inspector/tokens/TokensPanel.js +2 -1
- package/dist/inspector/tokens/editActions.d.ts +3 -3
- package/dist/inspector/tokens/editActions.js +9 -3
- package/dist/inspector/tokens/resolution/containerQueryEvaluator.d.ts +15 -0
- package/dist/inspector/tokens/resolution/containerQueryEvaluator.js +86 -0
- package/dist/inspector/tokens/resolution/cssomCollector.js +44 -9
- package/dist/inspector/tokens/resolution/nestedSelectors.d.ts +6 -0
- package/dist/inspector/tokens/resolution/nestedSelectors.js +67 -0
- package/dist/inspector/tokens/resolution/ruleMatching.js +23 -4
- package/dist/inspector/tokens/resolution.d.ts +6 -3
- package/dist/inspector/tokens/resolution.js +91 -112
- package/dist/inspector/tokens/tokenEdits.d.ts +1 -1
- package/dist/inspector/tokens/tokenEdits.js +1 -1
- package/dist/inspector/ui/InlineStyleWarning.js +2 -2
- package/dist/inspector/ui/InspectorStyle.d.ts +8 -0
- package/dist/inspector/ui/InspectorStyle.js +26 -0
- package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
- package/dist/inspector/ui/PopoverListbox.js +3 -3
- package/dist/inspector/ui/Toast.d.ts +14 -0
- package/dist/inspector/ui/Toast.js +30 -0
- package/dist/inspector/ui/assets/canvasIllustration.d.ts +2 -0
- package/dist/inspector/ui/assets/canvasIllustration.js +21 -0
- package/dist/inspector/ui/assets/gridIllustration.d.ts +2 -0
- package/dist/inspector/ui/assets/{grid.svg → gridIllustration.js} +3 -2
- package/dist/inspector/ui/customCursors.d.ts +5 -0
- package/dist/inspector/ui/customCursors.js +32 -6
- package/dist/inspector/ui/styles.js +12 -10
- package/dist/inspector/workspace/commands.js +1 -2
- package/dist/inspector/workspace/controller.js +1 -2
- package/dist/inspector/workspace/handoff.js +3 -2
- package/dist/inspector/workspace/sentItems.d.ts +3 -6
- package/dist/inspector/workspace/sentItems.js +6 -24
- package/dist/inspector/workspace/timeline.d.ts +24 -10
- package/dist/inspector/workspace/timeline.js +118 -96
- package/dist/internal/agent-protocol.d.ts +50 -13
- package/dist/internal/agent-protocol.js +145 -19
- package/dist/nudge-ui.mjs +81 -65
- package/dist/project/mcpPackage.d.ts +8 -0
- package/dist/project/mcpPackage.js +60 -0
- package/package.json +12 -2
- package/dist/inspector/canvas/measurementProjection.d.ts +0 -8
- package/dist/inspector/canvas/measurementProjection.js +0 -16
- package/dist/inspector/changes/changesLog.d.ts +0 -49
- package/dist/inspector/changes/changesLog.js +0 -255
- package/dist/inspector/changes/draftChanges.d.ts +0 -58
- package/dist/inspector/changes/draftChanges.js +0 -304
- package/dist/inspector/conformance/projection.d.ts +0 -2
- package/dist/inspector/conformance/projection.js +0 -3
- package/dist/inspector/inline-text/textChangeBoundary.d.ts +0 -6
- package/dist/inspector/inline-text/textChangeBoundary.js +0 -1
- package/dist/inspector/overlay/InspectorOverlay.d.ts +0 -5
- package/dist/inspector/overlay/InspectorOverlay.js +0 -332
- package/dist/inspector/overlay/elementSelector.d.ts +0 -1
- package/dist/inspector/overlay/elementSelector.js +0 -111
- package/dist/inspector/sketch/SketchChanges.d.ts +0 -2
- package/dist/inspector/sketch/SketchChanges.js +0 -72
- package/dist/inspector/sketch/SketchEntryButton.d.ts +0 -4
- package/dist/inspector/sketch/SketchEntryButton.js +0 -11
- package/dist/inspector/sketch/SketchLayersPanel.d.ts +0 -2
- package/dist/inspector/sketch/SketchLayersPanel.js +0 -71
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AGENT_PROTOCOL_VERSION,
|
|
1
|
+
import { AGENT_PROTOCOL_VERSION, decodeAgentStatusSnapshot, decodeBridgeEvent, decodePairingResponse, decodePromptDispatchResponse, } 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);
|
|
@@ -27,8 +27,7 @@ function configuredEndpointInDocument(doc) {
|
|
|
27
27
|
const target = doc.defaultView;
|
|
28
28
|
if (!target)
|
|
29
29
|
return undefined;
|
|
30
|
-
const globalConfig = endpointValue(target.__NUDGE_UI_AGENT_BRIDGE__)
|
|
31
|
-
?? endpointValue(target.__NUDGE_UI_AGENT__);
|
|
30
|
+
const globalConfig = endpointValue(target.__NUDGE_UI_AGENT_BRIDGE__);
|
|
32
31
|
if (globalConfig)
|
|
33
32
|
return globalConfig;
|
|
34
33
|
const meta = doc.querySelector('meta[name="nudge-ui-agent-bridge"]');
|
|
@@ -75,12 +74,12 @@ function safeUrl(value, origin) {
|
|
|
75
74
|
return null;
|
|
76
75
|
}
|
|
77
76
|
}
|
|
78
|
-
|
|
77
|
+
/** Null when the host published no endpoint; the browser never guesses a bridge port. */
|
|
78
|
+
function endpointUrl(config, key, fallbackPath, origin) {
|
|
79
79
|
const explicit = config[key];
|
|
80
80
|
if (explicit && key !== "baseUrl")
|
|
81
81
|
return safeUrl(explicit, origin);
|
|
82
|
-
const
|
|
83
|
-
const base = safeUrl(baseValue, origin);
|
|
82
|
+
const base = config.baseUrl ? safeUrl(config.baseUrl, origin) : null;
|
|
84
83
|
if (!base)
|
|
85
84
|
return null;
|
|
86
85
|
base.pathname = `${base.pathname.replace(/\/$/, "")}${fallbackPath}`;
|
|
@@ -123,83 +122,6 @@ async function readJson(response) {
|
|
|
123
122
|
}
|
|
124
123
|
return isRecord(payload) ? payload : {};
|
|
125
124
|
}
|
|
126
|
-
function statusPayload(value) {
|
|
127
|
-
if (!isRecord(value))
|
|
128
|
-
return null;
|
|
129
|
-
const status = isRecord(value.status) ? value.status : value;
|
|
130
|
-
if (typeof status.projectId !== "string"
|
|
131
|
-
|| (status.connection !== "offline"
|
|
132
|
-
&& status.connection !== "listening"
|
|
133
|
-
&& status.connection !== "paired"
|
|
134
|
-
&& status.connection !== "working")
|
|
135
|
-
|| typeof status.listenerActive !== "boolean"
|
|
136
|
-
|| typeof status.paired !== "boolean")
|
|
137
|
-
return null;
|
|
138
|
-
if (status.protocolVersion !== undefined && status.protocolVersion !== AGENT_PROTOCOL_VERSION)
|
|
139
|
-
return null;
|
|
140
|
-
const rawRequest = status.request;
|
|
141
|
-
let request = null;
|
|
142
|
-
if (rawRequest !== null && rawRequest !== undefined) {
|
|
143
|
-
if (!isRecord(rawRequest)
|
|
144
|
-
|| (rawRequest.status !== "working"
|
|
145
|
-
&& rawRequest.status !== "completed"
|
|
146
|
-
&& rawRequest.status !== "failed"
|
|
147
|
-
&& rawRequest.status !== "interrupted"))
|
|
148
|
-
return null;
|
|
149
|
-
const requestCandidate = {
|
|
150
|
-
requestId: rawRequest.requestId,
|
|
151
|
-
projectId: rawRequest.projectId,
|
|
152
|
-
prompt: rawRequest.prompt,
|
|
153
|
-
...(typeof rawRequest.changeRevision === "number" ? { changeRevision: rawRequest.changeRevision } : {}),
|
|
154
|
-
...(rawRequest.clientDispatchId === undefined ? {} : { clientDispatchId: rawRequest.clientDispatchId }),
|
|
155
|
-
...(rawRequest.sketches === undefined ? {} : { sketches: rawRequest.sketches }),
|
|
156
|
-
};
|
|
157
|
-
if (!isAgentPromptRequest(requestCandidate))
|
|
158
|
-
return null;
|
|
159
|
-
request = {
|
|
160
|
-
...requestCandidate,
|
|
161
|
-
status: rawRequest.status,
|
|
162
|
-
...(typeof rawRequest.summary === "string" ? { summary: rawRequest.summary } : {}),
|
|
163
|
-
...(typeof rawRequest.error === "string" ? { error: rawRequest.error } : {}),
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
return {
|
|
167
|
-
protocolVersion: AGENT_PROTOCOL_VERSION,
|
|
168
|
-
projectId: status.projectId,
|
|
169
|
-
connection: status.connection,
|
|
170
|
-
listenerActive: status.listenerActive,
|
|
171
|
-
...(typeof status.agentClientName === "string" ? { agentClientName: status.agentClientName.slice(0, 120) } : {}),
|
|
172
|
-
paired: status.paired,
|
|
173
|
-
request,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
function eventPayload(value) {
|
|
177
|
-
if (!isRecord(value))
|
|
178
|
-
return null;
|
|
179
|
-
const envelope = value;
|
|
180
|
-
const event = isRecord(envelope.event) ? envelope.event : value;
|
|
181
|
-
const type = stringValue(event.type);
|
|
182
|
-
if (type === "status") {
|
|
183
|
-
const status = statusPayload(event.status);
|
|
184
|
-
return status ? { type: "status", status } : null;
|
|
185
|
-
}
|
|
186
|
-
if (type === "connected") {
|
|
187
|
-
const status = statusPayload(event.status);
|
|
188
|
-
return status ? { type: "connected", status } : null;
|
|
189
|
-
}
|
|
190
|
-
if (type === "disconnected") {
|
|
191
|
-
return { type: "disconnected", ...(stringValue(event.reason) ? { reason: stringValue(event.reason) } : {}) };
|
|
192
|
-
}
|
|
193
|
-
if (type === "activity" && isAgentActivity(event.activity))
|
|
194
|
-
return { type: "activity", activity: event.activity };
|
|
195
|
-
if (type === "canvas-command" && isRecord(event.command)) {
|
|
196
|
-
// The Canvas controller owns command validation. Preserve the shared
|
|
197
|
-
// shape here so the parent stage can consume this event without a second
|
|
198
|
-
// protocol vocabulary.
|
|
199
|
-
return { type: "canvas-command", command: event.command };
|
|
200
|
-
}
|
|
201
|
-
return null;
|
|
202
|
-
}
|
|
203
125
|
function eventData(event) {
|
|
204
126
|
if (typeof event.data !== "string")
|
|
205
127
|
return event.data;
|
|
@@ -223,7 +145,7 @@ export class HttpAgentBridgeTransport {
|
|
|
223
145
|
this.config = config;
|
|
224
146
|
}
|
|
225
147
|
async discover(request, signal) {
|
|
226
|
-
const url = endpointUrl(this.config,
|
|
148
|
+
const url = endpointUrl(this.config, "healthUrl", "/health", pageOrigin());
|
|
227
149
|
if (!url || typeof fetch !== "function")
|
|
228
150
|
return null;
|
|
229
151
|
const response = await fetch(withQuery(url, {
|
|
@@ -238,10 +160,10 @@ export class HttpAgentBridgeTransport {
|
|
|
238
160
|
|| payload.projectId !== request.projectId
|
|
239
161
|
|| (payload.origin !== undefined && payload.origin !== null && payload.origin !== request.origin))
|
|
240
162
|
return null;
|
|
241
|
-
return
|
|
163
|
+
return decodeAgentStatusSnapshot(payload.status);
|
|
242
164
|
}
|
|
243
165
|
async pair(request, signal) {
|
|
244
|
-
const url = endpointUrl(this.config,
|
|
166
|
+
const url = endpointUrl(this.config, "pairUrl", "/pair", pageOrigin());
|
|
245
167
|
if (!url || typeof fetch !== "function")
|
|
246
168
|
throw new Error("Agent bridge is unavailable.");
|
|
247
169
|
const response = await fetch(url, {
|
|
@@ -250,26 +172,13 @@ export class HttpAgentBridgeTransport {
|
|
|
250
172
|
body: JSON.stringify(request),
|
|
251
173
|
signal,
|
|
252
174
|
});
|
|
253
|
-
const
|
|
254
|
-
if (
|
|
255
|
-
|| payload.projectId !== request.projectId
|
|
256
|
-
|| payload.origin !== request.origin
|
|
257
|
-
|| typeof payload.sessionToken !== "string") {
|
|
175
|
+
const pairing = decodePairingResponse(await readJson(response), request);
|
|
176
|
+
if (!pairing)
|
|
258
177
|
throw new Error("Agent bridge returned an invalid pairing response.");
|
|
259
|
-
|
|
260
|
-
const status = statusPayload(payload.status);
|
|
261
|
-
if (!status)
|
|
262
|
-
throw new Error("Agent bridge returned an invalid status.");
|
|
263
|
-
return {
|
|
264
|
-
protocolVersion: AGENT_PROTOCOL_VERSION,
|
|
265
|
-
projectId: request.projectId,
|
|
266
|
-
origin: request.origin,
|
|
267
|
-
sessionToken: payload.sessionToken,
|
|
268
|
-
status,
|
|
269
|
-
};
|
|
178
|
+
return pairing;
|
|
270
179
|
}
|
|
271
180
|
async takeOver(request, signal) {
|
|
272
|
-
const url = endpointUrl(this.config,
|
|
181
|
+
const url = endpointUrl(this.config, "takeoverUrl", "/takeover", pageOrigin());
|
|
273
182
|
if (!url || typeof fetch !== "function")
|
|
274
183
|
throw new Error("Agent bridge is unavailable.");
|
|
275
184
|
const response = await fetch(url, {
|
|
@@ -278,42 +187,26 @@ export class HttpAgentBridgeTransport {
|
|
|
278
187
|
body: JSON.stringify(request),
|
|
279
188
|
signal,
|
|
280
189
|
});
|
|
281
|
-
const
|
|
282
|
-
if (
|
|
283
|
-
|| payload.projectId !== request.projectId
|
|
284
|
-
|| payload.origin !== request.origin
|
|
285
|
-
|| typeof payload.sessionToken !== "string") {
|
|
190
|
+
const pairing = decodePairingResponse(await readJson(response), request);
|
|
191
|
+
if (!pairing)
|
|
286
192
|
throw new Error("Agent bridge returned an invalid takeover response.");
|
|
287
|
-
|
|
288
|
-
const status = statusPayload(payload.status);
|
|
289
|
-
if (!status)
|
|
290
|
-
throw new Error("Agent bridge returned an invalid status.");
|
|
291
|
-
return {
|
|
292
|
-
protocolVersion: AGENT_PROTOCOL_VERSION,
|
|
293
|
-
projectId: request.projectId,
|
|
294
|
-
origin: request.origin,
|
|
295
|
-
sessionToken: payload.sessionToken,
|
|
296
|
-
status,
|
|
297
|
-
};
|
|
193
|
+
return pairing;
|
|
298
194
|
}
|
|
299
195
|
async restore(request, signal) {
|
|
300
|
-
const url = endpointUrl(this.config,
|
|
196
|
+
const url = endpointUrl(this.config, "statusUrl", "/status", pageOrigin());
|
|
301
197
|
if (!url || typeof fetch !== "function")
|
|
302
198
|
return null;
|
|
303
199
|
const response = await fetch(withQuery(url, {
|
|
304
200
|
projectId: request.projectId,
|
|
305
201
|
sessionToken: request.sessionToken,
|
|
306
202
|
}), { method: "GET", headers: headers(), signal });
|
|
307
|
-
const
|
|
308
|
-
if (
|
|
309
|
-
return null;
|
|
310
|
-
const status = statusPayload(payload);
|
|
311
|
-
if (!status || !status.paired)
|
|
203
|
+
const status = decodeAgentStatusSnapshot(await readJson(response));
|
|
204
|
+
if (!status || status.projectId !== request.projectId || !status.paired)
|
|
312
205
|
return null;
|
|
313
206
|
return status;
|
|
314
207
|
}
|
|
315
208
|
openEvents(request, handlers) {
|
|
316
|
-
const url = endpointUrl(this.config,
|
|
209
|
+
const url = endpointUrl(this.config, "eventsUrl", "/events", pageOrigin());
|
|
317
210
|
if (!url || typeof EventSource !== "function") {
|
|
318
211
|
queueMicrotask(() => handlers.onDisconnect("Agent event transport is unavailable."));
|
|
319
212
|
return { close: () => undefined };
|
|
@@ -325,10 +218,13 @@ export class HttpAgentBridgeTransport {
|
|
|
325
218
|
const source = new EventSource(eventUrl.href);
|
|
326
219
|
let closed = false;
|
|
327
220
|
const handleMessage = (event) => {
|
|
328
|
-
const
|
|
329
|
-
if (isRecord(
|
|
221
|
+
const envelope = eventData(event);
|
|
222
|
+
if (!isRecord(envelope)
|
|
223
|
+
|| envelope.protocolVersion !== AGENT_PROTOCOL_VERSION
|
|
224
|
+
|| envelope.projectId !== request.projectId
|
|
225
|
+
|| envelope.sessionToken !== request.sessionToken)
|
|
330
226
|
return;
|
|
331
|
-
const parsed =
|
|
227
|
+
const parsed = decodeBridgeEvent(envelope.event);
|
|
332
228
|
if (parsed)
|
|
333
229
|
handlers.onEvent(parsed);
|
|
334
230
|
};
|
|
@@ -355,7 +251,7 @@ export class HttpAgentBridgeTransport {
|
|
|
355
251
|
};
|
|
356
252
|
}
|
|
357
253
|
async dispatch(request, signal) {
|
|
358
|
-
const url = endpointUrl(this.config,
|
|
254
|
+
const url = endpointUrl(this.config, "promptUrl", "/prompt", pageOrigin());
|
|
359
255
|
if (!url || typeof fetch !== "function")
|
|
360
256
|
throw new Error("Agent bridge is unavailable.");
|
|
361
257
|
const response = await fetch(url, {
|
|
@@ -364,25 +260,13 @@ export class HttpAgentBridgeTransport {
|
|
|
364
260
|
body: JSON.stringify(request),
|
|
365
261
|
signal,
|
|
366
262
|
});
|
|
367
|
-
const
|
|
368
|
-
if (!
|
|
263
|
+
const dispatched = decodePromptDispatchResponse(await readJson(response), request.projectId);
|
|
264
|
+
if (!dispatched)
|
|
369
265
|
throw new Error("Agent bridge returned an invalid prompt response.");
|
|
370
|
-
|
|
371
|
-
const requestCandidate = {
|
|
372
|
-
requestId: payload.request.requestId,
|
|
373
|
-
projectId: payload.request.projectId,
|
|
374
|
-
prompt: payload.request.prompt,
|
|
375
|
-
...(typeof payload.request.changeRevision === "number" ? { changeRevision: payload.request.changeRevision } : {}),
|
|
376
|
-
...(payload.request.clientDispatchId === undefined ? {} : { clientDispatchId: payload.request.clientDispatchId }),
|
|
377
|
-
...(payload.request.sketches === undefined ? {} : { sketches: payload.request.sketches }),
|
|
378
|
-
};
|
|
379
|
-
if (!isAgentPromptRequest(requestCandidate) || requestCandidate.projectId !== request.projectId) {
|
|
380
|
-
throw new Error("Agent bridge returned an invalid prompt response.");
|
|
381
|
-
}
|
|
382
|
-
return { request: requestCandidate, status: "working" };
|
|
266
|
+
return dispatched;
|
|
383
267
|
}
|
|
384
268
|
async disconnect(request, signal) {
|
|
385
|
-
const url = endpointUrl(this.config,
|
|
269
|
+
const url = endpointUrl(this.config, "disconnectUrl", "/disconnect", pageOrigin());
|
|
386
270
|
if (!url || typeof fetch !== "function")
|
|
387
271
|
return;
|
|
388
272
|
await fetch(url, {
|
|
@@ -393,7 +277,7 @@ export class HttpAgentBridgeTransport {
|
|
|
393
277
|
});
|
|
394
278
|
}
|
|
395
279
|
async acknowledgeCanvasCommand(request, signal) {
|
|
396
|
-
const url = endpointUrl(this.config,
|
|
280
|
+
const url = endpointUrl(this.config, "canvasAckUrl", "/canvas/ack", pageOrigin());
|
|
397
281
|
if (!url || typeof fetch !== "function")
|
|
398
282
|
return;
|
|
399
283
|
await fetch(url, {
|
|
@@ -7,7 +7,7 @@ import type { AgentActivity, AgentStatusSnapshot, CanvasCommand, CanvasCommandAc
|
|
|
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,
|
|
10
|
+
export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, CANVAS_COMMAND_TYPES, canonicalOrigin, decodeAgentStatusSnapshot, decodeBridgeEvent, decodePairingResponse, decodePromptDispatchResponse, deriveConnectionState, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchAnnotation, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAgentActivity, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "../../internal/agent-protocol.js";
|
|
11
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;
|
|
@@ -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,
|
|
9
|
+
export { AGENT_PROTOCOL_LIMITS, AGENT_PROTOCOL_VERSION, CANVAS_COMMAND_TYPES, canonicalOrigin, decodeAgentStatusSnapshot, decodeBridgeEvent, decodePairingResponse, decodePromptDispatchResponse, deriveConnectionState, isAgentPromptRequest, isAgentSketchAttachment, isAgentSketchAnnotation, isAgentSketchCaptureMetadata, isAgentSketchMetadata, isAgentStatusUpdate, isAgentActivity, isAllowedOrigin, isCanvasCommand, isCanvasGroup, isCanvasState, isCanonicalOrigin, isProjectIdentity, isSameOriginRoute, protocolError, validateSketchAttachments, validateRoutes, } from "../../internal/agent-protocol.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DraftTarget } from "../drafts/model.js";
|
|
2
|
-
import { type ChangeRecord } from "../changes/
|
|
2
|
+
import { type ChangeRecord } from "../changes/types.js";
|
|
3
3
|
import { type StructuralChange } from "../projection/structuralProjection.js";
|
|
4
4
|
export interface HandoffOwner {
|
|
5
5
|
readonly draftId: string;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { draftIdForCard } from "../drafts/store.js";
|
|
1
|
+
import { draftIdForCard, getActiveDraftChanges, getDraftChanges, reconcileDraftChanges } from "../drafts/store.js";
|
|
2
2
|
import { getCanvasCards } from "../canvas/canvasStore.js";
|
|
3
3
|
import { getRegisteredFrames, getCanvasCardIdForDocument } from "../canvas/projection.js";
|
|
4
4
|
import { applicationTarget, targetFromKey, targetKey } from "../drafts/model.js";
|
|
5
5
|
import { changeKey, tokenReference } from "../changes/model.js";
|
|
6
6
|
import { selectorForManagedChange } from "../changes/managedStyleProjection.js";
|
|
7
|
-
import {
|
|
8
|
-
import { isComponentChange, isTextContentChange, isTokenChange, } from "../changes/changesLog.js";
|
|
7
|
+
import { isComponentChange, isTextContentChange, isTokenChange, } from "../changes/types.js";
|
|
9
8
|
import { verifyPreview } from "../projection/managedStylesheet.js";
|
|
10
9
|
import { resolveMovedRenderedInstance } from "../projection/renderedInstance.js";
|
|
11
10
|
import { relocateSourceSite, sourceSiteSelector } from "../selection/sourceSite.js";
|
|
@@ -283,10 +282,14 @@ export async function verifyAndReconcileHandoff(snapshot, doc = handoffDocument(
|
|
|
283
282
|
finally {
|
|
284
283
|
// Reconciliation reapplies the canonical set. If it was unable to write
|
|
285
284
|
// (for example, a read-only Canvas lease), restore the untouched set here.
|
|
285
|
+
// A Canvas restore settles on the renderer's acknowledgement: that
|
|
286
|
+
// acknowledgement invalidates the frame's stylesheet revision, and a
|
|
287
|
+
// caller still inside this verification must not mistake it for a source
|
|
288
|
+
// change and schedule another verification.
|
|
286
289
|
if (doc === document)
|
|
287
290
|
await applyProjection(getActiveDraftChanges());
|
|
288
291
|
else
|
|
289
|
-
restoreCanonicalFrameProjection(doc);
|
|
292
|
+
await restoreCanonicalFrameProjection(doc);
|
|
290
293
|
}
|
|
291
294
|
}
|
|
292
295
|
export function documentBelongsToHandoff(doc, owner) {
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { startWorkspaceController } from "./workspace/controller.js";
|
|
2
|
+
import { createElement } from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import { toggleInspector, setInspectorOpen } from "./shell/openStore.js";
|
|
5
|
+
import { setSelectedElement } from "./selection/selectionStore.js";
|
|
6
|
+
import { removeManagedSheet } from "./projection/managedStylesheet.js";
|
|
7
|
+
import { isInspectorToggleShortcut, isOriginalPreviewShortcut, SEND_PROMPT_HOTKEY_EVENT, } from "./shell/shortcuts.js";
|
|
8
|
+
import { isCanvasRenderer } from "./canvas/roleDetection.js";
|
|
9
|
+
import { isPageSurface } from "./canvas/pageSurface.js";
|
|
10
|
+
import { isKeyboardShortcutMessage } from "./canvas/frameProtocol.js";
|
|
11
|
+
import { subscribeCanvasRendererMessages } from "./canvas/rendererMessageRouter.js";
|
|
12
|
+
import { bootstrapRenderer } from "./canvas/rendererBootstrap.js";
|
|
13
|
+
import { setRestoreCount, } from "./canvas/sessionStore.js";
|
|
14
|
+
import { getChangesList } from "./drafts/store.js";
|
|
15
|
+
import { acquireLease, enableWriteGuard, hasWriteLease, releaseLease, subscribeOwnership, } from "./canvas/workspaceLease.js";
|
|
16
|
+
import { cancelStaleDetection, startStaleDetection } from "./canvas/staleChangeDetector.js";
|
|
17
|
+
import { LockedWorkspaceNotice } from "./canvas/LockedWorkspaceNotice.js";
|
|
18
|
+
import { AppShell } from "./shell/AppShell.js";
|
|
19
|
+
import { installInspectionBridge } from "./inspection/bridge.js";
|
|
20
|
+
import { releaseDocumentProjection, getStructuralChanges } from "./projection/structuralProjection.js";
|
|
21
|
+
import { cancelInlineTextEdit } from "./inline-text/inlineTextEditor.js";
|
|
22
|
+
import { configureNudgeUiRuntime, getNudgeUiRuntimeConfig, isDemoRuntime } from "./runtime/runtimeConfig.js";
|
|
23
|
+
import { setCanvasMode } from "./canvas/viewStore.js";
|
|
24
|
+
import { isNudgeUiDev, setNudgeUiHostDevFlag } from "./runtime/devFlag.js";
|
|
25
|
+
import { clearClipboardHandoff, } from "./prompt/clipboardHandoff.js";
|
|
26
|
+
import { createWorkspace, InspectorSessionProvider, } from "./session/index.js";
|
|
27
|
+
import { clearSketchClipboardHandoff } from "./sketch/handoff.js";
|
|
28
|
+
import { cancelSketchInteraction, isSketchInteractionActive } from "./sketch/interaction.js";
|
|
29
|
+
import { setOriginalPreviewActive } from "./shell/originalPreview.js";
|
|
30
|
+
import { initializeSketchStore } from "./sketch/store.js";
|
|
31
|
+
import { inspectorStorage } from "./runtime/inspectorStorage.js";
|
|
32
|
+
import { disposeRuntimeIdentityClaims } from "./runtime/runtimeIdentityClaims.js";
|
|
33
|
+
let hostElement = null;
|
|
34
|
+
let reactRoot = null;
|
|
35
|
+
let lockedRoot = null;
|
|
36
|
+
const workspace = createWorkspace();
|
|
37
|
+
let inspectorSession = null;
|
|
38
|
+
let rendererBootstrapHandle = null;
|
|
39
|
+
let workspaceController = null;
|
|
40
|
+
let unsubscribeOwnership = null;
|
|
41
|
+
let removeInspectionBridge = null;
|
|
42
|
+
let controllerStartId = 0;
|
|
43
|
+
let keyboardPeekHeld = false;
|
|
44
|
+
function onKeydown(e) {
|
|
45
|
+
if (isSketchInteractionActive())
|
|
46
|
+
return;
|
|
47
|
+
if (isInspectorToggleShortcut(e)) {
|
|
48
|
+
toggleInspector();
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (isOriginalPreviewShortcut(e)) {
|
|
53
|
+
keyboardPeekHeld = true;
|
|
54
|
+
setOriginalPreviewActive(true);
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function onKeyup(e) {
|
|
59
|
+
// Release only a keyboard-started peek so a button-held preview survives
|
|
60
|
+
// unrelated Backslash keyups (e.g. the panel-toggle shortcuts pressed
|
|
61
|
+
// mid-hold). A guarded keydown never sets the flag, so this stays a no-op
|
|
62
|
+
// for keyups without a matching hold.
|
|
63
|
+
if (e.code === "Backslash" && keyboardPeekHeld) {
|
|
64
|
+
keyboardPeekHeld = false;
|
|
65
|
+
setOriginalPreviewActive(false);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function onRendererKeyboardShortcut(message, identity) {
|
|
69
|
+
if (!isKeyboardShortcutMessage(message, identity))
|
|
70
|
+
return;
|
|
71
|
+
if (message.code === "KeyS" && message.phase === "keydown") {
|
|
72
|
+
window.dispatchEvent(new Event(SEND_PROMPT_HOTKEY_EVENT));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (message.code !== "Backslash")
|
|
76
|
+
return;
|
|
77
|
+
if (message.phase === "keydown") {
|
|
78
|
+
keyboardPeekHeld = true;
|
|
79
|
+
setOriginalPreviewActive(true);
|
|
80
|
+
}
|
|
81
|
+
else if (keyboardPeekHeld) {
|
|
82
|
+
keyboardPeekHeld = false;
|
|
83
|
+
setOriginalPreviewActive(false);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function disposeInspectorSession() {
|
|
87
|
+
const session = inspectorSession;
|
|
88
|
+
inspectorSession = null;
|
|
89
|
+
session?.dispose();
|
|
90
|
+
}
|
|
91
|
+
export function bootstrapNudgeUi(inspectorHost) {
|
|
92
|
+
controllerStartId += 1;
|
|
93
|
+
const runtimeConfig = getNudgeUiRuntimeConfig();
|
|
94
|
+
const explicitDemo = isDemoRuntime();
|
|
95
|
+
if (!isNudgeUiDev() && !explicitDemo)
|
|
96
|
+
return;
|
|
97
|
+
if (explicitDemo) {
|
|
98
|
+
rendererBootstrapHandle?.teardown();
|
|
99
|
+
rendererBootstrapHandle = null;
|
|
100
|
+
// ADR-0014: only the configured demo runtime opens the shared dev gate
|
|
101
|
+
// for its own document. The bundle mode name alone must never flip it,
|
|
102
|
+
// so every build without both opt-ins stays governed by ADR-0002.
|
|
103
|
+
setNudgeUiHostDevFlag(true);
|
|
104
|
+
if (runtimeConfig.capabilities.canvas && isCanvasRenderer()) {
|
|
105
|
+
rendererBootstrapHandle = bootstrapRenderer() ?? null;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// The public demo shares the iframe editor while keeping the write lease,
|
|
109
|
+
// persistence, and agent bridge disabled.
|
|
110
|
+
setCanvasMode("canvas");
|
|
111
|
+
workspaceController?.dispose();
|
|
112
|
+
workspaceController = startWorkspaceController();
|
|
113
|
+
mountInspector(inspectorHost);
|
|
114
|
+
setInspectorOpen(false);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!runtimeConfig.capabilities.canvas) {
|
|
118
|
+
// A project can be reopened with a runtime that does not expose Canvas.
|
|
119
|
+
// Clear any stale in-memory mode before mounting the static inspector.
|
|
120
|
+
setCanvasMode("inspect");
|
|
121
|
+
}
|
|
122
|
+
rendererBootstrapHandle?.teardown();
|
|
123
|
+
rendererBootstrapHandle = null;
|
|
124
|
+
removeInspectionBridge?.();
|
|
125
|
+
removeInspectionBridge = installInspectionBridge();
|
|
126
|
+
if (getNudgeUiRuntimeConfig().capabilities.canvas && isCanvasRenderer()) {
|
|
127
|
+
rendererBootstrapHandle = bootstrapRenderer() ?? null;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
enableWriteGuard();
|
|
131
|
+
const leaseGranted = acquireLease();
|
|
132
|
+
if (!leaseGranted) {
|
|
133
|
+
mountLockedNotice(inspectorHost);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
void startController(inspectorHost);
|
|
137
|
+
}
|
|
138
|
+
async function startController(inspectorHost) {
|
|
139
|
+
const startId = ++controllerStartId;
|
|
140
|
+
if (!hasWriteLease()) {
|
|
141
|
+
mountLockedNotice(inspectorHost);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
// Ownership prevents the previous tab from saving after this snapshot.
|
|
145
|
+
// Refresh on remount as well as explicit takeover, before hydration writes.
|
|
146
|
+
try {
|
|
147
|
+
const storage = inspectorStorage();
|
|
148
|
+
if (storage?.refresh)
|
|
149
|
+
await storage.refresh();
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
if (startId !== controllerStartId)
|
|
153
|
+
return;
|
|
154
|
+
releaseLease();
|
|
155
|
+
mountLockedNotice(inspectorHost, true);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (startId !== controllerStartId)
|
|
159
|
+
return;
|
|
160
|
+
if (!hasWriteLease()) {
|
|
161
|
+
mountLockedNotice(inspectorHost);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (lockedRoot) {
|
|
165
|
+
lockedRoot.unmount();
|
|
166
|
+
lockedRoot = null;
|
|
167
|
+
}
|
|
168
|
+
void initializeSketchStore(getNudgeUiRuntimeConfig().projectId).catch(() => undefined);
|
|
169
|
+
unsubscribeOwnership?.();
|
|
170
|
+
unsubscribeOwnership = subscribeOwnership((hasLease) => {
|
|
171
|
+
if (!hasLease) {
|
|
172
|
+
workspaceController?.dispose();
|
|
173
|
+
workspaceController = null;
|
|
174
|
+
mountLockedNotice(inspectorHost);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
workspaceController?.dispose();
|
|
178
|
+
const result = startWorkspaceController();
|
|
179
|
+
workspaceController = result;
|
|
180
|
+
if (result.restored) {
|
|
181
|
+
setRestoreCount(getChangesList().length + getStructuralChanges().length);
|
|
182
|
+
const restored = getChangesList();
|
|
183
|
+
if (restored.length > 0) {
|
|
184
|
+
startStaleDetection(restored);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (getNudgeUiRuntimeConfig().capabilities.canvas) {
|
|
188
|
+
// Normal controllers always host the iframe workspace. Hydration runs
|
|
189
|
+
// first so this mode change cannot discard cards, camera, or edits.
|
|
190
|
+
setCanvasMode("canvas");
|
|
191
|
+
}
|
|
192
|
+
mountInspector(inspectorHost);
|
|
193
|
+
if (getNudgeUiRuntimeConfig().capabilities.canvas && isPageSurface()) {
|
|
194
|
+
rendererBootstrapHandle = bootstrapRenderer() ?? null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function mountLockedNotice(host, storageError = false) {
|
|
198
|
+
controllerStartId += 1;
|
|
199
|
+
if (reactRoot) {
|
|
200
|
+
reactRoot.unmount();
|
|
201
|
+
reactRoot = null;
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
disposeInspectorSession();
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
cancelStaleDetection();
|
|
208
|
+
setInspectorOpen(false);
|
|
209
|
+
cancelInlineTextEdit();
|
|
210
|
+
cancelSketchInteraction();
|
|
211
|
+
clearSketchClipboardHandoff();
|
|
212
|
+
setSelectedElement(null);
|
|
213
|
+
removeManagedSheet();
|
|
214
|
+
disposeRuntimeIdentityClaims(document);
|
|
215
|
+
releaseDocumentProjection(document);
|
|
216
|
+
hostElement = null;
|
|
217
|
+
unsubscribeOwnership?.();
|
|
218
|
+
unsubscribeOwnership = null;
|
|
219
|
+
}
|
|
220
|
+
const shadow = host.shadowRoot ?? host.attachShadow({ mode: "open" });
|
|
221
|
+
if (!lockedRoot) {
|
|
222
|
+
lockedRoot = createRoot(shadow);
|
|
223
|
+
}
|
|
224
|
+
lockedRoot.render(createElement(LockedWorkspaceNotice, {
|
|
225
|
+
onTakeover: () => startController(host),
|
|
226
|
+
storageError,
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
export function mountInspector(host) {
|
|
230
|
+
const demo = isDemoRuntime();
|
|
231
|
+
if (!demo && !hasWriteLease())
|
|
232
|
+
return;
|
|
233
|
+
const runtimeConfig = getNudgeUiRuntimeConfig();
|
|
234
|
+
if (runtimeConfig.capabilities.domNavigation !== true) {
|
|
235
|
+
configureNudgeUiRuntime({
|
|
236
|
+
...runtimeConfig,
|
|
237
|
+
capabilities: { ...runtimeConfig.capabilities, domNavigation: true },
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (lockedRoot) {
|
|
241
|
+
lockedRoot.unmount();
|
|
242
|
+
lockedRoot = null;
|
|
243
|
+
}
|
|
244
|
+
if (!hostElement)
|
|
245
|
+
hostElement = host;
|
|
246
|
+
const shadow = host.shadowRoot ?? host.attachShadow({ mode: "open" });
|
|
247
|
+
if (!reactRoot) {
|
|
248
|
+
reactRoot = createRoot(shadow);
|
|
249
|
+
inspectorSession = workspace.createInspectorSession(host);
|
|
250
|
+
inspectorSession.registerCleanup(() => window.removeEventListener("keydown", onKeydown));
|
|
251
|
+
inspectorSession.registerCleanup(() => window.removeEventListener("keyup", onKeyup));
|
|
252
|
+
inspectorSession.registerCleanup(subscribeCanvasRendererMessages(({ frame, message }) => {
|
|
253
|
+
onRendererKeyboardShortcut(message, frame.identity);
|
|
254
|
+
}));
|
|
255
|
+
reactRoot.render(createElement(InspectorSessionProvider, { inspector: inspectorSession, documentSession: null }, createElement(AppShell)));
|
|
256
|
+
window.addEventListener("keydown", onKeydown);
|
|
257
|
+
window.addEventListener("keyup", onKeyup);
|
|
258
|
+
}
|
|
259
|
+
setInspectorOpen(true);
|
|
260
|
+
}
|
|
261
|
+
export function unmountInspector() {
|
|
262
|
+
controllerStartId += 1;
|
|
263
|
+
rendererBootstrapHandle?.teardown();
|
|
264
|
+
rendererBootstrapHandle = null;
|
|
265
|
+
workspaceController?.dispose();
|
|
266
|
+
workspaceController = null;
|
|
267
|
+
unsubscribeOwnership?.();
|
|
268
|
+
unsubscribeOwnership = null;
|
|
269
|
+
if (lockedRoot) {
|
|
270
|
+
lockedRoot.unmount();
|
|
271
|
+
lockedRoot = null;
|
|
272
|
+
}
|
|
273
|
+
cancelStaleDetection();
|
|
274
|
+
cancelInlineTextEdit();
|
|
275
|
+
cancelSketchInteraction();
|
|
276
|
+
setSelectedElement(null);
|
|
277
|
+
if (reactRoot) {
|
|
278
|
+
reactRoot.unmount();
|
|
279
|
+
reactRoot = null;
|
|
280
|
+
}
|
|
281
|
+
try {
|
|
282
|
+
disposeInspectorSession();
|
|
283
|
+
}
|
|
284
|
+
finally {
|
|
285
|
+
// Document-session cleanup already releases host projection when a
|
|
286
|
+
// session exists; release directly as well so projection applied outside
|
|
287
|
+
// a session (gestures, workspace projection) cannot leak across unmount.
|
|
288
|
+
disposeRuntimeIdentityClaims(document);
|
|
289
|
+
releaseDocumentProjection(document);
|
|
290
|
+
clearClipboardHandoff();
|
|
291
|
+
clearSketchClipboardHandoff();
|
|
292
|
+
removeManagedSheet();
|
|
293
|
+
removeInspectionBridge?.();
|
|
294
|
+
removeInspectionBridge = null;
|
|
295
|
+
hostElement = null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CanvasFrame } from "./canvasFrame.js";
|
|
1
2
|
import { type ActivityFile } from "../agent/activity.js";
|
|
2
3
|
import { type FrameContent } from "./frameContent.js";
|
|
3
4
|
export interface ActivityAttribution {
|
|
@@ -9,5 +10,5 @@ export declare function attributeActivity(content: FrameContent, document: Docum
|
|
|
9
10
|
export declare function AgentActivityOverlay({ cardId, content, iframe }: {
|
|
10
11
|
cardId: string;
|
|
11
12
|
content: FrameContent;
|
|
12
|
-
iframe:
|
|
13
|
+
iframe: CanvasFrame | null;
|
|
13
14
|
}): import("react").JSX.Element | null;
|