@holdyourvoice/hyv 2.8.8 → 2.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +25 -2
- package/dist/index.js +616 -446
- package/package.json +3 -2
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
|
|
977
|
-
var
|
|
976
|
+
var path24 = require("node:path");
|
|
977
|
+
var fs25 = 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 =
|
|
1920
|
-
if (
|
|
1919
|
+
const localBin = path24.resolve(baseDir, baseName);
|
|
1920
|
+
if (fs25.existsSync(localBin))
|
|
1921
1921
|
return localBin;
|
|
1922
|
-
if (sourceExt.includes(
|
|
1922
|
+
if (sourceExt.includes(path24.extname(baseName)))
|
|
1923
1923
|
return void 0;
|
|
1924
1924
|
const foundExt = sourceExt.find(
|
|
1925
|
-
(ext) =>
|
|
1925
|
+
(ext) => fs25.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 =
|
|
1938
|
+
resolvedScriptPath = fs25.realpathSync(this._scriptPath);
|
|
1939
1939
|
} catch (err) {
|
|
1940
1940
|
resolvedScriptPath = this._scriptPath;
|
|
1941
1941
|
}
|
|
1942
|
-
executableDir =
|
|
1943
|
-
|
|
1942
|
+
executableDir = path24.resolve(
|
|
1943
|
+
path24.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 =
|
|
1950
|
+
const legacyName = path24.basename(
|
|
1951
1951
|
this._scriptPath,
|
|
1952
|
-
|
|
1952
|
+
path24.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(
|
|
1963
|
+
launchWithNode = sourceExt.includes(path24.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 =
|
|
2820
|
+
this._name = path24.basename(filename, path24.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(
|
|
2835
|
-
if (
|
|
2834
|
+
executableDir(path25) {
|
|
2835
|
+
if (path25 === void 0)
|
|
2836
2836
|
return this._executableDir;
|
|
2837
|
-
this._executableDir =
|
|
2837
|
+
this._executableDir = path25;
|
|
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
|
|
3937
|
+
const path24 = [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
|
-
|
|
3941
|
+
path24.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 =
|
|
3945
|
+
fn.conversion = path24;
|
|
3946
3946
|
return fn;
|
|
3947
3947
|
}
|
|
3948
3948
|
module2.exports = function(fromModel) {
|
|
@@ -4381,14 +4381,14 @@ var require_templates = __commonJS({
|
|
|
4381
4381
|
}
|
|
4382
4382
|
return results;
|
|
4383
4383
|
}
|
|
4384
|
-
function buildStyle(
|
|
4384
|
+
function buildStyle(chalk32, 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 =
|
|
4391
|
+
let current = chalk32;
|
|
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 = (
|
|
4403
|
+
module2.exports = (chalk32, 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(
|
|
4413
|
+
chunks.push(styles.length === 0 ? string : buildStyle(chalk32, 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(
|
|
4419
|
+
chunks.push(buildStyle(chalk32, 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
|
|
4468
|
-
applyOptions(
|
|
4469
|
-
|
|
4470
|
-
Object.setPrototypeOf(
|
|
4471
|
-
Object.setPrototypeOf(
|
|
4472
|
-
|
|
4467
|
+
const chalk33 = {};
|
|
4468
|
+
applyOptions(chalk33, options);
|
|
4469
|
+
chalk33.template = (...arguments_) => chalkTag(chalk33.template, ...arguments_);
|
|
4470
|
+
Object.setPrototypeOf(chalk33, Chalk.prototype);
|
|
4471
|
+
Object.setPrototypeOf(chalk33.template, chalk33);
|
|
4472
|
+
chalk33.template.constructor = () => {
|
|
4473
4473
|
throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.");
|
|
4474
4474
|
};
|
|
4475
|
-
|
|
4476
|
-
return
|
|
4475
|
+
chalk33.template.Instance = ChalkClass;
|
|
4476
|
+
return chalk33.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 = (
|
|
4587
|
+
var chalkTag = (chalk33, ...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(
|
|
4603
|
+
return template(chalk33, parts.join(""));
|
|
4604
4604
|
};
|
|
4605
4605
|
Object.defineProperties(Chalk.prototype, styles);
|
|
4606
|
-
var
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
module2.exports =
|
|
4606
|
+
var chalk32 = Chalk();
|
|
4607
|
+
chalk32.supportsColor = stdoutColor;
|
|
4608
|
+
chalk32.stderr = Chalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
4609
|
+
chalk32.stderr.supportsColor = stderrColor;
|
|
4610
|
+
module2.exports = chalk32;
|
|
4611
4611
|
}
|
|
4612
4612
|
});
|
|
4613
4613
|
|
|
@@ -4647,6 +4647,27 @@ function assertSafeOpenUrl(url) {
|
|
|
4647
4647
|
}
|
|
4648
4648
|
return url;
|
|
4649
4649
|
}
|
|
4650
|
+
function assertSafeOAuthUrl(url) {
|
|
4651
|
+
let parsed;
|
|
4652
|
+
try {
|
|
4653
|
+
parsed = new URL(url);
|
|
4654
|
+
} catch {
|
|
4655
|
+
throw new Error("Invalid URL");
|
|
4656
|
+
}
|
|
4657
|
+
if (parsed.protocol !== "https:") {
|
|
4658
|
+
throw new Error("Only https:// URLs can be opened");
|
|
4659
|
+
}
|
|
4660
|
+
if (ALLOWED_API_HOSTS.has(parsed.hostname)) {
|
|
4661
|
+
return url;
|
|
4662
|
+
}
|
|
4663
|
+
if (ALLOWED_OAUTH_HOSTS.has(parsed.hostname)) {
|
|
4664
|
+
if (parsed.hostname === "accounts.google.com" && !parsed.pathname.startsWith("/o/oauth2/")) {
|
|
4665
|
+
throw new Error(`Unexpected OAuth path: ${parsed.pathname}`);
|
|
4666
|
+
}
|
|
4667
|
+
return url;
|
|
4668
|
+
}
|
|
4669
|
+
throw new Error(`URL host not allowed: ${parsed.hostname}`);
|
|
4670
|
+
}
|
|
4650
4671
|
function assertSafeProfileName(name) {
|
|
4651
4672
|
const normalized = String(name || "").trim();
|
|
4652
4673
|
if (!normalized)
|
|
@@ -4804,7 +4825,7 @@ function readLastEditSession() {
|
|
|
4804
4825
|
return null;
|
|
4805
4826
|
}
|
|
4806
4827
|
}
|
|
4807
|
-
var fs, path, os, HYV_DIR, AUTH_FILE, CONFIG_FILE, PROFILES_DIR, CACHE_DIR, QUEUE_DIR, LAST_SESSION_FILE, ALLOWED_API_HOSTS, API_BASE, PROFILE_NAME_RE;
|
|
4828
|
+
var fs, path, os, HYV_DIR, AUTH_FILE, CONFIG_FILE, PROFILES_DIR, CACHE_DIR, QUEUE_DIR, LAST_SESSION_FILE, ALLOWED_API_HOSTS, ALLOWED_OAUTH_HOSTS, API_BASE, PROFILE_NAME_RE;
|
|
4808
4829
|
var init_config = __esm({
|
|
4809
4830
|
"src/lib/config.ts"() {
|
|
4810
4831
|
"use strict";
|
|
@@ -4825,6 +4846,7 @@ var init_config = __esm({
|
|
|
4825
4846
|
"localhost",
|
|
4826
4847
|
"127.0.0.1"
|
|
4827
4848
|
]);
|
|
4849
|
+
ALLOWED_OAUTH_HOSTS = /* @__PURE__ */ new Set(["accounts.google.com"]);
|
|
4828
4850
|
API_BASE = validateApiBase(process.env.HYV_API_URL || "https://holdyourvoice.com");
|
|
4829
4851
|
PROFILE_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,62}$/i;
|
|
4830
4852
|
}
|
|
@@ -4834,11 +4856,11 @@ var init_config = __esm({
|
|
|
4834
4856
|
var require_is_docker = __commonJS({
|
|
4835
4857
|
"node_modules/is-docker/index.js"(exports2, module2) {
|
|
4836
4858
|
"use strict";
|
|
4837
|
-
var
|
|
4859
|
+
var fs25 = require("fs");
|
|
4838
4860
|
var isDocker;
|
|
4839
4861
|
function hasDockerEnv() {
|
|
4840
4862
|
try {
|
|
4841
|
-
|
|
4863
|
+
fs25.statSync("/.dockerenv");
|
|
4842
4864
|
return true;
|
|
4843
4865
|
} catch (_) {
|
|
4844
4866
|
return false;
|
|
@@ -4846,7 +4868,7 @@ var require_is_docker = __commonJS({
|
|
|
4846
4868
|
}
|
|
4847
4869
|
function hasDockerCGroup() {
|
|
4848
4870
|
try {
|
|
4849
|
-
return
|
|
4871
|
+
return fs25.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
4850
4872
|
} catch (_) {
|
|
4851
4873
|
return false;
|
|
4852
4874
|
}
|
|
@@ -4865,7 +4887,7 @@ var require_is_wsl = __commonJS({
|
|
|
4865
4887
|
"node_modules/is-wsl/index.js"(exports2, module2) {
|
|
4866
4888
|
"use strict";
|
|
4867
4889
|
var os9 = require("os");
|
|
4868
|
-
var
|
|
4890
|
+
var fs25 = require("fs");
|
|
4869
4891
|
var isDocker = require_is_docker();
|
|
4870
4892
|
var isWsl = () => {
|
|
4871
4893
|
if (process.platform !== "linux") {
|
|
@@ -4878,7 +4900,7 @@ var require_is_wsl = __commonJS({
|
|
|
4878
4900
|
return true;
|
|
4879
4901
|
}
|
|
4880
4902
|
try {
|
|
4881
|
-
return
|
|
4903
|
+
return fs25.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isDocker() : false;
|
|
4882
4904
|
} catch (_) {
|
|
4883
4905
|
return false;
|
|
4884
4906
|
}
|
|
@@ -4917,17 +4939,17 @@ var require_define_lazy_prop = __commonJS({
|
|
|
4917
4939
|
// node_modules/open/index.js
|
|
4918
4940
|
var require_open = __commonJS({
|
|
4919
4941
|
"node_modules/open/index.js"(exports2, module2) {
|
|
4920
|
-
var
|
|
4942
|
+
var path24 = require("path");
|
|
4921
4943
|
var childProcess = require("child_process");
|
|
4922
|
-
var { promises:
|
|
4944
|
+
var { promises: fs25, constants: fsConstants } = require("fs");
|
|
4923
4945
|
var isWsl = require_is_wsl();
|
|
4924
4946
|
var isDocker = require_is_docker();
|
|
4925
4947
|
var defineLazyProperty = require_define_lazy_prop();
|
|
4926
|
-
var localXdgOpenPath =
|
|
4948
|
+
var localXdgOpenPath = path24.join(__dirname, "xdg-open");
|
|
4927
4949
|
var { platform, arch } = process;
|
|
4928
4950
|
var hasContainerEnv = () => {
|
|
4929
4951
|
try {
|
|
4930
|
-
|
|
4952
|
+
fs25.statSync("/run/.containerenv");
|
|
4931
4953
|
return true;
|
|
4932
4954
|
} catch {
|
|
4933
4955
|
return false;
|
|
@@ -4950,14 +4972,14 @@ var require_open = __commonJS({
|
|
|
4950
4972
|
const configFilePath = "/etc/wsl.conf";
|
|
4951
4973
|
let isConfigFileExists = false;
|
|
4952
4974
|
try {
|
|
4953
|
-
await
|
|
4975
|
+
await fs25.access(configFilePath, fsConstants.F_OK);
|
|
4954
4976
|
isConfigFileExists = true;
|
|
4955
4977
|
} catch {
|
|
4956
4978
|
}
|
|
4957
4979
|
if (!isConfigFileExists) {
|
|
4958
4980
|
return defaultMountPoint;
|
|
4959
4981
|
}
|
|
4960
|
-
const configContent = await
|
|
4982
|
+
const configContent = await fs25.readFile(configFilePath, { encoding: "utf8" });
|
|
4961
4983
|
const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
|
|
4962
4984
|
if (!configMountPoint) {
|
|
4963
4985
|
return defaultMountPoint;
|
|
@@ -5057,7 +5079,7 @@ var require_open = __commonJS({
|
|
|
5057
5079
|
const isBundled = !__dirname || __dirname === "/";
|
|
5058
5080
|
let exeLocalXdgOpen = false;
|
|
5059
5081
|
try {
|
|
5060
|
-
await
|
|
5082
|
+
await fs25.access(localXdgOpenPath, fsConstants.X_OK);
|
|
5061
5083
|
exeLocalXdgOpen = true;
|
|
5062
5084
|
} catch {
|
|
5063
5085
|
}
|
|
@@ -5244,6 +5266,33 @@ var init_version = __esm({
|
|
|
5244
5266
|
}
|
|
5245
5267
|
});
|
|
5246
5268
|
|
|
5269
|
+
// src/lib/auth-refresh.ts
|
|
5270
|
+
function tokenExpiresAtMs(expiresAt) {
|
|
5271
|
+
if (!expiresAt)
|
|
5272
|
+
return null;
|
|
5273
|
+
const ms = new Date(expiresAt).getTime();
|
|
5274
|
+
return Number.isFinite(ms) ? ms : null;
|
|
5275
|
+
}
|
|
5276
|
+
function shouldRefreshToken(expiresAt, now = Date.now()) {
|
|
5277
|
+
const expiresMs = tokenExpiresAtMs(expiresAt);
|
|
5278
|
+
if (expiresMs === null)
|
|
5279
|
+
return false;
|
|
5280
|
+
return expiresMs <= now + REFRESH_LEAD_MS;
|
|
5281
|
+
}
|
|
5282
|
+
function isTokenExpired(expiresAt, now = Date.now()) {
|
|
5283
|
+
const expiresMs = tokenExpiresAtMs(expiresAt);
|
|
5284
|
+
if (expiresMs === null)
|
|
5285
|
+
return false;
|
|
5286
|
+
return expiresMs < now;
|
|
5287
|
+
}
|
|
5288
|
+
var REFRESH_LEAD_MS;
|
|
5289
|
+
var init_auth_refresh = __esm({
|
|
5290
|
+
"src/lib/auth-refresh.ts"() {
|
|
5291
|
+
"use strict";
|
|
5292
|
+
REFRESH_LEAD_MS = 5 * 60 * 1e3;
|
|
5293
|
+
}
|
|
5294
|
+
});
|
|
5295
|
+
|
|
5247
5296
|
// src/lib/auth.ts
|
|
5248
5297
|
var auth_exports = {};
|
|
5249
5298
|
__export(auth_exports, {
|
|
@@ -5252,8 +5301,14 @@ __export(auth_exports, {
|
|
|
5252
5301
|
authenticatedRequest: () => authenticatedRequest,
|
|
5253
5302
|
checkSession: () => checkSession,
|
|
5254
5303
|
getValidToken: () => getValidToken,
|
|
5255
|
-
refreshToken: () => refreshToken
|
|
5304
|
+
refreshToken: () => refreshToken,
|
|
5305
|
+
verifyOAuthState: () => verifyOAuthState
|
|
5256
5306
|
});
|
|
5307
|
+
function verifyOAuthState(received, expected) {
|
|
5308
|
+
if (!received || !expected || received !== expected) {
|
|
5309
|
+
throw new Error("OAuth state mismatch \u2014 possible CSRF attempt");
|
|
5310
|
+
}
|
|
5311
|
+
}
|
|
5257
5312
|
function escapeHtml(value) {
|
|
5258
5313
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
5259
5314
|
}
|
|
@@ -5300,16 +5355,12 @@ async function getValidToken() {
|
|
|
5300
5355
|
const auth = readAuth();
|
|
5301
5356
|
if (!auth?.token)
|
|
5302
5357
|
return null;
|
|
5303
|
-
if (auth.expires_at) {
|
|
5304
|
-
const
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
return getToken();
|
|
5310
|
-
if (expires.getTime() < Date.now())
|
|
5311
|
-
return null;
|
|
5312
|
-
}
|
|
5358
|
+
if (shouldRefreshToken(auth.expires_at)) {
|
|
5359
|
+
const ok = await refreshToken(auth.token);
|
|
5360
|
+
if (ok)
|
|
5361
|
+
return getToken();
|
|
5362
|
+
if (isTokenExpired(auth.expires_at))
|
|
5363
|
+
return null;
|
|
5313
5364
|
}
|
|
5314
5365
|
return auth.token;
|
|
5315
5366
|
}
|
|
@@ -5363,7 +5414,7 @@ async function authenticateWithBrowser() {
|
|
|
5363
5414
|
throw new Error("Authentication server did not return OAuth state");
|
|
5364
5415
|
}
|
|
5365
5416
|
console.log(import_chalk.default.cyan("\nOpening browser for authentication..."));
|
|
5366
|
-
await (0, import_open.default)(
|
|
5417
|
+
await (0, import_open.default)(assertSafeOAuthUrl(auth_url));
|
|
5367
5418
|
const authData = await new Promise((resolve14, reject) => {
|
|
5368
5419
|
const timeout = setTimeout(() => {
|
|
5369
5420
|
server.close();
|
|
@@ -5382,12 +5433,14 @@ async function authenticateWithBrowser() {
|
|
|
5382
5433
|
reject(new Error("Invalid callback parameters"));
|
|
5383
5434
|
return;
|
|
5384
5435
|
}
|
|
5385
|
-
|
|
5436
|
+
try {
|
|
5437
|
+
verifyOAuthState(state, expectedState);
|
|
5438
|
+
} catch (stateErr) {
|
|
5386
5439
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
5387
5440
|
res.end("<h1>Authentication failed</h1><p>Invalid OAuth state.</p>");
|
|
5388
5441
|
clearTimeout(timeout);
|
|
5389
5442
|
server.close();
|
|
5390
|
-
reject(
|
|
5443
|
+
reject(stateErr);
|
|
5391
5444
|
return;
|
|
5392
5445
|
}
|
|
5393
5446
|
try {
|
|
@@ -5481,6 +5534,7 @@ var init_auth = __esm({
|
|
|
5481
5534
|
import_open = __toESM(require_open());
|
|
5482
5535
|
init_config();
|
|
5483
5536
|
init_version();
|
|
5537
|
+
init_auth_refresh();
|
|
5484
5538
|
}
|
|
5485
5539
|
});
|
|
5486
5540
|
|
|
@@ -5641,11 +5695,11 @@ __export(api_exports, {
|
|
|
5641
5695
|
apiPost: () => apiPost,
|
|
5642
5696
|
requireSubscription: () => requireSubscription
|
|
5643
5697
|
});
|
|
5644
|
-
async function request2(method,
|
|
5698
|
+
async function request2(method, path24, body) {
|
|
5645
5699
|
const token = await getValidToken();
|
|
5646
5700
|
if (!token)
|
|
5647
5701
|
throw new Error("you're not signed in yet. run: hyv init");
|
|
5648
|
-
const url = `${API_BASE}${
|
|
5702
|
+
const url = `${API_BASE}${path24}`;
|
|
5649
5703
|
const opts = {
|
|
5650
5704
|
method,
|
|
5651
5705
|
headers: {
|
|
@@ -5670,11 +5724,11 @@ async function request2(method, path23, body) {
|
|
|
5670
5724
|
}
|
|
5671
5725
|
return res.json();
|
|
5672
5726
|
}
|
|
5673
|
-
function apiGet(
|
|
5674
|
-
return request2("GET",
|
|
5727
|
+
function apiGet(path24) {
|
|
5728
|
+
return request2("GET", path24);
|
|
5675
5729
|
}
|
|
5676
|
-
function apiPost(
|
|
5677
|
-
return request2("POST",
|
|
5730
|
+
function apiPost(path24, body) {
|
|
5731
|
+
return request2("POST", path24, body);
|
|
5678
5732
|
}
|
|
5679
5733
|
async function requireSubscription() {
|
|
5680
5734
|
const { requirePaidFeature: requirePaidFeature2 } = await Promise.resolve().then(() => (init_access(), access_exports));
|
|
@@ -7246,26 +7300,26 @@ function runPipeline(text, profile, applyFixes = false) {
|
|
|
7246
7300
|
};
|
|
7247
7301
|
}
|
|
7248
7302
|
function readText(source) {
|
|
7249
|
-
const
|
|
7250
|
-
const
|
|
7303
|
+
const fs25 = require("fs");
|
|
7304
|
+
const path24 = require("path");
|
|
7251
7305
|
if (source === "-") {
|
|
7252
7306
|
if (process.stdin.isTTY) {
|
|
7253
7307
|
console.error("No input provided. Pipe content or specify a file.");
|
|
7254
7308
|
process.exit(1);
|
|
7255
7309
|
}
|
|
7256
|
-
return { text:
|
|
7310
|
+
return { text: fs25.readFileSync(0, "utf-8"), path: "stdin" };
|
|
7257
7311
|
}
|
|
7258
|
-
const resolved =
|
|
7259
|
-
if (!
|
|
7312
|
+
const resolved = path24.resolve(source);
|
|
7313
|
+
if (!fs25.existsSync(resolved)) {
|
|
7260
7314
|
console.error(`File not found: ${resolved}`);
|
|
7261
7315
|
process.exit(1);
|
|
7262
7316
|
}
|
|
7263
|
-
const stat =
|
|
7317
|
+
const stat = fs25.statSync(resolved);
|
|
7264
7318
|
if (stat.isDirectory()) {
|
|
7265
7319
|
console.error(`${resolved} is a directory, not a file.`);
|
|
7266
7320
|
process.exit(1);
|
|
7267
7321
|
}
|
|
7268
|
-
return { text:
|
|
7322
|
+
return { text: fs25.readFileSync(resolved, "utf-8"), path: resolved };
|
|
7269
7323
|
}
|
|
7270
7324
|
var init_pipeline = __esm({
|
|
7271
7325
|
"src/lib/pipeline.ts"() {
|
|
@@ -8273,7 +8327,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s))
|
|
|
8273
8327
|
g.minimatch.escape = vi.escape;
|
|
8274
8328
|
g.minimatch.unescape = Ei.unescape;
|
|
8275
8329
|
});
|
|
8276
|
-
var
|
|
8330
|
+
var fs25 = R((Wt) => {
|
|
8277
8331
|
"use strict";
|
|
8278
8332
|
Object.defineProperty(Wt, "__esModule", { value: true });
|
|
8279
8333
|
Wt.LRUCache = void 0;
|
|
@@ -9242,7 +9296,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s))
|
|
|
9242
9296
|
};
|
|
9243
9297
|
Object.defineProperty(_, "__esModule", { value: true });
|
|
9244
9298
|
_.PathScurry = _.Path = _.PathScurryDarwin = _.PathScurryPosix = _.PathScurryWin32 = _.PathScurryBase = _.PathPosix = _.PathWin32 = _.PathBase = _.ChildrenCache = _.ResolveCache = void 0;
|
|
9245
|
-
var Qt =
|
|
9299
|
+
var Qt = fs25(), Yt = require("node:path"), yr = require("node:url"), pt = require("fs"), Sr = br(require("node:fs")), vr = pt.realpathSync.native, Ht = require("node:fs/promises"), bs = Oe(), mt = { lstatSync: pt.lstatSync, readdir: pt.readdir, readdirSync: pt.readdirSync, readlinkSync: pt.readlinkSync, realpathSync: vr, promises: { lstat: Ht.lstat, readdir: Ht.readdir, readlink: Ht.readlink, realpath: Ht.realpath } }, _s = (n) => !n || n === mt || n === Sr ? mt : { ...mt, ...n, promises: { ...mt.promises, ...n.promises || {} } }, Os = /^\\\\\?\\([a-z]:)\\?$/i, Er = (n) => n.replace(/\//g, "\\").replace(Os, "$1\\"), _r = /[\\\/]/, N = 0, xs = 1, Ts = 2, G = 4, Cs = 6, Rs = 8, Q = 10, As = 12, j = 15, dt = ~j, xe = 16, ys = 32, gt = 64, W = 128, Vt = 256, Xt = 512, Ss = gt | W | Xt, Or = 1023, Te = (n) => n.isFile() ? Rs : n.isDirectory() ? G : n.isSymbolicLink() ? Q : n.isCharacterDevice() ? Ts : n.isBlockDevice() ? Cs : n.isSocket() ? As : n.isFIFO() ? xs : N, vs = new Qt.LRUCache({ max: 2 ** 12 }), wt = (n) => {
|
|
9246
9300
|
let t = vs.get(n);
|
|
9247
9301
|
if (t)
|
|
9248
9302
|
return t;
|
|
@@ -10761,7 +10815,7 @@ var {
|
|
|
10761
10815
|
} = import_index.default;
|
|
10762
10816
|
|
|
10763
10817
|
// src/index.ts
|
|
10764
|
-
var
|
|
10818
|
+
var import_chalk31 = __toESM(require_source());
|
|
10765
10819
|
|
|
10766
10820
|
// src/commands/init.ts
|
|
10767
10821
|
var import_chalk4 = __toESM(require_source());
|
|
@@ -12454,8 +12508,8 @@ function registerImportCommand(program3) {
|
|
|
12454
12508
|
}
|
|
12455
12509
|
function askQuestion(question) {
|
|
12456
12510
|
return new Promise((resolve14) => {
|
|
12457
|
-
const
|
|
12458
|
-
const rl =
|
|
12511
|
+
const readline2 = require("readline");
|
|
12512
|
+
const rl = readline2.createInterface({
|
|
12459
12513
|
input: process.stdin,
|
|
12460
12514
|
output: process.stdout
|
|
12461
12515
|
});
|
|
@@ -13040,28 +13094,137 @@ hyv scan ${filePath}`));
|
|
|
13040
13094
|
|
|
13041
13095
|
// src/commands/doctor.ts
|
|
13042
13096
|
var import_chalk16 = __toESM(require_source());
|
|
13043
|
-
var
|
|
13044
|
-
var
|
|
13097
|
+
var fs14 = __toESM(require("fs"));
|
|
13098
|
+
var path15 = __toESM(require("path"));
|
|
13045
13099
|
var os5 = __toESM(require("os"));
|
|
13046
13100
|
init_config();
|
|
13047
13101
|
init_auth();
|
|
13048
13102
|
init_access();
|
|
13049
13103
|
init_local_profile();
|
|
13050
13104
|
init_version();
|
|
13105
|
+
|
|
13106
|
+
// src/lib/mcp-stdio-test.ts
|
|
13107
|
+
var import_child_process2 = require("child_process");
|
|
13108
|
+
|
|
13109
|
+
// src/lib/cli-entry.ts
|
|
13110
|
+
var fs13 = __toESM(require("fs"));
|
|
13111
|
+
var path14 = __toESM(require("path"));
|
|
13112
|
+
function resolveCliEntry() {
|
|
13113
|
+
const candidates = [
|
|
13114
|
+
path14.resolve(process.argv[1] || ""),
|
|
13115
|
+
path14.resolve(__dirname, "index.js"),
|
|
13116
|
+
path14.resolve(__dirname, "..", "dist", "index.js")
|
|
13117
|
+
];
|
|
13118
|
+
return candidates.find((p) => p && fs13.existsSync(p)) || null;
|
|
13119
|
+
}
|
|
13120
|
+
function mcpServerCommand() {
|
|
13121
|
+
const entry = resolveCliEntry();
|
|
13122
|
+
if (entry) {
|
|
13123
|
+
return { command: process.execPath, args: [entry, "mcp"] };
|
|
13124
|
+
}
|
|
13125
|
+
return { command: "hyv", args: ["mcp"] };
|
|
13126
|
+
}
|
|
13127
|
+
function mcpServerSnippet() {
|
|
13128
|
+
const { command, args: args2 } = mcpServerCommand();
|
|
13129
|
+
return JSON.stringify({ command, args: args2 }, null, 2);
|
|
13130
|
+
}
|
|
13131
|
+
|
|
13132
|
+
// src/lib/mcp-stdio-test.ts
|
|
13133
|
+
async function testMcpStdioSubprocess() {
|
|
13134
|
+
const entry = resolveCliEntry();
|
|
13135
|
+
if (!entry)
|
|
13136
|
+
return { ok: false };
|
|
13137
|
+
return new Promise((resolve14) => {
|
|
13138
|
+
const child = (0, import_child_process2.spawn)(process.execPath, [entry, "mcp"], {
|
|
13139
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
13140
|
+
env: { ...process.env, HYV_POSTINSTALL_QUIET: "1" }
|
|
13141
|
+
});
|
|
13142
|
+
let buffer = "";
|
|
13143
|
+
let settled = false;
|
|
13144
|
+
const finish = (ok, toolCount) => {
|
|
13145
|
+
if (settled)
|
|
13146
|
+
return;
|
|
13147
|
+
settled = true;
|
|
13148
|
+
clearTimeout(timeout);
|
|
13149
|
+
try {
|
|
13150
|
+
child.kill();
|
|
13151
|
+
} catch {
|
|
13152
|
+
}
|
|
13153
|
+
resolve14({ ok, toolCount });
|
|
13154
|
+
};
|
|
13155
|
+
const timeout = setTimeout(() => finish(false), 1e4);
|
|
13156
|
+
const handleLine = (line) => {
|
|
13157
|
+
const trimmed = line.trim();
|
|
13158
|
+
if (!trimmed.startsWith("{"))
|
|
13159
|
+
return;
|
|
13160
|
+
try {
|
|
13161
|
+
const msg = JSON.parse(trimmed);
|
|
13162
|
+
if (msg.id === 2 && Array.isArray(msg.result?.tools) && msg.result.tools.length > 0) {
|
|
13163
|
+
finish(true, msg.result.tools.length);
|
|
13164
|
+
}
|
|
13165
|
+
} catch {
|
|
13166
|
+
}
|
|
13167
|
+
};
|
|
13168
|
+
child.stdout.on("data", (chunk) => {
|
|
13169
|
+
buffer += chunk.toString();
|
|
13170
|
+
const lines = buffer.split("\n");
|
|
13171
|
+
buffer = lines.pop() || "";
|
|
13172
|
+
for (const line of lines)
|
|
13173
|
+
handleLine(line);
|
|
13174
|
+
});
|
|
13175
|
+
child.on("error", () => finish(false));
|
|
13176
|
+
child.on("exit", () => {
|
|
13177
|
+
if (!settled) {
|
|
13178
|
+
handleLine(buffer);
|
|
13179
|
+
finish(buffer.includes("hyv_scan"));
|
|
13180
|
+
}
|
|
13181
|
+
});
|
|
13182
|
+
setTimeout(() => {
|
|
13183
|
+
const send2 = (payload) => {
|
|
13184
|
+
child.stdin.write(`${JSON.stringify(payload)}
|
|
13185
|
+
`);
|
|
13186
|
+
};
|
|
13187
|
+
send2({
|
|
13188
|
+
jsonrpc: "2.0",
|
|
13189
|
+
id: 1,
|
|
13190
|
+
method: "initialize",
|
|
13191
|
+
params: {
|
|
13192
|
+
protocolVersion: "2024-11-05",
|
|
13193
|
+
capabilities: {},
|
|
13194
|
+
clientInfo: { name: "hyv-self-test", version: "1.0" }
|
|
13195
|
+
}
|
|
13196
|
+
});
|
|
13197
|
+
send2({ jsonrpc: "2.0", method: "notifications/initialized" });
|
|
13198
|
+
send2({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} });
|
|
13199
|
+
}, 500);
|
|
13200
|
+
});
|
|
13201
|
+
}
|
|
13202
|
+
|
|
13203
|
+
// src/commands/doctor.ts
|
|
13051
13204
|
var HOME = os5.homedir();
|
|
13052
13205
|
var IS_WIN = process.platform === "win32";
|
|
13053
13206
|
function claudeDesktopDir() {
|
|
13054
13207
|
if (IS_WIN)
|
|
13055
|
-
return
|
|
13208
|
+
return path15.join(HOME, "AppData", "Roaming", "Claude");
|
|
13056
13209
|
if (process.platform === "linux")
|
|
13057
|
-
return
|
|
13058
|
-
return
|
|
13210
|
+
return path15.join(HOME, ".config", "Claude");
|
|
13211
|
+
return path15.join(HOME, "Library", "Application Support", "Claude");
|
|
13212
|
+
}
|
|
13213
|
+
function isOwnerOnlyFile(filePath) {
|
|
13214
|
+
try {
|
|
13215
|
+
if (!fs14.existsSync(filePath))
|
|
13216
|
+
return true;
|
|
13217
|
+
const mode = fs14.statSync(filePath).mode & 511;
|
|
13218
|
+
return (mode & 63) === 0;
|
|
13219
|
+
} catch {
|
|
13220
|
+
return false;
|
|
13221
|
+
}
|
|
13059
13222
|
}
|
|
13060
13223
|
function readMcpHyv(configFile) {
|
|
13061
13224
|
try {
|
|
13062
|
-
if (!
|
|
13225
|
+
if (!fs14.existsSync(configFile))
|
|
13063
13226
|
return false;
|
|
13064
|
-
const cfg = JSON.parse(
|
|
13227
|
+
const cfg = JSON.parse(fs14.readFileSync(configFile, "utf-8"));
|
|
13065
13228
|
return Boolean(cfg.mcpServers?.hyv);
|
|
13066
13229
|
} catch {
|
|
13067
13230
|
return false;
|
|
@@ -13082,28 +13245,28 @@ function registerDoctorCommand(program3) {
|
|
|
13082
13245
|
console.log(import_chalk16.default.dim("tip: run hyv welcome for free capabilities\n"));
|
|
13083
13246
|
console.log(import_chalk16.default.dim("checking cli installation..."));
|
|
13084
13247
|
const cliPath = process.argv[1];
|
|
13085
|
-
if (cliPath &&
|
|
13248
|
+
if (cliPath && fs14.existsSync(cliPath)) {
|
|
13086
13249
|
console.log(import_chalk16.default.green(" \u2713 cli installed"));
|
|
13087
13250
|
} else {
|
|
13088
13251
|
console.log(import_chalk16.default.red(" \u2717 cli not found"));
|
|
13089
13252
|
issues++;
|
|
13090
13253
|
}
|
|
13091
13254
|
console.log(import_chalk16.default.dim("checking .hyv directory..."));
|
|
13092
|
-
if (
|
|
13255
|
+
if (fs14.existsSync(HYV_DIR)) {
|
|
13093
13256
|
console.log(import_chalk16.default.green(" \u2713 .hyv directory exists"));
|
|
13094
13257
|
} else {
|
|
13095
13258
|
console.log(import_chalk16.default.yellow(" ! .hyv directory missing \u2014 creating..."));
|
|
13096
|
-
|
|
13259
|
+
fs14.mkdirSync(HYV_DIR, { recursive: true, mode: 448 });
|
|
13097
13260
|
fixed++;
|
|
13098
13261
|
}
|
|
13099
13262
|
console.log(import_chalk16.default.dim("checking cache..."));
|
|
13100
13263
|
const diskProfiles = listDiskCachedProfiles();
|
|
13101
|
-
const syncMeta =
|
|
13102
|
-
if (diskProfiles.length > 0 ||
|
|
13264
|
+
const syncMeta = path15.join(CACHE_DIR, "sync-meta.json");
|
|
13265
|
+
if (diskProfiles.length > 0 || fs14.existsSync(syncMeta)) {
|
|
13103
13266
|
console.log(import_chalk16.default.green(` \u2713 profile cache (${diskProfiles.length} full profile(s))`));
|
|
13104
|
-
if (
|
|
13267
|
+
if (fs14.existsSync(syncMeta)) {
|
|
13105
13268
|
try {
|
|
13106
|
-
const meta = JSON.parse(
|
|
13269
|
+
const meta = JSON.parse(fs14.readFileSync(syncMeta, "utf-8"));
|
|
13107
13270
|
console.log(import_chalk16.default.dim(` last sync: ${meta.synced_at || "unknown"}`));
|
|
13108
13271
|
} catch {
|
|
13109
13272
|
}
|
|
@@ -13111,6 +13274,26 @@ function registerDoctorCommand(program3) {
|
|
|
13111
13274
|
} else {
|
|
13112
13275
|
console.log(import_chalk16.default.dim(" - no full profile cache (free local engine still works)"));
|
|
13113
13276
|
}
|
|
13277
|
+
console.log(import_chalk16.default.dim("checking file permissions..."));
|
|
13278
|
+
if (fs14.existsSync(HYV_DIR)) {
|
|
13279
|
+
const hyvMode = fs14.statSync(HYV_DIR).mode & 511;
|
|
13280
|
+
if ((hyvMode & 63) === 0) {
|
|
13281
|
+
console.log(import_chalk16.default.green(" \u2713 .hyv directory permissions"));
|
|
13282
|
+
} else {
|
|
13283
|
+
console.log(import_chalk16.default.yellow(" ! .hyv directory is world/group accessible"));
|
|
13284
|
+
console.log(import_chalk16.default.dim(" run: chmod 700 ~/.hyv"));
|
|
13285
|
+
issues++;
|
|
13286
|
+
}
|
|
13287
|
+
}
|
|
13288
|
+
if (fs14.existsSync(AUTH_FILE)) {
|
|
13289
|
+
if (isOwnerOnlyFile(AUTH_FILE)) {
|
|
13290
|
+
console.log(import_chalk16.default.green(" \u2713 auth.json permissions"));
|
|
13291
|
+
} else {
|
|
13292
|
+
console.log(import_chalk16.default.yellow(" ! auth.json is world/group readable"));
|
|
13293
|
+
console.log(import_chalk16.default.dim(" run: chmod 600 ~/.hyv/auth.json"));
|
|
13294
|
+
issues++;
|
|
13295
|
+
}
|
|
13296
|
+
}
|
|
13114
13297
|
console.log(import_chalk16.default.dim("checking authentication..."));
|
|
13115
13298
|
if (isInitialized()) {
|
|
13116
13299
|
const auth = readAuth();
|
|
@@ -13135,9 +13318,9 @@ function registerDoctorCommand(program3) {
|
|
|
13135
13318
|
console.log(import_chalk16.default.dim(" run: hyv init for profiles + learning"));
|
|
13136
13319
|
}
|
|
13137
13320
|
console.log(import_chalk16.default.dim("checking voice profile..."));
|
|
13138
|
-
const voiceMd =
|
|
13139
|
-
const hasVoiceMd =
|
|
13140
|
-
const profileFiles =
|
|
13321
|
+
const voiceMd = path15.join(HYV_DIR, "voice.md");
|
|
13322
|
+
const hasVoiceMd = fs14.existsSync(voiceMd) && fs14.readFileSync(voiceMd, "utf-8").trim().length > 50;
|
|
13323
|
+
const profileFiles = fs14.existsSync(PROFILES_DIR) ? fs14.readdirSync(PROFILES_DIR).filter((f) => f.endsWith(".md") && f !== "voice.md") : [];
|
|
13141
13324
|
if (hasVoiceMd || profileFiles.length > 0 || diskProfiles.length > 0) {
|
|
13142
13325
|
if (hasVoiceMd)
|
|
13143
13326
|
console.log(import_chalk16.default.green(" \u2713 voice.md exists"));
|
|
@@ -13150,14 +13333,21 @@ function registerDoctorCommand(program3) {
|
|
|
13150
13333
|
console.log(import_chalk16.default.dim(" run: hyv new <name> or hyv init"));
|
|
13151
13334
|
}
|
|
13152
13335
|
console.log(import_chalk16.default.dim("checking agent configurations..."));
|
|
13336
|
+
const cursorLegacyRule = path15.join(HOME, ".cursor", "rules", "hyv.md");
|
|
13337
|
+
const cursorRule = path15.join(HOME, ".cursor", "rules", "hyv.mdc");
|
|
13338
|
+
if (fs14.existsSync(cursorLegacyRule) && fs14.existsSync(cursorRule)) {
|
|
13339
|
+
console.log(import_chalk16.default.yellow(" ! stale cursor rule ~/.cursor/rules/hyv.md (use hyv.mdc)"));
|
|
13340
|
+
console.log(import_chalk16.default.dim(" run: rm ~/.cursor/rules/hyv.md (or hyv doctor --fix-agents)"));
|
|
13341
|
+
issues++;
|
|
13342
|
+
}
|
|
13153
13343
|
const agentChecks = [
|
|
13154
|
-
{ name: "claude desktop mcp", ok: readMcpHyv(
|
|
13155
|
-
{ name: "cursor mcp", ok: readMcpHyv(
|
|
13156
|
-
{ name: "cursor rule", ok:
|
|
13157
|
-
{ name: "claude code command", ok:
|
|
13158
|
-
{ name: "claude code skill", ok:
|
|
13159
|
-
{ name: "codex agents", ok:
|
|
13160
|
-
{ name: "command code skill", ok:
|
|
13344
|
+
{ name: "claude desktop mcp", ok: readMcpHyv(path15.join(claudeDesktopDir(), "claude_desktop_config.json")) },
|
|
13345
|
+
{ name: "cursor mcp", ok: readMcpHyv(path15.join(HOME, ".cursor", "mcp.json")) },
|
|
13346
|
+
{ name: "cursor rule", ok: fs14.existsSync(cursorRule) },
|
|
13347
|
+
{ name: "claude code command", ok: fs14.existsSync(path15.join(HOME, ".claude", "commands", "hyv.md")) },
|
|
13348
|
+
{ name: "claude code skill", ok: fs14.existsSync(path15.join(HOME, ".claude", "skills", "hold-your-voice", "SKILL.md")) },
|
|
13349
|
+
{ name: "codex agents", ok: fs14.existsSync(path15.join(HOME, ".codex", "AGENTS.md")) && fs14.readFileSync(path15.join(HOME, ".codex", "AGENTS.md"), "utf-8").includes("hyv") },
|
|
13350
|
+
{ name: "command code skill", ok: fs14.existsSync(path15.join(HOME, ".commandcode", "skills", "hyv", "SKILL.md")) }
|
|
13161
13351
|
];
|
|
13162
13352
|
for (const agent of agentChecks) {
|
|
13163
13353
|
if (agent.ok) {
|
|
@@ -13168,8 +13358,8 @@ function registerDoctorCommand(program3) {
|
|
|
13168
13358
|
}
|
|
13169
13359
|
if (opts.fixAgents) {
|
|
13170
13360
|
try {
|
|
13171
|
-
const pkgDir =
|
|
13172
|
-
const { setupAgents } = require(
|
|
13361
|
+
const pkgDir = path15.resolve(__dirname, "..");
|
|
13362
|
+
const { setupAgents } = require(path15.join(pkgDir, "scripts", "postinstall-lib.js"));
|
|
13173
13363
|
const result = setupAgents({ pkgDir, quiet: true });
|
|
13174
13364
|
console.log(import_chalk16.default.green(` \u2713 re-ran agent setup (${result.configured.join(", ") || "no changes"})`));
|
|
13175
13365
|
if (result.warnings.length) {
|
|
@@ -13181,8 +13371,8 @@ function registerDoctorCommand(program3) {
|
|
|
13181
13371
|
}
|
|
13182
13372
|
}
|
|
13183
13373
|
console.log(import_chalk16.default.dim("checking mcp server..."));
|
|
13184
|
-
const claudeMcp = readMcpHyv(
|
|
13185
|
-
const cursorMcp = readMcpHyv(
|
|
13374
|
+
const claudeMcp = readMcpHyv(path15.join(claudeDesktopDir(), "claude_desktop_config.json"));
|
|
13375
|
+
const cursorMcp = readMcpHyv(path15.join(HOME, ".cursor", "mcp.json"));
|
|
13186
13376
|
if (claudeMcp || cursorMcp) {
|
|
13187
13377
|
if (claudeMcp)
|
|
13188
13378
|
console.log(import_chalk16.default.green(" \u2713 mcp configured for claude desktop"));
|
|
@@ -13192,6 +13382,22 @@ function registerDoctorCommand(program3) {
|
|
|
13192
13382
|
console.log(import_chalk16.default.yellow(" ! mcp not configured \u2014 run: hyv doctor --fix-agents or hyv mcp --setup"));
|
|
13193
13383
|
issues++;
|
|
13194
13384
|
}
|
|
13385
|
+
try {
|
|
13386
|
+
const stdio = await testMcpStdioSubprocess();
|
|
13387
|
+
if (stdio.ok && (stdio.toolCount || 0) >= 10) {
|
|
13388
|
+
console.log(import_chalk16.default.green(` \u2713 mcp stdio subprocess healthy (${stdio.toolCount} tools)`));
|
|
13389
|
+
} else if (stdio.ok) {
|
|
13390
|
+
console.log(import_chalk16.default.yellow(` ! mcp stdio ok but only ${stdio.toolCount || 0} tools`));
|
|
13391
|
+
issues++;
|
|
13392
|
+
} else {
|
|
13393
|
+
console.log(import_chalk16.default.red(" \u2717 mcp stdio subprocess failed"));
|
|
13394
|
+
console.log(import_chalk16.default.dim(" run: hyv mcp --test"));
|
|
13395
|
+
issues++;
|
|
13396
|
+
}
|
|
13397
|
+
} catch (err) {
|
|
13398
|
+
console.log(import_chalk16.default.red(` \u2717 mcp stdio probe failed: ${err.message}`));
|
|
13399
|
+
issues++;
|
|
13400
|
+
}
|
|
13195
13401
|
console.log("");
|
|
13196
13402
|
if (issues === 0 && fixed === 0) {
|
|
13197
13403
|
console.log(import_chalk16.default.green("\u2713 everything looks good!"));
|
|
@@ -13268,15 +13474,51 @@ error: ${error.message}
|
|
|
13268
13474
|
}
|
|
13269
13475
|
|
|
13270
13476
|
// src/commands/fix.ts
|
|
13271
|
-
var
|
|
13272
|
-
var fs14 = __toESM(require("fs"));
|
|
13273
|
-
var path15 = __toESM(require("path"));
|
|
13477
|
+
var import_chalk19 = __toESM(require_source());
|
|
13274
13478
|
init_pipeline();
|
|
13275
13479
|
init_local_profile();
|
|
13276
13480
|
init_access();
|
|
13277
13481
|
init_config();
|
|
13482
|
+
|
|
13483
|
+
// src/lib/destructive-write.ts
|
|
13484
|
+
var fs15 = __toESM(require("fs"));
|
|
13485
|
+
var path16 = __toESM(require("path"));
|
|
13486
|
+
var readline = __toESM(require("readline"));
|
|
13487
|
+
var import_chalk18 = __toESM(require_source());
|
|
13488
|
+
async function confirmDestructiveWrite(options) {
|
|
13489
|
+
if (options.yes)
|
|
13490
|
+
return true;
|
|
13491
|
+
const label = options.target ? `${options.action} (${options.target})` : options.action;
|
|
13492
|
+
if (!process.stdin.isTTY) {
|
|
13493
|
+
console.error(import_chalk18.default.red("\nRefusing destructive write without confirmation (non-interactive)."));
|
|
13494
|
+
console.error(import_chalk18.default.dim(" Re-run with --yes to create .bak backups and proceed.\n"));
|
|
13495
|
+
return false;
|
|
13496
|
+
}
|
|
13497
|
+
const question = `
|
|
13498
|
+
${label}
|
|
13499
|
+
A .bak backup will be created. Proceed? [y/N] `;
|
|
13500
|
+
const answer = await new Promise((resolve14) => {
|
|
13501
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
13502
|
+
rl.question(question, (value) => {
|
|
13503
|
+
rl.close();
|
|
13504
|
+
resolve14(value.trim().toLowerCase());
|
|
13505
|
+
});
|
|
13506
|
+
});
|
|
13507
|
+
return answer === "y" || answer === "yes";
|
|
13508
|
+
}
|
|
13509
|
+
function writeInPlaceWithBackup(filePath, content) {
|
|
13510
|
+
const backupPath = filePath + ".bak";
|
|
13511
|
+
fs15.copyFileSync(filePath, backupPath);
|
|
13512
|
+
fs15.writeFileSync(filePath, content);
|
|
13513
|
+
return backupPath;
|
|
13514
|
+
}
|
|
13515
|
+
function backupBasename(filePath) {
|
|
13516
|
+
return path16.basename(filePath) + ".bak";
|
|
13517
|
+
}
|
|
13518
|
+
|
|
13519
|
+
// src/commands/fix.ts
|
|
13278
13520
|
function registerFixCommand(program3) {
|
|
13279
|
-
program3.command("fix").description("Apply auto-fixes (word swaps, connector removals) without an LLM").argument("<file>", "File to fix (or - for stdin)").option("--dry-run", "Show changes without writing").option("-i, --in-place", "Write fixes back to the file").option("--profile <name>", "Voice profile for never-list checks").option("--ignore <rules>", "Comma-separated rule IDs to skip").option("--format <type>", "Output format (text or json)", "text").action(async (file, options) => {
|
|
13521
|
+
program3.command("fix").description("Apply auto-fixes (word swaps, connector removals) without an LLM").argument("<file>", "File to fix (or - for stdin)").option("--dry-run", "Show changes without writing").option("-i, --in-place", "Write fixes back to the file").option("-y, --yes", "Confirm in-place write without prompting (creates .bak backup)").option("--profile <name>", "Voice profile for never-list checks").option("--ignore <rules>", "Comma-separated rule IDs to skip").option("--format <type>", "Output format (text or json)", "text").action(async (file, options) => {
|
|
13280
13522
|
try {
|
|
13281
13523
|
const profile = await loadProfileForCommand(options.profile);
|
|
13282
13524
|
const { text, path: filePath } = readText(file);
|
|
@@ -13285,9 +13527,9 @@ function registerFixCommand(program3) {
|
|
|
13285
13527
|
if (options.format === "json") {
|
|
13286
13528
|
console.log(JSON.stringify({ file: filePath, autoFixes: 0, llmIssues: result.stats.needsLLM, changes: [] }));
|
|
13287
13529
|
} else {
|
|
13288
|
-
console.log(
|
|
13530
|
+
console.log(import_chalk19.default.green("\n\u2713 No auto-fixable issues found."));
|
|
13289
13531
|
if (result.stats.needsLLM > 0) {
|
|
13290
|
-
console.log(
|
|
13532
|
+
console.log(import_chalk19.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
|
|
13291
13533
|
}
|
|
13292
13534
|
}
|
|
13293
13535
|
return;
|
|
@@ -13301,24 +13543,30 @@ function registerFixCommand(program3) {
|
|
|
13301
13543
|
fixed: options.dryRun ? void 0 : result.fixed
|
|
13302
13544
|
}, null, 2));
|
|
13303
13545
|
} else {
|
|
13304
|
-
console.log(
|
|
13546
|
+
console.log(import_chalk19.default.dim(`
|
|
13305
13547
|
hyv fix ${filePath}
|
|
13306
13548
|
`));
|
|
13307
13549
|
for (const change of result.changes) {
|
|
13308
|
-
console.log(
|
|
13550
|
+
console.log(import_chalk19.default.dim(` Line ${change.line}: `) + import_chalk19.default.red(change.before) + import_chalk19.default.dim(" \u2192 ") + import_chalk19.default.green(change.after));
|
|
13309
13551
|
}
|
|
13310
|
-
console.log(
|
|
13552
|
+
console.log(import_chalk19.default.green(`
|
|
13311
13553
|
\u2713 ${result.changes.length} auto-fix${result.changes.length === 1 ? "" : "es"} applied`));
|
|
13312
13554
|
if (result.stats.needsLLM > 0) {
|
|
13313
|
-
console.log(
|
|
13555
|
+
console.log(import_chalk19.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite \u2014 run: hyv rewrite ${file}`));
|
|
13314
13556
|
}
|
|
13315
13557
|
}
|
|
13316
13558
|
if (!options.dryRun) {
|
|
13317
13559
|
if (options.inPlace && filePath !== "stdin") {
|
|
13318
|
-
const
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
|
|
13560
|
+
const confirmed = await confirmDestructiveWrite({
|
|
13561
|
+
yes: options.yes,
|
|
13562
|
+
action: "Apply auto-fixes in-place",
|
|
13563
|
+
target: filePath
|
|
13564
|
+
});
|
|
13565
|
+
if (!confirmed) {
|
|
13566
|
+
process.exit(1);
|
|
13567
|
+
}
|
|
13568
|
+
const backupPath = writeInPlaceWithBackup(filePath, result.fixed);
|
|
13569
|
+
console.log(import_chalk19.default.dim(` Written to ${filePath} (backup: ${backupBasename(filePath)})`));
|
|
13322
13570
|
saveLastEditSession({
|
|
13323
13571
|
original_path: filePath,
|
|
13324
13572
|
edited_path: filePath,
|
|
@@ -13326,7 +13574,7 @@ hyv fix ${filePath}
|
|
|
13326
13574
|
edited_text: result.fixed,
|
|
13327
13575
|
profile: options.profile
|
|
13328
13576
|
});
|
|
13329
|
-
console.log(
|
|
13577
|
+
console.log(import_chalk19.default.dim(" Tip: hyv reinforce --last to teach your profile from this edit"));
|
|
13330
13578
|
} else if (filePath === "stdin" || !options.inPlace) {
|
|
13331
13579
|
process.stdout.write("\n" + result.fixed + "\n");
|
|
13332
13580
|
if (filePath !== "stdin") {
|
|
@@ -13342,14 +13590,14 @@ hyv fix ${filePath}
|
|
|
13342
13590
|
}
|
|
13343
13591
|
await maybeShowLimitedModeHint(!!profile);
|
|
13344
13592
|
} catch (error) {
|
|
13345
|
-
console.error(
|
|
13593
|
+
console.error(import_chalk19.default.red(`Error: ${error.message}`));
|
|
13346
13594
|
process.exit(1);
|
|
13347
13595
|
}
|
|
13348
13596
|
});
|
|
13349
13597
|
}
|
|
13350
13598
|
|
|
13351
13599
|
// src/commands/check.ts
|
|
13352
|
-
var
|
|
13600
|
+
var import_chalk20 = __toESM(require_source());
|
|
13353
13601
|
init_pipeline();
|
|
13354
13602
|
init_local_profile();
|
|
13355
13603
|
init_access();
|
|
@@ -13359,20 +13607,20 @@ function registerCheckCommand(program3) {
|
|
|
13359
13607
|
const profile = await loadProfileForCommand(options.profile);
|
|
13360
13608
|
let inputText = text;
|
|
13361
13609
|
if (text === "-") {
|
|
13362
|
-
const
|
|
13610
|
+
const fs26 = require("fs");
|
|
13363
13611
|
if (process.stdin.isTTY) {
|
|
13364
|
-
console.error(
|
|
13612
|
+
console.error(import_chalk20.default.red("No input provided. Pipe content or pass text as argument."));
|
|
13365
13613
|
process.exit(1);
|
|
13366
13614
|
}
|
|
13367
|
-
inputText =
|
|
13615
|
+
inputText = fs26.readFileSync(0, "utf-8");
|
|
13368
13616
|
}
|
|
13369
13617
|
if (!inputText.trim()) {
|
|
13370
|
-
console.error(
|
|
13618
|
+
console.error(import_chalk20.default.red("No text provided."));
|
|
13371
13619
|
process.exit(1);
|
|
13372
13620
|
}
|
|
13373
|
-
const
|
|
13374
|
-
if (text !== "-" &&
|
|
13375
|
-
console.log(
|
|
13621
|
+
const fs25 = require("fs");
|
|
13622
|
+
if (text !== "-" && fs25.existsSync(text)) {
|
|
13623
|
+
console.log(import_chalk20.default.yellow(`"${text}" looks like a file. Did you mean: hyv scan ${text}`));
|
|
13376
13624
|
process.exit(1);
|
|
13377
13625
|
}
|
|
13378
13626
|
const result = runPipeline(inputText, profile, false);
|
|
@@ -13396,30 +13644,30 @@ function registerCheckCommand(program3) {
|
|
|
13396
13644
|
}, null, 2));
|
|
13397
13645
|
} else {
|
|
13398
13646
|
if (result.stats.totalSignals === 0) {
|
|
13399
|
-
console.log(
|
|
13400
|
-
console.log(
|
|
13647
|
+
console.log(import_chalk20.default.green("\n\u2713 Clean \u2014 no AI patterns found."));
|
|
13648
|
+
console.log(import_chalk20.default.dim(` score: ${result.score}/100`));
|
|
13401
13649
|
} else {
|
|
13402
13650
|
console.log("");
|
|
13403
13651
|
printGroupedSignals(result.signalMap.signals.slice(0, 15), profile);
|
|
13404
13652
|
if (result.signalMap.signals.length > 15) {
|
|
13405
|
-
console.log(
|
|
13653
|
+
console.log(import_chalk20.default.dim(` ... and ${result.signalMap.signals.length - 15} more`));
|
|
13406
13654
|
}
|
|
13407
|
-
console.log(
|
|
13655
|
+
console.log(import_chalk20.default.yellow(`
|
|
13408
13656
|
${result.stats.totalSignals} issues (${result.stats.red} red, ${result.stats.yellow} yellow)`));
|
|
13409
|
-
console.log(
|
|
13657
|
+
console.log(import_chalk20.default.dim(` score: ${result.score}/100`));
|
|
13410
13658
|
}
|
|
13411
13659
|
await maybeShowLimitedModeHint(!!profile);
|
|
13412
13660
|
}
|
|
13413
13661
|
process.exit(result.stats.totalSignals > 0 ? 1 : 0);
|
|
13414
13662
|
} catch (error) {
|
|
13415
|
-
console.error(
|
|
13663
|
+
console.error(import_chalk20.default.red(`Error: ${error.message}`));
|
|
13416
13664
|
process.exit(1);
|
|
13417
13665
|
}
|
|
13418
13666
|
});
|
|
13419
13667
|
}
|
|
13420
13668
|
|
|
13421
13669
|
// src/commands/score.ts
|
|
13422
|
-
var
|
|
13670
|
+
var import_chalk21 = __toESM(require_source());
|
|
13423
13671
|
init_pipeline();
|
|
13424
13672
|
init_local_profile();
|
|
13425
13673
|
function registerScoreCommand(program3) {
|
|
@@ -13444,14 +13692,14 @@ function registerScoreCommand(program3) {
|
|
|
13444
13692
|
process.exit(1);
|
|
13445
13693
|
}
|
|
13446
13694
|
} catch (error) {
|
|
13447
|
-
console.error(
|
|
13695
|
+
console.error(import_chalk21.default.red(`Error: ${error.message}`));
|
|
13448
13696
|
process.exit(1);
|
|
13449
13697
|
}
|
|
13450
13698
|
});
|
|
13451
13699
|
}
|
|
13452
13700
|
|
|
13453
13701
|
// src/commands/diff.ts
|
|
13454
|
-
var
|
|
13702
|
+
var import_chalk22 = __toESM(require_source());
|
|
13455
13703
|
init_pipeline();
|
|
13456
13704
|
init_local_profile();
|
|
13457
13705
|
function registerDiffCommand(program3) {
|
|
@@ -13461,9 +13709,9 @@ function registerDiffCommand(program3) {
|
|
|
13461
13709
|
const { text, path: filePath } = readText(file);
|
|
13462
13710
|
const result = runPipeline(text, profile, true);
|
|
13463
13711
|
if (result.changes.length === 0) {
|
|
13464
|
-
console.log(
|
|
13712
|
+
console.log(import_chalk22.default.green("\n\u2713 No auto-fixable changes."));
|
|
13465
13713
|
if (result.stats.needsLLM > 0) {
|
|
13466
|
-
console.log(
|
|
13714
|
+
console.log(import_chalk22.default.dim(` ${result.stats.needsLLM} issues need LLM rewrite`));
|
|
13467
13715
|
}
|
|
13468
13716
|
return;
|
|
13469
13717
|
}
|
|
@@ -13478,42 +13726,42 @@ function registerDiffCommand(program3) {
|
|
|
13478
13726
|
const originalLines = text.split("\n");
|
|
13479
13727
|
const fixedLines = result.fixed.split("\n");
|
|
13480
13728
|
const contextN = parseInt(options.context, 10);
|
|
13481
|
-
console.log(
|
|
13482
|
-
console.log(
|
|
13729
|
+
console.log(import_chalk22.default.dim(`--- ${filePath}`));
|
|
13730
|
+
console.log(import_chalk22.default.dim(`+++ ${filePath} (fixed)`));
|
|
13483
13731
|
for (const change of result.changes) {
|
|
13484
13732
|
const lineIdx = change.line - 1;
|
|
13485
13733
|
const start = Math.max(0, lineIdx - contextN);
|
|
13486
13734
|
const end = Math.min(originalLines.length, lineIdx + contextN + 1);
|
|
13487
|
-
console.log(
|
|
13735
|
+
console.log(import_chalk22.default.dim(`@@ -${start + 1},${end - start} +${start + 1},${end - start} @@`));
|
|
13488
13736
|
for (let i = start; i < end; i++) {
|
|
13489
13737
|
if (i === lineIdx) {
|
|
13490
|
-
console.log(
|
|
13491
|
-
console.log(
|
|
13738
|
+
console.log(import_chalk22.default.red(`-${originalLines[i]}`));
|
|
13739
|
+
console.log(import_chalk22.default.green(`+${fixedLines[i]}`));
|
|
13492
13740
|
} else {
|
|
13493
|
-
console.log(
|
|
13741
|
+
console.log(import_chalk22.default.dim(` ${originalLines[i]}`));
|
|
13494
13742
|
}
|
|
13495
13743
|
}
|
|
13496
13744
|
}
|
|
13497
|
-
console.log(
|
|
13745
|
+
console.log(import_chalk22.default.green(`
|
|
13498
13746
|
${result.changes.length} auto-fix${result.changes.length === 1 ? "" : "es"} available`));
|
|
13499
|
-
console.log(
|
|
13747
|
+
console.log(import_chalk22.default.dim(` run: hyv fix ${file} -i to apply`));
|
|
13500
13748
|
if (options.apply && filePath !== "stdin") {
|
|
13501
|
-
const
|
|
13502
|
-
const
|
|
13749
|
+
const fs25 = require("fs");
|
|
13750
|
+
const path24 = require("path");
|
|
13503
13751
|
const backupPath = filePath + ".bak";
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
console.log(
|
|
13752
|
+
fs25.copyFileSync(filePath, backupPath);
|
|
13753
|
+
fs25.writeFileSync(filePath, result.fixed);
|
|
13754
|
+
console.log(import_chalk22.default.green(` \u2713 Applied. Backup: ${path24.basename(backupPath)}`));
|
|
13507
13755
|
}
|
|
13508
13756
|
} catch (error) {
|
|
13509
|
-
console.error(
|
|
13757
|
+
console.error(import_chalk22.default.red(`Error: ${error.message}`));
|
|
13510
13758
|
process.exit(1);
|
|
13511
13759
|
}
|
|
13512
13760
|
});
|
|
13513
13761
|
}
|
|
13514
13762
|
|
|
13515
13763
|
// src/commands/rules.ts
|
|
13516
|
-
var
|
|
13764
|
+
var import_chalk23 = __toESM(require_source());
|
|
13517
13765
|
init_config();
|
|
13518
13766
|
var RULE_CATALOG = [
|
|
13519
13767
|
// AI Overused Words
|
|
@@ -13607,7 +13855,7 @@ function registerRulesCommand(program3) {
|
|
|
13607
13855
|
for (const id of ids)
|
|
13608
13856
|
disabledRules.delete(id);
|
|
13609
13857
|
writeConfig({ ...config, disabled_rules: [...disabledRules] });
|
|
13610
|
-
console.log(
|
|
13858
|
+
console.log(import_chalk23.default.green(`
|
|
13611
13859
|
\u2713 Enabled: ${ids.join(", ")}`));
|
|
13612
13860
|
return;
|
|
13613
13861
|
}
|
|
@@ -13616,13 +13864,13 @@ function registerRulesCommand(program3) {
|
|
|
13616
13864
|
for (const id of ids)
|
|
13617
13865
|
disabledRules.add(id);
|
|
13618
13866
|
writeConfig({ ...config, disabled_rules: [...disabledRules] });
|
|
13619
|
-
console.log(
|
|
13867
|
+
console.log(import_chalk23.default.green(`
|
|
13620
13868
|
\u2713 Disabled: ${ids.join(", ")}`));
|
|
13621
13869
|
return;
|
|
13622
13870
|
}
|
|
13623
13871
|
if (options.reset) {
|
|
13624
13872
|
writeConfig({ ...config, disabled_rules: [] });
|
|
13625
|
-
console.log(
|
|
13873
|
+
console.log(import_chalk23.default.green("\n\u2713 All rules reset to default (enabled)"));
|
|
13626
13874
|
return;
|
|
13627
13875
|
}
|
|
13628
13876
|
let rules = [...RULE_CATALOG];
|
|
@@ -13650,40 +13898,40 @@ function registerRulesCommand(program3) {
|
|
|
13650
13898
|
}
|
|
13651
13899
|
console.log("");
|
|
13652
13900
|
for (const [cat, catRules] of categories) {
|
|
13653
|
-
console.log(
|
|
13901
|
+
console.log(import_chalk23.default.bold(` ${cat} rules (${catRules.length})
|
|
13654
13902
|
`));
|
|
13655
|
-
console.log(
|
|
13656
|
-
console.log(
|
|
13903
|
+
console.log(import_chalk23.default.dim(" ID Sev AutoFix Status"));
|
|
13904
|
+
console.log(import_chalk23.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13657
13905
|
for (const rule of catRules) {
|
|
13658
|
-
const sev = rule.severity === "red" ?
|
|
13659
|
-
const fix = rule.autoFixable ?
|
|
13660
|
-
const enabled2 = disabledRules.has(rule.id) ?
|
|
13906
|
+
const sev = rule.severity === "red" ? import_chalk23.default.red("red") : import_chalk23.default.yellow("yel");
|
|
13907
|
+
const fix = rule.autoFixable ? import_chalk23.default.green(" \u2713") : import_chalk23.default.dim(" \u2717");
|
|
13908
|
+
const enabled2 = disabledRules.has(rule.id) ? import_chalk23.default.red(" \u2717 disabled") : import_chalk23.default.green(" \u2713 enabled");
|
|
13661
13909
|
const id = rule.id.padEnd(24);
|
|
13662
|
-
console.log(` ${
|
|
13910
|
+
console.log(` ${import_chalk23.default.dim(id)} ${sev} ${fix} ${enabled2}`);
|
|
13663
13911
|
}
|
|
13664
13912
|
console.log("");
|
|
13665
13913
|
}
|
|
13666
13914
|
const enabled = rules.filter((r) => !disabledRules.has(r.id)).length;
|
|
13667
13915
|
const disabled = rules.length - enabled;
|
|
13668
|
-
console.log(
|
|
13669
|
-
console.log(
|
|
13670
|
-
console.log(
|
|
13916
|
+
console.log(import_chalk23.default.dim(` ${rules.length} rules, ${enabled} enabled, ${disabled} disabled`));
|
|
13917
|
+
console.log(import_chalk23.default.dim(` toggle: hyv rules --disable <id>`));
|
|
13918
|
+
console.log(import_chalk23.default.dim(` reset: hyv rules --reset
|
|
13671
13919
|
`));
|
|
13672
13920
|
} catch (error) {
|
|
13673
|
-
console.error(
|
|
13921
|
+
console.error(import_chalk23.default.red(`Error: ${error.message}`));
|
|
13674
13922
|
process.exit(1);
|
|
13675
13923
|
}
|
|
13676
13924
|
});
|
|
13677
13925
|
}
|
|
13678
13926
|
|
|
13679
13927
|
// src/commands/batch.ts
|
|
13680
|
-
var
|
|
13681
|
-
var
|
|
13682
|
-
var
|
|
13928
|
+
var import_chalk24 = __toESM(require_source());
|
|
13929
|
+
var fs16 = __toESM(require("fs"));
|
|
13930
|
+
var path17 = __toESM(require("path"));
|
|
13683
13931
|
init_pipeline();
|
|
13684
13932
|
init_local_profile();
|
|
13685
13933
|
function registerBatchCommand(program3) {
|
|
13686
|
-
program3.command("batch").description("Scan or fix multiple files matching a glob").argument("<pattern>", 'Glob pattern (e.g., "posts/**/*.md")').option("--fix", "Apply auto-fixes (default: scan only)").option("-i, --in-place", "Write fixes back to files").option("-y, --yes", "Confirm destructive in-place fixes without prompting").option("--threshold <n>", "Fail if any file score < threshold").option("--fail-on-hit", "Exit
|
|
13934
|
+
program3.command("batch").description("Scan or fix multiple files matching a glob").argument("<pattern>", 'Glob pattern (e.g., "posts/**/*.md")').option("--fix", "Apply auto-fixes (default: scan only)").option("-i, --in-place", "Write fixes back to files").option("-y, --yes", "Confirm destructive in-place fixes without prompting").option("--threshold <n>", "Fail if any file score < threshold").option("--fail-on-hit", "Exit with code 2 if any file has issues").option("--sort <field>", "Sort by: issues, score, name", "issues").option("--format <type>", "Output format (text, json, csv)", "text").option("--profile <name>", "Voice profile").option("--ignore <patterns>", "Comma-separated glob ignores").action(async (pattern, options) => {
|
|
13687
13935
|
try {
|
|
13688
13936
|
const profile = await loadProfileForCommand(options.profile);
|
|
13689
13937
|
const glob = require_index_min();
|
|
@@ -13692,26 +13940,30 @@ function registerBatchCommand(program3) {
|
|
|
13692
13940
|
nodir: true
|
|
13693
13941
|
});
|
|
13694
13942
|
if (files.length === 0) {
|
|
13695
|
-
console.log(
|
|
13943
|
+
console.log(import_chalk24.default.yellow(`
|
|
13696
13944
|
No files matching: ${pattern}`));
|
|
13697
13945
|
return;
|
|
13698
13946
|
}
|
|
13699
|
-
if (options.fix && options.inPlace
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13947
|
+
if (options.fix && options.inPlace) {
|
|
13948
|
+
const confirmed = await confirmDestructiveWrite({
|
|
13949
|
+
yes: options.yes,
|
|
13950
|
+
action: `Apply auto-fixes in-place to ${files.length} file(s)`,
|
|
13951
|
+
target: pattern
|
|
13952
|
+
});
|
|
13953
|
+
if (!confirmed)
|
|
13954
|
+
process.exit(1);
|
|
13703
13955
|
}
|
|
13704
13956
|
if (options.format === "text") {
|
|
13705
|
-
console.log(
|
|
13957
|
+
console.log(import_chalk24.default.dim(`
|
|
13706
13958
|
scanning ${files.length} file${files.length === 1 ? "" : "s"}...
|
|
13707
13959
|
`));
|
|
13708
13960
|
}
|
|
13709
13961
|
const results = [];
|
|
13710
13962
|
for (const file of files) {
|
|
13711
|
-
const absPath =
|
|
13712
|
-
if (!
|
|
13963
|
+
const absPath = path17.resolve(file);
|
|
13964
|
+
if (!fs16.existsSync(absPath))
|
|
13713
13965
|
continue;
|
|
13714
|
-
const text =
|
|
13966
|
+
const text = fs16.readFileSync(absPath, "utf-8");
|
|
13715
13967
|
const result = runPipeline(text, profile, options.fix || false);
|
|
13716
13968
|
results.push({
|
|
13717
13969
|
file,
|
|
@@ -13722,9 +13974,7 @@ No files matching: ${pattern}`));
|
|
|
13722
13974
|
autoFixes: result.changes.length
|
|
13723
13975
|
});
|
|
13724
13976
|
if (options.fix && options.inPlace && result.changes.length > 0) {
|
|
13725
|
-
|
|
13726
|
-
fs15.copyFileSync(absPath, backupPath);
|
|
13727
|
-
fs15.writeFileSync(absPath, result.fixed);
|
|
13977
|
+
writeInPlaceWithBackup(absPath, result.fixed);
|
|
13728
13978
|
}
|
|
13729
13979
|
}
|
|
13730
13980
|
if (options.sort === "score") {
|
|
@@ -13743,23 +13993,23 @@ No files matching: ${pattern}`));
|
|
|
13743
13993
|
}
|
|
13744
13994
|
} else {
|
|
13745
13995
|
for (const r of results) {
|
|
13746
|
-
const icon = r.issues > 0 ?
|
|
13747
|
-
const score = r.score < 60 ?
|
|
13748
|
-
const issueStr = r.issues > 0 ?
|
|
13996
|
+
const icon = r.issues > 0 ? import_chalk24.default.red("\u25CF") : import_chalk24.default.green("\u25CB");
|
|
13997
|
+
const score = r.score < 60 ? import_chalk24.default.red(r.score) : r.score < 80 ? import_chalk24.default.yellow(r.score) : import_chalk24.default.green(r.score);
|
|
13998
|
+
const issueStr = r.issues > 0 ? import_chalk24.default.red(`${r.issues} issues`) : import_chalk24.default.green("clean");
|
|
13749
13999
|
console.log(` ${icon} ${r.file.padEnd(40)} ${issueStr.padEnd(20)} score: ${score}`);
|
|
13750
14000
|
}
|
|
13751
14001
|
const withIssues = results.filter((r) => r.issues > 0).length;
|
|
13752
14002
|
const totalIssues = results.reduce((sum, r) => sum + r.issues, 0);
|
|
13753
14003
|
const worst = results.reduce((min, r) => r.score < min.score ? r : min, results[0]);
|
|
13754
|
-
console.log(
|
|
14004
|
+
console.log(import_chalk24.default.dim(`
|
|
13755
14005
|
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
13756
|
-
console.log(
|
|
14006
|
+
console.log(import_chalk24.default.dim(` ${results.length} files, ${withIssues} with issues, ${totalIssues} total issues`));
|
|
13757
14007
|
if (withIssues > 0) {
|
|
13758
|
-
console.log(
|
|
14008
|
+
console.log(import_chalk24.default.dim(` worst: ${worst.file} (${worst.score}/100)`));
|
|
13759
14009
|
}
|
|
13760
14010
|
if (options.fix && options.inPlace) {
|
|
13761
14011
|
const fixed = results.filter((r) => r.autoFixes > 0);
|
|
13762
|
-
console.log(
|
|
14012
|
+
console.log(import_chalk24.default.green(`
|
|
13763
14013
|
\u2713 ${fixed.reduce((sum, r) => sum + r.autoFixes, 0)} auto-fixes applied across ${fixed.length} files`));
|
|
13764
14014
|
}
|
|
13765
14015
|
}
|
|
@@ -13771,108 +14021,114 @@ No files matching: ${pattern}`));
|
|
|
13771
14021
|
if (belowThreshold)
|
|
13772
14022
|
process.exit(1);
|
|
13773
14023
|
} catch (error) {
|
|
13774
|
-
console.error(
|
|
14024
|
+
console.error(import_chalk24.default.red(`Error: ${error.message}`));
|
|
13775
14025
|
process.exit(1);
|
|
13776
14026
|
}
|
|
13777
14027
|
});
|
|
13778
14028
|
}
|
|
13779
14029
|
|
|
13780
14030
|
// src/commands/watch.ts
|
|
13781
|
-
var
|
|
13782
|
-
var
|
|
13783
|
-
var
|
|
14031
|
+
var import_chalk25 = __toESM(require_source());
|
|
14032
|
+
var fs17 = __toESM(require("fs"));
|
|
14033
|
+
var path18 = __toESM(require("path"));
|
|
13784
14034
|
init_pipeline();
|
|
13785
14035
|
init_local_profile();
|
|
13786
14036
|
function registerWatchCommand(program3) {
|
|
13787
14037
|
program3.command("watch").description("Watch a file and re-scan on every save").argument("<file>", "File to watch").option("--command <cmd>", "What to run on change: scan, score, fix", "scan").option("--debounce <ms>", "Delay after save before scanning", "300").option("--notify", "OS notification when issues found").option("-y, --yes", "Confirm destructive auto-fix writes without prompting").option("--profile <name>", "Voice profile").action(async (file, options) => {
|
|
13788
14038
|
try {
|
|
13789
14039
|
const profile = await loadProfileForCommand(options.profile);
|
|
13790
|
-
const absPath =
|
|
13791
|
-
if (!
|
|
13792
|
-
console.error(
|
|
14040
|
+
const absPath = path18.resolve(file);
|
|
14041
|
+
if (!fs17.existsSync(absPath)) {
|
|
14042
|
+
console.error(import_chalk25.default.red(`File not found: ${absPath}`));
|
|
13793
14043
|
process.exit(1);
|
|
13794
14044
|
}
|
|
13795
|
-
if (options.command === "fix"
|
|
13796
|
-
|
|
13797
|
-
|
|
13798
|
-
|
|
14045
|
+
if (options.command === "fix") {
|
|
14046
|
+
const confirmed = await confirmDestructiveWrite({
|
|
14047
|
+
yes: options.yes,
|
|
14048
|
+
action: "Auto-fix on every save",
|
|
14049
|
+
target: absPath
|
|
14050
|
+
});
|
|
14051
|
+
if (!confirmed)
|
|
14052
|
+
process.exit(1);
|
|
13799
14053
|
}
|
|
13800
|
-
console.log(
|
|
14054
|
+
console.log(import_chalk25.default.dim(`
|
|
13801
14055
|
watching ${absPath}`));
|
|
13802
|
-
console.log(
|
|
13803
|
-
console.log(
|
|
14056
|
+
console.log(import_chalk25.default.dim(`command: ${options.command} debounce: ${options.debounce}ms`));
|
|
14057
|
+
console.log(import_chalk25.default.dim("ctrl+c to stop\n"));
|
|
13804
14058
|
let debounceTimer = null;
|
|
13805
14059
|
const debounceMs = parseInt(options.debounce, 10);
|
|
13806
14060
|
let scanCount = 0;
|
|
13807
14061
|
let lastScore = 0;
|
|
14062
|
+
let ignoreWatchUntil = 0;
|
|
13808
14063
|
const runScan = () => {
|
|
13809
|
-
const text =
|
|
14064
|
+
const text = fs17.readFileSync(absPath, "utf-8");
|
|
13810
14065
|
const result = runPipeline(text, profile, options.command === "fix");
|
|
13811
14066
|
scanCount++;
|
|
13812
14067
|
const now = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false });
|
|
13813
|
-
console.log(
|
|
14068
|
+
console.log(import_chalk25.default.dim(`[${now}] saved \u2014 ${options.command}ing...`));
|
|
13814
14069
|
if (options.command === "score") {
|
|
13815
14070
|
const score = result.score;
|
|
13816
|
-
const color = score < 60 ?
|
|
14071
|
+
const color = score < 60 ? import_chalk25.default.red : score < 80 ? import_chalk25.default.yellow : import_chalk25.default.green;
|
|
13817
14072
|
console.log(` ${color(score + "/100")}`);
|
|
13818
14073
|
if (lastScore > 0 && score !== lastScore) {
|
|
13819
14074
|
const delta = score - lastScore;
|
|
13820
|
-
console.log(
|
|
14075
|
+
console.log(import_chalk25.default.dim(` ${delta > 0 ? "\u2191" : "\u2193"} ${Math.abs(delta)} from last scan`));
|
|
13821
14076
|
}
|
|
13822
14077
|
lastScore = score;
|
|
13823
14078
|
} else if (options.command === "fix") {
|
|
13824
14079
|
if (result.changes.length > 0) {
|
|
13825
14080
|
for (const change of result.changes) {
|
|
13826
|
-
console.log(
|
|
14081
|
+
console.log(import_chalk25.default.dim(` Line ${change.line}: `) + import_chalk25.default.red(change.before) + import_chalk25.default.dim(" \u2192 ") + import_chalk25.default.green(change.after));
|
|
13827
14082
|
}
|
|
13828
|
-
|
|
13829
|
-
|
|
13830
|
-
|
|
13831
|
-
console.log(import_chalk24.default.green(` \u2713 ${result.changes.length} auto-fixes applied`));
|
|
14083
|
+
ignoreWatchUntil = Date.now() + debounceMs + 200;
|
|
14084
|
+
writeInPlaceWithBackup(absPath, result.fixed);
|
|
14085
|
+
console.log(import_chalk25.default.green(` \u2713 ${result.changes.length} auto-fixes applied`));
|
|
13832
14086
|
} else {
|
|
13833
|
-
console.log(
|
|
14087
|
+
console.log(import_chalk25.default.green(" \u2713 no auto-fixable issues"));
|
|
13834
14088
|
}
|
|
13835
14089
|
} else {
|
|
13836
14090
|
if (result.stats.totalSignals === 0) {
|
|
13837
|
-
console.log(
|
|
14091
|
+
console.log(import_chalk25.default.green(` \u2713 clean \u2014 score: ${result.score}/100`));
|
|
13838
14092
|
} else {
|
|
13839
|
-
console.log(
|
|
14093
|
+
console.log(import_chalk25.default.yellow(` ${result.stats.totalSignals} issues (${result.stats.red} red, ${result.stats.yellow} yellow) score: ${result.score}/100`));
|
|
13840
14094
|
for (const signal of result.signalMap.signals.slice(0, 3)) {
|
|
13841
|
-
const sev = signal.severity === "red" ?
|
|
14095
|
+
const sev = signal.severity === "red" ? import_chalk25.default.red("\u25CF") : import_chalk25.default.yellow("\u25CB");
|
|
13842
14096
|
console.log(` ${sev} line ${signal.line}: ${signal.id} \u2014 ${signal.suggestion}`);
|
|
13843
14097
|
}
|
|
13844
14098
|
if (result.signalMap.signals.length > 3) {
|
|
13845
|
-
console.log(
|
|
14099
|
+
console.log(import_chalk25.default.dim(` ... and ${result.signalMap.signals.length - 3} more`));
|
|
13846
14100
|
}
|
|
13847
14101
|
}
|
|
13848
14102
|
}
|
|
13849
14103
|
console.log("");
|
|
13850
14104
|
};
|
|
13851
14105
|
runScan();
|
|
13852
|
-
|
|
14106
|
+
fs17.watch(absPath, (eventType) => {
|
|
13853
14107
|
if (eventType !== "change")
|
|
13854
14108
|
return;
|
|
14109
|
+
if (Date.now() < ignoreWatchUntil)
|
|
14110
|
+
return;
|
|
13855
14111
|
if (debounceTimer)
|
|
13856
14112
|
clearTimeout(debounceTimer);
|
|
13857
14113
|
debounceTimer = setTimeout(runScan, debounceMs);
|
|
13858
14114
|
});
|
|
13859
14115
|
process.on("SIGINT", () => {
|
|
13860
|
-
console.log(
|
|
14116
|
+
console.log(import_chalk25.default.dim(`
|
|
13861
14117
|
${scanCount} scans completed. exiting.`));
|
|
13862
14118
|
process.exit(0);
|
|
13863
14119
|
});
|
|
13864
14120
|
await new Promise(() => {
|
|
13865
14121
|
});
|
|
13866
14122
|
} catch (error) {
|
|
13867
|
-
console.error(
|
|
14123
|
+
console.error(import_chalk25.default.red(`Error: ${error.message}`));
|
|
13868
14124
|
process.exit(1);
|
|
13869
14125
|
}
|
|
13870
14126
|
});
|
|
13871
14127
|
}
|
|
13872
14128
|
|
|
13873
14129
|
// src/commands/demo.ts
|
|
13874
|
-
var
|
|
13875
|
-
var
|
|
14130
|
+
var import_chalk26 = __toESM(require_source());
|
|
14131
|
+
var fs18 = __toESM(require("fs"));
|
|
13876
14132
|
var SAMPLES = {
|
|
13877
14133
|
linkedin: {
|
|
13878
14134
|
text: `In today's fast-paced digital landscape, it's important to note that leveraging the right tools is not just nice to have, but essential for success. Let's delve into the holistic approach that will transform your workflow.
|
|
@@ -13962,46 +14218,46 @@ function registerDemoCommand(program3) {
|
|
|
13962
14218
|
const style = options.clean ? "clean" : options.style;
|
|
13963
14219
|
const sample = SAMPLES[style];
|
|
13964
14220
|
if (!sample) {
|
|
13965
|
-
console.error(
|
|
14221
|
+
console.error(import_chalk26.default.red(`Unknown style: ${options.style}. Valid: ${Object.keys(SAMPLES).filter((k) => k !== "clean").join(", ")}`));
|
|
13966
14222
|
process.exit(1);
|
|
13967
14223
|
}
|
|
13968
14224
|
if (options.output) {
|
|
13969
14225
|
const outputPath = require("path").resolve(options.output);
|
|
13970
|
-
|
|
13971
|
-
console.log(
|
|
14226
|
+
fs18.writeFileSync(outputPath, sample.text);
|
|
14227
|
+
console.log(import_chalk26.default.green(`
|
|
13972
14228
|
\u2713 Sample written to ${outputPath}`));
|
|
13973
14229
|
if (sample.patterns.length > 0) {
|
|
13974
|
-
console.log(
|
|
14230
|
+
console.log(import_chalk26.default.dim(` Contains ${sample.patterns.length} AI patterns: ${sample.patterns.slice(0, 5).join(", ")}...`));
|
|
13975
14231
|
}
|
|
13976
|
-
console.log(
|
|
14232
|
+
console.log(import_chalk26.default.dim(`
|
|
13977
14233
|
Scan it: hyv scan ${options.output}`));
|
|
13978
|
-
console.log(
|
|
14234
|
+
console.log(import_chalk26.default.dim(` Fix it: hyv fix ${options.output}`));
|
|
13979
14235
|
} else {
|
|
13980
|
-
console.log(
|
|
14236
|
+
console.log(import_chalk26.default.bold(`
|
|
13981
14237
|
\u2500\u2500\u2500 sample (${style}) \u2500\u2500\u2500
|
|
13982
14238
|
`));
|
|
13983
14239
|
console.log(sample.text);
|
|
13984
|
-
console.log(
|
|
14240
|
+
console.log(import_chalk26.default.dim(`
|
|
13985
14241
|
\u2500\u2500\u2500 end \u2500\u2500\u2500`));
|
|
13986
14242
|
if (sample.patterns.length > 0) {
|
|
13987
|
-
console.log(
|
|
14243
|
+
console.log(import_chalk26.default.dim(`
|
|
13988
14244
|
${sample.patterns.length} AI patterns embedded: ${sample.patterns.slice(0, 8).join(", ")}...`));
|
|
13989
14245
|
}
|
|
13990
|
-
console.log(
|
|
14246
|
+
console.log(import_chalk26.default.dim(`
|
|
13991
14247
|
Save to file: hyv demo --output demo.md`));
|
|
13992
|
-
console.log(
|
|
13993
|
-
console.log(
|
|
14248
|
+
console.log(import_chalk26.default.dim(` Scan it: hyv scan demo.md`));
|
|
14249
|
+
console.log(import_chalk26.default.dim(` Fix it: hyv fix demo.md
|
|
13994
14250
|
`));
|
|
13995
14251
|
}
|
|
13996
14252
|
} catch (error) {
|
|
13997
|
-
console.error(
|
|
14253
|
+
console.error(import_chalk26.default.red(`Error: ${error.message}`));
|
|
13998
14254
|
process.exit(1);
|
|
13999
14255
|
}
|
|
14000
14256
|
});
|
|
14001
14257
|
}
|
|
14002
14258
|
|
|
14003
14259
|
// src/commands/open.ts
|
|
14004
|
-
var
|
|
14260
|
+
var import_chalk27 = __toESM(require_source());
|
|
14005
14261
|
var PAGES = {
|
|
14006
14262
|
dashboard: "https://holdyourvoice.com/dashboard",
|
|
14007
14263
|
profiles: "https://holdyourvoice.com/dashboard",
|
|
@@ -14018,12 +14274,12 @@ function registerOpenCommand(program3) {
|
|
|
14018
14274
|
return;
|
|
14019
14275
|
}
|
|
14020
14276
|
const open3 = (await Promise.resolve().then(() => __toESM(require_open()))).default;
|
|
14021
|
-
console.log(
|
|
14277
|
+
console.log(import_chalk27.default.dim(`
|
|
14022
14278
|
Opening ${url}...`));
|
|
14023
14279
|
await open3(url);
|
|
14024
|
-
console.log(
|
|
14280
|
+
console.log(import_chalk27.default.green(" \u2713 Opened in browser\n"));
|
|
14025
14281
|
} catch (error) {
|
|
14026
|
-
console.error(
|
|
14282
|
+
console.error(import_chalk27.default.red(`Error: ${error.message}`));
|
|
14027
14283
|
process.exit(1);
|
|
14028
14284
|
}
|
|
14029
14285
|
});
|
|
@@ -14033,35 +14289,35 @@ function registerOpenCommand(program3) {
|
|
|
14033
14289
|
init_welcome();
|
|
14034
14290
|
|
|
14035
14291
|
// src/lib/onboarding.ts
|
|
14036
|
-
var
|
|
14037
|
-
var
|
|
14292
|
+
var fs19 = __toESM(require("fs"));
|
|
14293
|
+
var path19 = __toESM(require("path"));
|
|
14038
14294
|
var os6 = __toESM(require("os"));
|
|
14039
|
-
var hyvDir =
|
|
14040
|
-
var onboardingFile =
|
|
14295
|
+
var hyvDir = path19.join(os6.homedir(), ".hyv");
|
|
14296
|
+
var onboardingFile = path19.join(hyvDir, "onboarding-complete.json");
|
|
14041
14297
|
function hasCompletedOnboarding() {
|
|
14042
14298
|
try {
|
|
14043
|
-
return
|
|
14299
|
+
return fs19.existsSync(onboardingFile);
|
|
14044
14300
|
} catch {
|
|
14045
14301
|
return false;
|
|
14046
14302
|
}
|
|
14047
14303
|
}
|
|
14048
14304
|
function markOnboardingComplete(version) {
|
|
14049
|
-
if (!
|
|
14050
|
-
|
|
14051
|
-
|
|
14305
|
+
if (!fs19.existsSync(hyvDir))
|
|
14306
|
+
fs19.mkdirSync(hyvDir, { recursive: true });
|
|
14307
|
+
fs19.writeFileSync(
|
|
14052
14308
|
onboardingFile,
|
|
14053
14309
|
JSON.stringify({ version, completed_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
|
|
14054
14310
|
);
|
|
14055
14311
|
}
|
|
14056
14312
|
|
|
14057
14313
|
// src/commands/welcome.ts
|
|
14058
|
-
var
|
|
14059
|
-
var
|
|
14314
|
+
var fs20 = __toESM(require("fs"));
|
|
14315
|
+
var path20 = __toESM(require("path"));
|
|
14060
14316
|
function registerWelcomeCommand(program3) {
|
|
14061
14317
|
const pkgVersion3 = (() => {
|
|
14062
14318
|
try {
|
|
14063
|
-
const pkgPath3 =
|
|
14064
|
-
return JSON.parse(
|
|
14319
|
+
const pkgPath3 = path20.resolve(__dirname, "..", "package.json");
|
|
14320
|
+
return JSON.parse(fs20.readFileSync(pkgPath3, "utf-8")).version;
|
|
14065
14321
|
} catch {
|
|
14066
14322
|
return "0.0.0";
|
|
14067
14323
|
}
|
|
@@ -14085,7 +14341,7 @@ function getWelcomeText() {
|
|
|
14085
14341
|
}
|
|
14086
14342
|
|
|
14087
14343
|
// src/commands/content.ts
|
|
14088
|
-
var
|
|
14344
|
+
var import_chalk28 = __toESM(require_source());
|
|
14089
14345
|
init_free_paid();
|
|
14090
14346
|
var TEMPLATES = {
|
|
14091
14347
|
cursor: {
|
|
@@ -14159,68 +14415,68 @@ ${COMMUNITY_URL}`
|
|
|
14159
14415
|
function registerContentCommand(program3) {
|
|
14160
14416
|
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) => {
|
|
14161
14417
|
if (opts.list) {
|
|
14162
|
-
console.log(
|
|
14418
|
+
console.log(import_chalk28.default.bold("\nhyv content templates\n"));
|
|
14163
14419
|
for (const [key, t2] of Object.entries(TEMPLATES)) {
|
|
14164
|
-
console.log(
|
|
14420
|
+
console.log(import_chalk28.default.dim(` ${key}`) + ` \u2014 ${t2.title}`);
|
|
14165
14421
|
}
|
|
14166
14422
|
console.log("");
|
|
14167
14423
|
return;
|
|
14168
14424
|
}
|
|
14169
14425
|
const t = TEMPLATES[topic] || TEMPLATES.cursor;
|
|
14170
|
-
console.log(
|
|
14426
|
+
console.log(import_chalk28.default.bold(`
|
|
14171
14427
|
${t.title}
|
|
14172
14428
|
`));
|
|
14173
14429
|
console.log(t.body);
|
|
14174
|
-
console.log(
|
|
14430
|
+
console.log(import_chalk28.default.dim("\nBlog: https://holdyourvoice.com/blog\n"));
|
|
14175
14431
|
});
|
|
14176
14432
|
}
|
|
14177
14433
|
|
|
14178
14434
|
// src/commands/upgrade.ts
|
|
14179
|
-
var
|
|
14180
|
-
var
|
|
14435
|
+
var import_chalk29 = __toESM(require_source());
|
|
14436
|
+
var import_child_process3 = require("child_process");
|
|
14181
14437
|
init_version();
|
|
14182
14438
|
function registerUpgradeCommand(program3) {
|
|
14183
14439
|
program3.command("upgrade").description("Upgrade to the latest @holdyourvoice/hyv").option("--check", "Only check if an update is available").action(async (opts) => {
|
|
14184
14440
|
const current = getCliVersion();
|
|
14185
|
-
console.log(
|
|
14441
|
+
console.log(import_chalk29.default.dim(`
|
|
14186
14442
|
Current: ${getEngineLabel()}
|
|
14187
14443
|
`));
|
|
14188
14444
|
let latest = current;
|
|
14189
14445
|
try {
|
|
14190
|
-
const out = (0,
|
|
14446
|
+
const out = (0, import_child_process3.execSync)("npm view @holdyourvoice/hyv version", { encoding: "utf-8", timeout: 15e3 });
|
|
14191
14447
|
latest = out.trim();
|
|
14192
14448
|
} catch {
|
|
14193
|
-
console.log(
|
|
14449
|
+
console.log(import_chalk29.default.yellow("Could not reach npm registry. Try: npm i -g @holdyourvoice/hyv@latest"));
|
|
14194
14450
|
return;
|
|
14195
14451
|
}
|
|
14196
14452
|
const cmp = compareSemver(current, latest);
|
|
14197
14453
|
if (cmp === 0) {
|
|
14198
|
-
console.log(
|
|
14454
|
+
console.log(import_chalk29.default.green("\u2713 You are on the latest version."));
|
|
14199
14455
|
return;
|
|
14200
14456
|
}
|
|
14201
14457
|
if (cmp > 0) {
|
|
14202
|
-
console.log(
|
|
14458
|
+
console.log(import_chalk29.default.green(`\u2713 You are ahead of npm (published: ${latest}).`));
|
|
14203
14459
|
return;
|
|
14204
14460
|
}
|
|
14205
|
-
console.log(
|
|
14461
|
+
console.log(import_chalk29.default.cyan(`Update available: ${current} \u2192 ${latest}`));
|
|
14206
14462
|
if (opts.check) {
|
|
14207
|
-
console.log(
|
|
14463
|
+
console.log(import_chalk29.default.dim("\nRun: hyv upgrade or npm i -g @holdyourvoice/hyv@latest\n"));
|
|
14208
14464
|
return;
|
|
14209
14465
|
}
|
|
14210
|
-
console.log(
|
|
14466
|
+
console.log(import_chalk29.default.dim("Installing..."));
|
|
14211
14467
|
try {
|
|
14212
|
-
(0,
|
|
14213
|
-
console.log(
|
|
14468
|
+
(0, import_child_process3.execSync)("npm i -g @holdyourvoice/hyv@latest", { stdio: "inherit" });
|
|
14469
|
+
console.log(import_chalk29.default.green("\n\u2713 Upgraded successfully. Restart your terminal.\n"));
|
|
14214
14470
|
} catch {
|
|
14215
|
-
console.log(
|
|
14471
|
+
console.log(import_chalk29.default.red("\nUpgrade failed. Run manually: npm i -g @holdyourvoice/hyv@latest\n"));
|
|
14216
14472
|
process.exit(1);
|
|
14217
14473
|
}
|
|
14218
14474
|
});
|
|
14219
14475
|
}
|
|
14220
14476
|
|
|
14221
14477
|
// src/mcp.ts
|
|
14222
|
-
var
|
|
14223
|
-
var
|
|
14478
|
+
var fs21 = __toESM(require("fs"));
|
|
14479
|
+
var path21 = __toESM(require("path"));
|
|
14224
14480
|
var os7 = __toESM(require("os"));
|
|
14225
14481
|
init_classifier();
|
|
14226
14482
|
init_autofix();
|
|
@@ -14232,20 +14488,20 @@ init_welcome();
|
|
|
14232
14488
|
init_config();
|
|
14233
14489
|
init_telemetry();
|
|
14234
14490
|
init_access();
|
|
14235
|
-
var VOICE_MD =
|
|
14491
|
+
var VOICE_MD = path21.join(os7.homedir(), ".hyv", "voice.md");
|
|
14236
14492
|
var MAX_RESPONSE_CHARS = 12e4;
|
|
14237
14493
|
var MAX_SCAN_FILE_BYTES = 2 * 1024 * 1024;
|
|
14238
14494
|
function readScanFile(filePath) {
|
|
14239
|
-
const cwdReal =
|
|
14240
|
-
const resolved =
|
|
14241
|
-
if (!resolved.startsWith(cwdReal +
|
|
14495
|
+
const cwdReal = fs21.realpathSync(process.cwd());
|
|
14496
|
+
const resolved = fs21.realpathSync(path21.resolve(filePath));
|
|
14497
|
+
if (!resolved.startsWith(cwdReal + path21.sep) && resolved !== cwdReal) {
|
|
14242
14498
|
throw new Error(`file must be in the current working directory (${cwdReal})`);
|
|
14243
14499
|
}
|
|
14244
|
-
const stat =
|
|
14500
|
+
const stat = fs21.statSync(resolved);
|
|
14245
14501
|
if (stat.size > MAX_SCAN_FILE_BYTES) {
|
|
14246
14502
|
throw new Error(`file too large (max ${MAX_SCAN_FILE_BYTES} bytes)`);
|
|
14247
14503
|
}
|
|
14248
|
-
return
|
|
14504
|
+
return fs21.readFileSync(resolved, "utf-8");
|
|
14249
14505
|
}
|
|
14250
14506
|
function toolResultPayload(result) {
|
|
14251
14507
|
const isError = result.startsWith("Error:") || result.startsWith("Unknown tool:");
|
|
@@ -14254,10 +14510,10 @@ function toolResultPayload(result) {
|
|
|
14254
14510
|
...isError ? { isError: true } : {}
|
|
14255
14511
|
};
|
|
14256
14512
|
}
|
|
14257
|
-
var pkgPath =
|
|
14513
|
+
var pkgPath = path21.resolve(__dirname, "..", "package.json");
|
|
14258
14514
|
var pkgVersion = (() => {
|
|
14259
14515
|
try {
|
|
14260
|
-
return JSON.parse(
|
|
14516
|
+
return JSON.parse(fs21.readFileSync(pkgPath, "utf-8")).version;
|
|
14261
14517
|
} catch {
|
|
14262
14518
|
return "2.7.1";
|
|
14263
14519
|
}
|
|
@@ -14831,7 +15087,7 @@ async function handleRequest(line) {
|
|
|
14831
15087
|
}
|
|
14832
15088
|
async function startMcpServer() {
|
|
14833
15089
|
const access = await getAccessState().catch(() => null);
|
|
14834
|
-
if (
|
|
15090
|
+
if (fs21.existsSync(VOICE_MD)) {
|
|
14835
15091
|
mcpLog("info", `voice profile: ${VOICE_MD}`);
|
|
14836
15092
|
} else {
|
|
14837
15093
|
mcpLog("info", "free local engine ready \u2014 no voice profile yet");
|
|
@@ -14863,228 +15119,142 @@ async function startMcpServer() {
|
|
|
14863
15119
|
}
|
|
14864
15120
|
|
|
14865
15121
|
// src/lib/mcp-setup.ts
|
|
14866
|
-
var
|
|
14867
|
-
var
|
|
14868
|
-
var
|
|
15122
|
+
var import_chalk30 = __toESM(require_source());
|
|
15123
|
+
var fs22 = __toESM(require("fs"));
|
|
15124
|
+
var path22 = __toESM(require("path"));
|
|
14869
15125
|
var os8 = __toESM(require("os"));
|
|
14870
|
-
var import_child_process3 = require("child_process");
|
|
14871
15126
|
init_version();
|
|
14872
15127
|
var HOME2 = os8.homedir();
|
|
14873
15128
|
var IS_WIN2 = process.platform === "win32";
|
|
14874
15129
|
function claudeDesktopConfigPath() {
|
|
14875
15130
|
if (IS_WIN2)
|
|
14876
|
-
return
|
|
15131
|
+
return path22.join(HOME2, "AppData", "Roaming", "Claude", "claude_desktop_config.json");
|
|
14877
15132
|
if (process.platform === "linux")
|
|
14878
|
-
return
|
|
14879
|
-
return
|
|
14880
|
-
}
|
|
14881
|
-
function mcpSnippet() {
|
|
14882
|
-
const entry = [
|
|
14883
|
-
path21.resolve(process.argv[1] || ""),
|
|
14884
|
-
path21.resolve(__dirname, "index.js"),
|
|
14885
|
-
path21.resolve(__dirname, "..", "dist", "index.js")
|
|
14886
|
-
].find((p) => p && fs21.existsSync(p));
|
|
14887
|
-
if (entry) {
|
|
14888
|
-
return JSON.stringify({ command: process.execPath, args: [entry, "mcp"] }, null, 2);
|
|
14889
|
-
}
|
|
14890
|
-
return JSON.stringify({ command: "hyv", args: ["mcp"] }, null, 2);
|
|
15133
|
+
return path22.join(HOME2, ".config", "Claude", "claude_desktop_config.json");
|
|
15134
|
+
return path22.join(HOME2, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
14891
15135
|
}
|
|
14892
15136
|
function printMcpSetup() {
|
|
14893
|
-
console.log(
|
|
14894
|
-
console.log(
|
|
15137
|
+
console.log(import_chalk30.default.bold("\nhold your voice \u2014 mcp setup\n"));
|
|
15138
|
+
console.log(import_chalk30.default.dim(` ${getEngineLabel()}
|
|
14895
15139
|
`));
|
|
14896
|
-
console.log(
|
|
14897
|
-
console.log(
|
|
14898
|
-
console.log(
|
|
14899
|
-
console.log(
|
|
15140
|
+
console.log(import_chalk30.default.bold("Claude Desktop"));
|
|
15141
|
+
console.log(import_chalk30.default.dim(" Add to claude_desktop_config.json \u2192 mcpServers.hyv:"));
|
|
15142
|
+
console.log(import_chalk30.default.cyan(` ${mcpServerSnippet().split("\n").join("\n ")}`));
|
|
15143
|
+
console.log(import_chalk30.default.dim(` Config: ${claudeDesktopConfigPath()}
|
|
14900
15144
|
`));
|
|
14901
|
-
console.log(
|
|
14902
|
-
console.log(
|
|
14903
|
-
console.log(
|
|
14904
|
-
console.log(
|
|
14905
|
-
console.log(
|
|
14906
|
-
console.log(
|
|
14907
|
-
console.log(
|
|
14908
|
-
console.log(
|
|
14909
|
-
console.log(
|
|
14910
|
-
console.log(
|
|
14911
|
-
console.log(
|
|
14912
|
-
console.log(
|
|
14913
|
-
console.log(
|
|
14914
|
-
console.log(
|
|
14915
|
-
console.log(
|
|
14916
|
-
console.log(
|
|
14917
|
-
console.log(
|
|
14918
|
-
console.log(
|
|
14919
|
-
console.log(
|
|
14920
|
-
console.log(
|
|
14921
|
-
}
|
|
14922
|
-
async function testMcpStdioSubprocess() {
|
|
14923
|
-
const candidates = [
|
|
14924
|
-
path21.resolve(process.argv[1] || ""),
|
|
14925
|
-
path21.resolve(__dirname, "index.js"),
|
|
14926
|
-
path21.resolve(__dirname, "..", "dist", "index.js")
|
|
14927
|
-
];
|
|
14928
|
-
const entry = candidates.find((p) => p && fs21.existsSync(p));
|
|
14929
|
-
if (!entry)
|
|
14930
|
-
return { ok: false };
|
|
14931
|
-
return new Promise((resolve14) => {
|
|
14932
|
-
const child = (0, import_child_process3.spawn)(process.execPath, [entry, "mcp"], {
|
|
14933
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
14934
|
-
env: { ...process.env, HYV_POSTINSTALL_QUIET: "1" }
|
|
14935
|
-
});
|
|
14936
|
-
let buffer = "";
|
|
14937
|
-
let settled = false;
|
|
14938
|
-
const finish = (ok, toolCount) => {
|
|
14939
|
-
if (settled)
|
|
14940
|
-
return;
|
|
14941
|
-
settled = true;
|
|
14942
|
-
clearTimeout(timeout);
|
|
14943
|
-
try {
|
|
14944
|
-
child.kill();
|
|
14945
|
-
} catch {
|
|
14946
|
-
}
|
|
14947
|
-
resolve14({ ok, toolCount });
|
|
14948
|
-
};
|
|
14949
|
-
const timeout = setTimeout(() => finish(false), 1e4);
|
|
14950
|
-
const handleLine = (line) => {
|
|
14951
|
-
const trimmed = line.trim();
|
|
14952
|
-
if (!trimmed.startsWith("{"))
|
|
14953
|
-
return;
|
|
14954
|
-
try {
|
|
14955
|
-
const msg = JSON.parse(trimmed);
|
|
14956
|
-
if (msg.id === 2 && Array.isArray(msg.result?.tools) && msg.result.tools.length > 0) {
|
|
14957
|
-
finish(true, msg.result.tools.length);
|
|
14958
|
-
}
|
|
14959
|
-
} catch {
|
|
14960
|
-
}
|
|
14961
|
-
};
|
|
14962
|
-
child.stdout.on("data", (chunk) => {
|
|
14963
|
-
buffer += chunk.toString();
|
|
14964
|
-
const lines = buffer.split("\n");
|
|
14965
|
-
buffer = lines.pop() || "";
|
|
14966
|
-
for (const line of lines)
|
|
14967
|
-
handleLine(line);
|
|
14968
|
-
});
|
|
14969
|
-
child.on("error", () => finish(false));
|
|
14970
|
-
child.on("exit", () => {
|
|
14971
|
-
if (!settled) {
|
|
14972
|
-
handleLine(buffer);
|
|
14973
|
-
finish(buffer.includes("hyv_scan"));
|
|
14974
|
-
}
|
|
14975
|
-
});
|
|
14976
|
-
setTimeout(() => {
|
|
14977
|
-
const send2 = (payload) => {
|
|
14978
|
-
child.stdin.write(`${JSON.stringify(payload)}
|
|
14979
|
-
`);
|
|
14980
|
-
};
|
|
14981
|
-
send2({
|
|
14982
|
-
jsonrpc: "2.0",
|
|
14983
|
-
id: 1,
|
|
14984
|
-
method: "initialize",
|
|
14985
|
-
params: {
|
|
14986
|
-
protocolVersion: "2024-11-05",
|
|
14987
|
-
capabilities: {},
|
|
14988
|
-
clientInfo: { name: "hyv-self-test", version: "1.0" }
|
|
14989
|
-
}
|
|
14990
|
-
});
|
|
14991
|
-
send2({ jsonrpc: "2.0", method: "notifications/initialized" });
|
|
14992
|
-
send2({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} });
|
|
14993
|
-
}, 500);
|
|
14994
|
-
});
|
|
15145
|
+
console.log(import_chalk30.default.bold("Cursor"));
|
|
15146
|
+
console.log(import_chalk30.default.dim(" MCP: ~/.cursor/mcp.json \u2192 mcpServers.hyv (same JSON as above)"));
|
|
15147
|
+
console.log(import_chalk30.default.dim(" Rule: ~/.cursor/rules/hyv.mdc (alwaysApply \u2014 auto via postinstall)\n"));
|
|
15148
|
+
console.log(import_chalk30.default.bold("Claude Code"));
|
|
15149
|
+
console.log(import_chalk30.default.dim(" Command: ~/.claude/commands/hyv.md"));
|
|
15150
|
+
console.log(import_chalk30.default.dim(" Skill: ~/.claude/skills/hold-your-voice/SKILL.md\n"));
|
|
15151
|
+
console.log(import_chalk30.default.bold("Windsurf"));
|
|
15152
|
+
console.log(import_chalk30.default.dim(" Rule: ~/.windsurf/rules/hyv.md (trigger: always_on)\n"));
|
|
15153
|
+
console.log(import_chalk30.default.bold("Codex"));
|
|
15154
|
+
console.log(import_chalk30.default.dim(" Instructions: ~/.codex/AGENTS.md (merged on install)\n"));
|
|
15155
|
+
console.log(import_chalk30.default.bold("Command Code"));
|
|
15156
|
+
console.log(import_chalk30.default.dim(" Skill: ~/.commandcode/skills/hyv/SKILL.md\n"));
|
|
15157
|
+
console.log(import_chalk30.default.bold("ChatGPT"));
|
|
15158
|
+
console.log(import_chalk30.default.dim(" hyv mcp --setup-chatgpt\n"));
|
|
15159
|
+
console.log(import_chalk30.default.bold("Auto-configure"));
|
|
15160
|
+
console.log(import_chalk30.default.dim(" hyv doctor --fix-agents"));
|
|
15161
|
+
console.log(import_chalk30.default.dim(" HYV_AUTO_CONFIGURE_AGENTS=0 npm i -g @holdyourvoice/hyv (skip)\n"));
|
|
15162
|
+
console.log(import_chalk30.default.bold("Verify"));
|
|
15163
|
+
console.log(import_chalk30.default.dim(" hyv mcp --test"));
|
|
15164
|
+
console.log(import_chalk30.default.dim(" HYV_TELEMETRY=1 hyv mcp (optional usage logging to ~/.hyv/telemetry/)\n"));
|
|
14995
15165
|
}
|
|
14996
15166
|
async function runMcpSelfTest() {
|
|
14997
|
-
console.log(
|
|
14998
|
-
console.log(
|
|
15167
|
+
console.log(import_chalk30.default.bold("\nhold your voice \u2014 mcp self-test\n"));
|
|
15168
|
+
console.log(import_chalk30.default.dim(` ${getEngineLabel()}
|
|
14999
15169
|
`));
|
|
15000
15170
|
let passed = 0;
|
|
15001
15171
|
let failed = 0;
|
|
15002
15172
|
const tools = getMcpToolNames();
|
|
15003
15173
|
if (tools.length >= 10) {
|
|
15004
|
-
console.log(
|
|
15174
|
+
console.log(import_chalk30.default.green(` \u2713 ${tools.length} MCP tools registered`));
|
|
15005
15175
|
passed++;
|
|
15006
15176
|
} else {
|
|
15007
|
-
console.log(
|
|
15177
|
+
console.log(import_chalk30.default.red(` \u2717 expected 10+ tools, got ${tools.length}`));
|
|
15008
15178
|
failed++;
|
|
15009
15179
|
}
|
|
15010
15180
|
const required = ["hyv_welcome", "hyv_scan", "hyv_analyze", "hyv_clean", "hyv_validate", "hyv_list_free_tools"];
|
|
15011
15181
|
for (const name of required) {
|
|
15012
15182
|
if (tools.includes(name)) {
|
|
15013
|
-
console.log(
|
|
15183
|
+
console.log(import_chalk30.default.green(` \u2713 tool: ${name}`));
|
|
15014
15184
|
passed++;
|
|
15015
15185
|
} else {
|
|
15016
|
-
console.log(
|
|
15186
|
+
console.log(import_chalk30.default.red(` \u2717 missing tool: ${name}`));
|
|
15017
15187
|
failed++;
|
|
15018
15188
|
}
|
|
15019
15189
|
}
|
|
15020
15190
|
try {
|
|
15021
15191
|
const welcome = await invokeMcpTool("hyv_welcome", {});
|
|
15022
15192
|
if (welcome.includes("Hold Your Voice") || welcome.includes("hold your voice")) {
|
|
15023
|
-
console.log(
|
|
15193
|
+
console.log(import_chalk30.default.green(" \u2713 hyv_welcome responds"));
|
|
15024
15194
|
passed++;
|
|
15025
15195
|
} else {
|
|
15026
|
-
console.log(
|
|
15196
|
+
console.log(import_chalk30.default.red(" \u2717 hyv_welcome unexpected output"));
|
|
15027
15197
|
failed++;
|
|
15028
15198
|
}
|
|
15029
15199
|
} catch (e) {
|
|
15030
|
-
console.log(
|
|
15200
|
+
console.log(import_chalk30.default.red(` \u2717 hyv_welcome failed: ${e.message}`));
|
|
15031
15201
|
failed++;
|
|
15032
15202
|
}
|
|
15033
15203
|
try {
|
|
15034
15204
|
const demo = await invokeMcpTool("hyv_demo", {});
|
|
15035
15205
|
if (demo.includes("Score") || demo.includes("issues")) {
|
|
15036
|
-
console.log(
|
|
15206
|
+
console.log(import_chalk30.default.green(" \u2713 hyv_demo pipeline works"));
|
|
15037
15207
|
passed++;
|
|
15038
15208
|
} else {
|
|
15039
|
-
console.log(
|
|
15209
|
+
console.log(import_chalk30.default.red(" \u2717 hyv_demo unexpected output"));
|
|
15040
15210
|
failed++;
|
|
15041
15211
|
}
|
|
15042
15212
|
} catch (e) {
|
|
15043
|
-
console.log(
|
|
15213
|
+
console.log(import_chalk30.default.red(` \u2717 hyv_demo failed: ${e.message}`));
|
|
15044
15214
|
failed++;
|
|
15045
15215
|
}
|
|
15046
|
-
const voiceMd =
|
|
15047
|
-
if (
|
|
15048
|
-
console.log(
|
|
15216
|
+
const voiceMd = path22.join(HOME2, ".hyv", "voice.md");
|
|
15217
|
+
if (fs22.existsSync(voiceMd)) {
|
|
15218
|
+
console.log(import_chalk30.default.green(" \u2713 voice profile found"));
|
|
15049
15219
|
passed++;
|
|
15050
15220
|
} else {
|
|
15051
|
-
console.log(
|
|
15221
|
+
console.log(import_chalk30.default.dim(" - no voice.md (free local engine still works)"));
|
|
15052
15222
|
}
|
|
15053
15223
|
if (getDemoText().length > 100) {
|
|
15054
|
-
console.log(
|
|
15224
|
+
console.log(import_chalk30.default.green(" \u2713 demo content available"));
|
|
15055
15225
|
passed++;
|
|
15056
15226
|
} else {
|
|
15057
|
-
console.log(
|
|
15227
|
+
console.log(import_chalk30.default.red(" \u2717 demo content missing"));
|
|
15058
15228
|
failed++;
|
|
15059
15229
|
}
|
|
15060
15230
|
try {
|
|
15061
15231
|
const stdio = await testMcpStdioSubprocess();
|
|
15062
15232
|
if (stdio.ok && (stdio.toolCount || 0) >= 10) {
|
|
15063
|
-
console.log(
|
|
15233
|
+
console.log(import_chalk30.default.green(` \u2713 stdio MCP subprocess responds (${stdio.toolCount} tools)`));
|
|
15064
15234
|
passed++;
|
|
15065
15235
|
} else if (stdio.ok) {
|
|
15066
|
-
console.log(
|
|
15236
|
+
console.log(import_chalk30.default.yellow(` ! stdio MCP subprocess ok but only ${stdio.toolCount || 0} tools`));
|
|
15067
15237
|
failed++;
|
|
15068
15238
|
} else {
|
|
15069
|
-
console.log(
|
|
15239
|
+
console.log(import_chalk30.default.red(" \u2717 stdio MCP subprocess failed"));
|
|
15070
15240
|
failed++;
|
|
15071
15241
|
}
|
|
15072
15242
|
} catch (e) {
|
|
15073
|
-
console.log(
|
|
15243
|
+
console.log(import_chalk30.default.red(` \u2717 stdio MCP subprocess failed: ${e.message}`));
|
|
15074
15244
|
failed++;
|
|
15075
15245
|
}
|
|
15076
15246
|
console.log("");
|
|
15077
15247
|
if (failed === 0) {
|
|
15078
|
-
console.log(
|
|
15079
|
-
console.log(
|
|
15248
|
+
console.log(import_chalk30.default.green(`\u2713 all checks passed (${passed})`));
|
|
15249
|
+
console.log(import_chalk30.default.dim("\nStart server: hyv mcp\n"));
|
|
15080
15250
|
return true;
|
|
15081
15251
|
}
|
|
15082
|
-
console.log(
|
|
15252
|
+
console.log(import_chalk30.default.yellow(`! ${failed} check(s) failed, ${passed} passed`));
|
|
15083
15253
|
return false;
|
|
15084
15254
|
}
|
|
15085
15255
|
|
|
15086
15256
|
// src/commands/export.ts
|
|
15087
|
-
var
|
|
15257
|
+
var fs23 = __toESM(require("fs"));
|
|
15088
15258
|
init_api();
|
|
15089
15259
|
var FORMATS = {
|
|
15090
15260
|
claude: {
|
|
@@ -15171,7 +15341,7 @@ async function exportCommand(format, opts) {
|
|
|
15171
15341
|
const prompt = fmt.wrap(detail.profile, detail.body);
|
|
15172
15342
|
if (opts.output) {
|
|
15173
15343
|
const outFile = opts.output.replace("{name}", profile.slug || profile.name);
|
|
15174
|
-
|
|
15344
|
+
fs23.writeFileSync(outFile, prompt);
|
|
15175
15345
|
results.push({ profile: profile.name, file: outFile });
|
|
15176
15346
|
} else {
|
|
15177
15347
|
results.push({ profile: profile.name, prompt });
|
|
@@ -15208,13 +15378,13 @@ async function exportCommand(format, opts) {
|
|
|
15208
15378
|
// src/index.ts
|
|
15209
15379
|
init_access();
|
|
15210
15380
|
init_welcome();
|
|
15211
|
-
var
|
|
15212
|
-
var
|
|
15381
|
+
var fs24 = __toESM(require("fs"));
|
|
15382
|
+
var path23 = __toESM(require("path"));
|
|
15213
15383
|
var program2 = new Command();
|
|
15214
|
-
var pkgPath2 =
|
|
15384
|
+
var pkgPath2 = path23.resolve(__dirname, "..", "package.json");
|
|
15215
15385
|
var pkgVersion2 = (() => {
|
|
15216
15386
|
try {
|
|
15217
|
-
return JSON.parse(
|
|
15387
|
+
return JSON.parse(fs24.readFileSync(pkgPath2, "utf-8")).version;
|
|
15218
15388
|
} catch {
|
|
15219
15389
|
return "2.7.1";
|
|
15220
15390
|
}
|
|
@@ -15258,15 +15428,15 @@ program2.command("mcp").description("Start MCP server (for Claude Desktop and ot
|
|
|
15258
15428
|
return;
|
|
15259
15429
|
}
|
|
15260
15430
|
if (opts.setupChatgpt) {
|
|
15261
|
-
console.log(
|
|
15431
|
+
console.log(import_chalk31.default.bold("\nhold your voice \u2014 chatgpt setup\n"));
|
|
15262
15432
|
console.log("To connect HYV to ChatGPT:");
|
|
15263
|
-
console.log(
|
|
15264
|
-
console.log(
|
|
15265
|
-
console.log(
|
|
15266
|
-
console.log(
|
|
15433
|
+
console.log(import_chalk31.default.dim(" 1. Go to ") + import_chalk31.default.cyan("https://chatgpt.com/#settings/Connectors"));
|
|
15434
|
+
console.log(import_chalk31.default.dim(" 2. Add a new connector"));
|
|
15435
|
+
console.log(import_chalk31.default.dim(" 3. For local MCP, use: ") + import_chalk31.default.cyan("hyv mcp"));
|
|
15436
|
+
console.log(import_chalk31.default.dim(" 4. ChatGPT Desktop supports stdio MCP servers"));
|
|
15267
15437
|
console.log("");
|
|
15268
|
-
console.log(
|
|
15269
|
-
console.log(
|
|
15438
|
+
console.log(import_chalk31.default.dim("Note: The remote HTTP MCP endpoint is not yet available."));
|
|
15439
|
+
console.log(import_chalk31.default.dim("Use the local stdio MCP server with Claude Desktop or Claude Code instead."));
|
|
15270
15440
|
return;
|
|
15271
15441
|
}
|
|
15272
15442
|
startMcpServer();
|