@holdyourvoice/hyv 2.9.10 → 2.9.12
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 +12 -0
- package/README.md +12 -0
- package/dist/index.js +563 -370
- package/package.json +3 -1
- package/scripts/install.ps1 +89 -0
- package/scripts/install.sh +155 -0
- package/scripts/postinstall-lib.js +163 -7
- package/scripts/postinstall.js +1 -0
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 path27 = require("node:path");
|
|
977
|
+
var fs30 = 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 = path27.resolve(baseDir, baseName);
|
|
1920
|
+
if (fs30.existsSync(localBin))
|
|
1921
1921
|
return localBin;
|
|
1922
|
-
if (sourceExt.includes(
|
|
1922
|
+
if (sourceExt.includes(path27.extname(baseName)))
|
|
1923
1923
|
return void 0;
|
|
1924
1924
|
const foundExt = sourceExt.find(
|
|
1925
|
-
(ext) =>
|
|
1925
|
+
(ext) => fs30.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 = fs30.realpathSync(this._scriptPath);
|
|
1939
1939
|
} catch (err) {
|
|
1940
1940
|
resolvedScriptPath = this._scriptPath;
|
|
1941
1941
|
}
|
|
1942
|
-
executableDir =
|
|
1943
|
-
|
|
1942
|
+
executableDir = path27.resolve(
|
|
1943
|
+
path27.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 = path27.basename(
|
|
1951
1951
|
this._scriptPath,
|
|
1952
|
-
|
|
1952
|
+
path27.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(path27.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 = path27.basename(filename, path27.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(path28) {
|
|
2835
|
+
if (path28 === void 0)
|
|
2836
2836
|
return this._executableDir;
|
|
2837
|
-
this._executableDir =
|
|
2837
|
+
this._executableDir = path28;
|
|
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 path27 = [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
|
+
path27.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 = path27;
|
|
3946
3946
|
return fn;
|
|
3947
3947
|
}
|
|
3948
3948
|
module2.exports = function(fromModel) {
|
|
@@ -4182,7 +4182,7 @@ var require_has_flag = __commonJS({
|
|
|
4182
4182
|
var require_supports_color = __commonJS({
|
|
4183
4183
|
"node_modules/supports-color/index.js"(exports2, module2) {
|
|
4184
4184
|
"use strict";
|
|
4185
|
-
var
|
|
4185
|
+
var os13 = require("os");
|
|
4186
4186
|
var tty = require("tty");
|
|
4187
4187
|
var hasFlag = require_has_flag();
|
|
4188
4188
|
var { env } = process;
|
|
@@ -4230,7 +4230,7 @@ var require_supports_color = __commonJS({
|
|
|
4230
4230
|
return min;
|
|
4231
4231
|
}
|
|
4232
4232
|
if (process.platform === "win32") {
|
|
4233
|
-
const osRelease =
|
|
4233
|
+
const osRelease = os13.release().split(".");
|
|
4234
4234
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
4235
4235
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
4236
4236
|
}
|
|
@@ -4619,12 +4619,12 @@ function shouldReplaceCachedContent(existing, incoming) {
|
|
|
4619
4619
|
}
|
|
4620
4620
|
return true;
|
|
4621
4621
|
}
|
|
4622
|
-
function
|
|
4623
|
-
if (!fs.existsSync(
|
|
4622
|
+
function backupFileIfExists(filePath) {
|
|
4623
|
+
if (!fs.existsSync(filePath)) {
|
|
4624
4624
|
return false;
|
|
4625
4625
|
}
|
|
4626
4626
|
try {
|
|
4627
|
-
fs.copyFileSync(
|
|
4627
|
+
fs.copyFileSync(filePath, `${filePath}.hyv.bak`);
|
|
4628
4628
|
return true;
|
|
4629
4629
|
} catch {
|
|
4630
4630
|
return false;
|
|
@@ -4637,10 +4637,21 @@ function safeWriteProfileFile(profilePath, content, existing) {
|
|
|
4637
4637
|
if (existing !== null && existing === content) {
|
|
4638
4638
|
return { written: false, backedUp: false, reason: "unchanged" };
|
|
4639
4639
|
}
|
|
4640
|
-
const backedUp =
|
|
4640
|
+
const backedUp = backupFileIfExists(profilePath);
|
|
4641
4641
|
fs.writeFileSync(profilePath, content, { mode: 384 });
|
|
4642
4642
|
return { written: true, backedUp };
|
|
4643
4643
|
}
|
|
4644
|
+
function safeWriteJsonFile(filePath, content, existing) {
|
|
4645
|
+
if (!shouldReplaceCachedContent(existing, content)) {
|
|
4646
|
+
return { written: false, backedUp: false, reason: "empty-would-erase" };
|
|
4647
|
+
}
|
|
4648
|
+
if (existing !== null && existing === content) {
|
|
4649
|
+
return { written: false, backedUp: false, reason: "unchanged" };
|
|
4650
|
+
}
|
|
4651
|
+
const backedUp = backupFileIfExists(filePath);
|
|
4652
|
+
fs.writeFileSync(filePath, content, { mode: 384 });
|
|
4653
|
+
return { written: true, backedUp };
|
|
4654
|
+
}
|
|
4644
4655
|
var fs;
|
|
4645
4656
|
var init_data_safety = __esm({
|
|
4646
4657
|
"src/lib/data-safety.ts"() {
|
|
@@ -4649,6 +4660,72 @@ var init_data_safety = __esm({
|
|
|
4649
4660
|
}
|
|
4650
4661
|
});
|
|
4651
4662
|
|
|
4663
|
+
// src/lib/profile-meta.ts
|
|
4664
|
+
function ensureCacheDir() {
|
|
4665
|
+
if (!fs2.existsSync(CACHE_DIR)) {
|
|
4666
|
+
fs2.mkdirSync(CACHE_DIR, { recursive: true, mode: 448 });
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4669
|
+
function readStore() {
|
|
4670
|
+
try {
|
|
4671
|
+
if (!fs2.existsSync(META_FILE))
|
|
4672
|
+
return {};
|
|
4673
|
+
return JSON.parse(fs2.readFileSync(META_FILE, "utf-8"));
|
|
4674
|
+
} catch {
|
|
4675
|
+
return {};
|
|
4676
|
+
}
|
|
4677
|
+
}
|
|
4678
|
+
function writeStore(store) {
|
|
4679
|
+
ensureCacheDir();
|
|
4680
|
+
fs2.writeFileSync(META_FILE, JSON.stringify(store, null, 2), { mode: 384 });
|
|
4681
|
+
}
|
|
4682
|
+
function getProfileMeta(cacheKey) {
|
|
4683
|
+
return readStore()[cacheKey];
|
|
4684
|
+
}
|
|
4685
|
+
function setProfileMeta(cacheKey, entry) {
|
|
4686
|
+
const store = readStore();
|
|
4687
|
+
store[cacheKey] = {
|
|
4688
|
+
...store[cacheKey],
|
|
4689
|
+
...entry,
|
|
4690
|
+
local_saved_at: entry.local_saved_at || (/* @__PURE__ */ new Date()).toISOString()
|
|
4691
|
+
};
|
|
4692
|
+
writeStore(store);
|
|
4693
|
+
}
|
|
4694
|
+
function parseIsoMs(iso) {
|
|
4695
|
+
if (!iso)
|
|
4696
|
+
return 0;
|
|
4697
|
+
const t = Date.parse(iso);
|
|
4698
|
+
return Number.isNaN(t) ? 0 : t;
|
|
4699
|
+
}
|
|
4700
|
+
function shouldApplyServerProfileUpdate(serverUpdatedAt, cacheKey, force = false) {
|
|
4701
|
+
if (force)
|
|
4702
|
+
return true;
|
|
4703
|
+
const meta = getProfileMeta(cacheKey);
|
|
4704
|
+
if (!meta)
|
|
4705
|
+
return true;
|
|
4706
|
+
const serverMs = parseIsoMs(serverUpdatedAt);
|
|
4707
|
+
const knownServerMs = parseIsoMs(meta.server_updated_at);
|
|
4708
|
+
const localMs = parseIsoMs(meta.local_saved_at);
|
|
4709
|
+
if (localMs > serverMs && localMs >= knownServerMs) {
|
|
4710
|
+
return false;
|
|
4711
|
+
}
|
|
4712
|
+
if (knownServerMs > serverMs) {
|
|
4713
|
+
return false;
|
|
4714
|
+
}
|
|
4715
|
+
return true;
|
|
4716
|
+
}
|
|
4717
|
+
var fs2, os, path, CACHE_DIR, META_FILE;
|
|
4718
|
+
var init_profile_meta = __esm({
|
|
4719
|
+
"src/lib/profile-meta.ts"() {
|
|
4720
|
+
"use strict";
|
|
4721
|
+
fs2 = __toESM(require("fs"));
|
|
4722
|
+
os = __toESM(require("os"));
|
|
4723
|
+
path = __toESM(require("path"));
|
|
4724
|
+
CACHE_DIR = path.join(os.homedir(), ".hyv", "cache");
|
|
4725
|
+
META_FILE = path.join(CACHE_DIR, "profile-meta.json");
|
|
4726
|
+
}
|
|
4727
|
+
});
|
|
4728
|
+
|
|
4652
4729
|
// src/lib/config.ts
|
|
4653
4730
|
function validateApiBase(raw) {
|
|
4654
4731
|
const trimmed = raw.replace(/\/$/, "");
|
|
@@ -4725,21 +4802,21 @@ function toSafeProfileCacheKey(name) {
|
|
|
4725
4802
|
function profilePathForName(name) {
|
|
4726
4803
|
const safe = assertSafeProfileName(name);
|
|
4727
4804
|
ensureHyvDir();
|
|
4728
|
-
const profilePath =
|
|
4729
|
-
const profilesRoot =
|
|
4805
|
+
const profilePath = path2.resolve(PROFILES_DIR, `${safe}.md`);
|
|
4806
|
+
const profilesRoot = path2.resolve(PROFILES_DIR) + path2.sep;
|
|
4730
4807
|
if (!profilePath.startsWith(profilesRoot)) {
|
|
4731
4808
|
throw new Error("Invalid profile name");
|
|
4732
4809
|
}
|
|
4733
4810
|
return profilePath;
|
|
4734
4811
|
}
|
|
4735
4812
|
function ensureHyvDir() {
|
|
4736
|
-
const dirs = [HYV_DIR, PROFILES_DIR,
|
|
4813
|
+
const dirs = [HYV_DIR, PROFILES_DIR, CACHE_DIR2, QUEUE_DIR];
|
|
4737
4814
|
for (const dir of dirs) {
|
|
4738
|
-
if (!
|
|
4739
|
-
|
|
4815
|
+
if (!fs3.existsSync(dir)) {
|
|
4816
|
+
fs3.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
4740
4817
|
} else {
|
|
4741
4818
|
try {
|
|
4742
|
-
|
|
4819
|
+
fs3.chmodSync(dir, 448);
|
|
4743
4820
|
} catch {
|
|
4744
4821
|
}
|
|
4745
4822
|
}
|
|
@@ -4747,33 +4824,33 @@ function ensureHyvDir() {
|
|
|
4747
4824
|
}
|
|
4748
4825
|
function appendSecureLine(filePath, line, dir) {
|
|
4749
4826
|
if (dir) {
|
|
4750
|
-
if (!
|
|
4751
|
-
|
|
4827
|
+
if (!fs3.existsSync(dir))
|
|
4828
|
+
fs3.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
4752
4829
|
else {
|
|
4753
4830
|
try {
|
|
4754
|
-
|
|
4831
|
+
fs3.chmodSync(dir, 448);
|
|
4755
4832
|
} catch {
|
|
4756
4833
|
}
|
|
4757
4834
|
}
|
|
4758
4835
|
}
|
|
4759
|
-
if (!
|
|
4760
|
-
|
|
4836
|
+
if (!fs3.existsSync(filePath)) {
|
|
4837
|
+
fs3.writeFileSync(filePath, line, { mode: 384 });
|
|
4761
4838
|
return;
|
|
4762
4839
|
}
|
|
4763
4840
|
try {
|
|
4764
|
-
|
|
4841
|
+
fs3.chmodSync(filePath, 384);
|
|
4765
4842
|
} catch {
|
|
4766
4843
|
}
|
|
4767
|
-
|
|
4844
|
+
fs3.appendFileSync(filePath, line);
|
|
4768
4845
|
}
|
|
4769
4846
|
function isInitialized() {
|
|
4770
|
-
return
|
|
4847
|
+
return fs3.existsSync(AUTH_FILE);
|
|
4771
4848
|
}
|
|
4772
4849
|
function readAuth() {
|
|
4773
4850
|
try {
|
|
4774
|
-
if (!
|
|
4851
|
+
if (!fs3.existsSync(AUTH_FILE))
|
|
4775
4852
|
return null;
|
|
4776
|
-
const data =
|
|
4853
|
+
const data = fs3.readFileSync(AUTH_FILE, "utf-8");
|
|
4777
4854
|
return JSON.parse(data);
|
|
4778
4855
|
} catch {
|
|
4779
4856
|
return null;
|
|
@@ -4781,13 +4858,19 @@ function readAuth() {
|
|
|
4781
4858
|
}
|
|
4782
4859
|
function writeAuth(auth) {
|
|
4783
4860
|
ensureHyvDir();
|
|
4784
|
-
|
|
4861
|
+
if (fs3.existsSync(AUTH_FILE)) {
|
|
4862
|
+
try {
|
|
4863
|
+
fs3.copyFileSync(AUTH_FILE, `${AUTH_FILE}.hyv.bak`);
|
|
4864
|
+
} catch {
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
fs3.writeFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), { mode: 384 });
|
|
4785
4868
|
}
|
|
4786
4869
|
function readConfig() {
|
|
4787
4870
|
try {
|
|
4788
|
-
if (!
|
|
4871
|
+
if (!fs3.existsSync(CONFIG_FILE))
|
|
4789
4872
|
return {};
|
|
4790
|
-
const data =
|
|
4873
|
+
const data = fs3.readFileSync(CONFIG_FILE, "utf-8");
|
|
4791
4874
|
return JSON.parse(data);
|
|
4792
4875
|
} catch {
|
|
4793
4876
|
return {};
|
|
@@ -4795,7 +4878,7 @@ function readConfig() {
|
|
|
4795
4878
|
}
|
|
4796
4879
|
function writeConfig(config) {
|
|
4797
4880
|
ensureHyvDir();
|
|
4798
|
-
|
|
4881
|
+
fs3.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 });
|
|
4799
4882
|
}
|
|
4800
4883
|
function getToken() {
|
|
4801
4884
|
const auth = readAuth();
|
|
@@ -4811,9 +4894,9 @@ function getToken() {
|
|
|
4811
4894
|
}
|
|
4812
4895
|
function listCachedProfiles() {
|
|
4813
4896
|
try {
|
|
4814
|
-
if (!
|
|
4897
|
+
if (!fs3.existsSync(PROFILES_DIR))
|
|
4815
4898
|
return [];
|
|
4816
|
-
return
|
|
4899
|
+
return fs3.readdirSync(PROFILES_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
|
|
4817
4900
|
} catch {
|
|
4818
4901
|
return [];
|
|
4819
4902
|
}
|
|
@@ -4821,9 +4904,9 @@ function listCachedProfiles() {
|
|
|
4821
4904
|
function readCachedProfile(name) {
|
|
4822
4905
|
const profilePath = profilePathForName(name);
|
|
4823
4906
|
try {
|
|
4824
|
-
if (!
|
|
4907
|
+
if (!fs3.existsSync(profilePath))
|
|
4825
4908
|
return null;
|
|
4826
|
-
return
|
|
4909
|
+
return fs3.readFileSync(profilePath, "utf-8");
|
|
4827
4910
|
} catch (err) {
|
|
4828
4911
|
if (err.message?.includes("Invalid profile name"))
|
|
4829
4912
|
throw err;
|
|
@@ -4832,19 +4915,22 @@ function readCachedProfile(name) {
|
|
|
4832
4915
|
}
|
|
4833
4916
|
function writeCachedProfile(name, content) {
|
|
4834
4917
|
const profilePath = profilePathForName(name);
|
|
4835
|
-
const existing =
|
|
4918
|
+
const existing = fs3.existsSync(profilePath) ? fs3.readFileSync(profilePath, "utf-8") : null;
|
|
4836
4919
|
const result = safeWriteProfileFile(profilePath, content, existing);
|
|
4837
4920
|
if (!result.written && result.reason === "empty-would-erase") {
|
|
4838
4921
|
throw new Error("Refusing to replace profile with empty content");
|
|
4839
4922
|
}
|
|
4923
|
+
if (result.written) {
|
|
4924
|
+
setProfileMeta(name, { local_saved_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
4925
|
+
}
|
|
4840
4926
|
}
|
|
4841
4927
|
function getQueuedSignals() {
|
|
4842
4928
|
try {
|
|
4843
|
-
if (!
|
|
4929
|
+
if (!fs3.existsSync(QUEUE_DIR))
|
|
4844
4930
|
return [];
|
|
4845
|
-
const files =
|
|
4931
|
+
const files = fs3.readdirSync(QUEUE_DIR).filter((f) => f.endsWith(".json"));
|
|
4846
4932
|
return files.map((f) => {
|
|
4847
|
-
const data =
|
|
4933
|
+
const data = fs3.readFileSync(path2.join(QUEUE_DIR, f), "utf-8");
|
|
4848
4934
|
return JSON.parse(data);
|
|
4849
4935
|
});
|
|
4850
4936
|
} catch {
|
|
@@ -4854,38 +4940,39 @@ function getQueuedSignals() {
|
|
|
4854
4940
|
function queueSignal(signal) {
|
|
4855
4941
|
ensureHyvDir();
|
|
4856
4942
|
const id = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
4857
|
-
const filePath =
|
|
4858
|
-
|
|
4943
|
+
const filePath = path2.join(QUEUE_DIR, `${id}.json`);
|
|
4944
|
+
fs3.writeFileSync(filePath, JSON.stringify(signal, null, 2), { mode: 384 });
|
|
4859
4945
|
}
|
|
4860
4946
|
function saveLastEditSession(session) {
|
|
4861
4947
|
ensureHyvDir();
|
|
4862
4948
|
const data = { ...session, saved_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4863
|
-
|
|
4949
|
+
fs3.writeFileSync(LAST_SESSION_FILE, JSON.stringify(data, null, 2), { mode: 384 });
|
|
4864
4950
|
}
|
|
4865
4951
|
function readLastEditSession() {
|
|
4866
4952
|
try {
|
|
4867
|
-
if (!
|
|
4953
|
+
if (!fs3.existsSync(LAST_SESSION_FILE))
|
|
4868
4954
|
return null;
|
|
4869
|
-
return JSON.parse(
|
|
4955
|
+
return JSON.parse(fs3.readFileSync(LAST_SESSION_FILE, "utf-8"));
|
|
4870
4956
|
} catch {
|
|
4871
4957
|
return null;
|
|
4872
4958
|
}
|
|
4873
4959
|
}
|
|
4874
|
-
var
|
|
4960
|
+
var fs3, path2, os2, HYV_DIR, AUTH_FILE, CONFIG_FILE, PROFILES_DIR, CACHE_DIR2, QUEUE_DIR, LAST_SESSION_FILE, ALLOWED_API_HOSTS, ALLOWED_OAUTH_HOSTS, API_BASE, PROFILE_NAME_RE;
|
|
4875
4961
|
var init_config = __esm({
|
|
4876
4962
|
"src/lib/config.ts"() {
|
|
4877
4963
|
"use strict";
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4964
|
+
fs3 = __toESM(require("fs"));
|
|
4965
|
+
path2 = __toESM(require("path"));
|
|
4966
|
+
os2 = __toESM(require("os"));
|
|
4881
4967
|
init_data_safety();
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4968
|
+
init_profile_meta();
|
|
4969
|
+
HYV_DIR = path2.join(os2.homedir(), ".hyv");
|
|
4970
|
+
AUTH_FILE = path2.join(HYV_DIR, "auth.json");
|
|
4971
|
+
CONFIG_FILE = path2.join(HYV_DIR, "config.json");
|
|
4972
|
+
PROFILES_DIR = path2.join(HYV_DIR, "profiles");
|
|
4973
|
+
CACHE_DIR2 = path2.join(HYV_DIR, "cache");
|
|
4974
|
+
QUEUE_DIR = path2.join(HYV_DIR, "queue");
|
|
4975
|
+
LAST_SESSION_FILE = path2.join(HYV_DIR, "last-session.json");
|
|
4889
4976
|
ALLOWED_API_HOSTS = /* @__PURE__ */ new Set([
|
|
4890
4977
|
"holdyourvoice.com",
|
|
4891
4978
|
"www.holdyourvoice.com",
|
|
@@ -4903,11 +4990,11 @@ var init_config = __esm({
|
|
|
4903
4990
|
var require_is_docker = __commonJS({
|
|
4904
4991
|
"node_modules/is-docker/index.js"(exports2, module2) {
|
|
4905
4992
|
"use strict";
|
|
4906
|
-
var
|
|
4993
|
+
var fs30 = require("fs");
|
|
4907
4994
|
var isDocker;
|
|
4908
4995
|
function hasDockerEnv() {
|
|
4909
4996
|
try {
|
|
4910
|
-
|
|
4997
|
+
fs30.statSync("/.dockerenv");
|
|
4911
4998
|
return true;
|
|
4912
4999
|
} catch (_2) {
|
|
4913
5000
|
return false;
|
|
@@ -4915,7 +5002,7 @@ var require_is_docker = __commonJS({
|
|
|
4915
5002
|
}
|
|
4916
5003
|
function hasDockerCGroup() {
|
|
4917
5004
|
try {
|
|
4918
|
-
return
|
|
5005
|
+
return fs30.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
4919
5006
|
} catch (_2) {
|
|
4920
5007
|
return false;
|
|
4921
5008
|
}
|
|
@@ -4933,21 +5020,21 @@ var require_is_docker = __commonJS({
|
|
|
4933
5020
|
var require_is_wsl = __commonJS({
|
|
4934
5021
|
"node_modules/is-wsl/index.js"(exports2, module2) {
|
|
4935
5022
|
"use strict";
|
|
4936
|
-
var
|
|
4937
|
-
var
|
|
5023
|
+
var os13 = require("os");
|
|
5024
|
+
var fs30 = require("fs");
|
|
4938
5025
|
var isDocker = require_is_docker();
|
|
4939
5026
|
var isWsl = () => {
|
|
4940
5027
|
if (process.platform !== "linux") {
|
|
4941
5028
|
return false;
|
|
4942
5029
|
}
|
|
4943
|
-
if (
|
|
5030
|
+
if (os13.release().toLowerCase().includes("microsoft")) {
|
|
4944
5031
|
if (isDocker()) {
|
|
4945
5032
|
return false;
|
|
4946
5033
|
}
|
|
4947
5034
|
return true;
|
|
4948
5035
|
}
|
|
4949
5036
|
try {
|
|
4950
|
-
return
|
|
5037
|
+
return fs30.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isDocker() : false;
|
|
4951
5038
|
} catch (_2) {
|
|
4952
5039
|
return false;
|
|
4953
5040
|
}
|
|
@@ -4986,17 +5073,17 @@ var require_define_lazy_prop = __commonJS({
|
|
|
4986
5073
|
// node_modules/open/index.js
|
|
4987
5074
|
var require_open = __commonJS({
|
|
4988
5075
|
"node_modules/open/index.js"(exports2, module2) {
|
|
4989
|
-
var
|
|
5076
|
+
var path27 = require("path");
|
|
4990
5077
|
var childProcess = require("child_process");
|
|
4991
|
-
var { promises:
|
|
5078
|
+
var { promises: fs30, constants: fsConstants } = require("fs");
|
|
4992
5079
|
var isWsl = require_is_wsl();
|
|
4993
5080
|
var isDocker = require_is_docker();
|
|
4994
5081
|
var defineLazyProperty = require_define_lazy_prop();
|
|
4995
|
-
var localXdgOpenPath =
|
|
5082
|
+
var localXdgOpenPath = path27.join(__dirname, "xdg-open");
|
|
4996
5083
|
var { platform, arch } = process;
|
|
4997
5084
|
var hasContainerEnv = () => {
|
|
4998
5085
|
try {
|
|
4999
|
-
|
|
5086
|
+
fs30.statSync("/run/.containerenv");
|
|
5000
5087
|
return true;
|
|
5001
5088
|
} catch {
|
|
5002
5089
|
return false;
|
|
@@ -5019,14 +5106,14 @@ var require_open = __commonJS({
|
|
|
5019
5106
|
const configFilePath = "/etc/wsl.conf";
|
|
5020
5107
|
let isConfigFileExists = false;
|
|
5021
5108
|
try {
|
|
5022
|
-
await
|
|
5109
|
+
await fs30.access(configFilePath, fsConstants.F_OK);
|
|
5023
5110
|
isConfigFileExists = true;
|
|
5024
5111
|
} catch {
|
|
5025
5112
|
}
|
|
5026
5113
|
if (!isConfigFileExists) {
|
|
5027
5114
|
return defaultMountPoint;
|
|
5028
5115
|
}
|
|
5029
|
-
const configContent = await
|
|
5116
|
+
const configContent = await fs30.readFile(configFilePath, { encoding: "utf8" });
|
|
5030
5117
|
const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
|
|
5031
5118
|
if (!configMountPoint) {
|
|
5032
5119
|
return defaultMountPoint;
|
|
@@ -5126,7 +5213,7 @@ var require_open = __commonJS({
|
|
|
5126
5213
|
const isBundled = !__dirname || __dirname === "/";
|
|
5127
5214
|
let exeLocalXdgOpen = false;
|
|
5128
5215
|
try {
|
|
5129
|
-
await
|
|
5216
|
+
await fs30.access(localXdgOpenPath, fsConstants.X_OK);
|
|
5130
5217
|
exeLocalXdgOpen = true;
|
|
5131
5218
|
} catch {
|
|
5132
5219
|
}
|
|
@@ -5298,7 +5385,7 @@ var init_free_paid = __esm({
|
|
|
5298
5385
|
"Rich profile-aware rewrite prompts (hyv rewrite)",
|
|
5299
5386
|
"Hybrid server analysis (hyv scan --server, MCP hyv_analyze)",
|
|
5300
5387
|
"Multiple profiles + team voices (Team plan)",
|
|
5301
|
-
"Dashboard at holdyourvoice.com/
|
|
5388
|
+
"Dashboard at holdyourvoice.com/dashboard"
|
|
5302
5389
|
];
|
|
5303
5390
|
FREE_WEB_TOOLS = [
|
|
5304
5391
|
{ name: "All free tools", url: "https://holdyourvoice.com/tools" },
|
|
@@ -5319,27 +5406,27 @@ var init_free_paid = __esm({
|
|
|
5319
5406
|
];
|
|
5320
5407
|
COMMUNITY_URL = "https://holdyourvoice.com/community";
|
|
5321
5408
|
PRICING_URL = "https://holdyourvoice.com/#pricing";
|
|
5322
|
-
DASHBOARD_BILLING_URL = "https://holdyourvoice.com/
|
|
5409
|
+
DASHBOARD_BILLING_URL = "https://holdyourvoice.com/dashboard?tab=billing";
|
|
5323
5410
|
}
|
|
5324
5411
|
});
|
|
5325
5412
|
|
|
5326
5413
|
// src/lib/version.ts
|
|
5327
5414
|
function pkgRoot() {
|
|
5328
5415
|
const candidates = [
|
|
5329
|
-
|
|
5416
|
+
path3.resolve(__dirname, ".."),
|
|
5330
5417
|
// dist/ or src/lib/ → cli/
|
|
5331
|
-
|
|
5418
|
+
path3.resolve(__dirname, "..", "..")
|
|
5332
5419
|
// src/lib/ → cli/
|
|
5333
5420
|
];
|
|
5334
5421
|
for (const root of candidates) {
|
|
5335
|
-
if (
|
|
5422
|
+
if (fs4.existsSync(path3.join(root, "package.json")))
|
|
5336
5423
|
return root;
|
|
5337
5424
|
}
|
|
5338
|
-
return
|
|
5425
|
+
return path3.resolve(__dirname, "..");
|
|
5339
5426
|
}
|
|
5340
5427
|
function getCliVersion() {
|
|
5341
5428
|
try {
|
|
5342
|
-
const pkg = JSON.parse(
|
|
5429
|
+
const pkg = JSON.parse(fs4.readFileSync(path3.join(PKG_ROOT, "package.json"), "utf-8"));
|
|
5343
5430
|
return pkg.version || "unknown";
|
|
5344
5431
|
} catch {
|
|
5345
5432
|
return "unknown";
|
|
@@ -5347,8 +5434,8 @@ function getCliVersion() {
|
|
|
5347
5434
|
}
|
|
5348
5435
|
function getRulesVersion() {
|
|
5349
5436
|
try {
|
|
5350
|
-
if (
|
|
5351
|
-
return JSON.parse(
|
|
5437
|
+
if (fs4.existsSync(RULES_MANIFEST)) {
|
|
5438
|
+
return JSON.parse(fs4.readFileSync(RULES_MANIFEST, "utf-8")).version || "unknown";
|
|
5352
5439
|
}
|
|
5353
5440
|
} catch {
|
|
5354
5441
|
}
|
|
@@ -5386,15 +5473,15 @@ function fetchLatestNpmVersion(timeoutMs = 8e3) {
|
|
|
5386
5473
|
);
|
|
5387
5474
|
});
|
|
5388
5475
|
}
|
|
5389
|
-
var
|
|
5476
|
+
var fs4, path3, import_child_process, PKG_ROOT, RULES_MANIFEST;
|
|
5390
5477
|
var init_version = __esm({
|
|
5391
5478
|
"src/lib/version.ts"() {
|
|
5392
5479
|
"use strict";
|
|
5393
|
-
|
|
5394
|
-
|
|
5480
|
+
fs4 = __toESM(require("fs"));
|
|
5481
|
+
path3 = __toESM(require("path"));
|
|
5395
5482
|
import_child_process = require("child_process");
|
|
5396
5483
|
PKG_ROOT = pkgRoot();
|
|
5397
|
-
RULES_MANIFEST =
|
|
5484
|
+
RULES_MANIFEST = path3.join(PKG_ROOT, "assets", "detection-rules.json");
|
|
5398
5485
|
}
|
|
5399
5486
|
});
|
|
5400
5487
|
|
|
@@ -5623,7 +5710,7 @@ async function authenticateWithBrowser() {
|
|
|
5623
5710
|
return authData;
|
|
5624
5711
|
}
|
|
5625
5712
|
async function openAuthenticatedDashboard(opts = {}) {
|
|
5626
|
-
const nextPath = opts.next || "/
|
|
5713
|
+
const nextPath = opts.next || "/dashboard?tab=billing";
|
|
5627
5714
|
try {
|
|
5628
5715
|
const response = await authenticatedRequest(cliApiUrl("/cli/auth/web-handoff"), {
|
|
5629
5716
|
method: "POST",
|
|
@@ -5638,7 +5725,7 @@ async function openAuthenticatedDashboard(opts = {}) {
|
|
|
5638
5725
|
}
|
|
5639
5726
|
} catch {
|
|
5640
5727
|
}
|
|
5641
|
-
const billingUrl = nextPath === "/app/billing" ? DASHBOARD_BILLING_URL : assertSafeOpenUrl(`https://holdyourvoice.com${nextPath}`);
|
|
5728
|
+
const billingUrl = nextPath === "/dashboard?tab=billing" || nextPath === "/app/billing" ? DASHBOARD_BILLING_URL : assertSafeOpenUrl(`https://holdyourvoice.com${nextPath}`);
|
|
5642
5729
|
await (0, import_open.default)(billingUrl);
|
|
5643
5730
|
}
|
|
5644
5731
|
async function refreshToken(tokenOverride) {
|
|
@@ -5754,15 +5841,15 @@ function recordEvent(event, meta) {
|
|
|
5754
5841
|
} catch {
|
|
5755
5842
|
}
|
|
5756
5843
|
}
|
|
5757
|
-
var
|
|
5844
|
+
var path4, os3, TELEMETRY_DIR, TELEMETRY_FILE;
|
|
5758
5845
|
var init_telemetry = __esm({
|
|
5759
5846
|
"src/lib/telemetry.ts"() {
|
|
5760
5847
|
"use strict";
|
|
5761
|
-
|
|
5762
|
-
|
|
5848
|
+
path4 = __toESM(require("path"));
|
|
5849
|
+
os3 = __toESM(require("os"));
|
|
5763
5850
|
init_config();
|
|
5764
|
-
TELEMETRY_DIR =
|
|
5765
|
-
TELEMETRY_FILE =
|
|
5851
|
+
TELEMETRY_DIR = path4.join(os3.homedir(), ".hyv", "telemetry");
|
|
5852
|
+
TELEMETRY_FILE = path4.join(TELEMETRY_DIR, "events.jsonl");
|
|
5766
5853
|
}
|
|
5767
5854
|
});
|
|
5768
5855
|
|
|
@@ -5773,11 +5860,11 @@ __export(api_exports, {
|
|
|
5773
5860
|
apiPost: () => apiPost,
|
|
5774
5861
|
requireSubscription: () => requireSubscription
|
|
5775
5862
|
});
|
|
5776
|
-
async function request2(method,
|
|
5863
|
+
async function request2(method, path27, body) {
|
|
5777
5864
|
const token = await getValidToken();
|
|
5778
5865
|
if (!token)
|
|
5779
5866
|
throw new Error("you're not signed in yet. run: hyv init");
|
|
5780
|
-
const url = `${API_BASE}${
|
|
5867
|
+
const url = `${API_BASE}${path27}`;
|
|
5781
5868
|
const opts = {
|
|
5782
5869
|
method,
|
|
5783
5870
|
headers: {
|
|
@@ -5796,17 +5883,17 @@ async function request2(method, path26, body) {
|
|
|
5796
5883
|
if (res.status === 401)
|
|
5797
5884
|
throw new Error("your session expired. run: hyv init to sign in again.");
|
|
5798
5885
|
if (res.status === 403)
|
|
5799
|
-
throw new Error("you don't have access to this feature. check your plan at holdyourvoice.com/
|
|
5886
|
+
throw new Error("you don't have access to this feature. check your plan at holdyourvoice.com/dashboard?tab=billing");
|
|
5800
5887
|
if (!res.ok) {
|
|
5801
5888
|
throw new Error(`something went wrong (${res.status}). try again or contact support.`);
|
|
5802
5889
|
}
|
|
5803
5890
|
return res.json();
|
|
5804
5891
|
}
|
|
5805
|
-
function apiGet(
|
|
5806
|
-
return request2("GET",
|
|
5892
|
+
function apiGet(path27) {
|
|
5893
|
+
return request2("GET", path27);
|
|
5807
5894
|
}
|
|
5808
|
-
function apiPost(
|
|
5809
|
-
return request2("POST",
|
|
5895
|
+
function apiPost(path27, body) {
|
|
5896
|
+
return request2("POST", path27, body);
|
|
5810
5897
|
}
|
|
5811
5898
|
async function requireSubscription() {
|
|
5812
5899
|
const { requirePaidFeature: requirePaidFeature2 } = await Promise.resolve().then(() => (init_access(), access_exports));
|
|
@@ -5990,7 +6077,7 @@ async function fetchAndCache(slug) {
|
|
|
5990
6077
|
};
|
|
5991
6078
|
const entry = { data: profile, timestamp: Date.now(), version: 1 };
|
|
5992
6079
|
memoryCache.set(slug, entry);
|
|
5993
|
-
saveToDiskCache(slug, entry);
|
|
6080
|
+
saveToDiskCache(slug, entry, profile.updated_at);
|
|
5994
6081
|
return profile;
|
|
5995
6082
|
} catch (err) {
|
|
5996
6083
|
const fallback = loadFromDiskCache(slug);
|
|
@@ -6011,14 +6098,14 @@ async function refreshInBackground(slug) {
|
|
|
6011
6098
|
}
|
|
6012
6099
|
}
|
|
6013
6100
|
function getDiskCachePath(slug) {
|
|
6014
|
-
return
|
|
6101
|
+
return path5.join(DISK_CACHE_DIR, `${slug.replace(/[^a-z0-9-]/gi, "_")}.json`);
|
|
6015
6102
|
}
|
|
6016
6103
|
function loadFromDiskCache(slug) {
|
|
6017
6104
|
try {
|
|
6018
6105
|
const cachePath = getDiskCachePath(slug);
|
|
6019
|
-
if (!
|
|
6106
|
+
if (!fs5.existsSync(cachePath))
|
|
6020
6107
|
return null;
|
|
6021
|
-
const content =
|
|
6108
|
+
const content = fs5.readFileSync(cachePath, "utf-8");
|
|
6022
6109
|
const entry = JSON.parse(content);
|
|
6023
6110
|
if (!entry.data || !entry.timestamp)
|
|
6024
6111
|
return null;
|
|
@@ -6027,12 +6114,24 @@ function loadFromDiskCache(slug) {
|
|
|
6027
6114
|
return null;
|
|
6028
6115
|
}
|
|
6029
6116
|
}
|
|
6030
|
-
function saveToDiskCache(slug, entry) {
|
|
6117
|
+
function saveToDiskCache(slug, entry, serverUpdatedAt) {
|
|
6031
6118
|
try {
|
|
6032
|
-
if (!
|
|
6033
|
-
|
|
6119
|
+
if (!fs5.existsSync(DISK_CACHE_DIR)) {
|
|
6120
|
+
fs5.mkdirSync(DISK_CACHE_DIR, { recursive: true });
|
|
6121
|
+
}
|
|
6122
|
+
const cachePath = getDiskCachePath(slug);
|
|
6123
|
+
const existing = fs5.existsSync(cachePath) ? fs5.readFileSync(cachePath, "utf-8") : null;
|
|
6124
|
+
const incoming = JSON.stringify(entry);
|
|
6125
|
+
const localUpdated = getProfileMeta(slug)?.server_updated_at;
|
|
6126
|
+
const serverMs = parseIsoMs(serverUpdatedAt || entry.data.updated_at);
|
|
6127
|
+
const localMs = parseIsoMs(localUpdated);
|
|
6128
|
+
if (existing && localMs > serverMs && serverMs > 0) {
|
|
6129
|
+
return;
|
|
6130
|
+
}
|
|
6131
|
+
const result = safeWriteJsonFile(cachePath, incoming, existing);
|
|
6132
|
+
if (result.written && serverUpdatedAt) {
|
|
6133
|
+
setProfileMeta(slug, { server_updated_at: serverUpdatedAt });
|
|
6034
6134
|
}
|
|
6035
|
-
fs4.writeFileSync(getDiskCachePath(slug), JSON.stringify(entry), "utf-8");
|
|
6036
6135
|
} catch {
|
|
6037
6136
|
}
|
|
6038
6137
|
}
|
|
@@ -6050,18 +6149,20 @@ function buildMinimalProfile(slug, body) {
|
|
|
6050
6149
|
cadence: {}
|
|
6051
6150
|
};
|
|
6052
6151
|
}
|
|
6053
|
-
var
|
|
6152
|
+
var fs5, path5, os4, CACHE_TTL, memoryCache, DISK_CACHE_DIR;
|
|
6054
6153
|
var init_profile = __esm({
|
|
6055
6154
|
"src/lib/profile.ts"() {
|
|
6056
6155
|
"use strict";
|
|
6057
6156
|
init_api();
|
|
6058
6157
|
init_config();
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6158
|
+
init_data_safety();
|
|
6159
|
+
init_profile_meta();
|
|
6160
|
+
fs5 = __toESM(require("fs"));
|
|
6161
|
+
path5 = __toESM(require("path"));
|
|
6162
|
+
os4 = __toESM(require("os"));
|
|
6062
6163
|
CACHE_TTL = 5 * 60 * 1e3;
|
|
6063
6164
|
memoryCache = /* @__PURE__ */ new Map();
|
|
6064
|
-
DISK_CACHE_DIR =
|
|
6165
|
+
DISK_CACHE_DIR = path5.join(os4.homedir(), ".hyv", "cache", "profiles");
|
|
6065
6166
|
}
|
|
6066
6167
|
});
|
|
6067
6168
|
|
|
@@ -6076,14 +6177,14 @@ __export(local_profile_exports, {
|
|
|
6076
6177
|
loadProfileFromDiskCache: () => loadProfileFromDiskCache
|
|
6077
6178
|
});
|
|
6078
6179
|
function cachePathForSlug(slug) {
|
|
6079
|
-
return
|
|
6180
|
+
return path6.join(DISK_CACHE_DIR2, `${slug.replace(/[^a-z0-9-]/gi, "_")}.json`);
|
|
6080
6181
|
}
|
|
6081
6182
|
function loadProfileFromDiskCache(slug) {
|
|
6082
6183
|
try {
|
|
6083
6184
|
const cachePath = cachePathForSlug(slug);
|
|
6084
|
-
if (!
|
|
6185
|
+
if (!fs6.existsSync(cachePath))
|
|
6085
6186
|
return void 0;
|
|
6086
|
-
const entry = JSON.parse(
|
|
6187
|
+
const entry = JSON.parse(fs6.readFileSync(cachePath, "utf-8"));
|
|
6087
6188
|
if (entry?.data?.body)
|
|
6088
6189
|
return entry.data;
|
|
6089
6190
|
} catch {
|
|
@@ -6107,9 +6208,9 @@ function profileFromMarkdown(slug, body) {
|
|
|
6107
6208
|
function getProfileCacheAge(slug) {
|
|
6108
6209
|
try {
|
|
6109
6210
|
const cachePath = cachePathForSlug(slug);
|
|
6110
|
-
if (!
|
|
6211
|
+
if (!fs6.existsSync(cachePath))
|
|
6111
6212
|
return null;
|
|
6112
|
-
const entry = JSON.parse(
|
|
6213
|
+
const entry = JSON.parse(fs6.readFileSync(cachePath, "utf-8"));
|
|
6113
6214
|
return entry.timestamp || null;
|
|
6114
6215
|
} catch {
|
|
6115
6216
|
return null;
|
|
@@ -6117,9 +6218,9 @@ function getProfileCacheAge(slug) {
|
|
|
6117
6218
|
}
|
|
6118
6219
|
function listDiskCachedProfiles() {
|
|
6119
6220
|
try {
|
|
6120
|
-
if (!
|
|
6221
|
+
if (!fs6.existsSync(DISK_CACHE_DIR2))
|
|
6121
6222
|
return [];
|
|
6122
|
-
return
|
|
6223
|
+
return fs6.readdirSync(DISK_CACHE_DIR2).filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
|
|
6123
6224
|
} catch {
|
|
6124
6225
|
return [];
|
|
6125
6226
|
}
|
|
@@ -6176,17 +6277,17 @@ function hasRichProfile(profile) {
|
|
|
6176
6277
|
return false;
|
|
6177
6278
|
return (profile.never_list?.length || 0) > 0 || (profile.learned_patterns?.length || 0) > 0 || (profile.drift_snapshot?.length || 0) > 0 || (profile.voice_rules?.length || 0) > 0;
|
|
6178
6279
|
}
|
|
6179
|
-
var
|
|
6280
|
+
var fs6, path6, os5, DISK_CACHE_DIR2;
|
|
6180
6281
|
var init_local_profile = __esm({
|
|
6181
6282
|
"src/lib/local-profile.ts"() {
|
|
6182
6283
|
"use strict";
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6284
|
+
fs6 = __toESM(require("fs"));
|
|
6285
|
+
path6 = __toESM(require("path"));
|
|
6286
|
+
os5 = __toESM(require("os"));
|
|
6186
6287
|
init_config();
|
|
6187
6288
|
init_config();
|
|
6188
6289
|
init_profile();
|
|
6189
|
-
DISK_CACHE_DIR2 =
|
|
6290
|
+
DISK_CACHE_DIR2 = path6.join(os5.homedir(), ".hyv", "cache", "profiles");
|
|
6190
6291
|
}
|
|
6191
6292
|
});
|
|
6192
6293
|
|
|
@@ -6276,24 +6377,24 @@ var init_profile_parse = __esm({
|
|
|
6276
6377
|
|
|
6277
6378
|
// src/lib/rules-loader.ts
|
|
6278
6379
|
function loadSupplementalPatterns() {
|
|
6279
|
-
const p =
|
|
6380
|
+
const p = path9.join(CACHE_DIR2, "supplemental-rules.json");
|
|
6280
6381
|
try {
|
|
6281
|
-
if (!
|
|
6382
|
+
if (!fs9.existsSync(p))
|
|
6282
6383
|
return [];
|
|
6283
|
-
const data = JSON.parse(
|
|
6384
|
+
const data = JSON.parse(fs9.readFileSync(p, "utf-8"));
|
|
6284
6385
|
return Array.isArray(data.patterns) ? data.patterns : [];
|
|
6285
6386
|
} catch {
|
|
6286
6387
|
return [];
|
|
6287
6388
|
}
|
|
6288
6389
|
}
|
|
6289
|
-
var
|
|
6390
|
+
var fs9, path9, BUNDLED_MANIFEST;
|
|
6290
6391
|
var init_rules_loader = __esm({
|
|
6291
6392
|
"src/lib/rules-loader.ts"() {
|
|
6292
6393
|
"use strict";
|
|
6293
|
-
|
|
6294
|
-
|
|
6394
|
+
fs9 = __toESM(require("fs"));
|
|
6395
|
+
path9 = __toESM(require("path"));
|
|
6295
6396
|
init_config();
|
|
6296
|
-
BUNDLED_MANIFEST =
|
|
6397
|
+
BUNDLED_MANIFEST = path9.resolve(__dirname, "..", "..", "assets", "detection-rules.json");
|
|
6297
6398
|
}
|
|
6298
6399
|
});
|
|
6299
6400
|
|
|
@@ -7325,10 +7426,10 @@ function Ht(n7) {
|
|
|
7325
7426
|
return isNaN(n7) ? n7.charCodeAt(0) : parseInt(n7, 10);
|
|
7326
7427
|
}
|
|
7327
7428
|
function ps(n7) {
|
|
7328
|
-
return n7.replace(as, fe).replace(ls, ue).replace(cs, qt).replace(
|
|
7429
|
+
return n7.replace(as, fe).replace(ls, ue).replace(cs, qt).replace(fs10, de).replace(us, pe);
|
|
7329
7430
|
}
|
|
7330
7431
|
function ms(n7) {
|
|
7331
|
-
return n7.replace(is, "\\").replace(rs, "{").replace(ns, "}").replace(
|
|
7432
|
+
return n7.replace(is, "\\").replace(rs, "{").replace(ns, "}").replace(os6, ",").replace(hs, ".");
|
|
7332
7433
|
}
|
|
7333
7434
|
function me(n7) {
|
|
7334
7435
|
if (!n7)
|
|
@@ -7428,7 +7529,7 @@ function Ut(n7, t = {}) {
|
|
|
7428
7529
|
function es(n7, t = {}) {
|
|
7429
7530
|
return new I(n7, t).iterate();
|
|
7430
7531
|
}
|
|
7431
|
-
var import_node_url, import_node_path, import_node_url2, import_fs, xi, import_promises, import_node_events, import_node_stream, import_node_string_decoder, Gt, ce, ss, fe, ue, qt, de, pe, is, rs, ns,
|
|
7532
|
+
var import_node_url, import_node_path, import_node_url2, import_fs, xi, import_promises, import_node_events, import_node_stream, import_node_string_decoder, Gt, ce, ss, fe, ue, qt, de, pe, is, rs, ns, os6, hs, as, ls, cs, fs10, us, ds, at, Ss, lt, Es, we, ye, W, xs, be, vs, Ct, Cs, Ts, As, ks, Kt, Se, Ee, Q, tt, O, Rs, Os, Fs, Ds, Ms, Ns, _s, Ls, Ws, Ps, js, Is, zs, Bs, Us, $s, Gs, Hs, Ce, Te, Ae, xe, qs, A, Ks, Vs, Ys, Xs, Js, N, Zs, ke, Qs, ti, ve, ei, D, si, Oe, Vt, Fe, At, Re, ii, q, De, Tt, ri, ft, Ne, oi, hi, ai, G, H, K, kt, ut, Rt, _e, Ot, Le, P, et, v, dt, st, C, F, T, Yt, Ft, k, x, Xt, Jt, We, Zt, B, Qt, Dt, pt, Y, M, mt, li, ci, fi, ui, Mt, te, di, pi, V, vi, wt, Ue, $e, Ri, Oi, L, Ge, He, U, qe, Ke, X, Ve, _, gt, se, je, yt, j, Nt, Lt, Ie, Fi, ie, ze, bt, Be, _t, Wt, ne, Ye, R, Pt, jt, It, it, rt, St, Cr, Xe, Di, Mi, Ni, nt, _i, ot, oe, he, ae, Et, Li, zt, xt, vt, Pi, I, le, ji, Ii, zi, Bi, Ui, Ze;
|
|
7432
7533
|
var init_index_min = __esm({
|
|
7433
7534
|
"node_modules/glob/dist/esm/index.min.js"() {
|
|
7434
7535
|
import_node_url = require("node:url");
|
|
@@ -7475,12 +7576,12 @@ var init_index_min = __esm({
|
|
|
7475
7576
|
is = new RegExp(fe, "g");
|
|
7476
7577
|
rs = new RegExp(ue, "g");
|
|
7477
7578
|
ns = new RegExp(qt, "g");
|
|
7478
|
-
|
|
7579
|
+
os6 = new RegExp(de, "g");
|
|
7479
7580
|
hs = new RegExp(pe, "g");
|
|
7480
7581
|
as = /\\\\/g;
|
|
7481
7582
|
ls = /\\{/g;
|
|
7482
7583
|
cs = /\\}/g;
|
|
7483
|
-
|
|
7584
|
+
fs10 = /\\,/g;
|
|
7484
7585
|
us = /\\./g;
|
|
7485
7586
|
ds = 1e5;
|
|
7486
7587
|
at = (n7) => {
|
|
@@ -10626,7 +10727,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s))
|
|
|
10626
10727
|
|
|
10627
10728
|
// src/lib/document-text.ts
|
|
10628
10729
|
function isSupportedDocument(filePath) {
|
|
10629
|
-
return SUPPORTED_EXTENSIONS.has(
|
|
10730
|
+
return SUPPORTED_EXTENSIONS.has(path10.extname(filePath).toLowerCase());
|
|
10630
10731
|
}
|
|
10631
10732
|
function stripHtml(html) {
|
|
10632
10733
|
return html.replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<br\s*\/?>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<[^>]+>/g, " ").replace(/ /gi, " ").replace(/&/gi, "&").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'/gi, "'").replace(/\s+\n/g, "\n").replace(/[ \t]+/g, " ").replace(/\n{3,}/g, "\n\n").trim();
|
|
@@ -10715,7 +10816,7 @@ function extractPdf(filePath) {
|
|
|
10715
10816
|
if (out.trim())
|
|
10716
10817
|
return out.trim();
|
|
10717
10818
|
}
|
|
10718
|
-
const raw = extractPdfRaw(
|
|
10819
|
+
const raw = extractPdfRaw(fs11.readFileSync(filePath));
|
|
10719
10820
|
if (raw.trim().length > 20)
|
|
10720
10821
|
return raw;
|
|
10721
10822
|
throw new Error("could not extract text from .pdf \u2014 try pasting the draft instead");
|
|
@@ -10737,23 +10838,23 @@ function extractSkillArchive(filePath) {
|
|
|
10737
10838
|
return parts.join("\n\n");
|
|
10738
10839
|
}
|
|
10739
10840
|
function extractTextFromFile(filePath) {
|
|
10740
|
-
const resolved =
|
|
10741
|
-
if (!
|
|
10841
|
+
const resolved = path10.resolve(filePath);
|
|
10842
|
+
if (!fs11.existsSync(resolved)) {
|
|
10742
10843
|
throw new Error(`file not found: ${resolved}`);
|
|
10743
10844
|
}
|
|
10744
|
-
const stat =
|
|
10845
|
+
const stat = fs11.statSync(resolved);
|
|
10745
10846
|
if (!stat.isFile()) {
|
|
10746
10847
|
throw new Error(`not a file: ${resolved}`);
|
|
10747
10848
|
}
|
|
10748
|
-
const ext =
|
|
10849
|
+
const ext = path10.extname(resolved).toLowerCase();
|
|
10749
10850
|
switch (ext) {
|
|
10750
10851
|
case ".md":
|
|
10751
10852
|
case ".txt":
|
|
10752
10853
|
case ".markdown":
|
|
10753
|
-
return
|
|
10854
|
+
return fs11.readFileSync(resolved, "utf-8");
|
|
10754
10855
|
case ".html":
|
|
10755
10856
|
case ".htm":
|
|
10756
|
-
return stripHtml(
|
|
10857
|
+
return stripHtml(fs11.readFileSync(resolved, "utf-8"));
|
|
10757
10858
|
case ".docx":
|
|
10758
10859
|
return extractDocx(resolved);
|
|
10759
10860
|
case ".pdf":
|
|
@@ -10773,11 +10874,11 @@ function listDocumentsInDir(dirPath) {
|
|
|
10773
10874
|
}).filter(isSupportedDocument);
|
|
10774
10875
|
}
|
|
10775
10876
|
function collectDocumentsFromPath(inputPath) {
|
|
10776
|
-
const resolved =
|
|
10777
|
-
if (!
|
|
10877
|
+
const resolved = path10.resolve(inputPath.trim().replace(/^~(?=$|\/)/, os7.homedir()));
|
|
10878
|
+
if (!fs11.existsSync(resolved)) {
|
|
10778
10879
|
throw new Error(`path not found: ${resolved}`);
|
|
10779
10880
|
}
|
|
10780
|
-
const stat =
|
|
10881
|
+
const stat = fs11.statSync(resolved);
|
|
10781
10882
|
const files = stat.isFile() ? [resolved] : listDocumentsInDir(resolved);
|
|
10782
10883
|
if (!files.length) {
|
|
10783
10884
|
throw new Error(
|
|
@@ -10804,20 +10905,20 @@ function readDraftInput(input) {
|
|
|
10804
10905
|
const trimmed = input.trim();
|
|
10805
10906
|
if (!trimmed)
|
|
10806
10907
|
throw new Error("empty draft");
|
|
10807
|
-
const maybePath =
|
|
10808
|
-
if (
|
|
10908
|
+
const maybePath = path10.resolve(trimmed.replace(/^~(?=$|\/)/, os7.homedir()));
|
|
10909
|
+
if (fs11.existsSync(maybePath) && fs11.statSync(maybePath).isFile()) {
|
|
10809
10910
|
return { text: extractTextFromFile(maybePath), source: maybePath };
|
|
10810
10911
|
}
|
|
10811
10912
|
return { text: trimmed, source: "paste" };
|
|
10812
10913
|
}
|
|
10813
|
-
var import_child_process2,
|
|
10914
|
+
var import_child_process2, fs11, os7, path10, SUPPORTED_EXTENSIONS, SAMPLE_GLOB, GLOB_IGNORE;
|
|
10814
10915
|
var init_document_text = __esm({
|
|
10815
10916
|
"src/lib/document-text.ts"() {
|
|
10816
10917
|
"use strict";
|
|
10817
10918
|
import_child_process2 = require("child_process");
|
|
10818
|
-
|
|
10819
|
-
|
|
10820
|
-
|
|
10919
|
+
fs11 = __toESM(require("fs"));
|
|
10920
|
+
os7 = __toESM(require("os"));
|
|
10921
|
+
path10 = __toESM(require("path"));
|
|
10821
10922
|
init_index_min();
|
|
10822
10923
|
SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
10823
10924
|
".md",
|
|
@@ -10892,21 +10993,21 @@ function runPipeline(text, profile, applyFixes = false) {
|
|
|
10892
10993
|
};
|
|
10893
10994
|
}
|
|
10894
10995
|
function readText(source) {
|
|
10895
|
-
const
|
|
10896
|
-
const
|
|
10996
|
+
const fs30 = require("fs");
|
|
10997
|
+
const path27 = require("path");
|
|
10897
10998
|
if (source === "-") {
|
|
10898
10999
|
if (process.stdin.isTTY) {
|
|
10899
11000
|
console.error("No input provided. Pipe content or specify a file.");
|
|
10900
11001
|
process.exit(1);
|
|
10901
11002
|
}
|
|
10902
|
-
return { text:
|
|
11003
|
+
return { text: fs30.readFileSync(0, "utf-8"), path: "stdin" };
|
|
10903
11004
|
}
|
|
10904
|
-
const resolved =
|
|
10905
|
-
if (!
|
|
11005
|
+
const resolved = path27.resolve(source);
|
|
11006
|
+
if (!fs30.existsSync(resolved)) {
|
|
10906
11007
|
console.error(`File not found: ${resolved}`);
|
|
10907
11008
|
process.exit(1);
|
|
10908
11009
|
}
|
|
10909
|
-
const stat =
|
|
11010
|
+
const stat = fs30.statSync(resolved);
|
|
10910
11011
|
if (stat.isDirectory()) {
|
|
10911
11012
|
console.error(`${resolved} is a directory, not a file.`);
|
|
10912
11013
|
process.exit(1);
|
|
@@ -11358,10 +11459,10 @@ var init_terminal_ui = __esm({
|
|
|
11358
11459
|
// src/lib/welcome-flow.ts
|
|
11359
11460
|
function readWelcomeState() {
|
|
11360
11461
|
try {
|
|
11361
|
-
if (!
|
|
11462
|
+
if (!fs15.existsSync(STATE_FILE)) {
|
|
11362
11463
|
return { completed_steps: [], updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
11363
11464
|
}
|
|
11364
|
-
return JSON.parse(
|
|
11465
|
+
return JSON.parse(fs15.readFileSync(STATE_FILE, "utf-8"));
|
|
11365
11466
|
} catch {
|
|
11366
11467
|
return { completed_steps: [], updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
11367
11468
|
}
|
|
@@ -11373,7 +11474,7 @@ function writeWelcomeState(patch) {
|
|
|
11373
11474
|
...patch,
|
|
11374
11475
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
11375
11476
|
};
|
|
11376
|
-
|
|
11477
|
+
fs15.writeFileSync(STATE_FILE, JSON.stringify(next, null, 2), { mode: 384 });
|
|
11377
11478
|
return next;
|
|
11378
11479
|
}
|
|
11379
11480
|
function markStepComplete(step) {
|
|
@@ -11602,7 +11703,7 @@ function saveLocalProfile(name, content) {
|
|
|
11602
11703
|
writeWelcomeState({ profile_name: safe });
|
|
11603
11704
|
markStepComplete("name");
|
|
11604
11705
|
markStepComplete("samples");
|
|
11605
|
-
return
|
|
11706
|
+
return path14.join(os8.homedir(), ".hyv", "profiles", `${safe}.md`);
|
|
11606
11707
|
}
|
|
11607
11708
|
function fetchUrlText(url) {
|
|
11608
11709
|
return new Promise((resolve15, reject) => {
|
|
@@ -11824,8 +11925,8 @@ async function stepSignup(profileName) {
|
|
|
11824
11925
|
} else {
|
|
11825
11926
|
console.log(import_chalk12.default.dim("\n already signed in \u2014 syncing profile..."));
|
|
11826
11927
|
}
|
|
11827
|
-
const content =
|
|
11828
|
-
|
|
11928
|
+
const content = fs15.readFileSync(
|
|
11929
|
+
path14.join(os8.homedir(), ".hyv", "profiles", `${profileName}.md`),
|
|
11829
11930
|
"utf-8"
|
|
11830
11931
|
);
|
|
11831
11932
|
try {
|
|
@@ -11855,7 +11956,7 @@ async function stepSignup(profileName) {
|
|
|
11855
11956
|
));
|
|
11856
11957
|
}
|
|
11857
11958
|
console.log(import_chalk12.default.cyan("\n opening billing in your dashboard ($1 first month)..."));
|
|
11858
|
-
await withSpinner("opening billing\u2026", () => openAuthenticatedDashboard({ next: "/
|
|
11959
|
+
await withSpinner("opening billing\u2026", () => openAuthenticatedDashboard({ next: "/dashboard?tab=billing" }));
|
|
11859
11960
|
await briefPause();
|
|
11860
11961
|
markStepComplete("signup");
|
|
11861
11962
|
console.log(import_chalk12.default.dim("\n you're signed in \u2014 pick a plan in billing, no second login.\n"));
|
|
@@ -11890,16 +11991,16 @@ function getMcpWelcomeResponse(args2) {
|
|
|
11890
11991
|
}
|
|
11891
11992
|
return buildWelcomeGuide({ profileName: args2.profile, forLlm: true });
|
|
11892
11993
|
}
|
|
11893
|
-
var import_chalk12,
|
|
11994
|
+
var import_chalk12, fs15, http2, https2, os8, path14, readline, WELCOME_TAGLINE, FLOW_STEPS, STATE_FILE;
|
|
11894
11995
|
var init_welcome_flow = __esm({
|
|
11895
11996
|
"src/lib/welcome-flow.ts"() {
|
|
11896
11997
|
"use strict";
|
|
11897
11998
|
import_chalk12 = __toESM(require_source());
|
|
11898
|
-
|
|
11999
|
+
fs15 = __toESM(require("fs"));
|
|
11899
12000
|
http2 = __toESM(require("http"));
|
|
11900
12001
|
https2 = __toESM(require("https"));
|
|
11901
|
-
|
|
11902
|
-
|
|
12002
|
+
os8 = __toESM(require("os"));
|
|
12003
|
+
path14 = __toESM(require("path"));
|
|
11903
12004
|
readline = __toESM(require("readline"));
|
|
11904
12005
|
init_pipeline();
|
|
11905
12006
|
init_document_text();
|
|
@@ -11918,7 +12019,7 @@ var init_welcome_flow = __esm({
|
|
|
11918
12019
|
{ n: 3, key: "test", title: "test on a draft", hint: "optional \u2014 scan or rewrite a draft" },
|
|
11919
12020
|
{ n: 4, key: "signup", title: "save & unlock", hint: "signup syncs your profile and unlocks learning" }
|
|
11920
12021
|
];
|
|
11921
|
-
STATE_FILE =
|
|
12022
|
+
STATE_FILE = path14.join(os8.homedir(), ".hyv", "welcome-state.json");
|
|
11922
12023
|
}
|
|
11923
12024
|
});
|
|
11924
12025
|
|
|
@@ -12906,15 +13007,15 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s))
|
|
|
12906
13007
|
g.minimatch.escape = vi2.escape;
|
|
12907
13008
|
g.minimatch.unescape = Ei2.unescape;
|
|
12908
13009
|
});
|
|
12909
|
-
var
|
|
13010
|
+
var fs30 = R2((Wt2) => {
|
|
12910
13011
|
"use strict";
|
|
12911
13012
|
Object.defineProperty(Wt2, "__esModule", { value: true });
|
|
12912
13013
|
Wt2.LRUCache = void 0;
|
|
12913
13014
|
var er = typeof performance == "object" && performance && typeof performance.now == "function" ? performance : Date, as2 = /* @__PURE__ */ new Set(), ge2 = typeof process == "object" && process ? process : {}, ls2 = (n7, t, e, s) => {
|
|
12914
13015
|
typeof ge2.emitWarning == "function" ? ge2.emitWarning(n7, t, e, s) : console.error(`[${e}] ${t}: ${n7}`);
|
|
12915
|
-
}, Lt2 = globalThis.AbortController,
|
|
13016
|
+
}, Lt2 = globalThis.AbortController, os13 = globalThis.AbortSignal;
|
|
12916
13017
|
if (typeof Lt2 > "u") {
|
|
12917
|
-
|
|
13018
|
+
os13 = class {
|
|
12918
13019
|
onabort;
|
|
12919
13020
|
_onabort = [];
|
|
12920
13021
|
reason;
|
|
@@ -12926,7 +13027,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s))
|
|
|
12926
13027
|
constructor() {
|
|
12927
13028
|
t();
|
|
12928
13029
|
}
|
|
12929
|
-
signal = new
|
|
13030
|
+
signal = new os13();
|
|
12930
13031
|
abort(e) {
|
|
12931
13032
|
if (!this.signal.aborted) {
|
|
12932
13033
|
this.signal.reason = e, this.signal.aborted = true;
|
|
@@ -13875,7 +13976,7 @@ globstar while`, t, d, e, u, m), this.matchOne(t.slice(d), e.slice(u), s))
|
|
|
13875
13976
|
};
|
|
13876
13977
|
Object.defineProperty(_2, "__esModule", { value: true });
|
|
13877
13978
|
_2.PathScurry = _2.Path = _2.PathScurryDarwin = _2.PathScurryPosix = _2.PathScurryWin32 = _2.PathScurryBase = _2.PathPosix = _2.PathWin32 = _2.PathBase = _2.ChildrenCache = _2.ResolveCache = void 0;
|
|
13878
|
-
var Qt2 =
|
|
13979
|
+
var Qt2 = fs30(), Yt2 = require("node:path"), yr = require("node:url"), pt2 = require("fs"), Sr = br(require("node:fs")), vr = pt2.realpathSync.native, Ht2 = require("node:fs/promises"), bs2 = Oe2(), mt2 = { lstatSync: pt2.lstatSync, readdir: pt2.readdir, readdirSync: pt2.readdirSync, readlinkSync: pt2.readlinkSync, realpathSync: vr, promises: { lstat: Ht2.lstat, readdir: Ht2.readdir, readlink: Ht2.readlink, realpath: Ht2.realpath } }, _s2 = (n7) => !n7 || n7 === mt2 || n7 === Sr ? mt2 : { ...mt2, ...n7, promises: { ...mt2.promises, ...n7.promises || {} } }, Os2 = /^\\\\\?\\([a-z]:)\\?$/i, Er = (n7) => n7.replace(/\//g, "\\").replace(Os2, "$1\\"), _r = /[\\\/]/, N2 = 0, xs2 = 1, Ts2 = 2, G2 = 4, Cs2 = 6, Rs2 = 8, Q2 = 10, As2 = 12, j2 = 15, dt2 = ~j2, xe2 = 16, ys2 = 32, gt2 = 64, W2 = 128, Vt2 = 256, Xt2 = 512, Ss2 = gt2 | W2 | Xt2, Or = 1023, Te2 = (n7) => n7.isFile() ? Rs2 : n7.isDirectory() ? G2 : n7.isSymbolicLink() ? Q2 : n7.isCharacterDevice() ? Ts2 : n7.isBlockDevice() ? Cs2 : n7.isSocket() ? As2 : n7.isFIFO() ? xs2 : N2, vs2 = new Qt2.LRUCache({ max: 2 ** 12 }), wt2 = (n7) => {
|
|
13879
13980
|
let t = vs2.get(n7);
|
|
13880
13981
|
if (t)
|
|
13881
13982
|
return t;
|
|
@@ -15523,7 +15624,7 @@ function registerInitCommand(program3) {
|
|
|
15523
15624
|
} else if (options?.browser === false) {
|
|
15524
15625
|
console.log(import_chalk4.default.red("License key required when --no-browser is set."));
|
|
15525
15626
|
console.log("\nUsage: hyv init <license-key>");
|
|
15526
|
-
console.log("\nGenerate a license key at: https://holdyourvoice.com/
|
|
15627
|
+
console.log("\nGenerate a license key at: https://holdyourvoice.com/dashboard");
|
|
15527
15628
|
process.exit(1);
|
|
15528
15629
|
} else {
|
|
15529
15630
|
authData = await authenticateWithBrowser();
|
|
@@ -15570,8 +15671,8 @@ init_version();
|
|
|
15570
15671
|
|
|
15571
15672
|
// src/lib/queue-sync.ts
|
|
15572
15673
|
var import_chalk6 = __toESM(require_source());
|
|
15573
|
-
var
|
|
15574
|
-
var
|
|
15674
|
+
var fs7 = __toESM(require("fs"));
|
|
15675
|
+
var path7 = __toESM(require("path"));
|
|
15575
15676
|
init_config();
|
|
15576
15677
|
init_auth();
|
|
15577
15678
|
async function flushQueuedSignals() {
|
|
@@ -15580,13 +15681,13 @@ async function flushQueuedSignals() {
|
|
|
15580
15681
|
return { sent: 0, failed: 0 };
|
|
15581
15682
|
let sent = 0;
|
|
15582
15683
|
let failed = 0;
|
|
15583
|
-
if (!
|
|
15684
|
+
if (!fs7.existsSync(QUEUE_DIR))
|
|
15584
15685
|
return { sent: 0, failed: 0 };
|
|
15585
|
-
const files =
|
|
15686
|
+
const files = fs7.readdirSync(QUEUE_DIR).filter((f) => f.endsWith(".json"));
|
|
15586
15687
|
for (const file of files) {
|
|
15587
|
-
const filePath =
|
|
15688
|
+
const filePath = path7.join(QUEUE_DIR, file);
|
|
15588
15689
|
try {
|
|
15589
|
-
const signal = JSON.parse(
|
|
15690
|
+
const signal = JSON.parse(fs7.readFileSync(filePath, "utf-8"));
|
|
15590
15691
|
let ok = false;
|
|
15591
15692
|
if (signal.type === "reinforce") {
|
|
15592
15693
|
const res = await authenticatedRequest(cliApiUrl("/cli/learning/reinforce"), {
|
|
@@ -15607,7 +15708,7 @@ async function flushQueuedSignals() {
|
|
|
15607
15708
|
ok = res.status === 200;
|
|
15608
15709
|
}
|
|
15609
15710
|
if (ok) {
|
|
15610
|
-
|
|
15711
|
+
fs7.unlinkSync(filePath);
|
|
15611
15712
|
sent++;
|
|
15612
15713
|
} else {
|
|
15613
15714
|
failed++;
|
|
@@ -15764,8 +15865,9 @@ init_config();
|
|
|
15764
15865
|
init_auth();
|
|
15765
15866
|
init_access();
|
|
15766
15867
|
init_profile();
|
|
15767
|
-
|
|
15768
|
-
var
|
|
15868
|
+
init_profile_meta();
|
|
15869
|
+
var fs8 = __toESM(require("fs"));
|
|
15870
|
+
var path8 = __toESM(require("path"));
|
|
15769
15871
|
function registerSyncCommand(program3) {
|
|
15770
15872
|
program3.command("sync").description("Sync profiles and rules from server").option("--force", "Force re-download even if cache is fresh").action(async (options) => {
|
|
15771
15873
|
try {
|
|
@@ -15783,27 +15885,40 @@ function registerSyncCommand(program3) {
|
|
|
15783
15885
|
const data = response.data;
|
|
15784
15886
|
ensureHyvDir();
|
|
15785
15887
|
let profileCount = 0;
|
|
15888
|
+
let skippedNewer = 0;
|
|
15786
15889
|
for (const profile of data.profiles) {
|
|
15787
15890
|
if (!profile.content?.trim()) {
|
|
15788
15891
|
console.log(import_chalk8.default.yellow(` ! skipped empty profile cache: ${profile.name}`));
|
|
15789
15892
|
continue;
|
|
15790
15893
|
}
|
|
15791
15894
|
const cacheKey = toSafeProfileCacheKey(profile.slug || profile.name);
|
|
15895
|
+
if (!shouldApplyServerProfileUpdate(profile.updated_at, cacheKey, options.force)) {
|
|
15896
|
+
skippedNewer++;
|
|
15897
|
+
console.log(import_chalk8.default.yellow(` ! kept newer local profile: ${profile.name}`));
|
|
15898
|
+
continue;
|
|
15899
|
+
}
|
|
15792
15900
|
writeCachedProfile(cacheKey, profile.content);
|
|
15901
|
+
setProfileMeta(cacheKey, { server_updated_at: profile.updated_at });
|
|
15793
15902
|
profileCount++;
|
|
15794
15903
|
}
|
|
15795
|
-
const rulesPath =
|
|
15796
|
-
|
|
15797
|
-
const promptPath =
|
|
15798
|
-
|
|
15904
|
+
const rulesPath = path8.join(CACHE_DIR2, "rules.md");
|
|
15905
|
+
fs8.writeFileSync(rulesPath, data.rules, { mode: 384 });
|
|
15906
|
+
const promptPath = path8.join(CACHE_DIR2, "prompt-template.md");
|
|
15907
|
+
fs8.writeFileSync(promptPath, data.prompt_template, { mode: 384 });
|
|
15799
15908
|
if (data.detection_rules) {
|
|
15800
|
-
const rulesJson =
|
|
15801
|
-
|
|
15909
|
+
const rulesJson = path8.join(CACHE_DIR2, "detection-rules.json");
|
|
15910
|
+
fs8.writeFileSync(rulesJson, JSON.stringify(data.detection_rules, null, 2), { mode: 384 });
|
|
15802
15911
|
}
|
|
15803
15912
|
for (const profile of data.profiles) {
|
|
15804
15913
|
try {
|
|
15805
15914
|
const cacheKey = toSafeProfileCacheKey(profile.slug || profile.name);
|
|
15806
|
-
|
|
15915
|
+
if (!shouldApplyServerProfileUpdate(profile.updated_at, cacheKey, options.force)) {
|
|
15916
|
+
continue;
|
|
15917
|
+
}
|
|
15918
|
+
await loadFullProfile(cacheKey, {
|
|
15919
|
+
forceRefresh: true,
|
|
15920
|
+
serverUpdatedAt: profile.updated_at
|
|
15921
|
+
});
|
|
15807
15922
|
} catch {
|
|
15808
15923
|
}
|
|
15809
15924
|
}
|
|
@@ -15814,8 +15929,8 @@ function registerSyncCommand(program3) {
|
|
|
15814
15929
|
if (queueResult.failed > 0) {
|
|
15815
15930
|
console.log(import_chalk8.default.yellow(` ! ${queueResult.failed} queued signal(s) could not send`));
|
|
15816
15931
|
}
|
|
15817
|
-
const metaPath =
|
|
15818
|
-
|
|
15932
|
+
const metaPath = path8.join(CACHE_DIR2, "sync-meta.json");
|
|
15933
|
+
fs8.writeFileSync(metaPath, JSON.stringify({
|
|
15819
15934
|
synced_at: data.synced_at,
|
|
15820
15935
|
profile_count: profileCount,
|
|
15821
15936
|
plan: data.plan
|
|
@@ -15823,6 +15938,9 @@ function registerSyncCommand(program3) {
|
|
|
15823
15938
|
console.log(import_chalk8.default.green(`
|
|
15824
15939
|
\u2713 Synced successfully!`));
|
|
15825
15940
|
console.log(import_chalk8.default.dim(` Profiles: ${profileCount}`));
|
|
15941
|
+
if (skippedNewer > 0) {
|
|
15942
|
+
console.log(import_chalk8.default.dim(` Kept local (newer): ${skippedNewer} \u2014 use --force to overwrite`));
|
|
15943
|
+
}
|
|
15826
15944
|
console.log(import_chalk8.default.dim(` Rules: cached`));
|
|
15827
15945
|
console.log(import_chalk8.default.dim(` Prompt template: cached`));
|
|
15828
15946
|
console.log(import_chalk8.default.dim(` Plan: ${data.plan}`));
|
|
@@ -15920,21 +16038,21 @@ Profile evolution: ${slug}
|
|
|
15920
16038
|
|
|
15921
16039
|
// src/commands/rewrite.ts
|
|
15922
16040
|
var import_chalk9 = __toESM(require_source());
|
|
15923
|
-
var
|
|
15924
|
-
var
|
|
16041
|
+
var fs13 = __toESM(require("fs"));
|
|
16042
|
+
var path12 = __toESM(require("path"));
|
|
15925
16043
|
init_pipeline();
|
|
15926
16044
|
|
|
15927
16045
|
// src/lib/prompt.ts
|
|
15928
|
-
var
|
|
15929
|
-
var
|
|
16046
|
+
var fs12 = __toESM(require("fs"));
|
|
16047
|
+
var path11 = __toESM(require("path"));
|
|
15930
16048
|
init_config();
|
|
15931
16049
|
init_signals();
|
|
15932
16050
|
init_profile_parse();
|
|
15933
16051
|
function loadPromptTemplate() {
|
|
15934
|
-
const templatePath =
|
|
16052
|
+
const templatePath = path11.join(CACHE_DIR2, "prompt-template.md");
|
|
15935
16053
|
try {
|
|
15936
|
-
if (
|
|
15937
|
-
return
|
|
16054
|
+
if (fs12.existsSync(templatePath)) {
|
|
16055
|
+
return fs12.readFileSync(templatePath, "utf-8");
|
|
15938
16056
|
}
|
|
15939
16057
|
} catch {
|
|
15940
16058
|
}
|
|
@@ -16121,8 +16239,8 @@ Draft: ${draftPath}`));
|
|
|
16121
16239
|
${result.stats.autoFixed} issues can be auto-fixed \u2014 run: hyv fix ${file}`));
|
|
16122
16240
|
}
|
|
16123
16241
|
if (options.output) {
|
|
16124
|
-
const outputPath =
|
|
16125
|
-
|
|
16242
|
+
const outputPath = path12.resolve(options.output);
|
|
16243
|
+
fs13.writeFileSync(outputPath, promptResult.prompt);
|
|
16126
16244
|
console.log(import_chalk9.default.green(`
|
|
16127
16245
|
\u2713 Prompt written to ${outputPath}`));
|
|
16128
16246
|
} else {
|
|
@@ -16142,8 +16260,8 @@ Draft: ${draftPath}`));
|
|
|
16142
16260
|
|
|
16143
16261
|
// src/commands/learning.ts
|
|
16144
16262
|
var import_chalk10 = __toESM(require_source());
|
|
16145
|
-
var
|
|
16146
|
-
var
|
|
16263
|
+
var fs14 = __toESM(require("fs"));
|
|
16264
|
+
var path13 = __toESM(require("path"));
|
|
16147
16265
|
|
|
16148
16266
|
// src/lib/diff.ts
|
|
16149
16267
|
init_scan();
|
|
@@ -16287,18 +16405,18 @@ function registerLearningCommands(program3) {
|
|
|
16287
16405
|
console.error(import_chalk10.default.red("Provide <original> <edited> or use --last"));
|
|
16288
16406
|
process.exit(1);
|
|
16289
16407
|
}
|
|
16290
|
-
origPath =
|
|
16291
|
-
editPath =
|
|
16292
|
-
if (!
|
|
16408
|
+
origPath = path13.resolve(original);
|
|
16409
|
+
editPath = path13.resolve(edited);
|
|
16410
|
+
if (!fs14.existsSync(origPath)) {
|
|
16293
16411
|
console.error(import_chalk10.default.red(`Original file not found: ${origPath}`));
|
|
16294
16412
|
process.exit(1);
|
|
16295
16413
|
}
|
|
16296
|
-
if (!
|
|
16414
|
+
if (!fs14.existsSync(editPath)) {
|
|
16297
16415
|
console.error(import_chalk10.default.red(`Edited file not found: ${editPath}`));
|
|
16298
16416
|
process.exit(1);
|
|
16299
16417
|
}
|
|
16300
|
-
origText =
|
|
16301
|
-
editText =
|
|
16418
|
+
origText = fs14.readFileSync(origPath, "utf-8");
|
|
16419
|
+
editText = fs14.readFileSync(editPath, "utf-8");
|
|
16302
16420
|
saveLastEditSession({
|
|
16303
16421
|
original_path: origPath,
|
|
16304
16422
|
edited_path: editPath,
|
|
@@ -16465,8 +16583,8 @@ function printProfileImpact(impact, data) {
|
|
|
16465
16583
|
|
|
16466
16584
|
// src/commands/onboarding.ts
|
|
16467
16585
|
var import_chalk13 = __toESM(require_source());
|
|
16468
|
-
var
|
|
16469
|
-
var
|
|
16586
|
+
var fs16 = __toESM(require("fs"));
|
|
16587
|
+
var path15 = __toESM(require("path"));
|
|
16470
16588
|
init_config();
|
|
16471
16589
|
init_auth();
|
|
16472
16590
|
init_scan();
|
|
@@ -16617,24 +16735,24 @@ Industry: ${industry}
|
|
|
16617
16735
|
}
|
|
16618
16736
|
}
|
|
16619
16737
|
async function createFromSamples(name, sampleDir, token) {
|
|
16620
|
-
const dirPath =
|
|
16621
|
-
if (!
|
|
16738
|
+
const dirPath = path15.resolve(sampleDir);
|
|
16739
|
+
if (!fs16.existsSync(dirPath)) {
|
|
16622
16740
|
throw new Error(`Directory not found: ${dirPath}`);
|
|
16623
16741
|
}
|
|
16624
16742
|
console.log(import_chalk13.default.bold(`
|
|
16625
16743
|
Creating voice profile: ${name}`));
|
|
16626
16744
|
console.log(import_chalk13.default.dim(`Reading samples from: ${dirPath}
|
|
16627
16745
|
`));
|
|
16628
|
-
const files =
|
|
16746
|
+
const files = fs16.readdirSync(dirPath).filter((f) => f.endsWith(".md") || f.endsWith(".txt")).map((f) => path15.join(dirPath, f));
|
|
16629
16747
|
if (files.length === 0) {
|
|
16630
16748
|
throw new Error("No .md or .txt files found in directory");
|
|
16631
16749
|
}
|
|
16632
16750
|
const samples = [];
|
|
16633
16751
|
for (const file of files) {
|
|
16634
|
-
const text =
|
|
16752
|
+
const text = fs16.readFileSync(file, "utf-8");
|
|
16635
16753
|
if (text.trim().length > 0) {
|
|
16636
16754
|
samples.push({ path: file, text });
|
|
16637
|
-
console.log(import_chalk13.default.dim(` \u2022 ${
|
|
16755
|
+
console.log(import_chalk13.default.dim(` \u2022 ${path15.basename(file)} (${words(text).length} words)`));
|
|
16638
16756
|
}
|
|
16639
16757
|
}
|
|
16640
16758
|
if (samples.length === 0) {
|
|
@@ -16705,12 +16823,12 @@ function registerImportCommand(program3) {
|
|
|
16705
16823
|
program3.command("import").description("Import a voice profile from file").argument("<name>", "Profile name").argument("<file>", "Profile markdown file").action(async (name, file) => {
|
|
16706
16824
|
try {
|
|
16707
16825
|
assertSafeProfileName(name);
|
|
16708
|
-
const filePath =
|
|
16709
|
-
if (!
|
|
16826
|
+
const filePath = path15.resolve(file);
|
|
16827
|
+
if (!fs16.existsSync(filePath)) {
|
|
16710
16828
|
console.error(import_chalk13.default.red(`File not found: ${filePath}`));
|
|
16711
16829
|
process.exit(1);
|
|
16712
16830
|
}
|
|
16713
|
-
const content =
|
|
16831
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
16714
16832
|
ensureHyvDir();
|
|
16715
16833
|
writeCachedProfile(name, content);
|
|
16716
16834
|
console.log(import_chalk13.default.green(`
|
|
@@ -16879,7 +16997,7 @@ async function showPlan() {
|
|
|
16879
16997
|
async function upgradePlan() {
|
|
16880
16998
|
console.log(import_chalk14.default.cyan("\nOpening billing in your dashboard ($1 first month)...\n"));
|
|
16881
16999
|
try {
|
|
16882
|
-
await openAuthenticatedDashboard({ next: "/
|
|
17000
|
+
await openAuthenticatedDashboard({ next: "/dashboard?tab=billing" });
|
|
16883
17001
|
console.log(import_chalk14.default.green("\n\u2713 Dashboard opened \u2014 you're already signed in"));
|
|
16884
17002
|
console.log(import_chalk14.default.dim("Pick a plan in billing. No second login."));
|
|
16885
17003
|
} catch {
|
|
@@ -17081,11 +17199,11 @@ async function runHybridAnalysis(text, profile, opts = {}) {
|
|
|
17081
17199
|
|
|
17082
17200
|
// src/commands/history.ts
|
|
17083
17201
|
var import_chalk16 = __toESM(require_source());
|
|
17084
|
-
var
|
|
17085
|
-
var
|
|
17202
|
+
var fs17 = __toESM(require("fs"));
|
|
17203
|
+
var path16 = __toESM(require("path"));
|
|
17086
17204
|
init_config();
|
|
17087
|
-
var HISTORY_DIR =
|
|
17088
|
-
var HISTORY_FILE =
|
|
17205
|
+
var HISTORY_DIR = path16.join(HYV_DIR, "history");
|
|
17206
|
+
var HISTORY_FILE = path16.join(HISTORY_DIR, "scans.jsonl");
|
|
17089
17207
|
function logScan(entry) {
|
|
17090
17208
|
try {
|
|
17091
17209
|
ensureHyvDir();
|
|
@@ -17095,9 +17213,9 @@ function logScan(entry) {
|
|
|
17095
17213
|
}
|
|
17096
17214
|
function readHistory() {
|
|
17097
17215
|
try {
|
|
17098
|
-
if (!
|
|
17216
|
+
if (!fs17.existsSync(HISTORY_FILE))
|
|
17099
17217
|
return [];
|
|
17100
|
-
const lines =
|
|
17218
|
+
const lines = fs17.readFileSync(HISTORY_FILE, "utf-8").trim().split("\n").filter(Boolean);
|
|
17101
17219
|
return lines.map((l) => JSON.parse(l));
|
|
17102
17220
|
} catch {
|
|
17103
17221
|
return [];
|
|
@@ -17129,8 +17247,8 @@ function registerHistoryCommand(program3) {
|
|
|
17129
17247
|
program3.command("history").description("Show past scan scores and track improvement").option("--limit <n>", "Number of entries to show", "20").option("--file <path>", "Filter by file path").option("--since <date>", "Show entries since (e.g., 7d, 1m, 2024-01-01)").option("--chart", "Show ASCII sparkline chart").option("--clear", "Clear history").option("--format <type>", "Output format (text, json)", "text").action(async (options) => {
|
|
17130
17248
|
try {
|
|
17131
17249
|
if (options.clear) {
|
|
17132
|
-
if (
|
|
17133
|
-
|
|
17250
|
+
if (fs17.existsSync(HISTORY_FILE)) {
|
|
17251
|
+
fs17.unlinkSync(HISTORY_FILE);
|
|
17134
17252
|
}
|
|
17135
17253
|
console.log(import_chalk16.default.green("\n\u2713 History cleared"));
|
|
17136
17254
|
return;
|
|
@@ -17188,7 +17306,7 @@ function registerHistoryCommand(program3) {
|
|
|
17188
17306
|
const icon = entry.issues === 0 ? import_chalk16.default.green("\u2713") : import_chalk16.default.red("\u25CF");
|
|
17189
17307
|
const score = entry.score < 60 ? import_chalk16.default.red(`${entry.score}/100`) : entry.score < 80 ? import_chalk16.default.yellow(`${entry.score}/100`) : import_chalk16.default.green(`${entry.score}/100`);
|
|
17190
17308
|
const issues = entry.issues > 0 ? import_chalk16.default.red(`${entry.issues} issues`) : import_chalk16.default.dim("clean");
|
|
17191
|
-
const file =
|
|
17309
|
+
const file = path16.basename(entry.file).slice(0, 25).padEnd(25);
|
|
17192
17310
|
console.log(` ${import_chalk16.default.dim(time)} ${icon} ${file} ${score} ${issues}`);
|
|
17193
17311
|
}
|
|
17194
17312
|
console.log("");
|
|
@@ -17296,9 +17414,9 @@ hyv scan ${filePath}`));
|
|
|
17296
17414
|
|
|
17297
17415
|
// src/commands/doctor.ts
|
|
17298
17416
|
var import_chalk18 = __toESM(require_source());
|
|
17299
|
-
var
|
|
17300
|
-
var
|
|
17301
|
-
var
|
|
17417
|
+
var fs19 = __toESM(require("fs"));
|
|
17418
|
+
var path18 = __toESM(require("path"));
|
|
17419
|
+
var os9 = __toESM(require("os"));
|
|
17302
17420
|
init_config();
|
|
17303
17421
|
init_auth();
|
|
17304
17422
|
init_access();
|
|
@@ -17309,15 +17427,15 @@ init_version();
|
|
|
17309
17427
|
var import_child_process3 = require("child_process");
|
|
17310
17428
|
|
|
17311
17429
|
// src/lib/cli-entry.ts
|
|
17312
|
-
var
|
|
17313
|
-
var
|
|
17430
|
+
var fs18 = __toESM(require("fs"));
|
|
17431
|
+
var path17 = __toESM(require("path"));
|
|
17314
17432
|
function resolveCliEntry() {
|
|
17315
17433
|
const candidates = [
|
|
17316
|
-
|
|
17317
|
-
|
|
17318
|
-
|
|
17434
|
+
path17.resolve(process.argv[1] || ""),
|
|
17435
|
+
path17.resolve(__dirname, "index.js"),
|
|
17436
|
+
path17.resolve(__dirname, "..", "dist", "index.js")
|
|
17319
17437
|
];
|
|
17320
|
-
return candidates.find((p) => p &&
|
|
17438
|
+
return candidates.find((p) => p && fs18.existsSync(p)) || null;
|
|
17321
17439
|
}
|
|
17322
17440
|
function mcpServerCommand() {
|
|
17323
17441
|
const entry = resolveCliEntry();
|
|
@@ -17403,20 +17521,47 @@ async function testMcpStdioSubprocess() {
|
|
|
17403
17521
|
}
|
|
17404
17522
|
|
|
17405
17523
|
// src/commands/doctor.ts
|
|
17406
|
-
var HOME =
|
|
17524
|
+
var HOME = os9.homedir();
|
|
17407
17525
|
var IS_WIN = process.platform === "win32";
|
|
17408
17526
|
function claudeDesktopDir() {
|
|
17409
17527
|
if (IS_WIN)
|
|
17410
|
-
return
|
|
17528
|
+
return path18.join(HOME, "AppData", "Roaming", "Claude");
|
|
17411
17529
|
if (process.platform === "linux")
|
|
17412
|
-
return
|
|
17413
|
-
return
|
|
17530
|
+
return path18.join(HOME, ".config", "Claude");
|
|
17531
|
+
return path18.join(HOME, "Library", "Application Support", "Claude");
|
|
17532
|
+
}
|
|
17533
|
+
function windsurfRulePath() {
|
|
17534
|
+
const dirs = [
|
|
17535
|
+
path18.join(HOME, ".windsurf"),
|
|
17536
|
+
IS_WIN ? path18.join(HOME, "AppData", "Roaming", "Windsurf") : path18.join(HOME, "Library", "Application Support", "Windsurf")
|
|
17537
|
+
];
|
|
17538
|
+
for (const dir of dirs) {
|
|
17539
|
+
const file = path18.join(dir, "rules", "hyv.md");
|
|
17540
|
+
if (fs19.existsSync(file))
|
|
17541
|
+
return file;
|
|
17542
|
+
}
|
|
17543
|
+
return null;
|
|
17544
|
+
}
|
|
17545
|
+
function opencodeAgentsPath() {
|
|
17546
|
+
return path18.join(HOME, ".config", "opencode", "AGENTS.md");
|
|
17547
|
+
}
|
|
17548
|
+
function readOpencodeHyv() {
|
|
17549
|
+
const file = path18.join(HOME, ".config", "opencode", "opencode.jsonc");
|
|
17550
|
+
if (!fs19.existsSync(file))
|
|
17551
|
+
return false;
|
|
17552
|
+
try {
|
|
17553
|
+
const raw = fs19.readFileSync(file, "utf-8").replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
|
|
17554
|
+
const cfg = JSON.parse(raw);
|
|
17555
|
+
return Boolean(cfg.mcp?.hyv);
|
|
17556
|
+
} catch {
|
|
17557
|
+
return false;
|
|
17558
|
+
}
|
|
17414
17559
|
}
|
|
17415
17560
|
function isOwnerOnlyFile(filePath) {
|
|
17416
17561
|
try {
|
|
17417
|
-
if (!
|
|
17562
|
+
if (!fs19.existsSync(filePath))
|
|
17418
17563
|
return true;
|
|
17419
|
-
const mode =
|
|
17564
|
+
const mode = fs19.statSync(filePath).mode & 511;
|
|
17420
17565
|
return (mode & 63) === 0;
|
|
17421
17566
|
} catch {
|
|
17422
17567
|
return false;
|
|
@@ -17424,16 +17569,16 @@ function isOwnerOnlyFile(filePath) {
|
|
|
17424
17569
|
}
|
|
17425
17570
|
function readMcpHyv(configFile) {
|
|
17426
17571
|
try {
|
|
17427
|
-
if (!
|
|
17572
|
+
if (!fs19.existsSync(configFile))
|
|
17428
17573
|
return false;
|
|
17429
|
-
const cfg = JSON.parse(
|
|
17574
|
+
const cfg = JSON.parse(fs19.readFileSync(configFile, "utf-8"));
|
|
17430
17575
|
return Boolean(cfg.mcpServers?.hyv);
|
|
17431
17576
|
} catch {
|
|
17432
17577
|
return false;
|
|
17433
17578
|
}
|
|
17434
17579
|
}
|
|
17435
17580
|
function registerDoctorCommand(program3) {
|
|
17436
|
-
program3.command("doctor").description("Diagnose CLI health: engine, cache, auth, agents").option("--fix-agents", "Re-run agent config copy (idempotent)").action(async (opts) => {
|
|
17581
|
+
program3.command("doctor").description("Diagnose CLI health: engine, cache, auth, agents").option("--fix-agents", "Re-run agent config copy (idempotent)").option("--verify-hosts", "Spawn MCP using each host config and report pass/fail").action(async (opts) => {
|
|
17437
17582
|
console.log(import_chalk18.default.bold("\nhold your voice \u2014 doctor\n"));
|
|
17438
17583
|
let issues = 0;
|
|
17439
17584
|
let fixed = 0;
|
|
@@ -17447,28 +17592,28 @@ function registerDoctorCommand(program3) {
|
|
|
17447
17592
|
console.log(import_chalk18.default.dim("tip: run hyv welcome for free capabilities\n"));
|
|
17448
17593
|
console.log(import_chalk18.default.dim("checking cli installation..."));
|
|
17449
17594
|
const cliPath = process.argv[1];
|
|
17450
|
-
if (cliPath &&
|
|
17595
|
+
if (cliPath && fs19.existsSync(cliPath)) {
|
|
17451
17596
|
console.log(import_chalk18.default.green(" \u2713 cli installed"));
|
|
17452
17597
|
} else {
|
|
17453
17598
|
console.log(import_chalk18.default.red(" \u2717 cli not found"));
|
|
17454
17599
|
issues++;
|
|
17455
17600
|
}
|
|
17456
17601
|
console.log(import_chalk18.default.dim("checking .hyv directory..."));
|
|
17457
|
-
if (
|
|
17602
|
+
if (fs19.existsSync(HYV_DIR)) {
|
|
17458
17603
|
console.log(import_chalk18.default.green(" \u2713 .hyv directory exists"));
|
|
17459
17604
|
} else {
|
|
17460
17605
|
console.log(import_chalk18.default.yellow(" ! .hyv directory missing \u2014 creating..."));
|
|
17461
|
-
|
|
17606
|
+
fs19.mkdirSync(HYV_DIR, { recursive: true, mode: 448 });
|
|
17462
17607
|
fixed++;
|
|
17463
17608
|
}
|
|
17464
17609
|
console.log(import_chalk18.default.dim("checking cache..."));
|
|
17465
17610
|
const diskProfiles = listDiskCachedProfiles();
|
|
17466
|
-
const syncMeta =
|
|
17467
|
-
if (diskProfiles.length > 0 ||
|
|
17611
|
+
const syncMeta = path18.join(CACHE_DIR2, "sync-meta.json");
|
|
17612
|
+
if (diskProfiles.length > 0 || fs19.existsSync(syncMeta)) {
|
|
17468
17613
|
console.log(import_chalk18.default.green(` \u2713 profile cache (${diskProfiles.length} full profile(s))`));
|
|
17469
|
-
if (
|
|
17614
|
+
if (fs19.existsSync(syncMeta)) {
|
|
17470
17615
|
try {
|
|
17471
|
-
const meta = JSON.parse(
|
|
17616
|
+
const meta = JSON.parse(fs19.readFileSync(syncMeta, "utf-8"));
|
|
17472
17617
|
console.log(import_chalk18.default.dim(` last sync: ${meta.synced_at || "unknown"}`));
|
|
17473
17618
|
} catch {
|
|
17474
17619
|
}
|
|
@@ -17477,8 +17622,8 @@ function registerDoctorCommand(program3) {
|
|
|
17477
17622
|
console.log(import_chalk18.default.dim(" - no full profile cache (free local engine still works)"));
|
|
17478
17623
|
}
|
|
17479
17624
|
console.log(import_chalk18.default.dim("checking file permissions..."));
|
|
17480
|
-
if (
|
|
17481
|
-
const hyvMode =
|
|
17625
|
+
if (fs19.existsSync(HYV_DIR)) {
|
|
17626
|
+
const hyvMode = fs19.statSync(HYV_DIR).mode & 511;
|
|
17482
17627
|
if ((hyvMode & 63) === 0) {
|
|
17483
17628
|
console.log(import_chalk18.default.green(" \u2713 .hyv directory permissions"));
|
|
17484
17629
|
} else {
|
|
@@ -17487,7 +17632,7 @@ function registerDoctorCommand(program3) {
|
|
|
17487
17632
|
issues++;
|
|
17488
17633
|
}
|
|
17489
17634
|
}
|
|
17490
|
-
if (
|
|
17635
|
+
if (fs19.existsSync(AUTH_FILE)) {
|
|
17491
17636
|
if (isOwnerOnlyFile(AUTH_FILE)) {
|
|
17492
17637
|
console.log(import_chalk18.default.green(" \u2713 auth.json permissions"));
|
|
17493
17638
|
} else {
|
|
@@ -17520,9 +17665,9 @@ function registerDoctorCommand(program3) {
|
|
|
17520
17665
|
console.log(import_chalk18.default.dim(" run: hyv init for profiles + learning"));
|
|
17521
17666
|
}
|
|
17522
17667
|
console.log(import_chalk18.default.dim("checking voice profile..."));
|
|
17523
|
-
const voiceMd =
|
|
17524
|
-
const hasVoiceMd =
|
|
17525
|
-
const profileFiles =
|
|
17668
|
+
const voiceMd = path18.join(HYV_DIR, "voice.md");
|
|
17669
|
+
const hasVoiceMd = fs19.existsSync(voiceMd) && fs19.readFileSync(voiceMd, "utf-8").trim().length > 50;
|
|
17670
|
+
const profileFiles = fs19.existsSync(PROFILES_DIR) ? fs19.readdirSync(PROFILES_DIR).filter((f) => f.endsWith(".md") && f !== "voice.md") : [];
|
|
17526
17671
|
if (hasVoiceMd || profileFiles.length > 0 || diskProfiles.length > 0) {
|
|
17527
17672
|
if (hasVoiceMd)
|
|
17528
17673
|
console.log(import_chalk18.default.green(" \u2713 voice.md exists"));
|
|
@@ -17535,21 +17680,27 @@ function registerDoctorCommand(program3) {
|
|
|
17535
17680
|
console.log(import_chalk18.default.dim(" run: hyv new <name> or hyv init"));
|
|
17536
17681
|
}
|
|
17537
17682
|
console.log(import_chalk18.default.dim("checking agent configurations..."));
|
|
17538
|
-
const cursorLegacyRule =
|
|
17539
|
-
const cursorRule =
|
|
17540
|
-
if (
|
|
17683
|
+
const cursorLegacyRule = path18.join(HOME, ".cursor", "rules", "hyv.md");
|
|
17684
|
+
const cursorRule = path18.join(HOME, ".cursor", "rules", "hyv.mdc");
|
|
17685
|
+
if (fs19.existsSync(cursorLegacyRule) && fs19.existsSync(cursorRule)) {
|
|
17541
17686
|
console.log(import_chalk18.default.yellow(" ! stale cursor rule ~/.cursor/rules/hyv.md (use hyv.mdc)"));
|
|
17542
17687
|
console.log(import_chalk18.default.dim(" run: rm ~/.cursor/rules/hyv.md (or hyv doctor --fix-agents)"));
|
|
17543
17688
|
issues++;
|
|
17544
17689
|
}
|
|
17690
|
+
const agMcpFile = path18.join(HOME, ".gemini", "config", "mcp_config.json");
|
|
17545
17691
|
const agentChecks = [
|
|
17546
|
-
{ name: "claude desktop mcp", ok: readMcpHyv(
|
|
17547
|
-
{ name: "cursor mcp", ok: readMcpHyv(
|
|
17548
|
-
{ name: "cursor rule", ok:
|
|
17549
|
-
{ name: "
|
|
17550
|
-
{ name: "
|
|
17551
|
-
{ name: "
|
|
17552
|
-
{ name: "
|
|
17692
|
+
{ name: "claude desktop mcp", ok: readMcpHyv(path18.join(claudeDesktopDir(), "claude_desktop_config.json")) },
|
|
17693
|
+
{ name: "cursor mcp", ok: readMcpHyv(path18.join(HOME, ".cursor", "mcp.json")) },
|
|
17694
|
+
{ name: "cursor rule", ok: fs19.existsSync(cursorRule) },
|
|
17695
|
+
{ name: "antigravity mcp", ok: readMcpHyv(agMcpFile) },
|
|
17696
|
+
{ name: "opencode mcp", ok: readOpencodeHyv() },
|
|
17697
|
+
{ name: "opencode agents", ok: fs19.existsSync(opencodeAgentsPath()) && fs19.readFileSync(opencodeAgentsPath(), "utf-8").includes("hyv") },
|
|
17698
|
+
{ name: "windsurf rule", ok: Boolean(windsurfRulePath()) },
|
|
17699
|
+
{ name: "claude code command", ok: fs19.existsSync(path18.join(HOME, ".claude", "commands", "hyv.md")) },
|
|
17700
|
+
{ name: "claude code skill", ok: fs19.existsSync(path18.join(HOME, ".claude", "skills", "hold-your-voice", "SKILL.md")) },
|
|
17701
|
+
{ name: "codex agents", ok: fs19.existsSync(path18.join(HOME, ".codex", "AGENTS.md")) && fs19.readFileSync(path18.join(HOME, ".codex", "AGENTS.md"), "utf-8").includes("hyv") },
|
|
17702
|
+
{ name: "command code skill", ok: fs19.existsSync(path18.join(HOME, ".commandcode", "skills", "hyv", "SKILL.md")) },
|
|
17703
|
+
{ name: "chatgpt connector guide", ok: fs19.existsSync(path18.join(HOME, ".chatgpt", "hyv-mcp-connector.txt")) }
|
|
17553
17704
|
];
|
|
17554
17705
|
for (const agent of agentChecks) {
|
|
17555
17706
|
if (agent.ok) {
|
|
@@ -17560,8 +17711,8 @@ function registerDoctorCommand(program3) {
|
|
|
17560
17711
|
}
|
|
17561
17712
|
if (opts.fixAgents) {
|
|
17562
17713
|
try {
|
|
17563
|
-
const pkgDir =
|
|
17564
|
-
const { setupAgents } = require(
|
|
17714
|
+
const pkgDir = path18.resolve(__dirname, "..");
|
|
17715
|
+
const { setupAgents } = require(path18.join(pkgDir, "scripts", "postinstall-lib.js"));
|
|
17565
17716
|
const result = setupAgents({ pkgDir, quiet: true });
|
|
17566
17717
|
console.log(import_chalk18.default.green(` \u2713 re-ran agent setup (${result.configured.join(", ") || "no changes"})`));
|
|
17567
17718
|
if (result.warnings.length) {
|
|
@@ -17573,8 +17724,8 @@ function registerDoctorCommand(program3) {
|
|
|
17573
17724
|
}
|
|
17574
17725
|
}
|
|
17575
17726
|
console.log(import_chalk18.default.dim("checking mcp server..."));
|
|
17576
|
-
const claudeMcp = readMcpHyv(
|
|
17577
|
-
const cursorMcp = readMcpHyv(
|
|
17727
|
+
const claudeMcp = readMcpHyv(path18.join(claudeDesktopDir(), "claude_desktop_config.json"));
|
|
17728
|
+
const cursorMcp = readMcpHyv(path18.join(HOME, ".cursor", "mcp.json"));
|
|
17578
17729
|
if (claudeMcp || cursorMcp) {
|
|
17579
17730
|
if (claudeMcp)
|
|
17580
17731
|
console.log(import_chalk18.default.green(" \u2713 mcp configured for claude desktop"));
|
|
@@ -17600,6 +17751,31 @@ function registerDoctorCommand(program3) {
|
|
|
17600
17751
|
console.log(import_chalk18.default.red(` \u2717 mcp stdio probe failed: ${err.message}`));
|
|
17601
17752
|
issues++;
|
|
17602
17753
|
}
|
|
17754
|
+
if (opts.verifyHosts) {
|
|
17755
|
+
console.log(import_chalk18.default.dim("verifying mcp hosts (spawns subprocess per config)..."));
|
|
17756
|
+
try {
|
|
17757
|
+
const pkgDir = path18.resolve(__dirname, "..");
|
|
17758
|
+
const { verifyAgentHosts } = require(path18.join(pkgDir, "scripts", "verify-agent-hosts.js"));
|
|
17759
|
+
const hosts = await verifyAgentHosts();
|
|
17760
|
+
for (const host of hosts) {
|
|
17761
|
+
if (host.kind === "manual") {
|
|
17762
|
+
console.log(import_chalk18.default.yellow(` \u25CB ${host.label} \u2014 ${host.detail}`));
|
|
17763
|
+
continue;
|
|
17764
|
+
}
|
|
17765
|
+
if (host.ok) {
|
|
17766
|
+
console.log(import_chalk18.default.green(` \u2713 ${host.label}${host.detail ? ` (${host.detail})` : ""}`));
|
|
17767
|
+
} else if (host.kind === "file") {
|
|
17768
|
+
console.log(import_chalk18.default.dim(` - ${host.label} \u2014 ${host.detail || "missing"}`));
|
|
17769
|
+
} else {
|
|
17770
|
+
console.log(import_chalk18.default.red(` \u2717 ${host.label} \u2014 ${host.detail || "failed"}`));
|
|
17771
|
+
issues++;
|
|
17772
|
+
}
|
|
17773
|
+
}
|
|
17774
|
+
} catch (err) {
|
|
17775
|
+
console.log(import_chalk18.default.red(` \u2717 host verification failed: ${err.message}`));
|
|
17776
|
+
issues++;
|
|
17777
|
+
}
|
|
17778
|
+
}
|
|
17603
17779
|
console.log("");
|
|
17604
17780
|
if (issues === 0 && fixed === 0) {
|
|
17605
17781
|
console.log(import_chalk18.default.green("\u2713 everything looks good!"));
|
|
@@ -17683,8 +17859,8 @@ init_access();
|
|
|
17683
17859
|
init_config();
|
|
17684
17860
|
|
|
17685
17861
|
// src/lib/destructive-write.ts
|
|
17686
|
-
var
|
|
17687
|
-
var
|
|
17862
|
+
var fs20 = __toESM(require("fs"));
|
|
17863
|
+
var path19 = __toESM(require("path"));
|
|
17688
17864
|
var readline2 = __toESM(require("readline"));
|
|
17689
17865
|
var import_chalk20 = __toESM(require_source());
|
|
17690
17866
|
async function confirmDestructiveWrite(options) {
|
|
@@ -17710,12 +17886,12 @@ A .bak backup will be created. Proceed? [y/N] `;
|
|
|
17710
17886
|
}
|
|
17711
17887
|
function writeInPlaceWithBackup(filePath, content) {
|
|
17712
17888
|
const backupPath = filePath + ".bak";
|
|
17713
|
-
|
|
17714
|
-
|
|
17889
|
+
fs20.copyFileSync(filePath, backupPath);
|
|
17890
|
+
fs20.writeFileSync(filePath, content);
|
|
17715
17891
|
return backupPath;
|
|
17716
17892
|
}
|
|
17717
17893
|
function backupBasename(filePath) {
|
|
17718
|
-
return
|
|
17894
|
+
return path19.basename(filePath) + ".bak";
|
|
17719
17895
|
}
|
|
17720
17896
|
|
|
17721
17897
|
// src/commands/fix.ts
|
|
@@ -17809,19 +17985,19 @@ function registerCheckCommand(program3) {
|
|
|
17809
17985
|
const profile = await loadProfileForCommand(options.profile);
|
|
17810
17986
|
let inputText = text;
|
|
17811
17987
|
if (text === "-") {
|
|
17812
|
-
const
|
|
17988
|
+
const fs31 = require("fs");
|
|
17813
17989
|
if (process.stdin.isTTY) {
|
|
17814
17990
|
console.error(import_chalk22.default.red("No input provided. Pipe content or pass text as argument."));
|
|
17815
17991
|
process.exit(1);
|
|
17816
17992
|
}
|
|
17817
|
-
inputText =
|
|
17993
|
+
inputText = fs31.readFileSync(0, "utf-8");
|
|
17818
17994
|
}
|
|
17819
17995
|
if (!inputText.trim()) {
|
|
17820
17996
|
console.error(import_chalk22.default.red("No text provided."));
|
|
17821
17997
|
process.exit(1);
|
|
17822
17998
|
}
|
|
17823
|
-
const
|
|
17824
|
-
if (text !== "-" &&
|
|
17999
|
+
const fs30 = require("fs");
|
|
18000
|
+
if (text !== "-" && fs30.existsSync(text)) {
|
|
17825
18001
|
console.log(import_chalk22.default.yellow(`"${text}" looks like a file. Did you mean: hyv scan ${text}`));
|
|
17826
18002
|
process.exit(1);
|
|
17827
18003
|
}
|
|
@@ -17948,12 +18124,12 @@ function registerDiffCommand(program3) {
|
|
|
17948
18124
|
${result.changes.length} auto-fix${result.changes.length === 1 ? "" : "es"} available`));
|
|
17949
18125
|
console.log(import_chalk24.default.dim(` run: hyv fix ${file} -i to apply`));
|
|
17950
18126
|
if (options.apply && filePath !== "stdin") {
|
|
17951
|
-
const
|
|
17952
|
-
const
|
|
18127
|
+
const fs30 = require("fs");
|
|
18128
|
+
const path27 = require("path");
|
|
17953
18129
|
const backupPath = filePath + ".bak";
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
console.log(import_chalk24.default.green(` \u2713 Applied. Backup: ${
|
|
18130
|
+
fs30.copyFileSync(filePath, backupPath);
|
|
18131
|
+
fs30.writeFileSync(filePath, result.fixed);
|
|
18132
|
+
console.log(import_chalk24.default.green(` \u2713 Applied. Backup: ${path27.basename(backupPath)}`));
|
|
17957
18133
|
}
|
|
17958
18134
|
} catch (error) {
|
|
17959
18135
|
console.error(import_chalk24.default.red(`Error: ${error.message}`));
|
|
@@ -18128,8 +18304,8 @@ function registerRulesCommand(program3) {
|
|
|
18128
18304
|
|
|
18129
18305
|
// src/commands/batch.ts
|
|
18130
18306
|
var import_chalk26 = __toESM(require_source());
|
|
18131
|
-
var
|
|
18132
|
-
var
|
|
18307
|
+
var fs21 = __toESM(require("fs"));
|
|
18308
|
+
var path20 = __toESM(require("path"));
|
|
18133
18309
|
init_pipeline();
|
|
18134
18310
|
init_local_profile();
|
|
18135
18311
|
function registerBatchCommand(program3) {
|
|
@@ -18162,10 +18338,10 @@ No files matching: ${pattern}`));
|
|
|
18162
18338
|
}
|
|
18163
18339
|
const results = [];
|
|
18164
18340
|
for (const file of files) {
|
|
18165
|
-
const absPath =
|
|
18166
|
-
if (!
|
|
18341
|
+
const absPath = path20.resolve(file);
|
|
18342
|
+
if (!fs21.existsSync(absPath))
|
|
18167
18343
|
continue;
|
|
18168
|
-
const text =
|
|
18344
|
+
const text = fs21.readFileSync(absPath, "utf-8");
|
|
18169
18345
|
const result = runPipeline(text, profile, options.fix || false);
|
|
18170
18346
|
results.push({
|
|
18171
18347
|
file,
|
|
@@ -18231,16 +18407,16 @@ No files matching: ${pattern}`));
|
|
|
18231
18407
|
|
|
18232
18408
|
// src/commands/watch.ts
|
|
18233
18409
|
var import_chalk27 = __toESM(require_source());
|
|
18234
|
-
var
|
|
18235
|
-
var
|
|
18410
|
+
var fs22 = __toESM(require("fs"));
|
|
18411
|
+
var path21 = __toESM(require("path"));
|
|
18236
18412
|
init_pipeline();
|
|
18237
18413
|
init_local_profile();
|
|
18238
18414
|
function registerWatchCommand(program3) {
|
|
18239
18415
|
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) => {
|
|
18240
18416
|
try {
|
|
18241
18417
|
const profile = await loadProfileForCommand(options.profile);
|
|
18242
|
-
const absPath =
|
|
18243
|
-
if (!
|
|
18418
|
+
const absPath = path21.resolve(file);
|
|
18419
|
+
if (!fs22.existsSync(absPath)) {
|
|
18244
18420
|
console.error(import_chalk27.default.red(`File not found: ${absPath}`));
|
|
18245
18421
|
process.exit(1);
|
|
18246
18422
|
}
|
|
@@ -18263,7 +18439,7 @@ watching ${absPath}`));
|
|
|
18263
18439
|
let lastScore = 0;
|
|
18264
18440
|
let ignoreWatchUntil = 0;
|
|
18265
18441
|
const runScan = () => {
|
|
18266
|
-
const text =
|
|
18442
|
+
const text = fs22.readFileSync(absPath, "utf-8");
|
|
18267
18443
|
const result = runPipeline(text, profile, options.command === "fix");
|
|
18268
18444
|
scanCount++;
|
|
18269
18445
|
const now = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false });
|
|
@@ -18305,7 +18481,7 @@ watching ${absPath}`));
|
|
|
18305
18481
|
console.log("");
|
|
18306
18482
|
};
|
|
18307
18483
|
runScan();
|
|
18308
|
-
|
|
18484
|
+
fs22.watch(absPath, (eventType) => {
|
|
18309
18485
|
if (eventType !== "change")
|
|
18310
18486
|
return;
|
|
18311
18487
|
if (Date.now() < ignoreWatchUntil)
|
|
@@ -18330,7 +18506,7 @@ watching ${absPath}`));
|
|
|
18330
18506
|
|
|
18331
18507
|
// src/commands/demo.ts
|
|
18332
18508
|
var import_chalk28 = __toESM(require_source());
|
|
18333
|
-
var
|
|
18509
|
+
var fs23 = __toESM(require("fs"));
|
|
18334
18510
|
var SAMPLES = {
|
|
18335
18511
|
linkedin: {
|
|
18336
18512
|
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.
|
|
@@ -18425,7 +18601,7 @@ function registerDemoCommand(program3) {
|
|
|
18425
18601
|
}
|
|
18426
18602
|
if (options.output) {
|
|
18427
18603
|
const outputPath = require("path").resolve(options.output);
|
|
18428
|
-
|
|
18604
|
+
fs23.writeFileSync(outputPath, sample.text);
|
|
18429
18605
|
console.log(import_chalk28.default.green(`
|
|
18430
18606
|
\u2713 Sample written to ${outputPath}`));
|
|
18431
18607
|
if (sample.patterns.length > 0) {
|
|
@@ -18461,11 +18637,11 @@ function registerDemoCommand(program3) {
|
|
|
18461
18637
|
// src/commands/open.ts
|
|
18462
18638
|
var import_chalk29 = __toESM(require_source());
|
|
18463
18639
|
var PAGES = {
|
|
18464
|
-
dashboard: "https://holdyourvoice.com/
|
|
18465
|
-
profiles: "https://holdyourvoice.com/
|
|
18466
|
-
pricing: "https://holdyourvoice.com/
|
|
18467
|
-
settings: "https://holdyourvoice.com/
|
|
18468
|
-
billing: "https://holdyourvoice.com/
|
|
18640
|
+
dashboard: "https://holdyourvoice.com/dashboard",
|
|
18641
|
+
profiles: "https://holdyourvoice.com/dashboard?tab=profiles",
|
|
18642
|
+
pricing: "https://holdyourvoice.com/dashboard?tab=billing",
|
|
18643
|
+
settings: "https://holdyourvoice.com/dashboard",
|
|
18644
|
+
billing: "https://holdyourvoice.com/dashboard?tab=billing"
|
|
18469
18645
|
};
|
|
18470
18646
|
function registerOpenCommand(program3) {
|
|
18471
18647
|
program3.command("open").description("Open the web dashboard in your browser").option("--page <path>", "Page: dashboard, profiles, pricing, settings", "dashboard").option("--profile <name>", "Deep-link to a specific profile").option("--no-browser", "Print URL only, don't open").action(async (options) => {
|
|
@@ -18492,22 +18668,22 @@ function registerOpenCommand(program3) {
|
|
|
18492
18668
|
init_welcome();
|
|
18493
18669
|
|
|
18494
18670
|
// src/lib/onboarding.ts
|
|
18495
|
-
var
|
|
18496
|
-
var
|
|
18497
|
-
var
|
|
18498
|
-
var hyvDir =
|
|
18499
|
-
var onboardingFile =
|
|
18671
|
+
var fs24 = __toESM(require("fs"));
|
|
18672
|
+
var path22 = __toESM(require("path"));
|
|
18673
|
+
var os10 = __toESM(require("os"));
|
|
18674
|
+
var hyvDir = path22.join(os10.homedir(), ".hyv");
|
|
18675
|
+
var onboardingFile = path22.join(hyvDir, "onboarding-complete.json");
|
|
18500
18676
|
function hasCompletedOnboarding() {
|
|
18501
18677
|
try {
|
|
18502
|
-
return
|
|
18678
|
+
return fs24.existsSync(onboardingFile);
|
|
18503
18679
|
} catch {
|
|
18504
18680
|
return false;
|
|
18505
18681
|
}
|
|
18506
18682
|
}
|
|
18507
18683
|
function markOnboardingComplete(version) {
|
|
18508
|
-
if (!
|
|
18509
|
-
|
|
18510
|
-
|
|
18684
|
+
if (!fs24.existsSync(hyvDir))
|
|
18685
|
+
fs24.mkdirSync(hyvDir, { recursive: true });
|
|
18686
|
+
fs24.writeFileSync(
|
|
18511
18687
|
onboardingFile,
|
|
18512
18688
|
JSON.stringify({ version, completed_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
|
|
18513
18689
|
);
|
|
@@ -18515,13 +18691,13 @@ function markOnboardingComplete(version) {
|
|
|
18515
18691
|
|
|
18516
18692
|
// src/commands/welcome.ts
|
|
18517
18693
|
init_welcome_flow();
|
|
18518
|
-
var
|
|
18519
|
-
var
|
|
18694
|
+
var fs25 = __toESM(require("fs"));
|
|
18695
|
+
var path23 = __toESM(require("path"));
|
|
18520
18696
|
function registerWelcomeCommand(program3) {
|
|
18521
18697
|
const pkgVersion3 = (() => {
|
|
18522
18698
|
try {
|
|
18523
|
-
const pkgPath3 =
|
|
18524
|
-
return JSON.parse(
|
|
18699
|
+
const pkgPath3 = path23.resolve(__dirname, "..", "package.json");
|
|
18700
|
+
return JSON.parse(fs25.readFileSync(pkgPath3, "utf-8")).version;
|
|
18525
18701
|
} catch {
|
|
18526
18702
|
return "0.0.0";
|
|
18527
18703
|
}
|
|
@@ -18702,9 +18878,9 @@ Current: ${getEngineLabel()}
|
|
|
18702
18878
|
}
|
|
18703
18879
|
|
|
18704
18880
|
// src/mcp.ts
|
|
18705
|
-
var
|
|
18706
|
-
var
|
|
18707
|
-
var
|
|
18881
|
+
var fs26 = __toESM(require("fs"));
|
|
18882
|
+
var path24 = __toESM(require("path"));
|
|
18883
|
+
var os11 = __toESM(require("os"));
|
|
18708
18884
|
init_classifier();
|
|
18709
18885
|
init_autofix();
|
|
18710
18886
|
init_validator();
|
|
@@ -18715,20 +18891,20 @@ init_welcome();
|
|
|
18715
18891
|
init_config();
|
|
18716
18892
|
init_telemetry();
|
|
18717
18893
|
init_access();
|
|
18718
|
-
var VOICE_MD =
|
|
18894
|
+
var VOICE_MD = path24.join(os11.homedir(), ".hyv", "voice.md");
|
|
18719
18895
|
var MAX_RESPONSE_CHARS = 12e4;
|
|
18720
18896
|
var MAX_SCAN_FILE_BYTES = 2 * 1024 * 1024;
|
|
18721
18897
|
function readScanFile(filePath) {
|
|
18722
|
-
const cwdReal =
|
|
18723
|
-
const resolved =
|
|
18724
|
-
if (!resolved.startsWith(cwdReal +
|
|
18898
|
+
const cwdReal = fs26.realpathSync(process.cwd());
|
|
18899
|
+
const resolved = fs26.realpathSync(path24.resolve(filePath));
|
|
18900
|
+
if (!resolved.startsWith(cwdReal + path24.sep) && resolved !== cwdReal) {
|
|
18725
18901
|
throw new Error(`file must be in the current working directory (${cwdReal})`);
|
|
18726
18902
|
}
|
|
18727
|
-
const stat =
|
|
18903
|
+
const stat = fs26.statSync(resolved);
|
|
18728
18904
|
if (stat.size > MAX_SCAN_FILE_BYTES) {
|
|
18729
18905
|
throw new Error(`file too large (max ${MAX_SCAN_FILE_BYTES} bytes)`);
|
|
18730
18906
|
}
|
|
18731
|
-
return
|
|
18907
|
+
return fs26.readFileSync(resolved, "utf-8");
|
|
18732
18908
|
}
|
|
18733
18909
|
function toolResultPayload(result) {
|
|
18734
18910
|
const isError = result.startsWith("Error:") || result.startsWith("Unknown tool:");
|
|
@@ -18737,10 +18913,10 @@ function toolResultPayload(result) {
|
|
|
18737
18913
|
...isError ? { isError: true } : {}
|
|
18738
18914
|
};
|
|
18739
18915
|
}
|
|
18740
|
-
var pkgPath =
|
|
18916
|
+
var pkgPath = path24.resolve(__dirname, "..", "package.json");
|
|
18741
18917
|
var pkgVersion = (() => {
|
|
18742
18918
|
try {
|
|
18743
|
-
return JSON.parse(
|
|
18919
|
+
return JSON.parse(fs26.readFileSync(pkgPath, "utf-8")).version;
|
|
18744
18920
|
} catch {
|
|
18745
18921
|
return "2.7.1";
|
|
18746
18922
|
}
|
|
@@ -19321,7 +19497,7 @@ async function handleRequest(line) {
|
|
|
19321
19497
|
}
|
|
19322
19498
|
async function startMcpServer() {
|
|
19323
19499
|
const access = await getAccessState().catch(() => null);
|
|
19324
|
-
if (
|
|
19500
|
+
if (fs26.existsSync(VOICE_MD)) {
|
|
19325
19501
|
mcpLog("info", `voice profile: ${VOICE_MD}`);
|
|
19326
19502
|
} else {
|
|
19327
19503
|
mcpLog("info", "free local engine ready \u2014 no voice profile yet");
|
|
@@ -19354,18 +19530,18 @@ async function startMcpServer() {
|
|
|
19354
19530
|
|
|
19355
19531
|
// src/lib/mcp-setup.ts
|
|
19356
19532
|
var import_chalk32 = __toESM(require_source());
|
|
19357
|
-
var
|
|
19358
|
-
var
|
|
19359
|
-
var
|
|
19533
|
+
var fs27 = __toESM(require("fs"));
|
|
19534
|
+
var path25 = __toESM(require("path"));
|
|
19535
|
+
var os12 = __toESM(require("os"));
|
|
19360
19536
|
init_version();
|
|
19361
|
-
var HOME2 =
|
|
19537
|
+
var HOME2 = os12.homedir();
|
|
19362
19538
|
var IS_WIN2 = process.platform === "win32";
|
|
19363
19539
|
function claudeDesktopConfigPath() {
|
|
19364
19540
|
if (IS_WIN2)
|
|
19365
|
-
return
|
|
19541
|
+
return path25.join(HOME2, "AppData", "Roaming", "Claude", "claude_desktop_config.json");
|
|
19366
19542
|
if (process.platform === "linux")
|
|
19367
|
-
return
|
|
19368
|
-
return
|
|
19543
|
+
return path25.join(HOME2, ".config", "Claude", "claude_desktop_config.json");
|
|
19544
|
+
return path25.join(HOME2, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
19369
19545
|
}
|
|
19370
19546
|
function printMcpSetup() {
|
|
19371
19547
|
console.log(import_chalk32.default.bold("\nhold your voice \u2014 mcp setup\n"));
|
|
@@ -19388,8 +19564,16 @@ function printMcpSetup() {
|
|
|
19388
19564
|
console.log(import_chalk32.default.dim(" Instructions: ~/.codex/AGENTS.md (merged on install)\n"));
|
|
19389
19565
|
console.log(import_chalk32.default.bold("Command Code"));
|
|
19390
19566
|
console.log(import_chalk32.default.dim(" Skill: ~/.commandcode/skills/hyv/SKILL.md\n"));
|
|
19391
|
-
console.log(import_chalk32.default.bold("ChatGPT"));
|
|
19567
|
+
console.log(import_chalk32.default.bold("ChatGPT Desktop (manual connector)"));
|
|
19568
|
+
console.log(import_chalk32.default.dim(" Settings \u2192 Connectors \u2192 add connector"));
|
|
19569
|
+
console.log(import_chalk32.default.dim(" Name: hold your voice | Command: hyv | Arguments: mcp"));
|
|
19570
|
+
console.log(import_chalk32.default.dim(" Guide: ~/.chatgpt/hyv-mcp-connector.txt (after hyv doctor --fix-agents)"));
|
|
19392
19571
|
console.log(import_chalk32.default.dim(" hyv mcp --setup-chatgpt\n"));
|
|
19572
|
+
console.log(import_chalk32.default.bold("Antigravity"));
|
|
19573
|
+
console.log(import_chalk32.default.dim(" MCP: ~/.gemini/config/mcp_config.json \u2192 mcpServers.hyv (auto via postinstall)\n"));
|
|
19574
|
+
console.log(import_chalk32.default.bold("OpenCode"));
|
|
19575
|
+
console.log(import_chalk32.default.dim(" MCP: ~/.config/opencode/opencode.jsonc \u2192 mcp.hyv (auto via postinstall)"));
|
|
19576
|
+
console.log(import_chalk32.default.dim(" Rules: ~/.config/opencode/AGENTS.md\n"));
|
|
19393
19577
|
console.log(import_chalk32.default.bold("Auto-configure"));
|
|
19394
19578
|
console.log(import_chalk32.default.dim(" hyv doctor --fix-agents"));
|
|
19395
19579
|
console.log(import_chalk32.default.dim(" HYV_AUTO_CONFIGURE_AGENTS=0 npm i -g @holdyourvoice/hyv (skip)\n"));
|
|
@@ -19447,8 +19631,8 @@ async function runMcpSelfTest() {
|
|
|
19447
19631
|
console.log(import_chalk32.default.red(` \u2717 hyv_demo failed: ${e.message}`));
|
|
19448
19632
|
failed++;
|
|
19449
19633
|
}
|
|
19450
|
-
const voiceMd =
|
|
19451
|
-
if (
|
|
19634
|
+
const voiceMd = path25.join(HOME2, ".hyv", "voice.md");
|
|
19635
|
+
if (fs27.existsSync(voiceMd)) {
|
|
19452
19636
|
console.log(import_chalk32.default.green(" \u2713 voice profile found"));
|
|
19453
19637
|
passed++;
|
|
19454
19638
|
} else {
|
|
@@ -19488,7 +19672,7 @@ async function runMcpSelfTest() {
|
|
|
19488
19672
|
}
|
|
19489
19673
|
|
|
19490
19674
|
// src/commands/export.ts
|
|
19491
|
-
var
|
|
19675
|
+
var fs28 = __toESM(require("fs"));
|
|
19492
19676
|
init_api();
|
|
19493
19677
|
var FORMATS = {
|
|
19494
19678
|
claude: {
|
|
@@ -19562,7 +19746,7 @@ async function exportCommand(format, opts) {
|
|
|
19562
19746
|
} else {
|
|
19563
19747
|
console.log(`
|
|
19564
19748
|
${c.red("\u2717")} no voice profiles found`);
|
|
19565
|
-
console.log(` ${c.dim("create one at")} ${c.cyan("https://holdyourvoice.com/
|
|
19749
|
+
console.log(` ${c.dim("create one at")} ${c.cyan("https://holdyourvoice.com/dashboard")}`);
|
|
19566
19750
|
}
|
|
19567
19751
|
process.exit(1);
|
|
19568
19752
|
return;
|
|
@@ -19575,7 +19759,7 @@ async function exportCommand(format, opts) {
|
|
|
19575
19759
|
const prompt = fmt.wrap(detail.profile, detail.body);
|
|
19576
19760
|
if (opts.output) {
|
|
19577
19761
|
const outFile = opts.output.replace("{name}", profile.slug || profile.name);
|
|
19578
|
-
|
|
19762
|
+
fs28.writeFileSync(outFile, prompt);
|
|
19579
19763
|
results.push({ profile: profile.name, file: outFile });
|
|
19580
19764
|
} else {
|
|
19581
19765
|
results.push({ profile: profile.name, prompt });
|
|
@@ -19612,13 +19796,13 @@ async function exportCommand(format, opts) {
|
|
|
19612
19796
|
// src/index.ts
|
|
19613
19797
|
init_access();
|
|
19614
19798
|
init_welcome();
|
|
19615
|
-
var
|
|
19616
|
-
var
|
|
19799
|
+
var fs29 = __toESM(require("fs"));
|
|
19800
|
+
var path26 = __toESM(require("path"));
|
|
19617
19801
|
var program2 = new Command();
|
|
19618
|
-
var pkgPath2 =
|
|
19802
|
+
var pkgPath2 = path26.resolve(__dirname, "..", "package.json");
|
|
19619
19803
|
var pkgVersion2 = (() => {
|
|
19620
19804
|
try {
|
|
19621
|
-
return JSON.parse(
|
|
19805
|
+
return JSON.parse(fs29.readFileSync(pkgPath2, "utf-8")).version;
|
|
19622
19806
|
} catch {
|
|
19623
19807
|
return "2.7.1";
|
|
19624
19808
|
}
|
|
@@ -19662,15 +19846,24 @@ program2.command("mcp").description("Start MCP server (for Claude Desktop and ot
|
|
|
19662
19846
|
return;
|
|
19663
19847
|
}
|
|
19664
19848
|
if (opts.setupChatgpt) {
|
|
19665
|
-
|
|
19666
|
-
|
|
19667
|
-
console.log(import_chalk33.default.
|
|
19668
|
-
console.log(
|
|
19669
|
-
console.log(import_chalk33.default.dim("
|
|
19670
|
-
console.log(import_chalk33.default.dim("
|
|
19849
|
+
const home = require("os").homedir();
|
|
19850
|
+
const guide = require("path").join(home, ".chatgpt", "hyv-mcp-connector.txt");
|
|
19851
|
+
console.log(import_chalk33.default.bold("\nhold your voice \u2014 chatgpt desktop mcp setup\n"));
|
|
19852
|
+
console.log("ChatGPT has no auto-config file. Add this connector once in the desktop app:\n");
|
|
19853
|
+
console.log(import_chalk33.default.dim(" 1. Install hyv: ") + import_chalk33.default.cyan("npm i -g @holdyourvoice/hyv@latest && hyv welcome"));
|
|
19854
|
+
console.log(import_chalk33.default.dim(" 2. Open ") + import_chalk33.default.cyan("https://chatgpt.com/#settings/Connectors"));
|
|
19855
|
+
console.log(import_chalk33.default.dim(" 3. Add connector"));
|
|
19856
|
+
console.log(import_chalk33.default.dim(" 4. Name: ") + import_chalk33.default.cyan("hold your voice"));
|
|
19857
|
+
console.log(import_chalk33.default.dim(" 5. Command: ") + import_chalk33.default.cyan("hyv"));
|
|
19858
|
+
console.log(import_chalk33.default.dim(" 6. Arguments: ") + import_chalk33.default.cyan("mcp"));
|
|
19859
|
+
console.log(import_chalk33.default.dim(" 7. Save, restart ChatGPT Desktop, ask: scan this with hold your voice"));
|
|
19671
19860
|
console.log("");
|
|
19672
|
-
|
|
19673
|
-
|
|
19861
|
+
if (require("fs").existsSync(guide)) {
|
|
19862
|
+
console.log(import_chalk33.default.dim(`Full guide written to: ${guide}`));
|
|
19863
|
+
} else {
|
|
19864
|
+
console.log(import_chalk33.default.dim("Run hyv doctor --fix-agents to write ~/.chatgpt/hyv-mcp-connector.txt"));
|
|
19865
|
+
}
|
|
19866
|
+
console.log(import_chalk33.default.dim("\nBrowser chatgpt cannot use local MCP \u2014 desktop app only."));
|
|
19674
19867
|
return;
|
|
19675
19868
|
}
|
|
19676
19869
|
startMcpServer();
|