libretto 0.3.1 → 0.4.0
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 +17 -7
- package/dist/cli/commands/ai.js +3 -5
- package/dist/cli/commands/browser.js +23 -2
- package/dist/cli/commands/init.js +157 -114
- package/dist/cli/commands/snapshot.js +147 -26
- package/dist/cli/core/ai-config.js +38 -46
- package/dist/cli/core/api-snapshot-analyzer.js +74 -0
- package/dist/cli/core/browser.js +21 -4
- package/dist/cli/core/context.js +1 -1
- package/dist/cli/core/snapshot-analyzer.js +295 -104
- package/dist/cli/core/snapshot-api-config.js +137 -0
- package/dist/cli/index.js +1 -0
- package/dist/shared/condense-dom/condense-dom.cjs +462 -0
- package/dist/shared/condense-dom/condense-dom.d.cts +34 -0
- package/dist/shared/condense-dom/condense-dom.d.ts +34 -0
- package/dist/shared/condense-dom/condense-dom.js +438 -0
- package/dist/shared/llm/ai-sdk-adapter.cjs +5 -1
- package/dist/shared/llm/ai-sdk-adapter.js +5 -1
- package/dist/shared/llm/client.cjs +106 -27
- package/dist/shared/llm/client.d.cts +8 -1
- package/dist/shared/llm/client.d.ts +8 -1
- package/dist/shared/llm/client.js +89 -23
- package/dist/shared/llm/types.d.cts +4 -3
- package/dist/shared/llm/types.d.ts +4 -3
- package/dist/shared/state/session-state.cjs +8 -1
- package/dist/shared/state/session-state.d.cts +24 -18
- package/dist/shared/state/session-state.d.ts +24 -18
- package/dist/shared/state/session-state.js +7 -1
- package/package.json +39 -33
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { LLMClient } from './types.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
|
|
4
|
+
type Provider = "google" | "vertex" | "anthropic" | "openai";
|
|
5
|
+
declare function parseModel(model: string): {
|
|
6
|
+
provider: Provider;
|
|
7
|
+
modelId: string;
|
|
8
|
+
};
|
|
9
|
+
declare function hasProviderCredentials(provider: Provider, env?: NodeJS.ProcessEnv): boolean;
|
|
10
|
+
declare function missingProviderCredentialsMessage(provider: Provider): string;
|
|
4
11
|
declare function createLLMClient(model: string): LLMClient;
|
|
5
12
|
|
|
6
|
-
export { createLLMClient };
|
|
13
|
+
export { type Provider, createLLMClient, hasProviderCredentials, missingProviderCredentialsMessage, parseModel };
|
|
@@ -1,32 +1,87 @@
|
|
|
1
|
-
import { createVertex } from "@ai-sdk/google-vertex";
|
|
2
|
-
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
3
|
-
import { createOpenAI } from "@ai-sdk/openai";
|
|
4
1
|
import { generateObject } from "ai";
|
|
2
|
+
const GEMINI_API_KEY_ENV_VARS = [
|
|
3
|
+
"GEMINI_API_KEY",
|
|
4
|
+
"GOOGLE_GENERATIVE_AI_API_KEY"
|
|
5
|
+
];
|
|
6
|
+
const VERTEX_PROJECT_ENV_VARS = [
|
|
7
|
+
"GOOGLE_CLOUD_PROJECT",
|
|
8
|
+
"GCLOUD_PROJECT"
|
|
9
|
+
];
|
|
10
|
+
const SUPPORTED_PROVIDER_ALIASES = {
|
|
11
|
+
google: "google",
|
|
12
|
+
gemini: "google",
|
|
13
|
+
vertex: "vertex",
|
|
14
|
+
anthropic: "anthropic",
|
|
15
|
+
codex: "openai",
|
|
16
|
+
openai: "openai"
|
|
17
|
+
};
|
|
18
|
+
function readFirstEnvValue(env, names) {
|
|
19
|
+
for (const name of names) {
|
|
20
|
+
const value = env[name]?.trim();
|
|
21
|
+
if (value) return value;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
5
25
|
function parseModel(model) {
|
|
6
26
|
const slashIndex = model.indexOf("/");
|
|
7
27
|
if (slashIndex === -1) {
|
|
8
28
|
throw new Error(
|
|
9
|
-
`Invalid model string "${model}". Expected format: "provider/model-id" (
|
|
29
|
+
`Invalid model string "${model}". Expected format: "provider/model-id" (for example "openai/gpt-5.4", "anthropic/claude-sonnet-4-6", "google/gemini-2.5-pro", or "vertex/gemini-2.5-pro").`
|
|
10
30
|
);
|
|
11
31
|
}
|
|
12
|
-
const
|
|
32
|
+
const providerInput = model.slice(0, slashIndex).toLowerCase();
|
|
33
|
+
const provider = SUPPORTED_PROVIDER_ALIASES[providerInput];
|
|
13
34
|
const modelId = model.slice(slashIndex + 1);
|
|
14
|
-
if (!
|
|
35
|
+
if (!provider) {
|
|
15
36
|
throw new Error(
|
|
16
|
-
`Unsupported provider "${
|
|
37
|
+
`Unsupported provider "${providerInput}". Supported providers: openai/codex, anthropic, google (Gemini API), and vertex.`
|
|
17
38
|
);
|
|
18
39
|
}
|
|
19
40
|
return { provider, modelId };
|
|
20
41
|
}
|
|
21
|
-
function
|
|
42
|
+
function hasProviderCredentials(provider, env = process.env) {
|
|
43
|
+
switch (provider) {
|
|
44
|
+
case "google":
|
|
45
|
+
return readFirstEnvValue(env, GEMINI_API_KEY_ENV_VARS) !== null;
|
|
46
|
+
case "vertex":
|
|
47
|
+
return readFirstEnvValue(env, VERTEX_PROJECT_ENV_VARS) !== null;
|
|
48
|
+
case "anthropic":
|
|
49
|
+
return Boolean(env.ANTHROPIC_API_KEY?.trim());
|
|
50
|
+
case "openai":
|
|
51
|
+
return Boolean(env.OPENAI_API_KEY?.trim());
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function missingProviderCredentialsMessage(provider) {
|
|
55
|
+
switch (provider) {
|
|
56
|
+
case "google":
|
|
57
|
+
return "Missing Gemini API key. Set GEMINI_API_KEY or GOOGLE_GENERATIVE_AI_API_KEY.";
|
|
58
|
+
case "vertex":
|
|
59
|
+
return "Missing Vertex AI project. Set GOOGLE_CLOUD_PROJECT (or GCLOUD_PROJECT) and ensure application default credentials are configured.";
|
|
60
|
+
case "anthropic": {
|
|
61
|
+
return "Missing Anthropic API key. Set ANTHROPIC_API_KEY.";
|
|
62
|
+
}
|
|
63
|
+
case "openai": {
|
|
64
|
+
return "Missing OpenAI API key. Set OPENAI_API_KEY.";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function getProviderModel(provider, modelId) {
|
|
22
69
|
switch (provider) {
|
|
23
70
|
case "google": {
|
|
24
|
-
const
|
|
71
|
+
const apiKey = readFirstEnvValue(process.env, GEMINI_API_KEY_ENV_VARS);
|
|
72
|
+
if (!apiKey) {
|
|
73
|
+
throw new Error(missingProviderCredentialsMessage(provider));
|
|
74
|
+
}
|
|
75
|
+
const { createGoogleGenerativeAI } = await import("@ai-sdk/google");
|
|
76
|
+
const google = createGoogleGenerativeAI({ apiKey });
|
|
77
|
+
return google(modelId);
|
|
78
|
+
}
|
|
79
|
+
case "vertex": {
|
|
80
|
+
const project = readFirstEnvValue(process.env, VERTEX_PROJECT_ENV_VARS);
|
|
25
81
|
if (!project) {
|
|
26
|
-
throw new Error(
|
|
27
|
-
"Missing GCP project for Vertex AI. Set GOOGLE_CLOUD_PROJECT environment variable and ensure application default credentials are configured (gcloud auth application-default login)."
|
|
28
|
-
);
|
|
82
|
+
throw new Error(missingProviderCredentialsMessage(provider));
|
|
29
83
|
}
|
|
84
|
+
const { createVertex } = await import("@ai-sdk/google-vertex");
|
|
30
85
|
const vertex = createVertex({
|
|
31
86
|
project,
|
|
32
87
|
location: process.env.GOOGLE_CLOUD_LOCATION || "global"
|
|
@@ -34,22 +89,20 @@ function getProviderModel(provider, modelId) {
|
|
|
34
89
|
return vertex(modelId);
|
|
35
90
|
}
|
|
36
91
|
case "anthropic": {
|
|
37
|
-
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
92
|
+
const apiKey = process.env.ANTHROPIC_API_KEY?.trim();
|
|
38
93
|
if (!apiKey) {
|
|
39
|
-
throw new Error(
|
|
40
|
-
"Missing API key for Anthropic. Set ANTHROPIC_API_KEY environment variable."
|
|
41
|
-
);
|
|
94
|
+
throw new Error(missingProviderCredentialsMessage(provider));
|
|
42
95
|
}
|
|
96
|
+
const { createAnthropic } = await import("@ai-sdk/anthropic");
|
|
43
97
|
const anthropic = createAnthropic({ apiKey });
|
|
44
98
|
return anthropic(modelId);
|
|
45
99
|
}
|
|
46
100
|
case "openai": {
|
|
47
|
-
const apiKey = process.env.OPENAI_API_KEY;
|
|
101
|
+
const apiKey = process.env.OPENAI_API_KEY?.trim();
|
|
48
102
|
if (!apiKey) {
|
|
49
|
-
throw new Error(
|
|
50
|
-
"Missing API key for OpenAI. Set OPENAI_API_KEY environment variable."
|
|
51
|
-
);
|
|
103
|
+
throw new Error(missingProviderCredentialsMessage(provider));
|
|
52
104
|
}
|
|
105
|
+
const { createOpenAI } = await import("@ai-sdk/openai");
|
|
53
106
|
const openai = createOpenAI({ apiKey });
|
|
54
107
|
return openai(modelId);
|
|
55
108
|
}
|
|
@@ -60,7 +113,11 @@ function convertUserContentParts(parts) {
|
|
|
60
113
|
if (part.type === "text") {
|
|
61
114
|
return { type: "text", text: part.text };
|
|
62
115
|
}
|
|
63
|
-
return {
|
|
116
|
+
return {
|
|
117
|
+
type: "image",
|
|
118
|
+
image: part.image,
|
|
119
|
+
...part.mediaType ? { mediaType: part.mediaType } : {}
|
|
120
|
+
};
|
|
64
121
|
});
|
|
65
122
|
}
|
|
66
123
|
function convertAssistantContentParts(parts) {
|
|
@@ -88,9 +145,14 @@ function convertMessages(messages) {
|
|
|
88
145
|
}
|
|
89
146
|
function createLLMClient(model) {
|
|
90
147
|
const { provider, modelId } = parseModel(model);
|
|
91
|
-
|
|
148
|
+
let modelPromise = null;
|
|
149
|
+
const getModel = () => {
|
|
150
|
+
modelPromise ??= getProviderModel(provider, modelId);
|
|
151
|
+
return modelPromise;
|
|
152
|
+
};
|
|
92
153
|
return {
|
|
93
154
|
async generateObject(opts) {
|
|
155
|
+
const aiModel = await getModel();
|
|
94
156
|
const result = await generateObject({
|
|
95
157
|
model: aiModel,
|
|
96
158
|
prompt: opts.prompt,
|
|
@@ -100,6 +162,7 @@ function createLLMClient(model) {
|
|
|
100
162
|
return result.object;
|
|
101
163
|
},
|
|
102
164
|
async generateObjectFromMessages(opts) {
|
|
165
|
+
const aiModel = await getModel();
|
|
103
166
|
const result = await generateObject({
|
|
104
167
|
model: aiModel,
|
|
105
168
|
messages: convertMessages(opts.messages),
|
|
@@ -111,5 +174,8 @@ function createLLMClient(model) {
|
|
|
111
174
|
};
|
|
112
175
|
}
|
|
113
176
|
export {
|
|
114
|
-
createLLMClient
|
|
177
|
+
createLLMClient,
|
|
178
|
+
hasProviderCredentials,
|
|
179
|
+
missingProviderCredentialsMessage,
|
|
180
|
+
parseModel
|
|
115
181
|
};
|
|
@@ -5,7 +5,8 @@ type MessageContentPart = {
|
|
|
5
5
|
text: string;
|
|
6
6
|
} | {
|
|
7
7
|
type: "image";
|
|
8
|
-
image: string;
|
|
8
|
+
image: string | Uint8Array;
|
|
9
|
+
mediaType?: string;
|
|
9
10
|
};
|
|
10
11
|
type Message = {
|
|
11
12
|
role: "user" | "assistant";
|
|
@@ -42,7 +43,7 @@ interface LLMClient {
|
|
|
42
43
|
prompt: string;
|
|
43
44
|
schema: T;
|
|
44
45
|
temperature?: number;
|
|
45
|
-
}): Promise<z.
|
|
46
|
+
}): Promise<z.output<T>>;
|
|
46
47
|
/**
|
|
47
48
|
* Generate a structured object from a conversation-style message array.
|
|
48
49
|
*
|
|
@@ -60,7 +61,7 @@ interface LLMClient {
|
|
|
60
61
|
messages: Message[];
|
|
61
62
|
schema: T;
|
|
62
63
|
temperature?: number;
|
|
63
|
-
}): Promise<z.
|
|
64
|
+
}): Promise<z.output<T>>;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
export type { LLMClient, Message, MessageContentPart };
|
|
@@ -5,7 +5,8 @@ type MessageContentPart = {
|
|
|
5
5
|
text: string;
|
|
6
6
|
} | {
|
|
7
7
|
type: "image";
|
|
8
|
-
image: string;
|
|
8
|
+
image: string | Uint8Array;
|
|
9
|
+
mediaType?: string;
|
|
9
10
|
};
|
|
10
11
|
type Message = {
|
|
11
12
|
role: "user" | "assistant";
|
|
@@ -42,7 +43,7 @@ interface LLMClient {
|
|
|
42
43
|
prompt: string;
|
|
43
44
|
schema: T;
|
|
44
45
|
temperature?: number;
|
|
45
|
-
}): Promise<z.
|
|
46
|
+
}): Promise<z.output<T>>;
|
|
46
47
|
/**
|
|
47
48
|
* Generate a structured object from a conversation-style message array.
|
|
48
49
|
*
|
|
@@ -60,7 +61,7 @@ interface LLMClient {
|
|
|
60
61
|
messages: Message[];
|
|
61
62
|
schema: T;
|
|
62
63
|
temperature?: number;
|
|
63
|
-
}): Promise<z.
|
|
64
|
+
}): Promise<z.output<T>>;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
export type { LLMClient, Message, MessageContentPart };
|
|
@@ -21,6 +21,7 @@ __export(session_state_exports, {
|
|
|
21
21
|
SESSION_STATE_VERSION: () => SESSION_STATE_VERSION,
|
|
22
22
|
SessionStateFileSchema: () => SessionStateFileSchema,
|
|
23
23
|
SessionStatusSchema: () => SessionStatusSchema,
|
|
24
|
+
SessionViewportSchema: () => SessionViewportSchema,
|
|
24
25
|
parseSessionStateContent: () => parseSessionStateContent,
|
|
25
26
|
parseSessionStateData: () => parseSessionStateData,
|
|
26
27
|
serializeSessionState: () => serializeSessionState
|
|
@@ -35,13 +36,18 @@ const SessionStatusSchema = import_zod.z.enum([
|
|
|
35
36
|
"failed",
|
|
36
37
|
"exited"
|
|
37
38
|
]);
|
|
39
|
+
const SessionViewportSchema = import_zod.z.object({
|
|
40
|
+
width: import_zod.z.number().int().min(1),
|
|
41
|
+
height: import_zod.z.number().int().min(1)
|
|
42
|
+
});
|
|
38
43
|
const SessionStateFileSchema = import_zod.z.object({
|
|
39
44
|
version: import_zod.z.literal(SESSION_STATE_VERSION),
|
|
40
45
|
port: import_zod.z.number().int().min(0).max(65535),
|
|
41
46
|
pid: import_zod.z.number().int(),
|
|
42
47
|
session: import_zod.z.string().min(1),
|
|
43
48
|
startedAt: import_zod.z.string().datetime({ offset: true }),
|
|
44
|
-
status: SessionStatusSchema.optional()
|
|
49
|
+
status: SessionStatusSchema.optional(),
|
|
50
|
+
viewport: SessionViewportSchema.optional()
|
|
45
51
|
});
|
|
46
52
|
function formatIssues(error) {
|
|
47
53
|
return error.issues.map((issue) => {
|
|
@@ -79,6 +85,7 @@ function serializeSessionState(state) {
|
|
|
79
85
|
SESSION_STATE_VERSION,
|
|
80
86
|
SessionStateFileSchema,
|
|
81
87
|
SessionStatusSchema,
|
|
88
|
+
SessionViewportSchema,
|
|
82
89
|
parseSessionStateContent,
|
|
83
90
|
parseSessionStateData,
|
|
84
91
|
serializeSessionState
|
|
@@ -1,29 +1,35 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
declare const SESSION_STATE_VERSION = 1;
|
|
4
|
-
declare const SessionStatusSchema: z.ZodEnum<
|
|
4
|
+
declare const SessionStatusSchema: z.ZodEnum<{
|
|
5
|
+
active: "active";
|
|
6
|
+
paused: "paused";
|
|
7
|
+
completed: "completed";
|
|
8
|
+
failed: "failed";
|
|
9
|
+
exited: "exited";
|
|
10
|
+
}>;
|
|
11
|
+
declare const SessionViewportSchema: z.ZodObject<{
|
|
12
|
+
width: z.ZodNumber;
|
|
13
|
+
height: z.ZodNumber;
|
|
14
|
+
}, z.core.$strip>;
|
|
5
15
|
declare const SessionStateFileSchema: z.ZodObject<{
|
|
6
16
|
version: z.ZodLiteral<1>;
|
|
7
17
|
port: z.ZodNumber;
|
|
8
18
|
pid: z.ZodNumber;
|
|
9
19
|
session: z.ZodString;
|
|
10
20
|
startedAt: z.ZodString;
|
|
11
|
-
status: z.ZodOptional<z.ZodEnum<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
session: string;
|
|
24
|
-
startedAt: string;
|
|
25
|
-
status?: "active" | "paused" | "completed" | "failed" | "exited" | undefined;
|
|
26
|
-
}>;
|
|
21
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
22
|
+
active: "active";
|
|
23
|
+
paused: "paused";
|
|
24
|
+
completed: "completed";
|
|
25
|
+
failed: "failed";
|
|
26
|
+
exited: "exited";
|
|
27
|
+
}>>;
|
|
28
|
+
viewport: z.ZodOptional<z.ZodObject<{
|
|
29
|
+
width: z.ZodNumber;
|
|
30
|
+
height: z.ZodNumber;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
}, z.core.$strip>;
|
|
27
33
|
type SessionStatus = z.infer<typeof SessionStatusSchema>;
|
|
28
34
|
type SessionStateFile = z.infer<typeof SessionStateFileSchema>;
|
|
29
35
|
type SessionState = Omit<SessionStateFile, "version">;
|
|
@@ -31,4 +37,4 @@ declare function parseSessionStateData(rawState: unknown, source: string): Sessi
|
|
|
31
37
|
declare function parseSessionStateContent(content: string, source: string): SessionState;
|
|
32
38
|
declare function serializeSessionState(state: SessionState): SessionStateFile;
|
|
33
39
|
|
|
34
|
-
export { SESSION_STATE_VERSION, type SessionState, type SessionStateFile, SessionStateFileSchema, type SessionStatus, SessionStatusSchema, parseSessionStateContent, parseSessionStateData, serializeSessionState };
|
|
40
|
+
export { SESSION_STATE_VERSION, type SessionState, type SessionStateFile, SessionStateFileSchema, type SessionStatus, SessionStatusSchema, SessionViewportSchema, parseSessionStateContent, parseSessionStateData, serializeSessionState };
|
|
@@ -1,29 +1,35 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
declare const SESSION_STATE_VERSION = 1;
|
|
4
|
-
declare const SessionStatusSchema: z.ZodEnum<
|
|
4
|
+
declare const SessionStatusSchema: z.ZodEnum<{
|
|
5
|
+
active: "active";
|
|
6
|
+
paused: "paused";
|
|
7
|
+
completed: "completed";
|
|
8
|
+
failed: "failed";
|
|
9
|
+
exited: "exited";
|
|
10
|
+
}>;
|
|
11
|
+
declare const SessionViewportSchema: z.ZodObject<{
|
|
12
|
+
width: z.ZodNumber;
|
|
13
|
+
height: z.ZodNumber;
|
|
14
|
+
}, z.core.$strip>;
|
|
5
15
|
declare const SessionStateFileSchema: z.ZodObject<{
|
|
6
16
|
version: z.ZodLiteral<1>;
|
|
7
17
|
port: z.ZodNumber;
|
|
8
18
|
pid: z.ZodNumber;
|
|
9
19
|
session: z.ZodString;
|
|
10
20
|
startedAt: z.ZodString;
|
|
11
|
-
status: z.ZodOptional<z.ZodEnum<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
session: string;
|
|
24
|
-
startedAt: string;
|
|
25
|
-
status?: "active" | "paused" | "completed" | "failed" | "exited" | undefined;
|
|
26
|
-
}>;
|
|
21
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
22
|
+
active: "active";
|
|
23
|
+
paused: "paused";
|
|
24
|
+
completed: "completed";
|
|
25
|
+
failed: "failed";
|
|
26
|
+
exited: "exited";
|
|
27
|
+
}>>;
|
|
28
|
+
viewport: z.ZodOptional<z.ZodObject<{
|
|
29
|
+
width: z.ZodNumber;
|
|
30
|
+
height: z.ZodNumber;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
}, z.core.$strip>;
|
|
27
33
|
type SessionStatus = z.infer<typeof SessionStatusSchema>;
|
|
28
34
|
type SessionStateFile = z.infer<typeof SessionStateFileSchema>;
|
|
29
35
|
type SessionState = Omit<SessionStateFile, "version">;
|
|
@@ -31,4 +37,4 @@ declare function parseSessionStateData(rawState: unknown, source: string): Sessi
|
|
|
31
37
|
declare function parseSessionStateContent(content: string, source: string): SessionState;
|
|
32
38
|
declare function serializeSessionState(state: SessionState): SessionStateFile;
|
|
33
39
|
|
|
34
|
-
export { SESSION_STATE_VERSION, type SessionState, type SessionStateFile, SessionStateFileSchema, type SessionStatus, SessionStatusSchema, parseSessionStateContent, parseSessionStateData, serializeSessionState };
|
|
40
|
+
export { SESSION_STATE_VERSION, type SessionState, type SessionStateFile, SessionStateFileSchema, type SessionStatus, SessionStatusSchema, SessionViewportSchema, parseSessionStateContent, parseSessionStateData, serializeSessionState };
|
|
@@ -7,13 +7,18 @@ const SessionStatusSchema = z.enum([
|
|
|
7
7
|
"failed",
|
|
8
8
|
"exited"
|
|
9
9
|
]);
|
|
10
|
+
const SessionViewportSchema = z.object({
|
|
11
|
+
width: z.number().int().min(1),
|
|
12
|
+
height: z.number().int().min(1)
|
|
13
|
+
});
|
|
10
14
|
const SessionStateFileSchema = z.object({
|
|
11
15
|
version: z.literal(SESSION_STATE_VERSION),
|
|
12
16
|
port: z.number().int().min(0).max(65535),
|
|
13
17
|
pid: z.number().int(),
|
|
14
18
|
session: z.string().min(1),
|
|
15
19
|
startedAt: z.string().datetime({ offset: true }),
|
|
16
|
-
status: SessionStatusSchema.optional()
|
|
20
|
+
status: SessionStatusSchema.optional(),
|
|
21
|
+
viewport: SessionViewportSchema.optional()
|
|
17
22
|
});
|
|
18
23
|
function formatIssues(error) {
|
|
19
24
|
return error.issues.map((issue) => {
|
|
@@ -50,6 +55,7 @@ export {
|
|
|
50
55
|
SESSION_STATE_VERSION,
|
|
51
56
|
SessionStateFileSchema,
|
|
52
57
|
SessionStatusSchema,
|
|
58
|
+
SessionViewportSchema,
|
|
53
59
|
parseSessionStateContent,
|
|
54
60
|
parseSessionStateData,
|
|
55
61
|
serializeSessionState
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libretto",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "AI-powered browser automation library and CLI built on Playwright",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"url": "https://github.com/saffron-health/libretto"
|
|
9
9
|
},
|
|
10
10
|
"type": "module",
|
|
11
|
+
"packageManager": "pnpm@9.15.4",
|
|
11
12
|
"publishConfig": {
|
|
12
13
|
"access": "public"
|
|
13
14
|
},
|
|
@@ -26,16 +27,32 @@
|
|
|
26
27
|
"require": "./dist/index.cjs"
|
|
27
28
|
}
|
|
28
29
|
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"postinstall": "playwright install chromium",
|
|
32
|
+
"build": "pnpm run build:runtime && pnpm run build:cli",
|
|
33
|
+
"build:runtime": "tsup --config tsup.config.ts",
|
|
34
|
+
"build:cli": "tsup --config tsup.cli.config.ts",
|
|
35
|
+
"type-check": "tsc --noEmit",
|
|
36
|
+
"test": "pnpm run build && vitest run",
|
|
37
|
+
"eval": "pnpm run build && vitest run --config vitest.evals.config.ts",
|
|
38
|
+
"benchmark": "pnpm run build && tsx benchmarks/run.ts",
|
|
39
|
+
"test:watch": "vitest",
|
|
40
|
+
"cli": "node dist/index.js",
|
|
41
|
+
"prepack": "pnpm run build"
|
|
42
|
+
},
|
|
29
43
|
"peerDependencies": {
|
|
30
|
-
"@ai-sdk/anthropic": "^3.0.
|
|
31
|
-
"@ai-sdk/google
|
|
32
|
-
"@ai-sdk/
|
|
33
|
-
"
|
|
44
|
+
"@ai-sdk/anthropic": "^3.0.58",
|
|
45
|
+
"@ai-sdk/google": "^3.0.51",
|
|
46
|
+
"@ai-sdk/google-vertex": "^4.0.80",
|
|
47
|
+
"@ai-sdk/openai": "^3.0.41"
|
|
34
48
|
},
|
|
35
49
|
"peerDependenciesMeta": {
|
|
36
50
|
"@ai-sdk/anthropic": {
|
|
37
51
|
"optional": true
|
|
38
52
|
},
|
|
53
|
+
"@ai-sdk/google": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
39
56
|
"@ai-sdk/google-vertex": {
|
|
40
57
|
"optional": true
|
|
41
58
|
},
|
|
@@ -44,34 +61,23 @@
|
|
|
44
61
|
}
|
|
45
62
|
},
|
|
46
63
|
"devDependencies": {
|
|
47
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.
|
|
48
|
-
"@ai-sdk/anthropic": "^3.0.
|
|
49
|
-
"@ai-sdk/google
|
|
50
|
-
"@ai-sdk/
|
|
51
|
-
"@
|
|
52
|
-
"@types/
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
64
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.75",
|
|
65
|
+
"@ai-sdk/anthropic": "^3.0.58",
|
|
66
|
+
"@ai-sdk/google": "^3.0.51",
|
|
67
|
+
"@ai-sdk/google-vertex": "^4.0.80",
|
|
68
|
+
"@ai-sdk/openai": "^3.0.41",
|
|
69
|
+
"@types/node": "^25.5.0",
|
|
70
|
+
"@types/yargs": "^17.0.35",
|
|
71
|
+
"openai": "^6.29.0",
|
|
72
|
+
"tsup": "^8.5.1",
|
|
73
|
+
"typescript": "^5.9.3",
|
|
74
|
+
"vitest": "^4.1.0"
|
|
58
75
|
},
|
|
59
76
|
"dependencies": {
|
|
60
|
-
"ai": "^6.0.
|
|
61
|
-
"playwright": "^1.
|
|
62
|
-
"tsx": "^4.
|
|
63
|
-
"yargs": "^
|
|
64
|
-
|
|
65
|
-
"scripts": {
|
|
66
|
-
"postinstall": "npx playwright install chromium",
|
|
67
|
-
"build": "pnpm run build:runtime && pnpm run build:cli",
|
|
68
|
-
"build:runtime": "tsup --config tsup.config.ts",
|
|
69
|
-
"build:cli": "tsup --config tsup.cli.config.ts",
|
|
70
|
-
"type-check": "tsc --noEmit",
|
|
71
|
-
"test": "pnpm run build && vitest run",
|
|
72
|
-
"eval": "pnpm run build && vitest run --config vitest.evals.config.ts",
|
|
73
|
-
"benchmark": "pnpm run build && tsx benchmarks/run.ts",
|
|
74
|
-
"test:watch": "vitest",
|
|
75
|
-
"cli": "node dist/index.js"
|
|
77
|
+
"ai": "^6.0.116",
|
|
78
|
+
"playwright": "^1.58.2",
|
|
79
|
+
"tsx": "^4.21.0",
|
|
80
|
+
"yargs": "^18.0.0",
|
|
81
|
+
"zod": "^4.3.6"
|
|
76
82
|
}
|
|
77
|
-
}
|
|
83
|
+
}
|