@yhong91/vibetime 0.1.65 → 0.1.67
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 +254 -83
- 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.67" : "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;
|
|
@@ -5832,12 +5832,46 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5832
5832
|
let project;
|
|
5833
5833
|
let model;
|
|
5834
5834
|
let currentTurnId;
|
|
5835
|
+
let currentTurnStartedAt;
|
|
5836
|
+
let currentTurnLastEventAt;
|
|
5835
5837
|
let sessionStartedAt;
|
|
5836
5838
|
let reasoningEffort;
|
|
5839
|
+
let emittedShutdownUsage = false;
|
|
5840
|
+
let sawWorkSinceShutdown = false;
|
|
5841
|
+
const lastShutdownUsage = /* @__PURE__ */ new Map();
|
|
5837
5842
|
const pendingTools = /* @__PURE__ */ new Map();
|
|
5838
5843
|
const turnTokenAccum = /* @__PURE__ */ new Map();
|
|
5839
|
-
const
|
|
5840
|
-
|
|
5844
|
+
const noteWork = (ts) => {
|
|
5845
|
+
if (currentTurnId) {
|
|
5846
|
+
currentTurnLastEventAt = ts;
|
|
5847
|
+
}
|
|
5848
|
+
sawWorkSinceShutdown = true;
|
|
5849
|
+
};
|
|
5850
|
+
const closeOpenTurn = () => {
|
|
5851
|
+
if (!currentTurnId || !currentTurnLastEventAt && !currentTurnStartedAt) {
|
|
5852
|
+
return;
|
|
5853
|
+
}
|
|
5854
|
+
const closedAt = currentTurnLastEventAt || currentTurnStartedAt;
|
|
5855
|
+
if (!closedAt) {
|
|
5856
|
+
return;
|
|
5857
|
+
}
|
|
5858
|
+
events.push(baseCopilotEvent({
|
|
5859
|
+
ts: closedAt,
|
|
5860
|
+
type: "turn.completed",
|
|
5861
|
+
sessionId,
|
|
5862
|
+
turnId: currentTurnId,
|
|
5863
|
+
cwd,
|
|
5864
|
+
project,
|
|
5865
|
+
model,
|
|
5866
|
+
confidence: "derived"
|
|
5867
|
+
}));
|
|
5868
|
+
};
|
|
5869
|
+
const releaseTurn = () => {
|
|
5870
|
+
closeOpenTurn();
|
|
5871
|
+
currentTurnId = void 0;
|
|
5872
|
+
currentTurnStartedAt = void 0;
|
|
5873
|
+
currentTurnLastEventAt = void 0;
|
|
5874
|
+
};
|
|
5841
5875
|
for (const [index, line] of lines.entries()) {
|
|
5842
5876
|
const lineNumber = index + 1;
|
|
5843
5877
|
const raw = parseJsonLine(line);
|
|
@@ -5875,7 +5909,11 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5875
5909
|
break;
|
|
5876
5910
|
}
|
|
5877
5911
|
case "user.message": {
|
|
5912
|
+
closeOpenTurn();
|
|
5878
5913
|
currentTurnId = `turn_${createStableHash([sessionId, lineNumber]).slice(0, 24)}`;
|
|
5914
|
+
currentTurnStartedAt = ts;
|
|
5915
|
+
currentTurnLastEventAt = ts;
|
|
5916
|
+
sawWorkSinceShutdown = true;
|
|
5879
5917
|
events.push(baseCopilotEvent({
|
|
5880
5918
|
ts,
|
|
5881
5919
|
type: "turn.started",
|
|
@@ -5913,8 +5951,8 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5913
5951
|
if (msgModel) {
|
|
5914
5952
|
model = msgModel;
|
|
5915
5953
|
}
|
|
5916
|
-
const
|
|
5917
|
-
|
|
5954
|
+
const turnId = currentTurnId;
|
|
5955
|
+
noteWork(ts);
|
|
5918
5956
|
events.push(baseCopilotEvent({
|
|
5919
5957
|
ts,
|
|
5920
5958
|
type: "agent.operation",
|
|
@@ -5928,20 +5966,20 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5928
5966
|
metrics: { modelCalls: 1 }
|
|
5929
5967
|
}));
|
|
5930
5968
|
const outputTokens = numberField(data, "outputTokens");
|
|
5931
|
-
if (outputTokens && outputTokens > 0) {
|
|
5932
|
-
const
|
|
5933
|
-
|
|
5934
|
-
accum.
|
|
5935
|
-
accum.
|
|
5936
|
-
turnTokenAccum.set(
|
|
5969
|
+
if (turnId && outputTokens && outputTokens > 0) {
|
|
5970
|
+
const accum = turnTokenAccum.get(turnId) || { metrics: { tokensOutput: 0, modelCalls: 0 }, ts };
|
|
5971
|
+
accum.metrics.tokensOutput = (accum.metrics.tokensOutput || 0) + outputTokens;
|
|
5972
|
+
accum.metrics.modelCalls = (accum.metrics.modelCalls || 0) + 1;
|
|
5973
|
+
accum.ts = ts;
|
|
5974
|
+
turnTokenAccum.set(turnId, accum);
|
|
5937
5975
|
}
|
|
5938
5976
|
break;
|
|
5939
5977
|
}
|
|
5940
5978
|
case "tool.execution_start": {
|
|
5941
5979
|
const toolCallId = stringField(data, "toolCallId");
|
|
5942
5980
|
const toolName = stringField(data, "toolName") || "tool";
|
|
5943
|
-
const
|
|
5944
|
-
|
|
5981
|
+
const turnId = currentTurnId;
|
|
5982
|
+
noteWork(ts);
|
|
5945
5983
|
if (toolCallId) {
|
|
5946
5984
|
pendingTools.set(toolCallId, { tool: toolName, startedAt: ts, turnId });
|
|
5947
5985
|
}
|
|
@@ -5985,6 +6023,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5985
6023
|
if (toolCallId) {
|
|
5986
6024
|
pendingTools.delete(toolCallId);
|
|
5987
6025
|
}
|
|
6026
|
+
noteWork(ts);
|
|
5988
6027
|
const success = data.success !== false;
|
|
5989
6028
|
const durationMs = pending ? Math.max(0, new Date(ts).getTime() - new Date(pending.startedAt).getTime()) : void 0;
|
|
5990
6029
|
events.push(baseCopilotEvent({
|
|
@@ -6027,54 +6066,27 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
6027
6066
|
break;
|
|
6028
6067
|
}
|
|
6029
6068
|
case "assistant.turn_end": {
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
accum.reasoningEffort = reasoningEffort;
|
|
6035
|
-
pendingTurnUsage.push(baseCopilotEvent({
|
|
6036
|
-
ts,
|
|
6037
|
-
type: "model.usage",
|
|
6038
|
-
sessionId,
|
|
6039
|
-
turnId,
|
|
6040
|
-
cwd,
|
|
6041
|
-
project,
|
|
6042
|
-
model,
|
|
6043
|
-
confidence: "partial",
|
|
6044
|
-
metrics: accum
|
|
6045
|
-
}));
|
|
6046
|
-
turnTokenAccum.delete(turnId);
|
|
6047
|
-
}
|
|
6048
|
-
events.push(baseCopilotEvent({
|
|
6049
|
-
ts,
|
|
6050
|
-
type: "turn.completed",
|
|
6051
|
-
sessionId,
|
|
6052
|
-
turnId,
|
|
6053
|
-
cwd,
|
|
6054
|
-
project,
|
|
6055
|
-
model,
|
|
6056
|
-
confidence: "derived"
|
|
6057
|
-
}));
|
|
6069
|
+
break;
|
|
6070
|
+
}
|
|
6071
|
+
case "session.resume": {
|
|
6072
|
+
releaseTurn();
|
|
6058
6073
|
break;
|
|
6059
6074
|
}
|
|
6060
6075
|
case "session.shutdown": {
|
|
6076
|
+
releaseTurn();
|
|
6061
6077
|
const modelMetrics2 = objectField(data, "modelMetrics");
|
|
6062
6078
|
for (const [modelName, metricsRaw] of Object.entries(modelMetrics2)) {
|
|
6063
6079
|
if (!isPlainObject(metricsRaw)) {
|
|
6064
6080
|
continue;
|
|
6065
6081
|
}
|
|
6066
|
-
const
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
const
|
|
6071
|
-
|
|
6072
|
-
const total = inputTokens + outputTokens;
|
|
6073
|
-
if (total <= 0) {
|
|
6082
|
+
const next = readShutdownSnapshot(metricsRaw);
|
|
6083
|
+
if (next.input + next.output <= 0) {
|
|
6084
|
+
continue;
|
|
6085
|
+
}
|
|
6086
|
+
const delta = positiveShutdownDelta(lastShutdownUsage.get(modelName), next);
|
|
6087
|
+
if (!delta) {
|
|
6074
6088
|
continue;
|
|
6075
6089
|
}
|
|
6076
|
-
const requests = objectField(metricsRaw, "requests");
|
|
6077
|
-
const requestCount = numberField(requests, "count");
|
|
6078
6090
|
events.push(baseCopilotEvent({
|
|
6079
6091
|
ts,
|
|
6080
6092
|
type: "model.usage",
|
|
@@ -6083,38 +6095,100 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
6083
6095
|
project,
|
|
6084
6096
|
model: modelName,
|
|
6085
6097
|
confidence: "exact",
|
|
6086
|
-
metrics:
|
|
6087
|
-
tokensInput: inputTokens || void 0,
|
|
6088
|
-
tokensOutput: outputTokens || void 0,
|
|
6089
|
-
tokensCachedInput: cacheReadTokens + cacheWriteTokens || void 0,
|
|
6090
|
-
tokensCacheReadInput: cacheReadTokens || void 0,
|
|
6091
|
-
tokensCacheCreationInput: cacheWriteTokens || void 0,
|
|
6092
|
-
tokensReasoningOutput: reasoningTokens || void 0,
|
|
6093
|
-
reasoningEffort,
|
|
6094
|
-
tokensTotal: total,
|
|
6095
|
-
modelCalls: requestCount || void 0
|
|
6096
|
-
}
|
|
6098
|
+
metrics: shutdownUsageMetrics(delta === "full" ? next : delta, reasoningEffort, delta === "full")
|
|
6097
6099
|
}));
|
|
6100
|
+
lastShutdownUsage.set(modelName, next);
|
|
6098
6101
|
emittedShutdownUsage = true;
|
|
6099
6102
|
}
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6103
|
+
if (sawWorkSinceShutdown) {
|
|
6104
|
+
events.push(baseCopilotEvent({
|
|
6105
|
+
ts,
|
|
6106
|
+
type: "session.ended",
|
|
6107
|
+
sessionId,
|
|
6108
|
+
cwd,
|
|
6109
|
+
project,
|
|
6110
|
+
model,
|
|
6111
|
+
operation: "session end"
|
|
6112
|
+
}));
|
|
6113
|
+
sawWorkSinceShutdown = false;
|
|
6114
|
+
}
|
|
6109
6115
|
break;
|
|
6110
6116
|
}
|
|
6111
6117
|
}
|
|
6112
6118
|
}
|
|
6119
|
+
if (isTurnIdle(currentTurnLastEventAt)) {
|
|
6120
|
+
closeOpenTurn();
|
|
6121
|
+
}
|
|
6113
6122
|
if (!emittedShutdownUsage) {
|
|
6114
|
-
|
|
6123
|
+
for (const [turnId, accum] of turnTokenAccum) {
|
|
6124
|
+
if (!accum.metrics.tokensOutput) {
|
|
6125
|
+
continue;
|
|
6126
|
+
}
|
|
6127
|
+
accum.metrics.reasoningEffort = reasoningEffort;
|
|
6128
|
+
events.push(baseCopilotEvent({
|
|
6129
|
+
ts: accum.ts,
|
|
6130
|
+
type: "model.usage",
|
|
6131
|
+
sessionId,
|
|
6132
|
+
turnId,
|
|
6133
|
+
cwd,
|
|
6134
|
+
project,
|
|
6135
|
+
model,
|
|
6136
|
+
confidence: "partial",
|
|
6137
|
+
metrics: accum.metrics
|
|
6138
|
+
}));
|
|
6139
|
+
}
|
|
6115
6140
|
}
|
|
6116
6141
|
return events.filter((event) => validateCanonicalEvent(event).valid);
|
|
6117
6142
|
}
|
|
6143
|
+
function readShutdownSnapshot(metricsRaw) {
|
|
6144
|
+
const usage = objectField(metricsRaw, "usage");
|
|
6145
|
+
const requests = objectField(metricsRaw, "requests");
|
|
6146
|
+
return {
|
|
6147
|
+
input: numberField(usage, "inputTokens") || 0,
|
|
6148
|
+
output: numberField(usage, "outputTokens") || 0,
|
|
6149
|
+
cacheRead: numberField(usage, "cacheReadTokens") || 0,
|
|
6150
|
+
cacheWrite: numberField(usage, "cacheWriteTokens") || 0,
|
|
6151
|
+
reasoning: numberField(usage, "reasoningTokens") || 0,
|
|
6152
|
+
requests: numberField(requests, "count") || 0
|
|
6153
|
+
};
|
|
6154
|
+
}
|
|
6155
|
+
function positiveShutdownDelta(prev, next) {
|
|
6156
|
+
if (!prev) {
|
|
6157
|
+
return "full";
|
|
6158
|
+
}
|
|
6159
|
+
const delta = {
|
|
6160
|
+
input: next.input - prev.input,
|
|
6161
|
+
output: next.output - prev.output,
|
|
6162
|
+
cacheRead: next.cacheRead - prev.cacheRead,
|
|
6163
|
+
cacheWrite: next.cacheWrite - prev.cacheWrite,
|
|
6164
|
+
reasoning: next.reasoning - prev.reasoning,
|
|
6165
|
+
requests: next.requests - prev.requests
|
|
6166
|
+
};
|
|
6167
|
+
if (delta.input <= 0 && delta.output <= 0 && delta.cacheRead <= 0 && delta.cacheWrite <= 0 && delta.requests <= 0) {
|
|
6168
|
+
return null;
|
|
6169
|
+
}
|
|
6170
|
+
return delta;
|
|
6171
|
+
}
|
|
6172
|
+
function shutdownUsageMetrics(snapshot, reasoningEffort, full) {
|
|
6173
|
+
const input = full ? snapshot.input : Math.max(0, snapshot.input);
|
|
6174
|
+
const output = full ? snapshot.output : Math.max(0, snapshot.output);
|
|
6175
|
+
const cacheRead = full ? snapshot.cacheRead : Math.max(0, snapshot.cacheRead);
|
|
6176
|
+
const cacheWrite = full ? snapshot.cacheWrite : Math.max(0, snapshot.cacheWrite);
|
|
6177
|
+
const reasoning = full ? snapshot.reasoning : Math.max(0, snapshot.reasoning);
|
|
6178
|
+
const requests = full ? snapshot.requests : Math.max(0, snapshot.requests);
|
|
6179
|
+
const total = input + output;
|
|
6180
|
+
return {
|
|
6181
|
+
tokensInput: input > 0 ? input : void 0,
|
|
6182
|
+
tokensOutput: output > 0 ? output : void 0,
|
|
6183
|
+
tokensCachedInput: cacheRead + cacheWrite > 0 ? cacheRead + cacheWrite : void 0,
|
|
6184
|
+
tokensCacheReadInput: cacheRead > 0 ? cacheRead : void 0,
|
|
6185
|
+
tokensCacheCreationInput: cacheWrite > 0 ? cacheWrite : void 0,
|
|
6186
|
+
tokensReasoningOutput: reasoning > 0 ? reasoning : void 0,
|
|
6187
|
+
reasoningEffort,
|
|
6188
|
+
tokensTotal: total > 0 ? total : void 0,
|
|
6189
|
+
modelCalls: requests > 0 ? requests : void 0
|
|
6190
|
+
};
|
|
6191
|
+
}
|
|
6118
6192
|
function copilotFileActivities(tool, args, ts, cwd) {
|
|
6119
6193
|
const normalized = tool.toLowerCase();
|
|
6120
6194
|
if (normalized === "apply_patch" && typeof args === "string") {
|
|
@@ -6217,6 +6291,7 @@ function createCopilotAdapter() {
|
|
|
6217
6291
|
}
|
|
6218
6292
|
|
|
6219
6293
|
// src/adapters/cursor.ts
|
|
6294
|
+
import { readFileSync } from "node:fs";
|
|
6220
6295
|
import { copyFile, mkdir as mkdir4, readdir as readdir6, readFile as readFile8, stat as stat8, writeFile as writeFile4 } from "node:fs/promises";
|
|
6221
6296
|
import os6 from "node:os";
|
|
6222
6297
|
import path13 from "node:path";
|
|
@@ -6799,9 +6874,18 @@ function cloudUsageToPersisted(row, index = 0) {
|
|
|
6799
6874
|
tokensCacheCreationInput: row.tokensCacheCreationInput || void 0
|
|
6800
6875
|
};
|
|
6801
6876
|
}
|
|
6802
|
-
async function resolveCursorSessionUsage(options, sessionId) {
|
|
6877
|
+
async function resolveCursorSessionUsage(options, sessionId, filePath) {
|
|
6803
6878
|
const persisted = await readPersistedSessionContextFromOptions(options, sessionId);
|
|
6804
|
-
|
|
6879
|
+
const hookUsage = persisted?.usage ?? [];
|
|
6880
|
+
if (hookUsage.length > 0) {
|
|
6881
|
+
return hookUsage;
|
|
6882
|
+
}
|
|
6883
|
+
const cloudMap = await loadCursorCloudUsageMap(options, filePath);
|
|
6884
|
+
const cloudEvents = cloudMap.get(sessionId);
|
|
6885
|
+
if (!cloudEvents?.length) {
|
|
6886
|
+
return [];
|
|
6887
|
+
}
|
|
6888
|
+
return cloudEvents.map((event, index) => cloudUsageToPersisted(event, index));
|
|
6805
6889
|
}
|
|
6806
6890
|
function cursorCloudUsageCachePath(home) {
|
|
6807
6891
|
return path13.join(home, ".vibetime", CURSOR_CLOUD_USAGE_FILENAME);
|
|
@@ -7072,13 +7156,99 @@ function loadBubbles(db, composerId) {
|
|
|
7072
7156
|
});
|
|
7073
7157
|
return bubbles;
|
|
7074
7158
|
}
|
|
7159
|
+
function pathFromCursorResource(value) {
|
|
7160
|
+
const trimmed = value.trim();
|
|
7161
|
+
if (!trimmed) {
|
|
7162
|
+
return void 0;
|
|
7163
|
+
}
|
|
7164
|
+
const remote = trimmed.match(/^vscode-remote:\/\/[^/]+(\/.*)$/i);
|
|
7165
|
+
if (remote?.[1]) {
|
|
7166
|
+
try {
|
|
7167
|
+
return decodeURIComponent(remote[1]);
|
|
7168
|
+
} catch {
|
|
7169
|
+
return remote[1];
|
|
7170
|
+
}
|
|
7171
|
+
}
|
|
7172
|
+
if (trimmed.startsWith("file:")) {
|
|
7173
|
+
const rest = trimmed.slice("file://".length);
|
|
7174
|
+
try {
|
|
7175
|
+
return decodeURIComponent(rest);
|
|
7176
|
+
} catch {
|
|
7177
|
+
return rest;
|
|
7178
|
+
}
|
|
7179
|
+
}
|
|
7180
|
+
if (path13.isAbsolute(trimmed) || trimmed.startsWith("/")) {
|
|
7181
|
+
return trimmed;
|
|
7182
|
+
}
|
|
7183
|
+
return void 0;
|
|
7184
|
+
}
|
|
7185
|
+
function projectFromFolderPaths(folders, fallback) {
|
|
7186
|
+
const names = [...new Set(
|
|
7187
|
+
folders.map((folder) => path13.basename(folder.replace(/[\\/]+$/, ""))).filter(Boolean)
|
|
7188
|
+
)];
|
|
7189
|
+
if (names.length === 1) {
|
|
7190
|
+
return names[0];
|
|
7191
|
+
}
|
|
7192
|
+
if (names.length > 1) {
|
|
7193
|
+
return names.join("+");
|
|
7194
|
+
}
|
|
7195
|
+
return fallback;
|
|
7196
|
+
}
|
|
7197
|
+
function projectFallbackFromWorkspaceFile(filePath) {
|
|
7198
|
+
const base = path13.basename(filePath, ".code-workspace");
|
|
7199
|
+
const stripped = base.replace(/-workspace$/i, "").trim();
|
|
7200
|
+
return stripped || void 0;
|
|
7201
|
+
}
|
|
7202
|
+
function folderPathsFromCodeWorkspace(workspacePath) {
|
|
7203
|
+
let parsed;
|
|
7204
|
+
try {
|
|
7205
|
+
parsed = JSON.parse(readFileSync(workspacePath, "utf8"));
|
|
7206
|
+
} catch {
|
|
7207
|
+
return [];
|
|
7208
|
+
}
|
|
7209
|
+
if (!isPlainObject(parsed) || !Array.isArray(parsed.folders)) {
|
|
7210
|
+
return [];
|
|
7211
|
+
}
|
|
7212
|
+
const root = path13.dirname(workspacePath);
|
|
7213
|
+
const folders = [];
|
|
7214
|
+
for (const folder of parsed.folders) {
|
|
7215
|
+
if (!isPlainObject(folder)) {
|
|
7216
|
+
continue;
|
|
7217
|
+
}
|
|
7218
|
+
const uri = stringField(folder, "uri");
|
|
7219
|
+
if (uri) {
|
|
7220
|
+
const resolved = pathFromCursorResource(uri);
|
|
7221
|
+
if (resolved) {
|
|
7222
|
+
folders.push(resolved);
|
|
7223
|
+
}
|
|
7224
|
+
continue;
|
|
7225
|
+
}
|
|
7226
|
+
const relative = stringField(folder, "path");
|
|
7227
|
+
if (relative) {
|
|
7228
|
+
folders.push(path13.resolve(root, relative));
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7231
|
+
return folders;
|
|
7232
|
+
}
|
|
7075
7233
|
function workspaceFromComposer(data) {
|
|
7076
7234
|
const ident = objectField(data, "workspaceIdentifier");
|
|
7077
7235
|
const uri = objectField(ident, "uri");
|
|
7078
|
-
const
|
|
7236
|
+
const fromUri = stringField(uri, "fsPath") || stringField(uri, "path") || (stringField(uri, "external") ? pathFromCursorResource(stringField(uri, "external")) : void 0);
|
|
7237
|
+
if (fromUri) {
|
|
7238
|
+
return {
|
|
7239
|
+
cwd: fromUri,
|
|
7240
|
+
project: path13.basename(fromUri.replace(/[\\/]+$/, "")) || void 0
|
|
7241
|
+
};
|
|
7242
|
+
}
|
|
7243
|
+
const configPath2 = objectField(ident, "configPath");
|
|
7244
|
+
const workspaceFile = stringField(configPath2, "fsPath") || stringField(configPath2, "path") || (stringField(configPath2, "external") ? pathFromCursorResource(stringField(configPath2, "external")) : void 0);
|
|
7245
|
+
if (!workspaceFile) {
|
|
7246
|
+
return {};
|
|
7247
|
+
}
|
|
7248
|
+
const folders = folderPathsFromCodeWorkspace(workspaceFile);
|
|
7079
7249
|
return {
|
|
7080
|
-
cwd,
|
|
7081
|
-
project:
|
|
7250
|
+
cwd: folders[0],
|
|
7251
|
+
project: projectFromFolderPaths(folders, projectFallbackFromWorkspaceFile(workspaceFile))
|
|
7082
7252
|
};
|
|
7083
7253
|
}
|
|
7084
7254
|
function modelFromComposer(data) {
|
|
@@ -7614,6 +7784,7 @@ async function parseCursorTranscriptFile(filePath, options) {
|
|
|
7614
7784
|
push,
|
|
7615
7785
|
sessionId,
|
|
7616
7786
|
options,
|
|
7787
|
+
filePath,
|
|
7617
7788
|
fallbackTs: endedAt || lastTs,
|
|
7618
7789
|
lastTurnId,
|
|
7619
7790
|
model,
|
|
@@ -7627,7 +7798,7 @@ async function appendPersistedCursorUsage(args) {
|
|
|
7627
7798
|
}
|
|
7628
7799
|
emitPersistedCursorUsage(
|
|
7629
7800
|
args.push,
|
|
7630
|
-
await resolveCursorSessionUsage(args.options, args.sessionId),
|
|
7801
|
+
await resolveCursorSessionUsage(args.options, args.sessionId, args.filePath),
|
|
7631
7802
|
args.fallbackTs,
|
|
7632
7803
|
args.lastTurnId,
|
|
7633
7804
|
args.model,
|
|
@@ -7731,7 +7902,7 @@ async function parseCursorSessionFile(filePath, options) {
|
|
|
7731
7902
|
try {
|
|
7732
7903
|
const composers = listComposers(opened.db);
|
|
7733
7904
|
for (const composer of composers) {
|
|
7734
|
-
const usage = await resolveCursorSessionUsage(options, composer.composerId);
|
|
7905
|
+
const usage = await resolveCursorSessionUsage(options, composer.composerId, filePath);
|
|
7735
7906
|
events.push(...parseComposer(opened.db, composer, filePath, sourcePathHash, options, usage));
|
|
7736
7907
|
}
|
|
7737
7908
|
} finally {
|
|
@@ -8106,7 +8277,7 @@ async function grokBotBackfillFiles(sourceRoot, home = os7.homedir(), env, optio
|
|
|
8106
8277
|
function createGrokBotAdapter() {
|
|
8107
8278
|
return {
|
|
8108
8279
|
id: SOURCE_ID2,
|
|
8109
|
-
label: "
|
|
8280
|
+
label: "Cloud Agent",
|
|
8110
8281
|
agentName: AGENT_NAME2,
|
|
8111
8282
|
kind: "agent",
|
|
8112
8283
|
// No hooks to install — data arrives via the Cursor dashboard API.
|
|
@@ -15026,7 +15197,7 @@ async function uninstallGeneratedFile(filePath, { dryRun, onWrite }) {
|
|
|
15026
15197
|
|
|
15027
15198
|
// src/lib/config.ts
|
|
15028
15199
|
import { randomUUID } from "node:crypto";
|
|
15029
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
15200
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "node:fs";
|
|
15030
15201
|
import { homedir, hostname } from "node:os";
|
|
15031
15202
|
import path24 from "node:path";
|
|
15032
15203
|
function disabledBackfillSourceSet(config) {
|
|
@@ -15048,7 +15219,7 @@ function readConfig(home = homedir()) {
|
|
|
15048
15219
|
return {};
|
|
15049
15220
|
}
|
|
15050
15221
|
try {
|
|
15051
|
-
const parsed = JSON.parse(
|
|
15222
|
+
const parsed = JSON.parse(readFileSync2(file, "utf8"));
|
|
15052
15223
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
15053
15224
|
} catch {
|
|
15054
15225
|
return {};
|
|
@@ -15065,7 +15236,7 @@ function writeConfig(config, home = homedir()) {
|
|
|
15065
15236
|
function ensureLocalMachineId(home = homedir()) {
|
|
15066
15237
|
const file = machineIdPath(home);
|
|
15067
15238
|
if (existsSync2(file)) {
|
|
15068
|
-
const value =
|
|
15239
|
+
const value = readFileSync2(file, "utf8").trim();
|
|
15069
15240
|
if (value.length > 0) {
|
|
15070
15241
|
return value;
|
|
15071
15242
|
}
|
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.67",
|
|
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": {
|