@yhong91/vibetime 0.1.43 → 0.1.44

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 +51 -18
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -1845,7 +1845,7 @@ function operationForTool(tool) {
1845
1845
  if (["write"].includes(normalized)) {
1846
1846
  return "write";
1847
1847
  }
1848
- if (["edit", "multiedit", "notebookedit", "apply_patch", "applypatch"].includes(normalized)) {
1848
+ if (["edit", "multiedit", "notebookedit", "apply_patch", "applypatch", "searchreplace"].includes(normalized)) {
1849
1849
  return "edit";
1850
1850
  }
1851
1851
  return "read";
@@ -1928,7 +1928,7 @@ function countTextLines(text) {
1928
1928
  }
1929
1929
 
1930
1930
  // src/lib/constants.ts
1931
- var PACKAGE_VERSION = true ? "0.1.43" : "0.1.1";
1931
+ var PACKAGE_VERSION = true ? "0.1.44" : "0.1.1";
1932
1932
  var DEFAULT_API_URL = "http://121.196.224.82:3001";
1933
1933
  var DEFAULT_BACKFILL_BATCH_SIZE = 50;
1934
1934
  var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
@@ -8150,7 +8150,11 @@ async function parseQoderCnSessionFile(filePath, options) {
8150
8150
  const mapped = {
8151
8151
  ...event,
8152
8152
  sessionId: parentSessionId,
8153
- refs: { ...event.refs, sourcePathHash: parentSourcePathHash }
8153
+ refs: {
8154
+ ...event.refs,
8155
+ sourcePathHash: parentSourcePathHash,
8156
+ ...event.sessionId && event.sessionId !== parentSessionId ? { supersededSessionId: event.sessionId } : {}
8157
+ }
8154
8158
  };
8155
8159
  return rebuildEventIdentity2(mapped);
8156
8160
  });
@@ -8163,7 +8167,11 @@ async function parseQoderCnSessionFile(filePath, options) {
8163
8167
  return validEvents.map((event) => rebuildEventIdentity2({
8164
8168
  ...event,
8165
8169
  sessionId: dbModelCalls.rootSessionId,
8166
- refs: { ...event.refs, sourcePathHash: parentSourcePathHash }
8170
+ refs: {
8171
+ ...event.refs,
8172
+ sourcePathHash: parentSourcePathHash,
8173
+ ...event.sessionId && event.sessionId !== dbModelCalls.rootSessionId ? { supersededSessionId: event.sessionId } : {}
8174
+ }
8167
8175
  }));
8168
8176
  }
8169
8177
  return validEvents;
@@ -8210,7 +8218,7 @@ function fileActivitiesFromQoderCnToolUse(tool, input, ts, cwd) {
8210
8218
  const metrics = fileMetricsFromQoderCnToolInput(tool, input);
8211
8219
  addResolvedPathActivity(changes, filePath, operation, ts, cwd, workdir, metrics);
8212
8220
  }
8213
- for (const edit of arrayField4(input, "edits")) {
8221
+ for (const edit of [...arrayField4(input, "edits"), ...arrayField4(input, "replacements")]) {
8214
8222
  if (!isPlainObject(edit)) {
8215
8223
  continue;
8216
8224
  }
@@ -8219,8 +8227,8 @@ function fileActivitiesFromQoderCnToolUse(tool, input, ts, cwd) {
8219
8227
  continue;
8220
8228
  }
8221
8229
  addResolvedPathActivity(changes, filePath, "edit", ts, cwd, workdir, {
8222
- linesAdded: countTextLines(stringField(edit, "new_string")),
8223
- linesRemoved: countTextLines(stringField(edit, "old_string"))
8230
+ linesAdded: countTextLines(stringField(edit, "new_string") || stringField(edit, "new_text")),
8231
+ linesRemoved: countTextLines(stringField(edit, "old_string") || stringField(edit, "original_text"))
8224
8232
  });
8225
8233
  }
8226
8234
  const command = stringField(input, "command");
@@ -8237,13 +8245,13 @@ function fileMetricsFromQoderCnToolInput(tool, input) {
8237
8245
  return { linesRead: numberField(input, "limit") };
8238
8246
  }
8239
8247
  if (normalized === "write") {
8240
- const content = stringField(input, "content");
8248
+ const content = stringField(input, "content") || stringField(input, "file_content");
8241
8249
  return {
8242
8250
  linesAdded: countTextLines(content),
8243
8251
  charsWritten: content?.length
8244
8252
  };
8245
8253
  }
8246
- if (normalized === "edit" || normalized === "multiedit") {
8254
+ if (normalized === "edit" || normalized === "multiedit" || normalized === "searchreplace") {
8247
8255
  const oldString = stringField(input, "old_string");
8248
8256
  const newString = stringField(input, "new_string");
8249
8257
  return {
@@ -8976,7 +8984,11 @@ async function parseQoderSessionFile(filePath, options) {
8976
8984
  const mapped = {
8977
8985
  ...event,
8978
8986
  sessionId: parentSessionId,
8979
- refs: { ...event.refs, sourcePathHash: parentSourcePathHash }
8987
+ refs: {
8988
+ ...event.refs,
8989
+ sourcePathHash: parentSourcePathHash,
8990
+ ...event.sessionId && event.sessionId !== parentSessionId ? { supersededSessionId: event.sessionId } : {}
8991
+ }
8980
8992
  };
8981
8993
  return rebuildEventIdentity3(mapped);
8982
8994
  });
@@ -8989,7 +9001,11 @@ async function parseQoderSessionFile(filePath, options) {
8989
9001
  return validEvents.map((event) => rebuildEventIdentity3({
8990
9002
  ...event,
8991
9003
  sessionId: dbModelCalls.rootSessionId,
8992
- refs: { ...event.refs, sourcePathHash: parentSourcePathHash }
9004
+ refs: {
9005
+ ...event.refs,
9006
+ sourcePathHash: parentSourcePathHash,
9007
+ ...event.sessionId && event.sessionId !== dbModelCalls.rootSessionId ? { supersededSessionId: event.sessionId } : {}
9008
+ }
8993
9009
  }));
8994
9010
  }
8995
9011
  return validEvents;
@@ -9036,7 +9052,7 @@ function fileActivitiesFromQoderToolUse(tool, input, ts, cwd) {
9036
9052
  const metrics = fileMetricsFromQoderToolInput(tool, input);
9037
9053
  addResolvedPathActivity(changes, filePath, operation, ts, cwd, workdir, metrics);
9038
9054
  }
9039
- for (const edit of arrayField5(input, "edits")) {
9055
+ for (const edit of [...arrayField5(input, "edits"), ...arrayField5(input, "replacements")]) {
9040
9056
  if (!isPlainObject(edit)) {
9041
9057
  continue;
9042
9058
  }
@@ -9045,8 +9061,8 @@ function fileActivitiesFromQoderToolUse(tool, input, ts, cwd) {
9045
9061
  continue;
9046
9062
  }
9047
9063
  addResolvedPathActivity(changes, filePath, "edit", ts, cwd, workdir, {
9048
- linesAdded: countTextLines(stringField(edit, "new_string")),
9049
- linesRemoved: countTextLines(stringField(edit, "old_string"))
9064
+ linesAdded: countTextLines(stringField(edit, "new_string") || stringField(edit, "new_text")),
9065
+ linesRemoved: countTextLines(stringField(edit, "old_string") || stringField(edit, "original_text"))
9050
9066
  });
9051
9067
  }
9052
9068
  const command = stringField(input, "command");
@@ -9063,13 +9079,13 @@ function fileMetricsFromQoderToolInput(tool, input) {
9063
9079
  return { linesRead: numberField(input, "limit") };
9064
9080
  }
9065
9081
  if (normalized === "write") {
9066
- const content = stringField(input, "content");
9082
+ const content = stringField(input, "content") || stringField(input, "file_content");
9067
9083
  return {
9068
9084
  linesAdded: countTextLines(content),
9069
9085
  charsWritten: content?.length
9070
9086
  };
9071
9087
  }
9072
- if (normalized === "edit" || normalized === "multiedit") {
9088
+ if (normalized === "edit" || normalized === "multiedit" || normalized === "searchreplace") {
9073
9089
  const oldString = stringField(input, "old_string");
9074
9090
  const newString = stringField(input, "new_string");
9075
9091
  return {
@@ -10758,6 +10774,7 @@ function buildSessionRollup(rollupKey, events) {
10758
10774
  const agent = first.agent || ordered.find((event) => event.agent)?.agent;
10759
10775
  const startedAt = ordered[0]?.ts || (/* @__PURE__ */ new Date()).toISOString();
10760
10776
  const lastEventAt = ordered.at(-1)?.ts || startedAt;
10777
+ const supersededSessionIds = [...new Set(ordered.map((event) => event.refs?.supersededSessionId).filter((id) => Boolean(id) && id !== sessionId))];
10761
10778
  const timeBuckets = /* @__PURE__ */ new Map();
10762
10779
  const modelRollups = /* @__PURE__ */ new Map();
10763
10780
  const toolRollups = /* @__PURE__ */ new Map();
@@ -11040,7 +11057,8 @@ function buildSessionRollup(rollupKey, events) {
11040
11057
  startedAt: startedAt2,
11041
11058
  durationMs: timing?.lastCallAt ? Math.max(0, Date.parse(timing.lastCallAt) - Date.parse(startedAt2)) : 0
11042
11059
  };
11043
- }).sort((a, b) => a.startedAt.localeCompare(b.startedAt))
11060
+ }).sort((a, b) => a.startedAt.localeCompare(b.startedAt)),
11061
+ ...supersededSessionIds.length > 0 ? { supersededSessionIds } : {}
11044
11062
  };
11045
11063
  return {
11046
11064
  ...baseRollup,
@@ -11454,7 +11472,7 @@ async function postRollupBatch(remote, rollups, options = {}) {
11454
11472
  };
11455
11473
  }
11456
11474
  async function deleteRollupsBySource(remote, source, machine, options = {}) {
11457
- const query = `source=${encodeURIComponent(source)}${options.preserveTokens ? "&preserveTokens=1" : ""}${options.allowHistoricalRewrite ? "&allowHistoricalRewrite=1" : ""}`;
11475
+ const query = `source=${encodeURIComponent(source)}${options.rollupKey ? `&rollupKey=${encodeURIComponent(options.rollupKey)}` : ""}${options.preserveTokens ? "&preserveTokens=1" : ""}${options.allowHistoricalRewrite ? "&allowHistoricalRewrite=1" : ""}`;
11458
11476
  const response = await remote.fetchImpl(
11459
11477
  joinUrl(remote.baseUrl, `/v3/agent/sessions?${query}`),
11460
11478
  { method: "DELETE", headers: buildHeaders(remote.token, machine) }
@@ -12311,6 +12329,21 @@ async function sendSessionRollupBatch(rollups, options, ctx) {
12311
12329
  machine,
12312
12330
  allowHistoricalRewrite: options["purge-all"] === true
12313
12331
  });
12332
+ if (options.force && result.conflicts === 0) {
12333
+ for (const rollup of rollups) {
12334
+ for (const sessionId of rollup.supersededSessionIds ?? []) {
12335
+ try {
12336
+ await deleteRollupsBySource(remote, rollup.source, machine, {
12337
+ rollupKey: createImportKey(["rollup", rollup.source, sessionId]),
12338
+ allowHistoricalRewrite: options["purge-all"] === true
12339
+ });
12340
+ } catch (error) {
12341
+ debug(ctx, `Failed to delete superseded ${rollup.source} session ${sessionId}: ${error.message}
12342
+ `);
12343
+ }
12344
+ }
12345
+ }
12346
+ }
12314
12347
  return result;
12315
12348
  }
12316
12349
  async function deleteSessionRollupsBySourceAPI(source, options, ctx, preserveTokens) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yhong91/vibetime",
3
3
  "type": "module",
4
- "version": "0.1.43",
4
+ "version": "0.1.44",
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": {