@onebrain-ai/cli 2.1.2 → 2.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/README.md +6 -3
- package/dist/onebrain +167 -941
- package/dist/postinstall.js +138 -0
- package/package.json +4 -2
package/dist/onebrain
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
3
|
var __create = Object.create;
|
|
5
4
|
var __getProtoOf = Object.getPrototypeOf;
|
|
6
5
|
var __defProp = Object.defineProperty;
|
|
@@ -28,7 +27,7 @@ var __export = (target, all) => {
|
|
|
28
27
|
});
|
|
29
28
|
};
|
|
30
29
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
31
|
-
var __require =
|
|
30
|
+
var __require = import.meta.require;
|
|
32
31
|
|
|
33
32
|
// node_modules/commander/lib/error.js
|
|
34
33
|
var require_error = __commonJS((exports) => {
|
|
@@ -353,7 +352,7 @@ var require_help = __commonJS((exports) => {
|
|
|
353
352
|
return Math.max(helper.longestOptionTermLength(cmd, helper), helper.longestGlobalOptionTermLength(cmd, helper), helper.longestSubcommandTermLength(cmd, helper), helper.longestArgumentTermLength(cmd, helper));
|
|
354
353
|
}
|
|
355
354
|
wrap(str, width, indent, minColumnWidth = 40) {
|
|
356
|
-
const indents = " \\f\\t\\v
|
|
355
|
+
const indents = " \\f\\t\\v\xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF";
|
|
357
356
|
const manualIndent = new RegExp(`[\\n][${indents}]+`);
|
|
358
357
|
if (str.match(manualIndent))
|
|
359
358
|
return str;
|
|
@@ -365,7 +364,7 @@ var require_help = __commonJS((exports) => {
|
|
|
365
364
|
`, `
|
|
366
365
|
`);
|
|
367
366
|
const indentString = " ".repeat(indent);
|
|
368
|
-
const zeroWidthSpace = "
|
|
367
|
+
const zeroWidthSpace = "\u200B";
|
|
369
368
|
const breaks = `\\s${zeroWidthSpace}`;
|
|
370
369
|
const regex = new RegExp(`
|
|
371
370
|
|.{1,${columnWidth - 1}}([${breaks}]|$)|[^${breaks}]+?([${breaks}]|$)`, "g");
|
|
@@ -608,11 +607,11 @@ var require_suggestSimilar = __commonJS((exports) => {
|
|
|
608
607
|
|
|
609
608
|
// node_modules/commander/lib/command.js
|
|
610
609
|
var require_command = __commonJS((exports) => {
|
|
611
|
-
var EventEmitter = __require("
|
|
612
|
-
var childProcess = __require("
|
|
613
|
-
var path = __require("
|
|
614
|
-
var fs = __require("
|
|
615
|
-
var process2 = __require("
|
|
610
|
+
var EventEmitter = __require("events").EventEmitter;
|
|
611
|
+
var childProcess = __require("child_process");
|
|
612
|
+
var path = __require("path");
|
|
613
|
+
var fs = __require("fs");
|
|
614
|
+
var process2 = __require("process");
|
|
616
615
|
var { Argument, humanReadableArgName } = require_argument();
|
|
617
616
|
var { CommanderError } = require_error();
|
|
618
617
|
var { Help } = require_help();
|
|
@@ -5365,15 +5364,15 @@ var require_errors = __commonJS((exports) => {
|
|
|
5365
5364
|
let lineStr = src.substring(lc.lineStarts[line - 1], lc.lineStarts[line]).replace(/[\n\r]+$/, "");
|
|
5366
5365
|
if (ci >= 60 && lineStr.length > 80) {
|
|
5367
5366
|
const trimStart = Math.min(ci - 39, lineStr.length - 79);
|
|
5368
|
-
lineStr = "
|
|
5367
|
+
lineStr = "\u2026" + lineStr.substring(trimStart);
|
|
5369
5368
|
ci -= trimStart - 1;
|
|
5370
5369
|
}
|
|
5371
5370
|
if (lineStr.length > 80)
|
|
5372
|
-
lineStr = lineStr.substring(0, 79) + "
|
|
5371
|
+
lineStr = lineStr.substring(0, 79) + "\u2026";
|
|
5373
5372
|
if (line > 1 && /^ *$/.test(lineStr.substring(0, ci))) {
|
|
5374
5373
|
let prev = src.substring(lc.lineStarts[line - 2], lc.lineStarts[line - 1]);
|
|
5375
5374
|
if (prev.length > 80)
|
|
5376
|
-
prev = prev.substring(0, 79) +
|
|
5375
|
+
prev = prev.substring(0, 79) + `\u2026
|
|
5377
5376
|
`;
|
|
5378
5377
|
lineStr = prev + lineStr;
|
|
5379
5378
|
}
|
|
@@ -6428,8 +6427,8 @@ var require_resolve_flow_scalar = __commonJS((exports) => {
|
|
|
6428
6427
|
r: "\r",
|
|
6429
6428
|
t: "\t",
|
|
6430
6429
|
v: "\v",
|
|
6431
|
-
N: "
|
|
6432
|
-
_: "
|
|
6430
|
+
N: "\x85",
|
|
6431
|
+
_: "\xA0",
|
|
6433
6432
|
L: "\u2028",
|
|
6434
6433
|
P: "\u2029",
|
|
6435
6434
|
" ": " ",
|
|
@@ -8904,7 +8903,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
8904
8903
|
});
|
|
8905
8904
|
|
|
8906
8905
|
// src/lib/parser.ts
|
|
8907
|
-
import { join } from "
|
|
8906
|
+
import { join } from "path";
|
|
8908
8907
|
async function loadVaultConfig(vaultRoot) {
|
|
8909
8908
|
const vaultYmlPath = join(vaultRoot, "vault.yml");
|
|
8910
8909
|
const file = Bun.file(vaultYmlPath);
|
|
@@ -8973,8 +8972,8 @@ var init_parser = __esm(() => {
|
|
|
8973
8972
|
});
|
|
8974
8973
|
|
|
8975
8974
|
// src/lib/validator.ts
|
|
8976
|
-
import { stat } from "
|
|
8977
|
-
import { join as join2 } from "
|
|
8975
|
+
import { stat } from "fs/promises";
|
|
8976
|
+
import { join as join2 } from "path";
|
|
8978
8977
|
async function checkVaultYml(vaultRoot) {
|
|
8979
8978
|
const vaultYmlPath = join2(vaultRoot, "vault.yml");
|
|
8980
8979
|
const file = Bun.file(vaultYmlPath);
|
|
@@ -9100,7 +9099,7 @@ async function checkQmdEmbeddings(config) {
|
|
|
9100
9099
|
if (total === null) {
|
|
9101
9100
|
return { check: "qmd-embeddings", status: "ok", message: "qmd status unavailable" };
|
|
9102
9101
|
}
|
|
9103
|
-
const summary = `${total} indexed
|
|
9102
|
+
const summary = `${total} indexed \xB7 ${pending} unembedded`;
|
|
9104
9103
|
if (pending > 0) {
|
|
9105
9104
|
return {
|
|
9106
9105
|
check: "qmd-embeddings",
|
|
@@ -9267,7 +9266,7 @@ async function checkPluginFiles(vaultRoot) {
|
|
|
9267
9266
|
check: "plugin-files",
|
|
9268
9267
|
status: "ok",
|
|
9269
9268
|
message: "all required files present",
|
|
9270
|
-
details: [`${skillCount} skills
|
|
9269
|
+
details: [`${skillCount} skills \xB7 ${agentCount} agents \xB7 INSTRUCTIONS.md \u2713`]
|
|
9271
9270
|
};
|
|
9272
9271
|
}
|
|
9273
9272
|
async function checkVaultYmlKeys(vaultRoot) {
|
|
@@ -9392,14 +9391,14 @@ async function checkSettingsHooks(vaultRoot, config) {
|
|
|
9392
9391
|
if (!hookPresent(settings, event, cmdSubstring)) {
|
|
9393
9392
|
warnings.push(`${event} hook missing`);
|
|
9394
9393
|
} else {
|
|
9395
|
-
confirmedHooks.push(`${event}
|
|
9394
|
+
confirmedHooks.push(`${event} \u2713`);
|
|
9396
9395
|
}
|
|
9397
9396
|
}
|
|
9398
9397
|
if (config.qmd_collection) {
|
|
9399
9398
|
if (!hookPresent(settings, "PostToolUse", QMD_HOOK_SUBSTRING)) {
|
|
9400
9399
|
warnings.push("PostToolUse (qmd) hook missing");
|
|
9401
9400
|
} else {
|
|
9402
|
-
confirmedHooks.push("PostToolUse
|
|
9401
|
+
confirmedHooks.push("PostToolUse \u2713");
|
|
9403
9402
|
}
|
|
9404
9403
|
}
|
|
9405
9404
|
const precompactGroups = settings.hooks?.["PreCompact"] ?? [];
|
|
@@ -9438,7 +9437,7 @@ async function checkSettingsHooks(vaultRoot, config) {
|
|
|
9438
9437
|
if (confirmedHooks.length > 0)
|
|
9439
9438
|
okDetails.push(`hooks: ${confirmedHooks.join(" ")}`);
|
|
9440
9439
|
if (permissionOk)
|
|
9441
|
-
okDetails.push("permissions: Bash(onebrain *)
|
|
9440
|
+
okDetails.push("permissions: Bash(onebrain *) \u2713");
|
|
9442
9441
|
return {
|
|
9443
9442
|
check: "settings-hooks",
|
|
9444
9443
|
status: "ok",
|
|
@@ -9498,8 +9497,8 @@ var init_lib = __esm(() => {
|
|
|
9498
9497
|
var require_package = __commonJS((exports, module) => {
|
|
9499
9498
|
module.exports = {
|
|
9500
9499
|
name: "@onebrain-ai/cli",
|
|
9501
|
-
version: "2.1.
|
|
9502
|
-
description: "CLI for OneBrain
|
|
9500
|
+
version: "2.1.4",
|
|
9501
|
+
description: "CLI for OneBrain \u2014 personal AI OS for Obsidian with persistent memory, 24+ skills, and Claude Code integration",
|
|
9503
9502
|
keywords: [
|
|
9504
9503
|
"onebrain",
|
|
9505
9504
|
"obsidian",
|
|
@@ -9524,9 +9523,11 @@ var require_package = __commonJS((exports, module) => {
|
|
|
9524
9523
|
bin: {
|
|
9525
9524
|
onebrain: "dist/onebrain"
|
|
9526
9525
|
},
|
|
9527
|
-
files: ["dist/onebrain"],
|
|
9526
|
+
files: ["dist/onebrain", "dist/postinstall.js"],
|
|
9528
9527
|
scripts: {
|
|
9529
9528
|
build: "bun build src/index.ts --outfile dist/onebrain --target bun",
|
|
9529
|
+
"build:postinstall": "bun build src/scripts/postinstall.ts --outfile dist/postinstall.js --target node",
|
|
9530
|
+
postinstall: "node dist/postinstall.js",
|
|
9530
9531
|
test: "bun test --pass-with-no-tests src/",
|
|
9531
9532
|
typecheck: "tsc --noEmit"
|
|
9532
9533
|
},
|
|
@@ -9563,13 +9564,13 @@ function barBlank() {
|
|
|
9563
9564
|
}
|
|
9564
9565
|
function close(msg, isError = false, isWarning = false) {
|
|
9565
9566
|
if (isError) {
|
|
9566
|
-
out(`${import_picocolors2.default.cyan("
|
|
9567
|
+
out(`${import_picocolors2.default.cyan("\u2514")} ${import_picocolors2.default.bold(import_picocolors2.default.red(msg))}
|
|
9567
9568
|
`);
|
|
9568
9569
|
} else if (isWarning) {
|
|
9569
|
-
out(`${import_picocolors2.default.cyan("
|
|
9570
|
+
out(`${import_picocolors2.default.cyan("\u2514")} ${import_picocolors2.default.yellow(msg)}
|
|
9570
9571
|
`);
|
|
9571
9572
|
} else {
|
|
9572
|
-
out(`${import_picocolors2.default.cyan("
|
|
9573
|
+
out(`${import_picocolors2.default.cyan("\u2514")} ${msg}
|
|
9573
9574
|
`);
|
|
9574
9575
|
}
|
|
9575
9576
|
}
|
|
@@ -9581,13 +9582,13 @@ function makeStepFn(isTTY) {
|
|
|
9581
9582
|
return function createStep(emoji, label) {
|
|
9582
9583
|
if (!isTTY)
|
|
9583
9584
|
return null;
|
|
9584
|
-
const frames = ["
|
|
9585
|
+
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
9585
9586
|
let i = 0;
|
|
9586
|
-
out(`${import_picocolors2.default.green(frames[0])} ${emoji} ${label}
|
|
9587
|
+
out(`${import_picocolors2.default.green(frames[0])} ${emoji} ${label}\u2026
|
|
9587
9588
|
`);
|
|
9588
9589
|
const timer = setInterval(() => {
|
|
9589
9590
|
i = (i + 1) % frames.length;
|
|
9590
|
-
out(`\x1B[1A\x1B[2K${import_picocolors2.default.green(frames[i])} ${emoji} ${label}
|
|
9591
|
+
out(`\x1B[1A\x1B[2K${import_picocolors2.default.green(frames[i])} ${emoji} ${label}\u2026
|
|
9591
9592
|
`);
|
|
9592
9593
|
}, 80);
|
|
9593
9594
|
return {
|
|
@@ -9600,19 +9601,19 @@ function makeStepFn(isTTY) {
|
|
|
9600
9601
|
barLine(result);
|
|
9601
9602
|
if (details)
|
|
9602
9603
|
for (const d of details)
|
|
9603
|
-
barLine(`
|
|
9604
|
+
barLine(` \xB7 ${d}`);
|
|
9604
9605
|
barBlank();
|
|
9605
9606
|
}
|
|
9606
9607
|
};
|
|
9607
9608
|
};
|
|
9608
9609
|
}
|
|
9609
9610
|
async function askYesNo(question) {
|
|
9610
|
-
out(`${import_picocolors2.default.cyan("
|
|
9611
|
+
out(`${import_picocolors2.default.cyan("\u25C6")} ${question}
|
|
9611
9612
|
`);
|
|
9612
9613
|
process.stdout.write(Buffer.from("\x1B[?25l", "utf8"));
|
|
9613
9614
|
function renderOptions(yes) {
|
|
9614
|
-
const yesLabel = yes ? `${import_picocolors2.default.bold(import_picocolors2.default.green("
|
|
9615
|
-
const noLabel = yes ? `${import_picocolors2.default.dim("
|
|
9615
|
+
const yesLabel = yes ? `${import_picocolors2.default.bold(import_picocolors2.default.green("\u25CF"))} Yes` : `${import_picocolors2.default.dim("\u25CB")} Yes`;
|
|
9616
|
+
const noLabel = yes ? `${import_picocolors2.default.dim("\u25CB")} No` : `${import_picocolors2.default.bold(import_picocolors2.default.green("\u25CF"))} No`;
|
|
9616
9617
|
out(`\x1B[2K${bar} ${yesLabel} / ${noLabel}\r`);
|
|
9617
9618
|
}
|
|
9618
9619
|
const answer = await new Promise((resolve) => {
|
|
@@ -9664,8 +9665,8 @@ async function askYesNo(question) {
|
|
|
9664
9665
|
var import_picocolors2, bar, dot;
|
|
9665
9666
|
var init_cli_ui = __esm(() => {
|
|
9666
9667
|
import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
9667
|
-
bar = import_picocolors2.default.cyan("
|
|
9668
|
-
dot = import_picocolors2.default.green("
|
|
9668
|
+
bar = import_picocolors2.default.cyan("\u2502");
|
|
9669
|
+
dot = import_picocolors2.default.green("\u25CF");
|
|
9669
9670
|
});
|
|
9670
9671
|
|
|
9671
9672
|
// node_modules/sisteransi/src/index.js
|
|
@@ -9727,8 +9728,8 @@ var require_src = __commonJS((exports, module) => {
|
|
|
9727
9728
|
});
|
|
9728
9729
|
|
|
9729
9730
|
// node_modules/@clack/core/dist/index.mjs
|
|
9730
|
-
import { stdin as $, stdout as j } from "
|
|
9731
|
-
import * as f from "
|
|
9731
|
+
import { stdin as $, stdout as j } from "process";
|
|
9732
|
+
import * as f from "readline";
|
|
9732
9733
|
function J({ onlyFirst: t = false } = {}) {
|
|
9733
9734
|
const F = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
|
|
9734
9735
|
return new RegExp(F, t ? undefined : "g");
|
|
@@ -9847,7 +9848,7 @@ var init_dist = __esm(() => {
|
|
|
9847
9848
|
eD = Object.keys(r.bgColor);
|
|
9848
9849
|
[...tD, ...eD];
|
|
9849
9850
|
iD = sD();
|
|
9850
|
-
v = new Set(["\x1B", "
|
|
9851
|
+
v = new Set(["\x1B", "\x9B"]);
|
|
9851
9852
|
y = `${rD}8;;`;
|
|
9852
9853
|
aD = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
9853
9854
|
c = { actions: new Set(aD), aliases: new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["\x03", "cancel"], ["escape", "cancel"]]) };
|
|
@@ -9856,7 +9857,7 @@ var init_dist = __esm(() => {
|
|
|
9856
9857
|
});
|
|
9857
9858
|
|
|
9858
9859
|
// node_modules/@clack/prompts/dist/index.mjs
|
|
9859
|
-
import p from "
|
|
9860
|
+
import p from "process";
|
|
9860
9861
|
function X2() {
|
|
9861
9862
|
return p.platform !== "win32" ? p.env.TERM !== "linux" : !!p.env.CI || !!p.env.WT_SESSION || !!p.env.TERMINUS_SUBLIME || p.env.ConEmuTask === "{cmd::Cmder}" || p.env.TERM_PROGRAM === "Terminus-Sublime" || p.env.TERM_PROGRAM === "vscode" || p.env.TERM === "xterm-256color" || p.env.TERM === "alacritty" || p.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
9862
9863
|
}
|
|
@@ -9869,7 +9870,7 @@ ${import_picocolors3.default.gray(m2)} ${s}
|
|
|
9869
9870
|
|
|
9870
9871
|
`);
|
|
9871
9872
|
}, L2 = () => {
|
|
9872
|
-
const s = E ? ["
|
|
9873
|
+
const s = E ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], n = E ? 80 : 120, t = process.env.CI === "true";
|
|
9873
9874
|
let i, r2, c2 = false, o = "", l2;
|
|
9874
9875
|
const $2 = (h) => {
|
|
9875
9876
|
const g = h > 1 ? "Something went wrong" : "Canceled";
|
|
@@ -9913,32 +9914,32 @@ var init_dist2 = __esm(() => {
|
|
|
9913
9914
|
import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
9914
9915
|
import_sisteransi2 = __toESM(require_src(), 1);
|
|
9915
9916
|
E = X2();
|
|
9916
|
-
ee = u("
|
|
9917
|
-
A = u("
|
|
9918
|
-
B = u("
|
|
9919
|
-
S2 = u("
|
|
9920
|
-
te = u("
|
|
9921
|
-
a = u("
|
|
9922
|
-
m2 = u("
|
|
9923
|
-
j2 = u("
|
|
9924
|
-
R = u("
|
|
9925
|
-
V = u("
|
|
9926
|
-
M = u("
|
|
9927
|
-
G = u("
|
|
9928
|
-
se = u("
|
|
9929
|
-
N2 = u("
|
|
9930
|
-
re = u("
|
|
9931
|
-
ie = u("
|
|
9932
|
-
ne = u("
|
|
9933
|
-
ae = u("
|
|
9934
|
-
oe = u("
|
|
9935
|
-
ce = u("
|
|
9936
|
-
le = u("
|
|
9917
|
+
ee = u("\u25C6", "*");
|
|
9918
|
+
A = u("\u25A0", "x");
|
|
9919
|
+
B = u("\u25B2", "x");
|
|
9920
|
+
S2 = u("\u25C7", "o");
|
|
9921
|
+
te = u("\u250C", "T");
|
|
9922
|
+
a = u("\u2502", "|");
|
|
9923
|
+
m2 = u("\u2514", "\u2014");
|
|
9924
|
+
j2 = u("\u25CF", ">");
|
|
9925
|
+
R = u("\u25CB", " ");
|
|
9926
|
+
V = u("\u25FB", "[\u2022]");
|
|
9927
|
+
M = u("\u25FC", "[+]");
|
|
9928
|
+
G = u("\u25FB", "[ ]");
|
|
9929
|
+
se = u("\u25AA", "\u2022");
|
|
9930
|
+
N2 = u("\u2500", "-");
|
|
9931
|
+
re = u("\u256E", "+");
|
|
9932
|
+
ie = u("\u251C", "+");
|
|
9933
|
+
ne = u("\u256F", "+");
|
|
9934
|
+
ae = u("\u25CF", "\u2022");
|
|
9935
|
+
oe = u("\u25C6", "*");
|
|
9936
|
+
ce = u("\u25B2", "!");
|
|
9937
|
+
le = u("\u25A0", "x");
|
|
9937
9938
|
});
|
|
9938
9939
|
|
|
9939
9940
|
// src/commands/internal/harness.ts
|
|
9940
|
-
import { stat as stat2 } from "
|
|
9941
|
-
import { join as join3 } from "
|
|
9941
|
+
import { stat as stat2 } from "fs/promises";
|
|
9942
|
+
import { join as join3 } from "path";
|
|
9942
9943
|
async function pathExists(p2) {
|
|
9943
9944
|
try {
|
|
9944
9945
|
await stat2(p2);
|
|
@@ -9956,7 +9957,7 @@ async function detectHarness(vaultRoot) {
|
|
|
9956
9957
|
return "gemini";
|
|
9957
9958
|
if (env === "direct")
|
|
9958
9959
|
return "direct";
|
|
9959
|
-
process.stderr.write(`harness: unknown ONEBRAIN_HARNESS value "${env}"
|
|
9960
|
+
process.stderr.write(`harness: unknown ONEBRAIN_HARNESS value "${env}" \u2014 ignoring, falling back to directory detection
|
|
9960
9961
|
`);
|
|
9961
9962
|
}
|
|
9962
9963
|
if (await pathExists(join3(vaultRoot, ".gemini")))
|
|
@@ -9973,9 +9974,9 @@ __export(exports_register_hooks, {
|
|
|
9973
9974
|
runRegisterHooks: () => runRegisterHooks,
|
|
9974
9975
|
registerHooksCommand: () => registerHooksCommand
|
|
9975
9976
|
});
|
|
9976
|
-
import { mkdir, readFile, rename, writeFile } from "
|
|
9977
|
-
import { homedir } from "
|
|
9978
|
-
import { dirname, join as join4 } from "
|
|
9977
|
+
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
9978
|
+
import { homedir } from "os";
|
|
9979
|
+
import { dirname, join as join4 } from "path";
|
|
9979
9980
|
async function readSettings(settingsPath) {
|
|
9980
9981
|
try {
|
|
9981
9982
|
const text = await readFile(settingsPath, "utf8");
|
|
@@ -10152,11 +10153,11 @@ async function runRegisterHooks(opts = {}) {
|
|
|
10152
10153
|
if (isTTY) {
|
|
10153
10154
|
const parts = HOOK_EVENTS.map((e2) => {
|
|
10154
10155
|
const status = result.hooks[e2];
|
|
10155
|
-
const icon = import_picocolors4.default.green(status === "ok" ? "
|
|
10156
|
+
const icon = import_picocolors4.default.green(status === "ok" ? "\u2713" : status === "migrated" ? "\u2191" : "+");
|
|
10156
10157
|
return `${import_picocolors4.default.dim(e2)} ${icon}`;
|
|
10157
10158
|
});
|
|
10158
10159
|
if (qmdStatus)
|
|
10159
|
-
parts.push(`${import_picocolors4.default.dim("PostToolUse")} ${import_picocolors4.default.green(qmdStatus === "ok" ? "
|
|
10160
|
+
parts.push(`${import_picocolors4.default.dim("PostToolUse")} ${import_picocolors4.default.green(qmdStatus === "ok" ? "\u2713" : "+")}`);
|
|
10160
10161
|
hooksSpinner?.stop(`Hooks ${parts.join(" ")}`);
|
|
10161
10162
|
} else {
|
|
10162
10163
|
const hookLine = HOOK_EVENTS.map((e2) => {
|
|
@@ -10252,9 +10253,9 @@ import {
|
|
|
10252
10253
|
stat as stat3,
|
|
10253
10254
|
unlink,
|
|
10254
10255
|
writeFile as writeFile2
|
|
10255
|
-
} from "
|
|
10256
|
-
import { homedir as homedir2, tmpdir } from "
|
|
10257
|
-
import { dirname as dirname2, join as join5, relative } from "
|
|
10256
|
+
} from "fs/promises";
|
|
10257
|
+
import { homedir as homedir2, tmpdir } from "os";
|
|
10258
|
+
import { dirname as dirname2, join as join5, relative } from "path";
|
|
10258
10259
|
function resolveBranch(updateChannel) {
|
|
10259
10260
|
return updateChannel === "stable" ? "main" : "next";
|
|
10260
10261
|
}
|
|
@@ -10263,9 +10264,9 @@ async function downloadTarball(branch, fetchFn) {
|
|
|
10263
10264
|
const response = await fetchFn(url);
|
|
10264
10265
|
if (!response.ok) {
|
|
10265
10266
|
const hints = {
|
|
10266
|
-
403: "
|
|
10267
|
-
404: "
|
|
10268
|
-
429: "
|
|
10267
|
+
403: " \u2014 check repo permissions or GITHUB_TOKEN",
|
|
10268
|
+
404: " \u2014 repo or branch not found",
|
|
10269
|
+
429: " \u2014 rate limited, wait and retry"
|
|
10269
10270
|
};
|
|
10270
10271
|
const hint = hints[response.status] ?? "";
|
|
10271
10272
|
throw new Error(`HTTP ${response.status} downloading tarball from ${url}${hint}`);
|
|
@@ -10703,14 +10704,14 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10703
10704
|
if (pinResult.skipped) {
|
|
10704
10705
|
stopSpinner("pin skipped (not found or marketplace)");
|
|
10705
10706
|
} else {
|
|
10706
|
-
stopSpinner("installPath
|
|
10707
|
+
stopSpinner("installPath \u2192 .claude/plugins/onebrain");
|
|
10707
10708
|
}
|
|
10708
10709
|
} catch (err) {
|
|
10709
10710
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10710
10711
|
process.stderr.write(`vault-sync: pin warning: ${msg}
|
|
10711
10712
|
`);
|
|
10712
10713
|
result.pinSkipped = true;
|
|
10713
|
-
stopSpinner("pin skipped (error
|
|
10714
|
+
stopSpinner("pin skipped (error \u2014 non-fatal)");
|
|
10714
10715
|
}
|
|
10715
10716
|
startSpinner("\uD83E\uDDF9", "Cleaning cache");
|
|
10716
10717
|
try {
|
|
@@ -10725,13 +10726,13 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10725
10726
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10726
10727
|
process.stderr.write(`vault-sync: cache clean warning: ${msg}
|
|
10727
10728
|
`);
|
|
10728
|
-
stopSpinner("cache clean skipped (error
|
|
10729
|
+
stopSpinner("cache clean skipped (error \u2014 non-fatal)");
|
|
10729
10730
|
}
|
|
10730
10731
|
}
|
|
10731
10732
|
result.ok = true;
|
|
10732
10733
|
if (isTTY) {
|
|
10733
10734
|
if (!embedded) {
|
|
10734
|
-
fe(`Done
|
|
10735
|
+
fe(`Done \u2014 v${result.version} synced`);
|
|
10735
10736
|
}
|
|
10736
10737
|
} else {
|
|
10737
10738
|
process.stdout.write(`vault-sync: done
|
|
@@ -10761,7 +10762,7 @@ var init_vault_sync = __esm(() => {
|
|
|
10761
10762
|
|
|
10762
10763
|
// src/index.ts
|
|
10763
10764
|
import { existsSync } from "fs";
|
|
10764
|
-
import { dirname as
|
|
10765
|
+
import { dirname as dirname4, join as join11 } from "path";
|
|
10765
10766
|
|
|
10766
10767
|
// node_modules/commander/esm.mjs
|
|
10767
10768
|
var import__ = __toESM(require_commander(), 1);
|
|
@@ -10787,7 +10788,7 @@ var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
|
10787
10788
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
10788
10789
|
function resolveBinaryVersion() {
|
|
10789
10790
|
if (true)
|
|
10790
|
-
return "2.1.
|
|
10791
|
+
return "2.1.4";
|
|
10791
10792
|
try {
|
|
10792
10793
|
const pkg = require_package();
|
|
10793
10794
|
return pkg.version ?? "dev";
|
|
@@ -10796,11 +10797,11 @@ function resolveBinaryVersion() {
|
|
|
10796
10797
|
}
|
|
10797
10798
|
}
|
|
10798
10799
|
var ART_LINES = [
|
|
10799
|
-
`
|
|
10800
|
-
"
|
|
10801
|
-
"
|
|
10802
|
-
"
|
|
10803
|
-
`
|
|
10800
|
+
` \u25C6${"\u2500".repeat(25)}\u25C6`,
|
|
10801
|
+
" \u250C\u2500\u2510\u250C\u2510\u2577\u250C\u2500\u2574\u250C\u2510 \u250C\u2500\u2510\u250C\u2500\u2510\u2577\u250C\u2510\u2577",
|
|
10802
|
+
" \u2502 \u2502\u2502\u2514\u2524\u251C\u2574 \u251C\u2534\u2510\u251C\u252C\u2518\u251C\u2500\u2524\u2502\u2502\u2514\u2524",
|
|
10803
|
+
" \u2514\u2500\u2518\u2575 \u2575\u2514\u2500\u2574\u2514\u2500\u2518\u2575\u2514\u2574\u2575 \u2575\u2575\u2575 \u2575",
|
|
10804
|
+
` \u25C6${"\u2500".repeat(25)}\u25C6`
|
|
10804
10805
|
];
|
|
10805
10806
|
var TAGLINE = "Your AI Thinking Partner";
|
|
10806
10807
|
var BANNER_LINE_COUNT = 1 + ART_LINES.length + 3;
|
|
@@ -10939,7 +10940,7 @@ async function printBanner() {
|
|
|
10939
10940
|
up(BANNER_LINE_COUNT);
|
|
10940
10941
|
printFrame(ART_LINES.map((l, i) => neonLine(l, i)), ` ${" ".repeat(TAGLINE.length)}`);
|
|
10941
10942
|
await delay(200);
|
|
10942
|
-
const cursor =
|
|
10943
|
+
const cursor = "\x1B[1;38;2;140;255;255m\u258C\x1B[0m";
|
|
10943
10944
|
for (let len = 1;len <= TAGLINE.length; len++) {
|
|
10944
10945
|
await delay(32);
|
|
10945
10946
|
up(BANNER_LINE_COUNT);
|
|
@@ -11018,7 +11019,7 @@ async function runDoctor(opts = {}) {
|
|
|
11018
11019
|
let vaultYmlKeysResult;
|
|
11019
11020
|
let settingsHooksResult;
|
|
11020
11021
|
if (isTTY) {
|
|
11021
|
-
const sp2 = createStep("
|
|
11022
|
+
const sp2 = createStep("\u2699\uFE0F", "Config schema");
|
|
11022
11023
|
vaultYmlKeysResult = await checkVaultYmlKeysFn(vaultDir);
|
|
11023
11024
|
await randDelay();
|
|
11024
11025
|
sp2.stop(fmtResult(vaultYmlKeysResult), vaultYmlKeysResult.details);
|
|
@@ -11082,15 +11083,15 @@ async function runDoctor(opts = {}) {
|
|
|
11082
11083
|
printNonTtyOutput(results, totalChecks, errorCount, warningCount, showFixHint, fixableCount);
|
|
11083
11084
|
} else {
|
|
11084
11085
|
if (errorCount > 0) {
|
|
11085
|
-
close(`${summaryParts.join("
|
|
11086
|
+
close(`${summaryParts.join(" \xB7 ")} \u2014 fix before using`, true);
|
|
11086
11087
|
} else if (warningCount > 0) {
|
|
11087
|
-
close(`${summaryParts.join("
|
|
11088
|
+
close(`${summaryParts.join(" \xB7 ")} \u2014 advisory only, safe to run`, false, true);
|
|
11088
11089
|
} else {
|
|
11089
|
-
close(import_picocolors5.default.green(`${summaryParts.join("
|
|
11090
|
+
close(import_picocolors5.default.green(`${summaryParts.join(" \xB7 ")} \u2014 all passed`));
|
|
11090
11091
|
}
|
|
11091
11092
|
if (showFixHint) {
|
|
11092
11093
|
process.stdout.write(`
|
|
11093
|
-
|
|
11094
|
+
\u2192 Run ${import_picocolors5.default.cyan("onebrain doctor --fix")} to auto-fix ${fixableCount} issue(s)
|
|
11094
11095
|
`);
|
|
11095
11096
|
}
|
|
11096
11097
|
}
|
|
@@ -11111,21 +11112,21 @@ async function doctorCommand(opts = {}) {
|
|
|
11111
11112
|
function printNonTtyOutput(results, totalChecks, errorCount, warningCount, showFixHint, fixableCount) {
|
|
11112
11113
|
const lines = ["OneBrain Doctor", ""];
|
|
11113
11114
|
for (const result of results) {
|
|
11114
|
-
const icon = result.status === "ok" ? "[
|
|
11115
|
+
const icon = result.status === "ok" ? "[\u2713]" : result.status === "warn" ? "[!]" : "[\u2717]";
|
|
11115
11116
|
lines.push(` ${icon} ${result.check.padEnd(20)} ${result.message}`);
|
|
11116
11117
|
if (result.hint)
|
|
11117
|
-
lines.push(`
|
|
11118
|
+
lines.push(` \u2192 ${result.hint}`);
|
|
11118
11119
|
if (result.details)
|
|
11119
11120
|
for (const d of result.details)
|
|
11120
|
-
lines.push(`
|
|
11121
|
+
lines.push(` \xB7 ${d}`);
|
|
11121
11122
|
}
|
|
11122
11123
|
lines.push("");
|
|
11123
11124
|
if (errorCount > 0) {
|
|
11124
|
-
lines.push(`Summary: ${totalChecks} checks
|
|
11125
|
+
lines.push(`Summary: ${totalChecks} checks \xB7 ${errorCount} error(s) \xB7 ${warningCount} warning(s) \u2014 fix before using`);
|
|
11125
11126
|
} else if (warningCount > 0) {
|
|
11126
|
-
lines.push(`Summary: ${totalChecks} checks
|
|
11127
|
+
lines.push(`Summary: ${totalChecks} checks \xB7 ${warningCount} warning(s) \u2014 ok to run`);
|
|
11127
11128
|
} else {
|
|
11128
|
-
lines.push(`Summary: ${totalChecks} checks
|
|
11129
|
+
lines.push(`Summary: ${totalChecks} checks \u2014 all passed`);
|
|
11129
11130
|
}
|
|
11130
11131
|
if (showFixHint)
|
|
11131
11132
|
lines.push(`hint: run onebrain doctor --fix to auto-fix ${fixableCount} issue(s)`);
|
|
@@ -11154,8 +11155,8 @@ function getFix(r2) {
|
|
|
11154
11155
|
const description = deprecated.length > 0 ? `Remove deprecated keys from vault.yml: ${deprecated.join(", ")}` : "Remove deprecated keys from vault.yml";
|
|
11155
11156
|
return {
|
|
11156
11157
|
fn: async (vaultDir) => {
|
|
11157
|
-
const { readFile: readFile2, writeFile: writeFile2, rename: rename2 } = await import("
|
|
11158
|
-
const { join: join5 } = await import("
|
|
11158
|
+
const { readFile: readFile2, writeFile: writeFile2, rename: rename2 } = await import("fs/promises");
|
|
11159
|
+
const { join: join5 } = await import("path");
|
|
11159
11160
|
const { parse: parse3, stringify } = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
11160
11161
|
const vaultYmlPath = join5(vaultDir, "vault.yml");
|
|
11161
11162
|
const text = await readFile2(vaultYmlPath, "utf8");
|
|
@@ -11187,9 +11188,9 @@ function getFix(r2) {
|
|
|
11187
11188
|
const count = pendingMatch?.[1] ?? "some";
|
|
11188
11189
|
return {
|
|
11189
11190
|
fn: async (vaultDir) => {
|
|
11190
|
-
const { join: join5 } = await import("
|
|
11191
|
+
const { join: join5 } = await import("path");
|
|
11191
11192
|
const { parse: parseYaml } = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
11192
|
-
const { readFile: readFile2 } = await import("
|
|
11193
|
+
const { readFile: readFile2 } = await import("fs/promises");
|
|
11193
11194
|
const raw = parseYaml(await readFile2(join5(vaultDir, "vault.yml"), "utf8"));
|
|
11194
11195
|
const collection = raw["qmd_collection"];
|
|
11195
11196
|
if (!collection)
|
|
@@ -11215,8 +11216,8 @@ function getFix(r2) {
|
|
|
11215
11216
|
const missingStr = r2.hint.replace("Missing: ", "");
|
|
11216
11217
|
return {
|
|
11217
11218
|
fn: async (vaultDir) => {
|
|
11218
|
-
const { mkdir: mkdir2 } = await import("
|
|
11219
|
-
const { join: join5 } = await import("
|
|
11219
|
+
const { mkdir: mkdir2 } = await import("fs/promises");
|
|
11220
|
+
const { join: join5 } = await import("path");
|
|
11220
11221
|
const missing = missingStr.split(", ").map((f2) => f2.trim()).filter(Boolean);
|
|
11221
11222
|
for (const folder of missing) {
|
|
11222
11223
|
await mkdir2(join5(vaultDir, folder), { recursive: true });
|
|
@@ -11231,7 +11232,7 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11231
11232
|
const fixable = results.filter((r2) => r2.status !== "ok" && getFix(r2) !== null);
|
|
11232
11233
|
if (fixable.length === 0) {
|
|
11233
11234
|
if (isTTY)
|
|
11234
|
-
barLine(`${import_picocolors5.default.green("
|
|
11235
|
+
barLine(`${import_picocolors5.default.green("\u25C6")} Nothing to fix`);
|
|
11235
11236
|
else
|
|
11236
11237
|
writeLine("nothing to fix");
|
|
11237
11238
|
return;
|
|
@@ -11241,14 +11242,14 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11241
11242
|
barLine(import_picocolors5.default.bold(`${fixable.length} fix(es) to apply:`));
|
|
11242
11243
|
barBlank();
|
|
11243
11244
|
for (const r2 of fixable) {
|
|
11244
|
-
barLine(` ${import_picocolors5.default.cyan("
|
|
11245
|
+
barLine(` ${import_picocolors5.default.cyan("\u25C6")} ${getFix(r2).description}`);
|
|
11245
11246
|
}
|
|
11246
11247
|
barBlank();
|
|
11247
11248
|
const answer = await askYesNo("Apply all?");
|
|
11248
11249
|
if (answer === null || answer === false) {
|
|
11249
11250
|
barLine(import_picocolors5.default.dim("No"));
|
|
11250
11251
|
barBlank();
|
|
11251
|
-
close(`No changes made
|
|
11252
|
+
close(`No changes made \u2014 run ${import_picocolors5.default.cyan("onebrain doctor --fix")} to apply`);
|
|
11252
11253
|
return;
|
|
11253
11254
|
}
|
|
11254
11255
|
barLine("Yes");
|
|
@@ -11268,11 +11269,11 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11268
11269
|
await fix.fn(vaultDir, registerHooksFn);
|
|
11269
11270
|
fixed++;
|
|
11270
11271
|
if (isTTY)
|
|
11271
|
-
barLine(`${import_picocolors5.default.green("
|
|
11272
|
+
barLine(`${import_picocolors5.default.green("\u25C6")} ${fix.description}`);
|
|
11272
11273
|
} catch (err) {
|
|
11273
11274
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
11274
11275
|
if (isTTY) {
|
|
11275
|
-
barLine(`${import_picocolors5.default.yellow("
|
|
11276
|
+
barLine(`${import_picocolors5.default.yellow("\u25B2")} Could not fix ${r2.check}: ${errMsg}`);
|
|
11276
11277
|
} else {
|
|
11277
11278
|
process.stderr.write(`doctor: fix failed for ${r2.check}: ${errMsg}
|
|
11278
11279
|
`);
|
|
@@ -11282,9 +11283,9 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11282
11283
|
if (isTTY) {
|
|
11283
11284
|
barBlank();
|
|
11284
11285
|
if (fixed > 0)
|
|
11285
|
-
barLine(`${import_picocolors5.default.green("
|
|
11286
|
+
barLine(`${import_picocolors5.default.green("\u25C6")} Fixed ${fixed} issue(s)`);
|
|
11286
11287
|
if (unfixable.length > 0) {
|
|
11287
|
-
barLine(`${import_picocolors5.default.yellow("
|
|
11288
|
+
barLine(`${import_picocolors5.default.yellow("\u25B2")} ${unfixable.length} issue(s) require manual action:`);
|
|
11288
11289
|
for (const r2 of unfixable) {
|
|
11289
11290
|
barLine(` ${r2.check}: ${r2.hint ?? "no auto-fix available"}`);
|
|
11290
11291
|
}
|
|
@@ -11304,9 +11305,9 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11304
11305
|
// src/commands/init.ts
|
|
11305
11306
|
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
11306
11307
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
11307
|
-
import { mkdir as mkdir3, readFile as readFile3, readdir as readdir2, rename as rename3, stat as stat4, writeFile as writeFile3 } from "
|
|
11308
|
-
import { homedir as homedir3 } from "
|
|
11309
|
-
import { dirname as dirname3, join as join6 } from "
|
|
11308
|
+
import { mkdir as mkdir3, readFile as readFile3, readdir as readdir2, rename as rename3, stat as stat4, writeFile as writeFile3 } from "fs/promises";
|
|
11309
|
+
import { homedir as homedir3 } from "os";
|
|
11310
|
+
import { dirname as dirname3, join as join6 } from "path";
|
|
11310
11311
|
init_cli_ui();
|
|
11311
11312
|
var binaryVersion = resolveBinaryVersion();
|
|
11312
11313
|
var STANDARD_FOLDERS = [
|
|
@@ -11372,7 +11373,7 @@ async function downloadPluginFiles(vaultDir, vaultSyncFn) {
|
|
|
11372
11373
|
} catch {}
|
|
11373
11374
|
let driftWarning;
|
|
11374
11375
|
if (pluginVersion && binaryVersion !== "dev" && pluginVersion !== binaryVersion) {
|
|
11375
|
-
driftWarning = `Plugin files v${pluginVersion}, binary v${binaryVersion}
|
|
11376
|
+
driftWarning = `Plugin files v${pluginVersion}, binary v${binaryVersion} \u2014 run onebrain update to sync.`;
|
|
11376
11377
|
}
|
|
11377
11378
|
return driftWarning !== undefined ? { skipped: true, driftWarning } : { skipped: true };
|
|
11378
11379
|
}
|
|
@@ -11573,7 +11574,7 @@ async function installObsidianPlugins(vaultDir, opts) {
|
|
|
11573
11574
|
}
|
|
11574
11575
|
if (pluginFailed) {
|
|
11575
11576
|
try {
|
|
11576
|
-
const { rm: rm2 } = await import("
|
|
11577
|
+
const { rm: rm2 } = await import("fs/promises");
|
|
11577
11578
|
await rm2(pluginDir, { recursive: true, force: true });
|
|
11578
11579
|
} catch {}
|
|
11579
11580
|
} else {
|
|
@@ -11655,7 +11656,7 @@ async function runInit(opts = {}) {
|
|
|
11655
11656
|
await writeVaultYml(vaultDir);
|
|
11656
11657
|
if (sp2) {
|
|
11657
11658
|
await randDelay();
|
|
11658
|
-
sp2.stop(import_picocolors7.default.dim("written"), ["update_channel: stable", "checkpoint: 15 msgs
|
|
11659
|
+
sp2.stop(import_picocolors7.default.dim("written"), ["update_channel: stable", "checkpoint: 15 msgs \xB7 30 min"]);
|
|
11659
11660
|
} else {
|
|
11660
11661
|
writeLine("vault.yml: written");
|
|
11661
11662
|
}
|
|
@@ -11671,24 +11672,21 @@ async function runInit(opts = {}) {
|
|
|
11671
11672
|
const pluginJsonPath = join6(vaultDir, ".claude", "plugins", "onebrain", ".claude-plugin", "plugin.json");
|
|
11672
11673
|
const pluginFilesExist = await pathExists2(pluginJsonPath);
|
|
11673
11674
|
const sp4 = pluginFilesExist ? createStep("\uD83D\uDCE6", "Plugin files") : null;
|
|
11674
|
-
const {
|
|
11675
|
-
skipped: pluginSkipped,
|
|
11676
|
-
failed: pluginDownloadFailed
|
|
11677
|
-
} = await downloadPluginFiles(vaultDir, vaultSyncFn);
|
|
11675
|
+
const { skipped: pluginSkipped, failed: pluginDownloadFailed } = await downloadPluginFiles(vaultDir, vaultSyncFn);
|
|
11678
11676
|
result.pluginSkipped = pluginSkipped;
|
|
11679
11677
|
if (sp4) {
|
|
11680
11678
|
if (pluginDownloadFailed) {
|
|
11681
11679
|
sp4.stop("download failed");
|
|
11682
11680
|
} else {
|
|
11683
11681
|
const { skills, agents } = await countPluginContents(vaultDir);
|
|
11684
|
-
sp4.stop(import_picocolors7.default.dim("already installed"), [`${skills} skills
|
|
11682
|
+
sp4.stop(import_picocolors7.default.dim("already installed"), [`${skills} skills \xB7 ${agents} agents`]);
|
|
11685
11683
|
}
|
|
11686
11684
|
} else if (isTTY) {
|
|
11687
11685
|
if (!pluginDownloadFailed) {
|
|
11688
11686
|
const { skills, agents } = await countPluginContents(vaultDir);
|
|
11689
11687
|
dotLine("\uD83D\uDCE6", "Plugin files");
|
|
11690
11688
|
barLine(import_picocolors7.default.dim("downloaded"));
|
|
11691
|
-
barLine(`
|
|
11689
|
+
barLine(` \xB7 ${skills} skills \xB7 ${agents} agents`);
|
|
11692
11690
|
barBlank();
|
|
11693
11691
|
}
|
|
11694
11692
|
} else {
|
|
@@ -11702,7 +11700,7 @@ async function runInit(opts = {}) {
|
|
|
11702
11700
|
if (isTTY) {
|
|
11703
11701
|
close("Could not download plugin files. Check your internet connection and try again.", true);
|
|
11704
11702
|
} else {
|
|
11705
|
-
writeLine("error: vault-sync failed
|
|
11703
|
+
writeLine("error: vault-sync failed \u2014 run onebrain update to download plugin files");
|
|
11706
11704
|
}
|
|
11707
11705
|
return result;
|
|
11708
11706
|
}
|
|
@@ -11733,7 +11731,9 @@ async function runInit(opts = {}) {
|
|
|
11733
11731
|
result.pluginRegistrationSkipped = pluginRegistrationSkipped;
|
|
11734
11732
|
if (sp5) {
|
|
11735
11733
|
await randDelay();
|
|
11736
|
-
sp5.stop(import_picocolors7.default.dim(pluginRegistrationSkipped ? "skipped" : "registered"), [
|
|
11734
|
+
sp5.stop(import_picocolors7.default.dim(pluginRegistrationSkipped ? "skipped" : "registered"), [
|
|
11735
|
+
`source: ${pluginRegistrationSkipped ? "marketplace" : "local"}`
|
|
11736
|
+
]);
|
|
11737
11737
|
} else {
|
|
11738
11738
|
writeLine(`plugin: ${pluginRegistrationSkipped ? "skipped (marketplace)" : "registered"}`);
|
|
11739
11739
|
}
|
|
@@ -11749,20 +11749,20 @@ async function runInit(opts = {}) {
|
|
|
11749
11749
|
}
|
|
11750
11750
|
if (sp6) {
|
|
11751
11751
|
await randDelay();
|
|
11752
|
-
sp6.stop(hooksOk ? undefined : "not registered
|
|
11752
|
+
sp6.stop(hooksOk ? undefined : "not registered \u2014 run onebrain update", hooksOk ? ["Stop \u2713 PostCompact \u2713", "Bash(onebrain *) \u2713"] : undefined);
|
|
11753
11753
|
} else {
|
|
11754
|
-
writeLine(`hooks: ${hooksOk ? "ok" : "warning
|
|
11754
|
+
writeLine(`hooks: ${hooksOk ? "ok" : "warning \u2014 hooks not registered; run onebrain update"}`);
|
|
11755
11755
|
}
|
|
11756
11756
|
result.ok = true;
|
|
11757
11757
|
result.exitCode = 0;
|
|
11758
11758
|
if (isTTY) {
|
|
11759
|
-
barLine(import_picocolors7.default.dim(
|
|
11759
|
+
barLine(import_picocolors7.default.dim(`\u2500\u2500\u2500 Next steps ${"\u2500".repeat(25)}`));
|
|
11760
11760
|
barBlank();
|
|
11761
|
-
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("1"))} \uD83D\uDCC1 Open Obsidian
|
|
11761
|
+
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("1"))} \uD83D\uDCC1 Open Obsidian \u2192 open this folder as vault`);
|
|
11762
11762
|
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("2"))} \uD83E\uDD16 Run ${import_picocolors7.default.cyan("claude")}`);
|
|
11763
11763
|
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("3"))} \uD83E\uDDE0 Type ${import_picocolors7.default.cyan("/onboarding")} to personalize`);
|
|
11764
11764
|
barBlank();
|
|
11765
|
-
close(
|
|
11765
|
+
close(`\u2728 ${import_picocolors7.default.bold("Ready")} \u2014 ${import_picocolors7.default.cyan("/onboarding")}`);
|
|
11766
11766
|
} else {
|
|
11767
11767
|
writeLine("done: run /onboarding in Claude to finish setup");
|
|
11768
11768
|
}
|
|
@@ -11776,9 +11776,9 @@ async function initCommand(opts = {}) {
|
|
|
11776
11776
|
}
|
|
11777
11777
|
|
|
11778
11778
|
// src/commands/internal/checkpoint.ts
|
|
11779
|
-
import { readFileSync, readdirSync, writeFileSync } from "
|
|
11780
|
-
import { tmpdir as osTmpdir } from "
|
|
11781
|
-
import { join as join7 } from "
|
|
11779
|
+
import { readFileSync, readdirSync, writeFileSync } from "fs";
|
|
11780
|
+
import { tmpdir as osTmpdir } from "os";
|
|
11781
|
+
import { join as join7 } from "path";
|
|
11782
11782
|
var SKIP_WINDOW = 60;
|
|
11783
11783
|
var MIN_ACTIVITY = 2;
|
|
11784
11784
|
var PRECOMPACT_RECENCY = 300;
|
|
@@ -11954,8 +11954,8 @@ async function checkpointCommand(mode, token, vaultRoot) {
|
|
|
11954
11954
|
// src/commands/internal/migrate.ts
|
|
11955
11955
|
init_lib();
|
|
11956
11956
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
11957
|
-
import { readFile as readFile4, readdir as readdir3, writeFile as writeFile4 } from "
|
|
11958
|
-
import { join as join8 } from "
|
|
11957
|
+
import { readFile as readFile4, readdir as readdir3, writeFile as writeFile4 } from "fs/promises";
|
|
11958
|
+
import { join as join8 } from "path";
|
|
11959
11959
|
function parseFrontmatterWithRest(rawText) {
|
|
11960
11960
|
const text = rawText.replace(/\r\n/g, `
|
|
11961
11961
|
`);
|
|
@@ -12024,7 +12024,7 @@ async function runBackfillRecapped(logsFolder, cutoffDate) {
|
|
|
12024
12024
|
const content = await readFile4(fpath, "utf8");
|
|
12025
12025
|
const parsed = parseFrontmatterWithRest(content);
|
|
12026
12026
|
if (!parsed) {
|
|
12027
|
-
process.stderr.write(`migrate: ${fname}
|
|
12027
|
+
process.stderr.write(`migrate: ${fname} \u2014 malformed frontmatter
|
|
12028
12028
|
`);
|
|
12029
12029
|
skipped++;
|
|
12030
12030
|
continue;
|
|
@@ -12071,8 +12071,8 @@ async function migrateCommand(migrationName, cutoffDate, vaultDir) {
|
|
|
12071
12071
|
|
|
12072
12072
|
// src/commands/internal/orphan-scan.ts
|
|
12073
12073
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
12074
|
-
import { readFile as readFile5, readdir as readdir4 } from "
|
|
12075
|
-
import { join as join9 } from "
|
|
12074
|
+
import { readFile as readFile5, readdir as readdir4 } from "fs/promises";
|
|
12075
|
+
import { join as join9 } from "path";
|
|
12076
12076
|
function parseFrontmatter(rawText) {
|
|
12077
12077
|
const text = rawText.replace(/\r\n/g, `
|
|
12078
12078
|
`);
|
|
@@ -12206,276 +12206,14 @@ async function qmdReindexCommand(vaultRoot) {
|
|
|
12206
12206
|
}
|
|
12207
12207
|
}
|
|
12208
12208
|
|
|
12209
|
-
// src/
|
|
12210
|
-
|
|
12211
|
-
init_lib();
|
|
12212
|
-
init_harness();
|
|
12213
|
-
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
12214
|
-
import { mkdir as mkdir4, readFile as readFile6, rename as rename4, writeFile as writeFile5 } from "node:fs/promises";
|
|
12215
|
-
import { homedir as homedir4 } from "node:os";
|
|
12216
|
-
import { dirname as dirname4, join as join10 } from "node:path";
|
|
12217
|
-
var HOOK_COMMANDS2 = {
|
|
12218
|
-
Stop: "onebrain checkpoint stop",
|
|
12219
|
-
PostCompact: "onebrain checkpoint postcompact"
|
|
12220
|
-
};
|
|
12221
|
-
var HOOK_EVENTS2 = ["Stop", "PostCompact"];
|
|
12222
|
-
var STALE_HOOK_COMMANDS2 = {
|
|
12223
|
-
PreCompact: "onebrain checkpoint precompact"
|
|
12224
|
-
};
|
|
12225
|
-
var PERMISSIONS_TO_ADD2 = [
|
|
12226
|
-
"Read",
|
|
12227
|
-
"Write",
|
|
12228
|
-
"Edit",
|
|
12229
|
-
"Glob",
|
|
12230
|
-
"Grep",
|
|
12231
|
-
"Bash(git *)",
|
|
12232
|
-
"Bash(bun *)",
|
|
12233
|
-
"Bash(gh *)",
|
|
12234
|
-
"Bash(node *)",
|
|
12235
|
-
"Bash(onebrain *)",
|
|
12236
|
-
"Bash(bun install -g @onebrain-ai/cli*)",
|
|
12237
|
-
"Bash(npm install -g @onebrain-ai/cli*)",
|
|
12238
|
-
"WebFetch",
|
|
12239
|
-
"WebSearch"
|
|
12240
|
-
];
|
|
12241
|
-
var ONEBRAIN_MARKER2 = "# onebrain";
|
|
12242
|
-
var PATH_EXPORT2 = 'export PATH="$HOME/.bun/bin:$HOME/.npm-global/bin:$PATH"';
|
|
12243
|
-
async function readSettings2(settingsPath) {
|
|
12244
|
-
try {
|
|
12245
|
-
const text = await readFile6(settingsPath, "utf8");
|
|
12246
|
-
return JSON.parse(text);
|
|
12247
|
-
} catch (err) {
|
|
12248
|
-
if (err.code === "ENOENT")
|
|
12249
|
-
return {};
|
|
12250
|
-
throw err;
|
|
12251
|
-
}
|
|
12252
|
-
}
|
|
12253
|
-
async function writeSettings2(settingsPath, settings) {
|
|
12254
|
-
await mkdir4(dirname4(settingsPath), { recursive: true });
|
|
12255
|
-
const tmpPath = `${settingsPath}.tmp`;
|
|
12256
|
-
await writeFile5(tmpPath, JSON.stringify(settings, null, 4), "utf8");
|
|
12257
|
-
await rename4(tmpPath, settingsPath);
|
|
12258
|
-
}
|
|
12259
|
-
function checkHookPresence2(groups, targetCmd) {
|
|
12260
|
-
let foundMigrate = false;
|
|
12261
|
-
for (const group of groups) {
|
|
12262
|
-
for (const entry of group.hooks ?? []) {
|
|
12263
|
-
const cmd = entry.command ?? "";
|
|
12264
|
-
if (cmd === targetCmd)
|
|
12265
|
-
return "found";
|
|
12266
|
-
if (cmd.includes("checkpoint-hook.sh"))
|
|
12267
|
-
foundMigrate = true;
|
|
12268
|
-
}
|
|
12269
|
-
}
|
|
12270
|
-
return foundMigrate ? "migrate" : "missing";
|
|
12271
|
-
}
|
|
12272
|
-
function applyHooks2(settings) {
|
|
12273
|
-
if (!settings.hooks)
|
|
12274
|
-
settings.hooks = {};
|
|
12275
|
-
const hooks = settings.hooks;
|
|
12276
|
-
const result = {};
|
|
12277
|
-
for (const [event, staleCmd] of Object.entries(STALE_HOOK_COMMANDS2)) {
|
|
12278
|
-
if (!hooks[event])
|
|
12279
|
-
continue;
|
|
12280
|
-
hooks[event] = hooks[event].filter((group) => !group.hooks?.some((entry) => entry.command === staleCmd));
|
|
12281
|
-
if (hooks[event].length === 0)
|
|
12282
|
-
delete hooks[event];
|
|
12283
|
-
}
|
|
12284
|
-
for (const event of HOOK_EVENTS2) {
|
|
12285
|
-
const cmd = HOOK_COMMANDS2[event];
|
|
12286
|
-
if (!cmd)
|
|
12287
|
-
continue;
|
|
12288
|
-
if (!hooks[event])
|
|
12289
|
-
hooks[event] = [];
|
|
12290
|
-
const groups = hooks[event];
|
|
12291
|
-
const presence = checkHookPresence2(groups, cmd);
|
|
12292
|
-
if (presence === "found") {
|
|
12293
|
-
result[event] = "ok";
|
|
12294
|
-
} else if (presence === "migrate") {
|
|
12295
|
-
for (const group of groups) {
|
|
12296
|
-
if (group.matcher === undefined)
|
|
12297
|
-
group.matcher = "";
|
|
12298
|
-
for (const entry of group.hooks ?? []) {
|
|
12299
|
-
if ((entry.command ?? "").includes("checkpoint-hook.sh")) {
|
|
12300
|
-
entry.command = cmd;
|
|
12301
|
-
if (!entry.type)
|
|
12302
|
-
entry.type = "command";
|
|
12303
|
-
}
|
|
12304
|
-
}
|
|
12305
|
-
}
|
|
12306
|
-
result[event] = "migrated";
|
|
12307
|
-
} else {
|
|
12308
|
-
groups.push({ matcher: "", hooks: [{ type: "command", command: cmd }] });
|
|
12309
|
-
result[event] = "added";
|
|
12310
|
-
}
|
|
12311
|
-
}
|
|
12312
|
-
return result;
|
|
12313
|
-
}
|
|
12314
|
-
var QMD_CMD2 = "onebrain qmd-reindex";
|
|
12315
|
-
var QMD_MATCHER2 = "Write|Edit";
|
|
12316
|
-
function applyQmdHook2(settings) {
|
|
12317
|
-
if (!settings.hooks)
|
|
12318
|
-
settings.hooks = {};
|
|
12319
|
-
if (!settings.hooks["PostToolUse"])
|
|
12320
|
-
settings.hooks["PostToolUse"] = [];
|
|
12321
|
-
const groups = settings.hooks["PostToolUse"];
|
|
12322
|
-
const already = groups.some((g) => g.hooks?.some((h) => h.command === QMD_CMD2));
|
|
12323
|
-
if (already)
|
|
12324
|
-
return "ok";
|
|
12325
|
-
groups.push({ matcher: QMD_MATCHER2, hooks: [{ type: "command", command: QMD_CMD2 }] });
|
|
12326
|
-
return "added";
|
|
12327
|
-
}
|
|
12328
|
-
function applyPermissions2(settings) {
|
|
12329
|
-
if (!settings.permissions)
|
|
12330
|
-
settings.permissions = {};
|
|
12331
|
-
if (!settings.permissions.allow)
|
|
12332
|
-
settings.permissions.allow = [];
|
|
12333
|
-
const allow = settings.permissions.allow;
|
|
12334
|
-
const added = [];
|
|
12335
|
-
for (const perm of PERMISSIONS_TO_ADD2) {
|
|
12336
|
-
if (!allow.includes(perm)) {
|
|
12337
|
-
allow.push(perm);
|
|
12338
|
-
added.push(perm);
|
|
12339
|
-
}
|
|
12340
|
-
}
|
|
12341
|
-
return added;
|
|
12342
|
-
}
|
|
12343
|
-
async function registerGeminiHooks2(vaultRoot) {
|
|
12344
|
-
const geminiSettingsPath = join10(vaultRoot, ".gemini", "settings.json");
|
|
12345
|
-
try {
|
|
12346
|
-
const text = await readFile6(geminiSettingsPath, "utf8");
|
|
12347
|
-
const settings = JSON.parse(text);
|
|
12348
|
-
applyHooks2(settings);
|
|
12349
|
-
await writeSettings2(geminiSettingsPath, settings);
|
|
12350
|
-
} catch (err) {
|
|
12351
|
-
if (err.code !== "ENOENT") {
|
|
12352
|
-
process.stderr.write(`register-hooks: gemini warning: ${err instanceof Error ? err.message : String(err)}
|
|
12353
|
-
`);
|
|
12354
|
-
}
|
|
12355
|
-
}
|
|
12356
|
-
}
|
|
12357
|
-
async function registerDirectPath2() {
|
|
12358
|
-
const home = homedir4();
|
|
12359
|
-
const candidates = [join10(home, ".zshrc"), join10(home, ".bashrc"), join10(home, ".profile")];
|
|
12360
|
-
let profilePath;
|
|
12361
|
-
for (const candidate of candidates) {
|
|
12362
|
-
try {
|
|
12363
|
-
await readFile6(candidate, "utf8");
|
|
12364
|
-
profilePath = candidate;
|
|
12365
|
-
break;
|
|
12366
|
-
} catch {}
|
|
12367
|
-
}
|
|
12368
|
-
if (!profilePath)
|
|
12369
|
-
return;
|
|
12370
|
-
const content = await readFile6(profilePath, "utf8");
|
|
12371
|
-
if (content.includes(ONEBRAIN_MARKER2))
|
|
12372
|
-
return;
|
|
12373
|
-
const updated = `${content}
|
|
12374
|
-
${ONEBRAIN_MARKER2}
|
|
12375
|
-
${PATH_EXPORT2}
|
|
12376
|
-
`;
|
|
12377
|
-
const tmpPath = `${profilePath}.tmp`;
|
|
12378
|
-
await writeFile5(tmpPath, updated, "utf8");
|
|
12379
|
-
await rename4(tmpPath, profilePath);
|
|
12380
|
-
}
|
|
12381
|
-
async function runRegisterHooks2(opts = {}) {
|
|
12382
|
-
const vaultRoot = opts.vaultDir ?? process.cwd();
|
|
12383
|
-
const isTTY = opts.isTTY ?? process.stdout.isTTY ?? false;
|
|
12384
|
-
const harness = await detectHarness(vaultRoot);
|
|
12385
|
-
let qmdCollection;
|
|
12386
|
-
try {
|
|
12387
|
-
const vaultConfig = await loadVaultConfig(vaultRoot);
|
|
12388
|
-
qmdCollection = vaultConfig.qmd_collection;
|
|
12389
|
-
} catch (err) {
|
|
12390
|
-
if (err.code !== "ENOENT") {
|
|
12391
|
-
process.stderr.write(`register-hooks: warning: could not read vault.yml: ${err instanceof Error ? err.message : String(err)}
|
|
12392
|
-
`);
|
|
12393
|
-
}
|
|
12394
|
-
}
|
|
12395
|
-
const result = {
|
|
12396
|
-
ok: false,
|
|
12397
|
-
hooks: {},
|
|
12398
|
-
permissionsAdded: []
|
|
12399
|
-
};
|
|
12400
|
-
const settingsPath = join10(vaultRoot, ".claude", "settings.json");
|
|
12401
|
-
const note = (msg) => {
|
|
12402
|
-
if (opts.silent)
|
|
12403
|
-
return;
|
|
12404
|
-
process.stdout.write(`register-hooks: ${msg}
|
|
12405
|
-
`);
|
|
12406
|
-
};
|
|
12407
|
-
let hooksSpinner = null;
|
|
12408
|
-
let permSpinner = null;
|
|
12409
|
-
try {
|
|
12410
|
-
if (harness === "claude") {
|
|
12411
|
-
hooksSpinner = isTTY ? L2() : null;
|
|
12412
|
-
hooksSpinner?.start("Registering hooks...");
|
|
12413
|
-
const settings = await readSettings2(settingsPath);
|
|
12414
|
-
result.hooks = applyHooks2(settings);
|
|
12415
|
-
let qmdStatus;
|
|
12416
|
-
if (qmdCollection)
|
|
12417
|
-
qmdStatus = applyQmdHook2(settings);
|
|
12418
|
-
if (isTTY) {
|
|
12419
|
-
const parts = HOOK_EVENTS2.map((e2) => {
|
|
12420
|
-
const status = result.hooks[e2];
|
|
12421
|
-
const icon = import_picocolors8.default.green(status === "ok" ? "✓" : status === "migrated" ? "↑" : "+");
|
|
12422
|
-
return `${import_picocolors8.default.dim(e2)} ${icon}`;
|
|
12423
|
-
});
|
|
12424
|
-
if (qmdStatus)
|
|
12425
|
-
parts.push(`${import_picocolors8.default.dim("PostToolUse")} ${import_picocolors8.default.green(qmdStatus === "ok" ? "✓" : "+")}`);
|
|
12426
|
-
hooksSpinner?.stop(`Hooks ${parts.join(" ")}`);
|
|
12427
|
-
} else {
|
|
12428
|
-
const hookLine = HOOK_EVENTS2.map((e2) => {
|
|
12429
|
-
const status = result.hooks[e2];
|
|
12430
|
-
const label = status === "ok" || status === "added" || status === "migrated" ? "ok" : status ?? "ok";
|
|
12431
|
-
return `${e2} ${label}`;
|
|
12432
|
-
}).join(" ");
|
|
12433
|
-
note(hookLine);
|
|
12434
|
-
if (qmdStatus)
|
|
12435
|
-
note(`PostToolUse ${qmdStatus === "added" ? "added" : "ok"}`);
|
|
12436
|
-
}
|
|
12437
|
-
permSpinner = isTTY ? L2() : null;
|
|
12438
|
-
permSpinner?.start("Updating permissions...");
|
|
12439
|
-
result.permissionsAdded = applyPermissions2(settings);
|
|
12440
|
-
await writeSettings2(settingsPath, settings);
|
|
12441
|
-
permSpinner?.stop("Permissions ok");
|
|
12442
|
-
if (!isTTY)
|
|
12443
|
-
note("permissions ok");
|
|
12444
|
-
}
|
|
12445
|
-
if (harness === "gemini") {
|
|
12446
|
-
await registerGeminiHooks2(vaultRoot);
|
|
12447
|
-
}
|
|
12448
|
-
if (harness === "direct") {
|
|
12449
|
-
await registerDirectPath2();
|
|
12450
|
-
}
|
|
12451
|
-
result.ok = true;
|
|
12452
|
-
if (!isTTY) {
|
|
12453
|
-
note("done");
|
|
12454
|
-
}
|
|
12455
|
-
} catch (err) {
|
|
12456
|
-
hooksSpinner?.stop("Registration failed");
|
|
12457
|
-
permSpinner?.stop("Permissions failed");
|
|
12458
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
12459
|
-
result.error = msg;
|
|
12460
|
-
process.stderr.write(`register-hooks: error: ${msg}
|
|
12461
|
-
`);
|
|
12462
|
-
}
|
|
12463
|
-
return result;
|
|
12464
|
-
}
|
|
12465
|
-
async function registerHooksCommand2(vaultDir) {
|
|
12466
|
-
const result = await runRegisterHooks2({
|
|
12467
|
-
...vaultDir !== undefined ? { vaultDir } : {}
|
|
12468
|
-
});
|
|
12469
|
-
if (!result.ok) {
|
|
12470
|
-
process.exit(1);
|
|
12471
|
-
}
|
|
12472
|
-
}
|
|
12209
|
+
// src/index.ts
|
|
12210
|
+
init_register_hooks();
|
|
12473
12211
|
|
|
12474
12212
|
// src/commands/internal/session-init.ts
|
|
12475
12213
|
init_lib();
|
|
12476
|
-
import { unlink as unlink2 } from "
|
|
12477
|
-
import { tmpdir as osTmpdir2 } from "
|
|
12478
|
-
import { join as
|
|
12214
|
+
import { unlink as unlink2 } from "fs/promises";
|
|
12215
|
+
import { tmpdir as osTmpdir2 } from "os";
|
|
12216
|
+
import { join as join10 } from "path";
|
|
12479
12217
|
var DAY_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
12480
12218
|
var MONTH_NAMES = [
|
|
12481
12219
|
"Jan",
|
|
@@ -12498,7 +12236,7 @@ function formatDatetime(date) {
|
|
|
12498
12236
|
const year = date.getFullYear();
|
|
12499
12237
|
const hh = String(date.getHours()).padStart(2, "0");
|
|
12500
12238
|
const mm = String(date.getMinutes()).padStart(2, "0");
|
|
12501
|
-
return `${dow}
|
|
12239
|
+
return `${dow} \xB7 ${day} ${mon} ${year} \xB7 ${hh}:${mm}`;
|
|
12502
12240
|
}
|
|
12503
12241
|
async function resolveSessionToken(tmpDir = osTmpdir2()) {
|
|
12504
12242
|
const wtSession = process.env["WT_SESSION"];
|
|
@@ -12525,7 +12263,7 @@ async function resolveSessionToken(tmpDir = osTmpdir2()) {
|
|
|
12525
12263
|
String(today.getMonth() + 1).padStart(2, "0"),
|
|
12526
12264
|
String(today.getDate()).padStart(2, "0")
|
|
12527
12265
|
].join("");
|
|
12528
|
-
const cacheFile =
|
|
12266
|
+
const cacheFile = join10(tmpDir, `onebrain-day-${yyyymmdd}.token`);
|
|
12529
12267
|
const cacheExists = await Bun.file(cacheFile).exists();
|
|
12530
12268
|
if (cacheExists) {
|
|
12531
12269
|
const cached = (await Bun.file(cacheFile).text()).trim();
|
|
@@ -12577,7 +12315,7 @@ async function resolveSessionToken(tmpDir = osTmpdir2()) {
|
|
|
12577
12315
|
async function cleanStaleStateFile(token, tmpDir) {
|
|
12578
12316
|
try {
|
|
12579
12317
|
const processStartMs = Date.now() - performance.now();
|
|
12580
|
-
const stateFile =
|
|
12318
|
+
const stateFile = join10(tmpDir, `onebrain-${token}.state`);
|
|
12581
12319
|
const f2 = Bun.file(stateFile);
|
|
12582
12320
|
const exists = await f2.exists();
|
|
12583
12321
|
if (!exists)
|
|
@@ -12642,523 +12380,11 @@ async function sessionInitCommand(vaultRoot) {
|
|
|
12642
12380
|
`);
|
|
12643
12381
|
}
|
|
12644
12382
|
|
|
12645
|
-
// src/
|
|
12646
|
-
|
|
12647
|
-
init_cli_ui();
|
|
12648
|
-
init_harness();
|
|
12649
|
-
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
12650
|
-
var import_yaml7 = __toESM(require_dist(), 1);
|
|
12651
|
-
import {
|
|
12652
|
-
mkdir as mkdir5,
|
|
12653
|
-
mkdtemp as mkdtemp2,
|
|
12654
|
-
readFile as readFile7,
|
|
12655
|
-
readdir as readdir5,
|
|
12656
|
-
rename as rename5,
|
|
12657
|
-
rm as rm2,
|
|
12658
|
-
stat as stat5,
|
|
12659
|
-
unlink as unlink3,
|
|
12660
|
-
writeFile as writeFile6
|
|
12661
|
-
} from "node:fs/promises";
|
|
12662
|
-
import { homedir as homedir5, tmpdir as tmpdir2 } from "node:os";
|
|
12663
|
-
import { dirname as dirname5, join as join12, relative as relative2 } from "node:path";
|
|
12664
|
-
function resolveBranch2(updateChannel) {
|
|
12665
|
-
return updateChannel === "stable" ? "main" : "next";
|
|
12666
|
-
}
|
|
12667
|
-
async function downloadTarball2(branch, fetchFn) {
|
|
12668
|
-
const url = `https://api.github.com/repos/kengio/onebrain/tarball/${branch}`;
|
|
12669
|
-
const response = await fetchFn(url);
|
|
12670
|
-
if (!response.ok) {
|
|
12671
|
-
const hints = {
|
|
12672
|
-
403: " — check repo permissions or GITHUB_TOKEN",
|
|
12673
|
-
404: " — repo or branch not found",
|
|
12674
|
-
429: " — rate limited, wait and retry"
|
|
12675
|
-
};
|
|
12676
|
-
const hint = hints[response.status] ?? "";
|
|
12677
|
-
throw new Error(`HTTP ${response.status} downloading tarball from ${url}${hint}`);
|
|
12678
|
-
}
|
|
12679
|
-
const tarball = await response.arrayBuffer();
|
|
12680
|
-
const tmpDir = await mkdtemp2(join12(tmpdir2(), "onebrain-sync-"));
|
|
12681
|
-
return { tarball, tmpDir };
|
|
12682
|
-
}
|
|
12683
|
-
async function extractTarball2(tarball, destDir) {
|
|
12684
|
-
const tarPath = join12(destDir, "bundle.tar.gz");
|
|
12685
|
-
await writeFile6(tarPath, Buffer.from(tarball));
|
|
12686
|
-
const proc = Bun.spawn(["tar", "-xzf", tarPath, "-C", destDir], {
|
|
12687
|
-
stdout: "pipe",
|
|
12688
|
-
stderr: "pipe"
|
|
12689
|
-
});
|
|
12690
|
-
const exitCode = await proc.exited;
|
|
12691
|
-
if (exitCode !== 0) {
|
|
12692
|
-
const errText = await new Response(proc.stderr).text();
|
|
12693
|
-
throw new Error(`tar extraction failed (exit ${exitCode}): ${errText.trim()}`);
|
|
12694
|
-
}
|
|
12695
|
-
await unlink3(tarPath);
|
|
12696
|
-
const entries = await readdir5(destDir);
|
|
12697
|
-
const topLevel = entries.find((e2) => e2 !== "bundle.tar.gz");
|
|
12698
|
-
if (!topLevel) {
|
|
12699
|
-
throw new Error("Extracted tarball contains no top-level directory");
|
|
12700
|
-
}
|
|
12701
|
-
return join12(destDir, topLevel);
|
|
12702
|
-
}
|
|
12703
|
-
async function listFilesRecursive2(dir) {
|
|
12704
|
-
const results = [];
|
|
12705
|
-
const queue = [dir];
|
|
12706
|
-
while (queue.length > 0) {
|
|
12707
|
-
const current = queue.pop();
|
|
12708
|
-
let entries;
|
|
12709
|
-
try {
|
|
12710
|
-
entries = await readdir5(current);
|
|
12711
|
-
} catch {
|
|
12712
|
-
continue;
|
|
12713
|
-
}
|
|
12714
|
-
for (const entry of entries) {
|
|
12715
|
-
const fullPath = join12(current, entry);
|
|
12716
|
-
let s;
|
|
12717
|
-
try {
|
|
12718
|
-
s = await stat5(fullPath);
|
|
12719
|
-
} catch {
|
|
12720
|
-
continue;
|
|
12721
|
-
}
|
|
12722
|
-
if (s.isDirectory()) {
|
|
12723
|
-
queue.push(fullPath);
|
|
12724
|
-
} else {
|
|
12725
|
-
results.push(fullPath);
|
|
12726
|
-
}
|
|
12727
|
-
}
|
|
12728
|
-
}
|
|
12729
|
-
return results;
|
|
12730
|
-
}
|
|
12731
|
-
async function syncPluginFiles2(extractedDir, vaultRoot, unlinkFn = unlink3) {
|
|
12732
|
-
const sourcePlugin = join12(extractedDir, ".claude", "plugins", "onebrain");
|
|
12733
|
-
const destPlugin = join12(vaultRoot, ".claude", "plugins", "onebrain");
|
|
12734
|
-
await mkdir5(destPlugin, { recursive: true });
|
|
12735
|
-
const sourceFiles = await listFilesRecursive2(sourcePlugin);
|
|
12736
|
-
const sourceRelSet = new Set(sourceFiles.map((f2) => relative2(sourcePlugin, f2)));
|
|
12737
|
-
const destFiles = await listFilesRecursive2(destPlugin);
|
|
12738
|
-
const destRelSet = new Set(destFiles.map((f2) => relative2(destPlugin, f2)));
|
|
12739
|
-
const staleRels = [];
|
|
12740
|
-
for (const rel of destRelSet) {
|
|
12741
|
-
if (!sourceRelSet.has(rel)) {
|
|
12742
|
-
staleRels.push(rel);
|
|
12743
|
-
}
|
|
12744
|
-
}
|
|
12745
|
-
let filesAdded = 0;
|
|
12746
|
-
for (const srcPath of sourceFiles) {
|
|
12747
|
-
const rel = relative2(sourcePlugin, srcPath);
|
|
12748
|
-
const destPath = join12(destPlugin, rel);
|
|
12749
|
-
await mkdir5(dirname5(destPath), { recursive: true });
|
|
12750
|
-
const content = await readFile7(srcPath);
|
|
12751
|
-
await writeFile6(destPath, content);
|
|
12752
|
-
filesAdded++;
|
|
12753
|
-
}
|
|
12754
|
-
let filesRemoved = 0;
|
|
12755
|
-
for (const rel of staleRels) {
|
|
12756
|
-
const destPath = join12(destPlugin, rel);
|
|
12757
|
-
try {
|
|
12758
|
-
await unlinkFn(destPath);
|
|
12759
|
-
filesRemoved++;
|
|
12760
|
-
} catch {}
|
|
12761
|
-
}
|
|
12762
|
-
return { filesAdded, filesRemoved };
|
|
12763
|
-
}
|
|
12764
|
-
async function copyRootDocs2(extractedDir, vaultRoot) {
|
|
12765
|
-
const docs = ["CONTRIBUTING.md", "CHANGELOG.md", "PLUGIN-CHANGELOG.md"];
|
|
12766
|
-
for (const doc of docs) {
|
|
12767
|
-
const srcPath = join12(extractedDir, doc);
|
|
12768
|
-
const destPath = join12(vaultRoot, doc);
|
|
12769
|
-
try {
|
|
12770
|
-
const content = await readFile7(srcPath);
|
|
12771
|
-
await writeFile6(destPath, content);
|
|
12772
|
-
} catch {}
|
|
12773
|
-
}
|
|
12774
|
-
}
|
|
12775
|
-
async function mergeHarnessFile2(extractedDir, vaultRoot, filename) {
|
|
12776
|
-
const srcPath = join12(extractedDir, filename);
|
|
12777
|
-
const destPath = join12(vaultRoot, filename);
|
|
12778
|
-
let repoText;
|
|
12779
|
-
try {
|
|
12780
|
-
repoText = await readFile7(srcPath, "utf8");
|
|
12781
|
-
} catch {
|
|
12782
|
-
return 0;
|
|
12783
|
-
}
|
|
12784
|
-
let vaultText;
|
|
12785
|
-
try {
|
|
12786
|
-
vaultText = await readFile7(destPath, "utf8");
|
|
12787
|
-
} catch {
|
|
12788
|
-
await writeFile6(destPath, repoText, "utf8");
|
|
12789
|
-
return repoText.split(`
|
|
12790
|
-
`).filter((l2) => l2.startsWith("@")).length;
|
|
12791
|
-
}
|
|
12792
|
-
const vaultAtSet = new Set(vaultText.split(`
|
|
12793
|
-
`).filter((l2) => l2.startsWith("@")).map((l2) => l2.trim()));
|
|
12794
|
-
const newImports = repoText.split(`
|
|
12795
|
-
`).filter((l2) => l2.startsWith("@") && !vaultAtSet.has(l2.trim())).map((l2) => l2.trimEnd());
|
|
12796
|
-
if (newImports.length === 0) {
|
|
12797
|
-
return 0;
|
|
12798
|
-
}
|
|
12799
|
-
const vaultLines = vaultText.split(`
|
|
12800
|
-
`);
|
|
12801
|
-
const lastAtIdx = vaultLines.reduce((acc, l2, i) => l2.startsWith("@") ? i : acc, -1);
|
|
12802
|
-
if (lastAtIdx >= 0) {
|
|
12803
|
-
vaultLines.splice(lastAtIdx, 0, ...newImports);
|
|
12804
|
-
} else {
|
|
12805
|
-
vaultLines.push("", ...newImports);
|
|
12806
|
-
}
|
|
12807
|
-
const merged = vaultLines.join(`
|
|
12808
|
-
`);
|
|
12809
|
-
await writeFile6(destPath, merged, "utf8");
|
|
12810
|
-
return newImports.length;
|
|
12811
|
-
}
|
|
12812
|
-
async function mergeHarnessFiles2(extractedDir, vaultRoot) {
|
|
12813
|
-
const harnessFiles = ["CLAUDE.md", "GEMINI.md", "AGENTS.md"];
|
|
12814
|
-
let totalImportsAdded = 0;
|
|
12815
|
-
const results = await Promise.all(harnessFiles.map((f2) => mergeHarnessFile2(extractedDir, vaultRoot, f2)));
|
|
12816
|
-
for (const n of results) {
|
|
12817
|
-
totalImportsAdded += n;
|
|
12818
|
-
}
|
|
12819
|
-
return totalImportsAdded;
|
|
12820
|
-
}
|
|
12821
|
-
async function updateVaultYml2(vaultRoot, updateChannel) {
|
|
12822
|
-
const vaultYmlPath = join12(vaultRoot, "vault.yml");
|
|
12823
|
-
let text;
|
|
12824
|
-
try {
|
|
12825
|
-
text = await readFile7(vaultYmlPath, "utf8");
|
|
12826
|
-
} catch {
|
|
12827
|
-
text = "";
|
|
12828
|
-
}
|
|
12829
|
-
const raw = import_yaml7.parse(text) ?? {};
|
|
12830
|
-
raw["update_channel"] = updateChannel;
|
|
12831
|
-
const updated = import_yaml7.stringify(raw, { lineWidth: 0 });
|
|
12832
|
-
const tmpPath = `${vaultYmlPath}.tmp`;
|
|
12833
|
-
await writeFile6(tmpPath, updated, "utf8");
|
|
12834
|
-
await rename5(tmpPath, vaultYmlPath);
|
|
12835
|
-
}
|
|
12836
|
-
async function readPluginVersion2(vaultRoot) {
|
|
12837
|
-
const pluginJsonPath = join12(vaultRoot, ".claude", "plugins", "onebrain", ".claude-plugin", "plugin.json");
|
|
12838
|
-
try {
|
|
12839
|
-
const text = await readFile7(pluginJsonPath, "utf8");
|
|
12840
|
-
const parsed = JSON.parse(text);
|
|
12841
|
-
return typeof parsed["version"] === "string" ? parsed["version"] : "unknown";
|
|
12842
|
-
} catch {
|
|
12843
|
-
return "unknown";
|
|
12844
|
-
}
|
|
12845
|
-
}
|
|
12846
|
-
async function pinToVault2(vaultRoot, installedPluginsPath, installedPluginsCacheDir) {
|
|
12847
|
-
let text;
|
|
12848
|
-
try {
|
|
12849
|
-
text = await readFile7(installedPluginsPath, "utf8");
|
|
12850
|
-
} catch {
|
|
12851
|
-
return { skipped: true };
|
|
12852
|
-
}
|
|
12853
|
-
let data;
|
|
12854
|
-
try {
|
|
12855
|
-
data = JSON.parse(text);
|
|
12856
|
-
} catch {
|
|
12857
|
-
throw new Error(`installed_plugins.json is not valid JSON: ${installedPluginsPath}`);
|
|
12858
|
-
}
|
|
12859
|
-
const plugins = data["plugins"];
|
|
12860
|
-
if (!plugins) {
|
|
12861
|
-
return { skipped: true };
|
|
12862
|
-
}
|
|
12863
|
-
const onebrainKeys = Object.keys(plugins).filter((k2) => k2.startsWith("onebrain@"));
|
|
12864
|
-
if (onebrainKeys.length === 0) {
|
|
12865
|
-
return { skipped: true };
|
|
12866
|
-
}
|
|
12867
|
-
const vaultPluginDir = join12(vaultRoot, ".claude", "plugins", "onebrain");
|
|
12868
|
-
const pluginVersion = await readPluginVersion2(vaultRoot);
|
|
12869
|
-
const cacheDir = installedPluginsCacheDir ?? join12(dirname5(installedPluginsPath), "cache");
|
|
12870
|
-
const hasMarketplace = onebrainKeys.some((k2) => {
|
|
12871
|
-
const entries = plugins[k2];
|
|
12872
|
-
return entries.some((e2) => e2["source"] === "marketplace");
|
|
12873
|
-
});
|
|
12874
|
-
if (hasMarketplace) {
|
|
12875
|
-
return { skipped: true };
|
|
12876
|
-
}
|
|
12877
|
-
let changed = false;
|
|
12878
|
-
for (const key of onebrainKeys) {
|
|
12879
|
-
const entries = plugins[key];
|
|
12880
|
-
for (const entry of entries) {
|
|
12881
|
-
const installPath = entry["installPath"];
|
|
12882
|
-
if (typeof installPath !== "string") {
|
|
12883
|
-
continue;
|
|
12884
|
-
}
|
|
12885
|
-
let inCache = false;
|
|
12886
|
-
try {
|
|
12887
|
-
inCache = installPath.startsWith(`${cacheDir}/`) || installPath === cacheDir;
|
|
12888
|
-
} catch {
|
|
12889
|
-
inCache = false;
|
|
12890
|
-
}
|
|
12891
|
-
if (!inCache) {
|
|
12892
|
-
continue;
|
|
12893
|
-
}
|
|
12894
|
-
entry["installPath"] = vaultPluginDir;
|
|
12895
|
-
entry["version"] = pluginVersion;
|
|
12896
|
-
changed = true;
|
|
12897
|
-
}
|
|
12898
|
-
}
|
|
12899
|
-
if (!changed) {
|
|
12900
|
-
return { skipped: false };
|
|
12901
|
-
}
|
|
12902
|
-
const tmpPath = `${installedPluginsPath}.tmp`;
|
|
12903
|
-
await writeFile6(tmpPath, JSON.stringify(data, null, 4), "utf8");
|
|
12904
|
-
await rename5(tmpPath, installedPluginsPath);
|
|
12905
|
-
return { skipped: false };
|
|
12906
|
-
}
|
|
12907
|
-
async function cleanPluginCache2(installedPluginsPath, installedPluginsCacheDir) {
|
|
12908
|
-
const cacheDir = installedPluginsCacheDir ?? join12(dirname5(installedPluginsPath), "cache");
|
|
12909
|
-
try {
|
|
12910
|
-
await stat5(cacheDir);
|
|
12911
|
-
} catch {
|
|
12912
|
-
return 0;
|
|
12913
|
-
}
|
|
12914
|
-
const onebrainDirs = [];
|
|
12915
|
-
try {
|
|
12916
|
-
const text = await readFile7(installedPluginsPath, "utf8");
|
|
12917
|
-
const data = JSON.parse(text);
|
|
12918
|
-
const plugins = data["plugins"];
|
|
12919
|
-
if (plugins) {
|
|
12920
|
-
for (const key of Object.keys(plugins)) {
|
|
12921
|
-
if (!key.startsWith("onebrain@"))
|
|
12922
|
-
continue;
|
|
12923
|
-
const marketplace = key.split("@")[1];
|
|
12924
|
-
const candidate = join12(cacheDir, marketplace, "onebrain");
|
|
12925
|
-
try {
|
|
12926
|
-
await stat5(candidate);
|
|
12927
|
-
onebrainDirs.push(candidate);
|
|
12928
|
-
} catch {}
|
|
12929
|
-
}
|
|
12930
|
-
}
|
|
12931
|
-
} catch {}
|
|
12932
|
-
if (onebrainDirs.length === 0) {
|
|
12933
|
-
try {
|
|
12934
|
-
const marketplaceDirs = await readdir5(cacheDir);
|
|
12935
|
-
for (const mp of marketplaceDirs) {
|
|
12936
|
-
const candidate = join12(cacheDir, mp, "onebrain");
|
|
12937
|
-
try {
|
|
12938
|
-
await stat5(candidate);
|
|
12939
|
-
onebrainDirs.push(candidate);
|
|
12940
|
-
} catch {}
|
|
12941
|
-
}
|
|
12942
|
-
} catch {
|
|
12943
|
-
return 0;
|
|
12944
|
-
}
|
|
12945
|
-
}
|
|
12946
|
-
let removed = 0;
|
|
12947
|
-
for (const pluginDir of onebrainDirs) {
|
|
12948
|
-
let versionDirs;
|
|
12949
|
-
try {
|
|
12950
|
-
versionDirs = await readdir5(pluginDir);
|
|
12951
|
-
} catch {
|
|
12952
|
-
continue;
|
|
12953
|
-
}
|
|
12954
|
-
for (const versionDir of versionDirs) {
|
|
12955
|
-
const fullPath = join12(pluginDir, versionDir);
|
|
12956
|
-
try {
|
|
12957
|
-
const s = await stat5(fullPath);
|
|
12958
|
-
if (s.isDirectory()) {
|
|
12959
|
-
await rm2(fullPath, { recursive: true, force: true });
|
|
12960
|
-
removed++;
|
|
12961
|
-
}
|
|
12962
|
-
} catch {}
|
|
12963
|
-
}
|
|
12964
|
-
}
|
|
12965
|
-
return removed;
|
|
12966
|
-
}
|
|
12967
|
-
async function runVaultSync2(vaultRoot, opts = {}) {
|
|
12968
|
-
const fetchFn = opts.fetchFn ?? globalThis.fetch;
|
|
12969
|
-
const isTTY = opts.isTTY ?? process.stdout.isTTY;
|
|
12970
|
-
const unlinkFn = opts.unlinkFn ?? unlink3;
|
|
12971
|
-
let updateChannel = "stable";
|
|
12972
|
-
try {
|
|
12973
|
-
const vaultYmlText = await readFile7(join12(vaultRoot, "vault.yml"), "utf8");
|
|
12974
|
-
const vaultYml = import_yaml7.parse(vaultYmlText) ?? {};
|
|
12975
|
-
if (typeof vaultYml["update_channel"] === "string") {
|
|
12976
|
-
updateChannel = vaultYml["update_channel"];
|
|
12977
|
-
}
|
|
12978
|
-
} catch {}
|
|
12979
|
-
const harness = await detectHarness(vaultRoot);
|
|
12980
|
-
const branch = opts.branch ?? resolveBranch2(updateChannel);
|
|
12981
|
-
const installedPluginsPath = opts.installedPluginsPath ?? join12(homedir5(), ".claude", "plugins", "installed_plugins.json");
|
|
12982
|
-
const installedPluginsCacheDir = opts.installedPluginsCacheDir;
|
|
12983
|
-
const result = {
|
|
12984
|
-
ok: false,
|
|
12985
|
-
version: "unknown",
|
|
12986
|
-
branch,
|
|
12987
|
-
filesAdded: 0,
|
|
12988
|
-
filesRemoved: 0,
|
|
12989
|
-
importsAdded: 0,
|
|
12990
|
-
pinSkipped: true,
|
|
12991
|
-
cacheRemoved: 0
|
|
12992
|
-
};
|
|
12993
|
-
const embedded = opts.embedded ?? false;
|
|
12994
|
-
const createEmbeddedStep = embedded ? makeStepFn(true) : null;
|
|
12995
|
-
let s = null;
|
|
12996
|
-
let currentStep = null;
|
|
12997
|
-
function startSpinner(emoji, label) {
|
|
12998
|
-
if (isTTY) {
|
|
12999
|
-
if (embedded) {
|
|
13000
|
-
currentStep = createEmbeddedStep(emoji, label);
|
|
13001
|
-
} else {
|
|
13002
|
-
s = L2();
|
|
13003
|
-
s.start(label);
|
|
13004
|
-
}
|
|
13005
|
-
} else {
|
|
13006
|
-
process.stdout.write(`vault-sync: ${label}
|
|
13007
|
-
`);
|
|
13008
|
-
}
|
|
13009
|
-
}
|
|
13010
|
-
function stopSpinner(result2, details) {
|
|
13011
|
-
if (isTTY) {
|
|
13012
|
-
if (embedded) {
|
|
13013
|
-
currentStep?.stop(import_picocolors9.default.dim(result2), details);
|
|
13014
|
-
currentStep = null;
|
|
13015
|
-
} else if (s) {
|
|
13016
|
-
s.stop(result2);
|
|
13017
|
-
s = null;
|
|
13018
|
-
}
|
|
13019
|
-
}
|
|
13020
|
-
}
|
|
13021
|
-
if (isTTY && !embedded) {
|
|
13022
|
-
we("OneBrain Vault Sync");
|
|
13023
|
-
}
|
|
13024
|
-
let tmpDir = null;
|
|
13025
|
-
try {
|
|
13026
|
-
startSpinner("\uD83D\uDCE5", "Downloading");
|
|
13027
|
-
let extractedDir;
|
|
13028
|
-
try {
|
|
13029
|
-
const dl = await downloadTarball2(branch, fetchFn);
|
|
13030
|
-
tmpDir = dl.tmpDir;
|
|
13031
|
-
extractedDir = await extractTarball2(dl.tarball, tmpDir);
|
|
13032
|
-
} catch (err) {
|
|
13033
|
-
stopSpinner("download failed");
|
|
13034
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
13035
|
-
result.error = msg;
|
|
13036
|
-
process.stderr.write(`vault-sync: download failed: ${msg}
|
|
13037
|
-
`);
|
|
13038
|
-
return result;
|
|
13039
|
-
}
|
|
13040
|
-
try {
|
|
13041
|
-
const pjText = await readFile7(join12(extractedDir, ".claude", "plugins", "onebrain", ".claude-plugin", "plugin.json"), "utf8");
|
|
13042
|
-
const pj = JSON.parse(pjText);
|
|
13043
|
-
if (typeof pj["version"] === "string") {
|
|
13044
|
-
result.version = pj["version"];
|
|
13045
|
-
}
|
|
13046
|
-
} catch {}
|
|
13047
|
-
stopSpinner(`kengio/onebrain@${branch} (v${result.version})`);
|
|
13048
|
-
startSpinner("\uD83D\uDCC2", "Syncing files");
|
|
13049
|
-
try {
|
|
13050
|
-
const { filesAdded, filesRemoved } = await syncPluginFiles2(extractedDir, vaultRoot, unlinkFn);
|
|
13051
|
-
result.filesAdded = filesAdded;
|
|
13052
|
-
result.filesRemoved = filesRemoved;
|
|
13053
|
-
} catch (err) {
|
|
13054
|
-
stopSpinner("plugin sync failed");
|
|
13055
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
13056
|
-
result.error = msg;
|
|
13057
|
-
process.stderr.write(`vault-sync: plugin sync failed: ${msg}
|
|
13058
|
-
`);
|
|
13059
|
-
return result;
|
|
13060
|
-
}
|
|
13061
|
-
stopSpinner(`${result.filesAdded} file${result.filesAdded !== 1 ? "s" : ""} synced, ${result.filesRemoved} removed`);
|
|
13062
|
-
if (opts.includeObsidian) {
|
|
13063
|
-
const sourceObsidian = join12(extractedDir, ".obsidian");
|
|
13064
|
-
const destObsidian = join12(vaultRoot, ".obsidian");
|
|
13065
|
-
try {
|
|
13066
|
-
const obsidianFiles = await listFilesRecursive2(sourceObsidian);
|
|
13067
|
-
for (const srcPath of obsidianFiles) {
|
|
13068
|
-
const rel = relative2(sourceObsidian, srcPath);
|
|
13069
|
-
const destPath = join12(destObsidian, rel);
|
|
13070
|
-
await mkdir5(dirname5(destPath), { recursive: true });
|
|
13071
|
-
const content = await readFile7(srcPath);
|
|
13072
|
-
await writeFile6(destPath, content);
|
|
13073
|
-
}
|
|
13074
|
-
} catch {}
|
|
13075
|
-
}
|
|
13076
|
-
await copyRootDocs2(extractedDir, vaultRoot);
|
|
13077
|
-
startSpinner("\uD83D\uDD27", "Updating harness");
|
|
13078
|
-
let importsAdded = 0;
|
|
13079
|
-
try {
|
|
13080
|
-
importsAdded = await mergeHarnessFiles2(extractedDir, vaultRoot);
|
|
13081
|
-
result.importsAdded = importsAdded;
|
|
13082
|
-
} catch (err) {
|
|
13083
|
-
stopSpinner("harness merge failed");
|
|
13084
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
13085
|
-
result.error = msg;
|
|
13086
|
-
process.stderr.write(`vault-sync: harness merge failed: ${msg}
|
|
13087
|
-
`);
|
|
13088
|
-
return result;
|
|
13089
|
-
}
|
|
13090
|
-
if (importsAdded > 0) {
|
|
13091
|
-
stopSpinner(`${importsAdded} import${importsAdded !== 1 ? "s" : ""} added`);
|
|
13092
|
-
} else {
|
|
13093
|
-
stopSpinner("harness files up-to-date");
|
|
13094
|
-
}
|
|
13095
|
-
try {
|
|
13096
|
-
await updateVaultYml2(vaultRoot, updateChannel);
|
|
13097
|
-
} catch (err) {
|
|
13098
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
13099
|
-
result.error = msg;
|
|
13100
|
-
process.stderr.write(`vault-sync: vault.yml update failed: ${msg}
|
|
13101
|
-
`);
|
|
13102
|
-
return result;
|
|
13103
|
-
}
|
|
13104
|
-
if (harness === "claude") {
|
|
13105
|
-
startSpinner("\uD83D\uDCCC", "Pinning to vault");
|
|
13106
|
-
try {
|
|
13107
|
-
const pinResult = await pinToVault2(vaultRoot, installedPluginsPath, installedPluginsCacheDir);
|
|
13108
|
-
result.pinSkipped = pinResult.skipped;
|
|
13109
|
-
if (pinResult.skipped) {
|
|
13110
|
-
stopSpinner("pin skipped (not found or marketplace)");
|
|
13111
|
-
} else {
|
|
13112
|
-
stopSpinner("installPath → .claude/plugins/onebrain");
|
|
13113
|
-
}
|
|
13114
|
-
} catch (err) {
|
|
13115
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
13116
|
-
process.stderr.write(`vault-sync: pin warning: ${msg}
|
|
13117
|
-
`);
|
|
13118
|
-
result.pinSkipped = true;
|
|
13119
|
-
stopSpinner("pin skipped (error — non-fatal)");
|
|
13120
|
-
}
|
|
13121
|
-
startSpinner("\uD83E\uDDF9", "Cleaning cache");
|
|
13122
|
-
try {
|
|
13123
|
-
const cacheRemoved = await cleanPluginCache2(installedPluginsPath, installedPluginsCacheDir);
|
|
13124
|
-
result.cacheRemoved = cacheRemoved;
|
|
13125
|
-
if (cacheRemoved > 0) {
|
|
13126
|
-
stopSpinner(`${cacheRemoved} cached version${cacheRemoved !== 1 ? "s" : ""} removed`);
|
|
13127
|
-
} else {
|
|
13128
|
-
stopSpinner("no cache to clean");
|
|
13129
|
-
}
|
|
13130
|
-
} catch (err) {
|
|
13131
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
13132
|
-
process.stderr.write(`vault-sync: cache clean warning: ${msg}
|
|
13133
|
-
`);
|
|
13134
|
-
stopSpinner("cache clean skipped (error — non-fatal)");
|
|
13135
|
-
}
|
|
13136
|
-
}
|
|
13137
|
-
result.ok = true;
|
|
13138
|
-
if (isTTY) {
|
|
13139
|
-
if (!embedded) {
|
|
13140
|
-
fe(`Done — v${result.version} synced`);
|
|
13141
|
-
}
|
|
13142
|
-
} else {
|
|
13143
|
-
process.stdout.write(`vault-sync: done
|
|
13144
|
-
`);
|
|
13145
|
-
}
|
|
13146
|
-
} finally {
|
|
13147
|
-
if (tmpDir) {
|
|
13148
|
-
rm2(tmpDir, { recursive: true, force: true }).catch(() => {});
|
|
13149
|
-
}
|
|
13150
|
-
}
|
|
13151
|
-
return result;
|
|
13152
|
-
}
|
|
13153
|
-
async function vaultSyncCommand2(vaultRoot, opts = {}) {
|
|
13154
|
-
const result = await runVaultSync2(vaultRoot, opts);
|
|
13155
|
-
if (!result.ok) {
|
|
13156
|
-
process.exit(1);
|
|
13157
|
-
}
|
|
13158
|
-
}
|
|
12383
|
+
// src/index.ts
|
|
12384
|
+
init_vault_sync();
|
|
13159
12385
|
|
|
13160
12386
|
// src/commands/update.ts
|
|
13161
|
-
var
|
|
12387
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
13162
12388
|
init_cli_ui();
|
|
13163
12389
|
var GITHUB_REPO = "https://api.github.com/repos/kengio/onebrain";
|
|
13164
12390
|
var GITHUB_RELEASES_URL = `${GITHUB_REPO}/releases/latest`;
|
|
@@ -13253,7 +12479,7 @@ async function runUpdate(opts = {}) {
|
|
|
13253
12479
|
const sp1 = createStep("\uD83D\uDD0D", "Local version");
|
|
13254
12480
|
const { version: currentVersion, publishedAt: localPublishedAt } = await currentVersionFn();
|
|
13255
12481
|
result.currentVersion = currentVersion;
|
|
13256
|
-
const localVersionLabel = localPublishedAt ? `${
|
|
12482
|
+
const localVersionLabel = localPublishedAt ? `${import_picocolors8.default.dim(currentVersion)} ${import_picocolors8.default.dim("\xB7")} ${import_picocolors8.default.dim(formatReleaseDate(localPublishedAt))}` : import_picocolors8.default.dim(currentVersion);
|
|
13257
12483
|
if (sp1)
|
|
13258
12484
|
sp1.stop(localVersionLabel);
|
|
13259
12485
|
else
|
|
@@ -13265,9 +12491,9 @@ async function runUpdate(opts = {}) {
|
|
|
13265
12491
|
const release = await fetchLatestRelease(fetchFn);
|
|
13266
12492
|
latestVersion = release.version;
|
|
13267
12493
|
publishedAt = release.publishedAt;
|
|
13268
|
-
const dateSuffix = publishedAt ? ` ${
|
|
12494
|
+
const dateSuffix = publishedAt ? ` ${import_picocolors8.default.dim("\xB7")} ${import_picocolors8.default.dim(formatReleaseDate(publishedAt))}` : "";
|
|
13269
12495
|
if (sp2)
|
|
13270
|
-
sp2.stop(`${
|
|
12496
|
+
sp2.stop(`${import_picocolors8.default.green(latestVersion)}${dateSuffix}`);
|
|
13271
12497
|
else
|
|
13272
12498
|
writeLine(`latest: ${latestVersion}`);
|
|
13273
12499
|
} catch (err) {
|
|
@@ -13288,12 +12514,12 @@ async function runUpdate(opts = {}) {
|
|
|
13288
12514
|
if (check) {
|
|
13289
12515
|
if (isTTY) {
|
|
13290
12516
|
if (currentVersion !== latestVersion) {
|
|
13291
|
-
barLine(
|
|
12517
|
+
barLine(`\u2B06\uFE0F ${import_picocolors8.default.dim(currentVersion)} \u2192 ${import_picocolors8.default.green(latestVersion)} \xB7 binary would upgrade`);
|
|
13292
12518
|
barBlank();
|
|
13293
12519
|
}
|
|
13294
|
-
close("Dry run complete
|
|
12520
|
+
close("Dry run complete \u2014 no changes made");
|
|
13295
12521
|
} else {
|
|
13296
|
-
writeLine("done: dry run complete
|
|
12522
|
+
writeLine("done: dry run complete \u2014 no changes made");
|
|
13297
12523
|
}
|
|
13298
12524
|
result.ok = true;
|
|
13299
12525
|
result.exitCode = 0;
|
|
@@ -13301,7 +12527,7 @@ async function runUpdate(opts = {}) {
|
|
|
13301
12527
|
}
|
|
13302
12528
|
if (latestVersion === currentVersion) {
|
|
13303
12529
|
if (isTTY) {
|
|
13304
|
-
close(`Already up to date
|
|
12530
|
+
close(`Already up to date \u2014 @onebrain-ai/cli ${import_picocolors8.default.dim(latestVersion)}`);
|
|
13305
12531
|
} else {
|
|
13306
12532
|
writeLine(`already up to date: @onebrain-ai/cli ${latestVersion}`);
|
|
13307
12533
|
writeLine("done: nothing to do");
|
|
@@ -13311,14 +12537,14 @@ async function runUpdate(opts = {}) {
|
|
|
13311
12537
|
return result;
|
|
13312
12538
|
}
|
|
13313
12539
|
if (isTTY) {
|
|
13314
|
-
barLine(
|
|
12540
|
+
barLine(`\u2B06\uFE0F ${import_picocolors8.default.dim(currentVersion)} \u2192 ${import_picocolors8.default.green(latestVersion)}`);
|
|
13315
12541
|
barBlank();
|
|
13316
12542
|
}
|
|
13317
12543
|
const sp3 = createStep("\uD83D\uDCE6", "Installing @onebrain-ai/cli");
|
|
13318
12544
|
try {
|
|
13319
12545
|
await installBinaryFn(latestVersion);
|
|
13320
12546
|
if (sp3)
|
|
13321
|
-
sp3.stop(
|
|
12547
|
+
sp3.stop(import_picocolors8.default.green(latestVersion));
|
|
13322
12548
|
else
|
|
13323
12549
|
writeLine(`upgrading: @onebrain-ai/cli ${latestVersion} installed`);
|
|
13324
12550
|
} catch (err) {
|
|
@@ -13335,7 +12561,7 @@ async function runUpdate(opts = {}) {
|
|
|
13335
12561
|
}
|
|
13336
12562
|
return result;
|
|
13337
12563
|
}
|
|
13338
|
-
const sp4 = createStep("
|
|
12564
|
+
const sp4 = createStep("\u2705", "Validating binary");
|
|
13339
12565
|
const binaryValid = await validateBinaryFn();
|
|
13340
12566
|
if (!binaryValid) {
|
|
13341
12567
|
if (sp4)
|
|
@@ -13355,7 +12581,7 @@ async function runUpdate(opts = {}) {
|
|
|
13355
12581
|
result.ok = true;
|
|
13356
12582
|
result.exitCode = 0;
|
|
13357
12583
|
if (isTTY) {
|
|
13358
|
-
close(`Done
|
|
12584
|
+
close(`Done \u2014 run ${import_picocolors8.default.cyan("/update")} in Claude to sync vault files`);
|
|
13359
12585
|
} else {
|
|
13360
12586
|
writeLine("done: run /update in Claude to sync vault files");
|
|
13361
12587
|
}
|
|
@@ -13382,7 +12608,7 @@ function patchUtf8(stream) {
|
|
|
13382
12608
|
}
|
|
13383
12609
|
|
|
13384
12610
|
// src/index.ts
|
|
13385
|
-
var VERSION = "2.1.
|
|
12611
|
+
var VERSION = "2.1.4";
|
|
13386
12612
|
var RELEASE_DATE = "2026-04-28";
|
|
13387
12613
|
patchUtf8(process.stdout);
|
|
13388
12614
|
patchUtf8(process.stderr);
|
|
@@ -13397,9 +12623,9 @@ function findVaultRoot(startDir) {
|
|
|
13397
12623
|
return process.cwd();
|
|
13398
12624
|
let dir = startDir;
|
|
13399
12625
|
while (true) {
|
|
13400
|
-
if (existsSync(
|
|
12626
|
+
if (existsSync(join11(dir, "vault.yml")))
|
|
13401
12627
|
return dir;
|
|
13402
|
-
const parent =
|
|
12628
|
+
const parent = dirname4(dir);
|
|
13403
12629
|
if (parent === dir)
|
|
13404
12630
|
return startDir;
|
|
13405
12631
|
dir = parent;
|
|
@@ -13446,10 +12672,10 @@ program2.command("qmd-reindex", { hidden: true }).description("Trigger qmd index
|
|
|
13446
12672
|
});
|
|
13447
12673
|
program2.command("vault-sync", { hidden: true }).description("Sync plugin files from GitHub to vault").argument("[vault_root]", "vault root directory (default: cwd)").option("--branch <branch>", "override branch (main | next)").action(async (vaultRoot, opts) => {
|
|
13448
12674
|
const root = vaultRoot ?? process.cwd();
|
|
13449
|
-
await
|
|
12675
|
+
await vaultSyncCommand(root, opts.branch !== undefined ? { branch: opts.branch } : {});
|
|
13450
12676
|
});
|
|
13451
12677
|
program2.command("register-hooks", { hidden: true }).description("Install Claude Code hooks into settings.json").option("--vault-dir <path>", "vault root directory (default: cwd)").action(async (opts) => {
|
|
13452
|
-
await
|
|
12678
|
+
await registerHooksCommand(opts.vaultDir);
|
|
13453
12679
|
});
|
|
13454
12680
|
program2.command("migrate", { hidden: true }).description("Run one-time migration scripts").argument("<name>", "migration name: backfill-recapped").argument("[cutoff_date]", "ISO date cutoff (YYYY-MM-DD) \u2014 skip logs newer than this date").action(async (name, cutoffDate) => {
|
|
13455
12681
|
await migrateCommand(name, cutoffDate);
|