@holdyourvoice/hyv 2.9.21 → 2.9.22

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 +156 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4727,6 +4727,41 @@ var init_profile_meta = __esm({
4727
4727
  });
4728
4728
 
4729
4729
  // src/lib/config.ts
4730
+ var config_exports = {};
4731
+ __export(config_exports, {
4732
+ API_BASE: () => API_BASE,
4733
+ AUTH_FILE: () => AUTH_FILE,
4734
+ CACHE_DIR: () => CACHE_DIR2,
4735
+ CONFIG_FILE: () => CONFIG_FILE,
4736
+ HYV_DIR: () => HYV_DIR,
4737
+ LAST_SESSION_FILE: () => LAST_SESSION_FILE,
4738
+ PROFILES_DIR: () => PROFILES_DIR,
4739
+ QUEUE_DIR: () => QUEUE_DIR,
4740
+ appendSecureLine: () => appendSecureLine,
4741
+ assertSafeOAuthUrl: () => assertSafeOAuthUrl,
4742
+ assertSafeOpenUrl: () => assertSafeOpenUrl,
4743
+ assertSafeProfileName: () => assertSafeProfileName,
4744
+ clearAuth: () => clearAuth,
4745
+ clearQueuedSignals: () => clearQueuedSignals,
4746
+ cliApiUrl: () => cliApiUrl,
4747
+ ensureHyvDir: () => ensureHyvDir,
4748
+ getQueuedSignals: () => getQueuedSignals,
4749
+ getToken: () => getToken,
4750
+ isInitialized: () => isInitialized,
4751
+ listCachedProfiles: () => listCachedProfiles,
4752
+ profilePathForName: () => profilePathForName,
4753
+ queueSignal: () => queueSignal,
4754
+ readAuth: () => readAuth,
4755
+ readCachedProfile: () => readCachedProfile,
4756
+ readConfig: () => readConfig,
4757
+ readLastEditSession: () => readLastEditSession,
4758
+ saveLastEditSession: () => saveLastEditSession,
4759
+ toSafeProfileCacheKey: () => toSafeProfileCacheKey,
4760
+ writeAuth: () => writeAuth,
4761
+ writeCachedProfile: () => writeCachedProfile,
4762
+ writeConfig: () => writeConfig,
4763
+ writeSecureFile: () => writeSecureFile
4764
+ });
4730
4765
  function validateApiBase(raw) {
4731
4766
  const trimmed = raw.replace(/\/$/, "");
4732
4767
  let parsed;
@@ -4822,6 +4857,10 @@ function ensureHyvDir() {
4822
4857
  }
4823
4858
  }
4824
4859
  }
4860
+ function writeSecureFile(filePath, content) {
4861
+ ensureHyvDir();
4862
+ fs3.writeFileSync(filePath, content, { mode: 384 });
4863
+ }
4825
4864
  function appendSecureLine(filePath, line, dir) {
4826
4865
  if (dir) {
4827
4866
  if (!fs3.existsSync(dir))
@@ -4866,6 +4905,11 @@ function writeAuth(auth) {
4866
4905
  }
4867
4906
  fs3.writeFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), { mode: 384 });
4868
4907
  }
4908
+ function clearAuth() {
4909
+ if (fs3.existsSync(AUTH_FILE)) {
4910
+ fs3.unlinkSync(AUTH_FILE);
4911
+ }
4912
+ }
4869
4913
  function readConfig() {
4870
4914
  try {
4871
4915
  if (!fs3.existsSync(CONFIG_FILE))
@@ -4943,6 +4987,17 @@ function queueSignal(signal) {
4943
4987
  const filePath = path2.join(QUEUE_DIR, `${id}.json`);
4944
4988
  fs3.writeFileSync(filePath, JSON.stringify(signal, null, 2), { mode: 384 });
4945
4989
  }
4990
+ function clearQueuedSignals() {
4991
+ try {
4992
+ if (!fs3.existsSync(QUEUE_DIR))
4993
+ return;
4994
+ const files = fs3.readdirSync(QUEUE_DIR).filter((f) => f.endsWith(".json"));
4995
+ for (const f of files) {
4996
+ fs3.unlinkSync(path2.join(QUEUE_DIR, f));
4997
+ }
4998
+ } catch {
4999
+ }
5000
+ }
4946
5001
  function saveLastEditSession(session) {
4947
5002
  ensureHyvDir();
4948
5003
  const data = { ...session, saved_at: (/* @__PURE__ */ new Date()).toISOString() };
@@ -17087,7 +17142,28 @@ function registerImportCommand(program3) {
17087
17142
  ensureHyvDir();
17088
17143
  writeCachedProfile(name, content);
17089
17144
  console.log(import_chalk13.default.green(`
17090
- \u2713 Profile imported: ${name}`));
17145
+ \u2713 Profile imported locally: ${name}`));
17146
+ const { getToken: getToken2 } = await Promise.resolve().then(() => (init_config(), config_exports));
17147
+ const { authenticatedRequest: authenticatedRequest2, cliApiUrl: cliApiUrl2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
17148
+ const token = getToken2();
17149
+ if (token) {
17150
+ console.log(import_chalk13.default.cyan("\nSyncing profile to your account..."));
17151
+ try {
17152
+ const syncResponse = await authenticatedRequest2(
17153
+ cliApiUrl2("/cli/profiles/new"),
17154
+ { method: "POST", body: { name, content, source: "import" } }
17155
+ );
17156
+ if (syncResponse.status === 200) {
17157
+ console.log(import_chalk13.default.green(" \u2713 synced to your account"));
17158
+ } else {
17159
+ console.log(import_chalk13.default.yellow(" profile saved locally \u2014 run `hyv sync` to push to your account"));
17160
+ }
17161
+ } catch {
17162
+ console.log(import_chalk13.default.yellow(" profile saved locally \u2014 run `hyv sync` to push to your account"));
17163
+ }
17164
+ } else {
17165
+ console.log(import_chalk13.default.dim("\n not signed in \u2014 profile saved locally. run `hyv init` then `hyv sync` to back it up."));
17166
+ }
17091
17167
  } catch (error) {
17092
17168
  console.error(import_chalk13.default.red(`Error: ${error.message}`));
17093
17169
  process.exit(1);
@@ -19319,6 +19395,69 @@ function formatMcpIntegrateReportText(result, opts = {}) {
19319
19395
  }
19320
19396
  return lines.join("\n");
19321
19397
  }
19398
+ function printMcpIntegrateReport(result, opts = {}) {
19399
+ const { agentIdForConfiguredLabel, isAgentIntegrated } = loadPostinstallLib();
19400
+ const configuredIds = new Set(
19401
+ result.configured.map((label) => agentIdForConfiguredLabel(label)).filter(Boolean)
19402
+ );
19403
+ console.log(import_chalk33.default.bold("\nhold your voice \u2014 mcp integration\n"));
19404
+ console.log(import_chalk33.default.dim(` ${getEngineLabel()}
19405
+ `));
19406
+ const welcome = readWelcomeState();
19407
+ const profiles = listLocalProfileNames2();
19408
+ if (profiles.length > 0) {
19409
+ console.log(import_chalk33.default.dim(` voice profiles: ${profiles.join(", ")}`));
19410
+ } else {
19411
+ console.log(import_chalk33.default.yellow(" no voice profile yet \u2014 mcp still works (free scan). finish onboarding in terminal or in-chat via hyv_welcome"));
19412
+ }
19413
+ if (welcome.completed_steps?.length) {
19414
+ console.log(import_chalk33.default.dim(` welcome progress: ${welcome.completed_steps.join(", ")}`));
19415
+ }
19416
+ console.log("");
19417
+ if (result.detected.length === 0) {
19418
+ console.log(import_chalk33.default.yellow(" no supported ai apps detected on this machine."));
19419
+ console.log(import_chalk33.default.dim("\n install cursor, claude desktop, chatgpt desktop, or another supported app,"));
19420
+ console.log(import_chalk33.default.dim(" then run hyv mcp again \u2014 or hyv doctor --fix-agents to configure everything."));
19421
+ console.log(import_chalk33.default.dim("\n in chatgpt/claude/cursor: call hyv_welcome to onboard without the terminal."));
19422
+ console.log(import_chalk33.default.dim(" chatgpt desktop (paid): developer mode \u2192 new app \u2192 https://holdyourvoice.com/mcp + oauth"));
19423
+ console.log(import_chalk33.default.dim(" full steps: hyv mcp --setup-chatgpt\n"));
19424
+ return;
19425
+ }
19426
+ console.log(import_chalk33.default.bold("detected apps"));
19427
+ for (const app of result.detected) {
19428
+ const justConfigured = configuredIds.has(app.id);
19429
+ const integrated = isAgentIntegrated(app.id) || justConfigured;
19430
+ const mark = app.integration === "manual" ? import_chalk33.default.yellow("\u25CB") : integrated ? import_chalk33.default.green("\u2713") : import_chalk33.default.cyan("\u2192");
19431
+ const status = app.integration === "manual" ? "manual connector \u2014 see ~/.chatgpt/hyv-mcp-connector.txt" : justConfigured ? opts.force ? "updated now" : "configured now" : integrated ? "integrated" : "needs setup";
19432
+ console.log(` ${mark} ${app.label} \u2014 ${status}`);
19433
+ console.log(import_chalk33.default.dim(` ${app.reason} \xB7 ${app.integration}`));
19434
+ }
19435
+ if (result.configured.length > 0) {
19436
+ console.log(import_chalk33.default.green(`
19437
+ wired hyv into: ${result.configured.join(", ")}`));
19438
+ }
19439
+ if (result.warnings.length > 0) {
19440
+ console.log(import_chalk33.default.yellow("\n notes:"));
19441
+ for (const warning of result.warnings) {
19442
+ console.log(import_chalk33.default.yellow(` ! ${warning}`));
19443
+ }
19444
+ }
19445
+ const mcpApps = result.detected.filter((a) => a.integration === "mcp");
19446
+ const manualApps = result.detected.filter((a) => a.integration === "manual");
19447
+ console.log(import_chalk33.default.bold("\nnext steps"));
19448
+ console.log(import_chalk33.default.dim(" in this app: hyv_welcome (onboarding) \xB7 hyv_mcp_setup (status/refresh) \xB7 hyv_demo (try a scan)"));
19449
+ if (mcpApps.length > 0) {
19450
+ console.log(import_chalk33.default.dim(" restart apps that use mcp (cursor, claude desktop, antigravity, opencode)"));
19451
+ }
19452
+ if (manualApps.length > 0) {
19453
+ console.log(import_chalk33.default.dim(" chatgpt (recommended): developer mode \u2192 new app \u2192 https://holdyourvoice.com/mcp + oauth"));
19454
+ console.log(import_chalk33.default.dim(" chatgpt (free fallback): settings \u2192 connectors \u2192 command hyv, arguments mcp"));
19455
+ console.log(import_chalk33.default.dim(" full steps: hyv mcp --setup-chatgpt"));
19456
+ }
19457
+ console.log(import_chalk33.default.dim(" refresh stale configs after upgrade: hyv mcp --force"));
19458
+ console.log(import_chalk33.default.dim(" verify: hyv mcp --test"));
19459
+ console.log(import_chalk33.default.dim(" all hosts: hyv doctor --verify-hosts\n"));
19460
+ }
19322
19461
 
19323
19462
  // src/mcp.ts
19324
19463
  init_mcp_profile_hydrate();
@@ -19758,7 +19897,7 @@ var TOOLS = [
19758
19897
  },
19759
19898
  {
19760
19899
  name: "hyv_scan",
19761
- description: "Fast local scan for 80+ AI patterns + profile never-list/learned rules. FREE, offline. ALWAYS scan before finalizing written content.",
19900
+ description: "Fast local scan for 80+ AI patterns + profile never-list/learned rules. FREE, offline. ALWAYS scan before finalizing any written content \u2014 emails, posts, docs, replies, messages, or prose.",
19762
19901
  inputSchema: {
19763
19902
  type: "object",
19764
19903
  properties: {
@@ -19971,6 +20110,16 @@ async function startMcpServer() {
19971
20110
  mcpLog("info", `account profile sync skipped: ${r.error}`);
19972
20111
  }).catch(() => {
19973
20112
  });
20113
+ try {
20114
+ const result = runMcpAutoIntegrate({ force: false });
20115
+ if (result.configured.length > 0) {
20116
+ mcpLog("info", `mcp auto-configured: ${result.configured.join(", ")}`);
20117
+ }
20118
+ if (result.detected.length > 0 && result.configured.length === 0) {
20119
+ mcpLog("info", `detected apps (already configured): ${result.detected.map((a) => a.label).join(", ")}`);
20120
+ }
20121
+ } catch {
20122
+ }
19974
20123
  let buffer = "";
19975
20124
  process.stdin.setEncoding("utf-8");
19976
20125
  let requestChain = Promise.resolve();
@@ -20335,7 +20484,7 @@ registerOpenCommand(program2);
20335
20484
  registerWelcomeCommand(program2);
20336
20485
  registerContentCommand(program2);
20337
20486
  registerUpgradeCommand(program2);
20338
- program2.command("mcp").description("Start MCP server (for Claude Desktop and other MCP hosts)").option("--setup", "Show MCP setup for Claude Desktop, Cursor, Windsurf, Codex").option("--test", "Run MCP health check (tools, profile, stdio)").option("--setup-chatgpt", "Show ChatGPT connector setup instructions").action(async (opts) => {
20487
+ program2.command("mcp").description("Detect installed apps, configure MCP, and start the MCP server").option("--setup", "Show MCP setup for Claude Desktop, Cursor, Windsurf, Codex").option("--test", "Run MCP health check (tools, profile, stdio)").option("--setup-chatgpt", "Show ChatGPT connector setup instructions").option("--force", "Force re-configure MCP even if already integrated").action(async (opts) => {
20339
20488
  if (opts.setup) {
20340
20489
  printMcpSetup();
20341
20490
  return;
@@ -20394,6 +20543,10 @@ program2.command("mcp").description("Start MCP server (for Claude Desktop and ot
20394
20543
  console.log("");
20395
20544
  return;
20396
20545
  }
20546
+ console.log(import_chalk35.default.bold("\nhold your voice \u2014 detecting and configuring mcp...\n"));
20547
+ const result = runMcpAutoIntegrate({ force: Boolean(opts.force) });
20548
+ printMcpIntegrateReport(result, { force: Boolean(opts.force) });
20549
+ console.log(import_chalk35.default.dim("\nstarting MCP server (press Ctrl+C to stop)...\n"));
20397
20550
  startMcpServer();
20398
20551
  });
20399
20552
  program2.command("export").description("Export voice profile for LLMs").argument("[format]", "Export format (claude, chatgpt, generic, cursor)", "claude").option("--output <file>", "Write to file instead of stdout").option("--json", "Output as JSON").action(async (format, opts) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holdyourvoice/hyv",
3
- "version": "2.9.21",
3
+ "version": "2.9.22",
4
4
  "description": "Free local AI writing scan for cursor & claude. MCP server, 220+ pattern detection, voice profiles. npx @holdyourvoice/hyv welcome",
5
5
  "main": "dist/index.js",
6
6
  "bin": {