mulmocast 0.0.2 → 0.0.4

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 (80) 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/translate.js +22 -9
  17. package/lib/agents/combine_audio_files_agent.js +13 -22
  18. package/lib/cli/args.d.ts +3 -1
  19. package/lib/cli/args.js +49 -34
  20. package/lib/cli/cli.d.ts +15 -0
  21. package/lib/cli/cli.js +44 -47
  22. package/lib/cli/run.d.ts +1 -0
  23. package/lib/cli/run.js +2 -0
  24. package/lib/cli/tool-args.d.ts +2 -0
  25. package/lib/cli/tool-args.js +12 -2
  26. package/lib/cli/tool-cli.js +6 -4
  27. package/lib/methods/index.d.ts +1 -0
  28. package/lib/methods/index.js +1 -0
  29. package/lib/methods/mulmo_media_source.d.ts +4 -0
  30. package/lib/methods/mulmo_media_source.js +21 -0
  31. package/lib/methods/mulmo_script.d.ts +2 -6
  32. package/lib/methods/mulmo_script.js +12 -5
  33. package/lib/tools/create_mulmo_script_interactively.d.ts +1 -1
  34. package/lib/tools/create_mulmo_script_interactively.js +61 -20
  35. package/lib/types/index.d.ts +1 -0
  36. package/lib/types/index.js +1 -0
  37. package/lib/types/schema.d.ts +3626 -3162
  38. package/lib/types/schema.js +75 -41
  39. package/lib/types/type.d.ts +28 -1
  40. package/lib/utils/const.d.ts +2 -0
  41. package/lib/utils/const.js +2 -0
  42. package/lib/utils/file.d.ts +4 -1
  43. package/lib/utils/file.js +15 -1
  44. package/lib/utils/filters.js +1 -1
  45. package/lib/utils/image_plugins/chart.d.ts +3 -0
  46. package/lib/utils/image_plugins/chart.js +18 -0
  47. package/lib/utils/image_plugins/image.d.ts +2 -0
  48. package/lib/utils/image_plugins/image.js +3 -0
  49. package/lib/utils/image_plugins/index.d.ts +7 -0
  50. package/lib/utils/image_plugins/index.js +7 -0
  51. package/lib/utils/image_plugins/markdown.d.ts +3 -0
  52. package/lib/utils/image_plugins/markdown.js +11 -0
  53. package/lib/utils/image_plugins/mermaid.d.ts +3 -0
  54. package/lib/utils/image_plugins/mermaid.js +21 -0
  55. package/lib/utils/image_plugins/movie.d.ts +2 -0
  56. package/lib/utils/image_plugins/movie.js +3 -0
  57. package/lib/utils/image_plugins/source.d.ts +4 -0
  58. package/lib/utils/image_plugins/source.js +15 -0
  59. package/lib/utils/image_plugins/text_slide.d.ts +3 -0
  60. package/lib/utils/image_plugins/text_slide.js +12 -0
  61. package/lib/utils/image_plugins/type_guards.d.ts +6 -0
  62. package/lib/utils/image_plugins/type_guards.js +21 -0
  63. package/lib/utils/markdown.js +4 -1
  64. package/lib/utils/pdf.d.ts +8 -0
  65. package/lib/utils/pdf.js +75 -0
  66. package/lib/utils/preprocess.d.ts +58 -128
  67. package/lib/utils/preprocess.js +37 -37
  68. package/lib/utils/utils.d.ts +12 -0
  69. package/lib/utils/utils.js +34 -0
  70. package/package.json +21 -12
  71. package/lib/tools/seed.d.ts +0 -3
  72. package/lib/tools/seed.js +0 -201
  73. package/lib/tools/seed_from_url.d.ts +0 -3
  74. package/lib/tools/seed_from_url.js +0 -178
  75. package/lib/tools/seed_from_url2.d.ts +0 -3
  76. package/lib/tools/seed_from_url2.js +0 -154
  77. package/lib/utils/image_preprocess.d.ts +0 -14
  78. package/lib/utils/image_preprocess.js +0 -52
  79. package/lib/utils/text_hash.d.ts +0 -1
  80. package/lib/utils/text_hash.js +0 -4
package/lib/cli/cli.js CHANGED
@@ -3,34 +3,45 @@ import "dotenv/config";
3
3
  import fs from "fs";
4
4
  import path from "path";
5
5
  import { GraphAILogger } from "graphai";
6
- import { args } from "./args.js";
6
+ import { getArgs } from "./args.js";
7
7
  import { createOrUpdateStudioData } from "../utils/preprocess.js";
8
8
  import { outDirName, imageDirName, audioDirName } from "../utils/const.js";
9
- import { MulmoScriptMethods } from "../methods/index.js";
10
- import { translate } from "../actions/translate.js";
11
- import { images } from "../actions/images.js";
12
- import { audio } from "../actions/audio.js";
13
- import { movie } from "../actions/movie.js";
14
- import { getBaseDirPath, getFullPath, readMulmoScriptFile, fetchMulmoScriptFile } from "../utils/file.js";
15
- import { mulmoScriptSchema } from "../types/schema.js";
16
- const isHttp = (fileOrUrl) => {
17
- return /^https?:\/\//.test(fileOrUrl);
18
- };
19
- const getFileObject = () => {
20
- const { basedir, file, outdir, imagedir, audiodir } = args;
9
+ import { translate, audio, images, movie, pdf } from "../actions/index.js";
10
+ import { getBaseDirPath, getFullPath, readMulmoScriptFile, fetchMulmoScriptFile, getOutputStudioFilePath } from "../utils/file.js";
11
+ import { isHttp } from "../utils/utils.js";
12
+ export const getFileObject = (_args) => {
13
+ const { basedir, file, outdir, imagedir, audiodir } = _args;
21
14
  const baseDirPath = getBaseDirPath(basedir);
22
15
  const fileOrUrl = file ?? "";
16
+ const fileName = path.parse(fileOrUrl).name;
23
17
  const isHttpPath = isHttp(fileOrUrl);
24
18
  const mulmoFilePath = isHttpPath ? "" : getFullPath(baseDirPath, fileOrUrl);
25
19
  const mulmoFileDirPath = path.dirname(isHttpPath ? baseDirPath : mulmoFilePath);
26
20
  const outDirPath = getFullPath(baseDirPath, outdir ?? outDirName);
27
21
  const imageDirPath = getFullPath(outDirPath, imagedir ?? imageDirName);
28
22
  const audioDirPath = getFullPath(outDirPath, audiodir ?? audioDirName);
29
- return { baseDirPath, mulmoFilePath, mulmoFileDirPath, outDirPath, imageDirPath, audioDirPath, isHttpPath, fileOrUrl };
23
+ const outputStudioFilePath = getOutputStudioFilePath(outDirPath, fileName);
24
+ return { baseDirPath, mulmoFilePath, mulmoFileDirPath, outDirPath, imageDirPath, audioDirPath, isHttpPath, fileOrUrl, outputStudioFilePath, fileName };
25
+ };
26
+ const fetchScript = async (isHttpPath, mulmoFilePath, fileOrUrl) => {
27
+ if (isHttpPath) {
28
+ const res = await fetchMulmoScriptFile(fileOrUrl);
29
+ if (!res.result || !res.script) {
30
+ GraphAILogger.info(`ERROR: HTTP error! ${res.status} ${fileOrUrl}`);
31
+ process.exit(1);
32
+ }
33
+ return res.script;
34
+ }
35
+ if (!fs.existsSync(mulmoFilePath)) {
36
+ GraphAILogger.info(`ERROR: File not exists ${mulmoFilePath}`);
37
+ process.exit(1);
38
+ }
39
+ return readMulmoScriptFile(mulmoFilePath, "ERROR: File does not exist " + mulmoFilePath).mulmoData;
30
40
  };
31
- const main = async () => {
32
- const files = getFileObject();
33
- const { mulmoFilePath, isHttpPath, fileOrUrl } = files;
41
+ export const main = async () => {
42
+ const args = getArgs();
43
+ const files = getFileObject(args);
44
+ const { mulmoFilePath, isHttpPath, fileOrUrl, fileName, outputStudioFilePath } = files;
34
45
  if (args.v) {
35
46
  GraphAILogger.info(files);
36
47
  }
@@ -39,37 +50,20 @@ const main = async () => {
39
50
  GraphAILogger.setLevelEnabled("log", false);
40
51
  GraphAILogger.setLevelEnabled("warn", false);
41
52
  }
42
- const { action, force } = args;
43
- const readData = await (async () => {
44
- if (isHttpPath) {
45
- const res = await fetchMulmoScriptFile(fileOrUrl);
46
- if (!res.result || !res.script) {
47
- GraphAILogger.info(`ERROR: HTTP error! ${res.status} ${fileOrUrl}`);
48
- process.exit(1);
49
- }
50
- return {
51
- mulmoData: res.script,
52
- fileName: path.parse(fileOrUrl).name,
53
- };
53
+ const { action, force, pdf_mode, pdf_size } = args;
54
+ const mulmoScript = await fetchScript(isHttpPath, mulmoFilePath, fileOrUrl);
55
+ // Create or update MulmoStudio file with MulmoScript
56
+ const currentStudio = readMulmoScriptFile(outputStudioFilePath);
57
+ const studio = (() => {
58
+ try {
59
+ // validate mulmoStudioSchema. skip if __test_invalid__ is true
60
+ return createOrUpdateStudioData(mulmoScript, currentStudio?.mulmoData, fileName);
54
61
  }
55
- if (!fs.existsSync(mulmoFilePath)) {
56
- GraphAILogger.info("ERROR: File not exists " + mulmoFilePath);
62
+ catch (error) {
63
+ GraphAILogger.info(`Error: invalid MulmoScript Schema: ${isHttpPath ? fileOrUrl : mulmoFilePath} \n ${error}`);
57
64
  process.exit(1);
58
65
  }
59
- return readMulmoScriptFile(mulmoFilePath, "ERROR: File does not exist " + mulmoFilePath);
60
66
  })();
61
- const { mulmoData: mulmoScript, fileName } = readData;
62
- // validate mulmoStudioSchema. skip if __test_invalid__ is true
63
- try {
64
- if (!mulmoScript?.__test_invalid__) {
65
- mulmoScriptSchema.parse(mulmoScript);
66
- }
67
- }
68
- catch (error) {
69
- GraphAILogger.info(`Error: invalid MulmoScript Schema: ${isHttpPath ? fileOrUrl : mulmoFilePath} \n ${error}`);
70
- process.exit(1);
71
- }
72
- const studio = createOrUpdateStudioData(mulmoScript, fileName, files);
73
67
  const context = {
74
68
  studio,
75
69
  fileDirs: files,
@@ -79,15 +73,18 @@ const main = async () => {
79
73
  await translate(context);
80
74
  }
81
75
  if (action === "audio") {
82
- await audio(context, MulmoScriptMethods.getSpeechProvider(studio.script) === "nijivoice" ? 1 : 8);
76
+ await audio(context);
83
77
  }
84
78
  if (action === "images") {
85
79
  await images(context);
86
80
  }
87
81
  if (action === "movie") {
88
- await audio(context, MulmoScriptMethods.getSpeechProvider(studio.script) === "nijivoice" ? 1 : 8);
82
+ await audio(context);
89
83
  await images(context);
90
84
  await movie(context);
91
85
  }
86
+ if (action === "pdf") {
87
+ await images(context);
88
+ await pdf(context, pdf_mode, pdf_size);
89
+ }
92
90
  };
93
- main();
@@ -0,0 +1 @@
1
+ export {};
package/lib/cli/run.js ADDED
@@ -0,0 +1,2 @@
1
+ import { main } from "./cli.js";
2
+ main();
@@ -8,6 +8,8 @@ export declare const args: {
8
8
  t: string | undefined;
9
9
  c: string | undefined;
10
10
  s: string;
11
+ llm_agent: string | undefined;
12
+ llm_model: string | undefined;
11
13
  _: (string | number)[];
12
14
  $0: string;
13
15
  };
@@ -1,9 +1,8 @@
1
1
  import yargs from "yargs";
2
2
  import { hideBin } from "yargs/helpers";
3
3
  import { commonOptions } from "./common.js";
4
- import { GraphAILogger } from "graphai";
5
4
  import { getAvailableTemplates } from "../utils/file.js";
6
- GraphAILogger.setLevelEnabled("error", false);
5
+ import { llmAgents } from "../utils/utils.js";
7
6
  const availableTemplateNames = getAvailableTemplates().map((template) => template.filename);
8
7
  export const args = commonOptions(yargs(hideBin(process.argv)))
9
8
  .scriptName("mulmo-tool")
@@ -40,6 +39,17 @@ export const args = commonOptions(yargs(hideBin(process.argv)))
40
39
  demandOption: false,
41
40
  default: "script",
42
41
  type: "string",
42
+ })
43
+ .option("llm_agent", {
44
+ description: "llm agent",
45
+ demandOption: false,
46
+ choices: llmAgents,
47
+ type: "string",
48
+ })
49
+ .option("llm_model", {
50
+ description: "llm model",
51
+ demandOption: false,
52
+ type: "string",
43
53
  })
44
54
  .command("$0 <action>", "Run mulmocast tool", (yargs) => {
45
55
  return yargs.positional("action", {
@@ -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";