libretto 0.2.4 → 0.2.6
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 +34 -3
- package/dist/cli/cli.js +4 -2
- package/dist/cli/commands/browser.js +26 -3
- package/dist/cli/commands/execution.js +50 -11
- package/dist/cli/core/browser.js +131 -6
- package/dist/cli/core/session.js +13 -13
- package/dist/cli/workers/run-integration-runtime.js +64 -59
- package/dist/cli/workers/run-integration-worker-protocol.js +12 -0
- package/dist/cli/workers/run-integration-worker.js +13 -30
- package/dist/index.cjs +2 -12
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -15
- package/dist/shared/debug/index.cjs +4 -6
- package/dist/shared/debug/index.d.cts +1 -2
- package/dist/shared/debug/index.d.ts +1 -2
- package/dist/shared/debug/index.js +3 -8
- package/dist/shared/debug/pause.cjs +58 -24
- package/dist/shared/debug/pause.d.cts +13 -20
- package/dist/shared/debug/pause.d.ts +13 -20
- package/dist/shared/debug/pause.js +46 -21
- package/dist/shared/llm/ai-sdk-adapter.cjs +7 -1
- package/dist/shared/llm/ai-sdk-adapter.js +7 -1
- package/dist/shared/run/api.cjs +0 -7
- package/dist/shared/run/api.d.cts +0 -1
- package/dist/shared/run/api.d.ts +0 -1
- package/dist/shared/run/api.js +0 -8
- package/dist/shared/workflow/workflow.d.cts +11 -24
- package/dist/shared/workflow/workflow.d.ts +11 -24
- package/package.json +10 -4
- package/skill/SKILL.md +18 -5
- package/skill/code-generation-rules.md +43 -10
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import { appendFileSync, existsSync } from "node:fs";
|
|
2
|
-
import {
|
|
1
|
+
import { appendFileSync, existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { writeFile } from "node:fs/promises";
|
|
3
3
|
import { cwd } from "node:process";
|
|
4
4
|
import { isAbsolute, resolve } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
import {
|
|
7
7
|
launchBrowser
|
|
8
8
|
} from "../../index.js";
|
|
9
|
+
import { setSessionForPause } from "../../shared/debug/pause.js";
|
|
10
|
+
import { parseSessionStateContent } from "../../shared/state/index.js";
|
|
9
11
|
import { getProfilePath, normalizeDomain } from "../core/browser.js";
|
|
10
12
|
import {
|
|
11
13
|
getSessionActionsLogPath,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
getSessionNetworkLogPath,
|
|
15
|
+
getSessionStatePath
|
|
14
16
|
} from "../core/context.js";
|
|
15
17
|
import { getPauseSignalPaths, removeSignalIfExists } from "../core/pause-signals.js";
|
|
16
18
|
import { installSessionTelemetry } from "../core/session-telemetry.js";
|
|
17
19
|
const LIBRETTO_WORKFLOW_BRAND = /* @__PURE__ */ Symbol.for("libretto.workflow");
|
|
18
|
-
const
|
|
20
|
+
const FAILURE_HOLD_POLL_INTERVAL_MS = 250;
|
|
19
21
|
function mirrorStdoutToFile(filePath) {
|
|
20
22
|
const stdout = process.stdout;
|
|
21
23
|
const originalWrite = stdout.write.bind(stdout);
|
|
@@ -31,23 +33,32 @@ function mirrorStdoutToFile(filePath) {
|
|
|
31
33
|
stdout.write = originalWrite;
|
|
32
34
|
};
|
|
33
35
|
}
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
function readSessionStatePid(session) {
|
|
37
|
+
const statePath = getSessionStatePath(session);
|
|
38
|
+
if (!existsSync(statePath)) return null;
|
|
39
|
+
try {
|
|
40
|
+
return parseSessionStateContent(readFileSync(statePath, "utf8"), statePath).pid;
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function waitForFailureSessionRelease(args) {
|
|
46
|
+
const { session, expectedPid, logger } = args;
|
|
47
|
+
logger.info("run-failure-session-hold", { session, expectedPid });
|
|
48
|
+
while (true) {
|
|
49
|
+
const currentPid = readSessionStatePid(session);
|
|
50
|
+
if (currentPid !== expectedPid) {
|
|
51
|
+
logger.info("run-failure-session-released", {
|
|
52
|
+
session,
|
|
53
|
+
expectedPid,
|
|
54
|
+
currentPid
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
45
58
|
await new Promise(
|
|
46
|
-
(resolveWait) => setTimeout(resolveWait,
|
|
59
|
+
(resolveWait) => setTimeout(resolveWait, FAILURE_HOLD_POLL_INTERVAL_MS)
|
|
47
60
|
);
|
|
48
61
|
}
|
|
49
|
-
await removeSignalIfExists(resumeSignalPath);
|
|
50
|
-
await removeSignalIfExists(pausedSignalPath);
|
|
51
62
|
}
|
|
52
63
|
function isLoadedLibrettoWorkflow(value) {
|
|
53
64
|
if (!value || typeof value !== "object") return false;
|
|
@@ -57,13 +68,6 @@ function isLoadedLibrettoWorkflow(value) {
|
|
|
57
68
|
function resolveLocalAuthProfilePath(domain) {
|
|
58
69
|
return getProfilePath(normalizeDomain(domain));
|
|
59
70
|
}
|
|
60
|
-
function resolveWorkflowStorageStatePath(workflow) {
|
|
61
|
-
const authProfile = workflow.metadata.authProfile;
|
|
62
|
-
if (authProfile?.type !== "local") {
|
|
63
|
-
return void 0;
|
|
64
|
-
}
|
|
65
|
-
return resolveLocalAuthProfilePath(authProfile.domain);
|
|
66
|
-
}
|
|
67
71
|
function getMissingLocalAuthProfileError(args) {
|
|
68
72
|
const normalizedDomain = normalizeDomain(args.domain);
|
|
69
73
|
return [
|
|
@@ -101,7 +105,24 @@ async function loadWorkflowExport(absolutePath, exportName) {
|
|
|
101
105
|
}
|
|
102
106
|
if (!isLoadedLibrettoWorkflow(targetExport)) {
|
|
103
107
|
throw new Error(
|
|
104
|
-
|
|
108
|
+
[
|
|
109
|
+
`Export "${exportName}" in ${absolutePath} is not a valid Libretto workflow.`,
|
|
110
|
+
"",
|
|
111
|
+
'A workflow must be created using the workflow() function from "libretto":',
|
|
112
|
+
"",
|
|
113
|
+
' import { workflow } from "libretto";',
|
|
114
|
+
"",
|
|
115
|
+
` export const ${exportName} = workflow<InputType, OutputType>(`,
|
|
116
|
+
" {},",
|
|
117
|
+
" async (ctx, input) => {",
|
|
118
|
+
" // ctx.page \u2014 Playwright Page instance",
|
|
119
|
+
" // ctx.logger \u2014 MinimalLogger",
|
|
120
|
+
" // ctx.services \u2014 injected dependencies (generic, default {})",
|
|
121
|
+
" // input \u2014 JSON-serializable input matching InputType",
|
|
122
|
+
" return output; // must match OutputType",
|
|
123
|
+
" },",
|
|
124
|
+
" );"
|
|
125
|
+
].join("\n")
|
|
105
126
|
);
|
|
106
127
|
}
|
|
107
128
|
return targetExport;
|
|
@@ -125,12 +146,12 @@ async function runIntegrationInternal(args, options) {
|
|
|
125
146
|
integrationExport: args.exportName,
|
|
126
147
|
session: args.session
|
|
127
148
|
});
|
|
128
|
-
const
|
|
129
|
-
const storageStatePath =
|
|
130
|
-
if (
|
|
149
|
+
const authProfileDomain = args.authProfileDomain;
|
|
150
|
+
const storageStatePath = authProfileDomain ? resolveLocalAuthProfilePath(authProfileDomain) : void 0;
|
|
151
|
+
if (authProfileDomain && storageStatePath && !existsSync(storageStatePath)) {
|
|
131
152
|
throw new Error(
|
|
132
153
|
getMissingLocalAuthProfileError({
|
|
133
|
-
domain:
|
|
154
|
+
domain: authProfileDomain,
|
|
134
155
|
profilePath: storageStatePath,
|
|
135
156
|
session: args.session
|
|
136
157
|
})
|
|
@@ -154,50 +175,35 @@ async function runIntegrationInternal(args, options) {
|
|
|
154
175
|
appendFileSync(networkLogPath, JSON.stringify(entry) + "\n");
|
|
155
176
|
}
|
|
156
177
|
});
|
|
178
|
+
setSessionForPause(args.session);
|
|
157
179
|
const workflowContext = {
|
|
158
180
|
logger: integrationLogger,
|
|
159
181
|
page: browserSession.page,
|
|
160
|
-
|
|
161
|
-
browser: browserSession.browser,
|
|
162
|
-
session: args.session,
|
|
163
|
-
integrationPath: absolutePath,
|
|
164
|
-
exportName: args.exportName,
|
|
165
|
-
headless: args.headless,
|
|
166
|
-
debug: args.debug,
|
|
167
|
-
pause: async () => {
|
|
168
|
-
const details = {
|
|
169
|
-
sessionName: args.session,
|
|
170
|
-
pausedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
171
|
-
url: browserSession.page.url()
|
|
172
|
-
};
|
|
173
|
-
console.log(`[pause] Paused at ${details.url}`);
|
|
174
|
-
console.log("[pause] Waiting for resume signal...");
|
|
175
|
-
await waitForResumeSignal({
|
|
176
|
-
signalPaths,
|
|
177
|
-
session: args.session,
|
|
178
|
-
details,
|
|
179
|
-
onPaused: options.onPaused
|
|
180
|
-
});
|
|
181
|
-
console.log("[pause] Resume signal received. Continuing workflow...");
|
|
182
|
-
}
|
|
182
|
+
services: {}
|
|
183
183
|
};
|
|
184
184
|
try {
|
|
185
185
|
try {
|
|
186
186
|
await workflow.run(workflowContext, args.params ?? {});
|
|
187
187
|
} catch (error) {
|
|
188
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
188
189
|
await writeFile(
|
|
189
190
|
signalPaths.failedSignalPath,
|
|
190
191
|
JSON.stringify(
|
|
191
192
|
{
|
|
192
193
|
failedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
193
|
-
message:
|
|
194
|
+
message: errorMessage
|
|
194
195
|
},
|
|
195
196
|
null,
|
|
196
197
|
2
|
|
197
198
|
),
|
|
198
199
|
"utf8"
|
|
199
200
|
);
|
|
200
|
-
|
|
201
|
+
await waitForFailureSessionRelease({
|
|
202
|
+
session: args.session,
|
|
203
|
+
expectedPid: process.pid,
|
|
204
|
+
logger
|
|
205
|
+
});
|
|
206
|
+
return { status: "failed-held" };
|
|
201
207
|
}
|
|
202
208
|
await writeFile(
|
|
203
209
|
signalPaths.completedSignalPath,
|
|
@@ -211,10 +217,9 @@ async function runIntegrationInternal(args, options) {
|
|
|
211
217
|
await browserSession.close();
|
|
212
218
|
}
|
|
213
219
|
}
|
|
214
|
-
async function runIntegrationFromFileInWorker(args, logger
|
|
220
|
+
async function runIntegrationFromFileInWorker(args, logger) {
|
|
215
221
|
return await runIntegrationInternal(args, {
|
|
216
|
-
logger
|
|
217
|
-
onPaused
|
|
222
|
+
logger
|
|
218
223
|
});
|
|
219
224
|
}
|
|
220
225
|
export {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const RunIntegrationWorkerRequestSchema = z.object({
|
|
3
|
+
integrationPath: z.string().min(1),
|
|
4
|
+
exportName: z.string().min(1),
|
|
5
|
+
session: z.string().min(1),
|
|
6
|
+
params: z.unknown(),
|
|
7
|
+
headless: z.boolean(),
|
|
8
|
+
authProfileDomain: z.string().optional()
|
|
9
|
+
});
|
|
10
|
+
export {
|
|
11
|
+
RunIntegrationWorkerRequestSchema
|
|
12
|
+
};
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { ZodError } from "zod";
|
|
3
|
+
import {
|
|
4
|
+
RunIntegrationWorkerRequestSchema
|
|
5
|
+
} from "./run-integration-worker-protocol.js";
|
|
2
6
|
import { runIntegrationFromFileInWorker } from "./run-integration-runtime.js";
|
|
3
7
|
import {
|
|
4
8
|
ensureLibrettoSetup,
|
|
5
9
|
withSessionLogger
|
|
6
10
|
} from "../core/context.js";
|
|
7
11
|
import { getPauseSignalPaths } from "../core/pause-signals.js";
|
|
8
|
-
function sendMessage(message) {
|
|
9
|
-
if (typeof process.send !== "function" || !process.connected) return;
|
|
10
|
-
try {
|
|
11
|
-
process.send(message);
|
|
12
|
-
} catch {
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
12
|
function parseWorkerRequest(argv) {
|
|
16
13
|
const rawPayload = argv[2];
|
|
17
14
|
if (!rawPayload) {
|
|
@@ -25,21 +22,15 @@ function parseWorkerRequest(argv) {
|
|
|
25
22
|
`Invalid worker payload JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
26
23
|
);
|
|
27
24
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
try {
|
|
26
|
+
return RunIntegrationWorkerRequestSchema.parse(parsed);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
if (error instanceof ZodError) {
|
|
29
|
+
const details = error.issues.map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`).join("; ");
|
|
30
|
+
throw new Error(`Worker payload is invalid: ${details}`);
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
34
33
|
}
|
|
35
|
-
return {
|
|
36
|
-
integrationPath: candidate.integrationPath,
|
|
37
|
-
exportName: candidate.exportName,
|
|
38
|
-
session: candidate.session,
|
|
39
|
-
headless: candidate.headless,
|
|
40
|
-
debug: candidate.debug,
|
|
41
|
-
params: candidate.params
|
|
42
|
-
};
|
|
43
34
|
}
|
|
44
35
|
async function main() {
|
|
45
36
|
let request = null;
|
|
@@ -49,15 +40,8 @@ async function main() {
|
|
|
49
40
|
const workerRequest = request;
|
|
50
41
|
ensureLibrettoSetup();
|
|
51
42
|
await withSessionLogger(workerRequest.session, async (logger) => {
|
|
52
|
-
await runIntegrationFromFileInWorker(
|
|
53
|
-
workerRequest,
|
|
54
|
-
logger,
|
|
55
|
-
async (details) => {
|
|
56
|
-
sendMessage({ type: "paused", details });
|
|
57
|
-
}
|
|
58
|
-
);
|
|
43
|
+
await runIntegrationFromFileInWorker(workerRequest, logger);
|
|
59
44
|
});
|
|
60
|
-
sendMessage({ type: "completed" });
|
|
61
45
|
} catch (error) {
|
|
62
46
|
const message = error instanceof Error ? error.message : String(error);
|
|
63
47
|
if (request) {
|
|
@@ -75,7 +59,6 @@ async function main() {
|
|
|
75
59
|
"utf8"
|
|
76
60
|
);
|
|
77
61
|
}
|
|
78
|
-
sendMessage({ type: "failed", message });
|
|
79
62
|
exitCode = 1;
|
|
80
63
|
}
|
|
81
64
|
process.exit(exitCode);
|
package/dist/index.cjs
CHANGED
|
@@ -18,11 +18,9 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var index_exports = {};
|
|
20
20
|
__export(index_exports, {
|
|
21
|
-
DebugPauseSignal: () => import_pause.DebugPauseSignal,
|
|
22
21
|
LIBRETTO_WORKFLOW_BRAND: () => import_workflow.LIBRETTO_WORKFLOW_BRAND,
|
|
23
22
|
LibrettoWorkflow: () => import_workflow.LibrettoWorkflow,
|
|
24
23
|
Logger: () => import_logger.Logger,
|
|
25
|
-
RunDebugPauseSignal: () => import_api.DebugPauseSignal,
|
|
26
24
|
SESSION_STATE_VERSION: () => import_state.SESSION_STATE_VERSION,
|
|
27
25
|
SessionStateFileSchema: () => import_state.SessionStateFileSchema,
|
|
28
26
|
SessionStatusSchema: () => import_state.SessionStatusSchema,
|
|
@@ -30,7 +28,6 @@ __export(index_exports, {
|
|
|
30
28
|
clearHighlights: () => import_highlight.clearHighlights,
|
|
31
29
|
createFileLogSink: () => import_sinks.createFileLogSink,
|
|
32
30
|
createLLMClientFromModel: () => import_ai_sdk_adapter.createLLMClientFromModel,
|
|
33
|
-
debugPause: () => import_pause.debugPause,
|
|
34
31
|
defaultLogger: () => import_logger.defaultLogger,
|
|
35
32
|
detectSubmissionError: () => import_errors.detectSubmissionError,
|
|
36
33
|
downloadAndSave: () => import_download.downloadAndSave,
|
|
@@ -45,17 +42,15 @@ __export(index_exports, {
|
|
|
45
42
|
instrumentContext: () => import_instrument.instrumentContext,
|
|
46
43
|
instrumentPage: () => import_instrument.instrumentPage,
|
|
47
44
|
isDebugMode: () => import_config.isDebugMode,
|
|
48
|
-
isDebugPauseSignal: () => import_pause.isDebugPauseSignal,
|
|
49
45
|
isDryRun: () => import_config.isDryRun,
|
|
50
|
-
isRunDebugPauseSignal: () => import_api.isDebugPauseSignal,
|
|
51
46
|
jsonlConsoleSink: () => import_sinks.jsonlConsoleSink,
|
|
52
47
|
launchBrowser: () => import_api.launchBrowser,
|
|
53
48
|
moveGhostCursor: () => import_ghost_cursor.moveGhostCursor,
|
|
54
49
|
pageRequest: () => import_network.pageRequest,
|
|
55
50
|
parseSessionStateContent: () => import_state.parseSessionStateContent,
|
|
56
51
|
parseSessionStateData: () => import_state.parseSessionStateData,
|
|
52
|
+
pause: () => import_pause.pause,
|
|
57
53
|
prettyConsoleSink: () => import_sinks.prettyConsoleSink,
|
|
58
|
-
runDebugPause: () => import_api.debugPause,
|
|
59
54
|
serializeSessionState: () => import_state.serializeSessionState,
|
|
60
55
|
shouldPauseBeforeMutation: () => import_config.shouldPauseBeforeMutation,
|
|
61
56
|
showHighlight: () => import_highlight.showHighlight,
|
|
@@ -81,11 +76,9 @@ var import_api = require("./shared/run/api.js");
|
|
|
81
76
|
var import_workflow = require("./shared/workflow/workflow.js");
|
|
82
77
|
// Annotate the CommonJS export names for ESM import in node:
|
|
83
78
|
0 && (module.exports = {
|
|
84
|
-
DebugPauseSignal,
|
|
85
79
|
LIBRETTO_WORKFLOW_BRAND,
|
|
86
80
|
LibrettoWorkflow,
|
|
87
81
|
Logger,
|
|
88
|
-
RunDebugPauseSignal,
|
|
89
82
|
SESSION_STATE_VERSION,
|
|
90
83
|
SessionStateFileSchema,
|
|
91
84
|
SessionStatusSchema,
|
|
@@ -93,7 +86,6 @@ var import_workflow = require("./shared/workflow/workflow.js");
|
|
|
93
86
|
clearHighlights,
|
|
94
87
|
createFileLogSink,
|
|
95
88
|
createLLMClientFromModel,
|
|
96
|
-
debugPause,
|
|
97
89
|
defaultLogger,
|
|
98
90
|
detectSubmissionError,
|
|
99
91
|
downloadAndSave,
|
|
@@ -108,17 +100,15 @@ var import_workflow = require("./shared/workflow/workflow.js");
|
|
|
108
100
|
instrumentContext,
|
|
109
101
|
instrumentPage,
|
|
110
102
|
isDebugMode,
|
|
111
|
-
isDebugPauseSignal,
|
|
112
103
|
isDryRun,
|
|
113
|
-
isRunDebugPauseSignal,
|
|
114
104
|
jsonlConsoleSink,
|
|
115
105
|
launchBrowser,
|
|
116
106
|
moveGhostCursor,
|
|
117
107
|
pageRequest,
|
|
118
108
|
parseSessionStateContent,
|
|
119
109
|
parseSessionStateData,
|
|
110
|
+
pause,
|
|
120
111
|
prettyConsoleSink,
|
|
121
|
-
runDebugPause,
|
|
122
112
|
serializeSessionState,
|
|
123
113
|
shouldPauseBeforeMutation,
|
|
124
114
|
showHighlight,
|
package/dist/index.d.cts
CHANGED
|
@@ -9,13 +9,13 @@ export { DetectedSubmissionError, KnownSubmissionError, detectSubmissionError }
|
|
|
9
9
|
export { ExtractOptions, extractFromPage } from './runtime/extract/extract.cjs';
|
|
10
10
|
export { PageRequestOptions, RequestConfig, pageRequest } from './runtime/network/network.cjs';
|
|
11
11
|
export { DownloadResult, DownloadViaClickOptions, SaveDownloadOptions, downloadAndSave, downloadViaClick } from './runtime/download/download.cjs';
|
|
12
|
-
export {
|
|
12
|
+
export { pause } from './shared/debug/pause.cjs';
|
|
13
13
|
export { isDebugMode, isDryRun, shouldPauseBeforeMutation } from './shared/config/config.cjs';
|
|
14
14
|
export { InstrumentationOptions, InstrumentedPage, installInstrumentation, instrumentContext, instrumentPage } from './shared/instrumentation/instrument.cjs';
|
|
15
15
|
export { GhostCursorOptions, ensureGhostCursor, ghostClick, hideGhostCursor, moveGhostCursor } from './shared/visualization/ghost-cursor.cjs';
|
|
16
16
|
export { HighlightOptions, clearHighlights, ensureHighlightLayer, showHighlight } from './shared/visualization/highlight.cjs';
|
|
17
17
|
export { BrowserSession, LaunchBrowserArgs, launchBrowser } from './shared/run/browser.cjs';
|
|
18
|
-
export { LIBRETTO_WORKFLOW_BRAND,
|
|
18
|
+
export { LIBRETTO_WORKFLOW_BRAND, LibrettoWorkflow, LibrettoWorkflowContext, LibrettoWorkflowHandler, LibrettoWorkflowMetadata, workflow } from './shared/workflow/workflow.cjs';
|
|
19
19
|
import 'zod';
|
|
20
20
|
import 'ai';
|
|
21
21
|
import 'playwright';
|
package/dist/index.d.ts
CHANGED
|
@@ -9,13 +9,13 @@ export { DetectedSubmissionError, KnownSubmissionError, detectSubmissionError }
|
|
|
9
9
|
export { ExtractOptions, extractFromPage } from './runtime/extract/extract.js';
|
|
10
10
|
export { PageRequestOptions, RequestConfig, pageRequest } from './runtime/network/network.js';
|
|
11
11
|
export { DownloadResult, DownloadViaClickOptions, SaveDownloadOptions, downloadAndSave, downloadViaClick } from './runtime/download/download.js';
|
|
12
|
-
export {
|
|
12
|
+
export { pause } from './shared/debug/pause.js';
|
|
13
13
|
export { isDebugMode, isDryRun, shouldPauseBeforeMutation } from './shared/config/config.js';
|
|
14
14
|
export { InstrumentationOptions, InstrumentedPage, installInstrumentation, instrumentContext, instrumentPage } from './shared/instrumentation/instrument.js';
|
|
15
15
|
export { GhostCursorOptions, ensureGhostCursor, ghostClick, hideGhostCursor, moveGhostCursor } from './shared/visualization/ghost-cursor.js';
|
|
16
16
|
export { HighlightOptions, clearHighlights, ensureHighlightLayer, showHighlight } from './shared/visualization/highlight.js';
|
|
17
17
|
export { BrowserSession, LaunchBrowserArgs, launchBrowser } from './shared/run/browser.js';
|
|
18
|
-
export { LIBRETTO_WORKFLOW_BRAND,
|
|
18
|
+
export { LIBRETTO_WORKFLOW_BRAND, LibrettoWorkflow, LibrettoWorkflowContext, LibrettoWorkflowHandler, LibrettoWorkflowMetadata, workflow } from './shared/workflow/workflow.js';
|
|
19
19
|
import 'zod';
|
|
20
20
|
import 'ai';
|
|
21
21
|
import 'playwright';
|
package/dist/index.js
CHANGED
|
@@ -26,11 +26,7 @@ import {
|
|
|
26
26
|
downloadViaClick,
|
|
27
27
|
downloadAndSave
|
|
28
28
|
} from "./runtime/download/download.js";
|
|
29
|
-
import {
|
|
30
|
-
debugPause,
|
|
31
|
-
DebugPauseSignal,
|
|
32
|
-
isDebugPauseSignal
|
|
33
|
-
} from "./shared/debug/pause.js";
|
|
29
|
+
import { pause } from "./shared/debug/pause.js";
|
|
34
30
|
import {
|
|
35
31
|
isDebugMode,
|
|
36
32
|
isDryRun,
|
|
@@ -53,10 +49,7 @@ import {
|
|
|
53
49
|
clearHighlights
|
|
54
50
|
} from "./shared/visualization/highlight.js";
|
|
55
51
|
import {
|
|
56
|
-
launchBrowser
|
|
57
|
-
debugPause as debugPause2,
|
|
58
|
-
DebugPauseSignal as DebugPauseSignal2,
|
|
59
|
-
isDebugPauseSignal as isDebugPauseSignal2
|
|
52
|
+
launchBrowser
|
|
60
53
|
} from "./shared/run/api.js";
|
|
61
54
|
import {
|
|
62
55
|
LibrettoWorkflow,
|
|
@@ -64,11 +57,9 @@ import {
|
|
|
64
57
|
workflow
|
|
65
58
|
} from "./shared/workflow/workflow.js";
|
|
66
59
|
export {
|
|
67
|
-
DebugPauseSignal,
|
|
68
60
|
LIBRETTO_WORKFLOW_BRAND,
|
|
69
61
|
LibrettoWorkflow,
|
|
70
62
|
Logger,
|
|
71
|
-
DebugPauseSignal2 as RunDebugPauseSignal,
|
|
72
63
|
SESSION_STATE_VERSION,
|
|
73
64
|
SessionStateFileSchema,
|
|
74
65
|
SessionStatusSchema,
|
|
@@ -76,7 +67,6 @@ export {
|
|
|
76
67
|
clearHighlights,
|
|
77
68
|
createFileLogSink,
|
|
78
69
|
createLLMClientFromModel,
|
|
79
|
-
debugPause,
|
|
80
70
|
defaultLogger,
|
|
81
71
|
detectSubmissionError,
|
|
82
72
|
downloadAndSave,
|
|
@@ -91,17 +81,15 @@ export {
|
|
|
91
81
|
instrumentContext,
|
|
92
82
|
instrumentPage,
|
|
93
83
|
isDebugMode,
|
|
94
|
-
isDebugPauseSignal,
|
|
95
84
|
isDryRun,
|
|
96
|
-
isDebugPauseSignal2 as isRunDebugPauseSignal,
|
|
97
85
|
jsonlConsoleSink,
|
|
98
86
|
launchBrowser,
|
|
99
87
|
moveGhostCursor,
|
|
100
88
|
pageRequest,
|
|
101
89
|
parseSessionStateContent,
|
|
102
90
|
parseSessionStateData,
|
|
91
|
+
pause,
|
|
103
92
|
prettyConsoleSink,
|
|
104
|
-
debugPause2 as runDebugPause,
|
|
105
93
|
serializeSessionState,
|
|
106
94
|
shouldPauseBeforeMutation,
|
|
107
95
|
showHighlight,
|
|
@@ -18,15 +18,13 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var debug_exports = {};
|
|
20
20
|
__export(debug_exports, {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
isDebugPauseSignal: () => import_pause.isDebugPauseSignal
|
|
21
|
+
pause: () => import_pause.pause,
|
|
22
|
+
setSessionForPause: () => import_pause.setSessionForPause
|
|
24
23
|
});
|
|
25
24
|
module.exports = __toCommonJS(debug_exports);
|
|
26
25
|
var import_pause = require("./pause.js");
|
|
27
26
|
// Annotate the CommonJS export names for ESM import in node:
|
|
28
27
|
0 && (module.exports = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
isDebugPauseSignal
|
|
28
|
+
pause,
|
|
29
|
+
setSessionForPause
|
|
32
30
|
});
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
import 'playwright';
|
|
1
|
+
export { pause, setSessionForPause } from './pause.cjs';
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
import 'playwright';
|
|
1
|
+
export { pause, setSessionForPause } from './pause.js';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,42 +17,74 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
var pause_exports = {};
|
|
20
30
|
__export(pause_exports, {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
isDebugPauseSignal: () => isDebugPauseSignal
|
|
31
|
+
pause: () => pause,
|
|
32
|
+
setSessionForPause: () => setSessionForPause
|
|
24
33
|
});
|
|
25
34
|
module.exports = __toCommonJS(pause_exports);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
var import_node_fs = require("node:fs");
|
|
36
|
+
var import_promises = require("node:fs/promises");
|
|
37
|
+
let _sessionName;
|
|
38
|
+
function setSessionForPause(session) {
|
|
39
|
+
_sessionName = session;
|
|
40
|
+
}
|
|
41
|
+
function getSessionFromProcessArgs() {
|
|
42
|
+
const rawPayload = process.argv[2];
|
|
43
|
+
if (!rawPayload) return void 0;
|
|
44
|
+
try {
|
|
45
|
+
const parsed = JSON.parse(rawPayload);
|
|
46
|
+
return typeof parsed.session === "string" ? parsed.session : void 0;
|
|
47
|
+
} catch {
|
|
48
|
+
return void 0;
|
|
32
49
|
}
|
|
33
50
|
}
|
|
34
|
-
function
|
|
35
|
-
|
|
36
|
-
const candidate = error;
|
|
37
|
-
if (candidate.name !== "DebugPauseSignal") return false;
|
|
38
|
-
return typeof candidate.details?.sessionName === "string" && typeof candidate.details?.pausedAt === "string" && typeof candidate.details?.url === "string";
|
|
51
|
+
function resolveSession() {
|
|
52
|
+
return _sessionName ?? getSessionFromProcessArgs();
|
|
39
53
|
}
|
|
40
|
-
async function
|
|
41
|
-
|
|
54
|
+
async function pause() {
|
|
55
|
+
if (process.env.NODE_ENV === "production") {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const session = resolveSession();
|
|
59
|
+
if (!session) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const { getPauseSignalPaths, removeSignalIfExists } = await import("../../cli/core/pause-signals.js");
|
|
63
|
+
const { getSessionDir } = await import("../../cli/core/context.js");
|
|
64
|
+
const signalPaths = getPauseSignalPaths(session);
|
|
65
|
+
const { pausedSignalPath, resumeSignalPath } = signalPaths;
|
|
66
|
+
await (0, import_promises.mkdir)(getSessionDir(session), { recursive: true });
|
|
67
|
+
await removeSignalIfExists(resumeSignalPath);
|
|
42
68
|
const details = {
|
|
43
|
-
sessionName:
|
|
69
|
+
sessionName: session,
|
|
44
70
|
pausedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45
|
-
url
|
|
71
|
+
url: "unknown"
|
|
46
72
|
};
|
|
47
|
-
|
|
48
|
-
console.log(
|
|
49
|
-
|
|
73
|
+
await (0, import_promises.writeFile)(pausedSignalPath, JSON.stringify(details, null, 2), "utf8");
|
|
74
|
+
console.log(`[pause] Paused (session: ${session})`);
|
|
75
|
+
console.log("[pause] Waiting for resume signal...");
|
|
76
|
+
const RESUME_POLL_INTERVAL_MS = 250;
|
|
77
|
+
while (!(0, import_node_fs.existsSync)(resumeSignalPath)) {
|
|
78
|
+
await new Promise(
|
|
79
|
+
(resolve) => setTimeout(resolve, RESUME_POLL_INTERVAL_MS)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
await removeSignalIfExists(resumeSignalPath);
|
|
83
|
+
await removeSignalIfExists(pausedSignalPath);
|
|
84
|
+
console.log("[pause] Resume signal received. Continuing workflow...");
|
|
50
85
|
}
|
|
51
86
|
// Annotate the CommonJS export names for ESM import in node:
|
|
52
87
|
0 && (module.exports = {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
isDebugPauseSignal
|
|
88
|
+
pause,
|
|
89
|
+
setSessionForPause
|
|
56
90
|
});
|
|
@@ -1,23 +1,16 @@
|
|
|
1
|
-
import { Page } from 'playwright';
|
|
2
|
-
|
|
3
|
-
type DebugPauseContext = {
|
|
4
|
-
page: Page;
|
|
5
|
-
session: string;
|
|
6
|
-
};
|
|
7
|
-
type DebugPauseDetails = {
|
|
8
|
-
sessionName: string;
|
|
9
|
-
pausedAt: string;
|
|
10
|
-
url: string;
|
|
11
|
-
};
|
|
12
|
-
declare class DebugPauseSignal extends Error {
|
|
13
|
-
readonly details: DebugPauseDetails;
|
|
14
|
-
constructor(details: DebugPauseDetails);
|
|
15
|
-
}
|
|
16
|
-
declare function isDebugPauseSignal(error: unknown): error is DebugPauseSignal;
|
|
17
1
|
/**
|
|
18
|
-
*
|
|
19
|
-
|
|
2
|
+
* Called by the CLI runtime to make the session name available to `pause()`.
|
|
3
|
+
*/
|
|
4
|
+
declare function setSessionForPause(session: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Standalone pause function.
|
|
7
|
+
*
|
|
8
|
+
* - In production (`NODE_ENV === "production"`), returns immediately (no-op).
|
|
9
|
+
* - Otherwise, writes a `.paused` signal file and polls for a `.resume` signal,
|
|
10
|
+
* using the same file-based mechanism as the CLI runner.
|
|
11
|
+
*
|
|
12
|
+
* Import directly: `import { pause } from "libretto";`
|
|
20
13
|
*/
|
|
21
|
-
declare function
|
|
14
|
+
declare function pause(): Promise<void>;
|
|
22
15
|
|
|
23
|
-
export {
|
|
16
|
+
export { pause, setSessionForPause };
|