@spotpatch/runtime 1.15.0 → 1.15.2
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/{chunk-ASRUAKA5.js → chunk-TEH2CCO3.js} +1 -1
- package/dist/chunk-TEH2CCO3.js.map +1 -0
- package/dist/external-handoff-panel.cjs +71 -9
- package/dist/external-handoff-panel.cjs.map +1 -1
- package/dist/external-handoff-panel.d.cts +1 -0
- package/dist/external-handoff-panel.d.ts +1 -0
- package/dist/external-handoff-panel.js +72 -10
- package/dist/external-handoff-panel.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-ASRUAKA5.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/external-handoff-contract.ts"],"sourcesContent":["import type {\n DispatchSummary,\n ErrorCode,\n ExternalAgentControlStatus,\n ExternalAgentManagedResult,\n ExternalHandoffCapability,\n ExternalHandoffPublishResult,\n ExternalHandoffStatusResult,\n ExternalHandoffFramework,\n SpotAnnotation,\n SpotPatchLocale,\n} from \"@spotpatch/shared/external-handoff-browser\";\n\nexport interface ExternalHandoffPanel {\n readonly cancelManagedButton: HTMLButtonElement;\n readonly connectButton: HTMLButtonElement;\n readonly readModel: () => string | undefined;\n readonly disconnectButton: HTMLButtonElement;\n readonly refreshButton: HTMLButtonElement;\n readonly root: HTMLElement;\n readonly sendButton: HTMLButtonElement;\n readonly styles: HTMLStyleElement;\n readonly confirmDisclosure: (annotation: SpotAnnotation) => Promise<boolean>;\n readonly dispose: () => void;\n readonly renderCapability: (capability: ExternalHandoffCapability) => void;\n readonly renderControlUnavailable: () => void;\n readonly renderControlStatus: (status: ExternalAgentControlStatus) => void;\n readonly renderError: (code?: ErrorCode, retryable?: boolean) => void;\n readonly renderPublishResult: (result: ExternalHandoffPublishResult) => void;\n readonly renderPublishing: () => void;\n readonly renderManagedResult: (result: ExternalAgentManagedResult) => void;\n readonly renderStatus: (result: ExternalHandoffStatusResult) => void;\n readonly resolveButton: HTMLButtonElement;\n readonly revokeButton: HTMLButtonElement;\n readonly setBusy: (busy: boolean) => void;\n readonly setControlBusy: (busy: boolean) => void;\n readonly setContextReady: (ready: boolean) => void;\n readonly setSelectionVisible: (visible: boolean) => void;\n}\n\nexport interface ExternalHandoffWorkflow {\n readonly cancelPending: () => void;\n readonly dispose: () => void;\n readonly mount: () => void;\n}\n\nexport interface ExternalHandoffExtension {\n readonly createPanel: (\n document: Document,\n framework: ExternalHandoffFramework,\n locale: () => SpotPatchLocale,\n sessionId: string,\n subscribeLocale: (listener: () => void) => () => void,\n onViewChange: () => void,\n onDispatchChange?: (dispatch: DispatchSummary | null) => void,\n onControlChange?: (status: ExternalAgentControlStatus | undefined) => void,\n ) => ExternalHandoffPanel;\n readonly createWorkflow: (\n fetch: typeof globalThis.fetch,\n panel: ExternalHandoffPanel,\n selectedAnnotation: () => SpotAnnotation | undefined,\n sessionToken: string,\n window: Window,\n ) => ExternalHandoffWorkflow;\n}\n\nconst EXTERNAL_HANDOFF_EXTENSION_KEY = Symbol.for(\"spotpatch.external-handoff.v1\");\ntype ExtensionStore = Partial<Record<symbol, ExternalHandoffExtension>>;\n\nexport function registerExternalHandoffExtension(\n extension: ExternalHandoffExtension,\n): void {\n (globalThis as ExtensionStore)[EXTERNAL_HANDOFF_EXTENSION_KEY] = extension;\n}\n\nexport function getExternalHandoffExtension(): ExternalHandoffExtension | undefined {\n return (globalThis as ExtensionStore)[EXTERNAL_HANDOFF_EXTENSION_KEY];\n}\n"],"mappings":";AAkEA,IAAM,iCAAiC,uBAAO,IAAI,+BAA+B;AAG1E,SAAS,iCACd,WACM;AACN,EAAC,WAA8B,8BAA8B,IAAI;AACnE;AAEO,SAAS,8BAAoE;AAClF,SAAQ,WAA8B,8BAA8B;AACtE;","names":[]}
|
|
@@ -197,6 +197,9 @@ function parseTask(value) {
|
|
|
197
197
|
...value.resultExpiresAt === void 0 ? {} : { resultExpiresAt: value.resultExpiresAt }
|
|
198
198
|
});
|
|
199
199
|
}
|
|
200
|
+
function validModel(value) {
|
|
201
|
+
return typeof value === "string" && value.length > 0 && value.length <= import_external_handoff_browser.EXTERNAL_AGENT_CONTROL_LIMITS.maximumModelCharacters && value.trim() === value;
|
|
202
|
+
}
|
|
200
203
|
function parseExternalAgentControlStatus(value) {
|
|
201
204
|
if (!record(value) || !optionalKeys(
|
|
202
205
|
value,
|
|
@@ -210,8 +213,8 @@ function parseExternalAgentControlStatus(value) {
|
|
|
210
213
|
"sequence",
|
|
211
214
|
"updatedAt"
|
|
212
215
|
],
|
|
213
|
-
["effectiveModel", "error", "requestedModel", "task"]
|
|
214
|
-
) || value.schemaVersion !== 1 || !integer(value.sequence) || !member(import_external_handoff_browser.EXTERNAL_AGENT_MODES, value.mode) || !member(import_external_handoff_browser.EXTERNAL_AGENT_CONNECTION_STATES, value.connectionState) || !member(import_external_handoff_browser.EXTERNAL_AGENT_AUTH_READINESS, value.authReadiness) || !member(import_external_handoff_browser.EXTERNAL_AGENT_GRANT_STATES, value.grantState) || !validTimestamp(value.updatedAt) || value.requestedModel !== void 0 && (
|
|
216
|
+
["effectiveModel", "error", "requestedModel", "task", "models"]
|
|
217
|
+
) || value.schemaVersion !== 1 || !integer(value.sequence) || !member(import_external_handoff_browser.EXTERNAL_AGENT_MODES, value.mode) || !member(import_external_handoff_browser.EXTERNAL_AGENT_CONNECTION_STATES, value.connectionState) || !member(import_external_handoff_browser.EXTERNAL_AGENT_AUTH_READINESS, value.authReadiness) || !member(import_external_handoff_browser.EXTERNAL_AGENT_GRANT_STATES, value.grantState) || !validTimestamp(value.updatedAt) || value.requestedModel !== void 0 && !validModel(value.requestedModel) || value.effectiveModel !== void 0 && !validModel(value.effectiveModel) || value.models !== void 0 && (!Array.isArray(value.models) || value.models.length === 0 || value.models.length > import_external_handoff_browser.EXTERNAL_AGENT_CONTROL_LIMITS.maximumModels || !value.models.every(validModel) || new Set(value.models).size !== value.models.length) || !record(value.adapter) || !exactKeys(value.adapter, ["availability", "kind", "maturity"]) || value.adapter.kind !== "codex" || value.adapter.maturity !== "experimental" || value.adapter.availability !== "available" && value.adapter.availability !== "unavailable") {
|
|
215
218
|
throw new TypeError("Invalid external Agent control status.");
|
|
216
219
|
}
|
|
217
220
|
let error;
|
|
@@ -238,6 +241,7 @@ function parseExternalAgentControlStatus(value) {
|
|
|
238
241
|
connectionState: value.connectionState,
|
|
239
242
|
authReadiness: value.authReadiness,
|
|
240
243
|
grantState: value.grantState,
|
|
244
|
+
...value.models === void 0 ? {} : { models: Object.freeze([...value.models]) },
|
|
241
245
|
...value.requestedModel === void 0 ? {} : { requestedModel: value.requestedModel },
|
|
242
246
|
...value.effectiveModel === void 0 ? {} : { effectiveModel: value.effectiveModel },
|
|
243
247
|
...value.task === void 0 ? {} : { task: parseTask(value.task) },
|
|
@@ -736,11 +740,13 @@ function createExternalHandoffWorkflow(fetch, panel, selectedAnnotation, session
|
|
|
736
740
|
}
|
|
737
741
|
};
|
|
738
742
|
const handleConnectClick = () => {
|
|
743
|
+
const model = options.panel.readModel();
|
|
739
744
|
void performControlAction(
|
|
740
745
|
() => controlClient.connect({
|
|
741
746
|
requestId: createRequestId(options.window),
|
|
742
747
|
adapterKind: "codex",
|
|
743
|
-
profile: import_external_handoff_browser2.EXTERNAL_AGENT_MANAGED_PROFILE
|
|
748
|
+
profile: import_external_handoff_browser2.EXTERNAL_AGENT_MANAGED_PROFILE,
|
|
749
|
+
...model === void 0 ? {} : { model }
|
|
744
750
|
})
|
|
745
751
|
);
|
|
746
752
|
};
|
|
@@ -1029,6 +1035,10 @@ var MESSAGES = Object.freeze({
|
|
|
1029
1035
|
"en-US": Object.freeze({
|
|
1030
1036
|
title: "External Agent connection",
|
|
1031
1037
|
agentLabel: "Agent",
|
|
1038
|
+
modelLabel: "Managed Codex model",
|
|
1039
|
+
modelLoading: "Connect to load available models",
|
|
1040
|
+
modelHint: "Applies only to this managed connection, not API Key settings. Apply changes before publishing; switching reconnects Codex.",
|
|
1041
|
+
applyModel: "Apply model",
|
|
1032
1042
|
codexManaged: "Codex \xB7 managed (experimental)",
|
|
1033
1043
|
connectManaged: "Connect Codex",
|
|
1034
1044
|
disconnectManaged: "Disconnect",
|
|
@@ -1067,7 +1077,7 @@ var MESSAGES = Object.freeze({
|
|
|
1067
1077
|
"install-agent": "Install Codex and retry.",
|
|
1068
1078
|
"use-supported-version": "Use a schema-compatible Codex version.",
|
|
1069
1079
|
"sign-in": "Sign in with Codex, then retry.",
|
|
1070
|
-
"choose-available-model": "Choose an available model
|
|
1080
|
+
"choose-available-model": "Choose an available model and reconnect Codex.",
|
|
1071
1081
|
"use-inbox": "Continue with the Agent inbox fallback.",
|
|
1072
1082
|
"confirm-managed-access": "Revoke the invalid grant and confirm access again.",
|
|
1073
1083
|
"review-candidate-diff": "Review the candidate diff and validation output.",
|
|
@@ -1116,6 +1126,10 @@ var MESSAGES = Object.freeze({
|
|
|
1116
1126
|
"zh-CN": Object.freeze({
|
|
1117
1127
|
title: "\u5916\u90E8 Agent \u8FDE\u63A5",
|
|
1118
1128
|
agentLabel: "Agent",
|
|
1129
|
+
modelLabel: "\u53D7\u7BA1 Codex \u6A21\u578B",
|
|
1130
|
+
modelLoading: "\u8FDE\u63A5\u540E\u52A0\u8F7D\u53EF\u7528\u6A21\u578B",
|
|
1131
|
+
modelHint: "\u4EC5\u4F5C\u7528\u4E8E\u6B64\u53D7\u7BA1\u8FDE\u63A5\uFF0C\u4E0D\u4FEE\u6539 API Key \u914D\u7F6E\u3002\u66F4\u6362\u540E\u8BF7\u5148\u5E94\u7528\u6A21\u578B\uFF0C\u518D\u53D1\u5E03\u4EFB\u52A1\uFF1B\u5E94\u7528\u65F6\u4F1A\u91CD\u65B0\u8FDE\u63A5 Codex\u3002",
|
|
1132
|
+
applyModel: "\u5E94\u7528\u6A21\u578B",
|
|
1119
1133
|
codexManaged: "Codex \xB7 \u53D7\u7BA1\u6A21\u5F0F\uFF08\u5B9E\u9A8C\u6027\uFF09",
|
|
1120
1134
|
connectManaged: "\u8FDE\u63A5 Codex",
|
|
1121
1135
|
disconnectManaged: "\u65AD\u5F00\u8FDE\u63A5",
|
|
@@ -1154,7 +1168,7 @@ var MESSAGES = Object.freeze({
|
|
|
1154
1168
|
"install-agent": "\u5B89\u88C5 Codex \u540E\u91CD\u8BD5\u3002",
|
|
1155
1169
|
"use-supported-version": "\u6539\u7528 Schema \u517C\u5BB9\u7684 Codex \u7248\u672C\u3002",
|
|
1156
1170
|
"sign-in": "\u767B\u5F55 Codex \u540E\u91CD\u8BD5\u3002",
|
|
1157
|
-
"choose-available-model": "\
|
|
1171
|
+
"choose-available-model": "\u9009\u62E9\u53EF\u7528\u6A21\u578B\u540E\u91CD\u65B0\u8FDE\u63A5 Codex\u3002",
|
|
1158
1172
|
"use-inbox": "\u7EE7\u7EED\u4F7F\u7528 Agent \u6536\u4EF6\u7BB1\u964D\u7EA7\u8DEF\u5F84\u3002",
|
|
1159
1173
|
"confirm-managed-access": "\u64A4\u9500\u65E0\u6548\u6388\u6743\u5E76\u91CD\u65B0\u786E\u8BA4\u3002",
|
|
1160
1174
|
"review-candidate-diff": "\u68C0\u67E5\u5019\u9009 diff \u548C\u9A8C\u8BC1\u8F93\u51FA\u3002",
|
|
@@ -1376,6 +1390,11 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1376
1390
|
codexOption.value = "codex";
|
|
1377
1391
|
agentSelect.append(codexOption);
|
|
1378
1392
|
agentLabel.append(agentLabelText, agentSelect);
|
|
1393
|
+
const modelLabel = createMarkedElement(document, "label");
|
|
1394
|
+
const modelLabelText = createMarkedElement(document, "span");
|
|
1395
|
+
const modelSelect = createMarkedElement(document, "select");
|
|
1396
|
+
const modelHint = createMarkedElement(document, "p");
|
|
1397
|
+
modelLabel.append(modelLabelText, modelSelect);
|
|
1379
1398
|
const controlStatus = createMarkedElement(document, "p");
|
|
1380
1399
|
controlStatus.className = "spotpatch-external-control-status";
|
|
1381
1400
|
controlStatus.setAttribute("role", "status");
|
|
@@ -1398,7 +1417,14 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1398
1417
|
const managedResultSummary = createMarkedElement(document, "p");
|
|
1399
1418
|
const managedResultDiff = createMarkedElement(document, "pre");
|
|
1400
1419
|
managedResult.append(managedResultTitle, managedResultSummary, managedResultDiff);
|
|
1401
|
-
controlRoot.append(
|
|
1420
|
+
controlRoot.append(
|
|
1421
|
+
agentLabel,
|
|
1422
|
+
modelLabel,
|
|
1423
|
+
modelHint,
|
|
1424
|
+
controlStatus,
|
|
1425
|
+
controlActions,
|
|
1426
|
+
managedResult
|
|
1427
|
+
);
|
|
1402
1428
|
const resolveButton = createButton(document, "", "spotpatch-external-resolve");
|
|
1403
1429
|
resolveButton.hidden = true;
|
|
1404
1430
|
const settings = createMarkedElement(document, "details");
|
|
@@ -1455,15 +1481,19 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1455
1481
|
} catch {
|
|
1456
1482
|
}
|
|
1457
1483
|
};
|
|
1484
|
+
const modelPending = () => control?.mode === "managed" && modelSelect.value !== "" && modelSelect.value !== control.requestedModel;
|
|
1485
|
+
const controlPending = () => controlOperationBusy || control?.connectionState === "diagnosing" || control?.connectionState === "connecting" || control?.connectionState === "disconnecting";
|
|
1458
1486
|
const refreshActions = () => {
|
|
1459
1487
|
sendButton.textContent = retryable ? messages.retry : activeAdapter?.canDispatch === true ? messages.send : messages.inboxSend;
|
|
1460
|
-
sendButton.disabled = !visible || !brokerReady || !contextReady || operationBusy || !retryable && dispatchBlocksSend;
|
|
1488
|
+
sendButton.disabled = !visible || !brokerReady || !contextReady || operationBusy || controlPending() || modelPending() || !retryable && dispatchBlocksSend;
|
|
1461
1489
|
sendButton.setAttribute("aria-busy", String(operationBusy));
|
|
1462
1490
|
refreshButton.disabled = !visible || operationBusy;
|
|
1463
1491
|
resolveButton.hidden = !unknownDelivery;
|
|
1464
1492
|
resolveButton.disabled = !visible || operationBusy || !unknownDelivery;
|
|
1465
1493
|
};
|
|
1466
1494
|
const refreshControlActions = () => {
|
|
1495
|
+
connectButton.textContent = modelPending() ? messages.applyModel : messages.connectManaged;
|
|
1496
|
+
modelSelect.disabled = true;
|
|
1467
1497
|
if (control === void 0) {
|
|
1468
1498
|
connectButton.disabled = true;
|
|
1469
1499
|
disconnectButton.disabled = true;
|
|
@@ -1472,8 +1502,9 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1472
1502
|
return;
|
|
1473
1503
|
}
|
|
1474
1504
|
const state = control.connectionState;
|
|
1475
|
-
const operationPending =
|
|
1476
|
-
|
|
1505
|
+
const operationPending = controlPending();
|
|
1506
|
+
modelSelect.disabled = operationPending || state === "busy" || !control.models?.length;
|
|
1507
|
+
connectButton.disabled = operationPending || state === "ready" && !modelPending() || state === "busy";
|
|
1477
1508
|
disconnectButton.disabled = operationPending || state === "disconnected";
|
|
1478
1509
|
revokeButton.disabled = operationPending || control.grantState !== "valid";
|
|
1479
1510
|
const phase = control.task?.managedPhase;
|
|
@@ -1524,6 +1555,11 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1524
1555
|
disclosureProvider.textContent = messages.disclosureProvider;
|
|
1525
1556
|
disclosureNoGuarantee.textContent = messages.disclosureNoGuarantee;
|
|
1526
1557
|
agentLabelText.textContent = messages.agentLabel;
|
|
1558
|
+
modelLabelText.textContent = messages.modelLabel;
|
|
1559
|
+
modelHint.textContent = messages.modelHint;
|
|
1560
|
+
if (modelSelect.options.length === 1 && modelSelect.options[0]?.value === "") {
|
|
1561
|
+
modelSelect.options[0].textContent = messages.modelLoading;
|
|
1562
|
+
}
|
|
1527
1563
|
codexOption.textContent = messages.codexManaged;
|
|
1528
1564
|
connectButton.textContent = messages.connectManaged;
|
|
1529
1565
|
disconnectButton.textContent = messages.disconnectManaged;
|
|
@@ -1555,6 +1591,25 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1555
1591
|
disclosure.addEventListener("keydown", handleDisclosureKeydown);
|
|
1556
1592
|
settings.addEventListener("toggle", options.onViewChange);
|
|
1557
1593
|
managedResult.addEventListener("toggle", options.onViewChange);
|
|
1594
|
+
const handleModelChange = () => {
|
|
1595
|
+
refreshControlActions();
|
|
1596
|
+
refreshActions();
|
|
1597
|
+
};
|
|
1598
|
+
modelSelect.addEventListener("change", handleModelChange);
|
|
1599
|
+
const renderModels = () => {
|
|
1600
|
+
const previous = modelSelect.value;
|
|
1601
|
+
const models = control?.models ?? [];
|
|
1602
|
+
modelSelect.replaceChildren(
|
|
1603
|
+
...(models.length ? models : [""]).map((model) => {
|
|
1604
|
+
const option = createMarkedElement(document, "option");
|
|
1605
|
+
option.value = model;
|
|
1606
|
+
option.textContent = model || messages.modelLoading;
|
|
1607
|
+
return option;
|
|
1608
|
+
})
|
|
1609
|
+
);
|
|
1610
|
+
modelSelect.value = models.includes(previous) ? previous : control?.requestedModel ?? models[0] ?? "";
|
|
1611
|
+
};
|
|
1612
|
+
renderModels();
|
|
1558
1613
|
const unsubscribeLocale = options.subscribeLocale(applyMessages);
|
|
1559
1614
|
applyMessages();
|
|
1560
1615
|
status.textContent = messages.ready;
|
|
@@ -1597,6 +1652,7 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1597
1652
|
resolveButton,
|
|
1598
1653
|
cancelManagedButton,
|
|
1599
1654
|
connectButton,
|
|
1655
|
+
readModel: () => modelSelect.value || void 0,
|
|
1600
1656
|
disconnectButton,
|
|
1601
1657
|
revokeButton,
|
|
1602
1658
|
confirmDisclosure(annotation) {
|
|
@@ -1653,20 +1709,24 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1653
1709
|
},
|
|
1654
1710
|
renderControlStatus(value) {
|
|
1655
1711
|
control = value;
|
|
1712
|
+
renderModels();
|
|
1656
1713
|
controlStatus.textContent = controlStatusText(value, messages, framework);
|
|
1657
1714
|
controlStatus.dataset.state = value.connectionState;
|
|
1658
1715
|
disclosureNoGuarantee.textContent = value.mode === "managed" ? messages.disclosureManagedGuarantee : messages.disclosureNoGuarantee;
|
|
1659
1716
|
refreshControlActions();
|
|
1717
|
+
refreshActions();
|
|
1660
1718
|
options.onControlChange?.(value);
|
|
1661
1719
|
options.onViewChange();
|
|
1662
1720
|
},
|
|
1663
1721
|
renderControlUnavailable() {
|
|
1664
1722
|
control = void 0;
|
|
1723
|
+
renderModels();
|
|
1665
1724
|
controlStatus.dataset.state = "unavailable";
|
|
1666
1725
|
controlStatus.textContent = messages.controlUnavailable;
|
|
1667
1726
|
disclosureNoGuarantee.textContent = messages.disclosureNoGuarantee;
|
|
1668
1727
|
refreshControlActions();
|
|
1669
1728
|
options.onControlChange?.(void 0);
|
|
1729
|
+
refreshActions();
|
|
1670
1730
|
options.onViewChange();
|
|
1671
1731
|
},
|
|
1672
1732
|
renderManagedResult(result) {
|
|
@@ -1694,6 +1754,7 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1694
1754
|
setControlBusy(nextBusy) {
|
|
1695
1755
|
controlOperationBusy = nextBusy;
|
|
1696
1756
|
refreshControlActions();
|
|
1757
|
+
refreshActions();
|
|
1697
1758
|
},
|
|
1698
1759
|
setContextReady(ready) {
|
|
1699
1760
|
contextReady = ready;
|
|
@@ -1711,6 +1772,7 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
|
|
|
1711
1772
|
disclosure.removeEventListener("keydown", handleDisclosureKeydown);
|
|
1712
1773
|
settings.removeEventListener("toggle", options.onViewChange);
|
|
1713
1774
|
managedResult.removeEventListener("toggle", options.onViewChange);
|
|
1775
|
+
modelSelect.removeEventListener("change", handleModelChange);
|
|
1714
1776
|
unsubscribeLocale();
|
|
1715
1777
|
}
|
|
1716
1778
|
});
|