threadnote 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp_server.cjs +52 -16
- package/dist/threadnote.cjs +90 -24
- package/docs/troubleshooting.md +11 -3
- package/package.json +1 -1
- package/scripts/install.sh +5 -1
package/dist/mcp_server.cjs
CHANGED
|
@@ -33081,7 +33081,6 @@ var StreamableHTTPClientTransport = class {
|
|
|
33081
33081
|
|
|
33082
33082
|
// src/mcp_server.ts
|
|
33083
33083
|
var import_promises5 = require("node:fs/promises");
|
|
33084
|
-
var import_node_os3 = require("node:os");
|
|
33085
33084
|
var import_node_path5 = require("node:path");
|
|
33086
33085
|
|
|
33087
33086
|
// src/constants.ts
|
|
@@ -35724,6 +35723,7 @@ var jsYaml = {
|
|
|
35724
35723
|
// src/utils.ts
|
|
35725
35724
|
var import_node_child_process = require("node:child_process");
|
|
35726
35725
|
var import_node_crypto = require("node:crypto");
|
|
35726
|
+
var import_node_fs = require("node:fs");
|
|
35727
35727
|
var import_promises = require("node:fs/promises");
|
|
35728
35728
|
var import_node_os = require("node:os");
|
|
35729
35729
|
var import_node_path = require("node:path");
|
|
@@ -35778,18 +35778,57 @@ function redactText(content) {
|
|
|
35778
35778
|
).replace(/Bearer\s+[A-Za-z0-9._~+/=-]+/gi, "Bearer [REDACTED]").replace(/sk-[A-Za-z0-9_-]{16,}/g, "sk-[REDACTED]").replace(/gh[pousr]_[A-Za-z0-9_]{16,}/g, "gh_[REDACTED]");
|
|
35779
35779
|
}
|
|
35780
35780
|
async function requiredOpenVikingCli() {
|
|
35781
|
-
const command2 = await
|
|
35781
|
+
const command2 = await findOpenVikingCli();
|
|
35782
35782
|
if (!command2) {
|
|
35783
|
-
throw new Error(
|
|
35783
|
+
throw new Error(
|
|
35784
|
+
"Neither ov nor openviking was found in PATH, uv tool bin dir, $UV_TOOL_BIN_DIR, or ~/.local/bin. Run threadnote install first."
|
|
35785
|
+
);
|
|
35784
35786
|
}
|
|
35785
35787
|
return command2;
|
|
35786
35788
|
}
|
|
35787
35789
|
async function openVikingCliForMode(dryRun) {
|
|
35788
35790
|
if (dryRun) {
|
|
35789
|
-
return await
|
|
35791
|
+
return await findOpenVikingCli() ?? "ov";
|
|
35790
35792
|
}
|
|
35791
35793
|
return requiredOpenVikingCli();
|
|
35792
35794
|
}
|
|
35795
|
+
async function findOpenVikingCli() {
|
|
35796
|
+
const override = process.env.THREADNOTE_OV?.trim();
|
|
35797
|
+
if (override) {
|
|
35798
|
+
return override;
|
|
35799
|
+
}
|
|
35800
|
+
const onPath = await findExecutable(["ov", "openviking"]);
|
|
35801
|
+
if (onPath) {
|
|
35802
|
+
return onPath;
|
|
35803
|
+
}
|
|
35804
|
+
for (const candidateDir of await openVikingToolCandidateDirs()) {
|
|
35805
|
+
for (const command2 of ["ov", "openviking"]) {
|
|
35806
|
+
const candidate = (0, import_node_path.join)(candidateDir, command2);
|
|
35807
|
+
if (await isExecutable(candidate)) {
|
|
35808
|
+
return candidate;
|
|
35809
|
+
}
|
|
35810
|
+
}
|
|
35811
|
+
}
|
|
35812
|
+
return void 0;
|
|
35813
|
+
}
|
|
35814
|
+
async function openVikingToolCandidateDirs() {
|
|
35815
|
+
const dirs = [];
|
|
35816
|
+
const uv = await findExecutable(["uv"]);
|
|
35817
|
+
if (uv) {
|
|
35818
|
+
const result = await runCommand(uv, ["tool", "dir", "--bin"], { allowFailure: true });
|
|
35819
|
+
if (result.exitCode === 0) {
|
|
35820
|
+
const dir = result.stdout.trim();
|
|
35821
|
+
if (dir) {
|
|
35822
|
+
dirs.push(dir);
|
|
35823
|
+
}
|
|
35824
|
+
}
|
|
35825
|
+
}
|
|
35826
|
+
if (process.env.UV_TOOL_BIN_DIR) {
|
|
35827
|
+
dirs.push(process.env.UV_TOOL_BIN_DIR);
|
|
35828
|
+
}
|
|
35829
|
+
dirs.push((0, import_node_path.join)((0, import_node_os.homedir)(), ".local", "bin"));
|
|
35830
|
+
return Array.from(new Set(dirs));
|
|
35831
|
+
}
|
|
35793
35832
|
async function requiredExecutable(command2) {
|
|
35794
35833
|
const executable = await findExecutable([command2]);
|
|
35795
35834
|
if (!executable) {
|
|
@@ -35946,6 +35985,14 @@ async function exists(path) {
|
|
|
35946
35985
|
return false;
|
|
35947
35986
|
}
|
|
35948
35987
|
}
|
|
35988
|
+
async function isExecutable(path) {
|
|
35989
|
+
try {
|
|
35990
|
+
await (0, import_promises.access)(path, import_node_fs.constants.X_OK);
|
|
35991
|
+
return true;
|
|
35992
|
+
} catch (_err) {
|
|
35993
|
+
return false;
|
|
35994
|
+
}
|
|
35995
|
+
}
|
|
35949
35996
|
async function isFile(path) {
|
|
35950
35997
|
try {
|
|
35951
35998
|
return (await (0, import_promises.stat)(path)).isFile();
|
|
@@ -40006,23 +40053,12 @@ function withIdentity2(config2, args) {
|
|
|
40006
40053
|
return [...args, "--account", config2.account, "--user", config2.user, "--agent-id", config2.agentId];
|
|
40007
40054
|
}
|
|
40008
40055
|
async function requiredOpenVikingCli2() {
|
|
40009
|
-
const command2 =
|
|
40056
|
+
const command2 = await findOpenVikingCli();
|
|
40010
40057
|
if (!command2) {
|
|
40011
40058
|
throw new Error("Neither ov nor openviking was found. Run threadnote install first.");
|
|
40012
40059
|
}
|
|
40013
40060
|
return command2;
|
|
40014
40061
|
}
|
|
40015
|
-
async function firstExistingPath(paths) {
|
|
40016
|
-
for (const path of paths) {
|
|
40017
|
-
try {
|
|
40018
|
-
await (0, import_promises5.access)(path);
|
|
40019
|
-
return await (0, import_promises5.realpath)(path);
|
|
40020
|
-
} catch (_err) {
|
|
40021
|
-
continue;
|
|
40022
|
-
}
|
|
40023
|
-
}
|
|
40024
|
-
return void 0;
|
|
40025
|
-
}
|
|
40026
40062
|
main().catch((err) => {
|
|
40027
40063
|
process.stderr.write(`${errorMessage(err)}
|
|
40028
40064
|
`);
|
package/dist/threadnote.cjs
CHANGED
|
@@ -3484,7 +3484,7 @@ var PYTHON_SYSTEM_CERTS_PACKAGE = "pip-system-certs";
|
|
|
3484
3484
|
var LAUNCHD_LABEL = "io.threadnote.openviking";
|
|
3485
3485
|
var MAX_SECRET_MATCHES_TO_PRINT = 5;
|
|
3486
3486
|
var START_HEALTH_POLL_INTERVAL_MS = 500;
|
|
3487
|
-
var START_HEALTH_TIMEOUT_MS =
|
|
3487
|
+
var START_HEALTH_TIMEOUT_MS = 6e4;
|
|
3488
3488
|
var SHIM_MARKER = "Generated by threadnote";
|
|
3489
3489
|
var USER_INSTRUCTIONS_START_MARKER = "<!-- BEGIN THREADNOTE USER INSTRUCTIONS -->";
|
|
3490
3490
|
var USER_INSTRUCTIONS_END_MARKER = "<!-- END THREADNOTE USER INSTRUCTIONS -->";
|
|
@@ -3743,18 +3743,57 @@ function escapeRegExp(value) {
|
|
|
3743
3743
|
return value.replace(/[\\^$+?.()|[\]{}]/g, "\\$&");
|
|
3744
3744
|
}
|
|
3745
3745
|
async function requiredOpenVikingCli() {
|
|
3746
|
-
const command2 = await
|
|
3746
|
+
const command2 = await findOpenVikingCli();
|
|
3747
3747
|
if (!command2) {
|
|
3748
|
-
throw new Error(
|
|
3748
|
+
throw new Error(
|
|
3749
|
+
"Neither ov nor openviking was found in PATH, uv tool bin dir, $UV_TOOL_BIN_DIR, or ~/.local/bin. Run threadnote install first."
|
|
3750
|
+
);
|
|
3749
3751
|
}
|
|
3750
3752
|
return command2;
|
|
3751
3753
|
}
|
|
3752
3754
|
async function openVikingCliForMode(dryRun) {
|
|
3753
3755
|
if (dryRun) {
|
|
3754
|
-
return await
|
|
3756
|
+
return await findOpenVikingCli() ?? "ov";
|
|
3755
3757
|
}
|
|
3756
3758
|
return requiredOpenVikingCli();
|
|
3757
3759
|
}
|
|
3760
|
+
async function findOpenVikingCli() {
|
|
3761
|
+
const override = process.env.THREADNOTE_OV?.trim();
|
|
3762
|
+
if (override) {
|
|
3763
|
+
return override;
|
|
3764
|
+
}
|
|
3765
|
+
const onPath = await findExecutable(["ov", "openviking"]);
|
|
3766
|
+
if (onPath) {
|
|
3767
|
+
return onPath;
|
|
3768
|
+
}
|
|
3769
|
+
for (const candidateDir of await openVikingToolCandidateDirs()) {
|
|
3770
|
+
for (const command2 of ["ov", "openviking"]) {
|
|
3771
|
+
const candidate = (0, import_node_path.join)(candidateDir, command2);
|
|
3772
|
+
if (await isExecutable(candidate)) {
|
|
3773
|
+
return candidate;
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
return void 0;
|
|
3778
|
+
}
|
|
3779
|
+
async function openVikingToolCandidateDirs() {
|
|
3780
|
+
const dirs = [];
|
|
3781
|
+
const uv = await findExecutable(["uv"]);
|
|
3782
|
+
if (uv) {
|
|
3783
|
+
const result = await runCommand(uv, ["tool", "dir", "--bin"], { allowFailure: true });
|
|
3784
|
+
if (result.exitCode === 0) {
|
|
3785
|
+
const dir = result.stdout.trim();
|
|
3786
|
+
if (dir) {
|
|
3787
|
+
dirs.push(dir);
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
if (process.env.UV_TOOL_BIN_DIR) {
|
|
3792
|
+
dirs.push(process.env.UV_TOOL_BIN_DIR);
|
|
3793
|
+
}
|
|
3794
|
+
dirs.push((0, import_node_path.join)((0, import_node_os.homedir)(), ".local", "bin"));
|
|
3795
|
+
return Array.from(new Set(dirs));
|
|
3796
|
+
}
|
|
3758
3797
|
async function requiredExecutable(command2) {
|
|
3759
3798
|
const executable = await findExecutable([command2]);
|
|
3760
3799
|
if (!executable) {
|
|
@@ -12381,7 +12420,7 @@ async function maybeRunPostUpdateAfterRepair(config, options) {
|
|
|
12381
12420
|
});
|
|
12382
12421
|
}
|
|
12383
12422
|
async function ensurePinnedOpenVikingInstalled(config, options) {
|
|
12384
|
-
const ov = await
|
|
12423
|
+
const ov = await findOpenVikingCli();
|
|
12385
12424
|
if (!ov) {
|
|
12386
12425
|
return;
|
|
12387
12426
|
}
|
|
@@ -12813,7 +12852,7 @@ async function collectDoctorChecks(config, options = {}) {
|
|
|
12813
12852
|
checks.push(await commandCheck("node", ["--version"]));
|
|
12814
12853
|
checks.push(await commandCheck("python3", ["--version"]));
|
|
12815
12854
|
checks.push(await openVikingServerCheck());
|
|
12816
|
-
checks.push(await
|
|
12855
|
+
checks.push(await openVikingCliCheck());
|
|
12817
12856
|
checks.push(await localEmbeddingCheck());
|
|
12818
12857
|
checks.push(await pythonSystemCertificatesCheck());
|
|
12819
12858
|
checks.push(await firstCommandCheck("python installer", ["pipx", "uv", "pip3"], ["--version"]));
|
|
@@ -13018,9 +13057,9 @@ async function repairManifest(config, dryRun) {
|
|
|
13018
13057
|
}
|
|
13019
13058
|
async function repairRecallIndex(config, dryRun) {
|
|
13020
13059
|
console.log("\nRepairing recall index freshness.");
|
|
13021
|
-
const ov = dryRun ? await
|
|
13060
|
+
const ov = dryRun ? await findOpenVikingCli() ?? "ov" : await findOpenVikingCli();
|
|
13022
13061
|
if (!ov) {
|
|
13023
|
-
console.log("Skipping recall index repair: neither ov nor openviking was found
|
|
13062
|
+
console.log("Skipping recall index repair: neither ov nor openviking was found.");
|
|
13024
13063
|
return;
|
|
13025
13064
|
}
|
|
13026
13065
|
const progress = startProgress("Scanning recall index freshness across memories and seeded resources.");
|
|
@@ -13071,7 +13110,7 @@ async function repairRecallIndex(config, dryRun) {
|
|
|
13071
13110
|
}
|
|
13072
13111
|
}
|
|
13073
13112
|
async function configureOpenVikingCliLanguage(config, dryRun) {
|
|
13074
|
-
const ov = dryRun ? await
|
|
13113
|
+
const ov = dryRun ? await findOpenVikingCli() ?? "ov" : await findOpenVikingCli();
|
|
13075
13114
|
if (!ov) {
|
|
13076
13115
|
return;
|
|
13077
13116
|
}
|
|
@@ -13197,7 +13236,11 @@ async function runStart(config, options) {
|
|
|
13197
13236
|
child.unref();
|
|
13198
13237
|
await (0, import_promises12.writeFile)((0, import_node_path13.join)(config.agentContextHome, "openviking-server.pid"), `${child.pid}
|
|
13199
13238
|
`, "utf8");
|
|
13200
|
-
const health = await waitForOpenVikingHealth(
|
|
13239
|
+
const health = await waitForOpenVikingHealth(
|
|
13240
|
+
config,
|
|
13241
|
+
START_HEALTH_TIMEOUT_MS,
|
|
13242
|
+
`Waiting for OpenViking health at ${healthUrl}.`
|
|
13243
|
+
);
|
|
13201
13244
|
if (health) {
|
|
13202
13245
|
console.log(`Started OpenViking with pid ${child.pid}. Health OK at ${healthUrl}. Logs: ${logPath}`);
|
|
13203
13246
|
return;
|
|
@@ -13308,6 +13351,20 @@ async function firstCommandCheck(name, commands, args) {
|
|
|
13308
13351
|
}
|
|
13309
13352
|
return { name, status: "fail", detail: `none found: ${commands.join(", ")}` };
|
|
13310
13353
|
}
|
|
13354
|
+
async function openVikingCliCheck() {
|
|
13355
|
+
const executable = await findOpenVikingCli();
|
|
13356
|
+
if (!executable) {
|
|
13357
|
+
return { name: "openviking cli", status: "fail", detail: "none found: ov, openviking" };
|
|
13358
|
+
}
|
|
13359
|
+
const result = await runCommand(executable, ["--help"], { allowFailure: true });
|
|
13360
|
+
const onPath = await findExecutable(["ov", "openviking"]);
|
|
13361
|
+
const detail = onPath ? executable : `${executable} (found outside PATH; add ${(0, import_node_path13.dirname)(executable)} to PATH)`;
|
|
13362
|
+
return {
|
|
13363
|
+
name: "openviking cli",
|
|
13364
|
+
status: result.exitCode === 0 ? "ok" : "warn",
|
|
13365
|
+
detail: result.exitCode === 0 ? detail : firstLine(result.stderr || result.stdout) || detail
|
|
13366
|
+
};
|
|
13367
|
+
}
|
|
13311
13368
|
async function localEmbeddingCheck() {
|
|
13312
13369
|
const serverPath = await findOpenVikingServer();
|
|
13313
13370
|
if (!serverPath) {
|
|
@@ -13475,21 +13532,26 @@ async function readOpenVikingHealthIfAvailable(config, timeoutMs) {
|
|
|
13475
13532
|
return void 0;
|
|
13476
13533
|
}
|
|
13477
13534
|
}
|
|
13478
|
-
async function waitForOpenVikingHealth(config, timeoutMs) {
|
|
13479
|
-
const
|
|
13480
|
-
|
|
13481
|
-
const
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13535
|
+
async function waitForOpenVikingHealth(config, timeoutMs, progressMessage) {
|
|
13536
|
+
const progress = progressMessage ? startProgress(progressMessage) : void 0;
|
|
13537
|
+
try {
|
|
13538
|
+
const deadline = Date.now() + timeoutMs;
|
|
13539
|
+
while (Date.now() <= deadline) {
|
|
13540
|
+
const requestTimeoutMs = Math.max(100, Math.min(1e3, deadline - Date.now()));
|
|
13541
|
+
const health = await readOpenVikingHealthIfAvailable(config, requestTimeoutMs);
|
|
13542
|
+
if (health) {
|
|
13543
|
+
return health;
|
|
13544
|
+
}
|
|
13545
|
+
const remainingMs = deadline - Date.now();
|
|
13546
|
+
if (remainingMs <= 0) {
|
|
13547
|
+
break;
|
|
13548
|
+
}
|
|
13549
|
+
await sleep(Math.min(START_HEALTH_POLL_INTERVAL_MS, remainingMs));
|
|
13489
13550
|
}
|
|
13490
|
-
|
|
13551
|
+
return void 0;
|
|
13552
|
+
} finally {
|
|
13553
|
+
progress?.stop();
|
|
13491
13554
|
}
|
|
13492
|
-
return void 0;
|
|
13493
13555
|
}
|
|
13494
13556
|
async function runInstallCommands(config, preferred, force, dryRun) {
|
|
13495
13557
|
let manager = preferred;
|
|
@@ -13950,7 +14012,11 @@ async function installLaunchAgent(config, dryRun) {
|
|
|
13950
14012
|
await maybeRun(false, "launchctl", ["load", destination]);
|
|
13951
14013
|
await maybeRun(false, "launchctl", ["start", LAUNCHD_LABEL]);
|
|
13952
14014
|
const healthUrl = openVikingHealthUrl(config);
|
|
13953
|
-
const health = await waitForOpenVikingHealth(
|
|
14015
|
+
const health = await waitForOpenVikingHealth(
|
|
14016
|
+
config,
|
|
14017
|
+
START_HEALTH_TIMEOUT_MS,
|
|
14018
|
+
`Waiting for OpenViking health at ${healthUrl}.`
|
|
14019
|
+
);
|
|
13954
14020
|
if (health) {
|
|
13955
14021
|
console.log(`Installed and started ${LAUNCHD_LABEL}. Health OK at ${healthUrl}`);
|
|
13956
14022
|
return;
|
package/docs/troubleshooting.md
CHANGED
|
@@ -8,7 +8,9 @@ Run:
|
|
|
8
8
|
threadnote install
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
The installer prefers `uv`, then `pipx`, then `python3 -m pip install --user`.
|
|
11
|
+
The installer prefers `uv`, then `pipx`, then `python3 -m pip install --user`. For `curl | sh` installs, the wrapper
|
|
12
|
+
reattaches `threadnote install` to your terminal when possible so it can prompt to install `uv` and continue instead of
|
|
13
|
+
falling straight through to the pip fallback.
|
|
12
14
|
|
|
13
15
|
## `uv` Fails With `UnknownIssuer`
|
|
14
16
|
|
|
@@ -83,8 +85,14 @@ For detached starts, logs are written to:
|
|
|
83
85
|
~/.openviking/logs/server.log
|
|
84
86
|
```
|
|
85
87
|
|
|
86
|
-
If `start` reports that OpenViking did not become healthy,
|
|
87
|
-
|
|
88
|
+
If `start` reports that OpenViking did not become healthy, first check whether it finished shortly after the timeout:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
threadnote doctor --dry-run
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
If it still is not healthy, open that log. Certificate failures during the first embedding model download are covered
|
|
95
|
+
above.
|
|
88
96
|
|
|
89
97
|
## Port Already In Use
|
|
90
98
|
|
package/package.json
CHANGED
package/scripts/install.sh
CHANGED
|
@@ -116,7 +116,11 @@ install_package "$runtime"
|
|
|
116
116
|
threadnote_bin="$(find_threadnote "$runtime")" || die "Installed $PACKAGE, but could not find the threadnote command."
|
|
117
117
|
|
|
118
118
|
say "Running threadnote install"
|
|
119
|
-
|
|
119
|
+
if { true </dev/tty; } 2>/dev/null; then
|
|
120
|
+
"$threadnote_bin" install "$@" </dev/tty
|
|
121
|
+
else
|
|
122
|
+
"$threadnote_bin" install "$@"
|
|
123
|
+
fi
|
|
120
124
|
|
|
121
125
|
if ! have threadnote; then
|
|
122
126
|
say ""
|