@spotpatch/runtime 1.1.2 → 1.2.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 +266 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +266 -14
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -157,6 +157,35 @@ function isAgentCapabilitySnapshot(value) {
|
|
|
157
157
|
}
|
|
158
158
|
return isProfileId(value.providerProfileId) && isBoundedString(value.providerLabel, 100) && isProfileId(value.modelProfileId) && isBoundedString(value.modelLabel, 100) && (value.protocol === "responses" || value.protocol === "chat-completions") && typeof value.state === "string" && CAPABILITY_STATE_VALUES.has(value.state) && typeof value.authenticated === "boolean" && typeof value.modelAvailable === "boolean" && typeof value.toolCalling === "boolean" && typeof value.toolResultContinuation === "boolean" && typeof value.streaming === "boolean" && (value.checkedAt === void 0 || isIsoTimestamp(value.checkedAt)) && (value.errorCode === void 0 || isAgentErrorCode(value.errorCode));
|
|
159
159
|
}
|
|
160
|
+
function isAgentWorkspaceHealthSnapshot(value) {
|
|
161
|
+
if (!isRecord(value) || !hasOnlyKeys(value, [
|
|
162
|
+
"state",
|
|
163
|
+
"checkedAt",
|
|
164
|
+
"changes",
|
|
165
|
+
"canIncludeLocalChanges",
|
|
166
|
+
"errorCode"
|
|
167
|
+
]) || value.state !== "ready" && value.state !== "consent-required" && value.state !== "blocked" || !isIsoTimestamp(value.checkedAt) || typeof value.canIncludeLocalChanges !== "boolean" || value.errorCode !== void 0 && !isAgentErrorCode(value.errorCode) || !isRecord(value.changes) || !hasOnlyKeys(value.changes, [
|
|
168
|
+
"staged",
|
|
169
|
+
"unstaged",
|
|
170
|
+
"untracked",
|
|
171
|
+
"conflicted",
|
|
172
|
+
"total"
|
|
173
|
+
])) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
const changes = value.changes;
|
|
177
|
+
const { staged, unstaged, untracked, conflicted, total } = changes;
|
|
178
|
+
if (!isNonnegativeInteger(staged) || !isNonnegativeInteger(unstaged) || !isNonnegativeInteger(untracked) || !isNonnegativeInteger(conflicted) || !isNonnegativeInteger(total) || total < staged || total < unstaged || total < untracked || total < conflicted || total > staged + unstaged + untracked) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (value.state === "ready") {
|
|
182
|
+
return total === 0 && !value.canIncludeLocalChanges && value.errorCode === void 0;
|
|
183
|
+
}
|
|
184
|
+
if (value.state === "consent-required") {
|
|
185
|
+
return total > 0 && conflicted === 0 && value.canIncludeLocalChanges && value.errorCode === void 0;
|
|
186
|
+
}
|
|
187
|
+
return !value.canIncludeLocalChanges && value.errorCode !== void 0;
|
|
188
|
+
}
|
|
160
189
|
function isAgentJobSnapshot(value) {
|
|
161
190
|
if (!isRecord(value) || !hasOnlyKeys(value, [
|
|
162
191
|
"jobId",
|
|
@@ -497,6 +526,17 @@ function createRuntimeApi(options) {
|
|
|
497
526
|
request
|
|
498
527
|
);
|
|
499
528
|
},
|
|
529
|
+
async agentWorkspaceHealth() {
|
|
530
|
+
const data = await requestJson(
|
|
531
|
+
import_shared3.SPOTPATCH_ENDPOINTS.agentWorkspaceHealth,
|
|
532
|
+
"POST",
|
|
533
|
+
emptyAction
|
|
534
|
+
);
|
|
535
|
+
if (!isAgentWorkspaceHealthSnapshot(data)) {
|
|
536
|
+
throw new RuntimeApiError();
|
|
537
|
+
}
|
|
538
|
+
return deepFreeze(data);
|
|
539
|
+
},
|
|
500
540
|
async createAgentJob(request) {
|
|
501
541
|
const serverRequest = omitBrowserCodeContext(request);
|
|
502
542
|
return parseJobSnapshot(
|
|
@@ -1567,15 +1607,62 @@ var AGENT_PANEL_STYLES = `
|
|
|
1567
1607
|
min-height: 46px;
|
|
1568
1608
|
margin-top: 7px;
|
|
1569
1609
|
border: 1px solid var(--spotpatch-border);
|
|
1570
|
-
border-radius:
|
|
1571
|
-
padding:
|
|
1610
|
+
border-radius: 12px;
|
|
1611
|
+
padding: 10px 38px 10px 13px;
|
|
1572
1612
|
color: #e8ebf2;
|
|
1573
1613
|
color-scheme: dark;
|
|
1574
|
-
background:
|
|
1614
|
+
background: linear-gradient(180deg, rgb(255 255 255 / 4%), rgb(255 255 255 / 2%));
|
|
1575
1615
|
font-size: 15px;
|
|
1616
|
+
font-weight: 560;
|
|
1617
|
+
line-height: 1.35;
|
|
1576
1618
|
outline: none;
|
|
1619
|
+
transition: 160ms ease;
|
|
1620
|
+
}
|
|
1621
|
+
.spotpatch-agent select:hover { border-color: rgb(148 163 184 / 38%); background-color: rgb(255 255 255 / 5%); }
|
|
1622
|
+
.spotpatch-agent select:focus-visible { border-color: rgb(139 124 247 / 76%); box-shadow: 0 0 0 3px rgb(109 93 246 / 18%); }
|
|
1623
|
+
.spotpatch-agent select option { min-height: 42px; color: #e8ebf2; background: #10151e; }
|
|
1624
|
+
@supports (appearance: base-select) {
|
|
1625
|
+
.spotpatch-agent select,
|
|
1626
|
+
::picker(select) { appearance: base-select; }
|
|
1627
|
+
.spotpatch-agent select { padding: 10px 13px; }
|
|
1628
|
+
.spotpatch-agent select::picker-icon {
|
|
1629
|
+
color: #9da6b5;
|
|
1630
|
+
transition: rotate 180ms cubic-bezier(.2, .8, .2, 1);
|
|
1631
|
+
}
|
|
1632
|
+
.spotpatch-agent select:open::picker-icon { rotate: 180deg; color: #c4b5fd; }
|
|
1633
|
+
.spotpatch-agent select::picker(select) {
|
|
1634
|
+
top: calc(anchor(bottom) + 7px);
|
|
1635
|
+
left: anchor(left);
|
|
1636
|
+
width: anchor-size(width);
|
|
1637
|
+
max-height: min(280px, 40vh);
|
|
1638
|
+
margin: 0;
|
|
1639
|
+
overflow: hidden;
|
|
1640
|
+
border: 1px solid rgb(139 124 247 / 28%);
|
|
1641
|
+
border-radius: 12px;
|
|
1642
|
+
padding: 6px;
|
|
1643
|
+
background: #10151e;
|
|
1644
|
+
box-shadow: 0 18px 50px rgb(0 0 0 / 38%);
|
|
1645
|
+
opacity: 0;
|
|
1646
|
+
transform: translateY(-5px) scale(.985);
|
|
1647
|
+
transition: opacity 150ms ease, transform 180ms cubic-bezier(.2, .8, .2, 1), overlay 180ms allow-discrete, display 180ms allow-discrete;
|
|
1648
|
+
}
|
|
1649
|
+
::picker(select):popover-open { opacity: 1; transform: translateY(0) scale(1); }
|
|
1650
|
+
@starting-style {
|
|
1651
|
+
::picker(select):popover-open { opacity: 0; transform: translateY(-5px) scale(.985); }
|
|
1652
|
+
}
|
|
1653
|
+
.spotpatch-agent select option {
|
|
1654
|
+
min-height: 42px;
|
|
1655
|
+
border-radius: 8px;
|
|
1656
|
+
padding: 10px 12px;
|
|
1657
|
+
color: #dfe4ee;
|
|
1658
|
+
background: transparent;
|
|
1659
|
+
cursor: pointer;
|
|
1660
|
+
}
|
|
1661
|
+
.spotpatch-agent select option:hover,
|
|
1662
|
+
.spotpatch-agent select option:focus { color: #fff; background: rgb(109 93 246 / 16%); }
|
|
1663
|
+
.spotpatch-agent select option:checked { color: #fff; background: rgb(109 93 246 / 24%); }
|
|
1664
|
+
.spotpatch-agent select option::checkmark { color: #8b7cf7; }
|
|
1577
1665
|
}
|
|
1578
|
-
.spotpatch-agent select option { color: #e8ebf2; background: #10151e; }
|
|
1579
1666
|
.spotpatch-agent select:focus-visible,
|
|
1580
1667
|
.spotpatch-consent input:focus-visible {
|
|
1581
1668
|
outline: 2px solid #8b7cf7;
|
|
@@ -1592,11 +1679,22 @@ var AGENT_PANEL_STYLES = `
|
|
|
1592
1679
|
line-height: 1.6;
|
|
1593
1680
|
}
|
|
1594
1681
|
.spotpatch-consent input { width: 16px; height: 16px; flex: none; margin: 3px 0 0; accent-color: var(--spotpatch-accent); }
|
|
1682
|
+
.spotpatch-workspace-consent {
|
|
1683
|
+
margin-top: 12px;
|
|
1684
|
+
border: 1px solid rgb(251 191 36 / 18%);
|
|
1685
|
+
border-radius: 10px;
|
|
1686
|
+
padding: 11px 12px;
|
|
1687
|
+
background: rgb(120 53 15 / 9%);
|
|
1688
|
+
}
|
|
1689
|
+
.spotpatch-workspace-consent strong { display: block; color: #fde68a; font-size: 13px; font-weight: 620; }
|
|
1690
|
+
.spotpatch-workspace-consent small { display: block; margin-top: 2px; color: #aeb6c4; font-size: 12px; line-height: 1.5; }
|
|
1691
|
+
.spotpatch-agent-health-list { display: grid; gap: 8px; margin-top: 14px; }
|
|
1692
|
+
.spotpatch-agent-workspace,
|
|
1595
1693
|
.spotpatch-agent-capability {
|
|
1596
1694
|
display: flex;
|
|
1597
1695
|
align-items: center;
|
|
1598
1696
|
gap: 8px;
|
|
1599
|
-
margin:
|
|
1697
|
+
margin: 0;
|
|
1600
1698
|
color: #929bab;
|
|
1601
1699
|
font-size: 13px;
|
|
1602
1700
|
}
|
|
@@ -1613,6 +1711,21 @@ var AGENT_PANEL_STYLES = `
|
|
|
1613
1711
|
.spotpatch-agent-capability[data-state="ready"]::before { background: var(--spotpatch-success); }
|
|
1614
1712
|
.spotpatch-agent-capability[data-state="error"] { color: #fecaca; }
|
|
1615
1713
|
.spotpatch-agent-capability[data-state="error"]::before { background: var(--spotpatch-danger); }
|
|
1714
|
+
.spotpatch-agent-workspace::before {
|
|
1715
|
+
width: 6px;
|
|
1716
|
+
height: 6px;
|
|
1717
|
+
flex: none;
|
|
1718
|
+
border-radius: 999px;
|
|
1719
|
+
background: #64748b;
|
|
1720
|
+
content: "";
|
|
1721
|
+
}
|
|
1722
|
+
.spotpatch-agent-workspace[data-state="checking"]::before { background: var(--spotpatch-warning); }
|
|
1723
|
+
.spotpatch-agent-workspace[data-state="ready"] { color: #a7f3d0; }
|
|
1724
|
+
.spotpatch-agent-workspace[data-state="ready"]::before { background: var(--spotpatch-success); }
|
|
1725
|
+
.spotpatch-agent-workspace[data-state="consent-required"] { color: #fde68a; }
|
|
1726
|
+
.spotpatch-agent-workspace[data-state="consent-required"]::before { background: #fbbf24; }
|
|
1727
|
+
.spotpatch-agent-workspace[data-state="blocked"] { color: #fecaca; }
|
|
1728
|
+
.spotpatch-agent-workspace[data-state="blocked"]::before { background: var(--spotpatch-danger); }
|
|
1616
1729
|
.spotpatch-agent-job { padding: 16px; }
|
|
1617
1730
|
.spotpatch-agent-job-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
|
1618
1731
|
.spotpatch-agent-model { min-width: 0; overflow: hidden; color: #d6dafe; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }
|
|
@@ -1701,10 +1814,26 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1701
1814
|
consentCheckbox.type = "checkbox";
|
|
1702
1815
|
const consentText = createMarkedElement(document, "span");
|
|
1703
1816
|
consent.append(consentCheckbox, consentText);
|
|
1817
|
+
const workspaceConsent = createMarkedElement(document, "label");
|
|
1818
|
+
workspaceConsent.className = "spotpatch-consent spotpatch-workspace-consent";
|
|
1819
|
+
workspaceConsent.hidden = true;
|
|
1820
|
+
const workspaceConsentCheckbox = createMarkedElement(document, "input");
|
|
1821
|
+
workspaceConsentCheckbox.type = "checkbox";
|
|
1822
|
+
const workspaceConsentContent = createMarkedElement(document, "span");
|
|
1823
|
+
const workspaceConsentTitle = createMarkedElement(document, "strong");
|
|
1824
|
+
const workspaceConsentHelp = createMarkedElement(document, "small");
|
|
1825
|
+
workspaceConsentContent.append(workspaceConsentTitle, workspaceConsentHelp);
|
|
1826
|
+
workspaceConsent.append(workspaceConsentCheckbox, workspaceConsentContent);
|
|
1827
|
+
const healthList = createMarkedElement(document, "div");
|
|
1828
|
+
healthList.className = "spotpatch-agent-health-list";
|
|
1829
|
+
const workspace = createMarkedElement(document, "p");
|
|
1830
|
+
workspace.className = "spotpatch-agent-workspace";
|
|
1831
|
+
workspace.dataset.state = "idle";
|
|
1704
1832
|
const capability = createMarkedElement(document, "p");
|
|
1705
1833
|
capability.className = "spotpatch-agent-capability";
|
|
1706
1834
|
capability.dataset.state = "idle";
|
|
1707
|
-
|
|
1835
|
+
healthList.append(workspace, capability);
|
|
1836
|
+
setup.append(selectors, consent, workspaceConsent, healthList);
|
|
1708
1837
|
const job = createMarkedElement(document, "div");
|
|
1709
1838
|
job.className = "spotpatch-agent-job";
|
|
1710
1839
|
job.hidden = true;
|
|
@@ -1763,6 +1892,9 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1763
1892
|
let latestCapabilityState = "idle";
|
|
1764
1893
|
let latestCapabilityMessage = messages.agent.connectionNotTested;
|
|
1765
1894
|
let latestCapabilityErrorCode;
|
|
1895
|
+
let latestWorkspaceState = "idle";
|
|
1896
|
+
let latestWorkspaceSnapshot;
|
|
1897
|
+
let latestWorkspaceErrorCode;
|
|
1766
1898
|
for (const provider of providers) {
|
|
1767
1899
|
addOption(document, providerSelect, provider.id, provider.label);
|
|
1768
1900
|
}
|
|
@@ -1790,7 +1922,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1790
1922
|
testButton.hidden = !setupVisible;
|
|
1791
1923
|
runButton.hidden = !setupVisible;
|
|
1792
1924
|
testButton.disabled = !editingEnabled || capabilityProbing || selectedProvider() === void 0;
|
|
1793
|
-
runButton.disabled = !editingEnabled || capabilityProbing || !contextReady || !consentCheckbox.checked || selectedProvider() === void 0 || modelSelect.value.length === 0;
|
|
1925
|
+
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;
|
|
1794
1926
|
if (!jobPresented || !selectionVisible) {
|
|
1795
1927
|
cancelButton.hidden = true;
|
|
1796
1928
|
applyButton.hidden = true;
|
|
@@ -1798,6 +1930,24 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1798
1930
|
resetButton.hidden = true;
|
|
1799
1931
|
}
|
|
1800
1932
|
};
|
|
1933
|
+
const renderWorkspaceMessage = () => {
|
|
1934
|
+
if (latestWorkspaceState === "idle") {
|
|
1935
|
+
workspace.textContent = messages.agent.workspaceNotChecked;
|
|
1936
|
+
} else if (latestWorkspaceState === "checking") {
|
|
1937
|
+
workspace.textContent = messages.agent.checkingWorkspace;
|
|
1938
|
+
} else if (latestWorkspaceState === "ready") {
|
|
1939
|
+
workspace.textContent = messages.agent.workspaceReady;
|
|
1940
|
+
} else if (latestWorkspaceState === "consent-required") {
|
|
1941
|
+
const changes = latestWorkspaceSnapshot?.changes;
|
|
1942
|
+
workspace.textContent = messages.agent.workspaceDirty(
|
|
1943
|
+
changes?.staged ?? 0,
|
|
1944
|
+
changes?.unstaged ?? 0,
|
|
1945
|
+
changes?.untracked ?? 0
|
|
1946
|
+
);
|
|
1947
|
+
} else {
|
|
1948
|
+
workspace.textContent = latestWorkspaceErrorCode === void 0 ? messages.errors.INTERNAL_ERROR : messages.errors[latestWorkspaceErrorCode];
|
|
1949
|
+
}
|
|
1950
|
+
};
|
|
1801
1951
|
function handleProviderChange() {
|
|
1802
1952
|
populateModels();
|
|
1803
1953
|
consentCheckbox.checked = false;
|
|
@@ -1822,6 +1972,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1822
1972
|
providerSelect.addEventListener("change", handleProviderChange);
|
|
1823
1973
|
modelSelect.addEventListener("change", handleModelChange);
|
|
1824
1974
|
consentCheckbox.addEventListener("change", refreshActions);
|
|
1975
|
+
workspaceConsentCheckbox.addEventListener("change", refreshActions);
|
|
1825
1976
|
function renderCurrentJob() {
|
|
1826
1977
|
if (latestSnapshot === void 0) {
|
|
1827
1978
|
return;
|
|
@@ -1876,6 +2027,8 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1876
2027
|
modelText.textContent = messages.agent.model;
|
|
1877
2028
|
providerSelect.setAttribute("aria-label", messages.agent.providerAriaLabel);
|
|
1878
2029
|
modelSelect.setAttribute("aria-label", messages.agent.modelAriaLabel);
|
|
2030
|
+
workspaceConsentTitle.textContent = messages.agent.includeLocalChanges;
|
|
2031
|
+
workspaceConsentHelp.textContent = messages.agent.includeLocalChangesHelp;
|
|
1879
2032
|
diff.setAttribute("aria-label", messages.agent.diffAriaLabel);
|
|
1880
2033
|
testButton.textContent = messages.agent.testConnection;
|
|
1881
2034
|
applyButton.textContent = messages.agent.apply;
|
|
@@ -1896,6 +2049,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1896
2049
|
} else {
|
|
1897
2050
|
capability.textContent = latestCapabilityMessage;
|
|
1898
2051
|
}
|
|
2052
|
+
renderWorkspaceMessage();
|
|
1899
2053
|
refreshActions();
|
|
1900
2054
|
renderCurrentJob();
|
|
1901
2055
|
}
|
|
@@ -1906,6 +2060,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1906
2060
|
providerSelect,
|
|
1907
2061
|
modelSelect,
|
|
1908
2062
|
consentCheckbox,
|
|
2063
|
+
workspaceConsentCheckbox,
|
|
1909
2064
|
testButton,
|
|
1910
2065
|
runButton,
|
|
1911
2066
|
cancelButton,
|
|
@@ -1915,6 +2070,9 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1915
2070
|
consentGranted() {
|
|
1916
2071
|
return consentCheckbox.checked;
|
|
1917
2072
|
},
|
|
2073
|
+
workspaceConsentGranted() {
|
|
2074
|
+
return workspaceConsentCheckbox.checked;
|
|
2075
|
+
},
|
|
1918
2076
|
readSelection() {
|
|
1919
2077
|
const provider = selectedProvider();
|
|
1920
2078
|
const model = provider?.models.find(
|
|
@@ -1935,6 +2093,20 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1935
2093
|
capability.textContent = capabilitySnapshot?.state === "agent-ready" ? `${message} \xB7 ${messages.agent.toolsReady}` : message;
|
|
1936
2094
|
refreshActions();
|
|
1937
2095
|
},
|
|
2096
|
+
renderWorkspaceHealth(state, snapshot, errorCode) {
|
|
2097
|
+
latestWorkspaceState = state;
|
|
2098
|
+
latestWorkspaceSnapshot = snapshot;
|
|
2099
|
+
latestWorkspaceErrorCode = errorCode ?? snapshot?.errorCode;
|
|
2100
|
+
workspace.dataset.state = state;
|
|
2101
|
+
if (state !== "checking") {
|
|
2102
|
+
workspaceConsent.hidden = state !== "consent-required";
|
|
2103
|
+
}
|
|
2104
|
+
if (state === "idle" || state === "ready" || state === "blocked") {
|
|
2105
|
+
workspaceConsentCheckbox.checked = false;
|
|
2106
|
+
}
|
|
2107
|
+
renderWorkspaceMessage();
|
|
2108
|
+
refreshActions();
|
|
2109
|
+
},
|
|
1938
2110
|
renderJob(snapshot, result, activities, errorCode) {
|
|
1939
2111
|
jobPresented = true;
|
|
1940
2112
|
setup.hidden = true;
|
|
@@ -1942,6 +2114,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1942
2114
|
providerSelect.disabled = true;
|
|
1943
2115
|
modelSelect.disabled = true;
|
|
1944
2116
|
consentCheckbox.disabled = true;
|
|
2117
|
+
workspaceConsentCheckbox.disabled = true;
|
|
1945
2118
|
latestSnapshot = snapshot;
|
|
1946
2119
|
latestResult = result;
|
|
1947
2120
|
latestActivities = activities;
|
|
@@ -1959,6 +2132,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1959
2132
|
providerSelect.disabled = false;
|
|
1960
2133
|
modelSelect.disabled = false;
|
|
1961
2134
|
consentCheckbox.disabled = false;
|
|
2135
|
+
workspaceConsentCheckbox.disabled = false;
|
|
1962
2136
|
activity.replaceChildren();
|
|
1963
2137
|
files.replaceChildren();
|
|
1964
2138
|
checks.replaceChildren();
|
|
@@ -1976,6 +2150,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1976
2150
|
providerSelect.disabled = !enabled || jobPresented;
|
|
1977
2151
|
modelSelect.disabled = !enabled || jobPresented;
|
|
1978
2152
|
consentCheckbox.disabled = !enabled || jobPresented;
|
|
2153
|
+
workspaceConsentCheckbox.disabled = !enabled || jobPresented;
|
|
1979
2154
|
refreshActions();
|
|
1980
2155
|
},
|
|
1981
2156
|
setProviderConsent(granted) {
|
|
@@ -1997,6 +2172,7 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
1997
2172
|
providerSelect.removeEventListener("change", handleProviderChange);
|
|
1998
2173
|
modelSelect.removeEventListener("change", handleModelChange);
|
|
1999
2174
|
consentCheckbox.removeEventListener("change", refreshActions);
|
|
2175
|
+
workspaceConsentCheckbox.removeEventListener("change", refreshActions);
|
|
2000
2176
|
}
|
|
2001
2177
|
});
|
|
2002
2178
|
}
|
|
@@ -2164,8 +2340,16 @@ var ERROR_MESSAGES_EN = Object.freeze({
|
|
|
2164
2340
|
[import_shared6.ERROR_CODES.AGENT_BUSY]: "Another write Agent job is still active.",
|
|
2165
2341
|
[import_shared6.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: "The Agent stopped at a configured time, turn, output, or size limit.",
|
|
2166
2342
|
[import_shared6.ERROR_CODES.AGENT_CANCELLED]: "The Agent job was cancelled.",
|
|
2167
|
-
[import_shared6.ERROR_CODES.WORKTREE_DIRTY]: "
|
|
2343
|
+
[import_shared6.ERROR_CODES.WORKTREE_DIRTY]: "Confirm inclusion of local changes before running AI.",
|
|
2344
|
+
[import_shared6.ERROR_CODES.WORKTREE_NOT_REPOSITORY]: "Vite root must be an initialized Git repository root.",
|
|
2345
|
+
[import_shared6.ERROR_CODES.WORKTREE_OPERATION_IN_PROGRESS]: "Finish the active merge, rebase, cherry-pick, or revert.",
|
|
2346
|
+
[import_shared6.ERROR_CODES.WORKTREE_CONFLICTED]: "Resolve all Git conflicts before running AI.",
|
|
2347
|
+
[import_shared6.ERROR_CODES.WORKTREE_LOCAL_CHANGES_TOO_LARGE]: "Reduce untracked files below the safe count and size limits.",
|
|
2348
|
+
[import_shared6.ERROR_CODES.WORKTREE_UNTRACKED_UNSUPPORTED]: "An untracked path is missing, linked, or not a regular file.",
|
|
2349
|
+
[import_shared6.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED]: "Local changes cannot be isolated safely.",
|
|
2168
2350
|
[import_shared6.ERROR_CODES.TOOL_DENIED]: "A model tool request violated the local safety policy.",
|
|
2351
|
+
[import_shared6.ERROR_CODES.TOOL_INPUT_INVALID]: "The model sent invalid tool arguments or reused a tool ID.",
|
|
2352
|
+
[import_shared6.ERROR_CODES.TOOL_PATH_DENIED]: "The model requested a protected, linked, non-text, or external path.",
|
|
2169
2353
|
[import_shared6.ERROR_CODES.PATCH_REJECTED]: "The proposed patch did not pass local policy.",
|
|
2170
2354
|
[import_shared6.ERROR_CODES.VALIDATION_FAILED]: "Required project checks failed. The change cannot be applied.",
|
|
2171
2355
|
[import_shared6.ERROR_CODES.APPLY_CONFLICT]: "Project files changed after the Agent baseline; no overwrite was performed.",
|
|
@@ -2189,8 +2373,16 @@ var ERROR_MESSAGES_ZH = Object.freeze({
|
|
|
2189
2373
|
[import_shared6.ERROR_CODES.AGENT_BUSY]: "\u5F53\u524D\u9879\u76EE\u5DF2\u6709\u4E00\u4E2A\u5199\u5165\u4EFB\u52A1\u6B63\u5728\u8FD0\u884C\u3002",
|
|
2190
2374
|
[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",
|
|
2191
2375
|
[import_shared6.ERROR_CODES.AGENT_CANCELLED]: "Agent \u4EFB\u52A1\u5DF2\u53D6\u6D88\u3002",
|
|
2192
|
-
[import_shared6.ERROR_CODES.WORKTREE_DIRTY]: "\u8FD0\u884C AI \u524D\uFF0C\u8BF7\
|
|
2376
|
+
[import_shared6.ERROR_CODES.WORKTREE_DIRTY]: "\u8FD0\u884C AI \u524D\uFF0C\u8BF7\u660E\u786E\u540C\u610F\u5C06\u5F53\u524D\u672C\u5730\u4FEE\u6539\u7EB3\u5165\u9694\u79BB\u57FA\u7EBF\u3002",
|
|
2377
|
+
[import_shared6.ERROR_CODES.WORKTREE_NOT_REPOSITORY]: "Vite \u6839\u76EE\u5F55\u4E0D\u662F\u5DF2\u521D\u59CB\u5316 Git \u4ED3\u5E93\u7684\u9876\u5C42\u76EE\u5F55\u3002",
|
|
2378
|
+
[import_shared6.ERROR_CODES.WORKTREE_OPERATION_IN_PROGRESS]: "\u8BF7\u5148\u5B8C\u6210\u5F53\u524D merge\u3001rebase\u3001cherry-pick \u6216 revert\uFF0C\u518D\u8FD0\u884C AI\u3002",
|
|
2379
|
+
[import_shared6.ERROR_CODES.WORKTREE_CONFLICTED]: "\u8BF7\u5148\u89E3\u51B3\u5168\u90E8 Git \u51B2\u7A81\uFF0C\u518D\u8FD0\u884C AI\u3002",
|
|
2380
|
+
[import_shared6.ERROR_CODES.WORKTREE_LOCAL_CHANGES_TOO_LARGE]: "\u672A\u8DDF\u8E2A\u6587\u4EF6\u8D85\u8FC7\u5B89\u5168\u6570\u91CF\u6216\u4F53\u79EF\u4E0A\u9650\uFF0C\u8BF7\u5148\u7CBE\u7B80\u3002",
|
|
2381
|
+
[import_shared6.ERROR_CODES.WORKTREE_UNTRACKED_UNSUPPORTED]: "\u672A\u8DDF\u8E2A\u9879\u5DF2\u4E22\u5931\u3001\u662F\u7B26\u53F7\u94FE\u63A5\u6216\u4E0D\u662F\u666E\u901A\u6587\u4EF6\u3002",
|
|
2382
|
+
[import_shared6.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED]: "\u5F53\u524D\u672C\u5730\u4FEE\u6539\u65E0\u6CD5\u5B89\u5168\u9694\u79BB\u3002",
|
|
2193
2383
|
[import_shared6.ERROR_CODES.TOOL_DENIED]: "\u6A21\u578B\u5DE5\u5177\u8BF7\u6C42\u8FDD\u53CD\u672C\u5730\u5B89\u5168\u7B56\u7565\u3002",
|
|
2384
|
+
[import_shared6.ERROR_CODES.TOOL_INPUT_INVALID]: "\u6A21\u578B\u53D1\u9001\u4E86\u65E0\u6548\u5DE5\u5177\u53C2\u6570\uFF0C\u6216\u590D\u7528\u4E86\u5DE5\u5177\u8C03\u7528 ID\u3002",
|
|
2385
|
+
[import_shared6.ERROR_CODES.TOOL_PATH_DENIED]: "\u6A21\u578B\u8BF7\u6C42\u4E86\u53D7\u4FDD\u62A4\u3001\u975E\u6587\u672C\u3001\u7B26\u53F7\u94FE\u63A5\u6216\u9879\u76EE\u5916\u8DEF\u5F84\u3002",
|
|
2194
2386
|
[import_shared6.ERROR_CODES.PATCH_REJECTED]: "\u5EFA\u8BAE\u8865\u4E01\u672A\u901A\u8FC7\u672C\u5730\u7B56\u7565\u68C0\u67E5\u3002",
|
|
2195
2387
|
[import_shared6.ERROR_CODES.VALIDATION_FAILED]: "\u9879\u76EE\u5FC5\u9700\u68C0\u67E5\u5931\u8D25\uFF0C\u4E0D\u80FD\u5E94\u7528\u672C\u6B21\u53D8\u66F4\u3002",
|
|
2196
2388
|
[import_shared6.ERROR_CODES.APPLY_CONFLICT]: "Agent \u5EFA\u7ACB\u57FA\u7EBF\u540E\u9879\u76EE\u6587\u4EF6\u5DF2\u53D8\u5316\uFF0C\u672A\u6267\u884C\u8986\u76D6\u3002",
|
|
@@ -2355,6 +2547,13 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2355
2547
|
providerUnavailable: "Provider configuration is unavailable.",
|
|
2356
2548
|
consent: (provider) => `I understand selected context and allowed source may be sent to ${provider}; its data policy is my responsibility.`,
|
|
2357
2549
|
connectionNotTested: "Connection not tested",
|
|
2550
|
+
workspaceNotChecked: "Local workspace not checked",
|
|
2551
|
+
checkingWorkspace: "Checking Git workspace and isolated execution\u2026",
|
|
2552
|
+
workspaceReady: "Local workspace is ready for isolated execution",
|
|
2553
|
+
workspaceDirty: (staged, unstaged, untracked) => `Local changes found \xB7 ${String(staged)} staged \xB7 ${String(unstaged)} unstaged \xB7 ${String(untracked)} untracked`,
|
|
2554
|
+
includeLocalChanges: "Allow the Agent to continue from my current local changes",
|
|
2555
|
+
includeLocalChangesHelp: "The Agent may edit these files. SpotPatch preserves the baseline and applies or reverts only the Agent delta.",
|
|
2556
|
+
localChangesConsentRequired: "Confirm inclusion of current local changes before running AI.",
|
|
2358
2557
|
capabilityVerified: "Agent capability verified",
|
|
2359
2558
|
capabilityVerifiedAnnouncement: "AI provider capability verified.",
|
|
2360
2559
|
testingCapability: "Testing authentication, tools, continuation, and streaming\u2026",
|
|
@@ -2363,7 +2562,7 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2363
2562
|
reverting: "Reverting the applied Agent change.",
|
|
2364
2563
|
consentRequired: "Confirm remote provider data transmission before running AI.",
|
|
2365
2564
|
toolsReady: "tools and streaming ready",
|
|
2366
|
-
testConnection: "
|
|
2565
|
+
testConnection: "Check environment",
|
|
2367
2566
|
verifyAndRun: "Verify & run",
|
|
2368
2567
|
verifying: "Verifying\u2026",
|
|
2369
2568
|
run: "Run AI",
|
|
@@ -2484,6 +2683,13 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2484
2683
|
providerUnavailable: "\u6A21\u578B\u670D\u52A1\u914D\u7F6E\u4E0D\u53EF\u7528\u3002",
|
|
2485
2684
|
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`,
|
|
2486
2685
|
connectionNotTested: "\u5C1A\u672A\u6D4B\u8BD5\u8FDE\u63A5",
|
|
2686
|
+
workspaceNotChecked: "\u5C1A\u672A\u68C0\u67E5\u672C\u5730\u5DE5\u4F5C\u533A",
|
|
2687
|
+
checkingWorkspace: "\u6B63\u5728\u68C0\u67E5 Git \u5DE5\u4F5C\u533A\u4E0E\u9694\u79BB\u6267\u884C\u73AF\u5883\u2026\u2026",
|
|
2688
|
+
workspaceReady: "\u672C\u5730\u5DE5\u4F5C\u533A\u5DF2\u6EE1\u8DB3\u9694\u79BB\u6267\u884C\u6761\u4EF6",
|
|
2689
|
+
workspaceDirty: (staged, unstaged, untracked) => `\u53D1\u73B0\u672C\u5730\u4FEE\u6539 \xB7 \u6682\u5B58 ${String(staged)} \xB7 \u672A\u6682\u5B58 ${String(unstaged)} \xB7 \u672A\u8DDF\u8E2A ${String(untracked)}`,
|
|
2690
|
+
includeLocalChanges: "\u5141\u8BB8 Agent \u57FA\u4E8E\u6211\u5F53\u524D\u7684\u672C\u5730\u4FEE\u6539\u7EE7\u7EED",
|
|
2691
|
+
includeLocalChangesHelp: "Agent \u53EF\u80FD\u7EE7\u7EED\u4FEE\u6539\u8FD9\u4E9B\u6587\u4EF6\uFF1BSpotPatch \u4F1A\u4FDD\u7559\u539F\u57FA\u7EBF\uFF0C\u4EC5\u5E94\u7528\u6216\u64A4\u9500 Agent \u81EA\u5DF1\u7684\u589E\u91CF\u3002",
|
|
2692
|
+
localChangesConsentRequired: "\u8FD0\u884C AI \u524D\uFF0C\u8BF7\u786E\u8BA4\u5141\u8BB8\u7EB3\u5165\u5F53\u524D\u672C\u5730\u4FEE\u6539\u3002",
|
|
2487
2693
|
capabilityVerified: "Agent \u80FD\u529B\u9A8C\u8BC1\u901A\u8FC7",
|
|
2488
2694
|
capabilityVerifiedAnnouncement: "AI \u6A21\u578B\u670D\u52A1\u80FD\u529B\u9A8C\u8BC1\u901A\u8FC7\u3002",
|
|
2489
2695
|
testingCapability: "\u6B63\u5728\u9A8C\u8BC1\u9274\u6743\u3001\u5DE5\u5177\u8C03\u7528\u3001\u8FDE\u7EED\u8C03\u7528\u4E0E\u6D41\u5F0F\u54CD\u5E94\u2026\u2026",
|
|
@@ -2492,7 +2698,7 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2492
2698
|
reverting: "\u6B63\u5728\u64A4\u9500\u5DF2\u5E94\u7528\u7684 Agent \u53D8\u66F4\u3002",
|
|
2493
2699
|
consentRequired: "\u8FD0\u884C AI \u524D\uFF0C\u8BF7\u5148\u786E\u8BA4\u5141\u8BB8\u5411\u8FDC\u7A0B\u6A21\u578B\u670D\u52A1\u4F20\u8F93\u6570\u636E\u3002",
|
|
2494
2700
|
toolsReady: "\u5DE5\u5177\u8C03\u7528\u4E0E\u6D41\u5F0F\u54CD\u5E94\u5DF2\u5C31\u7EEA",
|
|
2495
|
-
testConnection: "\
|
|
2701
|
+
testConnection: "\u68C0\u67E5\u8FD0\u884C\u73AF\u5883",
|
|
2496
2702
|
verifyAndRun: "\u9A8C\u8BC1\u5E76\u8FD0\u884C",
|
|
2497
2703
|
verifying: "\u9A8C\u8BC1\u4E2D\u2026\u2026",
|
|
2498
2704
|
run: "\u8FD0\u884C AI",
|
|
@@ -3742,6 +3948,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3742
3948
|
agentProviderSelect: agentPanel.providerSelect,
|
|
3743
3949
|
agentModelSelect: agentPanel.modelSelect,
|
|
3744
3950
|
agentConsentCheckbox: agentPanel.consentCheckbox,
|
|
3951
|
+
agentWorkspaceConsentCheckbox: agentPanel.workspaceConsentCheckbox,
|
|
3745
3952
|
agentTestButton: agentPanel.testButton,
|
|
3746
3953
|
agentRunButton: agentPanel.runButton,
|
|
3747
3954
|
agentCancelButton: agentPanel.cancelButton,
|
|
@@ -3853,6 +4060,10 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3853
4060
|
previewButton.classList.toggle("spotpatch-primary", !agentReady);
|
|
3854
4061
|
placeDialog();
|
|
3855
4062
|
},
|
|
4063
|
+
renderAgentWorkspaceHealth(state, snapshot, errorCode) {
|
|
4064
|
+
agentPanel.renderWorkspaceHealth(state, snapshot, errorCode);
|
|
4065
|
+
placeDialog();
|
|
4066
|
+
},
|
|
3856
4067
|
renderAgentJob(snapshot, result, activities, errorCode) {
|
|
3857
4068
|
agentPanel.renderJob(snapshot, result, activities, errorCode);
|
|
3858
4069
|
placeDialog();
|
|
@@ -3873,6 +4084,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3873
4084
|
},
|
|
3874
4085
|
locale: localizer.locale,
|
|
3875
4086
|
messages: localizer.messages,
|
|
4087
|
+
agentWorkspaceConsentGranted: agentPanel.workspaceConsentGranted,
|
|
3876
4088
|
subscribeLocale: localizer.subscribe,
|
|
3877
4089
|
dispose() {
|
|
3878
4090
|
diagnostics.removeEventListener("toggle", placeDialog);
|
|
@@ -3974,6 +4186,22 @@ function createAgentWorkflow(options) {
|
|
|
3974
4186
|
let appliedDuringCurrentJob = false;
|
|
3975
4187
|
let actionPending = false;
|
|
3976
4188
|
const selectedProfiles = () => options.view.readAgentSelection();
|
|
4189
|
+
const refreshWorkspaceHealth = async (workflowRevision) => {
|
|
4190
|
+
options.view.renderAgentWorkspaceHealth("checking");
|
|
4191
|
+
try {
|
|
4192
|
+
const health = await options.api.agentWorkspaceHealth();
|
|
4193
|
+
if (workflowRevision !== revision) {
|
|
4194
|
+
return health;
|
|
4195
|
+
}
|
|
4196
|
+
options.view.renderAgentWorkspaceHealth(health.state, health, health.errorCode);
|
|
4197
|
+
return health;
|
|
4198
|
+
} catch (error) {
|
|
4199
|
+
if (workflowRevision === revision) {
|
|
4200
|
+
options.view.renderAgentWorkspaceHealth("blocked", void 0, errorCode(error));
|
|
4201
|
+
}
|
|
4202
|
+
throw error;
|
|
4203
|
+
}
|
|
4204
|
+
};
|
|
3977
4205
|
const renderJob = (explicitErrorCode) => {
|
|
3978
4206
|
if (snapshot === void 0) {
|
|
3979
4207
|
return;
|
|
@@ -4149,6 +4377,10 @@ function createAgentWorkflow(options) {
|
|
|
4149
4377
|
},
|
|
4150
4378
|
beginSelection() {
|
|
4151
4379
|
resetState();
|
|
4380
|
+
const workflowRevision = revision;
|
|
4381
|
+
if (options.ai.enabled) {
|
|
4382
|
+
void refreshWorkspaceHealth(workflowRevision).catch(() => void 0);
|
|
4383
|
+
}
|
|
4152
4384
|
},
|
|
4153
4385
|
cancel() {
|
|
4154
4386
|
if (snapshot?.canCancel === true) {
|
|
@@ -4181,12 +4413,17 @@ function createAgentWorkflow(options) {
|
|
|
4181
4413
|
providerOrModelChanged() {
|
|
4182
4414
|
revision += 1;
|
|
4183
4415
|
restoreProviderState();
|
|
4416
|
+
const workflowRevision = revision;
|
|
4417
|
+
void refreshWorkspaceHealth(workflowRevision).catch(() => void 0);
|
|
4184
4418
|
},
|
|
4185
4419
|
reset() {
|
|
4186
4420
|
const mustReselect = appliedDuringCurrentJob;
|
|
4187
4421
|
resetState();
|
|
4188
4422
|
if (mustReselect) {
|
|
4189
4423
|
options.onReselectRequired();
|
|
4424
|
+
} else if (options.ai.enabled) {
|
|
4425
|
+
const workflowRevision = revision;
|
|
4426
|
+
void refreshWorkspaceHealth(workflowRevision).catch(() => void 0);
|
|
4190
4427
|
}
|
|
4191
4428
|
},
|
|
4192
4429
|
revert() {
|
|
@@ -4213,15 +4450,27 @@ function createAgentWorkflow(options) {
|
|
|
4213
4450
|
providerConsents.add(selection.providerProfileId);
|
|
4214
4451
|
const workflowRevision = ++revision;
|
|
4215
4452
|
options.view.setAgentEditingEnabled(false);
|
|
4216
|
-
void
|
|
4453
|
+
void Promise.all([
|
|
4454
|
+
probe(workflowRevision),
|
|
4455
|
+
refreshWorkspaceHealth(workflowRevision)
|
|
4456
|
+
]).then(async ([, health]) => {
|
|
4217
4457
|
if (workflowRevision !== revision) {
|
|
4218
4458
|
return;
|
|
4219
4459
|
}
|
|
4460
|
+
if (health.state === "blocked") {
|
|
4461
|
+
throw new RuntimeApiError(
|
|
4462
|
+
health.errorCode ?? import_shared8.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED
|
|
4463
|
+
);
|
|
4464
|
+
}
|
|
4465
|
+
if (health.state === "consent-required" && !options.view.agentWorkspaceConsentGranted()) {
|
|
4466
|
+
throw new RuntimeApiError(import_shared8.ERROR_CODES.WORKTREE_DIRTY);
|
|
4467
|
+
}
|
|
4220
4468
|
const created = await options.api.createAgentJob({
|
|
4221
4469
|
annotation,
|
|
4222
4470
|
providerProfileId: selection.providerProfileId,
|
|
4223
4471
|
modelProfileId: selection.modelProfileId,
|
|
4224
|
-
providerDataConsent: true
|
|
4472
|
+
providerDataConsent: true,
|
|
4473
|
+
workingTreeMode: health.state === "consent-required" ? "include-local-changes" : "require-clean"
|
|
4225
4474
|
});
|
|
4226
4475
|
if (workflowRevision !== revision) {
|
|
4227
4476
|
return;
|
|
@@ -4250,7 +4499,10 @@ function createAgentWorkflow(options) {
|
|
|
4250
4499
|
return;
|
|
4251
4500
|
}
|
|
4252
4501
|
const workflowRevision = ++revision;
|
|
4253
|
-
void
|
|
4502
|
+
void Promise.all([
|
|
4503
|
+
probe(workflowRevision),
|
|
4504
|
+
refreshWorkspaceHealth(workflowRevision)
|
|
4505
|
+
]).catch((error) => {
|
|
4254
4506
|
if (workflowRevision === revision) {
|
|
4255
4507
|
options.view.renderAgentCapability(
|
|
4256
4508
|
"error",
|