replicas-engine 0.1.531 → 0.1.533
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/README.md +2 -2
- package/dist/src/index.js +149 -123
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,8 +66,8 @@ From `monolith/src/lib/sandbox-helpers.ts` + `monolith/src/lib/workspaces.ts`, t
|
|
|
66
66
|
- Git identity (optional but expected for commits):
|
|
67
67
|
- `git config --global user.name <bot-or-user-name>`
|
|
68
68
|
- `git config --global user.email <bot-or-user-email>`
|
|
69
|
-
- Git credential helper setup when
|
|
70
|
-
- `git config --global credential.helper
|
|
69
|
+
- Managed Git credential helper setup when code-host tokens are available:
|
|
70
|
+
- `git config --global credential.helper ~/.git-credential-replicas`
|
|
71
71
|
- `~/.git-credentials` with `https://x-access-token:<token>@github.com`
|
|
72
72
|
- Repository materialization:
|
|
73
73
|
- clone repositories into `/home/ubuntu/workspaces/<repo-name>`
|
package/dist/src/index.js
CHANGED
|
@@ -623,7 +623,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
623
623
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
624
624
|
|
|
625
625
|
// ../shared/src/e2b.ts
|
|
626
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-31-
|
|
626
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-31-v4";
|
|
627
627
|
|
|
628
628
|
// ../shared/src/runtime-env.ts
|
|
629
629
|
function shellQuotePosix(value) {
|
|
@@ -685,6 +685,15 @@ function parsePosixEnvFile(content) {
|
|
|
685
685
|
}
|
|
686
686
|
|
|
687
687
|
// ../shared/src/git.ts
|
|
688
|
+
var GIT_CREDENTIAL_HELPER_FILENAME = ".git-credential-replicas";
|
|
689
|
+
function buildGitCredentialHelperScript(credentialsPath) {
|
|
690
|
+
return `#!/bin/sh
|
|
691
|
+
if [ "$1" = "get" ]; then
|
|
692
|
+
exec git credential-store --file=${shellQuotePosix(credentialsPath)} get
|
|
693
|
+
fi
|
|
694
|
+
exit 0
|
|
695
|
+
`;
|
|
696
|
+
}
|
|
688
697
|
function parseGitRemote(remoteUrl) {
|
|
689
698
|
const normalized = remoteUrl.trim().replace(/\/+$/, "").replace(/\.git$/, "");
|
|
690
699
|
try {
|
|
@@ -3412,7 +3421,12 @@ var workspaceChangedEventSchema = z2.discriminatedUnion("type", [
|
|
|
3412
3421
|
chatId: z2.string(),
|
|
3413
3422
|
ts: z2.string()
|
|
3414
3423
|
}),
|
|
3415
|
-
z2.object({ type: z2.literal("presence.changed"), ts: z2.string() })
|
|
3424
|
+
z2.object({ type: z2.literal("presence.changed"), ts: z2.string() }),
|
|
3425
|
+
z2.object({
|
|
3426
|
+
type: z2.literal("mobile-testing.changed"),
|
|
3427
|
+
workspaceId: z2.string(),
|
|
3428
|
+
ts: z2.string()
|
|
3429
|
+
})
|
|
3416
3430
|
]);
|
|
3417
3431
|
|
|
3418
3432
|
// ../shared/src/routes/presence.ts
|
|
@@ -5211,7 +5225,7 @@ var monolithService = new MonolithService();
|
|
|
5211
5225
|
|
|
5212
5226
|
// src/utils/file.ts
|
|
5213
5227
|
import { mkdir, readFile, rename, unlink, writeFile } from "fs/promises";
|
|
5214
|
-
import { dirname } from "path";
|
|
5228
|
+
import { dirname, join as join3 } from "path";
|
|
5215
5229
|
|
|
5216
5230
|
// src/utils/async-lock.ts
|
|
5217
5231
|
var AsyncLock = class {
|
|
@@ -5243,6 +5257,14 @@ async function writeSecureCredentialFile(filePath, content, options) {
|
|
|
5243
5257
|
}
|
|
5244
5258
|
await atomicWriteFile(filePath, content, { mode: 384 });
|
|
5245
5259
|
}
|
|
5260
|
+
async function configureManagedGitCredentialHelper(homeDir) {
|
|
5261
|
+
const credentialsPath = join3(homeDir, ".git-credentials");
|
|
5262
|
+
const helperPath = join3(homeDir, GIT_CREDENTIAL_HELPER_FILENAME);
|
|
5263
|
+
await atomicWriteFile(helperPath, buildGitCredentialHelperScript(credentialsPath), { mode: 448 });
|
|
5264
|
+
await execFileAsync("git", ["config", "--global", "credential.helper", helperPath], {
|
|
5265
|
+
env: { ...process.env, HOME: homeDir }
|
|
5266
|
+
});
|
|
5267
|
+
}
|
|
5246
5268
|
var credentialFileLock = new AsyncLock();
|
|
5247
5269
|
function upsertCredentialFileLines(filePath, hosts, lines) {
|
|
5248
5270
|
return credentialFileLock.run(async () => {
|
|
@@ -5272,12 +5294,12 @@ function removeCredentialFileLines(filePath, shouldRemove) {
|
|
|
5272
5294
|
// src/git/service.ts
|
|
5273
5295
|
import { readdir, readFile as readFile3, stat } from "fs/promises";
|
|
5274
5296
|
import { spawn } from "child_process";
|
|
5275
|
-
import { join as
|
|
5297
|
+
import { join as join6 } from "path";
|
|
5276
5298
|
|
|
5277
5299
|
// src/utils/state.ts
|
|
5278
5300
|
import { readFile as readFile2, mkdir as mkdir2 } from "fs/promises";
|
|
5279
5301
|
import { existsSync } from "fs";
|
|
5280
|
-
import { join as
|
|
5302
|
+
import { join as join4 } from "path";
|
|
5281
5303
|
import { homedir as homedir3 } from "os";
|
|
5282
5304
|
|
|
5283
5305
|
// src/utils/type-guards.ts
|
|
@@ -5286,8 +5308,8 @@ function isRecord4(value) {
|
|
|
5286
5308
|
}
|
|
5287
5309
|
|
|
5288
5310
|
// src/utils/state.ts
|
|
5289
|
-
var STATE_DIR =
|
|
5290
|
-
var STATE_FILE =
|
|
5311
|
+
var STATE_DIR = join4(homedir3(), ".replicas");
|
|
5312
|
+
var STATE_FILE = join4(STATE_DIR, "engine-state.json");
|
|
5291
5313
|
var DEFAULT_STATE = {
|
|
5292
5314
|
repos: {}
|
|
5293
5315
|
};
|
|
@@ -5385,7 +5407,7 @@ async function saveRepoState(repoName, state, fallbackState) {
|
|
|
5385
5407
|
|
|
5386
5408
|
// src/git/commands.ts
|
|
5387
5409
|
import { readFileSync as readFileSync2 } from "fs";
|
|
5388
|
-
import { join as
|
|
5410
|
+
import { join as join5 } from "path";
|
|
5389
5411
|
async function runGitCommand(args, cwd, options = {}) {
|
|
5390
5412
|
const { stdout } = await execFileAsync("git", args, {
|
|
5391
5413
|
cwd,
|
|
@@ -5396,7 +5418,7 @@ async function runGitCommand(args, cwd, options = {}) {
|
|
|
5396
5418
|
}
|
|
5397
5419
|
function readRepoHeadBranch(repoPath) {
|
|
5398
5420
|
try {
|
|
5399
|
-
const contents = readFileSync2(
|
|
5421
|
+
const contents = readFileSync2(join5(repoPath, ".git", "HEAD"), "utf-8").trim();
|
|
5400
5422
|
const match = contents.match(/^ref:\s+refs\/heads\/(.+)$/);
|
|
5401
5423
|
return match ? match[1] : null;
|
|
5402
5424
|
} catch {
|
|
@@ -5458,13 +5480,13 @@ var GitService = class {
|
|
|
5458
5480
|
const repos = [];
|
|
5459
5481
|
let complete = true;
|
|
5460
5482
|
for (const entry of entries) {
|
|
5461
|
-
const fullPath =
|
|
5483
|
+
const fullPath = join6(root, entry);
|
|
5462
5484
|
try {
|
|
5463
5485
|
const entryStat = await stat(fullPath);
|
|
5464
5486
|
if (!entryStat.isDirectory()) {
|
|
5465
5487
|
continue;
|
|
5466
5488
|
}
|
|
5467
|
-
const hasGit = Boolean(await this.safeStat(
|
|
5489
|
+
const hasGit = Boolean(await this.safeStat(join6(fullPath, ".git")));
|
|
5468
5490
|
if (!hasGit) {
|
|
5469
5491
|
continue;
|
|
5470
5492
|
}
|
|
@@ -5655,7 +5677,7 @@ var GitService = class {
|
|
|
5655
5677
|
let total = 0;
|
|
5656
5678
|
for (const path6 of paths) {
|
|
5657
5679
|
try {
|
|
5658
|
-
const contents = await readFile3(
|
|
5680
|
+
const contents = await readFile3(join6(repoPath, path6));
|
|
5659
5681
|
if (contents.length === 0 || contents.includes(0)) {
|
|
5660
5682
|
continue;
|
|
5661
5683
|
}
|
|
@@ -5838,7 +5860,7 @@ var GitService = class {
|
|
|
5838
5860
|
}
|
|
5839
5861
|
async getGitLabAccessToken(host) {
|
|
5840
5862
|
try {
|
|
5841
|
-
const credentials = await readFile3(
|
|
5863
|
+
const credentials = await readFile3(join6(ENGINE_ENV.HOME_DIR, ".git-credentials"), "utf-8");
|
|
5842
5864
|
for (const line of credentials.split("\n")) {
|
|
5843
5865
|
const trimmed = line.trim();
|
|
5844
5866
|
if (!trimmed) continue;
|
|
@@ -6344,7 +6366,7 @@ var infisicalTokenManager = new InfisicalTokenManager();
|
|
|
6344
6366
|
// src/utils/logger.ts
|
|
6345
6367
|
import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
|
|
6346
6368
|
import { homedir as homedir4 } from "os";
|
|
6347
|
-
import { join as
|
|
6369
|
+
import { join as join7 } from "path";
|
|
6348
6370
|
import { format } from "util";
|
|
6349
6371
|
import { randomBytes } from "crypto";
|
|
6350
6372
|
|
|
@@ -6419,7 +6441,7 @@ var StreamWriter = class {
|
|
|
6419
6441
|
};
|
|
6420
6442
|
|
|
6421
6443
|
// src/utils/logger.ts
|
|
6422
|
-
var LOG_DIR =
|
|
6444
|
+
var LOG_DIR = join7(homedir4(), ".replicas", "logs");
|
|
6423
6445
|
var EngineLogger = class {
|
|
6424
6446
|
_sessionId = null;
|
|
6425
6447
|
patched = false;
|
|
@@ -6430,7 +6452,7 @@ var EngineLogger = class {
|
|
|
6430
6452
|
async initialize() {
|
|
6431
6453
|
await mkdir3(LOG_DIR, { recursive: true });
|
|
6432
6454
|
this._sessionId = this.createSessionId();
|
|
6433
|
-
const logPath =
|
|
6455
|
+
const logPath = join7(LOG_DIR, `${this._sessionId}.log`);
|
|
6434
6456
|
await writeFile2(logPath, `=== Replicas Engine Session ${this._sessionId} ===
|
|
6435
6457
|
`, "utf-8");
|
|
6436
6458
|
this.writer.open(logPath);
|
|
@@ -6477,7 +6499,7 @@ var engineLogger = new EngineLogger();
|
|
|
6477
6499
|
// src/services/replicas-config-service.ts
|
|
6478
6500
|
import { readFile as readFile6, appendFile, writeFile as writeFile4, mkdir as mkdir6 } from "fs/promises";
|
|
6479
6501
|
import { existsSync as existsSync3 } from "fs";
|
|
6480
|
-
import { join as
|
|
6502
|
+
import { join as join11 } from "path";
|
|
6481
6503
|
import { homedir as homedir8 } from "os";
|
|
6482
6504
|
import { spawn as spawn2 } from "child_process";
|
|
6483
6505
|
|
|
@@ -6485,21 +6507,21 @@ import { spawn as spawn2 } from "child_process";
|
|
|
6485
6507
|
import { mkdir as mkdir4, readFile as readFile4 } from "fs/promises";
|
|
6486
6508
|
import { existsSync as existsSync2 } from "fs";
|
|
6487
6509
|
import { homedir as homedir6 } from "os";
|
|
6488
|
-
import { join as
|
|
6510
|
+
import { join as join9 } from "path";
|
|
6489
6511
|
|
|
6490
6512
|
// src/managers/agent-auth-paths.ts
|
|
6491
6513
|
import { homedir as homedir5 } from "os";
|
|
6492
|
-
import { join as
|
|
6493
|
-
var OPENCODE_AUTH_PATH =
|
|
6494
|
-
var PI_AUTH_PATH =
|
|
6514
|
+
import { join as join8 } from "path";
|
|
6515
|
+
var OPENCODE_AUTH_PATH = join8(homedir5(), ".local", "share", "opencode", "auth.json");
|
|
6516
|
+
var PI_AUTH_PATH = join8(homedir5(), ".pi", "agent", "auth.json");
|
|
6495
6517
|
|
|
6496
6518
|
// src/services/environment-details-service.ts
|
|
6497
|
-
var REPLICAS_DIR =
|
|
6498
|
-
var DETAILS_FILE =
|
|
6499
|
-
var CLAUDE_CREDENTIALS_PATH =
|
|
6500
|
-
var CODEX_AUTH_PATH =
|
|
6501
|
-
var GH_HOSTS_PATH =
|
|
6502
|
-
var GIT_CREDENTIALS_PATH =
|
|
6519
|
+
var REPLICAS_DIR = join9(homedir6(), ".replicas");
|
|
6520
|
+
var DETAILS_FILE = join9(REPLICAS_DIR, "environment-details.json");
|
|
6521
|
+
var CLAUDE_CREDENTIALS_PATH = join9(homedir6(), ".claude", ".credentials.json");
|
|
6522
|
+
var CODEX_AUTH_PATH = join9(homedir6(), ".codex", "auth.json");
|
|
6523
|
+
var GH_HOSTS_PATH = join9(homedir6(), ".config", "gh", "hosts.yml");
|
|
6524
|
+
var GIT_CREDENTIALS_PATH = join9(homedir6(), ".git-credentials");
|
|
6503
6525
|
function detectClaudeAuthMethod() {
|
|
6504
6526
|
if (existsSync2(CLAUDE_CREDENTIALS_PATH)) {
|
|
6505
6527
|
return "oauth";
|
|
@@ -6706,7 +6728,7 @@ var environmentDetailsService = new EnvironmentDetailsService();
|
|
|
6706
6728
|
// src/services/start-hook-logs-service.ts
|
|
6707
6729
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile3, readdir as readdir2 } from "fs/promises";
|
|
6708
6730
|
import { homedir as homedir7 } from "os";
|
|
6709
|
-
import { join as
|
|
6731
|
+
import { join as join10 } from "path";
|
|
6710
6732
|
|
|
6711
6733
|
// src/services/hook-log-files.ts
|
|
6712
6734
|
import { createHash } from "crypto";
|
|
@@ -6718,7 +6740,7 @@ function repoHookLogFilename(repoName) {
|
|
|
6718
6740
|
}
|
|
6719
6741
|
|
|
6720
6742
|
// src/services/start-hook-logs-service.ts
|
|
6721
|
-
var LOGS_DIR =
|
|
6743
|
+
var LOGS_DIR = join10(homedir7(), ".replicas", "start-hook-logs");
|
|
6722
6744
|
function withPreview(stored) {
|
|
6723
6745
|
const preview = buildHookOutputPreview(stored.output);
|
|
6724
6746
|
return { ...stored, ...preview };
|
|
@@ -6756,7 +6778,7 @@ var StartHookLogsService = class {
|
|
|
6756
6778
|
await this.ensureDir();
|
|
6757
6779
|
const log = { hookType, hookName, repoName: hookName, ...entry };
|
|
6758
6780
|
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
6759
|
-
await writeFile3(
|
|
6781
|
+
await writeFile3(join10(LOGS_DIR, filename), `${JSON.stringify(log, null, 2)}
|
|
6760
6782
|
`, "utf-8");
|
|
6761
6783
|
}
|
|
6762
6784
|
async saveEnvironmentLog(entry) {
|
|
@@ -6781,7 +6803,7 @@ var StartHookLogsService = class {
|
|
|
6781
6803
|
continue;
|
|
6782
6804
|
}
|
|
6783
6805
|
try {
|
|
6784
|
-
const raw = await readFile5(
|
|
6806
|
+
const raw = await readFile5(join10(LOGS_DIR, file), "utf-8");
|
|
6785
6807
|
const stored = normalizeStored(JSON.parse(raw));
|
|
6786
6808
|
if (stored) {
|
|
6787
6809
|
logs.push(withPreview(stored));
|
|
@@ -6800,7 +6822,7 @@ var StartHookLogsService = class {
|
|
|
6800
6822
|
async getFullOutput(hookType, hookName) {
|
|
6801
6823
|
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
6802
6824
|
try {
|
|
6803
|
-
const raw = await readFile5(
|
|
6825
|
+
const raw = await readFile5(join10(LOGS_DIR, filename), "utf-8");
|
|
6804
6826
|
const stored = normalizeStored(JSON.parse(raw));
|
|
6805
6827
|
if (!stored || stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
6806
6828
|
return null;
|
|
@@ -6817,7 +6839,7 @@ var StartHookLogsService = class {
|
|
|
6817
6839
|
var startHookLogsService = new StartHookLogsService();
|
|
6818
6840
|
|
|
6819
6841
|
// src/services/replicas-config-service.ts
|
|
6820
|
-
var START_HOOKS_LOG =
|
|
6842
|
+
var START_HOOKS_LOG = join11(homedir8(), ".replicas", "startHooks.log");
|
|
6821
6843
|
var START_HOOKS_RUNNING_PROMPT = `IMPORTANT - Start Hooks Running:
|
|
6822
6844
|
Start hooks are shell commands/scripts set by repository owners that run on workspace startup.
|
|
6823
6845
|
These hooks are currently executing in the background. You can:
|
|
@@ -6828,7 +6850,7 @@ The start hooks may install dependencies, build projects, or perform other setup
|
|
|
6828
6850
|
If your task depends on setup being complete, check the log file before proceeding.`;
|
|
6829
6851
|
async function readReplicasConfigFromDir(dirPath) {
|
|
6830
6852
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
6831
|
-
const configPath =
|
|
6853
|
+
const configPath = join11(dirPath, filename);
|
|
6832
6854
|
if (!existsSync3(configPath)) {
|
|
6833
6855
|
continue;
|
|
6834
6856
|
}
|
|
@@ -6898,7 +6920,7 @@ var ReplicasConfigService = class {
|
|
|
6898
6920
|
const logLine = `[${timestamp}] ${message}
|
|
6899
6921
|
`;
|
|
6900
6922
|
try {
|
|
6901
|
-
await mkdir6(
|
|
6923
|
+
await mkdir6(join11(homedir8(), ".replicas"), { recursive: true });
|
|
6902
6924
|
await appendFile(START_HOOKS_LOG, logLine, "utf-8");
|
|
6903
6925
|
} catch (error) {
|
|
6904
6926
|
console.error("Failed to write to start hooks log:", error);
|
|
@@ -7033,7 +7055,7 @@ var ReplicasConfigService = class {
|
|
|
7033
7055
|
this.hooksCompleted = false;
|
|
7034
7056
|
this.hooksFailed = false;
|
|
7035
7057
|
try {
|
|
7036
|
-
await mkdir6(
|
|
7058
|
+
await mkdir6(join11(homedir8(), ".replicas"), { recursive: true });
|
|
7037
7059
|
await writeFile4(
|
|
7038
7060
|
START_HOOKS_LOG,
|
|
7039
7061
|
`=== Start Hooks Execution Log ===
|
|
@@ -7229,10 +7251,10 @@ var replicasConfigService = new ReplicasConfigService();
|
|
|
7229
7251
|
// src/services/event-service.ts
|
|
7230
7252
|
import { mkdir as mkdir7 } from "fs/promises";
|
|
7231
7253
|
import { homedir as homedir9 } from "os";
|
|
7232
|
-
import { join as
|
|
7254
|
+
import { join as join12 } from "path";
|
|
7233
7255
|
import { randomUUID } from "crypto";
|
|
7234
|
-
var ENGINE_DIR =
|
|
7235
|
-
var EVENTS_FILE =
|
|
7256
|
+
var ENGINE_DIR = join12(homedir9(), ".replicas", "engine");
|
|
7257
|
+
var EVENTS_FILE = join12(ENGINE_DIR, "events.jsonl");
|
|
7236
7258
|
var EventService = class {
|
|
7237
7259
|
subscribers = /* @__PURE__ */ new Map();
|
|
7238
7260
|
writer = new StreamWriter();
|
|
@@ -7267,8 +7289,8 @@ import { mkdir as mkdir8, readFile as readFile7 } from "fs/promises";
|
|
|
7267
7289
|
import { existsSync as existsSync4 } from "fs";
|
|
7268
7290
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
7269
7291
|
import { homedir as homedir10 } from "os";
|
|
7270
|
-
import { dirname as dirname2, join as
|
|
7271
|
-
var PREVIEW_PORTS_FILE =
|
|
7292
|
+
import { dirname as dirname2, join as join13 } from "path";
|
|
7293
|
+
var PREVIEW_PORTS_FILE = join13(homedir10(), ".replicas", "preview-ports.json");
|
|
7272
7294
|
async function readPreviewsFile() {
|
|
7273
7295
|
try {
|
|
7274
7296
|
if (!existsSync4(PREVIEW_PORTS_FILE)) {
|
|
@@ -7381,7 +7403,7 @@ async function registerDesktopPreview() {
|
|
|
7381
7403
|
import { existsSync as existsSync7 } from "fs";
|
|
7382
7404
|
import { appendFile as appendFile3, copyFile, mkdir as mkdir14, readFile as readFile14, rename as rename2, rm as rm2 } from "fs/promises";
|
|
7383
7405
|
import { homedir as homedir15 } from "os";
|
|
7384
|
-
import { join as
|
|
7406
|
+
import { join as join26 } from "path";
|
|
7385
7407
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
7386
7408
|
|
|
7387
7409
|
// src/managers/claude-manager.ts
|
|
@@ -7389,7 +7411,7 @@ import {
|
|
|
7389
7411
|
query
|
|
7390
7412
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
7391
7413
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
7392
|
-
import { dirname as dirname4, join as
|
|
7414
|
+
import { dirname as dirname4, join as join16 } from "path";
|
|
7393
7415
|
import { mkdir as mkdir10 } from "fs/promises";
|
|
7394
7416
|
import { homedir as homedir12 } from "os";
|
|
7395
7417
|
|
|
@@ -7778,7 +7800,7 @@ function extractPlanFromCodexAspNotification(notification) {
|
|
|
7778
7800
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
7779
7801
|
import { mkdir as mkdir9, unlink as unlink2, writeFile as writeFile5 } from "fs/promises";
|
|
7780
7802
|
import { homedir as homedir11 } from "os";
|
|
7781
|
-
import { join as
|
|
7803
|
+
import { join as join14 } from "path";
|
|
7782
7804
|
function isImageMediaType(value) {
|
|
7783
7805
|
return IMAGE_MEDIA_TYPES.includes(value);
|
|
7784
7806
|
}
|
|
@@ -7878,14 +7900,14 @@ async function normalizeImages(images) {
|
|
|
7878
7900
|
}
|
|
7879
7901
|
return normalized;
|
|
7880
7902
|
}
|
|
7881
|
-
async function saveNormalizedImagesToTempFiles(images, tempImageDir =
|
|
7903
|
+
async function saveNormalizedImagesToTempFiles(images, tempImageDir = join14(homedir11(), ".replicas", "codex", "temp-images")) {
|
|
7882
7904
|
await mkdir9(tempImageDir, { recursive: true });
|
|
7883
7905
|
const tempPaths = [];
|
|
7884
7906
|
try {
|
|
7885
7907
|
for (const image of images) {
|
|
7886
7908
|
const ext = image.source.media_type.split("/")[1] || "png";
|
|
7887
7909
|
const filename = `img_${randomUUID3()}.${ext}`;
|
|
7888
|
-
const filepath =
|
|
7910
|
+
const filepath = join14(tempImageDir, filename);
|
|
7889
7911
|
await writeFile5(filepath, Buffer.from(image.source.data, "base64"));
|
|
7890
7912
|
tempPaths.push(filepath);
|
|
7891
7913
|
}
|
|
@@ -8470,7 +8492,7 @@ function reportCommandProtectionBlock(options) {
|
|
|
8470
8492
|
|
|
8471
8493
|
// src/services/skill-registry-service.ts
|
|
8472
8494
|
import { readFile as readFile8, readdir as readdir3, stat as stat2 } from "fs/promises";
|
|
8473
|
-
import { dirname as dirname3, isAbsolute, join as
|
|
8495
|
+
import { dirname as dirname3, isAbsolute, join as join15, relative, resolve } from "path";
|
|
8474
8496
|
var REGISTRY_ROOT_DIR = ".replicas/skill-registries";
|
|
8475
8497
|
var REGISTRY_MANIFEST = "manifest.json";
|
|
8476
8498
|
async function getSkillRegistryInventory(homeDir) {
|
|
@@ -8531,10 +8553,10 @@ async function scanRegistry(registryDir) {
|
|
|
8531
8553
|
}
|
|
8532
8554
|
async function findSkillCollections(registryDir) {
|
|
8533
8555
|
const candidateRoots = [
|
|
8534
|
-
{ source: "skills", root:
|
|
8535
|
-
{ source: "agents", root:
|
|
8536
|
-
{ source: "codex", root:
|
|
8537
|
-
{ source: "claude", root:
|
|
8556
|
+
{ source: "skills", root: join15(registryDir, "skills") },
|
|
8557
|
+
{ source: "agents", root: join15(registryDir, ".agents", "skills") },
|
|
8558
|
+
{ source: "codex", root: join15(registryDir, ".codex", "skills") },
|
|
8559
|
+
{ source: "claude", root: join15(registryDir, ".claude", "skills") }
|
|
8538
8560
|
];
|
|
8539
8561
|
const collections = [];
|
|
8540
8562
|
for (const { source, root } of candidateRoots) {
|
|
@@ -8548,9 +8570,9 @@ async function findSkillCollections(registryDir) {
|
|
|
8548
8570
|
async function findSkillDirsInRoot(root) {
|
|
8549
8571
|
const skillDirs = [];
|
|
8550
8572
|
for (const dirent of await safeReadDir(root)) {
|
|
8551
|
-
const skillDir =
|
|
8573
|
+
const skillDir = join15(root, dirent.name);
|
|
8552
8574
|
if (!await isDirectoryDirent(dirent, skillDir)) continue;
|
|
8553
|
-
if (await fileExists(
|
|
8575
|
+
if (await fileExists(join15(skillDir, "SKILL.md"))) {
|
|
8554
8576
|
skillDirs.push(skillDir);
|
|
8555
8577
|
}
|
|
8556
8578
|
}
|
|
@@ -8560,9 +8582,9 @@ async function findTopLevelSkills(registryDir) {
|
|
|
8560
8582
|
const skills = [];
|
|
8561
8583
|
for (const dirent of await safeReadDir(registryDir)) {
|
|
8562
8584
|
if (dirent.name.startsWith(".") || dirent.name === "skills" || dirent.name === "plugins") continue;
|
|
8563
|
-
const skillDir =
|
|
8585
|
+
const skillDir = join15(registryDir, dirent.name);
|
|
8564
8586
|
if (!await isDirectoryDirent(dirent, skillDir)) continue;
|
|
8565
|
-
if (await fileExists(
|
|
8587
|
+
if (await fileExists(join15(skillDir, "SKILL.md"))) {
|
|
8566
8588
|
skills.push({ source: "root", skillDir });
|
|
8567
8589
|
}
|
|
8568
8590
|
}
|
|
@@ -8573,10 +8595,10 @@ async function findClaudePluginRoots(registryDir) {
|
|
|
8573
8595
|
async function walk(dir) {
|
|
8574
8596
|
for (const dirent of await safeReadDir(dir)) {
|
|
8575
8597
|
if (dirent.name === ".git") continue;
|
|
8576
|
-
const child =
|
|
8598
|
+
const child = join15(dir, dirent.name);
|
|
8577
8599
|
if (!await isDirectoryDirent(dirent, child)) continue;
|
|
8578
8600
|
if (dirent.name === ".claude-plugin") {
|
|
8579
|
-
if (await fileExists(
|
|
8601
|
+
if (await fileExists(join15(child, "plugin.json"))) {
|
|
8580
8602
|
roots.push(dirname3(child));
|
|
8581
8603
|
}
|
|
8582
8604
|
continue;
|
|
@@ -8588,7 +8610,7 @@ async function findClaudePluginRoots(registryDir) {
|
|
|
8588
8610
|
return uniqueStrings(roots);
|
|
8589
8611
|
}
|
|
8590
8612
|
async function hasCodexMarketplace(registryDir) {
|
|
8591
|
-
return await fileExists(
|
|
8613
|
+
return await fileExists(join15(registryDir, ".agents", "plugins", "marketplace.json")) || await fileExists(join15(registryDir, ".codex", "plugins", "marketplace.json"));
|
|
8592
8614
|
}
|
|
8593
8615
|
async function installCodexRegistryPlugins(client, inventory) {
|
|
8594
8616
|
const cwds = inventory.codexMarketplaceCwds;
|
|
@@ -8638,10 +8660,10 @@ function isSkillRegistryEntry(value) {
|
|
|
8638
8660
|
return "index" in value && typeof value.index === "number" && "name" in value && typeof value.name === "string" && "url" in value && typeof value.url === "string" && "checkoutPath" in value && typeof value.checkoutPath === "string";
|
|
8639
8661
|
}
|
|
8640
8662
|
function getRegistryRoot(homeDir) {
|
|
8641
|
-
return
|
|
8663
|
+
return join15(homeDir, REGISTRY_ROOT_DIR);
|
|
8642
8664
|
}
|
|
8643
8665
|
function getManifestPath(homeDir) {
|
|
8644
|
-
return
|
|
8666
|
+
return join15(getRegistryRoot(homeDir), REGISTRY_MANIFEST);
|
|
8645
8667
|
}
|
|
8646
8668
|
function emptyInventory(registryRoot) {
|
|
8647
8669
|
return {
|
|
@@ -8989,7 +9011,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
8989
9011
|
authRetrying = false;
|
|
8990
9012
|
constructor(options) {
|
|
8991
9013
|
super(options);
|
|
8992
|
-
this.historyFilePath = options.historyFilePath ??
|
|
9014
|
+
this.historyFilePath = options.historyFilePath ?? join16(homedir12(), ".replicas", "claude", "history.jsonl");
|
|
8993
9015
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
8994
9016
|
this.systemPromptOverride = options.systemPromptOverride;
|
|
8995
9017
|
this.toolsOverride = options.tools;
|
|
@@ -9939,7 +9961,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
9939
9961
|
|
|
9940
9962
|
// src/managers/codex-asp/codex-asp-manager.ts
|
|
9941
9963
|
import { readdir as readdir4 } from "fs/promises";
|
|
9942
|
-
import { join as
|
|
9964
|
+
import { join as join18 } from "path";
|
|
9943
9965
|
|
|
9944
9966
|
// src/managers/codex-asp/app-server-process.ts
|
|
9945
9967
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -10140,7 +10162,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
|
10140
10162
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
10141
10163
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
10142
10164
|
var codexCliVersionEnsured = null;
|
|
10143
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
10165
|
+
var ENGINE_PACKAGE_VERSION = "0.1.533";
|
|
10144
10166
|
var INITIALIZE_METHOD = "initialize";
|
|
10145
10167
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
10146
10168
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -11064,15 +11086,15 @@ var TranscriptUpdateCoalescer = class {
|
|
|
11064
11086
|
|
|
11065
11087
|
// src/services/chat/history-paths.ts
|
|
11066
11088
|
import { homedir as homedir13 } from "os";
|
|
11067
|
-
import { join as
|
|
11068
|
-
var ENGINE_DIR2 =
|
|
11069
|
-
var CHATS_FILE =
|
|
11070
|
-
var CLAUDE_HISTORY_DIR =
|
|
11071
|
-
var RELAY_HISTORY_DIR =
|
|
11072
|
-
var CODEX_HISTORY_DIR =
|
|
11073
|
-
var CURSOR_HISTORY_DIR =
|
|
11074
|
-
var OPENCODE_HISTORY_DIR =
|
|
11075
|
-
var PI_HISTORY_DIR =
|
|
11089
|
+
import { join as join17 } from "path";
|
|
11090
|
+
var ENGINE_DIR2 = join17(homedir13(), ".replicas", "engine");
|
|
11091
|
+
var CHATS_FILE = join17(ENGINE_DIR2, "chats.json");
|
|
11092
|
+
var CLAUDE_HISTORY_DIR = join17(ENGINE_DIR2, "claude-histories");
|
|
11093
|
+
var RELAY_HISTORY_DIR = join17(ENGINE_DIR2, "relay-histories");
|
|
11094
|
+
var CODEX_HISTORY_DIR = join17(ENGINE_DIR2, "codex-histories");
|
|
11095
|
+
var CURSOR_HISTORY_DIR = join17(ENGINE_DIR2, "cursor-histories");
|
|
11096
|
+
var OPENCODE_HISTORY_DIR = join17(ENGINE_DIR2, "opencode-histories");
|
|
11097
|
+
var PI_HISTORY_DIR = join17(ENGINE_DIR2, "pi-histories");
|
|
11076
11098
|
var HISTORY_DIR_BY_PROVIDER = {
|
|
11077
11099
|
claude: CLAUDE_HISTORY_DIR,
|
|
11078
11100
|
relay: RELAY_HISTORY_DIR,
|
|
@@ -11118,7 +11140,7 @@ async function readCodexAspThreadHistory(threadId) {
|
|
|
11118
11140
|
}
|
|
11119
11141
|
for (const entry of entries) {
|
|
11120
11142
|
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
11121
|
-
const history = await new CodexHistoryFile(
|
|
11143
|
+
const history = await new CodexHistoryFile(join18(CODEX_HISTORY_DIR, entry.name)).load();
|
|
11122
11144
|
const transcript = history.transcriptsByThreadId.get(threadId);
|
|
11123
11145
|
if (transcript) {
|
|
11124
11146
|
return {
|
|
@@ -12345,7 +12367,7 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12345
12367
|
|
|
12346
12368
|
// src/managers/cursor-manager.ts
|
|
12347
12369
|
import { mkdir as mkdir11, readFile as readFile10, readdir as readdir5 } from "fs/promises";
|
|
12348
|
-
import { basename, dirname as dirname5, extname, join as
|
|
12370
|
+
import { basename, dirname as dirname5, extname, join as join19 } from "path";
|
|
12349
12371
|
import { parse as parseYaml2 } from "yaml";
|
|
12350
12372
|
import { Agent as CursorAgent } from "@cursor/sdk";
|
|
12351
12373
|
var CURSOR_SLASH_COMMANDS_CACHE_MS = 3e4;
|
|
@@ -12404,7 +12426,7 @@ async function listCursorCommandsInDirectory(directory) {
|
|
|
12404
12426
|
const name = basename(entry.name, ".md");
|
|
12405
12427
|
let description;
|
|
12406
12428
|
try {
|
|
12407
|
-
description = extractCursorCommandDescription(await readFile10(
|
|
12429
|
+
description = extractCursorCommandDescription(await readFile10(join19(directory, entry.name), "utf8"));
|
|
12408
12430
|
} catch (error) {
|
|
12409
12431
|
console.warn("[CursorManager] Failed to read slash command file:", error);
|
|
12410
12432
|
}
|
|
@@ -12426,7 +12448,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12426
12448
|
slashCommandsRequest = null;
|
|
12427
12449
|
constructor(options) {
|
|
12428
12450
|
super(options);
|
|
12429
|
-
this.historyFilePath = options.historyFilePath ??
|
|
12451
|
+
this.historyFilePath = options.historyFilePath ?? join19(ENGINE_ENV.HOME_DIR, ".replicas", "cursor", "history.jsonl");
|
|
12430
12452
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
12431
12453
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
12432
12454
|
}
|
|
@@ -12477,7 +12499,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12477
12499
|
this.slashCommandsRequest ??= (async () => {
|
|
12478
12500
|
try {
|
|
12479
12501
|
const repoDirectories = await getAgentAdditionalDirectories();
|
|
12480
|
-
const commandDirectories = [this.workingDirectory, ...repoDirectories, ENGINE_ENV.HOME_DIR].map((directory) =>
|
|
12502
|
+
const commandDirectories = [this.workingDirectory, ...repoDirectories, ENGINE_ENV.HOME_DIR].map((directory) => join19(directory, ".cursor", "commands"));
|
|
12481
12503
|
const commands = mergeSlashCommands(
|
|
12482
12504
|
...await Promise.all(commandDirectories.map(listCursorCommandsInDirectory))
|
|
12483
12505
|
);
|
|
@@ -12737,7 +12759,7 @@ ${request.message}` : request.message;
|
|
|
12737
12759
|
// src/managers/opencode-manager.ts
|
|
12738
12760
|
import { existsSync as existsSync6 } from "fs";
|
|
12739
12761
|
import { mkdir as mkdir12, readFile as readFile11 } from "fs/promises";
|
|
12740
|
-
import { delimiter, dirname as dirname6, join as
|
|
12762
|
+
import { delimiter, dirname as dirname6, join as join20 } from "path";
|
|
12741
12763
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
12742
12764
|
import { fileURLToPath } from "url";
|
|
12743
12765
|
import { Agent } from "undici";
|
|
@@ -12765,7 +12787,7 @@ import {
|
|
|
12765
12787
|
createOpencodeServer
|
|
12766
12788
|
} from "@opencode-ai/sdk/v2";
|
|
12767
12789
|
var OPENCODE_SHIM_DIR = dirname6(fileURLToPath(new URL("../../scripts/opencode", import.meta.url)));
|
|
12768
|
-
var OPENCODE_CONFIG_PATH =
|
|
12790
|
+
var OPENCODE_CONFIG_PATH = join20(ENGINE_ENV.HOME_DIR, ".config", "opencode", "opencode.json");
|
|
12769
12791
|
var OPENCODE_FETCH_DISPATCHER = new Agent({ headersTimeout: 0, bodyTimeout: 0 });
|
|
12770
12792
|
var OPENCODE_SERVER_STARTUP_TIMEOUT_MS = 3e4;
|
|
12771
12793
|
var OPENCODE_WORKSPACE_PERMISSION = {
|
|
@@ -13013,7 +13035,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
13013
13035
|
constructor(options) {
|
|
13014
13036
|
super(options);
|
|
13015
13037
|
this.sessionId = options.initialSessionId;
|
|
13016
|
-
this.historyFilePath = options.historyFilePath ??
|
|
13038
|
+
this.historyFilePath = options.historyFilePath ?? join20(ENGINE_ENV.HOME_DIR, ".replicas", "opencode", "history.jsonl");
|
|
13017
13039
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
13018
13040
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
13019
13041
|
}
|
|
@@ -13512,7 +13534,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
13512
13534
|
|
|
13513
13535
|
// src/managers/pi-manager.ts
|
|
13514
13536
|
import { mkdir as mkdir13 } from "fs/promises";
|
|
13515
|
-
import { dirname as dirname7, join as
|
|
13537
|
+
import { dirname as dirname7, join as join21 } from "path";
|
|
13516
13538
|
import {
|
|
13517
13539
|
AuthStorage,
|
|
13518
13540
|
createAgentSession,
|
|
@@ -13553,7 +13575,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13553
13575
|
providerId = "openrouter";
|
|
13554
13576
|
constructor(options) {
|
|
13555
13577
|
super(options);
|
|
13556
|
-
this.historyFilePath = options.historyFilePath ??
|
|
13578
|
+
this.historyFilePath = options.historyFilePath ?? join21(PI_HISTORY_DIR, `${Date.now()}.jsonl`);
|
|
13557
13579
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
13558
13580
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
13559
13581
|
}
|
|
@@ -13659,7 +13681,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13659
13681
|
const sessionManager = this.initialSessionId ? SessionManager.open(this.initialSessionId, PI_HISTORY_DIR, this.workingDirectory) : SessionManager.create(this.workingDirectory, PI_HISTORY_DIR);
|
|
13660
13682
|
const resourceLoader = new DefaultResourceLoader({
|
|
13661
13683
|
cwd: this.workingDirectory,
|
|
13662
|
-
agentDir:
|
|
13684
|
+
agentDir: join21(ENGINE_ENV.HOME_DIR, ".pi", "agent"),
|
|
13663
13685
|
extensionFactories: [registerCommandProtection(this.workingDirectory)],
|
|
13664
13686
|
appendSystemPrompt: [this.buildCombinedInstructions() ?? ""]
|
|
13665
13687
|
});
|
|
@@ -14372,17 +14394,17 @@ var keepAliveService = new KeepAliveService();
|
|
|
14372
14394
|
// src/services/canvas-service.ts
|
|
14373
14395
|
import { readdir as readdir6, readFile as readFile12, stat as stat3 } from "fs/promises";
|
|
14374
14396
|
import { homedir as homedir14 } from "os";
|
|
14375
|
-
import { join as
|
|
14397
|
+
import { join as join22 } from "path";
|
|
14376
14398
|
var GLOBAL_CANVAS_DIRECTORIES = [
|
|
14377
|
-
|
|
14378
|
-
|
|
14379
|
-
|
|
14399
|
+
join22(homedir14(), ".claude", "plans"),
|
|
14400
|
+
join22(process.env.XDG_DATA_HOME ?? join22(homedir14(), ".local", "share"), "opencode", "plans"),
|
|
14401
|
+
join22(homedir14(), ".replicas", "canvas")
|
|
14380
14402
|
];
|
|
14381
14403
|
async function canvasDirectories() {
|
|
14382
14404
|
const repositories = await gitService.listRepositories().catch(() => []);
|
|
14383
14405
|
return [
|
|
14384
14406
|
...GLOBAL_CANVAS_DIRECTORIES,
|
|
14385
|
-
...repositories.map((repository) =>
|
|
14407
|
+
...repositories.map((repository) => join22(repository.path, ".opencode", "plans"))
|
|
14386
14408
|
];
|
|
14387
14409
|
}
|
|
14388
14410
|
var CanvasService = class {
|
|
@@ -14402,7 +14424,7 @@ var CanvasService = class {
|
|
|
14402
14424
|
const { kind } = classifyCanvasFilename(entry.name);
|
|
14403
14425
|
let sizeBytes = 0;
|
|
14404
14426
|
try {
|
|
14405
|
-
const s = await stat3(
|
|
14427
|
+
const s = await stat3(join22(directory, entry.name));
|
|
14406
14428
|
sizeBytes = s.size;
|
|
14407
14429
|
} catch {
|
|
14408
14430
|
continue;
|
|
@@ -14417,7 +14439,7 @@ var CanvasService = class {
|
|
|
14417
14439
|
if (!safe) return null;
|
|
14418
14440
|
const { kind, mimeType } = classifyCanvasFilename(safe);
|
|
14419
14441
|
for (const directory of await canvasDirectories()) {
|
|
14420
|
-
const filePath =
|
|
14442
|
+
const filePath = join22(directory, safe);
|
|
14421
14443
|
let sizeBytes = 0;
|
|
14422
14444
|
let updatedAt = "";
|
|
14423
14445
|
try {
|
|
@@ -14557,13 +14579,13 @@ import { createReadStream } from "fs";
|
|
|
14557
14579
|
import { readdir as readdir7, readFile as readFile13, stat as stat4 } from "fs/promises";
|
|
14558
14580
|
import { request as httpRequest } from "http";
|
|
14559
14581
|
import { request as httpsRequest } from "https";
|
|
14560
|
-
import { basename as basename2, join as
|
|
14582
|
+
import { basename as basename2, join as join24 } from "path";
|
|
14561
14583
|
|
|
14562
14584
|
// src/services/chat/chat-senders.ts
|
|
14563
|
-
import { join as
|
|
14564
|
-
var CHAT_SENDERS_DIR =
|
|
14585
|
+
import { join as join23 } from "path";
|
|
14586
|
+
var CHAT_SENDERS_DIR = join23(ENGINE_DIR2, "chat-senders");
|
|
14565
14587
|
function chatMessageSendersFilePath(chatId) {
|
|
14566
|
-
return
|
|
14588
|
+
return join23(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
|
|
14567
14589
|
}
|
|
14568
14590
|
function parseChatMessageSendersJsonl(content) {
|
|
14569
14591
|
return content.split("\n").flatMap((line) => {
|
|
@@ -14579,9 +14601,9 @@ function parseChatMessageSendersJsonl(content) {
|
|
|
14579
14601
|
|
|
14580
14602
|
// src/services/upload-chat-transcripts.ts
|
|
14581
14603
|
var HISTORY_DIRS = [
|
|
14582
|
-
|
|
14583
|
-
|
|
14584
|
-
|
|
14604
|
+
join24(ENGINE_DIR2, "claude-histories"),
|
|
14605
|
+
join24(ENGINE_DIR2, "relay-histories"),
|
|
14606
|
+
join24(ENGINE_DIR2, "codex-histories")
|
|
14585
14607
|
];
|
|
14586
14608
|
async function putTranscript(uploadUrl, filePath, size) {
|
|
14587
14609
|
await new Promise((resolve4, reject) => {
|
|
@@ -14626,7 +14648,7 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
|
14626
14648
|
if (!entry.endsWith(".jsonl")) continue;
|
|
14627
14649
|
const chatId = basename2(entry, ".jsonl");
|
|
14628
14650
|
tasks.push(
|
|
14629
|
-
uploadChatTranscript(chatId,
|
|
14651
|
+
uploadChatTranscript(chatId, join24(dir, entry), chatsById.get(chatId)).then(() => {
|
|
14630
14652
|
flushed++;
|
|
14631
14653
|
}).catch((err) => {
|
|
14632
14654
|
failed++;
|
|
@@ -14713,7 +14735,7 @@ async function flushRepoState() {
|
|
|
14713
14735
|
// src/services/upload-engine-logs.ts
|
|
14714
14736
|
import { createReadStream as createReadStream2 } from "fs";
|
|
14715
14737
|
import { readdir as readdir8, stat as stat5 } from "fs/promises";
|
|
14716
|
-
import { join as
|
|
14738
|
+
import { join as join25 } from "path";
|
|
14717
14739
|
var MAX_ENGINE_LOG_FLUSH_SESSIONS = 10;
|
|
14718
14740
|
var MAX_ENGINE_LOG_FLUSH_BYTES = 5 * 1024 * 1024;
|
|
14719
14741
|
var ENGINE_LOG_FLUSH_TIMEOUT_MS = 2e4;
|
|
@@ -14742,7 +14764,7 @@ async function flushAllEngineLogs() {
|
|
|
14742
14764
|
const candidates = (await Promise.all(filenames.slice(0, MAX_ENGINE_LOG_FLUSH_SESSIONS).map(async (filename) => {
|
|
14743
14765
|
try {
|
|
14744
14766
|
const sessionId = filename.slice(0, -".log".length);
|
|
14745
|
-
const filePath =
|
|
14767
|
+
const filePath = join25(LOG_DIR, filename);
|
|
14746
14768
|
const fileStat = await runBeforeDeadline(() => stat5(filePath), deadline);
|
|
14747
14769
|
if (!fileStat.isFile()) {
|
|
14748
14770
|
skipped++;
|
|
@@ -14838,7 +14860,7 @@ async function uploadEngineLog(input, timeoutMs) {
|
|
|
14838
14860
|
}
|
|
14839
14861
|
|
|
14840
14862
|
// src/services/chat/chat-service.ts
|
|
14841
|
-
var CODEX_AUTH_PATH2 =
|
|
14863
|
+
var CODEX_AUTH_PATH2 = join26(homedir15(), ".codex", "auth.json");
|
|
14842
14864
|
var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
|
|
14843
14865
|
function isCodexAvailable() {
|
|
14844
14866
|
return existsSync7(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
|
|
@@ -15305,7 +15327,7 @@ var ChatService = class {
|
|
|
15305
15327
|
return descendants;
|
|
15306
15328
|
}
|
|
15307
15329
|
async deleteHistoryFile(persisted) {
|
|
15308
|
-
await rm2(
|
|
15330
|
+
await rm2(join26(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
|
|
15309
15331
|
await rm2(chatMessageSendersFilePath(persisted.id), { force: true });
|
|
15310
15332
|
}
|
|
15311
15333
|
async getChatHistory(chatId, page = {}) {
|
|
@@ -15381,7 +15403,7 @@ var ChatService = class {
|
|
|
15381
15403
|
if (persisted.provider === "claude") {
|
|
15382
15404
|
provider = new ClaudeManager({
|
|
15383
15405
|
workingDirectory: this.workingDirectory,
|
|
15384
|
-
historyFilePath:
|
|
15406
|
+
historyFilePath: join26(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15385
15407
|
initialSessionId: persisted.providerSessionId,
|
|
15386
15408
|
onSaveSessionId: saveSession,
|
|
15387
15409
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15390,7 +15412,7 @@ var ChatService = class {
|
|
|
15390
15412
|
} else if (persisted.provider === "relay") {
|
|
15391
15413
|
provider = new RelayManager({
|
|
15392
15414
|
workingDirectory: this.workingDirectory,
|
|
15393
|
-
historyFilePath:
|
|
15415
|
+
historyFilePath: join26(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15394
15416
|
initialSessionId: persisted.providerSessionId,
|
|
15395
15417
|
onSaveSessionId: saveSession,
|
|
15396
15418
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15404,7 +15426,7 @@ var ChatService = class {
|
|
|
15404
15426
|
} else if (persisted.provider === "cursor") {
|
|
15405
15427
|
provider = new CursorManager({
|
|
15406
15428
|
workingDirectory: this.workingDirectory,
|
|
15407
|
-
historyFilePath:
|
|
15429
|
+
historyFilePath: join26(CURSOR_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15408
15430
|
initialSessionId: persisted.providerSessionId,
|
|
15409
15431
|
onSaveSessionId: saveSession,
|
|
15410
15432
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15413,7 +15435,7 @@ var ChatService = class {
|
|
|
15413
15435
|
} else if (persisted.provider === "opencode") {
|
|
15414
15436
|
provider = new OpencodeManager({
|
|
15415
15437
|
workingDirectory: this.workingDirectory,
|
|
15416
|
-
historyFilePath:
|
|
15438
|
+
historyFilePath: join26(OPENCODE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15417
15439
|
initialSessionId: persisted.providerSessionId,
|
|
15418
15440
|
onSaveSessionId: saveSession,
|
|
15419
15441
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15422,7 +15444,7 @@ var ChatService = class {
|
|
|
15422
15444
|
} else if (persisted.provider === "pi") {
|
|
15423
15445
|
provider = new PiManager({
|
|
15424
15446
|
workingDirectory: this.workingDirectory,
|
|
15425
|
-
historyFilePath:
|
|
15447
|
+
historyFilePath: join26(PI_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15426
15448
|
initialSessionId: persisted.providerSessionId,
|
|
15427
15449
|
onSaveSessionId: saveSession,
|
|
15428
15450
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15431,7 +15453,7 @@ var ChatService = class {
|
|
|
15431
15453
|
} else {
|
|
15432
15454
|
provider = new CodexAspManager({
|
|
15433
15455
|
workingDirectory: this.workingDirectory,
|
|
15434
|
-
historyFilePath:
|
|
15456
|
+
historyFilePath: join26(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15435
15457
|
initialSessionId: persisted.providerSessionId,
|
|
15436
15458
|
onSaveSessionId: saveSession,
|
|
15437
15459
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15581,7 +15603,7 @@ var ChatService = class {
|
|
|
15581
15603
|
});
|
|
15582
15604
|
uploadChatTranscript(
|
|
15583
15605
|
chatId,
|
|
15584
|
-
|
|
15606
|
+
join26(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
|
|
15585
15607
|
this.toSummary(chat)
|
|
15586
15608
|
).catch((err) => {
|
|
15587
15609
|
console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
|
|
@@ -15717,7 +15739,7 @@ var ChatService = class {
|
|
|
15717
15739
|
// src/services/repo-file-service.ts
|
|
15718
15740
|
import { execFile as execFile2 } from "child_process";
|
|
15719
15741
|
import { readFile as readFile15, realpath, stat as stat6 } from "fs/promises";
|
|
15720
|
-
import { join as
|
|
15742
|
+
import { join as join27, resolve as resolve2, extname as extname2 } from "path";
|
|
15721
15743
|
var CACHE_TTL_MS = 3e4;
|
|
15722
15744
|
var SEARCH_TIMEOUT_MS = 15e3;
|
|
15723
15745
|
var MAX_CONTENT_BYTES = 256 * 1024;
|
|
@@ -15877,7 +15899,7 @@ var RepoFileService = class {
|
|
|
15877
15899
|
const repo = repos.find((r) => r.name === repoName);
|
|
15878
15900
|
if (!repo) return null;
|
|
15879
15901
|
try {
|
|
15880
|
-
const fullPath = await realpath(resolve2(
|
|
15902
|
+
const fullPath = await realpath(resolve2(join27(repo.path, filePath)));
|
|
15881
15903
|
const repoRoot = await realpath(repo.path);
|
|
15882
15904
|
const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
|
|
15883
15905
|
if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
|
|
@@ -15985,20 +16007,20 @@ var RepoFileService = class {
|
|
|
15985
16007
|
import { Hono } from "hono";
|
|
15986
16008
|
import { z as z7 } from "zod";
|
|
15987
16009
|
import { readdir as readdir10, stat as stat7, readFile as readFile18 } from "fs/promises";
|
|
15988
|
-
import { join as
|
|
16010
|
+
import { join as join30, resolve as resolve3 } from "path";
|
|
15989
16011
|
|
|
15990
16012
|
// src/services/warm-hooks-service.ts
|
|
15991
16013
|
import { spawn as spawn4 } from "child_process";
|
|
15992
16014
|
import { readFile as readFile17 } from "fs/promises";
|
|
15993
16015
|
import { existsSync as existsSync8 } from "fs";
|
|
15994
|
-
import { join as
|
|
16016
|
+
import { join as join29 } from "path";
|
|
15995
16017
|
|
|
15996
16018
|
// src/services/warm-hook-logs-service.ts
|
|
15997
16019
|
import { mkdir as mkdir15, readFile as readFile16, writeFile as writeFile6, readdir as readdir9, appendFile as appendFile4, unlink as unlink3 } from "fs/promises";
|
|
15998
16020
|
import { homedir as homedir16 } from "os";
|
|
15999
|
-
import { join as
|
|
16000
|
-
var LOGS_DIR2 =
|
|
16001
|
-
var CURRENT_RUN_LOG =
|
|
16021
|
+
import { join as join28 } from "path";
|
|
16022
|
+
var LOGS_DIR2 = join28(homedir16(), ".replicas", "warm-hook-logs");
|
|
16023
|
+
var CURRENT_RUN_LOG = join28(LOGS_DIR2, "current-run.log");
|
|
16002
16024
|
var GLOBAL_FILENAME = "global.json";
|
|
16003
16025
|
function withPreview2(stored) {
|
|
16004
16026
|
const preview = buildHookOutputPreview(stored.output);
|
|
@@ -16015,7 +16037,7 @@ var WarmHookLogsService = class {
|
|
|
16015
16037
|
hookName: "organization",
|
|
16016
16038
|
...entry
|
|
16017
16039
|
};
|
|
16018
|
-
await writeFile6(
|
|
16040
|
+
await writeFile6(join28(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
16019
16041
|
`, "utf-8");
|
|
16020
16042
|
}
|
|
16021
16043
|
async saveEnvironmentHookLog(entry) {
|
|
@@ -16025,7 +16047,7 @@ var WarmHookLogsService = class {
|
|
|
16025
16047
|
hookName: "environment",
|
|
16026
16048
|
...entry
|
|
16027
16049
|
};
|
|
16028
|
-
await writeFile6(
|
|
16050
|
+
await writeFile6(join28(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
16029
16051
|
`, "utf-8");
|
|
16030
16052
|
}
|
|
16031
16053
|
async saveRepoHookLog(repoName, entry) {
|
|
@@ -16035,7 +16057,7 @@ var WarmHookLogsService = class {
|
|
|
16035
16057
|
hookName: repoName,
|
|
16036
16058
|
...entry
|
|
16037
16059
|
};
|
|
16038
|
-
await writeFile6(
|
|
16060
|
+
await writeFile6(join28(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
|
|
16039
16061
|
`, "utf-8");
|
|
16040
16062
|
}
|
|
16041
16063
|
async getAllLogs() {
|
|
@@ -16054,7 +16076,7 @@ var WarmHookLogsService = class {
|
|
|
16054
16076
|
continue;
|
|
16055
16077
|
}
|
|
16056
16078
|
try {
|
|
16057
|
-
const raw = await readFile16(
|
|
16079
|
+
const raw = await readFile16(join28(LOGS_DIR2, file), "utf-8");
|
|
16058
16080
|
const stored = JSON.parse(raw);
|
|
16059
16081
|
logs.push(withPreview2(stored));
|
|
16060
16082
|
} catch {
|
|
@@ -16092,7 +16114,7 @@ var WarmHookLogsService = class {
|
|
|
16092
16114
|
async getFullOutput(hookType, hookName) {
|
|
16093
16115
|
const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
16094
16116
|
try {
|
|
16095
|
-
const raw = await readFile16(
|
|
16117
|
+
const raw = await readFile16(join28(LOGS_DIR2, filename), "utf-8");
|
|
16096
16118
|
const stored = JSON.parse(raw);
|
|
16097
16119
|
if (stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
16098
16120
|
return null;
|
|
@@ -16111,7 +16133,7 @@ var warmHookLogsService = new WarmHookLogsService();
|
|
|
16111
16133
|
// src/services/warm-hooks-service.ts
|
|
16112
16134
|
async function readRepoWarmHook(repoPath) {
|
|
16113
16135
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
16114
|
-
const configPath =
|
|
16136
|
+
const configPath = join29(repoPath, filename);
|
|
16115
16137
|
if (!existsSync8(configPath)) {
|
|
16116
16138
|
continue;
|
|
16117
16139
|
}
|
|
@@ -17373,7 +17395,7 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
17373
17395
|
const logFiles = files.filter((f) => f.endsWith(".log"));
|
|
17374
17396
|
const sessions = await Promise.all(
|
|
17375
17397
|
logFiles.map(async (filename) => {
|
|
17376
|
-
const filePath =
|
|
17398
|
+
const filePath = join30(LOG_DIR, filename);
|
|
17377
17399
|
const fileStat = await stat7(filePath);
|
|
17378
17400
|
const sessionId = filename.replace(/\.log$/, "");
|
|
17379
17401
|
return {
|
|
@@ -17758,6 +17780,10 @@ serve(
|
|
|
17758
17780
|
await timeStartupStep("chat_initialize", () => chatService.initialize());
|
|
17759
17781
|
await timeStartupStep("preview_initialize", () => previewService.initialize());
|
|
17760
17782
|
if (!IS_WARMING_MODE) {
|
|
17783
|
+
await timeStartupStep(
|
|
17784
|
+
"git_credential_helper_initialize",
|
|
17785
|
+
() => configureManagedGitCredentialHelper(ENGINE_ENV.HOME_DIR)
|
|
17786
|
+
);
|
|
17761
17787
|
await timeStartupStep("github_token_initialize", () => githubTokenManager.start());
|
|
17762
17788
|
}
|
|
17763
17789
|
engineReady = true;
|