@spotpatch/runtime 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +187 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +190 -28
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -259,6 +259,9 @@ function readSuccessData(value) {
|
|
|
259
259
|
function isCodeContext(value) {
|
|
260
260
|
return isRecord2(value) && typeof value.relativePath === "string" && (value.language === "tsx" || value.language === "jsx") && typeof value.startLine === "number" && typeof value.endLine === "number" && typeof value.excerpt === "string" && (value.boundary === "component" || value.boundary === "nearby-lines");
|
|
261
261
|
}
|
|
262
|
+
function isEditorOpenResult(value) {
|
|
263
|
+
return isRecord2(value) && typeof value.editor === "string" && import_shared3.SPOTPATCH_EDITOR_PREFERENCES.includes(value.editor);
|
|
264
|
+
}
|
|
262
265
|
function deepFreezeUnknown(value) {
|
|
263
266
|
if (!isRecord2(value) && !Array.isArray(value)) {
|
|
264
267
|
return;
|
|
@@ -485,7 +488,11 @@ function createRuntimeApi(options) {
|
|
|
485
488
|
return Object.freeze({ ...data });
|
|
486
489
|
},
|
|
487
490
|
async openEditor(request) {
|
|
488
|
-
await requestJson(import_shared3.SPOTPATCH_ENDPOINTS.openEditor, "POST", request);
|
|
491
|
+
const data = await requestJson(import_shared3.SPOTPATCH_ENDPOINTS.openEditor, "POST", request);
|
|
492
|
+
if (!isEditorOpenResult(data)) {
|
|
493
|
+
throw new RuntimeApiError();
|
|
494
|
+
}
|
|
495
|
+
return Object.freeze({ editor: data.editor });
|
|
489
496
|
},
|
|
490
497
|
async agentCapability(request) {
|
|
491
498
|
return parseCapability(
|
|
@@ -2135,6 +2142,15 @@ var STATUS_ZH = Object.freeze({
|
|
|
2135
2142
|
reverted: "\u5DF2\u64A4\u9500",
|
|
2136
2143
|
failed: "\u5931\u8D25"
|
|
2137
2144
|
});
|
|
2145
|
+
function editorName(editor, automatic) {
|
|
2146
|
+
if (editor === "vscode") {
|
|
2147
|
+
return "VS Code";
|
|
2148
|
+
}
|
|
2149
|
+
if (editor === "cursor") {
|
|
2150
|
+
return "Cursor";
|
|
2151
|
+
}
|
|
2152
|
+
return automatic;
|
|
2153
|
+
}
|
|
2138
2154
|
var ERROR_MESSAGES_EN = Object.freeze({
|
|
2139
2155
|
[import_shared6.ERROR_CODES.INVALID_REQUEST]: "The Agent request was rejected as invalid.",
|
|
2140
2156
|
[import_shared6.ERROR_CODES.INVALID_TOKEN]: "The local SpotPatch session expired.",
|
|
@@ -2270,7 +2286,12 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2270
2286
|
localeName: "EN",
|
|
2271
2287
|
alternateLocaleName: "\u4E2D",
|
|
2272
2288
|
switchLocale: "Switch interface language to Chinese",
|
|
2273
|
-
brand: Object.freeze({
|
|
2289
|
+
brand: Object.freeze({
|
|
2290
|
+
name: "SpotPatch",
|
|
2291
|
+
context: "Live context",
|
|
2292
|
+
repository: "GitHub",
|
|
2293
|
+
repositoryTitle: "Star SpotPatch on GitHub"
|
|
2294
|
+
}),
|
|
2274
2295
|
trigger: Object.freeze({
|
|
2275
2296
|
select: "Select element",
|
|
2276
2297
|
stop: "Stop selecting",
|
|
@@ -2322,7 +2343,8 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2322
2343
|
actions: Object.freeze({
|
|
2323
2344
|
addElement: "Add element",
|
|
2324
2345
|
reselect: "Start over",
|
|
2325
|
-
openEditor: "Open in
|
|
2346
|
+
openEditor: (editor) => editor === "auto" ? "Open source" : `Open in ${editorName(editor, "editor")}`,
|
|
2347
|
+
openTarget: (index, editor) => `Open target ${String(index)} in ${editorName(editor, "the detected editor")}`,
|
|
2326
2348
|
preview: "Preview prompt",
|
|
2327
2349
|
copy: "Copy prompt",
|
|
2328
2350
|
back: "Back to edit"
|
|
@@ -2378,8 +2400,9 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2378
2400
|
detachedTargetRemoved: "A removed page element was dropped from the selection.",
|
|
2379
2401
|
contextWarning: "Browser context collection completed with a warning.",
|
|
2380
2402
|
contextCollected: "Browser context collected.",
|
|
2381
|
-
|
|
2382
|
-
|
|
2403
|
+
editorOpening: (editor) => `Opening ${editorName(editor, "the detected editor")}\u2026`,
|
|
2404
|
+
editorOpened: (editor) => `Opened the source in ${editorName(editor, "the detected editor")}.`,
|
|
2405
|
+
editorFailed: (editor) => `Could not open ${editorName(editor, "an editor")}. Start the editor or configure editor: "cursor" / "vscode".`,
|
|
2383
2406
|
completeInstructions: "Add an instruction for every target and wait for context collection to finish.",
|
|
2384
2407
|
promptCopied: "Prompt copied to the clipboard.",
|
|
2385
2408
|
clipboardUnavailable: "Clipboard access is unavailable. Select the prompt manually.",
|
|
@@ -2392,7 +2415,12 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2392
2415
|
localeName: "\u4E2D",
|
|
2393
2416
|
alternateLocaleName: "EN",
|
|
2394
2417
|
switchLocale: "\u5C06\u754C\u9762\u8BED\u8A00\u5207\u6362\u4E3A\u82F1\u6587",
|
|
2395
|
-
brand: Object.freeze({
|
|
2418
|
+
brand: Object.freeze({
|
|
2419
|
+
name: "SpotPatch",
|
|
2420
|
+
context: "\u5B9E\u65F6\u4E0A\u4E0B\u6587",
|
|
2421
|
+
repository: "GitHub",
|
|
2422
|
+
repositoryTitle: "\u5728 GitHub \u4E0A Star SpotPatch"
|
|
2423
|
+
}),
|
|
2396
2424
|
trigger: Object.freeze({
|
|
2397
2425
|
select: "\u9009\u62E9\u5143\u7D20",
|
|
2398
2426
|
stop: "\u505C\u6B62\u9009\u62E9",
|
|
@@ -2444,7 +2472,8 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2444
2472
|
actions: Object.freeze({
|
|
2445
2473
|
addElement: "\u6DFB\u52A0\u5143\u7D20",
|
|
2446
2474
|
reselect: "\u91CD\u65B0\u5F00\u59CB",
|
|
2447
|
-
openEditor: "\u5728
|
|
2475
|
+
openEditor: (editor) => editor === "auto" ? "\u6253\u5F00\u6E90\u7801" : `\u5728 ${editorName(editor, "\u7F16\u8F91\u5668")} \u4E2D\u6253\u5F00`,
|
|
2476
|
+
openTarget: (index, editor) => `\u5728${editorName(editor, "\u81EA\u52A8\u68C0\u6D4B\u7684\u7F16\u8F91\u5668")}\u4E2D\u6253\u5F00\u76EE\u6807 ${String(index)} \u7684\u6E90\u7801`,
|
|
2448
2477
|
preview: "\u9884\u89C8 Prompt",
|
|
2449
2478
|
copy: "\u590D\u5236 Prompt",
|
|
2450
2479
|
back: "\u8FD4\u56DE\u7F16\u8F91"
|
|
@@ -2500,8 +2529,9 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2500
2529
|
detachedTargetRemoved: "\u9875\u9762\u4E2D\u7684\u76EE\u6807\u5DF2\u5378\u8F7D\uFF0C\u5DF2\u4ECE\u5F53\u524D\u9009\u62E9\u4E2D\u79FB\u9664\u3002",
|
|
2501
2530
|
contextWarning: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\uFF0C\u4F46\u5B58\u5728\u8B66\u544A\u3002",
|
|
2502
2531
|
contextCollected: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\u3002",
|
|
2503
|
-
|
|
2504
|
-
|
|
2532
|
+
editorOpening: (editor) => `\u6B63\u5728\u6253\u5F00${editorName(editor, "\u81EA\u52A8\u68C0\u6D4B\u7684\u7F16\u8F91\u5668")}\u2026\u2026`,
|
|
2533
|
+
editorOpened: (editor) => `\u5DF2\u5728${editorName(editor, "\u81EA\u52A8\u68C0\u6D4B\u7684\u7F16\u8F91\u5668")}\u4E2D\u6253\u5F00\u6E90\u7801\u3002`,
|
|
2534
|
+
editorFailed: (editor) => `\u65E0\u6CD5\u6253\u5F00${editorName(editor, "\u7F16\u8F91\u5668")}\u3002\u8BF7\u5148\u542F\u52A8\u7F16\u8F91\u5668\uFF0C\u6216\u914D\u7F6E editor: "cursor" / "vscode"\u3002`,
|
|
2505
2535
|
completeInstructions: "\u8BF7\u4E3A\u6BCF\u4E2A\u76EE\u6807\u586B\u5199\u4FEE\u6539\u8BF4\u660E\uFF0C\u5E76\u7B49\u5F85\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\u3002",
|
|
2506
2536
|
promptCopied: "Prompt \u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F\u3002",
|
|
2507
2537
|
clipboardUnavailable: "\u65E0\u6CD5\u8BBF\u95EE\u526A\u8D34\u677F\uFF0C\u8BF7\u624B\u52A8\u9009\u62E9\u5E76\u590D\u5236 Prompt\u3002",
|
|
@@ -2796,6 +2826,28 @@ function createStyles(document) {
|
|
|
2796
2826
|
gap: 8px;
|
|
2797
2827
|
flex: none;
|
|
2798
2828
|
}
|
|
2829
|
+
.spotpatch-repository {
|
|
2830
|
+
display: inline-flex;
|
|
2831
|
+
height: 30px;
|
|
2832
|
+
align-items: center;
|
|
2833
|
+
gap: 5px;
|
|
2834
|
+
border: 1px solid rgb(68 202 224 / 20%);
|
|
2835
|
+
border-radius: 9px;
|
|
2836
|
+
padding: 0 10px;
|
|
2837
|
+
color: #bcecf2;
|
|
2838
|
+
background: rgb(8 145 178 / 7%);
|
|
2839
|
+
font-size: 11px;
|
|
2840
|
+
font-weight: 680;
|
|
2841
|
+
text-decoration: none;
|
|
2842
|
+
transition: border-color 150ms ease, color 150ms ease, background 150ms ease, transform 150ms ease;
|
|
2843
|
+
}
|
|
2844
|
+
.spotpatch-repository::after { content: "\u2197"; font-size: 10px; }
|
|
2845
|
+
.spotpatch-repository:hover {
|
|
2846
|
+
border-color: rgb(68 202 224 / 42%);
|
|
2847
|
+
color: #e6fbff;
|
|
2848
|
+
background: rgb(8 145 178 / 12%);
|
|
2849
|
+
transform: translateY(-1px);
|
|
2850
|
+
}
|
|
2799
2851
|
.spotpatch-locale {
|
|
2800
2852
|
min-width: 38px;
|
|
2801
2853
|
height: 30px;
|
|
@@ -2939,7 +2991,7 @@ function createStyles(document) {
|
|
|
2939
2991
|
}
|
|
2940
2992
|
.spotpatch-target-summary {
|
|
2941
2993
|
display: grid;
|
|
2942
|
-
grid-template-columns: minmax(0, 1fr) 34px;
|
|
2994
|
+
grid-template-columns: minmax(0, 1fr) 34px 34px;
|
|
2943
2995
|
align-items: stretch;
|
|
2944
2996
|
gap: 4px;
|
|
2945
2997
|
padding: 5px;
|
|
@@ -2990,6 +3042,7 @@ function createStyles(document) {
|
|
|
2990
3042
|
white-space: nowrap;
|
|
2991
3043
|
}
|
|
2992
3044
|
.spotpatch-target-state[data-complete="false"] { color: #f5c97a; background: rgb(245 158 11 / 9%); }
|
|
3045
|
+
.spotpatch-target-open,
|
|
2993
3046
|
.spotpatch-target-remove {
|
|
2994
3047
|
display: inline-grid;
|
|
2995
3048
|
width: 34px;
|
|
@@ -3003,6 +3056,8 @@ function createStyles(document) {
|
|
|
3003
3056
|
background: transparent;
|
|
3004
3057
|
cursor: pointer;
|
|
3005
3058
|
}
|
|
3059
|
+
.spotpatch-target-open { color: #79d9e7; }
|
|
3060
|
+
.spotpatch-target-open:hover:not(:disabled) { border-color: rgb(68 202 224 / 30%); color: #c8f7ff; background: rgb(8 145 178 / 11%); }
|
|
3006
3061
|
.spotpatch-target-remove:hover:not(:disabled) { border-color: rgb(251 113 133 / 24%); color: #fda4af; background: rgb(127 29 29 / 12%); }
|
|
3007
3062
|
.spotpatch-target-editor {
|
|
3008
3063
|
border-top: 1px solid rgb(255 255 255 / 7%);
|
|
@@ -3112,6 +3167,30 @@ function createStyles(document) {
|
|
|
3112
3167
|
border-top: 1px solid rgb(255 255 255 / 8%);
|
|
3113
3168
|
background: rgb(8 12 22 / 82%);
|
|
3114
3169
|
}
|
|
3170
|
+
.spotpatch-editor-feedback {
|
|
3171
|
+
display: flex;
|
|
3172
|
+
width: 100%;
|
|
3173
|
+
align-items: center;
|
|
3174
|
+
gap: 7px;
|
|
3175
|
+
margin-bottom: 1px;
|
|
3176
|
+
color: #9ca5b5;
|
|
3177
|
+
font-size: 11px;
|
|
3178
|
+
line-height: 1.45;
|
|
3179
|
+
}
|
|
3180
|
+
.spotpatch-editor-feedback[hidden] { display: none; }
|
|
3181
|
+
.spotpatch-editor-feedback::before {
|
|
3182
|
+
width: 6px;
|
|
3183
|
+
height: 6px;
|
|
3184
|
+
flex: none;
|
|
3185
|
+
border-radius: 999px;
|
|
3186
|
+
background: #94a3b8;
|
|
3187
|
+
content: "";
|
|
3188
|
+
}
|
|
3189
|
+
.spotpatch-editor-feedback[data-state="opening"]::before { background: #38bdf8; }
|
|
3190
|
+
.spotpatch-editor-feedback[data-state="success"] { color: #9fe3c4; }
|
|
3191
|
+
.spotpatch-editor-feedback[data-state="success"]::before { background: #34d399; }
|
|
3192
|
+
.spotpatch-editor-feedback[data-state="error"] { color: #fecaca; }
|
|
3193
|
+
.spotpatch-editor-feedback[data-state="error"]::before { background: #fb7185; }
|
|
3115
3194
|
.spotpatch-actions button {
|
|
3116
3195
|
display: inline-flex;
|
|
3117
3196
|
min-height: 40px;
|
|
@@ -3143,6 +3222,8 @@ function createStyles(document) {
|
|
|
3143
3222
|
.spotpatch-actions .spotpatch-primary::after { margin-left: 8px; content: "\u2197"; font-size: 12px; }
|
|
3144
3223
|
.spotpatch-actions button:disabled { cursor: not-allowed; opacity: .4; transform: none; }
|
|
3145
3224
|
.spotpatch-actions button:focus-visible,
|
|
3225
|
+
.spotpatch-repository:focus-visible,
|
|
3226
|
+
.spotpatch-target-open:focus-visible,
|
|
3146
3227
|
.spotpatch-target-remove:focus-visible,
|
|
3147
3228
|
.spotpatch-close:focus-visible,
|
|
3148
3229
|
.spotpatch-trigger:focus-visible,
|
|
@@ -3175,6 +3256,8 @@ function createStyles(document) {
|
|
|
3175
3256
|
.spotpatch-actions { padding-left: 16px; padding-right: 16px; }
|
|
3176
3257
|
.spotpatch-target-select { grid-template-columns: 32px minmax(0, 1fr); }
|
|
3177
3258
|
.spotpatch-target-state { display: none; }
|
|
3259
|
+
.spotpatch-repository { width: 30px; overflow: hidden; padding: 0; justify-content: center; color: transparent; }
|
|
3260
|
+
.spotpatch-repository::after { color: #bcecf2; content: "\u2197"; }
|
|
3178
3261
|
}
|
|
3179
3262
|
${AGENT_PANEL_STYLES}
|
|
3180
3263
|
`;
|
|
@@ -3184,7 +3267,7 @@ function summaryLine(summary, prefix) {
|
|
|
3184
3267
|
const line = summary.split("\n").find((candidate) => candidate.startsWith(`${prefix}: `));
|
|
3185
3268
|
return line?.slice(prefix.length + 2).trim();
|
|
3186
3269
|
}
|
|
3187
|
-
function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: false }), localePreference = "auto") {
|
|
3270
|
+
function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: false }), localePreference = "auto", editorPreference = "auto") {
|
|
3188
3271
|
const localizer = createUiLocalizer(document, localePreference);
|
|
3189
3272
|
let messages = localizer.messages();
|
|
3190
3273
|
const host = document.createElement("spotpatch-root");
|
|
@@ -3234,9 +3317,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3234
3317
|
brand.append(createBrandMark(document), brandCopy);
|
|
3235
3318
|
const headerControls = createMarkedElement(document, "span");
|
|
3236
3319
|
headerControls.className = "spotpatch-header-controls";
|
|
3320
|
+
const repositoryLink = createMarkedElement(document, "a");
|
|
3321
|
+
repositoryLink.className = "spotpatch-repository";
|
|
3322
|
+
repositoryLink.href = import_shared7.SPOTPATCH_REPOSITORY_URL;
|
|
3323
|
+
repositoryLink.target = "_blank";
|
|
3324
|
+
repositoryLink.rel = "noopener noreferrer";
|
|
3237
3325
|
const localeButton = createButton(document, "", "spotpatch-locale");
|
|
3238
3326
|
const closeButton = createButton(document, "\xD7", "spotpatch-close");
|
|
3239
|
-
headerControls.append(localeButton, closeButton);
|
|
3327
|
+
headerControls.append(repositoryLink, localeButton, closeButton);
|
|
3240
3328
|
brandRow.append(brand, headerControls);
|
|
3241
3329
|
const title = createMarkedElement(document, "h2");
|
|
3242
3330
|
title.id = "spotpatch-selection-title";
|
|
@@ -3300,9 +3388,18 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3300
3388
|
body.append(selectionPanel, previewPanel);
|
|
3301
3389
|
const actions = createMarkedElement(document, "footer");
|
|
3302
3390
|
actions.className = "spotpatch-actions";
|
|
3391
|
+
const editorFeedback = createMarkedElement(document, "div");
|
|
3392
|
+
editorFeedback.className = "spotpatch-editor-feedback";
|
|
3393
|
+
editorFeedback.dataset.state = "idle";
|
|
3394
|
+
editorFeedback.setAttribute("role", "status");
|
|
3395
|
+
editorFeedback.setAttribute("aria-live", "polite");
|
|
3396
|
+
editorFeedback.hidden = true;
|
|
3303
3397
|
const addTargetButton = createButton(document, messages.actions.addElement);
|
|
3304
3398
|
const reselectButton = createButton(document, messages.actions.reselect);
|
|
3305
|
-
const openEditorButton = createButton(
|
|
3399
|
+
const openEditorButton = createButton(
|
|
3400
|
+
document,
|
|
3401
|
+
messages.actions.openEditor(editorPreference)
|
|
3402
|
+
);
|
|
3306
3403
|
const previewButton = createButton(
|
|
3307
3404
|
document,
|
|
3308
3405
|
messages.actions.preview,
|
|
@@ -3311,6 +3408,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3311
3408
|
const copyButton = createButton(document, messages.actions.copy, "spotpatch-primary");
|
|
3312
3409
|
const backButton = createButton(document, messages.actions.back);
|
|
3313
3410
|
actions.append(
|
|
3411
|
+
editorFeedback,
|
|
3314
3412
|
agentPanel.runButton,
|
|
3315
3413
|
previewButton,
|
|
3316
3414
|
agentPanel.testButton,
|
|
@@ -3348,6 +3446,23 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3348
3446
|
let editingEnabled = true;
|
|
3349
3447
|
let currentTargets = [];
|
|
3350
3448
|
let currentMaximum = 0;
|
|
3449
|
+
let currentEditorFeedbackState = "idle";
|
|
3450
|
+
function defaultEditorFeedback(state) {
|
|
3451
|
+
if (state === "opening") {
|
|
3452
|
+
return messages.announcements.editorOpening(editorPreference);
|
|
3453
|
+
}
|
|
3454
|
+
if (state === "success") {
|
|
3455
|
+
return messages.announcements.editorOpened(editorPreference);
|
|
3456
|
+
}
|
|
3457
|
+
return state === "error" ? messages.announcements.editorFailed(editorPreference) : "";
|
|
3458
|
+
}
|
|
3459
|
+
function renderEditorStatus(state, message = defaultEditorFeedback(state)) {
|
|
3460
|
+
currentEditorFeedbackState = state;
|
|
3461
|
+
editorFeedback.dataset.state = state;
|
|
3462
|
+
editorFeedback.hidden = state === "idle";
|
|
3463
|
+
editorFeedback.textContent = message;
|
|
3464
|
+
placeDialog();
|
|
3465
|
+
}
|
|
3351
3466
|
function statusText(target) {
|
|
3352
3467
|
if (target.status === "ready") {
|
|
3353
3468
|
return messages.targets.statusReady;
|
|
@@ -3426,12 +3541,20 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3426
3541
|
state.dataset.complete = String(instructionComplete);
|
|
3427
3542
|
state.textContent = instructionComplete ? messages.targets.instructionReady : messages.targets.instructionMissing;
|
|
3428
3543
|
select.append(number, copy, state);
|
|
3544
|
+
const open = createButton(document, "\u2197", "spotpatch-target-open");
|
|
3545
|
+
open.dataset.openTargetId = target.id;
|
|
3546
|
+
open.disabled = !target.canOpenEditor;
|
|
3547
|
+
open.setAttribute(
|
|
3548
|
+
"aria-label",
|
|
3549
|
+
messages.actions.openTarget(index + 1, editorPreference)
|
|
3550
|
+
);
|
|
3551
|
+
open.title = messages.actions.openTarget(index + 1, editorPreference);
|
|
3429
3552
|
const remove = createButton(document, "\xD7", "spotpatch-target-remove");
|
|
3430
3553
|
remove.dataset.removeTargetId = target.id;
|
|
3431
3554
|
remove.disabled = !editingEnabled;
|
|
3432
3555
|
remove.setAttribute("aria-label", messages.targets.remove(index + 1));
|
|
3433
3556
|
remove.title = messages.targets.removeTitle;
|
|
3434
|
-
targetSummary.append(select, remove);
|
|
3557
|
+
targetSummary.append(select, open, remove);
|
|
3435
3558
|
item.append(targetSummary);
|
|
3436
3559
|
if (target.active) {
|
|
3437
3560
|
const editor = createMarkedElement(document, "label");
|
|
@@ -3609,6 +3732,9 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3609
3732
|
messages = localizer.messages();
|
|
3610
3733
|
brandName.textContent = messages.brand.name;
|
|
3611
3734
|
brandContext.textContent = messages.brand.context;
|
|
3735
|
+
repositoryLink.textContent = messages.brand.repository;
|
|
3736
|
+
repositoryLink.title = messages.brand.repositoryTitle;
|
|
3737
|
+
repositoryLink.setAttribute("aria-label", messages.brand.repositoryTitle);
|
|
3612
3738
|
localeButton.textContent = messages.alternateLocaleName;
|
|
3613
3739
|
localeButton.title = messages.switchLocale;
|
|
3614
3740
|
localeButton.setAttribute("aria-label", messages.switchLocale);
|
|
@@ -3620,13 +3746,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3620
3746
|
promptOutput.setAttribute("aria-label", messages.diagnostics.promptAriaLabel);
|
|
3621
3747
|
addTargetButton.textContent = messages.actions.addElement;
|
|
3622
3748
|
reselectButton.textContent = messages.actions.reselect;
|
|
3623
|
-
openEditorButton.textContent = messages.actions.openEditor;
|
|
3749
|
+
openEditorButton.textContent = messages.actions.openEditor(editorPreference);
|
|
3624
3750
|
previewButton.textContent = messages.actions.preview;
|
|
3625
3751
|
copyButton.textContent = messages.actions.copy;
|
|
3626
3752
|
backButton.textContent = messages.actions.back;
|
|
3627
3753
|
triggerButton.title = messages.trigger.title(shortcut);
|
|
3628
3754
|
triggerButton.textContent = currentStatus === "inspecting" ? messages.trigger.stop : messages.trigger.select;
|
|
3629
3755
|
renderPanelStatus(currentStatus);
|
|
3756
|
+
renderEditorStatus(currentEditorFeedbackState);
|
|
3630
3757
|
if (currentTargets.length > 0) {
|
|
3631
3758
|
renderTargets(currentTargets, currentMaximum);
|
|
3632
3759
|
} else {
|
|
@@ -3657,6 +3784,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3657
3784
|
targetList,
|
|
3658
3785
|
reselectButton,
|
|
3659
3786
|
openEditorButton,
|
|
3787
|
+
repositoryLink,
|
|
3660
3788
|
previewButton,
|
|
3661
3789
|
copyButton,
|
|
3662
3790
|
backButton,
|
|
@@ -3676,6 +3804,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3676
3804
|
triggerButton.textContent = inspecting ? messages.trigger.stop : messages.trigger.select;
|
|
3677
3805
|
renderPanelStatus(status);
|
|
3678
3806
|
},
|
|
3807
|
+
renderEditorStatus,
|
|
3679
3808
|
showHighlight(rect, label) {
|
|
3680
3809
|
currentRect = rect;
|
|
3681
3810
|
highlight.hidden = false;
|
|
@@ -3719,6 +3848,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3719
3848
|
currentTargets = [];
|
|
3720
3849
|
currentMaximum = 0;
|
|
3721
3850
|
currentSummaryText = "";
|
|
3851
|
+
renderEditorStatus("idle");
|
|
3722
3852
|
targetCount.textContent = messages.targets.count(0, 0);
|
|
3723
3853
|
targetComplete.textContent = messages.targets.complete(0, 0);
|
|
3724
3854
|
targetLabel.textContent = messages.context.selectedElement;
|
|
@@ -3762,7 +3892,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3762
3892
|
).forEach((control) => {
|
|
3763
3893
|
control.disabled = !enabled;
|
|
3764
3894
|
});
|
|
3765
|
-
openEditorButton.disabled = !
|
|
3895
|
+
openEditorButton.disabled = !currentCanOpenEditor;
|
|
3766
3896
|
previewButton.disabled = !enabled || !currentCanPreview;
|
|
3767
3897
|
agentPanel.setEditingEnabled(enabled);
|
|
3768
3898
|
placeDialog();
|
|
@@ -4250,7 +4380,13 @@ function resolveBrowserDependencies(dependencies) {
|
|
|
4250
4380
|
}
|
|
4251
4381
|
function createController(config, dependencies = {}) {
|
|
4252
4382
|
const browser = resolveBrowserDependencies(dependencies);
|
|
4253
|
-
const view = dependencies.view ?? createRuntimeView(
|
|
4383
|
+
const view = dependencies.view ?? createRuntimeView(
|
|
4384
|
+
browser.document,
|
|
4385
|
+
config.shortcut,
|
|
4386
|
+
config.ai,
|
|
4387
|
+
config.locale,
|
|
4388
|
+
config.editor
|
|
4389
|
+
);
|
|
4254
4390
|
const api = dependencies.api ?? createRuntimeApi({
|
|
4255
4391
|
apiBase: config.apiBase,
|
|
4256
4392
|
fetch: browser.window.fetch.bind(browser.window),
|
|
@@ -4281,6 +4417,7 @@ function createController(config, dependencies = {}) {
|
|
|
4281
4417
|
let activeTargetId;
|
|
4282
4418
|
let targetSequence = 0;
|
|
4283
4419
|
let sessionRevision = 0;
|
|
4420
|
+
let editorRequestRevision = 0;
|
|
4284
4421
|
let addingTarget = false;
|
|
4285
4422
|
let previewPrompt = "";
|
|
4286
4423
|
let previousFocus;
|
|
@@ -4355,6 +4492,7 @@ ${summary}`;
|
|
|
4355
4492
|
id: target.id,
|
|
4356
4493
|
label: target.resolution.react.componentName ?? (target.element === void 0 ? target.elementContext?.tagName ?? "Element" : elementLabel(target.element)),
|
|
4357
4494
|
source: sourceLabel(target, view.messages().context.sourceUnavailable),
|
|
4495
|
+
canOpenEditor: target.marker !== void 0,
|
|
4358
4496
|
status: targetStatus(target),
|
|
4359
4497
|
active: target.id === activeTargetId,
|
|
4360
4498
|
instruction: target.instruction
|
|
@@ -4498,7 +4636,6 @@ ${summary}`;
|
|
|
4498
4636
|
resizeObserver?.disconnect();
|
|
4499
4637
|
for (const target of targets) {
|
|
4500
4638
|
target.element = void 0;
|
|
4501
|
-
target.marker = void 0;
|
|
4502
4639
|
}
|
|
4503
4640
|
view.hideHighlight();
|
|
4504
4641
|
view.hideSelectionHighlights();
|
|
@@ -4775,24 +4912,37 @@ ${summary}`;
|
|
|
4775
4912
|
}
|
|
4776
4913
|
refreshHighlights();
|
|
4777
4914
|
}
|
|
4778
|
-
function handleOpenEditor() {
|
|
4779
|
-
const current = activeTarget();
|
|
4915
|
+
function handleOpenEditor(targetId) {
|
|
4916
|
+
const current = targetId === void 0 ? activeTarget() : targets.find((target) => target.id === targetId);
|
|
4780
4917
|
if (state.status !== "selected" || current?.marker === void 0) {
|
|
4781
4918
|
return;
|
|
4782
4919
|
}
|
|
4920
|
+
if (activeTargetId !== current.id) {
|
|
4921
|
+
activeTargetId = current.id;
|
|
4922
|
+
refreshSelectionView();
|
|
4923
|
+
}
|
|
4783
4924
|
const marker = current.marker;
|
|
4925
|
+
const selectionRevision = sessionRevision;
|
|
4926
|
+
const requestRevision = ++editorRequestRevision;
|
|
4784
4927
|
transition({ type: "OPEN_EDITOR" });
|
|
4928
|
+
const openingMessage = view.messages().announcements.editorOpening(config.editor);
|
|
4929
|
+
view.renderEditorStatus("opening", openingMessage);
|
|
4930
|
+
view.announce(openingMessage);
|
|
4785
4931
|
void api.openEditor({
|
|
4786
4932
|
fileId: marker.fileId,
|
|
4787
4933
|
line: marker.line,
|
|
4788
4934
|
column: marker.column
|
|
4789
|
-
}).then(() => {
|
|
4790
|
-
if (mounted && state.status === "selected") {
|
|
4791
|
-
view.
|
|
4935
|
+
}).then((result) => {
|
|
4936
|
+
if (mounted && state.status === "selected" && selectionRevision === sessionRevision && requestRevision === editorRequestRevision && activeTargetId === current.id && targets.includes(current)) {
|
|
4937
|
+
const message = view.messages().announcements.editorOpened(result.editor);
|
|
4938
|
+
view.renderEditorStatus("success", message);
|
|
4939
|
+
view.announce(message);
|
|
4792
4940
|
}
|
|
4793
4941
|
}).catch(() => {
|
|
4794
|
-
if (mounted && state.status === "selected") {
|
|
4795
|
-
view.
|
|
4942
|
+
if (mounted && state.status === "selected" && selectionRevision === sessionRevision && requestRevision === editorRequestRevision && activeTargetId === current.id && targets.includes(current)) {
|
|
4943
|
+
const message = view.messages().announcements.editorFailed(config.editor);
|
|
4944
|
+
view.renderEditorStatus("error", message);
|
|
4945
|
+
view.announce(message);
|
|
4796
4946
|
}
|
|
4797
4947
|
});
|
|
4798
4948
|
}
|
|
@@ -4809,6 +4959,9 @@ ${summary}`;
|
|
|
4809
4959
|
view.updateTargetInstruction(target.id, target.instruction);
|
|
4810
4960
|
view.setPreviewEnabled(canPreview());
|
|
4811
4961
|
}
|
|
4962
|
+
function handleOpenEditorButtonClick() {
|
|
4963
|
+
handleOpenEditor();
|
|
4964
|
+
}
|
|
4812
4965
|
function handleTargetListKeydown(event) {
|
|
4813
4966
|
if (config.ai.enabled && state.status === "selected" && event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
|
|
4814
4967
|
event.preventDefault();
|
|
@@ -4886,6 +5039,13 @@ ${summary}`;
|
|
|
4886
5039
|
removeTarget(removeButton.dataset.removeTargetId);
|
|
4887
5040
|
return;
|
|
4888
5041
|
}
|
|
5042
|
+
const openButton = eventTarget.closest(
|
|
5043
|
+
"button[data-open-target-id]"
|
|
5044
|
+
);
|
|
5045
|
+
if (openButton?.dataset.openTargetId !== void 0) {
|
|
5046
|
+
handleOpenEditor(openButton.dataset.openTargetId);
|
|
5047
|
+
return;
|
|
5048
|
+
}
|
|
4889
5049
|
const activateButton = eventTarget.closest(
|
|
4890
5050
|
"button[data-activate-target-id]"
|
|
4891
5051
|
);
|
|
@@ -4917,7 +5077,7 @@ ${summary}`;
|
|
|
4917
5077
|
view.targetList.addEventListener("click", handleTargetListClick);
|
|
4918
5078
|
view.targetList.addEventListener("input", handleTargetListInput);
|
|
4919
5079
|
view.targetList.addEventListener("keydown", handleTargetListKeydown);
|
|
4920
|
-
view.openEditorButton.addEventListener("click",
|
|
5080
|
+
view.openEditorButton.addEventListener("click", handleOpenEditorButtonClick);
|
|
4921
5081
|
view.previewButton.addEventListener("click", handlePreview);
|
|
4922
5082
|
view.copyButton.addEventListener("click", handleCopy);
|
|
4923
5083
|
view.backButton.addEventListener("click", handleBack);
|
|
@@ -4977,7 +5137,7 @@ ${summary}`;
|
|
|
4977
5137
|
view.targetList.removeEventListener("click", handleTargetListClick);
|
|
4978
5138
|
view.targetList.removeEventListener("input", handleTargetListInput);
|
|
4979
5139
|
view.targetList.removeEventListener("keydown", handleTargetListKeydown);
|
|
4980
|
-
view.openEditorButton.removeEventListener("click",
|
|
5140
|
+
view.openEditorButton.removeEventListener("click", handleOpenEditorButtonClick);
|
|
4981
5141
|
view.previewButton.removeEventListener("click", handlePreview);
|
|
4982
5142
|
view.copyButton.removeEventListener("click", handleCopy);
|
|
4983
5143
|
view.backButton.removeEventListener("click", handleBack);
|