dsh-session-rollover 0.0.0-stage → 1.2.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 (69) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +201 -0
  3. package/LICENSE.upstream +21 -0
  4. package/NOTICE +9 -0
  5. package/README.md +157 -2
  6. package/assets/icon.png +0 -0
  7. package/assets/icon.svg +7 -0
  8. package/client.js +656 -0
  9. package/compatibility/policy.json +21 -0
  10. package/compatibility/runtime-0.2.2-rc.1.json +32 -0
  11. package/cordis.patch.yml +9 -0
  12. package/docs/COMPATIBILITY.md +70 -0
  13. package/docs/DETAIL.md +44 -0
  14. package/docs/DETAIL.zh-CN.md +49 -0
  15. package/docs/DEVELOPMENT.md +104 -0
  16. package/docs/PUBLISHING.md +80 -0
  17. package/docs/architecture.md +71 -0
  18. package/docs/live-host-validation.json +37 -0
  19. package/docs/marketplace-validation.md +22 -0
  20. package/docs/prototype-validation.json +10 -0
  21. package/docs/r3-demo.html +981 -0
  22. package/docs/r3-validation.md +59 -0
  23. package/docs/screenshots/help-dark.png +0 -0
  24. package/docs/screenshots/help-light.png +0 -0
  25. package/docs/screenshots/host-archived.png +0 -0
  26. package/docs/screenshots/host-dark.png +0 -0
  27. package/docs/screenshots/host-rollover.png +0 -0
  28. package/docs/screenshots/prototype-fixed.png +0 -0
  29. package/index.js +2 -0
  30. package/locale/en.json +7 -0
  31. package/locale/zh.json +7 -0
  32. package/marketplace/Oak-liuhj__dsh-session-rollover.yml +7 -0
  33. package/marketplace/SUBMISSION.md +37 -0
  34. package/package.json +103 -4
  35. package/screenshots.json +6 -0
  36. package/scripts/build-client.mjs +12 -0
  37. package/scripts/check-dsh-compatibility.mjs +44 -0
  38. package/scripts/check-package.mjs +51 -0
  39. package/scripts/check-release.mjs +76 -0
  40. package/scripts/dsh-contracts.mjs +69 -0
  41. package/src/application/handoff-message.mjs +53 -0
  42. package/src/application/rollover.mjs +236 -0
  43. package/src/assembly.mjs +4 -0
  44. package/src/client/rollover-ui.js +311 -0
  45. package/src/client/toast-client.js +342 -0
  46. package/src/cluster.mjs +3 -0
  47. package/src/domain/cluster-index.mjs +65 -0
  48. package/src/domain/handoff.mjs +67 -0
  49. package/src/domain/inflight.mjs +25 -0
  50. package/src/domain/mode.mjs +34 -0
  51. package/src/domain/naming.mjs +78 -0
  52. package/src/domain/summary.mjs +68 -0
  53. package/src/domain/todos.mjs +23 -0
  54. package/src/domain/turns.mjs +43 -0
  55. package/src/handoff.mjs +2 -0
  56. package/src/inflight.mjs +2 -0
  57. package/src/mode.mjs +2 -0
  58. package/src/naming.mjs +2 -0
  59. package/src/notices.mjs +2 -0
  60. package/src/server/compatibility.mjs +84 -0
  61. package/src/server/host-adapter.mjs +146 -0
  62. package/src/server/notice-route.mjs +104 -0
  63. package/src/server/plugin.mjs +447 -0
  64. package/src/storage/index-store.mjs +48 -0
  65. package/src/storage/notices.mjs +117 -0
  66. package/src/storage/rollover-state.mjs +75 -0
  67. package/src/summary.mjs +2 -0
  68. package/src/todos.mjs +2 -0
  69. package/src/turns.mjs +2 -0
@@ -0,0 +1,75 @@
1
+ // 分卷旁路状态:待清理清单、交接快照、只读标记;文件名与旧版一致。
2
+ import {mkdirSync, readFileSync, renameSync, writeFileSync} from 'node:fs';
3
+ import {dirname, join} from 'node:path';
4
+
5
+ export const PENDING_FILE = 'pending-cleanup.json';
6
+ export const READONLY_FILE = 'readonly-by-rollover.json'; // 旧版聚合标记:只读兼容
7
+ /** 需求 B9:开关状态存 <dataDir>/readonly-<sessionId>.json(与簇索引同目录同优先级,不写会话元数据)。 */
8
+ export const readonlyFileOf = (dir, sessionId) => join(dir, `readonly-${sessionId}.json`);
9
+
10
+ function readJson(path, fallback) {
11
+ try {
12
+ return JSON.parse(readFileSync(path, 'utf8'));
13
+ } catch {
14
+ return fallback;
15
+ }
16
+ }
17
+
18
+ function writeJsonAtomic(path, value) {
19
+ mkdirSync(dirname(path), {recursive: true});
20
+ const tmp = path + '.tmp';
21
+ writeFileSync(tmp, JSON.stringify(value, null, 2));
22
+ renameSync(tmp, path); // 与簇索引同一原子手法:临时文件 + rename
23
+ }
24
+
25
+ /** 插件旁路状态:待清理卷清单、交接快照、旧卷只读标记;沿用既有文件名以兼容升级。 */
26
+ export function createRolloverState(dir) {
27
+ const pendingPath = join(dir, PENDING_FILE);
28
+ const readonlyPath = join(dir, READONLY_FILE);
29
+ return {
30
+ dir,
31
+ pendingPath,
32
+ readonlyPath,
33
+ readonlyRecord(sessionId) { return readJson(readonlyFileOf(dir, sessionId), null); },
34
+ preflight() {
35
+ // 在创建宿主会话之前发现不可写目录,避免留下空会话。
36
+ writeJsonAtomic(join(dir, 'storage-health.json'), {checkedAt: new Date().toISOString()});
37
+ },
38
+ setReadonly(sessionId, readonly, payload = {}) {
39
+ const previous = readJson(readonlyFileOf(dir, sessionId), {});
40
+ const rec = {...previous, ...payload, readonly: !!readonly};
41
+ writeJsonAtomic(readonlyFileOf(dir, sessionId), rec);
42
+ return rec;
43
+ },
44
+ retryGet(sessionId) { return readJson(join(dir, `retry-${sessionId}.json`), {attempts: 0}); },
45
+ retrySave(sessionId, attempts) { writeJsonAtomic(join(dir, `retry-${sessionId}.json`), {attempts}); },
46
+ pendingList: () => Object.values(readJson(pendingPath, {})),
47
+ pendingAdd(rec) {
48
+ const all = readJson(pendingPath, {});
49
+ all[rec.sessionId] = rec;
50
+ writeJsonAtomic(pendingPath, all);
51
+ return rec;
52
+ },
53
+ pendingRemove(sessionId) {
54
+ const all = readJson(pendingPath, {});
55
+ delete all[sessionId];
56
+ writeJsonAtomic(pendingPath, all);
57
+ },
58
+ handoffGet(sessionId) { return readJson(join(dir, `handoff-${sessionId}.json`), null); },
59
+ handoffSave(sessionId, payload) { writeJsonAtomic(join(dir, `handoff-${sessionId}.json`), payload); },
60
+ markReadonly(sessionId, payload) {
61
+ const rec = {readonly: true, ...payload};
62
+ writeJsonAtomic(readonlyFileOf(dir, sessionId), rec);
63
+ return rec;
64
+ },
65
+ /**
66
+ * 手动开关:把 readonly-<sessionId>.json 里的 readonly 改成 false 即放行(保留历史全景)。
67
+ * 兼容旧版聚合文件 readonly-by-rollover.json。
68
+ */
69
+ isReadonly(sessionId) {
70
+ const per = readJson(readonlyFileOf(dir, sessionId), null);
71
+ if (per) return per.readonly !== false;
72
+ return !!readJson(readonlyPath, {})[sessionId];
73
+ },
74
+ };
75
+ }
@@ -0,0 +1,2 @@
1
+ // 兼容旧导入路径;新代码请直接使用 src/domain/summary.mjs。
2
+ export * from './domain/summary.mjs';
package/src/todos.mjs ADDED
@@ -0,0 +1,2 @@
1
+ // 兼容旧导入路径;新代码请直接使用 src/domain/todos.mjs。
2
+ export * from './domain/todos.mjs';
package/src/turns.mjs ADDED
@@ -0,0 +1,2 @@
1
+ // 兼容旧导入路径;新代码请直接使用 src/domain/turns.mjs。
2
+ export * from './domain/turns.mjs';