mulmocast 0.0.5 → 0.0.6

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 (132) hide show
  1. package/README.md +257 -39
  2. package/assets/audio/silent60sec.mp3 +0 -0
  3. package/assets/html/caption.html +45 -0
  4. package/assets/html/chart.html +1 -1
  5. package/assets/html/mermaid.html +6 -2
  6. package/assets/html/tailwind.html +13 -0
  7. package/assets/templates/business.json +57 -4
  8. package/assets/templates/comic_strips.json +35 -0
  9. package/assets/templates/ghibli_strips.json +35 -0
  10. package/lib/actions/audio.js +24 -11
  11. package/lib/actions/captions.d.ts +2 -0
  12. package/lib/actions/captions.js +62 -0
  13. package/lib/actions/images.js +3 -2
  14. package/lib/actions/index.d.ts +1 -0
  15. package/lib/actions/index.js +1 -0
  16. package/lib/actions/movie.js +78 -86
  17. package/lib/actions/pdf.js +15 -5
  18. package/lib/actions/translate.js +32 -26
  19. package/lib/agents/add_bgm_agent.js +15 -39
  20. package/lib/agents/combine_audio_files_agent.js +43 -36
  21. package/lib/agents/index.d.ts +2 -3
  22. package/lib/agents/index.js +2 -3
  23. package/lib/agents/tts_google_agent.d.ts +4 -0
  24. package/lib/agents/tts_google_agent.js +51 -0
  25. package/lib/agents/validate_schema_agent.d.ts +19 -0
  26. package/lib/agents/validate_schema_agent.js +36 -0
  27. package/lib/cli/args.d.ts +2 -0
  28. package/lib/cli/args.js +9 -2
  29. package/lib/cli/bin.d.ts +3 -0
  30. package/lib/cli/bin.js +38 -0
  31. package/lib/cli/cli.js +34 -7
  32. package/lib/cli/commands/audio/builder.d.ts +14 -0
  33. package/lib/cli/commands/audio/builder.js +6 -0
  34. package/lib/cli/commands/audio/handler.d.ts +4 -0
  35. package/lib/cli/commands/audio/handler.js +7 -0
  36. package/lib/cli/commands/audio/index.d.ts +4 -0
  37. package/lib/cli/commands/audio/index.js +4 -0
  38. package/lib/cli/commands/image/builder.d.ts +14 -0
  39. package/lib/cli/commands/image/builder.js +6 -0
  40. package/lib/cli/commands/image/handler.d.ts +4 -0
  41. package/lib/cli/commands/image/handler.js +7 -0
  42. package/lib/cli/commands/image/index.d.ts +4 -0
  43. package/lib/cli/commands/image/index.js +4 -0
  44. package/lib/cli/commands/movie/builder.d.ts +18 -0
  45. package/lib/cli/commands/movie/builder.js +19 -0
  46. package/lib/cli/commands/movie/handler.d.ts +6 -0
  47. package/lib/cli/commands/movie/handler.js +12 -0
  48. package/lib/cli/commands/movie/index.d.ts +4 -0
  49. package/lib/cli/commands/movie/index.js +4 -0
  50. package/lib/cli/commands/pdf/builder.d.ts +18 -0
  51. package/lib/cli/commands/pdf/builder.js +19 -0
  52. package/lib/cli/commands/pdf/handler.d.ts +6 -0
  53. package/lib/cli/commands/pdf/handler.js +8 -0
  54. package/lib/cli/commands/pdf/index.d.ts +4 -0
  55. package/lib/cli/commands/pdf/index.js +4 -0
  56. package/lib/cli/commands/tool/index.d.ts +6 -0
  57. package/lib/cli/commands/tool/index.js +8 -0
  58. package/lib/cli/commands/tool/prompt/builder.d.ts +4 -0
  59. package/lib/cli/commands/tool/prompt/builder.js +11 -0
  60. package/lib/cli/commands/tool/prompt/handler.d.ts +4 -0
  61. package/lib/cli/commands/tool/prompt/handler.js +14 -0
  62. package/lib/cli/commands/tool/prompt/index.d.ts +4 -0
  63. package/lib/cli/commands/tool/prompt/index.js +4 -0
  64. package/lib/cli/commands/tool/schema/builder.d.ts +2 -0
  65. package/lib/cli/commands/tool/schema/builder.js +3 -0
  66. package/lib/cli/commands/tool/schema/handler.d.ts +2 -0
  67. package/lib/cli/commands/tool/schema/handler.js +12 -0
  68. package/lib/cli/commands/tool/schema/index.d.ts +4 -0
  69. package/lib/cli/commands/tool/schema/index.js +4 -0
  70. package/lib/cli/commands/tool/scripting/builder.d.ts +20 -0
  71. package/lib/cli/commands/tool/scripting/builder.js +63 -0
  72. package/lib/cli/commands/tool/scripting/handler.d.ts +12 -0
  73. package/lib/cli/commands/tool/scripting/handler.js +36 -0
  74. package/lib/cli/commands/tool/scripting/index.d.ts +4 -0
  75. package/lib/cli/commands/tool/scripting/index.js +4 -0
  76. package/lib/cli/commands/tool/story_to_script/builder.d.ts +18 -0
  77. package/lib/cli/commands/tool/story_to_script/builder.js +53 -0
  78. package/lib/cli/commands/tool/story_to_script/handler.d.ts +11 -0
  79. package/lib/cli/commands/tool/story_to_script/handler.js +35 -0
  80. package/lib/cli/commands/tool/story_to_script/index.d.ts +4 -0
  81. package/lib/cli/commands/tool/story_to_script/index.js +4 -0
  82. package/lib/cli/commands/translate/builder.d.ts +14 -0
  83. package/lib/cli/commands/translate/builder.js +5 -0
  84. package/lib/cli/commands/translate/handler.d.ts +4 -0
  85. package/lib/cli/commands/translate/handler.js +6 -0
  86. package/lib/cli/commands/translate/index.d.ts +4 -0
  87. package/lib/cli/commands/translate/index.js +4 -0
  88. package/lib/cli/common.d.ts +6 -2
  89. package/lib/cli/common.js +18 -7
  90. package/lib/cli/helpers.d.ts +38 -0
  91. package/lib/cli/helpers.js +115 -0
  92. package/lib/cli/tool-args.d.ts +1 -0
  93. package/lib/cli/tool-args.js +1 -1
  94. package/lib/cli/tool-cli.js +8 -0
  95. package/lib/methods/mulmo_script.d.ts +0 -1
  96. package/lib/methods/mulmo_script.js +4 -7
  97. package/lib/methods/mulmo_script_template.js +2 -12
  98. package/lib/tools/create_mulmo_script_from_url.d.ts +1 -1
  99. package/lib/tools/create_mulmo_script_from_url.js +43 -14
  100. package/lib/tools/create_mulmo_script_interactively.js +14 -13
  101. package/lib/tools/dump_prompt.js +2 -0
  102. package/lib/tools/story_to_script.d.ts +10 -0
  103. package/lib/tools/story_to_script.js +201 -0
  104. package/lib/types/cli_types.d.ts +14 -0
  105. package/lib/types/cli_types.js +1 -0
  106. package/lib/types/schema.d.ts +493 -176
  107. package/lib/types/schema.js +37 -7
  108. package/lib/types/type.d.ts +6 -1
  109. package/lib/utils/const.d.ts +1 -0
  110. package/lib/utils/const.js +1 -0
  111. package/lib/utils/ffmpeg_utils.d.ts +12 -0
  112. package/lib/utils/ffmpeg_utils.js +63 -0
  113. package/lib/utils/file.d.ts +7 -3
  114. package/lib/utils/file.js +24 -5
  115. package/lib/utils/image_plugins/chart.js +6 -1
  116. package/lib/utils/image_plugins/html_tailwind.d.ts +3 -0
  117. package/lib/utils/image_plugins/html_tailwind.js +18 -0
  118. package/lib/utils/image_plugins/index.d.ts +2 -1
  119. package/lib/utils/image_plugins/index.js +2 -1
  120. package/lib/utils/image_plugins/mermaid.js +1 -1
  121. package/lib/utils/image_plugins/tailwind.d.ts +3 -0
  122. package/lib/utils/image_plugins/tailwind.js +18 -0
  123. package/lib/utils/image_plugins/text_slide.js +9 -2
  124. package/lib/utils/markdown.d.ts +1 -1
  125. package/lib/utils/markdown.js +8 -2
  126. package/lib/utils/preprocess.d.ts +23 -12
  127. package/lib/utils/preprocess.js +4 -0
  128. package/lib/utils/prompt.d.ts +15 -0
  129. package/lib/utils/prompt.js +57 -0
  130. package/lib/utils/utils.d.ts +2 -0
  131. package/lib/utils/utils.js +10 -0
  132. package/package.json +27 -23
@@ -0,0 +1,115 @@
1
+ import { GraphAILogger } from "graphai";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import clipboardy from "clipboardy";
5
+ import { getBaseDirPath, getFullPath, readMulmoScriptFile, fetchMulmoScriptFile, getOutputStudioFilePath, resolveDirPath } from "../utils/file.js";
6
+ import { isHttp } from "../utils/utils.js";
7
+ import { createOrUpdateStudioData } from "../utils/preprocess.js";
8
+ import { outDirName, imageDirName, audioDirName } from "../utils/const.js";
9
+ import { translate } from "../actions/translate.js";
10
+ export const setGraphAILogger = (verbose, logValues) => {
11
+ if (verbose) {
12
+ if (logValues) {
13
+ Object.entries(logValues).forEach(([key, value]) => {
14
+ GraphAILogger.info(`${key}:`, value);
15
+ });
16
+ }
17
+ }
18
+ else {
19
+ GraphAILogger.setLevelEnabled("error", false);
20
+ GraphAILogger.setLevelEnabled("log", false);
21
+ GraphAILogger.setLevelEnabled("warn", false);
22
+ }
23
+ };
24
+ export const getFileObject = (args) => {
25
+ const { basedir, outdir, imagedir, audiodir, file } = args;
26
+ const baseDirPath = getBaseDirPath(basedir);
27
+ const outDirPath = getFullPath(baseDirPath, outdir ?? outDirName);
28
+ const { fileOrUrl, fileName } = (() => {
29
+ if (file === "__clipboard") {
30
+ // We generate a new unique script file from clipboard text in the output directory
31
+ const now = new Date();
32
+ const pad = (n) => n.toString().padStart(2, "0");
33
+ const fileName = `script_${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
34
+ const clipboardText = clipboardy.readSync();
35
+ const fileOrUrl = resolveDirPath(outDirPath, `${fileName}.json`);
36
+ fs.writeFileSync(fileOrUrl, clipboardText, "utf8");
37
+ return { fileOrUrl, fileName };
38
+ }
39
+ const fileOrUrl = file ?? "";
40
+ const fileName = path.parse(fileOrUrl).name;
41
+ return { fileOrUrl, fileName };
42
+ })();
43
+ const isHttpPath = isHttp(fileOrUrl);
44
+ const mulmoFilePath = isHttpPath ? "" : getFullPath(baseDirPath, fileOrUrl);
45
+ const mulmoFileDirPath = path.dirname(isHttpPath ? baseDirPath : mulmoFilePath);
46
+ const imageDirPath = getFullPath(outDirPath, imagedir ?? imageDirName);
47
+ const audioDirPath = getFullPath(outDirPath, audiodir ?? audioDirName);
48
+ const outputStudioFilePath = getOutputStudioFilePath(outDirPath, fileName);
49
+ return {
50
+ baseDirPath,
51
+ mulmoFilePath,
52
+ mulmoFileDirPath,
53
+ outDirPath,
54
+ imageDirPath,
55
+ audioDirPath,
56
+ isHttpPath,
57
+ fileOrUrl,
58
+ outputStudioFilePath,
59
+ fileName,
60
+ };
61
+ };
62
+ export const fetchScript = async (isHttpPath, mulmoFilePath, fileOrUrl) => {
63
+ if (isHttpPath) {
64
+ const res = await fetchMulmoScriptFile(fileOrUrl);
65
+ if (!res.result || !res.script) {
66
+ GraphAILogger.info(`ERROR: HTTP error! ${res.status} ${fileOrUrl}`);
67
+ process.exit(1);
68
+ }
69
+ return res.script;
70
+ }
71
+ if (!fs.existsSync(mulmoFilePath)) {
72
+ GraphAILogger.info(`ERROR: File not exists ${mulmoFilePath}`);
73
+ process.exit(1);
74
+ }
75
+ return readMulmoScriptFile(mulmoFilePath, "ERROR: File does not exist " + mulmoFilePath).mulmoData;
76
+ };
77
+ export const initializeContext = async (argv) => {
78
+ const files = getFileObject({
79
+ basedir: argv.b,
80
+ outdir: argv.o,
81
+ imagedir: argv.i,
82
+ audiodir: argv.a,
83
+ file: argv.file ?? "",
84
+ });
85
+ const { fileName, isHttpPath, fileOrUrl, mulmoFilePath, outputStudioFilePath } = files;
86
+ setGraphAILogger(argv.v, {
87
+ files,
88
+ });
89
+ const mulmoScript = await fetchScript(isHttpPath, mulmoFilePath, fileOrUrl);
90
+ // Create or update MulmoStudio file with MulmoScript
91
+ const currentStudio = readMulmoScriptFile(outputStudioFilePath);
92
+ const studio = (() => {
93
+ try {
94
+ // validate mulmoStudioSchema. skip if __test_invalid__ is true
95
+ return createOrUpdateStudioData(mulmoScript, currentStudio?.mulmoData, fileName);
96
+ }
97
+ catch (error) {
98
+ GraphAILogger.info(`Error: invalid MulmoScript Schema: ${isHttpPath ? fileOrUrl : mulmoFilePath} \n ${error}`);
99
+ process.exit(1);
100
+ }
101
+ })();
102
+ return {
103
+ studio,
104
+ fileDirs: files,
105
+ force: Boolean(argv.f),
106
+ lang: argv.l,
107
+ caption: argv.c,
108
+ };
109
+ };
110
+ export const runTranslateIfNeeded = async (context, argv) => {
111
+ if (argv.l || argv.c) {
112
+ GraphAILogger.log("run translate");
113
+ await translate(context);
114
+ }
115
+ };
@@ -3,6 +3,7 @@ export declare const args: {
3
3
  v: boolean;
4
4
  o: string | undefined;
5
5
  b: string | undefined;
6
+ l: string | undefined;
6
7
  u: string[] | never[];
7
8
  i: boolean | undefined;
8
9
  t: string | undefined;
@@ -54,7 +54,7 @@ export const args = commonOptions(yargs(hideBin(process.argv)))
54
54
  .command("$0 <action>", "Run mulmocast tool", (yargs) => {
55
55
  return yargs.positional("action", {
56
56
  describe: "action to perform",
57
- choices: ["scripting", "prompt"],
57
+ choices: ["scripting", "prompt", "schema"],
58
58
  type: "string",
59
59
  });
60
60
  })
@@ -8,6 +8,8 @@ import { getBaseDirPath, getFullPath } from "../utils/file.js";
8
8
  import { createMulmoScriptInteractively } from "../tools/create_mulmo_script_interactively.js";
9
9
  import { dumpPromptFromTemplate } from "../tools/dump_prompt.js";
10
10
  import { getUrlsIfNeeded, selectTemplate } from "../utils/inquirer.js";
11
+ import { mulmoScriptSchema } from "../types/schema.js";
12
+ import { zodToJsonSchema } from "zod-to-json-schema";
11
13
  const main = async () => {
12
14
  const { o: outdir, b: basedir, action, v: verbose, i: interactive, s: filename, cache } = args;
13
15
  let { t: template } = args;
@@ -51,6 +53,12 @@ const main = async () => {
51
53
  else if (action === "prompt") {
52
54
  await dumpPromptFromTemplate({ templateName: template });
53
55
  }
56
+ else if (action === "schema") {
57
+ const defaultSchema = zodToJsonSchema(mulmoScriptSchema, {
58
+ strictUnions: true,
59
+ });
60
+ GraphAILogger.info(JSON.stringify(defaultSchema, null, 2));
61
+ }
54
62
  else {
55
63
  throw new Error(`Unknown or unsupported action: ${action}`);
56
64
  }
@@ -1,7 +1,6 @@
1
1
  import "dotenv/config";
2
2
  import { MulmoCanvasDimension, MulmoScript, MulmoBeat, SpeechOptions, Text2SpeechProvider, Text2ImageAgentInfo, BeatMediaType } from "../types/index.js";
3
3
  export declare const MulmoScriptMethods: {
4
- getPadding(script: MulmoScript): number;
5
4
  getCanvasSize(script: MulmoScript): MulmoCanvasDimension;
6
5
  getAspectRatio(script: MulmoScript): string;
7
6
  getSpeechProvider(script: MulmoScript): Text2SpeechProvider;
@@ -3,8 +3,8 @@ import { text2ImageProviderSchema, text2SpeechProviderSchema, mulmoCanvasDimensi
3
3
  const defaultTextSlideStyles = [
4
4
  '*,*::before,*::after{box-sizing:border-box}body,h1,h2,h3,h4,p,figure,blockquote,dl,dd{margin:0}ul[role="list"],ol[role="list"]{list-style:none}html:focus-within{scroll-behavior:smooth}body{min-height:100vh;text-rendering:optimizeSpeed;line-height:1.5}a:not([class]){text-decoration-skip-ink:auto}img,picture{max-width:100%;display:block}input,button,textarea,select{font:inherit}@media(prefers-reduced-motion:reduce){html:focus-within{scroll-behavior:auto}*,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important;scroll-behavior:auto !important}}',
5
5
  "body { margin: 60px; margin-top: 40px; color:#333; font-size: 30px; font-family: Arial, sans-serif; box-sizing: border-box; height: 100vh }",
6
- "h1 { font-size: 56px; margin-bottom: 20px; text-align: center; }",
7
- "h2 { font-size: 48px }",
6
+ "h1 { font-size: 56px; margin-bottom: 20px; text-align: center }",
7
+ "h2 { font-size: 48px; text-align: center }",
8
8
  "h3 { font-size: 36px }",
9
9
  "ul { margin-left: 40px } ",
10
10
  "pre { background: #eeeecc; font-size: 16px; padding:4px }",
@@ -15,9 +15,6 @@ const defaultTextSlideStyles = [
15
15
  "tr:nth-child(even) { background-color: #eee }",
16
16
  ];
17
17
  export const MulmoScriptMethods = {
18
- getPadding(script) {
19
- return script.videoParams?.padding ?? 1000; // msec
20
- },
21
18
  getCanvasSize(script) {
22
19
  return mulmoCanvasDimensionSchema.parse(script.canvasSize);
23
20
  },
@@ -30,11 +27,11 @@ export const MulmoScriptMethods = {
30
27
  return text2SpeechProviderSchema.parse(script.speechParams?.provider);
31
28
  },
32
29
  getTextSlideStyle(script, beat) {
33
- const styles = script.textSlideParams?.cssStyles ?? defaultTextSlideStyles;
30
+ const styles = script.textSlideParams?.cssStyles ?? [];
34
31
  // NOTES: Taking advantage of CSS override rule (you can redefine it to override)
35
32
  const extraStyles = beat.textSlideParams?.cssStyles ?? [];
36
33
  // This code allows us to support both string and array of strings for cssStyles
37
- return [...[styles], ...[extraStyles]].flat().join("\n");
34
+ return [...defaultTextSlideStyles, ...[styles], ...[extraStyles]].flat().join("\n");
38
35
  },
39
36
  getSpeechOptions(script, beat) {
40
37
  return { ...script.speechParams.speakers[beat.speaker].speechOptions, ...beat.speechOptions };
@@ -1,16 +1,6 @@
1
- import { zodToJsonSchema } from "zod-to-json-schema";
2
- import { mulmoScriptSchema } from "../types/schema.js";
1
+ import { getMulmoScriptTemplateSystemPrompt } from "../utils/prompt.js";
3
2
  export const MulmoScriptTemplateMethods = {
4
3
  getSystemPrompt(template) {
5
- // script is provided, use it as a script template
6
- if (template.script) {
7
- return `${template.systemPrompt}\n\`\`\`JSON\n${JSON.stringify(template.script)}\n\`\`\``;
8
- }
9
- // script is not provided, use the default schema
10
- const defaultSchema = zodToJsonSchema(mulmoScriptSchema, {
11
- strictUnions: true,
12
- });
13
- const specificOutputPrompt = `The output should follow the JSON schema specified below. Please provide your response as valid JSON within \`\`\`json code blocks for clarity.`;
14
- return `${template.systemPrompt}\n\n${specificOutputPrompt}\n\n\`\`\`JSON\n${JSON.stringify(defaultSchema)}\n\`\`\``;
4
+ return getMulmoScriptTemplateSystemPrompt(template);
15
5
  },
16
6
  };
@@ -1,3 +1,3 @@
1
1
  import "dotenv/config";
2
2
  import { ScriptingParams } from "../types/index.js";
3
- export declare const createMulmoScriptFromUrl: ({ urls, templateName, outDirPath, filename, cacheDirPath }: ScriptingParams) => Promise<void>;
3
+ export declare const createMulmoScriptFromUrl: ({ urls, templateName, outDirPath, filename, cacheDirPath, llm_agent, llm_model }: ScriptingParams) => Promise<void>;
@@ -1,14 +1,19 @@
1
1
  import "dotenv/config";
2
2
  import { GraphAI } from "graphai";
3
3
  import { openAIAgent } from "@graphai/openai_agent";
4
+ import { anthropicAgent } from "@graphai/anthropic_agent";
5
+ import { geminiAgent } from "@graphai/gemini_agent";
6
+ import { groqAgent } from "@graphai/groq_agent";
4
7
  import * as agents from "@graphai/vanilla";
5
8
  import { fileWriteAgent } from "@graphai/vanilla_node_agents";
6
9
  import { browserlessAgent } from "@graphai/browserless_agent";
7
- import validateMulmoScriptAgent from "../agents/validate_mulmo_script_agent.js";
10
+ import validateSchemaAgent from "../agents/validate_schema_agent.js";
8
11
  import { readTemplatePrompt, mkdir, writingMessage } from "../utils/file.js";
9
12
  import { browserlessCacheGenerator } from "../utils/filters.js";
10
- import { urlsSchema } from "../types/schema.js";
13
+ import { mulmoScriptSchema, urlsSchema } from "../types/schema.js";
11
14
  import { cliLoadingPlugin } from "../utils/plugins.js";
15
+ import { graphDataScriptFromUrlPrompt } from "../utils/prompt.js";
16
+ import { llmPair } from "../utils/utils.js";
12
17
  const { default: __, ...vanillaAgents } = agents;
13
18
  const graphData = {
14
19
  version: 0.5,
@@ -27,6 +32,15 @@ const graphData = {
27
32
  fileName: {
28
33
  value: "",
29
34
  },
35
+ llmAgent: {
36
+ value: "",
37
+ },
38
+ llmModel: {
39
+ value: "",
40
+ },
41
+ maxTokens: {
42
+ value: 0,
43
+ },
30
44
  // get the text content of the urls
31
45
  fetchResults: {
32
46
  agent: "mapAgent",
@@ -74,6 +88,9 @@ const graphData = {
74
88
  inputs: {
75
89
  sourceText: ":sourceText",
76
90
  prompt: ":prompt",
91
+ llmAgent: ":llmAgent",
92
+ llmModel: ":llmModel",
93
+ maxTokens: ":maxTokens",
77
94
  },
78
95
  graph: {
79
96
  loop: {
@@ -85,18 +102,23 @@ const graphData = {
85
102
  value: 0,
86
103
  update: ":counter.add(1)",
87
104
  },
88
- openAIAgent: {
89
- agent: "openAIAgent",
105
+ llm: {
106
+ agent: ":llmAgent",
107
+ params: {
108
+ model: ":llmModel",
109
+ system: ":prompt",
110
+ max_tokens: ":maxTokens",
111
+ },
90
112
  inputs: {
91
- model: "gpt-4o",
92
113
  system: ":prompt",
93
- prompt: "Please create a script using the information from the following URLs as reference: ${:sourceText.text}",
114
+ prompt: graphDataScriptFromUrlPrompt("${:sourceText.text}"),
94
115
  },
95
116
  },
96
- validateMulmoScriptAgent: {
97
- agent: "validateMulmoScriptAgent",
117
+ validateSchemaAgent: {
118
+ agent: "validateSchemaAgent",
98
119
  inputs: {
99
- text: ":openAIAgent.text.codeBlock()",
120
+ text: ":llm.text.codeBlock()",
121
+ schema: mulmoScriptSchema,
100
122
  },
101
123
  isResult: true,
102
124
  },
@@ -105,7 +127,7 @@ const graphData = {
105
127
  return !isValid && counter < 3;
106
128
  },
107
129
  inputs: {
108
- isValid: ":validateMulmoScriptAgent.isValid",
130
+ isValid: ":validateSchemaAgent.isValid",
109
131
  counter: ":counter",
110
132
  },
111
133
  },
@@ -113,17 +135,17 @@ const graphData = {
113
135
  },
114
136
  },
115
137
  writeJSON: {
116
- if: ":mulmoScript.validateMulmoScriptAgent.isValid",
138
+ if: ":mulmoScript.validateSchemaAgent.isValid",
117
139
  agent: "fileWriteAgent",
118
140
  inputs: {
119
141
  file: "${:outdir}/${:fileName}-${@now}.json",
120
- text: ":mulmoScript.validateMulmoScriptAgent.data.toJSON()",
142
+ text: ":mulmoScript.validateSchemaAgent.data.toJSON()",
121
143
  },
122
144
  isResult: true,
123
145
  },
124
146
  },
125
147
  };
126
- export const createMulmoScriptFromUrl = async ({ urls, templateName, outDirPath, filename, cacheDirPath }) => {
148
+ export const createMulmoScriptFromUrl = async ({ urls, templateName, outDirPath, filename, cacheDirPath, llm_agent, llm_model }) => {
127
149
  mkdir(outDirPath);
128
150
  mkdir(cacheDirPath);
129
151
  const parsedUrls = urlsSchema.parse(urls);
@@ -135,17 +157,24 @@ export const createMulmoScriptFromUrl = async ({ urls, templateName, outDirPath,
135
157
  nodeIds: ["fetcher"],
136
158
  },
137
159
  ];
160
+ const { agent, model, max_tokens } = llmPair(llm_agent, llm_model);
138
161
  const graph = new GraphAI(graphData, {
139
162
  ...vanillaAgents,
140
163
  openAIAgent,
164
+ anthropicAgent,
165
+ geminiAgent,
166
+ groqAgent,
141
167
  browserlessAgent,
142
- validateMulmoScriptAgent,
168
+ validateSchemaAgent,
143
169
  fileWriteAgent,
144
170
  }, { agentFilters });
145
171
  graph.injectValue("urls", parsedUrls);
146
172
  graph.injectValue("prompt", readTemplatePrompt(templateName));
147
173
  graph.injectValue("outdir", outDirPath);
148
174
  graph.injectValue("fileName", filename);
175
+ graph.injectValue("llmAgent", agent);
176
+ graph.injectValue("llmModel", model);
177
+ graph.injectValue("maxTokens", max_tokens);
149
178
  graph.registerCallback(cliLoadingPlugin({ nodeId: "mulmoScript", message: "Generating script..." }));
150
179
  const result = await graph.run();
151
180
  writingMessage(result?.writeJSON?.path ?? "");
@@ -1,7 +1,7 @@
1
1
  import "dotenv/config";
2
2
  import { GraphAILogger, GraphAI } from "graphai";
3
3
  import { textInputAgent } from "@graphai/input_agents";
4
- import { streamAgentFilterGenerator } from "@graphai/agent_filters";
4
+ import { consoleStreamDataAgentFilter } from "@graphai/stream_agent_filter/node";
5
5
  import { openAIAgent } from "@graphai/openai_agent";
6
6
  import { anthropicAgent } from "@graphai/anthropic_agent";
7
7
  import { geminiAgent } from "@graphai/gemini_agent";
@@ -10,9 +10,11 @@ import * as agents from "@graphai/vanilla";
10
10
  import { fileWriteAgent } from "@graphai/vanilla_node_agents";
11
11
  import { readTemplatePrompt, mkdir } from "../utils/file.js";
12
12
  import { browserlessCacheGenerator } from "../utils/filters.js";
13
+ import { mulmoScriptSchema } from "../types/index.js";
13
14
  import { browserlessAgent } from "@graphai/browserless_agent";
14
- import validateMulmoScriptAgent from "../agents/validate_mulmo_script_agent.js";
15
+ import validateSchemaAgent from "../agents/validate_schema_agent.js";
15
16
  import { llmPair } from "../utils/utils.js";
17
+ import { interactiveClarificationPrompt, prefixPrompt } from "../utils/prompt.js";
16
18
  // import { cliLoadingPlugin } from "../utils/plugins.js";
17
19
  const { default: __, ...vanillaAgents } = agents;
18
20
  const agentHeader = "\x1b[34m● \x1b[0m\x1b[1mAgent\x1b[0m:\x1b[0m";
@@ -119,6 +121,7 @@ const graphData = {
119
121
  params: {
120
122
  model: ":llmModel",
121
123
  stream: true,
124
+ dataStream: true,
122
125
  max_tokens: ":maxTokens",
123
126
  },
124
127
  inputs: {
@@ -127,10 +130,13 @@ const graphData = {
127
130
  },
128
131
  isResult: true,
129
132
  },
130
- validateMulmoScriptAgent: {
131
- agent: "validateMulmoScriptAgent",
133
+ validateSchemaAgent: {
134
+ if: ":chatAgent.text.codeBlock()",
135
+ defaultValue: false,
136
+ agent: "validateSchemaAgent",
132
137
  inputs: {
133
138
  text: ":chatAgent.text.codeBlock()",
139
+ schema: mulmoScriptSchema,
134
140
  },
135
141
  },
136
142
  continue: {
@@ -148,7 +154,7 @@ const graphData = {
148
154
  inputs: {
149
155
  counter: ":counter",
150
156
  codeBlock: ":chatAgent.text.codeBlock()",
151
- isValid: ":validateMulmoScriptAgent.isValid",
157
+ isValid: ":validateSchemaAgent.isValid",
152
158
  },
153
159
  },
154
160
  },
@@ -192,7 +198,6 @@ const graphData = {
192
198
  },
193
199
  },
194
200
  };
195
- const interactiveClarificationPrompt = `If there are any unclear points, be sure to ask the user questions and clarify them before generating the script.`;
196
201
  const scrapeWebContent = async (urls, cacheDirPath) => {
197
202
  mkdir(cacheDirPath);
198
203
  GraphAILogger.info(`${agentHeader} Scraping ${urls.length} URLs...\n`);
@@ -210,7 +215,6 @@ const scrapeWebContent = async (urls, cacheDirPath) => {
210
215
  if (!result?.sourceText?.text) {
211
216
  return "";
212
217
  }
213
- const prefixPrompt = "Here is the web content that can be used as reference material for the script:";
214
218
  return `\n\n${prefixPrompt}\n${result?.sourceText.text}`;
215
219
  };
216
220
  export const createMulmoScriptInteractively = async ({ outDirPath, cacheDirPath, filename, templateName, urls, llm_agent, llm_model }) => {
@@ -219,17 +223,14 @@ export const createMulmoScriptInteractively = async ({ outDirPath, cacheDirPath,
219
223
  const webContentPrompt = urls.length > 0 ? await scrapeWebContent(urls, cacheDirPath) : "";
220
224
  const { agent, model, max_tokens } = llmPair(llm_agent, llm_model);
221
225
  GraphAILogger.log({ agent, model, max_tokens });
222
- const streamAgentFilter = streamAgentFilterGenerator((context, data) => {
223
- process.stdout.write(String(data));
224
- });
225
226
  const agentFilters = [
226
227
  {
227
- name: "streamAgentFilter",
228
- agent: streamAgentFilter,
228
+ name: "consoleStreamDataAgentFilter",
229
+ agent: consoleStreamDataAgentFilter,
229
230
  nodeIds: ["chatAgent"],
230
231
  },
231
232
  ];
232
- const graph = new GraphAI(graphData, { ...vanillaAgents, anthropicAgent, geminiAgent, groqAgent, openAIAgent, textInputAgent, fileWriteAgent, validateMulmoScriptAgent }, { agentFilters });
233
+ const graph = new GraphAI(graphData, { ...vanillaAgents, anthropicAgent, geminiAgent, groqAgent, openAIAgent, textInputAgent, fileWriteAgent, validateSchemaAgent }, { agentFilters });
233
234
  const prompt = readTemplatePrompt(templateName);
234
235
  graph.injectValue("messages", [
235
236
  {
@@ -1,6 +1,8 @@
1
1
  import { GraphAILogger } from "graphai";
2
2
  import { readTemplatePrompt } from "../utils/file.js";
3
+ import clipboardy from "clipboardy";
3
4
  export const dumpPromptFromTemplate = async ({ templateName }) => {
4
5
  const prompt = readTemplatePrompt(templateName);
5
6
  GraphAILogger.info(prompt);
7
+ clipboardy.write(prompt);
6
8
  };
@@ -0,0 +1,10 @@
1
+ import { MulmoStoryboard } from "../types/index.js";
2
+ export declare const storyToScript: ({ story, beatsPerScene, templateName, outdir, fileName, llmAgent, llmModel, }: {
3
+ story: MulmoStoryboard;
4
+ beatsPerScene: number;
5
+ templateName: string;
6
+ outdir: string;
7
+ fileName: string;
8
+ llmAgent?: string;
9
+ llmModel?: string;
10
+ }) => Promise<void>;