bertrand 0.22.0 → 0.22.1
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/bertrand.js +51 -29
- package/package.json +1 -1
package/dist/bertrand.js
CHANGED
|
@@ -1363,6 +1363,8 @@ var init_update = __esm(() => {
|
|
|
1363
1363
|
|
|
1364
1364
|
// src/lib/transcript.ts
|
|
1365
1365
|
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
1366
|
+
import { homedir as homedir2 } from "os";
|
|
1367
|
+
import { join as join6 } from "path";
|
|
1366
1368
|
function getContextWindowSize(model) {
|
|
1367
1369
|
for (const [prefix, size] of Object.entries(CONTEXT_WINDOW_SIZES)) {
|
|
1368
1370
|
if (model.startsWith(prefix))
|
|
@@ -1370,6 +1372,13 @@ function getContextWindowSize(model) {
|
|
|
1370
1372
|
}
|
|
1371
1373
|
return 200000;
|
|
1372
1374
|
}
|
|
1375
|
+
function claudeTranscriptPath(sessionId, cwd) {
|
|
1376
|
+
const dir = (cwd ?? process.cwd()).replace(/\//g, "-");
|
|
1377
|
+
return join6(homedir2(), ".claude", "projects", dir, `${sessionId}.jsonl`);
|
|
1378
|
+
}
|
|
1379
|
+
function claudeSessionExists(sessionId, cwd) {
|
|
1380
|
+
return existsSync5(claudeTranscriptPath(sessionId, cwd));
|
|
1381
|
+
}
|
|
1373
1382
|
function getLatestAssistantTurn(filePath) {
|
|
1374
1383
|
if (!existsSync5(filePath))
|
|
1375
1384
|
return null;
|
|
@@ -1712,7 +1721,7 @@ class NoopAdapter {
|
|
|
1712
1721
|
|
|
1713
1722
|
// src/terminal/index.ts
|
|
1714
1723
|
import { readFileSync as readFileSync5 } from "fs";
|
|
1715
|
-
import { join as
|
|
1724
|
+
import { join as join7 } from "path";
|
|
1716
1725
|
function getTerminalAdapter() {
|
|
1717
1726
|
if (cachedAdapter)
|
|
1718
1727
|
return cachedAdapter;
|
|
@@ -1731,7 +1740,7 @@ function getTerminalAdapter() {
|
|
|
1731
1740
|
}
|
|
1732
1741
|
function readConfigTerminal() {
|
|
1733
1742
|
try {
|
|
1734
|
-
const config = JSON.parse(readFileSync5(
|
|
1743
|
+
const config = JSON.parse(readFileSync5(join7(paths.root, "config.json"), "utf-8"));
|
|
1735
1744
|
return config.terminal ?? null;
|
|
1736
1745
|
} catch {
|
|
1737
1746
|
return null;
|
|
@@ -2091,7 +2100,7 @@ var init_session_archive = __esm(() => {
|
|
|
2091
2100
|
// src/server/index.ts
|
|
2092
2101
|
import { execFile } from "child_process";
|
|
2093
2102
|
import { existsSync as existsSync6 } from "fs";
|
|
2094
|
-
import { join as
|
|
2103
|
+
import { join as join8 } from "path";
|
|
2095
2104
|
function liveStats(sessionId) {
|
|
2096
2105
|
return {
|
|
2097
2106
|
sessionId,
|
|
@@ -2164,11 +2173,11 @@ function match(pathname, url) {
|
|
|
2164
2173
|
}
|
|
2165
2174
|
function findDashboardDir() {
|
|
2166
2175
|
const candidates = [
|
|
2167
|
-
|
|
2168
|
-
|
|
2176
|
+
join8(import.meta.dir, "dashboard"),
|
|
2177
|
+
join8(import.meta.dir, "..", "dashboard")
|
|
2169
2178
|
];
|
|
2170
2179
|
for (const dir of candidates) {
|
|
2171
|
-
if (existsSync6(
|
|
2180
|
+
if (existsSync6(join8(dir, "index.html")))
|
|
2172
2181
|
return dir;
|
|
2173
2182
|
}
|
|
2174
2183
|
return null;
|
|
@@ -2177,13 +2186,13 @@ async function serveDashboard(pathname) {
|
|
|
2177
2186
|
if (!DASHBOARD_DIR)
|
|
2178
2187
|
return null;
|
|
2179
2188
|
const requested = pathname === "/" ? "/index.html" : pathname;
|
|
2180
|
-
const filePath =
|
|
2189
|
+
const filePath = join8(DASHBOARD_DIR, requested);
|
|
2181
2190
|
if (!filePath.startsWith(DASHBOARD_DIR))
|
|
2182
2191
|
return null;
|
|
2183
2192
|
const file = Bun.file(filePath);
|
|
2184
2193
|
if (await file.exists())
|
|
2185
2194
|
return new Response(file);
|
|
2186
|
-
return new Response(Bun.file(
|
|
2195
|
+
return new Response(Bun.file(join8(DASHBOARD_DIR, "index.html")));
|
|
2187
2196
|
}
|
|
2188
2197
|
function startServer(port = PORT) {
|
|
2189
2198
|
const server = Bun.serve({
|
|
@@ -3342,7 +3351,7 @@ var init_spawn_context = __esm(() => {
|
|
|
3342
3351
|
// src/lib/server-lifecycle.ts
|
|
3343
3352
|
import { spawn as spawn3 } from "child_process";
|
|
3344
3353
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2 } from "fs";
|
|
3345
|
-
import { join as
|
|
3354
|
+
import { join as join9 } from "path";
|
|
3346
3355
|
function readPidFile() {
|
|
3347
3356
|
try {
|
|
3348
3357
|
const pid = Number(readFileSync7(deps.pidFile, "utf-8").trim());
|
|
@@ -3410,11 +3419,11 @@ var init_server_lifecycle = __esm(() => {
|
|
|
3410
3419
|
init_paths();
|
|
3411
3420
|
init_sessions();
|
|
3412
3421
|
defaultDeps = {
|
|
3413
|
-
pidFile:
|
|
3422
|
+
pidFile: join9(paths.root, "server.pid"),
|
|
3414
3423
|
port: Number(process.env.BERTRAND_PORT ?? 5200),
|
|
3415
3424
|
resolveBin() {
|
|
3416
3425
|
try {
|
|
3417
|
-
const config = JSON.parse(readFileSync7(
|
|
3426
|
+
const config = JSON.parse(readFileSync7(join9(paths.root, "config.json"), "utf-8"));
|
|
3418
3427
|
return typeof config?.bin === "string" ? config.bin : null;
|
|
3419
3428
|
} catch {
|
|
3420
3429
|
return null;
|
|
@@ -3524,6 +3533,7 @@ async function resume(opts) {
|
|
|
3524
3533
|
throw new Error(`Session not found: ${opts.sessionId}`);
|
|
3525
3534
|
const category = getCategory(session.categoryId);
|
|
3526
3535
|
const sessionName = category ? `${category.path}/${session.slug}` : session.name;
|
|
3536
|
+
const isFreshClaudeSession = !claudeSessionExists(opts.conversationId);
|
|
3527
3537
|
updateSession(session.id, { status: "active", pid: process.pid });
|
|
3528
3538
|
liveSession = { sessionId: session.id, claudeId: opts.conversationId };
|
|
3529
3539
|
installExitHandlers();
|
|
@@ -3532,6 +3542,17 @@ async function resume(opts) {
|
|
|
3532
3542
|
sessionId: session.id,
|
|
3533
3543
|
conversationId: opts.conversationId
|
|
3534
3544
|
});
|
|
3545
|
+
if (isFreshClaudeSession) {
|
|
3546
|
+
const spawnContext = await captureSpawnContext();
|
|
3547
|
+
emitClaudeStarted({
|
|
3548
|
+
sessionId: session.id,
|
|
3549
|
+
conversationId: opts.conversationId,
|
|
3550
|
+
model: spawnContext.model,
|
|
3551
|
+
claudeVersion: spawnContext.claudeVersion,
|
|
3552
|
+
git: spawnContext.git,
|
|
3553
|
+
cwd: spawnContext.cwd
|
|
3554
|
+
});
|
|
3555
|
+
}
|
|
3535
3556
|
const categoryPath = category?.path ?? "";
|
|
3536
3557
|
const siblingContext = buildSiblingContext(session.categoryId, categoryPath, session.id);
|
|
3537
3558
|
const contract = buildContract(sessionName, siblingContext);
|
|
@@ -3541,7 +3562,7 @@ async function resume(opts) {
|
|
|
3541
3562
|
sessionName,
|
|
3542
3563
|
sessionSlug: session.slug,
|
|
3543
3564
|
contract,
|
|
3544
|
-
resume:
|
|
3565
|
+
resume: !isFreshClaudeSession
|
|
3545
3566
|
});
|
|
3546
3567
|
finalizeSession(session.id, opts.conversationId, exitCode);
|
|
3547
3568
|
return session.id;
|
|
@@ -3585,16 +3606,17 @@ var init_session = __esm(() => {
|
|
|
3585
3606
|
init_timing();
|
|
3586
3607
|
init_server_lifecycle();
|
|
3587
3608
|
init_trigger();
|
|
3609
|
+
init_transcript();
|
|
3588
3610
|
});
|
|
3589
3611
|
|
|
3590
3612
|
// src/tui/app.tsx
|
|
3591
3613
|
import { spawn as spawn4 } from "child_process";
|
|
3592
3614
|
import { existsSync as existsSync8, readFileSync as readFileSync8, unlinkSync as unlinkSync3 } from "fs";
|
|
3593
3615
|
import { tmpdir } from "os";
|
|
3594
|
-
import { join as
|
|
3616
|
+
import { join as join10 } from "path";
|
|
3595
3617
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3596
3618
|
async function runScreen(screen, ...args) {
|
|
3597
|
-
const tmpFile =
|
|
3619
|
+
const tmpFile = join10(tmpdir(), `bertrand-tui-${randomUUID2()}.json`);
|
|
3598
3620
|
if (process.env.BERTRAND_DEBUG_TUI) {
|
|
3599
3621
|
try {
|
|
3600
3622
|
const { appendFileSync } = await import("fs");
|
|
@@ -3751,8 +3773,8 @@ var init_app = __esm(() => {
|
|
|
3751
3773
|
init_create();
|
|
3752
3774
|
init_resolve();
|
|
3753
3775
|
SCREEN_ENTRY = (() => {
|
|
3754
|
-
const built =
|
|
3755
|
-
return existsSync8(built) ? built :
|
|
3776
|
+
const built = join10(import.meta.dir, "run-screen.js");
|
|
3777
|
+
return existsSync8(built) ? built : join10(import.meta.dir, "run-screen.tsx");
|
|
3756
3778
|
})();
|
|
3757
3779
|
});
|
|
3758
3780
|
|
|
@@ -4144,12 +4166,12 @@ var init_scripts = __esm(() => {
|
|
|
4144
4166
|
|
|
4145
4167
|
// src/hooks/install.ts
|
|
4146
4168
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync5, chmodSync as chmodSync2 } from "fs";
|
|
4147
|
-
import { join as
|
|
4169
|
+
import { join as join11 } from "path";
|
|
4148
4170
|
function installHookScripts(bin) {
|
|
4149
4171
|
mkdirSync7(paths.hooks, { recursive: true });
|
|
4150
4172
|
mkdirSync7(paths.runtime, { recursive: true });
|
|
4151
4173
|
for (const [filename, scriptFn] of Object.entries(HOOK_SCRIPTS)) {
|
|
4152
|
-
const filePath =
|
|
4174
|
+
const filePath = join11(paths.hooks, filename);
|
|
4153
4175
|
writeFileSync5(filePath, scriptFn(bin, paths.runtime));
|
|
4154
4176
|
chmodSync2(filePath, 493);
|
|
4155
4177
|
}
|
|
@@ -4162,8 +4184,8 @@ var init_install = __esm(() => {
|
|
|
4162
4184
|
|
|
4163
4185
|
// src/hooks/settings.ts
|
|
4164
4186
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync8 } from "fs";
|
|
4165
|
-
import { join as
|
|
4166
|
-
import { homedir as
|
|
4187
|
+
import { join as join12, dirname as dirname4 } from "path";
|
|
4188
|
+
import { homedir as homedir3 } from "os";
|
|
4167
4189
|
function isBertrandGroup(group) {
|
|
4168
4190
|
return group.hooks?.some((h) => h.command?.includes(".bertrand/hooks/")) ?? false;
|
|
4169
4191
|
}
|
|
@@ -4187,7 +4209,7 @@ function installHookSettings() {
|
|
|
4187
4209
|
var SETTINGS_PATH, BERTRAND_HOOKS;
|
|
4188
4210
|
var init_settings = __esm(() => {
|
|
4189
4211
|
init_paths();
|
|
4190
|
-
SETTINGS_PATH =
|
|
4212
|
+
SETTINGS_PATH = join12(homedir3(), ".claude", "settings.json");
|
|
4191
4213
|
BERTRAND_HOOKS = {
|
|
4192
4214
|
PreToolUse: [
|
|
4193
4215
|
{
|
|
@@ -4232,7 +4254,7 @@ var init_settings = __esm(() => {
|
|
|
4232
4254
|
|
|
4233
4255
|
// src/lib/completions.ts
|
|
4234
4256
|
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync9 } from "fs";
|
|
4235
|
-
import { join as
|
|
4257
|
+
import { join as join13 } from "path";
|
|
4236
4258
|
function bashCompletion() {
|
|
4237
4259
|
return `# bertrand bash completion
|
|
4238
4260
|
_bertrand() {
|
|
@@ -4262,11 +4284,11 @@ function fishCompletion() {
|
|
|
4262
4284
|
`;
|
|
4263
4285
|
}
|
|
4264
4286
|
function generateCompletions() {
|
|
4265
|
-
const dir =
|
|
4287
|
+
const dir = join13(paths.root, "completions");
|
|
4266
4288
|
mkdirSync9(dir, { recursive: true });
|
|
4267
|
-
writeFileSync7(
|
|
4268
|
-
writeFileSync7(
|
|
4269
|
-
writeFileSync7(
|
|
4289
|
+
writeFileSync7(join13(dir, "bertrand.bash"), bashCompletion());
|
|
4290
|
+
writeFileSync7(join13(dir, "_bertrand"), zshCompletion());
|
|
4291
|
+
writeFileSync7(join13(dir, "bertrand.fish"), fishCompletion());
|
|
4270
4292
|
console.log(`Shell completions written to ${dir}`);
|
|
4271
4293
|
console.log(" Add to your shell config:");
|
|
4272
4294
|
console.log(` bash: source ${dir}/bertrand.bash`);
|
|
@@ -4297,7 +4319,7 @@ var init_completions = __esm(() => {
|
|
|
4297
4319
|
var exports_init = {};
|
|
4298
4320
|
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, chmodSync as chmodSync3 } from "fs";
|
|
4299
4321
|
import { execSync as execSync2 } from "child_process";
|
|
4300
|
-
import { join as
|
|
4322
|
+
import { join as join14 } from "path";
|
|
4301
4323
|
function detectTerminal() {
|
|
4302
4324
|
try {
|
|
4303
4325
|
execSync2("which wsh", { stdio: "ignore" });
|
|
@@ -4312,8 +4334,8 @@ function resolveBin() {
|
|
|
4312
4334
|
return onPath;
|
|
4313
4335
|
const entry = process.argv[1];
|
|
4314
4336
|
if (entry && SOURCE_ENTRY.test(entry)) {
|
|
4315
|
-
const launcherDir =
|
|
4316
|
-
const launcher =
|
|
4337
|
+
const launcherDir = join14(paths.root, "bin");
|
|
4338
|
+
const launcher = join14(launcherDir, "bertrand-dev");
|
|
4317
4339
|
mkdirSync10(launcherDir, { recursive: true });
|
|
4318
4340
|
writeFileSync8(launcher, `#!/usr/bin/env bash
|
|
4319
4341
|
exec ${process.execPath} ${JSON.stringify(entry)} "$@"
|