mulmocast 0.0.2 → 0.0.3

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 (74) hide show
  1. package/README.md +27 -9
  2. package/assets/font/NotoSansJP-Regular.ttf +0 -0
  3. package/assets/html/chart.html +1 -10
  4. package/assets/html/mermaid.html +1 -13
  5. package/assets/templates/business.json +16 -27
  6. package/assets/templates/coding.json +58 -21
  7. package/lib/actions/audio.d.ts +1 -1
  8. package/lib/actions/audio.js +43 -27
  9. package/lib/actions/images.js +20 -26
  10. package/lib/actions/index.d.ts +5 -0
  11. package/lib/actions/index.js +5 -0
  12. package/lib/actions/movie.d.ts +9 -1
  13. package/lib/actions/movie.js +97 -38
  14. package/lib/actions/pdf.d.ts +2 -0
  15. package/lib/actions/pdf.js +211 -0
  16. package/lib/actions/pdf2.d.ts +2 -0
  17. package/lib/actions/pdf2.js +203 -0
  18. package/lib/actions/translate.js +22 -9
  19. package/lib/agents/anthropic_agent.d.ts +23 -0
  20. package/lib/agents/anthropic_agent.js +162 -0
  21. package/lib/agents/combine_audio_files_agent.js +13 -22
  22. package/lib/agents/nested_agent.d.ts +9 -0
  23. package/lib/agents/nested_agent.js +138 -0
  24. package/lib/cli/args.d.ts +3 -1
  25. package/lib/cli/args.js +49 -34
  26. package/lib/cli/cli.d.ts +14 -0
  27. package/lib/cli/cli.js +48 -46
  28. package/lib/cli/tool-args.d.ts +2 -0
  29. package/lib/cli/tool-args.js +12 -2
  30. package/lib/cli/tool-cli.js +6 -4
  31. package/lib/methods/index.d.ts +1 -0
  32. package/lib/methods/index.js +1 -0
  33. package/lib/methods/mulmo_media_source.d.ts +4 -0
  34. package/lib/methods/mulmo_media_source.js +21 -0
  35. package/lib/methods/mulmo_script.d.ts +2 -6
  36. package/lib/methods/mulmo_script.js +12 -5
  37. package/lib/tools/create_mulmo_script_interactively.d.ts +1 -1
  38. package/lib/tools/create_mulmo_script_interactively.js +61 -20
  39. package/lib/types/index.d.ts +1 -0
  40. package/lib/types/index.js +1 -0
  41. package/lib/types/schema.d.ts +3626 -3162
  42. package/lib/types/schema.js +75 -41
  43. package/lib/types/type.d.ts +28 -1
  44. package/lib/utils/const.d.ts +2 -0
  45. package/lib/utils/const.js +2 -0
  46. package/lib/utils/file.d.ts +4 -1
  47. package/lib/utils/file.js +15 -1
  48. package/lib/utils/filters.js +1 -1
  49. package/lib/utils/image_plugins/chart.d.ts +3 -0
  50. package/lib/utils/image_plugins/chart.js +18 -0
  51. package/lib/utils/image_plugins/image.d.ts +2 -0
  52. package/lib/utils/image_plugins/image.js +3 -0
  53. package/lib/utils/image_plugins/index.d.ts +7 -0
  54. package/lib/utils/image_plugins/index.js +7 -0
  55. package/lib/utils/image_plugins/markdown.d.ts +3 -0
  56. package/lib/utils/image_plugins/markdown.js +11 -0
  57. package/lib/utils/image_plugins/mermaid.d.ts +3 -0
  58. package/lib/utils/image_plugins/mermaid.js +21 -0
  59. package/lib/utils/image_plugins/movie.d.ts +2 -0
  60. package/lib/utils/image_plugins/movie.js +3 -0
  61. package/lib/utils/image_plugins/source.d.ts +4 -0
  62. package/lib/utils/image_plugins/source.js +15 -0
  63. package/lib/utils/image_plugins/text_slide.d.ts +3 -0
  64. package/lib/utils/image_plugins/text_slide.js +12 -0
  65. package/lib/utils/image_plugins/type_guards.d.ts +6 -0
  66. package/lib/utils/image_plugins/type_guards.js +21 -0
  67. package/lib/utils/markdown.js +4 -1
  68. package/lib/utils/pdf.d.ts +8 -0
  69. package/lib/utils/pdf.js +75 -0
  70. package/lib/utils/preprocess.d.ts +58 -128
  71. package/lib/utils/preprocess.js +37 -37
  72. package/lib/utils/utils.d.ts +12 -0
  73. package/lib/utils/utils.js +34 -0
  74. package/package.json +13 -4
@@ -11,7 +11,8 @@ import { getUrlsIfNeeded, selectTemplate } from "../utils/inquirer.js";
11
11
  const main = async () => {
12
12
  const { o: outdir, b: basedir, action, v: verbose, i: interactive, s: filename, cache } = args;
13
13
  let { t: template } = args;
14
- let { u: urls } = args;
14
+ const { u: urls } = args;
15
+ const { llm_model, llm_agent } = args;
15
16
  const baseDirPath = getBaseDirPath(basedir);
16
17
  const outDirPath = getFullPath(baseDirPath, outdir ?? outDirName);
17
18
  const cacheDirPath = getFullPath(outDirPath, cache ?? cacheDirName);
@@ -38,12 +39,13 @@ const main = async () => {
38
39
  }
39
40
  }
40
41
  if (action === "scripting") {
42
+ const context = { outDirPath, templateName: template, urls, filename, cacheDirPath, llm_model, llm_agent };
41
43
  if (interactive) {
42
- await createMulmoScriptInteractively({ outDirPath, templateName: template, urls, filename, cacheDirPath });
44
+ await createMulmoScriptInteractively(context);
43
45
  }
44
46
  else {
45
- urls = await getUrlsIfNeeded(urls);
46
- await createMulmoScriptFromUrl({ urls, templateName: template, outDirPath, filename, cacheDirPath });
47
+ context.urls = await getUrlsIfNeeded(urls);
48
+ await createMulmoScriptFromUrl(context);
47
49
  }
48
50
  }
49
51
  else if (action === "prompt") {
@@ -1,3 +1,4 @@
1
1
  export * from "./mulmo_script.js";
2
2
  export * from "./mulmo_script_template.js";
3
3
  export * from "./mulmo_studio_context.js";
4
+ export * from "./mulmo_media_source.js";
@@ -1,3 +1,4 @@
1
1
  export * from "./mulmo_script.js";
2
2
  export * from "./mulmo_script_template.js";
3
3
  export * from "./mulmo_studio_context.js";
4
+ export * from "./mulmo_media_source.js";
@@ -0,0 +1,4 @@
1
+ import { MulmoMediaSource, MulmoStudioContext } from "../types/index.js";
2
+ export declare const MulmoMediaSourceMethods: {
3
+ getText(mediaSource: MulmoMediaSource, context: MulmoStudioContext): Promise<string | null>;
4
+ };
@@ -0,0 +1,21 @@
1
+ import fs from "fs";
2
+ import { getFullPath } from "../utils/file.js";
3
+ export const MulmoMediaSourceMethods = {
4
+ async getText(mediaSource, context) {
5
+ if (mediaSource.kind === "text") {
6
+ return mediaSource.text;
7
+ }
8
+ if (mediaSource.kind === "url") {
9
+ const res = await fetch(mediaSource.url);
10
+ if (!res.ok) {
11
+ throw new Error(`Failed to fetch media source: ${mediaSource.url}`);
12
+ }
13
+ return await res.text();
14
+ }
15
+ if (mediaSource.kind === "path") {
16
+ const path = getFullPath(context.fileDirs.mulmoFileDirPath, mediaSource.path);
17
+ return fs.readFileSync(path, "utf-8");
18
+ }
19
+ return null;
20
+ },
21
+ };
@@ -1,10 +1,5 @@
1
1
  import "dotenv/config";
2
- import { MulmoCanvasDimension, MulmoScript, MulmoBeat, SpeechOptions, Text2ImageProvider, MulmoImageParams, Text2SpeechProvider } from "../types/index.js";
3
- export type Text2ImageAgentInfo = {
4
- provider: Text2ImageProvider;
5
- agent: string;
6
- imageParams: MulmoImageParams;
7
- };
2
+ import { MulmoCanvasDimension, MulmoScript, MulmoBeat, SpeechOptions, Text2SpeechProvider, Text2ImageAgentInfo, BeatMediaType } from "../types/index.js";
8
3
  export declare const MulmoScriptMethods: {
9
4
  getPadding(script: MulmoScript): number;
10
5
  getCanvasSize(script: MulmoScript): MulmoCanvasDimension;
@@ -13,4 +8,5 @@ export declare const MulmoScriptMethods: {
13
8
  getTextSlideStyle(script: MulmoScript, beat: MulmoBeat): string;
14
9
  getSpeechOptions(script: MulmoScript, beat: MulmoBeat): SpeechOptions | undefined;
15
10
  getImageAgentInfo(script: MulmoScript): Text2ImageAgentInfo;
11
+ getImageType(_: MulmoScript, beat: MulmoBeat): BeatMediaType;
16
12
  };
@@ -1,12 +1,15 @@
1
1
  import "dotenv/config";
2
2
  import { text2ImageProviderSchema, text2SpeechProviderSchema, mulmoCanvasDimensionSchema } from "../types/schema.js";
3
3
  const defaultTextSlideStyles = [
4
- "body { margin: 40px; margin-top: 60px; color:#333; font-size: 48px }",
5
- "h1 { font-size: 60px; text-align: center }",
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
+ "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 }",
8
+ "h3 { font-size: 36px }",
6
9
  "ul { margin-left: 40px } ",
7
- "pre { margin-left: 40px; font-size: 32px }",
10
+ "pre { background: #eeeecc; font-size: 16px; padding:4px }",
8
11
  "p { margin-left: 40px }",
9
- "table { font-size: 40px; margin: auto; border: 1px solid gray; border-collapse: collapse }",
12
+ "table { font-size: 36px; margin: auto; border: 1px solid gray; border-collapse: collapse }",
10
13
  "th { border-bottom: 1px solid gray }",
11
14
  "td, th { padding: 8px }",
12
15
  "tr:nth-child(even) { background-color: #eee }",
@@ -30,7 +33,8 @@ export const MulmoScriptMethods = {
30
33
  const styles = script.textSlideParams?.cssStyles ?? defaultTextSlideStyles;
31
34
  // NOTES: Taking advantage of CSS override rule (you can redefine it to override)
32
35
  const extraStyles = beat.textSlideParams?.cssStyles ?? [];
33
- return [...styles, ...extraStyles].join("\n");
36
+ // This code allows us to support both string and array of strings for cssStyles
37
+ return [...[styles], ...[extraStyles]].flat().join("\n");
34
38
  },
35
39
  getSpeechOptions(script, beat) {
36
40
  return { ...script.speechParams.speakers[beat.speaker].speechOptions, ...beat.speechOptions };
@@ -48,4 +52,7 @@ export const MulmoScriptMethods = {
48
52
  imageParams: { ...defaultImageParams, ...script.imageParams },
49
53
  };
50
54
  },
55
+ getImageType(_, beat) {
56
+ return beat.image?.type == "movie" ? "movie" : "image";
57
+ },
51
58
  };
@@ -1,3 +1,3 @@
1
1
  import "dotenv/config";
2
2
  import { ScriptingParams } from "../types/index.js";
3
- export declare const createMulmoScriptInteractively: ({ outDirPath, cacheDirPath, filename, templateName, urls }: ScriptingParams) => Promise<void>;
3
+ export declare const createMulmoScriptInteractively: ({ outDirPath, cacheDirPath, filename, templateName, urls, llm_agent, llm_model }: ScriptingParams) => Promise<void>;
@@ -1,14 +1,19 @@
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
5
  import { openAIAgent } from "@graphai/openai_agent";
6
+ import { anthropicAgent } from "@graphai/anthropic_agent";
7
+ import { geminiAgent } from "@graphai/gemini_agent";
8
+ import { groqAgent } from "@graphai/groq_agent";
5
9
  import * as agents from "@graphai/vanilla";
6
10
  import { fileWriteAgent } from "@graphai/vanilla_node_agents";
7
11
  import { readTemplatePrompt, mkdir } from "../utils/file.js";
8
12
  import { browserlessCacheGenerator } from "../utils/filters.js";
9
13
  import { browserlessAgent } from "@graphai/browserless_agent";
10
14
  import validateMulmoScriptAgent from "../agents/validate_mulmo_script_agent.js";
11
- import { cliLoadingPlugin } from "../utils/plugins.js";
15
+ import { llmPair } from "../utils/utils.js";
16
+ // import { cliLoadingPlugin } from "../utils/plugins.js";
12
17
  const { default: __, ...vanillaAgents } = agents;
13
18
  const agentHeader = "\x1b[34m● \x1b[0m\x1b[1mAgent\x1b[0m:\x1b[0m";
14
19
  const graphDataForScraping = {
@@ -65,6 +70,15 @@ const graphData = {
65
70
  while: ":continue",
66
71
  },
67
72
  nodes: {
73
+ llmAgent: {
74
+ update: ":llmAgent",
75
+ },
76
+ llmModel: {
77
+ update: ":llmModel",
78
+ },
79
+ maxTokens: {
80
+ update: ":maxTokens",
81
+ },
68
82
  fileName: {
69
83
  update: ":fileName",
70
84
  },
@@ -73,7 +87,7 @@ const graphData = {
73
87
  },
74
88
  messages: {
75
89
  value: [],
76
- update: ":reply.llmAgent.messages",
90
+ update: ":reply.chatAgent.messages",
77
91
  },
78
92
  userInput: {
79
93
  agent: "textInputAgent",
@@ -87,6 +101,9 @@ const graphData = {
87
101
  inputs: {
88
102
  messages: ":messages",
89
103
  prompt: ":userInput.text",
104
+ llmAgent: ":llmAgent",
105
+ llmModel: ":llmModel",
106
+ maxTokens: ":maxTokens",
90
107
  },
91
108
  graph: {
92
109
  loop: {
@@ -97,10 +114,12 @@ const graphData = {
97
114
  value: 0,
98
115
  update: ":counter.add(1)",
99
116
  },
100
- llmAgent: {
101
- agent: "openAIAgent",
117
+ chatAgent: {
118
+ agent: ":llmAgent",
102
119
  params: {
103
- model: "gpt-4o",
120
+ model: ":llmModel",
121
+ stream: true,
122
+ max_tokens: ":maxTokens",
104
123
  },
105
124
  inputs: {
106
125
  messages: ":messages",
@@ -111,7 +130,7 @@ const graphData = {
111
130
  validateMulmoScriptAgent: {
112
131
  agent: "validateMulmoScriptAgent",
113
132
  inputs: {
114
- text: ":llmAgent.text.codeBlock()",
133
+ text: ":chatAgent.text.codeBlock()",
115
134
  },
116
135
  },
117
136
  continue: {
@@ -120,11 +139,15 @@ const graphData = {
120
139
  GraphAILogger.info("\n" + agentHeader + " \x1b[31mFailed to generate a valid script. Please try again.\n");
121
140
  return false;
122
141
  }
123
- return !!codeBlock && !isValid;
142
+ const result = !!codeBlock && !isValid;
143
+ if (result) {
144
+ GraphAILogger.info("\n" + agentHeader + " Generated script was broken. Retry generate a script.");
145
+ }
146
+ return result;
124
147
  },
125
148
  inputs: {
126
149
  counter: ":counter",
127
- codeBlock: ":llmAgent.text.codeBlock()",
150
+ codeBlock: ":chatAgent.text.codeBlock()",
128
151
  isValid: ":validateMulmoScriptAgent.isValid",
129
152
  },
130
153
  },
@@ -134,8 +157,8 @@ const graphData = {
134
157
  json: {
135
158
  agent: "copyAgent",
136
159
  inputs: {
137
- json: ":reply.llmAgent.text.codeBlock().jsonParse()",
138
- text: ":reply.llmAgent.text.codeBlock()",
160
+ json: ":reply.chatAgent.text.codeBlock().jsonParse()",
161
+ text: ":reply.chatAgent.text.codeBlock()",
139
162
  },
140
163
  },
141
164
  writeJSON: {
@@ -159,13 +182,6 @@ const graphData = {
159
182
  array: [[":json.json", "==", undefined], "&&", [":userInput.text", "!=", "/bye"]],
160
183
  },
161
184
  },
162
- agentResponse: {
163
- if: ":shouldResponse.result",
164
- agent: "consoleAgent",
165
- inputs: {
166
- text: "\n" + agentHeader + " ${:reply.llmAgent.text}\n",
167
- },
168
- },
169
185
  checkInput: {
170
186
  agent: "compareAgent",
171
187
  inputs: { array: [":userInput.text", "!=", "/bye"] },
@@ -197,11 +213,23 @@ const scrapeWebContent = async (urls, cacheDirPath) => {
197
213
  const prefixPrompt = "Here is the web content that can be used as reference material for the script:";
198
214
  return `\n\n${prefixPrompt}\n${result?.sourceText.text}`;
199
215
  };
200
- export const createMulmoScriptInteractively = async ({ outDirPath, cacheDirPath, filename, templateName, urls }) => {
216
+ export const createMulmoScriptInteractively = async ({ outDirPath, cacheDirPath, filename, templateName, urls, llm_agent, llm_model }) => {
201
217
  mkdir(outDirPath);
202
218
  // if urls is not empty, scrape web content and reference it in the prompt
203
219
  const webContentPrompt = urls.length > 0 ? await scrapeWebContent(urls, cacheDirPath) : "";
204
- const graph = new GraphAI(graphData, { ...vanillaAgents, openAIAgent, textInputAgent, fileWriteAgent, validateMulmoScriptAgent });
220
+ const { agent, model, max_tokens } = llmPair(llm_agent, llm_model);
221
+ GraphAILogger.log({ agent, model, max_tokens });
222
+ const streamAgentFilter = streamAgentFilterGenerator((context, data) => {
223
+ process.stdout.write(String(data));
224
+ });
225
+ const agentFilters = [
226
+ {
227
+ name: "streamAgentFilter",
228
+ agent: streamAgentFilter,
229
+ nodeIds: ["chatAgent"],
230
+ },
231
+ ];
232
+ const graph = new GraphAI(graphData, { ...vanillaAgents, anthropicAgent, geminiAgent, groqAgent, openAIAgent, textInputAgent, fileWriteAgent, validateMulmoScriptAgent }, { agentFilters });
205
233
  const prompt = readTemplatePrompt(templateName);
206
234
  graph.injectValue("messages", [
207
235
  {
@@ -211,7 +239,20 @@ export const createMulmoScriptInteractively = async ({ outDirPath, cacheDirPath,
211
239
  ]);
212
240
  graph.injectValue("outdir", outDirPath);
213
241
  graph.injectValue("fileName", filename);
214
- graph.registerCallback(cliLoadingPlugin({ nodeId: "reply", message: "Loading..." }));
242
+ graph.injectValue("llmAgent", agent);
243
+ graph.injectValue("llmModel", model);
244
+ graph.injectValue("maxTokens", max_tokens);
245
+ graph.registerCallback(({ nodeId, state }) => {
246
+ if (nodeId === "chatAgent") {
247
+ if (state === "executing") {
248
+ process.stdout.write(String("\n" + agentHeader + " "));
249
+ }
250
+ if (state === "completed") {
251
+ process.stdout.write("\n\n");
252
+ }
253
+ }
254
+ });
255
+ // graph.registerCallback(cliLoadingPlugin({ nodeId: "reply", message: "Loading..." }));
215
256
  GraphAILogger.info(`${agentHeader} Hi! What topic would you like me to generate about?\n`);
216
257
  await graph.run();
217
258
  };
@@ -1 +1,2 @@
1
1
  export * from "./type.js";
2
+ export * from "./schema.js";
@@ -1 +1,2 @@
1
1
  export * from "./type.js";
2
+ export * from "./schema.js";