@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.
Files changed (2) hide show
  1. package/bin/vibetime.mjs +151 -32
  2. 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.13" : "0.1.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: usage
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
- "session.created": async (ctx) => {
5071
- await report({
5072
- hook_event_name: "SessionStart",
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
- await report({
5092
- hook_event_name: "PostToolUse",
5093
- tool_name: toolName,
5094
- tool_use_id: toolCallId,
5095
- cwd: directory,
5096
- tool_input: { command, file_path: filePath }
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yhong91/vibetime",
3
3
  "type": "module",
4
- "version": "0.1.13",
4
+ "version": "0.1.15",
5
5
  "description": "vibetime CLI — install AI-agent hooks (Claude Code, Codex, OpenCode, Pi) and report activity to vibetime.",
6
6
  "license": "MIT",
7
7
  "publishConfig": {