@spotpatch/runtime 1.15.1 → 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.
@@ -4,6 +4,7 @@ import { SpotPatchRuntimeConfig } from '@spotpatch/shared';
4
4
  interface ExternalHandoffPanel {
5
5
  readonly cancelManagedButton: HTMLButtonElement;
6
6
  readonly connectButton: HTMLButtonElement;
7
+ readonly readModel: () => string | undefined;
7
8
  readonly disconnectButton: HTMLButtonElement;
8
9
  readonly refreshButton: HTMLButtonElement;
9
10
  readonly root: HTMLElement;
@@ -4,6 +4,7 @@ import { SpotPatchRuntimeConfig } from '@spotpatch/shared';
4
4
  interface ExternalHandoffPanel {
5
5
  readonly cancelManagedButton: HTMLButtonElement;
6
6
  readonly connectButton: HTMLButtonElement;
7
+ readonly readModel: () => string | undefined;
7
8
  readonly disconnectButton: HTMLButtonElement;
8
9
  readonly refreshButton: HTMLButtonElement;
9
10
  readonly root: HTMLElement;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getExternalHandoffExtension,
3
3
  registerExternalHandoffExtension
4
- } from "./chunk-ASRUAKA5.js";
4
+ } from "./chunk-TEH2CCO3.js";
5
5
  import {
6
6
  createButton,
7
7
  createMarkedElement
@@ -203,6 +203,9 @@ function parseTask(value) {
203
203
  ...value.resultExpiresAt === void 0 ? {} : { resultExpiresAt: value.resultExpiresAt }
204
204
  });
205
205
  }
206
+ function validModel(value) {
207
+ return typeof value === "string" && value.length > 0 && value.length <= EXTERNAL_AGENT_CONTROL_LIMITS.maximumModelCharacters && value.trim() === value;
208
+ }
206
209
  function parseExternalAgentControlStatus(value) {
207
210
  if (!record(value) || !optionalKeys(
208
211
  value,
@@ -216,8 +219,8 @@ function parseExternalAgentControlStatus(value) {
216
219
  "sequence",
217
220
  "updatedAt"
218
221
  ],
219
- ["effectiveModel", "error", "requestedModel", "task"]
220
- ) || value.schemaVersion !== 1 || !integer(value.sequence) || !member(MODES, value.mode) || !member(CONNECTION_STATES, value.connectionState) || !member(AUTH_STATES, value.authReadiness) || !member(GRANT_STATES, value.grantState) || !validTimestamp(value.updatedAt) || value.requestedModel !== void 0 && (typeof value.requestedModel !== "string" || value.requestedModel.length === 0 || value.requestedModel.length > 128) || value.effectiveModel !== void 0 && (typeof value.effectiveModel !== "string" || value.effectiveModel.length === 0 || value.effectiveModel.length > 128) || !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") {
222
+ ["effectiveModel", "error", "requestedModel", "task", "models"]
223
+ ) || value.schemaVersion !== 1 || !integer(value.sequence) || !member(MODES, value.mode) || !member(CONNECTION_STATES, value.connectionState) || !member(AUTH_STATES, value.authReadiness) || !member(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 > 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") {
221
224
  throw new TypeError("Invalid external Agent control status.");
222
225
  }
223
226
  let error;
@@ -244,6 +247,7 @@ function parseExternalAgentControlStatus(value) {
244
247
  connectionState: value.connectionState,
245
248
  authReadiness: value.authReadiness,
246
249
  grantState: value.grantState,
250
+ ...value.models === void 0 ? {} : { models: Object.freeze([...value.models]) },
247
251
  ...value.requestedModel === void 0 ? {} : { requestedModel: value.requestedModel },
248
252
  ...value.effectiveModel === void 0 ? {} : { effectiveModel: value.effectiveModel },
249
253
  ...value.task === void 0 ? {} : { task: parseTask(value.task) },
@@ -742,11 +746,13 @@ function createExternalHandoffWorkflow(fetch, panel, selectedAnnotation, session
742
746
  }
743
747
  };
744
748
  const handleConnectClick = () => {
749
+ const model = options.panel.readModel();
745
750
  void performControlAction(
746
751
  () => controlClient.connect({
747
752
  requestId: createRequestId(options.window),
748
753
  adapterKind: "codex",
749
- profile: EXTERNAL_AGENT_MANAGED_PROFILE
754
+ profile: EXTERNAL_AGENT_MANAGED_PROFILE,
755
+ ...model === void 0 ? {} : { model }
750
756
  })
751
757
  );
752
758
  };
@@ -1005,6 +1011,10 @@ var MESSAGES = Object.freeze({
1005
1011
  "en-US": Object.freeze({
1006
1012
  title: "External Agent connection",
1007
1013
  agentLabel: "Agent",
1014
+ modelLabel: "Managed Codex model",
1015
+ modelLoading: "Connect to load available models",
1016
+ modelHint: "Applies only to this managed connection, not API Key settings. Apply changes before publishing; switching reconnects Codex.",
1017
+ applyModel: "Apply model",
1008
1018
  codexManaged: "Codex \xB7 managed (experimental)",
1009
1019
  connectManaged: "Connect Codex",
1010
1020
  disconnectManaged: "Disconnect",
@@ -1043,7 +1053,7 @@ var MESSAGES = Object.freeze({
1043
1053
  "install-agent": "Install Codex and retry.",
1044
1054
  "use-supported-version": "Use a schema-compatible Codex version.",
1045
1055
  "sign-in": "Sign in with Codex, then retry.",
1046
- "choose-available-model": "Choose an available model in Codex configuration.",
1056
+ "choose-available-model": "Choose an available model and reconnect Codex.",
1047
1057
  "use-inbox": "Continue with the Agent inbox fallback.",
1048
1058
  "confirm-managed-access": "Revoke the invalid grant and confirm access again.",
1049
1059
  "review-candidate-diff": "Review the candidate diff and validation output.",
@@ -1092,6 +1102,10 @@ var MESSAGES = Object.freeze({
1092
1102
  "zh-CN": Object.freeze({
1093
1103
  title: "\u5916\u90E8 Agent \u8FDE\u63A5",
1094
1104
  agentLabel: "Agent",
1105
+ modelLabel: "\u53D7\u7BA1 Codex \u6A21\u578B",
1106
+ modelLoading: "\u8FDE\u63A5\u540E\u52A0\u8F7D\u53EF\u7528\u6A21\u578B",
1107
+ 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",
1108
+ applyModel: "\u5E94\u7528\u6A21\u578B",
1095
1109
  codexManaged: "Codex \xB7 \u53D7\u7BA1\u6A21\u5F0F\uFF08\u5B9E\u9A8C\u6027\uFF09",
1096
1110
  connectManaged: "\u8FDE\u63A5 Codex",
1097
1111
  disconnectManaged: "\u65AD\u5F00\u8FDE\u63A5",
@@ -1130,7 +1144,7 @@ var MESSAGES = Object.freeze({
1130
1144
  "install-agent": "\u5B89\u88C5 Codex \u540E\u91CD\u8BD5\u3002",
1131
1145
  "use-supported-version": "\u6539\u7528 Schema \u517C\u5BB9\u7684 Codex \u7248\u672C\u3002",
1132
1146
  "sign-in": "\u767B\u5F55 Codex \u540E\u91CD\u8BD5\u3002",
1133
- "choose-available-model": "\u5728 Codex \u914D\u7F6E\u4E2D\u9009\u62E9\u53EF\u7528\u6A21\u578B\u3002",
1147
+ "choose-available-model": "\u9009\u62E9\u53EF\u7528\u6A21\u578B\u540E\u91CD\u65B0\u8FDE\u63A5 Codex\u3002",
1134
1148
  "use-inbox": "\u7EE7\u7EED\u4F7F\u7528 Agent \u6536\u4EF6\u7BB1\u964D\u7EA7\u8DEF\u5F84\u3002",
1135
1149
  "confirm-managed-access": "\u64A4\u9500\u65E0\u6548\u6388\u6743\u5E76\u91CD\u65B0\u786E\u8BA4\u3002",
1136
1150
  "review-candidate-diff": "\u68C0\u67E5\u5019\u9009 diff \u548C\u9A8C\u8BC1\u8F93\u51FA\u3002",
@@ -1352,6 +1366,11 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1352
1366
  codexOption.value = "codex";
1353
1367
  agentSelect.append(codexOption);
1354
1368
  agentLabel.append(agentLabelText, agentSelect);
1369
+ const modelLabel = createMarkedElement(document, "label");
1370
+ const modelLabelText = createMarkedElement(document, "span");
1371
+ const modelSelect = createMarkedElement(document, "select");
1372
+ const modelHint = createMarkedElement(document, "p");
1373
+ modelLabel.append(modelLabelText, modelSelect);
1355
1374
  const controlStatus = createMarkedElement(document, "p");
1356
1375
  controlStatus.className = "spotpatch-external-control-status";
1357
1376
  controlStatus.setAttribute("role", "status");
@@ -1374,7 +1393,14 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1374
1393
  const managedResultSummary = createMarkedElement(document, "p");
1375
1394
  const managedResultDiff = createMarkedElement(document, "pre");
1376
1395
  managedResult.append(managedResultTitle, managedResultSummary, managedResultDiff);
1377
- controlRoot.append(agentLabel, controlStatus, controlActions, managedResult);
1396
+ controlRoot.append(
1397
+ agentLabel,
1398
+ modelLabel,
1399
+ modelHint,
1400
+ controlStatus,
1401
+ controlActions,
1402
+ managedResult
1403
+ );
1378
1404
  const resolveButton = createButton(document, "", "spotpatch-external-resolve");
1379
1405
  resolveButton.hidden = true;
1380
1406
  const settings = createMarkedElement(document, "details");
@@ -1431,15 +1457,19 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1431
1457
  } catch {
1432
1458
  }
1433
1459
  };
1460
+ const modelPending = () => control?.mode === "managed" && modelSelect.value !== "" && modelSelect.value !== control.requestedModel;
1461
+ const controlPending = () => controlOperationBusy || control?.connectionState === "diagnosing" || control?.connectionState === "connecting" || control?.connectionState === "disconnecting";
1434
1462
  const refreshActions = () => {
1435
1463
  sendButton.textContent = retryable ? messages.retry : activeAdapter?.canDispatch === true ? messages.send : messages.inboxSend;
1436
- sendButton.disabled = !visible || !brokerReady || !contextReady || operationBusy || !retryable && dispatchBlocksSend;
1464
+ sendButton.disabled = !visible || !brokerReady || !contextReady || operationBusy || controlPending() || modelPending() || !retryable && dispatchBlocksSend;
1437
1465
  sendButton.setAttribute("aria-busy", String(operationBusy));
1438
1466
  refreshButton.disabled = !visible || operationBusy;
1439
1467
  resolveButton.hidden = !unknownDelivery;
1440
1468
  resolveButton.disabled = !visible || operationBusy || !unknownDelivery;
1441
1469
  };
1442
1470
  const refreshControlActions = () => {
1471
+ connectButton.textContent = modelPending() ? messages.applyModel : messages.connectManaged;
1472
+ modelSelect.disabled = true;
1443
1473
  if (control === void 0) {
1444
1474
  connectButton.disabled = true;
1445
1475
  disconnectButton.disabled = true;
@@ -1448,8 +1478,9 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1448
1478
  return;
1449
1479
  }
1450
1480
  const state = control.connectionState;
1451
- const operationPending = controlOperationBusy || state === "diagnosing" || state === "connecting" || state === "disconnecting";
1452
- connectButton.disabled = operationPending || state === "ready" || state === "busy";
1481
+ const operationPending = controlPending();
1482
+ modelSelect.disabled = operationPending || state === "busy" || !control.models?.length;
1483
+ connectButton.disabled = operationPending || state === "ready" && !modelPending() || state === "busy";
1453
1484
  disconnectButton.disabled = operationPending || state === "disconnected";
1454
1485
  revokeButton.disabled = operationPending || control.grantState !== "valid";
1455
1486
  const phase = control.task?.managedPhase;
@@ -1500,6 +1531,11 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1500
1531
  disclosureProvider.textContent = messages.disclosureProvider;
1501
1532
  disclosureNoGuarantee.textContent = messages.disclosureNoGuarantee;
1502
1533
  agentLabelText.textContent = messages.agentLabel;
1534
+ modelLabelText.textContent = messages.modelLabel;
1535
+ modelHint.textContent = messages.modelHint;
1536
+ if (modelSelect.options.length === 1 && modelSelect.options[0]?.value === "") {
1537
+ modelSelect.options[0].textContent = messages.modelLoading;
1538
+ }
1503
1539
  codexOption.textContent = messages.codexManaged;
1504
1540
  connectButton.textContent = messages.connectManaged;
1505
1541
  disconnectButton.textContent = messages.disconnectManaged;
@@ -1531,6 +1567,25 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1531
1567
  disclosure.addEventListener("keydown", handleDisclosureKeydown);
1532
1568
  settings.addEventListener("toggle", options.onViewChange);
1533
1569
  managedResult.addEventListener("toggle", options.onViewChange);
1570
+ const handleModelChange = () => {
1571
+ refreshControlActions();
1572
+ refreshActions();
1573
+ };
1574
+ modelSelect.addEventListener("change", handleModelChange);
1575
+ const renderModels = () => {
1576
+ const previous = modelSelect.value;
1577
+ const models = control?.models ?? [];
1578
+ modelSelect.replaceChildren(
1579
+ ...(models.length ? models : [""]).map((model) => {
1580
+ const option = createMarkedElement(document, "option");
1581
+ option.value = model;
1582
+ option.textContent = model || messages.modelLoading;
1583
+ return option;
1584
+ })
1585
+ );
1586
+ modelSelect.value = models.includes(previous) ? previous : control?.requestedModel ?? models[0] ?? "";
1587
+ };
1588
+ renderModels();
1534
1589
  const unsubscribeLocale = options.subscribeLocale(applyMessages);
1535
1590
  applyMessages();
1536
1591
  status.textContent = messages.ready;
@@ -1573,6 +1628,7 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1573
1628
  resolveButton,
1574
1629
  cancelManagedButton,
1575
1630
  connectButton,
1631
+ readModel: () => modelSelect.value || void 0,
1576
1632
  disconnectButton,
1577
1633
  revokeButton,
1578
1634
  confirmDisclosure(annotation) {
@@ -1629,20 +1685,24 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1629
1685
  },
1630
1686
  renderControlStatus(value) {
1631
1687
  control = value;
1688
+ renderModels();
1632
1689
  controlStatus.textContent = controlStatusText(value, messages, framework);
1633
1690
  controlStatus.dataset.state = value.connectionState;
1634
1691
  disclosureNoGuarantee.textContent = value.mode === "managed" ? messages.disclosureManagedGuarantee : messages.disclosureNoGuarantee;
1635
1692
  refreshControlActions();
1693
+ refreshActions();
1636
1694
  options.onControlChange?.(value);
1637
1695
  options.onViewChange();
1638
1696
  },
1639
1697
  renderControlUnavailable() {
1640
1698
  control = void 0;
1699
+ renderModels();
1641
1700
  controlStatus.dataset.state = "unavailable";
1642
1701
  controlStatus.textContent = messages.controlUnavailable;
1643
1702
  disclosureNoGuarantee.textContent = messages.disclosureNoGuarantee;
1644
1703
  refreshControlActions();
1645
1704
  options.onControlChange?.(void 0);
1705
+ refreshActions();
1646
1706
  options.onViewChange();
1647
1707
  },
1648
1708
  renderManagedResult(result) {
@@ -1670,6 +1730,7 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1670
1730
  setControlBusy(nextBusy) {
1671
1731
  controlOperationBusy = nextBusy;
1672
1732
  refreshControlActions();
1733
+ refreshActions();
1673
1734
  },
1674
1735
  setContextReady(ready) {
1675
1736
  contextReady = ready;
@@ -1687,6 +1748,7 @@ function createExternalHandoffPanel(document, framework, locale, sessionId, subs
1687
1748
  disclosure.removeEventListener("keydown", handleDisclosureKeydown);
1688
1749
  settings.removeEventListener("toggle", options.onViewChange);
1689
1750
  managedResult.removeEventListener("toggle", options.onViewChange);
1751
+ modelSelect.removeEventListener("change", handleModelChange);
1690
1752
  unsubscribeLocale();
1691
1753
  }
1692
1754
  });