libretto 0.2.0 → 0.2.1

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.
Files changed (65) hide show
  1. package/README.md +128 -126
  2. package/dist/cli/cli.js +2 -0
  3. package/dist/cli/commands/browser.js +4 -1
  4. package/dist/cli/commands/execution.js +21 -6
  5. package/dist/cli/commands/logs.js +36 -8
  6. package/dist/cli/commands/snapshot.js +14 -7
  7. package/dist/cli/core/browser.js +89 -253
  8. package/dist/cli/core/session-telemetry.js +491 -0
  9. package/dist/cli/core/telemetry.js +18 -6
  10. package/dist/cli/workers/run-integration-runtime.js +19 -1
  11. package/dist/index.cjs +2 -6
  12. package/dist/index.d.cts +2 -5
  13. package/dist/index.d.ts +2 -5
  14. package/dist/index.js +2 -5
  15. package/dist/runtime/download/download.d.cts +2 -2
  16. package/dist/runtime/download/download.d.ts +2 -2
  17. package/dist/runtime/extract/extract.cjs +2 -1
  18. package/dist/runtime/extract/extract.d.cts +5 -5
  19. package/dist/runtime/extract/extract.d.ts +5 -5
  20. package/dist/runtime/extract/extract.js +2 -1
  21. package/dist/runtime/network/network.d.cts +6 -6
  22. package/dist/runtime/network/network.d.ts +6 -6
  23. package/dist/runtime/recovery/agent.cjs +12 -7
  24. package/dist/runtime/recovery/agent.d.cts +2 -2
  25. package/dist/runtime/recovery/agent.d.ts +2 -2
  26. package/dist/runtime/recovery/agent.js +12 -7
  27. package/dist/runtime/recovery/errors.cjs +8 -6
  28. package/dist/runtime/recovery/errors.d.cts +2 -2
  29. package/dist/runtime/recovery/errors.d.ts +2 -2
  30. package/dist/runtime/recovery/errors.js +8 -6
  31. package/dist/runtime/recovery/recovery.cjs +5 -3
  32. package/dist/runtime/recovery/recovery.d.cts +2 -2
  33. package/dist/runtime/recovery/recovery.d.ts +2 -2
  34. package/dist/runtime/recovery/recovery.js +5 -3
  35. package/dist/shared/instrumentation/instrument.d.cts +2 -2
  36. package/dist/shared/instrumentation/instrument.d.ts +2 -2
  37. package/dist/shared/llm/types.d.cts +5 -5
  38. package/dist/shared/llm/types.d.ts +5 -5
  39. package/dist/shared/logger/index.cjs +2 -0
  40. package/dist/shared/logger/index.d.cts +1 -1
  41. package/dist/shared/logger/index.d.ts +1 -1
  42. package/dist/shared/logger/index.js +2 -1
  43. package/dist/shared/logger/logger.cjs +15 -2
  44. package/dist/shared/logger/logger.d.cts +13 -1
  45. package/dist/shared/logger/logger.d.ts +13 -1
  46. package/dist/shared/logger/logger.js +13 -1
  47. package/dist/shared/state/session-state.d.cts +2 -2
  48. package/dist/shared/state/session-state.d.ts +2 -2
  49. package/package.json +12 -10
  50. package/dist/runtime/step/index.cjs +0 -31
  51. package/dist/runtime/step/index.d.cts +0 -7
  52. package/dist/runtime/step/index.d.ts +0 -7
  53. package/dist/runtime/step/index.js +0 -6
  54. package/dist/runtime/step/runner.cjs +0 -208
  55. package/dist/runtime/step/runner.d.cts +0 -16
  56. package/dist/runtime/step/runner.d.ts +0 -16
  57. package/dist/runtime/step/runner.js +0 -187
  58. package/dist/runtime/step/step.cjs +0 -67
  59. package/dist/runtime/step/step.d.cts +0 -23
  60. package/dist/runtime/step/step.d.ts +0 -23
  61. package/dist/runtime/step/step.js +0 -43
  62. package/dist/runtime/step/types.cjs +0 -16
  63. package/dist/runtime/step/types.d.cts +0 -72
  64. package/dist/runtime/step/types.d.ts +0 -72
  65. package/dist/runtime/step/types.js +0 -0
@@ -1,4 +1,4 @@
1
- import { ZodType, infer } from 'zod';
1
+ import z from 'zod';
2
2
 
3
3
  type MessageContentPart = {
4
4
  type: "text";
@@ -19,16 +19,16 @@ type Message = {
19
19
  * recovery agents, and error detection.
20
20
  */
21
21
  interface LLMClient {
22
- generateObject<T extends ZodType>(opts: {
22
+ generateObject<T extends z.ZodType>(opts: {
23
23
  prompt: string;
24
24
  schema: T;
25
25
  temperature?: number;
26
- }): Promise<infer<T>>;
27
- generateObjectFromMessages<T extends ZodType>(opts: {
26
+ }): Promise<z.infer<T>>;
27
+ generateObjectFromMessages<T extends z.ZodType>(opts: {
28
28
  messages: Message[];
29
29
  schema: T;
30
30
  temperature?: number;
31
- }): Promise<infer<T>>;
31
+ }): Promise<z.infer<T>>;
32
32
  }
33
33
 
34
34
  export type { LLMClient, Message, MessageContentPart };
@@ -1,4 +1,4 @@
1
- import { ZodType, infer } from 'zod';
1
+ import z from 'zod';
2
2
 
3
3
  type MessageContentPart = {
4
4
  type: "text";
@@ -19,16 +19,16 @@ type Message = {
19
19
  * recovery agents, and error detection.
20
20
  */
21
21
  interface LLMClient {
22
- generateObject<T extends ZodType>(opts: {
22
+ generateObject<T extends z.ZodType>(opts: {
23
23
  prompt: string;
24
24
  schema: T;
25
25
  temperature?: number;
26
- }): Promise<infer<T>>;
27
- generateObjectFromMessages<T extends ZodType>(opts: {
26
+ }): Promise<z.infer<T>>;
27
+ generateObjectFromMessages<T extends z.ZodType>(opts: {
28
28
  messages: Message[];
29
29
  schema: T;
30
30
  temperature?: number;
31
- }): Promise<infer<T>>;
31
+ }): Promise<z.infer<T>>;
32
32
  }
33
33
 
34
34
  export type { LLMClient, Message, MessageContentPart };
@@ -20,6 +20,7 @@ var logger_exports = {};
20
20
  __export(logger_exports, {
21
21
  Logger: () => import_logger.Logger,
22
22
  createFileLogSink: () => import_sinks.createFileLogSink,
23
+ defaultLogger: () => import_logger.defaultLogger,
23
24
  jsonlConsoleSink: () => import_sinks.jsonlConsoleSink,
24
25
  prettyConsoleSink: () => import_sinks.prettyConsoleSink
25
26
  });
@@ -30,6 +31,7 @@ var import_sinks = require("./sinks.js");
30
31
  0 && (module.exports = {
31
32
  Logger,
32
33
  createFileLogSink,
34
+ defaultLogger,
33
35
  jsonlConsoleSink,
34
36
  prettyConsoleSink
35
37
  });
@@ -1,2 +1,2 @@
1
- export { LogOptions, Logger, LoggerApi, LoggerSink } from './logger.cjs';
1
+ export { LogOptions, Logger, LoggerApi, LoggerSink, MinimalLogger, defaultLogger } from './logger.cjs';
2
2
  export { createFileLogSink, jsonlConsoleSink, prettyConsoleSink } from './sinks.cjs';
@@ -1,2 +1,2 @@
1
- export { LogOptions, Logger, LoggerApi, LoggerSink } from './logger.js';
1
+ export { LogOptions, Logger, LoggerApi, LoggerSink, MinimalLogger, defaultLogger } from './logger.js';
2
2
  export { createFileLogSink, jsonlConsoleSink, prettyConsoleSink } from './sinks.js';
@@ -1,4 +1,4 @@
1
- import { Logger } from "./logger.js";
1
+ import { Logger, defaultLogger } from "./logger.js";
2
2
  import {
3
3
  createFileLogSink,
4
4
  prettyConsoleSink,
@@ -7,6 +7,7 @@ import {
7
7
  export {
8
8
  Logger,
9
9
  createFileLogSink,
10
+ defaultLogger,
10
11
  jsonlConsoleSink,
11
12
  prettyConsoleSink
12
13
  };
@@ -18,12 +18,24 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var logger_exports = {};
20
20
  __export(logger_exports, {
21
- Logger: () => Logger
21
+ Logger: () => Logger,
22
+ defaultLogger: () => defaultLogger
22
23
  });
23
24
  module.exports = __toCommonJS(logger_exports);
24
25
  function generateId() {
25
26
  return Math.random().toString(36).substring(2, 15);
26
27
  }
28
+ const defaultLogger = {
29
+ info(event, data) {
30
+ console.log(`[INFO] ${event}`, data ?? "");
31
+ },
32
+ warn(event, data) {
33
+ console.warn(`[WARN] ${event}`, data ?? "");
34
+ },
35
+ error(event, data) {
36
+ console.error(`[ERROR] ${event}`, data ?? "");
37
+ }
38
+ };
27
39
  const sinkLifecycleState = /* @__PURE__ */ new WeakMap();
28
40
  function getSinkLifecycleState(sink) {
29
41
  const existingState = sinkLifecycleState.get(sink);
@@ -196,5 +208,6 @@ class Logger {
196
208
  }
197
209
  // Annotate the CommonJS export names for ESM import in node:
198
210
  0 && (module.exports = {
199
- Logger
211
+ Logger,
212
+ defaultLogger
200
213
  });
@@ -1,6 +1,18 @@
1
1
  type LogOptions = {
2
2
  timestamp?: Date;
3
3
  };
4
+ /**
5
+ * Minimal logger interface accepted by public-facing runtime functions.
6
+ * Any logger with info/warn/error methods satisfies this — no need to
7
+ * implement withScope, withContext, flush, etc.
8
+ */
9
+ type MinimalLogger = {
10
+ info: (event: string, data?: Record<string, any>) => void;
11
+ warn: (event: string, data?: any) => void;
12
+ error: (event: string, data?: any) => any;
13
+ };
14
+ /** Default console logger used when callers omit the logger option. */
15
+ declare const defaultLogger: MinimalLogger;
4
16
  type LoggerApi = {
5
17
  log: (event: string, data?: Record<string, any>, options?: LogOptions) => void;
6
18
  /**
@@ -67,4 +79,4 @@ declare class Logger implements LoggerApi {
67
79
  close(): Promise<void>;
68
80
  }
69
81
 
70
- export { type LogOptions, Logger, type LoggerApi, type LoggerSink };
82
+ export { type LogOptions, Logger, type LoggerApi, type LoggerSink, type MinimalLogger, defaultLogger };
@@ -1,6 +1,18 @@
1
1
  type LogOptions = {
2
2
  timestamp?: Date;
3
3
  };
4
+ /**
5
+ * Minimal logger interface accepted by public-facing runtime functions.
6
+ * Any logger with info/warn/error methods satisfies this — no need to
7
+ * implement withScope, withContext, flush, etc.
8
+ */
9
+ type MinimalLogger = {
10
+ info: (event: string, data?: Record<string, any>) => void;
11
+ warn: (event: string, data?: any) => void;
12
+ error: (event: string, data?: any) => any;
13
+ };
14
+ /** Default console logger used when callers omit the logger option. */
15
+ declare const defaultLogger: MinimalLogger;
4
16
  type LoggerApi = {
5
17
  log: (event: string, data?: Record<string, any>, options?: LogOptions) => void;
6
18
  /**
@@ -67,4 +79,4 @@ declare class Logger implements LoggerApi {
67
79
  close(): Promise<void>;
68
80
  }
69
81
 
70
- export { type LogOptions, Logger, type LoggerApi, type LoggerSink };
82
+ export { type LogOptions, Logger, type LoggerApi, type LoggerSink, type MinimalLogger, defaultLogger };
@@ -1,6 +1,17 @@
1
1
  function generateId() {
2
2
  return Math.random().toString(36).substring(2, 15);
3
3
  }
4
+ const defaultLogger = {
5
+ info(event, data) {
6
+ console.log(`[INFO] ${event}`, data ?? "");
7
+ },
8
+ warn(event, data) {
9
+ console.warn(`[WARN] ${event}`, data ?? "");
10
+ },
11
+ error(event, data) {
12
+ console.error(`[ERROR] ${event}`, data ?? "");
13
+ }
14
+ };
4
15
  const sinkLifecycleState = /* @__PURE__ */ new WeakMap();
5
16
  function getSinkLifecycleState(sink) {
6
17
  const existingState = sinkLifecycleState.get(sink);
@@ -172,5 +183,6 @@ class Logger {
172
183
  }
173
184
  }
174
185
  export {
175
- Logger
186
+ Logger,
187
+ defaultLogger
176
188
  };
@@ -15,14 +15,14 @@ declare const SessionStateFileSchema: z.ZodObject<{
15
15
  pid: number;
16
16
  session: string;
17
17
  startedAt: string;
18
- status?: "completed" | "failed" | "paused" | "active" | "exited" | undefined;
18
+ status?: "active" | "paused" | "completed" | "failed" | "exited" | undefined;
19
19
  }, {
20
20
  version: 1;
21
21
  port: number;
22
22
  pid: number;
23
23
  session: string;
24
24
  startedAt: string;
25
- status?: "completed" | "failed" | "paused" | "active" | "exited" | undefined;
25
+ status?: "active" | "paused" | "completed" | "failed" | "exited" | undefined;
26
26
  }>;
27
27
  type SessionStatus = z.infer<typeof SessionStatusSchema>;
28
28
  type SessionStateFile = z.infer<typeof SessionStateFileSchema>;
@@ -15,14 +15,14 @@ declare const SessionStateFileSchema: z.ZodObject<{
15
15
  pid: number;
16
16
  session: string;
17
17
  startedAt: string;
18
- status?: "completed" | "failed" | "paused" | "active" | "exited" | undefined;
18
+ status?: "active" | "paused" | "completed" | "failed" | "exited" | undefined;
19
19
  }, {
20
20
  version: 1;
21
21
  port: number;
22
22
  pid: number;
23
23
  session: string;
24
24
  startedAt: string;
25
- status?: "completed" | "failed" | "paused" | "active" | "exited" | undefined;
25
+ status?: "active" | "paused" | "completed" | "failed" | "exited" | undefined;
26
26
  }>;
27
27
  type SessionStatus = z.infer<typeof SessionStatusSchema>;
28
28
  type SessionStateFile = z.infer<typeof SessionStateFileSchema>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libretto",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "AI-powered browser automation library and CLI built on Playwright",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -25,11 +25,6 @@
25
25
  "import": "./dist/index.js",
26
26
  "require": "./dist/index.cjs"
27
27
  },
28
- "./step": {
29
- "types": "./dist/runtime/step/index.d.ts",
30
- "import": "./dist/runtime/step/index.js",
31
- "require": "./dist/runtime/step/index.cjs"
32
- },
33
28
  "./logger": {
34
29
  "types": "./dist/shared/logger/index.d.ts",
35
30
  "import": "./dist/shared/logger/index.js",
@@ -98,7 +93,7 @@
98
93
  "build:cli": "tsup --config tsup.cli.config.ts",
99
94
  "type-check": "tsc --noEmit",
100
95
  "dev": "tsx src/cli/index.ts",
101
- "test": "vitest run",
96
+ "test": "pnpm run build && vitest run",
102
97
  "test:watch": "vitest"
103
98
  },
104
99
  "peerDependencies": {
@@ -108,9 +103,15 @@
108
103
  "zod": ">=3.0.0"
109
104
  },
110
105
  "peerDependenciesMeta": {
111
- "@ai-sdk/anthropic": { "optional": true },
112
- "@ai-sdk/google-vertex": { "optional": true },
113
- "@ai-sdk/openai": { "optional": true }
106
+ "@ai-sdk/anthropic": {
107
+ "optional": true
108
+ },
109
+ "@ai-sdk/google-vertex": {
110
+ "optional": true
111
+ },
112
+ "@ai-sdk/openai": {
113
+ "optional": true
114
+ }
114
115
  },
115
116
  "devDependencies": {
116
117
  "@ai-sdk/anthropic": "^3.0.53",
@@ -118,6 +119,7 @@
118
119
  "@ai-sdk/openai": "^3.0.39",
119
120
  "@types/node": "^25.3.3",
120
121
  "@types/yargs": "^17.0.33",
122
+ "openai": "^6.27.0",
121
123
  "tsup": "^8.0.0",
122
124
  "tsx": "^4.19.2",
123
125
  "typescript": "^5.7.0",
@@ -1,31 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var step_exports = {};
20
- __export(step_exports, {
21
- createRunner: () => import_runner.createRunner,
22
- step: () => import_step.step
23
- });
24
- module.exports = __toCommonJS(step_exports);
25
- var import_step = require("./step.js");
26
- var import_runner = require("./runner.js");
27
- // Annotate the CommonJS export names for ESM import in node:
28
- 0 && (module.exports = {
29
- createRunner,
30
- step
31
- });
@@ -1,7 +0,0 @@
1
- export { step } from './step.cjs';
2
- export { Runner, createRunner } from './runner.cjs';
3
- export { DebugBundle, RecoveryHandler, RunnerConfig, Step, StepContext, StepHandler, StepHistoryEntry, StepOptions } from './types.cjs';
4
- import 'playwright';
5
- import '../../shared/logger/logger.cjs';
6
- import '../../shared/llm/types.cjs';
7
- import 'zod';
@@ -1,7 +0,0 @@
1
- export { step } from './step.js';
2
- export { Runner, createRunner } from './runner.js';
3
- export { DebugBundle, RecoveryHandler, RunnerConfig, Step, StepContext, StepHandler, StepHistoryEntry, StepOptions } from './types.js';
4
- import 'playwright';
5
- import '../../shared/logger/logger.js';
6
- import '../../shared/llm/types.js';
7
- import 'zod';
@@ -1,6 +0,0 @@
1
- import { step } from "./step.js";
2
- import { createRunner } from "./runner.js";
3
- export {
4
- createRunner,
5
- step
6
- };
@@ -1,208 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var runner_exports = {};
20
- __export(runner_exports, {
21
- createRunner: () => createRunner
22
- });
23
- module.exports = __toCommonJS(runner_exports);
24
- var import_node_fs = require("node:fs");
25
- var import_node_path = require("node:path");
26
- var import_logger = require("../../shared/logger/logger.js");
27
- var import_sinks = require("../../shared/logger/sinks.js");
28
- var import_config = require("../../shared/config/config.js");
29
- var import_pause = require("../../shared/debug/pause.js");
30
- var import_recovery = require("../recovery/recovery.js");
31
- var import_paths = require("../../shared/paths/paths.js");
32
- function createRunner(config = {}) {
33
- const {
34
- llmClient,
35
- dryRun: dryRunOption,
36
- debug: debugOption,
37
- sessionName = "libretto",
38
- logDir: configuredLogDir
39
- } = config;
40
- const dryRun = dryRunOption ?? (0, import_config.isDryRun)();
41
- const debug = debugOption ?? false;
42
- const logDir = configuredLogDir ?? (0, import_paths.ensureLibrettoRunnerLogDir)(sessionName);
43
- return {
44
- run: async (page, steps) => {
45
- (0, import_node_fs.mkdirSync)(logDir, { recursive: true });
46
- const logPath = (0, import_paths.getRunnerLogPathForDir)(logDir);
47
- const logger = new import_logger.Logger().withSink((0, import_sinks.createFileLogSink)({ filePath: logPath })).withSink(import_sinks.prettyConsoleSink);
48
- const stepHistory = [];
49
- logger.info("runner:start", {
50
- totalSteps: steps.length,
51
- dryRun,
52
- debug,
53
- logDir
54
- });
55
- for (const step of steps) {
56
- const stepLogger = logger.withScope(`step:${step.name}`);
57
- const startTime = Date.now();
58
- if (dryRun && step.options.dryRun !== "execute") {
59
- if (step.options.dryRun === "skip") {
60
- stepLogger.info("skipped (dry-run)");
61
- stepHistory.push({
62
- name: step.name,
63
- status: "skipped",
64
- duration: 0
65
- });
66
- continue;
67
- }
68
- if (step.options.dryRun === "simulate" && step.options.simulate) {
69
- stepLogger.info("simulating (dry-run)");
70
- try {
71
- await step.options.simulate({ logger: stepLogger });
72
- } catch (simError) {
73
- stepLogger.warn("simulate failed", { error: simError });
74
- }
75
- stepHistory.push({
76
- name: step.name,
77
- status: "simulated",
78
- duration: Date.now() - startTime
79
- });
80
- continue;
81
- }
82
- stepLogger.info("skipped (dry-run, no simulate fn)");
83
- stepHistory.push({
84
- name: step.name,
85
- status: "skipped",
86
- duration: 0
87
- });
88
- continue;
89
- }
90
- await captureScreenshot(page, (0, import_node_path.join)(logDir, `${step.name}-start.png`), stepLogger);
91
- stepLogger.info("start");
92
- try {
93
- await (0, import_recovery.attemptWithRecovery)(
94
- page,
95
- () => step.handler({ page, logger: stepLogger, config: { dryRun, debug, logDir } }),
96
- stepLogger,
97
- llmClient
98
- );
99
- stepHistory.push({
100
- name: step.name,
101
- status: "completed",
102
- duration: Date.now() - startTime
103
- });
104
- stepLogger.info("end", { status: "completed", duration: Date.now() - startTime });
105
- } catch (firstError) {
106
- let recovered = false;
107
- const customRecovery = step.options.recovery ?? {};
108
- for (const [recoveryName, recoveryHandler] of Object.entries(customRecovery)) {
109
- try {
110
- stepLogger.info(`trying custom recovery: ${recoveryName}`);
111
- await recoveryHandler({ page, logger: stepLogger });
112
- await step.handler({ page, logger: stepLogger, config: { dryRun, debug, logDir } });
113
- recovered = true;
114
- stepHistory.push({
115
- name: step.name,
116
- status: "completed",
117
- duration: Date.now() - startTime
118
- });
119
- stepLogger.info("end", {
120
- status: "completed",
121
- recoveredBy: recoveryName,
122
- duration: Date.now() - startTime
123
- });
124
- break;
125
- } catch {
126
- stepLogger.warn(`custom recovery "${recoveryName}" failed`);
127
- }
128
- }
129
- if (!recovered) {
130
- stepHistory.push({
131
- name: step.name,
132
- status: "failed",
133
- duration: Date.now() - startTime
134
- });
135
- const bundle = await generateDebugBundle(
136
- page,
137
- step.name,
138
- firstError,
139
- logDir,
140
- logPath,
141
- stepHistory,
142
- stepLogger
143
- );
144
- stepLogger.info("step:debug-bundle", { path: bundle.bundlePath });
145
- if (debug) {
146
- await (0, import_pause.debugPause)({
147
- page,
148
- session: sessionName
149
- });
150
- }
151
- throw firstError;
152
- }
153
- }
154
- await captureScreenshot(page, (0, import_node_path.join)(logDir, `${step.name}-end.png`), stepLogger);
155
- }
156
- logger.info("runner:complete", {
157
- totalSteps: steps.length,
158
- completed: stepHistory.filter((s) => s.status === "completed").length,
159
- skipped: stepHistory.filter((s) => s.status === "skipped").length,
160
- simulated: stepHistory.filter((s) => s.status === "simulated").length
161
- });
162
- await logger.close();
163
- }
164
- };
165
- }
166
- async function captureScreenshot(page, filePath, logger) {
167
- try {
168
- const buffer = await page.screenshot({ fullPage: false, timeout: 5e3 });
169
- (0, import_node_fs.writeFileSync)(filePath, buffer);
170
- } catch (err) {
171
- logger.warn("Failed to capture screenshot", {
172
- path: filePath,
173
- error: err instanceof Error ? err.message : String(err)
174
- });
175
- }
176
- }
177
- async function generateDebugBundle(page, stepName, error, logDir, logPath, stepHistory, logger) {
178
- const screenshotPath = (0, import_node_path.join)(logDir, `${stepName}-error.png`);
179
- const domPath = (0, import_node_path.join)(logDir, `${stepName}-error.html`);
180
- const bundlePath = (0, import_node_path.join)(logDir, `${stepName}-debug-bundle.json`);
181
- await captureScreenshot(page, screenshotPath, logger);
182
- try {
183
- const html = await page.content();
184
- (0, import_node_fs.writeFileSync)(domPath, html);
185
- } catch (domErr) {
186
- logger.warn("Failed to capture DOM for debug bundle", {
187
- error: domErr instanceof Error ? domErr.message : String(domErr)
188
- });
189
- }
190
- const pageUrl = page.isClosed() ? "" : page.url();
191
- const bundle = {
192
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
193
- step: stepName,
194
- error: error instanceof Error ? error.message : String(error),
195
- stacktrace: error instanceof Error ? error.stack ?? "" : "",
196
- screenshotPath,
197
- domPath,
198
- logPath,
199
- stepHistory,
200
- pageUrl
201
- };
202
- (0, import_node_fs.writeFileSync)(bundlePath, JSON.stringify(bundle, null, 2));
203
- return { bundlePath };
204
- }
205
- // Annotate the CommonJS export names for ESM import in node:
206
- 0 && (module.exports = {
207
- createRunner
208
- });
@@ -1,16 +0,0 @@
1
- import { Page } from 'playwright';
2
- import { Step, RunnerConfig } from './types.cjs';
3
- import '../../shared/logger/logger.cjs';
4
- import '../../shared/llm/types.cjs';
5
- import 'zod';
6
-
7
- type Runner = {
8
- run: (page: Page, steps: Step[]) => Promise<void>;
9
- };
10
- /**
11
- * Creates a step runner that executes a sequence of steps with logging,
12
- * recovery, dry-run support, and debug bundle generation.
13
- */
14
- declare function createRunner(config?: RunnerConfig): Runner;
15
-
16
- export { type Runner, createRunner };
@@ -1,16 +0,0 @@
1
- import { Page } from 'playwright';
2
- import { Step, RunnerConfig } from './types.js';
3
- import '../../shared/logger/logger.js';
4
- import '../../shared/llm/types.js';
5
- import 'zod';
6
-
7
- type Runner = {
8
- run: (page: Page, steps: Step[]) => Promise<void>;
9
- };
10
- /**
11
- * Creates a step runner that executes a sequence of steps with logging,
12
- * recovery, dry-run support, and debug bundle generation.
13
- */
14
- declare function createRunner(config?: RunnerConfig): Runner;
15
-
16
- export { type Runner, createRunner };