@yhong91/vibetime 0.1.31 → 0.1.33
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 +295 -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.33" : "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,115 @@ 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 preferredModel = resolveSessionPreferredModel(db, sessionId, modelMap);
|
|
7476
|
+
const rows = db.prepare(
|
|
7477
|
+
`select request_id, token_info, model_info from chat_message where session_id = ? and role = 'assistant' and token_info != '' order by gmt_create asc`
|
|
7478
|
+
).all(sessionId);
|
|
7479
|
+
for (const row of rows) {
|
|
7480
|
+
const usage = parseJsonLine(stringField(row, "token_info") || "") || {};
|
|
7481
|
+
const modelInfo = parseJsonLine(stringField(row, "model_info") || "") || {};
|
|
7482
|
+
const modelKey = stringField(modelInfo, "model_key");
|
|
7483
|
+
const call = {
|
|
7484
|
+
model: modelKey ? modelMap[modelKey] || modelKey : preferredModel,
|
|
7485
|
+
inputTokens: numberField(usage, "prompt_tokens") || 0,
|
|
7486
|
+
outputTokens: numberField(usage, "completion_tokens") || 0,
|
|
7487
|
+
cachedTokens: numberField(usage, "cached_tokens") || 0
|
|
7488
|
+
};
|
|
7489
|
+
calls.ordered.push(call);
|
|
7490
|
+
const requestId = stringField(row, "request_id");
|
|
7491
|
+
if (!requestId) {
|
|
7492
|
+
continue;
|
|
7493
|
+
}
|
|
7494
|
+
const queue = calls.byRequestId.get(requestId);
|
|
7495
|
+
if (queue) {
|
|
7496
|
+
queue.push(call);
|
|
7497
|
+
} else {
|
|
7498
|
+
calls.byRequestId.set(requestId, [call]);
|
|
7499
|
+
}
|
|
7500
|
+
}
|
|
7501
|
+
} finally {
|
|
7502
|
+
db.close();
|
|
7503
|
+
}
|
|
7504
|
+
} catch {
|
|
7505
|
+
}
|
|
7506
|
+
return calls;
|
|
7507
|
+
}
|
|
7508
|
+
function resolveSessionPreferredModel(db, sessionId, modelMap) {
|
|
7509
|
+
let current = sessionId;
|
|
7510
|
+
for (let depth = 0; depth < 5 && current; depth++) {
|
|
7511
|
+
let row;
|
|
7512
|
+
try {
|
|
7513
|
+
row = db.prepare(
|
|
7514
|
+
"select preferred_model_info, parent_session_id from chat_session where session_id = ?"
|
|
7515
|
+
).get(current);
|
|
7516
|
+
} catch {
|
|
7517
|
+
return void 0;
|
|
7518
|
+
}
|
|
7519
|
+
if (!row) {
|
|
7520
|
+
return void 0;
|
|
7521
|
+
}
|
|
7522
|
+
const info = parseJsonLine(stringField(row, "preferred_model_info") || "") || {};
|
|
7523
|
+
const preferred = stringField(info, "preferred_model");
|
|
7524
|
+
if (preferred) {
|
|
7525
|
+
return modelMap[preferred] || preferred;
|
|
7526
|
+
}
|
|
7527
|
+
current = stringField(row, "parent_session_id");
|
|
7528
|
+
}
|
|
7529
|
+
return void 0;
|
|
7530
|
+
}
|
|
7531
|
+
|
|
7532
|
+
// src/adapters/qoder-cn.ts
|
|
7533
|
+
import { readdir as readdir7, readFile as readFile10, stat as stat8 } from "node:fs/promises";
|
|
7534
|
+
import os8 from "node:os";
|
|
7535
|
+
import path17 from "node:path";
|
|
7433
7536
|
function parseQoderCnPaths(filePath) {
|
|
7434
|
-
const parts = filePath.split(
|
|
7537
|
+
const parts = filePath.split(path17.sep);
|
|
7435
7538
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
7436
7539
|
let sessionId = "";
|
|
7437
7540
|
let projectName = "";
|
|
@@ -7441,14 +7544,17 @@ function parseQoderCnPaths(filePath) {
|
|
|
7441
7544
|
sessionId = parts[subagentsIdx - 1];
|
|
7442
7545
|
projectName = parts[subagentsIdx - 2];
|
|
7443
7546
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
7444
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
7445
|
-
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(
|
|
7547
|
+
configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
|
|
7548
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path17.sep);
|
|
7446
7549
|
} else {
|
|
7447
7550
|
const filename = parts.at(-1) || "";
|
|
7448
|
-
sessionId =
|
|
7551
|
+
sessionId = path17.basename(filename, ".jsonl");
|
|
7449
7552
|
projectName = parts.at(-2) || "";
|
|
7553
|
+
if (projectName === "transcript") {
|
|
7554
|
+
projectName = parts.at(-3) || "";
|
|
7555
|
+
}
|
|
7450
7556
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
7451
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
7557
|
+
configDir2 = parts.slice(0, projectsIdx).join(path17.sep);
|
|
7452
7558
|
}
|
|
7453
7559
|
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
7454
7560
|
}
|
|
@@ -7471,7 +7577,7 @@ function rebuildEventIdentity2(event) {
|
|
|
7471
7577
|
}
|
|
7472
7578
|
async function loadQoderCnModelNames(configDir2) {
|
|
7473
7579
|
try {
|
|
7474
|
-
const dynamicTextsPath =
|
|
7580
|
+
const dynamicTextsPath = path17.join(configDir2, ".auth", "dynamic-texts.json");
|
|
7475
7581
|
const content = await readFile10(dynamicTextsPath, "utf8");
|
|
7476
7582
|
const json = JSON.parse(content);
|
|
7477
7583
|
const texts = json.texts || {};
|
|
@@ -7489,7 +7595,7 @@ async function loadQoderCnModelNames(configDir2) {
|
|
|
7489
7595
|
}
|
|
7490
7596
|
async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
7491
7597
|
const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
|
|
7492
|
-
const segmentsPath =
|
|
7598
|
+
const segmentsPath = path17.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
7493
7599
|
const modelCalls = [];
|
|
7494
7600
|
try {
|
|
7495
7601
|
const files = await readdir7(segmentsPath);
|
|
@@ -7497,7 +7603,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
|
|
|
7497
7603
|
if (!file.endsWith(".jsonl")) {
|
|
7498
7604
|
continue;
|
|
7499
7605
|
}
|
|
7500
|
-
const content = await readFile10(
|
|
7606
|
+
const content = await readFile10(path17.join(segmentsPath, file), "utf8");
|
|
7501
7607
|
let currentTurnIsSubagent = false;
|
|
7502
7608
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
7503
7609
|
const raw = parseJsonLine(line);
|
|
@@ -7544,6 +7650,17 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7544
7650
|
const isSubagentSession = filePath.includes("subagents");
|
|
7545
7651
|
const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
7546
7652
|
let modelCallIndex = 0;
|
|
7653
|
+
let dbModelCalls;
|
|
7654
|
+
const nextDbModelCall = async (requestId, blockStart) => {
|
|
7655
|
+
dbModelCalls ??= await loadQoderDbModelCalls("QoderCN", sessionId, modelMap);
|
|
7656
|
+
if (requestId) {
|
|
7657
|
+
return dbModelCalls.byRequestId.get(requestId)?.shift();
|
|
7658
|
+
}
|
|
7659
|
+
if (!blockStart) {
|
|
7660
|
+
return void 0;
|
|
7661
|
+
}
|
|
7662
|
+
return dbModelCalls.ordered.shift();
|
|
7663
|
+
};
|
|
7547
7664
|
const state = new SessionParserState(filePath, options, (event) => baseQoderCnEvent({ ...event, cwd, project, model }));
|
|
7548
7665
|
state.sessionId = sessionId;
|
|
7549
7666
|
const push = (event, ln, topType, payloadType) => {
|
|
@@ -7554,6 +7671,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7554
7671
|
payloadType
|
|
7555
7672
|
);
|
|
7556
7673
|
};
|
|
7674
|
+
let assistantBlockOpen = false;
|
|
7557
7675
|
for (const [index, line] of lines.entries()) {
|
|
7558
7676
|
const lineNumber = index + 1;
|
|
7559
7677
|
const raw = parseJsonLine(line);
|
|
@@ -7561,11 +7679,14 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7561
7679
|
continue;
|
|
7562
7680
|
}
|
|
7563
7681
|
const topType = stringField(raw, "type");
|
|
7682
|
+
if (topType !== "assistant") {
|
|
7683
|
+
assistantBlockOpen = false;
|
|
7684
|
+
}
|
|
7564
7685
|
const ts = timestampFrom(raw.timestamp);
|
|
7565
7686
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
7566
7687
|
state.sessionId = sessionId;
|
|
7567
7688
|
cwd = stringField(raw, "cwd") || cwd;
|
|
7568
|
-
project = projectContext.project || (cwd ?
|
|
7689
|
+
project = projectContext.project || (cwd ? path17.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
|
|
7569
7690
|
if (!ts) {
|
|
7570
7691
|
continue;
|
|
7571
7692
|
}
|
|
@@ -7698,6 +7819,8 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7698
7819
|
model = rawModel ? modelMap[rawModel] || rawModel : void 0;
|
|
7699
7820
|
const messageId = stringField(message, "id");
|
|
7700
7821
|
const requestId = stringField(raw, "requestId");
|
|
7822
|
+
const isBlockStart = !assistantBlockOpen;
|
|
7823
|
+
assistantBlockOpen = true;
|
|
7701
7824
|
const usageKey = messageId ? `${messageId}:${requestId}` : null;
|
|
7702
7825
|
const shouldEmitUsage = usageKey == null || !seenUsageKeys.has(usageKey);
|
|
7703
7826
|
if (usageKey != null) {
|
|
@@ -7722,6 +7845,19 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
7722
7845
|
modelCalls: 1
|
|
7723
7846
|
};
|
|
7724
7847
|
model = call.model || model;
|
|
7848
|
+
} else if (shouldEmitUsage) {
|
|
7849
|
+
const dbCall = await nextDbModelCall(requestId, isBlockStart);
|
|
7850
|
+
if (dbCall) {
|
|
7851
|
+
usage = {
|
|
7852
|
+
tokensInput: dbCall.inputTokens || void 0,
|
|
7853
|
+
tokensCachedInput: dbCall.cachedTokens || void 0,
|
|
7854
|
+
tokensCacheReadInput: dbCall.cachedTokens || void 0,
|
|
7855
|
+
tokensOutput: dbCall.outputTokens || void 0,
|
|
7856
|
+
tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
|
|
7857
|
+
modelCalls: 1
|
|
7858
|
+
};
|
|
7859
|
+
model = dbCall.model || model;
|
|
7860
|
+
}
|
|
7725
7861
|
}
|
|
7726
7862
|
if (usage) {
|
|
7727
7863
|
const speed = stringField(objectField(message, "usage"), "speed");
|
|
@@ -8002,28 +8138,28 @@ function isNoisePrompt(text) {
|
|
|
8002
8138
|
}
|
|
8003
8139
|
async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
8004
8140
|
const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
|
|
8005
|
-
const isSubagent = filePath.includes(`${
|
|
8141
|
+
const isSubagent = filePath.includes(`${path17.sep}subagents${path17.sep}`);
|
|
8006
8142
|
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
8007
8143
|
let cwds = [];
|
|
8008
8144
|
for (const line of lines) {
|
|
8009
8145
|
const raw = parseJsonLine(line);
|
|
8010
8146
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8011
|
-
if (cwd &&
|
|
8147
|
+
if (cwd && path17.isAbsolute(cwd)) {
|
|
8012
8148
|
cwds.push(cwd);
|
|
8013
8149
|
}
|
|
8014
8150
|
}
|
|
8015
8151
|
if (isSubagent) {
|
|
8016
|
-
if (inherited?.cwd &&
|
|
8152
|
+
if (inherited?.cwd && path17.isAbsolute(inherited.cwd)) {
|
|
8017
8153
|
cwds = [inherited.cwd];
|
|
8018
8154
|
} else {
|
|
8019
|
-
const parentSessionPath =
|
|
8155
|
+
const parentSessionPath = path17.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
8020
8156
|
try {
|
|
8021
8157
|
const parentText = await readFile10(parentSessionPath, "utf8");
|
|
8022
8158
|
const parentCwds = [];
|
|
8023
8159
|
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
8024
8160
|
const raw = parseJsonLine(line);
|
|
8025
8161
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8026
|
-
if (cwd &&
|
|
8162
|
+
if (cwd && path17.isAbsolute(cwd)) {
|
|
8027
8163
|
parentCwds.push(cwd);
|
|
8028
8164
|
}
|
|
8029
8165
|
}
|
|
@@ -8035,7 +8171,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
8035
8171
|
}
|
|
8036
8172
|
}
|
|
8037
8173
|
const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
|
|
8038
|
-
const project = inherited?.project || (cwds.length > 0 ?
|
|
8174
|
+
const project = inherited?.project || (cwds.length > 0 ? path17.basename(cwds[0]) : root ? path17.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
|
|
8039
8175
|
return {
|
|
8040
8176
|
project,
|
|
8041
8177
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -8044,15 +8180,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
8044
8180
|
async function gitRootFromCwds2(cwds) {
|
|
8045
8181
|
const seen = /* @__PURE__ */ new Set();
|
|
8046
8182
|
for (const cwd of cwds) {
|
|
8047
|
-
let current =
|
|
8183
|
+
let current = path17.resolve(cwd);
|
|
8048
8184
|
while (!seen.has(current)) {
|
|
8049
8185
|
seen.add(current);
|
|
8050
8186
|
try {
|
|
8051
|
-
await stat8(
|
|
8187
|
+
await stat8(path17.join(current, ".git"));
|
|
8052
8188
|
return current;
|
|
8053
8189
|
} catch {
|
|
8054
8190
|
}
|
|
8055
|
-
const parent =
|
|
8191
|
+
const parent = path17.dirname(current);
|
|
8056
8192
|
if (parent === current) {
|
|
8057
8193
|
break;
|
|
8058
8194
|
}
|
|
@@ -8063,12 +8199,12 @@ async function gitRootFromCwds2(cwds) {
|
|
|
8063
8199
|
}
|
|
8064
8200
|
function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
8065
8201
|
for (const cwd of cwds) {
|
|
8066
|
-
let current =
|
|
8202
|
+
let current = path17.resolve(cwd);
|
|
8067
8203
|
while (true) {
|
|
8068
8204
|
if (encodeQoderCnProjectPath(current) === projectDir) {
|
|
8069
8205
|
return current;
|
|
8070
8206
|
}
|
|
8071
|
-
const parent =
|
|
8207
|
+
const parent = path17.dirname(current);
|
|
8072
8208
|
if (parent === current) {
|
|
8073
8209
|
break;
|
|
8074
8210
|
}
|
|
@@ -8078,14 +8214,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
|
8078
8214
|
return void 0;
|
|
8079
8215
|
}
|
|
8080
8216
|
function encodeQoderCnProjectPath(value) {
|
|
8081
|
-
return
|
|
8217
|
+
return path17.resolve(value).split(path17.sep).join("-").replace(/_/g, "-");
|
|
8082
8218
|
}
|
|
8083
8219
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
8084
|
-
const projectDir =
|
|
8085
|
-
const home = options ?
|
|
8220
|
+
const projectDir = path17.basename(path17.dirname(filePath));
|
|
8221
|
+
const home = options ? path17.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
|
|
8086
8222
|
const resolved = await resolveQoderCnProjectPath(projectDir, home);
|
|
8087
8223
|
if (resolved) {
|
|
8088
|
-
return
|
|
8224
|
+
return path17.basename(resolved);
|
|
8089
8225
|
}
|
|
8090
8226
|
const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
|
|
8091
8227
|
if (projectDir.startsWith(homePrefix)) {
|
|
@@ -8110,7 +8246,7 @@ async function resolveQoderCnProjectPath(projectDir, home) {
|
|
|
8110
8246
|
if (!entry.isDirectory()) {
|
|
8111
8247
|
continue;
|
|
8112
8248
|
}
|
|
8113
|
-
const candidate =
|
|
8249
|
+
const candidate = path17.join(current, entry.name);
|
|
8114
8250
|
const encoded = encodeQoderCnProjectPath(candidate);
|
|
8115
8251
|
if (encoded === projectDir) {
|
|
8116
8252
|
return candidate;
|
|
@@ -8155,9 +8291,9 @@ function hookConfig6() {
|
|
|
8155
8291
|
function qoderCnConfigDir(home, env) {
|
|
8156
8292
|
const override = env?.QODER_CN_CONFIG_DIR;
|
|
8157
8293
|
if (override && override.trim()) {
|
|
8158
|
-
return
|
|
8294
|
+
return path17.resolve(override);
|
|
8159
8295
|
}
|
|
8160
|
-
return
|
|
8296
|
+
return path17.join(home, ".qoder-cn");
|
|
8161
8297
|
}
|
|
8162
8298
|
function createQoderCnAdapter() {
|
|
8163
8299
|
return {
|
|
@@ -8169,27 +8305,27 @@ function createQoderCnAdapter() {
|
|
|
8169
8305
|
return qoderCnConfigDir(home, env);
|
|
8170
8306
|
},
|
|
8171
8307
|
installedPath(home, env) {
|
|
8172
|
-
return
|
|
8308
|
+
return path17.join(qoderCnConfigDir(home, env), "settings.json");
|
|
8173
8309
|
},
|
|
8174
8310
|
async isInstalled(home, env) {
|
|
8175
8311
|
return isHooksJsonInstalled(
|
|
8176
|
-
|
|
8312
|
+
path17.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
8177
8313
|
"vibetime hook --agent qoder-cn"
|
|
8178
8314
|
);
|
|
8179
8315
|
},
|
|
8180
8316
|
installEntries(home, env) {
|
|
8181
8317
|
return [{
|
|
8182
8318
|
kind: "hooks-json",
|
|
8183
|
-
path:
|
|
8319
|
+
path: path17.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
8184
8320
|
content: hookConfig6()
|
|
8185
8321
|
}];
|
|
8186
8322
|
},
|
|
8187
8323
|
sourcePaths(home, env) {
|
|
8188
8324
|
const base = qoderCnConfigDir(home, env);
|
|
8189
8325
|
return [
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8326
|
+
path17.join(base, "projects"),
|
|
8327
|
+
path17.join(base, ".qoder.json"),
|
|
8328
|
+
path17.join(home, ".qoder.json")
|
|
8193
8329
|
];
|
|
8194
8330
|
},
|
|
8195
8331
|
parseSessionFile: parseQoderCnSessionFile
|
|
@@ -8198,10 +8334,10 @@ function createQoderCnAdapter() {
|
|
|
8198
8334
|
|
|
8199
8335
|
// src/adapters/qoder.ts
|
|
8200
8336
|
import { readdir as readdir8, readFile as readFile11, stat as stat9 } from "node:fs/promises";
|
|
8201
|
-
import
|
|
8202
|
-
import
|
|
8337
|
+
import os9 from "node:os";
|
|
8338
|
+
import path18 from "node:path";
|
|
8203
8339
|
function parseQoderPaths(filePath) {
|
|
8204
|
-
const parts = filePath.split(
|
|
8340
|
+
const parts = filePath.split(path18.sep);
|
|
8205
8341
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
8206
8342
|
let sessionId = "";
|
|
8207
8343
|
let projectName = "";
|
|
@@ -8211,14 +8347,17 @@ function parseQoderPaths(filePath) {
|
|
|
8211
8347
|
sessionId = parts[subagentsIdx - 1];
|
|
8212
8348
|
projectName = parts[subagentsIdx - 2];
|
|
8213
8349
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8214
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
8215
|
-
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(
|
|
8350
|
+
configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
|
|
8351
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path18.sep);
|
|
8216
8352
|
} else {
|
|
8217
8353
|
const filename = parts.at(-1) || "";
|
|
8218
|
-
sessionId =
|
|
8354
|
+
sessionId = path18.basename(filename, ".jsonl");
|
|
8219
8355
|
projectName = parts.at(-2) || "";
|
|
8356
|
+
if (projectName === "transcript") {
|
|
8357
|
+
projectName = parts.at(-3) || "";
|
|
8358
|
+
}
|
|
8220
8359
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8221
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
8360
|
+
configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
|
|
8222
8361
|
}
|
|
8223
8362
|
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
8224
8363
|
}
|
|
@@ -8241,7 +8380,7 @@ function rebuildEventIdentity3(event) {
|
|
|
8241
8380
|
}
|
|
8242
8381
|
async function loadQoderModelNames(configDir2) {
|
|
8243
8382
|
try {
|
|
8244
|
-
const dynamicTextsPath =
|
|
8383
|
+
const dynamicTextsPath = path18.join(configDir2, ".auth", "dynamic-texts.json");
|
|
8245
8384
|
const content = await readFile11(dynamicTextsPath, "utf8");
|
|
8246
8385
|
const json = JSON.parse(content);
|
|
8247
8386
|
const texts = json.texts || {};
|
|
@@ -8259,7 +8398,7 @@ async function loadQoderModelNames(configDir2) {
|
|
|
8259
8398
|
}
|
|
8260
8399
|
async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
8261
8400
|
const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
|
|
8262
|
-
const segmentsPath =
|
|
8401
|
+
const segmentsPath = path18.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
8263
8402
|
const modelCalls = [];
|
|
8264
8403
|
try {
|
|
8265
8404
|
const files = await readdir8(segmentsPath);
|
|
@@ -8267,7 +8406,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
|
|
|
8267
8406
|
if (!file.endsWith(".jsonl")) {
|
|
8268
8407
|
continue;
|
|
8269
8408
|
}
|
|
8270
|
-
const content = await readFile11(
|
|
8409
|
+
const content = await readFile11(path18.join(segmentsPath, file), "utf8");
|
|
8271
8410
|
let currentTurnIsSubagent = false;
|
|
8272
8411
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
8273
8412
|
const raw = parseJsonLine(line);
|
|
@@ -8314,6 +8453,17 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8314
8453
|
const isSubagentSession = filePath.includes("subagents");
|
|
8315
8454
|
const segmentModelCalls = await loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
8316
8455
|
let modelCallIndex = 0;
|
|
8456
|
+
let dbModelCalls;
|
|
8457
|
+
const nextDbModelCall = async (requestId, blockStart) => {
|
|
8458
|
+
dbModelCalls ??= await loadQoderDbModelCalls("Qoder", sessionId, modelMap);
|
|
8459
|
+
if (requestId) {
|
|
8460
|
+
return dbModelCalls.byRequestId.get(requestId)?.shift();
|
|
8461
|
+
}
|
|
8462
|
+
if (!blockStart) {
|
|
8463
|
+
return void 0;
|
|
8464
|
+
}
|
|
8465
|
+
return dbModelCalls.ordered.shift();
|
|
8466
|
+
};
|
|
8317
8467
|
const state = new SessionParserState(filePath, options, (event) => baseQoderEvent({ ...event, cwd, project, model }));
|
|
8318
8468
|
state.sessionId = sessionId;
|
|
8319
8469
|
const push = (event, ln, topType, payloadType) => {
|
|
@@ -8324,6 +8474,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8324
8474
|
payloadType
|
|
8325
8475
|
);
|
|
8326
8476
|
};
|
|
8477
|
+
let assistantBlockOpen = false;
|
|
8327
8478
|
for (const [index, line] of lines.entries()) {
|
|
8328
8479
|
const lineNumber = index + 1;
|
|
8329
8480
|
const raw = parseJsonLine(line);
|
|
@@ -8331,11 +8482,14 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8331
8482
|
continue;
|
|
8332
8483
|
}
|
|
8333
8484
|
const topType = stringField(raw, "type");
|
|
8485
|
+
if (topType !== "assistant") {
|
|
8486
|
+
assistantBlockOpen = false;
|
|
8487
|
+
}
|
|
8334
8488
|
const ts = timestampFrom(raw.timestamp);
|
|
8335
8489
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
8336
8490
|
state.sessionId = sessionId;
|
|
8337
8491
|
cwd = stringField(raw, "cwd") || cwd;
|
|
8338
|
-
project = projectContext.project || (cwd ?
|
|
8492
|
+
project = projectContext.project || (cwd ? path18.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
|
|
8339
8493
|
if (!ts) {
|
|
8340
8494
|
continue;
|
|
8341
8495
|
}
|
|
@@ -8468,6 +8622,8 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8468
8622
|
model = rawModel ? modelMap[rawModel] || rawModel : void 0;
|
|
8469
8623
|
const messageId = stringField(message, "id");
|
|
8470
8624
|
const requestId = stringField(raw, "requestId");
|
|
8625
|
+
const isBlockStart = !assistantBlockOpen;
|
|
8626
|
+
assistantBlockOpen = true;
|
|
8471
8627
|
const usageKey = messageId ? `${messageId}:${requestId}` : null;
|
|
8472
8628
|
const shouldEmitUsage = usageKey == null || !seenUsageKeys.has(usageKey);
|
|
8473
8629
|
if (usageKey != null) {
|
|
@@ -8492,6 +8648,19 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8492
8648
|
modelCalls: 1
|
|
8493
8649
|
};
|
|
8494
8650
|
model = call.model || model;
|
|
8651
|
+
} else if (shouldEmitUsage) {
|
|
8652
|
+
const dbCall = await nextDbModelCall(requestId, isBlockStart);
|
|
8653
|
+
if (dbCall) {
|
|
8654
|
+
usage = {
|
|
8655
|
+
tokensInput: dbCall.inputTokens || void 0,
|
|
8656
|
+
tokensCachedInput: dbCall.cachedTokens || void 0,
|
|
8657
|
+
tokensCacheReadInput: dbCall.cachedTokens || void 0,
|
|
8658
|
+
tokensOutput: dbCall.outputTokens || void 0,
|
|
8659
|
+
tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
|
|
8660
|
+
modelCalls: 1
|
|
8661
|
+
};
|
|
8662
|
+
model = dbCall.model || model;
|
|
8663
|
+
}
|
|
8495
8664
|
}
|
|
8496
8665
|
if (usage) {
|
|
8497
8666
|
const speed = stringField(objectField(message, "usage"), "speed");
|
|
@@ -8738,28 +8907,28 @@ function qoderExtractText(value) {
|
|
|
8738
8907
|
}
|
|
8739
8908
|
async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
8740
8909
|
const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
|
|
8741
|
-
const isSubagent = filePath.includes(`${
|
|
8910
|
+
const isSubagent = filePath.includes(`${path18.sep}subagents${path18.sep}`);
|
|
8742
8911
|
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
8743
8912
|
let cwds = [];
|
|
8744
8913
|
for (const line of lines) {
|
|
8745
8914
|
const raw = parseJsonLine(line);
|
|
8746
8915
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8747
|
-
if (cwd &&
|
|
8916
|
+
if (cwd && path18.isAbsolute(cwd)) {
|
|
8748
8917
|
cwds.push(cwd);
|
|
8749
8918
|
}
|
|
8750
8919
|
}
|
|
8751
8920
|
if (isSubagent) {
|
|
8752
|
-
if (inherited?.cwd &&
|
|
8921
|
+
if (inherited?.cwd && path18.isAbsolute(inherited.cwd)) {
|
|
8753
8922
|
cwds = [inherited.cwd];
|
|
8754
8923
|
} else {
|
|
8755
|
-
const parentSessionPath =
|
|
8924
|
+
const parentSessionPath = path18.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
8756
8925
|
try {
|
|
8757
8926
|
const parentText = await readFile11(parentSessionPath, "utf8");
|
|
8758
8927
|
const parentCwds = [];
|
|
8759
8928
|
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
8760
8929
|
const raw = parseJsonLine(line);
|
|
8761
8930
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8762
|
-
if (cwd &&
|
|
8931
|
+
if (cwd && path18.isAbsolute(cwd)) {
|
|
8763
8932
|
parentCwds.push(cwd);
|
|
8764
8933
|
}
|
|
8765
8934
|
}
|
|
@@ -8771,7 +8940,7 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
8771
8940
|
}
|
|
8772
8941
|
}
|
|
8773
8942
|
const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
|
|
8774
|
-
const project = inherited?.project || (cwds.length > 0 ?
|
|
8943
|
+
const project = inherited?.project || (cwds.length > 0 ? path18.basename(cwds[0]) : root ? path18.basename(root) : await qoderProjectFromFilePath(filePath, options));
|
|
8775
8944
|
return {
|
|
8776
8945
|
project,
|
|
8777
8946
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -8780,15 +8949,15 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
8780
8949
|
async function gitRootFromCwds3(cwds) {
|
|
8781
8950
|
const seen = /* @__PURE__ */ new Set();
|
|
8782
8951
|
for (const cwd of cwds) {
|
|
8783
|
-
let current =
|
|
8952
|
+
let current = path18.resolve(cwd);
|
|
8784
8953
|
while (!seen.has(current)) {
|
|
8785
8954
|
seen.add(current);
|
|
8786
8955
|
try {
|
|
8787
|
-
await stat9(
|
|
8956
|
+
await stat9(path18.join(current, ".git"));
|
|
8788
8957
|
return current;
|
|
8789
8958
|
} catch {
|
|
8790
8959
|
}
|
|
8791
|
-
const parent =
|
|
8960
|
+
const parent = path18.dirname(current);
|
|
8792
8961
|
if (parent === current) {
|
|
8793
8962
|
break;
|
|
8794
8963
|
}
|
|
@@ -8799,12 +8968,12 @@ async function gitRootFromCwds3(cwds) {
|
|
|
8799
8968
|
}
|
|
8800
8969
|
function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
8801
8970
|
for (const cwd of cwds) {
|
|
8802
|
-
let current =
|
|
8971
|
+
let current = path18.resolve(cwd);
|
|
8803
8972
|
while (true) {
|
|
8804
8973
|
if (encodeQoderProjectPath(current) === projectDir) {
|
|
8805
8974
|
return current;
|
|
8806
8975
|
}
|
|
8807
|
-
const parent =
|
|
8976
|
+
const parent = path18.dirname(current);
|
|
8808
8977
|
if (parent === current) {
|
|
8809
8978
|
break;
|
|
8810
8979
|
}
|
|
@@ -8814,10 +8983,10 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
|
8814
8983
|
return void 0;
|
|
8815
8984
|
}
|
|
8816
8985
|
function encodeQoderProjectPath(value) {
|
|
8817
|
-
return
|
|
8986
|
+
return path18.resolve(value).split(path18.sep).join("-").replace(/_/g, "-");
|
|
8818
8987
|
}
|
|
8819
8988
|
function rawQoderProjectPath(value) {
|
|
8820
|
-
return
|
|
8989
|
+
return path18.resolve(value).split(path18.sep).join("-");
|
|
8821
8990
|
}
|
|
8822
8991
|
function qoderEncodedVariants(value) {
|
|
8823
8992
|
const raw = rawQoderProjectPath(value);
|
|
@@ -8833,11 +9002,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
|
|
|
8833
9002
|
return void 0;
|
|
8834
9003
|
}
|
|
8835
9004
|
async function qoderProjectFromFilePath(filePath, options) {
|
|
8836
|
-
const projectDir =
|
|
8837
|
-
const home = options ?
|
|
9005
|
+
const projectDir = path18.basename(path18.dirname(filePath));
|
|
9006
|
+
const home = options ? path18.resolve(stringOption(options.home) || os9.homedir()) : os9.homedir();
|
|
8838
9007
|
const resolved = await resolveQoderProjectPath(projectDir, home);
|
|
8839
9008
|
if (resolved) {
|
|
8840
|
-
return
|
|
9009
|
+
return path18.basename(resolved);
|
|
8841
9010
|
}
|
|
8842
9011
|
const suffix = qoderEncodedProjectSuffix(projectDir, home);
|
|
8843
9012
|
if (suffix) {
|
|
@@ -8863,7 +9032,7 @@ async function resolveQoderProjectPath(projectDir, home) {
|
|
|
8863
9032
|
if (!entry.isDirectory()) {
|
|
8864
9033
|
continue;
|
|
8865
9034
|
}
|
|
8866
|
-
const candidate =
|
|
9035
|
+
const candidate = path18.join(current, entry.name);
|
|
8867
9036
|
const candidateVariants = qoderEncodedVariants(candidate);
|
|
8868
9037
|
if (candidateVariants.includes(projectDir)) {
|
|
8869
9038
|
return candidate;
|
|
@@ -8908,9 +9077,9 @@ function hookConfig7() {
|
|
|
8908
9077
|
function qoderConfigDir(home, env) {
|
|
8909
9078
|
const override = env?.QODER_CONFIG_DIR;
|
|
8910
9079
|
if (override && override.trim()) {
|
|
8911
|
-
return
|
|
9080
|
+
return path18.resolve(override);
|
|
8912
9081
|
}
|
|
8913
|
-
return
|
|
9082
|
+
return path18.join(home, ".qoder");
|
|
8914
9083
|
}
|
|
8915
9084
|
function createQoderAdapter() {
|
|
8916
9085
|
return {
|
|
@@ -8922,27 +9091,27 @@ function createQoderAdapter() {
|
|
|
8922
9091
|
return qoderConfigDir(home, env);
|
|
8923
9092
|
},
|
|
8924
9093
|
installedPath(home, env) {
|
|
8925
|
-
return
|
|
9094
|
+
return path18.join(qoderConfigDir(home, env), "settings.json");
|
|
8926
9095
|
},
|
|
8927
9096
|
async isInstalled(home, env) {
|
|
8928
9097
|
return isHooksJsonInstalled(
|
|
8929
|
-
|
|
9098
|
+
path18.join(qoderConfigDir(home, env), "settings.json"),
|
|
8930
9099
|
"vibetime hook --agent qoder"
|
|
8931
9100
|
);
|
|
8932
9101
|
},
|
|
8933
9102
|
installEntries(home, env) {
|
|
8934
9103
|
return [{
|
|
8935
9104
|
kind: "hooks-json",
|
|
8936
|
-
path:
|
|
9105
|
+
path: path18.join(qoderConfigDir(home, env), "settings.json"),
|
|
8937
9106
|
content: hookConfig7()
|
|
8938
9107
|
}];
|
|
8939
9108
|
},
|
|
8940
9109
|
sourcePaths(home, env) {
|
|
8941
9110
|
const base = qoderConfigDir(home, env);
|
|
8942
9111
|
return [
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
9112
|
+
path18.join(base, "projects"),
|
|
9113
|
+
path18.join(base, ".qoder.json"),
|
|
9114
|
+
path18.join(home, ".qoder.json")
|
|
8946
9115
|
];
|
|
8947
9116
|
},
|
|
8948
9117
|
parseSessionFile: parseQoderSessionFile
|
|
@@ -8978,20 +9147,20 @@ function normalizeId(id) {
|
|
|
8978
9147
|
|
|
8979
9148
|
// src/adapters/workbuddy.ts
|
|
8980
9149
|
import { readFile as readFile12, readdir as readdir9, stat as stat10 } from "node:fs/promises";
|
|
8981
|
-
import
|
|
9150
|
+
import path19 from "node:path";
|
|
8982
9151
|
init_fs();
|
|
8983
9152
|
function workbuddyProjectsDir(home, env) {
|
|
8984
9153
|
const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
|
|
8985
9154
|
if (override && override.trim()) {
|
|
8986
|
-
return
|
|
9155
|
+
return path19.resolve(override, override.endsWith("projects") ? "" : "projects");
|
|
8987
9156
|
}
|
|
8988
|
-
return
|
|
9157
|
+
return path19.join(home, ".workbuddy", "projects");
|
|
8989
9158
|
}
|
|
8990
9159
|
function projectFromCwd(cwd, fallback) {
|
|
8991
9160
|
if (!cwd) {
|
|
8992
9161
|
return fallback;
|
|
8993
9162
|
}
|
|
8994
|
-
return
|
|
9163
|
+
return path19.basename(cwd) || fallback;
|
|
8995
9164
|
}
|
|
8996
9165
|
function sourceHash(filePath) {
|
|
8997
9166
|
return `sha256:${createStableHash(filePath)}`;
|
|
@@ -9094,8 +9263,8 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9094
9263
|
}
|
|
9095
9264
|
const events = [];
|
|
9096
9265
|
const first = lines[0].record;
|
|
9097
|
-
const sessionId = stringField(first, "sessionId") ||
|
|
9098
|
-
const fallbackProject =
|
|
9266
|
+
const sessionId = stringField(first, "sessionId") || path19.basename(filePath, ".jsonl");
|
|
9267
|
+
const fallbackProject = path19.basename(path19.dirname(filePath));
|
|
9099
9268
|
const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
|
|
9100
9269
|
const project = projectFromCwd(cwd, fallbackProject);
|
|
9101
9270
|
const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
|
|
@@ -9269,11 +9438,11 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
9269
9438
|
if (!project.isDirectory()) {
|
|
9270
9439
|
continue;
|
|
9271
9440
|
}
|
|
9272
|
-
const projectDir =
|
|
9441
|
+
const projectDir = path19.join(base, project.name);
|
|
9273
9442
|
const entries = await readdir9(projectDir, { withFileTypes: true });
|
|
9274
9443
|
for (const entry of entries) {
|
|
9275
9444
|
if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
9276
|
-
const filePath =
|
|
9445
|
+
const filePath = path19.join(projectDir, entry.name);
|
|
9277
9446
|
const info = await stat10(filePath);
|
|
9278
9447
|
files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
|
|
9279
9448
|
}
|
|
@@ -9312,19 +9481,19 @@ function createWorkbuddyAdapter() {
|
|
|
9312
9481
|
// src/adapters/zcode.ts
|
|
9313
9482
|
import { execFile } from "node:child_process";
|
|
9314
9483
|
import { readFile as readFile13, stat as stat11 } from "node:fs/promises";
|
|
9315
|
-
import
|
|
9484
|
+
import path20 from "node:path";
|
|
9316
9485
|
import { promisify as promisify2 } from "node:util";
|
|
9317
9486
|
init_fs();
|
|
9318
9487
|
var execFileAsync = promisify2(execFile);
|
|
9319
9488
|
function zcodeCliDir(home, env) {
|
|
9320
9489
|
const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
|
|
9321
9490
|
if (override && override.trim()) {
|
|
9322
|
-
return
|
|
9491
|
+
return path20.resolve(override, override.endsWith("cli") ? "" : "cli");
|
|
9323
9492
|
}
|
|
9324
|
-
return
|
|
9493
|
+
return path20.join(home, ".zcode", "cli");
|
|
9325
9494
|
}
|
|
9326
9495
|
function zcodeDbPath(home, env) {
|
|
9327
|
-
return
|
|
9496
|
+
return path20.join(zcodeCliDir(home, env), "db", "db.sqlite");
|
|
9328
9497
|
}
|
|
9329
9498
|
var providerNameCache = null;
|
|
9330
9499
|
async function loadProviderNames(configPath2) {
|
|
@@ -9358,7 +9527,7 @@ function sourceHash2(filePath) {
|
|
|
9358
9527
|
return `sha256:${createStableHash(filePath)}`;
|
|
9359
9528
|
}
|
|
9360
9529
|
function projectFromDirectory(directory) {
|
|
9361
|
-
return directory ?
|
|
9530
|
+
return directory ? path20.basename(directory) || "zcode" : "zcode";
|
|
9362
9531
|
}
|
|
9363
9532
|
function isoFromMs(value) {
|
|
9364
9533
|
return timestampFrom(typeof value === "number" ? value : Number(value));
|
|
@@ -9541,16 +9710,16 @@ async function parseZCodeDb(filePath, options) {
|
|
|
9541
9710
|
if (rows.length === 0) {
|
|
9542
9711
|
return [];
|
|
9543
9712
|
}
|
|
9544
|
-
let candidate =
|
|
9713
|
+
let candidate = path20.resolve(filePath);
|
|
9545
9714
|
let configPath2 = "";
|
|
9546
9715
|
for (let i = 0; i < 12; i++) {
|
|
9547
|
-
const probe =
|
|
9716
|
+
const probe = path20.join(candidate, ".zcode", "v2", "config.json");
|
|
9548
9717
|
try {
|
|
9549
9718
|
await stat11(probe);
|
|
9550
9719
|
configPath2 = probe;
|
|
9551
9720
|
break;
|
|
9552
9721
|
} catch {
|
|
9553
|
-
const parent =
|
|
9722
|
+
const parent = path20.dirname(candidate);
|
|
9554
9723
|
if (parent === candidate) break;
|
|
9555
9724
|
candidate = parent;
|
|
9556
9725
|
}
|
|
@@ -9766,7 +9935,7 @@ async function parseZCodeDb(filePath, options) {
|
|
|
9766
9935
|
}
|
|
9767
9936
|
async function zcodeBackfillFiles(sourceRoot, home, env) {
|
|
9768
9937
|
const candidate = sourceRoot || zcodeDbPath(home, env);
|
|
9769
|
-
const filePath = candidate.endsWith(".sqlite") ? candidate :
|
|
9938
|
+
const filePath = candidate.endsWith(".sqlite") ? candidate : path20.join(candidate, "db", "db.sqlite");
|
|
9770
9939
|
try {
|
|
9771
9940
|
const info = await stat11(filePath);
|
|
9772
9941
|
return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
|
|
@@ -9800,50 +9969,50 @@ function createZCodeAdapter() {
|
|
|
9800
9969
|
}
|
|
9801
9970
|
|
|
9802
9971
|
// src/adapters/zed.ts
|
|
9803
|
-
import
|
|
9804
|
-
import
|
|
9972
|
+
import os10 from "node:os";
|
|
9973
|
+
import path21 from "node:path";
|
|
9805
9974
|
function zedThreadsCandidates(home, env) {
|
|
9806
9975
|
const candidates = [];
|
|
9807
9976
|
const platform2 = process.platform;
|
|
9808
9977
|
if (platform2 === "darwin") {
|
|
9809
|
-
candidates.push(
|
|
9978
|
+
candidates.push(path21.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
|
|
9810
9979
|
} else if (platform2 === "win32") {
|
|
9811
9980
|
const appdata = env?.APPDATA;
|
|
9812
9981
|
if (appdata && appdata.trim()) {
|
|
9813
|
-
candidates.push(
|
|
9982
|
+
candidates.push(path21.join(path21.resolve(appdata), "Zed", "threads", "threads.db"));
|
|
9814
9983
|
}
|
|
9815
|
-
candidates.push(
|
|
9984
|
+
candidates.push(path21.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
|
|
9816
9985
|
} else {
|
|
9817
9986
|
const xdgData = env?.XDG_DATA_HOME;
|
|
9818
9987
|
if (xdgData && xdgData.trim()) {
|
|
9819
|
-
candidates.push(
|
|
9988
|
+
candidates.push(path21.join(path21.resolve(xdgData), "zed", "threads", "threads.db"));
|
|
9820
9989
|
}
|
|
9821
|
-
candidates.push(
|
|
9990
|
+
candidates.push(path21.join(home, ".local", "share", "zed", "threads", "threads.db"));
|
|
9822
9991
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
9823
9992
|
if (xdgConfig && xdgConfig.trim()) {
|
|
9824
|
-
candidates.push(
|
|
9993
|
+
candidates.push(path21.join(path21.resolve(xdgConfig), "zed", "threads", "threads.db"));
|
|
9825
9994
|
}
|
|
9826
|
-
candidates.push(
|
|
9995
|
+
candidates.push(path21.join(home, ".config", "zed", "threads", "threads.db"));
|
|
9827
9996
|
}
|
|
9828
9997
|
return candidates;
|
|
9829
9998
|
}
|
|
9830
9999
|
function zedConfigDir(home, env) {
|
|
9831
10000
|
const platform2 = process.platform;
|
|
9832
10001
|
if (platform2 === "darwin") {
|
|
9833
|
-
return
|
|
10002
|
+
return path21.join(home, "Library", "Application Support", "Zed");
|
|
9834
10003
|
}
|
|
9835
10004
|
if (platform2 === "win32") {
|
|
9836
10005
|
const appdata = env?.APPDATA;
|
|
9837
10006
|
if (appdata && appdata.trim()) {
|
|
9838
|
-
return
|
|
10007
|
+
return path21.join(path21.resolve(appdata), "Zed");
|
|
9839
10008
|
}
|
|
9840
|
-
return
|
|
10009
|
+
return path21.join(home, "AppData", "Roaming", "Zed");
|
|
9841
10010
|
}
|
|
9842
10011
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
9843
10012
|
if (xdgConfig && xdgConfig.trim()) {
|
|
9844
|
-
return
|
|
10013
|
+
return path21.join(path21.resolve(xdgConfig), "zed");
|
|
9845
10014
|
}
|
|
9846
|
-
return
|
|
10015
|
+
return path21.join(home, ".config", "zed");
|
|
9847
10016
|
}
|
|
9848
10017
|
function baseZedEvent(event) {
|
|
9849
10018
|
return {
|
|
@@ -9907,7 +10076,7 @@ async function parseZedSessionFile(dbPath, options) {
|
|
|
9907
10076
|
const folderRaw = row.folder_paths || "";
|
|
9908
10077
|
const folder = folderRaw.split(/[\n,]/).map((s) => s.trim()).find(Boolean);
|
|
9909
10078
|
const cwd = folder || void 0;
|
|
9910
|
-
const project = cwd ?
|
|
10079
|
+
const project = cwd ? path21.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
|
|
9911
10080
|
let json;
|
|
9912
10081
|
try {
|
|
9913
10082
|
const bytes = row.data_type === "zstd" ? decompress2(new Uint8Array(row.data)) : new Uint8Array(row.data);
|
|
@@ -10152,7 +10321,7 @@ async function parseZedSessionFile(dbPath, options) {
|
|
|
10152
10321
|
}
|
|
10153
10322
|
return events.filter((event) => matchesBackfillFilters(event, options));
|
|
10154
10323
|
}
|
|
10155
|
-
async function zedBackfillFiles(sourceRoot, home =
|
|
10324
|
+
async function zedBackfillFiles(sourceRoot, home = os10.homedir(), env) {
|
|
10156
10325
|
const { stat: stat14 } = await import("node:fs/promises");
|
|
10157
10326
|
if (sourceRoot) {
|
|
10158
10327
|
if (!sourceRoot.endsWith(".db")) {
|
|
@@ -10182,7 +10351,7 @@ function createZedAdapter() {
|
|
|
10182
10351
|
return zedConfigDir(home, env);
|
|
10183
10352
|
},
|
|
10184
10353
|
installedPath(home, env) {
|
|
10185
|
-
return
|
|
10354
|
+
return path21.join(zedConfigDir(home, env), "vibetime-marker");
|
|
10186
10355
|
},
|
|
10187
10356
|
async isInstalled() {
|
|
10188
10357
|
return false;
|
|
@@ -10641,15 +10810,15 @@ function hookCommandFromGroup(group) {
|
|
|
10641
10810
|
import { randomUUID } from "node:crypto";
|
|
10642
10811
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
10643
10812
|
import { homedir, hostname } from "node:os";
|
|
10644
|
-
import
|
|
10813
|
+
import path22 from "node:path";
|
|
10645
10814
|
function configDir(home = homedir()) {
|
|
10646
|
-
return
|
|
10815
|
+
return path22.join(home, ".vibetime");
|
|
10647
10816
|
}
|
|
10648
10817
|
function configPath(home = homedir()) {
|
|
10649
|
-
return
|
|
10818
|
+
return path22.join(configDir(home), "config.json");
|
|
10650
10819
|
}
|
|
10651
10820
|
function machineIdPath(home = homedir()) {
|
|
10652
|
-
return
|
|
10821
|
+
return path22.join(configDir(home), "machine-id");
|
|
10653
10822
|
}
|
|
10654
10823
|
function readConfig(home = homedir()) {
|
|
10655
10824
|
const file = configPath(home);
|
|
@@ -10698,13 +10867,13 @@ init_fs();
|
|
|
10698
10867
|
// src/lib/logger.ts
|
|
10699
10868
|
import { appendFile, mkdir as mkdir4, rename, stat as stat12 } from "node:fs/promises";
|
|
10700
10869
|
import { homedir as homedir2 } from "node:os";
|
|
10701
|
-
import
|
|
10870
|
+
import path23 from "node:path";
|
|
10702
10871
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
10703
10872
|
function logDir(home = homedir2()) {
|
|
10704
|
-
return
|
|
10873
|
+
return path23.join(home, ".vibetime", "logs");
|
|
10705
10874
|
}
|
|
10706
10875
|
function logPath(home = homedir2(), name = "cli.log") {
|
|
10707
|
-
return
|
|
10876
|
+
return path23.join(logDir(home), name);
|
|
10708
10877
|
}
|
|
10709
10878
|
function serializeError(error) {
|
|
10710
10879
|
if (error instanceof Error) {
|
|
@@ -10879,8 +11048,8 @@ function buildHeaders(token, machine) {
|
|
|
10879
11048
|
...machine?.platform ? { "x-machine-platform": machine.platform } : {}
|
|
10880
11049
|
};
|
|
10881
11050
|
}
|
|
10882
|
-
function joinUrl(base,
|
|
10883
|
-
return new URL(
|
|
11051
|
+
function joinUrl(base, path25) {
|
|
11052
|
+
return new URL(path25, base.endsWith("/") ? base : `${base}/`).toString();
|
|
10884
11053
|
}
|
|
10885
11054
|
async function postRollupBatch(remote, rollups, options = {}) {
|
|
10886
11055
|
const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
|
|
@@ -11799,13 +11968,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
|
|
|
11799
11968
|
});
|
|
11800
11969
|
}
|
|
11801
11970
|
function backfillIncrementalStatePath(home) {
|
|
11802
|
-
return
|
|
11971
|
+
return path24.join(home, ".vibetime", "backfill-state.json");
|
|
11803
11972
|
}
|
|
11804
11973
|
function syncLocalTriggerStatePath(home) {
|
|
11805
|
-
return
|
|
11974
|
+
return path24.join(home, ".vibetime", "sync-local-trigger.json");
|
|
11806
11975
|
}
|
|
11807
11976
|
function syncLocalTriggerLockPath(home) {
|
|
11808
|
-
return
|
|
11977
|
+
return path24.join(home, ".vibetime", "sync-local-trigger.lock");
|
|
11809
11978
|
}
|
|
11810
11979
|
function backfillRemoteKey(baseUrl) {
|
|
11811
11980
|
try {
|
|
@@ -11867,7 +12036,7 @@ async function readBackfillIncrementalStateFile(home, ctx) {
|
|
|
11867
12036
|
}
|
|
11868
12037
|
async function writeBackfillIncrementalStateFile(home, file) {
|
|
11869
12038
|
const statePath = backfillIncrementalStatePath(home);
|
|
11870
|
-
await mkdir5(
|
|
12039
|
+
await mkdir5(path24.dirname(statePath), { recursive: true });
|
|
11871
12040
|
await writeFile4(statePath, `${JSON.stringify(file, null, 2)}
|
|
11872
12041
|
`, "utf8");
|
|
11873
12042
|
}
|
|
@@ -11916,7 +12085,7 @@ async function readSyncLocalTriggerState(statePath) {
|
|
|
11916
12085
|
return nextState;
|
|
11917
12086
|
}
|
|
11918
12087
|
async function writeSyncLocalTriggerState(statePath, state) {
|
|
11919
|
-
await mkdir5(
|
|
12088
|
+
await mkdir5(path24.dirname(statePath), { recursive: true });
|
|
11920
12089
|
await writeFile4(statePath, `${JSON.stringify(state, null, 2)}
|
|
11921
12090
|
`, "utf8");
|
|
11922
12091
|
}
|
|
@@ -11931,12 +12100,12 @@ async function readSyncLocalLock(lockPath) {
|
|
|
11931
12100
|
return { pid: lock.pid, startedAt: lock.startedAt };
|
|
11932
12101
|
}
|
|
11933
12102
|
async function writeSyncLocalLock(lockPath, lock) {
|
|
11934
|
-
await mkdir5(
|
|
12103
|
+
await mkdir5(path24.dirname(lockPath), { recursive: true });
|
|
11935
12104
|
await writeFile4(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
11936
12105
|
`, "utf8");
|
|
11937
12106
|
}
|
|
11938
12107
|
async function acquireSyncLocalLock(lockPath, lock) {
|
|
11939
|
-
await mkdir5(
|
|
12108
|
+
await mkdir5(path24.dirname(lockPath), { recursive: true });
|
|
11940
12109
|
try {
|
|
11941
12110
|
const handle = await open(lockPath, "wx");
|
|
11942
12111
|
try {
|
|
@@ -12016,10 +12185,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
|
|
|
12016
12185
|
if (cliPath.endsWith(".ts")) {
|
|
12017
12186
|
return ["--import", "tsx", cliPath];
|
|
12018
12187
|
}
|
|
12019
|
-
return [
|
|
12188
|
+
return [path24.resolve(path24.dirname(cliPath), "../bin/vibetime.mjs")];
|
|
12020
12189
|
}
|
|
12021
12190
|
function resolveHome3(options, ctx) {
|
|
12022
|
-
return
|
|
12191
|
+
return path24.resolve(stringOption(options.home) || ctx.env.HOME || os11.homedir());
|
|
12023
12192
|
}
|
|
12024
12193
|
function requestedTargets(options) {
|
|
12025
12194
|
const value = options.target || options.targets;
|
package/package.json
CHANGED