agent-screenplay 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +141 -2
- package/assets/editor/index.html +536 -0
- package/assets/fonts/Inter-Bold.ttf +0 -0
- package/assets/fonts/Inter-LICENSE.txt +92 -0
- package/assets/fonts/Inter-Medium.ttf +0 -0
- package/assets/fonts/Inter-Regular.ttf +0 -0
- package/assets/fonts/Inter-SemiBold.ttf +0 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +163 -0
- package/dist/cli.js.map +1 -0
- package/dist/core.d.ts +16 -0
- package/dist/core.js +73 -0
- package/dist/core.js.map +1 -0
- package/dist/direct/plan.d.ts +100 -0
- package/dist/direct/plan.js +274 -0
- package/dist/direct/plan.js.map +1 -0
- package/dist/drivers/browser.d.ts +9 -0
- package/dist/drivers/browser.js +44 -0
- package/dist/drivers/browser.js.map +1 -0
- package/dist/drivers/desktop.d.ts +53 -0
- package/dist/drivers/desktop.js +650 -0
- package/dist/drivers/desktop.js.map +1 -0
- package/dist/drivers/pace.d.ts +11 -0
- package/dist/drivers/pace.js +44 -0
- package/dist/drivers/pace.js.map +1 -0
- package/dist/drivers/web.d.ts +37 -0
- package/dist/drivers/web.js +570 -0
- package/dist/drivers/web.js.map +1 -0
- package/dist/editor/server.d.ts +96 -0
- package/dist/editor/server.js +303 -0
- package/dist/editor/server.js.map +1 -0
- package/dist/ffmpeg.d.ts +5 -0
- package/dist/ffmpeg.js +44 -0
- package/dist/ffmpeg.js.map +1 -0
- package/dist/guide.d.ts +6 -0
- package/dist/guide.js +25 -0
- package/dist/guide.js.map +1 -0
- package/dist/init.d.ts +19 -0
- package/dist/init.js +147 -0
- package/dist/init.js.map +1 -0
- package/dist/login.d.ts +2 -0
- package/dist/login.js +50 -0
- package/dist/login.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +132 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/render/compose.d.ts +68 -0
- package/dist/render/compose.js +361 -0
- package/dist/render/compose.js.map +1 -0
- package/dist/render/presets.d.ts +42 -0
- package/dist/render/presets.js +111 -0
- package/dist/render/presets.js.map +1 -0
- package/dist/render/render.d.ts +25 -0
- package/dist/render/render.js +257 -0
- package/dist/render/render.js.map +1 -0
- package/dist/render/sources.d.ts +15 -0
- package/dist/render/sources.js +146 -0
- package/dist/render/sources.js.map +1 -0
- package/dist/render/style.d.ts +37 -0
- package/dist/render/style.js +118 -0
- package/dist/render/style.js.map +1 -0
- package/dist/scenario/config.d.ts +43 -0
- package/dist/scenario/config.js +69 -0
- package/dist/scenario/config.js.map +1 -0
- package/dist/scenario/fingerprint.d.ts +10 -0
- package/dist/scenario/fingerprint.js +58 -0
- package/dist/scenario/fingerprint.js.map +1 -0
- package/dist/scenario/load.d.ts +36 -0
- package/dist/scenario/load.js +101 -0
- package/dist/scenario/load.js.map +1 -0
- package/dist/scenario/schema.d.ts +553 -0
- package/dist/scenario/schema.js +262 -0
- package/dist/scenario/schema.js.map +1 -0
- package/dist/scenario/target.d.ts +26 -0
- package/dist/scenario/target.js +40 -0
- package/dist/scenario/target.js.map +1 -0
- package/dist/take.d.ts +100 -0
- package/dist/take.js +15 -0
- package/dist/take.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/dist/voice/cartesia.d.ts +12 -0
- package/dist/voice/cartesia.js +103 -0
- package/dist/voice/cartesia.js.map +1 -0
- package/package.json +65 -4
- package/schema/scenario.schema.json +1098 -0
- package/skills/screenplay/SKILL.md +127 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* A target names one element on screen, never coordinates (except `at` for
|
|
4
|
+
* desktop apps that expose no accessible elements). Playwright-style strings:
|
|
5
|
+
* "text=Save" visible text (exact match first, then contains)
|
|
6
|
+
* "role=button[name='Save']" ARIA role and accessible name
|
|
7
|
+
* "label=Email" form field by its label
|
|
8
|
+
* "placeholder=Search" input by placeholder
|
|
9
|
+
* "testid=save-button" data-testid
|
|
10
|
+
* "css=.toolbar > button" CSS selector (web only)
|
|
11
|
+
* A bare string without a prefix is treated as text.
|
|
12
|
+
*/
|
|
13
|
+
export const Target = z
|
|
14
|
+
.string()
|
|
15
|
+
.min(1)
|
|
16
|
+
.describe("The element to act on: text=…, role=button[name='…'], label=…, placeholder=…, testid=…, css=… (web only). A bare string means text=.");
|
|
17
|
+
export const SURFACES = ["window", "menubar", "menu", "sheet", "popover", "alert"];
|
|
18
|
+
const Common = {
|
|
19
|
+
say: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Narration for this step: shown as a caption, and spoken when voice is enabled. The step lasts at least as long as the sentence."),
|
|
23
|
+
zoom: z
|
|
24
|
+
.union([z.boolean(), z.number().min(1).max(4)])
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("false: keep the camera wide for this step. A number: force this zoom level (1 = no zoom)."),
|
|
27
|
+
hold: z
|
|
28
|
+
.number()
|
|
29
|
+
.min(0)
|
|
30
|
+
.max(30)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Extra seconds to stay on the result of this step before the next one."),
|
|
33
|
+
app: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe('Desktop: the app this step acts in (default: the scenario\'s app, or the last one opened). Another app than the scenario\'s needs "screen": true; there it also becomes the app the next steps act in.'),
|
|
37
|
+
surface: z
|
|
38
|
+
.enum(SURFACES)
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Desktop: where to look for the element: window (default, the app's front window), menubar (the app's menus in the menu bar), menu (an open menu), sheet, popover or alert."),
|
|
41
|
+
};
|
|
42
|
+
const Open = z
|
|
43
|
+
.object({
|
|
44
|
+
open: z.string().describe('Desktop, with "screen": true: launch this app or bring it to the front. The next steps act in it.'),
|
|
45
|
+
...Common,
|
|
46
|
+
})
|
|
47
|
+
.strict();
|
|
48
|
+
const Goto = z.object({ goto: z.string().describe("URL or path to open (relative to the scenario url)."), ...Common }).strict();
|
|
49
|
+
const Click = z
|
|
50
|
+
.object({
|
|
51
|
+
click: Target,
|
|
52
|
+
button: z.enum(["left", "right"]).optional(),
|
|
53
|
+
double: z.boolean().optional(),
|
|
54
|
+
...Common,
|
|
55
|
+
})
|
|
56
|
+
.strict();
|
|
57
|
+
const Type = z
|
|
58
|
+
.object({
|
|
59
|
+
type: z.string().describe("Text to type, letter by letter. ${ENV_VAR} is replaced from the environment."),
|
|
60
|
+
into: Target.optional().describe("Field to click first. Omit to type where the focus already is."),
|
|
61
|
+
clear: z.boolean().optional().describe("Clear the field before typing."),
|
|
62
|
+
secret: z.boolean().optional().describe("Mask the text in captions, logs and the storyboard."),
|
|
63
|
+
submit: z.boolean().optional().describe("Press Enter after typing."),
|
|
64
|
+
...Common,
|
|
65
|
+
})
|
|
66
|
+
.strict();
|
|
67
|
+
const Press = z.object({ press: z.string().describe("Key or chord, e.g. Enter, Escape, Meta+K."), ...Common }).strict();
|
|
68
|
+
const Hover = z.object({ hover: Target, ...Common }).strict();
|
|
69
|
+
const Scroll = z
|
|
70
|
+
.object({
|
|
71
|
+
scroll: z
|
|
72
|
+
.union([Target, z.enum(["down", "up", "top", "bottom"])])
|
|
73
|
+
.describe("An element to bring into view, or a direction (down/up scroll one screen)."),
|
|
74
|
+
...Common,
|
|
75
|
+
})
|
|
76
|
+
.strict();
|
|
77
|
+
const Select = z.object({ select: Target, option: z.string(), ...Common }).strict();
|
|
78
|
+
const Wait = z
|
|
79
|
+
.object({
|
|
80
|
+
wait: z
|
|
81
|
+
.union([Target, z.number().min(0).max(120)])
|
|
82
|
+
.describe("An element/text to wait for, or a number of seconds. Long waits are sped up in the video."),
|
|
83
|
+
timeout: z.number().min(1).max(300).optional().describe("Seconds before giving up (default 30)."),
|
|
84
|
+
...Common,
|
|
85
|
+
})
|
|
86
|
+
.strict();
|
|
87
|
+
const Pause = z.object({ pause: z.number().min(0).max(30).describe("Seconds to stay still."), ...Common }).strict();
|
|
88
|
+
const Title = z
|
|
89
|
+
.object({
|
|
90
|
+
title: z.string().describe("Opening card shown full screen."),
|
|
91
|
+
subtitle: z.string().optional(),
|
|
92
|
+
duration: z.number().min(0.5).max(15).optional(),
|
|
93
|
+
say: Common.say,
|
|
94
|
+
})
|
|
95
|
+
.strict();
|
|
96
|
+
const End = z
|
|
97
|
+
.object({
|
|
98
|
+
end: z.string().describe("Closing card shown full screen (result, call to action)."),
|
|
99
|
+
subtitle: z.string().optional(),
|
|
100
|
+
duration: z.number().min(0.5).max(15).optional(),
|
|
101
|
+
say: Common.say,
|
|
102
|
+
})
|
|
103
|
+
.strict();
|
|
104
|
+
const Callout = z
|
|
105
|
+
.object({
|
|
106
|
+
callout: Target,
|
|
107
|
+
text: z.string().describe("Text of the bubble pointing at the element."),
|
|
108
|
+
duration: z.number().min(0.5).max(15).optional(),
|
|
109
|
+
...Common,
|
|
110
|
+
})
|
|
111
|
+
.strict();
|
|
112
|
+
const Highlight = z
|
|
113
|
+
.object({
|
|
114
|
+
highlight: Target,
|
|
115
|
+
text: z.string().optional(),
|
|
116
|
+
duration: z.number().min(0.5).max(15).optional(),
|
|
117
|
+
...Common,
|
|
118
|
+
})
|
|
119
|
+
.strict();
|
|
120
|
+
const ZoomTo = z
|
|
121
|
+
.object({
|
|
122
|
+
zoomTo: Target.describe("Frame the camera on this element without acting on it."),
|
|
123
|
+
duration: z.number().min(0.5).max(15).optional(),
|
|
124
|
+
...Common,
|
|
125
|
+
})
|
|
126
|
+
.strict();
|
|
127
|
+
export const Step = z.union([
|
|
128
|
+
Goto,
|
|
129
|
+
Open,
|
|
130
|
+
Click,
|
|
131
|
+
Type,
|
|
132
|
+
Press,
|
|
133
|
+
Hover,
|
|
134
|
+
Scroll,
|
|
135
|
+
Select,
|
|
136
|
+
Wait,
|
|
137
|
+
Pause,
|
|
138
|
+
Title,
|
|
139
|
+
End,
|
|
140
|
+
Callout,
|
|
141
|
+
Highlight,
|
|
142
|
+
ZoomTo,
|
|
143
|
+
]);
|
|
144
|
+
export const BACKGROUNDS = ["sunset", "ocean", "lavender", "forest", "midnight", "mono", "paper"];
|
|
145
|
+
const Color = z.string().regex(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i, "a hex color like #0ea5e9");
|
|
146
|
+
export const Gradient = z
|
|
147
|
+
.object({
|
|
148
|
+
gradient: z.array(Color).min(2).max(4).describe("2 to 4 hex colors, from the start of the gradient to its end."),
|
|
149
|
+
angle: z.number().min(0).max(360).optional().describe("Direction in degrees, as in CSS: 90 goes left to right, 180 top to bottom (default 135)."),
|
|
150
|
+
})
|
|
151
|
+
.strict();
|
|
152
|
+
export const Style = z
|
|
153
|
+
.object({
|
|
154
|
+
background: z
|
|
155
|
+
.union([z.string(), Gradient])
|
|
156
|
+
.optional()
|
|
157
|
+
.describe(`A preset (${BACKGROUNDS.join(", ")}), a color like #0f172a, an image path (relative to the file that sets it), or a gradient { "gradient": ["#0ea5e9", "#6366f1"], "angle": 135 }.`),
|
|
158
|
+
padding: z.number().min(0).max(400).optional().describe("Space around the recording, in output pixels (default 72)."),
|
|
159
|
+
radius: z.number().min(0).max(80).optional().describe("Corner radius of the recording (default 14)."),
|
|
160
|
+
shadow: z.boolean().optional().describe("Drop shadow under the recording (default true)."),
|
|
161
|
+
cursor: z.enum(["macos", "dot", "none"]).optional().describe("Cursor drawn in the video (default macos)."),
|
|
162
|
+
cursorSize: z.number().min(0.5).max(3).optional().describe("Cursor scale (default 1)."),
|
|
163
|
+
maxZoom: z.number().min(1).max(4).optional().describe("Highest automatic zoom (default 1.9). Automatic zooms also stop where the capture runs out of pixels, so a small app window that already fills the video is not zoomed; a number in a step's `zoom` still forces it."),
|
|
164
|
+
autoZoom: z.boolean().optional().describe("Zoom automatically on clicks and typing (default true)."),
|
|
165
|
+
captions: z.boolean().optional().describe("Show the `say` text as captions (default true)."),
|
|
166
|
+
accent: z.string().optional().describe("Accent color for clicks, callouts and highlights (default #3b82f6)."),
|
|
167
|
+
frame: z.enum(["none", "browser"]).optional().describe("Draw a minimal browser window bar above web recordings (default none)."),
|
|
168
|
+
})
|
|
169
|
+
.strict();
|
|
170
|
+
export const Voice = z
|
|
171
|
+
.object({
|
|
172
|
+
enabled: z.boolean().optional().describe("Speak each step's `say` text (default false). Needs CARTESIA_API_KEY."),
|
|
173
|
+
language: z.string().optional().describe("Language code, e.g. en, fr, de (default en)."),
|
|
174
|
+
id: z.string().optional().describe("Cartesia voice id (default: a narration voice for the language)."),
|
|
175
|
+
speed: z.number().min(0.6).max(1.5).optional(),
|
|
176
|
+
model: z.string().optional().describe("Cartesia model (default sonic-3.6)."),
|
|
177
|
+
})
|
|
178
|
+
.strict();
|
|
179
|
+
export const Output = z
|
|
180
|
+
.object({
|
|
181
|
+
width: z.number().int().min(320).max(3840).optional().describe("Video width (default 1920)."),
|
|
182
|
+
height: z.number().int().min(240).max(2160).optional().describe("Video height (default 1080)."),
|
|
183
|
+
fps: z.union([z.literal(24), z.literal(25), z.literal(30), z.literal(50), z.literal(60)]).optional().describe("Frames per second (default 30)."),
|
|
184
|
+
gif: z.boolean().optional().describe("Also write a GIF (default false)."),
|
|
185
|
+
path: z.string().optional().describe("Where to write the MP4 (default: next to the scenario, same name)."),
|
|
186
|
+
})
|
|
187
|
+
.strict();
|
|
188
|
+
export const Scenario = z
|
|
189
|
+
.object({
|
|
190
|
+
$schema: z.string().optional(),
|
|
191
|
+
name: z.string().optional().describe("Name of the video (default: the file name)."),
|
|
192
|
+
url: z.string().optional().describe("Web: the page to start on."),
|
|
193
|
+
app: z
|
|
194
|
+
.string()
|
|
195
|
+
.optional()
|
|
196
|
+
.describe('Desktop: the application to film, as the OS names it. With "screen": true, the app brought to the front first (optional).'),
|
|
197
|
+
screen: z
|
|
198
|
+
.boolean()
|
|
199
|
+
.optional()
|
|
200
|
+
.describe("Desktop: film the whole main screen instead of one app's window, to show several apps or the menu bar. Everything on screen is filmed (notifications, other windows, the menu bar icons): close or hide what should not be seen."),
|
|
201
|
+
hideOthers: z
|
|
202
|
+
.boolean()
|
|
203
|
+
.optional()
|
|
204
|
+
.describe("Desktop, macOS, with \"screen\": true: hide the other apps before filming (Hide Others, ⌥⌘H, in `app`). Default false."),
|
|
205
|
+
viewport: z
|
|
206
|
+
.object({ width: z.number().int().min(320).max(3840), height: z.number().int().min(240).max(2160) })
|
|
207
|
+
.optional()
|
|
208
|
+
.describe("Web: browser size in CSS pixels (default 1440x900)."),
|
|
209
|
+
scale: z.number().min(1).max(3).optional().describe("Web: device pixel ratio of the capture (default 2, Retina)."),
|
|
210
|
+
colorScheme: z.enum(["light", "dark"]).optional(),
|
|
211
|
+
locale: z.string().optional().describe("Web: browser locale, e.g. fr-FR."),
|
|
212
|
+
auth: z
|
|
213
|
+
.object({ storageState: z.string().describe("Path to a session saved by `screenplay login`.") })
|
|
214
|
+
.optional(),
|
|
215
|
+
hideScrollbars: z.boolean().optional().describe("Web: hide scrollbars (default true)."),
|
|
216
|
+
typingSpeed: z.number().min(0.2).max(5).optional().describe("Typing speed multiplier (default 1, about 14 characters/second)."),
|
|
217
|
+
style: Style.optional(),
|
|
218
|
+
voice: Voice.optional(),
|
|
219
|
+
output: Output.optional(),
|
|
220
|
+
steps: z.array(Step).min(1),
|
|
221
|
+
})
|
|
222
|
+
.strict()
|
|
223
|
+
.refine((s) => Boolean(s.url) !== Boolean(s.app || s.screen), {
|
|
224
|
+
message: "Give either `url` (a website), or `app` (a desktop application's window) and/or `\"screen\": true` (the whole screen).",
|
|
225
|
+
})
|
|
226
|
+
.refine((s) => !s.url || s.steps.every((st) => !("open" in st) && !("app" in st) && !("surface" in st)), {
|
|
227
|
+
message: "`open`, `app` and `surface` in steps are for desktop recordings, not websites.",
|
|
228
|
+
});
|
|
229
|
+
const KINDS = [
|
|
230
|
+
"goto",
|
|
231
|
+
"open",
|
|
232
|
+
"click",
|
|
233
|
+
"type",
|
|
234
|
+
"press",
|
|
235
|
+
"hover",
|
|
236
|
+
"scroll",
|
|
237
|
+
"select",
|
|
238
|
+
"wait",
|
|
239
|
+
"pause",
|
|
240
|
+
"title",
|
|
241
|
+
"end",
|
|
242
|
+
"callout",
|
|
243
|
+
"highlight",
|
|
244
|
+
"zoomTo",
|
|
245
|
+
];
|
|
246
|
+
export function stepKind(step) {
|
|
247
|
+
for (const k of KINDS)
|
|
248
|
+
if (k in step)
|
|
249
|
+
return k;
|
|
250
|
+
throw new Error(`Unknown step: ${JSON.stringify(step)}`);
|
|
251
|
+
}
|
|
252
|
+
export function describeStep(step) {
|
|
253
|
+
const kind = stepKind(step);
|
|
254
|
+
const value = step[kind];
|
|
255
|
+
if (kind === "type") {
|
|
256
|
+
const t = step;
|
|
257
|
+
const text = t.secret ? "••••••" : t.type;
|
|
258
|
+
return t.into ? `type "${text}" into ${t.into}` : `type "${text}"`;
|
|
259
|
+
}
|
|
260
|
+
return `${kind} ${typeof value === "string" ? value : JSON.stringify(value)}`;
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/scenario/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type ParsedTarget = {
|
|
2
|
+
kind: "text";
|
|
3
|
+
text: string;
|
|
4
|
+
} | {
|
|
5
|
+
kind: "role";
|
|
6
|
+
role: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "label";
|
|
10
|
+
text: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "placeholder";
|
|
13
|
+
text: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "testid";
|
|
16
|
+
id: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "css";
|
|
19
|
+
selector: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "at";
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
};
|
|
25
|
+
/** Parse "text=…", "role=button[name='…']", "label=…", "placeholder=…", "testid=…", "css=…", "at=x,y". */
|
|
26
|
+
export declare function parseTarget(input: string): ParsedTarget;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const ROLE_RE = /^([a-z]+)(?:\[name=(['"])(.*)\2\])?$/i;
|
|
2
|
+
/** Parse "text=…", "role=button[name='…']", "label=…", "placeholder=…", "testid=…", "css=…", "at=x,y". */
|
|
3
|
+
export function parseTarget(input) {
|
|
4
|
+
const s = input.trim();
|
|
5
|
+
const eq = s.indexOf("=");
|
|
6
|
+
const prefix = eq > 0 ? s.slice(0, eq).toLowerCase() : "";
|
|
7
|
+
const rest = eq > 0 ? s.slice(eq + 1).trim() : s;
|
|
8
|
+
switch (prefix) {
|
|
9
|
+
case "text":
|
|
10
|
+
return { kind: "text", text: unquote(rest) };
|
|
11
|
+
case "role": {
|
|
12
|
+
const m = ROLE_RE.exec(rest);
|
|
13
|
+
if (!m)
|
|
14
|
+
throw new Error(`Invalid role target "${input}". Use role=button or role=button[name='Save'].`);
|
|
15
|
+
return { kind: "role", role: m[1].toLowerCase(), name: m[3] };
|
|
16
|
+
}
|
|
17
|
+
case "label":
|
|
18
|
+
return { kind: "label", text: unquote(rest) };
|
|
19
|
+
case "placeholder":
|
|
20
|
+
return { kind: "placeholder", text: unquote(rest) };
|
|
21
|
+
case "testid":
|
|
22
|
+
return { kind: "testid", id: unquote(rest) };
|
|
23
|
+
case "css":
|
|
24
|
+
return { kind: "css", selector: rest };
|
|
25
|
+
case "at": {
|
|
26
|
+
const [x, y] = rest.split(",").map((v) => Number(v.trim()));
|
|
27
|
+
if (!Number.isFinite(x) || !Number.isFinite(y))
|
|
28
|
+
throw new Error(`Invalid target "${input}". Use at=x,y.`);
|
|
29
|
+
return { kind: "at", x, y };
|
|
30
|
+
}
|
|
31
|
+
default:
|
|
32
|
+
return { kind: "text", text: unquote(s) };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function unquote(s) {
|
|
36
|
+
if (s.length >= 2 && (s[0] === "'" || s[0] === '"') && s[s.length - 1] === s[0])
|
|
37
|
+
return s.slice(1, -1);
|
|
38
|
+
return s;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../../src/scenario/target.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,GAAG,uCAAuC,CAAC;AAExD,0GAA0G;AAC1G,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvB,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1D,MAAM,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,KAAK,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,CAAC,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,iDAAiD,CAAC,CAAC;YACxG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,CAAC;QACD,KAAK,OAAO;YACV,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,KAAK,aAAa;YAChB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,KAAK,QAAQ;YACX,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,KAAK,KAAK;YACR,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACzC,KAAK,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,gBAAgB,CAAC,CAAC;YAC1G,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC9B,CAAC;QACD;YACE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,CAAS;IACxB,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvG,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/take.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { StepKind } from "./scenario/schema.js";
|
|
2
|
+
/** A rectangle in source coordinates (CSS pixels of the filmed viewport, or points of the filmed window or screen). */
|
|
3
|
+
export interface Box {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
export interface Point {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* What happened during one step of a take. Times are seconds since the start
|
|
15
|
+
* of the take, on the same clock as the captured frames.
|
|
16
|
+
*/
|
|
17
|
+
export interface TakeStep {
|
|
18
|
+
index: number;
|
|
19
|
+
kind: StepKind;
|
|
20
|
+
label: string;
|
|
21
|
+
start: number;
|
|
22
|
+
end: number;
|
|
23
|
+
/** The cursor starts travelling towards `point`. */
|
|
24
|
+
travelStart?: number;
|
|
25
|
+
/** The click happens / typing starts. */
|
|
26
|
+
actionAt?: number;
|
|
27
|
+
/** Typing ends. */
|
|
28
|
+
actionEnd?: number;
|
|
29
|
+
/** Where the cursor goes. */
|
|
30
|
+
point?: Point;
|
|
31
|
+
/** The element's box at action time. */
|
|
32
|
+
box?: Box;
|
|
33
|
+
/** Spans spent waiting (page loads, slow elements): sped up in the video. */
|
|
34
|
+
waits: Array<[number, number]>;
|
|
35
|
+
/** Smooth scroll spans. */
|
|
36
|
+
scrolls?: Array<[number, number]>;
|
|
37
|
+
/** The page navigated during this step. */
|
|
38
|
+
navigated?: boolean;
|
|
39
|
+
/** A title or end card, inserted at `start` (it takes no recording time). */
|
|
40
|
+
card?: {
|
|
41
|
+
kind: "title" | "end";
|
|
42
|
+
title: string;
|
|
43
|
+
subtitle?: string;
|
|
44
|
+
duration: number;
|
|
45
|
+
};
|
|
46
|
+
/** Typed characters (masked when secret). */
|
|
47
|
+
typed?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface FramesSource {
|
|
50
|
+
kind: "frames";
|
|
51
|
+
/** Directory of the frame images, relative to the take directory. */
|
|
52
|
+
dir: string;
|
|
53
|
+
/** [time, file name] sorted by time. */
|
|
54
|
+
frames: Array<[number, string]>;
|
|
55
|
+
}
|
|
56
|
+
export interface VideoSource {
|
|
57
|
+
kind: "video";
|
|
58
|
+
/** Video file, relative to the take directory. */
|
|
59
|
+
file: string;
|
|
60
|
+
fps: number;
|
|
61
|
+
/** Seconds between the take clock and the video's first frame (video time = take time - offset). */
|
|
62
|
+
offset: number;
|
|
63
|
+
/** Region of the video that holds the filmed window, in video pixels. */
|
|
64
|
+
crop: {
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
width: number;
|
|
68
|
+
height: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export interface Take {
|
|
72
|
+
version: 1;
|
|
73
|
+
name: string;
|
|
74
|
+
recordedAt: string;
|
|
75
|
+
platform: NodeJS.Platform;
|
|
76
|
+
target: {
|
|
77
|
+
kind: "web";
|
|
78
|
+
url: string;
|
|
79
|
+
} | {
|
|
80
|
+
kind: "desktop";
|
|
81
|
+
app: string;
|
|
82
|
+
screen?: boolean;
|
|
83
|
+
};
|
|
84
|
+
/** Size of the filmed area in source coordinates (CSS pixels / logical points). */
|
|
85
|
+
width: number;
|
|
86
|
+
height: number;
|
|
87
|
+
/** Pixels per source unit in the captured images. */
|
|
88
|
+
scale: number;
|
|
89
|
+
duration: number;
|
|
90
|
+
cursorStart: Point;
|
|
91
|
+
source: FramesSource | VideoSource;
|
|
92
|
+
steps: TakeStep[];
|
|
93
|
+
/** What the recording depends on (see scenario/fingerprint.ts), to refuse re-rendering a changed scenario. */
|
|
94
|
+
inputs?: {
|
|
95
|
+
setup: string;
|
|
96
|
+
steps: string[];
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export declare function writeTake(dir: string, take: Take): string;
|
|
100
|
+
export declare function readTake(dir: string): Take;
|
package/dist/take.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export function writeTake(dir, take) {
|
|
4
|
+
const file = path.join(dir, "take.json");
|
|
5
|
+
fs.writeFileSync(file, JSON.stringify(take, null, 2));
|
|
6
|
+
return file;
|
|
7
|
+
}
|
|
8
|
+
export function readTake(dir) {
|
|
9
|
+
const file = path.join(dir, "take.json");
|
|
10
|
+
if (!fs.existsSync(file)) {
|
|
11
|
+
throw new Error(`No recording found in ${dir}. Run \`screenplay record\` first.`);
|
|
12
|
+
}
|
|
13
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=take.js.map
|
package/dist/take.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"take.js","sourceRoot":"","sources":["../src/take.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAsF7B,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,IAAU;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACzC,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,oCAAoC,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAS,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION = "0.1.0";
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Voice } from "../scenario/schema.js";
|
|
2
|
+
export declare class VoiceError extends Error {
|
|
3
|
+
}
|
|
4
|
+
export interface Clip {
|
|
5
|
+
file: string;
|
|
6
|
+
duration: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function voiceKey(): string | undefined;
|
|
9
|
+
/** Synthesize each text (cached on disk by content), and return the clip files with their durations. */
|
|
10
|
+
export declare function synthesizeAll(texts: Map<number, string>, voice: Voice, cacheDir: string): Promise<Map<number, Clip>>;
|
|
11
|
+
/** Duration of a PCM WAV file, from its header. */
|
|
12
|
+
export declare function wavDuration(buf: Buffer): number;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const API = "https://api.cartesia.ai";
|
|
5
|
+
const VERSION = "2026-08-14";
|
|
6
|
+
const DEFAULT_MODEL = "sonic-3.6";
|
|
7
|
+
/** Narration voices picked for clear product walkthroughs. Other languages use Cartesia's first voice for the language. */
|
|
8
|
+
const DEFAULT_VOICES = {
|
|
9
|
+
en: "a33f7a4c-100f-41cf-a1fd-5822e8fc253f", // Lauren: expressive narration
|
|
10
|
+
fr: "7c58f4a4-a72c-42fa-a503-41b9408820f3", // Inès: corporate narration
|
|
11
|
+
};
|
|
12
|
+
export class VoiceError extends Error {
|
|
13
|
+
}
|
|
14
|
+
export function voiceKey() {
|
|
15
|
+
return process.env.CARTESIA_API_KEY || undefined;
|
|
16
|
+
}
|
|
17
|
+
/** Synthesize each text (cached on disk by content), and return the clip files with their durations. */
|
|
18
|
+
export async function synthesizeAll(texts, voice, cacheDir) {
|
|
19
|
+
// The key is only needed for sentences not generated before (they are cached by content).
|
|
20
|
+
const requireKey = () => {
|
|
21
|
+
const key = voiceKey();
|
|
22
|
+
if (!key) {
|
|
23
|
+
throw new VoiceError("Voice-over is enabled but CARTESIA_API_KEY is not set. Set it (https://play.cartesia.ai/keys), or remove `voice.enabled`, or pass --no-voice.");
|
|
24
|
+
}
|
|
25
|
+
return key;
|
|
26
|
+
};
|
|
27
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
28
|
+
const language = voice.language ?? "en";
|
|
29
|
+
const base = language.split("-")[0].toLowerCase();
|
|
30
|
+
const voiceId = voice.id ?? DEFAULT_VOICES[base] ?? (await defaultVoice(language, requireKey()));
|
|
31
|
+
const model = voice.model ?? DEFAULT_MODEL;
|
|
32
|
+
const out = new Map();
|
|
33
|
+
for (const [index, text] of texts) {
|
|
34
|
+
const hash = crypto
|
|
35
|
+
.createHash("sha1")
|
|
36
|
+
.update(JSON.stringify([model, voiceId, language, voice.speed ?? 1, text]))
|
|
37
|
+
.digest("hex")
|
|
38
|
+
.slice(0, 16);
|
|
39
|
+
const file = path.join(cacheDir, `${hash}.wav`);
|
|
40
|
+
if (!fs.existsSync(file)) {
|
|
41
|
+
const key = requireKey();
|
|
42
|
+
const body = {
|
|
43
|
+
model_id: model,
|
|
44
|
+
transcript: text,
|
|
45
|
+
voice: { id: voiceId },
|
|
46
|
+
language,
|
|
47
|
+
output_format: { container: "wav", encoding: "pcm_s16le", sample_rate: 44100 },
|
|
48
|
+
...(voice.speed ? { generation_config: { speed: voice.speed } } : {}),
|
|
49
|
+
};
|
|
50
|
+
const res = await fetch(`${API}/tts/bytes`, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers: { Authorization: `Bearer ${key}`, "Cartesia-Version": VERSION, "Content-Type": "application/json" },
|
|
53
|
+
body: JSON.stringify(body),
|
|
54
|
+
});
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
const detail = (await res.text()).slice(0, 400);
|
|
57
|
+
throw new VoiceError(`Cartesia refused the narration of step ${index + 1} (${res.status}): ${detail}`);
|
|
58
|
+
}
|
|
59
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
60
|
+
// Write then rename, so an interrupted download never leaves a broken cached clip.
|
|
61
|
+
fs.writeFileSync(`${file}.part`, buf);
|
|
62
|
+
fs.renameSync(`${file}.part`, file);
|
|
63
|
+
}
|
|
64
|
+
out.set(index, { file, duration: wavDuration(fs.readFileSync(file)) });
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
async function defaultVoice(language, key) {
|
|
69
|
+
const base = language.split("-")[0].toLowerCase();
|
|
70
|
+
if (DEFAULT_VOICES[base])
|
|
71
|
+
return DEFAULT_VOICES[base];
|
|
72
|
+
const res = await fetch(`${API}/voices?language=${encodeURIComponent(base)}&limit=1`, {
|
|
73
|
+
headers: { Authorization: `Bearer ${key}`, "Cartesia-Version": VERSION },
|
|
74
|
+
});
|
|
75
|
+
if (res.ok) {
|
|
76
|
+
const data = (await res.json());
|
|
77
|
+
const id = data.data?.[0]?.id;
|
|
78
|
+
if (id)
|
|
79
|
+
return id;
|
|
80
|
+
}
|
|
81
|
+
throw new VoiceError(`No Cartesia voice found for language "${language}". Set voice.id in the scenario.`);
|
|
82
|
+
}
|
|
83
|
+
/** Duration of a PCM WAV file, from its header. */
|
|
84
|
+
export function wavDuration(buf) {
|
|
85
|
+
if (buf.toString("ascii", 0, 4) !== "RIFF")
|
|
86
|
+
throw new VoiceError("Narration audio is not a WAV file.");
|
|
87
|
+
let off = 12;
|
|
88
|
+
let byteRate = 0;
|
|
89
|
+
while (off + 8 <= buf.length) {
|
|
90
|
+
const id = buf.toString("ascii", off, off + 4);
|
|
91
|
+
const size = buf.readUInt32LE(off + 4);
|
|
92
|
+
if (id === "fmt ")
|
|
93
|
+
byteRate = buf.readUInt32LE(off + 16);
|
|
94
|
+
if (id === "data") {
|
|
95
|
+
// Streaming WAVs may carry a placeholder size: fall back to the bytes present.
|
|
96
|
+
const real = Math.min(size, buf.length - off - 8);
|
|
97
|
+
return byteRate ? real / byteRate : 0;
|
|
98
|
+
}
|
|
99
|
+
off += 8 + size + (size % 2);
|
|
100
|
+
}
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=cartesia.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cartesia.js","sourceRoot":"","sources":["../../src/voice/cartesia.ts"],"names":[],"mappings":"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"}
|