@holdyourvoice/hyv 2.9.14 → 2.9.16

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 CHANGED
@@ -973,8 +973,8 @@ var require_command = __commonJS({
973
973
  "node_modules/commander/lib/command.js"(exports2) {
974
974
  var EventEmitter = require("node:events").EventEmitter;
975
975
  var childProcess = require("node:child_process");
976
- var path27 = require("node:path");
977
- var fs30 = require("node:fs");
976
+ var path28 = require("node:path");
977
+ var fs31 = require("node:fs");
978
978
  var process2 = require("node:process");
979
979
  var { Argument: Argument2, humanReadableArgName } = require_argument();
980
980
  var { CommanderError: CommanderError2 } = require_error();
@@ -1916,13 +1916,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
1916
1916
  let launchWithNode = false;
1917
1917
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1918
1918
  function findFile(baseDir, baseName) {
1919
- const localBin = path27.resolve(baseDir, baseName);
1920
- if (fs30.existsSync(localBin))
1919
+ const localBin = path28.resolve(baseDir, baseName);
1920
+ if (fs31.existsSync(localBin))
1921
1921
  return localBin;
1922
- if (sourceExt.includes(path27.extname(baseName)))
1922
+ if (sourceExt.includes(path28.extname(baseName)))
1923
1923
  return void 0;
1924
1924
  const foundExt = sourceExt.find(
1925
- (ext) => fs30.existsSync(`${localBin}${ext}`)
1925
+ (ext) => fs31.existsSync(`${localBin}${ext}`)
1926
1926
  );
1927
1927
  if (foundExt)
1928
1928
  return `${localBin}${foundExt}`;
@@ -1935,21 +1935,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1935
1935
  if (this._scriptPath) {
1936
1936
  let resolvedScriptPath;
1937
1937
  try {
1938
- resolvedScriptPath = fs30.realpathSync(this._scriptPath);
1938
+ resolvedScriptPath = fs31.realpathSync(this._scriptPath);
1939
1939
  } catch (err) {
1940
1940
  resolvedScriptPath = this._scriptPath;
1941
1941
  }
1942
- executableDir = path27.resolve(
1943
- path27.dirname(resolvedScriptPath),
1942
+ executableDir = path28.resolve(
1943
+ path28.dirname(resolvedScriptPath),
1944
1944
  executableDir
1945
1945
  );
1946
1946
  }
1947
1947
  if (executableDir) {
1948
1948
  let localFile = findFile(executableDir, executableFile);
1949
1949
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1950
- const legacyName = path27.basename(
1950
+ const legacyName = path28.basename(
1951
1951
  this._scriptPath,
1952
- path27.extname(this._scriptPath)
1952
+ path28.extname(this._scriptPath)
1953
1953
  );
1954
1954
  if (legacyName !== this._name) {
1955
1955
  localFile = findFile(
@@ -1960,7 +1960,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1960
1960
  }
1961
1961
  executableFile = localFile || executableFile;
1962
1962
  }
1963
- launchWithNode = sourceExt.includes(path27.extname(executableFile));
1963
+ launchWithNode = sourceExt.includes(path28.extname(executableFile));
1964
1964
  let proc;
1965
1965
  if (process2.platform !== "win32") {
1966
1966
  if (launchWithNode) {
@@ -2817,7 +2817,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2817
2817
  * @return {Command}
2818
2818
  */
2819
2819
  nameFromFilename(filename) {
2820
- this._name = path27.basename(filename, path27.extname(filename));
2820
+ this._name = path28.basename(filename, path28.extname(filename));
2821
2821
  return this;
2822
2822
  }
2823
2823
  /**
@@ -2831,10 +2831,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
2831
2831
  * @param {string} [path]
2832
2832
  * @return {(string|null|Command)}
2833
2833
  */
2834
- executableDir(path28) {
2835
- if (path28 === void 0)
2834
+ executableDir(path29) {
2835
+ if (path29 === void 0)
2836
2836
  return this._executableDir;
2837
- this._executableDir = path28;
2837
+ this._executableDir = path29;
2838
2838
  return this;
2839
2839
  }
2840
2840
  /**
@@ -3934,15 +3934,15 @@ var require_route = __commonJS({
3934
3934
  };
3935
3935
  }
3936
3936
  function wrapConversion(toModel, graph) {
3937
- const path27 = [graph[toModel].parent, toModel];
3937
+ const path28 = [graph[toModel].parent, toModel];
3938
3938
  let fn = conversions[graph[toModel].parent][toModel];
3939
3939
  let cur = graph[toModel].parent;
3940
3940
  while (graph[cur].parent) {
3941
- path27.unshift(graph[cur].parent);
3941
+ path28.unshift(graph[cur].parent);
3942
3942
  fn = link(conversions[graph[cur].parent][cur], fn);
3943
3943
  cur = graph[cur].parent;
3944
3944
  }
3945
- fn.conversion = path27;
3945
+ fn.conversion = path28;
3946
3946
  return fn;
3947
3947
  }
3948
3948
  module2.exports = function(fromModel) {
@@ -4182,7 +4182,7 @@ var require_has_flag = __commonJS({
4182
4182
  var require_supports_color = __commonJS({
4183
4183
  "node_modules/supports-color/index.js"(exports2, module2) {
4184
4184
  "use strict";
4185
- var os13 = require("os");
4185
+ var os15 = require("os");
4186
4186
  var tty = require("tty");
4187
4187
  var hasFlag = require_has_flag();
4188
4188
  var { env } = process;
@@ -4230,7 +4230,7 @@ var require_supports_color = __commonJS({
4230
4230
  return min;
4231
4231
  }
4232
4232
  if (process.platform === "win32") {
4233
- const osRelease = os13.release().split(".");
4233
+ const osRelease = os15.release().split(".");
4234
4234
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
4235
4235
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
4236
4236
  }
@@ -4381,14 +4381,14 @@ var require_templates = __commonJS({
4381
4381
  }
4382
4382
  return results;
4383
4383
  }
4384
- function buildStyle(chalk34, styles) {
4384
+ function buildStyle(chalk36, styles) {
4385
4385
  const enabled = {};
4386
4386
  for (const layer of styles) {
4387
4387
  for (const style of layer.styles) {
4388
4388
  enabled[style[0]] = layer.inverse ? null : style.slice(1);
4389
4389
  }
4390
4390
  }
4391
- let current = chalk34;
4391
+ let current = chalk36;
4392
4392
  for (const [styleName, styles2] of Object.entries(enabled)) {
4393
4393
  if (!Array.isArray(styles2)) {
4394
4394
  continue;
@@ -4400,7 +4400,7 @@ var require_templates = __commonJS({
4400
4400
  }
4401
4401
  return current;
4402
4402
  }
4403
- module2.exports = (chalk34, temporary) => {
4403
+ module2.exports = (chalk36, temporary) => {
4404
4404
  const styles = [];
4405
4405
  const chunks = [];
4406
4406
  let chunk = [];
@@ -4410,13 +4410,13 @@ var require_templates = __commonJS({
4410
4410
  } else if (style) {
4411
4411
  const string = chunk.join("");
4412
4412
  chunk = [];
4413
- chunks.push(styles.length === 0 ? string : buildStyle(chalk34, styles)(string));
4413
+ chunks.push(styles.length === 0 ? string : buildStyle(chalk36, styles)(string));
4414
4414
  styles.push({ inverse, styles: parseStyle(style) });
4415
4415
  } else if (close) {
4416
4416
  if (styles.length === 0) {
4417
4417
  throw new Error("Found extraneous } in Chalk template literal");
4418
4418
  }
4419
- chunks.push(buildStyle(chalk34, styles)(chunk.join("")));
4419
+ chunks.push(buildStyle(chalk36, styles)(chunk.join("")));
4420
4420
  chunk = [];
4421
4421
  styles.pop();
4422
4422
  } else {
@@ -4464,16 +4464,16 @@ var require_source = __commonJS({
4464
4464
  }
4465
4465
  };
4466
4466
  var chalkFactory = (options) => {
4467
- const chalk35 = {};
4468
- applyOptions(chalk35, options);
4469
- chalk35.template = (...arguments_) => chalkTag(chalk35.template, ...arguments_);
4470
- Object.setPrototypeOf(chalk35, Chalk.prototype);
4471
- Object.setPrototypeOf(chalk35.template, chalk35);
4472
- chalk35.template.constructor = () => {
4467
+ const chalk37 = {};
4468
+ applyOptions(chalk37, options);
4469
+ chalk37.template = (...arguments_) => chalkTag(chalk37.template, ...arguments_);
4470
+ Object.setPrototypeOf(chalk37, Chalk.prototype);
4471
+ Object.setPrototypeOf(chalk37.template, chalk37);
4472
+ chalk37.template.constructor = () => {
4473
4473
  throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.");
4474
4474
  };
4475
- chalk35.template.Instance = ChalkClass;
4476
- return chalk35.template;
4475
+ chalk37.template.Instance = ChalkClass;
4476
+ return chalk37.template;
4477
4477
  };
4478
4478
  function Chalk(options) {
4479
4479
  return chalkFactory(options);
@@ -4584,7 +4584,7 @@ var require_source = __commonJS({
4584
4584
  return openAll + string + closeAll;
4585
4585
  };
4586
4586
  var template;
4587
- var chalkTag = (chalk35, ...strings) => {
4587
+ var chalkTag = (chalk37, ...strings) => {
4588
4588
  const [firstString] = strings;
4589
4589
  if (!isArray(firstString) || !isArray(firstString.raw)) {
4590
4590
  return strings.join(" ");
@@ -4600,14 +4600,14 @@ var require_source = __commonJS({
4600
4600
  if (template === void 0) {
4601
4601
  template = require_templates();
4602
4602
  }
4603
- return template(chalk35, parts.join(""));
4603
+ return template(chalk37, parts.join(""));
4604
4604
  };
4605
4605
  Object.defineProperties(Chalk.prototype, styles);
4606
- var chalk34 = Chalk();
4607
- chalk34.supportsColor = stdoutColor;
4608
- chalk34.stderr = Chalk({ level: stderrColor ? stderrColor.level : 0 });
4609
- chalk34.stderr.supportsColor = stderrColor;
4610
- module2.exports = chalk34;
4606
+ var chalk36 = Chalk();
4607
+ chalk36.supportsColor = stdoutColor;
4608
+ chalk36.stderr = Chalk({ level: stderrColor ? stderrColor.level : 0 });
4609
+ chalk36.stderr.supportsColor = stderrColor;
4610
+ module2.exports = chalk36;
4611
4611
  }
4612
4612
  });
4613
4613
 
@@ -4990,11 +4990,11 @@ var init_config = __esm({
4990
4990
  var require_is_docker = __commonJS({
4991
4991
  "node_modules/is-docker/index.js"(exports2, module2) {
4992
4992
  "use strict";
4993
- var fs30 = require("fs");
4993
+ var fs31 = require("fs");
4994
4994
  var isDocker;
4995
4995
  function hasDockerEnv() {
4996
4996
  try {
4997
- fs30.statSync("/.dockerenv");
4997
+ fs31.statSync("/.dockerenv");
4998
4998
  return true;
4999
4999
  } catch (_2) {
5000
5000
  return false;
@@ -5002,7 +5002,7 @@ var require_is_docker = __commonJS({
5002
5002
  }
5003
5003
  function hasDockerCGroup() {
5004
5004
  try {
5005
- return fs30.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
5005
+ return fs31.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
5006
5006
  } catch (_2) {
5007
5007
  return false;
5008
5008
  }
@@ -5020,21 +5020,21 @@ var require_is_docker = __commonJS({
5020
5020
  var require_is_wsl = __commonJS({
5021
5021
  "node_modules/is-wsl/index.js"(exports2, module2) {
5022
5022
  "use strict";
5023
- var os13 = require("os");
5024
- var fs30 = require("fs");
5023
+ var os15 = require("os");
5024
+ var fs31 = require("fs");
5025
5025
  var isDocker = require_is_docker();
5026
5026
  var isWsl = () => {
5027
5027
  if (process.platform !== "linux") {
5028
5028
  return false;
5029
5029
  }
5030
- if (os13.release().toLowerCase().includes("microsoft")) {
5030
+ if (os15.release().toLowerCase().includes("microsoft")) {
5031
5031
  if (isDocker()) {
5032
5032
  return false;
5033
5033
  }
5034
5034
  return true;
5035
5035
  }
5036
5036
  try {
5037
- return fs30.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isDocker() : false;
5037
+ return fs31.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isDocker() : false;
5038
5038
  } catch (_2) {
5039
5039
  return false;
5040
5040
  }
@@ -5073,17 +5073,17 @@ var require_define_lazy_prop = __commonJS({
5073
5073
  // node_modules/open/index.js
5074
5074
  var require_open = __commonJS({
5075
5075
  "node_modules/open/index.js"(exports2, module2) {
5076
- var path27 = require("path");
5076
+ var path28 = require("path");
5077
5077
  var childProcess = require("child_process");
5078
- var { promises: fs30, constants: fsConstants } = require("fs");
5078
+ var { promises: fs31, constants: fsConstants } = require("fs");
5079
5079
  var isWsl = require_is_wsl();
5080
5080
  var isDocker = require_is_docker();
5081
5081
  var defineLazyProperty = require_define_lazy_prop();
5082
- var localXdgOpenPath = path27.join(__dirname, "xdg-open");
5082
+ var localXdgOpenPath = path28.join(__dirname, "xdg-open");
5083
5083
  var { platform, arch } = process;
5084
5084
  var hasContainerEnv = () => {
5085
5085
  try {
5086
- fs30.statSync("/run/.containerenv");
5086
+ fs31.statSync("/run/.containerenv");
5087
5087
  return true;
5088
5088
  } catch {
5089
5089
  return false;
@@ -5106,14 +5106,14 @@ var require_open = __commonJS({
5106
5106
  const configFilePath = "/etc/wsl.conf";
5107
5107
  let isConfigFileExists = false;
5108
5108
  try {
5109
- await fs30.access(configFilePath, fsConstants.F_OK);
5109
+ await fs31.access(configFilePath, fsConstants.F_OK);
5110
5110
  isConfigFileExists = true;
5111
5111
  } catch {
5112
5112
  }
5113
5113
  if (!isConfigFileExists) {
5114
5114
  return defaultMountPoint;
5115
5115
  }
5116
- const configContent = await fs30.readFile(configFilePath, { encoding: "utf8" });
5116
+ const configContent = await fs31.readFile(configFilePath, { encoding: "utf8" });
5117
5117
  const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
5118
5118
  if (!configMountPoint) {
5119
5119
  return defaultMountPoint;
@@ -5213,7 +5213,7 @@ var require_open = __commonJS({
5213
5213
  const isBundled = !__dirname || __dirname === "/";
5214
5214
  let exeLocalXdgOpen = false;
5215
5215
  try {
5216
- await fs30.access(localXdgOpenPath, fsConstants.X_OK);
5216
+ await fs31.access(localXdgOpenPath, fsConstants.X_OK);
5217
5217
  exeLocalXdgOpen = true;
5218
5218
  } catch {
5219
5219
  }
@@ -5236,14 +5236,14 @@ var require_open = __commonJS({
5236
5236
  }
5237
5237
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
5238
5238
  if (options.wait) {
5239
- return new Promise((resolve15, reject) => {
5239
+ return new Promise((resolve16, reject) => {
5240
5240
  subprocess.once("error", reject);
5241
5241
  subprocess.once("close", (exitCode) => {
5242
5242
  if (!options.allowNonzeroExitCode && exitCode > 0) {
5243
5243
  reject(new Error(`Exited with code ${exitCode}`));
5244
5244
  return;
5245
5245
  }
5246
- resolve15(subprocess);
5246
+ resolve16(subprocess);
5247
5247
  });
5248
5248
  });
5249
5249
  }
@@ -5459,16 +5459,16 @@ function compareSemver(a, b) {
5459
5459
  return 0;
5460
5460
  }
5461
5461
  function fetchLatestNpmVersion(timeoutMs = 8e3) {
5462
- return new Promise((resolve15) => {
5462
+ return new Promise((resolve16) => {
5463
5463
  (0, import_child_process.execFile)(
5464
5464
  "npm",
5465
5465
  ["view", "@holdyourvoice/hyv", "version"],
5466
5466
  { timeout: timeoutMs, encoding: "utf-8" },
5467
5467
  (err, stdout) => {
5468
5468
  if (err || !stdout?.trim())
5469
- resolve15(null);
5469
+ resolve16(null);
5470
5470
  else
5471
- resolve15(stdout.trim());
5471
+ resolve16(stdout.trim());
5472
5472
  }
5473
5473
  );
5474
5474
  });
@@ -5533,7 +5533,7 @@ function escapeHtml(value) {
5533
5533
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
5534
5534
  }
5535
5535
  function request(url, options = {}) {
5536
- return new Promise((resolve15, reject) => {
5536
+ return new Promise((resolve16, reject) => {
5537
5537
  const urlObj = new URL(url);
5538
5538
  const isHttps = urlObj.protocol === "https:";
5539
5539
  const client = isHttps ? https : http;
@@ -5554,9 +5554,9 @@ function request(url, options = {}) {
5554
5554
  res.on("data", (chunk) => data += chunk);
5555
5555
  res.on("end", () => {
5556
5556
  try {
5557
- resolve15({ status: res.statusCode || 0, data: JSON.parse(data) });
5557
+ resolve16({ status: res.statusCode || 0, data: JSON.parse(data) });
5558
5558
  } catch {
5559
- resolve15({ status: res.statusCode || 0, data });
5559
+ resolve16({ status: res.statusCode || 0, data });
5560
5560
  }
5561
5561
  });
5562
5562
  });
@@ -5614,9 +5614,9 @@ async function authenticateWithLicense(licenseKey) {
5614
5614
  }
5615
5615
  async function authenticateWithBrowser() {
5616
5616
  const server = http.createServer();
5617
- const port = await new Promise((resolve15) => {
5617
+ const port = await new Promise((resolve16) => {
5618
5618
  server.listen(0, "127.0.0.1", () => {
5619
- resolve15(server.address().port);
5619
+ resolve16(server.address().port);
5620
5620
  });
5621
5621
  });
5622
5622
  const redirectUri = `http://127.0.0.1:${port}/callback`;
@@ -5635,7 +5635,7 @@ async function authenticateWithBrowser() {
5635
5635
  }
5636
5636
  console.log(import_chalk2.default.cyan("\nOpening browser for authentication..."));
5637
5637
  await (0, import_open.default)(assertSafeOAuthUrl(auth_url));
5638
- const authData = await new Promise((resolve15, reject) => {
5638
+ const authData = await new Promise((resolve16, reject) => {
5639
5639
  const timeout = setTimeout(() => {
5640
5640
  server.close();
5641
5641
  reject(new Error("Authentication timeout. Please try again."));
@@ -5692,7 +5692,7 @@ async function authenticateWithBrowser() {
5692
5692
  `);
5693
5693
  clearTimeout(timeout);
5694
5694
  server.close();
5695
- resolve15(data);
5695
+ resolve16(data);
5696
5696
  } catch (error) {
5697
5697
  res.writeHead(500, { "Content-Type": "text/html" });
5698
5698
  res.end(`<h1>Authentication failed</h1><p>${escapeHtml(error.message)}</p>`);
@@ -5854,17 +5854,11 @@ var init_telemetry = __esm({
5854
5854
  });
5855
5855
 
5856
5856
  // src/lib/api.ts
5857
- var api_exports = {};
5858
- __export(api_exports, {
5859
- apiGet: () => apiGet,
5860
- apiPost: () => apiPost,
5861
- requireSubscription: () => requireSubscription
5862
- });
5863
- async function request2(method, path27, body) {
5857
+ async function request2(method, path28, body) {
5864
5858
  const token = await getValidToken();
5865
5859
  if (!token)
5866
5860
  throw new Error("you're not signed in yet. run: hyv init");
5867
- const url = `${API_BASE}${path27}`;
5861
+ const url = `${API_BASE}${path28}`;
5868
5862
  const opts = {
5869
5863
  method,
5870
5864
  headers: {
@@ -5889,15 +5883,11 @@ async function request2(method, path27, body) {
5889
5883
  }
5890
5884
  return res.json();
5891
5885
  }
5892
- function apiGet(path27) {
5893
- return request2("GET", path27);
5894
- }
5895
- function apiPost(path27, body) {
5896
- return request2("POST", path27, body);
5886
+ function apiGet(path28) {
5887
+ return request2("GET", path28);
5897
5888
  }
5898
- async function requireSubscription() {
5899
- const { requirePaidFeature: requirePaidFeature2 } = await Promise.resolve().then(() => (init_access(), access_exports));
5900
- await requirePaidFeature2("profiles");
5889
+ function apiPost(path28, body) {
5890
+ return request2("POST", path28, body);
5901
5891
  }
5902
5892
  var init_api = __esm({
5903
5893
  "src/lib/api.ts"() {
@@ -5907,130 +5897,6 @@ var init_api = __esm({
5907
5897
  }
5908
5898
  });
5909
5899
 
5910
- // src/lib/access.ts
5911
- var access_exports = {};
5912
- __export(access_exports, {
5913
- formatModeLabel: () => formatModeLabel,
5914
- getAccessState: () => getAccessState,
5915
- isLocalOnlyMode: () => isLocalOnlyMode,
5916
- maybeShowLimitedModeHint: () => maybeShowLimitedModeHint,
5917
- requirePaidFeature: () => requirePaidFeature,
5918
- setLocalOnlyMode: () => setLocalOnlyMode
5919
- });
5920
- function setLocalOnlyMode(enabled) {
5921
- localOnlyOverride = enabled;
5922
- }
5923
- function isLocalOnlyMode() {
5924
- if (localOnlyOverride)
5925
- return true;
5926
- const env = process.env.HYV_LOCAL_ONLY;
5927
- return env === "1" || env === "true";
5928
- }
5929
- async function getAccessState() {
5930
- if (isLocalOnlyMode()) {
5931
- return { authenticated: false, hasPaidPlan: false, plan: "local", localOnly: true };
5932
- }
5933
- const now = Date.now();
5934
- if (cachedAccess && now - cachedAccess.at < ACCESS_CACHE_MS) {
5935
- return cachedAccess.state;
5936
- }
5937
- const token = getToken();
5938
- if (!token) {
5939
- const state = { authenticated: false, hasPaidPlan: false, plan: "none", localOnly: false };
5940
- cachedAccess = { state, at: now };
5941
- return state;
5942
- }
5943
- try {
5944
- const session = await checkSession();
5945
- const plan = (session.plan || "none").toLowerCase();
5946
- const subStatus = String(session.subscription_status || "").toLowerCase();
5947
- const activeSubscription = !subStatus || ["active", "past_due", "trialing"].includes(subStatus);
5948
- const hasPaidPlan = session.valid && activeSubscription && plan !== "none" && plan !== "free" && plan !== "expired" && plan !== "unknown" && plan !== "pending";
5949
- const state = {
5950
- authenticated: session.valid,
5951
- hasPaidPlan,
5952
- plan: session.plan || "none",
5953
- localOnly: false
5954
- };
5955
- cachedAccess = { state, at: now };
5956
- return state;
5957
- } catch {
5958
- const state = { authenticated: !!token, hasPaidPlan: false, plan: "unknown", localOnly: false };
5959
- cachedAccess = { state, at: now };
5960
- return state;
5961
- }
5962
- }
5963
- async function requirePaidFeature(feature) {
5964
- if (isLocalOnlyMode()) {
5965
- throw new Error(
5966
- `${FEATURE_MESSAGES[feature]} (local-only mode is on \u2014 unset HYV_LOCAL_ONLY or remove --local-only)`
5967
- );
5968
- }
5969
- const token = getToken();
5970
- if (!token) {
5971
- throw new Error(`you're not signed in yet. run: hyv init \u2014 then ${FEATURE_MESSAGES[feature]}`);
5972
- }
5973
- let data;
5974
- try {
5975
- data = await apiGet("/cli/heartbeat");
5976
- } catch (err) {
5977
- const msg = err.message || "";
5978
- if (msg.includes("not signed in") || msg.includes("session expired") || msg.includes("don't have access")) {
5979
- throw err;
5980
- }
5981
- throw new Error("can't reach the server. check your internet connection and try again.");
5982
- }
5983
- const plan = (data.plan || "none").toLowerCase();
5984
- const subStatus = String(data.subscription_status || data.status || "").toLowerCase();
5985
- if (!data.plan || plan === "none" || plan === "free" || plan === "expired" || subStatus === "trialing" || subStatus === "none") {
5986
- throw new Error(FEATURE_MESSAGES[feature]);
5987
- }
5988
- }
5989
- async function maybeShowLimitedModeHint(hasProfile) {
5990
- if (isLocalOnlyMode())
5991
- return;
5992
- const access = await getAccessState();
5993
- if (access.hasPaidPlan)
5994
- return;
5995
- if (hasProfile) {
5996
- console.log(import_chalk5.default.dim("\n using cached profile (local). sync for latest: hyv sync"));
5997
- } else if (!access.authenticated) {
5998
- console.log(import_chalk5.default.dim("\n local mode \u2014 free scan engine. profiles + learning: hyv init"));
5999
- } else {
6000
- console.log(import_chalk5.default.dim("\n local mode \u2014 upgrade for full profiles + learning: hyv upgrade"));
6001
- }
6002
- }
6003
- function formatModeLabel(access, hasFullProfile) {
6004
- if (access.localOnly)
6005
- return "local-only (forced)";
6006
- if (access.hasPaidPlan && hasFullProfile)
6007
- return "full profile (paid)";
6008
- if (hasFullProfile)
6009
- return "cached profile (local)";
6010
- if (access.authenticated)
6011
- return "local engine (free)";
6012
- return "local engine (free, not signed in)";
6013
- }
6014
- var import_chalk5, FEATURE_MESSAGES, localOnlyOverride, cachedAccess, ACCESS_CACHE_MS;
6015
- var init_access = __esm({
6016
- "src/lib/access.ts"() {
6017
- "use strict";
6018
- import_chalk5 = __toESM(require_source());
6019
- init_config();
6020
- init_auth();
6021
- init_api();
6022
- FEATURE_MESSAGES = {
6023
- profiles: "syncing voice profiles from your account requires a paid plan. run: hyv upgrade",
6024
- learning: "the learning loop (reinforce, add) requires a paid plan. run: hyv upgrade",
6025
- premiumPrompts: "rich profile-aware rewrite prompts require a paid plan. run: hyv upgrade",
6026
- serverAnalysis: "server-assisted analysis requires a paid plan. run: hyv upgrade"
6027
- };
6028
- localOnlyOverride = false;
6029
- cachedAccess = null;
6030
- ACCESS_CACHE_MS = 3e4;
6031
- }
6032
- });
6033
-
6034
5900
  // src/lib/profile.ts
6035
5901
  async function loadFullProfile(slug, opts = {}) {
6036
5902
  const includeSamples = opts.includeSamples !== false;
@@ -6242,8 +6108,12 @@ function countLearnedPatterns(slug) {
6242
6108
  async function loadProfileForCommand(name, opts = {}) {
6243
6109
  const config = readConfig();
6244
6110
  const candidates = [];
6245
- if (name)
6111
+ if (name) {
6246
6112
  candidates.push(name);
6113
+ const normalized = toSafeProfileCacheKey(name);
6114
+ if (normalized !== name)
6115
+ candidates.push(normalized);
6116
+ }
6247
6117
  if (config.default_profile)
6248
6118
  candidates.push(config.default_profile);
6249
6119
  if (config.profile)
@@ -6294,6 +6164,250 @@ var init_local_profile = __esm({
6294
6164
  }
6295
6165
  });
6296
6166
 
6167
+ // src/lib/mcp-profile-hydrate.ts
6168
+ var mcp_profile_hydrate_exports = {};
6169
+ __export(mcp_profile_hydrate_exports, {
6170
+ ensureMcpProfilesHydrated: () => ensureMcpProfilesHydrated,
6171
+ formatMcpProfilesList: () => formatMcpProfilesList,
6172
+ normalizeProfileSlug: () => normalizeProfileSlug
6173
+ });
6174
+ function normalizeProfileSlug(name) {
6175
+ return toSafeProfileCacheKey(name);
6176
+ }
6177
+ async function ensureMcpProfilesHydrated(opts = {}) {
6178
+ if (process.env.VITEST) {
6179
+ return { ok: true, synced: [], skipped: true };
6180
+ }
6181
+ if (!getToken()) {
6182
+ return { ok: true, synced: [], skipped: true };
6183
+ }
6184
+ const now = Date.now();
6185
+ if (!opts.force && now - lastHydrateAt < HYDRATE_TTL_MS) {
6186
+ return { ok: true, synced: [], skipped: true };
6187
+ }
6188
+ if (hydrateInFlight && !opts.force) {
6189
+ return hydrateInFlight;
6190
+ }
6191
+ hydrateInFlight = runHydrate().then((result) => {
6192
+ lastHydrateAt = Date.now();
6193
+ return result;
6194
+ }).finally(() => {
6195
+ hydrateInFlight = null;
6196
+ });
6197
+ return hydrateInFlight;
6198
+ }
6199
+ async function runHydrate() {
6200
+ const synced = [];
6201
+ try {
6202
+ const data = await apiGet("/cli/profiles");
6203
+ const profiles = data.profiles || [];
6204
+ if (profiles.length === 0) {
6205
+ return { ok: true, synced: [] };
6206
+ }
6207
+ let defaultSlug;
6208
+ for (const row of profiles) {
6209
+ const slug = normalizeProfileSlug(row.slug || row.name);
6210
+ if (row.is_default)
6211
+ defaultSlug = slug;
6212
+ try {
6213
+ const detail = await apiGet(`/cli/profiles/${encodeURIComponent(slug)}`);
6214
+ const content = (detail.content || "").trim();
6215
+ if (content) {
6216
+ writeCachedProfile(slug, content);
6217
+ if (!synced.includes(slug))
6218
+ synced.push(slug);
6219
+ }
6220
+ await loadFullProfile(slug, {
6221
+ forceRefresh: true,
6222
+ serverUpdatedAt: row.updated_at || detail.updated_at
6223
+ });
6224
+ } catch {
6225
+ }
6226
+ }
6227
+ const config = readConfig();
6228
+ const localNames = /* @__PURE__ */ new Set([...listCachedProfiles(), ...listDiskCachedProfiles()]);
6229
+ const shouldSetDefault = defaultSlug && (!config.default_profile || !localNames.has(config.default_profile));
6230
+ if (shouldSetDefault && defaultSlug) {
6231
+ writeConfig({ ...config, default_profile: defaultSlug, profile: defaultSlug });
6232
+ }
6233
+ return { ok: true, synced, defaultProfile: defaultSlug || config.default_profile };
6234
+ } catch (err) {
6235
+ const message = err instanceof Error ? err.message : "profile sync failed";
6236
+ return { ok: false, synced, error: message };
6237
+ }
6238
+ }
6239
+ function formatMcpProfilesList(hydrate) {
6240
+ const config = readConfig();
6241
+ const local = [.../* @__PURE__ */ new Set([...listCachedProfiles(), ...listDiskCachedProfiles()])].sort();
6242
+ const active = config.default_profile || config.profile;
6243
+ const lines = ["### Voice profiles (MCP-ready)"];
6244
+ if (active && local.includes(active)) {
6245
+ lines.push(`Active default: **${active}** \u2014 hyv_scan / hyv_rewrite / hyv_clean use this unless you pass \`profile\`.`);
6246
+ } else if (local.length === 1) {
6247
+ lines.push(`Active default: **${local[0]}** (only local profile).`);
6248
+ } else if (local.length > 1) {
6249
+ lines.push("No default set \u2014 pass `profile` on tools, or run `hyv init` + create a default in the dashboard.");
6250
+ }
6251
+ if (local.length > 0) {
6252
+ lines.push("");
6253
+ lines.push("Local (ready for MCP tools now):");
6254
+ for (const name of local) {
6255
+ const mark = name === active ? " (default)" : "";
6256
+ lines.push(` \u2022 ${name}${mark}`);
6257
+ }
6258
+ } else {
6259
+ lines.push("");
6260
+ lines.push("No local profiles yet.");
6261
+ }
6262
+ if (!getToken()) {
6263
+ lines.push("");
6264
+ lines.push("Account profiles (dashboard / web): run **`hyv init`** once on this machine \u2014 MCP will auto-download them here.");
6265
+ lines.push("Terminal welcome (`hyv welcome`) saves locally immediately; no init needed for that path.");
6266
+ return lines.join("\n");
6267
+ }
6268
+ if (hydrate?.synced?.length) {
6269
+ lines.push("");
6270
+ lines.push(`Just synced from your account: ${hydrate.synced.join(", ")}`);
6271
+ } else if (hydrate?.error) {
6272
+ lines.push("");
6273
+ lines.push(`Account sync note: ${hydrate.error}`);
6274
+ } else if (local.length === 0 && hydrate?.skipped) {
6275
+ lines.push("");
6276
+ lines.push("Signed in \u2014 checking account\u2026 if profiles exist on holdyourvoice.com, they load automatically.");
6277
+ }
6278
+ lines.push("");
6279
+ lines.push("Same profile everywhere: build in **dashboard** or **`hyv welcome`**, then use MCP tools with no extra setup (after `hyv init` for dashboard-only profiles).");
6280
+ return lines.join("\n");
6281
+ }
6282
+ var lastHydrateAt, hydrateInFlight, HYDRATE_TTL_MS;
6283
+ var init_mcp_profile_hydrate = __esm({
6284
+ "src/lib/mcp-profile-hydrate.ts"() {
6285
+ "use strict";
6286
+ init_config();
6287
+ init_api();
6288
+ init_profile();
6289
+ init_local_profile();
6290
+ lastHydrateAt = 0;
6291
+ hydrateInFlight = null;
6292
+ HYDRATE_TTL_MS = 5 * 60 * 1e3;
6293
+ }
6294
+ });
6295
+
6296
+ // src/lib/access.ts
6297
+ function setLocalOnlyMode(enabled) {
6298
+ localOnlyOverride = enabled;
6299
+ }
6300
+ function isLocalOnlyMode() {
6301
+ if (localOnlyOverride)
6302
+ return true;
6303
+ const env = process.env.HYV_LOCAL_ONLY;
6304
+ return env === "1" || env === "true";
6305
+ }
6306
+ async function getAccessState() {
6307
+ if (isLocalOnlyMode()) {
6308
+ return { authenticated: false, hasPaidPlan: false, plan: "local", localOnly: true };
6309
+ }
6310
+ const now = Date.now();
6311
+ if (cachedAccess && now - cachedAccess.at < ACCESS_CACHE_MS) {
6312
+ return cachedAccess.state;
6313
+ }
6314
+ const token = getToken();
6315
+ if (!token) {
6316
+ const state = { authenticated: false, hasPaidPlan: false, plan: "none", localOnly: false };
6317
+ cachedAccess = { state, at: now };
6318
+ return state;
6319
+ }
6320
+ try {
6321
+ const session = await checkSession();
6322
+ const plan = (session.plan || "none").toLowerCase();
6323
+ const subStatus = String(session.subscription_status || "").toLowerCase();
6324
+ const activeSubscription = !subStatus || ["active", "past_due", "trialing"].includes(subStatus);
6325
+ const hasPaidPlan = session.valid && activeSubscription && plan !== "none" && plan !== "free" && plan !== "expired" && plan !== "unknown" && plan !== "pending";
6326
+ const state = {
6327
+ authenticated: session.valid,
6328
+ hasPaidPlan,
6329
+ plan: session.plan || "none",
6330
+ localOnly: false
6331
+ };
6332
+ cachedAccess = { state, at: now };
6333
+ return state;
6334
+ } catch {
6335
+ const state = { authenticated: !!token, hasPaidPlan: false, plan: "unknown", localOnly: false };
6336
+ cachedAccess = { state, at: now };
6337
+ return state;
6338
+ }
6339
+ }
6340
+ async function requirePaidFeature(feature) {
6341
+ if (isLocalOnlyMode()) {
6342
+ throw new Error(
6343
+ `${FEATURE_MESSAGES[feature]} (local-only mode is on \u2014 unset HYV_LOCAL_ONLY or remove --local-only)`
6344
+ );
6345
+ }
6346
+ const token = getToken();
6347
+ if (!token) {
6348
+ throw new Error(`you're not signed in yet. run: hyv init \u2014 then ${FEATURE_MESSAGES[feature]}`);
6349
+ }
6350
+ let data;
6351
+ try {
6352
+ data = await apiGet("/cli/heartbeat");
6353
+ } catch (err) {
6354
+ const msg = err.message || "";
6355
+ if (msg.includes("not signed in") || msg.includes("session expired") || msg.includes("don't have access")) {
6356
+ throw err;
6357
+ }
6358
+ throw new Error("can't reach the server. check your internet connection and try again.");
6359
+ }
6360
+ const plan = (data.plan || "none").toLowerCase();
6361
+ const subStatus = String(data.subscription_status || data.status || "").toLowerCase();
6362
+ if (!data.plan || plan === "none" || plan === "free" || plan === "expired" || subStatus === "trialing" || subStatus === "none") {
6363
+ throw new Error(FEATURE_MESSAGES[feature]);
6364
+ }
6365
+ }
6366
+ async function maybeShowLimitedModeHint(hasProfile) {
6367
+ if (isLocalOnlyMode())
6368
+ return;
6369
+ const access = await getAccessState();
6370
+ if (access.hasPaidPlan)
6371
+ return;
6372
+ if (hasProfile) {
6373
+ console.log(import_chalk5.default.dim("\n using cached profile (local). sync for latest: hyv sync"));
6374
+ } else if (!access.authenticated) {
6375
+ console.log(import_chalk5.default.dim("\n local mode \u2014 free scan engine. profiles + learning: hyv init"));
6376
+ } else {
6377
+ console.log(import_chalk5.default.dim("\n local mode \u2014 upgrade for full profiles + learning: hyv upgrade"));
6378
+ }
6379
+ }
6380
+ function formatModeLabel(access, hasFullProfile) {
6381
+ if (access.localOnly)
6382
+ return "local-only (forced)";
6383
+ if (access.hasPaidPlan && hasFullProfile)
6384
+ return "full profile (paid)";
6385
+ if (hasFullProfile)
6386
+ return "cached profile (local)";
6387
+ if (access.authenticated)
6388
+ return "local engine (free)";
6389
+ return "local engine (free, not signed in)";
6390
+ }
6391
+ var import_chalk5, FEATURE_MESSAGES, localOnlyOverride, cachedAccess, ACCESS_CACHE_MS;
6392
+ var init_access = __esm({
6393
+ "src/lib/access.ts"() {
6394
+ "use strict";
6395
+ import_chalk5 = __toESM(require_source());
6396
+ init_config();
6397
+ init_auth();
6398
+ init_api();
6399
+ FEATURE_MESSAGES = {
6400
+ profiles: "syncing voice profiles from your account requires a paid plan. run: hyv upgrade",
6401
+ learning: "the learning loop (reinforce, add) requires a paid plan. run: hyv upgrade",
6402
+ premiumPrompts: "rich profile-aware rewrite prompts require a paid plan. run: hyv upgrade",
6403
+ serverAnalysis: "server-assisted analysis requires a paid plan. run: hyv upgrade"
6404
+ };
6405
+ localOnlyOverride = false;
6406
+ cachedAccess = null;
6407
+ ACCESS_CACHE_MS = 3e4;
6408
+ }
6409
+ });
6410
+
6297
6411
  // src/lib/profile-parse.ts
6298
6412
  function parseAnchorsFromBody(body) {
6299
6413
  const anchors = [];
@@ -7432,7 +7546,7 @@ function ps(n7) {
7432
7546
  return n7.replace(as, fe).replace(ls, ue).replace(cs, qt).replace(fs10, de).replace(us, pe);
7433
7547
  }
7434
7548
  function ms(n7) {
7435
- return n7.replace(is, "\\").replace(rs, "{").replace(ns, "}").replace(os6, ",").replace(hs, ".");
7549
+ return n7.replace(is, "\\").replace(rs, "{").replace(ns, "}").replace(os7, ",").replace(hs, ".");
7436
7550
  }
7437
7551
  function me(n7) {
7438
7552
  if (!n7)
@@ -7532,7 +7646,7 @@ function Ut(n7, t = {}) {
7532
7646
  function es(n7, t = {}) {
7533
7647
  return new I(n7, t).iterate();
7534
7648
  }
7535
- var import_node_url, import_node_path, import_node_url2, import_fs, xi, import_promises, import_node_events, import_node_stream, import_node_string_decoder, Gt, ce, ss, fe, ue, qt, de, pe, is, rs, ns, os6, hs, as, ls, cs, fs10, us, ds, at, Ss, lt, Es, we, ye, W, xs, be, vs, Ct, Cs, Ts, As, ks, Kt, Se, Ee, Q, tt, O, Rs, Os, Fs, Ds, Ms, Ns, _s, Ls, Ws, Ps, js, Is, zs, Bs, Us, $s, Gs, Hs, Ce, Te, Ae, xe, qs, A, Ks, Vs, Ys, Xs, Js, N, Zs, ke, Qs, ti, ve, ei, D, si, Oe, Vt, Fe, At, Re, ii, q, De, Tt, ri, ft, Ne, oi, hi, ai, G, H, K, kt, ut, Rt, _e, Ot, Le, P, et, v, dt, st, C, F, T, Yt, Ft, k, x, Xt, Jt, We, Zt, B, Qt, Dt, pt, Y, M, mt, li, ci, fi, ui, Mt, te, di, pi, V, vi, wt, Ue, $e, Ri, Oi, L, Ge, He, U, qe, Ke, X, Ve, _, gt, se, je, yt, j, Nt, Lt, Ie, Fi, ie, ze, bt, Be, _t, Wt, ne, Ye, R, Pt, jt, It, it, rt, St, Cr, Xe, Di, Mi, Ni, nt, _i, ot, oe, he, ae, Et, Li, zt, xt, vt, Pi, I, le, ji, Ii, zi, Bi, Ui, Ze;
7649
+ var import_node_url, import_node_path, import_node_url2, import_fs, xi, import_promises, import_node_events, import_node_stream, import_node_string_decoder, Gt, ce, ss, fe, ue, qt, de, pe, is, rs, ns, os7, hs, as, ls, cs, fs10, us, ds, at, Ss, lt, Es, we, ye, W, xs, be, vs, Ct, Cs, Ts, As, ks, Kt, Se, Ee, Q, tt, O, Rs, Os, Fs, Ds, Ms, Ns, _s, Ls, Ws, Ps, js, Is, zs, Bs, Us, $s, Gs, Hs, Ce, Te, Ae, xe, qs, A, Ks, Vs, Ys, Xs, Js, N, Zs, ke, Qs, ti, ve, ei, D, si, Oe, Vt, Fe, At, Re, ii, q, De, Tt, ri, ft, Ne, oi, hi, ai, G, H, K, kt, ut, Rt, _e, Ot, Le, P, et, v, dt, st, C, F, T, Yt, Ft, k, x, Xt, Jt, We, Zt, B, Qt, Dt, pt, Y, M, mt, li, ci, fi, ui, Mt, te, di, pi, V, vi, wt, Ue, $e, Ri, Oi, L, Ge, He, U, qe, Ke, X, Ve, _, gt, se, je, yt, j, Nt, Lt, Ie, Fi, ie, ze, bt, Be, _t, Wt, ne, Ye, R, Pt, jt, It, it, rt, St, Cr, Xe, Di, Mi, Ni, nt, _i, ot, oe, he, ae, Et, Li, zt, xt, vt, Pi, I, le, ji, Ii, zi, Bi, Ui, Ze;
7536
7650
  var init_index_min = __esm({
7537
7651
  "node_modules/glob/dist/esm/index.min.js"() {
7538
7652
  import_node_url = require("node:url");
@@ -7579,7 +7693,7 @@ var init_index_min = __esm({
7579
7693
  is = new RegExp(fe, "g");
7580
7694
  rs = new RegExp(ue, "g");
7581
7695
  ns = new RegExp(qt, "g");
7582
- os6 = new RegExp(de, "g");
7696
+ os7 = new RegExp(de, "g");
7583
7697
  hs = new RegExp(pe, "g");
7584
7698
  as = /\\\\/g;
7585
7699
  ls = /\\{/g;
@@ -10740,18 +10854,18 @@ function stripXmlText(xml) {
10740
10854
  }
10741
10855
  function commandExists(cmd) {
10742
10856
  try {
10743
- (0, import_child_process2.execFileSync)("which", [cmd], { stdio: "ignore" });
10857
+ (0, import_child_process3.execFileSync)("which", [cmd], { stdio: "ignore" });
10744
10858
  return true;
10745
10859
  } catch {
10746
10860
  return false;
10747
10861
  }
10748
10862
  }
10749
10863
  function unzipList(filePath) {
10750
- const out = (0, import_child_process2.execFileSync)("unzip", ["-Z1", filePath], { encoding: "utf-8", maxBuffer: 5e6 });
10864
+ const out = (0, import_child_process3.execFileSync)("unzip", ["-Z1", filePath], { encoding: "utf-8", maxBuffer: 5e6 });
10751
10865
  return out.split("\n").map((l) => l.trim()).filter(Boolean);
10752
10866
  }
10753
10867
  function unzipExtract(filePath, entry) {
10754
- return (0, import_child_process2.execFileSync)("unzip", ["-p", filePath, entry], {
10868
+ return (0, import_child_process3.execFileSync)("unzip", ["-p", filePath, entry], {
10755
10869
  encoding: "utf-8",
10756
10870
  maxBuffer: 1e7
10757
10871
  });
@@ -10759,7 +10873,7 @@ function unzipExtract(filePath, entry) {
10759
10873
  function extractDocx(filePath) {
10760
10874
  if (process.platform === "darwin") {
10761
10875
  try {
10762
- const out = (0, import_child_process2.execFileSync)("textutil", ["-convert", "txt", "-stdout", filePath], {
10876
+ const out = (0, import_child_process3.execFileSync)("textutil", ["-convert", "txt", "-stdout", filePath], {
10763
10877
  encoding: "utf-8",
10764
10878
  maxBuffer: 1e7
10765
10879
  });
@@ -10802,7 +10916,7 @@ function extractPdfRaw(buffer) {
10802
10916
  function extractPdf(filePath) {
10803
10917
  if (process.platform === "darwin") {
10804
10918
  try {
10805
- const out = (0, import_child_process2.execFileSync)("textutil", ["-convert", "txt", "-stdout", filePath], {
10919
+ const out = (0, import_child_process3.execFileSync)("textutil", ["-convert", "txt", "-stdout", filePath], {
10806
10920
  encoding: "utf-8",
10807
10921
  maxBuffer: 1e7
10808
10922
  });
@@ -10812,7 +10926,7 @@ function extractPdf(filePath) {
10812
10926
  }
10813
10927
  }
10814
10928
  if (commandExists("pdftotext")) {
10815
- const out = (0, import_child_process2.execFileSync)("pdftotext", ["-layout", "-enc", "UTF-8", filePath, "-"], {
10929
+ const out = (0, import_child_process3.execFileSync)("pdftotext", ["-layout", "-enc", "UTF-8", filePath, "-"], {
10816
10930
  encoding: "utf-8",
10817
10931
  maxBuffer: 1e7
10818
10932
  });
@@ -10877,7 +10991,7 @@ function listDocumentsInDir(dirPath) {
10877
10991
  }).filter(isSupportedDocument);
10878
10992
  }
10879
10993
  function collectDocumentsFromPath(inputPath) {
10880
- const resolved = path10.resolve(inputPath.trim().replace(/^~(?=$|\/)/, os7.homedir()));
10994
+ const resolved = path10.resolve(inputPath.trim().replace(/^~(?=$|\/)/, os8.homedir()));
10881
10995
  if (!fs11.existsSync(resolved)) {
10882
10996
  throw new Error(`path not found: ${resolved}`);
10883
10997
  }
@@ -10908,19 +11022,19 @@ function readDraftInput(input) {
10908
11022
  const trimmed = input.trim();
10909
11023
  if (!trimmed)
10910
11024
  throw new Error("empty draft");
10911
- const maybePath = path10.resolve(trimmed.replace(/^~(?=$|\/)/, os7.homedir()));
11025
+ const maybePath = path10.resolve(trimmed.replace(/^~(?=$|\/)/, os8.homedir()));
10912
11026
  if (fs11.existsSync(maybePath) && fs11.statSync(maybePath).isFile()) {
10913
11027
  return { text: extractTextFromFile(maybePath), source: maybePath };
10914
11028
  }
10915
11029
  return { text: trimmed, source: "paste" };
10916
11030
  }
10917
- var import_child_process2, fs11, os7, path10, SUPPORTED_EXTENSIONS, SAMPLE_GLOB, GLOB_IGNORE;
11031
+ var import_child_process3, fs11, os8, path10, SUPPORTED_EXTENSIONS, SAMPLE_GLOB, GLOB_IGNORE;
10918
11032
  var init_document_text = __esm({
10919
11033
  "src/lib/document-text.ts"() {
10920
11034
  "use strict";
10921
- import_child_process2 = require("child_process");
11035
+ import_child_process3 = require("child_process");
10922
11036
  fs11 = __toESM(require("fs"));
10923
- os7 = __toESM(require("os"));
11037
+ os8 = __toESM(require("os"));
10924
11038
  path10 = __toESM(require("path"));
10925
11039
  init_index_min();
10926
11040
  SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -10996,21 +11110,21 @@ function runPipeline(text, profile, applyFixes = false) {
10996
11110
  };
10997
11111
  }
10998
11112
  function readText(source) {
10999
- const fs30 = require("fs");
11000
- const path27 = require("path");
11113
+ const fs31 = require("fs");
11114
+ const path28 = require("path");
11001
11115
  if (source === "-") {
11002
11116
  if (process.stdin.isTTY) {
11003
11117
  console.error("No input provided. Pipe content or specify a file.");
11004
11118
  process.exit(1);
11005
11119
  }
11006
- return { text: fs30.readFileSync(0, "utf-8"), path: "stdin" };
11120
+ return { text: fs31.readFileSync(0, "utf-8"), path: "stdin" };
11007
11121
  }
11008
- const resolved = path27.resolve(source);
11009
- if (!fs30.existsSync(resolved)) {
11122
+ const resolved = path28.resolve(source);
11123
+ if (!fs31.existsSync(resolved)) {
11010
11124
  console.error(`File not found: ${resolved}`);
11011
11125
  process.exit(1);
11012
11126
  }
11013
- const stat = fs30.statSync(resolved);
11127
+ const stat = fs31.statSync(resolved);
11014
11128
  if (stat.isDirectory()) {
11015
11129
  console.error(`${resolved} is a directory, not a file.`);
11016
11130
  process.exit(1);
@@ -11410,7 +11524,7 @@ function isInteractiveTTY() {
11410
11524
  return Boolean(process.stdin.isTTY && process.stdout.isTTY && !process.env.CI);
11411
11525
  }
11412
11526
  function briefPause(ms2 = 280) {
11413
- return new Promise((resolve15) => setTimeout(resolve15, ms2));
11527
+ return new Promise((resolve16) => setTimeout(resolve16, ms2));
11414
11528
  }
11415
11529
  async function withSpinner(label, fn, opts = {}) {
11416
11530
  const minMs = opts.minMs ?? 450;
@@ -11461,10 +11575,10 @@ var init_terminal_ui = __esm({
11461
11575
 
11462
11576
  // src/lib/welcome-flow.ts
11463
11577
  function localProfilePath(name) {
11464
- return path14.join(os8.homedir(), ".hyv", "profiles", `${name}.md`);
11578
+ return path14.join(os9.homedir(), ".hyv", "profiles", `${name}.md`);
11465
11579
  }
11466
11580
  function listLocalProfileNames() {
11467
- const profilesDir = path14.join(os8.homedir(), ".hyv", "profiles");
11581
+ const profilesDir = path14.join(os9.homedir(), ".hyv", "profiles");
11468
11582
  if (!fs15.existsSync(profilesDir))
11469
11583
  return [];
11470
11584
  return fs15.readdirSync(profilesDir).filter((entry) => entry.endsWith(".md")).map((entry) => entry.slice(0, -3));
@@ -11627,13 +11741,14 @@ function buildWelcomeGuide(opts = {}) {
11627
11741
  lines.push("");
11628
11742
  }
11629
11743
  lines.push("start in terminal:");
11630
- lines.push(" hyv welcome walk through all 4 steps");
11744
+ lines.push(" hyv welcome walk through all 4 steps (auto-configures mcp)");
11631
11745
  lines.push(" hyv welcome --guide show this guide (for agents / scripts)");
11632
11746
  lines.push("");
11633
11747
  lines.push("or jump in:");
11634
11748
  lines.push(" hyv import <name> <file.md> save a profile");
11635
11749
  lines.push(" hyv scan draft.md test a draft");
11636
11750
  lines.push(" hyv init signup when ready");
11751
+ lines.push(" hyv mcp --setup view all mcp configs");
11637
11752
  lines.push("");
11638
11753
  return lines.join("\n");
11639
11754
  }
@@ -11644,6 +11759,7 @@ function buildWelcomeHeader(opts = {}) {
11644
11759
  "",
11645
11760
  " hyv welcome set up your voice (4 steps)",
11646
11761
  " hyv scan test any draft free",
11762
+ " mcp auto-configured for your installed apps",
11647
11763
  ""
11648
11764
  ].join("\n");
11649
11765
  }
@@ -11725,10 +11841,10 @@ function saveLocalProfile(name, content) {
11725
11841
  writeWelcomeState({ profile_name: safe });
11726
11842
  markStepComplete("name");
11727
11843
  markStepComplete("samples");
11728
- return path14.join(os8.homedir(), ".hyv", "profiles", `${safe}.md`);
11844
+ return path14.join(os9.homedir(), ".hyv", "profiles", `${safe}.md`);
11729
11845
  }
11730
11846
  function fetchUrlText(url) {
11731
- return new Promise((resolve15, reject) => {
11847
+ return new Promise((resolve16, reject) => {
11732
11848
  let parsed;
11733
11849
  try {
11734
11850
  parsed = new URL(url);
@@ -11757,7 +11873,7 @@ function fetchUrlText(url) {
11757
11873
  });
11758
11874
  res.on("end", () => {
11759
11875
  const text = data.replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
11760
- resolve15(text.slice(0, 12e3));
11876
+ resolve16(text.slice(0, 12e3));
11761
11877
  });
11762
11878
  }
11763
11879
  );
@@ -11777,10 +11893,10 @@ async function collectSamplesFromLink(url) {
11777
11893
  }
11778
11894
  function askLine(prompt) {
11779
11895
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
11780
- return new Promise((resolve15) => {
11896
+ return new Promise((resolve16) => {
11781
11897
  rl.question(prompt, (answer) => {
11782
11898
  rl.close();
11783
- resolve15(answer.trim());
11899
+ resolve16(answer.trim());
11784
11900
  });
11785
11901
  });
11786
11902
  }
@@ -11789,11 +11905,11 @@ async function askMultiline(intro) {
11789
11905
  console.log(import_chalk12.default.dim(" paste below, then type --- on its own line when done\n"));
11790
11906
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
11791
11907
  const lines = [];
11792
- return new Promise((resolve15) => {
11908
+ return new Promise((resolve16) => {
11793
11909
  rl.on("line", (line) => {
11794
11910
  if (line.trim() === "---") {
11795
11911
  rl.close();
11796
- resolve15(lines.join("\n").trim());
11912
+ resolve16(lines.join("\n").trim());
11797
11913
  return;
11798
11914
  }
11799
11915
  lines.push(line);
@@ -12072,7 +12188,8 @@ async function runInteractiveWelcome() {
12072
12188
  console.log(import_chalk12.default.green("done \u2014 your voice profile is ready.\n"));
12073
12189
  console.log(import_chalk12.default.dim(" hyv scan draft.md"));
12074
12190
  console.log(import_chalk12.default.dim(` hyv rewrite draft.md --profile ${profileName}`));
12075
- console.log(import_chalk12.default.dim(" hyv mcp --setup\n"));
12191
+ console.log(import_chalk12.default.dim(" mcp auto-configured for your installed apps"));
12192
+ console.log(import_chalk12.default.dim(" hyv mcp --setup (view all configs)\n"));
12076
12193
  } catch (err) {
12077
12194
  console.error(import_chalk12.default.red(`
12078
12195
  ${err.message || "welcome flow stopped"}
@@ -12091,7 +12208,7 @@ function getMcpWelcomeResponse(args2) {
12091
12208
  }
12092
12209
  return buildWelcomeGuide({ profileName: args2.profile, forLlm: true });
12093
12210
  }
12094
- var import_chalk12, fs15, http2, https2, os8, path14, readline, PROFILE_SYNC_TIMEOUT_MS, WELCOME_TAGLINE, FLOW_STEPS, STATE_FILE;
12211
+ var import_chalk12, fs15, http2, https2, os9, path14, readline, PROFILE_SYNC_TIMEOUT_MS, WELCOME_TAGLINE, FLOW_STEPS, STATE_FILE;
12095
12212
  var init_welcome_flow = __esm({
12096
12213
  "src/lib/welcome-flow.ts"() {
12097
12214
  "use strict";
@@ -12099,7 +12216,7 @@ var init_welcome_flow = __esm({
12099
12216
  fs15 = __toESM(require("fs"));
12100
12217
  http2 = __toESM(require("http"));
12101
12218
  https2 = __toESM(require("https"));
12102
- os8 = __toESM(require("os"));
12219
+ os9 = __toESM(require("os"));
12103
12220
  path14 = __toESM(require("path"));
12104
12221
  readline = __toESM(require("readline"));
12105
12222
  init_pipeline();
@@ -12121,7 +12238,7 @@ var init_welcome_flow = __esm({
12121
12238
  { n: 3, key: "test", title: "test on a draft", hint: "optional \u2014 scan or rewrite a draft" },
12122
12239
  { n: 4, key: "signup", title: "save & unlock", hint: "signup syncs your profile and unlocks learning" }
12123
12240
  ];
12124
- STATE_FILE = path14.join(os8.homedir(), ".hyv", "welcome-state.json");
12241
+ STATE_FILE = path14.join(os9.homedir(), ".hyv", "welcome-state.json");
12125
12242
  }
12126
12243
  });
12127
12244
 
@@ -12204,6 +12321,7 @@ function buildWelcomeMessage(opts = {}) {
12204
12321
  lines.push(" set up your voice");
12205
12322
  lines.push(" hyv welcome");
12206
12323
  lines.push("");
12324
+ lines.push(" mcp auto-configured for your installed apps");
12207
12325
  lines.push(` unlock learning \u2192 ${PRICING_URL}`);
12208
12326
  lines.push("");
12209
12327
  return lines.join("\n");
@@ -13157,15 +13275,15 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s))
13157
13275
  g.minimatch.escape = vi2.escape;
13158
13276
  g.minimatch.unescape = Ei2.unescape;
13159
13277
  });
13160
- var fs30 = R2((Wt2) => {
13278
+ var fs31 = R2((Wt2) => {
13161
13279
  "use strict";
13162
13280
  Object.defineProperty(Wt2, "__esModule", { value: true });
13163
13281
  Wt2.LRUCache = void 0;
13164
13282
  var er = typeof performance == "object" && performance && typeof performance.now == "function" ? performance : Date, as2 = /* @__PURE__ */ new Set(), ge2 = typeof process == "object" && process ? process : {}, ls2 = (n7, t, e, s) => {
13165
13283
  typeof ge2.emitWarning == "function" ? ge2.emitWarning(n7, t, e, s) : console.error(`[${e}] ${t}: ${n7}`);
13166
- }, Lt2 = globalThis.AbortController, os13 = globalThis.AbortSignal;
13284
+ }, Lt2 = globalThis.AbortController, os15 = globalThis.AbortSignal;
13167
13285
  if (typeof Lt2 > "u") {
13168
- os13 = class {
13286
+ os15 = class {
13169
13287
  onabort;
13170
13288
  _onabort = [];
13171
13289
  reason;
@@ -13177,7 +13295,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s))
13177
13295
  constructor() {
13178
13296
  t();
13179
13297
  }
13180
- signal = new os13();
13298
+ signal = new os15();
13181
13299
  abort(e) {
13182
13300
  if (!this.signal.aborted) {
13183
13301
  this.signal.reason = e, this.signal.aborted = true;
@@ -14126,7 +14244,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s))
14126
14244
  };
14127
14245
  Object.defineProperty(_2, "__esModule", { value: true });
14128
14246
  _2.PathScurry = _2.Path = _2.PathScurryDarwin = _2.PathScurryPosix = _2.PathScurryWin32 = _2.PathScurryBase = _2.PathPosix = _2.PathWin32 = _2.PathBase = _2.ChildrenCache = _2.ResolveCache = void 0;
14129
- var Qt2 = fs30(), Yt2 = require("node:path"), yr = require("node:url"), pt2 = require("fs"), Sr = br(require("node:fs")), vr = pt2.realpathSync.native, Ht2 = require("node:fs/promises"), bs2 = Oe2(), mt2 = { lstatSync: pt2.lstatSync, readdir: pt2.readdir, readdirSync: pt2.readdirSync, readlinkSync: pt2.readlinkSync, realpathSync: vr, promises: { lstat: Ht2.lstat, readdir: Ht2.readdir, readlink: Ht2.readlink, realpath: Ht2.realpath } }, _s2 = (n7) => !n7 || n7 === mt2 || n7 === Sr ? mt2 : { ...mt2, ...n7, promises: { ...mt2.promises, ...n7.promises || {} } }, Os2 = /^\\\\\?\\([a-z]:)\\?$/i, Er = (n7) => n7.replace(/\//g, "\\").replace(Os2, "$1\\"), _r = /[\\\/]/, N2 = 0, xs2 = 1, Ts2 = 2, G2 = 4, Cs2 = 6, Rs2 = 8, Q2 = 10, As2 = 12, j2 = 15, dt2 = ~j2, xe2 = 16, ys2 = 32, gt2 = 64, W2 = 128, Vt2 = 256, Xt2 = 512, Ss2 = gt2 | W2 | Xt2, Or = 1023, Te2 = (n7) => n7.isFile() ? Rs2 : n7.isDirectory() ? G2 : n7.isSymbolicLink() ? Q2 : n7.isCharacterDevice() ? Ts2 : n7.isBlockDevice() ? Cs2 : n7.isSocket() ? As2 : n7.isFIFO() ? xs2 : N2, vs2 = new Qt2.LRUCache({ max: 2 ** 12 }), wt2 = (n7) => {
14247
+ var Qt2 = fs31(), Yt2 = require("node:path"), yr = require("node:url"), pt2 = require("fs"), Sr = br(require("node:fs")), vr = pt2.realpathSync.native, Ht2 = require("node:fs/promises"), bs2 = Oe2(), mt2 = { lstatSync: pt2.lstatSync, readdir: pt2.readdir, readdirSync: pt2.readdirSync, readlinkSync: pt2.readlinkSync, realpathSync: vr, promises: { lstat: Ht2.lstat, readdir: Ht2.readdir, readlink: Ht2.readlink, realpath: Ht2.realpath } }, _s2 = (n7) => !n7 || n7 === mt2 || n7 === Sr ? mt2 : { ...mt2, ...n7, promises: { ...mt2.promises, ...n7.promises || {} } }, Os2 = /^\\\\\?\\([a-z]:)\\?$/i, Er = (n7) => n7.replace(/\//g, "\\").replace(Os2, "$1\\"), _r = /[\\\/]/, N2 = 0, xs2 = 1, Ts2 = 2, G2 = 4, Cs2 = 6, Rs2 = 8, Q2 = 10, As2 = 12, j2 = 15, dt2 = ~j2, xe2 = 16, ys2 = 32, gt2 = 64, W2 = 128, Vt2 = 256, Xt2 = 512, Ss2 = gt2 | W2 | Xt2, Or = 1023, Te2 = (n7) => n7.isFile() ? Rs2 : n7.isDirectory() ? G2 : n7.isSymbolicLink() ? Q2 : n7.isCharacterDevice() ? Ts2 : n7.isBlockDevice() ? Cs2 : n7.isSocket() ? As2 : n7.isFIFO() ? xs2 : N2, vs2 = new Qt2.LRUCache({ max: 2 ** 12 }), wt2 = (n7) => {
14130
14248
  let t = vs2.get(n7);
14131
14249
  if (t)
14132
14250
  return t;
@@ -15645,7 +15763,7 @@ var {
15645
15763
  } = import_index.default;
15646
15764
 
15647
15765
  // src/index.ts
15648
- var import_chalk33 = __toESM(require_source());
15766
+ var import_chalk35 = __toESM(require_source());
15649
15767
 
15650
15768
  // src/commands/init.ts
15651
15769
  var import_chalk4 = __toESM(require_source());
@@ -15791,10 +15909,19 @@ function registerInitCommand(program3) {
15791
15909
  if (authData.license_key) {
15792
15910
  console.log(import_chalk4.default.dim(` License: ${authData.license_key.slice(0, 12)}...`));
15793
15911
  }
15912
+ try {
15913
+ const { ensureMcpProfilesHydrated: ensureMcpProfilesHydrated2 } = await Promise.resolve().then(() => (init_mcp_profile_hydrate(), mcp_profile_hydrate_exports));
15914
+ const hydrated = await ensureMcpProfilesHydrated2({ force: true });
15915
+ if (hydrated.synced?.length) {
15916
+ console.log(import_chalk4.default.green(`
15917
+ \u2713 MCP profiles ready: ${hydrated.synced.join(", ")}`));
15918
+ }
15919
+ } catch {
15920
+ }
15794
15921
  const mcpResults = configureMcpForDesktop();
15795
15922
  const { printPaidUnlockReminder: printPaidUnlockReminder2 } = await Promise.resolve().then(() => (init_marketing_hints(), marketing_hints_exports));
15796
15923
  console.log("\nNext steps:");
15797
- console.log(import_chalk4.default.dim(" 1. Set up your voice: hyv welcome"));
15924
+ console.log(import_chalk4.default.dim(" 1. Voice profile: hyv welcome (or use dashboard \u2014 MCP syncs after init)"));
15798
15925
  console.log(import_chalk4.default.dim(" 2. Scan a draft: hyv scan draft.md"));
15799
15926
  console.log(import_chalk4.default.dim(" 3. Rewrite with voice: hyv rewrite draft.md"));
15800
15927
  printPaidUnlockReminder2();
@@ -16018,6 +16145,8 @@ init_profile();
16018
16145
  init_profile_meta();
16019
16146
  var fs8 = __toESM(require("fs"));
16020
16147
  var path8 = __toESM(require("path"));
16148
+ var os6 = __toESM(require("os"));
16149
+ var import_child_process2 = require("child_process");
16021
16150
  function registerSyncCommand(program3) {
16022
16151
  program3.command("sync").description("Sync profiles and rules from server").option("--force", "Force re-download even if cache is fresh").action(async (options) => {
16023
16152
  try {
@@ -16105,7 +16234,15 @@ function registerSyncCommand(program3) {
16105
16234
  process.exit(1);
16106
16235
  }
16107
16236
  });
16108
- program3.command("profiles").description("List voice profiles").option("--verbose", "Show learned patterns, drift, anchors").option("--history <name>", "Show profile evolution for a slug").action(async (options) => {
16237
+ program3.command("profiles").description("List, edit, or delete voice profiles").option("--verbose", "Show learned patterns, drift, anchors").option("--history <name>", "Show profile evolution for a slug").option("--delete <name>", "Delete a profile (server + local cache)").option("--edit <name>", "Open a local profile in your $EDITOR").action(async (options) => {
16238
+ if (options.delete) {
16239
+ await deleteProfileByName(options.delete);
16240
+ return;
16241
+ }
16242
+ if (options.edit) {
16243
+ await editLocalProfile(options.edit);
16244
+ return;
16245
+ }
16109
16246
  if (options.history) {
16110
16247
  await showProfileHistory(options.history);
16111
16248
  return;
@@ -16151,6 +16288,58 @@ ${profiles.length} profile(s) cached.`));
16151
16288
  await program3.parseAsync(["node", "hyv", "sync", "--force"]);
16152
16289
  });
16153
16290
  }
16291
+ async function deleteProfileByName(name) {
16292
+ const token = getToken();
16293
+ const localKey = toSafeProfileCacheKey(name);
16294
+ const localPath = path8.join(os6.homedir(), ".hyv", "profiles", `${localKey}.md`);
16295
+ if (token) {
16296
+ try {
16297
+ const res = await authenticatedRequest(cliApiUrl("/cli/profiles/delete"), {
16298
+ method: "POST",
16299
+ body: { slug_or_id: name }
16300
+ });
16301
+ if (res.status !== 200) {
16302
+ const err = res.data?.error || `delete failed (HTTP ${res.status})`;
16303
+ console.log(import_chalk8.default.red(`
16304
+ ${err}
16305
+ `));
16306
+ process.exit(1);
16307
+ }
16308
+ console.log(import_chalk8.default.green(`
16309
+ \u2713 deleted "${name}" from your account
16310
+ `));
16311
+ } catch (err) {
16312
+ console.log(import_chalk8.default.red(`
16313
+ ${err.message || "delete failed"}
16314
+ `));
16315
+ process.exit(1);
16316
+ }
16317
+ } else {
16318
+ console.log(import_chalk8.default.yellow("\n not signed in \u2014 deleting local profile only\n"));
16319
+ }
16320
+ if (fs8.existsSync(localPath)) {
16321
+ fs8.unlinkSync(localPath);
16322
+ console.log(import_chalk8.default.dim(` removed ${localPath}`));
16323
+ }
16324
+ }
16325
+ async function editLocalProfile(name) {
16326
+ const localKey = toSafeProfileCacheKey(name);
16327
+ const localPath = path8.join(os6.homedir(), ".hyv", "profiles", `${localKey}.md`);
16328
+ if (!fs8.existsSync(localPath)) {
16329
+ console.log(import_chalk8.default.yellow(`
16330
+ no local profile at ${localPath}`));
16331
+ console.log(import_chalk8.default.dim(" run `hyv sync` or `hyv welcome` first\n"));
16332
+ process.exit(1);
16333
+ }
16334
+ const editor = process.env.EDITOR || process.env.VISUAL || (process.platform === "win32" ? "notepad" : "nano");
16335
+ const result = (0, import_child_process2.spawnSync)(editor, [localPath], { stdio: "inherit", shell: process.platform === "win32" });
16336
+ if (result.status !== 0) {
16337
+ process.exit(result.status || 1);
16338
+ }
16339
+ console.log(import_chalk8.default.green(`
16340
+ \u2713 saved ${localPath}`));
16341
+ console.log(import_chalk8.default.dim(" sync to account: hyv sync\n"));
16342
+ }
16154
16343
  async function showProfileHistory(slug) {
16155
16344
  const { authenticatedRequest: authenticatedRequest2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
16156
16345
  const token = getToken();
@@ -16990,7 +17179,7 @@ function registerImportCommand(program3) {
16990
17179
  });
16991
17180
  }
16992
17181
  function askQuestion(question) {
16993
- return new Promise((resolve15) => {
17182
+ return new Promise((resolve16) => {
16994
17183
  const readline3 = require("readline");
16995
17184
  const rl = readline3.createInterface({
16996
17185
  input: process.stdin,
@@ -16999,7 +17188,7 @@ function askQuestion(question) {
16999
17188
  rl.question(import_chalk13.default.cyan(` ${question}
17000
17189
  > `), (answer) => {
17001
17190
  rl.close();
17002
- resolve15(answer.trim());
17191
+ resolve16(answer.trim());
17003
17192
  });
17004
17193
  });
17005
17194
  }
@@ -17558,7 +17747,7 @@ hyv scan ${filePath}`));
17558
17747
  var import_chalk19 = __toESM(require_source());
17559
17748
  var fs19 = __toESM(require("fs"));
17560
17749
  var path18 = __toESM(require("path"));
17561
- var os9 = __toESM(require("os"));
17750
+ var os10 = __toESM(require("os"));
17562
17751
  init_config();
17563
17752
  init_auth();
17564
17753
  init_access();
@@ -17566,7 +17755,7 @@ init_local_profile();
17566
17755
  init_version();
17567
17756
 
17568
17757
  // src/lib/mcp-stdio-test.ts
17569
- var import_child_process3 = require("child_process");
17758
+ var import_child_process4 = require("child_process");
17570
17759
 
17571
17760
  // src/lib/cli-entry.ts
17572
17761
  var fs18 = __toESM(require("fs"));
@@ -17596,8 +17785,8 @@ async function testMcpStdioSubprocess() {
17596
17785
  const entry = resolveCliEntry();
17597
17786
  if (!entry)
17598
17787
  return { ok: false };
17599
- return new Promise((resolve15) => {
17600
- const child = (0, import_child_process3.spawn)(process.execPath, [entry, "mcp"], {
17788
+ return new Promise((resolve16) => {
17789
+ const child = (0, import_child_process4.spawn)(process.execPath, [entry, "mcp"], {
17601
17790
  stdio: ["pipe", "pipe", "pipe"],
17602
17791
  env: { ...process.env, HYV_POSTINSTALL_QUIET: "1" }
17603
17792
  });
@@ -17612,7 +17801,7 @@ async function testMcpStdioSubprocess() {
17612
17801
  child.kill();
17613
17802
  } catch {
17614
17803
  }
17615
- resolve15({ ok, toolCount });
17804
+ resolve16({ ok, toolCount });
17616
17805
  };
17617
17806
  const timeout = setTimeout(() => finish(false), 1e4);
17618
17807
  const handleLine = (line) => {
@@ -17663,7 +17852,7 @@ async function testMcpStdioSubprocess() {
17663
17852
  }
17664
17853
 
17665
17854
  // src/commands/doctor.ts
17666
- var HOME = os9.homedir();
17855
+ var HOME = os10.homedir();
17667
17856
  var IS_WIN = process.platform === "win32";
17668
17857
  function claudeDesktopDir() {
17669
17858
  if (IS_WIN)
@@ -17874,7 +18063,7 @@ function registerDoctorCommand(program3) {
17874
18063
  if (cursorMcp)
17875
18064
  console.log(import_chalk19.default.green(" \u2713 mcp configured for cursor"));
17876
18065
  } else {
17877
- console.log(import_chalk19.default.yellow(" ! mcp not configured \u2014 run: hyv doctor --fix-agents or hyv mcp --setup"));
18066
+ console.log(import_chalk19.default.yellow(" ! mcp not configured \u2014 run: hyv mcp (auto-detect) or hyv doctor --fix-agents"));
17878
18067
  issues++;
17879
18068
  }
17880
18069
  try {
@@ -18017,11 +18206,11 @@ async function confirmDestructiveWrite(options) {
18017
18206
  const question = `
18018
18207
  ${label}
18019
18208
  A .bak backup will be created. Proceed? [y/N] `;
18020
- const answer = await new Promise((resolve15) => {
18209
+ const answer = await new Promise((resolve16) => {
18021
18210
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
18022
18211
  rl.question(question, (value) => {
18023
18212
  rl.close();
18024
- resolve15(value.trim().toLowerCase());
18213
+ resolve16(value.trim().toLowerCase());
18025
18214
  });
18026
18215
  });
18027
18216
  return answer === "y" || answer === "yes";
@@ -18127,19 +18316,19 @@ function registerCheckCommand(program3) {
18127
18316
  const profile = await loadProfileForCommand(options.profile);
18128
18317
  let inputText = text;
18129
18318
  if (text === "-") {
18130
- const fs31 = require("fs");
18319
+ const fs32 = require("fs");
18131
18320
  if (process.stdin.isTTY) {
18132
18321
  console.error(import_chalk23.default.red("No input provided. Pipe content or pass text as argument."));
18133
18322
  process.exit(1);
18134
18323
  }
18135
- inputText = fs31.readFileSync(0, "utf-8");
18324
+ inputText = fs32.readFileSync(0, "utf-8");
18136
18325
  }
18137
18326
  if (!inputText.trim()) {
18138
18327
  console.error(import_chalk23.default.red("No text provided."));
18139
18328
  process.exit(1);
18140
18329
  }
18141
- const fs30 = require("fs");
18142
- if (text !== "-" && fs30.existsSync(text)) {
18330
+ const fs31 = require("fs");
18331
+ if (text !== "-" && fs31.existsSync(text)) {
18143
18332
  console.log(import_chalk23.default.yellow(`"${text}" looks like a file. Did you mean: hyv scan ${text}`));
18144
18333
  process.exit(1);
18145
18334
  }
@@ -18266,12 +18455,12 @@ function registerDiffCommand(program3) {
18266
18455
  ${result.changes.length} auto-fix${result.changes.length === 1 ? "" : "es"} available`));
18267
18456
  console.log(import_chalk25.default.dim(` run: hyv fix ${file} -i to apply`));
18268
18457
  if (options.apply && filePath !== "stdin") {
18269
- const fs30 = require("fs");
18270
- const path27 = require("path");
18458
+ const fs31 = require("fs");
18459
+ const path28 = require("path");
18271
18460
  const backupPath = filePath + ".bak";
18272
- fs30.copyFileSync(filePath, backupPath);
18273
- fs30.writeFileSync(filePath, result.fixed);
18274
- console.log(import_chalk25.default.green(` \u2713 Applied. Backup: ${path27.basename(backupPath)}`));
18461
+ fs31.copyFileSync(filePath, backupPath);
18462
+ fs31.writeFileSync(filePath, result.fixed);
18463
+ console.log(import_chalk25.default.green(` \u2713 Applied. Backup: ${path28.basename(backupPath)}`));
18275
18464
  }
18276
18465
  } catch (error) {
18277
18466
  console.error(import_chalk25.default.red(`Error: ${error.message}`));
@@ -18807,13 +18996,14 @@ function registerOpenCommand(program3) {
18807
18996
  }
18808
18997
 
18809
18998
  // src/commands/welcome.ts
18999
+ var import_chalk31 = __toESM(require_source());
18810
19000
  init_welcome();
18811
19001
 
18812
19002
  // src/lib/onboarding.ts
18813
19003
  var fs24 = __toESM(require("fs"));
18814
19004
  var path22 = __toESM(require("path"));
18815
- var os10 = __toESM(require("os"));
18816
- var hyvDir = path22.join(os10.homedir(), ".hyv");
19005
+ var os11 = __toESM(require("os"));
19006
+ var hyvDir = path22.join(os11.homedir(), ".hyv");
18817
19007
  var onboardingFile = path22.join(hyvDir, "onboarding-complete.json");
18818
19008
  function hasCompletedOnboarding() {
18819
19009
  try {
@@ -18835,6 +19025,20 @@ function markOnboardingComplete(version) {
18835
19025
  init_welcome_flow();
18836
19026
  var fs25 = __toESM(require("fs"));
18837
19027
  var path23 = __toESM(require("path"));
19028
+ function runBackgroundMcpSetup() {
19029
+ const pkgDir = path23.resolve(__dirname, "..");
19030
+ const postinstallLib = path23.join(pkgDir, "scripts", "postinstall-lib.js");
19031
+ if (!fs25.existsSync(postinstallLib))
19032
+ return;
19033
+ try {
19034
+ const { setupAgents } = require(postinstallLib);
19035
+ const result = setupAgents({ pkgDir, quiet: true });
19036
+ if (result.configured.length > 0) {
19037
+ console.log(import_chalk31.default.dim(` \u2713 mcp auto-configured: ${result.configured.join(", ")}`));
19038
+ }
19039
+ } catch {
19040
+ }
19041
+ }
18838
19042
  function registerWelcomeCommand(program3) {
18839
19043
  const pkgVersion3 = (() => {
18840
19044
  try {
@@ -18844,10 +19048,15 @@ function registerWelcomeCommand(program3) {
18844
19048
  return "0.0.0";
18845
19049
  }
18846
19050
  })();
18847
- program3.command("welcome").description("Set up your voice: name \u2192 samples \u2192 test \u2192 signup").option("--guide", "Show LLM/terminal guide (no prompts)").option("--extract-prompt [name]", "Print chat extraction prompt for agents").option("--step <n>", "Show guide for step 1\u20134", (v2) => parseInt(v2, 10)).option("--no-demo", "Skip sample scan line in guide mode").option("--quiet", "Suppress output").action(async (opts) => {
18848
- if (opts.quiet)
19051
+ program3.command("welcome").description("Set up your voice: name \u2192 samples \u2192 test \u2192 signup").option("--guide", "Show LLM/terminal guide (no prompts)").option("--extract-prompt [name]", "Print chat extraction prompt for agents").option("--step <n>", "Show guide for step 1\u20134", (v2) => parseInt(v2, 10)).option("--no-demo", "Skip sample scan line in guide mode").option("--skip-mcp", "Skip automatic MCP setup for IDE agents").option("--quiet", "Suppress output").action(async (opts) => {
19052
+ if (opts.quiet) {
19053
+ if (!opts.skipMcp)
19054
+ runBackgroundMcpSetup();
18849
19055
  return;
19056
+ }
18850
19057
  const fromPostinstall = process.env.HYV_POSTINSTALL_ONBOARDING === "1";
19058
+ if (!opts.skipMcp && !fromPostinstall)
19059
+ runBackgroundMcpSetup();
18851
19060
  if (opts.extractPrompt !== void 0) {
18852
19061
  const name = typeof opts.extractPrompt === "string" ? opts.extractPrompt : "my-voice";
18853
19062
  console.log("\n" + buildVoiceExtractionPrompt(name) + "\n");
@@ -18886,7 +19095,7 @@ function getWelcomeText(args2) {
18886
19095
  }
18887
19096
 
18888
19097
  // src/commands/content.ts
18889
- var import_chalk31 = __toESM(require_source());
19098
+ var import_chalk32 = __toESM(require_source());
18890
19099
  init_free_paid();
18891
19100
  var TEMPLATES = {
18892
19101
  cursor: {
@@ -18960,19 +19169,19 @@ ${COMMUNITY_URL}`
18960
19169
  function registerContentCommand(program3) {
18961
19170
  program3.command("content").description("Blog outlines, CI snippets, and share templates").argument("[topic]", "cursor | agents | ci | share", "cursor").option("--list", "List available templates").action((topic, opts) => {
18962
19171
  if (opts.list) {
18963
- console.log(import_chalk31.default.bold("\nhyv content templates\n"));
19172
+ console.log(import_chalk32.default.bold("\nhyv content templates\n"));
18964
19173
  for (const [key, t2] of Object.entries(TEMPLATES)) {
18965
- console.log(import_chalk31.default.dim(` ${key}`) + ` \u2014 ${t2.title}`);
19174
+ console.log(import_chalk32.default.dim(` ${key}`) + ` \u2014 ${t2.title}`);
18966
19175
  }
18967
19176
  console.log("");
18968
19177
  return;
18969
19178
  }
18970
19179
  const t = TEMPLATES[topic] || TEMPLATES.cursor;
18971
- console.log(import_chalk31.default.bold(`
19180
+ console.log(import_chalk32.default.bold(`
18972
19181
  ${t.title}
18973
19182
  `));
18974
19183
  console.log(t.body);
18975
- console.log(import_chalk31.default.dim("\nBlog: https://holdyourvoice.com/blog\n"));
19184
+ console.log(import_chalk32.default.dim("\nBlog: https://holdyourvoice.com/blog\n"));
18976
19185
  });
18977
19186
  }
18978
19187
 
@@ -18986,9 +19195,9 @@ function registerUpgradeCommand(program3) {
18986
19195
  }
18987
19196
 
18988
19197
  // src/mcp.ts
18989
- var fs26 = __toESM(require("fs"));
18990
- var path24 = __toESM(require("path"));
18991
- var os11 = __toESM(require("os"));
19198
+ var fs27 = __toESM(require("fs"));
19199
+ var path25 = __toESM(require("path"));
19200
+ var os13 = __toESM(require("os"));
18992
19201
  init_classifier();
18993
19202
  init_autofix();
18994
19203
  init_validator();
@@ -18996,23 +19205,201 @@ init_pipeline();
18996
19205
  init_signals();
18997
19206
  init_local_profile();
18998
19207
  init_welcome();
18999
- init_config();
19000
19208
  init_telemetry();
19001
19209
  init_access();
19002
- var VOICE_MD = path24.join(os11.homedir(), ".hyv", "voice.md");
19210
+
19211
+ // src/lib/mcp-integrate.ts
19212
+ var import_chalk33 = __toESM(require_source());
19213
+ var fs26 = __toESM(require("fs"));
19214
+ var os12 = __toESM(require("os"));
19215
+ var path24 = __toESM(require("path"));
19216
+ init_version();
19217
+ init_welcome_flow();
19218
+ init_config();
19219
+ init_local_profile();
19220
+ function resolveCliRoot() {
19221
+ const candidates = [
19222
+ path24.resolve(__dirname, ".."),
19223
+ path24.resolve(__dirname, "..", "..")
19224
+ ];
19225
+ for (const root of candidates) {
19226
+ if (fs26.existsSync(path24.join(root, "scripts", "postinstall-lib.js"))) {
19227
+ return root;
19228
+ }
19229
+ }
19230
+ return candidates[0];
19231
+ }
19232
+ function loadPostinstallLib() {
19233
+ return require(path24.join(resolveCliRoot(), "scripts", "postinstall-lib.js"));
19234
+ }
19235
+ function runMcpAutoIntegrate(opts = {}) {
19236
+ const { integrateDetectedAgents } = loadPostinstallLib();
19237
+ return integrateDetectedAgents({
19238
+ pkgDir: resolveCliRoot(),
19239
+ quiet: true,
19240
+ force: Boolean(opts.force)
19241
+ });
19242
+ }
19243
+ function listLocalProfileNames2() {
19244
+ return [.../* @__PURE__ */ new Set([...listCachedProfiles(), ...listDiskCachedProfiles()])].sort();
19245
+ }
19246
+ function buildOnboardingStatusLines() {
19247
+ const lines = [];
19248
+ const welcome = readWelcomeState();
19249
+ const profiles = listLocalProfileNames2();
19250
+ const onboarded = hasCompletedOnboarding();
19251
+ const config = readConfig();
19252
+ const active = config.default_profile || config.profile;
19253
+ if (profiles.length > 0) {
19254
+ const activeNote = active && profiles.includes(active) ? ` (default: ${active})` : "";
19255
+ lines.push(`voice profiles (MCP-ready): ${profiles.join(", ")}${activeNote}`);
19256
+ } else {
19257
+ lines.push("voice profiles: none on this machine yet");
19258
+ lines.push("dashboard profile \u2192 run `hyv init` once; terminal `hyv welcome` \u2192 saved locally automatically");
19259
+ }
19260
+ if (welcome.profile_name) {
19261
+ lines.push(`welcome progress: profile name "${welcome.profile_name}"`);
19262
+ }
19263
+ if (welcome.completed_steps?.length) {
19264
+ const done = welcome.completed_steps.map((key) => FLOW_STEPS.find((s) => s.key === key)?.title || key).join(", ");
19265
+ lines.push(`welcome steps done: ${done}`);
19266
+ } else if (!onboarded) {
19267
+ lines.push("welcome steps: not started (or only partial)");
19268
+ }
19269
+ lines.push("free without profile: hyv_scan, hyv_demo, hyv_fix, hyv_check work offline");
19270
+ lines.push("with profile: hyv_rewrite, hyv_validate, hyv_clean use your voice rules");
19271
+ return lines;
19272
+ }
19273
+ function formatChatGptConnectorGuide() {
19274
+ const lib = loadPostinstallLib();
19275
+ const mcpCmd = lib.resolveHyvMcpCommand(resolveCliRoot());
19276
+ const guidePath = path24.join(os12.homedir(), ".chatgpt", "hyv-mcp-connector.txt");
19277
+ const lines = [
19278
+ "### ChatGPT Desktop connector (manual \u2014 no auto-config file)",
19279
+ "",
19280
+ "1. Open ChatGPT **desktop** app (browser chat cannot use local MCP)",
19281
+ "2. Settings \u2192 Connectors \u2192 Add connector",
19282
+ "3. Name: **hold your voice**",
19283
+ "4. Command: **hyv**",
19284
+ "5. Arguments: **mcp**",
19285
+ "",
19286
+ "If the connector fails to start, use absolute paths:",
19287
+ ` command: ${mcpCmd.command}`,
19288
+ ` arguments: ${mcpCmd.args.join(" ")}`,
19289
+ "",
19290
+ "6. Save, restart ChatGPT Desktop",
19291
+ '7. Ask: "run hyv_welcome" or "scan this draft with hold your voice"',
19292
+ ""
19293
+ ];
19294
+ if (fs26.existsSync(guidePath)) {
19295
+ lines.push(`Full guide on disk: ${guidePath}`);
19296
+ } else {
19297
+ lines.push("Run `hyv mcp` or `hyv doctor --fix-agents` to write the guide file.");
19298
+ }
19299
+ return lines.join("\n");
19300
+ }
19301
+ function buildMcpAgentStatus() {
19302
+ const {
19303
+ detectInstalledAgents,
19304
+ isAgentIntegrated,
19305
+ resolveHyvMcpCommand
19306
+ } = loadPostinstallLib();
19307
+ const home = os12.homedir();
19308
+ const detected = detectInstalledAgents(home);
19309
+ const mcpCmd = resolveHyvMcpCommand(resolveCliRoot());
19310
+ const lines = [
19311
+ "### HYV MCP status",
19312
+ "",
19313
+ `mcp server command: ${mcpCmd.command} ${mcpCmd.args.join(" ")}`,
19314
+ "",
19315
+ ...buildOnboardingStatusLines().map((l) => `- ${l}`),
19316
+ ""
19317
+ ];
19318
+ if (detected.length === 0) {
19319
+ lines.push("### Installed apps");
19320
+ lines.push("- none detected \u2014 install Cursor, Claude Desktop, ChatGPT Desktop, etc.");
19321
+ lines.push("- then run `hyv mcp` in terminal or call hyv_mcp_setup with action=integrate");
19322
+ lines.push("");
19323
+ lines.push(formatChatGptConnectorGuide());
19324
+ return lines.join("\n");
19325
+ }
19326
+ lines.push("### Installed apps");
19327
+ for (const app of detected) {
19328
+ const integrated = isAgentIntegrated(app.id, home);
19329
+ const status = app.integration === "manual" ? integrated ? "guide written" : "add connector manually" : integrated ? "integrated" : "needs setup";
19330
+ lines.push(`- ${app.label}: ${status} (${app.integration})`);
19331
+ }
19332
+ lines.push("");
19333
+ lines.push("### In this chat (no terminal needed)");
19334
+ lines.push("- Which profile is active \u2192 hyv_profiles");
19335
+ lines.push("- New or partial setup \u2192 hyv_welcome (steps 1\u20134, or mode=extract_prompt for voice from chat)");
19336
+ lines.push("- Refresh app configs \u2192 hyv_mcp_setup with action=integrate (force=true after hyv upgrade)");
19337
+ lines.push("- ChatGPT connector steps \u2192 hyv_mcp_setup with action=chatgpt");
19338
+ lines.push("- Test free scan \u2192 hyv_demo or hyv_scan on any draft");
19339
+ return lines.join("\n");
19340
+ }
19341
+ function formatMcpIntegrateReportText(result, opts = {}) {
19342
+ const { agentIdForConfiguredLabel, isAgentIntegrated } = loadPostinstallLib();
19343
+ const configuredIds = new Set(
19344
+ result.configured.map((label) => agentIdForConfiguredLabel(label)).filter(Boolean)
19345
+ );
19346
+ const lines = [
19347
+ "### HYV MCP integration",
19348
+ "",
19349
+ ...buildOnboardingStatusLines().map((l) => `- ${l}`),
19350
+ ""
19351
+ ];
19352
+ if (result.detected.length === 0) {
19353
+ lines.push("No supported AI apps detected on this machine.");
19354
+ lines.push("Install Cursor, Claude Desktop, Windsurf, or ChatGPT Desktop, then run integrate again.");
19355
+ lines.push("");
19356
+ lines.push(formatChatGptConnectorGuide());
19357
+ return lines.join("\n");
19358
+ }
19359
+ lines.push("### Apps");
19360
+ for (const app of result.detected) {
19361
+ const justConfigured = configuredIds.has(app.id);
19362
+ const integrated = isAgentIntegrated(app.id) || justConfigured;
19363
+ const status = app.integration === "manual" ? "manual connector" : justConfigured ? opts.force ? "updated now" : "configured now" : integrated ? "integrated" : "needs setup";
19364
+ lines.push(`- ${app.label}: ${status}`);
19365
+ }
19366
+ if (result.configured.length > 0) {
19367
+ lines.push("");
19368
+ lines.push(`Wired: ${result.configured.join(", ")}`);
19369
+ }
19370
+ if (result.warnings.length > 0) {
19371
+ lines.push("");
19372
+ lines.push("Notes:");
19373
+ for (const warning of result.warnings) {
19374
+ lines.push(`- ${warning}`);
19375
+ }
19376
+ }
19377
+ lines.push("");
19378
+ lines.push("Restart MCP hosts (Cursor, Claude Desktop, Antigravity, OpenCode) after config changes.");
19379
+ if (result.detected.some((a) => a.integration === "manual")) {
19380
+ lines.push("");
19381
+ lines.push(formatChatGptConnectorGuide());
19382
+ }
19383
+ return lines.join("\n");
19384
+ }
19385
+
19386
+ // src/mcp.ts
19387
+ init_mcp_profile_hydrate();
19388
+ init_profile();
19389
+ var VOICE_MD = path25.join(os13.homedir(), ".hyv", "voice.md");
19003
19390
  var MAX_RESPONSE_CHARS = 12e4;
19004
19391
  var MAX_SCAN_FILE_BYTES = 2 * 1024 * 1024;
19005
19392
  function readScanFile(filePath) {
19006
- const cwdReal = fs26.realpathSync(process.cwd());
19007
- const resolved = fs26.realpathSync(path24.resolve(filePath));
19008
- if (!resolved.startsWith(cwdReal + path24.sep) && resolved !== cwdReal) {
19393
+ const cwdReal = fs27.realpathSync(process.cwd());
19394
+ const resolved = fs27.realpathSync(path25.resolve(filePath));
19395
+ if (!resolved.startsWith(cwdReal + path25.sep) && resolved !== cwdReal) {
19009
19396
  throw new Error(`file must be in the current working directory (${cwdReal})`);
19010
19397
  }
19011
- const stat = fs26.statSync(resolved);
19398
+ const stat = fs27.statSync(resolved);
19012
19399
  if (stat.size > MAX_SCAN_FILE_BYTES) {
19013
19400
  throw new Error(`file too large (max ${MAX_SCAN_FILE_BYTES} bytes)`);
19014
19401
  }
19015
- return fs26.readFileSync(resolved, "utf-8");
19402
+ return fs27.readFileSync(resolved, "utf-8");
19016
19403
  }
19017
19404
  function toolResultPayload(result) {
19018
19405
  const isError = result.startsWith("Error:") || result.startsWith("Unknown tool:");
@@ -19021,20 +19408,22 @@ function toolResultPayload(result) {
19021
19408
  ...isError ? { isError: true } : {}
19022
19409
  };
19023
19410
  }
19024
- var pkgPath = path24.resolve(__dirname, "..", "package.json");
19411
+ var pkgPath = path25.resolve(__dirname, "..", "package.json");
19025
19412
  var pkgVersion = (() => {
19026
19413
  try {
19027
- return JSON.parse(fs26.readFileSync(pkgPath, "utf-8")).version;
19414
+ return JSON.parse(fs27.readFileSync(pkgPath, "utf-8")).version;
19028
19415
  } catch {
19029
19416
  return "2.7.1";
19030
19417
  }
19031
19418
  })();
19032
- async function resolveProfile(slug, allowServerFetch = false) {
19033
- const profile = await loadProfileForCommand(slug, { allowServerFetch });
19034
- if (slug && !profile) {
19035
- const { requirePaidFeature: requirePaidFeature2 } = await Promise.resolve().then(() => (init_access(), access_exports));
19036
- await requirePaidFeature2("premiumPrompts");
19037
- return loadProfileForCommand(slug, { allowServerFetch: true });
19419
+ async function resolveProfile(slug) {
19420
+ await ensureMcpProfilesHydrated();
19421
+ let profile = await loadProfileForCommand(slug, { allowServerFetch: true });
19422
+ if (!profile && slug) {
19423
+ try {
19424
+ profile = await loadFullProfile(normalizeProfileSlug(slug), { forceRefresh: true });
19425
+ } catch {
19426
+ }
19038
19427
  }
19039
19428
  return profile;
19040
19429
  }
@@ -19134,27 +19523,8 @@ async function toolScan(args2) {
19134
19523
  }
19135
19524
  }
19136
19525
  async function toolProfiles(_args) {
19137
- const local = [.../* @__PURE__ */ new Set([...listCachedProfiles(), ...listDiskCachedProfiles()])];
19138
- if (local.length > 0) {
19139
- return "Cached profiles (local):\n" + local.map((p) => ` \u2022 ${p}`).join("\n");
19140
- }
19141
- try {
19142
- const { apiGet: apiGet2 } = await Promise.resolve().then(() => (init_api(), api_exports));
19143
- const data = await apiGet2("/cli/profiles");
19144
- const profiles = data.profiles || [];
19145
- if (profiles.length === 0) {
19146
- return "No voice profiles found. Free local scan works without a profile. Run: hyv init";
19147
- }
19148
- return profiles.map(
19149
- (p) => `${p.name}${p.is_default ? " (default)" : ""}${p.keywords?.length ? " \u2014 " + p.keywords.slice(0, 3).join(", ") : ""}`
19150
- ).join("\n");
19151
- } catch (err) {
19152
- const msg = err.message || "";
19153
- if (msg.includes("session expired") || msg.includes("not signed in")) {
19154
- return "Not signed in. Free local scan/fix/check work offline. Run `hyv init` for profiles.";
19155
- }
19156
- return `Cached profiles: none. Free local engine ready. (${msg})`;
19157
- }
19526
+ const hydrate = await ensureMcpProfilesHydrated();
19527
+ return formatMcpProfilesList(hydrate);
19158
19528
  }
19159
19529
  async function toolValidate(args2) {
19160
19530
  const text = args2.text || "";
@@ -19262,6 +19632,22 @@ function toolListFreeTools() {
19262
19632
  function toolDemo() {
19263
19633
  return getDemoText();
19264
19634
  }
19635
+ function toolMcpSetup(args2 = {}) {
19636
+ const action = (args2.action || "status").toLowerCase();
19637
+ const force = Boolean(args2.force);
19638
+ switch (action) {
19639
+ case "status":
19640
+ return buildMcpAgentStatus();
19641
+ case "integrate": {
19642
+ const result = runMcpAutoIntegrate({ force });
19643
+ return formatMcpIntegrateReportText(result, { force });
19644
+ }
19645
+ case "chatgpt":
19646
+ return formatChatGptConnectorGuide();
19647
+ default:
19648
+ return `Error: unknown action "${args2.action}". Use status, integrate, or chatgpt.`;
19649
+ }
19650
+ }
19265
19651
  async function toolAnalyze(args2) {
19266
19652
  const text = args2.text || "";
19267
19653
  if (!text.trim())
@@ -19356,6 +19742,23 @@ async function toolClean(args2) {
19356
19742
  }
19357
19743
  }
19358
19744
  var TOOLS = [
19745
+ {
19746
+ name: "hyv_mcp_setup",
19747
+ description: "MCP host setup without terminal: status of installed apps, auto-integrate configs, or ChatGPT Desktop connector steps. Works with or without a voice profile \u2014 use hyv_welcome for onboarding.",
19748
+ inputSchema: {
19749
+ type: "object",
19750
+ properties: {
19751
+ action: {
19752
+ type: "string",
19753
+ description: "status (default) | integrate (wire hyv into Cursor/Claude/etc.) | chatgpt (desktop connector steps)"
19754
+ },
19755
+ force: {
19756
+ type: "boolean",
19757
+ description: "Refresh MCP configs even when already integrated (e.g. after hyv upgrade)"
19758
+ }
19759
+ }
19760
+ }
19761
+ },
19359
19762
  {
19360
19763
  name: "hyv_welcome",
19361
19764
  description: "Profile-first onboarding: name \u2192 samples \u2192 test draft \u2192 signup. Call when the user is new. Use step (1-4) for one step, mode extract_prompt for chat voice extraction.",
@@ -19478,7 +19881,7 @@ var TOOLS = [
19478
19881
  },
19479
19882
  {
19480
19883
  name: "hyv_profiles",
19481
- description: "List cached or account voice profiles. Falls back gracefully when not signed in.",
19884
+ description: "List voice profiles ready for MCP tools (local + account after hyv init). Shows active default. Call before hyv_rewrite/hyv_clean if unsure which profile to use.",
19482
19885
  inputSchema: { type: "object", properties: {} }
19483
19886
  },
19484
19887
  {
@@ -19503,14 +19906,15 @@ var PROMPTS = [
19503
19906
  ];
19504
19907
  var HYV_STATUS_PROMPT = `Use hold your voice MCP tools:
19505
19908
 
19506
- 1. New user \u2192 hyv_welcome (or step 1\u20134). Step 2: hyv_welcome mode=extract_prompt to build profile from chat.
19507
- 2. Save profile \u2192 user runs hyv import <name> file.md (or you draft markdown for them).
19508
- 3. hyv_profiles \u2014 list local/account profiles.
19509
- 4. Writing: hyv_scan \u2192 hyv_fix / hyv_rewrite \u2192 hyv_validate.
19510
- 5. Ready to pay \u2192 hyv init + hyv plan --upgrade (signup last, not first).
19909
+ 0. MCP setup \u2192 hyv_mcp_setup (status | integrate | chatgpt). Profiles \u2192 hyv_profiles (lists MCP-ready profiles).
19910
+ 1. Profiles work automatically: terminal \`hyv welcome\` saves locally; dashboard profiles need \`hyv init\` once on this machine (MCP auto-syncs).
19911
+ 2. New onboarding in chat \u2192 hyv_welcome. Step 2: mode=extract_prompt. Save markdown \u2192 hyv import or dashboard.
19912
+ 3. Writing (use active profile from hyv_profiles): hyv_scan \u2192 hyv_fix / hyv_rewrite \u2192 hyv_validate. Optional profile= slug.
19913
+ 4. Paid extras \u2192 hyv init + hyv plan --upgrade (signup last).
19511
19914
 
19512
19915
  Keep the answer compact.`;
19513
19916
  var TOOL_HANDLERS = {
19917
+ hyv_mcp_setup: toolMcpSetup,
19514
19918
  hyv_welcome: toolWelcome,
19515
19919
  hyv_list_free_tools: () => toolListFreeTools(),
19516
19920
  hyv_demo: () => toolDemo(),
@@ -19605,14 +20009,31 @@ async function handleRequest(line) {
19605
20009
  }
19606
20010
  async function startMcpServer() {
19607
20011
  const access = await getAccessState().catch(() => null);
19608
- if (fs26.existsSync(VOICE_MD)) {
20012
+ const config = (() => {
20013
+ try {
20014
+ return JSON.parse(fs27.readFileSync(path25.join(os13.homedir(), ".hyv", "config.json"), "utf-8"));
20015
+ } catch {
20016
+ return {};
20017
+ }
20018
+ })();
20019
+ const defaultProfile = config.default_profile || config.profile;
20020
+ if (defaultProfile) {
20021
+ mcpLog("info", `default profile: ${defaultProfile}`);
20022
+ } else if (fs27.existsSync(VOICE_MD)) {
19609
20023
  mcpLog("info", `voice profile: ${VOICE_MD}`);
19610
20024
  } else {
19611
- mcpLog("info", "free local engine ready \u2014 no voice profile yet");
20025
+ mcpLog("info", "free local engine ready \u2014 no voice profile yet (hyv_profiles / hyv init)");
19612
20026
  }
19613
20027
  if (access) {
19614
20028
  mcpLog("info", `mode: ${access.hasPaidPlan ? "paid" : "free local"}${access.authenticated ? "" : " (not signed in)"}`);
19615
20029
  }
20030
+ ensureMcpProfilesHydrated().then((r) => {
20031
+ if (r.synced?.length)
20032
+ mcpLog("info", `synced account profiles: ${r.synced.join(", ")}`);
20033
+ else if (r.error)
20034
+ mcpLog("info", `account profile sync skipped: ${r.error}`);
20035
+ }).catch(() => {
20036
+ });
19616
20037
  let buffer = "";
19617
20038
  process.stdin.setEncoding("utf-8");
19618
20039
  let requestChain = Promise.resolve();
@@ -19637,150 +20058,184 @@ async function startMcpServer() {
19637
20058
  }
19638
20059
 
19639
20060
  // src/lib/mcp-setup.ts
19640
- var import_chalk32 = __toESM(require_source());
19641
- var fs27 = __toESM(require("fs"));
19642
- var path25 = __toESM(require("path"));
19643
- var os12 = __toESM(require("os"));
20061
+ var import_chalk34 = __toESM(require_source());
20062
+ var fs28 = __toESM(require("fs"));
20063
+ var path26 = __toESM(require("path"));
20064
+ var os14 = __toESM(require("os"));
19644
20065
  init_version();
19645
- var HOME2 = os12.homedir();
20066
+ var HOME2 = os14.homedir();
19646
20067
  var IS_WIN2 = process.platform === "win32";
19647
20068
  function claudeDesktopConfigPath() {
19648
20069
  if (IS_WIN2)
19649
- return path25.join(HOME2, "AppData", "Roaming", "Claude", "claude_desktop_config.json");
20070
+ return path26.join(HOME2, "AppData", "Roaming", "Claude", "claude_desktop_config.json");
19650
20071
  if (process.platform === "linux")
19651
- return path25.join(HOME2, ".config", "Claude", "claude_desktop_config.json");
19652
- return path25.join(HOME2, "Library", "Application Support", "Claude", "claude_desktop_config.json");
20072
+ return path26.join(HOME2, ".config", "Claude", "claude_desktop_config.json");
20073
+ return path26.join(HOME2, "Library", "Application Support", "Claude", "claude_desktop_config.json");
19653
20074
  }
19654
20075
  function printMcpSetup() {
19655
- console.log(import_chalk32.default.bold("\nhold your voice \u2014 mcp setup\n"));
19656
- console.log(import_chalk32.default.dim(` ${getEngineLabel()}
20076
+ console.log(import_chalk34.default.bold("\nhold your voice \u2014 mcp setup\n"));
20077
+ console.log(import_chalk34.default.dim(` ${getEngineLabel()}
19657
20078
  `));
19658
- console.log(import_chalk32.default.bold("Claude Desktop"));
19659
- console.log(import_chalk32.default.dim(" Add to claude_desktop_config.json \u2192 mcpServers.hyv:"));
19660
- console.log(import_chalk32.default.cyan(` ${mcpServerSnippet().split("\n").join("\n ")}`));
19661
- console.log(import_chalk32.default.dim(` Config: ${claudeDesktopConfigPath()}
20079
+ console.log(import_chalk34.default.bold("Claude Desktop"));
20080
+ console.log(import_chalk34.default.dim(" Add to claude_desktop_config.json \u2192 mcpServers.hyv:"));
20081
+ console.log(import_chalk34.default.cyan(` ${mcpServerSnippet().split("\n").join("\n ")}`));
20082
+ console.log(import_chalk34.default.dim(` Config: ${claudeDesktopConfigPath()}
19662
20083
  `));
19663
- console.log(import_chalk32.default.bold("Cursor"));
19664
- console.log(import_chalk32.default.dim(" MCP: ~/.cursor/mcp.json \u2192 mcpServers.hyv (same JSON as above)"));
19665
- console.log(import_chalk32.default.dim(" Rule: ~/.cursor/rules/hyv.mdc (alwaysApply \u2014 auto via postinstall)\n"));
19666
- console.log(import_chalk32.default.bold("Claude Code"));
19667
- console.log(import_chalk32.default.dim(" Command: ~/.claude/commands/hyv.md"));
19668
- console.log(import_chalk32.default.dim(" Skill: ~/.claude/skills/hold-your-voice/SKILL.md\n"));
19669
- console.log(import_chalk32.default.bold("Windsurf"));
19670
- console.log(import_chalk32.default.dim(" Rule: ~/.windsurf/rules/hyv.md (trigger: always_on)\n"));
19671
- console.log(import_chalk32.default.bold("Codex"));
19672
- console.log(import_chalk32.default.dim(" Instructions: ~/.codex/AGENTS.md (merged on install)\n"));
19673
- console.log(import_chalk32.default.bold("Command Code"));
19674
- console.log(import_chalk32.default.dim(" Skill: ~/.commandcode/skills/hyv/SKILL.md\n"));
19675
- console.log(import_chalk32.default.bold("ChatGPT Desktop (manual connector)"));
19676
- console.log(import_chalk32.default.dim(" Settings \u2192 Connectors \u2192 add connector"));
19677
- console.log(import_chalk32.default.dim(" Name: hold your voice | Command: hyv | Arguments: mcp"));
19678
- console.log(import_chalk32.default.dim(" Guide: ~/.chatgpt/hyv-mcp-connector.txt (after hyv doctor --fix-agents)"));
19679
- console.log(import_chalk32.default.dim(" hyv mcp --setup-chatgpt\n"));
19680
- console.log(import_chalk32.default.bold("Antigravity"));
19681
- console.log(import_chalk32.default.dim(" MCP: ~/.gemini/config/mcp_config.json \u2192 mcpServers.hyv (auto via postinstall)\n"));
19682
- console.log(import_chalk32.default.bold("OpenCode"));
19683
- console.log(import_chalk32.default.dim(" MCP: ~/.config/opencode/opencode.jsonc \u2192 mcp.hyv (auto via postinstall)"));
19684
- console.log(import_chalk32.default.dim(" Rules: ~/.config/opencode/AGENTS.md\n"));
19685
- console.log(import_chalk32.default.bold("Auto-configure"));
19686
- console.log(import_chalk32.default.dim(" hyv doctor --fix-agents"));
19687
- console.log(import_chalk32.default.dim(" HYV_AUTO_CONFIGURE_AGENTS=0 npm i -g @holdyourvoice/hyv (skip)\n"));
19688
- console.log(import_chalk32.default.bold("Verify"));
19689
- console.log(import_chalk32.default.dim(" hyv mcp --test"));
19690
- console.log(import_chalk32.default.dim(" HYV_TELEMETRY=1 hyv mcp (optional usage logging to ~/.hyv/telemetry/)\n"));
20084
+ console.log(import_chalk34.default.bold("Cursor"));
20085
+ console.log(import_chalk34.default.dim(" MCP: ~/.cursor/mcp.json \u2192 mcpServers.hyv (same JSON as above)"));
20086
+ console.log(import_chalk34.default.dim(" Rule: ~/.cursor/rules/hyv.mdc (alwaysApply \u2014 auto via postinstall)\n"));
20087
+ console.log(import_chalk34.default.bold("Claude Code"));
20088
+ console.log(import_chalk34.default.dim(" Command: ~/.claude/commands/hyv.md"));
20089
+ console.log(import_chalk34.default.dim(" Skill: ~/.claude/skills/hold-your-voice/SKILL.md\n"));
20090
+ console.log(import_chalk34.default.bold("Windsurf"));
20091
+ console.log(import_chalk34.default.dim(" Rule: ~/.windsurf/rules/hyv.md (trigger: always_on)\n"));
20092
+ console.log(import_chalk34.default.bold("Codex"));
20093
+ console.log(import_chalk34.default.dim(" Instructions: ~/.codex/AGENTS.md (merged on install)\n"));
20094
+ console.log(import_chalk34.default.bold("Command Code"));
20095
+ console.log(import_chalk34.default.dim(" Skill: ~/.commandcode/skills/hyv/SKILL.md\n"));
20096
+ console.log(import_chalk34.default.bold("ChatGPT Desktop (manual connector)"));
20097
+ console.log(import_chalk34.default.dim(" Settings \u2192 Connectors \u2192 add connector"));
20098
+ console.log(import_chalk34.default.dim(" Name: hold your voice | Command: hyv | Arguments: mcp"));
20099
+ console.log(import_chalk34.default.dim(" Guide: ~/.chatgpt/hyv-mcp-connector.txt (after hyv doctor --fix-agents)"));
20100
+ console.log(import_chalk34.default.dim(" hyv mcp --setup-chatgpt"));
20101
+ if (IS_WIN2) {
20102
+ console.log(import_chalk34.default.dim(" Windows (Lenovo/Win11 often Restricted): if blocked use:"));
20103
+ console.log(import_chalk34.default.cyan(' powershell -ExecutionPolicy Bypass -Command "hyv ..."'));
20104
+ console.log(import_chalk34.default.dim(" Diagnose: Get-ExecutionPolicy -List"));
20105
+ console.log(import_chalk34.default.dim(" Permanent fix: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force"));
20106
+ console.log(import_chalk34.default.dim(" For connectors: use full path printed in the .txt (node + .js)"));
20107
+ }
20108
+ console.log("");
20109
+ console.log(import_chalk34.default.bold("Antigravity"));
20110
+ console.log(import_chalk34.default.dim(" MCP: ~/.gemini/config/mcp_config.json \u2192 mcpServers.hyv (auto via postinstall)\n"));
20111
+ console.log(import_chalk34.default.bold("OpenCode"));
20112
+ console.log(import_chalk34.default.dim(" MCP: ~/.config/opencode/opencode.jsonc \u2192 mcp.hyv (auto via postinstall)"));
20113
+ console.log(import_chalk34.default.dim(" Rules: ~/.config/opencode/AGENTS.md\n"));
20114
+ console.log(import_chalk34.default.bold("Auto-configure"));
20115
+ console.log(import_chalk34.default.dim(" hyv mcp (detect installed apps + wire mcp into them)"));
20116
+ console.log(import_chalk34.default.dim(" hyv mcp --force (refresh configs after hyv upgrade)"));
20117
+ console.log(import_chalk34.default.dim(" hyv doctor --fix-agents (configure all apps, not just detected)"));
20118
+ console.log(import_chalk34.default.dim(" HYV_AUTO_CONFIGURE_AGENTS=0 npm i -g @holdyourvoice/hyv (skip)\n"));
20119
+ console.log(import_chalk34.default.bold("In-chat (no terminal)"));
20120
+ console.log(import_chalk34.default.dim(" hyv_mcp_setup \u2014 status, integrate, or chatgpt connector steps"));
20121
+ console.log(import_chalk34.default.dim(" hyv_welcome \u2014 finish onboarding inside Cursor/Claude/ChatGPT\n"));
20122
+ console.log(import_chalk34.default.bold("Verify"));
20123
+ console.log(import_chalk34.default.dim(" hyv mcp --test"));
20124
+ console.log(import_chalk34.default.dim(" HYV_TELEMETRY=1 hyv mcp (optional usage logging to ~/.hyv/telemetry/)\n"));
19691
20125
  }
19692
20126
  async function runMcpSelfTest() {
19693
- console.log(import_chalk32.default.bold("\nhold your voice \u2014 mcp self-test\n"));
19694
- console.log(import_chalk32.default.dim(` ${getEngineLabel()}
20127
+ console.log(import_chalk34.default.bold("\nhold your voice \u2014 mcp self-test\n"));
20128
+ console.log(import_chalk34.default.dim(` ${getEngineLabel()}
19695
20129
  `));
19696
20130
  let passed = 0;
19697
20131
  let failed = 0;
19698
20132
  const tools = getMcpToolNames();
19699
20133
  if (tools.length >= 10) {
19700
- console.log(import_chalk32.default.green(` \u2713 ${tools.length} MCP tools registered`));
20134
+ console.log(import_chalk34.default.green(` \u2713 ${tools.length} MCP tools registered`));
19701
20135
  passed++;
19702
20136
  } else {
19703
- console.log(import_chalk32.default.red(` \u2717 expected 10+ tools, got ${tools.length}`));
20137
+ console.log(import_chalk34.default.red(` \u2717 expected 10+ tools, got ${tools.length}`));
19704
20138
  failed++;
19705
20139
  }
19706
- const required = ["hyv_welcome", "hyv_scan", "hyv_analyze", "hyv_clean", "hyv_validate", "hyv_list_free_tools"];
20140
+ const required = [
20141
+ "hyv_mcp_setup",
20142
+ "hyv_welcome",
20143
+ "hyv_scan",
20144
+ "hyv_analyze",
20145
+ "hyv_clean",
20146
+ "hyv_validate",
20147
+ "hyv_list_free_tools"
20148
+ ];
19707
20149
  for (const name of required) {
19708
20150
  if (tools.includes(name)) {
19709
- console.log(import_chalk32.default.green(` \u2713 tool: ${name}`));
20151
+ console.log(import_chalk34.default.green(` \u2713 tool: ${name}`));
19710
20152
  passed++;
19711
20153
  } else {
19712
- console.log(import_chalk32.default.red(` \u2717 missing tool: ${name}`));
20154
+ console.log(import_chalk34.default.red(` \u2717 missing tool: ${name}`));
19713
20155
  failed++;
19714
20156
  }
19715
20157
  }
19716
20158
  try {
19717
20159
  const welcome = await invokeMcpTool("hyv_welcome", {});
19718
20160
  if (welcome.includes("Hold Your Voice") || welcome.includes("hold your voice")) {
19719
- console.log(import_chalk32.default.green(" \u2713 hyv_welcome responds"));
20161
+ console.log(import_chalk34.default.green(" \u2713 hyv_welcome responds"));
19720
20162
  passed++;
19721
20163
  } else {
19722
- console.log(import_chalk32.default.red(" \u2717 hyv_welcome unexpected output"));
20164
+ console.log(import_chalk34.default.red(" \u2717 hyv_welcome unexpected output"));
19723
20165
  failed++;
19724
20166
  }
19725
20167
  } catch (e) {
19726
- console.log(import_chalk32.default.red(` \u2717 hyv_welcome failed: ${e.message}`));
20168
+ console.log(import_chalk34.default.red(` \u2717 hyv_welcome failed: ${e.message}`));
20169
+ failed++;
20170
+ }
20171
+ try {
20172
+ const setup = await invokeMcpTool("hyv_mcp_setup", { action: "status" });
20173
+ if (setup.includes("HYV MCP status") && setup.includes("hyv_welcome")) {
20174
+ console.log(import_chalk34.default.green(" \u2713 hyv_mcp_setup responds"));
20175
+ passed++;
20176
+ } else {
20177
+ console.log(import_chalk34.default.red(" \u2717 hyv_mcp_setup unexpected output"));
20178
+ failed++;
20179
+ }
20180
+ } catch (e) {
20181
+ console.log(import_chalk34.default.red(` \u2717 hyv_mcp_setup failed: ${e.message}`));
19727
20182
  failed++;
19728
20183
  }
19729
20184
  try {
19730
20185
  const demo = await invokeMcpTool("hyv_demo", {});
19731
20186
  if (demo.includes("Score") || demo.includes("issues")) {
19732
- console.log(import_chalk32.default.green(" \u2713 hyv_demo pipeline works"));
20187
+ console.log(import_chalk34.default.green(" \u2713 hyv_demo pipeline works"));
19733
20188
  passed++;
19734
20189
  } else {
19735
- console.log(import_chalk32.default.red(" \u2717 hyv_demo unexpected output"));
20190
+ console.log(import_chalk34.default.red(" \u2717 hyv_demo unexpected output"));
19736
20191
  failed++;
19737
20192
  }
19738
20193
  } catch (e) {
19739
- console.log(import_chalk32.default.red(` \u2717 hyv_demo failed: ${e.message}`));
20194
+ console.log(import_chalk34.default.red(` \u2717 hyv_demo failed: ${e.message}`));
19740
20195
  failed++;
19741
20196
  }
19742
- const voiceMd = path25.join(HOME2, ".hyv", "voice.md");
19743
- if (fs27.existsSync(voiceMd)) {
19744
- console.log(import_chalk32.default.green(" \u2713 voice profile found"));
20197
+ const voiceMd = path26.join(HOME2, ".hyv", "voice.md");
20198
+ if (fs28.existsSync(voiceMd)) {
20199
+ console.log(import_chalk34.default.green(" \u2713 voice profile found"));
19745
20200
  passed++;
19746
20201
  } else {
19747
- console.log(import_chalk32.default.dim(" - no voice.md (free local engine still works)"));
20202
+ console.log(import_chalk34.default.dim(" - no voice.md (free local engine still works)"));
19748
20203
  }
19749
20204
  if (getDemoText().length > 100) {
19750
- console.log(import_chalk32.default.green(" \u2713 demo content available"));
20205
+ console.log(import_chalk34.default.green(" \u2713 demo content available"));
19751
20206
  passed++;
19752
20207
  } else {
19753
- console.log(import_chalk32.default.red(" \u2717 demo content missing"));
20208
+ console.log(import_chalk34.default.red(" \u2717 demo content missing"));
19754
20209
  failed++;
19755
20210
  }
19756
20211
  try {
19757
20212
  const stdio = await testMcpStdioSubprocess();
19758
20213
  if (stdio.ok && (stdio.toolCount || 0) >= 10) {
19759
- console.log(import_chalk32.default.green(` \u2713 stdio MCP subprocess responds (${stdio.toolCount} tools)`));
20214
+ console.log(import_chalk34.default.green(` \u2713 stdio MCP subprocess responds (${stdio.toolCount} tools)`));
19760
20215
  passed++;
19761
20216
  } else if (stdio.ok) {
19762
- console.log(import_chalk32.default.yellow(` ! stdio MCP subprocess ok but only ${stdio.toolCount || 0} tools`));
20217
+ console.log(import_chalk34.default.yellow(` ! stdio MCP subprocess ok but only ${stdio.toolCount || 0} tools`));
19763
20218
  failed++;
19764
20219
  } else {
19765
- console.log(import_chalk32.default.red(" \u2717 stdio MCP subprocess failed"));
20220
+ console.log(import_chalk34.default.red(" \u2717 stdio MCP subprocess failed"));
19766
20221
  failed++;
19767
20222
  }
19768
20223
  } catch (e) {
19769
- console.log(import_chalk32.default.red(` \u2717 stdio MCP subprocess failed: ${e.message}`));
20224
+ console.log(import_chalk34.default.red(` \u2717 stdio MCP subprocess failed: ${e.message}`));
19770
20225
  failed++;
19771
20226
  }
19772
20227
  console.log("");
19773
20228
  if (failed === 0) {
19774
- console.log(import_chalk32.default.green(`\u2713 all checks passed (${passed})`));
19775
- console.log(import_chalk32.default.dim("\nStart server: hyv mcp\n"));
20229
+ console.log(import_chalk34.default.green(`\u2713 all checks passed (${passed})`));
20230
+ console.log(import_chalk34.default.dim("\nStart server: hyv mcp\n"));
19776
20231
  return true;
19777
20232
  }
19778
- console.log(import_chalk32.default.yellow(`! ${failed} check(s) failed, ${passed} passed`));
20233
+ console.log(import_chalk34.default.yellow(`! ${failed} check(s) failed, ${passed} passed`));
19779
20234
  return false;
19780
20235
  }
19781
20236
 
19782
20237
  // src/commands/export.ts
19783
- var fs28 = __toESM(require("fs"));
20238
+ var fs29 = __toESM(require("fs"));
19784
20239
  init_api();
19785
20240
  var FORMATS = {
19786
20241
  claude: {
@@ -19867,7 +20322,7 @@ async function exportCommand(format, opts) {
19867
20322
  const prompt = fmt.wrap(detail.profile, detail.body);
19868
20323
  if (opts.output) {
19869
20324
  const outFile = opts.output.replace("{name}", profile.slug || profile.name);
19870
- fs28.writeFileSync(outFile, prompt);
20325
+ fs29.writeFileSync(outFile, prompt);
19871
20326
  results.push({ profile: profile.name, file: outFile });
19872
20327
  } else {
19873
20328
  results.push({ profile: profile.name, prompt });
@@ -19904,13 +20359,13 @@ async function exportCommand(format, opts) {
19904
20359
  // src/index.ts
19905
20360
  init_access();
19906
20361
  init_welcome();
19907
- var fs29 = __toESM(require("fs"));
19908
- var path26 = __toESM(require("path"));
20362
+ var fs30 = __toESM(require("fs"));
20363
+ var path27 = __toESM(require("path"));
19909
20364
  var program2 = new Command();
19910
- var pkgPath2 = path26.resolve(__dirname, "..", "package.json");
20365
+ var pkgPath2 = path27.resolve(__dirname, "..", "package.json");
19911
20366
  var pkgVersion2 = (() => {
19912
20367
  try {
19913
- return JSON.parse(fs29.readFileSync(pkgPath2, "utf-8")).version;
20368
+ return JSON.parse(fs30.readFileSync(pkgPath2, "utf-8")).version;
19914
20369
  } catch {
19915
20370
  return "2.7.1";
19916
20371
  }
@@ -19956,22 +20411,55 @@ program2.command("mcp").description("Start MCP server (for Claude Desktop and ot
19956
20411
  if (opts.setupChatgpt) {
19957
20412
  const home = require("os").homedir();
19958
20413
  const guide = require("path").join(home, ".chatgpt", "hyv-mcp-connector.txt");
19959
- console.log(import_chalk33.default.bold("\nhold your voice \u2014 chatgpt desktop mcp setup\n"));
19960
- console.log("ChatGPT has no auto-config file. Add this connector once in the desktop app:\n");
19961
- console.log(import_chalk33.default.dim(" 1. Install hyv: ") + import_chalk33.default.cyan("npm i -g @holdyourvoice/hyv@latest && hyv welcome"));
19962
- console.log(import_chalk33.default.dim(" 2. Open ") + import_chalk33.default.cyan("https://chatgpt.com/#settings/Connectors"));
19963
- console.log(import_chalk33.default.dim(" 3. Add connector"));
19964
- console.log(import_chalk33.default.dim(" 4. Name: ") + import_chalk33.default.cyan("hold your voice"));
19965
- console.log(import_chalk33.default.dim(" 5. Command: ") + import_chalk33.default.cyan("hyv"));
19966
- console.log(import_chalk33.default.dim(" 6. Arguments: ") + import_chalk33.default.cyan("mcp"));
19967
- console.log(import_chalk33.default.dim(" 7. Save, restart ChatGPT Desktop, ask: scan this with hold your voice"));
19968
- console.log("");
20414
+ console.log(import_chalk35.default.bold("\nhold your voice \u2014 chatgpt desktop setup\n"));
20415
+ console.log(import_chalk35.default.bold("=== which setup do i have? ===\n"));
20416
+ console.log(import_chalk35.default.dim(' If you see "New App" with a Server URL field:'));
20417
+ console.log(import_chalk35.default.dim(" \u2192 Developer mode is ON \u2192 use PATH A (remote, below)"));
20418
+ console.log(import_chalk35.default.dim(' If you see "Connectors" with Command/Arguments fields:'));
20419
+ console.log(import_chalk35.default.dim(" \u2192 use PATH B (local, below)"));
20420
+ console.log(import_chalk35.default.dim(" Neither? Turn Developer mode ON in ChatGPT settings.\n"));
20421
+ console.log(import_chalk35.default.bold("=== PATH A \u2014 remote mcp (Developer mode \u2192 New App) ==="));
20422
+ console.log(import_chalk35.default.dim(" Requires: paid HYV plan + ChatGPT Desktop + Developer mode ON\n"));
20423
+ console.log(import_chalk35.default.dim(" 1. In ChatGPT: Settings \u2192 turn ") + import_chalk35.default.cyan("Developer mode") + import_chalk35.default.dim(" ON"));
20424
+ console.log(import_chalk35.default.dim(" (Accept the elevated risk warning \u2014 expected, not a HYV bug)"));
20425
+ console.log(import_chalk35.default.dim(" 2. Settings \u2192 Apps \u2192 ") + import_chalk35.default.cyan("New App"));
20426
+ console.log(import_chalk35.default.dim(" 3. Fill in:"));
20427
+ console.log(import_chalk35.default.dim(" Name: ") + import_chalk35.default.cyan("hold your voice"));
20428
+ console.log(import_chalk35.default.dim(" Description: ") + import_chalk35.default.cyan("Scans writing for AI patterns and voice drift"));
20429
+ console.log(import_chalk35.default.dim(" Connection: ") + import_chalk35.default.cyan("Server URL") + import_chalk35.default.dim(" \u2192 ") + import_chalk35.default.cyan("https://holdyourvoice.com/mcp"));
20430
+ console.log(import_chalk35.default.dim(" Authentication: ") + import_chalk35.default.cyan("OAuth"));
20431
+ console.log(import_chalk35.default.dim(" Checkbox: ") + import_chalk35.default.cyan('"I understand and want to continue"'));
20432
+ console.log(import_chalk35.default.dim(" 4. Save \u2192 complete OAuth sign-in to holdyourvoice.com"));
20433
+ console.log(import_chalk35.default.dim(' 5. Test: "scan this with hold your voice"\n'));
20434
+ console.log(import_chalk35.default.dim(" Cloud app setup: ") + import_chalk35.default.cyan("https://holdyourvoice.com/app/api/mcp"));
20435
+ console.log(import_chalk35.default.dim(" Wiki guide: ") + import_chalk35.default.cyan("https://holdyourvoice.com/wiki/use-hyv-in-chatgpt\n"));
20436
+ console.log(import_chalk35.default.bold("=== PATH B \u2014 local connector (Connectors \u2192 Command/Arguments) ==="));
20437
+ console.log(import_chalk35.default.dim(" Requires: Node.js 18+ + ChatGPT Desktop (free offline scan)\n"));
20438
+ console.log(import_chalk35.default.dim(" 1. Install hyv: ") + import_chalk35.default.cyan("npm i -g @holdyourvoice/hyv@latest && hyv welcome"));
20439
+ console.log(import_chalk35.default.dim(" 2. In ChatGPT: ") + import_chalk35.default.cyan("Settings \u2192 Connectors") + import_chalk35.default.dim(" (or https://chatgpt.com/#settings/Connectors)"));
20440
+ console.log(import_chalk35.default.dim(" 3. Add connector:"));
20441
+ console.log(import_chalk35.default.dim(" Name: ") + import_chalk35.default.cyan("hold your voice"));
20442
+ console.log(import_chalk35.default.dim(" Command: ") + import_chalk35.default.cyan("hyv") + import_chalk35.default.dim(" (full path on Windows if needed)"));
20443
+ console.log(import_chalk35.default.dim(" Arguments: ") + import_chalk35.default.cyan("mcp"));
20444
+ console.log(import_chalk35.default.dim(" 4. Save, restart ChatGPT Desktop"));
20445
+ console.log(import_chalk35.default.dim(' 5. Test: "scan this with hold your voice"\n'));
20446
+ console.log(import_chalk35.default.dim(" If connector fails to start, use full paths from:"));
20447
+ console.log(import_chalk35.default.cyan(" " + guide));
20448
+ console.log(import_chalk35.default.dim(""));
20449
+ console.log(import_chalk35.default.dim('Windows tip: If you get "running scripts is disabled", use:'));
20450
+ console.log(import_chalk35.default.cyan(' powershell -ExecutionPolicy Bypass -Command "hyv mcp --setup-chatgpt"'));
20451
+ console.log(import_chalk35.default.dim(" Fix once: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force"));
20452
+ console.log(import_chalk35.default.dim(" In ChatGPT connector use the FULL path from the connector .txt file\n"));
20453
+ console.log(import_chalk35.default.bold("=== not seeing either UI? ==="));
20454
+ console.log(import_chalk35.default.dim(" \u2022 Turn Developer mode ON in ChatGPT settings for New App"));
20455
+ console.log(import_chalk35.default.dim(" \u2022 Connectors may require ChatGPT Plus"));
20456
+ console.log(import_chalk35.default.dim(" \u2022 Browser ChatGPT cannot use either path \u2014 desktop app only\n"));
19969
20457
  if (require("fs").existsSync(guide)) {
19970
- console.log(import_chalk33.default.dim(`Full guide written to: ${guide}`));
20458
+ console.log(import_chalk35.default.dim(` Full connector paths written to: ${guide}`));
19971
20459
  } else {
19972
- console.log(import_chalk33.default.dim("Run hyv doctor --fix-agents to write ~/.chatgpt/hyv-mcp-connector.txt"));
20460
+ console.log(import_chalk35.default.dim(" Run hyv doctor --fix-agents to write " + guide));
19973
20461
  }
19974
- console.log(import_chalk33.default.dim("\nBrowser chatgpt cannot use local MCP \u2014 desktop app only."));
20462
+ console.log("");
19975
20463
  return;
19976
20464
  }
19977
20465
  startMcpServer();