@yhong91/vibetime 0.1.70 → 0.1.72

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 +972 -279
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -884,9 +884,9 @@ var init_esm = __esm({
884
884
 
885
885
  // src/cli.ts
886
886
  import { spawn as spawn2, spawnSync } from "node:child_process";
887
- import { mkdir as mkdir6, open, rm, stat as stat17, writeFile as writeFile5 } from "node:fs/promises";
887
+ import { mkdir as mkdir6, open, rm, stat as stat18, writeFile as writeFile5 } from "node:fs/promises";
888
888
  import os14 from "node:os";
889
- import path26 from "node:path";
889
+ import path27 from "node:path";
890
890
  import { fileURLToPath } from "node:url";
891
891
 
892
892
  // ../shared/src/index.ts
@@ -924,7 +924,7 @@ var TELEMETRY_EVENT_TYPES = [
924
924
  "agent.operation"
925
925
  ];
926
926
  var FILE_ACTIVITY_OPERATIONS = ["read", "search", "create", "write", "edit", "delete"];
927
- var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "copilot", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn", "workbuddy", "zcode", "grok-build", "zed", "kimi-code", "cursor", "grok-bot"];
927
+ var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "copilot", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn", "workbuddy", "zcode", "grok-build", "zed", "kimi-code", "cursor", "grok-bot", "hermes"];
928
928
  function createWorkspaceId(input) {
929
929
  const basis = input.repoUrl || input.repoRoot || input.projectName || "unknown";
930
930
  return `workspace_${fnv1a(basis)}`;
@@ -1082,9 +1082,9 @@ function removeVolatileHashFields(value) {
1082
1082
  continue;
1083
1083
  }
1084
1084
  if (key === "refs" && isRecord(item)) {
1085
- const refs2 = { ...item };
1086
- delete refs2.payloadHash;
1087
- result[key] = removeVolatileHashFields(refs2);
1085
+ const refs3 = { ...item };
1086
+ delete refs3.payloadHash;
1087
+ result[key] = removeVolatileHashFields(refs3);
1088
1088
  continue;
1089
1089
  }
1090
1090
  result[key] = removeVolatileHashFields(item);
@@ -1747,13 +1747,13 @@ function isPlainObject(value) {
1747
1747
  return value !== null && typeof value === "object" && !Array.isArray(value);
1748
1748
  }
1749
1749
  function stringRefs(value) {
1750
- const refs2 = {};
1750
+ const refs3 = {};
1751
1751
  for (const [key, item] of Object.entries(value || {})) {
1752
1752
  if (typeof item === "string" && item.length > 0) {
1753
- refs2[key] = item;
1753
+ refs3[key] = item;
1754
1754
  }
1755
1755
  }
1756
- return refs2;
1756
+ return refs3;
1757
1757
  }
1758
1758
  function stringOption(value) {
1759
1759
  if (Array.isArray(value)) {
@@ -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.70" : "0.1.1";
2050
+ var PACKAGE_VERSION = true ? "0.1.72" : "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;
@@ -2111,7 +2111,7 @@ function withBackfillRefs(event, context) {
2111
2111
  event.type,
2112
2112
  event.refs?.sourceId
2113
2113
  ]);
2114
- const refs2 = {
2114
+ const refs3 = {
2115
2115
  ...stringRefs(event.refs),
2116
2116
  importKey,
2117
2117
  sourcePathHash: context.sourcePathHash,
@@ -2121,12 +2121,12 @@ function withBackfillRefs(event, context) {
2121
2121
  parserVersion: PACKAGE_VERSION
2122
2122
  };
2123
2123
  if (context.options.includeSourcePath) {
2124
- refs2.transcriptPath = context.filePath;
2124
+ refs3.transcriptPath = context.filePath;
2125
2125
  }
2126
2126
  return {
2127
2127
  ...event,
2128
2128
  id: createStableEventId(importKey),
2129
- refs: refs2
2129
+ refs: refs3
2130
2130
  };
2131
2131
  }
2132
2132
  function matchesBackfillFilters(event, options) {
@@ -4186,12 +4186,12 @@ async function parseClaudeCoworkSessionFile(filePath, options) {
4186
4186
  const sessionId = parentSessionId || prefixCoworkId(event.sessionId);
4187
4187
  const turnId = prefixCoworkId(event.turnId);
4188
4188
  const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
4189
- const refs2 = { ...event.refs };
4189
+ const refs3 = { ...event.refs };
4190
4190
  if (metadata.title) {
4191
- refs2.coworkTitleHash = `sha256:${createStableHash(metadata.title)}`;
4191
+ refs3.coworkTitleHash = `sha256:${createStableHash(metadata.title)}`;
4192
4192
  }
4193
4193
  if (parentSourcePathHash) {
4194
- refs2.sourcePathHash = parentSourcePathHash;
4194
+ refs3.sourcePathHash = parentSourcePathHash;
4195
4195
  }
4196
4196
  const mapped = {
4197
4197
  ...event,
@@ -4203,7 +4203,7 @@ async function parseClaudeCoworkSessionFile(filePath, options) {
4203
4203
  project,
4204
4204
  sessionId,
4205
4205
  turnId,
4206
- refs: refs2
4206
+ refs: refs3
4207
4207
  };
4208
4208
  return rebuildEventIdentity(mapped);
4209
4209
  });
@@ -4936,8 +4936,8 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
4936
4936
  }
4937
4937
  const filePath = path9.join(traceDir, entry);
4938
4938
  try {
4939
- const stat18 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
4940
- files.push({ path: filePath, modifiedAt: stat18.mtime.toISOString(), groupId: pidDir.name });
4939
+ const stat19 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
4940
+ files.push({ path: filePath, modifiedAt: stat19.mtime.toISOString(), groupId: pidDir.name });
4941
4941
  } catch {
4942
4942
  }
4943
4943
  }
@@ -9039,9 +9039,698 @@ function createGrokBuildAdapter() {
9039
9039
  };
9040
9040
  }
9041
9041
 
9042
+ // src/adapters/hermes.ts
9043
+ import { readdir as readdir8, stat as stat11 } from "node:fs/promises";
9044
+ import path15 from "node:path";
9045
+ init_fs();
9046
+ var SOURCE = "hermes";
9047
+ var PLUGIN_DIR = ["plugins", "vibetime"];
9048
+ var GENERATED_MARKER3 = "Generated by vibetime.";
9049
+ var HOOK_COMMAND3 = "vibetime hook --agent hermes";
9050
+ function hermesRoot(home, env) {
9051
+ const override = env?.HERMES_HOME;
9052
+ if (override && override.trim()) {
9053
+ return path15.resolve(override);
9054
+ }
9055
+ return path15.join(home, ".hermes");
9056
+ }
9057
+ function hermesPluginDir(home, env) {
9058
+ return path15.join(hermesRoot(home, env), ...PLUGIN_DIR);
9059
+ }
9060
+ function hermesPluginManifestPath(home, env) {
9061
+ return path15.join(hermesPluginDir(home, env), "plugin.yaml");
9062
+ }
9063
+ function hermesPluginInitPath(home, env) {
9064
+ return path15.join(hermesPluginDir(home, env), "__init__.py");
9065
+ }
9066
+ function sourceHash(filePath) {
9067
+ return `sha256:${createStableHash(filePath)}`;
9068
+ }
9069
+ function refs(values) {
9070
+ const out = {};
9071
+ for (const [key, value] of Object.entries(values)) {
9072
+ if (value !== void 0 && value !== "") {
9073
+ out[key] = String(value);
9074
+ }
9075
+ }
9076
+ return out;
9077
+ }
9078
+ function projectFromCwd(cwd, repoRoot) {
9079
+ const basis = repoRoot || cwd;
9080
+ return basis ? path15.basename(basis) || SOURCE : SOURCE;
9081
+ }
9082
+ function isoFromUnix(value) {
9083
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
9084
+ return void 0;
9085
+ }
9086
+ return timestampFrom(value);
9087
+ }
9088
+ function tableColumns(db, table) {
9089
+ try {
9090
+ const rows = db.prepare(`PRAGMA table_info(${table})`).all();
9091
+ return new Set(rows.map((row) => row.name).filter((name) => Boolean(name)));
9092
+ } catch {
9093
+ return /* @__PURE__ */ new Set();
9094
+ }
9095
+ }
9096
+ function selectExisting(columns, wanted) {
9097
+ return wanted.filter((name) => columns.has(name));
9098
+ }
9099
+ function asRecord(value) {
9100
+ return isPlainObject(value) ? value : {};
9101
+ }
9102
+ function sessionContext(row) {
9103
+ const rawId = stringField(row, "id") || "unknown";
9104
+ const cwd = stringField(row, "cwd");
9105
+ const repoRoot = stringField(row, "git_repo_root");
9106
+ const project = projectFromCwd(cwd, repoRoot);
9107
+ return {
9108
+ rawId,
9109
+ sessionId: `${SOURCE}:${rawId}`,
9110
+ cwd,
9111
+ project,
9112
+ workspaceId: createWorkspaceId({ projectName: project, repoRoot: repoRoot || cwd }),
9113
+ platform: stringField(row, "source"),
9114
+ profileName: stringField(row, "profile_name"),
9115
+ parentSessionId: stringField(row, "parent_session_id"),
9116
+ model: stringField(row, "model"),
9117
+ provider: stringField(row, "billing_provider")
9118
+ };
9119
+ }
9120
+ function makeEvent(event, lineNumber, filePath, options) {
9121
+ const withRefs = withBackfillRefs(event, {
9122
+ filePath,
9123
+ sourcePathHash: sourceHash(filePath),
9124
+ lineNumber,
9125
+ topType: event.type,
9126
+ payloadType: event.refs?.payloadType || event.tool || event.type,
9127
+ options
9128
+ });
9129
+ return validateCanonicalEvent(withRefs).valid ? withRefs : void 0;
9130
+ }
9131
+ function usageMetrics2(row) {
9132
+ const input = numberField(row, "input_tokens") || 0;
9133
+ const output = numberField(row, "output_tokens") || 0;
9134
+ const cacheRead = numberField(row, "cache_read_tokens") || 0;
9135
+ const cacheWrite = numberField(row, "cache_write_tokens") || 0;
9136
+ const reasoning = numberField(row, "reasoning_tokens") || 0;
9137
+ const actualCost = numberField(row, "actual_cost_usd");
9138
+ const estimatedCost = numberField(row, "estimated_cost_usd");
9139
+ const costUsd = actualCost && actualCost > 0 ? actualCost : estimatedCost;
9140
+ return {
9141
+ tokensInput: input || void 0,
9142
+ tokensOutput: output || void 0,
9143
+ tokensCacheReadInput: cacheRead || void 0,
9144
+ tokensCacheCreationInput: cacheWrite || void 0,
9145
+ tokensCachedInput: cacheRead + cacheWrite || void 0,
9146
+ tokensReasoningOutput: reasoning || void 0,
9147
+ tokensTotal: input + output + cacheRead + cacheWrite,
9148
+ modelCalls: numberField(row, "api_call_count") || void 0,
9149
+ costUsd: costUsd && costUsd > 0 ? costUsd : void 0
9150
+ };
9151
+ }
9152
+ function sessionHasWork(row, usageRows) {
9153
+ if (usageRows.some((item) => (numberField(item, "input_tokens") || 0) + (numberField(item, "output_tokens") || 0) > 0)) {
9154
+ return true;
9155
+ }
9156
+ if ((numberField(row, "input_tokens") || 0) + (numberField(row, "output_tokens") || 0) > 0) {
9157
+ return true;
9158
+ }
9159
+ if ((numberField(row, "message_count") || 0) > 0) {
9160
+ return true;
9161
+ }
9162
+ if ((numberField(row, "tool_call_count") || 0) > 0) {
9163
+ return true;
9164
+ }
9165
+ return false;
9166
+ }
9167
+ function parseToolCalls(raw) {
9168
+ let parsed = raw;
9169
+ if (typeof raw === "string" && raw.trim()) {
9170
+ try {
9171
+ parsed = JSON.parse(raw);
9172
+ } catch {
9173
+ return [];
9174
+ }
9175
+ }
9176
+ if (!Array.isArray(parsed)) {
9177
+ return [];
9178
+ }
9179
+ const out = [];
9180
+ for (const item of parsed) {
9181
+ if (!isPlainObject(item)) {
9182
+ continue;
9183
+ }
9184
+ const fn = isPlainObject(item.function) ? item.function : item;
9185
+ const name = stringField(fn, "name") || stringField(item, "name");
9186
+ if (!name) {
9187
+ continue;
9188
+ }
9189
+ let input = {};
9190
+ const args = fn.arguments ?? item.arguments;
9191
+ if (typeof args === "string" && args.trim()) {
9192
+ try {
9193
+ const parsedArgs = JSON.parse(args);
9194
+ if (isPlainObject(parsedArgs)) {
9195
+ input = parsedArgs;
9196
+ }
9197
+ } catch {
9198
+ input = {};
9199
+ }
9200
+ } else if (isPlainObject(args)) {
9201
+ input = args;
9202
+ }
9203
+ out.push({
9204
+ id: stringField(item, "id") || stringField(item, "call_id") || stringField(fn, "id"),
9205
+ name,
9206
+ input
9207
+ });
9208
+ }
9209
+ return out;
9210
+ }
9211
+ function hermesToolAlias(tool) {
9212
+ const normalized = tool.toLowerCase();
9213
+ if (normalized === "write_file") {
9214
+ return "write";
9215
+ }
9216
+ if (normalized === "patch") {
9217
+ return "edit";
9218
+ }
9219
+ if (normalized === "read_file") {
9220
+ return "read";
9221
+ }
9222
+ return tool;
9223
+ }
9224
+ async function sqliteMtime(filePath) {
9225
+ try {
9226
+ const info = await stat11(filePath);
9227
+ let modifiedMs = info.mtimeMs;
9228
+ for (const suffix of ["-wal", "-shm"]) {
9229
+ try {
9230
+ const sidecar = await stat11(`${filePath}${suffix}`);
9231
+ modifiedMs = Math.max(modifiedMs, sidecar.mtimeMs);
9232
+ } catch {
9233
+ }
9234
+ }
9235
+ return new Date(modifiedMs).toISOString();
9236
+ } catch {
9237
+ return void 0;
9238
+ }
9239
+ }
9240
+ async function parseHermesDb(filePath, options) {
9241
+ if (!filePath.endsWith(".db")) {
9242
+ return [];
9243
+ }
9244
+ const { DatabaseSync } = await import("node:sqlite");
9245
+ let db;
9246
+ try {
9247
+ db = new DatabaseSync(filePath, { readOnly: true });
9248
+ } catch {
9249
+ return [];
9250
+ }
9251
+ try {
9252
+ const sessionCols = tableColumns(db, "sessions");
9253
+ if (!sessionCols.has("id") || !sessionCols.has("started_at")) {
9254
+ return [];
9255
+ }
9256
+ const sessionSelect = selectExisting(sessionCols, [
9257
+ "id",
9258
+ "source",
9259
+ "model",
9260
+ "parent_session_id",
9261
+ "started_at",
9262
+ "ended_at",
9263
+ "message_count",
9264
+ "tool_call_count",
9265
+ "input_tokens",
9266
+ "output_tokens",
9267
+ "cache_read_tokens",
9268
+ "cache_write_tokens",
9269
+ "reasoning_tokens",
9270
+ "cwd",
9271
+ "git_repo_root",
9272
+ "billing_provider",
9273
+ "estimated_cost_usd",
9274
+ "actual_cost_usd",
9275
+ "title",
9276
+ "last_activity_at",
9277
+ "profile_name"
9278
+ ]);
9279
+ const sessions = db.prepare(
9280
+ `SELECT ${sessionSelect.join(", ")} FROM sessions WHERE started_at IS NOT NULL ORDER BY started_at, id`
9281
+ ).all().map(asRecord);
9282
+ const usageCols = tableColumns(db, "session_model_usage");
9283
+ const usageBySession = /* @__PURE__ */ new Map();
9284
+ if (usageCols.has("session_id")) {
9285
+ const usageSelect = selectExisting(usageCols, [
9286
+ "session_id",
9287
+ "model",
9288
+ "billing_provider",
9289
+ "billing_base_url",
9290
+ "billing_mode",
9291
+ "task",
9292
+ "api_call_count",
9293
+ "input_tokens",
9294
+ "output_tokens",
9295
+ "cache_read_tokens",
9296
+ "cache_write_tokens",
9297
+ "reasoning_tokens",
9298
+ "estimated_cost_usd",
9299
+ "actual_cost_usd",
9300
+ "first_seen",
9301
+ "last_seen"
9302
+ ]);
9303
+ const usageRows = db.prepare(
9304
+ `SELECT ${usageSelect.join(", ")} FROM session_model_usage`
9305
+ ).all().map(asRecord);
9306
+ for (const row of usageRows) {
9307
+ const sessionId = stringField(row, "session_id");
9308
+ if (!sessionId) {
9309
+ continue;
9310
+ }
9311
+ const list = usageBySession.get(sessionId) || [];
9312
+ list.push(row);
9313
+ usageBySession.set(sessionId, list);
9314
+ }
9315
+ }
9316
+ const messageCols = tableColumns(db, "messages");
9317
+ const messagesBySession = /* @__PURE__ */ new Map();
9318
+ if (messageCols.has("session_id") && messageCols.has("role")) {
9319
+ const messageSelect = selectExisting(messageCols, [
9320
+ "id",
9321
+ "session_id",
9322
+ "role",
9323
+ "content",
9324
+ "tool_calls",
9325
+ "timestamp",
9326
+ "token_count",
9327
+ "active"
9328
+ ]);
9329
+ const activeFilter = messageCols.has("active") ? " WHERE coalesce(active, 1) = 1" : "";
9330
+ const messageRows = db.prepare(
9331
+ `SELECT ${messageSelect.join(", ")} FROM messages${activeFilter} ORDER BY timestamp, id`
9332
+ ).all().map(asRecord);
9333
+ for (const row of messageRows) {
9334
+ const sessionId = stringField(row, "session_id");
9335
+ if (!sessionId) {
9336
+ continue;
9337
+ }
9338
+ const list = messagesBySession.get(sessionId) || [];
9339
+ list.push(row);
9340
+ messagesBySession.set(sessionId, list);
9341
+ }
9342
+ }
9343
+ const events = [];
9344
+ let lineNumber = 0;
9345
+ for (const session of sessions) {
9346
+ const ctx = sessionContext(session);
9347
+ const usageRows = usageBySession.get(ctx.rawId) || [];
9348
+ const messages = messagesBySession.get(ctx.rawId) || [];
9349
+ if (!sessionHasWork(session, usageRows) && messages.length === 0) {
9350
+ continue;
9351
+ }
9352
+ const startedTs = isoFromUnix(session.started_at);
9353
+ if (!startedTs) {
9354
+ continue;
9355
+ }
9356
+ lineNumber += 1;
9357
+ const started = makeEvent({
9358
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
9359
+ ts: startedTs,
9360
+ type: "session.started",
9361
+ source: SOURCE,
9362
+ workspaceId: ctx.workspaceId,
9363
+ project: ctx.project,
9364
+ cwd: ctx.cwd,
9365
+ sessionId: ctx.sessionId,
9366
+ parentAgentInstanceId: ctx.parentSessionId ? `${SOURCE}:${ctx.parentSessionId}` : void 0,
9367
+ agent: SOURCE,
9368
+ model: ctx.model,
9369
+ provider: ctx.provider,
9370
+ confidence: "exact",
9371
+ refs: refs({
9372
+ sourceId: `${ctx.rawId}:session`,
9373
+ hermesPlatform: ctx.platform,
9374
+ hermesProfile: ctx.profileName,
9375
+ hermesParentSessionId: ctx.parentSessionId
9376
+ })
9377
+ }, lineNumber, filePath, options);
9378
+ if (started) {
9379
+ events.push(started);
9380
+ }
9381
+ const endedTs = isoFromUnix(session.ended_at) || isoFromUnix(session.last_activity_at);
9382
+ if (endedTs && endedTs !== startedTs) {
9383
+ lineNumber += 1;
9384
+ const ended = makeEvent({
9385
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
9386
+ ts: endedTs,
9387
+ type: "session.ended",
9388
+ source: SOURCE,
9389
+ workspaceId: ctx.workspaceId,
9390
+ project: ctx.project,
9391
+ cwd: ctx.cwd,
9392
+ sessionId: ctx.sessionId,
9393
+ parentAgentInstanceId: ctx.parentSessionId ? `${SOURCE}:${ctx.parentSessionId}` : void 0,
9394
+ agent: SOURCE,
9395
+ model: ctx.model,
9396
+ provider: ctx.provider,
9397
+ confidence: "exact",
9398
+ refs: refs({
9399
+ sourceId: `${ctx.rawId}:session:ended`,
9400
+ hermesPlatform: ctx.platform,
9401
+ hermesProfile: ctx.profileName
9402
+ })
9403
+ }, lineNumber, filePath, options);
9404
+ if (ended) {
9405
+ events.push(ended);
9406
+ }
9407
+ }
9408
+ if (usageRows.length > 0) {
9409
+ for (const usage of usageRows) {
9410
+ const ts = isoFromUnix(usage.last_seen) || isoFromUnix(usage.first_seen) || startedTs;
9411
+ lineNumber += 1;
9412
+ const event = makeEvent({
9413
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
9414
+ ts,
9415
+ type: "model.usage",
9416
+ source: SOURCE,
9417
+ workspaceId: ctx.workspaceId,
9418
+ project: ctx.project,
9419
+ cwd: ctx.cwd,
9420
+ sessionId: ctx.sessionId,
9421
+ agent: SOURCE,
9422
+ model: stringField(usage, "model") || ctx.model,
9423
+ provider: stringField(usage, "billing_provider") || ctx.provider,
9424
+ success: true,
9425
+ metrics: usageMetrics2(usage),
9426
+ confidence: "exact",
9427
+ refs: refs({
9428
+ sourceId: `${ctx.rawId}:model:${stringField(usage, "model") || "unknown"}:${stringField(usage, "task") || "main"}:${stringField(usage, "billing_provider") || ""}`,
9429
+ hermesPlatform: ctx.platform,
9430
+ hermesProfile: ctx.profileName,
9431
+ hermesTask: stringField(usage, "task"),
9432
+ hermesBillingMode: stringField(usage, "billing_mode")
9433
+ })
9434
+ }, lineNumber, filePath, options);
9435
+ if (event) {
9436
+ events.push(event);
9437
+ }
9438
+ }
9439
+ } else if ((numberField(session, "input_tokens") || 0) + (numberField(session, "output_tokens") || 0) > 0) {
9440
+ lineNumber += 1;
9441
+ const event = makeEvent({
9442
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
9443
+ ts: endedTs || startedTs,
9444
+ type: "model.usage",
9445
+ source: SOURCE,
9446
+ workspaceId: ctx.workspaceId,
9447
+ project: ctx.project,
9448
+ cwd: ctx.cwd,
9449
+ sessionId: ctx.sessionId,
9450
+ agent: SOURCE,
9451
+ model: ctx.model,
9452
+ provider: ctx.provider,
9453
+ success: true,
9454
+ metrics: usageMetrics2(session),
9455
+ confidence: "partial",
9456
+ refs: refs({
9457
+ sourceId: `${ctx.rawId}:model:session`,
9458
+ hermesPlatform: ctx.platform,
9459
+ hermesProfile: ctx.profileName
9460
+ })
9461
+ }, lineNumber, filePath, options);
9462
+ if (event) {
9463
+ events.push(event);
9464
+ }
9465
+ }
9466
+ let turnIndex = 0;
9467
+ let activeTurnId;
9468
+ for (const message of messages) {
9469
+ const ts = isoFromUnix(message.timestamp);
9470
+ if (!ts) {
9471
+ continue;
9472
+ }
9473
+ const role = stringField(message, "role");
9474
+ if (role === "user") {
9475
+ turnIndex += 1;
9476
+ activeTurnId = `${ctx.sessionId}:turn:${turnIndex}`;
9477
+ lineNumber += 1;
9478
+ const turnStarted = makeEvent({
9479
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
9480
+ ts,
9481
+ type: "turn.started",
9482
+ source: SOURCE,
9483
+ workspaceId: ctx.workspaceId,
9484
+ project: ctx.project,
9485
+ cwd: ctx.cwd,
9486
+ sessionId: ctx.sessionId,
9487
+ turnId: activeTurnId,
9488
+ agent: SOURCE,
9489
+ confidence: "derived",
9490
+ refs: refs({ sourceId: `${ctx.rawId}:turn:${turnIndex}:start` })
9491
+ }, lineNumber, filePath, options);
9492
+ if (turnStarted) {
9493
+ events.push(turnStarted);
9494
+ }
9495
+ const content = stringField(message, "content");
9496
+ lineNumber += 1;
9497
+ const prompt = makeEvent({
9498
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
9499
+ ts,
9500
+ type: "prompt.submitted",
9501
+ source: SOURCE,
9502
+ workspaceId: ctx.workspaceId,
9503
+ project: ctx.project,
9504
+ cwd: ctx.cwd,
9505
+ sessionId: ctx.sessionId,
9506
+ turnId: activeTurnId,
9507
+ agent: SOURCE,
9508
+ confidence: "exact",
9509
+ metrics: { promptChars: content?.length, prompts: 1 },
9510
+ refs: refs({ sourceId: `${ctx.rawId}:prompt:${stringField(message, "id") || turnIndex}` })
9511
+ }, lineNumber, filePath, options);
9512
+ if (prompt) {
9513
+ events.push(prompt);
9514
+ }
9515
+ continue;
9516
+ }
9517
+ if (role !== "assistant") {
9518
+ continue;
9519
+ }
9520
+ const tools = parseToolCalls(message.tool_calls);
9521
+ for (const tool of tools) {
9522
+ const toolName = tool.name;
9523
+ const alias = hermesToolAlias(toolName);
9524
+ const toolCallId = tool.id || `${stringField(message, "id") || lineNumber}:${toolName}`;
9525
+ const spanId = `${ctx.sessionId}:tool:${toolCallId}`;
9526
+ const fileActivities = claudeStyleToolFileActivities(alias, tool.input, ts, ctx.cwd);
9527
+ lineNumber += 1;
9528
+ const startedTool = makeEvent({
9529
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
9530
+ ts,
9531
+ type: "tool.started",
9532
+ source: SOURCE,
9533
+ workspaceId: ctx.workspaceId,
9534
+ project: ctx.project,
9535
+ cwd: ctx.cwd,
9536
+ sessionId: ctx.sessionId,
9537
+ turnId: activeTurnId,
9538
+ spanId,
9539
+ agent: SOURCE,
9540
+ tool: toolName,
9541
+ confidence: "exact",
9542
+ refs: refs({ sourceId: `${toolCallId}:start` })
9543
+ }, lineNumber, filePath, options);
9544
+ if (startedTool) {
9545
+ events.push(startedTool);
9546
+ }
9547
+ lineNumber += 1;
9548
+ const completedTool = makeEvent({
9549
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
9550
+ ts,
9551
+ type: "tool.completed",
9552
+ source: SOURCE,
9553
+ workspaceId: ctx.workspaceId,
9554
+ project: ctx.project,
9555
+ cwd: ctx.cwd,
9556
+ sessionId: ctx.sessionId,
9557
+ turnId: activeTurnId,
9558
+ spanId,
9559
+ agent: SOURCE,
9560
+ tool: toolName,
9561
+ success: true,
9562
+ confidence: "exact",
9563
+ fileActivities: fileActivities.length > 0 ? fileActivities : void 0,
9564
+ refs: refs({ sourceId: `${toolCallId}:completed` })
9565
+ }, lineNumber, filePath, options);
9566
+ if (completedTool) {
9567
+ events.push(completedTool);
9568
+ }
9569
+ }
9570
+ }
9571
+ }
9572
+ return events.sort((a, b) => a.ts.localeCompare(b.ts) || (a.id || "").localeCompare(b.id || ""));
9573
+ } finally {
9574
+ db.close();
9575
+ }
9576
+ }
9577
+ async function collectStateDb(filePath, seen, out) {
9578
+ const resolved = path15.resolve(filePath);
9579
+ if (seen.has(resolved)) {
9580
+ return;
9581
+ }
9582
+ const modifiedAt = await sqliteMtime(resolved);
9583
+ if (!modifiedAt) {
9584
+ return;
9585
+ }
9586
+ seen.add(resolved);
9587
+ out.push({ path: resolved, modifiedAt });
9588
+ }
9589
+ async function collectHermesHome(root, seen, out) {
9590
+ await collectStateDb(path15.join(root, "state.db"), seen, out);
9591
+ const profilesDir = path15.join(root, "profiles");
9592
+ let entries;
9593
+ try {
9594
+ entries = await readdir8(profilesDir, { withFileTypes: true });
9595
+ } catch {
9596
+ return;
9597
+ }
9598
+ for (const entry of entries) {
9599
+ if (entry.isDirectory()) {
9600
+ await collectStateDb(path15.join(profilesDir, entry.name, "state.db"), seen, out);
9601
+ }
9602
+ }
9603
+ }
9604
+ async function hermesBackfillFiles(sourceRoot, home, env = {}) {
9605
+ const seen = /* @__PURE__ */ new Set();
9606
+ const out = [];
9607
+ if (sourceRoot) {
9608
+ if (sourceRoot.endsWith(".db")) {
9609
+ await collectStateDb(sourceRoot, seen, out);
9610
+ return out;
9611
+ }
9612
+ await collectHermesHome(sourceRoot, seen, out);
9613
+ return out;
9614
+ }
9615
+ const primary = hermesRoot(home, env);
9616
+ await collectHermesHome(primary, seen, out);
9617
+ const defaultRoot = path15.join(home, ".hermes");
9618
+ if (path15.resolve(defaultRoot) !== path15.resolve(primary)) {
9619
+ await collectHermesHome(defaultRoot, seen, out);
9620
+ }
9621
+ return out.sort((a, b) => a.path.localeCompare(b.path));
9622
+ }
9623
+ function pluginYaml() {
9624
+ return `# ${GENERATED_MARKER3}
9625
+ name: vibetime
9626
+ version: "1.0.0"
9627
+ description: "VibeTime session sync \u2014 thin trigger that runs local backfill on Hermes lifecycle events."
9628
+ author: VibeTime
9629
+ hooks:
9630
+ - on_session_start
9631
+ - on_session_end
9632
+ - on_session_finalize
9633
+ - post_tool_call
9634
+ `;
9635
+ }
9636
+ function pluginInit() {
9637
+ return `# ${GENERATED_MARKER3}
9638
+ """VibeTime observability plugin for Hermes Agent.
9639
+
9640
+ Thin trigger only: spawn \`vibetime hook --agent hermes\` on session/tool
9641
+ lifecycle events. Token usage is read from state.db by vibetime backfill.
9642
+ """
9643
+ from __future__ import annotations
9644
+
9645
+ import json
9646
+ import os
9647
+ import shutil
9648
+ import subprocess
9649
+ from typing import Any
9650
+
9651
+
9652
+ def _report(payload: dict[str, Any]) -> None:
9653
+ command = shutil.which("vibetime")
9654
+ if not command:
9655
+ return
9656
+ try:
9657
+ subprocess.run(
9658
+ [command, "hook", "--agent", "hermes"],
9659
+ input=json.dumps(payload),
9660
+ text=True,
9661
+ capture_output=True,
9662
+ timeout=10,
9663
+ check=False,
9664
+ env=os.environ.copy(),
9665
+ )
9666
+ except Exception:
9667
+ return
9668
+
9669
+
9670
+ def on_session_start(*, session_id: str = "", **_: Any) -> None:
9671
+ _report({"hook_event_name": "SessionStart", "session_id": session_id})
9672
+
9673
+
9674
+ def on_session_end(*, session_id: str = "", **_: Any) -> None:
9675
+ _report({"hook_event_name": "SessionEnd", "session_id": session_id})
9676
+
9677
+
9678
+ def on_post_tool_call(*, tool_name: str = "", session_id: str = "", **_: Any) -> None:
9679
+ _report({
9680
+ "hook_event_name": "PostToolUse",
9681
+ "tool_name": tool_name or "unknown",
9682
+ "session_id": session_id,
9683
+ })
9684
+
9685
+
9686
+ def register(ctx) -> None:
9687
+ ctx.register_hook("on_session_start", on_session_start)
9688
+ ctx.register_hook("on_session_end", on_session_end)
9689
+ ctx.register_hook("on_session_finalize", on_session_end)
9690
+ ctx.register_hook("post_tool_call", on_post_tool_call)
9691
+ `;
9692
+ }
9693
+ function createHermesAdapter() {
9694
+ return {
9695
+ id: SOURCE,
9696
+ label: "Hermes Agent",
9697
+ agentName: SOURCE,
9698
+ kind: "agent",
9699
+ detectPath(home, env) {
9700
+ return hermesRoot(home, env);
9701
+ },
9702
+ installedPath(home, env) {
9703
+ return hermesPluginManifestPath(home, env);
9704
+ },
9705
+ async isInstalled(home, env) {
9706
+ const manifest = await readTextIfExists(hermesPluginManifestPath(home, env));
9707
+ const init = await readTextIfExists(hermesPluginInitPath(home, env));
9708
+ return Boolean(manifest && init && init.includes(HOOK_COMMAND3));
9709
+ },
9710
+ installEntries(home, env) {
9711
+ return [
9712
+ {
9713
+ kind: "file",
9714
+ path: hermesPluginManifestPath(home, env),
9715
+ content: pluginYaml()
9716
+ },
9717
+ {
9718
+ kind: "file",
9719
+ path: hermesPluginInitPath(home, env),
9720
+ content: pluginInit()
9721
+ }
9722
+ ];
9723
+ },
9724
+ sourcePaths(home, env) {
9725
+ return [path15.join(hermesRoot(home, env), "state.db")];
9726
+ },
9727
+ parseSessionFile: parseHermesDb
9728
+ };
9729
+ }
9730
+
9042
9731
  // src/adapters/kimi-code.ts
9043
9732
  import { readFile as readFile10 } from "node:fs/promises";
9044
- import path15 from "node:path";
9733
+ import path16 from "node:path";
9045
9734
 
9046
9735
  // src/lib/toml-hooks.ts
9047
9736
  init_fs();
@@ -9219,20 +9908,20 @@ function tomlNumberField(body, key) {
9219
9908
  }
9220
9909
 
9221
9910
  // src/adapters/kimi-code.ts
9222
- var HOOK_COMMAND3 = "vibetime hook --agent kimi-code";
9911
+ var HOOK_COMMAND4 = "vibetime hook --agent kimi-code";
9223
9912
  var HOOK_TIMEOUT_SECONDS2 = 10;
9224
9913
  function kimiCodeHome(home, env) {
9225
9914
  const override = env?.KIMI_CODE_HOME || env?.KIMI_HOME;
9226
9915
  if (override && override.trim()) {
9227
- return path15.resolve(override);
9916
+ return path16.resolve(override);
9228
9917
  }
9229
- return path15.join(home, ".kimi-code");
9918
+ return path16.join(home, ".kimi-code");
9230
9919
  }
9231
9920
  function kimiCodeSessionsDir(home, env) {
9232
- return path15.join(kimiCodeHome(home, env), "sessions");
9921
+ return path16.join(kimiCodeHome(home, env), "sessions");
9233
9922
  }
9234
9923
  function kimiCodeConfigPath(home, env) {
9235
- return path15.join(kimiCodeHome(home, env), "config.toml");
9924
+ return path16.join(kimiCodeHome(home, env), "config.toml");
9236
9925
  }
9237
9926
  function kimiHookRules() {
9238
9927
  const events = [
@@ -9248,7 +9937,7 @@ function kimiHookRules() {
9248
9937
  ];
9249
9938
  return events.map((event) => ({
9250
9939
  event,
9251
- command: HOOK_COMMAND3,
9940
+ command: HOOK_COMMAND4,
9252
9941
  timeout: HOOK_TIMEOUT_SECONDS2
9253
9942
  }));
9254
9943
  }
@@ -9308,8 +9997,8 @@ function sessionIdFromWirePath(filePath) {
9308
9997
  return match?.[1];
9309
9998
  }
9310
9999
  async function readSessionState(filePath) {
9311
- const sessionDir = path15.dirname(path15.dirname(path15.dirname(filePath)));
9312
- const statePath = path15.join(sessionDir, "state.json");
10000
+ const sessionDir = path16.dirname(path16.dirname(path16.dirname(filePath)));
10001
+ const statePath = path16.join(sessionDir, "state.json");
9313
10002
  try {
9314
10003
  const text = await readFile10(statePath, "utf8");
9315
10004
  const raw = JSON.parse(text);
@@ -9326,7 +10015,7 @@ async function readSessionState(filePath) {
9326
10015
  }
9327
10016
  }
9328
10017
  async function parseKimiCodeSessionFile(filePath, options) {
9329
- if (path15.basename(filePath) !== "wire.jsonl") {
10018
+ if (path16.basename(filePath) !== "wire.jsonl") {
9330
10019
  return [];
9331
10020
  }
9332
10021
  const text = await readFile10(filePath, "utf8");
@@ -9334,7 +10023,7 @@ async function parseKimiCodeSessionFile(filePath, options) {
9334
10023
  const stateMeta = await readSessionState(filePath);
9335
10024
  let sessionId = stateMeta.sessionId || sessionIdFromWirePath(filePath);
9336
10025
  let cwd = stateMeta.cwd;
9337
- let project = cwd ? path15.basename(cwd) : void 0;
10026
+ let project = cwd ? path16.basename(cwd) : void 0;
9338
10027
  let model;
9339
10028
  let provider;
9340
10029
  let reasoningEffort;
@@ -9380,7 +10069,7 @@ async function parseKimiCodeSessionFile(filePath, options) {
9380
10069
  const disclosedCwd = stringField(disclosure, "cwd");
9381
10070
  if (disclosedCwd) {
9382
10071
  cwd = disclosedCwd;
9383
- project = path15.basename(disclosedCwd);
10072
+ project = path16.basename(disclosedCwd);
9384
10073
  }
9385
10074
  continue;
9386
10075
  }
@@ -9694,7 +10383,7 @@ function createKimiCodeAdapter() {
9694
10383
  return kimiCodeConfigPath(home, env);
9695
10384
  },
9696
10385
  async isInstalled(home, env) {
9697
- return hasTomlHookCommand(kimiCodeConfigPath(home, env), HOOK_COMMAND3);
10386
+ return hasTomlHookCommand(kimiCodeConfigPath(home, env), HOOK_COMMAND4);
9698
10387
  },
9699
10388
  installEntries(home, env) {
9700
10389
  return [{
@@ -9712,7 +10401,7 @@ function createKimiCodeAdapter() {
9712
10401
 
9713
10402
  // src/adapters/opencode.ts
9714
10403
  import os8 from "node:os";
9715
- import path16 from "node:path";
10404
+ import path17 from "node:path";
9716
10405
  async function parseOpenCodeSessionFile(dbPath, options) {
9717
10406
  const { DatabaseSync } = await import("node:sqlite");
9718
10407
  if (!dbPath.endsWith(".db")) {
@@ -9771,7 +10460,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
9771
10460
  const isSubagent = sessionId !== rawSessionId;
9772
10461
  const sessionEventStart = events.length;
9773
10462
  const cwd = session.directory || session.path || void 0;
9774
- const project = cwd ? path16.basename(cwd) : void 0;
10463
+ const project = cwd ? path17.basename(cwd) : void 0;
9775
10464
  const sessionTs = msToIso(session.time_created);
9776
10465
  events.push(baseOpenCodeEvent({
9777
10466
  ts: sessionTs,
@@ -9879,7 +10568,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
9879
10568
  const provider = currentProvider;
9880
10569
  const pathObj = objectField(info, "path");
9881
10570
  const assistantCwd = stringField(pathObj, "cwd") || cwd;
9882
- const assistantProject = assistantCwd ? path16.basename(assistantCwd) : project;
10571
+ const assistantProject = assistantCwd ? path17.basename(assistantCwd) : project;
9883
10572
  const completedTs = numberField(objectField(info, "time"), "completed");
9884
10573
  const createdTs = timeCreated;
9885
10574
  const tokens = opencodeUsageFromInfo(info);
@@ -10153,33 +10842,33 @@ function opencodeUsageFromInfo(info) {
10153
10842
  function opencodeConfigDir(home, env) {
10154
10843
  const override = env?.OPENCODE_CONFIG_DIR;
10155
10844
  if (override && override.trim()) {
10156
- return path16.resolve(override);
10845
+ return path17.resolve(override);
10157
10846
  }
10158
10847
  const xdgConfig = env?.XDG_CONFIG_HOME;
10159
10848
  if (xdgConfig && xdgConfig.trim()) {
10160
- return path16.join(path16.resolve(xdgConfig), "opencode");
10849
+ return path17.join(path17.resolve(xdgConfig), "opencode");
10161
10850
  }
10162
- return path16.join(home, ".config", "opencode");
10851
+ return path17.join(home, ".config", "opencode");
10163
10852
  }
10164
10853
  function opencodeDataCandidates(home, env) {
10165
10854
  const xdgData = env?.XDG_DATA_HOME;
10166
- const primary = xdgData && xdgData.trim() ? path16.join(path16.resolve(xdgData), "opencode", "opencode.db") : path16.join(home, ".local", "share", "opencode", "opencode.db");
10167
- return [primary, path16.join(home, ".opencode", "opencode.db")];
10855
+ const primary = xdgData && xdgData.trim() ? path17.join(path17.resolve(xdgData), "opencode", "opencode.db") : path17.join(home, ".local", "share", "opencode", "opencode.db");
10856
+ return [primary, path17.join(home, ".opencode", "opencode.db")];
10168
10857
  }
10169
10858
  async function opencodeBackfillFiles(sourceRoot, home = os8.homedir(), env) {
10170
- const { stat: stat18 } = await import("node:fs/promises");
10859
+ const { stat: stat19 } = await import("node:fs/promises");
10171
10860
  if (sourceRoot) {
10172
10861
  if (!sourceRoot.endsWith(".db")) {
10173
10862
  return [];
10174
10863
  }
10175
- const info = await stat18(sourceRoot).catch(() => null);
10864
+ const info = await stat19(sourceRoot).catch(() => null);
10176
10865
  if (!info) {
10177
10866
  return [];
10178
10867
  }
10179
10868
  return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
10180
10869
  }
10181
10870
  for (const candidatePath of opencodeDataCandidates(home, env)) {
10182
- const info = await stat18(candidatePath).catch(() => null);
10871
+ const info = await stat19(candidatePath).catch(() => null);
10183
10872
  if (info) {
10184
10873
  return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
10185
10874
  }
@@ -10254,12 +10943,12 @@ function createOpenCodeAdapter() {
10254
10943
  return opencodeConfigDir(home, env);
10255
10944
  },
10256
10945
  installedPath(home, env) {
10257
- return path16.join(opencodeConfigDir(home, env), PLUGIN_PATH);
10946
+ return path17.join(opencodeConfigDir(home, env), PLUGIN_PATH);
10258
10947
  },
10259
10948
  async isInstalled(home, env) {
10260
10949
  try {
10261
10950
  const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
10262
- return await pathExists2(path16.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path16.join(".opencode", PLUGIN_PATH));
10951
+ return await pathExists2(path17.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path17.join(".opencode", PLUGIN_PATH));
10263
10952
  } catch {
10264
10953
  return false;
10265
10954
  }
@@ -10267,7 +10956,7 @@ function createOpenCodeAdapter() {
10267
10956
  installEntries(home, env) {
10268
10957
  return [{
10269
10958
  kind: "file",
10270
- path: path16.join(opencodeConfigDir(home, env), PLUGIN_PATH),
10959
+ path: path17.join(opencodeConfigDir(home, env), PLUGIN_PATH),
10271
10960
  content: opencodePluginContent()
10272
10961
  }];
10273
10962
  },
@@ -10279,9 +10968,9 @@ function createOpenCodeAdapter() {
10279
10968
  }
10280
10969
 
10281
10970
  // src/adapters/pi.ts
10282
- import { readdir as readdir8, readFile as readFile11, stat as stat11 } from "node:fs/promises";
10971
+ import { readdir as readdir9, readFile as readFile11, stat as stat12 } from "node:fs/promises";
10283
10972
  import os9 from "node:os";
10284
- import path17 from "node:path";
10973
+ import path18 from "node:path";
10285
10974
  init_fs();
10286
10975
  function piHostSessionIdFromBasename(basename) {
10287
10976
  const withoutExt = basename.endsWith(".jsonl") ? basename.slice(0, -".jsonl".length) : basename;
@@ -10296,7 +10985,7 @@ function piHostSessionIdFromBasename(basename) {
10296
10985
  }
10297
10986
  function resolvePiBackfillGroupId(filePath) {
10298
10987
  const normalized = filePath.replaceAll("\\", "/");
10299
- const base = path17.basename(filePath);
10988
+ const base = path18.basename(filePath);
10300
10989
  const nest = normalized.match(/([^/]+)\/[^/]+\/run-\d+\/session\.jsonl$/);
10301
10990
  if (nest) {
10302
10991
  return piHostSessionIdFromBasename(nest[1]);
@@ -10308,8 +10997,8 @@ function resolvePiBackfillGroupId(filePath) {
10308
10997
  }
10309
10998
  function parsePiSubagentLink(filePath, headerParentSession) {
10310
10999
  if (headerParentSession) {
10311
- const parentFile = path17.isAbsolute(headerParentSession) ? headerParentSession : void 0;
10312
- const parentSessionId2 = parentFile ? path17.basename(parentFile, ".jsonl") : headerParentSession;
11000
+ const parentFile = path18.isAbsolute(headerParentSession) ? headerParentSession : void 0;
11001
+ const parentSessionId2 = parentFile ? path18.basename(parentFile, ".jsonl") : headerParentSession;
10313
11002
  return { parentSessionId: parentSessionId2, parentSessionFile: parentFile, explicit: true };
10314
11003
  }
10315
11004
  const normalized = filePath.replaceAll("\\", "/");
@@ -10322,8 +11011,8 @@ function parsePiSubagentLink(filePath, headerParentSession) {
10322
11011
  return void 0;
10323
11012
  }
10324
11013
  const parentSessionId = parentBasename.endsWith(".jsonl") ? parentBasename.slice(0, -".jsonl".length) : parentBasename;
10325
- const parentDir = path17.dirname(path17.dirname(path17.dirname(filePath)));
10326
- const parentSessionFile = path17.join(path17.dirname(parentDir), `${parentBasename}.jsonl`);
11014
+ const parentDir = path18.dirname(path18.dirname(path18.dirname(filePath)));
11015
+ const parentSessionFile = path18.join(path18.dirname(parentDir), `${parentBasename}.jsonl`);
10327
11016
  return { parentSessionId, parentSessionFile, explicit: false };
10328
11017
  }
10329
11018
  async function resolveParentContext(link, options) {
@@ -10335,7 +11024,7 @@ async function resolveParentContext(link, options) {
10335
11024
  if (raw) {
10336
11025
  const id = stringField(raw, "id");
10337
11026
  const cwd = stringField(raw, "cwd");
10338
- const project = cwd ? path17.basename(cwd) : void 0;
11027
+ const project = cwd ? path18.basename(cwd) : void 0;
10339
11028
  if (id || cwd || project) {
10340
11029
  return { sessionId: id, cwd, project };
10341
11030
  }
@@ -10416,7 +11105,7 @@ async function parsePiSessionFile(filePath, options) {
10416
11105
  sessionId = stringField(raw, "id") || state.sessionId;
10417
11106
  state.sessionId = sessionId || state.sessionId;
10418
11107
  cwd = stringField(raw, "cwd") || cwd;
10419
- project = cwd ? path17.basename(cwd) : project;
11108
+ project = cwd ? path18.basename(cwd) : project;
10420
11109
  headerParentSession = stringField(raw, "parentSession") || headerParentSession;
10421
11110
  continue;
10422
11111
  }
@@ -10691,17 +11380,17 @@ async function parsePiWorkflowRunFile(filePath, options) {
10691
11380
  return state.events.filter((event) => matchesBackfillFilters(event, options));
10692
11381
  }
10693
11382
  async function findPiSessionFileById(sessionId, options) {
10694
- const sessionsDir = piSessionDir(path17.resolve(stringOption(options.home) || os9.homedir()));
11383
+ const sessionsDir = piSessionDir(path18.resolve(stringOption(options.home) || os9.homedir()));
10695
11384
  try {
10696
- const projectDirs = await readdir8(sessionsDir, { withFileTypes: true });
11385
+ const projectDirs = await readdir9(sessionsDir, { withFileTypes: true });
10697
11386
  for (const dir of projectDirs) {
10698
11387
  if (!dir.isDirectory()) {
10699
11388
  continue;
10700
11389
  }
10701
- const names = await readdir8(path17.join(sessionsDir, dir.name));
11390
+ const names = await readdir9(path18.join(sessionsDir, dir.name));
10702
11391
  const hit = names.find((name) => name.endsWith(`_${sessionId}.jsonl`));
10703
11392
  if (hit) {
10704
- return path17.join(sessionsDir, dir.name, hit);
11393
+ return path18.join(sessionsDir, dir.name, hit);
10705
11394
  }
10706
11395
  }
10707
11396
  } catch {
@@ -10943,19 +11632,19 @@ export default function (pi: ExtensionAPI) {
10943
11632
  function piAgentDir(home, env) {
10944
11633
  const override = env?.PI_CODING_AGENT_DIR;
10945
11634
  if (override && override.trim()) {
10946
- return path17.resolve(override);
11635
+ return path18.resolve(override);
10947
11636
  }
10948
- return path17.join(home, ".pi", "agent");
11637
+ return path18.join(home, ".pi", "agent");
10949
11638
  }
10950
11639
  function piSessionDir(home, env) {
10951
11640
  const override = env?.PI_CODING_AGENT_SESSION_DIR;
10952
11641
  if (override && override.trim()) {
10953
- return path17.resolve(override);
11642
+ return path18.resolve(override);
10954
11643
  }
10955
- return path17.join(piAgentDir(home, env), "sessions");
11644
+ return path18.join(piAgentDir(home, env), "sessions");
10956
11645
  }
10957
11646
  function piWorkflowProjectsDir(home) {
10958
- return path17.join(home, ".pi", "workflows", "projects");
11647
+ return path18.join(home, ".pi", "workflows", "projects");
10959
11648
  }
10960
11649
  async function workflowRunGroupId(filePath) {
10961
11650
  try {
@@ -10975,7 +11664,7 @@ async function piBackfillFiles(sourceRoot, home = os9.homedir(), env) {
10975
11664
  ]);
10976
11665
  const files = lists.flat().sort();
10977
11666
  return Promise.all(files.map(async (filePath) => {
10978
- const info = await stat11(filePath);
11667
+ const info = await stat12(filePath);
10979
11668
  let groupId = resolvePiBackfillGroupId(filePath);
10980
11669
  if (!groupId && filePath.endsWith(".json")) {
10981
11670
  groupId = await workflowRunGroupId(filePath);
@@ -10997,12 +11686,12 @@ function createPiAdapter() {
10997
11686
  return piAgentDir(home, env);
10998
11687
  },
10999
11688
  installedPath(home, env) {
11000
- return path17.join(piAgentDir(home, env), "extensions", "vibetime.ts");
11689
+ return path18.join(piAgentDir(home, env), "extensions", "vibetime.ts");
11001
11690
  },
11002
11691
  async isInstalled(home, env) {
11003
11692
  try {
11004
11693
  const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
11005
- return await pathExists2(path17.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
11694
+ return await pathExists2(path18.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
11006
11695
  } catch {
11007
11696
  return false;
11008
11697
  }
@@ -11010,7 +11699,7 @@ function createPiAdapter() {
11010
11699
  installEntries(home, env) {
11011
11700
  return [{
11012
11701
  kind: "file",
11013
- path: path17.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
11702
+ path: path18.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
11014
11703
  content: piExtensionContent()
11015
11704
  }];
11016
11705
  },
@@ -11022,14 +11711,14 @@ function createPiAdapter() {
11022
11711
  }
11023
11712
 
11024
11713
  // src/adapters/qoder-cn.ts
11025
- import { readdir as readdir9, readFile as readFile12, stat as stat12 } from "node:fs/promises";
11714
+ import { readdir as readdir10, readFile as readFile12, stat as stat13 } from "node:fs/promises";
11026
11715
  import os11 from "node:os";
11027
- import path19 from "node:path";
11716
+ import path20 from "node:path";
11028
11717
 
11029
11718
  // src/adapters/qoder-local-db.ts
11030
11719
  import { access } from "node:fs/promises";
11031
11720
  import os10 from "node:os";
11032
- import path18 from "node:path";
11721
+ import path19 from "node:path";
11033
11722
  function takeQoderDbModelCall(calls, requestId, blockStart) {
11034
11723
  if (requestId) {
11035
11724
  const call = calls.byRequestId.get(requestId)?.shift();
@@ -11048,12 +11737,12 @@ function takeQoderDbModelCall(calls, requestId, blockStart) {
11048
11737
  }
11049
11738
  function appDataRoot(appDirName, home = os10.homedir()) {
11050
11739
  if (process.platform === "darwin") {
11051
- return path18.join(home, "Library", "Application Support", appDirName);
11740
+ return path19.join(home, "Library", "Application Support", appDirName);
11052
11741
  }
11053
11742
  if (process.platform === "win32") {
11054
- return path18.join(process.env.APPDATA || path18.join(home, "AppData", "Roaming"), appDirName);
11743
+ return path19.join(process.env.APPDATA || path19.join(home, "AppData", "Roaming"), appDirName);
11055
11744
  }
11056
- return path18.join(home, ".config", appDirName);
11745
+ return path19.join(home, ".config", appDirName);
11057
11746
  }
11058
11747
  function qoderLocalDbCandidates(appDirName) {
11059
11748
  const candidates = [];
@@ -11063,8 +11752,8 @@ function qoderLocalDbCandidates(appDirName) {
11063
11752
  }
11064
11753
  const configRoot = appDataRoot(appDirName);
11065
11754
  candidates.push(
11066
- path18.join(configRoot, "SharedClientCache", "cache", "db", "local.db"),
11067
- path18.join(configRoot, "SharedClientCache", "db", "local.db")
11755
+ path19.join(configRoot, "SharedClientCache", "cache", "db", "local.db"),
11756
+ path19.join(configRoot, "SharedClientCache", "db", "local.db")
11068
11757
  );
11069
11758
  return candidates;
11070
11759
  }
@@ -11073,7 +11762,7 @@ async function loadQoderIdeModelCatalog(appDirName, home) {
11073
11762
  try {
11074
11763
  const { DatabaseSync } = await import("node:sqlite");
11075
11764
  const db = new DatabaseSync(
11076
- path18.join(appDataRoot(appDirName, home), "User", "globalStorage", "state.vscdb"),
11765
+ path19.join(appDataRoot(appDirName, home), "User", "globalStorage", "state.vscdb"),
11077
11766
  { readOnly: true }
11078
11767
  );
11079
11768
  try {
@@ -11215,7 +11904,7 @@ function resolveSessionPreferredModel(db, sessionId, modelMap) {
11215
11904
 
11216
11905
  // src/adapters/qoder-cn.ts
11217
11906
  function parseQoderCnPaths(filePath) {
11218
- const parts = filePath.split(path19.sep);
11907
+ const parts = filePath.split(path20.sep);
11219
11908
  const subagentsIdx = parts.lastIndexOf("subagents");
11220
11909
  let sessionId = "";
11221
11910
  let projectName = "";
@@ -11225,17 +11914,17 @@ function parseQoderCnPaths(filePath) {
11225
11914
  sessionId = parts[subagentsIdx - 1];
11226
11915
  projectName = parts[subagentsIdx - 2];
11227
11916
  const projectsIdx = parts.lastIndexOf("projects");
11228
- configDir2 = parts.slice(0, projectsIdx).join(path19.sep);
11229
- mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path19.sep);
11917
+ configDir2 = parts.slice(0, projectsIdx).join(path20.sep);
11918
+ mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path20.sep);
11230
11919
  } else {
11231
11920
  const filename = parts.at(-1) || "";
11232
- sessionId = path19.basename(filename, ".jsonl");
11921
+ sessionId = path20.basename(filename, ".jsonl");
11233
11922
  projectName = parts.at(-2) || "";
11234
11923
  if (projectName === "transcript") {
11235
11924
  projectName = parts.at(-3) || "";
11236
11925
  }
11237
11926
  const projectsIdx = parts.lastIndexOf("projects");
11238
- configDir2 = parts.slice(0, projectsIdx).join(path19.sep);
11927
+ configDir2 = parts.slice(0, projectsIdx).join(path20.sep);
11239
11928
  }
11240
11929
  return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
11241
11930
  }
@@ -11283,7 +11972,7 @@ async function loadQoderCnModelNames(configDir2, home) {
11283
11972
  }
11284
11973
  }
11285
11974
  }
11286
- const textsMap = await parseModelNamesFromDynamicTexts(path19.join(configDir2, ".auth", "dynamic-texts.json"));
11975
+ const textsMap = await parseModelNamesFromDynamicTexts(path20.join(configDir2, ".auth", "dynamic-texts.json"));
11287
11976
  for (const [key, val] of Object.entries(textsMap)) {
11288
11977
  if (!(key in map)) {
11289
11978
  map[key] = val;
@@ -11291,7 +11980,7 @@ async function loadQoderCnModelNames(configDir2, home) {
11291
11980
  }
11292
11981
  const siblingConfigDir = configDir2.replace(/\.qoder-cn$/, ".qoder");
11293
11982
  if (siblingConfigDir !== configDir2) {
11294
- const siblingMap = await parseModelNamesFromDynamicTexts(path19.join(siblingConfigDir, ".auth", "dynamic-texts.json"));
11983
+ const siblingMap = await parseModelNamesFromDynamicTexts(path20.join(siblingConfigDir, ".auth", "dynamic-texts.json"));
11295
11984
  for (const [key, val] of Object.entries(siblingMap)) {
11296
11985
  if (!(key in map)) {
11297
11986
  map[key] = val;
@@ -11302,15 +11991,15 @@ async function loadQoderCnModelNames(configDir2, home) {
11302
11991
  }
11303
11992
  async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
11304
11993
  const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
11305
- const segmentsPath = path19.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
11994
+ const segmentsPath = path20.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
11306
11995
  const modelCalls = [];
11307
11996
  try {
11308
- const files = await readdir9(segmentsPath);
11997
+ const files = await readdir10(segmentsPath);
11309
11998
  for (const file of files) {
11310
11999
  if (!file.endsWith(".jsonl")) {
11311
12000
  continue;
11312
12001
  }
11313
- const content = await readFile12(path19.join(segmentsPath, file), "utf8");
12002
+ const content = await readFile12(path20.join(segmentsPath, file), "utf8");
11314
12003
  let currentTurnIsSubagent = false;
11315
12004
  for (const line of content.split("\n").filter(Boolean)) {
11316
12005
  const raw = parseJsonLine(line);
@@ -11355,7 +12044,7 @@ async function parseQoderCnSessionFile(filePath, options) {
11355
12044
  let cwd;
11356
12045
  let project = projectContext.project;
11357
12046
  let model;
11358
- const home = path19.resolve(stringOption(options.home) || os11.homedir());
12047
+ const home = path20.resolve(stringOption(options.home) || os11.homedir());
11359
12048
  const modelMap = await loadQoderCnModelNames(configDir2, home);
11360
12049
  const isSubagentSession = filePath.includes("subagents");
11361
12050
  const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
@@ -11390,7 +12079,7 @@ async function parseQoderCnSessionFile(filePath, options) {
11390
12079
  sessionId = stringField(raw, "sessionId") || sessionId;
11391
12080
  state.sessionId = sessionId;
11392
12081
  cwd = stringField(raw, "cwd") || cwd;
11393
- project = projectContext.project || (cwd ? path19.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
12082
+ project = projectContext.project || (cwd ? path20.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
11394
12083
  if (!ts) {
11395
12084
  continue;
11396
12085
  }
@@ -11726,7 +12415,7 @@ async function parseQoderCnSessionFile(filePath, options) {
11726
12415
  }
11727
12416
  dbModelCalls ??= await loadQoderDbModelCalls("QoderCN", parsedPaths.sessionId, modelMap);
11728
12417
  if (dbModelCalls.rootSessionId) {
11729
- const parentPath = path19.join(path19.dirname(filePath), `${dbModelCalls.rootSessionId}.jsonl`);
12418
+ const parentPath = path20.join(path20.dirname(filePath), `${dbModelCalls.rootSessionId}.jsonl`);
11730
12419
  const parentSourcePathHash = `sha256:${createStableHash(parentPath)}`;
11731
12420
  return withoutSubagentTurnEvents(validEvents).map((event) => rebuildEventIdentity3({
11732
12421
  ...event,
@@ -11879,28 +12568,28 @@ function extractQoderAttachedPrompt(content) {
11879
12568
  }
11880
12569
  async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
11881
12570
  const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
11882
- const isSubagent = filePath.includes(`${path19.sep}subagents${path19.sep}`);
12571
+ const isSubagent = filePath.includes(`${path20.sep}subagents${path20.sep}`);
11883
12572
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
11884
12573
  let cwds = [];
11885
12574
  for (const line of lines) {
11886
12575
  const raw = parseJsonLine(line);
11887
12576
  const cwd = raw ? stringField(raw, "cwd") : void 0;
11888
- if (cwd && path19.isAbsolute(cwd)) {
12577
+ if (cwd && path20.isAbsolute(cwd)) {
11889
12578
  cwds.push(cwd);
11890
12579
  }
11891
12580
  }
11892
12581
  if (isSubagent) {
11893
- if (inherited?.cwd && path19.isAbsolute(inherited.cwd)) {
12582
+ if (inherited?.cwd && path20.isAbsolute(inherited.cwd)) {
11894
12583
  cwds = [inherited.cwd];
11895
12584
  } else {
11896
- const parentSessionPath = path19.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
12585
+ const parentSessionPath = path20.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
11897
12586
  try {
11898
12587
  const parentText = await readFile12(parentSessionPath, "utf8");
11899
12588
  const parentCwds = [];
11900
12589
  for (const line of parentText.split("\n").filter(Boolean)) {
11901
12590
  const raw = parseJsonLine(line);
11902
12591
  const cwd = raw ? stringField(raw, "cwd") : void 0;
11903
- if (cwd && path19.isAbsolute(cwd)) {
12592
+ if (cwd && path20.isAbsolute(cwd)) {
11904
12593
  parentCwds.push(cwd);
11905
12594
  }
11906
12595
  }
@@ -11912,7 +12601,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
11912
12601
  }
11913
12602
  }
11914
12603
  const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
11915
- const project = inherited?.project || (cwds.length > 0 ? path19.basename(cwds[0]) : root ? path19.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
12604
+ const project = inherited?.project || (cwds.length > 0 ? path20.basename(cwds[0]) : root ? path20.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
11916
12605
  return {
11917
12606
  project,
11918
12607
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -11921,15 +12610,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
11921
12610
  async function gitRootFromCwds2(cwds) {
11922
12611
  const seen = /* @__PURE__ */ new Set();
11923
12612
  for (const cwd of cwds) {
11924
- let current = path19.resolve(cwd);
12613
+ let current = path20.resolve(cwd);
11925
12614
  while (!seen.has(current)) {
11926
12615
  seen.add(current);
11927
12616
  try {
11928
- await stat12(path19.join(current, ".git"));
12617
+ await stat13(path20.join(current, ".git"));
11929
12618
  return current;
11930
12619
  } catch {
11931
12620
  }
11932
- const parent = path19.dirname(current);
12621
+ const parent = path20.dirname(current);
11933
12622
  if (parent === current) {
11934
12623
  break;
11935
12624
  }
@@ -11940,12 +12629,12 @@ async function gitRootFromCwds2(cwds) {
11940
12629
  }
11941
12630
  function qoderCnProjectRootFromCwds(projectDir, cwds) {
11942
12631
  for (const cwd of cwds) {
11943
- let current = path19.resolve(cwd);
12632
+ let current = path20.resolve(cwd);
11944
12633
  while (true) {
11945
12634
  if (encodeQoderCnProjectPath(current) === projectDir) {
11946
12635
  return current;
11947
12636
  }
11948
- const parent = path19.dirname(current);
12637
+ const parent = path20.dirname(current);
11949
12638
  if (parent === current) {
11950
12639
  break;
11951
12640
  }
@@ -11955,14 +12644,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
11955
12644
  return void 0;
11956
12645
  }
11957
12646
  function encodeQoderCnProjectPath(value) {
11958
- return path19.resolve(value).split(path19.sep).join("-").replaceAll("_", "-");
12647
+ return path20.resolve(value).split(path20.sep).join("-").replaceAll("_", "-");
11959
12648
  }
11960
12649
  async function qoderCnProjectFromFilePath(filePath, options) {
11961
- const projectDir = path19.basename(path19.dirname(filePath));
11962
- const home = options ? path19.resolve(stringOption(options.home) || os11.homedir()) : os11.homedir();
12650
+ const projectDir = path20.basename(path20.dirname(filePath));
12651
+ const home = options ? path20.resolve(stringOption(options.home) || os11.homedir()) : os11.homedir();
11963
12652
  const resolved = await resolveQoderCnProjectPath(projectDir, home);
11964
12653
  if (resolved) {
11965
- return path19.basename(resolved);
12654
+ return path20.basename(resolved);
11966
12655
  }
11967
12656
  const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
11968
12657
  if (projectDir.startsWith(homePrefix)) {
@@ -11982,12 +12671,12 @@ async function resolveQoderCnProjectPath(projectDir, home) {
11982
12671
  while (projectDir.startsWith(`${currentEncoded}-`)) {
11983
12672
  let matchedChild;
11984
12673
  try {
11985
- const entries = await readdir9(current, { withFileTypes: true });
12674
+ const entries = await readdir10(current, { withFileTypes: true });
11986
12675
  for (const entry of entries) {
11987
12676
  if (!entry.isDirectory()) {
11988
12677
  continue;
11989
12678
  }
11990
- const candidate = path19.join(current, entry.name);
12679
+ const candidate = path20.join(current, entry.name);
11991
12680
  const encoded = encodeQoderCnProjectPath(candidate);
11992
12681
  if (encoded === projectDir) {
11993
12682
  return candidate;
@@ -12032,9 +12721,9 @@ function hookConfig6() {
12032
12721
  function qoderCnConfigDir(home, env) {
12033
12722
  const override = env?.QODER_CN_CONFIG_DIR;
12034
12723
  if (override && override.trim()) {
12035
- return path19.resolve(override);
12724
+ return path20.resolve(override);
12036
12725
  }
12037
- return path19.join(home, ".qoder-cn");
12726
+ return path20.join(home, ".qoder-cn");
12038
12727
  }
12039
12728
  function createQoderCnAdapter() {
12040
12729
  return {
@@ -12046,27 +12735,27 @@ function createQoderCnAdapter() {
12046
12735
  return qoderCnConfigDir(home, env);
12047
12736
  },
12048
12737
  installedPath(home, env) {
12049
- return path19.join(qoderCnConfigDir(home, env), "settings.json");
12738
+ return path20.join(qoderCnConfigDir(home, env), "settings.json");
12050
12739
  },
12051
12740
  async isInstalled(home, env) {
12052
12741
  return isHooksJsonInstalled(
12053
- path19.join(qoderCnConfigDir(home, env), "settings.json"),
12742
+ path20.join(qoderCnConfigDir(home, env), "settings.json"),
12054
12743
  "vibetime hook --agent qoder-cn"
12055
12744
  );
12056
12745
  },
12057
12746
  installEntries(home, env) {
12058
12747
  return [{
12059
12748
  kind: "hooks-json",
12060
- path: path19.join(qoderCnConfigDir(home, env), "settings.json"),
12749
+ path: path20.join(qoderCnConfigDir(home, env), "settings.json"),
12061
12750
  content: hookConfig6()
12062
12751
  }];
12063
12752
  },
12064
12753
  sourcePaths(home, env) {
12065
12754
  const base = qoderCnConfigDir(home, env);
12066
12755
  return [
12067
- path19.join(base, "projects"),
12068
- path19.join(base, ".qoder.json"),
12069
- path19.join(home, ".qoder.json")
12756
+ path20.join(base, "projects"),
12757
+ path20.join(base, ".qoder.json"),
12758
+ path20.join(home, ".qoder.json")
12070
12759
  ];
12071
12760
  },
12072
12761
  parseSessionFile: parseQoderCnSessionFile
@@ -12075,11 +12764,11 @@ function createQoderCnAdapter() {
12075
12764
 
12076
12765
  // src/adapters/qoder.ts
12077
12766
  import { existsSync } from "node:fs";
12078
- import { readdir as readdir10, readFile as readFile13, stat as stat13 } from "node:fs/promises";
12767
+ import { readdir as readdir11, readFile as readFile13, stat as stat14 } from "node:fs/promises";
12079
12768
  import os12 from "node:os";
12080
- import path20 from "node:path";
12769
+ import path21 from "node:path";
12081
12770
  function parseQoderPaths(filePath) {
12082
- const parts = filePath.split(path20.sep);
12771
+ const parts = filePath.split(path21.sep);
12083
12772
  const subagentsIdx = parts.lastIndexOf("subagents");
12084
12773
  let sessionId = "";
12085
12774
  let projectName = "";
@@ -12089,17 +12778,17 @@ function parseQoderPaths(filePath) {
12089
12778
  sessionId = parts[subagentsIdx - 1];
12090
12779
  projectName = parts[subagentsIdx - 2];
12091
12780
  const projectsIdx = parts.lastIndexOf("projects");
12092
- configDir2 = parts.slice(0, projectsIdx).join(path20.sep);
12093
- mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path20.sep);
12781
+ configDir2 = parts.slice(0, projectsIdx).join(path21.sep);
12782
+ mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path21.sep);
12094
12783
  } else {
12095
12784
  const filename = parts.at(-1) || "";
12096
- sessionId = path20.basename(filename, ".jsonl");
12785
+ sessionId = path21.basename(filename, ".jsonl");
12097
12786
  projectName = parts.at(-2) || "";
12098
12787
  if (projectName === "transcript") {
12099
12788
  projectName = parts.at(-3) || "";
12100
12789
  }
12101
12790
  const projectsIdx = parts.lastIndexOf("projects");
12102
- configDir2 = parts.slice(0, projectsIdx).join(path20.sep);
12791
+ configDir2 = parts.slice(0, projectsIdx).join(path21.sep);
12103
12792
  }
12104
12793
  return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
12105
12794
  }
@@ -12147,7 +12836,7 @@ async function loadQoderModelNames(configDir2, home) {
12147
12836
  }
12148
12837
  }
12149
12838
  }
12150
- const textsMap = await parseModelNamesFromDynamicTexts2(path20.join(configDir2, ".auth", "dynamic-texts.json"));
12839
+ const textsMap = await parseModelNamesFromDynamicTexts2(path21.join(configDir2, ".auth", "dynamic-texts.json"));
12151
12840
  for (const [key, val] of Object.entries(textsMap)) {
12152
12841
  if (!(key in map)) {
12153
12842
  map[key] = val;
@@ -12155,7 +12844,7 @@ async function loadQoderModelNames(configDir2, home) {
12155
12844
  }
12156
12845
  const siblingConfigDir = configDir2.replace(/\.qoder$/, ".qoder-cn");
12157
12846
  if (siblingConfigDir !== configDir2) {
12158
- const siblingMap = await parseModelNamesFromDynamicTexts2(path20.join(siblingConfigDir, ".auth", "dynamic-texts.json"));
12847
+ const siblingMap = await parseModelNamesFromDynamicTexts2(path21.join(siblingConfigDir, ".auth", "dynamic-texts.json"));
12159
12848
  for (const [key, val] of Object.entries(siblingMap)) {
12160
12849
  if (!(key in map)) {
12161
12850
  map[key] = val;
@@ -12163,11 +12852,11 @@ async function loadQoderModelNames(configDir2, home) {
12163
12852
  }
12164
12853
  }
12165
12854
  if (isQwenworkConfigRoot(configDir2)) {
12166
- for (const dir of [path20.join(home, ".qoder"), path20.join(home, ".qoder-cn")]) {
12167
- if (path20.resolve(dir) === path20.resolve(configDir2)) {
12855
+ for (const dir of [path21.join(home, ".qoder"), path21.join(home, ".qoder-cn")]) {
12856
+ if (path21.resolve(dir) === path21.resolve(configDir2)) {
12168
12857
  continue;
12169
12858
  }
12170
- const fallbackMap = await parseModelNamesFromDynamicTexts2(path20.join(dir, ".auth", "dynamic-texts.json"));
12859
+ const fallbackMap = await parseModelNamesFromDynamicTexts2(path21.join(dir, ".auth", "dynamic-texts.json"));
12171
12860
  for (const [key, val] of Object.entries(fallbackMap)) {
12172
12861
  if (!(key in map)) {
12173
12862
  map[key] = val;
@@ -12178,25 +12867,25 @@ async function loadQoderModelNames(configDir2, home) {
12178
12867
  return map;
12179
12868
  }
12180
12869
  function isQwenworkConfigRoot(configDir2) {
12181
- const name = path20.basename(path20.resolve(configDir2));
12870
+ const name = path21.basename(path21.resolve(configDir2));
12182
12871
  if (name === ".qwenworkcn" || name === ".qwenwork") {
12183
12872
  return true;
12184
12873
  }
12185
12874
  const override = process.env.QWENWORK_CONFIG_DIR;
12186
- return Boolean(override && override.trim() && path20.basename(path20.resolve(override)) === name);
12875
+ return Boolean(override && override.trim() && path21.basename(path21.resolve(override)) === name);
12187
12876
  }
12188
12877
  var FAILED_SEGMENT_STOP_REASONS = /* @__PURE__ */ new Set(["cancelled", "canceled", "error", "failed", "refusal"]);
12189
12878
  async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
12190
12879
  const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
12191
- const segmentsPath = path20.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
12880
+ const segmentsPath = path21.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
12192
12881
  const modelCalls = [];
12193
12882
  try {
12194
- const files = await readdir10(segmentsPath);
12883
+ const files = await readdir11(segmentsPath);
12195
12884
  for (const file of files) {
12196
12885
  if (!file.endsWith(".jsonl")) {
12197
12886
  continue;
12198
12887
  }
12199
- const content = await readFile13(path20.join(segmentsPath, file), "utf8");
12888
+ const content = await readFile13(path21.join(segmentsPath, file), "utf8");
12200
12889
  let currentTurnIsSubagent = false;
12201
12890
  for (const line of content.split("\n").filter(Boolean)) {
12202
12891
  const raw = parseJsonLine(line);
@@ -12241,7 +12930,7 @@ async function parseQoderSessionFile(filePath, options) {
12241
12930
  let cwd;
12242
12931
  let project = projectContext.project;
12243
12932
  let model;
12244
- const home = path20.resolve(stringOption(options.home) || os12.homedir());
12933
+ const home = path21.resolve(stringOption(options.home) || os12.homedir());
12245
12934
  const modelMap = await loadQoderModelNames(configDir2, home);
12246
12935
  const qwenworkRoot = isQwenworkConfigRoot(configDir2);
12247
12936
  const isSubagentSession = filePath.includes("subagents");
@@ -12277,7 +12966,7 @@ async function parseQoderSessionFile(filePath, options) {
12277
12966
  sessionId = stringField(raw, "sessionId") || sessionId;
12278
12967
  state.sessionId = sessionId;
12279
12968
  cwd = stringField(raw, "cwd") || cwd;
12280
- project = projectContext.project || (cwd ? path20.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
12969
+ project = projectContext.project || (cwd ? path21.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
12281
12970
  if (!ts) {
12282
12971
  continue;
12283
12972
  }
@@ -12588,7 +13277,7 @@ async function parseQoderSessionFile(filePath, options) {
12588
13277
  }
12589
13278
  dbModelCalls ??= await loadQoderDbModelCalls("Qoder", parsedPaths.sessionId, modelMap);
12590
13279
  if (dbModelCalls.rootSessionId) {
12591
- const parentPath = path20.join(path20.dirname(filePath), `${dbModelCalls.rootSessionId}.jsonl`);
13280
+ const parentPath = path21.join(path21.dirname(filePath), `${dbModelCalls.rootSessionId}.jsonl`);
12592
13281
  const parentSourcePathHash = `sha256:${createStableHash(parentPath)}`;
12593
13282
  return withoutSubagentTurnEvents(validEvents).map((event) => rebuildEventIdentity4({
12594
13283
  ...event,
@@ -12705,41 +13394,41 @@ function qoderExtractText(value) {
12705
13394
  }
12706
13395
  async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
12707
13396
  const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
12708
- const isSubagent = filePath.includes(`${path20.sep}subagents${path20.sep}`);
13397
+ const isSubagent = filePath.includes(`${path21.sep}subagents${path21.sep}`);
12709
13398
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
12710
13399
  let cwds = [];
12711
13400
  const workspaceDirs = [];
12712
13401
  for (const line of lines) {
12713
13402
  const raw = parseJsonLine(line);
12714
13403
  const cwd = raw ? stringField(raw, "cwd") : void 0;
12715
- if (cwd && path20.isAbsolute(cwd)) {
13404
+ if (cwd && path21.isAbsolute(cwd)) {
12716
13405
  cwds.push(cwd);
12717
13406
  }
12718
13407
  if (raw && stringField(raw, "type") === "workspace-directories") {
12719
13408
  for (const dir of arrayField5(raw, "directories")) {
12720
- if (typeof dir === "string" && path20.isAbsolute(dir)) {
13409
+ if (typeof dir === "string" && path21.isAbsolute(dir)) {
12721
13410
  workspaceDirs.push(dir);
12722
13411
  }
12723
13412
  }
12724
13413
  }
12725
13414
  }
12726
13415
  if (isSubagent) {
12727
- if (inherited?.cwd && path20.isAbsolute(inherited.cwd)) {
13416
+ if (inherited?.cwd && path21.isAbsolute(inherited.cwd)) {
12728
13417
  cwds = [inherited.cwd];
12729
13418
  } else {
12730
- const parentSessionPath = path20.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
13419
+ const parentSessionPath = path21.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
12731
13420
  try {
12732
13421
  const parentText = await readFile13(parentSessionPath, "utf8");
12733
13422
  const parentCwds = [];
12734
13423
  for (const line of parentText.split("\n").filter(Boolean)) {
12735
13424
  const raw = parseJsonLine(line);
12736
13425
  const cwd = raw ? stringField(raw, "cwd") : void 0;
12737
- if (cwd && path20.isAbsolute(cwd)) {
13426
+ if (cwd && path21.isAbsolute(cwd)) {
12738
13427
  parentCwds.push(cwd);
12739
13428
  }
12740
13429
  if (workspaceDirs.length === 0 && raw && stringField(raw, "type") === "workspace-directories") {
12741
13430
  for (const dir of arrayField5(raw, "directories")) {
12742
- if (typeof dir === "string" && path20.isAbsolute(dir)) {
13431
+ if (typeof dir === "string" && path21.isAbsolute(dir)) {
12743
13432
  workspaceDirs.push(dir);
12744
13433
  }
12745
13434
  }
@@ -12759,29 +13448,29 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
12759
13448
  }
12760
13449
  }
12761
13450
  const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
12762
- const project = inherited?.project || (cwds.length > 0 ? path20.basename(cwds[0]) : root ? path20.basename(root) : await qoderProjectFromFilePath(filePath, options));
13451
+ const project = inherited?.project || (cwds.length > 0 ? path21.basename(cwds[0]) : root ? path21.basename(root) : await qoderProjectFromFilePath(filePath, options));
12763
13452
  return {
12764
13453
  project,
12765
13454
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
12766
13455
  };
12767
13456
  }
12768
13457
  function pathInsideDir(candidate, dir) {
12769
- const resolvedDir = path20.resolve(dir);
12770
- const resolved = path20.resolve(candidate);
12771
- return resolved === resolvedDir || resolved.startsWith(`${resolvedDir}${path20.sep}`);
13458
+ const resolvedDir = path21.resolve(dir);
13459
+ const resolved = path21.resolve(candidate);
13460
+ return resolved === resolvedDir || resolved.startsWith(`${resolvedDir}${path21.sep}`);
12772
13461
  }
12773
13462
  async function gitRootFromCwds3(cwds) {
12774
13463
  const seen = /* @__PURE__ */ new Set();
12775
13464
  for (const cwd of cwds) {
12776
- let current = path20.resolve(cwd);
13465
+ let current = path21.resolve(cwd);
12777
13466
  while (!seen.has(current)) {
12778
13467
  seen.add(current);
12779
13468
  try {
12780
- await stat13(path20.join(current, ".git"));
13469
+ await stat14(path21.join(current, ".git"));
12781
13470
  return current;
12782
13471
  } catch {
12783
13472
  }
12784
- const parent = path20.dirname(current);
13473
+ const parent = path21.dirname(current);
12785
13474
  if (parent === current) {
12786
13475
  break;
12787
13476
  }
@@ -12792,12 +13481,12 @@ async function gitRootFromCwds3(cwds) {
12792
13481
  }
12793
13482
  function qoderProjectRootFromCwds(projectDir, cwds) {
12794
13483
  for (const cwd of cwds) {
12795
- let current = path20.resolve(cwd);
13484
+ let current = path21.resolve(cwd);
12796
13485
  while (true) {
12797
13486
  if (qoderEncodedVariants(current).includes(projectDir)) {
12798
13487
  return current;
12799
13488
  }
12800
- const parent = path20.dirname(current);
13489
+ const parent = path21.dirname(current);
12801
13490
  if (parent === current) {
12802
13491
  break;
12803
13492
  }
@@ -12807,7 +13496,7 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
12807
13496
  return void 0;
12808
13497
  }
12809
13498
  function rawQoderProjectPath(value) {
12810
- return path20.resolve(value).split(path20.sep).join("-");
13499
+ return path21.resolve(value).split(path21.sep).join("-");
12811
13500
  }
12812
13501
  function qoderEncodedVariants(value) {
12813
13502
  const raw = rawQoderProjectPath(value);
@@ -12828,11 +13517,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
12828
13517
  return void 0;
12829
13518
  }
12830
13519
  async function qoderProjectFromFilePath(filePath, options) {
12831
- const projectDir = path20.basename(path20.dirname(filePath));
12832
- const home = options ? path20.resolve(stringOption(options.home) || os12.homedir()) : os12.homedir();
13520
+ const projectDir = path21.basename(path21.dirname(filePath));
13521
+ const home = options ? path21.resolve(stringOption(options.home) || os12.homedir()) : os12.homedir();
12833
13522
  const resolved = await resolveQoderProjectPath(projectDir, home);
12834
13523
  if (resolved) {
12835
- return path20.basename(resolved);
13524
+ return path21.basename(resolved);
12836
13525
  }
12837
13526
  const suffix = qoderEncodedProjectSuffix(projectDir, home);
12838
13527
  if (suffix) {
@@ -12853,12 +13542,12 @@ async function resolveQoderProjectPath(projectDir, home) {
12853
13542
  while (currentEncodedVariants.some((prefix) => projectDir.startsWith(`${prefix}-`))) {
12854
13543
  let matchedChild;
12855
13544
  try {
12856
- const entries = await readdir10(current, { withFileTypes: true });
13545
+ const entries = await readdir11(current, { withFileTypes: true });
12857
13546
  for (const entry of entries) {
12858
13547
  if (!entry.isDirectory()) {
12859
13548
  continue;
12860
13549
  }
12861
- const candidate = path20.join(current, entry.name);
13550
+ const candidate = path21.join(current, entry.name);
12862
13551
  const candidateVariants = qoderEncodedVariants(candidate);
12863
13552
  if (candidateVariants.includes(projectDir)) {
12864
13553
  return candidate;
@@ -12903,19 +13592,19 @@ function hookConfig7() {
12903
13592
  function qoderConfigDir(home, env) {
12904
13593
  const override = env?.QODER_CONFIG_DIR;
12905
13594
  if (override && override.trim()) {
12906
- return path20.resolve(override);
13595
+ return path21.resolve(override);
12907
13596
  }
12908
- return path20.join(home, ".qoder");
13597
+ return path21.join(home, ".qoder");
12909
13598
  }
12910
13599
  function qwenworkConfigDir(home, env) {
12911
13600
  const override = env?.QWENWORK_CONFIG_DIR;
12912
13601
  if (override && override.trim()) {
12913
- return path20.resolve(override);
13602
+ return path21.resolve(override);
12914
13603
  }
12915
- return path20.join(home, ".qwenworkcn");
13604
+ return path21.join(home, ".qwenworkcn");
12916
13605
  }
12917
13606
  function qoderConfigDirs(home, env) {
12918
- return [...new Set([qoderConfigDir(home, env), qwenworkConfigDir(home, env)].map((dir) => path20.resolve(dir)))];
13607
+ return [...new Set([qoderConfigDir(home, env), qwenworkConfigDir(home, env)].map((dir) => path21.resolve(dir)))];
12919
13608
  }
12920
13609
  function createQoderAdapter() {
12921
13610
  return {
@@ -12927,11 +13616,11 @@ function createQoderAdapter() {
12927
13616
  return qoderConfigDir(home, env);
12928
13617
  },
12929
13618
  installedPath(home, env) {
12930
- return path20.join(qoderConfigDir(home, env), "settings.json");
13619
+ return path21.join(qoderConfigDir(home, env), "settings.json");
12931
13620
  },
12932
13621
  async isInstalled(home, env) {
12933
13622
  return isHooksJsonInstalled(
12934
- path20.join(qoderConfigDir(home, env), "settings.json"),
13623
+ path21.join(qoderConfigDir(home, env), "settings.json"),
12935
13624
  "vibetime hook --agent qoder"
12936
13625
  );
12937
13626
  },
@@ -12940,16 +13629,16 @@ function createQoderAdapter() {
12940
13629
  const targets = [primary, ...variants.filter((dir) => existsSync(dir))];
12941
13630
  return targets.map((base) => ({
12942
13631
  kind: "hooks-json",
12943
- path: path20.join(base, "settings.json"),
13632
+ path: path21.join(base, "settings.json"),
12944
13633
  content: hookConfig7()
12945
13634
  }));
12946
13635
  },
12947
13636
  sourcePaths(home, env) {
12948
- const paths = qoderConfigDirs(home, env).map((base2) => path20.join(base2, "projects"));
13637
+ const paths = qoderConfigDirs(home, env).map((base2) => path21.join(base2, "projects"));
12949
13638
  const base = qoderConfigDir(home, env);
12950
13639
  paths.push(
12951
- path20.join(base, ".qoder.json"),
12952
- path20.join(home, ".qoder.json")
13640
+ path21.join(base, ".qoder.json"),
13641
+ path21.join(home, ".qoder.json")
12953
13642
  );
12954
13643
  return paths;
12955
13644
  },
@@ -12985,35 +13674,35 @@ function normalizeId(id) {
12985
13674
  }
12986
13675
 
12987
13676
  // src/adapters/workbuddy.ts
12988
- import { readdir as readdir11, readFile as readFile14, stat as stat14 } from "node:fs/promises";
12989
- import path21 from "node:path";
13677
+ import { readdir as readdir12, readFile as readFile14, stat as stat15 } from "node:fs/promises";
13678
+ import path22 from "node:path";
12990
13679
  function workbuddyProjectsDir(home, env) {
12991
13680
  const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
12992
13681
  if (override && override.trim()) {
12993
- return path21.resolve(override, override.endsWith("projects") ? "" : "projects");
13682
+ return path22.resolve(override, override.endsWith("projects") ? "" : "projects");
12994
13683
  }
12995
- return path21.join(home, ".workbuddy", "projects");
13684
+ return path22.join(home, ".workbuddy", "projects");
12996
13685
  }
12997
13686
  function workbuddyBaseDir(home, env) {
12998
13687
  const override = env?.WORKBUDDY_HOME;
12999
13688
  if (override && override.trim()) {
13000
- return path21.resolve(override);
13689
+ return path22.resolve(override);
13001
13690
  }
13002
- return path21.join(home, ".workbuddy");
13691
+ return path22.join(home, ".workbuddy");
13003
13692
  }
13004
- function projectFromCwd(cwd, fallback) {
13693
+ function projectFromCwd2(cwd, fallback) {
13005
13694
  if (!cwd) {
13006
13695
  return fallback;
13007
13696
  }
13008
- return path21.basename(cwd) || fallback;
13697
+ return path22.basename(cwd) || fallback;
13009
13698
  }
13010
- function sourceHash(filePath) {
13699
+ function sourceHash2(filePath) {
13011
13700
  return `sha256:${createStableHash(filePath)}`;
13012
13701
  }
13013
- function makeEvent(event, line, filePath, options) {
13702
+ function makeEvent2(event, line, filePath, options) {
13014
13703
  const withRefs = withBackfillRefs(event, {
13015
13704
  filePath,
13016
- sourcePathHash: sourceHash(filePath),
13705
+ sourcePathHash: sourceHash2(filePath),
13017
13706
  lineNumber: line.lineNumber,
13018
13707
  topType: stringField(line.record, "type"),
13019
13708
  payloadType: stringField(line.record, "role") || stringField(line.record, "name"),
@@ -13093,7 +13782,7 @@ function isHiddenUserMessage(record) {
13093
13782
  return providerData.skipRun === true || providerData.isMeta === true || providerData.isCompactInternal === true || providerData.isCompact === true || providerData.isTeammateMessage === true || (stringField(providerData, "agentPurpose") || "").toLowerCase().includes("compact");
13094
13783
  }
13095
13784
  function workbuddySubagentRefs(lines) {
13096
- const refs2 = {};
13785
+ const refs3 = {};
13097
13786
  const keys = [
13098
13787
  ["parentSessionId", ["parent_session_id", "parentSessionId"]],
13099
13788
  ["parentToolCallId", ["parent_tool_call_id", "parentToolCallId"]],
@@ -13103,19 +13792,19 @@ function workbuddySubagentRefs(lines) {
13103
13792
  for (const line of lines) {
13104
13793
  const providerData = objectField(line.record, "providerData");
13105
13794
  for (const [ref, aliases] of keys) {
13106
- if (refs2[ref]) {
13795
+ if (refs3[ref]) {
13107
13796
  continue;
13108
13797
  }
13109
13798
  for (const alias of aliases) {
13110
13799
  const value = stringField(line.record, alias) || stringField(providerData, alias);
13111
13800
  if (value) {
13112
- refs2[ref] = value;
13801
+ refs3[ref] = value;
13113
13802
  break;
13114
13803
  }
13115
13804
  }
13116
13805
  }
13117
13806
  }
13118
- return refs2;
13807
+ return refs3;
13119
13808
  }
13120
13809
  function toolCallFailed(record) {
13121
13810
  const providerData = objectField(record, "providerData");
@@ -13143,10 +13832,10 @@ async function parseWorkbuddySessionFile(filePath, options) {
13143
13832
  }
13144
13833
  const events = [];
13145
13834
  const first = lines[0].record;
13146
- const sessionId = stringField(first, "sessionId") || path21.basename(filePath, ".jsonl");
13147
- const fallbackProject = path21.basename(path21.dirname(filePath));
13835
+ const sessionId = stringField(first, "sessionId") || path22.basename(filePath, ".jsonl");
13836
+ const fallbackProject = path22.basename(path22.dirname(filePath));
13148
13837
  const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
13149
- const project = projectFromCwd(cwd, fallbackProject);
13838
+ const project = projectFromCwd2(cwd, fallbackProject);
13150
13839
  const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
13151
13840
  const sessionPrefix = `workbuddy:${sessionId}`;
13152
13841
  const toolStarts = /* @__PURE__ */ new Map();
@@ -13161,7 +13850,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13161
13850
  return void 0;
13162
13851
  }
13163
13852
  const failed = turnLastAssistantStatus !== void 0 && ["incomplete", "failed", "cancelled"].includes(turnLastAssistantStatus);
13164
- return makeEvent({
13853
+ return makeEvent2({
13165
13854
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13166
13855
  ts: turnLastTs,
13167
13856
  type: failed ? "turn.failed" : "turn.completed",
@@ -13178,7 +13867,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13178
13867
  };
13179
13868
  const firstTs = lines.map((line) => timestampFrom(numberField(line.record, "timestamp"))).find(Boolean);
13180
13869
  if (firstTs) {
13181
- const event = makeEvent({
13870
+ const event = makeEvent2({
13182
13871
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13183
13872
  ts: firstTs,
13184
13873
  type: "session.started",
@@ -13218,7 +13907,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13218
13907
  turnLastAssistantStatus = void 0;
13219
13908
  const promptChars = contentLength(record.content);
13220
13909
  for (const event of [
13221
- makeEvent({
13910
+ makeEvent2({
13222
13911
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13223
13912
  ts,
13224
13913
  type: "turn.started",
@@ -13232,7 +13921,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13232
13921
  confidence: "derived",
13233
13922
  refs: { sourceId: `${sourceId}:turn` }
13234
13923
  }, line, filePath, options),
13235
- makeEvent({
13924
+ makeEvent2({
13236
13925
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13237
13926
  ts,
13238
13927
  type: "prompt.submitted",
@@ -13261,7 +13950,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13261
13950
  const metrics = workbuddyUsageMetrics(record);
13262
13951
  if (metrics) {
13263
13952
  const model = stringField(objectField(record, "providerData"), "model");
13264
- const usage = makeEvent({
13953
+ const usage = makeEvent2({
13265
13954
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13266
13955
  ts,
13267
13956
  type: "model.usage",
@@ -13290,7 +13979,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13290
13979
  const callId = stringField(record, "callId");
13291
13980
  if (tool && callId) {
13292
13981
  toolStarts.set(`${sessionId}:${callId}`, { line, ts, tool, callId });
13293
- const started = makeEvent({
13982
+ const started = makeEvent2({
13294
13983
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13295
13984
  ts,
13296
13985
  type: "tool.started",
@@ -13318,7 +14007,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13318
14007
  if (isPlainObject(toolInput)) {
13319
14008
  const fileActivities = claudeStyleToolFileActivities(tool, toolInput, ts, cwd);
13320
14009
  if (fileActivities.length > 0) {
13321
- const fileEvent = makeEvent({
14010
+ const fileEvent = makeEvent2({
13322
14011
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13323
14012
  ts,
13324
14013
  type: eventTypeFromFileActivities(fileActivities),
@@ -13344,7 +14033,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13344
14033
  const metrics = workbuddyUsageMetrics(record);
13345
14034
  const model = stringField(objectField(record, "providerData"), "model");
13346
14035
  if (metrics || model) {
13347
- const usage = makeEvent({
14036
+ const usage = makeEvent2({
13348
14037
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13349
14038
  ts,
13350
14039
  type: "model.usage",
@@ -13373,7 +14062,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13373
14062
  const start = toolStarts.get(`${sessionId}:${callId}`);
13374
14063
  const durationMs = start?.ts ? Math.max(0, Date.parse(ts) - Date.parse(start.ts)) : void 0;
13375
14064
  const failed = toolCallFailed(record);
13376
- const completed = makeEvent({
14065
+ const completed = makeEvent2({
13377
14066
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13378
14067
  ts,
13379
14068
  type: failed ? "tool.failed" : "tool.completed",
@@ -13405,7 +14094,7 @@ async function parseWorkbuddySessionFile(filePath, options) {
13405
14094
  }
13406
14095
  const lastTs = lastLine ? timestampFrom(numberField(lastLine.record, "timestamp")) : void 0;
13407
14096
  if (lastLine && lastTs) {
13408
- const event = makeEvent({
14097
+ const event = makeEvent2({
13409
14098
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13410
14099
  ts: lastTs,
13411
14100
  type: "session.ended",
@@ -13428,17 +14117,17 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
13428
14117
  const base = sourceRoot || workbuddyProjectsDir(home, env);
13429
14118
  const files = [];
13430
14119
  try {
13431
- const projects = await readdir11(base, { withFileTypes: true });
14120
+ const projects = await readdir12(base, { withFileTypes: true });
13432
14121
  for (const project of projects) {
13433
14122
  if (!project.isDirectory()) {
13434
14123
  continue;
13435
14124
  }
13436
- const projectDir = path21.join(base, project.name);
13437
- const entries = await readdir11(projectDir, { withFileTypes: true });
14125
+ const projectDir = path22.join(base, project.name);
14126
+ const entries = await readdir12(projectDir, { withFileTypes: true });
13438
14127
  for (const entry of entries) {
13439
14128
  if (entry.isFile() && entry.name.endsWith(".jsonl")) {
13440
- const filePath = path21.join(projectDir, entry.name);
13441
- const info = await stat14(filePath);
14129
+ const filePath = path22.join(projectDir, entry.name);
14130
+ const info = await stat15(filePath);
13442
14131
  files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
13443
14132
  }
13444
14133
  }
@@ -13475,18 +14164,18 @@ function createWorkbuddyAdapter() {
13475
14164
  return workbuddyProjectsDir(home, env);
13476
14165
  },
13477
14166
  installedPath(home, env) {
13478
- return path21.join(workbuddyBaseDir(home, env), "settings.json");
14167
+ return path22.join(workbuddyBaseDir(home, env), "settings.json");
13479
14168
  },
13480
14169
  async isInstalled(home, env) {
13481
14170
  return isHooksJsonInstalled(
13482
- path21.join(workbuddyBaseDir(home, env), "settings.json"),
14171
+ path22.join(workbuddyBaseDir(home, env), "settings.json"),
13483
14172
  "vibetime hook --agent workbuddy"
13484
14173
  );
13485
14174
  },
13486
14175
  installEntries(home, env) {
13487
14176
  return [{
13488
14177
  kind: "hooks-json",
13489
- path: path21.join(workbuddyBaseDir(home, env), "settings.json"),
14178
+ path: path22.join(workbuddyBaseDir(home, env), "settings.json"),
13490
14179
  content: hookConfig8()
13491
14180
  }];
13492
14181
  },
@@ -13499,22 +14188,22 @@ function createWorkbuddyAdapter() {
13499
14188
 
13500
14189
  // src/adapters/zcode.ts
13501
14190
  import { execFile } from "node:child_process";
13502
- import { readFile as readFile15, stat as stat15 } from "node:fs/promises";
13503
- import path22 from "node:path";
14191
+ import { readFile as readFile15, stat as stat16 } from "node:fs/promises";
14192
+ import path23 from "node:path";
13504
14193
  import { promisify as promisify2 } from "node:util";
13505
14194
  var execFileAsync = promisify2(execFile);
13506
14195
  function zcodeCliDir(home, env) {
13507
14196
  const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
13508
14197
  if (override && override.trim()) {
13509
- return path22.resolve(override, override.endsWith("cli") ? "" : "cli");
14198
+ return path23.resolve(override, override.endsWith("cli") ? "" : "cli");
13510
14199
  }
13511
- return path22.join(home, ".zcode", "cli");
14200
+ return path23.join(home, ".zcode", "cli");
13512
14201
  }
13513
14202
  function zcodeDbPath(home, env) {
13514
- return path22.join(zcodeCliDir(home, env), "db", "db.sqlite");
14203
+ return path23.join(zcodeCliDir(home, env), "db", "db.sqlite");
13515
14204
  }
13516
14205
  function zcodeConfigPath(home, env) {
13517
- return path22.join(zcodeCliDir(home, env), "config.json");
14206
+ return path23.join(zcodeCliDir(home, env), "config.json");
13518
14207
  }
13519
14208
  var zcodeHandler = (msg) => hookHandler("zcode", msg);
13520
14209
  function hookConfig9() {
@@ -13538,7 +14227,7 @@ var providerNameCache = null;
13538
14227
  async function loadProviderNames(configPath2) {
13539
14228
  let fileMtime = 0;
13540
14229
  try {
13541
- const info = await stat15(configPath2);
14230
+ const info = await stat16(configPath2);
13542
14231
  fileMtime = info.mtimeMs;
13543
14232
  } catch {
13544
14233
  return /* @__PURE__ */ new Map();
@@ -13562,19 +14251,19 @@ async function loadProviderNames(configPath2) {
13562
14251
  providerNameCache = { path: configPath2, mtimeMs: fileMtime, map };
13563
14252
  return map;
13564
14253
  }
13565
- function sourceHash2(filePath) {
14254
+ function sourceHash3(filePath) {
13566
14255
  return `sha256:${createStableHash(filePath)}`;
13567
14256
  }
13568
14257
  function projectFromDirectory(directory) {
13569
- return directory ? path22.basename(directory) || "zcode" : "zcode";
14258
+ return directory ? path23.basename(directory) || "zcode" : "zcode";
13570
14259
  }
13571
14260
  function isoFromMs(value) {
13572
14261
  return timestampFrom(typeof value === "number" ? value : Number(value));
13573
14262
  }
13574
- function makeEvent2(event, row, rowNumber, filePath, options) {
14263
+ function makeEvent3(event, row, rowNumber, filePath, options) {
13575
14264
  const withRefs = withBackfillRefs(event, {
13576
14265
  filePath,
13577
- sourcePathHash: sourceHash2(filePath),
14266
+ sourcePathHash: sourceHash3(filePath),
13578
14267
  lineNumber: rowNumber,
13579
14268
  topType: row.kind,
13580
14269
  payloadType: stringField(row, "status") || stringField(row, "query_source") || stringField(row, "tool_name"),
@@ -13582,7 +14271,7 @@ function makeEvent2(event, row, rowNumber, filePath, options) {
13582
14271
  });
13583
14272
  return validateCanonicalEvent(withRefs).valid ? withRefs : void 0;
13584
14273
  }
13585
- function refs(values) {
14274
+ function refs2(values) {
13586
14275
  const out = {};
13587
14276
  for (const [key, value] of Object.entries(values)) {
13588
14277
  if (value !== void 0 && value !== "") {
@@ -13739,7 +14428,7 @@ function resolveRootSessionId2(sessionId, sessions) {
13739
14428
  }
13740
14429
  return current;
13741
14430
  }
13742
- function sessionContext(row, sessions) {
14431
+ function sessionContext2(row, sessions) {
13743
14432
  const sessionId = stringField(row, "session_id") || stringField(row, "id") || "unknown";
13744
14433
  const session = sessions.get(sessionId);
13745
14434
  const cwd = stringField(session, "directory");
@@ -13761,16 +14450,16 @@ async function parseZCodeDb(filePath, options) {
13761
14450
  if (rows.length === 0) {
13762
14451
  return [];
13763
14452
  }
13764
- let candidate = path22.resolve(filePath);
14453
+ let candidate = path23.resolve(filePath);
13765
14454
  let configPath2 = "";
13766
14455
  for (let i = 0; i < 12; i++) {
13767
- const probe = path22.join(candidate, ".zcode", "v2", "config.json");
14456
+ const probe = path23.join(candidate, ".zcode", "v2", "config.json");
13768
14457
  try {
13769
- await stat15(probe);
14458
+ await stat16(probe);
13770
14459
  configPath2 = probe;
13771
14460
  break;
13772
14461
  } catch {
13773
- const parent = path22.dirname(candidate);
14462
+ const parent = path23.dirname(candidate);
13774
14463
  if (parent === candidate) break;
13775
14464
  candidate = parent;
13776
14465
  }
@@ -13794,8 +14483,8 @@ async function parseZCodeDb(filePath, options) {
13794
14483
  if (!id || !ts) {
13795
14484
  return;
13796
14485
  }
13797
- const ctx = sessionContext(row, sessions);
13798
- const event = makeEvent2({
14486
+ const ctx = sessionContext2(row, sessions);
14487
+ const event = makeEvent3({
13799
14488
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13800
14489
  ts,
13801
14490
  type: "session.started",
@@ -13807,7 +14496,7 @@ async function parseZCodeDb(filePath, options) {
13807
14496
  parentAgentInstanceId: ctx.parentSessionId,
13808
14497
  agent: "zcode",
13809
14498
  confidence: "exact",
13810
- refs: refs({
14499
+ refs: refs2({
13811
14500
  sourceId: `${id}:session`,
13812
14501
  zcodeTaskType: stringField(row, "task_type"),
13813
14502
  zcodeTitleHash: stringField(row, "title") ? `sha256:${createStableHash(stringField(row, "title"))}` : void 0
@@ -13819,7 +14508,7 @@ async function parseZCodeDb(filePath, options) {
13819
14508
  const linesAdded = numberField(row, "summary_additions");
13820
14509
  const linesRemoved = numberField(row, "summary_deletions");
13821
14510
  const filesChanged = numberField(row, "summary_files");
13822
- const completed = makeEvent2({
14511
+ const completed = makeEvent3({
13823
14512
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13824
14513
  ts: completedTs,
13825
14514
  type: "session.ended",
@@ -13844,12 +14533,12 @@ async function parseZCodeDb(filePath, options) {
13844
14533
  if (!rawTurnId || !ts) {
13845
14534
  return;
13846
14535
  }
13847
- const ctx = sessionContext(row, sessions);
14536
+ const ctx = sessionContext2(row, sessions);
13848
14537
  if (ctx.isSubagent) {
13849
14538
  return;
13850
14539
  }
13851
14540
  const turnId = `zcode:${rawTurnId}`;
13852
- const started = makeEvent2({
14541
+ const started = makeEvent3({
13853
14542
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13854
14543
  ts,
13855
14544
  type: "turn.started",
@@ -13867,7 +14556,7 @@ async function parseZCodeDb(filePath, options) {
13867
14556
  const completedTs = isoFromMs(numberField(row, "completed_at"));
13868
14557
  if (completedTs) {
13869
14558
  const status = stringField(row, "status");
13870
- const completed = makeEvent2({
14559
+ const completed = makeEvent3({
13871
14560
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13872
14561
  ts: completedTs,
13873
14562
  type: "turn.completed",
@@ -13886,7 +14575,7 @@ async function parseZCodeDb(filePath, options) {
13886
14575
  toolCalls: numberField(row, "tool_call_count")
13887
14576
  },
13888
14577
  confidence: "exact",
13889
- refs: refs({ sourceId: `${rawTurnId}:completed`, zcodeStatus: status })
14578
+ refs: refs2({ sourceId: `${rawTurnId}:completed`, zcodeStatus: status })
13890
14579
  }, row, rowNumber, filePath, options);
13891
14580
  if (completed) events.push(completed);
13892
14581
  }
@@ -13897,9 +14586,9 @@ async function parseZCodeDb(filePath, options) {
13897
14586
  if (!ts) {
13898
14587
  return;
13899
14588
  }
13900
- const ctx = sessionContext(row, sessions);
14589
+ const ctx = sessionContext2(row, sessions);
13901
14590
  const modelId = stringField(row, "model_id");
13902
- const usage = makeEvent2({
14591
+ const usage = makeEvent3({
13903
14592
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13904
14593
  ts,
13905
14594
  type: "model.usage",
@@ -13916,7 +14605,7 @@ async function parseZCodeDb(filePath, options) {
13916
14605
  success: stringField(row, "status") === "completed",
13917
14606
  metrics: modelMetrics(row),
13918
14607
  confidence: "exact",
13919
- refs: refs({
14608
+ refs: refs2({
13920
14609
  sourceId: stringField(row, "id") || `${ctx.rawSessionId}:model:${rowNumber}`,
13921
14610
  zcodeQuerySource: stringField(row, "query_source"),
13922
14611
  zcodeMode: stringField(row, "mode"),
@@ -13937,10 +14626,10 @@ async function parseZCodeDb(filePath, options) {
13937
14626
  if (!startedTs) {
13938
14627
  return;
13939
14628
  }
13940
- const ctx = sessionContext(row, sessions);
14629
+ const ctx = sessionContext2(row, sessions);
13941
14630
  const turnId = !ctx.isSubagent && stringField(row, "turn_id") ? `zcode:${stringField(row, "turn_id")}` : void 0;
13942
14631
  const spanId = `${ctx.sessionId}:tool:${toolCallId}`;
13943
- const started = makeEvent2({
14632
+ const started = makeEvent3({
13944
14633
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13945
14634
  ts: startedTs,
13946
14635
  type: "tool.started",
@@ -13954,7 +14643,7 @@ async function parseZCodeDb(filePath, options) {
13954
14643
  agent: "zcode",
13955
14644
  tool,
13956
14645
  confidence: "exact",
13957
- refs: refs({
14646
+ refs: refs2({
13958
14647
  sourceId: `${toolCallId}:start`,
13959
14648
  zcodeSideEffectScope: stringField(row, "side_effect_scope"),
13960
14649
  zcodeApprovalStatus: stringField(row, "approval_status")
@@ -13963,7 +14652,7 @@ async function parseZCodeDb(filePath, options) {
13963
14652
  if (started) events.push(started);
13964
14653
  if (completedTs) {
13965
14654
  const status = stringField(row, "status");
13966
- const completed = makeEvent2({
14655
+ const completed = makeEvent3({
13967
14656
  schemaVersion: AGENT_TIME_SCHEMA_VERSION,
13968
14657
  ts: completedTs,
13969
14658
  type: status === "completed" ? "tool.completed" : "tool.failed",
@@ -13983,7 +14672,7 @@ async function parseZCodeDb(filePath, options) {
13983
14672
  bytesRead: numberField(row, "output_bytes")
13984
14673
  },
13985
14674
  confidence: "exact",
13986
- refs: refs({
14675
+ refs: refs2({
13987
14676
  sourceId: `${toolCallId}:completed`,
13988
14677
  zcodeStatus: status,
13989
14678
  zcodeExitCode: numberField(row, "exit_code"),
@@ -13998,13 +14687,13 @@ async function parseZCodeDb(filePath, options) {
13998
14687
  }
13999
14688
  async function zcodeBackfillFiles(sourceRoot, home, env) {
14000
14689
  const candidate = sourceRoot || zcodeDbPath(home, env);
14001
- const filePath = candidate.endsWith(".sqlite") ? candidate : path22.join(candidate, "db", "db.sqlite");
14690
+ const filePath = candidate.endsWith(".sqlite") ? candidate : path23.join(candidate, "db", "db.sqlite");
14002
14691
  try {
14003
- const info = await stat15(filePath);
14692
+ const info = await stat16(filePath);
14004
14693
  let modifiedMs = info.mtimeMs;
14005
14694
  for (const suffix of ["-wal", "-shm"]) {
14006
14695
  try {
14007
- const sidecar = await stat15(`${filePath}${suffix}`);
14696
+ const sidecar = await stat16(`${filePath}${suffix}`);
14008
14697
  modifiedMs = Math.max(modifiedMs, sidecar.mtimeMs);
14009
14698
  } catch {
14010
14699
  }
@@ -14048,49 +14737,49 @@ function createZCodeAdapter() {
14048
14737
 
14049
14738
  // src/adapters/zed.ts
14050
14739
  import os13 from "node:os";
14051
- import path23 from "node:path";
14740
+ import path24 from "node:path";
14052
14741
  function zedThreadsCandidates(home, env) {
14053
14742
  const candidates = [];
14054
14743
  const platform2 = process.platform;
14055
14744
  if (platform2 === "darwin") {
14056
- candidates.push(path23.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
14745
+ candidates.push(path24.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
14057
14746
  } else if (platform2 === "win32") {
14058
14747
  const appdata = env?.APPDATA;
14059
14748
  if (appdata && appdata.trim()) {
14060
- candidates.push(path23.join(path23.resolve(appdata), "Zed", "threads", "threads.db"));
14749
+ candidates.push(path24.join(path24.resolve(appdata), "Zed", "threads", "threads.db"));
14061
14750
  }
14062
- candidates.push(path23.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
14751
+ candidates.push(path24.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
14063
14752
  } else {
14064
14753
  const xdgData = env?.XDG_DATA_HOME;
14065
14754
  if (xdgData && xdgData.trim()) {
14066
- candidates.push(path23.join(path23.resolve(xdgData), "zed", "threads", "threads.db"));
14755
+ candidates.push(path24.join(path24.resolve(xdgData), "zed", "threads", "threads.db"));
14067
14756
  }
14068
- candidates.push(path23.join(home, ".local", "share", "zed", "threads", "threads.db"));
14757
+ candidates.push(path24.join(home, ".local", "share", "zed", "threads", "threads.db"));
14069
14758
  const xdgConfig = env?.XDG_CONFIG_HOME;
14070
14759
  if (xdgConfig && xdgConfig.trim()) {
14071
- candidates.push(path23.join(path23.resolve(xdgConfig), "zed", "threads", "threads.db"));
14760
+ candidates.push(path24.join(path24.resolve(xdgConfig), "zed", "threads", "threads.db"));
14072
14761
  }
14073
- candidates.push(path23.join(home, ".config", "zed", "threads", "threads.db"));
14762
+ candidates.push(path24.join(home, ".config", "zed", "threads", "threads.db"));
14074
14763
  }
14075
14764
  return candidates;
14076
14765
  }
14077
14766
  function zedConfigDir(home, env) {
14078
14767
  const platform2 = process.platform;
14079
14768
  if (platform2 === "darwin") {
14080
- return path23.join(home, "Library", "Application Support", "Zed");
14769
+ return path24.join(home, "Library", "Application Support", "Zed");
14081
14770
  }
14082
14771
  if (platform2 === "win32") {
14083
14772
  const appdata = env?.APPDATA;
14084
14773
  if (appdata && appdata.trim()) {
14085
- return path23.join(path23.resolve(appdata), "Zed");
14774
+ return path24.join(path24.resolve(appdata), "Zed");
14086
14775
  }
14087
- return path23.join(home, "AppData", "Roaming", "Zed");
14776
+ return path24.join(home, "AppData", "Roaming", "Zed");
14088
14777
  }
14089
14778
  const xdgConfig = env?.XDG_CONFIG_HOME;
14090
14779
  if (xdgConfig && xdgConfig.trim()) {
14091
- return path23.join(path23.resolve(xdgConfig), "zed");
14780
+ return path24.join(path24.resolve(xdgConfig), "zed");
14092
14781
  }
14093
- return path23.join(home, ".config", "zed");
14782
+ return path24.join(home, ".config", "zed");
14094
14783
  }
14095
14784
  function baseZedEvent(event) {
14096
14785
  return {
@@ -14154,7 +14843,7 @@ async function parseZedSessionFile(dbPath, options) {
14154
14843
  const folderRaw = row.folder_paths || "";
14155
14844
  const folder = folderRaw.split(/[\n,]/).map((s) => s.trim()).find(Boolean);
14156
14845
  const cwd = folder || void 0;
14157
- const project = cwd ? path23.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
14846
+ const project = cwd ? path24.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
14158
14847
  let json;
14159
14848
  try {
14160
14849
  const bytes = row.data_type === "zstd" ? decompress2(new Uint8Array(row.data)) : new Uint8Array(row.data);
@@ -14400,19 +15089,19 @@ async function parseZedSessionFile(dbPath, options) {
14400
15089
  return events.filter((event) => matchesBackfillFilters(event, options));
14401
15090
  }
14402
15091
  async function zedBackfillFiles(sourceRoot, home = os13.homedir(), env) {
14403
- const { stat: stat18 } = await import("node:fs/promises");
15092
+ const { stat: stat19 } = await import("node:fs/promises");
14404
15093
  if (sourceRoot) {
14405
15094
  if (!sourceRoot.endsWith(".db")) {
14406
15095
  return [];
14407
15096
  }
14408
- const info = await stat18(sourceRoot).catch(() => null);
15097
+ const info = await stat19(sourceRoot).catch(() => null);
14409
15098
  if (!info) {
14410
15099
  return [];
14411
15100
  }
14412
15101
  return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
14413
15102
  }
14414
15103
  for (const candidatePath of zedThreadsCandidates(home, env)) {
14415
- const info = await stat18(candidatePath).catch(() => null);
15104
+ const info = await stat19(candidatePath).catch(() => null);
14416
15105
  if (info) {
14417
15106
  return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
14418
15107
  }
@@ -14429,7 +15118,7 @@ function createZedAdapter() {
14429
15118
  return zedConfigDir(home, env);
14430
15119
  },
14431
15120
  installedPath(home, env) {
14432
- return path23.join(zedConfigDir(home, env), "vibetime-marker");
15121
+ return path24.join(zedConfigDir(home, env), "vibetime-marker");
14433
15122
  },
14434
15123
  async isInstalled() {
14435
15124
  return false;
@@ -15244,19 +15933,19 @@ async function uninstallGeneratedFile(filePath, { dryRun, onWrite }) {
15244
15933
  import { randomUUID } from "node:crypto";
15245
15934
  import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "node:fs";
15246
15935
  import { homedir, hostname } from "node:os";
15247
- import path24 from "node:path";
15936
+ import path25 from "node:path";
15248
15937
  function disabledBackfillSourceSet(config) {
15249
15938
  const list = Array.isArray(config.disabledSources) ? config.disabledSources : [];
15250
15939
  return new Set(list.map((id) => String(id).trim()).filter(Boolean));
15251
15940
  }
15252
15941
  function configDir(home = homedir()) {
15253
- return path24.join(home, ".vibetime");
15942
+ return path25.join(home, ".vibetime");
15254
15943
  }
15255
15944
  function configPath(home = homedir()) {
15256
- return path24.join(configDir(home), "config.json");
15945
+ return path25.join(configDir(home), "config.json");
15257
15946
  }
15258
15947
  function machineIdPath(home = homedir()) {
15259
- return path24.join(configDir(home), "machine-id");
15948
+ return path25.join(configDir(home), "machine-id");
15260
15949
  }
15261
15950
  function readConfig(home = homedir()) {
15262
15951
  const file = configPath(home);
@@ -15303,15 +15992,15 @@ function defaultMachineName() {
15303
15992
  init_fs();
15304
15993
 
15305
15994
  // src/lib/logger.ts
15306
- import { appendFile, mkdir as mkdir5, rename as rename2, stat as stat16 } from "node:fs/promises";
15995
+ import { appendFile, mkdir as mkdir5, rename as rename2, stat as stat17 } from "node:fs/promises";
15307
15996
  import { homedir as homedir2 } from "node:os";
15308
- import path25 from "node:path";
15997
+ import path26 from "node:path";
15309
15998
  var MAX_BYTES = 1 * 1024 * 1024;
15310
15999
  function logDir(home = homedir2()) {
15311
- return path25.join(home, ".vibetime", "logs");
16000
+ return path26.join(home, ".vibetime", "logs");
15312
16001
  }
15313
16002
  function logPath(home = homedir2(), name = "cli.log") {
15314
- return path25.join(logDir(home), name);
16003
+ return path26.join(logDir(home), name);
15315
16004
  }
15316
16005
  function serializeError(error) {
15317
16006
  if (error instanceof Error) {
@@ -15321,7 +16010,7 @@ function serializeError(error) {
15321
16010
  }
15322
16011
  async function rotateIfNeeded(file) {
15323
16012
  try {
15324
- const info = await stat16(file);
16013
+ const info = await stat17(file);
15325
16014
  if (info.size > MAX_BYTES) {
15326
16015
  await rename2(file, `${file}.1`).catch(() => {
15327
16016
  });
@@ -15486,8 +16175,8 @@ function buildHeaders(token, machine) {
15486
16175
  ...machine?.platform ? { "x-machine-platform": machine.platform } : {}
15487
16176
  };
15488
16177
  }
15489
- function joinUrl(base, path27) {
15490
- return new URL(path27, base.endsWith("/") ? base : `${base}/`).toString();
16178
+ function joinUrl(base, path28) {
16179
+ return new URL(path28, base.endsWith("/") ? base : `${base}/`).toString();
15491
16180
  }
15492
16181
  async function postRollupBatch(remote, rollups, options = {}) {
15493
16182
  const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
@@ -15579,6 +16268,7 @@ function createRegistry() {
15579
16268
  registry.register(createKimiCodeAdapter());
15580
16269
  registry.register(createCursorAdapter());
15581
16270
  registry.register(createGrokBotAdapter());
16271
+ registry.register(createHermesAdapter());
15582
16272
  return registry;
15583
16273
  }
15584
16274
  var defaultContext = {
@@ -16143,6 +16833,9 @@ async function listBackfillSourceFiles(source, options, ctx) {
16143
16833
  if (source.id === "grok-bot") {
16144
16834
  return grokBotBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env, options);
16145
16835
  }
16836
+ if (source.id === "hermes") {
16837
+ return hermesBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
16838
+ }
16146
16839
  if (source.id === "pi") {
16147
16840
  return piBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
16148
16841
  }
@@ -16150,7 +16843,7 @@ async function listBackfillSourceFiles(source, options, ctx) {
16150
16843
  const fileLists = await Promise.all(roots.map((r) => listJsonlFiles(r)));
16151
16844
  const files = fileLists.flat().sort().slice(0, numberOption(options.limit) || void 0);
16152
16845
  return Promise.all(files.map(async (filePath) => {
16153
- const info = await stat17(filePath);
16846
+ const info = await stat18(filePath);
16154
16847
  return { path: filePath, modifiedAt: info.mtime.toISOString() };
16155
16848
  }));
16156
16849
  }
@@ -16482,13 +17175,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
16482
17175
  return picked;
16483
17176
  }
16484
17177
  function backfillIncrementalStatePath(home) {
16485
- return path26.join(home, ".vibetime", "backfill-state.json");
17178
+ return path27.join(home, ".vibetime", "backfill-state.json");
16486
17179
  }
16487
17180
  function syncLocalTriggerStatePath(home) {
16488
- return path26.join(home, ".vibetime", "sync-local-trigger.json");
17181
+ return path27.join(home, ".vibetime", "sync-local-trigger.json");
16489
17182
  }
16490
17183
  function syncLocalTriggerLockPath(home) {
16491
- return path26.join(home, ".vibetime", "sync-local-trigger.lock");
17184
+ return path27.join(home, ".vibetime", "sync-local-trigger.lock");
16492
17185
  }
16493
17186
  function backfillRemoteKey(baseUrl) {
16494
17187
  try {
@@ -16550,7 +17243,7 @@ async function readBackfillIncrementalStateFile(home, ctx) {
16550
17243
  }
16551
17244
  async function writeBackfillIncrementalStateFile(home, file) {
16552
17245
  const statePath = backfillIncrementalStatePath(home);
16553
- await mkdir6(path26.dirname(statePath), { recursive: true });
17246
+ await mkdir6(path27.dirname(statePath), { recursive: true });
16554
17247
  await writeFile5(statePath, `${JSON.stringify(file, null, 2)}
16555
17248
  `, "utf8");
16556
17249
  }
@@ -16599,7 +17292,7 @@ async function readSyncLocalTriggerState(statePath) {
16599
17292
  return nextState;
16600
17293
  }
16601
17294
  async function writeSyncLocalTriggerState(statePath, state) {
16602
- await mkdir6(path26.dirname(statePath), { recursive: true });
17295
+ await mkdir6(path27.dirname(statePath), { recursive: true });
16603
17296
  await writeFile5(statePath, `${JSON.stringify(state, null, 2)}
16604
17297
  `, "utf8");
16605
17298
  }
@@ -16614,12 +17307,12 @@ async function readSyncLocalLock(lockPath) {
16614
17307
  return { pid: lock.pid, startedAt: lock.startedAt };
16615
17308
  }
16616
17309
  async function writeSyncLocalLock(lockPath, lock) {
16617
- await mkdir6(path26.dirname(lockPath), { recursive: true });
17310
+ await mkdir6(path27.dirname(lockPath), { recursive: true });
16618
17311
  await writeFile5(lockPath, `${JSON.stringify(lock, null, 2)}
16619
17312
  `, "utf8");
16620
17313
  }
16621
17314
  async function acquireSyncLocalLock(lockPath, lock) {
16622
- await mkdir6(path26.dirname(lockPath), { recursive: true });
17315
+ await mkdir6(path27.dirname(lockPath), { recursive: true });
16623
17316
  try {
16624
17317
  const handle = await open(lockPath, "wx");
16625
17318
  try {
@@ -16699,10 +17392,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
16699
17392
  if (cliPath.endsWith(".ts")) {
16700
17393
  return ["--import", "tsx", cliPath];
16701
17394
  }
16702
- return [path26.resolve(path26.dirname(cliPath), "../bin/vibetime.mjs")];
17395
+ return [path27.resolve(path27.dirname(cliPath), "../bin/vibetime.mjs")];
16703
17396
  }
16704
17397
  function resolveHome3(options, ctx) {
16705
- return path26.resolve(stringOption(options.home) || ctx.env.HOME || os14.homedir());
17398
+ return path27.resolve(stringOption(options.home) || ctx.env.HOME || os14.homedir());
16706
17399
  }
16707
17400
  function requestedTargets(options) {
16708
17401
  const value = options.target || options.targets;