libretto 0.6.19 → 0.6.21
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 +10 -13
- package/README.template.md +10 -13
- package/dist/cli/cli.js +0 -14
- package/dist/cli/commands/deploy.js +5 -0
- package/dist/cli/commands/update.js +47 -18
- package/dist/cli/core/daemon/daemon.js +2 -0
- package/dist/cli/core/providers/libretto-cloud.js +22 -3
- package/dist/cli/core/skill-version.js +8 -95
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -0
- package/dist/shared/workflow/workflow.d.ts +6 -1
- package/dist/shared/workflow/workflow.js +13 -10
- package/package.json +1 -1
- package/skills/libretto/SKILL.md +36 -35
- package/skills/libretto/references/auth-profiles.md +3 -3
- package/skills/libretto/references/code-generation-rules.md +2 -2
- package/skills/libretto/references/configuration-file-reference.md +10 -10
- package/skills/libretto/references/pages-and-page-targeting.md +3 -3
- package/skills/libretto-readonly/SKILL.md +1 -1
- package/src/cli/cli.ts +0 -17
- package/src/cli/commands/deploy.ts +5 -0
- package/src/cli/commands/update.ts +57 -19
- package/src/cli/core/daemon/daemon.ts +2 -0
- package/src/cli/core/providers/libretto-cloud.ts +29 -6
- package/src/cli/core/skill-version.ts +10 -131
- package/src/index.ts +2 -0
- package/src/shared/workflow/workflow.ts +27 -10
package/README.md
CHANGED
|
@@ -28,17 +28,14 @@ https://github.com/user-attachments/assets/9b9a0ab3-5133-4b20-b3be-459943349d18
|
|
|
28
28
|
## Installation
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
#
|
|
32
|
-
curl -fsSL https://libretto.sh/install.sh | bash
|
|
33
|
-
|
|
34
|
-
# Add Libretto to your project
|
|
31
|
+
# Add Libretto to your project. Requires Node.js and npm.
|
|
35
32
|
npm install libretto
|
|
36
33
|
|
|
37
34
|
# First-time onboarding: install skills and download Chromium
|
|
38
|
-
libretto setup
|
|
35
|
+
npx libretto setup
|
|
39
36
|
|
|
40
37
|
# Check workspace readiness at any time
|
|
41
|
-
libretto status
|
|
38
|
+
npx libretto status
|
|
42
39
|
```
|
|
43
40
|
|
|
44
41
|
`setup` creates the `.libretto/` directory, installs agent skills, and downloads Chromium unless you pass `--skip-browsers`.
|
|
@@ -76,17 +73,17 @@ Agents can use Libretto to reproduce the failure, pause the workflow at any poin
|
|
|
76
73
|
You can also use Libretto directly from the command line. All commands accept `--session <name>` to target a specific session.
|
|
77
74
|
|
|
78
75
|
```bash
|
|
79
|
-
libretto open <url> # launch browser and open a URL
|
|
80
|
-
libretto run ./integration.ts --headless # run a workflow and close on success
|
|
81
|
-
libretto run ./integration.ts --headless --stay-open-on-success # keep a successful run inspectable
|
|
82
|
-
libretto snapshot --session <name> # capture a screenshot and compact accessibility tree
|
|
83
|
-
libretto exec "<code>" # execute Playwright TypeScript against the open page
|
|
84
|
-
libretto close # close the browser
|
|
76
|
+
npx libretto open <url> # launch browser and open a URL
|
|
77
|
+
npx libretto run ./integration.ts --headless # run a workflow and close on success
|
|
78
|
+
npx libretto run ./integration.ts --headless --stay-open-on-success # keep a successful run inspectable
|
|
79
|
+
npx libretto snapshot --session <name> # capture a screenshot and compact accessibility tree
|
|
80
|
+
npx libretto exec "<code>" # execute Playwright TypeScript against the open page
|
|
81
|
+
npx libretto close # close the browser
|
|
85
82
|
```
|
|
86
83
|
|
|
87
84
|
`run` sessions are inspectable through the same daemon-backed commands as `open` sessions. Successful runs close the browser by default; pass `--stay-open-on-success` to keep the browser open for `pages`, `snapshot`, and `exec`. Failed or paused workflows keep the browser open so you can inspect the exact page state before fixing or resuming the workflow.
|
|
88
85
|
|
|
89
|
-
Run `libretto help` for the full list of commands.
|
|
86
|
+
Run `npx libretto help` for the full list of commands.
|
|
90
87
|
|
|
91
88
|
## Configuration
|
|
92
89
|
|
package/README.template.md
CHANGED
|
@@ -26,17 +26,14 @@ https://github.com/user-attachments/assets/9b9a0ab3-5133-4b20-b3be-459943349d18
|
|
|
26
26
|
## Installation
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
#
|
|
30
|
-
curl -fsSL https://libretto.sh/install.sh | bash
|
|
31
|
-
|
|
32
|
-
# Add Libretto to your project
|
|
29
|
+
# Add Libretto to your project. Requires Node.js and npm.
|
|
33
30
|
npm install libretto
|
|
34
31
|
|
|
35
32
|
# First-time onboarding: install skills and download Chromium
|
|
36
|
-
libretto setup
|
|
33
|
+
npx libretto setup
|
|
37
34
|
|
|
38
35
|
# Check workspace readiness at any time
|
|
39
|
-
libretto status
|
|
36
|
+
npx libretto status
|
|
40
37
|
```
|
|
41
38
|
|
|
42
39
|
`setup` creates the `.libretto/` directory, installs agent skills, and downloads Chromium unless you pass `--skip-browsers`.
|
|
@@ -74,17 +71,17 @@ Agents can use Libretto to reproduce the failure, pause the workflow at any poin
|
|
|
74
71
|
You can also use Libretto directly from the command line. All commands accept `--session <name>` to target a specific session.
|
|
75
72
|
|
|
76
73
|
```bash
|
|
77
|
-
libretto open <url> # launch browser and open a URL
|
|
78
|
-
libretto run ./integration.ts --headless # run a workflow and close on success
|
|
79
|
-
libretto run ./integration.ts --headless --stay-open-on-success # keep a successful run inspectable
|
|
80
|
-
libretto snapshot --session <name> # capture a screenshot and compact accessibility tree
|
|
81
|
-
libretto exec "<code>" # execute Playwright TypeScript against the open page
|
|
82
|
-
libretto close # close the browser
|
|
74
|
+
npx libretto open <url> # launch browser and open a URL
|
|
75
|
+
npx libretto run ./integration.ts --headless # run a workflow and close on success
|
|
76
|
+
npx libretto run ./integration.ts --headless --stay-open-on-success # keep a successful run inspectable
|
|
77
|
+
npx libretto snapshot --session <name> # capture a screenshot and compact accessibility tree
|
|
78
|
+
npx libretto exec "<code>" # execute Playwright TypeScript against the open page
|
|
79
|
+
npx libretto close # close the browser
|
|
83
80
|
```
|
|
84
81
|
|
|
85
82
|
`run` sessions are inspectable through the same daemon-backed commands as `open` sessions. Successful runs close the browser by default; pass `--stay-open-on-success` to keep the browser open for `pages`, `snapshot`, and `exec`. Failed or paused workflows keep the browser open so you can inspect the exact page state before fixing or resuming the workflow.
|
|
86
83
|
|
|
87
|
-
Run `libretto help` for the full list of commands.
|
|
84
|
+
Run `npx libretto help` for the full list of commands.
|
|
88
85
|
|
|
89
86
|
## Configuration
|
|
90
87
|
|
package/dist/cli/cli.js
CHANGED
|
@@ -11,19 +11,6 @@ function renderVersion() {
|
|
|
11
11
|
function printSetupAudit() {
|
|
12
12
|
warnIfLibrettoVersionsDiffer();
|
|
13
13
|
}
|
|
14
|
-
function isPackageManagerExec(env = process.env) {
|
|
15
|
-
return env.npm_command === "exec";
|
|
16
|
-
}
|
|
17
|
-
function warnIfPackageManagerExec() {
|
|
18
|
-
if (!isPackageManagerExec()) return;
|
|
19
|
-
console.error(
|
|
20
|
-
[
|
|
21
|
-
"Warning: running Libretto through a package manager is deprecated and will be removed in a future release.",
|
|
22
|
-
"Install the native command instead:",
|
|
23
|
-
" curl -fsSL https://libretto.sh/install.sh | bash"
|
|
24
|
-
].join("\n")
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
14
|
function isRootHelpRequest(rawArgs) {
|
|
28
15
|
if (rawArgs.length === 0) return true;
|
|
29
16
|
return rawArgs[0] === "help" && rawArgs.length === 1;
|
|
@@ -42,7 +29,6 @@ async function runLibrettoCLI() {
|
|
|
42
29
|
const rawArgs = process.argv.slice(2);
|
|
43
30
|
let exitCode = 0;
|
|
44
31
|
loadEnv();
|
|
45
|
-
warnIfPackageManagerExec();
|
|
46
32
|
ensureLibrettoSetup();
|
|
47
33
|
const app = createCLIApp();
|
|
48
34
|
try {
|
|
@@ -93,6 +93,10 @@ const deployInput = SimpleCLI.input({
|
|
|
93
93
|
name: "entry-point",
|
|
94
94
|
help: "Entry point file (default: index.ts)"
|
|
95
95
|
}),
|
|
96
|
+
autoRepair: SimpleCLI.flag({
|
|
97
|
+
name: "auto-repair",
|
|
98
|
+
help: "Route failed jobs for this deployment to autofix"
|
|
99
|
+
}),
|
|
96
100
|
external: SimpleCLI.option(
|
|
97
101
|
z.string().optional().transform(
|
|
98
102
|
(value) => value?.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0) ?? []
|
|
@@ -120,6 +124,7 @@ const deployCommand = SimpleCLI.command({
|
|
|
120
124
|
entry_point: entryPoint
|
|
121
125
|
};
|
|
122
126
|
if (input.description) createPayload.description = input.description;
|
|
127
|
+
if (input.autoRepair) createPayload.auto_repair = true;
|
|
123
128
|
console.log("Uploading deployment...");
|
|
124
129
|
const body = await orpcCall({
|
|
125
130
|
apiUrl,
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { SimpleCLI } from "affordance";
|
|
5
|
-
|
|
6
|
+
import { REPO_ROOT } from "../core/context.js";
|
|
7
|
+
import {
|
|
8
|
+
detectProjectPackageManager,
|
|
9
|
+
installCommand
|
|
10
|
+
} from "../../shared/package-manager.js";
|
|
11
|
+
function packageInstallCommand(packageManager, packageSpec) {
|
|
12
|
+
return `${installCommand(packageManager)} ${packageSpec}`;
|
|
13
|
+
}
|
|
6
14
|
function readCurrentCliVersion() {
|
|
7
15
|
const packageJsonPath = fileURLToPath(
|
|
8
16
|
new URL("../../../package.json", import.meta.url)
|
|
@@ -17,6 +25,21 @@ function readCurrentCliVersion() {
|
|
|
17
25
|
}
|
|
18
26
|
return manifest.version;
|
|
19
27
|
}
|
|
28
|
+
function readPackageVersion(packageJsonPath) {
|
|
29
|
+
try {
|
|
30
|
+
const manifest = JSON.parse(
|
|
31
|
+
readFileSync(packageJsonPath, "utf8")
|
|
32
|
+
);
|
|
33
|
+
return manifest.version?.trim() || null;
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function readLocalPackageVersion() {
|
|
39
|
+
return readPackageVersion(
|
|
40
|
+
join(REPO_ROOT, "node_modules", "libretto", "package.json")
|
|
41
|
+
);
|
|
42
|
+
}
|
|
20
43
|
function readLatestNpmVersion() {
|
|
21
44
|
const result = spawnSync("npm", ["view", "libretto@latest", "version"], {
|
|
22
45
|
encoding: "utf8"
|
|
@@ -65,55 +88,61 @@ const updateInput = SimpleCLI.input({
|
|
|
65
88
|
})
|
|
66
89
|
}
|
|
67
90
|
});
|
|
68
|
-
function formatUpdateFailure(status, signal) {
|
|
69
|
-
const knownState = status === null ? `
|
|
91
|
+
function formatUpdateFailure(status, signal, updateCommand2) {
|
|
92
|
+
const knownState = status === null ? `package update was interrupted${signal ? ` by ${signal}` : ""}.` : `package update exited with status ${status}.`;
|
|
70
93
|
return [
|
|
71
94
|
"Error: failed to update Libretto to the latest version.",
|
|
72
95
|
`Known state: ${knownState}`,
|
|
73
|
-
`Try: ${
|
|
96
|
+
`Try: ${updateCommand2}`,
|
|
74
97
|
"Help: libretto help update"
|
|
75
98
|
].join("\n");
|
|
76
99
|
}
|
|
77
100
|
const updateCommand = SimpleCLI.command({
|
|
78
101
|
description: "Update Libretto to the latest version"
|
|
79
102
|
}).input(updateInput).handle(async ({ input }) => {
|
|
103
|
+
const packageManager = detectProjectPackageManager();
|
|
104
|
+
const updateCommand2 = packageInstallCommand(packageManager, "libretto@latest");
|
|
80
105
|
if (input.dryRun) {
|
|
81
106
|
console.log("Update command:");
|
|
82
|
-
console.log(` ${
|
|
107
|
+
console.log(` ${updateCommand2}`);
|
|
83
108
|
console.log("No changes made.");
|
|
84
109
|
return;
|
|
85
110
|
}
|
|
86
111
|
const currentVersion = readCurrentCliVersion();
|
|
112
|
+
const localPackageVersion = readLocalPackageVersion();
|
|
113
|
+
const installedVersion = localPackageVersion ?? currentVersion;
|
|
87
114
|
const latestVersion = readLatestNpmVersion();
|
|
88
|
-
console.log(`Current version: ${
|
|
115
|
+
console.log(`Current version: ${installedVersion}`);
|
|
89
116
|
console.log(`Latest version: ${latestVersion}`);
|
|
90
|
-
if (
|
|
91
|
-
console.log(`Libretto is already up to date (${
|
|
117
|
+
if (localPackageVersion && installedVersion === latestVersion) {
|
|
118
|
+
console.log(`Libretto is already up to date (${installedVersion}).`);
|
|
92
119
|
console.log("No further action required.");
|
|
93
120
|
return;
|
|
94
121
|
}
|
|
95
|
-
|
|
96
|
-
|
|
122
|
+
if (!localPackageVersion) {
|
|
123
|
+
console.log("Local package: not installed");
|
|
124
|
+
}
|
|
125
|
+
console.log("Updating local Libretto package to latest...");
|
|
126
|
+
const result = spawnSync(updateCommand2, {
|
|
97
127
|
stdio: "inherit",
|
|
98
|
-
|
|
99
|
-
...process.env,
|
|
100
|
-
LIBRETTO_VERSION: "latest"
|
|
101
|
-
}
|
|
128
|
+
shell: true
|
|
102
129
|
});
|
|
103
130
|
if (result.error) {
|
|
104
131
|
throw new Error(
|
|
105
132
|
[
|
|
106
|
-
"Error: failed to start the Libretto
|
|
133
|
+
"Error: failed to start the Libretto package update.",
|
|
107
134
|
`Known state: ${result.error.message}`,
|
|
108
|
-
`Try: ${
|
|
135
|
+
`Try: ${updateCommand2}`,
|
|
109
136
|
"Help: libretto help update"
|
|
110
137
|
].join("\n")
|
|
111
138
|
);
|
|
112
139
|
}
|
|
113
140
|
if (result.status !== 0) {
|
|
114
|
-
throw new Error(
|
|
141
|
+
throw new Error(
|
|
142
|
+
formatUpdateFailure(result.status, result.signal, updateCommand2)
|
|
143
|
+
);
|
|
115
144
|
}
|
|
116
|
-
console.log("Libretto updated to latest.");
|
|
145
|
+
console.log("Local Libretto package updated to latest.");
|
|
117
146
|
console.log("No further action required.");
|
|
118
147
|
});
|
|
119
148
|
export {
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
loadDefaultWorkflow
|
|
48
48
|
} from "../workflow-runtime.js";
|
|
49
49
|
import { WorkflowController } from "../workflow-runner/runner.js";
|
|
50
|
+
import { validateWorkflowInput } from "../../../shared/workflow/workflow.js";
|
|
50
51
|
function isOperationalPage(page) {
|
|
51
52
|
const url = page.url();
|
|
52
53
|
return !url.startsWith("devtools://") && !url.startsWith("chrome-error://");
|
|
@@ -682,6 +683,7 @@ async function main() {
|
|
|
682
683
|
loadedWorkflow = await loadDefaultWorkflow(
|
|
683
684
|
getAbsoluteIntegrationPath(config.workflow.integrationPath)
|
|
684
685
|
);
|
|
686
|
+
validateWorkflowInput(loadedWorkflow, config.workflow.params ?? {});
|
|
685
687
|
} catch (error) {
|
|
686
688
|
throw new UserFacingStartupError(
|
|
687
689
|
error instanceof Error ? error.message : String(error)
|
|
@@ -64,8 +64,11 @@ function createLibrettoCloudProvider() {
|
|
|
64
64
|
};
|
|
65
65
|
},
|
|
66
66
|
async closeSession(sessionId) {
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
await closeCloudSession(endpoint, apiKey, sessionId);
|
|
68
|
+
const replayUrl = await getCloudRecordingUrl(endpoint, apiKey, sessionId).catch(
|
|
69
|
+
() => void 0
|
|
70
|
+
);
|
|
71
|
+
return { replayUrl };
|
|
69
72
|
}
|
|
70
73
|
};
|
|
71
74
|
}
|
|
@@ -153,8 +156,24 @@ async function closeCloudSession(endpoint, apiKey, sessionId) {
|
|
|
153
156
|
`Libretto Cloud API error closing session ${sessionId} (${resp.status}): ${body}`
|
|
154
157
|
);
|
|
155
158
|
}
|
|
159
|
+
}
|
|
160
|
+
async function getCloudRecordingUrl(endpoint, apiKey, sessionId) {
|
|
161
|
+
const resp = await fetch(`${endpoint}/v1/recordings/get`, {
|
|
162
|
+
method: "POST",
|
|
163
|
+
headers: {
|
|
164
|
+
"x-api-key": apiKey,
|
|
165
|
+
"Content-Type": "application/json"
|
|
166
|
+
},
|
|
167
|
+
body: JSON.stringify({ json: { session_id: sessionId } })
|
|
168
|
+
});
|
|
169
|
+
if (!resp.ok) {
|
|
170
|
+
const body = await resp.text();
|
|
171
|
+
throw new Error(
|
|
172
|
+
`Libretto Cloud API error reading recording for session ${sessionId} (${resp.status}): ${body}`
|
|
173
|
+
);
|
|
174
|
+
}
|
|
156
175
|
const { json } = await resp.json();
|
|
157
|
-
return json;
|
|
176
|
+
return json.recording_url ?? void 0;
|
|
158
177
|
}
|
|
159
178
|
function createStartupSessionCleanup(endpoint, apiKey, sessionId) {
|
|
160
179
|
let cancelled = false;
|
|
@@ -68,115 +68,28 @@ function readInstalledSkillVersions() {
|
|
|
68
68
|
}
|
|
69
69
|
return [...versions];
|
|
70
70
|
}
|
|
71
|
-
function
|
|
72
|
-
const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/);
|
|
73
|
-
if (!match) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
return {
|
|
77
|
-
major: Number(match[1]),
|
|
78
|
-
minor: Number(match[2]),
|
|
79
|
-
patch: Number(match[3]),
|
|
80
|
-
prerelease: match[4] ?? null
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function compareVersions(left, right) {
|
|
84
|
-
const parsedLeft = parseVersion(left);
|
|
85
|
-
const parsedRight = parseVersion(right);
|
|
86
|
-
if (!parsedLeft || !parsedRight) {
|
|
87
|
-
return left.localeCompare(right);
|
|
88
|
-
}
|
|
89
|
-
for (const key of ["major", "minor", "patch"]) {
|
|
90
|
-
const diff = parsedLeft[key] - parsedRight[key];
|
|
91
|
-
if (diff !== 0) {
|
|
92
|
-
return diff;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (parsedLeft.prerelease === parsedRight.prerelease) {
|
|
96
|
-
return 0;
|
|
97
|
-
}
|
|
98
|
-
if (parsedLeft.prerelease === null) {
|
|
99
|
-
return 1;
|
|
100
|
-
}
|
|
101
|
-
if (parsedRight.prerelease === null) {
|
|
102
|
-
return -1;
|
|
103
|
-
}
|
|
104
|
-
return parsedLeft.prerelease.localeCompare(parsedRight.prerelease);
|
|
105
|
-
}
|
|
106
|
-
function selectTargetVersion(versions) {
|
|
107
|
-
const counts = /* @__PURE__ */ new Map();
|
|
108
|
-
for (const version of versions) {
|
|
109
|
-
counts.set(version, (counts.get(version) ?? 0) + 1);
|
|
110
|
-
}
|
|
111
|
-
const byCountThenVersion = [...counts.entries()].sort(
|
|
112
|
-
([leftVersion, leftCount], [rightVersion, rightCount]) => rightCount - leftCount || compareVersions(rightVersion, leftVersion)
|
|
113
|
-
);
|
|
114
|
-
return byCountThenVersion[0]?.[0] ?? versions[0] ?? "latest";
|
|
115
|
-
}
|
|
116
|
-
function formatVersion(version, targetVersion) {
|
|
117
|
-
return version === targetVersion ? version : `${version} (out of date)`;
|
|
118
|
-
}
|
|
119
|
-
function formatSkillVersions(versions, targetVersion) {
|
|
71
|
+
function formatSkillVersions(versions) {
|
|
120
72
|
if (versions.length === 0) {
|
|
121
73
|
return "not installed";
|
|
122
74
|
}
|
|
123
|
-
return versions.
|
|
124
|
-
}
|
|
125
|
-
function formatUpdateInstructions(components) {
|
|
126
|
-
const instructions = [];
|
|
127
|
-
if (components.cliVersion !== components.targetVersion) {
|
|
128
|
-
instructions.push(
|
|
129
|
-
` global CLI: curl -fsSL https://libretto.sh/install.sh | LIBRETTO_VERSION=${components.targetVersion} bash`
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
if (components.localPackageVersion && components.localPackageVersion !== components.targetVersion) {
|
|
133
|
-
instructions.push(
|
|
134
|
-
` local package: npm install libretto@${components.targetVersion}`
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
if (components.skillVersions.length > 0 && components.skillVersions.some(
|
|
138
|
-
(skillVersion) => skillVersion !== components.targetVersion
|
|
139
|
-
)) {
|
|
140
|
-
instructions.push(" agent skill: libretto setup");
|
|
141
|
-
}
|
|
142
|
-
return instructions;
|
|
75
|
+
return versions.join(", ");
|
|
143
76
|
}
|
|
144
77
|
function formatVersionWarning(components) {
|
|
145
|
-
const targetVersion = selectTargetVersion([
|
|
146
|
-
components.cliVersion,
|
|
147
|
-
...components.localPackageVersion ? [components.localPackageVersion] : [],
|
|
148
|
-
...components.skillVersions
|
|
149
|
-
]);
|
|
150
78
|
const skillLabel = components.skillVersions.length > 1 ? "agent skills" : "agent skill";
|
|
151
|
-
const updateInstructions = formatUpdateInstructions({
|
|
152
|
-
...components,
|
|
153
|
-
targetVersion
|
|
154
|
-
});
|
|
155
79
|
return [
|
|
156
|
-
"WARNING: Libretto version
|
|
157
|
-
|
|
158
|
-
`
|
|
159
|
-
|
|
160
|
-
` ${skillLabel}: ${formatSkillVersions(
|
|
161
|
-
components.skillVersions,
|
|
162
|
-
targetVersion
|
|
163
|
-
)}`,
|
|
164
|
-
"",
|
|
165
|
-
"How to update:",
|
|
166
|
-
...updateInstructions
|
|
80
|
+
"WARNING: Libretto skill version does not match the local package.",
|
|
81
|
+
` local package: ${components.localPackageVersion ?? `${components.cliVersion} (current command)`}`,
|
|
82
|
+
` ${skillLabel}: ${formatSkillVersions(components.skillVersions)}`,
|
|
83
|
+
"Fix: run libretto setup"
|
|
167
84
|
].join("\n");
|
|
168
85
|
}
|
|
169
86
|
function warnIfLibrettoVersionsDiffer() {
|
|
170
87
|
try {
|
|
171
88
|
const cliVersion = readCurrentCliVersion();
|
|
172
89
|
const localPackageVersion = readLocalPackageVersion();
|
|
90
|
+
const packageVersion = localPackageVersion ?? cliVersion;
|
|
173
91
|
const skillVersions = readInstalledSkillVersions();
|
|
174
|
-
|
|
175
|
-
cliVersion,
|
|
176
|
-
...localPackageVersion ? [localPackageVersion] : [],
|
|
177
|
-
...skillVersions
|
|
178
|
-
]);
|
|
179
|
-
if (observedVersions.size <= 1) {
|
|
92
|
+
if (skillVersions.length === 0 || skillVersions.every((skillVersion) => skillVersion === packageVersion)) {
|
|
180
93
|
return;
|
|
181
94
|
}
|
|
182
95
|
console.error(
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export { InstrumentationOptions, InstrumentedPage, installInstrumentation, instr
|
|
|
12
12
|
export { GhostCursorOptions, ensureGhostCursor, ghostClick, hideGhostCursor, moveGhostCursor } from './shared/visualization/ghost-cursor.js';
|
|
13
13
|
export { HighlightOptions, clearHighlights, ensureHighlightLayer, showHighlight } from './shared/visualization/highlight.js';
|
|
14
14
|
export { BrowserSession, LaunchBrowserArgs, launchBrowser } from './shared/run/browser.js';
|
|
15
|
-
export { ExportedLibrettoWorkflow, LIBRETTO_WORKFLOW_BRAND, LibrettoWorkflow, LibrettoWorkflowContext, LibrettoWorkflowHandler, LibrettoWorkflowInputError, LibrettoWorkflowSchemas, getDefaultWorkflowFromModuleExports, getWorkflowFromModuleExports, getWorkflowsFromModuleExports, isLibrettoWorkflow, workflow } from './shared/workflow/workflow.js';
|
|
15
|
+
export { ExportedLibrettoWorkflow, LIBRETTO_WORKFLOW_BRAND, LibrettoWorkflow, LibrettoWorkflowContext, LibrettoWorkflowHandler, LibrettoWorkflowInputError, LibrettoWorkflowSchemas, WorkflowInputValidator, getDefaultWorkflowFromModuleExports, getWorkflowFromModuleExports, getWorkflowsFromModuleExports, isLibrettoWorkflow, validateWorkflowInput, workflow } from './shared/workflow/workflow.js';
|
|
16
16
|
import 'zod';
|
|
17
17
|
import 'playwright';
|
|
18
18
|
import 'ai';
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
LibrettoWorkflow,
|
|
60
60
|
LibrettoWorkflowInputError,
|
|
61
61
|
LIBRETTO_WORKFLOW_BRAND,
|
|
62
|
+
validateWorkflowInput,
|
|
62
63
|
workflow
|
|
63
64
|
} from "./shared/workflow/workflow.js";
|
|
64
65
|
const isDirectExecution = () => {
|
|
@@ -113,5 +114,6 @@ export {
|
|
|
113
114
|
prettyConsoleSink,
|
|
114
115
|
serializeSessionState,
|
|
115
116
|
showHighlight,
|
|
117
|
+
validateWorkflowInput,
|
|
116
118
|
workflow
|
|
117
119
|
};
|
|
@@ -16,6 +16,11 @@ declare class LibrettoWorkflowInputError extends Error {
|
|
|
16
16
|
readonly zodError: z.ZodError;
|
|
17
17
|
constructor(workflowName: string, zodError: z.ZodError);
|
|
18
18
|
}
|
|
19
|
+
type WorkflowInputValidator = {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly inputSchema?: z.ZodType;
|
|
22
|
+
};
|
|
23
|
+
declare function validateWorkflowInput(workflow: WorkflowInputValidator, input: unknown): void;
|
|
19
24
|
declare class LibrettoWorkflow<InputSchema extends z.ZodType = z.ZodType<unknown>, OutputSchema extends z.ZodType = z.ZodType<unknown>> {
|
|
20
25
|
readonly [LIBRETTO_WORKFLOW_BRAND] = true;
|
|
21
26
|
readonly name: string;
|
|
@@ -40,4 +45,4 @@ declare function getWorkflowFromModuleExports(moduleExports: WorkflowModuleExpor
|
|
|
40
45
|
declare function workflow<InputSchema extends z.ZodType, OutputSchema extends z.ZodType>(name: string, schemas: LibrettoWorkflowSchemas<InputSchema, OutputSchema>, handler: LibrettoWorkflowHandler<z.infer<InputSchema>, z.infer<OutputSchema>>): LibrettoWorkflow<InputSchema, OutputSchema>;
|
|
41
46
|
declare function workflow<Input = unknown, Output = unknown>(name: string, handler: LibrettoWorkflowHandler<Input, Output>): LibrettoWorkflow<z.ZodType<Input>, z.ZodType<Output>>;
|
|
42
47
|
|
|
43
|
-
export { type ExportedLibrettoWorkflow, LIBRETTO_WORKFLOW_BRAND, LibrettoWorkflow, type LibrettoWorkflowContext, type LibrettoWorkflowHandler, LibrettoWorkflowInputError, type LibrettoWorkflowSchemas, getDefaultWorkflowFromModuleExports, getWorkflowFromModuleExports, getWorkflowsFromModuleExports, isLibrettoWorkflow, workflow };
|
|
48
|
+
export { type ExportedLibrettoWorkflow, LIBRETTO_WORKFLOW_BRAND, LibrettoWorkflow, type LibrettoWorkflowContext, type LibrettoWorkflowHandler, LibrettoWorkflowInputError, type LibrettoWorkflowSchemas, type WorkflowInputValidator, getDefaultWorkflowFromModuleExports, getWorkflowFromModuleExports, getWorkflowsFromModuleExports, isLibrettoWorkflow, validateWorkflowInput, workflow };
|
|
@@ -19,6 +19,17 @@ function formatZodErrorMessage(workflowName, zodError) {
|
|
|
19
19
|
...lines
|
|
20
20
|
].join("\n");
|
|
21
21
|
}
|
|
22
|
+
function parseWorkflowInput(workflowName, inputSchema, input) {
|
|
23
|
+
if (!inputSchema) return input;
|
|
24
|
+
const result = inputSchema.safeParse(input);
|
|
25
|
+
if (!result.success) {
|
|
26
|
+
throw new LibrettoWorkflowInputError(workflowName, result.error);
|
|
27
|
+
}
|
|
28
|
+
return result.data;
|
|
29
|
+
}
|
|
30
|
+
function validateWorkflowInput(workflow2, input) {
|
|
31
|
+
parseWorkflowInput(workflow2.name, workflow2.inputSchema, input);
|
|
32
|
+
}
|
|
22
33
|
class LibrettoWorkflow {
|
|
23
34
|
[LIBRETTO_WORKFLOW_BRAND] = true;
|
|
24
35
|
name;
|
|
@@ -38,16 +49,7 @@ class LibrettoWorkflow {
|
|
|
38
49
|
this.handler = handler;
|
|
39
50
|
}
|
|
40
51
|
async run(ctx, input) {
|
|
41
|
-
|
|
42
|
-
if (this.inputSchema) {
|
|
43
|
-
const result = this.inputSchema.safeParse(input);
|
|
44
|
-
if (!result.success) {
|
|
45
|
-
throw new LibrettoWorkflowInputError(this.name, result.error);
|
|
46
|
-
}
|
|
47
|
-
parsed = result.data;
|
|
48
|
-
} else {
|
|
49
|
-
parsed = input;
|
|
50
|
-
}
|
|
52
|
+
const parsed = parseWorkflowInput(this.name, this.inputSchema, input);
|
|
51
53
|
return this.handler(ctx, parsed);
|
|
52
54
|
}
|
|
53
55
|
}
|
|
@@ -118,5 +120,6 @@ export {
|
|
|
118
120
|
getWorkflowFromModuleExports,
|
|
119
121
|
getWorkflowsFromModuleExports,
|
|
120
122
|
isLibrettoWorkflow,
|
|
123
|
+
validateWorkflowInput,
|
|
121
124
|
workflow
|
|
122
125
|
};
|