@mengine/medeo-client 2.0.1-alpha.2 → 2.0.1-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -110
- package/dist/document-B_JQwrC5.js +1630 -0
- package/dist/{index-B31KeDzA.d.ts → index-CnZ9l3rb.d.ts} +708 -409
- package/dist/index.d.ts +131 -737
- package/dist/index.js +971 -2728
- package/dist/{loro-relay-doc-ssdYpuef.js → loro-relay-doc-cJSY-uau.js} +7 -2
- package/dist/relay.js +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +4 -58
- package/package.json +7 -12
- package/dist/document-BSAUud6c.js +0 -4537
- package/dist/index-CMa6ZCtX.d.ts +0 -609
- package/dist/schemas.d.ts +0 -2
- package/dist/schemas.js +0 -482
- package/dist/shared-iWnU2osE.js +0 -39
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { $ as SequenceRange, A as generatePartId, At as VideoDraft, B as ResolvedEntityClipPlacement, Bt as Track$1, C as PlannedSemanticOpKind, Ct as TrackItemTimePosition, D as SnapshotReadable, Dt as VideoDocumentSchemaVersion, E as SchemaValidator, Et as VideoDocument, F as videoDocumentMirrorSchema, Ft as CaptionPart$1, G as EntityTimelineProjectionError, H as ResolvedEntityTrack, I as VideoDocumentValidationError, It as CaptionStyle, J as RelationRow, K as EntityRelationRows, L as assertValidVideoDocument, Lt as PartAggregation, M as TrackItemDraft, Mt as effectiveVideoClipDurationMs, N as VideoDocumentDraft, Nt as speedOf, O as ValidationError, Ot as VideoDocumentValidationIssue, P as VideoDocumentMirrorSchema, Pt as Attachment, Q as SequenceDuration, R as validateVideoDocument, Rt as SpeedShift, S as ImplementedSemanticOpKind, St as TrackItem, T as isImplementedSemanticOpKind, Tt as VideoClipPart, U as resolveEntityTimelineLayout, V as ResolvedEntityTimelineLayout, Vt as TrackItem$1, W as projectEntityTimeline, X as CaptionStyleFields, Y as CaptionSegmentSelection, Z as ScriptTextSegment, _ as SemanticEditor, _t as PartKind, a as PlainMemoryAdapter, at as buildInitialVideoDocument, b as TransactAudit, bt as Timeline, c as MirrorVideoDocumentAdapter, ct as buildSpeechHostMap, d as createMirrorVideoDocument, dt as toVideoDocument, et as VoiceDescriptor, f as createMirrorVideoDocumentAdapter, ft as BgmPart, g as SemanticDocumentAdapter, gt as ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION, h as OpActor, ht as DEFAULT_UNIT_TIME_MS, i as JournalEntry, it as InitialDocumentFacts, j as TrackDraft, jt as VideoDraftPartUnion, k as PartIdFactory, kt as VideoDocumentValidationIssueCode, l as MirrorVideoDocumentOptions, lt as derivePositionFromAbs, m as CommitOptions, mt as CaptionPart, n as videoDocumentSchema, nt as JsonValue, o as PlainMemoryAdapterOptions, ot as DerivedItemPosition, p as writeVideoDocumentToDraft, pt as CaptionDisplayCue, q as EntityRow, r as readVideoDocumentFromDraft, rt as EntityId, s as createPlainMemoryAdapter, st as SpeechHostMap, t as partUnionSchema, tt as JsonObject, u as applyEntityTimelineProjection, ut as fromVideoDocument, v as SemanticOpInput, vt as PartUnion, w as SemanticOpKind, wt as VIDEO_DOCUMENT_SCHEMA_VERSION, x as IMPLEMENTED_SEMANTIC_OP_KINDS, xt as Track, y as SemanticOpName, yt as SpeechPart, z as EntityTimelineTrackRole, zt as Timeline$1 } from "./index-B31KeDzA.js";
|
|
1
|
+
import { $ as VideoDraft, A as assertValidVideoDocument, B as CaptionPart, C as index_d_exports, D as VideoDocumentMirrorSchema, E as VideoDocumentDraft, F as buildSpeechHostMap, G as Timeline, H as PartKind, I as derivePositionFromAbs, J as TrackItemTimePosition, K as Track, L as fromVideoDocument, M as buildInitialVideoDocument, N as DerivedItemPosition, O as videoDocumentMirrorSchema, P as SpeechHostMap, Q as VideoDocumentValidationIssueCode, R as toVideoDocument, S as ValidationError, T as TrackItemDraft, U as PartUnion, V as DEFAULT_UNIT_TIME_MS, W as SpeechPart, X as VideoDocument, Y as VideoClipPart, Z as VideoDocumentValidationIssue, _ as PlannedSemanticOpKind, a as MirrorVideoDocumentOptions, at as PartAggregation, b as SchemaValidator, c as CommitOptions, ct as Track$1, d as SemanticEditor, et as VideoDraftContent, f as SemanticOpInput, g as ImplementedSemanticOpKind, h as IMPLEMENTED_SEMANTIC_OP_KINDS, i as MirrorVideoDocumentAdapter, it as CaptionStyle, j as validateVideoDocument, k as VideoDocumentValidationError, l as OpActor, lt as TrackItem$1, m as TransactAudit, n as videoDocumentSchema, nt as Attachment, o as createMirrorVideoDocument, ot as SpeedShift, p as SemanticOpName, q as TrackItem, r as readVideoDocumentFromDraft, rt as CaptionPart$1, s as createMirrorVideoDocumentAdapter, st as Timeline$1, t as partUnionSchema, tt as VideoDraftPartUnion, u as SemanticDocumentAdapter, v as SemanticOpKind, w as TrackDraft, x as SnapshotReadable, y as isImplementedSemanticOpKind, z as BgmPart } from "./index-CnZ9l3rb.js";
|
|
3
2
|
import { LoroDoc, PeerID } from "loro-crdt";
|
|
4
|
-
import { DocState } from "@mengine/sync";
|
|
3
|
+
import { DocState, LocalSaveState } from "@mengine/sync";
|
|
5
4
|
import { BaseDocStorage, Connection, DocDiff, DocPushReceipt, DocSnapshotRecord, DocStorage, DocStorageOptions, DocUpdate, DocUpdateRecord } from "@mengine/storage";
|
|
6
5
|
|
|
7
6
|
//#region src/client/base64.d.ts
|
|
@@ -134,7 +133,6 @@ declare class MengineHttpClient {
|
|
|
134
133
|
private readonly fetchImpl;
|
|
135
134
|
constructor(options: MengineHttpClientOptions);
|
|
136
135
|
fetchSnapshot(): Promise<MengineSnapshotResponse>;
|
|
137
|
-
bootstrapSnapshot(snapshot: Uint8Array): Promise<MengineSnapshotResponse>;
|
|
138
136
|
/**
|
|
139
137
|
* Loro VV-diff pull: send the caller's oplog `VersionVector.encode` as `from`
|
|
140
138
|
* (omit for a full pull) and receive exactly the updates it is missing plus
|
|
@@ -175,688 +173,38 @@ interface MengineEventStreamOptions {
|
|
|
175
173
|
/** Fired once the stream response is established (HTTP ok, body readable). */
|
|
176
174
|
onOpen?(): void;
|
|
177
175
|
onUpdate(event: MengineSseUpdateEvent): void;
|
|
176
|
+
/** A committed update omitted from live transport; fetch the missing operations by VV. */
|
|
177
|
+
onResync?(): void;
|
|
178
178
|
}
|
|
179
179
|
declare function readMengineEventStream(options: MengineEventStreamOptions): Promise<void>;
|
|
180
180
|
//#endregion
|
|
181
|
-
//#region
|
|
182
|
-
type ScriptCompositionIssueCode = 'field_conflict' | 'composition_cycle' | 'invalid_bases' | 'composition_missing' | 'composition_ambiguous' | 'composition_dangling' | 'unknown_segment' | 'empty_selection' | 'invalid_script' | 'invalid_selection';
|
|
183
|
-
/** Assembly fails explicitly when declared bases cannot provide valid, unambiguous content. */
|
|
184
|
-
declare class ScriptCompositionError extends Error {
|
|
185
|
-
readonly code: ScriptCompositionIssueCode;
|
|
186
|
-
readonly entityId: EntityId;
|
|
187
|
-
constructor(code: ScriptCompositionIssueCode, entityId: EntityId, message: string);
|
|
188
|
-
}
|
|
189
|
-
interface AssembledCaptionContent {
|
|
190
|
-
readonly caption: EntityRow<'caption'>;
|
|
191
|
-
readonly audioScript: EntityRow<'audio-script'>;
|
|
192
|
-
/** Selected AudioScript segments in Caption selection order. */
|
|
193
|
-
readonly segments: readonly ScriptTextSegment[];
|
|
194
|
-
/** Complete display text: the selected segments' text joined in order. */
|
|
195
|
-
readonly text: string;
|
|
196
|
-
}
|
|
197
|
-
interface AssembledPhoneticScriptContent {
|
|
198
|
-
readonly phoneticScript: EntityRow<'phonetic-script'>;
|
|
199
|
-
readonly audioScript: EntityRow<'audio-script'>;
|
|
200
|
-
/** All AudioScript segments in script order; the pronunciation variant never reorders text. */
|
|
201
|
-
readonly segments: readonly ScriptTextSegment[];
|
|
202
|
-
/** Complete base text owned by the AudioScript. */
|
|
203
|
-
readonly text: string;
|
|
204
|
-
}
|
|
205
|
-
/** Validate all base providers before applying explicit own fields; ordering cannot resolve ambiguity. */
|
|
206
|
-
declare function assembleEntityContent(rows: EntityRelationRows, entityId: EntityId): EntityRow;
|
|
207
|
-
/** Find the actual AudioScript text owner through direct variant bases. */
|
|
208
|
-
declare function findComposedAudioScript(rows: EntityRelationRows, variantEntityId: EntityId, variantKind: 'caption' | 'phonetic-script'): EntityRow<'audio-script'>;
|
|
209
|
-
/** Join the whole AudioScript text in segment order. */
|
|
210
|
-
declare function assembleScriptText(script: EntityRow<'audio-script'>): string;
|
|
211
|
-
/** Assemble selected text after base-field validation and explicit variant overrides. */
|
|
212
|
-
declare function assembleCaptionContent(rows: EntityRelationRows, captionEntityId: EntityId): AssembledCaptionContent;
|
|
213
|
-
/**
|
|
214
|
-
* Assemble the complete Phonetic Script content for TTS: the composed
|
|
215
|
-
* AudioScript's base text plus the variant's own phoneme and prosody fields.
|
|
216
|
-
*/
|
|
217
|
-
declare function assemblePhoneticScriptContent(rows: EntityRelationRows, phoneticScriptEntityId: EntityId): AssembledPhoneticScriptContent;
|
|
218
|
-
/** Select source text without creating another authoritative text field. */
|
|
219
|
-
declare function selectAudioScriptSegment(script: EntityRow<'audio-script'>, selection: CaptionSegmentSelection): ScriptTextSegment;
|
|
220
|
-
//#endregion
|
|
221
|
-
//#region src/entity-editor/entity-graph-http-client.d.ts
|
|
222
|
-
/** One authenticated revision of the authoritative Medeo Entity graph. */
|
|
223
|
-
interface EntityGraphState {
|
|
224
|
-
/** Current AudioScript content version attached to the project. */
|
|
225
|
-
readonly audioScriptEntityId: string;
|
|
226
|
-
readonly revision: number;
|
|
227
|
-
readonly loroSnapshot: string;
|
|
228
|
-
readonly rows: EntityRelationRows;
|
|
229
|
-
}
|
|
230
|
-
interface EntityGraphCommitOptions {
|
|
231
|
-
/** Server version vector proving the explicit legacy-to-Entity migration baseline. */
|
|
232
|
-
readonly migrationBaseVv?: string;
|
|
233
|
-
}
|
|
234
|
-
/** Browser-safe authenticated Loro client for a document's Entity graph. */
|
|
235
|
-
declare class EntityGraphHttpClient {
|
|
236
|
-
private readonly options;
|
|
237
|
-
private readonly transport;
|
|
238
|
-
private readonly endpoint;
|
|
239
|
-
constructor(options: MengineHttpClientOptions);
|
|
240
|
-
fetchState(): Promise<EntityGraphState>;
|
|
241
|
-
/**
|
|
242
|
-
* Compile edits against the original causal snapshot and publish native Loro operations.
|
|
243
|
-
*
|
|
244
|
-
* Deletion intent is derived from baseline IDs omitted from `nextRows`, so a
|
|
245
|
-
* transient create-then-remove never becomes a request to delete unknown
|
|
246
|
-
* persisted data.
|
|
247
|
-
*/
|
|
248
|
-
commit(baseState: Pick<EntityGraphState, 'revision' | 'rows' | 'loroSnapshot'>, nextRows: EntityRelationRows, options?: EntityGraphCommitOptions): Promise<EntityGraphState>;
|
|
249
|
-
/** Send the same prepared bytes on retry; never recompile an unconfirmed edit. */
|
|
250
|
-
commitUpdate(update: string): Promise<EntityGraphState>;
|
|
251
|
-
private request;
|
|
252
|
-
}
|
|
253
|
-
//#endregion
|
|
254
|
-
//#region src/entity-editor/types.d.ts
|
|
255
|
-
/** Injectable domain-id mint shared by Entity and Relation authoring surfaces. */
|
|
256
|
-
type EntityTimelineIdFactory = (prefix: 'entity' | 'relation') => string;
|
|
257
|
-
interface ImageMediaAssetFact {
|
|
258
|
-
readonly assetId: string;
|
|
259
|
-
readonly kind: 'image';
|
|
260
|
-
readonly storageKey?: string;
|
|
261
|
-
}
|
|
262
|
-
interface VideoMediaAssetFact {
|
|
263
|
-
readonly assetId: string;
|
|
264
|
-
readonly kind: 'video';
|
|
265
|
-
readonly durationMs: number;
|
|
266
|
-
readonly storageKey?: string;
|
|
267
|
-
}
|
|
268
|
-
interface AudioMediaAssetFact {
|
|
269
|
-
readonly assetId: string;
|
|
270
|
-
readonly kind: 'audio';
|
|
271
|
-
readonly durationMs: number;
|
|
272
|
-
readonly storageKey: string;
|
|
273
|
-
}
|
|
274
|
-
interface VoiceMediaAssetFact {
|
|
275
|
-
/** Stable external speech result id, independent of the placed Clip id. */
|
|
276
|
-
readonly assetId: string;
|
|
277
|
-
readonly kind: 'voice';
|
|
278
|
-
readonly durationMs: number;
|
|
279
|
-
readonly storageKey: string;
|
|
280
|
-
/** Present for synthesized voice, absent for original recorded audio. */
|
|
281
|
-
readonly voice?: VoiceDescriptor;
|
|
282
|
-
}
|
|
283
|
-
/** Facts resolved from media storage. A trim window never substitutes for intrinsic duration. */
|
|
284
|
-
type MediaAssetFact = ImageMediaAssetFact | VideoMediaAssetFact | AudioMediaAssetFact | VoiceMediaAssetFact;
|
|
285
|
-
type ClipPlacement = {
|
|
286
|
-
readonly kind: 'sequential';
|
|
287
|
-
readonly order: number;
|
|
288
|
-
} | {
|
|
289
|
-
readonly kind: 'absolute';
|
|
290
|
-
readonly targetRange: SequenceRange<number>;
|
|
291
|
-
} | {
|
|
292
|
-
readonly kind: 'anchored';
|
|
293
|
-
readonly hostClipEntityId: string;
|
|
294
|
-
readonly anchorOffset: number;
|
|
295
|
-
};
|
|
296
|
-
interface InsertPlacedClipInput {
|
|
297
|
-
readonly trackEntityId: string;
|
|
298
|
-
readonly contentEntityId: string;
|
|
299
|
-
readonly sourceRange: SequenceRange<number>;
|
|
300
|
-
readonly duration: SequenceDuration<number>;
|
|
301
|
-
readonly placement: ClipPlacement;
|
|
302
|
-
readonly clipPayload?: JsonObject;
|
|
303
|
-
/** Stable caller-owned placement identity, when one already exists outside the graph. */
|
|
304
|
-
readonly clipEntityId?: string;
|
|
305
|
-
}
|
|
306
|
-
interface SetClipPlacementInput {
|
|
307
|
-
readonly clipEntityId: string;
|
|
308
|
-
readonly placement: ClipPlacement;
|
|
309
|
-
}
|
|
310
|
-
type SequentialClipAnchor = {
|
|
311
|
-
readonly position: 'before' | 'after';
|
|
312
|
-
readonly clipEntityId: string;
|
|
313
|
-
} | {
|
|
314
|
-
readonly position: 'trackStart';
|
|
315
|
-
};
|
|
316
|
-
interface MoveSequentialClipsInput {
|
|
317
|
-
readonly clipEntityIds: readonly string[];
|
|
318
|
-
readonly anchor: SequentialClipAnchor;
|
|
319
|
-
readonly onAnchored: 'follow' | 'keepAbsolute';
|
|
320
|
-
}
|
|
321
|
-
interface MoveClipsToStartsInput {
|
|
322
|
-
readonly moves: readonly {
|
|
323
|
-
readonly clipEntityId: string;
|
|
324
|
-
readonly newStartMs: number;
|
|
325
|
-
}[];
|
|
326
|
-
/** Absolute-time drags preserve every voiceover's current visible landing. */
|
|
327
|
-
readonly onAnchored: 'keepAbsolute';
|
|
328
|
-
}
|
|
329
|
-
interface DeleteClipTreeInput {
|
|
330
|
-
readonly clipEntityIds: readonly string[];
|
|
331
|
-
readonly onAnchored: 'cascade' | 'detach';
|
|
332
|
-
}
|
|
333
|
-
interface VoiceoverCaptionFact {
|
|
334
|
-
/** Stable placed caption identity supplied by the materialized side effect. */
|
|
335
|
-
readonly captionClipEntityId: string;
|
|
336
|
-
/** Directly held bases; includes the AudioScript used by the Voice. */
|
|
337
|
-
readonly baseEntityIds: readonly string[];
|
|
338
|
-
/** Ordered selection of AudioScript segments; caption text is never passed inline. */
|
|
339
|
-
readonly selection: CaptionSegmentSelection;
|
|
340
|
-
readonly startMs: number;
|
|
341
|
-
readonly durationMs: number;
|
|
342
|
-
readonly style?: CaptionStyleFields;
|
|
343
|
-
}
|
|
344
|
-
type VoiceoverTakeInput = {
|
|
345
|
-
readonly timelineEntityId: string; /** Stable placed speech identity, distinct from media.assetId. */
|
|
346
|
-
readonly voiceoverClipEntityId: string;
|
|
347
|
-
readonly media: VoiceMediaAssetFact; /** Existing pronunciation variant; its composed AudioScript stays the text owner. */
|
|
348
|
-
readonly phoneticScriptEntityId: string;
|
|
349
|
-
readonly volume: number;
|
|
350
|
-
readonly captions: readonly VoiceoverCaptionFact[];
|
|
351
|
-
} & ({
|
|
352
|
-
readonly placement: ClipPlacement;
|
|
353
|
-
readonly hostClipEntityId?: never;
|
|
354
|
-
readonly anchorOffset?: never;
|
|
355
|
-
} | {
|
|
356
|
-
readonly placement?: never;
|
|
357
|
-
readonly hostClipEntityId: string;
|
|
358
|
-
readonly anchorOffset: number;
|
|
359
|
-
});
|
|
360
|
-
type VisualMediaAssetFact = ImageMediaAssetFact | VideoMediaAssetFact;
|
|
361
|
-
interface InsertMediaClipInput {
|
|
362
|
-
readonly timelineEntityId: string;
|
|
363
|
-
readonly clipEntityId?: string;
|
|
364
|
-
readonly media: VisualMediaAssetFact;
|
|
365
|
-
/** Source/display window in whole milliseconds. Images use this as their finite display span. */
|
|
366
|
-
readonly sourceRange: SequenceRange<number>;
|
|
367
|
-
readonly placement: ClipPlacement;
|
|
368
|
-
readonly volume?: number;
|
|
369
|
-
}
|
|
370
|
-
interface ReplaceMediaClipInput {
|
|
371
|
-
readonly clipEntityId: string;
|
|
372
|
-
readonly media: VisualMediaAssetFact;
|
|
373
|
-
readonly sourceRange: SequenceRange<number>;
|
|
374
|
-
}
|
|
375
|
-
interface ReplacementMediaClipInput {
|
|
376
|
-
readonly clipEntityId?: string;
|
|
377
|
-
readonly media: VisualMediaAssetFact;
|
|
378
|
-
readonly sourceRange: SequenceRange<number>;
|
|
379
|
-
readonly volume?: number;
|
|
380
|
-
}
|
|
381
|
-
type MediaClipInsertion = {
|
|
382
|
-
readonly kind: 'before';
|
|
383
|
-
readonly clipEntityId: string;
|
|
384
|
-
} | {
|
|
385
|
-
readonly kind: 'after';
|
|
386
|
-
readonly clipEntityId: string;
|
|
387
|
-
} | {
|
|
388
|
-
readonly kind: 'firstStart';
|
|
389
|
-
readonly startMs: number;
|
|
390
|
-
};
|
|
391
|
-
interface InsertMediaClipsInput {
|
|
392
|
-
readonly timelineEntityId: string;
|
|
393
|
-
readonly clips: readonly ReplacementMediaClipInput[];
|
|
394
|
-
/** One placement decision for the whole input-ordered block. */
|
|
395
|
-
readonly insertion: MediaClipInsertion;
|
|
396
|
-
}
|
|
397
|
-
interface ReplaceSequentialClipsInput {
|
|
398
|
-
readonly timelineEntityId: string;
|
|
399
|
-
readonly oldClipEntityIds: readonly string[];
|
|
400
|
-
readonly newClips: readonly ReplacementMediaClipInput[];
|
|
401
|
-
readonly onAnchored: 'remap' | 'cascade';
|
|
402
|
-
}
|
|
403
|
-
interface SetClipVolumeInput {
|
|
404
|
-
readonly clipEntityId: string;
|
|
405
|
-
/** Playback gain in decibels. */
|
|
406
|
-
readonly volume: number;
|
|
407
|
-
}
|
|
408
|
-
interface LinearClipSpeed {
|
|
409
|
-
readonly kind: 'linear';
|
|
410
|
-
readonly rate: number;
|
|
411
|
-
readonly mode?: string;
|
|
412
|
-
}
|
|
413
|
-
interface SetClipSpeedInput {
|
|
414
|
-
readonly clipEntityId: string;
|
|
415
|
-
readonly timeRemapping: LinearClipSpeed | null;
|
|
416
|
-
}
|
|
417
|
-
interface TrimClipInput {
|
|
418
|
-
readonly clipEntityId: string;
|
|
419
|
-
readonly sourceRange: SequenceRange<number>;
|
|
420
|
-
}
|
|
421
|
-
interface VoiceoverTakeResult {
|
|
422
|
-
readonly voiceoverClipEntityId: string;
|
|
423
|
-
readonly voiceEntityId: string;
|
|
424
|
-
/** The pronunciation variant the Voice was rendered from. */
|
|
425
|
-
readonly phoneticScriptEntityId: string;
|
|
426
|
-
/** The base-text owner resolved from the PhoneticScript baseEntityIds. */
|
|
427
|
-
readonly audioScriptEntityId: string;
|
|
428
|
-
readonly captionClipEntityIds: readonly string[];
|
|
429
|
-
}
|
|
430
|
-
interface MoveVoiceoverInput {
|
|
431
|
-
readonly voiceoverClipEntityId: string;
|
|
432
|
-
/** Absolute requested timeline start; MEngine resolves and persists the host relation. */
|
|
433
|
-
readonly newStartMs: number;
|
|
434
|
-
}
|
|
435
|
-
interface DeleteVoiceoverInput {
|
|
436
|
-
readonly voiceoverClipEntityIds: readonly string[];
|
|
437
|
-
}
|
|
438
|
-
interface SetBgmInput {
|
|
439
|
-
readonly timelineEntityId: string;
|
|
440
|
-
readonly bgmClipEntityId: string;
|
|
441
|
-
readonly media: AudioMediaAssetFact;
|
|
442
|
-
readonly volume: number;
|
|
443
|
-
}
|
|
444
|
-
interface DeleteBgmInput {
|
|
445
|
-
readonly timelineEntityId: string;
|
|
446
|
-
}
|
|
447
|
-
interface SetCaptionVisibilityInput {
|
|
448
|
-
readonly timelineEntityId: string;
|
|
449
|
-
readonly hidden: boolean;
|
|
450
|
-
}
|
|
451
|
-
interface PatchCaptionStyleInput {
|
|
452
|
-
readonly timelineEntityId: string;
|
|
453
|
-
readonly style: CaptionStyleFields;
|
|
454
|
-
}
|
|
455
|
-
interface InsertCaptionClipInput {
|
|
456
|
-
readonly timelineEntityId: string;
|
|
457
|
-
/** Existing generation identity for newly materialized Caption content, distinct from its Clip. */
|
|
458
|
-
readonly captionEntityId?: string;
|
|
459
|
-
/** Stable placed caption identity, distinct from the Caption content identity. */
|
|
460
|
-
readonly captionClipEntityId?: string;
|
|
461
|
-
/** Existing bases composed by this variant; includes an AudioScript text owner. */
|
|
462
|
-
readonly baseEntityIds: readonly string[];
|
|
463
|
-
/** Ordered selection of the AudioScript segments this Caption displays. */
|
|
464
|
-
readonly selection: CaptionSegmentSelection;
|
|
465
|
-
/** Intrinsic cue length of the Caption entity itself; display comes from the placement. */
|
|
466
|
-
readonly durationMs: number;
|
|
467
|
-
readonly style?: CaptionStyleFields;
|
|
468
|
-
readonly placement: ClipPlacement;
|
|
469
|
-
}
|
|
470
|
-
interface InsertClipInput {
|
|
471
|
-
readonly trackEntityId: string;
|
|
472
|
-
/** Existing Sequence media Entity id. Asset ids and URLs are not content ids. */
|
|
473
|
-
readonly contentEntityId: string;
|
|
474
|
-
readonly sourceRange: SequenceRange<number>;
|
|
475
|
-
readonly duration: SequenceDuration<number>;
|
|
476
|
-
readonly targetRange?: SequenceRange<number>;
|
|
477
|
-
readonly clipPayload?: JsonObject;
|
|
478
|
-
}
|
|
479
|
-
interface UpdateClipMarkerInput {
|
|
480
|
-
readonly clipEntityId: string;
|
|
481
|
-
readonly sourceRange?: SequenceRange<number>;
|
|
482
|
-
/** Passing `undefined` explicitly removes the optional target range. */
|
|
483
|
-
readonly targetRange?: SequenceRange<number> | undefined;
|
|
484
|
-
readonly duration?: SequenceDuration<number>;
|
|
485
|
-
/** Passing `undefined` explicitly removes the optional remapping value. */
|
|
486
|
-
readonly timeRemapping?: JsonValue | undefined;
|
|
487
|
-
}
|
|
488
|
-
interface MoveClipInput {
|
|
489
|
-
readonly clipEntityId: string;
|
|
490
|
-
readonly trackEntityId: string;
|
|
491
|
-
}
|
|
492
|
-
interface ReplaceClipContentInput {
|
|
493
|
-
readonly clipEntityId: string;
|
|
494
|
-
/** Existing Sequence media Entity id. Asset ids and URLs are not content ids. */
|
|
495
|
-
readonly contentEntityId: string;
|
|
496
|
-
readonly sourceRange: SequenceRange<number>;
|
|
497
|
-
readonly duration: SequenceDuration<number>;
|
|
498
|
-
readonly targetRange?: SequenceRange<number>;
|
|
499
|
-
readonly timeRemapping?: JsonValue;
|
|
500
|
-
}
|
|
501
|
-
interface DeleteClipInput {
|
|
502
|
-
readonly clipEntityId: string;
|
|
503
|
-
}
|
|
504
|
-
interface UpdateClipInput {
|
|
505
|
-
readonly clipEntityId: string;
|
|
506
|
-
/** Complete replacement for the Clip-owned payload. */
|
|
507
|
-
readonly payload: JsonObject;
|
|
508
|
-
}
|
|
509
|
-
type ClipEntityId = EntityId;
|
|
510
|
-
//#endregion
|
|
511
|
-
//#region src/entity-editor/entity-timeline-editor.d.ts
|
|
512
|
-
/**
|
|
513
|
-
* Graph-native timeline authoring over authoritative Medeo Entity and Relation rows.
|
|
514
|
-
*
|
|
515
|
-
* Each mutation is applied to a detached graph, validated as a complete DSL set,
|
|
516
|
-
* and committed only after validation succeeds.
|
|
517
|
-
*/
|
|
518
|
-
declare class EntityTimelineEditor {
|
|
519
|
-
private readonly idFactory;
|
|
520
|
-
private state;
|
|
521
|
-
constructor(initialRows: EntityRelationRows, idFactory?: EntityTimelineIdFactory);
|
|
522
|
-
rows(): EntityRelationRows;
|
|
523
|
-
insertClip(input: InsertClipInput): ClipEntityId;
|
|
524
|
-
insertPlacedClip(input: InsertPlacedClipInput): ClipEntityId;
|
|
525
|
-
updateClipMarker(input: UpdateClipMarkerInput): void;
|
|
526
|
-
setClipPlacement(input: SetClipPlacementInput): void;
|
|
527
|
-
moveSequentialClips(input: MoveSequentialClipsInput): void;
|
|
528
|
-
moveClipsToStarts(input: MoveClipsToStartsInput): void;
|
|
529
|
-
moveClip(input: MoveClipInput): void;
|
|
530
|
-
replaceClipContent(input: ReplaceClipContentInput): void;
|
|
531
|
-
insertMediaClip(input: InsertMediaClipInput): ClipEntityId;
|
|
532
|
-
insertMediaClips(input: InsertMediaClipsInput): readonly ClipEntityId[];
|
|
533
|
-
replaceMediaClip(input: ReplaceMediaClipInput): void;
|
|
534
|
-
setClipVolume(input: SetClipVolumeInput): void;
|
|
535
|
-
setClipSpeed(input: SetClipSpeedInput): void;
|
|
536
|
-
trimClip(input: TrimClipInput): void;
|
|
537
|
-
replaceSequentialClips(input: ReplaceSequentialClipsInput): readonly ClipEntityId[];
|
|
538
|
-
deleteClip(input: DeleteClipInput): void;
|
|
539
|
-
deleteClipTree(input: DeleteClipTreeInput): void;
|
|
540
|
-
updateClip(input: UpdateClipInput): void;
|
|
541
|
-
upsertVoiceoverTake(input: VoiceoverTakeInput): VoiceoverTakeResult;
|
|
542
|
-
moveVoiceover(input: MoveVoiceoverInput): void;
|
|
543
|
-
deleteVoiceover(input: DeleteVoiceoverInput): void;
|
|
544
|
-
setBgm(input: SetBgmInput): ClipEntityId;
|
|
545
|
-
deleteBgm(input: DeleteBgmInput): void;
|
|
546
|
-
setCaptionVisibility(input: SetCaptionVisibilityInput): void;
|
|
547
|
-
patchCaptionStyle(input: PatchCaptionStyleInput): void;
|
|
548
|
-
/**
|
|
549
|
-
* Place a Caption as a composed variant of an existing AudioScript: the
|
|
550
|
-
* entity stores baseEntityIds, selection, optional style, and inherent cue-bounded
|
|
551
|
-
* Sequence. This helper does not copy base text. The Clip and its display Marker describe this use;
|
|
552
|
-
* moving or stretching the returned Clip later changes the Clip/Marker,
|
|
553
|
-
* never the Caption entity or the AudioScript.
|
|
554
|
-
*/
|
|
555
|
-
insertCaptionClip(input: InsertCaptionClipInput): ClipEntityId;
|
|
556
|
-
private insertPlacedClipIntoDraft;
|
|
557
|
-
private ensureRoleTrack;
|
|
558
|
-
/** The existing pronunciation variant a Voice consumes; composition is required. */
|
|
559
|
-
private requireComposedPhoneticScript;
|
|
560
|
-
/** Preserve the factual synthesis input, regardless of persisted endpoint positions. */
|
|
561
|
-
private ensurePhoneticRender;
|
|
562
|
-
private reconcileVoiceoverCaptions;
|
|
563
|
-
private ensureRoleTrackForClip;
|
|
564
|
-
private replaceCaptionAlignment;
|
|
565
|
-
/**
|
|
566
|
-
* Remove one placed Caption use. The composed AudioScript outlives the
|
|
567
|
-
* caption: it may anchor further captions and remains the text owner.
|
|
568
|
-
*/
|
|
569
|
-
private removeCaptionClipGraph;
|
|
570
|
-
private replaceAnchorHost;
|
|
571
|
-
/** Rebuild the legacy edit baseline from current visual order before a high-level cascade. */
|
|
572
|
-
private normalizeMainSequential;
|
|
573
|
-
private resolveOneVoiceoverOverlap;
|
|
574
|
-
private applyClipPlacement;
|
|
575
|
-
private reanchorAtAbsolute;
|
|
576
|
-
private removeAnchoredDescendants;
|
|
577
|
-
private removeClipGraph;
|
|
578
|
-
private transact;
|
|
579
|
-
private mintEntityId;
|
|
580
|
-
private createRelation;
|
|
581
|
-
private relinkRelation;
|
|
582
|
-
private mintRelationId;
|
|
583
|
-
}
|
|
584
|
-
//#endregion
|
|
585
|
-
//#region src/entity-editor/editor-resources.d.ts
|
|
586
|
-
declare const roleOrder: {
|
|
587
|
-
readonly caption: 0;
|
|
588
|
-
readonly video_clip: 1;
|
|
589
|
-
readonly speech: 2;
|
|
590
|
-
readonly bgm: 3;
|
|
591
|
-
};
|
|
592
|
-
type EditorTrackRole = keyof typeof roleOrder;
|
|
593
|
-
interface EditorFoundation {
|
|
594
|
-
readonly rows: EntityRelationRows;
|
|
595
|
-
readonly timelineEntityId: string;
|
|
596
|
-
readonly trackEntityIds: Readonly<Record<EditorTrackRole, string>>;
|
|
597
|
-
/** Initial or current AudioScript content ID selected by the foundation. */
|
|
598
|
-
readonly audioScriptEntityId: string;
|
|
599
|
-
}
|
|
181
|
+
//#region src/editor/id-gen.d.ts
|
|
600
182
|
/**
|
|
601
|
-
*
|
|
183
|
+
* Part-id generation, aligned with the online ecosystem.
|
|
602
184
|
*
|
|
603
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
*
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
/**
|
|
611
|
-
* Commit-transition policy shared by the editor, the HTTP commit boundary, the
|
|
612
|
-
* host tool, and the entity stores. It compares the authoritative before and
|
|
613
|
-
* after rows of one CAS commit and enforces the single-identity write rules
|
|
614
|
-
* on the complete after state, with no exemption for historical graphs:
|
|
615
|
-
*
|
|
616
|
-
* 1. every Image/Video/Audio/Voice Entity carries its own Asset `external`
|
|
617
|
-
* identity;
|
|
618
|
-
* 2. no `physical-asset` Relation may bind a media variant;
|
|
619
|
-
* 3. a self-carried media identity is immutable — it cannot be rewritten to
|
|
620
|
-
* another asset id.
|
|
185
|
+
* The authoritative online producers — agent-harness (`@harness/shared`
|
|
186
|
+
* `genObjId`) and director.v2 (`common/obj_id.py` `gen_obj_id`) — both mint part
|
|
187
|
+
* ids as `` `${prefix}_${ulid()}` ``, and real captured drafts use exactly that
|
|
188
|
+
* shape (`clip_…` / `spe_…` / `cap_…` / `bgm_…`, each a 26-char ULID). The engine
|
|
189
|
+
* previously emitted `vc_<base36 timestamp><6 random>`, a different prefix AND a
|
|
190
|
+
* different encoding — the sole cross-repo id divergence. This module removes it
|
|
191
|
+
* by emitting the same `<prefix>_<ULID>` bytes.
|
|
621
192
|
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
193
|
+
* The ULID is generated inline (Crockford Base32, 48-bit time + 80-bit random)
|
|
194
|
+
* rather than pulling the `ulid` npm package: the randomness class matches the
|
|
195
|
+
* old generator (both `Math.random`-based) and it keeps `@mengine/medeo-client`
|
|
196
|
+
* dependency-free for a purely mechanical id string. Part ids only need to be
|
|
197
|
+
* unique and lexicographically time-sortable, which this satisfies.
|
|
624
198
|
*/
|
|
625
|
-
declare function assertMediaAssetWritePolicy(before: EntityRelationRows, after: EntityRelationRows): void;
|
|
626
|
-
/** Add only missing editor structure; existing identities and owned settings are never replaced. */
|
|
627
|
-
declare function ensureEditorFoundation(initial: EntityRelationRows, idFactory?: EntityTimelineIdFactory, timelinePayload?: EntityRow['payload'], selectedAudioScriptEntityId?: string | null): EditorFoundation;
|
|
628
|
-
//#endregion
|
|
629
|
-
//#region src/entity-editor/media-asset-import.d.ts
|
|
630
|
-
interface ImportedMediaAsset {
|
|
631
|
-
readonly rows: EntityRelationRows;
|
|
632
|
-
/** The single media variant identity for this asset id; it is its own Asset. */
|
|
633
|
-
readonly contentEntityId: string;
|
|
634
|
-
}
|
|
635
199
|
/**
|
|
636
|
-
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
640
|
-
*
|
|
641
|
-
* the external locator itself, and deduplicates only against existing variants
|
|
642
|
-
* that already carry the same `(system, key)`. Legacy dual-entity graphs
|
|
643
|
-
* (`asset` row plus a `physical-asset` binding) are not reused and are
|
|
644
|
-
* rejected by the canonical resource policy instead of being migrated.
|
|
200
|
+
* Online part-id semantic prefixes. `clip` (video clip) is the only value the
|
|
201
|
+
* engine currently mints (see `addVideoClips`); the rest are declared so the
|
|
202
|
+
* type documents the shared vocabulary and guards against reintroducing the old
|
|
203
|
+
* `vc`/`sp`/`cp`/`bg` names. Speech/caption/bgm ids arrive pre-minted in op
|
|
204
|
+
* payloads, so the engine never generates them itself.
|
|
645
205
|
*/
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
//#region src/entity-editor/legacy-entity-migration.d.ts
|
|
649
|
-
/** One-time import only. Ordinary editor operations must never reverse-diff a legacy document. */
|
|
650
|
-
declare function migrateLegacyTimelineToEntities(legacy: VideoDocument, assetFacts: readonly MediaAssetFact[], initial?: EntityRelationRows, idFactory?: EntityTimelineIdFactory): EntityRelationRows;
|
|
651
|
-
/** Server gate: a cutover may change representation, never the existing render facts. */
|
|
652
|
-
declare function assertEntityProjectionPreservesLegacy(legacy: VideoDocument, projection: VideoDocument, rows: EntityRelationRows): void;
|
|
653
|
-
//#endregion
|
|
654
|
-
//#region src/entity-editor/caption-content.d.ts
|
|
655
|
-
interface CaptionContentInput {
|
|
656
|
-
readonly contentEntityId: string;
|
|
657
|
-
readonly audioScriptEntityId: string;
|
|
658
|
-
readonly text: string;
|
|
659
|
-
readonly selection?: CaptionSegmentSelection;
|
|
660
|
-
readonly durationMs: number;
|
|
661
|
-
}
|
|
662
|
-
/** Author Caption content from semantic intent; callers never reconcile variant bases or assembled fields. */
|
|
663
|
-
declare function prepareCaptionContent(rows: EntityRelationRows, input: CaptionContentInput): EntityRow<'caption'>;
|
|
664
|
-
//#endregion
|
|
665
|
-
//#region src/entity-editor/document-audio-script.d.ts
|
|
666
|
-
interface DocumentAudioScript {
|
|
667
|
-
readonly entityId: string;
|
|
668
|
-
readonly segments: readonly (ScriptTextSegment & Readonly<Record<string, unknown>>)[];
|
|
669
|
-
}
|
|
670
|
-
/** State exposing the current AudioScript content version attached to the project. */
|
|
671
|
-
interface DocumentAudioScriptState {
|
|
672
|
-
readonly rows: EntityRelationRows;
|
|
673
|
-
/** Current attachment; initialized projects point to a real script, including an empty one. */
|
|
674
|
-
readonly audioScriptEntityId: string | null;
|
|
675
|
-
}
|
|
676
|
-
/** Read only the attached version and preserve every segment; never aggregate other scripts. */
|
|
677
|
-
declare function readDocumentAudioScript(state: DocumentAudioScriptState): DocumentAudioScript;
|
|
678
|
-
//#endregion
|
|
679
|
-
//#region src/entity-crdt/field-changes.d.ts
|
|
680
|
-
/** List members are addressed by identity, never a transient array offset. */
|
|
681
|
-
type FieldPath = readonly (string | {
|
|
682
|
-
elementId: string;
|
|
683
|
-
})[];
|
|
684
|
-
type FieldChange = {
|
|
685
|
-
op: 'set';
|
|
686
|
-
path: FieldPath;
|
|
687
|
-
value: JsonValue;
|
|
688
|
-
} | {
|
|
689
|
-
op: 'unset';
|
|
690
|
-
path: FieldPath;
|
|
691
|
-
} | {
|
|
692
|
-
op: 'text.splice';
|
|
693
|
-
path: FieldPath;
|
|
694
|
-
index: number;
|
|
695
|
-
deleteCount: number;
|
|
696
|
-
text: string;
|
|
697
|
-
} | {
|
|
698
|
-
op: 'list.insert';
|
|
699
|
-
path: FieldPath;
|
|
700
|
-
value: JsonValue;
|
|
701
|
-
beforeElementId: string | null;
|
|
702
|
-
} | {
|
|
703
|
-
op: 'list.move';
|
|
704
|
-
path: FieldPath;
|
|
705
|
-
elementId: string;
|
|
706
|
-
beforeElementId: string | null;
|
|
707
|
-
} | {
|
|
708
|
-
op: 'list.remove';
|
|
709
|
-
path: FieldPath;
|
|
710
|
-
elementId: string;
|
|
711
|
-
};
|
|
712
|
-
declare function assertFieldChanges(changes: readonly FieldChange[]): void;
|
|
713
|
-
/** Resolve against the sequential causal view; the numeric path never crosses the API boundary. */
|
|
714
|
-
declare function resolveFieldPath(payload: JsonObject, path: FieldPath): (string | number)[];
|
|
715
|
-
/** Detached plan evaluation. Native compilation replays the original operations, not this snapshot. */
|
|
716
|
-
declare function applyFieldChanges(payload: JsonObject, changes: readonly FieldChange[]): JsonObject;
|
|
717
|
-
//#endregion
|
|
718
|
-
//#region src/entity-crdt/entity-document.d.ts
|
|
719
|
-
declare const LORO_ENTITY_SCHEMA = "medeo.entities.loro.v1";
|
|
720
|
-
interface EntityDocumentState {
|
|
721
|
-
readonly rows: EntityRelationRows;
|
|
722
|
-
readonly project: Readonly<Record<string, string>>;
|
|
723
|
-
}
|
|
724
|
-
type Command = {
|
|
725
|
-
type: 'create';
|
|
726
|
-
row: EntityRow;
|
|
727
|
-
} | {
|
|
728
|
-
type: 'selection-baseline';
|
|
729
|
-
root: string;
|
|
730
|
-
fingerprint: string;
|
|
731
|
-
} | {
|
|
732
|
-
type: 'order';
|
|
733
|
-
group: string;
|
|
734
|
-
roots: string[];
|
|
735
|
-
token: string;
|
|
736
|
-
} | {
|
|
737
|
-
type: 'write';
|
|
738
|
-
root: string;
|
|
739
|
-
payload: JsonObject;
|
|
740
|
-
token: string;
|
|
741
|
-
} | {
|
|
742
|
-
type: 'text';
|
|
743
|
-
root: string;
|
|
744
|
-
path: readonly (string | number)[];
|
|
745
|
-
start: number;
|
|
746
|
-
deleteCount: number;
|
|
747
|
-
text: string;
|
|
748
|
-
token: string;
|
|
749
|
-
} | {
|
|
750
|
-
type: 'field';
|
|
751
|
-
root: string;
|
|
752
|
-
path: (string | number)[];
|
|
753
|
-
change: FieldChange;
|
|
754
|
-
token: string;
|
|
755
|
-
} | {
|
|
756
|
-
type: 'relation-field';
|
|
757
|
-
root: string;
|
|
758
|
-
path: (string | number)[];
|
|
759
|
-
change: FieldChange;
|
|
760
|
-
} | {
|
|
761
|
-
type: 'delete';
|
|
762
|
-
root: string;
|
|
763
|
-
} | {
|
|
764
|
-
type: 'relation';
|
|
765
|
-
row: RelationRow;
|
|
766
|
-
} | {
|
|
767
|
-
type: 'relation-fields';
|
|
768
|
-
root: string;
|
|
769
|
-
metadata: JsonObject;
|
|
770
|
-
trace: JsonObject;
|
|
771
|
-
} | {
|
|
772
|
-
type: 'unlink';
|
|
773
|
-
root: string;
|
|
774
|
-
} | {
|
|
775
|
-
type: 'attach';
|
|
776
|
-
slot: string;
|
|
777
|
-
entityId: string;
|
|
778
|
-
};
|
|
779
|
-
/** Plain domain objects assembled from native Loro state, never a second writable authority. */
|
|
780
|
-
declare function readEntityDocument(doc: LoroDoc, allowSelectionConflicts?: boolean): EntityDocumentState;
|
|
781
|
-
/** Native editing containers survive domain version changes and merge independently. */
|
|
782
|
-
declare class LoroEntityDocument {
|
|
783
|
-
readonly doc: LoroDoc;
|
|
784
|
-
private readonly validate?;
|
|
785
|
-
private readonly undoManager;
|
|
786
|
-
constructor(doc: LoroDoc, validate?: ((state: EntityDocumentState) => void) | undefined);
|
|
787
|
-
/** Open a causal snapshot using the same Loro runtime as the compiler. */
|
|
788
|
-
static fromSnapshot(snapshot: Uint8Array, validate?: (state: EntityDocumentState) => void): LoroEntityDocument;
|
|
789
|
-
static create(rows: EntityRelationRows, project?: Readonly<Record<string, string>>, peerId?: PeerID): LoroEntityDocument;
|
|
790
|
-
snapshot(): EntityDocumentState;
|
|
791
|
-
relationsOf(entityId: string): readonly RelationRow[];
|
|
792
|
-
getVersion(id: string): EntityRow | undefined;
|
|
793
|
-
/** The callback and every domain validation execute on a causally complete fork first. */
|
|
794
|
-
transact(edit: (draft: LoroEntityDraft) => void): Uint8Array;
|
|
795
|
-
/** Import preserves native operation identities; projection errors never discard remote operations. */
|
|
796
|
-
import(update: Uint8Array): void;
|
|
797
|
-
canUndo(): boolean;
|
|
798
|
-
canRedo(): boolean;
|
|
799
|
-
undo(): boolean;
|
|
800
|
-
redo(): boolean;
|
|
801
|
-
private historyEdit;
|
|
802
|
-
}
|
|
803
|
-
declare class LoroEntityDraft {
|
|
804
|
-
private readonly doc;
|
|
805
|
-
readonly commands: Command[];
|
|
806
|
-
private readonly selectedRoots;
|
|
807
|
-
private readonly relationAliases;
|
|
808
|
-
constructor(doc: LoroDoc);
|
|
809
|
-
snapshot(): EntityDocumentState;
|
|
810
|
-
order(groupId: string, entityIds: readonly string[]): void;
|
|
811
|
-
/** Project the final scalar placement intents onto the existing native ordering containers. */
|
|
812
|
-
reconcileOrder(rows: EntityRelationRows): void;
|
|
813
|
-
create(row: EntityRow): void;
|
|
814
|
-
delete(entityId: string): void;
|
|
815
|
-
attach(slot: string, entityId: string): void;
|
|
816
|
-
link(row: RelationRow): void;
|
|
817
|
-
patchRelation(relationId: string, metadata: JsonObject, trace: JsonObject): void;
|
|
818
|
-
unlink(relationId: string): void;
|
|
819
|
-
private relationRoot;
|
|
820
|
-
update(entityId: string, fields: JsonObject): void;
|
|
821
|
-
declare(entityId: string, fields: JsonObject): void;
|
|
822
|
-
replaceOwned(entityId: string, payload: JsonObject): void;
|
|
823
|
-
editText(entityId: string, path: readonly (string | number)[], start: number, deleteCount: number, text: string): void;
|
|
824
|
-
/** Generic assembled-field edit compiled at the author's causal position. */
|
|
825
|
-
change(entityId: string, changes: readonly FieldChange[]): void;
|
|
826
|
-
changeRelation(relationId: string, changes: readonly FieldChange[]): void;
|
|
827
|
-
captureSelectionBaselines(): void;
|
|
828
|
-
private record;
|
|
829
|
-
}
|
|
830
|
-
//#endregion
|
|
831
|
-
//#region src/entity-crdt/compile-rows.d.ts
|
|
832
|
-
/** Lower a detached ordinary-object edit against its actual causal Loro baseline. */
|
|
833
|
-
declare function compileEntityRows(snapshot: Uint8Array, rows: EntityRelationRows, validate?: (state: EntityDocumentState) => void): {
|
|
834
|
-
update: Uint8Array;
|
|
835
|
-
state: EntityDocumentState;
|
|
836
|
-
};
|
|
837
|
-
/** Compile an edit on an existing peer, retaining its native local undo history. */
|
|
838
|
-
declare function applyEntityRows(editor: LoroEntityDocument, rows: EntityRelationRows): {
|
|
839
|
-
update: Uint8Array;
|
|
840
|
-
state: EntityDocumentState;
|
|
841
|
-
};
|
|
842
|
-
//#endregion
|
|
843
|
-
//#region src/editor/journal.d.ts
|
|
844
|
-
/**
|
|
845
|
-
* Wire a plain-memory adapter + editor that share a recording id factory, so
|
|
846
|
-
* every mutating transact lands in `journal` with ordered `generated_ids`.
|
|
847
|
-
*/
|
|
848
|
-
declare function createEditSandbox(document: VideoDocument, options?: PlainMemoryAdapterOptions): {
|
|
849
|
-
adapter: PlainMemoryAdapter;
|
|
850
|
-
editor: SemanticEditor;
|
|
851
|
-
journal: readonly JournalEntry[];
|
|
852
|
-
};
|
|
853
|
-
/**
|
|
854
|
-
* Re-drive `doc` from a recorded journal, forcing each entry's `generated_ids`
|
|
855
|
-
* through a queue-backed id factory. Never mints fresh ids: an empty queue on
|
|
856
|
-
* demand throws `unrecorded id`; leftover ids after an entry throws
|
|
857
|
-
* `unconsumed ids`. Legacy entries without `generated_ids` are treated as `[]`.
|
|
858
|
-
*/
|
|
859
|
-
declare function replayJournal(doc: SemanticDocumentAdapter, journal: readonly JournalEntry[]): Promise<void>;
|
|
206
|
+
type PartIdPrefix = 'clip' | 'spe' | 'cap' | 'bgm' | 'ti';
|
|
207
|
+
declare function generatePartId(prefix: PartIdPrefix): string;
|
|
860
208
|
//#endregion
|
|
861
209
|
//#region src/editor/snapshot-utils.d.ts
|
|
862
210
|
/** Main-track item identity read from a raw snapshot (only `part_id` is needed). */
|
|
@@ -949,7 +297,9 @@ type PushResultKind = 'ack' | 'duplicate' | 'rejected' | 'failed' | 'nothing_to_
|
|
|
949
297
|
*/
|
|
950
298
|
interface PushResult {
|
|
951
299
|
kind: PushResultKind;
|
|
952
|
-
/** Server
|
|
300
|
+
/** Server document sequence observed after a successful `ack` or `duplicate`. */
|
|
301
|
+
mengineUpdateSeq?: number | undefined;
|
|
302
|
+
/** @deprecated Ack-only sequence retained until consumers adopt `mengineUpdateSeq`. */
|
|
953
303
|
updateSeq?: number | undefined;
|
|
954
304
|
/** Whether the server held ops the local document lacked. See above. */
|
|
955
305
|
collaborated: boolean;
|
|
@@ -1056,8 +406,7 @@ declare class ManualSyncDoc {
|
|
|
1056
406
|
* Fetches the snapshot up front rather than starting empty and converging: the
|
|
1057
407
|
* agent's first act is to read the document, so there is no useful state before
|
|
1058
408
|
* the snapshot lands. This also fails fast and loudly on a document that does
|
|
1059
|
-
* not exist
|
|
1060
|
-
* waiting forever for content that will never arrive.
|
|
409
|
+
* not exist or whose first snapshot is incomplete or invalid.
|
|
1061
410
|
*/
|
|
1062
411
|
static open(options: ManualSyncDocOptions): Promise<ManualSyncDoc>;
|
|
1063
412
|
/** Current document read model (authoritative shape). */
|
|
@@ -1073,27 +422,16 @@ declare class ManualSyncDoc {
|
|
|
1073
422
|
* was passed to the constructor.
|
|
1074
423
|
*/
|
|
1075
424
|
editorPeerId(): PeerID;
|
|
1076
|
-
/** Current
|
|
1077
|
-
|
|
1078
|
-
/**
|
|
1079
|
-
* Replay a deterministic sandbox journal into this document.
|
|
1080
|
-
*
|
|
1081
|
-
* The adapter stays private so callers cannot bypass the manual-sync
|
|
1082
|
-
* lifecycle; journal replay is the one host-side operation that needs the
|
|
1083
|
-
* adapter's transaction boundary and recorded id queue. Durability is still
|
|
1084
|
-
* explicit: call {@link push} after replay and report success only from its
|
|
1085
|
-
* verdict.
|
|
1086
|
-
*/
|
|
1087
|
-
replayJournal(journal: readonly JournalEntry[]): Promise<void>;
|
|
425
|
+
/** Current content projected into the compatible track and part read shape. */
|
|
426
|
+
content(): VideoDraftContent;
|
|
1088
427
|
/**
|
|
1089
428
|
* Mark the document state the caller has just observed, for a later
|
|
1090
429
|
* {@link hasChangedSince}.
|
|
1091
430
|
*
|
|
1092
431
|
* This pair replaces the legacy integer-version comparison that
|
|
1093
432
|
* `DraftVersionDetector` used to tell the LLM "the draft was modified
|
|
1094
|
-
* externally, reload before editing".
|
|
1095
|
-
*
|
|
1096
|
-
* vectors restores the same capability.
|
|
433
|
+
* externally, reload before editing". Comparing Loro version vectors covers
|
|
434
|
+
* all collaborative edits without a business revision field in the document.
|
|
1097
435
|
*
|
|
1098
436
|
* Same capability, not a stronger one: like the legacy detector, this only
|
|
1099
437
|
* reports what changed between two moments the caller chose to sample.
|
|
@@ -1238,12 +576,24 @@ declare class MedeoHttpDocStorage implements DocStorage {
|
|
|
1238
576
|
* tool-level ack wait) subscribe here.
|
|
1239
577
|
*/
|
|
1240
578
|
subscribePushOutcome(callback: (outcome: PushOutcome) => void): () => void;
|
|
579
|
+
/** Observe live hints that require VV catch-up without replacing the SSE connection. */
|
|
580
|
+
subscribeResync(callback: () => void): () => void;
|
|
581
|
+
/** Authoritative HTTP reads and accepted pushes, never inferred from SSE bytes. */
|
|
582
|
+
subscribeServerVersion(callback: (version: Uint8Array) => void): () => void;
|
|
583
|
+
private reportServerVersion;
|
|
1241
584
|
deleteDoc(_docId: string): Promise<void>;
|
|
1242
585
|
subscribeDocUpdate(callback: (update: DocUpdate, origin: unknown) => void): () => void;
|
|
1243
586
|
private assertDocId;
|
|
1244
587
|
private emitUpdate;
|
|
1245
588
|
}
|
|
1246
589
|
//#endregion
|
|
590
|
+
//#region src/session/document-undo-manager.d.ts
|
|
591
|
+
/** Availability for this document's current editing session, not server revisions. */
|
|
592
|
+
interface MengineUndoState {
|
|
593
|
+
readonly canUndo: boolean;
|
|
594
|
+
readonly canRedo: boolean;
|
|
595
|
+
}
|
|
596
|
+
//#endregion
|
|
1247
597
|
//#region src/session/types.d.ts
|
|
1248
598
|
/**
|
|
1249
599
|
* Local storage contract the runtime depends on. Aliased to the engine
|
|
@@ -1282,10 +632,23 @@ declare class MengineAckFailedError extends Error {
|
|
|
1282
632
|
readonly cause: Error | undefined;
|
|
1283
633
|
constructor(reason: 'timeout' | 'rejected' | 'failed', code: string | undefined, cause: Error | undefined, message: string);
|
|
1284
634
|
}
|
|
635
|
+
type MengineLocalSaveState = LocalSaveState;
|
|
636
|
+
interface WaitForLocalSaveOptions {
|
|
637
|
+
/** Only limits waiting, never cancels persistence. */
|
|
638
|
+
timeoutMs?: number;
|
|
639
|
+
}
|
|
1285
640
|
interface WaitForServerAckOptions {
|
|
1286
641
|
/** Deadline in ms. Rejects with reason `timeout` when it elapses. */
|
|
1287
642
|
timeoutMs?: number;
|
|
1288
643
|
}
|
|
644
|
+
/** Document-level confirmation is independent of local operation completion. */
|
|
645
|
+
interface MengineDocSyncState {
|
|
646
|
+
/** Server-originated imports do not create a new local confirmation obligation. */
|
|
647
|
+
readonly confirmation: 'unknown' | 'pending' | 'confirmed';
|
|
648
|
+
/** Transport/activity phase. Idle does not imply confirmation; failure details
|
|
649
|
+
* remain available through push outcomes and confirmation wait errors. */
|
|
650
|
+
readonly phase: 'connecting' | 'idle' | 'syncing' | 'offline' | 'failed';
|
|
651
|
+
}
|
|
1289
652
|
interface MengineDocSessionOptions {
|
|
1290
653
|
docId: string;
|
|
1291
654
|
client: MengineHttpClient;
|
|
@@ -1295,24 +658,18 @@ interface MengineDocSessionOptions {
|
|
|
1295
658
|
* Browsers should pass an `IndexedDBDocStorage` for refresh/cross-tab support.
|
|
1296
659
|
*/
|
|
1297
660
|
localStorage?: DocStorageLike;
|
|
661
|
+
/** A freshly fetched remote snapshot to merge into storage before loading.
|
|
662
|
+
* Existing local changes are retained; the host owns any online startup gate. */
|
|
663
|
+
initialSnapshot?: Uint8Array;
|
|
1298
664
|
sseReconnectDelayMs?: number;
|
|
1299
|
-
/**
|
|
1300
|
-
* Keep remote synchronization read-only: pull snapshot/diffs and subscribe to
|
|
1301
|
-
* SSE updates, but never POST local Loro updates to the server.
|
|
1302
|
-
*/
|
|
1303
|
-
readonlyMode?: boolean;
|
|
1304
665
|
}
|
|
1305
666
|
/**
|
|
1306
667
|
* A live editing session for one Medeo document — the single entry point clients
|
|
1307
668
|
* (FE draft driver, Agent, embeds) use to open, edit, and observe a document.
|
|
1308
669
|
*
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1312
|
-
* ├─ ClientServerSynchronizer ── DocManager ── LoroDoc
|
|
1313
|
-
* MedeoHttpDocStorage┘ │
|
|
1314
|
-
* (remote = Rust mengine-server) ▼
|
|
1315
|
-
* MirrorVideoDocumentAdapter + SemanticEditor
|
|
670
|
+
* SemanticEditor writes through MirrorVideoDocumentAdapter directly, while
|
|
671
|
+
* DocumentUndoManager observes the same LoroDoc independently. Both mutation
|
|
672
|
+
* paths use the session's DocumentMutationGuard, closed before teardown.
|
|
1316
673
|
*
|
|
1317
674
|
* `DocManager` owns the `LoroDoc`: local edits committed on the adapter are
|
|
1318
675
|
* picked up via `subscribeLocalUpdates`, saved to local storage, then pushed to
|
|
@@ -1333,11 +690,21 @@ declare class MengineDocSession {
|
|
|
1333
690
|
private readonly manager;
|
|
1334
691
|
private readonly events;
|
|
1335
692
|
private readonly disposables;
|
|
693
|
+
private readonly mutationGuard;
|
|
1336
694
|
private adapterValue;
|
|
1337
695
|
private editorValue;
|
|
696
|
+
private undoManagerValue;
|
|
1338
697
|
private started;
|
|
698
|
+
private startTask;
|
|
699
|
+
private destroyed;
|
|
700
|
+
private closeTask;
|
|
701
|
+
private lifetime;
|
|
702
|
+
private hasConnected;
|
|
703
|
+
private initialVersionValue;
|
|
704
|
+
private localVersionValue;
|
|
705
|
+
private pushErrorValue;
|
|
1339
706
|
/**
|
|
1340
|
-
* Latest server oplog version seen on
|
|
707
|
+
* Latest server oplog version seen on an authoritative HTTP response. Lets `waitForServerAck`
|
|
1341
708
|
* return without waiting when the server is already known to cover the local
|
|
1342
709
|
* doc (e.g. nothing was edited since the last confirmed push).
|
|
1343
710
|
*/
|
|
@@ -1352,14 +719,14 @@ declare class MengineDocSession {
|
|
|
1352
719
|
*/
|
|
1353
720
|
subscribePushOutcome(callback: (outcome: PushOutcome) => void): () => void;
|
|
1354
721
|
/**
|
|
1355
|
-
* Resolve once the server has durably accepted the local
|
|
722
|
+
* Resolve once the server has durably accepted the local commits as of
|
|
1356
723
|
* *now* — the capability an Agent tool needs to answer "did my edit land?"
|
|
1357
724
|
* before reporting success.
|
|
1358
725
|
*
|
|
1359
726
|
* Call it right after the editor ops whose durability matters. It snapshots the
|
|
1360
|
-
* local
|
|
1361
|
-
*
|
|
1362
|
-
*
|
|
727
|
+
* latest local commit's version (or the loaded baseline before any edit) and
|
|
728
|
+
* resolves when an authoritative server version covers it. Remote-only
|
|
729
|
+
* imports do not extend this target, matching the displayed confirmation state.
|
|
1363
730
|
*
|
|
1364
731
|
* Version coverage, not byte identity, is the acceptance test — for two reasons:
|
|
1365
732
|
* the ops may reach the server inside a merged blob rather than as the exact
|
|
@@ -1381,43 +748,70 @@ declare class MengineDocSession {
|
|
|
1381
748
|
* step. The committed change drives DocManager's local-update push.
|
|
1382
749
|
*/
|
|
1383
750
|
get editor(): SemanticEditor;
|
|
751
|
+
/** Current document snapshot (read model). */
|
|
752
|
+
snapshot(): VideoDocument;
|
|
753
|
+
/** Current-session undo/redo availability. Loading and closed sessions report false. */
|
|
754
|
+
getUndoState(): MengineUndoState;
|
|
1384
755
|
/**
|
|
1385
|
-
*
|
|
1386
|
-
*
|
|
1387
|
-
* remote-arrived) since the token was taken. Throws when not started.
|
|
756
|
+
* Supplies current availability immediately, then coalesces stack changes in a
|
|
757
|
+
* microtask. Session teardown publishes empty availability synchronously.
|
|
1388
758
|
*/
|
|
1389
|
-
|
|
759
|
+
subscribeUndoState(cb: (state: MengineUndoState) => void): () => void;
|
|
1390
760
|
/**
|
|
1391
|
-
*
|
|
1392
|
-
*
|
|
1393
|
-
*
|
|
761
|
+
* Undo a local edit immediately; server confirmation remains asynchronous.
|
|
762
|
+
* On a shared LWW field this writes its prior value, potentially overwriting a
|
|
763
|
+
* later remote edit to that same field. Returns false if no update is produced.
|
|
1394
764
|
*/
|
|
1395
|
-
|
|
1396
|
-
/**
|
|
1397
|
-
|
|
765
|
+
undo(options?: CommitOptions): boolean;
|
|
766
|
+
/**
|
|
767
|
+
* Restore the state visible before undo without rerunning external side effects.
|
|
768
|
+
* Returns false if no update is produced; durable confirmation is separate.
|
|
769
|
+
*/
|
|
770
|
+
redo(options?: CommitOptions): boolean;
|
|
771
|
+
/**
|
|
772
|
+
* Combine existing semantic operations (e.g. trim a clip and adjust its volume)
|
|
773
|
+
* or repeated commits during one drag gesture into a single undo step. A gesture
|
|
774
|
+
* that only previews locally and commits once on release needs no group.
|
|
775
|
+
* Each commit is immediately visible locally and enters sync independently;
|
|
776
|
+
* a later failure does not roll it back.
|
|
777
|
+
* Always pair with endUndoGroup in a finally block. Conflicting remote imports
|
|
778
|
+
* can end/split the group early, and unrelated local edits would join it.
|
|
779
|
+
* Complete asynchronous asset preparation before opening the group.
|
|
780
|
+
*/
|
|
781
|
+
beginUndoGroup(): void;
|
|
782
|
+
/** End a gesture, including one already split by a conflicting remote import. */
|
|
783
|
+
endUndoGroup(): void;
|
|
1398
784
|
/**
|
|
1399
785
|
* Start the sync stack and connect the document.
|
|
1400
786
|
*
|
|
1401
|
-
* Returns
|
|
1402
|
-
*
|
|
1403
|
-
*
|
|
787
|
+
* Returns after DocManager loads a local snapshot, or after the first remote
|
|
788
|
+
* sync when no local snapshot exists. A valid empty document is ready too.
|
|
789
|
+
* Cached documents can open before SSE connects; subsequent remote changes
|
|
790
|
+
* surface through `subscribe`.
|
|
1404
791
|
*/
|
|
1405
792
|
start(): Promise<VideoDocument>;
|
|
793
|
+
private open;
|
|
794
|
+
getLocalSaveState(): MengineLocalSaveState;
|
|
795
|
+
/** Immediately reports local transaction state; independent of server confirmation. */
|
|
796
|
+
subscribeLocalSaveState(cb: (state: MengineLocalSaveState) => void): () => void;
|
|
797
|
+
/** Waits for commits present now to reach local storage. Does not wait for the network. */
|
|
798
|
+
waitForLocalSave(options?: WaitForLocalSaveOptions): Promise<void>;
|
|
799
|
+
/** Stop accepting edits and drain local persistence before releasing resources.
|
|
800
|
+
* A failed local write keeps retrying, even after the host has unmounted.
|
|
801
|
+
* Hosts should use this for normal teardown; destroy() is immediate cancellation. */
|
|
802
|
+
close(): Promise<void>;
|
|
803
|
+
getSyncState(): MengineDocSyncState;
|
|
804
|
+
private trackLocalVersion;
|
|
805
|
+
private confirmationTarget;
|
|
806
|
+
/** Immediately supplies current state; unsubscribe when the host changes docs. */
|
|
807
|
+
subscribeSyncState(cb: (state: MengineDocSyncState) => void): () => void;
|
|
808
|
+
private emitSyncState;
|
|
1406
809
|
subscribe(cb: (event: MengineDocSessionUpdateEvent) => void): () => void;
|
|
1407
810
|
onStateChange(cb: (state: DocState) => void): () => void;
|
|
1408
811
|
getState(): DocState;
|
|
1409
812
|
destroy(): void;
|
|
1410
|
-
/**
|
|
1411
|
-
|
|
1412
|
-
*
|
|
1413
|
-
* `DocManager` loads from local storage, which starts empty for a fresh
|
|
1414
|
-
* client; the server snapshot arrives asynchronously via the first sync job.
|
|
1415
|
-
* `loaded` only means the local load ran, so we wait for actual content
|
|
1416
|
-
* (populated schema roots) instead, surfaced by the doc subscription set up
|
|
1417
|
-
* in `start()`.
|
|
1418
|
-
*/
|
|
1419
|
-
private waitForContent;
|
|
1420
|
-
private hasContent;
|
|
813
|
+
/** Local absence needs a remote sync; empty business content does not. */
|
|
814
|
+
private waitForInitialLoad;
|
|
1421
815
|
}
|
|
1422
816
|
//#endregion
|
|
1423
817
|
//#region src/storage/memory-doc-storage.d.ts
|
|
@@ -1744,4 +1138,4 @@ declare function hostForAbsMs(ranges: MainClipRange[], absMs: number): MainClipR
|
|
|
1744
1138
|
*/
|
|
1745
1139
|
declare function relativePositionForAbs(ranges: MainClipRange[], absMs: number): TrackItemTimePosition;
|
|
1746
1140
|
//#endregion
|
|
1747
|
-
export { type Aggregation, type
|
|
1141
|
+
export { type Aggregation, type Attachment, type BgmPart, type CaptionPart, type CaptionStyle, type CommitOptions, DEFAULT_UNIT_TIME_MS, type DerivedItemPosition, type DocStorageLike, type DocVersionMark, IMPLEMENTED_SEMANTIC_OP_KINDS, type ImplementedSemanticOpKind, LANE_KINDS_IN_STACK_ORDER, type LaneKind, type MainClipRange, type MakeEmptyPart, ManualSyncDoc, type ManualSyncDocOptions, MedeoHttpDocStorage, type MedeoHttpDocStorageOptions, MemoryDocStorage, MengineAckFailedError, type MengineAuditEntry, type MengineAuditResponse, MengineDocSession, type MengineDocSessionOptions, type MengineDocSessionUpdateEvent, type MengineDocSyncState, type MengineDocumentVersion, type MengineEventStreamOptions, MengineHttpClient, type MengineHttpClientOptions, MengineHttpRequestError, type MengineLocalSaveState, MenginePushRejectedError, type MenginePushResponse, type MenginePushUpdateResponse, type MengineRejectedResponse, type MengineSnapshotResponse, type MengineSseUpdateEvent, type MengineSyncResponse, type MengineUndoState, 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, ValidationError, type VideoClipPart, type VideoDocument, type VideoDocumentDraft, type VideoDocumentMirrorSchema, VideoDocumentValidationError, type VideoDocumentValidationIssue, type VideoDocumentValidationIssueCode, type VideoDraft, type CaptionPart$1 as VideoDraftCaptionPart, type VideoDraftContent, type VideoDraftPartUnion, type Timeline$1 as VideoDraftTimeline, type Track$1 as VideoDraftTrack, type TrackItem$1 as VideoDraftTrackItem, type WaitForLocalSaveOptions, type WaitForServerAckOptions, arrangeMainTrackSeamlessly, assertValidVideoDocument, base64ToBytes, buildInitialVideoDocument, buildSpeechHostMap, bytesToBase64, cascadeAfterVideoClipChanges, createMirrorVideoDocument, createMirrorVideoDocumentAdapter, decodeDocVersionMark, derivePositionFromAbs, encodeDocVersionMark, ensureLaneTrack, fillMainTrackTimeGaps, findLaneTrack, fromVideoDocument, generatePartId, getAt, hostForAbsMs, isEmptyVideoClip, isImplementedSemanticOpKind, isMap, laneTrackId, mainTrackRanges, partDurationMs, partUnionSchema, readMainTrackItems, readMengineEventStream, readPart, readPartDurationMs, readVideoDocumentFromDraft, reassignSpeechesToVideoClipsByTime, recalculateTimelineDuration, relativePositionForAbs, resolveAllSpeechOverlaps, resolveSpeechOverlapByShiftingVideos, safeDurationMs, index_d_exports as schemas, snapshotToPlain, solveVideoDocument, syncAggregatedClipsTimePosition, toVideoDocument, validateVideoDocument, videoDocumentMirrorSchema, videoDocumentSchema };
|