libretto 0.4.0 → 0.4.2

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.
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  import { listOpenPages } from "../core/browser.js";
2
3
  import { withSessionLogger } from "../core/context.js";
3
4
  import {
@@ -8,6 +9,14 @@ import {
8
9
  readActionLog,
9
10
  readNetworkLog
10
11
  } from "../core/telemetry.js";
12
+ import { SimpleCLI } from "../framework/simple-cli.js";
13
+ import {
14
+ integerOption,
15
+ loadSessionStateMiddleware,
16
+ pageOption,
17
+ resolveSessionMiddleware,
18
+ sessionOption
19
+ } from "./shared.js";
11
20
  async function resolvePageId(session, pageId) {
12
21
  if (!pageId) return void 0;
13
22
  const pages = await withSessionLogger(
@@ -22,72 +31,88 @@ async function resolvePageId(session, pageId) {
22
31
  }
23
32
  return pageId;
24
33
  }
25
- function registerLogCommands(yargs) {
26
- return yargs.command(
27
- "network",
28
- "View captured network requests",
29
- (cmd) => cmd.option("last", { type: "number" }).option("filter", { type: "string" }).option("method", { type: "string" }).option("page", { type: "string" }).option("clear", { type: "boolean", default: false }),
30
- async (argv) => {
31
- const session = String(argv.session);
32
- if (argv.clear) {
33
- clearNetworkLog(session);
34
- console.log("Network log cleared.");
35
- return;
36
- }
37
- const pageId = await resolvePageId(
38
- session,
39
- argv.page ? String(argv.page) : void 0
40
- );
41
- const entries = readNetworkLog(session, {
42
- last: typeof argv.last === "number" ? argv.last : void 0,
43
- filter: argv.filter,
44
- method: argv.method,
45
- pageId
46
- });
47
- if (entries.length === 0) {
48
- console.log("No network requests captured.");
49
- return;
50
- }
51
- for (const entry of entries) {
52
- console.log(formatNetworkEntry(entry));
53
- }
54
- console.log(`
34
+ const networkInput = SimpleCLI.input({
35
+ positionals: [],
36
+ named: {
37
+ session: sessionOption(),
38
+ last: integerOption(),
39
+ filter: SimpleCLI.option(z.string().optional()),
40
+ method: SimpleCLI.option(z.string().optional()),
41
+ page: pageOption(),
42
+ clear: SimpleCLI.flag()
43
+ }
44
+ });
45
+ const networkCommand = SimpleCLI.command({
46
+ description: "View captured network requests"
47
+ }).input(networkInput).use(resolveSessionMiddleware).use(loadSessionStateMiddleware).handle(async ({ input, ctx }) => {
48
+ if (input.clear) {
49
+ clearNetworkLog(ctx.session);
50
+ console.log("Network log cleared.");
51
+ return;
52
+ }
53
+ const pageId = await resolvePageId(ctx.session, input.page);
54
+ const entries = readNetworkLog(ctx.session, {
55
+ last: input.last,
56
+ filter: input.filter,
57
+ method: input.method,
58
+ pageId
59
+ });
60
+ if (entries.length === 0) {
61
+ console.log("No network requests captured.");
62
+ return;
63
+ }
64
+ for (const entry of entries) {
65
+ console.log(formatNetworkEntry(entry));
66
+ }
67
+ console.log(`
55
68
  ${entries.length} request(s) shown.`);
56
- }
57
- ).command(
58
- "actions",
59
- "View captured actions",
60
- (cmd) => cmd.option("last", { type: "number" }).option("filter", { type: "string" }).option("action", { type: "string" }).option("source", { type: "string" }).option("page", { type: "string" }).option("clear", { type: "boolean", default: false }),
61
- async (argv) => {
62
- const session = String(argv.session);
63
- if (argv.clear) {
64
- clearActionLog(session);
65
- console.log("Action log cleared.");
66
- return;
67
- }
68
- const pageId = await resolvePageId(
69
- session,
70
- argv.page ? String(argv.page) : void 0
71
- );
72
- const entries = readActionLog(session, {
73
- last: typeof argv.last === "number" ? argv.last : void 0,
74
- filter: argv.filter,
75
- action: argv.action,
76
- source: argv.source,
77
- pageId
78
- });
79
- if (entries.length === 0) {
80
- console.log("No actions captured.");
81
- return;
82
- }
83
- for (const entry of entries) {
84
- console.log(formatActionEntry(entry));
85
- }
86
- console.log(`
69
+ });
70
+ const actionsInput = SimpleCLI.input({
71
+ positionals: [],
72
+ named: {
73
+ session: sessionOption(),
74
+ last: integerOption(),
75
+ filter: SimpleCLI.option(z.string().optional()),
76
+ action: SimpleCLI.option(z.string().optional()),
77
+ source: SimpleCLI.option(z.string().optional()),
78
+ page: pageOption(),
79
+ clear: SimpleCLI.flag()
80
+ }
81
+ });
82
+ const actionsCommand = SimpleCLI.command({
83
+ description: "View captured actions"
84
+ }).input(actionsInput).use(resolveSessionMiddleware).use(loadSessionStateMiddleware).handle(async ({ input, ctx }) => {
85
+ if (input.clear) {
86
+ clearActionLog(ctx.session);
87
+ console.log("Action log cleared.");
88
+ return;
89
+ }
90
+ const pageId = await resolvePageId(ctx.session, input.page);
91
+ const entries = readActionLog(ctx.session, {
92
+ last: input.last,
93
+ filter: input.filter,
94
+ action: input.action,
95
+ source: input.source,
96
+ pageId
97
+ });
98
+ if (entries.length === 0) {
99
+ console.log("No actions captured.");
100
+ return;
101
+ }
102
+ for (const entry of entries) {
103
+ console.log(formatActionEntry(entry));
104
+ }
105
+ console.log(`
87
106
  ${entries.length} action(s) shown.`);
88
- }
89
- );
90
- }
107
+ });
108
+ const logCommands = {
109
+ network: networkCommand,
110
+ actions: actionsCommand
111
+ };
91
112
  export {
92
- registerLogCommands
113
+ actionsCommand,
114
+ actionsInput,
115
+ logCommands,
116
+ networkCommand,
117
+ networkInput
93
118
  };
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import {
3
+ SESSION_DEFAULT,
4
+ readSessionStateOrThrow,
5
+ validateSessionName
6
+ } from "../core/session.js";
7
+ import {
8
+ SimpleCLI
9
+ } from "../framework/simple-cli.js";
10
+ function createSessionSchema() {
11
+ return z.string().default(SESSION_DEFAULT).superRefine((value, ctx) => {
12
+ try {
13
+ validateSessionName(value);
14
+ } catch (err) {
15
+ ctx.addIssue({
16
+ code: z.ZodIssueCode.custom,
17
+ message: err instanceof Error ? err.message : String(err)
18
+ });
19
+ }
20
+ });
21
+ }
22
+ function sessionOption(help = "Use a named session") {
23
+ return SimpleCLI.option(createSessionSchema(), { help });
24
+ }
25
+ function pageOption(help = "Target a specific page id") {
26
+ return SimpleCLI.option(z.string().optional(), { help });
27
+ }
28
+ function integerOption(help) {
29
+ return SimpleCLI.option(z.coerce.number().int().optional(), { help });
30
+ }
31
+ const resolveSessionMiddleware = async ({ input, ctx }) => {
32
+ return {
33
+ ...ctx,
34
+ session: input.session
35
+ };
36
+ };
37
+ const loadSessionStateMiddleware = async ({ ctx }) => {
38
+ return {
39
+ ...ctx,
40
+ sessionState: readSessionStateOrThrow(ctx.session)
41
+ };
42
+ };
43
+ export {
44
+ createSessionSchema,
45
+ integerOption,
46
+ loadSessionStateMiddleware,
47
+ pageOption,
48
+ resolveSessionMiddleware,
49
+ sessionOption
50
+ };
@@ -1,8 +1,16 @@
1
1
  import { mkdirSync } from "node:fs";
2
+ import { z } from "zod";
2
3
  import { connect, disconnectBrowser } from "../core/browser.js";
3
4
  import { getSessionSnapshotRunDir } from "../core/context.js";
4
5
  import { condenseDom } from "../../shared/condense-dom/condense-dom.js";
5
6
  import { readSessionState } from "../core/session.js";
7
+ import { SimpleCLI } from "../framework/simple-cli.js";
8
+ import {
9
+ loadSessionStateMiddleware,
10
+ pageOption,
11
+ resolveSessionMiddleware,
12
+ sessionOption
13
+ } from "./shared.js";
6
14
  import { runApiInterpret } from "../core/api-snapshot-analyzer.js";
7
15
  import { readAiConfig } from "../core/ai-config.js";
8
16
  const DEFAULT_SNAPSHOT_CONTEXT = "No additional user context provided.";
@@ -206,22 +214,29 @@ async function runSnapshot(session, logger, pageId, objective, context) {
206
214
  };
207
215
  await runApiInterpret(interpretArgs, logger, readAiConfig());
208
216
  }
209
- function registerSnapshotCommands(yargs, logger) {
210
- return yargs.command(
211
- "snapshot",
212
- "Capture PNG + HTML; analyze when --objective is provided (--context optional)",
213
- (cmd) => cmd.option("page", { type: "string" }).option("objective", { type: "string" }).option("context", { type: "string" }),
214
- async (argv) => {
215
- await runSnapshot(
216
- String(argv.session),
217
- logger,
218
- argv.page ? String(argv.page) : void 0,
219
- argv.objective,
220
- argv.context
221
- );
222
- }
223
- );
217
+ const snapshotInput = SimpleCLI.input({
218
+ positionals: [],
219
+ named: {
220
+ session: sessionOption(),
221
+ page: pageOption(),
222
+ objective: SimpleCLI.option(z.string().optional()),
223
+ context: SimpleCLI.option(z.string().optional())
224
+ }
225
+ });
226
+ function createSnapshotCommand(logger) {
227
+ return SimpleCLI.command({
228
+ description: "Capture PNG + HTML; analyze when --objective is provided (--context optional)"
229
+ }).input(snapshotInput).use(resolveSessionMiddleware).use(loadSessionStateMiddleware).handle(async ({ input, ctx }) => {
230
+ await runSnapshot(
231
+ ctx.session,
232
+ logger,
233
+ input.page,
234
+ input.objective,
235
+ input.context
236
+ );
237
+ });
224
238
  }
225
239
  export {
226
- registerSnapshotCommands
240
+ createSnapshotCommand,
241
+ snapshotInput
227
242
  };