dsh-edge 0.9.0 → 0.10.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.
Files changed (56) hide show
  1. package/THIRD_PARTY_NOTICES.md +1318 -1075
  2. package/dist/assets/index-Df-65__b.js +110 -0
  3. package/dist/assets/index-b24khbeK.css +1 -0
  4. package/dist/assets/langs/{php-DDkx9sim.js → php-DJl5gRdb.js} +2 -2
  5. package/dist/assets/langs/{ruby-DCxyoPen.js → ruby-5eNB0pDK.js} +2 -2
  6. package/dist/assets/vendor-BNsW4eBh.css +1 -0
  7. package/dist/assets/vendor-CCJJTK99.js +411 -0
  8. package/dist/index.html +8 -8
  9. package/dist/plugins/@deepseek-ai/dsh-api-gateway/client.js +1513 -77
  10. package/dist/plugins/@deepseek-ai/dsh-api-remotes/client.js +3608 -757
  11. package/dist/plugins/@deepseek-ai/dsh-api-session-controller/client.js +2777 -0
  12. package/dist/plugins/@deepseek-ai/dsh-api-workspace-controller/client.js +415 -0
  13. package/dist/plugins/@deepseek-ai/dsh-client-connection/client.js +1975 -7466
  14. package/dist/plugins/@deepseek-ai/dsh-client-locale/client.js +225 -76
  15. package/dist/plugins/@deepseek-ai/dsh-client-modules/client.js +67 -15
  16. package/dist/plugins/@deepseek-ai/dsh-client-ui-agent-preset/client.js +270 -460
  17. package/dist/plugins/@deepseek-ai/dsh-client-ui-approval/client.js +292 -0
  18. package/dist/plugins/@deepseek-ai/dsh-client-ui-attachment/client.js +42 -17
  19. package/dist/plugins/@deepseek-ai/dsh-client-ui-brand-official/client.js +7 -9
  20. package/dist/plugins/@deepseek-ai/dsh-client-ui-chat/client.js +8177 -0
  21. package/dist/plugins/@deepseek-ai/dsh-client-ui-commands/client.js +22 -10
  22. package/dist/plugins/@deepseek-ai/dsh-client-ui-conversation/client.js +14950 -8910
  23. package/dist/plugins/@deepseek-ai/dsh-client-ui-deliverables/client.js +161 -137
  24. package/dist/plugins/@deepseek-ai/dsh-client-ui-goal/client.js +6 -7
  25. package/dist/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js +268 -40
  26. package/dist/plugins/@deepseek-ai/dsh-client-ui-jobs/client.js +1 -1
  27. package/dist/plugins/@deepseek-ai/dsh-client-ui-layout/client.js +45 -11
  28. package/dist/plugins/@deepseek-ai/dsh-client-ui-message-feedback/client.js +30 -58
  29. package/dist/plugins/@deepseek-ai/dsh-client-ui-model-selection/client.js +188 -89
  30. package/dist/plugins/@deepseek-ai/dsh-client-ui-permission-presets/client.js +105 -75
  31. package/dist/plugins/@deepseek-ai/dsh-client-ui-renderer/client.js +650 -188
  32. package/dist/plugins/@deepseek-ai/dsh-client-ui-schedule/client.js +307 -0
  33. package/dist/plugins/@deepseek-ai/dsh-client-ui-session/client.js +340 -0
  34. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings/client.js +57 -50
  35. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-general/client.js +134 -69
  36. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-models/client.js +575 -442
  37. package/dist/plugins/@deepseek-ai/dsh-client-ui-sidebar/client.js +24 -11
  38. package/dist/plugins/@deepseek-ai/dsh-client-ui-skill/client.js +13 -9
  39. package/dist/plugins/@deepseek-ai/dsh-client-ui-subagent/client.js +44 -20
  40. package/dist/plugins/@deepseek-ai/dsh-client-ui-theme/client.js +265 -94
  41. package/dist/plugins/@deepseek-ai/dsh-client-ui-tool/client.js +899 -433
  42. package/dist/plugins/@deepseek-ai/dsh-client-ui-trajectory/client.js +1472 -613
  43. package/dist/plugins/@deepseek-ai/dsh-client-ui-user-questions/client.js +249 -95
  44. package/dist/plugins/@deepseek-ai/dsh-client-ui-workflow-run/client.js +5 -5
  45. package/dist/plugins/@deepseek-ai/dsh-client-ui-workspace/client.js +425 -146
  46. package/dist/plugins/@deepseek-ai/dsh-typert-registry/client.js +29 -14
  47. package/dist/plugins/dsh-edge-client-ui/client.js +28 -26
  48. package/package.json +62 -58
  49. package/scripts/verify-packed.mjs +1 -1
  50. package/worker/direct/index.js +2866 -1466
  51. package/worker/isolated/index.js +2438 -1038
  52. package/dist/assets/index-C6eRlFa6.css +0 -1
  53. package/dist/assets/index-ClqxG24t.js +0 -96
  54. package/dist/assets/vendor-CjyC-hUb.css +0 -1
  55. package/dist/assets/vendor-D22_Mp1f.js +0 -411
  56. package/dist/plugins/@deepseek-ai/dsh-client-runtime/client.js +0 -10574
@@ -5,7 +5,7 @@ window.__ModuleLoader__.load({
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let _deepseek_ai_cordis = require("@deepseek-ai/cordis");
8
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
8
+ let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
9
9
  //#region ../../../vendor/cosmokit/src/misc.ts
10
10
  /** Return true when a value is `null` or `undefined`. */
11
11
  function isNullable(value) {
@@ -934,11 +934,9 @@ window.__ModuleLoader__.load({
934
934
  //#endregion
935
935
  //#region lib/types/client/settings-scope.js
936
936
  /**
937
- * Host transport for the settings-namespace scope contract. The contract types
938
- * live in `dsh-client-runtime` (the common dependency of every feature that
939
- * owns a preference); this file owns the per-namespace derivation over the
940
- * shared {@link SettingsDescribeMirror} and the serialized write path, both of
941
- * which are Settings-surface concerns. Reads never touch the wire here: the
937
+ * Host transport for the settings-namespace scope contract. This file owns the
938
+ * per-namespace derivation over the shared {@link SettingsDescribeMirror} and
939
+ * the serialized write path. Reads never touch the wire here: the
942
940
  * mirror is the one `settings.describe` reader, and every scope is a selector
943
941
  * over its snapshot.
944
942
  */
@@ -949,7 +947,7 @@ window.__ModuleLoader__.load({
949
947
  * the operation already crossing the wire.
950
948
  */
951
949
  var SettingsScopeController = class {
952
- api;
950
+ ctx;
953
951
  spec;
954
952
  mirror;
955
953
  persistence;
@@ -966,19 +964,20 @@ window.__ModuleLoader__.load({
966
964
  */
967
965
  pendingRevision;
968
966
  /**
969
- * @param api - settings wire face (writes only; reads ride the mirror).
967
+ * @param ctx - the providing plugin's context, whose `remote.settings`
968
+ * namespace carries this scope's writes (reads ride the mirror).
970
969
  * @param spec - namespace identity and optional narrowing decoder.
971
970
  * @param mirror - the shared describe mirror this scope derives from.
972
- * @param persistence - remote browsers remain process-local because settings RPCs are loopback-only.
971
+ * @param persistence - client-selected Host persistence; non-loopback pages may remain process-local.
973
972
  * @param schema - settings-owned schema operations.
974
973
  */
975
- constructor(api, spec, mirror, persistence, schema) {
976
- this.api = api;
974
+ constructor(ctx, spec, mirror, persistence, schema) {
975
+ this.ctx = ctx;
977
976
  this.spec = spec;
978
977
  this.mirror = mirror;
979
978
  this.persistence = persistence;
980
979
  this.schema = schema;
981
- this.store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
980
+ this.store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
982
981
  status: persistence === "host" ? "loading" : "unavailable",
983
982
  value: void 0,
984
983
  base: void 0,
@@ -1014,11 +1013,11 @@ window.__ModuleLoader__.load({
1014
1013
  * @returns settlement after the write and any latest-write recovery read.
1015
1014
  */
1016
1015
  set(field, value) {
1017
- return this.write({
1016
+ return this.mutate([{
1018
1017
  op: "set",
1019
1018
  path: [field],
1020
1019
  value
1021
- });
1020
+ }]);
1022
1021
  }
1023
1022
  /**
1024
1023
  * Queue one field clear; see {@link SettingsScope.unset} for the ordering,
@@ -1027,35 +1026,32 @@ window.__ModuleLoader__.load({
1027
1026
  * @returns settlement after the clear and any latest-write recovery read.
1028
1027
  */
1029
1028
  unset(field) {
1030
- return this.write({
1029
+ return this.mutate([{
1031
1030
  op: "unset",
1032
1031
  path: [field]
1033
- });
1032
+ }]);
1034
1033
  }
1035
- write(op) {
1034
+ /**
1035
+ * Queue one atomic namespace mutation; see {@link SettingsScope.mutate}.
1036
+ * @param ops - ordered field operations copied when queued.
1037
+ * @param expectedRevision - optional fixed revision read by the domain editor.
1038
+ * @returns settlement after the mutation and any latest-write recovery read.
1039
+ */
1040
+ mutate(ops, expectedRevision) {
1041
+ const ownedOps = structuredClone(ops);
1036
1042
  const generation = ++this.writeGeneration;
1037
1043
  return this.enqueue(async () => {
1038
- const revision = this.pendingRevision ?? this.getSnapshot().revision;
1039
- let response;
1040
- try {
1041
- response = await this.api.settings.mutate({
1042
- ns: this.spec.namespace,
1043
- ops: [op],
1044
- ...revision === void 0 ? {} : { expectedRevision: revision }
1045
- });
1046
- } catch (_settingsWriteFailure) {
1047
- await this.recover(generation);
1048
- return;
1049
- }
1050
- if (!response.result.ok) {
1044
+ const revision = expectedRevision ?? this.pendingRevision ?? this.getSnapshot().revision;
1045
+ const response = await this.ctx.remote.settings.mutate(this.spec.namespace, ownedOps, revision);
1046
+ if (!response.ok) {
1051
1047
  await this.recover(generation);
1052
1048
  return;
1053
1049
  }
1054
1050
  if (this.disposed) return;
1055
1051
  if (generation === this.writeGeneration) {
1056
1052
  this.pendingRevision = void 0;
1057
- this.mirror.acceptView(response.result.value);
1058
- } else this.pendingRevision = response.result.value.revision;
1053
+ this.mirror.acceptView(response.value);
1054
+ } else this.pendingRevision = response.value.revision;
1059
1055
  });
1060
1056
  }
1061
1057
  /** Reload Host state for the latest failed write; superseded failures leave recovery to it. */
@@ -1130,15 +1126,25 @@ window.__ModuleLoader__.load({
1130
1126
  var SettingsScopeBinder = class extends _deepseek_ai_cordis.Service {
1131
1127
  mirror;
1132
1128
  schema;
1129
+ persistence;
1130
+ /**
1131
+ * The PROVIDING fiber, kept because a Service reads `ctx` as its *consumer's*
1132
+ * fiber: letting a bound scope write through the caller's context would make
1133
+ * every caller declare `remote.settings` in its own `inject`.
1134
+ */
1135
+ owner;
1133
1136
  /**
1134
1137
  * @param ctx - the providing plugin's context.
1135
1138
  * @param config - the shared describe mirror every bound scope derives from,
1136
- * plus the settings-owned schema operations.
1139
+ * the settings-owned schema operations, and the Host persistence the provider
1140
+ * resolved from `remote.$host`.
1137
1141
  */
1138
1142
  constructor(ctx, config) {
1139
1143
  super(ctx, "settingsScope");
1140
1144
  this.mirror = config.mirror;
1141
1145
  this.schema = config.schema;
1146
+ this.persistence = config.persistence;
1147
+ this.owner = ctx;
1142
1148
  }
1143
1149
  /**
1144
1150
  * The shared mirror's read/fold face for cross-namespace surfaces (schema
@@ -1162,8 +1168,7 @@ window.__ModuleLoader__.load({
1162
1168
  */
1163
1169
  bind(spec) {
1164
1170
  const ctx = this.ctx;
1165
- const connection = ctx.get("connection");
1166
- const controller = new SettingsScopeController(connection.api, spec, this.mirror, connection.isLoopback ? "host" : "memory", this.schema);
1171
+ const controller = new SettingsScopeController(this.owner, spec, this.mirror, this.persistence, this.schema);
1167
1172
  ctx.effect(() => {
1168
1173
  this.mirror.ensure();
1169
1174
  return async () => {
@@ -1191,20 +1196,21 @@ window.__ModuleLoader__.load({
1191
1196
  * so an invalidation arriving mid-read is never lost and never duplicated.
1192
1197
  */
1193
1198
  var SettingsDescribeMirror = class {
1194
- api;
1199
+ ctx;
1195
1200
  persistence;
1196
1201
  store;
1197
1202
  inFlight;
1198
1203
  rerun = false;
1199
1204
  generation = 0;
1200
1205
  /**
1201
- * @param api - settings wire face.
1202
- * @param persistence - remote browsers stay process-local because settings RPCs are loopback-only.
1206
+ * @param ctx - the providing plugin's context, whose `remote.settings`
1207
+ * namespace answers the describe read.
1208
+ * @param persistence - client-selected Host persistence; non-loopback pages may remain process-local.
1203
1209
  */
1204
- constructor(api, persistence = "host") {
1205
- this.api = api;
1210
+ constructor(ctx, persistence = "host") {
1211
+ this.ctx = ctx;
1206
1212
  this.persistence = persistence;
1207
- this.store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
1213
+ this.store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
1208
1214
  status: persistence === "host" ? "idle" : "unavailable",
1209
1215
  view: void 0,
1210
1216
  error: null
@@ -1290,8 +1296,8 @@ window.__ModuleLoader__.load({
1290
1296
  const generation = ++this.generation;
1291
1297
  let outcome;
1292
1298
  try {
1293
- const response = await this.api.settings.describe({});
1294
- outcome = response.result.ok ? { view: response.result.value } : { failure: response.result.error.message };
1299
+ const response = await this.ctx.remote.settings.describe();
1300
+ outcome = response.ok ? { view: response.value } : { failure: response.error.message };
1295
1301
  } catch (error) {
1296
1302
  outcome = { failure: error instanceof Error ? error.message : String(error) };
1297
1303
  }
@@ -1321,10 +1327,10 @@ window.__ModuleLoader__.load({
1321
1327
  //#endregion
1322
1328
  //#region lib/types/client/index.js
1323
1329
  /**
1324
- * Required services: the wire handle for the mirror's reads and the forwarded
1325
- * settings invalidation the mirror refreshes on.
1330
+ * Required services: the Remote namespace the mirror reads through and the
1331
+ * forwarded settings invalidation it refreshes on.
1326
1332
  */
1327
- const inject = ["connection", "remote"];
1333
+ const inject = ["remote", "remote.settings"];
1328
1334
  /**
1329
1335
  * Provide the settings-namespace scope service over one shared describe
1330
1336
  * mirror, and keep that mirror fresh on the two signals that can move the
@@ -1336,10 +1342,10 @@ window.__ModuleLoader__.load({
1336
1342
  */
1337
1343
  function apply(ctx) {
1338
1344
  const schema = new SettingsSchemaService(ctx);
1339
- const connection = ctx.get("connection");
1340
- const mirror = new SettingsDescribeMirror(connection.api, connection.isLoopback ? "host" : "memory");
1345
+ const persistence = ctx.remote.$host.isLoopback ? "host" : "memory";
1346
+ const mirror = new SettingsDescribeMirror(ctx, persistence);
1341
1347
  ctx.effect(() => {
1342
- const disposers = [ctx.get("remote").$on("settings/document-updated", () => {
1348
+ const disposers = [ctx.remote.$on("settings/document-updated", () => {
1343
1349
  mirror.load();
1344
1350
  }), ctx.on("connection/reset", () => {
1345
1351
  mirror.load();
@@ -1351,7 +1357,8 @@ window.__ModuleLoader__.load({
1351
1357
  }, "ui-settings: describe mirror invalidations");
1352
1358
  new SettingsScopeBinder(ctx, {
1353
1359
  mirror,
1354
- schema
1360
+ schema,
1361
+ persistence
1355
1362
  });
1356
1363
  }
1357
1364
  //#endregion
@@ -8,7 +8,7 @@ window.__ModuleLoader__.load({
8
8
  let react_jsx_runtime = require("react/jsx-runtime");
9
9
  let react = require("react");
10
10
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
11
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
11
+ let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
12
12
  //#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
13
13
  function r(e) {
14
14
  var t, f, n = "";
@@ -25,7 +25,7 @@ window.__ModuleLoader__.load({
25
25
  }
26
26
  //#endregion
27
27
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-general/src/client/SettingsRoot.module.css.mjs
28
- const css$3 = ".VOzbGW_trigger{box-sizing:border-box;cursor:pointer;width:calc(100% + 4px);height:42px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:12px;flex:none;align-items:center;gap:8px;margin:4px -2px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.VOzbGW_trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.VOzbGW_trigger.VOzbGW_rail{border-radius:50%;justify-content:center;gap:0;width:36px;height:36px;margin:8px 0 10px;padding:0}.VOzbGW_triggerLabel{white-space:nowrap;overflow:hidden}.VOzbGW_overlay{z-index:1000;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.VOzbGW_mask{background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur);position:absolute;inset:0}.VOzbGW_panel{z-index:1;background:var(--dsw-alias-bg-layer-2);width:800px;max-width:calc(100vw - 48px);height:min(800px,100vh - 48px);box-shadow:var(--dsw-shadow-lv3);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:24px;display:flex;position:relative;overflow:hidden}.VOzbGW_nav{box-sizing:border-box;flex-direction:column;flex:none;gap:18px;width:188px;padding:22px 12px 0;display:flex}.VOzbGW_navTitle{color:var(--dsw-alias-label-primary);padding:0 12px;font-size:16px;font-weight:500;line-height:24px}.VOzbGW_navList{flex-direction:column;gap:4px;display:flex}.VOzbGW_navCell{box-sizing:border-box;cursor:pointer;height:40px;color:var(--dsw-alias-label-primary);text-align:left;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:9px 16px 9px 12px;font-family:inherit;font-size:14px;font-weight:400;line-height:22px;display:flex}.VOzbGW_navCell:hover{background:var(--dsw-specific-sidebar-nav-item-hover)}.VOzbGW_navCell.VOzbGW_active{background:var(--dsw-specific-sidebar-nav-item-active)}.VOzbGW_navIcon{flex:none}.VOzbGW_navLabel{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.VOzbGW_content{flex-direction:column;flex:1;min-width:0;display:flex}.VOzbGW_header{box-sizing:border-box;flex:none;justify-content:space-between;align-items:flex-start;gap:8px;height:54px;padding:20px 14px 8px 10px;display:flex}.VOzbGW_actions{justify-content:flex-end;align-items:center;gap:8px;min-width:0;margin-left:auto;display:flex}.VOzbGW_close{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.VOzbGW_close:hover{background:var(--dsw-alias-interactive-bg-hover)}.VOzbGW_options{flex:1;min-height:0;padding:0 24px 24px;overflow-y:auto}.VOzbGW_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}";
28
+ const css$3 = ".VOzbGW_triggerRow{flex:none;align-items:center;gap:8px;width:calc(100% + 4px);margin:4px -2px;display:flex}.VOzbGW_triggerRow.VOzbGW_railRow{width:36px;margin:8px 0 10px}.VOzbGW_trigger{box-sizing:border-box;cursor:pointer;width:auto;min-width:0;height:42px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:12px;flex:1;align-items:center;gap:8px;margin:0;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.VOzbGW_trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.VOzbGW_trigger.VOzbGW_rail{corner-shape:round;border-radius:50%;flex:none;justify-content:center;gap:0;width:36px;height:36px;margin:0;padding:0}.VOzbGW_triggerLabel{white-space:nowrap;overflow:hidden}.VOzbGW_overlay{z-index:1000;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.VOzbGW_mask{background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur);position:absolute;inset:0}.VOzbGW_panel{z-index:1;background:var(--dsw-alias-bg-layer-2);width:800px;max-width:calc(100vw - 48px);height:min(800px,100vh - 48px);box-shadow:var(--dsw-elevation-prominent);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:32px;display:flex;position:relative;overflow:hidden}.VOzbGW_nav{box-sizing:border-box;flex-direction:column;flex:none;gap:18px;width:188px;padding:22px 12px 0;display:flex}.VOzbGW_navTitle{color:var(--dsw-alias-label-primary);padding:0 12px;font-size:16px;font-weight:500;line-height:24px}.VOzbGW_navList{flex-direction:column;gap:4px;display:flex}.VOzbGW_navCell{box-sizing:border-box;cursor:pointer;height:40px;color:var(--dsw-alias-label-primary);text-align:left;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:9px 16px 9px 12px;font-family:inherit;font-size:14px;font-weight:400;line-height:22px;display:flex}.VOzbGW_navCell:hover{background:var(--dsw-specific-sidebar-nav-item-hover)}.VOzbGW_navCell.VOzbGW_active{background:var(--dsw-specific-sidebar-nav-item-active)}.VOzbGW_navIcon{flex:none}.VOzbGW_navLabel{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.VOzbGW_content{flex-direction:column;flex:1;min-width:0;display:flex}.VOzbGW_header{box-sizing:border-box;flex:none;justify-content:space-between;align-items:flex-start;gap:8px;height:54px;padding:20px 14px 8px 10px;display:flex}.VOzbGW_actions{justify-content:flex-end;align-items:center;gap:8px;min-width:0;margin-left:auto;display:flex}.VOzbGW_close{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.VOzbGW_close:hover{background:var(--dsw-alias-interactive-bg-hover)}.VOzbGW_options{flex:1;min-height:0;padding:0 24px 24px;overflow-y:auto}.VOzbGW_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}";
29
29
  const tagId$3 = "@deepseek-ai/dsh-client-ui-settings-general/SettingsRoot.module.css";
30
30
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
31
31
  const tag = document.createElement("style");
@@ -52,8 +52,10 @@ window.__ModuleLoader__.load({
52
52
  "overlay": "VOzbGW_overlay",
53
53
  "panel": "VOzbGW_panel",
54
54
  "rail": "VOzbGW_rail",
55
+ "railRow": "VOzbGW_railRow",
55
56
  "trigger": "VOzbGW_trigger",
56
- "triggerLabel": "VOzbGW_triggerLabel"
57
+ "triggerLabel": "VOzbGW_triggerLabel",
58
+ "triggerRow": "VOzbGW_triggerRow"
57
59
  };
58
60
  //#endregion
59
61
  //#region lib/types/client/SettingsRoot.js
@@ -69,6 +71,7 @@ window.__ModuleLoader__.load({
69
71
  * sessions-derived empty-Hero fact is active. Visible dialog chrome belongs
70
72
  * to the step, so a mounted-but-deciding step paints nothing here.
71
73
  */
74
+ const RECOVERY_CONFIRMATION_MS = 2e3;
72
75
  /** Nav glyph by section id; unknown ids fall back to the settings gear. */
73
76
  function navIcon(id) {
74
77
  if (id === "models") return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDataOutline16, {
@@ -173,19 +176,28 @@ window.__ModuleLoader__.load({
173
176
  * @returns the settings shell element tree.
174
177
  */
175
178
  function SettingsRoot(props) {
176
- const { wide, useSections, useOnboardingSteps, useSessions, renderSlot } = props;
179
+ const { wide, reconnect, useConnectionState, useSections, useOnboardingSteps, useSessions, renderSlot, t } = props;
177
180
  const [open, setOpen] = (0, react.useState)(false);
178
181
  const [activeId, setActiveId] = (0, react.useState)(void 0);
179
182
  const [completedOnboarding, setCompletedOnboarding] = (0, react.useState)(() => /* @__PURE__ */ new Set());
183
+ const [showRecovery, setShowRecovery] = (0, react.useState)(false);
184
+ const triggerButton = (0, react.useRef)(null);
185
+ const wasOpen = (0, react.useRef)(open);
180
186
  const close = (0, react.useCallback)(() => {
181
187
  setOpen(false);
182
188
  setActiveId(void 0);
183
189
  }, []);
190
+ (0, react.useEffect)(() => {
191
+ if (wasOpen.current && !open) triggerButton.current?.focus();
192
+ wasOpen.current = open;
193
+ }, [open]);
184
194
  const openSection = (0, react.useCallback)((id) => {
185
195
  setActiveId(id);
186
196
  setOpen(true);
187
197
  }, []);
188
198
  const rows = useSections((s) => s);
199
+ const connectionState = useConnectionState((state) => state);
200
+ const previousConnectionState = (0, react.useRef)(connectionState);
189
201
  const onboardingSteps = useOnboardingSteps((s) => s);
190
202
  const onboardingActive = useSessions((state) => state.phase === "ready" && (state.current === void 0 || state.byId[state.current]?.blank === true));
191
203
  const onboardingStep = onboardingActive ? onboardingSteps.find((step) => !completedOnboarding.has(step.id)) : void 0;
@@ -193,22 +205,55 @@ window.__ModuleLoader__.load({
193
205
  if (onboardingActive) return;
194
206
  setCompletedOnboarding(/* @__PURE__ */ new Set());
195
207
  }, [onboardingActive]);
208
+ (0, react.useLayoutEffect)(() => {
209
+ const previous = previousConnectionState.current;
210
+ previousConnectionState.current = connectionState;
211
+ if (connectionState !== "connected") {
212
+ setShowRecovery(false);
213
+ return;
214
+ }
215
+ if (previous !== "disconnected" && previous !== "connecting") return;
216
+ setShowRecovery(true);
217
+ const timeout = window.setTimeout(() => {
218
+ setShowRecovery(false);
219
+ }, RECOVERY_CONFIRMATION_MS);
220
+ return () => {
221
+ window.clearTimeout(timeout);
222
+ };
223
+ }, [connectionState]);
196
224
  const completeOnboardingStep = (0, react.useCallback)((id) => {
197
225
  setCompletedOnboarding((previous) => {
198
226
  if (previous.has(id)) return previous;
199
227
  return new Set([...previous, id]);
200
228
  });
201
229
  }, []);
230
+ let connectionIndicator;
231
+ if (connectionState === "disconnected") connectionIndicator = "disconnected";
232
+ else if (connectionState === "connecting") connectionIndicator = "connecting";
233
+ else if (showRecovery) connectionIndicator = "recovered";
202
234
  return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
203
- (0, react_jsx_runtime.jsx)("button", {
204
- type: "button",
205
- className: clsx(SettingsRoot_module_css_default.trigger, !wide && SettingsRoot_module_css_default.rail),
206
- "aria-haspopup": "dialog",
207
- "aria-expanded": open,
208
- onClick: () => {
209
- setOpen(true);
210
- },
211
- children: renderSlot("settings.trigger", { wide })
235
+ (0, react_jsx_runtime.jsxs)("div", {
236
+ className: clsx(SettingsRoot_module_css_default.triggerRow, !wide && SettingsRoot_module_css_default.railRow),
237
+ children: [(0, react_jsx_runtime.jsx)("button", {
238
+ ref: triggerButton,
239
+ type: "button",
240
+ className: clsx(SettingsRoot_module_css_default.trigger, !wide && SettingsRoot_module_css_default.rail),
241
+ "aria-haspopup": "dialog",
242
+ "aria-expanded": open,
243
+ onClick: () => {
244
+ setOpen(true);
245
+ },
246
+ children: renderSlot("settings.trigger", { wide })
247
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.ConnectionIndicator, {
248
+ state: wide ? connectionIndicator : void 0,
249
+ disconnectedLabel: t("connection.error"),
250
+ reconnectLabel: t("connection.retry"),
251
+ connectingLabel: t("connection.connecting"),
252
+ recoveredLabel: t("connection.connected"),
253
+ reconnectActionLabel: t("connection.reconnect"),
254
+ restartActionLabel: t("connection.restart"),
255
+ onReconnect: reconnect
256
+ })]
212
257
  }),
213
258
  open && (0, react_jsx_runtime.jsx)(SettingsPanel, {
214
259
  rows,
@@ -347,26 +392,24 @@ window.__ModuleLoader__.load({
347
392
  //#endregion
348
393
  //#region lib/types/client/settings-document-store.js
349
394
  /** State owner for the optional local settings-document action. */
350
- function messageOf(error) {
351
- return error instanceof Error ? error.message : String(error);
352
- }
353
395
  /** Derives local-document availability from the shared mirror and invokes the pathless Host-owned open operation. */
354
396
  var SettingsDocumentStore = class {
355
- api;
397
+ ctx;
356
398
  describeFace;
357
399
  /** uSES-safe state source shared by the registered header action. */
358
- store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
400
+ store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
359
401
  status: "idle",
360
402
  opening: false,
361
403
  error: null
362
404
  });
363
405
  following;
364
406
  /**
365
- * @param api - loopback settings wire face that opens the provider document.
407
+ * @param ctx - the plugin's context, whose loopback `remote.settings`
408
+ * namespace opens the provider document.
366
409
  * @param describeFace - the shared mirror's describe face (`hasDocument` source).
367
410
  */
368
- constructor(api, describeFace) {
369
- this.api = api;
411
+ constructor(ctx, describeFace) {
412
+ this.ctx = ctx;
370
413
  this.describeFace = describeFace;
371
414
  }
372
415
  /**
@@ -397,12 +440,13 @@ window.__ModuleLoader__.load({
397
440
  state.error = null;
398
441
  });
399
442
  try {
400
- const response = await this.api.settings.openDocument({});
401
- if (!response.result.ok) throw new Error(response.result.error.message);
402
- } catch (error) {
403
- this.store.update((state) => {
404
- state.error = messageOf(error);
405
- });
443
+ const result = await this.ctx.remote.settings.openSettingsDocument();
444
+ if (!result.ok) {
445
+ const { message } = result.error;
446
+ this.store.update((state) => {
447
+ state.error = message;
448
+ });
449
+ }
406
450
  } finally {
407
451
  this.store.update((state) => {
408
452
  state.opening = false;
@@ -440,7 +484,13 @@ window.__ModuleLoader__.load({
440
484
  "close": "关闭",
441
485
  "openDocument": "打开配置文件",
442
486
  "openDocument.error": "无法打开配置文件",
443
- "general.nav": "通用设置"
487
+ "general.nav": "通用设置",
488
+ "connection.error": "连接异常",
489
+ "connection.retry": "立即重连",
490
+ "connection.connecting": "连接中",
491
+ "connection.connected": "连接成功",
492
+ "connection.reconnect": "连接异常,点击立即重连",
493
+ "connection.restart": "连接中,点击立即重连"
444
494
  };
445
495
  /** English dictionary, checked complete against the zh key set. */
446
496
  const en = {
@@ -449,7 +499,13 @@ window.__ModuleLoader__.load({
449
499
  "close": "Close",
450
500
  "openDocument": "Open configuration file",
451
501
  "openDocument.error": "Could not open configuration file",
452
- "general.nav": "General"
502
+ "general.nav": "General",
503
+ "connection.error": "Disconnected",
504
+ "connection.retry": "Reconnect now",
505
+ "connection.connecting": "Connecting",
506
+ "connection.connected": "Connected",
507
+ "connection.reconnect": "Disconnected, reconnect now",
508
+ "connection.restart": "Connecting, restart now"
453
509
  };
454
510
  //#endregion
455
511
  //#region lib/types/client/index.js
@@ -464,6 +520,8 @@ window.__ModuleLoader__.load({
464
520
  "slots",
465
521
  "locale",
466
522
  "connection",
523
+ "remote",
524
+ "remote.settings",
467
525
  "settingsScope"
468
526
  ];
469
527
  /**
@@ -476,9 +534,9 @@ window.__ModuleLoader__.load({
476
534
  zh,
477
535
  en
478
536
  }), "ui-settings-general: dictionaries");
479
- const t = ctx.locale.bind(NS);
480
537
  const connection = ctx.get("connection");
481
- const documentController = connection.isLoopback ? new SettingsDocumentStore(connection.api, ctx.settingsScope.describe()) : void 0;
538
+ const t = ctx.locale.bind(NS);
539
+ const documentController = ctx.remote.$host.isLoopback ? new SettingsDocumentStore(ctx, ctx.settingsScope.describe()) : void 0;
482
540
  const documentInjected = documentController === void 0 ? void 0 : () => ({
483
541
  controller: documentController,
484
542
  hooks: { snapshot: documentController.store }
@@ -491,50 +549,57 @@ window.__ModuleLoader__.load({
491
549
  let rows = [];
492
550
  let onboardingVersion = -1;
493
551
  let onboardingSteps = [];
494
- const shellInjected = () => ({ hooks: {
495
- sections: {
496
- getSnapshot: () => {
497
- const version = ctx.slots.getVersion("settings.section");
498
- const revision = ctx.locale.getSnapshot().revision;
499
- if (version !== rowsVersion || revision !== rowsRevision) {
500
- rowsVersion = version;
501
- rowsRevision = revision;
502
- rows = ctx.slots.entries("settings.section").map((e) => ({
503
- /* v8 ignore next -- list-slot registration requires id (SlotCore rejects an entry without one) */
504
- id: e.options.id ?? "",
505
- order: e.options.order ?? 0,
506
- label: (0, _deepseek_ai_dsh_client_ui_slots.resolveSlotLabel)(e.options.label) ?? ""
507
- })).sort((a, b) => a.order - b.order);
508
- }
509
- return rows;
510
- },
511
- subscribe: (listener) => {
512
- const offLedger = ctx.slots.subscribe("settings.section", listener);
513
- const offLocale = ctx.locale.subscribe(listener);
514
- return () => {
515
- offLedger();
516
- offLocale();
517
- };
518
- }
552
+ const shellInjected = () => ({
553
+ reconnect: () => {
554
+ connection.reconnect();
519
555
  },
520
- onboardingSteps: {
521
- getSnapshot: () => {
522
- const version = ctx.slots.getVersion("settings.onboarding");
523
- if (version !== onboardingVersion) {
524
- onboardingVersion = version;
525
- onboardingSteps = ctx.slots.entries("settings.onboarding").map((e) => ({
526
- /* v8 ignore next -- list-slot registration requires id */
527
- id: e.options.id ?? "",
528
- order: e.options.order ?? 0
529
- })).sort((a, b) => a.order - b.order);
556
+ hooks: {
557
+ connectionState: connection.state,
558
+ sections: {
559
+ getSnapshot: () => {
560
+ const version = ctx.slots.getVersion("settings.section");
561
+ const revision = ctx.locale.getSnapshot().revision;
562
+ if (version !== rowsVersion || revision !== rowsRevision) {
563
+ rowsVersion = version;
564
+ rowsRevision = revision;
565
+ rows = ctx.slots.entries("settings.section").map((e) => ({
566
+ /* v8 ignore next -- list-slot registration requires id (SlotCore rejects an entry without one) */
567
+ id: e.options.id ?? "",
568
+ order: e.options.order ?? 0,
569
+ label: (0, _deepseek_ai_dsh_client_ui_slots.resolveSlotLabel)(e.options.label) ?? ""
570
+ })).sort((a, b) => a.order - b.order);
571
+ }
572
+ return rows;
573
+ },
574
+ subscribe: (listener) => {
575
+ const offLedger = ctx.slots.subscribe("settings.section", listener);
576
+ const offLocale = ctx.locale.subscribe(listener);
577
+ return () => {
578
+ offLedger();
579
+ offLocale();
580
+ };
530
581
  }
531
- return onboardingSteps;
532
582
  },
533
- subscribe: (listener) => ctx.slots.subscribe("settings.onboarding", listener)
583
+ onboardingSteps: {
584
+ getSnapshot: () => {
585
+ const version = ctx.slots.getVersion("settings.onboarding");
586
+ if (version !== onboardingVersion) {
587
+ onboardingVersion = version;
588
+ onboardingSteps = ctx.slots.entries("settings.onboarding").map((e) => ({
589
+ /* v8 ignore next -- list-slot registration requires id */
590
+ id: e.options.id ?? "",
591
+ order: e.options.order ?? 0
592
+ })).sort((a, b) => a.order - b.order);
593
+ }
594
+ return onboardingSteps;
595
+ },
596
+ subscribe: (listener) => ctx.slots.subscribe("settings.onboarding", listener)
597
+ }
534
598
  }
535
- } });
599
+ });
536
600
  ctx.slots.inject("sidebar.settings", () => ctx.slots.register({
537
601
  name: "sidebar.settings",
602
+ locale: NS,
538
603
  children: {
539
604
  "settings.trigger": {
540
605
  kind: "single",