@cello-protocol/daemon 0.0.120 → 0.0.122
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/dist/content-park.d.ts +1 -1
- package/dist/content-park.d.ts.map +1 -1
- package/dist/content-park.js +64 -12
- package/dist/content-park.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +46 -32
- package/dist/daemon.js.map +1 -1
- package/dist/document-delivery-transport.d.ts +78 -0
- package/dist/document-delivery-transport.d.ts.map +1 -0
- package/dist/document-delivery-transport.js +109 -0
- package/dist/document-delivery-transport.js.map +1 -0
- package/dist/document-delivery.d.ts +130 -0
- package/dist/document-delivery.d.ts.map +1 -0
- package/dist/document-delivery.js +246 -0
- package/dist/document-delivery.js.map +1 -0
- package/dist/document-engine.d.ts +134 -0
- package/dist/document-engine.d.ts.map +1 -0
- package/dist/document-engine.js +281 -0
- package/dist/document-engine.js.map +1 -0
- package/dist/document-gate.d.ts +139 -0
- package/dist/document-gate.d.ts.map +1 -0
- package/dist/document-gate.js +465 -0
- package/dist/document-gate.js.map +1 -0
- package/dist/document-handshake.d.ts +88 -0
- package/dist/document-handshake.d.ts.map +1 -0
- package/dist/document-handshake.js +239 -0
- package/dist/document-handshake.js.map +1 -0
- package/dist/document-lifecycle.d.ts +104 -0
- package/dist/document-lifecycle.d.ts.map +1 -0
- package/dist/document-lifecycle.js +363 -0
- package/dist/document-lifecycle.js.map +1 -0
- package/dist/document-notify.d.ts +130 -0
- package/dist/document-notify.d.ts.map +1 -0
- package/dist/document-notify.js +313 -0
- package/dist/document-notify.js.map +1 -0
- package/dist/document-reachability.d.ts +42 -0
- package/dist/document-reachability.d.ts.map +1 -0
- package/dist/document-reachability.js +72 -0
- package/dist/document-reachability.js.map +1 -0
- package/dist/document-rejection.d.ts +224 -0
- package/dist/document-rejection.d.ts.map +1 -0
- package/dist/document-rejection.js +374 -0
- package/dist/document-rejection.js.map +1 -0
- package/dist/document-store.d.ts +269 -0
- package/dist/document-store.d.ts.map +1 -0
- package/dist/document-store.js +752 -0
- package/dist/document-store.js.map +1 -0
- package/dist/document-write-path.d.ts +84 -0
- package/dist/document-write-path.d.ts.map +1 -0
- package/dist/document-write-path.js +412 -0
- package/dist/document-write-path.js.map +1 -0
- package/dist/line-lcs.d.ts +51 -0
- package/dist/line-lcs.d.ts.map +1 -0
- package/dist/line-lcs.js +71 -0
- package/dist/line-lcs.js.map +1 -0
- package/dist/reconnect-drain.d.ts +15 -0
- package/dist/reconnect-drain.d.ts.map +1 -0
- package/dist/reconnect-drain.js +51 -0
- package/dist/reconnect-drain.js.map +1 -0
- package/dist/session-node-manager.d.ts +39 -0
- package/dist/session-node-manager.d.ts.map +1 -1
- package/dist/session-node-manager.js +152 -12
- package/dist/session-node-manager.js.map +1 -1
- package/dist/session-relay-client.d.ts +2 -0
- package/dist/session-relay-client.d.ts.map +1 -1
- package/dist/session-relay-client.js +16 -1
- package/dist/session-relay-client.js.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-store.js","sourceRoot":"","sources":["../src/document-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOD-DOC-WRITE-1 — the write path (§16.2).
|
|
3
|
+
*
|
|
4
|
+
* **The document is a real file.** The agent edits it with Read/Edit like any other file, and the
|
|
5
|
+
* human can open the same file; the daemon diffs it at publish and converts the diff into Yjs
|
|
6
|
+
* operations. No new editing surface exists — that is the design, not a shortcut.
|
|
7
|
+
*
|
|
8
|
+
* ── THE FOLD ORDER IS THE DESIGN ──────────────────────────────────────────────────────────────
|
|
9
|
+
*
|
|
10
|
+
* On admission (§16.2): fold the agent's UNPUBLISHED file edits into the `Y.Doc` as local
|
|
11
|
+
* operations FIRST, then merge the incoming update, then rewrite the file. Reversing the first
|
|
12
|
+
* two silently destroys the agent's unpublished work, and §4.1's overlap flag — which IS whether
|
|
13
|
+
* the merge touched what the fold just wrote — disappears with it.
|
|
14
|
+
*
|
|
15
|
+
* ── WHY THE PROJECTION IS PERSISTED ───────────────────────────────────────────────────────────
|
|
16
|
+
*
|
|
17
|
+
* §16.2 says publish diffs the file against "the last-known projection", and that baseline has to
|
|
18
|
+
* outlive the process. Diffing against the DOC's current text instead looks equivalent and is not:
|
|
19
|
+
* `admit` merges into the doc and rewrites the file as two separate steps, so a crash between them
|
|
20
|
+
* leaves a stale file beside an advanced doc. Diffing that against the doc reads the peer's
|
|
21
|
+
* admitted content as something the agent deleted, and publishes the deletion as deliberate
|
|
22
|
+
* intent. Measured, so the projection is written to disk beside the document and read back.
|
|
23
|
+
*/
|
|
24
|
+
import * as Y from "yjs";
|
|
25
|
+
import type { DocumentEngine } from "./document-engine.js";
|
|
26
|
+
import type { Logger } from "./types.js";
|
|
27
|
+
export type DocumentWriteFailure = "document_file_missing" | "document_file_unparseable" | "document_file_stale" | "document_file_changed_during_merge" | "document_projection_missing" | "document_file_unreadable" | "document_type_unsupported" | "document_id_invalid";
|
|
28
|
+
export declare class DocumentWriteError extends Error {
|
|
29
|
+
readonly reason: DocumentWriteFailure;
|
|
30
|
+
readonly detail: string;
|
|
31
|
+
constructor(reason: DocumentWriteFailure, detail: string);
|
|
32
|
+
}
|
|
33
|
+
export interface AdmitResult {
|
|
34
|
+
/**
|
|
35
|
+
* §4.1's overlap flag: the merge touched a region (or, for JSON, a key) holding UNPUBLISHED
|
|
36
|
+
* local edits. Not a conflict warning — Yjs resolved it — but a signal that the agent should
|
|
37
|
+
* re-read the merged projection before building on what it thought it had written.
|
|
38
|
+
*/
|
|
39
|
+
overlap: boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare class DocumentWritePath {
|
|
42
|
+
#private;
|
|
43
|
+
readonly engine: DocumentEngine;
|
|
44
|
+
constructor(engine: DocumentEngine, workspaceRoot: string, logger: Logger);
|
|
45
|
+
/**
|
|
46
|
+
* The file a document lives at. Keyed on the FULL `agent_id`/`document_id` — truncating them
|
|
47
|
+
* would let two documents sharing a prefix collide onto one file and destroy each other, and
|
|
48
|
+
* both ids are validated because they become path components.
|
|
49
|
+
*/
|
|
50
|
+
filePath(agentId: string, documentId: string, documentType: string): string;
|
|
51
|
+
/** Write the document's projection to disk and record it as the diff baseline. */
|
|
52
|
+
materialize(agentId: string, documentId: string, documentType: string, doc: Y.Doc): Promise<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Diff the file against the LAST-KNOWN PROJECTION and apply the difference as local operations.
|
|
55
|
+
* Returns the resulting update, or null when the file is unchanged.
|
|
56
|
+
*
|
|
57
|
+
* Null is a real answer: publish is an intent, so a publish with nothing to say must produce no
|
|
58
|
+
* envelope rather than an empty one that still costs a leaf and a round trip.
|
|
59
|
+
*/
|
|
60
|
+
publish(agentId: string, documentId: string, documentType: string, doc: Y.Doc): Promise<Uint8Array | null>;
|
|
61
|
+
/** Admit a peer's update: fold local edits, merge, rewrite, report overlap. */
|
|
62
|
+
admit(agentId: string, documentId: string, documentType: string, doc: Y.Doc, incoming: Uint8Array): Promise<AdmitResult>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Line-level hunks between two texts, as character offsets into `before`.
|
|
66
|
+
*
|
|
67
|
+
* Lines are represented as CHUNKS — each line carries its own trailing newline, except the last,
|
|
68
|
+
* which does not. That representation is what makes newline handling fall out instead of being
|
|
69
|
+
* special-cased: appending a line to "a\nb" turns the chunk "b" into "b\n" + "c", so the LCS
|
|
70
|
+
* sees the last line as changed and the hunk replaces "b" with "b\nc". A hand-rolled
|
|
71
|
+
* prefix/suffix trim got this wrong for every edit that changed the line count — measured, four
|
|
72
|
+
* of six ordinary markdown edits published text that was not what the file said.
|
|
73
|
+
*
|
|
74
|
+
* A real LCS (not a prefix/suffix trim) is required because the whole point is to emit SEPARATE
|
|
75
|
+
* hunks for separated edits: one span from the first change to the last would delete and
|
|
76
|
+
* re-insert everything between them as new operations, resurrecting text a peer concurrently
|
|
77
|
+
* deleted. Under publish-on-intent, multi-edit publishes are the modal case.
|
|
78
|
+
*/
|
|
79
|
+
export declare function lineHunks(before: string, after: string): Array<{
|
|
80
|
+
from: number;
|
|
81
|
+
to: number;
|
|
82
|
+
insert: string;
|
|
83
|
+
}>;
|
|
84
|
+
//# sourceMappingURL=document-write-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-write-path.d.ts","sourceRoot":"","sources":["../src/document-write-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAazC,MAAM,MAAM,oBAAoB,GAC5B,uBAAuB,GACvB,2BAA2B,GAC3B,qBAAqB,GACrB,oCAAoC,GACpC,6BAA6B,GAC7B,0BAA0B,GAC1B,2BAA2B,GAC3B,qBAAqB,CAAC;AAE1B,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM;CAMzD;AAED,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,iBAAiB;;IAC5B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;gBAIpB,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAMzE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAO3E,kFAAkF;IAC5E,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAUzG;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA0ChH,+EAA+E;IACzE,KAAK,CACT,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,QAAQ,EAAE,UAAU,GACnB,OAAO,CAAC,WAAW,CAAC;CAySxB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAqBrD"}
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOD-DOC-WRITE-1 — the write path (§16.2).
|
|
3
|
+
*
|
|
4
|
+
* **The document is a real file.** The agent edits it with Read/Edit like any other file, and the
|
|
5
|
+
* human can open the same file; the daemon diffs it at publish and converts the diff into Yjs
|
|
6
|
+
* operations. No new editing surface exists — that is the design, not a shortcut.
|
|
7
|
+
*
|
|
8
|
+
* ── THE FOLD ORDER IS THE DESIGN ──────────────────────────────────────────────────────────────
|
|
9
|
+
*
|
|
10
|
+
* On admission (§16.2): fold the agent's UNPUBLISHED file edits into the `Y.Doc` as local
|
|
11
|
+
* operations FIRST, then merge the incoming update, then rewrite the file. Reversing the first
|
|
12
|
+
* two silently destroys the agent's unpublished work, and §4.1's overlap flag — which IS whether
|
|
13
|
+
* the merge touched what the fold just wrote — disappears with it.
|
|
14
|
+
*
|
|
15
|
+
* ── WHY THE PROJECTION IS PERSISTED ───────────────────────────────────────────────────────────
|
|
16
|
+
*
|
|
17
|
+
* §16.2 says publish diffs the file against "the last-known projection", and that baseline has to
|
|
18
|
+
* outlive the process. Diffing against the DOC's current text instead looks equivalent and is not:
|
|
19
|
+
* `admit` merges into the doc and rewrites the file as two separate steps, so a crash between them
|
|
20
|
+
* leaves a stale file beside an advanced doc. Diffing that against the doc reads the peer's
|
|
21
|
+
* admitted content as something the agent deleted, and publishes the deletion as deliberate
|
|
22
|
+
* intent. Measured, so the projection is written to disk beside the document and read back.
|
|
23
|
+
*/
|
|
24
|
+
import { mkdir, readFile, writeFile, rename } from "node:fs/promises";
|
|
25
|
+
import { join } from "node:path";
|
|
26
|
+
import { lineRuns, toChunks } from "./line-lcs.js";
|
|
27
|
+
/** Yjs roots a materialized document projects from. TEXT_ROOT must match DocumentEngine's. */
|
|
28
|
+
const TEXT_ROOT = "content";
|
|
29
|
+
const MAP_ROOT = "data";
|
|
30
|
+
const TEXT_TYPES = new Set(["markdown", "text", "plaintext"]);
|
|
31
|
+
const JSON_TYPES = new Set(["json"]);
|
|
32
|
+
/** Ids are hex identities, never names, and they become path components. */
|
|
33
|
+
const ID_PATTERN = /^[0-9a-f]{64}$/;
|
|
34
|
+
export class DocumentWriteError extends Error {
|
|
35
|
+
reason;
|
|
36
|
+
detail;
|
|
37
|
+
constructor(reason, detail) {
|
|
38
|
+
super(`${reason}: ${detail}`);
|
|
39
|
+
this.name = "DocumentWriteError";
|
|
40
|
+
this.reason = reason;
|
|
41
|
+
this.detail = detail;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export class DocumentWritePath {
|
|
45
|
+
engine;
|
|
46
|
+
#root;
|
|
47
|
+
#logger;
|
|
48
|
+
constructor(engine, workspaceRoot, logger) {
|
|
49
|
+
this.engine = engine;
|
|
50
|
+
this.#root = workspaceRoot;
|
|
51
|
+
this.#logger = logger;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The file a document lives at. Keyed on the FULL `agent_id`/`document_id` — truncating them
|
|
55
|
+
* would let two documents sharing a prefix collide onto one file and destroy each other, and
|
|
56
|
+
* both ids are validated because they become path components.
|
|
57
|
+
*/
|
|
58
|
+
filePath(agentId, documentId, documentType) {
|
|
59
|
+
this.#assertId(agentId, "agent_id");
|
|
60
|
+
this.#assertId(documentId, "document_id");
|
|
61
|
+
const extension = JSON_TYPES.has(documentType) ? "json" : "md";
|
|
62
|
+
return join(this.#root, agentId, `${documentId}.${extension}`);
|
|
63
|
+
}
|
|
64
|
+
/** Write the document's projection to disk and record it as the diff baseline. */
|
|
65
|
+
async materialize(agentId, documentId, documentType, doc) {
|
|
66
|
+
this.#assertSupported(documentType);
|
|
67
|
+
const path = this.filePath(agentId, documentId, documentType);
|
|
68
|
+
const content = this.#project(doc, documentType);
|
|
69
|
+
await this.#writeAtomic(agentId, path, content);
|
|
70
|
+
await this.#saveProjection(agentId, documentId, documentType, content);
|
|
71
|
+
this.#logger.info("document.file.materialized", { documentId, bytes: content.length });
|
|
72
|
+
return path;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Diff the file against the LAST-KNOWN PROJECTION and apply the difference as local operations.
|
|
76
|
+
* Returns the resulting update, or null when the file is unchanged.
|
|
77
|
+
*
|
|
78
|
+
* Null is a real answer: publish is an intent, so a publish with nothing to say must produce no
|
|
79
|
+
* envelope rather than an empty one that still costs a leaf and a round trip.
|
|
80
|
+
*/
|
|
81
|
+
async publish(agentId, documentId, documentType, doc) {
|
|
82
|
+
this.#assertSupported(documentType);
|
|
83
|
+
const path = this.filePath(agentId, documentId, documentType);
|
|
84
|
+
const onDisk = await this.#readOrRefuse(path, documentId);
|
|
85
|
+
const projection = await this.#loadProjection(agentId, documentId, documentType);
|
|
86
|
+
if (projection === null) {
|
|
87
|
+
throw new DocumentWriteError("document_file_missing", `no recorded projection for document ${documentId} — materialize it before publishing`);
|
|
88
|
+
}
|
|
89
|
+
// A file that matches NEITHER the recorded projection nor the document's current state means
|
|
90
|
+
// a rewrite did not complete (admit merges into the doc and rewrites the file as two steps).
|
|
91
|
+
// Diffing it would read the peer's admitted content as an agent deletion and publish that
|
|
92
|
+
// deletion as deliberate intent. Refuse and re-materialize instead.
|
|
93
|
+
// THE BASELINE MUST MATCH THE DOCUMENT. Hunks are offsets into the projection, applied to the
|
|
94
|
+
// doc's text, so they are sound only while the two agree. An earlier version refused only when
|
|
95
|
+
// the file was ALSO untouched, which let through the one state that matters: the doc advanced
|
|
96
|
+
// past the projection AND the agent edited the file. That applies projection-offset hunks to a
|
|
97
|
+
// longer document and mutilates the peer's admitted content — measured. The condition is the
|
|
98
|
+
// invariant itself, not a symptom of it.
|
|
99
|
+
const current = this.#project(doc, documentType);
|
|
100
|
+
if (projection !== current) {
|
|
101
|
+
throw new DocumentWriteError("document_file_stale", `the recorded projection for ${documentId} no longer matches the document — a rewrite did ` +
|
|
102
|
+
`not complete, so re-materialize before publishing rather than diffing against a ` +
|
|
103
|
+
`baseline the document has moved past`);
|
|
104
|
+
}
|
|
105
|
+
const before = this.engine.encodeStateVector(doc);
|
|
106
|
+
const changed = this.#fold(doc, projection, onDisk, documentType) !== null;
|
|
107
|
+
if (!changed)
|
|
108
|
+
return null;
|
|
109
|
+
await this.#saveProjection(agentId, documentId, documentType, onDisk);
|
|
110
|
+
this.#logger.info("document.publish.diffed", { documentId, bytes: onDisk.length });
|
|
111
|
+
return this.engine.encodeState(doc, before);
|
|
112
|
+
}
|
|
113
|
+
/** Admit a peer's update: fold local edits, merge, rewrite, report overlap. */
|
|
114
|
+
async admit(agentId, documentId, documentType, doc, incoming) {
|
|
115
|
+
this.#assertSupported(documentType);
|
|
116
|
+
const path = this.filePath(agentId, documentId, documentType);
|
|
117
|
+
// 1. FOLD unpublished local edits in as local operations.
|
|
118
|
+
let onDisk = null;
|
|
119
|
+
try {
|
|
120
|
+
onDisk = await readFile(path, "utf8");
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
// ONLY a missing file means "nothing local to lose". Any other errno — EACCES, EIO, EMFILE —
|
|
124
|
+
// read as that would skip the fold and then overwrite the file with the merged projection,
|
|
125
|
+
// discarding the agent's unpublished work with no event at all.
|
|
126
|
+
if (err?.code !== "ENOENT") {
|
|
127
|
+
throw new DocumentWriteError("document_file_unreadable", `the file for ${documentId} could not be read (${err?.code ?? "unknown"}) — ` +
|
|
128
|
+
`refusing rather than treating it as absent and overwriting unpublished edits`);
|
|
129
|
+
}
|
|
130
|
+
onDisk = null;
|
|
131
|
+
}
|
|
132
|
+
// REFUSE a missing baseline rather than substituting "". Diffing "" against the file yields a
|
|
133
|
+
// whole-file hunk inserted at offset 0 of a document that already holds that content — the
|
|
134
|
+
// body duplicated into the CRDT and out to the peer, permanently.
|
|
135
|
+
const projection = await this.#loadProjection(agentId, documentId, documentType);
|
|
136
|
+
if (onDisk !== null && projection === null) {
|
|
137
|
+
throw new DocumentWriteError("document_projection_missing", `no recorded projection for document ${documentId} — re-materialize before admitting, ` +
|
|
138
|
+
`since without a baseline the file cannot be told apart from an empty document`);
|
|
139
|
+
}
|
|
140
|
+
let localText = null;
|
|
141
|
+
const localKeys = new Set();
|
|
142
|
+
if (onDisk !== null) {
|
|
143
|
+
const folded = this.#fold(doc, projection, onDisk, documentType);
|
|
144
|
+
if (folded && "from" in folded)
|
|
145
|
+
localText = folded;
|
|
146
|
+
else if (folded)
|
|
147
|
+
for (const k of folded.keys)
|
|
148
|
+
localKeys.add(k);
|
|
149
|
+
}
|
|
150
|
+
// 2. MERGE, observing what the incoming update touches — in BOTH coordinate spaces, because
|
|
151
|
+
// a JSON document's edits live in the map and a text observer sees none of them.
|
|
152
|
+
// Inserts and deletes are compared DIFFERENTLY, and the asymmetry is the point. A re-homed
|
|
153
|
+
// insert landing exactly on the local edit's boundary IS overlap — Yjs put it there because
|
|
154
|
+
// the local fold deleted the characters it was anchored to. A deletion landing on that
|
|
155
|
+
// boundary is NOT: it happened above the local edit and merely shifted it down, which is the
|
|
156
|
+
// ordinary case of a peer editing the paragraph above yours.
|
|
157
|
+
const inserted = [];
|
|
158
|
+
const deletedAt = [];
|
|
159
|
+
const mergedKeys = new Set();
|
|
160
|
+
const onText = (event) => {
|
|
161
|
+
let cursor = 0;
|
|
162
|
+
for (const delta of event.delta) {
|
|
163
|
+
if (delta.retain !== undefined)
|
|
164
|
+
cursor += delta.retain;
|
|
165
|
+
else if (typeof delta.insert === "string") {
|
|
166
|
+
inserted.push({ from: cursor, to: cursor + delta.insert.length });
|
|
167
|
+
// Shift any local region that sits at or after this insert into the SAME coordinate
|
|
168
|
+
// system. Without it the flag depends on how LONG the peer's insert was rather than
|
|
169
|
+
// where it landed — a disjoint edit reads as overlapping once the insert is big enough.
|
|
170
|
+
if (localText && localText.from >= cursor) {
|
|
171
|
+
localText = { from: localText.from + delta.insert.length, to: localText.to + delta.insert.length };
|
|
172
|
+
}
|
|
173
|
+
cursor += delta.insert.length;
|
|
174
|
+
}
|
|
175
|
+
else if (delta.delete !== undefined) {
|
|
176
|
+
// A POINT in post-delete coordinates. Recording the delete's OLD width made any local
|
|
177
|
+
// edit within N characters after it read as overlapping — the flag sensitive to how BIG
|
|
178
|
+
// the peer's delete was rather than where it landed.
|
|
179
|
+
deletedAt.push(cursor);
|
|
180
|
+
if (localText && localText.from >= cursor) {
|
|
181
|
+
const shift = Math.min(delta.delete, Math.max(0, localText.from - cursor));
|
|
182
|
+
localText = { from: localText.from - shift, to: localText.to - shift };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
const onMap = (event) => {
|
|
188
|
+
for (const key of event.keysChanged)
|
|
189
|
+
mergedKeys.add(key);
|
|
190
|
+
};
|
|
191
|
+
const text = doc.getText(TEXT_ROOT);
|
|
192
|
+
const map = doc.getMap(MAP_ROOT);
|
|
193
|
+
text.observe(onText);
|
|
194
|
+
map.observe(onMap);
|
|
195
|
+
try {
|
|
196
|
+
this.engine.applyUpdateOrThrow(doc, incoming);
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
text.unobserve(onText);
|
|
200
|
+
map.unobserve(onMap);
|
|
201
|
+
}
|
|
202
|
+
// 3. REWRITE so the agent sees the merged projection — refusing if the file moved under us.
|
|
203
|
+
if (onDisk !== null) {
|
|
204
|
+
// Re-read the CONTENT rather than trusting mtime: second-granularity filesystems hide a save
|
|
205
|
+
// inside the merge window, and a stat that itself fails must not read as "unchanged" — this
|
|
206
|
+
// guard exists precisely to prevent a silent clobber.
|
|
207
|
+
let nowOnDisk;
|
|
208
|
+
try {
|
|
209
|
+
nowOnDisk = await readFile(path, "utf8");
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
throw new DocumentWriteError("document_file_unreadable", `the file for ${documentId} became unreadable during the merge ` +
|
|
213
|
+
`(${err?.code ?? "unknown"}) — refusing rather than rewriting it`);
|
|
214
|
+
}
|
|
215
|
+
if (nowOnDisk !== onDisk) {
|
|
216
|
+
throw new DocumentWriteError("document_file_changed_during_merge", `the file for ${documentId} was written while the merge was in flight — its content was ` +
|
|
217
|
+
`not folded in, so rewriting would discard it`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const merged = this.#project(doc, documentType);
|
|
221
|
+
await this.#writeAtomic(agentId, path, merged);
|
|
222
|
+
await this.#saveProjection(agentId, documentId, documentType, merged);
|
|
223
|
+
// 4. OVERLAP falls out of the fold, in whichever space the document lives in.
|
|
224
|
+
// Endpoints are INCLUSIVE: when the local fold deletes the characters an incoming insert
|
|
225
|
+
// was anchored to, Yjs re-homes that insert onto the boundary of the local edit — and
|
|
226
|
+
// which side depends on its random clientID tie-break, so exclusive comparison answers a
|
|
227
|
+
// definite question with a coin flip.
|
|
228
|
+
const region = localText;
|
|
229
|
+
const overlap = region
|
|
230
|
+
? inserted.some((t) => t.from <= region.to && region.from <= t.to) ||
|
|
231
|
+
// STRICTLY inside: a deletion at the region's own boundary is adjacency, not overlap.
|
|
232
|
+
deletedAt.some((at) => at > region.from && at < region.to)
|
|
233
|
+
: [...localKeys].some((k) => mergedKeys.has(k));
|
|
234
|
+
this.#logger.info("document.file.rewritten", { documentId, bytes: merged.length });
|
|
235
|
+
if (overlap)
|
|
236
|
+
this.#logger.info("document.file.overlap_detected", { documentId });
|
|
237
|
+
return { overlap };
|
|
238
|
+
}
|
|
239
|
+
// ─── internals ────────────────────────────────────────────────────────────
|
|
240
|
+
#project(doc, documentType) {
|
|
241
|
+
if (JSON_TYPES.has(documentType)) {
|
|
242
|
+
return `${JSON.stringify(doc.getMap(MAP_ROOT).toJSON(), null, 2)}\n`;
|
|
243
|
+
}
|
|
244
|
+
return this.engine.readTextRoot(doc);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Apply the file's content to the document, diffing against the recorded projection.
|
|
248
|
+
* Returns the region (text) or key set (JSON) the local edit occupies, or null if unchanged.
|
|
249
|
+
*/
|
|
250
|
+
#fold(doc, projection, onDisk, documentType) {
|
|
251
|
+
if (JSON_TYPES.has(documentType)) {
|
|
252
|
+
const keys = this.#foldJson(doc, onDisk);
|
|
253
|
+
return keys.length > 0 ? { keys } : null;
|
|
254
|
+
}
|
|
255
|
+
return this.#foldText(doc, projection, onDisk);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Text diff producing N hunks, not one span.
|
|
259
|
+
*
|
|
260
|
+
* A single prefix/suffix range is coarse in a way §16.2 does NOT licence: a publish batch with
|
|
261
|
+
* two separated edits would delete and re-insert everything between them as new operations,
|
|
262
|
+
* which resurrects text a peer concurrently deleted and re-homes their insertions into the
|
|
263
|
+
* middle of it. Measured. Publish-on-intent makes multi-hunk the NORMAL shape — an agent edits
|
|
264
|
+
* across a turn and publishes once — so the line-level hunks below are the granularity the
|
|
265
|
+
* design actually wants, and they collapse to the old behaviour for one contiguous edit.
|
|
266
|
+
*/
|
|
267
|
+
#foldText(doc, projection, onDisk) {
|
|
268
|
+
const text = doc.getText(TEXT_ROOT);
|
|
269
|
+
if (text.toString() === onDisk)
|
|
270
|
+
return null;
|
|
271
|
+
const hunks = lineHunks(projection, onDisk);
|
|
272
|
+
if (hunks.length === 0)
|
|
273
|
+
return null;
|
|
274
|
+
// Apply back to front so earlier offsets stay valid.
|
|
275
|
+
doc.transact(() => {
|
|
276
|
+
for (const hunk of [...hunks].reverse()) {
|
|
277
|
+
if (hunk.to > hunk.from)
|
|
278
|
+
text.delete(hunk.from, hunk.to - hunk.from);
|
|
279
|
+
if (hunk.insert.length > 0)
|
|
280
|
+
text.insert(hunk.from, hunk.insert);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
// The span the local edits occupy AFTER folding — the coordinate system the merge's deltas
|
|
284
|
+
// will be reported in.
|
|
285
|
+
let shift = 0;
|
|
286
|
+
let low = Number.POSITIVE_INFINITY;
|
|
287
|
+
let high = 0;
|
|
288
|
+
for (const hunk of hunks) {
|
|
289
|
+
const from = hunk.from + shift;
|
|
290
|
+
const to = from + hunk.insert.length;
|
|
291
|
+
low = Math.min(low, from);
|
|
292
|
+
high = Math.max(high, to);
|
|
293
|
+
shift += hunk.insert.length - (hunk.to - hunk.from);
|
|
294
|
+
}
|
|
295
|
+
return { from: low, to: high };
|
|
296
|
+
}
|
|
297
|
+
/** Key diff: set what changed, delete what is gone. Returns the keys written. */
|
|
298
|
+
#foldJson(doc, onDisk) {
|
|
299
|
+
let parsed;
|
|
300
|
+
try {
|
|
301
|
+
parsed = JSON.parse(onDisk);
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
throw new DocumentWriteError("document_file_unparseable", `the document's file is not valid JSON — ${err instanceof Error ? err.message : String(err)}`);
|
|
305
|
+
}
|
|
306
|
+
const map = doc.getMap(MAP_ROOT);
|
|
307
|
+
const written = [];
|
|
308
|
+
doc.transact(() => {
|
|
309
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
310
|
+
if (JSON.stringify(map.get(key)) !== JSON.stringify(value)) {
|
|
311
|
+
map.set(key, value);
|
|
312
|
+
written.push(key);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
for (const key of [...map.keys()]) {
|
|
316
|
+
if (!(key in parsed)) {
|
|
317
|
+
map.delete(key);
|
|
318
|
+
written.push(key);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
return written;
|
|
323
|
+
}
|
|
324
|
+
/** tmp + rename, so an interrupted write cannot leave a truncated file a later diff reads as
|
|
325
|
+
* a deliberate mass deletion. */
|
|
326
|
+
async #writeAtomic(agentId, path, content) {
|
|
327
|
+
await mkdir(join(this.#root, agentId), { recursive: true });
|
|
328
|
+
const tmp = `${path}.tmp`;
|
|
329
|
+
await writeFile(tmp, content, "utf8");
|
|
330
|
+
await rename(tmp, path);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* The baseline lives in a dot-directory, NOT beside the document. §16.2's premise is that the
|
|
334
|
+
* agent edits an ordinary file and no new surface exists — a sibling `<name>.md.projection` IS
|
|
335
|
+
* a new surface, one an agent may open, edit, or tidy away, and deleting it used to duplicate
|
|
336
|
+
* the document.
|
|
337
|
+
*/
|
|
338
|
+
#projectionPath(agentId, documentId, documentType) {
|
|
339
|
+
const extension = JSON_TYPES.has(documentType) ? "json" : "md";
|
|
340
|
+
return join(this.#root, ".cello", agentId, `${documentId}.${extension}.projection`);
|
|
341
|
+
}
|
|
342
|
+
/** The projection is persisted so it survives a restart — see the header. */
|
|
343
|
+
async #saveProjection(agentId, documentId, documentType, content) {
|
|
344
|
+
const path = this.#projectionPath(agentId, documentId, documentType);
|
|
345
|
+
await mkdir(join(this.#root, ".cello", agentId), { recursive: true });
|
|
346
|
+
await writeFile(`${path}.tmp`, content, "utf8");
|
|
347
|
+
await rename(`${path}.tmp`, path);
|
|
348
|
+
}
|
|
349
|
+
async #loadProjection(agentId, documentId, documentType) {
|
|
350
|
+
try {
|
|
351
|
+
return await readFile(this.#projectionPath(agentId, documentId, documentType), "utf8");
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async #readOrRefuse(path, documentId) {
|
|
358
|
+
try {
|
|
359
|
+
return await readFile(path, "utf8");
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
throw new DocumentWriteError("document_file_missing", `no materialized file for document ${documentId} at ${path} — materialize it before publishing`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
#assertSupported(documentType) {
|
|
366
|
+
if (!TEXT_TYPES.has(documentType) && !JSON_TYPES.has(documentType)) {
|
|
367
|
+
throw new DocumentWriteError("document_type_unsupported", `no diff strategy for '${documentType}' — supported types are ${[...TEXT_TYPES, ...JSON_TYPES].join(", ")}`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
#assertId(value, field) {
|
|
371
|
+
if (!ID_PATTERN.test(value)) {
|
|
372
|
+
throw new DocumentWriteError("document_id_invalid", `${field} must be 64 lowercase hex characters — it becomes a path component, and an ` +
|
|
373
|
+
`unvalidated one escapes the workspace`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Line-level hunks between two texts, as character offsets into `before`.
|
|
379
|
+
*
|
|
380
|
+
* Lines are represented as CHUNKS — each line carries its own trailing newline, except the last,
|
|
381
|
+
* which does not. That representation is what makes newline handling fall out instead of being
|
|
382
|
+
* special-cased: appending a line to "a\nb" turns the chunk "b" into "b\n" + "c", so the LCS
|
|
383
|
+
* sees the last line as changed and the hunk replaces "b" with "b\nc". A hand-rolled
|
|
384
|
+
* prefix/suffix trim got this wrong for every edit that changed the line count — measured, four
|
|
385
|
+
* of six ordinary markdown edits published text that was not what the file said.
|
|
386
|
+
*
|
|
387
|
+
* A real LCS (not a prefix/suffix trim) is required because the whole point is to emit SEPARATE
|
|
388
|
+
* hunks for separated edits: one span from the first change to the last would delete and
|
|
389
|
+
* re-insert everything between them as new operations, resurrecting text a peer concurrently
|
|
390
|
+
* deleted. Under publish-on-intent, multi-edit publishes are the modal case.
|
|
391
|
+
*/
|
|
392
|
+
export function lineHunks(before, after) {
|
|
393
|
+
if (before === after)
|
|
394
|
+
return [];
|
|
395
|
+
const a = toChunks(before);
|
|
396
|
+
const b = toChunks(after);
|
|
397
|
+
const runs = lineRuns(a, b);
|
|
398
|
+
if (runs === null) {
|
|
399
|
+
// Above the LCS limit — one hunk, and the caller is not misled into thinking this is a
|
|
400
|
+
// measurement of what changed.
|
|
401
|
+
return [{ from: 0, to: before.length, insert: after }];
|
|
402
|
+
}
|
|
403
|
+
const offsets = [0];
|
|
404
|
+
for (const chunk of a)
|
|
405
|
+
offsets.push(offsets[offsets.length - 1] + chunk.length);
|
|
406
|
+
return runs.map((r) => ({
|
|
407
|
+
from: offsets[r.aStart],
|
|
408
|
+
to: offsets[r.aEnd],
|
|
409
|
+
insert: b.slice(r.bStart, r.bEnd).join(""),
|
|
410
|
+
}));
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=document-write-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-write-path.js","sourceRoot":"","sources":["../src/document-write-path.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The line LCS, shared by the write path (DOD-DOC-WRITE-1) and the diff surfaces
|
|
3
|
+
* (DOD-DOC-NOTIFY-1).
|
|
4
|
+
*
|
|
5
|
+
* One implementation, deliberately. These two need to agree about what changed — the write path
|
|
6
|
+
* publishes hunks and the diff surfaces describe them to an operator — and two hand-rolled diffs
|
|
7
|
+
* that must agree are two things to keep in step, which is how they stop agreeing.
|
|
8
|
+
*
|
|
9
|
+
* ── WHY A REAL LCS AND NOT A PREFIX/SUFFIX TRIM ───────────────────────────────────────────────
|
|
10
|
+
*
|
|
11
|
+
* Measured twice, in two units, with the same result. A prefix/suffix trim is correct only when
|
|
12
|
+
* exactly one contiguous region changed; the moment a line is INSERTED or DELETED, everything after
|
|
13
|
+
* it shifts and a naive positional walk reports the whole remainder as rewritten:
|
|
14
|
+
*
|
|
15
|
+
* inserting one line at the top of a 3-line file -> +4 -3, one range covering the file
|
|
16
|
+
*
|
|
17
|
+
* In the write path (WRITE-1) that published text the file did not contain — four of six ordinary
|
|
18
|
+
* markdown edits. In the diff surfaces (NOTIFY-1) it made the overlap flag permanently true, which
|
|
19
|
+
* is worse than useless: the flag exists so an agent can tell whether the peer touched what it
|
|
20
|
+
* touched, and one that always says yes trains the agent to ignore it.
|
|
21
|
+
*
|
|
22
|
+
* A real LCS is also what emits SEPARATE runs for separated edits. One span from the first change
|
|
23
|
+
* to the last would delete and re-insert everything between them as new operations, resurrecting
|
|
24
|
+
* text a peer concurrently deleted — and under publish-on-intent, multi-edit publishes are the
|
|
25
|
+
* modal case.
|
|
26
|
+
*/
|
|
27
|
+
/** Above this many lines the table is not worth building — the caller falls back and says so. */
|
|
28
|
+
export declare const LCS_LINE_LIMIT = 4000;
|
|
29
|
+
/**
|
|
30
|
+
* A contiguous run of changed lines, as HALF-OPEN index ranges into each side.
|
|
31
|
+
*
|
|
32
|
+
* `aStart === aEnd` is a pure insertion; `bStart === bEnd` is a pure deletion. Half-open because
|
|
33
|
+
* the empty range then has an unambiguous spelling, which a closed range does not.
|
|
34
|
+
*/
|
|
35
|
+
export interface LineRun {
|
|
36
|
+
aStart: number;
|
|
37
|
+
aEnd: number;
|
|
38
|
+
bStart: number;
|
|
39
|
+
bEnd: number;
|
|
40
|
+
}
|
|
41
|
+
/** Lines carrying their own trailing newline; the last line carries none. */
|
|
42
|
+
export declare function toChunks(text: string): string[];
|
|
43
|
+
/**
|
|
44
|
+
* The runs of changed lines between two chunk arrays.
|
|
45
|
+
*
|
|
46
|
+
* Returns `null` when either side exceeds `LCS_LINE_LIMIT` — the quadratic table on a document
|
|
47
|
+
* that large is the wrong kind of thorough, and a caller that silently degraded instead of being
|
|
48
|
+
* told would report a whole-file rewrite as if it were a measurement.
|
|
49
|
+
*/
|
|
50
|
+
export declare function lineRuns(a: readonly string[], b: readonly string[]): LineRun[] | null;
|
|
51
|
+
//# sourceMappingURL=line-lcs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line-lcs.d.ts","sourceRoot":"","sources":["../src/line-lcs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,iGAAiG;AACjG,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAG/C;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CA8BrF"}
|