@tita-agent/dsh-data-table 0.0.0-stage → 0.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.
- package/LICENSE +21 -0
- package/README.md +172 -2
- package/cordis.patch.yml +7 -0
- package/lib/client.js +16766 -0
- package/lib/contract-envelope.d.ts +91 -0
- package/lib/contract-envelope.js +106 -0
- package/lib/contract-layout.d.ts +130 -0
- package/lib/contract-layout.js +138 -0
- package/lib/contract-refs.d.ts +39 -0
- package/lib/contract-refs.js +9 -0
- package/lib/contract-version.d.ts +311 -0
- package/lib/contract-version.js +270 -0
- package/lib/contract-wire.d.ts +147 -0
- package/lib/contract-wire.js +99 -0
- package/lib/contracts.d.ts +12 -0
- package/lib/contracts.js +12 -0
- package/lib/types/audit.d.ts +42 -0
- package/lib/types/audit.js +39 -0
- package/lib/types/client/ProjectImportMenu.d.ts +30 -0
- package/lib/types/client/ProjectImportMenu.js +70 -0
- package/lib/types/client/SheetPanel.d.ts +33 -0
- package/lib/types/client/SheetPanel.js +1766 -0
- package/lib/types/client/SheetToggle.d.ts +18 -0
- package/lib/types/client/SheetToggle.js +26 -0
- package/lib/types/client/index.d.ts +15 -0
- package/lib/types/client/index.js +110 -0
- package/lib/types/client/persistence/changes.d.ts +15 -0
- package/lib/types/client/persistence/changes.js +51 -0
- package/lib/types/client/persistence/ids.d.ts +34 -0
- package/lib/types/client/persistence/ids.js +48 -0
- package/lib/types/client/persistence/merge.d.ts +35 -0
- package/lib/types/client/persistence/merge.js +362 -0
- package/lib/types/client/store.d.ts +61 -0
- package/lib/types/client/store.js +152 -0
- package/lib/types/client/surface-context.d.ts +27 -0
- package/lib/types/client/surface-context.js +104 -0
- package/lib/types/client/surface-control.d.ts +2 -0
- package/lib/types/client/surface-control.js +12 -0
- package/lib/types/client/transport/workbookApi.d.ts +159 -0
- package/lib/types/client/transport/workbookApi.js +246 -0
- package/lib/types/client/univer/StandaloneWorkbookPage.d.ts +5 -0
- package/lib/types/client/univer/StandaloneWorkbookPage.js +7 -0
- package/lib/types/client/univer/WorkbookCanvas.d.ts +40 -0
- package/lib/types/client/univer/WorkbookCanvas.js +87 -0
- package/lib/types/client/univer/WorkbookView.d.ts +3 -0
- package/lib/types/client/univer/WorkbookView.js +2 -0
- package/lib/types/client/univer/loader.d.ts +18 -0
- package/lib/types/client/univer/loader.js +81 -0
- package/lib/types/client/univer/standalone-entry.d.ts +1 -0
- package/lib/types/client/univer/standalone-entry.js +19 -0
- package/lib/types/client/versions/VersionChrome.d.ts +33 -0
- package/lib/types/client/versions/VersionChrome.js +21 -0
- package/lib/types/client/versions/inspect.d.ts +70 -0
- package/lib/types/client/versions/inspect.js +88 -0
- package/lib/types/client/versions/preview-decoration.d.ts +11 -0
- package/lib/types/client/versions/preview-decoration.js +54 -0
- package/lib/types/client/versions/records.d.ts +19 -0
- package/lib/types/client/versions/records.js +70 -0
- package/lib/types/client/workspace-host.d.ts +61 -0
- package/lib/types/client/workspace-host.js +124 -0
- package/lib/types/collaboration-hub.d.ts +31 -0
- package/lib/types/collaboration-hub.js +69 -0
- package/lib/types/contract/ids.d.ts +24 -0
- package/lib/types/contract/ids.js +46 -0
- package/lib/types/contract/mutations.d.ts +25 -0
- package/lib/types/contract/mutations.js +782 -0
- package/lib/types/contract/operations.d.ts +54 -0
- package/lib/types/contract/operations.js +203 -0
- package/lib/types/contract/snapshots.d.ts +176 -0
- package/lib/types/contract/snapshots.js +351 -0
- package/lib/types/contract/univer-api-catalog.d.ts +29 -0
- package/lib/types/contract/univer-api-catalog.js +264 -0
- package/lib/types/errors.d.ts +8 -0
- package/lib/types/errors.js +12 -0
- package/lib/types/http/assets-routes.d.ts +3 -0
- package/lib/types/http/assets-routes.js +169 -0
- package/lib/types/http/collaboration.d.ts +10 -0
- package/lib/types/http/collaboration.js +154 -0
- package/lib/types/http/history.d.ts +15 -0
- package/lib/types/http/history.js +134 -0
- package/lib/types/http/project-files.d.ts +79 -0
- package/lib/types/http/project-files.js +206 -0
- package/lib/types/http/project-scope.d.ts +50 -0
- package/lib/types/http/project-scope.js +52 -0
- package/lib/types/http/routes.d.ts +98 -0
- package/lib/types/http/routes.js +323 -0
- package/lib/types/http/standalone.d.ts +9 -0
- package/lib/types/http/standalone.js +31 -0
- package/lib/types/http/trunk.d.ts +10 -0
- package/lib/types/http/trunk.js +322 -0
- package/lib/types/http/worktree.d.ts +9 -0
- package/lib/types/http/worktree.js +145 -0
- package/lib/types/index.d.ts +18 -0
- package/lib/types/index.js +156 -0
- package/lib/types/invariant.d.ts +15 -0
- package/lib/types/invariant.js +15 -0
- package/lib/types/request-params.d.ts +21 -0
- package/lib/types/request-params.js +76 -0
- package/lib/types/store/paths.d.ts +68 -0
- package/lib/types/store/paths.js +148 -0
- package/lib/types/store/project.d.ts +88 -0
- package/lib/types/store/project.js +120 -0
- package/lib/types/store/read.d.ts +110 -0
- package/lib/types/store/read.js +404 -0
- package/lib/types/store/retention.d.ts +27 -0
- package/lib/types/store/retention.js +111 -0
- package/lib/types/store/write.d.ts +22 -0
- package/lib/types/store/write.js +210 -0
- package/lib/types/tools/arguments.d.ts +40 -0
- package/lib/types/tools/arguments.js +130 -0
- package/lib/types/tools/cells.d.ts +50 -0
- package/lib/types/tools/cells.js +298 -0
- package/lib/types/tools/index.d.ts +2 -0
- package/lib/types/tools/index.js +250 -0
- package/lib/types/tools/render.d.ts +47 -0
- package/lib/types/tools/render.js +290 -0
- package/lib/types/tools/univer-api.d.ts +18 -0
- package/lib/types/tools/univer-api.js +198 -0
- package/lib/types/tools/workbook-catalog.d.ts +3 -0
- package/lib/types/tools/workbook-catalog.js +83 -0
- package/lib/types/tools/workbook-edit.d.ts +192 -0
- package/lib/types/tools/workbook-edit.js +912 -0
- package/lib/types/tools/workbook-find.d.ts +11 -0
- package/lib/types/tools/workbook-find.js +89 -0
- package/lib/types/tools/workbook-history.d.ts +2 -0
- package/lib/types/tools/workbook-history.js +59 -0
- package/lib/types/tools/workbook-read.d.ts +21 -0
- package/lib/types/tools/workbook-read.js +204 -0
- package/lib/types/types.d.ts +377 -0
- package/lib/types/types.js +34 -0
- package/lib/types/univer/apply-operation.d.ts +14 -0
- package/lib/types/univer/apply-operation.js +398 -0
- package/lib/types/univer/chunk.d.ts +68 -0
- package/lib/types/univer/chunk.js +16 -0
- package/lib/types/univer/decoration.d.ts +34 -0
- package/lib/types/univer/decoration.js +88 -0
- package/lib/types/univer/diagnostics.d.ts +31 -0
- package/lib/types/univer/diagnostics.js +141 -0
- package/lib/types/univer/engine.d.ts +33 -0
- package/lib/types/univer/engine.js +338 -0
- package/lib/types/univer/entry.d.ts +8 -0
- package/lib/types/univer/entry.js +11 -0
- package/lib/types/univer/facade.d.ts +107 -0
- package/lib/types/univer/facade.js +1 -0
- package/lib/types/univer/fonts.d.ts +202 -0
- package/lib/types/univer/fonts.js +140 -0
- package/lib/types/univer/plugins/collaboration.d.ts +23 -0
- package/lib/types/univer/plugins/collaboration.js +47 -0
- package/lib/types/univer/plugins/export.d.ts +39 -0
- package/lib/types/univer/plugins/export.js +246 -0
- package/lib/types/univer/plugins/history.d.ts +24 -0
- package/lib/types/univer/plugins/history.js +50 -0
- package/lib/types/univer/plugins/version.d.ts +13 -0
- package/lib/types/univer/plugins/version.js +13 -0
- package/lib/types/version/diff.d.ts +36 -0
- package/lib/types/version/diff.js +156 -0
- package/lib/types/version/grouping.d.ts +7 -0
- package/lib/types/version/grouping.js +94 -0
- package/lib/types/version/records.d.ts +17 -0
- package/lib/types/version/records.js +102 -0
- package/lib/types/version/session.d.ts +36 -0
- package/lib/types/version/session.js +89 -0
- package/lib/types/version/summary.d.ts +24 -0
- package/lib/types/version/summary.js +111 -0
- package/lib/types/workbook-manager.d.ts +191 -0
- package/lib/types/workbook-manager.js +935 -0
- package/lib/types/xlsx-export-worker.d.ts +5 -0
- package/lib/types/xlsx-export-worker.js +24 -0
- package/lib/types/xlsx-export.d.ts +21 -0
- package/lib/types/xlsx-export.js +371 -0
- package/lib/types/xlsx-import-worker.d.ts +1 -0
- package/lib/types/xlsx-import-worker.js +19 -0
- package/lib/univer-client.js +690 -0
- package/lib/workbook-page.js +23826 -0
- package/lib/xlsx-export-worker.js +104 -0
- package/lib/xlsx-import-worker.js +46 -0
- package/package.json +106 -3
- package/src/audit.ts +58 -0
- package/src/client/ProjectImportMenu.tsx +100 -0
- package/src/client/SheetPanel.module.css +1578 -0
- package/src/client/SheetPanel.tsx +1934 -0
- package/src/client/SheetToggle.module.css +73 -0
- package/src/client/SheetToggle.tsx +65 -0
- package/src/client/contract.d.ts +19 -0
- package/src/client/index.ts +131 -0
- package/src/client/persistence/changes.ts +58 -0
- package/src/client/persistence/ids.ts +60 -0
- package/src/client/persistence/merge.ts +392 -0
- package/src/client/store.ts +188 -0
- package/src/client/surface-context.ts +123 -0
- package/src/client/surface-control.ts +13 -0
- package/src/client/transport/workbookApi.ts +355 -0
- package/src/client/univer/SheetView.module.css +110 -0
- package/src/client/univer/StandaloneWorkbookPage.module.css +8 -0
- package/src/client/univer/StandaloneWorkbookPage.tsx +15 -0
- package/src/client/univer/WorkbookCanvas.tsx +128 -0
- package/src/client/univer/WorkbookView.module.css +30 -0
- package/src/client/univer/WorkbookView.tsx +3 -0
- package/src/client/univer/loader.ts +90 -0
- package/src/client/univer/react-dom-client.d.ts +10 -0
- package/src/client/univer/standalone-entry.tsx +19 -0
- package/src/client/univer/standalone.css +12 -0
- package/src/client/univer/univer-locales.d.ts +89 -0
- package/src/client/univer/univer-modules.d.ts +26 -0
- package/src/client/versions/VersionChrome.tsx +114 -0
- package/src/client/versions/inspect.ts +138 -0
- package/src/client/versions/preview-decoration.ts +54 -0
- package/src/client/versions/records.ts +78 -0
- package/src/client/workspace-host.ts +147 -0
- package/src/collaboration-hub.ts +83 -0
- package/src/contract/ids.ts +50 -0
- package/src/contract/mutations.ts +791 -0
- package/src/contract/operations.ts +221 -0
- package/src/contract/snapshots.ts +383 -0
- package/src/contract/univer-api-catalog.ts +289 -0
- package/src/css-modules.d.ts +6 -0
- package/src/errors.ts +25 -0
- package/src/http/assets-routes.ts +177 -0
- package/src/http/collaboration.ts +144 -0
- package/src/http/history.ts +151 -0
- package/src/http/project-files.ts +227 -0
- package/src/http/project-scope.ts +77 -0
- package/src/http/routes.ts +364 -0
- package/src/http/standalone.ts +32 -0
- package/src/http/trunk.ts +322 -0
- package/src/http/worktree.ts +119 -0
- package/src/index.ts +165 -0
- package/src/invariant.ts +17 -0
- package/src/request-params.ts +92 -0
- package/src/store/paths.ts +165 -0
- package/src/store/project.ts +137 -0
- package/src/store/read.ts +454 -0
- package/src/store/retention.ts +106 -0
- package/src/store/write.ts +230 -0
- package/src/tools/arguments.ts +128 -0
- package/src/tools/cells.ts +298 -0
- package/src/tools/index.ts +274 -0
- package/src/tools/render.ts +301 -0
- package/src/tools/univer-api.ts +243 -0
- package/src/tools/workbook-catalog.ts +94 -0
- package/src/tools/workbook-edit.ts +987 -0
- package/src/tools/workbook-find.ts +80 -0
- package/src/tools/workbook-history.ts +63 -0
- package/src/tools/workbook-read.ts +210 -0
- package/src/types.ts +432 -0
- package/src/univer/apply-operation.ts +369 -0
- package/src/univer/chunk.ts +77 -0
- package/src/univer/decoration.ts +111 -0
- package/src/univer/diagnostics.ts +136 -0
- package/src/univer/engine.ts +370 -0
- package/src/univer/entry.ts +14 -0
- package/src/univer/facade.ts +91 -0
- package/src/univer/fonts.ts +148 -0
- package/src/univer/overrides.css +33 -0
- package/src/univer/plugins/collaboration.ts +47 -0
- package/src/univer/plugins/export.ts +236 -0
- package/src/univer/plugins/history.ts +49 -0
- package/src/univer/plugins/version.ts +13 -0
- package/src/version/diff.ts +169 -0
- package/src/version/grouping.ts +96 -0
- package/src/version/records.ts +113 -0
- package/src/version/session.ts +90 -0
- package/src/version/summary.ts +117 -0
- package/src/workbook-manager.ts +1111 -0
- package/src/xlsx-export-worker.ts +34 -0
- package/src/xlsx-export.ts +373 -0
- package/src/xlsx-import-worker.ts +30 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Version as the wire presents it (docs/issue/0022 P2/P3).
|
|
3
|
+
*
|
|
4
|
+
* The history endpoint and the Agent's history tool answer the same question,
|
|
5
|
+
* so they must produce the same record shape — including the content hash that
|
|
6
|
+
* lets a client prove it has the right Version without materializing a snapshot.
|
|
7
|
+
* That is why this is not part of either transport.
|
|
8
|
+
*
|
|
9
|
+
* `node:crypto` is deliberate and is pure computation: the hash is of the
|
|
10
|
+
* Version's *inputs* (its checkpoint plus its ordered Step ids), not of a file.
|
|
11
|
+
*/
|
|
12
|
+
import { createHash } from 'node:crypto';
|
|
13
|
+
/** Follow logical parents from the current head. Versions skipped by a
|
|
14
|
+
* rollback remain in history but are no longer part of the active main line. */
|
|
15
|
+
export function activeHistoryRevisions(currentRevision, operations) {
|
|
16
|
+
const active = new Set();
|
|
17
|
+
let cursor = currentRevision;
|
|
18
|
+
const visited = new Set();
|
|
19
|
+
while (cursor > 0 && !visited.has(cursor)) {
|
|
20
|
+
visited.add(cursor);
|
|
21
|
+
const operation = operations.get(cursor);
|
|
22
|
+
if (operation === undefined)
|
|
23
|
+
break;
|
|
24
|
+
active.add(cursor);
|
|
25
|
+
cursor = operation.parentRevision ?? Math.max(0, cursor - 1);
|
|
26
|
+
}
|
|
27
|
+
return active;
|
|
28
|
+
}
|
|
29
|
+
export function canReplayHistoryRevision(targetRevision, currentRevision, checkpoints, operations) {
|
|
30
|
+
if (targetRevision === currentRevision)
|
|
31
|
+
return true;
|
|
32
|
+
const checkpoint = checkpoints.filter(revision => revision <= targetRevision).at(-1);
|
|
33
|
+
if (checkpoint === undefined)
|
|
34
|
+
return false;
|
|
35
|
+
for (let revision = checkpoint + 1; revision <= targetRevision; revision += 1) {
|
|
36
|
+
const operation = operations.get(revision);
|
|
37
|
+
if (operation === undefined || (operation.type === 'snapshot_replace' && operation.payload.snapshot === undefined))
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Stable content hash for a Version (PRD §3.2): the checkpoint the Version
|
|
44
|
+
* starts from, plus the ordered opIds applied on top of it. It is a pure
|
|
45
|
+
* function of the Version's inputs, so the history list never has to
|
|
46
|
+
* materialise or copy a workbook snapshot into the browser (PRD §11).
|
|
47
|
+
*/
|
|
48
|
+
export function versionContentHash(version, checkpointHash) {
|
|
49
|
+
const chain = version.steps.map(step => step.opId).join(',');
|
|
50
|
+
return createHash('sha256').update(`${checkpointHash(version.revision)}#${version.startRevision}#${chain}`).digest('hex');
|
|
51
|
+
}
|
|
52
|
+
/** Map the Data Sheet history shape onto the shared Version record (PRD §7.1). */
|
|
53
|
+
export function toVersionRecords(versions, workbookId, checkpointHash) {
|
|
54
|
+
return versions.map(version => {
|
|
55
|
+
const status = version.status === 'final'
|
|
56
|
+
? 'committed'
|
|
57
|
+
: version.status === 'temporary'
|
|
58
|
+
? 'open'
|
|
59
|
+
: version.status;
|
|
60
|
+
return {
|
|
61
|
+
versionId: version.versionId,
|
|
62
|
+
artifactKind: 'workbook',
|
|
63
|
+
artifactId: workbookId,
|
|
64
|
+
number: version.number,
|
|
65
|
+
startRevision: version.startRevision,
|
|
66
|
+
endRevision: version.revision,
|
|
67
|
+
// The unified record points at the reinstated Version, like other versioned artifacts
|
|
68
|
+
// record does; `r48` only survives on the legacy history shape.
|
|
69
|
+
...(version.restoredFromRevision === undefined
|
|
70
|
+
? {}
|
|
71
|
+
: { restoredFromVersionId: versions.find(candidate => candidate.revision === version.restoredFromRevision)?.versionId ?? `r${version.restoredFromRevision}` }),
|
|
72
|
+
status,
|
|
73
|
+
kind: version.kind,
|
|
74
|
+
actor: version.actor === 'agent' ? 'agent' : 'user',
|
|
75
|
+
summary: version.summary,
|
|
76
|
+
...(version.intent === undefined ? {} : { intent: version.intent }),
|
|
77
|
+
stepCount: version.stepCount,
|
|
78
|
+
contentHash: versionContentHash(version, checkpointHash),
|
|
79
|
+
createdAt: version.timestamp,
|
|
80
|
+
...(status === 'committed' || status === 'restored' ? { committedAt: version.timestamp } : {}),
|
|
81
|
+
...(version.lineage === undefined ? {} : { lineage: version.lineage }),
|
|
82
|
+
replayable: version.canPreview,
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** Memoized checkpoint hash lookup: hashes each snapshot at most once. */
|
|
87
|
+
export function checkpointHasher(checkpoints) {
|
|
88
|
+
const ascending = checkpoints.slice().sort((left, right) => left.revision - right.revision);
|
|
89
|
+
const cache = new Map();
|
|
90
|
+
const genesis = createHash('sha256').update('genesis').digest('hex');
|
|
91
|
+
return (revision) => {
|
|
92
|
+
const cached = cache.get(revision);
|
|
93
|
+
if (cached !== undefined)
|
|
94
|
+
return cached;
|
|
95
|
+
const base = ascending.filter(checkpoint => checkpoint.revision <= revision).at(-1);
|
|
96
|
+
const hash = base === undefined
|
|
97
|
+
? genesis
|
|
98
|
+
: createHash('sha256').update(JSON.stringify(base.snapshot)).digest('hex');
|
|
99
|
+
cache.set(revision, hash);
|
|
100
|
+
return hash;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The editing session: when a Version opens, what closes it, and the shape of
|
|
3
|
+
* the version fields on the wire (docs/issue/0022 P2).
|
|
4
|
+
*
|
|
5
|
+
* Two boundaries close a session (PRD v3.5 D21) — the idle window and the Step
|
|
6
|
+
* cap — and nothing else does. `settleIdleUserVersions` exists because the write
|
|
7
|
+
* path can only fork a session when the *next* write arrives: an abandoned tab
|
|
8
|
+
* left a Version `open` forever, so settling is evaluated lazily at the moment
|
|
9
|
+
* the user can observe the outcome (reading the version list).
|
|
10
|
+
*/
|
|
11
|
+
import { type VersionKind } from '#contracts';
|
|
12
|
+
import type { WorkbookMeta, WorkbookVersionStatus } from '../types.ts';
|
|
13
|
+
export declare const VERSION_STEP_LIMIT = 20;
|
|
14
|
+
/** Old logs use `temporary`; expose it as the clearer `open` lifecycle state. */
|
|
15
|
+
export declare function normalizeVersionStatus(status: WorkbookVersionStatus | undefined): WorkbookVersionStatus | undefined;
|
|
16
|
+
/** v3 tier on the wire; unknown values are dropped rather than guessed. */
|
|
17
|
+
export declare function normalizeVersionKind(kind: VersionKind | undefined): VersionKind | undefined;
|
|
18
|
+
export declare function isOpenVersionStatus(status: WorkbookVersionStatus | undefined): boolean;
|
|
19
|
+
export declare function optionalVersionText(value: string | undefined, name: string, maxLength: number): string | undefined;
|
|
20
|
+
export declare function finalizeOpenUserVersions(meta: WorkbookMeta): void;
|
|
21
|
+
/**
|
|
22
|
+
* Close every user Version whose last Step is older than the idle window
|
|
23
|
+
* (PRD v3.3 D21).
|
|
24
|
+
*
|
|
25
|
+
* The write path already forks a session when the *next* write arrives after a
|
|
26
|
+
* pause, but nothing settled a session that was simply abandoned — leaving the
|
|
27
|
+
* tab open, or closing it, left the Version `open` forever, so "停手 10 分钟"
|
|
28
|
+
* never actually produced a saved Version. Settling is evaluated lazily when
|
|
29
|
+
* the version list is read, which is the moment a user can observe the outcome.
|
|
30
|
+
*
|
|
31
|
+
* Idempotent: a second call finds nothing open past the window and writes
|
|
32
|
+
* nothing.
|
|
33
|
+
*/
|
|
34
|
+
export declare function settleIdleUserVersions(workbookId: string, nowMs?: number): Promise<number>;
|
|
35
|
+
/** Finalize exactly one open Version, leaving other Versions untouched. */
|
|
36
|
+
export declare function finalizeVersion(meta: WorkbookMeta, versionId: string): void;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The editing session: when a Version opens, what closes it, and the shape of
|
|
3
|
+
* the version fields on the wire (docs/issue/0022 P2).
|
|
4
|
+
*
|
|
5
|
+
* Two boundaries close a session (PRD v3.5 D21) — the idle window and the Step
|
|
6
|
+
* cap — and nothing else does. `settleIdleUserVersions` exists because the write
|
|
7
|
+
* path can only fork a session when the *next* write arrives: an abandoned tab
|
|
8
|
+
* left a Version `open` forever, so settling is evaluated lazily at the moment
|
|
9
|
+
* the user can observe the outcome (reading the version list).
|
|
10
|
+
*/
|
|
11
|
+
import { VERSION_MAX_STEPS } from '#contracts';
|
|
12
|
+
import { cloneSnapshot } from "../contract/snapshots.js";
|
|
13
|
+
import { isIdlePast } from "../store/retention.js";
|
|
14
|
+
import { readWorkbook } from "../store/read.js";
|
|
15
|
+
import { writeWorkbook } from "../store/write.js";
|
|
16
|
+
// Safety cap only: idle and semantic boundaries are the primary Version
|
|
17
|
+
// boundary now (PRD §4.1). Shared through data-contracts.
|
|
18
|
+
export const VERSION_STEP_LIMIT = VERSION_MAX_STEPS;
|
|
19
|
+
/** Old logs use `temporary`; expose it as the clearer `open` lifecycle state. */
|
|
20
|
+
export function normalizeVersionStatus(status) {
|
|
21
|
+
return status === 'temporary' ? 'open' : status;
|
|
22
|
+
}
|
|
23
|
+
/** v3 tier on the wire; unknown values are dropped rather than guessed. */
|
|
24
|
+
export function normalizeVersionKind(kind) {
|
|
25
|
+
return kind === 'named' || kind === 'auto' ? kind : undefined;
|
|
26
|
+
}
|
|
27
|
+
export function isOpenVersionStatus(status) {
|
|
28
|
+
return status === 'open' || status === 'temporary';
|
|
29
|
+
}
|
|
30
|
+
export function optionalVersionText(value, name, maxLength) {
|
|
31
|
+
if (value === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
const normalized = value.trim();
|
|
34
|
+
if (normalized.length === 0 || normalized.length > maxLength)
|
|
35
|
+
throw new Error(`${name} 必须是 1 到 ${maxLength} 字符的字符串`);
|
|
36
|
+
return normalized;
|
|
37
|
+
}
|
|
38
|
+
export function finalizeOpenUserVersions(meta) {
|
|
39
|
+
const openVersionIds = new Set((meta.operations ?? [])
|
|
40
|
+
.filter(operation => operation.actor === 'user' && isOpenVersionStatus(operation.versionStatus) && operation.versionId !== undefined)
|
|
41
|
+
.map(operation => operation.versionId));
|
|
42
|
+
if (openVersionIds.size === 0)
|
|
43
|
+
return;
|
|
44
|
+
meta.operations = (meta.operations ?? []).map(operation => openVersionIds.has(operation.versionId ?? '')
|
|
45
|
+
? { ...operation, versionStatus: 'final' }
|
|
46
|
+
: operation);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Close every user Version whose last Step is older than the idle window
|
|
50
|
+
* (PRD v3.3 D21).
|
|
51
|
+
*
|
|
52
|
+
* The write path already forks a session when the *next* write arrives after a
|
|
53
|
+
* pause, but nothing settled a session that was simply abandoned — leaving the
|
|
54
|
+
* tab open, or closing it, left the Version `open` forever, so "停手 10 分钟"
|
|
55
|
+
* never actually produced a saved Version. Settling is evaluated lazily when
|
|
56
|
+
* the version list is read, which is the moment a user can observe the outcome.
|
|
57
|
+
*
|
|
58
|
+
* Idempotent: a second call finds nothing open past the window and writes
|
|
59
|
+
* nothing.
|
|
60
|
+
*/
|
|
61
|
+
export async function settleIdleUserVersions(workbookId, nowMs = Date.now()) {
|
|
62
|
+
const meta = await readWorkbook(workbookId);
|
|
63
|
+
if (meta === null)
|
|
64
|
+
return 0;
|
|
65
|
+
const open = (meta.operations ?? []).filter(operation => operation.actor === 'user' && isOpenVersionStatus(operation.versionStatus));
|
|
66
|
+
if (open.length === 0)
|
|
67
|
+
return 0;
|
|
68
|
+
const lastAt = new Map();
|
|
69
|
+
for (const operation of open) {
|
|
70
|
+
const id = operation.versionId ?? `revision:${operation.revision}`;
|
|
71
|
+
const previous = lastAt.get(id);
|
|
72
|
+
if (previous === undefined || operation.timestamp > previous)
|
|
73
|
+
lastAt.set(id, operation.timestamp);
|
|
74
|
+
}
|
|
75
|
+
const idle = [...lastAt.entries()].filter(([, timestamp]) => isIdlePast(timestamp, nowMs)).map(([id]) => id);
|
|
76
|
+
if (idle.length === 0)
|
|
77
|
+
return 0;
|
|
78
|
+
const next = cloneSnapshot(meta);
|
|
79
|
+
for (const id of idle)
|
|
80
|
+
finalizeVersion(next, id);
|
|
81
|
+
await writeWorkbook(next, { persistSnapshot: false, persistCheckpoints: false });
|
|
82
|
+
return idle.length;
|
|
83
|
+
}
|
|
84
|
+
/** Finalize exactly one open Version, leaving other Versions untouched. */
|
|
85
|
+
export function finalizeVersion(meta, versionId) {
|
|
86
|
+
meta.operations = (meta.operations ?? []).map(operation => operation.versionId === versionId && isOpenVersionStatus(operation.versionStatus)
|
|
87
|
+
? { ...operation, versionStatus: 'final' }
|
|
88
|
+
: operation);
|
|
89
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { WorkbookOperation } from '../types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Describe a whole-snapshot save by what it actually changed (PRD v3.1 §7).
|
|
4
|
+
* The browser persists most edits this way, and 「替换 workbook 快照」 told the
|
|
5
|
+
* user nothing; the diff is already computed for Version comparison, so a Step
|
|
6
|
+
* can say `修改 1 个单元格:Sheet1!C3` — an address the user can paste straight
|
|
7
|
+
* into the formula bar, unlike the former `Sheet1!R3C2`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function describeSnapshotReplace(before: unknown, after: unknown): string;
|
|
10
|
+
/**
|
|
11
|
+
* Describe an editing session that was never given a name (PRD v3.3 D21, D22).
|
|
12
|
+
*
|
|
13
|
+
* It used to read `编辑会话 · 5 个 Step`, which stated the same count twice: the
|
|
14
|
+
* row's meta line immediately above it already says `用户 · 5 个 Step`, and the
|
|
15
|
+
* two lines are read together. A session has no single operation to quote, and
|
|
16
|
+
* diffing its two ends would mean two snapshot reads plus a diff per Version on
|
|
17
|
+
* every list request — but the *kinds* of its Steps are already in hand, and
|
|
18
|
+
* 「改了什么」 is the question the summary line is there to answer; the size of
|
|
19
|
+
* the session is what the meta line is for.
|
|
20
|
+
*
|
|
21
|
+
* An unknown Step type is counted rather than dropped: a summary that silently
|
|
22
|
+
* omits a kind of change is worse than one that admits it does not know it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function describeSessionSteps(steps: readonly WorkbookOperation[]): string;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a Version and its Steps are described in words (docs/issue/0022 P2).
|
|
3
|
+
*
|
|
4
|
+
* This is the copy the user reads in the version list, so it is deliberately a
|
|
5
|
+
* module of its own: PRD 0002 changed it four times, and each of those changes
|
|
6
|
+
* is a change to *one* file rather than to the repository layer.
|
|
7
|
+
*
|
|
8
|
+
* A one-line summary of an *operation* (before it is diffed) lives in
|
|
9
|
+
* `contract/operations.ts` instead — `store/write.ts` embeds it in the sidecar
|
|
10
|
+
* index, and a store module may not import upward into `version/`.
|
|
11
|
+
*/
|
|
12
|
+
import { cellAddress, formatCellReference } from '#contracts';
|
|
13
|
+
import { DIFF_CHANGE_LIMIT, diffReachedLimit, diffWorkbookSnapshots } from "./diff.js";
|
|
14
|
+
/**
|
|
15
|
+
* Describe a whole-snapshot save by what it actually changed (PRD v3.1 §7).
|
|
16
|
+
* The browser persists most edits this way, and 「替换 workbook 快照」 told the
|
|
17
|
+
* user nothing; the diff is already computed for Version comparison, so a Step
|
|
18
|
+
* can say `修改 1 个单元格:Sheet1!C3` — an address the user can paste straight
|
|
19
|
+
* into the formula bar, unlike the former `Sheet1!R3C2`.
|
|
20
|
+
*/
|
|
21
|
+
export function describeSnapshotReplace(before, after) {
|
|
22
|
+
const changes = diffWorkbookSnapshots(before, after);
|
|
23
|
+
if (changes.length === 0)
|
|
24
|
+
return '保存内容(无变化)';
|
|
25
|
+
// Content edits are 修改; everything else is 样式. Splitting them is what
|
|
26
|
+
// makes the sentence true: a cell that only had its formatting touched is not
|
|
27
|
+
// a modification of anything the reader can see in the grid.
|
|
28
|
+
const cells = changes.filter(change => change.kind === 'cell' && change.styleOnly !== true);
|
|
29
|
+
const styled = changes.filter(change => change.kind !== 'cell' || change.styleOnly === true);
|
|
30
|
+
const sheetOf = (change) => change.sheetName ?? change.sheetId ?? 'sheet';
|
|
31
|
+
// One sheet is named once: `发版日志!B27、B28、B29` reads like a spreadsheet
|
|
32
|
+
// selection, while `发版日志!B27、发版日志!B28` repeats the same word per cell.
|
|
33
|
+
const head = changes.slice(0, 3);
|
|
34
|
+
const sheets = new Set(head.map(change => (change.kind === 'cell' ? sheetOf(change) : '')));
|
|
35
|
+
const labels = head.map(change => change.kind === 'cell'
|
|
36
|
+
? (sheets.size === 1
|
|
37
|
+
? cellAddress(change.row ?? 0, change.column ?? 0)
|
|
38
|
+
: formatCellReference({ sheet: sheetOf(change), row: change.row ?? 0, column: change.column ?? 0 }))
|
|
39
|
+
: (change.description === undefined ? sheetOf(change) : `${sheetOf(change)}·${change.description}`));
|
|
40
|
+
const scope = sheets.size === 1 && [...sheets][0] !== '' ? `${[...sheets][0]}!` : '';
|
|
41
|
+
// Three structural changes in one sheet used to print `Sheet1、Sheet1、Sheet1`.
|
|
42
|
+
const distinct = [...new Set(labels)];
|
|
43
|
+
// A sheet being merged or frozen — or a cell that only had its formatting
|
|
44
|
+
// touched — is not a 修改 of anything: nothing about the *content* changed.
|
|
45
|
+
// The old headline said `修改 4 处结构变化`, which read as though the count
|
|
46
|
+
// were the verb's object, and it once reported `修改 496 个单元格` when 473 of
|
|
47
|
+
// those were styled-but-empty cells. Each bucket now carries its own verb.
|
|
48
|
+
// 结构 / 改变 → 样式 is the user's wording (GUI feedback 2026-09-19): it is
|
|
49
|
+
// the word they read cell-formatting adjustments as, and it covers the
|
|
50
|
+
// sheet-level ones too.
|
|
51
|
+
// `capped` is not the same as `truncated` below: that one is about the *sample*
|
|
52
|
+
// list being cut short, this one about the counts themselves being a floor.
|
|
53
|
+
const capped = diffReachedLimit(changes);
|
|
54
|
+
const headline = [
|
|
55
|
+
cells.length > 0 ? `修改 ${cells.length}${capped ? '+' : ''} 个单元格` : '',
|
|
56
|
+
styled.length > 0 ? `样式 ${styled.length}${capped ? '+' : ''} 处` : '',
|
|
57
|
+
].filter(part => part !== '').join('、');
|
|
58
|
+
const truncated = changes.length > 3 || distinct.length < labels.length;
|
|
59
|
+
const limitNote = capped ? `(差异已达 ${DIFF_CHANGE_LIMIT} 条上限,计数为下限)` : '';
|
|
60
|
+
return `${headline}:${scope}${distinct.join('、')}${truncated ? ' 等' : ''}${limitNote}`;
|
|
61
|
+
}
|
|
62
|
+
/** One Step's kind → the bucket a session summary counts it in. */
|
|
63
|
+
const SESSION_STEP_BUCKET = {
|
|
64
|
+
update_cells: '修改单元格',
|
|
65
|
+
append_rows: '追加行',
|
|
66
|
+
set_hyperlink: '设置超链接',
|
|
67
|
+
remove_hyperlink: '移除超链接',
|
|
68
|
+
snapshot_replace: '保存内容',
|
|
69
|
+
create_sheet: '新增 sheet',
|
|
70
|
+
delete_sheet: '删除 sheet',
|
|
71
|
+
rename_sheet: '重命名 sheet',
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Fixed bucket order: what was edited first, then what the workbook is made of,
|
|
75
|
+
* then the presentation of a sheet. Map insertion order would have made the
|
|
76
|
+
* same session read differently depending on which Step happened to come first.
|
|
77
|
+
*/
|
|
78
|
+
const SESSION_BUCKET_ORDER = [
|
|
79
|
+
'修改单元格', '追加行', '设置超链接', '移除超链接', '保存内容',
|
|
80
|
+
'新增 sheet', '删除 sheet', '重命名 sheet',
|
|
81
|
+
];
|
|
82
|
+
/**
|
|
83
|
+
* Describe an editing session that was never given a name (PRD v3.3 D21, D22).
|
|
84
|
+
*
|
|
85
|
+
* It used to read `编辑会话 · 5 个 Step`, which stated the same count twice: the
|
|
86
|
+
* row's meta line immediately above it already says `用户 · 5 个 Step`, and the
|
|
87
|
+
* two lines are read together. A session has no single operation to quote, and
|
|
88
|
+
* diffing its two ends would mean two snapshot reads plus a diff per Version on
|
|
89
|
+
* every list request — but the *kinds* of its Steps are already in hand, and
|
|
90
|
+
* 「改了什么」 is the question the summary line is there to answer; the size of
|
|
91
|
+
* the session is what the meta line is for.
|
|
92
|
+
*
|
|
93
|
+
* An unknown Step type is counted rather than dropped: a summary that silently
|
|
94
|
+
* omits a kind of change is worse than one that admits it does not know it.
|
|
95
|
+
*/
|
|
96
|
+
export function describeSessionSteps(steps) {
|
|
97
|
+
const counts = new Map();
|
|
98
|
+
for (const step of steps) {
|
|
99
|
+
const bucket = SESSION_STEP_BUCKET[step.type] ?? '其他改动';
|
|
100
|
+
counts.set(bucket, (counts.get(bucket) ?? 0) + 1);
|
|
101
|
+
}
|
|
102
|
+
const buckets = [...counts.keys()].sort((left, right) => bucketRank(left) - bucketRank(right));
|
|
103
|
+
if (buckets.length === 0)
|
|
104
|
+
return '编辑会话';
|
|
105
|
+
return `编辑会话:${buckets.map(bucket => `${bucket} ${counts.get(bucket) ?? 0} 次`).join('、')}`;
|
|
106
|
+
}
|
|
107
|
+
/** Position in {@link SESSION_BUCKET_ORDER}; anything unlisted sorts last. */
|
|
108
|
+
function bucketRank(bucket) {
|
|
109
|
+
const at = SESSION_BUCKET_ORDER.indexOf(bucket);
|
|
110
|
+
return at === -1 ? SESSION_BUCKET_ORDER.length : at;
|
|
111
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-side workbook repository for dsh-data-table.
|
|
3
|
+
*
|
|
4
|
+
* One named workbook = one Univer snapshot JSON file under the DSH home
|
|
5
|
+
* storage root (`<dshHome>/storages/data-table/<id>.json`; the pre-rename
|
|
6
|
+
* `storages/data-sheet` root is migrated once on first access). The agent tools
|
|
7
|
+
* address workbooks by id across sessions; the browser mounts a residency
|
|
8
|
+
* instance from the current snapshot and saves back in Version-sized batches.
|
|
9
|
+
* @module dsh-data-table/workbook-manager
|
|
10
|
+
*/
|
|
11
|
+
import { type WorkbookMeta, type WorkbookOperation, type WorkbookOperationPayload, type WorkbookOperationType, type WorkbookVersionStatus, type WorkbookChange, type WorkbookProposal, type WorkbookWorktree } from './types.ts';
|
|
12
|
+
import { type ConflictEntry, type ConflictPayload, type VersionKind } from '#contracts';
|
|
13
|
+
import type { LineageContext } from '#contracts';
|
|
14
|
+
export { workbookRoot, legacyWorkbookRoot, WorkbookStorageMigration, migrateLegacyWorkbookStorage, workbookPath, workbookIndexPath } from './store/paths.ts';
|
|
15
|
+
export { WorkbookIndex, WorkbookIndexOperation, WorkbookIndexProposal, readWorkbookIndex, readWorkbook, readWorkbookAtRevision, workbookExists, listWorkbooks, listWorkbookSummaries, listWorkbookWorktrees, readWorkbookWorktree, summarize } from './store/read.ts';
|
|
16
|
+
export { writeWorkbook, deleteWorkbook, renameWorkbook } from './store/write.ts';
|
|
17
|
+
export { newWorktreeId, normalizeWorkbookId, normalizeWorktreeId } from './contract/ids.ts';
|
|
18
|
+
export { workbookOperationSteps } from './contract/operations.ts';
|
|
19
|
+
export { findDuplicateRows, readWorkbookRange } from './contract/snapshots.ts';
|
|
20
|
+
export { applyWorkbookOperation } from './contract/mutations.ts';
|
|
21
|
+
export { describeSnapshotReplace } from './version/summary.ts';
|
|
22
|
+
export { settleIdleUserVersions } from './version/session.ts';
|
|
23
|
+
export { diffWorkbookSnapshots, type WorkbookDiffScope } from './version/diff.ts';
|
|
24
|
+
/** Expand a persisted operation into the ordered steps represented by one
|
|
25
|
+
* version. A normal operation is one step; a batch keeps each child visible
|
|
26
|
+
* for history and replay without introducing a second persistence model. */
|
|
27
|
+
/** Create a worktree from the current trunk snapshot without mutating trunk. */
|
|
28
|
+
export declare function createWorkbookWorktree(args: {
|
|
29
|
+
workbookId: string;
|
|
30
|
+
ownerSessionId: string;
|
|
31
|
+
name?: string;
|
|
32
|
+
worktreeId?: string;
|
|
33
|
+
}): Promise<WorkbookWorktree>;
|
|
34
|
+
/** Apply an operation inside a worktree; trunk remains unchanged. */
|
|
35
|
+
export declare function mutateWorkbookWorktree(args: {
|
|
36
|
+
workbookId: string;
|
|
37
|
+
worktreeId: string;
|
|
38
|
+
ownerSessionId: string;
|
|
39
|
+
actor: 'agent' | 'user';
|
|
40
|
+
type: WorkbookOperationType;
|
|
41
|
+
payload: WorkbookOperationPayload;
|
|
42
|
+
expectedRevision?: number;
|
|
43
|
+
opId?: string;
|
|
44
|
+
lineage?: LineageContext;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
worktree: WorkbookWorktree;
|
|
47
|
+
operation: WorkbookOperation;
|
|
48
|
+
}>;
|
|
49
|
+
/** Move a worktree between review states without changing trunk data. */
|
|
50
|
+
export declare function setWorkbookWorktreeStatus(args: {
|
|
51
|
+
workbookId: string;
|
|
52
|
+
worktreeId: string;
|
|
53
|
+
ownerSessionId: string;
|
|
54
|
+
status: 'ready' | 'reopen' | 'discarded';
|
|
55
|
+
}): Promise<WorkbookWorktree>;
|
|
56
|
+
/** Merge a ready worktree into trunk as one atomic snapshot replacement. */
|
|
57
|
+
export declare function mergeWorkbookWorktree(args: {
|
|
58
|
+
workbookId: string;
|
|
59
|
+
worktreeId: string;
|
|
60
|
+
ownerSessionId: string;
|
|
61
|
+
actor?: 'agent' | 'user';
|
|
62
|
+
expectedRevision?: number;
|
|
63
|
+
}): Promise<{
|
|
64
|
+
worktree: WorkbookWorktree;
|
|
65
|
+
mutation: WorkbookMutationResult;
|
|
66
|
+
}>;
|
|
67
|
+
/** Create an empty workbook snapshot (one blank default sheet). */
|
|
68
|
+
export declare function blankSnapshot(name: string): unknown;
|
|
69
|
+
/** A failed optimistic-concurrency check, surfaced as a model-facing error. */
|
|
70
|
+
export declare class WorkbookRevisionConflictError extends Error {
|
|
71
|
+
readonly expected: number;
|
|
72
|
+
readonly actual: number;
|
|
73
|
+
readonly conflictSet: ConflictEntry[];
|
|
74
|
+
readonly workbookId: string;
|
|
75
|
+
/** Unified cross-plugin 409 body (PRD §5.1). */
|
|
76
|
+
readonly payload: ConflictPayload;
|
|
77
|
+
constructor(expected: number, actual: number, message?: string, conflictSet?: ConflictEntry[], workbookId?: string);
|
|
78
|
+
}
|
|
79
|
+
export interface WorkbookMutationResult {
|
|
80
|
+
meta: WorkbookMeta;
|
|
81
|
+
operation: WorkbookOperation;
|
|
82
|
+
/** Operations observed after the caller's base revision when it was rebased. */
|
|
83
|
+
rebasedOperations?: WorkbookOperation[];
|
|
84
|
+
/** True when the server accepted a safe concurrent cell edit. */
|
|
85
|
+
transformed?: boolean;
|
|
86
|
+
}
|
|
87
|
+
export interface WorkbookMutationPlanStep {
|
|
88
|
+
type: WorkbookOperationType;
|
|
89
|
+
payload: WorkbookOperationPayload;
|
|
90
|
+
opId?: string;
|
|
91
|
+
versionId?: string;
|
|
92
|
+
versionSummary?: string;
|
|
93
|
+
versionKind?: VersionKind;
|
|
94
|
+
versionIntent?: string;
|
|
95
|
+
agentRunId?: string;
|
|
96
|
+
lineage?: LineageContext;
|
|
97
|
+
}
|
|
98
|
+
export interface WorkbookMutationPlanResult {
|
|
99
|
+
meta: WorkbookMeta;
|
|
100
|
+
operations: WorkbookOperation[];
|
|
101
|
+
/** True when every step was already committed and the request was replayed. */
|
|
102
|
+
replayed?: boolean;
|
|
103
|
+
/** True when the plan was validated in memory only and nothing was persisted. */
|
|
104
|
+
dryRun?: boolean;
|
|
105
|
+
/** Operations observed after the caller's base revision when the plan was rebased. */
|
|
106
|
+
rebasedOperations?: WorkbookOperation[];
|
|
107
|
+
/** True when the plan was accepted on top of a newer revision instead of 409ing. */
|
|
108
|
+
transformed?: boolean;
|
|
109
|
+
}
|
|
110
|
+
export interface WorkbookProposalResult {
|
|
111
|
+
meta: WorkbookMeta;
|
|
112
|
+
proposal: WorkbookProposal;
|
|
113
|
+
}
|
|
114
|
+
export declare function mutateWorkbook(args: {
|
|
115
|
+
workbookId: string;
|
|
116
|
+
actor: 'agent' | 'user';
|
|
117
|
+
type: WorkbookOperationType;
|
|
118
|
+
payload: WorkbookOperationPayload;
|
|
119
|
+
expectedRevision?: number;
|
|
120
|
+
opId?: string;
|
|
121
|
+
createIfMissing?: boolean;
|
|
122
|
+
/** Join an existing open logical Version (browser user saves). */
|
|
123
|
+
versionId?: string;
|
|
124
|
+
versionStatus?: WorkbookVersionStatus;
|
|
125
|
+
/** Host-owned audit metadata for a semantic Agent Version. */
|
|
126
|
+
versionSummary?: string;
|
|
127
|
+
/** v3 tier; omitted by browser user edits, which are auto checkpoints. */
|
|
128
|
+
versionKind?: VersionKind;
|
|
129
|
+
versionIntent?: string;
|
|
130
|
+
agentRunId?: string;
|
|
131
|
+
lineage?: LineageContext;
|
|
132
|
+
}): Promise<WorkbookMutationResult>;
|
|
133
|
+
export declare function mutateWorkbookPlan(args: {
|
|
134
|
+
workbookId: string;
|
|
135
|
+
actor: 'agent';
|
|
136
|
+
steps: WorkbookMutationPlanStep[];
|
|
137
|
+
expectedRevision?: number;
|
|
138
|
+
dryRun?: boolean;
|
|
139
|
+
}): Promise<WorkbookMutationPlanResult>;
|
|
140
|
+
/** Build and persist a durable proposal without changing the workbook revision. */
|
|
141
|
+
export declare function previewWorkbookChanges(args: {
|
|
142
|
+
workbookId: string;
|
|
143
|
+
actor: 'agent' | 'user';
|
|
144
|
+
operations: Array<{
|
|
145
|
+
type: WorkbookOperationType;
|
|
146
|
+
payload: WorkbookOperationPayload;
|
|
147
|
+
}>;
|
|
148
|
+
expectedRevision?: number;
|
|
149
|
+
proposalId?: string;
|
|
150
|
+
summary?: string;
|
|
151
|
+
}): Promise<WorkbookProposalResult>;
|
|
152
|
+
/** Commit a proposal atomically after checking the revision it was previewed on. */
|
|
153
|
+
export declare function commitWorkbookProposal(args: {
|
|
154
|
+
workbookId: string;
|
|
155
|
+
proposalId: string;
|
|
156
|
+
actor: 'agent' | 'user';
|
|
157
|
+
expectedRevision?: number;
|
|
158
|
+
}): Promise<WorkbookMutationResult>;
|
|
159
|
+
/** Reject a pending proposal without changing workbook data or revision. */
|
|
160
|
+
export declare function rejectWorkbookProposal(workbookId: string, proposalId: string): Promise<WorkbookMeta>;
|
|
161
|
+
/** Restore any replayable previous version as a new revision. */
|
|
162
|
+
export declare function rollbackWorkbook(args: {
|
|
163
|
+
workbookId: string;
|
|
164
|
+
targetRevision: number;
|
|
165
|
+
expectedRevision?: number;
|
|
166
|
+
actor?: 'agent' | 'user';
|
|
167
|
+
opId?: string;
|
|
168
|
+
/** User-facing summary for the restored Version, e.g. `恢复到 V3`. */
|
|
169
|
+
summary?: string;
|
|
170
|
+
lineage?: LineageContext;
|
|
171
|
+
}): Promise<WorkbookMutationResult>;
|
|
172
|
+
/**
|
|
173
|
+
* What one Step changed: the diff between the state before it and the state
|
|
174
|
+
* after it (PRD v3.3 §7.2).
|
|
175
|
+
*
|
|
176
|
+
* Step replay used to hand the browser a snapshot and nothing else, so the
|
|
177
|
+
* viewport stayed wherever the previous state happened to leave it and the user
|
|
178
|
+
* had to hunt for the cell that moved. This answers "which cells, and where" in
|
|
179
|
+
* the same request as the snapshot, so the canvas can scroll to and tint them.
|
|
180
|
+
*/
|
|
181
|
+
export declare function readStepChanges(workbookId: string, targetRevision: number, stepIndex: number): Promise<WorkbookChange[] | null>;
|
|
182
|
+
/** Reconstruct the state after one step inside a Version. This starts from
|
|
183
|
+
* the revision before the Version's first physical operation, then applies
|
|
184
|
+
* only the requested ordered children so the UI can replay it step by step. */
|
|
185
|
+
export declare function readWorkbookAtStep(workbookId: string, targetRevision: number, stepIndex: number): Promise<{
|
|
186
|
+
snapshot: unknown;
|
|
187
|
+
revision: number;
|
|
188
|
+
step: number;
|
|
189
|
+
stepCount: number;
|
|
190
|
+
baseRevision?: number;
|
|
191
|
+
} | null>;
|