@spotpatch/runtime 1.0.0 → 1.1.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/dist/index.cjs CHANGED
@@ -485,7 +485,11 @@ function createRuntimeApi(options) {
485
485
  return Object.freeze({ ...data });
486
486
  },
487
487
  async openEditor(request) {
488
- await requestJson(import_shared3.SPOTPATCH_ENDPOINTS.openEditor, "POST", request);
488
+ const data = await requestJson(import_shared3.SPOTPATCH_ENDPOINTS.openEditor, "POST", request);
489
+ if (!isRecord2(data) || data.editor !== "auto" && data.editor !== "vscode" && data.editor !== "cursor") {
490
+ throw new RuntimeApiError();
491
+ }
492
+ return Object.freeze({ editor: data.editor });
489
493
  },
490
494
  async agentCapability(request) {
491
495
  return parseCapability(
@@ -2270,7 +2274,12 @@ var UI_MESSAGES = Object.freeze({
2270
2274
  localeName: "EN",
2271
2275
  alternateLocaleName: "\u4E2D",
2272
2276
  switchLocale: "Switch interface language to Chinese",
2273
- brand: Object.freeze({ name: "SpotPatch", context: "Live context" }),
2277
+ brand: Object.freeze({
2278
+ name: "SpotPatch",
2279
+ context: "Live context",
2280
+ repository: "GitHub \u2197",
2281
+ repositoryTitle: "Star SpotPatch on GitHub"
2282
+ }),
2274
2283
  trigger: Object.freeze({
2275
2284
  select: "Select element",
2276
2285
  stop: "Stop selecting",
@@ -2322,7 +2331,8 @@ var UI_MESSAGES = Object.freeze({
2322
2331
  actions: Object.freeze({
2323
2332
  addElement: "Add element",
2324
2333
  reselect: "Start over",
2325
- openEditor: "Open in VS Code",
2334
+ openEditor: "Open source",
2335
+ openTarget: (index) => `Open source for target ${String(index)}`,
2326
2336
  preview: "Preview prompt",
2327
2337
  copy: "Copy prompt",
2328
2338
  back: "Back to edit"
@@ -2378,8 +2388,9 @@ var UI_MESSAGES = Object.freeze({
2378
2388
  detachedTargetRemoved: "A removed page element was dropped from the selection.",
2379
2389
  contextWarning: "Browser context collection completed with a warning.",
2380
2390
  contextCollected: "Browser context collected.",
2381
- editorOpened: "VS Code open request sent.",
2382
- editorFailed: "VS Code could not be opened.",
2391
+ editorOpening: "Opening source\u2026",
2392
+ editorOpened: "Source opened in the editor.",
2393
+ editorFailed: "Could not open the editor. Start it or configure editor.",
2383
2394
  completeInstructions: "Add an instruction for every target and wait for context collection to finish.",
2384
2395
  promptCopied: "Prompt copied to the clipboard.",
2385
2396
  clipboardUnavailable: "Clipboard access is unavailable. Select the prompt manually.",
@@ -2392,7 +2403,12 @@ var UI_MESSAGES = Object.freeze({
2392
2403
  localeName: "\u4E2D",
2393
2404
  alternateLocaleName: "EN",
2394
2405
  switchLocale: "\u5C06\u754C\u9762\u8BED\u8A00\u5207\u6362\u4E3A\u82F1\u6587",
2395
- brand: Object.freeze({ name: "SpotPatch", context: "\u5B9E\u65F6\u4E0A\u4E0B\u6587" }),
2406
+ brand: Object.freeze({
2407
+ name: "SpotPatch",
2408
+ context: "\u5B9E\u65F6\u4E0A\u4E0B\u6587",
2409
+ repository: "GitHub \u2197",
2410
+ repositoryTitle: "\u5728 GitHub \u4E0A Star SpotPatch"
2411
+ }),
2396
2412
  trigger: Object.freeze({
2397
2413
  select: "\u9009\u62E9\u5143\u7D20",
2398
2414
  stop: "\u505C\u6B62\u9009\u62E9",
@@ -2444,7 +2460,8 @@ var UI_MESSAGES = Object.freeze({
2444
2460
  actions: Object.freeze({
2445
2461
  addElement: "\u6DFB\u52A0\u5143\u7D20",
2446
2462
  reselect: "\u91CD\u65B0\u5F00\u59CB",
2447
- openEditor: "\u5728 VS Code \u4E2D\u6253\u5F00",
2463
+ openEditor: "\u6253\u5F00\u6E90\u7801",
2464
+ openTarget: (index) => `\u6253\u5F00\u76EE\u6807 ${String(index)} \u7684\u6E90\u7801`,
2448
2465
  preview: "\u9884\u89C8 Prompt",
2449
2466
  copy: "\u590D\u5236 Prompt",
2450
2467
  back: "\u8FD4\u56DE\u7F16\u8F91"
@@ -2500,8 +2517,9 @@ var UI_MESSAGES = Object.freeze({
2500
2517
  detachedTargetRemoved: "\u9875\u9762\u4E2D\u7684\u76EE\u6807\u5DF2\u5378\u8F7D\uFF0C\u5DF2\u4ECE\u5F53\u524D\u9009\u62E9\u4E2D\u79FB\u9664\u3002",
2501
2518
  contextWarning: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\uFF0C\u4F46\u5B58\u5728\u8B66\u544A\u3002",
2502
2519
  contextCollected: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\u3002",
2503
- editorOpened: "\u5DF2\u53D1\u9001 VS Code \u6253\u5F00\u8BF7\u6C42\u3002",
2504
- editorFailed: "\u65E0\u6CD5\u6253\u5F00 VS Code\u3002",
2520
+ editorOpening: "\u6B63\u5728\u6253\u5F00\u6E90\u7801\u2026\u2026",
2521
+ editorOpened: "\u6E90\u7801\u5DF2\u5728\u7F16\u8F91\u5668\u4E2D\u6253\u5F00\u3002",
2522
+ editorFailed: "\u65E0\u6CD5\u6253\u5F00\u7F16\u8F91\u5668\u3002\u8BF7\u5148\u542F\u52A8\u7F16\u8F91\u5668\u6216\u68C0\u67E5 editor \u914D\u7F6E\u3002",
2505
2523
  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
2524
  promptCopied: "Prompt \u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F\u3002",
2507
2525
  clipboardUnavailable: "\u65E0\u6CD5\u8BBF\u95EE\u526A\u8D34\u677F\uFF0C\u8BF7\u624B\u52A8\u9009\u62E9\u5E76\u590D\u5236 Prompt\u3002",
@@ -2796,14 +2814,27 @@ function createStyles(document) {
2796
2814
  gap: 8px;
2797
2815
  flex: none;
2798
2816
  }
2799
- .spotpatch-locale {
2800
- min-width: 38px;
2817
+ .spotpatch-repository,
2818
+ .spotpatch-locale,
2819
+ .spotpatch-close {
2801
2820
  height: 30px;
2802
2821
  border: 1px solid rgb(255 255 255 / 11%);
2803
2822
  border-radius: 9px;
2823
+ background: rgb(255 255 255 / 4%);
2824
+ }
2825
+ .spotpatch-repository {
2826
+ display: inline-flex;
2827
+ align-items: center;
2828
+ padding: 0 10px;
2829
+ color: #bcecf2;
2830
+ font-size: 11px;
2831
+ font-weight: 680;
2832
+ text-decoration: none;
2833
+ }
2834
+ .spotpatch-locale {
2835
+ min-width: 38px;
2804
2836
  padding: 0 9px;
2805
2837
  color: #c5cad5;
2806
- background: rgb(255 255 255 / 4%);
2807
2838
  cursor: pointer;
2808
2839
  font-size: 12px;
2809
2840
  font-weight: 650;
@@ -2811,20 +2842,17 @@ function createStyles(document) {
2811
2842
  .spotpatch-close {
2812
2843
  display: inline-grid;
2813
2844
  width: 30px;
2814
- height: 30px;
2815
2845
  padding: 0;
2816
2846
  place-items: center;
2817
- border: 1px solid rgb(255 255 255 / 11%);
2818
- border-radius: 9px;
2819
2847
  color: #9da5b4;
2820
- background: rgb(255 255 255 / 4%);
2821
2848
  cursor: pointer;
2822
2849
  font-size: 17px;
2823
2850
  line-height: 1;
2824
2851
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
2825
2852
  }
2826
2853
  .spotpatch-close:hover,
2827
- .spotpatch-locale:hover { border-color: rgb(129 112 247 / 45%); color: #fff; background: rgb(109 93 246 / 10%); }
2854
+ .spotpatch-locale:hover,
2855
+ .spotpatch-repository:hover { border-color: rgb(129 112 247 / 45%); color: #fff; background: rgb(109 93 246 / 10%); }
2828
2856
  .spotpatch-title {
2829
2857
  margin: 0;
2830
2858
  color: #fff;
@@ -2874,10 +2902,14 @@ function createStyles(document) {
2874
2902
  background: #f59e0b;
2875
2903
  content: "";
2876
2904
  }
2877
- .spotpatch-context-state[data-state="ready"] { color: #9fe3c4; }
2878
- .spotpatch-context-state[data-state="ready"]::before { background: #34d399; }
2879
- .spotpatch-context-state[data-state="warning"] { color: #fecaca; }
2880
- .spotpatch-context-state[data-state="warning"]::before { background: #fb7185; }
2905
+ .spotpatch-context-state[data-state="ready"],
2906
+ .spotpatch-editor-feedback[data-state="success"] { color: #9fe3c4; }
2907
+ .spotpatch-context-state[data-state="ready"]::before,
2908
+ .spotpatch-editor-feedback[data-state="success"]::before { background: #34d399; }
2909
+ .spotpatch-context-state[data-state="warning"],
2910
+ .spotpatch-editor-feedback[data-state="error"] { color: #fecaca; }
2911
+ .spotpatch-context-state[data-state="warning"]::before,
2912
+ .spotpatch-editor-feedback[data-state="error"]::before { background: #fb7185; }
2881
2913
  .spotpatch-body {
2882
2914
  min-height: 0;
2883
2915
  overflow: auto;
@@ -2939,7 +2971,7 @@ function createStyles(document) {
2939
2971
  }
2940
2972
  .spotpatch-target-summary {
2941
2973
  display: grid;
2942
- grid-template-columns: minmax(0, 1fr) 34px;
2974
+ grid-template-columns: minmax(0, 1fr) 34px 34px;
2943
2975
  align-items: stretch;
2944
2976
  gap: 4px;
2945
2977
  padding: 5px;
@@ -2990,6 +3022,7 @@ function createStyles(document) {
2990
3022
  white-space: nowrap;
2991
3023
  }
2992
3024
  .spotpatch-target-state[data-complete="false"] { color: #f5c97a; background: rgb(245 158 11 / 9%); }
3025
+ .spotpatch-target-open,
2993
3026
  .spotpatch-target-remove {
2994
3027
  display: inline-grid;
2995
3028
  width: 34px;
@@ -3003,6 +3036,8 @@ function createStyles(document) {
3003
3036
  background: transparent;
3004
3037
  cursor: pointer;
3005
3038
  }
3039
+ .spotpatch-target-open { color: #79d9e7; }
3040
+ .spotpatch-target-open:hover:not(:disabled) { border-color: rgb(68 202 224 / 30%); color: #c8f7ff; background: rgb(8 145 178 / 11%); }
3006
3041
  .spotpatch-target-remove:hover:not(:disabled) { border-color: rgb(251 113 133 / 24%); color: #fda4af; background: rgb(127 29 29 / 12%); }
3007
3042
  .spotpatch-target-editor {
3008
3043
  border-top: 1px solid rgb(255 255 255 / 7%);
@@ -3112,6 +3147,10 @@ function createStyles(document) {
3112
3147
  border-top: 1px solid rgb(255 255 255 / 8%);
3113
3148
  background: rgb(8 12 22 / 82%);
3114
3149
  }
3150
+ .spotpatch-editor-feedback {
3151
+ flex-basis: 100%;
3152
+ white-space: normal;
3153
+ }
3115
3154
  .spotpatch-actions button {
3116
3155
  display: inline-flex;
3117
3156
  min-height: 40px;
@@ -3143,6 +3182,8 @@ function createStyles(document) {
3143
3182
  .spotpatch-actions .spotpatch-primary::after { margin-left: 8px; content: "\u2197"; font-size: 12px; }
3144
3183
  .spotpatch-actions button:disabled { cursor: not-allowed; opacity: .4; transform: none; }
3145
3184
  .spotpatch-actions button:focus-visible,
3185
+ .spotpatch-repository:focus-visible,
3186
+ .spotpatch-target-open:focus-visible,
3146
3187
  .spotpatch-target-remove:focus-visible,
3147
3188
  .spotpatch-close:focus-visible,
3148
3189
  .spotpatch-trigger:focus-visible,
@@ -3234,9 +3275,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3234
3275
  brand.append(createBrandMark(document), brandCopy);
3235
3276
  const headerControls = createMarkedElement(document, "span");
3236
3277
  headerControls.className = "spotpatch-header-controls";
3278
+ const repositoryLink = createMarkedElement(document, "a");
3279
+ repositoryLink.className = "spotpatch-repository";
3280
+ repositoryLink.href = import_shared7.SPOTPATCH_REPOSITORY_URL;
3281
+ repositoryLink.target = "_blank";
3282
+ repositoryLink.rel = "noopener noreferrer";
3237
3283
  const localeButton = createButton(document, "", "spotpatch-locale");
3238
3284
  const closeButton = createButton(document, "\xD7", "spotpatch-close");
3239
- headerControls.append(localeButton, closeButton);
3285
+ headerControls.append(repositoryLink, localeButton, closeButton);
3240
3286
  brandRow.append(brand, headerControls);
3241
3287
  const title = createMarkedElement(document, "h2");
3242
3288
  title.id = "spotpatch-selection-title";
@@ -3300,6 +3346,12 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3300
3346
  body.append(selectionPanel, previewPanel);
3301
3347
  const actions = createMarkedElement(document, "footer");
3302
3348
  actions.className = "spotpatch-actions";
3349
+ const editorFeedback = createMarkedElement(document, "div");
3350
+ editorFeedback.className = "spotpatch-context-state spotpatch-editor-feedback";
3351
+ editorFeedback.dataset.state = "idle";
3352
+ editorFeedback.setAttribute("role", "status");
3353
+ editorFeedback.setAttribute("aria-live", "polite");
3354
+ editorFeedback.hidden = true;
3303
3355
  const addTargetButton = createButton(document, messages.actions.addElement);
3304
3356
  const reselectButton = createButton(document, messages.actions.reselect);
3305
3357
  const openEditorButton = createButton(document, messages.actions.openEditor);
@@ -3311,6 +3363,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3311
3363
  const copyButton = createButton(document, messages.actions.copy, "spotpatch-primary");
3312
3364
  const backButton = createButton(document, messages.actions.back);
3313
3365
  actions.append(
3366
+ editorFeedback,
3314
3367
  agentPanel.runButton,
3315
3368
  previewButton,
3316
3369
  agentPanel.testButton,
@@ -3348,6 +3401,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3348
3401
  let editingEnabled = true;
3349
3402
  let currentTargets = [];
3350
3403
  let currentMaximum = 0;
3404
+ let currentEditorFeedbackState = "idle";
3405
+ function renderEditorStatus(state) {
3406
+ currentEditorFeedbackState = state;
3407
+ editorFeedback.dataset.state = state;
3408
+ editorFeedback.hidden = state === "idle";
3409
+ editorFeedback.textContent = state === "opening" ? messages.announcements.editorOpening : state === "success" ? messages.announcements.editorOpened : state === "error" ? messages.announcements.editorFailed : "";
3410
+ placeDialog();
3411
+ }
3351
3412
  function statusText(target) {
3352
3413
  if (target.status === "ready") {
3353
3414
  return messages.targets.statusReady;
@@ -3426,12 +3487,17 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3426
3487
  state.dataset.complete = String(instructionComplete);
3427
3488
  state.textContent = instructionComplete ? messages.targets.instructionReady : messages.targets.instructionMissing;
3428
3489
  select.append(number, copy, state);
3490
+ const open = createButton(document, "\u2197", "spotpatch-target-open");
3491
+ open.dataset.openTargetId = target.id;
3492
+ open.disabled = !target.canOpenEditor;
3493
+ open.setAttribute("aria-label", messages.actions.openTarget(index + 1));
3494
+ open.title = messages.actions.openTarget(index + 1);
3429
3495
  const remove = createButton(document, "\xD7", "spotpatch-target-remove");
3430
3496
  remove.dataset.removeTargetId = target.id;
3431
3497
  remove.disabled = !editingEnabled;
3432
3498
  remove.setAttribute("aria-label", messages.targets.remove(index + 1));
3433
3499
  remove.title = messages.targets.removeTitle;
3434
- targetSummary.append(select, remove);
3500
+ targetSummary.append(select, open, remove);
3435
3501
  item.append(targetSummary);
3436
3502
  if (target.active) {
3437
3503
  const editor = createMarkedElement(document, "label");
@@ -3609,6 +3675,9 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3609
3675
  messages = localizer.messages();
3610
3676
  brandName.textContent = messages.brand.name;
3611
3677
  brandContext.textContent = messages.brand.context;
3678
+ repositoryLink.textContent = messages.brand.repository;
3679
+ repositoryLink.title = messages.brand.repositoryTitle;
3680
+ repositoryLink.setAttribute("aria-label", messages.brand.repositoryTitle);
3612
3681
  localeButton.textContent = messages.alternateLocaleName;
3613
3682
  localeButton.title = messages.switchLocale;
3614
3683
  localeButton.setAttribute("aria-label", messages.switchLocale);
@@ -3627,6 +3696,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3627
3696
  triggerButton.title = messages.trigger.title(shortcut);
3628
3697
  triggerButton.textContent = currentStatus === "inspecting" ? messages.trigger.stop : messages.trigger.select;
3629
3698
  renderPanelStatus(currentStatus);
3699
+ renderEditorStatus(currentEditorFeedbackState);
3630
3700
  if (currentTargets.length > 0) {
3631
3701
  renderTargets(currentTargets, currentMaximum);
3632
3702
  } else {
@@ -3657,6 +3727,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3657
3727
  targetList,
3658
3728
  reselectButton,
3659
3729
  openEditorButton,
3730
+ repositoryLink,
3660
3731
  previewButton,
3661
3732
  copyButton,
3662
3733
  backButton,
@@ -3676,6 +3747,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3676
3747
  triggerButton.textContent = inspecting ? messages.trigger.stop : messages.trigger.select;
3677
3748
  renderPanelStatus(status);
3678
3749
  },
3750
+ renderEditorStatus,
3679
3751
  showHighlight(rect, label) {
3680
3752
  currentRect = rect;
3681
3753
  highlight.hidden = false;
@@ -3719,6 +3791,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3719
3791
  currentTargets = [];
3720
3792
  currentMaximum = 0;
3721
3793
  currentSummaryText = "";
3794
+ renderEditorStatus("idle");
3722
3795
  targetCount.textContent = messages.targets.count(0, 0);
3723
3796
  targetComplete.textContent = messages.targets.complete(0, 0);
3724
3797
  targetLabel.textContent = messages.context.selectedElement;
@@ -3762,7 +3835,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3762
3835
  ).forEach((control) => {
3763
3836
  control.disabled = !enabled;
3764
3837
  });
3765
- openEditorButton.disabled = !enabled || !currentCanOpenEditor;
3838
+ openEditorButton.disabled = !currentCanOpenEditor;
3766
3839
  previewButton.disabled = !enabled || !currentCanPreview;
3767
3840
  agentPanel.setEditingEnabled(enabled);
3768
3841
  placeDialog();
@@ -4281,6 +4354,7 @@ function createController(config, dependencies = {}) {
4281
4354
  let activeTargetId;
4282
4355
  let targetSequence = 0;
4283
4356
  let sessionRevision = 0;
4357
+ let editorRequestRevision = 0;
4284
4358
  let addingTarget = false;
4285
4359
  let previewPrompt = "";
4286
4360
  let previousFocus;
@@ -4355,6 +4429,7 @@ ${summary}`;
4355
4429
  id: target.id,
4356
4430
  label: target.resolution.react.componentName ?? (target.element === void 0 ? target.elementContext?.tagName ?? "Element" : elementLabel(target.element)),
4357
4431
  source: sourceLabel(target, view.messages().context.sourceUnavailable),
4432
+ canOpenEditor: target.marker !== void 0,
4358
4433
  status: targetStatus(target),
4359
4434
  active: target.id === activeTargetId,
4360
4435
  instruction: target.instruction
@@ -4498,7 +4573,6 @@ ${summary}`;
4498
4573
  resizeObserver?.disconnect();
4499
4574
  for (const target of targets) {
4500
4575
  target.element = void 0;
4501
- target.marker = void 0;
4502
4576
  }
4503
4577
  view.hideHighlight();
4504
4578
  view.hideSelectionHighlights();
@@ -4775,24 +4849,31 @@ ${summary}`;
4775
4849
  }
4776
4850
  refreshHighlights();
4777
4851
  }
4778
- function handleOpenEditor() {
4779
- const current = activeTarget();
4852
+ function handleOpenEditor(targetId) {
4853
+ const current = targetId === void 0 ? activeTarget() : targets.find((target) => target.id === targetId);
4780
4854
  if (state.status !== "selected" || current?.marker === void 0) {
4781
4855
  return;
4782
4856
  }
4857
+ if (activeTargetId !== current.id) {
4858
+ activeTargetId = current.id;
4859
+ refreshSelectionView();
4860
+ }
4783
4861
  const marker = current.marker;
4862
+ const selectionRevision = sessionRevision;
4863
+ const requestRevision = ++editorRequestRevision;
4784
4864
  transition({ type: "OPEN_EDITOR" });
4865
+ view.renderEditorStatus("opening");
4785
4866
  void api.openEditor({
4786
4867
  fileId: marker.fileId,
4787
4868
  line: marker.line,
4788
4869
  column: marker.column
4789
4870
  }).then(() => {
4790
- if (mounted && state.status === "selected") {
4791
- view.announce(view.messages().announcements.editorOpened);
4871
+ if (mounted && state.status === "selected" && selectionRevision === sessionRevision && requestRevision === editorRequestRevision && activeTargetId === current.id && targets.includes(current)) {
4872
+ view.renderEditorStatus("success");
4792
4873
  }
4793
4874
  }).catch(() => {
4794
- if (mounted && state.status === "selected") {
4795
- view.announce(view.messages().announcements.editorFailed);
4875
+ if (mounted && state.status === "selected" && selectionRevision === sessionRevision && requestRevision === editorRequestRevision && activeTargetId === current.id && targets.includes(current)) {
4876
+ view.renderEditorStatus("error");
4796
4877
  }
4797
4878
  });
4798
4879
  }
@@ -4809,6 +4890,9 @@ ${summary}`;
4809
4890
  view.updateTargetInstruction(target.id, target.instruction);
4810
4891
  view.setPreviewEnabled(canPreview());
4811
4892
  }
4893
+ function handleOpenEditorButtonClick() {
4894
+ handleOpenEditor();
4895
+ }
4812
4896
  function handleTargetListKeydown(event) {
4813
4897
  if (config.ai.enabled && state.status === "selected" && event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
4814
4898
  event.preventDefault();
@@ -4886,6 +4970,13 @@ ${summary}`;
4886
4970
  removeTarget(removeButton.dataset.removeTargetId);
4887
4971
  return;
4888
4972
  }
4973
+ const openButton = eventTarget.closest(
4974
+ "button[data-open-target-id]"
4975
+ );
4976
+ if (openButton?.dataset.openTargetId !== void 0) {
4977
+ handleOpenEditor(openButton.dataset.openTargetId);
4978
+ return;
4979
+ }
4889
4980
  const activateButton = eventTarget.closest(
4890
4981
  "button[data-activate-target-id]"
4891
4982
  );
@@ -4917,7 +5008,7 @@ ${summary}`;
4917
5008
  view.targetList.addEventListener("click", handleTargetListClick);
4918
5009
  view.targetList.addEventListener("input", handleTargetListInput);
4919
5010
  view.targetList.addEventListener("keydown", handleTargetListKeydown);
4920
- view.openEditorButton.addEventListener("click", handleOpenEditor);
5011
+ view.openEditorButton.addEventListener("click", handleOpenEditorButtonClick);
4921
5012
  view.previewButton.addEventListener("click", handlePreview);
4922
5013
  view.copyButton.addEventListener("click", handleCopy);
4923
5014
  view.backButton.addEventListener("click", handleBack);
@@ -4977,7 +5068,7 @@ ${summary}`;
4977
5068
  view.targetList.removeEventListener("click", handleTargetListClick);
4978
5069
  view.targetList.removeEventListener("input", handleTargetListInput);
4979
5070
  view.targetList.removeEventListener("keydown", handleTargetListKeydown);
4980
- view.openEditorButton.removeEventListener("click", handleOpenEditor);
5071
+ view.openEditorButton.removeEventListener("click", handleOpenEditorButtonClick);
4981
5072
  view.previewButton.removeEventListener("click", handlePreview);
4982
5073
  view.copyButton.removeEventListener("click", handleCopy);
4983
5074
  view.backButton.removeEventListener("click", handleBack);