@sparkelf/dsh-plugin-backup 0.2.1-alpha.3 → 0.2.1-alpha.4

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.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/plus/backup/README.md
5
- README.md: 9779790a882ee3c85bda21914a77bf9048ec76b0
6
- README.zh.md: 9570b2eee62259f48ec41e9f0229b7116547dbbf
5
+ README.md: 543f8bc850fc01e68d03735450a99372e7c68455
6
+ README.zh.md: 090bd8e8cfec3776cdda407446a8baf35a05f39e
package/README.md CHANGED
@@ -23,7 +23,7 @@ This complete Host and Client plugin exports and restores three explicit user-da
23
23
  <a id="use-this-package"></a>
24
24
  ## Use this package
25
25
 
26
- Mount the Host entry after `connection`, `webServer`, `settings`, and `workspaceRegistry`, and mount the Client entry after locale and Settings. The file-backed Settings provider supplies `settings.documentPath`; `maxUploadBytes` defaults to 2147483648 bytes.
26
+ Mount the Host entry after `connection`, `webServer`, `settings`, and `workspaceRegistry`, and mount the Client entry after locale and Settings. The file-backed Settings provider supplies `settings.documentPath`; the archive covers the Harness home, and `maxUploadBytes` defaults to 2147483648 bytes.
27
27
 
28
28
  The Settings section uses a three-way segmented control. **Everything** is the union of configuration and sessions; it does not archive generated profiles, releases, logs, Supervisor files, cached packages, or other runtime output. **Configuration** restores only configuration files and leaves Session/Workspace storage open. **Sessions** restores `sessions`, `attachments`, and `storages` together inside the Workspace storage-restore transaction. The archive manifest records the scope and active Settings filename; configuration-bearing archives require the same Settings filename at import.
29
29
 
package/README.zh.md CHANGED
@@ -23,7 +23,7 @@ kind: "package-reference"
23
23
  <a id="use-this-package"></a>
24
24
  ## 使用此软件包
25
25
 
26
- Host entry需mount在`connection`、`webServer`、`settings`及`workspaceRegistry`之后,Client entry需mount在locale及Settings之后。file-backed Settings provider提供`settings.documentPath`;`maxUploadBytes`默认为2147483648 bytes。
26
+ Host entry需mount在`connection`、`webServer`、`settings`及`workspaceRegistry`之后,Client entry需mount在locale及Settings之后。file-backed Settings provider提供`settings.documentPath`;归档覆盖Harness home,`maxUploadBytes`默认为2147483648 bytes。
27
27
 
28
28
  Settings section使用三段segmented control。**全部**是配置与会话的并集;它不归档generated profiles、releases、logs、Supervisor files、cached packages或其他runtime output。**配置**只恢复配置文件,不关闭Session/Workspace storage。**会话**把`sessions`、`attachments`及`storages`一起放进Workspace storage-restore transaction恢复。Archive manifest记录scope与active Settings filename;含配置的archive在import时要求相同Settings filename。
29
29
 
package/lib/client.js CHANGED
@@ -4,8 +4,8 @@ window.__ModuleLoader__.load({
4
4
  var module = { exports: {} };
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
- let react_jsx_runtime = require("react/jsx-runtime");
8
7
  let react = require("react");
8
+ let react_jsx_runtime = require("react/jsx-runtime");
9
9
  let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
10
10
  //#region \0dsh-css:/root/projects/deepseek-harness-plus/packages/plus/backup/src/client/BackupSection.module.css.mjs
11
11
  const css = ".pZQljq_section{flex-direction:column;gap:16px;display:flex}.pZQljq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:600}.pZQljq_desc{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px}.pZQljq_scopeGroup{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:6px;align-self:flex-start;padding:2px;display:inline-flex}.pZQljq_scopeButton{min-width:72px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:4px;padding:0 10px;font-size:13px}.pZQljq_scopeButton:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.pZQljq_scopeButton[aria-checked=true]{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);box-shadow:0 1px 2px #0000001f}.pZQljq_scopeButton:focus-visible{outline:1px solid var(--dsw-alias-state-business-primary);outline-offset:1px}.pZQljq_scopeButton:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.pZQljq_actions{flex-wrap:wrap;align-items:center;gap:12px;display:flex}.pZQljq_button{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:8px;padding:8px 14px;font-size:13px}.pZQljq_button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.pZQljq_button:disabled{opacity:.6;cursor:default}.pZQljq_fileInput{display:none}.pZQljq_progress{flex-direction:column;gap:8px;width:min(100%,480px);display:flex}.pZQljq_progressLabel,.pZQljq_progressDetail{margin:0;font-size:13px}.pZQljq_progressLabel{color:var(--dsw-alias-label-primary);font-weight:500}.pZQljq_progressDetail{color:var(--dsw-alias-label-secondary)}.pZQljq_progressTrack{width:100%;height:8px;accent-color:var(--dsw-alias-state-business-primary);border:0}.pZQljq_progressTrack::-webkit-progress-bar{background:var(--dsw-alias-border-l2);border-radius:4px}.pZQljq_progressTrack::-webkit-progress-value{background:var(--dsw-alias-state-business-primary);border-radius:4px}.pZQljq_progressTrack::-moz-progress-bar{background:var(--dsw-alias-state-business-primary);border-radius:4px}.pZQljq_status{color:var(--dsw-alias-state-success-primary);margin:0;font-size:13px}.pZQljq_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:13px}.pZQljq_warning{color:var(--dsw-alias-state-warn-primary);margin:0;font-size:12px}";
@@ -35,7 +35,7 @@ window.__ModuleLoader__.load({
35
35
  "warning": "pZQljq_warning"
36
36
  };
37
37
  //#endregion
38
- //#region lib/types/client/BackupSection.js
38
+ //#region src/client/BackupSection.tsx
39
39
  /**
40
40
  * Backup settings section: exact Host routes stream archive bytes and progress;
41
41
  * the slot store survives settings-driven component remounts.
@@ -176,18 +176,18 @@ window.__ModuleLoader__.load({
176
176
  };
177
177
  const percent = operation === null ? void 0 : progressPercent(operation.progress);
178
178
  const progressText = operation === null ? "" : t(progressTextKey(operation.progress)) + (percent === void 0 ? "" : " " + String(percent) + "%");
179
- return (0, react_jsx_runtime.jsxs)("section", {
179
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
180
180
  className: BackupSection_module_css_default.section,
181
181
  children: [
182
- (0, react_jsx_runtime.jsx)("h2", {
182
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
183
183
  className: BackupSection_module_css_default.title,
184
184
  children: t("title")
185
185
  }),
186
- (0, react_jsx_runtime.jsx)("p", {
186
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
187
187
  className: BackupSection_module_css_default.desc,
188
188
  children: t("desc")
189
189
  }),
190
- (0, react_jsx_runtime.jsx)("div", {
190
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
191
191
  className: BackupSection_module_css_default.scopeGroup,
192
192
  role: "radiogroup",
193
193
  "aria-label": t("scopeLabel"),
@@ -195,7 +195,7 @@ window.__ModuleLoader__.load({
195
195
  "all",
196
196
  "configuration",
197
197
  "sessions"
198
- ].map((value) => (0, react_jsx_runtime.jsx)("button", {
198
+ ].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
199
199
  type: "button",
200
200
  role: "radio",
201
201
  "aria-checked": scope === value,
@@ -207,10 +207,10 @@ window.__ModuleLoader__.load({
207
207
  children: t(value === "all" ? "scopeAll" : value === "configuration" ? "scopeConfiguration" : "scopeSessions")
208
208
  }, value))
209
209
  }),
210
- (0, react_jsx_runtime.jsxs)("div", {
210
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211
211
  className: BackupSection_module_css_default.actions,
212
212
  children: [
213
- (0, react_jsx_runtime.jsx)("button", {
213
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
214
214
  type: "button",
215
215
  className: BackupSection_module_css_default.button,
216
216
  disabled: operation !== null || reloadRequired,
@@ -219,7 +219,7 @@ window.__ModuleLoader__.load({
219
219
  },
220
220
  children: operation?.kind === "export" ? t("busyExport") : t("exportButton")
221
221
  }),
222
- (0, react_jsx_runtime.jsx)("button", {
222
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
223
223
  type: "button",
224
224
  className: BackupSection_module_css_default.button,
225
225
  disabled: operation !== null || reloadRequired,
@@ -228,7 +228,7 @@ window.__ModuleLoader__.load({
228
228
  },
229
229
  children: operation?.kind === "import" ? t("busyImport") : t("importButton")
230
230
  }),
231
- operation !== null && canCancel(operation.progress) ? (0, react_jsx_runtime.jsx)("button", {
231
+ operation !== null && canCancel(operation.progress) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
232
232
  type: "button",
233
233
  className: BackupSection_module_css_default.button,
234
234
  disabled: cancelling,
@@ -238,7 +238,7 @@ window.__ModuleLoader__.load({
238
238
  },
239
239
  children: t(cancelling ? "cancellingButton" : "cancelButton")
240
240
  }) : null,
241
- (0, react_jsx_runtime.jsx)("input", {
241
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
242
242
  ref: fileRef,
243
243
  type: "file",
244
244
  accept: ".zip,application/zip",
@@ -247,38 +247,38 @@ window.__ModuleLoader__.load({
247
247
  })
248
248
  ]
249
249
  }),
250
- operation !== null ? (0, react_jsx_runtime.jsxs)("div", {
250
+ operation !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
251
251
  className: BackupSection_module_css_default.progress,
252
252
  role: "status",
253
253
  "aria-live": "polite",
254
254
  children: [
255
- (0, react_jsx_runtime.jsx)("p", {
255
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
256
256
  className: BackupSection_module_css_default.progressLabel,
257
257
  children: progressText
258
258
  }),
259
- percent === void 0 ? (0, react_jsx_runtime.jsx)("progress", {
259
+ percent === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("progress", {
260
260
  className: BackupSection_module_css_default.progressTrack,
261
261
  "aria-label": t(operation.kind === "export" ? "exportProgressLabel" : "importProgressLabel"),
262
262
  "aria-valuetext": progressText
263
- }) : (0, react_jsx_runtime.jsx)("progress", {
263
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("progress", {
264
264
  className: BackupSection_module_css_default.progressTrack,
265
265
  max: 100,
266
266
  value: percent,
267
267
  "aria-label": t(operation.kind === "export" ? "exportProgressLabel" : "importProgressLabel"),
268
268
  "aria-valuetext": progressText
269
269
  }),
270
- (0, react_jsx_runtime.jsx)("p", {
270
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
271
271
  className: BackupSection_module_css_default.progressDetail,
272
272
  children: t("progressDetail")
273
273
  })
274
274
  ]
275
275
  }) : null,
276
- result !== null ? (0, react_jsx_runtime.jsx)("p", {
276
+ result !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
277
277
  className: BackupSection_module_css_default.status,
278
278
  role: "status",
279
279
  children: t(resultTextKey(result))
280
280
  }) : null,
281
- reloadRequired ? (0, react_jsx_runtime.jsx)("button", {
281
+ reloadRequired ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
282
282
  type: "button",
283
283
  className: BackupSection_module_css_default.button,
284
284
  onClick: () => {
@@ -286,12 +286,12 @@ window.__ModuleLoader__.load({
286
286
  },
287
287
  children: t("reloadButton")
288
288
  }) : null,
289
- error !== null ? (0, react_jsx_runtime.jsx)("p", {
289
+ error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
290
290
  className: BackupSection_module_css_default.error,
291
291
  role: "alert",
292
292
  children: t(error)
293
293
  }) : null,
294
- (0, react_jsx_runtime.jsx)("p", {
294
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
295
295
  className: BackupSection_module_css_default.warning,
296
296
  children: t("warning")
297
297
  })
@@ -299,7 +299,7 @@ window.__ModuleLoader__.load({
299
299
  });
300
300
  }
301
301
  //#endregion
302
- //#region lib/types/client/store.js
302
+ //#region src/client/store.ts
303
303
  /**
304
304
  * Declare the Backup section operation and result state.
305
305
  * @returns the root-scoped store handle.
@@ -351,7 +351,7 @@ window.__ModuleLoader__.load({
351
351
  });
352
352
  }
353
353
  //#endregion
354
- //#region lib/types/client/locales.js
354
+ //#region src/client/locales.ts
355
355
  /** Settings Backup section dictionaries (zh product copy, en twin). */
356
356
  const zh = {
357
357
  nav: "备份",
@@ -427,12 +427,7 @@ window.__ModuleLoader__.load({
427
427
  warning: "The backup archive contains sensitive data such as API keys; store it carefully."
428
428
  };
429
429
  //#endregion
430
- //#region lib/types/client/index.js
431
- /**
432
- * Settings Backup section plugin, browser half. Archive bytes use exact Host
433
- * routes; preparation and restore state arrive as validated NDJSON progress
434
- * lines, outside the unary RPC carrier.
435
- */
430
+ //#region src/client/index.ts
436
431
  const NS = "settingsBackup";
437
432
  const inject = ["slots", "locale"];
438
433
  /** Resolve a Host logical path beneath the runtime-injected document base. */
package/lib/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { basename, dirname, join } from "node:path";
2
2
  import Schema from "@deepseek-ai/schemastery";
3
+ import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
3
4
  import { randomUUID } from "node:crypto";
4
5
  import { once } from "node:events";
5
6
  import { createReadStream, createWriteStream } from "node:fs";
@@ -783,7 +784,14 @@ const DEFAULT_MAX_UPLOAD_BYTES = 2 * 1024 * 1024 * 1024;
783
784
  /** Validate Backup Host resource policy. */
784
785
  const Config = Schema.object({ maxUploadBytes: Schema.number().step(1).min(1).default(DEFAULT_MAX_UPLOAD_BYTES) });
785
786
  /**
786
- * Register authenticated archive routes against a file-backed DSH home.
787
+ * Register authenticated archive routes against the Harness home.
788
+ *
789
+ * The archived user data lives under the Harness home, not beside the settings document: Session
790
+ * logs, attachments, Workspace storage, credentials, and identity are all written there. Only the
791
+ * profile's patch file sits beside the document, so deriving the root from the document archived
792
+ * that one file and silently dropped every other planned entry — a Sessions export produced an
793
+ * archive holding nothing but its manifest.
794
+ *
787
795
  * @param ctx - Host services plus the temporary patched Workspace restore operation.
788
796
  * @param config - Upload resource policy resolved by Cordis.
789
797
  */
@@ -793,7 +801,7 @@ function apply(ctx, config = {}) {
793
801
  registerBackupRoutes(ctx, {
794
802
  maxUploadBytes: config.maxUploadBytes ?? DEFAULT_MAX_UPLOAD_BYTES,
795
803
  settingsFile: basename(documentPath)
796
- }, dirname(documentPath));
804
+ }, resolveDshHome());
797
805
  }
798
806
  //#endregion
799
807
  export { Config, apply, inject, name };
@@ -11,7 +11,14 @@ export interface Config {
11
11
  /** Validate Backup Host resource policy. */
12
12
  export declare const Config: Schema<Config>;
13
13
  /**
14
- * Register authenticated archive routes against a file-backed DSH home.
14
+ * Register authenticated archive routes against the Harness home.
15
+ *
16
+ * The archived user data lives under the Harness home, not beside the settings document: Session
17
+ * logs, attachments, Workspace storage, credentials, and identity are all written there. Only the
18
+ * profile's patch file sits beside the document, so deriving the root from the document archived
19
+ * that one file and silently dropped every other planned entry — a Sessions export produced an
20
+ * archive holding nothing but its manifest.
21
+ *
15
22
  * @param ctx - Host services plus the temporary patched Workspace restore operation.
16
23
  * @param config - Upload resource policy resolved by Cordis.
17
24
  */
package/package.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "@deepseek-ai/dsh-client-ui-renderer": "^0.1.6-alpha.1",
14
14
  "@deepseek-ai/dsh-client-ui-settings": "^0.1.6-alpha.1",
15
15
  "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.1",
16
+ "@deepseek-ai/dsh-home-paths": "^0.1.6-alpha.1",
16
17
  "@deepseek-ai/dsh-host-webserver": "^0.1.6-alpha.1",
17
18
  "@deepseek-ai/dsh-settings": "^0.1.6-alpha.1",
18
19
  "@deepseek-ai/dsh-workspace": "^0.1.6-alpha.1",
@@ -55,6 +56,7 @@
55
56
  "@deepseek-ai/dsh-client-ui-renderer": "^0.1.6-alpha.1",
56
57
  "@deepseek-ai/dsh-client-ui-settings": "^0.1.6-alpha.1",
57
58
  "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.1",
59
+ "@deepseek-ai/dsh-home-paths": "^0.1.6-alpha.1",
58
60
  "@deepseek-ai/dsh-host-webserver": "^0.1.6-alpha.1",
59
61
  "@deepseek-ai/dsh-settings": "^0.1.6-alpha.1",
60
62
  "@deepseek-ai/dsh-workspace": "^0.1.6-alpha.1"
@@ -73,5 +75,5 @@
73
75
  },
74
76
  "type": "module",
75
77
  "types": "lib/types/index.d.ts",
76
- "version": "0.2.1-alpha.3"
78
+ "version": "0.2.1-alpha.4"
77
79
  }