videobook-engine 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +214 -0
  2. package/dist/artifacts.d.ts +20 -0
  3. package/dist/artifacts.d.ts.map +1 -0
  4. package/dist/artifacts.js +312 -0
  5. package/dist/artifacts.js.map +1 -0
  6. package/dist/books.d.ts +7 -0
  7. package/dist/books.d.ts.map +1 -0
  8. package/dist/books.js +27 -0
  9. package/dist/books.js.map +1 -0
  10. package/dist/cas.d.ts +26 -0
  11. package/dist/cas.d.ts.map +1 -0
  12. package/dist/cas.js +139 -0
  13. package/dist/cas.js.map +1 -0
  14. package/dist/communications.d.ts +15 -0
  15. package/dist/communications.d.ts.map +1 -0
  16. package/dist/communications.js +139 -0
  17. package/dist/communications.js.map +1 -0
  18. package/dist/context.d.ts +42 -0
  19. package/dist/context.d.ts.map +1 -0
  20. package/dist/context.js +197 -0
  21. package/dist/context.js.map +1 -0
  22. package/dist/domain.d.ts +32 -0
  23. package/dist/domain.d.ts.map +1 -0
  24. package/dist/domain.js +399 -0
  25. package/dist/domain.js.map +1 -0
  26. package/dist/engine-types.d.ts +548 -0
  27. package/dist/engine-types.d.ts.map +1 -0
  28. package/dist/engine-types.js +10 -0
  29. package/dist/engine-types.js.map +1 -0
  30. package/dist/engine.d.ts +213 -0
  31. package/dist/engine.d.ts.map +1 -0
  32. package/dist/engine.js +130 -0
  33. package/dist/engine.js.map +1 -0
  34. package/dist/files.d.ts +28 -0
  35. package/dist/files.d.ts.map +1 -0
  36. package/dist/files.js +476 -0
  37. package/dist/files.js.map +1 -0
  38. package/dist/history-types.d.ts +74 -0
  39. package/dist/history-types.d.ts.map +1 -0
  40. package/dist/history-types.js +2 -0
  41. package/dist/history-types.js.map +1 -0
  42. package/dist/history.d.ts +20 -0
  43. package/dist/history.d.ts.map +1 -0
  44. package/dist/history.js +921 -0
  45. package/dist/history.js.map +1 -0
  46. package/dist/ids.d.ts +4 -0
  47. package/dist/ids.d.ts.map +1 -0
  48. package/dist/ids.js +14 -0
  49. package/dist/ids.js.map +1 -0
  50. package/dist/index.d.ts +16 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +12 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/job-queue.d.ts +51 -0
  55. package/dist/job-queue.d.ts.map +1 -0
  56. package/dist/job-queue.js +443 -0
  57. package/dist/job-queue.js.map +1 -0
  58. package/dist/media.d.ts +7 -0
  59. package/dist/media.d.ts.map +1 -0
  60. package/dist/media.js +60 -0
  61. package/dist/media.js.map +1 -0
  62. package/dist/metadata.d.ts +21 -0
  63. package/dist/metadata.d.ts.map +1 -0
  64. package/dist/metadata.js +222 -0
  65. package/dist/metadata.js.map +1 -0
  66. package/dist/notebook/types.d.ts +51 -0
  67. package/dist/notebook/types.d.ts.map +1 -0
  68. package/dist/notebook/types.js +2 -0
  69. package/dist/notebook/types.js.map +1 -0
  70. package/dist/resolver.d.ts +15 -0
  71. package/dist/resolver.d.ts.map +1 -0
  72. package/dist/resolver.js +81 -0
  73. package/dist/resolver.js.map +1 -0
  74. package/dist/runtime-services.d.ts +65 -0
  75. package/dist/runtime-services.d.ts.map +1 -0
  76. package/dist/runtime-services.js +584 -0
  77. package/dist/runtime-services.js.map +1 -0
  78. package/dist/schema.d.ts +7 -0
  79. package/dist/schema.d.ts.map +1 -0
  80. package/dist/schema.js +509 -0
  81. package/dist/schema.js.map +1 -0
  82. package/dist/similarity.d.ts +4 -0
  83. package/dist/similarity.d.ts.map +1 -0
  84. package/dist/similarity.js +1551 -0
  85. package/dist/similarity.js.map +1 -0
  86. package/dist/status.d.ts +9 -0
  87. package/dist/status.d.ts.map +1 -0
  88. package/dist/status.js +231 -0
  89. package/dist/status.js.map +1 -0
  90. package/dist/storage.d.ts +7 -0
  91. package/dist/storage.d.ts.map +1 -0
  92. package/dist/storage.js +129 -0
  93. package/dist/storage.js.map +1 -0
  94. package/dist/store.d.ts +55 -0
  95. package/dist/store.d.ts.map +1 -0
  96. package/dist/store.js +378 -0
  97. package/dist/store.js.map +1 -0
  98. package/dist/timeline.d.ts +9 -0
  99. package/dist/timeline.d.ts.map +1 -0
  100. package/dist/timeline.js +236 -0
  101. package/dist/timeline.js.map +1 -0
  102. package/docs/engine-layout.md +489 -0
  103. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # videobook-engine
2
+
3
+ `videobook-engine` is a local-first, Dolt-native storage engine for one
4
+ videobook per engine root. It keeps book state, artifacts, files, metadata,
5
+ notebook graphs, revisions, and action history in a single catalog.
6
+
7
+ There is no project layer. A fresh engine root creates exactly one Book;
8
+ reopening that root always returns the same book.
9
+
10
+ ## Quick start
11
+
12
+ ```ts
13
+ import { createEngine } from "videobook-engine";
14
+
15
+ const engine = createEngine({
16
+ rootDir: ".videobook",
17
+ initialBookSlug: "my-story",
18
+ });
19
+
20
+ const book = engine.book.get();
21
+ // { bookId: "…", slug: "my-story", createdAt: … }
22
+
23
+ const script = await engine.artifacts.create({
24
+ kind: "script",
25
+ name: "opening draft",
26
+ });
27
+ if (!script.ok) throw new Error(script.error.message);
28
+
29
+ await engine.files.write(
30
+ script.value.artifactId,
31
+ "original.md",
32
+ "# Opening\n\nA small cat waits by the window.",
33
+ );
34
+
35
+ const history = engine.history.artifact(script.value.artifactId);
36
+ engine.close();
37
+ ```
38
+
39
+ `initialBookSlug` is required only when `videobook.db` does not exist yet. On
40
+ later opens it is optional and never changes the stored book. Rename the book
41
+ explicitly with `await engine.book.rename("new-name")`.
42
+
43
+ ## Storage model
44
+
45
+ Each engine root owns exactly one book:
46
+
47
+ ```text
48
+ rootDir/
49
+ data/
50
+ videobook.db # Dolt semantic catalog and SQLite runtime state
51
+ objects/sha256/ # content-addressed file objects
52
+ workspaces/
53
+ <artifact UUID>/ # disposable materialized artifact files
54
+ ```
55
+
56
+ Semantic tables are committed as Dolt revisions. Runtime tables (jobs, leases,
57
+ views, caches, settings, and logs) share the same database, match the
58
+ versioned `runtime_%` ignore policy, and are never staged. Semantic surrogate
59
+ identities are UUIDv7 values. Artifact slugs are human-facing names and can be
60
+ reused after hard deletion; immutable CAS objects remain available to history.
61
+
62
+ The current catalog format is schema version 4. It intentionally rejects v3
63
+ and older catalogs rather than migrating them; create a fresh engine root.
64
+
65
+ The 25 versioned semantic tables are `engine_schema`, `book`, `artifacts`,
66
+ `objects`, `artifact_files`, `book_metadata`, `artifact_metadata`,
67
+ `entities`, `notebooks`, `cells`, `edges`, `runs`, `timeline`,
68
+ `timeline_slots`, `timeline_audio`, `audio_waveforms`, `prompt_entries`,
69
+ `messages`, `operations`, `actions`, `action_events`, `action_parents`,
70
+ `action_artifacts`, `action_write_set`, and `job_runs`. Dolt's versioned
71
+ `dolt_ignore` configuration table carries the local-table policy.
72
+
73
+ The 14 local-only tables are `runtime_meta`, `runtime_jobs`,
74
+ `runtime_resource_leases`, `runtime_object_publications`,
75
+ `runtime_workspace_entries`, `runtime_artifact_views`,
76
+ `runtime_pending_tasks`, `runtime_generation_errors`, `runtime_settings`,
77
+ `runtime_logs`, `runtime_commit_outbox`, `runtime_similarity_embeddings`,
78
+ `runtime_text_similarity_documents`, and `runtime_text_similarity_chunks`.
79
+
80
+ See [the complete engine layout](docs/engine-layout.md) for every schema
81
+ column, relationship, index, runtime/CAS structure, current editing contract,
82
+ and the additional normalized structures a full non-linear editor will need.
83
+
84
+ ## Artifacts and slugs
85
+
86
+ Artifact slugs are canonical and kind-prefixed. Supplying a `name` derives a
87
+ slug; supplying a `slug` validates it. Repeated name-based creation adds a
88
+ numeric suffix when needed.
89
+
90
+ | Kind | Prefix | Example |
91
+ | --- | --- | --- |
92
+ | `video` | `vid-` | `vid-opening-shot` |
93
+ | `image` | `img-` | `img-cat-portrait` |
94
+ | `audio` | `aud-` | `aud-ambient-bed` |
95
+ | `script` | `script-` | `script-opening-draft` |
96
+ | `character` | `char-` | `char-protagonist` |
97
+ | `prompt` | `prompt-` | `prompt-sunrise` |
98
+ | `scene` | `scene-` | `scene-rooftop` |
99
+ | `final` | `final` | `final` |
100
+
101
+ There is no `notebook` artifact kind or `book-` artifact prefix. Notebook
102
+ graphs remain available separately through `engine.notebooks`.
103
+
104
+ ## API surface
105
+
106
+ - `engine.book` — `get()` and `rename(slug)` for the singleton book
107
+ - `engine.artifacts` — create, list, get, rename, delete, and resolve slugs
108
+ - `engine.files` and `engine.workspaces` — immutable object-backed files and
109
+ disposable materialization
110
+ - `engine.metadata` — book metadata, artifact metadata, and audio waveforms
111
+ - `engine.timeline` — typed timeline reads, revision reads, replacement, and
112
+ reset
113
+ - `engine.entities` and `engine.notebooks` — normalized characters, prompts,
114
+ scenes, and notebook graph documents
115
+ - `engine.prompts` and `engine.messages` — semantic prompt and message history
116
+ - `engine.history` — revisions, generic action graph entries, and forward
117
+ restores
118
+ - `engine.jobs`, `engine.status`, `engine.settings`, and `engine.logs` —
119
+ runtime coordination
120
+ - `engine.storage` — object publication and catalog backup
121
+ - `engine.similarity` — optional local media and text similarity
122
+
123
+ All APIs operate in the engine's one book. No method accepts or returns a
124
+ project ID.
125
+
126
+ Deleting an artifact or entity that is referenced by a live cell or timeline
127
+ row returns `IN_USE` with `details.references`. Deleting a notebook cascades
128
+ its owned cells, edges, and terminal runs. There are no tombstone rows.
129
+
130
+ ## Revisions and restores
131
+
132
+ Every semantic mutation creates a Dolt revision. Use a revision hash (or an
133
+ unambiguous prefix) to inspect or restore state:
134
+
135
+ ```ts
136
+ const revisions = engine.history.revisions();
137
+
138
+ await engine.history.restoreArtifact(
139
+ artifactId,
140
+ revisions[0]!.hash,
141
+ "script-restored-draft", // optional replacement slug
142
+ );
143
+
144
+ await engine.history.restore(revisions[0]!.hash);
145
+ ```
146
+
147
+ `restoreArtifact` keeps the artifact UUID stable and restores its files,
148
+ metadata, and waveform as a new forward revision. `restore` replays the whole
149
+ book snapshot forward: book metadata, artifacts and files, entities,
150
+ notebooks, timeline, prompts, and messages. Runtime work is invalidated and
151
+ active jobs are aborted during a restore.
152
+
153
+ ## Future forks
154
+
155
+ Schema v4 prepares stable row identities and normalized merge boundaries for
156
+ DoltHub-native forks. A fork is a separate catalog copy in another namespace,
157
+ keeps the same `bookId`, and can open a pull request against the upstream
158
+ `main` branch. User, origin, fork, and pull-request APIs are intentionally not
159
+ part of this release; an open engine still accepts only its local `main`
160
+ branch.
161
+
162
+ Generic action records are available for higher-level workflows:
163
+
164
+ ```ts
165
+ const action = await engine.history.recordAction({
166
+ operation: "generate_image",
167
+ scope: "artifact",
168
+ targetArtifactId: imageId,
169
+ inputArtifactIds: [promptId],
170
+ outputArtifactIds: [imageId],
171
+ writeSet: [`artifact:${imageId}`],
172
+ });
173
+
174
+ const page = engine.history.actions({ limit: 50 });
175
+ ```
176
+
177
+ ## Similarity
178
+
179
+ Similarity is opt-in. Provide a media embedding provider or use the built-in
180
+ local CLIP configuration. Text similarity is enabled separately.
181
+
182
+ ```ts
183
+ const engine = createEngine({
184
+ rootDir: ".videobook",
185
+ initialBookSlug: "reference-library",
186
+ similarity: {
187
+ audio: {},
188
+ text: {},
189
+ },
190
+ });
191
+
192
+ await engine.similarity.index(imageArtifactId);
193
+ await engine.similarity.index(similarImageArtifactId);
194
+
195
+ const matches = await engine.similarity.findSimilar(imageArtifactId, {
196
+ limit: 10,
197
+ minScore: 0.7,
198
+ });
199
+ ```
200
+
201
+ Image, video, and audio sources must be named `original.<extension>`. Audio
202
+ similarity is opt-in through `similarity.audio` and uses local CLAP embeddings
203
+ without Python. Supported audio extensions are MP3, WAV, OGG, FLAC, AAC, and
204
+ M4A. Text similarity supports `original.md`, `original.txt`, and
205
+ `original.json` for `script`, `character`, `prompt`, `scene`, and `final`
206
+ artifacts. All similarity queries search the single book-wide pool while
207
+ preserving media kind and embedding-space boundaries.
208
+
209
+ ## Backups
210
+
211
+ Configure `remoteObjects` to publish content-addressed objects and
212
+ `catalogBackup` to push the Dolt catalog. `engine.storage.backup()` publishes
213
+ objects first, then pushes the catalog, so a restored catalog never points to
214
+ objects that have not been uploaded.
@@ -0,0 +1,20 @@
1
+ import type { Artifact, ArtifactKind, CreateArtifactInput, EngineError, RenameArtifactInput, Result } from "./engine-types.js";
2
+ import { EngineContext } from "./context.js";
3
+ export declare function createArtifactsApi(context: EngineContext): {
4
+ create: (input: CreateArtifactInput | string, name?: string) => Promise<Result<Artifact, EngineError>>;
5
+ list: (options?: {
6
+ sort?: "newest" | "oldest";
7
+ }) => Artifact[];
8
+ get: (artifact: string) => Result<Artifact, EngineError>;
9
+ resolveSlug: (slug: string) => Result<Artifact, EngineError>;
10
+ isSlugAvailable: (slug: string) => boolean;
11
+ rename: (input: RenameArtifactInput | string, name?: string) => Promise<Result<Artifact, EngineError>>;
12
+ delete: (artifact: string) => Promise<Result<{
13
+ artifactId: string;
14
+ slug: string;
15
+ }, EngineError>>;
16
+ };
17
+ export declare function normalizeKind(input: string): ArtifactKind;
18
+ /** Normalizes a name or slug with the canonical prefix for its artifact kind. */
19
+ export declare function artifactSlug(kind: ArtifactKind, input: string): string;
20
+ //# sourceMappingURL=artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,MAAM,EACP,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EAId,MAAM,cAAc,CAAC;AActB,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa;oBAG5C,mBAAmB,GAAG,MAAM,SAC5B,MAAM,KACZ,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;qBAExB;QAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;KAAE,KAAG,QAAQ,EAAE;oBAE5C,MAAM,KAAG,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC;wBAElC,MAAM,KAAG,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC;4BAYlC,MAAM,KAAG,OAAO;oBAS/B,mBAAmB,GAAG,MAAM,SAC5B,MAAM,KACZ,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;uBAG7B,MAAM,KACf,OAAO,CACR,MAAM,CACJ;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EACpC,WAAW,CACZ,CACF;EAEJ;AAgPD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CA4BzD;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAuBtE"}
@@ -0,0 +1,312 @@
1
+ import { rm } from "node:fs/promises";
2
+ import { ok } from "./engine-types.js";
3
+ import { resultOf, syncResultOf, } from "./context.js";
4
+ import { canonicalJson } from "./store.js";
5
+ import { EngineFault } from "./store.js";
6
+ import { newUuidV7 } from "./ids.js";
7
+ export function createArtifactsApi(context) {
8
+ return {
9
+ create: (input, name) => createArtifact(context, input, name),
10
+ list: (options) => listArtifacts(context, options),
11
+ get: (artifact) => syncResultOf(() => context.artifact(context.artifactRow(artifact))),
12
+ resolveSlug: (slug) => syncResultOf(() => {
13
+ const row = context.store.db
14
+ .prepare(`SELECT artifact_id, slug, kind, created_at
15
+ FROM artifacts
16
+ WHERE slug=?`)
17
+ .get(slug);
18
+ if (!row)
19
+ throw new Error(`Active artifact slug not found: ${slug}`);
20
+ return context.artifact(row);
21
+ }),
22
+ isSlugAvailable: (slug) => !context.store.db
23
+ .prepare(`SELECT 1 AS present
24
+ FROM artifacts
25
+ WHERE slug=?`)
26
+ .get(slug),
27
+ rename: (input, name) => renameArtifact(context, input, name),
28
+ delete: (artifact) => deleteArtifact(context, artifact),
29
+ };
30
+ }
31
+ async function createArtifact(context, input, positionalName) {
32
+ return resultOf(async () => {
33
+ const parsed = typeof input === "string"
34
+ ? {
35
+ kind: normalizeKind(input),
36
+ name: positionalName ?? "",
37
+ explicitSlug: undefined,
38
+ }
39
+ : {
40
+ kind: normalizeKind(input.kind),
41
+ name: input.name ?? input.slug ?? "",
42
+ explicitSlug: input.slug,
43
+ };
44
+ const base = artifactSlug(parsed.kind, parsed.explicitSlug ?? parsed.name);
45
+ const slug = parsed.explicitSlug === undefined
46
+ ? nextActiveSlug(context, base)
47
+ : base;
48
+ const artifactId = newUuidV7();
49
+ const mutation = await context.store.semantic({
50
+ operation: "create_artifact",
51
+ artifactId,
52
+ details: { slug, kind: parsed.kind },
53
+ writeSet: [
54
+ `artifact:${artifactId}`,
55
+ `artifact-slug:${slug}`,
56
+ ],
57
+ }, ["artifacts"], (_operationId, now) => {
58
+ context.store.db
59
+ .prepare(`INSERT INTO artifacts(
60
+ artifact_id, slug, kind, created_at
61
+ ) VALUES (?, ?, ?, ?)`)
62
+ .run(artifactId, slug, parsed.kind, now);
63
+ context.store.db
64
+ .prepare(`INSERT INTO runtime_artifact_views(
65
+ artifact_id, status, meta_json, deadline_at, updated_at
66
+ ) VALUES (?, 'pending', '{}', ?, ?)`)
67
+ .run(artifactId, now + 30_000, now);
68
+ context.store.db
69
+ .prepare(`INSERT INTO runtime_workspace_entries(
70
+ artifact_id, path, last_accessed_at
71
+ ) VALUES (?, ?, ?)`)
72
+ .run(artifactId, context.artifactPath(artifactId), now);
73
+ });
74
+ context.ensureArtifactWorkspace(artifactId);
75
+ return ok(context.artifact(context.artifactRow(artifactId)), mutation.revision);
76
+ });
77
+ }
78
+ function listArtifacts(context, options = {}) {
79
+ const direction = options.sort === "oldest" ? "ASC" : "DESC";
80
+ const rows = context.store.db
81
+ .prepare(`SELECT artifact_id, slug, kind, created_at
82
+ FROM artifacts
83
+ ORDER BY created_at ${direction}, artifact_id ${direction}`)
84
+ .all();
85
+ return rows.map((row) => context.artifact(row));
86
+ }
87
+ async function renameArtifact(context, input, positionalName) {
88
+ return resultOf(async () => {
89
+ const parsed = typeof input === "string"
90
+ ? { artifact: input, name: positionalName ?? "", slug: undefined }
91
+ : input;
92
+ const current = context.artifactRow(parsed.artifact);
93
+ const slug = artifactSlug(current.kind, parsed.slug ?? parsed.name ?? "");
94
+ if (slug === current.slug)
95
+ return context.artifact(current);
96
+ const mutation = await context.store.semantic({
97
+ operation: "rename_artifact",
98
+ artifactId: current.artifact_id,
99
+ details: { oldSlug: current.slug, newSlug: slug },
100
+ writeSet: [
101
+ `artifact:${current.artifact_id}`,
102
+ `artifact-slug:${current.slug}`,
103
+ `artifact-slug:${slug}`,
104
+ ],
105
+ }, ["artifacts"], () => {
106
+ context.store.db
107
+ .prepare(`UPDATE artifacts
108
+ SET slug=?
109
+ WHERE artifact_id=?`)
110
+ .run(slug, current.artifact_id);
111
+ });
112
+ return ok(context.artifact(context.artifactRow(current.artifact_id)), mutation.revision);
113
+ });
114
+ }
115
+ async function deleteArtifact(context, artifactReference) {
116
+ return resultOf(async () => {
117
+ const artifact = context.artifactRow(artifactReference);
118
+ const references = artifactReferences(context, artifact.artifact_id);
119
+ if (references.length > 0) {
120
+ throw new EngineFault({
121
+ code: "IN_USE",
122
+ message: `Artifact is still referenced: ${artifact.slug}`,
123
+ details: { references },
124
+ });
125
+ }
126
+ const jobs = context.store.db
127
+ .prepare(`SELECT id, artifact_id, type, payload_json, result_json, started_at
128
+ FROM runtime_jobs
129
+ WHERE artifact_id=?
130
+ AND state IN ('queued','running','completing')`)
131
+ .all(artifact.artifact_id);
132
+ const mutation = await context.store.semantic({
133
+ operation: "delete_artifact",
134
+ artifactId: artifact.artifact_id,
135
+ details: {
136
+ slug: artifact.slug,
137
+ cancelledJobs: jobs.map((job) => job.id),
138
+ },
139
+ writeSet: [
140
+ `artifact:${artifact.artifact_id}`,
141
+ `artifact-slug:${artifact.slug}`,
142
+ ],
143
+ }, [
144
+ "artifacts",
145
+ "artifact_files",
146
+ "artifact_metadata",
147
+ "audio_waveforms",
148
+ "job_runs",
149
+ ], (_operationId, now) => {
150
+ context.store.db
151
+ .prepare("DELETE FROM artifacts WHERE artifact_id=?")
152
+ .run(artifact.artifact_id);
153
+ for (const job of jobs) {
154
+ const errorJson = canonicalJson({ message: "Artifact deleted" });
155
+ context.store.db
156
+ .prepare(`UPDATE runtime_jobs
157
+ SET state='aborted', error_json=?, finished_at=?,
158
+ lease_expires_at=NULL, pid=NULL, fence=fence+1
159
+ WHERE id=?`)
160
+ .run(errorJson, now, job.id);
161
+ context.store.db
162
+ .prepare(`INSERT INTO job_runs(
163
+ run_id, artifact_id, job_type, state,
164
+ payload_json, result_json, error_json,
165
+ started_at, finished_at
166
+ ) VALUES (?, ?, ?, 'aborted', ?, ?, ?, ?, ?)`)
167
+ .run(newUuidV7(), job.artifact_id, job.type, job.payload_json, job.result_json, errorJson, job.started_at, now);
168
+ }
169
+ context.store.db
170
+ .prepare(`UPDATE runtime_resource_leases
171
+ SET revoked_at=?, fence=fence+1
172
+ WHERE artifact_id=? AND revoked_at IS NULL`)
173
+ .run(now, artifact.artifact_id);
174
+ context.store.db
175
+ .prepare("DELETE FROM runtime_workspace_entries WHERE artifact_id=?")
176
+ .run(artifact.artifact_id);
177
+ context.store.db
178
+ .prepare("DELETE FROM runtime_artifact_views WHERE artifact_id=?")
179
+ .run(artifact.artifact_id);
180
+ context.store.db
181
+ .prepare("DELETE FROM runtime_pending_tasks WHERE artifact_id=?")
182
+ .run(artifact.artifact_id);
183
+ context.store.db
184
+ .prepare("DELETE FROM runtime_generation_errors WHERE artifact_id=?")
185
+ .run(artifact.artifact_id);
186
+ context.store.db
187
+ .prepare("DELETE FROM runtime_similarity_embeddings WHERE artifact_id=?")
188
+ .run(artifact.artifact_id);
189
+ context.store.db
190
+ .prepare("DELETE FROM runtime_text_similarity_documents WHERE artifact_id=?")
191
+ .run(artifact.artifact_id);
192
+ });
193
+ await rm(context.artifactPath(artifact.artifact_id), {
194
+ recursive: true,
195
+ force: true,
196
+ });
197
+ return ok({
198
+ artifactId: artifact.artifact_id,
199
+ slug: artifact.slug,
200
+ }, mutation.revision);
201
+ });
202
+ }
203
+ export function normalizeKind(input) {
204
+ switch (input.trim().toLowerCase()) {
205
+ case "vid":
206
+ case "video":
207
+ return "video";
208
+ case "img":
209
+ case "image":
210
+ return "image";
211
+ case "aud":
212
+ case "audio":
213
+ return "audio";
214
+ case "script":
215
+ case "scr":
216
+ return "script";
217
+ case "char":
218
+ case "character":
219
+ return "character";
220
+ case "prm":
221
+ case "prompt":
222
+ return "prompt";
223
+ case "scn":
224
+ case "scene":
225
+ return "scene";
226
+ case "final":
227
+ return "final";
228
+ default:
229
+ throw new Error(`Invalid artifact kind: ${input}`);
230
+ }
231
+ }
232
+ /** Normalizes a name or slug with the canonical prefix for its artifact kind. */
233
+ export function artifactSlug(kind, input) {
234
+ if (kind === "final")
235
+ return "final";
236
+ const prefix = prefixForKind(kind);
237
+ let normalized = input
238
+ .trim()
239
+ .toLowerCase()
240
+ .replace(/^@/, "")
241
+ .replace(/[^a-z0-9_-]+/g, "-")
242
+ .replace(/-+/g, "-")
243
+ .replace(/^[-_]+|[-_]+$/g, "");
244
+ if (!normalized)
245
+ throw new Error("Artifact name or slug is required");
246
+ const knownPrefix = /^(vid|img|aud|script|char|prompt|scene|prm|scn)-/;
247
+ if (knownPrefix.test(normalized)) {
248
+ if (!normalized.startsWith(`${prefix}-`)) {
249
+ throw new Error(`Artifact slug ${normalized} does not match kind ${kind}`);
250
+ }
251
+ return normalized;
252
+ }
253
+ normalized = `${prefix}-${normalized}`;
254
+ if (!/^[a-z0-9]+(?:[a-z0-9_-]*[a-z0-9])?$/.test(normalized)) {
255
+ throw new Error(`Invalid artifact slug: ${normalized}`);
256
+ }
257
+ return normalized;
258
+ }
259
+ function nextActiveSlug(context, base) {
260
+ let suffix = 1;
261
+ let candidate = base;
262
+ while (context.store.db
263
+ .prepare(`SELECT 1 AS present
264
+ FROM artifacts
265
+ WHERE slug=?`)
266
+ .get(candidate)) {
267
+ suffix += 1;
268
+ candidate = `${base}-${suffix}`;
269
+ }
270
+ return candidate;
271
+ }
272
+ function artifactReferences(context, artifactId) {
273
+ const references = [];
274
+ const cells = context.store.db
275
+ .prepare(`SELECT notebook_id, cell_id FROM cells
276
+ WHERE output_artifact_id=? ORDER BY notebook_id, cell_id`)
277
+ .all(artifactId);
278
+ references.push(...cells.map((cell) => ({
279
+ kind: "cell.outputArtifact",
280
+ id: `${cell.notebook_id}/${cell.cell_id}`,
281
+ })));
282
+ const slots = context.store.db
283
+ .prepare("SELECT slot_id FROM timeline_slots WHERE artifact_id=? ORDER BY slot_id")
284
+ .all(artifactId);
285
+ references.push(...slots.map((slot) => ({ kind: "timeline.slot", id: slot.slot_id })));
286
+ const audio = context.store.db
287
+ .prepare("SELECT audio_id FROM timeline_audio WHERE artifact_id=? ORDER BY audio_id")
288
+ .all(artifactId);
289
+ references.push(...audio.map((item) => ({ kind: "timeline.audio", id: item.audio_id })));
290
+ return references;
291
+ }
292
+ function prefixForKind(kind) {
293
+ switch (kind) {
294
+ case "video":
295
+ return "vid";
296
+ case "image":
297
+ return "img";
298
+ case "audio":
299
+ return "aud";
300
+ case "script":
301
+ return "script";
302
+ case "character":
303
+ return "char";
304
+ case "prompt":
305
+ return "prompt";
306
+ case "scene":
307
+ return "scene";
308
+ case "final":
309
+ return "final";
310
+ }
311
+ }
312
+ //# sourceMappingURL=artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Book, EngineError, Result } from "./engine-types.js";
2
+ import { EngineContext } from "./context.js";
3
+ export declare function createBookApi(context: EngineContext): {
4
+ get: () => Book;
5
+ rename: (slug: string) => Promise<Result<Book, EngineError>>;
6
+ };
7
+ //# sourceMappingURL=books.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"books.d.ts","sourceRoot":"","sources":["../src/books.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EACL,aAAa,EAGd,MAAM,cAAc,CAAC;AAEtB,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa;eAEvC,IAAI;mBACE,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;EAG7D"}
package/dist/books.js ADDED
@@ -0,0 +1,27 @@
1
+ import { ok } from "./engine-types.js";
2
+ import { normalizeBookSlug, resultOf, } from "./context.js";
3
+ export function createBookApi(context) {
4
+ return {
5
+ get: () => context.book(),
6
+ rename: (slug) => renameBook(context, slug),
7
+ };
8
+ }
9
+ async function renameBook(context, requestedSlug) {
10
+ return resultOf(async () => {
11
+ const current = context.bookRow();
12
+ const slug = normalizeBookSlug(requestedSlug);
13
+ if (current.slug === slug)
14
+ return context.book(current);
15
+ const mutation = await context.store.semantic({
16
+ operation: "rename_book",
17
+ details: { oldSlug: current.slug, newSlug: slug },
18
+ writeSet: ["book", `book-slug:${current.slug}`, `book-slug:${slug}`],
19
+ }, ["book"], () => {
20
+ context.store.db
21
+ .prepare("UPDATE book SET slug=? WHERE book_id=?")
22
+ .run(slug, current.book_id);
23
+ });
24
+ return ok(context.book(), mutation.revision);
25
+ });
26
+ }
27
+ //# sourceMappingURL=books.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"books.js","sourceRoot":"","sources":["../src/books.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAEL,iBAAiB,EACjB,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,MAAM,UAAU,aAAa,CAAC,OAAsB;IAClD,OAAO;QACL,GAAG,EAAE,GAAS,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE;QAC/B,MAAM,EAAE,CAAC,IAAY,EAAsC,EAAE,CAC3D,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC;KAC5B,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,OAAsB,EACtB,aAAqB;IAErB,OAAO,QAAQ,CAAC,KAAK,IAAI,EAAE;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAC9C,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,CAC3C;YACE,SAAS,EAAE,aAAa;YACxB,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;YACjD,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,IAAI,EAAE,CAAC;SACrE,EACD,CAAC,MAAM,CAAC,EACR,GAAG,EAAE;YACH,OAAO,CAAC,KAAK,CAAC,EAAE;iBACb,OAAO,CAAC,wCAAwC,CAAC;iBACjD,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC,CACF,CAAC;QACF,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/cas.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { ContentStore } from "./engine-types.js";
2
+ export interface StoredObject {
3
+ hash: string;
4
+ size: number;
5
+ path: string;
6
+ }
7
+ export declare class ObjectStore {
8
+ private readonly remote?;
9
+ readonly root: string;
10
+ readonly prefix: string;
11
+ constructor(root: string, remote?: ContentStore | undefined, prefix?: string);
12
+ put(data: Buffer | string): Promise<StoredObject>;
13
+ import(sourcePath: string): Promise<StoredObject>;
14
+ read(hash: string): Promise<Buffer>;
15
+ /**
16
+ * Makes a content-addressed object available locally and returns its path
17
+ * without copying it into an artifact workspace.
18
+ */
19
+ ensureLocalPath(hash: string): Promise<string>;
20
+ materialize(hash: string, destinationPath: string): Promise<void>;
21
+ publish(hash: string, expectedSize: number): Promise<void>;
22
+ pathFor(hash: string): string;
23
+ keyFor(hash: string): string;
24
+ private ensureLocal;
25
+ }
26
+ //# sourceMappingURL=cas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cas.d.ts","sourceRoot":"","sources":["../src/cas.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,WAAW;IAMpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAL1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGtB,IAAI,EAAE,MAAM,EACK,MAAM,CAAC,EAAE,YAAY,YAAA,EACtC,MAAM,SAAoC;IAMtC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAmBjD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAgBjD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKzC;;;OAGG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK9C,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBhE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAK7B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;YAKd,WAAW;CAkB1B"}