@inventec/dsh-copilot-auth 1.2.18 → 1.2.19

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/lib/client.js CHANGED
@@ -34,13 +34,12 @@ var import_react = require("react");
34
34
 
35
35
  // src/shared.mjs
36
36
  var ROUTE_PREFIX = "/copilot-auth";
37
- var PROTOCOL_VERSION = 2;
37
+ var PROTOCOL_VERSION = 3;
38
38
  var routes = () => ({
39
39
  start: `${ROUTE_PREFIX}/start`,
40
40
  state: `${ROUTE_PREFIX}/state`,
41
41
  status: `${ROUTE_PREFIX}/status`,
42
42
  logout: `${ROUTE_PREFIX}/logout`,
43
- cancel: `${ROUTE_PREFIX}/cancel`,
44
43
  refreshPreview: `${ROUTE_PREFIX}/refresh/preview`,
45
44
  refreshApply: `${ROUTE_PREFIX}/refresh/apply`,
46
45
  refreshRetire: `${ROUTE_PREFIX}/refresh/retire`
@@ -134,6 +133,41 @@ function refreshBlocked(flags) {
134
133
  const mode = flags?.catalogMode;
135
134
  return flags?.scopeAvailable === false || mode === "blocked" || mode === "unknown";
136
135
  }
136
+ function selectionFields(lastSelection = {}) {
137
+ const out = {};
138
+ if (lastSelection.selectedIds !== void 0) out.selectedIds = lastSelection.selectedIds;
139
+ if (lastSelection.clearOverrides !== void 0) out.clearOverrides = lastSelection.clearOverrides;
140
+ if (lastSelection.confirmEmpty !== void 0) out.confirmEmpty = lastSelection.confirmEmpty;
141
+ return out;
142
+ }
143
+ function upgradeCandidate(state) {
144
+ const p = state.preview;
145
+ if (!p || state.liveUpgradeUsed) return null;
146
+ if ((p.diff?.removed?.length ?? 0) === 0) return null;
147
+ if (p.evidence?.source !== "cache" || p.evidence?.stale === true) return null;
148
+ if (p.catalogSource !== "latest") return null;
149
+ return {
150
+ type: "preview",
151
+ operation: p.operation,
152
+ catalogSource: p.catalogSource,
153
+ ...selectionFields(state.lastSelection)
154
+ };
155
+ }
156
+ function enterConfirming({ flags, preview, staleNotice, lastSelection }) {
157
+ const state = {
158
+ name: "confirming",
159
+ flags: flags ?? initial.flags,
160
+ preview,
161
+ staleNotice: staleNotice === true,
162
+ materializing: false,
163
+ awaitingUpgrade: false,
164
+ liveUpgradeUsed: false,
165
+ lastSelection: lastSelection ?? {}
166
+ };
167
+ const effect = upgradeCandidate(state);
168
+ if (!effect) return [state, null];
169
+ return [{ ...state, liveUpgradeUsed: true, awaitingUpgrade: true, materializing: true }, effect];
170
+ }
137
171
  function reduce(state, event) {
138
172
  switch (state.name) {
139
173
  case "idle":
@@ -146,14 +180,10 @@ function reduce(state, event) {
146
180
  return [{
147
181
  name: "previewing",
148
182
  flags: state.flags ?? initial.flags,
149
- operation: event.operation === "rebuild" ? "rebuild" : "supplement",
183
+ operation: "manage",
150
184
  catalogSource: event.catalogSource,
151
185
  stale: false
152
- }, {
153
- type: "preview",
154
- operation: event.operation === "rebuild" ? "rebuild" : "supplement",
155
- catalogSource: event.catalogSource
156
- }];
186
+ }, { type: "preview", operation: "manage", catalogSource: event.catalogSource }];
157
187
  }
158
188
  if (event.type === "init" && state.name === "idle") return [state, { type: "status" }];
159
189
  if (event.type === "check" && state.name === "resultUnknown") {
@@ -184,7 +214,7 @@ function reduce(state, event) {
184
214
  }
185
215
  case "previewing": {
186
216
  if (event.type === "preview-ok") {
187
- return [{ name: "confirming", flags: state.flags ?? initial.flags, preview: event.preview, staleNotice: state.stale === true }, null];
217
+ return enterConfirming({ flags: state.flags ?? initial.flags, preview: event.preview, staleNotice: state.stale === true });
188
218
  }
189
219
  if (event.type === "preview-fail") return [{ name: "failed", flags: state.flags ?? initial.flags, error: event.error }, null];
190
220
  return [state, null];
@@ -192,25 +222,63 @@ function reduce(state, event) {
192
222
  case "confirming": {
193
223
  const p = state.preview;
194
224
  if (event.type === "select") {
225
+ const lastSelection = { ...selectionFields({
226
+ selectedIds: event.selectedIds,
227
+ clearOverrides: event.clearOverrides,
228
+ confirmEmpty: event.confirmEmpty
229
+ }) };
195
230
  return [{
196
231
  name: "confirming",
197
232
  flags: state.flags ?? initial.flags,
198
233
  preview: p,
199
234
  materializing: true,
235
+ awaitingUpgrade: false,
236
+ liveUpgradeUsed: state.liveUpgradeUsed ?? false,
237
+ lastSelection,
200
238
  staleNotice: state.staleNotice
201
239
  }, {
202
240
  type: "preview",
203
241
  operation: p.operation,
204
242
  catalogSource: p.catalogSource,
205
243
  basePreviewId: p.previewId,
206
- selectedIds: event.selectedIds ?? [],
207
- confirmEmpty: event.confirmEmpty === true
244
+ ...selectionFields(lastSelection)
208
245
  }];
209
246
  }
210
247
  if (event.type === "preview-ok") {
211
- return [{ name: "confirming", flags: state.flags ?? initial.flags, preview: event.preview, staleNotice: state.stale === true, materializing: false }, null];
248
+ const wasUpgrade = state.awaitingUpgrade === true;
249
+ const landed = {
250
+ name: "confirming",
251
+ flags: state.flags ?? initial.flags,
252
+ preview: event.preview,
253
+ materializing: false,
254
+ awaitingUpgrade: false,
255
+ liveUpgradeUsed: state.liveUpgradeUsed ?? false,
256
+ lastSelection: state.lastSelection ?? {},
257
+ staleNotice: wasUpgrade && event.preview?.evidence?.source !== "live" || state.staleNotice === true
258
+ };
259
+ const effect = upgradeCandidate(landed);
260
+ if (effect) return [{ ...landed, liveUpgradeUsed: true, awaitingUpgrade: true, materializing: true }, effect];
261
+ return [landed, null];
212
262
  }
213
263
  if (event.type === "preview-fail") {
264
+ if (state.awaitingUpgrade === true && p) {
265
+ return [{
266
+ name: "confirming",
267
+ flags: state.flags ?? initial.flags,
268
+ preview: p,
269
+ materializing: true,
270
+ awaitingUpgrade: false,
271
+ liveUpgradeUsed: state.liveUpgradeUsed ?? true,
272
+ lastSelection: state.lastSelection ?? {},
273
+ staleNotice: true
274
+ }, {
275
+ type: "preview",
276
+ operation: p.operation,
277
+ catalogSource: p.catalogSource,
278
+ basePreviewId: p.previewId,
279
+ ...selectionFields(state.lastSelection)
280
+ }];
281
+ }
214
282
  return [{ name: "failed", flags: state.flags ?? initial.flags, error: event.error }, null];
215
283
  }
216
284
  if (event.type === "start") {
@@ -219,19 +287,14 @@ function reduce(state, event) {
219
287
  flags: state.flags ?? initial.flags,
220
288
  preview: p,
221
289
  materializing: true,
290
+ awaitingUpgrade: false,
291
+ liveUpgradeUsed: state.liveUpgradeUsed ?? false,
292
+ lastSelection: state.lastSelection ?? {},
222
293
  staleNotice: state.staleNotice
223
- }, {
224
- type: "preview",
225
- operation: event.operation === "rebuild" ? "rebuild" : p.operation,
226
- catalogSource: event.catalogSource
227
- }];
294
+ }, { type: "preview", operation: p.operation, catalogSource: event.catalogSource }];
228
295
  }
229
296
  if (event.type === "confirm") {
230
297
  if (state.materializing) return [state, null];
231
- const isRebuild = p.operation === "rebuild";
232
- const emptyTarget = isRebuild && (p.diff?.targetView?.models ?? []).length === 0;
233
- if (isRebuild && event.second !== true) return [state, null];
234
- if (emptyTarget && event.empty !== true) return [state, null];
235
298
  if (p.evidence?.stale === true) return [state, null];
236
299
  return [{ name: "applying", flags: state.flags ?? initial.flags, preview: p }, { type: "apply", previewId: p.previewId, operationId: p.operationId }];
237
300
  }
@@ -303,8 +366,10 @@ async function runEffect(effect, fetchImpl) {
303
366
  const res = await post(r.refreshPreview, {
304
367
  operation: effect.operation,
305
368
  ...effect.catalogSource ? { catalogSource: effect.catalogSource } : {},
306
- ...effect.basePreviewId ? { basePreviewId: effect.basePreviewId, selectedIds: effect.selectedIds ?? [] } : {},
307
- ...effect.confirmEmpty ? { confirmEmpty: true } : {}
369
+ ...effect.basePreviewId !== void 0 ? { basePreviewId: effect.basePreviewId } : {},
370
+ ...effect.selectedIds !== void 0 ? { selectedIds: effect.selectedIds } : {},
371
+ ...effect.clearOverrides !== void 0 ? { clearOverrides: effect.clearOverrides } : {},
372
+ ...effect.confirmEmpty !== void 0 ? { confirmEmpty: effect.confirmEmpty } : {}
308
373
  });
309
374
  if (res.ok) return { type: "preview-ok", preview: res.body };
310
375
  return { type: "preview-fail", error: res.error?.details?.errorCode ?? res.error?.messageKey };
@@ -406,7 +471,7 @@ function createAuthFlow({ fetchImpl, clock = defaultClock(), onState = () => {
406
471
  emit({ phase: "failed", error: s?.error ?? "authorization-failed" });
407
472
  return;
408
473
  }
409
- if (s?.status === "withdrawal-pending-unverified" || s?.status === "timed-out-unverified") {
474
+ if (s?.status === "timed-out-unverified") {
410
475
  emit({ phase: "risk", riskKind: s.status });
411
476
  return;
412
477
  }
@@ -486,6 +551,10 @@ function createAuthFlow({ fetchImpl, clock = defaultClock(), onState = () => {
486
551
  emit({ phase: "idle", error: r.error?.messageKey, connectivity: "manual" });
487
552
  return;
488
553
  }
554
+ if (r.body?.status === "authorized" && body.configured !== true) {
555
+ emit({ phase: "idle" });
556
+ return;
557
+ }
489
558
  applySnapshot(gen, r.body);
490
559
  }
491
560
  async function start() {
@@ -521,14 +590,6 @@ function createAuthFlow({ fetchImpl, clock = defaultClock(), onState = () => {
521
590
  }
522
591
  emit({ phase: "failed", error: errorCode ?? r.error?.messageKey });
523
592
  }
524
- async function cancel() {
525
- const r = await requestJson(fetchImpl, "/copilot-auth/cancel", { method: "POST" });
526
- if (r.ok) {
527
- emit({ withdrawalDelivery: r.body?.withdrawalDelivery ?? "unavailable" });
528
- return;
529
- }
530
- emit({ withdrawalDelivery: "failed", error: r.error?.details?.errorCode ?? r.error?.messageKey });
531
- }
532
593
  async function logout() {
533
594
  const gen = ++generation;
534
595
  clearTimer();
@@ -553,7 +614,7 @@ function createAuthFlow({ fetchImpl, clock = defaultClock(), onState = () => {
553
614
  generation += 1;
554
615
  clearTimer();
555
616
  }
556
- return { init, start, cancel, logout, refresh, dispose };
617
+ return { init, start, logout, refresh, dispose };
557
618
  }
558
619
 
559
620
  // src/client.jsx
@@ -572,9 +633,6 @@ var DICTS = {
572
633
  loading: "\u2026",
573
634
  login: "Sign in",
574
635
  logout: "Sign out",
575
- withdrawAuth: "Request withdrawal",
576
- withdrawal: "Withdrawal requested; the outcome remains unverified.",
577
- withdrawalUnavailable: "The withdrawal request could not be sent to the host; the outcome remains unverified.",
578
636
  authUnsafe: "Safe completion of the authorization flow is unconfirmed. Sign-out and a new authorization attempt are unavailable.",
579
637
  attemptTimeout: "Authorization wait timed out; the outcome remains unverified. A new authorization attempt is unavailable. Check the status or verify it manually.",
580
638
  attemptShared: "An authorization attempt is already running in this instance.",
@@ -598,28 +656,30 @@ var DICTS = {
598
656
  errHttp: "The authorization request failed. Check status and retry.",
599
657
  logoutScope: "This removes Copilot authorization from this credential store and affects other instances using it. It does not delete your GitHub account.",
600
658
  logoutFailed: "Sign-out did not complete; authorization credentials may remain. Please retry.",
601
- // ---- Model management (protocol v2, design §5) ----
602
- supplement: "Add models",
603
- rebuild: "Rebuild model list",
604
- supplementTitle: "Add models",
605
- rebuildTitle: "Rebuild model list",
606
- candidates: "Models available to add",
659
+ // ---- Model management (protocol v3, design §5 / ADR 0005) ----
660
+ manageModels: "Manage model list",
607
661
  selectAll: "Select all",
608
662
  selectNone: "Deselect all",
609
- supplementRisk: "Existing models and customizations will be kept. Only selected models will be added.",
610
- rebuildRisk: "Rebuilding clears model parameters and overrides. Other provider settings remain unchanged.",
611
- clearRisk: "This clears the Copilot model list and its model customizations. Confirm clearing separately.",
612
- secondConfirm: "This is destructive. Click again to confirm.",
663
+ alignAction: "Align with account & catalog",
664
+ groupAddable: "Available to add",
665
+ groupListed: "In list",
666
+ groupRemoval: "Proposed for removal",
667
+ retain: "Keep: re-check to retain",
668
+ customizedBadge: "Customized",
669
+ clearOverrides: "Also clear all model customizations.",
670
+ inheritedOverrides: "Inherited model customizations cannot be cleared here.",
671
+ clearRisk: "Clearing hides nothing \u2014 all available models stay listed; to trim, keep only the ones you check.",
613
672
  applyChanges: "Apply changes",
614
- addedModels: "Models to add",
615
- removedModels: "Models to be removed",
616
- keptModels: "Kept",
617
- removedAccount: "Not included in this account model list",
673
+ removalRisk: "{count} listed model(s) will be removed; their customizations are removed with them.",
674
+ summaryLine: "After applying: {total} model(s) \u2014 {kept} kept \xB7 {added} added \xB7 {removed} removed",
675
+ catalogNotice: "{count} catalog entries will be added",
676
+ noChanges: "No changes and no new catalog entries.",
677
+ removalNeedsLive: "Removals require live account evidence",
678
+ removedAccount: "Not reported by this account",
618
679
  removedUnresolvable: "Not resolvable by the current catalog",
619
- warnings: "Warnings",
620
680
  skippedModels: "Upstream entries skipped by validation",
621
681
  srcLive: "Account models: live",
622
- srcCache: "Account models: cached at {time}; add-only use",
682
+ srcCache: "Account models: cached at {time}; removals require upgrading to live evidence",
623
683
  srcStale: "The cache has no trusted timestamp, is expired, or belongs to changed authorization; reference only.",
624
684
  srcLatest: "Catalog source: latest pi-ai from npm",
625
685
  srcLocal: "Catalog source: local (npm fetch failed)",
@@ -661,9 +721,6 @@ var DICTS = {
661
721
  loading: "\u2026",
662
722
  login: "\u6388\u6743\u767B\u5F55",
663
723
  logout: "\u9000\u51FA\u767B\u5F55",
664
- withdrawAuth: "\u8BF7\u6C42\u64A4\u56DE",
665
- withdrawal: "\u64A4\u56DE\u8BF7\u6C42\u5DF2\u53D1\u9001\uFF0C\u7ED3\u679C\u4ECD\u5F85\u6838\u5B9E\u3002",
666
- withdrawalUnavailable: "\u672A\u80FD\u5411\u5BBF\u4E3B\u53D1\u9001\u64A4\u56DE\u8BF7\u6C42\uFF0C\u7ED3\u679C\u4ECD\u5F85\u6838\u5B9E\u3002",
667
724
  authUnsafe: "\u5C1A\u4E0D\u80FD\u786E\u8BA4\u6388\u6743\u6D41\u7A0B\u5DF2\u5B89\u5168\u7ED3\u675F\uFF0C\u6682\u4E0D\u80FD\u9000\u51FA\u6216\u53D1\u8D77\u65B0\u7684\u6388\u6743\u5C1D\u8BD5\u3002",
668
725
  attemptTimeout: "\u7B49\u5F85\u6388\u6743\u8D85\u65F6\uFF0C\u7ED3\u679C\u4ECD\u5F85\u6838\u5B9E\u3002\u5F53\u524D\u4E0D\u80FD\u53D1\u8D77\u65B0\u7684\u6388\u6743\u5C1D\u8BD5\uFF0C\u8BF7\u67E5\u8BE2\u72B6\u6001\u6216\u4EBA\u5DE5\u6838\u5B9E\u3002",
669
726
  attemptShared: "\u6B64\u5B9E\u4F8B\u5DF2\u6709\u6388\u6743\u6B63\u5728\u8FDB\u884C\u3002",
@@ -686,28 +743,30 @@ var DICTS = {
686
743
  errHttp: "\u6388\u6743\u8BF7\u6C42\u5931\u8D25\u3002\u8BF7\u67E5\u8BE2\u72B6\u6001\u540E\u91CD\u8BD5\u3002",
687
744
  logoutScope: "\u5C06\u6E05\u9664\u6B64\u51ED\u636E\u5E93\u4E2D\u7684 Copilot \u6388\u6743\uFF0C\u4F7F\u7528\u540C\u4E00\u51ED\u636E\u5E93\u7684\u5176\u4ED6\u5B9E\u4F8B\u4E5F\u4F1A\u53D7\u5230\u5F71\u54CD\u3002\u6B64\u64CD\u4F5C\u4E0D\u6CE8\u9500 GitHub \u8D26\u53F7\u3002",
688
745
  logoutFailed: "\u9000\u51FA\u767B\u5F55\u672A\u5B8C\u6210\uFF0C\u6388\u6743\u51ED\u636E\u4ECD\u53EF\u80FD\u5B58\u5728\u3002\u8BF7\u91CD\u8BD5\u3002",
689
- // ---- 模型管理(协议 v2,设计§5) ----
690
- supplement: "\u8865\u5145\u6A21\u578B",
691
- rebuild: "\u91CD\u5EFA\u6A21\u578B\u5217\u8868",
692
- supplementTitle: "\u8865\u5145\u6A21\u578B",
693
- rebuildTitle: "\u91CD\u5EFA\u6A21\u578B\u5217\u8868",
694
- candidates: "\u53EF\u65B0\u589E\u7684\u6A21\u578B",
746
+ // ---- 模型管理(协议 v3,设计§5 / ADR 0005) ----
747
+ manageModels: "\u7BA1\u7406\u6A21\u578B\u5217\u8868",
695
748
  selectAll: "\u5168\u9009",
696
749
  selectNone: "\u53D6\u6D88\u5168\u9009",
697
- supplementRisk: "\u5C06\u4FDD\u7559\u73B0\u6709\u6A21\u578B\u53CA\u5B9A\u5236\uFF0C\u53EA\u6DFB\u52A0\u4F60\u52FE\u9009\u7684\u6A21\u578B\u3002",
698
- rebuildRisk: "\u91CD\u5EFA\u5C06\u6E05\u9664\u73B0\u6709\u6A21\u578B\u53C2\u6570\u4E0E\u8986\u76D6\u914D\u7F6E\uFF0C\u5176\u4ED6\u63D0\u4F9B\u65B9\u8BBE\u7F6E\u4E0D\u53D8\u3002",
699
- clearRisk: "\u672C\u6B21\u5C06\u6E05\u7A7A Copilot \u6A21\u578B\u5217\u8868\u5E76\u6E05\u9664\u5176\u6A21\u578B\u5B9A\u5236\u3002\u8BF7\u5355\u72EC\u786E\u8BA4\u6E05\u7A7A\u3002",
700
- secondConfirm: "\u6B64\u64CD\u4F5C\u5177\u6709\u7834\u574F\u6027\uFF0C\u8BF7\u518D\u6B21\u70B9\u51FB\u786E\u8BA4\u3002",
750
+ alignAction: "\u5BF9\u9F50\u8D26\u53F7\u4E0E\u76EE\u5F55",
751
+ groupAddable: "\u53EF\u65B0\u589E",
752
+ groupListed: "\u5728\u5217",
753
+ groupRemoval: "\u5F85\u5220\u9664\u5019\u9009",
754
+ retain: "\u633D\u7559\uFF1A\u91CD\u65B0\u52FE\u9009\u4EE5\u4FDD\u7559",
755
+ customizedBadge: "\u6709\u5B9A\u5236",
756
+ clearOverrides: "\u540C\u65F6\u6E05\u9664\u5168\u90E8\u6A21\u578B\u5B9A\u5236\u3002",
757
+ inheritedOverrides: "\u5B58\u5728\u7EE7\u627F\u7684\u6A21\u578B\u5B9A\u5236\uFF0C\u65E0\u6CD5\u5728\u6B64\u6E05\u9664\u3002",
758
+ clearRisk: "\u6E05\u7A7A\u4E0D\u4F1A\u9690\u85CF\u6A21\u578B\u2014\u2014\u4F1A\u8BDD\u5185\u5C06\u663E\u793A\u5168\u90E8\u53EF\u7528\u6A21\u578B\uFF1B\u8981\u7CBE\u7B80\uFF0C\u53EA\u9700\u52FE\u9009\u4FDD\u7559\u9879\u3002",
701
759
  applyChanges: "\u5E94\u7528\u66F4\u6539",
702
- addedModels: "\u5C06\u6DFB\u52A0\u7684\u6A21\u578B",
703
- removedModels: "\u5C06\u79FB\u9664\u7684\u6A21\u578B",
704
- keptModels: "\u4FDD\u7559",
705
- removedAccount: "\u672A\u5305\u542B\u5728\u672C\u6B21\u8D26\u53F7\u6A21\u578B\u5217\u8868",
706
- removedUnresolvable: "\u5F53\u524D\u76EE\u5F55\u65E0\u6CD5\u89E3\u6790",
707
- warnings: "\u8B66\u544A",
760
+ removalRisk: "\u5C06\u79FB\u9664 {count} \u4E2A\u5728\u5217\u6A21\u578B\uFF0C\u5176\u5B9A\u5236\u968F\u4E4B\u6E05\u9664\u3002",
761
+ summaryLine: "\u5E94\u7528\u540E\u5171 {total} \u4E2A\uFF1A\u4FDD\u7559 {kept} \xB7 \u65B0\u589E {added} \xB7 \u79FB\u9664 {removed}",
762
+ catalogNotice: "\u76EE\u5F55\u5C06\u65B0\u589E {count} \u6761\u63CF\u8FF0",
763
+ noChanges: "\u65E0\u9700\u66F4\u6539\uFF0C\u76EE\u5F55\u4E5F\u65E0\u65B0\u6570\u636E\u3002",
764
+ removalNeedsLive: "\u79FB\u9664\u7C7B\u66F4\u6539\u9700\u8981\u5B9E\u65F6\u8D26\u53F7\u8BC1\u636E",
765
+ removedAccount: "\u8D26\u53F7\u672A\u62A5\u544A",
766
+ removedUnresolvable: "\u76EE\u5F55\u65E0\u6CD5\u89E3\u6790",
708
767
  skippedModels: "\u88AB\u6821\u9A8C\u8DF3\u8FC7\u7684\u4E0A\u6E38\u6761\u76EE",
709
768
  srcLive: "\u8D26\u53F7\u6A21\u578B\uFF1A\u5B9E\u65F6\u83B7\u53D6",
710
- srcCache: "\u8D26\u53F7\u6A21\u578B\uFF1A\u7F13\u5B58\uFF0C\u83B7\u53D6\u4E8E {time}\uFF0C\u4EC5\u53EF\u7528\u4E8E\u8865\u5145",
769
+ srcCache: "\u8D26\u53F7\u6A21\u578B\uFF1A\u7F13\u5B58\uFF0C\u83B7\u53D6\u4E8E {time}\uFF1B\u79FB\u9664\u7C7B\u66F4\u6539\u9700\u5347\u7EA7\u4E3A\u5B9E\u65F6\u8BC1\u636E",
711
770
  srcStale: "\u7F13\u5B58\u7F3A\u5C11\u53EF\u4FE1\u65F6\u95F4\u3001\u5DF2\u8FC7\u671F\u6216\u6388\u6743\u5DF2\u53D8\u5316\uFF0C\u4EC5\u4F9B\u53C2\u8003\u3002",
712
771
  srcLatest: "\u76EE\u5F55\u6765\u6E90\uFF1Anpm \u6700\u65B0 pi-ai",
713
772
  srcLocal: "\u76EE\u5F55\u6765\u6E90\uFF1A\u672C\u5730\u76EE\u5F55\uFF08npm \u62C9\u53D6\u5931\u8D25\uFF09",
@@ -872,134 +931,134 @@ function sampleThemeSurface() {
872
931
  }
873
932
  function RefreshModal({ t, flow, onSelect, onConfirm, onCancel, onOverlay }) {
874
933
  const p = flow.preview;
875
- const diff = p.diff ?? {};
876
- const isRebuild = p.operation === "rebuild";
877
- const emptyTarget = isRebuild && (diff.targetView?.models ?? []).length === 0;
878
- const candidates = diff.candidates ?? [];
934
+ const isStale = p.evidence?.stale === true;
935
+ const degradedCatalog = p.catalogSource === "local" || p.catalogSource === "overlay";
936
+ const locked = isStale || degradedCatalog;
937
+ const rows = p.rows ?? [];
938
+ const addableIds = rows.filter((r) => r.status === "addable").map((r) => r.id);
939
+ const rawAllIds = rows.filter((r) => r.status !== "addable").map((r) => r.id);
940
+ const removalRows = rows.filter((r) => r.status === "removal-proposal");
879
941
  const [localSel, setLocalSel] = (0, import_react.useState)(null);
942
+ const [coChecked, setCoChecked] = (0, import_react.useState)(false);
880
943
  (0, import_react.useEffect)(() => {
881
944
  setLocalSel(null);
945
+ setCoChecked(p.clearOverrides === true);
882
946
  }, [p.diff]);
883
- const selectedIds = new Set(localSel ?? (diff.added ?? []));
884
- const emitSel = (ids) => {
885
- setLocalSel(new Set(ids));
886
- onSelect(ids);
947
+ const lockedIds = rows.filter((r) => r.status === "removal-proposal" && locked).map((r) => r.id);
948
+ const selected = (() => {
949
+ const s = new Set(localSel ?? (p.diff?.selectedIds ?? []));
950
+ for (const id of lockedIds) s.add(id);
951
+ return s;
952
+ })();
953
+ const confirmEmptyOf = (set) => set.size === 0 && p.hadModels === true;
954
+ const emitSel = (nextSet) => {
955
+ setLocalSel(nextSet);
956
+ const ce = confirmEmptyOf(nextSet);
957
+ onSelect({ selectedIds: [...nextSet], clearOverrides: coChecked, ...ce ? { confirmEmpty: true } : {} });
958
+ };
959
+ const toggle = (id) => {
960
+ const next = new Set(selected);
961
+ if (next.has(id)) next.delete(id);
962
+ else next.add(id);
963
+ emitSel(next);
964
+ };
965
+ const toggleClearOverrides = (v) => {
966
+ setCoChecked(v);
967
+ const ce = confirmEmptyOf(selected);
968
+ onSelect({ selectedIds: [...selected], clearOverrides: v, ...ce ? { confirmEmpty: true } : {} });
887
969
  };
888
- const [stage, setStage] = (0, import_react.useState)(0);
970
+ const keptCount = rawAllIds.filter((id) => selected.has(id)).length;
971
+ const addedCount = addableIds.filter((id) => selected.has(id)).length;
972
+ const removedCount = rawAllIds.length - keptCount;
973
+ const total = keptCount + addedCount;
974
+ const emptyTarget = confirmEmptyOf(selected);
975
+ const applyBlocked = isStale || removedCount > 0 && (p.evidence?.source !== "live" || degradedCatalog);
889
976
  const cancelRef = (0, import_react.useRef)(null);
890
977
  const surface = (0, import_react.useRef)(null);
891
978
  if (!surface.current) surface.current = sampleThemeSurface();
892
- (0, import_react.useEffect)(() => {
893
- setStage(0);
894
- }, [p.previewId]);
895
- (0, import_react.useEffect)(() => {
896
- if (stage > 0) cancelRef.current?.focus();
897
- }, [stage]);
898
979
  const escCancel = (e) => {
899
980
  if (e.key === "Escape") onCancel();
900
981
  };
901
982
  const confirmClick = () => {
902
- if (p.evidence?.stale === true) return;
903
- if (!isRebuild) {
904
- onConfirm({ second: false, empty: false });
905
- return;
906
- }
907
- if (stage === 0) {
908
- setStage(1);
909
- return;
910
- }
911
- if (emptyTarget && stage === 1) {
912
- setStage(2);
913
- return;
914
- }
915
- onConfirm({ second: true, empty: emptyTarget });
983
+ if (isStale || applyBlocked) return;
984
+ onConfirm({});
916
985
  };
917
986
  const sourceLine = [
918
987
  p.evidence?.source === "live" ? t("srcLive") : p.evidence?.source === "cache" ? t("srcCache").replace("{time}", String(p.evidence?.fetchedAt ?? "")) : null,
919
988
  p.catalogSource === "latest" ? t("srcLatest") : p.catalogSource === "overlay" ? t("srcOverlay") : t("srcLocal")
920
989
  ].filter(Boolean).join(" \xB7 ");
921
- const list = (items, style, render) => items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.6 }, children: t("none") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.diffList, children: items.map((x, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { style: { ...style, ...styles.mono }, children: render ? render(x) : x }, x?.id ?? x ?? i)) });
990
+ const groupDefs = [
991
+ { key: "groupAddable", items: rows.filter((r) => r.status === "addable") },
992
+ { key: "groupListed", items: rows.filter((r) => r.status === "listed") },
993
+ { key: "groupRemoval", items: removalRows, retain: true }
994
+ ];
922
995
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.modalMask, role: "dialog", "aria-modal": "true", onKeyDown: escCancel, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...styles.modal, background: surface.current.bg, color: surface.current.fg, height: "min(80vh, 680px)", padding: 0, overflow: "hidden" }, children: [
923
996
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "18px 20px 6px" }, children: [
924
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { style: styles.modalTitle, children: t(isRebuild ? "rebuildTitle" : "supplementTitle") }),
925
- flow.staleNotice && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
997
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { style: styles.modalTitle, children: t("manageModels") }),
998
+ flow.staleNotice && !(!isStale && p.evidence?.source !== "live" && p.catalogSource === "latest") && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
926
999
  "\u26A0 ",
927
1000
  t("previewStale")
928
1001
  ] }),
929
1002
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: sourceLine }),
930
- p.evidence?.stale === true && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
1003
+ isStale && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
931
1004
  "\u26A0 ",
932
1005
  t("srcStale")
933
1006
  ] })
934
1007
  ] }),
935
1008
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { flex: 1, overflowY: "auto", minHeight: 0, scrollbarGutter: "stable", padding: "0 20px" }, children: [
936
- !isRebuild && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
937
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
938
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("candidates") }),
939
- "\uFF08",
940
- candidates.length,
941
- "\uFF09",
942
- candidates.length > 0 && (() => {
943
- const allSelected = candidates.every((id) => selectedIds.has(id));
944
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary, height: 24, marginLeft: 10, fontSize: 12 }, onClick: () => emitSel(allSelected ? [] : candidates), children: allSelected ? t("selectNone") : t("selectAll") });
945
- })()
946
- ] }),
947
- list(candidates, styles.added, (id) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
948
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: selectedIds.has(id), onChange: () => {
949
- const next = new Set(selectedIds);
950
- if (next.has(id)) next.delete(id);
951
- else next.add(id);
952
- emitSel([...next]);
953
- } }),
954
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: id })
955
- ] })),
956
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
957
- "\u26A0 ",
958
- t("supplementRisk")
959
- ] })
960
- ] }),
961
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
962
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("addedModels") }),
963
- "\uFF08",
964
- (diff.added ?? []).length,
965
- "\uFF09"
1009
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap", padding: "6px 0" }, children: [
1010
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1011
+ "button",
1012
+ {
1013
+ type: "button",
1014
+ style: { ...styles.button, ...styles.secondary, height: 24, fontSize: 12 },
1015
+ onClick: () => emitSel(/* @__PURE__ */ new Set([...addableIds, ...rawAllIds])),
1016
+ children: t("selectAll")
1017
+ }
1018
+ ),
1019
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1020
+ "button",
1021
+ {
1022
+ type: "button",
1023
+ style: { ...styles.button, ...styles.secondary, height: 24, fontSize: 12 },
1024
+ onClick: () => emitSel(new Set(lockedIds)),
1025
+ children: t("selectNone")
1026
+ }
1027
+ ),
1028
+ removalRows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1029
+ "button",
1030
+ {
1031
+ type: "button",
1032
+ style: { ...styles.button, ...styles.secondary, height: 24, fontSize: 12, ...locked ? { opacity: 0.5, cursor: "not-allowed" } : null },
1033
+ disabled: locked,
1034
+ title: locked ? t("removalNeedsLive") : void 0,
1035
+ onClick: () => emitSel(/* @__PURE__ */ new Set([...addableIds, ...rows.filter((r) => r.status === "listed").map((r) => r.id)])),
1036
+ children: t("alignAction")
1037
+ }
1038
+ )
966
1039
  ] }),
967
- list(diff.added ?? [], styles.added),
968
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
969
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("removedModels") }),
970
- "\uFF08",
971
- (diff.removed ?? []).length,
972
- "\uFF09"
973
- ] }),
974
- list(diff.removed ?? [], styles.removed, (x) => `${x.id} \u2014 ${t(x.reason === "unresolvable" ? "removedUnresolvable" : "removedAccount")}`),
975
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
976
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("keptModels") }),
977
- "\uFF08",
978
- (diff.kept ?? []).length,
979
- "\uFF09"
980
- ] }),
981
- list(diff.kept ?? [], styles.muted),
982
- (diff.warnings ?? []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
983
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
984
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("warnings") }),
1040
+ groupDefs.map(({ key, items, retain }) => items.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: 8 }, children: [
1041
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { ...styles.modalText, fontWeight: 600, margin: "6px 0 2px" }, title: retain ? t("retain") : void 0, children: [
1042
+ t(key),
985
1043
  "\uFF08",
986
- diff.warnings.length,
1044
+ items.length,
987
1045
  "\uFF09"
988
1046
  ] }),
989
- list(diff.warnings, styles.skipped, (w) => `${w.id ?? ""} \u2014 ${w.reason ?? ""}`)
990
- ] }),
991
- isRebuild && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
992
- "\u26A0 ",
993
- t("rebuildRisk")
994
- ] }),
995
- emptyTarget && stage >= 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
996
- "\u26A0 ",
997
- t("clearRisk")
998
- ] }),
999
- stage === 1 && !emptyTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
1000
- "\u26A0 ",
1001
- t("secondConfirm")
1002
- ] }),
1047
+ items.map((r) => {
1048
+ const forceKept = r.status === "removal-proposal" && locked;
1049
+ const checked = forceKept || selected.has(r.id);
1050
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "flex", gap: 8, alignItems: "center", padding: "2px 0" }, children: [
1051
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked, disabled: forceKept, onChange: () => toggle(r.id) }),
1052
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.mono, children: r.id }),
1053
+ r.status === "removal-proposal" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...styles.removed, fontSize: 12 }, children: t(r.reason === "unresolvable" ? "removedUnresolvable" : "removedAccount") }),
1054
+ r.customized === true && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...styles.muted, fontSize: 12 }, children: t("customizedBadge") })
1055
+ ] }, r.id);
1056
+ })
1057
+ ] }, key)),
1058
+ (p.overridesMeta?.clearable || p.overridesMeta?.inheritedOnly) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "4px 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
1059
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: coChecked, disabled: !p.overridesMeta?.clearable, onChange: (e) => toggleClearOverrides(e.target.checked) }),
1060
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: p.overridesMeta?.clearable ? void 0 : { ...styles.muted, fontSize: 13 }, children: t(p.overridesMeta?.clearable ? "clearOverrides" : "inheritedOverrides") })
1061
+ ] }) }),
1003
1062
  (p.skipped ?? []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { style: styles.modalText, children: [
1004
1063
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("summary", { children: [
1005
1064
  t("skippedModels"),
@@ -1013,25 +1072,57 @@ function RefreshModal({ t, flow, onSelect, onConfirm, onCancel, onOverlay }) {
1013
1072
  s.reason
1014
1073
  ] }, s.id)) })
1015
1074
  ] }),
1016
- p.catalogError && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { style: styles.modalText, children: [
1075
+ ((p.diff?.warnings ?? []).length > 0 || p.catalogError) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { style: styles.modalText, children: [
1017
1076
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: t("techDetails") }),
1018
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...styles.mono, fontSize: 12 }, children: p.catalogError })
1077
+ (p.diff?.warnings ?? []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.diffList, children: (p.diff?.warnings ?? []).map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { style: styles.skipped, children: [
1078
+ w.id,
1079
+ " \u2014 ",
1080
+ w.reason
1081
+ ] }, w.id ?? i)) }),
1082
+ p.catalogError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...styles.mono, fontSize: 12 }, children: p.catalogError })
1019
1083
  ] })
1020
1084
  ] }),
1021
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "8px 20px 16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.modalActions, children: [
1022
- p.catalogSource === "local" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary, marginRight: "auto" }, onClick: onOverlay, children: t("overlayBtn") }),
1023
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ref: cancelRef, type: "button", style: { ...styles.button, ...styles.secondary }, onClick: onCancel, children: t("cancel") }),
1024
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1025
- "button",
1026
- {
1027
- type: "button",
1028
- style: { ...styles.button, ...styles.primary, ...p.evidence?.stale === true ? { opacity: 0.5, cursor: "not-allowed" } : null },
1029
- disabled: p.evidence?.stale === true,
1030
- onClick: confirmClick,
1031
- children: t("applyChanges")
1032
- }
1033
- )
1034
- ] }) })
1085
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "8px 20px 16px" }, children: [
1086
+ (removedCount > 0 || coChecked || emptyTarget) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: 4 }, children: [
1087
+ removedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
1088
+ "\u26A0 ",
1089
+ t("removalRisk").replace("{count}", String(removedCount))
1090
+ ] }),
1091
+ coChecked && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
1092
+ "\u26A0 ",
1093
+ t("clearOverrides")
1094
+ ] }),
1095
+ emptyTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
1096
+ "\u26A0 ",
1097
+ t("clearRisk")
1098
+ ] })
1099
+ ] }),
1100
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { ...styles.modalText, margin: 0 }, children: total === 0 && removedCount === 0 && (p.catalogNewEntries ?? 0) === 0 ? t("noChanges") : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1101
+ t("summaryLine").replace("{total}", String(total)).replace("{kept}", String(keptCount)).replace("{added}", String(addedCount)).replace("{removed}", String(removedCount)),
1102
+ (p.catalogNewEntries ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1103
+ " \xB7 ",
1104
+ t("catalogNotice").replace("{count}", String(p.catalogNewEntries))
1105
+ ] })
1106
+ ] }) }),
1107
+ removedCount > 0 && applyBlocked && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
1108
+ "\u26A0 ",
1109
+ t("removalNeedsLive")
1110
+ ] }),
1111
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.modalActions, children: [
1112
+ p.catalogSource === "local" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary, marginRight: "auto" }, onClick: onOverlay, children: t("overlayBtn") }),
1113
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ref: cancelRef, type: "button", style: { ...styles.button, ...styles.secondary }, onClick: onCancel, children: t("cancel") }),
1114
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1115
+ "button",
1116
+ {
1117
+ type: "button",
1118
+ style: { ...styles.button, ...styles.primary, ...applyBlocked ? { opacity: 0.5, cursor: "not-allowed" } : null },
1119
+ disabled: applyBlocked,
1120
+ onClick: confirmClick,
1121
+ children: t("applyChanges")
1122
+ }
1123
+ )
1124
+ ] })
1125
+ ] })
1035
1126
  ] }) });
1036
1127
  }
1037
1128
  function RetireDialog({ t, onConfirm, onCancel }) {
@@ -1098,9 +1189,6 @@ function CopilotSection({ t = (key) => DICTS.en[key] ?? key }) {
1098
1189
  setCopyFail(false);
1099
1190
  void authFlowRef.current?.start();
1100
1191
  };
1101
- const withdraw = () => {
1102
- void authFlowRef.current?.cancel();
1103
- };
1104
1192
  const checkStatus = () => {
1105
1193
  void authFlowRef.current?.refresh();
1106
1194
  };
@@ -1151,15 +1239,13 @@ function CopilotSection({ t = (key) => DICTS.en[key] ?? key }) {
1151
1239
  ] }),
1152
1240
  codeNotice.url && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { style: styles.link, href: codeNotice.url, target: "_blank", rel: "noreferrer", children: codeNotice.url }),
1153
1241
  copyFail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.error, children: t("copyFailed") })
1154
- ] }),
1155
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary }, onClick: withdraw, children: t("withdrawAuth") }) })
1242
+ ] })
1156
1243
  ] }),
1157
1244
  phase === "risk" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.card, children: [
1158
1245
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
1159
1246
  "\u26A0 ",
1160
1247
  t("authUnsafe")
1161
1248
  ] }),
1162
- auth.riskKind === "withdrawal-pending-unverified" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: auth.withdrawalDelivery === "invoked" ? t("withdrawal") : t("withdrawalUnavailable") }),
1163
1249
  auth.riskKind === "timed-out-unverified" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: t("attemptTimeout") }),
1164
1250
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary }, onClick: checkStatus, children: t("retryNow") }) })
1165
1251
  ] }),
@@ -1204,28 +1290,16 @@ function CopilotSection({ t = (key) => DICTS.en[key] ?? key }) {
1204
1290
  }
1205
1291
  );
1206
1292
  })(),
1207
- ["previewing", "applying", "checking", "retiring"].includes(flow.name) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.primary, opacity: 0.5 }, disabled: true, children: flow.name === "applying" ? t("applying") : t("refreshing") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1208
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1209
- "button",
1210
- {
1211
- type: "button",
1212
- style: { ...styles.button, ...styles.primary, ...refreshBlocked(flow.flags) ? { opacity: 0.5, cursor: "not-allowed" } : null },
1213
- disabled: refreshBlocked(flow.flags),
1214
- onClick: () => drive({ type: "start", operation: "supplement" }),
1215
- children: t("supplement")
1216
- }
1217
- ),
1218
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1219
- "button",
1220
- {
1221
- type: "button",
1222
- style: { ...styles.button, ...styles.primary, ...refreshBlocked(flow.flags) ? { opacity: 0.5, cursor: "not-allowed" } : null },
1223
- disabled: refreshBlocked(flow.flags),
1224
- onClick: () => drive({ type: "start", operation: "rebuild" }),
1225
- children: t("rebuild")
1226
- }
1227
- )
1228
- ] })
1293
+ ["previewing", "applying", "checking", "retiring"].includes(flow.name) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.primary, opacity: 0.5 }, disabled: true, children: flow.name === "applying" ? t("applying") : t("refreshing") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1294
+ "button",
1295
+ {
1296
+ type: "button",
1297
+ style: { ...styles.button, ...styles.primary, ...refreshBlocked(flow.flags) ? { opacity: 0.5, cursor: "not-allowed" } : null },
1298
+ disabled: refreshBlocked(flow.flags),
1299
+ onClick: () => drive({ type: "start", operation: "manage" }),
1300
+ children: t("manageModels")
1301
+ }
1302
+ )
1229
1303
  ] }),
1230
1304
  auth.logoutError && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.error, children: [
1231
1305
  "\u26A0 ",
@@ -1285,7 +1359,7 @@ function CopilotSection({ t = (key) => DICTS.en[key] ?? key }) {
1285
1359
  {
1286
1360
  t,
1287
1361
  flow,
1288
- onSelect: (selectedIds) => drive({ type: "select", selectedIds }),
1362
+ onSelect: ({ selectedIds, clearOverrides, confirmEmpty }) => drive({ type: "select", selectedIds, clearOverrides, confirmEmpty }),
1289
1363
  onConfirm: (opts) => drive({ type: "confirm", ...opts }),
1290
1364
  onCancel: () => drive({ type: "cancel" }),
1291
1365
  onOverlay: () => drive({ type: "start", catalogSource: "overlay" })