@elmohq/cli 0.4.1 → 0.4.3
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 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -529,6 +529,7 @@ function buildWorkerService(options) {
|
|
|
529
529
|
const CLORO_AFFILIATE = "https://affiliate.cloro.dev/elmo?sid=cli";
|
|
530
530
|
const BRIGHTDATA_AFFILIATE = "https://get.brightdata.com/elmo?sid=cli";
|
|
531
531
|
const OXYLABS_AFFILIATE = "https://oxylabs.go2cloud.org/aff_c?offer_id=7&aff_id=2263&url_id=32";
|
|
532
|
+
const SEARCHAPI_AFFILIATE = "https://www.searchapi.io/?via=elmo";
|
|
532
533
|
const OLOSTEP_AFFILIATE = "https://olostep.com/?ref=elmo";
|
|
533
534
|
const DATAFORSEO_AFFILIATE = "https://dataforseo.com/?aff=184966";
|
|
534
535
|
const BRIGHTDATA_MODELS = [
|
|
@@ -539,6 +540,14 @@ const BRIGHTDATA_MODELS = [
|
|
|
539
540
|
"copilot",
|
|
540
541
|
"gemini"
|
|
541
542
|
];
|
|
543
|
+
const SEARCHAPI_MODELS = [
|
|
544
|
+
"chatgpt",
|
|
545
|
+
"google-ai-mode",
|
|
546
|
+
"google-ai-overview",
|
|
547
|
+
"perplexity",
|
|
548
|
+
"copilot",
|
|
549
|
+
"gemini"
|
|
550
|
+
];
|
|
542
551
|
const OLOSTEP_MODELS = [
|
|
543
552
|
"chatgpt",
|
|
544
553
|
"google-ai-mode",
|
|
@@ -756,6 +765,24 @@ const PROVIDER_PROMPTS = [
|
|
|
756
765
|
}],
|
|
757
766
|
picker: scraperPicker("Oxylabs", "oxylabs", OXYLABS_MODELS)
|
|
758
767
|
},
|
|
768
|
+
{
|
|
769
|
+
id: "searchapi",
|
|
770
|
+
kind: "scraper",
|
|
771
|
+
label: "SearchApi",
|
|
772
|
+
costHint: "flat per-search, every surface — ~$1.20/mo per prompt, $40/mo min",
|
|
773
|
+
confirmDefault: false,
|
|
774
|
+
signup: {
|
|
775
|
+
message: "Sign up and copy your API key",
|
|
776
|
+
url: SEARCHAPI_AFFILIATE
|
|
777
|
+
},
|
|
778
|
+
credentials: [{
|
|
779
|
+
envKey: "SEARCHAPI_API_KEY",
|
|
780
|
+
message: "SearchApi API key",
|
|
781
|
+
secret: true,
|
|
782
|
+
validate: required
|
|
783
|
+
}],
|
|
784
|
+
picker: scraperPicker("SearchApi", "searchapi", SEARCHAPI_MODELS)
|
|
785
|
+
},
|
|
759
786
|
{
|
|
760
787
|
id: "olostep",
|
|
761
788
|
kind: "scraper",
|
|
@@ -1067,6 +1094,20 @@ function validatePort(value) {
|
|
|
1067
1094
|
const port = Number(value);
|
|
1068
1095
|
return Number.isInteger(port) && port >= 1 && port <= 65535 ? void 0 : "Must be an integer between 1 and 65535";
|
|
1069
1096
|
}
|
|
1097
|
+
function toPublicUrl(value) {
|
|
1098
|
+
const withScheme = /^https?:\/\//i.test(value) ? value : `https://${value}`;
|
|
1099
|
+
try {
|
|
1100
|
+
return new URL(withScheme);
|
|
1101
|
+
} catch {
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
function validatePublicUrl(value) {
|
|
1106
|
+
if (!value) return "Required";
|
|
1107
|
+
const url = toPublicUrl(value.trim());
|
|
1108
|
+
if (!url?.hostname.includes(".")) return "Enter a domain, e.g. elmo.example.com";
|
|
1109
|
+
if (url.pathname !== "/") return "Must not include a path";
|
|
1110
|
+
}
|
|
1070
1111
|
async function configureProvidersInteractive(env) {
|
|
1071
1112
|
p.note([
|
|
1072
1113
|
"Elmo needs two kinds of providers:",
|
|
@@ -1075,6 +1116,7 @@ async function configureProvidersInteractive(env) {
|
|
|
1075
1116
|
` • ${pc.cyan("Cloro")} — most reliable, every surface, ~$0.65/mo per prompt ($30/mo min)`,
|
|
1076
1117
|
` • ${pc.cyan("BrightData")} — pay-as-you-go and cheaper, but slower, ~$0.45/mo per prompt`,
|
|
1077
1118
|
` • ${pc.cyan("Oxylabs")} — cheapest per run, no Gemini/Copilot, $49/mo min`,
|
|
1119
|
+
` • ${pc.cyan("SearchApi")} — flat per-search, every surface, ~$1.20/mo per prompt ($40/mo min)`,
|
|
1078
1120
|
` • ${pc.cyan("Olostep")} — premium, built for high volume, ~$2.25/mo per prompt`,
|
|
1079
1121
|
` • ${pc.cyan("DataForSEO")} — pay-as-you-go, scrapers + direct APIs, ~$1.20/mo per prompt`,
|
|
1080
1122
|
"",
|
|
@@ -1118,6 +1160,10 @@ async function configureProvidersRecommended(env) {
|
|
|
1118
1160
|
value: "oxylabs",
|
|
1119
1161
|
label: "Oxylabs — cheapest per run, no Gemini/Copilot ($49/mo min)"
|
|
1120
1162
|
},
|
|
1163
|
+
{
|
|
1164
|
+
value: "searchapi",
|
|
1165
|
+
label: "SearchApi — flat per-search, every surface (~$1.20/mo per prompt, $40/mo min)"
|
|
1166
|
+
},
|
|
1121
1167
|
{
|
|
1122
1168
|
value: "olostep",
|
|
1123
1169
|
label: "Olostep — premium, built for high volume (~$2.25/mo per prompt)"
|
|
@@ -1282,15 +1328,37 @@ async function runInit(options, version) {
|
|
|
1282
1328
|
placeholder: "you@example.com"
|
|
1283
1329
|
});
|
|
1284
1330
|
const email = p.isCancel(updatesEmail) ? void 0 : updatesEmail || void 0;
|
|
1331
|
+
const access = await p.select({
|
|
1332
|
+
message: "How will you access Elmo?",
|
|
1333
|
+
options: [{
|
|
1334
|
+
value: "local",
|
|
1335
|
+
label: "On this machine (localhost)"
|
|
1336
|
+
}, {
|
|
1337
|
+
value: "public",
|
|
1338
|
+
label: "From a domain (e.g. behind a reverse proxy)"
|
|
1339
|
+
}],
|
|
1340
|
+
initialValue: "local"
|
|
1341
|
+
});
|
|
1342
|
+
assertNotCancelled(access);
|
|
1343
|
+
let publicUrl;
|
|
1344
|
+
if (access === "public") {
|
|
1345
|
+
const domain = await p.text({
|
|
1346
|
+
message: "Domain",
|
|
1347
|
+
placeholder: "elmo.example.com",
|
|
1348
|
+
validate: validatePublicUrl
|
|
1349
|
+
});
|
|
1350
|
+
assertNotCancelled(domain);
|
|
1351
|
+
publicUrl = toPublicUrl(domain.trim());
|
|
1352
|
+
}
|
|
1285
1353
|
const portInput = await p.text({
|
|
1286
|
-
message: "Web app port",
|
|
1354
|
+
message: access === "public" ? "Port for your reverse proxy to forward to" : "Web app port",
|
|
1287
1355
|
placeholder: String(DEFAULT_APP_PORT),
|
|
1288
1356
|
defaultValue: String(DEFAULT_APP_PORT),
|
|
1289
1357
|
validate: validatePort
|
|
1290
1358
|
});
|
|
1291
1359
|
assertNotCancelled(portInput);
|
|
1292
1360
|
const port = Number(portInput);
|
|
1293
|
-
env.APP_URL = `http://localhost:${port}`;
|
|
1361
|
+
env.APP_URL = publicUrl?.origin ?? `http://localhost:${port}`;
|
|
1294
1362
|
env.VITE_APP_URL = env.APP_URL;
|
|
1295
1363
|
const composeYaml = buildComposeYaml({
|
|
1296
1364
|
dev: Boolean(options.dev),
|
|
@@ -1326,7 +1394,7 @@ async function runInit(options, version) {
|
|
|
1326
1394
|
postgres_mode: postgresMode,
|
|
1327
1395
|
dev_mode: Boolean(options.dev),
|
|
1328
1396
|
setup_mode: setupMode,
|
|
1329
|
-
has_scraper: Boolean(env.BRIGHTDATA_API_TOKEN || env.OLOSTEP_API_KEY || env.OXYLABS_USERNAME || env.CLORO_API_KEY),
|
|
1397
|
+
has_scraper: Boolean(env.BRIGHTDATA_API_TOKEN || env.SEARCHAPI_API_KEY || env.OLOSTEP_API_KEY || env.OXYLABS_USERNAME || env.CLORO_API_KEY),
|
|
1330
1398
|
has_direct_api: hasDirectApiConfigured(env)
|
|
1331
1399
|
});
|
|
1332
1400
|
if (email) await submitNewsletterSignup(configDir, email);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elmohq/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"marketing",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^26.4.1",
|
|
40
40
|
"@types/semver": "^7.8.0",
|
|
41
|
-
"@workspace/config": "0.4.
|
|
41
|
+
"@workspace/config": "0.4.3",
|
|
42
42
|
"rolldown": "^1.2.7",
|
|
43
43
|
"typescript": "^7.0.2",
|
|
44
44
|
"vitest": "^4.1.11"
|