@mengine/medeo-client 2.0.1-alpha.28 → 2.0.1-alpha.29
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.
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { u as volumeSchema } from "./shared-iWnU2osE.js";
|
|
2
2
|
import { Mirror, schema, validateSchema } from "loro-mirror";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { LoroDoc, LoroMap, LoroMovableList, LoroText, UndoManager } from "loro-crdt";
|
|
5
4
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
6
|
-
import { bytesToHex } from "@noble/hashes/utils.js";
|
|
5
|
+
import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils.js";
|
|
6
|
+
import { LoroDoc, LoroMap, LoroMovableList, LoroText, UndoManager } from "loro-crdt";
|
|
7
7
|
import { produce } from "immer";
|
|
8
8
|
//#region src/client/base64.ts
|
|
9
9
|
function bytesToBase64(bytes) {
|
|
@@ -1508,6 +1508,7 @@ const ENTITY_KINDS = Object.freeze({
|
|
|
1508
1508
|
]),
|
|
1509
1509
|
voice: Object.freeze(["Container", "IPBound"]),
|
|
1510
1510
|
"sequence-marker": Object.freeze([]),
|
|
1511
|
+
script: Object.freeze(["SegmentText"]),
|
|
1511
1512
|
"audio-script": Object.freeze(["SegmentText", "MediaFile"]),
|
|
1512
1513
|
"phonetic-script": Object.freeze(["SegmentText", "MediaFile"]),
|
|
1513
1514
|
caption: Object.freeze([
|
|
@@ -1809,6 +1810,32 @@ function entityToRow(entity) {
|
|
|
1809
1810
|
};
|
|
1810
1811
|
}
|
|
1811
1812
|
//#endregion
|
|
1813
|
+
//#region ../medeo-dsl/src/script-content.ts
|
|
1814
|
+
/** Canonical text used to identify one immutable professional Script version. */
|
|
1815
|
+
function normalizeScriptText(text) {
|
|
1816
|
+
return text.normalize("NFC").replaceAll("\r\n", "\n").replaceAll("\r", "\n").split("\n").map((line) => line.trimEnd()).join("\n");
|
|
1817
|
+
}
|
|
1818
|
+
/** Preserve segment identity, boundaries and order while removing textual encoding noise. */
|
|
1819
|
+
function normalizeScriptSegments(segments) {
|
|
1820
|
+
return segments.map(({ segmentId, text, language }) => ({
|
|
1821
|
+
segmentId,
|
|
1822
|
+
text: normalizeScriptText(text),
|
|
1823
|
+
...language === void 0 ? {} : { language: language.normalize("NFC").trim() }
|
|
1824
|
+
}));
|
|
1825
|
+
}
|
|
1826
|
+
/** Content identity: ordered canonical text with array boundaries, never local ids or language metadata. */
|
|
1827
|
+
function scriptContentHash(segments) {
|
|
1828
|
+
return `sha256:${bytesToHex(sha256(utf8ToBytes(JSON.stringify(normalizeScriptSegments(segments).map((segment) => segment.text)))))}`;
|
|
1829
|
+
}
|
|
1830
|
+
//#endregion
|
|
1831
|
+
//#region ../medeo-dsl/src/script-revision.ts
|
|
1832
|
+
const HASH = /^sha256:[0-9a-f]{64}$/;
|
|
1833
|
+
function readScriptRevisionTrace(value) {
|
|
1834
|
+
if (!isJsonObject(value)) return null;
|
|
1835
|
+
if (Object.keys(value).length !== 4 || value.command !== "revise-script" || typeof value.editId !== "string" || value.editId.trim() !== value.editId || value.editId === "" || typeof value.sourceContentHash !== "string" || !HASH.test(value.sourceContentHash) || typeof value.resultContentHash !== "string" || !HASH.test(value.resultContentHash)) return null;
|
|
1836
|
+
return value;
|
|
1837
|
+
}
|
|
1838
|
+
//#endregion
|
|
1812
1839
|
//#region ../medeo-dsl/src/invariants.ts
|
|
1813
1840
|
/** An entity is made from at most one Asset; two would leave its bytes ambiguous. */
|
|
1814
1841
|
/** Validates one complete set of entities and its authoritative Relation rows. */
|
|
@@ -1848,6 +1875,38 @@ function validateEntityRelationSet(entityRefs, index) {
|
|
|
1848
1875
|
issues.push(...validateSequenceComposition(entity));
|
|
1849
1876
|
}
|
|
1850
1877
|
issues.push(...validateClipAnchorCycles(entities, index));
|
|
1878
|
+
issues.push(...validateScriptRevisionRelations(entities, index));
|
|
1879
|
+
return issues;
|
|
1880
|
+
}
|
|
1881
|
+
function validateScriptRevisionRelations(entities, index) {
|
|
1882
|
+
const byId = new Map(entities.map((entity) => [entity.entityId, entity.current()]));
|
|
1883
|
+
const seenRelations = /* @__PURE__ */ new Set();
|
|
1884
|
+
const editIds = /* @__PURE__ */ new Set();
|
|
1885
|
+
const parentCounts = /* @__PURE__ */ new Map();
|
|
1886
|
+
const issues = [];
|
|
1887
|
+
for (const entity of entities) for (const relation of index.relationsOf(entity)) {
|
|
1888
|
+
const row = relation.toRow();
|
|
1889
|
+
if (row == null || seenRelations.has(row.relationId)) continue;
|
|
1890
|
+
seenRelations.add(row.relationId);
|
|
1891
|
+
const result = byId.get(row.endpoint0EntityId);
|
|
1892
|
+
const source = byId.get(row.endpoint1EntityId);
|
|
1893
|
+
if (row.relationKind !== "derived-from" || result?.entityKind !== "script" || source?.entityKind !== "script") continue;
|
|
1894
|
+
const trace = readScriptRevisionTrace(row.trace);
|
|
1895
|
+
const invalid = trace == null || trace.resultContentHash !== result.contentHash || trace.sourceContentHash !== source.contentHash || trace.resultContentHash === trace.sourceContentHash || trace != null && editIds.has(trace.editId);
|
|
1896
|
+
if (trace != null) editIds.add(trace.editId);
|
|
1897
|
+
const parentCount = (parentCounts.get(row.endpoint0EntityId) ?? 0) + 1;
|
|
1898
|
+
parentCounts.set(row.endpoint0EntityId, parentCount);
|
|
1899
|
+
if (invalid) issues.push({
|
|
1900
|
+
code: "invalid_script_revision",
|
|
1901
|
+
entityId: row.endpoint0EntityId,
|
|
1902
|
+
message: "Script revision requires one canonical revise-script trace matching distinct result and source text"
|
|
1903
|
+
});
|
|
1904
|
+
if (parentCount > 1) issues.push({
|
|
1905
|
+
code: "invalid_script_revision",
|
|
1906
|
+
entityId: row.endpoint0EntityId,
|
|
1907
|
+
message: "A Script revision may name exactly one source Script"
|
|
1908
|
+
});
|
|
1909
|
+
}
|
|
1851
1910
|
return issues;
|
|
1852
1911
|
}
|
|
1853
1912
|
function validateMarkerUse(marker, index) {
|
|
@@ -2068,7 +2127,7 @@ function validateKnownEntityPayload(entity) {
|
|
|
2068
2127
|
const value = entity;
|
|
2069
2128
|
const problems = [];
|
|
2070
2129
|
if (value.lifecycle !== void 0 && !isRecord(value.lifecycle)) problems.push("lifecycle must be an object when present");
|
|
2071
|
-
if (entity.entityKind === "audio-script" || entity.entityKind === "phonetic-script") {
|
|
2130
|
+
if (entity.entityKind === "script" || entity.entityKind === "audio-script" || entity.entityKind === "phonetic-script") {
|
|
2072
2131
|
for (const key of [
|
|
2073
2132
|
"durationMs",
|
|
2074
2133
|
"extent",
|
|
@@ -2109,6 +2168,9 @@ function validateKnownEntityPayload(entity) {
|
|
|
2109
2168
|
case "audio-script":
|
|
2110
2169
|
validateScriptPayload(value, problems);
|
|
2111
2170
|
break;
|
|
2171
|
+
case "script":
|
|
2172
|
+
validateProfessionalScriptPayload(value, problems);
|
|
2173
|
+
break;
|
|
2112
2174
|
case "phonetic-script":
|
|
2113
2175
|
validatePhoneticScriptPayload(value, problems);
|
|
2114
2176
|
break;
|
|
@@ -2284,6 +2346,24 @@ function validateScriptPayload(value, problems) {
|
|
|
2284
2346
|
if (segment.language !== void 0 && typeof segment.language !== "string") problems.push(`segments[${index}].language must be a string when present`);
|
|
2285
2347
|
}
|
|
2286
2348
|
}
|
|
2349
|
+
function validateProfessionalScriptPayload(value, problems) {
|
|
2350
|
+
validateScriptPayload(value, problems);
|
|
2351
|
+
if (!Array.isArray(value.segments) || !value.segments.every(isCompleteScriptSegment)) return;
|
|
2352
|
+
const segments = value.segments;
|
|
2353
|
+
if (segments.length === 0) problems.push("segments must contain at least one screenplay segment");
|
|
2354
|
+
const ids = segments.map((segment) => segment.segmentId);
|
|
2355
|
+
if (ids.some((id) => id.trim() === "")) problems.push("segmentId must be a non-empty trimmed string");
|
|
2356
|
+
if (ids.some((id) => id.trim() !== id)) problems.push("segmentId must be a non-empty trimmed string");
|
|
2357
|
+
if (new Set(ids).size !== ids.length) problems.push("segmentId must be unique within the Script");
|
|
2358
|
+
const normalized = normalizeScriptSegments(segments);
|
|
2359
|
+
if (normalized.some((segment) => segment.text === "")) problems.push("segment text must be non-empty after normalization");
|
|
2360
|
+
if (segments.some((segment, index) => segment.text !== normalized[index].text)) problems.push("segment text must use canonical NFC, LF line endings, and trimmed line endings");
|
|
2361
|
+
if (segments.some((segment, index) => segment.language !== normalized[index].language)) problems.push("segment language must be canonical NFC and trimmed when present");
|
|
2362
|
+
if (typeof value.contentHash !== "string" || value.contentHash !== scriptContentHash(segments)) problems.push("contentHash must equal the SHA-256 of the canonical ordered segment texts");
|
|
2363
|
+
}
|
|
2364
|
+
function isCompleteScriptSegment(value) {
|
|
2365
|
+
return isRecord(value) && typeof value.segmentId === "string" && typeof value.text === "string" && (value.language === void 0 || typeof value.language === "string");
|
|
2366
|
+
}
|
|
2287
2367
|
function validateOptionalField(value, key, expectedType, problems) {
|
|
2288
2368
|
if (value[key] !== void 0 && typeof value[key] !== expectedType) problems.push(`${key} must be a ${expectedType} when present`);
|
|
2289
2369
|
}
|
|
@@ -2342,6 +2422,7 @@ function isOwnedLocalEntityValuePath(entityKind, path) {
|
|
|
2342
2422
|
if (entityKind === "voice" && /^voice\.(?:system|key|name)$/.test(path)) return true;
|
|
2343
2423
|
if (entityKind === "caption" && (path.startsWith("style.") || path === "selection.segmentId")) return true;
|
|
2344
2424
|
if ([
|
|
2425
|
+
"script",
|
|
2345
2426
|
"audio-script",
|
|
2346
2427
|
"caption",
|
|
2347
2428
|
"phonetic-script"
|
|
@@ -2351,6 +2432,7 @@ function isOwnedLocalEntityValuePath(entityKind, path) {
|
|
|
2351
2432
|
function isOwnedLocalIdPath(entityKind, path) {
|
|
2352
2433
|
if (path === "lifecycle.actorId") return true;
|
|
2353
2434
|
if ([
|
|
2435
|
+
"script",
|
|
2354
2436
|
"audio-script",
|
|
2355
2437
|
"caption",
|
|
2356
2438
|
"phonetic-script"
|
|
@@ -2517,7 +2599,7 @@ const derivedFromRelationSpec = Object.freeze({
|
|
|
2517
2599
|
kind: "derived-from",
|
|
2518
2600
|
ordered: true,
|
|
2519
2601
|
sequenced: false,
|
|
2520
|
-
validateEndpoints: (endpoints) => hasKinds(endpoints, new Set(MEDIA_VARIANT_KINDS), new Set(MEDIA_VARIANT_KINDS)) || hasKinds(endpoints, new Set(["voiceover-recording"]), new Set(["phonetic-script"])) || hasKinds(endpoints, new Set(["audio-script"]), new Set(MEDIA_AUDIBLE_KINDS)) || hasKinds(endpoints, new Set(["audio-script"]), new Set(["audio-script"])),
|
|
2602
|
+
validateEndpoints: (endpoints) => hasKinds(endpoints, new Set(MEDIA_VARIANT_KINDS), new Set(MEDIA_VARIANT_KINDS)) || hasKinds(endpoints, new Set(["voiceover-recording"]), new Set(["phonetic-script"])) || hasKinds(endpoints, new Set(["video"]), new Set(["script"])) || hasKinds(endpoints, new Set(["script"]), new Set(["script"])) || hasKinds(endpoints, new Set(["audio-script"]), new Set(MEDIA_AUDIBLE_KINDS)) || hasKinds(endpoints, new Set(["audio-script"]), new Set(["audio-script"])),
|
|
2521
2603
|
validateMetadata: isEmptyMetadata
|
|
2522
2604
|
});
|
|
2523
2605
|
const captionAlignmentRelationSpec = Object.freeze({
|
|
@@ -2652,6 +2734,7 @@ var BiRelationIndex = class {
|
|
|
2652
2734
|
}
|
|
2653
2735
|
/** Author `derived-from(product, source)` without exposing positional arguments. */
|
|
2654
2736
|
linkDerivedFrom(input) {
|
|
2737
|
+
if (input.product.current().entityKind === "script" && input.source.current().entityKind === "script") throw new Error("Script revision provenance is host-authored by reviseScript");
|
|
2655
2738
|
return this.linkValidated({
|
|
2656
2739
|
relationId: input.relationId,
|
|
2657
2740
|
spec: derivedFromRelationSpec,
|
|
@@ -2900,10 +2983,27 @@ var InvalidEntityRelationTransitionError = class extends Error {
|
|
|
2900
2983
|
function validateEntityRelationTransition(before, candidate) {
|
|
2901
2984
|
const issues = [];
|
|
2902
2985
|
const previous = new Map(before.relations.map((row) => [row.relationId, row]));
|
|
2986
|
+
const beforeEntities = new Map(before.entities.map((row) => [row.entityId, row]));
|
|
2987
|
+
const candidateEntities = new Map(candidate.entities.map((row) => [row.entityId, row]));
|
|
2988
|
+
const revisionEditIds = new Set(before.relations.filter((relation) => isScriptRevision(relation, beforeEntities)).map((relation) => readScriptRevisionTrace(relation.trace)?.editId).filter((editId) => editId !== void 0));
|
|
2989
|
+
const revisionParents = /* @__PURE__ */ new Map();
|
|
2990
|
+
for (const entity of before.entities) if (entity.entityKind === "script" && !candidateEntities.has(entity.entityId)) issues.push(`Script entity "${entity.entityId}" is immutable history and cannot be deleted or replaced`);
|
|
2903
2991
|
for (const relation of candidate.relations) {
|
|
2992
|
+
if (isScriptRevision(relation, candidateEntities)) {
|
|
2993
|
+
const count = (revisionParents.get(relation.endpoint0EntityId) ?? 0) + 1;
|
|
2994
|
+
revisionParents.set(relation.endpoint0EntityId, count);
|
|
2995
|
+
if (count > 1) issues.push(`Script "${relation.endpoint0EntityId}" may name only one revision source`);
|
|
2996
|
+
}
|
|
2904
2997
|
const original = previous.get(relation.relationId);
|
|
2905
2998
|
if (original == null) {
|
|
2906
2999
|
if (relation.relationKind === "caption-alignment") issues.push(`new caption-alignment relation "${relation.relationId}" is forbidden`);
|
|
3000
|
+
if (isScriptRevision(relation, candidateEntities)) {
|
|
3001
|
+
const trace = readScriptRevisionTrace(relation.trace);
|
|
3002
|
+
const result = candidateEntities.get(relation.endpoint0EntityId);
|
|
3003
|
+
const source = candidateEntities.get(relation.endpoint1EntityId);
|
|
3004
|
+
if (trace == null || beforeEntities.has(relation.endpoint0EntityId) || !beforeEntities.has(relation.endpoint1EntityId) || trace.resultContentHash !== result.payload.contentHash || trace.sourceContentHash !== source.payload.contentHash || trace.resultContentHash === trace.sourceContentHash || revisionEditIds.has(trace.editId)) issues.push(`Script revision relation "${relation.relationId}" must be one canonical new-result to existing-source edit`);
|
|
3005
|
+
else revisionEditIds.add(trace.editId);
|
|
3006
|
+
}
|
|
2907
3007
|
continue;
|
|
2908
3008
|
}
|
|
2909
3009
|
if (original.relationKind !== relation.relationKind || original.endpoint0EntityId !== relation.endpoint0EntityId || original.endpoint1EntityId !== relation.endpoint1EntityId) {
|
|
@@ -2912,9 +3012,13 @@ function validateEntityRelationTransition(before, candidate) {
|
|
|
2912
3012
|
}
|
|
2913
3013
|
if (!sameJson(original.metadata, relation.metadata)) issues.push(`relation "${relation.relationId}" changed semantic metadata without a new identity`);
|
|
2914
3014
|
if (relation.relationKind === "caption-alignment" && !sameJson(original.trace, relation.trace)) issues.push(`legacy caption-alignment relation "${relation.relationId}" may only be carried unchanged or deleted`);
|
|
3015
|
+
if (isScriptRevision(relation, candidateEntities) && !sameJson(original.trace, relation.trace)) issues.push(`Script revision relation "${relation.relationId}" trace is immutable`);
|
|
2915
3016
|
}
|
|
2916
3017
|
if (issues.length > 0) throw new InvalidEntityRelationTransitionError(issues);
|
|
2917
3018
|
}
|
|
3019
|
+
function isScriptRevision(relation, entities) {
|
|
3020
|
+
return relation.relationKind === "derived-from" && entities.get(relation.endpoint0EntityId)?.entityKind === "script" && entities.get(relation.endpoint1EntityId)?.entityKind === "script";
|
|
3021
|
+
}
|
|
2918
3022
|
function sameJson(left, right) {
|
|
2919
3023
|
if (left === right) return true;
|
|
2920
3024
|
if (Array.isArray(left) && Array.isArray(right)) return left.length === right.length && left.every((value, index) => sameJson(value, right[index]));
|
|
@@ -3204,6 +3308,7 @@ function projectEntityTimeline(rows) {
|
|
|
3204
3308
|
media_duration_ms: placement.duration,
|
|
3205
3309
|
audio_storage_key: storageKey(asset),
|
|
3206
3310
|
origin_speech_id: external.key,
|
|
3311
|
+
...synthesized ? {} : { origin_asset_system: "memota" },
|
|
3207
3312
|
audio_script: assembled?.text ?? (transcript === void 0 ? "" : assembleScriptText(transcript)),
|
|
3208
3313
|
volume: volume.data,
|
|
3209
3314
|
voice: object(voice) ? {
|
|
@@ -4005,11 +4110,13 @@ var LoroEntityDocument = class LoroEntityDocument {
|
|
|
4005
4110
|
}
|
|
4006
4111
|
/** The callback and every domain validation execute on a causally complete fork first. */
|
|
4007
4112
|
transact(edit) {
|
|
4113
|
+
const before = readEntityDocument(this.doc, true);
|
|
4008
4114
|
const probe = this.doc.fork();
|
|
4009
4115
|
const draft = new LoroEntityDraft(probe);
|
|
4010
4116
|
edit(draft);
|
|
4011
4117
|
draft.captureSelectionBaselines();
|
|
4012
4118
|
const state = readEntityDocument(probe);
|
|
4119
|
+
validateEntityRelationTransition(before.rows, state.rows);
|
|
4013
4120
|
assertState(state);
|
|
4014
4121
|
this.validate?.(state);
|
|
4015
4122
|
materialize(probe);
|
|
@@ -4023,8 +4130,15 @@ var LoroEntityDocument = class LoroEntityDocument {
|
|
|
4023
4130
|
from
|
|
4024
4131
|
});
|
|
4025
4132
|
}
|
|
4026
|
-
/**
|
|
4133
|
+
/** Validate remote operations on a fork before importing their native identities. */
|
|
4027
4134
|
import(update) {
|
|
4135
|
+
const before = readEntityDocument(this.doc, true);
|
|
4136
|
+
const probe = this.doc.fork();
|
|
4137
|
+
probe.import(update);
|
|
4138
|
+
const candidate = readEntityDocument(probe, true);
|
|
4139
|
+
validateEntityRelationTransition(before.rows, candidate.rows);
|
|
4140
|
+
assertState(candidate);
|
|
4141
|
+
this.validate?.(candidate);
|
|
4028
4142
|
this.doc.import(update);
|
|
4029
4143
|
const state = this.snapshot();
|
|
4030
4144
|
assertState(state);
|
|
@@ -4140,6 +4254,7 @@ var LoroEntityDraft = class {
|
|
|
4140
4254
|
});
|
|
4141
4255
|
}
|
|
4142
4256
|
delete(entityId) {
|
|
4257
|
+
if (workspace(this.doc, family(this.doc, entityId)).get("kind") === "script") throw new Error("Script entities are immutable history and cannot be deleted");
|
|
4143
4258
|
this.record({
|
|
4144
4259
|
type: "delete",
|
|
4145
4260
|
root: family(this.doc, entityId)
|
|
@@ -4241,6 +4356,7 @@ var LoroEntityDraft = class {
|
|
|
4241
4356
|
});
|
|
4242
4357
|
}
|
|
4243
4358
|
replaceOwned(entityId, payload) {
|
|
4359
|
+
this.assertGenericMutationAllowed(entityId);
|
|
4244
4360
|
this.record({
|
|
4245
4361
|
type: "write",
|
|
4246
4362
|
root: family(this.doc, entityId),
|
|
@@ -4251,6 +4367,7 @@ var LoroEntityDraft = class {
|
|
|
4251
4367
|
editText(entityId, path, start, deleteCount, text) {
|
|
4252
4368
|
if (typeof path[0] !== "string") throw new Error("Text path must start with a field");
|
|
4253
4369
|
const owner = resolveEntityFieldOwner(this.snapshot().rows, createEntityId(currentId(this.doc, entityId)), path[0]);
|
|
4370
|
+
this.assertGenericMutationAllowed(owner);
|
|
4254
4371
|
this.record({
|
|
4255
4372
|
type: "text",
|
|
4256
4373
|
root: family(this.doc, owner),
|
|
@@ -4276,6 +4393,7 @@ var LoroEntityDraft = class {
|
|
|
4276
4393
|
const owner = resolveEntityFieldOwner(state.rows, id, change.path[0]);
|
|
4277
4394
|
const row = state.rows.entities.find((row) => row.entityId === owner);
|
|
4278
4395
|
if (equalJson(row.payload, applyFieldChanges(row.payload, [change]))) continue;
|
|
4396
|
+
this.assertGenericMutationAllowed(owner);
|
|
4279
4397
|
this.record({
|
|
4280
4398
|
type: "field",
|
|
4281
4399
|
root: family(this.doc, owner),
|
|
@@ -4285,6 +4403,9 @@ var LoroEntityDraft = class {
|
|
|
4285
4403
|
});
|
|
4286
4404
|
}
|
|
4287
4405
|
}
|
|
4406
|
+
assertGenericMutationAllowed(entityId) {
|
|
4407
|
+
if (workspace(this.doc, family(this.doc, entityId)).get("kind") === "script") throw new Error("Script content is immutable; create a new Script revision");
|
|
4408
|
+
}
|
|
4288
4409
|
changeRelation(relationId, changes) {
|
|
4289
4410
|
assertFieldChanges(changes);
|
|
4290
4411
|
const key = this.relationRoot(relationId);
|
|
@@ -736,7 +736,8 @@ type VideoClipPart = Omit<VideoClipPart$1, 'duration_ms'>;
|
|
|
736
736
|
* from it by the projection.
|
|
737
737
|
*/
|
|
738
738
|
type SpeechPart = Omit<SpeechPart$1, 'duration_ms'> & {
|
|
739
|
-
media_duration_ms?: number | undefined;
|
|
739
|
+
media_duration_ms?: number | undefined; /** Compatibility discriminator for already-recorded Audio projected as speech. */
|
|
740
|
+
origin_asset_system?: 'memota' | undefined;
|
|
740
741
|
};
|
|
741
742
|
/**
|
|
742
743
|
* Authoritative caption part. The IDL `CaptionPart` carries `duration_ms` (the
|
|
@@ -1286,7 +1287,7 @@ declare function buildInitialVideoDocument(): VideoDocument;
|
|
|
1286
1287
|
//#endregion
|
|
1287
1288
|
//#region ../medeo-dsl/src/sandbox.d.ts
|
|
1288
1289
|
/** Kinds a script can author. */
|
|
1289
|
-
type EntityKind = 'timeline' | 'track' | 'clip' | 'sequence-marker' | 'video' | 'audio' | 'voiceover-recording' | 'image' | 'voice' | 'audio-script' | 'phonetic-script' | 'caption';
|
|
1290
|
+
type EntityKind = 'timeline' | 'track' | 'clip' | 'sequence-marker' | 'video' | 'audio' | 'voiceover-recording' | 'image' | 'voice' | 'script' | 'audio-script' | 'phonetic-script' | 'caption';
|
|
1290
1291
|
type RelationKind = 'contain' | 'marker' | 'clip-anchor' | 'voice-timbre' | 'caption-alignment' | 'derived-from';
|
|
1291
1292
|
//#endregion
|
|
1292
1293
|
//#region ../medeo-dsl/src/ids.d.ts
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as index_d_exports } from "./index-CMa6ZCtX.js";
|
|
2
|
-
import { $ as derivePositionFromAbs, A as assertValidVideoDocument, At as VideoDraftContent, B as EntityRow, Bt as Track$1, C as isImplementedSemanticOpKind, Ct as TrackItem, D as PartIdFactory, Dt as VideoDocumentValidationIssue, E as ValidationError, Et as VideoDocument, F as ResolvedEntityTrack, Ft as CaptionPart$1, G as VoiceDescriptor, H as CaptionSegmentSelection, I as resolveEntityTimelineLayout, It as CaptionStyle, J as EntityId, K as JsonObject, L as projectEntityTimeline, Lt as PartAggregation, M as EntityTimelineTrackRole, Mt as effectiveVideoClipDurationMs, N as ResolvedEntityClipPlacement, Nt as speedOf, O as generatePartId, Ot as VideoDocumentValidationIssueCode, P as ResolvedEntityTimelineLayout, Pt as Attachment, Q as buildSpeechHostMap, R as EntityTimelineProjectionError, Rt as SpeedShift, S as SemanticOpKind, St as Track, T as SnapshotReadable, Tt as VideoClipPart, U as CaptionStyleFields, V as RelationRow, Vt as TrackItem$1, W as ScriptTextSegment, X as DerivedItemPosition, Y as buildInitialVideoDocument, Z as SpeechHostMap, _ as SemanticOpName, _t as DEFAULT_UNIT_TIME_MS, a as PlainMemoryAdapter, at as ensureLaneTrack, b as ImplementedSemanticOpKind, bt as SpeechPart, c as MirrorVideoDocumentAdapter, ct as solveVideoDocument, d as createMirrorVideoDocumentAdapter, dt as VideoDocumentDraft, et as fromVideoDocument, f as CommitOptions, ft as VideoDocumentMirrorSchema, g as SemanticOpInput, gt as CaptionPart, h as SemanticEditor, ht as CaptionDisplayCue, i as JournalEntry, it as SolvedVideoDocument, j as validateVideoDocument, jt as VideoDraftPartUnion, k as VideoDocumentValidationError, kt as VideoDraft, l as MirrorVideoDocumentOptions, lt as TrackDraft, m as SemanticDocumentAdapter, mt as BgmPart, n as videoDocumentSchema, nt as LANE_KINDS_IN_STACK_ORDER, o as PlainMemoryAdapterOptions, ot as findLaneTrack, p as OpActor, pt as videoDocumentMirrorSchema, q as JsonValue, r as readVideoDocumentFromDraft, rt as LaneKind, s as createPlainMemoryAdapter, st as laneTrackId, t as partUnionSchema, tt as toVideoDocument, u as createMirrorVideoDocument, ut as TrackItemDraft, v as TransactAudit, vt as PartKind, w as SchemaValidator, wt as TrackItemTimePosition, x as PlannedSemanticOpKind, xt as Timeline, y as IMPLEMENTED_SEMANTIC_OP_KINDS, yt as PartUnion, z as EntityRelationRows, zt as Timeline$1 } from "./index-
|
|
2
|
+
import { $ as derivePositionFromAbs, A as assertValidVideoDocument, At as VideoDraftContent, B as EntityRow, Bt as Track$1, C as isImplementedSemanticOpKind, Ct as TrackItem, D as PartIdFactory, Dt as VideoDocumentValidationIssue, E as ValidationError, Et as VideoDocument, F as ResolvedEntityTrack, Ft as CaptionPart$1, G as VoiceDescriptor, H as CaptionSegmentSelection, I as resolveEntityTimelineLayout, It as CaptionStyle, J as EntityId, K as JsonObject, L as projectEntityTimeline, Lt as PartAggregation, M as EntityTimelineTrackRole, Mt as effectiveVideoClipDurationMs, N as ResolvedEntityClipPlacement, Nt as speedOf, O as generatePartId, Ot as VideoDocumentValidationIssueCode, P as ResolvedEntityTimelineLayout, Pt as Attachment, Q as buildSpeechHostMap, R as EntityTimelineProjectionError, Rt as SpeedShift, S as SemanticOpKind, St as Track, T as SnapshotReadable, Tt as VideoClipPart, U as CaptionStyleFields, V as RelationRow, Vt as TrackItem$1, W as ScriptTextSegment, X as DerivedItemPosition, Y as buildInitialVideoDocument, Z as SpeechHostMap, _ as SemanticOpName, _t as DEFAULT_UNIT_TIME_MS, a as PlainMemoryAdapter, at as ensureLaneTrack, b as ImplementedSemanticOpKind, bt as SpeechPart, c as MirrorVideoDocumentAdapter, ct as solveVideoDocument, d as createMirrorVideoDocumentAdapter, dt as VideoDocumentDraft, et as fromVideoDocument, f as CommitOptions, ft as VideoDocumentMirrorSchema, g as SemanticOpInput, gt as CaptionPart, h as SemanticEditor, ht as CaptionDisplayCue, i as JournalEntry, it as SolvedVideoDocument, j as validateVideoDocument, jt as VideoDraftPartUnion, k as VideoDocumentValidationError, kt as VideoDraft, l as MirrorVideoDocumentOptions, lt as TrackDraft, m as SemanticDocumentAdapter, mt as BgmPart, n as videoDocumentSchema, nt as LANE_KINDS_IN_STACK_ORDER, o as PlainMemoryAdapterOptions, ot as findLaneTrack, p as OpActor, pt as videoDocumentMirrorSchema, q as JsonValue, r as readVideoDocumentFromDraft, rt as LaneKind, s as createPlainMemoryAdapter, st as laneTrackId, t as partUnionSchema, tt as toVideoDocument, u as createMirrorVideoDocument, ut as TrackItemDraft, v as TransactAudit, vt as PartKind, w as SchemaValidator, wt as TrackItemTimePosition, x as PlannedSemanticOpKind, xt as Timeline, y as IMPLEMENTED_SEMANTIC_OP_KINDS, yt as PartUnion, z as EntityRelationRows, zt as Timeline$1 } from "./index-DaabF2vA.js";
|
|
3
3
|
import { LoroDoc, PeerID } from "loro-crdt";
|
|
4
4
|
import { DocState } from "@mengine/sync";
|
|
5
5
|
import { BaseDocStorage, Connection, DocDiff, DocPushReceipt, DocSnapshotRecord, DocStorage, DocStorageOptions, DocUpdate, DocUpdateRecord } from "@mengine/storage";
|
|
@@ -880,7 +880,7 @@ declare class LoroEntityDocument {
|
|
|
880
880
|
getVersion(id: string): EntityRow | undefined;
|
|
881
881
|
/** The callback and every domain validation execute on a causally complete fork first. */
|
|
882
882
|
transact(edit: (draft: LoroEntityDraft) => void): Uint8Array;
|
|
883
|
-
/**
|
|
883
|
+
/** Validate remote operations on a fork before importing their native identities. */
|
|
884
884
|
import(update: Uint8Array): void;
|
|
885
885
|
/**
|
|
886
886
|
* Bind a saved snapshot without rewriting text operations or resolving
|
|
@@ -924,6 +924,7 @@ declare class LoroEntityDraft {
|
|
|
924
924
|
editText(entityId: string, path: readonly (string | number)[], start: number, deleteCount: number, text: string): void;
|
|
925
925
|
/** Generic assembled-field edit compiled at the author's causal position. */
|
|
926
926
|
change(entityId: string, changes: readonly FieldChange[]): void;
|
|
927
|
+
private assertGenericMutationAllowed;
|
|
927
928
|
changeRelation(relationId: string, changes: readonly FieldChange[]): void;
|
|
928
929
|
captureSelectionBaselines(): void;
|
|
929
930
|
private record;
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as fromVideoDocument, A as resolveEntityTimelineLayout, At as base64ToBytes, B as assembleScriptText, C as canonicalJson, Ct as safeDurationMs, D as resolveFieldPath, Dt as partUnionToDraft, E as assertFieldChanges, Et as speedOf, F as relationsTo, G as isJsonObject, H as selectAudioScriptSegment, I as ScriptCompositionError, J as hasSequence, K as createEntityId, L as assembleCaptionContent, M as validateEntityRelationTransition, N as decodeEntityRelationRows, O as projectEntityTimeline, Ot as recordEntries, P as relationsFrom, Q as derivePositionFromAbs, R as assembleEntityContent, S as scriptSourceAssetOf, St as partDurationMs, T as applyFieldChanges, Tt as effectiveVideoClipDurationMs, U as updateEntityFields, V as findComposedAudioScript, W as variantBaseEntityIds, X as buildInitialVideoDocument, Y as isMediaAssetVariantKind, Z as buildSpeechHostMap, _ as audioScriptAssetHash, _t as resolveAllSpeechOverlaps, a as createMirrorVideoDocument, at as videoDocumentSchema, b as phoneticScriptAssetHash, bt as TIMELINE_SKELETON_DURATION_MS, c as DocumentMutationGuard, ct as findLaneTrack, d as LoroEntityDraft, dt as solveVideoDocument, et as toVideoDocument, f as readEntityDocument, ft as cascadeAfterVideoClipChanges, g as audioScriptAssetFields, gt as recalculateTimelineDuration, h as audioScriptAssetContent, ht as reassignSpeechesToVideoClipsByTime, i as MirrorVideoDocumentAdapter, it as partUnionSchema, j as EntityTimelineProjectionError, jt as bytesToBase64, k as EntityProjectionGraph, kt as videoDocumentMirrorSchema, l as LORO_ENTITY_SCHEMA, lt as hasResolvedPlacement, m as entityOrderGroups, mt as fillMainTrackTimeGaps, n as createPlainMemoryAdapter, nt as assertValidVideoDocument, o as createMirrorVideoDocumentAdapter, ot as LANE_KINDS_IN_STACK_ORDER, p as readEntityRelationRecords, pt as arrangeMainTrackSeamlessly, q as createRelationId, r as generatePartId, rt as validateVideoDocument, s as readVideoDocumentFromDraft, st as ensureLaneTrack, t as PlainMemoryAdapter, tt as VideoDocumentValidationError, u as LoroEntityDocument, ut as laneTrackId, v as audioScriptAssetOf, vt as resolveSpeechOverlapByShiftingVideos, w as equalJson, wt as DEFAULT_UNIT_TIME_MS, x as phoneticScriptAssetOf, xt as isEmptyVideoClip, y as phoneticScriptAssetContent, yt as syncAggregatedClipsTimePosition, z as assemblePhoneticScriptContent } from "./document-
|
|
1
|
+
import { $ as fromVideoDocument, A as resolveEntityTimelineLayout, At as base64ToBytes, B as assembleScriptText, C as canonicalJson, Ct as safeDurationMs, D as resolveFieldPath, Dt as partUnionToDraft, E as assertFieldChanges, Et as speedOf, F as relationsTo, G as isJsonObject, H as selectAudioScriptSegment, I as ScriptCompositionError, J as hasSequence, K as createEntityId, L as assembleCaptionContent, M as validateEntityRelationTransition, N as decodeEntityRelationRows, O as projectEntityTimeline, Ot as recordEntries, P as relationsFrom, Q as derivePositionFromAbs, R as assembleEntityContent, S as scriptSourceAssetOf, St as partDurationMs, T as applyFieldChanges, Tt as effectiveVideoClipDurationMs, U as updateEntityFields, V as findComposedAudioScript, W as variantBaseEntityIds, X as buildInitialVideoDocument, Y as isMediaAssetVariantKind, Z as buildSpeechHostMap, _ as audioScriptAssetHash, _t as resolveAllSpeechOverlaps, a as createMirrorVideoDocument, at as videoDocumentSchema, b as phoneticScriptAssetHash, bt as TIMELINE_SKELETON_DURATION_MS, c as DocumentMutationGuard, ct as findLaneTrack, d as LoroEntityDraft, dt as solveVideoDocument, et as toVideoDocument, f as readEntityDocument, ft as cascadeAfterVideoClipChanges, g as audioScriptAssetFields, gt as recalculateTimelineDuration, h as audioScriptAssetContent, ht as reassignSpeechesToVideoClipsByTime, i as MirrorVideoDocumentAdapter, it as partUnionSchema, j as EntityTimelineProjectionError, jt as bytesToBase64, k as EntityProjectionGraph, kt as videoDocumentMirrorSchema, l as LORO_ENTITY_SCHEMA, lt as hasResolvedPlacement, m as entityOrderGroups, mt as fillMainTrackTimeGaps, n as createPlainMemoryAdapter, nt as assertValidVideoDocument, o as createMirrorVideoDocumentAdapter, ot as LANE_KINDS_IN_STACK_ORDER, p as readEntityRelationRecords, pt as arrangeMainTrackSeamlessly, q as createRelationId, r as generatePartId, rt as validateVideoDocument, s as readVideoDocumentFromDraft, st as ensureLaneTrack, t as PlainMemoryAdapter, tt as VideoDocumentValidationError, u as LoroEntityDocument, ut as laneTrackId, v as audioScriptAssetOf, vt as resolveSpeechOverlapByShiftingVideos, w as equalJson, wt as DEFAULT_UNIT_TIME_MS, x as phoneticScriptAssetOf, xt as isEmptyVideoClip, y as phoneticScriptAssetContent, yt as syncAggregatedClipsTimePosition, z as assemblePhoneticScriptContent } from "./document-B3RLmTzA.js";
|
|
2
2
|
import { addSpeechesInputSchema, addVideoClipsInputSchema, adjustBgmVolumeInputSchema, adjustSpeechVolumeInputSchema, adjustVideoClipDurationInputSchema, adjustVideoClipVolumeInputSchema, changeSpeechScriptInputSchema, changeSpeechVoiceInputSchema, deleteBgmInputSchema, deleteSpeechesInputSchema, deleteVideoClipsInputSchema, moveSpeechesInputSchema, moveVideoClipsByAnchorInputSchema, moveVideoClipsInputSchema, replaceVideoClipContentInputSchema, replaceVideoClipSequenceInputSchema, setBgmInputSchema, setCaptionStyleInputSchema, setCaptionVisibilityInputSchema, setVideoClipSpeedShiftInputSchema, t as schemas_exports } from "./schemas.js";
|
|
3
|
-
import { LoroDoc, LoroMap, UndoManager, VersionVector } from "loro-crdt";
|
|
4
3
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
5
4
|
import { bytesToHex } from "@noble/hashes/utils.js";
|
|
5
|
+
import { LoroDoc, LoroMap, UndoManager, VersionVector } from "loro-crdt";
|
|
6
6
|
import { ClientServerSynchronizer, DocManager } from "@mengine/sync";
|
|
7
7
|
import { DisposableSet, EventBus, Task } from "@mengine/utils";
|
|
8
8
|
import { BaseDocStorage, DummyConnection } from "@mengine/storage";
|
package/dist/testing.d.ts
CHANGED
package/dist/testing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as base64ToBytes, jt as bytesToBase64, o as createMirrorVideoDocumentAdapter } from "./document-
|
|
1
|
+
import { At as base64ToBytes, jt as bytesToBase64, o as createMirrorVideoDocumentAdapter } from "./document-B3RLmTzA.js";
|
|
2
2
|
import { t as classifyUpdate } from "./loro-relay-doc-cJSY-uau.js";
|
|
3
3
|
import { LoroDoc, VersionVector, encodeFrontiers } from "loro-crdt";
|
|
4
4
|
//#region src/testing/in-memory-mengine-server.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mengine/medeo-client",
|
|
3
|
-
"version": "2.0.1-alpha.
|
|
3
|
+
"version": "2.0.1-alpha.29",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"immer": "^10.2.0",
|
|
29
29
|
"loro-mirror": "^2.3.3",
|
|
30
30
|
"zod": "^4.4.3",
|
|
31
|
-
"@mengine/
|
|
32
|
-
"@mengine/utils": "2.0.1-alpha.
|
|
33
|
-
"@mengine/
|
|
31
|
+
"@mengine/storage": "2.0.1-alpha.29",
|
|
32
|
+
"@mengine/utils": "2.0.1-alpha.29",
|
|
33
|
+
"@mengine/sync": "2.0.1-alpha.29"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^25.9.1",
|