libretto 0.6.10 → 0.6.12
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 +4 -0
- package/README.template.md +4 -0
- package/dist/cli/cli.js +4 -3
- package/dist/cli/commands/ai.js +3 -2
- package/dist/cli/commands/browser.js +17 -17
- package/dist/cli/commands/execution.js +254 -234
- package/dist/cli/commands/experiments.js +100 -0
- package/dist/cli/commands/setup.js +20 -34
- package/dist/cli/commands/shared.js +10 -0
- package/dist/cli/commands/snapshot.js +81 -9
- package/dist/cli/commands/status.js +5 -4
- package/dist/cli/core/ai-model.js +6 -3
- package/dist/cli/core/browser.js +300 -121
- package/dist/cli/core/config.js +4 -2
- package/dist/cli/core/context.js +4 -0
- package/dist/cli/core/daemon/config.js +0 -6
- package/dist/cli/core/daemon/daemon.js +535 -89
- package/dist/cli/core/daemon/ipc.js +170 -129
- package/dist/cli/core/daemon/snapshot.js +72 -6
- package/dist/cli/core/experiments.js +66 -0
- package/dist/cli/core/session.js +5 -4
- package/dist/cli/core/skill-version.js +2 -1
- package/dist/cli/core/snapshot-analyzer.js +4 -3
- package/dist/cli/core/workflow-runner/runner.js +147 -0
- package/dist/cli/core/workflow-runtime.js +60 -0
- package/dist/cli/router.js +4 -1
- package/dist/shared/debug/pause-handler.d.ts +9 -0
- package/dist/shared/debug/pause-handler.js +15 -0
- package/dist/shared/debug/pause.d.ts +1 -2
- package/dist/shared/debug/pause.js +13 -36
- package/dist/shared/ipc/child-process-transport.d.ts +7 -0
- package/dist/shared/ipc/child-process-transport.js +60 -0
- package/dist/shared/ipc/child-process-transport.spec.d.ts +2 -0
- package/dist/shared/ipc/child-process-transport.spec.js +68 -0
- package/dist/shared/ipc/ipc.d.ts +46 -0
- package/dist/shared/ipc/ipc.js +165 -0
- package/dist/shared/ipc/ipc.spec.d.ts +2 -0
- package/dist/shared/ipc/ipc.spec.js +114 -0
- package/dist/shared/ipc/socket-transport.d.ts +9 -0
- package/dist/shared/ipc/socket-transport.js +143 -0
- package/dist/shared/ipc/socket-transport.spec.d.ts +2 -0
- package/dist/shared/ipc/socket-transport.spec.js +117 -0
- package/dist/shared/package-manager.d.ts +7 -0
- package/dist/shared/package-manager.js +60 -0
- package/dist/shared/paths/paths.d.ts +1 -8
- package/dist/shared/paths/paths.js +1 -49
- package/dist/shared/snapshot/capture-snapshot.d.ts +9 -0
- package/dist/shared/snapshot/capture-snapshot.js +463 -0
- package/dist/shared/snapshot/diff-snapshots.d.ts +72 -0
- package/dist/shared/snapshot/diff-snapshots.js +358 -0
- package/dist/shared/snapshot/render-snapshot.d.ts +39 -0
- package/dist/shared/snapshot/render-snapshot.js +651 -0
- package/dist/shared/snapshot/snapshot.spec.d.ts +2 -0
- package/dist/shared/snapshot/snapshot.spec.js +333 -0
- package/dist/shared/snapshot/types.d.ts +40 -0
- package/dist/shared/snapshot/types.js +0 -0
- package/dist/shared/snapshot/wait-for-page-stable.d.ts +17 -0
- package/dist/shared/snapshot/wait-for-page-stable.js +281 -0
- package/dist/shared/state/session-state.d.ts +1 -0
- package/dist/shared/state/session-state.js +1 -0
- package/docs/experiments.md +67 -0
- package/package.json +4 -2
- package/skills/libretto/SKILL.md +3 -1
- package/skills/libretto-readonly/SKILL.md +1 -1
- package/src/cli/AGENTS.md +7 -0
- package/src/cli/cli.ts +4 -3
- package/src/cli/commands/ai.ts +3 -2
- package/src/cli/commands/browser.ts +13 -11
- package/src/cli/commands/execution.ts +303 -271
- package/src/cli/commands/experiments.ts +120 -0
- package/src/cli/commands/setup.ts +18 -36
- package/src/cli/commands/shared.ts +20 -0
- package/src/cli/commands/snapshot.ts +99 -11
- package/src/cli/commands/status.ts +5 -4
- package/src/cli/core/ai-model.ts +6 -3
- package/src/cli/core/browser.ts +369 -147
- package/src/cli/core/config.ts +3 -1
- package/src/cli/core/context.ts +4 -0
- package/src/cli/core/daemon/config.ts +35 -19
- package/src/cli/core/daemon/daemon.ts +686 -106
- package/src/cli/core/daemon/ipc.ts +330 -214
- package/src/cli/core/daemon/snapshot.ts +106 -8
- package/src/cli/core/experiments.ts +85 -0
- package/src/cli/core/session.ts +5 -4
- package/src/cli/core/skill-version.ts +2 -1
- package/src/cli/core/snapshot-analyzer.ts +4 -3
- package/src/cli/core/workflow-runner/runner.ts +237 -0
- package/src/cli/core/workflow-runtime.ts +85 -0
- package/src/cli/router.ts +4 -1
- package/src/shared/debug/pause-handler.ts +20 -0
- package/src/shared/debug/pause.ts +14 -48
- package/src/shared/ipc/AGENTS.md +24 -0
- package/src/shared/ipc/child-process-transport.spec.ts +86 -0
- package/src/shared/ipc/child-process-transport.ts +96 -0
- package/src/shared/ipc/ipc.spec.ts +161 -0
- package/src/shared/ipc/ipc.ts +288 -0
- package/src/shared/ipc/socket-transport.spec.ts +141 -0
- package/src/shared/ipc/socket-transport.ts +189 -0
- package/src/shared/package-manager.ts +76 -0
- package/src/shared/paths/paths.ts +0 -72
- package/src/shared/snapshot/capture-snapshot.ts +615 -0
- package/src/shared/snapshot/diff-snapshots.ts +579 -0
- package/src/shared/snapshot/render-snapshot.ts +962 -0
- package/src/shared/snapshot/snapshot.spec.ts +388 -0
- package/src/shared/snapshot/types.ts +43 -0
- package/src/shared/snapshot/wait-for-page-stable.ts +425 -0
- package/src/shared/state/session-state.ts +1 -0
- package/dist/cli/core/daemon/index.js +0 -16
- package/dist/cli/core/daemon/spawn.js +0 -90
- package/dist/cli/core/pause-signals.js +0 -29
- package/dist/cli/workers/run-integration-runtime.js +0 -235
- package/dist/cli/workers/run-integration-worker-protocol.js +0 -17
- package/dist/cli/workers/run-integration-worker.js +0 -64
- package/src/cli/core/daemon/index.ts +0 -24
- package/src/cli/core/daemon/spawn.ts +0 -171
- package/src/cli/core/pause-signals.ts +0 -35
- package/src/cli/workers/run-integration-runtime.ts +0 -326
- package/src/cli/workers/run-integration-worker-protocol.ts +0 -19
- package/src/cli/workers/run-integration-worker.ts +0 -72
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
import type { BrowserContext } from "playwright";
|
|
2
|
-
import { appendFileSync, existsSync, readFileSync } from "node:fs";
|
|
3
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
-
import { cwd } from "node:process";
|
|
5
|
-
import { isAbsolute, resolve } from "node:path";
|
|
6
|
-
import { pathToFileURL } from "node:url";
|
|
7
|
-
import {
|
|
8
|
-
getDefaultWorkflowFromModuleExports,
|
|
9
|
-
getWorkflowsFromModuleExports,
|
|
10
|
-
instrumentContext,
|
|
11
|
-
launchBrowser,
|
|
12
|
-
type ExportedLibrettoWorkflow,
|
|
13
|
-
type LibrettoWorkflowContext,
|
|
14
|
-
} from "../../index.js";
|
|
15
|
-
import type { LoggerApi } from "../../shared/logger/index.js";
|
|
16
|
-
import { parseSessionStateContent } from "../../shared/state/index.js";
|
|
17
|
-
import {
|
|
18
|
-
getProfilePath,
|
|
19
|
-
normalizeDomain,
|
|
20
|
-
normalizeUrl,
|
|
21
|
-
} from "../core/browser.js";
|
|
22
|
-
import {
|
|
23
|
-
getSessionActionsLogPath,
|
|
24
|
-
getSessionDir,
|
|
25
|
-
getSessionNetworkLogPath,
|
|
26
|
-
getSessionStatePath,
|
|
27
|
-
} from "../core/context.js";
|
|
28
|
-
import {
|
|
29
|
-
getPauseSignalPaths,
|
|
30
|
-
removeSignalIfExists,
|
|
31
|
-
} from "../core/pause-signals.js";
|
|
32
|
-
import { installSessionTelemetry } from "../core/session-telemetry.js";
|
|
33
|
-
import type { RunIntegrationWorkerRequest } from "./run-integration-worker-protocol.js";
|
|
34
|
-
|
|
35
|
-
type LoadedLibrettoWorkflow = ExportedLibrettoWorkflow & {
|
|
36
|
-
run: (ctx: LibrettoWorkflowContext, input: unknown) => Promise<unknown>;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
type RunIntegrationOutcome =
|
|
40
|
-
| { status: "completed" }
|
|
41
|
-
| { status: "failed-held" };
|
|
42
|
-
|
|
43
|
-
const FAILURE_HOLD_POLL_INTERVAL_MS = 250;
|
|
44
|
-
const TSCONFIG_HINT =
|
|
45
|
-
"TypeScript compilation failed. Pass --tsconfig <path> to run against a specific tsconfig.";
|
|
46
|
-
|
|
47
|
-
function isTsxCompileError(error: unknown): error is Error {
|
|
48
|
-
return (
|
|
49
|
-
error instanceof Error &&
|
|
50
|
-
(error.name === "TransformError" ||
|
|
51
|
-
error.message.startsWith("Cannot resolve tsconfig at path:"))
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function mirrorStdoutToFile(filePath: string): () => void {
|
|
56
|
-
const stdout = process.stdout as NodeJS.WriteStream & {
|
|
57
|
-
write: (...args: any[]) => boolean;
|
|
58
|
-
};
|
|
59
|
-
const originalWrite = stdout.write.bind(stdout);
|
|
60
|
-
|
|
61
|
-
stdout.write = ((chunk: unknown, ...args: unknown[]) => {
|
|
62
|
-
try {
|
|
63
|
-
const buffer = Buffer.isBuffer(chunk)
|
|
64
|
-
? chunk
|
|
65
|
-
: Buffer.from(String(chunk), "utf8");
|
|
66
|
-
appendFileSync(filePath, buffer);
|
|
67
|
-
} catch {
|
|
68
|
-
// Ignore log mirroring failures; primary stdout should still flow.
|
|
69
|
-
}
|
|
70
|
-
return originalWrite(chunk, ...args);
|
|
71
|
-
}) as typeof stdout.write;
|
|
72
|
-
|
|
73
|
-
return () => {
|
|
74
|
-
stdout.write = originalWrite as typeof stdout.write;
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function readSessionStatePid(session: string): number | null {
|
|
79
|
-
const statePath = getSessionStatePath(session);
|
|
80
|
-
if (!existsSync(statePath)) return null;
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
return (
|
|
84
|
-
parseSessionStateContent(readFileSync(statePath, "utf8"), statePath)
|
|
85
|
-
.pid ?? null
|
|
86
|
-
);
|
|
87
|
-
} catch {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async function waitForFailureSessionRelease(args: {
|
|
93
|
-
session: string;
|
|
94
|
-
expectedPid: number;
|
|
95
|
-
logger: LoggerApi;
|
|
96
|
-
}): Promise<void> {
|
|
97
|
-
const { session, expectedPid, logger } = args;
|
|
98
|
-
logger.info("run-failure-session-hold", { session, expectedPid });
|
|
99
|
-
|
|
100
|
-
while (true) {
|
|
101
|
-
const currentPid = readSessionStatePid(session);
|
|
102
|
-
if (currentPid !== expectedPid) {
|
|
103
|
-
logger.info("run-failure-session-released", {
|
|
104
|
-
session,
|
|
105
|
-
expectedPid,
|
|
106
|
-
currentPid,
|
|
107
|
-
});
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
await new Promise((resolveWait) =>
|
|
111
|
-
setTimeout(resolveWait, FAILURE_HOLD_POLL_INTERVAL_MS),
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function getMissingLocalAuthProfileError(args: {
|
|
117
|
-
normalizedDomain: string;
|
|
118
|
-
profilePath: string;
|
|
119
|
-
session: string;
|
|
120
|
-
}): string {
|
|
121
|
-
return [
|
|
122
|
-
`Local auth profile not found for domain "${args.normalizedDomain}".`,
|
|
123
|
-
`Expected profile file: ${args.profilePath}`,
|
|
124
|
-
"To create it:",
|
|
125
|
-
` 1. libretto open https://${args.normalizedDomain} --headed --session ${args.session}`,
|
|
126
|
-
" 2. Log in manually in the browser window.",
|
|
127
|
-
` 3. libretto save ${args.normalizedDomain} --session ${args.session}`,
|
|
128
|
-
].join("\n");
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function getAbsoluteIntegrationPath(integrationPath: string): string {
|
|
132
|
-
const absolutePath = isAbsolute(integrationPath)
|
|
133
|
-
? integrationPath
|
|
134
|
-
: resolve(cwd(), integrationPath);
|
|
135
|
-
if (!existsSync(absolutePath)) {
|
|
136
|
-
throw new Error(`Integration file does not exist: ${absolutePath}`);
|
|
137
|
-
}
|
|
138
|
-
return absolutePath;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async function loadDefaultWorkflow(
|
|
142
|
-
absolutePath: string,
|
|
143
|
-
): Promise<LoadedLibrettoWorkflow> {
|
|
144
|
-
let loadedModule: Record<string, unknown>;
|
|
145
|
-
try {
|
|
146
|
-
loadedModule = (await import(pathToFileURL(absolutePath).href)) as Record<
|
|
147
|
-
string,
|
|
148
|
-
unknown
|
|
149
|
-
>;
|
|
150
|
-
} catch (error) {
|
|
151
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
152
|
-
const compileHint = isTsxCompileError(error) ? `\n${TSCONFIG_HINT}` : "";
|
|
153
|
-
throw new Error(
|
|
154
|
-
`Failed to import integration module at ${absolutePath}: ${message}${compileHint}`,
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const defaultWorkflow = getDefaultWorkflowFromModuleExports(loadedModule);
|
|
159
|
-
if (defaultWorkflow) {
|
|
160
|
-
return defaultWorkflow as LoadedLibrettoWorkflow;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const availableWorkflowNames = getWorkflowsFromModuleExports(loadedModule).map(
|
|
164
|
-
(candidate) => candidate.name,
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
if (availableWorkflowNames.length === 0) {
|
|
168
|
-
throw new Error(
|
|
169
|
-
`No default-exported workflow found in ${absolutePath}. Export the workflow with \`export default workflow("name", handler)\`.`,
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
throw new Error(
|
|
174
|
-
`No default-exported workflow found in ${absolutePath}. libretto run only uses the file's default export. Available named workflows: ${availableWorkflowNames.join(", ")}`,
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export async function installHeadedWorkflowVisualization(args: {
|
|
179
|
-
context: BrowserContext;
|
|
180
|
-
logger: LoggerApi;
|
|
181
|
-
instrument?: typeof instrumentContext;
|
|
182
|
-
}): Promise<void> {
|
|
183
|
-
await (args.instrument ?? instrumentContext)(args.context, {
|
|
184
|
-
visualize: true,
|
|
185
|
-
logger: args.logger,
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async function runIntegrationInternal(
|
|
190
|
-
args: RunIntegrationWorkerRequest,
|
|
191
|
-
options: {
|
|
192
|
-
logger: LoggerApi;
|
|
193
|
-
},
|
|
194
|
-
): Promise<RunIntegrationOutcome> {
|
|
195
|
-
const { logger } = options;
|
|
196
|
-
const absolutePath = getAbsoluteIntegrationPath(args.integrationPath);
|
|
197
|
-
|
|
198
|
-
const workflow = await loadDefaultWorkflow(absolutePath);
|
|
199
|
-
const signalPaths = getPauseSignalPaths(args.session);
|
|
200
|
-
await removeSignalIfExists(signalPaths.pausedSignalPath);
|
|
201
|
-
await removeSignalIfExists(signalPaths.resumeSignalPath);
|
|
202
|
-
await removeSignalIfExists(signalPaths.completedSignalPath);
|
|
203
|
-
await removeSignalIfExists(signalPaths.failedSignalPath);
|
|
204
|
-
const restoreStdout = mirrorStdoutToFile(signalPaths.outputSignalPath);
|
|
205
|
-
|
|
206
|
-
console.log(
|
|
207
|
-
`Running workflow "${workflow.name}" from ${absolutePath} (${args.headless ? "headless" : "headed"})...`,
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
const integrationLogger = logger.withScope("integration-run", {
|
|
211
|
-
integrationPath: absolutePath,
|
|
212
|
-
workflowName: workflow.name,
|
|
213
|
-
session: args.session,
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// Resolve auth profile from CLI flag (--auth-profile <domain>)
|
|
217
|
-
const authProfileDomain = args.authProfileDomain;
|
|
218
|
-
const normalizedAuthProfileDomain = authProfileDomain
|
|
219
|
-
? normalizeDomain(normalizeUrl(authProfileDomain))
|
|
220
|
-
: undefined;
|
|
221
|
-
const storageStatePath = normalizedAuthProfileDomain
|
|
222
|
-
? getProfilePath(normalizedAuthProfileDomain)
|
|
223
|
-
: undefined;
|
|
224
|
-
if (
|
|
225
|
-
normalizedAuthProfileDomain &&
|
|
226
|
-
storageStatePath &&
|
|
227
|
-
!existsSync(storageStatePath)
|
|
228
|
-
) {
|
|
229
|
-
throw new Error(
|
|
230
|
-
getMissingLocalAuthProfileError({
|
|
231
|
-
normalizedDomain: normalizedAuthProfileDomain,
|
|
232
|
-
profilePath: storageStatePath,
|
|
233
|
-
session: args.session,
|
|
234
|
-
}),
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
const browserSession = await launchBrowser({
|
|
238
|
-
sessionName: args.session,
|
|
239
|
-
headless: args.headless,
|
|
240
|
-
storageStatePath,
|
|
241
|
-
viewport: args.viewport,
|
|
242
|
-
accessMode: args.accessMode,
|
|
243
|
-
cdpEndpoint: args.cdpEndpoint,
|
|
244
|
-
provider: args.provider,
|
|
245
|
-
});
|
|
246
|
-
if (!args.headless && args.visualize !== false) {
|
|
247
|
-
await installHeadedWorkflowVisualization({
|
|
248
|
-
context: browserSession.context,
|
|
249
|
-
logger: integrationLogger,
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
const actionsLogPath = getSessionActionsLogPath(args.session);
|
|
253
|
-
const networkLogPath = getSessionNetworkLogPath(args.session);
|
|
254
|
-
await installSessionTelemetry({
|
|
255
|
-
context: browserSession.context,
|
|
256
|
-
initialPage: browserSession.page,
|
|
257
|
-
includeUserDomActions: true,
|
|
258
|
-
logAction: (entry) => {
|
|
259
|
-
appendFileSync(actionsLogPath, JSON.stringify(entry) + "\n");
|
|
260
|
-
},
|
|
261
|
-
logNetwork: (entry) => {
|
|
262
|
-
appendFileSync(networkLogPath, JSON.stringify(entry) + "\n");
|
|
263
|
-
},
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
// tsx/esbuild injects __name() wrappers when keepNames is true. Playwright
|
|
267
|
-
// serializes callbacks via Function#toString() into the browser context which
|
|
268
|
-
// lacks __name, causing ReferenceError. Inject a no-op polyfill into every page.
|
|
269
|
-
await browserSession.context.addInitScript(() => {
|
|
270
|
-
(globalThis as Record<string, unknown>).__name = (
|
|
271
|
-
target: unknown,
|
|
272
|
-
value: string,
|
|
273
|
-
) => Object.defineProperty(target as object, "name", { value, configurable: true });
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
const workflowContext: LibrettoWorkflowContext = {
|
|
277
|
-
session: args.session,
|
|
278
|
-
page: browserSession.page,
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
try {
|
|
282
|
-
try {
|
|
283
|
-
await workflow.run(workflowContext, args.params ?? {});
|
|
284
|
-
} catch (error) {
|
|
285
|
-
const errorMessage =
|
|
286
|
-
error instanceof Error ? error.message : String(error);
|
|
287
|
-
await writeFile(
|
|
288
|
-
signalPaths.failedSignalPath,
|
|
289
|
-
JSON.stringify(
|
|
290
|
-
{
|
|
291
|
-
failedAt: new Date().toISOString(),
|
|
292
|
-
message: errorMessage,
|
|
293
|
-
phase: "workflow",
|
|
294
|
-
},
|
|
295
|
-
null,
|
|
296
|
-
2,
|
|
297
|
-
),
|
|
298
|
-
"utf8",
|
|
299
|
-
);
|
|
300
|
-
await waitForFailureSessionRelease({
|
|
301
|
-
session: args.session,
|
|
302
|
-
expectedPid: process.pid,
|
|
303
|
-
logger,
|
|
304
|
-
});
|
|
305
|
-
return { status: "failed-held" };
|
|
306
|
-
}
|
|
307
|
-
await writeFile(
|
|
308
|
-
signalPaths.completedSignalPath,
|
|
309
|
-
JSON.stringify({ completedAt: new Date().toISOString() }, null, 2),
|
|
310
|
-
"utf8",
|
|
311
|
-
);
|
|
312
|
-
return { status: "completed" };
|
|
313
|
-
} finally {
|
|
314
|
-
restoreStdout();
|
|
315
|
-
await browserSession.close();
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
export async function runIntegrationFromFileInWorker(
|
|
320
|
-
args: RunIntegrationWorkerRequest,
|
|
321
|
-
logger: LoggerApi,
|
|
322
|
-
): Promise<RunIntegrationOutcome> {
|
|
323
|
-
return await runIntegrationInternal(args, {
|
|
324
|
-
logger,
|
|
325
|
-
});
|
|
326
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { SessionAccessModeSchema } from "../../shared/state/index.js";
|
|
3
|
-
|
|
4
|
-
export const RunIntegrationWorkerRequestSchema = z.object({
|
|
5
|
-
integrationPath: z.string().min(1),
|
|
6
|
-
session: z.string().min(1),
|
|
7
|
-
params: z.unknown(),
|
|
8
|
-
headless: z.boolean(),
|
|
9
|
-
visualize: z.boolean().default(true),
|
|
10
|
-
authProfileDomain: z.string().optional(),
|
|
11
|
-
viewport: z.object({ width: z.number(), height: z.number() }).optional(),
|
|
12
|
-
accessMode: SessionAccessModeSchema.default("write-access"),
|
|
13
|
-
cdpEndpoint: z.string().optional(),
|
|
14
|
-
provider: z.object({ name: z.string(), sessionId: z.string() }).optional(),
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
export type RunIntegrationWorkerRequest = z.infer<
|
|
18
|
-
typeof RunIntegrationWorkerRequestSchema
|
|
19
|
-
>;
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { writeFile } from "node:fs/promises";
|
|
2
|
-
import { ZodError } from "zod";
|
|
3
|
-
import {
|
|
4
|
-
RunIntegrationWorkerRequestSchema,
|
|
5
|
-
type RunIntegrationWorkerRequest,
|
|
6
|
-
} from "./run-integration-worker-protocol.js";
|
|
7
|
-
import { runIntegrationFromFileInWorker } from "./run-integration-runtime.js";
|
|
8
|
-
import { ensureLibrettoSetup, withSessionLogger } from "../core/context.js";
|
|
9
|
-
import { getPauseSignalPaths } from "../core/pause-signals.js";
|
|
10
|
-
|
|
11
|
-
function parseWorkerRequest(argv: string[]): RunIntegrationWorkerRequest {
|
|
12
|
-
const rawPayload = argv[2];
|
|
13
|
-
if (!rawPayload) {
|
|
14
|
-
throw new Error("Missing worker payload argument.");
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
let parsed: unknown;
|
|
18
|
-
try {
|
|
19
|
-
parsed = JSON.parse(rawPayload);
|
|
20
|
-
} catch (error) {
|
|
21
|
-
throw new Error(
|
|
22
|
-
`Invalid worker payload JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
return RunIntegrationWorkerRequestSchema.parse(parsed);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
if (error instanceof ZodError) {
|
|
30
|
-
const details = error.issues
|
|
31
|
-
.map((issue) => `${issue.path.join(".") || "root"}: ${issue.message}`)
|
|
32
|
-
.join("; ");
|
|
33
|
-
throw new Error(`Worker payload is invalid: ${details}`);
|
|
34
|
-
}
|
|
35
|
-
throw error;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function main(): Promise<void> {
|
|
40
|
-
let request: RunIntegrationWorkerRequest | null = null;
|
|
41
|
-
let exitCode = 0;
|
|
42
|
-
try {
|
|
43
|
-
request = parseWorkerRequest(process.argv);
|
|
44
|
-
const workerRequest = request;
|
|
45
|
-
ensureLibrettoSetup();
|
|
46
|
-
await withSessionLogger(workerRequest.session, async (logger) => {
|
|
47
|
-
await runIntegrationFromFileInWorker(workerRequest, logger);
|
|
48
|
-
});
|
|
49
|
-
} catch (error) {
|
|
50
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
51
|
-
if (request) {
|
|
52
|
-
const { failedSignalPath } = getPauseSignalPaths(request.session);
|
|
53
|
-
await writeFile(
|
|
54
|
-
failedSignalPath,
|
|
55
|
-
JSON.stringify(
|
|
56
|
-
{
|
|
57
|
-
failedAt: new Date().toISOString(),
|
|
58
|
-
message,
|
|
59
|
-
phase: "setup",
|
|
60
|
-
},
|
|
61
|
-
null,
|
|
62
|
-
2,
|
|
63
|
-
),
|
|
64
|
-
"utf8",
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
exitCode = 1;
|
|
68
|
-
}
|
|
69
|
-
process.exit(exitCode);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
void main();
|