@holdyourvoice/hyv 2.9.3 → 2.9.5
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/CHANGELOG.md +15 -0
- package/dist/index.js +77 -48
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable CLI changes. Also mirrored to [holdyourvoice.com/changelog](https://holdyourvoice.com/changelog) for user-facing releases.
|
|
4
4
|
|
|
5
|
+
## [2.9.5] — 2026-06-12
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Post-signup browser opens `/app/billing` (live dashboard) instead of `/dashboard` (404)
|
|
9
|
+
- Worker redirects `/dashboard` → `/app` for old links
|
|
10
|
+
|
|
11
|
+
## [2.9.4] — 2026-06-12
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- Welcome step 4 — one sign-in only; opens dashboard billing tab (no second Google login on marketing site)
|
|
15
|
+
- `hyv plan --upgrade` opens authenticated dashboard billing instead of public pricing page
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Step 4 copy tightened; spinners while account + profile sync run
|
|
19
|
+
|
|
5
20
|
## [2.9.3] — 2026-06-12
|
|
6
21
|
|
|
7
22
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -4624,7 +4624,7 @@ __export(config_exports, {
|
|
|
4624
4624
|
QUEUE_DIR: () => QUEUE_DIR,
|
|
4625
4625
|
appendSecureLine: () => appendSecureLine,
|
|
4626
4626
|
assertSafeOAuthUrl: () => assertSafeOAuthUrl,
|
|
4627
|
-
assertSafeOpenUrl: () =>
|
|
4627
|
+
assertSafeOpenUrl: () => assertSafeOpenUrl2,
|
|
4628
4628
|
assertSafeProfileName: () => assertSafeProfileName,
|
|
4629
4629
|
clearAuth: () => clearAuth,
|
|
4630
4630
|
clearQueuedSignals: () => clearQueuedSignals,
|
|
@@ -4666,7 +4666,7 @@ function cliApiUrl(apiPath) {
|
|
|
4666
4666
|
const p = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
|
|
4667
4667
|
return `${API_BASE}${p}`;
|
|
4668
4668
|
}
|
|
4669
|
-
function
|
|
4669
|
+
function assertSafeOpenUrl2(url) {
|
|
4670
4670
|
let parsed;
|
|
4671
4671
|
try {
|
|
4672
4672
|
parsed = new URL(url);
|
|
@@ -5355,6 +5355,7 @@ __export(auth_exports, {
|
|
|
5355
5355
|
authenticatedRequest: () => authenticatedRequest,
|
|
5356
5356
|
checkSession: () => checkSession,
|
|
5357
5357
|
getValidToken: () => getValidToken,
|
|
5358
|
+
openAuthenticatedDashboard: () => openAuthenticatedDashboard,
|
|
5358
5359
|
refreshToken: () => refreshToken,
|
|
5359
5360
|
verifyOAuthState: () => verifyOAuthState
|
|
5360
5361
|
});
|
|
@@ -5543,6 +5544,22 @@ async function authenticateWithBrowser() {
|
|
|
5543
5544
|
writeAuth(authData);
|
|
5544
5545
|
return authData;
|
|
5545
5546
|
}
|
|
5547
|
+
async function openAuthenticatedDashboard(opts = {}) {
|
|
5548
|
+
const response = await authenticatedRequest(cliApiUrl("/cli/auth/web-handoff"), {
|
|
5549
|
+
method: "POST",
|
|
5550
|
+
body: {
|
|
5551
|
+
next: opts.next || "/app/billing"
|
|
5552
|
+
}
|
|
5553
|
+
});
|
|
5554
|
+
if (response.status !== 200) {
|
|
5555
|
+
throw new Error("Could not open dashboard \u2014 try https://holdyourvoice.com/dashboard");
|
|
5556
|
+
}
|
|
5557
|
+
const { url } = response.data;
|
|
5558
|
+
if (!url) {
|
|
5559
|
+
throw new Error("Dashboard handoff URL missing");
|
|
5560
|
+
}
|
|
5561
|
+
await (0, import_open.default)(assertSafeOpenUrl(url));
|
|
5562
|
+
}
|
|
5546
5563
|
async function refreshToken(tokenOverride) {
|
|
5547
5564
|
const token = tokenOverride || readAuth()?.token;
|
|
5548
5565
|
if (!token)
|
|
@@ -5602,6 +5619,17 @@ var init_auth = __esm({
|
|
|
5602
5619
|
});
|
|
5603
5620
|
|
|
5604
5621
|
// src/lib/free-paid.ts
|
|
5622
|
+
var free_paid_exports = {};
|
|
5623
|
+
__export(free_paid_exports, {
|
|
5624
|
+
COMMUNITY_URL: () => COMMUNITY_URL,
|
|
5625
|
+
DASHBOARD_BILLING_URL: () => DASHBOARD_BILLING_URL,
|
|
5626
|
+
FREE_CLI_COMMANDS: () => FREE_CLI_COMMANDS,
|
|
5627
|
+
FREE_WEB_TOOLS: () => FREE_WEB_TOOLS,
|
|
5628
|
+
NPX_EXAMPLES: () => NPX_EXAMPLES,
|
|
5629
|
+
PAID_FEATURES: () => PAID_FEATURES,
|
|
5630
|
+
PRICING_URL: () => PRICING_URL,
|
|
5631
|
+
printFreePaidMatrix: () => printFreePaidMatrix
|
|
5632
|
+
});
|
|
5605
5633
|
function printFreePaidMatrix(opts = {}) {
|
|
5606
5634
|
if (opts.compact) {
|
|
5607
5635
|
console.log(import_chalk2.default.bold("\nFree forever (local)"));
|
|
@@ -5634,7 +5662,7 @@ function printFreePaidMatrix(opts = {}) {
|
|
|
5634
5662
|
First month $1 \u2192 ${PRICING_URL}`));
|
|
5635
5663
|
console.log(import_chalk2.default.dim(" hyv init | hyv plan --upgrade\n"));
|
|
5636
5664
|
}
|
|
5637
|
-
var import_chalk2, NPX_EXAMPLES, FREE_CLI_COMMANDS, PAID_FEATURES, FREE_WEB_TOOLS, COMMUNITY_URL, PRICING_URL;
|
|
5665
|
+
var import_chalk2, NPX_EXAMPLES, FREE_CLI_COMMANDS, PAID_FEATURES, FREE_WEB_TOOLS, COMMUNITY_URL, PRICING_URL, DASHBOARD_BILLING_URL;
|
|
5638
5666
|
var init_free_paid = __esm({
|
|
5639
5667
|
"src/lib/free-paid.ts"() {
|
|
5640
5668
|
"use strict";
|
|
@@ -5682,6 +5710,7 @@ var init_free_paid = __esm({
|
|
|
5682
5710
|
];
|
|
5683
5711
|
COMMUNITY_URL = "https://holdyourvoice.com/community";
|
|
5684
5712
|
PRICING_URL = "https://holdyourvoice.com/#pricing";
|
|
5713
|
+
DASHBOARD_BILLING_URL = "https://holdyourvoice.com/app/billing";
|
|
5685
5714
|
}
|
|
5686
5715
|
});
|
|
5687
5716
|
|
|
@@ -11452,12 +11481,12 @@ function buildStepGuide(step, profileName) {
|
|
|
11452
11481
|
return [
|
|
11453
11482
|
"### Step 4 \u2014 save & unlock",
|
|
11454
11483
|
"",
|
|
11455
|
-
"Explain warmly:
|
|
11484
|
+
"Explain warmly: local profile until signup. One browser sign-in via CLI \u2014 then open dashboard billing (no second login).",
|
|
11456
11485
|
"Paid unlock is **$1 for the first month** \u2014 profiles that learn, hybrid rewrite, dashboard.",
|
|
11457
11486
|
"Scanning/fix/MCP stay free forever without an account.",
|
|
11458
11487
|
"",
|
|
11459
|
-
"1. `hyv init` \u2014
|
|
11460
|
-
"2.
|
|
11488
|
+
"1. `hyv init` or welcome step 4 \u2014 single Google sign-in from terminal",
|
|
11489
|
+
"2. Dashboard opens on billing tab \u2014 user picks plan there",
|
|
11461
11490
|
"",
|
|
11462
11491
|
`Pricing: ${PRICING_URL}`
|
|
11463
11492
|
].join("\n");
|
|
@@ -11784,14 +11813,13 @@ async function stepTest(profileName) {
|
|
|
11784
11813
|
}
|
|
11785
11814
|
async function stepSignup(profileName) {
|
|
11786
11815
|
console.log(import_chalk12.default.bold("\nstep 4 \xB7 save & unlock\n"));
|
|
11787
|
-
console.log(" your
|
|
11788
|
-
console.log("
|
|
11789
|
-
console.log("
|
|
11790
|
-
console.log("
|
|
11791
|
-
console.log("
|
|
11792
|
-
console.log(" access to profiles that learn, hybrid rewrite, and your dashboard.\n");
|
|
11816
|
+
console.log(" your profile works on this machine. scan anything, anytime \u2014 free forever.");
|
|
11817
|
+
console.log("");
|
|
11818
|
+
console.log(" create a free account to back it up and sync everywhere.");
|
|
11819
|
+
console.log(" then unlock learning for " + import_chalk12.default.bold("$1 your first month") + " \u2014 profiles that");
|
|
11820
|
+
console.log(" get sharper every rewrite, hybrid rewrites, and your dashboard.\n");
|
|
11793
11821
|
console.log(import_chalk12.default.dim(" free forever (no account): scan, fix, check, mcp"));
|
|
11794
|
-
console.log(import_chalk12.default.dim("
|
|
11822
|
+
console.log(import_chalk12.default.dim(" $1 first month: learning loop, rich rewrites, sync across devices\n"));
|
|
11795
11823
|
const ready = await askYesNo(" create your free account now? ($1 first month to unlock everything)");
|
|
11796
11824
|
if (!ready) {
|
|
11797
11825
|
console.log(import_chalk12.default.dim("\n no rush \u2014 your profile stays on this machine."));
|
|
@@ -11803,18 +11831,25 @@ async function stepSignup(profileName) {
|
|
|
11803
11831
|
return;
|
|
11804
11832
|
}
|
|
11805
11833
|
if (!isInitialized() || !getToken()) {
|
|
11806
|
-
console.log(import_chalk12.default.cyan("\n opening browser for signup...\n"));
|
|
11807
|
-
await authenticateWithBrowser();
|
|
11834
|
+
console.log(import_chalk12.default.cyan("\n opening browser for signup (one sign-in)...\n"));
|
|
11835
|
+
await withSpinner("creating your account\u2026", () => authenticateWithBrowser());
|
|
11836
|
+
await briefPause();
|
|
11837
|
+
console.log(import_chalk12.default.green(" \u2713 account created"));
|
|
11838
|
+
} else {
|
|
11839
|
+
console.log(import_chalk12.default.dim("\n already signed in \u2014 syncing profile..."));
|
|
11808
11840
|
}
|
|
11809
11841
|
const content = fs13.readFileSync(
|
|
11810
11842
|
path13.join(os7.homedir(), ".hyv", "profiles", `${profileName}.md`),
|
|
11811
11843
|
"utf-8"
|
|
11812
11844
|
);
|
|
11813
11845
|
try {
|
|
11814
|
-
const response = await
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11846
|
+
const response = await withSpinner(
|
|
11847
|
+
"syncing profile\u2026",
|
|
11848
|
+
() => authenticatedRequest(cliApiUrl("/cli/profiles/new"), {
|
|
11849
|
+
method: "POST",
|
|
11850
|
+
body: { name: profileName, content, source: "welcome" }
|
|
11851
|
+
})
|
|
11852
|
+
);
|
|
11818
11853
|
if (response.status === 200) {
|
|
11819
11854
|
console.log(import_chalk12.default.green(" \u2713 profile synced to your account"));
|
|
11820
11855
|
} else {
|
|
@@ -11823,12 +11858,19 @@ async function stepSignup(profileName) {
|
|
|
11823
11858
|
} catch {
|
|
11824
11859
|
console.log(import_chalk12.default.yellow(" profile saved locally \u2014 run `hyv sync` after you upgrade"));
|
|
11825
11860
|
}
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11861
|
+
try {
|
|
11862
|
+
console.log(import_chalk12.default.cyan("\n opening billing in your dashboard ($1 first month)..."));
|
|
11863
|
+
await withSpinner("opening dashboard\u2026", () => openAuthenticatedDashboard({ next: "/app/billing" }));
|
|
11864
|
+
await briefPause();
|
|
11865
|
+
} catch {
|
|
11866
|
+
const { DASHBOARD_BILLING_URL: DASHBOARD_BILLING_URL2 } = await Promise.resolve().then(() => (init_free_paid(), free_paid_exports));
|
|
11867
|
+
const { assertSafeOpenUrl: assertSafeOpenUrl3 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
11868
|
+
const { default: open3 } = await Promise.resolve().then(() => __toESM(require_open()));
|
|
11869
|
+
console.log(import_chalk12.default.yellow(" handoff unavailable \u2014 opening billing (sign in if prompted)..."));
|
|
11870
|
+
await open3(assertSafeOpenUrl3(DASHBOARD_BILLING_URL2));
|
|
11871
|
+
}
|
|
11830
11872
|
markStepComplete("signup");
|
|
11831
|
-
console.log(import_chalk12.default.dim("\n
|
|
11873
|
+
console.log(import_chalk12.default.dim("\n you're signed in \u2014 pick a plan in billing, no second login.\n"));
|
|
11832
11874
|
}
|
|
11833
11875
|
async function runInteractiveWelcome() {
|
|
11834
11876
|
recordEvent("welcome_interactive");
|
|
@@ -16854,28 +16896,15 @@ async function showPlan() {
|
|
|
16854
16896
|
}
|
|
16855
16897
|
}
|
|
16856
16898
|
async function upgradePlan() {
|
|
16857
|
-
console.log(import_chalk14.default.cyan("\nOpening
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
|
|
16865
|
-
|
|
16866
|
-
const data = response.data;
|
|
16867
|
-
const checkoutUrl = data.checkout_url;
|
|
16868
|
-
if (checkoutUrl) {
|
|
16869
|
-
console.log(import_chalk14.default.dim("Opening browser..."));
|
|
16870
|
-
await (0, import_open2.default)(assertSafeOpenUrl(checkoutUrl));
|
|
16871
|
-
console.log(import_chalk14.default.green("\n\u2713 Checkout opened in browser"));
|
|
16872
|
-
console.log(import_chalk14.default.dim("Complete the checkout to activate your plan."));
|
|
16873
|
-
} else {
|
|
16874
|
-
console.log(import_chalk14.default.yellow("No checkout URL received."));
|
|
16875
|
-
}
|
|
16876
|
-
} else {
|
|
16877
|
-
console.log(import_chalk14.default.yellow("Could not create checkout session."));
|
|
16878
|
-
console.log(import_chalk14.default.dim("Visit https://holdyourvoice.com/pricing to subscribe."));
|
|
16899
|
+
console.log(import_chalk14.default.cyan("\nOpening billing in your dashboard ($1 first month)...\n"));
|
|
16900
|
+
try {
|
|
16901
|
+
await openAuthenticatedDashboard({ next: "/app/billing" });
|
|
16902
|
+
console.log(import_chalk14.default.green("\n\u2713 Dashboard opened \u2014 you're already signed in"));
|
|
16903
|
+
console.log(import_chalk14.default.dim("Pick a plan in billing. No second login."));
|
|
16904
|
+
} catch {
|
|
16905
|
+
console.log(import_chalk14.default.yellow("Could not open dashboard automatically."));
|
|
16906
|
+
console.log(import_chalk14.default.dim(`Visit ${DASHBOARD_BILLING_URL} after running hyv init`));
|
|
16907
|
+
console.log(import_chalk14.default.dim(`Or see plans: ${PRICING_URL}`));
|
|
16879
16908
|
}
|
|
16880
16909
|
}
|
|
16881
16910
|
async function openBillingPortal() {
|
|
@@ -16889,7 +16918,7 @@ async function openBillingPortal() {
|
|
|
16889
16918
|
const portalUrl = data.portal_url;
|
|
16890
16919
|
if (portalUrl) {
|
|
16891
16920
|
console.log(import_chalk14.default.dim("Opening browser..."));
|
|
16892
|
-
await (0, import_open2.default)(
|
|
16921
|
+
await (0, import_open2.default)(assertSafeOpenUrl2(portalUrl));
|
|
16893
16922
|
console.log(import_chalk14.default.green("\n\u2713 Billing portal opened"));
|
|
16894
16923
|
} else {
|
|
16895
16924
|
console.log(import_chalk14.default.yellow("No portal URL received."));
|
|
@@ -18453,7 +18482,7 @@ var import_chalk29 = __toESM(require_source());
|
|
|
18453
18482
|
var PAGES = {
|
|
18454
18483
|
dashboard: "https://holdyourvoice.com/dashboard",
|
|
18455
18484
|
profiles: "https://holdyourvoice.com/dashboard",
|
|
18456
|
-
pricing: "https://holdyourvoice.com/
|
|
18485
|
+
pricing: "https://holdyourvoice.com/app/billing",
|
|
18457
18486
|
settings: "https://holdyourvoice.com/dashboard"
|
|
18458
18487
|
};
|
|
18459
18488
|
function registerOpenCommand(program3) {
|
package/package.json
CHANGED