bashbros 0.1.2 → 0.1.3
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/{chunk-XCZMQRSX.js → chunk-2RPTM6EQ.js} +91 -3
- package/dist/chunk-2RPTM6EQ.js.map +1 -0
- package/dist/{chunk-BW6XCOJH.js → chunk-A535VV7N.js} +3 -4
- package/dist/chunk-A535VV7N.js.map +1 -0
- package/dist/chunk-EYO44OMN.js +181 -0
- package/dist/chunk-EYO44OMN.js.map +1 -0
- package/dist/{chunk-YUMNBQAY.js → chunk-JYWQT2B4.js} +102 -2
- package/dist/chunk-JYWQT2B4.js.map +1 -0
- package/dist/{chunk-SQCP6IYB.js → chunk-WPJJZLT6.js} +2 -2
- package/dist/cli.js +127 -177
- package/dist/cli.js.map +1 -1
- package/dist/{config-JLLOTFLI.js → config-43SK6SFI.js} +2 -2
- package/dist/{db-OBKEXRTP.js → db-SWJUUSFX.js} +2 -2
- package/dist/{display-6LZ2HBCU.js → display-HFIFXOOL.js} +3 -3
- package/dist/index.d.ts +19 -0
- package/dist/index.js +2 -2
- package/dist/writer-4ZEAKUFD.js +12 -0
- package/dist/writer-4ZEAKUFD.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-BW6XCOJH.js.map +0 -1
- package/dist/chunk-XCZMQRSX.js.map +0 -1
- package/dist/chunk-YUMNBQAY.js.map +0 -1
- /package/dist/{chunk-SQCP6IYB.js.map → chunk-WPJJZLT6.js.map} +0 -0
- /package/dist/{config-JLLOTFLI.js.map → config-43SK6SFI.js.map} +0 -0
- /package/dist/{db-OBKEXRTP.js.map → db-SWJUUSFX.js.map} +0 -0
- /package/dist/{display-6LZ2HBCU.js.map → display-HFIFXOOL.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DashboardWriter
|
|
4
|
+
} from "./chunk-EYO44OMN.js";
|
|
2
5
|
import {
|
|
3
6
|
DashboardDB
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JYWQT2B4.js";
|
|
5
8
|
import {
|
|
6
9
|
formatAllAgentsInfo,
|
|
7
10
|
formatPermissionsTable
|
|
8
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-WPJJZLT6.js";
|
|
9
12
|
import {
|
|
10
13
|
BashBro,
|
|
11
14
|
BashBros,
|
|
@@ -17,14 +20,14 @@ import {
|
|
|
17
20
|
UndoStack,
|
|
18
21
|
gateCommand,
|
|
19
22
|
getBashgymIntegration
|
|
20
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-2RPTM6EQ.js";
|
|
21
24
|
import "./chunk-SG752FZC.js";
|
|
22
25
|
import "./chunk-DLP2O6PN.js";
|
|
23
26
|
import {
|
|
24
27
|
findConfig,
|
|
25
28
|
getDefaultConfig,
|
|
26
29
|
loadConfig
|
|
27
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-A535VV7N.js";
|
|
28
31
|
import "./chunk-QWZGB4V3.js";
|
|
29
32
|
import {
|
|
30
33
|
allowForSession
|
|
@@ -1015,7 +1018,7 @@ var EgressPatternMatcher = class {
|
|
|
1015
1018
|
// src/policy/ward/egress.ts
|
|
1016
1019
|
var DashboardDB2 = null;
|
|
1017
1020
|
try {
|
|
1018
|
-
const dbModule = await import("./db-
|
|
1021
|
+
const dbModule = await import("./db-SWJUUSFX.js");
|
|
1019
1022
|
DashboardDB2 = dbModule.DashboardDB;
|
|
1020
1023
|
} catch {
|
|
1021
1024
|
}
|
|
@@ -1425,162 +1428,6 @@ ${passed} passed, ${failed} failed. Fix issues above.
|
|
|
1425
1428
|
import chalk3 from "chalk";
|
|
1426
1429
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
1427
1430
|
import { parse, stringify as stringify2 } from "yaml";
|
|
1428
|
-
|
|
1429
|
-
// src/dashboard/writer.ts
|
|
1430
|
-
import { homedir as homedir4 } from "os";
|
|
1431
|
-
import { join as join4 } from "path";
|
|
1432
|
-
import { mkdirSync as mkdirSync2, existsSync as existsSync5 } from "fs";
|
|
1433
|
-
function getDefaultDbPath() {
|
|
1434
|
-
const bashbrosDir = join4(homedir4(), ".bashbros");
|
|
1435
|
-
if (!existsSync5(bashbrosDir)) {
|
|
1436
|
-
mkdirSync2(bashbrosDir, { recursive: true });
|
|
1437
|
-
}
|
|
1438
|
-
return join4(bashbrosDir, "dashboard.db");
|
|
1439
|
-
}
|
|
1440
|
-
var DashboardWriter = class {
|
|
1441
|
-
db;
|
|
1442
|
-
sessionId = null;
|
|
1443
|
-
commandCount = 0;
|
|
1444
|
-
blockedCount = 0;
|
|
1445
|
-
totalRiskScore = 0;
|
|
1446
|
-
constructor(dbPath) {
|
|
1447
|
-
const path = dbPath ?? getDefaultDbPath();
|
|
1448
|
-
this.db = new DashboardDB(path);
|
|
1449
|
-
}
|
|
1450
|
-
/**
|
|
1451
|
-
* Start a new watch session
|
|
1452
|
-
*/
|
|
1453
|
-
startSession(agent, workingDir) {
|
|
1454
|
-
this.sessionId = this.db.insertSession({
|
|
1455
|
-
agent,
|
|
1456
|
-
pid: process.pid,
|
|
1457
|
-
workingDir
|
|
1458
|
-
});
|
|
1459
|
-
this.commandCount = 0;
|
|
1460
|
-
this.blockedCount = 0;
|
|
1461
|
-
this.totalRiskScore = 0;
|
|
1462
|
-
return this.sessionId;
|
|
1463
|
-
}
|
|
1464
|
-
/**
|
|
1465
|
-
* End the current session
|
|
1466
|
-
*/
|
|
1467
|
-
endSession() {
|
|
1468
|
-
if (!this.sessionId) return;
|
|
1469
|
-
const avgRiskScore = this.commandCount > 0 ? this.totalRiskScore / this.commandCount : 0;
|
|
1470
|
-
this.db.updateSession(this.sessionId, {
|
|
1471
|
-
endTime: /* @__PURE__ */ new Date(),
|
|
1472
|
-
status: "completed",
|
|
1473
|
-
commandCount: this.commandCount,
|
|
1474
|
-
blockedCount: this.blockedCount,
|
|
1475
|
-
avgRiskScore
|
|
1476
|
-
});
|
|
1477
|
-
this.sessionId = null;
|
|
1478
|
-
}
|
|
1479
|
-
/**
|
|
1480
|
-
* Mark session as crashed (for unexpected exits)
|
|
1481
|
-
*/
|
|
1482
|
-
crashSession() {
|
|
1483
|
-
if (!this.sessionId) return;
|
|
1484
|
-
const avgRiskScore = this.commandCount > 0 ? this.totalRiskScore / this.commandCount : 0;
|
|
1485
|
-
this.db.updateSession(this.sessionId, {
|
|
1486
|
-
endTime: /* @__PURE__ */ new Date(),
|
|
1487
|
-
status: "crashed",
|
|
1488
|
-
commandCount: this.commandCount,
|
|
1489
|
-
blockedCount: this.blockedCount,
|
|
1490
|
-
avgRiskScore
|
|
1491
|
-
});
|
|
1492
|
-
this.sessionId = null;
|
|
1493
|
-
}
|
|
1494
|
-
/**
|
|
1495
|
-
* Record a command execution
|
|
1496
|
-
*/
|
|
1497
|
-
recordCommand(command, allowed, riskScore, violations, durationMs) {
|
|
1498
|
-
if (!this.sessionId) return null;
|
|
1499
|
-
const input = {
|
|
1500
|
-
sessionId: this.sessionId,
|
|
1501
|
-
command,
|
|
1502
|
-
allowed,
|
|
1503
|
-
riskScore: riskScore.score,
|
|
1504
|
-
riskLevel: riskScore.level,
|
|
1505
|
-
riskFactors: riskScore.factors,
|
|
1506
|
-
durationMs,
|
|
1507
|
-
violations: violations.map((v) => v.message)
|
|
1508
|
-
};
|
|
1509
|
-
const id = this.db.insertCommand(input);
|
|
1510
|
-
this.commandCount++;
|
|
1511
|
-
this.totalRiskScore += riskScore.score;
|
|
1512
|
-
if (!allowed) {
|
|
1513
|
-
this.blockedCount++;
|
|
1514
|
-
}
|
|
1515
|
-
if (this.commandCount % 10 === 0) {
|
|
1516
|
-
const avgRiskScore = this.totalRiskScore / this.commandCount;
|
|
1517
|
-
this.db.updateSession(this.sessionId, {
|
|
1518
|
-
commandCount: this.commandCount,
|
|
1519
|
-
blockedCount: this.blockedCount,
|
|
1520
|
-
avgRiskScore
|
|
1521
|
-
});
|
|
1522
|
-
}
|
|
1523
|
-
return id;
|
|
1524
|
-
}
|
|
1525
|
-
/**
|
|
1526
|
-
* Record a Bash Bro AI event
|
|
1527
|
-
*/
|
|
1528
|
-
recordBroEvent(input) {
|
|
1529
|
-
const dbInput = {
|
|
1530
|
-
sessionId: this.sessionId ?? void 0,
|
|
1531
|
-
eventType: input.eventType,
|
|
1532
|
-
inputContext: input.inputContext,
|
|
1533
|
-
outputSummary: input.outputSummary,
|
|
1534
|
-
modelUsed: input.modelUsed,
|
|
1535
|
-
latencyMs: input.latencyMs,
|
|
1536
|
-
success: input.success
|
|
1537
|
-
};
|
|
1538
|
-
return this.db.insertBroEvent(dbInput);
|
|
1539
|
-
}
|
|
1540
|
-
/**
|
|
1541
|
-
* Update Bash Bro status
|
|
1542
|
-
*/
|
|
1543
|
-
updateBroStatus(status) {
|
|
1544
|
-
const dbInput = {
|
|
1545
|
-
ollamaAvailable: status.ollamaAvailable,
|
|
1546
|
-
ollamaModel: status.ollamaModel,
|
|
1547
|
-
platform: status.platform,
|
|
1548
|
-
shell: status.shell,
|
|
1549
|
-
projectType: status.projectType
|
|
1550
|
-
};
|
|
1551
|
-
return this.db.updateBroStatus(dbInput);
|
|
1552
|
-
}
|
|
1553
|
-
/**
|
|
1554
|
-
* Get current session ID
|
|
1555
|
-
*/
|
|
1556
|
-
getSessionId() {
|
|
1557
|
-
return this.sessionId;
|
|
1558
|
-
}
|
|
1559
|
-
/**
|
|
1560
|
-
* Get current session stats
|
|
1561
|
-
*/
|
|
1562
|
-
getSessionStats() {
|
|
1563
|
-
return {
|
|
1564
|
-
commandCount: this.commandCount,
|
|
1565
|
-
blockedCount: this.blockedCount,
|
|
1566
|
-
avgRiskScore: this.commandCount > 0 ? this.totalRiskScore / this.commandCount : 0
|
|
1567
|
-
};
|
|
1568
|
-
}
|
|
1569
|
-
/**
|
|
1570
|
-
* Close database connection
|
|
1571
|
-
*/
|
|
1572
|
-
close() {
|
|
1573
|
-
this.db.close();
|
|
1574
|
-
}
|
|
1575
|
-
/**
|
|
1576
|
-
* Get the underlying database instance (for advanced use)
|
|
1577
|
-
*/
|
|
1578
|
-
getDB() {
|
|
1579
|
-
return this.db;
|
|
1580
|
-
}
|
|
1581
|
-
};
|
|
1582
|
-
|
|
1583
|
-
// src/watch.ts
|
|
1584
1431
|
var dashboardWriter = null;
|
|
1585
1432
|
var riskScorer = null;
|
|
1586
1433
|
function cleanup() {
|
|
@@ -1865,16 +1712,16 @@ import express from "express";
|
|
|
1865
1712
|
import { WebSocketServer } from "ws";
|
|
1866
1713
|
import { createServer } from "http";
|
|
1867
1714
|
import { fileURLToPath } from "url";
|
|
1868
|
-
import { dirname, join as
|
|
1869
|
-
import { homedir as
|
|
1870
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as
|
|
1715
|
+
import { dirname, join as join4 } from "path";
|
|
1716
|
+
import { homedir as homedir4 } from "os";
|
|
1717
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
1871
1718
|
import { parse as parse3, stringify as stringify4 } from "yaml";
|
|
1872
|
-
function
|
|
1873
|
-
const bashbrosDir =
|
|
1874
|
-
if (!
|
|
1875
|
-
|
|
1719
|
+
function getDefaultDbPath() {
|
|
1720
|
+
const bashbrosDir = join4(homedir4(), ".bashbros");
|
|
1721
|
+
if (!existsSync5(bashbrosDir)) {
|
|
1722
|
+
mkdirSync2(bashbrosDir, { recursive: true });
|
|
1876
1723
|
}
|
|
1877
|
-
return
|
|
1724
|
+
return join4(bashbrosDir, "dashboard.db");
|
|
1878
1725
|
}
|
|
1879
1726
|
var DashboardServer = class {
|
|
1880
1727
|
app;
|
|
@@ -1887,7 +1734,7 @@ var DashboardServer = class {
|
|
|
1887
1734
|
constructor(config = {}) {
|
|
1888
1735
|
this.port = config.port ?? 17800;
|
|
1889
1736
|
this.bind = config.bind ?? "127.0.0.1";
|
|
1890
|
-
this.db = new DashboardDB(config.dbPath ??
|
|
1737
|
+
this.db = new DashboardDB(config.dbPath ?? getDefaultDbPath());
|
|
1891
1738
|
this.app = express();
|
|
1892
1739
|
this.setupMiddleware();
|
|
1893
1740
|
this.setupRoutes();
|
|
@@ -2072,6 +1919,36 @@ var DashboardServer = class {
|
|
|
2072
1919
|
res.status(500).json({ error: "Failed to fetch commands" });
|
|
2073
1920
|
}
|
|
2074
1921
|
});
|
|
1922
|
+
this.app.get("/api/tools/live", (req, res) => {
|
|
1923
|
+
try {
|
|
1924
|
+
const limit = req.query.limit ? parseInt(req.query.limit, 10) : 50;
|
|
1925
|
+
const tools = this.db.getLiveToolUses(limit);
|
|
1926
|
+
res.json(tools);
|
|
1927
|
+
} catch (error) {
|
|
1928
|
+
res.status(500).json({ error: "Failed to fetch live tool uses" });
|
|
1929
|
+
}
|
|
1930
|
+
});
|
|
1931
|
+
this.app.get("/api/tools", (req, res) => {
|
|
1932
|
+
try {
|
|
1933
|
+
const filter = {};
|
|
1934
|
+
if (req.query.toolName) filter.toolName = req.query.toolName;
|
|
1935
|
+
if (req.query.since) filter.since = new Date(req.query.since);
|
|
1936
|
+
if (req.query.limit) filter.limit = parseInt(req.query.limit, 10);
|
|
1937
|
+
if (req.query.offset) filter.offset = parseInt(req.query.offset, 10);
|
|
1938
|
+
const tools = this.db.getToolUses(filter);
|
|
1939
|
+
res.json(tools);
|
|
1940
|
+
} catch (error) {
|
|
1941
|
+
res.status(500).json({ error: "Failed to fetch tool uses" });
|
|
1942
|
+
}
|
|
1943
|
+
});
|
|
1944
|
+
this.app.get("/api/tools/stats", (_req, res) => {
|
|
1945
|
+
try {
|
|
1946
|
+
const stats = this.db.getToolUseStats();
|
|
1947
|
+
res.json(stats);
|
|
1948
|
+
} catch (error) {
|
|
1949
|
+
res.status(500).json({ error: "Failed to fetch tool use stats" });
|
|
1950
|
+
}
|
|
1951
|
+
});
|
|
2075
1952
|
this.app.get("/api/bro/status", (_req, res) => {
|
|
2076
1953
|
try {
|
|
2077
1954
|
const status = this.db.getLatestBroStatus();
|
|
@@ -2116,7 +1993,7 @@ var DashboardServer = class {
|
|
|
2116
1993
|
res.status(400).json({ error: "Model name required" });
|
|
2117
1994
|
return;
|
|
2118
1995
|
}
|
|
2119
|
-
const controlPath =
|
|
1996
|
+
const controlPath = join4(homedir4(), ".bashbros", "model-control.json");
|
|
2120
1997
|
writeFileSync4(controlPath, JSON.stringify({
|
|
2121
1998
|
model,
|
|
2122
1999
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2128,7 +2005,7 @@ var DashboardServer = class {
|
|
|
2128
2005
|
});
|
|
2129
2006
|
this.app.post("/api/bro/scan", (_req, res) => {
|
|
2130
2007
|
try {
|
|
2131
|
-
const controlPath =
|
|
2008
|
+
const controlPath = join4(homedir4(), ".bashbros", "scan-control.json");
|
|
2132
2009
|
writeFileSync4(controlPath, JSON.stringify({
|
|
2133
2010
|
action: "scan",
|
|
2134
2011
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2178,10 +2055,10 @@ var DashboardServer = class {
|
|
|
2178
2055
|
});
|
|
2179
2056
|
const __filename = fileURLToPath(import.meta.url);
|
|
2180
2057
|
const __dirname = dirname(__filename);
|
|
2181
|
-
const staticPath =
|
|
2058
|
+
const staticPath = join4(__dirname, "static");
|
|
2182
2059
|
this.app.use(express.static(staticPath));
|
|
2183
2060
|
this.app.get("/{*path}", (_req, res) => {
|
|
2184
|
-
res.sendFile(
|
|
2061
|
+
res.sendFile(join4(staticPath, "index.html"));
|
|
2185
2062
|
});
|
|
2186
2063
|
}
|
|
2187
2064
|
setupWebSocket() {
|
|
@@ -2312,7 +2189,7 @@ program.command("scan").description("Scan your system and project environment").
|
|
|
2312
2189
|
console.log(bro.getSystemContext());
|
|
2313
2190
|
console.log();
|
|
2314
2191
|
console.log(chalk5.bold("\n## Agent Configurations\n"));
|
|
2315
|
-
const { formatAgentSummary } = await import("./display-
|
|
2192
|
+
const { formatAgentSummary } = await import("./display-HFIFXOOL.js");
|
|
2316
2193
|
const agents = await getAllAgentConfigs();
|
|
2317
2194
|
console.log(formatAgentSummary(agents));
|
|
2318
2195
|
console.log();
|
|
@@ -2559,11 +2436,30 @@ hookCmd.command("status").description("Check Claude Code hook status").action(()
|
|
|
2559
2436
|
console.log();
|
|
2560
2437
|
console.log(` Claude Code: ${status.claudeInstalled ? chalk5.green("installed") : chalk5.yellow("not found")}`);
|
|
2561
2438
|
console.log(` BashBros hooks: ${status.hooksInstalled ? chalk5.green("active") : chalk5.dim("not installed")}`);
|
|
2439
|
+
console.log(` All-tools recording: ${status.allToolsInstalled ? chalk5.green("active") : chalk5.dim("not installed")}`);
|
|
2562
2440
|
if (status.hooks.length > 0) {
|
|
2563
2441
|
console.log(` Active hooks: ${status.hooks.join(", ")}`);
|
|
2564
2442
|
}
|
|
2565
2443
|
console.log();
|
|
2566
2444
|
});
|
|
2445
|
+
hookCmd.command("install-all-tools").description("Install hook to record ALL Claude Code tool uses (not just Bash)").action(() => {
|
|
2446
|
+
const result = ClaudeCodeHooks.installAllTools();
|
|
2447
|
+
if (result.success) {
|
|
2448
|
+
console.log(chalk5.green("\u2713"), result.message);
|
|
2449
|
+
} else {
|
|
2450
|
+
console.log(chalk5.red("\u2717"), result.message);
|
|
2451
|
+
process.exit(1);
|
|
2452
|
+
}
|
|
2453
|
+
});
|
|
2454
|
+
hookCmd.command("uninstall-all-tools").description("Remove all-tools recording hook").action(() => {
|
|
2455
|
+
const result = ClaudeCodeHooks.uninstallAllTools();
|
|
2456
|
+
if (result.success) {
|
|
2457
|
+
console.log(chalk5.green("\u2713"), result.message);
|
|
2458
|
+
} else {
|
|
2459
|
+
console.log(chalk5.red("\u2717"), result.message);
|
|
2460
|
+
process.exit(1);
|
|
2461
|
+
}
|
|
2462
|
+
});
|
|
2567
2463
|
var moltbotCmd = program.command("moltbot").alias("clawdbot").description("Manage Moltbot/Clawdbot integration");
|
|
2568
2464
|
moltbotCmd.command("install").description("Install BashBros hooks into Moltbot").action(() => {
|
|
2569
2465
|
const result = MoltbotHooks.install();
|
|
@@ -2671,7 +2567,7 @@ program.command("agent-info [agent]").description("Show detailed info about inst
|
|
|
2671
2567
|
return;
|
|
2672
2568
|
}
|
|
2673
2569
|
const info = await getAgentConfigInfo(agent);
|
|
2674
|
-
const { formatAgentInfo: formatAgentInfo2 } = await import("./display-
|
|
2570
|
+
const { formatAgentInfo: formatAgentInfo2 } = await import("./display-HFIFXOOL.js");
|
|
2675
2571
|
console.log();
|
|
2676
2572
|
console.log(formatAgentInfo2(info));
|
|
2677
2573
|
if (options.raw && info.configExists && info.configPath) {
|
|
@@ -2710,7 +2606,7 @@ program.command("gate <command>").description("Check if a command should be allo
|
|
|
2710
2606
|
const { allowForSession: allowForSession2 } = await import("./session-Y4MICATZ.js");
|
|
2711
2607
|
const { readFileSync: readFileSync5, writeFileSync: writeFileSync5 } = await import("fs");
|
|
2712
2608
|
const { parse: parse4, stringify: stringify5 } = await import("yaml");
|
|
2713
|
-
const { findConfig: findConfig2 } = await import("./config-
|
|
2609
|
+
const { findConfig: findConfig2 } = await import("./config-43SK6SFI.js");
|
|
2714
2610
|
console.error();
|
|
2715
2611
|
console.error(chalk5.red("\u{1F6E1}\uFE0F BashBros blocked a command"));
|
|
2716
2612
|
console.error();
|
|
@@ -2778,6 +2674,60 @@ program.command("gate <command>").description("Check if a command should be allo
|
|
|
2778
2674
|
}
|
|
2779
2675
|
process.exit(0);
|
|
2780
2676
|
});
|
|
2677
|
+
program.command("record-tool").description("Record a Claude Code tool execution (used by hooks)").option("--marker <marker>", "Hook marker (ignored, used for identification)").action(async () => {
|
|
2678
|
+
const eventJson = process.env.CLAUDE_HOOK_EVENT || "";
|
|
2679
|
+
if (!eventJson) {
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2682
|
+
try {
|
|
2683
|
+
const event = JSON.parse(eventJson);
|
|
2684
|
+
const events = Array.isArray(event) ? event : [event];
|
|
2685
|
+
const { DashboardWriter: DashboardWriter2 } = await import("./writer-4ZEAKUFD.js");
|
|
2686
|
+
const writer = new DashboardWriter2();
|
|
2687
|
+
for (const evt of events) {
|
|
2688
|
+
const toolName = evt.tool_name || evt.tool || "unknown";
|
|
2689
|
+
const toolInput = evt.tool_input || evt.input || {};
|
|
2690
|
+
const toolOutput = evt.tool_output || evt.output || "";
|
|
2691
|
+
let inputStr;
|
|
2692
|
+
if (typeof toolInput === "string") {
|
|
2693
|
+
inputStr = toolInput;
|
|
2694
|
+
} else if (typeof toolInput === "object") {
|
|
2695
|
+
inputStr = JSON.stringify(toolInput, null, 2);
|
|
2696
|
+
} else {
|
|
2697
|
+
inputStr = String(toolInput);
|
|
2698
|
+
}
|
|
2699
|
+
let outputStr;
|
|
2700
|
+
let exitCode = null;
|
|
2701
|
+
let success = null;
|
|
2702
|
+
if (typeof toolOutput === "object" && toolOutput !== null) {
|
|
2703
|
+
outputStr = (toolOutput.stdout || "") + (toolOutput.stderr || "");
|
|
2704
|
+
exitCode = toolOutput.exit_code ?? toolOutput.exitCode ?? null;
|
|
2705
|
+
if (exitCode !== null) {
|
|
2706
|
+
success = exitCode === 0;
|
|
2707
|
+
}
|
|
2708
|
+
} else {
|
|
2709
|
+
outputStr = String(toolOutput || "");
|
|
2710
|
+
}
|
|
2711
|
+
const repoName = evt.repo?.name ?? null;
|
|
2712
|
+
const repoPath = evt.repo?.path ?? null;
|
|
2713
|
+
writer.recordToolUse({
|
|
2714
|
+
toolName,
|
|
2715
|
+
toolInput: inputStr,
|
|
2716
|
+
toolOutput: outputStr,
|
|
2717
|
+
exitCode,
|
|
2718
|
+
success,
|
|
2719
|
+
cwd: evt.cwd || process.cwd(),
|
|
2720
|
+
repoName,
|
|
2721
|
+
repoPath
|
|
2722
|
+
});
|
|
2723
|
+
const preview = inputStr.substring(0, 40).replace(/\n/g, " ");
|
|
2724
|
+
console.log(`[BashBros] ${toolName}: ${preview}${inputStr.length > 40 ? "..." : ""}`);
|
|
2725
|
+
}
|
|
2726
|
+
writer.close();
|
|
2727
|
+
} catch (e) {
|
|
2728
|
+
console.error(`[BashBros] Error recording tool: ${e instanceof Error ? e.message : e}`);
|
|
2729
|
+
}
|
|
2730
|
+
});
|
|
2781
2731
|
program.command("record <command>").description("Record a command execution (used by hooks)").option("-o, --output <output>", "Command output").option("-e, --exit-code <code>", "Exit code", "0").action(async (command, options) => {
|
|
2782
2732
|
if (!metricsCollector) metricsCollector = new MetricsCollector();
|
|
2783
2733
|
if (!costEstimator) costEstimator = new CostEstimator();
|