@oya-ai/cli 1.0.61 → 1.0.64
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 +33 -13
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -168,12 +168,32 @@ var Browser = class {
|
|
|
168
168
|
return res.text;
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
171
|
-
* Watch it work:
|
|
172
|
-
*
|
|
173
|
-
*
|
|
171
|
+
* Watch it work: the console, opened on this browser.
|
|
172
|
+
*
|
|
173
|
+
* This used to return the raw frame stream with the project's API key in the
|
|
174
|
+
* query string — a permanent credential in browser history, Referer headers
|
|
175
|
+
* and every proxy log on the way, and a URL that renders as a wall of
|
|
176
|
+
* text/event-stream if a person actually opens it. It is the console deep
|
|
177
|
+
* link now, the same one the server hands back from `completeMfa()`, and it
|
|
178
|
+
* carries no credential at all.
|
|
179
|
+
*
|
|
180
|
+
* For the frames themselves, use `liveStreamUrl()`.
|
|
174
181
|
*/
|
|
175
182
|
liveViewUrl() {
|
|
176
|
-
return `${this.http.baseUrl}/
|
|
183
|
+
return `${this.http.baseUrl}/dashboard/?browser=${encodeURIComponent(this.id)}`;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The SSE stream of JPEG frames, for embedding in your own UI. EventSource
|
|
187
|
+
* cannot set headers, so the URL carries a connection ticket: single use,
|
|
188
|
+
* 60 seconds. Mint one per viewer — the first connection spends it.
|
|
189
|
+
*/
|
|
190
|
+
async liveStreamUrl() {
|
|
191
|
+
const { ticket } = await this.http.request(
|
|
192
|
+
"POST",
|
|
193
|
+
`/api/control/sessions/${encodeURIComponent(this.id)}/ticket`,
|
|
194
|
+
{}
|
|
195
|
+
);
|
|
196
|
+
return `${this.http.baseUrl}/api/live/${this.id}?ticket=${encodeURIComponent(ticket)}`;
|
|
177
197
|
}
|
|
178
198
|
/** Counters, health and the last 50 things this browser did. */
|
|
179
199
|
status() {
|
|
@@ -957,7 +977,7 @@ async function preflight(root, a) {
|
|
|
957
977
|
const daemon = await capture("docker", ["info", "--format", "{{.ID}}"]);
|
|
958
978
|
checks.push({ ok: !!daemon, label: "docker daemon reachable", detail: daemon ? "ok" : "not running", fatal: true });
|
|
959
979
|
const compose = await capture("docker", ["compose", "version", "--short"]);
|
|
960
|
-
checks.push({ ok: atLeast(compose, 2, 24), label: "docker compose \u2265 2.24", detail: compose || "not found", fatal:
|
|
980
|
+
checks.push({ ok: atLeast(compose, 2, 24), label: "docker compose \u2265 2.24", detail: compose || "not found", fatal: true });
|
|
961
981
|
}
|
|
962
982
|
if (a.host !== "docker") {
|
|
963
983
|
checks.push({ ok: atLeast(process.versions.node, 22, 13), label: "node \u2265 22.13 (node:sqlite)", detail: process.versions.node, fatal: true });
|
|
@@ -1035,15 +1055,16 @@ function buildEnv(a, secrets, existing) {
|
|
|
1035
1055
|
];
|
|
1036
1056
|
return { values: v, extra, apiKey };
|
|
1037
1057
|
}
|
|
1058
|
+
var PROBE_IMAGE = "alpine@sha256:14358309a308569c32bdc37e2e0e9694be33a9d99e68afb0f5ff33cc1f695dce";
|
|
1038
1059
|
async function priorState() {
|
|
1039
1060
|
const volumes = await capture("docker", ["volume", "ls", "-q", "--filter", "name=oya-data"]) || "";
|
|
1040
1061
|
for (const name of volumes.split("\n").map((v) => v.trim()).filter(Boolean)) {
|
|
1041
|
-
const listing = await capture("docker", ["run", "--rm", "-v", `${name}:/d`,
|
|
1062
|
+
const listing = await capture("docker", ["run", "--rm", "-v", `${name}:/d`, PROBE_IMAGE, "ls", "/d"]);
|
|
1042
1063
|
if (listing === null || /cookies\.json|personas\.json|profiles|\.secret/.test(listing)) return name;
|
|
1043
1064
|
}
|
|
1044
1065
|
return null;
|
|
1045
1066
|
}
|
|
1046
|
-
async function resolveKekConflict(volume) {
|
|
1067
|
+
async function resolveKekConflict(volume, root) {
|
|
1047
1068
|
warn(`${volume} already holds encrypted data from an earlier install.`);
|
|
1048
1069
|
note("Cookies, proxy credentials and TOTP seeds in it were sealed with that");
|
|
1049
1070
|
note("install's OYA_PROFILE_SECRET. A new secret cannot open them, and the");
|
|
@@ -1062,10 +1083,9 @@ async function resolveKekConflict(volume) {
|
|
|
1062
1083
|
if (!await confirm(`Delete ${volume} and everything stored in it?`, false)) {
|
|
1063
1084
|
throw new InputError("Stopped without changing anything.");
|
|
1064
1085
|
}
|
|
1065
|
-
await run("docker", ["compose", "down", "-v"], { cwd:
|
|
1066
|
-
});
|
|
1067
|
-
await run("docker", ["volume", "rm", "-f", volume], { cwd: process.cwd(), quiet: true }).catch(() => {
|
|
1086
|
+
await run("docker", ["compose", "down", "-v"], { cwd: root, quiet: true }).catch(() => {
|
|
1068
1087
|
});
|
|
1088
|
+
await run("docker", ["volume", "rm", "-f", volume], { cwd: root, quiet: true });
|
|
1069
1089
|
success(`removed ${volume}`);
|
|
1070
1090
|
return null;
|
|
1071
1091
|
}
|
|
@@ -1189,7 +1209,7 @@ ${style.bold(" Preflight")}`);
|
|
|
1189
1209
|
if (!existing.OYA_PROFILE_SECRET && answers.host === "docker" && !dryRun) {
|
|
1190
1210
|
const volume = await priorState();
|
|
1191
1211
|
if (volume) {
|
|
1192
|
-
const reused = await resolveKekConflict(volume);
|
|
1212
|
+
const reused = await resolveKekConflict(volume, root);
|
|
1193
1213
|
if (reused) existing.OYA_PROFILE_SECRET = reused;
|
|
1194
1214
|
}
|
|
1195
1215
|
}
|
|
@@ -1572,8 +1592,8 @@ async function cmdPersonas(args2, flags2) {
|
|
|
1572
1592
|
async function cmdOpen(flags2) {
|
|
1573
1593
|
const browser = await targetBrowser(client(flags2), flags2);
|
|
1574
1594
|
const url = browser.liveViewUrl();
|
|
1575
|
-
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
1576
|
-
spawn2(opener,
|
|
1595
|
+
const [opener, args2] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
1596
|
+
spawn2(opener, args2, { detached: true, stdio: "ignore" }).unref();
|
|
1577
1597
|
console.log(`Opening ${browser.id}`);
|
|
1578
1598
|
}
|
|
1579
1599
|
async function cmdConfig(args2, 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.64",
|
|
4
4
|
"description": "Command line for the Oya browser control plane.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://browser.getoya.ai",
|
|
@@ -39,9 +39,10 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@oya-ai/browser": "1.0.
|
|
42
|
+
"@oya-ai/browser": "1.0.64",
|
|
43
43
|
"@types/node": "^20.19.43",
|
|
44
44
|
"tsup": "^8.0.0",
|
|
45
45
|
"typescript": "^5.4.0"
|
|
46
|
-
}
|
|
46
|
+
},
|
|
47
|
+
"author": "mk@getoya.ai"
|
|
47
48
|
}
|