@oya-ai/cli 1.0.106 → 1.0.110
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 +18 -0
- package/dist/index.js +69 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -102,6 +102,24 @@ oya personas edit <id> --max 4 --geo US
|
|
|
102
102
|
oya personas rm <id>
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
+
### Moving logins (`oya cookies`)
|
|
106
|
+
|
|
107
|
+
A persona's cookie jar is its logins. Sign in once, then carry the session to wherever it is needed:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Save a persona's logins to a file (owner-readable only: it holds live sessions)
|
|
111
|
+
oya cookies export <persona> --out logins.json
|
|
112
|
+
|
|
113
|
+
# The same, shaped for Playwright's context.addCookies()
|
|
114
|
+
oya cookies export <persona> --format playwright --out pw-cookies.json
|
|
115
|
+
|
|
116
|
+
# Bring logins in from a file: an export, or any JSON list of cookies
|
|
117
|
+
oya cookies import <persona> logins.json
|
|
118
|
+
|
|
119
|
+
# Give one persona another persona's logins (each keeps its own device)
|
|
120
|
+
oya cookies copy <from-persona> <to-persona>
|
|
121
|
+
```
|
|
122
|
+
|
|
105
123
|
### Human-in-the-Loop Takeover
|
|
106
124
|
|
|
107
125
|
When automation encounters hardware 2FA, phone biometric approvals, or complex verification:
|
package/dist/index.js
CHANGED
|
@@ -1270,6 +1270,7 @@ var ARGV_SKIP = 2;
|
|
|
1270
1270
|
var JSON_INDENT2 = 2;
|
|
1271
1271
|
var DEFAULT_BASE_URL = "https://oyabrowser.com";
|
|
1272
1272
|
var CONFIG_FILE_MODE = 384;
|
|
1273
|
+
var PRIVATE_FILE_MODE = 384;
|
|
1273
1274
|
var LsColumns = {
|
|
1274
1275
|
/** Provider name. */
|
|
1275
1276
|
PROVIDER: 14,
|
|
@@ -2009,11 +2010,28 @@ var loginCalls = (http) => ({
|
|
|
2009
2010
|
await http().request("DELETE", `/api/personas/${id}/credentials?domain=${encodeURIComponent(domain)}`);
|
|
2010
2011
|
}
|
|
2011
2012
|
});
|
|
2013
|
+
var jarPath = (id) => `/api/pool/cookies?persona=${encodeURIComponent(id)}`;
|
|
2014
|
+
var jarCalls = (http) => ({
|
|
2015
|
+
/** Every cookie in the jar; `format: 'playwright'` is ready for `context.addCookies()`. */
|
|
2016
|
+
cookies: async (id, format = "json") => (await http().request("GET", `${jarPath(id)}&format=${format}`)).cookies,
|
|
2017
|
+
/** Merge cookies into the jar. The persona's browsers pick them up on their next visit to each site. */
|
|
2018
|
+
importCookies: (id, list2) => http().request("PUT", jarPath(id), { cookies: list2 })
|
|
2019
|
+
});
|
|
2020
|
+
var cookieCalls = (http) => ({
|
|
2021
|
+
...jarCalls(http),
|
|
2022
|
+
/** Copy every login of persona `from` into persona `to`, which keeps its own device. */
|
|
2023
|
+
copyCookies: async (from, to) => jarCalls(http).importCookies(to, await jarCalls(http).cookies(from)),
|
|
2024
|
+
/** Forget every cookie in the jar: signs the persona out everywhere. */
|
|
2025
|
+
clearCookies: async (id) => {
|
|
2026
|
+
await http().request("DELETE", jarPath(id));
|
|
2027
|
+
}
|
|
2028
|
+
});
|
|
2012
2029
|
var personaApi = (http) => ({
|
|
2013
2030
|
...identityCalls(http),
|
|
2014
2031
|
...deviceCalls(http),
|
|
2015
2032
|
...mfaCalls(http),
|
|
2016
|
-
...loginCalls(http)
|
|
2033
|
+
...loginCalls(http),
|
|
2034
|
+
...cookieCalls(http)
|
|
2017
2035
|
});
|
|
2018
2036
|
var configApi = (http) => ({
|
|
2019
2037
|
/** This key's settings. Secrets read back masked. */
|
|
@@ -2389,6 +2407,52 @@ async function cmdPersonas(args2, flags2) {
|
|
|
2389
2407
|
await run2(oya, rest, flags2);
|
|
2390
2408
|
}
|
|
2391
2409
|
|
|
2410
|
+
// src/commands/cookies.ts
|
|
2411
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
2412
|
+
var USAGE = `Usage: oya cookies export <persona> [--format json|playwright] [--out <file>]
|
|
2413
|
+
oya cookies import <persona> <file.json>
|
|
2414
|
+
oya cookies copy <from-persona> <to-persona>
|
|
2415
|
+
oya cookies clear <persona>`;
|
|
2416
|
+
var exportJar = async (oya, rest, flags2) => {
|
|
2417
|
+
if (!rest[0]) throw new Error("Usage: oya cookies export <persona> [--format json|playwright] [--out <file>]");
|
|
2418
|
+
const cookies = await oya.personas.cookies(rest[0], flagStr(flags2, "format") || "json");
|
|
2419
|
+
const file = flagStr(flags2, "out");
|
|
2420
|
+
if (!file) return console.log(JSON.stringify(cookies, null, JSON_INDENT2));
|
|
2421
|
+
writeFileSync5(file, JSON.stringify(cookies, null, JSON_INDENT2) + "\n", { mode: PRIVATE_FILE_MODE });
|
|
2422
|
+
console.log(`\u2705 ${cookies.length} cookie${cookies.length === 1 ? "" : "s"} written to ${file}`);
|
|
2423
|
+
};
|
|
2424
|
+
function cookiesIn(file) {
|
|
2425
|
+
const parsed = JSON.parse(readFileSync4(file, "utf8"));
|
|
2426
|
+
const list2 = Array.isArray(parsed) ? parsed : parsed?.cookies;
|
|
2427
|
+
if (!Array.isArray(list2)) throw new Error(`${file} holds no list of cookies`);
|
|
2428
|
+
return list2;
|
|
2429
|
+
}
|
|
2430
|
+
var importJar = async (oya, rest, flags2) => {
|
|
2431
|
+
if (!rest[0] || !rest[1]) throw new Error("Usage: oya cookies import <persona> <file.json>");
|
|
2432
|
+
const done = await oya.personas.importCookies(rest[0], cookiesIn(rest[1]));
|
|
2433
|
+
out(
|
|
2434
|
+
flags2,
|
|
2435
|
+
done,
|
|
2436
|
+
() => console.log(`\u2705 ${done.imported} imported, ${done.skipped} skipped, ${done.total} in the jar`)
|
|
2437
|
+
);
|
|
2438
|
+
};
|
|
2439
|
+
var copy = async (oya, rest, flags2) => {
|
|
2440
|
+
if (!rest[0] || !rest[1]) throw new Error("Usage: oya cookies copy <from-persona> <to-persona>");
|
|
2441
|
+
const done = await oya.personas.copyCookies(rest[0], rest[1]);
|
|
2442
|
+
out(flags2, done, () => console.log(`\u2705 ${done.imported} copied to ${rest[1]}, ${done.total} in its jar`));
|
|
2443
|
+
};
|
|
2444
|
+
var clear = async (oya, rest) => {
|
|
2445
|
+
if (!rest[0]) throw new Error("Usage: oya cookies clear <persona>");
|
|
2446
|
+
await oya.personas.clearCookies(rest[0]);
|
|
2447
|
+
console.log(`\u2705 cleared ${rest[0]}`);
|
|
2448
|
+
};
|
|
2449
|
+
var SUBCOMMANDS2 = { export: exportJar, import: importJar, copy, clear };
|
|
2450
|
+
async function cmdCookies(args2, flags2) {
|
|
2451
|
+
const [sub, ...rest] = args2;
|
|
2452
|
+
if (sub === void 0 || !Object.hasOwn(SUBCOMMANDS2, sub)) throw new Error(USAGE);
|
|
2453
|
+
await SUBCOMMANDS2[sub](client(flags2), rest, flags2);
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2392
2456
|
// src/commands/settings.ts
|
|
2393
2457
|
function parsePairs(args2) {
|
|
2394
2458
|
const updates = {};
|
|
@@ -2511,6 +2575,9 @@ var HELP = `oya, thousands of browsers, one API
|
|
|
2511
2575
|
oya personas new [name] --platform Win32|MacIntel|Linux --tz <zone> --locale <l> --max <n>
|
|
2512
2576
|
oya personas edit <id> --name <n> --max <n> --geo <cc>
|
|
2513
2577
|
oya personas clone|rm <id> A new device of the same kind \xB7 delete
|
|
2578
|
+
oya cookies export <persona> Logins to stdout or --out <file>; --format playwright for addCookies()
|
|
2579
|
+
oya cookies import <persona> <file> Logins from a JSON file
|
|
2580
|
+
oya cookies copy <from> <to> One persona's logins into another
|
|
2514
2581
|
oya status [--id <id>] Health, counters and what it has been doing
|
|
2515
2582
|
oya open [--id <id>] Open the live view in your browser
|
|
2516
2583
|
oya config [key=value ...] Show or change this key's settings
|
|
@@ -2554,6 +2621,7 @@ var COMMANDS2 = {
|
|
|
2554
2621
|
rm: cmdRm,
|
|
2555
2622
|
stop: cmdRm,
|
|
2556
2623
|
personas: cmdPersonas,
|
|
2624
|
+
cookies: cmdCookies,
|
|
2557
2625
|
open: (_args, flags2) => cmdOpen(flags2),
|
|
2558
2626
|
config: cmdConfig,
|
|
2559
2627
|
usage: (_args, flags2) => cmdUsage(flags2),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oya-ai/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.110",
|
|
4
4
|
"description": "Command line for the Oya browser control plane.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://oyabrowser.com",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@oya-ai/browser": "1.0.
|
|
42
|
+
"@oya-ai/browser": "1.0.110",
|
|
43
43
|
"@types/node": "^20.19.43",
|
|
44
44
|
"tsup": "^8.0.0",
|
|
45
45
|
"typescript": "^5.4.0"
|