@vanillaskyai/video 0.4.1 → 0.5.0

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 (53) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/PUBLIC-API.md +12 -5
  3. package/README.md +14 -17
  4. package/dist/{builtin-server-BRTZN4Q7.js → builtin-server-YHEZ2JRF.js} +2 -2
  5. package/dist/check-runtime.js +1 -1
  6. package/dist/{chunk-BKF3A357.js → chunk-34O5BY6X.js} +1 -1
  7. package/dist/{chunk-LHFADNWJ.js → chunk-3ROGEU5A.js} +179 -342
  8. package/dist/{chunk-XAMUOSX7.js → chunk-3RV4YKB3.js} +0 -1
  9. package/dist/{chunk-GHJEAP4O.js → chunk-66MNRUCR.js} +1 -1
  10. package/dist/{chunk-EE6PK6XC.js → chunk-AOWSXU2K.js} +1 -1
  11. package/dist/{chunk-GR4I3MN2.js → chunk-EFL34TXF.js} +3 -3
  12. package/dist/{chunk-I5YWVQ5R.js → chunk-FVTMYS6U.js} +1 -1
  13. package/dist/{chunk-STIFILQG.js → chunk-FZHMQFG3.js} +46 -38
  14. package/dist/{chunk-JW47XCRL.js → chunk-G66Z5CWR.js} +30 -72
  15. package/dist/{chunk-RBQN3VSY.js → chunk-HVCPEAQF.js} +83 -1265
  16. package/dist/{chunk-N3KUA7VP.js → chunk-K6YVQODK.js} +4 -1
  17. package/dist/{chunk-WHPZED7X.js → chunk-PNS52FL4.js} +2 -5
  18. package/dist/{chunk-S5ZU5WUU.js → chunk-ZQQQAAKP.js} +2 -2
  19. package/dist/cli.js +20 -14
  20. package/dist/compose-video-QJHKTOQ7.js +13 -0
  21. package/dist/{events-D_1F6gw5.d.ts → events-BBP30j3c.d.ts} +3 -14
  22. package/dist/index.d.ts +2 -2
  23. package/dist/index.js +2 -2
  24. package/dist/{kit-DLeCr3d0.d.ts → kit-DEG3fcaL.d.ts} +1 -1
  25. package/dist/react.d.ts +6 -5
  26. package/dist/react.js +999 -348
  27. package/dist/server.d.ts +3 -3
  28. package/dist/server.js +18 -79
  29. package/dist/{system-prompt-NMYHLAMJ.js → system-prompt-4I6Z5HK3.js} +1 -1
  30. package/dist/template-catalog.js +1 -1
  31. package/dist/templates.d.ts +3 -3
  32. package/dist/templates.js +87 -4
  33. package/dist/test.d.ts +3 -27
  34. package/dist/test.js +3 -3
  35. package/dist/{text-stream-UPGUD2TD.js → text-stream-J6EDDJP4.js} +3 -3
  36. package/dist/{types-Cg0Onj7l.d.ts → types-BV9IqExh.d.ts} +1 -16
  37. package/docs/agent-integration.md +4 -3
  38. package/docs/concepts.md +4 -4
  39. package/docs/custom-templates.md +2 -2
  40. package/docs/getting-started.md +13 -18
  41. package/docs/integrate-nextjs.md +12 -8
  42. package/docs/persistence.md +1 -1
  43. package/docs/prompt-and-input.md +2 -2
  44. package/docs/reference/protocol.md +9 -12
  45. package/docs/reference/provider-adapters.md +5 -5
  46. package/docs/testing.md +1 -1
  47. package/examples/nextjs-quickstart/.env.example +2 -2
  48. package/examples/nextjs-quickstart/README.md +4 -1
  49. package/examples/nextjs-quickstart/package.json +4 -4
  50. package/examples/nextjs-quickstart/src/app/api/video/route.ts +4 -2
  51. package/package.json +8 -8
  52. package/dist/chunk-CR7FE7BW.js +0 -109
  53. package/dist/compose-video-6UQ33DOO.js +0 -13
@@ -1,10 +1,10 @@
1
- # Video Response Protocol 0.4
1
+ # Video Response Protocol 0.5
2
2
 
3
3
  ## Transport
4
4
 
5
5
  The public transport is UTF-8 Server-Sent Events returned from a `POST` request.
6
6
  Responses use `Content-Type: text/event-stream`,
7
- `x-vanillasky-video-stream: 0.4`, `Cache-Control: no-cache, no-transform`, and
7
+ `x-vanillasky-video-stream: 0.5`, `Cache-Control: no-cache, no-transform`, and
8
8
  `X-Accel-Buffering: no`. Each block has an SSE `id`, the event name
9
9
  `video`, and one JSON envelope in `data`. A final `data: [DONE]`
10
10
  closes the transport after a terminal protocol event. Comment heartbeats do not
@@ -14,7 +14,7 @@ change protocol state.
14
14
 
15
15
  ```ts
16
16
  type VideoEvent<T extends string, D> = {
17
- protocolVersion: "0.4";
17
+ protocolVersion: "0.5";
18
18
  runId: string;
19
19
  sequence: number;
20
20
  eventId: string; // exactly `${runId}:${sequence}`
@@ -33,10 +33,8 @@ midstream and events cannot follow a terminal state.
33
33
  1. `response.start` establishes request ID, orientation, style, and negotiated
34
34
  templates/extensions.
35
35
  2. Optional `audio.set` occurs at most once and before the first scene.
36
- 3. `scene.add` appends one trusted-template scene at revision `0`.
37
- 4. `scene.patch` or `asset.patch` advances that scene revision by exactly one.
38
- A host must reject patches after the scene has played.
39
- 5. Exactly one terminal event ends the run:
36
+ 3. `scene.add` appends one complete, immutable trusted-template scene.
37
+ 4. Exactly one terminal event ends the run:
40
38
  `response.complete`, terminal `response.error`, or `response.abort`.
41
39
 
42
40
  `response.complete` carries the complete replayable `Video`, a
@@ -55,8 +53,8 @@ server callback.
55
53
 
56
54
  ### Duration ceiling
57
55
 
58
- `maxDurationSec` is enforced by the runtime for scene additions and timing
59
- patches. A final scene may be shortened to the remaining duration. If a later
56
+ `maxDurationSec` is enforced by the runtime for scene additions. A final scene
57
+ may be shortened to the remaining duration. If a later
60
58
  scene would start at the ceiling, the runtime preserves the partial response
61
59
  and emits `response.complete` with `finishReason: "length"`; reaching the
62
60
  declared maximum is normal completion, not a generation error. The value is a
@@ -73,9 +71,8 @@ change core video state.
73
71
  ## Planning boundary
74
72
 
75
73
  LLMs do not emit public protocol envelopes. A server-only planner emits
76
- validated `scene.add`, `scene.patch`, `asset.patch`, `plan.complete`, or
77
- `plan.error` parts. The runtime assigns sequences, revisions, IDs, terminal
78
- snapshots, and checksums. Generated HTML, React, JavaScript, CSS, component
74
+ validated `scene.add` or `plan.complete` parts. The runtime assigns sequences,
75
+ IDs, terminal snapshots, and checksums. Generated HTML, React, JavaScript, CSS, component
79
76
  source, audio events, protocol envelopes, and unknown part types are rejected.
80
77
 
81
78
  A planner may add `placement: "closer"` to exactly one `scene.add`. The
@@ -14,21 +14,21 @@ community, AI Gateway, OpenAI-compatible, and custom providers.
14
14
  Install the AI SDK plus the provider package your application chooses:
15
15
 
16
16
  ```bash
17
- npm install ai @ai-sdk/openai
17
+ npm install ai @ai-sdk/anthropic
18
18
  ```
19
19
 
20
20
  ```ts
21
- import { openai } from "@ai-sdk/openai";
21
+ import { anthropic } from "@ai-sdk/anthropic";
22
22
  import { streamText } from "ai";
23
23
  import { createVideoHandler } from "@vanillaskyai/video/server";
24
24
 
25
- const modelId = process.env.OPENAI_MODEL;
26
- if (!modelId) throw new Error("Set OPENAI_MODEL in the server environment");
25
+ const modelId = process.env.ANTHROPIC_MODEL;
26
+ if (!modelId) throw new Error("Set ANTHROPIC_MODEL in the server environment");
27
27
 
28
28
  export const POST = createVideoHandler({
29
29
  authorize: verifySession,
30
30
  streamText: ({ systemPrompt, userPrompt, signal }) => streamText({
31
- model: openai(modelId),
31
+ model: anthropic(modelId),
32
32
  system: systemPrompt,
33
33
  prompt: userPrompt,
34
34
  abortSignal: signal,
package/docs/testing.md CHANGED
@@ -28,7 +28,7 @@ describe("POST /api/video", () => {
28
28
  const response = await handle(new Request("https://app.test/api/video", {
29
29
  method: "POST",
30
30
  body: JSON.stringify({
31
- protocolVersion: "0.4",
31
+ protocolVersion: "0.5",
32
32
  requestId: "route-test",
33
33
  input: videoFixtures.portrait.input,
34
34
  }),
@@ -1,2 +1,2 @@
1
- OPENAI_API_KEY=replace-me
2
- OPENAI_MODEL=gpt-4.1
1
+ ANTHROPIC_API_KEY=replace-me
2
+ ANTHROPIC_MODEL=replace-with-current-sonnet-model
@@ -12,7 +12,10 @@ npm run dev
12
12
  ```
13
13
  <!-- verify:end -->
14
14
 
15
- Add your OpenAI API key to `.env.local` before selecting **Generate video**.
15
+ Before selecting **Generate video**, add your Anthropic API key and replace the
16
+ model placeholder with a current Claude Sonnet model ID available to your
17
+ account. Provider and model selection happen here, after SDK installation, so
18
+ VanillaSky never silently chooses either one.
16
19
 
17
20
  Open <http://localhost:3000> and select **Generate video**.
18
21
 
@@ -8,10 +8,10 @@
8
8
  "start": "next start"
9
9
  },
10
10
  "dependencies": {
11
- "@ai-sdk/openai": "^4.0.42",
12
- "@vanillaskyai/video": "0.4.1",
13
- "ai": "^7.0.66",
14
- "next": "16.3.1",
11
+ "@ai-sdk/anthropic": "^4.0.41",
12
+ "@vanillaskyai/video": "0.5.0",
13
+ "ai": "^7.0.77",
14
+ "next": "16.3.2",
15
15
  "react": "19.2.8",
16
16
  "react-dom": "19.2.8"
17
17
  },
@@ -1,8 +1,10 @@
1
- import { openai } from "@ai-sdk/openai";
1
+ import { anthropic } from "@ai-sdk/anthropic";
2
2
  import { streamText } from "ai";
3
3
  import { createVideoHandler } from "@vanillaskyai/video/server";
4
4
 
5
- const model = openai(process.env.OPENAI_MODEL ?? "gpt-4.1");
5
+ const modelId = process.env.ANTHROPIC_MODEL;
6
+ if (!modelId) throw new Error("Set ANTHROPIC_MODEL in the server environment");
7
+ const model = anthropic(modelId);
6
8
 
7
9
  const handle = createVideoHandler({
8
10
  authorize: (request) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanillaskyai/video",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Open-source video response SDK for personalized AI applications.",
5
5
  "keywords": [
6
6
  "generative-video",
@@ -131,21 +131,21 @@
131
131
  }
132
132
  },
133
133
  "devDependencies": {
134
- "@anthropic-ai/sdk": "^0.116.0",
134
+ "@anthropic-ai/sdk": "^0.120.0",
135
135
  "@eslint/js": "^9.39.1",
136
136
  "@playwright/test": "1.62.0",
137
137
  "@testing-library/react": "^16.3.0",
138
138
  "@types/node": "^24.10.1",
139
- "@types/react": "^18.3.28",
140
- "@types/react-dom": "^18.3.7",
139
+ "@types/react": "^19.2.18",
140
+ "@types/react-dom": "^19.2.4",
141
141
  "es-module-lexer": "^1.7.0",
142
142
  "eslint": "^9.39.1",
143
143
  "globals": "^16.5.0",
144
144
  "jsdom": "^26.1.0",
145
145
  "mdast-util-from-markdown": "2.0.3",
146
- "openai": "^7.4.0",
147
- "react": "^18.3.1",
148
- "react-dom": "^18.3.1",
146
+ "openai": "^7.5.0",
147
+ "react": "^19.2.8",
148
+ "react-dom": "^19.2.8",
149
149
  "tsup": "^8.5.1",
150
150
  "tsx": "^4.23.12",
151
151
  "typescript": "^5.9.3",
@@ -156,7 +156,7 @@
156
156
  "esbuild": "^0.28.2"
157
157
  },
158
158
  "engines": {
159
- "node": ">=20"
159
+ "node": ">=22"
160
160
  },
161
161
  "packageManager": "npm@11.17.0",
162
162
  "publishConfig": {
@@ -1,109 +0,0 @@
1
- import {
2
- assertTemplateTransitionMetadata
3
- } from "./chunk-2E6T633S.js";
4
-
5
- // src/visual-system/catalog/kit.ts
6
- function toMetadata(template) {
7
- return {
8
- id: template.id,
9
- label: template.label,
10
- description: template.description,
11
- category: template.category,
12
- family: template.family,
13
- usesGlobalTextEffect: template.usesGlobalTextEffect,
14
- usesGlobalTransition: template.usesGlobalTransition,
15
- transitionTiming: template.transitionTiming,
16
- usesGlobalBackgroundEffect: template.usesGlobalBackgroundEffect,
17
- textCanvas: template.textCanvas,
18
- jobs: template.jobs,
19
- register: template.register,
20
- useWhen: template.useWhen,
21
- avoidWhen: template.avoidWhen,
22
- schema: template.schema,
23
- minDuration: template.minDuration,
24
- preferredDuration: template.preferredDuration,
25
- timing: template.timing
26
- };
27
- }
28
- function isTemplateJsonSchema(value) {
29
- if (typeof value !== "object" || value == null) return false;
30
- const schema = value;
31
- return schema.type === "object" && typeof schema.properties === "object" && schema.properties != null;
32
- }
33
- function defineTemplate(definition) {
34
- if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(definition.id)) {
35
- throw new Error(`Invalid template id: ${definition.id}`);
36
- }
37
- const suppliedSchema = "schema" in definition ? definition.schema : void 0;
38
- const standard = suppliedSchema && "~standard" in suppliedSchema ? suppliedSchema["~standard"] : void 0;
39
- const convertedSchema = standard?.jsonSchema ? standard.jsonSchema.input({ target: "draft-07" }) : suppliedSchema && !("~standard" in suppliedSchema) ? suppliedSchema : void 0;
40
- if (standard && !standard.jsonSchema) {
41
- throw new Error("Template schemas must expose Standard JSON Schema so the server registry can be generated safely");
42
- }
43
- if (!convertedSchema || !isTemplateJsonSchema(convertedSchema)) {
44
- throw new Error("Template schema must describe a JSON object");
45
- }
46
- const schema = { ...convertedSchema, additionalProperties: convertedSchema.additionalProperties ?? false };
47
- const transitionMetadata = {
48
- id: definition.id,
49
- usesGlobalTransition: definition.usesGlobalTransition ?? false,
50
- transitionTiming: definition.transitionTiming
51
- };
52
- assertTemplateTransitionMetadata(transitionMetadata);
53
- const { schema: _runtimeSchema, duration, ...definitionWithoutSchema } = definition;
54
- return Object.freeze({
55
- label: definition.id,
56
- description: "",
57
- usesGlobalTextEffect: false,
58
- usesGlobalTransition: false,
59
- usesGlobalBackgroundEffect: false,
60
- ...definitionWithoutSchema,
61
- schema,
62
- ...duration == null ? {} : { preferredDuration: duration }
63
- });
64
- }
65
- function createRenderTemplateRegistry(options) {
66
- const byId = /* @__PURE__ */ new Map();
67
- for (const template of options.templates) {
68
- assertTemplateTransitionMetadata(template);
69
- if (byId.has(template.id)) throw new Error(`Duplicate template id: ${template.id}`);
70
- byId.set(template.id, template);
71
- }
72
- const templates = Object.freeze([...options.templates]);
73
- if (options.metadata && options.metadata.map(({ id }) => id).join("\0") !== templates.map(({ id }) => id).join("\0")) {
74
- throw new Error("Template metadata does not match render templates");
75
- }
76
- const metadata = new Map((options.metadata ?? templates.map(toMetadata)).map((template) => [template.id, template]));
77
- const capabilities = { templates: templates.map(({ id }) => id) };
78
- return Object.freeze({
79
- templates,
80
- capabilities,
81
- getTemplate: (id) => byId.get(id),
82
- getTemplateMetadata: (id) => metadata.get(id),
83
- listTemplateMetadata: () => [...metadata.values()]
84
- });
85
- }
86
- function overlayTemplateRegistry(defaults, customer) {
87
- const customerTemplates = new Map(customer.templates.map((template) => [template.id, template]));
88
- const defaultIds = new Set(defaults.templates.map(({ id }) => id));
89
- const templates = [
90
- ...defaults.templates.map((template) => customerTemplates.get(template.id) ?? template),
91
- ...customer.templates.filter(({ id }) => !defaultIds.has(id))
92
- ];
93
- const customerMetadataList = customer.listTemplateMetadata();
94
- const customerMetadata = new Map(customerMetadataList.map((template) => [template.id, template]));
95
- const metadata = [
96
- ...defaults.listTemplateMetadata().map((template) => customerMetadata.get(template.id) ?? template),
97
- ...customerMetadataList.filter(({ id }) => !defaultIds.has(id))
98
- ];
99
- return createRenderTemplateRegistry({ templates, metadata });
100
- }
101
- function createTemplateRegistry(options) {
102
- return createRenderTemplateRegistry({ templates: options.definitions });
103
- }
104
-
105
- export {
106
- defineTemplate,
107
- overlayTemplateRegistry,
108
- createTemplateRegistry
109
- };
@@ -1,13 +0,0 @@
1
- import {
2
- createVideo
3
- } from "./chunk-LHFADNWJ.js";
4
- import "./chunk-E7CL7UPB.js";
5
- import "./chunk-STIFILQG.js";
6
- import "./chunk-JW47XCRL.js";
7
- import "./chunk-GHJEAP4O.js";
8
- import "./chunk-EE6PK6XC.js";
9
- import "./chunk-3O7OMMMF.js";
10
- import "./chunk-XGRA2MUV.js";
11
- export {
12
- createVideo
13
- };