@vibe-cafe/vibe-usage 0.10.5 → 0.10.8
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 +11 -7
- package/package.json +1 -1
- package/src/claude-roots.js +86 -4
- package/src/cline-roots.js +40 -0
- package/src/craft-roots.js +15 -0
- package/src/parsers/alma.js +91 -0
- package/src/parsers/amp.js +16 -4
- package/src/parsers/claude-code.js +3 -1
- package/src/parsers/cline.js +26 -40
- package/src/parsers/craft-agent.js +21 -0
- package/src/parsers/index.js +8 -0
- package/src/parsers/omp.js +10 -0
- package/src/parsers/openclaw.js +24 -2
- package/src/parsers/pi-coding-agent.js +7 -141
- package/src/parsers/pi-session-jsonl.js +148 -0
- package/src/parsers/workbuddy.js +287 -0
- package/src/pi-roots.js +89 -0
- package/src/sync.js +13 -2
- package/src/tools.js +48 -3
- package/src/workbuddy-roots.js +19 -0
package/src/sync.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from './state.js';
|
|
7
7
|
import { ingest, fetchSettings } from './api.js';
|
|
8
8
|
import { createSyncClient, forBatch } from './client-meta.js';
|
|
9
|
-
import { parsers } from './parsers/index.js';
|
|
9
|
+
import { aggregateToBuckets, parsers } from './parsers/index.js';
|
|
10
10
|
import { success, failure, arrow, link, dim } from './output.js';
|
|
11
11
|
|
|
12
12
|
const BATCH_SIZE = 100;
|
|
@@ -31,6 +31,16 @@ export function resolveCodexExtraHome(configured, temporary) {
|
|
|
31
31
|
return temporary ?? configured;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// Hiding project names can collapse multiple parser buckets onto one server
|
|
35
|
+
// identity. Merge those buckets before hashing/uploading so no project's usage
|
|
36
|
+
// wins by iteration order.
|
|
37
|
+
export function reaggregateHiddenProjectBuckets(buckets) {
|
|
38
|
+
return aggregateToBuckets(buckets.map(bucket => ({
|
|
39
|
+
...bucket,
|
|
40
|
+
timestamp: new Date(bucket.bucketStart),
|
|
41
|
+
})));
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
export async function runSync({
|
|
35
45
|
throws = false,
|
|
36
46
|
quiet = false,
|
|
@@ -70,7 +80,7 @@ export async function runSync({
|
|
|
70
80
|
process.exit(1);
|
|
71
81
|
}
|
|
72
82
|
|
|
73
|
-
|
|
83
|
+
let allBuckets = [];
|
|
74
84
|
const allSessions = [];
|
|
75
85
|
const parserResults = [];
|
|
76
86
|
const parserProgress = [];
|
|
@@ -166,6 +176,7 @@ export async function runSync({
|
|
|
166
176
|
if (!uploadProject) {
|
|
167
177
|
for (const b of allBuckets) b.project = 'unknown';
|
|
168
178
|
for (const s of allSessions) s.project = 'unknown';
|
|
179
|
+
allBuckets = reaggregateHiddenProjectBuckets(allBuckets);
|
|
169
180
|
}
|
|
170
181
|
|
|
171
182
|
// Incremental upload diff: parsers above emit a complete view of live local
|
package/src/tools.js
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
-
import { isAbsolute, join, resolve } from 'node:path';
|
|
2
|
+
import { isAbsolute, join, posix, resolve, win32 } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { findClaudeCodeDataDirs } from './claude-roots.js';
|
|
5
5
|
import { codexSessionDirs, resolveCodexHomes } from './codex-roots.js';
|
|
6
|
+
import { findClineDataDirs } from './cline-roots.js';
|
|
7
|
+
import { findCraftDataDirs } from './craft-roots.js';
|
|
8
|
+
import { findOmpDataDirs, findPiDataDirs } from './pi-roots.js';
|
|
9
|
+
import { findWorkbuddyDataDirs } from './workbuddy-roots.js';
|
|
10
|
+
|
|
11
|
+
export function getAlmaDbPath(env = process.env, platform = process.platform, home = homedir()) {
|
|
12
|
+
const pathImpl = platform === 'win32' ? win32 : posix;
|
|
13
|
+
const override = env.VIBE_USAGE_ALMA_DB?.trim();
|
|
14
|
+
if (override) {
|
|
15
|
+
return platform === process.platform ? resolve(override) : pathImpl.resolve(override);
|
|
16
|
+
}
|
|
17
|
+
if (platform === 'darwin') {
|
|
18
|
+
return pathImpl.join(home, 'Library', 'Application Support', 'alma', 'chat_threads.db');
|
|
19
|
+
}
|
|
20
|
+
if (platform === 'win32') {
|
|
21
|
+
const appData = env.APPDATA?.trim() || pathImpl.join(home, 'AppData', 'Roaming');
|
|
22
|
+
return pathImpl.join(appData, 'alma', 'chat_threads.db');
|
|
23
|
+
}
|
|
24
|
+
const configHome = env.XDG_CONFIG_HOME?.trim() || pathImpl.join(home, '.config');
|
|
25
|
+
return pathImpl.join(configHome, 'alma', 'chat_threads.db');
|
|
26
|
+
}
|
|
6
27
|
|
|
7
28
|
function getCursorStateDbPath() {
|
|
8
29
|
const rel = join('User', 'globalStorage', 'state.vscdb');
|
|
@@ -61,7 +82,6 @@ function findExtensionDirs(extensionId) {
|
|
|
61
82
|
return dirs;
|
|
62
83
|
}
|
|
63
84
|
|
|
64
|
-
const findClineDataDirs = () => findExtensionDirs('saoudrizwan.claude-dev');
|
|
65
85
|
const findRooCodeDataDirs = () => findExtensionDirs('rooveterinaryinc.roo-cline');
|
|
66
86
|
|
|
67
87
|
/** Find all OpenClaw data roots: ~/.openclaw and ~/.openclaw-<profile> */
|
|
@@ -175,6 +195,12 @@ export function findDimAgentDataDirs() {
|
|
|
175
195
|
}
|
|
176
196
|
|
|
177
197
|
export const TOOLS = [
|
|
198
|
+
{
|
|
199
|
+
name: 'Alma',
|
|
200
|
+
id: 'alma',
|
|
201
|
+
dataDir: getAlmaDbPath(),
|
|
202
|
+
detectDataDirs: () => [getAlmaDbPath()].filter(existsSync),
|
|
203
|
+
},
|
|
178
204
|
{
|
|
179
205
|
name: 'Claude Code',
|
|
180
206
|
id: 'claude-code',
|
|
@@ -198,6 +224,12 @@ export const TOOLS = [
|
|
|
198
224
|
id: 'copilot-cli',
|
|
199
225
|
dataDir: join(homedir(), '.copilot', 'session-state'),
|
|
200
226
|
},
|
|
227
|
+
{
|
|
228
|
+
name: 'CraftAgent',
|
|
229
|
+
id: 'craft-agent',
|
|
230
|
+
dataDir: join(homedir(), '.craft-agent', 'workspaces'),
|
|
231
|
+
detectDataDirs: findCraftDataDirs,
|
|
232
|
+
},
|
|
201
233
|
{
|
|
202
234
|
name: 'Cursor',
|
|
203
235
|
id: 'cursor',
|
|
@@ -225,10 +257,17 @@ export const TOOLS = [
|
|
|
225
257
|
dataDir: join(homedir(), '.openclaw', 'agents'),
|
|
226
258
|
detectDataDirs: findOpenclawDataDirs,
|
|
227
259
|
},
|
|
260
|
+
{
|
|
261
|
+
name: 'Oh My Pi',
|
|
262
|
+
id: 'omp',
|
|
263
|
+
dataDir: join(homedir(), '.omp', 'agent', 'sessions'),
|
|
264
|
+
detectDataDirs: findOmpDataDirs,
|
|
265
|
+
},
|
|
228
266
|
{
|
|
229
267
|
name: 'pi',
|
|
230
268
|
id: 'pi-coding-agent',
|
|
231
269
|
dataDir: join(homedir(), '.pi', 'agent', 'sessions'),
|
|
270
|
+
detectDataDirs: findPiDataDirs,
|
|
232
271
|
},
|
|
233
272
|
{
|
|
234
273
|
name: 'Qwen Code',
|
|
@@ -284,7 +323,7 @@ export const TOOLS = [
|
|
|
284
323
|
{
|
|
285
324
|
name: 'Cline',
|
|
286
325
|
id: 'cline',
|
|
287
|
-
dataDir: join(homedir(), '
|
|
326
|
+
dataDir: join(homedir(), '.cline'),
|
|
288
327
|
detectDataDirs: findClineDataDirs,
|
|
289
328
|
},
|
|
290
329
|
{
|
|
@@ -293,6 +332,12 @@ export const TOOLS = [
|
|
|
293
332
|
dataDir: join(homedir(), 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'rooveterinaryinc.roo-cline'),
|
|
294
333
|
detectDataDirs: findRooCodeDataDirs,
|
|
295
334
|
},
|
|
335
|
+
{
|
|
336
|
+
name: 'WorkBuddy',
|
|
337
|
+
id: 'workbuddy',
|
|
338
|
+
dataDir: join(homedir(), '.workbuddy', 'projects'),
|
|
339
|
+
detectDataDirs: () => findWorkbuddyDataDirs().filter(existsSync),
|
|
340
|
+
},
|
|
296
341
|
{
|
|
297
342
|
name: 'ZCode',
|
|
298
343
|
id: 'zcode',
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { delimiter, join } from 'node:path';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
|
|
4
|
+
export function getDefaultWorkbuddyProjectsDir() {
|
|
5
|
+
return join(homedir(), '.workbuddy', 'projects');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Fixture/relocation hook. Entries may name either the WorkBuddy home or its
|
|
9
|
+
// projects/ directory; the parser normalizes both forms.
|
|
10
|
+
export function findWorkbuddyDataDirs() {
|
|
11
|
+
const override = process.env.VIBE_USAGE_WORKBUDDY_DIRS?.trim();
|
|
12
|
+
if (!override) return [getDefaultWorkbuddyProjectsDir()];
|
|
13
|
+
return [...new Set(
|
|
14
|
+
override
|
|
15
|
+
.split(delimiter)
|
|
16
|
+
.map(entry => entry.trim())
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
)];
|
|
19
|
+
}
|