@onkernel/cua-cli 0.1.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 +170 -0
- package/dist/cli.js +1758 -0
- package/dist/harness-models-GT8Ke1vt.js +106 -0
- package/dist/main-Bphx_zOj.js +899 -0
- package/package.json +48 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { formatCuaModelRef, getCuaModel, isCuaProvider, listCuaModels, parseCuaModelRef } from "@onkernel/cua-ai";
|
|
2
|
+
import Kernel, { NotFoundError } from "@onkernel/sdk";
|
|
3
|
+
//#region src/harness-browser.ts
|
|
4
|
+
const CUID2_LENGTH = 24;
|
|
5
|
+
const CUID2_PATTERN = /^[a-z][a-z0-9]{23}$/;
|
|
6
|
+
function looksLikeProfileId(selector) {
|
|
7
|
+
const trimmed = selector.trim();
|
|
8
|
+
return trimmed.length === CUID2_LENGTH && CUID2_PATTERN.test(trimmed);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a `--profile <name|id>` selector to a concrete profile id.
|
|
12
|
+
* Looks up by id first; if the API reports not-found and the selector does
|
|
13
|
+
* not look like a CUID2 id, the profile is created with that name.
|
|
14
|
+
*/
|
|
15
|
+
async function resolveProfileId(client, selector) {
|
|
16
|
+
const trimmed = selector.trim();
|
|
17
|
+
if (!trimmed) throw new Error("profile selector is empty");
|
|
18
|
+
try {
|
|
19
|
+
return (await client.profiles.retrieve(trimmed)).id;
|
|
20
|
+
} catch (err) {
|
|
21
|
+
if (!(err instanceof NotFoundError)) throw new Error(`looking up browser profile "${trimmed}": ${err.message}`, { cause: err });
|
|
22
|
+
if (looksLikeProfileId(trimmed)) throw new Error(`browser profile "${trimmed}" was not found`);
|
|
23
|
+
return (await client.profiles.create({ name: trimmed })).id;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Create a Kernel SDK client with the supplied auth. */
|
|
27
|
+
function createKernelClient(apiKey, baseUrl) {
|
|
28
|
+
return new Kernel({
|
|
29
|
+
apiKey,
|
|
30
|
+
...baseUrl ? { baseURL: baseUrl } : {}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/** Provision a fresh Kernel cloud browser session and return a handle. */
|
|
34
|
+
async function provisionBrowser(opts) {
|
|
35
|
+
const client = createKernelClient(opts.apiKey, opts.baseUrl);
|
|
36
|
+
const timeoutSeconds = opts.timeoutSeconds && opts.timeoutSeconds > 0 ? opts.timeoutSeconds : 300;
|
|
37
|
+
let profileId = (opts.profileId ?? "").trim();
|
|
38
|
+
if (!profileId && opts.profileSelector && opts.profileSelector.trim()) profileId = await resolveProfileId(client, opts.profileSelector);
|
|
39
|
+
const params = {
|
|
40
|
+
stealth: true,
|
|
41
|
+
timeout_seconds: timeoutSeconds
|
|
42
|
+
};
|
|
43
|
+
if (profileId) params.profile = {
|
|
44
|
+
id: profileId,
|
|
45
|
+
save_changes: opts.saveChanges ?? false
|
|
46
|
+
};
|
|
47
|
+
const browser = await client.browsers.create(params);
|
|
48
|
+
return {
|
|
49
|
+
client,
|
|
50
|
+
browser,
|
|
51
|
+
profileId: profileId || void 0,
|
|
52
|
+
async close() {
|
|
53
|
+
await client.browsers.deleteByID(browser.session_id);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Capture a screenshot through the SDK. Falls back to undefined when the
|
|
59
|
+
* call fails — first-prompt images are best-effort.
|
|
60
|
+
*/
|
|
61
|
+
async function captureScreenshot(client, sessionId) {
|
|
62
|
+
try {
|
|
63
|
+
const arrayBuffer = await (await client.browsers.computer.captureScreenshot(sessionId)).arrayBuffer();
|
|
64
|
+
return Buffer.from(arrayBuffer);
|
|
65
|
+
} catch {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/harness-models.ts
|
|
71
|
+
/** Default model used by the new harness wiring. */
|
|
72
|
+
const DEFAULT_CUA_MODEL_REF = "openai:gpt-5.5";
|
|
73
|
+
/**
|
|
74
|
+
* Resolve a model ref from CLI input. Accepts either a provider-qualified
|
|
75
|
+
* `provider:model` ref or a bare model id when it matches exactly one
|
|
76
|
+
* catalog entry. Throws when bare ids are ambiguous or unknown.
|
|
77
|
+
*/
|
|
78
|
+
function resolveCuaModelRef(input) {
|
|
79
|
+
if (!input || !input.trim()) return DEFAULT_CUA_MODEL_REF;
|
|
80
|
+
const value = input.trim();
|
|
81
|
+
if (value.includes(":")) {
|
|
82
|
+
const { provider, model } = parseCuaModelRef(value);
|
|
83
|
+
const ref = formatCuaModelRef(provider, model);
|
|
84
|
+
getCuaModel(ref);
|
|
85
|
+
return ref;
|
|
86
|
+
}
|
|
87
|
+
const matches = listCuaModels().filter((m) => m.model === value);
|
|
88
|
+
if (matches.length === 0) throw new Error(`unknown model "${value}" (run \`cua models\` to list supported -m/--model values)`);
|
|
89
|
+
if (matches.length > 1) {
|
|
90
|
+
const refs = matches.map((m) => m.ref).join(", ");
|
|
91
|
+
throw new Error(`ambiguous model "${value}" (matches: ${refs}); pass a provider-qualified ref like "openai:${value}"`);
|
|
92
|
+
}
|
|
93
|
+
return matches[0].ref;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* List supported models, optionally filtered to a provider. Accepts either
|
|
97
|
+
* the canonical `"google"` or the CLI-friendly `"gemini"` alias.
|
|
98
|
+
*/
|
|
99
|
+
function listSupportedModels(provider) {
|
|
100
|
+
if (!provider) return listCuaModels();
|
|
101
|
+
const normalized = provider === "gemini" ? "google" : provider;
|
|
102
|
+
if (!isCuaProvider(normalized)) throw new Error(`unknown provider "${provider}"`);
|
|
103
|
+
return listCuaModels(normalized);
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { createKernelClient as a, captureScreenshot as i, listSupportedModels as n, provisionBrowser as o, resolveCuaModelRef as r, resolveProfileId as s, DEFAULT_CUA_MODEL_REF as t };
|