@inventec/dsh-copilot-auth 1.2.6 → 1.2.8
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/README.md +40 -26
- package/lib/client.js +806 -275
- package/package.json +9 -2
- package/src/auth-flow.mjs +190 -0
- package/src/auth-host.mjs +182 -0
- package/src/catalog-registry.mjs +31 -4
- package/src/client-http.mjs +80 -0
- package/src/host.mjs +365 -631
- package/src/model-update.mjs +118 -0
- package/src/refresh-flow.mjs +200 -86
- package/src/refresh-service.mjs +276 -0
- package/src/refresh-transaction.mjs +573 -0
- package/src/runtime-scope.mjs +25 -0
- package/src/shared.mjs +3 -0
- package/src/state.mjs +61 -60
package/lib/client.js
CHANGED
|
@@ -34,68 +34,250 @@ 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
38
|
var routes = () => ({
|
|
38
39
|
start: `${ROUTE_PREFIX}/start`,
|
|
39
40
|
state: `${ROUTE_PREFIX}/state`,
|
|
40
41
|
status: `${ROUTE_PREFIX}/status`,
|
|
41
42
|
logout: `${ROUTE_PREFIX}/logout`,
|
|
43
|
+
cancel: `${ROUTE_PREFIX}/cancel`,
|
|
42
44
|
refreshPreview: `${ROUTE_PREFIX}/refresh/preview`,
|
|
43
|
-
refreshApply: `${ROUTE_PREFIX}/refresh/apply
|
|
45
|
+
refreshApply: `${ROUTE_PREFIX}/refresh/apply`,
|
|
46
|
+
refreshRetire: `${ROUTE_PREFIX}/refresh/retire`
|
|
44
47
|
});
|
|
45
48
|
|
|
49
|
+
// src/client-http.mjs
|
|
50
|
+
var SAFE_ERROR_CODE = /^[A-Za-z][A-Za-z0-9 -]{0,79}$/;
|
|
51
|
+
var SAFE_CONTENT_TYPE = /^[\w./+-]{0,100}$/;
|
|
52
|
+
function sanitizeErrorCode(value) {
|
|
53
|
+
return typeof value === "string" && SAFE_ERROR_CODE.test(value) ? value : "http-error";
|
|
54
|
+
}
|
|
55
|
+
var SAFE_STRING = /^[A-Za-z0-9][A-Za-z0-9 -]{0,127}$/;
|
|
56
|
+
function deepSanitize(value) {
|
|
57
|
+
if (typeof value === "string") return SAFE_STRING.test(value) ? value : void 0;
|
|
58
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") return value;
|
|
59
|
+
if (Array.isArray(value)) return value.map(deepSanitize);
|
|
60
|
+
if (value && typeof value === "object") {
|
|
61
|
+
const out = {};
|
|
62
|
+
for (const [k, v] of Object.entries(value)) {
|
|
63
|
+
const s = deepSanitize(v);
|
|
64
|
+
if (s !== void 0) out[k] = s;
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
return void 0;
|
|
69
|
+
}
|
|
70
|
+
function sanitizeContentType(value) {
|
|
71
|
+
if (typeof value !== "string" || !SAFE_CONTENT_TYPE.test(value)) return void 0;
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
async function requestJson(fetchImpl, url, init = {}) {
|
|
75
|
+
let res;
|
|
76
|
+
try {
|
|
77
|
+
res = await fetchImpl(url, init);
|
|
78
|
+
} catch {
|
|
79
|
+
return { ok: false, httpStatus: null, body: void 0, error: { messageKey: "network-error", details: {} } };
|
|
80
|
+
}
|
|
81
|
+
const httpStatus = res.status;
|
|
82
|
+
let text = "";
|
|
83
|
+
try {
|
|
84
|
+
text = await res.text();
|
|
85
|
+
} catch {
|
|
86
|
+
text = "";
|
|
87
|
+
}
|
|
88
|
+
if (typeof text !== "string" || text.trim() === "") {
|
|
89
|
+
return {
|
|
90
|
+
ok: false,
|
|
91
|
+
httpStatus,
|
|
92
|
+
body: void 0,
|
|
93
|
+
error: { messageKey: httpStatus >= 500 ? "bad-gateway" : "bad-response", details: { httpStatus } }
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
let body;
|
|
97
|
+
try {
|
|
98
|
+
body = JSON.parse(text);
|
|
99
|
+
} catch {
|
|
100
|
+
const contentType = sanitizeContentType(res.headers?.get?.("content-type"));
|
|
101
|
+
const looksHtml = contentType?.includes("html") || /^\s*<(?:!doctype|html)/i.test(text);
|
|
102
|
+
const messageKey = httpStatus >= 500 || looksHtml ? "bad-gateway" : "bad-response";
|
|
103
|
+
const details2 = { httpStatus };
|
|
104
|
+
if (contentType !== void 0) details2.contentType = contentType;
|
|
105
|
+
return { ok: false, httpStatus, body: void 0, error: { messageKey, details: details2 } };
|
|
106
|
+
}
|
|
107
|
+
const ok = res.ok && body?.ok !== false;
|
|
108
|
+
if (ok) return { ok: true, httpStatus, body, error: void 0 };
|
|
109
|
+
const details = {};
|
|
110
|
+
if (!res.ok) details.httpStatus = httpStatus;
|
|
111
|
+
const errorCode = sanitizeErrorCode(body?.error);
|
|
112
|
+
if (errorCode !== void 0) details.errorCode = errorCode;
|
|
113
|
+
return { ok: false, httpStatus, body: deepSanitize(body), error: { messageKey: "http-error", details } };
|
|
114
|
+
}
|
|
115
|
+
|
|
46
116
|
// src/refresh-flow.mjs
|
|
47
|
-
var initial = Object.freeze({
|
|
117
|
+
var initial = Object.freeze({
|
|
118
|
+
name: "idle",
|
|
119
|
+
flags: { catalogMode: null, blockedReason: null, scopeAvailable: true, legacyStateDetected: false },
|
|
120
|
+
lastResult: null
|
|
121
|
+
});
|
|
122
|
+
var fromRefresh = (state, refresh) => ({
|
|
123
|
+
...state,
|
|
124
|
+
flags: {
|
|
125
|
+
catalogMode: refresh && "catalogMode" in refresh ? refresh.catalogMode : state.flags.catalogMode,
|
|
126
|
+
blockedReason: refresh && "blockedReason" in refresh ? refresh.blockedReason : state.flags.blockedReason,
|
|
127
|
+
scopeAvailable: refresh ? refresh.scopeAvailable !== false : state.flags.scopeAvailable,
|
|
128
|
+
legacyStateDetected: refresh?.legacyStateDetected === true
|
|
129
|
+
},
|
|
130
|
+
lastResult: refresh?.lastResult ?? null
|
|
131
|
+
});
|
|
132
|
+
var restartStates = /* @__PURE__ */ new Set(["pending-restart"]);
|
|
133
|
+
function refreshBlocked(flags) {
|
|
134
|
+
const mode = flags?.catalogMode;
|
|
135
|
+
return flags?.scopeAvailable === false || mode === "blocked" || mode === "unknown";
|
|
136
|
+
}
|
|
48
137
|
function reduce(state, event) {
|
|
49
138
|
switch (state.name) {
|
|
50
139
|
case "idle":
|
|
51
140
|
case "failed":
|
|
52
|
-
case "
|
|
141
|
+
case "result":
|
|
142
|
+
case "pendingRestart":
|
|
143
|
+
case "busy":
|
|
144
|
+
case "resultUnknown": {
|
|
53
145
|
if (event.type === "start") {
|
|
54
|
-
return [{
|
|
146
|
+
return [{
|
|
147
|
+
name: "previewing",
|
|
148
|
+
flags: state.flags ?? initial.flags,
|
|
149
|
+
operation: event.operation === "rebuild" ? "rebuild" : "supplement",
|
|
150
|
+
catalogSource: event.catalogSource,
|
|
151
|
+
stale: false
|
|
152
|
+
}, {
|
|
153
|
+
type: "preview",
|
|
154
|
+
operation: event.operation === "rebuild" ? "rebuild" : "supplement",
|
|
155
|
+
catalogSource: event.catalogSource
|
|
156
|
+
}];
|
|
157
|
+
}
|
|
158
|
+
if (event.type === "init" && state.name === "idle") return [state, { type: "status" }];
|
|
159
|
+
if (event.type === "check" && state.name === "resultUnknown") {
|
|
160
|
+
return [{ ...state, name: "checking", operationId: state.operationId }, { type: "statusQuery", operationId: state.operationId }];
|
|
161
|
+
}
|
|
162
|
+
if (event.type === "retire-request" && state.name === "result") {
|
|
163
|
+
return [{ name: "retireConfirm", result: state.result }, null];
|
|
164
|
+
}
|
|
165
|
+
if (event.type === "dismiss" && state.name === "failed") {
|
|
166
|
+
return [{ ...initial, flags: state.flags }, null];
|
|
55
167
|
}
|
|
56
|
-
if (state.name === "failed" && event.type === "dismiss") return [initial, null];
|
|
57
|
-
if (state.name === "idle" && event.type === "init") return [state, { type: "status" }];
|
|
58
168
|
if (event.type === "hydrate") {
|
|
59
169
|
const refresh = event.status?.refresh;
|
|
60
170
|
if (!event.status) return [state, null];
|
|
61
|
-
if (refresh?.lastError === "state-corrupt") return [{ name: "failed", error: "state-corrupt" }, null];
|
|
62
|
-
|
|
63
|
-
|
|
171
|
+
if (refresh?.lastError === "state-corrupt") return [{ ...state, name: "failed", error: "state-corrupt" }, null];
|
|
172
|
+
const base = fromRefresh({ ...initial, name: "idle" }, refresh);
|
|
173
|
+
if (restartStates.has(refresh?.lastResult?.status ?? "") || refresh?.pendingRestart === true) {
|
|
174
|
+
return [{ ...base, name: "pendingRestart", result: refresh.lastResult }, null];
|
|
175
|
+
}
|
|
176
|
+
const st = refresh?.lastResult?.status;
|
|
177
|
+
if (st && ["recovery-needed", "rollback-conflict", "conflict", "partial", "rolled-back", "intent-retired", "applied"].includes(st)) {
|
|
178
|
+
return [{ ...base, name: "result", result: refresh.lastResult }, null];
|
|
64
179
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return [{ ...state, catalogWritable: writable, catalogMode: mode }, null];
|
|
180
|
+
if (refresh?.activeOperation) return [{ ...base, name: "busy", active: refresh.activeOperation }, null];
|
|
181
|
+
return [base, null];
|
|
68
182
|
}
|
|
69
183
|
return [state, null];
|
|
70
184
|
}
|
|
71
185
|
case "previewing": {
|
|
72
186
|
if (event.type === "preview-ok") {
|
|
73
|
-
return [{ name: "confirming",
|
|
187
|
+
return [{ name: "confirming", flags: state.flags ?? initial.flags, preview: event.preview, staleNotice: state.stale === true }, null];
|
|
74
188
|
}
|
|
75
|
-
if (event.type === "preview-fail") return [{ name: "failed", error: event.error }, null];
|
|
189
|
+
if (event.type === "preview-fail") return [{ name: "failed", flags: state.flags ?? initial.flags, error: event.error }, null];
|
|
76
190
|
return [state, null];
|
|
77
191
|
}
|
|
78
192
|
case "confirming": {
|
|
193
|
+
const p = state.preview;
|
|
194
|
+
if (event.type === "select") {
|
|
195
|
+
return [{
|
|
196
|
+
name: "previewing",
|
|
197
|
+
flags: state.flags ?? initial.flags,
|
|
198
|
+
operation: p.operation,
|
|
199
|
+
catalogSource: p.catalogSource,
|
|
200
|
+
stale: false
|
|
201
|
+
}, {
|
|
202
|
+
type: "preview",
|
|
203
|
+
operation: p.operation,
|
|
204
|
+
catalogSource: p.catalogSource,
|
|
205
|
+
basePreviewId: p.previewId,
|
|
206
|
+
selectedIds: event.selectedIds ?? [],
|
|
207
|
+
confirmEmpty: event.confirmEmpty === true
|
|
208
|
+
}];
|
|
209
|
+
}
|
|
79
210
|
if (event.type === "start") {
|
|
80
|
-
return [{
|
|
211
|
+
return [{
|
|
212
|
+
name: "previewing",
|
|
213
|
+
operation: event.operation === "rebuild" ? "rebuild" : p.operation,
|
|
214
|
+
catalogSource: event.catalogSource,
|
|
215
|
+
stale: false
|
|
216
|
+
}, {
|
|
217
|
+
type: "preview",
|
|
218
|
+
operation: event.operation === "rebuild" ? "rebuild" : p.operation,
|
|
219
|
+
catalogSource: event.catalogSource
|
|
220
|
+
}];
|
|
81
221
|
}
|
|
82
222
|
if (event.type === "confirm") {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
];
|
|
223
|
+
const isRebuild = p.operation === "rebuild";
|
|
224
|
+
const emptyTarget = isRebuild && (p.diff?.targetView?.models ?? []).length === 0;
|
|
225
|
+
if (isRebuild && event.second !== true) return [state, null];
|
|
226
|
+
if (emptyTarget && event.empty !== true) return [state, null];
|
|
227
|
+
if (p.evidence?.stale === true) return [state, null];
|
|
228
|
+
return [{ name: "applying", flags: state.flags ?? initial.flags, preview: p }, { type: "apply", previewId: p.previewId, operationId: p.operationId }];
|
|
87
229
|
}
|
|
88
|
-
if (event.type === "cancel") return [initial, null];
|
|
230
|
+
if (event.type === "cancel") return [{ ...initial, flags: state.flags ?? initial.flags, lastResult: state.lastResult ?? null }, null];
|
|
89
231
|
return [state, null];
|
|
90
232
|
}
|
|
91
233
|
case "applying": {
|
|
92
234
|
if (event.type === "apply-ok") {
|
|
93
|
-
return event.
|
|
235
|
+
return restartStates.has(event.result?.status ?? "") ? [{ ...state, name: "pendingRestart", result: event.result }, null] : [{ ...state, name: "result", result: event.result }, null];
|
|
94
236
|
}
|
|
95
237
|
if (event.type === "apply-stale") {
|
|
96
|
-
return [{
|
|
238
|
+
return [{
|
|
239
|
+
name: "previewing",
|
|
240
|
+
flags: state.flags ?? initial.flags,
|
|
241
|
+
operation: state.preview.operation,
|
|
242
|
+
catalogSource: state.preview.catalogSource,
|
|
243
|
+
stale: true
|
|
244
|
+
}, { type: "preview", operation: state.preview.operation, catalogSource: state.preview.catalogSource }];
|
|
245
|
+
}
|
|
246
|
+
if (event.type === "apply-busy") {
|
|
247
|
+
return [{ ...state, name: "checking" }, { type: "status" }];
|
|
248
|
+
}
|
|
249
|
+
if (event.type === "apply-unknown") {
|
|
250
|
+
return [{ ...state, name: "checking", operationId: state.preview.operationId }, { type: "statusQuery", operationId: state.preview.operationId }];
|
|
97
251
|
}
|
|
98
|
-
if (event.type === "apply-fail") return [{ name: "failed", error: event.error }, null];
|
|
252
|
+
if (event.type === "apply-fail") return [{ ...state, name: "failed", error: event.error }, null];
|
|
253
|
+
return [state, null];
|
|
254
|
+
}
|
|
255
|
+
case "checking": {
|
|
256
|
+
if (event.type === "query-result") {
|
|
257
|
+
if (event.query === "active") return [{ ...state, name: "busy", active: event.active }, null];
|
|
258
|
+
if (event.query === "last") {
|
|
259
|
+
return restartStates.has(event.lastResult?.status ?? "") ? [{ ...state, name: "pendingRestart", result: event.lastResult }, null] : [{ ...state, name: "result", result: event.lastResult }, null];
|
|
260
|
+
}
|
|
261
|
+
return [{ ...state, name: "resultUnknown", operationId: state.operationId }, null];
|
|
262
|
+
}
|
|
263
|
+
if (event.type === "hydrate") {
|
|
264
|
+
const refresh = event.status?.refresh;
|
|
265
|
+
if (refresh?.activeOperation) return [{ ...state, name: "busy", active: refresh.activeOperation }, null];
|
|
266
|
+
if (refresh?.lastResult) return [{ ...state, name: "result", result: refresh.lastResult }, null];
|
|
267
|
+
return [{ ...state, name: "resultUnknown", operationId: state.operationId }, null];
|
|
268
|
+
}
|
|
269
|
+
return [state, null];
|
|
270
|
+
}
|
|
271
|
+
case "retireConfirm": {
|
|
272
|
+
if (event.type === "retire-confirm") {
|
|
273
|
+
return [{ name: "retiring", operationId: state.result?.operationId, result: state.result }, { type: "retire", operationId: state.result?.operationId }];
|
|
274
|
+
}
|
|
275
|
+
if (event.type === "cancel") return [{ name: "result", result: state.result }, null];
|
|
276
|
+
return [state, null];
|
|
277
|
+
}
|
|
278
|
+
case "retiring": {
|
|
279
|
+
if (event.type === "retire-ok") return [{ ...state, name: "checking" }, { type: "status" }];
|
|
280
|
+
if (event.type === "retire-fail") return [{ name: "result", result: state.result, retireError: event.error }, null];
|
|
99
281
|
return [state, null];
|
|
100
282
|
}
|
|
101
283
|
default:
|
|
@@ -104,52 +286,58 @@ function reduce(state, event) {
|
|
|
104
286
|
}
|
|
105
287
|
async function runEffect(effect, fetchImpl) {
|
|
106
288
|
const r = routes();
|
|
107
|
-
const post = (url, body) => fetchImpl
|
|
289
|
+
const post = (url, body) => requestJson(fetchImpl, url, {
|
|
108
290
|
method: "POST",
|
|
109
291
|
headers: { "content-type": "application/json" },
|
|
110
|
-
body: JSON.stringify(body)
|
|
292
|
+
body: JSON.stringify({ protocolVersion: PROTOCOL_VERSION, ...body })
|
|
111
293
|
});
|
|
112
294
|
if (effect.type === "preview") {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
295
|
+
const res = await post(r.refreshPreview, {
|
|
296
|
+
operation: effect.operation,
|
|
297
|
+
...effect.catalogSource ? { catalogSource: effect.catalogSource } : {},
|
|
298
|
+
...effect.basePreviewId ? { basePreviewId: effect.basePreviewId, selectedIds: effect.selectedIds ?? [] } : {},
|
|
299
|
+
...effect.confirmEmpty ? { confirmEmpty: true } : {}
|
|
300
|
+
});
|
|
301
|
+
if (res.ok) return { type: "preview-ok", preview: res.body };
|
|
302
|
+
return { type: "preview-fail", error: res.error?.details?.errorCode ?? res.error?.messageKey };
|
|
120
303
|
}
|
|
121
304
|
if (effect.type === "apply") {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return
|
|
130
|
-
type: "apply-ok",
|
|
131
|
-
restartRequired: body.restartRequired !== false,
|
|
132
|
-
mode: body.mode ?? null,
|
|
133
|
-
injected: Array.isArray(body.injected) ? body.injected.length : 0
|
|
134
|
-
} : { type: "apply-fail", error: body?.error ?? `HTTP ${res.status}` };
|
|
135
|
-
} catch (err) {
|
|
136
|
-
return { type: "apply-fail", error: String(err?.message ?? err) };
|
|
305
|
+
const res = await post(r.refreshApply, { previewId: effect.previewId, operationId: effect.operationId });
|
|
306
|
+
if (res.ok) return { type: "apply-ok", result: res.body?.result ?? { status: "unknown" } };
|
|
307
|
+
const code = res.error?.details?.errorCode ?? "";
|
|
308
|
+
const status = res.httpStatus;
|
|
309
|
+
if (status === null) return { type: "apply-unknown" };
|
|
310
|
+
if (status === 423 || code === "resource-busy") return { type: "apply-busy" };
|
|
311
|
+
if (status === 409 && ["preview-stale", "auth-changed", "preview-invalid"].includes(code)) {
|
|
312
|
+
return { type: "apply-stale", error: code };
|
|
137
313
|
}
|
|
314
|
+
return { type: "apply-fail", error: code || res.error?.messageKey };
|
|
315
|
+
}
|
|
316
|
+
if (effect.type === "retire") {
|
|
317
|
+
const res = await post(r.refreshRetire, { operationId: effect.operationId });
|
|
318
|
+
if (res.ok) return { type: "retire-ok", result: res.body?.result ?? null };
|
|
319
|
+
return { type: "retire-fail", error: res.error?.details?.errorCode ?? res.error?.messageKey };
|
|
138
320
|
}
|
|
139
321
|
if (effect.type === "status") {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
322
|
+
const res = await requestJson(fetchImpl, r.status, { method: "GET" });
|
|
323
|
+
if (res.ok) return { type: "hydrate", status: res.body };
|
|
324
|
+
return { type: "hydrate", status: null };
|
|
325
|
+
}
|
|
326
|
+
if (effect.type === "statusQuery") {
|
|
327
|
+
const res = await requestJson(fetchImpl, `${r.status}?operationId=${encodeURIComponent(effect.operationId ?? "")}`, { method: "GET" });
|
|
328
|
+
if (res.ok && res.body?.operation) {
|
|
329
|
+
return { type: "query-result", query: res.body.operation.query, active: res.body.operation.active, lastResult: res.body.operation.lastResult };
|
|
145
330
|
}
|
|
331
|
+
return { type: "query-result", query: "unknown" };
|
|
146
332
|
}
|
|
147
333
|
throw new Error(`unknown effect: ${effect.type}`);
|
|
148
334
|
}
|
|
149
335
|
async function advance(state, event, fetchImpl, onState) {
|
|
150
336
|
let [s, fx] = reduce(state, event);
|
|
151
337
|
onState?.(s);
|
|
338
|
+
let guard = 0;
|
|
152
339
|
while (fx) {
|
|
340
|
+
if (guard++ > 8) throw new Error("effect loop guard");
|
|
153
341
|
const resultEvent = await runEffect(fx, fetchImpl);
|
|
154
342
|
[s, fx] = reduce(s, resultEvent);
|
|
155
343
|
onState?.(s);
|
|
@@ -157,6 +345,174 @@ async function advance(state, event, fetchImpl, onState) {
|
|
|
157
345
|
return s;
|
|
158
346
|
}
|
|
159
347
|
|
|
348
|
+
// src/auth-flow.mjs
|
|
349
|
+
var POLL_INTERVAL_MS = 1e3;
|
|
350
|
+
var BACKOFF_STEPS_S = [1, 2, 4, 8, 15];
|
|
351
|
+
var AUTO_RETRY_LIMIT_MS = 6e4;
|
|
352
|
+
var LIVE_STATUSES = ["starting", "waiting", "finishing"];
|
|
353
|
+
var defaultClock = () => ({
|
|
354
|
+
now: () => Date.now(),
|
|
355
|
+
setTimeout: (fn, ms) => setTimeout(fn, ms),
|
|
356
|
+
clearTimeout: (id) => clearTimeout(id)
|
|
357
|
+
});
|
|
358
|
+
function createAuthFlow({ fetchImpl, clock = defaultClock(), onState = () => {
|
|
359
|
+
} } = {}) {
|
|
360
|
+
let generation = 0;
|
|
361
|
+
let timer = null;
|
|
362
|
+
let failures = 0;
|
|
363
|
+
let backoffIdx = 0;
|
|
364
|
+
let failureWindowStart = null;
|
|
365
|
+
let last = { phase: "loading", connectivity: "online", shared: false };
|
|
366
|
+
const emit = (patch) => {
|
|
367
|
+
last = { ...last, ...patch };
|
|
368
|
+
onState({ ...last });
|
|
369
|
+
};
|
|
370
|
+
const stale = (gen) => gen !== generation;
|
|
371
|
+
const clearTimer = () => {
|
|
372
|
+
if (timer !== null) {
|
|
373
|
+
clock.clearTimeout(timer);
|
|
374
|
+
timer = null;
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
const schedule = (gen, delayMs) => {
|
|
378
|
+
if (stale(gen)) return;
|
|
379
|
+
clearTimer();
|
|
380
|
+
timer = clock.setTimeout(() => {
|
|
381
|
+
timer = null;
|
|
382
|
+
void pollTick(gen);
|
|
383
|
+
}, delayMs);
|
|
384
|
+
};
|
|
385
|
+
function applySnapshot(gen, s) {
|
|
386
|
+
if (stale(gen)) return;
|
|
387
|
+
emit({ attempt: s, riskLatch: s?.riskLatch ?? null });
|
|
388
|
+
if (LIVE_STATUSES.includes(s?.status)) {
|
|
389
|
+
emit({ phase: "waiting" });
|
|
390
|
+
schedule(gen, POLL_INTERVAL_MS);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
if (s?.status === "authorized") {
|
|
394
|
+
emit({ phase: "authorized", error: void 0 });
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (s?.status === "failed") {
|
|
398
|
+
emit({ phase: "failed", error: s?.error ?? "authorization-failed" });
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (s?.status === "withdrawal-pending-unverified" || s?.status === "timed-out-unverified") {
|
|
402
|
+
emit({ phase: "risk", riskKind: s.status });
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
emit({ phase: "idle" });
|
|
406
|
+
}
|
|
407
|
+
async function pollTick(gen) {
|
|
408
|
+
const r = await requestJson(fetchImpl, "/copilot-auth/state", { method: "GET" });
|
|
409
|
+
if (stale(gen)) return;
|
|
410
|
+
if (r.ok) {
|
|
411
|
+
failures = 0;
|
|
412
|
+
backoffIdx = 0;
|
|
413
|
+
failureWindowStart = null;
|
|
414
|
+
emit({ connectivity: "online" });
|
|
415
|
+
applySnapshot(gen, r.body);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
failures += 1;
|
|
419
|
+
if (failureWindowStart === null) failureWindowStart = clock.now();
|
|
420
|
+
const cumulative = clock.now() - failureWindowStart;
|
|
421
|
+
if (cumulative >= AUTO_RETRY_LIMIT_MS) {
|
|
422
|
+
emit({ connectivity: "manual" });
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
emit({ connectivity: "retrying" });
|
|
426
|
+
const delayS = BACKOFF_STEPS_S[Math.min(backoffIdx, BACKOFF_STEPS_S.length - 1)];
|
|
427
|
+
backoffIdx += 1;
|
|
428
|
+
schedule(gen, delayS * 1e3);
|
|
429
|
+
}
|
|
430
|
+
function beginPolling(gen) {
|
|
431
|
+
void pollTick(gen);
|
|
432
|
+
}
|
|
433
|
+
async function init() {
|
|
434
|
+
const gen = ++generation;
|
|
435
|
+
clearTimer();
|
|
436
|
+
const status = await requestJson(fetchImpl, "/copilot-auth/status", { method: "GET" });
|
|
437
|
+
if (stale(gen)) return;
|
|
438
|
+
if (!status.ok) {
|
|
439
|
+
emit({ phase: "idle", error: status.error?.messageKey });
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
const body = status.body ?? {};
|
|
443
|
+
if (body.refresh?.scopeAvailable === false) {
|
|
444
|
+
emit({ phase: "unavailable" });
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
emit({ status: body });
|
|
448
|
+
if (body.authorization?.riskLatch) {
|
|
449
|
+
emit({ riskLatch: body.authorization.riskLatch });
|
|
450
|
+
}
|
|
451
|
+
if (body.configured === true) {
|
|
452
|
+
emit({ phase: "authorized" });
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const r = await requestJson(fetchImpl, "/copilot-auth/state", { method: "GET" });
|
|
456
|
+
if (stale(gen)) return;
|
|
457
|
+
if (!r.ok) {
|
|
458
|
+
emit({ phase: "idle" });
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
applySnapshot(gen, r.body);
|
|
462
|
+
}
|
|
463
|
+
async function start() {
|
|
464
|
+
const gen = ++generation;
|
|
465
|
+
clearTimer();
|
|
466
|
+
failures = 0;
|
|
467
|
+
backoffIdx = 0;
|
|
468
|
+
failureWindowStart = null;
|
|
469
|
+
emit({ phase: "waiting", shared: false, error: void 0, connectivity: "online" });
|
|
470
|
+
const r = await requestJson(fetchImpl, "/copilot-auth/start", { method: "POST" });
|
|
471
|
+
if (stale(gen)) return;
|
|
472
|
+
if (r.ok) {
|
|
473
|
+
beginPolling(gen);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const errorCode = r.error?.details?.errorCode;
|
|
477
|
+
if (r.httpStatus === 409) {
|
|
478
|
+
emit({ shared: true });
|
|
479
|
+
beginPolling(gen);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
if (errorCode === "auth-unsafe") {
|
|
483
|
+
emit({ phase: "risk", riskKind: "auth-unsafe" });
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
if (errorCode === "scope-unavailable" || r.httpStatus === 503) {
|
|
487
|
+
emit({ phase: "unavailable" });
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
emit({ phase: "failed", error: errorCode ?? r.error?.messageKey });
|
|
491
|
+
}
|
|
492
|
+
async function cancel() {
|
|
493
|
+
const r = await requestJson(fetchImpl, "/copilot-auth/cancel", { method: "POST" });
|
|
494
|
+
if (r.ok) {
|
|
495
|
+
emit({ withdrawalDelivery: r.body?.withdrawalDelivery ?? "unavailable" });
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
emit({ withdrawalDelivery: "failed", error: r.error?.details?.errorCode ?? r.error?.messageKey });
|
|
499
|
+
}
|
|
500
|
+
function refresh() {
|
|
501
|
+
const gen = ++generation;
|
|
502
|
+
clearTimer();
|
|
503
|
+
failures = 0;
|
|
504
|
+
backoffIdx = 0;
|
|
505
|
+
failureWindowStart = null;
|
|
506
|
+
emit({ connectivity: "online" });
|
|
507
|
+
void pollTick(gen);
|
|
508
|
+
}
|
|
509
|
+
function dispose() {
|
|
510
|
+
generation += 1;
|
|
511
|
+
clearTimer();
|
|
512
|
+
}
|
|
513
|
+
return { init, start, cancel, refresh, dispose };
|
|
514
|
+
}
|
|
515
|
+
|
|
160
516
|
// src/client.jsx
|
|
161
517
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
162
518
|
var name = "copilot-auth-ui";
|
|
@@ -164,107 +520,166 @@ var inject = ["slots", "locale"];
|
|
|
164
520
|
var DICTS = {
|
|
165
521
|
en: {
|
|
166
522
|
nav: "GHC Settings",
|
|
167
|
-
title: "GitHub Copilot
|
|
168
|
-
intro: "
|
|
523
|
+
title: "GitHub Copilot",
|
|
524
|
+
intro: "Authorize with a personal or organization account on github.com that has Copilot access. No API token is required.",
|
|
169
525
|
idle: "Not signed in",
|
|
170
|
-
|
|
526
|
+
waiting: "Waiting for you to authorize on GitHub",
|
|
171
527
|
authorized: "Signed in",
|
|
172
528
|
failed: "Failed",
|
|
173
529
|
loading: "\u2026",
|
|
174
530
|
login: "Sign in",
|
|
175
531
|
logout: "Sign out",
|
|
532
|
+
reauthorize: "Reauthorize",
|
|
533
|
+
withdrawAuth: "Request withdrawal",
|
|
534
|
+
withdrawal: "Withdrawal requested; the outcome remains unverified.",
|
|
535
|
+
withdrawalUnavailable: "The withdrawal request could not be sent to the host; the outcome remains unverified.",
|
|
536
|
+
authUnsafe: "Safe completion of the authorization flow is unconfirmed. Sign-out and a new authorization attempt are unavailable.",
|
|
537
|
+
attemptTimeout: "Authorization wait timed out; the outcome remains unverified. A new authorization attempt is unavailable. Check the status or verify it manually.",
|
|
538
|
+
attemptShared: "An authorization attempt is already running in this instance.",
|
|
539
|
+
unavailable: "This runtime lacks the capabilities needed to apply changes safely.",
|
|
540
|
+
connection: "Connection lost. The last confirmed status is shown.",
|
|
541
|
+
retryNow: "Check status",
|
|
542
|
+
copyFailed: "Copy failed. Select and copy the device code manually.",
|
|
543
|
+
riskBadge: "Outcome unverified",
|
|
176
544
|
codeHint: "Open the link below and enter this code to finish signing in:",
|
|
177
545
|
copy: "Copy",
|
|
178
546
|
copied: "Copied \u2713",
|
|
179
547
|
unknown: "Unknown error",
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
548
|
+
// ---- Model management (protocol v2, design §5) ----
|
|
549
|
+
supplement: "Add models",
|
|
550
|
+
rebuild: "Rebuild model list",
|
|
551
|
+
supplementTitle: "Add models",
|
|
552
|
+
rebuildTitle: "Rebuild model list",
|
|
553
|
+
candidates: "Models available to add",
|
|
554
|
+
selectAll: "Select all",
|
|
555
|
+
supplementRisk: "Existing models and customizations will be kept. Only selected models will be added.",
|
|
556
|
+
rebuildRisk: "This rebuilds Copilot model configuration from the verified account list and clears the model customizations below. Other provider settings remain unchanged.",
|
|
557
|
+
clearRisk: "This clears the Copilot model list and its model customizations. Confirm clearing separately.",
|
|
558
|
+
secondConfirm: "This is destructive. Click again to confirm.",
|
|
559
|
+
applyChanges: "Apply changes",
|
|
560
|
+
addedModels: "Models to add",
|
|
561
|
+
removedModels: "Models to be removed",
|
|
188
562
|
keptModels: "Kept",
|
|
563
|
+
removedAccount: "Not included in this account model list",
|
|
564
|
+
removedUnresolvable: "Not resolvable by the current catalog",
|
|
565
|
+
warnings: "Warnings",
|
|
189
566
|
skippedModels: "Upstream entries skipped by validation",
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
confirmRefresh: "Confirm refresh",
|
|
194
|
-
cancel: "Cancel",
|
|
195
|
-
refreshing: "Fetching preview\u2026",
|
|
196
|
-
applying: "Applying\u2026",
|
|
197
|
-
restartNeeded: "Catalog patched. Restart dsh web to finish syncing the model list.",
|
|
198
|
-
stalePreview: "Inputs changed \u2014 review the new diff",
|
|
199
|
-
overlayBtn: "Preview with bundled overlay",
|
|
200
|
-
stateCorrupt: "State file was corrupted and quarantined; auto self-heal is disabled \u2014 run a refresh to re-activate.",
|
|
201
|
-
srcLive: "Account models: live fetch",
|
|
202
|
-
srcCache: "Account models: credential cache (live fetch failed)",
|
|
567
|
+
srcLive: "Account models: live",
|
|
568
|
+
srcCache: "Account models: cached at {time}; add-only use",
|
|
569
|
+
srcStale: "The cache has no trusted timestamp, is expired, or belongs to changed authorization; reference only.",
|
|
203
570
|
srcLatest: "Catalog source: latest pi-ai from npm",
|
|
204
|
-
srcLocal: "Catalog source: local
|
|
571
|
+
srcLocal: "Catalog source: local (npm fetch failed)",
|
|
205
572
|
srcOverlay: "Catalog source: bundled overlay (offline bootstrap)",
|
|
573
|
+
overlayBtn: "Preview with bundled overlay",
|
|
574
|
+
previewStale: "Configuration or data changed. Preview and confirm again.",
|
|
206
575
|
none: "(none)",
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
576
|
+
applying: "Applying\u2026",
|
|
577
|
+
refreshing: "Fetching preview\u2026",
|
|
578
|
+
cancel: "Cancel",
|
|
579
|
+
applied: "Changes are active. No restart is needed.",
|
|
580
|
+
pendingRestart: "Changes are saved and require restarting this instance's service or application. Refreshing the page alone is not enough.",
|
|
581
|
+
conflict: "Configuration changed. To protect your edits, preview and confirm again.",
|
|
582
|
+
partial: "Changes were only partially applied. Review the current status and recovery guidance.",
|
|
583
|
+
rolledBack: "This operation's model configuration changes were rolled back. Catalog data may still have been added.",
|
|
584
|
+
rollbackConflict: "Newer configuration was detected and preserved. Automatic rollback did not complete.",
|
|
585
|
+
busy: "Another operation is using this resource. Please retry shortly.",
|
|
586
|
+
unknownResult: "Completion has not been confirmed. Check the current status before submitting again.",
|
|
587
|
+
recoveryNeeded: "A previous configuration intent is stale or conflicted. End it before applying new changes.",
|
|
588
|
+
retireBtn: "End previous configuration intent",
|
|
589
|
+
retireTitle: "End previous configuration intent",
|
|
590
|
+
retireConfirmText: "End the intent only; existing changes are not rolled back or undone.",
|
|
591
|
+
legacy: "Legacy shared recovery state was found. It will not be applied automatically; preview and confirm in this profile.",
|
|
592
|
+
techDetails: "Technical details",
|
|
593
|
+
stateCorrupt: "State file was corrupted and quarantined. Preview and confirm again.",
|
|
594
|
+
blockedReasons: {
|
|
595
|
+
"inject-unavailable": "The in-process catalog registry is unavailable in this installation.",
|
|
596
|
+
"install-unresolved": "The pi-ai installation could not be located."
|
|
597
|
+
}
|
|
212
598
|
},
|
|
213
599
|
zh: {
|
|
214
600
|
nav: "GHC\u8BBE\u7F6E",
|
|
215
|
-
title: "GitHub Copilot
|
|
216
|
-
intro: "\u4F7F\u7528\
|
|
601
|
+
title: "GitHub Copilot",
|
|
602
|
+
intro: "\u4F7F\u7528\u5177\u6709 Copilot \u6743\u9650\u7684 github.com \u4E2A\u4EBA\u6216\u7EC4\u7EC7\u8D26\u53F7\u6388\u6743\uFF0C\u65E0\u9700\u586B\u5199 API Token\u3002",
|
|
217
603
|
idle: "\u672A\u767B\u5F55",
|
|
218
|
-
|
|
604
|
+
waiting: "\u7B49\u5F85\u4F60\u5728 GitHub \u5B8C\u6210\u6388\u6743",
|
|
219
605
|
authorized: "\u5DF2\u767B\u5F55",
|
|
220
606
|
failed: "\u5931\u8D25",
|
|
221
607
|
loading: "\u2026",
|
|
222
|
-
login: "\u767B\u5F55",
|
|
223
|
-
logout: "\
|
|
608
|
+
login: "\u6388\u6743\u767B\u5F55",
|
|
609
|
+
logout: "\u9000\u51FA\u767B\u5F55",
|
|
610
|
+
reauthorize: "\u91CD\u65B0\u6388\u6743",
|
|
611
|
+
withdrawAuth: "\u8BF7\u6C42\u64A4\u56DE",
|
|
612
|
+
withdrawal: "\u64A4\u56DE\u8BF7\u6C42\u5DF2\u53D1\u9001\uFF0C\u7ED3\u679C\u4ECD\u5F85\u6838\u5B9E\u3002",
|
|
613
|
+
withdrawalUnavailable: "\u672A\u80FD\u5411\u5BBF\u4E3B\u53D1\u9001\u64A4\u56DE\u8BF7\u6C42\uFF0C\u7ED3\u679C\u4ECD\u5F85\u6838\u5B9E\u3002",
|
|
614
|
+
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",
|
|
615
|
+
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",
|
|
616
|
+
attemptShared: "\u6B64\u5B9E\u4F8B\u5DF2\u6709\u6388\u6743\u6B63\u5728\u8FDB\u884C\u3002",
|
|
617
|
+
connection: "\u8FDE\u63A5\u5F02\u5E38\uFF0C\u663E\u793A\u7684\u662F\u6700\u540E\u786E\u8BA4\u7684\u72B6\u6001\u3002",
|
|
618
|
+
retryNow: "\u67E5\u8BE2\u72B6\u6001",
|
|
619
|
+
copyFailed: "\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u9009\u4E2D\u8BBE\u5907\u7801\u590D\u5236\u3002",
|
|
620
|
+
riskBadge: "\u7ED3\u679C\u5F85\u6838\u5B9E",
|
|
224
621
|
codeHint: "\u5728\u6D4F\u89C8\u5668\u6253\u5F00\u4E0B\u9762\u7684\u94FE\u63A5\uFF0C\u8F93\u5165\u8FD9\u4E32\u4EE3\u7801\u5B8C\u6210\u6388\u6743\uFF1A",
|
|
225
622
|
copy: "\u590D\u5236",
|
|
226
623
|
copied: "\u5DF2\u590D\u5236 \u2713",
|
|
227
624
|
unknown: "\u672A\u77E5\u9519\u8BEF",
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
625
|
+
// ---- 模型管理(协议 v2,设计§5) ----
|
|
626
|
+
supplement: "\u8865\u5145\u6A21\u578B",
|
|
627
|
+
rebuild: "\u91CD\u5EFA\u6A21\u578B\u5217\u8868",
|
|
628
|
+
supplementTitle: "\u8865\u5145\u6A21\u578B",
|
|
629
|
+
rebuildTitle: "\u91CD\u5EFA\u6A21\u578B\u5217\u8868",
|
|
630
|
+
candidates: "\u53EF\u65B0\u589E\u7684\u6A21\u578B",
|
|
631
|
+
selectAll: "\u5168\u9009",
|
|
632
|
+
supplementRisk: "\u5C06\u4FDD\u7559\u73B0\u6709\u6A21\u578B\u53CA\u5B9A\u5236\uFF0C\u53EA\u6DFB\u52A0\u4F60\u52FE\u9009\u7684\u6A21\u578B\u3002",
|
|
633
|
+
rebuildRisk: "\u5C06\u6309\u672C\u6B21\u53EF\u4FE1\u8D26\u53F7\u5217\u8868\u91CD\u5EFA Copilot \u6A21\u578B\u914D\u7F6E\uFF0C\u5E76\u6E05\u9664\u4E0B\u5217\u6A21\u578B\u53C2\u6570\u4E0E\u8986\u76D6\u914D\u7F6E\u3002\u5176\u4ED6\u63D0\u4F9B\u65B9\u8BBE\u7F6E\u4E0D\u53D8\u3002",
|
|
634
|
+
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",
|
|
635
|
+
secondConfirm: "\u6B64\u64CD\u4F5C\u5177\u6709\u7834\u574F\u6027\uFF0C\u8BF7\u518D\u6B21\u70B9\u51FB\u786E\u8BA4\u3002",
|
|
636
|
+
applyChanges: "\u5E94\u7528\u66F4\u6539",
|
|
637
|
+
addedModels: "\u5C06\u6DFB\u52A0\u7684\u6A21\u578B",
|
|
638
|
+
removedModels: "\u5C06\u79FB\u9664\u7684\u6A21\u578B",
|
|
236
639
|
keptModels: "\u4FDD\u7559",
|
|
640
|
+
removedAccount: "\u672A\u5305\u542B\u5728\u672C\u6B21\u8D26\u53F7\u6A21\u578B\u5217\u8868",
|
|
641
|
+
removedUnresolvable: "\u5F53\u524D\u76EE\u5F55\u65E0\u6CD5\u89E3\u6790",
|
|
642
|
+
warnings: "\u8B66\u544A",
|
|
237
643
|
skippedModels: "\u88AB\u6821\u9A8C\u8DF3\u8FC7\u7684\u4E0A\u6E38\u6761\u76EE",
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
confirmRefresh: "\u786E\u8BA4\u5237\u65B0",
|
|
242
|
-
cancel: "\u53D6\u6D88",
|
|
243
|
-
refreshing: "\u62C9\u53D6\u9884\u89C8\u4E2D\u2026",
|
|
244
|
-
applying: "\u5E94\u7528\u4E2D\u2026",
|
|
245
|
-
restartNeeded: "\u76EE\u5F55\u8865\u4E01\u5DF2\u5199\u5165\u3002\u91CD\u542F dsh web \u540E\u5B8C\u6210\u6A21\u578B\u5217\u8868\u540C\u6B65\u3002",
|
|
246
|
-
stalePreview: "\u6570\u636E\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u786E\u8BA4\u5DEE\u5F02",
|
|
247
|
-
overlayBtn: "\u6539\u7528\u5185\u7F6E\u8986\u76D6\u5C42\u9884\u89C8",
|
|
248
|
-
stateCorrupt: "\u72B6\u6001\u6587\u4EF6\u5DF2\u635F\u574F\u5E76\u88AB\u9694\u79BB\uFF1B\u81EA\u52A8\u81EA\u6108\u5DF2\u505C\u7528\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C\u4E00\u6B21\u5237\u65B0\u4EE5\u6FC0\u6D3B\u3002",
|
|
249
|
-
srcLive: "\u8D26\u53F7\u6A21\u578B\uFF1A\u73B0\u573A\u62C9\u53D6",
|
|
250
|
-
srcCache: "\u8D26\u53F7\u6A21\u578B\uFF1A\u51ED\u8BC1\u7F13\u5B58\uFF08\u73B0\u573A\u62C9\u53D6\u5931\u8D25\uFF09",
|
|
644
|
+
srcLive: "\u8D26\u53F7\u6A21\u578B\uFF1A\u5B9E\u65F6\u83B7\u53D6",
|
|
645
|
+
srcCache: "\u8D26\u53F7\u6A21\u578B\uFF1A\u7F13\u5B58\uFF0C\u83B7\u53D6\u4E8E {time}\uFF0C\u4EC5\u53EF\u7528\u4E8E\u8865\u5145",
|
|
646
|
+
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",
|
|
251
647
|
srcLatest: "\u76EE\u5F55\u6765\u6E90\uFF1Anpm \u6700\u65B0 pi-ai",
|
|
252
|
-
srcLocal: "\u76EE\u5F55\u6765\u6E90\uFF1A\
|
|
648
|
+
srcLocal: "\u76EE\u5F55\u6765\u6E90\uFF1A\u672C\u5730\u76EE\u5F55\uFF08npm \u62C9\u53D6\u5931\u8D25\uFF09",
|
|
253
649
|
srcOverlay: "\u76EE\u5F55\u6765\u6E90\uFF1A\u5185\u7F6E\u8986\u76D6\u5C42\uFF08\u79BB\u7EBF bootstrap\uFF09",
|
|
650
|
+
overlayBtn: "\u6539\u7528\u5185\u7F6E\u76EE\u5F55\u6570\u636E\u9884\u89C8",
|
|
651
|
+
previewStale: "\u914D\u7F6E\u6216\u6570\u636E\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u9884\u89C8\u5E76\u786E\u8BA4\u3002",
|
|
254
652
|
none: "\uFF08\u65E0\uFF09",
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
653
|
+
applying: "\u5E94\u7528\u4E2D\u2026",
|
|
654
|
+
refreshing: "\u62C9\u53D6\u9884\u89C8\u4E2D\u2026",
|
|
655
|
+
cancel: "\u53D6\u6D88",
|
|
656
|
+
applied: "\u66F4\u6539\u5DF2\u751F\u6548\uFF0C\u65E0\u9700\u91CD\u542F\u3002",
|
|
657
|
+
pendingRestart: "\u66F4\u6539\u5DF2\u4FDD\u5B58\uFF0C\u5F85\u91CD\u542F\u751F\u6548\u3002\u8BF7\u91CD\u542F\u8FD0\u884C\u6B64\u5B9E\u4F8B\u7684\u670D\u52A1\u6216\u5E94\u7528\uFF1B\u4EC5\u5237\u65B0\u9875\u9762\u4E0D\u4F1A\u751F\u6548\u3002",
|
|
658
|
+
conflict: "\u914D\u7F6E\u5DF2\u53D8\u5316\u3002\u4E3A\u4FDD\u62A4\u4F60\u7684\u4FEE\u6539\uFF0C\u8BF7\u91CD\u65B0\u9884\u89C8\u5E76\u786E\u8BA4\u3002",
|
|
659
|
+
partial: "\u66F4\u6539\u672A\u5B8C\u5168\u5E94\u7528\uFF0C\u8BF7\u67E5\u770B\u5F53\u524D\u72B6\u6001\u548C\u6062\u590D\u5EFA\u8BAE\u3002",
|
|
660
|
+
rolledBack: "\u672C\u6B21\u6A21\u578B\u914D\u7F6E\u66F4\u6539\u5DF2\u56DE\u6EDA\u3002\u76EE\u5F55\u6570\u636E\u53EF\u80FD\u4ECD\u5DF2\u8865\u5145\u3002",
|
|
661
|
+
rollbackConflict: "\u68C0\u6D4B\u5230\u66F4\u65B0\u7684\u914D\u7F6E\uFF0C\u5DF2\u4FDD\u7559\u4F60\u7684\u4FEE\u6539\uFF1B\u81EA\u52A8\u56DE\u6EDA\u672A\u5B8C\u6210\u3002",
|
|
662
|
+
busy: "\u53E6\u4E00\u4E2A\u64CD\u4F5C\u6B63\u5728\u5904\u7406\u6B64\u8D44\u6E90\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
663
|
+
unknownResult: "\u5C1A\u672A\u786E\u8BA4\u64CD\u4F5C\u5B8C\u6210\u3002\u8BF7\u6838\u5B9E\u5F53\u524D\u72B6\u6001\uFF0C\u52FF\u91CD\u590D\u63D0\u4EA4\u3002",
|
|
664
|
+
recoveryNeeded: "\u5B58\u5728\u5DF2\u5931\u6548\u6216\u51B2\u7A81\u7684\u65E7\u914D\u7F6E\u610F\u56FE\uFF0C\u8BF7\u5148\u7ED3\u675F\u65E7\u610F\u56FE\u518D\u5E94\u7528\u65B0\u66F4\u6539\u3002",
|
|
665
|
+
retireBtn: "\u7ED3\u675F\u65E7\u914D\u7F6E\u610F\u56FE",
|
|
666
|
+
retireTitle: "\u7ED3\u675F\u65E7\u914D\u7F6E\u610F\u56FE",
|
|
667
|
+
retireConfirmText: "\u53EA\u7ED3\u675F\u65E7\u610F\u56FE\uFF0C\u4E0D\u56DE\u6EDA\u6216\u64A4\u9500\u5DF2\u53D1\u751F\u7684\u66F4\u6539\u3002",
|
|
668
|
+
legacy: "\u68C0\u6D4B\u5230\u65E7\u7684\u5171\u4EAB\u6062\u590D\u72B6\u6001\u3002\u4E0D\u4F1A\u81EA\u52A8\u5E94\u7528\uFF0C\u8BF7\u5728\u5F53\u524D profile \u91CD\u65B0\u9884\u89C8\u786E\u8BA4\u3002",
|
|
669
|
+
techDetails: "\u6280\u672F\u8BE6\u60C5",
|
|
670
|
+
stateCorrupt: "\u6062\u590D\u72B6\u6001\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u539F\u4EF6\u5DF2\u4FDD\u7559\u3002\u8BF7\u91CD\u65B0\u9884\u89C8\u786E\u8BA4\u3002",
|
|
671
|
+
unavailable: "\u5F53\u524D\u8FD0\u884C\u65F6\u7F3A\u5C11\u5B89\u5168\u5E94\u7528\u6240\u9700\u7684\u80FD\u529B\uFF0C\u6682\u4E0D\u80FD\u5E94\u7528\u66F4\u6539\u3002",
|
|
672
|
+
blockedReasons: {
|
|
673
|
+
"inject-unavailable": "\u5F53\u524D\u5B89\u88C5\u7684\u8FDB\u7A0B\u5185\u76EE\u5F55\u6CE8\u518C\u8868\u4E0D\u53EF\u7528\u3002",
|
|
674
|
+
"install-unresolved": "\u65E0\u6CD5\u5B9A\u4F4D pi-ai \u5B89\u88C5\u3002"
|
|
675
|
+
}
|
|
260
676
|
}
|
|
261
677
|
};
|
|
262
678
|
var NAV_TEXTS = Object.keys(DICTS).map((locale) => DICTS[locale].nav);
|
|
263
|
-
function
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
return flags?.catalogWritable === false && flags?.catalogMode !== "registry";
|
|
679
|
+
function blockedReasonText(t, flags) {
|
|
680
|
+
const reason = flags?.blockedReason;
|
|
681
|
+
if (reason && t("blockedReasons")?.[reason]) return t("blockedReasons")[reason];
|
|
682
|
+
return t("unavailable");
|
|
268
683
|
}
|
|
269
684
|
var COPILOT_ICON_SVG = '<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" style="flex:none"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"/><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"/></svg>';
|
|
270
685
|
function enforceNavIcon(labelText) {
|
|
@@ -373,7 +788,7 @@ var styles = {
|
|
|
373
788
|
modalActions: { display: "flex", gap: 10, justifyContent: "flex-end", marginTop: 4 },
|
|
374
789
|
mono: { fontFamily: "ui-monospace, monospace" }
|
|
375
790
|
};
|
|
376
|
-
var badgeColor = { idle: "#adb5bd",
|
|
791
|
+
var badgeColor = { idle: "#adb5bd", waiting: "#f59f00", authorized: "#37b24d", failed: "#e03131", loading: "#adb5bd", risk: "#f59f00", unavailable: "#adb5bd" };
|
|
377
792
|
function sampleThemeSurface() {
|
|
378
793
|
if (typeof document === "undefined") return { bg: "#fff", fg: "inherit" };
|
|
379
794
|
const cs = getComputedStyle(document.body);
|
|
@@ -381,108 +796,182 @@ function sampleThemeSurface() {
|
|
|
381
796
|
const bg = m ? `rgb(${m[1].split(",").slice(0, 3).join(",")})` : "#fff";
|
|
382
797
|
return { bg, fg: cs.color || "inherit" };
|
|
383
798
|
}
|
|
384
|
-
function RefreshModal({ t, flow, onConfirm, onCancel, onOverlay }) {
|
|
799
|
+
function RefreshModal({ t, flow, onSelect, onConfirm, onCancel, onOverlay }) {
|
|
385
800
|
const p = flow.preview;
|
|
801
|
+
const diff = p.diff ?? {};
|
|
802
|
+
const isRebuild = p.operation === "rebuild";
|
|
803
|
+
const emptyTarget = isRebuild && (diff.targetView?.models ?? []).length === 0;
|
|
804
|
+
const candidates = diff.candidates ?? [];
|
|
805
|
+
const selectedIds = new Set(diff.added ?? []);
|
|
806
|
+
const [stage, setStage] = (0, import_react.useState)(0);
|
|
807
|
+
const cancelRef = (0, import_react.useRef)(null);
|
|
386
808
|
const surface = (0, import_react.useRef)(null);
|
|
387
809
|
if (!surface.current) surface.current = sampleThemeSurface();
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
810
|
+
(0, import_react.useEffect)(() => {
|
|
811
|
+
setStage(0);
|
|
812
|
+
}, [p.previewId]);
|
|
813
|
+
(0, import_react.useEffect)(() => {
|
|
814
|
+
if (stage > 0) cancelRef.current?.focus();
|
|
815
|
+
}, [stage]);
|
|
816
|
+
const escCancel = (e) => {
|
|
817
|
+
if (e.key === "Escape") onCancel();
|
|
818
|
+
};
|
|
819
|
+
const confirmClick = () => {
|
|
820
|
+
if (p.evidence?.stale === true) return;
|
|
821
|
+
if (!isRebuild) {
|
|
822
|
+
onConfirm({ second: false, empty: false });
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
if (stage === 0) {
|
|
826
|
+
setStage(1);
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
if (emptyTarget && stage === 1) {
|
|
830
|
+
setStage(2);
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
onConfirm({ second: true, empty: emptyTarget });
|
|
834
|
+
};
|
|
835
|
+
const sourceLine = [
|
|
836
|
+
p.evidence?.source === "live" ? t("srcLive") : p.evidence?.source === "cache" ? t("srcCache").replace("{time}", String(p.evidence?.fetchedAt ?? "")) : null,
|
|
837
|
+
p.catalogSource === "latest" ? t("srcLatest") : p.catalogSource === "overlay" ? t("srcOverlay") : t("srcLocal")
|
|
838
|
+
].filter(Boolean).join(" \xB7 ");
|
|
839
|
+
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)) });
|
|
840
|
+
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 }, children: [
|
|
841
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { style: styles.modalTitle, children: t(isRebuild ? "rebuildTitle" : "supplementTitle") }),
|
|
400
842
|
flow.staleNotice && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
401
843
|
"\u26A0 ",
|
|
402
|
-
t("
|
|
844
|
+
t("previewStale")
|
|
845
|
+
] }),
|
|
846
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: sourceLine }),
|
|
847
|
+
p.evidence?.stale === true && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
848
|
+
"\u26A0 ",
|
|
849
|
+
t("srcStale")
|
|
850
|
+
] }),
|
|
851
|
+
!isRebuild && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
|
|
853
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("candidates") }),
|
|
854
|
+
"\uFF08",
|
|
855
|
+
candidates.length,
|
|
856
|
+
"\uFF09",
|
|
857
|
+
candidates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary, height: 24, marginLeft: 10, fontSize: 12 }, onClick: () => onSelect(candidates), children: t("selectAll") })
|
|
858
|
+
] }),
|
|
859
|
+
list(candidates, styles.added, (id) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
|
|
860
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: selectedIds.has(id), onChange: () => {
|
|
861
|
+
const next = new Set(selectedIds);
|
|
862
|
+
if (next.has(id)) next.delete(id);
|
|
863
|
+
else next.add(id);
|
|
864
|
+
onSelect([...next]);
|
|
865
|
+
} }),
|
|
866
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: id })
|
|
867
|
+
] })),
|
|
868
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
|
|
869
|
+
"\u26A0 ",
|
|
870
|
+
t("supplementRisk")
|
|
871
|
+
] })
|
|
403
872
|
] }),
|
|
404
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: sourceKeys.map((k) => t(k)).join(" \xB7 ") }),
|
|
405
873
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
|
|
406
874
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("addedModels") }),
|
|
407
875
|
"\uFF08",
|
|
408
|
-
|
|
876
|
+
(diff.added ?? []).length,
|
|
409
877
|
"\uFF09"
|
|
410
878
|
] }),
|
|
411
|
-
list(
|
|
879
|
+
list(diff.added ?? [], styles.added),
|
|
412
880
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
|
|
413
881
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("removedModels") }),
|
|
414
882
|
"\uFF08",
|
|
415
|
-
|
|
883
|
+
(diff.removed ?? []).length,
|
|
416
884
|
"\uFF09"
|
|
417
885
|
] }),
|
|
418
|
-
list(
|
|
886
|
+
list(diff.removed ?? [], styles.removed, (x) => `${x.id} \u2014 ${t(x.reason === "unresolvable" ? "removedUnresolvable" : "removedAccount")}`),
|
|
419
887
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
|
|
420
888
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("keptModels") }),
|
|
421
889
|
"\uFF08",
|
|
422
|
-
|
|
890
|
+
(diff.kept ?? []).length,
|
|
423
891
|
"\uFF09"
|
|
424
892
|
] }),
|
|
425
|
-
|
|
893
|
+
(diff.warnings ?? []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
426
894
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.modalText, children: [
|
|
427
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("
|
|
895
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("warnings") }),
|
|
428
896
|
"\uFF08",
|
|
429
|
-
|
|
897
|
+
diff.warnings.length,
|
|
430
898
|
"\uFF09"
|
|
431
899
|
] }),
|
|
432
|
-
|
|
433
|
-
s.id,
|
|
434
|
-
" \u2014 ",
|
|
435
|
-
s.reason
|
|
436
|
-
] }, s.id)) })
|
|
437
|
-
] }),
|
|
438
|
-
resets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
439
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: t("customReset") }) }),
|
|
440
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.diffList, children: resets.map((x) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { style: styles.skipped, children: x }, x)) })
|
|
900
|
+
list(diff.warnings, styles.skipped, (w) => `${w.id ?? ""} \u2014 ${w.reason ?? ""}`)
|
|
441
901
|
] }),
|
|
442
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
|
|
902
|
+
isRebuild && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
|
|
443
903
|
"\u26A0 ",
|
|
444
|
-
t("
|
|
904
|
+
t("rebuildRisk")
|
|
445
905
|
] }),
|
|
446
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
|
|
906
|
+
emptyTarget && stage >= 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
|
|
447
907
|
"\u26A0 ",
|
|
448
|
-
t("
|
|
908
|
+
t("clearRisk")
|
|
449
909
|
] }),
|
|
450
|
-
|
|
910
|
+
stage === 1 && !emptyTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.risk, children: [
|
|
451
911
|
"\u26A0 ",
|
|
452
|
-
t("
|
|
912
|
+
t("secondConfirm")
|
|
453
913
|
] }),
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
914
|
+
(p.skipped ?? []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { style: styles.modalText, children: [
|
|
915
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("summary", { children: [
|
|
916
|
+
t("skippedModels"),
|
|
917
|
+
"\uFF08",
|
|
918
|
+
p.skipped.length,
|
|
919
|
+
"\uFF09"
|
|
920
|
+
] }),
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.diffList, children: p.skipped.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { style: styles.skipped, children: [
|
|
922
|
+
s.id,
|
|
923
|
+
" \u2014 ",
|
|
924
|
+
s.reason
|
|
925
|
+
] }, s.id)) })
|
|
457
926
|
] }),
|
|
458
|
-
|
|
459
|
-
"
|
|
460
|
-
|
|
927
|
+
p.catalogError && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { style: styles.modalText, children: [
|
|
928
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: t("techDetails") }),
|
|
929
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...styles.mono, fontSize: 12 }, children: p.catalogError })
|
|
461
930
|
] }),
|
|
462
931
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.modalActions, children: [
|
|
463
932
|
p.catalogSource === "local" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary, marginRight: "auto" }, onClick: onOverlay, children: t("overlayBtn") }),
|
|
464
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary }, onClick: onCancel, children: t("cancel") }),
|
|
933
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ref: cancelRef, type: "button", style: { ...styles.button, ...styles.secondary }, onClick: onCancel, children: t("cancel") }),
|
|
465
934
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
466
935
|
"button",
|
|
467
936
|
{
|
|
468
937
|
type: "button",
|
|
469
|
-
style: { ...styles.button, ...styles.primary, ...
|
|
470
|
-
disabled:
|
|
471
|
-
onClick:
|
|
472
|
-
children: t("
|
|
938
|
+
style: { ...styles.button, ...styles.primary, ...p.evidence?.stale === true ? { opacity: 0.5, cursor: "not-allowed" } : null },
|
|
939
|
+
disabled: p.evidence?.stale === true,
|
|
940
|
+
onClick: confirmClick,
|
|
941
|
+
children: t("applyChanges")
|
|
473
942
|
}
|
|
474
943
|
)
|
|
475
944
|
] })
|
|
476
945
|
] }) });
|
|
477
946
|
}
|
|
947
|
+
function RetireDialog({ t, onConfirm, onCancel }) {
|
|
948
|
+
const cancelRef = (0, import_react.useRef)(null);
|
|
949
|
+
const surface = (0, import_react.useRef)(null);
|
|
950
|
+
if (!surface.current) surface.current = sampleThemeSurface();
|
|
951
|
+
(0, import_react.useEffect)(() => {
|
|
952
|
+
cancelRef.current?.focus();
|
|
953
|
+
}, []);
|
|
954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.modalMask, role: "dialog", "aria-modal": "true", onKeyDown: (e) => {
|
|
955
|
+
if (e.key === "Escape") onCancel();
|
|
956
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...styles.modal, background: surface.current.bg, color: surface.current.fg, maxWidth: 420 }, children: [
|
|
957
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { style: styles.modalTitle, children: t("retireTitle") }),
|
|
958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: t("retireConfirmText") }),
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.modalActions, children: [
|
|
960
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ref: cancelRef, type: "button", style: { ...styles.button, ...styles.secondary }, onClick: onCancel, children: t("cancel") }),
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.primary }, onClick: onConfirm, children: t("retireBtn") })
|
|
962
|
+
] })
|
|
963
|
+
] }) });
|
|
964
|
+
}
|
|
478
965
|
function CopilotSection({ t = (key) => DICTS.en[key] ?? key }) {
|
|
479
|
-
const [
|
|
480
|
-
const [notices, setNotices] = (0, import_react.useState)([]);
|
|
481
|
-
const [error, setError] = (0, import_react.useState)(void 0);
|
|
966
|
+
const [auth, setAuth] = (0, import_react.useState)({ phase: "loading", connectivity: "online", shared: false });
|
|
482
967
|
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
483
|
-
const
|
|
968
|
+
const [copyFail, setCopyFail] = (0, import_react.useState)(false);
|
|
484
969
|
const [flow, setFlow] = (0, import_react.useState)(initial);
|
|
485
970
|
const flowRef = (0, import_react.useRef)(flow);
|
|
971
|
+
const authFlowRef = (0, import_react.useRef)(null);
|
|
972
|
+
if (!authFlowRef.current && typeof fetch === "function") {
|
|
973
|
+
authFlowRef.current = createAuthFlow({ onState: (s) => setAuth(s) });
|
|
974
|
+
}
|
|
486
975
|
const drive = (event) => advance(flowRef.current, event, fetch, (next) => {
|
|
487
976
|
flowRef.current = next;
|
|
488
977
|
setFlow(next);
|
|
@@ -492,141 +981,183 @@ function CopilotSection({ t = (key) => DICTS.en[key] ?? key }) {
|
|
|
492
981
|
drive({ type: "init" });
|
|
493
982
|
}, []);
|
|
494
983
|
(0, import_react.useEffect)(() => {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
if (!alive) return;
|
|
498
|
-
if (d.configured) {
|
|
499
|
-
setPage("authorized");
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
fetch("/copilot-auth/state").then((r) => r.json()).then((s) => {
|
|
503
|
-
if (!alive) return;
|
|
504
|
-
setNotices(s.notices ?? []);
|
|
505
|
-
if (s.status === "failed") {
|
|
506
|
-
setPage("failed");
|
|
507
|
-
setError(s.error ?? t("unknown"));
|
|
508
|
-
} else if (s.status === "running") {
|
|
509
|
-
setPage("running");
|
|
510
|
-
poll();
|
|
511
|
-
} else {
|
|
512
|
-
setPage("idle");
|
|
513
|
-
}
|
|
514
|
-
}).catch(() => {
|
|
515
|
-
if (alive) setPage("idle");
|
|
516
|
-
});
|
|
517
|
-
}).catch(() => {
|
|
518
|
-
if (alive) setPage("idle");
|
|
519
|
-
});
|
|
520
|
-
return () => {
|
|
521
|
-
alive = false;
|
|
522
|
-
if (timer.current) clearInterval(timer.current);
|
|
523
|
-
};
|
|
984
|
+
void authFlowRef.current?.init();
|
|
985
|
+
return () => authFlowRef.current?.dispose();
|
|
524
986
|
}, []);
|
|
525
|
-
const poll = () => {
|
|
526
|
-
if (timer.current) clearInterval(timer.current);
|
|
527
|
-
timer.current = setInterval(() => {
|
|
528
|
-
fetch("/copilot-auth/state").then((r) => r.json()).then((s) => {
|
|
529
|
-
setNotices(s.notices ?? []);
|
|
530
|
-
if (s.status !== "running") {
|
|
531
|
-
if (timer.current) clearInterval(timer.current);
|
|
532
|
-
timer.current = null;
|
|
533
|
-
if (s.status === "authorized") {
|
|
534
|
-
setPage("authorized");
|
|
535
|
-
} else {
|
|
536
|
-
setPage("failed");
|
|
537
|
-
setError(s.error ?? t("unknown"));
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
}).catch(() => {
|
|
541
|
-
});
|
|
542
|
-
}, 1e3);
|
|
543
|
-
};
|
|
544
987
|
const login = () => {
|
|
545
988
|
setCopied(false);
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
fetch("/copilot-auth/start", { method: "POST" }).catch(() => {
|
|
549
|
-
});
|
|
550
|
-
setPage("running");
|
|
551
|
-
poll();
|
|
989
|
+
setCopyFail(false);
|
|
990
|
+
void authFlowRef.current?.start();
|
|
552
991
|
};
|
|
553
|
-
const
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
try {
|
|
559
|
-
await fetch("/copilot-auth/logout", { method: "POST" });
|
|
560
|
-
} catch {
|
|
561
|
-
}
|
|
562
|
-
setNotices([]);
|
|
563
|
-
setError(void 0);
|
|
564
|
-
setPage("idle");
|
|
992
|
+
const withdraw = () => {
|
|
993
|
+
void authFlowRef.current?.cancel();
|
|
994
|
+
};
|
|
995
|
+
const checkStatus = () => {
|
|
996
|
+
void authFlowRef.current?.refresh();
|
|
565
997
|
};
|
|
566
998
|
const copyCode = async (code) => {
|
|
567
999
|
try {
|
|
568
1000
|
await navigator.clipboard.writeText(code);
|
|
569
1001
|
setCopied(true);
|
|
1002
|
+
setCopyFail(false);
|
|
570
1003
|
setTimeout(() => setCopied(false), 2e3);
|
|
571
1004
|
} catch {
|
|
1005
|
+
setCopyFail(true);
|
|
572
1006
|
}
|
|
573
1007
|
};
|
|
574
|
-
const
|
|
575
|
-
const
|
|
1008
|
+
const phase = auth.phase;
|
|
1009
|
+
const attempt = auth.attempt;
|
|
1010
|
+
const notices = [...attempt?.notices ?? []].reverse();
|
|
1011
|
+
const codeNotice = typeof attempt?.code === "string" && attempt.code !== "" ? { code: attempt.code, url: attempt.url } : (() => {
|
|
1012
|
+
const n = notices.find((x) => x && typeof x.code === "string" && x.code !== "");
|
|
1013
|
+
return n ? { code: n.code, url: n.url } : null;
|
|
1014
|
+
})();
|
|
1015
|
+
const badgeText = t(phase === "risk" ? "riskBadge" : phase === "loading" ? "loading" : phase);
|
|
576
1016
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
|
|
577
1017
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: styles.title, children: t("title") }),
|
|
578
1018
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.intro, children: t("intro") }),
|
|
579
1019
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.badgeRow, children: [
|
|
580
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...styles.dot, background: badgeColor[
|
|
1020
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...styles.dot, background: badgeColor[phase] ?? "#adb5bd" } }),
|
|
581
1021
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.badge, children: badgeText })
|
|
582
1022
|
] }),
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.code, children: codeNotice.code }),
|
|
587
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary }, onClick: () => copyCode(codeNotice.code), children: copied ? t("copied") : t("copy") })
|
|
588
|
-
] }),
|
|
589
|
-
codeNotice.url && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { style: styles.link, href: codeNotice.url, target: "_blank", rel: "noreferrer", children: codeNotice.url })
|
|
1023
|
+
auth.connectivity !== "online" && phase !== "loading" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
1024
|
+
"\u26A0 ",
|
|
1025
|
+
t("connection")
|
|
590
1026
|
] }),
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
594
|
-
|
|
595
|
-
"
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
|
|
1027
|
+
auth.connectivity === "manual" && /* @__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") }) }),
|
|
1028
|
+
phase === "waiting" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1029
|
+
auth.shared && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
1030
|
+
"\u24D8 ",
|
|
1031
|
+
t("attemptShared")
|
|
1032
|
+
] }),
|
|
1033
|
+
codeNotice && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.card, children: [
|
|
1034
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.codeHint, children: t("codeHint") }),
|
|
1035
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.codeRow, children: [
|
|
1036
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.code, children: codeNotice.code }),
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary }, onClick: () => copyCode(codeNotice.code), children: copied ? t("copied") : t("copy") })
|
|
1038
|
+
] }),
|
|
1039
|
+
codeNotice.url && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { style: styles.link, href: codeNotice.url, target: "_blank", rel: "noreferrer", children: codeNotice.url }),
|
|
1040
|
+
copyFail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.error, children: t("copyFailed") })
|
|
1041
|
+
] }),
|
|
1042
|
+
/* @__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") }) })
|
|
604
1043
|
] }),
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
1044
|
+
phase === "risk" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.card, children: [
|
|
1045
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
1046
|
+
"\u26A0 ",
|
|
1047
|
+
t("authUnsafe")
|
|
1048
|
+
] }),
|
|
1049
|
+
auth.riskKind === "withdrawal-pending-unverified" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: auth.withdrawalDelivery === "invoked" ? t("withdrawal") : t("withdrawalUnavailable") }),
|
|
1050
|
+
auth.riskKind === "timed-out-unverified" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.modalText, children: t("attemptTimeout") }),
|
|
1051
|
+
/* @__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") }) })
|
|
608
1052
|
] }),
|
|
609
|
-
|
|
1053
|
+
phase === "unavailable" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
610
1054
|
"\u26A0 ",
|
|
611
|
-
t("
|
|
1055
|
+
t("unavailable")
|
|
612
1056
|
] }),
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
"
|
|
616
|
-
|
|
1057
|
+
phase === "failed" && attempt?.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.error, children: attempt.error }),
|
|
1058
|
+
phase === "authorized" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.card, children: [
|
|
1059
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }, children: [
|
|
1060
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary, opacity: 0.5, cursor: "not-allowed" }, disabled: true, title: t("authUnsafe"), children: t("logout") }),
|
|
1061
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary, opacity: 0.5, cursor: "not-allowed" }, disabled: true, title: t("authUnsafe"), children: t("reauthorize") }),
|
|
1062
|
+
["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: [
|
|
1063
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1064
|
+
"button",
|
|
1065
|
+
{
|
|
1066
|
+
type: "button",
|
|
1067
|
+
style: { ...styles.button, ...styles.primary, ...refreshBlocked(flow.flags) ? { opacity: 0.5, cursor: "not-allowed" } : null },
|
|
1068
|
+
disabled: refreshBlocked(flow.flags),
|
|
1069
|
+
onClick: () => drive({ type: "start", operation: "supplement" }),
|
|
1070
|
+
children: t("supplement")
|
|
1071
|
+
}
|
|
1072
|
+
),
|
|
1073
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1074
|
+
"button",
|
|
1075
|
+
{
|
|
1076
|
+
type: "button",
|
|
1077
|
+
style: { ...styles.button, ...styles.primary, ...refreshBlocked(flow.flags) ? { opacity: 0.5, cursor: "not-allowed" } : null },
|
|
1078
|
+
disabled: refreshBlocked(flow.flags),
|
|
1079
|
+
onClick: () => drive({ type: "start", operation: "rebuild" }),
|
|
1080
|
+
children: t("rebuild")
|
|
1081
|
+
}
|
|
1082
|
+
)
|
|
1083
|
+
] })
|
|
1084
|
+
] }),
|
|
1085
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
1086
|
+
"\u24D8 ",
|
|
1087
|
+
t("authUnsafe")
|
|
1088
|
+
] }),
|
|
1089
|
+
refreshBlocked(flow.flags) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
1090
|
+
"\u26A0 ",
|
|
1091
|
+
blockedReasonText(t, flow.flags)
|
|
1092
|
+
] }),
|
|
1093
|
+
flow.flags?.legacyStateDetected && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
1094
|
+
"\u24D8 ",
|
|
1095
|
+
t("legacy")
|
|
1096
|
+
] }),
|
|
1097
|
+
flow.name === "pendingRestart" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
1098
|
+
"\u26A0 ",
|
|
1099
|
+
t("pendingRestart")
|
|
1100
|
+
] }),
|
|
1101
|
+
flow.name === "busy" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.banner, children: [
|
|
1102
|
+
"\u24D8 ",
|
|
1103
|
+
t("busy")
|
|
1104
|
+
] }),
|
|
1105
|
+
flow.name === "resultUnknown" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1106
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: styles.error, children: [
|
|
1107
|
+
"\u26A0 ",
|
|
1108
|
+
t("unknownResult")
|
|
1109
|
+
] }),
|
|
1110
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary }, onClick: () => drive({ type: "check" }), children: t("retryNow") }) })
|
|
1111
|
+
] }),
|
|
1112
|
+
flow.name === "result" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1113
|
+
(() => {
|
|
1114
|
+
const st = flow.result?.status;
|
|
1115
|
+
const key = {
|
|
1116
|
+
applied: "applied",
|
|
1117
|
+
conflict: "conflict",
|
|
1118
|
+
partial: "partial",
|
|
1119
|
+
"rolled-back": "rolledBack",
|
|
1120
|
+
"rollback-conflict": "rollbackConflict",
|
|
1121
|
+
"recovery-needed": "recoveryNeeded",
|
|
1122
|
+
"intent-retired": "recoveryNeeded"
|
|
1123
|
+
}[st];
|
|
1124
|
+
return key ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: st === "applied" ? styles.banner : styles.error, children: [
|
|
1125
|
+
st === "applied" ? "\u2713" : "\u26A0",
|
|
1126
|
+
" ",
|
|
1127
|
+
t(key)
|
|
1128
|
+
] }) : null;
|
|
1129
|
+
})(),
|
|
1130
|
+
["recovery-needed", "rollback-conflict", "intent-retired"].includes(flow.result?.status) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.secondary }, onClick: () => drive({ type: "retire-request" }), children: t("retireBtn") }) }),
|
|
1131
|
+
(flow.result?.error || flow.result?.changes) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { style: styles.modalText, children: [
|
|
1132
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: t("techDetails") }),
|
|
1133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { ...styles.mono, fontSize: 12 }, children: [
|
|
1134
|
+
flow.result?.error ?? "",
|
|
1135
|
+
flow.result?.changes ? ` ${JSON.stringify(flow.result.changes)}` : ""
|
|
1136
|
+
] })
|
|
1137
|
+
] })
|
|
1138
|
+
] }),
|
|
1139
|
+
flow.name === "failed" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.error, children: flow.error === "state-corrupt" ? t("stateCorrupt") : flow.error })
|
|
617
1140
|
] }),
|
|
618
|
-
page === "authorized" && flow.name === "failed" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.error, children: flow.error === "state-corrupt" ? t("stateCorrupt") : flow.error === "catalog-not-writable" ? t("notWritable") : flow.error === "registry-inject-failed" || flow.error === "registry-not-effective" ? t("registryFailed") : flow.error }),
|
|
619
1141
|
flow.name === "confirming" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
620
1142
|
RefreshModal,
|
|
621
1143
|
{
|
|
622
1144
|
t,
|
|
623
1145
|
flow,
|
|
624
|
-
|
|
1146
|
+
onSelect: (selectedIds) => drive({ type: "select", selectedIds }),
|
|
1147
|
+
onConfirm: (opts) => drive({ type: "confirm", ...opts }),
|
|
625
1148
|
onCancel: () => drive({ type: "cancel" }),
|
|
626
|
-
onOverlay: () => drive({ type: "start",
|
|
1149
|
+
onOverlay: () => drive({ type: "start", catalogSource: "overlay" })
|
|
1150
|
+
}
|
|
1151
|
+
),
|
|
1152
|
+
flow.name === "retireConfirm" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1153
|
+
RetireDialog,
|
|
1154
|
+
{
|
|
1155
|
+
t,
|
|
1156
|
+
onConfirm: () => drive({ type: "retire-confirm" }),
|
|
1157
|
+
onCancel: () => drive({ type: "cancel" })
|
|
627
1158
|
}
|
|
628
1159
|
),
|
|
629
|
-
(
|
|
1160
|
+
(phase === "idle" || phase === "failed") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: { ...styles.button, ...styles.primary }, onClick: login, children: t("login") }) })
|
|
630
1161
|
] });
|
|
631
1162
|
}
|
|
632
1163
|
function apply(ctx) {
|