@spotpatch/runtime 1.4.0 → 1.5.1
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/README.md +3 -7
- package/dist/index.cjs +892 -546
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +890 -544
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -10,45 +10,46 @@ import {
|
|
|
10
10
|
MAX_ANNOTATION_TARGETS,
|
|
11
11
|
MAX_TARGET_INSTRUCTION_CHARACTERS
|
|
12
12
|
} from "@spotpatch/shared";
|
|
13
|
-
function freezeSource(
|
|
13
|
+
function freezeSource(source2, code2) {
|
|
14
14
|
return Object.freeze({
|
|
15
|
-
...
|
|
16
|
-
...
|
|
15
|
+
...source2,
|
|
16
|
+
...source2.relativePath === void 0 && code2 !== void 0 ? { relativePath: code2.relativePath } : {}
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
-
function freezeReact(
|
|
19
|
+
function freezeReact(react2) {
|
|
20
20
|
return Object.freeze({
|
|
21
|
-
...
|
|
22
|
-
componentStack: Object.freeze([...
|
|
23
|
-
...
|
|
21
|
+
...react2,
|
|
22
|
+
componentStack: Object.freeze([...react2.componentStack]),
|
|
23
|
+
...react2.source === void 0 ? {} : { source: freezeSource(react2.source) }
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
|
-
function freezeElement(
|
|
26
|
+
function freezeElement(element2) {
|
|
27
27
|
return Object.freeze({
|
|
28
|
-
...
|
|
29
|
-
rect: Object.freeze({ ...
|
|
28
|
+
...element2,
|
|
29
|
+
rect: Object.freeze({ ...element2.rect })
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
function freezeStyles(
|
|
32
|
+
function freezeStyles(styles2) {
|
|
33
33
|
return Object.freeze({
|
|
34
|
-
...
|
|
35
|
-
classNames: Object.freeze([...
|
|
34
|
+
...styles2,
|
|
35
|
+
classNames: Object.freeze([...styles2.classNames]),
|
|
36
36
|
matchedRules: Object.freeze(
|
|
37
|
-
|
|
37
|
+
styles2.matchedRules.map((rule) => Object.freeze({ ...rule }))
|
|
38
38
|
),
|
|
39
|
-
computed: Object.freeze({ ...
|
|
40
|
-
warnings: Object.freeze([...
|
|
39
|
+
computed: Object.freeze({ ...styles2.computed }),
|
|
40
|
+
warnings: Object.freeze([...styles2.warnings])
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
function freezeTarget(
|
|
43
|
+
function freezeTarget(target2) {
|
|
44
44
|
return Object.freeze({
|
|
45
|
-
instruction:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
instruction: target2.instruction.trim(),
|
|
46
|
+
...target2.page === void 0 ? {} : { page: Object.freeze({ ...target2.page }) },
|
|
47
|
+
source: freezeSource(target2.source, target2.code),
|
|
48
|
+
react: freezeReact(target2.react),
|
|
49
|
+
element: freezeElement(target2.element),
|
|
50
|
+
styles: freezeStyles(target2.styles),
|
|
51
|
+
...target2.code === void 0 ? {} : { code: Object.freeze({ ...target2.code }) },
|
|
52
|
+
warnings: Object.freeze([...target2.warnings])
|
|
52
53
|
});
|
|
53
54
|
}
|
|
54
55
|
function createAnnotation(input) {
|
|
@@ -57,7 +58,7 @@ function createAnnotation(input) {
|
|
|
57
58
|
`SpotPatch annotations require between 1 and ${String(MAX_ANNOTATION_TARGETS)} targets.`
|
|
58
59
|
);
|
|
59
60
|
}
|
|
60
|
-
const instructions = input.targets.map((
|
|
61
|
+
const instructions = input.targets.map((target2) => target2.instruction.trim());
|
|
61
62
|
if (instructions.some(
|
|
62
63
|
(instruction) => instruction.length === 0 || instruction.length > MAX_TARGET_INSTRUCTION_CHARACTERS
|
|
63
64
|
) || instructions.reduce((total, instruction) => total + instruction.length, 0) > MAX_ANNOTATION_INSTRUCTION_CHARACTERS) {
|
|
@@ -254,10 +255,10 @@ var MAX_EVENT_LINE_BYTES = 1e5;
|
|
|
254
255
|
var MAX_EVENT_STREAM_BYTES = 4e6;
|
|
255
256
|
var RuntimeApiError = class extends Error {
|
|
256
257
|
code;
|
|
257
|
-
constructor(
|
|
258
|
+
constructor(code2) {
|
|
258
259
|
super("SpotPatch local API request failed.");
|
|
259
260
|
this.name = "RuntimeApiError";
|
|
260
|
-
this.code =
|
|
261
|
+
this.code = code2;
|
|
261
262
|
}
|
|
262
263
|
};
|
|
263
264
|
function isRecord2(value) {
|
|
@@ -329,9 +330,9 @@ async function readBoundedText(response, maximumBytes) {
|
|
|
329
330
|
reader.releaseLock();
|
|
330
331
|
}
|
|
331
332
|
}
|
|
332
|
-
function parseJson(
|
|
333
|
+
function parseJson(text2) {
|
|
333
334
|
try {
|
|
334
|
-
return JSON.parse(
|
|
335
|
+
return JSON.parse(text2);
|
|
335
336
|
} catch {
|
|
336
337
|
throw new RuntimeApiError();
|
|
337
338
|
}
|
|
@@ -374,13 +375,13 @@ function omitBrowserCodeContext(request) {
|
|
|
374
375
|
...request,
|
|
375
376
|
annotation: {
|
|
376
377
|
...request.annotation,
|
|
377
|
-
targets: request.annotation.targets.map((
|
|
378
|
-
instruction:
|
|
379
|
-
source:
|
|
380
|
-
react:
|
|
381
|
-
element:
|
|
382
|
-
styles:
|
|
383
|
-
warnings:
|
|
378
|
+
targets: request.annotation.targets.map((target2) => ({
|
|
379
|
+
instruction: target2.instruction,
|
|
380
|
+
source: target2.source,
|
|
381
|
+
react: target2.react,
|
|
382
|
+
element: target2.element,
|
|
383
|
+
styles: target2.styles,
|
|
384
|
+
warnings: target2.warnings
|
|
384
385
|
}))
|
|
385
386
|
}
|
|
386
387
|
};
|
|
@@ -671,12 +672,12 @@ function contextCharacterCount(classNames, inlineStyle, rules, computed, warning
|
|
|
671
672
|
function stylesheetSource(sheet, baseUrl) {
|
|
672
673
|
return sheet.href === null ? void 0 : sanitizeUrl(sheet.href, baseUrl);
|
|
673
674
|
}
|
|
674
|
-
function collectMatchedRules(
|
|
675
|
+
function collectMatchedRules(element2, rules, source2, inheritedConditions, output, warnings) {
|
|
675
676
|
for (const rule of rules) {
|
|
676
677
|
if (isStyleRule(rule)) {
|
|
677
678
|
let matches = false;
|
|
678
679
|
try {
|
|
679
|
-
matches =
|
|
680
|
+
matches = element2.matches(rule.selectorText);
|
|
680
681
|
} catch {
|
|
681
682
|
warnings.add(CSS_COLLECTION_WARNINGS.selector);
|
|
682
683
|
continue;
|
|
@@ -686,7 +687,7 @@ function collectMatchedRules(element, rules, source, inheritedConditions, output
|
|
|
686
687
|
Object.freeze({
|
|
687
688
|
selector: sanitizeCssText(rule.selectorText),
|
|
688
689
|
declarations: sanitizeCssText(rule.style.cssText),
|
|
689
|
-
...
|
|
690
|
+
...source2 === void 0 ? {} : { source: source2 },
|
|
690
691
|
...inheritedConditions.length === 0 ? {} : { media: inheritedConditions.join(" and ") }
|
|
691
692
|
})
|
|
692
693
|
);
|
|
@@ -696,9 +697,9 @@ function collectMatchedRules(element, rules, source, inheritedConditions, output
|
|
|
696
697
|
if (isGroupingRule(rule)) {
|
|
697
698
|
const condition = groupingCondition(rule);
|
|
698
699
|
collectMatchedRules(
|
|
699
|
-
|
|
700
|
+
element2,
|
|
700
701
|
rule.cssRules,
|
|
701
|
-
|
|
702
|
+
source2,
|
|
702
703
|
condition === void 0 ? inheritedConditions : [...inheritedConditions, condition],
|
|
703
704
|
output,
|
|
704
705
|
warnings
|
|
@@ -706,11 +707,11 @@ function collectMatchedRules(element, rules, source, inheritedConditions, output
|
|
|
706
707
|
}
|
|
707
708
|
}
|
|
708
709
|
}
|
|
709
|
-
function collectComputedStyle(
|
|
710
|
+
function collectComputedStyle(element2, getComputedStyle) {
|
|
710
711
|
if (getComputedStyle === void 0) {
|
|
711
712
|
return {};
|
|
712
713
|
}
|
|
713
|
-
const declaration = getComputedStyle(
|
|
714
|
+
const declaration = getComputedStyle(element2);
|
|
714
715
|
const computed = {};
|
|
715
716
|
for (const property of COMPUTED_STYLE_PROPERTIES) {
|
|
716
717
|
const value = sanitizeCssText(declaration.getPropertyValue(property).trim());
|
|
@@ -848,11 +849,11 @@ function escapeHtml(value) {
|
|
|
848
849
|
function isPreservedAttribute(name) {
|
|
849
850
|
return SAFE_ATTRIBUTE_NAMES.has(name) || name.startsWith("aria-") || name === "data-testid";
|
|
850
851
|
}
|
|
851
|
-
function openingTag(
|
|
852
|
-
const tagName =
|
|
852
|
+
function openingTag(element2) {
|
|
853
|
+
const tagName = element2.tagName.toLowerCase();
|
|
853
854
|
const attributes = [];
|
|
854
|
-
const baseUrl =
|
|
855
|
-
for (const attribute of
|
|
855
|
+
const baseUrl = element2.ownerDocument.baseURI;
|
|
856
|
+
for (const attribute of element2.attributes) {
|
|
856
857
|
const name = attribute.name.toLowerCase();
|
|
857
858
|
if (!isPreservedAttribute(name)) {
|
|
858
859
|
continue;
|
|
@@ -867,28 +868,28 @@ function openingTag(element) {
|
|
|
867
868
|
function normalizedText(value) {
|
|
868
869
|
return redactSensitiveText(value).replaceAll(/\s+/gu, " ").trim();
|
|
869
870
|
}
|
|
870
|
-
function serializeElement(
|
|
871
|
+
function serializeElement(element2, depth, state, lines) {
|
|
871
872
|
if (state.nodeCount >= DOM_COLLECTION_LIMITS.maxNodes) {
|
|
872
873
|
state.truncated = true;
|
|
873
874
|
return;
|
|
874
875
|
}
|
|
875
876
|
state.nodeCount += 1;
|
|
876
877
|
const indent = " ".repeat(depth);
|
|
877
|
-
const tagName =
|
|
878
|
-
lines.push(`${indent}${openingTag(
|
|
878
|
+
const tagName = element2.tagName.toLowerCase();
|
|
879
|
+
lines.push(`${indent}${openingTag(element2)}`);
|
|
879
880
|
if (VOID_ELEMENT_NAMES.has(tagName)) {
|
|
880
881
|
return;
|
|
881
882
|
}
|
|
882
|
-
for (const child of
|
|
883
|
+
for (const child of element2.childNodes) {
|
|
883
884
|
if (state.nodeCount >= DOM_COLLECTION_LIMITS.maxNodes) {
|
|
884
885
|
state.truncated = true;
|
|
885
886
|
break;
|
|
886
887
|
}
|
|
887
888
|
if (child.nodeType === 3) {
|
|
888
|
-
const
|
|
889
|
-
if (
|
|
889
|
+
const text2 = normalizedText(child.textContent ?? "");
|
|
890
|
+
if (text2.length > 0) {
|
|
890
891
|
state.nodeCount += 1;
|
|
891
|
-
const truncated =
|
|
892
|
+
const truncated = text2.length <= DOM_COLLECTION_LIMITS.maxTextCharacters ? text2 : `${text2.slice(0, DOM_COLLECTION_LIMITS.maxTextCharacters)}\u2026`;
|
|
892
893
|
lines.push(`${" ".repeat(depth + 1)}${escapeHtml(truncated)}`);
|
|
893
894
|
}
|
|
894
895
|
continue;
|
|
@@ -907,9 +908,9 @@ function serializeElement(element, depth, state, lines) {
|
|
|
907
908
|
}
|
|
908
909
|
lines.push(`${indent}</${tagName}>`);
|
|
909
910
|
}
|
|
910
|
-
function parentContext(
|
|
911
|
+
function parentContext(element2) {
|
|
911
912
|
const parents = [];
|
|
912
|
-
let parent =
|
|
913
|
+
let parent = element2.parentElement;
|
|
913
914
|
while (parent !== null && parents.length < DOM_COLLECTION_LIMITS.maxParentDepth) {
|
|
914
915
|
parents.push(openingTag(parent));
|
|
915
916
|
parent = parent.parentElement;
|
|
@@ -930,26 +931,26 @@ function escapeCssIdentifier(value) {
|
|
|
930
931
|
function escapeCssAttribute(value) {
|
|
931
932
|
return value.replaceAll("\\", "\\\\").replaceAll('"', '\\"');
|
|
932
933
|
}
|
|
933
|
-
function selectorSegment(
|
|
934
|
-
const tagName =
|
|
935
|
-
if (
|
|
936
|
-
return `${tagName}#${escapeCssIdentifier(
|
|
934
|
+
function selectorSegment(element2) {
|
|
935
|
+
const tagName = element2.tagName.toLowerCase();
|
|
936
|
+
if (element2.id.length > 0) {
|
|
937
|
+
return `${tagName}#${escapeCssIdentifier(element2.id)}`;
|
|
937
938
|
}
|
|
938
|
-
const testId =
|
|
939
|
+
const testId = element2.getAttribute("data-testid");
|
|
939
940
|
if (testId !== null && testId.length > 0) {
|
|
940
941
|
return `${tagName}[data-testid="${escapeCssAttribute(testId)}"]`;
|
|
941
942
|
}
|
|
942
|
-
const classes = Array.from(
|
|
943
|
-
const sameTagSiblings =
|
|
944
|
-
(sibling) => sibling.tagName ===
|
|
943
|
+
const classes = Array.from(element2.classList).slice(0, 2).map((name) => `.${escapeCssIdentifier(name)}`).join("");
|
|
944
|
+
const sameTagSiblings = element2.parentElement === null ? [] : Array.from(element2.parentElement.children).filter(
|
|
945
|
+
(sibling) => sibling.tagName === element2.tagName
|
|
945
946
|
);
|
|
946
|
-
const position = sameTagSiblings.indexOf(
|
|
947
|
+
const position = sameTagSiblings.indexOf(element2);
|
|
947
948
|
const nth = sameTagSiblings.length > 1 && position >= 0 ? `:nth-of-type(${String(position + 1)})` : "";
|
|
948
949
|
return `${tagName}${classes}${nth}`;
|
|
949
950
|
}
|
|
950
|
-
function createSelector(
|
|
951
|
+
function createSelector(element2) {
|
|
951
952
|
const segments = [];
|
|
952
|
-
let current =
|
|
953
|
+
let current = element2;
|
|
953
954
|
while (current !== null && segments.length < 5) {
|
|
954
955
|
const segment = selectorSegment(current);
|
|
955
956
|
segments.unshift(segment);
|
|
@@ -968,15 +969,15 @@ function collectElementContext(options) {
|
|
|
968
969
|
if (parents.length > 0) {
|
|
969
970
|
lines.push("<!-- Parent context: nearest first -->", ...parents);
|
|
970
971
|
}
|
|
971
|
-
const
|
|
972
|
+
const text2 = normalizedText(options.element.textContent);
|
|
972
973
|
const rect = options.element.getBoundingClientRect();
|
|
973
974
|
const role = options.element.getAttribute("role");
|
|
974
975
|
return Object.freeze({
|
|
975
976
|
tagName: options.element.tagName.toLowerCase(),
|
|
976
977
|
selector: createSelector(options.element),
|
|
977
978
|
sanitizedHtml: truncateContext(lines.join("\n"), options.maxCharacters),
|
|
978
|
-
...
|
|
979
|
-
textPreview:
|
|
979
|
+
...text2.length === 0 ? {} : {
|
|
980
|
+
textPreview: text2.length <= DOM_COLLECTION_LIMITS.maxTextCharacters ? text2 : `${text2.slice(0, DOM_COLLECTION_LIMITS.maxTextCharacters)}\u2026`
|
|
980
981
|
},
|
|
981
982
|
...role === null ? {} : { role },
|
|
982
983
|
rect: Object.freeze({
|
|
@@ -995,11 +996,11 @@ function isApplePlatform(platform) {
|
|
|
995
996
|
function normalizedKey(key) {
|
|
996
997
|
return key.toLowerCase();
|
|
997
998
|
}
|
|
998
|
-
function isTextEntryTarget(
|
|
999
|
-
if (!(
|
|
999
|
+
function isTextEntryTarget(target2) {
|
|
1000
|
+
if (!(target2 instanceof Element)) {
|
|
1000
1001
|
return false;
|
|
1001
1002
|
}
|
|
1002
|
-
return
|
|
1003
|
+
return target2 instanceof HTMLInputElement || target2 instanceof HTMLTextAreaElement || target2 instanceof HTMLSelectElement || target2.closest("[contenteditable]:not([contenteditable='false'])") !== null;
|
|
1003
1004
|
}
|
|
1004
1005
|
function matchesShortcut(event, shortcut, platform) {
|
|
1005
1006
|
const tokens = shortcut.split("+").map((token) => token.trim().toLowerCase()).filter((token) => token.length > 0);
|
|
@@ -1049,15 +1050,25 @@ function unionRects(rects) {
|
|
|
1049
1050
|
height: bottom - top
|
|
1050
1051
|
});
|
|
1051
1052
|
}
|
|
1052
|
-
function
|
|
1053
|
-
const display = view.getComputedStyle(element).display;
|
|
1053
|
+
function measureElementRect(element2, display) {
|
|
1054
1054
|
if (display.startsWith("inline")) {
|
|
1055
|
-
const lineBoxRect = unionRects(Array.from(
|
|
1055
|
+
const lineBoxRect = unionRects(Array.from(element2.getClientRects()));
|
|
1056
1056
|
if (lineBoxRect !== void 0) {
|
|
1057
1057
|
return lineBoxRect;
|
|
1058
1058
|
}
|
|
1059
1059
|
}
|
|
1060
|
-
return toElementRect(
|
|
1060
|
+
return toElementRect(element2.getBoundingClientRect());
|
|
1061
|
+
}
|
|
1062
|
+
function getElementRect(element2, view) {
|
|
1063
|
+
return measureElementRect(element2, view.getComputedStyle(element2).display);
|
|
1064
|
+
}
|
|
1065
|
+
function getVisibleElementRect(element2, view) {
|
|
1066
|
+
const style = view.getComputedStyle(element2);
|
|
1067
|
+
if (style.display === "none" || style.visibility === "hidden") {
|
|
1068
|
+
return void 0;
|
|
1069
|
+
}
|
|
1070
|
+
const rect = measureElementRect(element2, style.display);
|
|
1071
|
+
return rect.width > 0 && rect.height > 0 ? rect : void 0;
|
|
1061
1072
|
}
|
|
1062
1073
|
|
|
1063
1074
|
// src/ui/ui-constants.ts
|
|
@@ -1068,32 +1079,27 @@ var UI_Z_INDEX = Object.freeze({
|
|
|
1068
1079
|
});
|
|
1069
1080
|
|
|
1070
1081
|
// src/picker/hit-test.ts
|
|
1071
|
-
function isInsideSpotPatchUI(
|
|
1072
|
-
if (
|
|
1082
|
+
function isInsideSpotPatchUI(element2) {
|
|
1083
|
+
if (element2.closest(`[${UI_MARKER_ATTRIBUTE}]`) !== null) {
|
|
1073
1084
|
return true;
|
|
1074
1085
|
}
|
|
1075
|
-
const root =
|
|
1086
|
+
const root = element2.getRootNode();
|
|
1076
1087
|
return root instanceof ShadowRoot && root.host.hasAttribute(UI_MARKER_ATTRIBUTE);
|
|
1077
1088
|
}
|
|
1078
|
-
function hasVisibleArea(
|
|
1079
|
-
|
|
1080
|
-
if (style.display === "none" || style.visibility === "hidden") {
|
|
1081
|
-
return false;
|
|
1082
|
-
}
|
|
1083
|
-
const rect = element.getBoundingClientRect();
|
|
1084
|
-
return rect.width > 0 && rect.height > 0;
|
|
1089
|
+
function hasVisibleArea(element2, view) {
|
|
1090
|
+
return getVisibleElementRect(element2, view) !== void 0;
|
|
1085
1091
|
}
|
|
1086
|
-
function isDocumentRoot(
|
|
1087
|
-
return
|
|
1092
|
+
function isDocumentRoot(element2) {
|
|
1093
|
+
return element2.tagName === "HTML" || element2.tagName === "BODY";
|
|
1088
1094
|
}
|
|
1089
1095
|
function pickElementAt(document, view, clientX, clientY) {
|
|
1090
1096
|
const visibleCandidates = document.elementsFromPoint(clientX, clientY).filter(
|
|
1091
|
-
(
|
|
1097
|
+
(element2) => !isInsideSpotPatchUI(element2) && hasVisibleArea(element2, view)
|
|
1092
1098
|
);
|
|
1093
|
-
return visibleCandidates.find((
|
|
1099
|
+
return visibleCandidates.find((element2) => !isDocumentRoot(element2)) ?? visibleCandidates[0];
|
|
1094
1100
|
}
|
|
1095
|
-
function isSpotPatchUIEventTarget(
|
|
1096
|
-
return
|
|
1101
|
+
function isSpotPatchUIEventTarget(target2) {
|
|
1102
|
+
return target2 instanceof Element && isInsideSpotPatchUI(target2);
|
|
1097
1103
|
}
|
|
1098
1104
|
|
|
1099
1105
|
// src/prompt/prompt-composer.ts
|
|
@@ -1172,10 +1178,10 @@ function fenced(language, value) {
|
|
|
1172
1178
|
${value}
|
|
1173
1179
|
${fence}`;
|
|
1174
1180
|
}
|
|
1175
|
-
function sourceLocation(
|
|
1176
|
-
const path =
|
|
1177
|
-
const line =
|
|
1178
|
-
const column =
|
|
1181
|
+
function sourceLocation(target2, messages) {
|
|
1182
|
+
const path = target2.code?.relativePath ?? target2.source.relativePath;
|
|
1183
|
+
const line = target2.source.line;
|
|
1184
|
+
const column = target2.source.column;
|
|
1179
1185
|
if (path === void 0) {
|
|
1180
1186
|
return messages.unavailable;
|
|
1181
1187
|
}
|
|
@@ -1194,10 +1200,10 @@ function renderRule(rule) {
|
|
|
1194
1200
|
}`;
|
|
1195
1201
|
return [...metadata, body].join("\n");
|
|
1196
1202
|
}
|
|
1197
|
-
function renderStyles(
|
|
1203
|
+
function renderStyles(target2, rules, messages) {
|
|
1198
1204
|
const metadata = [
|
|
1199
|
-
|
|
1200
|
-
|
|
1205
|
+
target2.styles.classNames.length === 0 ? void 0 : `/* classes: ${target2.styles.classNames.map(sanitizeCssText).join(" ")} */`,
|
|
1206
|
+
target2.styles.inlineStyle === void 0 ? void 0 : `/* inline: ${sanitizeCssText(target2.styles.inlineStyle)} */`
|
|
1201
1207
|
].filter((line) => line !== void 0);
|
|
1202
1208
|
const blocks = [...metadata, ...rules.map(renderRule)];
|
|
1203
1209
|
return blocks.length === 0 ? messages.unavailable : fenced("css", blocks.join("\n\n"));
|
|
@@ -1210,41 +1216,47 @@ function renderComputed(entries, messages) {
|
|
|
1210
1216
|
).join("\n")
|
|
1211
1217
|
);
|
|
1212
1218
|
}
|
|
1213
|
-
function renderTarget(
|
|
1219
|
+
function renderTarget(target2, draft, index, messages) {
|
|
1214
1220
|
const reactLines = [
|
|
1215
|
-
`- ${messages.adapter}: ${
|
|
1216
|
-
...
|
|
1217
|
-
...
|
|
1218
|
-
`- ${messages.component}: ${redactSensitiveText(
|
|
1221
|
+
`- ${messages.adapter}: ${target2.react.supported ? messages.supported : messages.unsupported}`,
|
|
1222
|
+
...target2.react.version === void 0 ? [] : [`- ${messages.reactVersion}: ${redactSensitiveText(target2.react.version)}`],
|
|
1223
|
+
...target2.react.componentName === void 0 ? [] : [
|
|
1224
|
+
`- ${messages.component}: ${redactSensitiveText(target2.react.componentName)}`
|
|
1219
1225
|
],
|
|
1220
1226
|
...draft.reactStack.length === 0 ? [] : [
|
|
1221
1227
|
`- ${messages.stack}: ${draft.reactStack.map(redactSensitiveText).join(" > ")}`
|
|
1222
1228
|
]
|
|
1223
1229
|
];
|
|
1224
|
-
const
|
|
1230
|
+
const code2 = target2.code === void 0 || draft.codeLines.length === 0 ? messages.unavailable : `- ${messages.boundary}: ${target2.code.boundary}
|
|
1225
1231
|
|
|
1226
1232
|
${fenced(
|
|
1227
|
-
|
|
1233
|
+
target2.code.language,
|
|
1228
1234
|
redactSensitiveText(draft.codeLines.join("\n"))
|
|
1229
1235
|
)}`;
|
|
1230
1236
|
return [
|
|
1231
1237
|
`### ${messages.target(index + 1)}`,
|
|
1232
1238
|
`#### ${messages.requestedChange}`,
|
|
1233
1239
|
draft.instruction,
|
|
1240
|
+
...target2.page === void 0 ? [] : [
|
|
1241
|
+
`#### ${messages.pageEnvironment}`,
|
|
1242
|
+
`- ${messages.url}: <${sanitizeUrl(target2.page.url, target2.page.url)}>
|
|
1243
|
+
- ${messages.pathname}: ${redactSensitiveText(target2.page.pathname)}
|
|
1244
|
+
- ${messages.title}: ${redactSensitiveText(target2.page.title) || messages.unavailable}`
|
|
1245
|
+
],
|
|
1234
1246
|
`#### ${messages.reactContext}`,
|
|
1235
1247
|
reactLines.join("\n"),
|
|
1236
1248
|
`#### ${messages.source}`,
|
|
1237
|
-
`- ${messages.file}: ${sourceLocation(
|
|
1238
|
-
- ${messages.origin}: ${
|
|
1239
|
-
- ${messages.confidence}: ${
|
|
1249
|
+
`- ${messages.file}: ${sourceLocation(target2, messages)}
|
|
1250
|
+
- ${messages.origin}: ${target2.source.origin}
|
|
1251
|
+
- ${messages.confidence}: ${target2.source.confidence}`,
|
|
1240
1252
|
`#### ${messages.element}`,
|
|
1241
1253
|
fenced("html", redactSensitiveText(draft.dom)),
|
|
1242
1254
|
`#### ${messages.styles}`,
|
|
1243
|
-
renderStyles(
|
|
1255
|
+
renderStyles(target2, draft.matchedRules, messages),
|
|
1244
1256
|
`#### ${messages.computedStyles}`,
|
|
1245
1257
|
renderComputed(draft.computedEntries, messages),
|
|
1246
1258
|
`#### ${messages.code}`,
|
|
1247
|
-
|
|
1259
|
+
code2,
|
|
1248
1260
|
`#### ${messages.warnings}`,
|
|
1249
1261
|
draft.warnings.length === 0 ? `- ${messages.none}` : draft.warnings.map((warning) => `- ${redactSensitiveText(warning)}`).join("\n")
|
|
1250
1262
|
].join("\n\n");
|
|
@@ -1260,19 +1272,19 @@ function renderPrompt(annotation, draft) {
|
|
|
1260
1272
|
- ${messages.viewport}: ${String(annotation.page.viewportWidth)} \xD7 ${String(annotation.page.viewportHeight)}
|
|
1261
1273
|
- ${messages.devicePixelRatio}: ${String(annotation.page.devicePixelRatio)}`,
|
|
1262
1274
|
`## ${messages.selectedTargets(annotation.targets.length)}`,
|
|
1263
|
-
annotation.targets.map((
|
|
1275
|
+
annotation.targets.map((target2, index) => {
|
|
1264
1276
|
const targetDraft = draft.targets[index];
|
|
1265
1277
|
if (targetDraft === void 0) {
|
|
1266
1278
|
throw new RangeError("Prompt target draft is missing.");
|
|
1267
1279
|
}
|
|
1268
|
-
return renderTarget(
|
|
1280
|
+
return renderTarget(target2, targetDraft, index, messages);
|
|
1269
1281
|
}).join("\n\n"),
|
|
1270
1282
|
`## ${messages.modificationRequirements}`,
|
|
1271
1283
|
messages.modificationConstraint
|
|
1272
1284
|
].join("\n\n");
|
|
1273
1285
|
}
|
|
1274
|
-
function shrinkCode(
|
|
1275
|
-
if (draft.codeLines.length === 0 ||
|
|
1286
|
+
function shrinkCode(target2, draft) {
|
|
1287
|
+
if (draft.codeLines.length === 0 || target2.code === void 0) {
|
|
1276
1288
|
return false;
|
|
1277
1289
|
}
|
|
1278
1290
|
if (draft.codeLines.length === 1) {
|
|
@@ -1284,9 +1296,9 @@ function shrinkCode(target, draft) {
|
|
|
1284
1296
|
}
|
|
1285
1297
|
return true;
|
|
1286
1298
|
}
|
|
1287
|
-
const selectedLine =
|
|
1288
|
-
const firstDistance = Math.abs(
|
|
1289
|
-
const lastLine =
|
|
1299
|
+
const selectedLine = target2.source.line ?? target2.code.startLine;
|
|
1300
|
+
const firstDistance = Math.abs(target2.code.startLine - selectedLine);
|
|
1301
|
+
const lastLine = target2.code.startLine + draft.codeLines.length - 1;
|
|
1290
1302
|
const lastDistance = Math.abs(lastLine - selectedLine);
|
|
1291
1303
|
if (lastDistance >= firstDistance) {
|
|
1292
1304
|
draft.codeLines.pop();
|
|
@@ -1295,15 +1307,15 @@ function shrinkCode(target, draft) {
|
|
|
1295
1307
|
}
|
|
1296
1308
|
return true;
|
|
1297
1309
|
}
|
|
1298
|
-
function createTargetDraft(
|
|
1310
|
+
function createTargetDraft(target2) {
|
|
1299
1311
|
return {
|
|
1300
|
-
instruction: redactSensitiveText(
|
|
1301
|
-
reactStack: [...
|
|
1302
|
-
dom:
|
|
1303
|
-
matchedRules: [...
|
|
1304
|
-
computedEntries: Object.entries(
|
|
1305
|
-
codeLines:
|
|
1306
|
-
warnings: Array.from(/* @__PURE__ */ new Set([...
|
|
1312
|
+
instruction: redactSensitiveText(target2.instruction.trim()),
|
|
1313
|
+
reactStack: [...target2.react.componentStack],
|
|
1314
|
+
dom: target2.element.sanitizedHtml,
|
|
1315
|
+
matchedRules: [...target2.styles.matchedRules],
|
|
1316
|
+
computedEntries: Object.entries(target2.styles.computed),
|
|
1317
|
+
codeLines: target2.code?.excerpt.split(/\r?\n/u) ?? [],
|
|
1318
|
+
warnings: Array.from(/* @__PURE__ */ new Set([...target2.styles.warnings, ...target2.warnings]))
|
|
1307
1319
|
};
|
|
1308
1320
|
}
|
|
1309
1321
|
function createDraft(annotation) {
|
|
@@ -1332,9 +1344,9 @@ function shrinkTargetsFairly(annotation, draft, cursor) {
|
|
|
1332
1344
|
for (const operation of operations) {
|
|
1333
1345
|
for (let offset = 0; offset < annotation.targets.length; offset += 1) {
|
|
1334
1346
|
const index = (cursor + offset) % annotation.targets.length;
|
|
1335
|
-
const
|
|
1347
|
+
const target2 = annotation.targets[index];
|
|
1336
1348
|
const targetDraft = draft.targets[index];
|
|
1337
|
-
if (
|
|
1349
|
+
if (target2 !== void 0 && targetDraft !== void 0 && operation(target2, targetDraft)) {
|
|
1338
1350
|
return (index + 1) % annotation.targets.length;
|
|
1339
1351
|
}
|
|
1340
1352
|
}
|
|
@@ -1343,15 +1355,15 @@ function shrinkTargetsFairly(annotation, draft, cursor) {
|
|
|
1343
1355
|
}
|
|
1344
1356
|
function renderCompactPrompt(annotation, draft) {
|
|
1345
1357
|
const messages = PROMPT_MESSAGES[annotation.locale];
|
|
1346
|
-
const targets = annotation.targets.map((
|
|
1358
|
+
const targets = annotation.targets.map((target2, index) => {
|
|
1347
1359
|
const targetDraft = draft.targets[index];
|
|
1348
|
-
const component =
|
|
1360
|
+
const component = target2.react.componentName;
|
|
1349
1361
|
return [
|
|
1350
1362
|
`### ${messages.target(index + 1)}`,
|
|
1351
|
-
`- ${messages.requestedChange}: ${targetDraft?.instruction ?? redactSensitiveText(
|
|
1352
|
-
`- ${messages.file}: ${sourceLocation(
|
|
1363
|
+
`- ${messages.requestedChange}: ${targetDraft?.instruction ?? redactSensitiveText(target2.instruction)}`,
|
|
1364
|
+
`- ${messages.file}: ${sourceLocation(target2, messages)}`,
|
|
1353
1365
|
...component === void 0 ? [] : [`- ${messages.component}: ${redactSensitiveText(component)}`],
|
|
1354
|
-
`- ${messages.element}: ${redactSensitiveText(openingTag2(targetDraft?.dom ??
|
|
1366
|
+
`- ${messages.element}: ${redactSensitiveText(openingTag2(targetDraft?.dom ?? target2.element.sanitizedHtml, messages.unavailable))}`
|
|
1355
1367
|
].join("\n");
|
|
1356
1368
|
});
|
|
1357
1369
|
return [
|
|
@@ -1409,7 +1421,10 @@ var STATES = Object.freeze({
|
|
|
1409
1421
|
});
|
|
1410
1422
|
var INITIAL_RUNTIME_STATE = STATES.idle;
|
|
1411
1423
|
function reduceIdle(event) {
|
|
1412
|
-
|
|
1424
|
+
if (event.type === "ACTIVATE") {
|
|
1425
|
+
return STATES.inspecting;
|
|
1426
|
+
}
|
|
1427
|
+
return event.type === "RESTORE" ? STATES.selected : STATES.idle;
|
|
1413
1428
|
}
|
|
1414
1429
|
function reduceInspecting(event) {
|
|
1415
1430
|
switch (event.type) {
|
|
@@ -1461,6 +1476,121 @@ function reduceRuntimeState(state, event) {
|
|
|
1461
1476
|
}
|
|
1462
1477
|
}
|
|
1463
1478
|
|
|
1479
|
+
// src/state/selection-session.ts
|
|
1480
|
+
var STORAGE_PREFIX = "spotpatch:selection:";
|
|
1481
|
+
var SNAPSHOT_VERSION = 1;
|
|
1482
|
+
var MAX_SNAPSHOT_CHARACTERS = 1e6;
|
|
1483
|
+
function record(value) {
|
|
1484
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
1485
|
+
}
|
|
1486
|
+
function text(value) {
|
|
1487
|
+
return typeof value === "string";
|
|
1488
|
+
}
|
|
1489
|
+
function optionalText(value) {
|
|
1490
|
+
return value === void 0 || text(value);
|
|
1491
|
+
}
|
|
1492
|
+
function strings(value) {
|
|
1493
|
+
return Array.isArray(value) && value.length <= 256 && value.every(text);
|
|
1494
|
+
}
|
|
1495
|
+
function finiteNumber(value) {
|
|
1496
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
1497
|
+
}
|
|
1498
|
+
function optionalNumber(value) {
|
|
1499
|
+
return value === void 0 || finiteNumber(value);
|
|
1500
|
+
}
|
|
1501
|
+
function source(value) {
|
|
1502
|
+
const item = record(value);
|
|
1503
|
+
return item !== void 0 && text(item.origin) && text(item.confidence) && optionalText(item.fileId) && optionalText(item.relativePath) && optionalNumber(item.line) && optionalNumber(item.column);
|
|
1504
|
+
}
|
|
1505
|
+
function react(value) {
|
|
1506
|
+
const item = record(value);
|
|
1507
|
+
return item !== void 0 && typeof item.supported === "boolean" && optionalText(item.version) && optionalText(item.componentName) && strings(item.componentStack) && (item.source === void 0 || source(item.source));
|
|
1508
|
+
}
|
|
1509
|
+
function page(value) {
|
|
1510
|
+
const item = record(value);
|
|
1511
|
+
return item !== void 0 && text(item.url) && text(item.pathname) && text(item.title) && finiteNumber(item.viewportWidth) && finiteNumber(item.viewportHeight) && finiteNumber(item.devicePixelRatio);
|
|
1512
|
+
}
|
|
1513
|
+
function element(value) {
|
|
1514
|
+
const item = record(value);
|
|
1515
|
+
const rect = record(item?.rect);
|
|
1516
|
+
return item !== void 0 && text(item.tagName) && text(item.selector) && text(item.sanitizedHtml) && optionalText(item.textPreview) && optionalText(item.role) && rect !== void 0 && finiteNumber(rect.x) && finiteNumber(rect.y) && finiteNumber(rect.width) && finiteNumber(rect.height);
|
|
1517
|
+
}
|
|
1518
|
+
function styles(value) {
|
|
1519
|
+
const item = record(value);
|
|
1520
|
+
const computed = record(item?.computed);
|
|
1521
|
+
return item !== void 0 && strings(item.classNames) && optionalText(item.inlineStyle) && Array.isArray(item.matchedRules) && item.matchedRules.length <= 256 && item.matchedRules.every((value2) => {
|
|
1522
|
+
const rule = record(value2);
|
|
1523
|
+
return rule !== void 0 && text(rule.selector) && text(rule.declarations) && optionalText(rule.source) && optionalText(rule.media);
|
|
1524
|
+
}) && computed !== void 0 && Object.values(computed).every(text) && strings(item.warnings);
|
|
1525
|
+
}
|
|
1526
|
+
function code(value) {
|
|
1527
|
+
const item = record(value);
|
|
1528
|
+
return item !== void 0 && text(item.relativePath) && text(item.language) && finiteNumber(item.startLine) && finiteNumber(item.endLine) && text(item.excerpt) && text(item.boundary);
|
|
1529
|
+
}
|
|
1530
|
+
function target(value) {
|
|
1531
|
+
const item = record(value);
|
|
1532
|
+
return item !== void 0 && text(item.id) && text(item.instruction) && page(item.page) && source(item.source) && react(item.react) && element(item.element) && styles(item.styles) && (item.code === void 0 || code(item.code));
|
|
1533
|
+
}
|
|
1534
|
+
function parseSnapshot(value, maximumTargets) {
|
|
1535
|
+
const item = record(value);
|
|
1536
|
+
if (item?.version !== SNAPSHOT_VERSION || typeof item.open !== "boolean" || !Number.isSafeInteger(item.sequence) || Number(item.sequence) < 0 || item.activeTargetId !== void 0 && typeof item.activeTargetId !== "string" || !Array.isArray(item.targets) || item.targets.length === 0 || item.targets.length > maximumTargets || !item.targets.every(target)) {
|
|
1537
|
+
return void 0;
|
|
1538
|
+
}
|
|
1539
|
+
const targets = item.targets;
|
|
1540
|
+
const ids = targets.map(({ id }) => id);
|
|
1541
|
+
if (new Set(ids).size !== ids.length || item.activeTargetId !== void 0 && !ids.includes(item.activeTargetId)) {
|
|
1542
|
+
return void 0;
|
|
1543
|
+
}
|
|
1544
|
+
return {
|
|
1545
|
+
...item.activeTargetId === void 0 ? {} : { activeTargetId: item.activeTargetId },
|
|
1546
|
+
open: item.open,
|
|
1547
|
+
sequence: Number(item.sequence),
|
|
1548
|
+
targets
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
function createSelectionSession(window, sessionId, maximumTargets) {
|
|
1552
|
+
const key = `${STORAGE_PREFIX}${sessionId}`;
|
|
1553
|
+
let storage;
|
|
1554
|
+
try {
|
|
1555
|
+
storage = window.sessionStorage;
|
|
1556
|
+
} catch {
|
|
1557
|
+
storage = void 0;
|
|
1558
|
+
}
|
|
1559
|
+
return Object.freeze({
|
|
1560
|
+
clear() {
|
|
1561
|
+
try {
|
|
1562
|
+
storage?.removeItem(key);
|
|
1563
|
+
} catch {
|
|
1564
|
+
}
|
|
1565
|
+
},
|
|
1566
|
+
load() {
|
|
1567
|
+
let serialized;
|
|
1568
|
+
try {
|
|
1569
|
+
serialized = storage?.getItem(key) ?? null;
|
|
1570
|
+
} catch {
|
|
1571
|
+
return void 0;
|
|
1572
|
+
}
|
|
1573
|
+
if (serialized === null || serialized.length > MAX_SNAPSHOT_CHARACTERS) {
|
|
1574
|
+
return void 0;
|
|
1575
|
+
}
|
|
1576
|
+
try {
|
|
1577
|
+
return parseSnapshot(JSON.parse(serialized), maximumTargets);
|
|
1578
|
+
} catch {
|
|
1579
|
+
return void 0;
|
|
1580
|
+
}
|
|
1581
|
+
},
|
|
1582
|
+
save(snapshot) {
|
|
1583
|
+
try {
|
|
1584
|
+
storage?.setItem(
|
|
1585
|
+
key,
|
|
1586
|
+
JSON.stringify({ version: SNAPSHOT_VERSION, ...snapshot })
|
|
1587
|
+
);
|
|
1588
|
+
} catch {
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1464
1594
|
// src/source/source-resolver.ts
|
|
1465
1595
|
import {
|
|
1466
1596
|
parseSourceMarker,
|
|
@@ -1470,11 +1600,11 @@ var EMPTY_REACT_CONTEXT = Object.freeze({
|
|
|
1470
1600
|
supported: false,
|
|
1471
1601
|
componentStack: Object.freeze([])
|
|
1472
1602
|
});
|
|
1473
|
-
function directMarker(
|
|
1474
|
-
return parseSourceMarker(
|
|
1603
|
+
function directMarker(element2) {
|
|
1604
|
+
return parseSourceMarker(element2.getAttribute(SOURCE_MARKER_ATTRIBUTE));
|
|
1475
1605
|
}
|
|
1476
|
-
function ancestorMarker(
|
|
1477
|
-
let ancestor =
|
|
1606
|
+
function ancestorMarker(element2) {
|
|
1607
|
+
let ancestor = element2.parentElement;
|
|
1478
1608
|
while (ancestor !== null) {
|
|
1479
1609
|
const marker = directMarker(ancestor);
|
|
1480
1610
|
if (marker !== void 0) {
|
|
@@ -1496,21 +1626,21 @@ function markerSource(marker, origin, confidence) {
|
|
|
1496
1626
|
function unknownSource() {
|
|
1497
1627
|
return Object.freeze({ origin: "none", confidence: "unknown" });
|
|
1498
1628
|
}
|
|
1499
|
-
function sourceRefToMarker(
|
|
1500
|
-
return
|
|
1501
|
-
fileId:
|
|
1502
|
-
line:
|
|
1503
|
-
column:
|
|
1629
|
+
function sourceRefToMarker(source2) {
|
|
1630
|
+
return source2.fileId === void 0 || source2.line === void 0 || source2.column === void 0 ? void 0 : Object.freeze({
|
|
1631
|
+
fileId: source2.fileId,
|
|
1632
|
+
line: source2.line,
|
|
1633
|
+
column: source2.column
|
|
1504
1634
|
});
|
|
1505
1635
|
}
|
|
1506
1636
|
function createSourceResolver(options) {
|
|
1507
1637
|
let adapterEnabled = true;
|
|
1508
|
-
function inspectReact(
|
|
1638
|
+
function inspectReact(element2) {
|
|
1509
1639
|
if (!adapterEnabled) {
|
|
1510
1640
|
return EMPTY_REACT_CONTEXT;
|
|
1511
1641
|
}
|
|
1512
1642
|
try {
|
|
1513
|
-
return options.adapter.inspect(
|
|
1643
|
+
return options.adapter.inspect(element2);
|
|
1514
1644
|
} catch {
|
|
1515
1645
|
adapterEnabled = false;
|
|
1516
1646
|
options.onAdapterError?.();
|
|
@@ -1518,26 +1648,26 @@ function createSourceResolver(options) {
|
|
|
1518
1648
|
}
|
|
1519
1649
|
}
|
|
1520
1650
|
return Object.freeze({
|
|
1521
|
-
resolve(
|
|
1522
|
-
const marker = directMarker(
|
|
1523
|
-
const
|
|
1651
|
+
resolve(element2) {
|
|
1652
|
+
const marker = directMarker(element2);
|
|
1653
|
+
const react2 = inspectReact(element2);
|
|
1524
1654
|
if (marker !== void 0) {
|
|
1525
1655
|
return Object.freeze({
|
|
1526
|
-
react,
|
|
1656
|
+
react: react2,
|
|
1527
1657
|
source: markerSource(marker, "jsx-host", "exact")
|
|
1528
1658
|
});
|
|
1529
1659
|
}
|
|
1530
|
-
if (
|
|
1531
|
-
return Object.freeze({ react, source:
|
|
1660
|
+
if (react2.source !== void 0) {
|
|
1661
|
+
return Object.freeze({ react: react2, source: react2.source });
|
|
1532
1662
|
}
|
|
1533
|
-
const nearestAncestor = ancestorMarker(
|
|
1663
|
+
const nearestAncestor = ancestorMarker(element2);
|
|
1534
1664
|
if (nearestAncestor !== void 0) {
|
|
1535
1665
|
return Object.freeze({
|
|
1536
|
-
react,
|
|
1666
|
+
react: react2,
|
|
1537
1667
|
source: markerSource(nearestAncestor, "dom-ancestor", "approximate")
|
|
1538
1668
|
});
|
|
1539
1669
|
}
|
|
1540
|
-
return Object.freeze({ react, source: unknownSource() });
|
|
1670
|
+
return Object.freeze({ react: react2, source: unknownSource() });
|
|
1541
1671
|
},
|
|
1542
1672
|
dispose() {
|
|
1543
1673
|
adapterEnabled = false;
|
|
@@ -1555,9 +1685,9 @@ import {
|
|
|
1555
1685
|
|
|
1556
1686
|
// src/ui/dom.ts
|
|
1557
1687
|
function createMarkedElement(document, tagName) {
|
|
1558
|
-
const
|
|
1559
|
-
|
|
1560
|
-
return
|
|
1688
|
+
const element2 = document.createElement(tagName);
|
|
1689
|
+
element2.setAttribute(UI_MARKER_ATTRIBUTE, "");
|
|
1690
|
+
return element2;
|
|
1561
1691
|
}
|
|
1562
1692
|
function createButton(document, label, className = "") {
|
|
1563
1693
|
const button = createMarkedElement(document, "button");
|
|
@@ -1570,7 +1700,7 @@ function createButton(document, label, className = "") {
|
|
|
1570
1700
|
// src/ui/agent-panel.ts
|
|
1571
1701
|
var AGENT_PANEL_STYLES = `
|
|
1572
1702
|
.spotpatch-agent {
|
|
1573
|
-
margin-top:
|
|
1703
|
+
margin-top: 10px;
|
|
1574
1704
|
overflow: hidden;
|
|
1575
1705
|
border: 1px solid var(--spotpatch-border-subtle);
|
|
1576
1706
|
border-radius: var(--spotpatch-radius-card);
|
|
@@ -1580,36 +1710,36 @@ var AGENT_PANEL_STYLES = `
|
|
|
1580
1710
|
display: flex;
|
|
1581
1711
|
align-items: center;
|
|
1582
1712
|
justify-content: space-between;
|
|
1583
|
-
gap:
|
|
1584
|
-
padding:
|
|
1713
|
+
gap: 10px;
|
|
1714
|
+
padding: 10px 12px;
|
|
1585
1715
|
border-bottom: 1px solid rgb(255 255 255 / 7%);
|
|
1586
1716
|
}
|
|
1587
|
-
.spotpatch-agent-title { color: #eef0f5; font-size:
|
|
1717
|
+
.spotpatch-agent-title { color: #eef0f5; font-size: 13px; font-weight: 650; }
|
|
1588
1718
|
.spotpatch-agent-badge {
|
|
1589
1719
|
border: 1px solid rgb(129 112 247 / 24%);
|
|
1590
1720
|
border-radius: 999px;
|
|
1591
1721
|
padding: 3px 7px;
|
|
1592
1722
|
color: #c5cafa;
|
|
1593
1723
|
background: rgb(109 93 246 / 9%);
|
|
1594
|
-
font-size:
|
|
1724
|
+
font-size: 10px;
|
|
1595
1725
|
font-weight: 650;
|
|
1596
1726
|
}
|
|
1597
|
-
.spotpatch-agent-setup { padding:
|
|
1598
|
-
.spotpatch-agent-selectors { display: grid; grid-template-columns: 1fr; gap:
|
|
1599
|
-
.spotpatch-agent-selectors label { min-width: 0; color: var(--spotpatch-text-secondary); font-size:
|
|
1727
|
+
.spotpatch-agent-setup { padding: 12px; }
|
|
1728
|
+
.spotpatch-agent-selectors { display: grid; grid-template-columns: 1fr; gap: 10px; }
|
|
1729
|
+
.spotpatch-agent-selectors label { min-width: 0; color: var(--spotpatch-text-secondary); font-size: 11.5px; font-weight: 580; }
|
|
1600
1730
|
.spotpatch-agent select {
|
|
1601
1731
|
box-sizing: border-box;
|
|
1602
1732
|
width: 100%;
|
|
1603
1733
|
min-width: 0;
|
|
1604
|
-
min-height:
|
|
1605
|
-
margin-top:
|
|
1734
|
+
min-height: 34px;
|
|
1735
|
+
margin-top: 4px;
|
|
1606
1736
|
border: 1px solid var(--spotpatch-border);
|
|
1607
|
-
border-radius:
|
|
1608
|
-
padding:
|
|
1737
|
+
border-radius: 8px;
|
|
1738
|
+
padding: 7px 32px 7px 9px;
|
|
1609
1739
|
color: #e8ebf2;
|
|
1610
1740
|
color-scheme: dark;
|
|
1611
1741
|
background: linear-gradient(180deg, rgb(255 255 255 / 4%), rgb(255 255 255 / 2%));
|
|
1612
|
-
font-size:
|
|
1742
|
+
font-size: 12px;
|
|
1613
1743
|
font-weight: 560;
|
|
1614
1744
|
line-height: 1.35;
|
|
1615
1745
|
outline: none;
|
|
@@ -1621,7 +1751,7 @@ var AGENT_PANEL_STYLES = `
|
|
|
1621
1751
|
@supports (appearance: base-select) {
|
|
1622
1752
|
.spotpatch-agent select,
|
|
1623
1753
|
::picker(select) { appearance: base-select; }
|
|
1624
|
-
.spotpatch-agent select { padding:
|
|
1754
|
+
.spotpatch-agent select { padding: 7px 9px; }
|
|
1625
1755
|
.spotpatch-agent select::picker-icon {
|
|
1626
1756
|
color: #9da6b5;
|
|
1627
1757
|
transition: rotate 180ms cubic-bezier(.2, .8, .2, 1);
|
|
@@ -1668,24 +1798,24 @@ var AGENT_PANEL_STYLES = `
|
|
|
1668
1798
|
.spotpatch-consent {
|
|
1669
1799
|
display: flex;
|
|
1670
1800
|
align-items: flex-start;
|
|
1671
|
-
gap:
|
|
1672
|
-
margin-top:
|
|
1801
|
+
gap: 8px;
|
|
1802
|
+
margin-top: 10px;
|
|
1673
1803
|
color: var(--spotpatch-text-secondary);
|
|
1674
1804
|
cursor: pointer;
|
|
1675
|
-
font-size:
|
|
1676
|
-
line-height: 1.
|
|
1805
|
+
font-size: 11.5px;
|
|
1806
|
+
line-height: 1.5;
|
|
1677
1807
|
}
|
|
1678
|
-
.spotpatch-consent input { width:
|
|
1808
|
+
.spotpatch-consent input { width: 14px; height: 14px; flex: none; margin: 2px 0 0; accent-color: var(--spotpatch-accent); }
|
|
1679
1809
|
.spotpatch-workspace-consent {
|
|
1680
|
-
margin-top:
|
|
1810
|
+
margin-top: 9px;
|
|
1681
1811
|
border: 1px solid rgb(251 191 36 / 18%);
|
|
1682
1812
|
border-radius: 10px;
|
|
1683
|
-
padding:
|
|
1813
|
+
padding: 9px 10px;
|
|
1684
1814
|
background: rgb(120 53 15 / 9%);
|
|
1685
1815
|
}
|
|
1686
|
-
.spotpatch-workspace-consent strong { display: block; color: #fde68a; font-size:
|
|
1687
|
-
.spotpatch-workspace-consent small { display: block; margin-top: 2px; color: #aeb6c4; font-size:
|
|
1688
|
-
.spotpatch-agent-health-list { display: grid; gap:
|
|
1816
|
+
.spotpatch-workspace-consent strong { display: block; color: #fde68a; font-size: 11.5px; font-weight: 620; }
|
|
1817
|
+
.spotpatch-workspace-consent small { display: block; margin-top: 2px; color: #aeb6c4; font-size: 10.5px; line-height: 1.45; }
|
|
1818
|
+
.spotpatch-agent-health-list { display: grid; gap: 6px; margin-top: 10px; }
|
|
1689
1819
|
.spotpatch-agent-workspace,
|
|
1690
1820
|
.spotpatch-agent-capability {
|
|
1691
1821
|
display: flex;
|
|
@@ -1693,7 +1823,7 @@ var AGENT_PANEL_STYLES = `
|
|
|
1693
1823
|
gap: 8px;
|
|
1694
1824
|
margin: 0;
|
|
1695
1825
|
color: #929bab;
|
|
1696
|
-
font-size:
|
|
1826
|
+
font-size: 11px;
|
|
1697
1827
|
}
|
|
1698
1828
|
.spotpatch-agent-capability::before {
|
|
1699
1829
|
width: 6px;
|
|
@@ -1723,7 +1853,7 @@ var AGENT_PANEL_STYLES = `
|
|
|
1723
1853
|
.spotpatch-agent-workspace[data-state="consent-required"]::before { background: #fbbf24; }
|
|
1724
1854
|
.spotpatch-agent-workspace[data-state="blocked"] { color: #fecaca; }
|
|
1725
1855
|
.spotpatch-agent-workspace[data-state="blocked"]::before { background: var(--spotpatch-danger); }
|
|
1726
|
-
.spotpatch-agent-job { padding:
|
|
1856
|
+
.spotpatch-agent-job { padding: 12px; }
|
|
1727
1857
|
.spotpatch-agent-job-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
|
1728
1858
|
.spotpatch-agent-model { min-width: 0; overflow: hidden; color: #d6dafe; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }
|
|
1729
1859
|
.spotpatch-agent-status {
|
|
@@ -2174,68 +2304,81 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
2174
2304
|
});
|
|
2175
2305
|
}
|
|
2176
2306
|
|
|
2307
|
+
// src/ui/brand-mark-content.ts
|
|
2308
|
+
var BRAND_MARK_CONTENT = `
|
|
2309
|
+
<defs>
|
|
2310
|
+
<linearGradient id="locator-gradient" x1="76" y1="92" x2="436" y2="374" gradientUnits="userSpaceOnUse">
|
|
2311
|
+
<stop offset="0" stop-color="#B61CFF" />
|
|
2312
|
+
<stop offset="0.38" stop-color="#6D35FF" />
|
|
2313
|
+
<stop offset="0.72" stop-color="#168EFF" />
|
|
2314
|
+
<stop offset="1" stop-color="#00D9E9" />
|
|
2315
|
+
</linearGradient>
|
|
2316
|
+
<linearGradient id="left-code-gradient" x1="165" y1="166" x2="236" y2="258" gradientUnits="userSpaceOnUse">
|
|
2317
|
+
<stop stop-color="#A51EFF" />
|
|
2318
|
+
<stop offset="1" stop-color="#653BFF" />
|
|
2319
|
+
</linearGradient>
|
|
2320
|
+
<linearGradient id="right-code-gradient" x1="276" y1="166" x2="347" y2="258" gradientUnits="userSpaceOnUse">
|
|
2321
|
+
<stop stop-color="#158DFF" />
|
|
2322
|
+
<stop offset="1" stop-color="#00D8E9" />
|
|
2323
|
+
</linearGradient>
|
|
2324
|
+
<linearGradient id="bolt-gradient" x1="270" y1="111" x2="252" y2="365" gradientUnits="userSpaceOnUse">
|
|
2325
|
+
<stop stop-color="#6840FF" />
|
|
2326
|
+
<stop offset="0.48" stop-color="#257BFF" />
|
|
2327
|
+
<stop offset="1" stop-color="#00CBEF" />
|
|
2328
|
+
</linearGradient>
|
|
2329
|
+
</defs>
|
|
2330
|
+
<path
|
|
2331
|
+
fill="url(#locator-gradient)"
|
|
2332
|
+
fill-rule="evenodd"
|
|
2333
|
+
clip-rule="evenodd"
|
|
2334
|
+
d="M256 52C345.47 52 418 124.53 418 214C418 267.55 391.98 316.24 354.04 348.02L256 468L157.96 348.02C120.02 316.24 94 267.55 94 214C94 124.53 166.53 52 256 52ZM256 88C186.41 88 130 144.41 130 214C130 258.2 152.76 297.08 187.2 319.57L256 403.8L324.8 319.57C359.24 297.08 382 258.2 382 214C382 144.41 325.59 88 256 88Z"
|
|
2335
|
+
/>
|
|
2336
|
+
<rect x="238" y="20" width="36" height="84" rx="4" fill="url(#locator-gradient)" />
|
|
2337
|
+
<rect x="62" y="196" width="84" height="36" rx="4" fill="url(#locator-gradient)" />
|
|
2338
|
+
<rect x="366" y="196" width="84" height="36" rx="4" fill="url(#locator-gradient)" />
|
|
2339
|
+
<path
|
|
2340
|
+
d="M213.5 160L158 211.5L213.5 263L238 236.5L211 211.5L238 186.5L213.5 160Z"
|
|
2341
|
+
fill="url(#left-code-gradient)"
|
|
2342
|
+
/>
|
|
2343
|
+
<path
|
|
2344
|
+
d="M298.5 160L354 211.5L298.5 263L274 236.5L301 211.5L274 186.5L298.5 160Z"
|
|
2345
|
+
fill="url(#right-code-gradient)"
|
|
2346
|
+
/>
|
|
2347
|
+
<path
|
|
2348
|
+
d="M283 108L232 212L266 253L238 369L302 237L267 198L283 108Z"
|
|
2349
|
+
fill="url(#bolt-gradient)"
|
|
2350
|
+
/>
|
|
2351
|
+
`;
|
|
2352
|
+
|
|
2177
2353
|
// src/ui/brand-mark.ts
|
|
2178
2354
|
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
2355
|
+
function resolveBrandMarkContent(override) {
|
|
2356
|
+
if (override !== void 0) {
|
|
2357
|
+
return { content: override, viewBox: "0 0 512 512" };
|
|
2358
|
+
}
|
|
2359
|
+
const injected = typeof __SPOTPATCH_BRAND_MARK_CONTENT__ === "string" ? __SPOTPATCH_BRAND_MARK_CONTENT__ : void 0;
|
|
2360
|
+
if (typeof injected === "string") {
|
|
2361
|
+
return { content: injected, viewBox: "0 0 512 512" };
|
|
2362
|
+
}
|
|
2363
|
+
return true ? { content: BRAND_MARK_CONTENT, viewBox: "0 0 512 512" } : { content: FALLBACK_BRAND_MARK_CONTENT, viewBox: "0 0 1 1" };
|
|
2364
|
+
}
|
|
2179
2365
|
function svgElement(document, tagName, attributes) {
|
|
2180
|
-
const
|
|
2366
|
+
const element2 = document.createElementNS(SVG_NAMESPACE, tagName);
|
|
2181
2367
|
for (const [name, value] of Object.entries(attributes)) {
|
|
2182
|
-
|
|
2368
|
+
element2.setAttribute(name, value);
|
|
2183
2369
|
}
|
|
2184
|
-
return
|
|
2370
|
+
return element2;
|
|
2185
2371
|
}
|
|
2186
|
-
function createBrandMark(document) {
|
|
2372
|
+
function createBrandMark(document, content) {
|
|
2373
|
+
const resolved = resolveBrandMarkContent(content);
|
|
2187
2374
|
const svg = svgElement(document, "svg", {
|
|
2375
|
+
xmlns: SVG_NAMESPACE,
|
|
2188
2376
|
class: "spotpatch-brand-mark",
|
|
2189
|
-
viewBox:
|
|
2377
|
+
viewBox: resolved.viewBox,
|
|
2190
2378
|
"aria-hidden": "true",
|
|
2191
2379
|
focusable: "false"
|
|
2192
2380
|
});
|
|
2193
|
-
|
|
2194
|
-
const gradient = svgElement(document, "linearGradient", {
|
|
2195
|
-
id: "spotpatch-brand-gradient",
|
|
2196
|
-
x1: "35",
|
|
2197
|
-
y1: "42",
|
|
2198
|
-
x2: "184",
|
|
2199
|
-
y2: "176",
|
|
2200
|
-
gradientUnits: "userSpaceOnUse"
|
|
2201
|
-
});
|
|
2202
|
-
gradient.append(
|
|
2203
|
-
svgElement(document, "stop", { offset: "0", "stop-color": "#7c22ff" }),
|
|
2204
|
-
svgElement(document, "stop", { offset: ".52", "stop-color": "#4a69ff" }),
|
|
2205
|
-
svgElement(document, "stop", { offset: "1", "stop-color": "#06d9ef" })
|
|
2206
|
-
);
|
|
2207
|
-
definitions.append(gradient);
|
|
2208
|
-
const commonStroke = {
|
|
2209
|
-
fill: "none",
|
|
2210
|
-
stroke: "url(#spotpatch-brand-gradient)",
|
|
2211
|
-
"stroke-linecap": "square",
|
|
2212
|
-
"stroke-linejoin": "miter"
|
|
2213
|
-
};
|
|
2214
|
-
const outer = svgElement(document, "path", {
|
|
2215
|
-
d: "M106 42C67 42 43 68 43 105c0 36 24 61 63 96 39-35 63-60 63-96 0-37-24-63-63-63Z",
|
|
2216
|
-
...commonStroke,
|
|
2217
|
-
"stroke-width": "14"
|
|
2218
|
-
});
|
|
2219
|
-
const topStem = svgElement(document, "path", {
|
|
2220
|
-
d: "M106 25v42",
|
|
2221
|
-
...commonStroke,
|
|
2222
|
-
"stroke-width": "14"
|
|
2223
|
-
});
|
|
2224
|
-
const sideStems = svgElement(document, "path", {
|
|
2225
|
-
d: "M35 109h20m102 0h38",
|
|
2226
|
-
...commonStroke,
|
|
2227
|
-
"stroke-width": "13"
|
|
2228
|
-
});
|
|
2229
|
-
const brackets = svgElement(document, "path", {
|
|
2230
|
-
d: "m94 89-18 19 18 17m39-36 18 19-18 17",
|
|
2231
|
-
...commonStroke,
|
|
2232
|
-
"stroke-width": "9"
|
|
2233
|
-
});
|
|
2234
|
-
const bolt = svgElement(document, "path", {
|
|
2235
|
-
d: "m119 61-20 45 15 11-13 47 30-56-16-12 4-35Z",
|
|
2236
|
-
fill: "url(#spotpatch-brand-gradient)"
|
|
2237
|
-
});
|
|
2238
|
-
svg.append(definitions, outer, topStem, sideStems, brackets, bolt);
|
|
2381
|
+
svg.innerHTML = resolved.content;
|
|
2239
2382
|
return svg;
|
|
2240
2383
|
}
|
|
2241
2384
|
|
|
@@ -2250,32 +2393,51 @@ function clamp(value, minimum, maximum) {
|
|
|
2250
2393
|
function calculateDialogPlacement({
|
|
2251
2394
|
dialogHeight,
|
|
2252
2395
|
dialogWidth,
|
|
2253
|
-
target,
|
|
2396
|
+
target: target2,
|
|
2254
2397
|
viewportHeight,
|
|
2255
2398
|
viewportWidth
|
|
2256
2399
|
}) {
|
|
2257
2400
|
const maxLeft = viewportWidth - dialogWidth - VIEWPORT_MARGIN;
|
|
2258
2401
|
const maxTop = viewportHeight - dialogHeight - VIEWPORT_MARGIN;
|
|
2259
|
-
const
|
|
2260
|
-
|
|
2402
|
+
const viewportLeft = clamp(
|
|
2403
|
+
(viewportWidth - dialogWidth) / 2,
|
|
2404
|
+
VIEWPORT_MARGIN,
|
|
2405
|
+
maxLeft
|
|
2406
|
+
);
|
|
2407
|
+
const viewportTop = clamp(
|
|
2408
|
+
(viewportHeight - dialogHeight) / 2,
|
|
2409
|
+
VIEWPORT_MARGIN,
|
|
2410
|
+
maxTop
|
|
2411
|
+
);
|
|
2412
|
+
if (target2 === void 0) {
|
|
2413
|
+
return Object.freeze({
|
|
2414
|
+
anchorX: clamp(dialogWidth / 2, ANCHOR_INSET, dialogWidth - ANCHOR_INSET),
|
|
2415
|
+
anchorY: clamp(dialogHeight / 2, ANCHOR_INSET, dialogHeight - ANCHOR_INSET),
|
|
2416
|
+
left: viewportLeft,
|
|
2417
|
+
mode: "viewport",
|
|
2418
|
+
top: viewportTop
|
|
2419
|
+
});
|
|
2420
|
+
}
|
|
2421
|
+
const targetCenterX = target2.x + target2.width / 2;
|
|
2422
|
+
const targetCenterY = target2.y + target2.height / 2;
|
|
2261
2423
|
const centeredLeft = clamp(targetCenterX - dialogWidth / 2, VIEWPORT_MARGIN, maxLeft);
|
|
2262
2424
|
const centeredTop = clamp(targetCenterY - dialogHeight / 2, VIEWPORT_MARGIN, maxTop);
|
|
2263
2425
|
let left = centeredLeft;
|
|
2264
2426
|
let top = centeredTop;
|
|
2265
2427
|
let mode = "viewport";
|
|
2266
|
-
if (
|
|
2428
|
+
if (target2.width >= dialogWidth + TARGET_INSET * 2 && target2.height >= dialogHeight + TARGET_INSET * 2) {
|
|
2267
2429
|
mode = "center";
|
|
2268
|
-
} else if (
|
|
2269
|
-
top =
|
|
2430
|
+
} else if (target2.y - dialogHeight - TARGET_GAP >= VIEWPORT_MARGIN) {
|
|
2431
|
+
top = target2.y - dialogHeight - TARGET_GAP;
|
|
2270
2432
|
mode = "above";
|
|
2271
|
-
} else if (
|
|
2272
|
-
top =
|
|
2433
|
+
} else if (target2.y + target2.height + TARGET_GAP + dialogHeight <= viewportHeight - VIEWPORT_MARGIN) {
|
|
2434
|
+
top = target2.y + target2.height + TARGET_GAP;
|
|
2273
2435
|
mode = "below";
|
|
2274
|
-
} else if (
|
|
2275
|
-
left =
|
|
2436
|
+
} else if (target2.x + target2.width + TARGET_GAP + dialogWidth <= viewportWidth - VIEWPORT_MARGIN) {
|
|
2437
|
+
left = target2.x + target2.width + TARGET_GAP;
|
|
2276
2438
|
mode = "right";
|
|
2277
|
-
} else if (
|
|
2278
|
-
left =
|
|
2439
|
+
} else if (target2.x - dialogWidth - TARGET_GAP >= VIEWPORT_MARGIN) {
|
|
2440
|
+
left = target2.x - dialogWidth - TARGET_GAP;
|
|
2279
2441
|
mode = "left";
|
|
2280
2442
|
}
|
|
2281
2443
|
return Object.freeze({
|
|
@@ -2594,7 +2756,7 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2594
2756
|
noSelectable: "No selectable element was found.",
|
|
2595
2757
|
allTargetsRemoved: "All targets were removed. Choose an element to continue.",
|
|
2596
2758
|
targetRemoved: "Selected target removed.",
|
|
2597
|
-
|
|
2759
|
+
detachedTargetPreserved: "The page element was unloaded; its collected context remains selected.",
|
|
2598
2760
|
contextWarning: "Browser context collection completed with a warning.",
|
|
2599
2761
|
contextCollected: "Browser context collected.",
|
|
2600
2762
|
editorOpening: "Opening source\u2026",
|
|
@@ -2730,7 +2892,7 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2730
2892
|
noSelectable: "\u5F53\u524D\u4F4D\u7F6E\u6CA1\u6709\u53EF\u9009\u62E9\u7684\u5143\u7D20\u3002",
|
|
2731
2893
|
allTargetsRemoved: "\u5DF2\u79FB\u9664\u5168\u90E8\u76EE\u6807\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u5143\u7D20\u3002",
|
|
2732
2894
|
targetRemoved: "\u5DF2\u79FB\u9664\u9009\u4E2D\u76EE\u6807\u3002",
|
|
2733
|
-
|
|
2895
|
+
detachedTargetPreserved: "\u9875\u9762\u5143\u7D20\u5DF2\u5378\u8F7D\uFF0C\u5DF2\u91C7\u96C6\u7684\u4E0A\u4E0B\u6587\u4ECD\u4FDD\u7559\u5728\u9009\u62E9\u4E2D\u3002",
|
|
2734
2896
|
contextWarning: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\uFF0C\u4F46\u5B58\u5728\u8B66\u544A\u3002",
|
|
2735
2897
|
contextCollected: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\u3002",
|
|
2736
2898
|
editorOpening: "\u6B63\u5728\u6253\u5F00\u6E90\u7801\u2026\u2026",
|
|
@@ -2788,33 +2950,36 @@ function createUiLocalizer(document, preference = "auto") {
|
|
|
2788
2950
|
}
|
|
2789
2951
|
|
|
2790
2952
|
// src/ui/runtime-view.ts
|
|
2791
|
-
var
|
|
2953
|
+
var DIALOG_MAX_WIDTH = 460;
|
|
2954
|
+
var DIALOG_MAX_HEIGHT = 620;
|
|
2792
2955
|
var DIALOG_FALLBACK_HEIGHT = Object.freeze({
|
|
2793
|
-
previewing:
|
|
2794
|
-
selected:
|
|
2956
|
+
previewing: 560,
|
|
2957
|
+
selected: DIALOG_MAX_HEIGHT
|
|
2795
2958
|
});
|
|
2796
2959
|
function createStyles(document) {
|
|
2797
2960
|
const style = document.createElement("style");
|
|
2798
2961
|
style.textContent = `
|
|
2799
2962
|
:host {
|
|
2800
2963
|
all: initial;
|
|
2801
|
-
--spotpatch-bg: #
|
|
2802
|
-
--spotpatch-bg-raised: #
|
|
2803
|
-
--spotpatch-bg-
|
|
2804
|
-
--spotpatch-
|
|
2805
|
-
--spotpatch-border
|
|
2806
|
-
--spotpatch-
|
|
2807
|
-
--spotpatch-text
|
|
2808
|
-
--spotpatch-text-
|
|
2809
|
-
--spotpatch-
|
|
2810
|
-
--spotpatch-accent
|
|
2811
|
-
--spotpatch-accent-
|
|
2964
|
+
--spotpatch-bg: #0e0e12;
|
|
2965
|
+
--spotpatch-bg-raised: #17171c;
|
|
2966
|
+
--spotpatch-bg-active: #1c1c22;
|
|
2967
|
+
--spotpatch-bg-input: #0b0b0f;
|
|
2968
|
+
--spotpatch-border: #2a2a32;
|
|
2969
|
+
--spotpatch-border-subtle: #232329;
|
|
2970
|
+
--spotpatch-text: #f2f2f5;
|
|
2971
|
+
--spotpatch-text-secondary: #96969f;
|
|
2972
|
+
--spotpatch-text-muted: #686872;
|
|
2973
|
+
--spotpatch-accent: #8b7bff;
|
|
2974
|
+
--spotpatch-accent-strong: #6a5ce8;
|
|
2975
|
+
--spotpatch-accent-cyan: #52a8ff;
|
|
2812
2976
|
--spotpatch-danger: #fb7185;
|
|
2813
2977
|
--spotpatch-success: #34d399;
|
|
2814
2978
|
--spotpatch-warning: #f59e0b;
|
|
2815
|
-
--spotpatch-
|
|
2816
|
-
--spotpatch-radius-
|
|
2817
|
-
--spotpatch-
|
|
2979
|
+
--spotpatch-text-on-accent: #0b0b12;
|
|
2980
|
+
--spotpatch-radius-panel: 16px;
|
|
2981
|
+
--spotpatch-radius-card: 10px;
|
|
2982
|
+
--spotpatch-shadow-panel: 0 30px 60px -20px rgb(0 0 0 / 70%);
|
|
2818
2983
|
color-scheme: dark;
|
|
2819
2984
|
color: var(--spotpatch-text);
|
|
2820
2985
|
font-family: Inter, "SF Pro Display", "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
@@ -2934,7 +3099,7 @@ function createStyles(document) {
|
|
|
2934
3099
|
left: 16px;
|
|
2935
3100
|
z-index: ${String(UI_Z_INDEX.controls)};
|
|
2936
3101
|
box-sizing: border-box;
|
|
2937
|
-
width: min(
|
|
3102
|
+
width: min(${String(DIALOG_MAX_WIDTH)}px, calc(100vw - 32px));
|
|
2938
3103
|
color: #edf0f7;
|
|
2939
3104
|
outline: none;
|
|
2940
3105
|
filter: drop-shadow(var(--spotpatch-shadow-panel));
|
|
@@ -2978,78 +3143,92 @@ function createStyles(document) {
|
|
|
2978
3143
|
position: relative;
|
|
2979
3144
|
z-index: 1;
|
|
2980
3145
|
display: flex;
|
|
2981
|
-
|
|
3146
|
+
box-sizing: border-box;
|
|
3147
|
+
max-height: min(${String(DIALOG_MAX_HEIGHT)}px, calc(100vh - 32px));
|
|
2982
3148
|
overflow: hidden;
|
|
2983
3149
|
flex-direction: column;
|
|
2984
3150
|
border: 1px solid var(--spotpatch-border);
|
|
2985
3151
|
border-radius: var(--spotpatch-radius-panel);
|
|
2986
3152
|
background: var(--spotpatch-bg);
|
|
2987
|
-
box-shadow: inset 0 1px rgb(255 255 255 /
|
|
3153
|
+
box-shadow: inset 0 1px rgb(255 255 255 / 5%), 0 0 60px -32px rgb(139 123 255 / 20%);
|
|
3154
|
+
}
|
|
3155
|
+
.spotpatch-shell::before {
|
|
3156
|
+
position: absolute;
|
|
3157
|
+
z-index: 2;
|
|
3158
|
+
top: 0;
|
|
3159
|
+
right: 20%;
|
|
3160
|
+
left: 20%;
|
|
3161
|
+
height: 1px;
|
|
3162
|
+
background: linear-gradient(90deg, transparent, var(--spotpatch-accent), var(--spotpatch-accent-cyan), transparent);
|
|
3163
|
+
content: "";
|
|
3164
|
+
opacity: .65;
|
|
3165
|
+
pointer-events: none;
|
|
2988
3166
|
}
|
|
2989
3167
|
.spotpatch-header {
|
|
2990
3168
|
position: relative;
|
|
2991
|
-
padding:
|
|
2992
|
-
border-bottom: 1px solid rgb(255 255 255 / 8%);
|
|
3169
|
+
padding: 0 18px 14px;
|
|
2993
3170
|
}
|
|
2994
3171
|
.spotpatch-brand-row {
|
|
2995
3172
|
display: flex;
|
|
2996
3173
|
align-items: center;
|
|
2997
3174
|
justify-content: space-between;
|
|
2998
|
-
gap:
|
|
2999
|
-
margin
|
|
3175
|
+
gap: 12px;
|
|
3176
|
+
margin: 0 -18px 18px;
|
|
3177
|
+
padding: 14px 18px 13px;
|
|
3178
|
+
border-bottom: 1px solid var(--spotpatch-border-subtle);
|
|
3000
3179
|
}
|
|
3001
3180
|
.spotpatch-brand {
|
|
3002
3181
|
display: inline-flex;
|
|
3003
3182
|
align-items: center;
|
|
3004
|
-
gap:
|
|
3183
|
+
gap: 10px;
|
|
3005
3184
|
min-width: 0;
|
|
3006
3185
|
color: #f8fafc;
|
|
3007
3186
|
}
|
|
3008
3187
|
.spotpatch-brand-mark {
|
|
3009
|
-
width:
|
|
3010
|
-
height:
|
|
3188
|
+
width: 30px;
|
|
3189
|
+
height: 30px;
|
|
3011
3190
|
flex: none;
|
|
3012
3191
|
filter: drop-shadow(0 6px 12px rgb(76 29 149 / 22%));
|
|
3013
3192
|
}
|
|
3014
3193
|
.spotpatch-brand-copy { display: grid; min-width: 0; gap: 1px; }
|
|
3015
3194
|
.spotpatch-brand-name {
|
|
3016
3195
|
color: #fff;
|
|
3017
|
-
font-size:
|
|
3018
|
-
font-weight:
|
|
3196
|
+
font-size: 13.5px;
|
|
3197
|
+
font-weight: 680;
|
|
3019
3198
|
letter-spacing: -.01em;
|
|
3020
3199
|
}
|
|
3021
3200
|
.spotpatch-brand-context {
|
|
3022
3201
|
color: #8e98aa;
|
|
3023
|
-
font-size:
|
|
3202
|
+
font-size: 10.5px;
|
|
3024
3203
|
font-weight: 560;
|
|
3025
3204
|
letter-spacing: .02em;
|
|
3026
3205
|
}
|
|
3027
3206
|
.spotpatch-header-controls {
|
|
3028
3207
|
display: inline-flex;
|
|
3029
3208
|
align-items: center;
|
|
3030
|
-
gap:
|
|
3209
|
+
gap: 6px;
|
|
3031
3210
|
flex: none;
|
|
3032
3211
|
}
|
|
3033
3212
|
.spotpatch-repository,
|
|
3034
3213
|
.spotpatch-locale,
|
|
3035
3214
|
.spotpatch-close {
|
|
3036
|
-
height:
|
|
3215
|
+
height: 27px;
|
|
3037
3216
|
border: 1px solid rgb(255 255 255 / 11%);
|
|
3038
|
-
border-radius:
|
|
3039
|
-
background:
|
|
3217
|
+
border-radius: 7px;
|
|
3218
|
+
background: transparent;
|
|
3040
3219
|
}
|
|
3041
3220
|
.spotpatch-repository {
|
|
3042
3221
|
display: inline-flex;
|
|
3043
3222
|
align-items: center;
|
|
3044
|
-
padding: 0
|
|
3045
|
-
color:
|
|
3223
|
+
padding: 0 9px;
|
|
3224
|
+
color: var(--spotpatch-text-secondary);
|
|
3046
3225
|
font-size: 11px;
|
|
3047
3226
|
font-weight: 680;
|
|
3048
3227
|
text-decoration: none;
|
|
3049
3228
|
}
|
|
3050
3229
|
.spotpatch-locale {
|
|
3051
|
-
min-width:
|
|
3052
|
-
padding: 0
|
|
3230
|
+
min-width: 34px;
|
|
3231
|
+
padding: 0 8px;
|
|
3053
3232
|
color: #c5cad5;
|
|
3054
3233
|
cursor: pointer;
|
|
3055
3234
|
font-size: 12px;
|
|
@@ -3057,12 +3236,12 @@ function createStyles(document) {
|
|
|
3057
3236
|
}
|
|
3058
3237
|
.spotpatch-close {
|
|
3059
3238
|
display: inline-grid;
|
|
3060
|
-
width:
|
|
3239
|
+
width: 27px;
|
|
3061
3240
|
padding: 0;
|
|
3062
3241
|
place-items: center;
|
|
3063
3242
|
color: #9da5b4;
|
|
3064
3243
|
cursor: pointer;
|
|
3065
|
-
font-size:
|
|
3244
|
+
font-size: 15px;
|
|
3066
3245
|
line-height: 1;
|
|
3067
3246
|
transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
|
|
3068
3247
|
}
|
|
@@ -3072,30 +3251,30 @@ function createStyles(document) {
|
|
|
3072
3251
|
.spotpatch-title {
|
|
3073
3252
|
margin: 0;
|
|
3074
3253
|
color: #fff;
|
|
3075
|
-
font-size:
|
|
3076
|
-
font-weight:
|
|
3077
|
-
letter-spacing: -.
|
|
3254
|
+
font-size: 18px;
|
|
3255
|
+
font-weight: 680;
|
|
3256
|
+
letter-spacing: -.015em;
|
|
3078
3257
|
}
|
|
3079
3258
|
.spotpatch-subtitle {
|
|
3080
|
-
max-width:
|
|
3081
|
-
margin:
|
|
3082
|
-
color:
|
|
3083
|
-
font-size:
|
|
3084
|
-
line-height: 1.
|
|
3259
|
+
max-width: 390px;
|
|
3260
|
+
margin: 4px 0 0;
|
|
3261
|
+
color: var(--spotpatch-text-secondary);
|
|
3262
|
+
font-size: 12.5px;
|
|
3263
|
+
line-height: 1.5;
|
|
3085
3264
|
}
|
|
3086
3265
|
.spotpatch-target-row {
|
|
3087
3266
|
display: flex;
|
|
3088
3267
|
align-items: center;
|
|
3089
3268
|
gap: 8px;
|
|
3090
3269
|
min-width: 0;
|
|
3091
|
-
margin-top:
|
|
3270
|
+
margin-top: 14px;
|
|
3092
3271
|
}
|
|
3093
3272
|
.spotpatch-target-label {
|
|
3094
3273
|
min-width: 0;
|
|
3095
3274
|
overflow: hidden;
|
|
3096
3275
|
border: 1px solid rgb(129 112 247 / 24%);
|
|
3097
3276
|
border-radius: 999px;
|
|
3098
|
-
padding:
|
|
3277
|
+
padding: 4px 10px;
|
|
3099
3278
|
color: #cdd2ff;
|
|
3100
3279
|
background: rgb(109 93 246 / 10%);
|
|
3101
3280
|
font: 600 11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
@@ -3108,7 +3287,7 @@ function createStyles(document) {
|
|
|
3108
3287
|
gap: 6px;
|
|
3109
3288
|
flex: none;
|
|
3110
3289
|
color: #a5adba;
|
|
3111
|
-
font-size:
|
|
3290
|
+
font-size: 11px;
|
|
3112
3291
|
white-space: nowrap;
|
|
3113
3292
|
}
|
|
3114
3293
|
.spotpatch-context-state::before {
|
|
@@ -3129,7 +3308,7 @@ function createStyles(document) {
|
|
|
3129
3308
|
.spotpatch-body {
|
|
3130
3309
|
min-height: 0;
|
|
3131
3310
|
overflow: auto;
|
|
3132
|
-
padding:
|
|
3311
|
+
padding: 0 18px 14px;
|
|
3133
3312
|
scrollbar-color: rgb(100 116 139 / 50%) transparent;
|
|
3134
3313
|
scrollbar-width: thin;
|
|
3135
3314
|
}
|
|
@@ -3140,36 +3319,54 @@ function createStyles(document) {
|
|
|
3140
3319
|
display: flex;
|
|
3141
3320
|
align-items: center;
|
|
3142
3321
|
justify-content: space-between;
|
|
3143
|
-
gap:
|
|
3144
|
-
margin-bottom:
|
|
3145
|
-
color:
|
|
3146
|
-
font-size:
|
|
3147
|
-
font-weight:
|
|
3322
|
+
gap: 10px;
|
|
3323
|
+
margin-bottom: 8px;
|
|
3324
|
+
color: var(--spotpatch-text-secondary);
|
|
3325
|
+
font-size: 11px;
|
|
3326
|
+
font-weight: 650;
|
|
3327
|
+
letter-spacing: .04em;
|
|
3328
|
+
text-transform: uppercase;
|
|
3148
3329
|
}
|
|
3149
3330
|
.spotpatch-targets-meta {
|
|
3150
3331
|
display: flex;
|
|
3151
3332
|
align-items: center;
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3333
|
+
gap: 8px;
|
|
3334
|
+
min-width: 0;
|
|
3335
|
+
letter-spacing: 0;
|
|
3336
|
+
text-transform: none;
|
|
3155
3337
|
}
|
|
3156
|
-
.spotpatch-target-complete { color: var(--spotpatch-text-
|
|
3338
|
+
.spotpatch-target-complete { color: var(--spotpatch-text-muted); font-size: 11px; font-weight: 560; }
|
|
3157
3339
|
.spotpatch-target-budget {
|
|
3158
3340
|
color: var(--spotpatch-text-muted);
|
|
3159
|
-
font: 550
|
|
3341
|
+
font: 550 10.5px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
3160
3342
|
}
|
|
3343
|
+
.spotpatch-target-budget[data-state="ready"] { display: none; }
|
|
3161
3344
|
.spotpatch-target-budget[data-state="over"] { color: #fda4af; }
|
|
3162
3345
|
.spotpatch-target-count {
|
|
3346
|
+
margin-left: auto;
|
|
3163
3347
|
border-radius: 999px;
|
|
3164
3348
|
padding: 3px 8px;
|
|
3165
|
-
color:
|
|
3166
|
-
|
|
3167
|
-
|
|
3349
|
+
color: var(--spotpatch-text-muted);
|
|
3350
|
+
font: 600 10.5px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
3351
|
+
}
|
|
3352
|
+
.spotpatch-target-progress {
|
|
3353
|
+
height: 3px;
|
|
3354
|
+
margin-bottom: 13px;
|
|
3355
|
+
overflow: hidden;
|
|
3356
|
+
border-radius: 999px;
|
|
3357
|
+
background: var(--spotpatch-border-subtle);
|
|
3358
|
+
}
|
|
3359
|
+
.spotpatch-target-progress-fill {
|
|
3360
|
+
width: 0;
|
|
3361
|
+
height: 100%;
|
|
3362
|
+
border-radius: inherit;
|
|
3363
|
+
background: linear-gradient(90deg, var(--spotpatch-accent), var(--spotpatch-accent-cyan));
|
|
3364
|
+
transition: width 180ms ease;
|
|
3168
3365
|
}
|
|
3169
3366
|
.spotpatch-target-list {
|
|
3170
3367
|
display: grid;
|
|
3171
|
-
gap:
|
|
3172
|
-
max-height: min(
|
|
3368
|
+
gap: 8px;
|
|
3369
|
+
max-height: min(340px, 48vh);
|
|
3173
3370
|
overflow: auto;
|
|
3174
3371
|
padding-right: 2px;
|
|
3175
3372
|
}
|
|
@@ -3177,30 +3374,30 @@ function createStyles(document) {
|
|
|
3177
3374
|
overflow: hidden;
|
|
3178
3375
|
border: 1px solid var(--spotpatch-border-subtle);
|
|
3179
3376
|
border-radius: var(--spotpatch-radius-card);
|
|
3180
|
-
background:
|
|
3377
|
+
background: var(--spotpatch-bg-raised);
|
|
3181
3378
|
transition: border-color 150ms ease, background 150ms ease;
|
|
3182
3379
|
}
|
|
3183
3380
|
.spotpatch-target-item[data-active="true"] {
|
|
3184
|
-
border-color: rgb(
|
|
3185
|
-
background:
|
|
3186
|
-
box-shadow:
|
|
3381
|
+
border-color: rgb(139 123 255 / 34%);
|
|
3382
|
+
background: var(--spotpatch-bg-active);
|
|
3383
|
+
box-shadow: 0 0 0 3px rgb(139 123 255 / 10%);
|
|
3187
3384
|
}
|
|
3188
3385
|
.spotpatch-target-summary {
|
|
3189
3386
|
display: grid;
|
|
3190
|
-
grid-template-columns: minmax(0, 1fr)
|
|
3387
|
+
grid-template-columns: minmax(0, 1fr) 28px 28px;
|
|
3191
3388
|
align-items: stretch;
|
|
3192
|
-
gap:
|
|
3193
|
-
padding:
|
|
3389
|
+
gap: 2px;
|
|
3390
|
+
padding: 4px;
|
|
3194
3391
|
}
|
|
3195
3392
|
.spotpatch-target-select {
|
|
3196
3393
|
display: grid;
|
|
3197
|
-
grid-template-columns:
|
|
3394
|
+
grid-template-columns: 24px minmax(0, 1fr) auto;
|
|
3198
3395
|
align-items: center;
|
|
3199
|
-
gap:
|
|
3396
|
+
gap: 9px;
|
|
3200
3397
|
min-width: 0;
|
|
3201
3398
|
border: 0;
|
|
3202
|
-
border-radius:
|
|
3203
|
-
padding:
|
|
3399
|
+
border-radius: 8px;
|
|
3400
|
+
padding: 8px;
|
|
3204
3401
|
color: inherit;
|
|
3205
3402
|
background: transparent;
|
|
3206
3403
|
cursor: pointer;
|
|
@@ -3209,14 +3406,14 @@ function createStyles(document) {
|
|
|
3209
3406
|
.spotpatch-target-select:hover { background: rgb(255 255 255 / 3.5%); }
|
|
3210
3407
|
.spotpatch-target-index {
|
|
3211
3408
|
display: inline-grid;
|
|
3212
|
-
width:
|
|
3213
|
-
height:
|
|
3409
|
+
width: 22px;
|
|
3410
|
+
height: 22px;
|
|
3214
3411
|
place-items: center;
|
|
3215
3412
|
border: 1px solid rgb(68 202 224 / 25%);
|
|
3216
|
-
border-radius:
|
|
3217
|
-
color:
|
|
3218
|
-
background:
|
|
3219
|
-
font:
|
|
3413
|
+
border-radius: 6px;
|
|
3414
|
+
color: var(--spotpatch-text-secondary);
|
|
3415
|
+
background: var(--spotpatch-bg);
|
|
3416
|
+
font: 650 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
3220
3417
|
}
|
|
3221
3418
|
.spotpatch-target-copy { min-width: 0; }
|
|
3222
3419
|
.spotpatch-target-name,
|
|
@@ -3226,14 +3423,14 @@ function createStyles(document) {
|
|
|
3226
3423
|
text-overflow: ellipsis;
|
|
3227
3424
|
white-space: nowrap;
|
|
3228
3425
|
}
|
|
3229
|
-
.spotpatch-target-name { color: #
|
|
3230
|
-
.spotpatch-target-source { margin-top:
|
|
3426
|
+
.spotpatch-target-name { color: #f2f2f5; font-size: 13px; font-weight: 650; }
|
|
3427
|
+
.spotpatch-target-source { margin-top: 1px; color: var(--spotpatch-text-muted); font: 500 10.5px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
3231
3428
|
.spotpatch-target-state {
|
|
3232
3429
|
border-radius: 999px;
|
|
3233
|
-
padding:
|
|
3430
|
+
padding: 3px 8px;
|
|
3234
3431
|
color: #a7f3d0;
|
|
3235
3432
|
background: rgb(16 185 129 / 9%);
|
|
3236
|
-
font-size:
|
|
3433
|
+
font-size: 10.5px;
|
|
3237
3434
|
font-weight: 650;
|
|
3238
3435
|
white-space: nowrap;
|
|
3239
3436
|
}
|
|
@@ -3241,13 +3438,13 @@ function createStyles(document) {
|
|
|
3241
3438
|
.spotpatch-target-open,
|
|
3242
3439
|
.spotpatch-target-remove {
|
|
3243
3440
|
display: inline-grid;
|
|
3244
|
-
width:
|
|
3441
|
+
width: 28px;
|
|
3245
3442
|
height: 100%;
|
|
3246
|
-
min-height:
|
|
3443
|
+
min-height: 34px;
|
|
3247
3444
|
padding: 0;
|
|
3248
3445
|
place-items: center;
|
|
3249
3446
|
border: 1px solid transparent;
|
|
3250
|
-
border-radius:
|
|
3447
|
+
border-radius: 7px;
|
|
3251
3448
|
color: #7f899a;
|
|
3252
3449
|
background: transparent;
|
|
3253
3450
|
cursor: pointer;
|
|
@@ -3256,31 +3453,30 @@ function createStyles(document) {
|
|
|
3256
3453
|
.spotpatch-target-open:hover:not(:disabled) { border-color: rgb(68 202 224 / 30%); color: #c8f7ff; background: rgb(8 145 178 / 11%); }
|
|
3257
3454
|
.spotpatch-target-remove:hover:not(:disabled) { border-color: rgb(251 113 133 / 24%); color: #fda4af; background: rgb(127 29 29 / 12%); }
|
|
3258
3455
|
.spotpatch-target-editor {
|
|
3259
|
-
|
|
3260
|
-
padding: 18px;
|
|
3456
|
+
padding: 0 12px 12px;
|
|
3261
3457
|
}
|
|
3262
3458
|
.spotpatch-target-editor-head {
|
|
3263
3459
|
display: flex;
|
|
3264
3460
|
align-items: baseline;
|
|
3265
3461
|
justify-content: space-between;
|
|
3266
3462
|
gap: 12px;
|
|
3267
|
-
margin-bottom:
|
|
3463
|
+
margin-bottom: 6px;
|
|
3268
3464
|
}
|
|
3269
|
-
.spotpatch-target-editor-label { color:
|
|
3270
|
-
.spotpatch-target-editor-count { color: var(--spotpatch-text-muted); font: 500
|
|
3465
|
+
.spotpatch-target-editor-label { color: var(--spotpatch-text-secondary); font-size: 11px; font-weight: 650; }
|
|
3466
|
+
.spotpatch-target-editor-count { color: var(--spotpatch-text-muted); font: 500 10.5px/1.3 ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
3271
3467
|
.spotpatch-target-editor textarea {
|
|
3272
3468
|
box-sizing: border-box;
|
|
3273
3469
|
width: 100%;
|
|
3274
|
-
min-height:
|
|
3470
|
+
min-height: 74px;
|
|
3275
3471
|
resize: vertical;
|
|
3276
3472
|
border: 1px solid var(--spotpatch-border);
|
|
3277
|
-
border-radius:
|
|
3278
|
-
padding:
|
|
3473
|
+
border-radius: 7px;
|
|
3474
|
+
padding: 9px 10px;
|
|
3279
3475
|
color: #f8fafc;
|
|
3280
3476
|
caret-color: #8b7cf7;
|
|
3281
3477
|
background: var(--spotpatch-bg-input);
|
|
3282
|
-
font-size:
|
|
3283
|
-
line-height: 1.
|
|
3478
|
+
font-size: 12.5px;
|
|
3479
|
+
line-height: 1.55;
|
|
3284
3480
|
outline: none;
|
|
3285
3481
|
transition: border-color 150ms ease, box-shadow 150ms ease, background 150ms ease;
|
|
3286
3482
|
}
|
|
@@ -3289,23 +3485,23 @@ function createStyles(document) {
|
|
|
3289
3485
|
.spotpatch-target-editor textarea:focus {
|
|
3290
3486
|
border-color: rgb(139 124 247 / 68%);
|
|
3291
3487
|
background: rgb(3 7 18 / 65%);
|
|
3292
|
-
box-shadow: 0 0 0
|
|
3488
|
+
box-shadow: 0 0 0 2px rgb(109 93 246 / 10%);
|
|
3293
3489
|
}
|
|
3294
3490
|
.spotpatch-diagnostics {
|
|
3295
|
-
margin-top:
|
|
3491
|
+
margin-top: 10px;
|
|
3296
3492
|
overflow: hidden;
|
|
3297
3493
|
border: 1px solid rgb(255 255 255 / 8%);
|
|
3298
|
-
border-radius:
|
|
3494
|
+
border-radius: 9px;
|
|
3299
3495
|
background: rgb(255 255 255 / 2.5%);
|
|
3300
3496
|
}
|
|
3301
3497
|
.spotpatch-diagnostics > summary {
|
|
3302
3498
|
display: flex;
|
|
3303
3499
|
align-items: center;
|
|
3304
3500
|
gap: 8px;
|
|
3305
|
-
padding: 11px
|
|
3501
|
+
padding: 9px 11px;
|
|
3306
3502
|
color: #bfc5d0;
|
|
3307
3503
|
cursor: pointer;
|
|
3308
|
-
font-size:
|
|
3504
|
+
font-size: 11px;
|
|
3309
3505
|
font-weight: 650;
|
|
3310
3506
|
list-style: none;
|
|
3311
3507
|
user-select: none;
|
|
@@ -3334,9 +3530,9 @@ function createStyles(document) {
|
|
|
3334
3530
|
margin: 0;
|
|
3335
3531
|
overflow: auto;
|
|
3336
3532
|
border-top: 1px solid rgb(255 255 255 / 7%);
|
|
3337
|
-
padding:
|
|
3533
|
+
padding: 10px 11px 11px;
|
|
3338
3534
|
color: #9ca5b5;
|
|
3339
|
-
font:
|
|
3535
|
+
font: 10.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
3340
3536
|
overflow-wrap: anywhere;
|
|
3341
3537
|
white-space: pre-wrap;
|
|
3342
3538
|
user-select: text;
|
|
@@ -3346,39 +3542,44 @@ function createStyles(document) {
|
|
|
3346
3542
|
margin: 0;
|
|
3347
3543
|
overflow: auto;
|
|
3348
3544
|
border: 1px solid rgb(255 255 255 / 9%);
|
|
3349
|
-
border-radius:
|
|
3350
|
-
padding:
|
|
3545
|
+
border-radius: 9px;
|
|
3546
|
+
padding: 11px;
|
|
3351
3547
|
color: #d8ddeb;
|
|
3352
3548
|
background: rgb(3 7 18 / 55%);
|
|
3353
|
-
font:
|
|
3549
|
+
font: 11px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
3354
3550
|
overflow-wrap: anywhere;
|
|
3355
3551
|
white-space: pre-wrap;
|
|
3356
3552
|
user-select: text;
|
|
3357
3553
|
}
|
|
3358
3554
|
.spotpatch-actions {
|
|
3359
|
-
display:
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
padding: 14px 22px 18px;
|
|
3555
|
+
display: grid;
|
|
3556
|
+
gap: 8px;
|
|
3557
|
+
padding: 10px 18px 14px;
|
|
3363
3558
|
border-top: 1px solid rgb(255 255 255 / 8%);
|
|
3364
|
-
background: rgb(8 12
|
|
3559
|
+
background: rgb(8 8 12 / 86%);
|
|
3365
3560
|
}
|
|
3366
3561
|
.spotpatch-editor-feedback {
|
|
3367
|
-
flex-basis: 100%;
|
|
3368
3562
|
white-space: normal;
|
|
3369
3563
|
}
|
|
3564
|
+
.spotpatch-secondary-actions,
|
|
3565
|
+
.spotpatch-primary-actions {
|
|
3566
|
+
display: flex;
|
|
3567
|
+
align-items: center;
|
|
3568
|
+
gap: 7px;
|
|
3569
|
+
}
|
|
3570
|
+
.spotpatch-secondary-actions { min-height: 30px; }
|
|
3370
3571
|
.spotpatch-actions button {
|
|
3371
3572
|
display: inline-flex;
|
|
3372
|
-
min-height:
|
|
3573
|
+
min-height: 34px;
|
|
3373
3574
|
align-items: center;
|
|
3374
3575
|
justify-content: center;
|
|
3375
3576
|
border: 1px solid rgb(255 255 255 / 10%);
|
|
3376
|
-
border-radius:
|
|
3377
|
-
padding:
|
|
3378
|
-
color:
|
|
3577
|
+
border-radius: 9px;
|
|
3578
|
+
padding: 7px 11px;
|
|
3579
|
+
color: var(--spotpatch-text-secondary);
|
|
3379
3580
|
background: rgb(255 255 255 / 4%);
|
|
3380
3581
|
cursor: pointer;
|
|
3381
|
-
font-size:
|
|
3582
|
+
font-size: 12px;
|
|
3382
3583
|
font-weight: 650;
|
|
3383
3584
|
transition: border-color 150ms ease, box-shadow 150ms ease, color 150ms ease, transform 150ms ease;
|
|
3384
3585
|
}
|
|
@@ -3388,14 +3589,36 @@ function createStyles(document) {
|
|
|
3388
3589
|
transform: translateY(-1px);
|
|
3389
3590
|
}
|
|
3390
3591
|
.spotpatch-actions .spotpatch-primary {
|
|
3391
|
-
min-width:
|
|
3592
|
+
min-width: 138px;
|
|
3392
3593
|
flex: 1;
|
|
3393
|
-
border-color:
|
|
3394
|
-
color:
|
|
3395
|
-
background: var(--spotpatch-accent-strong);
|
|
3396
|
-
box-shadow: 0
|
|
3594
|
+
border-color: transparent;
|
|
3595
|
+
color: var(--spotpatch-text-on-accent);
|
|
3596
|
+
background: linear-gradient(135deg, var(--spotpatch-accent), var(--spotpatch-accent-strong));
|
|
3597
|
+
box-shadow: 0 8px 20px -8px rgb(139 123 255 / 55%);
|
|
3397
3598
|
}
|
|
3599
|
+
.spotpatch-actions .spotpatch-primary:hover:not(:disabled) { color: var(--spotpatch-text-on-accent); filter: brightness(1.08); }
|
|
3398
3600
|
.spotpatch-actions .spotpatch-primary::after { margin-left: 8px; content: "\u2197"; font-size: 12px; }
|
|
3601
|
+
.spotpatch-actions .spotpatch-secondary-action {
|
|
3602
|
+
min-height: 30px;
|
|
3603
|
+
border-style: dashed;
|
|
3604
|
+
padding: 5px 10px;
|
|
3605
|
+
color: var(--spotpatch-text-muted);
|
|
3606
|
+
background: transparent;
|
|
3607
|
+
font-size: 11px;
|
|
3608
|
+
}
|
|
3609
|
+
.spotpatch-actions .spotpatch-icon-action {
|
|
3610
|
+
width: 34px;
|
|
3611
|
+
min-width: 34px;
|
|
3612
|
+
padding: 0;
|
|
3613
|
+
font-size: 0;
|
|
3614
|
+
}
|
|
3615
|
+
.spotpatch-actions .spotpatch-icon-action::before {
|
|
3616
|
+
color: var(--spotpatch-text-secondary);
|
|
3617
|
+
content: attr(data-compact-icon);
|
|
3618
|
+
font-size: 18px;
|
|
3619
|
+
font-weight: 400;
|
|
3620
|
+
line-height: 1;
|
|
3621
|
+
}
|
|
3399
3622
|
.spotpatch-actions button:disabled { cursor: not-allowed; opacity: .4; transform: none; }
|
|
3400
3623
|
.spotpatch-actions button:focus-visible,
|
|
3401
3624
|
.spotpatch-repository:focus-visible,
|
|
@@ -3427,11 +3650,13 @@ function createStyles(document) {
|
|
|
3427
3650
|
}
|
|
3428
3651
|
@media (max-width: 520px) {
|
|
3429
3652
|
.spotpatch-dialog { top: 8px; left: 8px; width: calc(100vw - 16px); }
|
|
3430
|
-
.spotpatch-shell { max-height: calc(100vh - 16px); border-radius:
|
|
3431
|
-
.spotpatch-header, .spotpatch-body { padding-left:
|
|
3432
|
-
.spotpatch-
|
|
3433
|
-
.spotpatch-
|
|
3653
|
+
.spotpatch-shell { max-height: calc(100vh - 16px); border-radius: 14px; }
|
|
3654
|
+
.spotpatch-header, .spotpatch-body { padding-left: 14px; padding-right: 14px; }
|
|
3655
|
+
.spotpatch-brand-row { margin-right: -14px; margin-left: -14px; padding-right: 14px; padding-left: 14px; }
|
|
3656
|
+
.spotpatch-actions { padding-right: 14px; padding-left: 14px; }
|
|
3657
|
+
.spotpatch-target-select { grid-template-columns: 24px minmax(0, 1fr); }
|
|
3434
3658
|
.spotpatch-target-state { display: none; }
|
|
3659
|
+
.spotpatch-repository { display: none; }
|
|
3435
3660
|
}
|
|
3436
3661
|
${AGENT_PANEL_STYLES}
|
|
3437
3662
|
`;
|
|
@@ -3534,10 +3759,17 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3534
3759
|
const targetCount = createMarkedElement(document, "span");
|
|
3535
3760
|
targetCount.className = "spotpatch-target-count";
|
|
3536
3761
|
targetsMeta.append(targetComplete, targetBudget);
|
|
3537
|
-
|
|
3762
|
+
targetRow.append(targetCount);
|
|
3763
|
+
targetsHeading.append(targetsTitle, targetsMeta);
|
|
3764
|
+
const targetProgress = createMarkedElement(document, "div");
|
|
3765
|
+
targetProgress.className = "spotpatch-target-progress";
|
|
3766
|
+
targetProgress.setAttribute("aria-hidden", "true");
|
|
3767
|
+
const targetProgressFill = createMarkedElement(document, "div");
|
|
3768
|
+
targetProgressFill.className = "spotpatch-target-progress-fill";
|
|
3769
|
+
targetProgress.append(targetProgressFill);
|
|
3538
3770
|
const targetList = createMarkedElement(document, "div");
|
|
3539
3771
|
targetList.className = "spotpatch-target-list";
|
|
3540
|
-
targetsPanel.append(targetsHeading,
|
|
3772
|
+
targetsPanel.append(targetsHeading, targetProgress, targetList);
|
|
3541
3773
|
const diagnostics = createMarkedElement(document, "details");
|
|
3542
3774
|
diagnostics.className = "spotpatch-diagnostics";
|
|
3543
3775
|
const diagnosticsLabel = createMarkedElement(document, "summary");
|
|
@@ -3578,21 +3810,30 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3578
3810
|
);
|
|
3579
3811
|
const copyButton = createButton(document, messages.actions.copy, "spotpatch-primary");
|
|
3580
3812
|
const backButton = createButton(document, messages.actions.back);
|
|
3581
|
-
|
|
3582
|
-
|
|
3813
|
+
const secondaryActions = createMarkedElement(document, "div");
|
|
3814
|
+
secondaryActions.className = "spotpatch-secondary-actions";
|
|
3815
|
+
const primaryActions = createMarkedElement(document, "div");
|
|
3816
|
+
primaryActions.className = "spotpatch-primary-actions";
|
|
3817
|
+
addTargetButton.classList.add("spotpatch-icon-action");
|
|
3818
|
+
addTargetButton.dataset.compactIcon = "+";
|
|
3819
|
+
agentPanel.testButton.classList.add("spotpatch-icon-action");
|
|
3820
|
+
agentPanel.testButton.dataset.compactIcon = "\u2713";
|
|
3821
|
+
openEditorButton.classList.add("spotpatch-secondary-action");
|
|
3822
|
+
reselectButton.classList.add("spotpatch-secondary-action");
|
|
3823
|
+
secondaryActions.append(openEditorButton, reselectButton);
|
|
3824
|
+
primaryActions.append(
|
|
3825
|
+
agentPanel.testButton,
|
|
3826
|
+
addTargetButton,
|
|
3583
3827
|
agentPanel.runButton,
|
|
3584
3828
|
previewButton,
|
|
3585
|
-
agentPanel.testButton,
|
|
3586
3829
|
agentPanel.cancelButton,
|
|
3587
3830
|
agentPanel.applyButton,
|
|
3588
3831
|
agentPanel.revertButton,
|
|
3589
3832
|
agentPanel.resetButton,
|
|
3590
|
-
addTargetButton,
|
|
3591
|
-
openEditorButton,
|
|
3592
|
-
reselectButton,
|
|
3593
3833
|
copyButton,
|
|
3594
3834
|
backButton
|
|
3595
3835
|
);
|
|
3836
|
+
actions.append(editorFeedback, secondaryActions, primaryActions);
|
|
3596
3837
|
shell.append(header, body, actions);
|
|
3597
3838
|
dialog.append(anchor, shell);
|
|
3598
3839
|
const liveRegion = createMarkedElement(document, "div");
|
|
@@ -3625,11 +3866,15 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3625
3866
|
editorFeedback.textContent = state === "opening" ? messages.announcements.editorOpening : state === "success" ? messages.announcements.editorOpened : state === "error" ? messages.announcements.editorFailed : "";
|
|
3626
3867
|
placeDialog();
|
|
3627
3868
|
}
|
|
3628
|
-
function statusText(
|
|
3629
|
-
if (
|
|
3869
|
+
function statusText(target2) {
|
|
3870
|
+
if (target2.status === "ready") {
|
|
3630
3871
|
return messages.targets.statusReady;
|
|
3631
3872
|
}
|
|
3632
|
-
return
|
|
3873
|
+
return target2.status === "warning" ? messages.targets.statusPartial : messages.targets.statusCollecting;
|
|
3874
|
+
}
|
|
3875
|
+
function renderTargetProgress(complete, total) {
|
|
3876
|
+
const ratio = total === 0 ? 0 : complete / total;
|
|
3877
|
+
targetProgressFill.style.width = `${String(ratio * 100)}%`;
|
|
3633
3878
|
}
|
|
3634
3879
|
function instructionInput(targetId) {
|
|
3635
3880
|
const inputs = targetList.querySelectorAll(
|
|
@@ -3646,16 +3891,17 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3646
3891
|
const focusedTargetId = focusedInstruction?.dataset.targetInstructionId;
|
|
3647
3892
|
const selectionStart = focusedInstruction?.selectionStart;
|
|
3648
3893
|
const selectionEnd = focusedInstruction?.selectionEnd;
|
|
3649
|
-
currentTargets = targets.map((
|
|
3894
|
+
currentTargets = targets.map((target2) => Object.freeze({ ...target2 }));
|
|
3650
3895
|
currentMaximum = maximum;
|
|
3651
3896
|
targetList.replaceChildren();
|
|
3652
3897
|
const completeCount = targets.filter(
|
|
3653
|
-
(
|
|
3898
|
+
(target2) => target2.instruction.trim().length > 0
|
|
3654
3899
|
).length;
|
|
3655
3900
|
const instructionCharacters = targets.reduce(
|
|
3656
|
-
(total,
|
|
3901
|
+
(total, target2) => total + target2.instruction.trim().length,
|
|
3657
3902
|
0
|
|
3658
3903
|
);
|
|
3904
|
+
renderTargetProgress(completeCount, targets.length);
|
|
3659
3905
|
targetCount.textContent = messages.targets.count(targets.length, maximum);
|
|
3660
3906
|
targetComplete.textContent = messages.targets.complete(
|
|
3661
3907
|
completeCount,
|
|
@@ -3673,18 +3919,18 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3673
3919
|
addTargetButton.disabled = !editingEnabled || targets.length >= maximum;
|
|
3674
3920
|
addTargetButton.title = targets.length >= maximum ? messages.targets.limitTitle(maximum) : messages.targets.addTitle;
|
|
3675
3921
|
targetLabel.textContent = targets.length === 1 ? targets[0]?.label ?? messages.context.selectedElement : messages.context.selectedCount(targets.length);
|
|
3676
|
-
for (const [index,
|
|
3922
|
+
for (const [index, target2] of targets.entries()) {
|
|
3677
3923
|
const item = createMarkedElement(document, "div");
|
|
3678
3924
|
item.className = "spotpatch-target-item";
|
|
3679
|
-
item.dataset.active = String(
|
|
3680
|
-
item.dataset.status =
|
|
3681
|
-
item.dataset.targetId =
|
|
3925
|
+
item.dataset.active = String(target2.active);
|
|
3926
|
+
item.dataset.status = target2.status;
|
|
3927
|
+
item.dataset.targetId = target2.id;
|
|
3682
3928
|
const targetSummary = createMarkedElement(document, "div");
|
|
3683
3929
|
targetSummary.className = "spotpatch-target-summary";
|
|
3684
3930
|
const select = createButton(document, "", "spotpatch-target-select");
|
|
3685
|
-
select.dataset.activateTargetId =
|
|
3931
|
+
select.dataset.activateTargetId = target2.id;
|
|
3686
3932
|
select.setAttribute("aria-label", messages.targets.activate(index + 1));
|
|
3687
|
-
select.setAttribute("aria-expanded", String(
|
|
3933
|
+
select.setAttribute("aria-expanded", String(target2.active));
|
|
3688
3934
|
const number = createMarkedElement(document, "span");
|
|
3689
3935
|
number.className = "spotpatch-target-index";
|
|
3690
3936
|
number.textContent = String(index + 1);
|
|
@@ -3692,54 +3938,54 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3692
3938
|
copy.className = "spotpatch-target-copy";
|
|
3693
3939
|
const name = createMarkedElement(document, "span");
|
|
3694
3940
|
name.className = "spotpatch-target-name";
|
|
3695
|
-
name.textContent =
|
|
3696
|
-
const
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
copy.append(name,
|
|
3700
|
-
const instructionComplete =
|
|
3941
|
+
name.textContent = target2.label;
|
|
3942
|
+
const source2 = createMarkedElement(document, "span");
|
|
3943
|
+
source2.className = "spotpatch-target-source";
|
|
3944
|
+
source2.textContent = `${statusText(target2)} \xB7 ${target2.source}`;
|
|
3945
|
+
copy.append(name, source2);
|
|
3946
|
+
const instructionComplete = target2.instruction.trim().length > 0;
|
|
3701
3947
|
const state = createMarkedElement(document, "span");
|
|
3702
3948
|
state.className = "spotpatch-target-state";
|
|
3703
3949
|
state.dataset.complete = String(instructionComplete);
|
|
3704
3950
|
state.textContent = instructionComplete ? messages.targets.instructionReady : messages.targets.instructionMissing;
|
|
3705
3951
|
select.append(number, copy, state);
|
|
3706
3952
|
const open = createButton(document, "\u2197", "spotpatch-target-open");
|
|
3707
|
-
open.dataset.openTargetId =
|
|
3708
|
-
open.disabled = !
|
|
3953
|
+
open.dataset.openTargetId = target2.id;
|
|
3954
|
+
open.disabled = !target2.canOpenEditor;
|
|
3709
3955
|
open.setAttribute("aria-label", messages.actions.openTarget(index + 1));
|
|
3710
3956
|
open.title = messages.actions.openTarget(index + 1);
|
|
3711
3957
|
const remove = createButton(document, "\xD7", "spotpatch-target-remove");
|
|
3712
|
-
remove.dataset.removeTargetId =
|
|
3958
|
+
remove.dataset.removeTargetId = target2.id;
|
|
3713
3959
|
remove.disabled = !editingEnabled;
|
|
3714
3960
|
remove.setAttribute("aria-label", messages.targets.remove(index + 1));
|
|
3715
3961
|
remove.title = messages.targets.removeTitle;
|
|
3716
3962
|
targetSummary.append(select, open, remove);
|
|
3717
3963
|
item.append(targetSummary);
|
|
3718
|
-
if (
|
|
3964
|
+
if (target2.active) {
|
|
3719
3965
|
const editor = createMarkedElement(document, "label");
|
|
3720
3966
|
editor.className = "spotpatch-target-editor";
|
|
3721
3967
|
const editorHead = createMarkedElement(document, "span");
|
|
3722
3968
|
editorHead.className = "spotpatch-target-editor-head";
|
|
3723
3969
|
const editorLabel = createMarkedElement(document, "span");
|
|
3724
3970
|
editorLabel.className = "spotpatch-target-editor-label";
|
|
3725
|
-
editorLabel.textContent = messages.targets.instructionLabel(
|
|
3971
|
+
editorLabel.textContent = messages.targets.instructionLabel(target2.label);
|
|
3726
3972
|
const characterCount = createMarkedElement(document, "span");
|
|
3727
3973
|
characterCount.className = "spotpatch-target-editor-count";
|
|
3728
3974
|
characterCount.textContent = messages.targets.instructionCount(
|
|
3729
|
-
|
|
3975
|
+
target2.instruction.length,
|
|
3730
3976
|
MAX_TARGET_INSTRUCTION_CHARACTERS2
|
|
3731
3977
|
);
|
|
3732
3978
|
editorHead.append(editorLabel, characterCount);
|
|
3733
3979
|
const input = createMarkedElement(document, "textarea");
|
|
3734
3980
|
input.rows = 4;
|
|
3735
3981
|
input.maxLength = MAX_TARGET_INSTRUCTION_CHARACTERS2;
|
|
3736
|
-
input.value =
|
|
3982
|
+
input.value = target2.instruction;
|
|
3737
3983
|
input.placeholder = messages.targets.instructionPlaceholder;
|
|
3738
3984
|
input.disabled = !editingEnabled;
|
|
3739
|
-
input.dataset.targetInstructionId =
|
|
3985
|
+
input.dataset.targetInstructionId = target2.id;
|
|
3740
3986
|
input.setAttribute(
|
|
3741
3987
|
"aria-label",
|
|
3742
|
-
messages.targets.instructionLabel(
|
|
3988
|
+
messages.targets.instructionLabel(target2.label)
|
|
3743
3989
|
);
|
|
3744
3990
|
editor.append(editorHead, input);
|
|
3745
3991
|
item.append(editor);
|
|
@@ -3756,7 +4002,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3756
4002
|
}
|
|
3757
4003
|
function updateTargetInstruction(targetId, instruction) {
|
|
3758
4004
|
currentTargets = currentTargets.map(
|
|
3759
|
-
(
|
|
4005
|
+
(target2) => target2.id === targetId ? Object.freeze({ ...target2, instruction }) : target2
|
|
3760
4006
|
);
|
|
3761
4007
|
const item = Array.from(
|
|
3762
4008
|
targetList.querySelectorAll(".spotpatch-target-item")
|
|
@@ -3777,12 +4023,16 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3777
4023
|
MAX_TARGET_INSTRUCTION_CHARACTERS2
|
|
3778
4024
|
);
|
|
3779
4025
|
}
|
|
4026
|
+
const completeCount = currentTargets.filter(
|
|
4027
|
+
(target2) => target2.instruction.trim().length > 0
|
|
4028
|
+
).length;
|
|
3780
4029
|
targetComplete.textContent = messages.targets.complete(
|
|
3781
|
-
|
|
4030
|
+
completeCount,
|
|
3782
4031
|
currentTargets.length
|
|
3783
4032
|
);
|
|
4033
|
+
renderTargetProgress(completeCount, currentTargets.length);
|
|
3784
4034
|
const instructionCharacters = currentTargets.reduce(
|
|
3785
|
-
(total,
|
|
4035
|
+
(total, target2) => total + target2.instruction.trim().length,
|
|
3786
4036
|
0
|
|
3787
4037
|
);
|
|
3788
4038
|
const instructionLimitExceeded = instructionCharacters > MAX_ANNOTATION_INSTRUCTION_CHARACTERS2;
|
|
@@ -3797,25 +4047,25 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3797
4047
|
}
|
|
3798
4048
|
function showSelectionHighlights(targets) {
|
|
3799
4049
|
selectionHighlights.replaceChildren();
|
|
3800
|
-
activeSelectionRect = targets.find((
|
|
4050
|
+
activeSelectionRect = targets.find((target2) => target2.active)?.rect;
|
|
3801
4051
|
currentRect = activeSelectionRect;
|
|
3802
|
-
for (const [index,
|
|
4052
|
+
for (const [index, target2] of targets.entries()) {
|
|
3803
4053
|
const box = createMarkedElement(document, "div");
|
|
3804
4054
|
box.className = "spotpatch-selection-highlight";
|
|
3805
|
-
box.dataset.targetId =
|
|
3806
|
-
box.dataset.active = String(
|
|
3807
|
-
box.style.transform = `translate(${String(
|
|
3808
|
-
box.style.width = `${String(
|
|
3809
|
-
box.style.height = `${String(
|
|
4055
|
+
box.dataset.targetId = target2.id;
|
|
4056
|
+
box.dataset.active = String(target2.active);
|
|
4057
|
+
box.style.transform = `translate(${String(target2.rect.x)}px, ${String(target2.rect.y)}px)`;
|
|
4058
|
+
box.style.width = `${String(target2.rect.width)}px`;
|
|
4059
|
+
box.style.height = `${String(target2.rect.height)}px`;
|
|
3810
4060
|
const label = createMarkedElement(document, "span");
|
|
3811
|
-
label.textContent = `${String(index + 1)} \xB7 ${
|
|
4061
|
+
label.textContent = `${String(index + 1)} \xB7 ${target2.label}`;
|
|
3812
4062
|
box.append(label);
|
|
3813
4063
|
selectionHighlights.append(box);
|
|
3814
4064
|
}
|
|
3815
4065
|
placeDialog();
|
|
3816
4066
|
}
|
|
3817
4067
|
function placeDialog() {
|
|
3818
|
-
if (dialog.hidden
|
|
4068
|
+
if (dialog.hidden) {
|
|
3819
4069
|
return;
|
|
3820
4070
|
}
|
|
3821
4071
|
const view = document.defaultView;
|
|
@@ -3823,14 +4073,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3823
4073
|
const viewportHeight = view?.innerHeight ?? document.documentElement.clientHeight;
|
|
3824
4074
|
const measured = dialog.getBoundingClientRect();
|
|
3825
4075
|
const status = currentStatus === "previewing" ? "previewing" : "selected";
|
|
3826
|
-
const dialogWidth = measured.width > 0 ? measured.width : Math.min(
|
|
4076
|
+
const dialogWidth = measured.width > 0 ? measured.width : Math.min(DIALOG_MAX_WIDTH, viewportWidth - 32);
|
|
3827
4077
|
const dialogHeight = measured.height > 0 ? measured.height : Math.min(DIALOG_FALLBACK_HEIGHT[status], viewportHeight - 32);
|
|
3828
4078
|
const placement = calculateDialogPlacement({
|
|
3829
|
-
target: currentRect,
|
|
3830
4079
|
dialogWidth,
|
|
3831
4080
|
dialogHeight,
|
|
3832
4081
|
viewportWidth,
|
|
3833
|
-
viewportHeight
|
|
4082
|
+
viewportHeight,
|
|
4083
|
+
...currentRect === void 0 ? {} : { target: currentRect }
|
|
3834
4084
|
});
|
|
3835
4085
|
dialog.style.left = `${String(placement.left)}px`;
|
|
3836
4086
|
dialog.style.top = `${String(placement.top)}px`;
|
|
@@ -3840,8 +4090,8 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3840
4090
|
}
|
|
3841
4091
|
function updateContextOverview(summaryText) {
|
|
3842
4092
|
const summaryMessages = messages.summary;
|
|
3843
|
-
const
|
|
3844
|
-
sourcePeek.textContent =
|
|
4093
|
+
const source2 = summaryLine(summaryText, summaryMessages.source);
|
|
4094
|
+
sourcePeek.textContent = source2 ?? messages.diagnostics.noExactSource;
|
|
3845
4095
|
const browserReady = `${summaryMessages.browserContext}: ${summaryMessages.collectionStatuses.ready}`;
|
|
3846
4096
|
const browserLoading = `${summaryMessages.browserContext}: ${summaryMessages.collectionStatuses.loading}`;
|
|
3847
4097
|
const browserFailed = `${summaryMessages.browserContext}: ${summaryMessages.collectionStatuses.failed}`;
|
|
@@ -3880,6 +4130,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3880
4130
|
addTargetButton.hidden = !selected;
|
|
3881
4131
|
openEditorButton.hidden = !selected;
|
|
3882
4132
|
previewButton.hidden = !selected;
|
|
4133
|
+
secondaryActions.hidden = !selected;
|
|
3883
4134
|
agentPanel.setSelectionVisible(selected);
|
|
3884
4135
|
copyButton.hidden = !previewing;
|
|
3885
4136
|
backButton.hidden = !previewing;
|
|
@@ -3918,6 +4169,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3918
4169
|
} else {
|
|
3919
4170
|
targetCount.textContent = messages.targets.count(0, currentMaximum);
|
|
3920
4171
|
targetComplete.textContent = messages.targets.complete(0, 0);
|
|
4172
|
+
renderTargetProgress(0, 0);
|
|
3921
4173
|
targetBudget.dataset.state = "ready";
|
|
3922
4174
|
targetBudget.textContent = messages.targets.instructionBudget(
|
|
3923
4175
|
0,
|
|
@@ -3986,6 +4238,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3986
4238
|
selectionHighlights.replaceChildren();
|
|
3987
4239
|
activeSelectionRect = void 0;
|
|
3988
4240
|
currentRect = void 0;
|
|
4241
|
+
placeDialog();
|
|
3989
4242
|
},
|
|
3990
4243
|
showSelection(summaryText, canOpenEditor, canPreview) {
|
|
3991
4244
|
updateSelection(summaryText, canOpenEditor, canPreview);
|
|
@@ -4011,6 +4264,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
4011
4264
|
renderEditorStatus("idle");
|
|
4012
4265
|
targetCount.textContent = messages.targets.count(0, 0);
|
|
4013
4266
|
targetComplete.textContent = messages.targets.complete(0, 0);
|
|
4267
|
+
renderTargetProgress(0, 0);
|
|
4014
4268
|
targetLabel.textContent = messages.context.selectedElement;
|
|
4015
4269
|
summary.textContent = "";
|
|
4016
4270
|
promptOutput.textContent = "";
|
|
@@ -4552,25 +4806,25 @@ var EMPTY_STYLE_CONTEXT = Object.freeze({
|
|
|
4552
4806
|
computed: Object.freeze({}),
|
|
4553
4807
|
warnings: Object.freeze(["CSS context collection failed."])
|
|
4554
4808
|
});
|
|
4555
|
-
function elementLabel(
|
|
4556
|
-
const id =
|
|
4557
|
-
const className = Array.from(
|
|
4558
|
-
return `<${
|
|
4559
|
-
}
|
|
4560
|
-
function sourceLabel(
|
|
4561
|
-
const path =
|
|
4562
|
-
const line =
|
|
4563
|
-
const column =
|
|
4809
|
+
function elementLabel(element2) {
|
|
4810
|
+
const id = element2.id.length > 0 ? `#${element2.id}` : "";
|
|
4811
|
+
const className = Array.from(element2.classList).slice(0, 2).map((name) => `.${name}`).join("");
|
|
4812
|
+
return `<${element2.tagName.toLowerCase()}${id}${className}>`;
|
|
4813
|
+
}
|
|
4814
|
+
function sourceLabel(target2, unavailable) {
|
|
4815
|
+
const path = target2.code?.relativePath ?? target2.resolution.source.relativePath;
|
|
4816
|
+
const line = target2.resolution.source.line;
|
|
4817
|
+
const column = target2.resolution.source.column;
|
|
4564
4818
|
if (path === void 0) {
|
|
4565
4819
|
return unavailable;
|
|
4566
4820
|
}
|
|
4567
4821
|
return `${path}${line === void 0 ? "" : `:${String(line)}`}${column === void 0 ? "" : `:${String(column)}`}`;
|
|
4568
4822
|
}
|
|
4569
|
-
function targetStatus(
|
|
4570
|
-
if (
|
|
4823
|
+
function targetStatus(target2) {
|
|
4824
|
+
if (target2.apiStatus === "failed" || target2.collectionStatus === "failed") {
|
|
4571
4825
|
return "warning";
|
|
4572
4826
|
}
|
|
4573
|
-
if (
|
|
4827
|
+
if (target2.apiStatus === "loading" || target2.collectionStatus === "loading") {
|
|
4574
4828
|
return "loading";
|
|
4575
4829
|
}
|
|
4576
4830
|
return "ready";
|
|
@@ -4597,6 +4851,8 @@ function createController(config, dependencies = {}) {
|
|
|
4597
4851
|
const clipboard = dependencies.clipboard ?? resolveClipboardWriter(browser.window.navigator);
|
|
4598
4852
|
const createId = dependencies.createId ?? (() => createBrowserAnnotationId(browser.window));
|
|
4599
4853
|
const now = dependencies.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
4854
|
+
const selectionSession = dependencies.selectionSession ?? createSelectionSession(browser.window, config.sessionId, config.maxTargets);
|
|
4855
|
+
const restoredSelection = selectionSession.load();
|
|
4600
4856
|
const sourceResolver = createSourceResolver({
|
|
4601
4857
|
adapter: dependencies.reactAdapter ?? createReact18Adapter({
|
|
4602
4858
|
maxComponentDepth: config.budget.maxComponentDepth
|
|
@@ -4614,9 +4870,26 @@ function createController(config, dependencies = {}) {
|
|
|
4614
4870
|
let mounted = false;
|
|
4615
4871
|
let animationFrame;
|
|
4616
4872
|
let lastPointer;
|
|
4617
|
-
let targets =
|
|
4618
|
-
|
|
4619
|
-
|
|
4873
|
+
let targets = restoredSelection?.targets.map((target2) => {
|
|
4874
|
+
const marker = sourceRefToMarker(target2.source);
|
|
4875
|
+
return {
|
|
4876
|
+
id: target2.id,
|
|
4877
|
+
resolution: Object.freeze({ source: target2.source, react: target2.react }),
|
|
4878
|
+
apiStatus: marker === void 0 ? "not-required" : target2.code === void 0 ? "failed" : "connected",
|
|
4879
|
+
code: target2.code,
|
|
4880
|
+
collectionStatus: "ready",
|
|
4881
|
+
element: void 0,
|
|
4882
|
+
elementContext: target2.element,
|
|
4883
|
+
instruction: target2.instruction,
|
|
4884
|
+
marker,
|
|
4885
|
+
page: target2.page,
|
|
4886
|
+
styles: target2.styles
|
|
4887
|
+
};
|
|
4888
|
+
}) ?? [];
|
|
4889
|
+
let activeTargetId = restoredSelection?.activeTargetId;
|
|
4890
|
+
let targetSequence = restoredSelection?.sequence ?? 0;
|
|
4891
|
+
let selectionOpen = restoredSelection?.open ?? false;
|
|
4892
|
+
let workflowSelectionActive = false;
|
|
4620
4893
|
let sessionRevision = 0;
|
|
4621
4894
|
let editorRequestRevision = 0;
|
|
4622
4895
|
let addingTarget = false;
|
|
@@ -4631,51 +4904,87 @@ function createController(config, dependencies = {}) {
|
|
|
4631
4904
|
view.renderStatus(state.status);
|
|
4632
4905
|
}
|
|
4633
4906
|
function activeTarget() {
|
|
4634
|
-
return targets.find((
|
|
4907
|
+
return targets.find((target2) => target2.id === activeTargetId) ?? targets.at(-1);
|
|
4908
|
+
}
|
|
4909
|
+
function snapshotTarget(target2) {
|
|
4910
|
+
if (target2.elementContext === void 0 || target2.styles === void 0) {
|
|
4911
|
+
return void 0;
|
|
4912
|
+
}
|
|
4913
|
+
return {
|
|
4914
|
+
id: target2.id,
|
|
4915
|
+
instruction: target2.instruction,
|
|
4916
|
+
page: target2.page,
|
|
4917
|
+
source: target2.resolution.source,
|
|
4918
|
+
react: target2.resolution.react,
|
|
4919
|
+
element: target2.elementContext,
|
|
4920
|
+
styles: target2.styles,
|
|
4921
|
+
...target2.code === void 0 ? {} : { code: target2.code }
|
|
4922
|
+
};
|
|
4635
4923
|
}
|
|
4636
|
-
function
|
|
4637
|
-
|
|
4924
|
+
function persistSelection() {
|
|
4925
|
+
const persistedTargets = targets.flatMap((target2) => {
|
|
4926
|
+
const snapshot = snapshotTarget(target2);
|
|
4927
|
+
return snapshot === void 0 ? [] : [snapshot];
|
|
4928
|
+
});
|
|
4929
|
+
if (persistedTargets.length === 0) {
|
|
4930
|
+
selectionSession.clear();
|
|
4931
|
+
return;
|
|
4932
|
+
}
|
|
4933
|
+
const persistedIds = new Set(persistedTargets.map(({ id }) => id));
|
|
4934
|
+
selectionSession.save({
|
|
4935
|
+
...activeTargetId !== void 0 && persistedIds.has(activeTargetId) ? { activeTargetId } : {},
|
|
4936
|
+
open: selectionOpen,
|
|
4937
|
+
sequence: targetSequence,
|
|
4938
|
+
targets: persistedTargets
|
|
4939
|
+
});
|
|
4940
|
+
}
|
|
4941
|
+
function targetIsCurrent(target2, revision) {
|
|
4942
|
+
return mounted && revision === sessionRevision && state.status !== "idle" && targets.includes(target2);
|
|
4638
4943
|
}
|
|
4639
4944
|
function canPreview() {
|
|
4640
4945
|
const instructionCharacters = targets.reduce(
|
|
4641
|
-
(total,
|
|
4946
|
+
(total, target2) => total + target2.instruction.trim().length,
|
|
4642
4947
|
0
|
|
4643
4948
|
);
|
|
4644
4949
|
return targets.length > 0 && instructionCharacters <= MAX_ANNOTATION_INSTRUCTION_CHARACTERS3 && targets.every(
|
|
4645
|
-
(
|
|
4950
|
+
(target2) => target2.instruction.trim().length > 0 && target2.elementContext !== void 0 && target2.styles !== void 0 && target2.apiStatus !== "loading"
|
|
4646
4951
|
);
|
|
4647
4952
|
}
|
|
4648
4953
|
function selectionSummary() {
|
|
4649
4954
|
const messages = view.messages().summary;
|
|
4650
|
-
return targets.map((
|
|
4955
|
+
return targets.map((target2, index) => {
|
|
4651
4956
|
const summary = createSelectionSummary(
|
|
4652
4957
|
{
|
|
4653
|
-
resolution:
|
|
4654
|
-
...
|
|
4655
|
-
...
|
|
4656
|
-
apiStatus:
|
|
4657
|
-
collectionStatus:
|
|
4958
|
+
resolution: target2.resolution,
|
|
4959
|
+
...target2.code === void 0 ? {} : { code: target2.code },
|
|
4960
|
+
...target2.styles === void 0 ? {} : { styles: target2.styles },
|
|
4961
|
+
apiStatus: target2.apiStatus,
|
|
4962
|
+
collectionStatus: target2.collectionStatus,
|
|
4658
4963
|
framework: config.framework,
|
|
4659
4964
|
frameworkVersion: config.frameworkVersion,
|
|
4660
4965
|
spotPatchVersion: config.spotPatchVersion
|
|
4661
4966
|
},
|
|
4662
4967
|
messages
|
|
4663
4968
|
);
|
|
4664
|
-
return `${messages.target(index + 1,
|
|
4969
|
+
return `${messages.target(index + 1, target2.id === activeTargetId)}
|
|
4665
4970
|
${summary}`;
|
|
4666
4971
|
}).join("\n\n");
|
|
4667
4972
|
}
|
|
4668
4973
|
function refreshHighlights() {
|
|
4669
|
-
const highlights = targets.flatMap((
|
|
4670
|
-
if (!
|
|
4974
|
+
const highlights = targets.flatMap((target2) => {
|
|
4975
|
+
if (!target2.element?.isConnected) {
|
|
4976
|
+
return [];
|
|
4977
|
+
}
|
|
4978
|
+
const rect = getVisibleElementRect(target2.element, browser.window);
|
|
4979
|
+
if (rect === void 0) {
|
|
4671
4980
|
return [];
|
|
4672
4981
|
}
|
|
4673
4982
|
return [
|
|
4674
4983
|
{
|
|
4675
|
-
id:
|
|
4676
|
-
label: elementLabel(
|
|
4677
|
-
rect
|
|
4678
|
-
active:
|
|
4984
|
+
id: target2.id,
|
|
4985
|
+
label: elementLabel(target2.element),
|
|
4986
|
+
rect,
|
|
4987
|
+
active: target2.id === activeTargetId
|
|
4679
4988
|
}
|
|
4680
4989
|
];
|
|
4681
4990
|
});
|
|
@@ -4690,14 +4999,14 @@ ${summary}`;
|
|
|
4690
4999
|
return;
|
|
4691
5000
|
}
|
|
4692
5001
|
view.renderTargets(
|
|
4693
|
-
targets.map((
|
|
4694
|
-
id:
|
|
4695
|
-
label:
|
|
4696
|
-
source: sourceLabel(
|
|
4697
|
-
canOpenEditor:
|
|
4698
|
-
status: targetStatus(
|
|
4699
|
-
active:
|
|
4700
|
-
instruction:
|
|
5002
|
+
targets.map((target2) => ({
|
|
5003
|
+
id: target2.id,
|
|
5004
|
+
label: target2.resolution.react.componentName ?? (target2.element === void 0 ? target2.elementContext?.tagName ?? "Element" : elementLabel(target2.element)),
|
|
5005
|
+
source: sourceLabel(target2, view.messages().context.sourceUnavailable),
|
|
5006
|
+
canOpenEditor: target2.marker !== void 0,
|
|
5007
|
+
status: targetStatus(target2),
|
|
5008
|
+
active: target2.id === activeTargetId,
|
|
5009
|
+
instruction: target2.instruction
|
|
4701
5010
|
})),
|
|
4702
5011
|
config.maxTargets
|
|
4703
5012
|
);
|
|
@@ -4715,21 +5024,22 @@ ${summary}`;
|
|
|
4715
5024
|
if (!canPreview()) {
|
|
4716
5025
|
return void 0;
|
|
4717
5026
|
}
|
|
4718
|
-
const annotationTargets = targets.map((
|
|
4719
|
-
if (
|
|
5027
|
+
const annotationTargets = targets.map((target2) => {
|
|
5028
|
+
if (target2.elementContext === void 0 || target2.styles === void 0) {
|
|
4720
5029
|
throw new Error("SpotPatch attempted to compose an incomplete target.");
|
|
4721
5030
|
}
|
|
4722
5031
|
const warnings = [
|
|
4723
|
-
...
|
|
4724
|
-
...
|
|
5032
|
+
...target2.apiStatus === "failed" ? ["Source context could not be loaded."] : [],
|
|
5033
|
+
...target2.collectionStatus === "failed" ? ["Part of the browser context could not be collected."] : []
|
|
4725
5034
|
];
|
|
4726
5035
|
return {
|
|
4727
|
-
instruction:
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
5036
|
+
instruction: target2.instruction.trim(),
|
|
5037
|
+
page: target2.page,
|
|
5038
|
+
source: target2.resolution.source,
|
|
5039
|
+
react: target2.resolution.react,
|
|
5040
|
+
element: target2.elementContext,
|
|
5041
|
+
styles: target2.styles,
|
|
5042
|
+
...target2.code === void 0 ? {} : { code: target2.code },
|
|
4733
5043
|
warnings
|
|
4734
5044
|
};
|
|
4735
5045
|
});
|
|
@@ -4741,8 +5051,8 @@ ${summary}`;
|
|
|
4741
5051
|
targets: annotationTargets
|
|
4742
5052
|
});
|
|
4743
5053
|
}
|
|
4744
|
-
function showElementHighlight(
|
|
4745
|
-
view.showHighlight(getElementRect(
|
|
5054
|
+
function showElementHighlight(element2) {
|
|
5055
|
+
view.showHighlight(getElementRect(element2, browser.window), elementLabel(element2));
|
|
4746
5056
|
}
|
|
4747
5057
|
function restoreFocus() {
|
|
4748
5058
|
if (previousFocus?.isConnected === true) {
|
|
@@ -4764,10 +5074,13 @@ ${summary}`;
|
|
|
4764
5074
|
resizeObserver?.disconnect();
|
|
4765
5075
|
targets = [];
|
|
4766
5076
|
activeTargetId = void 0;
|
|
5077
|
+
selectionOpen = false;
|
|
5078
|
+
workflowSelectionActive = false;
|
|
4767
5079
|
addingTarget = false;
|
|
4768
5080
|
previewPrompt = "";
|
|
4769
5081
|
view.hideSelection();
|
|
4770
5082
|
view.hideSelectionHighlights();
|
|
5083
|
+
selectionSession.clear();
|
|
4771
5084
|
restoreFocus();
|
|
4772
5085
|
}
|
|
4773
5086
|
function close() {
|
|
@@ -4779,7 +5092,11 @@ ${summary}`;
|
|
|
4779
5092
|
transition({ type: "BACK" });
|
|
4780
5093
|
transition({ type: "CLOSE" });
|
|
4781
5094
|
}
|
|
4782
|
-
|
|
5095
|
+
selectionOpen = false;
|
|
5096
|
+
persistSelection();
|
|
5097
|
+
view.hideSelection();
|
|
5098
|
+
view.hideSelectionHighlights();
|
|
5099
|
+
restoreFocus();
|
|
4783
5100
|
view.hideHighlight();
|
|
4784
5101
|
}
|
|
4785
5102
|
function cancelAddTarget() {
|
|
@@ -4803,6 +5120,18 @@ ${summary}`;
|
|
|
4803
5120
|
close();
|
|
4804
5121
|
return;
|
|
4805
5122
|
}
|
|
5123
|
+
if (targets.length > 0) {
|
|
5124
|
+
selectionOpen = true;
|
|
5125
|
+
transition({ type: "RESTORE" });
|
|
5126
|
+
if (!workflowSelectionActive) {
|
|
5127
|
+
agentWorkflow.beginSelection();
|
|
5128
|
+
workflowSelectionActive = true;
|
|
5129
|
+
}
|
|
5130
|
+
refreshSelectionView(true);
|
|
5131
|
+
view.focusTargetInstruction(activeTargetId);
|
|
5132
|
+
persistSelection();
|
|
5133
|
+
return;
|
|
5134
|
+
}
|
|
4806
5135
|
transition({ type: "ACTIVATE" });
|
|
4807
5136
|
view.hideSelection();
|
|
4808
5137
|
view.announce(view.messages().announcements.selectionEnabled);
|
|
@@ -4836,12 +5165,13 @@ ${summary}`;
|
|
|
4836
5165
|
sessionRevision += 1;
|
|
4837
5166
|
clearCollectionTimers();
|
|
4838
5167
|
resizeObserver?.disconnect();
|
|
4839
|
-
for (const
|
|
4840
|
-
|
|
5168
|
+
for (const target2 of targets) {
|
|
5169
|
+
target2.element = void 0;
|
|
4841
5170
|
}
|
|
4842
5171
|
view.hideHighlight();
|
|
4843
5172
|
view.hideSelectionHighlights();
|
|
4844
5173
|
refreshSelectionView();
|
|
5174
|
+
selectionSession.clear();
|
|
4845
5175
|
view.announce(view.messages().announcements.appliedTargetsDetached);
|
|
4846
5176
|
}
|
|
4847
5177
|
const agentWorkflow = createAgentWorkflow({
|
|
@@ -4854,8 +5184,8 @@ ${summary}`;
|
|
|
4854
5184
|
},
|
|
4855
5185
|
view
|
|
4856
5186
|
});
|
|
4857
|
-
async function loadSourceContext(
|
|
4858
|
-
const marker =
|
|
5187
|
+
async function loadSourceContext(target2, revision) {
|
|
5188
|
+
const marker = target2.marker;
|
|
4859
5189
|
if (marker === void 0) {
|
|
4860
5190
|
return;
|
|
4861
5191
|
}
|
|
@@ -4866,16 +5196,18 @@ ${summary}`;
|
|
|
4866
5196
|
column: marker.column,
|
|
4867
5197
|
maxLines: config.budget.maxCodeLines
|
|
4868
5198
|
});
|
|
4869
|
-
if (targetIsCurrent(
|
|
4870
|
-
|
|
4871
|
-
|
|
5199
|
+
if (targetIsCurrent(target2, revision)) {
|
|
5200
|
+
target2.code = context;
|
|
5201
|
+
target2.apiStatus = "connected";
|
|
5202
|
+
persistSelection();
|
|
4872
5203
|
refreshSelectionView();
|
|
4873
5204
|
view.announce(view.messages().announcements.sourceLoaded);
|
|
4874
5205
|
}
|
|
4875
5206
|
} catch (error) {
|
|
4876
|
-
if (targetIsCurrent(
|
|
4877
|
-
|
|
4878
|
-
|
|
5207
|
+
if (targetIsCurrent(target2, revision)) {
|
|
5208
|
+
target2.code = void 0;
|
|
5209
|
+
target2.apiStatus = "failed";
|
|
5210
|
+
persistSelection();
|
|
4879
5211
|
refreshSelectionView();
|
|
4880
5212
|
view.announce(view.messages().announcements.sourceFailed);
|
|
4881
5213
|
if (config.debug && !(error instanceof DOMException && error.name === "AbortError")) {
|
|
@@ -4884,61 +5216,62 @@ ${summary}`;
|
|
|
4884
5216
|
}
|
|
4885
5217
|
}
|
|
4886
5218
|
}
|
|
4887
|
-
function scheduleBrowserContextCollection(
|
|
4888
|
-
const
|
|
4889
|
-
if (
|
|
5219
|
+
function scheduleBrowserContextCollection(target2, revision) {
|
|
5220
|
+
const element2 = target2.element;
|
|
5221
|
+
if (element2 === void 0) {
|
|
4890
5222
|
return;
|
|
4891
5223
|
}
|
|
4892
5224
|
const timer = browser.window.setTimeout(() => {
|
|
4893
|
-
collectionTimers.delete(
|
|
4894
|
-
if (!targetIsCurrent(
|
|
5225
|
+
collectionTimers.delete(target2.id);
|
|
5226
|
+
if (!targetIsCurrent(target2, revision)) {
|
|
4895
5227
|
return;
|
|
4896
5228
|
}
|
|
4897
5229
|
let failed = false;
|
|
4898
5230
|
try {
|
|
4899
|
-
|
|
4900
|
-
element,
|
|
5231
|
+
target2.elementContext = collectElementContext({
|
|
5232
|
+
element: element2,
|
|
4901
5233
|
maxCharacters: config.budget.domCharacters
|
|
4902
5234
|
});
|
|
4903
5235
|
} catch {
|
|
4904
|
-
|
|
5236
|
+
target2.elementContext = void 0;
|
|
4905
5237
|
failed = true;
|
|
4906
5238
|
}
|
|
4907
5239
|
try {
|
|
4908
|
-
|
|
5240
|
+
target2.styles = collectStyleContext({
|
|
4909
5241
|
document: browser.document,
|
|
4910
|
-
element,
|
|
5242
|
+
element: element2,
|
|
4911
5243
|
maxCharacters: config.budget.cssCharacters
|
|
4912
5244
|
});
|
|
4913
5245
|
} catch {
|
|
4914
|
-
|
|
5246
|
+
target2.styles = EMPTY_STYLE_CONTEXT;
|
|
4915
5247
|
failed = true;
|
|
4916
5248
|
}
|
|
4917
|
-
|
|
5249
|
+
target2.collectionStatus = failed ? "failed" : "ready";
|
|
5250
|
+
persistSelection();
|
|
4918
5251
|
refreshSelectionView();
|
|
4919
5252
|
view.announce(
|
|
4920
5253
|
failed ? view.messages().announcements.contextWarning : view.messages().announcements.contextCollected
|
|
4921
5254
|
);
|
|
4922
|
-
if (config.debug &&
|
|
5255
|
+
if (config.debug && target2.styles.warnings.length > 0) {
|
|
4923
5256
|
console.warn(
|
|
4924
|
-
`[spotpatch:runtime] CSS collection completed with ${String(
|
|
5257
|
+
`[spotpatch:runtime] CSS collection completed with ${String(target2.styles.warnings.length)} warning(s).`
|
|
4925
5258
|
);
|
|
4926
5259
|
}
|
|
4927
5260
|
}, 0);
|
|
4928
|
-
collectionTimers.set(
|
|
5261
|
+
collectionTimers.set(target2.id, timer);
|
|
4929
5262
|
}
|
|
4930
|
-
function duplicateTarget(
|
|
5263
|
+
function duplicateTarget(element2, marker) {
|
|
4931
5264
|
if (marker !== void 0) {
|
|
4932
5265
|
return targets.find(
|
|
4933
|
-
(
|
|
5266
|
+
(target2) => target2.marker?.fileId === marker.fileId && target2.marker.line === marker.line && target2.marker.column === marker.column
|
|
4934
5267
|
);
|
|
4935
5268
|
}
|
|
4936
|
-
return targets.find((
|
|
5269
|
+
return targets.find((target2) => target2.element === element2);
|
|
4937
5270
|
}
|
|
4938
|
-
function selectElement(
|
|
4939
|
-
const resolution = sourceResolver.resolve(
|
|
5271
|
+
function selectElement(element2) {
|
|
5272
|
+
const resolution = sourceResolver.resolve(element2);
|
|
4940
5273
|
const marker = sourceRefToMarker(resolution.source);
|
|
4941
|
-
const duplicate = duplicateTarget(
|
|
5274
|
+
const duplicate = duplicateTarget(element2, marker);
|
|
4942
5275
|
if (duplicate !== void 0) {
|
|
4943
5276
|
activeTargetId = duplicate.id;
|
|
4944
5277
|
addingTarget = false;
|
|
@@ -4962,13 +5295,15 @@ ${summary}`;
|
|
|
4962
5295
|
previousFocus = browser.document.activeElement instanceof HTMLElement ? browser.document.activeElement : void 0;
|
|
4963
5296
|
previewPrompt = "";
|
|
4964
5297
|
agentWorkflow.beginSelection();
|
|
5298
|
+
workflowSelectionActive = true;
|
|
4965
5299
|
}
|
|
4966
5300
|
targetSequence += 1;
|
|
4967
|
-
const
|
|
5301
|
+
const target2 = {
|
|
4968
5302
|
id: `target-${String(targetSequence)}`,
|
|
4969
|
-
element,
|
|
5303
|
+
element: element2,
|
|
4970
5304
|
resolution,
|
|
4971
5305
|
marker,
|
|
5306
|
+
page: collectPageContext(browser.document, browser.window),
|
|
4972
5307
|
code: void 0,
|
|
4973
5308
|
elementContext: void 0,
|
|
4974
5309
|
styles: void 0,
|
|
@@ -4976,18 +5311,19 @@ ${summary}`;
|
|
|
4976
5311
|
apiStatus: marker === void 0 ? "not-required" : "loading",
|
|
4977
5312
|
collectionStatus: "loading"
|
|
4978
5313
|
};
|
|
4979
|
-
targets.push(
|
|
4980
|
-
activeTargetId =
|
|
5314
|
+
targets.push(target2);
|
|
5315
|
+
activeTargetId = target2.id;
|
|
4981
5316
|
addingTarget = false;
|
|
4982
5317
|
const revision = sessionRevision;
|
|
4983
5318
|
transition({ type: "SELECT" });
|
|
4984
5319
|
view.hideHighlight();
|
|
4985
|
-
resizeObserver?.observe(
|
|
5320
|
+
resizeObserver?.observe(element2);
|
|
4986
5321
|
refreshSelectionView(true);
|
|
4987
|
-
|
|
4988
|
-
|
|
5322
|
+
selectionOpen = true;
|
|
5323
|
+
view.focusTargetInstruction(target2.id);
|
|
5324
|
+
scheduleBrowserContextCollection(target2, revision);
|
|
4989
5325
|
if (marker !== void 0) {
|
|
4990
|
-
void loadSourceContext(
|
|
5326
|
+
void loadSourceContext(target2, revision);
|
|
4991
5327
|
} else {
|
|
4992
5328
|
view.announce(
|
|
4993
5329
|
resolution.source.confidence === "probable" ? view.messages().announcements.sourceProbable : view.messages().announcements.sourceMissing
|
|
@@ -5061,7 +5397,7 @@ ${summary}`;
|
|
|
5061
5397
|
if (state.status !== "selected" && state.status !== "inspecting") {
|
|
5062
5398
|
return;
|
|
5063
5399
|
}
|
|
5064
|
-
const index = targets.findIndex((
|
|
5400
|
+
const index = targets.findIndex((target2) => target2.id === targetId);
|
|
5065
5401
|
if (index < 0) {
|
|
5066
5402
|
return;
|
|
5067
5403
|
}
|
|
@@ -5087,10 +5423,12 @@ ${summary}`;
|
|
|
5087
5423
|
}
|
|
5088
5424
|
view.hideSelectionTemporarily();
|
|
5089
5425
|
view.hideSelectionHighlights();
|
|
5426
|
+
selectionSession.clear();
|
|
5090
5427
|
view.announce(view.messages().announcements.allTargetsRemoved);
|
|
5091
5428
|
return;
|
|
5092
5429
|
}
|
|
5093
5430
|
refreshSelectionView();
|
|
5431
|
+
persistSelection();
|
|
5094
5432
|
view.announce(view.messages().announcements.targetRemoved);
|
|
5095
5433
|
}
|
|
5096
5434
|
function refreshSelectedGeometry() {
|
|
@@ -5098,24 +5436,24 @@ ${summary}`;
|
|
|
5098
5436
|
return;
|
|
5099
5437
|
}
|
|
5100
5438
|
const disconnected = targets.filter(
|
|
5101
|
-
(
|
|
5439
|
+
(target2) => target2.element !== void 0 && !target2.element.isConnected
|
|
5102
5440
|
);
|
|
5103
5441
|
if (disconnected.length > 0) {
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
}
|
|
5110
|
-
if (targets.length > 0) {
|
|
5111
|
-
view.announce(view.messages().announcements.detachedTargetRemoved);
|
|
5442
|
+
for (const target2 of disconnected) {
|
|
5443
|
+
if (target2.element !== void 0) {
|
|
5444
|
+
resizeObserver?.unobserve(target2.element);
|
|
5445
|
+
target2.element = void 0;
|
|
5446
|
+
}
|
|
5112
5447
|
}
|
|
5448
|
+
refreshSelectionView();
|
|
5449
|
+
persistSelection();
|
|
5450
|
+
view.announce(view.messages().announcements.detachedTargetPreserved);
|
|
5113
5451
|
return;
|
|
5114
5452
|
}
|
|
5115
5453
|
refreshHighlights();
|
|
5116
5454
|
}
|
|
5117
5455
|
function handleOpenEditor(targetId) {
|
|
5118
|
-
const current = targetId === void 0 ? activeTarget() : targets.find((
|
|
5456
|
+
const current = targetId === void 0 ? activeTarget() : targets.find((target2) => target2.id === targetId);
|
|
5119
5457
|
if (state.status !== "selected" || current?.marker === void 0) {
|
|
5120
5458
|
return;
|
|
5121
5459
|
}
|
|
@@ -5147,13 +5485,14 @@ ${summary}`;
|
|
|
5147
5485
|
return;
|
|
5148
5486
|
}
|
|
5149
5487
|
const targetId = event.target.dataset.targetInstructionId;
|
|
5150
|
-
const
|
|
5151
|
-
if (
|
|
5488
|
+
const target2 = targets.find((candidate) => candidate.id === targetId);
|
|
5489
|
+
if (target2 === void 0) {
|
|
5152
5490
|
return;
|
|
5153
5491
|
}
|
|
5154
|
-
|
|
5155
|
-
view.updateTargetInstruction(
|
|
5492
|
+
target2.instruction = event.target.value;
|
|
5493
|
+
view.updateTargetInstruction(target2.id, target2.instruction);
|
|
5156
5494
|
view.setPreviewEnabled(canPreview());
|
|
5495
|
+
persistSelection();
|
|
5157
5496
|
}
|
|
5158
5497
|
function handleOpenEditorButtonClick() {
|
|
5159
5498
|
handleOpenEditor();
|
|
@@ -5246,7 +5585,7 @@ ${summary}`;
|
|
|
5246
5585
|
"button[data-activate-target-id]"
|
|
5247
5586
|
);
|
|
5248
5587
|
const targetId = activateButton?.dataset.activateTargetId;
|
|
5249
|
-
if (state.status !== "selected" || targetId === void 0 || !targets.some((
|
|
5588
|
+
if (state.status !== "selected" || targetId === void 0 || !targets.some((target2) => target2.id === targetId)) {
|
|
5250
5589
|
return;
|
|
5251
5590
|
}
|
|
5252
5591
|
activeTargetId = targetId;
|
|
@@ -5304,6 +5643,12 @@ ${summary}`;
|
|
|
5304
5643
|
subtree: true
|
|
5305
5644
|
});
|
|
5306
5645
|
}
|
|
5646
|
+
if (selectionOpen && targets.length > 0) {
|
|
5647
|
+
transition({ type: "RESTORE" });
|
|
5648
|
+
agentWorkflow.beginSelection();
|
|
5649
|
+
workflowSelectionActive = true;
|
|
5650
|
+
refreshSelectionView(true);
|
|
5651
|
+
}
|
|
5307
5652
|
if (config.debug) {
|
|
5308
5653
|
console.info(`[spotpatch:runtime] Mounted. Shortcut: ${config.shortcut}.`);
|
|
5309
5654
|
}
|
|
@@ -5361,6 +5706,7 @@ ${summary}`;
|
|
|
5361
5706
|
animationFrame = void 0;
|
|
5362
5707
|
}
|
|
5363
5708
|
clearCollectionTimers();
|
|
5709
|
+
persistSelection();
|
|
5364
5710
|
resizeObserver?.disconnect();
|
|
5365
5711
|
mutationObserver?.disconnect();
|
|
5366
5712
|
resizeObserver = void 0;
|
|
@@ -5383,10 +5729,10 @@ ${summary}`;
|
|
|
5383
5729
|
// src/controller/bootstrap.ts
|
|
5384
5730
|
var RUNTIME_INSTANCE_KEY = "__spotpatchRuntime__";
|
|
5385
5731
|
function bootstrapSpotPatch(config) {
|
|
5386
|
-
const
|
|
5387
|
-
|
|
5732
|
+
const target2 = globalThis;
|
|
5733
|
+
target2[RUNTIME_INSTANCE_KEY]?.dispose();
|
|
5388
5734
|
const controller = createController(config);
|
|
5389
|
-
|
|
5735
|
+
target2[RUNTIME_INSTANCE_KEY] = controller;
|
|
5390
5736
|
controller.mount();
|
|
5391
5737
|
}
|
|
5392
5738
|
export {
|