@yhong91/vibetime 0.1.60 → 0.1.62
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/bin/vibetime.mjs +124 -107
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -2047,7 +2047,7 @@ function claudeStyleFileMetrics(tool, input) {
|
|
|
2047
2047
|
}
|
|
2048
2048
|
|
|
2049
2049
|
// src/lib/constants.ts
|
|
2050
|
-
var PACKAGE_VERSION = true ? "0.1.
|
|
2050
|
+
var PACKAGE_VERSION = true ? "0.1.62" : "0.1.1";
|
|
2051
2051
|
var GENERATED_MARKER = "Generated by vibetime.";
|
|
2052
2052
|
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
2053
2053
|
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
@@ -3364,9 +3364,12 @@ async function isHooksJsonInstalled(filePath, command) {
|
|
|
3364
3364
|
if (!isPlainObject(config) || !isPlainObject(config.hooks)) {
|
|
3365
3365
|
return false;
|
|
3366
3366
|
}
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3367
|
+
const hookScopes = [config.hooks, isPlainObject(config.hooks.events) ? config.hooks.events : {}];
|
|
3368
|
+
return hookScopes.some(
|
|
3369
|
+
(scope) => Object.values(scope).some(
|
|
3370
|
+
(groups) => Array.isArray(groups) && groups.some(
|
|
3371
|
+
(group) => isPlainObject(group) && Array.isArray(group.hooks) && group.hooks.some((hook) => hook.command === command)
|
|
3372
|
+
)
|
|
3370
3373
|
)
|
|
3371
3374
|
);
|
|
3372
3375
|
} catch {
|
|
@@ -3375,11 +3378,7 @@ async function isHooksJsonInstalled(filePath, command) {
|
|
|
3375
3378
|
}
|
|
3376
3379
|
|
|
3377
3380
|
// src/adapters/claude-code.ts
|
|
3378
|
-
init_fs();
|
|
3379
3381
|
async function parseClaudeCodeSessionFile(filePath, options) {
|
|
3380
|
-
if (path7.basename(filePath) === "usage.jsonl" && path7.basename(path7.dirname(filePath)) === ".viberouter") {
|
|
3381
|
-
return parseClaudeRouterUsageFile(filePath, options);
|
|
3382
|
-
}
|
|
3383
3382
|
const text = await readFile3(filePath, "utf8");
|
|
3384
3383
|
const lines = text.split("\n").filter(Boolean);
|
|
3385
3384
|
const projectContext = await claudeProjectContextFromLines(filePath, lines, options);
|
|
@@ -3646,86 +3645,6 @@ async function parseClaudeCodeSessionFile(filePath, options) {
|
|
|
3646
3645
|
}
|
|
3647
3646
|
return state.events.filter((event) => validateCanonicalEvent(event).valid);
|
|
3648
3647
|
}
|
|
3649
|
-
async function parseClaudeRouterUsageFile(filePath, options) {
|
|
3650
|
-
const rows = (await readFile3(filePath, "utf8")).split("\n").map(parseJsonLine).filter((row) => Boolean(
|
|
3651
|
-
row && row.surface === "claude" && (numberField(row, "timestamp") ?? 0) > 0 && Object.keys(objectField(row, "usage")).length > 0
|
|
3652
|
-
));
|
|
3653
|
-
if (rows.length === 0) {
|
|
3654
|
-
return [];
|
|
3655
|
-
}
|
|
3656
|
-
const timestamps = rows.map((row) => numberField(row, "timestamp") ?? 0);
|
|
3657
|
-
const firstTs = Math.min(...timestamps) - 6e4;
|
|
3658
|
-
const lastTs = Math.max(...timestamps) + 6e4;
|
|
3659
|
-
const home = path7.resolve(stringOption(options.home) || path7.dirname(path7.dirname(filePath)));
|
|
3660
|
-
const transcriptCounts = /* @__PURE__ */ new Map();
|
|
3661
|
-
for (const transcript of await listJsonlFiles(path7.join(claudeConfigDir(home, process.env), "projects"))) {
|
|
3662
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3663
|
-
for (const line of (await readFile3(transcript, "utf8")).split("\n")) {
|
|
3664
|
-
const raw = parseJsonLine(line);
|
|
3665
|
-
const ts = raw ? Date.parse(timestampFrom(raw.timestamp) || "") : Number.NaN;
|
|
3666
|
-
if (!raw || stringField(raw, "type") !== "assistant" || ts < firstTs || ts > lastTs) {
|
|
3667
|
-
continue;
|
|
3668
|
-
}
|
|
3669
|
-
const message = objectField(raw, "message");
|
|
3670
|
-
const messageId = stringField(message, "id");
|
|
3671
|
-
const usageKey = messageId ? `${messageId}:${stringField(raw, "requestId")}` : null;
|
|
3672
|
-
if (usageKey && seen.has(usageKey)) {
|
|
3673
|
-
continue;
|
|
3674
|
-
}
|
|
3675
|
-
if (usageKey) {
|
|
3676
|
-
seen.add(usageKey);
|
|
3677
|
-
}
|
|
3678
|
-
const usage = claudeUsageFromMessage(message);
|
|
3679
|
-
if (!usage) {
|
|
3680
|
-
continue;
|
|
3681
|
-
}
|
|
3682
|
-
const key = `${usage.tokensInput || 0}:${usage.tokensOutput || 0}`;
|
|
3683
|
-
transcriptCounts.set(key, (transcriptCounts.get(key) || 0) + 1);
|
|
3684
|
-
}
|
|
3685
|
-
}
|
|
3686
|
-
const sourcePathHash = `sha256:${createStableHash(filePath)}`;
|
|
3687
|
-
const events = [];
|
|
3688
|
-
for (const row of rows) {
|
|
3689
|
-
const usage = objectField(row, "usage");
|
|
3690
|
-
const input = numberField(usage, "inputTokens") || 0;
|
|
3691
|
-
const output = numberField(usage, "outputTokens") || 0;
|
|
3692
|
-
const key = `${input}:${output}`;
|
|
3693
|
-
const matched = transcriptCounts.get(key) || 0;
|
|
3694
|
-
if (matched > 0) {
|
|
3695
|
-
transcriptCounts.set(key, matched - 1);
|
|
3696
|
-
continue;
|
|
3697
|
-
}
|
|
3698
|
-
const timestamp = numberField(row, "timestamp") ?? 0;
|
|
3699
|
-
const requestId = stringField(row, "requestId") || createStableHash(row).slice(0, 24);
|
|
3700
|
-
const cacheCreation = numberField(usage, "cacheCreationInputTokens") || 0;
|
|
3701
|
-
const cacheRead = numberField(usage, "cacheReadInputTokens") || 0;
|
|
3702
|
-
const cached = numberField(usage, "cachedInputTokens") || cacheCreation + cacheRead;
|
|
3703
|
-
const event = baseClaudeEvent({
|
|
3704
|
-
ts: new Date(timestamp).toISOString(),
|
|
3705
|
-
type: "model.usage",
|
|
3706
|
-
sessionId: `viberouter:${new Date(timestamp).toISOString().slice(0, 10)}`,
|
|
3707
|
-
project: "unknown",
|
|
3708
|
-
model: stringField(row, "resolvedModel") || stringField(row, "requestedModel") || stringField(row, "model"),
|
|
3709
|
-
provider: stringField(row, "provider"),
|
|
3710
|
-
confidence: "exact",
|
|
3711
|
-
metrics: {
|
|
3712
|
-
tokensInput: input || void 0,
|
|
3713
|
-
tokensCachedInput: cached || void 0,
|
|
3714
|
-
tokensCacheCreationInput: cacheCreation || void 0,
|
|
3715
|
-
tokensCacheReadInput: cacheRead || void 0,
|
|
3716
|
-
tokensOutput: output || void 0,
|
|
3717
|
-
tokensReasoningOutput: numberField(usage, "reasoningOutputTokens") || void 0,
|
|
3718
|
-
tokensTotal: numberField(usage, "totalTokens") || input + output || void 0,
|
|
3719
|
-
modelCalls: 1
|
|
3720
|
-
},
|
|
3721
|
-
refs: stringRefs({ sourceId: requestId, sourcePathHash, importKey: `claude-code:viberouter:${requestId}` })
|
|
3722
|
-
});
|
|
3723
|
-
if (validateCanonicalEvent(event).valid) {
|
|
3724
|
-
events.push(event);
|
|
3725
|
-
}
|
|
3726
|
-
}
|
|
3727
|
-
return events;
|
|
3728
|
-
}
|
|
3729
3648
|
function baseClaudeEvent(event) {
|
|
3730
3649
|
return {
|
|
3731
3650
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
@@ -4062,7 +3981,6 @@ function createClaudeCodeAdapter() {
|
|
|
4062
3981
|
const base = claudeConfigDir(home, env);
|
|
4063
3982
|
return [
|
|
4064
3983
|
path7.join(base, "projects"),
|
|
4065
|
-
path7.join(home, ".viberouter", "usage.jsonl"),
|
|
4066
3984
|
path7.join(base, ".claude.json"),
|
|
4067
3985
|
path7.join(home, ".claude.json")
|
|
4068
3986
|
];
|
|
@@ -6833,11 +6751,12 @@ async function readCursorAccessTokenFromHome(options) {
|
|
|
6833
6751
|
return void 0;
|
|
6834
6752
|
}
|
|
6835
6753
|
function cloudUsageToPersisted(row, index = 0) {
|
|
6754
|
+
const tokensInput = (row.tokensInput || 0) + (row.tokensCacheReadInput || 0) + (row.tokensCacheCreationInput || 0);
|
|
6836
6755
|
return {
|
|
6837
6756
|
generationId: `${CURSOR_CLOUD_USAGE_GENERATION_ID}:${index}:${row.tokensInput}:${row.tokensOutput}:${row.tokensCacheReadInput}`,
|
|
6838
6757
|
ts: row.ts,
|
|
6839
6758
|
model: row.model,
|
|
6840
|
-
tokensInput:
|
|
6759
|
+
tokensInput: tokensInput || void 0,
|
|
6841
6760
|
tokensOutput: row.tokensOutput || void 0,
|
|
6842
6761
|
tokensCacheReadInput: row.tokensCacheReadInput || void 0,
|
|
6843
6762
|
tokensCacheCreationInput: row.tokensCacheCreationInput || void 0
|
|
@@ -13232,7 +13151,6 @@ import { execFile } from "node:child_process";
|
|
|
13232
13151
|
import { readFile as readFile15, stat as stat14 } from "node:fs/promises";
|
|
13233
13152
|
import path22 from "node:path";
|
|
13234
13153
|
import { promisify as promisify2 } from "node:util";
|
|
13235
|
-
init_fs();
|
|
13236
13154
|
var execFileAsync = promisify2(execFile);
|
|
13237
13155
|
function zcodeCliDir(home, env) {
|
|
13238
13156
|
const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
|
|
@@ -13244,6 +13162,27 @@ function zcodeCliDir(home, env) {
|
|
|
13244
13162
|
function zcodeDbPath(home, env) {
|
|
13245
13163
|
return path22.join(zcodeCliDir(home, env), "db", "db.sqlite");
|
|
13246
13164
|
}
|
|
13165
|
+
function zcodeConfigPath(home, env) {
|
|
13166
|
+
return path22.join(zcodeCliDir(home, env), "config.json");
|
|
13167
|
+
}
|
|
13168
|
+
var zcodeHandler = (msg) => hookHandler("zcode", msg);
|
|
13169
|
+
function hookConfig9() {
|
|
13170
|
+
const anyTool = [{ matcher: ".*", hooks: [zcodeHandler("Reporting tool activity")] }];
|
|
13171
|
+
return {
|
|
13172
|
+
hooks: {
|
|
13173
|
+
enabled: true,
|
|
13174
|
+
events: {
|
|
13175
|
+
SessionStart: [{ hooks: [zcodeHandler("Reporting session start")] }],
|
|
13176
|
+
UserPromptSubmit: [{ hooks: [zcodeHandler("Reporting prompt activity")] }],
|
|
13177
|
+
PreToolUse: anyTool,
|
|
13178
|
+
PermissionRequest: anyTool,
|
|
13179
|
+
PostToolUse: anyTool,
|
|
13180
|
+
PostToolUseFailure: anyTool,
|
|
13181
|
+
Stop: [{ hooks: [zcodeHandler("Reporting turn completion")] }]
|
|
13182
|
+
}
|
|
13183
|
+
}
|
|
13184
|
+
};
|
|
13185
|
+
}
|
|
13247
13186
|
var providerNameCache = null;
|
|
13248
13187
|
async function loadProviderNames(configPath2) {
|
|
13249
13188
|
let fileMtime = 0;
|
|
@@ -13325,10 +13264,14 @@ async function readZCodeRows(dbPath) {
|
|
|
13325
13264
|
'id',id,
|
|
13326
13265
|
'parent_id',parent_id,
|
|
13327
13266
|
'directory',directory,
|
|
13267
|
+
'workspace_id',workspace_id,
|
|
13328
13268
|
'title',title,
|
|
13329
13269
|
'task_type',task_type,
|
|
13330
13270
|
'time_created',time_created,
|
|
13331
|
-
'time_updated',time_updated
|
|
13271
|
+
'time_updated',time_updated,
|
|
13272
|
+
'summary_additions',summary_additions,
|
|
13273
|
+
'summary_deletions',summary_deletions,
|
|
13274
|
+
'summary_files',summary_files
|
|
13332
13275
|
) from session order by time_created, id;`,
|
|
13333
13276
|
`select json_object(
|
|
13334
13277
|
'kind','turn',
|
|
@@ -13355,6 +13298,7 @@ async function readZCodeRows(dbPath) {
|
|
|
13355
13298
|
'query_source',query_source,
|
|
13356
13299
|
'provider_id',provider_id,
|
|
13357
13300
|
'model_id',model_id,
|
|
13301
|
+
'variant',variant,
|
|
13358
13302
|
'agent',agent,
|
|
13359
13303
|
'mode',mode,
|
|
13360
13304
|
'status',status,
|
|
@@ -13368,7 +13312,9 @@ async function readZCodeRows(dbPath) {
|
|
|
13368
13312
|
'cache_read_input_tokens',cache_read_input_tokens,
|
|
13369
13313
|
'provider_total_tokens',provider_total_tokens,
|
|
13370
13314
|
'computed_total_tokens',computed_total_tokens,
|
|
13371
|
-
'tool_call_count',tool_call_count
|
|
13315
|
+
'tool_call_count',tool_call_count,
|
|
13316
|
+
'retry_count',retry_count,
|
|
13317
|
+
'error_type',error_type
|
|
13372
13318
|
) from model_usage order by started_at, id;`,
|
|
13373
13319
|
`select json_object(
|
|
13374
13320
|
'kind','tool',
|
|
@@ -13386,7 +13332,8 @@ async function readZCodeRows(dbPath) {
|
|
|
13386
13332
|
'completed_at',completed_at,
|
|
13387
13333
|
'duration_ms',duration_ms,
|
|
13388
13334
|
'output_bytes',output_bytes,
|
|
13389
|
-
'exit_code',exit_code
|
|
13335
|
+
'exit_code',exit_code,
|
|
13336
|
+
'error_type',error_type
|
|
13390
13337
|
) from tool_usage order by started_at, id;`
|
|
13391
13338
|
];
|
|
13392
13339
|
const results = await Promise.all(queries.map((query) => sqliteJsonRows(dbPath, query)));
|
|
@@ -13408,6 +13355,7 @@ function modelMetrics(row) {
|
|
|
13408
13355
|
const alignedInput = input > 0 ? input + (cacheIsSeparate ? cached : 0) : cached;
|
|
13409
13356
|
const alignedTotal = alignedInput + output;
|
|
13410
13357
|
const durationMs = numberField(row, "duration_ms");
|
|
13358
|
+
const variant = stringField(row, "variant");
|
|
13411
13359
|
return {
|
|
13412
13360
|
tokensInput: alignedInput || void 0,
|
|
13413
13361
|
tokensOutput: output,
|
|
@@ -13416,6 +13364,7 @@ function modelMetrics(row) {
|
|
|
13416
13364
|
tokensCacheCreationInput: cacheCreation,
|
|
13417
13365
|
tokensCacheReadInput: cacheRead,
|
|
13418
13366
|
tokensTotal: alignedTotal,
|
|
13367
|
+
reasoningEffort: variant || void 0,
|
|
13419
13368
|
modelDurationMs: durationMs,
|
|
13420
13369
|
durationMs,
|
|
13421
13370
|
modelCalls: 1,
|
|
@@ -13445,13 +13394,14 @@ function sessionContext(row, sessions) {
|
|
|
13445
13394
|
const cwd = stringField(session, "directory");
|
|
13446
13395
|
const project = projectFromDirectory(cwd);
|
|
13447
13396
|
const rootSessionId = resolveRootSessionId2(sessionId, sessions);
|
|
13397
|
+
const workspaceId = stringField(session, "workspace_id") || createWorkspaceId({ projectName: project, repoRoot: cwd });
|
|
13448
13398
|
return {
|
|
13449
13399
|
rawSessionId: sessionId,
|
|
13450
13400
|
sessionId: `zcode:${rootSessionId}`,
|
|
13451
13401
|
isSubagent: rootSessionId !== sessionId,
|
|
13452
13402
|
cwd,
|
|
13453
13403
|
project,
|
|
13454
|
-
workspaceId
|
|
13404
|
+
workspaceId,
|
|
13455
13405
|
parentSessionId: stringField(session, "parent_id") ? `zcode:${stringField(session, "parent_id")}` : void 0
|
|
13456
13406
|
};
|
|
13457
13407
|
}
|
|
@@ -13515,6 +13465,9 @@ async function parseZCodeDb(filePath, options) {
|
|
|
13515
13465
|
if (event) events.push(event);
|
|
13516
13466
|
const completedTs = isoFromMs(numberField(row, "time_updated"));
|
|
13517
13467
|
if (completedTs && completedTs !== ts) {
|
|
13468
|
+
const linesAdded = numberField(row, "summary_additions");
|
|
13469
|
+
const linesRemoved = numberField(row, "summary_deletions");
|
|
13470
|
+
const filesChanged = numberField(row, "summary_files");
|
|
13518
13471
|
const completed = makeEvent2({
|
|
13519
13472
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
13520
13473
|
ts: completedTs,
|
|
@@ -13527,6 +13480,7 @@ async function parseZCodeDb(filePath, options) {
|
|
|
13527
13480
|
parentAgentInstanceId: ctx.parentSessionId,
|
|
13528
13481
|
agent: "zcode",
|
|
13529
13482
|
confidence: "exact",
|
|
13483
|
+
metrics: linesAdded || linesRemoved || filesChanged ? { linesAdded: linesAdded || void 0, linesRemoved: linesRemoved || void 0, filesChanged: filesChanged || void 0 } : void 0,
|
|
13530
13484
|
refs: { sourceId: `${id}:session:ended` }
|
|
13531
13485
|
}, row, rowNumber, filePath, options);
|
|
13532
13486
|
if (completed) events.push(completed);
|
|
@@ -13615,7 +13569,10 @@ async function parseZCodeDb(filePath, options) {
|
|
|
13615
13569
|
sourceId: stringField(row, "id") || `${ctx.rawSessionId}:model:${rowNumber}`,
|
|
13616
13570
|
zcodeQuerySource: stringField(row, "query_source"),
|
|
13617
13571
|
zcodeMode: stringField(row, "mode"),
|
|
13618
|
-
zcodeStatus: stringField(row, "status")
|
|
13572
|
+
zcodeStatus: stringField(row, "status"),
|
|
13573
|
+
zcodeVariant: stringField(row, "variant"),
|
|
13574
|
+
zcodeErrorType: stringField(row, "error_type"),
|
|
13575
|
+
zcodeRetryCount: numberField(row, "retry_count") || void 0
|
|
13619
13576
|
})
|
|
13620
13577
|
}, row, rowNumber, filePath, options);
|
|
13621
13578
|
if (usage) events.push(usage);
|
|
@@ -13678,7 +13635,8 @@ async function parseZCodeDb(filePath, options) {
|
|
|
13678
13635
|
refs: refs({
|
|
13679
13636
|
sourceId: `${toolCallId}:completed`,
|
|
13680
13637
|
zcodeStatus: status,
|
|
13681
|
-
zcodeExitCode: numberField(row, "exit_code")
|
|
13638
|
+
zcodeExitCode: numberField(row, "exit_code"),
|
|
13639
|
+
zcodeErrorType: stringField(row, "error_type")
|
|
13682
13640
|
})
|
|
13683
13641
|
}, row, rowNumber, filePath, options);
|
|
13684
13642
|
if (completed) events.push(completed);
|
|
@@ -13692,7 +13650,15 @@ async function zcodeBackfillFiles(sourceRoot, home, env) {
|
|
|
13692
13650
|
const filePath = candidate.endsWith(".sqlite") ? candidate : path22.join(candidate, "db", "db.sqlite");
|
|
13693
13651
|
try {
|
|
13694
13652
|
const info = await stat14(filePath);
|
|
13695
|
-
|
|
13653
|
+
let modifiedMs = info.mtimeMs;
|
|
13654
|
+
for (const suffix of ["-wal", "-shm"]) {
|
|
13655
|
+
try {
|
|
13656
|
+
const sidecar = await stat14(`${filePath}${suffix}`);
|
|
13657
|
+
modifiedMs = Math.max(modifiedMs, sidecar.mtimeMs);
|
|
13658
|
+
} catch {
|
|
13659
|
+
}
|
|
13660
|
+
}
|
|
13661
|
+
return [{ path: filePath, modifiedAt: new Date(modifiedMs).toISOString() }];
|
|
13696
13662
|
} catch {
|
|
13697
13663
|
return [];
|
|
13698
13664
|
}
|
|
@@ -13707,13 +13673,20 @@ function createZCodeAdapter() {
|
|
|
13707
13673
|
return zcodeCliDir(home, env);
|
|
13708
13674
|
},
|
|
13709
13675
|
installedPath(home, env) {
|
|
13710
|
-
return
|
|
13676
|
+
return zcodeConfigPath(home, env);
|
|
13711
13677
|
},
|
|
13712
13678
|
async isInstalled(home, env) {
|
|
13713
|
-
return
|
|
13679
|
+
return isHooksJsonInstalled(
|
|
13680
|
+
zcodeConfigPath(home, env),
|
|
13681
|
+
"vibetime hook --agent zcode"
|
|
13682
|
+
);
|
|
13714
13683
|
},
|
|
13715
|
-
installEntries() {
|
|
13716
|
-
return [
|
|
13684
|
+
installEntries(home, env) {
|
|
13685
|
+
return [{
|
|
13686
|
+
kind: "hooks-json",
|
|
13687
|
+
path: zcodeConfigPath(home, env),
|
|
13688
|
+
content: hookConfig9()
|
|
13689
|
+
}];
|
|
13717
13690
|
},
|
|
13718
13691
|
sourcePaths(home, env) {
|
|
13719
13692
|
return [zcodeDbPath(home, env)];
|
|
@@ -14639,11 +14612,24 @@ function mergeHookObjects(existing, addition) {
|
|
|
14639
14612
|
const additionHooks = isPlainObject(additionObject.hooks) ? additionObject.hooks : {};
|
|
14640
14613
|
merged.hooks = isPlainObject(merged.hooks) ? merged.hooks : {};
|
|
14641
14614
|
const mergedHooks = merged.hooks;
|
|
14642
|
-
|
|
14615
|
+
mergeHookEvents(mergedHooks, additionHooks);
|
|
14616
|
+
const additionEvents = isPlainObject(additionHooks.events) ? additionHooks.events : {};
|
|
14617
|
+
if (Object.keys(additionEvents).length > 0) {
|
|
14618
|
+
const mergedEvents = isPlainObject(mergedHooks.events) ? mergedHooks.events : {};
|
|
14619
|
+
mergeHookEvents(mergedEvents, additionEvents);
|
|
14620
|
+
mergedHooks.events = mergedEvents;
|
|
14621
|
+
if (additionHooks.enabled === true) {
|
|
14622
|
+
mergedHooks.enabled = true;
|
|
14623
|
+
}
|
|
14624
|
+
}
|
|
14625
|
+
return merged;
|
|
14626
|
+
}
|
|
14627
|
+
function mergeHookEvents(target, addition) {
|
|
14628
|
+
for (const [event, groups] of Object.entries(addition)) {
|
|
14643
14629
|
if (!Array.isArray(groups)) {
|
|
14644
14630
|
continue;
|
|
14645
14631
|
}
|
|
14646
|
-
const existingGroups = Array.isArray(
|
|
14632
|
+
const existingGroups = Array.isArray(target[event]) ? target[event] : [];
|
|
14647
14633
|
const nextGroups = [...existingGroups];
|
|
14648
14634
|
for (const group of groups) {
|
|
14649
14635
|
const command = hookCommandFromGroup(group);
|
|
@@ -14654,9 +14640,8 @@ function mergeHookObjects(existing, addition) {
|
|
|
14654
14640
|
nextGroups.push(group);
|
|
14655
14641
|
}
|
|
14656
14642
|
}
|
|
14657
|
-
|
|
14643
|
+
target[event] = nextGroups;
|
|
14658
14644
|
}
|
|
14659
|
-
return merged;
|
|
14660
14645
|
}
|
|
14661
14646
|
function hookCommandFromGroup(group) {
|
|
14662
14647
|
if (!isPlainObject(group) || !Array.isArray(group.hooks)) {
|
|
@@ -14745,6 +14730,12 @@ function collectHookCommandsFromJsonContent(content) {
|
|
|
14745
14730
|
for (const groups of Object.values(content.hooks)) {
|
|
14746
14731
|
walkGroups(groups);
|
|
14747
14732
|
}
|
|
14733
|
+
const nestedEvents = content.hooks.events;
|
|
14734
|
+
if (isPlainObject(nestedEvents)) {
|
|
14735
|
+
for (const groups of Object.values(nestedEvents)) {
|
|
14736
|
+
walkGroups(groups);
|
|
14737
|
+
}
|
|
14738
|
+
}
|
|
14748
14739
|
}
|
|
14749
14740
|
for (const [key, value] of Object.entries(content)) {
|
|
14750
14741
|
if (key === "hooks" || key === "enable_json_hooks" || !isPlainObject(value)) {
|
|
@@ -14809,7 +14800,33 @@ async function uninstallHooksJson(filePath, content, { dryRun, onWrite }) {
|
|
|
14809
14800
|
}
|
|
14810
14801
|
}
|
|
14811
14802
|
}
|
|
14812
|
-
if (isPlainObject(next.hooks
|
|
14803
|
+
if (isPlainObject(next.hooks.events)) {
|
|
14804
|
+
for (const [event, groups] of Object.entries(next.hooks.events)) {
|
|
14805
|
+
const stripped = stripHookCommandsFromGroups(groups, commands);
|
|
14806
|
+
if (JSON.stringify(stripped) !== JSON.stringify(groups)) {
|
|
14807
|
+
changed = true;
|
|
14808
|
+
if (Array.isArray(stripped) && stripped.length === 0) {
|
|
14809
|
+
delete next.hooks.events[event];
|
|
14810
|
+
} else {
|
|
14811
|
+
next.hooks.events[event] = stripped;
|
|
14812
|
+
}
|
|
14813
|
+
}
|
|
14814
|
+
}
|
|
14815
|
+
if (Object.keys(next.hooks.events).length === 0) {
|
|
14816
|
+
delete next.hooks.events;
|
|
14817
|
+
}
|
|
14818
|
+
}
|
|
14819
|
+
const eventsObject = isPlainObject(next.hooks.events) ? next.hooks.events : {};
|
|
14820
|
+
const hooksHasGroups = Object.values(next.hooks).some((value) => Array.isArray(value) && value.length > 0) || Object.values(eventsObject).some((value) => Array.isArray(value) && value.length > 0);
|
|
14821
|
+
if (!hooksHasGroups) {
|
|
14822
|
+
if (next.hooks.enabled !== void 0) {
|
|
14823
|
+
delete next.hooks.enabled;
|
|
14824
|
+
}
|
|
14825
|
+
if (Object.keys(next.hooks).length === 0) {
|
|
14826
|
+
delete next.hooks;
|
|
14827
|
+
changed = true;
|
|
14828
|
+
}
|
|
14829
|
+
} else if (isPlainObject(next.hooks) && Object.keys(next.hooks).length === 0) {
|
|
14813
14830
|
delete next.hooks;
|
|
14814
14831
|
changed = true;
|
|
14815
14832
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yhong91/vibetime",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.62",
|
|
5
5
|
"description": "vibetime CLI — install AI-agent hooks (Claude Code, Codex, OpenCode, Pi, Cursor) and report activity to vibetime.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|