libretto 0.5.0 → 0.5.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.
- package/README.md +109 -35
- package/dist/cli/cli.js +22 -97
- package/dist/cli/commands/browser.js +86 -59
- package/dist/cli/commands/execution.js +199 -86
- package/dist/cli/commands/init.js +34 -29
- package/dist/cli/commands/logs.js +4 -5
- package/dist/cli/commands/shared.js +30 -29
- package/dist/cli/commands/snapshot.js +26 -39
- package/dist/cli/core/ai-config.js +21 -4
- package/dist/cli/core/api-snapshot-analyzer.js +15 -5
- package/dist/cli/core/browser.js +207 -37
- package/dist/cli/core/context.js +4 -1
- package/dist/cli/core/session-telemetry.js +434 -174
- package/dist/cli/core/session.js +21 -8
- package/dist/cli/core/snapshot-analyzer.js +14 -31
- package/dist/cli/core/snapshot-api-config.js +2 -6
- package/dist/cli/core/telemetry.js +20 -4
- package/dist/cli/framework/simple-cli.js +45 -25
- package/dist/cli/router.js +14 -21
- package/dist/cli/workers/run-integration-runtime.js +24 -5
- package/dist/cli/workers/run-integration-worker-protocol.js +3 -1
- package/dist/cli/workers/run-integration-worker.js +1 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.js +7 -10
- package/dist/runtime/download/download.js +5 -1
- package/dist/runtime/extract/extract.js +11 -2
- package/dist/runtime/network/network.js +8 -1
- package/dist/runtime/recovery/agent.js +6 -2
- package/dist/runtime/recovery/errors.js +3 -1
- package/dist/runtime/recovery/recovery.js +3 -1
- package/dist/shared/condense-dom/condense-dom.js +17 -69
- package/dist/shared/config/config.d.ts +1 -9
- package/dist/shared/config/config.js +0 -18
- package/dist/shared/config/index.d.ts +2 -1
- package/dist/shared/config/index.js +0 -10
- package/dist/shared/debug/pause.js +9 -3
- package/dist/shared/dom-semantics.d.ts +8 -0
- package/dist/shared/dom-semantics.js +69 -0
- package/dist/shared/instrumentation/instrument.js +101 -5
- package/dist/shared/llm/ai-sdk-adapter.js +3 -1
- package/dist/shared/llm/client.js +3 -1
- package/dist/shared/logger/index.js +4 -1
- package/dist/shared/run/api.js +3 -1
- package/dist/shared/run/browser.js +47 -3
- package/dist/shared/state/session-state.d.ts +2 -1
- package/dist/shared/state/session-state.js +5 -2
- package/dist/shared/visualization/ghost-cursor.js +36 -14
- package/dist/shared/visualization/highlight.js +9 -6
- package/dist/shared/workflow/workflow.d.ts +4 -5
- package/dist/shared/workflow/workflow.js +3 -5
- package/package.json +6 -2
- package/scripts/check-skills-sync.mjs +25 -0
- package/scripts/compare-eval-summary.mjs +47 -0
- package/scripts/postinstall.mjs +15 -15
- package/scripts/prepare-release.sh +97 -0
- package/scripts/skills-libretto.mjs +103 -0
- package/scripts/summarize-evals.mjs +135 -0
- package/scripts/sync-skills.mjs +12 -0
- package/skills/libretto/SKILL.md +132 -54
- package/skills/libretto/references/action-logs.md +101 -0
- package/skills/libretto/references/auth-profiles.md +1 -2
- package/skills/libretto/references/code-generation-rules.md +210 -0
- package/skills/libretto/references/configuration-file-reference.md +53 -0
- package/skills/libretto/references/pages-and-page-targeting.md +1 -1
- package/skills/libretto/references/site-security-review.md +143 -0
- package/src/cli/cli.ts +23 -110
- package/src/cli/commands/browser.ts +94 -70
- package/src/cli/commands/execution.ts +233 -102
- package/src/cli/commands/init.ts +37 -33
- package/src/cli/commands/logs.ts +7 -7
- package/src/cli/commands/shared.ts +36 -37
- package/src/cli/commands/snapshot.ts +44 -59
- package/src/cli/core/ai-config.ts +24 -4
- package/src/cli/core/api-snapshot-analyzer.ts +17 -6
- package/src/cli/core/browser.ts +260 -49
- package/src/cli/core/context.ts +7 -2
- package/src/cli/core/session-telemetry.ts +449 -197
- package/src/cli/core/session.ts +21 -7
- package/src/cli/core/snapshot-analyzer.ts +26 -46
- package/src/cli/core/snapshot-api-config.ts +170 -175
- package/src/cli/core/telemetry.ts +39 -4
- package/src/cli/framework/simple-cli.ts +144 -77
- package/src/cli/router.ts +13 -21
- package/src/cli/workers/run-integration-runtime.ts +36 -9
- package/src/cli/workers/run-integration-worker-protocol.ts +2 -0
- package/src/cli/workers/run-integration-worker.ts +1 -4
- package/src/index.ts +73 -66
- package/src/runtime/download/download.ts +62 -58
- package/src/runtime/download/index.ts +5 -5
- package/src/runtime/extract/extract.ts +71 -61
- package/src/runtime/network/index.ts +3 -3
- package/src/runtime/network/network.ts +99 -93
- package/src/runtime/recovery/agent.ts +217 -212
- package/src/runtime/recovery/errors.ts +107 -104
- package/src/runtime/recovery/index.ts +3 -3
- package/src/runtime/recovery/recovery.ts +38 -35
- package/src/shared/condense-dom/condense-dom.ts +27 -82
- package/src/shared/config/config.ts +0 -19
- package/src/shared/config/index.ts +0 -5
- package/src/shared/debug/pause.ts +57 -51
- package/src/shared/dom-semantics.ts +68 -0
- package/src/shared/instrumentation/errors.ts +64 -62
- package/src/shared/instrumentation/index.ts +5 -5
- package/src/shared/instrumentation/instrument.ts +339 -209
- package/src/shared/llm/ai-sdk-adapter.ts +58 -55
- package/src/shared/llm/client.ts +181 -174
- package/src/shared/llm/types.ts +39 -39
- package/src/shared/logger/index.ts +11 -4
- package/src/shared/logger/logger.ts +312 -306
- package/src/shared/logger/sinks.ts +118 -114
- package/src/shared/paths/paths.ts +50 -49
- package/src/shared/paths/repo-root.ts +17 -17
- package/src/shared/run/api.ts +5 -1
- package/src/shared/run/browser.ts +65 -3
- package/src/shared/state/index.ts +9 -9
- package/src/shared/state/session-state.ts +46 -43
- package/src/shared/visualization/ghost-cursor.ts +180 -149
- package/src/shared/visualization/highlight.ts +89 -86
- package/src/shared/visualization/index.ts +13 -13
- package/src/shared/workflow/workflow.ts +19 -25
- package/skills/libretto/references/reverse-engineering-network-requests.md +0 -39
- package/skills/libretto/references/user-action-log.md +0 -31
package/src/cli/commands/logs.ts
CHANGED
|
@@ -12,13 +12,15 @@ import {
|
|
|
12
12
|
import { SimpleCLI } from "../framework/simple-cli.js";
|
|
13
13
|
import {
|
|
14
14
|
integerOption,
|
|
15
|
-
loadSessionStateMiddleware,
|
|
16
15
|
pageOption,
|
|
17
|
-
resolveSessionMiddleware,
|
|
18
16
|
sessionOption,
|
|
17
|
+
withRequiredSession,
|
|
19
18
|
} from "./shared.js";
|
|
20
19
|
|
|
21
|
-
async function resolvePageId(
|
|
20
|
+
async function resolvePageId(
|
|
21
|
+
session: string,
|
|
22
|
+
pageId?: string,
|
|
23
|
+
): Promise<string | undefined> {
|
|
22
24
|
if (!pageId) return undefined;
|
|
23
25
|
const pages = await withSessionLogger(session, async (logger) =>
|
|
24
26
|
listOpenPages(session, logger),
|
|
@@ -48,8 +50,7 @@ export const networkCommand = SimpleCLI.command({
|
|
|
48
50
|
description: "View captured network requests",
|
|
49
51
|
})
|
|
50
52
|
.input(networkInput)
|
|
51
|
-
.use(
|
|
52
|
-
.use(loadSessionStateMiddleware)
|
|
53
|
+
.use(withRequiredSession())
|
|
53
54
|
.handle(async ({ input, ctx }) => {
|
|
54
55
|
if (input.clear) {
|
|
55
56
|
clearNetworkLog(ctx.session);
|
|
@@ -93,8 +94,7 @@ export const actionsCommand = SimpleCLI.command({
|
|
|
93
94
|
description: "View captured actions",
|
|
94
95
|
})
|
|
95
96
|
.input(actionsInput)
|
|
96
|
-
.use(
|
|
97
|
-
.use(loadSessionStateMiddleware)
|
|
97
|
+
.use(withRequiredSession())
|
|
98
98
|
.handle(async ({ input, ctx }) => {
|
|
99
99
|
if (input.clear) {
|
|
100
100
|
clearActionLog(ctx.session);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import type { LoggerApi } from "../../shared/logger/index.js";
|
|
3
|
+
import { createLoggerForSession } from "../core/context.js";
|
|
2
4
|
import {
|
|
3
|
-
|
|
5
|
+
generateSessionName,
|
|
4
6
|
readSessionStateOrThrow,
|
|
5
7
|
type SessionState,
|
|
6
8
|
validateSessionName,
|
|
@@ -10,21 +12,8 @@ import {
|
|
|
10
12
|
type SimpleCLIMiddleware,
|
|
11
13
|
} from "../framework/simple-cli.js";
|
|
12
14
|
|
|
13
|
-
export function
|
|
14
|
-
return z.string().
|
|
15
|
-
try {
|
|
16
|
-
validateSessionName(value);
|
|
17
|
-
} catch (err) {
|
|
18
|
-
ctx.addIssue({
|
|
19
|
-
code: z.ZodIssueCode.custom,
|
|
20
|
-
message: err instanceof Error ? err.message : String(err),
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function sessionOption(help = "Use a named session") {
|
|
27
|
-
return SimpleCLI.option(createSessionSchema(), { help });
|
|
15
|
+
export function sessionOption(help = "Session name") {
|
|
16
|
+
return SimpleCLI.option(z.string().optional(), { help });
|
|
28
17
|
}
|
|
29
18
|
|
|
30
19
|
export function pageOption(help = "Target a specific page id") {
|
|
@@ -35,36 +24,46 @@ export function integerOption(help?: string) {
|
|
|
35
24
|
return SimpleCLI.option(z.coerce.number().int().optional(), { help });
|
|
36
25
|
}
|
|
37
26
|
|
|
38
|
-
export type SessionInput = {
|
|
39
|
-
session: string;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
27
|
export type SessionContext = {
|
|
43
28
|
session: string;
|
|
29
|
+
logger: LoggerApi;
|
|
44
30
|
};
|
|
45
31
|
|
|
46
32
|
export type SessionStateContext = SessionContext & {
|
|
47
33
|
sessionState: SessionState;
|
|
48
34
|
};
|
|
49
35
|
|
|
50
|
-
export
|
|
51
|
-
|
|
36
|
+
export function withRequiredSession(): SimpleCLIMiddleware<
|
|
37
|
+
{ session?: string },
|
|
52
38
|
{},
|
|
53
|
-
|
|
54
|
-
>
|
|
55
|
-
return {
|
|
56
|
-
|
|
57
|
-
|
|
39
|
+
SessionStateContext
|
|
40
|
+
> {
|
|
41
|
+
return async ({ input, ctx }) => {
|
|
42
|
+
if (!input.session) {
|
|
43
|
+
throw new Error("Missing required option --session.");
|
|
44
|
+
}
|
|
45
|
+
validateSessionName(input.session);
|
|
46
|
+
const logger = createLoggerForSession(input.session);
|
|
47
|
+
return {
|
|
48
|
+
...ctx,
|
|
49
|
+
session: input.session,
|
|
50
|
+
logger,
|
|
51
|
+
sessionState: readSessionStateOrThrow(input.session),
|
|
52
|
+
};
|
|
58
53
|
};
|
|
59
|
-
}
|
|
54
|
+
}
|
|
60
55
|
|
|
61
|
-
export
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
>
|
|
66
|
-
return {
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
export function withAutoSession(): SimpleCLIMiddleware<
|
|
57
|
+
{ session?: string },
|
|
58
|
+
{},
|
|
59
|
+
SessionContext
|
|
60
|
+
> {
|
|
61
|
+
return async ({ input, ctx }) => {
|
|
62
|
+
const session = input.session ?? generateSessionName();
|
|
63
|
+
if (input.session) {
|
|
64
|
+
validateSessionName(input.session);
|
|
65
|
+
}
|
|
66
|
+
const logger = createLoggerForSession(session);
|
|
67
|
+
return { ...ctx, session, logger };
|
|
69
68
|
};
|
|
70
|
-
}
|
|
69
|
+
}
|
|
@@ -10,17 +10,11 @@ import {
|
|
|
10
10
|
type ScreenshotPair,
|
|
11
11
|
} from "../core/snapshot-analyzer.js";
|
|
12
12
|
import { SimpleCLI } from "../framework/simple-cli.js";
|
|
13
|
-
import {
|
|
14
|
-
loadSessionStateMiddleware,
|
|
15
|
-
pageOption,
|
|
16
|
-
resolveSessionMiddleware,
|
|
17
|
-
sessionOption,
|
|
18
|
-
} from "./shared.js";
|
|
13
|
+
import { pageOption, sessionOption, withRequiredSession } from "./shared.js";
|
|
19
14
|
import { runApiInterpret } from "../core/api-snapshot-analyzer.js";
|
|
20
15
|
import { readAiConfig } from "../core/ai-config.js";
|
|
21
16
|
import { resolveSnapshotApiModelOrThrow } from "../core/snapshot-api-config.js";
|
|
22
17
|
|
|
23
|
-
const DEFAULT_SNAPSHOT_CONTEXT = "No additional user context provided.";
|
|
24
18
|
const FALLBACK_SNAPSHOT_VIEWPORT = { width: 1280, height: 800 } as const;
|
|
25
19
|
|
|
26
20
|
function generateSnapshotRunId(): string {
|
|
@@ -38,28 +32,28 @@ function isZeroViewport(value: number | null): boolean {
|
|
|
38
32
|
return typeof value === "number" && value <= 0;
|
|
39
33
|
}
|
|
40
34
|
|
|
41
|
-
function shouldForceSnapshotViewport(
|
|
35
|
+
function shouldForceSnapshotViewport(
|
|
36
|
+
metrics: SnapshotViewportMetrics,
|
|
37
|
+
): boolean {
|
|
42
38
|
return (
|
|
43
|
-
isZeroViewport(metrics.configuredWidth)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
isZeroViewport(metrics.configuredWidth) ||
|
|
40
|
+
isZeroViewport(metrics.configuredHeight) ||
|
|
41
|
+
isZeroViewport(metrics.innerWidth) ||
|
|
42
|
+
isZeroViewport(metrics.innerHeight)
|
|
47
43
|
);
|
|
48
44
|
}
|
|
49
45
|
|
|
50
46
|
function isZeroWidthScreenshotError(error: unknown): boolean {
|
|
51
47
|
return (
|
|
52
|
-
error instanceof Error
|
|
53
|
-
|
|
48
|
+
error instanceof Error &&
|
|
49
|
+
error.message.includes("Cannot take screenshot with 0 width")
|
|
54
50
|
);
|
|
55
51
|
}
|
|
56
52
|
|
|
57
|
-
async function readSnapshotViewportMetrics(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
},
|
|
62
|
-
): Promise<SnapshotViewportMetrics> {
|
|
53
|
+
async function readSnapshotViewportMetrics(page: {
|
|
54
|
+
viewportSize(): { width: number; height: number } | null;
|
|
55
|
+
evaluate<T>(pageFunction: () => T | Promise<T>): Promise<T>;
|
|
56
|
+
}): Promise<SnapshotViewportMetrics> {
|
|
63
57
|
const configuredViewport = page.viewportSize();
|
|
64
58
|
let innerWidth: number | null = null;
|
|
65
59
|
let innerHeight: number | null = null;
|
|
@@ -161,6 +155,12 @@ async function captureScreenshot(
|
|
|
161
155
|
const htmlPath = `${snapshotRunDir}/page.html`;
|
|
162
156
|
const condensedHtmlPath = `${snapshotRunDir}/page.condensed.html`;
|
|
163
157
|
|
|
158
|
+
const RENDER_SETTLE_TIMEOUT_MS = 10_000;
|
|
159
|
+
await Promise.race([
|
|
160
|
+
page.waitForLoadState("networkidle").catch(() => {}),
|
|
161
|
+
new Promise((resolve) => setTimeout(resolve, RENDER_SETTLE_TIMEOUT_MS)),
|
|
162
|
+
]);
|
|
163
|
+
|
|
164
164
|
const restoreViewport = resolveSnapshotViewport(session, logger);
|
|
165
165
|
const viewportMetrics = await readSnapshotViewportMetrics(page);
|
|
166
166
|
logger.info("screenshot-viewport-metrics", {
|
|
@@ -249,22 +249,15 @@ async function captureScreenshot(
|
|
|
249
249
|
async function runSnapshot(
|
|
250
250
|
session: string,
|
|
251
251
|
logger: LoggerApi,
|
|
252
|
-
pageId
|
|
253
|
-
objective
|
|
254
|
-
context
|
|
252
|
+
pageId: string | undefined,
|
|
253
|
+
objective: string,
|
|
254
|
+
context: string,
|
|
255
255
|
): Promise<void> {
|
|
256
|
-
const normalizedObjective = objective
|
|
257
|
-
const normalizedContext = context
|
|
258
|
-
if (!normalizedObjective && normalizedContext) {
|
|
259
|
-
throw new Error(
|
|
260
|
-
"Couldn't run analysis: --objective is required when providing --context.",
|
|
261
|
-
);
|
|
262
|
-
}
|
|
256
|
+
const normalizedObjective = objective.trim();
|
|
257
|
+
const normalizedContext = context.trim();
|
|
263
258
|
|
|
264
|
-
const configuredAi =
|
|
265
|
-
|
|
266
|
-
resolveSnapshotApiModelOrThrow(configuredAi);
|
|
267
|
-
}
|
|
259
|
+
const configuredAi = readAiConfig();
|
|
260
|
+
resolveSnapshotApiModelOrThrow(configuredAi);
|
|
268
261
|
|
|
269
262
|
const { pngPath, htmlPath, condensedHtmlPath } = await captureScreenshot(
|
|
270
263
|
session,
|
|
@@ -277,15 +270,10 @@ async function runSnapshot(
|
|
|
277
270
|
console.log(` HTML: ${htmlPath}`);
|
|
278
271
|
console.log(` Condensed HTML: ${condensedHtmlPath}`);
|
|
279
272
|
|
|
280
|
-
if (!normalizedObjective) {
|
|
281
|
-
console.log("Use --objective flag to analyze snapshots.");
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
273
|
const interpretArgs: InterpretArgs = {
|
|
286
274
|
objective: normalizedObjective,
|
|
287
275
|
session,
|
|
288
|
-
context: normalizedContext
|
|
276
|
+
context: normalizedContext,
|
|
289
277
|
pngPath,
|
|
290
278
|
htmlPath,
|
|
291
279
|
condensedHtmlPath,
|
|
@@ -303,25 +291,22 @@ export const snapshotInput = SimpleCLI.input({
|
|
|
303
291
|
named: {
|
|
304
292
|
session: sessionOption(),
|
|
305
293
|
page: pageOption(),
|
|
306
|
-
objective: SimpleCLI.option(z.string()
|
|
307
|
-
context: SimpleCLI.option(z.string()
|
|
294
|
+
objective: SimpleCLI.option(z.string()),
|
|
295
|
+
context: SimpleCLI.option(z.string()),
|
|
308
296
|
},
|
|
309
297
|
});
|
|
310
298
|
|
|
311
|
-
export
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
);
|
|
326
|
-
});
|
|
327
|
-
}
|
|
299
|
+
export const snapshotCommand = SimpleCLI.command({
|
|
300
|
+
description: "Capture PNG + HTML and analyze with --objective and --context",
|
|
301
|
+
})
|
|
302
|
+
.input(snapshotInput)
|
|
303
|
+
.use(withRequiredSession())
|
|
304
|
+
.handle(async ({ input, ctx }) => {
|
|
305
|
+
await runSnapshot(
|
|
306
|
+
ctx.session,
|
|
307
|
+
ctx.logger,
|
|
308
|
+
input.page,
|
|
309
|
+
input.objective,
|
|
310
|
+
input.context,
|
|
311
|
+
);
|
|
312
|
+
});
|
|
@@ -29,11 +29,18 @@ export const ViewportConfigSchema = z.object({
|
|
|
29
29
|
});
|
|
30
30
|
export type ViewportConfig = z.infer<typeof ViewportConfigSchema>;
|
|
31
31
|
|
|
32
|
+
export const WindowPositionConfigSchema = z.object({
|
|
33
|
+
x: z.number().int(),
|
|
34
|
+
y: z.number().int(),
|
|
35
|
+
});
|
|
36
|
+
export type WindowPositionConfig = z.infer<typeof WindowPositionConfigSchema>;
|
|
37
|
+
|
|
32
38
|
export const LibrettoConfigSchema = z
|
|
33
39
|
.object({
|
|
34
40
|
version: z.literal(CURRENT_CONFIG_VERSION),
|
|
35
41
|
ai: AiConfigSchema.optional(),
|
|
36
42
|
viewport: ViewportConfigSchema.optional(),
|
|
43
|
+
windowPosition: WindowPositionConfigSchema.optional(),
|
|
37
44
|
})
|
|
38
45
|
.passthrough();
|
|
39
46
|
export type LibrettoConfig = z.infer<typeof LibrettoConfigSchema>;
|
|
@@ -51,7 +58,12 @@ const PROVIDER_ALIASES: Record<string, string> = {
|
|
|
51
58
|
google: DEFAULT_MODELS.gemini,
|
|
52
59
|
};
|
|
53
60
|
|
|
54
|
-
const CONFIGURE_PROVIDERS = [
|
|
61
|
+
const CONFIGURE_PROVIDERS = [
|
|
62
|
+
"openai",
|
|
63
|
+
"anthropic",
|
|
64
|
+
"gemini",
|
|
65
|
+
"vertex",
|
|
66
|
+
] as const;
|
|
55
67
|
|
|
56
68
|
function formatConfigureProviders(separator = " | "): string {
|
|
57
69
|
return CONFIGURE_PROVIDERS.join(separator);
|
|
@@ -75,6 +87,10 @@ function formatExpectedConfigExample(): string {
|
|
|
75
87
|
width: 1280,
|
|
76
88
|
height: 800,
|
|
77
89
|
},
|
|
90
|
+
windowPosition: {
|
|
91
|
+
x: 1600,
|
|
92
|
+
y: 120,
|
|
93
|
+
},
|
|
78
94
|
},
|
|
79
95
|
null,
|
|
80
96
|
2,
|
|
@@ -89,11 +105,13 @@ function invalidConfigError(configPath: string, detail?: string): Error {
|
|
|
89
105
|
"Expected config example:",
|
|
90
106
|
formatExpectedConfigExample(),
|
|
91
107
|
"Notes:",
|
|
92
|
-
' - "ai" and "
|
|
108
|
+
' - "ai", "viewport", and "windowPosition" are optional.',
|
|
93
109
|
' - "ai.model" must be a provider/model string like "openai/gpt-5.4" or "anthropic/claude-sonnet-4-6".',
|
|
94
110
|
"Fix the file to match this shape, or delete it and rerun:",
|
|
95
111
|
` npx libretto ai configure ${formatConfigureProviders()}`,
|
|
96
|
-
]
|
|
112
|
+
]
|
|
113
|
+
.filter(Boolean)
|
|
114
|
+
.join("\n"),
|
|
97
115
|
);
|
|
98
116
|
}
|
|
99
117
|
|
|
@@ -220,7 +238,9 @@ export function runAiConfigure(
|
|
|
220
238
|
console.log(
|
|
221
239
|
`No AI config set. Choose a default model: ${configureCommandName} ${formatConfigureProviders()}`,
|
|
222
240
|
);
|
|
223
|
-
console.log(
|
|
241
|
+
console.log(
|
|
242
|
+
"Provider credentials still come from your shell or .env file.",
|
|
243
|
+
);
|
|
224
244
|
return;
|
|
225
245
|
}
|
|
226
246
|
printAiConfig(config, configPath);
|
|
@@ -10,7 +10,6 @@ import { readFileSync } from "node:fs";
|
|
|
10
10
|
import type { LoggerApi } from "../../shared/logger/index.js";
|
|
11
11
|
import { createLLMClient } from "../../shared/llm/client.js";
|
|
12
12
|
import {
|
|
13
|
-
formatInterpretationOutput,
|
|
14
13
|
InterpretResultSchema,
|
|
15
14
|
buildInlinePromptSelection,
|
|
16
15
|
getMimeType,
|
|
@@ -19,9 +18,7 @@ import {
|
|
|
19
18
|
type InterpretArgs,
|
|
20
19
|
} from "./snapshot-analyzer.js";
|
|
21
20
|
import { readAiConfig, type AiConfig } from "./ai-config.js";
|
|
22
|
-
import {
|
|
23
|
-
resolveSnapshotApiModelOrThrow,
|
|
24
|
-
} from "./snapshot-api-config.js";
|
|
21
|
+
import { resolveSnapshotApiModelOrThrow } from "./snapshot-api-config.js";
|
|
25
22
|
|
|
26
23
|
export async function runApiInterpret(
|
|
27
24
|
args: InterpretArgs,
|
|
@@ -52,7 +49,8 @@ export async function runApiInterpret(
|
|
|
52
49
|
logger.info("api-interpret-dom-selection", {
|
|
53
50
|
configuredModel: promptSelection.stats.configuredModel,
|
|
54
51
|
fullDomEstimatedTokens: promptSelection.stats.fullDomEstimatedTokens,
|
|
55
|
-
condensedDomEstimatedTokens:
|
|
52
|
+
condensedDomEstimatedTokens:
|
|
53
|
+
promptSelection.stats.condensedDomEstimatedTokens,
|
|
56
54
|
contextWindowTokens: promptSelection.budget.contextWindowTokens,
|
|
57
55
|
promptBudgetTokens: promptSelection.budget.promptBudgetTokens,
|
|
58
56
|
selectedDom: promptSelection.domSource,
|
|
@@ -93,5 +91,18 @@ export async function runApiInterpret(
|
|
|
93
91
|
answer: parsed.answer.slice(0, 200),
|
|
94
92
|
});
|
|
95
93
|
|
|
96
|
-
console.log(
|
|
94
|
+
console.log("");
|
|
95
|
+
console.log("Analysis:");
|
|
96
|
+
console.log(parsed.answer);
|
|
97
|
+
if (parsed.selectors.length > 0) {
|
|
98
|
+
console.log("");
|
|
99
|
+
console.log("Selectors:");
|
|
100
|
+
parsed.selectors.forEach((selector, index) => {
|
|
101
|
+
console.log(` ${index + 1}. ${selector.label}: ${selector.selector}`);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (parsed.notes?.trim()) {
|
|
105
|
+
console.log("");
|
|
106
|
+
console.log(`Notes: ${parsed.notes.trim()}`);
|
|
107
|
+
}
|
|
97
108
|
}
|