@mengine/medeo-tool 1.2.1-alpha.9 → 1.3.1-alpha.11
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 +39 -14
- package/dist/{entity-contract-DycLxdQ5.d.mts → entity-contract-DHasvrhq.d.mts} +89 -33
- package/dist/index.d.mts +51 -178
- package/dist/index.mjs +300 -497
- package/dist/index.mjs.map +1 -1
- package/dist/sandbox-api.d.mts +149 -44
- package/dist/{script-session-CHyIUBkO.mjs → script-session-DLBhoA1R.mjs} +682 -132
- package/dist/script-session-DLBhoA1R.mjs.map +1 -0
- package/dist/worker-entry.d.mts +1 -1
- package/dist/worker-entry.mjs +39 -11
- package/dist/worker-entry.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/script-session-CHyIUBkO.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ const commit = await medeo.handle({
|
|
|
38
38
|
plan_id: run.plan_id,
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
//
|
|
41
|
+
// Media facts are recalled by the host and passed into the sandbox.
|
|
42
42
|
// This example is text-to-image: there is no invented input-media entity.
|
|
43
43
|
const entityRun = await medeo.handle({
|
|
44
44
|
op: 'run-edit-script',
|
|
@@ -48,12 +48,10 @@ const entityRun = await medeo.handle({
|
|
|
48
48
|
if (typeof inputs.output_asset_id !== 'string' || typeof inputs.track_entity_id !== 'string') {
|
|
49
49
|
throw new Error('missing recalled generation facts');
|
|
50
50
|
}
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
payload: { extent: { kind: 'unbounded', start: 0 }, sampling: 'constant', coordinateSpace: 'ms' },
|
|
51
|
+
const { contentEntityId: output } = entities.ensureMedia({
|
|
52
|
+
assetId: inputs.output_asset_id,
|
|
53
|
+
kind: 'image',
|
|
55
54
|
});
|
|
56
|
-
relations.link({ relation_kind: 'physical-asset', endpoint_0_entity_id: output, endpoint_1_entity_id: asset });
|
|
57
55
|
edit.insertClip({
|
|
58
56
|
trackEntityId: inputs.track_entity_id,
|
|
59
57
|
contentEntityId: output,
|
|
@@ -70,8 +68,35 @@ await medeo.close();
|
|
|
70
68
|
The sandbox has no network, storage, clock, or generation access. Materialize
|
|
71
69
|
or recall speech/media side effects in the host first and pass stable facts
|
|
72
70
|
through `inputs`. There is no automatic Asset→Entity projection: the model
|
|
73
|
-
selects
|
|
74
|
-
|
|
71
|
+
selects when to bring a recalled asset into the editor through `entities.ensureMedia`.
|
|
72
|
+
The resolver gets or creates one typed Asset by external `(system, key)` within
|
|
73
|
+
the document. Image/Video/Audio/Voice are logical Asset variants: the typed row
|
|
74
|
+
directly owns `external`, `storageKey` and its media fields, and its Asset ID is
|
|
75
|
+
also its content Entity ID. Imports create no separate physical-only Asset
|
|
76
|
+
row and no `physical-asset` relation. Raw typed resource creation also reuses
|
|
77
|
+
an existing identity; prefer `ensureMedia` with the recalled media kind.
|
|
78
|
+
`findByAssetId` includes Voice (`memota-speech`) variants. There is no separate
|
|
79
|
+
`importAsset` API.
|
|
80
|
+
Generation facts currently carry bare asset IDs. If a returned fact matches
|
|
81
|
+
both media and speech namespaces, synchronization fails explicitly without
|
|
82
|
+
writing ambiguous lineage edges.
|
|
83
|
+
Conflicting facts or duplicate candidates fail explicitly; no automatic
|
|
84
|
+
merge or deletion occurs. This is the MEngine editor profile, not a global DSL
|
|
85
|
+
cardinality rule. Separate Asset+media graphs are invalid: every media variant
|
|
86
|
+
must directly own its external identity, with no read fallback or migration.
|
|
87
|
+
Inline caption Assets without external identity are not deduplicated.
|
|
88
|
+
|
|
89
|
+
Before model context/snapshot/editing, the host ensures one Timeline and the four
|
|
90
|
+
fixed Tracks (`video_clip`, `speech`, `caption`, `bgm`). Existing IDs, settings and
|
|
91
|
+
relations are retained; repeated calls add no rows or revisions. First initialization
|
|
92
|
+
uses revision CAS and may write. An empty legacy draft is initialized through the
|
|
93
|
+
version-guarded migration path to preserve configured track identities/visibility;
|
|
94
|
+
non-empty legacy content still requires explicit `migrate-legacy`. Missing Tracks
|
|
95
|
+
are filled in a subsequent CAS when necessary. A lost initialization response is
|
|
96
|
+
reconciled by a fresh snapshot, never by assuming success.
|
|
97
|
+
|
|
98
|
+
Each placement still creates an independent Clip and SequenceMarker. Reusing a
|
|
99
|
+
media variant does not share per-placement trim, speed, volume or placement state.
|
|
75
100
|
|
|
76
101
|
The production tool exposes native Clip/Marker editing plus visual placement,
|
|
77
102
|
voiceover, caption, and BGM helpers through its generated sandbox interface.
|
|
@@ -83,9 +108,9 @@ Generation lineage is program-synced, not model-authored. After a confirmed
|
|
|
83
108
|
entity commit the tool resolves the plan's diff against host-supplied generation
|
|
84
109
|
facts and commits missing `generated` Relations between fact-matched media
|
|
85
110
|
Entities already present in the document (endpoint 0 output, endpoint 1 input;
|
|
86
|
-
lookup can use either endpoint). The diff covers
|
|
87
|
-
|
|
88
|
-
|
|
111
|
+
lookup can use either endpoint). The diff covers newly exposed media Asset
|
|
112
|
+
identities; placement-only edits and
|
|
113
|
+
pairs already fact-resolvable before the plan stay untouched. Models
|
|
89
114
|
do not pass generation history through inputs — the host queries it with
|
|
90
115
|
`loadGenerationFacts(docId, assetIds)`, returning every known generation record
|
|
91
116
|
involving the given asset ids in either role. Each record must carry an explicit
|
|
@@ -95,9 +120,9 @@ that fails the whole query instead of being silently read as text-only.
|
|
|
95
120
|
One-sided facts are skipped without creating entities or blocking the commit —
|
|
96
121
|
lineage sync never backfills a missing source or output Entity; entity creation
|
|
97
122
|
stays a model decision inside the edit plan. Repeated commits are idempotent,
|
|
98
|
-
and deletions
|
|
99
|
-
|
|
100
|
-
|
|
123
|
+
and deletions and revision conflicts are respected: a CAS-conflict retry reads
|
|
124
|
+
the fresh graph and recomputes missing edges without recreating deleted endpoints.
|
|
125
|
+
Asset identities are immutable, so each synchronization queries its facts once.
|
|
101
126
|
An empty result array means no known lineage; a rejection means the lineage
|
|
102
127
|
query failed and is reported as `generation_sync: {status:'failed'}` plus a
|
|
103
128
|
`generation_sync_failed` warning — never as synced state.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { MediaAssetFact } from "@mengine/medeo-client";
|
|
2
|
+
|
|
1
3
|
//#region src/entity/entity-contract.d.ts
|
|
2
4
|
type JsonPrimitive = string | number | boolean | null;
|
|
3
5
|
type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
@@ -5,7 +7,9 @@ interface JsonObject {
|
|
|
5
7
|
[key: string]: JsonValue;
|
|
6
8
|
}
|
|
7
9
|
type KnownEntityKind = 'axvideo' | 'timeline' | 'track' | 'clip' | 'asset' | 'video' | 'audio' | 'voice' | 'image' | 'sequence-marker' | 'viewport' | 'audio-script' | 'phonetic-script' | 'caption';
|
|
8
|
-
|
|
10
|
+
/** Asset identity, either an old physical-only row or a directly composed media variant. */
|
|
11
|
+
type ResourceEntityKind = 'image' | 'video' | 'audio' | 'voice';
|
|
12
|
+
type KnownRelationKind = 'timeline-track' | 'track-clip' | 'clip-marker' | 'marker-content' | 'axvideo-marker' | 'marker-timeline' | 'physical-asset' | 'generated' | 'caption-alignment' | 'clip-anchor' | 'phonetic-script-render' | 'audio-script-source' | 'audio-script-marker';
|
|
9
13
|
type AuthorableRelationKind = Exclude<KnownRelationKind, 'generated'>;
|
|
10
14
|
interface BoundedNativeSequencePayload extends JsonObject {
|
|
11
15
|
/** Factual coordinates from recalled media metadata; never invent an end/duration. */
|
|
@@ -39,6 +43,30 @@ type ScriptTextSegment = JsonObject & {
|
|
|
39
43
|
text: string;
|
|
40
44
|
language?: string;
|
|
41
45
|
};
|
|
46
|
+
type MediaAssetPayload = JsonObject & {
|
|
47
|
+
external: {
|
|
48
|
+
system: 'memota' | 'memota-speech';
|
|
49
|
+
key: string;
|
|
50
|
+
};
|
|
51
|
+
storageKey?: string;
|
|
52
|
+
};
|
|
53
|
+
type CaptionTextSelection = JsonObject & {
|
|
54
|
+
segmentId: string; /** Half-open Unicode code-point range within the selected source segment. */
|
|
55
|
+
textRange?: {
|
|
56
|
+
start: number;
|
|
57
|
+
end: number;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
/** Read result only: base text is assembled from the real AudioScript row. */
|
|
61
|
+
interface ComposedScriptContent {
|
|
62
|
+
audio_script_entity_id: string;
|
|
63
|
+
text: string;
|
|
64
|
+
segments: ScriptTextSegment[];
|
|
65
|
+
}
|
|
66
|
+
interface ComposedPhoneticContent extends ComposedScriptContent {
|
|
67
|
+
phonemeScript?: string;
|
|
68
|
+
prosody?: JsonObject;
|
|
69
|
+
}
|
|
42
70
|
interface EntityPayloadByKind {
|
|
43
71
|
axvideo: BoundedDerivedSequencePayload;
|
|
44
72
|
timeline: JsonObject;
|
|
@@ -47,12 +75,12 @@ interface EntityPayloadByKind {
|
|
|
47
75
|
role?: string;
|
|
48
76
|
};
|
|
49
77
|
clip: JsonObject;
|
|
50
|
-
/**
|
|
78
|
+
/** Physical resource fields; never a copy of Caption content. */
|
|
51
79
|
asset: JsonObject;
|
|
52
|
-
video: BoundedNativeSequencePayload;
|
|
53
|
-
audio: BoundedNativeSequencePayload;
|
|
54
|
-
voice: BoundedNativeSequencePayload;
|
|
55
|
-
image: UnboundedConstantSequencePayload;
|
|
80
|
+
video: BoundedNativeSequencePayload & MediaAssetPayload;
|
|
81
|
+
audio: BoundedNativeSequencePayload & MediaAssetPayload;
|
|
82
|
+
voice: BoundedNativeSequencePayload & MediaAssetPayload;
|
|
83
|
+
image: UnboundedConstantSequencePayload & MediaAssetPayload;
|
|
56
84
|
'sequence-marker': JsonObject & {
|
|
57
85
|
sourceRange: {
|
|
58
86
|
start: number;
|
|
@@ -70,21 +98,36 @@ interface EntityPayloadByKind {
|
|
|
70
98
|
};
|
|
71
99
|
timeRemapping?: JsonValue;
|
|
72
100
|
anchorOffset?: number;
|
|
73
|
-
durationPolicy?: 'timeline';
|
|
101
|
+
durationPolicy?: 'timeline'; /** Directly assigned AudioScript annotation times; annotation Markers only. */
|
|
102
|
+
segmentRanges?: {
|
|
103
|
+
segmentId: string;
|
|
104
|
+
startMs: number;
|
|
105
|
+
endMs: number;
|
|
106
|
+
}[];
|
|
74
107
|
};
|
|
75
108
|
viewport: JsonObject;
|
|
76
109
|
'audio-script': JsonObject & {
|
|
77
110
|
segments: ScriptTextSegment[];
|
|
78
111
|
};
|
|
79
112
|
'phonetic-script': JsonObject & {
|
|
80
|
-
|
|
113
|
+
baseEntityIds: string[];
|
|
114
|
+
phonemeScript?: string;
|
|
115
|
+
prosody?: JsonObject;
|
|
116
|
+
};
|
|
117
|
+
caption: BoundedNativeSequencePayload & {
|
|
118
|
+
baseEntityIds: string[];
|
|
119
|
+
selections: CaptionTextSelection[];
|
|
120
|
+
style?: JsonObject;
|
|
81
121
|
};
|
|
82
|
-
caption: BoundedNativeSequencePayload;
|
|
83
122
|
}
|
|
123
|
+
/** Stored own fields; a variant may obtain required content fields from its declared bases. */
|
|
124
|
+
type StoredEntityPayload<K extends KnownEntityKind> = EntityPayloadByKind[K] | (JsonObject & Partial<EntityPayloadByKind[K]> & {
|
|
125
|
+
baseEntityIds: string[];
|
|
126
|
+
});
|
|
84
127
|
interface SandboxEntity<K extends KnownEntityKind = KnownEntityKind> {
|
|
85
128
|
entity_id: string;
|
|
86
129
|
entity_kind: K;
|
|
87
|
-
payload:
|
|
130
|
+
payload: StoredEntityPayload<K>;
|
|
88
131
|
}
|
|
89
132
|
interface SandboxRelation {
|
|
90
133
|
relation_id: string;
|
|
@@ -95,15 +138,20 @@ interface SandboxRelation {
|
|
|
95
138
|
trace: JsonObject;
|
|
96
139
|
}
|
|
97
140
|
interface EntityStoreSnapshot {
|
|
141
|
+
/** Causal compiler baseline; required for publishing edits. */
|
|
142
|
+
loroSnapshot?: string;
|
|
98
143
|
revision: number;
|
|
144
|
+
/** Current AudioScript version attached to the project; initialized projects always attach a script, possibly empty. */
|
|
145
|
+
audioScriptEntityId: string | null;
|
|
99
146
|
entities: SandboxEntity[];
|
|
100
147
|
relations: SandboxRelation[];
|
|
101
148
|
}
|
|
102
149
|
type CreateEntityInput = { [K in KnownEntityKind]: {
|
|
103
150
|
entity_id?: string;
|
|
104
151
|
entity_kind: K;
|
|
105
|
-
payload:
|
|
152
|
+
payload: StoredEntityPayload<K>;
|
|
106
153
|
} }[KnownEntityKind];
|
|
154
|
+
/** Patch supplied fields on the assembled entity; omitted fields remain unchanged. */
|
|
107
155
|
interface UpdateEntityInput {
|
|
108
156
|
entity_id: string;
|
|
109
157
|
payload: JsonObject;
|
|
@@ -111,12 +159,7 @@ interface UpdateEntityInput {
|
|
|
111
159
|
interface DeleteEntityInput {
|
|
112
160
|
entity_id: string;
|
|
113
161
|
}
|
|
114
|
-
|
|
115
|
-
asset_id: string;
|
|
116
|
-
entity_id?: string;
|
|
117
|
-
payload?: JsonObject;
|
|
118
|
-
}
|
|
119
|
-
type EmptyRelationKind = 'timeline-track' | 'track-clip' | 'clip-marker' | 'marker-content' | 'axvideo-marker' | 'marker-timeline';
|
|
162
|
+
type EmptyRelationKind = 'timeline-track' | 'track-clip' | 'clip-marker' | 'marker-content' | 'axvideo-marker' | 'marker-timeline' | 'audio-script-marker';
|
|
120
163
|
interface LinkRelationBase {
|
|
121
164
|
relation_id?: string;
|
|
122
165
|
endpoint_0_entity_id: string;
|
|
@@ -131,11 +174,6 @@ type LinkRelationInput = (LinkRelationBase & {
|
|
|
131
174
|
}) | (LinkRelationBase & {
|
|
132
175
|
relation_kind: 'physical-asset';
|
|
133
176
|
metadata?: JsonObject;
|
|
134
|
-
}) | (LinkRelationBase & {
|
|
135
|
-
relation_kind: 'phonetic-script-provenance' | 'caption-provenance';
|
|
136
|
-
metadata: JsonObject & {
|
|
137
|
-
segmentAlignment: JsonValue;
|
|
138
|
-
};
|
|
139
177
|
}) | (LinkRelationBase & {
|
|
140
178
|
relation_kind: 'caption-alignment';
|
|
141
179
|
metadata: JsonObject & {
|
|
@@ -154,10 +192,17 @@ interface LinkClipAnchorRelationInput {
|
|
|
154
192
|
host_clip_entity_id: string;
|
|
155
193
|
trace?: JsonObject;
|
|
156
194
|
}
|
|
157
|
-
interface
|
|
195
|
+
interface LinkPhoneticScriptRenderRelationInput {
|
|
158
196
|
relation_id?: string;
|
|
159
197
|
output_entity_id: string;
|
|
198
|
+
phonetic_script_entity_id: string;
|
|
199
|
+
trace?: JsonObject;
|
|
200
|
+
}
|
|
201
|
+
/** `audio-script-source(script, source)`; the script was transcribed from the source media. */
|
|
202
|
+
interface LinkAudioScriptSourceRelationInput {
|
|
203
|
+
relation_id?: string;
|
|
160
204
|
script_entity_id: string;
|
|
205
|
+
source_entity_id: string;
|
|
161
206
|
trace?: JsonObject;
|
|
162
207
|
}
|
|
163
208
|
interface UnlinkRelationInput {
|
|
@@ -188,33 +233,44 @@ interface EntityPlanState {
|
|
|
188
233
|
deleted_relation_ids: readonly string[];
|
|
189
234
|
}
|
|
190
235
|
interface EntityFacade {
|
|
236
|
+
/** Read complete assembled fields; returned objects are snapshots. Use update to persist edits. */
|
|
191
237
|
list(): SandboxEntity[];
|
|
192
238
|
get(entityId: string): SandboxEntity | null;
|
|
193
|
-
/**
|
|
194
|
-
findByAssetId(assetId: string): SandboxEntity<
|
|
239
|
+
/** Find document resources by external Memota asset id, including directly composed media variants. */
|
|
240
|
+
findByAssetId(assetId: string): SandboxEntity<ResourceEntityKind>[];
|
|
241
|
+
/** Assemble selected Caption text; missing composition is an error. */
|
|
242
|
+
readCaptionContent(entityId: string): ComposedScriptContent;
|
|
243
|
+
/** Assemble base text and pronunciation fields before generating Voice. */
|
|
244
|
+
readPhoneticScriptContent(entityId: string): ComposedPhoneticContent;
|
|
195
245
|
create(input: CreateEntityInput): string;
|
|
196
|
-
/**
|
|
246
|
+
/** Patch assembled fields, routing inherited fields to their declaring entity. */
|
|
197
247
|
update(input: UpdateEntityInput): void;
|
|
248
|
+
/** Explicitly declare own fields, overriding unambiguous bases without modifying them. Ordinary edits use update. */
|
|
249
|
+
declareFields(input: UpdateEntityInput): void;
|
|
198
250
|
/** Delete an Entity only after all of its incident Relations have been explicitly unlinked. */
|
|
199
251
|
delete(input: DeleteEntityInput): void;
|
|
200
|
-
/**
|
|
201
|
-
|
|
252
|
+
/** Get or create one typed Asset by factual external id and return its single content identity. Never creates a Clip. */
|
|
253
|
+
ensureMedia(fact: MediaAssetFact): {
|
|
254
|
+
contentEntityId: string;
|
|
255
|
+
};
|
|
202
256
|
}
|
|
203
257
|
interface RelationFacade {
|
|
204
258
|
list(): SandboxRelation[];
|
|
205
259
|
/** Incident lookup is endpoint-agnostic; persisted endpoint positions stay unchanged. */
|
|
206
260
|
of(entityId: string, relationKind?: KnownRelationKind): SandboxRelation[];
|
|
207
|
-
/**
|
|
261
|
+
/** Link existing entities through ordinary associations; variant bases are stored directly on the variant. */
|
|
208
262
|
link(input: LinkRelationInput): string;
|
|
209
263
|
/** Author ordered generated(output,input); generic link() deliberately rejects this kind. */
|
|
210
264
|
linkGenerated(input: LinkGeneratedRelationInput): string;
|
|
211
265
|
/** Author ordered clip-anchor(child,host) without positional endpoint ambiguity. */
|
|
212
266
|
linkClipAnchor(input: LinkClipAnchorRelationInput): string;
|
|
213
|
-
/** Author ordered
|
|
214
|
-
|
|
267
|
+
/** Author ordered phonetic-script-render(output,script) without positional endpoint ambiguity. */
|
|
268
|
+
linkPhoneticScriptRender(input: LinkPhoneticScriptRenderRelationInput): string;
|
|
269
|
+
/** Author ordered audio-script-source(script,source) without positional endpoint ambiguity. */
|
|
270
|
+
linkAudioScriptSource(input: LinkAudioScriptSourceRelationInput): string;
|
|
215
271
|
/** Remove a Relation by identity; endpoint replacement is an explicit unlink plus link. */
|
|
216
272
|
unlink(input: UnlinkRelationInput): void;
|
|
217
273
|
}
|
|
218
274
|
//#endregion
|
|
219
|
-
export { SandboxEntity as _, EntityFacade as a, UpdateEntityInput as b,
|
|
220
|
-
//# sourceMappingURL=entity-contract-
|
|
275
|
+
export { SandboxEntity as _, EntityFacade as a, UpdateEntityInput as b, JsonObject as c, KnownEntityKind as d, KnownRelationKind as f, ResourceEntityKind as g, RelationFacade as h, EntityCommand as i, JsonPrimitive as l, LinkRelationInput as m, CreateEntityInput as n, EntityPlanState as o, LinkGeneratedRelationInput as p, DeleteEntityInput as r, EntityStoreSnapshot as s, AuthorableRelationKind as t, JsonValue as u, SandboxRelation as v, UnlinkRelationInput as y };
|
|
276
|
+
//# sourceMappingURL=entity-contract-DHasvrhq.d.mts.map
|