@yhong91/vibetime 0.1.3 → 0.1.4

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 +65 -23
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -1195,7 +1195,7 @@ function countTextLines(text) {
1195
1195
  }
1196
1196
 
1197
1197
  // src/lib/constants.ts
1198
- var PACKAGE_VERSION = true ? "0.1.3" : "0.1.1";
1198
+ var PACKAGE_VERSION = true ? "0.1.4" : "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;
@@ -8072,7 +8072,7 @@ async function deleteMachine(remote, id) {
8072
8072
  }
8073
8073
 
8074
8074
  // src/lib/types.ts
8075
- var BACKFILL_STATE_SCHEMA_VERSION = 4;
8075
+ var BACKFILL_STATE_SCHEMA_VERSION = 5;
8076
8076
 
8077
8077
  // src/cli.ts
8078
8078
  function createRegistry() {
@@ -8593,10 +8593,12 @@ async function importBackfillPlan(plan, options, ctx, registry) {
8593
8593
  return 1;
8594
8594
  }
8595
8595
  const sourceDefs = registry.all().filter((a) => supportedSources.has(a.id) && (source === "all" || a.id === source)).map((a) => ({ id: a.id, label: a.label, paths: a.sourcePaths(home, ctx.env) }));
8596
+ const remote = resolveRemoteFromOptions(options, ctx);
8597
+ const remoteKey = backfillRemoteKey(remote?.baseUrl ?? DEFAULT_API_URL);
8596
8598
  if (options.force) {
8597
- await purgeForcedSources(sourceDefs, home, options, ctx);
8599
+ await purgeForcedSources(sourceDefs, home, remoteKey, options, ctx);
8598
8600
  }
8599
- const incrementalState = shouldUseIncrementalBackfill(options) ? await readBackfillIncrementalState(home, ctx) : void 0;
8601
+ const incrementalState = shouldUseIncrementalBackfill(options) ? await readBackfillIncrementalState(home, remoteKey, ctx) : void 0;
8600
8602
  if (!options.json) {
8601
8603
  write(ctx.stdout, `importRun ${plan.importRun.importRunId}
8602
8604
  `);
@@ -8624,13 +8626,15 @@ async function importBackfillPlan(plan, options, ctx, registry) {
8624
8626
  `);
8625
8627
  }
8626
8628
  if (counts.failed === 0 && counts.conflicts === 0 && incrementalState) {
8627
- await updateBackfillIncrementalState(home, incrementalState, selectedFilesBySource);
8629
+ await updateBackfillIncrementalState(home, remoteKey, incrementalState, selectedFilesBySource);
8628
8630
  }
8629
8631
  return counts.failed > 0 || counts.conflicts > 0 && !options["skip-conflicts"] ? 1 : 0;
8630
8632
  }
8631
- async function purgeForcedSources(sourceDefs, home, options, ctx) {
8633
+ async function purgeForcedSources(sourceDefs, home, remoteKey, options, ctx) {
8632
8634
  try {
8633
- await rm(backfillIncrementalStatePath(home), { force: true });
8635
+ const file = await readBackfillIncrementalStateFile(home);
8636
+ delete file.remotes[remoteKey];
8637
+ await writeBackfillIncrementalStateFile(home, file);
8634
8638
  } catch (error) {
8635
8639
  debug(ctx, `Failed to clear backfill watermark: ${error.message}
8636
8640
  `);
@@ -8826,36 +8830,75 @@ function syncLocalTriggerStatePath(home) {
8826
8830
  function syncLocalTriggerLockPath(home) {
8827
8831
  return path18.join(home, ".vibetime", "sync-local-trigger.lock");
8828
8832
  }
8829
- async function readBackfillIncrementalState(home, ctx) {
8833
+ function backfillRemoteKey(baseUrl) {
8834
+ try {
8835
+ const url = new URL(baseUrl);
8836
+ return `${url.protocol}//${url.host}${url.pathname.replace(/\/+$/, "")}`;
8837
+ } catch {
8838
+ return baseUrl.replace(/\/+$/, "");
8839
+ }
8840
+ }
8841
+ function sanitizeBackfillSources(raw) {
8842
+ const sources = {};
8843
+ if (!isPlainObject(raw)) {
8844
+ return sources;
8845
+ }
8846
+ for (const source of BACKFILL_SOURCE_IDS) {
8847
+ const item = raw[source];
8848
+ if (isPlainObject(item) && typeof item.watermarkTs === "string" && !Number.isNaN(Date.parse(item.watermarkTs))) {
8849
+ sources[source] = { watermarkTs: item.watermarkTs };
8850
+ }
8851
+ }
8852
+ return sources;
8853
+ }
8854
+ async function readBackfillIncrementalStateFile(home, ctx) {
8855
+ const empty = { version: BACKFILL_STATE_SCHEMA_VERSION, remotes: {} };
8830
8856
  const statePath = backfillIncrementalStatePath(home);
8831
8857
  const state = await readJsonIfExists(statePath);
8832
8858
  if (state === null) {
8833
- return { version: BACKFILL_STATE_SCHEMA_VERSION, sources: {} };
8859
+ return empty;
8834
8860
  }
8835
- if (!isPlainObject(state) || !isPlainObject(state.sources)) {
8861
+ if (!isPlainObject(state)) {
8836
8862
  if (ctx) {
8837
8863
  debug(ctx, `backfill-state malformed at ${statePath}; ignoring watermarks
8838
8864
  `);
8839
8865
  }
8840
- return { version: BACKFILL_STATE_SCHEMA_VERSION, sources: {} };
8866
+ return empty;
8841
8867
  }
8842
8868
  if (state.version !== BACKFILL_STATE_SCHEMA_VERSION) {
8843
8869
  if (ctx) {
8844
8870
  debug(ctx, `backfill-state version ${String(state.version)} at ${statePath} differs from current v${BACKFILL_STATE_SCHEMA_VERSION}; dropping watermarks so the next sync re-imports under the new parser
8845
8871
  `);
8846
8872
  }
8847
- return { version: BACKFILL_STATE_SCHEMA_VERSION, sources: {} };
8873
+ return empty;
8848
8874
  }
8849
- const sources = {};
8850
- for (const source of BACKFILL_SOURCE_IDS) {
8851
- const item = state.sources[source];
8852
- if (isPlainObject(item) && typeof item.watermarkTs === "string" && !Number.isNaN(Date.parse(item.watermarkTs))) {
8853
- sources[source] = { watermarkTs: item.watermarkTs };
8875
+ if (!isPlainObject(state.remotes)) {
8876
+ if (ctx) {
8877
+ debug(ctx, `backfill-state malformed at ${statePath}; ignoring watermarks
8878
+ `);
8879
+ }
8880
+ return empty;
8881
+ }
8882
+ const remotes = {};
8883
+ for (const [remoteKey, entry] of Object.entries(state.remotes)) {
8884
+ if (!isPlainObject(entry)) {
8885
+ continue;
8854
8886
  }
8887
+ remotes[remoteKey] = { sources: sanitizeBackfillSources(entry.sources) };
8855
8888
  }
8856
- return { version: BACKFILL_STATE_SCHEMA_VERSION, sources };
8889
+ return { version: BACKFILL_STATE_SCHEMA_VERSION, remotes };
8857
8890
  }
8858
- async function updateBackfillIncrementalState(home, state, selectedFilesBySource) {
8891
+ async function writeBackfillIncrementalStateFile(home, file) {
8892
+ const statePath = backfillIncrementalStatePath(home);
8893
+ await mkdir4(path18.dirname(statePath), { recursive: true });
8894
+ await writeFile3(statePath, `${JSON.stringify(file, null, 2)}
8895
+ `, "utf8");
8896
+ }
8897
+ async function readBackfillIncrementalState(home, remoteKey, ctx) {
8898
+ const file = await readBackfillIncrementalStateFile(home, ctx);
8899
+ return { version: BACKFILL_STATE_SCHEMA_VERSION, sources: file.remotes[remoteKey]?.sources ?? {} };
8900
+ }
8901
+ async function updateBackfillIncrementalState(home, remoteKey, state, selectedFilesBySource) {
8859
8902
  for (const [source, files] of selectedFilesBySource.entries()) {
8860
8903
  const latest = maxTimestamp(files.map((f) => f.modifiedAt));
8861
8904
  if (!latest) {
@@ -8863,10 +8906,9 @@ async function updateBackfillIncrementalState(home, state, selectedFilesBySource
8863
8906
  }
8864
8907
  state.sources[source] = { watermarkTs: latest };
8865
8908
  }
8866
- const statePath = backfillIncrementalStatePath(home);
8867
- await mkdir4(path18.dirname(statePath), { recursive: true });
8868
- await writeFile3(statePath, `${JSON.stringify(state, null, 2)}
8869
- `, "utf8");
8909
+ const file = await readBackfillIncrementalStateFile(home);
8910
+ file.remotes[remoteKey] = { sources: state.sources };
8911
+ await writeBackfillIncrementalStateFile(home, file);
8870
8912
  }
8871
8913
  async function readSyncLocalTriggerState(statePath) {
8872
8914
  let state;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yhong91/vibetime",
3
3
  "type": "module",
4
- "version": "0.1.3",
4
+ "version": "0.1.4",
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": {