@yhong91/vibetime 0.1.16 → 0.1.17
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 +283 -207
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -159,9 +159,10 @@ var init_fs = __esm({
|
|
|
159
159
|
|
|
160
160
|
// src/cli.ts
|
|
161
161
|
import { spawn, spawnSync } from "node:child_process";
|
|
162
|
-
import {
|
|
163
|
-
import
|
|
164
|
-
import
|
|
162
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
163
|
+
import { mkdir as mkdir5, rename as rename2, rm, stat as stat11, writeFile as writeFile4 } from "node:fs/promises";
|
|
164
|
+
import os9 from "node:os";
|
|
165
|
+
import path20 from "node:path";
|
|
165
166
|
import { fileURLToPath } from "node:url";
|
|
166
167
|
|
|
167
168
|
// ../shared/src/index.ts
|
|
@@ -1195,7 +1196,7 @@ function countTextLines(text) {
|
|
|
1195
1196
|
}
|
|
1196
1197
|
|
|
1197
1198
|
// src/lib/constants.ts
|
|
1198
|
-
var PACKAGE_VERSION = true ? "0.1.
|
|
1199
|
+
var PACKAGE_VERSION = true ? "0.1.17" : "0.1.1";
|
|
1199
1200
|
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
1200
1201
|
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
1201
1202
|
var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
|
|
@@ -3731,7 +3732,7 @@ async function codebuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
3731
3732
|
|
|
3732
3733
|
// src/adapters/codex.ts
|
|
3733
3734
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
3734
|
-
import
|
|
3735
|
+
import path10 from "node:path";
|
|
3735
3736
|
|
|
3736
3737
|
// src/lib/diff.ts
|
|
3737
3738
|
function diffStats(diff) {
|
|
@@ -3776,6 +3777,61 @@ function fileActivitiesFromPatchChanges(changes, ts, cwd, displayFilePath3) {
|
|
|
3776
3777
|
});
|
|
3777
3778
|
}
|
|
3778
3779
|
|
|
3780
|
+
// src/lib/session-context.ts
|
|
3781
|
+
init_fs();
|
|
3782
|
+
import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
3783
|
+
import os4 from "node:os";
|
|
3784
|
+
import path9 from "node:path";
|
|
3785
|
+
var SESSION_CONTEXT_VERSION = 1;
|
|
3786
|
+
function sessionContextDir(home) {
|
|
3787
|
+
return path9.join(home, ".vibetime", "session-context");
|
|
3788
|
+
}
|
|
3789
|
+
function sessionContextPath(home, sessionId) {
|
|
3790
|
+
return path9.join(sessionContextDir(home), `${encodeURIComponent(sessionId)}.json`);
|
|
3791
|
+
}
|
|
3792
|
+
function resolveHome2(options) {
|
|
3793
|
+
return options ? path9.resolve(stringOption(options.home) || os4.homedir()) : os4.homedir();
|
|
3794
|
+
}
|
|
3795
|
+
async function readPersistedSessionContext(home, sessionId) {
|
|
3796
|
+
const raw = await readJsonIfExists(sessionContextPath(home, sessionId));
|
|
3797
|
+
if (!isPlainObject(raw)) {
|
|
3798
|
+
return void 0;
|
|
3799
|
+
}
|
|
3800
|
+
if (raw.version !== SESSION_CONTEXT_VERSION || raw.sessionId !== sessionId) {
|
|
3801
|
+
return void 0;
|
|
3802
|
+
}
|
|
3803
|
+
if (typeof raw.updatedAt !== "string") {
|
|
3804
|
+
return void 0;
|
|
3805
|
+
}
|
|
3806
|
+
const cwd = typeof raw.cwd === "string" && raw.cwd.length > 0 ? raw.cwd : void 0;
|
|
3807
|
+
const project = typeof raw.project === "string" && raw.project.length > 0 ? raw.project : void 0;
|
|
3808
|
+
return { version: SESSION_CONTEXT_VERSION, sessionId, cwd, project, updatedAt: raw.updatedAt };
|
|
3809
|
+
}
|
|
3810
|
+
async function readPersistedSessionContextFromOptions(options, sessionId) {
|
|
3811
|
+
return readPersistedSessionContext(resolveHome2(options), sessionId);
|
|
3812
|
+
}
|
|
3813
|
+
async function persistHookSessionContext(home, payload) {
|
|
3814
|
+
if (!isPlainObject(payload)) {
|
|
3815
|
+
return;
|
|
3816
|
+
}
|
|
3817
|
+
const sessionId = typeof payload.session_id === "string" ? payload.session_id.trim() : typeof payload.sessionId === "string" ? payload.sessionId.trim() : "";
|
|
3818
|
+
const cwd = typeof payload.cwd === "string" ? payload.cwd.trim() : "";
|
|
3819
|
+
if (!sessionId || !cwd || !path9.isAbsolute(cwd)) {
|
|
3820
|
+
return;
|
|
3821
|
+
}
|
|
3822
|
+
const project = path9.basename(cwd) || void 0;
|
|
3823
|
+
const context = {
|
|
3824
|
+
version: SESSION_CONTEXT_VERSION,
|
|
3825
|
+
sessionId,
|
|
3826
|
+
cwd,
|
|
3827
|
+
project,
|
|
3828
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3829
|
+
};
|
|
3830
|
+
await mkdir3(sessionContextDir(home), { recursive: true });
|
|
3831
|
+
await writeFile3(sessionContextPath(home, sessionId), `${JSON.stringify(context, null, 2)}
|
|
3832
|
+
`, "utf8");
|
|
3833
|
+
}
|
|
3834
|
+
|
|
3779
3835
|
// src/adapters/codex.ts
|
|
3780
3836
|
async function parseCodexSessionFile(filePath, options) {
|
|
3781
3837
|
const text = await readFile6(filePath, "utf8");
|
|
@@ -3810,9 +3866,11 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
3810
3866
|
continue;
|
|
3811
3867
|
}
|
|
3812
3868
|
sessionMetaLocked = true;
|
|
3869
|
+
const forkedFromId = stringField(payload, "forked_from_id");
|
|
3870
|
+
const inherited = forkedFromId ? await readPersistedSessionContextFromOptions(options, forkedFromId) : void 0;
|
|
3813
3871
|
sessionId = stringField(payload, "id") || sessionId;
|
|
3814
|
-
cwd = stringField(payload, "cwd") || cwd;
|
|
3815
|
-
project = cwd ?
|
|
3872
|
+
cwd = inherited?.cwd || stringField(payload, "cwd") || cwd;
|
|
3873
|
+
project = inherited?.project || (cwd ? path10.basename(cwd) : project);
|
|
3816
3874
|
model = stringField(payload, "model_provider") || model;
|
|
3817
3875
|
events.push(withBackfillRefs({
|
|
3818
3876
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
@@ -3833,7 +3891,7 @@ async function parseCodexSessionFile(filePath, options) {
|
|
|
3833
3891
|
if (topType === "turn_context") {
|
|
3834
3892
|
currentTurnId = stringField(payload, "turn_id") || currentTurnId;
|
|
3835
3893
|
cwd = stringField(payload, "cwd") || cwd;
|
|
3836
|
-
project = cwd ?
|
|
3894
|
+
project = cwd ? path10.basename(cwd) : project;
|
|
3837
3895
|
model = stringField(payload, "model") || model;
|
|
3838
3896
|
const effort = stringField(payload, "effort") || stringField(objectField(objectField(payload, "collaboration_mode"), "settings"), "reasoning_effort");
|
|
3839
3897
|
if (effort) {
|
|
@@ -4280,11 +4338,11 @@ function functionCallArguments(payload) {
|
|
|
4280
4338
|
}
|
|
4281
4339
|
}
|
|
4282
4340
|
function displayFilePath2(filePath, cwd) {
|
|
4283
|
-
if (!cwd || !
|
|
4341
|
+
if (!cwd || !path10.isAbsolute(filePath)) {
|
|
4284
4342
|
return filePath;
|
|
4285
4343
|
}
|
|
4286
|
-
const relative =
|
|
4287
|
-
return relative && !relative.startsWith("..") && !
|
|
4344
|
+
const relative = path10.relative(cwd, filePath);
|
|
4345
|
+
return relative && !relative.startsWith("..") && !path10.isAbsolute(relative) ? relative : filePath;
|
|
4288
4346
|
}
|
|
4289
4347
|
var codexHandler = (msg) => hookHandler("codex", msg);
|
|
4290
4348
|
function hookConfig4() {
|
|
@@ -4303,9 +4361,9 @@ function hookConfig4() {
|
|
|
4303
4361
|
function codexHome(home, env) {
|
|
4304
4362
|
const override = env?.CODEX_HOME;
|
|
4305
4363
|
if (override && override.trim()) {
|
|
4306
|
-
return
|
|
4364
|
+
return path10.resolve(override);
|
|
4307
4365
|
}
|
|
4308
|
-
return
|
|
4366
|
+
return path10.join(home, ".codex");
|
|
4309
4367
|
}
|
|
4310
4368
|
function createCodexAdapter() {
|
|
4311
4369
|
return {
|
|
@@ -4317,26 +4375,26 @@ function createCodexAdapter() {
|
|
|
4317
4375
|
return codexHome(home, env);
|
|
4318
4376
|
},
|
|
4319
4377
|
installedPath(home, env) {
|
|
4320
|
-
return
|
|
4378
|
+
return path10.join(codexHome(home, env), "hooks.json");
|
|
4321
4379
|
},
|
|
4322
4380
|
async isInstalled(home, env) {
|
|
4323
4381
|
return isHooksJsonInstalled(
|
|
4324
|
-
|
|
4382
|
+
path10.join(codexHome(home, env), "hooks.json"),
|
|
4325
4383
|
"vibetime hook --agent codex"
|
|
4326
4384
|
);
|
|
4327
4385
|
},
|
|
4328
4386
|
installEntries(home, env) {
|
|
4329
4387
|
return [{
|
|
4330
4388
|
kind: "hooks-json",
|
|
4331
|
-
path:
|
|
4389
|
+
path: path10.join(codexHome(home, env), "hooks.json"),
|
|
4332
4390
|
content: hookConfig4()
|
|
4333
4391
|
}];
|
|
4334
4392
|
},
|
|
4335
4393
|
sourcePaths(home, env) {
|
|
4336
4394
|
const base = codexHome(home, env);
|
|
4337
4395
|
return [
|
|
4338
|
-
|
|
4339
|
-
|
|
4396
|
+
path10.join(base, "sessions"),
|
|
4397
|
+
path10.join(base, "history.jsonl")
|
|
4340
4398
|
];
|
|
4341
4399
|
},
|
|
4342
4400
|
parseSessionFile: parseCodexSessionFile
|
|
@@ -4345,8 +4403,8 @@ function createCodexAdapter() {
|
|
|
4345
4403
|
|
|
4346
4404
|
// src/adapters/copilot.ts
|
|
4347
4405
|
import { readdir as readdir5, readFile as readFile7, stat as stat5 } from "node:fs/promises";
|
|
4348
|
-
import
|
|
4349
|
-
import
|
|
4406
|
+
import os5 from "node:os";
|
|
4407
|
+
import path11 from "node:path";
|
|
4350
4408
|
async function parseCopilotSessionFile(filePath, options) {
|
|
4351
4409
|
const text = await readFile7(filePath, "utf8");
|
|
4352
4410
|
const lines = text.split("\n").filter(Boolean);
|
|
@@ -4382,7 +4440,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
4382
4440
|
}
|
|
4383
4441
|
const context = objectField(data, "context");
|
|
4384
4442
|
cwd = stringField(context, "cwd") || stringField(context, "gitRoot") || cwd;
|
|
4385
|
-
project = stringField(context, "repository") || (cwd ?
|
|
4443
|
+
project = stringField(context, "repository") || (cwd ? path11.basename(cwd) : void 0);
|
|
4386
4444
|
sessionStartedAt = ts;
|
|
4387
4445
|
events.push(baseCopilotEvent({
|
|
4388
4446
|
ts,
|
|
@@ -4613,8 +4671,8 @@ function baseCopilotEvent(event) {
|
|
|
4613
4671
|
...event
|
|
4614
4672
|
};
|
|
4615
4673
|
}
|
|
4616
|
-
async function copilotBackfillFiles(sourceRoot, home =
|
|
4617
|
-
const sessionDir = sourceRoot ||
|
|
4674
|
+
async function copilotBackfillFiles(sourceRoot, home = os5.homedir(), _env) {
|
|
4675
|
+
const sessionDir = sourceRoot || path11.join(home, ".copilot", "session-state");
|
|
4618
4676
|
const results = [];
|
|
4619
4677
|
let entries;
|
|
4620
4678
|
try {
|
|
@@ -4626,7 +4684,7 @@ async function copilotBackfillFiles(sourceRoot, home = os4.homedir(), _env) {
|
|
|
4626
4684
|
if (entry.startsWith("pending-session")) {
|
|
4627
4685
|
continue;
|
|
4628
4686
|
}
|
|
4629
|
-
const eventsPath =
|
|
4687
|
+
const eventsPath = path11.join(sessionDir, entry, "events.jsonl");
|
|
4630
4688
|
const info = await stat5(eventsPath).catch(() => null);
|
|
4631
4689
|
if (info) {
|
|
4632
4690
|
results.push({ path: eventsPath, modifiedAt: info.mtime.toISOString() });
|
|
@@ -4644,9 +4702,9 @@ function copilotPluginContent() {
|
|
|
4644
4702
|
function copilotHome(home, env) {
|
|
4645
4703
|
const override = env?.COPILOT_HOME;
|
|
4646
4704
|
if (override && override.trim()) {
|
|
4647
|
-
return
|
|
4705
|
+
return path11.resolve(override);
|
|
4648
4706
|
}
|
|
4649
|
-
return
|
|
4707
|
+
return path11.join(home, ".copilot");
|
|
4650
4708
|
}
|
|
4651
4709
|
function createCopilotAdapter() {
|
|
4652
4710
|
return {
|
|
@@ -4658,12 +4716,12 @@ function createCopilotAdapter() {
|
|
|
4658
4716
|
return copilotHome(home, env);
|
|
4659
4717
|
},
|
|
4660
4718
|
installedPath(home, env) {
|
|
4661
|
-
return
|
|
4719
|
+
return path11.join(copilotHome(home, env), ".vibetime");
|
|
4662
4720
|
},
|
|
4663
4721
|
async isInstalled(home, env) {
|
|
4664
4722
|
try {
|
|
4665
4723
|
const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
4666
|
-
return await pathExists2(
|
|
4724
|
+
return await pathExists2(path11.join(copilotHome(home, env), ".vibetime"));
|
|
4667
4725
|
} catch {
|
|
4668
4726
|
return false;
|
|
4669
4727
|
}
|
|
@@ -4671,20 +4729,20 @@ function createCopilotAdapter() {
|
|
|
4671
4729
|
installEntries(home, env) {
|
|
4672
4730
|
return [{
|
|
4673
4731
|
kind: "file",
|
|
4674
|
-
path:
|
|
4732
|
+
path: path11.join(copilotHome(home, env), ".vibetime"),
|
|
4675
4733
|
content: copilotPluginContent()
|
|
4676
4734
|
}];
|
|
4677
4735
|
},
|
|
4678
4736
|
sourcePaths(home, env) {
|
|
4679
|
-
return [
|
|
4737
|
+
return [path11.join(copilotHome(home, env), "session-state")];
|
|
4680
4738
|
},
|
|
4681
4739
|
parseSessionFile: parseCopilotSessionFile
|
|
4682
4740
|
};
|
|
4683
4741
|
}
|
|
4684
4742
|
|
|
4685
4743
|
// src/adapters/opencode.ts
|
|
4686
|
-
import
|
|
4687
|
-
import
|
|
4744
|
+
import os6 from "node:os";
|
|
4745
|
+
import path12 from "node:path";
|
|
4688
4746
|
async function parseOpenCodeSessionFile(dbPath, options) {
|
|
4689
4747
|
const { DatabaseSync } = await import("node:sqlite");
|
|
4690
4748
|
if (!dbPath.endsWith(".db")) {
|
|
@@ -4715,7 +4773,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
4715
4773
|
for (const session of sessions) {
|
|
4716
4774
|
const sessionId = session.id;
|
|
4717
4775
|
const cwd = session.directory || session.path || void 0;
|
|
4718
|
-
const project = cwd ?
|
|
4776
|
+
const project = cwd ? path12.basename(cwd) : void 0;
|
|
4719
4777
|
const sessionTs = msToIso(session.time_created);
|
|
4720
4778
|
events.push(baseOpenCodeEvent({
|
|
4721
4779
|
ts: sessionTs,
|
|
@@ -4823,7 +4881,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
4823
4881
|
const provider = currentProvider;
|
|
4824
4882
|
const pathObj = objectField(info, "path");
|
|
4825
4883
|
const assistantCwd = stringField(pathObj, "cwd") || cwd;
|
|
4826
|
-
const assistantProject = assistantCwd ?
|
|
4884
|
+
const assistantProject = assistantCwd ? path12.basename(assistantCwd) : project;
|
|
4827
4885
|
const completedTs = numberField(objectField(info, "time"), "completed");
|
|
4828
4886
|
const createdTs = timeCreated;
|
|
4829
4887
|
const tokens = opencodeUsageFromInfo(info);
|
|
@@ -5069,20 +5127,20 @@ function opencodeUsageFromInfo(info) {
|
|
|
5069
5127
|
function opencodeConfigDir(home, env) {
|
|
5070
5128
|
const override = env?.OPENCODE_CONFIG_DIR;
|
|
5071
5129
|
if (override && override.trim()) {
|
|
5072
|
-
return
|
|
5130
|
+
return path12.resolve(override);
|
|
5073
5131
|
}
|
|
5074
5132
|
const xdgConfig = env?.XDG_CONFIG_HOME;
|
|
5075
5133
|
if (xdgConfig && xdgConfig.trim()) {
|
|
5076
|
-
return
|
|
5134
|
+
return path12.join(path12.resolve(xdgConfig), "opencode");
|
|
5077
5135
|
}
|
|
5078
|
-
return
|
|
5136
|
+
return path12.join(home, ".config", "opencode");
|
|
5079
5137
|
}
|
|
5080
5138
|
function opencodeDataCandidates(home, env) {
|
|
5081
5139
|
const xdgData = env?.XDG_DATA_HOME;
|
|
5082
|
-
const primary = xdgData && xdgData.trim() ?
|
|
5083
|
-
return [primary,
|
|
5140
|
+
const primary = xdgData && xdgData.trim() ? path12.join(path12.resolve(xdgData), "opencode", "opencode.db") : path12.join(home, ".local", "share", "opencode", "opencode.db");
|
|
5141
|
+
return [primary, path12.join(home, ".opencode", "opencode.db")];
|
|
5084
5142
|
}
|
|
5085
|
-
async function opencodeBackfillFiles(sourceRoot, home =
|
|
5143
|
+
async function opencodeBackfillFiles(sourceRoot, home = os6.homedir(), env) {
|
|
5086
5144
|
const { stat: stat12 } = await import("node:fs/promises");
|
|
5087
5145
|
if (sourceRoot) {
|
|
5088
5146
|
if (!sourceRoot.endsWith(".db")) {
|
|
@@ -5170,12 +5228,12 @@ function createOpenCodeAdapter() {
|
|
|
5170
5228
|
return opencodeConfigDir(home, env);
|
|
5171
5229
|
},
|
|
5172
5230
|
installedPath(home, env) {
|
|
5173
|
-
return
|
|
5231
|
+
return path12.join(opencodeConfigDir(home, env), PLUGIN_PATH);
|
|
5174
5232
|
},
|
|
5175
5233
|
async isInstalled(home, env) {
|
|
5176
5234
|
try {
|
|
5177
5235
|
const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
5178
|
-
return await pathExists2(
|
|
5236
|
+
return await pathExists2(path12.join(opencodeConfigDir(home, env), PLUGIN_PATH)) || await pathExists2(path12.join(".opencode", PLUGIN_PATH));
|
|
5179
5237
|
} catch {
|
|
5180
5238
|
return false;
|
|
5181
5239
|
}
|
|
@@ -5183,7 +5241,7 @@ function createOpenCodeAdapter() {
|
|
|
5183
5241
|
installEntries(home, env) {
|
|
5184
5242
|
return [{
|
|
5185
5243
|
kind: "file",
|
|
5186
|
-
path:
|
|
5244
|
+
path: path12.join(opencodeConfigDir(home, env), PLUGIN_PATH),
|
|
5187
5245
|
content: opencodePluginContent()
|
|
5188
5246
|
}];
|
|
5189
5247
|
},
|
|
@@ -5196,7 +5254,7 @@ function createOpenCodeAdapter() {
|
|
|
5196
5254
|
|
|
5197
5255
|
// src/adapters/pi.ts
|
|
5198
5256
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
5199
|
-
import
|
|
5257
|
+
import path13 from "node:path";
|
|
5200
5258
|
async function parsePiSessionFile(filePath, options) {
|
|
5201
5259
|
const text = await readFile8(filePath, "utf8");
|
|
5202
5260
|
const lines = text.split("\n").filter(Boolean);
|
|
@@ -5229,7 +5287,7 @@ async function parsePiSessionFile(filePath, options) {
|
|
|
5229
5287
|
sessionId = stringField(raw, "id") || state.sessionId;
|
|
5230
5288
|
state.sessionId = sessionId || state.sessionId;
|
|
5231
5289
|
cwd = stringField(raw, "cwd") || cwd;
|
|
5232
|
-
project = cwd ?
|
|
5290
|
+
project = cwd ? path13.basename(cwd) : project;
|
|
5233
5291
|
continue;
|
|
5234
5292
|
}
|
|
5235
5293
|
if (entryType === "model_change") {
|
|
@@ -5638,16 +5696,16 @@ export default function (pi: ExtensionAPI) {
|
|
|
5638
5696
|
function piAgentDir(home, env) {
|
|
5639
5697
|
const override = env?.PI_CODING_AGENT_DIR;
|
|
5640
5698
|
if (override && override.trim()) {
|
|
5641
|
-
return
|
|
5699
|
+
return path13.resolve(override);
|
|
5642
5700
|
}
|
|
5643
|
-
return
|
|
5701
|
+
return path13.join(home, ".pi", "agent");
|
|
5644
5702
|
}
|
|
5645
5703
|
function piSessionDir(home, env) {
|
|
5646
5704
|
const override = env?.PI_CODING_AGENT_SESSION_DIR;
|
|
5647
5705
|
if (override && override.trim()) {
|
|
5648
|
-
return
|
|
5706
|
+
return path13.resolve(override);
|
|
5649
5707
|
}
|
|
5650
|
-
return
|
|
5708
|
+
return path13.join(piAgentDir(home, env), "sessions");
|
|
5651
5709
|
}
|
|
5652
5710
|
function createPiAdapter() {
|
|
5653
5711
|
return {
|
|
@@ -5659,12 +5717,12 @@ function createPiAdapter() {
|
|
|
5659
5717
|
return piAgentDir(home, env);
|
|
5660
5718
|
},
|
|
5661
5719
|
installedPath(home, env) {
|
|
5662
|
-
return
|
|
5720
|
+
return path13.join(piAgentDir(home, env), "extensions", "vibetime.ts");
|
|
5663
5721
|
},
|
|
5664
5722
|
async isInstalled(home, env) {
|
|
5665
5723
|
try {
|
|
5666
5724
|
const { pathExists: pathExists2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
5667
|
-
return await pathExists2(
|
|
5725
|
+
return await pathExists2(path13.join(piAgentDir(home, env), "extensions", "vibetime.ts"));
|
|
5668
5726
|
} catch {
|
|
5669
5727
|
return false;
|
|
5670
5728
|
}
|
|
@@ -5672,7 +5730,7 @@ function createPiAdapter() {
|
|
|
5672
5730
|
installEntries(home, env) {
|
|
5673
5731
|
return [{
|
|
5674
5732
|
kind: "file",
|
|
5675
|
-
path:
|
|
5733
|
+
path: path13.join(piAgentDir(home, env), "extensions", "vibetime.ts"),
|
|
5676
5734
|
content: piExtensionContent()
|
|
5677
5735
|
}];
|
|
5678
5736
|
},
|
|
@@ -5685,10 +5743,10 @@ function createPiAdapter() {
|
|
|
5685
5743
|
|
|
5686
5744
|
// src/adapters/qoder-cn.ts
|
|
5687
5745
|
import { readdir as readdir6, readFile as readFile9, stat as stat6 } from "node:fs/promises";
|
|
5688
|
-
import
|
|
5689
|
-
import
|
|
5746
|
+
import os7 from "node:os";
|
|
5747
|
+
import path14 from "node:path";
|
|
5690
5748
|
function parseQoderCnPaths(filePath) {
|
|
5691
|
-
const parts = filePath.split(
|
|
5749
|
+
const parts = filePath.split(path14.sep);
|
|
5692
5750
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
5693
5751
|
let sessionId = "";
|
|
5694
5752
|
let projectName = "";
|
|
@@ -5697,19 +5755,19 @@ function parseQoderCnPaths(filePath) {
|
|
|
5697
5755
|
sessionId = parts[subagentsIdx - 1];
|
|
5698
5756
|
projectName = parts[subagentsIdx - 2];
|
|
5699
5757
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
5700
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
5758
|
+
configDir2 = parts.slice(0, projectsIdx).join(path14.sep);
|
|
5701
5759
|
} else {
|
|
5702
5760
|
const filename = parts.at(-1) || "";
|
|
5703
|
-
sessionId =
|
|
5761
|
+
sessionId = path14.basename(filename, ".jsonl");
|
|
5704
5762
|
projectName = parts.at(-2) || "";
|
|
5705
5763
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
5706
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
5764
|
+
configDir2 = parts.slice(0, projectsIdx).join(path14.sep);
|
|
5707
5765
|
}
|
|
5708
5766
|
return { configDir: configDir2, projectName, sessionId };
|
|
5709
5767
|
}
|
|
5710
5768
|
async function loadQoderCnModelNames(configDir2) {
|
|
5711
5769
|
try {
|
|
5712
|
-
const dynamicTextsPath =
|
|
5770
|
+
const dynamicTextsPath = path14.join(configDir2, ".auth", "dynamic-texts.json");
|
|
5713
5771
|
const content = await readFile9(dynamicTextsPath, "utf8");
|
|
5714
5772
|
const json = JSON.parse(content);
|
|
5715
5773
|
const texts = json.texts || {};
|
|
@@ -5727,7 +5785,7 @@ async function loadQoderCnModelNames(configDir2) {
|
|
|
5727
5785
|
}
|
|
5728
5786
|
async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
5729
5787
|
const { configDir: configDir2, projectName, sessionId } = parseQoderCnPaths(filePath);
|
|
5730
|
-
const segmentsPath =
|
|
5788
|
+
const segmentsPath = path14.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
5731
5789
|
const modelCalls = [];
|
|
5732
5790
|
try {
|
|
5733
5791
|
const files = await readdir6(segmentsPath);
|
|
@@ -5735,7 +5793,7 @@ async function loadQoderCnSegmentModelCalls(filePath, isSubagentSession, modelMa
|
|
|
5735
5793
|
if (!file.endsWith(".jsonl")) {
|
|
5736
5794
|
continue;
|
|
5737
5795
|
}
|
|
5738
|
-
const content = await readFile9(
|
|
5796
|
+
const content = await readFile9(path14.join(segmentsPath, file), "utf8");
|
|
5739
5797
|
let currentTurnIsSubagent = false;
|
|
5740
5798
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
5741
5799
|
const raw = parseJsonLine(line);
|
|
@@ -5803,7 +5861,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
5803
5861
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
5804
5862
|
state.sessionId = sessionId;
|
|
5805
5863
|
cwd = stringField(raw, "cwd") || cwd;
|
|
5806
|
-
project = projectContext.project || (cwd ?
|
|
5864
|
+
project = projectContext.project || (cwd ? path14.basename(cwd) : project || await qoderCnProjectFromFilePath(filePath, options));
|
|
5807
5865
|
if (!ts) {
|
|
5808
5866
|
continue;
|
|
5809
5867
|
}
|
|
@@ -6232,35 +6290,40 @@ function isNoisePrompt(text) {
|
|
|
6232
6290
|
}
|
|
6233
6291
|
async function qoderCnProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
6234
6292
|
const { projectName: projectDir, sessionId } = parseQoderCnPaths(filePath);
|
|
6235
|
-
const isSubagent = filePath.includes(`${
|
|
6293
|
+
const isSubagent = filePath.includes(`${path14.sep}subagents${path14.sep}`);
|
|
6294
|
+
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
6236
6295
|
let cwds = [];
|
|
6237
6296
|
for (const line of lines) {
|
|
6238
6297
|
const raw = parseJsonLine(line);
|
|
6239
6298
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
6240
|
-
if (cwd &&
|
|
6299
|
+
if (cwd && path14.isAbsolute(cwd)) {
|
|
6241
6300
|
cwds.push(cwd);
|
|
6242
6301
|
}
|
|
6243
6302
|
}
|
|
6244
6303
|
if (isSubagent) {
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
const
|
|
6249
|
-
|
|
6250
|
-
const
|
|
6251
|
-
const
|
|
6252
|
-
|
|
6253
|
-
|
|
6304
|
+
if (inherited?.cwd && path14.isAbsolute(inherited.cwd)) {
|
|
6305
|
+
cwds = [inherited.cwd];
|
|
6306
|
+
} else {
|
|
6307
|
+
const parentSessionPath = path14.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
6308
|
+
try {
|
|
6309
|
+
const parentText = await readFile9(parentSessionPath, "utf8");
|
|
6310
|
+
const parentCwds = [];
|
|
6311
|
+
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
6312
|
+
const raw = parseJsonLine(line);
|
|
6313
|
+
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
6314
|
+
if (cwd && path14.isAbsolute(cwd)) {
|
|
6315
|
+
parentCwds.push(cwd);
|
|
6316
|
+
}
|
|
6254
6317
|
}
|
|
6318
|
+
if (parentCwds.length > 0) {
|
|
6319
|
+
cwds = parentCwds;
|
|
6320
|
+
}
|
|
6321
|
+
} catch {
|
|
6255
6322
|
}
|
|
6256
|
-
if (parentCwds.length > 0) {
|
|
6257
|
-
cwds = parentCwds;
|
|
6258
|
-
}
|
|
6259
|
-
} catch {
|
|
6260
6323
|
}
|
|
6261
6324
|
}
|
|
6262
6325
|
const root = await gitRootFromCwds2(cwds) || qoderCnProjectRootFromCwds(projectDir, cwds);
|
|
6263
|
-
const project = cwds.length > 0 ?
|
|
6326
|
+
const project = inherited?.project || (cwds.length > 0 ? path14.basename(cwds[0]) : root ? path14.basename(root) : await qoderCnProjectFromFilePath(filePath, options));
|
|
6264
6327
|
return {
|
|
6265
6328
|
project,
|
|
6266
6329
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -6269,15 +6332,15 @@ async function qoderCnProjectContextFromLines(filePath, lines, options, configDi
|
|
|
6269
6332
|
async function gitRootFromCwds2(cwds) {
|
|
6270
6333
|
const seen = /* @__PURE__ */ new Set();
|
|
6271
6334
|
for (const cwd of cwds) {
|
|
6272
|
-
let current =
|
|
6335
|
+
let current = path14.resolve(cwd);
|
|
6273
6336
|
while (!seen.has(current)) {
|
|
6274
6337
|
seen.add(current);
|
|
6275
6338
|
try {
|
|
6276
|
-
await stat6(
|
|
6339
|
+
await stat6(path14.join(current, ".git"));
|
|
6277
6340
|
return current;
|
|
6278
6341
|
} catch {
|
|
6279
6342
|
}
|
|
6280
|
-
const parent =
|
|
6343
|
+
const parent = path14.dirname(current);
|
|
6281
6344
|
if (parent === current) {
|
|
6282
6345
|
break;
|
|
6283
6346
|
}
|
|
@@ -6288,12 +6351,12 @@ async function gitRootFromCwds2(cwds) {
|
|
|
6288
6351
|
}
|
|
6289
6352
|
function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
6290
6353
|
for (const cwd of cwds) {
|
|
6291
|
-
let current =
|
|
6354
|
+
let current = path14.resolve(cwd);
|
|
6292
6355
|
while (true) {
|
|
6293
6356
|
if (encodeQoderCnProjectPath(current) === projectDir) {
|
|
6294
6357
|
return current;
|
|
6295
6358
|
}
|
|
6296
|
-
const parent =
|
|
6359
|
+
const parent = path14.dirname(current);
|
|
6297
6360
|
if (parent === current) {
|
|
6298
6361
|
break;
|
|
6299
6362
|
}
|
|
@@ -6303,14 +6366,14 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
|
6303
6366
|
return void 0;
|
|
6304
6367
|
}
|
|
6305
6368
|
function encodeQoderCnProjectPath(value) {
|
|
6306
|
-
return
|
|
6369
|
+
return path14.resolve(value).split(path14.sep).join("-").replace(/_/g, "-");
|
|
6307
6370
|
}
|
|
6308
6371
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
6309
|
-
const projectDir =
|
|
6310
|
-
const home = options ?
|
|
6372
|
+
const projectDir = path14.basename(path14.dirname(filePath));
|
|
6373
|
+
const home = options ? path14.resolve(stringOption(options.home) || os7.homedir()) : os7.homedir();
|
|
6311
6374
|
const resolved = await resolveQoderCnProjectPath(projectDir, home);
|
|
6312
6375
|
if (resolved) {
|
|
6313
|
-
return
|
|
6376
|
+
return path14.basename(resolved);
|
|
6314
6377
|
}
|
|
6315
6378
|
const homePrefix = `${encodeQoderCnProjectPath(home)}-`;
|
|
6316
6379
|
if (projectDir.startsWith(homePrefix)) {
|
|
@@ -6335,7 +6398,7 @@ async function resolveQoderCnProjectPath(projectDir, home) {
|
|
|
6335
6398
|
if (!entry.isDirectory()) {
|
|
6336
6399
|
continue;
|
|
6337
6400
|
}
|
|
6338
|
-
const candidate =
|
|
6401
|
+
const candidate = path14.join(current, entry.name);
|
|
6339
6402
|
const encoded = encodeQoderCnProjectPath(candidate);
|
|
6340
6403
|
if (encoded === projectDir) {
|
|
6341
6404
|
return candidate;
|
|
@@ -6380,9 +6443,9 @@ function hookConfig5() {
|
|
|
6380
6443
|
function qoderCnConfigDir(home, env) {
|
|
6381
6444
|
const override = env?.QODER_CN_CONFIG_DIR;
|
|
6382
6445
|
if (override && override.trim()) {
|
|
6383
|
-
return
|
|
6446
|
+
return path14.resolve(override);
|
|
6384
6447
|
}
|
|
6385
|
-
return
|
|
6448
|
+
return path14.join(home, ".qoder-cn");
|
|
6386
6449
|
}
|
|
6387
6450
|
function createQoderCnAdapter() {
|
|
6388
6451
|
return {
|
|
@@ -6394,27 +6457,27 @@ function createQoderCnAdapter() {
|
|
|
6394
6457
|
return qoderCnConfigDir(home, env);
|
|
6395
6458
|
},
|
|
6396
6459
|
installedPath(home, env) {
|
|
6397
|
-
return
|
|
6460
|
+
return path14.join(qoderCnConfigDir(home, env), "settings.json");
|
|
6398
6461
|
},
|
|
6399
6462
|
async isInstalled(home, env) {
|
|
6400
6463
|
return isHooksJsonInstalled(
|
|
6401
|
-
|
|
6464
|
+
path14.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
6402
6465
|
"vibetime hook --agent qoder-cn"
|
|
6403
6466
|
);
|
|
6404
6467
|
},
|
|
6405
6468
|
installEntries(home, env) {
|
|
6406
6469
|
return [{
|
|
6407
6470
|
kind: "hooks-json",
|
|
6408
|
-
path:
|
|
6471
|
+
path: path14.join(qoderCnConfigDir(home, env), "settings.json"),
|
|
6409
6472
|
content: hookConfig5()
|
|
6410
6473
|
}];
|
|
6411
6474
|
},
|
|
6412
6475
|
sourcePaths(home, env) {
|
|
6413
6476
|
const base = qoderCnConfigDir(home, env);
|
|
6414
6477
|
return [
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6478
|
+
path14.join(base, "projects"),
|
|
6479
|
+
path14.join(base, ".qoder.json"),
|
|
6480
|
+
path14.join(home, ".qoder.json")
|
|
6418
6481
|
];
|
|
6419
6482
|
},
|
|
6420
6483
|
parseSessionFile: parseQoderCnSessionFile
|
|
@@ -6423,10 +6486,10 @@ function createQoderCnAdapter() {
|
|
|
6423
6486
|
|
|
6424
6487
|
// src/adapters/qoder.ts
|
|
6425
6488
|
import { readdir as readdir7, readFile as readFile10, stat as stat7 } from "node:fs/promises";
|
|
6426
|
-
import
|
|
6427
|
-
import
|
|
6489
|
+
import os8 from "node:os";
|
|
6490
|
+
import path15 from "node:path";
|
|
6428
6491
|
function parseQoderPaths(filePath) {
|
|
6429
|
-
const parts = filePath.split(
|
|
6492
|
+
const parts = filePath.split(path15.sep);
|
|
6430
6493
|
const subagentsIdx = parts.lastIndexOf("subagents");
|
|
6431
6494
|
let sessionId = "";
|
|
6432
6495
|
let projectName = "";
|
|
@@ -6435,19 +6498,19 @@ function parseQoderPaths(filePath) {
|
|
|
6435
6498
|
sessionId = parts[subagentsIdx - 1];
|
|
6436
6499
|
projectName = parts[subagentsIdx - 2];
|
|
6437
6500
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
6438
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
6501
|
+
configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
|
|
6439
6502
|
} else {
|
|
6440
6503
|
const filename = parts.at(-1) || "";
|
|
6441
|
-
sessionId =
|
|
6504
|
+
sessionId = path15.basename(filename, ".jsonl");
|
|
6442
6505
|
projectName = parts.at(-2) || "";
|
|
6443
6506
|
const projectsIdx = parts.lastIndexOf("projects");
|
|
6444
|
-
configDir2 = parts.slice(0, projectsIdx).join(
|
|
6507
|
+
configDir2 = parts.slice(0, projectsIdx).join(path15.sep);
|
|
6445
6508
|
}
|
|
6446
6509
|
return { configDir: configDir2, projectName, sessionId };
|
|
6447
6510
|
}
|
|
6448
6511
|
async function loadQoderModelNames(configDir2) {
|
|
6449
6512
|
try {
|
|
6450
|
-
const dynamicTextsPath =
|
|
6513
|
+
const dynamicTextsPath = path15.join(configDir2, ".auth", "dynamic-texts.json");
|
|
6451
6514
|
const content = await readFile10(dynamicTextsPath, "utf8");
|
|
6452
6515
|
const json = JSON.parse(content);
|
|
6453
6516
|
const texts = json.texts || {};
|
|
@@ -6465,7 +6528,7 @@ async function loadQoderModelNames(configDir2) {
|
|
|
6465
6528
|
}
|
|
6466
6529
|
async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap) {
|
|
6467
6530
|
const { configDir: configDir2, projectName, sessionId } = parseQoderPaths(filePath);
|
|
6468
|
-
const segmentsPath =
|
|
6531
|
+
const segmentsPath = path15.join(configDir2, "logs", "sessions", projectName, sessionId, "segments");
|
|
6469
6532
|
const modelCalls = [];
|
|
6470
6533
|
try {
|
|
6471
6534
|
const files = await readdir7(segmentsPath);
|
|
@@ -6473,7 +6536,7 @@ async function loadQoderSegmentModelCalls(filePath, isSubagentSession, modelMap)
|
|
|
6473
6536
|
if (!file.endsWith(".jsonl")) {
|
|
6474
6537
|
continue;
|
|
6475
6538
|
}
|
|
6476
|
-
const content = await readFile10(
|
|
6539
|
+
const content = await readFile10(path15.join(segmentsPath, file), "utf8");
|
|
6477
6540
|
let currentTurnIsSubagent = false;
|
|
6478
6541
|
for (const line of content.split("\n").filter(Boolean)) {
|
|
6479
6542
|
const raw = parseJsonLine(line);
|
|
@@ -6541,7 +6604,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
6541
6604
|
sessionId = stringField(raw, "sessionId") || sessionId;
|
|
6542
6605
|
state.sessionId = sessionId;
|
|
6543
6606
|
cwd = stringField(raw, "cwd") || cwd;
|
|
6544
|
-
project = projectContext.project || (cwd ?
|
|
6607
|
+
project = projectContext.project || (cwd ? path15.basename(cwd) : project || await qoderProjectFromFilePath(filePath, options));
|
|
6545
6608
|
if (!ts) {
|
|
6546
6609
|
continue;
|
|
6547
6610
|
}
|
|
@@ -6936,35 +6999,40 @@ function qoderExtractText(value) {
|
|
|
6936
6999
|
}
|
|
6937
7000
|
async function qoderProjectContextFromLines(filePath, lines, options, configDir2) {
|
|
6938
7001
|
const { projectName: projectDir, sessionId } = parseQoderPaths(filePath);
|
|
6939
|
-
const isSubagent = filePath.includes(`${
|
|
7002
|
+
const isSubagent = filePath.includes(`${path15.sep}subagents${path15.sep}`);
|
|
7003
|
+
const inherited = isSubagent ? await readPersistedSessionContextFromOptions(options, sessionId) : void 0;
|
|
6940
7004
|
let cwds = [];
|
|
6941
7005
|
for (const line of lines) {
|
|
6942
7006
|
const raw = parseJsonLine(line);
|
|
6943
7007
|
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
6944
|
-
if (cwd &&
|
|
7008
|
+
if (cwd && path15.isAbsolute(cwd)) {
|
|
6945
7009
|
cwds.push(cwd);
|
|
6946
7010
|
}
|
|
6947
7011
|
}
|
|
6948
7012
|
if (isSubagent) {
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
const
|
|
6953
|
-
|
|
6954
|
-
const
|
|
6955
|
-
const
|
|
6956
|
-
|
|
6957
|
-
|
|
7013
|
+
if (inherited?.cwd && path15.isAbsolute(inherited.cwd)) {
|
|
7014
|
+
cwds = [inherited.cwd];
|
|
7015
|
+
} else {
|
|
7016
|
+
const parentSessionPath = path15.join(configDir2, "projects", projectDir, `${sessionId}.jsonl`);
|
|
7017
|
+
try {
|
|
7018
|
+
const parentText = await readFile10(parentSessionPath, "utf8");
|
|
7019
|
+
const parentCwds = [];
|
|
7020
|
+
for (const line of parentText.split("\n").filter(Boolean)) {
|
|
7021
|
+
const raw = parseJsonLine(line);
|
|
7022
|
+
const cwd = raw ? stringField(raw, "cwd") : void 0;
|
|
7023
|
+
if (cwd && path15.isAbsolute(cwd)) {
|
|
7024
|
+
parentCwds.push(cwd);
|
|
7025
|
+
}
|
|
6958
7026
|
}
|
|
7027
|
+
if (parentCwds.length > 0) {
|
|
7028
|
+
cwds = parentCwds;
|
|
7029
|
+
}
|
|
7030
|
+
} catch {
|
|
6959
7031
|
}
|
|
6960
|
-
if (parentCwds.length > 0) {
|
|
6961
|
-
cwds = parentCwds;
|
|
6962
|
-
}
|
|
6963
|
-
} catch {
|
|
6964
7032
|
}
|
|
6965
7033
|
}
|
|
6966
7034
|
const root = await gitRootFromCwds3(cwds) || qoderProjectRootFromCwds(projectDir, cwds);
|
|
6967
|
-
const project = cwds.length > 0 ?
|
|
7035
|
+
const project = inherited?.project || (cwds.length > 0 ? path15.basename(cwds[0]) : root ? path15.basename(root) : await qoderProjectFromFilePath(filePath, options));
|
|
6968
7036
|
return {
|
|
6969
7037
|
project,
|
|
6970
7038
|
workspaceId: createWorkspaceId({ projectName: project, repoRoot: root })
|
|
@@ -6973,15 +7041,15 @@ async function qoderProjectContextFromLines(filePath, lines, options, configDir2
|
|
|
6973
7041
|
async function gitRootFromCwds3(cwds) {
|
|
6974
7042
|
const seen = /* @__PURE__ */ new Set();
|
|
6975
7043
|
for (const cwd of cwds) {
|
|
6976
|
-
let current =
|
|
7044
|
+
let current = path15.resolve(cwd);
|
|
6977
7045
|
while (!seen.has(current)) {
|
|
6978
7046
|
seen.add(current);
|
|
6979
7047
|
try {
|
|
6980
|
-
await stat7(
|
|
7048
|
+
await stat7(path15.join(current, ".git"));
|
|
6981
7049
|
return current;
|
|
6982
7050
|
} catch {
|
|
6983
7051
|
}
|
|
6984
|
-
const parent =
|
|
7052
|
+
const parent = path15.dirname(current);
|
|
6985
7053
|
if (parent === current) {
|
|
6986
7054
|
break;
|
|
6987
7055
|
}
|
|
@@ -6992,12 +7060,12 @@ async function gitRootFromCwds3(cwds) {
|
|
|
6992
7060
|
}
|
|
6993
7061
|
function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
6994
7062
|
for (const cwd of cwds) {
|
|
6995
|
-
let current =
|
|
7063
|
+
let current = path15.resolve(cwd);
|
|
6996
7064
|
while (true) {
|
|
6997
7065
|
if (encodeQoderProjectPath(current) === projectDir) {
|
|
6998
7066
|
return current;
|
|
6999
7067
|
}
|
|
7000
|
-
const parent =
|
|
7068
|
+
const parent = path15.dirname(current);
|
|
7001
7069
|
if (parent === current) {
|
|
7002
7070
|
break;
|
|
7003
7071
|
}
|
|
@@ -7007,10 +7075,10 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
|
7007
7075
|
return void 0;
|
|
7008
7076
|
}
|
|
7009
7077
|
function encodeQoderProjectPath(value) {
|
|
7010
|
-
return
|
|
7078
|
+
return path15.resolve(value).split(path15.sep).join("-").replace(/_/g, "-");
|
|
7011
7079
|
}
|
|
7012
7080
|
function rawQoderProjectPath(value) {
|
|
7013
|
-
return
|
|
7081
|
+
return path15.resolve(value).split(path15.sep).join("-");
|
|
7014
7082
|
}
|
|
7015
7083
|
function qoderEncodedVariants(value) {
|
|
7016
7084
|
const raw = rawQoderProjectPath(value);
|
|
@@ -7026,11 +7094,11 @@ function qoderEncodedProjectSuffix(projectDir, home) {
|
|
|
7026
7094
|
return void 0;
|
|
7027
7095
|
}
|
|
7028
7096
|
async function qoderProjectFromFilePath(filePath, options) {
|
|
7029
|
-
const projectDir =
|
|
7030
|
-
const home = options ?
|
|
7097
|
+
const projectDir = path15.basename(path15.dirname(filePath));
|
|
7098
|
+
const home = options ? path15.resolve(stringOption(options.home) || os8.homedir()) : os8.homedir();
|
|
7031
7099
|
const resolved = await resolveQoderProjectPath(projectDir, home);
|
|
7032
7100
|
if (resolved) {
|
|
7033
|
-
return
|
|
7101
|
+
return path15.basename(resolved);
|
|
7034
7102
|
}
|
|
7035
7103
|
const suffix = qoderEncodedProjectSuffix(projectDir, home);
|
|
7036
7104
|
if (suffix) {
|
|
@@ -7056,7 +7124,7 @@ async function resolveQoderProjectPath(projectDir, home) {
|
|
|
7056
7124
|
if (!entry.isDirectory()) {
|
|
7057
7125
|
continue;
|
|
7058
7126
|
}
|
|
7059
|
-
const candidate =
|
|
7127
|
+
const candidate = path15.join(current, entry.name);
|
|
7060
7128
|
const candidateVariants = qoderEncodedVariants(candidate);
|
|
7061
7129
|
if (candidateVariants.includes(projectDir)) {
|
|
7062
7130
|
return candidate;
|
|
@@ -7101,9 +7169,9 @@ function hookConfig6() {
|
|
|
7101
7169
|
function qoderConfigDir(home, env) {
|
|
7102
7170
|
const override = env?.QODER_CONFIG_DIR;
|
|
7103
7171
|
if (override && override.trim()) {
|
|
7104
|
-
return
|
|
7172
|
+
return path15.resolve(override);
|
|
7105
7173
|
}
|
|
7106
|
-
return
|
|
7174
|
+
return path15.join(home, ".qoder");
|
|
7107
7175
|
}
|
|
7108
7176
|
function createQoderAdapter() {
|
|
7109
7177
|
return {
|
|
@@ -7115,27 +7183,27 @@ function createQoderAdapter() {
|
|
|
7115
7183
|
return qoderConfigDir(home, env);
|
|
7116
7184
|
},
|
|
7117
7185
|
installedPath(home, env) {
|
|
7118
|
-
return
|
|
7186
|
+
return path15.join(qoderConfigDir(home, env), "settings.json");
|
|
7119
7187
|
},
|
|
7120
7188
|
async isInstalled(home, env) {
|
|
7121
7189
|
return isHooksJsonInstalled(
|
|
7122
|
-
|
|
7190
|
+
path15.join(qoderConfigDir(home, env), "settings.json"),
|
|
7123
7191
|
"vibetime hook --agent qoder"
|
|
7124
7192
|
);
|
|
7125
7193
|
},
|
|
7126
7194
|
installEntries(home, env) {
|
|
7127
7195
|
return [{
|
|
7128
7196
|
kind: "hooks-json",
|
|
7129
|
-
path:
|
|
7197
|
+
path: path15.join(qoderConfigDir(home, env), "settings.json"),
|
|
7130
7198
|
content: hookConfig6()
|
|
7131
7199
|
}];
|
|
7132
7200
|
},
|
|
7133
7201
|
sourcePaths(home, env) {
|
|
7134
7202
|
const base = qoderConfigDir(home, env);
|
|
7135
7203
|
return [
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7204
|
+
path15.join(base, "projects"),
|
|
7205
|
+
path15.join(base, ".qoder.json"),
|
|
7206
|
+
path15.join(home, ".qoder.json")
|
|
7139
7207
|
];
|
|
7140
7208
|
},
|
|
7141
7209
|
parseSessionFile: parseQoderSessionFile
|
|
@@ -7171,20 +7239,20 @@ function normalizeId(id) {
|
|
|
7171
7239
|
|
|
7172
7240
|
// src/adapters/workbuddy.ts
|
|
7173
7241
|
import { readFile as readFile11, readdir as readdir8, stat as stat8 } from "node:fs/promises";
|
|
7174
|
-
import
|
|
7242
|
+
import path16 from "node:path";
|
|
7175
7243
|
init_fs();
|
|
7176
7244
|
function workbuddyProjectsDir(home, env) {
|
|
7177
7245
|
const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
|
|
7178
7246
|
if (override && override.trim()) {
|
|
7179
|
-
return
|
|
7247
|
+
return path16.resolve(override, override.endsWith("projects") ? "" : "projects");
|
|
7180
7248
|
}
|
|
7181
|
-
return
|
|
7249
|
+
return path16.join(home, ".workbuddy", "projects");
|
|
7182
7250
|
}
|
|
7183
7251
|
function projectFromCwd(cwd, fallback) {
|
|
7184
7252
|
if (!cwd) {
|
|
7185
7253
|
return fallback;
|
|
7186
7254
|
}
|
|
7187
|
-
return
|
|
7255
|
+
return path16.basename(cwd) || fallback;
|
|
7188
7256
|
}
|
|
7189
7257
|
function sourceHash(filePath) {
|
|
7190
7258
|
return `sha256:${createStableHash(filePath)}`;
|
|
@@ -7286,8 +7354,8 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
7286
7354
|
}
|
|
7287
7355
|
const events = [];
|
|
7288
7356
|
const first = lines[0].record;
|
|
7289
|
-
const sessionId = stringField(first, "sessionId") ||
|
|
7290
|
-
const fallbackProject =
|
|
7357
|
+
const sessionId = stringField(first, "sessionId") || path16.basename(filePath, ".jsonl");
|
|
7358
|
+
const fallbackProject = path16.basename(path16.dirname(filePath));
|
|
7291
7359
|
const cwd = lines.map((line) => stringField(line.record, "cwd")).find(Boolean);
|
|
7292
7360
|
const project = projectFromCwd(cwd, fallbackProject);
|
|
7293
7361
|
const workspaceId = createWorkspaceId({ projectName: project, repoRoot: cwd });
|
|
@@ -7461,11 +7529,11 @@ async function workbuddyBackfillFiles(sourceRoot, home, env) {
|
|
|
7461
7529
|
if (!project.isDirectory()) {
|
|
7462
7530
|
continue;
|
|
7463
7531
|
}
|
|
7464
|
-
const projectDir =
|
|
7532
|
+
const projectDir = path16.join(base, project.name);
|
|
7465
7533
|
const entries = await readdir8(projectDir, { withFileTypes: true });
|
|
7466
7534
|
for (const entry of entries) {
|
|
7467
7535
|
if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
7468
|
-
const filePath =
|
|
7536
|
+
const filePath = path16.join(projectDir, entry.name);
|
|
7469
7537
|
const info = await stat8(filePath);
|
|
7470
7538
|
files.push({ path: filePath, modifiedAt: info.mtime.toISOString() });
|
|
7471
7539
|
}
|
|
@@ -7504,19 +7572,19 @@ function createWorkbuddyAdapter() {
|
|
|
7504
7572
|
// src/adapters/zcode.ts
|
|
7505
7573
|
import { execFile } from "node:child_process";
|
|
7506
7574
|
import { readFile as readFile12, stat as stat9 } from "node:fs/promises";
|
|
7507
|
-
import
|
|
7575
|
+
import path17 from "node:path";
|
|
7508
7576
|
import { promisify as promisify2 } from "node:util";
|
|
7509
7577
|
init_fs();
|
|
7510
7578
|
var execFileAsync = promisify2(execFile);
|
|
7511
7579
|
function zcodeCliDir(home, env) {
|
|
7512
7580
|
const override = env?.ZCODE_CLI_DIR || env?.ZCODE_HOME;
|
|
7513
7581
|
if (override && override.trim()) {
|
|
7514
|
-
return
|
|
7582
|
+
return path17.resolve(override, override.endsWith("cli") ? "" : "cli");
|
|
7515
7583
|
}
|
|
7516
|
-
return
|
|
7584
|
+
return path17.join(home, ".zcode", "cli");
|
|
7517
7585
|
}
|
|
7518
7586
|
function zcodeDbPath(home, env) {
|
|
7519
|
-
return
|
|
7587
|
+
return path17.join(zcodeCliDir(home, env), "db", "db.sqlite");
|
|
7520
7588
|
}
|
|
7521
7589
|
var providerNameCache = null;
|
|
7522
7590
|
async function loadProviderNames(configPath2) {
|
|
@@ -7550,7 +7618,7 @@ function sourceHash2(filePath) {
|
|
|
7550
7618
|
return `sha256:${createStableHash(filePath)}`;
|
|
7551
7619
|
}
|
|
7552
7620
|
function projectFromDirectory(directory) {
|
|
7553
|
-
return directory ?
|
|
7621
|
+
return directory ? path17.basename(directory) || "zcode" : "zcode";
|
|
7554
7622
|
}
|
|
7555
7623
|
function isoFromMs(value) {
|
|
7556
7624
|
return timestampFrom(typeof value === "number" ? value : Number(value));
|
|
@@ -7706,16 +7774,16 @@ async function parseZCodeDb(filePath, options) {
|
|
|
7706
7774
|
if (rows.length === 0) {
|
|
7707
7775
|
return [];
|
|
7708
7776
|
}
|
|
7709
|
-
let candidate =
|
|
7777
|
+
let candidate = path17.resolve(filePath);
|
|
7710
7778
|
let configPath2 = "";
|
|
7711
7779
|
for (let i = 0; i < 12; i++) {
|
|
7712
|
-
const probe =
|
|
7780
|
+
const probe = path17.join(candidate, ".zcode", "v2", "config.json");
|
|
7713
7781
|
try {
|
|
7714
7782
|
await stat9(probe);
|
|
7715
7783
|
configPath2 = probe;
|
|
7716
7784
|
break;
|
|
7717
7785
|
} catch {
|
|
7718
|
-
const parent =
|
|
7786
|
+
const parent = path17.dirname(candidate);
|
|
7719
7787
|
if (parent === candidate) break;
|
|
7720
7788
|
candidate = parent;
|
|
7721
7789
|
}
|
|
@@ -7931,7 +7999,7 @@ async function parseZCodeDb(filePath, options) {
|
|
|
7931
7999
|
}
|
|
7932
8000
|
async function zcodeBackfillFiles(sourceRoot, home, env) {
|
|
7933
8001
|
const candidate = sourceRoot || zcodeDbPath(home, env);
|
|
7934
|
-
const filePath = candidate.endsWith(".sqlite") ? candidate :
|
|
8002
|
+
const filePath = candidate.endsWith(".sqlite") ? candidate : path17.join(candidate, "db", "db.sqlite");
|
|
7935
8003
|
try {
|
|
7936
8004
|
const info = await stat9(filePath);
|
|
7937
8005
|
return [{ path: filePath, modifiedAt: info.mtime.toISOString() }];
|
|
@@ -8305,7 +8373,7 @@ async function installEntry(entry, options) {
|
|
|
8305
8373
|
});
|
|
8306
8374
|
}
|
|
8307
8375
|
async function mergeHooksJson(filePath, content, { dryRun, force, onWrite }) {
|
|
8308
|
-
const { mkdir:
|
|
8376
|
+
const { mkdir: mkdir6, writeFile: writeFile5 } = await import("node:fs/promises");
|
|
8309
8377
|
const pathMod = await import("node:path");
|
|
8310
8378
|
if (dryRun) {
|
|
8311
8379
|
onWrite(`Would merge ${filePath}`);
|
|
@@ -8326,8 +8394,8 @@ async function mergeHooksJson(filePath, content, { dryRun, force, onWrite }) {
|
|
|
8326
8394
|
onWrite(`Already installed ${filePath}`);
|
|
8327
8395
|
return;
|
|
8328
8396
|
}
|
|
8329
|
-
await
|
|
8330
|
-
await
|
|
8397
|
+
await mkdir6(pathMod.dirname(filePath), { recursive: true });
|
|
8398
|
+
await writeFile5(filePath, nextText, "utf8");
|
|
8331
8399
|
onWrite(`Installed ${filePath}`);
|
|
8332
8400
|
}
|
|
8333
8401
|
function mergeAgyHooksJson(existing, addition) {
|
|
@@ -8405,15 +8473,15 @@ function hookCommandFromGroup(group) {
|
|
|
8405
8473
|
import { randomUUID } from "node:crypto";
|
|
8406
8474
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
8407
8475
|
import { homedir, hostname } from "node:os";
|
|
8408
|
-
import
|
|
8476
|
+
import path18 from "node:path";
|
|
8409
8477
|
function configDir(home = homedir()) {
|
|
8410
|
-
return
|
|
8478
|
+
return path18.join(home, ".vibetime");
|
|
8411
8479
|
}
|
|
8412
8480
|
function configPath(home = homedir()) {
|
|
8413
|
-
return
|
|
8481
|
+
return path18.join(configDir(home), "config.json");
|
|
8414
8482
|
}
|
|
8415
8483
|
function machineIdPath(home = homedir()) {
|
|
8416
|
-
return
|
|
8484
|
+
return path18.join(configDir(home), "machine-id");
|
|
8417
8485
|
}
|
|
8418
8486
|
function readConfig(home = homedir()) {
|
|
8419
8487
|
const file = configPath(home);
|
|
@@ -8460,15 +8528,15 @@ function defaultMachineName() {
|
|
|
8460
8528
|
init_fs();
|
|
8461
8529
|
|
|
8462
8530
|
// src/lib/logger.ts
|
|
8463
|
-
import { appendFile, mkdir as
|
|
8531
|
+
import { appendFile, mkdir as mkdir4, rename, stat as stat10 } from "node:fs/promises";
|
|
8464
8532
|
import { homedir as homedir2 } from "node:os";
|
|
8465
|
-
import
|
|
8533
|
+
import path19 from "node:path";
|
|
8466
8534
|
var MAX_BYTES = 1 * 1024 * 1024;
|
|
8467
8535
|
function logDir(home = homedir2()) {
|
|
8468
|
-
return
|
|
8536
|
+
return path19.join(home, ".vibetime", "logs");
|
|
8469
8537
|
}
|
|
8470
8538
|
function logPath(home = homedir2(), name = "cli.log") {
|
|
8471
|
-
return
|
|
8539
|
+
return path19.join(logDir(home), name);
|
|
8472
8540
|
}
|
|
8473
8541
|
function serializeError(error) {
|
|
8474
8542
|
if (error instanceof Error) {
|
|
@@ -8489,7 +8557,7 @@ async function rotateIfNeeded(file) {
|
|
|
8489
8557
|
async function writeLog(entry, home = homedir2(), fileName = "cli.log") {
|
|
8490
8558
|
try {
|
|
8491
8559
|
const dir = logDir(home);
|
|
8492
|
-
await
|
|
8560
|
+
await mkdir4(dir, { recursive: true });
|
|
8493
8561
|
const file = logPath(home, fileName);
|
|
8494
8562
|
await rotateIfNeeded(file);
|
|
8495
8563
|
const record = {
|
|
@@ -8643,8 +8711,8 @@ function buildHeaders(token, machine) {
|
|
|
8643
8711
|
...machine?.platform ? { "x-machine-platform": machine.platform } : {}
|
|
8644
8712
|
};
|
|
8645
8713
|
}
|
|
8646
|
-
function joinUrl(base,
|
|
8647
|
-
return new URL(
|
|
8714
|
+
function joinUrl(base, path21) {
|
|
8715
|
+
return new URL(path21, base.endsWith("/") ? base : `${base}/`).toString();
|
|
8648
8716
|
}
|
|
8649
8717
|
async function postRollupBatch(remote, rollups, options = {}) {
|
|
8650
8718
|
const response = await remote.fetchImpl(joinUrl(remote.baseUrl, "/v3/agent/ingest"), {
|
|
@@ -8816,7 +8884,7 @@ function normalizeOptions(options) {
|
|
|
8816
8884
|
return normalized;
|
|
8817
8885
|
}
|
|
8818
8886
|
async function detectCommand(options, ctx, registry) {
|
|
8819
|
-
const home =
|
|
8887
|
+
const home = resolveHome3(options, ctx);
|
|
8820
8888
|
const env = ctx.env;
|
|
8821
8889
|
const adapters = registry.all();
|
|
8822
8890
|
const targets = await Promise.all(adapters.map(async (adapter) => {
|
|
@@ -8845,7 +8913,7 @@ async function detectCommand(options, ctx, registry) {
|
|
|
8845
8913
|
}
|
|
8846
8914
|
}
|
|
8847
8915
|
async function installCommand(options, ctx, registry) {
|
|
8848
|
-
const home =
|
|
8916
|
+
const home = resolveHome3(options, ctx);
|
|
8849
8917
|
const env = ctx.env;
|
|
8850
8918
|
const dryRun = Boolean(options["dry-run"]);
|
|
8851
8919
|
const force = Boolean(options.force);
|
|
@@ -8943,7 +9011,7 @@ Upgraded ${current} \u2192 ${latest}
|
|
|
8943
9011
|
return 0;
|
|
8944
9012
|
}
|
|
8945
9013
|
async function hookCommand(options, ctx) {
|
|
8946
|
-
const home =
|
|
9014
|
+
const home = resolveHome3(options, ctx);
|
|
8947
9015
|
try {
|
|
8948
9016
|
const agent = requiredOption(options, "agent");
|
|
8949
9017
|
const payload = await readHookPayload(ctx.stdin);
|
|
@@ -8956,6 +9024,7 @@ async function hookCommand(options, ctx) {
|
|
|
8956
9024
|
`);
|
|
8957
9025
|
return 0;
|
|
8958
9026
|
}
|
|
9027
|
+
await persistHookSessionContext(home, payload);
|
|
8959
9028
|
return await syncLocalTriggerCommand({
|
|
8960
9029
|
...options,
|
|
8961
9030
|
agent,
|
|
@@ -8969,7 +9038,7 @@ async function hookCommand(options, ctx) {
|
|
|
8969
9038
|
}
|
|
8970
9039
|
}
|
|
8971
9040
|
async function syncLocalTriggerCommand(options, ctx, _registry) {
|
|
8972
|
-
const home =
|
|
9041
|
+
const home = resolveHome3(options, ctx);
|
|
8973
9042
|
const statePath = syncLocalTriggerStatePath(home);
|
|
8974
9043
|
const lockPath = syncLocalTriggerLockPath(home);
|
|
8975
9044
|
const minIntervalSeconds = Math.max(0, Math.floor(numberOption(options["min-interval"]) ?? DEFAULT_HOOK_SYNC_MIN_INTERVAL_SECONDS));
|
|
@@ -9012,7 +9081,7 @@ async function syncLocalTriggerCommand(options, ctx, _registry) {
|
|
|
9012
9081
|
return 0;
|
|
9013
9082
|
}
|
|
9014
9083
|
async function syncLocalRunnerCommand(options, ctx, _registry) {
|
|
9015
|
-
const home =
|
|
9084
|
+
const home = resolveHome3(options, ctx);
|
|
9016
9085
|
const lockPath = stringOption(options["lock-file"]) || syncLocalTriggerLockPath(home);
|
|
9017
9086
|
const statePath = stringOption(options["state-file"]) || syncLocalTriggerStatePath(home);
|
|
9018
9087
|
const state = await readSyncLocalTriggerState(statePath);
|
|
@@ -9072,7 +9141,7 @@ async function backfillCommand(options, ctx, registry) {
|
|
|
9072
9141
|
return importBackfillPlan(plan, options, ctx, reg);
|
|
9073
9142
|
}
|
|
9074
9143
|
async function createBackfillPlanFromOptions(options, ctx, action, registry) {
|
|
9075
|
-
const home =
|
|
9144
|
+
const home = resolveHome3(options, ctx);
|
|
9076
9145
|
const env = ctx.env;
|
|
9077
9146
|
const source = normalizeBackfillSource(stringOption(options.source) || "all");
|
|
9078
9147
|
const sourceDefs = source === "all" ? registry.all().map((a) => ({ id: a.id, label: a.label, paths: a.sourcePaths(home, env) })) : (() => {
|
|
@@ -9141,7 +9210,7 @@ async function createBackfillPlanFromOptions(options, ctx, action, registry) {
|
|
|
9141
9210
|
}
|
|
9142
9211
|
async function createBackfillEventsFromDefs(sourceDefs, options, registry, ctx, overrideFiles) {
|
|
9143
9212
|
const events = [];
|
|
9144
|
-
const home =
|
|
9213
|
+
const home = resolveHome3(options, ctx);
|
|
9145
9214
|
for (const item of sourceDefs) {
|
|
9146
9215
|
const parser = registry.getParser(item.id);
|
|
9147
9216
|
if (!parser) {
|
|
@@ -9191,25 +9260,25 @@ async function createBackfillCandidates(source, options) {
|
|
|
9191
9260
|
}
|
|
9192
9261
|
async function listBackfillSourceFiles(source, options, ctx) {
|
|
9193
9262
|
if (source.id === "opencode") {
|
|
9194
|
-
return opencodeBackfillFiles(stringOption(options["source-root"]),
|
|
9263
|
+
return opencodeBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
9195
9264
|
}
|
|
9196
9265
|
if (source.id === "agy") {
|
|
9197
|
-
return agyBackfillFiles(stringOption(options["source-root"]),
|
|
9266
|
+
return agyBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
9198
9267
|
}
|
|
9199
9268
|
if (source.id === "claude-cowork") {
|
|
9200
|
-
return claudeCoworkBackfillFiles(stringOption(options["source-root"]),
|
|
9269
|
+
return claudeCoworkBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
9201
9270
|
}
|
|
9202
9271
|
if (source.id === "codebuddy") {
|
|
9203
|
-
return codebuddyBackfillFiles(stringOption(options["source-root"]),
|
|
9272
|
+
return codebuddyBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
9204
9273
|
}
|
|
9205
9274
|
if (source.id === "workbuddy") {
|
|
9206
|
-
return workbuddyBackfillFiles(stringOption(options["source-root"]),
|
|
9275
|
+
return workbuddyBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
9207
9276
|
}
|
|
9208
9277
|
if (source.id === "zcode") {
|
|
9209
|
-
return zcodeBackfillFiles(stringOption(options["source-root"]),
|
|
9278
|
+
return zcodeBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
9210
9279
|
}
|
|
9211
9280
|
if (source.id === "copilot") {
|
|
9212
|
-
return copilotBackfillFiles(stringOption(options["source-root"]),
|
|
9281
|
+
return copilotBackfillFiles(stringOption(options["source-root"]), resolveHome3(options, ctx), ctx.env);
|
|
9213
9282
|
}
|
|
9214
9283
|
const roots = stringOption(options["source-root"]) ? [requiredOption(options, "source-root")] : source.paths;
|
|
9215
9284
|
const fileLists = await Promise.all(roots.map((r) => listJsonlFiles(r)));
|
|
@@ -9292,7 +9361,7 @@ function writeBackfillPlan(plan, options, ctx) {
|
|
|
9292
9361
|
async function importBackfillPlan(plan, options, ctx, registry) {
|
|
9293
9362
|
const source = normalizeBackfillSource(stringOption(options.source) || "all");
|
|
9294
9363
|
const supportedSources = new Set(BACKFILL_SOURCE_IDS);
|
|
9295
|
-
const home =
|
|
9364
|
+
const home = resolveHome3(options, ctx);
|
|
9296
9365
|
if (source !== "all" && !supportedSources.has(source)) {
|
|
9297
9366
|
write(ctx.stderr, `Unsupported backfill source: ${source}
|
|
9298
9367
|
`);
|
|
@@ -9361,7 +9430,7 @@ async function purgeForcedSources(sourceDefs, home, remoteKey, options, ctx) {
|
|
|
9361
9430
|
async function collectCanonicalEvents(sourceDefs, registry, incrementalState, options, ctx) {
|
|
9362
9431
|
const selectedFilesBySource = /* @__PURE__ */ new Map();
|
|
9363
9432
|
const canonicalEvents = [];
|
|
9364
|
-
const home =
|
|
9433
|
+
const home = resolveHome3(options, ctx);
|
|
9365
9434
|
for (const item of sourceDefs) {
|
|
9366
9435
|
const parser = registry.getParser(item.id);
|
|
9367
9436
|
if (!parser) {
|
|
@@ -9465,7 +9534,7 @@ async function sendSessionRollupBatch(rollups, options, ctx) {
|
|
|
9465
9534
|
if (!remote) {
|
|
9466
9535
|
throw new Error("No fetch available for HTTP upload");
|
|
9467
9536
|
}
|
|
9468
|
-
const home =
|
|
9537
|
+
const home = resolveHome3(options, ctx);
|
|
9469
9538
|
const cfg = readConfig(home);
|
|
9470
9539
|
const machine = {
|
|
9471
9540
|
id: ensureLocalMachineId(home),
|
|
@@ -9484,7 +9553,7 @@ async function deleteSessionRollupsBySourceAPI(source, options, ctx) {
|
|
|
9484
9553
|
if (!remote) {
|
|
9485
9554
|
throw new Error("No fetch available for HTTP delete");
|
|
9486
9555
|
}
|
|
9487
|
-
const home =
|
|
9556
|
+
const home = resolveHome3(options, ctx);
|
|
9488
9557
|
return deleteRollupsBySource(remote, source, {
|
|
9489
9558
|
id: ensureLocalMachineId(home),
|
|
9490
9559
|
hostname: defaultMachineName(),
|
|
@@ -9528,13 +9597,13 @@ function selectBackfillFilesForImport(files, watermarkTs) {
|
|
|
9528
9597
|
});
|
|
9529
9598
|
}
|
|
9530
9599
|
function backfillIncrementalStatePath(home) {
|
|
9531
|
-
return
|
|
9600
|
+
return path20.join(home, ".vibetime", "backfill-state.json");
|
|
9532
9601
|
}
|
|
9533
9602
|
function syncLocalTriggerStatePath(home) {
|
|
9534
|
-
return
|
|
9603
|
+
return path20.join(home, ".vibetime", "sync-local-trigger.json");
|
|
9535
9604
|
}
|
|
9536
9605
|
function syncLocalTriggerLockPath(home) {
|
|
9537
|
-
return
|
|
9606
|
+
return path20.join(home, ".vibetime", "sync-local-trigger.lock");
|
|
9538
9607
|
}
|
|
9539
9608
|
function backfillRemoteKey(baseUrl) {
|
|
9540
9609
|
try {
|
|
@@ -9596,8 +9665,8 @@ async function readBackfillIncrementalStateFile(home, ctx) {
|
|
|
9596
9665
|
}
|
|
9597
9666
|
async function writeBackfillIncrementalStateFile(home, file) {
|
|
9598
9667
|
const statePath = backfillIncrementalStatePath(home);
|
|
9599
|
-
await
|
|
9600
|
-
await
|
|
9668
|
+
await mkdir5(path20.dirname(statePath), { recursive: true });
|
|
9669
|
+
await writeFile4(statePath, `${JSON.stringify(file, null, 2)}
|
|
9601
9670
|
`, "utf8");
|
|
9602
9671
|
}
|
|
9603
9672
|
async function readBackfillIncrementalState(home, remoteKey, ctx) {
|
|
@@ -9645,9 +9714,9 @@ async function readSyncLocalTriggerState(statePath) {
|
|
|
9645
9714
|
return nextState;
|
|
9646
9715
|
}
|
|
9647
9716
|
async function writeSyncLocalTriggerState(statePath, state) {
|
|
9648
|
-
await
|
|
9649
|
-
const tmpPath = `${statePath}.tmp`;
|
|
9650
|
-
await
|
|
9717
|
+
await mkdir5(path20.dirname(statePath), { recursive: true });
|
|
9718
|
+
const tmpPath = `${statePath}.${process.pid}.${randomUUID2()}.tmp`;
|
|
9719
|
+
await writeFile4(tmpPath, `${JSON.stringify(state, null, 2)}
|
|
9651
9720
|
`, "utf8");
|
|
9652
9721
|
await rename2(tmpPath, statePath);
|
|
9653
9722
|
}
|
|
@@ -9662,8 +9731,8 @@ async function readSyncLocalLock(lockPath) {
|
|
|
9662
9731
|
return { pid: lock.pid, startedAt: lock.startedAt };
|
|
9663
9732
|
}
|
|
9664
9733
|
async function writeSyncLocalLock(lockPath, lock) {
|
|
9665
|
-
await
|
|
9666
|
-
await
|
|
9734
|
+
await mkdir5(path20.dirname(lockPath), { recursive: true });
|
|
9735
|
+
await writeFile4(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
9667
9736
|
`, "utf8");
|
|
9668
9737
|
}
|
|
9669
9738
|
async function clearSyncLocalLock(lockPath) {
|
|
@@ -9701,12 +9770,19 @@ function spawnSyncLocalRunner(input) {
|
|
|
9701
9770
|
const child = input.ctx.spawn(process.execPath, args, {
|
|
9702
9771
|
detached: true,
|
|
9703
9772
|
stdio: "ignore",
|
|
9704
|
-
cwd:
|
|
9705
|
-
env:
|
|
9773
|
+
cwd: resolveSpawnCwd(input.home),
|
|
9774
|
+
env: input.ctx.env
|
|
9706
9775
|
});
|
|
9707
9776
|
child.unref();
|
|
9708
9777
|
return child;
|
|
9709
9778
|
}
|
|
9779
|
+
function resolveSpawnCwd(home) {
|
|
9780
|
+
try {
|
|
9781
|
+
return process.cwd();
|
|
9782
|
+
} catch {
|
|
9783
|
+
return home;
|
|
9784
|
+
}
|
|
9785
|
+
}
|
|
9710
9786
|
function syncLocalRunnerArgs(input) {
|
|
9711
9787
|
const args = syncLocalRunnerEntryArgs(fileURLToPath(import.meta.url));
|
|
9712
9788
|
args.push("sync-local-runner", "--home", input.home, "--lock-file", input.lockPath, "--state-file", input.statePath);
|
|
@@ -9722,10 +9798,10 @@ function syncLocalRunnerEntryArgs(cliPath) {
|
|
|
9722
9798
|
if (cliPath.endsWith(".ts")) {
|
|
9723
9799
|
return ["--import", "tsx", cliPath];
|
|
9724
9800
|
}
|
|
9725
|
-
return [
|
|
9801
|
+
return [path20.resolve(path20.dirname(cliPath), "../bin/vibetime.mjs")];
|
|
9726
9802
|
}
|
|
9727
|
-
function
|
|
9728
|
-
return
|
|
9803
|
+
function resolveHome3(options, ctx) {
|
|
9804
|
+
return path20.resolve(stringOption(options.home) || ctx.env.HOME || os9.homedir());
|
|
9729
9805
|
}
|
|
9730
9806
|
function requestedTargets(options) {
|
|
9731
9807
|
const value = options.target || options.targets;
|
|
@@ -9788,7 +9864,7 @@ function maskToken(token) {
|
|
|
9788
9864
|
}
|
|
9789
9865
|
async function tokenCommand(action, value, options, ctx) {
|
|
9790
9866
|
const verb = action || "show";
|
|
9791
|
-
const home =
|
|
9867
|
+
const home = resolveHome3(options, ctx);
|
|
9792
9868
|
if (verb === "set") {
|
|
9793
9869
|
if (!value || value.trim().length === 0) {
|
|
9794
9870
|
write(ctx.stderr, "Usage: vibetime token set <token> [--remote <url>]\n");
|
|
@@ -9860,7 +9936,7 @@ async function machineCommand(action, options, ctx) {
|
|
|
9860
9936
|
return 0;
|
|
9861
9937
|
}
|
|
9862
9938
|
if (verb === "rename") {
|
|
9863
|
-
const home =
|
|
9939
|
+
const home = resolveHome3(options, ctx);
|
|
9864
9940
|
const id = stringOption(options.id) || ensureLocalMachineId(home);
|
|
9865
9941
|
const name = stringOption(options.name);
|
|
9866
9942
|
if (!name) {
|
package/package.json
CHANGED