replicas-engine 0.1.499 → 0.1.501
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/dist/src/index.js +157 -143
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -526,17 +526,19 @@ var AUTOMATED_SOURCES = ["api", "automation"];
|
|
|
526
526
|
var INTEGRATION_SOURCES_SQL = INTEGRATION_SOURCES.map((s) => `'${s}'`).join(", ");
|
|
527
527
|
var AUTOMATED_SOURCES_SQL = AUTOMATED_SOURCES.map((s) => `'${s}'`).join(", ");
|
|
528
528
|
var PLANS = {
|
|
529
|
-
|
|
530
|
-
id: "
|
|
531
|
-
name: "
|
|
529
|
+
trial: {
|
|
530
|
+
id: "trial",
|
|
531
|
+
name: "Free Trial",
|
|
532
532
|
monthlyPrice: 0,
|
|
533
533
|
seatPriceCents: 0,
|
|
534
534
|
features: [
|
|
535
|
-
"
|
|
536
|
-
"
|
|
537
|
-
"
|
|
538
|
-
"
|
|
539
|
-
"
|
|
535
|
+
"14 days free, no credit card required",
|
|
536
|
+
"Unlimited manual workspace minutes",
|
|
537
|
+
"15,000 automated workspace minutes",
|
|
538
|
+
"Unlimited repositories and environments",
|
|
539
|
+
"Unlimited automations",
|
|
540
|
+
"Warm pools and warm hooks",
|
|
541
|
+
"API access"
|
|
540
542
|
]
|
|
541
543
|
},
|
|
542
544
|
developer: {
|
|
@@ -609,7 +611,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
609
611
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
610
612
|
|
|
611
613
|
// ../shared/src/e2b.ts
|
|
612
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-25-
|
|
614
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-25-v3";
|
|
613
615
|
|
|
614
616
|
// ../shared/src/runtime-env.ts
|
|
615
617
|
function shellQuotePosix(value) {
|
|
@@ -4853,7 +4855,6 @@ function loadEngineEnv() {
|
|
|
4853
4855
|
ANTHROPIC_API_KEY: readEnv("ANTHROPIC_API_KEY"),
|
|
4854
4856
|
OPENAI_API_KEY: readEnv("OPENAI_API_KEY"),
|
|
4855
4857
|
CURSOR_API_KEY: readEnv("CURSOR_API_KEY"),
|
|
4856
|
-
OPENROUTER_API_KEY: readEnv("OPENROUTER_API_KEY"),
|
|
4857
4858
|
CLAUDE_CODE_USE_BEDROCK: readEnv("CLAUDE_CODE_USE_BEDROCK"),
|
|
4858
4859
|
AWS_ACCESS_KEY_ID: readEnv("AWS_ACCESS_KEY_ID"),
|
|
4859
4860
|
AWS_SECRET_ACCESS_KEY: readEnv("AWS_SECRET_ACCESS_KEY"),
|
|
@@ -6297,22 +6298,29 @@ var engineLogger = new EngineLogger();
|
|
|
6297
6298
|
// src/services/replicas-config-service.ts
|
|
6298
6299
|
import { readFile as readFile6, appendFile, writeFile as writeFile4, mkdir as mkdir6 } from "fs/promises";
|
|
6299
6300
|
import { existsSync as existsSync3 } from "fs";
|
|
6300
|
-
import { join as
|
|
6301
|
-
import { homedir as
|
|
6301
|
+
import { join as join10 } from "path";
|
|
6302
|
+
import { homedir as homedir8 } from "os";
|
|
6302
6303
|
import { spawn as spawn2 } from "child_process";
|
|
6303
6304
|
|
|
6304
6305
|
// src/services/environment-details-service.ts
|
|
6305
6306
|
import { mkdir as mkdir4, readFile as readFile4 } from "fs/promises";
|
|
6306
6307
|
import { existsSync as existsSync2 } from "fs";
|
|
6308
|
+
import { homedir as homedir6 } from "os";
|
|
6309
|
+
import { join as join8 } from "path";
|
|
6310
|
+
|
|
6311
|
+
// src/managers/agent-auth-paths.ts
|
|
6307
6312
|
import { homedir as homedir5 } from "os";
|
|
6308
6313
|
import { join as join7 } from "path";
|
|
6309
|
-
var REPLICAS_DIR = join7(homedir5(), ".replicas");
|
|
6310
|
-
var DETAILS_FILE = join7(REPLICAS_DIR, "environment-details.json");
|
|
6311
|
-
var CLAUDE_CREDENTIALS_PATH = join7(homedir5(), ".claude", ".credentials.json");
|
|
6312
|
-
var CODEX_AUTH_PATH = join7(homedir5(), ".codex", "auth.json");
|
|
6313
6314
|
var OPENCODE_AUTH_PATH = join7(homedir5(), ".local", "share", "opencode", "auth.json");
|
|
6314
|
-
var
|
|
6315
|
-
|
|
6315
|
+
var PI_AUTH_PATH = join7(homedir5(), ".pi", "agent", "auth.json");
|
|
6316
|
+
|
|
6317
|
+
// src/services/environment-details-service.ts
|
|
6318
|
+
var REPLICAS_DIR = join8(homedir6(), ".replicas");
|
|
6319
|
+
var DETAILS_FILE = join8(REPLICAS_DIR, "environment-details.json");
|
|
6320
|
+
var CLAUDE_CREDENTIALS_PATH = join8(homedir6(), ".claude", ".credentials.json");
|
|
6321
|
+
var CODEX_AUTH_PATH = join8(homedir6(), ".codex", "auth.json");
|
|
6322
|
+
var GH_HOSTS_PATH = join8(homedir6(), ".config", "gh", "hosts.yml");
|
|
6323
|
+
var GIT_CREDENTIALS_PATH = join8(homedir6(), ".git-credentials");
|
|
6316
6324
|
function detectClaudeAuthMethod() {
|
|
6317
6325
|
if (existsSync2(CLAUDE_CREDENTIALS_PATH)) {
|
|
6318
6326
|
return "oauth";
|
|
@@ -6342,10 +6350,10 @@ function detectCursorAuthMethod() {
|
|
|
6342
6350
|
return ENGINE_ENV.CURSOR_API_KEY ? "api_key" : "none";
|
|
6343
6351
|
}
|
|
6344
6352
|
function detectOpencodeAuthMethod() {
|
|
6345
|
-
return existsSync2(OPENCODE_AUTH_PATH)
|
|
6353
|
+
return existsSync2(OPENCODE_AUTH_PATH) ? "api_key" : "none";
|
|
6346
6354
|
}
|
|
6347
6355
|
function detectPiAuthMethod() {
|
|
6348
|
-
return
|
|
6356
|
+
return existsSync2(PI_AUTH_PATH) ? "api_key" : "none";
|
|
6349
6357
|
}
|
|
6350
6358
|
async function detectGitIdentityConfigured() {
|
|
6351
6359
|
try {
|
|
@@ -6518,8 +6526,8 @@ var environmentDetailsService = new EnvironmentDetailsService();
|
|
|
6518
6526
|
|
|
6519
6527
|
// src/services/start-hook-logs-service.ts
|
|
6520
6528
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile3, readdir as readdir2 } from "fs/promises";
|
|
6521
|
-
import { homedir as
|
|
6522
|
-
import { join as
|
|
6529
|
+
import { homedir as homedir7 } from "os";
|
|
6530
|
+
import { join as join9 } from "path";
|
|
6523
6531
|
|
|
6524
6532
|
// src/services/hook-log-files.ts
|
|
6525
6533
|
import { createHash } from "crypto";
|
|
@@ -6531,7 +6539,7 @@ function repoHookLogFilename(repoName) {
|
|
|
6531
6539
|
}
|
|
6532
6540
|
|
|
6533
6541
|
// src/services/start-hook-logs-service.ts
|
|
6534
|
-
var LOGS_DIR =
|
|
6542
|
+
var LOGS_DIR = join9(homedir7(), ".replicas", "start-hook-logs");
|
|
6535
6543
|
function withPreview(stored) {
|
|
6536
6544
|
const preview = buildHookOutputPreview(stored.output);
|
|
6537
6545
|
return { ...stored, ...preview };
|
|
@@ -6569,7 +6577,7 @@ var StartHookLogsService = class {
|
|
|
6569
6577
|
await this.ensureDir();
|
|
6570
6578
|
const log = { hookType, hookName, repoName: hookName, ...entry };
|
|
6571
6579
|
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
6572
|
-
await writeFile3(
|
|
6580
|
+
await writeFile3(join9(LOGS_DIR, filename), `${JSON.stringify(log, null, 2)}
|
|
6573
6581
|
`, "utf-8");
|
|
6574
6582
|
}
|
|
6575
6583
|
async saveEnvironmentLog(entry) {
|
|
@@ -6594,7 +6602,7 @@ var StartHookLogsService = class {
|
|
|
6594
6602
|
continue;
|
|
6595
6603
|
}
|
|
6596
6604
|
try {
|
|
6597
|
-
const raw = await readFile5(
|
|
6605
|
+
const raw = await readFile5(join9(LOGS_DIR, file), "utf-8");
|
|
6598
6606
|
const stored = normalizeStored(JSON.parse(raw));
|
|
6599
6607
|
if (stored) {
|
|
6600
6608
|
logs.push(withPreview(stored));
|
|
@@ -6613,7 +6621,7 @@ var StartHookLogsService = class {
|
|
|
6613
6621
|
async getFullOutput(hookType, hookName) {
|
|
6614
6622
|
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
6615
6623
|
try {
|
|
6616
|
-
const raw = await readFile5(
|
|
6624
|
+
const raw = await readFile5(join9(LOGS_DIR, filename), "utf-8");
|
|
6617
6625
|
const stored = normalizeStored(JSON.parse(raw));
|
|
6618
6626
|
if (!stored || stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
6619
6627
|
return null;
|
|
@@ -6630,7 +6638,7 @@ var StartHookLogsService = class {
|
|
|
6630
6638
|
var startHookLogsService = new StartHookLogsService();
|
|
6631
6639
|
|
|
6632
6640
|
// src/services/replicas-config-service.ts
|
|
6633
|
-
var START_HOOKS_LOG =
|
|
6641
|
+
var START_HOOKS_LOG = join10(homedir8(), ".replicas", "startHooks.log");
|
|
6634
6642
|
var START_HOOKS_RUNNING_PROMPT = `IMPORTANT - Start Hooks Running:
|
|
6635
6643
|
Start hooks are shell commands/scripts set by repository owners that run on workspace startup.
|
|
6636
6644
|
These hooks are currently executing in the background. You can:
|
|
@@ -6641,7 +6649,7 @@ The start hooks may install dependencies, build projects, or perform other setup
|
|
|
6641
6649
|
If your task depends on setup being complete, check the log file before proceeding.`;
|
|
6642
6650
|
async function readReplicasConfigFromDir(dirPath) {
|
|
6643
6651
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
6644
|
-
const configPath =
|
|
6652
|
+
const configPath = join10(dirPath, filename);
|
|
6645
6653
|
if (!existsSync3(configPath)) {
|
|
6646
6654
|
continue;
|
|
6647
6655
|
}
|
|
@@ -6711,7 +6719,7 @@ var ReplicasConfigService = class {
|
|
|
6711
6719
|
const logLine = `[${timestamp}] ${message}
|
|
6712
6720
|
`;
|
|
6713
6721
|
try {
|
|
6714
|
-
await mkdir6(
|
|
6722
|
+
await mkdir6(join10(homedir8(), ".replicas"), { recursive: true });
|
|
6715
6723
|
await appendFile(START_HOOKS_LOG, logLine, "utf-8");
|
|
6716
6724
|
} catch (error) {
|
|
6717
6725
|
console.error("Failed to write to start hooks log:", error);
|
|
@@ -6723,7 +6731,7 @@ var ReplicasConfigService = class {
|
|
|
6723
6731
|
command: params.content,
|
|
6724
6732
|
label: "env start hook",
|
|
6725
6733
|
repoName: "environment",
|
|
6726
|
-
cwd:
|
|
6734
|
+
cwd: homedir8(),
|
|
6727
6735
|
timeout: params.timeoutMs ?? DEFAULT_START_HOOK_TIMEOUT_MS,
|
|
6728
6736
|
onOutputChunk: params.onOutputChunk
|
|
6729
6737
|
});
|
|
@@ -6846,7 +6854,7 @@ var ReplicasConfigService = class {
|
|
|
6846
6854
|
this.hooksCompleted = false;
|
|
6847
6855
|
this.hooksFailed = false;
|
|
6848
6856
|
try {
|
|
6849
|
-
await mkdir6(
|
|
6857
|
+
await mkdir6(join10(homedir8(), ".replicas"), { recursive: true });
|
|
6850
6858
|
await writeFile4(
|
|
6851
6859
|
START_HOOKS_LOG,
|
|
6852
6860
|
`=== Start Hooks Execution Log ===
|
|
@@ -7041,11 +7049,11 @@ var replicasConfigService = new ReplicasConfigService();
|
|
|
7041
7049
|
|
|
7042
7050
|
// src/services/event-service.ts
|
|
7043
7051
|
import { mkdir as mkdir7 } from "fs/promises";
|
|
7044
|
-
import { homedir as
|
|
7045
|
-
import { join as
|
|
7052
|
+
import { homedir as homedir9 } from "os";
|
|
7053
|
+
import { join as join11 } from "path";
|
|
7046
7054
|
import { randomUUID } from "crypto";
|
|
7047
|
-
var ENGINE_DIR =
|
|
7048
|
-
var EVENTS_FILE =
|
|
7055
|
+
var ENGINE_DIR = join11(homedir9(), ".replicas", "engine");
|
|
7056
|
+
var EVENTS_FILE = join11(ENGINE_DIR, "events.jsonl");
|
|
7049
7057
|
var EventService = class {
|
|
7050
7058
|
subscribers = /* @__PURE__ */ new Map();
|
|
7051
7059
|
writer = new StreamWriter();
|
|
@@ -7079,9 +7087,9 @@ var eventService = new EventService();
|
|
|
7079
7087
|
import { mkdir as mkdir8, readFile as readFile7 } from "fs/promises";
|
|
7080
7088
|
import { existsSync as existsSync4 } from "fs";
|
|
7081
7089
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
7082
|
-
import { homedir as
|
|
7083
|
-
import { dirname as dirname2, join as
|
|
7084
|
-
var PREVIEW_PORTS_FILE =
|
|
7090
|
+
import { homedir as homedir10 } from "os";
|
|
7091
|
+
import { dirname as dirname2, join as join12 } from "path";
|
|
7092
|
+
var PREVIEW_PORTS_FILE = join12(homedir10(), ".replicas", "preview-ports.json");
|
|
7085
7093
|
async function readPreviewsFile() {
|
|
7086
7094
|
try {
|
|
7087
7095
|
if (!existsSync4(PREVIEW_PORTS_FILE)) {
|
|
@@ -7193,8 +7201,8 @@ async function registerDesktopPreview() {
|
|
|
7193
7201
|
// src/services/chat/chat-service.ts
|
|
7194
7202
|
import { existsSync as existsSync7 } from "fs";
|
|
7195
7203
|
import { appendFile as appendFile3, copyFile, mkdir as mkdir14, readFile as readFile14, rename as rename2, rm as rm2 } from "fs/promises";
|
|
7196
|
-
import { homedir as
|
|
7197
|
-
import { join as
|
|
7204
|
+
import { homedir as homedir15 } from "os";
|
|
7205
|
+
import { join as join25 } from "path";
|
|
7198
7206
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
7199
7207
|
|
|
7200
7208
|
// src/managers/claude-manager.ts
|
|
@@ -7202,9 +7210,9 @@ import {
|
|
|
7202
7210
|
query
|
|
7203
7211
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
7204
7212
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
7205
|
-
import { dirname as dirname4, join as
|
|
7213
|
+
import { dirname as dirname4, join as join15 } from "path";
|
|
7206
7214
|
import { mkdir as mkdir10 } from "fs/promises";
|
|
7207
|
-
import { homedir as
|
|
7215
|
+
import { homedir as homedir12 } from "os";
|
|
7208
7216
|
|
|
7209
7217
|
// src/utils/linear-converter.ts
|
|
7210
7218
|
function linearThoughtToResponse(thought) {
|
|
@@ -7590,8 +7598,8 @@ function extractPlanFromCodexAspNotification(notification) {
|
|
|
7590
7598
|
// src/utils/image-utils.ts
|
|
7591
7599
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
7592
7600
|
import { mkdir as mkdir9, unlink as unlink2, writeFile as writeFile5 } from "fs/promises";
|
|
7593
|
-
import { homedir as
|
|
7594
|
-
import { join as
|
|
7601
|
+
import { homedir as homedir11 } from "os";
|
|
7602
|
+
import { join as join13 } from "path";
|
|
7595
7603
|
function isImageMediaType(value) {
|
|
7596
7604
|
return IMAGE_MEDIA_TYPES.includes(value);
|
|
7597
7605
|
}
|
|
@@ -7691,14 +7699,14 @@ async function normalizeImages(images) {
|
|
|
7691
7699
|
}
|
|
7692
7700
|
return normalized;
|
|
7693
7701
|
}
|
|
7694
|
-
async function saveNormalizedImagesToTempFiles(images, tempImageDir =
|
|
7702
|
+
async function saveNormalizedImagesToTempFiles(images, tempImageDir = join13(homedir11(), ".replicas", "codex", "temp-images")) {
|
|
7695
7703
|
await mkdir9(tempImageDir, { recursive: true });
|
|
7696
7704
|
const tempPaths = [];
|
|
7697
7705
|
try {
|
|
7698
7706
|
for (const image of images) {
|
|
7699
7707
|
const ext = image.source.media_type.split("/")[1] || "png";
|
|
7700
7708
|
const filename = `img_${randomUUID3()}.${ext}`;
|
|
7701
|
-
const filepath =
|
|
7709
|
+
const filepath = join13(tempImageDir, filename);
|
|
7702
7710
|
await writeFile5(filepath, Buffer.from(image.source.data, "base64"));
|
|
7703
7711
|
tempPaths.push(filepath);
|
|
7704
7712
|
}
|
|
@@ -8283,7 +8291,7 @@ function reportCommandProtectionBlock(options) {
|
|
|
8283
8291
|
|
|
8284
8292
|
// src/services/skill-registry-service.ts
|
|
8285
8293
|
import { readFile as readFile8, readdir as readdir3, stat as stat2 } from "fs/promises";
|
|
8286
|
-
import { dirname as dirname3, isAbsolute, join as
|
|
8294
|
+
import { dirname as dirname3, isAbsolute, join as join14, relative, resolve } from "path";
|
|
8287
8295
|
var REGISTRY_ROOT_DIR = ".replicas/skill-registries";
|
|
8288
8296
|
var REGISTRY_MANIFEST = "manifest.json";
|
|
8289
8297
|
async function getSkillRegistryInventory(homeDir) {
|
|
@@ -8344,10 +8352,10 @@ async function scanRegistry(registryDir) {
|
|
|
8344
8352
|
}
|
|
8345
8353
|
async function findSkillCollections(registryDir) {
|
|
8346
8354
|
const candidateRoots = [
|
|
8347
|
-
{ source: "skills", root:
|
|
8348
|
-
{ source: "agents", root:
|
|
8349
|
-
{ source: "codex", root:
|
|
8350
|
-
{ source: "claude", root:
|
|
8355
|
+
{ source: "skills", root: join14(registryDir, "skills") },
|
|
8356
|
+
{ source: "agents", root: join14(registryDir, ".agents", "skills") },
|
|
8357
|
+
{ source: "codex", root: join14(registryDir, ".codex", "skills") },
|
|
8358
|
+
{ source: "claude", root: join14(registryDir, ".claude", "skills") }
|
|
8351
8359
|
];
|
|
8352
8360
|
const collections = [];
|
|
8353
8361
|
for (const { source, root } of candidateRoots) {
|
|
@@ -8361,9 +8369,9 @@ async function findSkillCollections(registryDir) {
|
|
|
8361
8369
|
async function findSkillDirsInRoot(root) {
|
|
8362
8370
|
const skillDirs = [];
|
|
8363
8371
|
for (const dirent of await safeReadDir(root)) {
|
|
8364
|
-
const skillDir =
|
|
8372
|
+
const skillDir = join14(root, dirent.name);
|
|
8365
8373
|
if (!await isDirectoryDirent(dirent, skillDir)) continue;
|
|
8366
|
-
if (await fileExists(
|
|
8374
|
+
if (await fileExists(join14(skillDir, "SKILL.md"))) {
|
|
8367
8375
|
skillDirs.push(skillDir);
|
|
8368
8376
|
}
|
|
8369
8377
|
}
|
|
@@ -8373,9 +8381,9 @@ async function findTopLevelSkills(registryDir) {
|
|
|
8373
8381
|
const skills = [];
|
|
8374
8382
|
for (const dirent of await safeReadDir(registryDir)) {
|
|
8375
8383
|
if (dirent.name.startsWith(".") || dirent.name === "skills" || dirent.name === "plugins") continue;
|
|
8376
|
-
const skillDir =
|
|
8384
|
+
const skillDir = join14(registryDir, dirent.name);
|
|
8377
8385
|
if (!await isDirectoryDirent(dirent, skillDir)) continue;
|
|
8378
|
-
if (await fileExists(
|
|
8386
|
+
if (await fileExists(join14(skillDir, "SKILL.md"))) {
|
|
8379
8387
|
skills.push({ source: "root", skillDir });
|
|
8380
8388
|
}
|
|
8381
8389
|
}
|
|
@@ -8386,10 +8394,10 @@ async function findClaudePluginRoots(registryDir) {
|
|
|
8386
8394
|
async function walk(dir) {
|
|
8387
8395
|
for (const dirent of await safeReadDir(dir)) {
|
|
8388
8396
|
if (dirent.name === ".git") continue;
|
|
8389
|
-
const child =
|
|
8397
|
+
const child = join14(dir, dirent.name);
|
|
8390
8398
|
if (!await isDirectoryDirent(dirent, child)) continue;
|
|
8391
8399
|
if (dirent.name === ".claude-plugin") {
|
|
8392
|
-
if (await fileExists(
|
|
8400
|
+
if (await fileExists(join14(child, "plugin.json"))) {
|
|
8393
8401
|
roots.push(dirname3(child));
|
|
8394
8402
|
}
|
|
8395
8403
|
continue;
|
|
@@ -8401,7 +8409,7 @@ async function findClaudePluginRoots(registryDir) {
|
|
|
8401
8409
|
return uniqueStrings(roots);
|
|
8402
8410
|
}
|
|
8403
8411
|
async function hasCodexMarketplace(registryDir) {
|
|
8404
|
-
return await fileExists(
|
|
8412
|
+
return await fileExists(join14(registryDir, ".agents", "plugins", "marketplace.json")) || await fileExists(join14(registryDir, ".codex", "plugins", "marketplace.json"));
|
|
8405
8413
|
}
|
|
8406
8414
|
async function installCodexRegistryPlugins(client, inventory) {
|
|
8407
8415
|
const cwds = inventory.codexMarketplaceCwds;
|
|
@@ -8451,10 +8459,10 @@ function isSkillRegistryEntry(value) {
|
|
|
8451
8459
|
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";
|
|
8452
8460
|
}
|
|
8453
8461
|
function getRegistryRoot(homeDir) {
|
|
8454
|
-
return
|
|
8462
|
+
return join14(homeDir, REGISTRY_ROOT_DIR);
|
|
8455
8463
|
}
|
|
8456
8464
|
function getManifestPath(homeDir) {
|
|
8457
|
-
return
|
|
8465
|
+
return join14(getRegistryRoot(homeDir), REGISTRY_MANIFEST);
|
|
8458
8466
|
}
|
|
8459
8467
|
function emptyInventory(registryRoot) {
|
|
8460
8468
|
return {
|
|
@@ -8801,7 +8809,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
8801
8809
|
authRetrying = false;
|
|
8802
8810
|
constructor(options) {
|
|
8803
8811
|
super(options);
|
|
8804
|
-
this.historyFilePath = options.historyFilePath ??
|
|
8812
|
+
this.historyFilePath = options.historyFilePath ?? join15(homedir12(), ".replicas", "claude", "history.jsonl");
|
|
8805
8813
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
8806
8814
|
this.systemPromptOverride = options.systemPromptOverride;
|
|
8807
8815
|
this.toolsOverride = options.tools;
|
|
@@ -9733,7 +9741,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
9733
9741
|
|
|
9734
9742
|
// src/managers/codex-asp/codex-asp-manager.ts
|
|
9735
9743
|
import { readdir as readdir4 } from "fs/promises";
|
|
9736
|
-
import { join as
|
|
9744
|
+
import { join as join17 } from "path";
|
|
9737
9745
|
|
|
9738
9746
|
// src/managers/codex-asp/app-server-process.ts
|
|
9739
9747
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -9934,7 +9942,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
|
9934
9942
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
9935
9943
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
9936
9944
|
var codexCliVersionEnsured = null;
|
|
9937
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
9945
|
+
var ENGINE_PACKAGE_VERSION = "0.1.501";
|
|
9938
9946
|
var INITIALIZE_METHOD = "initialize";
|
|
9939
9947
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
9940
9948
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -10859,16 +10867,16 @@ var TranscriptUpdateCoalescer = class {
|
|
|
10859
10867
|
};
|
|
10860
10868
|
|
|
10861
10869
|
// src/services/chat/history-paths.ts
|
|
10862
|
-
import { homedir as
|
|
10863
|
-
import { join as
|
|
10864
|
-
var ENGINE_DIR2 =
|
|
10865
|
-
var CHATS_FILE =
|
|
10866
|
-
var CLAUDE_HISTORY_DIR =
|
|
10867
|
-
var RELAY_HISTORY_DIR =
|
|
10868
|
-
var CODEX_HISTORY_DIR =
|
|
10869
|
-
var CURSOR_HISTORY_DIR =
|
|
10870
|
-
var OPENCODE_HISTORY_DIR =
|
|
10871
|
-
var PI_HISTORY_DIR =
|
|
10870
|
+
import { homedir as homedir13 } from "os";
|
|
10871
|
+
import { join as join16 } from "path";
|
|
10872
|
+
var ENGINE_DIR2 = join16(homedir13(), ".replicas", "engine");
|
|
10873
|
+
var CHATS_FILE = join16(ENGINE_DIR2, "chats.json");
|
|
10874
|
+
var CLAUDE_HISTORY_DIR = join16(ENGINE_DIR2, "claude-histories");
|
|
10875
|
+
var RELAY_HISTORY_DIR = join16(ENGINE_DIR2, "relay-histories");
|
|
10876
|
+
var CODEX_HISTORY_DIR = join16(ENGINE_DIR2, "codex-histories");
|
|
10877
|
+
var CURSOR_HISTORY_DIR = join16(ENGINE_DIR2, "cursor-histories");
|
|
10878
|
+
var OPENCODE_HISTORY_DIR = join16(ENGINE_DIR2, "opencode-histories");
|
|
10879
|
+
var PI_HISTORY_DIR = join16(ENGINE_DIR2, "pi-histories");
|
|
10872
10880
|
var HISTORY_DIR_BY_PROVIDER = {
|
|
10873
10881
|
claude: CLAUDE_HISTORY_DIR,
|
|
10874
10882
|
relay: RELAY_HISTORY_DIR,
|
|
@@ -10914,7 +10922,7 @@ async function readCodexAspThreadHistory(threadId) {
|
|
|
10914
10922
|
}
|
|
10915
10923
|
for (const entry of entries) {
|
|
10916
10924
|
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
10917
|
-
const history = await new CodexHistoryFile(
|
|
10925
|
+
const history = await new CodexHistoryFile(join17(CODEX_HISTORY_DIR, entry.name)).load();
|
|
10918
10926
|
const transcript = history.transcriptsByThreadId.get(threadId);
|
|
10919
10927
|
if (transcript) {
|
|
10920
10928
|
return {
|
|
@@ -12131,7 +12139,7 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12131
12139
|
|
|
12132
12140
|
// src/managers/cursor-manager.ts
|
|
12133
12141
|
import { mkdir as mkdir11, readFile as readFile10, readdir as readdir5 } from "fs/promises";
|
|
12134
|
-
import { basename, dirname as dirname5, extname, join as
|
|
12142
|
+
import { basename, dirname as dirname5, extname, join as join18 } from "path";
|
|
12135
12143
|
import { parse as parseYaml2 } from "yaml";
|
|
12136
12144
|
import { Agent as CursorAgent } from "@cursor/sdk";
|
|
12137
12145
|
var CURSOR_SLASH_COMMANDS_CACHE_MS = 3e4;
|
|
@@ -12190,7 +12198,7 @@ async function listCursorCommandsInDirectory(directory) {
|
|
|
12190
12198
|
const name = basename(entry.name, ".md");
|
|
12191
12199
|
let description;
|
|
12192
12200
|
try {
|
|
12193
|
-
description = extractCursorCommandDescription(await readFile10(
|
|
12201
|
+
description = extractCursorCommandDescription(await readFile10(join18(directory, entry.name), "utf8"));
|
|
12194
12202
|
} catch (error) {
|
|
12195
12203
|
console.warn("[CursorManager] Failed to read slash command file:", error);
|
|
12196
12204
|
}
|
|
@@ -12212,7 +12220,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12212
12220
|
slashCommandsRequest = null;
|
|
12213
12221
|
constructor(options) {
|
|
12214
12222
|
super(options);
|
|
12215
|
-
this.historyFilePath = options.historyFilePath ??
|
|
12223
|
+
this.historyFilePath = options.historyFilePath ?? join18(ENGINE_ENV.HOME_DIR, ".replicas", "cursor", "history.jsonl");
|
|
12216
12224
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
12217
12225
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
12218
12226
|
}
|
|
@@ -12263,7 +12271,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12263
12271
|
this.slashCommandsRequest ??= (async () => {
|
|
12264
12272
|
try {
|
|
12265
12273
|
const repoDirectories = await getAgentAdditionalDirectories();
|
|
12266
|
-
const commandDirectories = [this.workingDirectory, ...repoDirectories, ENGINE_ENV.HOME_DIR].map((directory) =>
|
|
12274
|
+
const commandDirectories = [this.workingDirectory, ...repoDirectories, ENGINE_ENV.HOME_DIR].map((directory) => join18(directory, ".cursor", "commands"));
|
|
12267
12275
|
const commands = mergeSlashCommands(
|
|
12268
12276
|
...await Promise.all(commandDirectories.map(listCursorCommandsInDirectory))
|
|
12269
12277
|
);
|
|
@@ -12512,7 +12520,7 @@ ${request.message}` : request.message;
|
|
|
12512
12520
|
// src/managers/opencode-manager.ts
|
|
12513
12521
|
import { existsSync as existsSync6 } from "fs";
|
|
12514
12522
|
import { mkdir as mkdir12, readFile as readFile11 } from "fs/promises";
|
|
12515
|
-
import { delimiter, dirname as dirname6, join as
|
|
12523
|
+
import { delimiter, dirname as dirname6, join as join19 } from "path";
|
|
12516
12524
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
12517
12525
|
import { fileURLToPath } from "url";
|
|
12518
12526
|
import { Agent } from "undici";
|
|
@@ -12522,8 +12530,7 @@ import {
|
|
|
12522
12530
|
createOpencodeServer
|
|
12523
12531
|
} from "@opencode-ai/sdk/v2";
|
|
12524
12532
|
var OPENCODE_SHIM_DIR = dirname6(fileURLToPath(new URL("../../scripts/opencode", import.meta.url)));
|
|
12525
|
-
var OPENCODE_CONFIG_PATH =
|
|
12526
|
-
var OPENCODE_AUTH_PATH2 = join18(ENGINE_ENV.HOME_DIR, ".local", "share", "opencode", "auth.json");
|
|
12533
|
+
var OPENCODE_CONFIG_PATH = join19(ENGINE_ENV.HOME_DIR, ".config", "opencode", "opencode.json");
|
|
12527
12534
|
var OPENCODE_FETCH_DISPATCHER = new Agent({ headersTimeout: 0, bodyTimeout: 0 });
|
|
12528
12535
|
var OPENCODE_SERVER_STARTUP_TIMEOUT_MS = 3e4;
|
|
12529
12536
|
var OPENCODE_WORKSPACE_PERMISSION = {
|
|
@@ -12557,11 +12564,11 @@ var opencodeAuthSchema = z5.record(z5.string(), z5.object({
|
|
|
12557
12564
|
type: z5.string().optional(),
|
|
12558
12565
|
key: z5.string().optional()
|
|
12559
12566
|
}));
|
|
12560
|
-
async function
|
|
12561
|
-
if (!existsSync6(
|
|
12567
|
+
async function hasOpencodeCredentials(provider) {
|
|
12568
|
+
if (!existsSync6(OPENCODE_AUTH_PATH)) return false;
|
|
12562
12569
|
try {
|
|
12563
|
-
const auth = opencodeAuthSchema.safeParse(JSON.parse(await readFile11(
|
|
12564
|
-
return auth.success && auth.data[
|
|
12570
|
+
const auth = opencodeAuthSchema.safeParse(JSON.parse(await readFile11(OPENCODE_AUTH_PATH, "utf8")));
|
|
12571
|
+
return auth.success && auth.data[provider]?.type === "api" && Boolean(auth.data[provider]?.key);
|
|
12565
12572
|
} catch {
|
|
12566
12573
|
return false;
|
|
12567
12574
|
}
|
|
@@ -12571,7 +12578,7 @@ function getOpenCodeGoModel(model) {
|
|
|
12571
12578
|
}
|
|
12572
12579
|
async function opencodeConfig(model) {
|
|
12573
12580
|
let config;
|
|
12574
|
-
if (await
|
|
12581
|
+
if (await hasOpencodeCredentials(OPENCODE_GO_PROVIDER)) {
|
|
12575
12582
|
config = {
|
|
12576
12583
|
enabled_providers: [OPENCODE_GO_PROVIDER],
|
|
12577
12584
|
model: `${OPENCODE_GO_PROVIDER}/${model}`,
|
|
@@ -12585,10 +12592,7 @@ async function opencodeConfig(model) {
|
|
|
12585
12592
|
model: `openrouter/${model}`,
|
|
12586
12593
|
provider: {
|
|
12587
12594
|
openrouter: {
|
|
12588
|
-
models: Object.fromEntries(models.map((candidate) => [candidate, {}]))
|
|
12589
|
-
options: {
|
|
12590
|
-
apiKey: "{env:OPENROUTER_API_KEY}"
|
|
12591
|
-
}
|
|
12595
|
+
models: Object.fromEntries(models.map((candidate) => [candidate, {}]))
|
|
12592
12596
|
}
|
|
12593
12597
|
},
|
|
12594
12598
|
permission: OPENCODE_WORKSPACE_PERMISSION,
|
|
@@ -12752,7 +12756,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
12752
12756
|
constructor(options) {
|
|
12753
12757
|
super(options);
|
|
12754
12758
|
this.sessionId = options.initialSessionId;
|
|
12755
|
-
this.historyFilePath = options.historyFilePath ??
|
|
12759
|
+
this.historyFilePath = options.historyFilePath ?? join19(ENGINE_ENV.HOME_DIR, ".replicas", "opencode", "history.jsonl");
|
|
12756
12760
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
12757
12761
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
12758
12762
|
}
|
|
@@ -12823,7 +12827,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
12823
12827
|
return this.slashCommandsRequest;
|
|
12824
12828
|
}
|
|
12825
12829
|
async ensureClient(model) {
|
|
12826
|
-
const providerId = await
|
|
12830
|
+
const providerId = await hasOpencodeCredentials(OPENCODE_GO_PROVIDER) ? OPENCODE_GO_PROVIDER : "openrouter";
|
|
12827
12831
|
if (this.client && this.providerId !== providerId) {
|
|
12828
12832
|
this.eventAbortController?.abort();
|
|
12829
12833
|
this.server?.close();
|
|
@@ -12836,7 +12840,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
12836
12840
|
if (this.client && (providerId === OPENCODE_GO_PROVIDER || this.configuredModels.has(configuredModel))) {
|
|
12837
12841
|
return this.client;
|
|
12838
12842
|
}
|
|
12839
|
-
if (
|
|
12843
|
+
if (this.providerId !== OPENCODE_GO_PROVIDER && !await hasOpencodeCredentials("openrouter")) {
|
|
12840
12844
|
throw new Error("OpenCode Go or OpenRouter credentials are not configured for Opencode in this workspace.");
|
|
12841
12845
|
}
|
|
12842
12846
|
this.eventAbortController?.abort();
|
|
@@ -13243,7 +13247,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
13243
13247
|
|
|
13244
13248
|
// src/managers/pi-manager.ts
|
|
13245
13249
|
import { mkdir as mkdir13 } from "fs/promises";
|
|
13246
|
-
import { dirname as dirname7, join as
|
|
13250
|
+
import { dirname as dirname7, join as join20 } from "path";
|
|
13247
13251
|
import {
|
|
13248
13252
|
AuthStorage,
|
|
13249
13253
|
createAgentSession,
|
|
@@ -13283,7 +13287,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13283
13287
|
historyFile;
|
|
13284
13288
|
constructor(options) {
|
|
13285
13289
|
super(options);
|
|
13286
|
-
this.historyFilePath = options.historyFilePath ??
|
|
13290
|
+
this.historyFilePath = options.historyFilePath ?? join20(PI_HISTORY_DIR, `${Date.now()}.jsonl`);
|
|
13287
13291
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
13288
13292
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
13289
13293
|
}
|
|
@@ -13310,6 +13314,13 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13310
13314
|
await this.initialized;
|
|
13311
13315
|
return mergeSlashCommands(...(this.session?.promptTemplates ?? []).map((template) => createProviderSlashCommand("pi", template.name, template.description)).filter((command) => Boolean(command)));
|
|
13312
13316
|
}
|
|
13317
|
+
async enqueueMessage(request) {
|
|
13318
|
+
await this.initialized;
|
|
13319
|
+
if (!this.session && !await this.getOpenRouterApiKey()) {
|
|
13320
|
+
throw new Error("OpenRouter authentication is missing for Pi. Add an OpenRouter API key in Settings \u2192 Coding agents.");
|
|
13321
|
+
}
|
|
13322
|
+
return this.messageQueue.enqueue(request);
|
|
13323
|
+
}
|
|
13313
13324
|
dispose() {
|
|
13314
13325
|
this.unsubscribe?.();
|
|
13315
13326
|
this.unsubscribe = null;
|
|
@@ -13327,9 +13338,9 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13327
13338
|
}
|
|
13328
13339
|
return this.session;
|
|
13329
13340
|
}
|
|
13330
|
-
const
|
|
13341
|
+
const authStorage = AuthStorage.create(PI_AUTH_PATH);
|
|
13342
|
+
const apiKey = await this.getOpenRouterApiKey(authStorage);
|
|
13331
13343
|
if (!apiKey) throw new Error("OpenRouter API key is not configured for Pi.");
|
|
13332
|
-
const authStorage = AuthStorage.inMemory({ openrouter: { type: "api_key", key: apiKey } });
|
|
13333
13344
|
const modelRegistry = ModelRegistry.create(authStorage);
|
|
13334
13345
|
const openRouterModels = modelRegistry.getAll().filter((candidate) => candidate.provider === "openrouter");
|
|
13335
13346
|
const modelTemplate = openRouterModels[0];
|
|
@@ -13359,7 +13370,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13359
13370
|
const sessionManager = this.initialSessionId ? SessionManager.open(this.initialSessionId, PI_HISTORY_DIR, this.workingDirectory) : SessionManager.create(this.workingDirectory, PI_HISTORY_DIR);
|
|
13360
13371
|
const resourceLoader = new DefaultResourceLoader({
|
|
13361
13372
|
cwd: this.workingDirectory,
|
|
13362
|
-
agentDir:
|
|
13373
|
+
agentDir: join20(ENGINE_ENV.HOME_DIR, ".pi", "agent"),
|
|
13363
13374
|
extensionFactories: [registerCommandProtection(this.workingDirectory)],
|
|
13364
13375
|
appendSystemPrompt: [this.buildCombinedInstructions() ?? ""]
|
|
13365
13376
|
});
|
|
@@ -13381,6 +13392,10 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13381
13392
|
this.unsubscribe = this.session.subscribe((event) => this.handleEvent(event));
|
|
13382
13393
|
return this.session;
|
|
13383
13394
|
}
|
|
13395
|
+
async getOpenRouterApiKey(authStorage = AuthStorage.create(PI_AUTH_PATH)) {
|
|
13396
|
+
const credential = authStorage.get("openrouter");
|
|
13397
|
+
return credential?.type === "api_key" ? credential.key : void 0;
|
|
13398
|
+
}
|
|
13384
13399
|
handleEvent(event) {
|
|
13385
13400
|
const payload = eventPayload(event);
|
|
13386
13401
|
this.recordHistoryEvent(`pi-${event.type}`, payload, this.historyFile);
|
|
@@ -14064,18 +14079,18 @@ var keepAliveService = new KeepAliveService();
|
|
|
14064
14079
|
|
|
14065
14080
|
// src/services/canvas-service.ts
|
|
14066
14081
|
import { readdir as readdir6, readFile as readFile12, stat as stat3 } from "fs/promises";
|
|
14067
|
-
import { homedir as
|
|
14068
|
-
import { join as
|
|
14082
|
+
import { homedir as homedir14 } from "os";
|
|
14083
|
+
import { join as join21 } from "path";
|
|
14069
14084
|
var GLOBAL_CANVAS_DIRECTORIES = [
|
|
14070
|
-
|
|
14071
|
-
|
|
14072
|
-
|
|
14085
|
+
join21(homedir14(), ".claude", "plans"),
|
|
14086
|
+
join21(process.env.XDG_DATA_HOME ?? join21(homedir14(), ".local", "share"), "opencode", "plans"),
|
|
14087
|
+
join21(homedir14(), ".replicas", "canvas")
|
|
14073
14088
|
];
|
|
14074
14089
|
async function canvasDirectories() {
|
|
14075
14090
|
const repositories = await gitService.listRepositories().catch(() => []);
|
|
14076
14091
|
return [
|
|
14077
14092
|
...GLOBAL_CANVAS_DIRECTORIES,
|
|
14078
|
-
...repositories.map((repository) =>
|
|
14093
|
+
...repositories.map((repository) => join21(repository.path, ".opencode", "plans"))
|
|
14079
14094
|
];
|
|
14080
14095
|
}
|
|
14081
14096
|
var CanvasService = class {
|
|
@@ -14095,7 +14110,7 @@ var CanvasService = class {
|
|
|
14095
14110
|
const { kind } = classifyCanvasFilename(entry.name);
|
|
14096
14111
|
let sizeBytes = 0;
|
|
14097
14112
|
try {
|
|
14098
|
-
const s = await stat3(
|
|
14113
|
+
const s = await stat3(join21(directory, entry.name));
|
|
14099
14114
|
sizeBytes = s.size;
|
|
14100
14115
|
} catch {
|
|
14101
14116
|
continue;
|
|
@@ -14110,7 +14125,7 @@ var CanvasService = class {
|
|
|
14110
14125
|
if (!safe) return null;
|
|
14111
14126
|
const { kind, mimeType } = classifyCanvasFilename(safe);
|
|
14112
14127
|
for (const directory of await canvasDirectories()) {
|
|
14113
|
-
const filePath =
|
|
14128
|
+
const filePath = join21(directory, safe);
|
|
14114
14129
|
let sizeBytes = 0;
|
|
14115
14130
|
let updatedAt = "";
|
|
14116
14131
|
try {
|
|
@@ -14247,13 +14262,13 @@ async function reconcileCanvasItems(filenames) {
|
|
|
14247
14262
|
|
|
14248
14263
|
// src/services/upload-chat-transcripts.ts
|
|
14249
14264
|
import { readdir as readdir7, readFile as readFile13 } from "fs/promises";
|
|
14250
|
-
import { basename as basename2, join as
|
|
14265
|
+
import { basename as basename2, join as join23 } from "path";
|
|
14251
14266
|
|
|
14252
14267
|
// src/services/chat/chat-senders.ts
|
|
14253
|
-
import { join as
|
|
14254
|
-
var CHAT_SENDERS_DIR =
|
|
14268
|
+
import { join as join22 } from "path";
|
|
14269
|
+
var CHAT_SENDERS_DIR = join22(ENGINE_DIR2, "chat-senders");
|
|
14255
14270
|
function chatMessageSendersFilePath(chatId) {
|
|
14256
|
-
return
|
|
14271
|
+
return join22(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
|
|
14257
14272
|
}
|
|
14258
14273
|
function parseChatMessageSendersJsonl(content) {
|
|
14259
14274
|
return content.split("\n").flatMap((line) => {
|
|
@@ -14269,9 +14284,9 @@ function parseChatMessageSendersJsonl(content) {
|
|
|
14269
14284
|
|
|
14270
14285
|
// src/services/upload-chat-transcripts.ts
|
|
14271
14286
|
var HISTORY_DIRS = [
|
|
14272
|
-
|
|
14273
|
-
|
|
14274
|
-
|
|
14287
|
+
join23(ENGINE_DIR2, "claude-histories"),
|
|
14288
|
+
join23(ENGINE_DIR2, "relay-histories"),
|
|
14289
|
+
join23(ENGINE_DIR2, "codex-histories")
|
|
14275
14290
|
];
|
|
14276
14291
|
async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
14277
14292
|
let flushed = 0;
|
|
@@ -14288,7 +14303,7 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
|
14288
14303
|
if (!entry.endsWith(".jsonl")) continue;
|
|
14289
14304
|
const chatId = basename2(entry, ".jsonl");
|
|
14290
14305
|
tasks.push(
|
|
14291
|
-
uploadChatTranscript(chatId,
|
|
14306
|
+
uploadChatTranscript(chatId, join23(dir, entry), chatsById.get(chatId)).then(() => {
|
|
14292
14307
|
flushed++;
|
|
14293
14308
|
}).catch((err) => {
|
|
14294
14309
|
failed++;
|
|
@@ -14378,7 +14393,7 @@ async function flushRepoState() {
|
|
|
14378
14393
|
// src/services/upload-engine-logs.ts
|
|
14379
14394
|
import { createReadStream } from "fs";
|
|
14380
14395
|
import { readdir as readdir8, stat as stat4 } from "fs/promises";
|
|
14381
|
-
import { join as
|
|
14396
|
+
import { join as join24 } from "path";
|
|
14382
14397
|
var MAX_ENGINE_LOG_FLUSH_SESSIONS = 10;
|
|
14383
14398
|
var MAX_ENGINE_LOG_FLUSH_BYTES = 5 * 1024 * 1024;
|
|
14384
14399
|
var ENGINE_LOG_FLUSH_TIMEOUT_MS = 2e4;
|
|
@@ -14407,7 +14422,7 @@ async function flushAllEngineLogs() {
|
|
|
14407
14422
|
const candidates = (await Promise.all(filenames.slice(0, MAX_ENGINE_LOG_FLUSH_SESSIONS).map(async (filename) => {
|
|
14408
14423
|
try {
|
|
14409
14424
|
const sessionId = filename.slice(0, -".log".length);
|
|
14410
|
-
const filePath =
|
|
14425
|
+
const filePath = join24(LOG_DIR, filename);
|
|
14411
14426
|
const fileStat = await runBeforeDeadline(() => stat4(filePath), deadline);
|
|
14412
14427
|
if (!fileStat.isFile()) {
|
|
14413
14428
|
skipped++;
|
|
@@ -14503,17 +14518,16 @@ async function uploadEngineLog(input, timeoutMs) {
|
|
|
14503
14518
|
}
|
|
14504
14519
|
|
|
14505
14520
|
// src/services/chat/chat-service.ts
|
|
14506
|
-
var CODEX_AUTH_PATH2 =
|
|
14507
|
-
var OPENCODE_AUTH_PATH3 = join24(homedir14(), ".local", "share", "opencode", "auth.json");
|
|
14521
|
+
var CODEX_AUTH_PATH2 = join25(homedir15(), ".codex", "auth.json");
|
|
14508
14522
|
var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
|
|
14509
14523
|
function isCodexAvailable() {
|
|
14510
14524
|
return existsSync7(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
|
|
14511
14525
|
}
|
|
14512
14526
|
function isOpencodeAvailable() {
|
|
14513
|
-
return existsSync7(
|
|
14527
|
+
return existsSync7(OPENCODE_AUTH_PATH);
|
|
14514
14528
|
}
|
|
14515
14529
|
function isPiAvailable() {
|
|
14516
|
-
return
|
|
14530
|
+
return existsSync7(PI_AUTH_PATH);
|
|
14517
14531
|
}
|
|
14518
14532
|
function isCursorAvailable() {
|
|
14519
14533
|
return Boolean(ENGINE_ENV.CURSOR_API_KEY);
|
|
@@ -14970,7 +14984,7 @@ var ChatService = class {
|
|
|
14970
14984
|
return descendants;
|
|
14971
14985
|
}
|
|
14972
14986
|
async deleteHistoryFile(persisted) {
|
|
14973
|
-
await rm2(
|
|
14987
|
+
await rm2(join25(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
|
|
14974
14988
|
await rm2(chatMessageSendersFilePath(persisted.id), { force: true });
|
|
14975
14989
|
}
|
|
14976
14990
|
async getChatHistory(chatId, page = {}) {
|
|
@@ -15046,7 +15060,7 @@ var ChatService = class {
|
|
|
15046
15060
|
if (persisted.provider === "claude") {
|
|
15047
15061
|
provider = new ClaudeManager({
|
|
15048
15062
|
workingDirectory: this.workingDirectory,
|
|
15049
|
-
historyFilePath:
|
|
15063
|
+
historyFilePath: join25(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15050
15064
|
initialSessionId: persisted.providerSessionId,
|
|
15051
15065
|
onSaveSessionId: saveSession,
|
|
15052
15066
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15055,7 +15069,7 @@ var ChatService = class {
|
|
|
15055
15069
|
} else if (persisted.provider === "relay") {
|
|
15056
15070
|
provider = new RelayManager({
|
|
15057
15071
|
workingDirectory: this.workingDirectory,
|
|
15058
|
-
historyFilePath:
|
|
15072
|
+
historyFilePath: join25(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15059
15073
|
initialSessionId: persisted.providerSessionId,
|
|
15060
15074
|
onSaveSessionId: saveSession,
|
|
15061
15075
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15069,7 +15083,7 @@ var ChatService = class {
|
|
|
15069
15083
|
} else if (persisted.provider === "cursor") {
|
|
15070
15084
|
provider = new CursorManager({
|
|
15071
15085
|
workingDirectory: this.workingDirectory,
|
|
15072
|
-
historyFilePath:
|
|
15086
|
+
historyFilePath: join25(CURSOR_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15073
15087
|
initialSessionId: persisted.providerSessionId,
|
|
15074
15088
|
onSaveSessionId: saveSession,
|
|
15075
15089
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15078,7 +15092,7 @@ var ChatService = class {
|
|
|
15078
15092
|
} else if (persisted.provider === "opencode") {
|
|
15079
15093
|
provider = new OpencodeManager({
|
|
15080
15094
|
workingDirectory: this.workingDirectory,
|
|
15081
|
-
historyFilePath:
|
|
15095
|
+
historyFilePath: join25(OPENCODE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15082
15096
|
initialSessionId: persisted.providerSessionId,
|
|
15083
15097
|
onSaveSessionId: saveSession,
|
|
15084
15098
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15087,7 +15101,7 @@ var ChatService = class {
|
|
|
15087
15101
|
} else if (persisted.provider === "pi") {
|
|
15088
15102
|
provider = new PiManager({
|
|
15089
15103
|
workingDirectory: this.workingDirectory,
|
|
15090
|
-
historyFilePath:
|
|
15104
|
+
historyFilePath: join25(PI_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15091
15105
|
initialSessionId: persisted.providerSessionId,
|
|
15092
15106
|
onSaveSessionId: saveSession,
|
|
15093
15107
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15096,7 +15110,7 @@ var ChatService = class {
|
|
|
15096
15110
|
} else {
|
|
15097
15111
|
provider = new CodexAspManager({
|
|
15098
15112
|
workingDirectory: this.workingDirectory,
|
|
15099
|
-
historyFilePath:
|
|
15113
|
+
historyFilePath: join25(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15100
15114
|
initialSessionId: persisted.providerSessionId,
|
|
15101
15115
|
onSaveSessionId: saveSession,
|
|
15102
15116
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15245,7 +15259,7 @@ var ChatService = class {
|
|
|
15245
15259
|
});
|
|
15246
15260
|
uploadChatTranscript(
|
|
15247
15261
|
chatId,
|
|
15248
|
-
|
|
15262
|
+
join25(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
|
|
15249
15263
|
this.toSummary(chat)
|
|
15250
15264
|
).catch((err) => {
|
|
15251
15265
|
console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
|
|
@@ -15381,7 +15395,7 @@ var ChatService = class {
|
|
|
15381
15395
|
// src/services/repo-file-service.ts
|
|
15382
15396
|
import { execFile as execFile2 } from "child_process";
|
|
15383
15397
|
import { readFile as readFile15, realpath, stat as stat5 } from "fs/promises";
|
|
15384
|
-
import { join as
|
|
15398
|
+
import { join as join26, resolve as resolve2, extname as extname2 } from "path";
|
|
15385
15399
|
var CACHE_TTL_MS = 3e4;
|
|
15386
15400
|
var SEARCH_TIMEOUT_MS = 15e3;
|
|
15387
15401
|
var MAX_CONTENT_BYTES = 256 * 1024;
|
|
@@ -15541,7 +15555,7 @@ var RepoFileService = class {
|
|
|
15541
15555
|
const repo = repos.find((r) => r.name === repoName);
|
|
15542
15556
|
if (!repo) return null;
|
|
15543
15557
|
try {
|
|
15544
|
-
const fullPath = await realpath(resolve2(
|
|
15558
|
+
const fullPath = await realpath(resolve2(join26(repo.path, filePath)));
|
|
15545
15559
|
const repoRoot = await realpath(repo.path);
|
|
15546
15560
|
const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
|
|
15547
15561
|
if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
|
|
@@ -15649,20 +15663,20 @@ var RepoFileService = class {
|
|
|
15649
15663
|
import { Hono } from "hono";
|
|
15650
15664
|
import { z as z7 } from "zod";
|
|
15651
15665
|
import { readdir as readdir10, stat as stat6, readFile as readFile18 } from "fs/promises";
|
|
15652
|
-
import { join as
|
|
15666
|
+
import { join as join29, resolve as resolve3 } from "path";
|
|
15653
15667
|
|
|
15654
15668
|
// src/services/warm-hooks-service.ts
|
|
15655
15669
|
import { spawn as spawn4 } from "child_process";
|
|
15656
15670
|
import { readFile as readFile17 } from "fs/promises";
|
|
15657
15671
|
import { existsSync as existsSync8 } from "fs";
|
|
15658
|
-
import { join as
|
|
15672
|
+
import { join as join28 } from "path";
|
|
15659
15673
|
|
|
15660
15674
|
// src/services/warm-hook-logs-service.ts
|
|
15661
15675
|
import { mkdir as mkdir15, readFile as readFile16, writeFile as writeFile6, readdir as readdir9, appendFile as appendFile4, unlink as unlink3 } from "fs/promises";
|
|
15662
|
-
import { homedir as
|
|
15663
|
-
import { join as
|
|
15664
|
-
var LOGS_DIR2 =
|
|
15665
|
-
var CURRENT_RUN_LOG =
|
|
15676
|
+
import { homedir as homedir16 } from "os";
|
|
15677
|
+
import { join as join27 } from "path";
|
|
15678
|
+
var LOGS_DIR2 = join27(homedir16(), ".replicas", "warm-hook-logs");
|
|
15679
|
+
var CURRENT_RUN_LOG = join27(LOGS_DIR2, "current-run.log");
|
|
15666
15680
|
var GLOBAL_FILENAME = "global.json";
|
|
15667
15681
|
function withPreview2(stored) {
|
|
15668
15682
|
const preview = buildHookOutputPreview(stored.output);
|
|
@@ -15679,7 +15693,7 @@ var WarmHookLogsService = class {
|
|
|
15679
15693
|
hookName: "organization",
|
|
15680
15694
|
...entry
|
|
15681
15695
|
};
|
|
15682
|
-
await writeFile6(
|
|
15696
|
+
await writeFile6(join27(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
15683
15697
|
`, "utf-8");
|
|
15684
15698
|
}
|
|
15685
15699
|
async saveEnvironmentHookLog(entry) {
|
|
@@ -15689,7 +15703,7 @@ var WarmHookLogsService = class {
|
|
|
15689
15703
|
hookName: "environment",
|
|
15690
15704
|
...entry
|
|
15691
15705
|
};
|
|
15692
|
-
await writeFile6(
|
|
15706
|
+
await writeFile6(join27(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
15693
15707
|
`, "utf-8");
|
|
15694
15708
|
}
|
|
15695
15709
|
async saveRepoHookLog(repoName, entry) {
|
|
@@ -15699,7 +15713,7 @@ var WarmHookLogsService = class {
|
|
|
15699
15713
|
hookName: repoName,
|
|
15700
15714
|
...entry
|
|
15701
15715
|
};
|
|
15702
|
-
await writeFile6(
|
|
15716
|
+
await writeFile6(join27(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
|
|
15703
15717
|
`, "utf-8");
|
|
15704
15718
|
}
|
|
15705
15719
|
async getAllLogs() {
|
|
@@ -15718,7 +15732,7 @@ var WarmHookLogsService = class {
|
|
|
15718
15732
|
continue;
|
|
15719
15733
|
}
|
|
15720
15734
|
try {
|
|
15721
|
-
const raw = await readFile16(
|
|
15735
|
+
const raw = await readFile16(join27(LOGS_DIR2, file), "utf-8");
|
|
15722
15736
|
const stored = JSON.parse(raw);
|
|
15723
15737
|
logs.push(withPreview2(stored));
|
|
15724
15738
|
} catch {
|
|
@@ -15756,7 +15770,7 @@ var WarmHookLogsService = class {
|
|
|
15756
15770
|
async getFullOutput(hookType, hookName) {
|
|
15757
15771
|
const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
15758
15772
|
try {
|
|
15759
|
-
const raw = await readFile16(
|
|
15773
|
+
const raw = await readFile16(join27(LOGS_DIR2, filename), "utf-8");
|
|
15760
15774
|
const stored = JSON.parse(raw);
|
|
15761
15775
|
if (stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
15762
15776
|
return null;
|
|
@@ -15775,7 +15789,7 @@ var warmHookLogsService = new WarmHookLogsService();
|
|
|
15775
15789
|
// src/services/warm-hooks-service.ts
|
|
15776
15790
|
async function readRepoWarmHook(repoPath) {
|
|
15777
15791
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
15778
|
-
const configPath =
|
|
15792
|
+
const configPath = join28(repoPath, filename);
|
|
15779
15793
|
if (!existsSync8(configPath)) {
|
|
15780
15794
|
continue;
|
|
15781
15795
|
}
|
|
@@ -17008,7 +17022,7 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
17008
17022
|
const logFiles = files.filter((f) => f.endsWith(".log"));
|
|
17009
17023
|
const sessions = await Promise.all(
|
|
17010
17024
|
logFiles.map(async (filename) => {
|
|
17011
|
-
const filePath =
|
|
17025
|
+
const filePath = join29(LOG_DIR, filename);
|
|
17012
17026
|
const fileStat = await stat6(filePath);
|
|
17013
17027
|
const sessionId = filename.replace(/\.log$/, "");
|
|
17014
17028
|
return {
|