@yhong91/vibetime 0.1.49 → 0.1.50
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 +242 -79
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -2047,7 +2047,7 @@ function claudeStyleFileMetrics(tool, input) {
|
|
|
2047
2047
|
}
|
|
2048
2048
|
|
|
2049
2049
|
// src/lib/constants.ts
|
|
2050
|
-
var PACKAGE_VERSION = true ? "0.1.
|
|
2050
|
+
var PACKAGE_VERSION = true ? "0.1.50" : "0.1.1";
|
|
2051
2051
|
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
2052
2052
|
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
2053
2053
|
var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
|
|
@@ -8094,27 +8094,98 @@ import path17 from "node:path";
|
|
|
8094
8094
|
import { access } from "node:fs/promises";
|
|
8095
8095
|
import os7 from "node:os";
|
|
8096
8096
|
import path16 from "node:path";
|
|
8097
|
+
function takeQoderDbModelCall(calls, requestId, blockStart) {
|
|
8098
|
+
if (requestId) {
|
|
8099
|
+
const call = calls.byRequestId.get(requestId)?.shift();
|
|
8100
|
+
if (call) {
|
|
8101
|
+
const index = calls.ordered.indexOf(call);
|
|
8102
|
+
if (index !== -1) {
|
|
8103
|
+
calls.ordered.splice(index, 1);
|
|
8104
|
+
}
|
|
8105
|
+
}
|
|
8106
|
+
return call;
|
|
8107
|
+
}
|
|
8108
|
+
if (!blockStart) {
|
|
8109
|
+
return void 0;
|
|
8110
|
+
}
|
|
8111
|
+
return calls.ordered.shift();
|
|
8112
|
+
}
|
|
8113
|
+
function appDataRoot(appDirName, home = os7.homedir()) {
|
|
8114
|
+
if (process.platform === "darwin") {
|
|
8115
|
+
return path16.join(home, "Library", "Application Support", appDirName);
|
|
8116
|
+
}
|
|
8117
|
+
if (process.platform === "win32") {
|
|
8118
|
+
return path16.join(process.env.APPDATA || path16.join(home, "AppData", "Roaming"), appDirName);
|
|
8119
|
+
}
|
|
8120
|
+
return path16.join(home, ".config", appDirName);
|
|
8121
|
+
}
|
|
8097
8122
|
function qoderLocalDbCandidates(appDirName) {
|
|
8098
8123
|
const candidates = [];
|
|
8099
8124
|
const envPath = process.env.QODER_LOCAL_DB_PATH;
|
|
8100
8125
|
if (envPath) {
|
|
8101
8126
|
candidates.push(envPath);
|
|
8102
8127
|
}
|
|
8103
|
-
const
|
|
8104
|
-
let configRoot;
|
|
8105
|
-
if (process.platform === "darwin") {
|
|
8106
|
-
configRoot = path16.join(home, "Library", "Application Support", appDirName);
|
|
8107
|
-
} else if (process.platform === "win32") {
|
|
8108
|
-
configRoot = path16.join(process.env.APPDATA || path16.join(home, "AppData", "Roaming"), appDirName);
|
|
8109
|
-
} else {
|
|
8110
|
-
configRoot = path16.join(home, ".config", appDirName);
|
|
8111
|
-
}
|
|
8128
|
+
const configRoot = appDataRoot(appDirName);
|
|
8112
8129
|
candidates.push(
|
|
8113
8130
|
path16.join(configRoot, "SharedClientCache", "cache", "db", "local.db"),
|
|
8114
8131
|
path16.join(configRoot, "SharedClientCache", "db", "local.db")
|
|
8115
8132
|
);
|
|
8116
8133
|
return candidates;
|
|
8117
8134
|
}
|
|
8135
|
+
async function loadQoderIdeModelCatalog(appDirName, home) {
|
|
8136
|
+
const map = {};
|
|
8137
|
+
try {
|
|
8138
|
+
const { DatabaseSync } = await import("node:sqlite");
|
|
8139
|
+
const db = new DatabaseSync(
|
|
8140
|
+
path16.join(appDataRoot(appDirName, home), "User", "globalStorage", "state.vscdb"),
|
|
8141
|
+
{ readOnly: true }
|
|
8142
|
+
);
|
|
8143
|
+
try {
|
|
8144
|
+
const rows = db.prepare(
|
|
8145
|
+
`select key, value from ItemTable where key like 'aicoding.modelConfigs.cache.%' or key = 'aicoding.customModels'`
|
|
8146
|
+
).all();
|
|
8147
|
+
const customIds = [];
|
|
8148
|
+
for (const row of rows) {
|
|
8149
|
+
const key = stringField(row, "key");
|
|
8150
|
+
const value = stringField(row, "value");
|
|
8151
|
+
if (!key || !value) {
|
|
8152
|
+
continue;
|
|
8153
|
+
}
|
|
8154
|
+
let entries;
|
|
8155
|
+
try {
|
|
8156
|
+
entries = JSON.parse(value);
|
|
8157
|
+
} catch {
|
|
8158
|
+
continue;
|
|
8159
|
+
}
|
|
8160
|
+
for (const entry of entries) {
|
|
8161
|
+
const displayName = stringField(entry, "displayName");
|
|
8162
|
+
if (key === "aicoding.customModels") {
|
|
8163
|
+
const id = stringField(entry, "id");
|
|
8164
|
+
if (id && displayName) {
|
|
8165
|
+
map[`custom:${id}`] = displayName;
|
|
8166
|
+
customIds.push(id);
|
|
8167
|
+
}
|
|
8168
|
+
} else {
|
|
8169
|
+
const name = stringField(entry, "name");
|
|
8170
|
+
if (name && displayName) {
|
|
8171
|
+
map[name] = displayName;
|
|
8172
|
+
}
|
|
8173
|
+
}
|
|
8174
|
+
}
|
|
8175
|
+
}
|
|
8176
|
+
if (customIds.length === 1) {
|
|
8177
|
+
const displayName = map[`custom:${customIds[0]}`];
|
|
8178
|
+
if (displayName) {
|
|
8179
|
+
map.custom_model = displayName;
|
|
8180
|
+
}
|
|
8181
|
+
}
|
|
8182
|
+
} finally {
|
|
8183
|
+
db.close();
|
|
8184
|
+
}
|
|
8185
|
+
} catch {
|
|
8186
|
+
}
|
|
8187
|
+
return map;
|
|
8188
|
+
}
|
|
8118
8189
|
async function loadQoderDbModelCalls(appDirName, sessionId, modelMap) {
|
|
8119
8190
|
const calls = { byRequestId: /* @__PURE__ */ new Map(), ordered: [] };
|
|
8120
8191
|
if (!sessionId) {
|
|
@@ -8266,7 +8337,7 @@ async function parseModelNamesFromDynamicTexts(dynamicTextsPath) {
|
|
|
8266
8337
|
return {};
|
|
8267
8338
|
}
|
|
8268
8339
|
}
|
|
8269
|
-
async function loadQoderCnModelNames(configDir2) {
|
|
8340
|
+
async function loadQoderCnModelNames(configDir2, home) {
|
|
8270
8341
|
const map = await parseModelNamesFromDynamicTexts(path17.join(configDir2, ".auth", "dynamic-texts.json"));
|
|
8271
8342
|
const siblingConfigDir = configDir2.replace(/\.qoder-cn$/, ".qoder");
|
|
8272
8343
|
if (siblingConfigDir !== configDir2) {
|
|
@@ -8277,6 +8348,14 @@ async function loadQoderCnModelNames(configDir2) {
|
|
|
8277
8348
|
}
|
|
8278
8349
|
}
|
|
8279
8350
|
}
|
|
8351
|
+
for (const appDirName of ["QoderCN", "Qoder"]) {
|
|
8352
|
+
const ideMap = await loadQoderIdeModelCatalog(appDirName, home);
|
|
8353
|
+
for (const [key, val] of Object.entries(ideMap)) {
|
|
8354
|
+
if (!(key in map)) {
|
|
8355
|
+
map[key] = val;
|
|
8356
|
+
}
|
|
8357
|
+
}
|
|
8358
|
+
}
|
|
8280
8359
|
return map;
|
|
8281
8360
|
}
|
|
8282
8361
|
async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
@@ -8310,7 +8389,8 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
|
|
|
8310
8389
|
inputTokens: numberField(data, "input_tokens") || 0,
|
|
8311
8390
|
outputTokens: numberField(data, "output_tokens") || 0,
|
|
8312
8391
|
cacheCreationInputTokens: numberField(data, "cache_creation_input_tokens") || 0,
|
|
8313
|
-
cacheReadInputTokens: numberField(data, "cache_read_input_tokens") || 0
|
|
8392
|
+
cacheReadInputTokens: numberField(data, "cache_read_input_tokens") || 0,
|
|
8393
|
+
stopReason: stringField(data, "stop_reason") || void 0
|
|
8314
8394
|
});
|
|
8315
8395
|
}
|
|
8316
8396
|
}
|
|
@@ -8333,20 +8413,15 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
8333
8413
|
let cwd;
|
|
8334
8414
|
let project = projectContext.project;
|
|
8335
8415
|
let model;
|
|
8336
|
-
const
|
|
8416
|
+
const home = path17.resolve(stringOption(options.home) || os8.homedir());
|
|
8417
|
+
const modelMap = await loadQoderCnModelNames(configDir2, home);
|
|
8337
8418
|
const isSubagentSession = filePath.includes("subagents");
|
|
8338
8419
|
const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
8339
8420
|
let modelCallIndex = 0;
|
|
8340
8421
|
let dbModelCalls;
|
|
8341
8422
|
const nextDbModelCall = async (requestId, blockStart) => {
|
|
8342
8423
|
dbModelCalls ??= await loadQoderDbModelCalls("QoderCN", sessionId, modelMap);
|
|
8343
|
-
|
|
8344
|
-
return dbModelCalls.byRequestId.get(requestId)?.shift();
|
|
8345
|
-
}
|
|
8346
|
-
if (!blockStart) {
|
|
8347
|
-
return void 0;
|
|
8348
|
-
}
|
|
8349
|
-
return dbModelCalls.ordered.shift();
|
|
8424
|
+
return takeQoderDbModelCall(dbModelCalls, requestId, blockStart);
|
|
8350
8425
|
};
|
|
8351
8426
|
const state = new SessionParserState(filePath, options, (event) => baseQoderCnEvent({ ...event, cwd, project, model }));
|
|
8352
8427
|
state.sessionId = sessionId;
|
|
@@ -8532,6 +8607,20 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
8532
8607
|
modelCalls: 1
|
|
8533
8608
|
};
|
|
8534
8609
|
model = call.model || model;
|
|
8610
|
+
if (!usage.tokensTotal && !usage.tokensCachedInput) {
|
|
8611
|
+
const dbCall = await nextDbModelCall(requestId, isBlockStart);
|
|
8612
|
+
if (dbCall && (dbCall.inputTokens || dbCall.outputTokens || dbCall.cachedTokens)) {
|
|
8613
|
+
usage = {
|
|
8614
|
+
tokensInput: dbCall.inputTokens || void 0,
|
|
8615
|
+
tokensCachedInput: dbCall.cachedTokens || void 0,
|
|
8616
|
+
tokensCacheReadInput: dbCall.cachedTokens || void 0,
|
|
8617
|
+
tokensOutput: dbCall.outputTokens || void 0,
|
|
8618
|
+
tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
|
|
8619
|
+
modelCalls: 1
|
|
8620
|
+
};
|
|
8621
|
+
model = dbCall.model || model;
|
|
8622
|
+
}
|
|
8623
|
+
}
|
|
8535
8624
|
} else if (shouldEmitUsage) {
|
|
8536
8625
|
const dbCall = await nextDbModelCall(requestId, isBlockStart);
|
|
8537
8626
|
if (dbCall) {
|
|
@@ -8982,6 +9071,7 @@ function createQoderCnAdapter() {
|
|
|
8982
9071
|
}
|
|
8983
9072
|
|
|
8984
9073
|
// src/adapters/qoder.ts
|
|
9074
|
+
import { existsSync } from "node:fs";
|
|
8985
9075
|
import { readdir as readdir8, readFile as readFile11, stat as stat9 } from "node:fs/promises";
|
|
8986
9076
|
import os9 from "node:os";
|
|
8987
9077
|
import path18 from "node:path";
|
|
@@ -9044,7 +9134,7 @@ async function parseModelNamesFromDynamicTexts2(dynamicTextsPath) {
|
|
|
9044
9134
|
return {};
|
|
9045
9135
|
}
|
|
9046
9136
|
}
|
|
9047
|
-
async function loadQoderModelNames(configDir2) {
|
|
9137
|
+
async function loadQoderModelNames(configDir2, home) {
|
|
9048
9138
|
const map = await parseModelNamesFromDynamicTexts2(path18.join(configDir2, ".auth", "dynamic-texts.json"));
|
|
9049
9139
|
const siblingConfigDir = configDir2.replace(/\.qoder$/, ".qoder-cn");
|
|
9050
9140
|
if (siblingConfigDir !== configDir2) {
|
|
@@ -9055,8 +9145,38 @@ async function loadQoderModelNames(configDir2) {
|
|
|
9055
9145
|
}
|
|
9056
9146
|
}
|
|
9057
9147
|
}
|
|
9148
|
+
if (isQwenworkConfigRoot(configDir2)) {
|
|
9149
|
+
for (const dir of [path18.join(home, ".qoder"), path18.join(home, ".qoder-cn")]) {
|
|
9150
|
+
if (path18.resolve(dir) === path18.resolve(configDir2)) {
|
|
9151
|
+
continue;
|
|
9152
|
+
}
|
|
9153
|
+
const fallbackMap = await parseModelNamesFromDynamicTexts2(path18.join(dir, ".auth", "dynamic-texts.json"));
|
|
9154
|
+
for (const [key, val] of Object.entries(fallbackMap)) {
|
|
9155
|
+
if (!(key in map)) {
|
|
9156
|
+
map[key] = val;
|
|
9157
|
+
}
|
|
9158
|
+
}
|
|
9159
|
+
}
|
|
9160
|
+
}
|
|
9161
|
+
for (const appDirName of ["Qoder", "QoderCN"]) {
|
|
9162
|
+
const ideMap = await loadQoderIdeModelCatalog(appDirName, home);
|
|
9163
|
+
for (const [key, val] of Object.entries(ideMap)) {
|
|
9164
|
+
if (!(key in map)) {
|
|
9165
|
+
map[key] = val;
|
|
9166
|
+
}
|
|
9167
|
+
}
|
|
9168
|
+
}
|
|
9058
9169
|
return map;
|
|
9059
9170
|
}
|
|
9171
|
+
function isQwenworkConfigRoot(configDir2) {
|
|
9172
|
+
const name = path18.basename(path18.resolve(configDir2));
|
|
9173
|
+
if (name === ".qwenworkcn" || name === ".qwenwork") {
|
|
9174
|
+
return true;
|
|
9175
|
+
}
|
|
9176
|
+
const override = process.env.QWENWORK_CONFIG_DIR;
|
|
9177
|
+
return Boolean(override && override.trim() && path18.basename(path18.resolve(override)) === name);
|
|
9178
|
+
}
|
|
9179
|
+
var FAILED_SEGMENT_STOP_REASONS = /* @__PURE__ */ new Set(["cancelled", "canceled", "error", "failed", "refusal"]);
|
|
9060
9180
|
async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
9061
9181
|
const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
|
|
9062
9182
|
const segmentsPath = path18.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
@@ -9088,7 +9208,8 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
|
|
|
9088
9208
|
inputTokens: numberField(data, "input_tokens") || 0,
|
|
9089
9209
|
outputTokens: numberField(data, "output_tokens") || 0,
|
|
9090
9210
|
cacheCreationInputTokens: numberField(data, "cache_creation_input_tokens") || 0,
|
|
9091
|
-
cacheReadInputTokens: numberField(data, "cache_read_input_tokens") || 0
|
|
9211
|
+
cacheReadInputTokens: numberField(data, "cache_read_input_tokens") || 0,
|
|
9212
|
+
stopReason: stringField(data, "stop_reason") || void 0
|
|
9092
9213
|
});
|
|
9093
9214
|
}
|
|
9094
9215
|
}
|
|
@@ -9111,20 +9232,16 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
9111
9232
|
let cwd;
|
|
9112
9233
|
let project = projectContext.project;
|
|
9113
9234
|
let model;
|
|
9114
|
-
const
|
|
9235
|
+
const home = path18.resolve(stringOption(options.home) || os9.homedir());
|
|
9236
|
+
const modelMap = await loadQoderModelNames(configDir2, home);
|
|
9237
|
+
const qwenworkRoot = isQwenworkConfigRoot(configDir2);
|
|
9115
9238
|
const isSubagentSession = filePath.includes("subagents");
|
|
9116
9239
|
const segmentModelCalls = await loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
9117
9240
|
let modelCallIndex = 0;
|
|
9118
9241
|
let dbModelCalls;
|
|
9119
9242
|
const nextDbModelCall = async (requestId, blockStart) => {
|
|
9120
9243
|
dbModelCalls ??= await loadQoderDbModelCalls("Qoder", sessionId, modelMap);
|
|
9121
|
-
|
|
9122
|
-
return dbModelCalls.byRequestId.get(requestId)?.shift();
|
|
9123
|
-
}
|
|
9124
|
-
if (!blockStart) {
|
|
9125
|
-
return void 0;
|
|
9126
|
-
}
|
|
9127
|
-
return dbModelCalls.ordered.shift();
|
|
9244
|
+
return takeQoderDbModelCall(dbModelCalls, requestId, blockStart);
|
|
9128
9245
|
};
|
|
9129
9246
|
const state = new SessionParserState(filePath, options, (event) => baseQoderEvent({ ...event, cwd, project, model }));
|
|
9130
9247
|
state.sessionId = sessionId;
|
|
@@ -9292,39 +9409,28 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
9292
9409
|
seenUsageKeys.add(usageKey);
|
|
9293
9410
|
}
|
|
9294
9411
|
let usage;
|
|
9412
|
+
let keepZeroTokenUsage = false;
|
|
9295
9413
|
if (shouldEmitUsage && modelCallIndex < segmentModelCalls.length) {
|
|
9296
9414
|
const call = segmentModelCalls[modelCallIndex++];
|
|
9297
|
-
|
|
9298
|
-
const cacheCreationInputTokens = call.cacheCreationInputTokens;
|
|
9299
|
-
const cacheReadInputTokens = call.cacheReadInputTokens;
|
|
9300
|
-
const outputTokens = call.outputTokens;
|
|
9301
|
-
const cachedInputTokens = cacheCreationInputTokens + cacheReadInputTokens;
|
|
9302
|
-
const totalInputTokens = inputTokens;
|
|
9303
|
-
usage = {
|
|
9304
|
-
tokensInput: totalInputTokens || void 0,
|
|
9305
|
-
tokensCachedInput: cachedInputTokens || void 0,
|
|
9306
|
-
tokensCacheCreationInput: cacheCreationInputTokens || void 0,
|
|
9307
|
-
tokensCacheReadInput: cacheReadInputTokens || void 0,
|
|
9308
|
-
tokensOutput: outputTokens || void 0,
|
|
9309
|
-
tokensTotal: totalInputTokens + outputTokens || void 0,
|
|
9310
|
-
modelCalls: 1
|
|
9311
|
-
};
|
|
9415
|
+
usage = qoderSegmentUsage(call);
|
|
9312
9416
|
model = call.model || model;
|
|
9417
|
+
if (!usage.tokensTotal && !usage.tokensCachedInput) {
|
|
9418
|
+
const dbCall = await nextDbModelCall(requestId, isBlockStart);
|
|
9419
|
+
if (dbCall && (dbCall.inputTokens || dbCall.outputTokens || dbCall.cachedTokens)) {
|
|
9420
|
+
usage = qoderDbUsage(dbCall);
|
|
9421
|
+
model = dbCall.model || model;
|
|
9422
|
+
} else if (qwenworkRoot && (!call.stopReason || !FAILED_SEGMENT_STOP_REASONS.has(call.stopReason))) {
|
|
9423
|
+
keepZeroTokenUsage = true;
|
|
9424
|
+
}
|
|
9425
|
+
}
|
|
9313
9426
|
} else if (shouldEmitUsage) {
|
|
9314
9427
|
const dbCall = await nextDbModelCall(requestId, isBlockStart);
|
|
9315
9428
|
if (dbCall) {
|
|
9316
|
-
usage =
|
|
9317
|
-
tokensInput: dbCall.inputTokens || void 0,
|
|
9318
|
-
tokensCachedInput: dbCall.cachedTokens || void 0,
|
|
9319
|
-
tokensCacheReadInput: dbCall.cachedTokens || void 0,
|
|
9320
|
-
tokensOutput: dbCall.outputTokens || void 0,
|
|
9321
|
-
tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
|
|
9322
|
-
modelCalls: 1
|
|
9323
|
-
};
|
|
9429
|
+
usage = qoderDbUsage(dbCall);
|
|
9324
9430
|
model = dbCall.model || model;
|
|
9325
9431
|
}
|
|
9326
9432
|
}
|
|
9327
|
-
if (usage && (usage.tokensTotal || usage.tokensCachedInput)) {
|
|
9433
|
+
if (usage && (usage.tokensTotal || usage.tokensCachedInput || keepZeroTokenUsage)) {
|
|
9328
9434
|
const speed = stringField(objectField(message, "usage"), "speed");
|
|
9329
9435
|
const usageModel = speed === "fast" && model ? `${model}-fast` : model;
|
|
9330
9436
|
push(baseQoderEvent({
|
|
@@ -9451,6 +9557,28 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
9451
9557
|
}
|
|
9452
9558
|
return validEvents;
|
|
9453
9559
|
}
|
|
9560
|
+
function qoderSegmentUsage(call) {
|
|
9561
|
+
const cachedInputTokens = call.cacheCreationInputTokens + call.cacheReadInputTokens;
|
|
9562
|
+
return {
|
|
9563
|
+
tokensInput: call.inputTokens || void 0,
|
|
9564
|
+
tokensCachedInput: cachedInputTokens || void 0,
|
|
9565
|
+
tokensCacheCreationInput: call.cacheCreationInputTokens || void 0,
|
|
9566
|
+
tokensCacheReadInput: call.cacheReadInputTokens || void 0,
|
|
9567
|
+
tokensOutput: call.outputTokens || void 0,
|
|
9568
|
+
tokensTotal: call.inputTokens + call.outputTokens || void 0,
|
|
9569
|
+
modelCalls: 1
|
|
9570
|
+
};
|
|
9571
|
+
}
|
|
9572
|
+
function qoderDbUsage(dbCall) {
|
|
9573
|
+
return {
|
|
9574
|
+
tokensInput: dbCall.inputTokens || void 0,
|
|
9575
|
+
tokensCachedInput: dbCall.cachedTokens || void 0,
|
|
9576
|
+
tokensCacheReadInput: dbCall.cachedTokens || void 0,
|
|
9577
|
+
tokensOutput: dbCall.outputTokens || void 0,
|
|
9578
|
+
tokensTotal: dbCall.inputTokens + dbCall.outputTokens || void 0,
|
|
9579
|
+
modelCalls: 1
|
|
9580
|
+
};
|
|
9581
|
+
}
|
|
9454
9582
|
function baseQoderEvent(event) {
|
|
9455
9583
|
return {
|
|
9456
9584
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
@@ -9534,12 +9662,20 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
9534
9662
|
const isSubagent = filePath.includes(`${path18.sep}subagents${path18.sep}`);
|
|
9535
9663
|
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
9536
9664
|
let cwds = [];
|
|
9665
|
+
const workspaceDirs = [];
|
|
9537
9666
|
for (const line of lines) {
|
|
9538
9667
|
const raw = parseJsonLine(line);
|
|
9539
9668
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
9540
9669
|
if (cwd && path18.isAbsolute(cwd)) {
|
|
9541
9670
|
cwds.push(cwd);
|
|
9542
9671
|
}
|
|
9672
|
+
if (raw && stringField(raw, "type") === "workspace-directories") {
|
|
9673
|
+
for (const dir of arrayField5(raw, "directories")) {
|
|
9674
|
+
if (typeof dir === "string" && path18.isAbsolute(dir)) {
|
|
9675
|
+
workspaceDirs.push(dir);
|
|
9676
|
+
}
|
|
9677
|
+
}
|
|
9678
|
+
}
|
|
9543
9679
|
}
|
|
9544
9680
|
if (isSubagent) {
|
|
9545
9681
|
if (inherited?.cwd && path18.isAbsolute(inherited.cwd)) {
|
|
@@ -9555,6 +9691,13 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
9555
9691
|
if (cwd && path18.isAbsolute(cwd)) {
|
|
9556
9692
|
parentCwds.push(cwd);
|
|
9557
9693
|
}
|
|
9694
|
+
if (workspaceDirs.length === 0 && raw && stringField(raw, "type") === "workspace-directories") {
|
|
9695
|
+
for (const dir of arrayField5(raw, "directories")) {
|
|
9696
|
+
if (typeof dir === "string" && path18.isAbsolute(dir)) {
|
|
9697
|
+
workspaceDirs.push(dir);
|
|
9698
|
+
}
|
|
9699
|
+
}
|
|
9700
|
+
}
|
|
9558
9701
|
}
|
|
9559
9702
|
if (parentCwds.length > 0) {
|
|
9560
9703
|
cwds = parentCwds;
|
|
@@ -9563,6 +9706,12 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
9563
9706
|
}
|
|
9564
9707
|
}
|
|
9565
9708
|
}
|
|
9709
|
+
if (cwds.length > 0 && cwds.every((cwd) => pathInsideDir(cwd, configDir2))) {
|
|
9710
|
+
const external = workspaceDirs.filter((dir) => !pathInsideDir(dir, configDir2));
|
|
9711
|
+
if (external.length > 0) {
|
|
9712
|
+
cwds = external;
|
|
9713
|
+
}
|
|
9714
|
+
}
|
|
9566
9715
|
const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
|
|
9567
9716
|
const project = inherited?.project || (cwds.length > 0 ? path18.basename(cwds[0]) : root ? path18.basename(root) : await qoderProjectFromFilePath(filePath, options));
|
|
9568
9717
|
return {
|
|
@@ -9570,6 +9719,11 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
9570
9719
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
9571
9720
|
};
|
|
9572
9721
|
}
|
|
9722
|
+
function pathInsideDir(candidate, dir) {
|
|
9723
|
+
const resolvedDir = path18.resolve(dir);
|
|
9724
|
+
const resolved = path18.resolve(candidate);
|
|
9725
|
+
return resolved === resolvedDir || resolved.startsWith(`${resolvedDir}${path18.sep}`);
|
|
9726
|
+
}
|
|
9573
9727
|
async function gitRootFromCwds3(cwds) {
|
|
9574
9728
|
const seen = /* @__PURE__ */ new Set();
|
|
9575
9729
|
for (const cwd of cwds) {
|
|
@@ -9594,7 +9748,7 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
|
9594
9748
|
for (const cwd of cwds) {
|
|
9595
9749
|
let current = path18.resolve(cwd);
|
|
9596
9750
|
while (true) {
|
|
9597
|
-
if (
|
|
9751
|
+
if (qoderEncodedVariants(current).includes(projectDir)) {
|
|
9598
9752
|
return current;
|
|
9599
9753
|
}
|
|
9600
9754
|
const parent = path18.dirname(current);
|
|
@@ -9606,21 +9760,23 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
|
9606
9760
|
}
|
|
9607
9761
|
return void 0;
|
|
9608
9762
|
}
|
|
9609
|
-
function encodeQoderProjectPath(value) {
|
|
9610
|
-
return path18.resolve(value).split(path18.sep).join("-").replaceAll("_", "-");
|
|
9611
|
-
}
|
|
9612
9763
|
function rawQoderProjectPath(value) {
|
|
9613
9764
|
return path18.resolve(value).split(path18.sep).join("-");
|
|
9614
9765
|
}
|
|
9615
9766
|
function qoderEncodedVariants(value) {
|
|
9616
9767
|
const raw = rawQoderProjectPath(value);
|
|
9617
|
-
const
|
|
9618
|
-
|
|
9768
|
+
const variants = /* @__PURE__ */ new Set([
|
|
9769
|
+
raw,
|
|
9770
|
+
raw.replaceAll("_", "-"),
|
|
9771
|
+
raw.replaceAll(".", "-"),
|
|
9772
|
+
raw.replaceAll("_", "-").replaceAll(".", "-")
|
|
9773
|
+
]);
|
|
9774
|
+
return [...variants];
|
|
9619
9775
|
}
|
|
9620
9776
|
function qoderEncodedProjectSuffix(projectDir, home) {
|
|
9621
9777
|
for (const prefix of qoderEncodedVariants(home).map((value) => `${value}-`)) {
|
|
9622
9778
|
if (projectDir.startsWith(prefix)) {
|
|
9623
|
-
return projectDir.slice(prefix.length) || void 0;
|
|
9779
|
+
return projectDir.slice(prefix.length).replace(/^-+/, "") || void 0;
|
|
9624
9780
|
}
|
|
9625
9781
|
}
|
|
9626
9782
|
return void 0;
|
|
@@ -9705,6 +9861,16 @@ function qoderConfigDir(home, env) {
|
|
|
9705
9861
|
}
|
|
9706
9862
|
return path18.join(home, ".qoder");
|
|
9707
9863
|
}
|
|
9864
|
+
function qwenworkConfigDir(home, env) {
|
|
9865
|
+
const override = env?.QWENWORK_CONFIG_DIR;
|
|
9866
|
+
if (override && override.trim()) {
|
|
9867
|
+
return path18.resolve(override);
|
|
9868
|
+
}
|
|
9869
|
+
return path18.join(home, ".qwenworkcn");
|
|
9870
|
+
}
|
|
9871
|
+
function qoderConfigDirs(home, env) {
|
|
9872
|
+
return [...new Set([qoderConfigDir(home, env), qwenworkConfigDir(home, env)].map((dir) => path18.resolve(dir)))];
|
|
9873
|
+
}
|
|
9708
9874
|
function createQoderAdapter() {
|
|
9709
9875
|
return {
|
|
9710
9876
|
id: "qoder",
|
|
@@ -9724,19 +9890,22 @@ function createQoderAdapter() {
|
|
|
9724
9890
|
);
|
|
9725
9891
|
},
|
|
9726
9892
|
installEntries(home, env) {
|
|
9727
|
-
|
|
9893
|
+
const [primary, ...variants] = qoderConfigDirs(home, env);
|
|
9894
|
+
const targets = [primary, ...variants.filter((dir) => existsSync(dir))];
|
|
9895
|
+
return targets.map((base) => ({
|
|
9728
9896
|
kind: "hooks-json",
|
|
9729
|
-
path: path18.join(
|
|
9897
|
+
path: path18.join(base, "settings.json"),
|
|
9730
9898
|
content: hookConfig7()
|
|
9731
|
-
}
|
|
9899
|
+
}));
|
|
9732
9900
|
},
|
|
9733
9901
|
sourcePaths(home, env) {
|
|
9902
|
+
const paths = qoderConfigDirs(home, env).map((base2) => path18.join(base2, "projects"));
|
|
9734
9903
|
const base = qoderConfigDir(home, env);
|
|
9735
|
-
|
|
9736
|
-
path18.join(base, "projects"),
|
|
9904
|
+
paths.push(
|
|
9737
9905
|
path18.join(base, ".qoder.json"),
|
|
9738
9906
|
path18.join(home, ".qoder.json")
|
|
9739
|
-
|
|
9907
|
+
);
|
|
9908
|
+
return paths;
|
|
9740
9909
|
},
|
|
9741
9910
|
parseSessionFile: parseQoderSessionFile
|
|
9742
9911
|
};
|
|
@@ -11171,13 +11340,7 @@ function createZedAdapter() {
|
|
|
11171
11340
|
}
|
|
11172
11341
|
|
|
11173
11342
|
// src/lib/pricing.ts
|
|
11174
|
-
function estimateEventCostUsd(
|
|
11175
|
-
if (event.type !== "model.usage") {
|
|
11176
|
-
return 0;
|
|
11177
|
-
}
|
|
11178
|
-
if (typeof event.metrics?.costUsd === "number" && event.metrics.costUsd > 0) {
|
|
11179
|
-
return event.metrics.costUsd;
|
|
11180
|
-
}
|
|
11343
|
+
function estimateEventCostUsd(_event) {
|
|
11181
11344
|
return 0;
|
|
11182
11345
|
}
|
|
11183
11346
|
|
|
@@ -11640,7 +11803,7 @@ function hookCommandFromGroup(group) {
|
|
|
11640
11803
|
|
|
11641
11804
|
// src/lib/config.ts
|
|
11642
11805
|
import { randomUUID } from "node:crypto";
|
|
11643
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
11806
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
11644
11807
|
import { homedir, hostname } from "node:os";
|
|
11645
11808
|
import path22 from "node:path";
|
|
11646
11809
|
function configDir(home = homedir()) {
|
|
@@ -11654,7 +11817,7 @@ function machineIdPath(home = homedir()) {
|
|
|
11654
11817
|
}
|
|
11655
11818
|
function readConfig(home = homedir()) {
|
|
11656
11819
|
const file = configPath(home);
|
|
11657
|
-
if (!
|
|
11820
|
+
if (!existsSync2(file)) {
|
|
11658
11821
|
return {};
|
|
11659
11822
|
}
|
|
11660
11823
|
try {
|
|
@@ -11666,7 +11829,7 @@ function readConfig(home = homedir()) {
|
|
|
11666
11829
|
}
|
|
11667
11830
|
function writeConfig(config, home = homedir()) {
|
|
11668
11831
|
const dir = configDir(home);
|
|
11669
|
-
if (!
|
|
11832
|
+
if (!existsSync2(dir)) {
|
|
11670
11833
|
mkdirSync(dir, { recursive: true });
|
|
11671
11834
|
}
|
|
11672
11835
|
writeFileSync(configPath(home), `${JSON.stringify(config, null, 2)}
|
|
@@ -11674,7 +11837,7 @@ function writeConfig(config, home = homedir()) {
|
|
|
11674
11837
|
}
|
|
11675
11838
|
function ensureLocalMachineId(home = homedir()) {
|
|
11676
11839
|
const file = machineIdPath(home);
|
|
11677
|
-
if (
|
|
11840
|
+
if (existsSync2(file)) {
|
|
11678
11841
|
const value = readFileSync(file, "utf8").trim();
|
|
11679
11842
|
if (value.length > 0) {
|
|
11680
11843
|
return value;
|
|
@@ -11682,7 +11845,7 @@ function ensureLocalMachineId(home = homedir()) {
|
|
|
11682
11845
|
}
|
|
11683
11846
|
const id = randomUUID();
|
|
11684
11847
|
const dir = configDir(home);
|
|
11685
|
-
if (!
|
|
11848
|
+
if (!existsSync2(dir)) {
|
|
11686
11849
|
mkdirSync(dir, { recursive: true });
|
|
11687
11850
|
}
|
|
11688
11851
|
writeFileSync(file, `${id}
|
package/package.json
CHANGED