@oya-ai/cli 1.0.129 → 1.0.131
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/index.js +70 -13
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1931,9 +1931,8 @@ var Browser = class {
|
|
|
1931
1931
|
/**
|
|
1932
1932
|
* Replay a playbook with no LLM in the loop. Variables left out reuse the
|
|
1933
1933
|
* recorded values where there are any. If a step no longer fits the page and
|
|
1934
|
-
* `autoHeal` is on (the default), the agent finishes the task and its fix
|
|
1935
|
-
*
|
|
1936
|
-
* Play `'<name>:draft'` to try a draft before promoting it.
|
|
1934
|
+
* `autoHeal` is on (the default), the agent finishes the task and its fix
|
|
1935
|
+
* replaces the broken steps in the playbook (`healed`); off, the step's error is thrown.
|
|
1937
1936
|
*/
|
|
1938
1937
|
async play(name, data = {}, { autoHeal = true } = {}) {
|
|
1939
1938
|
const path = `/api/browsers/${this.id}/playbooks/${segment(name, "name")}/play`;
|
|
@@ -2153,7 +2152,24 @@ var playbookApi = (http) => ({
|
|
|
2153
2152
|
await http().request("DELETE", playbook(name));
|
|
2154
2153
|
},
|
|
2155
2154
|
/** Replace a playbook with the draft a healed replay saved. Try it first with `browser.play('<name>:draft')`. */
|
|
2156
|
-
promote: async (name) => http().request("POST", `${playbook(name)}/promote`, {})
|
|
2155
|
+
promote: async (name) => http().request("POST", `${playbook(name)}/promote`, {}),
|
|
2156
|
+
...transferApi(http)
|
|
2157
|
+
});
|
|
2158
|
+
var transferApi = (http) => ({
|
|
2159
|
+
/** The playbook as one JSON document, to move it to another environment with `import()`. Secrets travel by name only. */
|
|
2160
|
+
export: async (name) => http().request("GET", `${playbook(name)}/export`),
|
|
2161
|
+
/**
|
|
2162
|
+
* Save an exported playbook here, as `name` or the name it was exported with. A name
|
|
2163
|
+
* already taken is refused unless `overwrite` is true.
|
|
2164
|
+
*/
|
|
2165
|
+
import: async (doc, options = {}) => http().request("POST", "/api/playbooks/import", { playbook: doc, ...options })
|
|
2166
|
+
});
|
|
2167
|
+
var llmApi = (http) => ({
|
|
2168
|
+
/**
|
|
2169
|
+
* The text for one free-text field, written by this key's model: what an exported
|
|
2170
|
+
* playbook calls as `oya.llm.answer(question, vars)` for a comment or a question's answer.
|
|
2171
|
+
*/
|
|
2172
|
+
answer: async (question, values = {}, task) => (await http().request("POST", "/api/playbooks/answer", { question, values, task })).answer
|
|
2157
2173
|
});
|
|
2158
2174
|
var proxyApi = (http) => ({
|
|
2159
2175
|
/** Every proxy this key can use, shared ones included. */
|
|
@@ -2226,7 +2242,7 @@ var jarCalls = (http) => ({
|
|
|
2226
2242
|
/** Every cookie in the jar; `format: 'playwright'` is ready for `context.addCookies()`. */
|
|
2227
2243
|
cookies: async (id, format = "json") => (await http().request("GET", `${jarPath(id)}&format=${encodeURIComponent(format)}`)).cookies,
|
|
2228
2244
|
/** Merge cookies into the jar. The persona's browsers pick them up on their next visit to each site. */
|
|
2229
|
-
importCookies: async (id,
|
|
2245
|
+
importCookies: async (id, list3) => http().request("PUT", jarPath(id), { cookies: list3 })
|
|
2230
2246
|
});
|
|
2231
2247
|
var cookieCalls = (http) => ({
|
|
2232
2248
|
...jarCalls(http),
|
|
@@ -2319,10 +2335,10 @@ function openLink(link) {
|
|
|
2319
2335
|
});
|
|
2320
2336
|
child.unref();
|
|
2321
2337
|
}
|
|
2322
|
-
async function waitForDesktop(
|
|
2338
|
+
async function waitForDesktop(list3, link, timeoutMs, persona) {
|
|
2323
2339
|
const deadline = Date.now() + timeoutMs;
|
|
2324
2340
|
while (Date.now() < deadline) {
|
|
2325
|
-
const found = desktopOf(await
|
|
2341
|
+
const found = desktopOf(await list3(), persona);
|
|
2326
2342
|
if (found) return found;
|
|
2327
2343
|
await new Promise((r) => setTimeout(r, READY_POLL_MS2));
|
|
2328
2344
|
}
|
|
@@ -2334,7 +2350,7 @@ async function handleOn(http, id) {
|
|
|
2334
2350
|
const started = { id, provider: DESKTOP_PROVIDER, persona: found.persona || "default", cdpUrl: found.cdpUrl };
|
|
2335
2351
|
return new Browser(http, { ...started, status: "ready", reused: true }, false);
|
|
2336
2352
|
}
|
|
2337
|
-
var desktopApi = (http,
|
|
2353
|
+
var desktopApi = (http, list3) => ({
|
|
2338
2354
|
/**
|
|
2339
2355
|
* The person's own desktop browser, signed in to their sites. When it is not
|
|
2340
2356
|
* connected yet this pairs it: it opens a link, the person clicks Connect in
|
|
@@ -2343,11 +2359,11 @@ var desktopApi = (http, list2) => ({
|
|
|
2343
2359
|
* another persona is switched the same way: the link reconnects it as this one.
|
|
2344
2360
|
*/
|
|
2345
2361
|
connect: async (options = {}) => {
|
|
2346
|
-
const running = desktopOf(await
|
|
2362
|
+
const running = desktopOf(await list3(), options.persona);
|
|
2347
2363
|
if (running) return handleOn(http(), running.id);
|
|
2348
2364
|
const link = await pairingLink(http(), options.persona);
|
|
2349
2365
|
if (options.open !== false) openLink(link);
|
|
2350
|
-
const found = await waitForDesktop(
|
|
2366
|
+
const found = await waitForDesktop(list3, link, options.timeoutMs ?? DESKTOP_TIMEOUT_MS, options.persona);
|
|
2351
2367
|
return handleOn(http(), found.id);
|
|
2352
2368
|
}
|
|
2353
2369
|
});
|
|
@@ -2380,6 +2396,8 @@ var Oya = class {
|
|
|
2380
2396
|
control = controlApi(() => this.http);
|
|
2381
2397
|
/** Playbooks saved with `browser.toPlaybook()`. */
|
|
2382
2398
|
playbooks = playbookApi(() => this.http);
|
|
2399
|
+
/** This key's model for one-off text: `oya.llm.answer(question, vars)` fills a playbook's free-text field. */
|
|
2400
|
+
llm = llmApi(() => this.http);
|
|
2383
2401
|
/**
|
|
2384
2402
|
* Proxy exits for your personas. A persona takes one at first connect (by its
|
|
2385
2403
|
* geo hint) or by `personas.pinProxy`, and keeps it.
|
|
@@ -2841,9 +2859,9 @@ var exportJar = async (oya, rest, flags) => {
|
|
|
2841
2859
|
};
|
|
2842
2860
|
function cookiesIn(file) {
|
|
2843
2861
|
const parsed = readJsonFile(file);
|
|
2844
|
-
const
|
|
2845
|
-
if (!Array.isArray(
|
|
2846
|
-
return
|
|
2862
|
+
const list3 = Array.isArray(parsed) ? parsed : parsed?.cookies;
|
|
2863
|
+
if (!Array.isArray(list3)) throw usage(`${file} holds no list of cookies.`);
|
|
2864
|
+
return list3;
|
|
2847
2865
|
}
|
|
2848
2866
|
var importJar = async (oya, rest, flags) => {
|
|
2849
2867
|
if (!rest[0] || !rest[1])
|
|
@@ -2873,6 +2891,39 @@ async function cmdCookies(args, flags) {
|
|
|
2873
2891
|
await SUBCOMMANDS2[sub](client(flags), rest, flags);
|
|
2874
2892
|
}
|
|
2875
2893
|
|
|
2894
|
+
// src/commands/playbooks.ts
|
|
2895
|
+
import { writeFileSync as writeFileSync6 } from "fs";
|
|
2896
|
+
var list2 = async (oya, _rest, flags) => {
|
|
2897
|
+
const playbooks = await oya.playbooks.list();
|
|
2898
|
+
out(flags, playbooks, () => {
|
|
2899
|
+
if (!playbooks.length) return console.log("No playbooks yet: save a run with browser.toPlaybook().");
|
|
2900
|
+
for (const p of playbooks) console.log(`${p.name} ${p.steps} steps ${p.variables.join(", ") || "(no inputs)"}`);
|
|
2901
|
+
});
|
|
2902
|
+
};
|
|
2903
|
+
var exportOne = async (oya, rest, flags) => {
|
|
2904
|
+
if (!rest[0]) throw usage("oya playbooks export needs a name: oya playbooks export <name> [--out <file>].");
|
|
2905
|
+
const doc = await oya.playbooks.export(rest[0]);
|
|
2906
|
+
const file = flagStr(flags, "out");
|
|
2907
|
+
if (!file) return console.log(JSON.stringify(doc, null, JSON_INDENT2));
|
|
2908
|
+
writeFileSync6(file, JSON.stringify(doc, null, JSON_INDENT2) + "\n");
|
|
2909
|
+
out(flags, { ok: true, name: rest[0], file }, () => console.log(`\u2705 ${rest[0]} written to ${file}`));
|
|
2910
|
+
};
|
|
2911
|
+
var importOne = async (oya, rest, flags) => {
|
|
2912
|
+
if (!rest[0])
|
|
2913
|
+
throw usage("oya playbooks import needs a file: oya playbooks import <file> [--name <name>] [--replace].");
|
|
2914
|
+
const doc = readJsonFile(rest[0]);
|
|
2915
|
+
const name = flagStr(flags, "name") || void 0;
|
|
2916
|
+
const saved = await oya.playbooks.import(doc, { name, overwrite: flags.replace === true });
|
|
2917
|
+
out(flags, saved, () => console.log(`\u2705 imported ${saved.name}: ${saved.steps} steps`));
|
|
2918
|
+
};
|
|
2919
|
+
var SUBCOMMANDS3 = { list: list2, export: exportOne, import: importOne };
|
|
2920
|
+
async function cmdPlaybooks(args, flags) {
|
|
2921
|
+
const [sub = "list", ...rest] = args;
|
|
2922
|
+
if (!Object.hasOwn(SUBCOMMANDS3, sub))
|
|
2923
|
+
throw usage(`Unknown playbooks subcommand "${sub}". Use list, export or import.`);
|
|
2924
|
+
await SUBCOMMANDS3[sub](client(flags), rest, flags);
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2876
2927
|
// src/commands/settings.ts
|
|
2877
2928
|
function parsePairs(args) {
|
|
2878
2929
|
const updates = {};
|
|
@@ -3034,6 +3085,11 @@ Personas and cookies
|
|
|
3034
3085
|
oya cookies copy <from> <to> One persona's logins into another
|
|
3035
3086
|
oya cookies clear <persona> Delete a persona's logins
|
|
3036
3087
|
|
|
3088
|
+
Playbooks
|
|
3089
|
+
oya playbooks List saved playbooks
|
|
3090
|
+
oya playbooks export <name> One playbook as JSON; [--out <file>]
|
|
3091
|
+
oya playbooks import <file> Save an export here; [--name <name>] [--replace]
|
|
3092
|
+
|
|
3037
3093
|
Account
|
|
3038
3094
|
oya config [key=value ...] Show or change this key's settings
|
|
3039
3095
|
oya usage What this key has spent
|
|
@@ -3105,6 +3161,7 @@ var COMMANDS = {
|
|
|
3105
3161
|
stop: cmdRm,
|
|
3106
3162
|
personas: cmdPersonas,
|
|
3107
3163
|
cookies: cmdCookies,
|
|
3164
|
+
playbooks: cmdPlaybooks,
|
|
3108
3165
|
open: (_args, flags) => cmdOpen(flags),
|
|
3109
3166
|
config: cmdConfig,
|
|
3110
3167
|
usage: (_args, flags) => cmdUsage(flags),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oya-ai/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.131",
|
|
4
4
|
"description": "Command line for the Oya browser control plane.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://oyabrowser.com",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@oya-ai/browser": "1.0.
|
|
53
|
+
"@oya-ai/browser": "1.0.131",
|
|
54
54
|
"@types/node": "^20.19.43",
|
|
55
55
|
"tsup": "^8.0.0",
|
|
56
56
|
"typescript": "^5.4.0"
|