@statforge/claudestat 1.6.0 → 1.6.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/daemon.js CHANGED
@@ -248,7 +248,7 @@ function startDaemon() {
248
248
  process.on('SIGINT', () => { if (_server)
249
249
  shutdown(_server); process.exit(0); });
250
250
  console.log(`\n● claudestat daemon → http://localhost:${PORT}`);
251
- console.log(` Waiting for Claude Code events...\n`);
251
+ console.log(` Watching for events...\n`);
252
252
  console.log(` In another terminal: \x1b[36mclaudestat watch\x1b[0m\n`);
253
253
  // Weekly insight — se muestra una vez por semana al iniciar el daemon
254
254
  Promise.resolve().then(() => __importStar(require('./insights'))).then(({ getWeeklyInsightData, shouldShowInsight, markInsightShown, renderWeeklyInsight }) => {
package/dist/enricher.js CHANGED
@@ -159,6 +159,8 @@ async function processLatestForSession(sessionId, onUpdate, source) {
159
159
  ? [(0, adapter_1.getAdapter)(source)].filter(Boolean)
160
160
  : (0, adapter_1.getActiveAdapters)();
161
161
  for (const adapter of adapters) {
162
+ if ((0, adapter_1.isPollable)(adapter))
163
+ continue;
162
164
  for (const watchPath of adapter.getWatchPaths()) {
163
165
  const baseDir = watchPath.split('/**')[0];
164
166
  if (!baseDir)
package/dist/paths.d.ts CHANGED
@@ -72,6 +72,11 @@ export declare function homeSlugRegex(): RegExp;
72
72
  * Windows: C:\Users\db → C--Users-db
73
73
  */
74
74
  export declare function getHomeSlug(): string;
75
+ /**
76
+ * Returns the OpenCode SQLite database path.
77
+ * Can be overridden via OPENCODE_DB env var.
78
+ */
79
+ export declare function getOpencodeDb(): string;
75
80
  /**
76
81
  * Returns the appropriate command to find an executable in PATH.
77
82
  * Unix: which <name>
package/dist/paths.js CHANGED
@@ -26,6 +26,7 @@ exports.encodeClaudePath = encodeClaudePath;
26
26
  exports.decodeClaudePath = decodeClaudePath;
27
27
  exports.homeSlugRegex = homeSlugRegex;
28
28
  exports.getHomeSlug = getHomeSlug;
29
+ exports.getOpencodeDb = getOpencodeDb;
29
30
  exports.whichCmd = whichCmd;
30
31
  exports.whichAllCmd = whichAllCmd;
31
32
  exports.portCheckCmd = portCheckCmd;
@@ -145,6 +146,14 @@ function homeSlugRegex() {
145
146
  function getHomeSlug() {
146
147
  return encodeClaudePath(os_1.default.homedir());
147
148
  }
149
+ // ─── OpenCode data directory ───────────────────────────────────────────────────
150
+ /**
151
+ * Returns the OpenCode SQLite database path.
152
+ * Can be overridden via OPENCODE_DB env var.
153
+ */
154
+ function getOpencodeDb() {
155
+ return process.env.OPENCODE_DB ?? path_1.default.join(os_1.default.homedir(), '.local', 'share', 'opencode', 'opencode.db');
156
+ }
148
157
  // ─── Platform utilities ────────────────────────────────────────────────────────
149
158
  /**
150
159
  * Returns the appropriate command to find an executable in PATH.
@@ -141,7 +141,7 @@ exports.miscRouter.get('/api/active-sessions', (_req, res) => {
141
141
  const lastSeen = s.last_event_at ?? s.started_at;
142
142
  if (lastSeen < cutoff)
143
143
  continue;
144
- const src = s.source ?? 'claude-code';
144
+ const src = s.source ?? 'unknown';
145
145
  const existing = bySource.get(src);
146
146
  if (!existing || lastSeen > existing.last_seen_ms) {
147
147
  bySource.set(src, {
@@ -10,12 +10,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.opencodeReaderRouter = void 0;
13
- const os_1 = __importDefault(require("os"));
14
- const path_1 = __importDefault(require("path"));
15
13
  const fs_1 = __importDefault(require("fs"));
16
14
  const express_1 = require("express");
15
+ const paths_1 = require("../paths");
17
16
  exports.opencodeReaderRouter = (0, express_1.Router)();
18
- const OPENCODE_DB = path_1.default.join(os_1.default.homedir(), '.local', 'share', 'opencode', 'opencode.db');
19
17
  // OpenCode tool names → claudestat canonical names
20
18
  const TOOL_NAME_MAP = {
21
19
  glob: 'Glob', read: 'Read', write: 'Write', edit: 'Edit', bash: 'Bash',
@@ -27,10 +25,10 @@ function mapToolName(raw) {
27
25
  }
28
26
  function openDb() {
29
27
  const { DatabaseSync } = require('node:sqlite');
30
- return new DatabaseSync(OPENCODE_DB, { open: true });
28
+ return new DatabaseSync((0, paths_1.getOpencodeDb)(), { open: true });
31
29
  }
32
30
  exports.opencodeReaderRouter.get('/api/opencode/session/:id', (req, res) => {
33
- if (!fs_1.default.existsSync(OPENCODE_DB)) {
31
+ if (!fs_1.default.existsSync((0, paths_1.getOpencodeDb)())) {
34
32
  res.status(404).json({ error: 'OpenCode DB not found' });
35
33
  return;
36
34
  }
@@ -46,7 +46,7 @@ exports.streamRouter.get('/stream', (req, res) => {
46
46
  res.flushHeaders();
47
47
  const clientId = Math.random().toString(36).slice(2);
48
48
  sseClients.set(clientId, res);
49
- const latestSession = db_1.dbOps.getLatestClaudeSession();
49
+ const latestSession = db_1.dbOps.getLatestSession();
50
50
  if (latestSession) {
51
51
  const allEvents = db_1.dbOps.getSessionEvents(latestSession.id);
52
52
  const events = allEvents.length > SSE_INIT_EVENT_LIMIT
@@ -11,14 +11,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.opencodeAdapter = void 0;
14
- const path_1 = __importDefault(require("path"));
15
- const os_1 = __importDefault(require("os"));
16
14
  const fs_1 = __importDefault(require("fs"));
17
15
  const adapter_1 = require("./adapter");
18
- const OPENCODE_DB = path_1.default.join(os_1.default.homedir(), '.local', 'share', 'opencode', 'opencode.db');
16
+ const paths_1 = require("../paths");
19
17
  function openDb() {
20
18
  const { DatabaseSync } = require('node:sqlite');
21
- return new DatabaseSync(OPENCODE_DB, { open: true });
19
+ return new DatabaseSync((0, paths_1.getOpencodeDb)(), { open: true });
22
20
  }
23
21
  function parseModel(raw) {
24
22
  if (!raw)
@@ -37,7 +35,7 @@ exports.opencodeAdapter = {
37
35
  get shortName() { return 'OC'; },
38
36
  detect() {
39
37
  try {
40
- return fs_1.default.existsSync(OPENCODE_DB);
38
+ return fs_1.default.existsSync((0, paths_1.getOpencodeDb)());
41
39
  }
42
40
  catch {
43
41
  return false;
@@ -53,14 +51,13 @@ exports.opencodeAdapter = {
53
51
  return null;
54
52
  },
55
53
  async pollSessions(since) {
54
+ let db = null;
56
55
  try {
57
- const db = openDb();
58
- const stmt = db.prepare(`SELECT id, model, cost, tokens_input, tokens_output, tokens_cache_read, tokens_cache_write, time_updated
56
+ db = openDb();
57
+ const rows = db.prepare(`SELECT id, model, cost, tokens_input, tokens_output, tokens_cache_read, tokens_cache_write, time_updated
59
58
  FROM session
60
59
  WHERE time_updated >= ?
61
- AND time_archived IS NULL`);
62
- const rows = stmt.all(since);
63
- db.close();
60
+ AND time_archived IS NULL`).all(since);
64
61
  return rows.map(row => ({
65
62
  sessionId: row.id,
66
63
  cost: {
@@ -78,6 +75,9 @@ exports.opencodeAdapter = {
78
75
  catch {
79
76
  return [];
80
77
  }
78
+ finally {
79
+ db?.close();
80
+ }
81
81
  },
82
82
  };
83
83
  (0, adapter_1.registerAdapter)(exports.opencodeAdapter);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statforge/claudestat",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"