@spotpatch/runtime 1.6.0 → 1.7.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
@@ -1725,7 +1725,8 @@ var AGENT_PANEL_STYLES = `
1725
1725
  font-weight: 650;
1726
1726
  }
1727
1727
  .spotpatch-agent-setup { padding: 12px; }
1728
- .spotpatch-agent-selectors { display: grid; grid-template-columns: 1fr; gap: 10px; }
1728
+ .spotpatch-agent-selectors { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
1729
+ .spotpatch-agent-mode { grid-column: 1 / -1; }
1729
1730
  .spotpatch-agent-selectors label { min-width: 0; color: var(--spotpatch-text-secondary); font-size: 11.5px; font-weight: 580; }
1730
1731
  .spotpatch-agent select {
1731
1732
  box-sizing: border-box;
@@ -1763,19 +1764,21 @@ var AGENT_PANEL_STYLES = `
1763
1764
  width: anchor-size(width);
1764
1765
  max-height: min(280px, 40vh);
1765
1766
  margin: 0;
1766
- overflow: hidden;
1767
+ overflow: auto;
1767
1768
  border: 1px solid rgb(139 124 247 / 28%);
1768
1769
  border-radius: 12px;
1769
1770
  padding: 6px;
1770
1771
  background: #10151e;
1771
1772
  box-shadow: 0 18px 50px rgb(0 0 0 / 38%);
1772
- opacity: 0;
1773
- transform: translateY(-5px) scale(.985);
1773
+ opacity: 1;
1774
+ transform: translateY(0) scale(1);
1774
1775
  transition: opacity 150ms ease, transform 180ms cubic-bezier(.2, .8, .2, 1), overlay 180ms allow-discrete, display 180ms allow-discrete;
1775
1776
  }
1776
- ::picker(select):popover-open { opacity: 1; transform: translateY(0) scale(1); }
1777
1777
  @starting-style {
1778
- ::picker(select):popover-open { opacity: 0; transform: translateY(-5px) scale(.985); }
1778
+ .spotpatch-agent select::picker(select):popover-open {
1779
+ opacity: 0;
1780
+ transform: translateY(-5px) scale(.985);
1781
+ }
1779
1782
  }
1780
1783
  .spotpatch-agent select option {
1781
1784
  min-height: 42px;
@@ -1910,12 +1913,17 @@ var AGENT_PANEL_STYLES = `
1910
1913
  white-space: pre;
1911
1914
  user-select: text;
1912
1915
  }
1916
+ @media (max-width: 520px) {
1917
+ .spotpatch-agent-selectors { grid-template-columns: 1fr; }
1918
+ .spotpatch-agent-mode { grid-column: auto; }
1919
+ }
1913
1920
  `;
1914
1921
  function addOption(document, select, value, label) {
1915
1922
  const option = document.createElement("option");
1916
1923
  option.value = value;
1917
1924
  option.textContent = label;
1918
1925
  select.append(option);
1926
+ return option;
1919
1927
  }
1920
1928
  function createAgentPanel(document, ai, localizer) {
1921
1929
  let messages = localizer.messages();
@@ -1933,6 +1941,11 @@ function createAgentPanel(document, ai, localizer) {
1933
1941
  setup.className = "spotpatch-agent-setup";
1934
1942
  const selectors = createMarkedElement(document, "div");
1935
1943
  selectors.className = "spotpatch-agent-selectors";
1944
+ const modeLabel = createMarkedElement(document, "label");
1945
+ modeLabel.className = "spotpatch-agent-mode";
1946
+ const modeText = createMarkedElement(document, "span");
1947
+ const modeSelect = createMarkedElement(document, "select");
1948
+ modeLabel.append(modeText, modeSelect);
1936
1949
  const providerLabel = createMarkedElement(document, "label");
1937
1950
  const providerText = createMarkedElement(document, "span");
1938
1951
  const providerSelect = createMarkedElement(document, "select");
@@ -1941,7 +1954,7 @@ function createAgentPanel(document, ai, localizer) {
1941
1954
  const modelText = createMarkedElement(document, "span");
1942
1955
  const modelSelect = createMarkedElement(document, "select");
1943
1956
  modelLabel.append(modelText, modelSelect);
1944
- selectors.append(providerLabel, modelLabel);
1957
+ selectors.append(modeLabel, providerLabel, modelLabel);
1945
1958
  const consent = createMarkedElement(document, "label");
1946
1959
  consent.className = "spotpatch-consent";
1947
1960
  const consentCheckbox = createMarkedElement(document, "input");
@@ -2008,8 +2021,8 @@ function createAgentPanel(document, ai, localizer) {
2008
2021
  const revertButton = createButton(document, messages.agent.revert);
2009
2022
  const resetButton = createButton(document, messages.agent.revise);
2010
2023
  const providers = ai.enabled ? ai.providers : [];
2011
- const trustedFastMode = ai.enabled && ai.applyMode === "trusted-auto";
2012
- consent.classList.toggle("spotpatch-trusted-consent", trustedFastMode);
2024
+ const trustedFastModeAvailable = ai.enabled && ai.applyMode === "trusted-auto";
2025
+ const configuredApplyMode = ai.enabled ? ai.applyMode : "review";
2013
2026
  const providerById = new Map(providers.map((provider) => [provider.id, provider]));
2014
2027
  let contextReady = false;
2015
2028
  let editingEnabled = true;
@@ -2033,14 +2046,42 @@ function createAgentPanel(document, ai, localizer) {
2033
2046
  if (ai.enabled) {
2034
2047
  providerSelect.value = ai.defaultProvider;
2035
2048
  }
2049
+ let reviewOption;
2050
+ let trustedOption;
2051
+ let autoOption;
2052
+ if (configuredApplyMode === "auto") {
2053
+ autoOption = addOption(document, modeSelect, "auto", messages.agent.autoGated);
2054
+ } else {
2055
+ reviewOption = addOption(document, modeSelect, "review", messages.agent.review);
2056
+ if (trustedFastModeAvailable) {
2057
+ trustedOption = addOption(
2058
+ document,
2059
+ modeSelect,
2060
+ "trusted-auto",
2061
+ messages.agent.trustedFast
2062
+ );
2063
+ }
2064
+ }
2065
+ const defaultApplyMode = trustedFastModeAvailable ? "review" : configuredApplyMode;
2066
+ modeSelect.value = defaultApplyMode;
2067
+ modeLabel.hidden = !trustedFastModeAvailable;
2068
+ const selectedApplyMode = () => modeSelect.value === "trusted-auto" ? "trusted-auto" : defaultApplyMode;
2069
+ const trustedFastMode = () => selectedApplyMode() === "trusted-auto";
2036
2070
  const selectedProvider = () => providerById.get(providerSelect.value);
2037
2071
  const consentMessage = (provider) => {
2038
2072
  if (provider === void 0) {
2039
2073
  return messages.agent.providerUnavailable;
2040
2074
  }
2041
- return trustedFastMode ? messages.agent.trustedFastConsent(provider.label) : messages.agent.consent(provider.label);
2075
+ return trustedFastMode() ? messages.agent.trustedFastConsent(provider.label) : messages.agent.consent(provider.label);
2076
+ };
2077
+ const localChangesConsentGranted = () => trustedFastMode() ? consentCheckbox.checked : workspaceConsentCheckbox.checked;
2078
+ const renderMode = () => {
2079
+ const trusted = trustedFastMode();
2080
+ consent.classList.toggle("spotpatch-trusted-consent", trusted);
2081
+ badge.textContent = trusted ? messages.agent.trustedFast : configuredApplyMode === "auto" ? messages.agent.autoGated : messages.agent.review;
2082
+ consentText.textContent = consentMessage(selectedProvider());
2083
+ workspaceConsent.hidden = trusted || latestWorkspaceState !== "consent-required";
2042
2084
  };
2043
- const localChangesConsentGranted = () => trustedFastMode ? consentCheckbox.checked : workspaceConsentCheckbox.checked;
2044
2085
  const populateModels = () => {
2045
2086
  const provider = selectedProvider();
2046
2087
  modelSelect.replaceChildren();
@@ -2107,7 +2148,14 @@ function createAgentPanel(document, ai, localizer) {
2107
2148
  capabilityReady = false;
2108
2149
  refreshActions();
2109
2150
  }
2151
+ function handleModeChange() {
2152
+ consentCheckbox.checked = false;
2153
+ workspaceConsentCheckbox.checked = false;
2154
+ renderMode();
2155
+ refreshActions();
2156
+ }
2110
2157
  populateModels();
2158
+ modeSelect.addEventListener("change", handleModeChange);
2111
2159
  providerSelect.addEventListener("change", handleProviderChange);
2112
2160
  modelSelect.addEventListener("change", handleModelChange);
2113
2161
  consentCheckbox.addEventListener("change", refreshActions);
@@ -2161,7 +2209,11 @@ function createAgentPanel(document, ai, localizer) {
2161
2209
  function applyMessages() {
2162
2210
  messages = localizer.messages();
2163
2211
  title.textContent = messages.agent.title;
2164
- badge.textContent = trustedFastMode ? messages.agent.trustedFast : ai.enabled && ai.applyMode === "auto" ? messages.agent.autoGated : messages.agent.review;
2212
+ modeText.textContent = messages.agent.mode;
2213
+ if (reviewOption !== void 0) reviewOption.textContent = messages.agent.review;
2214
+ if (trustedOption !== void 0)
2215
+ trustedOption.textContent = messages.agent.trustedFast;
2216
+ if (autoOption !== void 0) autoOption.textContent = messages.agent.autoGated;
2165
2217
  providerText.textContent = messages.agent.provider;
2166
2218
  modelText.textContent = messages.agent.model;
2167
2219
  providerSelect.setAttribute("aria-label", messages.agent.providerAriaLabel);
@@ -2173,8 +2225,7 @@ function createAgentPanel(document, ai, localizer) {
2173
2225
  applyButton.textContent = messages.agent.apply;
2174
2226
  revertButton.textContent = messages.agent.revert;
2175
2227
  resetButton.textContent = messages.agent.revise;
2176
- const provider = selectedProvider();
2177
- consentText.textContent = consentMessage(provider);
2228
+ renderMode();
2178
2229
  if (latestCapabilityState === "idle") {
2179
2230
  capability.textContent = messages.agent.connectionNotTested;
2180
2231
  } else if (latestCapabilityState === "probing") {
@@ -2196,6 +2247,7 @@ function createAgentPanel(document, ai, localizer) {
2196
2247
  applyMessages();
2197
2248
  return Object.freeze({
2198
2249
  root,
2250
+ modeSelect,
2199
2251
  providerSelect,
2200
2252
  modelSelect,
2201
2253
  consentCheckbox,
@@ -2218,6 +2270,7 @@ function createAgentPanel(document, ai, localizer) {
2218
2270
  (candidate) => candidate.id === modelSelect.value
2219
2271
  );
2220
2272
  return provider === void 0 || model === void 0 ? void 0 : Object.freeze({
2273
+ applyMode: selectedApplyMode(),
2221
2274
  providerProfileId: provider.id,
2222
2275
  modelProfileId: model.id
2223
2276
  });
@@ -2238,7 +2291,7 @@ function createAgentPanel(document, ai, localizer) {
2238
2291
  latestWorkspaceErrorCode = errorCode ?? snapshot?.errorCode;
2239
2292
  workspace.dataset.state = state;
2240
2293
  if (state !== "checking") {
2241
- workspaceConsent.hidden = trustedFastMode || state !== "consent-required";
2294
+ workspaceConsent.hidden = trustedFastMode() || state !== "consent-required";
2242
2295
  }
2243
2296
  if (state === "idle" || state === "ready" || state === "blocked") {
2244
2297
  workspaceConsentCheckbox.checked = false;
@@ -2252,6 +2305,7 @@ function createAgentPanel(document, ai, localizer) {
2252
2305
  job.hidden = false;
2253
2306
  providerSelect.disabled = true;
2254
2307
  modelSelect.disabled = true;
2308
+ modeSelect.disabled = true;
2255
2309
  consentCheckbox.disabled = true;
2256
2310
  workspaceConsentCheckbox.disabled = true;
2257
2311
  latestSnapshot = snapshot;
@@ -2270,6 +2324,7 @@ function createAgentPanel(document, ai, localizer) {
2270
2324
  job.hidden = true;
2271
2325
  providerSelect.disabled = false;
2272
2326
  modelSelect.disabled = false;
2327
+ modeSelect.disabled = false;
2273
2328
  consentCheckbox.disabled = false;
2274
2329
  workspaceConsentCheckbox.disabled = false;
2275
2330
  activity.replaceChildren();
@@ -2288,6 +2343,7 @@ function createAgentPanel(document, ai, localizer) {
2288
2343
  editingEnabled = enabled;
2289
2344
  providerSelect.disabled = !enabled || jobPresented;
2290
2345
  modelSelect.disabled = !enabled || jobPresented;
2346
+ modeSelect.disabled = !enabled || jobPresented;
2291
2347
  consentCheckbox.disabled = !enabled || jobPresented;
2292
2348
  workspaceConsentCheckbox.disabled = !enabled || jobPresented;
2293
2349
  refreshActions();
@@ -2310,6 +2366,7 @@ function createAgentPanel(document, ai, localizer) {
2310
2366
  unsubscribeLocale();
2311
2367
  providerSelect.removeEventListener("change", handleProviderChange);
2312
2368
  modelSelect.removeEventListener("change", handleModelChange);
2369
+ modeSelect.removeEventListener("change", handleModeChange);
2313
2370
  consentCheckbox.removeEventListener("change", refreshActions);
2314
2371
  workspaceConsentCheckbox.removeEventListener("change", refreshActions);
2315
2372
  }
@@ -2715,6 +2772,7 @@ var UI_MESSAGES = Object.freeze({
2715
2772
  }),
2716
2773
  agent: Object.freeze({
2717
2774
  title: "AI code agent",
2775
+ mode: "Execution mode",
2718
2776
  review: "Review",
2719
2777
  autoGated: "Auto gated",
2720
2778
  trustedFast: "Trusted fast",
@@ -2852,6 +2910,7 @@ var UI_MESSAGES = Object.freeze({
2852
2910
  }),
2853
2911
  agent: Object.freeze({
2854
2912
  title: "AI \u4EE3\u7801 Agent",
2913
+ mode: "\u6267\u884C\u65B9\u5F0F",
2855
2914
  review: "\u5BA1\u9605\u6A21\u5F0F",
2856
2915
  autoGated: "\u53D7\u63A7\u81EA\u52A8\u6A21\u5F0F",
2857
2916
  trustedFast: "\u53EF\u4FE1\u5FEB\u901F\u6A21\u5F0F",
@@ -4216,6 +4275,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
4216
4275
  closeButton,
4217
4276
  agentProviderSelect: agentPanel.providerSelect,
4218
4277
  agentModelSelect: agentPanel.modelSelect,
4278
+ agentModeSelect: agentPanel.modeSelect,
4219
4279
  agentConsentCheckbox: agentPanel.consentCheckbox,
4220
4280
  agentWorkspaceConsentCheckbox: agentPanel.workspaceConsentCheckbox,
4221
4281
  agentTestButton: agentPanel.testButton,
@@ -4459,6 +4519,7 @@ function createAgentWorkflow(options) {
4459
4519
  let appliedDuringCurrentJob = false;
4460
4520
  let actionPending = false;
4461
4521
  const selectedProfiles = () => options.view.readAgentSelection();
4522
+ const consentKey = (selection) => `${selection.providerProfileId}:${selection.applyMode}`;
4462
4523
  const refreshWorkspaceHealth = async (workflowRevision) => {
4463
4524
  options.view.renderAgentWorkspaceHealth("checking");
4464
4525
  try {
@@ -4496,9 +4557,7 @@ function createAgentWorkflow(options) {
4496
4557
  );
4497
4558
  return;
4498
4559
  }
4499
- options.view.setAgentProviderConsent(
4500
- providerConsents.has(selection.providerProfileId)
4501
- );
4560
+ options.view.setAgentProviderConsent(providerConsents.has(consentKey(selection)));
4502
4561
  const cached = capabilities.get(
4503
4562
  capabilityKey(selection.providerProfileId, selection.modelProfileId)
4504
4563
  );
@@ -4666,9 +4725,9 @@ function createAgentWorkflow(options) {
4666
4725
  return;
4667
4726
  }
4668
4727
  if (options.view.agentConsentGranted()) {
4669
- providerConsents.add(selection.providerProfileId);
4728
+ providerConsents.add(consentKey(selection));
4670
4729
  } else {
4671
- providerConsents.delete(selection.providerProfileId);
4730
+ providerConsents.delete(consentKey(selection));
4672
4731
  }
4673
4732
  },
4674
4733
  disposeSelection() {
@@ -4708,7 +4767,6 @@ function createAgentWorkflow(options) {
4708
4767
  if (!options.ai.enabled || snapshot !== void 0) {
4709
4768
  return;
4710
4769
  }
4711
- const trustedFastMode = options.ai.applyMode === "trusted-auto";
4712
4770
  const selection = selectedProfiles();
4713
4771
  const annotation = options.getAnnotation();
4714
4772
  if (selection === void 0 || annotation === void 0) {
@@ -4721,7 +4779,7 @@ function createAgentWorkflow(options) {
4721
4779
  options.view.announce(options.view.messages().agent.consentRequired);
4722
4780
  return;
4723
4781
  }
4724
- providerConsents.add(selection.providerProfileId);
4782
+ providerConsents.add(consentKey(selection));
4725
4783
  const workflowRevision = ++revision;
4726
4784
  options.view.setAgentEditingEnabled(false);
4727
4785
  void refreshWorkspaceHealth(workflowRevision).then(async (health) => {
@@ -4738,10 +4796,11 @@ function createAgentWorkflow(options) {
4738
4796
  }
4739
4797
  const created = await options.api.createAgentJob({
4740
4798
  annotation,
4799
+ applyMode: selection.applyMode,
4741
4800
  providerProfileId: selection.providerProfileId,
4742
4801
  modelProfileId: selection.modelProfileId,
4743
4802
  providerDataConsent: true,
4744
- ...trustedFastMode ? { trustedFastModeConsent: true } : {},
4803
+ ...selection.applyMode === "trusted-auto" ? { trustedFastModeConsent: true } : {},
4745
4804
  workingTreeMode: health.state === "consent-required" ? "include-local-changes" : "require-clean"
4746
4805
  });
4747
4806
  if (workflowRevision !== revision) {
@@ -5638,6 +5697,10 @@ ${summary}`;
5638
5697
  "change",
5639
5698
  agentWorkflow.providerOrModelChanged
5640
5699
  );
5700
+ view.agentModeSelect.addEventListener(
5701
+ "change",
5702
+ agentWorkflow.providerOrModelChanged
5703
+ );
5641
5704
  view.agentConsentCheckbox.addEventListener("change", agentWorkflow.consentChanged);
5642
5705
  view.agentTestButton.addEventListener("click", agentWorkflow.testCapability);
5643
5706
  view.agentRunButton.addEventListener("click", agentWorkflow.run);
@@ -5704,6 +5767,10 @@ ${summary}`;
5704
5767
  "change",
5705
5768
  agentWorkflow.providerOrModelChanged
5706
5769
  );
5770
+ view.agentModeSelect.removeEventListener(
5771
+ "change",
5772
+ agentWorkflow.providerOrModelChanged
5773
+ );
5707
5774
  view.agentConsentCheckbox.removeEventListener(
5708
5775
  "change",
5709
5776
  agentWorkflow.consentChanged