@mulmoclaude/mulmoscript-plugin 0.1.0 → 0.2.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/contract-DxKVCRQk.cjs +13 -0
- package/dist/contract-DxKVCRQk.cjs.map +1 -0
- package/dist/contract-vY0niHkh.js +8 -0
- package/dist/contract-vY0niHkh.js.map +1 -0
- package/dist/server/dispatch.d.ts +10 -0
- package/dist/server/dispatch.d.ts.map +1 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/mulmoErrorCapture.d.ts +29 -0
- package/dist/server/mulmoErrorCapture.d.ts.map +1 -0
- package/dist/server/ops.d.ts +101 -0
- package/dist/server/ops.d.ts.map +1 -0
- package/dist/server/support.d.ts +9 -0
- package/dist/server/support.d.ts.map +1 -0
- package/dist/server/types.d.ts +74 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server.cjs +992 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.js +955 -0
- package/dist/server.js.map +1 -0
- package/dist/style.css +87 -0
- package/dist/vue.cjs +3 -7
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +1 -5
- package/dist/vue.js.map +1 -1
- package/package.json +10 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/core/contract.ts
|
|
2
|
+
/** Plugin pubsub event name the host publishes generation events on
|
|
3
|
+
* (full channel: `plugin:<scope>:generation`). */
|
|
4
|
+
var GENERATION_EVENT = "generation";
|
|
5
|
+
//#endregion
|
|
6
|
+
Object.defineProperty(exports, "GENERATION_EVENT", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function() {
|
|
9
|
+
return GENERATION_EVENT;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=contract-DxKVCRQk.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-DxKVCRQk.cjs","names":[],"sources":["../src/core/contract.ts"],"sourcesContent":["// Host-agnostic dispatch envelope for the presentMulmoScript View. The Vue\n// View is decoupled from any one host's REST surface: it calls\n// `useRuntime().dispatch({ kind, … })`, the host routes that to its\n// mulmoScript dispatch handler, and every response is an `{ ok: … }`\n// envelope so failures travel as data (no HTTP-status coupling, no\n// \"dispatch failed (500)\" prefixes in user-facing errors).\n//\n// Long-running generation (movie / PDF) is a single long-held dispatch that\n// resolves when the pipeline finishes; per-beat progress arrives on the\n// plugin pubsub channel (`GENERATION_EVENT`) instead of an SSE stream, which\n// also covers generations started elsewhere (background autoGenerateMovie,\n// another tab, the agent).\n\n/** One in-flight or per-beat generation notice, published on the plugin\n * pubsub `generation` channel and returned by the `pendingGenerations`\n * snapshot. Value strings mirror @mulmobridge/protocol's GENERATION_KINDS\n * so MulmoClaude's host bridge maps 1:1 without a lookup table. */\nexport interface MulmoScriptGenerationEvent {\n kind: \"beatImage\" | \"beatAudio\" | \"characterImage\" | \"movie\" | \"pdf\";\n /** Wire `stories/…` path of the script the generation belongs to. */\n filePath: string;\n /** beatIndex (as string) for beat*, character key for characterImage, \"\" for movie/pdf. */\n key: string;\n /** false = started, true = finished (reload the asset off disk). */\n done: boolean;\n /** Only set on done=true when the work failed. */\n error?: string;\n}\n\n/** Plugin pubsub event name the host publishes generation events on\n * (full channel: `plugin:<scope>:generation`). */\nexport const GENERATION_EVENT = \"generation\";\n\ninterface BeatRef {\n filePath: string;\n beatIndex: number;\n}\n\ninterface CharacterRef {\n filePath: string;\n key: string;\n}\n\n/** Session tag for hosts that surface per-session generation indicators\n * (MulmoClaude's sidebar). Optional everywhere; hosts without sessions\n * ignore it. */\ninterface SessionTag {\n chatSessionId?: string;\n}\n\nexport type MulmoScriptDispatchArgs =\n | ({ kind: \"save\" } & { filePath?: string; script?: unknown; filename?: string })\n | { kind: \"updateBeat\"; filePath: string; beatIndex: number; beat: unknown }\n | { kind: \"updateScript\"; filePath: string; script: unknown }\n | ({ kind: \"beatImage\" } & BeatRef)\n | ({ kind: \"beatAudio\" } & BeatRef)\n | ({ kind: \"beatMovie\" } & BeatRef)\n | ({ kind: \"renderBeat\" } & BeatRef & SessionTag & { force?: boolean })\n | ({ kind: \"generateBeatAudio\" } & BeatRef & SessionTag & { force?: boolean })\n | ({ kind: \"uploadBeatImage\" } & BeatRef & { imageData: string })\n | ({ kind: \"characterImage\" } & CharacterRef)\n | ({ kind: \"renderCharacter\" } & CharacterRef & SessionTag & { force?: boolean })\n | ({ kind: \"uploadCharacterImage\" } & CharacterRef & { imageData: string })\n | ({ kind: \"movieStatus\" } & { filePath: string })\n | ({ kind: \"pdfStatus\" } & { filePath: string })\n | ({ kind: \"generateMovie\" } & { filePath: string } & SessionTag)\n | ({ kind: \"generatePdf\" } & { filePath: string } & SessionTag)\n | { kind: \"pendingGenerations\"; filePath: string };\n\nexport type MulmoScriptDispatchKind = MulmoScriptDispatchArgs[\"kind\"];\n\n/** Failure half of every dispatch response. `code` mirrors the phase-1\n * outcome codes so a host can log/telemetry on it; the View only reads\n * `error`. */\nexport interface DispatchFailure {\n ok: false;\n code?: \"bad_request\" | \"not_found\" | \"server_error\";\n error: string;\n}\n\nexport type DispatchEnvelope<T> = ({ ok: true } & T) | DispatchFailure;\n\n/** Maps a dispatch `kind` to its success payload so the View's transport\n * can call `dispatch` without casts at every site. */\nexport interface MulmoScriptDispatchResult {\n save: { script: Record<string, unknown>; filePath: string; message: string };\n updateBeat: Record<string, never>;\n updateScript: Record<string, never>;\n beatImage: { image: string | null };\n beatAudio: { audio: string | null };\n beatMovie: { moviePath: string | null };\n renderBeat: { image: string };\n generateBeatAudio: { audio: string };\n uploadBeatImage: { image: string };\n characterImage: { image: string | null };\n renderCharacter: { image: string };\n uploadCharacterImage: { image: string };\n movieStatus: { moviePath: string | null };\n pdfStatus: { pdfPath: string | null };\n generateMovie: { moviePath: string };\n generatePdf: { pdfPath: string };\n pendingGenerations: { pending: MulmoScriptGenerationEvent[] };\n}\n"],"mappings":";;;AA+BA,IAAa,mBAAmB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/core/contract.ts
|
|
2
|
+
/** Plugin pubsub event name the host publishes generation events on
|
|
3
|
+
* (full channel: `plugin:<scope>:generation`). */
|
|
4
|
+
var GENERATION_EVENT = "generation";
|
|
5
|
+
//#endregion
|
|
6
|
+
export { GENERATION_EVENT as t };
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=contract-vY0niHkh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-vY0niHkh.js","names":[],"sources":["../src/core/contract.ts"],"sourcesContent":["// Host-agnostic dispatch envelope for the presentMulmoScript View. The Vue\n// View is decoupled from any one host's REST surface: it calls\n// `useRuntime().dispatch({ kind, … })`, the host routes that to its\n// mulmoScript dispatch handler, and every response is an `{ ok: … }`\n// envelope so failures travel as data (no HTTP-status coupling, no\n// \"dispatch failed (500)\" prefixes in user-facing errors).\n//\n// Long-running generation (movie / PDF) is a single long-held dispatch that\n// resolves when the pipeline finishes; per-beat progress arrives on the\n// plugin pubsub channel (`GENERATION_EVENT`) instead of an SSE stream, which\n// also covers generations started elsewhere (background autoGenerateMovie,\n// another tab, the agent).\n\n/** One in-flight or per-beat generation notice, published on the plugin\n * pubsub `generation` channel and returned by the `pendingGenerations`\n * snapshot. Value strings mirror @mulmobridge/protocol's GENERATION_KINDS\n * so MulmoClaude's host bridge maps 1:1 without a lookup table. */\nexport interface MulmoScriptGenerationEvent {\n kind: \"beatImage\" | \"beatAudio\" | \"characterImage\" | \"movie\" | \"pdf\";\n /** Wire `stories/…` path of the script the generation belongs to. */\n filePath: string;\n /** beatIndex (as string) for beat*, character key for characterImage, \"\" for movie/pdf. */\n key: string;\n /** false = started, true = finished (reload the asset off disk). */\n done: boolean;\n /** Only set on done=true when the work failed. */\n error?: string;\n}\n\n/** Plugin pubsub event name the host publishes generation events on\n * (full channel: `plugin:<scope>:generation`). */\nexport const GENERATION_EVENT = \"generation\";\n\ninterface BeatRef {\n filePath: string;\n beatIndex: number;\n}\n\ninterface CharacterRef {\n filePath: string;\n key: string;\n}\n\n/** Session tag for hosts that surface per-session generation indicators\n * (MulmoClaude's sidebar). Optional everywhere; hosts without sessions\n * ignore it. */\ninterface SessionTag {\n chatSessionId?: string;\n}\n\nexport type MulmoScriptDispatchArgs =\n | ({ kind: \"save\" } & { filePath?: string; script?: unknown; filename?: string })\n | { kind: \"updateBeat\"; filePath: string; beatIndex: number; beat: unknown }\n | { kind: \"updateScript\"; filePath: string; script: unknown }\n | ({ kind: \"beatImage\" } & BeatRef)\n | ({ kind: \"beatAudio\" } & BeatRef)\n | ({ kind: \"beatMovie\" } & BeatRef)\n | ({ kind: \"renderBeat\" } & BeatRef & SessionTag & { force?: boolean })\n | ({ kind: \"generateBeatAudio\" } & BeatRef & SessionTag & { force?: boolean })\n | ({ kind: \"uploadBeatImage\" } & BeatRef & { imageData: string })\n | ({ kind: \"characterImage\" } & CharacterRef)\n | ({ kind: \"renderCharacter\" } & CharacterRef & SessionTag & { force?: boolean })\n | ({ kind: \"uploadCharacterImage\" } & CharacterRef & { imageData: string })\n | ({ kind: \"movieStatus\" } & { filePath: string })\n | ({ kind: \"pdfStatus\" } & { filePath: string })\n | ({ kind: \"generateMovie\" } & { filePath: string } & SessionTag)\n | ({ kind: \"generatePdf\" } & { filePath: string } & SessionTag)\n | { kind: \"pendingGenerations\"; filePath: string };\n\nexport type MulmoScriptDispatchKind = MulmoScriptDispatchArgs[\"kind\"];\n\n/** Failure half of every dispatch response. `code` mirrors the phase-1\n * outcome codes so a host can log/telemetry on it; the View only reads\n * `error`. */\nexport interface DispatchFailure {\n ok: false;\n code?: \"bad_request\" | \"not_found\" | \"server_error\";\n error: string;\n}\n\nexport type DispatchEnvelope<T> = ({ ok: true } & T) | DispatchFailure;\n\n/** Maps a dispatch `kind` to its success payload so the View's transport\n * can call `dispatch` without casts at every site. */\nexport interface MulmoScriptDispatchResult {\n save: { script: Record<string, unknown>; filePath: string; message: string };\n updateBeat: Record<string, never>;\n updateScript: Record<string, never>;\n beatImage: { image: string | null };\n beatAudio: { audio: string | null };\n beatMovie: { moviePath: string | null };\n renderBeat: { image: string };\n generateBeatAudio: { audio: string };\n uploadBeatImage: { image: string };\n characterImage: { image: string | null };\n renderCharacter: { image: string };\n uploadCharacterImage: { image: string };\n movieStatus: { moviePath: string | null };\n pdfStatus: { pdfPath: string | null };\n generateMovie: { moviePath: string };\n generatePdf: { pdfPath: string };\n pendingGenerations: { pending: MulmoScriptGenerationEvent[] };\n}\n"],"mappings":";;;AA+BA,IAAa,mBAAmB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MulmoScriptServerOps } from "./ops";
|
|
2
|
+
export type MulmoScriptDispatchHandler = (args: Record<string, unknown>) => Promise<unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* Build the kind router over an ops instance. The save / reopen / update
|
|
5
|
+
* kinds run the phase-1 core executes against the backend's artifacts
|
|
6
|
+
* FileOps, guarded by the instance's realpath containment
|
|
7
|
+
* (`guardStoryWirePath`) — the core's own guard is lexical.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createMulmoScriptDispatchHandler(ops: MulmoScriptServerOps): MulmoScriptDispatchHandler;
|
|
10
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/server/dispatch.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAqElD,MAAM,MAAM,0BAA0B,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE7F;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,oBAAoB,GAAG,0BAA0B,CAuFtG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { GenerateOpArgs, MovieGenerationResult, MovieProgressEvent, MulmoScriptServerBackend, MulmoScriptServerLog, OpFailure, OpResult, PdfGenerationResult, } from "./types";
|
|
2
|
+
export { buildContext, buildBeatIdIndex, createMulmoScriptServerOps, PDF_MODE, PDF_SIZE, type MulmoScriptServerOps, type RunStoryOpDeps, type RunStoryOpOptions, type StoryContext, } from "./ops";
|
|
3
|
+
export { createMulmoScriptDispatchHandler, type MulmoScriptDispatchHandler } from "./dispatch";
|
|
4
|
+
export { withMulmoErrorCapture, enableGraphAIErrorCapture, composeMulmoErrorMessage, describeMulmoCause } from "./mulmoErrorCapture";
|
|
5
|
+
export { GENERATION_EVENT, type MulmoScriptGenerationEvent } from "../core/contract";
|
|
6
|
+
export { executeMulmoScriptSave, executeUpdateBeat, executeUpdateScript, type MulmoScriptFailure } from "../core/plugin";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAMA,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,SAAS,EACT,QAAQ,EACR,mBAAmB,GACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,0BAA0B,EAC1B,QAAQ,EACR,QAAQ,EACR,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,YAAY,GAClB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,gCAAgC,EAAE,KAAK,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACrI,OAAO,EAAE,gBAAgB,EAAE,KAAK,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { MulmoScriptServerLog } from "./types";
|
|
2
|
+
/** Route captured GraphAI errors into the host logger. Set once by
|
|
3
|
+
* `createMulmoScriptServerOps`; the GraphAILogger sink is global, so the
|
|
4
|
+
* last-configured host logger wins (one ops instance per process). */
|
|
5
|
+
export declare function setMulmoErrorCaptureLogger(log: MulmoScriptServerLog | null): void;
|
|
6
|
+
/**
|
|
7
|
+
* Re-enable GraphAI's error level (everything else stays silenced) and
|
|
8
|
+
* route it into the host logger + the per-operation capture store.
|
|
9
|
+
* Call after every `setGraphAILogger(false)` — that helper disables all
|
|
10
|
+
* levels including error. Idempotent.
|
|
11
|
+
*/
|
|
12
|
+
export declare function enableGraphAIErrorCapture(): void;
|
|
13
|
+
/** Render mulmocast's structured error `cause` as "field=value" pairs. */
|
|
14
|
+
export declare function describeMulmoCause(err: unknown): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Compose the enriched message for a failed mulmocast operation:
|
|
17
|
+
* mulmocast's own message, then its structured cause, then the
|
|
18
|
+
* captured underlying provider error(s). Deduped — GraphAI retries
|
|
19
|
+
* log the same error more than once.
|
|
20
|
+
*/
|
|
21
|
+
export declare function composeMulmoErrorMessage(err: unknown, captured: readonly string[]): string;
|
|
22
|
+
/**
|
|
23
|
+
* Run a mulmocast operation, capturing GraphAI error logs emitted while
|
|
24
|
+
* it executes. On failure, rethrows with the captured provider error(s)
|
|
25
|
+
* appended to the message (original error kept as `cause`). Uses
|
|
26
|
+
* AsyncLocalStorage so concurrent operations don't cross-attribute.
|
|
27
|
+
*/
|
|
28
|
+
export declare function withMulmoErrorCapture<T>(operation: () => Promise<T>): Promise<T>;
|
|
29
|
+
//# sourceMappingURL=mulmoErrorCapture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mulmoErrorCapture.d.ts","sourceRoot":"","sources":["../../src/server/mulmoErrorCapture.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAMpD;;uEAEuE;AACvE,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,oBAAoB,GAAG,IAAI,GAAG,IAAI,CAEjF;AAYD;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAUhD;AAOD,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAQ9D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAI1F;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQtF"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { MulmoBeat, MulmoStudioContext } from "@mulmocast/types";
|
|
2
|
+
import type { MulmoScriptGenerationEvent } from "../core/contract";
|
|
3
|
+
import type { GenerateOpArgs, MovieGenerationResult, MovieProgressEvent, MulmoScriptServerBackend, OpFailure, OpResult, PdfGenerationResult } from "./types";
|
|
4
|
+
type GenerationKind = MulmoScriptGenerationEvent["kind"];
|
|
5
|
+
export declare const PDF_MODE: "slide";
|
|
6
|
+
export declare const PDF_SIZE: "a4";
|
|
7
|
+
export declare function buildContext(absoluteFilePath: string, force?: boolean): Promise<MulmoStudioContext | null | undefined>;
|
|
8
|
+
export type StoryContext = NonNullable<Awaited<ReturnType<typeof buildContext>>>;
|
|
9
|
+
export interface RunStoryOpDeps {
|
|
10
|
+
resolveStory?: (filePath: string) => {
|
|
11
|
+
ok: true;
|
|
12
|
+
absolutePath: string;
|
|
13
|
+
} | OpFailure;
|
|
14
|
+
buildContext?: (absoluteFilePath: string, force?: boolean) => Promise<StoryContext | undefined>;
|
|
15
|
+
}
|
|
16
|
+
export interface RunStoryOpOptions<T> {
|
|
17
|
+
force?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Op-specific tag included in the failure log so dashboards can
|
|
20
|
+
* distinguish which op is failing (e.g. `"generate-beat-audio"`).
|
|
21
|
+
* Falls back to a generic `"op failed"` entry when omitted.
|
|
22
|
+
*/
|
|
23
|
+
operation?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Soft-fail override for `buildContext` returning undefined. Some
|
|
26
|
+
* ops (e.g. `beatAudio`) historically returned a 200 `{ audio: null }`
|
|
27
|
+
* in that case so the frontend can silently retry. If provided, this
|
|
28
|
+
* callback returns the fallback result instead of the default
|
|
29
|
+
* server_error "Failed to initialize mulmo context".
|
|
30
|
+
*/
|
|
31
|
+
onContextMissing?: () => OpResult<T>;
|
|
32
|
+
}
|
|
33
|
+
export declare function buildBeatIdIndex(beats: MulmoBeat[]): Map<string, number>;
|
|
34
|
+
/**
|
|
35
|
+
* Build the per-host mulmoScript server ops instance. One instance per
|
|
36
|
+
* process — it owns the in-flight movie/PDF dedup sets and the
|
|
37
|
+
* generation-state tracker, and binds the injected host backend.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createMulmoScriptServerOps(backend: MulmoScriptServerBackend): {
|
|
40
|
+
backend: MulmoScriptServerBackend;
|
|
41
|
+
toStoryRef: (absolutePath: string) => string;
|
|
42
|
+
resolveStory: (filePath: string) => {
|
|
43
|
+
ok: true;
|
|
44
|
+
absolutePath: string;
|
|
45
|
+
} | OpFailure;
|
|
46
|
+
guardStoryWirePath: (filePath: unknown) => OpFailure | null;
|
|
47
|
+
ffmpegGuard: () => OpFailure | null;
|
|
48
|
+
runStoryOp: <T>(filePath: string, options: RunStoryOpOptions<T>, handler: (ctx: {
|
|
49
|
+
absoluteFilePath: string;
|
|
50
|
+
context: StoryContext;
|
|
51
|
+
}) => Promise<OpResult<T>>, deps?: RunStoryOpDeps) => Promise<OpResult<T>>;
|
|
52
|
+
publishGeneration: (chatSessionId: string | undefined, kind: GenerationKind, filePath: string, key: string, finished: boolean, error?: string) => void;
|
|
53
|
+
pendingGenerations: (filePath: string) => MulmoScriptGenerationEvent[];
|
|
54
|
+
beatImageOp: (filePath: string, beatIndex: number) => Promise<OpResult<{
|
|
55
|
+
image: string | null;
|
|
56
|
+
}>>;
|
|
57
|
+
beatAudioOp: (filePath: string, beatIndex: number) => Promise<OpResult<{
|
|
58
|
+
audio: string | null;
|
|
59
|
+
}>>;
|
|
60
|
+
beatMovieOp: (filePath: string, beatIndex: number) => Promise<OpResult<{
|
|
61
|
+
moviePath: string | null;
|
|
62
|
+
}>>;
|
|
63
|
+
characterImageOp: (filePath: string, key: string) => Promise<OpResult<{
|
|
64
|
+
image: string | null;
|
|
65
|
+
}>>;
|
|
66
|
+
movieStatusOp: (filePath: string) => Promise<OpResult<{
|
|
67
|
+
moviePath: string | null;
|
|
68
|
+
}>>;
|
|
69
|
+
pdfStatusOp: (filePath: string) => Promise<OpResult<{
|
|
70
|
+
pdfPath: string | null;
|
|
71
|
+
}>>;
|
|
72
|
+
renderBeatOp: (args: Required<Pick<GenerateOpArgs, "filePath" | "beatIndex">> & GenerateOpArgs) => Promise<OpResult<{
|
|
73
|
+
image: string;
|
|
74
|
+
}>>;
|
|
75
|
+
generateBeatAudioOp: (args: Required<Pick<GenerateOpArgs, "filePath" | "beatIndex">> & GenerateOpArgs) => Promise<OpResult<{
|
|
76
|
+
audio: string;
|
|
77
|
+
}>>;
|
|
78
|
+
renderCharacterOp: (args: Required<Pick<GenerateOpArgs, "filePath" | "key">> & GenerateOpArgs) => Promise<OpResult<{
|
|
79
|
+
image: string;
|
|
80
|
+
}>>;
|
|
81
|
+
uploadBeatImageOp: (filePath: string, beatIndex: number, imageData: string) => Promise<OpResult<{
|
|
82
|
+
image: string;
|
|
83
|
+
}>>;
|
|
84
|
+
uploadCharacterImageOp: (filePath: string, key: string, imageData: string) => Promise<OpResult<{
|
|
85
|
+
image: string;
|
|
86
|
+
}>>;
|
|
87
|
+
inFlightMovies: Set<string>;
|
|
88
|
+
inFlightPdfs: Set<string>;
|
|
89
|
+
runMovieGeneration: (absoluteFilePath: string, onProgressEvent: (event: MovieProgressEvent) => void) => Promise<MovieGenerationResult>;
|
|
90
|
+
runPdfGeneration: (context: StoryContext, onImageBeatDone: (beatIndex: number) => void) => Promise<PdfGenerationResult>;
|
|
91
|
+
generateMovieOp: (filePath: string, chatSessionId: string | undefined) => Promise<OpResult<{
|
|
92
|
+
moviePath: string;
|
|
93
|
+
}>>;
|
|
94
|
+
generatePdfOp: (filePath: string, chatSessionId: string | undefined) => Promise<OpResult<{
|
|
95
|
+
pdfPath: string;
|
|
96
|
+
}>>;
|
|
97
|
+
triggerAutoBackgroundMovie: (absoluteFilePath: string, wireFilePath: string, chatSessionId: string | undefined) => void;
|
|
98
|
+
};
|
|
99
|
+
export type MulmoScriptServerOps = ReturnType<typeof createMulmoScriptServerOps>;
|
|
100
|
+
export {};
|
|
101
|
+
//# sourceMappingURL=ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../src/server/ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function errorText(err: unknown): string;
|
|
2
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
3
|
+
export declare function stripDataUri(dataUri: string): string;
|
|
4
|
+
/** Realpath-based containment: resolve `relPath` against the ROOT's
|
|
5
|
+
* realpath and require the target's realpath to stay inside it. Returns
|
|
6
|
+
* null on ENOENT or traversal (symlink escapes included). */
|
|
7
|
+
export declare function resolveWithinRoot(rootReal: string, relPath: string): string | null;
|
|
8
|
+
export declare function fileToDataUri(filePath: string, mimeType: string): Promise<string>;
|
|
9
|
+
//# sourceMappingURL=support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../src/server/support.ts"],"names":[],"mappings":"AAUA,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAQ9C;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;8DAE8D;AAC9D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAalF;AAID,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGvF"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { FileOps } from "gui-chat-protocol";
|
|
2
|
+
import type { MulmoScriptGenerationEvent } from "../core/contract";
|
|
3
|
+
export interface OpFailure {
|
|
4
|
+
ok: false;
|
|
5
|
+
/** REST adapter mapping: bad_request→400, not_found→404,
|
|
6
|
+
* unavailable→503, server_error→500. */
|
|
7
|
+
code: "bad_request" | "not_found" | "server_error" | "unavailable";
|
|
8
|
+
error: string;
|
|
9
|
+
}
|
|
10
|
+
export type OpResult<T> = ({
|
|
11
|
+
ok: true;
|
|
12
|
+
} & T) | OpFailure;
|
|
13
|
+
export interface GenerateOpArgs {
|
|
14
|
+
filePath: string;
|
|
15
|
+
beatIndex?: number;
|
|
16
|
+
key?: string;
|
|
17
|
+
force?: boolean;
|
|
18
|
+
chatSessionId?: string;
|
|
19
|
+
}
|
|
20
|
+
export type MovieGenerationResult = {
|
|
21
|
+
ok: true;
|
|
22
|
+
outputPath: string;
|
|
23
|
+
} | {
|
|
24
|
+
ok: false;
|
|
25
|
+
error: string;
|
|
26
|
+
};
|
|
27
|
+
export type PdfGenerationResult = {
|
|
28
|
+
ok: true;
|
|
29
|
+
outputPath: string;
|
|
30
|
+
} | {
|
|
31
|
+
ok: false;
|
|
32
|
+
error: string;
|
|
33
|
+
};
|
|
34
|
+
export interface MovieProgressEvent {
|
|
35
|
+
kind: "image" | "audio";
|
|
36
|
+
beatIndex: number;
|
|
37
|
+
}
|
|
38
|
+
/** Host logger; every entry is already namespaced to mulmoScript by the
|
|
39
|
+
* package, so hosts just bind their own prefix/transport. */
|
|
40
|
+
export interface MulmoScriptServerLog {
|
|
41
|
+
info: (message: string, data?: Record<string, unknown>) => void;
|
|
42
|
+
warn: (message: string, data?: Record<string, unknown>) => void;
|
|
43
|
+
error: (message: string, data?: Record<string, unknown>) => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Host capabilities the server ops run against. Only genuinely
|
|
47
|
+
* host-specific transport lives here — the mulmocast orchestration, path
|
|
48
|
+
* containment, and generation-state tracking are all in-package.
|
|
49
|
+
*/
|
|
50
|
+
export interface MulmoScriptServerBackend {
|
|
51
|
+
/** Absolute path of the stories directory (`<workspace>/artifacts/stories`).
|
|
52
|
+
* May not exist yet — the ops lazily create + realpath it. */
|
|
53
|
+
storiesDir: string;
|
|
54
|
+
/** Shared artifacts FileOps (rooted at `<workspace>/artifacts`) for the
|
|
55
|
+
* save / reopen / update dispatch kinds (phase-1 core executes). */
|
|
56
|
+
artifacts: FileOps;
|
|
57
|
+
/** Atomic file write (tmp alongside destination + rename; parent dirs
|
|
58
|
+
* created). Hosts inject their hardened implementation. */
|
|
59
|
+
writeFileAtomic: (absolutePath: string, data: string | Uint8Array) => Promise<void>;
|
|
60
|
+
/** ffmpeg availability probe. `false` blocks render/movie/PDF ops with a
|
|
61
|
+
* clear message; `true`/`undefined` proceeds (a boot probe may not have
|
|
62
|
+
* completed yet — never block on the startup window). */
|
|
63
|
+
isFfmpegAvailable?: () => boolean | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Generation fan-out (session channels, UI pubsub). Called on EDGE
|
|
66
|
+
* transitions only — first start / last finish of concurrent same-key
|
|
67
|
+
* runs — plus the finish-only per-beat pulses from the movie/PDF
|
|
68
|
+
* pipelines. `chatSessionId` is undefined for callers outside a chat
|
|
69
|
+
* session. The package keeps the in-flight snapshot itself.
|
|
70
|
+
*/
|
|
71
|
+
onGenerationEvent?: (chatSessionId: string | undefined, event: MulmoScriptGenerationEvent) => void;
|
|
72
|
+
log?: MulmoScriptServerLog;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAEnE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,KAAK,CAAC;IACV;6CACyC;IACzC,IAAI,EAAE,aAAa,GAAG,WAAW,GAAG,cAAc,GAAG,aAAa,CAAC;IACnE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,qBAAqB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACpG,MAAM,MAAM,mBAAmB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElG,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;8DAC8D;AAC9D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAClE;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC;mEAC+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB;yEACqE;IACrE,SAAS,EAAE,OAAO,CAAC;IACnB;gEAC4D;IAC5D,eAAe,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF;;8DAE0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,OAAO,GAAG,SAAS,CAAC;IAC9C;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;IACnG,GAAG,CAAC,EAAE,oBAAoB,CAAC;CAC5B"}
|