mulmocast-preprocessor 0.1.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/README.md +160 -0
- package/lib/actions/index.d.ts +1 -0
- package/lib/actions/index.js +3 -0
- package/lib/cli/commands/process.d.ts +9 -0
- package/lib/cli/commands/process.js +32 -0
- package/lib/cli/commands/profiles.d.ts +4 -0
- package/lib/cli/commands/profiles.js +32 -0
- package/lib/cli/index.d.ts +2 -0
- package/lib/cli/index.js +44 -0
- package/lib/core/filter.d.ts +14 -0
- package/lib/core/filter.js +26 -0
- package/lib/core/process.d.ts +7 -0
- package/lib/core/process.js +16 -0
- package/lib/core/profiles.d.ts +5 -0
- package/lib/core/profiles.js +38 -0
- package/lib/core/variant.d.ts +6 -0
- package/lib/core/variant.js +26 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +7 -0
- package/lib/types/index.d.ts +1946 -0
- package/lib/types/index.js +42 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# mulmocast-preprocessor
|
|
2
|
+
|
|
3
|
+
Preprocessor for MulmoScript that enables generating multiple variations (full, summary, teaser, etc.) from a single script.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install mulmocast-preprocessor
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Profile-based variants**: Generate different versions (summary, teaser) from one script
|
|
14
|
+
- **Section filtering**: Extract beats by section
|
|
15
|
+
- **Tag filtering**: Extract beats by tags
|
|
16
|
+
- **Profile listing**: List available profiles with beat counts
|
|
17
|
+
- **CLI tool**: Command-line interface for processing scripts
|
|
18
|
+
|
|
19
|
+
## CLI Usage
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Process script with profile
|
|
23
|
+
mulmocast-preprocessor script.json --profile summary -o summary.json
|
|
24
|
+
|
|
25
|
+
# Output to stdout (for piping)
|
|
26
|
+
mulmocast-preprocessor script.json --profile teaser
|
|
27
|
+
|
|
28
|
+
# List available profiles
|
|
29
|
+
mulmocast-preprocessor profiles script.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### CLI Options
|
|
33
|
+
|
|
34
|
+
| Option | Alias | Description |
|
|
35
|
+
|--------|-------|-------------|
|
|
36
|
+
| `--profile <name>` | `-p` | Profile name to apply (default: "default") |
|
|
37
|
+
| `--output <path>` | `-o` | Output file path (default: stdout) |
|
|
38
|
+
| `--help` | `-h` | Show help |
|
|
39
|
+
| `--version` | `-v` | Show version |
|
|
40
|
+
|
|
41
|
+
## Programmatic Usage
|
|
42
|
+
|
|
43
|
+
### Basic Example
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { processScript, listProfiles, applyProfile } from "mulmocast-preprocessor";
|
|
47
|
+
import type { ExtendedScript } from "mulmocast-preprocessor";
|
|
48
|
+
|
|
49
|
+
const script: ExtendedScript = {
|
|
50
|
+
title: "My Presentation",
|
|
51
|
+
beats: [
|
|
52
|
+
{
|
|
53
|
+
text: "Full introduction text here...",
|
|
54
|
+
variants: {
|
|
55
|
+
summary: { text: "Brief intro" },
|
|
56
|
+
teaser: { skip: true }
|
|
57
|
+
},
|
|
58
|
+
meta: { section: "intro", tags: ["important"] }
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
text: "Main content...",
|
|
62
|
+
meta: { section: "main", tags: ["core"] }
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// List available profiles
|
|
68
|
+
const profiles = listProfiles(script);
|
|
69
|
+
// [{ name: "default", beatCount: 2 }, { name: "summary", beatCount: 2 }, { name: "teaser", beatCount: 1, skippedCount: 1 }]
|
|
70
|
+
|
|
71
|
+
// Generate summary version
|
|
72
|
+
const summary = applyProfile(script, "summary");
|
|
73
|
+
// First beat's text is replaced with "Brief intro"
|
|
74
|
+
|
|
75
|
+
// Process with multiple options
|
|
76
|
+
const result = processScript(script, {
|
|
77
|
+
profile: "summary",
|
|
78
|
+
section: "intro"
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## API
|
|
83
|
+
|
|
84
|
+
### `processScript(script, options)`
|
|
85
|
+
|
|
86
|
+
Main processing function that applies profile and filters.
|
|
87
|
+
|
|
88
|
+
**Parameters:**
|
|
89
|
+
- `script: ExtendedScript` - Input script with variants/meta
|
|
90
|
+
- `options: ProcessOptions` - Processing options
|
|
91
|
+
- `profile?: string` - Profile name to apply
|
|
92
|
+
- `section?: string` - Filter by section
|
|
93
|
+
- `tags?: string[]` - Filter by tags (OR logic)
|
|
94
|
+
|
|
95
|
+
**Returns:** `MulmoScript` - Standard MulmoScript with variants/meta stripped
|
|
96
|
+
|
|
97
|
+
### `applyProfile(script, profileName)`
|
|
98
|
+
|
|
99
|
+
Apply a profile to the script, replacing text/image and skipping marked beats.
|
|
100
|
+
|
|
101
|
+
**Parameters:**
|
|
102
|
+
- `script: ExtendedScript` - Input script
|
|
103
|
+
- `profileName: string` - Profile name
|
|
104
|
+
|
|
105
|
+
**Returns:** `MulmoScript` - Processed script
|
|
106
|
+
|
|
107
|
+
### `listProfiles(script)`
|
|
108
|
+
|
|
109
|
+
Get list of available profiles from script.
|
|
110
|
+
|
|
111
|
+
**Parameters:**
|
|
112
|
+
- `script: ExtendedScript` - Input script
|
|
113
|
+
|
|
114
|
+
**Returns:** `ProfileInfo[]` - Array of profile info with beat counts
|
|
115
|
+
|
|
116
|
+
### `filterBySection(script, section)`
|
|
117
|
+
|
|
118
|
+
Filter beats by section.
|
|
119
|
+
|
|
120
|
+
### `filterByTags(script, tags)`
|
|
121
|
+
|
|
122
|
+
Filter beats by tags (extracts beats that have any of the specified tags).
|
|
123
|
+
|
|
124
|
+
## Extended Schema
|
|
125
|
+
|
|
126
|
+
### ExtendedBeat
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
interface ExtendedBeat extends MulmoBeat {
|
|
130
|
+
variants?: Record<string, BeatVariant>;
|
|
131
|
+
meta?: BeatMeta;
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### BeatVariant
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
interface BeatVariant {
|
|
139
|
+
text?: string; // Override text
|
|
140
|
+
skip?: boolean; // Skip this beat
|
|
141
|
+
image?: MulmoImage; // Override image
|
|
142
|
+
imagePrompt?: string; // Override imagePrompt
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### BeatMeta
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
interface BeatMeta {
|
|
150
|
+
tags?: string[];
|
|
151
|
+
section?: string;
|
|
152
|
+
context?: string;
|
|
153
|
+
keywords?: string[];
|
|
154
|
+
expectedQuestions?: string[];
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const preprocessorVersion = "0.0.1";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { GraphAILogger } from "graphai";
|
|
3
|
+
import { processScript } from "../../core/process.js";
|
|
4
|
+
/**
|
|
5
|
+
* Process script with profile and output result
|
|
6
|
+
*/
|
|
7
|
+
export const processCommand = (scriptPath, options) => {
|
|
8
|
+
try {
|
|
9
|
+
const content = readFileSync(scriptPath, "utf-8");
|
|
10
|
+
const script = JSON.parse(content);
|
|
11
|
+
const result = processScript(script, {
|
|
12
|
+
profile: options.profile,
|
|
13
|
+
});
|
|
14
|
+
const output = JSON.stringify(result, null, 2);
|
|
15
|
+
if (options.output) {
|
|
16
|
+
writeFileSync(options.output, output);
|
|
17
|
+
GraphAILogger.info(`Output written to ${options.output}`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
process.stdout.write(output + "\n");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (error instanceof Error) {
|
|
25
|
+
GraphAILogger.error(`Error: ${error.message}`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
GraphAILogger.error("Unknown error occurred");
|
|
29
|
+
}
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { GraphAILogger } from "graphai";
|
|
3
|
+
import { listProfiles } from "../../core/profiles.js";
|
|
4
|
+
/**
|
|
5
|
+
* List available profiles in script
|
|
6
|
+
*/
|
|
7
|
+
export const profilesCommand = (scriptPath) => {
|
|
8
|
+
try {
|
|
9
|
+
const content = readFileSync(scriptPath, "utf-8");
|
|
10
|
+
const script = JSON.parse(content);
|
|
11
|
+
const profiles = listProfiles(script);
|
|
12
|
+
GraphAILogger.log("\nAvailable profiles:");
|
|
13
|
+
profiles.forEach((profile) => {
|
|
14
|
+
const displayName = profile.displayName ? ` (${profile.displayName})` : "";
|
|
15
|
+
const skipped = profile.skippedCount > 0 ? `, ${profile.skippedCount} skipped` : "";
|
|
16
|
+
GraphAILogger.log(` ${profile.name}${displayName}: ${profile.beatCount} beats${skipped}`);
|
|
17
|
+
if (profile.description) {
|
|
18
|
+
GraphAILogger.log(` ${profile.description}`);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
GraphAILogger.log("");
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (error instanceof Error) {
|
|
25
|
+
GraphAILogger.error(`Error: ${error.message}`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
GraphAILogger.error("Unknown error occurred");
|
|
29
|
+
}
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
};
|
package/lib/cli/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import yargs from "yargs";
|
|
3
|
+
import { hideBin } from "yargs/helpers";
|
|
4
|
+
import { processCommand } from "./commands/process.js";
|
|
5
|
+
import { profilesCommand } from "./commands/profiles.js";
|
|
6
|
+
yargs(hideBin(process.argv))
|
|
7
|
+
.command("$0 <script>", "Process MulmoScript with profile", (builder) => builder
|
|
8
|
+
.positional("script", {
|
|
9
|
+
describe: "Path to MulmoScript JSON file",
|
|
10
|
+
type: "string",
|
|
11
|
+
demandOption: true,
|
|
12
|
+
})
|
|
13
|
+
.option("profile", {
|
|
14
|
+
alias: "p",
|
|
15
|
+
describe: "Profile name to apply",
|
|
16
|
+
type: "string",
|
|
17
|
+
default: "default",
|
|
18
|
+
})
|
|
19
|
+
.option("output", {
|
|
20
|
+
alias: "o",
|
|
21
|
+
describe: "Output file path (default: stdout)",
|
|
22
|
+
type: "string",
|
|
23
|
+
}), (argv) => {
|
|
24
|
+
processCommand(argv.script, {
|
|
25
|
+
profile: argv.profile,
|
|
26
|
+
output: argv.output,
|
|
27
|
+
});
|
|
28
|
+
})
|
|
29
|
+
.command("profiles <script>", "List available profiles in script", (builder) => builder.positional("script", {
|
|
30
|
+
describe: "Path to MulmoScript JSON file",
|
|
31
|
+
type: "string",
|
|
32
|
+
demandOption: true,
|
|
33
|
+
}), (argv) => {
|
|
34
|
+
profilesCommand(argv.script);
|
|
35
|
+
})
|
|
36
|
+
.example("$0 script.json --profile summary -o summary.json", "Apply summary profile and save to file")
|
|
37
|
+
.example("$0 script.json -p teaser", "Apply teaser profile and output to stdout")
|
|
38
|
+
.example("$0 profiles script.json", "List all available profiles")
|
|
39
|
+
.help()
|
|
40
|
+
.alias("h", "help")
|
|
41
|
+
.version()
|
|
42
|
+
.alias("v", "version")
|
|
43
|
+
.strict()
|
|
44
|
+
.parse();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { MulmoScript } from "mulmocast";
|
|
2
|
+
import type { ExtendedScript } from "../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Filter beats by section
|
|
5
|
+
*/
|
|
6
|
+
export declare const filterBySection: (script: ExtendedScript, section: string) => MulmoScript;
|
|
7
|
+
/**
|
|
8
|
+
* Filter beats by tags (extract beats that have any of the specified tags)
|
|
9
|
+
*/
|
|
10
|
+
export declare const filterByTags: (script: ExtendedScript, tags: string[]) => MulmoScript;
|
|
11
|
+
/**
|
|
12
|
+
* Strip variants and meta fields, converting to standard MulmoScript
|
|
13
|
+
*/
|
|
14
|
+
export declare const stripExtendedFields: (script: ExtendedScript) => MulmoScript;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const stripBeatExtendedFields = (beat) => {
|
|
2
|
+
const { variants: __variants, meta: __meta, ...baseBeat } = beat;
|
|
3
|
+
return baseBeat;
|
|
4
|
+
};
|
|
5
|
+
const filterBeats = (script, predicate) => {
|
|
6
|
+
const { outputProfiles: __outputProfiles, ...baseScript } = script;
|
|
7
|
+
return {
|
|
8
|
+
...baseScript,
|
|
9
|
+
beats: script.beats.filter(predicate).map(stripBeatExtendedFields),
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Filter beats by section
|
|
14
|
+
*/
|
|
15
|
+
export const filterBySection = (script, section) => filterBeats(script, (beat) => beat.meta?.section === section);
|
|
16
|
+
/**
|
|
17
|
+
* Filter beats by tags (extract beats that have any of the specified tags)
|
|
18
|
+
*/
|
|
19
|
+
export const filterByTags = (script, tags) => {
|
|
20
|
+
const tagSet = new Set(tags);
|
|
21
|
+
return filterBeats(script, (beat) => (beat.meta?.tags ?? []).some((tag) => tagSet.has(tag)));
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Strip variants and meta fields, converting to standard MulmoScript
|
|
25
|
+
*/
|
|
26
|
+
export const stripExtendedFields = (script) => filterBeats(script, () => true);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MulmoScript } from "mulmocast";
|
|
2
|
+
import type { ExtendedScript, ProcessOptions } from "../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Main processing function
|
|
5
|
+
* Applies profile and filters in a single call
|
|
6
|
+
*/
|
|
7
|
+
export declare const processScript: (script: ExtendedScript, options?: ProcessOptions) => MulmoScript;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { applyProfile } from "./variant.js";
|
|
2
|
+
import { filterBySection, filterByTags, stripExtendedFields } from "./filter.js";
|
|
3
|
+
const toExtendedScript = (script) => ({
|
|
4
|
+
...script,
|
|
5
|
+
beats: script.beats.map((beat) => ({ ...beat })),
|
|
6
|
+
});
|
|
7
|
+
/**
|
|
8
|
+
* Main processing function
|
|
9
|
+
* Applies profile and filters in a single call
|
|
10
|
+
*/
|
|
11
|
+
export const processScript = (script, options = {}) => {
|
|
12
|
+
const afterProfile = options.profile && options.profile !== "default" ? applyProfile(script, options.profile) : stripExtendedFields(script);
|
|
13
|
+
const afterSection = options.section ? filterBySection(toExtendedScript(afterProfile), options.section) : afterProfile;
|
|
14
|
+
const afterTags = options.tags && options.tags.length > 0 ? filterByTags(toExtendedScript(afterSection), options.tags) : afterSection;
|
|
15
|
+
return afterTags;
|
|
16
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get list of available profiles from script
|
|
3
|
+
*/
|
|
4
|
+
export const listProfiles = (script) => {
|
|
5
|
+
const profileNames = new Set(["default"]);
|
|
6
|
+
script.beats
|
|
7
|
+
.filter((beat) => beat.variants)
|
|
8
|
+
.flatMap((beat) => Object.keys(beat.variants))
|
|
9
|
+
.forEach((name) => profileNames.add(name));
|
|
10
|
+
const buildProfileInfo = (profileName) => {
|
|
11
|
+
const outputProfile = script.outputProfiles?.[profileName];
|
|
12
|
+
const { beatCount, skippedCount } = profileName === "default"
|
|
13
|
+
? { beatCount: script.beats.length, skippedCount: 0 }
|
|
14
|
+
: script.beats.reduce((acc, beat) => {
|
|
15
|
+
const isSkipped = beat.variants?.[profileName]?.skip === true;
|
|
16
|
+
return {
|
|
17
|
+
beatCount: acc.beatCount + (isSkipped ? 0 : 1),
|
|
18
|
+
skippedCount: acc.skippedCount + (isSkipped ? 1 : 0),
|
|
19
|
+
};
|
|
20
|
+
}, { beatCount: 0, skippedCount: 0 });
|
|
21
|
+
return {
|
|
22
|
+
name: profileName,
|
|
23
|
+
displayName: outputProfile?.name,
|
|
24
|
+
description: outputProfile?.description,
|
|
25
|
+
beatCount,
|
|
26
|
+
skippedCount,
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
return Array.from(profileNames)
|
|
30
|
+
.map(buildProfileInfo)
|
|
31
|
+
.sort((a, b) => {
|
|
32
|
+
if (a.name === "default")
|
|
33
|
+
return -1;
|
|
34
|
+
if (b.name === "default")
|
|
35
|
+
return 1;
|
|
36
|
+
return a.name.localeCompare(b.name);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MulmoScript } from "mulmocast";
|
|
2
|
+
import type { ExtendedScript } from "../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Apply profile to script and return standard MulmoScript
|
|
5
|
+
*/
|
|
6
|
+
export declare const applyProfile: (script: ExtendedScript, profileName: string) => MulmoScript;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply profile variant to a single beat
|
|
3
|
+
* @returns Processed beat, or null if skip is set
|
|
4
|
+
*/
|
|
5
|
+
const applyVariantToBeat = (beat, profileName) => {
|
|
6
|
+
const variant = beat.variants?.[profileName];
|
|
7
|
+
if (variant?.skip) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const { variants: __variants, meta: __meta, ...baseBeat } = beat;
|
|
11
|
+
if (!variant) {
|
|
12
|
+
return baseBeat;
|
|
13
|
+
}
|
|
14
|
+
const { skip: __skip, ...overrides } = variant;
|
|
15
|
+
return { ...baseBeat, ...overrides };
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Apply profile to script and return standard MulmoScript
|
|
19
|
+
*/
|
|
20
|
+
export const applyProfile = (script, profileName) => {
|
|
21
|
+
const { outputProfiles: __outputProfiles, ...baseScript } = script;
|
|
22
|
+
return {
|
|
23
|
+
...baseScript,
|
|
24
|
+
beats: script.beats.map((beat) => applyVariantToBeat(beat, profileName)).filter((beat) => beat !== null),
|
|
25
|
+
};
|
|
26
|
+
};
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { processScript } from "./core/process.js";
|
|
2
|
+
export { applyProfile } from "./core/variant.js";
|
|
3
|
+
export { filterBySection, filterByTags, stripExtendedFields } from "./core/filter.js";
|
|
4
|
+
export { listProfiles } from "./core/profiles.js";
|
|
5
|
+
export type { BeatVariant, BeatMeta, ExtendedBeat, ExtendedScript, OutputProfile, ProcessOptions, ProfileInfo } from "./types/index.js";
|
|
6
|
+
export { beatVariantSchema, beatMetaSchema, extendedBeatSchema, extendedScriptSchema, outputProfileSchema } from "./types/index.js";
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Core API
|
|
2
|
+
export { processScript } from "./core/process.js";
|
|
3
|
+
export { applyProfile } from "./core/variant.js";
|
|
4
|
+
export { filterBySection, filterByTags, stripExtendedFields } from "./core/filter.js";
|
|
5
|
+
export { listProfiles } from "./core/profiles.js";
|
|
6
|
+
// Schemas (for validation)
|
|
7
|
+
export { beatVariantSchema, beatMetaSchema, extendedBeatSchema, extendedScriptSchema, outputProfileSchema } from "./types/index.js";
|