replicas-engine 0.1.500 → 0.1.502
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 +170 -136
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -611,7 +611,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
611
611
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
612
612
|
|
|
613
613
|
// ../shared/src/e2b.ts
|
|
614
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-25-
|
|
614
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-25-v4";
|
|
615
615
|
|
|
616
616
|
// ../shared/src/runtime-env.ts
|
|
617
617
|
function shellQuotePosix(value) {
|
|
@@ -772,6 +772,11 @@ var SLASH_COMMANDS = [
|
|
|
772
772
|
description: "Set, pause, resume, or clear a task goal.",
|
|
773
773
|
argumentHint: "<objective | pause | resume | clear>",
|
|
774
774
|
providers: ["codex"]
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
command: "/compact",
|
|
778
|
+
description: "Compact the conversation context.",
|
|
779
|
+
providers: ["codex"]
|
|
775
780
|
}
|
|
776
781
|
];
|
|
777
782
|
function mergeSlashCommands(...commandGroups) {
|
|
@@ -4855,7 +4860,6 @@ function loadEngineEnv() {
|
|
|
4855
4860
|
ANTHROPIC_API_KEY: readEnv("ANTHROPIC_API_KEY"),
|
|
4856
4861
|
OPENAI_API_KEY: readEnv("OPENAI_API_KEY"),
|
|
4857
4862
|
CURSOR_API_KEY: readEnv("CURSOR_API_KEY"),
|
|
4858
|
-
OPENROUTER_API_KEY: readEnv("OPENROUTER_API_KEY"),
|
|
4859
4863
|
CLAUDE_CODE_USE_BEDROCK: readEnv("CLAUDE_CODE_USE_BEDROCK"),
|
|
4860
4864
|
AWS_ACCESS_KEY_ID: readEnv("AWS_ACCESS_KEY_ID"),
|
|
4861
4865
|
AWS_SECRET_ACCESS_KEY: readEnv("AWS_SECRET_ACCESS_KEY"),
|
|
@@ -6299,22 +6303,29 @@ var engineLogger = new EngineLogger();
|
|
|
6299
6303
|
// src/services/replicas-config-service.ts
|
|
6300
6304
|
import { readFile as readFile6, appendFile, writeFile as writeFile4, mkdir as mkdir6 } from "fs/promises";
|
|
6301
6305
|
import { existsSync as existsSync3 } from "fs";
|
|
6302
|
-
import { join as
|
|
6303
|
-
import { homedir as
|
|
6306
|
+
import { join as join10 } from "path";
|
|
6307
|
+
import { homedir as homedir8 } from "os";
|
|
6304
6308
|
import { spawn as spawn2 } from "child_process";
|
|
6305
6309
|
|
|
6306
6310
|
// src/services/environment-details-service.ts
|
|
6307
6311
|
import { mkdir as mkdir4, readFile as readFile4 } from "fs/promises";
|
|
6308
6312
|
import { existsSync as existsSync2 } from "fs";
|
|
6313
|
+
import { homedir as homedir6 } from "os";
|
|
6314
|
+
import { join as join8 } from "path";
|
|
6315
|
+
|
|
6316
|
+
// src/managers/agent-auth-paths.ts
|
|
6309
6317
|
import { homedir as homedir5 } from "os";
|
|
6310
6318
|
import { join as join7 } from "path";
|
|
6311
|
-
var REPLICAS_DIR = join7(homedir5(), ".replicas");
|
|
6312
|
-
var DETAILS_FILE = join7(REPLICAS_DIR, "environment-details.json");
|
|
6313
|
-
var CLAUDE_CREDENTIALS_PATH = join7(homedir5(), ".claude", ".credentials.json");
|
|
6314
|
-
var CODEX_AUTH_PATH = join7(homedir5(), ".codex", "auth.json");
|
|
6315
6319
|
var OPENCODE_AUTH_PATH = join7(homedir5(), ".local", "share", "opencode", "auth.json");
|
|
6316
|
-
var
|
|
6317
|
-
|
|
6320
|
+
var PI_AUTH_PATH = join7(homedir5(), ".pi", "agent", "auth.json");
|
|
6321
|
+
|
|
6322
|
+
// src/services/environment-details-service.ts
|
|
6323
|
+
var REPLICAS_DIR = join8(homedir6(), ".replicas");
|
|
6324
|
+
var DETAILS_FILE = join8(REPLICAS_DIR, "environment-details.json");
|
|
6325
|
+
var CLAUDE_CREDENTIALS_PATH = join8(homedir6(), ".claude", ".credentials.json");
|
|
6326
|
+
var CODEX_AUTH_PATH = join8(homedir6(), ".codex", "auth.json");
|
|
6327
|
+
var GH_HOSTS_PATH = join8(homedir6(), ".config", "gh", "hosts.yml");
|
|
6328
|
+
var GIT_CREDENTIALS_PATH = join8(homedir6(), ".git-credentials");
|
|
6318
6329
|
function detectClaudeAuthMethod() {
|
|
6319
6330
|
if (existsSync2(CLAUDE_CREDENTIALS_PATH)) {
|
|
6320
6331
|
return "oauth";
|
|
@@ -6344,10 +6355,10 @@ function detectCursorAuthMethod() {
|
|
|
6344
6355
|
return ENGINE_ENV.CURSOR_API_KEY ? "api_key" : "none";
|
|
6345
6356
|
}
|
|
6346
6357
|
function detectOpencodeAuthMethod() {
|
|
6347
|
-
return existsSync2(OPENCODE_AUTH_PATH)
|
|
6358
|
+
return existsSync2(OPENCODE_AUTH_PATH) ? "api_key" : "none";
|
|
6348
6359
|
}
|
|
6349
6360
|
function detectPiAuthMethod() {
|
|
6350
|
-
return
|
|
6361
|
+
return existsSync2(PI_AUTH_PATH) ? "api_key" : "none";
|
|
6351
6362
|
}
|
|
6352
6363
|
async function detectGitIdentityConfigured() {
|
|
6353
6364
|
try {
|
|
@@ -6520,8 +6531,8 @@ var environmentDetailsService = new EnvironmentDetailsService();
|
|
|
6520
6531
|
|
|
6521
6532
|
// src/services/start-hook-logs-service.ts
|
|
6522
6533
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile3, readdir as readdir2 } from "fs/promises";
|
|
6523
|
-
import { homedir as
|
|
6524
|
-
import { join as
|
|
6534
|
+
import { homedir as homedir7 } from "os";
|
|
6535
|
+
import { join as join9 } from "path";
|
|
6525
6536
|
|
|
6526
6537
|
// src/services/hook-log-files.ts
|
|
6527
6538
|
import { createHash } from "crypto";
|
|
@@ -6533,7 +6544,7 @@ function repoHookLogFilename(repoName) {
|
|
|
6533
6544
|
}
|
|
6534
6545
|
|
|
6535
6546
|
// src/services/start-hook-logs-service.ts
|
|
6536
|
-
var LOGS_DIR =
|
|
6547
|
+
var LOGS_DIR = join9(homedir7(), ".replicas", "start-hook-logs");
|
|
6537
6548
|
function withPreview(stored) {
|
|
6538
6549
|
const preview = buildHookOutputPreview(stored.output);
|
|
6539
6550
|
return { ...stored, ...preview };
|
|
@@ -6571,7 +6582,7 @@ var StartHookLogsService = class {
|
|
|
6571
6582
|
await this.ensureDir();
|
|
6572
6583
|
const log = { hookType, hookName, repoName: hookName, ...entry };
|
|
6573
6584
|
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
6574
|
-
await writeFile3(
|
|
6585
|
+
await writeFile3(join9(LOGS_DIR, filename), `${JSON.stringify(log, null, 2)}
|
|
6575
6586
|
`, "utf-8");
|
|
6576
6587
|
}
|
|
6577
6588
|
async saveEnvironmentLog(entry) {
|
|
@@ -6596,7 +6607,7 @@ var StartHookLogsService = class {
|
|
|
6596
6607
|
continue;
|
|
6597
6608
|
}
|
|
6598
6609
|
try {
|
|
6599
|
-
const raw = await readFile5(
|
|
6610
|
+
const raw = await readFile5(join9(LOGS_DIR, file), "utf-8");
|
|
6600
6611
|
const stored = normalizeStored(JSON.parse(raw));
|
|
6601
6612
|
if (stored) {
|
|
6602
6613
|
logs.push(withPreview(stored));
|
|
@@ -6615,7 +6626,7 @@ var StartHookLogsService = class {
|
|
|
6615
6626
|
async getFullOutput(hookType, hookName) {
|
|
6616
6627
|
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
6617
6628
|
try {
|
|
6618
|
-
const raw = await readFile5(
|
|
6629
|
+
const raw = await readFile5(join9(LOGS_DIR, filename), "utf-8");
|
|
6619
6630
|
const stored = normalizeStored(JSON.parse(raw));
|
|
6620
6631
|
if (!stored || stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
6621
6632
|
return null;
|
|
@@ -6632,7 +6643,7 @@ var StartHookLogsService = class {
|
|
|
6632
6643
|
var startHookLogsService = new StartHookLogsService();
|
|
6633
6644
|
|
|
6634
6645
|
// src/services/replicas-config-service.ts
|
|
6635
|
-
var START_HOOKS_LOG =
|
|
6646
|
+
var START_HOOKS_LOG = join10(homedir8(), ".replicas", "startHooks.log");
|
|
6636
6647
|
var START_HOOKS_RUNNING_PROMPT = `IMPORTANT - Start Hooks Running:
|
|
6637
6648
|
Start hooks are shell commands/scripts set by repository owners that run on workspace startup.
|
|
6638
6649
|
These hooks are currently executing in the background. You can:
|
|
@@ -6643,7 +6654,7 @@ The start hooks may install dependencies, build projects, or perform other setup
|
|
|
6643
6654
|
If your task depends on setup being complete, check the log file before proceeding.`;
|
|
6644
6655
|
async function readReplicasConfigFromDir(dirPath) {
|
|
6645
6656
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
6646
|
-
const configPath =
|
|
6657
|
+
const configPath = join10(dirPath, filename);
|
|
6647
6658
|
if (!existsSync3(configPath)) {
|
|
6648
6659
|
continue;
|
|
6649
6660
|
}
|
|
@@ -6713,7 +6724,7 @@ var ReplicasConfigService = class {
|
|
|
6713
6724
|
const logLine = `[${timestamp}] ${message}
|
|
6714
6725
|
`;
|
|
6715
6726
|
try {
|
|
6716
|
-
await mkdir6(
|
|
6727
|
+
await mkdir6(join10(homedir8(), ".replicas"), { recursive: true });
|
|
6717
6728
|
await appendFile(START_HOOKS_LOG, logLine, "utf-8");
|
|
6718
6729
|
} catch (error) {
|
|
6719
6730
|
console.error("Failed to write to start hooks log:", error);
|
|
@@ -6725,7 +6736,7 @@ var ReplicasConfigService = class {
|
|
|
6725
6736
|
command: params.content,
|
|
6726
6737
|
label: "env start hook",
|
|
6727
6738
|
repoName: "environment",
|
|
6728
|
-
cwd:
|
|
6739
|
+
cwd: homedir8(),
|
|
6729
6740
|
timeout: params.timeoutMs ?? DEFAULT_START_HOOK_TIMEOUT_MS,
|
|
6730
6741
|
onOutputChunk: params.onOutputChunk
|
|
6731
6742
|
});
|
|
@@ -6848,7 +6859,7 @@ var ReplicasConfigService = class {
|
|
|
6848
6859
|
this.hooksCompleted = false;
|
|
6849
6860
|
this.hooksFailed = false;
|
|
6850
6861
|
try {
|
|
6851
|
-
await mkdir6(
|
|
6862
|
+
await mkdir6(join10(homedir8(), ".replicas"), { recursive: true });
|
|
6852
6863
|
await writeFile4(
|
|
6853
6864
|
START_HOOKS_LOG,
|
|
6854
6865
|
`=== Start Hooks Execution Log ===
|
|
@@ -7043,11 +7054,11 @@ var replicasConfigService = new ReplicasConfigService();
|
|
|
7043
7054
|
|
|
7044
7055
|
// src/services/event-service.ts
|
|
7045
7056
|
import { mkdir as mkdir7 } from "fs/promises";
|
|
7046
|
-
import { homedir as
|
|
7047
|
-
import { join as
|
|
7057
|
+
import { homedir as homedir9 } from "os";
|
|
7058
|
+
import { join as join11 } from "path";
|
|
7048
7059
|
import { randomUUID } from "crypto";
|
|
7049
|
-
var ENGINE_DIR =
|
|
7050
|
-
var EVENTS_FILE =
|
|
7060
|
+
var ENGINE_DIR = join11(homedir9(), ".replicas", "engine");
|
|
7061
|
+
var EVENTS_FILE = join11(ENGINE_DIR, "events.jsonl");
|
|
7051
7062
|
var EventService = class {
|
|
7052
7063
|
subscribers = /* @__PURE__ */ new Map();
|
|
7053
7064
|
writer = new StreamWriter();
|
|
@@ -7081,9 +7092,9 @@ var eventService = new EventService();
|
|
|
7081
7092
|
import { mkdir as mkdir8, readFile as readFile7 } from "fs/promises";
|
|
7082
7093
|
import { existsSync as existsSync4 } from "fs";
|
|
7083
7094
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
7084
|
-
import { homedir as
|
|
7085
|
-
import { dirname as dirname2, join as
|
|
7086
|
-
var PREVIEW_PORTS_FILE =
|
|
7095
|
+
import { homedir as homedir10 } from "os";
|
|
7096
|
+
import { dirname as dirname2, join as join12 } from "path";
|
|
7097
|
+
var PREVIEW_PORTS_FILE = join12(homedir10(), ".replicas", "preview-ports.json");
|
|
7087
7098
|
async function readPreviewsFile() {
|
|
7088
7099
|
try {
|
|
7089
7100
|
if (!existsSync4(PREVIEW_PORTS_FILE)) {
|
|
@@ -7195,8 +7206,8 @@ async function registerDesktopPreview() {
|
|
|
7195
7206
|
// src/services/chat/chat-service.ts
|
|
7196
7207
|
import { existsSync as existsSync7 } from "fs";
|
|
7197
7208
|
import { appendFile as appendFile3, copyFile, mkdir as mkdir14, readFile as readFile14, rename as rename2, rm as rm2 } from "fs/promises";
|
|
7198
|
-
import { homedir as
|
|
7199
|
-
import { join as
|
|
7209
|
+
import { homedir as homedir15 } from "os";
|
|
7210
|
+
import { join as join25 } from "path";
|
|
7200
7211
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
7201
7212
|
|
|
7202
7213
|
// src/managers/claude-manager.ts
|
|
@@ -7204,9 +7215,9 @@ import {
|
|
|
7204
7215
|
query
|
|
7205
7216
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
7206
7217
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
7207
|
-
import { dirname as dirname4, join as
|
|
7218
|
+
import { dirname as dirname4, join as join15 } from "path";
|
|
7208
7219
|
import { mkdir as mkdir10 } from "fs/promises";
|
|
7209
|
-
import { homedir as
|
|
7220
|
+
import { homedir as homedir12 } from "os";
|
|
7210
7221
|
|
|
7211
7222
|
// src/utils/linear-converter.ts
|
|
7212
7223
|
function linearThoughtToResponse(thought) {
|
|
@@ -7592,8 +7603,8 @@ function extractPlanFromCodexAspNotification(notification) {
|
|
|
7592
7603
|
// src/utils/image-utils.ts
|
|
7593
7604
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
7594
7605
|
import { mkdir as mkdir9, unlink as unlink2, writeFile as writeFile5 } from "fs/promises";
|
|
7595
|
-
import { homedir as
|
|
7596
|
-
import { join as
|
|
7606
|
+
import { homedir as homedir11 } from "os";
|
|
7607
|
+
import { join as join13 } from "path";
|
|
7597
7608
|
function isImageMediaType(value) {
|
|
7598
7609
|
return IMAGE_MEDIA_TYPES.includes(value);
|
|
7599
7610
|
}
|
|
@@ -7693,14 +7704,14 @@ async function normalizeImages(images) {
|
|
|
7693
7704
|
}
|
|
7694
7705
|
return normalized;
|
|
7695
7706
|
}
|
|
7696
|
-
async function saveNormalizedImagesToTempFiles(images, tempImageDir =
|
|
7707
|
+
async function saveNormalizedImagesToTempFiles(images, tempImageDir = join13(homedir11(), ".replicas", "codex", "temp-images")) {
|
|
7697
7708
|
await mkdir9(tempImageDir, { recursive: true });
|
|
7698
7709
|
const tempPaths = [];
|
|
7699
7710
|
try {
|
|
7700
7711
|
for (const image of images) {
|
|
7701
7712
|
const ext = image.source.media_type.split("/")[1] || "png";
|
|
7702
7713
|
const filename = `img_${randomUUID3()}.${ext}`;
|
|
7703
|
-
const filepath =
|
|
7714
|
+
const filepath = join13(tempImageDir, filename);
|
|
7704
7715
|
await writeFile5(filepath, Buffer.from(image.source.data, "base64"));
|
|
7705
7716
|
tempPaths.push(filepath);
|
|
7706
7717
|
}
|
|
@@ -8285,7 +8296,7 @@ function reportCommandProtectionBlock(options) {
|
|
|
8285
8296
|
|
|
8286
8297
|
// src/services/skill-registry-service.ts
|
|
8287
8298
|
import { readFile as readFile8, readdir as readdir3, stat as stat2 } from "fs/promises";
|
|
8288
|
-
import { dirname as dirname3, isAbsolute, join as
|
|
8299
|
+
import { dirname as dirname3, isAbsolute, join as join14, relative, resolve } from "path";
|
|
8289
8300
|
var REGISTRY_ROOT_DIR = ".replicas/skill-registries";
|
|
8290
8301
|
var REGISTRY_MANIFEST = "manifest.json";
|
|
8291
8302
|
async function getSkillRegistryInventory(homeDir) {
|
|
@@ -8346,10 +8357,10 @@ async function scanRegistry(registryDir) {
|
|
|
8346
8357
|
}
|
|
8347
8358
|
async function findSkillCollections(registryDir) {
|
|
8348
8359
|
const candidateRoots = [
|
|
8349
|
-
{ source: "skills", root:
|
|
8350
|
-
{ source: "agents", root:
|
|
8351
|
-
{ source: "codex", root:
|
|
8352
|
-
{ source: "claude", root:
|
|
8360
|
+
{ source: "skills", root: join14(registryDir, "skills") },
|
|
8361
|
+
{ source: "agents", root: join14(registryDir, ".agents", "skills") },
|
|
8362
|
+
{ source: "codex", root: join14(registryDir, ".codex", "skills") },
|
|
8363
|
+
{ source: "claude", root: join14(registryDir, ".claude", "skills") }
|
|
8353
8364
|
];
|
|
8354
8365
|
const collections = [];
|
|
8355
8366
|
for (const { source, root } of candidateRoots) {
|
|
@@ -8363,9 +8374,9 @@ async function findSkillCollections(registryDir) {
|
|
|
8363
8374
|
async function findSkillDirsInRoot(root) {
|
|
8364
8375
|
const skillDirs = [];
|
|
8365
8376
|
for (const dirent of await safeReadDir(root)) {
|
|
8366
|
-
const skillDir =
|
|
8377
|
+
const skillDir = join14(root, dirent.name);
|
|
8367
8378
|
if (!await isDirectoryDirent(dirent, skillDir)) continue;
|
|
8368
|
-
if (await fileExists(
|
|
8379
|
+
if (await fileExists(join14(skillDir, "SKILL.md"))) {
|
|
8369
8380
|
skillDirs.push(skillDir);
|
|
8370
8381
|
}
|
|
8371
8382
|
}
|
|
@@ -8375,9 +8386,9 @@ async function findTopLevelSkills(registryDir) {
|
|
|
8375
8386
|
const skills = [];
|
|
8376
8387
|
for (const dirent of await safeReadDir(registryDir)) {
|
|
8377
8388
|
if (dirent.name.startsWith(".") || dirent.name === "skills" || dirent.name === "plugins") continue;
|
|
8378
|
-
const skillDir =
|
|
8389
|
+
const skillDir = join14(registryDir, dirent.name);
|
|
8379
8390
|
if (!await isDirectoryDirent(dirent, skillDir)) continue;
|
|
8380
|
-
if (await fileExists(
|
|
8391
|
+
if (await fileExists(join14(skillDir, "SKILL.md"))) {
|
|
8381
8392
|
skills.push({ source: "root", skillDir });
|
|
8382
8393
|
}
|
|
8383
8394
|
}
|
|
@@ -8388,10 +8399,10 @@ async function findClaudePluginRoots(registryDir) {
|
|
|
8388
8399
|
async function walk(dir) {
|
|
8389
8400
|
for (const dirent of await safeReadDir(dir)) {
|
|
8390
8401
|
if (dirent.name === ".git") continue;
|
|
8391
|
-
const child =
|
|
8402
|
+
const child = join14(dir, dirent.name);
|
|
8392
8403
|
if (!await isDirectoryDirent(dirent, child)) continue;
|
|
8393
8404
|
if (dirent.name === ".claude-plugin") {
|
|
8394
|
-
if (await fileExists(
|
|
8405
|
+
if (await fileExists(join14(child, "plugin.json"))) {
|
|
8395
8406
|
roots.push(dirname3(child));
|
|
8396
8407
|
}
|
|
8397
8408
|
continue;
|
|
@@ -8403,7 +8414,7 @@ async function findClaudePluginRoots(registryDir) {
|
|
|
8403
8414
|
return uniqueStrings(roots);
|
|
8404
8415
|
}
|
|
8405
8416
|
async function hasCodexMarketplace(registryDir) {
|
|
8406
|
-
return await fileExists(
|
|
8417
|
+
return await fileExists(join14(registryDir, ".agents", "plugins", "marketplace.json")) || await fileExists(join14(registryDir, ".codex", "plugins", "marketplace.json"));
|
|
8407
8418
|
}
|
|
8408
8419
|
async function installCodexRegistryPlugins(client, inventory) {
|
|
8409
8420
|
const cwds = inventory.codexMarketplaceCwds;
|
|
@@ -8453,10 +8464,10 @@ function isSkillRegistryEntry(value) {
|
|
|
8453
8464
|
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";
|
|
8454
8465
|
}
|
|
8455
8466
|
function getRegistryRoot(homeDir) {
|
|
8456
|
-
return
|
|
8467
|
+
return join14(homeDir, REGISTRY_ROOT_DIR);
|
|
8457
8468
|
}
|
|
8458
8469
|
function getManifestPath(homeDir) {
|
|
8459
|
-
return
|
|
8470
|
+
return join14(getRegistryRoot(homeDir), REGISTRY_MANIFEST);
|
|
8460
8471
|
}
|
|
8461
8472
|
function emptyInventory(registryRoot) {
|
|
8462
8473
|
return {
|
|
@@ -8803,7 +8814,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
8803
8814
|
authRetrying = false;
|
|
8804
8815
|
constructor(options) {
|
|
8805
8816
|
super(options);
|
|
8806
|
-
this.historyFilePath = options.historyFilePath ??
|
|
8817
|
+
this.historyFilePath = options.historyFilePath ?? join15(homedir12(), ".replicas", "claude", "history.jsonl");
|
|
8807
8818
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
8808
8819
|
this.systemPromptOverride = options.systemPromptOverride;
|
|
8809
8820
|
this.toolsOverride = options.tools;
|
|
@@ -9735,7 +9746,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
9735
9746
|
|
|
9736
9747
|
// src/managers/codex-asp/codex-asp-manager.ts
|
|
9737
9748
|
import { readdir as readdir4 } from "fs/promises";
|
|
9738
|
-
import { join as
|
|
9749
|
+
import { join as join17 } from "path";
|
|
9739
9750
|
|
|
9740
9751
|
// src/managers/codex-asp/app-server-process.ts
|
|
9741
9752
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -9936,7 +9947,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
|
9936
9947
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
9937
9948
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
9938
9949
|
var codexCliVersionEnsured = null;
|
|
9939
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
9950
|
+
var ENGINE_PACKAGE_VERSION = "0.1.502";
|
|
9940
9951
|
var INITIALIZE_METHOD = "initialize";
|
|
9941
9952
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
9942
9953
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -10230,6 +10241,7 @@ var THREAD_READ_METHOD = "thread/read";
|
|
|
10230
10241
|
var THREAD_GOAL_SET_METHOD = "thread/goal/set";
|
|
10231
10242
|
var THREAD_GOAL_GET_METHOD = "thread/goal/get";
|
|
10232
10243
|
var THREAD_GOAL_CLEAR_METHOD = "thread/goal/clear";
|
|
10244
|
+
var THREAD_COMPACT_START_METHOD = "thread/compact/start";
|
|
10233
10245
|
var THREAD_SETTINGS_UPDATE_METHOD = "thread/settings/update";
|
|
10234
10246
|
var TURN_START_METHOD = "turn/start";
|
|
10235
10247
|
var TURN_INTERRUPT_METHOD = "turn/interrupt";
|
|
@@ -10861,16 +10873,16 @@ var TranscriptUpdateCoalescer = class {
|
|
|
10861
10873
|
};
|
|
10862
10874
|
|
|
10863
10875
|
// src/services/chat/history-paths.ts
|
|
10864
|
-
import { homedir as
|
|
10865
|
-
import { join as
|
|
10866
|
-
var ENGINE_DIR2 =
|
|
10867
|
-
var CHATS_FILE =
|
|
10868
|
-
var CLAUDE_HISTORY_DIR =
|
|
10869
|
-
var RELAY_HISTORY_DIR =
|
|
10870
|
-
var CODEX_HISTORY_DIR =
|
|
10871
|
-
var CURSOR_HISTORY_DIR =
|
|
10872
|
-
var OPENCODE_HISTORY_DIR =
|
|
10873
|
-
var PI_HISTORY_DIR =
|
|
10876
|
+
import { homedir as homedir13 } from "os";
|
|
10877
|
+
import { join as join16 } from "path";
|
|
10878
|
+
var ENGINE_DIR2 = join16(homedir13(), ".replicas", "engine");
|
|
10879
|
+
var CHATS_FILE = join16(ENGINE_DIR2, "chats.json");
|
|
10880
|
+
var CLAUDE_HISTORY_DIR = join16(ENGINE_DIR2, "claude-histories");
|
|
10881
|
+
var RELAY_HISTORY_DIR = join16(ENGINE_DIR2, "relay-histories");
|
|
10882
|
+
var CODEX_HISTORY_DIR = join16(ENGINE_DIR2, "codex-histories");
|
|
10883
|
+
var CURSOR_HISTORY_DIR = join16(ENGINE_DIR2, "cursor-histories");
|
|
10884
|
+
var OPENCODE_HISTORY_DIR = join16(ENGINE_DIR2, "opencode-histories");
|
|
10885
|
+
var PI_HISTORY_DIR = join16(ENGINE_DIR2, "pi-histories");
|
|
10874
10886
|
var HISTORY_DIR_BY_PROVIDER = {
|
|
10875
10887
|
claude: CLAUDE_HISTORY_DIR,
|
|
10876
10888
|
relay: RELAY_HISTORY_DIR,
|
|
@@ -10916,7 +10928,7 @@ async function readCodexAspThreadHistory(threadId) {
|
|
|
10916
10928
|
}
|
|
10917
10929
|
for (const entry of entries) {
|
|
10918
10930
|
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
10919
|
-
const history = await new CodexHistoryFile(
|
|
10931
|
+
const history = await new CodexHistoryFile(join17(CODEX_HISTORY_DIR, entry.name)).load();
|
|
10920
10932
|
const transcript = history.transcriptsByThreadId.get(threadId);
|
|
10921
10933
|
if (transcript) {
|
|
10922
10934
|
return {
|
|
@@ -10956,6 +10968,9 @@ function skillsListToSlashCommands(response) {
|
|
|
10956
10968
|
}))
|
|
10957
10969
|
);
|
|
10958
10970
|
}
|
|
10971
|
+
function isCompactCommand(message) {
|
|
10972
|
+
return /^\/compact$/i.test(message.trim());
|
|
10973
|
+
}
|
|
10959
10974
|
var CodexAspManager = class extends CodingAgentManager {
|
|
10960
10975
|
currentThreadId = null;
|
|
10961
10976
|
activeTurnId = null;
|
|
@@ -11019,7 +11034,7 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
11019
11034
|
const expectedTurnId = this.activeTurnId;
|
|
11020
11035
|
if (!threadId || !expectedTurnId || !this.messageQueue.isProcessing()) return false;
|
|
11021
11036
|
if (this.isCompacting()) return false;
|
|
11022
|
-
if (getGoalCommand(request.message, request.goalMode)) return false;
|
|
11037
|
+
if (getGoalCommand(request.message, request.goalMode) || isCompactCommand(request.message)) return false;
|
|
11023
11038
|
const { input, tempImagePaths } = await buildTurnInput(request);
|
|
11024
11039
|
try {
|
|
11025
11040
|
const host = await getCodexAspHost();
|
|
@@ -11163,6 +11178,19 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
11163
11178
|
};
|
|
11164
11179
|
const goalCommand = getGoalCommand(request.message, request.goalMode);
|
|
11165
11180
|
const dispatch = async () => {
|
|
11181
|
+
if (isCompactCommand(request.message)) {
|
|
11182
|
+
await this.executeAspTurn(request, recordUserMessage, {
|
|
11183
|
+
runTurn: (host, threadId) => this.observeTurn(host, threadId, request, async () => {
|
|
11184
|
+
await host.client.request(
|
|
11185
|
+
THREAD_COMPACT_START_METHOD,
|
|
11186
|
+
{ threadId }
|
|
11187
|
+
);
|
|
11188
|
+
return { turn: null, tempImagePaths: [] };
|
|
11189
|
+
}),
|
|
11190
|
+
userMessagePayload: { command: "compact" }
|
|
11191
|
+
});
|
|
11192
|
+
return;
|
|
11193
|
+
}
|
|
11166
11194
|
if (goalCommand?.type === "clear") {
|
|
11167
11195
|
await this.executeGoalClearCommand(request, recordUserMessage);
|
|
11168
11196
|
return;
|
|
@@ -12133,7 +12161,7 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12133
12161
|
|
|
12134
12162
|
// src/managers/cursor-manager.ts
|
|
12135
12163
|
import { mkdir as mkdir11, readFile as readFile10, readdir as readdir5 } from "fs/promises";
|
|
12136
|
-
import { basename, dirname as dirname5, extname, join as
|
|
12164
|
+
import { basename, dirname as dirname5, extname, join as join18 } from "path";
|
|
12137
12165
|
import { parse as parseYaml2 } from "yaml";
|
|
12138
12166
|
import { Agent as CursorAgent } from "@cursor/sdk";
|
|
12139
12167
|
var CURSOR_SLASH_COMMANDS_CACHE_MS = 3e4;
|
|
@@ -12192,7 +12220,7 @@ async function listCursorCommandsInDirectory(directory) {
|
|
|
12192
12220
|
const name = basename(entry.name, ".md");
|
|
12193
12221
|
let description;
|
|
12194
12222
|
try {
|
|
12195
|
-
description = extractCursorCommandDescription(await readFile10(
|
|
12223
|
+
description = extractCursorCommandDescription(await readFile10(join18(directory, entry.name), "utf8"));
|
|
12196
12224
|
} catch (error) {
|
|
12197
12225
|
console.warn("[CursorManager] Failed to read slash command file:", error);
|
|
12198
12226
|
}
|
|
@@ -12214,7 +12242,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12214
12242
|
slashCommandsRequest = null;
|
|
12215
12243
|
constructor(options) {
|
|
12216
12244
|
super(options);
|
|
12217
|
-
this.historyFilePath = options.historyFilePath ??
|
|
12245
|
+
this.historyFilePath = options.historyFilePath ?? join18(ENGINE_ENV.HOME_DIR, ".replicas", "cursor", "history.jsonl");
|
|
12218
12246
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
12219
12247
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
12220
12248
|
}
|
|
@@ -12265,7 +12293,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
12265
12293
|
this.slashCommandsRequest ??= (async () => {
|
|
12266
12294
|
try {
|
|
12267
12295
|
const repoDirectories = await getAgentAdditionalDirectories();
|
|
12268
|
-
const commandDirectories = [this.workingDirectory, ...repoDirectories, ENGINE_ENV.HOME_DIR].map((directory) =>
|
|
12296
|
+
const commandDirectories = [this.workingDirectory, ...repoDirectories, ENGINE_ENV.HOME_DIR].map((directory) => join18(directory, ".cursor", "commands"));
|
|
12269
12297
|
const commands = mergeSlashCommands(
|
|
12270
12298
|
...await Promise.all(commandDirectories.map(listCursorCommandsInDirectory))
|
|
12271
12299
|
);
|
|
@@ -12514,7 +12542,7 @@ ${request.message}` : request.message;
|
|
|
12514
12542
|
// src/managers/opencode-manager.ts
|
|
12515
12543
|
import { existsSync as existsSync6 } from "fs";
|
|
12516
12544
|
import { mkdir as mkdir12, readFile as readFile11 } from "fs/promises";
|
|
12517
|
-
import { delimiter, dirname as dirname6, join as
|
|
12545
|
+
import { delimiter, dirname as dirname6, join as join19 } from "path";
|
|
12518
12546
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
12519
12547
|
import { fileURLToPath } from "url";
|
|
12520
12548
|
import { Agent } from "undici";
|
|
@@ -12524,8 +12552,7 @@ import {
|
|
|
12524
12552
|
createOpencodeServer
|
|
12525
12553
|
} from "@opencode-ai/sdk/v2";
|
|
12526
12554
|
var OPENCODE_SHIM_DIR = dirname6(fileURLToPath(new URL("../../scripts/opencode", import.meta.url)));
|
|
12527
|
-
var OPENCODE_CONFIG_PATH =
|
|
12528
|
-
var OPENCODE_AUTH_PATH2 = join18(ENGINE_ENV.HOME_DIR, ".local", "share", "opencode", "auth.json");
|
|
12555
|
+
var OPENCODE_CONFIG_PATH = join19(ENGINE_ENV.HOME_DIR, ".config", "opencode", "opencode.json");
|
|
12529
12556
|
var OPENCODE_FETCH_DISPATCHER = new Agent({ headersTimeout: 0, bodyTimeout: 0 });
|
|
12530
12557
|
var OPENCODE_SERVER_STARTUP_TIMEOUT_MS = 3e4;
|
|
12531
12558
|
var OPENCODE_WORKSPACE_PERMISSION = {
|
|
@@ -12559,11 +12586,11 @@ var opencodeAuthSchema = z5.record(z5.string(), z5.object({
|
|
|
12559
12586
|
type: z5.string().optional(),
|
|
12560
12587
|
key: z5.string().optional()
|
|
12561
12588
|
}));
|
|
12562
|
-
async function
|
|
12563
|
-
if (!existsSync6(
|
|
12589
|
+
async function hasOpencodeCredentials(provider) {
|
|
12590
|
+
if (!existsSync6(OPENCODE_AUTH_PATH)) return false;
|
|
12564
12591
|
try {
|
|
12565
|
-
const auth = opencodeAuthSchema.safeParse(JSON.parse(await readFile11(
|
|
12566
|
-
return auth.success && auth.data[
|
|
12592
|
+
const auth = opencodeAuthSchema.safeParse(JSON.parse(await readFile11(OPENCODE_AUTH_PATH, "utf8")));
|
|
12593
|
+
return auth.success && auth.data[provider]?.type === "api" && Boolean(auth.data[provider]?.key);
|
|
12567
12594
|
} catch {
|
|
12568
12595
|
return false;
|
|
12569
12596
|
}
|
|
@@ -12573,7 +12600,7 @@ function getOpenCodeGoModel(model) {
|
|
|
12573
12600
|
}
|
|
12574
12601
|
async function opencodeConfig(model) {
|
|
12575
12602
|
let config;
|
|
12576
|
-
if (await
|
|
12603
|
+
if (await hasOpencodeCredentials(OPENCODE_GO_PROVIDER)) {
|
|
12577
12604
|
config = {
|
|
12578
12605
|
enabled_providers: [OPENCODE_GO_PROVIDER],
|
|
12579
12606
|
model: `${OPENCODE_GO_PROVIDER}/${model}`,
|
|
@@ -12587,10 +12614,7 @@ async function opencodeConfig(model) {
|
|
|
12587
12614
|
model: `openrouter/${model}`,
|
|
12588
12615
|
provider: {
|
|
12589
12616
|
openrouter: {
|
|
12590
|
-
models: Object.fromEntries(models.map((candidate) => [candidate, {}]))
|
|
12591
|
-
options: {
|
|
12592
|
-
apiKey: "{env:OPENROUTER_API_KEY}"
|
|
12593
|
-
}
|
|
12617
|
+
models: Object.fromEntries(models.map((candidate) => [candidate, {}]))
|
|
12594
12618
|
}
|
|
12595
12619
|
},
|
|
12596
12620
|
permission: OPENCODE_WORKSPACE_PERMISSION,
|
|
@@ -12754,7 +12778,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
12754
12778
|
constructor(options) {
|
|
12755
12779
|
super(options);
|
|
12756
12780
|
this.sessionId = options.initialSessionId;
|
|
12757
|
-
this.historyFilePath = options.historyFilePath ??
|
|
12781
|
+
this.historyFilePath = options.historyFilePath ?? join19(ENGINE_ENV.HOME_DIR, ".replicas", "opencode", "history.jsonl");
|
|
12758
12782
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
12759
12783
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
12760
12784
|
}
|
|
@@ -12825,7 +12849,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
12825
12849
|
return this.slashCommandsRequest;
|
|
12826
12850
|
}
|
|
12827
12851
|
async ensureClient(model) {
|
|
12828
|
-
const providerId = await
|
|
12852
|
+
const providerId = await hasOpencodeCredentials(OPENCODE_GO_PROVIDER) ? OPENCODE_GO_PROVIDER : "openrouter";
|
|
12829
12853
|
if (this.client && this.providerId !== providerId) {
|
|
12830
12854
|
this.eventAbortController?.abort();
|
|
12831
12855
|
this.server?.close();
|
|
@@ -12838,7 +12862,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
12838
12862
|
if (this.client && (providerId === OPENCODE_GO_PROVIDER || this.configuredModels.has(configuredModel))) {
|
|
12839
12863
|
return this.client;
|
|
12840
12864
|
}
|
|
12841
|
-
if (
|
|
12865
|
+
if (this.providerId !== OPENCODE_GO_PROVIDER && !await hasOpencodeCredentials("openrouter")) {
|
|
12842
12866
|
throw new Error("OpenCode Go or OpenRouter credentials are not configured for Opencode in this workspace.");
|
|
12843
12867
|
}
|
|
12844
12868
|
this.eventAbortController?.abort();
|
|
@@ -13245,7 +13269,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
13245
13269
|
|
|
13246
13270
|
// src/managers/pi-manager.ts
|
|
13247
13271
|
import { mkdir as mkdir13 } from "fs/promises";
|
|
13248
|
-
import { dirname as dirname7, join as
|
|
13272
|
+
import { dirname as dirname7, join as join20 } from "path";
|
|
13249
13273
|
import {
|
|
13250
13274
|
AuthStorage,
|
|
13251
13275
|
createAgentSession,
|
|
@@ -13285,7 +13309,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13285
13309
|
historyFile;
|
|
13286
13310
|
constructor(options) {
|
|
13287
13311
|
super(options);
|
|
13288
|
-
this.historyFilePath = options.historyFilePath ??
|
|
13312
|
+
this.historyFilePath = options.historyFilePath ?? join20(PI_HISTORY_DIR, `${Date.now()}.jsonl`);
|
|
13289
13313
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
13290
13314
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
13291
13315
|
}
|
|
@@ -13312,6 +13336,13 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13312
13336
|
await this.initialized;
|
|
13313
13337
|
return mergeSlashCommands(...(this.session?.promptTemplates ?? []).map((template) => createProviderSlashCommand("pi", template.name, template.description)).filter((command) => Boolean(command)));
|
|
13314
13338
|
}
|
|
13339
|
+
async enqueueMessage(request) {
|
|
13340
|
+
await this.initialized;
|
|
13341
|
+
if (!this.session && !await this.getOpenRouterApiKey()) {
|
|
13342
|
+
throw new Error("OpenRouter authentication is missing for Pi. Add an OpenRouter API key in Settings \u2192 Coding agents.");
|
|
13343
|
+
}
|
|
13344
|
+
return this.messageQueue.enqueue(request);
|
|
13345
|
+
}
|
|
13315
13346
|
dispose() {
|
|
13316
13347
|
this.unsubscribe?.();
|
|
13317
13348
|
this.unsubscribe = null;
|
|
@@ -13329,9 +13360,9 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13329
13360
|
}
|
|
13330
13361
|
return this.session;
|
|
13331
13362
|
}
|
|
13332
|
-
const
|
|
13363
|
+
const authStorage = AuthStorage.create(PI_AUTH_PATH);
|
|
13364
|
+
const apiKey = await this.getOpenRouterApiKey(authStorage);
|
|
13333
13365
|
if (!apiKey) throw new Error("OpenRouter API key is not configured for Pi.");
|
|
13334
|
-
const authStorage = AuthStorage.inMemory({ openrouter: { type: "api_key", key: apiKey } });
|
|
13335
13366
|
const modelRegistry = ModelRegistry.create(authStorage);
|
|
13336
13367
|
const openRouterModels = modelRegistry.getAll().filter((candidate) => candidate.provider === "openrouter");
|
|
13337
13368
|
const modelTemplate = openRouterModels[0];
|
|
@@ -13361,7 +13392,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13361
13392
|
const sessionManager = this.initialSessionId ? SessionManager.open(this.initialSessionId, PI_HISTORY_DIR, this.workingDirectory) : SessionManager.create(this.workingDirectory, PI_HISTORY_DIR);
|
|
13362
13393
|
const resourceLoader = new DefaultResourceLoader({
|
|
13363
13394
|
cwd: this.workingDirectory,
|
|
13364
|
-
agentDir:
|
|
13395
|
+
agentDir: join20(ENGINE_ENV.HOME_DIR, ".pi", "agent"),
|
|
13365
13396
|
extensionFactories: [registerCommandProtection(this.workingDirectory)],
|
|
13366
13397
|
appendSystemPrompt: [this.buildCombinedInstructions() ?? ""]
|
|
13367
13398
|
});
|
|
@@ -13383,6 +13414,10 @@ var PiManager = class extends CodingAgentManager {
|
|
|
13383
13414
|
this.unsubscribe = this.session.subscribe((event) => this.handleEvent(event));
|
|
13384
13415
|
return this.session;
|
|
13385
13416
|
}
|
|
13417
|
+
async getOpenRouterApiKey(authStorage = AuthStorage.create(PI_AUTH_PATH)) {
|
|
13418
|
+
const credential = authStorage.get("openrouter");
|
|
13419
|
+
return credential?.type === "api_key" ? credential.key : void 0;
|
|
13420
|
+
}
|
|
13386
13421
|
handleEvent(event) {
|
|
13387
13422
|
const payload = eventPayload(event);
|
|
13388
13423
|
this.recordHistoryEvent(`pi-${event.type}`, payload, this.historyFile);
|
|
@@ -14066,18 +14101,18 @@ var keepAliveService = new KeepAliveService();
|
|
|
14066
14101
|
|
|
14067
14102
|
// src/services/canvas-service.ts
|
|
14068
14103
|
import { readdir as readdir6, readFile as readFile12, stat as stat3 } from "fs/promises";
|
|
14069
|
-
import { homedir as
|
|
14070
|
-
import { join as
|
|
14104
|
+
import { homedir as homedir14 } from "os";
|
|
14105
|
+
import { join as join21 } from "path";
|
|
14071
14106
|
var GLOBAL_CANVAS_DIRECTORIES = [
|
|
14072
|
-
|
|
14073
|
-
|
|
14074
|
-
|
|
14107
|
+
join21(homedir14(), ".claude", "plans"),
|
|
14108
|
+
join21(process.env.XDG_DATA_HOME ?? join21(homedir14(), ".local", "share"), "opencode", "plans"),
|
|
14109
|
+
join21(homedir14(), ".replicas", "canvas")
|
|
14075
14110
|
];
|
|
14076
14111
|
async function canvasDirectories() {
|
|
14077
14112
|
const repositories = await gitService.listRepositories().catch(() => []);
|
|
14078
14113
|
return [
|
|
14079
14114
|
...GLOBAL_CANVAS_DIRECTORIES,
|
|
14080
|
-
...repositories.map((repository) =>
|
|
14115
|
+
...repositories.map((repository) => join21(repository.path, ".opencode", "plans"))
|
|
14081
14116
|
];
|
|
14082
14117
|
}
|
|
14083
14118
|
var CanvasService = class {
|
|
@@ -14097,7 +14132,7 @@ var CanvasService = class {
|
|
|
14097
14132
|
const { kind } = classifyCanvasFilename(entry.name);
|
|
14098
14133
|
let sizeBytes = 0;
|
|
14099
14134
|
try {
|
|
14100
|
-
const s = await stat3(
|
|
14135
|
+
const s = await stat3(join21(directory, entry.name));
|
|
14101
14136
|
sizeBytes = s.size;
|
|
14102
14137
|
} catch {
|
|
14103
14138
|
continue;
|
|
@@ -14112,7 +14147,7 @@ var CanvasService = class {
|
|
|
14112
14147
|
if (!safe) return null;
|
|
14113
14148
|
const { kind, mimeType } = classifyCanvasFilename(safe);
|
|
14114
14149
|
for (const directory of await canvasDirectories()) {
|
|
14115
|
-
const filePath =
|
|
14150
|
+
const filePath = join21(directory, safe);
|
|
14116
14151
|
let sizeBytes = 0;
|
|
14117
14152
|
let updatedAt = "";
|
|
14118
14153
|
try {
|
|
@@ -14249,13 +14284,13 @@ async function reconcileCanvasItems(filenames) {
|
|
|
14249
14284
|
|
|
14250
14285
|
// src/services/upload-chat-transcripts.ts
|
|
14251
14286
|
import { readdir as readdir7, readFile as readFile13 } from "fs/promises";
|
|
14252
|
-
import { basename as basename2, join as
|
|
14287
|
+
import { basename as basename2, join as join23 } from "path";
|
|
14253
14288
|
|
|
14254
14289
|
// src/services/chat/chat-senders.ts
|
|
14255
|
-
import { join as
|
|
14256
|
-
var CHAT_SENDERS_DIR =
|
|
14290
|
+
import { join as join22 } from "path";
|
|
14291
|
+
var CHAT_SENDERS_DIR = join22(ENGINE_DIR2, "chat-senders");
|
|
14257
14292
|
function chatMessageSendersFilePath(chatId) {
|
|
14258
|
-
return
|
|
14293
|
+
return join22(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
|
|
14259
14294
|
}
|
|
14260
14295
|
function parseChatMessageSendersJsonl(content) {
|
|
14261
14296
|
return content.split("\n").flatMap((line) => {
|
|
@@ -14271,9 +14306,9 @@ function parseChatMessageSendersJsonl(content) {
|
|
|
14271
14306
|
|
|
14272
14307
|
// src/services/upload-chat-transcripts.ts
|
|
14273
14308
|
var HISTORY_DIRS = [
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14309
|
+
join23(ENGINE_DIR2, "claude-histories"),
|
|
14310
|
+
join23(ENGINE_DIR2, "relay-histories"),
|
|
14311
|
+
join23(ENGINE_DIR2, "codex-histories")
|
|
14277
14312
|
];
|
|
14278
14313
|
async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
14279
14314
|
let flushed = 0;
|
|
@@ -14290,7 +14325,7 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
|
14290
14325
|
if (!entry.endsWith(".jsonl")) continue;
|
|
14291
14326
|
const chatId = basename2(entry, ".jsonl");
|
|
14292
14327
|
tasks.push(
|
|
14293
|
-
uploadChatTranscript(chatId,
|
|
14328
|
+
uploadChatTranscript(chatId, join23(dir, entry), chatsById.get(chatId)).then(() => {
|
|
14294
14329
|
flushed++;
|
|
14295
14330
|
}).catch((err) => {
|
|
14296
14331
|
failed++;
|
|
@@ -14380,7 +14415,7 @@ async function flushRepoState() {
|
|
|
14380
14415
|
// src/services/upload-engine-logs.ts
|
|
14381
14416
|
import { createReadStream } from "fs";
|
|
14382
14417
|
import { readdir as readdir8, stat as stat4 } from "fs/promises";
|
|
14383
|
-
import { join as
|
|
14418
|
+
import { join as join24 } from "path";
|
|
14384
14419
|
var MAX_ENGINE_LOG_FLUSH_SESSIONS = 10;
|
|
14385
14420
|
var MAX_ENGINE_LOG_FLUSH_BYTES = 5 * 1024 * 1024;
|
|
14386
14421
|
var ENGINE_LOG_FLUSH_TIMEOUT_MS = 2e4;
|
|
@@ -14409,7 +14444,7 @@ async function flushAllEngineLogs() {
|
|
|
14409
14444
|
const candidates = (await Promise.all(filenames.slice(0, MAX_ENGINE_LOG_FLUSH_SESSIONS).map(async (filename) => {
|
|
14410
14445
|
try {
|
|
14411
14446
|
const sessionId = filename.slice(0, -".log".length);
|
|
14412
|
-
const filePath =
|
|
14447
|
+
const filePath = join24(LOG_DIR, filename);
|
|
14413
14448
|
const fileStat = await runBeforeDeadline(() => stat4(filePath), deadline);
|
|
14414
14449
|
if (!fileStat.isFile()) {
|
|
14415
14450
|
skipped++;
|
|
@@ -14505,17 +14540,16 @@ async function uploadEngineLog(input, timeoutMs) {
|
|
|
14505
14540
|
}
|
|
14506
14541
|
|
|
14507
14542
|
// src/services/chat/chat-service.ts
|
|
14508
|
-
var CODEX_AUTH_PATH2 =
|
|
14509
|
-
var OPENCODE_AUTH_PATH3 = join24(homedir14(), ".local", "share", "opencode", "auth.json");
|
|
14543
|
+
var CODEX_AUTH_PATH2 = join25(homedir15(), ".codex", "auth.json");
|
|
14510
14544
|
var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
|
|
14511
14545
|
function isCodexAvailable() {
|
|
14512
14546
|
return existsSync7(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
|
|
14513
14547
|
}
|
|
14514
14548
|
function isOpencodeAvailable() {
|
|
14515
|
-
return existsSync7(
|
|
14549
|
+
return existsSync7(OPENCODE_AUTH_PATH);
|
|
14516
14550
|
}
|
|
14517
14551
|
function isPiAvailable() {
|
|
14518
|
-
return
|
|
14552
|
+
return existsSync7(PI_AUTH_PATH);
|
|
14519
14553
|
}
|
|
14520
14554
|
function isCursorAvailable() {
|
|
14521
14555
|
return Boolean(ENGINE_ENV.CURSOR_API_KEY);
|
|
@@ -14972,7 +15006,7 @@ var ChatService = class {
|
|
|
14972
15006
|
return descendants;
|
|
14973
15007
|
}
|
|
14974
15008
|
async deleteHistoryFile(persisted) {
|
|
14975
|
-
await rm2(
|
|
15009
|
+
await rm2(join25(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
|
|
14976
15010
|
await rm2(chatMessageSendersFilePath(persisted.id), { force: true });
|
|
14977
15011
|
}
|
|
14978
15012
|
async getChatHistory(chatId, page = {}) {
|
|
@@ -15048,7 +15082,7 @@ var ChatService = class {
|
|
|
15048
15082
|
if (persisted.provider === "claude") {
|
|
15049
15083
|
provider = new ClaudeManager({
|
|
15050
15084
|
workingDirectory: this.workingDirectory,
|
|
15051
|
-
historyFilePath:
|
|
15085
|
+
historyFilePath: join25(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15052
15086
|
initialSessionId: persisted.providerSessionId,
|
|
15053
15087
|
onSaveSessionId: saveSession,
|
|
15054
15088
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15057,7 +15091,7 @@ var ChatService = class {
|
|
|
15057
15091
|
} else if (persisted.provider === "relay") {
|
|
15058
15092
|
provider = new RelayManager({
|
|
15059
15093
|
workingDirectory: this.workingDirectory,
|
|
15060
|
-
historyFilePath:
|
|
15094
|
+
historyFilePath: join25(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15061
15095
|
initialSessionId: persisted.providerSessionId,
|
|
15062
15096
|
onSaveSessionId: saveSession,
|
|
15063
15097
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15071,7 +15105,7 @@ var ChatService = class {
|
|
|
15071
15105
|
} else if (persisted.provider === "cursor") {
|
|
15072
15106
|
provider = new CursorManager({
|
|
15073
15107
|
workingDirectory: this.workingDirectory,
|
|
15074
|
-
historyFilePath:
|
|
15108
|
+
historyFilePath: join25(CURSOR_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15075
15109
|
initialSessionId: persisted.providerSessionId,
|
|
15076
15110
|
onSaveSessionId: saveSession,
|
|
15077
15111
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15080,7 +15114,7 @@ var ChatService = class {
|
|
|
15080
15114
|
} else if (persisted.provider === "opencode") {
|
|
15081
15115
|
provider = new OpencodeManager({
|
|
15082
15116
|
workingDirectory: this.workingDirectory,
|
|
15083
|
-
historyFilePath:
|
|
15117
|
+
historyFilePath: join25(OPENCODE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15084
15118
|
initialSessionId: persisted.providerSessionId,
|
|
15085
15119
|
onSaveSessionId: saveSession,
|
|
15086
15120
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15089,7 +15123,7 @@ var ChatService = class {
|
|
|
15089
15123
|
} else if (persisted.provider === "pi") {
|
|
15090
15124
|
provider = new PiManager({
|
|
15091
15125
|
workingDirectory: this.workingDirectory,
|
|
15092
|
-
historyFilePath:
|
|
15126
|
+
historyFilePath: join25(PI_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15093
15127
|
initialSessionId: persisted.providerSessionId,
|
|
15094
15128
|
onSaveSessionId: saveSession,
|
|
15095
15129
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15098,7 +15132,7 @@ var ChatService = class {
|
|
|
15098
15132
|
} else {
|
|
15099
15133
|
provider = new CodexAspManager({
|
|
15100
15134
|
workingDirectory: this.workingDirectory,
|
|
15101
|
-
historyFilePath:
|
|
15135
|
+
historyFilePath: join25(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
15102
15136
|
initialSessionId: persisted.providerSessionId,
|
|
15103
15137
|
onSaveSessionId: saveSession,
|
|
15104
15138
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -15247,7 +15281,7 @@ var ChatService = class {
|
|
|
15247
15281
|
});
|
|
15248
15282
|
uploadChatTranscript(
|
|
15249
15283
|
chatId,
|
|
15250
|
-
|
|
15284
|
+
join25(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
|
|
15251
15285
|
this.toSummary(chat)
|
|
15252
15286
|
).catch((err) => {
|
|
15253
15287
|
console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
|
|
@@ -15383,7 +15417,7 @@ var ChatService = class {
|
|
|
15383
15417
|
// src/services/repo-file-service.ts
|
|
15384
15418
|
import { execFile as execFile2 } from "child_process";
|
|
15385
15419
|
import { readFile as readFile15, realpath, stat as stat5 } from "fs/promises";
|
|
15386
|
-
import { join as
|
|
15420
|
+
import { join as join26, resolve as resolve2, extname as extname2 } from "path";
|
|
15387
15421
|
var CACHE_TTL_MS = 3e4;
|
|
15388
15422
|
var SEARCH_TIMEOUT_MS = 15e3;
|
|
15389
15423
|
var MAX_CONTENT_BYTES = 256 * 1024;
|
|
@@ -15543,7 +15577,7 @@ var RepoFileService = class {
|
|
|
15543
15577
|
const repo = repos.find((r) => r.name === repoName);
|
|
15544
15578
|
if (!repo) return null;
|
|
15545
15579
|
try {
|
|
15546
|
-
const fullPath = await realpath(resolve2(
|
|
15580
|
+
const fullPath = await realpath(resolve2(join26(repo.path, filePath)));
|
|
15547
15581
|
const repoRoot = await realpath(repo.path);
|
|
15548
15582
|
const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
|
|
15549
15583
|
if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
|
|
@@ -15651,20 +15685,20 @@ var RepoFileService = class {
|
|
|
15651
15685
|
import { Hono } from "hono";
|
|
15652
15686
|
import { z as z7 } from "zod";
|
|
15653
15687
|
import { readdir as readdir10, stat as stat6, readFile as readFile18 } from "fs/promises";
|
|
15654
|
-
import { join as
|
|
15688
|
+
import { join as join29, resolve as resolve3 } from "path";
|
|
15655
15689
|
|
|
15656
15690
|
// src/services/warm-hooks-service.ts
|
|
15657
15691
|
import { spawn as spawn4 } from "child_process";
|
|
15658
15692
|
import { readFile as readFile17 } from "fs/promises";
|
|
15659
15693
|
import { existsSync as existsSync8 } from "fs";
|
|
15660
|
-
import { join as
|
|
15694
|
+
import { join as join28 } from "path";
|
|
15661
15695
|
|
|
15662
15696
|
// src/services/warm-hook-logs-service.ts
|
|
15663
15697
|
import { mkdir as mkdir15, readFile as readFile16, writeFile as writeFile6, readdir as readdir9, appendFile as appendFile4, unlink as unlink3 } from "fs/promises";
|
|
15664
|
-
import { homedir as
|
|
15665
|
-
import { join as
|
|
15666
|
-
var LOGS_DIR2 =
|
|
15667
|
-
var CURRENT_RUN_LOG =
|
|
15698
|
+
import { homedir as homedir16 } from "os";
|
|
15699
|
+
import { join as join27 } from "path";
|
|
15700
|
+
var LOGS_DIR2 = join27(homedir16(), ".replicas", "warm-hook-logs");
|
|
15701
|
+
var CURRENT_RUN_LOG = join27(LOGS_DIR2, "current-run.log");
|
|
15668
15702
|
var GLOBAL_FILENAME = "global.json";
|
|
15669
15703
|
function withPreview2(stored) {
|
|
15670
15704
|
const preview = buildHookOutputPreview(stored.output);
|
|
@@ -15681,7 +15715,7 @@ var WarmHookLogsService = class {
|
|
|
15681
15715
|
hookName: "organization",
|
|
15682
15716
|
...entry
|
|
15683
15717
|
};
|
|
15684
|
-
await writeFile6(
|
|
15718
|
+
await writeFile6(join27(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
15685
15719
|
`, "utf-8");
|
|
15686
15720
|
}
|
|
15687
15721
|
async saveEnvironmentHookLog(entry) {
|
|
@@ -15691,7 +15725,7 @@ var WarmHookLogsService = class {
|
|
|
15691
15725
|
hookName: "environment",
|
|
15692
15726
|
...entry
|
|
15693
15727
|
};
|
|
15694
|
-
await writeFile6(
|
|
15728
|
+
await writeFile6(join27(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
15695
15729
|
`, "utf-8");
|
|
15696
15730
|
}
|
|
15697
15731
|
async saveRepoHookLog(repoName, entry) {
|
|
@@ -15701,7 +15735,7 @@ var WarmHookLogsService = class {
|
|
|
15701
15735
|
hookName: repoName,
|
|
15702
15736
|
...entry
|
|
15703
15737
|
};
|
|
15704
|
-
await writeFile6(
|
|
15738
|
+
await writeFile6(join27(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
|
|
15705
15739
|
`, "utf-8");
|
|
15706
15740
|
}
|
|
15707
15741
|
async getAllLogs() {
|
|
@@ -15720,7 +15754,7 @@ var WarmHookLogsService = class {
|
|
|
15720
15754
|
continue;
|
|
15721
15755
|
}
|
|
15722
15756
|
try {
|
|
15723
|
-
const raw = await readFile16(
|
|
15757
|
+
const raw = await readFile16(join27(LOGS_DIR2, file), "utf-8");
|
|
15724
15758
|
const stored = JSON.parse(raw);
|
|
15725
15759
|
logs.push(withPreview2(stored));
|
|
15726
15760
|
} catch {
|
|
@@ -15758,7 +15792,7 @@ var WarmHookLogsService = class {
|
|
|
15758
15792
|
async getFullOutput(hookType, hookName) {
|
|
15759
15793
|
const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
15760
15794
|
try {
|
|
15761
|
-
const raw = await readFile16(
|
|
15795
|
+
const raw = await readFile16(join27(LOGS_DIR2, filename), "utf-8");
|
|
15762
15796
|
const stored = JSON.parse(raw);
|
|
15763
15797
|
if (stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
15764
15798
|
return null;
|
|
@@ -15777,7 +15811,7 @@ var warmHookLogsService = new WarmHookLogsService();
|
|
|
15777
15811
|
// src/services/warm-hooks-service.ts
|
|
15778
15812
|
async function readRepoWarmHook(repoPath) {
|
|
15779
15813
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
15780
|
-
const configPath =
|
|
15814
|
+
const configPath = join28(repoPath, filename);
|
|
15781
15815
|
if (!existsSync8(configPath)) {
|
|
15782
15816
|
continue;
|
|
15783
15817
|
}
|
|
@@ -17010,7 +17044,7 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
17010
17044
|
const logFiles = files.filter((f) => f.endsWith(".log"));
|
|
17011
17045
|
const sessions = await Promise.all(
|
|
17012
17046
|
logFiles.map(async (filename) => {
|
|
17013
|
-
const filePath =
|
|
17047
|
+
const filePath = join29(LOG_DIR, filename);
|
|
17014
17048
|
const fileStat = await stat6(filePath);
|
|
17015
17049
|
const sessionId = filename.replace(/\.log$/, "");
|
|
17016
17050
|
return {
|