dsh-plugin-upgrader 1.6.2 → 1.7.0

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
@@ -87,6 +87,11 @@ window.__ModuleLoader__.load({
87
87
  noHistoryWhy: "\u8FD9\u4E2A\u5305\u4E0D\u662F\u4ECE npm \u6CE8\u518C\u8868\u5B89\u88C5\u7684\uFF0C\u6CA1\u6709\u53D1\u5E03\u5386\u53F2\u3002",
88
88
  historyFailed: "\u7248\u672C\u5217\u8868\u8BFB\u53D6\u5931\u8D25\uFF0C\u70B9\u300C\u68C0\u67E5\u66F4\u65B0\u300D\u53EF\u91CD\u8BD5",
89
89
  mirrorBehind: "\u955C\u50CF\u6E90\u5C1A\u672A\u540C\u6B65\u8FD9\u4E9B\u5DF2\u53D1\u5E03\u7248\u672C\uFF0C\u88C5\u4E0D\u4E86",
90
+ incompatible: "\u4E0D\u652F\u6301\u5F53\u524D DSH",
91
+ incompatibleWhy: (range) => `\u8FD9\u4E2A\u7248\u672C\u8981\u6C42 DSH ${range}\uFF0C\u800C\u5F53\u524D\u5BBF\u4E3B\u4E0D\u6EE1\u8DB3\u3002\u88C5\u4E0A\u53BB\u4F1A\u88AB\u5BBF\u4E3B\u62D2\u7EDD\u3002`,
92
+ incompatibleLatest: (version, range) => `\u6700\u65B0\u7248 ${version} \u8981\u6C42 DSH ${range}\uFF0C\u5F53\u524D\u5BBF\u4E3B\u4E0D\u6EE1\u8DB3\uFF0C\u6240\u4EE5\u4E0D\u80FD\u5347\u4E0A\u53BB\u3002\u53EF\u4EE5\u5148\u628A DSH \u5347\u5230\u90A3\u4E2A\u8303\u56F4\uFF0C\u6216\u6362\u4E00\u4E2A\u517C\u5BB9\u7684\u7248\u672C\u3002`,
93
+ runtimeUnknown: "\u8BFB\u4E0D\u5230\u5F53\u524D DSH \u7248\u672C\uFF0C\u65E0\u6CD5\u5224\u65AD\u517C\u5BB9\u6027",
94
+ requiresDsh: (range) => `\u8981\u6C42 DSH ${range}`,
90
95
  versions: (n) => `${n} \u4E2A\u7248\u672C`,
91
96
  showingNewest: (n) => `\u5217\u51FA\u6700\u65B0 ${n} \u4E2A`,
92
97
  progress: (done, total) => `\u6B63\u5728\u5904\u7406 ${done}/${total}`,
@@ -105,6 +110,21 @@ window.__ModuleLoader__.load({
105
110
  cancelling: "\u6B63\u5728\u53D6\u6D88\u2026",
106
111
  restart: "\u9700\u8981\u91CD\u542F DSH \u624D\u4F1A\u751F\u6548\u3002",
107
112
  restartHint: "\u5DF2\u4FDD\u5B58\u7684\u6539\u52A8\u5728\u4E0B\u6B21\u542F\u52A8\u65F6\u751F\u6548\u3002",
113
+ restartOpen: "\u91CD\u542F DSH",
114
+ restartTitle: "\u91CD\u542F DSH",
115
+ restartBody: "\u5DF2\u4FDD\u5B58\u7684\u6539\u52A8\u8981\u7B49 DSH \u91CD\u65B0\u542F\u52A8\u624D\u4F1A\u751F\u6548\u3002\u8FD9\u4E00\u9875\u4E0D\u80FD\u66FF\u4F60\u91CD\u542F\u5B83\u2014\u2014\u684C\u9762\u7248\u7531\u5E94\u7528\u5916\u58F3\u638C\u63E1\u91CD\u542F\uFF0C\u4ECE\u7EC8\u7AEF\u542F\u52A8\u7684\u5BBF\u4E3B\u4E5F\u6CA1\u4EBA\u66FF\u5B83\u62C9\u8D77\u3002",
116
+ restartDesktopHint: "\u5B8C\u5168\u9000\u51FA DeepSeek Harness\uFF08\u4E0D\u662F\u5173\u7A97\u53E3\uFF0C\u800C\u662F\u9000\u51FA\u5E94\u7528\uFF09\uFF0C\u518D\u91CD\u65B0\u6253\u5F00\u5B83\u3002",
117
+ restartCommandHint: "\u5728\u539F\u6765\u7684\u7EC8\u7AEF\u91CC\u505C\u6389\u5B83\uFF0C\u518D\u8FD0\u884C\u540C\u4E00\u6761\u547D\u4EE4\uFF1A",
118
+ restartCopy: "\u590D\u5236\u547D\u4EE4",
119
+ restartCopied: "\u5DF2\u590D\u5236",
120
+ restartPid: (pid, profile) => `\u5F53\u524D\u5BBF\u4E3B\u8FDB\u7A0B ${pid}\uFF0Cprofile\uFF1A${profile}`,
121
+ restartRefresh: "\u91CD\u542F\u597D\u4E86\uFF0C\u5237\u65B0\u9875\u9762",
122
+ restartWaiting: "\u6B63\u5728\u7B49\u5BBF\u4E3B\u56DE\u6765\u2026",
123
+ restartStillOld: "\u5BBF\u4E3B\u8FD8\u6CA1\u6362\u65B0\u8FDB\u7A0B\u3002\u786E\u8BA4\u65E7\u8FDB\u7A0B\u5DF2\u7ECF\u9000\u51FA\uFF0C\u518D\u8BD5\u4E00\u6B21\u3002",
124
+ restartReloadBlocked: "\u5BBF\u4E3B\u5DF2\u7ECF\u91CD\u542F\uFF0C\u4F46\u8FD9\u4E00\u9875\u7684\u63D2\u4EF6\u6E05\u5355\u8FC7\u671F\u4E86\uFF0C\u76F4\u63A5\u5237\u65B0\u4F1A\u542F\u52A8\u5931\u8D25\u3002\u8BF7\u518D\u91CD\u542F\u4E00\u6B21 DSH\u3002",
125
+ restartReloadRefused: "\u5BBF\u4E3B\u5DF2\u7ECF\u91CD\u542F\uFF0C\u4F46\u8FD9\u4E00\u9875\u6CA1\u6CD5\u81EA\u5DF1\u5237\u65B0\u3002\u624B\u52A8\u5237\u65B0\u4E00\u4E0B\uFF0C\u6216\u8005\u91CD\u542F DSH \u5B8C\u6210\u5347\u7EA7\u3002",
126
+ restartLoading: "\u6B63\u5728\u8BFB\u53D6\u5BBF\u4E3B\u4FE1\u606F\u2026",
127
+ restartLoadFailed: (detail) => `\u8BFB\u4E0D\u5230\u5BBF\u4E3B\u4FE1\u606F\uFF1A${detail}`,
108
128
  reloadForAppearance: "\u4E3B\u9898\u63D2\u4EF6\u5DF2\u66F4\u65B0\uFF0C\u6B63\u5728\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u4EE5\u6062\u590D\u4E3B\u9898\u5916\u89C2\uFF08\u4E3B\u9898\u914D\u7F6E\u4FDD\u5B58\u5728\u78C1\u76D8\u4E0A\uFF0C\u4E0D\u4F1A\u4E22\u5931\uFF09\u3002",
109
129
  reloadBlocked: "\u5916\u89C2\u5DF2\u6062\u590D\uFF0C\u4F46\u8FD9\u4E00\u9875\u7684\u63D2\u4EF6\u6E05\u5355\u5DF2\u7ECF\u8FC7\u671F\uFF0C\u91CD\u65B0\u52A0\u8F7D\u4F1A\u542F\u52A8\u5931\u8D25\u3002\u8BF7\u91CD\u542F DSH \u5B8C\u6210\u8FD9\u6B21\u5347\u7EA7\u3002",
110
130
  done: "\u5B8C\u6210",
@@ -206,6 +226,11 @@ window.__ModuleLoader__.load({
206
226
  noHistoryWhy: "This package was not installed from an npm registry, so it has no published history.",
207
227
  historyFailed: 'Could not read the version list; "Check for updates" retries it',
208
228
  mirrorBehind: "Your mirror has not synced these published versions yet, so they cannot be installed",
229
+ incompatible: "Not for this DSH",
230
+ incompatibleWhy: (range) => `This version requires DSH ${range}, which this host does not satisfy. Installing it would be rejected.`,
231
+ incompatibleLatest: (version, range) => `The newest release ${version} requires DSH ${range}, which this host does not satisfy, so the upgrade is not offered. Upgrade DSH into that range, or pick a compatible version.`,
232
+ runtimeUnknown: "Could not read the running DSH version, so compatibility cannot be judged",
233
+ requiresDsh: (range) => `requires DSH ${range}`,
209
234
  versions: (n) => `${n} versions`,
210
235
  showingNewest: (n) => `showing newest ${n}`,
211
236
  progress: (done, total) => `Working on ${done}/${total}`,
@@ -224,6 +249,21 @@ window.__ModuleLoader__.load({
224
249
  cancelling: "Cancelling\u2026",
225
250
  restart: "Restart DSH to finish.",
226
251
  restartHint: "Saved changes take effect on the next start.",
252
+ restartOpen: "Restart DSH",
253
+ restartTitle: "Restart DSH",
254
+ restartBody: "The saved change only takes effect once DSH starts again. This page cannot do that for you \u2014 the desktop app keeps the restart in its own shell, and a host started from a terminal has nobody to start it again.",
255
+ restartDesktopHint: "Quit DeepSeek Harness completely (quit the app, not just the window), then open it again.",
256
+ restartCommandHint: "Stop it in the terminal it was started from, then run the same command:",
257
+ restartCopy: "Copy command",
258
+ restartCopied: "Copied",
259
+ restartPid: (pid, profile) => `Host process ${pid}, profile ${profile}`,
260
+ restartRefresh: "Restarted \u2014 reload the page",
261
+ restartWaiting: "Waiting for the host to come back\u2026",
262
+ restartStillOld: "The host has not been replaced yet. Check that the old process exited, then try again.",
263
+ restartReloadBlocked: "The host restarted, but this page's plugin list is out of date and reloading it would fail to start. Restart DSH once more.",
264
+ restartReloadRefused: "The host restarted, but this page could not reload itself. Reload it by hand, or restart DSH to finish the upgrade.",
265
+ restartLoading: "Reading host information\u2026",
266
+ restartLoadFailed: (detail) => `Could not read host information: ${detail}`,
227
267
  reloadForAppearance: "The theme plugin was updated; reloading the page to restore its look (its settings are on disk and are not lost).",
228
268
  reloadBlocked: "The look is restored, but this page's plugin list is out of date and reloading it would fail to start. Restart DSH to finish this upgrade.",
229
269
  done: "done",
@@ -393,15 +433,23 @@ window.__ModuleLoader__.load({
393
433
  const started = await readJson(response);
394
434
  return started.id;
395
435
  }
436
+ var WATCH_MISS_LIMIT = 4;
396
437
  async function watchJob(id, options) {
438
+ const wait = options.delay ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
439
+ let missed = 0;
397
440
  for (; ; ) {
398
441
  if (!options.isAlive()) return void 0;
399
- const response = await fetch(`${API}/job?id=${encodeURIComponent(id)}`, { credentials: "same-origin" });
400
- const snapshot = await readJson(response).catch(() => void 0);
401
- if (snapshot === void 0) return void 0;
442
+ const snapshot = await fetch(`${API}/job?id=${encodeURIComponent(id)}`, { credentials: "same-origin" }).then((response) => readJson(response)).catch(() => void 0);
443
+ if (snapshot === void 0) {
444
+ missed += 1;
445
+ if (missed >= WATCH_MISS_LIMIT) return void 0;
446
+ await wait(POLL_MS);
447
+ continue;
448
+ }
449
+ missed = 0;
402
450
  if (options.isAlive()) options.onSnapshot(snapshot);
403
451
  if (snapshot.status !== "running" && snapshot.status !== "queued") return snapshot;
404
- await new Promise((resolve) => setTimeout(resolve, POLL_MS));
452
+ await wait(POLL_MS);
405
453
  }
406
454
  }
407
455
  async function submitJob(steps, watch) {
@@ -430,6 +478,10 @@ window.__ModuleLoader__.load({
430
478
  });
431
479
  return readJson(response);
432
480
  }
481
+ async function readHostInfo() {
482
+ const response = await fetch(`${API}/host`, { credentials: "same-origin" });
483
+ return readJson(response);
484
+ }
433
485
 
434
486
  // src/client/boot.ts
435
487
  function bootBatches(wire) {
@@ -740,6 +792,7 @@ window.__ModuleLoader__.load({
740
792
  .dsh-pu-tag { font-size: 10px; line-height: 1; padding: 3px 6px; border-radius: 999px; border: 1px solid var(--dsw-alias-border-l1); color: var(--dsw-alias-label-secondary); font-weight: 500; white-space: nowrap; }
741
793
  .dsh-pu-tag.is-new { border-color: var(--dsw-alias-brand-primary); color: var(--dsw-alias-brand-primary); background: color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent); }
742
794
  .dsh-pu-tag.is-err { border-color: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-state-error-primary); }
795
+ .dsh-pu-tag.is-foreign { border-color: var(--dsw-alias-state-warn-primary); color: var(--dsw-alias-state-warn-primary); }
743
796
  .dsh-pu-vers { display: flex; align-items: center; gap: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--dsw-alias-label-secondary); flex: none; }
744
797
  .dsh-pu-vers b { color: var(--dsw-alias-label-primary); font-weight: 600; }
745
798
  .dsh-pu-vers i { font-style: normal; color: var(--dsw-alias-label-tertiary); }
@@ -752,6 +805,7 @@ window.__ModuleLoader__.load({
752
805
  .dsh-pu-hist-row { display: flex; align-items: center; gap: 10px; padding: 5px 6px; border-radius: 6px; font-size: 11px; }
753
806
  .dsh-pu-hist-row:hover { background: var(--dsw-alias-interactive-bg-hover); }
754
807
  .dsh-pu-hist-row.is-current { background: var(--dsw-alias-interactive-bg-hover); box-shadow: inset 2px 0 0 var(--dsw-alias-brand-primary); }
808
+ .dsh-pu-hist-row.is-foreign .dsh-pu-mono, .dsh-pu-hist-row.is-foreign time { opacity: .6; }
755
809
  .dsh-pu-hist-row .dsh-pu-mono { flex: none; min-width: 108px; color: var(--dsw-alias-label-primary); }
756
810
  .dsh-pu-link { display: inline-flex; align-items: center; gap: 4px; border: 0; padding: 0; margin: 0; background: none; cursor: pointer; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--dsw-alias-link); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--dsw-alias-link) 40%, transparent); text-underline-offset: 2px; }
757
811
  .dsh-pu-link:hover { color: var(--dsw-alias-brand-primary); text-decoration-color: currentColor; }
@@ -774,6 +828,8 @@ window.__ModuleLoader__.load({
774
828
  .dsh-pu-banner.is-warn { border-color: var(--dsw-alias-state-warn-primary); color: var(--dsw-alias-state-warn-primary); }
775
829
  .dsh-pu-banner.is-err { border-color: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-state-error-primary); }
776
830
  .dsh-pu-foot { display: flex; align-items: center; gap: 10px; font-size: 11px; color: var(--dsw-alias-label-tertiary); flex-wrap: wrap; }
831
+ .dsh-pu-cmdbox { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
832
+ .dsh-pu-cmd { display: block; width: 100%; box-sizing: border-box; margin: 0; padding: 7px 9px; border-radius: 8px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; line-height: 1.5; white-space: pre-wrap; word-break: break-all; user-select: all; }
777
833
  .dsh-pu-spin { width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--dsw-alias-border-l2); border-top-color: var(--dsw-alias-brand-primary); animation: dsh-pu-spin .8s linear infinite; flex: none; }
778
834
  @keyframes dsh-pu-spin { to { transform: rotate(360deg); } }
779
835
  @media (prefers-reduced-motion: reduce) { .dsh-pu-spin { animation-duration: 2.4s; } .dsh-pu-bar-inner.is-busy { animation-duration: 3s; } }
@@ -871,9 +927,11 @@ window.__ModuleLoader__.load({
871
927
  const link = resolveVersionLink(row, version);
872
928
  const linkLabel = link !== void 0 && /\/releases\/tag\//.test(link) ? t("githubVersion") : t("githubReleases");
873
929
  const title = link === void 0 ? void 0 : `${linkLabel} \u2192${link}`;
930
+ const foreign = version.compatible === false;
931
+ const why = foreign ? t("incompatibleWhy", version.requires ?? "") : title;
874
932
  return h(
875
933
  "div",
876
- { className: `dsh-pu-hist-row${version.current ? " is-current" : ""}` },
934
+ { className: `dsh-pu-hist-row${version.current ? " is-current" : ""}${foreign ? " is-foreign" : ""}` },
877
935
  link !== void 0 ? h(
878
936
  "button",
879
937
  {
@@ -887,6 +945,7 @@ window.__ModuleLoader__.load({
887
945
  h("time", null, formatDate(version.time)),
888
946
  version.latest ? h("span", { className: "dsh-pu-tag is-new" }, t("latest")) : null,
889
947
  version.current ? h("span", { className: "dsh-pu-tag" }, t("current")) : null,
948
+ foreign ? h("span", { className: "dsh-pu-tag is-foreign", title: why }, t("incompatible")) : null,
890
949
  h("span", { className: "dsh-pu-note" }, note),
891
950
  link === void 0 ? null : h(
892
951
  "button",
@@ -904,7 +963,8 @@ window.__ModuleLoader__.load({
904
963
  {
905
964
  type: "button",
906
965
  className: "dsh-pu-btn is-tiny",
907
- disabled: busy || version.current === true,
966
+ disabled: busy || version.current === true || foreign,
967
+ title: why,
908
968
  onClick: () => onSwitch(row, version.version)
909
969
  },
910
970
  /*
@@ -991,6 +1051,20 @@ window.__ModuleLoader__.load({
991
1051
  },
992
1052
  `${t("mirrorBehind")}: ${row.mirrorMissing.slice(0, 3).join(", ")}${row.mirrorMissing.length > 3 ? " \u2026" : ""}`
993
1053
  ) : null,
1054
+ /*
1055
+ * The newest release refuses to run on this DSH version. The row's
1056
+ * upgrade button points at `latest`, so it is no longer an upgrade:
1057
+ * naming the requirement is the only thing that turns "nothing happens"
1058
+ * into something the person can act on.
1059
+ */
1060
+ row.blocked !== void 0 ? h(
1061
+ "div",
1062
+ {
1063
+ className: "dsh-pu-note is-err",
1064
+ title: t("incompatibleLatest", row.blocked.version, row.blocked.requires)
1065
+ },
1066
+ t("incompatibleLatest", row.blocked.version, row.blocked.requires)
1067
+ ) : null,
994
1068
  failure !== void 0 && retriable ? h(
995
1069
  "div",
996
1070
  { className: "dsh-pu-note is-err", title: failure },
@@ -1102,6 +1176,158 @@ window.__ModuleLoader__.load({
1102
1176
  );
1103
1177
  }
1104
1178
 
1179
+ // src/client/components/RestartDialog.ts
1180
+ var PROBE_MS = 1e3;
1181
+ var WAIT_LIMIT_MS = 12e4;
1182
+ function stalledMessage(problem, t) {
1183
+ return problem.trim() === "" ? t("restartStillOld") : problem;
1184
+ }
1185
+ function RestartDialog(props) {
1186
+ const { t, onClose } = props;
1187
+ const h = getH();
1188
+ const React = getReact();
1189
+ const [host, setHost] = React.useState(void 0);
1190
+ const [phase, setPhase] = React.useState("loading");
1191
+ const [problem, setProblem] = React.useState("");
1192
+ const [copied, setCopied] = React.useState(false);
1193
+ const timerRef = React.useRef(void 0);
1194
+ React.useEffect(() => {
1195
+ let live = true;
1196
+ void readHostInfo().then((info) => {
1197
+ if (!live) return;
1198
+ setHost(info);
1199
+ setPhase("ready");
1200
+ }).catch((error) => {
1201
+ if (!live) return;
1202
+ setProblem(error instanceof Error ? error.message : String(error));
1203
+ setPhase("failed");
1204
+ });
1205
+ return () => {
1206
+ live = false;
1207
+ };
1208
+ }, []);
1209
+ const stop = React.useCallback(() => {
1210
+ const timer = timerRef.current;
1211
+ if (timer === void 0) return;
1212
+ timerRef.current = void 0;
1213
+ window.clearInterval(timer);
1214
+ }, []);
1215
+ React.useEffect(() => stop, [stop]);
1216
+ const waitForRestart = React.useCallback(() => {
1217
+ const before = host?.pid;
1218
+ if (before === void 0) return;
1219
+ setProblem("");
1220
+ setPhase("waiting");
1221
+ const startedAt = Date.now();
1222
+ const timer = window.setInterval(() => {
1223
+ void readHostInfo().then((info) => {
1224
+ if (info.pid === before) {
1225
+ if (Date.now() - startedAt > WAIT_LIMIT_MS) {
1226
+ stop();
1227
+ setPhase("stalled");
1228
+ }
1229
+ return;
1230
+ }
1231
+ stop();
1232
+ let blocked = false;
1233
+ void reloadWhenBootDocumentFresh({
1234
+ onBlocked: () => {
1235
+ blocked = true;
1236
+ setProblem(t("restartReloadBlocked"));
1237
+ setPhase("stalled");
1238
+ }
1239
+ }).then((done) => {
1240
+ if (!done && !blocked) {
1241
+ setProblem(t("restartReloadRefused"));
1242
+ setPhase("stalled");
1243
+ }
1244
+ });
1245
+ }).catch(() => {
1246
+ });
1247
+ }, PROBE_MS);
1248
+ timerRef.current = timer;
1249
+ }, [host?.pid, stop, t]);
1250
+ const copy = React.useCallback(() => {
1251
+ const command = host?.command ?? "";
1252
+ if (command === "") return;
1253
+ void navigator.clipboard?.writeText(command).then(() => {
1254
+ setCopied(true);
1255
+ }).catch(() => {
1256
+ });
1257
+ }, [host?.command]);
1258
+ React.useEffect(() => {
1259
+ const onKey = (event) => {
1260
+ if (event.key === "Escape") onClose();
1261
+ };
1262
+ document.addEventListener("keydown", onKey);
1263
+ return () => {
1264
+ document.removeEventListener("keydown", onKey);
1265
+ };
1266
+ }, [onClose]);
1267
+ const desktop = host?.kind === "desktop";
1268
+ return h(
1269
+ "div",
1270
+ { className: "dsh-pu-modal" },
1271
+ h("div", { className: "dsh-pu-modal-backdrop", onClick: onClose, "aria-hidden": "true" }),
1272
+ h(
1273
+ "div",
1274
+ {
1275
+ className: "dsh-pu-modal-body",
1276
+ role: "dialog",
1277
+ "aria-modal": "true",
1278
+ "aria-label": t("restartTitle")
1279
+ },
1280
+ h(
1281
+ "div",
1282
+ { className: "dsh-pu-modal-head" },
1283
+ h("span", { className: "dsh-pu-modal-title" }, t("restartTitle")),
1284
+ h("button", { type: "button", className: "dsh-pu-btn is-ghost is-tiny", onClick: onClose }, "\u2715")
1285
+ ),
1286
+ h("p", { className: "dsh-pu-modal-sub" }, t("restartBody")),
1287
+ phase === "loading" ? h("p", { className: "dsh-pu-hint" }, t("restartLoading")) : null,
1288
+ phase === "failed" ? h("p", { className: "dsh-pu-hint" }, t("restartLoadFailed", problem)) : null,
1289
+ desktop ? h("p", { className: "dsh-pu-hint" }, t("restartDesktopHint")) : host === void 0 ? null : h(
1290
+ "div",
1291
+ { className: "dsh-pu-cmdbox" },
1292
+ h("p", { className: "dsh-pu-hint" }, t("restartCommandHint")),
1293
+ h("code", { className: "dsh-pu-cmd" }, host.command),
1294
+ h(
1295
+ "button",
1296
+ {
1297
+ type: "button",
1298
+ className: "dsh-pu-btn is-tiny",
1299
+ onClick: copy,
1300
+ disabled: host.command === ""
1301
+ },
1302
+ copied ? t("restartCopied") : t("restartCopy")
1303
+ )
1304
+ ),
1305
+ host === void 0 ? null : h("p", { className: "dsh-pu-hint" }, t("restartPid", host.pid, host.profileName ?? "\u2014")),
1306
+ phase === "waiting" ? h("p", { className: "dsh-pu-hint" }, t("restartWaiting")) : null,
1307
+ phase === "stalled" ? h("p", { className: "dsh-pu-hint" }, stalledMessage(problem, t)) : null,
1308
+ h(
1309
+ "div",
1310
+ { className: "dsh-pu-src-foot" },
1311
+ h(
1312
+ "button",
1313
+ {
1314
+ type: "button",
1315
+ className: "dsh-pu-btn is-primary is-tiny",
1316
+ onClick: waitForRestart,
1317
+ disabled: host === void 0 || phase === "waiting"
1318
+ },
1319
+ phase === "waiting" ? t("restartWaiting") : t("restartRefresh")
1320
+ ),
1321
+ h(
1322
+ "button",
1323
+ { type: "button", className: "dsh-pu-btn is-ghost is-tiny", onClick: onClose },
1324
+ t("sourcesClose")
1325
+ )
1326
+ )
1327
+ )
1328
+ );
1329
+ }
1330
+
1105
1331
  // src/client/components/SourceDialog.ts
1106
1332
  function RegistrySourceButton(props) {
1107
1333
  const h = getH();
@@ -1578,6 +1804,8 @@ window.__ModuleLoader__.load({
1578
1804
  const [busyName, setBusyName] = React.useState(void 0);
1579
1805
  const [cancelling, setCancelling] = React.useState(false);
1580
1806
  const [banner, setBanner] = React.useState(void 0);
1807
+ const [restartOpen, setRestartOpen] = React.useState(false);
1808
+ const [restartPending, setRestartPending] = React.useState(false);
1581
1809
  const alive = useAlive();
1582
1810
  const watch = React.useCallback(
1583
1811
  async (id) => {
@@ -1585,6 +1813,7 @@ window.__ModuleLoader__.load({
1585
1813
  if (!alive.current) return settled;
1586
1814
  setBusyName(void 0);
1587
1815
  setCancelling(false);
1816
+ setRestartPending(false);
1588
1817
  reload(false);
1589
1818
  if (settled === void 0) {
1590
1819
  setJob(void 0);
@@ -1602,12 +1831,15 @@ window.__ModuleLoader__.load({
1602
1831
  });
1603
1832
  } else if (settled?.results?.some((result) => result.application === "restart-required") === true) {
1604
1833
  setBanner({ tone: "warn", text: t("restart") });
1834
+ setRestartPending(true);
1605
1835
  } else if (replacedAppearance(settled?.results)) {
1606
1836
  setBanner({ tone: "info", text: t("reloadForAppearance") });
1607
1837
  window.setTimeout(() => {
1608
1838
  void reloadWhenBootDocumentFresh({
1609
1839
  onBlocked: () => {
1610
- if (alive.current) setBanner({ tone: "warn", text: t("reloadBlocked") });
1840
+ if (!alive.current) return;
1841
+ setBanner({ tone: "warn", text: t("reloadBlocked") });
1842
+ setRestartPending(true);
1611
1843
  }
1612
1844
  });
1613
1845
  }, APPEARANCE_RELOAD_DELAY_MS);
@@ -1630,6 +1862,7 @@ window.__ModuleLoader__.load({
1630
1862
  async (steps, label) => {
1631
1863
  if (steps.length === 0) return;
1632
1864
  setBanner(void 0);
1865
+ setRestartPending(false);
1633
1866
  setBusyName(label);
1634
1867
  setJob({ id: "", status: "queued", total: steps.length, done: 0, failed: 0, log: [] });
1635
1868
  const outcome = await submitJob(steps, watch);
@@ -1685,6 +1918,7 @@ window.__ModuleLoader__.load({
1685
1918
  return;
1686
1919
  }
1687
1920
  setBanner(void 0);
1921
+ setRestartPending(false);
1688
1922
  install({ spec: `${row.name}@${version}`, title: row.title, version });
1689
1923
  },
1690
1924
  [props.install, t]
@@ -1788,12 +2022,29 @@ window.__ModuleLoader__.load({
1788
2022
  },
1789
2023
  h("span", null, banner.text),
1790
2024
  banner.tone === "warn" ? h("span", null, t("restartHint")) : null,
2025
+ /**
2026
+ * The restart button belongs to the restart banner only. A `warn`
2027
+ * banner is also raised for "the reload was stopped" and for "this
2028
+ * page has no install entry", and offering a restart for those would
2029
+ * be advice that does not apply — so the flag set by the result
2030
+ * decides, not the tone.
2031
+ */
2032
+ restartPending ? h(
2033
+ "button",
2034
+ {
2035
+ type: "button",
2036
+ className: "dsh-pu-btn is-tiny",
2037
+ onClick: () => setRestartOpen(true)
2038
+ },
2039
+ t("restartOpen")
2040
+ ) : null,
1791
2041
  h(
1792
2042
  "button",
1793
2043
  { type: "button", className: "dsh-pu-btn is-ghost is-tiny", onClick: () => setBanner(void 0) },
1794
2044
  "\u2715"
1795
2045
  )
1796
2046
  ),
2047
+ restartOpen ? h(RestartDialog, { t, onClose: () => setRestartOpen(false) }) : null,
1797
2048
  job === void 0 ? null : h(JobPanel, { job, t, onCancel: cancel, cancelling }),
1798
2049
  rows.length === 0 ? null : h(
1799
2050
  "div",
@@ -0,0 +1,82 @@
1
+ /**
2
+ * How this host was started, in terms a person can act on.
3
+ *
4
+ * A change the manager reports as `restart-required` can only be finished by
5
+ * restarting the process that refused it, and nothing here can do that to
6
+ * itself: the desktop shell exposes no relaunch channel to a page, and a host
7
+ * started from a terminal has nobody to start it again. What the page *can* do
8
+ * is name the one action that finishes the job, and for that it needs two
9
+ * facts that only the host process has — whether it was started by the desktop
10
+ * app or by a command line, and what that command line was.
11
+ *
12
+ * `pid` is the load-bearing half of the answer. Every other field describes the
13
+ * profile, which survives a restart untouched; the pid is the only value that
14
+ * tells a polling page whether the host answering it is still the old one.
15
+ *
16
+ * @module dsh-plugin-upgrader/host/hostinfo
17
+ */
18
+ /**
19
+ * Who started this process.
20
+ *
21
+ * `desktop` means the Electron shell owns the lifecycle and the user finishes
22
+ * the restart by quitting and reopening the app; `cli` means the host *is* the
23
+ * terminal command and the user finishes it by running that command again.
24
+ */
25
+ export type HostKind = 'desktop' | 'cli';
26
+ /** What `/api/plugin-upgrader/host` answers with. */
27
+ export interface HostInfo {
28
+ /** The process id; a restart is the only thing that changes it. */
29
+ pid: number;
30
+ /** When this process started, in the same clock as `Date.now()`. */
31
+ startedAt: number;
32
+ kind: HostKind;
33
+ /** The profile directory's last path segment, for display only. */
34
+ profileName: string | null;
35
+ /** The profile directory this host opened, when it could be resolved. */
36
+ profileDir: string | null;
37
+ /** A command line that starts this same host again; empty for `desktop`. */
38
+ command: string;
39
+ }
40
+ /**
41
+ * Decide who owns this process's lifecycle from its entry point.
42
+ *
43
+ * The check is on the entry script rather than on an environment variable
44
+ * because the entry script is what the shell actually executes: the desktop
45
+ * shell runs `dsh-desktop-host/lib/index.js` and nothing else in this install
46
+ * runs from that path.
47
+ *
48
+ * @param entry - `process.argv[1]`, possibly absent.
49
+ * @returns which kind of start this was.
50
+ */
51
+ export declare function hostKindOf(entry: string): HostKind;
52
+ /**
53
+ * Rebuild the command that started this process.
54
+ *
55
+ * The desktop shell is deliberately answered with an empty string: its host is
56
+ * a child of the app, and replaying the child's own command line would start a
57
+ * second host holding the same profile. The instruction that actually works
58
+ * there is "quit the app and open it again", which the page writes itself.
59
+ *
60
+ * @param execPath - `process.execPath`.
61
+ * @param argv - `process.argv`.
62
+ * @param kind - who owns the lifecycle.
63
+ * @returns the command line, or an empty string when there is none to give.
64
+ */
65
+ export declare function relaunchCommand(execPath: string, argv: readonly string[], kind: HostKind): string;
66
+ /**
67
+ * Assemble the answer for one host process.
68
+ *
69
+ * Pure on purpose: the pid, the start time and the profile directory are all
70
+ * inputs, so the shape can be tested without a host.
71
+ *
72
+ * @param input - the facts the process has about itself.
73
+ * @returns what the page may show.
74
+ */
75
+ export declare function buildHostInfo(input: {
76
+ pid: number;
77
+ startedAt: number;
78
+ execPath: string;
79
+ argv: readonly string[];
80
+ profileDir: string | null;
81
+ }): HostInfo;
82
+ //# sourceMappingURL=hostinfo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostinfo.d.ts","sourceRoot":"","sources":["../../src/host/hostinfo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAA;AAExC,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACvB,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAA;IACX,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,QAAQ,CAAA;IACd,mEAAmE;IACnE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,yEAAyE;IACzE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAA;CAChB;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAElD;AAeD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAIjG;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,GAAG,QAAQ,CAkBX"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * How this host was started, in terms a person can act on.
3
+ *
4
+ * A change the manager reports as `restart-required` can only be finished by
5
+ * restarting the process that refused it, and nothing here can do that to
6
+ * itself: the desktop shell exposes no relaunch channel to a page, and a host
7
+ * started from a terminal has nobody to start it again. What the page *can* do
8
+ * is name the one action that finishes the job, and for that it needs two
9
+ * facts that only the host process has — whether it was started by the desktop
10
+ * app or by a command line, and what that command line was.
11
+ *
12
+ * `pid` is the load-bearing half of the answer. Every other field describes the
13
+ * profile, which survives a restart untouched; the pid is the only value that
14
+ * tells a polling page whether the host answering it is still the old one.
15
+ *
16
+ * @module dsh-plugin-upgrader/host/hostinfo
17
+ */
18
+ /** The entry point the desktop shell spawns for its host child process. */
19
+ const DESKTOP_ENTRY = /[\\/]dsh-desktop-host[\\/]lib[\\/]index\.js$/i;
20
+ /**
21
+ * Decide who owns this process's lifecycle from its entry point.
22
+ *
23
+ * The check is on the entry script rather than on an environment variable
24
+ * because the entry script is what the shell actually executes: the desktop
25
+ * shell runs `dsh-desktop-host/lib/index.js` and nothing else in this install
26
+ * runs from that path.
27
+ *
28
+ * @param entry - `process.argv[1]`, possibly absent.
29
+ * @returns which kind of start this was.
30
+ */
31
+ export function hostKindOf(entry) {
32
+ return DESKTOP_ENTRY.test(entry) ? 'desktop' : 'cli';
33
+ }
34
+ /**
35
+ * Quote one argument for the platform's shell.
36
+ *
37
+ * Only the case a person can paste is handled: an argument with whitespace is
38
+ * wrapped in double quotes, which both `cmd.exe` and POSIX shells accept.
39
+ *
40
+ * @param argument - one raw argv entry.
41
+ * @returns the entry as it would be typed.
42
+ */
43
+ function quoted(argument) {
44
+ return /\s/.test(argument) ? `"${argument}"` : argument;
45
+ }
46
+ /**
47
+ * Rebuild the command that started this process.
48
+ *
49
+ * The desktop shell is deliberately answered with an empty string: its host is
50
+ * a child of the app, and replaying the child's own command line would start a
51
+ * second host holding the same profile. The instruction that actually works
52
+ * there is "quit the app and open it again", which the page writes itself.
53
+ *
54
+ * @param execPath - `process.execPath`.
55
+ * @param argv - `process.argv`.
56
+ * @param kind - who owns the lifecycle.
57
+ * @returns the command line, or an empty string when there is none to give.
58
+ */
59
+ export function relaunchCommand(execPath, argv, kind) {
60
+ if (kind === 'desktop')
61
+ return '';
62
+ const rest = argv.slice(1).map(quoted).join(' ');
63
+ return rest === '' ? quoted(execPath) : `${quoted(execPath)} ${rest}`;
64
+ }
65
+ /**
66
+ * Assemble the answer for one host process.
67
+ *
68
+ * Pure on purpose: the pid, the start time and the profile directory are all
69
+ * inputs, so the shape can be tested without a host.
70
+ *
71
+ * @param input - the facts the process has about itself.
72
+ * @returns what the page may show.
73
+ */
74
+ export function buildHostInfo(input) {
75
+ const kind = hostKindOf(input.argv[1] ?? '');
76
+ const profileDir = input.profileDir;
77
+ const profileName = profileDir === null
78
+ ? null
79
+ : (profileDir
80
+ .split(/[\\/]/)
81
+ .filter((segment) => segment !== '')
82
+ .at(-1) ?? null);
83
+ return {
84
+ pid: input.pid,
85
+ startedAt: input.startedAt,
86
+ kind,
87
+ profileName,
88
+ profileDir,
89
+ command: relaunchCommand(input.execPath, input.argv, kind),
90
+ };
91
+ }
92
+ //# sourceMappingURL=hostinfo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostinfo.js","sourceRoot":"","sources":["../../src/host/hostinfo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA0BH,2EAA2E;AAC3E,MAAM,aAAa,GAAG,+CAA+C,CAAA;AAErE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;AACtD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,MAAM,CAAC,QAAgB;IAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAA;AACzD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAuB,EAAE,IAAc;IACvF,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAChD,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAA;AACvE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,KAM7B;IACC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAA;IACnC,MAAM,WAAW,GACf,UAAU,KAAK,IAAI;QACjB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,UAAU;aACR,KAAK,CAAC,OAAO,CAAC;aACd,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC;aACnC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAA;IACxB,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,IAAI;QACJ,WAAW;QACX,UAAU;QACV,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;KAC3D,CAAA;AACH,CAAC"}
@@ -26,6 +26,8 @@ export interface StepOutcome {
26
26
  detail?: string;
27
27
  pendingBuilds?: string[];
28
28
  warnings?: string[];
29
+ /** The version this step put back after destroying the one that was there. */
30
+ rolledBack?: string;
29
31
  packageResult?: {
30
32
  exitCode: number;
31
33
  kind?: string;
@@ -35,6 +37,21 @@ export interface StepOutcome {
35
37
  }
36
38
  /** Allowed per-step actions. */
37
39
  export declare const ACTIONS: Set<string>;
40
+ /**
41
+ * One version's DSH requirement, looked up only when a step is about to run.
42
+ *
43
+ * The lookup is injected rather than imported so this module keeps no registry
44
+ * client: the caller already has the packument cache and the chosen registry,
45
+ * and asking the network here would duplicate both.
46
+ */
47
+ export interface InstallGuard {
48
+ /** The DSH build this process runs, when it could be read. */
49
+ runtimeVersion?: string | undefined;
50
+ /** The requirement `name@version` declares, or `undefined` when unknown. */
51
+ requirementOf: (name: string, version: string) => Promise<{
52
+ range: string;
53
+ } | undefined>;
54
+ }
38
55
  /**
39
56
  * Re-apply the enabled state a step asked for after the package was replaced.
40
57
  *
@@ -78,9 +95,10 @@ export declare function restoreSelection(manager: PluginManager, name: string, l
78
95
  * @param log - progress sink.
79
96
  * @param announce - receives the request id the step installs under.
80
97
  * @param registry - the registry chosen in this plugin's config, if any.
98
+ * @param guard - the compatibility check, when the caller can supply one.
81
99
  * @returns the outcome record.
82
100
  */
83
- export declare function runStep(manager: PluginManager, step: StepRecord, log: LogSink, announce?: RequestIdSink, registry?: string): Promise<StepOutcome>;
101
+ export declare function runStep(manager: PluginManager, step: StepRecord, log: LogSink, announce?: RequestIdSink, registry?: string, guard?: InstallGuard): Promise<StepOutcome>;
84
102
  /**
85
103
  * Whether a step names something this plugin is willing to install.
86
104
  *
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/host/install.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAc,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAGvF,iCAAiC;AACjC,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;AAEvD,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;IACzC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACvC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,gCAAgC;AAChC,eAAO,MAAM,OAAO,aAAyC,CAAA;AA2L7D;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAC9B,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAuB9B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAsGD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE,aAAa,EACxB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAqJtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM9D"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/host/install.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAc,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAIvF,iCAAiC;AACjC,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;AAEvD,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;IACzC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACvC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,gCAAgC;AAChC,eAAO,MAAM,OAAO,aAAyC,CAAA;AA+H7D;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,4EAA4E;IAC5E,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAA;CACzF;AA8GD;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAC9B,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAuB9B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,OAAO,CAAC,CAmBlB;AA0MD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE,aAAa,EACxB,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,WAAW,CAAC,CAuLtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM9D"}