@vibeframe/cli 0.105.1 → 0.106.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.
- package/dist/agent/adapters/claude.d.ts +14 -0
- package/dist/agent/adapters/gemini.d.ts +14 -0
- package/dist/agent/adapters/index.d.ts +27 -0
- package/dist/agent/adapters/ollama.d.ts +19 -0
- package/dist/agent/adapters/openai.d.ts +14 -0
- package/dist/agent/adapters/openrouter.d.ts +15 -0
- package/dist/agent/adapters/openrouter.test.d.ts +4 -0
- package/dist/agent/adapters/xai.d.ts +14 -0
- package/dist/agent/index.d.ts +109 -0
- package/dist/agent/memory/index.d.ts +69 -0
- package/dist/agent/prompts/system.d.ts +5 -0
- package/dist/agent/tools/e2e.test.d.ts +25 -0
- package/dist/agent/tools/index.d.ts +59 -0
- package/dist/agent/tools/integration.test.d.ts +10 -0
- package/dist/agent/tools/scene.test.d.ts +1 -0
- package/dist/agent/types.d.ts +72 -0
- package/dist/commands/_shared/build-asset-metadata.d.ts +43 -0
- package/dist/commands/_shared/build-asset-reference.d.ts +18 -0
- package/dist/commands/_shared/build-backdrop-prompt.d.ts +8 -0
- package/dist/commands/_shared/build-backdrop-prompt.test.d.ts +1 -0
- package/dist/commands/_shared/build-cache.d.ts +37 -0
- package/dist/commands/_shared/build-plan.d.ts +107 -0
- package/dist/commands/_shared/build-plan.test.d.ts +1 -0
- package/dist/commands/_shared/compose-prompts.d.ts +97 -0
- package/dist/commands/_shared/compose-prompts.test.d.ts +1 -0
- package/dist/commands/_shared/compose-scenes-skills.d.ts +282 -0
- package/dist/commands/_shared/compose-scenes-skills.test.d.ts +1 -0
- package/dist/commands/_shared/composer-resolve.d.ts +47 -0
- package/dist/commands/_shared/composer-resolve.test.d.ts +1 -0
- package/dist/commands/_shared/cost-tier.d.ts +58 -0
- package/dist/commands/_shared/edit/_helpers.d.ts +12 -0
- package/dist/commands/_shared/edit/caption.d.ts +47 -0
- package/dist/commands/_shared/edit/fade.d.ts +38 -0
- package/dist/commands/_shared/edit/jump-cut.d.ts +80 -0
- package/dist/commands/_shared/edit/noise-reduce.d.ts +33 -0
- package/dist/commands/_shared/edit/silence-cut.d.ts +63 -0
- package/dist/commands/_shared/edit/text-overlay.d.ts +50 -0
- package/dist/commands/_shared/edit/translate-srt.d.ts +40 -0
- package/dist/commands/_shared/edit/video-review.d.ts +62 -0
- package/dist/commands/_shared/execute-fill-gaps.d.ts +97 -0
- package/dist/commands/_shared/hf-skill-bundle/bundle-content.d.ts +16 -0
- package/dist/commands/_shared/hf-skill-bundle/bundle.d.ts +57 -0
- package/dist/commands/_shared/hf-skill-bundle/bundle.test.d.ts +1 -0
- package/dist/commands/_shared/init-templates.d.ts +58 -0
- package/dist/commands/_shared/init-templates.test.d.ts +1 -0
- package/dist/commands/_shared/install-skill.d.ts +76 -0
- package/dist/commands/_shared/install-skill.test.d.ts +1 -0
- package/dist/commands/_shared/openai-image.d.ts +49 -0
- package/dist/commands/_shared/openai-image.test.d.ts +1 -0
- package/dist/commands/_shared/product-surface.d.ts +11 -0
- package/dist/commands/_shared/product-surface.test.d.ts +1 -0
- package/dist/commands/_shared/project-config.d.ts +60 -0
- package/dist/commands/_shared/render-inspect.d.ts +104 -0
- package/dist/commands/_shared/render-inspect.test.d.ts +1 -0
- package/dist/commands/_shared/review-report.d.ts +65 -0
- package/dist/commands/_shared/root-sync.d.ts +39 -0
- package/dist/commands/_shared/scene-audio-mux.d.ts +74 -0
- package/dist/commands/_shared/scene-audio-mux.test.d.ts +6 -0
- package/dist/commands/_shared/scene-audio-scan.d.ts +93 -0
- package/dist/commands/_shared/scene-audio-scan.test.d.ts +5 -0
- package/dist/commands/_shared/scene-build-mode.d.ts +4 -0
- package/dist/commands/_shared/scene-build-mode.test.d.ts +1 -0
- package/dist/commands/_shared/scene-build.d.ts +452 -0
- package/dist/commands/_shared/scene-build.test.d.ts +1 -0
- package/dist/commands/_shared/scene-html-emit.d.ts +163 -0
- package/dist/commands/_shared/scene-html-emit.test.d.ts +1 -0
- package/dist/commands/_shared/scene-inspect.d.ts +56 -0
- package/dist/commands/_shared/scene-inspect.test.d.ts +1 -0
- package/dist/commands/_shared/scene-lint.d.ts +109 -0
- package/dist/commands/_shared/scene-lint.test.d.ts +1 -0
- package/dist/commands/_shared/scene-project.d.ts +147 -0
- package/dist/commands/_shared/scene-project.test.d.ts +1 -0
- package/dist/commands/_shared/scene-render.d.ts +109 -0
- package/dist/commands/_shared/scene-render.test.d.ts +1 -0
- package/dist/commands/_shared/scene-repair.d.ts +22 -0
- package/dist/commands/_shared/scene-repair.test.d.ts +1 -0
- package/dist/commands/_shared/status-jobs.d.ts +197 -0
- package/dist/commands/_shared/status-jobs.test.d.ts +1 -0
- package/dist/commands/_shared/storyboard-draft.d.ts +13 -0
- package/dist/commands/_shared/storyboard-draft.test.d.ts +1 -0
- package/dist/commands/_shared/storyboard-edit.d.ts +26 -0
- package/dist/commands/_shared/storyboard-edit.test.d.ts +1 -0
- package/dist/commands/_shared/storyboard-parse.d.ts +159 -0
- package/dist/commands/_shared/storyboard-parse.test.d.ts +1 -0
- package/dist/commands/_shared/storyboard-revise.d.ts +32 -0
- package/dist/commands/_shared/storyboard-revise.test.d.ts +1 -0
- package/dist/commands/_shared/timeline-project.d.ts +32 -0
- package/dist/commands/_shared/tts-resolve.d.ts +75 -0
- package/dist/commands/_shared/tts-resolve.test.d.ts +5 -0
- package/dist/commands/_shared/video-providers.d.ts +44 -0
- package/dist/commands/_shared/video-utils.d.ts +71 -0
- package/dist/commands/_shared/visual-styles.d.ts +55 -0
- package/dist/commands/_shared/visual-styles.test.d.ts +1 -0
- package/dist/commands/_shared/walkthroughs/walkthroughs.d.ts +47 -0
- package/dist/commands/_shared/walkthroughs/walkthroughs.test.d.ts +1 -0
- package/dist/commands/agent.d.ts +24 -0
- package/dist/commands/ai-analyze.d.ts +105 -0
- package/dist/commands/ai-animated-caption.d.ts +63 -0
- package/dist/commands/ai-audio.d.ts +92 -0
- package/dist/commands/ai-edit-cli.d.ts +13 -0
- package/dist/commands/ai-edit.d.ts +29 -0
- package/dist/commands/ai-fill-gaps.d.ts +15 -0
- package/dist/commands/ai-helpers.d.ts +26 -0
- package/dist/commands/ai-highlights.d.ts +126 -0
- package/dist/commands/ai-image.d.ts +71 -0
- package/dist/commands/ai-motion.d.ts +53 -0
- package/dist/commands/ai-review.d.ts +58 -0
- package/dist/commands/ai-script-pipeline-cli.d.ts +10 -0
- package/dist/commands/ai-script-pipeline.d.ts +74 -0
- package/dist/commands/ai-suggest-edit.d.ts +32 -0
- package/dist/commands/ai-video.d.ts +95 -0
- package/dist/commands/ai.test.d.ts +1 -0
- package/dist/commands/audio.d.ts +17 -0
- package/dist/commands/batch.d.ts +2 -0
- package/dist/commands/batch.test.d.ts +1 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/completion.d.ts +20 -0
- package/dist/commands/completion.test.d.ts +1 -0
- package/dist/commands/context.d.ts +7 -0
- package/dist/commands/context.test.d.ts +1 -0
- package/dist/commands/demo.d.ts +6 -0
- package/dist/commands/detect.d.ts +55 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.test.d.ts +1 -0
- package/dist/commands/edit/motion-overlay.d.ts +30 -0
- package/dist/commands/edit-cmd.d.ts +112 -0
- package/dist/commands/envelope-snapshots.test.d.ts +32 -0
- package/dist/commands/export.d.ts +60 -0
- package/dist/commands/export.test.d.ts +1 -0
- package/dist/commands/generate/background.d.ts +22 -0
- package/dist/commands/generate/image.d.ts +8 -0
- package/dist/commands/generate/music-status.d.ts +20 -0
- package/dist/commands/generate/music.d.ts +27 -0
- package/dist/commands/generate/sound-effect.d.ts +19 -0
- package/dist/commands/generate/speech.d.ts +21 -0
- package/dist/commands/generate/storyboard.d.ts +27 -0
- package/dist/commands/generate/thumbnail.d.ts +8 -0
- package/dist/commands/generate/video-cancel.d.ts +8 -0
- package/dist/commands/generate/video-extend.d.ts +8 -0
- package/dist/commands/generate/video-status.d.ts +8 -0
- package/dist/commands/generate/video.d.ts +8 -0
- package/dist/commands/generate.d.ts +36 -0
- package/dist/commands/init.d.ts +24 -0
- package/dist/commands/init.test.d.ts +1 -0
- package/dist/commands/inspect.d.ts +20 -0
- package/dist/commands/media.d.ts +2 -0
- package/dist/commands/output.d.ts +80 -0
- package/dist/commands/output.test.d.ts +1 -0
- package/dist/commands/plan.d.ts +2 -0
- package/dist/commands/project.d.ts +2 -0
- package/dist/commands/project.test.d.ts +1 -0
- package/dist/commands/provider-config-cli.test.d.ts +1 -0
- package/dist/commands/q-flag-collision.test.d.ts +1 -0
- package/dist/commands/remix.d.ts +20 -0
- package/dist/commands/render.d.ts +2 -0
- package/dist/commands/run.d.ts +14 -0
- package/dist/commands/sanitize.d.ts +20 -0
- package/dist/commands/scene.d.ts +95 -0
- package/dist/commands/scene.test.d.ts +1 -0
- package/dist/commands/schema.d.ts +12 -0
- package/dist/commands/setup.d.ts +5 -0
- package/dist/commands/setup.test.d.ts +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/storyboard.d.ts +2 -0
- package/dist/commands/timeline.d.ts +2 -0
- package/dist/commands/timeline.test.d.ts +1 -0
- package/dist/commands/validate.d.ts +33 -0
- package/dist/commands/walkthrough.d.ts +21 -0
- package/dist/config/config.test.d.ts +1 -0
- package/dist/config/index.d.ts +110 -0
- package/dist/config/schema.d.ts +64 -0
- package/dist/config/scope.test.d.ts +1 -0
- package/dist/engine/index.d.ts +2 -0
- package/dist/engine/index.js +345 -0
- package/dist/engine/project.d.ts +93 -0
- package/dist/engine/project.test.d.ts +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +500 -330
- package/dist/pipeline/executor.d.ts +27 -0
- package/dist/pipeline/generate-actions.test.d.ts +1 -0
- package/dist/pipeline/index.d.ts +3 -0
- package/dist/pipeline/renderers/__tests__/html-template.test.d.ts +1 -0
- package/dist/pipeline/renderers/__tests__/integration.test.d.ts +1 -0
- package/dist/pipeline/renderers/chrome.d.ts +25 -0
- package/dist/pipeline/renderers/html-clips.d.ts +19 -0
- package/dist/pipeline/renderers/html-runtime.d.ts +6 -0
- package/dist/pipeline/renderers/html-template.d.ts +2 -0
- package/dist/pipeline/renderers/hyperframes.d.ts +7 -0
- package/dist/pipeline/renderers/project-builder.d.ts +7 -0
- package/dist/pipeline/renderers/types.d.ts +39 -0
- package/dist/pipeline/resolver.d.ts +19 -0
- package/dist/pipeline/scene-actions.test.d.ts +1 -0
- package/dist/pipeline/types.d.ts +81 -0
- package/dist/tools/adapters/agent.d.ts +9 -0
- package/dist/tools/adapters/agent.js +188 -0
- package/dist/tools/adapters/mcp.d.ts +34 -0
- package/dist/tools/adapters/mcp.js +173 -0
- package/dist/tools/define-tool.d.ts +82 -0
- package/dist/tools/define-tool.js +214 -0
- package/dist/tools/manifest/_project-io.d.ts +13 -0
- package/dist/tools/manifest/agent-only.d.ts +236 -0
- package/dist/tools/manifest/audio.d.ts +93 -0
- package/dist/tools/manifest/detect.d.ts +47 -0
- package/dist/tools/manifest/edit.d.ts +398 -0
- package/dist/tools/manifest/export.d.ts +27 -0
- package/dist/tools/manifest/generate.d.ts +310 -0
- package/dist/tools/manifest/index.d.ts +22 -0
- package/dist/tools/manifest/index.js +60812 -0
- package/dist/tools/manifest/inspect.d.ts +139 -0
- package/dist/tools/manifest/project.d.ts +33 -0
- package/dist/tools/manifest/remix.d.ts +154 -0
- package/dist/tools/manifest/scene.d.ts +221 -0
- package/dist/tools/manifest/status.d.ts +36 -0
- package/dist/tools/manifest/storyboard.d.ts +136 -0
- package/dist/tools/manifest/timeline.d.ts +173 -0
- package/dist/tools/manifest/walkthrough.d.ts +22 -0
- package/dist/tools/manifest.test.d.ts +13 -0
- package/dist/tools/zod-to-json-schema.d.ts +47 -0
- package/dist/utils/agent-host-detect.d.ts +61 -0
- package/dist/utils/agent-host-detect.test.d.ts +1 -0
- package/dist/utils/api-key.d.ts +58 -0
- package/dist/utils/api-key.test.d.ts +1 -0
- package/dist/utils/audio.d.ts +22 -0
- package/dist/utils/clipboard.d.ts +27 -0
- package/dist/utils/clipboard.test.d.ts +1 -0
- package/dist/utils/exec-safe.d.ts +21 -0
- package/dist/utils/first-run.d.ts +16 -0
- package/dist/utils/input-validation.d.ts +26 -0
- package/dist/utils/key-format.d.ts +15 -0
- package/dist/utils/key-live-test.d.ts +29 -0
- package/dist/utils/key-live-test.test.d.ts +1 -0
- package/dist/utils/open-url.d.ts +26 -0
- package/dist/utils/open-url.test.d.ts +1 -0
- package/dist/utils/project-resolver.d.ts +30 -0
- package/dist/utils/project-resolver.test.d.ts +8 -0
- package/dist/utils/provider-resolver.d.ts +32 -0
- package/dist/utils/provider-resolver.test.d.ts +13 -0
- package/dist/utils/remotion.d.ts +201 -0
- package/dist/utils/subtitle.d.ts +64 -0
- package/dist/utils/subtitle.test.d.ts +1 -0
- package/dist/utils/tty.d.ts +86 -0
- package/dist/utils/tty.test.d.ts +1 -0
- package/dist/utils/upload-host.d.ts +15 -0
- package/dist/utils/upload-host.test.d.ts +1 -0
- package/package.json +15 -115
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module validate
|
|
3
|
+
* @description Input validation layer for CLI commands.
|
|
4
|
+
* Guards against path traversal, control characters, and invalid resource IDs.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Validate and resolve an output path.
|
|
8
|
+
* Prevents path traversal attacks (e.g., --output ../../etc/passwd).
|
|
9
|
+
* Absolute paths are allowed (explicit user intent), but relative paths
|
|
10
|
+
* containing ".." that escape the working directory are blocked.
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateOutputPath(path: string, cwd?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Validate a resource ID (source-*, clip-*, track-*, effect-*).
|
|
15
|
+
* Only allows alphanumeric characters, hyphens, and underscores.
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateResourceId(id: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Reject strings containing control characters (U+0000–U+001F, U+007F–U+009F).
|
|
20
|
+
* Prevents terminal injection and other control-char exploits.
|
|
21
|
+
*/
|
|
22
|
+
export declare function rejectControlChars(input: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Validate a media file path and check its extension against an allowlist.
|
|
25
|
+
*/
|
|
26
|
+
export declare function validateMediaFile(path: string, allowedExts: string[]): string;
|
|
27
|
+
/** Common media file extensions */
|
|
28
|
+
export declare const MEDIA_EXTS: {
|
|
29
|
+
video: string[];
|
|
30
|
+
audio: string[];
|
|
31
|
+
image: string[];
|
|
32
|
+
subtitle: string[];
|
|
33
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module commands/walkthrough
|
|
3
|
+
*
|
|
4
|
+
* `vibe guide [topic]` — universal CLI equivalent of Claude Code's
|
|
5
|
+
* `/vibe-scene` and `/vibe-pipeline` slash commands. Any host agent
|
|
6
|
+
* (Claude Code, Codex, Cursor, Aider, Gemini CLI, OpenCode) can invoke
|
|
7
|
+
* this to load the same step-by-step authoring guide the slash commands
|
|
8
|
+
* deliver in Claude Code — closes the last Claude-Code-only gap on top
|
|
9
|
+
* of Plan H's universal skill / compose primitives.
|
|
10
|
+
*
|
|
11
|
+
* Without arguments, lists available topics. With a topic, emits the
|
|
12
|
+
* full markdown body + structured metadata. `--json` returns the
|
|
13
|
+
* structured shape from `loadWalkthrough()` directly.
|
|
14
|
+
*
|
|
15
|
+
* The old `vibe walkthrough` spelling is registered as a hidden deprecated
|
|
16
|
+
* compatibility command from `index.ts`, but all public help/docs should point
|
|
17
|
+
* users at `vibe guide`.
|
|
18
|
+
*/
|
|
19
|
+
import { Command } from "commander";
|
|
20
|
+
export declare const guideCommand: Command;
|
|
21
|
+
export declare const legacyGuideAliasCommand: Command;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader/saver for VibeFrame CLI.
|
|
3
|
+
*
|
|
4
|
+
* Two scopes:
|
|
5
|
+
* - user ~/.vibeframe/config.yaml (shared across projects)
|
|
6
|
+
* - project <cwd>/.vibeframe/config.yaml (gitignored, per-project)
|
|
7
|
+
*
|
|
8
|
+
* Precedence at runtime: process.env > project > user.
|
|
9
|
+
*
|
|
10
|
+
* Default `loadConfig()` behavior is "auto" — if a project config exists in
|
|
11
|
+
* the current working directory or one of its parents, it is used and the user
|
|
12
|
+
* config is ignored.
|
|
13
|
+
* Pass `{scope:"user"}` or `{scope:"project"}` to force one side.
|
|
14
|
+
*
|
|
15
|
+
* Pass `{merge:true}` to overlay project on user (project wins). Used by
|
|
16
|
+
* doctor to render "where did this key come from" diagnostics.
|
|
17
|
+
*/
|
|
18
|
+
import { type VibeConfig } from "./schema.js";
|
|
19
|
+
export type Scope = "user" | "project";
|
|
20
|
+
/** User-scope config directory (~/.vibeframe by default). */
|
|
21
|
+
export declare const USER_CONFIG_DIR: string;
|
|
22
|
+
/** User-scope config file (~/.vibeframe/config.yaml by default). */
|
|
23
|
+
export declare const USER_CONFIG_PATH: string;
|
|
24
|
+
/** User data directory (~/.local/share/vibeframe by default). */
|
|
25
|
+
export declare const USER_DATA_DIR: string;
|
|
26
|
+
/** User cache directory (~/.vibeframe/cache by default). */
|
|
27
|
+
export declare const USER_CACHE_DIR: string;
|
|
28
|
+
/** Legacy user-scope config directory used by pre-XDG installs. */
|
|
29
|
+
export declare const LEGACY_USER_CONFIG_DIR: string;
|
|
30
|
+
/** Legacy user-scope config file used by pre-XDG installs. */
|
|
31
|
+
export declare const LEGACY_USER_CONFIG_PATH: string;
|
|
32
|
+
/**
|
|
33
|
+
* Back-compat aliases. New code should use `USER_CONFIG_PATH` /
|
|
34
|
+
* `USER_CONFIG_DIR` or `getConfigPath(scope)` to be scope-explicit.
|
|
35
|
+
*/
|
|
36
|
+
export declare const CONFIG_DIR: string;
|
|
37
|
+
export declare const CONFIG_PATH: string;
|
|
38
|
+
export declare class ConfigFileError extends Error {
|
|
39
|
+
readonly path: string;
|
|
40
|
+
constructor(path: string, cause: unknown);
|
|
41
|
+
}
|
|
42
|
+
/** Project-scope config directory (`<cwd>/.vibeframe`). */
|
|
43
|
+
export declare function getProjectConfigDir(cwd?: string): string;
|
|
44
|
+
/** Project-scope config file (`<cwd>/.vibeframe/config.yaml`). */
|
|
45
|
+
export declare function getProjectConfigPath(cwd?: string): string;
|
|
46
|
+
/** Resolve config file path for a given scope. */
|
|
47
|
+
export declare function getConfigPath(scope: Scope, cwd?: string): string;
|
|
48
|
+
/** Resolve config directory for a given scope. */
|
|
49
|
+
export declare function getConfigDir(scope: Scope, cwd?: string): string;
|
|
50
|
+
export interface UserConfigStatus {
|
|
51
|
+
/** True when either the primary config file or legacy ~/.vibeframe/config.yaml exists. */
|
|
52
|
+
configured: boolean;
|
|
53
|
+
/** Path loadConfig({scope:"user"}) will read from, or the write path when absent. */
|
|
54
|
+
configPath: string;
|
|
55
|
+
/** Write target for new user-scope saves. */
|
|
56
|
+
writePath: string;
|
|
57
|
+
/** Legacy fallback path. */
|
|
58
|
+
legacyConfigPath: string;
|
|
59
|
+
/** True when the primary write target exists. */
|
|
60
|
+
primaryConfigured: boolean;
|
|
61
|
+
/** True when the legacy fallback exists. */
|
|
62
|
+
legacyConfigured: boolean;
|
|
63
|
+
/** Source currently used for user-scope reads. */
|
|
64
|
+
source: "user" | "legacy" | null;
|
|
65
|
+
}
|
|
66
|
+
export declare function getUserConfigStatus(): Promise<UserConfigStatus>;
|
|
67
|
+
export declare function findProjectConfigPath(cwd?: string): Promise<string | null>;
|
|
68
|
+
/**
|
|
69
|
+
* The scope that `loadConfig()` will read from when called without an
|
|
70
|
+
* explicit scope. Returns `"project"` if a project config exists at cwd or an
|
|
71
|
+
* ancestor directory, else `"user"` (regardless of whether the user file exists).
|
|
72
|
+
*/
|
|
73
|
+
export declare function getActiveScope(cwd?: string): Promise<Scope>;
|
|
74
|
+
export interface LoadConfigOptions {
|
|
75
|
+
/** Force a specific scope. Default: auto (project if exists, else user). */
|
|
76
|
+
scope?: Scope;
|
|
77
|
+
/** Working directory for resolving the project scope. Default: process.cwd(). */
|
|
78
|
+
cwd?: string;
|
|
79
|
+
/** Overlay project on user (project wins). Useful for doctor diagnostics. */
|
|
80
|
+
merge?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Load configuration. Returns null if no config exists at the resolved scope.
|
|
84
|
+
*/
|
|
85
|
+
export declare function loadConfig(options?: LoadConfigOptions): Promise<VibeConfig | null>;
|
|
86
|
+
export interface SaveConfigOptions {
|
|
87
|
+
/** Target scope. Default: "user" (back-compat with prior behavior). */
|
|
88
|
+
scope?: Scope;
|
|
89
|
+
/** Working directory for resolving the project scope. Default: process.cwd(). */
|
|
90
|
+
cwd?: string;
|
|
91
|
+
}
|
|
92
|
+
/** Save configuration to the chosen scope. Default scope is "user". */
|
|
93
|
+
export declare function saveConfig(config: VibeConfig, options?: SaveConfigOptions): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Check if any configuration is present and the primary LLM provider has a
|
|
96
|
+
* key (in the active scope or the environment).
|
|
97
|
+
*/
|
|
98
|
+
export declare function isConfigured(options?: Pick<LoadConfigOptions, "cwd">): Promise<boolean>;
|
|
99
|
+
/**
|
|
100
|
+
* Get an API key. Auto-detects scope (project > user) and falls through to
|
|
101
|
+
* the provider's environment variable if neither config has it.
|
|
102
|
+
*/
|
|
103
|
+
export declare function getApiKeyFromConfig(providerKey: string, options?: Pick<LoadConfigOptions, "cwd">): Promise<string | undefined>;
|
|
104
|
+
/**
|
|
105
|
+
* Update a provider key in the active scope (project if present, else user).
|
|
106
|
+
* Pass `{scope}` to force a specific destination.
|
|
107
|
+
*/
|
|
108
|
+
export declare function updateProviderKey(providerKey: string, apiKey: string, options?: SaveConfigOptions): Promise<void>;
|
|
109
|
+
export type { VibeConfig, LLMProvider } from "./schema.js";
|
|
110
|
+
export { createDefaultConfig, PROVIDER_NAMES, PROVIDER_ENV_ALIASES, PROVIDER_ENV_VARS, } from "./schema.js";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration schema for VibeFrame CLI
|
|
3
|
+
* Stored at ~/.vibeframe/config.yaml by default.
|
|
4
|
+
*/
|
|
5
|
+
export type LLMProvider = "claude" | "openai" | "gemini" | "ollama" | "xai" | "openrouter";
|
|
6
|
+
export interface VibeConfig {
|
|
7
|
+
/** Config file version */
|
|
8
|
+
version: string;
|
|
9
|
+
/** LLM provider settings */
|
|
10
|
+
llm: {
|
|
11
|
+
/** Primary LLM provider for AI commands */
|
|
12
|
+
provider: LLMProvider;
|
|
13
|
+
};
|
|
14
|
+
/** API keys for various providers */
|
|
15
|
+
providers: {
|
|
16
|
+
anthropic?: string;
|
|
17
|
+
openai?: string;
|
|
18
|
+
google?: string;
|
|
19
|
+
elevenlabs?: string;
|
|
20
|
+
runway?: string;
|
|
21
|
+
kling?: string;
|
|
22
|
+
fal?: string;
|
|
23
|
+
imgbb?: string;
|
|
24
|
+
replicate?: string;
|
|
25
|
+
xai?: string;
|
|
26
|
+
openrouter?: string;
|
|
27
|
+
};
|
|
28
|
+
/** Default settings for new projects */
|
|
29
|
+
defaults: {
|
|
30
|
+
aspectRatio: "16:9" | "9:16" | "1:1" | "4:5";
|
|
31
|
+
exportQuality: "draft" | "standard" | "high" | "ultra";
|
|
32
|
+
/** Default provider for image generation */
|
|
33
|
+
imageProvider?: "gemini" | "openai" | "grok";
|
|
34
|
+
/** Default provider for video generation. `fal` is a deprecated v0.x alias for `seedance` and will be removed at 1.0. */
|
|
35
|
+
videoProvider?: "seedance" | "fal" | "grok" | "kling" | "runway" | "veo";
|
|
36
|
+
/** Default provider for storyboard analysis */
|
|
37
|
+
storyboardProvider?: "claude" | "openai" | "gemini";
|
|
38
|
+
/** Default voice for TTS */
|
|
39
|
+
voice?: string;
|
|
40
|
+
};
|
|
41
|
+
/** Temporary upload host for providers that require HTTPS image URLs */
|
|
42
|
+
upload: {
|
|
43
|
+
provider: "imgbb" | "s3";
|
|
44
|
+
ttlSeconds: number;
|
|
45
|
+
s3?: {
|
|
46
|
+
bucket?: string;
|
|
47
|
+
region?: string;
|
|
48
|
+
prefix?: string;
|
|
49
|
+
endpoint?: string;
|
|
50
|
+
publicBaseUrl?: string;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
/** REPL settings */
|
|
54
|
+
repl: {
|
|
55
|
+
/** Auto-save project after each command */
|
|
56
|
+
autoSave: boolean;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Provider display names */
|
|
60
|
+
export declare const PROVIDER_NAMES: Record<LLMProvider, string>;
|
|
61
|
+
export declare const PROVIDER_ENV_VARS: Record<string, string>;
|
|
62
|
+
export declare const PROVIDER_ENV_ALIASES: Record<string, readonly string[]>;
|
|
63
|
+
/** Default configuration */
|
|
64
|
+
export declare function createDefaultConfig(): VibeConfig;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { createRequire as __vfCreateRequire } from 'node:module';
|
|
2
|
+
const require = __vfCreateRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/engine/project.ts
|
|
5
|
+
var generateId = () => {
|
|
6
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
7
|
+
};
|
|
8
|
+
function createDefaultState(name = "Untitled Project") {
|
|
9
|
+
return {
|
|
10
|
+
project: {
|
|
11
|
+
id: generateId(),
|
|
12
|
+
name,
|
|
13
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
14
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
15
|
+
aspectRatio: "16:9",
|
|
16
|
+
frameRate: 30,
|
|
17
|
+
duration: 0
|
|
18
|
+
},
|
|
19
|
+
tracks: [
|
|
20
|
+
{
|
|
21
|
+
id: "video-track-1",
|
|
22
|
+
name: "Video 1",
|
|
23
|
+
type: "video",
|
|
24
|
+
order: 1,
|
|
25
|
+
isMuted: false,
|
|
26
|
+
isLocked: false,
|
|
27
|
+
isVisible: true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "audio-track-1",
|
|
31
|
+
name: "Audio 1",
|
|
32
|
+
type: "audio",
|
|
33
|
+
order: 0,
|
|
34
|
+
isMuted: false,
|
|
35
|
+
isLocked: false,
|
|
36
|
+
isVisible: true
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
clips: [],
|
|
40
|
+
sources: [],
|
|
41
|
+
transitions: [],
|
|
42
|
+
currentTime: 0,
|
|
43
|
+
isPlaying: false,
|
|
44
|
+
zoom: 50,
|
|
45
|
+
scrollX: 0,
|
|
46
|
+
selectedClipIds: [],
|
|
47
|
+
selectedTrackId: null
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var Project = class _Project {
|
|
51
|
+
state;
|
|
52
|
+
filePath = null;
|
|
53
|
+
constructor(name) {
|
|
54
|
+
this.state = createDefaultState(name);
|
|
55
|
+
}
|
|
56
|
+
/** Get current state (immutable copy) */
|
|
57
|
+
getState() {
|
|
58
|
+
return structuredClone(this.state);
|
|
59
|
+
}
|
|
60
|
+
/** Get project metadata */
|
|
61
|
+
getMeta() {
|
|
62
|
+
return { ...this.state.project };
|
|
63
|
+
}
|
|
64
|
+
/** Get file path */
|
|
65
|
+
getFilePath() {
|
|
66
|
+
return this.filePath;
|
|
67
|
+
}
|
|
68
|
+
// ============ Project Operations ============
|
|
69
|
+
setName(name) {
|
|
70
|
+
this.state.project.name = name;
|
|
71
|
+
this.state.project.updatedAt = /* @__PURE__ */ new Date();
|
|
72
|
+
}
|
|
73
|
+
setAspectRatio(ratio) {
|
|
74
|
+
this.state.project.aspectRatio = ratio;
|
|
75
|
+
this.state.project.updatedAt = /* @__PURE__ */ new Date();
|
|
76
|
+
}
|
|
77
|
+
setFrameRate(fps) {
|
|
78
|
+
this.state.project.frameRate = fps;
|
|
79
|
+
this.state.project.updatedAt = /* @__PURE__ */ new Date();
|
|
80
|
+
}
|
|
81
|
+
// ============ Media Source Operations ============
|
|
82
|
+
addSource(source) {
|
|
83
|
+
const newSource = { ...source, id: generateId() };
|
|
84
|
+
this.state.sources.push(newSource);
|
|
85
|
+
return newSource;
|
|
86
|
+
}
|
|
87
|
+
removeSource(id) {
|
|
88
|
+
const index = this.state.sources.findIndex((s) => s.id === id);
|
|
89
|
+
if (index === -1) return false;
|
|
90
|
+
this.state.sources.splice(index, 1);
|
|
91
|
+
this.state.clips = this.state.clips.filter((c) => c.sourceId !== id);
|
|
92
|
+
this.calculateDuration();
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
getSource(id) {
|
|
96
|
+
return this.state.sources.find((s) => s.id === id);
|
|
97
|
+
}
|
|
98
|
+
getSources() {
|
|
99
|
+
return [...this.state.sources];
|
|
100
|
+
}
|
|
101
|
+
// ============ Track Operations ============
|
|
102
|
+
addTrack(track) {
|
|
103
|
+
const newTrack = { ...track, id: generateId() };
|
|
104
|
+
this.state.tracks.push(newTrack);
|
|
105
|
+
return newTrack;
|
|
106
|
+
}
|
|
107
|
+
removeTrack(id) {
|
|
108
|
+
const index = this.state.tracks.findIndex((t) => t.id === id);
|
|
109
|
+
if (index === -1) return false;
|
|
110
|
+
this.state.tracks.splice(index, 1);
|
|
111
|
+
this.state.clips = this.state.clips.filter((c) => c.trackId !== id);
|
|
112
|
+
this.calculateDuration();
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
updateTrack(id, updates) {
|
|
116
|
+
const track = this.state.tracks.find((t) => t.id === id);
|
|
117
|
+
if (!track) return false;
|
|
118
|
+
Object.assign(track, updates);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
getTrack(id) {
|
|
122
|
+
return this.state.tracks.find((t) => t.id === id);
|
|
123
|
+
}
|
|
124
|
+
getTracks() {
|
|
125
|
+
return [...this.state.tracks];
|
|
126
|
+
}
|
|
127
|
+
getTracksByType(type) {
|
|
128
|
+
return this.state.tracks.filter((t) => t.type === type);
|
|
129
|
+
}
|
|
130
|
+
// ============ Clip Operations ============
|
|
131
|
+
addClip(clip) {
|
|
132
|
+
const newClip = {
|
|
133
|
+
...clip,
|
|
134
|
+
id: generateId(),
|
|
135
|
+
effects: []
|
|
136
|
+
};
|
|
137
|
+
this.state.clips.push(newClip);
|
|
138
|
+
this.calculateDuration();
|
|
139
|
+
return newClip;
|
|
140
|
+
}
|
|
141
|
+
removeClip(id) {
|
|
142
|
+
const index = this.state.clips.findIndex((c) => c.id === id);
|
|
143
|
+
if (index === -1) return false;
|
|
144
|
+
this.state.clips.splice(index, 1);
|
|
145
|
+
this.state.selectedClipIds = this.state.selectedClipIds.filter((cid) => cid !== id);
|
|
146
|
+
this.calculateDuration();
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
updateClip(id, updates) {
|
|
150
|
+
const clip = this.state.clips.find((c) => c.id === id);
|
|
151
|
+
if (!clip) return false;
|
|
152
|
+
Object.assign(clip, updates);
|
|
153
|
+
this.calculateDuration();
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
moveClip(id, trackId, startTime) {
|
|
157
|
+
const clip = this.state.clips.find((c) => c.id === id);
|
|
158
|
+
if (!clip) return false;
|
|
159
|
+
clip.trackId = trackId;
|
|
160
|
+
clip.startTime = Math.max(0, startTime);
|
|
161
|
+
this.calculateDuration();
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
trimClipStart(id, newStartTime) {
|
|
165
|
+
const clip = this.state.clips.find((c) => c.id === id);
|
|
166
|
+
if (!clip) return false;
|
|
167
|
+
const delta = newStartTime - clip.startTime;
|
|
168
|
+
clip.startTime = newStartTime;
|
|
169
|
+
clip.sourceStartOffset += delta;
|
|
170
|
+
clip.duration -= delta;
|
|
171
|
+
this.calculateDuration();
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
trimClipEnd(id, newDuration) {
|
|
175
|
+
const clip = this.state.clips.find((c) => c.id === id);
|
|
176
|
+
if (!clip) return false;
|
|
177
|
+
clip.duration = Math.max(0.1, newDuration);
|
|
178
|
+
clip.sourceEndOffset = clip.sourceStartOffset + clip.duration;
|
|
179
|
+
this.calculateDuration();
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
getClip(id) {
|
|
183
|
+
return this.state.clips.find((c) => c.id === id);
|
|
184
|
+
}
|
|
185
|
+
getClips() {
|
|
186
|
+
return [...this.state.clips];
|
|
187
|
+
}
|
|
188
|
+
getClipsByTrack(trackId) {
|
|
189
|
+
return this.state.clips.filter((c) => c.trackId === trackId);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Split a clip at a specific time, creating two clips
|
|
193
|
+
* @param id Clip ID to split
|
|
194
|
+
* @param splitTime Time relative to clip start (not timeline time)
|
|
195
|
+
* @returns [firstClip, secondClip] or null if failed
|
|
196
|
+
*/
|
|
197
|
+
splitClip(id, splitTime) {
|
|
198
|
+
const clip = this.state.clips.find((c) => c.id === id);
|
|
199
|
+
if (!clip) return null;
|
|
200
|
+
if (splitTime <= 0 || splitTime >= clip.duration) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
const secondClip = {
|
|
204
|
+
id: generateId(),
|
|
205
|
+
sourceId: clip.sourceId,
|
|
206
|
+
trackId: clip.trackId,
|
|
207
|
+
startTime: clip.startTime + splitTime,
|
|
208
|
+
duration: clip.duration - splitTime,
|
|
209
|
+
sourceStartOffset: clip.sourceStartOffset + splitTime,
|
|
210
|
+
sourceEndOffset: clip.sourceEndOffset,
|
|
211
|
+
effects: []
|
|
212
|
+
// Effects don't transfer to split clips
|
|
213
|
+
};
|
|
214
|
+
clip.duration = splitTime;
|
|
215
|
+
clip.sourceEndOffset = clip.sourceStartOffset + splitTime;
|
|
216
|
+
this.state.clips.push(secondClip);
|
|
217
|
+
this.calculateDuration();
|
|
218
|
+
return [clip, secondClip];
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Duplicate a clip
|
|
222
|
+
* @param id Clip ID to duplicate
|
|
223
|
+
* @param offsetTime Optional time offset for the duplicate (default: place after original)
|
|
224
|
+
* @returns The duplicated clip or null if failed
|
|
225
|
+
*/
|
|
226
|
+
duplicateClip(id, offsetTime) {
|
|
227
|
+
const clip = this.state.clips.find((c) => c.id === id);
|
|
228
|
+
if (!clip) return null;
|
|
229
|
+
const newStartTime = offsetTime ?? clip.startTime + clip.duration;
|
|
230
|
+
const duplicatedClip = {
|
|
231
|
+
id: generateId(),
|
|
232
|
+
sourceId: clip.sourceId,
|
|
233
|
+
trackId: clip.trackId,
|
|
234
|
+
startTime: newStartTime,
|
|
235
|
+
duration: clip.duration,
|
|
236
|
+
sourceStartOffset: clip.sourceStartOffset,
|
|
237
|
+
sourceEndOffset: clip.sourceEndOffset,
|
|
238
|
+
effects: clip.effects.map((e) => ({
|
|
239
|
+
...e,
|
|
240
|
+
id: generateId()
|
|
241
|
+
}))
|
|
242
|
+
};
|
|
243
|
+
this.state.clips.push(duplicatedClip);
|
|
244
|
+
this.calculateDuration();
|
|
245
|
+
return duplicatedClip;
|
|
246
|
+
}
|
|
247
|
+
// ============ Effect Operations ============
|
|
248
|
+
addEffect(clipId, effect) {
|
|
249
|
+
const clip = this.state.clips.find((c) => c.id === clipId);
|
|
250
|
+
if (!clip) return null;
|
|
251
|
+
const newEffect = { ...effect, id: generateId() };
|
|
252
|
+
clip.effects.push(newEffect);
|
|
253
|
+
return newEffect;
|
|
254
|
+
}
|
|
255
|
+
removeEffect(clipId, effectId) {
|
|
256
|
+
const clip = this.state.clips.find((c) => c.id === clipId);
|
|
257
|
+
if (!clip) return false;
|
|
258
|
+
const index = clip.effects.findIndex((e) => e.id === effectId);
|
|
259
|
+
if (index === -1) return false;
|
|
260
|
+
clip.effects.splice(index, 1);
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
updateEffect(clipId, effectId, updates) {
|
|
264
|
+
const clip = this.state.clips.find((c) => c.id === clipId);
|
|
265
|
+
if (!clip) return false;
|
|
266
|
+
const effect = clip.effects.find((e) => e.id === effectId);
|
|
267
|
+
if (!effect) return false;
|
|
268
|
+
Object.assign(effect, updates);
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
// ============ Transition Operations ============
|
|
272
|
+
addTransition(transition) {
|
|
273
|
+
const newTransition = { ...transition, id: generateId() };
|
|
274
|
+
this.state.transitions.push(newTransition);
|
|
275
|
+
return newTransition;
|
|
276
|
+
}
|
|
277
|
+
removeTransition(id) {
|
|
278
|
+
const index = this.state.transitions.findIndex((t) => t.id === id);
|
|
279
|
+
if (index === -1) return false;
|
|
280
|
+
this.state.transitions.splice(index, 1);
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
getTransitions() {
|
|
284
|
+
return [...this.state.transitions];
|
|
285
|
+
}
|
|
286
|
+
// ============ Duration Calculation ============
|
|
287
|
+
calculateDuration() {
|
|
288
|
+
const maxEndTime = this.state.clips.reduce((max, clip) => {
|
|
289
|
+
const endTime = clip.startTime + clip.duration;
|
|
290
|
+
return Math.max(max, endTime);
|
|
291
|
+
}, 0);
|
|
292
|
+
this.state.project.duration = maxEndTime;
|
|
293
|
+
}
|
|
294
|
+
getDuration() {
|
|
295
|
+
return this.state.project.duration;
|
|
296
|
+
}
|
|
297
|
+
// ============ Serialization ============
|
|
298
|
+
toJSON() {
|
|
299
|
+
const state = this.getState();
|
|
300
|
+
return {
|
|
301
|
+
version: "1.0.0",
|
|
302
|
+
state: {
|
|
303
|
+
project: state.project,
|
|
304
|
+
tracks: state.tracks,
|
|
305
|
+
clips: state.clips,
|
|
306
|
+
sources: state.sources,
|
|
307
|
+
transitions: state.transitions
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
static fromJSON(data) {
|
|
312
|
+
const project = new _Project();
|
|
313
|
+
data.state.project.createdAt = new Date(data.state.project.createdAt);
|
|
314
|
+
data.state.project.updatedAt = new Date(data.state.project.updatedAt);
|
|
315
|
+
project.state = {
|
|
316
|
+
...data.state,
|
|
317
|
+
currentTime: 0,
|
|
318
|
+
isPlaying: false,
|
|
319
|
+
zoom: 50,
|
|
320
|
+
scrollX: 0,
|
|
321
|
+
selectedClipIds: [],
|
|
322
|
+
selectedTrackId: null
|
|
323
|
+
};
|
|
324
|
+
return project;
|
|
325
|
+
}
|
|
326
|
+
setFilePath(path) {
|
|
327
|
+
this.filePath = path;
|
|
328
|
+
}
|
|
329
|
+
// ============ Summary ============
|
|
330
|
+
getSummary() {
|
|
331
|
+
return {
|
|
332
|
+
name: this.state.project.name,
|
|
333
|
+
duration: this.state.project.duration,
|
|
334
|
+
aspectRatio: this.state.project.aspectRatio,
|
|
335
|
+
frameRate: this.state.project.frameRate,
|
|
336
|
+
trackCount: this.state.tracks.length,
|
|
337
|
+
clipCount: this.state.clips.length,
|
|
338
|
+
sourceCount: this.state.sources.length
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
export {
|
|
343
|
+
Project,
|
|
344
|
+
generateId
|
|
345
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless Project Engine for CLI operations
|
|
3
|
+
* No React/Zustand dependency - pure TypeScript
|
|
4
|
+
*/
|
|
5
|
+
import type { TimelineState, ProjectMeta, Track, Clip, MediaSource, Effect, Transition, Id, TimeSeconds, AspectRatio, MediaType } from "@vibeframe/core/timeline";
|
|
6
|
+
/** Generate unique ID */
|
|
7
|
+
export declare const generateId: () => Id;
|
|
8
|
+
/**
|
|
9
|
+
* Persisted timeline shape — what gets written to disk.
|
|
10
|
+
*
|
|
11
|
+
* UI runtime fields (currentTime, isPlaying, zoom, scrollX, selectedClipIds,
|
|
12
|
+
* selectedTrackId) are stripped on save and re-injected with defaults on
|
|
13
|
+
* load. They have no business in a CLI-generated project file: every CLI
|
|
14
|
+
* command starts a fresh process, so playhead / zoom / selection have no
|
|
15
|
+
* continuity to preserve.
|
|
16
|
+
*/
|
|
17
|
+
export type PersistedTimelineState = Omit<TimelineState, "currentTime" | "isPlaying" | "zoom" | "scrollX" | "selectedClipIds" | "selectedTrackId">;
|
|
18
|
+
/** Project file format */
|
|
19
|
+
export interface ProjectFile {
|
|
20
|
+
version: string;
|
|
21
|
+
state: PersistedTimelineState;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Headless Project Engine
|
|
25
|
+
* Manages timeline state without React/Zustand
|
|
26
|
+
*/
|
|
27
|
+
export declare class Project {
|
|
28
|
+
private state;
|
|
29
|
+
private filePath;
|
|
30
|
+
constructor(name?: string);
|
|
31
|
+
/** Get current state (immutable copy) */
|
|
32
|
+
getState(): TimelineState;
|
|
33
|
+
/** Get project metadata */
|
|
34
|
+
getMeta(): ProjectMeta;
|
|
35
|
+
/** Get file path */
|
|
36
|
+
getFilePath(): string | null;
|
|
37
|
+
setName(name: string): void;
|
|
38
|
+
setAspectRatio(ratio: AspectRatio): void;
|
|
39
|
+
setFrameRate(fps: number): void;
|
|
40
|
+
addSource(source: Omit<MediaSource, "id">): MediaSource;
|
|
41
|
+
removeSource(id: Id): boolean;
|
|
42
|
+
getSource(id: Id): MediaSource | undefined;
|
|
43
|
+
getSources(): MediaSource[];
|
|
44
|
+
addTrack(track: Omit<Track, "id">): Track;
|
|
45
|
+
removeTrack(id: Id): boolean;
|
|
46
|
+
updateTrack(id: Id, updates: Partial<Omit<Track, "id">>): boolean;
|
|
47
|
+
getTrack(id: Id): Track | undefined;
|
|
48
|
+
getTracks(): Track[];
|
|
49
|
+
getTracksByType(type: MediaType): Track[];
|
|
50
|
+
addClip(clip: Omit<Clip, "id" | "effects">): Clip;
|
|
51
|
+
removeClip(id: Id): boolean;
|
|
52
|
+
updateClip(id: Id, updates: Partial<Omit<Clip, "id">>): boolean;
|
|
53
|
+
moveClip(id: Id, trackId: Id, startTime: TimeSeconds): boolean;
|
|
54
|
+
trimClipStart(id: Id, newStartTime: TimeSeconds): boolean;
|
|
55
|
+
trimClipEnd(id: Id, newDuration: TimeSeconds): boolean;
|
|
56
|
+
getClip(id: Id): Clip | undefined;
|
|
57
|
+
getClips(): Clip[];
|
|
58
|
+
getClipsByTrack(trackId: Id): Clip[];
|
|
59
|
+
/**
|
|
60
|
+
* Split a clip at a specific time, creating two clips
|
|
61
|
+
* @param id Clip ID to split
|
|
62
|
+
* @param splitTime Time relative to clip start (not timeline time)
|
|
63
|
+
* @returns [firstClip, secondClip] or null if failed
|
|
64
|
+
*/
|
|
65
|
+
splitClip(id: Id, splitTime: TimeSeconds): [Clip, Clip] | null;
|
|
66
|
+
/**
|
|
67
|
+
* Duplicate a clip
|
|
68
|
+
* @param id Clip ID to duplicate
|
|
69
|
+
* @param offsetTime Optional time offset for the duplicate (default: place after original)
|
|
70
|
+
* @returns The duplicated clip or null if failed
|
|
71
|
+
*/
|
|
72
|
+
duplicateClip(id: Id, offsetTime?: TimeSeconds): Clip | null;
|
|
73
|
+
addEffect(clipId: Id, effect: Omit<Effect, "id">): Effect | null;
|
|
74
|
+
removeEffect(clipId: Id, effectId: Id): boolean;
|
|
75
|
+
updateEffect(clipId: Id, effectId: Id, updates: Partial<Omit<Effect, "id">>): boolean;
|
|
76
|
+
addTransition(transition: Omit<Transition, "id">): Transition;
|
|
77
|
+
removeTransition(id: Id): boolean;
|
|
78
|
+
getTransitions(): Transition[];
|
|
79
|
+
private calculateDuration;
|
|
80
|
+
getDuration(): TimeSeconds;
|
|
81
|
+
toJSON(): ProjectFile;
|
|
82
|
+
static fromJSON(data: ProjectFile): Project;
|
|
83
|
+
setFilePath(path: string): void;
|
|
84
|
+
getSummary(): {
|
|
85
|
+
name: string;
|
|
86
|
+
duration: TimeSeconds;
|
|
87
|
+
aspectRatio: AspectRatio;
|
|
88
|
+
frameRate: number;
|
|
89
|
+
trackCount: number;
|
|
90
|
+
clipCount: number;
|
|
91
|
+
sourceCount: number;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|