@yhong91/vibetime 0.1.50 → 0.1.52
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 +754 -192
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -886,7 +886,7 @@ var init_esm = __esm({
|
|
|
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
888
|
import os11 from "node:os";
|
|
889
|
-
import
|
|
889
|
+
import path25 from "node:path";
|
|
890
890
|
import { fileURLToPath } from "node:url";
|
|
891
891
|
|
|
892
892
|
// ../shared/src/index.ts
|
|
@@ -924,7 +924,7 @@ var TELEMETRY_EVENT_TYPES = [
|
|
|
924
924
|
"agent.operation"
|
|
925
925
|
];
|
|
926
926
|
var FILE_ACTIVITY_OPERATIONS = ["read", "search", "create", "write", "edit", "delete"];
|
|
927
|
-
var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "copilot", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn", "workbuddy", "zcode", "grok-build", "zed"];
|
|
927
|
+
var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "copilot", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn", "workbuddy", "zcode", "grok-build", "zed", "kimi-code"];
|
|
928
928
|
function createWorkspaceId(input) {
|
|
929
929
|
const basis = input.repoUrl || input.repoRoot || input.projectName || "unknown";
|
|
930
930
|
return `workspace_${fnv1a(basis)}`;
|
|
@@ -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.52" : "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;
|
|
@@ -6935,9 +6935,476 @@ function createGrokBuildAdapter() {
|
|
|
6935
6935
|
};
|
|
6936
6936
|
}
|
|
6937
6937
|
|
|
6938
|
+
// src/adapters/kimi-code.ts
|
|
6939
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
6940
|
+
import path14 from "node:path";
|
|
6941
|
+
function kimiCodeHome(home, env) {
|
|
6942
|
+
const override = env?.KIMI_CODE_HOME || env?.KIMI_HOME;
|
|
6943
|
+
if (override && override.trim()) {
|
|
6944
|
+
return path14.resolve(override);
|
|
6945
|
+
}
|
|
6946
|
+
return path14.join(home, ".kimi-code");
|
|
6947
|
+
}
|
|
6948
|
+
function kimiCodeSessionsDir(home, env) {
|
|
6949
|
+
return path14.join(kimiCodeHome(home, env), "sessions");
|
|
6950
|
+
}
|
|
6951
|
+
function baseKimiEvent(event) {
|
|
6952
|
+
return {
|
|
6953
|
+
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
6954
|
+
source: "kimi-code",
|
|
6955
|
+
agent: "kimi-code",
|
|
6956
|
+
workspaceId: createWorkspaceId({ projectName: event.project, repoRoot: event.cwd }),
|
|
6957
|
+
...event
|
|
6958
|
+
};
|
|
6959
|
+
}
|
|
6960
|
+
function extractTextParts(input) {
|
|
6961
|
+
if (typeof input === "string") {
|
|
6962
|
+
return input;
|
|
6963
|
+
}
|
|
6964
|
+
if (!Array.isArray(input)) {
|
|
6965
|
+
return "";
|
|
6966
|
+
}
|
|
6967
|
+
return input.filter((item) => isPlainObject(item) && item.type === "text").map((item) => stringField(item, "text") || "").join("");
|
|
6968
|
+
}
|
|
6969
|
+
function kimiUsageFromRecord(usage) {
|
|
6970
|
+
const inputOther = numberField(usage, "inputOther") || 0;
|
|
6971
|
+
const output = numberField(usage, "output") || 0;
|
|
6972
|
+
const cacheRead = numberField(usage, "inputCacheRead") || 0;
|
|
6973
|
+
const cacheWrite = numberField(usage, "inputCacheCreation") || 0;
|
|
6974
|
+
const inputTokens = numberField(usage, "input_tokens") || numberField(usage, "input") || 0;
|
|
6975
|
+
const outputTokens = numberField(usage, "output_tokens") || 0;
|
|
6976
|
+
const nonCached = inputOther || inputTokens;
|
|
6977
|
+
const out = output || outputTokens;
|
|
6978
|
+
const total = nonCached + out + cacheRead + cacheWrite;
|
|
6979
|
+
if (total <= 0) {
|
|
6980
|
+
return void 0;
|
|
6981
|
+
}
|
|
6982
|
+
return {
|
|
6983
|
+
tokensInput: nonCached + cacheRead + cacheWrite || void 0,
|
|
6984
|
+
tokensOutput: out || void 0,
|
|
6985
|
+
tokensCacheReadInput: cacheRead || void 0,
|
|
6986
|
+
tokensCacheCreationInput: cacheWrite || void 0,
|
|
6987
|
+
tokensCachedInput: cacheRead + cacheWrite || void 0,
|
|
6988
|
+
tokensTotal: total,
|
|
6989
|
+
modelCalls: 1
|
|
6990
|
+
};
|
|
6991
|
+
}
|
|
6992
|
+
function normalizeTurnId(raw) {
|
|
6993
|
+
if (typeof raw === "number" && Number.isFinite(raw)) {
|
|
6994
|
+
return `turn_${raw}`;
|
|
6995
|
+
}
|
|
6996
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
6997
|
+
return raw.startsWith("turn_") ? raw : `turn_${raw}`;
|
|
6998
|
+
}
|
|
6999
|
+
return void 0;
|
|
7000
|
+
}
|
|
7001
|
+
function sessionIdFromWirePath(filePath) {
|
|
7002
|
+
const normalized = filePath.replaceAll("\\", "/");
|
|
7003
|
+
const match = normalized.match(/\/(session_[^/]+)\/agents\/[^/]+\/wire\.jsonl$/);
|
|
7004
|
+
return match?.[1];
|
|
7005
|
+
}
|
|
7006
|
+
async function readSessionState(filePath) {
|
|
7007
|
+
const sessionDir = path14.dirname(path14.dirname(path14.dirname(filePath)));
|
|
7008
|
+
const statePath = path14.join(sessionDir, "state.json");
|
|
7009
|
+
try {
|
|
7010
|
+
const text = await readFile9(statePath, "utf8");
|
|
7011
|
+
const raw = JSON.parse(text);
|
|
7012
|
+
if (!isPlainObject(raw)) {
|
|
7013
|
+
return {};
|
|
7014
|
+
}
|
|
7015
|
+
return {
|
|
7016
|
+
sessionId: stringField(raw, "id"),
|
|
7017
|
+
cwd: stringField(raw, "cwd"),
|
|
7018
|
+
title: stringField(raw, "title")
|
|
7019
|
+
};
|
|
7020
|
+
} catch {
|
|
7021
|
+
return {};
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
async function parseKimiCodeSessionFile(filePath, options) {
|
|
7025
|
+
if (path14.basename(filePath) !== "wire.jsonl") {
|
|
7026
|
+
return [];
|
|
7027
|
+
}
|
|
7028
|
+
const text = await readFile9(filePath, "utf8");
|
|
7029
|
+
const lines = text.split("\n").filter(Boolean);
|
|
7030
|
+
const stateMeta = await readSessionState(filePath);
|
|
7031
|
+
let sessionId = stateMeta.sessionId || sessionIdFromWirePath(filePath);
|
|
7032
|
+
let cwd = stateMeta.cwd;
|
|
7033
|
+
let project = cwd ? path14.basename(cwd) : void 0;
|
|
7034
|
+
let model;
|
|
7035
|
+
let provider;
|
|
7036
|
+
let reasoningEffort;
|
|
7037
|
+
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
7038
|
+
const pendingPermissions = /* @__PURE__ */ new Map();
|
|
7039
|
+
let sawUsageRecord = false;
|
|
7040
|
+
const state = new SessionParserState(filePath, options, (event) => baseKimiEvent({ ...event, cwd, project, model, provider }));
|
|
7041
|
+
if (sessionId) {
|
|
7042
|
+
state.sessionId = sessionId;
|
|
7043
|
+
}
|
|
7044
|
+
const push = (event, ln, topType) => {
|
|
7045
|
+
state.push(
|
|
7046
|
+
{
|
|
7047
|
+
...event,
|
|
7048
|
+
sessionId: event.sessionId || sessionId,
|
|
7049
|
+
workspaceId: event.workspaceId || createWorkspaceId({ projectName: project, repoRoot: cwd })
|
|
7050
|
+
},
|
|
7051
|
+
ln,
|
|
7052
|
+
topType || event.type,
|
|
7053
|
+
event.type
|
|
7054
|
+
);
|
|
7055
|
+
};
|
|
7056
|
+
for (const [index, line] of lines.entries()) {
|
|
7057
|
+
const lineNumber = index + 1;
|
|
7058
|
+
const raw = parseJsonLine(line);
|
|
7059
|
+
if (!raw) {
|
|
7060
|
+
continue;
|
|
7061
|
+
}
|
|
7062
|
+
const entryType = stringField(raw, "type");
|
|
7063
|
+
const ts = timestampFrom(raw.time) || timestampFrom(raw.created_at) || timestampFrom(raw.timestamp);
|
|
7064
|
+
if (!ts || !entryType) {
|
|
7065
|
+
continue;
|
|
7066
|
+
}
|
|
7067
|
+
if (entryType === "metadata") {
|
|
7068
|
+
state.ensureSessionStarted(ts, lineNumber, entryType);
|
|
7069
|
+
continue;
|
|
7070
|
+
}
|
|
7071
|
+
if (entryType === "profile.bind") {
|
|
7072
|
+
state.ensureSessionStarted(ts, lineNumber, entryType);
|
|
7073
|
+
model = stringField(raw, "modelAlias") || stringField(raw, "model") || model;
|
|
7074
|
+
reasoningEffort = stringField(raw, "thinkingEffort") || reasoningEffort;
|
|
7075
|
+
const disclosure = objectField(raw, "environmentDisclosure");
|
|
7076
|
+
const disclosedCwd = stringField(disclosure, "cwd");
|
|
7077
|
+
if (disclosedCwd) {
|
|
7078
|
+
cwd = disclosedCwd;
|
|
7079
|
+
project = path14.basename(disclosedCwd);
|
|
7080
|
+
}
|
|
7081
|
+
continue;
|
|
7082
|
+
}
|
|
7083
|
+
if (entryType === "turn.prompt") {
|
|
7084
|
+
state.ensureSessionStarted(ts, lineNumber, entryType);
|
|
7085
|
+
if (isTurnIdle(state.currentTurnLastEventAt) || state.currentTurnId) {
|
|
7086
|
+
state.closeTurn(ts, lineNumber, entryType);
|
|
7087
|
+
}
|
|
7088
|
+
const nextOrdinal = state.currentTurnId ? Number.parseInt(state.currentTurnId.replace(/^turn_/, ""), 10) : Number.NaN;
|
|
7089
|
+
const turnOrdinal = Number.isFinite(nextOrdinal) ? nextOrdinal + 1 : 0;
|
|
7090
|
+
const turnId = `turn_${turnOrdinal}`;
|
|
7091
|
+
state.startTurn(turnId, ts);
|
|
7092
|
+
push(baseKimiEvent({
|
|
7093
|
+
ts,
|
|
7094
|
+
type: "turn.started",
|
|
7095
|
+
sessionId,
|
|
7096
|
+
turnId,
|
|
7097
|
+
cwd,
|
|
7098
|
+
project,
|
|
7099
|
+
model,
|
|
7100
|
+
provider,
|
|
7101
|
+
confidence: "exact"
|
|
7102
|
+
}), lineNumber, entryType);
|
|
7103
|
+
const promptText = extractTextParts(raw.input);
|
|
7104
|
+
push(baseKimiEvent({
|
|
7105
|
+
ts,
|
|
7106
|
+
type: "prompt.submitted",
|
|
7107
|
+
sessionId,
|
|
7108
|
+
turnId,
|
|
7109
|
+
cwd,
|
|
7110
|
+
project,
|
|
7111
|
+
model,
|
|
7112
|
+
provider,
|
|
7113
|
+
confidence: "exact",
|
|
7114
|
+
metrics: {
|
|
7115
|
+
prompts: 1,
|
|
7116
|
+
promptChars: promptText.length || void 0
|
|
7117
|
+
},
|
|
7118
|
+
refs: stringRefs({
|
|
7119
|
+
promptHash: promptText ? `sha256:${createStableHash(promptText)}` : void 0
|
|
7120
|
+
})
|
|
7121
|
+
}), lineNumber, entryType);
|
|
7122
|
+
continue;
|
|
7123
|
+
}
|
|
7124
|
+
if (entryType === "llm.request") {
|
|
7125
|
+
state.ensureSessionStarted(ts, lineNumber, entryType);
|
|
7126
|
+
model = stringField(raw, "modelAlias") || stringField(raw, "model") || model;
|
|
7127
|
+
provider = stringField(raw, "provider") || provider;
|
|
7128
|
+
reasoningEffort = stringField(raw, "thinkingEffort") || reasoningEffort;
|
|
7129
|
+
const turnStep = stringField(raw, "turnStep");
|
|
7130
|
+
if (turnStep && !state.currentTurnId) {
|
|
7131
|
+
const turnPart = turnStep.split(".")[0];
|
|
7132
|
+
const turnId = normalizeTurnId(turnPart);
|
|
7133
|
+
if (turnId) {
|
|
7134
|
+
state.startTurn(turnId, ts);
|
|
7135
|
+
}
|
|
7136
|
+
}
|
|
7137
|
+
continue;
|
|
7138
|
+
}
|
|
7139
|
+
if (entryType === "usage.record") {
|
|
7140
|
+
state.ensureSessionStarted(ts, lineNumber, entryType);
|
|
7141
|
+
sawUsageRecord = true;
|
|
7142
|
+
model = stringField(raw, "model") || model;
|
|
7143
|
+
const usage = objectField(raw, "usage");
|
|
7144
|
+
const metrics = kimiUsageFromRecord(usage);
|
|
7145
|
+
if (metrics) {
|
|
7146
|
+
if (reasoningEffort) {
|
|
7147
|
+
metrics.reasoningEffort = reasoningEffort;
|
|
7148
|
+
}
|
|
7149
|
+
push(baseKimiEvent({
|
|
7150
|
+
ts,
|
|
7151
|
+
type: "model.usage",
|
|
7152
|
+
sessionId,
|
|
7153
|
+
turnId: state.currentTurnId,
|
|
7154
|
+
cwd,
|
|
7155
|
+
project,
|
|
7156
|
+
model,
|
|
7157
|
+
provider,
|
|
7158
|
+
confidence: "exact",
|
|
7159
|
+
metrics
|
|
7160
|
+
}), lineNumber, entryType);
|
|
7161
|
+
}
|
|
7162
|
+
continue;
|
|
7163
|
+
}
|
|
7164
|
+
if (entryType === "context.append_loop_event") {
|
|
7165
|
+
state.ensureSessionStarted(ts, lineNumber, entryType);
|
|
7166
|
+
const loopEvent = objectField(raw, "event");
|
|
7167
|
+
const loopType = stringField(loopEvent, "type");
|
|
7168
|
+
const turnId = normalizeTurnId(loopEvent.turnId) || state.currentTurnId;
|
|
7169
|
+
if (turnId && turnId !== state.currentTurnId) {
|
|
7170
|
+
if (state.currentTurnId) {
|
|
7171
|
+
state.closeTurn(ts, lineNumber, entryType);
|
|
7172
|
+
}
|
|
7173
|
+
state.startTurn(turnId, ts);
|
|
7174
|
+
}
|
|
7175
|
+
if (loopType === "tool.call") {
|
|
7176
|
+
const toolCallId = stringField(loopEvent, "toolCallId") || stringField(loopEvent, "uuid");
|
|
7177
|
+
const toolName = stringField(loopEvent, "name") || "tool";
|
|
7178
|
+
const toolInput = isPlainObject(loopEvent.args) ? loopEvent.args : {};
|
|
7179
|
+
if (toolCallId) {
|
|
7180
|
+
pendingToolCalls.set(toolCallId, {
|
|
7181
|
+
toolName,
|
|
7182
|
+
startedAt: ts,
|
|
7183
|
+
turnId: turnId || state.currentTurnId,
|
|
7184
|
+
input: toolInput
|
|
7185
|
+
});
|
|
7186
|
+
}
|
|
7187
|
+
push(baseKimiEvent({
|
|
7188
|
+
ts,
|
|
7189
|
+
type: "tool.started",
|
|
7190
|
+
operation: `${toolName} started`,
|
|
7191
|
+
sessionId,
|
|
7192
|
+
turnId: turnId || state.currentTurnId,
|
|
7193
|
+
cwd,
|
|
7194
|
+
project,
|
|
7195
|
+
model,
|
|
7196
|
+
provider,
|
|
7197
|
+
tool: toolName,
|
|
7198
|
+
confidence: "exact",
|
|
7199
|
+
metrics: { toolCalls: 1 },
|
|
7200
|
+
refs: stringRefs({
|
|
7201
|
+
sourceId: toolCallId,
|
|
7202
|
+
commandHash: toolName.toLowerCase() === "bash" && stringField(toolInput, "command") ? createStableHash(stringField(toolInput, "command")) : void 0
|
|
7203
|
+
})
|
|
7204
|
+
}), lineNumber, entryType);
|
|
7205
|
+
const fileActivities = claudeStyleToolFileActivities(
|
|
7206
|
+
toolName,
|
|
7207
|
+
toolInput,
|
|
7208
|
+
ts,
|
|
7209
|
+
cwd
|
|
7210
|
+
);
|
|
7211
|
+
if (fileActivities.length > 0) {
|
|
7212
|
+
push(baseKimiEvent({
|
|
7213
|
+
ts,
|
|
7214
|
+
type: eventTypeFromFileActivities(fileActivities),
|
|
7215
|
+
operation: `${toolName} file activity`,
|
|
7216
|
+
sessionId,
|
|
7217
|
+
turnId: turnId || state.currentTurnId,
|
|
7218
|
+
cwd,
|
|
7219
|
+
project,
|
|
7220
|
+
model,
|
|
7221
|
+
provider,
|
|
7222
|
+
tool: toolName,
|
|
7223
|
+
confidence: "derived",
|
|
7224
|
+
fileActivities,
|
|
7225
|
+
metrics: summarizeFileActivities(fileActivities),
|
|
7226
|
+
refs: stringRefs({ sourceId: toolCallId })
|
|
7227
|
+
}), lineNumber, entryType);
|
|
7228
|
+
}
|
|
7229
|
+
continue;
|
|
7230
|
+
}
|
|
7231
|
+
if (loopType === "tool.result") {
|
|
7232
|
+
const toolCallId = stringField(loopEvent, "toolCallId");
|
|
7233
|
+
const pending = toolCallId ? pendingToolCalls.get(toolCallId) : void 0;
|
|
7234
|
+
if (toolCallId) {
|
|
7235
|
+
pendingToolCalls.delete(toolCallId);
|
|
7236
|
+
}
|
|
7237
|
+
const result = objectField(loopEvent, "result");
|
|
7238
|
+
const isError = Boolean(result.isError);
|
|
7239
|
+
const toolName = pending?.toolName || "tool";
|
|
7240
|
+
const durationMs = pending ? durationMsBetween(pending.startedAt, ts) : void 0;
|
|
7241
|
+
push(baseKimiEvent({
|
|
7242
|
+
ts,
|
|
7243
|
+
type: isError ? "tool.failed" : "tool.completed",
|
|
7244
|
+
operation: isError ? `${toolName} failed` : `${toolName} completed`,
|
|
7245
|
+
sessionId,
|
|
7246
|
+
turnId: pending?.turnId || turnId || state.currentTurnId,
|
|
7247
|
+
cwd,
|
|
7248
|
+
project,
|
|
7249
|
+
model,
|
|
7250
|
+
provider,
|
|
7251
|
+
tool: toolName,
|
|
7252
|
+
success: !isError,
|
|
7253
|
+
confidence: "exact",
|
|
7254
|
+
metrics: {
|
|
7255
|
+
toolDurationMs: durationMs,
|
|
7256
|
+
durationMs
|
|
7257
|
+
},
|
|
7258
|
+
refs: stringRefs({ sourceId: toolCallId })
|
|
7259
|
+
}), lineNumber, entryType);
|
|
7260
|
+
if (toolName.toLowerCase() === "bash") {
|
|
7261
|
+
push(baseKimiEvent({
|
|
7262
|
+
ts,
|
|
7263
|
+
type: isError ? "command.failed" : "command.completed",
|
|
7264
|
+
operation: "command completed",
|
|
7265
|
+
sessionId,
|
|
7266
|
+
turnId: pending?.turnId || turnId || state.currentTurnId,
|
|
7267
|
+
cwd,
|
|
7268
|
+
project,
|
|
7269
|
+
model,
|
|
7270
|
+
provider,
|
|
7271
|
+
tool: "Bash",
|
|
7272
|
+
success: !isError,
|
|
7273
|
+
confidence: "derived",
|
|
7274
|
+
metrics: {
|
|
7275
|
+
commandCalls: 1,
|
|
7276
|
+
commandDurationMs: durationMs,
|
|
7277
|
+
durationMs
|
|
7278
|
+
},
|
|
7279
|
+
refs: stringRefs({
|
|
7280
|
+
sourceId: toolCallId,
|
|
7281
|
+
commandHash: pending?.input.command ? `sha256:${createStableHash(String(pending.input.command))}` : void 0
|
|
7282
|
+
})
|
|
7283
|
+
}), lineNumber, entryType);
|
|
7284
|
+
}
|
|
7285
|
+
continue;
|
|
7286
|
+
}
|
|
7287
|
+
if (loopType === "step.end") {
|
|
7288
|
+
if (!sawUsageRecord) {
|
|
7289
|
+
const streamMs = numberField(loopEvent, "llmStreamDurationMs") || numberField(loopEvent, "llmServerDecodeMs");
|
|
7290
|
+
const usage = objectField(loopEvent, "usage");
|
|
7291
|
+
const metrics = kimiUsageFromRecord(usage);
|
|
7292
|
+
if (metrics) {
|
|
7293
|
+
if (streamMs) {
|
|
7294
|
+
metrics.modelDurationMs = streamMs;
|
|
7295
|
+
}
|
|
7296
|
+
if (reasoningEffort) {
|
|
7297
|
+
metrics.reasoningEffort = reasoningEffort;
|
|
7298
|
+
}
|
|
7299
|
+
push(baseKimiEvent({
|
|
7300
|
+
ts,
|
|
7301
|
+
type: "model.usage",
|
|
7302
|
+
sessionId,
|
|
7303
|
+
turnId: turnId || state.currentTurnId,
|
|
7304
|
+
cwd,
|
|
7305
|
+
project,
|
|
7306
|
+
model,
|
|
7307
|
+
provider,
|
|
7308
|
+
confidence: "exact",
|
|
7309
|
+
metrics
|
|
7310
|
+
}), lineNumber, entryType);
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7313
|
+
continue;
|
|
7314
|
+
}
|
|
7315
|
+
continue;
|
|
7316
|
+
}
|
|
7317
|
+
if (entryType === "interaction.request") {
|
|
7318
|
+
state.ensureSessionStarted(ts, lineNumber, entryType);
|
|
7319
|
+
const requestId = stringField(raw, "id") || stringField(raw, "toolCallId");
|
|
7320
|
+
const request2 = objectField(raw, "request");
|
|
7321
|
+
const toolName = stringField(request2, "toolName") || stringField(raw, "toolName");
|
|
7322
|
+
const turnId = normalizeTurnId(request2.turnId) || state.currentTurnId;
|
|
7323
|
+
if (requestId) {
|
|
7324
|
+
pendingPermissions.set(requestId, { toolName, startedAt: ts, turnId });
|
|
7325
|
+
}
|
|
7326
|
+
push(baseKimiEvent({
|
|
7327
|
+
ts,
|
|
7328
|
+
type: "permission.requested",
|
|
7329
|
+
operation: toolName ? `${toolName} permission` : "permission requested",
|
|
7330
|
+
sessionId,
|
|
7331
|
+
turnId,
|
|
7332
|
+
cwd,
|
|
7333
|
+
project,
|
|
7334
|
+
model,
|
|
7335
|
+
provider,
|
|
7336
|
+
tool: toolName,
|
|
7337
|
+
confidence: "exact",
|
|
7338
|
+
refs: stringRefs({ sourceId: requestId })
|
|
7339
|
+
}), lineNumber, entryType);
|
|
7340
|
+
continue;
|
|
7341
|
+
}
|
|
7342
|
+
if (entryType === "interaction.resolved") {
|
|
7343
|
+
state.ensureSessionStarted(ts, lineNumber, entryType);
|
|
7344
|
+
const requestId = stringField(raw, "id");
|
|
7345
|
+
const pending = requestId ? pendingPermissions.get(requestId) : void 0;
|
|
7346
|
+
if (requestId) {
|
|
7347
|
+
pendingPermissions.delete(requestId);
|
|
7348
|
+
}
|
|
7349
|
+
const response = objectField(raw, "response");
|
|
7350
|
+
const decision = stringField(response, "decision") || stringField(raw, "decision");
|
|
7351
|
+
const granted = decision === "approved" || decision === "allow" || decision === "granted";
|
|
7352
|
+
const denied = decision === "denied" || decision === "reject" || decision === "rejected";
|
|
7353
|
+
push(baseKimiEvent({
|
|
7354
|
+
ts,
|
|
7355
|
+
type: granted ? "permission.granted" : denied ? "permission.denied" : "permission.resolved",
|
|
7356
|
+
operation: decision ? `permission ${decision}` : "permission resolved",
|
|
7357
|
+
sessionId,
|
|
7358
|
+
turnId: pending?.turnId || state.currentTurnId,
|
|
7359
|
+
cwd,
|
|
7360
|
+
project,
|
|
7361
|
+
model,
|
|
7362
|
+
provider,
|
|
7363
|
+
tool: pending?.toolName,
|
|
7364
|
+
success: granted ? true : denied ? false : void 0,
|
|
7365
|
+
confidence: "exact",
|
|
7366
|
+
metrics: {
|
|
7367
|
+
durationMs: pending ? durationMsBetween(pending.startedAt, ts) : void 0,
|
|
7368
|
+
approvalWaitMs: pending ? durationMsBetween(pending.startedAt, ts) : void 0
|
|
7369
|
+
},
|
|
7370
|
+
refs: stringRefs({ sourceId: requestId })
|
|
7371
|
+
}), lineNumber, entryType);
|
|
7372
|
+
continue;
|
|
7373
|
+
}
|
|
7374
|
+
}
|
|
7375
|
+
if (isTurnIdle(state.currentTurnLastEventAt)) {
|
|
7376
|
+
state.closeTurn(state.currentTurnLastEventAt, lines.length);
|
|
7377
|
+
}
|
|
7378
|
+
return state.events.filter((event) => matchesBackfillFilters(event, options));
|
|
7379
|
+
}
|
|
7380
|
+
function createKimiCodeAdapter() {
|
|
7381
|
+
return {
|
|
7382
|
+
id: "kimi-code",
|
|
7383
|
+
label: "Kimi Code",
|
|
7384
|
+
agentName: "kimi-code",
|
|
7385
|
+
kind: "agent",
|
|
7386
|
+
detectPath(home, env) {
|
|
7387
|
+
return kimiCodeHome(home, env);
|
|
7388
|
+
},
|
|
7389
|
+
installedPath(home, env) {
|
|
7390
|
+
return path14.join(kimiCodeHome(home, env), "vibetime-marker");
|
|
7391
|
+
},
|
|
7392
|
+
async isInstalled() {
|
|
7393
|
+
return false;
|
|
7394
|
+
},
|
|
7395
|
+
installEntries(_home, _env) {
|
|
7396
|
+
return [];
|
|
7397
|
+
},
|
|
7398
|
+
sourcePaths(home, env) {
|
|
7399
|
+
return [kimiCodeSessionsDir(home, env)];
|
|
7400
|
+
},
|
|
7401
|
+
parseSessionFile: parseKimiCodeSessionFile
|
|
7402
|
+
};
|
|
7403
|
+
}
|
|
7404
|
+
|
|
6938
7405
|
// src/adapters/opencode.ts
|
|
6939
7406
|
import os6 from "node:os";
|
|
6940
|
-
import
|
|
7407
|
+
import path15 from "node:path";
|
|
6941
7408
|
async function parseOpenCodeSessionFile(dbPath, options) {
|
|
6942
7409
|
const { DatabaseSync } = await import("node:sqlite");
|
|
6943
7410
|
if (!dbPath.endsWith(".db")) {
|
|
@@ -6994,7 +7461,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
6994
7461
|
const rawSessionId = session.id;
|
|
6995
7462
|
const sessionId = rootIdByRawId.get(rawSessionId) || rawSessionId;
|
|
6996
7463
|
const cwd = session.directory || session.path || void 0;
|
|
6997
|
-
const project = cwd ?
|
|
7464
|
+
const project = cwd ? path15.basename(cwd) : void 0;
|
|
6998
7465
|
const sessionTs = msToIso(session.time_created);
|
|
6999
7466
|
events.push(baseOpenCodeEvent({
|
|
7000
7467
|
ts: sessionTs,
|
|
@@ -7102,7 +7569,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
7102
7569
|
const provider = currentProvider;
|
|
7103
7570
|
const pathObj = objectField(info, "path");
|
|
7104
7571
|
const assistantCwd = stringField(pathObj, "cwd") || cwd;
|
|
7105
|
-
const assistantProject = assistantCwd ?
|
|
7572
|
+
const assistantProject = assistantCwd ? path15.basename(assistantCwd) : project;
|
|
7106
7573
|
const completedTs = numberField(objectField(info, "time"), "completed");
|
|
7107
7574
|
const createdTs = timeCreated;
|
|
7108
7575
|
const tokens = opencodeUsageFromInfo(info);
|
|
@@ -7373,18 +7840,18 @@ function opencodeUsageFromInfo(info) {
|
|
|
7373
7840
|
function opencodeConfigDir(home, env) {
|
|
7374
7841
|
const override = env?.OPENCODE_CONFIG_DIR;
|
|
7375
7842
|
if (override && override.trim()) {
|
|
7376
|
-
return
|
|
7843
|
+
return path15.resolve(override);
|
|
7377
7844
|
}
|
|
7378
7845
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
7379
7846
|
if (xdgConfig && xdgConfig.trim()) {
|
|
7380
|
-
return
|
|
7847
|
+
return path15.join(path15.resolve(xdgConfig), "opencode");
|
|
7381
7848
|
}
|
|
7382
|
-
return
|
|
7849
|
+
return path15.join(home, ".config", "opencode");
|
|
7383
7850
|
}
|
|
7384
7851
|
function opencodeDataCandidates(home, env) {
|
|
7385
7852
|
const xdgData = env?.XDG_DATA_HOME;
|
|
7386
|
-
const primary = xdgData && xdgData.trim() ?
|
|
7387
|
-
return [primary,
|
|
7853
|
+
const primary = xdgData && xdgData.trim() ? path15.join(path15.resolve(xdgData), "opencode", "opencode.db") : path15.join(home, ".local", "share", "opencode", "opencode.db");
|
|
7854
|
+
return [primary, path15.join(home, ".opencode", "opencode.db")];
|
|
7388
7855
|
}
|
|
7389
7856
|
async function opencodeBackfillFiles(sourceRoot, home = os6.homedir(), env) {
|
|
7390
7857
|
const { stat: stat14 } = await import("node:fs/promises");
|
|
@@ -7474,12 +7941,12 @@ function createOpenCodeAdapter() {
|
|
|
7474
7941
|
return opencodeConfigDir(home, env);
|
|
7475
7942
|
},
|
|
7476
7943
|
installedPath(home, env) {
|
|
7477
|
-
return
|
|
7944
|
+
return path15.join(opencodeConfigDir(home, env), PLUGIN_PATH);
|
|
7478
7945
|
},
|
|
7479
7946
|
async isInstalled(home, env) {
|
|
7480
7947
|
try {
|
|
7481
7948
|
const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
7482
|
-
return await pathExists2(
|
|
7949
|
+
return await pathExists2(path15.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path15.join(".opencode", PLUGIN_PATH));
|
|
7483
7950
|
} catch {
|
|
7484
7951
|
return false;
|
|
7485
7952
|
}
|
|
@@ -7487,7 +7954,7 @@ function createOpenCodeAdapter() {
|
|
|
7487
7954
|
installEntries(home, env) {
|
|
7488
7955
|
return [{
|
|
7489
7956
|
kind: "file",
|
|
7490
|
-
path:
|
|
7957
|
+
path: path15.join(opencodeConfigDir(home, env), PLUGIN_PATH),
|
|
7491
7958
|
content: opencodePluginContent()
|
|
7492
7959
|
}];
|
|
7493
7960
|
},
|
|
@@ -7499,12 +7966,12 @@ function createOpenCodeAdapter() {
|
|
|
7499
7966
|
}
|
|
7500
7967
|
|
|
7501
7968
|
// src/adapters/pi.ts
|
|
7502
|
-
import { readFile as
|
|
7503
|
-
import
|
|
7969
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
7970
|
+
import path16 from "node:path";
|
|
7504
7971
|
function parsePiSubagentLink(filePath, headerParentSession) {
|
|
7505
7972
|
if (headerParentSession) {
|
|
7506
|
-
const parentFile =
|
|
7507
|
-
const parentSessionId2 = parentFile ?
|
|
7973
|
+
const parentFile = path16.isAbsolute(headerParentSession) ? headerParentSession : void 0;
|
|
7974
|
+
const parentSessionId2 = parentFile ? path16.basename(parentFile, ".jsonl") : headerParentSession;
|
|
7508
7975
|
return { parentSessionId: parentSessionId2, parentSessionFile: parentFile, explicit: true };
|
|
7509
7976
|
}
|
|
7510
7977
|
const normalized = filePath.replaceAll("\\", "/");
|
|
@@ -7517,20 +7984,20 @@ function parsePiSubagentLink(filePath, headerParentSession) {
|
|
|
7517
7984
|
return void 0;
|
|
7518
7985
|
}
|
|
7519
7986
|
const parentSessionId = parentBasename.endsWith(".jsonl") ? parentBasename.slice(0, -".jsonl".length) : parentBasename;
|
|
7520
|
-
const parentDir =
|
|
7521
|
-
const parentSessionFile =
|
|
7987
|
+
const parentDir = path16.dirname(path16.dirname(path16.dirname(filePath)));
|
|
7988
|
+
const parentSessionFile = path16.join(path16.dirname(parentDir), `${parentBasename}.jsonl`);
|
|
7522
7989
|
return { parentSessionId, parentSessionFile, explicit: false };
|
|
7523
7990
|
}
|
|
7524
7991
|
async function resolveParentContext(link, options) {
|
|
7525
7992
|
if (link.parentSessionFile) {
|
|
7526
7993
|
try {
|
|
7527
|
-
const text = await
|
|
7994
|
+
const text = await readFile10(link.parentSessionFile, "utf8");
|
|
7528
7995
|
const firstLine = text.split("\n").find((line) => line.trim().length > 0);
|
|
7529
7996
|
const raw = firstLine ? parseJsonLine(firstLine) : void 0;
|
|
7530
7997
|
if (raw) {
|
|
7531
7998
|
const id = stringField(raw, "id");
|
|
7532
7999
|
const cwd = stringField(raw, "cwd");
|
|
7533
|
-
const project = cwd ?
|
|
8000
|
+
const project = cwd ? path16.basename(cwd) : void 0;
|
|
7534
8001
|
if (id || cwd || project) {
|
|
7535
8002
|
return { sessionId: id, cwd, project };
|
|
7536
8003
|
}
|
|
@@ -7575,7 +8042,7 @@ function rebuildEventIdentity2(event) {
|
|
|
7575
8042
|
};
|
|
7576
8043
|
}
|
|
7577
8044
|
async function parsePiSessionFile(filePath, options) {
|
|
7578
|
-
const text = await
|
|
8045
|
+
const text = await readFile10(filePath, "utf8");
|
|
7579
8046
|
const lines = text.split("\n").filter(Boolean);
|
|
7580
8047
|
let sessionId;
|
|
7581
8048
|
let cwd;
|
|
@@ -7607,7 +8074,7 @@ async function parsePiSessionFile(filePath, options) {
|
|
|
7607
8074
|
sessionId = stringField(raw, "id") || state.sessionId;
|
|
7608
8075
|
state.sessionId = sessionId || state.sessionId;
|
|
7609
8076
|
cwd = stringField(raw, "cwd") || cwd;
|
|
7610
|
-
project = cwd ?
|
|
8077
|
+
project = cwd ? path16.basename(cwd) : project;
|
|
7611
8078
|
headerParentSession = stringField(raw, "parentSession") || headerParentSession;
|
|
7612
8079
|
continue;
|
|
7613
8080
|
}
|
|
@@ -8040,16 +8507,16 @@ export default function (pi: ExtensionAPI) {
|
|
|
8040
8507
|
function piAgentDir(home, env) {
|
|
8041
8508
|
const override = env?.PI_CODING_AGENT_DIR;
|
|
8042
8509
|
if (override && override.trim()) {
|
|
8043
|
-
return
|
|
8510
|
+
return path16.resolve(override);
|
|
8044
8511
|
}
|
|
8045
|
-
return
|
|
8512
|
+
return path16.join(home, ".pi", "agent");
|
|
8046
8513
|
}
|
|
8047
8514
|
function piSessionDir(home, env) {
|
|
8048
8515
|
const override = env?.PI_CODING_AGENT_SESSION_DIR;
|
|
8049
8516
|
if (override && override.trim()) {
|
|
8050
|
-
return
|
|
8517
|
+
return path16.resolve(override);
|
|
8051
8518
|
}
|
|
8052
|
-
return
|
|
8519
|
+
return path16.join(piAgentDir(home, env), "sessions");
|
|
8053
8520
|
}
|
|
8054
8521
|
function createPiAdapter() {
|
|
8055
8522
|
return {
|
|
@@ -8061,12 +8528,12 @@ function createPiAdapter() {
|
|
|
8061
8528
|
return piAgentDir(home, env);
|
|
8062
8529
|
},
|
|
8063
8530
|
installedPath(home, env) {
|
|
8064
|
-
return
|
|
8531
|
+
return path16.join(piAgentDir(home, env), "extensions", "vibetime.ts");
|
|
8065
8532
|
},
|
|
8066
8533
|
async isInstalled(home, env) {
|
|
8067
8534
|
try {
|
|
8068
8535
|
const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
8069
|
-
return await pathExists2(
|
|
8536
|
+
return await pathExists2(path16.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
|
|
8070
8537
|
} catch {
|
|
8071
8538
|
return false;
|
|
8072
8539
|
}
|
|
@@ -8074,7 +8541,7 @@ function createPiAdapter() {
|
|
|
8074
8541
|
installEntries(home, env) {
|
|
8075
8542
|
return [{
|
|
8076
8543
|
kind: "file",
|
|
8077
|
-
path:
|
|
8544
|
+
path: path16.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
|
|
8078
8545
|
content: piExtensionContent()
|
|
8079
8546
|
}];
|
|
8080
8547
|
},
|
|
@@ -8086,14 +8553,14 @@ function createPiAdapter() {
|
|
|
8086
8553
|
}
|
|
8087
8554
|
|
|
8088
8555
|
// src/adapters/qoder-cn.ts
|
|
8089
|
-
import { readdir as readdir7, readFile as
|
|
8556
|
+
import { readdir as readdir7, readFile as readFile11, stat as stat8 } from "node:fs/promises";
|
|
8090
8557
|
import os8 from "node:os";
|
|
8091
|
-
import
|
|
8558
|
+
import path18 from "node:path";
|
|
8092
8559
|
|
|
8093
8560
|
// src/adapters/qoder-local-db.ts
|
|
8094
8561
|
import { access } from "node:fs/promises";
|
|
8095
8562
|
import os7 from "node:os";
|
|
8096
|
-
import
|
|
8563
|
+
import path17 from "node:path";
|
|
8097
8564
|
function takeQoderDbModelCall(calls, requestId, blockStart) {
|
|
8098
8565
|
if (requestId) {
|
|
8099
8566
|
const call = calls.byRequestId.get(requestId)?.shift();
|
|
@@ -8112,12 +8579,12 @@ function takeQoderDbModelCall(calls, requestId, blockStart) {
|
|
|
8112
8579
|
}
|
|
8113
8580
|
function appDataRoot(appDirName, home = os7.homedir()) {
|
|
8114
8581
|
if (process.platform === "darwin") {
|
|
8115
|
-
return
|
|
8582
|
+
return path17.join(home, "Library", "Application Support", appDirName);
|
|
8116
8583
|
}
|
|
8117
8584
|
if (process.platform === "win32") {
|
|
8118
|
-
return
|
|
8585
|
+
return path17.join(process.env.APPDATA || path17.join(home, "AppData", "Roaming"), appDirName);
|
|
8119
8586
|
}
|
|
8120
|
-
return
|
|
8587
|
+
return path17.join(home, ".config", appDirName);
|
|
8121
8588
|
}
|
|
8122
8589
|
function qoderLocalDbCandidates(appDirName) {
|
|
8123
8590
|
const candidates = [];
|
|
@@ -8127,8 +8594,8 @@ function qoderLocalDbCandidates(appDirName) {
|
|
|
8127
8594
|
}
|
|
8128
8595
|
const configRoot = appDataRoot(appDirName);
|
|
8129
8596
|
candidates.push(
|
|
8130
|
-
|
|
8131
|
-
|
|
8597
|
+
path17.join(configRoot, "SharedClientCache", "cache", "db", "local.db"),
|
|
8598
|
+
path17.join(configRoot, "SharedClientCache", "db", "local.db")
|
|
8132
8599
|
);
|
|
8133
8600
|
return candidates;
|
|
8134
8601
|
}
|
|
@@ -8137,7 +8604,7 @@ async function loadQoderIdeModelCatalog(appDirName, home) {
|
|
|
8137
8604
|
try {
|
|
8138
8605
|
const { DatabaseSync } = await import("node:sqlite");
|
|
8139
8606
|
const db = new DatabaseSync(
|
|
8140
|
-
|
|
8607
|
+
path17.join(appDataRoot(appDirName, home), "User", "globalStorage", "state.vscdb"),
|
|
8141
8608
|
{ readOnly: true }
|
|
8142
8609
|
);
|
|
8143
8610
|
try {
|
|
@@ -8279,7 +8746,7 @@ function resolveSessionPreferredModel(db, sessionId, modelMap) {
|
|
|
8279
8746
|
|
|
8280
8747
|
// src/adapters/qoder-cn.ts
|
|
8281
8748
|
function parseQoderCnPaths(filePath) {
|
|
8282
|
-
const parts = filePath.split(
|
|
8749
|
+
const parts = filePath.split(path18.sep);
|
|
8283
8750
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
8284
8751
|
let sessionId = "";
|
|
8285
8752
|
let projectName = "";
|
|
@@ -8289,17 +8756,17 @@ function parseQoderCnPaths(filePath) {
|
|
|
8289
8756
|
sessionId = parts[subagentsIdx - 1];
|
|
8290
8757
|
projectName = parts[subagentsIdx - 2];
|
|
8291
8758
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8292
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
8293
|
-
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(
|
|
8759
|
+
configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
|
|
8760
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path18.sep);
|
|
8294
8761
|
} else {
|
|
8295
8762
|
const filename = parts.at(-1) || "";
|
|
8296
|
-
sessionId =
|
|
8763
|
+
sessionId = path18.basename(filename, ".jsonl");
|
|
8297
8764
|
projectName = parts.at(-2) || "";
|
|
8298
8765
|
if (projectName === "transcript") {
|
|
8299
8766
|
projectName = parts.at(-3) || "";
|
|
8300
8767
|
}
|
|
8301
8768
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
8302
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
8769
|
+
configDir2 = parts.slice(0, projectsIdx).join(path18.sep);
|
|
8303
8770
|
}
|
|
8304
8771
|
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
8305
8772
|
}
|
|
@@ -8322,7 +8789,7 @@ function rebuildEventIdentity3(event) {
|
|
|
8322
8789
|
}
|
|
8323
8790
|
async function parseModelNamesFromDynamicTexts(dynamicTextsPath) {
|
|
8324
8791
|
try {
|
|
8325
|
-
const content = await
|
|
8792
|
+
const content = await readFile11(dynamicTextsPath, "utf8");
|
|
8326
8793
|
const json = JSON.parse(content);
|
|
8327
8794
|
const texts = json.texts || {};
|
|
8328
8795
|
const map = {};
|
|
@@ -8338,10 +8805,10 @@ async function parseModelNamesFromDynamicTexts(dynamicTextsPath) {
|
|
|
8338
8805
|
}
|
|
8339
8806
|
}
|
|
8340
8807
|
async function loadQoderCnModelNames(configDir2, home) {
|
|
8341
|
-
const map = await parseModelNamesFromDynamicTexts(
|
|
8808
|
+
const map = await parseModelNamesFromDynamicTexts(path18.join(configDir2, ".auth", "dynamic-texts.json"));
|
|
8342
8809
|
const siblingConfigDir = configDir2.replace(/\.qoder-cn$/, ".qoder");
|
|
8343
8810
|
if (siblingConfigDir !== configDir2) {
|
|
8344
|
-
const siblingMap = await parseModelNamesFromDynamicTexts(
|
|
8811
|
+
const siblingMap = await parseModelNamesFromDynamicTexts(path18.join(siblingConfigDir, ".auth", "dynamic-texts.json"));
|
|
8345
8812
|
for (const [key, val] of Object.entries(siblingMap)) {
|
|
8346
8813
|
if (!(key in map)) {
|
|
8347
8814
|
map[key] = val;
|
|
@@ -8360,7 +8827,7 @@ async function loadQoderCnModelNames(configDir2, home) {
|
|
|
8360
8827
|
}
|
|
8361
8828
|
async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
8362
8829
|
const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
|
|
8363
|
-
const segmentsPath =
|
|
8830
|
+
const segmentsPath = path18.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
8364
8831
|
const modelCalls = [];
|
|
8365
8832
|
try {
|
|
8366
8833
|
const files = await readdir7(segmentsPath);
|
|
@@ -8368,7 +8835,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
|
|
|
8368
8835
|
if (!file.endsWith(".jsonl")) {
|
|
8369
8836
|
continue;
|
|
8370
8837
|
}
|
|
8371
|
-
const content = await
|
|
8838
|
+
const content = await readFile11(path18.join(segmentsPath, file), "utf8");
|
|
8372
8839
|
let currentTurnIsSubagent = false;
|
|
8373
8840
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
8374
8841
|
const raw = parseJsonLine(line);
|
|
@@ -8402,7 +8869,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
|
|
|
8402
8869
|
return modelCalls.filter((call) => call.isSubagent === isSubagentSession);
|
|
8403
8870
|
}
|
|
8404
8871
|
async function parseQoderCnSessionFile(filePath, options) {
|
|
8405
|
-
const text = await
|
|
8872
|
+
const text = await readFile11(filePath, "utf8");
|
|
8406
8873
|
const lines = text.split("\n").filter(Boolean);
|
|
8407
8874
|
const parsedPaths = parseQoderCnPaths(filePath);
|
|
8408
8875
|
const { configDir: configDir2 } = parsedPaths;
|
|
@@ -8413,7 +8880,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
8413
8880
|
let cwd;
|
|
8414
8881
|
let project = projectContext.project;
|
|
8415
8882
|
let model;
|
|
8416
|
-
const home =
|
|
8883
|
+
const home = path18.resolve(stringOption(options.home) || os8.homedir());
|
|
8417
8884
|
const modelMap = await loadQoderCnModelNames(configDir2, home);
|
|
8418
8885
|
const isSubagentSession = filePath.includes("subagents");
|
|
8419
8886
|
const segmentModelCalls = await loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap);
|
|
@@ -8448,7 +8915,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
8448
8915
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
8449
8916
|
state.sessionId = sessionId;
|
|
8450
8917
|
cwd = stringField(raw, "cwd") || cwd;
|
|
8451
|
-
project = projectContext.project || (cwd ?
|
|
8918
|
+
project = projectContext.project || (cwd ? path18.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
|
|
8452
8919
|
if (!ts) {
|
|
8453
8920
|
continue;
|
|
8454
8921
|
}
|
|
@@ -8533,6 +9000,41 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
8533
9000
|
}
|
|
8534
9001
|
pendingTools.delete(pending.id);
|
|
8535
9002
|
}
|
|
9003
|
+
const attachedPrompt = extractQoderAttachedPrompt(qoderCnToolResultItems(message)[0]?.content);
|
|
9004
|
+
if (attachedPrompt) {
|
|
9005
|
+
const prompt = qoderCnTextStats(attachedPrompt);
|
|
9006
|
+
state.closeTurn(ts, lineNumber, topType);
|
|
9007
|
+
state.currentTurnId = stringField(raw, "uuid") || stringField(raw, "promptId") || `turn_${createStableHash([sessionId, lineNumber]).slice(0, 24)}`;
|
|
9008
|
+
state.currentTurnStartedAt = ts;
|
|
9009
|
+
state.currentTurnLastEventAt = ts;
|
|
9010
|
+
push(baseQoderCnEvent({
|
|
9011
|
+
ts,
|
|
9012
|
+
type: "turn.started",
|
|
9013
|
+
sessionId,
|
|
9014
|
+
turnId: state.currentTurnId,
|
|
9015
|
+
cwd,
|
|
9016
|
+
project,
|
|
9017
|
+
model,
|
|
9018
|
+
confidence: "derived"
|
|
9019
|
+
}), lineNumber, topType, "attached_prompt");
|
|
9020
|
+
push(baseQoderCnEvent({
|
|
9021
|
+
ts,
|
|
9022
|
+
type: "prompt.submitted",
|
|
9023
|
+
sessionId,
|
|
9024
|
+
turnId: state.currentTurnId,
|
|
9025
|
+
cwd,
|
|
9026
|
+
project,
|
|
9027
|
+
model,
|
|
9028
|
+
confidence: "exact",
|
|
9029
|
+
metrics: {
|
|
9030
|
+
prompts: 1,
|
|
9031
|
+
promptChars: prompt.chars
|
|
9032
|
+
},
|
|
9033
|
+
refs: stringRefs({
|
|
9034
|
+
promptHash: prompt.hash
|
|
9035
|
+
})
|
|
9036
|
+
}), lineNumber, topType, "attached_prompt");
|
|
9037
|
+
}
|
|
8536
9038
|
continue;
|
|
8537
9039
|
}
|
|
8538
9040
|
if (topType === "user") {
|
|
@@ -8748,7 +9250,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
8748
9250
|
}
|
|
8749
9251
|
dbModelCalls ??= await loadQoderDbModelCalls("QoderCN", parsedPaths.sessionId, modelMap);
|
|
8750
9252
|
if (dbModelCalls.rootSessionId) {
|
|
8751
|
-
const parentPath =
|
|
9253
|
+
const parentPath = path18.join(path18.dirname(filePath), `${dbModelCalls.rootSessionId}.jsonl`);
|
|
8752
9254
|
const parentSourcePathHash = `sha256:${createStableHash(parentPath)}`;
|
|
8753
9255
|
return validEvents.map((event) => rebuildEventIdentity3({
|
|
8754
9256
|
...event,
|
|
@@ -8874,30 +9376,54 @@ function isNoisePrompt(text) {
|
|
|
8874
9376
|
}
|
|
8875
9377
|
return false;
|
|
8876
9378
|
}
|
|
9379
|
+
function extractQoderAttachedPrompt(content) {
|
|
9380
|
+
let text;
|
|
9381
|
+
if (typeof content === "string") {
|
|
9382
|
+
text = content;
|
|
9383
|
+
} else if (Array.isArray(content)) {
|
|
9384
|
+
text = content.filter((it) => isPlainObject(it) && it.type === "text").map((it) => stringField(it, "text")).join("\n");
|
|
9385
|
+
} else {
|
|
9386
|
+
return void 0;
|
|
9387
|
+
}
|
|
9388
|
+
if (!text.includes("aicoding-text-field") || !text.includes("text-field-content")) {
|
|
9389
|
+
return void 0;
|
|
9390
|
+
}
|
|
9391
|
+
const fenceStart = text.indexOf("```");
|
|
9392
|
+
if (fenceStart === -1) {
|
|
9393
|
+
return void 0;
|
|
9394
|
+
}
|
|
9395
|
+
const afterFence = text.slice(fenceStart + 3);
|
|
9396
|
+
const fenceEnd = afterFence.indexOf("```");
|
|
9397
|
+
if (fenceEnd === -1) {
|
|
9398
|
+
return void 0;
|
|
9399
|
+
}
|
|
9400
|
+
const inner = afterFence.slice(0, fenceEnd);
|
|
9401
|
+
return inner.split("\n").map((line) => line.replace(/^\s*\d+->/, "")).join("\n").trim() || void 0;
|
|
9402
|
+
}
|
|
8877
9403
|
async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
8878
9404
|
const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
|
|
8879
|
-
const isSubagent = filePath.includes(`${
|
|
9405
|
+
const isSubagent = filePath.includes(`${path18.sep}subagents${path18.sep}`);
|
|
8880
9406
|
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
8881
9407
|
let cwds = [];
|
|
8882
9408
|
for (const line of lines) {
|
|
8883
9409
|
const raw = parseJsonLine(line);
|
|
8884
9410
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8885
|
-
if (cwd &&
|
|
9411
|
+
if (cwd && path18.isAbsolute(cwd)) {
|
|
8886
9412
|
cwds.push(cwd);
|
|
8887
9413
|
}
|
|
8888
9414
|
}
|
|
8889
9415
|
if (isSubagent) {
|
|
8890
|
-
if (inherited?.cwd &&
|
|
9416
|
+
if (inherited?.cwd && path18.isAbsolute(inherited.cwd)) {
|
|
8891
9417
|
cwds = [inherited.cwd];
|
|
8892
9418
|
} else {
|
|
8893
|
-
const parentSessionPath =
|
|
9419
|
+
const parentSessionPath = path18.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
8894
9420
|
try {
|
|
8895
|
-
const parentText = await
|
|
9421
|
+
const parentText = await readFile11(parentSessionPath, "utf8");
|
|
8896
9422
|
const parentCwds = [];
|
|
8897
9423
|
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
8898
9424
|
const raw = parseJsonLine(line);
|
|
8899
9425
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
8900
|
-
if (cwd &&
|
|
9426
|
+
if (cwd && path18.isAbsolute(cwd)) {
|
|
8901
9427
|
parentCwds.push(cwd);
|
|
8902
9428
|
}
|
|
8903
9429
|
}
|
|
@@ -8909,7 +9435,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
8909
9435
|
}
|
|
8910
9436
|
}
|
|
8911
9437
|
const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
|
|
8912
|
-
const project = inherited?.project || (cwds.length > 0 ?
|
|
9438
|
+
const project = inherited?.project || (cwds.length > 0 ? path18.basename(cwds[0]) : root ? path18.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
|
|
8913
9439
|
return {
|
|
8914
9440
|
project,
|
|
8915
9441
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -8918,15 +9444,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
8918
9444
|
async function gitRootFromCwds2(cwds) {
|
|
8919
9445
|
const seen = /* @__PURE__ */ new Set();
|
|
8920
9446
|
for (const cwd of cwds) {
|
|
8921
|
-
let current =
|
|
9447
|
+
let current = path18.resolve(cwd);
|
|
8922
9448
|
while (!seen.has(current)) {
|
|
8923
9449
|
seen.add(current);
|
|
8924
9450
|
try {
|
|
8925
|
-
await stat8(
|
|
9451
|
+
await stat8(path18.join(current, ".git"));
|
|
8926
9452
|
return current;
|
|
8927
9453
|
} catch {
|
|
8928
9454
|
}
|
|
8929
|
-
const parent =
|
|
9455
|
+
const parent = path18.dirname(current);
|
|
8930
9456
|
if (parent === current) {
|
|
8931
9457
|
break;
|
|
8932
9458
|
}
|
|
@@ -8937,12 +9463,12 @@ async function gitRootFromCwds2(cwds) {
|
|
|
8937
9463
|
}
|
|
8938
9464
|
function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
8939
9465
|
for (const cwd of cwds) {
|
|
8940
|
-
let current =
|
|
9466
|
+
let current = path18.resolve(cwd);
|
|
8941
9467
|
while (true) {
|
|
8942
9468
|
if (encodeQoderCnProjectPath(current) === projectDir) {
|
|
8943
9469
|
return current;
|
|
8944
9470
|
}
|
|
8945
|
-
const parent =
|
|
9471
|
+
const parent = path18.dirname(current);
|
|
8946
9472
|
if (parent === current) {
|
|
8947
9473
|
break;
|
|
8948
9474
|
}
|
|
@@ -8952,14 +9478,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
|
8952
9478
|
return void 0;
|
|
8953
9479
|
}
|
|
8954
9480
|
function encodeQoderCnProjectPath(value) {
|
|
8955
|
-
return
|
|
9481
|
+
return path18.resolve(value).split(path18.sep).join("-").replaceAll("_", "-");
|
|
8956
9482
|
}
|
|
8957
9483
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
8958
|
-
const projectDir =
|
|
8959
|
-
const home = options ?
|
|
9484
|
+
const projectDir = path18.basename(path18.dirname(filePath));
|
|
9485
|
+
const home = options ? path18.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
|
|
8960
9486
|
const resolved = await resolveQoderCnProjectPath(projectDir, home);
|
|
8961
9487
|
if (resolved) {
|
|
8962
|
-
return
|
|
9488
|
+
return path18.basename(resolved);
|
|
8963
9489
|
}
|
|
8964
9490
|
const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
|
|
8965
9491
|
if (projectDir.startsWith(homePrefix)) {
|
|
@@ -8984,7 +9510,7 @@ async function resolveQoderCnProjectPath(projectDir, home) {
|
|
|
8984
9510
|
if (!entry.isDirectory()) {
|
|
8985
9511
|
continue;
|
|
8986
9512
|
}
|
|
8987
|
-
const candidate =
|
|
9513
|
+
const candidate = path18.join(current, entry.name);
|
|
8988
9514
|
const encoded = encodeQoderCnProjectPath(candidate);
|
|
8989
9515
|
if (encoded === projectDir) {
|
|
8990
9516
|
return candidate;
|
|
@@ -9029,9 +9555,9 @@ function hookConfig6() {
|
|
|
9029
9555
|
function qoderCnConfigDir(home, env) {
|
|
9030
9556
|
const override = env?.QODER_CN_CONFIG_DIR;
|
|
9031
9557
|
if (override && override.trim()) {
|
|
9032
|
-
return
|
|
9558
|
+
return path18.resolve(override);
|
|
9033
9559
|
}
|
|
9034
|
-
return
|
|
9560
|
+
return path18.join(home, ".qoder-cn");
|
|
9035
9561
|
}
|
|
9036
9562
|
function createQoderCnAdapter() {
|
|
9037
9563
|
return {
|
|
@@ -9043,27 +9569,27 @@ function createQoderCnAdapter() {
|
|
|
9043
9569
|
return qoderCnConfigDir(home, env);
|
|
9044
9570
|
},
|
|
9045
9571
|
installedPath(home, env) {
|
|
9046
|
-
return
|
|
9572
|
+
return path18.join(qoderCnConfigDir(home, env), "settings.json");
|
|
9047
9573
|
},
|
|
9048
9574
|
async isInstalled(home, env) {
|
|
9049
9575
|
return isHooksJsonInstalled(
|
|
9050
|
-
|
|
9576
|
+
path18.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
9051
9577
|
"vibetime hook --agent qoder-cn"
|
|
9052
9578
|
);
|
|
9053
9579
|
},
|
|
9054
9580
|
installEntries(home, env) {
|
|
9055
9581
|
return [{
|
|
9056
9582
|
kind: "hooks-json",
|
|
9057
|
-
path:
|
|
9583
|
+
path: path18.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
9058
9584
|
content: hookConfig6()
|
|
9059
9585
|
}];
|
|
9060
9586
|
},
|
|
9061
9587
|
sourcePaths(home, env) {
|
|
9062
9588
|
const base = qoderCnConfigDir(home, env);
|
|
9063
9589
|
return [
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9590
|
+
path18.join(base, "projects"),
|
|
9591
|
+
path18.join(base, ".qoder.json"),
|
|
9592
|
+
path18.join(home, ".qoder.json")
|
|
9067
9593
|
];
|
|
9068
9594
|
},
|
|
9069
9595
|
parseSessionFile: parseQoderCnSessionFile
|
|
@@ -9072,11 +9598,11 @@ function createQoderCnAdapter() {
|
|
|
9072
9598
|
|
|
9073
9599
|
// src/adapters/qoder.ts
|
|
9074
9600
|
import { existsSync } from "node:fs";
|
|
9075
|
-
import { readdir as readdir8, readFile as
|
|
9601
|
+
import { readdir as readdir8, readFile as readFile12, stat as stat9 } from "node:fs/promises";
|
|
9076
9602
|
import os9 from "node:os";
|
|
9077
|
-
import
|
|
9603
|
+
import path19 from "node:path";
|
|
9078
9604
|
function parseQoderPaths(filePath) {
|
|
9079
|
-
const parts = filePath.split(
|
|
9605
|
+
const parts = filePath.split(path19.sep);
|
|
9080
9606
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
9081
9607
|
let sessionId = "";
|
|
9082
9608
|
let projectName = "";
|
|
@@ -9086,17 +9612,17 @@ function parseQoderPaths(filePath) {
|
|
|
9086
9612
|
sessionId = parts[subagentsIdx - 1];
|
|
9087
9613
|
projectName = parts[subagentsIdx - 2];
|
|
9088
9614
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
9089
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
9090
|
-
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(
|
|
9615
|
+
configDir2 = parts.slice(0, projectsIdx).join(path19.sep);
|
|
9616
|
+
mainTranscriptPath = [...parts.slice(0, subagentsIdx - 1), `${sessionId}.jsonl`].join(path19.sep);
|
|
9091
9617
|
} else {
|
|
9092
9618
|
const filename = parts.at(-1) || "";
|
|
9093
|
-
sessionId =
|
|
9619
|
+
sessionId = path19.basename(filename, ".jsonl");
|
|
9094
9620
|
projectName = parts.at(-2) || "";
|
|
9095
9621
|
if (projectName === "transcript") {
|
|
9096
9622
|
projectName = parts.at(-3) || "";
|
|
9097
9623
|
}
|
|
9098
9624
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
9099
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
9625
|
+
configDir2 = parts.slice(0, projectsIdx).join(path19.sep);
|
|
9100
9626
|
}
|
|
9101
9627
|
return { configDir: configDir2, projectName, sessionId, mainTranscriptPath };
|
|
9102
9628
|
}
|
|
@@ -9119,7 +9645,7 @@ function rebuildEventIdentity4(event) {
|
|
|
9119
9645
|
}
|
|
9120
9646
|
async function parseModelNamesFromDynamicTexts2(dynamicTextsPath) {
|
|
9121
9647
|
try {
|
|
9122
|
-
const content = await
|
|
9648
|
+
const content = await readFile12(dynamicTextsPath, "utf8");
|
|
9123
9649
|
const json = JSON.parse(content);
|
|
9124
9650
|
const texts = json.texts || {};
|
|
9125
9651
|
const map = {};
|
|
@@ -9135,10 +9661,10 @@ async function parseModelNamesFromDynamicTexts2(dynamicTextsPath) {
|
|
|
9135
9661
|
}
|
|
9136
9662
|
}
|
|
9137
9663
|
async function loadQoderModelNames(configDir2, home) {
|
|
9138
|
-
const map = await parseModelNamesFromDynamicTexts2(
|
|
9664
|
+
const map = await parseModelNamesFromDynamicTexts2(path19.join(configDir2, ".auth", "dynamic-texts.json"));
|
|
9139
9665
|
const siblingConfigDir = configDir2.replace(/\.qoder$/, ".qoder-cn");
|
|
9140
9666
|
if (siblingConfigDir !== configDir2) {
|
|
9141
|
-
const siblingMap = await parseModelNamesFromDynamicTexts2(
|
|
9667
|
+
const siblingMap = await parseModelNamesFromDynamicTexts2(path19.join(siblingConfigDir, ".auth", "dynamic-texts.json"));
|
|
9142
9668
|
for (const [key, val] of Object.entries(siblingMap)) {
|
|
9143
9669
|
if (!(key in map)) {
|
|
9144
9670
|
map[key] = val;
|
|
@@ -9146,11 +9672,11 @@ async function loadQoderModelNames(configDir2, home) {
|
|
|
9146
9672
|
}
|
|
9147
9673
|
}
|
|
9148
9674
|
if (isQwenworkConfigRoot(configDir2)) {
|
|
9149
|
-
for (const dir of [
|
|
9150
|
-
if (
|
|
9675
|
+
for (const dir of [path19.join(home, ".qoder"), path19.join(home, ".qoder-cn")]) {
|
|
9676
|
+
if (path19.resolve(dir) === path19.resolve(configDir2)) {
|
|
9151
9677
|
continue;
|
|
9152
9678
|
}
|
|
9153
|
-
const fallbackMap = await parseModelNamesFromDynamicTexts2(
|
|
9679
|
+
const fallbackMap = await parseModelNamesFromDynamicTexts2(path19.join(dir, ".auth", "dynamic-texts.json"));
|
|
9154
9680
|
for (const [key, val] of Object.entries(fallbackMap)) {
|
|
9155
9681
|
if (!(key in map)) {
|
|
9156
9682
|
map[key] = val;
|
|
@@ -9169,17 +9695,17 @@ async function loadQoderModelNames(configDir2, home) {
|
|
|
9169
9695
|
return map;
|
|
9170
9696
|
}
|
|
9171
9697
|
function isQwenworkConfigRoot(configDir2) {
|
|
9172
|
-
const name =
|
|
9698
|
+
const name = path19.basename(path19.resolve(configDir2));
|
|
9173
9699
|
if (name === ".qwenworkcn" || name === ".qwenwork") {
|
|
9174
9700
|
return true;
|
|
9175
9701
|
}
|
|
9176
9702
|
const override = process.env.QWENWORK_CONFIG_DIR;
|
|
9177
|
-
return Boolean(override && override.trim() &&
|
|
9703
|
+
return Boolean(override && override.trim() && path19.basename(path19.resolve(override)) === name);
|
|
9178
9704
|
}
|
|
9179
9705
|
var FAILED_SEGMENT_STOP_REASONS = /* @__PURE__ */ new Set(["cancelled", "canceled", "error", "failed", "refusal"]);
|
|
9180
9706
|
async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
9181
9707
|
const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
|
|
9182
|
-
const segmentsPath =
|
|
9708
|
+
const segmentsPath = path19.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
9183
9709
|
const modelCalls = [];
|
|
9184
9710
|
try {
|
|
9185
9711
|
const files = await readdir8(segmentsPath);
|
|
@@ -9187,7 +9713,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
|
|
|
9187
9713
|
if (!file.endsWith(".jsonl")) {
|
|
9188
9714
|
continue;
|
|
9189
9715
|
}
|
|
9190
|
-
const content = await
|
|
9716
|
+
const content = await readFile12(path19.join(segmentsPath, file), "utf8");
|
|
9191
9717
|
let currentTurnIsSubagent = false;
|
|
9192
9718
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
9193
9719
|
const raw = parseJsonLine(line);
|
|
@@ -9221,7 +9747,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
|
|
|
9221
9747
|
return modelCalls.filter((call) => call.isSubagent === isSubagentSession);
|
|
9222
9748
|
}
|
|
9223
9749
|
async function parseQoderSessionFile(filePath, options) {
|
|
9224
|
-
const text = await
|
|
9750
|
+
const text = await readFile12(filePath, "utf8");
|
|
9225
9751
|
const lines = text.split("\n").filter(Boolean);
|
|
9226
9752
|
const parsedPaths = parseQoderPaths(filePath);
|
|
9227
9753
|
const { configDir: configDir2 } = parsedPaths;
|
|
@@ -9232,7 +9758,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
9232
9758
|
let cwd;
|
|
9233
9759
|
let project = projectContext.project;
|
|
9234
9760
|
let model;
|
|
9235
|
-
const home =
|
|
9761
|
+
const home = path19.resolve(stringOption(options.home) || os9.homedir());
|
|
9236
9762
|
const modelMap = await loadQoderModelNames(configDir2, home);
|
|
9237
9763
|
const qwenworkRoot = isQwenworkConfigRoot(configDir2);
|
|
9238
9764
|
const isSubagentSession = filePath.includes("subagents");
|
|
@@ -9268,7 +9794,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
9268
9794
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
9269
9795
|
state.sessionId = sessionId;
|
|
9270
9796
|
cwd = stringField(raw, "cwd") || cwd;
|
|
9271
|
-
project = projectContext.project || (cwd ?
|
|
9797
|
+
project = projectContext.project || (cwd ? path19.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
|
|
9272
9798
|
if (!ts) {
|
|
9273
9799
|
continue;
|
|
9274
9800
|
}
|
|
@@ -9353,6 +9879,41 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
9353
9879
|
}
|
|
9354
9880
|
pendingTools.delete(pending.id);
|
|
9355
9881
|
}
|
|
9882
|
+
const attachedPrompt = extractQoderAttachedPrompt(qoderToolResultItems(message)[0]?.content);
|
|
9883
|
+
if (attachedPrompt) {
|
|
9884
|
+
const prompt = qoderTextStats(attachedPrompt);
|
|
9885
|
+
state.closeTurn(ts, lineNumber, topType);
|
|
9886
|
+
state.currentTurnId = stringField(raw, "uuid") || stringField(raw, "promptId") || `turn_${createStableHash([sessionId, lineNumber]).slice(0, 24)}`;
|
|
9887
|
+
state.currentTurnStartedAt = ts;
|
|
9888
|
+
state.currentTurnLastEventAt = ts;
|
|
9889
|
+
push(baseQoderEvent({
|
|
9890
|
+
ts,
|
|
9891
|
+
type: "turn.started",
|
|
9892
|
+
sessionId,
|
|
9893
|
+
turnId: state.currentTurnId,
|
|
9894
|
+
cwd,
|
|
9895
|
+
project,
|
|
9896
|
+
model,
|
|
9897
|
+
confidence: "derived"
|
|
9898
|
+
}), lineNumber, topType, "attached_prompt");
|
|
9899
|
+
push(baseQoderEvent({
|
|
9900
|
+
ts,
|
|
9901
|
+
type: "prompt.submitted",
|
|
9902
|
+
sessionId,
|
|
9903
|
+
turnId: state.currentTurnId,
|
|
9904
|
+
cwd,
|
|
9905
|
+
project,
|
|
9906
|
+
model,
|
|
9907
|
+
confidence: "exact",
|
|
9908
|
+
metrics: {
|
|
9909
|
+
prompts: 1,
|
|
9910
|
+
promptChars: prompt.chars
|
|
9911
|
+
},
|
|
9912
|
+
refs: stringRefs({
|
|
9913
|
+
promptHash: prompt.hash
|
|
9914
|
+
})
|
|
9915
|
+
}), lineNumber, topType, "attached_prompt");
|
|
9916
|
+
}
|
|
9356
9917
|
continue;
|
|
9357
9918
|
}
|
|
9358
9919
|
if (topType === "user") {
|
|
@@ -9543,7 +10104,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
9543
10104
|
}
|
|
9544
10105
|
dbModelCalls ??= await loadQoderDbModelCalls("Qoder", parsedPaths.sessionId, modelMap);
|
|
9545
10106
|
if (dbModelCalls.rootSessionId) {
|
|
9546
|
-
const parentPath =
|
|
10107
|
+
const parentPath = path19.join(path19.dirname(filePath), `${dbModelCalls.rootSessionId}.jsonl`);
|
|
9547
10108
|
const parentSourcePathHash = `sha256:${createStableHash(parentPath)}`;
|
|
9548
10109
|
return validEvents.map((event) => rebuildEventIdentity4({
|
|
9549
10110
|
...event,
|
|
@@ -9659,41 +10220,41 @@ function qoderExtractText(value) {
|
|
|
9659
10220
|
}
|
|
9660
10221
|
async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
9661
10222
|
const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
|
|
9662
|
-
const isSubagent = filePath.includes(`${
|
|
10223
|
+
const isSubagent = filePath.includes(`${path19.sep}subagents${path19.sep}`);
|
|
9663
10224
|
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
9664
10225
|
let cwds = [];
|
|
9665
10226
|
const workspaceDirs = [];
|
|
9666
10227
|
for (const line of lines) {
|
|
9667
10228
|
const raw = parseJsonLine(line);
|
|
9668
10229
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
9669
|
-
if (cwd &&
|
|
10230
|
+
if (cwd && path19.isAbsolute(cwd)) {
|
|
9670
10231
|
cwds.push(cwd);
|
|
9671
10232
|
}
|
|
9672
10233
|
if (raw && stringField(raw, "type") === "workspace-directories") {
|
|
9673
10234
|
for (const dir of arrayField5(raw, "directories")) {
|
|
9674
|
-
if (typeof dir === "string" &&
|
|
10235
|
+
if (typeof dir === "string" && path19.isAbsolute(dir)) {
|
|
9675
10236
|
workspaceDirs.push(dir);
|
|
9676
10237
|
}
|
|
9677
10238
|
}
|
|
9678
10239
|
}
|
|
9679
10240
|
}
|
|
9680
10241
|
if (isSubagent) {
|
|
9681
|
-
if (inherited?.cwd &&
|
|
10242
|
+
if (inherited?.cwd && path19.isAbsolute(inherited.cwd)) {
|
|
9682
10243
|
cwds = [inherited.cwd];
|
|
9683
10244
|
} else {
|
|
9684
|
-
const parentSessionPath =
|
|
10245
|
+
const parentSessionPath = path19.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
9685
10246
|
try {
|
|
9686
|
-
const parentText = await
|
|
10247
|
+
const parentText = await readFile12(parentSessionPath, "utf8");
|
|
9687
10248
|
const parentCwds = [];
|
|
9688
10249
|
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
9689
10250
|
const raw = parseJsonLine(line);
|
|
9690
10251
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
9691
|
-
if (cwd &&
|
|
10252
|
+
if (cwd && path19.isAbsolute(cwd)) {
|
|
9692
10253
|
parentCwds.push(cwd);
|
|
9693
10254
|
}
|
|
9694
10255
|
if (workspaceDirs.length === 0 && raw && stringField(raw, "type") === "workspace-directories") {
|
|
9695
10256
|
for (const dir of arrayField5(raw, "directories")) {
|
|
9696
|
-
if (typeof dir === "string" &&
|
|
10257
|
+
if (typeof dir === "string" && path19.isAbsolute(dir)) {
|
|
9697
10258
|
workspaceDirs.push(dir);
|
|
9698
10259
|
}
|
|
9699
10260
|
}
|
|
@@ -9713,29 +10274,29 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
9713
10274
|
}
|
|
9714
10275
|
}
|
|
9715
10276
|
const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
|
|
9716
|
-
const project = inherited?.project || (cwds.length > 0 ?
|
|
10277
|
+
const project = inherited?.project || (cwds.length > 0 ? path19.basename(cwds[0]) : root ? path19.basename(root) : await qoderProjectFromFilePath(filePath, options));
|
|
9717
10278
|
return {
|
|
9718
10279
|
project,
|
|
9719
10280
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
9720
10281
|
};
|
|
9721
10282
|
}
|
|
9722
10283
|
function pathInsideDir(candidate, dir) {
|
|
9723
|
-
const resolvedDir =
|
|
9724
|
-
const resolved =
|
|
9725
|
-
return resolved === resolvedDir || resolved.startsWith(`${resolvedDir}${
|
|
10284
|
+
const resolvedDir = path19.resolve(dir);
|
|
10285
|
+
const resolved = path19.resolve(candidate);
|
|
10286
|
+
return resolved === resolvedDir || resolved.startsWith(`${resolvedDir}${path19.sep}`);
|
|
9726
10287
|
}
|
|
9727
10288
|
async function gitRootFromCwds3(cwds) {
|
|
9728
10289
|
const seen = /* @__PURE__ */ new Set();
|
|
9729
10290
|
for (const cwd of cwds) {
|
|
9730
|
-
let current =
|
|
10291
|
+
let current = path19.resolve(cwd);
|
|
9731
10292
|
while (!seen.has(current)) {
|
|
9732
10293
|
seen.add(current);
|
|
9733
10294
|
try {
|
|
9734
|
-
await stat9(
|
|
10295
|
+
await stat9(path19.join(current, ".git"));
|
|
9735
10296
|
return current;
|
|
9736
10297
|
} catch {
|
|
9737
10298
|
}
|
|
9738
|
-
const parent =
|
|
10299
|
+
const parent = path19.dirname(current);
|
|
9739
10300
|
if (parent === current) {
|
|
9740
10301
|
break;
|
|
9741
10302
|
}
|
|
@@ -9746,12 +10307,12 @@ async function gitRootFromCwds3(cwds) {
|
|
|
9746
10307
|
}
|
|
9747
10308
|
function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
9748
10309
|
for (const cwd of cwds) {
|
|
9749
|
-
let current =
|
|
10310
|
+
let current = path19.resolve(cwd);
|
|
9750
10311
|
while (true) {
|
|
9751
10312
|
if (qoderEncodedVariants(current).includes(projectDir)) {
|
|
9752
10313
|
return current;
|
|
9753
10314
|
}
|
|
9754
|
-
const parent =
|
|
10315
|
+
const parent = path19.dirname(current);
|
|
9755
10316
|
if (parent === current) {
|
|
9756
10317
|
break;
|
|
9757
10318
|
}
|
|
@@ -9761,7 +10322,7 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
|
9761
10322
|
return void 0;
|
|
9762
10323
|
}
|
|
9763
10324
|
function rawQoderProjectPath(value) {
|
|
9764
|
-
return
|
|
10325
|
+
return path19.resolve(value).split(path19.sep).join("-");
|
|
9765
10326
|
}
|
|
9766
10327
|
function qoderEncodedVariants(value) {
|
|
9767
10328
|
const raw = rawQoderProjectPath(value);
|
|
@@ -9782,11 +10343,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
|
|
|
9782
10343
|
return void 0;
|
|
9783
10344
|
}
|
|
9784
10345
|
async function qoderProjectFromFilePath(filePath, options) {
|
|
9785
|
-
const projectDir =
|
|
9786
|
-
const home = options ?
|
|
10346
|
+
const projectDir = path19.basename(path19.dirname(filePath));
|
|
10347
|
+
const home = options ? path19.resolve(stringOption(options.home) || os9.homedir()) : os9.homedir();
|
|
9787
10348
|
const resolved = await resolveQoderProjectPath(projectDir, home);
|
|
9788
10349
|
if (resolved) {
|
|
9789
|
-
return
|
|
10350
|
+
return path19.basename(resolved);
|
|
9790
10351
|
}
|
|
9791
10352
|
const suffix = qoderEncodedProjectSuffix(projectDir, home);
|
|
9792
10353
|
if (suffix) {
|
|
@@ -9812,7 +10373,7 @@ async function resolveQoderProjectPath(projectDir, home) {
|
|
|
9812
10373
|
if (!entry.isDirectory()) {
|
|
9813
10374
|
continue;
|
|
9814
10375
|
}
|
|
9815
|
-
const candidate =
|
|
10376
|
+
const candidate = path19.join(current, entry.name);
|
|
9816
10377
|
const candidateVariants = qoderEncodedVariants(candidate);
|
|
9817
10378
|
if (candidateVariants.includes(projectDir)) {
|
|
9818
10379
|
return candidate;
|
|
@@ -9857,19 +10418,19 @@ function hookConfig7() {
|
|
|
9857
10418
|
function qoderConfigDir(home, env) {
|
|
9858
10419
|
const override = env?.QODER_CONFIG_DIR;
|
|
9859
10420
|
if (override && override.trim()) {
|
|
9860
|
-
return
|
|
10421
|
+
return path19.resolve(override);
|
|
9861
10422
|
}
|
|
9862
|
-
return
|
|
10423
|
+
return path19.join(home, ".qoder");
|
|
9863
10424
|
}
|
|
9864
10425
|
function qwenworkConfigDir(home, env) {
|
|
9865
10426
|
const override = env?.QWENWORK_CONFIG_DIR;
|
|
9866
10427
|
if (override && override.trim()) {
|
|
9867
|
-
return
|
|
10428
|
+
return path19.resolve(override);
|
|
9868
10429
|
}
|
|
9869
|
-
return
|
|
10430
|
+
return path19.join(home, ".qwenworkcn");
|
|
9870
10431
|
}
|
|
9871
10432
|
function qoderConfigDirs(home, env) {
|
|
9872
|
-
return [...new Set([qoderConfigDir(home, env), qwenworkConfigDir(home, env)].map((dir) =>
|
|
10433
|
+
return [...new Set([qoderConfigDir(home, env), qwenworkConfigDir(home, env)].map((dir) => path19.resolve(dir)))];
|
|
9873
10434
|
}
|
|
9874
10435
|
function createQoderAdapter() {
|
|
9875
10436
|
return {
|
|
@@ -9881,11 +10442,11 @@ function createQoderAdapter() {
|
|
|
9881
10442
|
return qoderConfigDir(home, env);
|
|
9882
10443
|
},
|
|
9883
10444
|
installedPath(home, env) {
|
|
9884
|
-
return
|
|
10445
|
+
return path19.join(qoderConfigDir(home, env), "settings.json");
|
|
9885
10446
|
},
|
|
9886
10447
|
async isInstalled(home, env) {
|
|
9887
10448
|
return isHooksJsonInstalled(
|
|
9888
|
-
|
|
10449
|
+
path19.join(qoderConfigDir(home, env), "settings.json"),
|
|
9889
10450
|
"vibetime hook --agent qoder"
|
|
9890
10451
|
);
|
|
9891
10452
|
},
|
|
@@ -9894,16 +10455,16 @@ function createQoderAdapter() {
|
|
|
9894
10455
|
const targets = [primary, ...variants.filter((dir) => existsSync(dir))];
|
|
9895
10456
|
return targets.map((base) => ({
|
|
9896
10457
|
kind: "hooks-json",
|
|
9897
|
-
path:
|
|
10458
|
+
path: path19.join(base, "settings.json"),
|
|
9898
10459
|
content: hookConfig7()
|
|
9899
10460
|
}));
|
|
9900
10461
|
},
|
|
9901
10462
|
sourcePaths(home, env) {
|
|
9902
|
-
const paths = qoderConfigDirs(home, env).map((base2) =>
|
|
10463
|
+
const paths = qoderConfigDirs(home, env).map((base2) => path19.join(base2, "projects"));
|
|
9903
10464
|
const base = qoderConfigDir(home, env);
|
|
9904
10465
|
paths.push(
|
|
9905
|
-
|
|
9906
|
-
|
|
10466
|
+
path19.join(base, ".qoder.json"),
|
|
10467
|
+
path19.join(home, ".qoder.json")
|
|
9907
10468
|
);
|
|
9908
10469
|
return paths;
|
|
9909
10470
|
},
|
|
@@ -9939,27 +10500,27 @@ function normalizeId(id) {
|
|
|
9939
10500
|
}
|
|
9940
10501
|
|
|
9941
10502
|
// src/adapters/workbuddy.ts
|
|
9942
|
-
import { readdir as readdir9, readFile as
|
|
9943
|
-
import
|
|
10503
|
+
import { readdir as readdir9, readFile as readFile13, stat as stat10 } from "node:fs/promises";
|
|
10504
|
+
import path20 from "node:path";
|
|
9944
10505
|
function workbuddyProjectsDir(home, env) {
|
|
9945
10506
|
const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
|
|
9946
10507
|
if (override && override.trim()) {
|
|
9947
|
-
return
|
|
10508
|
+
return path20.resolve(override, override.endsWith("projects") ? "" : "projects");
|
|
9948
10509
|
}
|
|
9949
|
-
return
|
|
10510
|
+
return path20.join(home, ".workbuddy", "projects");
|
|
9950
10511
|
}
|
|
9951
10512
|
function workbuddyBaseDir(home, env) {
|
|
9952
10513
|
const override = env?.WORKBUDDY_HOME;
|
|
9953
10514
|
if (override && override.trim()) {
|
|
9954
|
-
return
|
|
10515
|
+
return path20.resolve(override);
|
|
9955
10516
|
}
|
|
9956
|
-
return
|
|
10517
|
+
return path20.join(home, ".workbuddy");
|
|
9957
10518
|
}
|
|
9958
10519
|
function projectFromCwd(cwd, fallback) {
|
|
9959
10520
|
if (!cwd) {
|
|
9960
10521
|
return fallback;
|
|
9961
10522
|
}
|
|
9962
|
-
return
|
|
10523
|
+
return path20.basename(cwd) || fallback;
|
|
9963
10524
|
}
|
|
9964
10525
|
function sourceHash(filePath) {
|
|
9965
10526
|
return `sha256:${createStableHash(filePath)}`;
|
|
@@ -10077,7 +10638,7 @@ function toolCallFailed(record) {
|
|
|
10077
10638
|
return status === "failed" || status === "incomplete" || record.is_error === true || providerData.error != null || providerData.isError === true;
|
|
10078
10639
|
}
|
|
10079
10640
|
async function readWorkbuddyLines(filePath) {
|
|
10080
|
-
const text = await
|
|
10641
|
+
const text = await readFile13(filePath, "utf8");
|
|
10081
10642
|
return text.split(/\r?\n/).map((line, index) => {
|
|
10082
10643
|
if (!line.trim()) {
|
|
10083
10644
|
return void 0;
|
|
@@ -10097,8 +10658,8 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
10097
10658
|
}
|
|
10098
10659
|
const events = [];
|
|
10099
10660
|
const first = lines[0].record;
|
|
10100
|
-
const sessionId = stringField(first, "sessionId") ||
|
|
10101
|
-
const fallbackProject =
|
|
10661
|
+
const sessionId = stringField(first, "sessionId") || path20.basename(filePath, ".jsonl");
|
|
10662
|
+
const fallbackProject = path20.basename(path20.dirname(filePath));
|
|
10102
10663
|
const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
|
|
10103
10664
|
const project = projectFromCwd(cwd, fallbackProject);
|
|
10104
10665
|
const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
|
|
@@ -10387,11 +10948,11 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
10387
10948
|
if (!project.isDirectory()) {
|
|
10388
10949
|
continue;
|
|
10389
10950
|
}
|
|
10390
|
-
const projectDir =
|
|
10951
|
+
const projectDir = path20.join(base, project.name);
|
|
10391
10952
|
const entries = await readdir9(projectDir, { withFileTypes: true });
|
|
10392
10953
|
for (const entry of entries) {
|
|
10393
10954
|
if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
10394
|
-
const filePath =
|
|
10955
|
+
const filePath = path20.join(projectDir, entry.name);
|
|
10395
10956
|
const info = await stat10(filePath);
|
|
10396
10957
|
files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
|
|
10397
10958
|
}
|
|
@@ -10429,18 +10990,18 @@ function createWorkbuddyAdapter() {
|
|
|
10429
10990
|
return workbuddyProjectsDir(home, env);
|
|
10430
10991
|
},
|
|
10431
10992
|
installedPath(home, env) {
|
|
10432
|
-
return
|
|
10993
|
+
return path20.join(workbuddyBaseDir(home, env), "settings.json");
|
|
10433
10994
|
},
|
|
10434
10995
|
async isInstalled(home, env) {
|
|
10435
10996
|
return isHooksJsonInstalled(
|
|
10436
|
-
|
|
10997
|
+
path20.join(workbuddyBaseDir(home, env), "settings.json"),
|
|
10437
10998
|
"vibetime hook --agent workbuddy"
|
|
10438
10999
|
);
|
|
10439
11000
|
},
|
|
10440
11001
|
installEntries(home, env) {
|
|
10441
11002
|
return [{
|
|
10442
11003
|
kind: "hooks-json",
|
|
10443
|
-
path:
|
|
11004
|
+
path: path20.join(workbuddyBaseDir(home, env), "settings.json"),
|
|
10444
11005
|
content: hookConfig8()
|
|
10445
11006
|
}];
|
|
10446
11007
|
},
|
|
@@ -10453,20 +11014,20 @@ function createWorkbuddyAdapter() {
|
|
|
10453
11014
|
|
|
10454
11015
|
// src/adapters/zcode.ts
|
|
10455
11016
|
import { execFile } from "node:child_process";
|
|
10456
|
-
import { readFile as
|
|
10457
|
-
import
|
|
11017
|
+
import { readFile as readFile14, stat as stat11 } from "node:fs/promises";
|
|
11018
|
+
import path21 from "node:path";
|
|
10458
11019
|
import { promisify as promisify2 } from "node:util";
|
|
10459
11020
|
init_fs();
|
|
10460
11021
|
var execFileAsync = promisify2(execFile);
|
|
10461
11022
|
function zcodeCliDir(home, env) {
|
|
10462
11023
|
const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
|
|
10463
11024
|
if (override && override.trim()) {
|
|
10464
|
-
return
|
|
11025
|
+
return path21.resolve(override, override.endsWith("cli") ? "" : "cli");
|
|
10465
11026
|
}
|
|
10466
|
-
return
|
|
11027
|
+
return path21.join(home, ".zcode", "cli");
|
|
10467
11028
|
}
|
|
10468
11029
|
function zcodeDbPath(home, env) {
|
|
10469
|
-
return
|
|
11030
|
+
return path21.join(zcodeCliDir(home, env), "db", "db.sqlite");
|
|
10470
11031
|
}
|
|
10471
11032
|
var providerNameCache = null;
|
|
10472
11033
|
async function loadProviderNames(configPath2) {
|
|
@@ -10482,7 +11043,7 @@ async function loadProviderNames(configPath2) {
|
|
|
10482
11043
|
}
|
|
10483
11044
|
const map = /* @__PURE__ */ new Map();
|
|
10484
11045
|
try {
|
|
10485
|
-
const raw = await
|
|
11046
|
+
const raw = await readFile14(configPath2, "utf-8");
|
|
10486
11047
|
const config = JSON.parse(raw);
|
|
10487
11048
|
const providers = config?.provider;
|
|
10488
11049
|
if (isPlainObject(providers)) {
|
|
@@ -10500,7 +11061,7 @@ function sourceHash2(filePath) {
|
|
|
10500
11061
|
return `sha256:${createStableHash(filePath)}`;
|
|
10501
11062
|
}
|
|
10502
11063
|
function projectFromDirectory(directory) {
|
|
10503
|
-
return directory ?
|
|
11064
|
+
return directory ? path21.basename(directory) || "zcode" : "zcode";
|
|
10504
11065
|
}
|
|
10505
11066
|
function isoFromMs(value) {
|
|
10506
11067
|
return timestampFrom(typeof value === "number" ? value : Number(value));
|
|
@@ -10683,16 +11244,16 @@ async function parseZCodeDb(filePath, options) {
|
|
|
10683
11244
|
if (rows.length === 0) {
|
|
10684
11245
|
return [];
|
|
10685
11246
|
}
|
|
10686
|
-
let candidate =
|
|
11247
|
+
let candidate = path21.resolve(filePath);
|
|
10687
11248
|
let configPath2 = "";
|
|
10688
11249
|
for (let i = 0; i < 12; i++) {
|
|
10689
|
-
const probe =
|
|
11250
|
+
const probe = path21.join(candidate, ".zcode", "v2", "config.json");
|
|
10690
11251
|
try {
|
|
10691
11252
|
await stat11(probe);
|
|
10692
11253
|
configPath2 = probe;
|
|
10693
11254
|
break;
|
|
10694
11255
|
} catch {
|
|
10695
|
-
const parent =
|
|
11256
|
+
const parent = path21.dirname(candidate);
|
|
10696
11257
|
if (parent === candidate) break;
|
|
10697
11258
|
candidate = parent;
|
|
10698
11259
|
}
|
|
@@ -10908,7 +11469,7 @@ async function parseZCodeDb(filePath, options) {
|
|
|
10908
11469
|
}
|
|
10909
11470
|
async function zcodeBackfillFiles(sourceRoot, home, env) {
|
|
10910
11471
|
const candidate = sourceRoot || zcodeDbPath(home, env);
|
|
10911
|
-
const filePath = candidate.endsWith(".sqlite") ? candidate :
|
|
11472
|
+
const filePath = candidate.endsWith(".sqlite") ? candidate : path21.join(candidate, "db", "db.sqlite");
|
|
10912
11473
|
try {
|
|
10913
11474
|
const info = await stat11(filePath);
|
|
10914
11475
|
return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
|
|
@@ -10943,49 +11504,49 @@ function createZCodeAdapter() {
|
|
|
10943
11504
|
|
|
10944
11505
|
// src/adapters/zed.ts
|
|
10945
11506
|
import os10 from "node:os";
|
|
10946
|
-
import
|
|
11507
|
+
import path22 from "node:path";
|
|
10947
11508
|
function zedThreadsCandidates(home, env) {
|
|
10948
11509
|
const candidates = [];
|
|
10949
11510
|
const platform2 = process.platform;
|
|
10950
11511
|
if (platform2 === "darwin") {
|
|
10951
|
-
candidates.push(
|
|
11512
|
+
candidates.push(path22.join(home, "Library", "Application Support", "Zed", "threads", "threads.db"));
|
|
10952
11513
|
} else if (platform2 === "win32") {
|
|
10953
11514
|
const appdata = env?.APPDATA;
|
|
10954
11515
|
if (appdata && appdata.trim()) {
|
|
10955
|
-
candidates.push(
|
|
11516
|
+
candidates.push(path22.join(path22.resolve(appdata), "Zed", "threads", "threads.db"));
|
|
10956
11517
|
}
|
|
10957
|
-
candidates.push(
|
|
11518
|
+
candidates.push(path22.join(home, "AppData", "Roaming", "Zed", "threads", "threads.db"));
|
|
10958
11519
|
} else {
|
|
10959
11520
|
const xdgData = env?.XDG_DATA_HOME;
|
|
10960
11521
|
if (xdgData && xdgData.trim()) {
|
|
10961
|
-
candidates.push(
|
|
11522
|
+
candidates.push(path22.join(path22.resolve(xdgData), "zed", "threads", "threads.db"));
|
|
10962
11523
|
}
|
|
10963
|
-
candidates.push(
|
|
11524
|
+
candidates.push(path22.join(home, ".local", "share", "zed", "threads", "threads.db"));
|
|
10964
11525
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
10965
11526
|
if (xdgConfig && xdgConfig.trim()) {
|
|
10966
|
-
candidates.push(
|
|
11527
|
+
candidates.push(path22.join(path22.resolve(xdgConfig), "zed", "threads", "threads.db"));
|
|
10967
11528
|
}
|
|
10968
|
-
candidates.push(
|
|
11529
|
+
candidates.push(path22.join(home, ".config", "zed", "threads", "threads.db"));
|
|
10969
11530
|
}
|
|
10970
11531
|
return candidates;
|
|
10971
11532
|
}
|
|
10972
11533
|
function zedConfigDir(home, env) {
|
|
10973
11534
|
const platform2 = process.platform;
|
|
10974
11535
|
if (platform2 === "darwin") {
|
|
10975
|
-
return
|
|
11536
|
+
return path22.join(home, "Library", "Application Support", "Zed");
|
|
10976
11537
|
}
|
|
10977
11538
|
if (platform2 === "win32") {
|
|
10978
11539
|
const appdata = env?.APPDATA;
|
|
10979
11540
|
if (appdata && appdata.trim()) {
|
|
10980
|
-
return
|
|
11541
|
+
return path22.join(path22.resolve(appdata), "Zed");
|
|
10981
11542
|
}
|
|
10982
|
-
return
|
|
11543
|
+
return path22.join(home, "AppData", "Roaming", "Zed");
|
|
10983
11544
|
}
|
|
10984
11545
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
10985
11546
|
if (xdgConfig && xdgConfig.trim()) {
|
|
10986
|
-
return
|
|
11547
|
+
return path22.join(path22.resolve(xdgConfig), "zed");
|
|
10987
11548
|
}
|
|
10988
|
-
return
|
|
11549
|
+
return path22.join(home, ".config", "zed");
|
|
10989
11550
|
}
|
|
10990
11551
|
function baseZedEvent(event) {
|
|
10991
11552
|
return {
|
|
@@ -11049,7 +11610,7 @@ async function parseZedSessionFile(dbPath, options) {
|
|
|
11049
11610
|
const folderRaw = row.folder_paths || "";
|
|
11050
11611
|
const folder = folderRaw.split(/[\n,]/).map((s) => s.trim()).find(Boolean);
|
|
11051
11612
|
const cwd = folder || void 0;
|
|
11052
|
-
const project = cwd ?
|
|
11613
|
+
const project = cwd ? path22.basename(cwd) : row.summary ? row.summary.slice(0, 40) : void 0;
|
|
11053
11614
|
let json;
|
|
11054
11615
|
try {
|
|
11055
11616
|
const bytes = row.data_type === "zstd" ? decompress2(new Uint8Array(row.data)) : new Uint8Array(row.data);
|
|
@@ -11324,7 +11885,7 @@ function createZedAdapter() {
|
|
|
11324
11885
|
return zedConfigDir(home, env);
|
|
11325
11886
|
},
|
|
11326
11887
|
installedPath(home, env) {
|
|
11327
|
-
return
|
|
11888
|
+
return path22.join(zedConfigDir(home, env), "vibetime-marker");
|
|
11328
11889
|
},
|
|
11329
11890
|
async isInstalled() {
|
|
11330
11891
|
return false;
|
|
@@ -11805,15 +12366,15 @@ function hookCommandFromGroup(group) {
|
|
|
11805
12366
|
import { randomUUID } from "node:crypto";
|
|
11806
12367
|
import { existsSync as existsSync2, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
11807
12368
|
import { homedir, hostname } from "node:os";
|
|
11808
|
-
import
|
|
12369
|
+
import path23 from "node:path";
|
|
11809
12370
|
function configDir(home = homedir()) {
|
|
11810
|
-
return
|
|
12371
|
+
return path23.join(home, ".vibetime");
|
|
11811
12372
|
}
|
|
11812
12373
|
function configPath(home = homedir()) {
|
|
11813
|
-
return
|
|
12374
|
+
return path23.join(configDir(home), "config.json");
|
|
11814
12375
|
}
|
|
11815
12376
|
function machineIdPath(home = homedir()) {
|
|
11816
|
-
return
|
|
12377
|
+
return path23.join(configDir(home), "machine-id");
|
|
11817
12378
|
}
|
|
11818
12379
|
function readConfig(home = homedir()) {
|
|
11819
12380
|
const file = configPath(home);
|
|
@@ -11862,13 +12423,13 @@ init_fs();
|
|
|
11862
12423
|
// src/lib/logger.ts
|
|
11863
12424
|
import { appendFile, mkdir as mkdir4, rename, stat as stat12 } from "node:fs/promises";
|
|
11864
12425
|
import { homedir as homedir2 } from "node:os";
|
|
11865
|
-
import
|
|
12426
|
+
import path24 from "node:path";
|
|
11866
12427
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
11867
12428
|
function logDir(home = homedir2()) {
|
|
11868
|
-
return
|
|
12429
|
+
return path24.join(home, ".vibetime", "logs");
|
|
11869
12430
|
}
|
|
11870
12431
|
function logPath(home = homedir2(), name = "cli.log") {
|
|
11871
|
-
return
|
|
12432
|
+
return path24.join(logDir(home), name);
|
|
11872
12433
|
}
|
|
11873
12434
|
function serializeError(error) {
|
|
11874
12435
|
if (error instanceof Error) {
|
|
@@ -12043,8 +12604,8 @@ function buildHeaders(token, machine) {
|
|
|
12043
12604
|
...machine?.platform ? { "x-machine-platform": machine.platform } : {}
|
|
12044
12605
|
};
|
|
12045
12606
|
}
|
|
12046
|
-
function joinUrl(base,
|
|
12047
|
-
return new URL(
|
|
12607
|
+
function joinUrl(base, path26) {
|
|
12608
|
+
return new URL(path26, base.endsWith("/") ? base : `${base}/`).toString();
|
|
12048
12609
|
}
|
|
12049
12610
|
async function postRollupBatch(remote, rollups, options = {}) {
|
|
12050
12611
|
const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
|
|
@@ -12134,6 +12695,7 @@ function createRegistry() {
|
|
|
12134
12695
|
registry.register(createZCodeAdapter());
|
|
12135
12696
|
registry.register(createGrokBuildAdapter());
|
|
12136
12697
|
registry.register(createZedAdapter());
|
|
12698
|
+
registry.register(createKimiCodeAdapter());
|
|
12137
12699
|
return registry;
|
|
12138
12700
|
}
|
|
12139
12701
|
var defaultContext = {
|
|
@@ -13029,13 +13591,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
|
|
|
13029
13591
|
return picked;
|
|
13030
13592
|
}
|
|
13031
13593
|
function backfillIncrementalStatePath(home) {
|
|
13032
|
-
return
|
|
13594
|
+
return path25.join(home, ".vibetime", "backfill-state.json");
|
|
13033
13595
|
}
|
|
13034
13596
|
function syncLocalTriggerStatePath(home) {
|
|
13035
|
-
return
|
|
13597
|
+
return path25.join(home, ".vibetime", "sync-local-trigger.json");
|
|
13036
13598
|
}
|
|
13037
13599
|
function syncLocalTriggerLockPath(home) {
|
|
13038
|
-
return
|
|
13600
|
+
return path25.join(home, ".vibetime", "sync-local-trigger.lock");
|
|
13039
13601
|
}
|
|
13040
13602
|
function backfillRemoteKey(baseUrl) {
|
|
13041
13603
|
try {
|
|
@@ -13097,7 +13659,7 @@ async function readBackfillIncrementalStateFile(home, ctx) {
|
|
|
13097
13659
|
}
|
|
13098
13660
|
async function writeBackfillIncrementalStateFile(home, file) {
|
|
13099
13661
|
const statePath = backfillIncrementalStatePath(home);
|
|
13100
|
-
await mkdir5(
|
|
13662
|
+
await mkdir5(path25.dirname(statePath), { recursive: true });
|
|
13101
13663
|
await writeFile4(statePath, `${JSON.stringify(file, null, 2)}
|
|
13102
13664
|
`, "utf8");
|
|
13103
13665
|
}
|
|
@@ -13146,7 +13708,7 @@ async function readSyncLocalTriggerState(statePath) {
|
|
|
13146
13708
|
return nextState;
|
|
13147
13709
|
}
|
|
13148
13710
|
async function writeSyncLocalTriggerState(statePath, state) {
|
|
13149
|
-
await mkdir5(
|
|
13711
|
+
await mkdir5(path25.dirname(statePath), { recursive: true });
|
|
13150
13712
|
await writeFile4(statePath, `${JSON.stringify(state, null, 2)}
|
|
13151
13713
|
`, "utf8");
|
|
13152
13714
|
}
|
|
@@ -13161,12 +13723,12 @@ async function readSyncLocalLock(lockPath) {
|
|
|
13161
13723
|
return { pid: lock.pid, startedAt: lock.startedAt };
|
|
13162
13724
|
}
|
|
13163
13725
|
async function writeSyncLocalLock(lockPath, lock) {
|
|
13164
|
-
await mkdir5(
|
|
13726
|
+
await mkdir5(path25.dirname(lockPath), { recursive: true });
|
|
13165
13727
|
await writeFile4(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
13166
13728
|
`, "utf8");
|
|
13167
13729
|
}
|
|
13168
13730
|
async function acquireSyncLocalLock(lockPath, lock) {
|
|
13169
|
-
await mkdir5(
|
|
13731
|
+
await mkdir5(path25.dirname(lockPath), { recursive: true });
|
|
13170
13732
|
try {
|
|
13171
13733
|
const handle = await open(lockPath, "wx");
|
|
13172
13734
|
try {
|
|
@@ -13246,10 +13808,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
|
|
|
13246
13808
|
if (cliPath.endsWith(".ts")) {
|
|
13247
13809
|
return ["--import", "tsx", cliPath];
|
|
13248
13810
|
}
|
|
13249
|
-
return [
|
|
13811
|
+
return [path25.resolve(path25.dirname(cliPath), "../bin/vibetime.mjs")];
|
|
13250
13812
|
}
|
|
13251
13813
|
function resolveHome3(options, ctx) {
|
|
13252
|
-
return
|
|
13814
|
+
return path25.resolve(stringOption(options.home) || ctx.env.HOME || os11.homedir());
|
|
13253
13815
|
}
|
|
13254
13816
|
function requestedTargets(options) {
|
|
13255
13817
|
const value = options.target || options.targets;
|