@spotpatch/runtime 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-BXRMVHNT.js → chunk-ASRUAKA5.js} +1 -1
- package/dist/chunk-ASRUAKA5.js.map +1 -0
- package/dist/chunk-KIDHJQRG.js +14 -0
- package/dist/chunk-KIDHJQRG.js.map +1 -0
- package/dist/{chunk-7ES63LA7.js → chunk-P6X75LO5.js} +11 -1
- package/dist/chunk-P6X75LO5.js.map +1 -0
- package/dist/chunk-P7W3F4UA.js +115 -0
- package/dist/chunk-P7W3F4UA.js.map +1 -0
- package/dist/contextual-ask-panel.cjs +1637 -0
- package/dist/contextual-ask-panel.cjs.map +1 -0
- package/dist/contextual-ask-panel.d.cts +163 -0
- package/dist/contextual-ask-panel.d.ts +163 -0
- package/dist/contextual-ask-panel.js +1593 -0
- package/dist/contextual-ask-panel.js.map +1 -0
- package/dist/data-flow-panel.cjs +9 -0
- package/dist/data-flow-panel.cjs.map +1 -1
- package/dist/data-flow-panel.js +1 -1
- package/dist/external-handoff-panel.cjs +29 -9
- package/dist/external-handoff-panel.cjs.map +1 -1
- package/dist/external-handoff-panel.d.cts +3 -3
- package/dist/external-handoff-panel.d.ts +3 -3
- package/dist/external-handoff-panel.js +22 -11
- package/dist/external-handoff-panel.js.map +1 -1
- package/dist/index.cjs +1285 -279
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1250 -356
- package/dist/index.js.map +1 -1
- package/dist/motion-extension-contract-B3m26CML.d.cts +72 -0
- package/dist/motion-extension-contract-B3m26CML.d.ts +72 -0
- package/dist/motion.cjs +1251 -0
- package/dist/motion.cjs.map +1 -0
- package/dist/motion.d.cts +11 -0
- package/dist/motion.d.ts +11 -0
- package/dist/motion.js +1092 -0
- package/dist/motion.js.map +1 -0
- package/package.json +31 -3
- package/dist/chunk-7ES63LA7.js.map +0 -1
- package/dist/chunk-BXRMVHNT.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -424,7 +424,7 @@ function omitBrowserCodeContext(request) {
|
|
|
424
424
|
};
|
|
425
425
|
}
|
|
426
426
|
function runtimeApiErrorCode(error) {
|
|
427
|
-
return error instanceof RuntimeApiError ? error.code : void 0;
|
|
427
|
+
return error instanceof RuntimeApiError && isAgentErrorCode(error.code) ? error.code : void 0;
|
|
428
428
|
}
|
|
429
429
|
function createRuntimeApi(options) {
|
|
430
430
|
const pendingRequests = /* @__PURE__ */ new Set();
|
|
@@ -1138,6 +1138,15 @@ var UI_Z_INDEX = Object.freeze({
|
|
|
1138
1138
|
highlight: 2147483646,
|
|
1139
1139
|
controls: 2147483647
|
|
1140
1140
|
});
|
|
1141
|
+
var FLOATING_SURFACE_LAYOUT = Object.freeze({
|
|
1142
|
+
compactInset: 8,
|
|
1143
|
+
compactViewportWidth: 520,
|
|
1144
|
+
desktopInset: 24,
|
|
1145
|
+
dragActivationDistance: 6,
|
|
1146
|
+
edgeSnapDistance: 20,
|
|
1147
|
+
workbenchMaxHeight: 620,
|
|
1148
|
+
workbenchMaxWidth: 460
|
|
1149
|
+
});
|
|
1141
1150
|
|
|
1142
1151
|
// src/picker/hit-test.ts
|
|
1143
1152
|
function isInsideSpotPatchUI(element2) {
|
|
@@ -1986,6 +1995,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1986
1995
|
root.hidden = !ai.enabled;
|
|
1987
1996
|
const header = createMarkedElement(document, "div");
|
|
1988
1997
|
header.className = "spotpatch-agent-head";
|
|
1998
|
+
header.setAttribute("data-spotpatch-agent-identity", "");
|
|
1989
1999
|
const title = createMarkedElement(document, "span");
|
|
1990
2000
|
title.className = "spotpatch-agent-title";
|
|
1991
2001
|
const badge = createMarkedElement(document, "span");
|
|
@@ -2492,7 +2502,27 @@ function svgElement(document, tagName, attributes) {
|
|
|
2492
2502
|
}
|
|
2493
2503
|
return element2;
|
|
2494
2504
|
}
|
|
2495
|
-
function
|
|
2505
|
+
function namespaceSvgIds(svg, prefix) {
|
|
2506
|
+
const safePrefix = prefix.replace(/[^a-zA-Z0-9_-]/gu, "-");
|
|
2507
|
+
const ids = /* @__PURE__ */ new Map();
|
|
2508
|
+
for (const element2 of svg.querySelectorAll("[id]")) {
|
|
2509
|
+
const id = element2.id;
|
|
2510
|
+
const namespacedId = `${safePrefix}-${id}`;
|
|
2511
|
+
ids.set(id, namespacedId);
|
|
2512
|
+
element2.id = namespacedId;
|
|
2513
|
+
}
|
|
2514
|
+
for (const element2 of [svg, ...svg.querySelectorAll("*")]) {
|
|
2515
|
+
for (const attribute of [...element2.attributes]) {
|
|
2516
|
+
let value = attribute.value;
|
|
2517
|
+
for (const [id, namespacedId] of ids) {
|
|
2518
|
+
value = value.replaceAll(`url(#${id})`, `url(#${namespacedId})`);
|
|
2519
|
+
if (value === `#${id}`) value = `#${namespacedId}`;
|
|
2520
|
+
}
|
|
2521
|
+
if (value !== attribute.value) element2.setAttribute(attribute.name, value);
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
function createBrandMark(document, content, idPrefix) {
|
|
2496
2526
|
const resolved = resolveBrandMarkContent(content);
|
|
2497
2527
|
const svg = svgElement(document, "svg", {
|
|
2498
2528
|
xmlns: SVG_NAMESPACE,
|
|
@@ -2502,6 +2532,7 @@ function createBrandMark(document, content) {
|
|
|
2502
2532
|
focusable: "false"
|
|
2503
2533
|
});
|
|
2504
2534
|
svg.innerHTML = resolved.content;
|
|
2535
|
+
if (idPrefix !== void 0) namespaceSvgIds(svg, idPrefix);
|
|
2505
2536
|
return svg;
|
|
2506
2537
|
}
|
|
2507
2538
|
|
|
@@ -2511,79 +2542,24 @@ function getDataFlowExtension(target2 = globalThis) {
|
|
|
2511
2542
|
return target2[DATA_FLOW_EXTENSION_KEY];
|
|
2512
2543
|
}
|
|
2513
2544
|
|
|
2514
|
-
// src/ui/dialog-placement.ts
|
|
2515
|
-
var VIEWPORT_MARGIN = 16;
|
|
2516
|
-
var TARGET_GAP = 14;
|
|
2517
|
-
var TARGET_INSET = 24;
|
|
2518
|
-
var ANCHOR_INSET = 22;
|
|
2519
|
-
function clamp(value, minimum, maximum) {
|
|
2520
|
-
return Math.min(Math.max(value, minimum), Math.max(minimum, maximum));
|
|
2521
|
-
}
|
|
2522
|
-
function calculateDialogPlacement({
|
|
2523
|
-
dialogHeight,
|
|
2524
|
-
dialogWidth,
|
|
2525
|
-
target: target2,
|
|
2526
|
-
viewportHeight,
|
|
2527
|
-
viewportWidth
|
|
2528
|
-
}) {
|
|
2529
|
-
const maxLeft = viewportWidth - dialogWidth - VIEWPORT_MARGIN;
|
|
2530
|
-
const maxTop = viewportHeight - dialogHeight - VIEWPORT_MARGIN;
|
|
2531
|
-
const viewportLeft = clamp(
|
|
2532
|
-
(viewportWidth - dialogWidth) / 2,
|
|
2533
|
-
VIEWPORT_MARGIN,
|
|
2534
|
-
maxLeft
|
|
2535
|
-
);
|
|
2536
|
-
const viewportTop = clamp(
|
|
2537
|
-
(viewportHeight - dialogHeight) / 2,
|
|
2538
|
-
VIEWPORT_MARGIN,
|
|
2539
|
-
maxTop
|
|
2540
|
-
);
|
|
2541
|
-
if (target2 === void 0) {
|
|
2542
|
-
return Object.freeze({
|
|
2543
|
-
anchorX: clamp(dialogWidth / 2, ANCHOR_INSET, dialogWidth - ANCHOR_INSET),
|
|
2544
|
-
anchorY: clamp(dialogHeight / 2, ANCHOR_INSET, dialogHeight - ANCHOR_INSET),
|
|
2545
|
-
left: viewportLeft,
|
|
2546
|
-
mode: "viewport",
|
|
2547
|
-
top: viewportTop
|
|
2548
|
-
});
|
|
2549
|
-
}
|
|
2550
|
-
const targetCenterX = target2.x + target2.width / 2;
|
|
2551
|
-
const targetCenterY = target2.y + target2.height / 2;
|
|
2552
|
-
const centeredLeft = clamp(targetCenterX - dialogWidth / 2, VIEWPORT_MARGIN, maxLeft);
|
|
2553
|
-
const centeredTop = clamp(targetCenterY - dialogHeight / 2, VIEWPORT_MARGIN, maxTop);
|
|
2554
|
-
let left = centeredLeft;
|
|
2555
|
-
let top = centeredTop;
|
|
2556
|
-
let mode = "viewport";
|
|
2557
|
-
if (target2.width >= dialogWidth + TARGET_INSET * 2 && target2.height >= dialogHeight + TARGET_INSET * 2) {
|
|
2558
|
-
mode = "center";
|
|
2559
|
-
} else if (target2.y - dialogHeight - TARGET_GAP >= VIEWPORT_MARGIN) {
|
|
2560
|
-
top = target2.y - dialogHeight - TARGET_GAP;
|
|
2561
|
-
mode = "above";
|
|
2562
|
-
} else if (target2.y + target2.height + TARGET_GAP + dialogHeight <= viewportHeight - VIEWPORT_MARGIN) {
|
|
2563
|
-
top = target2.y + target2.height + TARGET_GAP;
|
|
2564
|
-
mode = "below";
|
|
2565
|
-
} else if (target2.x + target2.width + TARGET_GAP + dialogWidth <= viewportWidth - VIEWPORT_MARGIN) {
|
|
2566
|
-
left = target2.x + target2.width + TARGET_GAP;
|
|
2567
|
-
mode = "right";
|
|
2568
|
-
} else if (target2.x - dialogWidth - TARGET_GAP >= VIEWPORT_MARGIN) {
|
|
2569
|
-
left = target2.x - dialogWidth - TARGET_GAP;
|
|
2570
|
-
mode = "left";
|
|
2571
|
-
}
|
|
2572
|
-
return Object.freeze({
|
|
2573
|
-
anchorX: clamp(targetCenterX - left, ANCHOR_INSET, dialogWidth - ANCHOR_INSET),
|
|
2574
|
-
anchorY: clamp(targetCenterY - top, ANCHOR_INSET, dialogHeight - ANCHOR_INSET),
|
|
2575
|
-
left,
|
|
2576
|
-
mode,
|
|
2577
|
-
top
|
|
2578
|
-
});
|
|
2579
|
-
}
|
|
2580
|
-
|
|
2581
2545
|
// src/ui/external-handoff-contract.ts
|
|
2582
2546
|
var EXTERNAL_HANDOFF_EXTENSION_KEY = /* @__PURE__ */ Symbol.for("spotpatch.external-handoff.v1");
|
|
2583
2547
|
function getExternalHandoffExtension() {
|
|
2584
2548
|
return globalThis[EXTERNAL_HANDOFF_EXTENSION_KEY];
|
|
2585
2549
|
}
|
|
2586
2550
|
|
|
2551
|
+
// src/ui/contextual-ask-contract.ts
|
|
2552
|
+
var CONTEXTUAL_ASK_EXTENSION_KEY = /* @__PURE__ */ Symbol.for("spotpatch.contextual-ask.v1");
|
|
2553
|
+
function getContextualAskExtension() {
|
|
2554
|
+
return globalThis[CONTEXTUAL_ASK_EXTENSION_KEY];
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
// src/ui/motion-extension-contract.ts
|
|
2558
|
+
var MOTION_EXTENSION_KEY = /* @__PURE__ */ Symbol.for("spotpatch.motion.v1");
|
|
2559
|
+
function getFloatingSurfaceMotionExtension() {
|
|
2560
|
+
return globalThis[MOTION_EXTENSION_KEY];
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2587
2563
|
// src/ui/localization.ts
|
|
2588
2564
|
var import_shared6 = require("@spotpatch/shared");
|
|
2589
2565
|
var STATUS_EN = Object.freeze({
|
|
@@ -2616,6 +2592,51 @@ var STATUS_ZH = Object.freeze({
|
|
|
2616
2592
|
reverted: "\u5DF2\u64A4\u9500",
|
|
2617
2593
|
failed: "\u5931\u8D25"
|
|
2618
2594
|
});
|
|
2595
|
+
var EXECUTION_ACTIVITY_EN = Object.freeze({
|
|
2596
|
+
prepare: "Preparing context",
|
|
2597
|
+
dispatch: "Dispatching context",
|
|
2598
|
+
discover: "Discovering project files",
|
|
2599
|
+
search: "Searching source",
|
|
2600
|
+
read: "Reading",
|
|
2601
|
+
patch: "Generating a minimal patch",
|
|
2602
|
+
check: "Running",
|
|
2603
|
+
audit: "Auditing proposed changes",
|
|
2604
|
+
apply: "Applying verified changes",
|
|
2605
|
+
sync: "Returning results to SpotPatch",
|
|
2606
|
+
unknown: "Processing the current task"
|
|
2607
|
+
});
|
|
2608
|
+
var EXECUTION_ACTIVITY_ZH = Object.freeze({
|
|
2609
|
+
prepare: "\u6B63\u5728\u51C6\u5907\u4E0A\u4E0B\u6587",
|
|
2610
|
+
dispatch: "\u6B63\u5728\u6D3E\u53D1\u4E0A\u4E0B\u6587",
|
|
2611
|
+
discover: "\u6B63\u5728\u67E5\u627E\u9879\u76EE\u6587\u4EF6",
|
|
2612
|
+
search: "\u6B63\u5728\u641C\u7D22\u6E90\u7801",
|
|
2613
|
+
read: "\u6B63\u5728\u8BFB\u53D6",
|
|
2614
|
+
patch: "\u6B63\u5728\u751F\u6210\u6700\u5C0F\u4FEE\u6539\u8865\u4E01",
|
|
2615
|
+
check: "\u6B63\u5728\u8FD0\u884C",
|
|
2616
|
+
audit: "\u6B63\u5728\u5BA1\u8BA1\u5019\u9009\u4FEE\u6539",
|
|
2617
|
+
apply: "\u6B63\u5728\u5E94\u7528\u5DF2\u9A8C\u8BC1\u4FEE\u6539",
|
|
2618
|
+
sync: "\u6B63\u5728\u5C06\u7ED3\u679C\u56DE\u6D41 SpotPatch",
|
|
2619
|
+
unknown: "\u6B63\u5728\u5904\u7406\u5F53\u524D\u4EFB\u52A1"
|
|
2620
|
+
});
|
|
2621
|
+
var EXECUTION_LANE_LABELS = Object.freeze({
|
|
2622
|
+
prepare: "prepare",
|
|
2623
|
+
dispatch: "dispatch",
|
|
2624
|
+
discover: "list",
|
|
2625
|
+
search: "search",
|
|
2626
|
+
read: "read",
|
|
2627
|
+
patch: "patch",
|
|
2628
|
+
check: "check",
|
|
2629
|
+
audit: "audit",
|
|
2630
|
+
apply: "apply",
|
|
2631
|
+
sync: "sync",
|
|
2632
|
+
unknown: "agent"
|
|
2633
|
+
});
|
|
2634
|
+
function executionActivityAction(labels, kind, detail) {
|
|
2635
|
+
return detail === void 0 || detail.length === 0 ? labels[kind] : `${labels[kind]} ${detail}`;
|
|
2636
|
+
}
|
|
2637
|
+
function executionActivityLane(kind, detail) {
|
|
2638
|
+
return detail === void 0 || detail.length === 0 ? EXECUTION_LANE_LABELS[kind] : `${EXECUTION_LANE_LABELS[kind]} \xB7 ${detail}`;
|
|
2639
|
+
}
|
|
2619
2640
|
var EXTERNAL_HANDOFF_ERROR_EN = "The external Agent handoff request failed.";
|
|
2620
2641
|
var EXTERNAL_HANDOFF_ERROR_ZH = "\u5916\u90E8 Agent \u4EA4\u63A5\u8BF7\u6C42\u5931\u8D25\u3002";
|
|
2621
2642
|
var ERROR_MESSAGES_EN = Object.freeze({
|
|
@@ -2833,6 +2854,11 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2833
2854
|
previewTitle: "Review the request",
|
|
2834
2855
|
previewSubtitle: "Verify the complete context before it leaves the browser."
|
|
2835
2856
|
}),
|
|
2857
|
+
floatingSurface: Object.freeze({
|
|
2858
|
+
dragHandle: "Drag to move the SpotPatch workbench",
|
|
2859
|
+
resetPosition: "Reset workbench position",
|
|
2860
|
+
positionReset: "SpotPatch position reset to the lower-right corner."
|
|
2861
|
+
}),
|
|
2836
2862
|
context: Object.freeze({
|
|
2837
2863
|
collecting: "Collecting context",
|
|
2838
2864
|
ready: "Context ready",
|
|
@@ -2919,6 +2945,27 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2919
2945
|
noOutput: "No output.",
|
|
2920
2946
|
status: (status) => STATUS_EN[status]
|
|
2921
2947
|
}),
|
|
2948
|
+
execution: Object.freeze({
|
|
2949
|
+
claude: "Claude",
|
|
2950
|
+
codex: "Codex",
|
|
2951
|
+
receivingTitle: "Receiving context",
|
|
2952
|
+
dispatchingTitle: (identity) => `Handing off to ${identity}`,
|
|
2953
|
+
runningTitle: (target2) => `Modifying ${target2}`,
|
|
2954
|
+
expandedRunningTitle: (identity) => `${identity} is making changes`,
|
|
2955
|
+
completedTitle: "Change complete",
|
|
2956
|
+
expandedCompletedTitle: "Changes complete",
|
|
2957
|
+
failedTitle: "Execution failed",
|
|
2958
|
+
receivingStatus: "Receiving",
|
|
2959
|
+
dispatchingStatus: "Dispatching",
|
|
2960
|
+
runningStatus: "Running",
|
|
2961
|
+
checkingStatus: "Checking",
|
|
2962
|
+
completedStatus: "Done",
|
|
2963
|
+
failedStatus: "Failed",
|
|
2964
|
+
resultReturned: "The result is back in SpotPatch",
|
|
2965
|
+
resultSummary: (files) => `${String(files)} ${files === 1 ? "file" : "files"}`,
|
|
2966
|
+
activityAction: (kind, detail) => executionActivityAction(EXECUTION_ACTIVITY_EN, kind, detail),
|
|
2967
|
+
activityLane: executionActivityLane
|
|
2968
|
+
}),
|
|
2922
2969
|
announcements: Object.freeze({
|
|
2923
2970
|
adapterDisabled: "React inspection was disabled after an adapter failure.",
|
|
2924
2971
|
selectionEnabled: "Element selection enabled.",
|
|
@@ -2971,6 +3018,11 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2971
3018
|
previewTitle: "\u5BA1\u9605\u4FEE\u6539\u8BF7\u6C42",
|
|
2972
3019
|
previewSubtitle: "\u53D1\u9001\u7ED9 AI \u524D\uFF0C\u8BF7\u6838\u5BF9\u5B8C\u6574\u4E0A\u4E0B\u6587\u4E0E\u6BCF\u9879\u76EE\u6807\u8BF4\u660E\u3002"
|
|
2973
3020
|
}),
|
|
3021
|
+
floatingSurface: Object.freeze({
|
|
3022
|
+
dragHandle: "\u62D6\u62FD\u4EE5\u79FB\u52A8 SpotPatch \u5DE5\u4F5C\u53F0",
|
|
3023
|
+
resetPosition: "\u91CD\u7F6E\u5DE5\u4F5C\u53F0\u4F4D\u7F6E",
|
|
3024
|
+
positionReset: "SpotPatch \u5DF2\u6062\u590D\u5230\u53F3\u4E0B\u89D2\u3002"
|
|
3025
|
+
}),
|
|
2974
3026
|
context: Object.freeze({
|
|
2975
3027
|
collecting: "\u6B63\u5728\u91C7\u96C6\u4E0A\u4E0B\u6587",
|
|
2976
3028
|
ready: "\u4E0A\u4E0B\u6587\u5DF2\u5C31\u7EEA",
|
|
@@ -3057,6 +3109,27 @@ var UI_MESSAGES = Object.freeze({
|
|
|
3057
3109
|
noOutput: "\u6CA1\u6709\u8F93\u51FA\u3002",
|
|
3058
3110
|
status: (status) => STATUS_ZH[status]
|
|
3059
3111
|
}),
|
|
3112
|
+
execution: Object.freeze({
|
|
3113
|
+
claude: "Claude",
|
|
3114
|
+
codex: "Codex",
|
|
3115
|
+
receivingTitle: "\u6B63\u5728\u63A5\u6536\u4E0A\u4E0B\u6587",
|
|
3116
|
+
dispatchingTitle: (identity) => `\u6B63\u5728\u4EA4\u63A5\u7ED9 ${identity}`,
|
|
3117
|
+
runningTitle: (target2) => `\u6B63\u5728\u4FEE\u6539 ${target2}`,
|
|
3118
|
+
expandedRunningTitle: (identity) => `${identity} \u6B63\u5728\u6267\u884C\u4FEE\u6539`,
|
|
3119
|
+
completedTitle: "\u4FEE\u6539\u5B8C\u6210",
|
|
3120
|
+
expandedCompletedTitle: "\u4FEE\u6539\u5DF2\u5B8C\u6210",
|
|
3121
|
+
failedTitle: "\u6267\u884C\u5931\u8D25",
|
|
3122
|
+
receivingStatus: "\u63A5\u6536\u4E2D",
|
|
3123
|
+
dispatchingStatus: "\u6D3E\u53D1\u4E2D",
|
|
3124
|
+
runningStatus: "\u6267\u884C\u4E2D",
|
|
3125
|
+
checkingStatus: "\u68C0\u67E5\u4E2D",
|
|
3126
|
+
completedStatus: "\u5B8C\u6210",
|
|
3127
|
+
failedStatus: "\u5931\u8D25",
|
|
3128
|
+
resultReturned: "\u7ED3\u679C\u5DF2\u56DE\u6D41 SpotPatch",
|
|
3129
|
+
resultSummary: (files) => `${String(files)} \u4E2A\u6587\u4EF6`,
|
|
3130
|
+
activityAction: (kind, detail) => executionActivityAction(EXECUTION_ACTIVITY_ZH, kind, detail),
|
|
3131
|
+
activityLane: executionActivityLane
|
|
3132
|
+
}),
|
|
3060
3133
|
announcements: Object.freeze({
|
|
3061
3134
|
adapterDisabled: "React \u9002\u914D\u5668\u5F02\u5E38\uFF0C\u672C\u6B21\u4F1A\u8BDD\u5DF2\u505C\u7528 React \u68C0\u67E5\u3002",
|
|
3062
3135
|
selectionEnabled: "\u5143\u7D20\u9009\u62E9\u5DF2\u542F\u7528\u3002",
|
|
@@ -3130,13 +3203,500 @@ function createUiLocalizer(document, preference = "auto") {
|
|
|
3130
3203
|
});
|
|
3131
3204
|
}
|
|
3132
3205
|
|
|
3133
|
-
// src/
|
|
3134
|
-
var
|
|
3135
|
-
var
|
|
3136
|
-
var
|
|
3137
|
-
|
|
3138
|
-
|
|
3206
|
+
// src/state/floating-surface-session.ts
|
|
3207
|
+
var STORAGE_PREFIX2 = "spotpatch:floating-surface:";
|
|
3208
|
+
var SNAPSHOT_VERSION2 = 1;
|
|
3209
|
+
var MAX_SNAPSHOT_CHARACTERS2 = 1024;
|
|
3210
|
+
function record2(value) {
|
|
3211
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
3212
|
+
}
|
|
3213
|
+
function finiteRatio(value) {
|
|
3214
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
|
|
3215
|
+
}
|
|
3216
|
+
function alignment(value) {
|
|
3217
|
+
return value === "start" || value === "end";
|
|
3218
|
+
}
|
|
3219
|
+
function parseSnapshot2(value) {
|
|
3220
|
+
const snapshot = record2(value);
|
|
3221
|
+
if (snapshot?.version !== SNAPSHOT_VERSION2 || !alignment(snapshot.horizontal) || !alignment(snapshot.vertical) || !finiteRatio(snapshot.xRatio) || !finiteRatio(snapshot.yRatio)) {
|
|
3222
|
+
return void 0;
|
|
3223
|
+
}
|
|
3224
|
+
return Object.freeze({
|
|
3225
|
+
horizontal: snapshot.horizontal,
|
|
3226
|
+
vertical: snapshot.vertical,
|
|
3227
|
+
xRatio: snapshot.xRatio,
|
|
3228
|
+
yRatio: snapshot.yRatio
|
|
3229
|
+
});
|
|
3230
|
+
}
|
|
3231
|
+
function createFloatingSurfaceSession(window, sessionId) {
|
|
3232
|
+
const key = `${STORAGE_PREFIX2}${sessionId}`;
|
|
3233
|
+
let storage;
|
|
3234
|
+
try {
|
|
3235
|
+
storage = window.sessionStorage;
|
|
3236
|
+
} catch {
|
|
3237
|
+
storage = void 0;
|
|
3238
|
+
}
|
|
3239
|
+
return Object.freeze({
|
|
3240
|
+
clear() {
|
|
3241
|
+
try {
|
|
3242
|
+
storage?.removeItem(key);
|
|
3243
|
+
} catch {
|
|
3244
|
+
}
|
|
3245
|
+
},
|
|
3246
|
+
load() {
|
|
3247
|
+
let serialized;
|
|
3248
|
+
try {
|
|
3249
|
+
serialized = storage?.getItem(key) ?? null;
|
|
3250
|
+
} catch {
|
|
3251
|
+
return void 0;
|
|
3252
|
+
}
|
|
3253
|
+
if (serialized === null || serialized.length > MAX_SNAPSHOT_CHARACTERS2) {
|
|
3254
|
+
return void 0;
|
|
3255
|
+
}
|
|
3256
|
+
try {
|
|
3257
|
+
return parseSnapshot2(JSON.parse(serialized));
|
|
3258
|
+
} catch {
|
|
3259
|
+
return void 0;
|
|
3260
|
+
}
|
|
3261
|
+
},
|
|
3262
|
+
save(position) {
|
|
3263
|
+
try {
|
|
3264
|
+
storage?.setItem(
|
|
3265
|
+
key,
|
|
3266
|
+
JSON.stringify({ version: SNAPSHOT_VERSION2, ...position })
|
|
3267
|
+
);
|
|
3268
|
+
} catch {
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
});
|
|
3272
|
+
}
|
|
3273
|
+
|
|
3274
|
+
// src/ui/floating-surface-position.ts
|
|
3275
|
+
var DEFAULT_FLOATING_SURFACE_POSITION = Object.freeze({
|
|
3276
|
+
horizontal: "end",
|
|
3277
|
+
vertical: "end",
|
|
3278
|
+
xRatio: 1,
|
|
3279
|
+
yRatio: 1
|
|
3139
3280
|
});
|
|
3281
|
+
function clamp(value, minimum, maximum) {
|
|
3282
|
+
return Math.min(Math.max(value, minimum), maximum);
|
|
3283
|
+
}
|
|
3284
|
+
function finiteNonNegative(value) {
|
|
3285
|
+
return Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
3286
|
+
}
|
|
3287
|
+
function boundedRatio(value) {
|
|
3288
|
+
return Number.isFinite(value) ? clamp(value, 0, 1) : 0.5;
|
|
3289
|
+
}
|
|
3290
|
+
function normalizedViewport(viewport) {
|
|
3291
|
+
return Object.freeze({
|
|
3292
|
+
height: finiteNonNegative(viewport.height),
|
|
3293
|
+
left: Number.isFinite(viewport.left) ? viewport.left : 0,
|
|
3294
|
+
top: Number.isFinite(viewport.top) ? viewport.top : 0,
|
|
3295
|
+
width: finiteNonNegative(viewport.width)
|
|
3296
|
+
});
|
|
3297
|
+
}
|
|
3298
|
+
function horizontalAnchor(rect, alignment2) {
|
|
3299
|
+
return alignment2 === "end" ? rect.left + rect.width : rect.left;
|
|
3300
|
+
}
|
|
3301
|
+
function verticalAnchor(rect, alignment2) {
|
|
3302
|
+
return alignment2 === "end" ? rect.top + rect.height : rect.top;
|
|
3303
|
+
}
|
|
3304
|
+
function normalizedCoordinate(coordinate, origin, length) {
|
|
3305
|
+
if (length <= 0) {
|
|
3306
|
+
return 0.5;
|
|
3307
|
+
}
|
|
3308
|
+
return boundedRatio((coordinate - origin) / length);
|
|
3309
|
+
}
|
|
3310
|
+
function positionFromAnchor(anchor, viewport, horizontal, vertical) {
|
|
3311
|
+
return Object.freeze({
|
|
3312
|
+
horizontal,
|
|
3313
|
+
vertical,
|
|
3314
|
+
xRatio: normalizedCoordinate(anchor.x, viewport.left, viewport.width),
|
|
3315
|
+
yRatio: normalizedCoordinate(anchor.y, viewport.top, viewport.height)
|
|
3316
|
+
});
|
|
3317
|
+
}
|
|
3318
|
+
function resolveFloatingSurfaceRect(position, size, viewport) {
|
|
3319
|
+
const width = finiteNonNegative(size.width);
|
|
3320
|
+
const height = finiteNonNegative(size.height);
|
|
3321
|
+
const normalized = normalizedViewport(viewport);
|
|
3322
|
+
const viewportWidth = normalized.width;
|
|
3323
|
+
const viewportHeight = normalized.height;
|
|
3324
|
+
const leftBoundary = normalized.left;
|
|
3325
|
+
const topBoundary = normalized.top;
|
|
3326
|
+
const rightBoundary = leftBoundary + viewportWidth;
|
|
3327
|
+
const bottomBoundary = topBoundary + viewportHeight;
|
|
3328
|
+
const anchorX = leftBoundary + boundedRatio(position.xRatio) * viewportWidth;
|
|
3329
|
+
const anchorY = topBoundary + boundedRatio(position.yRatio) * viewportHeight;
|
|
3330
|
+
const requestedLeft = position.horizontal === "end" ? anchorX - width : anchorX;
|
|
3331
|
+
const requestedTop = position.vertical === "end" ? anchorY - height : anchorY;
|
|
3332
|
+
const maximumLeft = Math.max(leftBoundary, rightBoundary - width);
|
|
3333
|
+
const maximumTop = Math.max(topBoundary, bottomBoundary - height);
|
|
3334
|
+
return Object.freeze({
|
|
3335
|
+
height,
|
|
3336
|
+
left: clamp(requestedLeft, leftBoundary, maximumLeft),
|
|
3337
|
+
top: clamp(requestedTop, topBoundary, maximumTop),
|
|
3338
|
+
width
|
|
3339
|
+
});
|
|
3340
|
+
}
|
|
3341
|
+
function snapFloatingSurfaceRect(rect, viewport, snapDistance) {
|
|
3342
|
+
const distance = finiteNonNegative(snapDistance);
|
|
3343
|
+
const width = finiteNonNegative(rect.width);
|
|
3344
|
+
const height = finiteNonNegative(rect.height);
|
|
3345
|
+
const normalized = normalizedViewport(viewport);
|
|
3346
|
+
const viewportRight = normalized.left + normalized.width;
|
|
3347
|
+
const viewportBottom = normalized.top + normalized.height;
|
|
3348
|
+
const maximumLeft = Math.max(normalized.left, viewportRight - width);
|
|
3349
|
+
const maximumTop = Math.max(normalized.top, viewportBottom - height);
|
|
3350
|
+
const requestedLeft = clamp(rect.left, normalized.left, maximumLeft);
|
|
3351
|
+
const requestedTop = clamp(rect.top, normalized.top, maximumTop);
|
|
3352
|
+
const leftDistance = Math.abs(requestedLeft - normalized.left);
|
|
3353
|
+
const rightDistance = Math.abs(viewportRight - (requestedLeft + width));
|
|
3354
|
+
const topDistance = Math.abs(requestedTop - normalized.top);
|
|
3355
|
+
const bottomDistance = Math.abs(viewportBottom - (requestedTop + height));
|
|
3356
|
+
const left = Math.min(leftDistance, rightDistance) <= distance ? leftDistance <= rightDistance ? normalized.left : viewportRight - width : requestedLeft;
|
|
3357
|
+
const top = Math.min(topDistance, bottomDistance) <= distance ? topDistance <= bottomDistance ? normalized.top : viewportBottom - height : requestedTop;
|
|
3358
|
+
return Object.freeze({ height, left, top, width });
|
|
3359
|
+
}
|
|
3360
|
+
function positionFromFloatingSurfaceRect(rect, viewport, previous) {
|
|
3361
|
+
const bounded = snapFloatingSurfaceRect(rect, viewport, 0);
|
|
3362
|
+
const centerX = bounded.left + bounded.width / 2;
|
|
3363
|
+
const centerY = bounded.top + bounded.height / 2;
|
|
3364
|
+
const viewportCenterX = viewport.left + finiteNonNegative(viewport.width) / 2;
|
|
3365
|
+
const viewportCenterY = viewport.top + finiteNonNegative(viewport.height) / 2;
|
|
3366
|
+
const horizontal = centerX === viewportCenterX ? previous.horizontal : centerX < viewportCenterX ? "start" : "end";
|
|
3367
|
+
const vertical = centerY === viewportCenterY ? previous.vertical : centerY < viewportCenterY ? "start" : "end";
|
|
3368
|
+
return positionFromAnchor(
|
|
3369
|
+
{
|
|
3370
|
+
x: horizontalAnchor(bounded, horizontal),
|
|
3371
|
+
y: verticalAnchor(bounded, vertical)
|
|
3372
|
+
},
|
|
3373
|
+
viewport,
|
|
3374
|
+
horizontal,
|
|
3375
|
+
vertical
|
|
3376
|
+
);
|
|
3377
|
+
}
|
|
3378
|
+
|
|
3379
|
+
// src/ui/floating-surface-controller.ts
|
|
3380
|
+
function finite(value, fallback = 0) {
|
|
3381
|
+
return Number.isFinite(value) ? value : fallback;
|
|
3382
|
+
}
|
|
3383
|
+
function distanceBetween(first, second) {
|
|
3384
|
+
return Math.hypot(first.x - second.x, first.y - second.y);
|
|
3385
|
+
}
|
|
3386
|
+
function isPrimaryPointer(event) {
|
|
3387
|
+
return event.button === 0 && event.isPrimary;
|
|
3388
|
+
}
|
|
3389
|
+
function surfaceSize(surface) {
|
|
3390
|
+
const rect = surface.getBoundingClientRect();
|
|
3391
|
+
return Object.freeze({
|
|
3392
|
+
height: Math.max(0, finite(rect.height)),
|
|
3393
|
+
width: Math.max(0, finite(rect.width))
|
|
3394
|
+
});
|
|
3395
|
+
}
|
|
3396
|
+
function requestFrame(window, callback) {
|
|
3397
|
+
if (typeof window.requestAnimationFrame === "function") {
|
|
3398
|
+
return window.requestAnimationFrame(callback);
|
|
3399
|
+
}
|
|
3400
|
+
return window.setTimeout(() => {
|
|
3401
|
+
callback(Date.now());
|
|
3402
|
+
}, 0);
|
|
3403
|
+
}
|
|
3404
|
+
function cancelFrame(window, frame) {
|
|
3405
|
+
if (typeof window.cancelAnimationFrame === "function") {
|
|
3406
|
+
window.cancelAnimationFrame(frame);
|
|
3407
|
+
return;
|
|
3408
|
+
}
|
|
3409
|
+
window.clearTimeout(frame);
|
|
3410
|
+
}
|
|
3411
|
+
function createFloatingSurfaceController(window, session, layout) {
|
|
3412
|
+
let position = session.load() ?? DEFAULT_FLOATING_SURFACE_POSITION;
|
|
3413
|
+
let drag;
|
|
3414
|
+
let frame;
|
|
3415
|
+
let suppressClickFor;
|
|
3416
|
+
let suppressClickTimer;
|
|
3417
|
+
let disposed = false;
|
|
3418
|
+
const surfaces = /* @__PURE__ */ new Set();
|
|
3419
|
+
const cleanup = /* @__PURE__ */ new Set();
|
|
3420
|
+
function viewport() {
|
|
3421
|
+
const visualViewport = window.visualViewport;
|
|
3422
|
+
const width = Math.max(0, finite(visualViewport?.width ?? window.innerWidth));
|
|
3423
|
+
const height = Math.max(0, finite(visualViewport?.height ?? window.innerHeight));
|
|
3424
|
+
const inset = width <= layout.compactViewportWidth ? layout.compactInset : layout.desktopInset;
|
|
3425
|
+
return Object.freeze({
|
|
3426
|
+
height: Math.max(0, height - inset * 2),
|
|
3427
|
+
left: finite(visualViewport?.offsetLeft ?? 0) + inset,
|
|
3428
|
+
top: finite(visualViewport?.offsetTop ?? 0) + inset,
|
|
3429
|
+
width: Math.max(0, width - inset * 2)
|
|
3430
|
+
});
|
|
3431
|
+
}
|
|
3432
|
+
function isCompact() {
|
|
3433
|
+
return viewport().width + layout.compactInset * 2 <= layout.compactViewportWidth;
|
|
3434
|
+
}
|
|
3435
|
+
function apply(surface) {
|
|
3436
|
+
if (surface.hidden) {
|
|
3437
|
+
return void 0;
|
|
3438
|
+
}
|
|
3439
|
+
if (surface.dataset.motionMorphing === "true" && surface.dataset.floatingPositioned === "true") {
|
|
3440
|
+
return void 0;
|
|
3441
|
+
}
|
|
3442
|
+
const size = surfaceSize(surface);
|
|
3443
|
+
if (size.width === 0 || size.height === 0) {
|
|
3444
|
+
return void 0;
|
|
3445
|
+
}
|
|
3446
|
+
const rect = resolveFloatingSurfaceRect(position, size, viewport());
|
|
3447
|
+
surface.style.left = `${String(rect.left)}px`;
|
|
3448
|
+
surface.style.top = `${String(rect.top)}px`;
|
|
3449
|
+
surface.style.right = "auto";
|
|
3450
|
+
surface.style.bottom = "auto";
|
|
3451
|
+
surface.dataset.floatingPositioned = "true";
|
|
3452
|
+
return rect;
|
|
3453
|
+
}
|
|
3454
|
+
function reconcile() {
|
|
3455
|
+
if (disposed) {
|
|
3456
|
+
return;
|
|
3457
|
+
}
|
|
3458
|
+
if (frame !== void 0) {
|
|
3459
|
+
cancelFrame(window, frame);
|
|
3460
|
+
frame = void 0;
|
|
3461
|
+
}
|
|
3462
|
+
for (const surface of surfaces) {
|
|
3463
|
+
apply(surface);
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
function requestReconcile() {
|
|
3467
|
+
if (disposed || frame !== void 0) {
|
|
3468
|
+
return;
|
|
3469
|
+
}
|
|
3470
|
+
frame = requestFrame(window, () => {
|
|
3471
|
+
frame = void 0;
|
|
3472
|
+
reconcile();
|
|
3473
|
+
});
|
|
3474
|
+
}
|
|
3475
|
+
function commit(nextPosition) {
|
|
3476
|
+
position = nextPosition;
|
|
3477
|
+
session.save(position);
|
|
3478
|
+
}
|
|
3479
|
+
function finishDrag(commitPosition) {
|
|
3480
|
+
const current = drag;
|
|
3481
|
+
if (current === void 0) {
|
|
3482
|
+
return;
|
|
3483
|
+
}
|
|
3484
|
+
drag = void 0;
|
|
3485
|
+
current.handle.dataset.dragging = "false";
|
|
3486
|
+
current.surface.dataset.dragging = "false";
|
|
3487
|
+
try {
|
|
3488
|
+
if (current.handle.hasPointerCapture(current.pointerId)) {
|
|
3489
|
+
current.handle.releasePointerCapture(current.pointerId);
|
|
3490
|
+
}
|
|
3491
|
+
} catch {
|
|
3492
|
+
}
|
|
3493
|
+
if (commitPosition) {
|
|
3494
|
+
const rect = apply(current.surface);
|
|
3495
|
+
if (rect !== void 0) {
|
|
3496
|
+
const snapped = snapFloatingSurfaceRect(
|
|
3497
|
+
rect,
|
|
3498
|
+
viewport(),
|
|
3499
|
+
layout.edgeSnapDistance
|
|
3500
|
+
);
|
|
3501
|
+
commit(positionFromFloatingSurfaceRect(snapped, viewport(), position));
|
|
3502
|
+
apply(current.surface);
|
|
3503
|
+
}
|
|
3504
|
+
} else {
|
|
3505
|
+
position = session.load() ?? DEFAULT_FLOATING_SURFACE_POSITION;
|
|
3506
|
+
reconcile();
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
function updateDrag(event) {
|
|
3510
|
+
const current = drag;
|
|
3511
|
+
if (current === void 0) {
|
|
3512
|
+
return;
|
|
3513
|
+
}
|
|
3514
|
+
if (event.pointerId !== current.pointerId) {
|
|
3515
|
+
return;
|
|
3516
|
+
}
|
|
3517
|
+
const pointer = Object.freeze({ x: event.clientX, y: event.clientY });
|
|
3518
|
+
const start = Object.freeze({ x: current.startX, y: current.startY });
|
|
3519
|
+
if (current.handle.dataset.dragging !== "true" && distanceBetween(pointer, start) < layout.dragActivationDistance) {
|
|
3520
|
+
return;
|
|
3521
|
+
}
|
|
3522
|
+
if (current.handle.dataset.dragging !== "true") {
|
|
3523
|
+
current.onDragStart?.();
|
|
3524
|
+
}
|
|
3525
|
+
current.handle.dataset.dragging = "true";
|
|
3526
|
+
current.surface.dataset.dragging = "true";
|
|
3527
|
+
position = positionFromAnchor(
|
|
3528
|
+
{
|
|
3529
|
+
x: pointer.x + current.anchorOffsetX,
|
|
3530
|
+
y: pointer.y + current.anchorOffsetY
|
|
3531
|
+
},
|
|
3532
|
+
viewport(),
|
|
3533
|
+
position.horizontal,
|
|
3534
|
+
position.vertical
|
|
3535
|
+
);
|
|
3536
|
+
requestReconcile();
|
|
3537
|
+
event.preventDefault();
|
|
3538
|
+
}
|
|
3539
|
+
function addListener(target2, type, listener, options) {
|
|
3540
|
+
target2.addEventListener(type, listener, options);
|
|
3541
|
+
cleanup.add(() => {
|
|
3542
|
+
target2.removeEventListener(type, listener, options);
|
|
3543
|
+
});
|
|
3544
|
+
}
|
|
3545
|
+
function attachDraggable(handle, surface, options = {}) {
|
|
3546
|
+
const onPointerDown = (event) => {
|
|
3547
|
+
if (disposed || drag !== void 0 || !isPrimaryPointer(event) || options.canStartDrag?.(event) === false) {
|
|
3548
|
+
return;
|
|
3549
|
+
}
|
|
3550
|
+
const rect = apply(surface) ?? surface.getBoundingClientRect();
|
|
3551
|
+
const anchorX = position.horizontal === "end" ? rect.left + rect.width : rect.left;
|
|
3552
|
+
const anchorY = position.vertical === "end" ? rect.top + rect.height : rect.top;
|
|
3553
|
+
drag = Object.freeze({
|
|
3554
|
+
anchorOffsetX: anchorX - event.clientX,
|
|
3555
|
+
anchorOffsetY: anchorY - event.clientY,
|
|
3556
|
+
handle,
|
|
3557
|
+
...options.onDragStart === void 0 ? {} : { onDragStart: options.onDragStart },
|
|
3558
|
+
pointerId: event.pointerId,
|
|
3559
|
+
startX: event.clientX,
|
|
3560
|
+
startY: event.clientY,
|
|
3561
|
+
suppressClickOnDrag: options.suppressClickOnDrag ?? false,
|
|
3562
|
+
surface
|
|
3563
|
+
});
|
|
3564
|
+
try {
|
|
3565
|
+
handle.setPointerCapture(event.pointerId);
|
|
3566
|
+
} catch {
|
|
3567
|
+
}
|
|
3568
|
+
};
|
|
3569
|
+
const onLostPointerCapture = (event) => {
|
|
3570
|
+
if (drag?.pointerId === event.pointerId) {
|
|
3571
|
+
finishDrag(handle.dataset.dragging === "true");
|
|
3572
|
+
}
|
|
3573
|
+
};
|
|
3574
|
+
const onClickCapture = (event) => {
|
|
3575
|
+
if (suppressClickFor !== handle) {
|
|
3576
|
+
return;
|
|
3577
|
+
}
|
|
3578
|
+
suppressClickFor = void 0;
|
|
3579
|
+
if (suppressClickTimer !== void 0) {
|
|
3580
|
+
window.clearTimeout(suppressClickTimer);
|
|
3581
|
+
suppressClickTimer = void 0;
|
|
3582
|
+
}
|
|
3583
|
+
event.preventDefault();
|
|
3584
|
+
event.stopImmediatePropagation();
|
|
3585
|
+
};
|
|
3586
|
+
addListener(handle, "pointerdown", (event) => {
|
|
3587
|
+
onPointerDown(event);
|
|
3588
|
+
});
|
|
3589
|
+
addListener(handle, "lostpointercapture", (event) => {
|
|
3590
|
+
onLostPointerCapture(event);
|
|
3591
|
+
});
|
|
3592
|
+
addListener(
|
|
3593
|
+
handle,
|
|
3594
|
+
"click",
|
|
3595
|
+
(event) => {
|
|
3596
|
+
onClickCapture(event);
|
|
3597
|
+
},
|
|
3598
|
+
true
|
|
3599
|
+
);
|
|
3600
|
+
}
|
|
3601
|
+
function reset() {
|
|
3602
|
+
finishDrag(false);
|
|
3603
|
+
position = DEFAULT_FLOATING_SURFACE_POSITION;
|
|
3604
|
+
session.clear();
|
|
3605
|
+
reconcile();
|
|
3606
|
+
}
|
|
3607
|
+
function cancelOnWindowBlur() {
|
|
3608
|
+
finishDrag(false);
|
|
3609
|
+
}
|
|
3610
|
+
function cancelOnEscape(event) {
|
|
3611
|
+
if (event.key !== "Escape" || drag === void 0) {
|
|
3612
|
+
return;
|
|
3613
|
+
}
|
|
3614
|
+
finishDrag(false);
|
|
3615
|
+
event.preventDefault();
|
|
3616
|
+
event.stopImmediatePropagation();
|
|
3617
|
+
}
|
|
3618
|
+
function endPointer(event) {
|
|
3619
|
+
if (drag?.pointerId !== event.pointerId) {
|
|
3620
|
+
return;
|
|
3621
|
+
}
|
|
3622
|
+
const current = drag;
|
|
3623
|
+
const moved = current.handle.dataset.dragging === "true";
|
|
3624
|
+
finishDrag(moved);
|
|
3625
|
+
if (moved && current.suppressClickOnDrag) {
|
|
3626
|
+
suppressClickFor = current.handle;
|
|
3627
|
+
suppressClickTimer = window.setTimeout(() => {
|
|
3628
|
+
suppressClickFor = void 0;
|
|
3629
|
+
suppressClickTimer = void 0;
|
|
3630
|
+
}, 0);
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3633
|
+
function cancelPointer(event) {
|
|
3634
|
+
if (drag?.pointerId === event.pointerId) {
|
|
3635
|
+
finishDrag(false);
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
addListener(window, "pointermove", (event) => {
|
|
3639
|
+
updateDrag(event);
|
|
3640
|
+
});
|
|
3641
|
+
addListener(window, "pointerup", (event) => {
|
|
3642
|
+
endPointer(event);
|
|
3643
|
+
});
|
|
3644
|
+
addListener(window, "pointercancel", (event) => {
|
|
3645
|
+
cancelPointer(event);
|
|
3646
|
+
});
|
|
3647
|
+
addListener(window, "resize", requestReconcile);
|
|
3648
|
+
addListener(window, "blur", cancelOnWindowBlur);
|
|
3649
|
+
addListener(
|
|
3650
|
+
window,
|
|
3651
|
+
"keydown",
|
|
3652
|
+
(event) => {
|
|
3653
|
+
cancelOnEscape(event);
|
|
3654
|
+
},
|
|
3655
|
+
true
|
|
3656
|
+
);
|
|
3657
|
+
window.visualViewport?.addEventListener("resize", requestReconcile);
|
|
3658
|
+
window.visualViewport?.addEventListener("scroll", requestReconcile);
|
|
3659
|
+
cleanup.add(
|
|
3660
|
+
() => window.visualViewport?.removeEventListener("resize", requestReconcile)
|
|
3661
|
+
);
|
|
3662
|
+
cleanup.add(
|
|
3663
|
+
() => window.visualViewport?.removeEventListener("scroll", requestReconcile)
|
|
3664
|
+
);
|
|
3665
|
+
return Object.freeze({
|
|
3666
|
+
attachDraggable,
|
|
3667
|
+
dispose() {
|
|
3668
|
+
if (disposed) {
|
|
3669
|
+
return;
|
|
3670
|
+
}
|
|
3671
|
+
disposed = true;
|
|
3672
|
+
finishDrag(false);
|
|
3673
|
+
if (frame !== void 0) {
|
|
3674
|
+
cancelFrame(window, frame);
|
|
3675
|
+
frame = void 0;
|
|
3676
|
+
}
|
|
3677
|
+
if (suppressClickTimer !== void 0) {
|
|
3678
|
+
window.clearTimeout(suppressClickTimer);
|
|
3679
|
+
suppressClickTimer = void 0;
|
|
3680
|
+
}
|
|
3681
|
+
suppressClickFor = void 0;
|
|
3682
|
+
for (const disposeListener of cleanup) {
|
|
3683
|
+
disposeListener();
|
|
3684
|
+
}
|
|
3685
|
+
cleanup.clear();
|
|
3686
|
+
surfaces.clear();
|
|
3687
|
+
},
|
|
3688
|
+
isCompact,
|
|
3689
|
+
reconcile,
|
|
3690
|
+
registerSurface(surface) {
|
|
3691
|
+
surfaces.add(surface);
|
|
3692
|
+
},
|
|
3693
|
+
requestReconcile,
|
|
3694
|
+
reset
|
|
3695
|
+
});
|
|
3696
|
+
}
|
|
3697
|
+
|
|
3698
|
+
// src/ui/runtime-view.ts
|
|
3699
|
+
var SUCCESS_SETTLE_MS = 1500;
|
|
3140
3700
|
function resolveStyleNonce(document) {
|
|
3141
3701
|
const nonces = new Set(
|
|
3142
3702
|
[...document.querySelectorAll("script[nonce]")].map((script) => script.nonce?.trim() ?? "").filter(Boolean)
|
|
@@ -3167,53 +3727,20 @@ function createStyles(document) {
|
|
|
3167
3727
|
--spotpatch-success: #34d399;
|
|
3168
3728
|
--spotpatch-warning: #f59e0b;
|
|
3169
3729
|
--spotpatch-text-on-accent: #0b0b12;
|
|
3170
|
-
--spotpatch-radius-panel: 16px;
|
|
3171
3730
|
--spotpatch-radius-card: 10px;
|
|
3172
|
-
--spotpatch-shadow-panel: 0 30px 60px -20px rgb(0 0 0 / 70%);
|
|
3173
|
-
color-scheme: dark;
|
|
3174
3731
|
color: var(--spotpatch-text);
|
|
3175
3732
|
font-family: Inter, "SF Pro Display", "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
3176
3733
|
font-size: 14px;
|
|
3177
3734
|
line-height: 1.5;
|
|
3178
|
-
text-rendering: optimizeLegibility;
|
|
3179
|
-
-webkit-font-smoothing: antialiased;
|
|
3180
3735
|
}
|
|
3181
3736
|
[hidden] { display: none !important; }
|
|
3182
3737
|
button, textarea, select { font: inherit; }
|
|
3183
|
-
|
|
3184
|
-
.spotpatch-trigger {
|
|
3738
|
+
.spotpatch-floating-surface {
|
|
3185
3739
|
position: fixed;
|
|
3186
|
-
right:
|
|
3187
|
-
bottom:
|
|
3740
|
+
right: ${String(FLOATING_SURFACE_LAYOUT.desktopInset)}px;
|
|
3741
|
+
bottom: ${String(FLOATING_SURFACE_LAYOUT.desktopInset)}px;
|
|
3188
3742
|
z-index: ${String(UI_Z_INDEX.controls)};
|
|
3189
|
-
|
|
3190
|
-
align-items: center;
|
|
3191
|
-
gap: 10px;
|
|
3192
|
-
min-height: 44px;
|
|
3193
|
-
border: 1px solid rgb(255 255 255 / 12%);
|
|
3194
|
-
border-radius: 999px;
|
|
3195
|
-
padding: 10px 17px;
|
|
3196
|
-
color: #f8fafc;
|
|
3197
|
-
background: #171b23;
|
|
3198
|
-
box-shadow: 0 12px 34px rgb(0 0 0 / 25%), inset 0 1px rgb(255 255 255 / 5%);
|
|
3199
|
-
cursor: pointer;
|
|
3200
|
-
font-size: 14px;
|
|
3201
|
-
font-weight: 650;
|
|
3202
|
-
transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
|
|
3203
|
-
}
|
|
3204
|
-
.spotpatch-trigger::before {
|
|
3205
|
-
width: 9px;
|
|
3206
|
-
height: 9px;
|
|
3207
|
-
border-radius: 999px;
|
|
3208
|
-
background: var(--spotpatch-accent);
|
|
3209
|
-
box-shadow: 0 0 0 4px rgb(99 102 241 / 10%);
|
|
3210
|
-
content: "";
|
|
3211
|
-
}
|
|
3212
|
-
.spotpatch-trigger:hover { transform: translateY(-1px); border-color: rgb(129 140 248 / 52%); }
|
|
3213
|
-
.spotpatch-trigger[aria-pressed="true"] {
|
|
3214
|
-
border-color: rgb(124 58 237 / 55%);
|
|
3215
|
-
background: #24203b;
|
|
3216
|
-
box-shadow: 0 14px 42px rgb(76 29 149 / 24%), inset 0 1px rgb(255 255 255 / 10%);
|
|
3743
|
+
isolation: isolate;
|
|
3217
3744
|
}
|
|
3218
3745
|
.spotpatch-highlight {
|
|
3219
3746
|
position: fixed;
|
|
@@ -3282,82 +3809,28 @@ function createStyles(document) {
|
|
|
3282
3809
|
background: #5546dc;
|
|
3283
3810
|
}
|
|
3284
3811
|
.spotpatch-dialog {
|
|
3285
|
-
|
|
3286
|
-
--spotpatch-anchor-y: 50%;
|
|
3287
|
-
position: fixed;
|
|
3288
|
-
top: 16px;
|
|
3289
|
-
left: 16px;
|
|
3290
|
-
z-index: ${String(UI_Z_INDEX.controls)};
|
|
3812
|
+
position: relative;
|
|
3291
3813
|
box-sizing: border-box;
|
|
3292
|
-
width: min(${String(
|
|
3293
|
-
color: #edf0f7;
|
|
3814
|
+
width: min(${String(FLOATING_SURFACE_LAYOUT.workbenchMaxWidth)}px, calc(100vw - ${String(FLOATING_SURFACE_LAYOUT.desktopInset * 2)}px));
|
|
3294
3815
|
outline: none;
|
|
3295
|
-
filter: drop-shadow(var(--spotpatch-shadow-panel));
|
|
3296
3816
|
}
|
|
3297
|
-
.spotpatch-anchor {
|
|
3298
|
-
position: absolute;
|
|
3299
|
-
z-index: 0;
|
|
3300
|
-
width: 14px;
|
|
3301
|
-
height: 14px;
|
|
3302
|
-
border: 1px solid rgb(255 255 255 / 12%);
|
|
3303
|
-
background: var(--spotpatch-bg);
|
|
3304
|
-
transform: rotate(45deg);
|
|
3305
|
-
}
|
|
3306
|
-
.spotpatch-dialog[data-placement="above"] .spotpatch-anchor {
|
|
3307
|
-
bottom: -6px;
|
|
3308
|
-
left: calc(var(--spotpatch-anchor-x) - 7px);
|
|
3309
|
-
border-top: 0;
|
|
3310
|
-
border-left: 0;
|
|
3311
|
-
}
|
|
3312
|
-
.spotpatch-dialog[data-placement="below"] .spotpatch-anchor {
|
|
3313
|
-
top: -6px;
|
|
3314
|
-
left: calc(var(--spotpatch-anchor-x) - 7px);
|
|
3315
|
-
border-right: 0;
|
|
3316
|
-
border-bottom: 0;
|
|
3317
|
-
}
|
|
3318
|
-
.spotpatch-dialog[data-placement="left"] .spotpatch-anchor {
|
|
3319
|
-
top: calc(var(--spotpatch-anchor-y) - 7px);
|
|
3320
|
-
right: -6px;
|
|
3321
|
-
border-bottom: 0;
|
|
3322
|
-
border-left: 0;
|
|
3323
|
-
}
|
|
3324
|
-
.spotpatch-dialog[data-placement="right"] .spotpatch-anchor {
|
|
3325
|
-
top: calc(var(--spotpatch-anchor-y) - 7px);
|
|
3326
|
-
left: -6px;
|
|
3327
|
-
border-top: 0;
|
|
3328
|
-
border-right: 0;
|
|
3329
|
-
}
|
|
3330
|
-
.spotpatch-dialog[data-placement="center"] .spotpatch-anchor,
|
|
3331
|
-
.spotpatch-dialog[data-placement="viewport"] .spotpatch-anchor { display: none; }
|
|
3332
3817
|
.spotpatch-shell {
|
|
3333
3818
|
position: relative;
|
|
3334
3819
|
z-index: 1;
|
|
3335
3820
|
display: flex;
|
|
3336
3821
|
box-sizing: border-box;
|
|
3337
|
-
max-height: min(${String(
|
|
3822
|
+
max-height: min(${String(FLOATING_SURFACE_LAYOUT.workbenchMaxHeight)}px, calc(100vh - ${String(FLOATING_SURFACE_LAYOUT.desktopInset * 2)}px));
|
|
3338
3823
|
overflow: hidden;
|
|
3339
3824
|
flex-direction: column;
|
|
3340
|
-
border: 1px solid var(--spotpatch-border);
|
|
3341
|
-
border-radius: var(--spotpatch-radius-panel);
|
|
3342
|
-
background: var(--spotpatch-bg);
|
|
3343
|
-
box-shadow: inset 0 1px rgb(255 255 255 / 5%), 0 0 60px -32px rgb(139 123 255 / 20%);
|
|
3344
|
-
}
|
|
3345
|
-
.spotpatch-shell::before {
|
|
3346
|
-
position: absolute;
|
|
3347
|
-
z-index: 2;
|
|
3348
|
-
top: 0;
|
|
3349
|
-
right: 20%;
|
|
3350
|
-
left: 20%;
|
|
3351
|
-
height: 1px;
|
|
3352
|
-
background: linear-gradient(90deg, transparent, var(--spotpatch-accent), var(--spotpatch-accent-cyan), transparent);
|
|
3353
|
-
content: "";
|
|
3354
|
-
opacity: .65;
|
|
3355
|
-
pointer-events: none;
|
|
3356
3825
|
}
|
|
3357
3826
|
.spotpatch-header {
|
|
3358
3827
|
position: relative;
|
|
3359
3828
|
padding: 0 18px 14px;
|
|
3360
3829
|
}
|
|
3830
|
+
.spotpatch-header[data-spotpatch-drag-handle] { cursor: grab; touch-action: none; user-select: none; }
|
|
3831
|
+
.spotpatch-header[data-dragging="true"] { cursor: grabbing; }
|
|
3832
|
+
.spotpatch-header button,
|
|
3833
|
+
.spotpatch-header a { cursor: pointer; user-select: auto; }
|
|
3361
3834
|
.spotpatch-brand-row {
|
|
3362
3835
|
display: flex;
|
|
3363
3836
|
align-items: center;
|
|
@@ -3381,18 +3854,6 @@ function createStyles(document) {
|
|
|
3381
3854
|
filter: drop-shadow(0 6px 12px rgb(76 29 149 / 22%));
|
|
3382
3855
|
}
|
|
3383
3856
|
.spotpatch-brand-copy { display: grid; min-width: 0; gap: 1px; }
|
|
3384
|
-
.spotpatch-brand-name {
|
|
3385
|
-
color: #fff;
|
|
3386
|
-
font-size: 13.5px;
|
|
3387
|
-
font-weight: 680;
|
|
3388
|
-
letter-spacing: -.01em;
|
|
3389
|
-
}
|
|
3390
|
-
.spotpatch-brand-context {
|
|
3391
|
-
color: #8e98aa;
|
|
3392
|
-
font-size: 10.5px;
|
|
3393
|
-
font-weight: 560;
|
|
3394
|
-
letter-spacing: .02em;
|
|
3395
|
-
}
|
|
3396
3857
|
.spotpatch-header-controls {
|
|
3397
3858
|
display: inline-flex;
|
|
3398
3859
|
align-items: center;
|
|
@@ -3401,6 +3862,7 @@ function createStyles(document) {
|
|
|
3401
3862
|
}
|
|
3402
3863
|
.spotpatch-repository,
|
|
3403
3864
|
.spotpatch-locale,
|
|
3865
|
+
.spotpatch-reset-position,
|
|
3404
3866
|
.spotpatch-close {
|
|
3405
3867
|
height: 27px;
|
|
3406
3868
|
border: 1px solid rgb(255 255 255 / 11%);
|
|
@@ -3424,6 +3886,16 @@ function createStyles(document) {
|
|
|
3424
3886
|
font-size: 12px;
|
|
3425
3887
|
font-weight: 650;
|
|
3426
3888
|
}
|
|
3889
|
+
.spotpatch-reset-position {
|
|
3890
|
+
display: inline-grid;
|
|
3891
|
+
width: 27px;
|
|
3892
|
+
padding: 0;
|
|
3893
|
+
place-items: center;
|
|
3894
|
+
color: #c5cad5;
|
|
3895
|
+
cursor: pointer;
|
|
3896
|
+
font-size: 15px;
|
|
3897
|
+
line-height: 1;
|
|
3898
|
+
}
|
|
3427
3899
|
.spotpatch-close {
|
|
3428
3900
|
display: inline-grid;
|
|
3429
3901
|
width: 27px;
|
|
@@ -3437,21 +3909,8 @@ function createStyles(document) {
|
|
|
3437
3909
|
}
|
|
3438
3910
|
.spotpatch-close:hover,
|
|
3439
3911
|
.spotpatch-locale:hover,
|
|
3912
|
+
.spotpatch-reset-position:hover,
|
|
3440
3913
|
.spotpatch-repository:hover { border-color: rgb(129 112 247 / 45%); color: #fff; background: rgb(109 93 246 / 10%); }
|
|
3441
|
-
.spotpatch-title {
|
|
3442
|
-
margin: 0;
|
|
3443
|
-
color: #fff;
|
|
3444
|
-
font-size: 18px;
|
|
3445
|
-
font-weight: 680;
|
|
3446
|
-
letter-spacing: -.015em;
|
|
3447
|
-
}
|
|
3448
|
-
.spotpatch-subtitle {
|
|
3449
|
-
max-width: 390px;
|
|
3450
|
-
margin: 4px 0 0;
|
|
3451
|
-
color: var(--spotpatch-text-secondary);
|
|
3452
|
-
font-size: 12.5px;
|
|
3453
|
-
line-height: 1.5;
|
|
3454
|
-
}
|
|
3455
3914
|
.spotpatch-target-row {
|
|
3456
3915
|
display: flex;
|
|
3457
3916
|
align-items: center;
|
|
@@ -3815,6 +4274,7 @@ function createStyles(document) {
|
|
|
3815
4274
|
.spotpatch-target-open:focus-visible,
|
|
3816
4275
|
.spotpatch-target-remove:focus-visible,
|
|
3817
4276
|
.spotpatch-close:focus-visible,
|
|
4277
|
+
.spotpatch-reset-position:focus-visible,
|
|
3818
4278
|
.spotpatch-trigger:focus-visible,
|
|
3819
4279
|
.spotpatch-target-select:focus-visible,
|
|
3820
4280
|
.spotpatch-target-editor textarea:focus-visible,
|
|
@@ -3839,8 +4299,8 @@ function createStyles(document) {
|
|
|
3839
4299
|
.spotpatch-diagnostics > summary::before { transition: none; }
|
|
3840
4300
|
}
|
|
3841
4301
|
@media (max-width: 520px) {
|
|
3842
|
-
.spotpatch-dialog {
|
|
3843
|
-
.spotpatch-shell { max-height: calc(
|
|
4302
|
+
.spotpatch-dialog { width: calc(100vw - 16px); }
|
|
4303
|
+
.spotpatch-shell { max-height: calc(100dvh - 16px); }
|
|
3844
4304
|
.spotpatch-header, .spotpatch-body { padding-left: 14px; padding-right: 14px; }
|
|
3845
4305
|
.spotpatch-brand-row { margin-right: -14px; margin-left: -14px; padding-right: 14px; padding-left: 14px; }
|
|
3846
4306
|
.spotpatch-actions { padding-right: 14px; padding-left: 14px; }
|
|
@@ -3856,6 +4316,38 @@ function summaryLine(summary, prefix) {
|
|
|
3856
4316
|
const line = summary.split("\n").find((candidate) => candidate.startsWith(`${prefix}: `));
|
|
3857
4317
|
return line?.slice(prefix.length + 2).trim();
|
|
3858
4318
|
}
|
|
4319
|
+
function startsOnInteractiveControl(event) {
|
|
4320
|
+
const target2 = event.target;
|
|
4321
|
+
return target2 instanceof Element && target2.closest(
|
|
4322
|
+
"a, button, input, select, textarea, summary, [contenteditable='true']"
|
|
4323
|
+
) !== null;
|
|
4324
|
+
}
|
|
4325
|
+
function createFallbackExecutionIsland(document) {
|
|
4326
|
+
const root = createButton(document, "", "spotpatch-execution-island");
|
|
4327
|
+
root.hidden = true;
|
|
4328
|
+
root.setAttribute("aria-hidden", "true");
|
|
4329
|
+
const logo = createBrandMark(
|
|
4330
|
+
document,
|
|
4331
|
+
void 0,
|
|
4332
|
+
"spotpatch-fallback-execution-island"
|
|
4333
|
+
);
|
|
4334
|
+
logo.classList.add("spotpatch-execution-logo");
|
|
4335
|
+
const copy = createMarkedElement(document, "span");
|
|
4336
|
+
root.append(logo, copy);
|
|
4337
|
+
return Object.freeze({
|
|
4338
|
+
canExpand: () => false,
|
|
4339
|
+
isExpanded: () => false,
|
|
4340
|
+
root,
|
|
4341
|
+
setExpanded: () => void 0,
|
|
4342
|
+
render(projection) {
|
|
4343
|
+
const text2 = [projection.headline, projection.action, projection.meta].filter((value) => value.length > 0).join(" \xB7 ");
|
|
4344
|
+
copy.textContent = text2;
|
|
4345
|
+
root.setAttribute("aria-label", text2);
|
|
4346
|
+
},
|
|
4347
|
+
dispose() {
|
|
4348
|
+
}
|
|
4349
|
+
});
|
|
4350
|
+
}
|
|
3859
4351
|
function createUnavailableDataFlowPanel(document, changesRoot, diagnosticsRoot) {
|
|
3860
4352
|
changesRoot.append(diagnosticsRoot);
|
|
3861
4353
|
return Object.freeze({
|
|
@@ -3867,12 +4359,38 @@ function createUnavailableDataFlowPanel(document, changesRoot, diagnosticsRoot)
|
|
|
3867
4359
|
resetView: () => void 0
|
|
3868
4360
|
});
|
|
3869
4361
|
}
|
|
3870
|
-
function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: false }), localePreference = "auto", dataFlowEnabled = false, externalAgentEnabled = false, framework = "vite", sessionId = "") {
|
|
4362
|
+
function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: false }), localePreference = "auto", dataFlowEnabled = false, externalAgentEnabled = false, framework = "vite", sessionId = "", contextualAskEnabled = false) {
|
|
3871
4363
|
const localizer = createUiLocalizer(document, localePreference);
|
|
4364
|
+
const associatedWindow = document.defaultView;
|
|
4365
|
+
if (associatedWindow === null) {
|
|
4366
|
+
throw new Error("SpotPatch requires a document with an associated window.");
|
|
4367
|
+
}
|
|
4368
|
+
const runtimeWindow = associatedWindow;
|
|
4369
|
+
const floatingSurface = createFloatingSurfaceController(
|
|
4370
|
+
runtimeWindow,
|
|
4371
|
+
createFloatingSurfaceSession(runtimeWindow, sessionId),
|
|
4372
|
+
FLOATING_SURFACE_LAYOUT
|
|
4373
|
+
);
|
|
3872
4374
|
let messages = localizer.messages();
|
|
4375
|
+
let currentStatus = "idle";
|
|
4376
|
+
let contextualAskMode = "change";
|
|
4377
|
+
let contextualAskTitle = "";
|
|
4378
|
+
let contextualAskSubtitle = "";
|
|
4379
|
+
let plannerVisible = false;
|
|
4380
|
+
let executionSuppressed = false;
|
|
4381
|
+
let executionProjection;
|
|
4382
|
+
let pendingAgentMotion;
|
|
4383
|
+
let successSettleKey;
|
|
4384
|
+
let settledSuccessKey;
|
|
4385
|
+
let successSettleTimer;
|
|
4386
|
+
let observedExecutionStartedAt;
|
|
3873
4387
|
const host = document.createElement("spotpatch-root");
|
|
3874
4388
|
host.setAttribute(UI_MARKER_ATTRIBUTE, "");
|
|
3875
4389
|
const shadowRoot = host.attachShadow({ mode: "open" });
|
|
4390
|
+
const floatingSurfaceRoot = createMarkedElement(document, "div");
|
|
4391
|
+
floatingSurfaceRoot.className = "spotpatch-floating-surface";
|
|
4392
|
+
floatingSurfaceRoot.dataset.scene = "pill";
|
|
4393
|
+
floatingSurfaceRoot.dataset.tone = "neutral";
|
|
3876
4394
|
const triggerButton = createButton(
|
|
3877
4395
|
document,
|
|
3878
4396
|
messages.trigger.select,
|
|
@@ -3880,6 +4398,10 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3880
4398
|
);
|
|
3881
4399
|
triggerButton.title = messages.trigger.title(shortcut);
|
|
3882
4400
|
triggerButton.setAttribute("aria-pressed", "false");
|
|
4401
|
+
const motionExtension = getFloatingSurfaceMotionExtension();
|
|
4402
|
+
const motionExecutionIsland = motionExtension?.createExecutionIsland(document);
|
|
4403
|
+
const executionIslandView = motionExecutionIsland ?? createFallbackExecutionIsland(document);
|
|
4404
|
+
const executionIsland = executionIslandView.root;
|
|
3883
4405
|
const highlight = createMarkedElement(document, "div");
|
|
3884
4406
|
highlight.className = "spotpatch-highlight";
|
|
3885
4407
|
highlight.hidden = true;
|
|
@@ -3893,16 +4415,13 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3893
4415
|
dialog.className = "spotpatch-dialog";
|
|
3894
4416
|
dialog.hidden = true;
|
|
3895
4417
|
dialog.tabIndex = -1;
|
|
3896
|
-
dialog.dataset.placement = "viewport";
|
|
3897
4418
|
dialog.setAttribute("role", "dialog");
|
|
3898
4419
|
dialog.setAttribute("aria-labelledby", "spotpatch-selection-title");
|
|
3899
|
-
const anchor = createMarkedElement(document, "span");
|
|
3900
|
-
anchor.className = "spotpatch-anchor";
|
|
3901
|
-
anchor.setAttribute("aria-hidden", "true");
|
|
3902
4420
|
const shell = createMarkedElement(document, "div");
|
|
3903
4421
|
shell.className = "spotpatch-shell";
|
|
3904
4422
|
const header = createMarkedElement(document, "header");
|
|
3905
4423
|
header.className = "spotpatch-header";
|
|
4424
|
+
header.setAttribute("data-spotpatch-drag-handle", "");
|
|
3906
4425
|
const brandRow = createMarkedElement(document, "div");
|
|
3907
4426
|
brandRow.className = "spotpatch-brand-row";
|
|
3908
4427
|
const brand = createMarkedElement(document, "div");
|
|
@@ -3923,8 +4442,9 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3923
4442
|
repositoryLink.target = "_blank";
|
|
3924
4443
|
repositoryLink.rel = "noopener noreferrer";
|
|
3925
4444
|
const localeButton = createButton(document, "", "spotpatch-locale");
|
|
4445
|
+
const resetPositionButton = createButton(document, "\u2316", "spotpatch-reset-position");
|
|
3926
4446
|
const closeButton = createButton(document, "\xD7", "spotpatch-close");
|
|
3927
|
-
headerControls.append(repositoryLink, localeButton, closeButton);
|
|
4447
|
+
headerControls.append(repositoryLink, localeButton, resetPositionButton, closeButton);
|
|
3928
4448
|
brandRow.append(brand, headerControls);
|
|
3929
4449
|
const title = createMarkedElement(document, "h2");
|
|
3930
4450
|
title.id = "spotpatch-selection-title";
|
|
@@ -3984,13 +4504,20 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3984
4504
|
diagnostics.append(diagnosticsLabel, summary);
|
|
3985
4505
|
const agentPanel = createAgentPanel(document, ai, localizer);
|
|
3986
4506
|
const changesPanel = createMarkedElement(document, "div");
|
|
4507
|
+
function requestFloatingSurfaceLayout() {
|
|
4508
|
+
if (plannerVisible) {
|
|
4509
|
+
floatingSurface.requestReconcile();
|
|
4510
|
+
}
|
|
4511
|
+
}
|
|
3987
4512
|
const externalHandoffPanel = externalAgentEnabled ? getExternalHandoffExtension()?.createPanel(
|
|
3988
4513
|
document,
|
|
3989
4514
|
framework,
|
|
3990
4515
|
localizer.locale,
|
|
3991
4516
|
sessionId,
|
|
3992
4517
|
localizer.subscribe,
|
|
3993
|
-
|
|
4518
|
+
requestFloatingSurfaceLayout,
|
|
4519
|
+
renderExternalDispatch,
|
|
4520
|
+
renderExternalControl
|
|
3994
4521
|
) : void 0;
|
|
3995
4522
|
changesPanel.append(
|
|
3996
4523
|
targetsPanel,
|
|
@@ -4003,7 +4530,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4003
4530
|
localizer.locale,
|
|
4004
4531
|
changesPanel,
|
|
4005
4532
|
diagnostics,
|
|
4006
|
-
|
|
4533
|
+
requestFloatingSurfaceLayout
|
|
4007
4534
|
) ?? createUnavailableDataFlowPanel(document, changesPanel, diagnostics);
|
|
4008
4535
|
selectionPanel.append(dataFlowPanel.root);
|
|
4009
4536
|
const previewPanel = createMarkedElement(document, "div");
|
|
@@ -4058,15 +4585,40 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4058
4585
|
backButton
|
|
4059
4586
|
);
|
|
4060
4587
|
actions.append(editorFeedback, secondaryActions, primaryActions);
|
|
4588
|
+
const contextualAskPanel = contextualAskEnabled ? getContextualAskExtension()?.createPanel({
|
|
4589
|
+
document,
|
|
4590
|
+
locale: localizer.locale,
|
|
4591
|
+
subscribeLocale: localizer.subscribe,
|
|
4592
|
+
changeRoot: dataFlowPanel.root,
|
|
4593
|
+
changeActions: actions,
|
|
4594
|
+
announce,
|
|
4595
|
+
onModeChange(mode, askTitle, askSubtitle) {
|
|
4596
|
+
contextualAskMode = mode;
|
|
4597
|
+
contextualAskTitle = askTitle;
|
|
4598
|
+
contextualAskSubtitle = askSubtitle;
|
|
4599
|
+
if (host.isConnected) renderPanelStatus(currentStatus);
|
|
4600
|
+
},
|
|
4601
|
+
onExecutionChange(projection) {
|
|
4602
|
+
executionProjection = projection;
|
|
4603
|
+
executionSuppressed = false;
|
|
4604
|
+
renderFloatingSurfaceMotion();
|
|
4605
|
+
},
|
|
4606
|
+
onViewChange: requestFloatingSurfaceLayout
|
|
4607
|
+
}) : void 0;
|
|
4608
|
+
if (contextualAskPanel !== void 0) {
|
|
4609
|
+
selectionPanel.prepend(contextualAskPanel.root);
|
|
4610
|
+
}
|
|
4061
4611
|
shell.append(header, body, actions);
|
|
4062
|
-
dialog.append(
|
|
4612
|
+
dialog.append(shell);
|
|
4063
4613
|
const liveRegion = createMarkedElement(document, "div");
|
|
4064
4614
|
liveRegion.className = "spotpatch-live";
|
|
4065
4615
|
liveRegion.setAttribute("aria-live", "polite");
|
|
4066
4616
|
liveRegion.setAttribute("aria-atomic", "true");
|
|
4067
4617
|
const styles2 = [
|
|
4068
4618
|
createStyles(document),
|
|
4619
|
+
...motionExtension === void 0 ? [] : [motionExtension.createStyles(document)],
|
|
4069
4620
|
dataFlowPanel.styles,
|
|
4621
|
+
...contextualAskPanel === void 0 ? [] : [contextualAskPanel.styles],
|
|
4070
4622
|
...externalHandoffPanel === void 0 ? [] : [externalHandoffPanel.styles]
|
|
4071
4623
|
];
|
|
4072
4624
|
const styleNonce = resolveStyleNonce(document);
|
|
@@ -4079,14 +4631,38 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4079
4631
|
...styles2,
|
|
4080
4632
|
selectionHighlights,
|
|
4081
4633
|
highlight,
|
|
4082
|
-
|
|
4083
|
-
triggerButton,
|
|
4634
|
+
floatingSurfaceRoot,
|
|
4084
4635
|
liveRegion
|
|
4085
4636
|
);
|
|
4637
|
+
floatingSurfaceRoot.append(triggerButton, dialog, executionIsland);
|
|
4086
4638
|
document.documentElement.append(host);
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4639
|
+
floatingSurface.registerSurface(floatingSurfaceRoot);
|
|
4640
|
+
const motionController = motionExtension === void 0 || motionExecutionIsland === void 0 ? void 0 : motionExtension.createController(
|
|
4641
|
+
document,
|
|
4642
|
+
Object.freeze({
|
|
4643
|
+
execution: motionExecutionIsland.elements,
|
|
4644
|
+
pill: triggerButton,
|
|
4645
|
+
planner: dialog,
|
|
4646
|
+
surface: floatingSurfaceRoot
|
|
4647
|
+
}),
|
|
4648
|
+
floatingSurface.reconcile
|
|
4649
|
+
);
|
|
4650
|
+
const cancelMotionOnDrag = () => {
|
|
4651
|
+
motionController?.cancel();
|
|
4652
|
+
};
|
|
4653
|
+
floatingSurface.attachDraggable(triggerButton, floatingSurfaceRoot, {
|
|
4654
|
+
onDragStart: cancelMotionOnDrag,
|
|
4655
|
+
suppressClickOnDrag: true
|
|
4656
|
+
});
|
|
4657
|
+
floatingSurface.attachDraggable(header, floatingSurfaceRoot, {
|
|
4658
|
+
canStartDrag: (event) => !floatingSurface.isCompact() && !startsOnInteractiveControl(event),
|
|
4659
|
+
onDragStart: cancelMotionOnDrag
|
|
4660
|
+
});
|
|
4661
|
+
floatingSurface.attachDraggable(executionIsland, floatingSurfaceRoot, {
|
|
4662
|
+
onDragStart: cancelMotionOnDrag,
|
|
4663
|
+
suppressClickOnDrag: true
|
|
4664
|
+
});
|
|
4665
|
+
floatingSurface.reconcile();
|
|
4090
4666
|
let currentCanOpenEditor = false;
|
|
4091
4667
|
let currentCanPreview = false;
|
|
4092
4668
|
let currentSummaryText = "";
|
|
@@ -4101,12 +4677,274 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4101
4677
|
page: Object.freeze({ status: dataFlowEnabled ? "idle" : "disabled" }),
|
|
4102
4678
|
observationCount: 0
|
|
4103
4679
|
});
|
|
4680
|
+
function currentTargetSummary() {
|
|
4681
|
+
const target2 = currentTargets.find((candidate) => candidate.active);
|
|
4682
|
+
return target2 === void 0 ? Object.freeze({
|
|
4683
|
+
label: messages.context.selectedElement,
|
|
4684
|
+
source: ""
|
|
4685
|
+
}) : Object.freeze({ label: target2.label, source: target2.source });
|
|
4686
|
+
}
|
|
4687
|
+
function currentTargetContext() {
|
|
4688
|
+
const target2 = currentTargetSummary();
|
|
4689
|
+
return target2.source.length === 0 ? target2.label : `${target2.label} \xB7 ${target2.source}`;
|
|
4690
|
+
}
|
|
4691
|
+
function beginObservedExecution() {
|
|
4692
|
+
observedExecutionStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4693
|
+
return observedExecutionStartedAt;
|
|
4694
|
+
}
|
|
4695
|
+
function observedExecutionStart() {
|
|
4696
|
+
return observedExecutionStartedAt ?? beginObservedExecution();
|
|
4697
|
+
}
|
|
4698
|
+
function clearSuccessSettle(resetKeys) {
|
|
4699
|
+
if (successSettleTimer !== void 0) {
|
|
4700
|
+
runtimeWindow.clearTimeout(successSettleTimer);
|
|
4701
|
+
successSettleTimer = void 0;
|
|
4702
|
+
}
|
|
4703
|
+
if (resetKeys) {
|
|
4704
|
+
successSettleKey = void 0;
|
|
4705
|
+
settledSuccessKey = void 0;
|
|
4706
|
+
}
|
|
4707
|
+
}
|
|
4708
|
+
function showSuccessUntilSettled(key) {
|
|
4709
|
+
if (settledSuccessKey === key) return false;
|
|
4710
|
+
if (successSettleKey === key) return true;
|
|
4711
|
+
clearSuccessSettle(false);
|
|
4712
|
+
successSettleKey = key;
|
|
4713
|
+
successSettleTimer = runtimeWindow.setTimeout(() => {
|
|
4714
|
+
successSettleTimer = void 0;
|
|
4715
|
+
if (!host.isConnected) return;
|
|
4716
|
+
settledSuccessKey = key;
|
|
4717
|
+
executionProjection = void 0;
|
|
4718
|
+
observedExecutionStartedAt = void 0;
|
|
4719
|
+
executionSuppressed = false;
|
|
4720
|
+
plannerVisible = false;
|
|
4721
|
+
renderFloatingSurfaceMotion();
|
|
4722
|
+
}, SUCCESS_SETTLE_MS);
|
|
4723
|
+
return true;
|
|
4724
|
+
}
|
|
4725
|
+
function externalAgentIdentity(kind) {
|
|
4726
|
+
return kind.startsWith("claude") ? messages.execution.claude : kind.startsWith("codex") ? messages.execution.codex : kind;
|
|
4727
|
+
}
|
|
4728
|
+
function projectAgentActivity(item) {
|
|
4729
|
+
return Object.freeze({
|
|
4730
|
+
...item.detail === void 0 ? {} : { detail: item.detail },
|
|
4731
|
+
key: item.key,
|
|
4732
|
+
kind: item.kind,
|
|
4733
|
+
label: messages.execution.activityLane(item.kind, item.detail),
|
|
4734
|
+
state: item.state
|
|
4735
|
+
});
|
|
4736
|
+
}
|
|
4737
|
+
function motionActivity(key, kind, detail, state = "active") {
|
|
4738
|
+
return Object.freeze({
|
|
4739
|
+
...detail === void 0 ? {} : { detail },
|
|
4740
|
+
key,
|
|
4741
|
+
kind,
|
|
4742
|
+
label: messages.execution.activityLane(kind, detail),
|
|
4743
|
+
state
|
|
4744
|
+
});
|
|
4745
|
+
}
|
|
4746
|
+
function renderFloatingSurfaceMotion() {
|
|
4747
|
+
const capturing = currentStatus === "inspecting";
|
|
4748
|
+
const pillActive = !plannerVisible || capturing;
|
|
4749
|
+
const projection = pillActive ? {
|
|
4750
|
+
scene: capturing ? "capturing" : "pill",
|
|
4751
|
+
tone: capturing ? "capturing" : "neutral",
|
|
4752
|
+
headline: triggerButton.textContent,
|
|
4753
|
+
action: "",
|
|
4754
|
+
meta: "",
|
|
4755
|
+
recentActivities: Object.freeze([])
|
|
4756
|
+
} : !executionSuppressed && executionProjection !== void 0 ? executionProjection : {
|
|
4757
|
+
scene: "planner",
|
|
4758
|
+
tone: "ready",
|
|
4759
|
+
headline: messages.dialog.editTitle,
|
|
4760
|
+
action: messages.dialog.editSubtitle,
|
|
4761
|
+
meta: messages.context.ready,
|
|
4762
|
+
recentActivities: Object.freeze([])
|
|
4763
|
+
};
|
|
4764
|
+
if (motionController !== void 0) {
|
|
4765
|
+
motionController.render(projection, () => {
|
|
4766
|
+
executionIslandView.render(projection);
|
|
4767
|
+
});
|
|
4768
|
+
return;
|
|
4769
|
+
}
|
|
4770
|
+
executionIslandView.render(projection);
|
|
4771
|
+
floatingSurfaceRoot.dataset.scene = projection.scene;
|
|
4772
|
+
floatingSurfaceRoot.dataset.tone = projection.tone;
|
|
4773
|
+
const plannerActive = projection.scene === "planner";
|
|
4774
|
+
triggerButton.hidden = !pillActive;
|
|
4775
|
+
triggerButton.inert = !pillActive;
|
|
4776
|
+
dialog.hidden = !plannerActive;
|
|
4777
|
+
dialog.inert = !plannerActive;
|
|
4778
|
+
dialog.setAttribute("aria-hidden", String(!plannerActive));
|
|
4779
|
+
executionIsland.hidden = pillActive || plannerActive;
|
|
4780
|
+
executionIsland.inert = pillActive || plannerActive;
|
|
4781
|
+
executionIsland.setAttribute("aria-hidden", String(pillActive || plannerActive));
|
|
4782
|
+
floatingSurface.reconcile();
|
|
4783
|
+
}
|
|
4784
|
+
function renderExternalDispatch(dispatch) {
|
|
4785
|
+
if (dispatch === null) {
|
|
4786
|
+
pendingAgentMotion = void 0;
|
|
4787
|
+
observedExecutionStartedAt = void 0;
|
|
4788
|
+
} else if (pendingAgentMotion !== void 0 && dispatch.phase !== "failed" && dispatch.phase !== "delivery-unknown") {
|
|
4789
|
+
startStagedAgentRequest();
|
|
4790
|
+
} else if (dispatch.phase === "failed" || dispatch.phase === "delivery-unknown") {
|
|
4791
|
+
pendingAgentMotion = void 0;
|
|
4792
|
+
}
|
|
4793
|
+
if (dispatch !== null && !executionSuppressed) {
|
|
4794
|
+
const failed = dispatch.phase === "failed" || dispatch.phase === "delivery-unknown";
|
|
4795
|
+
const completed = dispatch.phase === "completed";
|
|
4796
|
+
const startedAt = failed || completed ? void 0 : observedExecutionStart();
|
|
4797
|
+
if (failed || completed) observedExecutionStartedAt = void 0;
|
|
4798
|
+
const successKey = `dispatch:${String(dispatch.revision)}`;
|
|
4799
|
+
if (completed && !showSuccessUntilSettled(successKey)) {
|
|
4800
|
+
executionProjection = void 0;
|
|
4801
|
+
renderFloatingSurfaceMotion();
|
|
4802
|
+
return;
|
|
4803
|
+
}
|
|
4804
|
+
const identity = externalAgentIdentity(dispatch.adapterKind);
|
|
4805
|
+
const target2 = currentTargetSummary();
|
|
4806
|
+
const activityKind = dispatch.phase === "queued" || dispatch.phase === "dispatching" || dispatch.phase === "dispatched" ? "dispatch" : completed ? "sync" : "unknown";
|
|
4807
|
+
const activity = motionActivity(
|
|
4808
|
+
`dispatch:${String(dispatch.revision)}:${dispatch.phase}`,
|
|
4809
|
+
activityKind,
|
|
4810
|
+
dispatch.phase,
|
|
4811
|
+
failed ? "failure" : completed ? "success" : "active"
|
|
4812
|
+
);
|
|
4813
|
+
const scene = failed ? "failed" : completed ? "success" : dispatch.phase === "working" ? "running" : "handoff";
|
|
4814
|
+
executionProjection = {
|
|
4815
|
+
scene,
|
|
4816
|
+
tone: failed ? "danger" : completed ? "success" : "running",
|
|
4817
|
+
headline: completed ? messages.execution.completedTitle : failed ? messages.execution.failedTitle : scene === "running" ? messages.execution.runningTitle(target2.label) : messages.execution.dispatchingTitle(identity),
|
|
4818
|
+
action: completed ? messages.execution.resultReturned : target2.source,
|
|
4819
|
+
expandedHeadline: completed ? messages.execution.expandedCompletedTitle : failed ? messages.execution.failedTitle : scene === "running" ? messages.execution.expandedRunningTitle(identity) : messages.execution.dispatchingTitle(identity),
|
|
4820
|
+
expandedAction: completed ? messages.execution.resultReturned : currentTargetContext(),
|
|
4821
|
+
meta: failed ? messages.execution.failedStatus : completed ? messages.execution.completedStatus : scene === "running" ? messages.execution.runningStatus : messages.execution.dispatchingStatus,
|
|
4822
|
+
activity,
|
|
4823
|
+
recentActivities: Object.freeze([activity]),
|
|
4824
|
+
...startedAt === void 0 ? {} : { startedAt }
|
|
4825
|
+
};
|
|
4826
|
+
} else if (dispatch === null) {
|
|
4827
|
+
executionProjection = void 0;
|
|
4828
|
+
}
|
|
4829
|
+
renderFloatingSurfaceMotion();
|
|
4830
|
+
}
|
|
4831
|
+
function renderExternalControl(status) {
|
|
4832
|
+
const task = status?.task;
|
|
4833
|
+
if (status === void 0 || task === void 0 || executionSuppressed) return;
|
|
4834
|
+
const phase = task.managedPhase;
|
|
4835
|
+
const failed = phase === "failed" || phase === "cleanup-warning";
|
|
4836
|
+
const completed = phase === "completed" || phase === "review-required";
|
|
4837
|
+
const cancelled = phase === "cancelled";
|
|
4838
|
+
if (failed || cancelled) {
|
|
4839
|
+
pendingAgentMotion = void 0;
|
|
4840
|
+
} else if (pendingAgentMotion !== void 0) {
|
|
4841
|
+
startStagedAgentRequest();
|
|
4842
|
+
}
|
|
4843
|
+
if (cancelled) {
|
|
4844
|
+
executionProjection = void 0;
|
|
4845
|
+
observedExecutionStartedAt = void 0;
|
|
4846
|
+
renderFloatingSurfaceMotion();
|
|
4847
|
+
return;
|
|
4848
|
+
}
|
|
4849
|
+
const startedAt = failed || completed ? void 0 : observedExecutionStart();
|
|
4850
|
+
if (failed || completed) observedExecutionStartedAt = void 0;
|
|
4851
|
+
if (phase === "completed" && !showSuccessUntilSettled(`managed:${String(task.revision)}`)) {
|
|
4852
|
+
executionProjection = void 0;
|
|
4853
|
+
renderFloatingSurfaceMotion();
|
|
4854
|
+
return;
|
|
4855
|
+
}
|
|
4856
|
+
const scene = failed ? "failed" : completed ? "success" : phase === "preparing" ? "handoff" : "running";
|
|
4857
|
+
const tone = failed ? "danger" : completed ? "success" : "running";
|
|
4858
|
+
const identity = messages.execution.codex;
|
|
4859
|
+
const target2 = currentTargetSummary();
|
|
4860
|
+
const activityKind = phase === "preparing" ? "prepare" : phase === "auditing" ? "audit" : phase === "validating" ? "check" : phase === "applying" ? "apply" : completed ? "sync" : "unknown";
|
|
4861
|
+
const latestCheck = task.checks.at(-1);
|
|
4862
|
+
const latestFile = task.files.at(-1);
|
|
4863
|
+
const activityDetail = phase === "validating" ? latestCheck?.id : phase === "auditing" || phase === "applying" ? latestFile?.path : void 0;
|
|
4864
|
+
const activity = motionActivity(
|
|
4865
|
+
`managed:${String(task.revision)}:${phase}:${activityDetail ?? ""}`,
|
|
4866
|
+
activityKind,
|
|
4867
|
+
activityDetail,
|
|
4868
|
+
failed ? "failure" : completed ? "success" : "active"
|
|
4869
|
+
);
|
|
4870
|
+
const recentActivities = Object.freeze([
|
|
4871
|
+
...task.files.slice(-2).map(
|
|
4872
|
+
(file) => motionActivity(
|
|
4873
|
+
`managed-file:${String(task.revision)}:${file.path}`,
|
|
4874
|
+
"patch",
|
|
4875
|
+
file.path,
|
|
4876
|
+
"success"
|
|
4877
|
+
)
|
|
4878
|
+
),
|
|
4879
|
+
...task.checks.slice(-2).map(
|
|
4880
|
+
(check) => motionActivity(
|
|
4881
|
+
`managed-check:${String(task.revision)}:${check.id}`,
|
|
4882
|
+
"check",
|
|
4883
|
+
check.id,
|
|
4884
|
+
check.outcome === "passed" ? "success" : "failure"
|
|
4885
|
+
)
|
|
4886
|
+
),
|
|
4887
|
+
activity
|
|
4888
|
+
]);
|
|
4889
|
+
executionProjection = {
|
|
4890
|
+
scene,
|
|
4891
|
+
tone,
|
|
4892
|
+
headline: completed ? messages.execution.completedTitle : failed ? messages.execution.failedTitle : scene === "handoff" ? messages.execution.dispatchingTitle(identity) : phase === "validating" ? messages.execution.activityAction("check", activityDetail) : messages.execution.runningTitle(target2.label),
|
|
4893
|
+
action: completed ? task.files.length === 0 ? messages.execution.resultReturned : messages.execution.resultSummary(task.files.length) : target2.source,
|
|
4894
|
+
expandedHeadline: completed ? messages.execution.expandedCompletedTitle : failed ? messages.execution.failedTitle : scene === "handoff" ? messages.execution.dispatchingTitle(identity) : messages.execution.expandedRunningTitle(identity),
|
|
4895
|
+
expandedAction: completed ? messages.execution.resultReturned : currentTargetContext(),
|
|
4896
|
+
meta: failed ? messages.execution.failedStatus : completed ? messages.execution.completedStatus : phase === "validating" ? messages.execution.checkingStatus : scene === "handoff" ? messages.execution.dispatchingStatus : messages.execution.runningStatus,
|
|
4897
|
+
activity,
|
|
4898
|
+
recentActivities,
|
|
4899
|
+
...startedAt === void 0 ? {} : { startedAt }
|
|
4900
|
+
};
|
|
4901
|
+
renderFloatingSurfaceMotion();
|
|
4902
|
+
}
|
|
4903
|
+
function beginAgentRequest(target2, agentCard) {
|
|
4904
|
+
if (!plannerVisible) {
|
|
4905
|
+
return;
|
|
4906
|
+
}
|
|
4907
|
+
clearSuccessSettle(true);
|
|
4908
|
+
const startedAt = beginObservedExecution();
|
|
4909
|
+
executionSuppressed = false;
|
|
4910
|
+
const activity = motionActivity(
|
|
4911
|
+
`dispatch-start:${currentTargetContext()}`,
|
|
4912
|
+
"dispatch",
|
|
4913
|
+
currentTargetContext()
|
|
4914
|
+
);
|
|
4915
|
+
executionProjection = {
|
|
4916
|
+
scene: "agent-charging",
|
|
4917
|
+
tone: "running",
|
|
4918
|
+
headline: messages.execution.receivingTitle,
|
|
4919
|
+
action: currentTargetContext(),
|
|
4920
|
+
expandedHeadline: messages.execution.receivingTitle,
|
|
4921
|
+
expandedAction: currentTargetContext(),
|
|
4922
|
+
meta: messages.execution.receivingStatus,
|
|
4923
|
+
activity,
|
|
4924
|
+
recentActivities: Object.freeze([activity]),
|
|
4925
|
+
startedAt
|
|
4926
|
+
};
|
|
4927
|
+
renderFloatingSurfaceMotion();
|
|
4928
|
+
motionController?.dispatch(target2, agentCard);
|
|
4929
|
+
}
|
|
4930
|
+
function stageAgentRequest(source2, target2) {
|
|
4931
|
+
if (!plannerVisible || source2.disabled) return;
|
|
4932
|
+
pendingAgentMotion = Object.freeze({ source: source2, target: target2 });
|
|
4933
|
+
}
|
|
4934
|
+
function startStagedAgentRequest() {
|
|
4935
|
+
const pending = pendingAgentMotion;
|
|
4936
|
+
pendingAgentMotion = void 0;
|
|
4937
|
+
if (pending === void 0 || !pending.source.isConnected || !pending.target.isConnected) {
|
|
4938
|
+
return;
|
|
4939
|
+
}
|
|
4940
|
+
beginAgentRequest(pending.source, pending.target);
|
|
4941
|
+
}
|
|
4104
4942
|
function renderEditorStatus(state) {
|
|
4105
4943
|
currentEditorFeedbackState = state;
|
|
4106
4944
|
editorFeedback.dataset.state = state;
|
|
4107
4945
|
editorFeedback.hidden = state === "idle";
|
|
4108
4946
|
editorFeedback.textContent = state === "opening" ? messages.announcements.editorOpening : state === "success" ? messages.announcements.editorOpened : state === "error" ? messages.announcements.editorFailed : "";
|
|
4109
|
-
|
|
4947
|
+
requestFloatingSurfaceLayout();
|
|
4110
4948
|
}
|
|
4111
4949
|
function statusText(target2) {
|
|
4112
4950
|
if (target2.status === "ready") {
|
|
@@ -4241,6 +5079,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4241
5079
|
replacement?.setSelectionRange(selectionStart, selectionEnd);
|
|
4242
5080
|
}
|
|
4243
5081
|
}
|
|
5082
|
+
requestFloatingSurfaceLayout();
|
|
4244
5083
|
}
|
|
4245
5084
|
function updateTargetInstruction(targetId, instruction) {
|
|
4246
5085
|
currentTargets = currentTargets.map(
|
|
@@ -4289,8 +5128,6 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4289
5128
|
}
|
|
4290
5129
|
function showSelectionHighlights(targets) {
|
|
4291
5130
|
selectionHighlights.replaceChildren();
|
|
4292
|
-
activeSelectionRect = targets.find((target2) => target2.active)?.rect;
|
|
4293
|
-
currentRect = activeSelectionRect;
|
|
4294
5131
|
for (const [index, target2] of targets.entries()) {
|
|
4295
5132
|
const box = createMarkedElement(document, "div");
|
|
4296
5133
|
box.className = "spotpatch-selection-highlight";
|
|
@@ -4304,31 +5141,6 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4304
5141
|
box.append(label);
|
|
4305
5142
|
selectionHighlights.append(box);
|
|
4306
5143
|
}
|
|
4307
|
-
placeDialog();
|
|
4308
|
-
}
|
|
4309
|
-
function placeDialog() {
|
|
4310
|
-
if (dialog.hidden) {
|
|
4311
|
-
return;
|
|
4312
|
-
}
|
|
4313
|
-
const view = document.defaultView;
|
|
4314
|
-
const viewportWidth = view?.innerWidth ?? document.documentElement.clientWidth;
|
|
4315
|
-
const viewportHeight = view?.innerHeight ?? document.documentElement.clientHeight;
|
|
4316
|
-
const measured = dialog.getBoundingClientRect();
|
|
4317
|
-
const status = currentStatus === "previewing" ? "previewing" : "selected";
|
|
4318
|
-
const dialogWidth = measured.width > 0 ? measured.width : Math.min(DIALOG_MAX_WIDTH, viewportWidth - 32);
|
|
4319
|
-
const dialogHeight = measured.height > 0 ? measured.height : Math.min(DIALOG_FALLBACK_HEIGHT[status], viewportHeight - 32);
|
|
4320
|
-
const placement = calculateDialogPlacement({
|
|
4321
|
-
dialogWidth,
|
|
4322
|
-
dialogHeight,
|
|
4323
|
-
viewportWidth,
|
|
4324
|
-
viewportHeight,
|
|
4325
|
-
...currentRect === void 0 ? {} : { target: currentRect }
|
|
4326
|
-
});
|
|
4327
|
-
dialog.style.left = `${String(placement.left)}px`;
|
|
4328
|
-
dialog.style.top = `${String(placement.top)}px`;
|
|
4329
|
-
dialog.style.setProperty("--spotpatch-anchor-x", `${String(placement.anchorX)}px`);
|
|
4330
|
-
dialog.style.setProperty("--spotpatch-anchor-y", `${String(placement.anchorY)}px`);
|
|
4331
|
-
dialog.dataset.placement = placement.mode;
|
|
4332
5144
|
}
|
|
4333
5145
|
function updateContextOverview(summaryText) {
|
|
4334
5146
|
const summaryMessages = messages.summary;
|
|
@@ -4359,14 +5171,18 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4359
5171
|
previewButton.disabled = !canPreview;
|
|
4360
5172
|
agentPanel.setContextReady(canPreview);
|
|
4361
5173
|
externalHandoffPanel?.setContextReady(canPreview);
|
|
5174
|
+
contextualAskPanel?.setSelectionPreview({
|
|
5175
|
+
contextReady: currentTargets.every((target2) => target2.status !== "loading"),
|
|
5176
|
+
targetCount: currentTargets.length,
|
|
5177
|
+
sourceCount: currentTargets.filter((target2) => target2.canOpenEditor).length
|
|
5178
|
+
});
|
|
4362
5179
|
updateContextOverview(summaryText);
|
|
4363
|
-
|
|
5180
|
+
requestFloatingSurfaceLayout();
|
|
4364
5181
|
}
|
|
4365
5182
|
function renderPanelStatus(status) {
|
|
4366
5183
|
currentStatus = status;
|
|
4367
5184
|
const selected = status === "selected";
|
|
4368
5185
|
const previewing = status === "previewing";
|
|
4369
|
-
triggerButton.hidden = selected || previewing;
|
|
4370
5186
|
selectionPanel.hidden = !selected;
|
|
4371
5187
|
previewPanel.hidden = !previewing;
|
|
4372
5188
|
reselectButton.hidden = !selected;
|
|
@@ -4376,11 +5192,12 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4376
5192
|
secondaryActions.hidden = !selected;
|
|
4377
5193
|
agentPanel.setSelectionVisible(selected);
|
|
4378
5194
|
externalHandoffPanel?.setSelectionVisible(selected);
|
|
5195
|
+
contextualAskPanel?.setSelectionVisible(selected);
|
|
4379
5196
|
copyButton.hidden = !previewing;
|
|
4380
5197
|
backButton.hidden = !previewing;
|
|
4381
|
-
title.textContent = previewing ? messages.dialog.previewTitle : messages.dialog.editTitle;
|
|
4382
|
-
subtitle.textContent = previewing ? messages.dialog.previewSubtitle : messages.dialog.editSubtitle;
|
|
4383
|
-
|
|
5198
|
+
title.textContent = previewing ? messages.dialog.previewTitle : contextualAskMode === "ask" && contextualAskTitle.length > 0 ? contextualAskTitle : messages.dialog.editTitle;
|
|
5199
|
+
subtitle.textContent = previewing ? messages.dialog.previewSubtitle : contextualAskMode === "ask" && contextualAskSubtitle.length > 0 ? contextualAskSubtitle : messages.dialog.editSubtitle;
|
|
5200
|
+
renderFloatingSurfaceMotion();
|
|
4384
5201
|
}
|
|
4385
5202
|
function applyMessages() {
|
|
4386
5203
|
messages = localizer.messages();
|
|
@@ -4392,8 +5209,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4392
5209
|
localeButton.textContent = messages.alternateLocaleName;
|
|
4393
5210
|
localeButton.title = messages.switchLocale;
|
|
4394
5211
|
localeButton.setAttribute("aria-label", messages.switchLocale);
|
|
5212
|
+
resetPositionButton.title = messages.floatingSurface.resetPosition;
|
|
5213
|
+
resetPositionButton.setAttribute(
|
|
5214
|
+
"aria-label",
|
|
5215
|
+
messages.floatingSurface.resetPosition
|
|
5216
|
+
);
|
|
4395
5217
|
closeButton.setAttribute("aria-label", messages.dialog.close);
|
|
4396
5218
|
closeButton.title = messages.dialog.close;
|
|
5219
|
+
header.title = messages.floatingSurface.dragHandle;
|
|
4397
5220
|
targetsPanel.setAttribute("aria-label", messages.targets.ariaLabel);
|
|
4398
5221
|
targetsTitle.textContent = messages.targets.title;
|
|
4399
5222
|
diagnosticsTitle.textContent = messages.diagnostics.title;
|
|
@@ -4429,8 +5252,58 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4429
5252
|
contextState.textContent = messages.context.collecting;
|
|
4430
5253
|
}
|
|
4431
5254
|
}
|
|
4432
|
-
|
|
5255
|
+
function announce(message) {
|
|
5256
|
+
liveRegion.textContent = "";
|
|
5257
|
+
liveRegion.textContent = message;
|
|
5258
|
+
}
|
|
5259
|
+
function resetFloatingSurfacePosition() {
|
|
5260
|
+
floatingSurface.reset();
|
|
5261
|
+
announce(messages.floatingSurface.positionReset);
|
|
5262
|
+
}
|
|
5263
|
+
diagnostics.addEventListener("toggle", requestFloatingSurfaceLayout);
|
|
4433
5264
|
localeButton.addEventListener("click", localizer.toggle);
|
|
5265
|
+
resetPositionButton.addEventListener("click", resetFloatingSurfacePosition);
|
|
5266
|
+
const onAgentRun = () => {
|
|
5267
|
+
stageAgentRequest(agentPanel.runButton, agentPanel.root);
|
|
5268
|
+
};
|
|
5269
|
+
const onExternalSend = () => {
|
|
5270
|
+
if (externalHandoffPanel !== void 0) {
|
|
5271
|
+
stageAgentRequest(externalHandoffPanel.sendButton, externalHandoffPanel.root);
|
|
5272
|
+
}
|
|
5273
|
+
};
|
|
5274
|
+
const onExecutionOpen = () => {
|
|
5275
|
+
if (executionIslandView.canExpand() && !executionIslandView.isExpanded()) {
|
|
5276
|
+
if (motionController === void 0) {
|
|
5277
|
+
executionIslandView.setExpanded(true);
|
|
5278
|
+
floatingSurface.reconcile();
|
|
5279
|
+
} else {
|
|
5280
|
+
motionController.updateLayout(() => {
|
|
5281
|
+
executionIslandView.setExpanded(true);
|
|
5282
|
+
});
|
|
5283
|
+
}
|
|
5284
|
+
return;
|
|
5285
|
+
}
|
|
5286
|
+
clearSuccessSettle(false);
|
|
5287
|
+
executionSuppressed = true;
|
|
5288
|
+
renderFloatingSurfaceMotion();
|
|
5289
|
+
};
|
|
5290
|
+
const onExecutionKeyDown = (event) => {
|
|
5291
|
+
if (event.key !== "Escape" || !executionIslandView.isExpanded()) return;
|
|
5292
|
+
event.preventDefault();
|
|
5293
|
+
event.stopPropagation();
|
|
5294
|
+
if (motionController === void 0) {
|
|
5295
|
+
executionIslandView.setExpanded(false);
|
|
5296
|
+
floatingSurface.reconcile();
|
|
5297
|
+
} else {
|
|
5298
|
+
motionController.updateLayout(() => {
|
|
5299
|
+
executionIslandView.setExpanded(false);
|
|
5300
|
+
});
|
|
5301
|
+
}
|
|
5302
|
+
};
|
|
5303
|
+
agentPanel.runButton.addEventListener("click", onAgentRun);
|
|
5304
|
+
externalHandoffPanel?.sendButton.addEventListener("click", onExternalSend);
|
|
5305
|
+
executionIsland.addEventListener("click", onExecutionOpen);
|
|
5306
|
+
executionIsland.addEventListener("keydown", onExecutionKeyDown);
|
|
4434
5307
|
const unsubscribeLocale = localizer.subscribe(applyMessages);
|
|
4435
5308
|
applyMessages();
|
|
4436
5309
|
return Object.freeze({
|
|
@@ -4458,8 +5331,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4458
5331
|
agentRevertButton: agentPanel.revertButton,
|
|
4459
5332
|
agentResetButton: agentPanel.resetButton,
|
|
4460
5333
|
...externalHandoffPanel === void 0 ? {} : { externalHandoffPanel },
|
|
5334
|
+
...contextualAskPanel === void 0 ? {} : { contextualAskPanel },
|
|
4461
5335
|
renderStatus(status) {
|
|
4462
5336
|
const inspecting = status === "inspecting";
|
|
5337
|
+
if (status === "idle" || inspecting) {
|
|
5338
|
+
plannerVisible = false;
|
|
5339
|
+
} else {
|
|
5340
|
+
plannerVisible = true;
|
|
5341
|
+
}
|
|
4463
5342
|
triggerButton.setAttribute("aria-pressed", String(inspecting));
|
|
4464
5343
|
triggerButton.textContent = inspecting ? messages.trigger.stop : messages.trigger.select;
|
|
4465
5344
|
renderPanelStatus(status);
|
|
@@ -4468,36 +5347,28 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4468
5347
|
renderDataFlow(state) {
|
|
4469
5348
|
currentDataFlowState = state;
|
|
4470
5349
|
dataFlowPanel.render(state);
|
|
4471
|
-
|
|
5350
|
+
requestFloatingSurfaceLayout();
|
|
4472
5351
|
},
|
|
4473
5352
|
showHighlight(rect, label) {
|
|
4474
|
-
currentRect = rect;
|
|
4475
5353
|
highlight.hidden = false;
|
|
4476
5354
|
highlight.style.transform = `translate(${String(rect.x)}px, ${String(rect.y)}px)`;
|
|
4477
5355
|
highlight.style.width = `${String(rect.width)}px`;
|
|
4478
5356
|
highlight.style.height = `${String(rect.height)}px`;
|
|
4479
5357
|
highlightLabel.textContent = label;
|
|
4480
5358
|
targetLabel.textContent = label;
|
|
4481
|
-
placeDialog();
|
|
4482
5359
|
},
|
|
4483
5360
|
hideHighlight() {
|
|
4484
|
-
currentRect = activeSelectionRect;
|
|
4485
5361
|
highlight.hidden = true;
|
|
4486
5362
|
highlightLabel.textContent = "";
|
|
4487
|
-
placeDialog();
|
|
4488
5363
|
},
|
|
4489
5364
|
showSelectionHighlights,
|
|
4490
5365
|
hideSelectionHighlights() {
|
|
4491
5366
|
selectionHighlights.replaceChildren();
|
|
4492
|
-
activeSelectionRect = void 0;
|
|
4493
|
-
currentRect = void 0;
|
|
4494
|
-
placeDialog();
|
|
4495
5367
|
},
|
|
4496
5368
|
showSelection(summaryText, canOpenEditor, canPreview) {
|
|
4497
5369
|
updateSelection(summaryText, canOpenEditor, canPreview);
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
placeDialog();
|
|
5370
|
+
plannerVisible = true;
|
|
5371
|
+
renderPanelStatus(currentStatus === "previewing" ? "previewing" : "selected");
|
|
4501
5372
|
},
|
|
4502
5373
|
updateSelection,
|
|
4503
5374
|
renderTargets,
|
|
@@ -4509,8 +5380,9 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4509
5380
|
externalHandoffPanel?.setContextReady(enabled);
|
|
4510
5381
|
},
|
|
4511
5382
|
hideSelection() {
|
|
4512
|
-
|
|
4513
|
-
|
|
5383
|
+
plannerVisible = false;
|
|
5384
|
+
executionSuppressed = false;
|
|
5385
|
+
executionProjection = void 0;
|
|
4514
5386
|
targetList.replaceChildren();
|
|
4515
5387
|
currentTargets = [];
|
|
4516
5388
|
currentMaximum = 0;
|
|
@@ -4533,17 +5405,21 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4533
5405
|
agentPanel.setSelectionVisible(false);
|
|
4534
5406
|
externalHandoffPanel?.setContextReady(false);
|
|
4535
5407
|
externalHandoffPanel?.setSelectionVisible(false);
|
|
5408
|
+
contextualAskPanel?.setSelectionVisible(false);
|
|
4536
5409
|
agentPanel.setEditingEnabled(true);
|
|
4537
5410
|
agentPanel.resetJob();
|
|
4538
5411
|
dataFlowPanel.resetView();
|
|
5412
|
+
renderFloatingSurfaceMotion();
|
|
4539
5413
|
},
|
|
4540
5414
|
hideSelectionTemporarily() {
|
|
4541
|
-
|
|
4542
|
-
|
|
5415
|
+
plannerVisible = false;
|
|
5416
|
+
executionSuppressed = false;
|
|
5417
|
+
executionProjection = void 0;
|
|
5418
|
+
renderFloatingSurfaceMotion();
|
|
4543
5419
|
},
|
|
4544
5420
|
showPreview(prompt) {
|
|
4545
5421
|
promptOutput.textContent = prompt;
|
|
4546
|
-
|
|
5422
|
+
requestFloatingSurfaceLayout();
|
|
4547
5423
|
},
|
|
4548
5424
|
readAgentSelection() {
|
|
4549
5425
|
return agentPanel.readSelection();
|
|
@@ -4567,25 +5443,86 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4567
5443
|
previewButton.disabled = !enabled || !currentCanPreview;
|
|
4568
5444
|
externalHandoffPanel?.setContextReady(enabled && currentCanPreview);
|
|
4569
5445
|
agentPanel.setEditingEnabled(enabled);
|
|
4570
|
-
|
|
5446
|
+
requestFloatingSurfaceLayout();
|
|
4571
5447
|
},
|
|
4572
5448
|
renderAgentCapability(state, message, capabilitySnapshot, errorCode) {
|
|
4573
5449
|
agentPanel.renderCapability(state, message, capabilitySnapshot, errorCode);
|
|
5450
|
+
if (state === "error") {
|
|
5451
|
+
pendingAgentMotion = void 0;
|
|
5452
|
+
renderFloatingSurfaceMotion();
|
|
5453
|
+
}
|
|
4574
5454
|
const agentReady = state === "ready" && capabilitySnapshot?.state === "agent-ready";
|
|
4575
5455
|
previewButton.classList.toggle("spotpatch-primary", !agentReady);
|
|
4576
|
-
|
|
5456
|
+
requestFloatingSurfaceLayout();
|
|
4577
5457
|
},
|
|
4578
5458
|
renderAgentWorkspaceHealth(state, snapshot, errorCode) {
|
|
4579
5459
|
agentPanel.renderWorkspaceHealth(state, snapshot, errorCode);
|
|
4580
|
-
|
|
5460
|
+
if (state === "blocked") {
|
|
5461
|
+
pendingAgentMotion = void 0;
|
|
5462
|
+
renderFloatingSurfaceMotion();
|
|
5463
|
+
}
|
|
5464
|
+
requestFloatingSurfaceLayout();
|
|
4581
5465
|
},
|
|
4582
5466
|
renderAgentJob(snapshot, result, activities, errorCode) {
|
|
4583
5467
|
agentPanel.renderJob(snapshot, result, activities, errorCode);
|
|
4584
|
-
|
|
5468
|
+
if (pendingAgentMotion !== void 0 && snapshot.status !== "failed" && snapshot.status !== "cancelled") {
|
|
5469
|
+
startStagedAgentRequest();
|
|
5470
|
+
}
|
|
5471
|
+
if (snapshot.status === "failed" || snapshot.status === "cancelled") {
|
|
5472
|
+
pendingAgentMotion = void 0;
|
|
5473
|
+
}
|
|
5474
|
+
const successful = snapshot.status === "awaiting-review" || snapshot.status === "applied" || snapshot.status === "completed" || snapshot.status === "reverted";
|
|
5475
|
+
const failed = snapshot.status === "failed";
|
|
5476
|
+
const cancelled = snapshot.status === "cancelled";
|
|
5477
|
+
const terminalSuccess = snapshot.status === "applied" || snapshot.status === "completed" || snapshot.status === "reverted";
|
|
5478
|
+
const scene = successful ? "success" : failed ? "failed" : snapshot.status === "queued" || snapshot.status === "preparing" ? "handoff" : "running";
|
|
5479
|
+
if (!executionSuppressed) {
|
|
5480
|
+
if (terminalSuccess && !showSuccessUntilSettled(`job:${snapshot.jobId}:${snapshot.status}`)) {
|
|
5481
|
+
executionProjection = void 0;
|
|
5482
|
+
renderFloatingSurfaceMotion();
|
|
5483
|
+
requestFloatingSurfaceLayout();
|
|
5484
|
+
return;
|
|
5485
|
+
}
|
|
5486
|
+
const identity = snapshot.providerLabel;
|
|
5487
|
+
const target2 = currentTargetSummary();
|
|
5488
|
+
const projectedActivities = Object.freeze(activities.map(projectAgentActivity));
|
|
5489
|
+
const latestActivity = activities.at(-1);
|
|
5490
|
+
const phaseKind = snapshot.status === "queued" || snapshot.status === "preparing" ? "prepare" : snapshot.status === "validating" ? "check" : snapshot.status === "applying" || snapshot.status === "reverting" ? "apply" : snapshot.status === "awaiting-review" || successful ? "sync" : "unknown";
|
|
5491
|
+
const phaseActivity = motionActivity(
|
|
5492
|
+
`job-phase:${snapshot.jobId}:${snapshot.status}:${snapshot.updatedAt}`,
|
|
5493
|
+
phaseKind,
|
|
5494
|
+
void 0,
|
|
5495
|
+
successful ? "success" : failed ? "failure" : "active"
|
|
5496
|
+
);
|
|
5497
|
+
const activity = snapshot.status === "running" && latestActivity !== void 0 ? projectAgentActivity(latestActivity) : phaseActivity;
|
|
5498
|
+
executionProjection = cancelled ? void 0 : {
|
|
5499
|
+
scene,
|
|
5500
|
+
tone: successful ? "success" : failed ? "danger" : "running",
|
|
5501
|
+
headline: successful ? messages.execution.completedTitle : failed ? messages.execution.failedTitle : scene === "handoff" ? messages.execution.dispatchingTitle(identity) : snapshot.status === "validating" ? messages.execution.activityAction(
|
|
5502
|
+
"check",
|
|
5503
|
+
latestActivity?.detail
|
|
5504
|
+
) : snapshot.status === "applying" || snapshot.status === "reverting" ? messages.execution.activityAction(phaseKind) : messages.execution.runningTitle(target2.label),
|
|
5505
|
+
action: successful ? result === void 0 || result.files.length === 0 ? messages.execution.resultReturned : messages.execution.resultSummary(result.files.length) : latestActivity?.detail ?? target2.source,
|
|
5506
|
+
expandedHeadline: successful ? messages.execution.expandedCompletedTitle : failed ? messages.execution.failedTitle : scene === "handoff" ? messages.execution.dispatchingTitle(identity) : messages.execution.expandedRunningTitle(identity),
|
|
5507
|
+
expandedAction: successful ? result === void 0 || result.files.length === 0 ? messages.execution.resultReturned : messages.execution.resultSummary(result.files.length) : currentTargetContext(),
|
|
5508
|
+
meta: successful ? messages.execution.completedStatus : failed ? messages.execution.failedStatus : snapshot.status === "validating" ? messages.execution.checkingStatus : scene === "handoff" ? messages.execution.dispatchingStatus : messages.execution.runningStatus,
|
|
5509
|
+
activity,
|
|
5510
|
+
recentActivities: projectedActivities.length === 0 ? Object.freeze([phaseActivity]) : projectedActivities,
|
|
5511
|
+
startedAt: snapshot.createdAt
|
|
5512
|
+
};
|
|
5513
|
+
}
|
|
5514
|
+
renderFloatingSurfaceMotion();
|
|
5515
|
+
requestFloatingSurfaceLayout();
|
|
4585
5516
|
},
|
|
4586
5517
|
resetAgentJob() {
|
|
4587
5518
|
agentPanel.resetJob();
|
|
4588
|
-
|
|
5519
|
+
observedExecutionStartedAt = void 0;
|
|
5520
|
+
if (executionProjection !== void 0) {
|
|
5521
|
+
executionProjection = void 0;
|
|
5522
|
+
executionSuppressed = false;
|
|
5523
|
+
renderFloatingSurfaceMotion();
|
|
5524
|
+
}
|
|
5525
|
+
requestFloatingSurfaceLayout();
|
|
4589
5526
|
},
|
|
4590
5527
|
focusTargetInstruction(targetId) {
|
|
4591
5528
|
instructionInput(targetId)?.focus({ preventScroll: true });
|
|
@@ -4593,21 +5530,28 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4593
5530
|
focusPrompt() {
|
|
4594
5531
|
promptOutput.focus({ preventScroll: true });
|
|
4595
5532
|
},
|
|
4596
|
-
announce
|
|
4597
|
-
liveRegion.textContent = "";
|
|
4598
|
-
liveRegion.textContent = message;
|
|
4599
|
-
},
|
|
5533
|
+
announce,
|
|
4600
5534
|
locale: localizer.locale,
|
|
4601
5535
|
messages: localizer.messages,
|
|
4602
5536
|
agentWorkspaceConsentGranted: agentPanel.workspaceConsentGranted,
|
|
4603
5537
|
subscribeLocale: localizer.subscribe,
|
|
4604
5538
|
dispose() {
|
|
4605
|
-
diagnostics.removeEventListener("toggle",
|
|
5539
|
+
diagnostics.removeEventListener("toggle", requestFloatingSurfaceLayout);
|
|
4606
5540
|
localeButton.removeEventListener("click", localizer.toggle);
|
|
5541
|
+
resetPositionButton.removeEventListener("click", resetFloatingSurfacePosition);
|
|
5542
|
+
agentPanel.runButton.removeEventListener("click", onAgentRun);
|
|
5543
|
+
externalHandoffPanel?.sendButton.removeEventListener("click", onExternalSend);
|
|
5544
|
+
executionIsland.removeEventListener("click", onExecutionOpen);
|
|
5545
|
+
executionIsland.removeEventListener("keydown", onExecutionKeyDown);
|
|
4607
5546
|
unsubscribeLocale();
|
|
4608
5547
|
dataFlowPanel.dispose();
|
|
4609
5548
|
externalHandoffPanel?.dispose();
|
|
5549
|
+
contextualAskPanel?.dispose();
|
|
4610
5550
|
agentPanel.dispose();
|
|
5551
|
+
motionController?.dispose();
|
|
5552
|
+
executionIslandView.dispose();
|
|
5553
|
+
clearSuccessSettle(true);
|
|
5554
|
+
floatingSurface.dispose();
|
|
4611
5555
|
host.remove();
|
|
4612
5556
|
}
|
|
4613
5557
|
});
|
|
@@ -4674,17 +5618,33 @@ var import_shared8 = require("@spotpatch/shared");
|
|
|
4674
5618
|
function capabilityKey(providerProfileId, modelProfileId) {
|
|
4675
5619
|
return `${providerProfileId}:${modelProfileId}`;
|
|
4676
5620
|
}
|
|
5621
|
+
var TOOL_ACTIVITY_KIND = Object.freeze({
|
|
5622
|
+
list_files: "discover",
|
|
5623
|
+
search_text: "search",
|
|
5624
|
+
read_file: "read",
|
|
5625
|
+
replace_text: "patch",
|
|
5626
|
+
apply_patch: "patch",
|
|
5627
|
+
run_check: "check"
|
|
5628
|
+
});
|
|
5629
|
+
function toolActivityKind(toolName) {
|
|
5630
|
+
return TOOL_ACTIVITY_KIND[toolName] ?? "unknown";
|
|
5631
|
+
}
|
|
4677
5632
|
function activityFromEvent(event) {
|
|
4678
5633
|
if (event.type === "tool") {
|
|
5634
|
+
const detail = event.data.relativePath ?? event.data.checkLabel;
|
|
4679
5635
|
return Object.freeze({
|
|
4680
5636
|
key: `tool:${String(event.data.turn)}:${event.data.toolCallId}`,
|
|
4681
|
-
|
|
5637
|
+
kind: toolActivityKind(event.data.toolName),
|
|
5638
|
+
...detail === void 0 ? {} : { detail },
|
|
5639
|
+
label: `${event.data.toolName}${detail === void 0 ? "" : ` \xB7 ${detail}`} \xB7 ${event.data.state}`,
|
|
4682
5640
|
state: event.data.state === "started" ? "active" : event.data.state === "succeeded" ? "success" : "failure"
|
|
4683
5641
|
});
|
|
4684
5642
|
}
|
|
4685
5643
|
if (event.type === "check") {
|
|
4686
5644
|
return Object.freeze({
|
|
4687
5645
|
key: `check:${event.data.result.checkId}:${String(event.sequence)}`,
|
|
5646
|
+
kind: "check",
|
|
5647
|
+
detail: event.data.result.label,
|
|
4688
5648
|
label: `${event.data.result.label} \xB7 ${event.data.result.status}`,
|
|
4689
5649
|
state: event.data.result.status === "passed" ? "success" : event.data.result.status === "failed" || event.data.result.status === "timed-out" ? "failure" : "info"
|
|
4690
5650
|
});
|
|
@@ -5105,7 +6065,8 @@ function createController(config, dependencies = {}) {
|
|
|
5105
6065
|
config.dataFlow.enabled,
|
|
5106
6066
|
config.externalAgent.enabled,
|
|
5107
6067
|
config.framework,
|
|
5108
|
-
config.sessionId
|
|
6068
|
+
config.sessionId,
|
|
6069
|
+
config.contextualAsk.enabled
|
|
5109
6070
|
);
|
|
5110
6071
|
const api = dependencies.api ?? createRuntimeApi({
|
|
5111
6072
|
apiBase: config.apiBase,
|
|
@@ -5308,6 +6269,19 @@ function createController(config, dependencies = {}) {
|
|
|
5308
6269
|
(target2) => target2.instruction.trim().length > 0 && target2.elementContext !== void 0 && target2.styles !== void 0 && target2.apiStatus !== "loading"
|
|
5309
6270
|
);
|
|
5310
6271
|
}
|
|
6272
|
+
function selectedAskSelection() {
|
|
6273
|
+
const snapshots = targets.flatMap((target2) => {
|
|
6274
|
+
const snapshot = snapshotTarget(target2);
|
|
6275
|
+
return snapshot === void 0 ? [] : [snapshot];
|
|
6276
|
+
});
|
|
6277
|
+
if (snapshots.length === 0 || snapshots.length !== targets.length) {
|
|
6278
|
+
return void 0;
|
|
6279
|
+
}
|
|
6280
|
+
return Object.freeze({
|
|
6281
|
+
locale: view.locale(),
|
|
6282
|
+
targets: snapshots
|
|
6283
|
+
});
|
|
6284
|
+
}
|
|
5311
6285
|
function selectionSummary() {
|
|
5312
6286
|
const messages = view.messages().summary;
|
|
5313
6287
|
return targets.map((target2, index) => {
|
|
@@ -5429,6 +6403,7 @@ ${summary}`;
|
|
|
5429
6403
|
api.cancelPending();
|
|
5430
6404
|
agentWorkflow.disposeSelection();
|
|
5431
6405
|
externalHandoffWorkflow?.cancelPending();
|
|
6406
|
+
contextualAskWorkflow?.cancelPending();
|
|
5432
6407
|
clearCollectionTimers();
|
|
5433
6408
|
resizeObserver?.disconnect();
|
|
5434
6409
|
targets = [];
|
|
@@ -5554,6 +6529,27 @@ ${summary}`;
|
|
|
5554
6529
|
config.sessionToken,
|
|
5555
6530
|
browser.window
|
|
5556
6531
|
) : void 0;
|
|
6532
|
+
const contextualAskWorkflow = config.contextualAsk.enabled && view.contextualAskPanel !== void 0 ? getContextualAskExtension()?.createWorkflow({
|
|
6533
|
+
...clipboard === void 0 ? {} : { clipboard },
|
|
6534
|
+
createId,
|
|
6535
|
+
fetch: browser.window.fetch.bind(browser.window),
|
|
6536
|
+
getSelection: selectedAskSelection,
|
|
6537
|
+
onBusyChange(busy) {
|
|
6538
|
+
view.setAgentEditingEnabled(!busy);
|
|
6539
|
+
},
|
|
6540
|
+
onConvert() {
|
|
6541
|
+
view.focusTargetInstruction(activeTargetId);
|
|
6542
|
+
},
|
|
6543
|
+
async onOpenSource(source2) {
|
|
6544
|
+
await api.openEditor({
|
|
6545
|
+
fileId: source2.fileId,
|
|
6546
|
+
line: source2.startLine,
|
|
6547
|
+
column: 1
|
|
6548
|
+
});
|
|
6549
|
+
},
|
|
6550
|
+
panel: view.contextualAskPanel,
|
|
6551
|
+
sessionToken: config.sessionToken
|
|
6552
|
+
}) : void 0;
|
|
5557
6553
|
async function loadSourceContext(target2, revision) {
|
|
5558
6554
|
const marker = target2.marker;
|
|
5559
6555
|
if (marker === void 0) {
|
|
@@ -5667,6 +6663,7 @@ ${summary}`;
|
|
|
5667
6663
|
previewPrompt = "";
|
|
5668
6664
|
agentWorkflow.beginSelection();
|
|
5669
6665
|
workflowSelectionActive = true;
|
|
6666
|
+
contextualAskWorkflow?.beginSelection();
|
|
5670
6667
|
}
|
|
5671
6668
|
targetSequence += 1;
|
|
5672
6669
|
const target2 = {
|
|
@@ -5685,6 +6682,9 @@ ${summary}`;
|
|
|
5685
6682
|
dataFlowStatus: "idle"
|
|
5686
6683
|
};
|
|
5687
6684
|
targets.push(target2);
|
|
6685
|
+
if (!initialSelection) {
|
|
6686
|
+
contextualAskWorkflow?.selectionChanged();
|
|
6687
|
+
}
|
|
5688
6688
|
activeTargetId = target2.id;
|
|
5689
6689
|
addingTarget = false;
|
|
5690
6690
|
const revision = sessionRevision;
|
|
@@ -5801,10 +6801,12 @@ ${summary}`;
|
|
|
5801
6801
|
pageDataFlowStatus = "idle";
|
|
5802
6802
|
renderDataFlowView();
|
|
5803
6803
|
selectionSession.clear();
|
|
6804
|
+
contextualAskWorkflow?.selectionChanged();
|
|
5804
6805
|
view.announce(view.messages().announcements.allTargetsRemoved);
|
|
5805
6806
|
return;
|
|
5806
6807
|
}
|
|
5807
6808
|
refreshSelectionView();
|
|
6809
|
+
contextualAskWorkflow?.selectionChanged();
|
|
5808
6810
|
void loadDataFlowReports();
|
|
5809
6811
|
persistSelection();
|
|
5810
6812
|
view.announce(view.messages().announcements.targetRemoved);
|
|
@@ -5983,6 +6985,7 @@ ${summary}`;
|
|
|
5983
6985
|
}
|
|
5984
6986
|
mounted = true;
|
|
5985
6987
|
externalHandoffWorkflow?.mount();
|
|
6988
|
+
contextualAskWorkflow?.mount();
|
|
5986
6989
|
view.renderStatus(state.status);
|
|
5987
6990
|
browser.document.addEventListener("pointermove", handlePointerMove, true);
|
|
5988
6991
|
browser.document.addEventListener("click", handleClick, true);
|
|
@@ -6034,6 +7037,7 @@ ${summary}`;
|
|
|
6034
7037
|
if (selectionOpen && targets.length > 0) {
|
|
6035
7038
|
transition({ type: "RESTORE" });
|
|
6036
7039
|
agentWorkflow.beginSelection();
|
|
7040
|
+
contextualAskWorkflow?.beginSelection();
|
|
6037
7041
|
workflowSelectionActive = true;
|
|
6038
7042
|
refreshSelectionView(true);
|
|
6039
7043
|
}
|
|
@@ -6050,6 +7054,7 @@ ${summary}`;
|
|
|
6050
7054
|
api.dispose();
|
|
6051
7055
|
agentWorkflow.disposeSelection();
|
|
6052
7056
|
externalHandoffWorkflow?.dispose();
|
|
7057
|
+
contextualAskWorkflow?.dispose();
|
|
6053
7058
|
sourceResolver.dispose();
|
|
6054
7059
|
return;
|
|
6055
7060
|
}
|
|
@@ -6114,6 +7119,7 @@ ${summary}`;
|
|
|
6114
7119
|
api.dispose();
|
|
6115
7120
|
agentWorkflow.disposeSelection();
|
|
6116
7121
|
externalHandoffWorkflow?.dispose();
|
|
7122
|
+
contextualAskWorkflow?.dispose();
|
|
6117
7123
|
sourceResolver.dispose();
|
|
6118
7124
|
view.dispose();
|
|
6119
7125
|
state = INITIAL_RUNTIME_STATE;
|
|
@@ -6258,9 +7264,9 @@ function installWritableDataProperty(target2, key, replacement, original = ownPr
|
|
|
6258
7264
|
}
|
|
6259
7265
|
};
|
|
6260
7266
|
}
|
|
6261
|
-
function recordWithoutAffectingHost(
|
|
7267
|
+
function recordWithoutAffectingHost(record3) {
|
|
6262
7268
|
try {
|
|
6263
|
-
|
|
7269
|
+
record3();
|
|
6264
7270
|
} catch {
|
|
6265
7271
|
}
|
|
6266
7272
|
}
|