@spotpatch/runtime 1.1.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.js CHANGED
@@ -76,7 +76,6 @@ function createAnnotation(input) {
76
76
  // src/api/runtime-api.ts
77
77
  import {
78
78
  SPOTPATCH_ENDPOINTS,
79
- SPOTPATCH_EDITOR_PREFERENCES,
80
79
  SPOTPATCH_TOKEN_HEADER,
81
80
  getAgentJobEndpoint
82
81
  } from "@spotpatch/shared";
@@ -249,9 +248,6 @@ function readSuccessData(value) {
249
248
  function isCodeContext(value) {
250
249
  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");
251
250
  }
252
- function isEditorOpenResult(value) {
253
- return isRecord2(value) && typeof value.editor === "string" && SPOTPATCH_EDITOR_PREFERENCES.includes(value.editor);
254
- }
255
251
  function deepFreezeUnknown(value) {
256
252
  if (!isRecord2(value) && !Array.isArray(value)) {
257
253
  return;
@@ -479,7 +475,7 @@ function createRuntimeApi(options) {
479
475
  },
480
476
  async openEditor(request) {
481
477
  const data = await requestJson(SPOTPATCH_ENDPOINTS.openEditor, "POST", request);
482
- if (!isEditorOpenResult(data)) {
478
+ if (!isRecord2(data) || data.editor !== "auto" && data.editor !== "vscode" && data.editor !== "cursor") {
483
479
  throw new RuntimeApiError();
484
480
  }
485
481
  return Object.freeze({ editor: data.editor });
@@ -2141,15 +2137,6 @@ var STATUS_ZH = Object.freeze({
2141
2137
  reverted: "\u5DF2\u64A4\u9500",
2142
2138
  failed: "\u5931\u8D25"
2143
2139
  });
2144
- function editorName(editor, automatic) {
2145
- if (editor === "vscode") {
2146
- return "VS Code";
2147
- }
2148
- if (editor === "cursor") {
2149
- return "Cursor";
2150
- }
2151
- return automatic;
2152
- }
2153
2140
  var ERROR_MESSAGES_EN = Object.freeze({
2154
2141
  [ERROR_CODES2.INVALID_REQUEST]: "The Agent request was rejected as invalid.",
2155
2142
  [ERROR_CODES2.INVALID_TOKEN]: "The local SpotPatch session expired.",
@@ -2288,7 +2275,7 @@ var UI_MESSAGES = Object.freeze({
2288
2275
  brand: Object.freeze({
2289
2276
  name: "SpotPatch",
2290
2277
  context: "Live context",
2291
- repository: "GitHub",
2278
+ repository: "GitHub \u2197",
2292
2279
  repositoryTitle: "Star SpotPatch on GitHub"
2293
2280
  }),
2294
2281
  trigger: Object.freeze({
@@ -2342,8 +2329,8 @@ var UI_MESSAGES = Object.freeze({
2342
2329
  actions: Object.freeze({
2343
2330
  addElement: "Add element",
2344
2331
  reselect: "Start over",
2345
- openEditor: (editor) => editor === "auto" ? "Open source" : `Open in ${editorName(editor, "editor")}`,
2346
- openTarget: (index, editor) => `Open target ${String(index)} in ${editorName(editor, "the detected editor")}`,
2332
+ openEditor: "Open source",
2333
+ openTarget: (index) => `Open source for target ${String(index)}`,
2347
2334
  preview: "Preview prompt",
2348
2335
  copy: "Copy prompt",
2349
2336
  back: "Back to edit"
@@ -2399,9 +2386,9 @@ var UI_MESSAGES = Object.freeze({
2399
2386
  detachedTargetRemoved: "A removed page element was dropped from the selection.",
2400
2387
  contextWarning: "Browser context collection completed with a warning.",
2401
2388
  contextCollected: "Browser context collected.",
2402
- editorOpening: (editor) => `Opening ${editorName(editor, "the detected editor")}\u2026`,
2403
- editorOpened: (editor) => `Opened the source in ${editorName(editor, "the detected editor")}.`,
2404
- editorFailed: (editor) => `Could not open ${editorName(editor, "an editor")}. Start the editor or configure editor: "cursor" / "vscode".`,
2389
+ editorOpening: "Opening source\u2026",
2390
+ editorOpened: "Source opened in the editor.",
2391
+ editorFailed: "Could not open the editor. Start it or configure editor.",
2405
2392
  completeInstructions: "Add an instruction for every target and wait for context collection to finish.",
2406
2393
  promptCopied: "Prompt copied to the clipboard.",
2407
2394
  clipboardUnavailable: "Clipboard access is unavailable. Select the prompt manually.",
@@ -2417,7 +2404,7 @@ var UI_MESSAGES = Object.freeze({
2417
2404
  brand: Object.freeze({
2418
2405
  name: "SpotPatch",
2419
2406
  context: "\u5B9E\u65F6\u4E0A\u4E0B\u6587",
2420
- repository: "GitHub",
2407
+ repository: "GitHub \u2197",
2421
2408
  repositoryTitle: "\u5728 GitHub \u4E0A Star SpotPatch"
2422
2409
  }),
2423
2410
  trigger: Object.freeze({
@@ -2471,8 +2458,8 @@ var UI_MESSAGES = Object.freeze({
2471
2458
  actions: Object.freeze({
2472
2459
  addElement: "\u6DFB\u52A0\u5143\u7D20",
2473
2460
  reselect: "\u91CD\u65B0\u5F00\u59CB",
2474
- openEditor: (editor) => editor === "auto" ? "\u6253\u5F00\u6E90\u7801" : `\u5728 ${editorName(editor, "\u7F16\u8F91\u5668")} \u4E2D\u6253\u5F00`,
2475
- openTarget: (index, editor) => `\u5728${editorName(editor, "\u81EA\u52A8\u68C0\u6D4B\u7684\u7F16\u8F91\u5668")}\u4E2D\u6253\u5F00\u76EE\u6807 ${String(index)} \u7684\u6E90\u7801`,
2461
+ openEditor: "\u6253\u5F00\u6E90\u7801",
2462
+ openTarget: (index) => `\u6253\u5F00\u76EE\u6807 ${String(index)} \u7684\u6E90\u7801`,
2476
2463
  preview: "\u9884\u89C8 Prompt",
2477
2464
  copy: "\u590D\u5236 Prompt",
2478
2465
  back: "\u8FD4\u56DE\u7F16\u8F91"
@@ -2528,9 +2515,9 @@ var UI_MESSAGES = Object.freeze({
2528
2515
  detachedTargetRemoved: "\u9875\u9762\u4E2D\u7684\u76EE\u6807\u5DF2\u5378\u8F7D\uFF0C\u5DF2\u4ECE\u5F53\u524D\u9009\u62E9\u4E2D\u79FB\u9664\u3002",
2529
2516
  contextWarning: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\uFF0C\u4F46\u5B58\u5728\u8B66\u544A\u3002",
2530
2517
  contextCollected: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\u3002",
2531
- editorOpening: (editor) => `\u6B63\u5728\u6253\u5F00${editorName(editor, "\u81EA\u52A8\u68C0\u6D4B\u7684\u7F16\u8F91\u5668")}\u2026\u2026`,
2532
- editorOpened: (editor) => `\u5DF2\u5728${editorName(editor, "\u81EA\u52A8\u68C0\u6D4B\u7684\u7F16\u8F91\u5668")}\u4E2D\u6253\u5F00\u6E90\u7801\u3002`,
2533
- 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`,
2518
+ editorOpening: "\u6B63\u5728\u6253\u5F00\u6E90\u7801\u2026\u2026",
2519
+ editorOpened: "\u6E90\u7801\u5DF2\u5728\u7F16\u8F91\u5668\u4E2D\u6253\u5F00\u3002",
2520
+ editorFailed: "\u65E0\u6CD5\u6253\u5F00\u7F16\u8F91\u5668\u3002\u8BF7\u5148\u542F\u52A8\u7F16\u8F91\u5668\u6216\u68C0\u67E5 editor \u914D\u7F6E\u3002",
2534
2521
  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",
2535
2522
  promptCopied: "Prompt \u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F\u3002",
2536
2523
  clipboardUnavailable: "\u65E0\u6CD5\u8BBF\u95EE\u526A\u8D34\u677F\uFF0C\u8BF7\u624B\u52A8\u9009\u62E9\u5E76\u590D\u5236 Prompt\u3002",
@@ -2825,36 +2812,27 @@ function createStyles(document) {
2825
2812
  gap: 8px;
2826
2813
  flex: none;
2827
2814
  }
2815
+ .spotpatch-repository,
2816
+ .spotpatch-locale,
2817
+ .spotpatch-close {
2818
+ height: 30px;
2819
+ border: 1px solid rgb(255 255 255 / 11%);
2820
+ border-radius: 9px;
2821
+ background: rgb(255 255 255 / 4%);
2822
+ }
2828
2823
  .spotpatch-repository {
2829
2824
  display: inline-flex;
2830
- height: 30px;
2831
2825
  align-items: center;
2832
- gap: 5px;
2833
- border: 1px solid rgb(68 202 224 / 20%);
2834
- border-radius: 9px;
2835
2826
  padding: 0 10px;
2836
2827
  color: #bcecf2;
2837
- background: rgb(8 145 178 / 7%);
2838
2828
  font-size: 11px;
2839
2829
  font-weight: 680;
2840
2830
  text-decoration: none;
2841
- transition: border-color 150ms ease, color 150ms ease, background 150ms ease, transform 150ms ease;
2842
- }
2843
- .spotpatch-repository::after { content: "\u2197"; font-size: 10px; }
2844
- .spotpatch-repository:hover {
2845
- border-color: rgb(68 202 224 / 42%);
2846
- color: #e6fbff;
2847
- background: rgb(8 145 178 / 12%);
2848
- transform: translateY(-1px);
2849
2831
  }
2850
2832
  .spotpatch-locale {
2851
2833
  min-width: 38px;
2852
- height: 30px;
2853
- border: 1px solid rgb(255 255 255 / 11%);
2854
- border-radius: 9px;
2855
2834
  padding: 0 9px;
2856
2835
  color: #c5cad5;
2857
- background: rgb(255 255 255 / 4%);
2858
2836
  cursor: pointer;
2859
2837
  font-size: 12px;
2860
2838
  font-weight: 650;
@@ -2862,20 +2840,17 @@ function createStyles(document) {
2862
2840
  .spotpatch-close {
2863
2841
  display: inline-grid;
2864
2842
  width: 30px;
2865
- height: 30px;
2866
2843
  padding: 0;
2867
2844
  place-items: center;
2868
- border: 1px solid rgb(255 255 255 / 11%);
2869
- border-radius: 9px;
2870
2845
  color: #9da5b4;
2871
- background: rgb(255 255 255 / 4%);
2872
2846
  cursor: pointer;
2873
2847
  font-size: 17px;
2874
2848
  line-height: 1;
2875
2849
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
2876
2850
  }
2877
2851
  .spotpatch-close:hover,
2878
- .spotpatch-locale:hover { border-color: rgb(129 112 247 / 45%); color: #fff; background: rgb(109 93 246 / 10%); }
2852
+ .spotpatch-locale:hover,
2853
+ .spotpatch-repository:hover { border-color: rgb(129 112 247 / 45%); color: #fff; background: rgb(109 93 246 / 10%); }
2879
2854
  .spotpatch-title {
2880
2855
  margin: 0;
2881
2856
  color: #fff;
@@ -2925,10 +2900,14 @@ function createStyles(document) {
2925
2900
  background: #f59e0b;
2926
2901
  content: "";
2927
2902
  }
2928
- .spotpatch-context-state[data-state="ready"] { color: #9fe3c4; }
2929
- .spotpatch-context-state[data-state="ready"]::before { background: #34d399; }
2930
- .spotpatch-context-state[data-state="warning"] { color: #fecaca; }
2931
- .spotpatch-context-state[data-state="warning"]::before { background: #fb7185; }
2903
+ .spotpatch-context-state[data-state="ready"],
2904
+ .spotpatch-editor-feedback[data-state="success"] { color: #9fe3c4; }
2905
+ .spotpatch-context-state[data-state="ready"]::before,
2906
+ .spotpatch-editor-feedback[data-state="success"]::before { background: #34d399; }
2907
+ .spotpatch-context-state[data-state="warning"],
2908
+ .spotpatch-editor-feedback[data-state="error"] { color: #fecaca; }
2909
+ .spotpatch-context-state[data-state="warning"]::before,
2910
+ .spotpatch-editor-feedback[data-state="error"]::before { background: #fb7185; }
2932
2911
  .spotpatch-body {
2933
2912
  min-height: 0;
2934
2913
  overflow: auto;
@@ -3167,29 +3146,9 @@ function createStyles(document) {
3167
3146
  background: rgb(8 12 22 / 82%);
3168
3147
  }
3169
3148
  .spotpatch-editor-feedback {
3170
- display: flex;
3171
- width: 100%;
3172
- align-items: center;
3173
- gap: 7px;
3174
- margin-bottom: 1px;
3175
- color: #9ca5b5;
3176
- font-size: 11px;
3177
- line-height: 1.45;
3178
- }
3179
- .spotpatch-editor-feedback[hidden] { display: none; }
3180
- .spotpatch-editor-feedback::before {
3181
- width: 6px;
3182
- height: 6px;
3183
- flex: none;
3184
- border-radius: 999px;
3185
- background: #94a3b8;
3186
- content: "";
3149
+ flex-basis: 100%;
3150
+ white-space: normal;
3187
3151
  }
3188
- .spotpatch-editor-feedback[data-state="opening"]::before { background: #38bdf8; }
3189
- .spotpatch-editor-feedback[data-state="success"] { color: #9fe3c4; }
3190
- .spotpatch-editor-feedback[data-state="success"]::before { background: #34d399; }
3191
- .spotpatch-editor-feedback[data-state="error"] { color: #fecaca; }
3192
- .spotpatch-editor-feedback[data-state="error"]::before { background: #fb7185; }
3193
3152
  .spotpatch-actions button {
3194
3153
  display: inline-flex;
3195
3154
  min-height: 40px;
@@ -3255,8 +3214,6 @@ function createStyles(document) {
3255
3214
  .spotpatch-actions { padding-left: 16px; padding-right: 16px; }
3256
3215
  .spotpatch-target-select { grid-template-columns: 32px minmax(0, 1fr); }
3257
3216
  .spotpatch-target-state { display: none; }
3258
- .spotpatch-repository { width: 30px; overflow: hidden; padding: 0; justify-content: center; color: transparent; }
3259
- .spotpatch-repository::after { color: #bcecf2; content: "\u2197"; }
3260
3217
  }
3261
3218
  ${AGENT_PANEL_STYLES}
3262
3219
  `;
@@ -3266,7 +3223,7 @@ function summaryLine(summary, prefix) {
3266
3223
  const line = summary.split("\n").find((candidate) => candidate.startsWith(`${prefix}: `));
3267
3224
  return line?.slice(prefix.length + 2).trim();
3268
3225
  }
3269
- function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: false }), localePreference = "auto", editorPreference = "auto") {
3226
+ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: false }), localePreference = "auto") {
3270
3227
  const localizer = createUiLocalizer(document, localePreference);
3271
3228
  let messages = localizer.messages();
3272
3229
  const host = document.createElement("spotpatch-root");
@@ -3388,17 +3345,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3388
3345
  const actions = createMarkedElement(document, "footer");
3389
3346
  actions.className = "spotpatch-actions";
3390
3347
  const editorFeedback = createMarkedElement(document, "div");
3391
- editorFeedback.className = "spotpatch-editor-feedback";
3348
+ editorFeedback.className = "spotpatch-context-state spotpatch-editor-feedback";
3392
3349
  editorFeedback.dataset.state = "idle";
3393
3350
  editorFeedback.setAttribute("role", "status");
3394
3351
  editorFeedback.setAttribute("aria-live", "polite");
3395
3352
  editorFeedback.hidden = true;
3396
3353
  const addTargetButton = createButton(document, messages.actions.addElement);
3397
3354
  const reselectButton = createButton(document, messages.actions.reselect);
3398
- const openEditorButton = createButton(
3399
- document,
3400
- messages.actions.openEditor(editorPreference)
3401
- );
3355
+ const openEditorButton = createButton(document, messages.actions.openEditor);
3402
3356
  const previewButton = createButton(
3403
3357
  document,
3404
3358
  messages.actions.preview,
@@ -3446,20 +3400,11 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3446
3400
  let currentTargets = [];
3447
3401
  let currentMaximum = 0;
3448
3402
  let currentEditorFeedbackState = "idle";
3449
- function defaultEditorFeedback(state) {
3450
- if (state === "opening") {
3451
- return messages.announcements.editorOpening(editorPreference);
3452
- }
3453
- if (state === "success") {
3454
- return messages.announcements.editorOpened(editorPreference);
3455
- }
3456
- return state === "error" ? messages.announcements.editorFailed(editorPreference) : "";
3457
- }
3458
- function renderEditorStatus(state, message = defaultEditorFeedback(state)) {
3403
+ function renderEditorStatus(state) {
3459
3404
  currentEditorFeedbackState = state;
3460
3405
  editorFeedback.dataset.state = state;
3461
3406
  editorFeedback.hidden = state === "idle";
3462
- editorFeedback.textContent = message;
3407
+ editorFeedback.textContent = state === "opening" ? messages.announcements.editorOpening : state === "success" ? messages.announcements.editorOpened : state === "error" ? messages.announcements.editorFailed : "";
3463
3408
  placeDialog();
3464
3409
  }
3465
3410
  function statusText(target) {
@@ -3543,11 +3488,8 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3543
3488
  const open = createButton(document, "\u2197", "spotpatch-target-open");
3544
3489
  open.dataset.openTargetId = target.id;
3545
3490
  open.disabled = !target.canOpenEditor;
3546
- open.setAttribute(
3547
- "aria-label",
3548
- messages.actions.openTarget(index + 1, editorPreference)
3549
- );
3550
- open.title = messages.actions.openTarget(index + 1, editorPreference);
3491
+ open.setAttribute("aria-label", messages.actions.openTarget(index + 1));
3492
+ open.title = messages.actions.openTarget(index + 1);
3551
3493
  const remove = createButton(document, "\xD7", "spotpatch-target-remove");
3552
3494
  remove.dataset.removeTargetId = target.id;
3553
3495
  remove.disabled = !editingEnabled;
@@ -3745,7 +3687,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3745
3687
  promptOutput.setAttribute("aria-label", messages.diagnostics.promptAriaLabel);
3746
3688
  addTargetButton.textContent = messages.actions.addElement;
3747
3689
  reselectButton.textContent = messages.actions.reselect;
3748
- openEditorButton.textContent = messages.actions.openEditor(editorPreference);
3690
+ openEditorButton.textContent = messages.actions.openEditor;
3749
3691
  previewButton.textContent = messages.actions.preview;
3750
3692
  copyButton.textContent = messages.actions.copy;
3751
3693
  backButton.textContent = messages.actions.back;
@@ -4381,13 +4323,7 @@ function resolveBrowserDependencies(dependencies) {
4381
4323
  }
4382
4324
  function createController(config, dependencies = {}) {
4383
4325
  const browser = resolveBrowserDependencies(dependencies);
4384
- const view = dependencies.view ?? createRuntimeView(
4385
- browser.document,
4386
- config.shortcut,
4387
- config.ai,
4388
- config.locale,
4389
- config.editor
4390
- );
4326
+ const view = dependencies.view ?? createRuntimeView(browser.document, config.shortcut, config.ai, config.locale);
4391
4327
  const api = dependencies.api ?? createRuntimeApi({
4392
4328
  apiBase: config.apiBase,
4393
4329
  fetch: browser.window.fetch.bind(browser.window),
@@ -4926,24 +4862,18 @@ ${summary}`;
4926
4862
  const selectionRevision = sessionRevision;
4927
4863
  const requestRevision = ++editorRequestRevision;
4928
4864
  transition({ type: "OPEN_EDITOR" });
4929
- const openingMessage = view.messages().announcements.editorOpening(config.editor);
4930
- view.renderEditorStatus("opening", openingMessage);
4931
- view.announce(openingMessage);
4865
+ view.renderEditorStatus("opening");
4932
4866
  void api.openEditor({
4933
4867
  fileId: marker.fileId,
4934
4868
  line: marker.line,
4935
4869
  column: marker.column
4936
- }).then((result) => {
4870
+ }).then(() => {
4937
4871
  if (mounted && state.status === "selected" && selectionRevision === sessionRevision && requestRevision === editorRequestRevision && activeTargetId === current.id && targets.includes(current)) {
4938
- const message = view.messages().announcements.editorOpened(result.editor);
4939
- view.renderEditorStatus("success", message);
4940
- view.announce(message);
4872
+ view.renderEditorStatus("success");
4941
4873
  }
4942
4874
  }).catch(() => {
4943
4875
  if (mounted && state.status === "selected" && selectionRevision === sessionRevision && requestRevision === editorRequestRevision && activeTargetId === current.id && targets.includes(current)) {
4944
- const message = view.messages().announcements.editorFailed(config.editor);
4945
- view.renderEditorStatus("error", message);
4946
- view.announce(message);
4876
+ view.renderEditorStatus("error");
4947
4877
  }
4948
4878
  });
4949
4879
  }