@onebrain-ai/cli 2.0.3 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/onebrain +134 -30
- package/package.json +1 -1
package/dist/onebrain
CHANGED
|
@@ -10742,7 +10742,7 @@ init_dist();
|
|
|
10742
10742
|
import { mkdir as mkdir3, readFile as readFile3, rename as rename3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
10743
10743
|
import { homedir as homedir3 } from "node:os";
|
|
10744
10744
|
import { dirname as dirname3, join as join5 } from "node:path";
|
|
10745
|
-
var binaryVersion = "2.0.
|
|
10745
|
+
var binaryVersion = "2.0.4";
|
|
10746
10746
|
var STANDARD_FOLDERS = [
|
|
10747
10747
|
"00-inbox",
|
|
10748
10748
|
"01-projects",
|
|
@@ -11228,8 +11228,8 @@ async function updateCommand(opts = {}) {
|
|
|
11228
11228
|
}
|
|
11229
11229
|
|
|
11230
11230
|
// src/internal/checkpoint.ts
|
|
11231
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
11232
|
-
import { mkdir as mkdir4, writeFile as writeFile5 } from "node:fs/promises";
|
|
11231
|
+
import { readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
11232
|
+
import { mkdir as mkdir4, readdir as readdir2, writeFile as writeFile5 } from "node:fs/promises";
|
|
11233
11233
|
import { tmpdir as osTmpdir } from "node:os";
|
|
11234
11234
|
import { join as join7 } from "node:path";
|
|
11235
11235
|
var SKIP_WINDOW = 60;
|
|
@@ -11282,13 +11282,15 @@ function writeState(token, state, tmpDir = osTmpdir()) {
|
|
|
11282
11282
|
`);
|
|
11283
11283
|
}
|
|
11284
11284
|
}
|
|
11285
|
-
|
|
11285
|
+
var DEFAULT_LOGS_FOLDER = "07-logs";
|
|
11286
|
+
function loadVaultSettings(vaultRoot) {
|
|
11286
11287
|
try {
|
|
11287
11288
|
const vaultYml = join7(vaultRoot, "vault.yml");
|
|
11288
11289
|
const raw = readFileSync(vaultYml, "utf8");
|
|
11289
|
-
const checkpointBlock = raw.match(/^checkpoint:\s*\n((?:[ \t]+[^\n]+\n?)*)/m);
|
|
11290
11290
|
let messages = DEFAULT_MESSAGES_THRESHOLD;
|
|
11291
11291
|
let minutes = DEFAULT_MINUTES_THRESHOLD;
|
|
11292
|
+
let logsFolder = DEFAULT_LOGS_FOLDER;
|
|
11293
|
+
const checkpointBlock = raw.match(/^checkpoint:\s*\n((?:[ \t]+[^\n]+\n?)*)/m);
|
|
11292
11294
|
if (checkpointBlock?.[1]) {
|
|
11293
11295
|
const block = checkpointBlock[1];
|
|
11294
11296
|
const msgMatch = block.match(/messages:\s*(\d+)/);
|
|
@@ -11298,14 +11300,40 @@ function loadThresholds(vaultRoot) {
|
|
|
11298
11300
|
if (minMatch?.[1])
|
|
11299
11301
|
minutes = Number(minMatch[1]);
|
|
11300
11302
|
}
|
|
11301
|
-
|
|
11303
|
+
const foldersBlock = raw.match(/^folders:\s*\n((?:[ \t]+[^\n]+\n?)*)/m);
|
|
11304
|
+
if (foldersBlock?.[1]) {
|
|
11305
|
+
const logsMatch = foldersBlock[1].match(/logs:\s*['"]?([^'"\s]+)['"]?/);
|
|
11306
|
+
if (logsMatch?.[1])
|
|
11307
|
+
logsFolder = logsMatch[1];
|
|
11308
|
+
}
|
|
11309
|
+
return { messagesThreshold: messages, minutesThreshold: minutes, logsFolder };
|
|
11302
11310
|
} catch {
|
|
11303
11311
|
return {
|
|
11304
11312
|
messagesThreshold: DEFAULT_MESSAGES_THRESHOLD,
|
|
11305
|
-
minutesThreshold: DEFAULT_MINUTES_THRESHOLD
|
|
11313
|
+
minutesThreshold: DEFAULT_MINUTES_THRESHOLD,
|
|
11314
|
+
logsFolder: DEFAULT_LOGS_FOLDER
|
|
11306
11315
|
};
|
|
11307
11316
|
}
|
|
11308
11317
|
}
|
|
11318
|
+
function maxCheckpointNnSync(vaultRoot, date, token, logsFolder) {
|
|
11319
|
+
const yyyy = date.slice(0, 4);
|
|
11320
|
+
const mm = date.slice(5, 7);
|
|
11321
|
+
const dir = join7(vaultRoot, logsFolder, yyyy, mm);
|
|
11322
|
+
const prefix = `${date}-${token}-checkpoint-`;
|
|
11323
|
+
try {
|
|
11324
|
+
let max = 0;
|
|
11325
|
+
for (const f2 of readdirSync(dir)) {
|
|
11326
|
+
if (!f2.startsWith(prefix) || !f2.endsWith(".md"))
|
|
11327
|
+
continue;
|
|
11328
|
+
const m3 = f2.match(/-checkpoint-(\d{2})\.md$/);
|
|
11329
|
+
if (m3)
|
|
11330
|
+
max = Math.max(max, Number(m3[1]));
|
|
11331
|
+
}
|
|
11332
|
+
return max;
|
|
11333
|
+
} catch {
|
|
11334
|
+
return 0;
|
|
11335
|
+
}
|
|
11336
|
+
}
|
|
11309
11337
|
function formatDate(epochSeconds) {
|
|
11310
11338
|
const d2 = new Date(epochSeconds * 1000);
|
|
11311
11339
|
const yyyy = d2.getFullYear().toString();
|
|
@@ -11332,7 +11360,7 @@ function handleStop(token, vaultRoot, now = Math.floor(Date.now() / 1000), tmpDi
|
|
|
11332
11360
|
return;
|
|
11333
11361
|
}
|
|
11334
11362
|
state.count += 1;
|
|
11335
|
-
const { messagesThreshold, minutesThreshold } =
|
|
11363
|
+
const { messagesThreshold, minutesThreshold, logsFolder } = loadVaultSettings(vaultRoot);
|
|
11336
11364
|
const timeThreshold = minutesThreshold * 60;
|
|
11337
11365
|
const elapsed = state.last_ts === 0 ? 0 : now - state.last_ts;
|
|
11338
11366
|
const thresholdMet = state.count >= messagesThreshold || elapsed >= timeThreshold;
|
|
@@ -11344,12 +11372,13 @@ function handleStop(token, vaultRoot, now = Math.floor(Date.now() / 1000), tmpDi
|
|
|
11344
11372
|
writeState(token, { count: state.count, last_ts: state.last_ts, last_stop_nn: state.last_stop_nn }, tmpDir);
|
|
11345
11373
|
return;
|
|
11346
11374
|
}
|
|
11347
|
-
const nextNn = String(Number(state.last_stop_nn) + 1).padStart(2, "0");
|
|
11348
11375
|
const date = formatDate(now);
|
|
11376
|
+
const maxNn = maxCheckpointNnSync(vaultRoot, date, token, logsFolder);
|
|
11377
|
+
const nextNn = String(maxNn + 1).padStart(2, "0");
|
|
11378
|
+
const since = maxNn === 0 ? " since start" : ` since checkpoint-${String(maxNn).padStart(2, "0")}`;
|
|
11349
11379
|
const filename = `${date}-${token}-checkpoint-${nextNn}.md`;
|
|
11350
|
-
const since = state.last_stop_nn === "00" ? " since start" : ` since checkpoint-${state.last_stop_nn}`;
|
|
11351
11380
|
emitBlock(`${filename}${since}`);
|
|
11352
|
-
writeState(token, { count: 0, last_ts: now, last_stop_nn: nextNn }, tmpDir);
|
|
11381
|
+
writeState(token, { count: 0, last_ts: now, last_stop_nn: nextNn, pending_stub: state.pending_stub }, tmpDir);
|
|
11353
11382
|
}
|
|
11354
11383
|
var PRECOMPACT_STUB_TEMPLATE = (date, nn) => `---
|
|
11355
11384
|
tags: [checkpoint, session-log]
|
|
@@ -11388,10 +11417,11 @@ async function handlePrecompact(token, vaultRoot, now = Math.floor(Date.now() /
|
|
|
11388
11417
|
if (state.last_ts > 0 && now - state.last_ts < PRECOMPACT_RECENCY) {
|
|
11389
11418
|
return;
|
|
11390
11419
|
}
|
|
11391
|
-
|
|
11420
|
+
if (state.pending_stub) {
|
|
11421
|
+
return;
|
|
11422
|
+
}
|
|
11392
11423
|
const date = formatDate(now);
|
|
11393
|
-
|
|
11394
|
-
let logsFolder = "07-logs";
|
|
11424
|
+
let logsFolder = DEFAULT_LOGS_FOLDER;
|
|
11395
11425
|
try {
|
|
11396
11426
|
const config = await loadVaultConfig(vaultRoot);
|
|
11397
11427
|
logsFolder = config.folders.logs;
|
|
@@ -11399,6 +11429,16 @@ async function handlePrecompact(token, vaultRoot, now = Math.floor(Date.now() /
|
|
|
11399
11429
|
const yyyy = formatYYYY(now);
|
|
11400
11430
|
const mm = formatMM(now);
|
|
11401
11431
|
const stubDir = join7(vaultRoot, logsFolder, yyyy, mm);
|
|
11432
|
+
const existingFiles = await readdir2(stubDir).catch(() => []);
|
|
11433
|
+
const prefix = `${date}-${token}-checkpoint-`;
|
|
11434
|
+
const maxNn = existingFiles.reduce((max, f2) => {
|
|
11435
|
+
if (!f2.startsWith(prefix) || !f2.endsWith(".md"))
|
|
11436
|
+
return max;
|
|
11437
|
+
const m3 = f2.match(/-checkpoint-(\d{2})\.md$/);
|
|
11438
|
+
return m3 ? Math.max(max, Number(m3[1])) : max;
|
|
11439
|
+
}, 0);
|
|
11440
|
+
const stubNn = String(maxNn + 1).padStart(2, "0");
|
|
11441
|
+
const stubFilename = `${date}-${token}-checkpoint-${stubNn}.md`;
|
|
11402
11442
|
const stubPath = join7(stubDir, stubFilename);
|
|
11403
11443
|
try {
|
|
11404
11444
|
await mkdir4(stubDir, { recursive: true });
|
|
@@ -11415,15 +11455,79 @@ async function handlePrecompact(token, vaultRoot, now = Math.floor(Date.now() /
|
|
|
11415
11455
|
pending_stub: stubFilename
|
|
11416
11456
|
}, tmpDir);
|
|
11417
11457
|
}
|
|
11418
|
-
function handlePostcompact(token,
|
|
11458
|
+
function handlePostcompact(token, vaultRoot, now = Math.floor(Date.now() / 1000), tmpDir = osTmpdir()) {
|
|
11419
11459
|
const state = readState(token, tmpDir);
|
|
11420
11460
|
if (!state.pending_stub) {
|
|
11421
11461
|
writeState(token, { count: 0, last_ts: state.last_ts, last_stop_nn: state.last_stop_nn }, tmpDir);
|
|
11422
11462
|
return;
|
|
11423
11463
|
}
|
|
11424
|
-
const
|
|
11464
|
+
const stubNnMatch = state.pending_stub.match(/-checkpoint-(\d{2})\.md$/);
|
|
11465
|
+
const stubNn = stubNnMatch?.[1] ?? "01";
|
|
11466
|
+
const stubNnNum = Number(stubNn);
|
|
11467
|
+
const { logsFolder } = loadVaultSettings(vaultRoot);
|
|
11468
|
+
const date = state.pending_stub.slice(0, 10);
|
|
11469
|
+
const yyyy = date.slice(0, 4);
|
|
11470
|
+
const mm = date.slice(5, 7);
|
|
11471
|
+
const dir = join7(vaultRoot, logsFolder, yyyy, mm);
|
|
11472
|
+
const prefix = `${date}-${token}-checkpoint-`;
|
|
11473
|
+
let predecessorNn = 0;
|
|
11474
|
+
try {
|
|
11475
|
+
for (const f2 of readdirSync(dir)) {
|
|
11476
|
+
if (!f2.startsWith(prefix) || !f2.endsWith(".md"))
|
|
11477
|
+
continue;
|
|
11478
|
+
const m3 = f2.match(/-checkpoint-(\d{2})\.md$/);
|
|
11479
|
+
if (m3) {
|
|
11480
|
+
const nn = Number(m3[1]);
|
|
11481
|
+
if (nn < stubNnNum)
|
|
11482
|
+
predecessorNn = Math.max(predecessorNn, nn);
|
|
11483
|
+
}
|
|
11484
|
+
}
|
|
11485
|
+
} catch {}
|
|
11486
|
+
const since = predecessorNn === 0 ? " since start" : ` since checkpoint-${String(predecessorNn).padStart(2, "0")}`;
|
|
11425
11487
|
emitBlock(`fill-checkpoint: ${state.pending_stub}${since}`);
|
|
11426
|
-
writeState(token, { count: 0, last_ts:
|
|
11488
|
+
writeState(token, { count: 0, last_ts: now, last_stop_nn: stubNn }, tmpDir);
|
|
11489
|
+
}
|
|
11490
|
+
function postcompactFallback(token, vaultRoot, now = Math.floor(Date.now() / 1000), tmpDir = osTmpdir()) {
|
|
11491
|
+
const state = readState(token, tmpDir);
|
|
11492
|
+
if (state.pending_stub) {
|
|
11493
|
+
handlePostcompact(token, vaultRoot, now, tmpDir);
|
|
11494
|
+
return;
|
|
11495
|
+
}
|
|
11496
|
+
const { logsFolder } = loadVaultSettings(vaultRoot);
|
|
11497
|
+
const date = formatDate(now);
|
|
11498
|
+
const yyyy = date.slice(0, 4);
|
|
11499
|
+
const mm = date.slice(5, 7);
|
|
11500
|
+
const dir = join7(vaultRoot, logsFolder, yyyy, mm);
|
|
11501
|
+
const prefix = `${date}-${token}-checkpoint-`;
|
|
11502
|
+
const stubs = [];
|
|
11503
|
+
const allNns = [];
|
|
11504
|
+
try {
|
|
11505
|
+
for (const f2 of readdirSync(dir)) {
|
|
11506
|
+
if (!f2.startsWith(prefix) || !f2.endsWith(".md"))
|
|
11507
|
+
continue;
|
|
11508
|
+
const m3 = f2.match(/-checkpoint-(\d{2})\.md$/);
|
|
11509
|
+
if (!m3)
|
|
11510
|
+
continue;
|
|
11511
|
+
allNns.push(Number(m3[1]));
|
|
11512
|
+
const content = readFileSync(join7(dir, f2), "utf8");
|
|
11513
|
+
if (/^trigger:\s*precompact/m.test(content) && !/^merged:\s*true/m.test(content)) {
|
|
11514
|
+
stubs.push(f2);
|
|
11515
|
+
}
|
|
11516
|
+
}
|
|
11517
|
+
} catch {}
|
|
11518
|
+
if (stubs.length === 0) {
|
|
11519
|
+
writeState(token, { count: 0, last_ts: state.last_ts, last_stop_nn: state.last_stop_nn }, tmpDir);
|
|
11520
|
+
return;
|
|
11521
|
+
}
|
|
11522
|
+
stubs.sort();
|
|
11523
|
+
const stubFilename = stubs[stubs.length - 1];
|
|
11524
|
+
const stubNnMatch = stubFilename.match(/-checkpoint-(\d{2})\.md$/);
|
|
11525
|
+
const stubNn = stubNnMatch?.[1] ?? "01";
|
|
11526
|
+
const stubNnNum = Number(stubNn);
|
|
11527
|
+
const predecessorNn = allNns.filter((n) => n < stubNnNum).reduce((max, n) => Math.max(max, n), 0);
|
|
11528
|
+
const since = predecessorNn === 0 ? " since start" : ` since checkpoint-${String(predecessorNn).padStart(2, "0")}`;
|
|
11529
|
+
emitBlock(`fill-checkpoint: ${stubFilename}${since}`);
|
|
11530
|
+
writeState(token, { count: 0, last_ts: now, last_stop_nn: stubNn }, tmpDir);
|
|
11427
11531
|
}
|
|
11428
11532
|
async function checkpointCommand(mode, token, vaultRoot) {
|
|
11429
11533
|
try {
|
|
@@ -11435,7 +11539,7 @@ async function checkpointCommand(mode, token, vaultRoot) {
|
|
|
11435
11539
|
await handlePrecompact(token, vaultRoot);
|
|
11436
11540
|
break;
|
|
11437
11541
|
case "postcompact":
|
|
11438
|
-
|
|
11542
|
+
postcompactFallback(token, vaultRoot);
|
|
11439
11543
|
break;
|
|
11440
11544
|
case "reset":
|
|
11441
11545
|
handleReset(token);
|
|
@@ -11451,7 +11555,7 @@ async function checkpointCommand(mode, token, vaultRoot) {
|
|
|
11451
11555
|
}
|
|
11452
11556
|
|
|
11453
11557
|
// src/internal/migrate.ts
|
|
11454
|
-
import { readFile as readFile5, readdir as
|
|
11558
|
+
import { readFile as readFile5, readdir as readdir3, writeFile as writeFile6 } from "node:fs/promises";
|
|
11455
11559
|
import { join as join8 } from "node:path";
|
|
11456
11560
|
init_dist();
|
|
11457
11561
|
function parseFrontmatterWithRest(rawText) {
|
|
@@ -11480,7 +11584,7 @@ function parseFrontmatterWithRest(rawText) {
|
|
|
11480
11584
|
}
|
|
11481
11585
|
async function listMdFiles(dir) {
|
|
11482
11586
|
try {
|
|
11483
|
-
const entries = await
|
|
11587
|
+
const entries = await readdir3(dir);
|
|
11484
11588
|
return entries.filter((e2) => e2.endsWith(".md"));
|
|
11485
11589
|
} catch {
|
|
11486
11590
|
return [];
|
|
@@ -11492,7 +11596,7 @@ async function runBackfillRecapped(logsFolder) {
|
|
|
11492
11596
|
let skipped = 0;
|
|
11493
11597
|
let yearDirs = [];
|
|
11494
11598
|
try {
|
|
11495
|
-
yearDirs = await
|
|
11599
|
+
yearDirs = await readdir3(logsFolder);
|
|
11496
11600
|
} catch {
|
|
11497
11601
|
return { backfilled: 0, skipped: 0 };
|
|
11498
11602
|
}
|
|
@@ -11500,7 +11604,7 @@ async function runBackfillRecapped(logsFolder) {
|
|
|
11500
11604
|
const yearPath = join8(logsFolder, yearDir);
|
|
11501
11605
|
let monthDirs = [];
|
|
11502
11606
|
try {
|
|
11503
|
-
monthDirs = await
|
|
11607
|
+
monthDirs = await readdir3(yearPath);
|
|
11504
11608
|
} catch {
|
|
11505
11609
|
continue;
|
|
11506
11610
|
}
|
|
@@ -11563,7 +11667,7 @@ async function migrateCommand(migrationName) {
|
|
|
11563
11667
|
|
|
11564
11668
|
// src/internal/orphan-scan.ts
|
|
11565
11669
|
init_dist();
|
|
11566
|
-
import { readFile as readFile6, readdir as
|
|
11670
|
+
import { readFile as readFile6, readdir as readdir4 } from "node:fs/promises";
|
|
11567
11671
|
import { join as join9 } from "node:path";
|
|
11568
11672
|
function parseFrontmatter(rawText) {
|
|
11569
11673
|
const text = rawText.replace(/\r\n/g, `
|
|
@@ -11592,7 +11696,7 @@ function getMonthParts(now = new Date) {
|
|
|
11592
11696
|
}
|
|
11593
11697
|
async function listMdFiles2(dir) {
|
|
11594
11698
|
try {
|
|
11595
|
-
const entries = await
|
|
11699
|
+
const entries = await readdir4(dir);
|
|
11596
11700
|
return entries.filter((e2) => e2.endsWith(".md"));
|
|
11597
11701
|
} catch {
|
|
11598
11702
|
return [];
|
|
@@ -12115,7 +12219,7 @@ import {
|
|
|
12115
12219
|
mkdir as mkdir6,
|
|
12116
12220
|
mkdtemp as mkdtemp2,
|
|
12117
12221
|
readFile as readFile8,
|
|
12118
|
-
readdir as
|
|
12222
|
+
readdir as readdir5,
|
|
12119
12223
|
rename as rename6,
|
|
12120
12224
|
rm as rm2,
|
|
12121
12225
|
stat as stat4,
|
|
@@ -12156,7 +12260,7 @@ async function extractTarball2(tarball, destDir) {
|
|
|
12156
12260
|
throw new Error(`tar extraction failed (exit ${exitCode}): ${errText.trim()}`);
|
|
12157
12261
|
}
|
|
12158
12262
|
await unlink3(tarPath);
|
|
12159
|
-
const entries = await
|
|
12263
|
+
const entries = await readdir5(destDir);
|
|
12160
12264
|
const topLevel = entries.find((e2) => e2 !== "bundle.tar.gz");
|
|
12161
12265
|
if (!topLevel) {
|
|
12162
12266
|
throw new Error("Extracted tarball contains no top-level directory");
|
|
@@ -12170,7 +12274,7 @@ async function listFilesRecursive2(dir) {
|
|
|
12170
12274
|
const current = queue.pop();
|
|
12171
12275
|
let entries;
|
|
12172
12276
|
try {
|
|
12173
|
-
entries = await
|
|
12277
|
+
entries = await readdir5(current);
|
|
12174
12278
|
} catch {
|
|
12175
12279
|
continue;
|
|
12176
12280
|
}
|
|
@@ -12395,7 +12499,7 @@ async function cleanPluginCache2(installedPluginsPath, installedPluginsCacheDir)
|
|
|
12395
12499
|
} catch {}
|
|
12396
12500
|
if (onebrainDirs.length === 0) {
|
|
12397
12501
|
try {
|
|
12398
|
-
const marketplaceDirs = await
|
|
12502
|
+
const marketplaceDirs = await readdir5(cacheDir);
|
|
12399
12503
|
for (const mp of marketplaceDirs) {
|
|
12400
12504
|
const candidate = join12(cacheDir, mp, "onebrain");
|
|
12401
12505
|
try {
|
|
@@ -12411,7 +12515,7 @@ async function cleanPluginCache2(installedPluginsPath, installedPluginsCacheDir)
|
|
|
12411
12515
|
for (const pluginDir of onebrainDirs) {
|
|
12412
12516
|
let versionDirs;
|
|
12413
12517
|
try {
|
|
12414
|
-
versionDirs = await
|
|
12518
|
+
versionDirs = await readdir5(pluginDir);
|
|
12415
12519
|
} catch {
|
|
12416
12520
|
continue;
|
|
12417
12521
|
}
|
|
@@ -12598,7 +12702,7 @@ async function vaultSyncCommand2(vaultRoot, opts = {}) {
|
|
|
12598
12702
|
}
|
|
12599
12703
|
|
|
12600
12704
|
// src/index.ts
|
|
12601
|
-
var VERSION = "2.0.
|
|
12705
|
+
var VERSION = "2.0.4";
|
|
12602
12706
|
var RELEASE_DATE = "2026-04-25";
|
|
12603
12707
|
var VERSION_STRING = `OneBrain v${VERSION} \u2014 released ${RELEASE_DATE}`;
|
|
12604
12708
|
if (process.argv.slice(2).length === 0) {
|