@yhong91/vibetime 0.1.31 → 0.1.32
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.
- package/bin/vibetime.mjs +271 -126
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -885,8 +885,8 @@ var init_esm = __esm({
|
|
|
885
885
|
// src/cli.ts
|
|
886
886
|
import { spawn as spawn2, spawnSync } from "node:child_process";
|
|
887
887
|
import { mkdir as mkdir5, open, rm, stat as stat13, writeFile as writeFile4 } from "node:fs/promises";
|
|
888
|
-
import
|
|
889
|
-
import
|
|
888
|
+
import os11 from "node:os";
|
|
889
|
+
import path24 from "node:path";
|
|
890
890
|
import { fileURLToPath } from "node:url";
|
|
891
891
|
|
|
892
892
|
// ../shared/src/index.ts
|
|
@@ -1928,7 +1928,7 @@ function countTextLines(text) {
|
|
|
1928
1928
|
}
|
|
1929
1929
|
|
|
1930
1930
|
// src/lib/constants.ts
|
|
1931
|
-
var PACKAGE_VERSION = true ? "0.1.
|
|
1931
|
+
var PACKAGE_VERSION = true ? "0.1.32" : "0.1.1";
|
|
1932
1932
|
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
1933
1933
|
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
1934
1934
|
var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
|
|
@@ -7426,12 +7426,91 @@ function createPiAdapter() {
|
|
|
7426
7426
|
};
|
|
7427
7427
|
}
|
|
7428
7428
|
|
|
7429
|
-
// src/adapters/qoder-
|
|
7430
|
-
import {
|
|
7429
|
+
// src/adapters/qoder-local-db.ts
|
|
7430
|
+
import { access } from "node:fs/promises";
|
|
7431
7431
|
import os7 from "node:os";
|
|
7432
7432
|
import path16 from "node:path";
|
|
7433
|
+
function qoderLocalDbCandidates(appDirName) {
|
|
7434
|
+
const candidates = [];
|
|
7435
|
+
const envPath = process.env.QODER_LOCAL_DB_PATH;
|
|
7436
|
+
if (envPath) {
|
|
7437
|
+
candidates.push(envPath);
|
|
7438
|
+
}
|
|
7439
|
+
const home = os7.homedir();
|
|
7440
|
+
let configRoot;
|
|
7441
|
+
if (process.platform === "darwin") {
|
|
7442
|
+
configRoot = path16.join(home, "Library", "Application Support", appDirName);
|
|
7443
|
+
} else if (process.platform === "win32") {
|
|
7444
|
+
configRoot = path16.join(process.env.APPDATA || path16.join(home, "AppData", "Roaming"), appDirName);
|
|
7445
|
+
} else {
|
|
7446
|
+
configRoot = path16.join(home, ".config", appDirName);
|
|
7447
|
+
}
|
|
7448
|
+
candidates.push(
|
|
7449
|
+
path16.join(configRoot, "SharedClientCache", "cache", "db", "local.db"),
|
|
7450
|
+
path16.join(configRoot, "SharedClientCache", "db", "local.db")
|
|
7451
|
+
);
|
|
7452
|
+
return candidates;
|
|
7453
|
+
}
|
|
7454
|
+
async function loadQoderDbModelCalls(appDirName, sessionId, modelMap) {
|
|
7455
|
+
const calls = { byRequestId: /* @__PURE__ */ new Map(), ordered: [] };
|
|
7456
|
+
if (!sessionId) {
|
|
7457
|
+
return calls;
|
|
7458
|
+
}
|
|
7459
|
+
try {
|
|
7460
|
+
const { DatabaseSync } = await import("node:sqlite");
|
|
7461
|
+
let dbPath;
|
|
7462
|
+
for (const candidate of qoderLocalDbCandidates(appDirName)) {
|
|
7463
|
+
try {
|
|
7464
|
+
await access(candidate);
|
|
7465
|
+
dbPath = candidate;
|
|
7466
|
+
break;
|
|
7467
|
+
} catch {
|
|
7468
|
+
}
|
|
7469
|
+
}
|
|
7470
|
+
if (!dbPath) {
|
|
7471
|
+
return calls;
|
|
7472
|
+
}
|
|
7473
|
+
const db = new DatabaseSync(dbPath, { readOnly: true });
|
|
7474
|
+
try {
|
|
7475
|
+
const rows = db.prepare(
|
|
7476
|
+
`select request_id, token_info, model_info from chat_message where session_id = ? and role = 'assistant' and token_info != '' order by gmt_create asc`
|
|
7477
|
+
).all(sessionId);
|
|
7478
|
+
for (const row of rows) {
|
|
7479
|
+
const usage = parseJsonLine(stringField(row, "token_info") || "") || {};
|
|
7480
|
+
const modelInfo = parseJsonLine(stringField(row, "model_info") || "") || {};
|
|
7481
|
+
const modelKey = stringField(modelInfo, "model_key");
|
|
7482
|
+
const call = {
|
|
7483
|
+
model: modelKey ? modelMap[modelKey] || modelKey : void 0,
|
|
7484
|
+
inputTokens: numberField(usage, "prompt_tokens") || 0,
|
|
7485
|
+
outputTokens: numberField(usage, "completion_tokens") || 0,
|
|
7486
|
+
cachedTokens: numberField(usage, "cached_tokens") || 0
|
|
7487
|
+
};
|
|
7488
|
+
calls.ordered.push(call);
|
|
7489
|
+
const requestId = stringField(row, "request_id");
|
|
7490
|
+
if (!requestId) {
|
|
7491
|
+
continue;
|
|
7492
|
+
}
|
|
7493
|
+
const queue = calls.byRequestId.get(requestId);
|
|
7494
|
+
if (queue) {
|
|
7495
|
+
queue.push(call);
|
|
7496
|
+
} else {
|
|
7497
|
+
calls.byRequestId.set(requestId, [call]);
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
} finally {
|
|
7501
|
+
db.close();
|
|
7502
|
+
}
|
|
7503
|
+
} catch {
|
|
7504
|
+
}
|
|
7505
|
+
return calls;
|
|
7506
|
+
}
|
|
7507
|
+
|
|
7508
|
+
// src/adapters/qoder-cn.ts
|
|
7509
|
+
import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
|
|
7510
|
+
import os8 from "node:os";
|
|
7511
|
+
import path17 from "node:path";
|
|
7433
7512
|
function parseQoderCnPaths(filePath) {
|
|
7434
|
-
const parts = filePath.split(
|
|
7513
|
+
const parts = filePath.split(path17.sep);
|
|
7435
7514
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
7436
7515
|
let sessionId = "";
|
|
7437
7516
|
let projectName = "";
|
|
@@ -7441,14 +7520,17 @@ function parseQoderCnPaths(filePath) {
|
|
|
7441
7520
|
sessionId = parts[subagentsIdx - 1];
|
|
7442
7521
|
projectName = parts[subagentsIdx - 2];
|
|
7443
7522
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
7444
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
7445
|
-
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(
|
|
7523
|
+
configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
|
|
7524
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path17.sep);
|
|
7446
7525
|
} else {
|
|
7447
7526
|
const filename = parts.at(-1) || "";
|
|
7448
|
-
sessionId =
|
|
7527
|
+
sessionId = path17.basename(filename, ".jsonl");
|
|
7449
7528
|
projectName = parts.at(-2) || "";
|
|
7529
|
+
if (projectName === "transcript") {
|
|
7530
|
+
projectName = parts.at(-3) || "";
|
|
7531
|
+
}
|
|
7450
7532
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
7451
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
7533
|
+
configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
|
|
7452
7534
|
}
|
|
7453
7535
|
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
7454
7536
|
}
|
|
@@ -7471,7 +7553,7 @@ function rebuildEventIdentity2(event) {
|
|
|
7471
7553
|
}
|
|
7472
7554
|
async function loadQoderCnModelNames(configDir2) {
|
|
7473
7555
|
try {
|
|
7474
|
-
const dynamicTextsPath =
|
|
7556
|
+
const dynamicTextsPath = path17.join(configDir2, ".auth", "dynamic-texts.json");
|
|
7475
7557
|
const content = await readFile10(dynamicTextsPath, "utf8");
|
|
7476
7558
|
const json = JSON.parse(content);
|
|
7477
7559
|
const texts = json.texts || {};
|
|
@@ -7489,7 +7571,7 @@ async function loadQoderCnModelNames(configDir2) {
|
|
|
7489
7571
|
}
|
|
7490
7572
|
async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
7491
7573
|
const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
|
|
7492
|
-
const segmentsPath =
|
|
7574
|
+
const segmentsPath = path17.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
7493
7575
|
const modelCalls = [];
|
|
7494
7576
|
try {
|
|
7495
7577
|
const files = await readdir7(segmentsPath);
|
|
@@ -7497,7 +7579,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
|
|
|
7497
7579
|
if (!file.endsWith(".jsonl")) {
|
|
7498
7580
|
continue;
|
|
7499
7581
|
}
|
|
7500
|
-
const content = await readFile10(
|
|
7582
|
+
const content = await readFile10(path17.join(segmentsPath, file), "utf8");
|
|
7501
7583
|
let currentTurnIsSubagent = false;
|
|
7502
7584
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
7503
7585
|
const raw = parseJsonLine(line);
|
|
@@ -7544,6 +7626,17 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7544
7626
|
const isSubagentSession = filePath.includes("subagents");
|
|
7545
7627
|
const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
7546
7628
|
let modelCallIndex = 0;
|
|
7629
|
+
let dbModelCalls;
|
|
7630
|
+
const nextDbModelCall = async (requestId, blockStart) => {
|
|
7631
|
+
dbModelCalls ??= await loadQoderDbModelCalls("QoderCN", sessionId, modelMap);
|
|
7632
|
+
if (requestId) {
|
|
7633
|
+
return dbModelCalls.byRequestId.get(requestId)?.shift();
|
|
7634
|
+
}
|
|
7635
|
+
if (!blockStart) {
|
|
7636
|
+
return void 0;
|
|
7637
|
+
}
|
|
7638
|
+
return dbModelCalls.ordered.shift();
|
|
7639
|
+
};
|
|
7547
7640
|
const state = new SessionParserState(filePath, options, (event) => baseQoderCnEvent({ ...event, cwd, project, model }));
|
|
7548
7641
|
state.sessionId = sessionId;
|
|
7549
7642
|
const push = (event, ln, topType, payloadType) => {
|
|
@@ -7554,6 +7647,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7554
7647
|
payloadType
|
|
7555
7648
|
);
|
|
7556
7649
|
};
|
|
7650
|
+
let assistantBlockOpen = false;
|
|
7557
7651
|
for (const [index, line] of lines.entries()) {
|
|
7558
7652
|
const lineNumber = index + 1;
|
|
7559
7653
|
const raw = parseJsonLine(line);
|
|
@@ -7561,11 +7655,14 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7561
7655
|
continue;
|
|
7562
7656
|
}
|
|
7563
7657
|
const topType = stringField(raw, "type");
|
|
7658
|
+
if (topType !== "assistant") {
|
|
7659
|
+
assistantBlockOpen = false;
|
|
7660
|
+
}
|
|
7564
7661
|
const ts = timestampFrom(raw.timestamp);
|
|
7565
7662
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
7566
7663
|
state.sessionId = sessionId;
|
|
7567
7664
|
cwd = stringField(raw, "cwd") || cwd;
|
|
7568
|
-
project = projectContext.project || (cwd ?
|
|
7665
|
+
project = projectContext.project || (cwd ? path17.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
|
|
7569
7666
|
if (!ts) {
|
|
7570
7667
|
continue;
|
|
7571
7668
|
}
|
|
@@ -7698,6 +7795,8 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7698
7795
|
model = rawModel ? modelMap[rawModel] || rawModel : void 0;
|
|
7699
7796
|
const messageId = stringField(message, "id");
|
|
7700
7797
|
const requestId = stringField(raw, "requestId");
|
|
7798
|
+
const isBlockStart = !assistantBlockOpen;
|
|
7799
|
+
assistantBlockOpen = true;
|
|
7701
7800
|
const usageKey = messageId ? `${messageId}:${requestId}` : null;
|
|
7702
7801
|
const shouldEmitUsage = usageKey == null || !seenUsageKeys.has(usageKey);
|
|
7703
7802
|
if (usageKey != null) {
|
|
@@ -7722,6 +7821,19 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7722
7821
|
modelCalls: 1
|
|
7723
7822
|
};
|
|
7724
7823
|
model = call.model || model;
|
|
7824
|
+
} else if (shouldEmitUsage) {
|
|
7825
|
+
const dbCall = await nextDbModelCall(requestId, isBlockStart);
|
|
7826
|
+
if (dbCall) {
|
|
7827
|
+
usage = {
|
|
7828
|
+
tokensInput: dbCall.inputTokens || void 0,
|
|
7829
|
+
tokensCachedInput: dbCall.cachedTokens || void 0,
|
|
7830
|
+
tokensCacheReadInput: dbCall.cachedTokens || void 0,
|
|
7831
|
+
tokensOutput: dbCall.outputTokens || void 0,
|
|
7832
|
+
tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
|
|
7833
|
+
modelCalls: 1
|
|
7834
|
+
};
|
|
7835
|
+
model = dbCall.model || model;
|
|
7836
|
+
}
|
|
7725
7837
|
}
|
|
7726
7838
|
if (usage) {
|
|
7727
7839
|
const speed = stringField(objectField(message, "usage"), "speed");
|
|
@@ -8002,28 +8114,28 @@ function isNoisePrompt(text) {
|
|
|
8002
8114
|
}
|
|
8003
8115
|
async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
8004
8116
|
const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
|
|
8005
|
-
const isSubagent = filePath.includes(`${
|
|
8117
|
+
const isSubagent = filePath.includes(`${path17.sep}subagents${path17.sep}`);
|
|
8006
8118
|
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
8007
8119
|
let cwds = [];
|
|
8008
8120
|
for (const line of lines) {
|
|
8009
8121
|
const raw = parseJsonLine(line);
|
|
8010
8122
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8011
|
-
if (cwd &&
|
|
8123
|
+
if (cwd && path17.isAbsolute(cwd)) {
|
|
8012
8124
|
cwds.push(cwd);
|
|
8013
8125
|
}
|
|
8014
8126
|
}
|
|
8015
8127
|
if (isSubagent) {
|
|
8016
|
-
if (inherited?.cwd &&
|
|
8128
|
+
if (inherited?.cwd && path17.isAbsolute(inherited.cwd)) {
|
|
8017
8129
|
cwds = [inherited.cwd];
|
|
8018
8130
|
} else {
|
|
8019
|
-
const parentSessionPath =
|
|
8131
|
+
const parentSessionPath = path17.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
8020
8132
|
try {
|
|
8021
8133
|
const parentText = await readFile10(parentSessionPath, "utf8");
|
|
8022
8134
|
const parentCwds = [];
|
|
8023
8135
|
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
8024
8136
|
const raw = parseJsonLine(line);
|
|
8025
8137
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8026
|
-
if (cwd &&
|
|
8138
|
+
if (cwd && path17.isAbsolute(cwd)) {
|
|
8027
8139
|
parentCwds.push(cwd);
|
|
8028
8140
|
}
|
|
8029
8141
|
}
|
|
@@ -8035,7 +8147,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
8035
8147
|
}
|
|
8036
8148
|
}
|
|
8037
8149
|
const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
|
|
8038
|
-
const project = inherited?.project || (cwds.length > 0 ?
|
|
8150
|
+
const project = inherited?.project || (cwds.length > 0 ? path17.basename(cwds[0]) : root ? path17.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
|
|
8039
8151
|
return {
|
|
8040
8152
|
project,
|
|
8041
8153
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -8044,15 +8156,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
8044
8156
|
async function gitRootFromCwds2(cwds) {
|
|
8045
8157
|
const seen = /* @__PURE__ */ new Set();
|
|
8046
8158
|
for (const cwd of cwds) {
|
|
8047
|
-
let current =
|
|
8159
|
+
let current = path17.resolve(cwd);
|
|
8048
8160
|
while (!seen.has(current)) {
|
|
8049
8161
|
seen.add(current);
|
|
8050
8162
|
try {
|
|
8051
|
-
await stat8(
|
|
8163
|
+
await stat8(path17.join(current, ".git"));
|
|
8052
8164
|
return current;
|
|
8053
8165
|
} catch {
|
|
8054
8166
|
}
|
|
8055
|
-
const parent =
|
|
8167
|
+
const parent = path17.dirname(current);
|
|
8056
8168
|
if (parent === current) {
|
|
8057
8169
|
break;
|
|
8058
8170
|
}
|
|
@@ -8063,12 +8175,12 @@ async function gitRootFromCwds2(cwds) {
|
|
|
8063
8175
|
}
|
|
8064
8176
|
function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
8065
8177
|
for (const cwd of cwds) {
|
|
8066
|
-
let current =
|
|
8178
|
+
let current = path17.resolve(cwd);
|
|
8067
8179
|
while (true) {
|
|
8068
8180
|
if (encodeQoderCnProjectPath(current) === projectDir) {
|
|
8069
8181
|
return current;
|
|
8070
8182
|
}
|
|
8071
|
-
const parent =
|
|
8183
|
+
const parent = path17.dirname(current);
|
|
8072
8184
|
if (parent === current) {
|
|
8073
8185
|
break;
|
|
8074
8186
|
}
|
|
@@ -8078,14 +8190,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
|
8078
8190
|
return void 0;
|
|
8079
8191
|
}
|
|
8080
8192
|
function encodeQoderCnProjectPath(value) {
|
|
8081
|
-
return
|
|
8193
|
+
return path17.resolve(value).split(path17.sep).join("-").replace(/_/g, "-");
|
|
8082
8194
|
}
|
|
8083
8195
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
8084
|
-
const projectDir =
|
|
8085
|
-
const home = options ?
|
|
8196
|
+
const projectDir = path17.basename(path17.dirname(filePath));
|
|
8197
|
+
const home = options ? path17.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
|
|
8086
8198
|
const resolved = await resolveQoderCnProjectPath(projectDir, home);
|
|
8087
8199
|
if (resolved) {
|
|
8088
|
-
return
|
|
8200
|
+
return path17.basename(resolved);
|
|
8089
8201
|
}
|
|
8090
8202
|
const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
|
|
8091
8203
|
if (projectDir.startsWith(homePrefix)) {
|
|
@@ -8110,7 +8222,7 @@ async function resolveQoderCnProjectPath(projectDir, home) {
|
|
|
8110
8222
|
if (!entry.isDirectory()) {
|
|
8111
8223
|
continue;
|
|
8112
8224
|
}
|
|
8113
|
-
const candidate =
|
|
8225
|
+
const candidate = path17.join(current, entry.name);
|
|
8114
8226
|
const encoded = encodeQoderCnProjectPath(candidate);
|
|
8115
8227
|
if (encoded === projectDir) {
|
|
8116
8228
|
return candidate;
|
|
@@ -8155,9 +8267,9 @@ function hookConfig6() {
|
|
|
8155
8267
|
function qoderCnConfigDir(home, env) {
|
|
8156
8268
|
const override = env?.QODER_CN_CONFIG_DIR;
|
|
8157
8269
|
if (override && override.trim()) {
|
|
8158
|
-
return
|
|
8270
|
+
return path17.resolve(override);
|
|
8159
8271
|
}
|
|
8160
|
-
return
|
|
8272
|
+
return path17.join(home, ".qoder-cn");
|
|
8161
8273
|
}
|
|
8162
8274
|
function createQoderCnAdapter() {
|
|
8163
8275
|
return {
|
|
@@ -8169,27 +8281,27 @@ function createQoderCnAdapter() {
|
|
|
8169
8281
|
return qoderCnConfigDir(home, env);
|
|
8170
8282
|
},
|
|
8171
8283
|
installedPath(home, env) {
|
|
8172
|
-
return
|
|
8284
|
+
return path17.join(qoderCnConfigDir(home, env), "settings.json");
|
|
8173
8285
|
},
|
|
8174
8286
|
async isInstalled(home, env) {
|
|
8175
8287
|
return isHooksJsonInstalled(
|
|
8176
|
-
|
|
8288
|
+
path17.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
8177
8289
|
"vibetime hook --agent qoder-cn"
|
|
8178
8290
|
);
|
|
8179
8291
|
},
|
|
8180
8292
|
installEntries(home, env) {
|
|
8181
8293
|
return [{
|
|
8182
8294
|
kind: "hooks-json",
|
|
8183
|
-
path:
|
|
8295
|
+
path: path17.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
8184
8296
|
content: hookConfig6()
|
|
8185
8297
|
}];
|
|
8186
8298
|
},
|
|
8187
8299
|
sourcePaths(home, env) {
|
|
8188
8300
|
const base = qoderCnConfigDir(home, env);
|
|
8189
8301
|
return [
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8302
|
+
path17.join(base, "projects"),
|
|
8303
|
+
path17.join(base, ".qoder.json"),
|
|
8304
|
+
path17.join(home, ".qoder.json")
|
|
8193
8305
|
];
|
|
8194
8306
|
},
|
|
8195
8307
|
parseSessionFile: parseQoderCnSessionFile
|
|
@@ -8198,10 +8310,10 @@ function createQoderCnAdapter() {
|
|
|
8198
8310
|
|
|
8199
8311
|
// src/adapters/qoder.ts
|
|
8200
8312
|
import { readdir as readdir8, readFile as readFile11, stat as stat9 } from "node:fs/promises";
|
|
8201
|
-
import
|
|
8202
|
-
import
|
|
8313
|
+
import os9 from "node:os";
|
|
8314
|
+
import path18 from "node:path";
|
|
8203
8315
|
function parseQoderPaths(filePath) {
|
|
8204
|
-
const parts = filePath.split(
|
|
8316
|
+
const parts = filePath.split(path18.sep);
|
|
8205
8317
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
8206
8318
|
let sessionId = "";
|
|
8207
8319
|
let projectName = "";
|
|
@@ -8211,14 +8323,17 @@ function parseQoderPaths(filePath) {
|
|
|
8211
8323
|
sessionId = parts[subagentsIdx - 1];
|
|
8212
8324
|
projectName = parts[subagentsIdx - 2];
|
|
8213
8325
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8214
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
8215
|
-
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(
|
|
8326
|
+
configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
|
|
8327
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path18.sep);
|
|
8216
8328
|
} else {
|
|
8217
8329
|
const filename = parts.at(-1) || "";
|
|
8218
|
-
sessionId =
|
|
8330
|
+
sessionId = path18.basename(filename, ".jsonl");
|
|
8219
8331
|
projectName = parts.at(-2) || "";
|
|
8332
|
+
if (projectName === "transcript") {
|
|
8333
|
+
projectName = parts.at(-3) || "";
|
|
8334
|
+
}
|
|
8220
8335
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8221
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
8336
|
+
configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
|
|
8222
8337
|
}
|
|
8223
8338
|
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
8224
8339
|
}
|
|
@@ -8241,7 +8356,7 @@ function rebuildEventIdentity3(event) {
|
|
|
8241
8356
|
}
|
|
8242
8357
|
async function loadQoderModelNames(configDir2) {
|
|
8243
8358
|
try {
|
|
8244
|
-
const dynamicTextsPath =
|
|
8359
|
+
const dynamicTextsPath = path18.join(configDir2, ".auth", "dynamic-texts.json");
|
|
8245
8360
|
const content = await readFile11(dynamicTextsPath, "utf8");
|
|
8246
8361
|
const json = JSON.parse(content);
|
|
8247
8362
|
const texts = json.texts || {};
|
|
@@ -8259,7 +8374,7 @@ async function loadQoderModelNames(configDir2) {
|
|
|
8259
8374
|
}
|
|
8260
8375
|
async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
8261
8376
|
const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
|
|
8262
|
-
const segmentsPath =
|
|
8377
|
+
const segmentsPath = path18.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
8263
8378
|
const modelCalls = [];
|
|
8264
8379
|
try {
|
|
8265
8380
|
const files = await readdir8(segmentsPath);
|
|
@@ -8267,7 +8382,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
|
|
|
8267
8382
|
if (!file.endsWith(".jsonl")) {
|
|
8268
8383
|
continue;
|
|
8269
8384
|
}
|
|
8270
|
-
const content = await readFile11(
|
|
8385
|
+
const content = await readFile11(path18.join(segmentsPath, file), "utf8");
|
|
8271
8386
|
let currentTurnIsSubagent = false;
|
|
8272
8387
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
8273
8388
|
const raw = parseJsonLine(line);
|
|
@@ -8314,6 +8429,17 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8314
8429
|
const isSubagentSession = filePath.includes("subagents");
|
|
8315
8430
|
const segmentModelCalls = await loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
8316
8431
|
let modelCallIndex = 0;
|
|
8432
|
+
let dbModelCalls;
|
|
8433
|
+
const nextDbModelCall = async (requestId, blockStart) => {
|
|
8434
|
+
dbModelCalls ??= await loadQoderDbModelCalls("Qoder", sessionId, modelMap);
|
|
8435
|
+
if (requestId) {
|
|
8436
|
+
return dbModelCalls.byRequestId.get(requestId)?.shift();
|
|
8437
|
+
}
|
|
8438
|
+
if (!blockStart) {
|
|
8439
|
+
return void 0;
|
|
8440
|
+
}
|
|
8441
|
+
return dbModelCalls.ordered.shift();
|
|
8442
|
+
};
|
|
8317
8443
|
const state = new SessionParserState(filePath, options, (event) => baseQoderEvent({ ...event, cwd, project, model }));
|
|
8318
8444
|
state.sessionId = sessionId;
|
|
8319
8445
|
const push = (event, ln, topType, payloadType) => {
|
|
@@ -8324,6 +8450,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8324
8450
|
payloadType
|
|
8325
8451
|
);
|
|
8326
8452
|
};
|
|
8453
|
+
let assistantBlockOpen = false;
|
|
8327
8454
|
for (const [index, line] of lines.entries()) {
|
|
8328
8455
|
const lineNumber = index + 1;
|
|
8329
8456
|
const raw = parseJsonLine(line);
|
|
@@ -8331,11 +8458,14 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8331
8458
|
continue;
|
|
8332
8459
|
}
|
|
8333
8460
|
const topType = stringField(raw, "type");
|
|
8461
|
+
if (topType !== "assistant") {
|
|
8462
|
+
assistantBlockOpen = false;
|
|
8463
|
+
}
|
|
8334
8464
|
const ts = timestampFrom(raw.timestamp);
|
|
8335
8465
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
8336
8466
|
state.sessionId = sessionId;
|
|
8337
8467
|
cwd = stringField(raw, "cwd") || cwd;
|
|
8338
|
-
project = projectContext.project || (cwd ?
|
|
8468
|
+
project = projectContext.project || (cwd ? path18.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
|
|
8339
8469
|
if (!ts) {
|
|
8340
8470
|
continue;
|
|
8341
8471
|
}
|
|
@@ -8468,6 +8598,8 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8468
8598
|
model = rawModel ? modelMap[rawModel] || rawModel : void 0;
|
|
8469
8599
|
const messageId = stringField(message, "id");
|
|
8470
8600
|
const requestId = stringField(raw, "requestId");
|
|
8601
|
+
const isBlockStart = !assistantBlockOpen;
|
|
8602
|
+
assistantBlockOpen = true;
|
|
8471
8603
|
const usageKey = messageId ? `${messageId}:${requestId}` : null;
|
|
8472
8604
|
const shouldEmitUsage = usageKey == null || !seenUsageKeys.has(usageKey);
|
|
8473
8605
|
if (usageKey != null) {
|
|
@@ -8492,6 +8624,19 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8492
8624
|
modelCalls: 1
|
|
8493
8625
|
};
|
|
8494
8626
|
model = call.model || model;
|
|
8627
|
+
} else if (shouldEmitUsage) {
|
|
8628
|
+
const dbCall = await nextDbModelCall(requestId, isBlockStart);
|
|
8629
|
+
if (dbCall) {
|
|
8630
|
+
usage = {
|
|
8631
|
+
tokensInput: dbCall.inputTokens || void 0,
|
|
8632
|
+
tokensCachedInput: dbCall.cachedTokens || void 0,
|
|
8633
|
+
tokensCacheReadInput: dbCall.cachedTokens || void 0,
|
|
8634
|
+
tokensOutput: dbCall.outputTokens || void 0,
|
|
8635
|
+
tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
|
|
8636
|
+
modelCalls: 1
|
|
8637
|
+
};
|
|
8638
|
+
model = dbCall.model || model;
|
|
8639
|
+
}
|
|
8495
8640
|
}
|
|
8496
8641
|
if (usage) {
|
|
8497
8642
|
const speed = stringField(objectField(message, "usage"), "speed");
|
|
@@ -8738,28 +8883,28 @@ function qoderExtractText(value) {
|
|
|
8738
8883
|
}
|
|
8739
8884
|
async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
8740
8885
|
const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
|
|
8741
|
-
const isSubagent = filePath.includes(`${
|
|
8886
|
+
const isSubagent = filePath.includes(`${path18.sep}subagents${path18.sep}`);
|
|
8742
8887
|
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
8743
8888
|
let cwds = [];
|
|
8744
8889
|
for (const line of lines) {
|
|
8745
8890
|
const raw = parseJsonLine(line);
|
|
8746
8891
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8747
|
-
if (cwd &&
|
|
8892
|
+
if (cwd && path18.isAbsolute(cwd)) {
|
|
8748
8893
|
cwds.push(cwd);
|
|
8749
8894
|
}
|
|
8750
8895
|
}
|
|
8751
8896
|
if (isSubagent) {
|
|
8752
|
-
if (inherited?.cwd &&
|
|
8897
|
+
if (inherited?.cwd && path18.isAbsolute(inherited.cwd)) {
|
|
8753
8898
|
cwds = [inherited.cwd];
|
|
8754
8899
|
} else {
|
|
8755
|
-
const parentSessionPath =
|
|
8900
|
+
const parentSessionPath = path18.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
8756
8901
|
try {
|
|
8757
8902
|
const parentText = await readFile11(parentSessionPath, "utf8");
|
|
8758
8903
|
const parentCwds = [];
|
|
8759
8904
|
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
8760
8905
|
const raw = parseJsonLine(line);
|
|
8761
8906
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8762
|
-
if (cwd &&
|
|
8907
|
+
if (cwd && path18.isAbsolute(cwd)) {
|
|
8763
8908
|
parentCwds.push(cwd);
|
|
8764
8909
|
}
|
|
8765
8910
|
}
|
|
@@ -8771,7 +8916,7 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
8771
8916
|
}
|
|
8772
8917
|
}
|
|
8773
8918
|
const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
|
|
8774
|
-
const project = inherited?.project || (cwds.length > 0 ?
|
|
8919
|
+
const project = inherited?.project || (cwds.length > 0 ? path18.basename(cwds[0]) : root ? path18.basename(root) : await qoderProjectFromFilePath(filePath, options));
|
|
8775
8920
|
return {
|
|
8776
8921
|
project,
|
|
8777
8922
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -8780,15 +8925,15 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
8780
8925
|
async function gitRootFromCwds3(cwds) {
|
|
8781
8926
|
const seen = /* @__PURE__ */ new Set();
|
|
8782
8927
|
for (const cwd of cwds) {
|
|
8783
|
-
let current =
|
|
8928
|
+
let current = path18.resolve(cwd);
|
|
8784
8929
|
while (!seen.has(current)) {
|
|
8785
8930
|
seen.add(current);
|
|
8786
8931
|
try {
|
|
8787
|
-
await stat9(
|
|
8932
|
+
await stat9(path18.join(current, ".git"));
|
|
8788
8933
|
return current;
|
|
8789
8934
|
} catch {
|
|
8790
8935
|
}
|
|
8791
|
-
const parent =
|
|
8936
|
+
const parent = path18.dirname(current);
|
|
8792
8937
|
if (parent === current) {
|
|
8793
8938
|
break;
|
|
8794
8939
|
}
|
|
@@ -8799,12 +8944,12 @@ async function gitRootFromCwds3(cwds) {
|
|
|
8799
8944
|
}
|
|
8800
8945
|
function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
8801
8946
|
for (const cwd of cwds) {
|
|
8802
|
-
let current =
|
|
8947
|
+
let current = path18.resolve(cwd);
|
|
8803
8948
|
while (true) {
|
|
8804
8949
|
if (encodeQoderProjectPath(current) === projectDir) {
|
|
8805
8950
|
return current;
|
|
8806
8951
|
}
|
|
8807
|
-
const parent =
|
|
8952
|
+
const parent = path18.dirname(current);
|
|
8808
8953
|
if (parent === current) {
|
|
8809
8954
|
break;
|
|
8810
8955
|
}
|
|
@@ -8814,10 +8959,10 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
|
8814
8959
|
return void 0;
|
|
8815
8960
|
}
|
|
8816
8961
|
function encodeQoderProjectPath(value) {
|
|
8817
|
-
return
|
|
8962
|
+
return path18.resolve(value).split(path18.sep).join("-").replace(/_/g, "-");
|
|
8818
8963
|
}
|
|
8819
8964
|
function rawQoderProjectPath(value) {
|
|
8820
|
-
return
|
|
8965
|
+
return path18.resolve(value).split(path18.sep).join("-");
|
|
8821
8966
|
}
|
|
8822
8967
|
function qoderEncodedVariants(value) {
|
|
8823
8968
|
const raw = rawQoderProjectPath(value);
|
|
@@ -8833,11 +8978,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
|
|
|
8833
8978
|
return void 0;
|
|
8834
8979
|
}
|
|
8835
8980
|
async function qoderProjectFromFilePath(filePath, options) {
|
|
8836
|
-
const projectDir =
|
|
8837
|
-
const home = options ?
|
|
8981
|
+
const projectDir = path18.basename(path18.dirname(filePath));
|
|
8982
|
+
const home = options ? path18.resolve(stringOption(options.home) || os9.homedir()) : os9.homedir();
|
|
8838
8983
|
const resolved = await resolveQoderProjectPath(projectDir, home);
|
|
8839
8984
|
if (resolved) {
|
|
8840
|
-
return
|
|
8985
|
+
return path18.basename(resolved);
|
|
8841
8986
|
}
|
|
8842
8987
|
const suffix = qoderEncodedProjectSuffix(projectDir, home);
|
|
8843
8988
|
if (suffix) {
|
|
@@ -8863,7 +9008,7 @@ async function resolveQoderProjectPath(projectDir, home) {
|
|
|
8863
9008
|
if (!entry.isDirectory()) {
|
|
8864
9009
|
continue;
|
|
8865
9010
|
}
|
|
8866
|
-
const candidate =
|
|
9011
|
+
const candidate = path18.join(current, entry.name);
|
|
8867
9012
|
const candidateVariants = qoderEncodedVariants(candidate);
|
|
8868
9013
|
if (candidateVariants.includes(projectDir)) {
|
|
8869
9014
|
return candidate;
|
|
@@ -8908,9 +9053,9 @@ function hookConfig7() {
|
|
|
8908
9053
|
function qoderConfigDir(home, env) {
|
|
8909
9054
|
const override = env?.QODER_CONFIG_DIR;
|
|
8910
9055
|
if (override && override.trim()) {
|
|
8911
|
-
return
|
|
9056
|
+
return path18.resolve(override);
|
|
8912
9057
|
}
|
|
8913
|
-
return
|
|
9058
|
+
return path18.join(home, ".qoder");
|
|
8914
9059
|
}
|
|
8915
9060
|
function createQoderAdapter() {
|
|
8916
9061
|
return {
|
|
@@ -8922,27 +9067,27 @@ function createQoderAdapter() {
|
|
|
8922
9067
|
return qoderConfigDir(home, env);
|
|
8923
9068
|
},
|
|
8924
9069
|
installedPath(home, env) {
|
|
8925
|
-
return
|
|
9070
|
+
return path18.join(qoderConfigDir(home, env), "settings.json");
|
|
8926
9071
|
},
|
|
8927
9072
|
async isInstalled(home, env) {
|
|
8928
9073
|
return isHooksJsonInstalled(
|
|
8929
|
-
|
|
9074
|
+
path18.join(qoderConfigDir(home, env), "settings.json"),
|
|
8930
9075
|
"vibetime hook --agent qoder"
|
|
8931
9076
|
);
|
|
8932
9077
|
},
|
|
8933
9078
|
installEntries(home, env) {
|
|
8934
9079
|
return [{
|
|
8935
9080
|
kind: "hooks-json",
|
|
8936
|
-
path:
|
|
9081
|
+
path: path18.join(qoderConfigDir(home, env), "settings.json"),
|
|
8937
9082
|
content: hookConfig7()
|
|
8938
9083
|
}];
|
|
8939
9084
|
},
|
|
8940
9085
|
sourcePaths(home, env) {
|
|
8941
9086
|
const base = qoderConfigDir(home, env);
|
|
8942
9087
|
return [
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
9088
|
+
path18.join(base, "projects"),
|
|
9089
|
+
path18.join(base, ".qoder.json"),
|
|
9090
|
+
path18.join(home, ".qoder.json")
|
|
8946
9091
|
];
|
|
8947
9092
|
},
|
|
8948
9093
|
parseSessionFile: parseQoderSessionFile
|
|
@@ -8978,20 +9123,20 @@ function normalizeId(id) {
|
|
|
8978
9123
|
|
|
8979
9124
|
// src/adapters/workbuddy.ts
|
|
8980
9125
|
import { readFile as readFile12, readdir as readdir9, stat as stat10 } from "node:fs/promises";
|
|
8981
|
-
import
|
|
9126
|
+
import path19 from "node:path";
|
|
8982
9127
|
init_fs();
|
|
8983
9128
|
function workbuddyProjectsDir(home, env) {
|
|
8984
9129
|
const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
|
|
8985
9130
|
if (override && override.trim()) {
|
|
8986
|
-
return
|
|
9131
|
+
return path19.resolve(override, override.endsWith("projects") ? "" : "projects");
|
|
8987
9132
|
}
|
|
8988
|
-
return
|
|
9133
|
+
return path19.join(home, ".workbuddy", "projects");
|
|
8989
9134
|
}
|
|
8990
9135
|
function projectFromCwd(cwd, fallback) {
|
|
8991
9136
|
if (!cwd) {
|
|
8992
9137
|
return fallback;
|
|
8993
9138
|
}
|
|
8994
|
-
return
|
|
9139
|
+
return path19.basename(cwd) || fallback;
|
|
8995
9140
|
}
|
|
8996
9141
|
function sourceHash(filePath) {
|
|
8997
9142
|
return `sha256:${createStableHash(filePath)}`;
|
|
@@ -9094,8 +9239,8 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9094
9239
|
}
|
|
9095
9240
|
const events = [];
|
|
9096
9241
|
const first = lines[0].record;
|
|
9097
|
-
const sessionId = stringField(first, "sessionId") ||
|
|
9098
|
-
const fallbackProject =
|
|
9242
|
+
const sessionId = stringField(first, "sessionId") || path19.basename(filePath, ".jsonl");
|
|
9243
|
+
const fallbackProject = path19.basename(path19.dirname(filePath));
|
|
9099
9244
|
const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
|
|
9100
9245
|
const project = projectFromCwd(cwd, fallbackProject);
|
|
9101
9246
|
const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
|
|
@@ -9269,11 +9414,11 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
9269
9414
|
if (!project.isDirectory()) {
|
|
9270
9415
|
continue;
|
|
9271
9416
|
}
|
|
9272
|
-
const projectDir =
|
|
9417
|
+
const projectDir = path19.join(base, project.name);
|
|
9273
9418
|
const entries = await readdir9(projectDir, { withFileTypes: true });
|
|
9274
9419
|
for (const entry of entries) {
|
|
9275
9420
|
if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
9276
|
-
const filePath =
|
|
9421
|
+
const filePath = path19.join(projectDir, entry.name);
|
|
9277
9422
|
const info = await stat10(filePath);
|
|
9278
9423
|
files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
|
|
9279
9424
|
}
|
|
@@ -9312,19 +9457,19 @@ function createWorkbuddyAdapter() {
|
|
|
9312
9457
|
// src/adapters/zcode.ts
|
|
9313
9458
|
import { execFile } from "node:child_process";
|
|
9314
9459
|
import { readFile as readFile13, stat as stat11 } from "node:fs/promises";
|
|
9315
|
-
import
|
|
9460
|
+
import path20 from "node:path";
|
|
9316
9461
|
import { promisify as promisify2 } from "node:util";
|
|
9317
9462
|
init_fs();
|
|
9318
9463
|
var execFileAsync = promisify2(execFile);
|
|
9319
9464
|
function zcodeCliDir(home, env) {
|
|
9320
9465
|
const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
|
|
9321
9466
|
if (override && override.trim()) {
|
|
9322
|
-
return
|
|
9467
|
+
return path20.resolve(override, override.endsWith("cli") ? "" : "cli");
|
|
9323
9468
|
}
|
|
9324
|
-
return
|
|
9469
|
+
return path20.join(home, ".zcode", "cli");
|
|
9325
9470
|
}
|
|
9326
9471
|
function zcodeDbPath(home, env) {
|
|
9327
|
-
return
|
|
9472
|
+
return path20.join(zcodeCliDir(home, env), "db", "db.sqlite");
|
|
9328
9473
|
}
|
|
9329
9474
|
var providerNameCache = null;
|
|
9330
9475
|
async function loadProviderNames(configPath2) {
|
|
@@ -9358,7 +9503,7 @@ function sourceHash2(filePath) {
|
|
|
9358
9503
|
return `sha256:${createStableHash(filePath)}`;
|
|
9359
9504
|
}
|
|
9360
9505
|
function projectFromDirectory(directory) {
|
|
9361
|
-
return directory ?
|
|
9506
|
+
return directory ? path20.basename(directory) || "zcode" : "zcode";
|
|
9362
9507
|
}
|
|
9363
9508
|
function isoFromMs(value) {
|
|
9364
9509
|
return timestampFrom(typeof value === "number" ? value : Number(value));
|
|
@@ -9541,16 +9686,16 @@ async function parseZCodeDb(filePath, options) {
|
|
|
9541
9686
|
if (rows.length === 0) {
|
|
9542
9687
|
return [];
|
|
9543
9688
|
}
|
|
9544
|
-
let candidate =
|
|
9689
|
+
let candidate = path20.resolve(filePath);
|
|
9545
9690
|
let configPath2 = "";
|
|
9546
9691
|
for (let i = 0; i < 12; i++) {
|
|
9547
|
-
const probe =
|
|
9692
|
+
const probe = path20.join(candidate, ".zcode", "v2", "config.json");
|
|
9548
9693
|
try {
|
|
9549
9694
|
await stat11(probe);
|
|
9550
9695
|
configPath2 = probe;
|
|
9551
9696
|
break;
|
|
9552
9697
|
} catch {
|
|
9553
|
-
const parent =
|
|
9698
|
+
const parent = path20.dirname(candidate);
|
|
9554
9699
|
if (parent === candidate) break;
|
|
9555
9700
|
candidate = parent;
|
|
9556
9701
|
}
|
|
@@ -9766,7 +9911,7 @@ async function parseZCodeDb(filePath, options) {
|
|
|
9766
9911
|
}
|
|
9767
9912
|
async function zcodeBackfillFiles(sourceRoot, home, env) {
|
|
9768
9913
|
const candidate = sourceRoot || zcodeDbPath(home, env);
|
|
9769
|
-
const filePath = candidate.endsWith(".sqlite") ? candidate :
|
|
9914
|
+
const filePath = candidate.endsWith(".sqlite") ? candidate : path20.join(candidate, "db", "db.sqlite");
|
|
9770
9915
|
try {
|
|
9771
9916
|
const info = await stat11(filePath);
|
|
9772
9917
|
return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
|
|
@@ -9800,50 +9945,50 @@ function createZCodeAdapter() {
|
|
|
9800
9945
|
}
|
|
9801
9946
|
|
|
9802
9947
|
// src/adapters/zed.ts
|
|
9803
|
-
import
|
|
9804
|
-
import
|
|
9948
|
+
import os10 from "node:os";
|
|
9949
|
+
import path21 from "node:path";
|
|
9805
9950
|
function zedThreadsCandidates(home, env) {
|
|
9806
9951
|
const candidates = [];
|
|
9807
9952
|
const platform2 = process.platform;
|
|
9808
9953
|
if (platform2 === "darwin") {
|
|
9809
|
-
candidates.push(
|
|
9954
|
+
candidates.push(path21.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
|
|
9810
9955
|
} else if (platform2 === "win32") {
|
|
9811
9956
|
const appdata = env?.APPDATA;
|
|
9812
9957
|
if (appdata && appdata.trim()) {
|
|
9813
|
-
candidates.push(
|
|
9958
|
+
candidates.push(path21.join(path21.resolve(appdata), "Zed", "threads", "threads.db"));
|
|
9814
9959
|
}
|
|
9815
|
-
candidates.push(
|
|
9960
|
+
candidates.push(path21.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
|
|
9816
9961
|
} else {
|
|
9817
9962
|
const xdgData = env?.XDG_DATA_HOME;
|
|
9818
9963
|
if (xdgData && xdgData.trim()) {
|
|
9819
|
-
candidates.push(
|
|
9964
|
+
candidates.push(path21.join(path21.resolve(xdgData), "zed", "threads", "threads.db"));
|
|
9820
9965
|
}
|
|
9821
|
-
candidates.push(
|
|
9966
|
+
candidates.push(path21.join(home, ".local", "share", "zed", "threads", "threads.db"));
|
|
9822
9967
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
9823
9968
|
if (xdgConfig && xdgConfig.trim()) {
|
|
9824
|
-
candidates.push(
|
|
9969
|
+
candidates.push(path21.join(path21.resolve(xdgConfig), "zed", "threads", "threads.db"));
|
|
9825
9970
|
}
|
|
9826
|
-
candidates.push(
|
|
9971
|
+
candidates.push(path21.join(home, ".config", "zed", "threads", "threads.db"));
|
|
9827
9972
|
}
|
|
9828
9973
|
return candidates;
|
|
9829
9974
|
}
|
|
9830
9975
|
function zedConfigDir(home, env) {
|
|
9831
9976
|
const platform2 = process.platform;
|
|
9832
9977
|
if (platform2 === "darwin") {
|
|
9833
|
-
return
|
|
9978
|
+
return path21.join(home, "Library", "Application Support", "Zed");
|
|
9834
9979
|
}
|
|
9835
9980
|
if (platform2 === "win32") {
|
|
9836
9981
|
const appdata = env?.APPDATA;
|
|
9837
9982
|
if (appdata && appdata.trim()) {
|
|
9838
|
-
return
|
|
9983
|
+
return path21.join(path21.resolve(appdata), "Zed");
|
|
9839
9984
|
}
|
|
9840
|
-
return
|
|
9985
|
+
return path21.join(home, "AppData", "Roaming", "Zed");
|
|
9841
9986
|
}
|
|
9842
9987
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
9843
9988
|
if (xdgConfig && xdgConfig.trim()) {
|
|
9844
|
-
return
|
|
9989
|
+
return path21.join(path21.resolve(xdgConfig), "zed");
|
|
9845
9990
|
}
|
|
9846
|
-
return
|
|
9991
|
+
return path21.join(home, ".config", "zed");
|
|
9847
9992
|
}
|
|
9848
9993
|
function baseZedEvent(event) {
|
|
9849
9994
|
return {
|
|
@@ -9907,7 +10052,7 @@ async function parseZedSessionFile(dbPath, options) {
|
|
|
9907
10052
|
const folderRaw = row.folder_paths || "";
|
|
9908
10053
|
const folder = folderRaw.split(/[\n,]/).map((s) => s.trim()).find(Boolean);
|
|
9909
10054
|
const cwd = folder || void 0;
|
|
9910
|
-
const project = cwd ?
|
|
10055
|
+
const project = cwd ? path21.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
|
|
9911
10056
|
let json;
|
|
9912
10057
|
try {
|
|
9913
10058
|
const bytes = row.data_type === "zstd" ? decompress2(new Uint8Array(row.data)) : new Uint8Array(row.data);
|
|
@@ -10152,7 +10297,7 @@ async function parseZedSessionFile(dbPath, options) {
|
|
|
10152
10297
|
}
|
|
10153
10298
|
return events.filter((event) => matchesBackfillFilters(event, options));
|
|
10154
10299
|
}
|
|
10155
|
-
async function zedBackfillFiles(sourceRoot, home =
|
|
10300
|
+
async function zedBackfillFiles(sourceRoot, home = os10.homedir(), env) {
|
|
10156
10301
|
const { stat: stat14 } = await import("node:fs/promises");
|
|
10157
10302
|
if (sourceRoot) {
|
|
10158
10303
|
if (!sourceRoot.endsWith(".db")) {
|
|
@@ -10182,7 +10327,7 @@ function createZedAdapter() {
|
|
|
10182
10327
|
return zedConfigDir(home, env);
|
|
10183
10328
|
},
|
|
10184
10329
|
installedPath(home, env) {
|
|
10185
|
-
return
|
|
10330
|
+
return path21.join(zedConfigDir(home, env), "vibetime-marker");
|
|
10186
10331
|
},
|
|
10187
10332
|
async isInstalled() {
|
|
10188
10333
|
return false;
|
|
@@ -10641,15 +10786,15 @@ function hookCommandFromGroup(group) {
|
|
|
10641
10786
|
import { randomUUID } from "node:crypto";
|
|
10642
10787
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
10643
10788
|
import { homedir, hostname } from "node:os";
|
|
10644
|
-
import
|
|
10789
|
+
import path22 from "node:path";
|
|
10645
10790
|
function configDir(home = homedir()) {
|
|
10646
|
-
return
|
|
10791
|
+
return path22.join(home, ".vibetime");
|
|
10647
10792
|
}
|
|
10648
10793
|
function configPath(home = homedir()) {
|
|
10649
|
-
return
|
|
10794
|
+
return path22.join(configDir(home), "config.json");
|
|
10650
10795
|
}
|
|
10651
10796
|
function machineIdPath(home = homedir()) {
|
|
10652
|
-
return
|
|
10797
|
+
return path22.join(configDir(home), "machine-id");
|
|
10653
10798
|
}
|
|
10654
10799
|
function readConfig(home = homedir()) {
|
|
10655
10800
|
const file = configPath(home);
|
|
@@ -10698,13 +10843,13 @@ init_fs();
|
|
|
10698
10843
|
// src/lib/logger.ts
|
|
10699
10844
|
import { appendFile, mkdir as mkdir4, rename, stat as stat12 } from "node:fs/promises";
|
|
10700
10845
|
import { homedir as homedir2 } from "node:os";
|
|
10701
|
-
import
|
|
10846
|
+
import path23 from "node:path";
|
|
10702
10847
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
10703
10848
|
function logDir(home = homedir2()) {
|
|
10704
|
-
return
|
|
10849
|
+
return path23.join(home, ".vibetime", "logs");
|
|
10705
10850
|
}
|
|
10706
10851
|
function logPath(home = homedir2(), name = "cli.log") {
|
|
10707
|
-
return
|
|
10852
|
+
return path23.join(logDir(home), name);
|
|
10708
10853
|
}
|
|
10709
10854
|
function serializeError(error) {
|
|
10710
10855
|
if (error instanceof Error) {
|
|
@@ -10879,8 +11024,8 @@ function buildHeaders(token, machine) {
|
|
|
10879
11024
|
...machine?.platform ? { "x-machine-platform": machine.platform } : {}
|
|
10880
11025
|
};
|
|
10881
11026
|
}
|
|
10882
|
-
function joinUrl(base,
|
|
10883
|
-
return new URL(
|
|
11027
|
+
function joinUrl(base, path25) {
|
|
11028
|
+
return new URL(path25, base.endsWith("/") ? base : `${base}/`).toString();
|
|
10884
11029
|
}
|
|
10885
11030
|
async function postRollupBatch(remote, rollups, options = {}) {
|
|
10886
11031
|
const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
|
|
@@ -11799,13 +11944,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
|
|
|
11799
11944
|
});
|
|
11800
11945
|
}
|
|
11801
11946
|
function backfillIncrementalStatePath(home) {
|
|
11802
|
-
return
|
|
11947
|
+
return path24.join(home, ".vibetime", "backfill-state.json");
|
|
11803
11948
|
}
|
|
11804
11949
|
function syncLocalTriggerStatePath(home) {
|
|
11805
|
-
return
|
|
11950
|
+
return path24.join(home, ".vibetime", "sync-local-trigger.json");
|
|
11806
11951
|
}
|
|
11807
11952
|
function syncLocalTriggerLockPath(home) {
|
|
11808
|
-
return
|
|
11953
|
+
return path24.join(home, ".vibetime", "sync-local-trigger.lock");
|
|
11809
11954
|
}
|
|
11810
11955
|
function backfillRemoteKey(baseUrl) {
|
|
11811
11956
|
try {
|
|
@@ -11867,7 +12012,7 @@ async function readBackfillIncrementalStateFile(home, ctx) {
|
|
|
11867
12012
|
}
|
|
11868
12013
|
async function writeBackfillIncrementalStateFile(home, file) {
|
|
11869
12014
|
const statePath = backfillIncrementalStatePath(home);
|
|
11870
|
-
await mkdir5(
|
|
12015
|
+
await mkdir5(path24.dirname(statePath), { recursive: true });
|
|
11871
12016
|
await writeFile4(statePath, `${JSON.stringify(file, null, 2)}
|
|
11872
12017
|
`, "utf8");
|
|
11873
12018
|
}
|
|
@@ -11916,7 +12061,7 @@ async function readSyncLocalTriggerState(statePath) {
|
|
|
11916
12061
|
return nextState;
|
|
11917
12062
|
}
|
|
11918
12063
|
async function writeSyncLocalTriggerState(statePath, state) {
|
|
11919
|
-
await mkdir5(
|
|
12064
|
+
await mkdir5(path24.dirname(statePath), { recursive: true });
|
|
11920
12065
|
await writeFile4(statePath, `${JSON.stringify(state, null, 2)}
|
|
11921
12066
|
`, "utf8");
|
|
11922
12067
|
}
|
|
@@ -11931,12 +12076,12 @@ async function readSyncLocalLock(lockPath) {
|
|
|
11931
12076
|
return { pid: lock.pid, startedAt: lock.startedAt };
|
|
11932
12077
|
}
|
|
11933
12078
|
async function writeSyncLocalLock(lockPath, lock) {
|
|
11934
|
-
await mkdir5(
|
|
12079
|
+
await mkdir5(path24.dirname(lockPath), { recursive: true });
|
|
11935
12080
|
await writeFile4(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
11936
12081
|
`, "utf8");
|
|
11937
12082
|
}
|
|
11938
12083
|
async function acquireSyncLocalLock(lockPath, lock) {
|
|
11939
|
-
await mkdir5(
|
|
12084
|
+
await mkdir5(path24.dirname(lockPath), { recursive: true });
|
|
11940
12085
|
try {
|
|
11941
12086
|
const handle = await open(lockPath, "wx");
|
|
11942
12087
|
try {
|
|
@@ -12016,10 +12161,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
|
|
|
12016
12161
|
if (cliPath.endsWith(".ts")) {
|
|
12017
12162
|
return ["--import", "tsx", cliPath];
|
|
12018
12163
|
}
|
|
12019
|
-
return [
|
|
12164
|
+
return [path24.resolve(path24.dirname(cliPath), "../bin/vibetime.mjs")];
|
|
12020
12165
|
}
|
|
12021
12166
|
function resolveHome3(options, ctx) {
|
|
12022
|
-
return
|
|
12167
|
+
return path24.resolve(stringOption(options.home) || ctx.env.HOME || os11.homedir());
|
|
12023
12168
|
}
|
|
12024
12169
|
function requestedTargets(options) {
|
|
12025
12170
|
const value = options.target || options.targets;
|
package/package.json
CHANGED