@yhong91/vibetime 0.1.70 → 0.1.71

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