@oya-ai/cli 1.0.144 → 1.0.145
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 +71 -20
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -35,7 +35,8 @@ var SWITCHES = /* @__PURE__ */ new Set([
|
|
|
35
35
|
"live",
|
|
36
36
|
"preview",
|
|
37
37
|
"replace",
|
|
38
|
-
"version"
|
|
38
|
+
"version",
|
|
39
|
+
"yes"
|
|
39
40
|
]);
|
|
40
41
|
var VALUE_FLAGS = {
|
|
41
42
|
after: "--after 120",
|
|
@@ -568,12 +569,13 @@ function findRepoRoot(from = process.cwd()) {
|
|
|
568
569
|
}
|
|
569
570
|
return null;
|
|
570
571
|
}
|
|
572
|
+
var DEFAULT_CLONE = () => join(process.cwd(), "oya-browser");
|
|
571
573
|
var REPO_URL = "https://github.com/OyadotAI/oya-browser.git";
|
|
572
|
-
async function locateRepo(dryRun = false) {
|
|
574
|
+
async function locateRepo(dryRun = false, yes = false) {
|
|
573
575
|
const found = findRepoRoot();
|
|
574
576
|
if (found) return found;
|
|
575
577
|
console.log("\nThis does not look like an oya-browser checkout.");
|
|
576
|
-
const where = await ask("Clone it to:",
|
|
578
|
+
const where = yes ? DEFAULT_CLONE() : await ask("Clone it to:", DEFAULT_CLONE());
|
|
577
579
|
if (dryRun) return wouldClone(where);
|
|
578
580
|
if (existsSync(where)) throw new Error(`${where} already exists`);
|
|
579
581
|
await run("git", ["clone", "--depth", "1", REPO_URL, where], { cwd: process.cwd() });
|
|
@@ -1304,17 +1306,56 @@ function printDone(publicUrl, apiKey) {
|
|
|
1304
1306
|
console.log(` oya login --url ${publicUrl} --key ${apiKey}`);
|
|
1305
1307
|
console.log(` oya ls && oya goto https://example.com
|
|
1306
1308
|
`);
|
|
1309
|
+
console.log(`OYA_BASE_URL=${publicUrl}`);
|
|
1310
|
+
console.log(`OYA_API_KEY=${apiKey}`);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
// src/install/defaults.ts
|
|
1314
|
+
var NO_LLM = { provider: "skip", baseUrl: "", model: "" };
|
|
1315
|
+
function openaiFromEnv(env2) {
|
|
1316
|
+
const { base, model } = LLM_PRESETS.openai;
|
|
1317
|
+
const llm = { provider: "openai", baseUrl: env2.OPENAI_BASE_URL || base, model: env2.CHAT_MODEL || model };
|
|
1318
|
+
return { llm, secrets: { OPENAI_API_KEY: env2.OPENAI_API_KEY || "" } };
|
|
1319
|
+
}
|
|
1320
|
+
function llmFromEnv(env2) {
|
|
1321
|
+
if (env2.OPENAI_API_KEY) return openaiFromEnv(env2);
|
|
1322
|
+
if (!env2.ANTHROPIC_API_KEY) return { llm: NO_LLM, secrets: {} };
|
|
1323
|
+
const { base, model } = LLM_PRESETS.anthropic;
|
|
1324
|
+
return { llm: { provider: "anthropic", baseUrl: base, model }, secrets: { OPENAI_API_KEY: env2.ANTHROPIC_API_KEY } };
|
|
1325
|
+
}
|
|
1326
|
+
var LOCAL = {
|
|
1327
|
+
version: 1,
|
|
1328
|
+
host: "docker",
|
|
1329
|
+
database: "sqlite",
|
|
1330
|
+
fleet: "docker-workers",
|
|
1331
|
+
workers: 1,
|
|
1332
|
+
publicUrl: `http://localhost:${DEFAULT_PORT}`,
|
|
1333
|
+
optional: { captcha: "", recordingBucket: "", metrics: false }
|
|
1334
|
+
};
|
|
1335
|
+
function defaultInstall(env2 = process.env) {
|
|
1336
|
+
const { llm, secrets } = llmFromEnv(env2);
|
|
1337
|
+
return { answers: { ...LOCAL, optional: { ...LOCAL.optional }, llm }, secrets };
|
|
1307
1338
|
}
|
|
1308
1339
|
|
|
1309
1340
|
// src/install.ts
|
|
1310
1341
|
var ANSWERS_FILE = "oya-install.json";
|
|
1311
|
-
|
|
1312
|
-
const
|
|
1313
|
-
|
|
1342
|
+
function presetFor(m) {
|
|
1343
|
+
const saved = m.configPath ? readJsonFile(m.configPath) : {};
|
|
1344
|
+
return m.yes ? { ...defaultInstall().answers, ...saved } : saved;
|
|
1345
|
+
}
|
|
1346
|
+
function announce(root, m, replay) {
|
|
1314
1347
|
banner("Oya Browser, self-host install", root);
|
|
1315
|
-
if (
|
|
1316
|
-
|
|
1317
|
-
|
|
1348
|
+
if (m.configPath) note(`replaying ${m.configPath}`);
|
|
1349
|
+
if (m.yes) note("--yes: SQLite, Docker on this machine, no questions");
|
|
1350
|
+
steps(replay ? 0 : INTERVIEW_STEPS);
|
|
1351
|
+
}
|
|
1352
|
+
async function gather(m) {
|
|
1353
|
+
const root = await locateRepo(m.dryRun, m.yes);
|
|
1354
|
+
const replay = !!m.configPath || m.yes;
|
|
1355
|
+
announce(root, m, replay);
|
|
1356
|
+
const result = await interview(presetFor(m), replay);
|
|
1357
|
+
if (m.yes) result.secrets = { ...defaultInstall().secrets, ...result.secrets };
|
|
1358
|
+
return { root, ...result };
|
|
1318
1359
|
}
|
|
1319
1360
|
async function checkMachine(root, answers, dryRun) {
|
|
1320
1361
|
const checks = await preflight(root, answers);
|
|
@@ -1329,21 +1370,28 @@ function warnLocalDatabase(answers, databaseUrl = "") {
|
|
|
1329
1370
|
warn("DATABASE_URL points at localhost, which inside a container means the container itself.");
|
|
1330
1371
|
note("Use host.docker.internal (macOS, Windows) or the host IP so the server can reach it.");
|
|
1331
1372
|
}
|
|
1332
|
-
|
|
1333
|
-
if (
|
|
1373
|
+
function unattendedKek(volume) {
|
|
1374
|
+
if (process.env.OYA_PROFILE_SECRET) return process.env.OYA_PROFILE_SECRET;
|
|
1375
|
+
throw new Error(
|
|
1376
|
+
`${volume} holds encrypted data from an earlier install, and there is no .env with its OYA_PROFILE_SECRET.
|
|
1377
|
+
Re-run with OYA_PROFILE_SECRET=<the old secret> set, or without --yes to choose what to do.`
|
|
1378
|
+
);
|
|
1379
|
+
}
|
|
1380
|
+
async function guardKek(existing, answers, root, m) {
|
|
1381
|
+
if (existing.OYA_PROFILE_SECRET || answers.host !== "docker" || m.dryRun) return;
|
|
1334
1382
|
const volume = await priorState();
|
|
1335
1383
|
if (!volume) return;
|
|
1336
|
-
const reused = await resolveKekConflict(volume, root);
|
|
1384
|
+
const reused = m.yes ? unattendedKek(volume) : await resolveKekConflict(volume, root);
|
|
1337
1385
|
if (reused) existing.OYA_PROFILE_SECRET = reused;
|
|
1338
1386
|
}
|
|
1339
|
-
async function plan(
|
|
1340
|
-
const interviewed = await gather(
|
|
1387
|
+
async function plan(m) {
|
|
1388
|
+
const interviewed = await gather(m);
|
|
1341
1389
|
const { root, answers, secrets } = interviewed;
|
|
1342
|
-
await checkMachine(root, answers, dryRun);
|
|
1390
|
+
await checkMachine(root, answers, m.dryRun);
|
|
1343
1391
|
warnLocalDatabase(answers, secrets.DATABASE_URL);
|
|
1344
1392
|
const envPath = join5(root, ".env");
|
|
1345
1393
|
const existing = readEnv(envPath);
|
|
1346
|
-
await guardKek(existing, answers, root,
|
|
1394
|
+
await guardKek(existing, answers, root, m);
|
|
1347
1395
|
return { ...interviewed, envPath, existing, env: buildEnv(answers, secrets, existing) };
|
|
1348
1396
|
}
|
|
1349
1397
|
function writeFiles(p) {
|
|
@@ -1370,10 +1418,11 @@ async function apply2(p) {
|
|
|
1370
1418
|
printDone(p.answers.publicUrl, p.env.apiKey);
|
|
1371
1419
|
}
|
|
1372
1420
|
async function cmdInstall(flags) {
|
|
1373
|
-
const
|
|
1374
|
-
const
|
|
1421
|
+
const configPath2 = typeof flags.config === "string" ? flags.config : null;
|
|
1422
|
+
const m = { configPath: configPath2, yes: flags.yes === true, dryRun: flags["dry-run"] === true };
|
|
1423
|
+
const p = await plan(m);
|
|
1375
1424
|
printPlan(p.answers, p.envPath);
|
|
1376
|
-
if (dryRun) return printDryRun(p.env.values);
|
|
1425
|
+
if (m.dryRun) return printDryRun(p.env.values);
|
|
1377
1426
|
await apply2(p);
|
|
1378
1427
|
}
|
|
1379
1428
|
|
|
@@ -3056,7 +3105,9 @@ var HELP = `oya, thousands of browsers, one API
|
|
|
3056
3105
|
Usage: oya <command> [arguments] [options]
|
|
3057
3106
|
|
|
3058
3107
|
Set up
|
|
3059
|
-
oya install [--dry-run] [--config <file>]
|
|
3108
|
+
oya install [--yes] [--dry-run] [--config <file>]
|
|
3109
|
+
Stand up a self-hosted control plane;
|
|
3110
|
+
--yes: SQLite + Docker here, no questions
|
|
3060
3111
|
oya login [--key <key>] [--url <url>] Save an API key for this machine
|
|
3061
3112
|
oya init Set your model, browser provider and sign-ins
|
|
3062
3113
|
oya whoami Which control plane and key are in use, and from where
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oya-ai/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.145",
|
|
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.145",
|
|
54
54
|
"@types/node": "^20.19.43",
|
|
55
55
|
"tsup": "^8.0.0",
|
|
56
56
|
"typescript": "^5.4.0"
|