@spotpatch/runtime 1.5.1 → 1.6.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 CHANGED
@@ -1810,6 +1810,13 @@ var AGENT_PANEL_STYLES = `
1810
1810
  line-height: 1.5;
1811
1811
  }
1812
1812
  .spotpatch-consent input { width: 14px; height: 14px; flex: none; margin: 2px 0 0; accent-color: var(--spotpatch-accent); }
1813
+ .spotpatch-trusted-consent {
1814
+ border: 1px solid rgb(251 191 36 / 20%);
1815
+ border-radius: 10px;
1816
+ padding: 9px 10px;
1817
+ color: #e5e7eb;
1818
+ background: rgb(120 53 15 / 10%);
1819
+ }
1813
1820
  .spotpatch-workspace-consent {
1814
1821
  margin-top: 9px;
1815
1822
  border: 1px solid rgb(251 191 36 / 18%);
@@ -1999,16 +2006,14 @@ function createAgentPanel(document, ai, localizer) {
1999
2006
  job.append(jobMeta, phase, error, activity, resultPanel);
2000
2007
  root.append(header, setup, job);
2001
2008
  const testButton = createButton(document, messages.agent.testConnection);
2002
- const runButton = createButton(
2003
- document,
2004
- messages.agent.verifyAndRun,
2005
- "spotpatch-run"
2006
- );
2009
+ const runButton = createButton(document, messages.agent.run, "spotpatch-run");
2007
2010
  const cancelButton = createButton(document, messages.agent.cancel);
2008
2011
  const applyButton = createButton(document, messages.agent.apply, "spotpatch-primary");
2009
2012
  const revertButton = createButton(document, messages.agent.revert);
2010
2013
  const resetButton = createButton(document, messages.agent.revise);
2011
2014
  const providers = ai.enabled ? ai.providers : [];
2015
+ const trustedFastMode = ai.enabled && ai.applyMode === "trusted-auto";
2016
+ consent.classList.toggle("spotpatch-trusted-consent", trustedFastMode);
2012
2017
  const providerById = new Map(providers.map((provider) => [provider.id, provider]));
2013
2018
  let contextReady = false;
2014
2019
  let editingEnabled = true;
@@ -2033,27 +2038,34 @@ function createAgentPanel(document, ai, localizer) {
2033
2038
  providerSelect.value = ai.defaultProvider;
2034
2039
  }
2035
2040
  const selectedProvider = () => providerById.get(providerSelect.value);
2041
+ const consentMessage = (provider) => {
2042
+ if (provider === void 0) {
2043
+ return messages.agent.providerUnavailable;
2044
+ }
2045
+ return trustedFastMode ? messages.agent.trustedFastConsent(provider.label) : messages.agent.consent(provider.label);
2046
+ };
2047
+ const localChangesConsentGranted = () => trustedFastMode ? consentCheckbox.checked : workspaceConsentCheckbox.checked;
2036
2048
  const populateModels = () => {
2037
2049
  const provider = selectedProvider();
2038
2050
  modelSelect.replaceChildren();
2039
2051
  if (provider === void 0) {
2040
- consentText.textContent = messages.agent.providerUnavailable;
2052
+ consentText.textContent = consentMessage(provider);
2041
2053
  return;
2042
2054
  }
2043
2055
  for (const model of provider.models) {
2044
2056
  addOption(document, modelSelect, model.id, model.label);
2045
2057
  }
2046
2058
  modelSelect.value = provider.defaultModel;
2047
- consentText.textContent = messages.agent.consent(provider.label);
2059
+ consentText.textContent = consentMessage(provider);
2048
2060
  };
2049
2061
  const refreshActions = () => {
2050
2062
  const setupVisible = ai.enabled && selectionVisible && !jobPresented;
2051
- runButton.textContent = capabilityProbing ? messages.agent.verifying : capabilityReady ? messages.agent.run : messages.agent.verifyAndRun;
2063
+ runButton.textContent = capabilityProbing ? messages.agent.verifying : messages.agent.run;
2052
2064
  runButton.classList.toggle("spotpatch-primary", capabilityReady);
2053
2065
  testButton.hidden = !setupVisible;
2054
2066
  runButton.hidden = !setupVisible;
2055
2067
  testButton.disabled = !editingEnabled || capabilityProbing || selectedProvider() === void 0;
2056
- runButton.disabled = !editingEnabled || capabilityProbing || !contextReady || !consentCheckbox.checked || latestWorkspaceState === "idle" || latestWorkspaceState === "checking" || latestWorkspaceState === "blocked" || latestWorkspaceState === "consent-required" && !workspaceConsentCheckbox.checked || selectedProvider() === void 0 || modelSelect.value.length === 0;
2068
+ runButton.disabled = !editingEnabled || capabilityProbing || !contextReady || !consentCheckbox.checked || latestWorkspaceState === "idle" || latestWorkspaceState === "checking" || latestWorkspaceState === "blocked" || latestWorkspaceState === "consent-required" && !localChangesConsentGranted() || selectedProvider() === void 0 || modelSelect.value.length === 0;
2057
2069
  if (!jobPresented || !selectionVisible) {
2058
2070
  cancelButton.hidden = true;
2059
2071
  applyButton.hidden = true;
@@ -2153,7 +2165,7 @@ function createAgentPanel(document, ai, localizer) {
2153
2165
  function applyMessages() {
2154
2166
  messages = localizer.messages();
2155
2167
  title.textContent = messages.agent.title;
2156
- badge.textContent = ai.enabled && ai.applyMode === "auto" ? messages.agent.autoGated : messages.agent.review;
2168
+ badge.textContent = trustedFastMode ? messages.agent.trustedFast : ai.enabled && ai.applyMode === "auto" ? messages.agent.autoGated : messages.agent.review;
2157
2169
  providerText.textContent = messages.agent.provider;
2158
2170
  modelText.textContent = messages.agent.model;
2159
2171
  providerSelect.setAttribute("aria-label", messages.agent.providerAriaLabel);
@@ -2166,7 +2178,7 @@ function createAgentPanel(document, ai, localizer) {
2166
2178
  revertButton.textContent = messages.agent.revert;
2167
2179
  resetButton.textContent = messages.agent.revise;
2168
2180
  const provider = selectedProvider();
2169
- consentText.textContent = provider === void 0 ? messages.agent.providerUnavailable : messages.agent.consent(provider.label);
2181
+ consentText.textContent = consentMessage(provider);
2170
2182
  if (latestCapabilityState === "idle") {
2171
2183
  capability.textContent = messages.agent.connectionNotTested;
2172
2184
  } else if (latestCapabilityState === "probing") {
@@ -2202,7 +2214,7 @@ function createAgentPanel(document, ai, localizer) {
2202
2214
  return consentCheckbox.checked;
2203
2215
  },
2204
2216
  workspaceConsentGranted() {
2205
- return workspaceConsentCheckbox.checked;
2217
+ return localChangesConsentGranted();
2206
2218
  },
2207
2219
  readSelection() {
2208
2220
  const provider = selectedProvider();
@@ -2230,7 +2242,7 @@ function createAgentPanel(document, ai, localizer) {
2230
2242
  latestWorkspaceErrorCode = errorCode ?? snapshot?.errorCode;
2231
2243
  workspace.dataset.state = state;
2232
2244
  if (state !== "checking") {
2233
- workspaceConsent.hidden = state !== "consent-required";
2245
+ workspaceConsent.hidden = trustedFastMode || state !== "consent-required";
2234
2246
  }
2235
2247
  if (state === "idle" || state === "ready" || state === "blocked") {
2236
2248
  workspaceConsentCheckbox.checked = false;
@@ -2498,7 +2510,7 @@ var ERROR_MESSAGES_EN = Object.freeze({
2498
2510
  [import_shared6.ERROR_CODES.PROVIDER_AUTH_FAILED]: "The provider rejected authentication. Check the server-side Key.",
2499
2511
  [import_shared6.ERROR_CODES.PROVIDER_PROTOCOL_UNSUPPORTED]: "The relay does not match the configured OpenAI-compatible protocol.",
2500
2512
  [import_shared6.ERROR_CODES.MODEL_NOT_ALLOWED]: "The selected model profile is not allowed.",
2501
- [import_shared6.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "The selected model did not complete the required tool-call probe.",
2513
+ [import_shared6.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "The selected model did not start or continue the required tool call.",
2502
2514
  [import_shared6.ERROR_CODES.PROVIDER_RATE_LIMITED]: "The provider is rate limited. Wait and try again.",
2503
2515
  [import_shared6.ERROR_CODES.AGENT_BUSY]: "Another write Agent job is still active.",
2504
2516
  [import_shared6.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: "The Agent stopped at a configured time, turn, output, or size limit.",
@@ -2533,7 +2545,7 @@ var ERROR_MESSAGES_ZH = Object.freeze({
2533
2545
  [import_shared6.ERROR_CODES.PROVIDER_AUTH_FAILED]: "\u6A21\u578B\u670D\u52A1\u9274\u6743\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u670D\u52A1\u7AEF Key\u3002",
2534
2546
  [import_shared6.ERROR_CODES.PROVIDER_PROTOCOL_UNSUPPORTED]: "\u4E2D\u8F6C\u670D\u52A1\u4E0E\u914D\u7F6E\u7684 OpenAI \u517C\u5BB9\u534F\u8BAE\u4E0D\u4E00\u81F4\u3002",
2535
2547
  [import_shared6.ERROR_CODES.MODEL_NOT_ALLOWED]: "\u5F53\u524D\u6A21\u578B\u914D\u7F6E\u672A\u83B7\u6388\u6743\u3002",
2536
- [import_shared6.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "\u5F53\u524D\u6A21\u578B\u672A\u901A\u8FC7\u5FC5\u8981\u7684\u5DE5\u5177\u8C03\u7528\u80FD\u529B\u63A2\u6D4B\u3002",
2548
+ [import_shared6.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "\u5F53\u524D\u6A21\u578B\u672A\u5B8C\u6210\u5FC5\u8981\u7684\u5DE5\u5177\u8C03\u7528\u6216\u7ED3\u679C\u7EED\u63A5\u3002",
2537
2549
  [import_shared6.ERROR_CODES.PROVIDER_RATE_LIMITED]: "\u6A21\u578B\u670D\u52A1\u6B63\u5728\u9650\u6D41\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
2538
2550
  [import_shared6.ERROR_CODES.AGENT_BUSY]: "\u5F53\u524D\u9879\u76EE\u5DF2\u6709\u4E00\u4E2A\u5199\u5165\u4EFB\u52A1\u6B63\u5728\u8FD0\u884C\u3002",
2539
2551
  [import_shared6.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: "Agent \u8FBE\u5230\u65F6\u95F4\u3001\u8F6E\u6B21\u3001\u8F93\u51FA\u6216\u53D8\u66F4\u89C4\u6A21\u9650\u5236\u3002",
@@ -2707,13 +2719,15 @@ var UI_MESSAGES = Object.freeze({
2707
2719
  title: "AI code agent",
2708
2720
  review: "Review",
2709
2721
  autoGated: "Auto gated",
2722
+ trustedFast: "Trusted fast",
2710
2723
  provider: "Provider",
2711
2724
  model: "Model",
2712
2725
  providerAriaLabel: "AI provider",
2713
2726
  modelAriaLabel: "AI model",
2714
2727
  providerUnavailable: "Provider configuration is unavailable.",
2715
2728
  consent: (provider) => `I understand selected context and allowed source may be sent to ${provider}; its data policy is my responsibility.`,
2716
- connectionNotTested: "Connection not tested",
2729
+ trustedFastConsent: (provider) => `Enable trusted fast mode for ${provider}: send allowed project context, include current local changes, and directly apply AI changes after required checks, including file deletions and configuration changes.`,
2730
+ connectionNotTested: "Optional connection check not run",
2717
2731
  workspaceNotChecked: "Local workspace not checked",
2718
2732
  checkingWorkspace: "Checking Git workspace and isolated execution\u2026",
2719
2733
  workspaceReady: "Local workspace is ready for isolated execution",
@@ -2730,7 +2744,6 @@ var UI_MESSAGES = Object.freeze({
2730
2744
  consentRequired: "Confirm remote provider data transmission before running AI.",
2731
2745
  toolsReady: "tools and streaming ready",
2732
2746
  testConnection: "Check environment",
2733
- verifyAndRun: "Verify & run",
2734
2747
  verifying: "Verifying\u2026",
2735
2748
  run: "Run AI",
2736
2749
  cancel: "Cancel agent",
@@ -2843,13 +2856,15 @@ var UI_MESSAGES = Object.freeze({
2843
2856
  title: "AI \u4EE3\u7801 Agent",
2844
2857
  review: "\u5BA1\u9605\u6A21\u5F0F",
2845
2858
  autoGated: "\u53D7\u63A7\u81EA\u52A8\u6A21\u5F0F",
2859
+ trustedFast: "\u53EF\u4FE1\u5FEB\u901F\u6A21\u5F0F",
2846
2860
  provider: "\u6A21\u578B\u670D\u52A1",
2847
2861
  model: "\u6A21\u578B",
2848
2862
  providerAriaLabel: "AI \u6A21\u578B\u670D\u52A1",
2849
2863
  modelAriaLabel: "AI \u6A21\u578B",
2850
2864
  providerUnavailable: "\u6A21\u578B\u670D\u52A1\u914D\u7F6E\u4E0D\u53EF\u7528\u3002",
2851
2865
  consent: (provider) => `\u6211\u4E86\u89E3\u9009\u4E2D\u4E0A\u4E0B\u6587\u4E0E\u83B7\u51C6\u6E90\u7801\u53EF\u80FD\u53D1\u9001\u5230 ${provider}\uFF0C\u5E76\u81EA\u884C\u8D1F\u8D23\u5176\u6570\u636E\u7B56\u7565\u3002`,
2852
- connectionNotTested: "\u5C1A\u672A\u6D4B\u8BD5\u8FDE\u63A5",
2866
+ trustedFastConsent: (provider) => `\u4E3A ${provider} \u542F\u7528\u53EF\u4FE1\u5FEB\u901F\u6A21\u5F0F\uFF1A\u53D1\u9001\u83B7\u51C6\u7684\u9879\u76EE\u4E0A\u4E0B\u6587\u3001\u7EB3\u5165\u5F53\u524D\u672C\u5730\u4FEE\u6539\uFF0C\u5E76\u5728\u5FC5\u9700\u68C0\u67E5\u901A\u8FC7\u540E\u76F4\u63A5\u5E94\u7528 AI \u53D8\u66F4\uFF0C\u5305\u62EC\u5220\u9664\u6587\u4EF6\u4E0E\u914D\u7F6E\u53D8\u66F4\u3002`,
2867
+ connectionNotTested: "\u5C1A\u672A\u6267\u884C\u53EF\u9009\u8FDE\u63A5\u68C0\u67E5",
2853
2868
  workspaceNotChecked: "\u5C1A\u672A\u68C0\u67E5\u672C\u5730\u5DE5\u4F5C\u533A",
2854
2869
  checkingWorkspace: "\u6B63\u5728\u68C0\u67E5 Git \u5DE5\u4F5C\u533A\u4E0E\u9694\u79BB\u6267\u884C\u73AF\u5883\u2026\u2026",
2855
2870
  workspaceReady: "\u672C\u5730\u5DE5\u4F5C\u533A\u5DF2\u6EE1\u8DB3\u9694\u79BB\u6267\u884C\u6761\u4EF6",
@@ -2866,7 +2881,6 @@ var UI_MESSAGES = Object.freeze({
2866
2881
  consentRequired: "\u8FD0\u884C AI \u524D\uFF0C\u8BF7\u5148\u786E\u8BA4\u5141\u8BB8\u5411\u8FDC\u7A0B\u6A21\u578B\u670D\u52A1\u4F20\u8F93\u6570\u636E\u3002",
2867
2882
  toolsReady: "\u5DE5\u5177\u8C03\u7528\u4E0E\u6D41\u5F0F\u54CD\u5E94\u5DF2\u5C31\u7EEA",
2868
2883
  testConnection: "\u68C0\u67E5\u8FD0\u884C\u73AF\u5883",
2869
- verifyAndRun: "\u9A8C\u8BC1\u5E76\u8FD0\u884C",
2870
2884
  verifying: "\u9A8C\u8BC1\u4E2D\u2026\u2026",
2871
2885
  run: "\u8FD0\u884C AI",
2872
2886
  cancel: "\u53D6\u6D88 Agent",
@@ -4694,6 +4708,7 @@ function createAgentWorkflow(options) {
4694
4708
  if (!options.ai.enabled || snapshot !== void 0) {
4695
4709
  return;
4696
4710
  }
4711
+ const trustedFastMode = options.ai.applyMode === "trusted-auto";
4697
4712
  const selection = selectedProfiles();
4698
4713
  const annotation = options.getAnnotation();
4699
4714
  if (selection === void 0 || annotation === void 0) {
@@ -4709,10 +4724,7 @@ function createAgentWorkflow(options) {
4709
4724
  providerConsents.add(selection.providerProfileId);
4710
4725
  const workflowRevision = ++revision;
4711
4726
  options.view.setAgentEditingEnabled(false);
4712
- void Promise.all([
4713
- probe(workflowRevision),
4714
- refreshWorkspaceHealth(workflowRevision)
4715
- ]).then(async ([, health]) => {
4727
+ void refreshWorkspaceHealth(workflowRevision).then(async (health) => {
4716
4728
  if (workflowRevision !== revision) {
4717
4729
  return;
4718
4730
  }
@@ -4729,6 +4741,7 @@ function createAgentWorkflow(options) {
4729
4741
  providerProfileId: selection.providerProfileId,
4730
4742
  modelProfileId: selection.modelProfileId,
4731
4743
  providerDataConsent: true,
4744
+ ...trustedFastMode ? { trustedFastModeConsent: true } : {},
4732
4745
  workingTreeMode: health.state === "consent-required" ? "include-local-changes" : "require-clean"
4733
4746
  });
4734
4747
  if (workflowRevision !== revision) {