@mengine/medeo-client 1.0.1-alpha.1 → 1.0.1
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/{index-DRUGsbm2.d.ts → index-DLchEQG7.d.ts} +723 -112
- package/dist/index.d.ts +562 -75
- package/dist/index.js +1307 -145
- package/dist/{document-DgffKwRw.js → loro-relay-doc-Br-ZJBHa.js} +136 -134
- package/dist/testing.d.ts +16 -1
- package/dist/testing.js +57 -6
- package/package.json +4 -7
- package/dist/index-6e5cbdM3.d.ts +0 -475
- package/dist/schemas.d.ts +0 -2
- package/dist/schemas.js +0 -378
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { PeerID } from "loro-crdt";
|
|
1
|
+
import { $ as VideoDraft, A as assertValidVideoDocument, B as PartKind, C as index_d_exports, D as VideoDocumentMirrorSchema, E as VideoDocumentDraft, F as derivePositionFromAbs, G as TrackItem, H as SpeechPart, I as fromVideoDocument, J as VideoClipPart, K as TrackItemTimePosition, L as toVideoDocument, M as DerivedItemPosition, N as SpeechHostMap, O as videoDocumentMirrorSchema, P as buildSpeechHostMap, Q as VideoDocumentValidationIssueCode, R as BgmPart, S as ValidationError, T as TrackItemDraft, U as Timeline, V as PartUnion, W as Track, X as VideoDocumentSchemaVersion, Y as VideoDocument, Z as VideoDocumentValidationIssue, _ as PlannedSemanticOpKind, a as MirrorVideoDocumentOptions, at as SpeedShift, b as SchemaValidator, c as CommitOptions, ct as TrackItem$1, d as SemanticEditor, et as VideoDraftPartUnion, f as SemanticOpInput, g as ImplementedSemanticOpKind, h as IMPLEMENTED_SEMANTIC_OP_KINDS, i as MirrorVideoDocumentAdapter, it as PartAggregation, j as validateVideoDocument, k as VideoDocumentValidationError, l as OpActor, m as TransactAudit, n as videoDocumentSchema, nt as CaptionPart$1, o as createMirrorVideoDocument, ot as Timeline$1, p as SemanticOpName, q as VIDEO_DOCUMENT_SCHEMA_VERSION, r as readVideoDocumentFromDraft, rt as CaptionStyle, s as createMirrorVideoDocumentAdapter, st as Track$1, t as partUnionSchema, tt as Attachment, u as SemanticDocumentAdapter, v as SemanticOpKind, w as TrackDraft, x as SnapshotReadable, y as isImplementedSemanticOpKind, z as CaptionPart } from "./index-DLchEQG7.js";
|
|
2
|
+
import { LoroDoc, PeerID, VersionVector } from "loro-crdt";
|
|
4
3
|
import { DocState } from "@mengine/sync";
|
|
5
4
|
import { BaseDocStorage, Connection, DocDiff, DocSnapshotRecord, DocStorage, DocStorageOptions, DocUpdate, DocUpdateRecord } from "@mengine/storage";
|
|
6
5
|
|
|
@@ -25,6 +24,16 @@ interface MengineUpdateMeta {
|
|
|
25
24
|
semantic_op: string | null;
|
|
26
25
|
payload: unknown;
|
|
27
26
|
intent: string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Who authored the op, as recorded in the Loro commit message (see `OpActor`).
|
|
29
|
+
* Null for writes with no acting user — bootstrap, repair — and for Changes
|
|
30
|
+
* written before attribution existed. Self-reported by the authoring client;
|
|
31
|
+
* the server does not verify it against the request identity.
|
|
32
|
+
*/
|
|
33
|
+
actor: {
|
|
34
|
+
user_id: string;
|
|
35
|
+
role: string;
|
|
36
|
+
} | null;
|
|
28
37
|
message: string | null;
|
|
29
38
|
parse_error: boolean;
|
|
30
39
|
peer: string;
|
|
@@ -99,6 +108,26 @@ declare class MengineHttpRequestError extends Error {
|
|
|
99
108
|
readonly payload: unknown;
|
|
100
109
|
constructor(status: number, payload: unknown);
|
|
101
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* A push the server refused on its merits (`kind: 'rejected'`), as opposed to a
|
|
113
|
+
* transport failure. Carries the server's machine `code` so callers can branch on
|
|
114
|
+
* *why* rather than on an HTTP status:
|
|
115
|
+
*
|
|
116
|
+
* - `missing_dependency` (server answers 409) — retryable: the update depends on
|
|
117
|
+
* ops the server log lacks, so catching up and re-exporting resolves it.
|
|
118
|
+
* - `corrupt_update` (server answers 422) — never valid, retrying cannot help.
|
|
119
|
+
*
|
|
120
|
+
* Distinct from {@link MengineHttpRequestError} (transport/status-level failure)
|
|
121
|
+
* and from a raw `fetch` rejection (network down): the three are separate classes
|
|
122
|
+
* so a caller can tell "the server said no" from "the server never answered".
|
|
123
|
+
*/
|
|
124
|
+
declare class MenginePushRejectedError extends Error {
|
|
125
|
+
readonly code: string;
|
|
126
|
+
readonly serverMessage: string;
|
|
127
|
+
readonly serverVersion: MengineDocumentVersion | undefined;
|
|
128
|
+
readonly status: number | undefined;
|
|
129
|
+
constructor(code: string, serverMessage: string, serverVersion: MengineDocumentVersion | undefined, status: number | undefined);
|
|
130
|
+
}
|
|
102
131
|
declare class MengineHttpClient {
|
|
103
132
|
private readonly options;
|
|
104
133
|
private readonly fetchImpl;
|
|
@@ -113,7 +142,24 @@ declare class MengineHttpClient {
|
|
|
113
142
|
sync(fromVV?: Uint8Array): Promise<MengineSyncResponse>;
|
|
114
143
|
/** Audit trail: extracted metadata per accepted update, in log order. */
|
|
115
144
|
audit(): Promise<MengineAuditResponse>;
|
|
116
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Append one Loro update to the server log.
|
|
147
|
+
*
|
|
148
|
+
* Resolves for both accepted outcomes and hands the verdict back verbatim —
|
|
149
|
+
* `ack` (appended, `update_seq` allocated) and `duplicate` (already known, no
|
|
150
|
+
* row appended). A `duplicate` is NOT an error, but it is also not an ack: it
|
|
151
|
+
* means the bytes contributed nothing, so a caller waiting for its own write to
|
|
152
|
+
* land must be able to tell them apart. Hence the verdict is returned rather
|
|
153
|
+
* than collapsed into `void`.
|
|
154
|
+
*
|
|
155
|
+
* Rejections raise {@link MenginePushRejectedError} carrying the server's
|
|
156
|
+
* machine `code`. The server answers them with 409/422, so the failure arrives
|
|
157
|
+
* as a non-ok response; this method re-reads the parsed body to recover `code` /
|
|
158
|
+
* `server_version` instead of leaving the caller a bare status. Transport-level
|
|
159
|
+
* failures stay {@link MengineHttpRequestError}, and a dead network keeps
|
|
160
|
+
* surfacing as the underlying `fetch` rejection.
|
|
161
|
+
*/
|
|
162
|
+
pushUpdate(update: Uint8Array): Promise<MenginePushUpdateResponse>;
|
|
117
163
|
eventsUrl(): string;
|
|
118
164
|
headers(): Headers;
|
|
119
165
|
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
@@ -131,23 +177,33 @@ interface MengineEventStreamOptions {
|
|
|
131
177
|
}
|
|
132
178
|
declare function readMengineEventStream(options: MengineEventStreamOptions): Promise<void>;
|
|
133
179
|
//#endregion
|
|
134
|
-
//#region src/editor/
|
|
180
|
+
//#region src/editor/id-gen.d.ts
|
|
135
181
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
182
|
+
* Part-id generation, aligned with the online ecosystem.
|
|
183
|
+
*
|
|
184
|
+
* The authoritative online producers — agent-harness (`@harness/shared`
|
|
185
|
+
* `genObjId`) and director.v2 (`common/obj_id.py` `gen_obj_id`) — both mint part
|
|
186
|
+
* ids as `` `${prefix}_${ulid()}` ``, and real captured drafts use exactly that
|
|
187
|
+
* shape (`clip_…` / `spe_…` / `cap_…` / `bgm_…`, each a 26-char ULID). The engine
|
|
188
|
+
* previously emitted `vc_<base36 timestamp><6 random>`, a different prefix AND a
|
|
189
|
+
* different encoding — the sole cross-repo id divergence. This module removes it
|
|
190
|
+
* by emitting the same `<prefix>_<ULID>` bytes.
|
|
191
|
+
*
|
|
192
|
+
* The ULID is generated inline (Crockford Base32, 48-bit time + 80-bit random)
|
|
193
|
+
* rather than pulling the `ulid` npm package: the randomness class matches the
|
|
194
|
+
* old generator (both `Math.random`-based) and it keeps `@mengine/medeo-client`
|
|
195
|
+
* dependency-free for a purely mechanical id string. Part ids only need to be
|
|
196
|
+
* unique and lexicographically time-sortable, which this satisfies.
|
|
138
197
|
*/
|
|
139
|
-
declare function createEditSandbox(document: VideoDocument, options?: PlainMemoryAdapterOptions): {
|
|
140
|
-
adapter: PlainMemoryAdapter;
|
|
141
|
-
editor: SemanticEditor;
|
|
142
|
-
journal: readonly JournalEntry[];
|
|
143
|
-
};
|
|
144
198
|
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* `
|
|
199
|
+
* Online part-id semantic prefixes. `clip` (video clip) is the only value the
|
|
200
|
+
* engine currently mints (see `addVideoClips`); the rest are declared so the
|
|
201
|
+
* type documents the shared vocabulary and guards against reintroducing the old
|
|
202
|
+
* `vc`/`sp`/`cp`/`bg` names. Speech/caption/bgm ids arrive pre-minted in op
|
|
203
|
+
* payloads, so the engine never generates them itself.
|
|
149
204
|
*/
|
|
150
|
-
|
|
205
|
+
type PartIdPrefix = 'clip' | 'spe' | 'cap' | 'bgm' | 'ti';
|
|
206
|
+
declare function generatePartId(prefix: PartIdPrefix): string;
|
|
151
207
|
//#endregion
|
|
152
208
|
//#region src/editor/snapshot-utils.d.ts
|
|
153
209
|
/** Main-track item identity read from a raw snapshot (only `part_id` is needed). */
|
|
@@ -171,6 +227,414 @@ declare function readPart(snapshot: unknown, partId: string): (Record<string, un
|
|
|
171
227
|
part_kind?: PartKind;
|
|
172
228
|
}) | null;
|
|
173
229
|
//#endregion
|
|
230
|
+
//#region src/manual-sync/types.d.ts
|
|
231
|
+
/**
|
|
232
|
+
* Opaque marker for "the document state I last looked at".
|
|
233
|
+
*
|
|
234
|
+
* Deliberately not a number. Under mengine there is no monotonic document
|
|
235
|
+
* version to compare: `meta.version` is stamped once at legacy ingest and then
|
|
236
|
+
* frozen, and the server's `update_seq` counts every writer's pushes, so neither
|
|
237
|
+
* can answer "has this document changed since I last read it". The answer comes
|
|
238
|
+
* from comparing version vectors.
|
|
239
|
+
*
|
|
240
|
+
* Opaque means: no arithmetic, no ordering, no comparison other than handing it
|
|
241
|
+
* back to {@link ManualSyncDoc.hasChangedSince}. Two version vectors are only
|
|
242
|
+
* partially ordered — concurrent ones are neither greater nor equal, and Loro's
|
|
243
|
+
* own `compare` returns `undefined` for them — so `mark1 > mark2` or sorting a
|
|
244
|
+
* list of marks has no meaning to get wrong.
|
|
245
|
+
*
|
|
246
|
+
* Persisting one IS supported, via {@link encodeDocVersionMark} /
|
|
247
|
+
* {@link decodeDocVersionMark}. Storing an opaque blob and reading it back does
|
|
248
|
+
* not order or compute anything, and callers that compare across turns (rather
|
|
249
|
+
* than within one process) need it: the legacy integer version this replaces was
|
|
250
|
+
* itself persisted between agent turns.
|
|
251
|
+
*/
|
|
252
|
+
interface DocVersionMark {
|
|
253
|
+
readonly __brand: 'mengine-doc-version-mark';
|
|
254
|
+
/** Encoded oplog `VersionVector` at the moment the mark was taken. */
|
|
255
|
+
readonly encoded: Uint8Array;
|
|
256
|
+
}
|
|
257
|
+
/** Why a `pull()` did not complete. Mirrors the push failure taxonomy. */
|
|
258
|
+
type PullFailureReason = 'failed';
|
|
259
|
+
/**
|
|
260
|
+
* Result of a `pull()`.
|
|
261
|
+
*
|
|
262
|
+
* `ok: false` is a first-class outcome, not an exception: per the M2/A ruling a
|
|
263
|
+
* failed pull must not hard-fail the tool call, matching legacy's tolerance for
|
|
264
|
+
* read failures (`getDraftVersion` swallows to null, `DraftVersionDetector`
|
|
265
|
+
* catches and skips). The caller decides whether to proceed on a possibly-stale
|
|
266
|
+
* document, so the degradation has to be visible in the return value.
|
|
267
|
+
*/
|
|
268
|
+
type PullResult = {
|
|
269
|
+
ok: true; /** True when the pull actually advanced the local document. */
|
|
270
|
+
changed: boolean;
|
|
271
|
+
} | {
|
|
272
|
+
ok: false;
|
|
273
|
+
reason: PullFailureReason;
|
|
274
|
+
error: Error;
|
|
275
|
+
};
|
|
276
|
+
/**
|
|
277
|
+
* What the server did with a `push()`.
|
|
278
|
+
*
|
|
279
|
+
* The first four mirror the server's verdict taxonomy (see `PushOutcomeKind`);
|
|
280
|
+
* `nothing_to_push` is a local short-circuit — no request was made because the
|
|
281
|
+
* document holds no ops the server lacks.
|
|
282
|
+
*/
|
|
283
|
+
type PushResultKind = 'ack' | 'duplicate' | 'rejected' | 'failed' | 'nothing_to_push';
|
|
284
|
+
/**
|
|
285
|
+
* Result of a `push()`.
|
|
286
|
+
*
|
|
287
|
+
* `collaborated` is the load-bearing field. The legacy Drizzle path fails loudly
|
|
288
|
+
* on concurrent writes (`Optimistic lock failed`); mengine merges silently by
|
|
289
|
+
* design (M0/S2 accepted CRDT merge semantics). Migrating without surfacing this
|
|
290
|
+
* would replace a path that reports conflicts with one that hides them, so every
|
|
291
|
+
* successful push says whether the server held ops the local document did not.
|
|
292
|
+
*
|
|
293
|
+
* Its meaning is "the server has ops you don't", NOT "there was a conflict" — the
|
|
294
|
+
* same user's other browser tab counts. It is therefore suitable for driving a
|
|
295
|
+
* re-pull and for informing the caller, but not for raising an alarm on its own.
|
|
296
|
+
*/
|
|
297
|
+
interface PushResult {
|
|
298
|
+
kind: PushResultKind;
|
|
299
|
+
/** Server-allocated sequence number; only present for `ack`. */
|
|
300
|
+
updateSeq?: number | undefined;
|
|
301
|
+
/** Whether the server held ops the local document lacked. See above. */
|
|
302
|
+
collaborated: boolean;
|
|
303
|
+
/** Server machine code for `rejected` (`missing_dependency` / `corrupt_update`). */
|
|
304
|
+
code?: string | undefined;
|
|
305
|
+
/** Underlying error for `rejected` / `failed`. */
|
|
306
|
+
error?: Error | undefined;
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/manual-sync/doc-version-mark.d.ts
|
|
310
|
+
/**
|
|
311
|
+
* Encode a {@link DocVersionMark} for storage or transport.
|
|
312
|
+
*
|
|
313
|
+
* The mark stays opaque across the round trip — the string is not a version
|
|
314
|
+
* number and must not be compared, ordered, or parsed. Its only use is
|
|
315
|
+
* {@link decodeDocVersionMark} followed by `hasChangedSince`.
|
|
316
|
+
*
|
|
317
|
+
* Callers that persist this should know the encoded length grows with the number
|
|
318
|
+
* of peers that have ever written to the document (one counter each), and the FE
|
|
319
|
+
* mints a fresh peer per page load. Still small in practice (a few hundred bytes
|
|
320
|
+
* for dozens of peers), but it grows with document age rather than size; version
|
|
321
|
+
* vector compaction is deferred to a later phase.
|
|
322
|
+
*/
|
|
323
|
+
declare function encodeDocVersionMark(mark: DocVersionMark): string;
|
|
324
|
+
/**
|
|
325
|
+
* Rebuild a mark from {@link encodeDocVersionMark}'s output.
|
|
326
|
+
*
|
|
327
|
+
* Returns `undefined` for input this did not produce (a legacy integer version,
|
|
328
|
+
* a truncated value, an empty string). That is the honest answer — "I cannot
|
|
329
|
+
* establish what you last saw" — and callers should treat it as "no baseline"
|
|
330
|
+
* rather than as "unchanged". Decoding does not validate the bytes as a version
|
|
331
|
+
* vector; `hasChangedSince` reports "changed" for an undecodable mark, which is
|
|
332
|
+
* the conservative direction.
|
|
333
|
+
*/
|
|
334
|
+
declare function decodeDocVersionMark(encoded: string): DocVersionMark | undefined;
|
|
335
|
+
//#endregion
|
|
336
|
+
//#region src/manual-sync/manual-sync-doc.d.ts
|
|
337
|
+
interface ManualSyncDocOptions {
|
|
338
|
+
client: MengineHttpClient;
|
|
339
|
+
/**
|
|
340
|
+
* Peer id for this writer. Every writer needs a distinct one: two writers
|
|
341
|
+
* sharing a peer and branching from the same base emit identical
|
|
342
|
+
* `(peer, counter)` pairs, the server classifies the second as `duplicate` and
|
|
343
|
+
* drops it, and the write is silently lost. Callers mint a random one (see the
|
|
344
|
+
* harness's `mintHarnessPeerId`).
|
|
345
|
+
*/
|
|
346
|
+
peerId?: PeerID;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Agent-facing document with explicit `pull()` / `push()` over one Loro
|
|
350
|
+
* document, with no background sync (ADR 0015 D1–D4).
|
|
351
|
+
*
|
|
352
|
+
* It deliberately does NOT reuse `MengineDocSession`'s stack. That stack —
|
|
353
|
+
* SSE + local `DocStorage` + `ClientServerSynchronizer` + `DocManager` — is
|
|
354
|
+
* correct for a browser editor and actively wrong here:
|
|
355
|
+
*
|
|
356
|
+
* - Its retry backoff lands *outside* the tool-call lifetime, so a write can
|
|
357
|
+
* settle seconds after the tool already told the LLM what happened.
|
|
358
|
+
* - It has no durable local queue in the harness, so pending pushes die with the
|
|
359
|
+
* process — that is lost data, reported as success.
|
|
360
|
+
* - Agent semantics require the document to change only at points the agent can
|
|
361
|
+
* name. If it converged on its own between tool calls, "what state was this
|
|
362
|
+
* decision based on" would be unanswerable, and a remote change could land
|
|
363
|
+
* mid-edit.
|
|
364
|
+
*
|
|
365
|
+
* What replaces the whole background job queue is one variable: the **watermark**,
|
|
366
|
+
* the version the server has confirmed. `push()` exports `{mode:'update', from:
|
|
367
|
+
* watermark}` and only advances it on a confirmed verdict, so a failed push is
|
|
368
|
+
* retried implicitly — the next push carries both the failed ops and any new
|
|
369
|
+
* ones, in one blob. No queue, no timer, no retry bookkeeping.
|
|
370
|
+
*
|
|
371
|
+
* Two non-obvious properties of that watermark, both verified against a real
|
|
372
|
+
* server in the ADR 0015 spike:
|
|
373
|
+
*
|
|
374
|
+
* - It can legitimately *lead* the local document (it carries other peers'
|
|
375
|
+
* counters). Exporting `from` a leading watermark does not error; the blob
|
|
376
|
+
* correctly contains only the local peer's new ops. So a collaborative merge
|
|
377
|
+
* does not force a pull before pushing.
|
|
378
|
+
* - Therefore every emptiness/coverage test must be one-directional containment,
|
|
379
|
+
* never equality. See {@link covers}.
|
|
380
|
+
*
|
|
381
|
+
* Lifecycle: one `LoroDoc` per document, shared across agent loops with a
|
|
382
|
+
* refcount held by the caller's session registry. Rebuilding the doc per tool
|
|
383
|
+
* call would mint a new peer each time and permanently inflate the document's
|
|
384
|
+
* version vector for every future reader.
|
|
385
|
+
*
|
|
386
|
+
* Not thread-safe by design and it does not need to be: harness tool calls run
|
|
387
|
+
* serially (`execToolCalls` is a `for` + `await`).
|
|
388
|
+
*/
|
|
389
|
+
declare class ManualSyncDoc {
|
|
390
|
+
private readonly client;
|
|
391
|
+
private readonly doc;
|
|
392
|
+
private readonly adapter;
|
|
393
|
+
readonly editor: SemanticEditor;
|
|
394
|
+
/**
|
|
395
|
+
* The version the server is known to hold. Starts empty (nothing confirmed)
|
|
396
|
+
* and only ever moves forward on a verdict that proves the server took our ops.
|
|
397
|
+
*/
|
|
398
|
+
private watermark;
|
|
399
|
+
private constructor();
|
|
400
|
+
/**
|
|
401
|
+
* Open an existing server document.
|
|
402
|
+
*
|
|
403
|
+
* Fetches the snapshot up front rather than starting empty and converging: the
|
|
404
|
+
* agent's first act is to read the document, so there is no useful state before
|
|
405
|
+
* the snapshot lands. This also fails fast and loudly on a document that does
|
|
406
|
+
* not exist, instead of `MengineDocSession.waitForContent()`'s behavior of
|
|
407
|
+
* waiting forever for content that will never arrive.
|
|
408
|
+
*/
|
|
409
|
+
static open(options: ManualSyncDocOptions): Promise<ManualSyncDoc>;
|
|
410
|
+
/** Current document read model (authoritative shape). */
|
|
411
|
+
snapshot(): VideoDocument;
|
|
412
|
+
/**
|
|
413
|
+
* The Loro peer this document writes as.
|
|
414
|
+
*
|
|
415
|
+
* Exposed because the peer is an externally-meaningful fact, not an internal
|
|
416
|
+
* detail: it is the identity every op this document emits is attributed to, and
|
|
417
|
+
* callers mint it under rules of their own (the harness reserves a range so a
|
|
418
|
+
* peer id alone says "Agent wrote this"). Being able to read it back means those
|
|
419
|
+
* rules can be verified against the live document rather than against whatever
|
|
420
|
+
* was passed to the constructor.
|
|
421
|
+
*/
|
|
422
|
+
editorPeerId(): PeerID;
|
|
423
|
+
/** Current document projected to the legacy `VideoDraft` read shape. */
|
|
424
|
+
draft(): VideoDraft;
|
|
425
|
+
/**
|
|
426
|
+
* Mark the document state the caller has just observed, for a later
|
|
427
|
+
* {@link hasChangedSince}.
|
|
428
|
+
*
|
|
429
|
+
* This pair replaces the legacy integer-version comparison that
|
|
430
|
+
* `DraftVersionDetector` used to tell the LLM "the draft was modified
|
|
431
|
+
* externally, reload before editing". Under mengine `meta.version` never
|
|
432
|
+
* changes, so that detector would go permanently silent; comparing version
|
|
433
|
+
* vectors restores the same capability.
|
|
434
|
+
*
|
|
435
|
+
* Same capability, not a stronger one: like the legacy detector, this only
|
|
436
|
+
* reports what changed between two moments the caller chose to sample.
|
|
437
|
+
*/
|
|
438
|
+
versionMark(): DocVersionMark;
|
|
439
|
+
/**
|
|
440
|
+
* Has the document moved since `mark` was taken?
|
|
441
|
+
*
|
|
442
|
+
* Reports any advance, whoever caused it — including this document's own edits.
|
|
443
|
+
* The caller decides what is interesting: a detector sampling once per turn is
|
|
444
|
+
* asking "did anything happen", and its own edits legitimately count.
|
|
445
|
+
*/
|
|
446
|
+
hasChangedSince(mark: DocVersionMark): boolean;
|
|
447
|
+
/**
|
|
448
|
+
* Fetch and merge everything the server has that this document lacks.
|
|
449
|
+
*
|
|
450
|
+
* Must run *before* the editor on each tool call. `SemanticEditor` validates
|
|
451
|
+
* against the local document, so editing a stale one validates against a world
|
|
452
|
+
* that no longer exists: the ADR 0015 spike confirmed that without pull-first
|
|
453
|
+
* an edit to a clip another writer had already deleted passes validation and is
|
|
454
|
+
* accepted by the server. Pulling afterwards cannot undo that.
|
|
455
|
+
*
|
|
456
|
+
* A failure is returned, not thrown — a transient network blip must not make
|
|
457
|
+
* the tool unusable (M2/A ruling; legacy tolerates read failures the same way).
|
|
458
|
+
* The caller proceeds on a possibly-stale document knowingly.
|
|
459
|
+
*/
|
|
460
|
+
pull(): Promise<PullResult>;
|
|
461
|
+
/**
|
|
462
|
+
* Push every local op the server has not confirmed, and report the verdict.
|
|
463
|
+
*
|
|
464
|
+
* The return value is the durability answer a tool needs before claiming
|
|
465
|
+
* success: only `ack` / `duplicate` mean the server holds the ops. This is why
|
|
466
|
+
* this class exists rather than an ack-waiter — with a direct call, "did it
|
|
467
|
+
* land" is simply the result.
|
|
468
|
+
*
|
|
469
|
+
* `duplicate` counts as durable: the bytes added nothing *because* the server
|
|
470
|
+
* already had them.
|
|
471
|
+
*/
|
|
472
|
+
push(): Promise<PushResult>;
|
|
473
|
+
/** Decode a wire `server_vv`, tolerating absence/corruption (never throws). */
|
|
474
|
+
private serverVVFrom;
|
|
475
|
+
}
|
|
476
|
+
//#endregion
|
|
477
|
+
//#region src/manual-sync/version-coverage.d.ts
|
|
478
|
+
/**
|
|
479
|
+
* Version-vector coverage: "does `outer` contain everything in `inner`?"
|
|
480
|
+
*
|
|
481
|
+
* This one predicate answers three different questions in the manual-sync document, which
|
|
482
|
+
* is why it is factored out rather than inlined three times:
|
|
483
|
+
*
|
|
484
|
+
* | question | call |
|
|
485
|
+
* | ------------------------------------- | ------------------------------- |
|
|
486
|
+
* | is there anything left to push? | `covers(watermark, localOplog)` |
|
|
487
|
+
* | did someone else write concurrently? | `covers(localOplog, serverVV)` |
|
|
488
|
+
* | has the doc moved since I last read? | `covers(seenVersion, localOplog)`|
|
|
489
|
+
*
|
|
490
|
+
* `VersionVector.compare` cannot be used for any of them: it returns `undefined`
|
|
491
|
+
* for concurrent vectors, and concurrency is the NORMAL case here — the server
|
|
492
|
+
* routinely holds peers the local doc has never seen, and after a collaborative
|
|
493
|
+
* merge the local doc holds ops the watermark predates. Treating "concurrent" as
|
|
494
|
+
* "not covered" is right for some of these and wrong for others, so the per-peer
|
|
495
|
+
* counter check is the only formulation that stays correct for all three.
|
|
496
|
+
*
|
|
497
|
+
* Equality must NOT be used as a substitute either: once collaboration happens
|
|
498
|
+
* the watermark legitimately *leads* the local doc (it carries other peers'
|
|
499
|
+
* counters), so an equality test reports "still has ops to push" forever.
|
|
500
|
+
*/
|
|
501
|
+
declare function covers(outer: VersionVector, inner: VersionVector): boolean;
|
|
502
|
+
//#endregion
|
|
503
|
+
//#region src/relay/loro-relay-doc.d.ts
|
|
504
|
+
/**
|
|
505
|
+
* Loro OpLog-relay primitives: the doc shape and update classification an update
|
|
506
|
+
* *host* needs, as opposed to an editing client.
|
|
507
|
+
*
|
|
508
|
+
* A relay never materializes DocState (`docs/concepts/oplog_docstate` §Relay
|
|
509
|
+
* Server) — it keeps a detached `LoroDoc` that validates and accumulates updates
|
|
510
|
+
* and exports diffs by version vector.
|
|
511
|
+
*
|
|
512
|
+
* These live in `medeo-client` rather than in `mengine-server` because two
|
|
513
|
+
* separate hosts must classify identically: the real server (`apps/mengine-server`,
|
|
514
|
+
* both storage implementations) and the in-process test double
|
|
515
|
+
* (`testing/in-memory-mengine-server.ts`) that client-side tests push against. A
|
|
516
|
+
* double with its own verdict logic drifts from the server it stands in for, and
|
|
517
|
+
* the four push outcomes it produces are exactly what those tests assert on — so
|
|
518
|
+
* the classification is shared code, not duplicated code.
|
|
519
|
+
*/
|
|
520
|
+
/** Build a fresh detached relay doc (no DocState materialization). */
|
|
521
|
+
declare function newRelayDoc(): LoroDoc;
|
|
522
|
+
/** Load a detached relay doc from a stored snapshot. */
|
|
523
|
+
declare function relayDocFromSnapshot(snapshot: Uint8Array): LoroDoc;
|
|
524
|
+
type ImportVerdict = 'accepted' | 'duplicate' | 'corrupt_update' | 'missing_dependency';
|
|
525
|
+
/**
|
|
526
|
+
* Classify an incoming update against `doc` without mutating it.
|
|
527
|
+
*
|
|
528
|
+
* Deliberately version-delta based, not `ImportStatus`-shape based: in loro-crdt
|
|
529
|
+
* 1.13.x the JS `import()` returns `success`/`pending` as objects whose ranges
|
|
530
|
+
* are not reliably populated, and a pending (out-of-order) import still buffers
|
|
531
|
+
* the orphan op into the oplog. So this imports into a throwaway snapshot-clone
|
|
532
|
+
* and inspects whether the oplog frontiers advanced — letting the caller import
|
|
533
|
+
* into its canonical doc only on `accepted`, keeping orphan bytes out of the log.
|
|
534
|
+
*/
|
|
535
|
+
declare function classifyUpdate(doc: LoroDoc, update: Uint8Array): ImportVerdict;
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/storage/medeo-http-doc-storage.d.ts
|
|
538
|
+
interface MedeoHttpDocStorageOptions {
|
|
539
|
+
docId: string;
|
|
540
|
+
client: MengineHttpClient;
|
|
541
|
+
sseReconnectDelayMs?: number;
|
|
542
|
+
readonlyMode?: boolean;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* What the server did with one pushed update, as observed by this storage.
|
|
546
|
+
*
|
|
547
|
+
* `ack` / `duplicate` mirror the server verdict. `rejected` is a refusal on the
|
|
548
|
+
* merits (carrying the machine `code`: `missing_dependency` is retryable after
|
|
549
|
+
* catch-up, `corrupt_update` never is). `failed` is everything else — transport
|
|
550
|
+
* error, non-2xx status, dead network — i.e. the server's answer is unknown.
|
|
551
|
+
*
|
|
552
|
+
* The four are kept distinct because the recovery differs per case, and because
|
|
553
|
+
* the whole point of M1 is that a caller can tell "written" from "not written".
|
|
554
|
+
*/
|
|
555
|
+
type PushOutcomeKind = 'ack' | 'duplicate' | 'rejected' | 'failed';
|
|
556
|
+
interface PushOutcome {
|
|
557
|
+
kind: PushOutcomeKind;
|
|
558
|
+
/** The bytes this outcome describes — lets a waiter match its own update. */
|
|
559
|
+
update: Uint8Array;
|
|
560
|
+
/** Server-allocated sequence number; only present for `ack`. */
|
|
561
|
+
updateSeq?: number | undefined;
|
|
562
|
+
/**
|
|
563
|
+
* The server oplog version vector *after* handling this push (`ack` and
|
|
564
|
+
* `duplicate` both carry it; encoded `VersionVector`).
|
|
565
|
+
*
|
|
566
|
+
* This — not the pushed bytes — is what an "is my write durable" waiter should
|
|
567
|
+
* key on. The same ops can reach the server either as the individual blob the
|
|
568
|
+
* push job carried or as a merged `export({from: serverVV})` blob produced by
|
|
569
|
+
* the synchronizer's sync path, so byte identity is not a reliable match.
|
|
570
|
+
* Version coverage is, and it makes `duplicate` satisfy a waiter correctly: the
|
|
571
|
+
* bytes appended nothing precisely because the server already held them.
|
|
572
|
+
*/
|
|
573
|
+
serverVV?: Uint8Array | undefined;
|
|
574
|
+
/** Server machine code for `rejected` (e.g. `missing_dependency`). */
|
|
575
|
+
code?: string | undefined;
|
|
576
|
+
/** The underlying error for `rejected` / `failed`. */
|
|
577
|
+
error?: Error | undefined;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Adapts the mengine-server HTTP/SSE protocol to the engine `DocStorage`
|
|
581
|
+
* contract so `ClientServerSynchronizer` can treat it as a remote peer.
|
|
582
|
+
*
|
|
583
|
+
* Deliberately thin (mirrors the socket `DocStorage` in the playground): it
|
|
584
|
+
* forwards live SSE updates and exposes a version-vector diff, and keeps NO
|
|
585
|
+
* sync state of its own.
|
|
586
|
+
*
|
|
587
|
+
* - `getDocDiff(docId, knownVersion)` pulls the server-computed VV-diff via
|
|
588
|
+
* `GET /sync?from=<vv>` — the synchronizer passes the real `doc.version()`, so
|
|
589
|
+
* the response carries exactly the ops the doc is missing. `getDoc` (full
|
|
590
|
+
* `/snapshot`) stays for cold start, when the caller holds no version yet.
|
|
591
|
+
* - `pushDocUpdate` forwards a Loro update; the server appends it.
|
|
592
|
+
* - `subscribeDocUpdate` registers a callback for live SSE updates. It does no
|
|
593
|
+
* catch-up and keeps no cursor: after an SSE drop the connection reports a
|
|
594
|
+
* status change, and the synchronizer re-runs its cycle to catch up via
|
|
595
|
+
* `getDocDiff(doc.version())`. `LoroDoc.import` is idempotent (OpId/VV), so
|
|
596
|
+
* re-forwarded or echoed updates are harmless.
|
|
597
|
+
*
|
|
598
|
+
* It is bound to a single `docId` because `MengineHttpClient` is per-document.
|
|
599
|
+
*/
|
|
600
|
+
declare class MedeoHttpDocStorage implements DocStorage {
|
|
601
|
+
private readonly options;
|
|
602
|
+
readonly connection: Connection;
|
|
603
|
+
private readonly client;
|
|
604
|
+
private readonly docId;
|
|
605
|
+
private readonly events;
|
|
606
|
+
constructor(options: MedeoHttpDocStorageOptions);
|
|
607
|
+
get isReadonly(): boolean;
|
|
608
|
+
getDoc(docId: string): Promise<DocSnapshotRecord | null>;
|
|
609
|
+
getDocDiff(docId: string, knownVersion?: Uint8Array): Promise<DocDiff | null>;
|
|
610
|
+
/**
|
|
611
|
+
* Forward one update to the server.
|
|
612
|
+
*
|
|
613
|
+
* The `DocStorage` contract returns `void`, so the server's verdict cannot be
|
|
614
|
+
* the return value — it is published on {@link subscribePushOutcome} instead,
|
|
615
|
+
* for BOTH outcomes and failures. That channel is what makes the push
|
|
616
|
+
* observable; previously the verdict was read and dropped, so a `duplicate`
|
|
617
|
+
* (bytes contributed nothing) was indistinguishable from a successful write.
|
|
618
|
+
*
|
|
619
|
+
* The error is still rethrown after being published: the synchronizer treats a
|
|
620
|
+
* throw as "retry this cycle", and swallowing it here would strand the update.
|
|
621
|
+
* Publishing is therefore additive observability, not error handling.
|
|
622
|
+
*/
|
|
623
|
+
pushDocUpdate(update: DocUpdate, _origin: unknown): Promise<void>;
|
|
624
|
+
/**
|
|
625
|
+
* Observe the server's verdict for every pushed update, including failures.
|
|
626
|
+
*
|
|
627
|
+
* This is the loud channel the `void`-returning `DocStorage.pushDocUpdate`
|
|
628
|
+
* cannot express. Consumers that need "did my write land" (the agent's
|
|
629
|
+
* tool-level ack wait) subscribe here.
|
|
630
|
+
*/
|
|
631
|
+
subscribePushOutcome(callback: (outcome: PushOutcome) => void): () => void;
|
|
632
|
+
deleteDoc(_docId: string): Promise<void>;
|
|
633
|
+
subscribeDocUpdate(callback: (update: DocUpdate, origin: unknown) => void): () => void;
|
|
634
|
+
private assertDocId;
|
|
635
|
+
private emitUpdate;
|
|
636
|
+
}
|
|
637
|
+
//#endregion
|
|
174
638
|
//#region src/session/types.d.ts
|
|
175
639
|
/**
|
|
176
640
|
* Local storage contract the runtime depends on. Aliased to the engine
|
|
@@ -185,6 +649,30 @@ interface MengineDocSessionUpdateEvent {
|
|
|
185
649
|
source: 'remote' | 'local';
|
|
186
650
|
snapshot: VideoDocument;
|
|
187
651
|
}
|
|
652
|
+
/**
|
|
653
|
+
* Raised by {@link MengineDocSession.waitForServerAck} when the local edits it
|
|
654
|
+
* was asked to confirm did not reach the server in time, or were refused.
|
|
655
|
+
*
|
|
656
|
+
* The distinction the caller needs is "was it written": if this throws, treat the
|
|
657
|
+
* write as NOT durable. `reason` says which failure it was, and `code` carries the
|
|
658
|
+
* server's machine code when the push was rejected on its merits:
|
|
659
|
+
*
|
|
660
|
+
* - `timeout` — no verdict within the deadline. Ambiguous by nature: the push may
|
|
661
|
+
* still land later. The caller should surface it as unconfirmed, not as "failed".
|
|
662
|
+
* - `rejected` — the server refused. `missing_dependency` is retryable after
|
|
663
|
+
* catch-up; `corrupt_update` never is.
|
|
664
|
+
* - `failed` — transport/network failure; the server's answer is unknown.
|
|
665
|
+
*/
|
|
666
|
+
declare class MengineAckTimeoutError extends Error {
|
|
667
|
+
readonly reason: 'timeout' | 'rejected' | 'failed';
|
|
668
|
+
readonly code: string | undefined;
|
|
669
|
+
readonly cause: Error | undefined;
|
|
670
|
+
constructor(reason: 'timeout' | 'rejected' | 'failed', code: string | undefined, cause: Error | undefined, message: string);
|
|
671
|
+
}
|
|
672
|
+
interface WaitForServerAckOptions {
|
|
673
|
+
/** Deadline in ms. Rejects with reason `timeout` when it elapses. */
|
|
674
|
+
timeoutMs?: number;
|
|
675
|
+
}
|
|
188
676
|
interface MengineDocSessionOptions {
|
|
189
677
|
docId: string;
|
|
190
678
|
client: MengineHttpClient;
|
|
@@ -230,7 +718,44 @@ declare class MengineDocSession {
|
|
|
230
718
|
private adapterValue;
|
|
231
719
|
private editorValue;
|
|
232
720
|
private started;
|
|
721
|
+
/**
|
|
722
|
+
* Latest server oplog version seen on a push outcome. Lets `waitForServerAck`
|
|
723
|
+
* return without waiting when the server is already known to cover the local
|
|
724
|
+
* doc (e.g. nothing was edited since the last confirmed push).
|
|
725
|
+
*/
|
|
726
|
+
private serverVVValue;
|
|
233
727
|
constructor(options: MengineDocSessionOptions);
|
|
728
|
+
/**
|
|
729
|
+
* Observe every push verdict, including `duplicate` and failures.
|
|
730
|
+
*
|
|
731
|
+
* Exposed so a host can log/meter the four outcomes (rfc/05 §3 asks for
|
|
732
|
+
* explicit ack/rejected semantics). Most callers want the higher-level
|
|
733
|
+
* {@link waitForServerAck} instead.
|
|
734
|
+
*/
|
|
735
|
+
subscribePushOutcome(callback: (outcome: PushOutcome) => void): () => void;
|
|
736
|
+
/**
|
|
737
|
+
* Resolve once the server has durably accepted the local document state as of
|
|
738
|
+
* *now* — the capability an Agent tool needs to answer "did my edit land?"
|
|
739
|
+
* before reporting success.
|
|
740
|
+
*
|
|
741
|
+
* Call it right after the editor ops whose durability matters. It snapshots the
|
|
742
|
+
* local doc's current version and resolves on the first push outcome whose
|
|
743
|
+
* `serverVV` covers that version, i.e. the server log is at least as advanced as
|
|
744
|
+
* the local doc was when this was called.
|
|
745
|
+
*
|
|
746
|
+
* Version coverage, not byte identity, is the acceptance test — for two reasons:
|
|
747
|
+
* the ops may reach the server inside a merged blob rather than as the exact
|
|
748
|
+
* bytes a push job carried, and a `duplicate` verdict then correctly satisfies
|
|
749
|
+
* the wait (the bytes appended nothing *because* the server already had them).
|
|
750
|
+
* A `rejected` / `failed` outcome rejects immediately with that reason rather
|
|
751
|
+
* than burning the whole timeout, since neither will resolve by waiting.
|
|
752
|
+
*
|
|
753
|
+
* Returns early when the server is already known to be current, so a caller
|
|
754
|
+
* with nothing outstanding does not block.
|
|
755
|
+
*
|
|
756
|
+
* @throws {MengineAckTimeoutError} on timeout, rejection, or transport failure.
|
|
757
|
+
*/
|
|
758
|
+
waitForServerAck(options?: WaitForServerAckOptions): Promise<void>;
|
|
234
759
|
/**
|
|
235
760
|
* The editor for local edits. Each op method validates, writes, and commits
|
|
236
761
|
* itself as one SemanticOp (single commit carrying its audit message), so
|
|
@@ -238,18 +763,6 @@ declare class MengineDocSession {
|
|
|
238
763
|
* step. The committed change drives DocManager's local-update push.
|
|
239
764
|
*/
|
|
240
765
|
get editor(): SemanticEditor;
|
|
241
|
-
/**
|
|
242
|
-
* Opaque version token of the local oplog (base64 `VersionVector.encode`).
|
|
243
|
-
* Equality-comparable only: equal means no observed change (local or
|
|
244
|
-
* remote-arrived) since the token was taken. Throws when not started.
|
|
245
|
-
*/
|
|
246
|
-
version(): string;
|
|
247
|
-
/**
|
|
248
|
-
* The live document adapter, exposed for journal replay (commit channel).
|
|
249
|
-
* Replaying through it still goes SemanticEditor → Loro → mengine-server —
|
|
250
|
-
* no write bypass. Typed by the narrow interface on purpose.
|
|
251
|
-
*/
|
|
252
|
-
get documentAdapter(): SemanticDocumentAdapter;
|
|
253
766
|
/** Current document snapshot (read model). */
|
|
254
767
|
snapshot(): VideoDocument;
|
|
255
768
|
/**
|
|
@@ -277,51 +790,6 @@ declare class MengineDocSession {
|
|
|
277
790
|
private hasContent;
|
|
278
791
|
}
|
|
279
792
|
//#endregion
|
|
280
|
-
//#region src/storage/medeo-http-doc-storage.d.ts
|
|
281
|
-
interface MedeoHttpDocStorageOptions {
|
|
282
|
-
docId: string;
|
|
283
|
-
client: MengineHttpClient;
|
|
284
|
-
sseReconnectDelayMs?: number;
|
|
285
|
-
readonlyMode?: boolean;
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Adapts the mengine-server HTTP/SSE protocol to the engine `DocStorage`
|
|
289
|
-
* contract so `ClientServerSynchronizer` can treat it as a remote peer.
|
|
290
|
-
*
|
|
291
|
-
* Deliberately thin (mirrors the socket `DocStorage` in the playground): it
|
|
292
|
-
* forwards live SSE updates and exposes a version-vector diff, and keeps NO
|
|
293
|
-
* sync state of its own.
|
|
294
|
-
*
|
|
295
|
-
* - `getDocDiff(docId, knownVersion)` pulls the server-computed VV-diff via
|
|
296
|
-
* `GET /sync?from=<vv>` — the synchronizer passes the real `doc.version()`, so
|
|
297
|
-
* the response carries exactly the ops the doc is missing. `getDoc` (full
|
|
298
|
-
* `/snapshot`) stays for cold start, when the caller holds no version yet.
|
|
299
|
-
* - `pushDocUpdate` forwards a Loro update; the server appends it.
|
|
300
|
-
* - `subscribeDocUpdate` registers a callback for live SSE updates. It does no
|
|
301
|
-
* catch-up and keeps no cursor: after an SSE drop the connection reports a
|
|
302
|
-
* status change, and the synchronizer re-runs its cycle to catch up via
|
|
303
|
-
* `getDocDiff(doc.version())`. `LoroDoc.import` is idempotent (OpId/VV), so
|
|
304
|
-
* re-forwarded or echoed updates are harmless.
|
|
305
|
-
*
|
|
306
|
-
* It is bound to a single `docId` because `MengineHttpClient` is per-document.
|
|
307
|
-
*/
|
|
308
|
-
declare class MedeoHttpDocStorage implements DocStorage {
|
|
309
|
-
private readonly options;
|
|
310
|
-
readonly connection: Connection;
|
|
311
|
-
private readonly client;
|
|
312
|
-
private readonly docId;
|
|
313
|
-
private readonly events;
|
|
314
|
-
constructor(options: MedeoHttpDocStorageOptions);
|
|
315
|
-
get isReadonly(): boolean;
|
|
316
|
-
getDoc(docId: string): Promise<DocSnapshotRecord | null>;
|
|
317
|
-
getDocDiff(docId: string, knownVersion?: Uint8Array): Promise<DocDiff | null>;
|
|
318
|
-
pushDocUpdate(update: DocUpdate, _origin: unknown): Promise<void>;
|
|
319
|
-
deleteDoc(_docId: string): Promise<void>;
|
|
320
|
-
subscribeDocUpdate(callback: (update: DocUpdate, origin: unknown) => void): () => void;
|
|
321
|
-
private assertDocId;
|
|
322
|
-
private emitUpdate;
|
|
323
|
-
}
|
|
324
|
-
//#endregion
|
|
325
793
|
//#region src/storage/memory-doc-storage.d.ts
|
|
326
794
|
/**
|
|
327
795
|
* Runtime-neutral local `DocStorage` backed by in-process memory.
|
|
@@ -530,6 +998,25 @@ interface SolvedVideoDocument {
|
|
|
530
998
|
aggregations: PartAggregation[];
|
|
531
999
|
durationMs: number;
|
|
532
1000
|
partLibrary: Record<string, PartUnion>;
|
|
1001
|
+
/**
|
|
1002
|
+
* Part ids of the gap fillers this solve minted.
|
|
1003
|
+
*
|
|
1004
|
+
* They exist only inside the solve: gap filling needs them so the clips after a
|
|
1005
|
+
* gap land at the right absolute time, but they are not authoritative state and
|
|
1006
|
+
* the read view does not carry them (see `fromVideoDocument`).
|
|
1007
|
+
*
|
|
1008
|
+
* Reported as ids rather than left for the caller to detect, because the caller
|
|
1009
|
+
* *cannot* detect them. The obvious predicate — `origin_media_id === ''` — also
|
|
1010
|
+
* matches an empty clip a writer placed on purpose (`batch_replace_video_clip_sequence`
|
|
1011
|
+
* documents "Omit to create an empty clip placeholder"), and those are
|
|
1012
|
+
* authoritative parts that must survive the projection. The mint callback is the
|
|
1013
|
+
* only place that knows the difference.
|
|
1014
|
+
*
|
|
1015
|
+
* Note this deliberately excludes the fillers that gap filling *extended* rather
|
|
1016
|
+
* than minted (`fillMainTrackTimeGaps` cases 1 and 2): those are authoritative
|
|
1017
|
+
* empty clips already in `part_library`, and only their length is derived.
|
|
1018
|
+
*/
|
|
1019
|
+
derivedFillerPartIds: Set<string>;
|
|
533
1020
|
}
|
|
534
1021
|
/**
|
|
535
1022
|
* Solve a `VideoDocument` (authoritative, position-only) into its derived
|
|
@@ -592,4 +1079,4 @@ declare function hostForAbsMs(ranges: MainClipRange[], absMs: number): MainClipR
|
|
|
592
1079
|
*/
|
|
593
1080
|
declare function relativePositionForAbs(ranges: MainClipRange[], absMs: number): TrackItemTimePosition;
|
|
594
1081
|
//#endregion
|
|
595
|
-
export { type Aggregation, type Attachment, type BgmPart, type CaptionPart, type CaptionStyle, type CommitOptions, type DerivedItemPosition, type DocStorageLike, IMPLEMENTED_SEMANTIC_OP_KINDS, type ImplementedSemanticOpKind, type
|
|
1082
|
+
export { type Aggregation, type Attachment, type BgmPart, type CaptionPart, type CaptionStyle, type CommitOptions, type DerivedItemPosition, type DocStorageLike, type DocVersionMark, IMPLEMENTED_SEMANTIC_OP_KINDS, type ImplementedSemanticOpKind, type ImportVerdict, type MainClipRange, type MakeEmptyPart, ManualSyncDoc, type ManualSyncDocOptions, MedeoHttpDocStorage, type MedeoHttpDocStorageOptions, MemoryDocStorage, MengineAckTimeoutError, type MengineAuditEntry, type MengineAuditResponse, MengineDocSession, type MengineDocSessionOptions, type MengineDocSessionUpdateEvent, type MengineDocumentVersion, type MengineEventStreamOptions, MengineHttpClient, type MengineHttpClientOptions, MengineHttpRequestError, MenginePushRejectedError, type MenginePushResponse, type MenginePushUpdateResponse, type MengineRejectedResponse, type MengineSnapshotResponse, type MengineSseUpdateEvent, type MengineSyncResponse, type MengineUpdateMeta, MirrorVideoDocumentAdapter, type MirrorVideoDocumentOptions, type OpActor, type PartAggregation, type PartKind, type PartUnion, type PlannedSemanticOpKind, type PullFailureReason, type PullResult, type PushOutcome, type PushOutcomeKind, type PushResult, type PushResultKind, SchemaValidator, type SemanticDocumentAdapter, SemanticEditor, type SemanticOpInput, type SemanticOpKind, type SemanticOpName, type SnapshotReadable, type SolvedVideoDocument, type SpeechHostMap, type SpeechPart, type SpeedShift, TIMELINE_SKELETON_DURATION_MS, type Timeline, type TimelineDoc, type TimelineItem, type Track, type TrackDraft, type TrackItem, type TrackItemDraft, type TrackItemTimePosition, type TransactAudit, VIDEO_DOCUMENT_SCHEMA_VERSION, ValidationError, type VideoClipPart, type VideoDocument, type VideoDocumentDraft, type VideoDocumentMirrorSchema, type VideoDocumentSchemaVersion, VideoDocumentValidationError, type VideoDocumentValidationIssue, type VideoDocumentValidationIssueCode, type VideoDraft, type CaptionPart$1 as VideoDraftCaptionPart, type VideoDraftPartUnion, type Timeline$1 as VideoDraftTimeline, type Track$1 as VideoDraftTrack, type TrackItem$1 as VideoDraftTrackItem, type WaitForServerAckOptions, arrangeMainTrackSeamlessly, assertValidVideoDocument, base64ToBytes, buildSpeechHostMap, bytesToBase64, cascadeAfterVideoClipChanges, classifyUpdate, covers, createMirrorVideoDocument, createMirrorVideoDocumentAdapter, decodeDocVersionMark, derivePositionFromAbs, encodeDocVersionMark, ensureLaneTrack, fillMainTrackTimeGaps, findLaneTrack, fromVideoDocument, generatePartId, getAt, hostForAbsMs, isEmptyVideoClip, isImplementedSemanticOpKind, isMap, mainTrackRanges, newRelayDoc, partDurationMs, partUnionSchema, readMainTrackItems, readMengineEventStream, readPart, readPartDurationMs, readVideoDocumentFromDraft, reassignSpeechesToVideoClipsByTime, recalculateTimelineDuration, relativePositionForAbs, relayDocFromSnapshot, resolveAllSpeechOverlaps, resolveSpeechOverlapByShiftingVideos, safeDurationMs, index_d_exports as schemas, snapshotToPlain, solveVideoDocument, syncAggregatedClipsTimePosition, toVideoDocument, validateVideoDocument, videoDocumentMirrorSchema, videoDocumentSchema };
|