libretto 0.3.2 → 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/dist/cli/commands/ai.js +3 -5
- package/dist/cli/commands/init.js +157 -114
- package/dist/cli/commands/snapshot.js +32 -22
- package/dist/cli/core/ai-config.js +29 -44
- package/dist/cli/core/api-snapshot-analyzer.js +74 -0
- package/dist/cli/core/context.js +1 -1
- package/dist/cli/core/snapshot-analyzer.js +200 -87
- package/dist/cli/core/snapshot-api-config.js +137 -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 +2 -1
- package/dist/shared/llm/types.d.ts +2 -1
- package/package.json +6 -1
|
@@ -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
|
};
|
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": {
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@ai-sdk/anthropic": "^3.0.58",
|
|
45
|
+
"@ai-sdk/google": "^3.0.51",
|
|
45
46
|
"@ai-sdk/google-vertex": "^4.0.80",
|
|
46
47
|
"@ai-sdk/openai": "^3.0.41"
|
|
47
48
|
},
|
|
@@ -49,6 +50,9 @@
|
|
|
49
50
|
"@ai-sdk/anthropic": {
|
|
50
51
|
"optional": true
|
|
51
52
|
},
|
|
53
|
+
"@ai-sdk/google": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
52
56
|
"@ai-sdk/google-vertex": {
|
|
53
57
|
"optional": true
|
|
54
58
|
},
|
|
@@ -59,6 +63,7 @@
|
|
|
59
63
|
"devDependencies": {
|
|
60
64
|
"@anthropic-ai/claude-agent-sdk": "^0.2.75",
|
|
61
65
|
"@ai-sdk/anthropic": "^3.0.58",
|
|
66
|
+
"@ai-sdk/google": "^3.0.51",
|
|
62
67
|
"@ai-sdk/google-vertex": "^4.0.80",
|
|
63
68
|
"@ai-sdk/openai": "^3.0.41",
|
|
64
69
|
"@types/node": "^25.5.0",
|