@yhong91/vibetime 0.1.24 → 0.1.26

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 +659 -165
  2. package/package.json +1 -1
package/bin/vibetime.mjs CHANGED
@@ -159,9 +159,9 @@ var init_fs = __esm({
159
159
 
160
160
  // src/cli.ts
161
161
  import { spawn as spawn2, spawnSync } from "node:child_process";
162
- import { mkdir as mkdir5, open, rm, stat as stat12, writeFile as writeFile4 } from "node:fs/promises";
162
+ import { mkdir as mkdir5, open, rm, stat as stat13, writeFile as writeFile4 } from "node:fs/promises";
163
163
  import os9 from "node:os";
164
- import path21 from "node:path";
164
+ import path22 from "node:path";
165
165
  import { fileURLToPath } from "node:url";
166
166
 
167
167
  // ../shared/src/index.ts
@@ -191,13 +191,15 @@ var TELEMETRY_EVENT_TYPES = [
191
191
  "model.usage",
192
192
  "permission.requested",
193
193
  "permission.resolved",
194
+ "permission.granted",
195
+ "permission.denied",
194
196
  "context.compacted",
195
197
  "test.completed",
196
198
  "git.changed",
197
199
  "agent.operation"
198
200
  ];
199
201
  var FILE_ACTIVITY_OPERATIONS = ["read", "search", "create", "write", "edit", "delete"];
200
- var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "copilot", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn", "workbuddy", "zcode"];
202
+ var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "copilot", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn", "workbuddy", "zcode", "grok-build"];
201
203
  function createWorkspaceId(input) {
202
204
  const basis = input.repoUrl || input.repoRoot || input.projectName || "unknown";
203
205
  return `workspace_${fnv1a(basis)}`;
@@ -1201,7 +1203,7 @@ function countTextLines(text) {
1201
1203
  }
1202
1204
 
1203
1205
  // src/lib/constants.ts
1204
- var PACKAGE_VERSION = true ? "0.1.24" : "0.1.1";
1206
+ var PACKAGE_VERSION = true ? "0.1.26" : "0.1.1";
1205
1207
  var DEFAULT_API_URL = "http://121.196.224.82:3001";
1206
1208
  var DEFAULT_BACKFILL_BATCH_SIZE = 50;
1207
1209
  var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
@@ -4029,8 +4031,8 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
4029
4031
  }
4030
4032
  const filePath = path9.join(traceDir, entry);
4031
4033
  try {
4032
- const stat13 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
4033
- files.push({ path: filePath, modifiedAt: stat13.mtime.toISOString() });
4034
+ const stat14 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
4035
+ files.push({ path: filePath, modifiedAt: stat14.mtime.toISOString() });
4034
4036
  } catch {
4035
4037
  }
4036
4038
  }
@@ -5058,9 +5060,497 @@ function createCopilotAdapter() {
5058
5060
  };
5059
5061
  }
5060
5062
 
5063
+ // src/adapters/grok-build.ts
5064
+ import { readdir as readdir6, readFile as readFile8, stat as stat7 } from "node:fs/promises";
5065
+ import path13 from "node:path";
5066
+ init_fs();
5067
+ var SOURCE_ID = "grok-build";
5068
+ var AGENT_NAME = "grok-build";
5069
+ var HOOK_COMMAND = `vibetime hook --agent ${SOURCE_ID}`;
5070
+ function grokHome(home, env) {
5071
+ const override = env?.GROK_HOME;
5072
+ if (override && override.trim()) {
5073
+ return path13.resolve(override);
5074
+ }
5075
+ return path13.join(home, ".grok");
5076
+ }
5077
+ function grokHooksPath(home, env) {
5078
+ return path13.join(grokHome(home, env), "hooks", "vibetime.json");
5079
+ }
5080
+ function grokSessionsDir(home, env) {
5081
+ return path13.join(grokHome(home, env), "sessions");
5082
+ }
5083
+ async function grokBackfillFiles(sourceRoot, home, env) {
5084
+ const root = sourceRoot || grokSessionsDir(home, env);
5085
+ const files = [];
5086
+ async function walk(dir) {
5087
+ let entries;
5088
+ try {
5089
+ entries = await readdir6(dir, { withFileTypes: true });
5090
+ } catch {
5091
+ return;
5092
+ }
5093
+ for (const entry of entries) {
5094
+ const entryPath = path13.join(dir, entry.name);
5095
+ if (entry.isDirectory()) {
5096
+ await walk(entryPath);
5097
+ continue;
5098
+ }
5099
+ if (!entry.isFile() || entry.name !== "summary.json") {
5100
+ continue;
5101
+ }
5102
+ try {
5103
+ const info = await stat7(entryPath);
5104
+ files.push({ path: entryPath, modifiedAt: info.mtime.toISOString() });
5105
+ } catch {
5106
+ }
5107
+ }
5108
+ }
5109
+ await walk(root);
5110
+ return files.sort((a, b) => a.path.localeCompare(b.path));
5111
+ }
5112
+ async function parseGrokSessionFile(filePath, options) {
5113
+ const sessionDir = resolveSessionDir(filePath);
5114
+ if (!sessionDir) {
5115
+ return [];
5116
+ }
5117
+ const summaryPath = path13.join(sessionDir, "summary.json");
5118
+ const eventsPath = path13.join(sessionDir, "events.jsonl");
5119
+ const signalsPath = path13.join(sessionDir, "signals.json");
5120
+ const updatesPath = path13.join(sessionDir, "updates.jsonl");
5121
+ const summary = await readJsonIfExists(summaryPath);
5122
+ if (!isPlainObject(summary)) {
5123
+ return [];
5124
+ }
5125
+ const info = objectField(summary, "info");
5126
+ const sessionId = stringField(info, "id") || path13.basename(sessionDir);
5127
+ const cwd = stringField(info, "cwd");
5128
+ const project = cwd ? path13.basename(cwd) : void 0;
5129
+ const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
5130
+ const model = stringField(summary, "current_model_id");
5131
+ const createdAt = timestampFrom(summary.created_at) || timestampFrom(summary.createdAt);
5132
+ const updatedAt = timestampFrom(summary.updated_at) || timestampFrom(summary.last_active_at) || timestampFrom(summary.updatedAt) || createdAt;
5133
+ if (!createdAt) {
5134
+ return [];
5135
+ }
5136
+ const sourcePathHash = `sha256:${createStableHash(summaryPath)}`;
5137
+ const toolInputs = await loadToolInputsFromUpdates(updatesPath);
5138
+ const events = [];
5139
+ const push = (event, lineNumber2, topType, payloadType) => {
5140
+ const validated = validateCanonicalEvent(event);
5141
+ if (!validated.valid) {
5142
+ return;
5143
+ }
5144
+ events.push(withBackfillRefs(event, {
5145
+ filePath: summaryPath,
5146
+ sourcePathHash,
5147
+ lineNumber: lineNumber2,
5148
+ topType: topType || "session",
5149
+ payloadType: payloadType || event.type,
5150
+ options
5151
+ }));
5152
+ };
5153
+ const base = (partial) => ({
5154
+ schemaVersion: AGENT_TIME_SCHEMA_VERSION,
5155
+ source: SOURCE_ID,
5156
+ agent: AGENT_NAME,
5157
+ workspaceId,
5158
+ project,
5159
+ cwd,
5160
+ model,
5161
+ sessionId,
5162
+ ...partial
5163
+ });
5164
+ push(base({
5165
+ ts: createdAt,
5166
+ type: "session.started",
5167
+ confidence: "exact",
5168
+ refs: stringRefs({ sourceId: `${sessionId}:started` })
5169
+ }), 0, "summary", "session.started");
5170
+ let currentTurnId;
5171
+ let currentTurnStartedAt;
5172
+ let lineNumber = 0;
5173
+ const pendingTools = /* @__PURE__ */ new Map();
5174
+ let eventsText = "";
5175
+ try {
5176
+ eventsText = await readFile8(eventsPath, "utf8");
5177
+ } catch {
5178
+ }
5179
+ const lines = eventsText.split("\n").filter(Boolean);
5180
+ for (const [index, line] of lines.entries()) {
5181
+ lineNumber = index + 1;
5182
+ const raw = parseJsonLine(line);
5183
+ if (!raw) {
5184
+ continue;
5185
+ }
5186
+ const type = stringField(raw, "type");
5187
+ const ts = timestampFrom(raw.ts) || timestampFrom(raw.timestamp);
5188
+ if (!type || !ts) {
5189
+ continue;
5190
+ }
5191
+ if (type === "turn_started") {
5192
+ const turnNumber = numberField(raw, "turn_number");
5193
+ currentTurnId = turnNumber !== void 0 ? `turn_${turnNumber}` : `turn_${createStableHash([sessionId, lineNumber]).slice(0, 24)}`;
5194
+ currentTurnStartedAt = ts;
5195
+ const turnModel = stringField(raw, "model_id") || model;
5196
+ push(base({
5197
+ ts,
5198
+ type: "turn.started",
5199
+ turnId: currentTurnId,
5200
+ model: turnModel,
5201
+ confidence: "exact",
5202
+ refs: stringRefs({ sourceId: `${sessionId}:${currentTurnId}:started` })
5203
+ }), lineNumber, type, "turn.started");
5204
+ continue;
5205
+ }
5206
+ if (type === "turn_ended") {
5207
+ const turnId = currentTurnId;
5208
+ const outcome = stringField(raw, "outcome");
5209
+ const success = outcome !== "error" && outcome !== "failed" && outcome !== "cancelled";
5210
+ const durationMs = durationMsBetween(currentTurnStartedAt, ts);
5211
+ push(base({
5212
+ ts,
5213
+ type: success ? "turn.completed" : "turn.failed",
5214
+ turnId,
5215
+ success,
5216
+ confidence: "exact",
5217
+ metrics: durationMs !== void 0 ? { durationMs } : void 0,
5218
+ refs: stringRefs({
5219
+ sourceId: `${sessionId}:${turnId || "turn"}:ended`,
5220
+ outcome
5221
+ })
5222
+ }), lineNumber, type, "turn.ended");
5223
+ currentTurnId = void 0;
5224
+ currentTurnStartedAt = void 0;
5225
+ continue;
5226
+ }
5227
+ if (type === "tool_started" || type === "mcp_tool_call_started") {
5228
+ const toolName = type === "mcp_tool_call_started" ? mcpToolName(raw) : stringField(raw, "tool_name") || "unknown";
5229
+ const toolId = stringField(raw, "call_id") || `${sessionId}:tool:${lineNumber}:${toolName}`;
5230
+ pendingTools.set(toolId, {
5231
+ id: toolId,
5232
+ name: toolName,
5233
+ startedAt: ts,
5234
+ lineNumber,
5235
+ turnId: currentTurnId
5236
+ });
5237
+ const knownInput = toolInputs.get(toolId);
5238
+ const fileActivities = fileActivitiesFromTool(
5239
+ toolName,
5240
+ knownInput?.input || {},
5241
+ ts,
5242
+ cwd
5243
+ );
5244
+ push(base({
5245
+ ts,
5246
+ type: "tool.started",
5247
+ turnId: currentTurnId,
5248
+ tool: toolName,
5249
+ operation: `${toolName} started`,
5250
+ confidence: "exact",
5251
+ fileActivities: fileActivities.length > 0 ? fileActivities : void 0,
5252
+ refs: stringRefs({ sourceId: `${toolId}:started` })
5253
+ }), lineNumber, type, "tool.started");
5254
+ if (isShellTool(toolName)) {
5255
+ const command = stringField(knownInput?.input || {}, "command");
5256
+ if (command) {
5257
+ push(base({
5258
+ ts,
5259
+ type: "command.started",
5260
+ turnId: currentTurnId,
5261
+ tool: toolName,
5262
+ operation: "command started",
5263
+ confidence: "derived",
5264
+ refs: stringRefs({
5265
+ sourceId: `${toolId}:command:started`,
5266
+ commandHash: `sha256:${createStableHash(command)}`
5267
+ })
5268
+ }), lineNumber, type, "command.started");
5269
+ }
5270
+ }
5271
+ continue;
5272
+ }
5273
+ if (type === "tool_completed" || type === "mcp_tool_call_completed") {
5274
+ const toolName = type === "mcp_tool_call_completed" ? mcpToolName(raw) : stringField(raw, "tool_name") || "unknown";
5275
+ const toolId = stringField(raw, "call_id") || findPendingToolId(pendingTools, toolName) || `${sessionId}:tool:${lineNumber}:${toolName}`;
5276
+ const pending = pendingTools.get(toolId);
5277
+ const durationMs = numberField(raw, "duration_ms") ?? durationMsBetween(pending?.startedAt, ts);
5278
+ const outcome = stringField(raw, "outcome");
5279
+ const success = raw.success !== false && outcome !== "error" && outcome !== "failed" && !raw.is_timeout;
5280
+ push(base({
5281
+ ts,
5282
+ type: success ? "tool.completed" : "tool.failed",
5283
+ turnId: pending?.turnId || currentTurnId,
5284
+ tool: pending?.name || toolName,
5285
+ operation: `${pending?.name || toolName} completed`,
5286
+ success,
5287
+ confidence: "exact",
5288
+ metrics: {
5289
+ toolCalls: 1,
5290
+ toolDurationMs: durationMs,
5291
+ durationMs
5292
+ },
5293
+ refs: stringRefs({ sourceId: `${toolId}:completed` })
5294
+ }), lineNumber, type, "tool.completed");
5295
+ if (isShellTool(pending?.name || toolName)) {
5296
+ push(base({
5297
+ ts,
5298
+ type: success ? "command.completed" : "command.failed",
5299
+ turnId: pending?.turnId || currentTurnId,
5300
+ tool: pending?.name || toolName,
5301
+ operation: "command completed",
5302
+ success,
5303
+ confidence: "derived",
5304
+ metrics: {
5305
+ commandCalls: 1,
5306
+ commandDurationMs: durationMs,
5307
+ durationMs
5308
+ },
5309
+ refs: stringRefs({ sourceId: `${toolId}:command:completed` })
5310
+ }), lineNumber, type, "command.completed");
5311
+ }
5312
+ pendingTools.delete(toolId);
5313
+ continue;
5314
+ }
5315
+ if (type === "permission_resolved") {
5316
+ const toolName = stringField(raw, "tool_name");
5317
+ const decision = stringField(raw, "decision") || stringField(raw, "outcome");
5318
+ const allowed = decision !== "deny" && decision !== "denied" && decision !== "reject";
5319
+ push(base({
5320
+ ts,
5321
+ type: allowed ? "permission.granted" : "permission.denied",
5322
+ turnId: currentTurnId,
5323
+ tool: toolName,
5324
+ success: allowed,
5325
+ confidence: "partial",
5326
+ refs: stringRefs({
5327
+ sourceId: `${sessionId}:permission:${lineNumber}`,
5328
+ decision
5329
+ })
5330
+ }), lineNumber, type, "permission");
5331
+ }
5332
+ }
5333
+ const signals = await readJsonIfExists(signalsPath);
5334
+ if (isPlainObject(signals) && updatedAt) {
5335
+ const metrics = metricsFromSignals(signals);
5336
+ if (metrics) {
5337
+ push(base({
5338
+ ts: updatedAt,
5339
+ type: "model.usage",
5340
+ model: stringField(signals, "primaryModelId") || model,
5341
+ confidence: "partial",
5342
+ metrics,
5343
+ refs: stringRefs({ sourceId: `${sessionId}:usage:signals` })
5344
+ }), lineNumber + 1, "signals", "model.usage");
5345
+ }
5346
+ }
5347
+ if (updatedAt) {
5348
+ push(base({
5349
+ ts: updatedAt,
5350
+ type: "session.ended",
5351
+ confidence: "derived",
5352
+ refs: stringRefs({ sourceId: `${sessionId}:ended` })
5353
+ }), lineNumber + 2, "summary", "session.ended");
5354
+ }
5355
+ return events;
5356
+ }
5357
+ function resolveSessionDir(filePath) {
5358
+ const base = path13.basename(filePath);
5359
+ if (base === "summary.json" || base === "events.jsonl" || base === "signals.json") {
5360
+ return path13.dirname(filePath);
5361
+ }
5362
+ if (base.match(/^[0-9a-f]{8}-[0-9a-f-]{27,}$/i)) {
5363
+ return filePath;
5364
+ }
5365
+ return void 0;
5366
+ }
5367
+ function mcpToolName(raw) {
5368
+ const server = stringField(raw, "server_name");
5369
+ const tool = stringField(raw, "tool_name");
5370
+ if (server && tool) {
5371
+ return `${server}__${tool}`;
5372
+ }
5373
+ return tool || server || "mcp_tool";
5374
+ }
5375
+ function findPendingToolId(pending, toolName) {
5376
+ for (const [id, item] of pending) {
5377
+ if (item.name === toolName) {
5378
+ return id;
5379
+ }
5380
+ }
5381
+ return void 0;
5382
+ }
5383
+ function isShellTool(name) {
5384
+ if (!name) {
5385
+ return false;
5386
+ }
5387
+ const lower = name.toLowerCase();
5388
+ return lower === "run_terminal_command" || lower === "bash" || lower === "shell" || lower.endsWith("__run_terminal_command");
5389
+ }
5390
+ function fileActivitiesFromTool(toolName, input, ts, cwd) {
5391
+ const lower = toolName.toLowerCase();
5392
+ if (isShellTool(toolName)) {
5393
+ const command = stringField(input, "command");
5394
+ if (command) {
5395
+ return fileActivitiesFromShellCommand(command, ts, cwd, cwd);
5396
+ }
5397
+ return [];
5398
+ }
5399
+ if (lower === "read_file" || lower.endsWith("__read_file")) {
5400
+ const target = stringField(input, "target_file") || stringField(input, "path");
5401
+ if (!target) {
5402
+ return [];
5403
+ }
5404
+ return [{
5405
+ ts,
5406
+ path: displayPath(target, cwd),
5407
+ operation: "read",
5408
+ confidence: "exact"
5409
+ }];
5410
+ }
5411
+ if (lower === "search_replace" || lower === "write" || lower.endsWith("__search_replace") || lower.endsWith("__write")) {
5412
+ const target = stringField(input, "file_path") || stringField(input, "target_file") || stringField(input, "path");
5413
+ if (!target) {
5414
+ return [];
5415
+ }
5416
+ return [{
5417
+ ts,
5418
+ path: displayPath(target, cwd),
5419
+ operation: "edit",
5420
+ confidence: "exact"
5421
+ }];
5422
+ }
5423
+ return [];
5424
+ }
5425
+ function displayPath(filePath, cwd) {
5426
+ if (!cwd || !path13.isAbsolute(filePath)) {
5427
+ return filePath;
5428
+ }
5429
+ const relative = path13.relative(cwd, filePath);
5430
+ return relative && !relative.startsWith("..") && !path13.isAbsolute(relative) ? relative : filePath;
5431
+ }
5432
+ async function loadToolInputsFromUpdates(updatesPath) {
5433
+ const map = /* @__PURE__ */ new Map();
5434
+ let text = "";
5435
+ try {
5436
+ text = await readFile8(updatesPath, "utf8");
5437
+ } catch {
5438
+ return map;
5439
+ }
5440
+ for (const line of text.split("\n")) {
5441
+ if (!line.trim()) {
5442
+ continue;
5443
+ }
5444
+ const raw = parseJsonLine(line);
5445
+ if (!raw) {
5446
+ continue;
5447
+ }
5448
+ const params = objectField(raw, "params");
5449
+ const update = objectField(params, "update");
5450
+ const sessionUpdate = stringField(update, "sessionUpdate");
5451
+ if (sessionUpdate !== "tool_call" && sessionUpdate !== "tool_call_update") {
5452
+ continue;
5453
+ }
5454
+ const toolCallId = stringField(update, "toolCallId");
5455
+ if (!toolCallId) {
5456
+ continue;
5457
+ }
5458
+ const meta = objectField(update, "_meta");
5459
+ const toolMeta = objectField(meta, "x.ai/tool");
5460
+ const name = stringField(toolMeta, "name") || stringField(update, "title") || "unknown";
5461
+ const rawInput = objectField(update, "rawInput");
5462
+ const nestedInput = objectField(toolMeta, "input");
5463
+ const input = Object.keys(rawInput).length > 0 ? rawInput : nestedInput;
5464
+ if (!map.has(toolCallId) || Object.keys(input).length > 0) {
5465
+ map.set(toolCallId, { name, input });
5466
+ }
5467
+ }
5468
+ return map;
5469
+ }
5470
+ function metricsFromSignals(signals) {
5471
+ const contextTokens = numberField(signals, "contextTokensUsed");
5472
+ const toolCallCount = numberField(signals, "toolCallCount");
5473
+ const turnCount = numberField(signals, "turnCount");
5474
+ const durationSec = numberField(signals, "sessionDurationSeconds");
5475
+ const linesAdded = numberField(signals, "agentLinesAdded");
5476
+ const linesRemoved = numberField(signals, "agentLinesRemoved");
5477
+ if (contextTokens === void 0 && toolCallCount === void 0 && turnCount === void 0 && durationSec === void 0) {
5478
+ return void 0;
5479
+ }
5480
+ const metrics = {};
5481
+ if (contextTokens !== void 0 && contextTokens > 0) {
5482
+ metrics.tokensTotal = contextTokens;
5483
+ metrics.tokensInput = contextTokens;
5484
+ }
5485
+ if (toolCallCount !== void 0) {
5486
+ metrics.toolCalls = toolCallCount;
5487
+ }
5488
+ if (turnCount !== void 0) {
5489
+ metrics.modelCalls = turnCount;
5490
+ }
5491
+ if (durationSec !== void 0) {
5492
+ metrics.durationMs = Math.round(durationSec * 1e3);
5493
+ }
5494
+ if (linesAdded !== void 0) {
5495
+ metrics.linesAdded = linesAdded;
5496
+ }
5497
+ if (linesRemoved !== void 0) {
5498
+ metrics.linesRemoved = linesRemoved;
5499
+ }
5500
+ return metrics;
5501
+ }
5502
+ var grokHandler = (msg) => hookHandler(SOURCE_ID, msg);
5503
+ function hookConfig5() {
5504
+ const anyTool = [{ matcher: ".*", hooks: [grokHandler("Reporting tool activity")] }];
5505
+ return {
5506
+ hooks: {
5507
+ SessionStart: [{ hooks: [grokHandler("Reporting session start")] }],
5508
+ SessionEnd: [{ hooks: [grokHandler("Reporting session end")] }],
5509
+ UserPromptSubmit: [{ hooks: [grokHandler("Reporting prompt activity")] }],
5510
+ PreToolUse: anyTool,
5511
+ PostToolUse: anyTool,
5512
+ PostToolUseFailure: anyTool,
5513
+ PermissionDenied: anyTool,
5514
+ SubagentStart: [{ hooks: [grokHandler("Reporting subagent start")] }],
5515
+ SubagentStop: [{ hooks: [grokHandler("Reporting subagent completion")] }],
5516
+ Stop: [{ hooks: [grokHandler("Reporting turn completion")] }],
5517
+ StopFailure: [{ hooks: [grokHandler("Reporting turn failure")] }],
5518
+ PostCompact: [{ hooks: [grokHandler("Reporting context compaction")] }]
5519
+ }
5520
+ };
5521
+ }
5522
+ function createGrokBuildAdapter() {
5523
+ return {
5524
+ id: SOURCE_ID,
5525
+ label: "Grok Build",
5526
+ agentName: AGENT_NAME,
5527
+ kind: "agent",
5528
+ detectPath(home, env) {
5529
+ return grokHome(home, env);
5530
+ },
5531
+ installedPath(home, env) {
5532
+ return grokHooksPath(home, env);
5533
+ },
5534
+ async isInstalled(home, env) {
5535
+ return isHooksJsonInstalled(grokHooksPath(home, env), HOOK_COMMAND);
5536
+ },
5537
+ installEntries(home, env) {
5538
+ return [{
5539
+ kind: "hooks-json",
5540
+ path: grokHooksPath(home, env),
5541
+ content: hookConfig5()
5542
+ }];
5543
+ },
5544
+ sourcePaths(home, env) {
5545
+ return [grokSessionsDir(home, env)];
5546
+ },
5547
+ parseSessionFile: parseGrokSessionFile
5548
+ };
5549
+ }
5550
+
5061
5551
  // src/adapters/opencode.ts
5062
5552
  import os6 from "node:os";
5063
- import path13 from "node:path";
5553
+ import path14 from "node:path";
5064
5554
  async function parseOpenCodeSessionFile(dbPath, options) {
5065
5555
  const { DatabaseSync } = await import("node:sqlite");
5066
5556
  if (!dbPath.endsWith(".db")) {
@@ -5091,7 +5581,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
5091
5581
  for (const session of sessions) {
5092
5582
  const sessionId = session.id;
5093
5583
  const cwd = session.directory || session.path || void 0;
5094
- const project = cwd ? path13.basename(cwd) : void 0;
5584
+ const project = cwd ? path14.basename(cwd) : void 0;
5095
5585
  const sessionTs = msToIso(session.time_created);
5096
5586
  events.push(baseOpenCodeEvent({
5097
5587
  ts: sessionTs,
@@ -5199,7 +5689,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
5199
5689
  const provider = currentProvider;
5200
5690
  const pathObj = objectField(info, "path");
5201
5691
  const assistantCwd = stringField(pathObj, "cwd") || cwd;
5202
- const assistantProject = assistantCwd ? path13.basename(assistantCwd) : project;
5692
+ const assistantProject = assistantCwd ? path14.basename(assistantCwd) : project;
5203
5693
  const completedTs = numberField(objectField(info, "time"), "completed");
5204
5694
  const createdTs = timeCreated;
5205
5695
  const tokens = opencodeUsageFromInfo(info);
@@ -5447,33 +5937,33 @@ function opencodeUsageFromInfo(info) {
5447
5937
  function opencodeConfigDir(home, env) {
5448
5938
  const override = env?.OPENCODE_CONFIG_DIR;
5449
5939
  if (override && override.trim()) {
5450
- return path13.resolve(override);
5940
+ return path14.resolve(override);
5451
5941
  }
5452
5942
  const xdgConfig = env?.XDG_CONFIG_HOME;
5453
5943
  if (xdgConfig && xdgConfig.trim()) {
5454
- return path13.join(path13.resolve(xdgConfig), "opencode");
5944
+ return path14.join(path14.resolve(xdgConfig), "opencode");
5455
5945
  }
5456
- return path13.join(home, ".config", "opencode");
5946
+ return path14.join(home, ".config", "opencode");
5457
5947
  }
5458
5948
  function opencodeDataCandidates(home, env) {
5459
5949
  const xdgData = env?.XDG_DATA_HOME;
5460
- const primary = xdgData && xdgData.trim() ? path13.join(path13.resolve(xdgData), "opencode", "opencode.db") : path13.join(home, ".local", "share", "opencode", "opencode.db");
5461
- return [primary, path13.join(home, ".opencode", "opencode.db")];
5950
+ const primary = xdgData && xdgData.trim() ? path14.join(path14.resolve(xdgData), "opencode", "opencode.db") : path14.join(home, ".local", "share", "opencode", "opencode.db");
5951
+ return [primary, path14.join(home, ".opencode", "opencode.db")];
5462
5952
  }
5463
5953
  async function opencodeBackfillFiles(sourceRoot, home = os6.homedir(), env) {
5464
- const { stat: stat13 } = await import("node:fs/promises");
5954
+ const { stat: stat14 } = await import("node:fs/promises");
5465
5955
  if (sourceRoot) {
5466
5956
  if (!sourceRoot.endsWith(".db")) {
5467
5957
  return [];
5468
5958
  }
5469
- const info = await stat13(sourceRoot).catch(() => null);
5959
+ const info = await stat14(sourceRoot).catch(() => null);
5470
5960
  if (!info) {
5471
5961
  return [];
5472
5962
  }
5473
5963
  return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
5474
5964
  }
5475
5965
  for (const candidatePath of opencodeDataCandidates(home, env)) {
5476
- const info = await stat13(candidatePath).catch(() => null);
5966
+ const info = await stat14(candidatePath).catch(() => null);
5477
5967
  if (info) {
5478
5968
  return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
5479
5969
  }
@@ -5548,12 +6038,12 @@ function createOpenCodeAdapter() {
5548
6038
  return opencodeConfigDir(home, env);
5549
6039
  },
5550
6040
  installedPath(home, env) {
5551
- return path13.join(opencodeConfigDir(home, env), PLUGIN_PATH);
6041
+ return path14.join(opencodeConfigDir(home, env), PLUGIN_PATH);
5552
6042
  },
5553
6043
  async isInstalled(home, env) {
5554
6044
  try {
5555
6045
  const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
5556
- return await pathExists2(path13.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path13.join(".opencode", PLUGIN_PATH));
6046
+ return await pathExists2(path14.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path14.join(".opencode", PLUGIN_PATH));
5557
6047
  } catch {
5558
6048
  return false;
5559
6049
  }
@@ -5561,7 +6051,7 @@ function createOpenCodeAdapter() {
5561
6051
  installEntries(home, env) {
5562
6052
  return [{
5563
6053
  kind: "file",
5564
- path: path13.join(opencodeConfigDir(home, env), PLUGIN_PATH),
6054
+ path: path14.join(opencodeConfigDir(home, env), PLUGIN_PATH),
5565
6055
  content: opencodePluginContent()
5566
6056
  }];
5567
6057
  },
@@ -5573,10 +6063,10 @@ function createOpenCodeAdapter() {
5573
6063
  }
5574
6064
 
5575
6065
  // src/adapters/pi.ts
5576
- import { readFile as readFile8 } from "node:fs/promises";
5577
- import path14 from "node:path";
6066
+ import { readFile as readFile9 } from "node:fs/promises";
6067
+ import path15 from "node:path";
5578
6068
  async function parsePiSessionFile(filePath, options) {
5579
- const text = await readFile8(filePath, "utf8");
6069
+ const text = await readFile9(filePath, "utf8");
5580
6070
  const lines = text.split("\n").filter(Boolean);
5581
6071
  let sessionId;
5582
6072
  let cwd;
@@ -5607,7 +6097,7 @@ async function parsePiSessionFile(filePath, options) {
5607
6097
  sessionId = stringField(raw, "id") || state.sessionId;
5608
6098
  state.sessionId = sessionId || state.sessionId;
5609
6099
  cwd = stringField(raw, "cwd") || cwd;
5610
- project = cwd ? path14.basename(cwd) : project;
6100
+ project = cwd ? path15.basename(cwd) : project;
5611
6101
  continue;
5612
6102
  }
5613
6103
  if (entryType === "model_change") {
@@ -6016,16 +6506,16 @@ export default function (pi: ExtensionAPI) {
6016
6506
  function piAgentDir(home, env) {
6017
6507
  const override = env?.PI_CODING_AGENT_DIR;
6018
6508
  if (override && override.trim()) {
6019
- return path14.resolve(override);
6509
+ return path15.resolve(override);
6020
6510
  }
6021
- return path14.join(home, ".pi", "agent");
6511
+ return path15.join(home, ".pi", "agent");
6022
6512
  }
6023
6513
  function piSessionDir(home, env) {
6024
6514
  const override = env?.PI_CODING_AGENT_SESSION_DIR;
6025
6515
  if (override && override.trim()) {
6026
- return path14.resolve(override);
6516
+ return path15.resolve(override);
6027
6517
  }
6028
- return path14.join(piAgentDir(home, env), "sessions");
6518
+ return path15.join(piAgentDir(home, env), "sessions");
6029
6519
  }
6030
6520
  function createPiAdapter() {
6031
6521
  return {
@@ -6037,12 +6527,12 @@ function createPiAdapter() {
6037
6527
  return piAgentDir(home, env);
6038
6528
  },
6039
6529
  installedPath(home, env) {
6040
- return path14.join(piAgentDir(home, env), "extensions", "vibetime.ts");
6530
+ return path15.join(piAgentDir(home, env), "extensions", "vibetime.ts");
6041
6531
  },
6042
6532
  async isInstalled(home, env) {
6043
6533
  try {
6044
6534
  const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
6045
- return await pathExists2(path14.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
6535
+ return await pathExists2(path15.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
6046
6536
  } catch {
6047
6537
  return false;
6048
6538
  }
@@ -6050,7 +6540,7 @@ function createPiAdapter() {
6050
6540
  installEntries(home, env) {
6051
6541
  return [{
6052
6542
  kind: "file",
6053
- path: path14.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
6543
+ path: path15.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
6054
6544
  content: piExtensionContent()
6055
6545
  }];
6056
6546
  },
@@ -6062,11 +6552,11 @@ function createPiAdapter() {
6062
6552
  }
6063
6553
 
6064
6554
  // src/adapters/qoder-cn.ts
6065
- import { readdir as readdir6, readFile as readFile9, stat as stat7 } from "node:fs/promises";
6555
+ import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
6066
6556
  import os7 from "node:os";
6067
- import path15 from "node:path";
6557
+ import path16 from "node:path";
6068
6558
  function parseQoderCnPaths(filePath) {
6069
- const parts = filePath.split(path15.sep);
6559
+ const parts = filePath.split(path16.sep);
6070
6560
  const subagentsIdx = parts.lastIndexOf("subagents");
6071
6561
  let sessionId = "";
6072
6562
  let projectName = "";
@@ -6075,20 +6565,20 @@ function parseQoderCnPaths(filePath) {
6075
6565
  sessionId = parts[subagentsIdx - 1];
6076
6566
  projectName = parts[subagentsIdx - 2];
6077
6567
  const projectsIdx = parts.lastIndexOf("projects");
6078
- configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
6568
+ configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
6079
6569
  } else {
6080
6570
  const filename = parts.at(-1) || "";
6081
- sessionId = path15.basename(filename, ".jsonl");
6571
+ sessionId = path16.basename(filename, ".jsonl");
6082
6572
  projectName = parts.at(-2) || "";
6083
6573
  const projectsIdx = parts.lastIndexOf("projects");
6084
- configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
6574
+ configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
6085
6575
  }
6086
6576
  return { configDir: configDir2, projectName, sessionId };
6087
6577
  }
6088
6578
  async function loadQoderCnModelNames(configDir2) {
6089
6579
  try {
6090
- const dynamicTextsPath = path15.join(configDir2, ".auth", "dynamic-texts.json");
6091
- const content = await readFile9(dynamicTextsPath, "utf8");
6580
+ const dynamicTextsPath = path16.join(configDir2, ".auth", "dynamic-texts.json");
6581
+ const content = await readFile10(dynamicTextsPath, "utf8");
6092
6582
  const json = JSON.parse(content);
6093
6583
  const texts = json.texts || {};
6094
6584
  const map = {};
@@ -6105,15 +6595,15 @@ async function loadQoderCnModelNames(configDir2) {
6105
6595
  }
6106
6596
  async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
6107
6597
  const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
6108
- const segmentsPath = path15.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
6598
+ const segmentsPath = path16.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
6109
6599
  const modelCalls = [];
6110
6600
  try {
6111
- const files = await readdir6(segmentsPath);
6601
+ const files = await readdir7(segmentsPath);
6112
6602
  for (const file of files) {
6113
6603
  if (!file.endsWith(".jsonl")) {
6114
6604
  continue;
6115
6605
  }
6116
- const content = await readFile9(path15.join(segmentsPath, file), "utf8");
6606
+ const content = await readFile10(path16.join(segmentsPath, file), "utf8");
6117
6607
  let currentTurnIsSubagent = false;
6118
6608
  for (const line of content.split("\n").filter(Boolean)) {
6119
6609
  const raw = parseJsonLine(line);
@@ -6146,7 +6636,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
6146
6636
  return modelCalls.filter((call) => call.isSubagent === isSubagentSession);
6147
6637
  }
6148
6638
  async function parseQoderCnSessionFile(filePath, options) {
6149
- const text = await readFile9(filePath, "utf8");
6639
+ const text = await readFile10(filePath, "utf8");
6150
6640
  const lines = text.split("\n").filter(Boolean);
6151
6641
  const { configDir: configDir2 } = parseQoderCnPaths(filePath);
6152
6642
  const projectContext = await qoderCnProjectContextFromLines(filePath, lines, options, configDir2);
@@ -6181,7 +6671,7 @@ async function parseQoderCnSessionFile(filePath, options) {
6181
6671
  sessionId = stringField(raw, "sessionId") || sessionId;
6182
6672
  state.sessionId = sessionId;
6183
6673
  cwd = stringField(raw, "cwd") || cwd;
6184
- project = projectContext.project || (cwd ? path15.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
6674
+ project = projectContext.project || (cwd ? path16.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
6185
6675
  if (!ts) {
6186
6676
  continue;
6187
6677
  }
@@ -6610,28 +7100,28 @@ function isNoisePrompt(text) {
6610
7100
  }
6611
7101
  async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
6612
7102
  const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
6613
- const isSubagent = filePath.includes(`${path15.sep}subagents${path15.sep}`);
7103
+ const isSubagent = filePath.includes(`${path16.sep}subagents${path16.sep}`);
6614
7104
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
6615
7105
  let cwds = [];
6616
7106
  for (const line of lines) {
6617
7107
  const raw = parseJsonLine(line);
6618
7108
  const cwd = raw ? stringField(raw, "cwd") : void 0;
6619
- if (cwd && path15.isAbsolute(cwd)) {
7109
+ if (cwd && path16.isAbsolute(cwd)) {
6620
7110
  cwds.push(cwd);
6621
7111
  }
6622
7112
  }
6623
7113
  if (isSubagent) {
6624
- if (inherited?.cwd && path15.isAbsolute(inherited.cwd)) {
7114
+ if (inherited?.cwd && path16.isAbsolute(inherited.cwd)) {
6625
7115
  cwds = [inherited.cwd];
6626
7116
  } else {
6627
- const parentSessionPath = path15.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
7117
+ const parentSessionPath = path16.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
6628
7118
  try {
6629
- const parentText = await readFile9(parentSessionPath, "utf8");
7119
+ const parentText = await readFile10(parentSessionPath, "utf8");
6630
7120
  const parentCwds = [];
6631
7121
  for (const line of parentText.split("\n").filter(Boolean)) {
6632
7122
  const raw = parseJsonLine(line);
6633
7123
  const cwd = raw ? stringField(raw, "cwd") : void 0;
6634
- if (cwd && path15.isAbsolute(cwd)) {
7124
+ if (cwd && path16.isAbsolute(cwd)) {
6635
7125
  parentCwds.push(cwd);
6636
7126
  }
6637
7127
  }
@@ -6643,7 +7133,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
6643
7133
  }
6644
7134
  }
6645
7135
  const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
6646
- const project = inherited?.project || (cwds.length > 0 ? path15.basename(cwds[0]) : root ? path15.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
7136
+ const project = inherited?.project || (cwds.length > 0 ? path16.basename(cwds[0]) : root ? path16.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
6647
7137
  return {
6648
7138
  project,
6649
7139
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -6652,15 +7142,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
6652
7142
  async function gitRootFromCwds2(cwds) {
6653
7143
  const seen = /* @__PURE__ */ new Set();
6654
7144
  for (const cwd of cwds) {
6655
- let current = path15.resolve(cwd);
7145
+ let current = path16.resolve(cwd);
6656
7146
  while (!seen.has(current)) {
6657
7147
  seen.add(current);
6658
7148
  try {
6659
- await stat7(path15.join(current, ".git"));
7149
+ await stat8(path16.join(current, ".git"));
6660
7150
  return current;
6661
7151
  } catch {
6662
7152
  }
6663
- const parent = path15.dirname(current);
7153
+ const parent = path16.dirname(current);
6664
7154
  if (parent === current) {
6665
7155
  break;
6666
7156
  }
@@ -6671,12 +7161,12 @@ async function gitRootFromCwds2(cwds) {
6671
7161
  }
6672
7162
  function qoderCnProjectRootFromCwds(projectDir, cwds) {
6673
7163
  for (const cwd of cwds) {
6674
- let current = path15.resolve(cwd);
7164
+ let current = path16.resolve(cwd);
6675
7165
  while (true) {
6676
7166
  if (encodeQoderCnProjectPath(current) === projectDir) {
6677
7167
  return current;
6678
7168
  }
6679
- const parent = path15.dirname(current);
7169
+ const parent = path16.dirname(current);
6680
7170
  if (parent === current) {
6681
7171
  break;
6682
7172
  }
@@ -6686,14 +7176,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
6686
7176
  return void 0;
6687
7177
  }
6688
7178
  function encodeQoderCnProjectPath(value) {
6689
- return path15.resolve(value).split(path15.sep).join("-").replace(/_/g, "-");
7179
+ return path16.resolve(value).split(path16.sep).join("-").replace(/_/g, "-");
6690
7180
  }
6691
7181
  async function qoderCnProjectFromFilePath(filePath, options) {
6692
- const projectDir = path15.basename(path15.dirname(filePath));
6693
- const home = options ? path15.resolve(stringOption(options.home) || os7.homedir()) : os7.homedir();
7182
+ const projectDir = path16.basename(path16.dirname(filePath));
7183
+ const home = options ? path16.resolve(stringOption(options.home) || os7.homedir()) : os7.homedir();
6694
7184
  const resolved = await resolveQoderCnProjectPath(projectDir, home);
6695
7185
  if (resolved) {
6696
- return path15.basename(resolved);
7186
+ return path16.basename(resolved);
6697
7187
  }
6698
7188
  const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
6699
7189
  if (projectDir.startsWith(homePrefix)) {
@@ -6713,12 +7203,12 @@ async function resolveQoderCnProjectPath(projectDir, home) {
6713
7203
  while (projectDir.startsWith(`${currentEncoded}-`)) {
6714
7204
  let matchedChild;
6715
7205
  try {
6716
- const entries = await readdir6(current, { withFileTypes: true });
7206
+ const entries = await readdir7(current, { withFileTypes: true });
6717
7207
  for (const entry of entries) {
6718
7208
  if (!entry.isDirectory()) {
6719
7209
  continue;
6720
7210
  }
6721
- const candidate = path15.join(current, entry.name);
7211
+ const candidate = path16.join(current, entry.name);
6722
7212
  const encoded = encodeQoderCnProjectPath(candidate);
6723
7213
  if (encoded === projectDir) {
6724
7214
  return candidate;
@@ -6740,7 +7230,7 @@ async function resolveQoderCnProjectPath(projectDir, home) {
6740
7230
  return void 0;
6741
7231
  }
6742
7232
  var qoderCnHandler = (msg) => hookHandler("qoder-cn", msg);
6743
- function hookConfig5() {
7233
+ function hookConfig6() {
6744
7234
  const anyTool = [{ matcher: ".*", hooks: [qoderCnHandler("Reporting tool activity")] }];
6745
7235
  return {
6746
7236
  hooks: {
@@ -6763,9 +7253,9 @@ function hookConfig5() {
6763
7253
  function qoderCnConfigDir(home, env) {
6764
7254
  const override = env?.QODER_CN_CONFIG_DIR;
6765
7255
  if (override && override.trim()) {
6766
- return path15.resolve(override);
7256
+ return path16.resolve(override);
6767
7257
  }
6768
- return path15.join(home, ".qoder-cn");
7258
+ return path16.join(home, ".qoder-cn");
6769
7259
  }
6770
7260
  function createQoderCnAdapter() {
6771
7261
  return {
@@ -6777,27 +7267,27 @@ function createQoderCnAdapter() {
6777
7267
  return qoderCnConfigDir(home, env);
6778
7268
  },
6779
7269
  installedPath(home, env) {
6780
- return path15.join(qoderCnConfigDir(home, env), "settings.json");
7270
+ return path16.join(qoderCnConfigDir(home, env), "settings.json");
6781
7271
  },
6782
7272
  async isInstalled(home, env) {
6783
7273
  return isHooksJsonInstalled(
6784
- path15.join(qoderCnConfigDir(home, env), "settings.json"),
7274
+ path16.join(qoderCnConfigDir(home, env), "settings.json"),
6785
7275
  "vibetime hook --agent qoder-cn"
6786
7276
  );
6787
7277
  },
6788
7278
  installEntries(home, env) {
6789
7279
  return [{
6790
7280
  kind: "hooks-json",
6791
- path: path15.join(qoderCnConfigDir(home, env), "settings.json"),
6792
- content: hookConfig5()
7281
+ path: path16.join(qoderCnConfigDir(home, env), "settings.json"),
7282
+ content: hookConfig6()
6793
7283
  }];
6794
7284
  },
6795
7285
  sourcePaths(home, env) {
6796
7286
  const base = qoderCnConfigDir(home, env);
6797
7287
  return [
6798
- path15.join(base, "projects"),
6799
- path15.join(base, ".qoder.json"),
6800
- path15.join(home, ".qoder.json")
7288
+ path16.join(base, "projects"),
7289
+ path16.join(base, ".qoder.json"),
7290
+ path16.join(home, ".qoder.json")
6801
7291
  ];
6802
7292
  },
6803
7293
  parseSessionFile: parseQoderCnSessionFile
@@ -6805,11 +7295,11 @@ function createQoderCnAdapter() {
6805
7295
  }
6806
7296
 
6807
7297
  // src/adapters/qoder.ts
6808
- import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
7298
+ import { readdir as readdir8, readFile as readFile11, stat as stat9 } from "node:fs/promises";
6809
7299
  import os8 from "node:os";
6810
- import path16 from "node:path";
7300
+ import path17 from "node:path";
6811
7301
  function parseQoderPaths(filePath) {
6812
- const parts = filePath.split(path16.sep);
7302
+ const parts = filePath.split(path17.sep);
6813
7303
  const subagentsIdx = parts.lastIndexOf("subagents");
6814
7304
  let sessionId = "";
6815
7305
  let projectName = "";
@@ -6818,20 +7308,20 @@ function parseQoderPaths(filePath) {
6818
7308
  sessionId = parts[subagentsIdx - 1];
6819
7309
  projectName = parts[subagentsIdx - 2];
6820
7310
  const projectsIdx = parts.lastIndexOf("projects");
6821
- configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
7311
+ configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
6822
7312
  } else {
6823
7313
  const filename = parts.at(-1) || "";
6824
- sessionId = path16.basename(filename, ".jsonl");
7314
+ sessionId = path17.basename(filename, ".jsonl");
6825
7315
  projectName = parts.at(-2) || "";
6826
7316
  const projectsIdx = parts.lastIndexOf("projects");
6827
- configDir2 = parts.slice(0, projectsIdx).join(path16.sep);
7317
+ configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
6828
7318
  }
6829
7319
  return { configDir: configDir2, projectName, sessionId };
6830
7320
  }
6831
7321
  async function loadQoderModelNames(configDir2) {
6832
7322
  try {
6833
- const dynamicTextsPath = path16.join(configDir2, ".auth", "dynamic-texts.json");
6834
- const content = await readFile10(dynamicTextsPath, "utf8");
7323
+ const dynamicTextsPath = path17.join(configDir2, ".auth", "dynamic-texts.json");
7324
+ const content = await readFile11(dynamicTextsPath, "utf8");
6835
7325
  const json = JSON.parse(content);
6836
7326
  const texts = json.texts || {};
6837
7327
  const map = {};
@@ -6848,15 +7338,15 @@ async function loadQoderModelNames(configDir2) {
6848
7338
  }
6849
7339
  async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
6850
7340
  const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
6851
- const segmentsPath = path16.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
7341
+ const segmentsPath = path17.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
6852
7342
  const modelCalls = [];
6853
7343
  try {
6854
- const files = await readdir7(segmentsPath);
7344
+ const files = await readdir8(segmentsPath);
6855
7345
  for (const file of files) {
6856
7346
  if (!file.endsWith(".jsonl")) {
6857
7347
  continue;
6858
7348
  }
6859
- const content = await readFile10(path16.join(segmentsPath, file), "utf8");
7349
+ const content = await readFile11(path17.join(segmentsPath, file), "utf8");
6860
7350
  let currentTurnIsSubagent = false;
6861
7351
  for (const line of content.split("\n").filter(Boolean)) {
6862
7352
  const raw = parseJsonLine(line);
@@ -6889,7 +7379,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
6889
7379
  return modelCalls.filter((call) => call.isSubagent === isSubagentSession);
6890
7380
  }
6891
7381
  async function parseQoderSessionFile(filePath, options) {
6892
- const text = await readFile10(filePath, "utf8");
7382
+ const text = await readFile11(filePath, "utf8");
6893
7383
  const lines = text.split("\n").filter(Boolean);
6894
7384
  const { configDir: configDir2 } = parseQoderPaths(filePath);
6895
7385
  const projectContext = await qoderProjectContextFromLines(filePath, lines, options, configDir2);
@@ -6924,7 +7414,7 @@ async function parseQoderSessionFile(filePath, options) {
6924
7414
  sessionId = stringField(raw, "sessionId") || sessionId;
6925
7415
  state.sessionId = sessionId;
6926
7416
  cwd = stringField(raw, "cwd") || cwd;
6927
- project = projectContext.project || (cwd ? path16.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
7417
+ project = projectContext.project || (cwd ? path17.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
6928
7418
  if (!ts) {
6929
7419
  continue;
6930
7420
  }
@@ -7319,28 +7809,28 @@ function qoderExtractText(value) {
7319
7809
  }
7320
7810
  async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
7321
7811
  const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
7322
- const isSubagent = filePath.includes(`${path16.sep}subagents${path16.sep}`);
7812
+ const isSubagent = filePath.includes(`${path17.sep}subagents${path17.sep}`);
7323
7813
  const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
7324
7814
  let cwds = [];
7325
7815
  for (const line of lines) {
7326
7816
  const raw = parseJsonLine(line);
7327
7817
  const cwd = raw ? stringField(raw, "cwd") : void 0;
7328
- if (cwd && path16.isAbsolute(cwd)) {
7818
+ if (cwd && path17.isAbsolute(cwd)) {
7329
7819
  cwds.push(cwd);
7330
7820
  }
7331
7821
  }
7332
7822
  if (isSubagent) {
7333
- if (inherited?.cwd && path16.isAbsolute(inherited.cwd)) {
7823
+ if (inherited?.cwd && path17.isAbsolute(inherited.cwd)) {
7334
7824
  cwds = [inherited.cwd];
7335
7825
  } else {
7336
- const parentSessionPath = path16.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
7826
+ const parentSessionPath = path17.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
7337
7827
  try {
7338
- const parentText = await readFile10(parentSessionPath, "utf8");
7828
+ const parentText = await readFile11(parentSessionPath, "utf8");
7339
7829
  const parentCwds = [];
7340
7830
  for (const line of parentText.split("\n").filter(Boolean)) {
7341
7831
  const raw = parseJsonLine(line);
7342
7832
  const cwd = raw ? stringField(raw, "cwd") : void 0;
7343
- if (cwd && path16.isAbsolute(cwd)) {
7833
+ if (cwd && path17.isAbsolute(cwd)) {
7344
7834
  parentCwds.push(cwd);
7345
7835
  }
7346
7836
  }
@@ -7352,7 +7842,7 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
7352
7842
  }
7353
7843
  }
7354
7844
  const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
7355
- const project = inherited?.project || (cwds.length > 0 ? path16.basename(cwds[0]) : root ? path16.basename(root) : await qoderProjectFromFilePath(filePath, options));
7845
+ const project = inherited?.project || (cwds.length > 0 ? path17.basename(cwds[0]) : root ? path17.basename(root) : await qoderProjectFromFilePath(filePath, options));
7356
7846
  return {
7357
7847
  project,
7358
7848
  workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
@@ -7361,15 +7851,15 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
7361
7851
  async function gitRootFromCwds3(cwds) {
7362
7852
  const seen = /* @__PURE__ */ new Set();
7363
7853
  for (const cwd of cwds) {
7364
- let current = path16.resolve(cwd);
7854
+ let current = path17.resolve(cwd);
7365
7855
  while (!seen.has(current)) {
7366
7856
  seen.add(current);
7367
7857
  try {
7368
- await stat8(path16.join(current, ".git"));
7858
+ await stat9(path17.join(current, ".git"));
7369
7859
  return current;
7370
7860
  } catch {
7371
7861
  }
7372
- const parent = path16.dirname(current);
7862
+ const parent = path17.dirname(current);
7373
7863
  if (parent === current) {
7374
7864
  break;
7375
7865
  }
@@ -7380,12 +7870,12 @@ async function gitRootFromCwds3(cwds) {
7380
7870
  }
7381
7871
  function qoderProjectRootFromCwds(projectDir, cwds) {
7382
7872
  for (const cwd of cwds) {
7383
- let current = path16.resolve(cwd);
7873
+ let current = path17.resolve(cwd);
7384
7874
  while (true) {
7385
7875
  if (encodeQoderProjectPath(current) === projectDir) {
7386
7876
  return current;
7387
7877
  }
7388
- const parent = path16.dirname(current);
7878
+ const parent = path17.dirname(current);
7389
7879
  if (parent === current) {
7390
7880
  break;
7391
7881
  }
@@ -7395,10 +7885,10 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
7395
7885
  return void 0;
7396
7886
  }
7397
7887
  function encodeQoderProjectPath(value) {
7398
- return path16.resolve(value).split(path16.sep).join("-").replace(/_/g, "-");
7888
+ return path17.resolve(value).split(path17.sep).join("-").replace(/_/g, "-");
7399
7889
  }
7400
7890
  function rawQoderProjectPath(value) {
7401
- return path16.resolve(value).split(path16.sep).join("-");
7891
+ return path17.resolve(value).split(path17.sep).join("-");
7402
7892
  }
7403
7893
  function qoderEncodedVariants(value) {
7404
7894
  const raw = rawQoderProjectPath(value);
@@ -7414,11 +7904,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
7414
7904
  return void 0;
7415
7905
  }
7416
7906
  async function qoderProjectFromFilePath(filePath, options) {
7417
- const projectDir = path16.basename(path16.dirname(filePath));
7418
- const home = options ? path16.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
7907
+ const projectDir = path17.basename(path17.dirname(filePath));
7908
+ const home = options ? path17.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
7419
7909
  const resolved = await resolveQoderProjectPath(projectDir, home);
7420
7910
  if (resolved) {
7421
- return path16.basename(resolved);
7911
+ return path17.basename(resolved);
7422
7912
  }
7423
7913
  const suffix = qoderEncodedProjectSuffix(projectDir, home);
7424
7914
  if (suffix) {
@@ -7439,12 +7929,12 @@ async function resolveQoderProjectPath(projectDir, home) {
7439
7929
  while (currentEncodedVariants.some((prefix) => projectDir.startsWith(`${prefix}-`))) {
7440
7930
  let matchedChild;
7441
7931
  try {
7442
- const entries = await readdir7(current, { withFileTypes: true });
7932
+ const entries = await readdir8(current, { withFileTypes: true });
7443
7933
  for (const entry of entries) {
7444
7934
  if (!entry.isDirectory()) {
7445
7935
  continue;
7446
7936
  }
7447
- const candidate = path16.join(current, entry.name);
7937
+ const candidate = path17.join(current, entry.name);
7448
7938
  const candidateVariants = qoderEncodedVariants(candidate);
7449
7939
  if (candidateVariants.includes(projectDir)) {
7450
7940
  return candidate;
@@ -7466,7 +7956,7 @@ async function resolveQoderProjectPath(projectDir, home) {
7466
7956
  return void 0;
7467
7957
  }
7468
7958
  var qoderHandler = (msg) => hookHandler("qoder", msg);
7469
- function hookConfig6() {
7959
+ function hookConfig7() {
7470
7960
  const anyTool = [{ matcher: ".*", hooks: [qoderHandler("Reporting tool activity")] }];
7471
7961
  return {
7472
7962
  hooks: {
@@ -7489,9 +7979,9 @@ function hookConfig6() {
7489
7979
  function qoderConfigDir(home, env) {
7490
7980
  const override = env?.QODER_CONFIG_DIR;
7491
7981
  if (override && override.trim()) {
7492
- return path16.resolve(override);
7982
+ return path17.resolve(override);
7493
7983
  }
7494
- return path16.join(home, ".qoder");
7984
+ return path17.join(home, ".qoder");
7495
7985
  }
7496
7986
  function createQoderAdapter() {
7497
7987
  return {
@@ -7503,27 +7993,27 @@ function createQoderAdapter() {
7503
7993
  return qoderConfigDir(home, env);
7504
7994
  },
7505
7995
  installedPath(home, env) {
7506
- return path16.join(qoderConfigDir(home, env), "settings.json");
7996
+ return path17.join(qoderConfigDir(home, env), "settings.json");
7507
7997
  },
7508
7998
  async isInstalled(home, env) {
7509
7999
  return isHooksJsonInstalled(
7510
- path16.join(qoderConfigDir(home, env), "settings.json"),
8000
+ path17.join(qoderConfigDir(home, env), "settings.json"),
7511
8001
  "vibetime hook --agent qoder"
7512
8002
  );
7513
8003
  },
7514
8004
  installEntries(home, env) {
7515
8005
  return [{
7516
8006
  kind: "hooks-json",
7517
- path: path16.join(qoderConfigDir(home, env), "settings.json"),
7518
- content: hookConfig6()
8007
+ path: path17.join(qoderConfigDir(home, env), "settings.json"),
8008
+ content: hookConfig7()
7519
8009
  }];
7520
8010
  },
7521
8011
  sourcePaths(home, env) {
7522
8012
  const base = qoderConfigDir(home, env);
7523
8013
  return [
7524
- path16.join(base, "projects"),
7525
- path16.join(base, ".qoder.json"),
7526
- path16.join(home, ".qoder.json")
8014
+ path17.join(base, "projects"),
8015
+ path17.join(base, ".qoder.json"),
8016
+ path17.join(home, ".qoder.json")
7527
8017
  ];
7528
8018
  },
7529
8019
  parseSessionFile: parseQoderSessionFile
@@ -7558,21 +8048,21 @@ function normalizeId(id) {
7558
8048
  }
7559
8049
 
7560
8050
  // src/adapters/workbuddy.ts
7561
- import { readFile as readFile11, readdir as readdir8, stat as stat9 } from "node:fs/promises";
7562
- import path17 from "node:path";
8051
+ import { readFile as readFile12, readdir as readdir9, stat as stat10 } from "node:fs/promises";
8052
+ import path18 from "node:path";
7563
8053
  init_fs();
7564
8054
  function workbuddyProjectsDir(home, env) {
7565
8055
  const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
7566
8056
  if (override && override.trim()) {
7567
- return path17.resolve(override, override.endsWith("projects") ? "" : "projects");
8057
+ return path18.resolve(override, override.endsWith("projects") ? "" : "projects");
7568
8058
  }
7569
- return path17.join(home, ".workbuddy", "projects");
8059
+ return path18.join(home, ".workbuddy", "projects");
7570
8060
  }
7571
8061
  function projectFromCwd(cwd, fallback) {
7572
8062
  if (!cwd) {
7573
8063
  return fallback;
7574
8064
  }
7575
- return path17.basename(cwd) || fallback;
8065
+ return path18.basename(cwd) || fallback;
7576
8066
  }
7577
8067
  function sourceHash(filePath) {
7578
8068
  return `sha256:${createStableHash(filePath)}`;
@@ -7654,7 +8144,7 @@ function contentLength(value) {
7654
8144
  return 0;
7655
8145
  }
7656
8146
  async function readWorkbuddyLines(filePath) {
7657
- const text = await readFile11(filePath, "utf8");
8147
+ const text = await readFile12(filePath, "utf8");
7658
8148
  return text.split(/\r?\n/).map((line, index) => {
7659
8149
  if (!line.trim()) {
7660
8150
  return void 0;
@@ -7674,8 +8164,8 @@ async function parseWorkbuddySessionFile(filePath, options) {
7674
8164
  }
7675
8165
  const events = [];
7676
8166
  const first = lines[0].record;
7677
- const sessionId = stringField(first, "sessionId") || path17.basename(filePath, ".jsonl");
7678
- const fallbackProject = path17.basename(path17.dirname(filePath));
8167
+ const sessionId = stringField(first, "sessionId") || path18.basename(filePath, ".jsonl");
8168
+ const fallbackProject = path18.basename(path18.dirname(filePath));
7679
8169
  const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
7680
8170
  const project = projectFromCwd(cwd, fallbackProject);
7681
8171
  const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
@@ -7844,17 +8334,17 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
7844
8334
  const base = sourceRoot || workbuddyProjectsDir(home, env);
7845
8335
  const files = [];
7846
8336
  try {
7847
- const projects = await readdir8(base, { withFileTypes: true });
8337
+ const projects = await readdir9(base, { withFileTypes: true });
7848
8338
  for (const project of projects) {
7849
8339
  if (!project.isDirectory()) {
7850
8340
  continue;
7851
8341
  }
7852
- const projectDir = path17.join(base, project.name);
7853
- const entries = await readdir8(projectDir, { withFileTypes: true });
8342
+ const projectDir = path18.join(base, project.name);
8343
+ const entries = await readdir9(projectDir, { withFileTypes: true });
7854
8344
  for (const entry of entries) {
7855
8345
  if (entry.isFile() && entry.name.endsWith(".jsonl")) {
7856
- const filePath = path17.join(projectDir, entry.name);
7857
- const info = await stat9(filePath);
8346
+ const filePath = path18.join(projectDir, entry.name);
8347
+ const info = await stat10(filePath);
7858
8348
  files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
7859
8349
  }
7860
8350
  }
@@ -7891,26 +8381,26 @@ function createWorkbuddyAdapter() {
7891
8381
 
7892
8382
  // src/adapters/zcode.ts
7893
8383
  import { execFile } from "node:child_process";
7894
- import { readFile as readFile12, stat as stat10 } from "node:fs/promises";
7895
- import path18 from "node:path";
8384
+ import { readFile as readFile13, stat as stat11 } from "node:fs/promises";
8385
+ import path19 from "node:path";
7896
8386
  import { promisify as promisify2 } from "node:util";
7897
8387
  init_fs();
7898
8388
  var execFileAsync = promisify2(execFile);
7899
8389
  function zcodeCliDir(home, env) {
7900
8390
  const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
7901
8391
  if (override && override.trim()) {
7902
- return path18.resolve(override, override.endsWith("cli") ? "" : "cli");
8392
+ return path19.resolve(override, override.endsWith("cli") ? "" : "cli");
7903
8393
  }
7904
- return path18.join(home, ".zcode", "cli");
8394
+ return path19.join(home, ".zcode", "cli");
7905
8395
  }
7906
8396
  function zcodeDbPath(home, env) {
7907
- return path18.join(zcodeCliDir(home, env), "db", "db.sqlite");
8397
+ return path19.join(zcodeCliDir(home, env), "db", "db.sqlite");
7908
8398
  }
7909
8399
  var providerNameCache = null;
7910
8400
  async function loadProviderNames(configPath2) {
7911
8401
  let fileMtime = 0;
7912
8402
  try {
7913
- const info = await stat10(configPath2);
8403
+ const info = await stat11(configPath2);
7914
8404
  fileMtime = info.mtimeMs;
7915
8405
  } catch {
7916
8406
  return /* @__PURE__ */ new Map();
@@ -7920,7 +8410,7 @@ async function loadProviderNames(configPath2) {
7920
8410
  }
7921
8411
  const map = /* @__PURE__ */ new Map();
7922
8412
  try {
7923
- const raw = await readFile12(configPath2, "utf-8");
8413
+ const raw = await readFile13(configPath2, "utf-8");
7924
8414
  const config = JSON.parse(raw);
7925
8415
  const providers = config?.provider;
7926
8416
  if (isPlainObject(providers)) {
@@ -7938,7 +8428,7 @@ function sourceHash2(filePath) {
7938
8428
  return `sha256:${createStableHash(filePath)}`;
7939
8429
  }
7940
8430
  function projectFromDirectory(directory) {
7941
- return directory ? path18.basename(directory) || "zcode" : "zcode";
8431
+ return directory ? path19.basename(directory) || "zcode" : "zcode";
7942
8432
  }
7943
8433
  function isoFromMs(value) {
7944
8434
  return timestampFrom(typeof value === "number" ? value : Number(value));
@@ -8094,16 +8584,16 @@ async function parseZCodeDb(filePath, options) {
8094
8584
  if (rows.length === 0) {
8095
8585
  return [];
8096
8586
  }
8097
- let candidate = path18.resolve(filePath);
8587
+ let candidate = path19.resolve(filePath);
8098
8588
  let configPath2 = "";
8099
8589
  for (let i = 0; i < 12; i++) {
8100
- const probe = path18.join(candidate, ".zcode", "v2", "config.json");
8590
+ const probe = path19.join(candidate, ".zcode", "v2", "config.json");
8101
8591
  try {
8102
- await stat10(probe);
8592
+ await stat11(probe);
8103
8593
  configPath2 = probe;
8104
8594
  break;
8105
8595
  } catch {
8106
- const parent = path18.dirname(candidate);
8596
+ const parent = path19.dirname(candidate);
8107
8597
  if (parent === candidate) break;
8108
8598
  candidate = parent;
8109
8599
  }
@@ -8319,9 +8809,9 @@ async function parseZCodeDb(filePath, options) {
8319
8809
  }
8320
8810
  async function zcodeBackfillFiles(sourceRoot, home, env) {
8321
8811
  const candidate = sourceRoot || zcodeDbPath(home, env);
8322
- const filePath = candidate.endsWith(".sqlite") ? candidate : path18.join(candidate, "db", "db.sqlite");
8812
+ const filePath = candidate.endsWith(".sqlite") ? candidate : path19.join(candidate, "db", "db.sqlite");
8323
8813
  try {
8324
- const info = await stat10(filePath);
8814
+ const info = await stat11(filePath);
8325
8815
  return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
8326
8816
  } catch {
8327
8817
  return [];
@@ -8583,11 +9073,11 @@ function buildSessionRollup(rollupKey, events) {
8583
9073
  bucket.activityCount += 1;
8584
9074
  }
8585
9075
  for (const file of event.fileActivities || []) {
8586
- const displayPath = displayBackfillPath(file.path);
8587
- const pathHash = `sha256:${createStableHash(displayPath)}`;
9076
+ const displayPath2 = displayBackfillPath(file.path);
9077
+ const pathHash = `sha256:${createStableHash(displayPath2)}`;
8588
9078
  const fileRollup = fileRollups.get(pathHash) || {
8589
9079
  pathHash,
8590
- displayPath,
9080
+ displayPath: displayPath2,
8591
9081
  reads: 0,
8592
9082
  writes: 0,
8593
9083
  linesAdded: 0,
@@ -8796,15 +9286,15 @@ function hookCommandFromGroup(group) {
8796
9286
  import { randomUUID } from "node:crypto";
8797
9287
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
8798
9288
  import { homedir, hostname } from "node:os";
8799
- import path19 from "node:path";
9289
+ import path20 from "node:path";
8800
9290
  function configDir(home = homedir()) {
8801
- return path19.join(home, ".vibetime");
9291
+ return path20.join(home, ".vibetime");
8802
9292
  }
8803
9293
  function configPath(home = homedir()) {
8804
- return path19.join(configDir(home), "config.json");
9294
+ return path20.join(configDir(home), "config.json");
8805
9295
  }
8806
9296
  function machineIdPath(home = homedir()) {
8807
- return path19.join(configDir(home), "machine-id");
9297
+ return path20.join(configDir(home), "machine-id");
8808
9298
  }
8809
9299
  function readConfig(home = homedir()) {
8810
9300
  const file = configPath(home);
@@ -8851,15 +9341,15 @@ function defaultMachineName() {
8851
9341
  init_fs();
8852
9342
 
8853
9343
  // src/lib/logger.ts
8854
- import { appendFile, mkdir as mkdir4, rename, stat as stat11 } from "node:fs/promises";
9344
+ import { appendFile, mkdir as mkdir4, rename, stat as stat12 } from "node:fs/promises";
8855
9345
  import { homedir as homedir2 } from "node:os";
8856
- import path20 from "node:path";
9346
+ import path21 from "node:path";
8857
9347
  var MAX_BYTES = 1 * 1024 * 1024;
8858
9348
  function logDir(home = homedir2()) {
8859
- return path20.join(home, ".vibetime", "logs");
9349
+ return path21.join(home, ".vibetime", "logs");
8860
9350
  }
8861
9351
  function logPath(home = homedir2(), name = "cli.log") {
8862
- return path20.join(logDir(home), name);
9352
+ return path21.join(logDir(home), name);
8863
9353
  }
8864
9354
  function serializeError(error) {
8865
9355
  if (error instanceof Error) {
@@ -8869,7 +9359,7 @@ function serializeError(error) {
8869
9359
  }
8870
9360
  async function rotateIfNeeded(file) {
8871
9361
  try {
8872
- const info = await stat11(file);
9362
+ const info = await stat12(file);
8873
9363
  if (info.size > MAX_BYTES) {
8874
9364
  await rename(file, `${file}.1`).catch(() => {
8875
9365
  });
@@ -9034,8 +9524,8 @@ function buildHeaders(token, machine) {
9034
9524
  ...machine?.platform ? { "x-machine-platform": machine.platform } : {}
9035
9525
  };
9036
9526
  }
9037
- function joinUrl(base, path22) {
9038
- return new URL(path22, base.endsWith("/") ? base : `${base}/`).toString();
9527
+ function joinUrl(base, path23) {
9528
+ return new URL(path23, base.endsWith("/") ? base : `${base}/`).toString();
9039
9529
  }
9040
9530
  async function postRollupBatch(remote, rollups, options = {}) {
9041
9531
  const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
@@ -9117,6 +9607,7 @@ function createRegistry() {
9117
9607
  registry.register(createQoderCnAdapter());
9118
9608
  registry.register(createWorkbuddyAdapter());
9119
9609
  registry.register(createZCodeAdapter());
9610
+ registry.register(createGrokBuildAdapter());
9120
9611
  return registry;
9121
9612
  }
9122
9613
  var defaultContext = {
@@ -9629,11 +10120,14 @@ async function listBackfillSourceFiles(source, options, ctx) {
9629
10120
  if (source.id === "copilot") {
9630
10121
  return copilotBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
9631
10122
  }
10123
+ if (source.id === "grok-build") {
10124
+ return grokBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
10125
+ }
9632
10126
  const roots = stringOption(options["source-root"]) ? [requiredOption(options, "source-root")] : source.paths;
9633
10127
  const fileLists = await Promise.all(roots.map((r) => listJsonlFiles(r)));
9634
10128
  const files = fileLists.flat().sort().slice(0, numberOption(options.limit) || void 0);
9635
10129
  return Promise.all(files.map(async (filePath) => {
9636
- const info = await stat12(filePath);
10130
+ const info = await stat13(filePath);
9637
10131
  return { path: filePath, modifiedAt: info.mtime.toISOString() };
9638
10132
  }));
9639
10133
  }
@@ -9946,13 +10440,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
9946
10440
  });
9947
10441
  }
9948
10442
  function backfillIncrementalStatePath(home) {
9949
- return path21.join(home, ".vibetime", "backfill-state.json");
10443
+ return path22.join(home, ".vibetime", "backfill-state.json");
9950
10444
  }
9951
10445
  function syncLocalTriggerStatePath(home) {
9952
- return path21.join(home, ".vibetime", "sync-local-trigger.json");
10446
+ return path22.join(home, ".vibetime", "sync-local-trigger.json");
9953
10447
  }
9954
10448
  function syncLocalTriggerLockPath(home) {
9955
- return path21.join(home, ".vibetime", "sync-local-trigger.lock");
10449
+ return path22.join(home, ".vibetime", "sync-local-trigger.lock");
9956
10450
  }
9957
10451
  function backfillRemoteKey(baseUrl) {
9958
10452
  try {
@@ -10014,7 +10508,7 @@ async function readBackfillIncrementalStateFile(home, ctx) {
10014
10508
  }
10015
10509
  async function writeBackfillIncrementalStateFile(home, file) {
10016
10510
  const statePath = backfillIncrementalStatePath(home);
10017
- await mkdir5(path21.dirname(statePath), { recursive: true });
10511
+ await mkdir5(path22.dirname(statePath), { recursive: true });
10018
10512
  await writeFile4(statePath, `${JSON.stringify(file, null, 2)}
10019
10513
  `, "utf8");
10020
10514
  }
@@ -10063,7 +10557,7 @@ async function readSyncLocalTriggerState(statePath) {
10063
10557
  return nextState;
10064
10558
  }
10065
10559
  async function writeSyncLocalTriggerState(statePath, state) {
10066
- await mkdir5(path21.dirname(statePath), { recursive: true });
10560
+ await mkdir5(path22.dirname(statePath), { recursive: true });
10067
10561
  await writeFile4(statePath, `${JSON.stringify(state, null, 2)}
10068
10562
  `, "utf8");
10069
10563
  }
@@ -10078,12 +10572,12 @@ async function readSyncLocalLock(lockPath) {
10078
10572
  return { pid: lock.pid, startedAt: lock.startedAt };
10079
10573
  }
10080
10574
  async function writeSyncLocalLock(lockPath, lock) {
10081
- await mkdir5(path21.dirname(lockPath), { recursive: true });
10575
+ await mkdir5(path22.dirname(lockPath), { recursive: true });
10082
10576
  await writeFile4(lockPath, `${JSON.stringify(lock, null, 2)}
10083
10577
  `, "utf8");
10084
10578
  }
10085
10579
  async function acquireSyncLocalLock(lockPath, lock) {
10086
- await mkdir5(path21.dirname(lockPath), { recursive: true });
10580
+ await mkdir5(path22.dirname(lockPath), { recursive: true });
10087
10581
  try {
10088
10582
  const handle = await open(lockPath, "wx");
10089
10583
  try {
@@ -10163,10 +10657,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
10163
10657
  if (cliPath.endsWith(".ts")) {
10164
10658
  return ["--import", "tsx", cliPath];
10165
10659
  }
10166
- return [path21.resolve(path21.dirname(cliPath), "../bin/vibetime.mjs")];
10660
+ return [path22.resolve(path22.dirname(cliPath), "../bin/vibetime.mjs")];
10167
10661
  }
10168
10662
  function resolveHome3(options, ctx) {
10169
- return path21.resolve(stringOption(options.home) || ctx.env.HOME || os9.homedir());
10663
+ return path22.resolve(stringOption(options.home) || ctx.env.HOME || os9.homedir());
10170
10664
  }
10171
10665
  function requestedTargets(options) {
10172
10666
  const value = options.target || options.targets;