@yhong91/vibetime 0.1.1 → 0.1.2
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 +421 -172
- package/package.json +8 -9
package/bin/vibetime.mjs
CHANGED
|
@@ -159,9 +159,9 @@ var init_fs = __esm({
|
|
|
159
159
|
|
|
160
160
|
// src/cli.ts
|
|
161
161
|
import { spawn } from "node:child_process";
|
|
162
|
-
import { mkdir as mkdir4, rename as rename2, rm, stat as
|
|
163
|
-
import
|
|
164
|
-
import
|
|
162
|
+
import { mkdir as mkdir4, rename as rename2, rm, stat as stat8, writeFile as writeFile3 } from "node:fs/promises";
|
|
163
|
+
import os7 from "node:os";
|
|
164
|
+
import path16 from "node:path";
|
|
165
165
|
import { fileURLToPath } from "node:url";
|
|
166
166
|
|
|
167
167
|
// ../shared/src/index.ts
|
|
@@ -197,7 +197,7 @@ var TELEMETRY_EVENT_TYPES = [
|
|
|
197
197
|
"agent.operation"
|
|
198
198
|
];
|
|
199
199
|
var FILE_ACTIVITY_OPERATIONS = ["read", "search", "create", "write", "edit", "delete"];
|
|
200
|
-
var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn"];
|
|
200
|
+
var BACKFILL_SOURCE_IDS = ["codex", "claude-code", "claude-cowork", "opencode", "pi", "agy", "codebuddy", "qoder", "qoder-cn"];
|
|
201
201
|
function createWorkspaceId(input) {
|
|
202
202
|
const basis = input.repoUrl || input.repoRoot || input.projectName || "unknown";
|
|
203
203
|
return `workspace_${fnv1a(basis)}`;
|
|
@@ -1195,7 +1195,7 @@ function countTextLines(text) {
|
|
|
1195
1195
|
}
|
|
1196
1196
|
|
|
1197
1197
|
// src/lib/constants.ts
|
|
1198
|
-
var PACKAGE_VERSION = true ? "0.1.
|
|
1198
|
+
var PACKAGE_VERSION = true ? "0.1.2" : "0.1.1";
|
|
1199
1199
|
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
1200
1200
|
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
1201
1201
|
var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
|
|
@@ -2776,11 +2776,256 @@ function createClaudeCodeAdapter() {
|
|
|
2776
2776
|
};
|
|
2777
2777
|
}
|
|
2778
2778
|
|
|
2779
|
-
// src/adapters/
|
|
2780
|
-
import { readFile as readFile4,
|
|
2779
|
+
// src/adapters/claude-cowork.ts
|
|
2780
|
+
import { readdir as readdir3, readFile as readFile4, stat as stat4 } from "node:fs/promises";
|
|
2781
|
+
import os3 from "node:os";
|
|
2781
2782
|
import path7 from "node:path";
|
|
2783
|
+
init_fs();
|
|
2784
|
+
var COWORK_PREFIX = "cowork:";
|
|
2785
|
+
function coworkDataDirs(home, env) {
|
|
2786
|
+
const override = env?.COWORK_DIR || env?.CLAUDE_COWORK_DIR;
|
|
2787
|
+
if (override && override.trim()) {
|
|
2788
|
+
return override.split(",").map((item) => item.trim()).filter(Boolean).map((item) => path7.resolve(item));
|
|
2789
|
+
}
|
|
2790
|
+
return [
|
|
2791
|
+
path7.join(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions"),
|
|
2792
|
+
path7.join(home, ".config", "Claude", "local-agent-mode-sessions"),
|
|
2793
|
+
path7.join(home, "AppData", "Local", "Packages", "Claude_pzs8sxrjxfjjc", "LocalCache", "Roaming", "Claude", "local-agent-mode-sessions"),
|
|
2794
|
+
path7.join(home, "AppData", "Roaming", "Claude", "local-agent-mode-sessions")
|
|
2795
|
+
];
|
|
2796
|
+
}
|
|
2797
|
+
function isCoworkMetaFileName(name) {
|
|
2798
|
+
return /^local_[\w-]+\.json$/.test(name);
|
|
2799
|
+
}
|
|
2800
|
+
async function readCoworkMeta(filePath) {
|
|
2801
|
+
try {
|
|
2802
|
+
const raw = JSON.parse(await readFile4(filePath, "utf8"));
|
|
2803
|
+
return raw && typeof raw === "object" ? raw : {};
|
|
2804
|
+
} catch {
|
|
2805
|
+
return {};
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
async function isRegularFile(filePath) {
|
|
2809
|
+
try {
|
|
2810
|
+
return (await stat4(filePath)).isFile();
|
|
2811
|
+
} catch {
|
|
2812
|
+
return false;
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
async function resolveCoworkTranscript(sessionDir, cliSessionId) {
|
|
2816
|
+
if (!sessionDir || !cliSessionId) {
|
|
2817
|
+
return void 0;
|
|
2818
|
+
}
|
|
2819
|
+
const projectsDir = path7.join(sessionDir, ".claude", "projects");
|
|
2820
|
+
let entries;
|
|
2821
|
+
try {
|
|
2822
|
+
entries = await readdir3(projectsDir, { withFileTypes: true });
|
|
2823
|
+
} catch {
|
|
2824
|
+
return void 0;
|
|
2825
|
+
}
|
|
2826
|
+
const target = `${cliSessionId}.jsonl`;
|
|
2827
|
+
for (const entry of entries) {
|
|
2828
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
2829
|
+
continue;
|
|
2830
|
+
}
|
|
2831
|
+
const candidate = path7.join(projectsDir, entry.name, target);
|
|
2832
|
+
if (await isRegularFile(candidate)) {
|
|
2833
|
+
return candidate;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
return void 0;
|
|
2837
|
+
}
|
|
2838
|
+
async function coworkSubagentTranscripts(mainTranscript, cliSessionId) {
|
|
2839
|
+
const root = path7.join(path7.dirname(mainTranscript), cliSessionId, "subagents");
|
|
2840
|
+
const out = [];
|
|
2841
|
+
async function walk(dir) {
|
|
2842
|
+
let entries;
|
|
2843
|
+
try {
|
|
2844
|
+
entries = await readdir3(dir, { withFileTypes: true });
|
|
2845
|
+
} catch {
|
|
2846
|
+
return;
|
|
2847
|
+
}
|
|
2848
|
+
await Promise.all(entries.map(async (entry) => {
|
|
2849
|
+
const entryPath = path7.join(dir, entry.name);
|
|
2850
|
+
if (entry.isDirectory()) {
|
|
2851
|
+
await walk(entryPath);
|
|
2852
|
+
return;
|
|
2853
|
+
}
|
|
2854
|
+
if (entry.isFile() && /^agent-.+\.jsonl$/.test(entry.name)) {
|
|
2855
|
+
out.push(entryPath);
|
|
2856
|
+
}
|
|
2857
|
+
}));
|
|
2858
|
+
}
|
|
2859
|
+
await walk(root);
|
|
2860
|
+
return out.sort();
|
|
2861
|
+
}
|
|
2862
|
+
async function discoverCoworkTranscripts(root) {
|
|
2863
|
+
const transcripts = [];
|
|
2864
|
+
async function walk(dir) {
|
|
2865
|
+
let entries;
|
|
2866
|
+
try {
|
|
2867
|
+
entries = await readdir3(dir, { withFileTypes: true });
|
|
2868
|
+
} catch {
|
|
2869
|
+
return;
|
|
2870
|
+
}
|
|
2871
|
+
await Promise.all(entries.map(async (entry) => {
|
|
2872
|
+
const entryPath = path7.join(dir, entry.name);
|
|
2873
|
+
if (entry.isDirectory()) {
|
|
2874
|
+
if (entry.name.startsWith("local_") || entry.name === "skills-plugin" || entry.name === "node_modules" || entry.name === ".git") {
|
|
2875
|
+
return;
|
|
2876
|
+
}
|
|
2877
|
+
await walk(entryPath);
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2880
|
+
if (!entry.isFile() || !isCoworkMetaFileName(entry.name)) {
|
|
2881
|
+
return;
|
|
2882
|
+
}
|
|
2883
|
+
const metadata = await readCoworkMeta(entryPath);
|
|
2884
|
+
if (!metadata.cliSessionId) {
|
|
2885
|
+
return;
|
|
2886
|
+
}
|
|
2887
|
+
const sessionDir = entryPath.slice(0, -".json".length);
|
|
2888
|
+
const mainTranscript = await resolveCoworkTranscript(sessionDir, metadata.cliSessionId);
|
|
2889
|
+
if (!mainTranscript) {
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2892
|
+
transcripts.push({ transcriptPath: mainTranscript, metadataPath: entryPath, metadata });
|
|
2893
|
+
for (const subagentPath of await coworkSubagentTranscripts(mainTranscript, metadata.cliSessionId)) {
|
|
2894
|
+
transcripts.push({ transcriptPath: subagentPath, metadataPath: entryPath, metadata });
|
|
2895
|
+
}
|
|
2896
|
+
}));
|
|
2897
|
+
}
|
|
2898
|
+
await walk(root);
|
|
2899
|
+
return transcripts.sort((a, b) => a.transcriptPath.localeCompare(b.transcriptPath));
|
|
2900
|
+
}
|
|
2901
|
+
function coworkMetaPathForTranscript(transcriptPath) {
|
|
2902
|
+
const marker = `${path7.sep}.claude${path7.sep}projects${path7.sep}`;
|
|
2903
|
+
const index = transcriptPath.indexOf(marker);
|
|
2904
|
+
if (index < 0) {
|
|
2905
|
+
return void 0;
|
|
2906
|
+
}
|
|
2907
|
+
return `${transcriptPath.slice(0, index)}.json`;
|
|
2908
|
+
}
|
|
2909
|
+
function selectedFolder(meta) {
|
|
2910
|
+
return meta.userSelectedFolders?.find((item) => typeof item === "string" && item.trim());
|
|
2911
|
+
}
|
|
2912
|
+
function projectFromMeta(meta) {
|
|
2913
|
+
const folder = selectedFolder(meta);
|
|
2914
|
+
if (!folder) {
|
|
2915
|
+
return { project: "cowork" };
|
|
2916
|
+
}
|
|
2917
|
+
const resolved = path7.resolve(folder);
|
|
2918
|
+
return {
|
|
2919
|
+
project: path7.basename(resolved).replace(/-/g, "_") || "cowork",
|
|
2920
|
+
cwd: resolved
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2923
|
+
function prefixCoworkId(value) {
|
|
2924
|
+
if (!value) {
|
|
2925
|
+
return void 0;
|
|
2926
|
+
}
|
|
2927
|
+
return value.startsWith(COWORK_PREFIX) ? value : `${COWORK_PREFIX}${value}`;
|
|
2928
|
+
}
|
|
2929
|
+
function rebuildEventIdentity(event) {
|
|
2930
|
+
const importKey = createImportKey([
|
|
2931
|
+
event.source,
|
|
2932
|
+
event.refs?.sourcePathHash,
|
|
2933
|
+
event.refs?.sourceLine,
|
|
2934
|
+
event.type,
|
|
2935
|
+
event.refs?.sourceId
|
|
2936
|
+
]);
|
|
2937
|
+
return {
|
|
2938
|
+
...event,
|
|
2939
|
+
id: createStableEventId(importKey),
|
|
2940
|
+
refs: {
|
|
2941
|
+
...event.refs,
|
|
2942
|
+
importKey
|
|
2943
|
+
}
|
|
2944
|
+
};
|
|
2945
|
+
}
|
|
2946
|
+
async function parseClaudeCoworkSessionFile(filePath, options) {
|
|
2947
|
+
const metaPath = coworkMetaPathForTranscript(filePath);
|
|
2948
|
+
const metadata = metaPath ? await readCoworkMeta(metaPath) : {};
|
|
2949
|
+
const { project, cwd } = projectFromMeta(metadata);
|
|
2950
|
+
const parser = createClaudeCodeAdapter().parseSessionFile;
|
|
2951
|
+
if (!parser) {
|
|
2952
|
+
return [];
|
|
2953
|
+
}
|
|
2954
|
+
const events = await parser(filePath, options);
|
|
2955
|
+
return events.map((event) => {
|
|
2956
|
+
const sessionId = prefixCoworkId(event.sessionId);
|
|
2957
|
+
const turnId = prefixCoworkId(event.turnId);
|
|
2958
|
+
const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
|
|
2959
|
+
const refs = { ...event.refs };
|
|
2960
|
+
if (metadata.title) {
|
|
2961
|
+
refs.coworkTitleHash = `sha256:${createStableHash(metadata.title)}`;
|
|
2962
|
+
}
|
|
2963
|
+
const mapped = {
|
|
2964
|
+
...event,
|
|
2965
|
+
schemaVersion: event.schemaVersion || AGENT_TIME_SCHEMA_VERSION,
|
|
2966
|
+
source: "claude-cowork",
|
|
2967
|
+
agent: "claude-cowork",
|
|
2968
|
+
workspaceId,
|
|
2969
|
+
cwd: cwd || event.cwd,
|
|
2970
|
+
project,
|
|
2971
|
+
sessionId,
|
|
2972
|
+
turnId,
|
|
2973
|
+
refs
|
|
2974
|
+
};
|
|
2975
|
+
return rebuildEventIdentity(mapped);
|
|
2976
|
+
});
|
|
2977
|
+
}
|
|
2978
|
+
async function claudeCoworkBackfillFiles(sourceRoot, home, env) {
|
|
2979
|
+
const roots = sourceRoot ? [path7.resolve(sourceRoot)] : coworkDataDirs(home, env);
|
|
2980
|
+
const discovered = (await Promise.all(roots.map(discoverCoworkTranscripts))).flat();
|
|
2981
|
+
return Promise.all(discovered.map(async ({ transcriptPath, metadataPath }) => {
|
|
2982
|
+
const transcriptInfo = await stat4(transcriptPath);
|
|
2983
|
+
let modifiedAt = transcriptInfo.mtime;
|
|
2984
|
+
try {
|
|
2985
|
+
const metaInfo = await stat4(metadataPath);
|
|
2986
|
+
if (metaInfo.mtime > modifiedAt) {
|
|
2987
|
+
modifiedAt = metaInfo.mtime;
|
|
2988
|
+
}
|
|
2989
|
+
} catch {
|
|
2990
|
+
}
|
|
2991
|
+
return { path: transcriptPath, modifiedAt: modifiedAt.toISOString() };
|
|
2992
|
+
}));
|
|
2993
|
+
}
|
|
2994
|
+
function createClaudeCoworkAdapter() {
|
|
2995
|
+
return {
|
|
2996
|
+
id: "claude-cowork",
|
|
2997
|
+
label: "Claude Cowork",
|
|
2998
|
+
agentName: "claude-cowork",
|
|
2999
|
+
kind: "agent",
|
|
3000
|
+
detectPath(home, env) {
|
|
3001
|
+
return coworkDataDirs(home, env)[0] || path7.join(os3.homedir(), "Library", "Application Support", "Claude", "local-agent-mode-sessions");
|
|
3002
|
+
},
|
|
3003
|
+
installedPath(home, env) {
|
|
3004
|
+
return this.detectPath(home, env);
|
|
3005
|
+
},
|
|
3006
|
+
async isInstalled() {
|
|
3007
|
+
return false;
|
|
3008
|
+
},
|
|
3009
|
+
installEntries() {
|
|
3010
|
+
return [];
|
|
3011
|
+
},
|
|
3012
|
+
sourcePaths(home, env) {
|
|
3013
|
+
return coworkDataDirs(home, env);
|
|
3014
|
+
},
|
|
3015
|
+
async parseSessionFile(filePath, options) {
|
|
3016
|
+
if (!await pathExists(filePath)) {
|
|
3017
|
+
return [];
|
|
3018
|
+
}
|
|
3019
|
+
return parseClaudeCoworkSessionFile(filePath, options);
|
|
3020
|
+
}
|
|
3021
|
+
};
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
// src/adapters/codebuddy.ts
|
|
3025
|
+
import { readFile as readFile5, readdir as readdir4 } from "node:fs/promises";
|
|
3026
|
+
import path8 from "node:path";
|
|
2782
3027
|
async function parseCodebuddyTraceFile(filePath, options) {
|
|
2783
|
-
const text = await
|
|
3028
|
+
const text = await readFile5(filePath, "utf8");
|
|
2784
3029
|
const sourcePathHash = `sha256:${createStableHash(filePath)}`;
|
|
2785
3030
|
const events = [];
|
|
2786
3031
|
let traceFile;
|
|
@@ -2804,7 +3049,7 @@ async function parseCodebuddyTraceFile(filePath, options) {
|
|
|
2804
3049
|
if (!cwd && trace.startedAt) {
|
|
2805
3050
|
cwd = await cwdFromHistoryFile(trace.startedAt, options);
|
|
2806
3051
|
}
|
|
2807
|
-
const project = cwd ?
|
|
3052
|
+
const project = cwd ? path8.basename(cwd) : void 0;
|
|
2808
3053
|
const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
|
|
2809
3054
|
const model = trace.modelInfo?.models?.[0];
|
|
2810
3055
|
const baseEvent = (event) => ({
|
|
@@ -3090,15 +3335,15 @@ function modelUsageFromTrace(trace, generationIndex, totalGenerations) {
|
|
|
3090
3335
|
return { modelCalls: 1 };
|
|
3091
3336
|
}
|
|
3092
3337
|
function sessionIdFromTracePath(filePath) {
|
|
3093
|
-
const match =
|
|
3338
|
+
const match = path8.basename(filePath).match(/trace_([0-9a-f]{32})/);
|
|
3094
3339
|
return match?.[1] ? `codebuddy_${match[1]}` : `codebuddy_${createStableHash(filePath).slice(0, 24)}`;
|
|
3095
3340
|
}
|
|
3096
3341
|
function resolveHome(options) {
|
|
3097
|
-
return options.home ?
|
|
3342
|
+
return options.home ? path8.resolve(String(options.home)) : process.env.HOME || __require("node:os").homedir();
|
|
3098
3343
|
}
|
|
3099
3344
|
async function readCwdFromSession(sessionPath, matchSessionId) {
|
|
3100
3345
|
try {
|
|
3101
|
-
const text = await
|
|
3346
|
+
const text = await readFile5(sessionPath, "utf8");
|
|
3102
3347
|
const session = JSON.parse(text);
|
|
3103
3348
|
if (!isPlainObject(session)) {
|
|
3104
3349
|
return void 0;
|
|
@@ -3115,22 +3360,22 @@ async function readCwdFromSession(sessionPath, matchSessionId) {
|
|
|
3115
3360
|
}
|
|
3116
3361
|
async function cwdFromSessionFile(pid, traceSessionId, options) {
|
|
3117
3362
|
const home = resolveHome(options);
|
|
3118
|
-
const sessionsDir =
|
|
3363
|
+
const sessionsDir = path8.join(home, ".codebuddy", "sessions");
|
|
3119
3364
|
if (pid) {
|
|
3120
|
-
const cwd = await readCwdFromSession(
|
|
3365
|
+
const cwd = await readCwdFromSession(path8.join(sessionsDir, `${pid}.json`));
|
|
3121
3366
|
if (cwd) {
|
|
3122
3367
|
return cwd;
|
|
3123
3368
|
}
|
|
3124
3369
|
}
|
|
3125
3370
|
if (traceSessionId) {
|
|
3126
3371
|
try {
|
|
3127
|
-
const files = await
|
|
3372
|
+
const files = await readdir4(sessionsDir);
|
|
3128
3373
|
for (const f of files) {
|
|
3129
3374
|
if (!f.endsWith(".json")) {
|
|
3130
3375
|
continue;
|
|
3131
3376
|
}
|
|
3132
3377
|
const cwd = await readCwdFromSession(
|
|
3133
|
-
|
|
3378
|
+
path8.join(sessionsDir, f),
|
|
3134
3379
|
traceSessionId
|
|
3135
3380
|
);
|
|
3136
3381
|
if (cwd) {
|
|
@@ -3144,13 +3389,13 @@ async function cwdFromSessionFile(pid, traceSessionId, options) {
|
|
|
3144
3389
|
}
|
|
3145
3390
|
async function cwdFromHistoryFile(traceStartedAt, options) {
|
|
3146
3391
|
const home = resolveHome(options);
|
|
3147
|
-
const historyPath =
|
|
3392
|
+
const historyPath = path8.join(home, ".codebuddy", "history.jsonl");
|
|
3148
3393
|
const traceMs = Date.parse(traceStartedAt);
|
|
3149
3394
|
if (Number.isNaN(traceMs)) {
|
|
3150
3395
|
return void 0;
|
|
3151
3396
|
}
|
|
3152
3397
|
try {
|
|
3153
|
-
const text = await
|
|
3398
|
+
const text = await readFile5(historyPath, "utf8");
|
|
3154
3399
|
let bestCwd;
|
|
3155
3400
|
let bestDistance = Infinity;
|
|
3156
3401
|
for (const line of text.split("\n")) {
|
|
@@ -3206,9 +3451,9 @@ function hookConfig3() {
|
|
|
3206
3451
|
function codebuddyConfigDir(home, env) {
|
|
3207
3452
|
const override = env?.CODEBUDDY_CONFIG_DIR;
|
|
3208
3453
|
if (override && override.trim()) {
|
|
3209
|
-
return
|
|
3454
|
+
return path8.resolve(override);
|
|
3210
3455
|
}
|
|
3211
|
-
return
|
|
3456
|
+
return path8.join(home, ".codebuddy");
|
|
3212
3457
|
}
|
|
3213
3458
|
function createCodebuddyAdapter() {
|
|
3214
3459
|
return {
|
|
@@ -3220,50 +3465,50 @@ function createCodebuddyAdapter() {
|
|
|
3220
3465
|
return codebuddyConfigDir(home, env);
|
|
3221
3466
|
},
|
|
3222
3467
|
installedPath(home, env) {
|
|
3223
|
-
return
|
|
3468
|
+
return path8.join(codebuddyConfigDir(home, env), "settings.json");
|
|
3224
3469
|
},
|
|
3225
3470
|
async isInstalled(home, env) {
|
|
3226
3471
|
return isHooksJsonInstalled(
|
|
3227
|
-
|
|
3472
|
+
path8.join(codebuddyConfigDir(home, env), "settings.json"),
|
|
3228
3473
|
"vibetime hook --agent codebuddy"
|
|
3229
3474
|
);
|
|
3230
3475
|
},
|
|
3231
3476
|
installEntries(home, env) {
|
|
3232
3477
|
return [{
|
|
3233
3478
|
kind: "hooks-json",
|
|
3234
|
-
path:
|
|
3479
|
+
path: path8.join(codebuddyConfigDir(home, env), "settings.json"),
|
|
3235
3480
|
content: hookConfig3()
|
|
3236
3481
|
}];
|
|
3237
3482
|
},
|
|
3238
3483
|
sourcePaths(home, env) {
|
|
3239
3484
|
const base = codebuddyConfigDir(home, env);
|
|
3240
3485
|
return [
|
|
3241
|
-
|
|
3486
|
+
path8.join(base, "traces")
|
|
3242
3487
|
];
|
|
3243
3488
|
},
|
|
3244
3489
|
parseSessionFile: parseCodebuddyTraceFile
|
|
3245
3490
|
};
|
|
3246
3491
|
}
|
|
3247
3492
|
async function codebuddyBackfillFiles(sourceRoot, home, env) {
|
|
3248
|
-
const base = sourceRoot ||
|
|
3493
|
+
const base = sourceRoot || path8.join(codebuddyConfigDir(home, env), "traces");
|
|
3249
3494
|
const files = [];
|
|
3250
3495
|
try {
|
|
3251
|
-
const pidDirs = await
|
|
3496
|
+
const pidDirs = await readdir4(base, { withFileTypes: true });
|
|
3252
3497
|
for (const pidDir of pidDirs) {
|
|
3253
3498
|
if (!pidDir.isDirectory()) {
|
|
3254
3499
|
continue;
|
|
3255
3500
|
}
|
|
3256
|
-
const traceDir =
|
|
3501
|
+
const traceDir = path8.join(base, pidDir.name);
|
|
3257
3502
|
try {
|
|
3258
|
-
const entries = await
|
|
3503
|
+
const entries = await readdir4(traceDir);
|
|
3259
3504
|
for (const entry of entries) {
|
|
3260
3505
|
if (!entry.endsWith(".json") || !entry.startsWith("trace_")) {
|
|
3261
3506
|
continue;
|
|
3262
3507
|
}
|
|
3263
|
-
const filePath =
|
|
3508
|
+
const filePath = path8.join(traceDir, entry);
|
|
3264
3509
|
try {
|
|
3265
|
-
const
|
|
3266
|
-
files.push({ path: filePath, modifiedAt:
|
|
3510
|
+
const stat9 = await import("node:fs/promises").then((fs) => fs.stat(filePath));
|
|
3511
|
+
files.push({ path: filePath, modifiedAt: stat9.mtime.toISOString() });
|
|
3267
3512
|
} catch {
|
|
3268
3513
|
}
|
|
3269
3514
|
}
|
|
@@ -3276,8 +3521,8 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
3276
3521
|
}
|
|
3277
3522
|
|
|
3278
3523
|
// src/adapters/codex.ts
|
|
3279
|
-
import { readFile as
|
|
3280
|
-
import
|
|
3524
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
3525
|
+
import path9 from "node:path";
|
|
3281
3526
|
|
|
3282
3527
|
// src/lib/diff.ts
|
|
3283
3528
|
function diffStats(diff) {
|
|
@@ -3324,7 +3569,7 @@ function fileActivitiesFromPatchChanges(changes, ts, cwd, displayFilePath3) {
|
|
|
3324
3569
|
|
|
3325
3570
|
// src/adapters/codex.ts
|
|
3326
3571
|
async function parseCodexSessionFile(filePath, options) {
|
|
3327
|
-
const text = await
|
|
3572
|
+
const text = await readFile6(filePath, "utf8");
|
|
3328
3573
|
const lines = text.split("\n").filter(Boolean);
|
|
3329
3574
|
const sourcePathHash = `sha256:${createStableHash(filePath)}`;
|
|
3330
3575
|
const events = [];
|
|
@@ -3357,7 +3602,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
3357
3602
|
sessionMetaLocked = true;
|
|
3358
3603
|
sessionId = stringField(payload, "id") || sessionId;
|
|
3359
3604
|
cwd = stringField(payload, "cwd") || cwd;
|
|
3360
|
-
project = cwd ?
|
|
3605
|
+
project = cwd ? path9.basename(cwd) : project;
|
|
3361
3606
|
model = stringField(payload, "model_provider") || model;
|
|
3362
3607
|
events.push(withBackfillRefs({
|
|
3363
3608
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
@@ -3378,7 +3623,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
3378
3623
|
if (topType === "turn_context") {
|
|
3379
3624
|
currentTurnId = stringField(payload, "turn_id") || currentTurnId;
|
|
3380
3625
|
cwd = stringField(payload, "cwd") || cwd;
|
|
3381
|
-
project = cwd ?
|
|
3626
|
+
project = cwd ? path9.basename(cwd) : project;
|
|
3382
3627
|
model = stringField(payload, "model") || model;
|
|
3383
3628
|
const tier = stringField(payload, "service_tier");
|
|
3384
3629
|
if (tier) {
|
|
@@ -3820,11 +4065,11 @@ function functionCallArguments(payload) {
|
|
|
3820
4065
|
}
|
|
3821
4066
|
}
|
|
3822
4067
|
function displayFilePath2(filePath, cwd) {
|
|
3823
|
-
if (!cwd || !
|
|
4068
|
+
if (!cwd || !path9.isAbsolute(filePath)) {
|
|
3824
4069
|
return filePath;
|
|
3825
4070
|
}
|
|
3826
|
-
const relative =
|
|
3827
|
-
return relative && !relative.startsWith("..") && !
|
|
4071
|
+
const relative = path9.relative(cwd, filePath);
|
|
4072
|
+
return relative && !relative.startsWith("..") && !path9.isAbsolute(relative) ? relative : filePath;
|
|
3828
4073
|
}
|
|
3829
4074
|
var codexHandler = (msg) => hookHandler("codex", msg);
|
|
3830
4075
|
function hookConfig4() {
|
|
@@ -3843,9 +4088,9 @@ function hookConfig4() {
|
|
|
3843
4088
|
function codexHome(home, env) {
|
|
3844
4089
|
const override = env?.CODEX_HOME;
|
|
3845
4090
|
if (override && override.trim()) {
|
|
3846
|
-
return
|
|
4091
|
+
return path9.resolve(override);
|
|
3847
4092
|
}
|
|
3848
|
-
return
|
|
4093
|
+
return path9.join(home, ".codex");
|
|
3849
4094
|
}
|
|
3850
4095
|
function createCodexAdapter() {
|
|
3851
4096
|
return {
|
|
@@ -3857,26 +4102,26 @@ function createCodexAdapter() {
|
|
|
3857
4102
|
return codexHome(home, env);
|
|
3858
4103
|
},
|
|
3859
4104
|
installedPath(home, env) {
|
|
3860
|
-
return
|
|
4105
|
+
return path9.join(codexHome(home, env), "hooks.json");
|
|
3861
4106
|
},
|
|
3862
4107
|
async isInstalled(home, env) {
|
|
3863
4108
|
return isHooksJsonInstalled(
|
|
3864
|
-
|
|
4109
|
+
path9.join(codexHome(home, env), "hooks.json"),
|
|
3865
4110
|
"vibetime hook --agent codex"
|
|
3866
4111
|
);
|
|
3867
4112
|
},
|
|
3868
4113
|
installEntries(home, env) {
|
|
3869
4114
|
return [{
|
|
3870
4115
|
kind: "hooks-json",
|
|
3871
|
-
path:
|
|
4116
|
+
path: path9.join(codexHome(home, env), "hooks.json"),
|
|
3872
4117
|
content: hookConfig4()
|
|
3873
4118
|
}];
|
|
3874
4119
|
},
|
|
3875
4120
|
sourcePaths(home, env) {
|
|
3876
4121
|
const base = codexHome(home, env);
|
|
3877
4122
|
return [
|
|
3878
|
-
|
|
3879
|
-
|
|
4123
|
+
path9.join(base, "sessions"),
|
|
4124
|
+
path9.join(base, "history.jsonl")
|
|
3880
4125
|
];
|
|
3881
4126
|
},
|
|
3882
4127
|
parseSessionFile: parseCodexSessionFile
|
|
@@ -3884,8 +4129,8 @@ function createCodexAdapter() {
|
|
|
3884
4129
|
}
|
|
3885
4130
|
|
|
3886
4131
|
// src/adapters/opencode.ts
|
|
3887
|
-
import
|
|
3888
|
-
import
|
|
4132
|
+
import os4 from "node:os";
|
|
4133
|
+
import path10 from "node:path";
|
|
3889
4134
|
async function parseOpenCodeSessionFile(dbPath, options) {
|
|
3890
4135
|
const { DatabaseSync } = await import("node:sqlite");
|
|
3891
4136
|
if (!dbPath.endsWith(".db")) {
|
|
@@ -3916,7 +4161,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
3916
4161
|
for (const session of sessions) {
|
|
3917
4162
|
const sessionId = session.id;
|
|
3918
4163
|
const cwd = session.directory || session.path || void 0;
|
|
3919
|
-
const project = cwd ?
|
|
4164
|
+
const project = cwd ? path10.basename(cwd) : void 0;
|
|
3920
4165
|
const sessionTs = msToIso(session.time_created);
|
|
3921
4166
|
events.push(baseOpenCodeEvent({
|
|
3922
4167
|
ts: sessionTs,
|
|
@@ -4010,7 +4255,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
4010
4255
|
const provider = currentProvider;
|
|
4011
4256
|
const pathObj = objectField(info, "path");
|
|
4012
4257
|
const assistantCwd = stringField(pathObj, "cwd") || cwd;
|
|
4013
|
-
const assistantProject = assistantCwd ?
|
|
4258
|
+
const assistantProject = assistantCwd ? path10.basename(assistantCwd) : project;
|
|
4014
4259
|
const completedTs = numberField(objectField(info, "time"), "completed");
|
|
4015
4260
|
const createdTs = timeCreated;
|
|
4016
4261
|
const tokens = opencodeUsageFromInfo(info);
|
|
@@ -4254,33 +4499,33 @@ function opencodeUsageFromInfo(info) {
|
|
|
4254
4499
|
function opencodeConfigDir(home, env) {
|
|
4255
4500
|
const override = env?.OPENCODE_CONFIG_DIR;
|
|
4256
4501
|
if (override && override.trim()) {
|
|
4257
|
-
return
|
|
4502
|
+
return path10.resolve(override);
|
|
4258
4503
|
}
|
|
4259
4504
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
4260
4505
|
if (xdgConfig && xdgConfig.trim()) {
|
|
4261
|
-
return
|
|
4506
|
+
return path10.join(path10.resolve(xdgConfig), "opencode");
|
|
4262
4507
|
}
|
|
4263
|
-
return
|
|
4508
|
+
return path10.join(home, ".config", "opencode");
|
|
4264
4509
|
}
|
|
4265
4510
|
function opencodeDataCandidates(home, env) {
|
|
4266
4511
|
const xdgData = env?.XDG_DATA_HOME;
|
|
4267
|
-
const primary = xdgData && xdgData.trim() ?
|
|
4268
|
-
return [primary,
|
|
4512
|
+
const primary = xdgData && xdgData.trim() ? path10.join(path10.resolve(xdgData), "opencode", "opencode.db") : path10.join(home, ".local", "share", "opencode", "opencode.db");
|
|
4513
|
+
return [primary, path10.join(home, ".opencode", "opencode.db")];
|
|
4269
4514
|
}
|
|
4270
|
-
async function opencodeBackfillFiles(sourceRoot, home =
|
|
4271
|
-
const { stat:
|
|
4515
|
+
async function opencodeBackfillFiles(sourceRoot, home = os4.homedir(), env) {
|
|
4516
|
+
const { stat: stat9 } = await import("node:fs/promises");
|
|
4272
4517
|
if (sourceRoot) {
|
|
4273
4518
|
if (!sourceRoot.endsWith(".db")) {
|
|
4274
4519
|
return [];
|
|
4275
4520
|
}
|
|
4276
|
-
const info = await
|
|
4521
|
+
const info = await stat9(sourceRoot).catch(() => null);
|
|
4277
4522
|
if (!info) {
|
|
4278
4523
|
return [];
|
|
4279
4524
|
}
|
|
4280
4525
|
return [{ path: sourceRoot, modifiedAt: info.mtime.toISOString() }];
|
|
4281
4526
|
}
|
|
4282
4527
|
for (const candidatePath of opencodeDataCandidates(home, env)) {
|
|
4283
|
-
const info = await
|
|
4528
|
+
const info = await stat9(candidatePath).catch(() => null);
|
|
4284
4529
|
if (info) {
|
|
4285
4530
|
return [{ path: candidatePath, modifiedAt: info.mtime.toISOString() }];
|
|
4286
4531
|
}
|
|
@@ -4345,12 +4590,12 @@ function createOpenCodeAdapter() {
|
|
|
4345
4590
|
return opencodeConfigDir(home, env);
|
|
4346
4591
|
},
|
|
4347
4592
|
installedPath(home, env) {
|
|
4348
|
-
return
|
|
4593
|
+
return path10.join(opencodeConfigDir(home, env), PLUGIN_PATH);
|
|
4349
4594
|
},
|
|
4350
4595
|
async isInstalled(home, env) {
|
|
4351
4596
|
try {
|
|
4352
4597
|
const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
4353
|
-
return await pathExists2(
|
|
4598
|
+
return await pathExists2(path10.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path10.join(".opencode", PLUGIN_PATH));
|
|
4354
4599
|
} catch {
|
|
4355
4600
|
return false;
|
|
4356
4601
|
}
|
|
@@ -4358,7 +4603,7 @@ function createOpenCodeAdapter() {
|
|
|
4358
4603
|
installEntries(home, env) {
|
|
4359
4604
|
return [{
|
|
4360
4605
|
kind: "file",
|
|
4361
|
-
path:
|
|
4606
|
+
path: path10.join(opencodeConfigDir(home, env), PLUGIN_PATH),
|
|
4362
4607
|
content: opencodePluginContent()
|
|
4363
4608
|
}];
|
|
4364
4609
|
},
|
|
@@ -4370,10 +4615,10 @@ function createOpenCodeAdapter() {
|
|
|
4370
4615
|
}
|
|
4371
4616
|
|
|
4372
4617
|
// src/adapters/pi.ts
|
|
4373
|
-
import { readFile as
|
|
4374
|
-
import
|
|
4618
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
4619
|
+
import path11 from "node:path";
|
|
4375
4620
|
async function parsePiSessionFile(filePath, options) {
|
|
4376
|
-
const text = await
|
|
4621
|
+
const text = await readFile7(filePath, "utf8");
|
|
4377
4622
|
const lines = text.split("\n").filter(Boolean);
|
|
4378
4623
|
let sessionId;
|
|
4379
4624
|
let cwd;
|
|
@@ -4403,7 +4648,7 @@ async function parsePiSessionFile(filePath, options) {
|
|
|
4403
4648
|
sessionId = stringField(raw, "id") || state.sessionId;
|
|
4404
4649
|
state.sessionId = sessionId || state.sessionId;
|
|
4405
4650
|
cwd = stringField(raw, "cwd") || cwd;
|
|
4406
|
-
project = cwd ?
|
|
4651
|
+
project = cwd ? path11.basename(cwd) : project;
|
|
4407
4652
|
continue;
|
|
4408
4653
|
}
|
|
4409
4654
|
if (entryType === "model_change") {
|
|
@@ -4804,16 +5049,16 @@ export default function (pi: ExtensionAPI) {
|
|
|
4804
5049
|
function piAgentDir(home, env) {
|
|
4805
5050
|
const override = env?.PI_CODING_AGENT_DIR;
|
|
4806
5051
|
if (override && override.trim()) {
|
|
4807
|
-
return
|
|
5052
|
+
return path11.resolve(override);
|
|
4808
5053
|
}
|
|
4809
|
-
return
|
|
5054
|
+
return path11.join(home, ".pi", "agent");
|
|
4810
5055
|
}
|
|
4811
5056
|
function piSessionDir(home, env) {
|
|
4812
5057
|
const override = env?.PI_CODING_AGENT_SESSION_DIR;
|
|
4813
5058
|
if (override && override.trim()) {
|
|
4814
|
-
return
|
|
5059
|
+
return path11.resolve(override);
|
|
4815
5060
|
}
|
|
4816
|
-
return
|
|
5061
|
+
return path11.join(piAgentDir(home, env), "sessions");
|
|
4817
5062
|
}
|
|
4818
5063
|
function createPiAdapter() {
|
|
4819
5064
|
return {
|
|
@@ -4825,12 +5070,12 @@ function createPiAdapter() {
|
|
|
4825
5070
|
return piAgentDir(home, env);
|
|
4826
5071
|
},
|
|
4827
5072
|
installedPath(home, env) {
|
|
4828
|
-
return
|
|
5073
|
+
return path11.join(piAgentDir(home, env), "extensions", "vibetime.ts");
|
|
4829
5074
|
},
|
|
4830
5075
|
async isInstalled(home, env) {
|
|
4831
5076
|
try {
|
|
4832
5077
|
const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
4833
|
-
return await pathExists2(
|
|
5078
|
+
return await pathExists2(path11.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
|
|
4834
5079
|
} catch {
|
|
4835
5080
|
return false;
|
|
4836
5081
|
}
|
|
@@ -4838,7 +5083,7 @@ function createPiAdapter() {
|
|
|
4838
5083
|
installEntries(home, env) {
|
|
4839
5084
|
return [{
|
|
4840
5085
|
kind: "file",
|
|
4841
|
-
path:
|
|
5086
|
+
path: path11.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
|
|
4842
5087
|
content: piExtensionContent()
|
|
4843
5088
|
}];
|
|
4844
5089
|
},
|
|
@@ -4850,11 +5095,11 @@ function createPiAdapter() {
|
|
|
4850
5095
|
}
|
|
4851
5096
|
|
|
4852
5097
|
// src/adapters/qoder-cn.ts
|
|
4853
|
-
import { readdir as
|
|
4854
|
-
import
|
|
4855
|
-
import
|
|
5098
|
+
import { readdir as readdir5, readFile as readFile8, stat as stat5 } from "node:fs/promises";
|
|
5099
|
+
import os5 from "node:os";
|
|
5100
|
+
import path12 from "node:path";
|
|
4856
5101
|
function parseQoderCnPaths(filePath) {
|
|
4857
|
-
const parts = filePath.split(
|
|
5102
|
+
const parts = filePath.split(path12.sep);
|
|
4858
5103
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
4859
5104
|
let sessionId = "";
|
|
4860
5105
|
let projectName = "";
|
|
@@ -4863,20 +5108,20 @@ function parseQoderCnPaths(filePath) {
|
|
|
4863
5108
|
sessionId = parts[subagentsIdx - 1];
|
|
4864
5109
|
projectName = parts[subagentsIdx - 2];
|
|
4865
5110
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
4866
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
5111
|
+
configDir2 = parts.slice(0, projectsIdx).join(path12.sep);
|
|
4867
5112
|
} else {
|
|
4868
5113
|
const filename = parts.at(-1) || "";
|
|
4869
|
-
sessionId =
|
|
5114
|
+
sessionId = path12.basename(filename, ".jsonl");
|
|
4870
5115
|
projectName = parts.at(-2) || "";
|
|
4871
5116
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
4872
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
5117
|
+
configDir2 = parts.slice(0, projectsIdx).join(path12.sep);
|
|
4873
5118
|
}
|
|
4874
5119
|
return { configDir: configDir2, projectName, sessionId };
|
|
4875
5120
|
}
|
|
4876
5121
|
async function loadQoderCnModelNames(configDir2) {
|
|
4877
5122
|
try {
|
|
4878
|
-
const dynamicTextsPath =
|
|
4879
|
-
const content = await
|
|
5123
|
+
const dynamicTextsPath = path12.join(configDir2, ".auth", "dynamic-texts.json");
|
|
5124
|
+
const content = await readFile8(dynamicTextsPath, "utf8");
|
|
4880
5125
|
const json = JSON.parse(content);
|
|
4881
5126
|
const texts = json.texts || {};
|
|
4882
5127
|
const map = {};
|
|
@@ -4893,15 +5138,15 @@ async function loadQoderCnModelNames(configDir2) {
|
|
|
4893
5138
|
}
|
|
4894
5139
|
async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
4895
5140
|
const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
|
|
4896
|
-
const segmentsPath =
|
|
5141
|
+
const segmentsPath = path12.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
4897
5142
|
const modelCalls = [];
|
|
4898
5143
|
try {
|
|
4899
|
-
const files = await
|
|
5144
|
+
const files = await readdir5(segmentsPath);
|
|
4900
5145
|
for (const file of files) {
|
|
4901
5146
|
if (!file.endsWith(".jsonl")) {
|
|
4902
5147
|
continue;
|
|
4903
5148
|
}
|
|
4904
|
-
const content = await
|
|
5149
|
+
const content = await readFile8(path12.join(segmentsPath, file), "utf8");
|
|
4905
5150
|
let currentTurnIsSubagent = false;
|
|
4906
5151
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
4907
5152
|
const raw = parseJsonLine(line);
|
|
@@ -4934,7 +5179,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
|
|
|
4934
5179
|
return modelCalls.filter((call) => call.isSubagent === isSubagentSession);
|
|
4935
5180
|
}
|
|
4936
5181
|
async function parseQoderCnSessionFile(filePath, options) {
|
|
4937
|
-
const text = await
|
|
5182
|
+
const text = await readFile8(filePath, "utf8");
|
|
4938
5183
|
const lines = text.split("\n").filter(Boolean);
|
|
4939
5184
|
const { configDir: configDir2 } = parseQoderCnPaths(filePath);
|
|
4940
5185
|
const projectContext = await qoderCnProjectContextFromLines(filePath, lines, options, configDir2);
|
|
@@ -4969,7 +5214,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
4969
5214
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
4970
5215
|
state.sessionId = sessionId;
|
|
4971
5216
|
cwd = stringField(raw, "cwd") || cwd;
|
|
4972
|
-
project = projectContext.project || (cwd ?
|
|
5217
|
+
project = projectContext.project || (cwd ? path12.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
|
|
4973
5218
|
if (!ts) {
|
|
4974
5219
|
continue;
|
|
4975
5220
|
}
|
|
@@ -5398,24 +5643,24 @@ function isNoisePrompt(text) {
|
|
|
5398
5643
|
}
|
|
5399
5644
|
async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
5400
5645
|
const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
|
|
5401
|
-
const isSubagent = filePath.includes(`${
|
|
5646
|
+
const isSubagent = filePath.includes(`${path12.sep}subagents${path12.sep}`);
|
|
5402
5647
|
let cwds = [];
|
|
5403
5648
|
for (const line of lines) {
|
|
5404
5649
|
const raw = parseJsonLine(line);
|
|
5405
5650
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
5406
|
-
if (cwd &&
|
|
5651
|
+
if (cwd && path12.isAbsolute(cwd)) {
|
|
5407
5652
|
cwds.push(cwd);
|
|
5408
5653
|
}
|
|
5409
5654
|
}
|
|
5410
5655
|
if (isSubagent) {
|
|
5411
|
-
const parentSessionPath =
|
|
5656
|
+
const parentSessionPath = path12.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
5412
5657
|
try {
|
|
5413
|
-
const parentText = await
|
|
5658
|
+
const parentText = await readFile8(parentSessionPath, "utf8");
|
|
5414
5659
|
const parentCwds = [];
|
|
5415
5660
|
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
5416
5661
|
const raw = parseJsonLine(line);
|
|
5417
5662
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
5418
|
-
if (cwd &&
|
|
5663
|
+
if (cwd && path12.isAbsolute(cwd)) {
|
|
5419
5664
|
parentCwds.push(cwd);
|
|
5420
5665
|
}
|
|
5421
5666
|
}
|
|
@@ -5426,7 +5671,7 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
5426
5671
|
}
|
|
5427
5672
|
}
|
|
5428
5673
|
const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
|
|
5429
|
-
const project = cwds.length > 0 ?
|
|
5674
|
+
const project = cwds.length > 0 ? path12.basename(cwds[0]) : root ? path12.basename(root) : await qoderCnProjectFromFilePath(filePath, options);
|
|
5430
5675
|
return {
|
|
5431
5676
|
project,
|
|
5432
5677
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -5435,15 +5680,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
5435
5680
|
async function gitRootFromCwds2(cwds) {
|
|
5436
5681
|
const seen = /* @__PURE__ */ new Set();
|
|
5437
5682
|
for (const cwd of cwds) {
|
|
5438
|
-
let current =
|
|
5683
|
+
let current = path12.resolve(cwd);
|
|
5439
5684
|
while (!seen.has(current)) {
|
|
5440
5685
|
seen.add(current);
|
|
5441
5686
|
try {
|
|
5442
|
-
await
|
|
5687
|
+
await stat5(path12.join(current, ".git"));
|
|
5443
5688
|
return current;
|
|
5444
5689
|
} catch {
|
|
5445
5690
|
}
|
|
5446
|
-
const parent =
|
|
5691
|
+
const parent = path12.dirname(current);
|
|
5447
5692
|
if (parent === current) {
|
|
5448
5693
|
break;
|
|
5449
5694
|
}
|
|
@@ -5454,12 +5699,12 @@ async function gitRootFromCwds2(cwds) {
|
|
|
5454
5699
|
}
|
|
5455
5700
|
function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
5456
5701
|
for (const cwd of cwds) {
|
|
5457
|
-
let current =
|
|
5702
|
+
let current = path12.resolve(cwd);
|
|
5458
5703
|
while (true) {
|
|
5459
5704
|
if (encodeQoderCnProjectPath(current) === projectDir) {
|
|
5460
5705
|
return current;
|
|
5461
5706
|
}
|
|
5462
|
-
const parent =
|
|
5707
|
+
const parent = path12.dirname(current);
|
|
5463
5708
|
if (parent === current) {
|
|
5464
5709
|
break;
|
|
5465
5710
|
}
|
|
@@ -5469,14 +5714,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
|
5469
5714
|
return void 0;
|
|
5470
5715
|
}
|
|
5471
5716
|
function encodeQoderCnProjectPath(value) {
|
|
5472
|
-
return
|
|
5717
|
+
return path12.resolve(value).split(path12.sep).join("-").replace(/_/g, "-");
|
|
5473
5718
|
}
|
|
5474
5719
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
5475
|
-
const projectDir =
|
|
5476
|
-
const home = options ?
|
|
5720
|
+
const projectDir = path12.basename(path12.dirname(filePath));
|
|
5721
|
+
const home = options ? path12.resolve(stringOption(options.home) || os5.homedir()) : os5.homedir();
|
|
5477
5722
|
const resolved = await resolveQoderCnProjectPath(projectDir, home);
|
|
5478
5723
|
if (resolved) {
|
|
5479
|
-
return
|
|
5724
|
+
return path12.basename(resolved);
|
|
5480
5725
|
}
|
|
5481
5726
|
const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
|
|
5482
5727
|
if (projectDir.startsWith(homePrefix)) {
|
|
@@ -5496,12 +5741,12 @@ async function resolveQoderCnProjectPath(projectDir, home) {
|
|
|
5496
5741
|
while (projectDir.startsWith(`${currentEncoded}-`)) {
|
|
5497
5742
|
let matchedChild;
|
|
5498
5743
|
try {
|
|
5499
|
-
const entries = await
|
|
5744
|
+
const entries = await readdir5(current, { withFileTypes: true });
|
|
5500
5745
|
for (const entry of entries) {
|
|
5501
5746
|
if (!entry.isDirectory()) {
|
|
5502
5747
|
continue;
|
|
5503
5748
|
}
|
|
5504
|
-
const candidate =
|
|
5749
|
+
const candidate = path12.join(current, entry.name);
|
|
5505
5750
|
const encoded = encodeQoderCnProjectPath(candidate);
|
|
5506
5751
|
if (encoded === projectDir) {
|
|
5507
5752
|
return candidate;
|
|
@@ -5546,9 +5791,9 @@ function hookConfig5() {
|
|
|
5546
5791
|
function qoderCnConfigDir(home, env) {
|
|
5547
5792
|
const override = env?.QODER_CN_CONFIG_DIR;
|
|
5548
5793
|
if (override && override.trim()) {
|
|
5549
|
-
return
|
|
5794
|
+
return path12.resolve(override);
|
|
5550
5795
|
}
|
|
5551
|
-
return
|
|
5796
|
+
return path12.join(home, ".qoder-cn");
|
|
5552
5797
|
}
|
|
5553
5798
|
function createQoderCnAdapter() {
|
|
5554
5799
|
return {
|
|
@@ -5560,27 +5805,27 @@ function createQoderCnAdapter() {
|
|
|
5560
5805
|
return qoderCnConfigDir(home, env);
|
|
5561
5806
|
},
|
|
5562
5807
|
installedPath(home, env) {
|
|
5563
|
-
return
|
|
5808
|
+
return path12.join(qoderCnConfigDir(home, env), "settings.json");
|
|
5564
5809
|
},
|
|
5565
5810
|
async isInstalled(home, env) {
|
|
5566
5811
|
return isHooksJsonInstalled(
|
|
5567
|
-
|
|
5812
|
+
path12.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
5568
5813
|
"vibetime hook --agent qoder-cn"
|
|
5569
5814
|
);
|
|
5570
5815
|
},
|
|
5571
5816
|
installEntries(home, env) {
|
|
5572
5817
|
return [{
|
|
5573
5818
|
kind: "hooks-json",
|
|
5574
|
-
path:
|
|
5819
|
+
path: path12.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
5575
5820
|
content: hookConfig5()
|
|
5576
5821
|
}];
|
|
5577
5822
|
},
|
|
5578
5823
|
sourcePaths(home, env) {
|
|
5579
5824
|
const base = qoderCnConfigDir(home, env);
|
|
5580
5825
|
return [
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5826
|
+
path12.join(base, "projects"),
|
|
5827
|
+
path12.join(base, ".qoder.json"),
|
|
5828
|
+
path12.join(home, ".qoder.json")
|
|
5584
5829
|
];
|
|
5585
5830
|
},
|
|
5586
5831
|
parseSessionFile: parseQoderCnSessionFile
|
|
@@ -5588,11 +5833,11 @@ function createQoderCnAdapter() {
|
|
|
5588
5833
|
}
|
|
5589
5834
|
|
|
5590
5835
|
// src/adapters/qoder.ts
|
|
5591
|
-
import { readdir as
|
|
5592
|
-
import
|
|
5593
|
-
import
|
|
5836
|
+
import { readdir as readdir6, readFile as readFile9, stat as stat6 } from "node:fs/promises";
|
|
5837
|
+
import os6 from "node:os";
|
|
5838
|
+
import path13 from "node:path";
|
|
5594
5839
|
function parseQoderPaths(filePath) {
|
|
5595
|
-
const parts = filePath.split(
|
|
5840
|
+
const parts = filePath.split(path13.sep);
|
|
5596
5841
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
5597
5842
|
let sessionId = "";
|
|
5598
5843
|
let projectName = "";
|
|
@@ -5601,20 +5846,20 @@ function parseQoderPaths(filePath) {
|
|
|
5601
5846
|
sessionId = parts[subagentsIdx - 1];
|
|
5602
5847
|
projectName = parts[subagentsIdx - 2];
|
|
5603
5848
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
5604
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
5849
|
+
configDir2 = parts.slice(0, projectsIdx).join(path13.sep);
|
|
5605
5850
|
} else {
|
|
5606
5851
|
const filename = parts.at(-1) || "";
|
|
5607
|
-
sessionId =
|
|
5852
|
+
sessionId = path13.basename(filename, ".jsonl");
|
|
5608
5853
|
projectName = parts.at(-2) || "";
|
|
5609
5854
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
5610
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
5855
|
+
configDir2 = parts.slice(0, projectsIdx).join(path13.sep);
|
|
5611
5856
|
}
|
|
5612
5857
|
return { configDir: configDir2, projectName, sessionId };
|
|
5613
5858
|
}
|
|
5614
5859
|
async function loadQoderModelNames(configDir2) {
|
|
5615
5860
|
try {
|
|
5616
|
-
const dynamicTextsPath =
|
|
5617
|
-
const content = await
|
|
5861
|
+
const dynamicTextsPath = path13.join(configDir2, ".auth", "dynamic-texts.json");
|
|
5862
|
+
const content = await readFile9(dynamicTextsPath, "utf8");
|
|
5618
5863
|
const json = JSON.parse(content);
|
|
5619
5864
|
const texts = json.texts || {};
|
|
5620
5865
|
const map = {};
|
|
@@ -5631,15 +5876,15 @@ async function loadQoderModelNames(configDir2) {
|
|
|
5631
5876
|
}
|
|
5632
5877
|
async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
5633
5878
|
const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
|
|
5634
|
-
const segmentsPath =
|
|
5879
|
+
const segmentsPath = path13.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
5635
5880
|
const modelCalls = [];
|
|
5636
5881
|
try {
|
|
5637
|
-
const files = await
|
|
5882
|
+
const files = await readdir6(segmentsPath);
|
|
5638
5883
|
for (const file of files) {
|
|
5639
5884
|
if (!file.endsWith(".jsonl")) {
|
|
5640
5885
|
continue;
|
|
5641
5886
|
}
|
|
5642
|
-
const content = await
|
|
5887
|
+
const content = await readFile9(path13.join(segmentsPath, file), "utf8");
|
|
5643
5888
|
let currentTurnIsSubagent = false;
|
|
5644
5889
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
5645
5890
|
const raw = parseJsonLine(line);
|
|
@@ -5672,7 +5917,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
|
|
|
5672
5917
|
return modelCalls.filter((call) => call.isSubagent === isSubagentSession);
|
|
5673
5918
|
}
|
|
5674
5919
|
async function parseQoderSessionFile(filePath, options) {
|
|
5675
|
-
const text = await
|
|
5920
|
+
const text = await readFile9(filePath, "utf8");
|
|
5676
5921
|
const lines = text.split("\n").filter(Boolean);
|
|
5677
5922
|
const { configDir: configDir2 } = parseQoderPaths(filePath);
|
|
5678
5923
|
const projectContext = await qoderProjectContextFromLines(filePath, lines, options, configDir2);
|
|
@@ -5707,7 +5952,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
5707
5952
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
5708
5953
|
state.sessionId = sessionId;
|
|
5709
5954
|
cwd = stringField(raw, "cwd") || cwd;
|
|
5710
|
-
project = projectContext.project || (cwd ?
|
|
5955
|
+
project = projectContext.project || (cwd ? path13.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
|
|
5711
5956
|
if (!ts) {
|
|
5712
5957
|
continue;
|
|
5713
5958
|
}
|
|
@@ -6102,24 +6347,24 @@ function qoderExtractText(value) {
|
|
|
6102
6347
|
}
|
|
6103
6348
|
async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
6104
6349
|
const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
|
|
6105
|
-
const isSubagent = filePath.includes(`${
|
|
6350
|
+
const isSubagent = filePath.includes(`${path13.sep}subagents${path13.sep}`);
|
|
6106
6351
|
let cwds = [];
|
|
6107
6352
|
for (const line of lines) {
|
|
6108
6353
|
const raw = parseJsonLine(line);
|
|
6109
6354
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
6110
|
-
if (cwd &&
|
|
6355
|
+
if (cwd && path13.isAbsolute(cwd)) {
|
|
6111
6356
|
cwds.push(cwd);
|
|
6112
6357
|
}
|
|
6113
6358
|
}
|
|
6114
6359
|
if (isSubagent) {
|
|
6115
|
-
const parentSessionPath =
|
|
6360
|
+
const parentSessionPath = path13.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
6116
6361
|
try {
|
|
6117
|
-
const parentText = await
|
|
6362
|
+
const parentText = await readFile9(parentSessionPath, "utf8");
|
|
6118
6363
|
const parentCwds = [];
|
|
6119
6364
|
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
6120
6365
|
const raw = parseJsonLine(line);
|
|
6121
6366
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
6122
|
-
if (cwd &&
|
|
6367
|
+
if (cwd && path13.isAbsolute(cwd)) {
|
|
6123
6368
|
parentCwds.push(cwd);
|
|
6124
6369
|
}
|
|
6125
6370
|
}
|
|
@@ -6130,7 +6375,7 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
6130
6375
|
}
|
|
6131
6376
|
}
|
|
6132
6377
|
const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
|
|
6133
|
-
const project = cwds.length > 0 ?
|
|
6378
|
+
const project = cwds.length > 0 ? path13.basename(cwds[0]) : root ? path13.basename(root) : await qoderProjectFromFilePath(filePath, options);
|
|
6134
6379
|
return {
|
|
6135
6380
|
project,
|
|
6136
6381
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -6139,15 +6384,15 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
6139
6384
|
async function gitRootFromCwds3(cwds) {
|
|
6140
6385
|
const seen = /* @__PURE__ */ new Set();
|
|
6141
6386
|
for (const cwd of cwds) {
|
|
6142
|
-
let current =
|
|
6387
|
+
let current = path13.resolve(cwd);
|
|
6143
6388
|
while (!seen.has(current)) {
|
|
6144
6389
|
seen.add(current);
|
|
6145
6390
|
try {
|
|
6146
|
-
await
|
|
6391
|
+
await stat6(path13.join(current, ".git"));
|
|
6147
6392
|
return current;
|
|
6148
6393
|
} catch {
|
|
6149
6394
|
}
|
|
6150
|
-
const parent =
|
|
6395
|
+
const parent = path13.dirname(current);
|
|
6151
6396
|
if (parent === current) {
|
|
6152
6397
|
break;
|
|
6153
6398
|
}
|
|
@@ -6158,12 +6403,12 @@ async function gitRootFromCwds3(cwds) {
|
|
|
6158
6403
|
}
|
|
6159
6404
|
function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
6160
6405
|
for (const cwd of cwds) {
|
|
6161
|
-
let current =
|
|
6406
|
+
let current = path13.resolve(cwd);
|
|
6162
6407
|
while (true) {
|
|
6163
6408
|
if (encodeQoderProjectPath(current) === projectDir) {
|
|
6164
6409
|
return current;
|
|
6165
6410
|
}
|
|
6166
|
-
const parent =
|
|
6411
|
+
const parent = path13.dirname(current);
|
|
6167
6412
|
if (parent === current) {
|
|
6168
6413
|
break;
|
|
6169
6414
|
}
|
|
@@ -6173,10 +6418,10 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
|
6173
6418
|
return void 0;
|
|
6174
6419
|
}
|
|
6175
6420
|
function encodeQoderProjectPath(value) {
|
|
6176
|
-
return
|
|
6421
|
+
return path13.resolve(value).split(path13.sep).join("-").replace(/_/g, "-");
|
|
6177
6422
|
}
|
|
6178
6423
|
function rawQoderProjectPath(value) {
|
|
6179
|
-
return
|
|
6424
|
+
return path13.resolve(value).split(path13.sep).join("-");
|
|
6180
6425
|
}
|
|
6181
6426
|
function qoderEncodedVariants(value) {
|
|
6182
6427
|
const raw = rawQoderProjectPath(value);
|
|
@@ -6192,11 +6437,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
|
|
|
6192
6437
|
return void 0;
|
|
6193
6438
|
}
|
|
6194
6439
|
async function qoderProjectFromFilePath(filePath, options) {
|
|
6195
|
-
const projectDir =
|
|
6196
|
-
const home = options ?
|
|
6440
|
+
const projectDir = path13.basename(path13.dirname(filePath));
|
|
6441
|
+
const home = options ? path13.resolve(stringOption(options.home) || os6.homedir()) : os6.homedir();
|
|
6197
6442
|
const resolved = await resolveQoderProjectPath(projectDir, home);
|
|
6198
6443
|
if (resolved) {
|
|
6199
|
-
return
|
|
6444
|
+
return path13.basename(resolved);
|
|
6200
6445
|
}
|
|
6201
6446
|
const suffix = qoderEncodedProjectSuffix(projectDir, home);
|
|
6202
6447
|
if (suffix) {
|
|
@@ -6217,12 +6462,12 @@ async function resolveQoderProjectPath(projectDir, home) {
|
|
|
6217
6462
|
while (currentEncodedVariants.some((prefix) => projectDir.startsWith(`${prefix}-`))) {
|
|
6218
6463
|
let matchedChild;
|
|
6219
6464
|
try {
|
|
6220
|
-
const entries = await
|
|
6465
|
+
const entries = await readdir6(current, { withFileTypes: true });
|
|
6221
6466
|
for (const entry of entries) {
|
|
6222
6467
|
if (!entry.isDirectory()) {
|
|
6223
6468
|
continue;
|
|
6224
6469
|
}
|
|
6225
|
-
const candidate =
|
|
6470
|
+
const candidate = path13.join(current, entry.name);
|
|
6226
6471
|
const candidateVariants = qoderEncodedVariants(candidate);
|
|
6227
6472
|
if (candidateVariants.includes(projectDir)) {
|
|
6228
6473
|
return candidate;
|
|
@@ -6267,9 +6512,9 @@ function hookConfig6() {
|
|
|
6267
6512
|
function qoderConfigDir(home, env) {
|
|
6268
6513
|
const override = env?.QODER_CONFIG_DIR;
|
|
6269
6514
|
if (override && override.trim()) {
|
|
6270
|
-
return
|
|
6515
|
+
return path13.resolve(override);
|
|
6271
6516
|
}
|
|
6272
|
-
return
|
|
6517
|
+
return path13.join(home, ".qoder");
|
|
6273
6518
|
}
|
|
6274
6519
|
function createQoderAdapter() {
|
|
6275
6520
|
return {
|
|
@@ -6281,27 +6526,27 @@ function createQoderAdapter() {
|
|
|
6281
6526
|
return qoderConfigDir(home, env);
|
|
6282
6527
|
},
|
|
6283
6528
|
installedPath(home, env) {
|
|
6284
|
-
return
|
|
6529
|
+
return path13.join(qoderConfigDir(home, env), "settings.json");
|
|
6285
6530
|
},
|
|
6286
6531
|
async isInstalled(home, env) {
|
|
6287
6532
|
return isHooksJsonInstalled(
|
|
6288
|
-
|
|
6533
|
+
path13.join(qoderConfigDir(home, env), "settings.json"),
|
|
6289
6534
|
"vibetime hook --agent qoder"
|
|
6290
6535
|
);
|
|
6291
6536
|
},
|
|
6292
6537
|
installEntries(home, env) {
|
|
6293
6538
|
return [{
|
|
6294
6539
|
kind: "hooks-json",
|
|
6295
|
-
path:
|
|
6540
|
+
path: path13.join(qoderConfigDir(home, env), "settings.json"),
|
|
6296
6541
|
content: hookConfig6()
|
|
6297
6542
|
}];
|
|
6298
6543
|
},
|
|
6299
6544
|
sourcePaths(home, env) {
|
|
6300
6545
|
const base = qoderConfigDir(home, env);
|
|
6301
6546
|
return [
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6547
|
+
path13.join(base, "projects"),
|
|
6548
|
+
path13.join(base, ".qoder.json"),
|
|
6549
|
+
path13.join(home, ".qoder.json")
|
|
6305
6550
|
];
|
|
6306
6551
|
},
|
|
6307
6552
|
parseSessionFile: parseQoderSessionFile
|
|
@@ -6771,15 +7016,15 @@ function hookCommandFromGroup(group) {
|
|
|
6771
7016
|
import { randomUUID } from "node:crypto";
|
|
6772
7017
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
6773
7018
|
import { homedir, hostname } from "node:os";
|
|
6774
|
-
import
|
|
7019
|
+
import path14 from "node:path";
|
|
6775
7020
|
function configDir(home = homedir()) {
|
|
6776
|
-
return
|
|
7021
|
+
return path14.join(home, ".vibetime");
|
|
6777
7022
|
}
|
|
6778
7023
|
function configPath(home = homedir()) {
|
|
6779
|
-
return
|
|
7024
|
+
return path14.join(configDir(home), "config.json");
|
|
6780
7025
|
}
|
|
6781
7026
|
function machineIdPath(home = homedir()) {
|
|
6782
|
-
return
|
|
7027
|
+
return path14.join(configDir(home), "machine-id");
|
|
6783
7028
|
}
|
|
6784
7029
|
function readConfig(home = homedir()) {
|
|
6785
7030
|
const file = configPath(home);
|
|
@@ -6826,15 +7071,15 @@ function defaultMachineName() {
|
|
|
6826
7071
|
init_fs();
|
|
6827
7072
|
|
|
6828
7073
|
// src/lib/logger.ts
|
|
6829
|
-
import { appendFile, mkdir as mkdir3, rename, stat as
|
|
7074
|
+
import { appendFile, mkdir as mkdir3, rename, stat as stat7 } from "node:fs/promises";
|
|
6830
7075
|
import { homedir as homedir2 } from "node:os";
|
|
6831
|
-
import
|
|
7076
|
+
import path15 from "node:path";
|
|
6832
7077
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
6833
7078
|
function logDir(home = homedir2()) {
|
|
6834
|
-
return
|
|
7079
|
+
return path15.join(home, ".vibetime", "logs");
|
|
6835
7080
|
}
|
|
6836
7081
|
function logPath(home = homedir2(), name = "cli.log") {
|
|
6837
|
-
return
|
|
7082
|
+
return path15.join(logDir(home), name);
|
|
6838
7083
|
}
|
|
6839
7084
|
function serializeError(error) {
|
|
6840
7085
|
if (error instanceof Error) {
|
|
@@ -6844,7 +7089,7 @@ function serializeError(error) {
|
|
|
6844
7089
|
}
|
|
6845
7090
|
async function rotateIfNeeded(file) {
|
|
6846
7091
|
try {
|
|
6847
|
-
const info = await
|
|
7092
|
+
const info = await stat7(file);
|
|
6848
7093
|
if (info.size > MAX_BYTES) {
|
|
6849
7094
|
await rename(file, `${file}.1`).catch(() => {
|
|
6850
7095
|
});
|
|
@@ -7009,8 +7254,8 @@ function buildHeaders(token, machine) {
|
|
|
7009
7254
|
...machine?.platform ? { "x-machine-platform": machine.platform } : {}
|
|
7010
7255
|
};
|
|
7011
7256
|
}
|
|
7012
|
-
function joinUrl(base,
|
|
7013
|
-
return new URL(
|
|
7257
|
+
function joinUrl(base, path17) {
|
|
7258
|
+
return new URL(path17, base.endsWith("/") ? base : `${base}/`).toString();
|
|
7014
7259
|
}
|
|
7015
7260
|
async function postRollupBatch(remote, rollups, options = {}) {
|
|
7016
7261
|
const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
|
|
@@ -7082,6 +7327,7 @@ function createRegistry() {
|
|
|
7082
7327
|
const registry = new AdapterRegistry();
|
|
7083
7328
|
registry.register(createCodexAdapter());
|
|
7084
7329
|
registry.register(createClaudeCodeAdapter());
|
|
7330
|
+
registry.register(createClaudeCoworkAdapter());
|
|
7085
7331
|
registry.register(createPiAdapter());
|
|
7086
7332
|
registry.register(createOpenCodeAdapter());
|
|
7087
7333
|
registry.register(createAgyAdapter());
|
|
@@ -7493,6 +7739,9 @@ async function listBackfillSourceFiles(source, options, ctx) {
|
|
|
7493
7739
|
if (source.id === "agy") {
|
|
7494
7740
|
return agyBackfillFiles(stringOption(options["source-root"]), resolveHome2(options, ctx), ctx.env);
|
|
7495
7741
|
}
|
|
7742
|
+
if (source.id === "claude-cowork") {
|
|
7743
|
+
return claudeCoworkBackfillFiles(stringOption(options["source-root"]), resolveHome2(options, ctx), ctx.env);
|
|
7744
|
+
}
|
|
7496
7745
|
if (source.id === "codebuddy") {
|
|
7497
7746
|
return codebuddyBackfillFiles(stringOption(options["source-root"]), resolveHome2(options, ctx), ctx.env);
|
|
7498
7747
|
}
|
|
@@ -7500,7 +7749,7 @@ async function listBackfillSourceFiles(source, options, ctx) {
|
|
|
7500
7749
|
const fileLists = await Promise.all(roots.map((r) => listJsonlFiles(r)));
|
|
7501
7750
|
const files = fileLists.flat().sort().slice(0, numberOption(options.limit) || void 0);
|
|
7502
7751
|
return Promise.all(files.map(async (filePath) => {
|
|
7503
|
-
const info = await
|
|
7752
|
+
const info = await stat8(filePath);
|
|
7504
7753
|
return { path: filePath, modifiedAt: info.mtime.toISOString() };
|
|
7505
7754
|
}));
|
|
7506
7755
|
}
|
|
@@ -7809,13 +8058,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
|
|
|
7809
8058
|
});
|
|
7810
8059
|
}
|
|
7811
8060
|
function backfillIncrementalStatePath(home) {
|
|
7812
|
-
return
|
|
8061
|
+
return path16.join(home, ".vibetime", "backfill-state.json");
|
|
7813
8062
|
}
|
|
7814
8063
|
function syncLocalTriggerStatePath(home) {
|
|
7815
|
-
return
|
|
8064
|
+
return path16.join(home, ".vibetime", "sync-local-trigger.json");
|
|
7816
8065
|
}
|
|
7817
8066
|
function syncLocalTriggerLockPath(home) {
|
|
7818
|
-
return
|
|
8067
|
+
return path16.join(home, ".vibetime", "sync-local-trigger.lock");
|
|
7819
8068
|
}
|
|
7820
8069
|
async function readBackfillIncrementalState(home, ctx) {
|
|
7821
8070
|
const statePath = backfillIncrementalStatePath(home);
|
|
@@ -7855,7 +8104,7 @@ async function updateBackfillIncrementalState(home, state, selectedFilesBySource
|
|
|
7855
8104
|
state.sources[source] = { watermarkTs: latest };
|
|
7856
8105
|
}
|
|
7857
8106
|
const statePath = backfillIncrementalStatePath(home);
|
|
7858
|
-
await mkdir4(
|
|
8107
|
+
await mkdir4(path16.dirname(statePath), { recursive: true });
|
|
7859
8108
|
await writeFile3(statePath, `${JSON.stringify(state, null, 2)}
|
|
7860
8109
|
`, "utf8");
|
|
7861
8110
|
}
|
|
@@ -7888,7 +8137,7 @@ async function readSyncLocalTriggerState(statePath) {
|
|
|
7888
8137
|
return nextState;
|
|
7889
8138
|
}
|
|
7890
8139
|
async function writeSyncLocalTriggerState(statePath, state) {
|
|
7891
|
-
await mkdir4(
|
|
8140
|
+
await mkdir4(path16.dirname(statePath), { recursive: true });
|
|
7892
8141
|
const tmpPath = `${statePath}.tmp`;
|
|
7893
8142
|
await writeFile3(tmpPath, `${JSON.stringify(state, null, 2)}
|
|
7894
8143
|
`, "utf8");
|
|
@@ -7905,7 +8154,7 @@ async function readSyncLocalLock(lockPath) {
|
|
|
7905
8154
|
return { pid: lock.pid, startedAt: lock.startedAt };
|
|
7906
8155
|
}
|
|
7907
8156
|
async function writeSyncLocalLock(lockPath, lock) {
|
|
7908
|
-
await mkdir4(
|
|
8157
|
+
await mkdir4(path16.dirname(lockPath), { recursive: true });
|
|
7909
8158
|
await writeFile3(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
7910
8159
|
`, "utf8");
|
|
7911
8160
|
}
|
|
@@ -7965,10 +8214,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
|
|
|
7965
8214
|
if (cliPath.endsWith(".ts")) {
|
|
7966
8215
|
return ["--import", "tsx", cliPath];
|
|
7967
8216
|
}
|
|
7968
|
-
return [
|
|
8217
|
+
return [path16.resolve(path16.dirname(cliPath), "../bin/vibetime.mjs")];
|
|
7969
8218
|
}
|
|
7970
8219
|
function resolveHome2(options, ctx) {
|
|
7971
|
-
return
|
|
8220
|
+
return path16.resolve(stringOption(options.home) || ctx.env.HOME || os7.homedir());
|
|
7972
8221
|
}
|
|
7973
8222
|
function requestedTargets(options) {
|
|
7974
8223
|
const value = options.target || options.targets;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yhong91/vibetime",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
5
|
-
"description": "vibetime CLI
|
|
4
|
+
"version": "0.1.2",
|
|
5
|
+
"description": "vibetime CLI — install AI-agent hooks (Claude Code, Codex, OpenCode, Pi) and report activity to vibetime.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
@@ -32,15 +32,14 @@
|
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=20"
|
|
34
34
|
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"cac": "^7.0.0",
|
|
37
|
+
"esbuild": "^0.28.0",
|
|
38
|
+
"@codetime/shared": "0.4.0"
|
|
39
|
+
},
|
|
35
40
|
"scripts": {
|
|
36
41
|
"build": "tsc -p tsconfig.json",
|
|
37
42
|
"build:bundle": "node bundle.mjs",
|
|
38
|
-
"prepublishOnly": "node bundle.mjs",
|
|
39
43
|
"test": "node --conditions=development --test --import tsx test/*.test.ts"
|
|
40
|
-
},
|
|
41
|
-
"devDependencies": {
|
|
42
|
-
"@codetime/shared": "workspace:*",
|
|
43
|
-
"cac": "^7.0.0",
|
|
44
|
-
"esbuild": "^0.28.0"
|
|
45
44
|
}
|
|
46
|
-
}
|
|
45
|
+
}
|