@elmohq/cli 0.6.1 → 0.7.0

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.
Files changed (2) hide show
  1. package/dist/index.js +47 -1
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -525,6 +525,33 @@ function buildWorkerService(options) {
525
525
  return lines.join("\n");
526
526
  }
527
527
  //#endregion
528
+ //#region src/judge.ts
529
+ const SIGNUP_URL = "https://console.typesafe.ai";
530
+ async function collectJudgeKey(env) {
531
+ p.note([
532
+ "Elmo reads every answer with Jev (TypeSafe) to decide which ones really",
533
+ "mention your brand and competitors, how they describe each, and the",
534
+ "passage that shows it. Answers that name a tracked company are sent to",
535
+ "TypeSafe for this; the rest cost nothing.",
536
+ "",
537
+ "Very roughly $0.15–0.35 per 1,000 answers, more when answers are long or",
538
+ "name many competitors. With the default 5 samples a day, 25 prompts on 3",
539
+ "platforms is ~11,000 answers, about $2–4 a month; 100 prompts on 5",
540
+ "platforms is ~75,000, about $11–26.",
541
+ "",
542
+ "On first start Elmo also re-judges the last 90 days of history once",
543
+ "(REPROCESS_DAYS), about three months of the above.",
544
+ "",
545
+ `Get a key: ${link(pc.cyan(SIGNUP_URL), SIGNUP_URL)}`
546
+ ].join("\n"), "Mention and sentiment judging");
547
+ const key = await p.password({
548
+ message: "TypeSafe API key (for Jev)",
549
+ validate: (value) => value?.trim() ? void 0 : "Required"
550
+ });
551
+ assertNotCancelled(key);
552
+ env.TYPESAFE_API_KEY = key.trim();
553
+ }
554
+ //#endregion
528
555
  //#region src/providers.ts
529
556
  const CLORO_AFFILIATE = "https://cloro.dev?fpr=elmo&fp_sid=cli";
530
557
  const BRIGHTDATA_AFFILIATE = "https://get.brightdata.com/elmo?sid=cli";
@@ -1183,7 +1210,7 @@ async function configureProvidersRecommended(env) {
1183
1210
  webSearch: true
1184
1211
  }));
1185
1212
  const direct = await p.select({
1186
- message: "Direct LLM API (powers onboarding analysis + sentiment scoring)",
1213
+ message: "Direct LLM API (powers onboarding analysis + the Opportunities report)",
1187
1214
  options: [
1188
1215
  {
1189
1216
  value: "openrouter",
@@ -1295,6 +1322,7 @@ async function runInit(options, version) {
1295
1322
  env.DATABASE_URL = url;
1296
1323
  } else env.DATABASE_URL = LOCAL_DATABASE_URL;
1297
1324
  const setupMode = await configureProvidersInteractive(env);
1325
+ await collectJudgeKey(env);
1298
1326
  p.note([
1299
1327
  "Elmo is open source and maintained by a small team. Telemetry",
1300
1328
  "from both the CLI and your local deployment (web + worker)",
@@ -1571,6 +1599,7 @@ async function runUpgrade(options, cliVersion) {
1571
1599
  p.cancel("Upgrade cancelled.");
1572
1600
  process.exit(0);
1573
1601
  }
1602
+ await ensureJudgeKey(configDir, buildMigrationContext(configDir, cliVersion), options.yes);
1574
1603
  assertDockerRunning();
1575
1604
  const wasRunning = await stackHasRunningServices(configDir);
1576
1605
  if (wasRunning) {
@@ -1597,6 +1626,23 @@ async function runUpgrade(options, cliVersion) {
1597
1626
  });
1598
1627
  p.outro(pc.green(`Upgraded to ${cliVersion}.`));
1599
1628
  }
1629
+ /** Elmo can't judge answers without a Jev key, so an upgrade that lacks one asks for it before stopping anything. */
1630
+ async function ensureJudgeKey(configDir, context, nonInteractive) {
1631
+ if (!await fs.stat(path.join(configDir, ".env")).catch(() => null)) {
1632
+ log.error(`Couldn't find ${path.join(configDir, ".env")}; run \`elmo init\` or restore it, then rerun the upgrade.`);
1633
+ process.exit(1);
1634
+ }
1635
+ const env = await context.readEnv();
1636
+ if (env.TYPESAFE_API_KEY?.trim()) return;
1637
+ if (nonInteractive) {
1638
+ log.error("This version needs TYPESAFE_API_KEY (Jev, https://console.typesafe.ai) to judge mentions and sentiment.");
1639
+ log.info("Add it to .env with `elmo edit env`, then rerun the upgrade.");
1640
+ process.exit(1);
1641
+ }
1642
+ await collectJudgeKey(env);
1643
+ await context.writeEnv(env);
1644
+ log.success("Saved TYPESAFE_API_KEY to .env.");
1645
+ }
1600
1646
  function buildMigrationContext(configDir, version) {
1601
1647
  const envPath = path.join(configDir, ".env");
1602
1648
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elmohq/cli",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "license": "MIT",
5
5
  "keywords": [
6
6
  "marketing",
@@ -30,16 +30,16 @@
30
30
  "dependencies": {
31
31
  "@clack/prompts": "^1.8.1",
32
32
  "commander": "^15.0.0",
33
- "dotenv": "17.4.2",
33
+ "dotenv": "18.0.7",
34
34
  "picocolors": "^1.1.1",
35
- "posthog-node": "^5.55.0",
35
+ "posthog-node": "^5.55.2",
36
36
  "semver": "^7.8.5"
37
37
  },
38
38
  "devDependencies": {
39
- "@types/node": "^26.6.4",
39
+ "@types/node": "^26.6.5",
40
40
  "@types/semver": "^7.8.0",
41
- "@workspace/config": "0.6.1",
42
- "rolldown": "^1.2.12",
41
+ "@workspace/config": "0.7.0",
42
+ "rolldown": "^1.2.13",
43
43
  "typescript": "^7.0.2",
44
44
  "vitest": "^5.0.3"
45
45
  },