@yhong91/vibetime 0.1.13 → 0.1.15
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 +151 -32
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -158,7 +158,7 @@ var init_fs = __esm({
|
|
|
158
158
|
});
|
|
159
159
|
|
|
160
160
|
// src/cli.ts
|
|
161
|
-
import { spawn } from "node:child_process";
|
|
161
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
162
162
|
import { mkdir as mkdir4, rename as rename2, rm, stat as stat11, writeFile as writeFile3 } from "node:fs/promises";
|
|
163
163
|
import os8 from "node:os";
|
|
164
164
|
import path19 from "node:path";
|
|
@@ -1195,7 +1195,7 @@ function countTextLines(text) {
|
|
|
1195
1195
|
}
|
|
1196
1196
|
|
|
1197
1197
|
// src/lib/constants.ts
|
|
1198
|
-
var PACKAGE_VERSION = true ? "0.1.
|
|
1198
|
+
var PACKAGE_VERSION = true ? "0.1.15" : "0.1.1";
|
|
1199
1199
|
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
1200
1200
|
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
1201
1201
|
var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
|
|
@@ -3770,6 +3770,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
3770
3770
|
let model;
|
|
3771
3771
|
let sessionStartEmitted = false;
|
|
3772
3772
|
let serviceTier;
|
|
3773
|
+
let reasoningEffort;
|
|
3773
3774
|
let currentTurnId;
|
|
3774
3775
|
let lastTurnIdForComplete;
|
|
3775
3776
|
let turnIdAtLastUserMessage;
|
|
@@ -3816,6 +3817,10 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
3816
3817
|
cwd = stringField(payload, "cwd") || cwd;
|
|
3817
3818
|
project = cwd ? path9.basename(cwd) : project;
|
|
3818
3819
|
model = stringField(payload, "model") || model;
|
|
3820
|
+
const effort = stringField(payload, "effort") || stringField(objectField(objectField(payload, "collaboration_mode"), "settings"), "reasoning_effort");
|
|
3821
|
+
if (effort) {
|
|
3822
|
+
reasoningEffort = effort;
|
|
3823
|
+
}
|
|
3819
3824
|
const tier = stringField(payload, "service_tier");
|
|
3820
3825
|
if (tier) {
|
|
3821
3826
|
serviceTier = tier.toLowerCase();
|
|
@@ -3916,6 +3921,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
3916
3921
|
}
|
|
3917
3922
|
const usage = tokenUsageFromPayload(payload);
|
|
3918
3923
|
if (usage) {
|
|
3924
|
+
const metrics = { ...usage, reasoningEffort };
|
|
3919
3925
|
const usageKey = [
|
|
3920
3926
|
usage.tokensInput,
|
|
3921
3927
|
usage.tokensCachedInput,
|
|
@@ -3939,7 +3945,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
3939
3945
|
// model was the user on") don't show tier-specific names.
|
|
3940
3946
|
model: rewriteCodexModelForTier(model, serviceTier),
|
|
3941
3947
|
confidence: "partial",
|
|
3942
|
-
metrics
|
|
3948
|
+
metrics
|
|
3943
3949
|
}), { filePath, sourcePathHash, lineNumber, topType, payloadType, options }));
|
|
3944
3950
|
}
|
|
3945
3951
|
break;
|
|
@@ -4333,6 +4339,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
4333
4339
|
let model;
|
|
4334
4340
|
let currentTurnId;
|
|
4335
4341
|
let sessionStartedAt;
|
|
4342
|
+
let reasoningEffort;
|
|
4336
4343
|
const pendingTools = /* @__PURE__ */ new Map();
|
|
4337
4344
|
const turnTokenAccum = /* @__PURE__ */ new Map();
|
|
4338
4345
|
for (const [index, line] of lines.entries()) {
|
|
@@ -4351,6 +4358,10 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
4351
4358
|
case "session.start": {
|
|
4352
4359
|
sessionId = stringField(data, "sessionId") || sessionId;
|
|
4353
4360
|
model = stringField(data, "selectedModel") || model;
|
|
4361
|
+
const effort = stringField(data, "reasoningEffort");
|
|
4362
|
+
if (effort) {
|
|
4363
|
+
reasoningEffort = effort;
|
|
4364
|
+
}
|
|
4354
4365
|
const context = objectField(data, "context");
|
|
4355
4366
|
cwd = stringField(context, "cwd") || stringField(context, "gitRoot") || cwd;
|
|
4356
4367
|
project = stringField(context, "repository") || (cwd ? path10.basename(cwd) : void 0);
|
|
@@ -4494,6 +4505,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
4494
4505
|
const turnId = endTurnId !== void 0 ? `turn_${createStableHash([sessionId, endTurnId]).slice(0, 24)}` : currentTurnId;
|
|
4495
4506
|
const accum = turnId ? turnTokenAccum.get(turnId) : void 0;
|
|
4496
4507
|
if (accum && accum.tokensOutput && accum.tokensOutput > 0) {
|
|
4508
|
+
accum.reasoningEffort = reasoningEffort;
|
|
4497
4509
|
events.push(baseCopilotEvent({
|
|
4498
4510
|
ts,
|
|
4499
4511
|
type: "model.usage",
|
|
@@ -4553,6 +4565,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
4553
4565
|
tokensCacheReadInput: cacheReadTokens || void 0,
|
|
4554
4566
|
tokensCacheCreationInput: cacheWriteTokens || void 0,
|
|
4555
4567
|
tokensReasoningOutput: reasoningTokens || void 0,
|
|
4568
|
+
reasoningEffort,
|
|
4556
4569
|
tokensTotal: total,
|
|
4557
4570
|
modelCalls: requestCount || void 0
|
|
4558
4571
|
}
|
|
@@ -4700,6 +4713,20 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
4700
4713
|
let currentTurnId;
|
|
4701
4714
|
let currentProvider;
|
|
4702
4715
|
let turnTs;
|
|
4716
|
+
let reasoningEffort;
|
|
4717
|
+
const modelSwitchedEvents = db.prepare(
|
|
4718
|
+
"SELECT data FROM event WHERE aggregate_id = ? AND type = 'session.next.model.switched.1' ORDER BY seq"
|
|
4719
|
+
).all(sessionId);
|
|
4720
|
+
for (const evt of modelSwitchedEvents) {
|
|
4721
|
+
try {
|
|
4722
|
+
const evtData = JSON.parse(evt.data);
|
|
4723
|
+
const variant = isPlainObject(evtData) ? stringField(evtData.model || evtData, "variant") : void 0;
|
|
4724
|
+
if (variant && variant !== "default") {
|
|
4725
|
+
reasoningEffort = variant;
|
|
4726
|
+
}
|
|
4727
|
+
} catch {
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
4703
4730
|
for (const msg of messages) {
|
|
4704
4731
|
let info;
|
|
4705
4732
|
try {
|
|
@@ -4791,7 +4818,8 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
4791
4818
|
tokensCachedInput: tokens.tokensCachedInput,
|
|
4792
4819
|
tokensCacheReadInput: tokens.tokensCacheReadInput,
|
|
4793
4820
|
tokensCacheCreationInput: tokens.tokensCacheCreationInput,
|
|
4794
|
-
tokensTotal: tokens.tokensTotal
|
|
4821
|
+
tokensTotal: tokens.tokensTotal,
|
|
4822
|
+
reasoningEffort
|
|
4795
4823
|
};
|
|
4796
4824
|
if (cost !== void 0) {
|
|
4797
4825
|
metrics.costUsd = cost;
|
|
@@ -4916,7 +4944,8 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
4916
4944
|
tokensCachedInput: stepTokens.tokensCachedInput,
|
|
4917
4945
|
tokensCacheReadInput: stepTokens.tokensCacheReadInput,
|
|
4918
4946
|
tokensCacheCreationInput: stepTokens.tokensCacheCreationInput,
|
|
4919
|
-
tokensTotal: stepTokens.tokensTotal
|
|
4947
|
+
tokensTotal: stepTokens.tokensTotal,
|
|
4948
|
+
reasoningEffort
|
|
4920
4949
|
};
|
|
4921
4950
|
if (stepCost !== void 0) {
|
|
4922
4951
|
stepMetrics.costUsd = stepCost;
|
|
@@ -5067,34 +5096,43 @@ export const AgentTime = async ({ $, directory }) => {
|
|
|
5067
5096
|
}
|
|
5068
5097
|
|
|
5069
5098
|
return {
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
session_id: ctx?.id,
|
|
5074
|
-
cwd: directory
|
|
5075
|
-
})
|
|
5076
|
-
},
|
|
5077
|
-
"session.idle": async (ctx) => {
|
|
5078
|
-
await report({
|
|
5079
|
-
hook_event_name: "SessionEnd",
|
|
5080
|
-
session_id: ctx?.id,
|
|
5081
|
-
cwd: directory
|
|
5082
|
-
})
|
|
5083
|
-
},
|
|
5084
|
-
"tool.execute.after": async (input) => {
|
|
5085
|
-
const toolName = input?.tool || "unknown"
|
|
5086
|
-
const toolCallId = input?.toolCallId
|
|
5087
|
-
const toolInput = input?.args || input?.input || {}
|
|
5088
|
-
const command = toolInput?.command
|
|
5089
|
-
const filePath = toolInput?.file_path || toolInput?.filePath
|
|
5099
|
+
event: async ({ event }) => {
|
|
5100
|
+
const type = event?.type
|
|
5101
|
+
const props = event?.properties || {}
|
|
5090
5102
|
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5103
|
+
if (type === "session.created") {
|
|
5104
|
+
await report({
|
|
5105
|
+
hook_event_name: "SessionStart",
|
|
5106
|
+
session_id: event?.sessionID || event?.sessionId || props?.session?.id || event?.id,
|
|
5107
|
+
cwd: directory
|
|
5108
|
+
})
|
|
5109
|
+
return
|
|
5110
|
+
}
|
|
5111
|
+
|
|
5112
|
+
if (type === "session.idle") {
|
|
5113
|
+
await report({
|
|
5114
|
+
hook_event_name: "SessionEnd",
|
|
5115
|
+
session_id: event?.sessionID || event?.sessionId || props?.session?.id || event?.id,
|
|
5116
|
+
cwd: directory
|
|
5117
|
+
})
|
|
5118
|
+
return
|
|
5119
|
+
}
|
|
5120
|
+
|
|
5121
|
+
if (type === "tool.execute.after") {
|
|
5122
|
+
const toolName = props?.tool || event?.tool || "unknown"
|
|
5123
|
+
const toolCallId = props?.toolCallId || event?.toolCallId
|
|
5124
|
+
const toolInput = props?.args || props?.input || {}
|
|
5125
|
+
const command = toolInput?.command
|
|
5126
|
+
const filePath = toolInput?.file_path || toolInput?.filePath
|
|
5127
|
+
|
|
5128
|
+
await report({
|
|
5129
|
+
hook_event_name: "PostToolUse",
|
|
5130
|
+
tool_name: toolName,
|
|
5131
|
+
tool_use_id: toolCallId,
|
|
5132
|
+
cwd: directory,
|
|
5133
|
+
tool_input: { command, file_path: filePath }
|
|
5134
|
+
})
|
|
5135
|
+
}
|
|
5098
5136
|
}
|
|
5099
5137
|
}
|
|
5100
5138
|
}
|
|
@@ -5149,6 +5187,7 @@ async function parsePiSessionFile(filePath, options) {
|
|
|
5149
5187
|
let model;
|
|
5150
5188
|
let provider;
|
|
5151
5189
|
let turnStartedAt;
|
|
5190
|
+
let reasoningEffort;
|
|
5152
5191
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
5153
5192
|
const state = new SessionParserState(filePath, options, (event) => basePiEvent({ ...event, cwd, project, model }));
|
|
5154
5193
|
const push = (event, ln) => {
|
|
@@ -5179,6 +5218,13 @@ async function parsePiSessionFile(filePath, options) {
|
|
|
5179
5218
|
provider = stringField(raw, "provider") || provider;
|
|
5180
5219
|
continue;
|
|
5181
5220
|
}
|
|
5221
|
+
if (entryType === "thinking_level_change") {
|
|
5222
|
+
const level = stringField(raw, "thinkingLevel");
|
|
5223
|
+
if (level) {
|
|
5224
|
+
reasoningEffort = level;
|
|
5225
|
+
}
|
|
5226
|
+
continue;
|
|
5227
|
+
}
|
|
5182
5228
|
if (entryType !== "message") {
|
|
5183
5229
|
continue;
|
|
5184
5230
|
}
|
|
@@ -5228,6 +5274,7 @@ async function parsePiSessionFile(filePath, options) {
|
|
|
5228
5274
|
provider = stringField(message, "provider") || provider;
|
|
5229
5275
|
const usage = piUsageFromMessage(message);
|
|
5230
5276
|
if (usage) {
|
|
5277
|
+
usage.reasoningEffort = reasoningEffort;
|
|
5231
5278
|
push(basePiEvent({
|
|
5232
5279
|
ts,
|
|
5233
5280
|
type: "model.usage",
|
|
@@ -7948,6 +7995,7 @@ function buildSessionRollup(rollupKey, events) {
|
|
|
7948
7995
|
let cacheReadInputTokens = 0;
|
|
7949
7996
|
let outputTokens = 0;
|
|
7950
7997
|
let reasoningOutputTokens = 0;
|
|
7998
|
+
let reasoningEffort;
|
|
7951
7999
|
let totalTokens = 0;
|
|
7952
8000
|
let linesAdded = 0;
|
|
7953
8001
|
let linesRemoved = 0;
|
|
@@ -8042,6 +8090,9 @@ function buildSessionRollup(rollupKey, events) {
|
|
|
8042
8090
|
cacheReadInputTokens += eventCacheReadInputTokens;
|
|
8043
8091
|
outputTokens += eventOutputTokens;
|
|
8044
8092
|
reasoningOutputTokens += eventReasoningOutputTokens;
|
|
8093
|
+
if (event.metrics?.reasoningEffort) {
|
|
8094
|
+
reasoningEffort = event.metrics.reasoningEffort;
|
|
8095
|
+
}
|
|
8045
8096
|
totalTokens += eventTotalTokens;
|
|
8046
8097
|
linesAdded += lineStats.linesAdded;
|
|
8047
8098
|
linesRemoved += lineStats.linesRemoved;
|
|
@@ -8173,6 +8224,7 @@ function buildSessionRollup(rollupKey, events) {
|
|
|
8173
8224
|
cacheReadInputTokens,
|
|
8174
8225
|
outputTokens,
|
|
8175
8226
|
reasoningOutputTokens,
|
|
8227
|
+
reasoningEffort,
|
|
8176
8228
|
totalTokens,
|
|
8177
8229
|
linesAdded,
|
|
8178
8230
|
linesRemoved,
|
|
@@ -8712,6 +8764,7 @@ function createCli(ctx, registry) {
|
|
|
8712
8764
|
});
|
|
8713
8765
|
cli.command("detect", "Show supported local targets and install status").action((options) => detectCommand(normalizeOptions(options), ctx, registry).then(() => 0));
|
|
8714
8766
|
cli.command("install", "Install integration files into detected or requested targets").option("--target <targets>", "Target integrations, comma-separated").option("--targets <targets>", "Target integrations, comma-separated").option("--all", "Install all supported integrations").option("--force", "Overwrite existing non-generated files when needed").action((options) => installCommand(normalizeOptions(options), ctx, registry));
|
|
8767
|
+
cli.command("upgrade", "Check for updates and upgrade to the latest version").option("--check", "Only check for updates, do not install").action((options) => upgradeCommand(normalizeOptions(options), ctx, registry));
|
|
8715
8768
|
cli.command("hook", "Read agent hook JSON from stdin and report a throttled event").option("--agent <name>", "Agent name").option("--project <name>", "Project name").option("--min-interval <seconds>", "Minimum seconds between similar hook reports").action((options) => hookCommand(normalizeOptions(options), ctx));
|
|
8716
8769
|
cli.command("sync-local-trigger", "Trigger one background local sync with throttle and locking").option("--min-interval <seconds>", "Minimum seconds between sync triggers").action((options) => syncLocalTriggerCommand(normalizeOptions(options), ctx, registry));
|
|
8717
8770
|
cli.command("sync-local-runner", "Internal background local sync runner").option("--lock-file <path>", "Lock file for the active sync").option("--state-file <path>", "State file for trigger metadata").action((options) => syncLocalRunnerCommand(normalizeOptions(options), ctx, registry));
|
|
@@ -8806,6 +8859,70 @@ async function installCommand(options, ctx, registry) {
|
|
|
8806
8859
|
}
|
|
8807
8860
|
return 0;
|
|
8808
8861
|
}
|
|
8862
|
+
var NPM_PACKAGE = "@yhong91/vibetime";
|
|
8863
|
+
async function fetchLatestVersion() {
|
|
8864
|
+
try {
|
|
8865
|
+
const response = await fetch(`https://registry.npmjs.org/${NPM_PACKAGE}/latest`, {
|
|
8866
|
+
headers: { Accept: "application/json" },
|
|
8867
|
+
signal: AbortSignal.timeout(1e4)
|
|
8868
|
+
});
|
|
8869
|
+
if (!response.ok) return null;
|
|
8870
|
+
const data = await response.json();
|
|
8871
|
+
return typeof data.version === "string" ? data.version : null;
|
|
8872
|
+
} catch {
|
|
8873
|
+
return null;
|
|
8874
|
+
}
|
|
8875
|
+
}
|
|
8876
|
+
function compareVersions(a, b) {
|
|
8877
|
+
const pa = a.split(".").map(Number);
|
|
8878
|
+
const pb = b.split(".").map(Number);
|
|
8879
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
8880
|
+
const na = pa[i] ?? 0;
|
|
8881
|
+
const nb = pb[i] ?? 0;
|
|
8882
|
+
if (na > nb) return 1;
|
|
8883
|
+
if (na < nb) return -1;
|
|
8884
|
+
}
|
|
8885
|
+
return 0;
|
|
8886
|
+
}
|
|
8887
|
+
async function upgradeCommand(options, ctx, registry) {
|
|
8888
|
+
const current = PACKAGE_VERSION;
|
|
8889
|
+
write(ctx.stdout, `Current version: ${current}
|
|
8890
|
+
`);
|
|
8891
|
+
write(ctx.stdout, "Checking npm registry...\n");
|
|
8892
|
+
const latest = await fetchLatestVersion();
|
|
8893
|
+
if (!latest) {
|
|
8894
|
+
write(ctx.stderr, "Could not fetch latest version from npm. Check your network connection.\n");
|
|
8895
|
+
return 1;
|
|
8896
|
+
}
|
|
8897
|
+
if (compareVersions(current, latest) >= 0) {
|
|
8898
|
+
write(ctx.stdout, `Already up to date (${current}).
|
|
8899
|
+
`);
|
|
8900
|
+
return 0;
|
|
8901
|
+
}
|
|
8902
|
+
write(ctx.stdout, `New version available: ${latest}
|
|
8903
|
+
`);
|
|
8904
|
+
if (options.check) {
|
|
8905
|
+
write(ctx.stdout, `Run \`vibetime upgrade\` to install.
|
|
8906
|
+
`);
|
|
8907
|
+
return 0;
|
|
8908
|
+
}
|
|
8909
|
+
write(ctx.stdout, `Installing ${NPM_PACKAGE}@${latest}...
|
|
8910
|
+
|
|
8911
|
+
`);
|
|
8912
|
+
const result = spawnSync("npm", ["install", "-g", `${NPM_PACKAGE}@latest`], {
|
|
8913
|
+
stdio: "inherit"
|
|
8914
|
+
});
|
|
8915
|
+
if (result.status !== 0) {
|
|
8916
|
+
write(ctx.stderr, "\nFailed to install update. Try manually: npm install -g @yhong91/vibetime@latest\n");
|
|
8917
|
+
return 1;
|
|
8918
|
+
}
|
|
8919
|
+
write(ctx.stdout, "\nRefreshing integration hooks...\n");
|
|
8920
|
+
await installCommand({ ...options, all: true, _: [] }, ctx, registry);
|
|
8921
|
+
write(ctx.stdout, `
|
|
8922
|
+
Upgraded ${current} \u2192 ${latest}
|
|
8923
|
+
`);
|
|
8924
|
+
return 0;
|
|
8925
|
+
}
|
|
8809
8926
|
async function hookCommand(options, ctx) {
|
|
8810
8927
|
const home = resolveHome2(options, ctx);
|
|
8811
8928
|
try {
|
|
@@ -9760,6 +9877,7 @@ function helpText() {
|
|
|
9760
9877
|
Usage:
|
|
9761
9878
|
vibetime detect [--json] [--home <path>]
|
|
9762
9879
|
vibetime install [--target codex,claude,opencode,pi] [--all] [--dry-run] [--force] [--home <path>]
|
|
9880
|
+
vibetime upgrade [--check]
|
|
9763
9881
|
vibetime hook --agent <name>
|
|
9764
9882
|
vibetime backfill discover|plan|import|verify --source codex|claude-code|opencode|pi|all --dry-run [--json] [--batch-size <count>]
|
|
9765
9883
|
vibetime token set <token>
|
|
@@ -9773,6 +9891,7 @@ Setup:
|
|
|
9773
9891
|
Commands:
|
|
9774
9892
|
detect Show supported local targets and install status.
|
|
9775
9893
|
install Install integration files into detected or requested targets.
|
|
9894
|
+
upgrade Check for updates and upgrade to the latest version.
|
|
9776
9895
|
hook Read agent hook JSON from stdin and report a throttled event.
|
|
9777
9896
|
backfill Discover local history and create metadata-only import plans.
|
|
9778
9897
|
token Set, show, or clear the persisted API token.
|
package/package.json
CHANGED