@onebrain-ai/cli 2.1.2 → 2.1.5
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 +553 -1138
- 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,16 +9099,16 @@ 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",
|
|
9107
9106
|
status: "warn",
|
|
9108
9107
|
message: summary,
|
|
9109
|
-
hint: "
|
|
9108
|
+
hint: "Advisory: run /qmd embed when ready (or onebrain doctor --fix)",
|
|
9110
9109
|
details: [
|
|
9111
9110
|
`collection: ${config.qmd_collection}`,
|
|
9112
|
-
"
|
|
9111
|
+
"Advisory: run /qmd embed when ready (or onebrain doctor --fix)"
|
|
9113
9112
|
]
|
|
9114
9113
|
};
|
|
9115
9114
|
}
|
|
@@ -9141,20 +9140,7 @@ async function checkOrphanCheckpoints(vaultRoot, config) {
|
|
|
9141
9140
|
message: "0 orphans"
|
|
9142
9141
|
};
|
|
9143
9142
|
}
|
|
9144
|
-
|
|
9145
|
-
return {
|
|
9146
|
-
check: "orphan-checkpoints",
|
|
9147
|
-
status: "ok",
|
|
9148
|
-
message: "0 orphans"
|
|
9149
|
-
};
|
|
9150
|
-
}
|
|
9151
|
-
let orphanCount = 0;
|
|
9152
|
-
for (const filePath of checkpointFiles) {
|
|
9153
|
-
const merged = await readMergedField(filePath);
|
|
9154
|
-
if (merged !== true) {
|
|
9155
|
-
orphanCount++;
|
|
9156
|
-
}
|
|
9157
|
-
}
|
|
9143
|
+
const orphanCount = checkpointFiles.length;
|
|
9158
9144
|
if (orphanCount === 0) {
|
|
9159
9145
|
return {
|
|
9160
9146
|
check: "orphan-checkpoints",
|
|
@@ -9170,30 +9156,6 @@ async function checkOrphanCheckpoints(vaultRoot, config) {
|
|
|
9170
9156
|
details: ["Run /wrapup to synthesize and merge them"]
|
|
9171
9157
|
};
|
|
9172
9158
|
}
|
|
9173
|
-
async function readMergedField(filePath) {
|
|
9174
|
-
try {
|
|
9175
|
-
const file = Bun.file(filePath);
|
|
9176
|
-
const text = await file.text();
|
|
9177
|
-
if (!text.startsWith("---"))
|
|
9178
|
-
return;
|
|
9179
|
-
const endIdx = text.indexOf(`
|
|
9180
|
-
---`, 3);
|
|
9181
|
-
if (endIdx === -1)
|
|
9182
|
-
return;
|
|
9183
|
-
const frontmatter = text.slice(3, endIdx).trim();
|
|
9184
|
-
const parsed = import_yaml2.parse(frontmatter);
|
|
9185
|
-
if (!parsed)
|
|
9186
|
-
return;
|
|
9187
|
-
const merged = parsed["merged"];
|
|
9188
|
-
if (merged === true || merged === "true")
|
|
9189
|
-
return true;
|
|
9190
|
-
if (merged === false || merged === "false")
|
|
9191
|
-
return false;
|
|
9192
|
-
return;
|
|
9193
|
-
} catch {
|
|
9194
|
-
return;
|
|
9195
|
-
}
|
|
9196
|
-
}
|
|
9197
9159
|
async function checkPluginFiles(vaultRoot) {
|
|
9198
9160
|
const pluginBase = join2(vaultRoot, ".claude", "plugins", "onebrain");
|
|
9199
9161
|
const missingFiles = [];
|
|
@@ -9267,7 +9229,7 @@ async function checkPluginFiles(vaultRoot) {
|
|
|
9267
9229
|
check: "plugin-files",
|
|
9268
9230
|
status: "ok",
|
|
9269
9231
|
message: "all required files present",
|
|
9270
|
-
details: [`${skillCount} skills
|
|
9232
|
+
details: [`${skillCount} skills \xB7 ${agentCount} agents \xB7 INSTRUCTIONS.md \u2713`]
|
|
9271
9233
|
};
|
|
9272
9234
|
}
|
|
9273
9235
|
async function checkVaultYmlKeys(vaultRoot) {
|
|
@@ -9392,14 +9354,14 @@ async function checkSettingsHooks(vaultRoot, config) {
|
|
|
9392
9354
|
if (!hookPresent(settings, event, cmdSubstring)) {
|
|
9393
9355
|
warnings.push(`${event} hook missing`);
|
|
9394
9356
|
} else {
|
|
9395
|
-
confirmedHooks.push(`${event}
|
|
9357
|
+
confirmedHooks.push(`${event} \u2713`);
|
|
9396
9358
|
}
|
|
9397
9359
|
}
|
|
9398
9360
|
if (config.qmd_collection) {
|
|
9399
9361
|
if (!hookPresent(settings, "PostToolUse", QMD_HOOK_SUBSTRING)) {
|
|
9400
9362
|
warnings.push("PostToolUse (qmd) hook missing");
|
|
9401
9363
|
} else {
|
|
9402
|
-
confirmedHooks.push("PostToolUse
|
|
9364
|
+
confirmedHooks.push("PostToolUse \u2713");
|
|
9403
9365
|
}
|
|
9404
9366
|
}
|
|
9405
9367
|
const precompactGroups = settings.hooks?.["PreCompact"] ?? [];
|
|
@@ -9438,7 +9400,7 @@ async function checkSettingsHooks(vaultRoot, config) {
|
|
|
9438
9400
|
if (confirmedHooks.length > 0)
|
|
9439
9401
|
okDetails.push(`hooks: ${confirmedHooks.join(" ")}`);
|
|
9440
9402
|
if (permissionOk)
|
|
9441
|
-
okDetails.push("permissions: Bash(onebrain *)
|
|
9403
|
+
okDetails.push("permissions: Bash(onebrain *) \u2713");
|
|
9442
9404
|
return {
|
|
9443
9405
|
check: "settings-hooks",
|
|
9444
9406
|
status: "ok",
|
|
@@ -9498,8 +9460,8 @@ var init_lib = __esm(() => {
|
|
|
9498
9460
|
var require_package = __commonJS((exports, module) => {
|
|
9499
9461
|
module.exports = {
|
|
9500
9462
|
name: "@onebrain-ai/cli",
|
|
9501
|
-
version: "2.1.
|
|
9502
|
-
description: "CLI for OneBrain
|
|
9463
|
+
version: "2.1.5",
|
|
9464
|
+
description: "CLI for OneBrain \u2014 personal AI OS for Obsidian with persistent memory, 24+ skills, and Claude Code integration",
|
|
9503
9465
|
keywords: [
|
|
9504
9466
|
"onebrain",
|
|
9505
9467
|
"obsidian",
|
|
@@ -9524,9 +9486,11 @@ var require_package = __commonJS((exports, module) => {
|
|
|
9524
9486
|
bin: {
|
|
9525
9487
|
onebrain: "dist/onebrain"
|
|
9526
9488
|
},
|
|
9527
|
-
files: ["dist/onebrain"],
|
|
9489
|
+
files: ["dist/onebrain", "dist/postinstall.js"],
|
|
9528
9490
|
scripts: {
|
|
9529
9491
|
build: "bun build src/index.ts --outfile dist/onebrain --target bun",
|
|
9492
|
+
"build:postinstall": "bun build src/scripts/postinstall.ts --outfile dist/postinstall.js --target node",
|
|
9493
|
+
postinstall: "node dist/postinstall.js",
|
|
9530
9494
|
test: "bun test --pass-with-no-tests src/",
|
|
9531
9495
|
typecheck: "tsc --noEmit"
|
|
9532
9496
|
},
|
|
@@ -9561,15 +9525,19 @@ function barBlank() {
|
|
|
9561
9525
|
out(`${bar}
|
|
9562
9526
|
`);
|
|
9563
9527
|
}
|
|
9528
|
+
function barOpen(msg) {
|
|
9529
|
+
out(`${import_picocolors2.default.cyan("\u250C")} ${msg}
|
|
9530
|
+
`);
|
|
9531
|
+
}
|
|
9564
9532
|
function close(msg, isError = false, isWarning = false) {
|
|
9565
9533
|
if (isError) {
|
|
9566
|
-
out(`${import_picocolors2.default.cyan("
|
|
9534
|
+
out(`${import_picocolors2.default.cyan("\u2514")} ${import_picocolors2.default.bold(import_picocolors2.default.red(msg))}
|
|
9567
9535
|
`);
|
|
9568
9536
|
} else if (isWarning) {
|
|
9569
|
-
out(`${import_picocolors2.default.cyan("
|
|
9537
|
+
out(`${import_picocolors2.default.cyan("\u2514")} ${import_picocolors2.default.yellow(msg)}
|
|
9570
9538
|
`);
|
|
9571
9539
|
} else {
|
|
9572
|
-
out(`${import_picocolors2.default.cyan("
|
|
9540
|
+
out(`${import_picocolors2.default.cyan("\u2514")} ${msg}
|
|
9573
9541
|
`);
|
|
9574
9542
|
}
|
|
9575
9543
|
}
|
|
@@ -9581,13 +9549,13 @@ function makeStepFn(isTTY) {
|
|
|
9581
9549
|
return function createStep(emoji, label) {
|
|
9582
9550
|
if (!isTTY)
|
|
9583
9551
|
return null;
|
|
9584
|
-
const frames = ["
|
|
9552
|
+
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
9585
9553
|
let i = 0;
|
|
9586
|
-
out(`${import_picocolors2.default.green(frames[0])} ${emoji} ${label}
|
|
9554
|
+
out(`${import_picocolors2.default.green(frames[0])} ${emoji} ${label}\u2026
|
|
9587
9555
|
`);
|
|
9588
9556
|
const timer = setInterval(() => {
|
|
9589
9557
|
i = (i + 1) % frames.length;
|
|
9590
|
-
out(`\x1B[1A\x1B[2K${import_picocolors2.default.green(frames[i])} ${emoji} ${label}
|
|
9558
|
+
out(`\x1B[1A\x1B[2K${import_picocolors2.default.green(frames[i])} ${emoji} ${label}\u2026
|
|
9591
9559
|
`);
|
|
9592
9560
|
}, 80);
|
|
9593
9561
|
return {
|
|
@@ -9600,19 +9568,19 @@ function makeStepFn(isTTY) {
|
|
|
9600
9568
|
barLine(result);
|
|
9601
9569
|
if (details)
|
|
9602
9570
|
for (const d of details)
|
|
9603
|
-
barLine(`
|
|
9571
|
+
barLine(` \xB7 ${d}`);
|
|
9604
9572
|
barBlank();
|
|
9605
9573
|
}
|
|
9606
9574
|
};
|
|
9607
9575
|
};
|
|
9608
9576
|
}
|
|
9609
9577
|
async function askYesNo(question) {
|
|
9610
|
-
out(`${import_picocolors2.default.cyan("
|
|
9578
|
+
out(`${import_picocolors2.default.cyan("\u25C6")} ${question}
|
|
9611
9579
|
`);
|
|
9612
9580
|
process.stdout.write(Buffer.from("\x1B[?25l", "utf8"));
|
|
9613
9581
|
function renderOptions(yes) {
|
|
9614
|
-
const yesLabel = yes ? `${import_picocolors2.default.bold(import_picocolors2.default.green("
|
|
9615
|
-
const noLabel = yes ? `${import_picocolors2.default.dim("
|
|
9582
|
+
const yesLabel = yes ? `${import_picocolors2.default.bold(import_picocolors2.default.green("\u25CF"))} Yes` : `${import_picocolors2.default.dim("\u25CB")} Yes`;
|
|
9583
|
+
const noLabel = yes ? `${import_picocolors2.default.dim("\u25CB")} No` : `${import_picocolors2.default.bold(import_picocolors2.default.green("\u25CF"))} No`;
|
|
9616
9584
|
out(`\x1B[2K${bar} ${yesLabel} / ${noLabel}\r`);
|
|
9617
9585
|
}
|
|
9618
9586
|
const answer = await new Promise((resolve) => {
|
|
@@ -9664,8 +9632,8 @@ async function askYesNo(question) {
|
|
|
9664
9632
|
var import_picocolors2, bar, dot;
|
|
9665
9633
|
var init_cli_ui = __esm(() => {
|
|
9666
9634
|
import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
9667
|
-
bar = import_picocolors2.default.cyan("
|
|
9668
|
-
dot = import_picocolors2.default.green("
|
|
9635
|
+
bar = import_picocolors2.default.cyan("\u2502");
|
|
9636
|
+
dot = import_picocolors2.default.green("\u25CF");
|
|
9669
9637
|
});
|
|
9670
9638
|
|
|
9671
9639
|
// node_modules/sisteransi/src/index.js
|
|
@@ -9727,8 +9695,8 @@ var require_src = __commonJS((exports, module) => {
|
|
|
9727
9695
|
});
|
|
9728
9696
|
|
|
9729
9697
|
// node_modules/@clack/core/dist/index.mjs
|
|
9730
|
-
import { stdin as $, stdout as j } from "
|
|
9731
|
-
import * as f from "
|
|
9698
|
+
import { stdin as $, stdout as j } from "process";
|
|
9699
|
+
import * as f from "readline";
|
|
9732
9700
|
function J({ onlyFirst: t = false } = {}) {
|
|
9733
9701
|
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
9702
|
return new RegExp(F, t ? undefined : "g");
|
|
@@ -9847,7 +9815,7 @@ var init_dist = __esm(() => {
|
|
|
9847
9815
|
eD = Object.keys(r.bgColor);
|
|
9848
9816
|
[...tD, ...eD];
|
|
9849
9817
|
iD = sD();
|
|
9850
|
-
v = new Set(["\x1B", "
|
|
9818
|
+
v = new Set(["\x1B", "\x9B"]);
|
|
9851
9819
|
y = `${rD}8;;`;
|
|
9852
9820
|
aD = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
9853
9821
|
c = { actions: new Set(aD), aliases: new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["\x03", "cancel"], ["escape", "cancel"]]) };
|
|
@@ -9856,7 +9824,7 @@ var init_dist = __esm(() => {
|
|
|
9856
9824
|
});
|
|
9857
9825
|
|
|
9858
9826
|
// node_modules/@clack/prompts/dist/index.mjs
|
|
9859
|
-
import p from "
|
|
9827
|
+
import p from "process";
|
|
9860
9828
|
function X2() {
|
|
9861
9829
|
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
9830
|
}
|
|
@@ -9869,7 +9837,7 @@ ${import_picocolors3.default.gray(m2)} ${s}
|
|
|
9869
9837
|
|
|
9870
9838
|
`);
|
|
9871
9839
|
}, L2 = () => {
|
|
9872
|
-
const s = E ? ["
|
|
9840
|
+
const s = E ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], n = E ? 80 : 120, t = process.env.CI === "true";
|
|
9873
9841
|
let i, r2, c2 = false, o = "", l2;
|
|
9874
9842
|
const $2 = (h) => {
|
|
9875
9843
|
const g = h > 1 ? "Something went wrong" : "Canceled";
|
|
@@ -9913,32 +9881,32 @@ var init_dist2 = __esm(() => {
|
|
|
9913
9881
|
import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
9914
9882
|
import_sisteransi2 = __toESM(require_src(), 1);
|
|
9915
9883
|
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("
|
|
9884
|
+
ee = u("\u25C6", "*");
|
|
9885
|
+
A = u("\u25A0", "x");
|
|
9886
|
+
B = u("\u25B2", "x");
|
|
9887
|
+
S2 = u("\u25C7", "o");
|
|
9888
|
+
te = u("\u250C", "T");
|
|
9889
|
+
a = u("\u2502", "|");
|
|
9890
|
+
m2 = u("\u2514", "\u2014");
|
|
9891
|
+
j2 = u("\u25CF", ">");
|
|
9892
|
+
R = u("\u25CB", " ");
|
|
9893
|
+
V = u("\u25FB", "[\u2022]");
|
|
9894
|
+
M = u("\u25FC", "[+]");
|
|
9895
|
+
G = u("\u25FB", "[ ]");
|
|
9896
|
+
se = u("\u25AA", "\u2022");
|
|
9897
|
+
N2 = u("\u2500", "-");
|
|
9898
|
+
re = u("\u256E", "+");
|
|
9899
|
+
ie = u("\u251C", "+");
|
|
9900
|
+
ne = u("\u256F", "+");
|
|
9901
|
+
ae = u("\u25CF", "\u2022");
|
|
9902
|
+
oe = u("\u25C6", "*");
|
|
9903
|
+
ce = u("\u25B2", "!");
|
|
9904
|
+
le = u("\u25A0", "x");
|
|
9937
9905
|
});
|
|
9938
9906
|
|
|
9939
9907
|
// src/commands/internal/harness.ts
|
|
9940
|
-
import { stat as stat2 } from "
|
|
9941
|
-
import { join as join3 } from "
|
|
9908
|
+
import { stat as stat2 } from "fs/promises";
|
|
9909
|
+
import { join as join3 } from "path";
|
|
9942
9910
|
async function pathExists(p2) {
|
|
9943
9911
|
try {
|
|
9944
9912
|
await stat2(p2);
|
|
@@ -9956,7 +9924,7 @@ async function detectHarness(vaultRoot) {
|
|
|
9956
9924
|
return "gemini";
|
|
9957
9925
|
if (env === "direct")
|
|
9958
9926
|
return "direct";
|
|
9959
|
-
process.stderr.write(`harness: unknown ONEBRAIN_HARNESS value "${env}"
|
|
9927
|
+
process.stderr.write(`harness: unknown ONEBRAIN_HARNESS value "${env}" \u2014 ignoring, falling back to directory detection
|
|
9960
9928
|
`);
|
|
9961
9929
|
}
|
|
9962
9930
|
if (await pathExists(join3(vaultRoot, ".gemini")))
|
|
@@ -9973,9 +9941,9 @@ __export(exports_register_hooks, {
|
|
|
9973
9941
|
runRegisterHooks: () => runRegisterHooks,
|
|
9974
9942
|
registerHooksCommand: () => registerHooksCommand
|
|
9975
9943
|
});
|
|
9976
|
-
import { mkdir, readFile, rename, writeFile } from "
|
|
9977
|
-
import { homedir } from "
|
|
9978
|
-
import { dirname, join as join4 } from "
|
|
9944
|
+
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
9945
|
+
import { homedir } from "os";
|
|
9946
|
+
import { dirname, join as join4 } from "path";
|
|
9979
9947
|
async function readSettings(settingsPath) {
|
|
9980
9948
|
try {
|
|
9981
9949
|
const text = await readFile(settingsPath, "utf8");
|
|
@@ -10152,11 +10120,11 @@ async function runRegisterHooks(opts = {}) {
|
|
|
10152
10120
|
if (isTTY) {
|
|
10153
10121
|
const parts = HOOK_EVENTS.map((e2) => {
|
|
10154
10122
|
const status = result.hooks[e2];
|
|
10155
|
-
const icon = import_picocolors4.default.green(status === "ok" ? "
|
|
10123
|
+
const icon = import_picocolors4.default.green(status === "ok" ? "\u2713" : status === "migrated" ? "\u2191" : "+");
|
|
10156
10124
|
return `${import_picocolors4.default.dim(e2)} ${icon}`;
|
|
10157
10125
|
});
|
|
10158
10126
|
if (qmdStatus)
|
|
10159
|
-
parts.push(`${import_picocolors4.default.dim("PostToolUse")} ${import_picocolors4.default.green(qmdStatus === "ok" ? "
|
|
10127
|
+
parts.push(`${import_picocolors4.default.dim("PostToolUse")} ${import_picocolors4.default.green(qmdStatus === "ok" ? "\u2713" : "+")}`);
|
|
10160
10128
|
hooksSpinner?.stop(`Hooks ${parts.join(" ")}`);
|
|
10161
10129
|
} else {
|
|
10162
10130
|
const hookLine = HOOK_EVENTS.map((e2) => {
|
|
@@ -10252,9 +10220,9 @@ import {
|
|
|
10252
10220
|
stat as stat3,
|
|
10253
10221
|
unlink,
|
|
10254
10222
|
writeFile as writeFile2
|
|
10255
|
-
} from "
|
|
10256
|
-
import { homedir as homedir2, tmpdir } from "
|
|
10257
|
-
import { dirname as dirname2, join as join5, relative } from "
|
|
10223
|
+
} from "fs/promises";
|
|
10224
|
+
import { homedir as homedir2, tmpdir } from "os";
|
|
10225
|
+
import { dirname as dirname2, join as join5, relative } from "path";
|
|
10258
10226
|
function resolveBranch(updateChannel) {
|
|
10259
10227
|
return updateChannel === "stable" ? "main" : "next";
|
|
10260
10228
|
}
|
|
@@ -10263,9 +10231,9 @@ async function downloadTarball(branch, fetchFn) {
|
|
|
10263
10231
|
const response = await fetchFn(url);
|
|
10264
10232
|
if (!response.ok) {
|
|
10265
10233
|
const hints = {
|
|
10266
|
-
403: "
|
|
10267
|
-
404: "
|
|
10268
|
-
429: "
|
|
10234
|
+
403: " \u2014 check repo permissions or GITHUB_TOKEN",
|
|
10235
|
+
404: " \u2014 repo or branch not found",
|
|
10236
|
+
429: " \u2014 rate limited, wait and retry"
|
|
10269
10237
|
};
|
|
10270
10238
|
const hint = hints[response.status] ?? "";
|
|
10271
10239
|
throw new Error(`HTTP ${response.status} downloading tarball from ${url}${hint}`);
|
|
@@ -10703,14 +10671,14 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10703
10671
|
if (pinResult.skipped) {
|
|
10704
10672
|
stopSpinner("pin skipped (not found or marketplace)");
|
|
10705
10673
|
} else {
|
|
10706
|
-
stopSpinner("installPath
|
|
10674
|
+
stopSpinner("installPath \u2192 .claude/plugins/onebrain");
|
|
10707
10675
|
}
|
|
10708
10676
|
} catch (err) {
|
|
10709
10677
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10710
10678
|
process.stderr.write(`vault-sync: pin warning: ${msg}
|
|
10711
10679
|
`);
|
|
10712
10680
|
result.pinSkipped = true;
|
|
10713
|
-
stopSpinner("pin skipped (error
|
|
10681
|
+
stopSpinner("pin skipped (error \u2014 non-fatal)");
|
|
10714
10682
|
}
|
|
10715
10683
|
startSpinner("\uD83E\uDDF9", "Cleaning cache");
|
|
10716
10684
|
try {
|
|
@@ -10725,13 +10693,13 @@ async function runVaultSync(vaultRoot, opts = {}) {
|
|
|
10725
10693
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10726
10694
|
process.stderr.write(`vault-sync: cache clean warning: ${msg}
|
|
10727
10695
|
`);
|
|
10728
|
-
stopSpinner("cache clean skipped (error
|
|
10696
|
+
stopSpinner("cache clean skipped (error \u2014 non-fatal)");
|
|
10729
10697
|
}
|
|
10730
10698
|
}
|
|
10731
10699
|
result.ok = true;
|
|
10732
10700
|
if (isTTY) {
|
|
10733
10701
|
if (!embedded) {
|
|
10734
|
-
fe(`Done
|
|
10702
|
+
fe(`Done \u2014 v${result.version} synced`);
|
|
10735
10703
|
}
|
|
10736
10704
|
} else {
|
|
10737
10705
|
process.stdout.write(`vault-sync: done
|
|
@@ -10761,7 +10729,7 @@ var init_vault_sync = __esm(() => {
|
|
|
10761
10729
|
|
|
10762
10730
|
// src/index.ts
|
|
10763
10731
|
import { existsSync } from "fs";
|
|
10764
|
-
import { dirname as
|
|
10732
|
+
import { dirname as dirname4, join as join11 } from "path";
|
|
10765
10733
|
|
|
10766
10734
|
// node_modules/commander/esm.mjs
|
|
10767
10735
|
var import__ = __toESM(require_commander(), 1);
|
|
@@ -10787,7 +10755,7 @@ var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
|
10787
10755
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
10788
10756
|
function resolveBinaryVersion() {
|
|
10789
10757
|
if (true)
|
|
10790
|
-
return "2.1.
|
|
10758
|
+
return "2.1.5";
|
|
10791
10759
|
try {
|
|
10792
10760
|
const pkg = require_package();
|
|
10793
10761
|
return pkg.version ?? "dev";
|
|
@@ -10796,43 +10764,52 @@ function resolveBinaryVersion() {
|
|
|
10796
10764
|
}
|
|
10797
10765
|
}
|
|
10798
10766
|
var ART_LINES = [
|
|
10799
|
-
`
|
|
10800
|
-
"
|
|
10801
|
-
"
|
|
10802
|
-
"
|
|
10803
|
-
`
|
|
10767
|
+
` \u25C6${"\u2500".repeat(26)}\u25C6`,
|
|
10768
|
+
" \u250C\u2500\u2510\u250C\u2510\u2577\u250C\u2500\u2574\u250C\u2510 \u250C\u2500\u2510\u250C\u2500\u2510\u2577\u250C\u2510\u2577",
|
|
10769
|
+
" \u2502 \u2502\u2502\u2514\u2524\u251C\u2574 \u251C\u2534\u2510\u251C\u252C\u2518\u251C\u2500\u2524\u2502\u2502\u2514\u2524",
|
|
10770
|
+
" \u2514\u2500\u2518\u2575 \u2575\u2514\u2500\u2574\u2514\u2500\u2518\u2575\u2514\u2574\u2575 \u2575\u2575\u2575 \u2575",
|
|
10771
|
+
` \u25C6${"\u2500".repeat(26)}\u25C6`
|
|
10804
10772
|
];
|
|
10805
|
-
var
|
|
10773
|
+
var PREFIX = "Your AI ";
|
|
10774
|
+
var TAGLINE_LEAD = " ";
|
|
10775
|
+
var TAGLINE_FALLBACK = `${PREFIX}Thinking Partner`;
|
|
10806
10776
|
var BANNER_LINE_COUNT = 1 + ART_LINES.length + 3;
|
|
10777
|
+
var PREFIX_COLOR = [120, 230, 255];
|
|
10778
|
+
var TRAILING_COLOR = [255, 80, 255];
|
|
10779
|
+
var FINAL_COLOR = [120, 230, 255];
|
|
10780
|
+
var SENTENCES = [
|
|
10781
|
+
{ trailing: "Remembers You", trailingWords: ["Remembers", "You"], wordTicks: [24, 32] },
|
|
10782
|
+
{ trailing: "Catches Insights", trailingWords: ["Catches", "Insights"], wordTicks: [27, 26] },
|
|
10783
|
+
{ trailing: "Thinking Partner", trailingWords: ["Thinking", "Partner"], wordTicks: [26, 31] }
|
|
10784
|
+
];
|
|
10807
10785
|
function supportsRgb() {
|
|
10808
10786
|
const c = process.env["COLORTERM"] ?? "";
|
|
10809
10787
|
return c === "truecolor" || c === "24bit";
|
|
10810
10788
|
}
|
|
10789
|
+
function rgb(r, g, b, ch) {
|
|
10790
|
+
return `\x1B[1;38;2;${r};${g};${b}m${ch}\x1B[0m`;
|
|
10791
|
+
}
|
|
10792
|
+
function rgbStr(c, ch) {
|
|
10793
|
+
return rgb(c[0], c[1], c[2], ch);
|
|
10794
|
+
}
|
|
10811
10795
|
function hsvToRgb(h, floor = 80) {
|
|
10812
10796
|
const c = 255;
|
|
10813
10797
|
const x = Math.round(c * (1 - Math.abs(h / 60 % 2 - 1)));
|
|
10814
10798
|
let r = 0;
|
|
10815
10799
|
let g = 0;
|
|
10816
10800
|
let b = 0;
|
|
10817
|
-
if (h < 60)
|
|
10818
|
-
r = c;
|
|
10819
|
-
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
g = c;
|
|
10823
|
-
|
|
10824
|
-
g = c;
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
b = c;
|
|
10829
|
-
} else if (h < 300) {
|
|
10830
|
-
r = x;
|
|
10831
|
-
b = c;
|
|
10832
|
-
} else {
|
|
10833
|
-
r = c;
|
|
10834
|
-
b = x;
|
|
10835
|
-
}
|
|
10801
|
+
if (h < 60)
|
|
10802
|
+
[r, g, b] = [c, x, 0];
|
|
10803
|
+
else if (h < 120)
|
|
10804
|
+
[r, g, b] = [x, c, 0];
|
|
10805
|
+
else if (h < 180)
|
|
10806
|
+
[r, g, b] = [0, c, x];
|
|
10807
|
+
else if (h < 240)
|
|
10808
|
+
[r, g, b] = [0, x, c];
|
|
10809
|
+
else if (h < 300)
|
|
10810
|
+
[r, g, b] = [x, 0, c];
|
|
10811
|
+
else
|
|
10812
|
+
[r, g, b] = [c, 0, x];
|
|
10836
10813
|
return [Math.min(255, r + floor), Math.min(255, g + floor), Math.min(255, b + floor)];
|
|
10837
10814
|
}
|
|
10838
10815
|
var HUE_PER_CHAR = 10;
|
|
@@ -10843,15 +10820,25 @@ function neonLine(line, lineIndex = 0, floor = 80) {
|
|
|
10843
10820
|
return ch;
|
|
10844
10821
|
const hue = ((i * HUE_PER_CHAR - lineIndex * HUE_PER_ROW) % 360 + 360) % 360;
|
|
10845
10822
|
const [r, g, b] = hsvToRgb(hue, floor);
|
|
10846
|
-
return
|
|
10823
|
+
return rgb(r, g, b, ch);
|
|
10847
10824
|
}).join("");
|
|
10848
10825
|
}
|
|
10849
|
-
function
|
|
10850
|
-
return line.split("").map((ch) => ch === " " ? ch : `\x1B[1;
|
|
10826
|
+
function whiteLine(line) {
|
|
10827
|
+
return line.split("").map((ch) => ch === " " ? ch : `\x1B[1;97m${ch}\x1B[0m`).join("");
|
|
10828
|
+
}
|
|
10829
|
+
function whiteGlowLine(line, alpha) {
|
|
10830
|
+
return line.split("").map((ch) => ch === " " ? ch : `\x1B[1;38;2;${alpha};${alpha};${alpha}m${ch}\x1B[0m`).join("");
|
|
10851
10831
|
}
|
|
10852
10832
|
function dimLine(line) {
|
|
10853
10833
|
return line.split("").map((ch) => ch === " " ? ch : `\x1B[2;38;2;50;50;70m${ch}\x1B[0m`).join("");
|
|
10854
10834
|
}
|
|
10835
|
+
function scanLineCh(line) {
|
|
10836
|
+
return line.split("").map((ch) => ch === " " ? ch : rgb(140, 255, 255, ch)).join("");
|
|
10837
|
+
}
|
|
10838
|
+
var CURSOR = rgb(140, 255, 255, "\u258C");
|
|
10839
|
+
var GLYPHS = "\u2593\u2591\u2592\u2588\u2502\u2524\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u256A\u256B\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u2518\u250C\u2551\u258C\u2580\u2584\u2590\u2206\u0192\u03A9\xA7\xB6\xB1\xF7\xD7\xF8\xA5\u20AC";
|
|
10840
|
+
var randGlyph = () => GLYPHS[Math.floor(Math.random() * GLYPHS.length)] ?? "?";
|
|
10841
|
+
var glitchWhite = (g) => `\x1B[1;97m${g}\x1B[0m`;
|
|
10855
10842
|
function outb(str) {
|
|
10856
10843
|
process.stdout.write(Buffer.from(str, "utf8"));
|
|
10857
10844
|
}
|
|
@@ -10868,11 +10855,274 @@ function printFrame(artLines, tagline) {
|
|
|
10868
10855
|
outb(`
|
|
10869
10856
|
`);
|
|
10870
10857
|
}
|
|
10858
|
+
function blankTagline() {
|
|
10859
|
+
return `${TAGLINE_LEAD}${" ".repeat(TAGLINE_FALLBACK.length)}`;
|
|
10860
|
+
}
|
|
10861
|
+
function buildTaglineLine(prefixLockedChars, trailingPart) {
|
|
10862
|
+
let s = TAGLINE_LEAD;
|
|
10863
|
+
for (let i = 0;i < PREFIX.length; i++) {
|
|
10864
|
+
if (i < prefixLockedChars) {
|
|
10865
|
+
s += PREFIX[i] === " " ? " " : rgbStr(PREFIX_COLOR, PREFIX[i]);
|
|
10866
|
+
} else {
|
|
10867
|
+
s += " ";
|
|
10868
|
+
}
|
|
10869
|
+
}
|
|
10870
|
+
s += trailingPart;
|
|
10871
|
+
return `${s}\x1B[K`;
|
|
10872
|
+
}
|
|
10873
|
+
var LOCK_LATENCY = 4;
|
|
10874
|
+
var PREFIX_TICK_MS = [27, 27];
|
|
10875
|
+
var INTER_WORD_PAUSE_MS = 65;
|
|
10876
|
+
var SENTENCE_HOLD_MS = 500;
|
|
10877
|
+
var WIPE_TICK_MS = 22;
|
|
10878
|
+
var WIPE_TRAIL = 3;
|
|
10879
|
+
var WIPE_PAUSE_MS = 80;
|
|
10880
|
+
async function playBannerIntro(rainbowArt, whiteArt) {
|
|
10881
|
+
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
10882
|
+
const up = (n) => outb(`\x1B[${n}F`);
|
|
10883
|
+
printFrame(ART_LINES.map(dimLine), blankTagline());
|
|
10884
|
+
for (let scan = 0;scan < ART_LINES.length; scan++) {
|
|
10885
|
+
await delay(55);
|
|
10886
|
+
up(BANNER_LINE_COUNT);
|
|
10887
|
+
printFrame(ART_LINES.map((l, i) => {
|
|
10888
|
+
if (i < scan - 2)
|
|
10889
|
+
return whiteLine(l);
|
|
10890
|
+
if (i === scan - 2)
|
|
10891
|
+
return whiteGlowLine(l, 200);
|
|
10892
|
+
if (i === scan - 1)
|
|
10893
|
+
return whiteGlowLine(l, 230);
|
|
10894
|
+
if (i === scan)
|
|
10895
|
+
return scanLineCh(l);
|
|
10896
|
+
return dimLine(l);
|
|
10897
|
+
}), blankTagline());
|
|
10898
|
+
}
|
|
10899
|
+
await delay(40);
|
|
10900
|
+
up(BANNER_LINE_COUNT);
|
|
10901
|
+
printFrame(whiteArt, blankTagline());
|
|
10902
|
+
await delay(600);
|
|
10903
|
+
let minD = 0;
|
|
10904
|
+
let maxD = 0;
|
|
10905
|
+
for (let row = 0;row < ART_LINES.length; row++) {
|
|
10906
|
+
minD = Math.min(minD, -row * 3);
|
|
10907
|
+
maxD = Math.max(maxD, ART_LINES[row].length - 1 - row * 3);
|
|
10908
|
+
}
|
|
10909
|
+
function flowFrame(frontD) {
|
|
10910
|
+
return ART_LINES.map((line, row) => line.split("").map((ch, col) => {
|
|
10911
|
+
if (ch === " ")
|
|
10912
|
+
return ch;
|
|
10913
|
+
const d = col - 3 * row;
|
|
10914
|
+
if (d <= frontD) {
|
|
10915
|
+
const hue = ((col * HUE_PER_CHAR - row * HUE_PER_ROW) % 360 + 360) % 360;
|
|
10916
|
+
const [r, g, b] = hsvToRgb(hue);
|
|
10917
|
+
return rgb(r, g, b, ch);
|
|
10918
|
+
}
|
|
10919
|
+
return `\x1B[1;97m${ch}\x1B[0m`;
|
|
10920
|
+
}).join(""));
|
|
10921
|
+
}
|
|
10922
|
+
for (let d = minD;d <= maxD; d++) {
|
|
10923
|
+
await delay(9);
|
|
10924
|
+
up(BANNER_LINE_COUNT);
|
|
10925
|
+
printFrame(flowFrame(d), blankTagline());
|
|
10926
|
+
}
|
|
10927
|
+
up(BANNER_LINE_COUNT);
|
|
10928
|
+
printFrame(rainbowArt, blankTagline());
|
|
10929
|
+
await delay(180);
|
|
10930
|
+
function shimmerArtFrame(highlight) {
|
|
10931
|
+
return ART_LINES.map((line, row) => line.split("").map((ch, col) => {
|
|
10932
|
+
if (ch === " ")
|
|
10933
|
+
return ch;
|
|
10934
|
+
const d = col - 3 * row;
|
|
10935
|
+
if (Math.abs(d - highlight) <= 1)
|
|
10936
|
+
return `\x1B[1;97m${ch}\x1B[0m`;
|
|
10937
|
+
const hue = ((col * HUE_PER_CHAR - row * HUE_PER_ROW) % 360 + 360) % 360;
|
|
10938
|
+
const [r, g, b] = hsvToRgb(hue);
|
|
10939
|
+
return rgb(r, g, b, ch);
|
|
10940
|
+
}).join(""));
|
|
10941
|
+
}
|
|
10942
|
+
for (let d = minD;d <= maxD; d++) {
|
|
10943
|
+
await delay(9);
|
|
10944
|
+
up(BANNER_LINE_COUNT);
|
|
10945
|
+
printFrame(shimmerArtFrame(d), blankTagline());
|
|
10946
|
+
}
|
|
10947
|
+
up(BANNER_LINE_COUNT);
|
|
10948
|
+
printFrame(rainbowArt, blankTagline());
|
|
10949
|
+
await delay(80);
|
|
10950
|
+
}
|
|
10951
|
+
async function decodeFirstSentence(rainbowArt, s) {
|
|
10952
|
+
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
10953
|
+
const up = (n) => outb(`\x1B[${n}F`);
|
|
10954
|
+
const prefixWords = ["Your", "AI"];
|
|
10955
|
+
for (let wi = 0;wi < prefixWords.length; wi++) {
|
|
10956
|
+
const w = prefixWords[wi];
|
|
10957
|
+
const tickMs = PREFIX_TICK_MS[wi];
|
|
10958
|
+
const totalTicks = w.length + LOCK_LATENCY;
|
|
10959
|
+
const baseIdx = prefixWords.slice(0, wi).reduce((a, x) => a + x.length + 1, 0);
|
|
10960
|
+
for (let t = 1;t <= totalTicks; t++) {
|
|
10961
|
+
await delay(tickMs);
|
|
10962
|
+
up(BANNER_LINE_COUNT);
|
|
10963
|
+
let prefixPart = TAGLINE_LEAD;
|
|
10964
|
+
for (let i = 0;i < PREFIX.length; i++) {
|
|
10965
|
+
if (i < baseIdx) {
|
|
10966
|
+
prefixPart += PREFIX[i] === " " ? " " : rgbStr(PREFIX_COLOR, PREFIX[i]);
|
|
10967
|
+
} else if (i >= baseIdx + w.length) {
|
|
10968
|
+
prefixPart += " ";
|
|
10969
|
+
} else {
|
|
10970
|
+
const localIdx = i - baseIdx;
|
|
10971
|
+
const age = t - localIdx;
|
|
10972
|
+
if (age > LOCK_LATENCY)
|
|
10973
|
+
prefixPart += rgbStr(PREFIX_COLOR, PREFIX[i]);
|
|
10974
|
+
else if (age > 0)
|
|
10975
|
+
prefixPart += glitchWhite(randGlyph());
|
|
10976
|
+
else if (age === 0 && t < w.length)
|
|
10977
|
+
prefixPart += CURSOR;
|
|
10978
|
+
else
|
|
10979
|
+
prefixPart += " ";
|
|
10980
|
+
}
|
|
10981
|
+
}
|
|
10982
|
+
const trailingBlank = " ".repeat(s.trailing.length);
|
|
10983
|
+
printFrame(rainbowArt, `${prefixPart}${trailingBlank}\x1B[K`);
|
|
10984
|
+
}
|
|
10985
|
+
if (wi < prefixWords.length - 1) {
|
|
10986
|
+
await delay(INTER_WORD_PAUSE_MS);
|
|
10987
|
+
}
|
|
10988
|
+
}
|
|
10989
|
+
await delay(INTER_WORD_PAUSE_MS);
|
|
10990
|
+
await decodeTrailing(rainbowArt, s, PREFIX.length);
|
|
10991
|
+
}
|
|
10992
|
+
async function decodeTrailing(rainbowArt, s, lockedPrefixChars) {
|
|
10993
|
+
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
10994
|
+
const up = (n) => outb(`\x1B[${n}F`);
|
|
10995
|
+
const words = s.trailingWords;
|
|
10996
|
+
const ticks = s.wordTicks;
|
|
10997
|
+
const offsets = [];
|
|
10998
|
+
let off = 0;
|
|
10999
|
+
for (const w of words) {
|
|
11000
|
+
offsets.push(off);
|
|
11001
|
+
off += w.length + 1;
|
|
11002
|
+
}
|
|
11003
|
+
for (let wi = 0;wi < words.length; wi++) {
|
|
11004
|
+
const w = words[wi];
|
|
11005
|
+
const tickMs = ticks[wi];
|
|
11006
|
+
const totalTicks = w.length + LOCK_LATENCY;
|
|
11007
|
+
for (let t = 1;t <= totalTicks; t++) {
|
|
11008
|
+
await delay(tickMs);
|
|
11009
|
+
up(BANNER_LINE_COUNT);
|
|
11010
|
+
let trailing = "";
|
|
11011
|
+
for (let j = 0;j < s.trailing.length; j++) {
|
|
11012
|
+
const ch = s.trailing[j];
|
|
11013
|
+
if (ch === " ") {
|
|
11014
|
+
trailing += " ";
|
|
11015
|
+
continue;
|
|
11016
|
+
}
|
|
11017
|
+
let owningWi = -1;
|
|
11018
|
+
let localIdx = -1;
|
|
11019
|
+
for (let k = 0;k < words.length; k++) {
|
|
11020
|
+
const start = offsets[k];
|
|
11021
|
+
const end = start + words[k].length;
|
|
11022
|
+
if (j >= start && j < end) {
|
|
11023
|
+
owningWi = k;
|
|
11024
|
+
localIdx = j - start;
|
|
11025
|
+
break;
|
|
11026
|
+
}
|
|
11027
|
+
}
|
|
11028
|
+
if (owningWi < wi) {
|
|
11029
|
+
trailing += rgbStr(TRAILING_COLOR, ch);
|
|
11030
|
+
} else if (owningWi > wi) {
|
|
11031
|
+
trailing += " ";
|
|
11032
|
+
} else {
|
|
11033
|
+
const age = t - localIdx;
|
|
11034
|
+
if (age > LOCK_LATENCY)
|
|
11035
|
+
trailing += rgbStr(TRAILING_COLOR, ch);
|
|
11036
|
+
else if (age > 0)
|
|
11037
|
+
trailing += glitchWhite(randGlyph());
|
|
11038
|
+
else if (age === 0 && t < w.length)
|
|
11039
|
+
trailing += CURSOR;
|
|
11040
|
+
else
|
|
11041
|
+
trailing += " ";
|
|
11042
|
+
}
|
|
11043
|
+
}
|
|
11044
|
+
printFrame(rainbowArt, buildTaglineLine(lockedPrefixChars, trailing));
|
|
11045
|
+
}
|
|
11046
|
+
if (wi < words.length - 1) {
|
|
11047
|
+
await delay(INTER_WORD_PAUSE_MS);
|
|
11048
|
+
}
|
|
11049
|
+
}
|
|
11050
|
+
}
|
|
11051
|
+
async function wipeSwapTransition(rainbowArt, from, to) {
|
|
11052
|
+
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
11053
|
+
const up = (n) => outb(`\x1B[${n}F`);
|
|
11054
|
+
for (let pos = from.trailing.length - 1;pos >= -WIPE_TRAIL; pos--) {
|
|
11055
|
+
await delay(WIPE_TICK_MS);
|
|
11056
|
+
up(BANNER_LINE_COUNT);
|
|
11057
|
+
let trailing = "";
|
|
11058
|
+
for (let j = 0;j < from.trailing.length; j++) {
|
|
11059
|
+
const ch = from.trailing[j];
|
|
11060
|
+
if (ch === " ") {
|
|
11061
|
+
trailing += " ";
|
|
11062
|
+
continue;
|
|
11063
|
+
}
|
|
11064
|
+
const offset = j - pos;
|
|
11065
|
+
if (offset >= 0 && offset <= WIPE_TRAIL) {
|
|
11066
|
+
trailing += rgb(140, 255, 255, randGlyph());
|
|
11067
|
+
} else if (j > pos) {
|
|
11068
|
+
trailing += " ";
|
|
11069
|
+
} else {
|
|
11070
|
+
trailing += rgbStr(TRAILING_COLOR, ch);
|
|
11071
|
+
}
|
|
11072
|
+
}
|
|
11073
|
+
printFrame(rainbowArt, buildTaglineLine(PREFIX.length, trailing));
|
|
11074
|
+
}
|
|
11075
|
+
await delay(WIPE_PAUSE_MS);
|
|
11076
|
+
await decodeTrailing(rainbowArt, to, PREFIX.length);
|
|
11077
|
+
}
|
|
11078
|
+
async function lockShimmer(rainbowArt, s) {
|
|
11079
|
+
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
11080
|
+
const up = (n) => outb(`\x1B[${n}F`);
|
|
11081
|
+
const SHIMMER_TICK_MS = 22;
|
|
11082
|
+
const TRAIL = 3;
|
|
11083
|
+
const STOPS = [
|
|
11084
|
+
[255, 255, 255],
|
|
11085
|
+
[200, 245, 255],
|
|
11086
|
+
[150, 235, 255]
|
|
11087
|
+
];
|
|
11088
|
+
const fullText = PREFIX + s.trailing;
|
|
11089
|
+
const N = fullText.length;
|
|
11090
|
+
for (let pos = 0;pos <= N + TRAIL; pos++) {
|
|
11091
|
+
await delay(SHIMMER_TICK_MS);
|
|
11092
|
+
up(BANNER_LINE_COUNT);
|
|
11093
|
+
let line = TAGLINE_LEAD;
|
|
11094
|
+
for (let j = 0;j < N; j++) {
|
|
11095
|
+
const ch = fullText[j];
|
|
11096
|
+
if (ch === " ") {
|
|
11097
|
+
line += " ";
|
|
11098
|
+
continue;
|
|
11099
|
+
}
|
|
11100
|
+
const offset = pos - j;
|
|
11101
|
+
if (offset >= 0 && offset < TRAIL) {
|
|
11102
|
+
line += rgbStr(STOPS[offset], ch);
|
|
11103
|
+
} else if (offset >= TRAIL) {
|
|
11104
|
+
line += rgbStr(FINAL_COLOR, ch);
|
|
11105
|
+
} else {
|
|
11106
|
+
const baseColor = j < PREFIX.length ? PREFIX_COLOR : TRAILING_COLOR;
|
|
11107
|
+
line += rgbStr(baseColor, ch);
|
|
11108
|
+
}
|
|
11109
|
+
}
|
|
11110
|
+
line += "\x1B[K";
|
|
11111
|
+
printFrame(rainbowArt, line);
|
|
11112
|
+
}
|
|
11113
|
+
up(BANNER_LINE_COUNT);
|
|
11114
|
+
let finalLine = TAGLINE_LEAD;
|
|
11115
|
+
for (let j = 0;j < N; j++) {
|
|
11116
|
+
const ch = fullText[j];
|
|
11117
|
+
finalLine += ch === " " ? " " : rgbStr(FINAL_COLOR, ch);
|
|
11118
|
+
}
|
|
11119
|
+
finalLine += "\x1B[K";
|
|
11120
|
+
printFrame(rainbowArt, finalLine);
|
|
11121
|
+
await delay(150);
|
|
11122
|
+
}
|
|
10871
11123
|
async function printBanner() {
|
|
10872
11124
|
if (!process.stdout.isTTY)
|
|
10873
11125
|
return;
|
|
10874
|
-
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
10875
|
-
const up = (n) => outb(`\x1B[${n}F`);
|
|
10876
11126
|
if (!supportsRgb()) {
|
|
10877
11127
|
outb(`
|
|
10878
11128
|
`);
|
|
@@ -10881,84 +11131,24 @@ async function printBanner() {
|
|
|
10881
11131
|
`);
|
|
10882
11132
|
outb(`
|
|
10883
11133
|
`);
|
|
10884
|
-
outb(
|
|
11134
|
+
outb(`${TAGLINE_LEAD}${import_picocolors.default.bold(import_picocolors.default.cyan(TAGLINE_FALLBACK))}
|
|
10885
11135
|
`);
|
|
10886
11136
|
outb(`
|
|
10887
11137
|
`);
|
|
10888
11138
|
return;
|
|
10889
11139
|
}
|
|
10890
|
-
|
|
11140
|
+
const rainbowArt = ART_LINES.map((l, i) => neonLine(l, i));
|
|
11141
|
+
const whiteArt = ART_LINES.map((l) => whiteLine(l));
|
|
10891
11142
|
try {
|
|
10892
|
-
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
return `\x1B[1;38;2;${r};${g};${b}m${ch}\x1B[0m`;
|
|
10902
|
-
}).join(""));
|
|
10903
|
-
};
|
|
10904
|
-
printFrame(ART_LINES.map(dimLine), ` ${" ".repeat(TAGLINE.length)}`);
|
|
10905
|
-
for (let scan = 0;scan < ART_LINES.length; scan++) {
|
|
10906
|
-
await delay(65);
|
|
10907
|
-
up(BANNER_LINE_COUNT);
|
|
10908
|
-
printFrame(ART_LINES.map((l, i) => {
|
|
10909
|
-
if (i < scan - 2)
|
|
10910
|
-
return neonLine(l, i);
|
|
10911
|
-
if (i === scan - 2)
|
|
10912
|
-
return neonLine(l, i, 120);
|
|
10913
|
-
if (i === scan - 1)
|
|
10914
|
-
return neonLine(l, i, 200);
|
|
10915
|
-
if (i === scan)
|
|
10916
|
-
return scanLine(l);
|
|
10917
|
-
return dimLine(l);
|
|
10918
|
-
}), ` ${" ".repeat(TAGLINE.length)}`);
|
|
10919
|
-
}
|
|
10920
|
-
await delay(60);
|
|
10921
|
-
up(BANNER_LINE_COUNT);
|
|
10922
|
-
printFrame(ART_LINES.map((l, i) => neonLine(l, i)), ` ${" ".repeat(TAGLINE.length)}`);
|
|
10923
|
-
let minD = 0;
|
|
10924
|
-
let maxD = 0;
|
|
10925
|
-
for (let row = 0;row < ART_LINES.length; row++) {
|
|
10926
|
-
minD = Math.min(minD, -row * 3);
|
|
10927
|
-
maxD = Math.max(maxD, ART_LINES[row].length - 1 - row * 3);
|
|
10928
|
-
}
|
|
10929
|
-
for (let d = minD;d <= maxD; d++) {
|
|
10930
|
-
await delay(16);
|
|
10931
|
-
up(BANNER_LINE_COUNT);
|
|
10932
|
-
printFrame(diagFrame(d), ` ${" ".repeat(TAGLINE.length)}`);
|
|
10933
|
-
}
|
|
10934
|
-
for (let d = maxD;d >= minD; d--) {
|
|
10935
|
-
await delay(16);
|
|
10936
|
-
up(BANNER_LINE_COUNT);
|
|
10937
|
-
printFrame(diagFrame(d), ` ${" ".repeat(TAGLINE.length)}`);
|
|
10938
|
-
}
|
|
10939
|
-
up(BANNER_LINE_COUNT);
|
|
10940
|
-
printFrame(ART_LINES.map((l, i) => neonLine(l, i)), ` ${" ".repeat(TAGLINE.length)}`);
|
|
10941
|
-
await delay(200);
|
|
10942
|
-
const cursor = `\x1B[1;38;2;140;255;255m▌\x1B[0m`;
|
|
10943
|
-
for (let len = 1;len <= TAGLINE.length; len++) {
|
|
10944
|
-
await delay(32);
|
|
10945
|
-
up(BANNER_LINE_COUNT);
|
|
10946
|
-
const hasCursor = len < TAGLINE.length;
|
|
10947
|
-
printFrame(ART_LINES.map((l, i) => neonLine(l, i)), ` \x1B[1;97m${TAGLINE.slice(0, len)}\x1B[0m${hasCursor ? cursor : ""}${" ".repeat(Math.max(0, TAGLINE.length - len - 1))}`);
|
|
10948
|
-
}
|
|
10949
|
-
const tagWithCursor = ` \x1B[1;97m${TAGLINE}\x1B[0m${cursor}`;
|
|
10950
|
-
const tagWhite = ` \x1B[1;97m${TAGLINE}\x1B[0m\x1B[K`;
|
|
10951
|
-
for (let b = 0;b < 2; b++) {
|
|
10952
|
-
await delay(600);
|
|
10953
|
-
up(BANNER_LINE_COUNT);
|
|
10954
|
-
printFrame(ART_LINES.map((l, i) => neonLine(l, i)), tagWhite);
|
|
10955
|
-
await delay(600);
|
|
10956
|
-
up(BANNER_LINE_COUNT);
|
|
10957
|
-
printFrame(ART_LINES.map((l, i) => neonLine(l, i)), tagWithCursor);
|
|
10958
|
-
}
|
|
10959
|
-
await delay(600);
|
|
10960
|
-
up(BANNER_LINE_COUNT);
|
|
10961
|
-
printFrame(ART_LINES.map((l, i) => neonLine(l, i)), ` ${import_picocolors.default.bold(import_picocolors.default.magenta(TAGLINE))}\x1B[K`);
|
|
11143
|
+
outb("\x1B[?25l");
|
|
11144
|
+
await playBannerIntro(rainbowArt, whiteArt);
|
|
11145
|
+
await decodeFirstSentence(rainbowArt, SENTENCES[0]);
|
|
11146
|
+
await new Promise((r) => setTimeout(r, SENTENCE_HOLD_MS));
|
|
11147
|
+
await wipeSwapTransition(rainbowArt, SENTENCES[0], SENTENCES[1]);
|
|
11148
|
+
await new Promise((r) => setTimeout(r, SENTENCE_HOLD_MS));
|
|
11149
|
+
await wipeSwapTransition(rainbowArt, SENTENCES[1], SENTENCES[2]);
|
|
11150
|
+
await new Promise((r) => setTimeout(r, SENTENCE_HOLD_MS));
|
|
11151
|
+
await lockShimmer(rainbowArt, SENTENCES[2]);
|
|
10962
11152
|
} finally {
|
|
10963
11153
|
outb("\x1B[?25h");
|
|
10964
11154
|
}
|
|
@@ -11018,7 +11208,7 @@ async function runDoctor(opts = {}) {
|
|
|
11018
11208
|
let vaultYmlKeysResult;
|
|
11019
11209
|
let settingsHooksResult;
|
|
11020
11210
|
if (isTTY) {
|
|
11021
|
-
const sp2 = createStep("
|
|
11211
|
+
const sp2 = createStep("\u2699\uFE0F", "Config schema");
|
|
11022
11212
|
vaultYmlKeysResult = await checkVaultYmlKeysFn(vaultDir);
|
|
11023
11213
|
await randDelay();
|
|
11024
11214
|
sp2.stop(fmtResult(vaultYmlKeysResult), vaultYmlKeysResult.details);
|
|
@@ -11071,7 +11261,12 @@ async function runDoctor(opts = {}) {
|
|
|
11071
11261
|
const totalChecks = results.length;
|
|
11072
11262
|
const errorCount = results.filter((r2) => r2.status === "error").length;
|
|
11073
11263
|
const warningCount = results.filter((r2) => r2.status === "warn").length;
|
|
11074
|
-
const fixableCount = results.filter((r2) =>
|
|
11264
|
+
const fixableCount = results.filter((r2) => {
|
|
11265
|
+
if (r2.status === "ok")
|
|
11266
|
+
return false;
|
|
11267
|
+
const fix = getFix(r2);
|
|
11268
|
+
return fix !== null && !fix.advisory;
|
|
11269
|
+
}).length;
|
|
11075
11270
|
const showFixHint = !opts.fix && fixableCount > 0;
|
|
11076
11271
|
const summaryParts = [`${totalChecks} checks`];
|
|
11077
11272
|
if (errorCount > 0)
|
|
@@ -11082,15 +11277,15 @@ async function runDoctor(opts = {}) {
|
|
|
11082
11277
|
printNonTtyOutput(results, totalChecks, errorCount, warningCount, showFixHint, fixableCount);
|
|
11083
11278
|
} else {
|
|
11084
11279
|
if (errorCount > 0) {
|
|
11085
|
-
close(`${summaryParts.join("
|
|
11280
|
+
close(`${summaryParts.join(" \xB7 ")} \u2014 fix before using`, true);
|
|
11086
11281
|
} else if (warningCount > 0) {
|
|
11087
|
-
close(`${summaryParts.join("
|
|
11282
|
+
close(`${summaryParts.join(" \xB7 ")} \u2014 advisory only, safe to run`, false, true);
|
|
11088
11283
|
} else {
|
|
11089
|
-
close(import_picocolors5.default.green(`${summaryParts.join("
|
|
11284
|
+
close(import_picocolors5.default.green(`${summaryParts.join(" \xB7 ")} \u2014 all passed`));
|
|
11090
11285
|
}
|
|
11091
11286
|
if (showFixHint) {
|
|
11092
11287
|
process.stdout.write(`
|
|
11093
|
-
|
|
11288
|
+
\u2192 Run ${import_picocolors5.default.cyan("onebrain doctor --fix")} to auto-fix ${fixableCount} issue(s)
|
|
11094
11289
|
`);
|
|
11095
11290
|
}
|
|
11096
11291
|
}
|
|
@@ -11111,21 +11306,21 @@ async function doctorCommand(opts = {}) {
|
|
|
11111
11306
|
function printNonTtyOutput(results, totalChecks, errorCount, warningCount, showFixHint, fixableCount) {
|
|
11112
11307
|
const lines = ["OneBrain Doctor", ""];
|
|
11113
11308
|
for (const result of results) {
|
|
11114
|
-
const icon = result.status === "ok" ? "[
|
|
11309
|
+
const icon = result.status === "ok" ? "[\u2713]" : result.status === "warn" ? "[!]" : "[\u2717]";
|
|
11115
11310
|
lines.push(` ${icon} ${result.check.padEnd(20)} ${result.message}`);
|
|
11116
11311
|
if (result.hint)
|
|
11117
|
-
lines.push(`
|
|
11312
|
+
lines.push(` \u2192 ${result.hint}`);
|
|
11118
11313
|
if (result.details)
|
|
11119
11314
|
for (const d of result.details)
|
|
11120
|
-
lines.push(`
|
|
11315
|
+
lines.push(` \xB7 ${d}`);
|
|
11121
11316
|
}
|
|
11122
11317
|
lines.push("");
|
|
11123
11318
|
if (errorCount > 0) {
|
|
11124
|
-
lines.push(`Summary: ${totalChecks} checks
|
|
11319
|
+
lines.push(`Summary: ${totalChecks} checks \xB7 ${errorCount} error(s) \xB7 ${warningCount} warning(s) \u2014 fix before using`);
|
|
11125
11320
|
} else if (warningCount > 0) {
|
|
11126
|
-
lines.push(`Summary: ${totalChecks} checks
|
|
11321
|
+
lines.push(`Summary: ${totalChecks} checks \xB7 ${warningCount} warning(s) \u2014 ok to run`);
|
|
11127
11322
|
} else {
|
|
11128
|
-
lines.push(`Summary: ${totalChecks} checks
|
|
11323
|
+
lines.push(`Summary: ${totalChecks} checks \u2014 all passed`);
|
|
11129
11324
|
}
|
|
11130
11325
|
if (showFixHint)
|
|
11131
11326
|
lines.push(`hint: run onebrain doctor --fix to auto-fix ${fixableCount} issue(s)`);
|
|
@@ -11154,8 +11349,8 @@ function getFix(r2) {
|
|
|
11154
11349
|
const description = deprecated.length > 0 ? `Remove deprecated keys from vault.yml: ${deprecated.join(", ")}` : "Remove deprecated keys from vault.yml";
|
|
11155
11350
|
return {
|
|
11156
11351
|
fn: async (vaultDir) => {
|
|
11157
|
-
const { readFile: readFile2, writeFile: writeFile2, rename: rename2 } = await import("
|
|
11158
|
-
const { join: join5 } = await import("
|
|
11352
|
+
const { readFile: readFile2, writeFile: writeFile2, rename: rename2 } = await import("fs/promises");
|
|
11353
|
+
const { join: join5 } = await import("path");
|
|
11159
11354
|
const { parse: parse3, stringify } = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
11160
11355
|
const vaultYmlPath = join5(vaultDir, "vault.yml");
|
|
11161
11356
|
const text = await readFile2(vaultYmlPath, "utf8");
|
|
@@ -11186,10 +11381,11 @@ function getFix(r2) {
|
|
|
11186
11381
|
const pendingMatch = r2.message.match(/(\d+) unembedded/);
|
|
11187
11382
|
const count = pendingMatch?.[1] ?? "some";
|
|
11188
11383
|
return {
|
|
11384
|
+
advisory: true,
|
|
11189
11385
|
fn: async (vaultDir) => {
|
|
11190
|
-
const { join: join5 } = await import("
|
|
11386
|
+
const { join: join5 } = await import("path");
|
|
11191
11387
|
const { parse: parseYaml } = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
11192
|
-
const { readFile: readFile2 } = await import("
|
|
11388
|
+
const { readFile: readFile2 } = await import("fs/promises");
|
|
11193
11389
|
const raw = parseYaml(await readFile2(join5(vaultDir, "vault.yml"), "utf8"));
|
|
11194
11390
|
const collection = raw["qmd_collection"];
|
|
11195
11391
|
if (!collection)
|
|
@@ -11215,8 +11411,8 @@ function getFix(r2) {
|
|
|
11215
11411
|
const missingStr = r2.hint.replace("Missing: ", "");
|
|
11216
11412
|
return {
|
|
11217
11413
|
fn: async (vaultDir) => {
|
|
11218
|
-
const { mkdir: mkdir2 } = await import("
|
|
11219
|
-
const { join: join5 } = await import("
|
|
11414
|
+
const { mkdir: mkdir2 } = await import("fs/promises");
|
|
11415
|
+
const { join: join5 } = await import("path");
|
|
11220
11416
|
const missing = missingStr.split(", ").map((f2) => f2.trim()).filter(Boolean);
|
|
11221
11417
|
for (const folder of missing) {
|
|
11222
11418
|
await mkdir2(join5(vaultDir, folder), { recursive: true });
|
|
@@ -11231,24 +11427,24 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11231
11427
|
const fixable = results.filter((r2) => r2.status !== "ok" && getFix(r2) !== null);
|
|
11232
11428
|
if (fixable.length === 0) {
|
|
11233
11429
|
if (isTTY)
|
|
11234
|
-
|
|
11430
|
+
writeLine(`${import_picocolors5.default.green("\u25C6")} Nothing to fix`);
|
|
11235
11431
|
else
|
|
11236
11432
|
writeLine("nothing to fix");
|
|
11237
11433
|
return;
|
|
11238
11434
|
}
|
|
11239
11435
|
if (isTTY) {
|
|
11240
|
-
|
|
11241
|
-
|
|
11436
|
+
writeLine("");
|
|
11437
|
+
barOpen(import_picocolors5.default.bold(`${fixable.length} fix(es) to apply:`));
|
|
11242
11438
|
barBlank();
|
|
11243
11439
|
for (const r2 of fixable) {
|
|
11244
|
-
barLine(` ${import_picocolors5.default.cyan("
|
|
11440
|
+
barLine(` ${import_picocolors5.default.cyan("\u25C6")} ${getFix(r2).description}`);
|
|
11245
11441
|
}
|
|
11246
11442
|
barBlank();
|
|
11247
11443
|
const answer = await askYesNo("Apply all?");
|
|
11248
11444
|
if (answer === null || answer === false) {
|
|
11249
11445
|
barLine(import_picocolors5.default.dim("No"));
|
|
11250
11446
|
barBlank();
|
|
11251
|
-
close(`No changes made
|
|
11447
|
+
close(`No changes made \u2014 run ${import_picocolors5.default.cyan("onebrain doctor --fix")} to apply`);
|
|
11252
11448
|
return;
|
|
11253
11449
|
}
|
|
11254
11450
|
barLine("Yes");
|
|
@@ -11268,11 +11464,11 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11268
11464
|
await fix.fn(vaultDir, registerHooksFn);
|
|
11269
11465
|
fixed++;
|
|
11270
11466
|
if (isTTY)
|
|
11271
|
-
barLine(`${import_picocolors5.default.green("
|
|
11467
|
+
barLine(`${import_picocolors5.default.green("\u25C6")} ${fix.description}`);
|
|
11272
11468
|
} catch (err) {
|
|
11273
11469
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
11274
11470
|
if (isTTY) {
|
|
11275
|
-
barLine(`${import_picocolors5.default.yellow("
|
|
11471
|
+
barLine(`${import_picocolors5.default.yellow("\u25B2")} Could not fix ${r2.check}: ${errMsg}`);
|
|
11276
11472
|
} else {
|
|
11277
11473
|
process.stderr.write(`doctor: fix failed for ${r2.check}: ${errMsg}
|
|
11278
11474
|
`);
|
|
@@ -11282,9 +11478,9 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11282
11478
|
if (isTTY) {
|
|
11283
11479
|
barBlank();
|
|
11284
11480
|
if (fixed > 0)
|
|
11285
|
-
barLine(`${import_picocolors5.default.green("
|
|
11481
|
+
barLine(`${import_picocolors5.default.green("\u25C6")} Fixed ${fixed} issue(s)`);
|
|
11286
11482
|
if (unfixable.length > 0) {
|
|
11287
|
-
barLine(`${import_picocolors5.default.yellow("
|
|
11483
|
+
barLine(`${import_picocolors5.default.yellow("\u25B2")} ${unfixable.length} issue(s) require manual action:`);
|
|
11288
11484
|
for (const r2 of unfixable) {
|
|
11289
11485
|
barLine(` ${r2.check}: ${r2.hint ?? "no auto-fix available"}`);
|
|
11290
11486
|
}
|
|
@@ -11304,9 +11500,9 @@ async function applyFixes(vaultDir, results, isTTY, registerHooksFn) {
|
|
|
11304
11500
|
// src/commands/init.ts
|
|
11305
11501
|
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
11306
11502
|
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 "
|
|
11503
|
+
import { mkdir as mkdir3, readFile as readFile3, readdir as readdir2, rename as rename3, stat as stat4, writeFile as writeFile3 } from "fs/promises";
|
|
11504
|
+
import { homedir as homedir3 } from "os";
|
|
11505
|
+
import { dirname as dirname3, join as join6 } from "path";
|
|
11310
11506
|
init_cli_ui();
|
|
11311
11507
|
var binaryVersion = resolveBinaryVersion();
|
|
11312
11508
|
var STANDARD_FOLDERS = [
|
|
@@ -11372,7 +11568,7 @@ async function downloadPluginFiles(vaultDir, vaultSyncFn) {
|
|
|
11372
11568
|
} catch {}
|
|
11373
11569
|
let driftWarning;
|
|
11374
11570
|
if (pluginVersion && binaryVersion !== "dev" && pluginVersion !== binaryVersion) {
|
|
11375
|
-
driftWarning = `Plugin files v${pluginVersion}, binary v${binaryVersion}
|
|
11571
|
+
driftWarning = `Plugin files v${pluginVersion}, binary v${binaryVersion} \u2014 run onebrain update to sync.`;
|
|
11376
11572
|
}
|
|
11377
11573
|
return driftWarning !== undefined ? { skipped: true, driftWarning } : { skipped: true };
|
|
11378
11574
|
}
|
|
@@ -11573,7 +11769,7 @@ async function installObsidianPlugins(vaultDir, opts) {
|
|
|
11573
11769
|
}
|
|
11574
11770
|
if (pluginFailed) {
|
|
11575
11771
|
try {
|
|
11576
|
-
const { rm: rm2 } = await import("
|
|
11772
|
+
const { rm: rm2 } = await import("fs/promises");
|
|
11577
11773
|
await rm2(pluginDir, { recursive: true, force: true });
|
|
11578
11774
|
} catch {}
|
|
11579
11775
|
} else {
|
|
@@ -11655,7 +11851,7 @@ async function runInit(opts = {}) {
|
|
|
11655
11851
|
await writeVaultYml(vaultDir);
|
|
11656
11852
|
if (sp2) {
|
|
11657
11853
|
await randDelay();
|
|
11658
|
-
sp2.stop(import_picocolors7.default.dim("written"), ["update_channel: stable", "checkpoint: 15 msgs
|
|
11854
|
+
sp2.stop(import_picocolors7.default.dim("written"), ["update_channel: stable", "checkpoint: 15 msgs \xB7 30 min"]);
|
|
11659
11855
|
} else {
|
|
11660
11856
|
writeLine("vault.yml: written");
|
|
11661
11857
|
}
|
|
@@ -11671,24 +11867,21 @@ async function runInit(opts = {}) {
|
|
|
11671
11867
|
const pluginJsonPath = join6(vaultDir, ".claude", "plugins", "onebrain", ".claude-plugin", "plugin.json");
|
|
11672
11868
|
const pluginFilesExist = await pathExists2(pluginJsonPath);
|
|
11673
11869
|
const sp4 = pluginFilesExist ? createStep("\uD83D\uDCE6", "Plugin files") : null;
|
|
11674
|
-
const {
|
|
11675
|
-
skipped: pluginSkipped,
|
|
11676
|
-
failed: pluginDownloadFailed
|
|
11677
|
-
} = await downloadPluginFiles(vaultDir, vaultSyncFn);
|
|
11870
|
+
const { skipped: pluginSkipped, failed: pluginDownloadFailed } = await downloadPluginFiles(vaultDir, vaultSyncFn);
|
|
11678
11871
|
result.pluginSkipped = pluginSkipped;
|
|
11679
11872
|
if (sp4) {
|
|
11680
11873
|
if (pluginDownloadFailed) {
|
|
11681
11874
|
sp4.stop("download failed");
|
|
11682
11875
|
} else {
|
|
11683
11876
|
const { skills, agents } = await countPluginContents(vaultDir);
|
|
11684
|
-
sp4.stop(import_picocolors7.default.dim("already installed"), [`${skills} skills
|
|
11877
|
+
sp4.stop(import_picocolors7.default.dim("already installed"), [`${skills} skills \xB7 ${agents} agents`]);
|
|
11685
11878
|
}
|
|
11686
11879
|
} else if (isTTY) {
|
|
11687
11880
|
if (!pluginDownloadFailed) {
|
|
11688
11881
|
const { skills, agents } = await countPluginContents(vaultDir);
|
|
11689
11882
|
dotLine("\uD83D\uDCE6", "Plugin files");
|
|
11690
11883
|
barLine(import_picocolors7.default.dim("downloaded"));
|
|
11691
|
-
barLine(`
|
|
11884
|
+
barLine(` \xB7 ${skills} skills \xB7 ${agents} agents`);
|
|
11692
11885
|
barBlank();
|
|
11693
11886
|
}
|
|
11694
11887
|
} else {
|
|
@@ -11702,7 +11895,7 @@ async function runInit(opts = {}) {
|
|
|
11702
11895
|
if (isTTY) {
|
|
11703
11896
|
close("Could not download plugin files. Check your internet connection and try again.", true);
|
|
11704
11897
|
} else {
|
|
11705
|
-
writeLine("error: vault-sync failed
|
|
11898
|
+
writeLine("error: vault-sync failed \u2014 run onebrain update to download plugin files");
|
|
11706
11899
|
}
|
|
11707
11900
|
return result;
|
|
11708
11901
|
}
|
|
@@ -11733,7 +11926,9 @@ async function runInit(opts = {}) {
|
|
|
11733
11926
|
result.pluginRegistrationSkipped = pluginRegistrationSkipped;
|
|
11734
11927
|
if (sp5) {
|
|
11735
11928
|
await randDelay();
|
|
11736
|
-
sp5.stop(import_picocolors7.default.dim(pluginRegistrationSkipped ? "skipped" : "registered"), [
|
|
11929
|
+
sp5.stop(import_picocolors7.default.dim(pluginRegistrationSkipped ? "skipped" : "registered"), [
|
|
11930
|
+
`source: ${pluginRegistrationSkipped ? "marketplace" : "local"}`
|
|
11931
|
+
]);
|
|
11737
11932
|
} else {
|
|
11738
11933
|
writeLine(`plugin: ${pluginRegistrationSkipped ? "skipped (marketplace)" : "registered"}`);
|
|
11739
11934
|
}
|
|
@@ -11749,20 +11944,20 @@ async function runInit(opts = {}) {
|
|
|
11749
11944
|
}
|
|
11750
11945
|
if (sp6) {
|
|
11751
11946
|
await randDelay();
|
|
11752
|
-
sp6.stop(hooksOk ? undefined : "not registered
|
|
11947
|
+
sp6.stop(hooksOk ? undefined : "not registered \u2014 run onebrain update", hooksOk ? ["Stop \u2713 PostCompact \u2713", "Bash(onebrain *) \u2713"] : undefined);
|
|
11753
11948
|
} else {
|
|
11754
|
-
writeLine(`hooks: ${hooksOk ? "ok" : "warning
|
|
11949
|
+
writeLine(`hooks: ${hooksOk ? "ok" : "warning \u2014 hooks not registered; run onebrain update"}`);
|
|
11755
11950
|
}
|
|
11756
11951
|
result.ok = true;
|
|
11757
11952
|
result.exitCode = 0;
|
|
11758
11953
|
if (isTTY) {
|
|
11759
|
-
barLine(import_picocolors7.default.dim(
|
|
11954
|
+
barLine(import_picocolors7.default.dim(`\u2500\u2500\u2500 Next steps ${"\u2500".repeat(25)}`));
|
|
11760
11955
|
barBlank();
|
|
11761
|
-
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("1"))} \uD83D\uDCC1 Open Obsidian
|
|
11956
|
+
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("1"))} \uD83D\uDCC1 Open Obsidian \u2192 open this folder as vault`);
|
|
11762
11957
|
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("2"))} \uD83E\uDD16 Run ${import_picocolors7.default.cyan("claude")}`);
|
|
11763
11958
|
barLine(` ${import_picocolors7.default.bold(import_picocolors7.default.cyan("3"))} \uD83E\uDDE0 Type ${import_picocolors7.default.cyan("/onboarding")} to personalize`);
|
|
11764
11959
|
barBlank();
|
|
11765
|
-
close(
|
|
11960
|
+
close(`\u2728 ${import_picocolors7.default.bold("Ready")} \u2014 ${import_picocolors7.default.cyan("/onboarding")}`);
|
|
11766
11961
|
} else {
|
|
11767
11962
|
writeLine("done: run /onboarding in Claude to finish setup");
|
|
11768
11963
|
}
|
|
@@ -11776,9 +11971,9 @@ async function initCommand(opts = {}) {
|
|
|
11776
11971
|
}
|
|
11777
11972
|
|
|
11778
11973
|
// src/commands/internal/checkpoint.ts
|
|
11779
|
-
import { readFileSync, readdirSync, writeFileSync } from "
|
|
11780
|
-
import { tmpdir as osTmpdir } from "
|
|
11781
|
-
import { join as join7 } from "
|
|
11974
|
+
import { readFileSync, readdirSync, writeFileSync } from "fs";
|
|
11975
|
+
import { tmpdir as osTmpdir } from "os";
|
|
11976
|
+
import { join as join7 } from "path";
|
|
11782
11977
|
var SKIP_WINDOW = 60;
|
|
11783
11978
|
var MIN_ACTIVITY = 2;
|
|
11784
11979
|
var PRECOMPACT_RECENCY = 300;
|
|
@@ -11954,8 +12149,8 @@ async function checkpointCommand(mode, token, vaultRoot) {
|
|
|
11954
12149
|
// src/commands/internal/migrate.ts
|
|
11955
12150
|
init_lib();
|
|
11956
12151
|
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 "
|
|
12152
|
+
import { readFile as readFile4, readdir as readdir3, writeFile as writeFile4 } from "fs/promises";
|
|
12153
|
+
import { join as join8 } from "path";
|
|
11959
12154
|
function parseFrontmatterWithRest(rawText) {
|
|
11960
12155
|
const text = rawText.replace(/\r\n/g, `
|
|
11961
12156
|
`);
|
|
@@ -12024,7 +12219,7 @@ async function runBackfillRecapped(logsFolder, cutoffDate) {
|
|
|
12024
12219
|
const content = await readFile4(fpath, "utf8");
|
|
12025
12220
|
const parsed = parseFrontmatterWithRest(content);
|
|
12026
12221
|
if (!parsed) {
|
|
12027
|
-
process.stderr.write(`migrate: ${fname}
|
|
12222
|
+
process.stderr.write(`migrate: ${fname} \u2014 malformed frontmatter
|
|
12028
12223
|
`);
|
|
12029
12224
|
skipped++;
|
|
12030
12225
|
continue;
|
|
@@ -12071,8 +12266,8 @@ async function migrateCommand(migrationName, cutoffDate, vaultDir) {
|
|
|
12071
12266
|
|
|
12072
12267
|
// src/commands/internal/orphan-scan.ts
|
|
12073
12268
|
var import_yaml6 = __toESM(require_dist(), 1);
|
|
12074
|
-
import { readFile as readFile5, readdir as readdir4 } from "
|
|
12075
|
-
import { join as join9 } from "
|
|
12269
|
+
import { readFile as readFile5, readdir as readdir4 } from "fs/promises";
|
|
12270
|
+
import { join as join9 } from "path";
|
|
12076
12271
|
function parseFrontmatter(rawText) {
|
|
12077
12272
|
const text = rawText.replace(/\r\n/g, `
|
|
12078
12273
|
`);
|
|
@@ -12142,12 +12337,6 @@ async function scanMonthDir(monthDir, currentToken, today, seenTokens) {
|
|
|
12142
12337
|
continue;
|
|
12143
12338
|
if (seenTokens.has(ftoken))
|
|
12144
12339
|
continue;
|
|
12145
|
-
try {
|
|
12146
|
-
const content = await readFile5(join9(monthDir, fname), "utf8");
|
|
12147
|
-
const fm = parseFrontmatter(content);
|
|
12148
|
-
if (fm && (fm["merged"] === true || fm["merged"] === "true"))
|
|
12149
|
-
continue;
|
|
12150
|
-
} catch {}
|
|
12151
12340
|
if (await hasManualSessionLog(monthDir, fdate))
|
|
12152
12341
|
continue;
|
|
12153
12342
|
seenTokens.add(ftoken);
|
|
@@ -12206,332 +12395,70 @@ async function qmdReindexCommand(vaultRoot) {
|
|
|
12206
12395
|
}
|
|
12207
12396
|
}
|
|
12208
12397
|
|
|
12209
|
-
// src/
|
|
12210
|
-
|
|
12398
|
+
// src/index.ts
|
|
12399
|
+
init_register_hooks();
|
|
12400
|
+
|
|
12401
|
+
// src/commands/internal/session-init.ts
|
|
12211
12402
|
init_lib();
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
import {
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
12223
|
-
|
|
12224
|
-
|
|
12225
|
-
|
|
12226
|
-
"
|
|
12227
|
-
"
|
|
12228
|
-
"
|
|
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"
|
|
12403
|
+
import { unlink as unlink2 } from "fs/promises";
|
|
12404
|
+
import { tmpdir as osTmpdir2 } from "os";
|
|
12405
|
+
import { join as join10 } from "path";
|
|
12406
|
+
var DAY_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
12407
|
+
var MONTH_NAMES = [
|
|
12408
|
+
"Jan",
|
|
12409
|
+
"Feb",
|
|
12410
|
+
"Mar",
|
|
12411
|
+
"Apr",
|
|
12412
|
+
"May",
|
|
12413
|
+
"Jun",
|
|
12414
|
+
"Jul",
|
|
12415
|
+
"Aug",
|
|
12416
|
+
"Sep",
|
|
12417
|
+
"Oct",
|
|
12418
|
+
"Nov",
|
|
12419
|
+
"Dec"
|
|
12240
12420
|
];
|
|
12241
|
-
|
|
12242
|
-
|
|
12243
|
-
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
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);
|
|
12421
|
+
function formatDatetime(date) {
|
|
12422
|
+
const dow = DAY_NAMES[date.getDay()];
|
|
12423
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
12424
|
+
const mon = MONTH_NAMES[date.getMonth()];
|
|
12425
|
+
const year = date.getFullYear();
|
|
12426
|
+
const hh = String(date.getHours()).padStart(2, "0");
|
|
12427
|
+
const mm = String(date.getMinutes()).padStart(2, "0");
|
|
12428
|
+
return `${dow} \xB7 ${day} ${mon} ${year} \xB7 ${hh}:${mm}`;
|
|
12258
12429
|
}
|
|
12259
|
-
function
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
return "found";
|
|
12266
|
-
if (cmd.includes("checkpoint-hook.sh"))
|
|
12267
|
-
foundMigrate = true;
|
|
12268
|
-
}
|
|
12430
|
+
async function resolveSessionToken(tmpDir = osTmpdir2()) {
|
|
12431
|
+
const wtSession = process.env["WT_SESSION"];
|
|
12432
|
+
if (wtSession) {
|
|
12433
|
+
const stripped = wtSession.replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
|
|
12434
|
+
if (stripped.length > 0)
|
|
12435
|
+
return stripped;
|
|
12269
12436
|
}
|
|
12270
|
-
|
|
12271
|
-
|
|
12272
|
-
|
|
12273
|
-
|
|
12274
|
-
|
|
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];
|
|
12437
|
+
const tmuxPane = process.env["TMUX_PANE"];
|
|
12438
|
+
if (tmuxPane) {
|
|
12439
|
+
const stripped = tmuxPane.replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
|
|
12440
|
+
if (stripped.length > 0)
|
|
12441
|
+
return stripped;
|
|
12283
12442
|
}
|
|
12284
|
-
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
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
|
-
}
|
|
12443
|
+
const termSessionId = process.env["TERM_SESSION_ID"];
|
|
12444
|
+
if (termSessionId) {
|
|
12445
|
+
const stripped = termSessionId.replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
|
|
12446
|
+
if (stripped.length > 0)
|
|
12447
|
+
return stripped;
|
|
12311
12448
|
}
|
|
12312
|
-
|
|
12313
|
-
|
|
12314
|
-
|
|
12315
|
-
|
|
12316
|
-
|
|
12317
|
-
|
|
12318
|
-
|
|
12319
|
-
|
|
12320
|
-
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
12324
|
-
|
|
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
|
-
}
|
|
12473
|
-
|
|
12474
|
-
// src/commands/internal/session-init.ts
|
|
12475
|
-
init_lib();
|
|
12476
|
-
import { unlink as unlink2 } from "node:fs/promises";
|
|
12477
|
-
import { tmpdir as osTmpdir2 } from "node:os";
|
|
12478
|
-
import { join as join11 } from "node:path";
|
|
12479
|
-
var DAY_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
12480
|
-
var MONTH_NAMES = [
|
|
12481
|
-
"Jan",
|
|
12482
|
-
"Feb",
|
|
12483
|
-
"Mar",
|
|
12484
|
-
"Apr",
|
|
12485
|
-
"May",
|
|
12486
|
-
"Jun",
|
|
12487
|
-
"Jul",
|
|
12488
|
-
"Aug",
|
|
12489
|
-
"Sep",
|
|
12490
|
-
"Oct",
|
|
12491
|
-
"Nov",
|
|
12492
|
-
"Dec"
|
|
12493
|
-
];
|
|
12494
|
-
function formatDatetime(date) {
|
|
12495
|
-
const dow = DAY_NAMES[date.getDay()];
|
|
12496
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
12497
|
-
const mon = MONTH_NAMES[date.getMonth()];
|
|
12498
|
-
const year = date.getFullYear();
|
|
12499
|
-
const hh = String(date.getHours()).padStart(2, "0");
|
|
12500
|
-
const mm = String(date.getMinutes()).padStart(2, "0");
|
|
12501
|
-
return `${dow} · ${day} ${mon} ${year} · ${hh}:${mm}`;
|
|
12502
|
-
}
|
|
12503
|
-
async function resolveSessionToken(tmpDir = osTmpdir2()) {
|
|
12504
|
-
const wtSession = process.env["WT_SESSION"];
|
|
12505
|
-
if (wtSession) {
|
|
12506
|
-
const stripped = wtSession.replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
|
|
12507
|
-
if (stripped.length > 0)
|
|
12508
|
-
return stripped;
|
|
12509
|
-
}
|
|
12510
|
-
const tmuxPane = process.env["TMUX_PANE"];
|
|
12511
|
-
if (tmuxPane) {
|
|
12512
|
-
const stripped = tmuxPane.replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
|
|
12513
|
-
if (stripped.length > 0)
|
|
12514
|
-
return stripped;
|
|
12515
|
-
}
|
|
12516
|
-
const termSessionId = process.env["TERM_SESSION_ID"];
|
|
12517
|
-
if (termSessionId) {
|
|
12518
|
-
const stripped = termSessionId.replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
|
|
12519
|
-
if (stripped.length > 0)
|
|
12520
|
-
return stripped;
|
|
12521
|
-
}
|
|
12522
|
-
const today = new Date;
|
|
12523
|
-
const yyyymmdd = [
|
|
12524
|
-
today.getFullYear(),
|
|
12525
|
-
String(today.getMonth() + 1).padStart(2, "0"),
|
|
12526
|
-
String(today.getDate()).padStart(2, "0")
|
|
12527
|
-
].join("");
|
|
12528
|
-
const cacheFile = join11(tmpDir, `onebrain-day-${yyyymmdd}.token`);
|
|
12529
|
-
const cacheExists = await Bun.file(cacheFile).exists();
|
|
12530
|
-
if (cacheExists) {
|
|
12531
|
-
const cached = (await Bun.file(cacheFile).text()).trim();
|
|
12532
|
-
const n = Number(cached);
|
|
12533
|
-
if (!Number.isNaN(n) && n > 1)
|
|
12534
|
-
return cached;
|
|
12449
|
+
const today = new Date;
|
|
12450
|
+
const yyyymmdd = [
|
|
12451
|
+
today.getFullYear(),
|
|
12452
|
+
String(today.getMonth() + 1).padStart(2, "0"),
|
|
12453
|
+
String(today.getDate()).padStart(2, "0")
|
|
12454
|
+
].join("");
|
|
12455
|
+
const cacheFile = join10(tmpDir, `onebrain-day-${yyyymmdd}.token`);
|
|
12456
|
+
const cacheExists = await Bun.file(cacheFile).exists();
|
|
12457
|
+
if (cacheExists) {
|
|
12458
|
+
const cached = (await Bun.file(cacheFile).text()).trim();
|
|
12459
|
+
const n = Number(cached);
|
|
12460
|
+
if (!Number.isNaN(n) && n > 1)
|
|
12461
|
+
return cached;
|
|
12535
12462
|
}
|
|
12536
12463
|
const ppid = process.ppid;
|
|
12537
12464
|
if (ppid !== undefined && ppid > 1) {
|
|
@@ -12577,7 +12504,7 @@ async function resolveSessionToken(tmpDir = osTmpdir2()) {
|
|
|
12577
12504
|
async function cleanStaleStateFile(token, tmpDir) {
|
|
12578
12505
|
try {
|
|
12579
12506
|
const processStartMs = Date.now() - performance.now();
|
|
12580
|
-
const stateFile =
|
|
12507
|
+
const stateFile = join10(tmpDir, `onebrain-${token}.state`);
|
|
12581
12508
|
const f2 = Bun.file(stateFile);
|
|
12582
12509
|
const exists = await f2.exists();
|
|
12583
12510
|
if (!exists)
|
|
@@ -12642,523 +12569,11 @@ async function sessionInitCommand(vaultRoot) {
|
|
|
12642
12569
|
`);
|
|
12643
12570
|
}
|
|
12644
12571
|
|
|
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
|
-
}
|
|
12572
|
+
// src/index.ts
|
|
12573
|
+
init_vault_sync();
|
|
13159
12574
|
|
|
13160
12575
|
// src/commands/update.ts
|
|
13161
|
-
var
|
|
12576
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
13162
12577
|
init_cli_ui();
|
|
13163
12578
|
var GITHUB_REPO = "https://api.github.com/repos/kengio/onebrain";
|
|
13164
12579
|
var GITHUB_RELEASES_URL = `${GITHUB_REPO}/releases/latest`;
|
|
@@ -13253,7 +12668,7 @@ async function runUpdate(opts = {}) {
|
|
|
13253
12668
|
const sp1 = createStep("\uD83D\uDD0D", "Local version");
|
|
13254
12669
|
const { version: currentVersion, publishedAt: localPublishedAt } = await currentVersionFn();
|
|
13255
12670
|
result.currentVersion = currentVersion;
|
|
13256
|
-
const localVersionLabel = localPublishedAt ? `${
|
|
12671
|
+
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
12672
|
if (sp1)
|
|
13258
12673
|
sp1.stop(localVersionLabel);
|
|
13259
12674
|
else
|
|
@@ -13265,9 +12680,9 @@ async function runUpdate(opts = {}) {
|
|
|
13265
12680
|
const release = await fetchLatestRelease(fetchFn);
|
|
13266
12681
|
latestVersion = release.version;
|
|
13267
12682
|
publishedAt = release.publishedAt;
|
|
13268
|
-
const dateSuffix = publishedAt ? ` ${
|
|
12683
|
+
const dateSuffix = publishedAt ? ` ${import_picocolors8.default.dim("\xB7")} ${import_picocolors8.default.dim(formatReleaseDate(publishedAt))}` : "";
|
|
13269
12684
|
if (sp2)
|
|
13270
|
-
sp2.stop(`${
|
|
12685
|
+
sp2.stop(`${import_picocolors8.default.green(latestVersion)}${dateSuffix}`);
|
|
13271
12686
|
else
|
|
13272
12687
|
writeLine(`latest: ${latestVersion}`);
|
|
13273
12688
|
} catch (err) {
|
|
@@ -13288,12 +12703,12 @@ async function runUpdate(opts = {}) {
|
|
|
13288
12703
|
if (check) {
|
|
13289
12704
|
if (isTTY) {
|
|
13290
12705
|
if (currentVersion !== latestVersion) {
|
|
13291
|
-
barLine(
|
|
12706
|
+
barLine(`\u2B06\uFE0F ${import_picocolors8.default.dim(currentVersion)} \u2192 ${import_picocolors8.default.green(latestVersion)} \xB7 binary would upgrade`);
|
|
13292
12707
|
barBlank();
|
|
13293
12708
|
}
|
|
13294
|
-
close("Dry run complete
|
|
12709
|
+
close("Dry run complete \u2014 no changes made");
|
|
13295
12710
|
} else {
|
|
13296
|
-
writeLine("done: dry run complete
|
|
12711
|
+
writeLine("done: dry run complete \u2014 no changes made");
|
|
13297
12712
|
}
|
|
13298
12713
|
result.ok = true;
|
|
13299
12714
|
result.exitCode = 0;
|
|
@@ -13301,7 +12716,7 @@ async function runUpdate(opts = {}) {
|
|
|
13301
12716
|
}
|
|
13302
12717
|
if (latestVersion === currentVersion) {
|
|
13303
12718
|
if (isTTY) {
|
|
13304
|
-
close(`Already up to date
|
|
12719
|
+
close(`Already up to date \u2014 @onebrain-ai/cli ${import_picocolors8.default.dim(latestVersion)}`);
|
|
13305
12720
|
} else {
|
|
13306
12721
|
writeLine(`already up to date: @onebrain-ai/cli ${latestVersion}`);
|
|
13307
12722
|
writeLine("done: nothing to do");
|
|
@@ -13311,14 +12726,14 @@ async function runUpdate(opts = {}) {
|
|
|
13311
12726
|
return result;
|
|
13312
12727
|
}
|
|
13313
12728
|
if (isTTY) {
|
|
13314
|
-
barLine(
|
|
12729
|
+
barLine(`\u2B06\uFE0F ${import_picocolors8.default.dim(currentVersion)} \u2192 ${import_picocolors8.default.green(latestVersion)}`);
|
|
13315
12730
|
barBlank();
|
|
13316
12731
|
}
|
|
13317
12732
|
const sp3 = createStep("\uD83D\uDCE6", "Installing @onebrain-ai/cli");
|
|
13318
12733
|
try {
|
|
13319
12734
|
await installBinaryFn(latestVersion);
|
|
13320
12735
|
if (sp3)
|
|
13321
|
-
sp3.stop(
|
|
12736
|
+
sp3.stop(import_picocolors8.default.green(latestVersion));
|
|
13322
12737
|
else
|
|
13323
12738
|
writeLine(`upgrading: @onebrain-ai/cli ${latestVersion} installed`);
|
|
13324
12739
|
} catch (err) {
|
|
@@ -13335,7 +12750,7 @@ async function runUpdate(opts = {}) {
|
|
|
13335
12750
|
}
|
|
13336
12751
|
return result;
|
|
13337
12752
|
}
|
|
13338
|
-
const sp4 = createStep("
|
|
12753
|
+
const sp4 = createStep("\u2705", "Validating binary");
|
|
13339
12754
|
const binaryValid = await validateBinaryFn();
|
|
13340
12755
|
if (!binaryValid) {
|
|
13341
12756
|
if (sp4)
|
|
@@ -13355,7 +12770,7 @@ async function runUpdate(opts = {}) {
|
|
|
13355
12770
|
result.ok = true;
|
|
13356
12771
|
result.exitCode = 0;
|
|
13357
12772
|
if (isTTY) {
|
|
13358
|
-
close(`Done
|
|
12773
|
+
close(`Done \u2014 run ${import_picocolors8.default.cyan("/update")} in Claude to sync vault files`);
|
|
13359
12774
|
} else {
|
|
13360
12775
|
writeLine("done: run /update in Claude to sync vault files");
|
|
13361
12776
|
}
|
|
@@ -13382,8 +12797,8 @@ function patchUtf8(stream) {
|
|
|
13382
12797
|
}
|
|
13383
12798
|
|
|
13384
12799
|
// src/index.ts
|
|
13385
|
-
var VERSION = "2.1.
|
|
13386
|
-
var RELEASE_DATE = "2026-04-
|
|
12800
|
+
var VERSION = "2.1.5";
|
|
12801
|
+
var RELEASE_DATE = "2026-04-29";
|
|
13387
12802
|
patchUtf8(process.stdout);
|
|
13388
12803
|
patchUtf8(process.stderr);
|
|
13389
12804
|
var VERSION_STRING = `OneBrain v${VERSION} \u2014 released ${RELEASE_DATE}`;
|
|
@@ -13397,9 +12812,9 @@ function findVaultRoot(startDir) {
|
|
|
13397
12812
|
return process.cwd();
|
|
13398
12813
|
let dir = startDir;
|
|
13399
12814
|
while (true) {
|
|
13400
|
-
if (existsSync(
|
|
12815
|
+
if (existsSync(join11(dir, "vault.yml")))
|
|
13401
12816
|
return dir;
|
|
13402
|
-
const parent =
|
|
12817
|
+
const parent = dirname4(dir);
|
|
13403
12818
|
if (parent === dir)
|
|
13404
12819
|
return startDir;
|
|
13405
12820
|
dir = parent;
|
|
@@ -13446,10 +12861,10 @@ program2.command("qmd-reindex", { hidden: true }).description("Trigger qmd index
|
|
|
13446
12861
|
});
|
|
13447
12862
|
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
12863
|
const root = vaultRoot ?? process.cwd();
|
|
13449
|
-
await
|
|
12864
|
+
await vaultSyncCommand(root, opts.branch !== undefined ? { branch: opts.branch } : {});
|
|
13450
12865
|
});
|
|
13451
12866
|
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
|
|
12867
|
+
await registerHooksCommand(opts.vaultDir);
|
|
13453
12868
|
});
|
|
13454
12869
|
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
12870
|
await migrateCommand(name, cutoffDate);
|