replicas-engine 0.1.635 → 0.1.637
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/{chunk-464TFYYL.js → chunk-ESC6QHTZ.js} +87 -215
- package/dist/src/headless-agent.js +27 -8
- package/dist/src/index.js +367 -201
- package/package.json +2 -2
package/dist/src/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
|
|
3
4
|
AGENT,
|
|
5
|
+
AGENT_MESSAGE_DELTA_METHOD,
|
|
4
6
|
AGENT_MODELS,
|
|
5
7
|
ASTER_BASE_URL,
|
|
6
8
|
ASTER_MODELS,
|
|
@@ -15,16 +17,20 @@ import {
|
|
|
15
17
|
CLAUDE_AUTH_ENV_KEYS_BY_METHOD,
|
|
16
18
|
CLAUDE_FABLE_5_BEDROCK_MODEL,
|
|
17
19
|
CLAUDE_FABLE_5_MODEL,
|
|
20
|
+
CLAUDE_HAIKU_4_5_BEDROCK_MODEL,
|
|
18
21
|
CLAUDE_HAIKU_4_5_MODEL,
|
|
22
|
+
CLAUDE_OPUS_4_8_BEDROCK_MODEL,
|
|
19
23
|
CLAUDE_OPUS_4_8_MODEL,
|
|
20
24
|
CLAUDE_OPUS_5_BEDROCK_MODEL,
|
|
21
25
|
CLAUDE_OPUS_5_MODEL,
|
|
22
26
|
CLAUDE_PARTIAL_MESSAGE_EVENT_TYPE,
|
|
27
|
+
CLAUDE_SONNET_5_BEDROCK_MODEL,
|
|
23
28
|
CLAUDE_SONNET_5_MODEL,
|
|
24
29
|
CODEX_ASP_TRANSCRIPT_UPDATED_EVENT_TYPE,
|
|
25
30
|
CODEX_AUTH_ENV_KEYS,
|
|
26
31
|
CODEX_AUTH_ENV_KEYS_BY_METHOD,
|
|
27
32
|
CODEX_QUOTA_STATUS_EVENT_TYPE,
|
|
33
|
+
COMMAND_EXECUTION_OUTPUT_DELTA_METHOD,
|
|
28
34
|
COMPACTION_STATUS_EVENT_TYPE,
|
|
29
35
|
CONTEXT_USAGE_EVENT_TYPE,
|
|
30
36
|
DEFAULT_ASTER_MODEL,
|
|
@@ -37,16 +43,17 @@ import {
|
|
|
37
43
|
DEFAULT_PI_MODEL,
|
|
38
44
|
DEFAULT_START_HOOK_TIMEOUT_MS,
|
|
39
45
|
DESKTOP_STREAM_PORT,
|
|
40
|
-
ENGINE_ENV,
|
|
41
46
|
ENGINE_HEALTH_MAX_WAIT_MS,
|
|
42
47
|
ENGINE_HEALTH_WAIT_HEADER,
|
|
43
48
|
ENGINE_HEALTH_WAIT_QUERY_PARAM,
|
|
49
|
+
FILE_CHANGE_OUTPUT_DELTA_METHOD,
|
|
44
50
|
GITHUB_CREDENTIAL_REFRESH_PATH,
|
|
45
51
|
GITLAB_CREDENTIAL_REFRESH_PATH,
|
|
46
52
|
GIT_CREDENTIAL_HELPER_FILENAME,
|
|
47
53
|
HOOK_EXEC_MAX_BUFFER_BYTES,
|
|
48
54
|
IMAGE_MEDIA_TYPES,
|
|
49
|
-
|
|
55
|
+
ITEM_COMPLETED_METHOD,
|
|
56
|
+
ITEM_STARTED_METHOD,
|
|
50
57
|
InFlightMap,
|
|
51
58
|
MAX_CANVAS_FILE_BYTES,
|
|
52
59
|
MAX_CANVAS_PREVIEW_BYTES,
|
|
@@ -55,19 +62,31 @@ import {
|
|
|
55
62
|
MEMORY_ROOT,
|
|
56
63
|
MEMORY_SUMMARY_FILENAME,
|
|
57
64
|
MERGED_MESSAGE_SEPARATOR,
|
|
65
|
+
REASONING_SUMMARY_PART_ADDED_METHOD,
|
|
66
|
+
REASONING_SUMMARY_TEXT_DELTA_METHOD,
|
|
67
|
+
REASONING_TEXT_DELTA_METHOD,
|
|
58
68
|
REPLICAS_CONFIG_FILENAMES,
|
|
69
|
+
REPLICAS_RUNTIME_ENV_ALIASES,
|
|
59
70
|
SANDBOX_PATHS,
|
|
60
71
|
SUBPROCESS_MAX_BUFFER,
|
|
72
|
+
THREAD_COMPACTED_METHOD,
|
|
73
|
+
THREAD_GOAL_CLEARED_METHOD,
|
|
74
|
+
THREAD_GOAL_UPDATED_METHOD,
|
|
75
|
+
THREAD_TOKEN_USAGE_UPDATED_METHOD,
|
|
61
76
|
TIMEOUT,
|
|
77
|
+
TURN_COMPLETED_METHOD,
|
|
78
|
+
TURN_PLAN_UPDATED_METHOD,
|
|
79
|
+
TURN_STARTED_METHOD,
|
|
62
80
|
TaskAccumulator,
|
|
63
81
|
USER_MESSAGE_ID_PAYLOAD_KEY,
|
|
64
82
|
VALID_AGENT_PROVIDERS,
|
|
65
83
|
VALID_THINKING_LEVELS,
|
|
84
|
+
agentCredentialSnapshotSchema,
|
|
66
85
|
applyCodexAspTranscriptDelta,
|
|
67
86
|
areSameUserMessageEvents,
|
|
68
87
|
areUserMessagesWithinMatchWindow,
|
|
69
88
|
autoCompactThresholdField,
|
|
70
|
-
|
|
89
|
+
buildCodexAgentEnv,
|
|
71
90
|
buildCodexTokenUsageContextUsagePayload,
|
|
72
91
|
buildGitCredentialHelperScript,
|
|
73
92
|
buildHookOutputPreview,
|
|
@@ -90,6 +109,7 @@ import {
|
|
|
90
109
|
decodePathSegments,
|
|
91
110
|
detectAgentQuotaLimit,
|
|
92
111
|
detectLanguageByPath,
|
|
112
|
+
dispatchAspNotification,
|
|
93
113
|
execAsync,
|
|
94
114
|
execFileAsync,
|
|
95
115
|
extractCommandProtectionCommandText,
|
|
@@ -120,7 +140,6 @@ import {
|
|
|
120
140
|
isDefaultChat,
|
|
121
141
|
isGitHubUrl,
|
|
122
142
|
isRecord,
|
|
123
|
-
isRecord2,
|
|
124
143
|
isSkillRegistryManifest,
|
|
125
144
|
isTerminalBackgroundTaskStatus,
|
|
126
145
|
isTransientErrorText,
|
|
@@ -141,18 +160,19 @@ import {
|
|
|
141
160
|
parseGitRemote,
|
|
142
161
|
parseLatestCodexAspTranscriptTurn,
|
|
143
162
|
parseMcpToolName,
|
|
163
|
+
parsePosixEnvFile,
|
|
144
164
|
parseReplicasConfigString,
|
|
145
165
|
percentage,
|
|
146
166
|
putPresignedFile,
|
|
147
167
|
raceWithTimeout,
|
|
148
|
-
|
|
168
|
+
readReplicasRuntimeEnv,
|
|
169
|
+
recoverCompletedTurn,
|
|
149
170
|
resolveWarmHookConfig,
|
|
150
171
|
sanitizeCanvasFilename,
|
|
151
172
|
serializeCanvasContentResponse,
|
|
152
|
-
setAgentCredentialSnapshot,
|
|
153
173
|
shellQuotePosix,
|
|
154
174
|
stripAgentDiagnosticErrors
|
|
155
|
-
} from "./chunk-
|
|
175
|
+
} from "./chunk-ESC6QHTZ.js";
|
|
156
176
|
|
|
157
177
|
// src/index.ts
|
|
158
178
|
import { serve } from "@hono/node-server";
|
|
@@ -164,6 +184,151 @@ import { connect } from "net";
|
|
|
164
184
|
// src/managers/github-token-manager.ts
|
|
165
185
|
import path from "path";
|
|
166
186
|
|
|
187
|
+
// src/engine-env.ts
|
|
188
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
189
|
+
import { homedir as homedir2 } from "os";
|
|
190
|
+
import { join as join2 } from "path";
|
|
191
|
+
|
|
192
|
+
// src/runtime-env-loader.ts
|
|
193
|
+
import { readFileSync } from "fs";
|
|
194
|
+
import { homedir } from "os";
|
|
195
|
+
import { join } from "path";
|
|
196
|
+
function loadRuntimeEnvFile() {
|
|
197
|
+
let content;
|
|
198
|
+
try {
|
|
199
|
+
content = readFileSync(join(homedir(), ".replicas", "runtime-env.sh"), "utf-8");
|
|
200
|
+
} catch {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
for (const [key, value] of Object.entries(parsePosixEnvFile(content))) {
|
|
204
|
+
process.env[key] = value;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/utils/type-guards.ts
|
|
209
|
+
function isRecord2(value) {
|
|
210
|
+
return typeof value === "object" && value !== null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/engine-env.ts
|
|
214
|
+
var SANDBOX_IMAGE_VERSION_FILE = "/usr/local/lib/replicas-sandbox-image-version";
|
|
215
|
+
function readEnv(name) {
|
|
216
|
+
const value = process.env[name]?.trim();
|
|
217
|
+
return value ? value : void 0;
|
|
218
|
+
}
|
|
219
|
+
function readSandboxImageVersion() {
|
|
220
|
+
const environmentVersion = readEnv("REPLICAS_SANDBOX_IMAGE_VERSION");
|
|
221
|
+
if (environmentVersion) return environmentVersion;
|
|
222
|
+
try {
|
|
223
|
+
return readFileSync2(SANDBOX_IMAGE_VERSION_FILE, "utf8").trim() || "development";
|
|
224
|
+
} catch {
|
|
225
|
+
return "development";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function parsePort(value) {
|
|
229
|
+
if (!value) {
|
|
230
|
+
return 3737;
|
|
231
|
+
}
|
|
232
|
+
const parsed = Number(value);
|
|
233
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
234
|
+
throw new Error("Invalid engine environment: REPLICAS_ENGINE_PORT must be a positive integer");
|
|
235
|
+
}
|
|
236
|
+
return parsed;
|
|
237
|
+
}
|
|
238
|
+
function requireDefined(value, name) {
|
|
239
|
+
if (value === void 0 || value === null) {
|
|
240
|
+
throw new Error(`Invalid engine environment: ${name} is required`);
|
|
241
|
+
}
|
|
242
|
+
return value;
|
|
243
|
+
}
|
|
244
|
+
function requireValidURL(value, name) {
|
|
245
|
+
try {
|
|
246
|
+
new URL(value);
|
|
247
|
+
return value;
|
|
248
|
+
} catch {
|
|
249
|
+
throw new Error(`Invalid engine environment: ${name} must be a valid URL`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function parseClaudeAuthMethod(value) {
|
|
253
|
+
if (value === "oauth" || value === "api_key" || value === "bedrock" || value === "foundry") {
|
|
254
|
+
return value;
|
|
255
|
+
}
|
|
256
|
+
return void 0;
|
|
257
|
+
}
|
|
258
|
+
function parseCodexAuthMethod(value) {
|
|
259
|
+
if (value === "oauth" || value === "api_key" || value === "foundry") {
|
|
260
|
+
return value;
|
|
261
|
+
}
|
|
262
|
+
return void 0;
|
|
263
|
+
}
|
|
264
|
+
function parseAgentCredentialSnapshots(value) {
|
|
265
|
+
if (!value) return {};
|
|
266
|
+
try {
|
|
267
|
+
const parsed = JSON.parse(value);
|
|
268
|
+
if (!isRecord2(parsed)) return {};
|
|
269
|
+
const snapshots = {};
|
|
270
|
+
for (const [provider, snapshot] of Object.entries(parsed)) {
|
|
271
|
+
if (!isValidAgentProvider(provider)) continue;
|
|
272
|
+
const parsedSnapshot = agentCredentialSnapshotSchema.safeParse(snapshot);
|
|
273
|
+
if (parsedSnapshot.success) snapshots[provider] = parsedSnapshot.data;
|
|
274
|
+
}
|
|
275
|
+
return snapshots;
|
|
276
|
+
} catch {
|
|
277
|
+
return {};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
var IS_WARMING_MODE = process.argv.includes("--warming");
|
|
281
|
+
function loadEngineEnv() {
|
|
282
|
+
loadRuntimeEnvFile();
|
|
283
|
+
const HOME_DIR = homedir2();
|
|
284
|
+
const env = {
|
|
285
|
+
// Defined: always available
|
|
286
|
+
REPLICAS_ENGINE_SECRET: requireDefined(readEnv("REPLICAS_ENGINE_SECRET"), "REPLICAS_ENGINE_SECRET"),
|
|
287
|
+
REPLICAS_ENGINE_PORT: parsePort(readEnv("REPLICAS_ENGINE_PORT")),
|
|
288
|
+
REPLICAS_MONOLITH_URL: requireValidURL(
|
|
289
|
+
requireDefined(readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.monolithUrl), "REPLICAS_MONOLITH_URL"),
|
|
290
|
+
"REPLICAS_MONOLITH_URL"
|
|
291
|
+
),
|
|
292
|
+
HOME_DIR,
|
|
293
|
+
WORKSPACE_ROOT: join2(HOME_DIR, "workspaces"),
|
|
294
|
+
REPLICAS_SANDBOX_IMAGE_VERSION: readSandboxImageVersion(),
|
|
295
|
+
// Runtime: may not be set during warming
|
|
296
|
+
REPLICAS_WORKSPACE_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.workspaceId),
|
|
297
|
+
REPLICAS_LINEAR_SESSION_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.linearSessionId),
|
|
298
|
+
REPLICAS_LINEAR_ACCESS_TOKEN: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.linearAccessToken),
|
|
299
|
+
REPLICAS_SLACK_BOT_TOKEN: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackBotToken),
|
|
300
|
+
REPLICAS_SLACK_CHANNEL_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackChannelId),
|
|
301
|
+
REPLICAS_SLACK_THREAD_TS: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackThreadTs),
|
|
302
|
+
ANTHROPIC_API_KEY: readEnv("ANTHROPIC_API_KEY"),
|
|
303
|
+
OPENAI_API_KEY: readEnv("OPENAI_API_KEY"),
|
|
304
|
+
CURSOR_API_KEY: readEnv("CURSOR_API_KEY"),
|
|
305
|
+
CLAUDE_CODE_USE_BEDROCK: readEnv("CLAUDE_CODE_USE_BEDROCK"),
|
|
306
|
+
AWS_ACCESS_KEY_ID: readEnv("AWS_ACCESS_KEY_ID"),
|
|
307
|
+
AWS_SECRET_ACCESS_KEY: readEnv("AWS_SECRET_ACCESS_KEY"),
|
|
308
|
+
AWS_REGION: readEnv("AWS_REGION"),
|
|
309
|
+
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION: readEnv("ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION"),
|
|
310
|
+
REPLICAS_CLAUDE_AUTH_METHOD: parseClaudeAuthMethod(readEnv("REPLICAS_CLAUDE_AUTH_METHOD")),
|
|
311
|
+
REPLICAS_CODEX_AUTH_METHOD: parseCodexAuthMethod(readEnv("REPLICAS_CODEX_AUTH_METHOD")),
|
|
312
|
+
REPLICAS_AGENT_CREDENTIALS: parseAgentCredentialSnapshots(readEnv("REPLICAS_AGENT_CREDENTIALS")),
|
|
313
|
+
REPLICAS_ENV_SYSTEM_PROMPT: readEnv("REPLICAS_ENV_SYSTEM_PROMPT"),
|
|
314
|
+
REPLICAS_ENV_START_HOOK: readEnv("REPLICAS_ENV_START_HOOK"),
|
|
315
|
+
REPLICAS_DISABLE_AUTO_START_HOOKS: readEnv("REPLICAS_DISABLE_AUTO_START_HOOKS")?.toLowerCase() === "true",
|
|
316
|
+
REPLICAS_ENGINE_DEFER_INITIALIZATION: readEnv("REPLICAS_ENGINE_DEFER_INITIALIZATION")?.toLowerCase() === "true"
|
|
317
|
+
};
|
|
318
|
+
if (!IS_WARMING_MODE && !env.REPLICAS_WORKSPACE_ID) {
|
|
319
|
+
console.error("REPLICAS_WORKSPACE_ID is not set \u2014 this is required in normal (non-warming) mode");
|
|
320
|
+
}
|
|
321
|
+
return env;
|
|
322
|
+
}
|
|
323
|
+
var ENGINE_ENV = loadEngineEnv();
|
|
324
|
+
function setAgentCredentialSnapshot(provider, snapshot) {
|
|
325
|
+
ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS = {
|
|
326
|
+
...ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS,
|
|
327
|
+
[provider]: snapshot
|
|
328
|
+
};
|
|
329
|
+
process.env.REPLICAS_AGENT_CREDENTIALS = JSON.stringify(ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS);
|
|
330
|
+
}
|
|
331
|
+
|
|
167
332
|
// src/services/credential-fallbacks.ts
|
|
168
333
|
var fallbacksByAgent = /* @__PURE__ */ new Map();
|
|
169
334
|
var exhaustedByAgent = /* @__PURE__ */ new Map();
|
|
@@ -384,7 +549,7 @@ var monolithService = new MonolithService();
|
|
|
384
549
|
|
|
385
550
|
// src/utils/file.ts
|
|
386
551
|
import { mkdir, readFile, rename, unlink, writeFile } from "fs/promises";
|
|
387
|
-
import { dirname, join } from "path";
|
|
552
|
+
import { dirname, join as join3 } from "path";
|
|
388
553
|
|
|
389
554
|
// src/utils/async-lock.ts
|
|
390
555
|
var AsyncLock = class {
|
|
@@ -417,8 +582,8 @@ async function writeSecureCredentialFile(filePath, content, options) {
|
|
|
417
582
|
await atomicWriteFile(filePath, content, { mode: 384 });
|
|
418
583
|
}
|
|
419
584
|
async function configureManagedGitCredentialHelper(homeDir) {
|
|
420
|
-
const credentialsPath =
|
|
421
|
-
const helperPath =
|
|
585
|
+
const credentialsPath = join3(homeDir, ".git-credentials");
|
|
586
|
+
const helperPath = join3(homeDir, GIT_CREDENTIAL_HELPER_FILENAME);
|
|
422
587
|
await atomicWriteFile(helperPath, buildGitCredentialHelperScript(credentialsPath), { mode: 448 });
|
|
423
588
|
await execFileAsync("git", ["config", "--global", "credential.helper", helperPath], {
|
|
424
589
|
env: { ...process.env, HOME: homeDir }
|
|
@@ -453,15 +618,15 @@ function removeCredentialFileLines(filePath, shouldRemove) {
|
|
|
453
618
|
// src/git/service.ts
|
|
454
619
|
import { readdir, readFile as readFile3, stat } from "fs/promises";
|
|
455
620
|
import { spawn } from "child_process";
|
|
456
|
-
import { join as
|
|
621
|
+
import { join as join6 } from "path";
|
|
457
622
|
|
|
458
623
|
// src/utils/state.ts
|
|
459
624
|
import { readFile as readFile2, mkdir as mkdir2 } from "fs/promises";
|
|
460
625
|
import { existsSync } from "fs";
|
|
461
|
-
import { join as
|
|
462
|
-
import { homedir } from "os";
|
|
463
|
-
var STATE_DIR =
|
|
464
|
-
var STATE_FILE =
|
|
626
|
+
import { join as join4 } from "path";
|
|
627
|
+
import { homedir as homedir3 } from "os";
|
|
628
|
+
var STATE_DIR = join4(homedir3(), ".replicas");
|
|
629
|
+
var STATE_FILE = join4(STATE_DIR, "engine-state.json");
|
|
465
630
|
var DEFAULT_STATE = {
|
|
466
631
|
repos: {}
|
|
467
632
|
};
|
|
@@ -558,8 +723,8 @@ async function saveRepoState(repoName, state, fallbackState) {
|
|
|
558
723
|
}
|
|
559
724
|
|
|
560
725
|
// src/git/commands.ts
|
|
561
|
-
import { readFileSync } from "fs";
|
|
562
|
-
import { join as
|
|
726
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
727
|
+
import { join as join5 } from "path";
|
|
563
728
|
async function runGitCommand(args, cwd, options = {}) {
|
|
564
729
|
const { stdout } = await execFileAsync("git", args, {
|
|
565
730
|
cwd,
|
|
@@ -570,7 +735,7 @@ async function runGitCommand(args, cwd, options = {}) {
|
|
|
570
735
|
}
|
|
571
736
|
function readRepoHeadBranch(repoPath) {
|
|
572
737
|
try {
|
|
573
|
-
const contents =
|
|
738
|
+
const contents = readFileSync3(join5(repoPath, ".git", "HEAD"), "utf-8").trim();
|
|
574
739
|
const match = contents.match(/^ref:\s+refs\/heads\/(.+)$/);
|
|
575
740
|
return match ? match[1] : null;
|
|
576
741
|
} catch {
|
|
@@ -632,13 +797,13 @@ var GitService = class {
|
|
|
632
797
|
const repos = [];
|
|
633
798
|
let complete = true;
|
|
634
799
|
for (const entry of entries) {
|
|
635
|
-
const fullPath =
|
|
800
|
+
const fullPath = join6(root, entry);
|
|
636
801
|
try {
|
|
637
802
|
const entryStat = await stat(fullPath);
|
|
638
803
|
if (!entryStat.isDirectory()) {
|
|
639
804
|
continue;
|
|
640
805
|
}
|
|
641
|
-
const hasGit = Boolean(await this.safeStat(
|
|
806
|
+
const hasGit = Boolean(await this.safeStat(join6(fullPath, ".git")));
|
|
642
807
|
if (!hasGit) {
|
|
643
808
|
continue;
|
|
644
809
|
}
|
|
@@ -829,7 +994,7 @@ var GitService = class {
|
|
|
829
994
|
let total = 0;
|
|
830
995
|
for (const path6 of paths) {
|
|
831
996
|
try {
|
|
832
|
-
const contents = await readFile3(
|
|
997
|
+
const contents = await readFile3(join6(repoPath, path6));
|
|
833
998
|
if (contents.length === 0 || contents.includes(0)) {
|
|
834
999
|
continue;
|
|
835
1000
|
}
|
|
@@ -1017,7 +1182,7 @@ var GitService = class {
|
|
|
1017
1182
|
}
|
|
1018
1183
|
async getGitLabAccessToken(host) {
|
|
1019
1184
|
try {
|
|
1020
|
-
const credentials = await readFile3(
|
|
1185
|
+
const credentials = await readFile3(join6(ENGINE_ENV.HOME_DIR, ".git-credentials"), "utf-8");
|
|
1021
1186
|
for (const line of credentials.split("\n")) {
|
|
1022
1187
|
const trimmed = line.trim();
|
|
1023
1188
|
if (!trimmed) continue;
|
|
@@ -1502,8 +1667,8 @@ var infisicalTokenManager = new InfisicalTokenManager();
|
|
|
1502
1667
|
|
|
1503
1668
|
// src/utils/logger.ts
|
|
1504
1669
|
import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
|
|
1505
|
-
import { homedir as
|
|
1506
|
-
import { join as
|
|
1670
|
+
import { homedir as homedir4 } from "os";
|
|
1671
|
+
import { join as join7 } from "path";
|
|
1507
1672
|
import { format } from "util";
|
|
1508
1673
|
import { randomBytes } from "crypto";
|
|
1509
1674
|
|
|
@@ -1578,7 +1743,7 @@ var StreamWriter = class {
|
|
|
1578
1743
|
};
|
|
1579
1744
|
|
|
1580
1745
|
// src/utils/logger.ts
|
|
1581
|
-
var LOG_DIR =
|
|
1746
|
+
var LOG_DIR = join7(homedir4(), ".replicas", "logs");
|
|
1582
1747
|
var EngineLogger = class {
|
|
1583
1748
|
_sessionId = null;
|
|
1584
1749
|
patched = false;
|
|
@@ -1589,7 +1754,7 @@ var EngineLogger = class {
|
|
|
1589
1754
|
async initialize() {
|
|
1590
1755
|
await mkdir3(LOG_DIR, { recursive: true });
|
|
1591
1756
|
this._sessionId = this.createSessionId();
|
|
1592
|
-
const logPath =
|
|
1757
|
+
const logPath = join7(LOG_DIR, `${this._sessionId}.log`);
|
|
1593
1758
|
await writeFile2(logPath, `=== Replicas Engine Session ${this._sessionId} ===
|
|
1594
1759
|
`, "utf-8");
|
|
1595
1760
|
this.writer.open(logPath);
|
|
@@ -1636,29 +1801,29 @@ var engineLogger = new EngineLogger();
|
|
|
1636
1801
|
// src/services/replicas-config-service.ts
|
|
1637
1802
|
import { readFile as readFile6, appendFile, writeFile as writeFile4, mkdir as mkdir6 } from "fs/promises";
|
|
1638
1803
|
import { existsSync as existsSync3 } from "fs";
|
|
1639
|
-
import { join as
|
|
1640
|
-
import { homedir as
|
|
1804
|
+
import { join as join11 } from "path";
|
|
1805
|
+
import { homedir as homedir8 } from "os";
|
|
1641
1806
|
import { spawn as spawn2 } from "child_process";
|
|
1642
1807
|
|
|
1643
1808
|
// src/services/environment-details-service.ts
|
|
1644
1809
|
import { mkdir as mkdir4, readFile as readFile4 } from "fs/promises";
|
|
1645
1810
|
import { existsSync as existsSync2 } from "fs";
|
|
1646
|
-
import { homedir as
|
|
1647
|
-
import { join as
|
|
1811
|
+
import { homedir as homedir6 } from "os";
|
|
1812
|
+
import { join as join9 } from "path";
|
|
1648
1813
|
|
|
1649
1814
|
// src/managers/agent-auth-paths.ts
|
|
1650
|
-
import { homedir as
|
|
1651
|
-
import { join as
|
|
1652
|
-
var OPENCODE_AUTH_PATH =
|
|
1653
|
-
var PI_AUTH_PATH =
|
|
1815
|
+
import { homedir as homedir5 } from "os";
|
|
1816
|
+
import { join as join8 } from "path";
|
|
1817
|
+
var OPENCODE_AUTH_PATH = join8(homedir5(), ".local", "share", "opencode", "auth.json");
|
|
1818
|
+
var PI_AUTH_PATH = join8(homedir5(), ".pi", "agent", "auth.json");
|
|
1654
1819
|
|
|
1655
1820
|
// src/services/environment-details-service.ts
|
|
1656
|
-
var REPLICAS_DIR =
|
|
1657
|
-
var DETAILS_FILE =
|
|
1658
|
-
var CLAUDE_CREDENTIALS_PATH =
|
|
1659
|
-
var CODEX_AUTH_PATH =
|
|
1660
|
-
var GH_HOSTS_PATH =
|
|
1661
|
-
var GIT_CREDENTIALS_PATH =
|
|
1821
|
+
var REPLICAS_DIR = join9(homedir6(), ".replicas");
|
|
1822
|
+
var DETAILS_FILE = join9(REPLICAS_DIR, "environment-details.json");
|
|
1823
|
+
var CLAUDE_CREDENTIALS_PATH = join9(homedir6(), ".claude", ".credentials.json");
|
|
1824
|
+
var CODEX_AUTH_PATH = join9(homedir6(), ".codex", "auth.json");
|
|
1825
|
+
var GH_HOSTS_PATH = join9(homedir6(), ".config", "gh", "hosts.yml");
|
|
1826
|
+
var GIT_CREDENTIALS_PATH = join9(homedir6(), ".git-credentials");
|
|
1662
1827
|
function detectClaudeAuthMethod() {
|
|
1663
1828
|
if (existsSync2(CLAUDE_CREDENTIALS_PATH)) {
|
|
1664
1829
|
return "oauth";
|
|
@@ -1868,8 +2033,8 @@ var environmentDetailsService = new EnvironmentDetailsService();
|
|
|
1868
2033
|
|
|
1869
2034
|
// src/services/start-hook-logs-service.ts
|
|
1870
2035
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile3, readdir as readdir2 } from "fs/promises";
|
|
1871
|
-
import { homedir as
|
|
1872
|
-
import { join as
|
|
2036
|
+
import { homedir as homedir7 } from "os";
|
|
2037
|
+
import { join as join10 } from "path";
|
|
1873
2038
|
|
|
1874
2039
|
// src/services/hook-log-files.ts
|
|
1875
2040
|
import { createHash } from "crypto";
|
|
@@ -1881,7 +2046,7 @@ function repoHookLogFilename(repoName) {
|
|
|
1881
2046
|
}
|
|
1882
2047
|
|
|
1883
2048
|
// src/services/start-hook-logs-service.ts
|
|
1884
|
-
var LOGS_DIR =
|
|
2049
|
+
var LOGS_DIR = join10(homedir7(), ".replicas", "start-hook-logs");
|
|
1885
2050
|
function withPreview(stored) {
|
|
1886
2051
|
const preview = buildHookOutputPreview(stored.output);
|
|
1887
2052
|
return { ...stored, ...preview };
|
|
@@ -1919,7 +2084,7 @@ var StartHookLogsService = class {
|
|
|
1919
2084
|
await this.ensureDir();
|
|
1920
2085
|
const log = { hookType, hookName, repoName: hookName, ...entry };
|
|
1921
2086
|
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
1922
|
-
await writeFile3(
|
|
2087
|
+
await writeFile3(join10(LOGS_DIR, filename), `${JSON.stringify(log, null, 2)}
|
|
1923
2088
|
`, "utf-8");
|
|
1924
2089
|
}
|
|
1925
2090
|
async saveEnvironmentLog(entry) {
|
|
@@ -1944,7 +2109,7 @@ var StartHookLogsService = class {
|
|
|
1944
2109
|
continue;
|
|
1945
2110
|
}
|
|
1946
2111
|
try {
|
|
1947
|
-
const raw = await readFile5(
|
|
2112
|
+
const raw = await readFile5(join10(LOGS_DIR, file), "utf-8");
|
|
1948
2113
|
const stored = normalizeStored(JSON.parse(raw));
|
|
1949
2114
|
if (stored) {
|
|
1950
2115
|
logs.push(withPreview(stored));
|
|
@@ -1963,7 +2128,7 @@ var StartHookLogsService = class {
|
|
|
1963
2128
|
async getFullOutput(hookType, hookName) {
|
|
1964
2129
|
const filename = hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
1965
2130
|
try {
|
|
1966
|
-
const raw = await readFile5(
|
|
2131
|
+
const raw = await readFile5(join10(LOGS_DIR, filename), "utf-8");
|
|
1967
2132
|
const stored = normalizeStored(JSON.parse(raw));
|
|
1968
2133
|
if (!stored || stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
1969
2134
|
return null;
|
|
@@ -1980,7 +2145,7 @@ var StartHookLogsService = class {
|
|
|
1980
2145
|
var startHookLogsService = new StartHookLogsService();
|
|
1981
2146
|
|
|
1982
2147
|
// src/services/replicas-config-service.ts
|
|
1983
|
-
var START_HOOKS_LOG =
|
|
2148
|
+
var START_HOOKS_LOG = join11(homedir8(), ".replicas", "startHooks.log");
|
|
1984
2149
|
var START_HOOKS_RUNNING_PROMPT = `IMPORTANT - Start Hooks Running:
|
|
1985
2150
|
Start hooks are shell commands/scripts set by repository owners that run on workspace startup.
|
|
1986
2151
|
These hooks are currently executing in the background. You can:
|
|
@@ -1991,7 +2156,7 @@ The start hooks may install dependencies, build projects, or perform other setup
|
|
|
1991
2156
|
If your task depends on setup being complete, check the log file before proceeding.`;
|
|
1992
2157
|
async function readReplicasConfigFromDir(dirPath) {
|
|
1993
2158
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
1994
|
-
const configPath =
|
|
2159
|
+
const configPath = join11(dirPath, filename);
|
|
1995
2160
|
if (!existsSync3(configPath)) {
|
|
1996
2161
|
continue;
|
|
1997
2162
|
}
|
|
@@ -2061,7 +2226,7 @@ var ReplicasConfigService = class {
|
|
|
2061
2226
|
const logLine = `[${timestamp}] ${message}
|
|
2062
2227
|
`;
|
|
2063
2228
|
try {
|
|
2064
|
-
await mkdir6(
|
|
2229
|
+
await mkdir6(join11(homedir8(), ".replicas"), { recursive: true });
|
|
2065
2230
|
await appendFile(START_HOOKS_LOG, logLine, "utf-8");
|
|
2066
2231
|
} catch (error) {
|
|
2067
2232
|
console.error("Failed to write to start hooks log:", error);
|
|
@@ -2073,7 +2238,7 @@ var ReplicasConfigService = class {
|
|
|
2073
2238
|
command: params.content,
|
|
2074
2239
|
label: "env start hook",
|
|
2075
2240
|
repoName: "environment",
|
|
2076
|
-
cwd:
|
|
2241
|
+
cwd: homedir8(),
|
|
2077
2242
|
timeout: params.timeoutMs ?? DEFAULT_START_HOOK_TIMEOUT_MS,
|
|
2078
2243
|
onOutputChunk: params.onOutputChunk
|
|
2079
2244
|
});
|
|
@@ -2196,7 +2361,7 @@ var ReplicasConfigService = class {
|
|
|
2196
2361
|
this.hooksCompleted = false;
|
|
2197
2362
|
this.hooksFailed = false;
|
|
2198
2363
|
try {
|
|
2199
|
-
await mkdir6(
|
|
2364
|
+
await mkdir6(join11(homedir8(), ".replicas"), { recursive: true });
|
|
2200
2365
|
await writeFile4(
|
|
2201
2366
|
START_HOOKS_LOG,
|
|
2202
2367
|
`=== Start Hooks Execution Log ===
|
|
@@ -2391,11 +2556,11 @@ var replicasConfigService = new ReplicasConfigService();
|
|
|
2391
2556
|
|
|
2392
2557
|
// src/services/event-service.ts
|
|
2393
2558
|
import { mkdir as mkdir7 } from "fs/promises";
|
|
2394
|
-
import { homedir as
|
|
2395
|
-
import { join as
|
|
2559
|
+
import { homedir as homedir9 } from "os";
|
|
2560
|
+
import { join as join12 } from "path";
|
|
2396
2561
|
import { randomUUID } from "crypto";
|
|
2397
|
-
var ENGINE_DIR =
|
|
2398
|
-
var EVENTS_FILE =
|
|
2562
|
+
var ENGINE_DIR = join12(homedir9(), ".replicas", "engine");
|
|
2563
|
+
var EVENTS_FILE = join12(ENGINE_DIR, "events.jsonl");
|
|
2399
2564
|
var EventService = class {
|
|
2400
2565
|
subscribers = /* @__PURE__ */ new Map();
|
|
2401
2566
|
writer = new StreamWriter();
|
|
@@ -2429,9 +2594,9 @@ var eventService = new EventService();
|
|
|
2429
2594
|
import { mkdir as mkdir8, readFile as readFile7 } from "fs/promises";
|
|
2430
2595
|
import { existsSync as existsSync4 } from "fs";
|
|
2431
2596
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2432
|
-
import { homedir as
|
|
2433
|
-
import { dirname as dirname2, join as
|
|
2434
|
-
var PREVIEW_PORTS_FILE =
|
|
2597
|
+
import { homedir as homedir10 } from "os";
|
|
2598
|
+
import { dirname as dirname2, join as join13 } from "path";
|
|
2599
|
+
var PREVIEW_PORTS_FILE = join13(homedir10(), ".replicas", "preview-ports.json");
|
|
2435
2600
|
async function readPreviewsFile() {
|
|
2436
2601
|
try {
|
|
2437
2602
|
if (!existsSync4(PREVIEW_PORTS_FILE)) {
|
|
@@ -2543,8 +2708,8 @@ async function registerDesktopPreview() {
|
|
|
2543
2708
|
// src/services/chat/chat-service.ts
|
|
2544
2709
|
import { existsSync as existsSync7 } from "fs";
|
|
2545
2710
|
import { appendFile as appendFile4, copyFile, mkdir as mkdir15, readFile as readFile15, rename as rename3, rm as rm2 } from "fs/promises";
|
|
2546
|
-
import { homedir as
|
|
2547
|
-
import { join as
|
|
2711
|
+
import { homedir as homedir15 } from "os";
|
|
2712
|
+
import { join as join28 } from "path";
|
|
2548
2713
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
2549
2714
|
|
|
2550
2715
|
// src/managers/claude-manager.ts
|
|
@@ -2552,9 +2717,9 @@ import {
|
|
|
2552
2717
|
query
|
|
2553
2718
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
2554
2719
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
2555
|
-
import { dirname as dirname4, join as
|
|
2720
|
+
import { dirname as dirname4, join as join17 } from "path";
|
|
2556
2721
|
import { mkdir as mkdir10 } from "fs/promises";
|
|
2557
|
-
import { homedir as
|
|
2722
|
+
import { homedir as homedir12 } from "os";
|
|
2558
2723
|
|
|
2559
2724
|
// src/utils/linear-converter.ts
|
|
2560
2725
|
function linearThoughtToResponse(thought) {
|
|
@@ -2939,8 +3104,8 @@ function extractPlanFromCodexAspNotification(notification) {
|
|
|
2939
3104
|
// src/utils/image-utils.ts
|
|
2940
3105
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2941
3106
|
import { mkdir as mkdir9, unlink as unlink2, writeFile as writeFile5 } from "fs/promises";
|
|
2942
|
-
import { homedir as
|
|
2943
|
-
import { join as
|
|
3107
|
+
import { homedir as homedir11 } from "os";
|
|
3108
|
+
import { join as join14 } from "path";
|
|
2944
3109
|
function isImageMediaType(value) {
|
|
2945
3110
|
return IMAGE_MEDIA_TYPES.includes(value);
|
|
2946
3111
|
}
|
|
@@ -3040,14 +3205,14 @@ async function normalizeImages(images) {
|
|
|
3040
3205
|
}
|
|
3041
3206
|
return normalized;
|
|
3042
3207
|
}
|
|
3043
|
-
async function saveNormalizedImagesToTempFiles(images, tempImageDir =
|
|
3208
|
+
async function saveNormalizedImagesToTempFiles(images, tempImageDir = join14(homedir11(), ".replicas", "codex", "temp-images")) {
|
|
3044
3209
|
await mkdir9(tempImageDir, { recursive: true });
|
|
3045
3210
|
const tempPaths = [];
|
|
3046
3211
|
try {
|
|
3047
3212
|
for (const image of images) {
|
|
3048
3213
|
const ext = image.source.media_type.split("/")[1] || "png";
|
|
3049
3214
|
const filename = `img_${randomUUID3()}.${ext}`;
|
|
3050
|
-
const filepath =
|
|
3215
|
+
const filepath = join14(tempImageDir, filename);
|
|
3051
3216
|
await writeFile5(filepath, Buffer.from(image.source.data, "base64"));
|
|
3052
3217
|
tempPaths.push(filepath);
|
|
3053
3218
|
}
|
|
@@ -3062,8 +3227,8 @@ async function removeTempImageFiles(paths) {
|
|
|
3062
3227
|
}
|
|
3063
3228
|
|
|
3064
3229
|
// src/managers/coding-agent-manager.ts
|
|
3065
|
-
import { readFileSync as
|
|
3066
|
-
import { join as
|
|
3230
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3231
|
+
import { join as join15 } from "path";
|
|
3067
3232
|
|
|
3068
3233
|
// src/managers/auth-fallback.ts
|
|
3069
3234
|
var SWAPPABLE_AGENTS = {
|
|
@@ -3527,7 +3692,7 @@ var CodingAgentManager = class {
|
|
|
3527
3692
|
buildMemoryInstruction() {
|
|
3528
3693
|
const readSummary = (scope) => {
|
|
3529
3694
|
try {
|
|
3530
|
-
return
|
|
3695
|
+
return readFileSync4(join15(MEMORY_ROOT, scope, MEMORY_SUMMARY_FILENAME), "utf8").trim();
|
|
3531
3696
|
} catch {
|
|
3532
3697
|
return "";
|
|
3533
3698
|
}
|
|
@@ -3548,6 +3713,47 @@ ${seat}
|
|
|
3548
3713
|
}
|
|
3549
3714
|
};
|
|
3550
3715
|
|
|
3716
|
+
// src/utils/agent-env.ts
|
|
3717
|
+
function resolveClaudeAuthMethodForMessage(env = ENGINE_ENV) {
|
|
3718
|
+
const method = env.REPLICAS_CLAUDE_AUTH_METHOD;
|
|
3719
|
+
if (method && method !== "none") {
|
|
3720
|
+
return method;
|
|
3721
|
+
}
|
|
3722
|
+
if (env.CLAUDE_CODE_USE_BEDROCK === "1") return "bedrock";
|
|
3723
|
+
if (env.ANTHROPIC_API_KEY) return "api_key";
|
|
3724
|
+
return "unknown";
|
|
3725
|
+
}
|
|
3726
|
+
function buildClaudeAgentEnv(overrides) {
|
|
3727
|
+
const env = { ...process.env };
|
|
3728
|
+
if (overrides) {
|
|
3729
|
+
Object.assign(env, overrides);
|
|
3730
|
+
}
|
|
3731
|
+
const isBedrock = isClaudeBedrockEnv(env);
|
|
3732
|
+
if (shouldStripAnthropicApiKey(isBedrock)) {
|
|
3733
|
+
env.ANTHROPIC_API_KEY = void 0;
|
|
3734
|
+
}
|
|
3735
|
+
if (isBedrock) {
|
|
3736
|
+
env.CLAUDE_CODE_USE_BEDROCK = "1";
|
|
3737
|
+
env.CLAUDE_CODE_USE_MANTLE = "1";
|
|
3738
|
+
env.ANTHROPIC_DEFAULT_OPUS_MODEL = CLAUDE_OPUS_4_8_BEDROCK_MODEL;
|
|
3739
|
+
env.ANTHROPIC_DEFAULT_SONNET_MODEL = CLAUDE_SONNET_5_BEDROCK_MODEL;
|
|
3740
|
+
env.ANTHROPIC_DEFAULT_HAIKU_MODEL = CLAUDE_HAIKU_4_5_BEDROCK_MODEL;
|
|
3741
|
+
}
|
|
3742
|
+
env.GH_TOKEN = void 0;
|
|
3743
|
+
env.GITHUB_TOKEN = void 0;
|
|
3744
|
+
env.GH_CONFIG_DIR = void 0;
|
|
3745
|
+
env.CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD = "1";
|
|
3746
|
+
env.CLAUDE_CODE_DISABLE_AUTO_MEMORY = "1";
|
|
3747
|
+
return env;
|
|
3748
|
+
}
|
|
3749
|
+
function shouldStripAnthropicApiKey(isBedrock) {
|
|
3750
|
+
const method = ENGINE_ENV.REPLICAS_CLAUDE_AUTH_METHOD;
|
|
3751
|
+
return method === "oauth" || method === "bedrock" || method === "foundry" || isBedrock;
|
|
3752
|
+
}
|
|
3753
|
+
function isClaudeBedrockEnv(env) {
|
|
3754
|
+
return ENGINE_ENV.REPLICAS_CLAUDE_AUTH_METHOD === "bedrock" || env.REPLICAS_CLAUDE_AUTH_METHOD === "bedrock" || env.CLAUDE_CODE_USE_BEDROCK === "1";
|
|
3755
|
+
}
|
|
3756
|
+
|
|
3551
3757
|
// src/utils/agent-additional-directories.ts
|
|
3552
3758
|
async function getAgentAdditionalDirectories() {
|
|
3553
3759
|
try {
|
|
@@ -3681,7 +3887,7 @@ function reportCommandProtectionBlock(options) {
|
|
|
3681
3887
|
|
|
3682
3888
|
// src/services/skill-registry-service.ts
|
|
3683
3889
|
import { readFile as readFile8, readdir as readdir3, stat as stat2 } from "fs/promises";
|
|
3684
|
-
import { dirname as dirname3, isAbsolute, join as
|
|
3890
|
+
import { dirname as dirname3, isAbsolute, join as join16, relative, resolve } from "path";
|
|
3685
3891
|
var REGISTRY_ROOT_DIR = ".replicas/skill-registries";
|
|
3686
3892
|
var REGISTRY_MANIFEST = "manifest.json";
|
|
3687
3893
|
async function getSkillRegistryInventory(homeDir) {
|
|
@@ -3742,10 +3948,10 @@ async function scanRegistry(registryDir) {
|
|
|
3742
3948
|
}
|
|
3743
3949
|
async function findSkillCollections(registryDir) {
|
|
3744
3950
|
const candidateRoots = [
|
|
3745
|
-
{ source: "skills", root:
|
|
3746
|
-
{ source: "agents", root:
|
|
3747
|
-
{ source: "codex", root:
|
|
3748
|
-
{ source: "claude", root:
|
|
3951
|
+
{ source: "skills", root: join16(registryDir, "skills") },
|
|
3952
|
+
{ source: "agents", root: join16(registryDir, ".agents", "skills") },
|
|
3953
|
+
{ source: "codex", root: join16(registryDir, ".codex", "skills") },
|
|
3954
|
+
{ source: "claude", root: join16(registryDir, ".claude", "skills") }
|
|
3749
3955
|
];
|
|
3750
3956
|
const collections = [];
|
|
3751
3957
|
for (const { source, root } of candidateRoots) {
|
|
@@ -3759,9 +3965,9 @@ async function findSkillCollections(registryDir) {
|
|
|
3759
3965
|
async function findSkillDirsInRoot(root) {
|
|
3760
3966
|
const skillDirs = [];
|
|
3761
3967
|
for (const dirent of await safeReadDir(root)) {
|
|
3762
|
-
const skillDir =
|
|
3968
|
+
const skillDir = join16(root, dirent.name);
|
|
3763
3969
|
if (!await isDirectoryDirent(dirent, skillDir)) continue;
|
|
3764
|
-
if (await fileExists(
|
|
3970
|
+
if (await fileExists(join16(skillDir, "SKILL.md"))) {
|
|
3765
3971
|
skillDirs.push(skillDir);
|
|
3766
3972
|
}
|
|
3767
3973
|
}
|
|
@@ -3771,9 +3977,9 @@ async function findTopLevelSkills(registryDir) {
|
|
|
3771
3977
|
const skills = [];
|
|
3772
3978
|
for (const dirent of await safeReadDir(registryDir)) {
|
|
3773
3979
|
if (dirent.name.startsWith(".") || dirent.name === "skills" || dirent.name === "plugins") continue;
|
|
3774
|
-
const skillDir =
|
|
3980
|
+
const skillDir = join16(registryDir, dirent.name);
|
|
3775
3981
|
if (!await isDirectoryDirent(dirent, skillDir)) continue;
|
|
3776
|
-
if (await fileExists(
|
|
3982
|
+
if (await fileExists(join16(skillDir, "SKILL.md"))) {
|
|
3777
3983
|
skills.push({ source: "root", skillDir });
|
|
3778
3984
|
}
|
|
3779
3985
|
}
|
|
@@ -3784,10 +3990,10 @@ async function findClaudePluginRoots(registryDir) {
|
|
|
3784
3990
|
async function walk(dir) {
|
|
3785
3991
|
for (const dirent of await safeReadDir(dir)) {
|
|
3786
3992
|
if (dirent.name === ".git") continue;
|
|
3787
|
-
const child =
|
|
3993
|
+
const child = join16(dir, dirent.name);
|
|
3788
3994
|
if (!await isDirectoryDirent(dirent, child)) continue;
|
|
3789
3995
|
if (dirent.name === ".claude-plugin") {
|
|
3790
|
-
if (await fileExists(
|
|
3996
|
+
if (await fileExists(join16(child, "plugin.json"))) {
|
|
3791
3997
|
roots.push(dirname3(child));
|
|
3792
3998
|
}
|
|
3793
3999
|
continue;
|
|
@@ -3799,7 +4005,7 @@ async function findClaudePluginRoots(registryDir) {
|
|
|
3799
4005
|
return uniqueStrings(roots);
|
|
3800
4006
|
}
|
|
3801
4007
|
async function hasCodexMarketplace(registryDir) {
|
|
3802
|
-
return await fileExists(
|
|
4008
|
+
return await fileExists(join16(registryDir, ".agents", "plugins", "marketplace.json")) || await fileExists(join16(registryDir, ".codex", "plugins", "marketplace.json"));
|
|
3803
4009
|
}
|
|
3804
4010
|
async function installCodexRegistryPlugins(client, inventory) {
|
|
3805
4011
|
const cwds = inventory.codexMarketplaceCwds;
|
|
@@ -3841,10 +4047,10 @@ async function readManifest(homeDir) {
|
|
|
3841
4047
|
}
|
|
3842
4048
|
}
|
|
3843
4049
|
function getRegistryRoot(homeDir) {
|
|
3844
|
-
return
|
|
4050
|
+
return join16(homeDir, REGISTRY_ROOT_DIR);
|
|
3845
4051
|
}
|
|
3846
4052
|
function getManifestPath(homeDir) {
|
|
3847
|
-
return
|
|
4053
|
+
return join16(getRegistryRoot(homeDir), REGISTRY_MANIFEST);
|
|
3848
4054
|
}
|
|
3849
4055
|
function emptyInventory(registryRoot) {
|
|
3850
4056
|
return {
|
|
@@ -4322,7 +4528,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
4322
4528
|
authRetrying = false;
|
|
4323
4529
|
constructor(options) {
|
|
4324
4530
|
super({ ...options, provider: AGENT.CLAUDE });
|
|
4325
|
-
this.historyFilePath = options.historyFilePath ??
|
|
4531
|
+
this.historyFilePath = options.historyFilePath ?? join17(homedir12(), ".replicas", "claude", "history.jsonl");
|
|
4326
4532
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
4327
4533
|
this.systemPromptOverride = options.systemPromptOverride;
|
|
4328
4534
|
this.toolsOverride = options.tools;
|
|
@@ -5346,7 +5552,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5346
5552
|
|
|
5347
5553
|
// src/managers/codex-asp/codex-asp-manager.ts
|
|
5348
5554
|
import { readdir as readdir4 } from "fs/promises";
|
|
5349
|
-
import { join as
|
|
5555
|
+
import { join as join19 } from "path";
|
|
5350
5556
|
|
|
5351
5557
|
// src/managers/codex-asp/asp-host.ts
|
|
5352
5558
|
var hostPromise = null;
|
|
@@ -5358,7 +5564,10 @@ async function getCodexAspHost() {
|
|
|
5358
5564
|
}
|
|
5359
5565
|
hostPromise ??= (async () => {
|
|
5360
5566
|
try {
|
|
5361
|
-
const process2 = new AppServerProcess(
|
|
5567
|
+
const process2 = new AppServerProcess({
|
|
5568
|
+
cwd: ENGINE_ENV.WORKSPACE_ROOT,
|
|
5569
|
+
env: buildCodexAgentEnv()
|
|
5570
|
+
});
|
|
5362
5571
|
const { client } = await process2.start();
|
|
5363
5572
|
activeProcess = process2;
|
|
5364
5573
|
process2.on("exit", () => {
|
|
@@ -5456,7 +5665,7 @@ var CodexQuotaStatusTracker = class {
|
|
|
5456
5665
|
};
|
|
5457
5666
|
|
|
5458
5667
|
// src/managers/codex-asp/mappers.ts
|
|
5459
|
-
import { existsSync as existsSync5, readFileSync as
|
|
5668
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
5460
5669
|
var localImageCache = /* @__PURE__ */ new Map();
|
|
5461
5670
|
var DEFAULT_MODEL = DEFAULT_CODEX_MODEL;
|
|
5462
5671
|
var THREAD_START_METHOD = "thread/start";
|
|
@@ -5579,7 +5788,7 @@ function userImageForLocalPath(path6) {
|
|
|
5579
5788
|
const image = {
|
|
5580
5789
|
type: "image",
|
|
5581
5790
|
mediaType: inferMediaType(path6),
|
|
5582
|
-
data:
|
|
5791
|
+
data: readFileSync5(path6).toString("base64")
|
|
5583
5792
|
};
|
|
5584
5793
|
if (image.data.length > 0) localImageCache.set(path6, image);
|
|
5585
5794
|
return image;
|
|
@@ -6013,29 +6222,6 @@ async function buildTurnStartParams(threadId, request, serviceTier) {
|
|
|
6013
6222
|
};
|
|
6014
6223
|
}
|
|
6015
6224
|
|
|
6016
|
-
// src/managers/codex-asp/notification-dispatch.ts
|
|
6017
|
-
var TURN_STARTED_METHOD = "turn/started";
|
|
6018
|
-
var TURN_COMPLETED_METHOD = "turn/completed";
|
|
6019
|
-
var TURN_PLAN_UPDATED_METHOD = "turn/plan/updated";
|
|
6020
|
-
var THREAD_GOAL_UPDATED_METHOD = "thread/goal/updated";
|
|
6021
|
-
var THREAD_GOAL_CLEARED_METHOD = "thread/goal/cleared";
|
|
6022
|
-
var ITEM_STARTED_METHOD = "item/started";
|
|
6023
|
-
var ITEM_COMPLETED_METHOD = "item/completed";
|
|
6024
|
-
var AGENT_MESSAGE_DELTA_METHOD = "item/agentMessage/delta";
|
|
6025
|
-
var REASONING_SUMMARY_TEXT_DELTA_METHOD = "item/reasoning/summaryTextDelta";
|
|
6026
|
-
var REASONING_TEXT_DELTA_METHOD = "item/reasoning/textDelta";
|
|
6027
|
-
var REASONING_SUMMARY_PART_ADDED_METHOD = "item/reasoning/summaryPartAdded";
|
|
6028
|
-
var COMMAND_EXECUTION_OUTPUT_DELTA_METHOD = "item/commandExecution/outputDelta";
|
|
6029
|
-
var FILE_CHANGE_OUTPUT_DELTA_METHOD = "item/fileChange/outputDelta";
|
|
6030
|
-
var ACCOUNT_RATE_LIMITS_UPDATED_METHOD = "account/rateLimits/updated";
|
|
6031
|
-
var THREAD_TOKEN_USAGE_UPDATED_METHOD = "thread/tokenUsage/updated";
|
|
6032
|
-
var THREAD_COMPACTED_METHOD = "thread/compacted";
|
|
6033
|
-
function dispatchAspNotification(notification, handlers) {
|
|
6034
|
-
const handler = handlers[notification.method];
|
|
6035
|
-
if (!handler) return;
|
|
6036
|
-
handler(notification);
|
|
6037
|
-
}
|
|
6038
|
-
|
|
6039
6225
|
// src/managers/codex-asp/transcript-update-coalescer.ts
|
|
6040
6226
|
var TRANSCRIPT_UPDATE_COALESCE_MS = 1e3;
|
|
6041
6227
|
var TranscriptUpdateCoalescer = class {
|
|
@@ -6096,16 +6282,16 @@ var TranscriptUpdateCoalescer = class {
|
|
|
6096
6282
|
};
|
|
6097
6283
|
|
|
6098
6284
|
// src/services/chat/history-paths.ts
|
|
6099
|
-
import { homedir as
|
|
6100
|
-
import { join as
|
|
6101
|
-
var ENGINE_DIR2 =
|
|
6102
|
-
var CHATS_FILE =
|
|
6103
|
-
var CLAUDE_HISTORY_DIR =
|
|
6104
|
-
var RELAY_HISTORY_DIR =
|
|
6105
|
-
var CODEX_HISTORY_DIR =
|
|
6106
|
-
var CURSOR_HISTORY_DIR =
|
|
6107
|
-
var OPENCODE_HISTORY_DIR =
|
|
6108
|
-
var PI_HISTORY_DIR =
|
|
6285
|
+
import { homedir as homedir13 } from "os";
|
|
6286
|
+
import { join as join18 } from "path";
|
|
6287
|
+
var ENGINE_DIR2 = join18(homedir13(), ".replicas", "engine");
|
|
6288
|
+
var CHATS_FILE = join18(ENGINE_DIR2, "chats.json");
|
|
6289
|
+
var CLAUDE_HISTORY_DIR = join18(ENGINE_DIR2, "claude-histories");
|
|
6290
|
+
var RELAY_HISTORY_DIR = join18(ENGINE_DIR2, "relay-histories");
|
|
6291
|
+
var CODEX_HISTORY_DIR = join18(ENGINE_DIR2, "codex-histories");
|
|
6292
|
+
var CURSOR_HISTORY_DIR = join18(ENGINE_DIR2, "cursor-histories");
|
|
6293
|
+
var OPENCODE_HISTORY_DIR = join18(ENGINE_DIR2, "opencode-histories");
|
|
6294
|
+
var PI_HISTORY_DIR = join18(ENGINE_DIR2, "pi-histories");
|
|
6109
6295
|
var HISTORY_DIR_BY_PROVIDER = {
|
|
6110
6296
|
claude: CLAUDE_HISTORY_DIR,
|
|
6111
6297
|
relay: RELAY_HISTORY_DIR,
|
|
@@ -6161,7 +6347,7 @@ async function readCodexAspThreadHistory(threadId) {
|
|
|
6161
6347
|
}
|
|
6162
6348
|
for (const entry of entries) {
|
|
6163
6349
|
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
6164
|
-
const history = await new CodexHistoryFile(
|
|
6350
|
+
const history = await new CodexHistoryFile(join19(CODEX_HISTORY_DIR, entry.name)).load();
|
|
6165
6351
|
const transcript = history.transcriptsByThreadId.get(threadId);
|
|
6166
6352
|
if (transcript) {
|
|
6167
6353
|
return {
|
|
@@ -6810,27 +6996,7 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
6810
6996
|
if (notification.params.threadId !== threadId) return;
|
|
6811
6997
|
if (!observedTurnIds.has(notification.params.turn.id)) return;
|
|
6812
6998
|
observedTurnId = notification.params.turn.id;
|
|
6813
|
-
const
|
|
6814
|
-
const items = turn.items.length > 0 ? [...turn.items] : [];
|
|
6815
|
-
const itemIds = new Set(items.map((item) => item.id));
|
|
6816
|
-
for (const item of completedItems) {
|
|
6817
|
-
if (!itemIds.has(item.id)) {
|
|
6818
|
-
items.push(item);
|
|
6819
|
-
itemIds.add(item.id);
|
|
6820
|
-
}
|
|
6821
|
-
}
|
|
6822
|
-
for (const [itemId, text] of agentMessageDeltas) {
|
|
6823
|
-
if (!itemIds.has(itemId)) {
|
|
6824
|
-
items.push({
|
|
6825
|
-
type: "agentMessage",
|
|
6826
|
-
id: itemId,
|
|
6827
|
-
text,
|
|
6828
|
-
phase: null,
|
|
6829
|
-
memoryCitation: null
|
|
6830
|
-
});
|
|
6831
|
-
}
|
|
6832
|
-
}
|
|
6833
|
-
const completedTurn = items.length > 0 ? { ...turn, items, itemsView: "full" } : turn;
|
|
6999
|
+
const completedTurn = recoverCompletedTurn(notification.params.turn, completedItems, agentMessageDeltas);
|
|
6834
7000
|
this.mergeTranscriptTurn(notification.params.threadId, completedTurn);
|
|
6835
7001
|
this.emitTranscriptUpdated(notification.params.threadId, { immediate: true });
|
|
6836
7002
|
lastCompletedTurn = completedTurn;
|
|
@@ -7445,7 +7611,7 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
7445
7611
|
|
|
7446
7612
|
// src/managers/cursor-manager.ts
|
|
7447
7613
|
import { mkdir as mkdir11, readFile as readFile10, readdir as readdir5 } from "fs/promises";
|
|
7448
|
-
import { basename, dirname as dirname5, extname, join as
|
|
7614
|
+
import { basename, dirname as dirname5, extname, join as join20 } from "path";
|
|
7449
7615
|
import { parse as parseYaml } from "yaml";
|
|
7450
7616
|
import { Agent as CursorAgent } from "@cursor/sdk";
|
|
7451
7617
|
var CURSOR_SLASH_COMMANDS_CACHE_MS = 3e4;
|
|
@@ -7504,7 +7670,7 @@ async function listCursorCommandsInDirectory(directory) {
|
|
|
7504
7670
|
const name = basename(entry.name, ".md");
|
|
7505
7671
|
let description;
|
|
7506
7672
|
try {
|
|
7507
|
-
description = extractCursorCommandDescription(await readFile10(
|
|
7673
|
+
description = extractCursorCommandDescription(await readFile10(join20(directory, entry.name), "utf8"));
|
|
7508
7674
|
} catch (error) {
|
|
7509
7675
|
console.warn("[CursorManager] Failed to read slash command file:", error);
|
|
7510
7676
|
}
|
|
@@ -7526,7 +7692,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
7526
7692
|
slashCommandsRequest = null;
|
|
7527
7693
|
constructor(options) {
|
|
7528
7694
|
super(options);
|
|
7529
|
-
this.historyFilePath = options.historyFilePath ??
|
|
7695
|
+
this.historyFilePath = options.historyFilePath ?? join20(ENGINE_ENV.HOME_DIR, ".replicas", "cursor", "history.jsonl");
|
|
7530
7696
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
7531
7697
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
7532
7698
|
}
|
|
@@ -7577,7 +7743,7 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
7577
7743
|
this.slashCommandsRequest ??= (async () => {
|
|
7578
7744
|
try {
|
|
7579
7745
|
const repoDirectories = await getAgentAdditionalDirectories();
|
|
7580
|
-
const commandDirectories = [this.workingDirectory, ...repoDirectories, ENGINE_ENV.HOME_DIR].map((directory) =>
|
|
7746
|
+
const commandDirectories = [this.workingDirectory, ...repoDirectories, ENGINE_ENV.HOME_DIR].map((directory) => join20(directory, ".cursor", "commands"));
|
|
7581
7747
|
const commands = mergeSlashCommands(
|
|
7582
7748
|
...await Promise.all(commandDirectories.map(listCursorCommandsInDirectory))
|
|
7583
7749
|
);
|
|
@@ -7838,7 +8004,7 @@ ${instructions}
|
|
|
7838
8004
|
// src/managers/opencode-manager.ts
|
|
7839
8005
|
import { existsSync as existsSync6 } from "fs";
|
|
7840
8006
|
import { mkdir as mkdir12, readFile as readFile11 } from "fs/promises";
|
|
7841
|
-
import { delimiter, dirname as dirname6, join as
|
|
8007
|
+
import { delimiter, dirname as dirname6, join as join21 } from "path";
|
|
7842
8008
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
7843
8009
|
import { fileURLToPath } from "url";
|
|
7844
8010
|
import { Agent } from "undici";
|
|
@@ -7885,7 +8051,7 @@ async function getAllowedOpenRouterModels() {
|
|
|
7885
8051
|
|
|
7886
8052
|
// src/managers/opencode-manager.ts
|
|
7887
8053
|
var OPENCODE_SHIM_DIR = dirname6(fileURLToPath(new URL("../../scripts/opencode", import.meta.url)));
|
|
7888
|
-
var OPENCODE_CONFIG_PATH =
|
|
8054
|
+
var OPENCODE_CONFIG_PATH = join21(ENGINE_ENV.HOME_DIR, ".config", "opencode", "opencode.json");
|
|
7889
8055
|
var OPENCODE_FETCH_DISPATCHER = new Agent({ headersTimeout: 0, bodyTimeout: 0 });
|
|
7890
8056
|
var OPENCODE_SERVER_STARTUP_TIMEOUT_MS = 3e4;
|
|
7891
8057
|
var OPENCODE_WORKSPACE_PERMISSION = {
|
|
@@ -8135,7 +8301,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
8135
8301
|
constructor(options) {
|
|
8136
8302
|
super(options);
|
|
8137
8303
|
this.sessionId = options.initialSessionId;
|
|
8138
|
-
this.historyFilePath = options.historyFilePath ??
|
|
8304
|
+
this.historyFilePath = options.historyFilePath ?? join21(ENGINE_ENV.HOME_DIR, ".replicas", "opencode", "history.jsonl");
|
|
8139
8305
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
8140
8306
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
8141
8307
|
}
|
|
@@ -8645,7 +8811,7 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
8645
8811
|
|
|
8646
8812
|
// src/managers/pi-manager.ts
|
|
8647
8813
|
import { mkdir as mkdir13 } from "fs/promises";
|
|
8648
|
-
import { dirname as dirname7, join as
|
|
8814
|
+
import { dirname as dirname7, join as join22 } from "path";
|
|
8649
8815
|
import {
|
|
8650
8816
|
AuthStorage,
|
|
8651
8817
|
createAgentSession,
|
|
@@ -8728,7 +8894,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
8728
8894
|
providerApiKey = null;
|
|
8729
8895
|
constructor(options) {
|
|
8730
8896
|
super(options);
|
|
8731
|
-
this.historyFilePath = options.historyFilePath ??
|
|
8897
|
+
this.historyFilePath = options.historyFilePath ?? join22(PI_HISTORY_DIR, `${Date.now()}.jsonl`);
|
|
8732
8898
|
this.historyFile = new CodexHistoryFile(this.historyFilePath);
|
|
8733
8899
|
this.initializeManager(this.processMessageInternal.bind(this));
|
|
8734
8900
|
}
|
|
@@ -8828,7 +8994,7 @@ var PiManager = class extends CodingAgentManager {
|
|
|
8828
8994
|
const sessionManager = this.initialSessionId ? SessionManager.open(this.initialSessionId, PI_HISTORY_DIR, this.workingDirectory) : SessionManager.create(this.workingDirectory, PI_HISTORY_DIR);
|
|
8829
8995
|
const resourceLoader = new DefaultResourceLoader({
|
|
8830
8996
|
cwd: this.workingDirectory,
|
|
8831
|
-
agentDir:
|
|
8997
|
+
agentDir: join22(ENGINE_ENV.HOME_DIR, ".pi", "agent"),
|
|
8832
8998
|
extensionFactories: [registerCommandProtection(
|
|
8833
8999
|
this.workingDirectory,
|
|
8834
9000
|
this.historyFile,
|
|
@@ -9516,7 +9682,7 @@ import {
|
|
|
9516
9682
|
rename as rename2,
|
|
9517
9683
|
unlink as unlink3
|
|
9518
9684
|
} from "fs/promises";
|
|
9519
|
-
import { join as
|
|
9685
|
+
import { join as join23 } from "path";
|
|
9520
9686
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
9521
9687
|
|
|
9522
9688
|
// src/analytics/agent/activity/skill-mcp-call-extractor.ts
|
|
@@ -9567,7 +9733,7 @@ var AgentChatActivityBuffer = class {
|
|
|
9567
9733
|
options.storageName,
|
|
9568
9734
|
...options.legacyStorageNames ?? []
|
|
9569
9735
|
];
|
|
9570
|
-
this.liveFile =
|
|
9736
|
+
this.liveFile = join23(ENGINE_DIR2, `${options.storageName}.jsonl`);
|
|
9571
9737
|
this.segmentFilePatterns = this.storageNames.map(
|
|
9572
9738
|
(storageName) => new RegExp(`^${storageName}\\.(\\d+)\\.jsonl$`)
|
|
9573
9739
|
);
|
|
@@ -9626,8 +9792,8 @@ var AgentChatActivityBuffer = class {
|
|
|
9626
9792
|
await Promise.allSettled([...this.pendingAppends]);
|
|
9627
9793
|
for (const storageName of this.storageNames) {
|
|
9628
9794
|
await rename2(
|
|
9629
|
-
|
|
9630
|
-
|
|
9795
|
+
join23(ENGINE_DIR2, `${storageName}.jsonl`),
|
|
9796
|
+
join23(ENGINE_DIR2, `${storageName}.${Date.now()}.jsonl`)
|
|
9631
9797
|
).catch(() => {
|
|
9632
9798
|
});
|
|
9633
9799
|
}
|
|
@@ -9638,7 +9804,7 @@ var AgentChatActivityBuffer = class {
|
|
|
9638
9804
|
if (!this.segmentFilePatterns.some((pattern) => pattern.test(entry)))
|
|
9639
9805
|
continue;
|
|
9640
9806
|
try {
|
|
9641
|
-
await this.uploadSegment(
|
|
9807
|
+
await this.uploadSegment(join23(ENGINE_DIR2, entry));
|
|
9642
9808
|
flushed++;
|
|
9643
9809
|
} catch (error) {
|
|
9644
9810
|
failed++;
|
|
@@ -9670,7 +9836,7 @@ var AgentChatActivityBuffer = class {
|
|
|
9670
9836
|
) && entry.endsWith(UPLOADED_SUFFIX)
|
|
9671
9837
|
).sort();
|
|
9672
9838
|
for (const entry of uploaded.slice(0, -MAX_UPLOADED_SEGMENTS)) {
|
|
9673
|
-
await unlink3(
|
|
9839
|
+
await unlink3(join23(ENGINE_DIR2, entry)).catch(() => {
|
|
9674
9840
|
});
|
|
9675
9841
|
}
|
|
9676
9842
|
return { flushed, failed };
|
|
@@ -9902,18 +10068,18 @@ var keepAliveService = new KeepAliveService();
|
|
|
9902
10068
|
|
|
9903
10069
|
// src/services/canvas-service.ts
|
|
9904
10070
|
import { readdir as readdir7, readFile as readFile13, stat as stat3 } from "fs/promises";
|
|
9905
|
-
import { homedir as
|
|
9906
|
-
import { join as
|
|
10071
|
+
import { homedir as homedir14 } from "os";
|
|
10072
|
+
import { join as join24 } from "path";
|
|
9907
10073
|
var GLOBAL_CANVAS_DIRECTORIES = [
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
10074
|
+
join24(homedir14(), ".claude", "plans"),
|
|
10075
|
+
join24(process.env.XDG_DATA_HOME ?? join24(homedir14(), ".local", "share"), "opencode", "plans"),
|
|
10076
|
+
join24(homedir14(), ".replicas", "canvas")
|
|
9911
10077
|
];
|
|
9912
10078
|
async function canvasDirectories() {
|
|
9913
10079
|
const repositories = await gitService.listRepositories().catch(() => []);
|
|
9914
10080
|
return [
|
|
9915
10081
|
...GLOBAL_CANVAS_DIRECTORIES,
|
|
9916
|
-
...repositories.map((repository) =>
|
|
10082
|
+
...repositories.map((repository) => join24(repository.path, ".opencode", "plans"))
|
|
9917
10083
|
];
|
|
9918
10084
|
}
|
|
9919
10085
|
var CanvasService = class {
|
|
@@ -9937,7 +10103,7 @@ var CanvasService = class {
|
|
|
9937
10103
|
for (const entry of entries) {
|
|
9938
10104
|
if (entry.name.startsWith(".")) continue;
|
|
9939
10105
|
const filename = current.relativePath ? `${current.relativePath}/${entry.name}` : entry.name;
|
|
9940
|
-
const filePath =
|
|
10106
|
+
const filePath = join24(current.directory, entry.name);
|
|
9941
10107
|
if (entry.isDirectory()) {
|
|
9942
10108
|
pending.push({ directory: filePath, relativePath: filename });
|
|
9943
10109
|
continue;
|
|
@@ -9962,7 +10128,7 @@ var CanvasService = class {
|
|
|
9962
10128
|
if (!safe) return null;
|
|
9963
10129
|
const { kind, mimeType } = classifyCanvasFilename(safe);
|
|
9964
10130
|
for (const directory of await this.directories()) {
|
|
9965
|
-
const filePath =
|
|
10131
|
+
const filePath = join24(directory, safe);
|
|
9966
10132
|
let sizeBytes = 0;
|
|
9967
10133
|
let updatedAt = "";
|
|
9968
10134
|
try {
|
|
@@ -10134,13 +10300,13 @@ async function reconcileCanvasItems(filenames) {
|
|
|
10134
10300
|
import { createReadStream } from "fs";
|
|
10135
10301
|
import { createHash as createHash2 } from "crypto";
|
|
10136
10302
|
import { readdir as readdir8, readFile as readFile14, stat as stat4 } from "fs/promises";
|
|
10137
|
-
import { basename as basename2, join as
|
|
10303
|
+
import { basename as basename2, join as join26 } from "path";
|
|
10138
10304
|
|
|
10139
10305
|
// src/services/chat/chat-senders.ts
|
|
10140
|
-
import { join as
|
|
10141
|
-
var CHAT_SENDERS_DIR =
|
|
10306
|
+
import { join as join25 } from "path";
|
|
10307
|
+
var CHAT_SENDERS_DIR = join25(ENGINE_DIR2, "chat-senders");
|
|
10142
10308
|
function chatMessageSendersFilePath(chatId) {
|
|
10143
|
-
return
|
|
10309
|
+
return join25(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
|
|
10144
10310
|
}
|
|
10145
10311
|
function parseChatMessageSendersJsonl(content) {
|
|
10146
10312
|
return content.split("\n").flatMap((line) => {
|
|
@@ -10156,9 +10322,9 @@ function parseChatMessageSendersJsonl(content) {
|
|
|
10156
10322
|
|
|
10157
10323
|
// src/services/upload-chat-transcripts.ts
|
|
10158
10324
|
var HISTORY_DIRS = [
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
|
|
10325
|
+
join26(ENGINE_DIR2, "claude-histories"),
|
|
10326
|
+
join26(ENGINE_DIR2, "relay-histories"),
|
|
10327
|
+
join26(ENGINE_DIR2, "codex-histories")
|
|
10162
10328
|
];
|
|
10163
10329
|
async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map(), capture) {
|
|
10164
10330
|
let flushed = 0;
|
|
@@ -10176,7 +10342,7 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map(), ca
|
|
|
10176
10342
|
if (!entry.endsWith(".jsonl")) continue;
|
|
10177
10343
|
const chatId = basename2(entry, ".jsonl");
|
|
10178
10344
|
tasks.push(
|
|
10179
|
-
uploadChatTranscript(chatId,
|
|
10345
|
+
uploadChatTranscript(chatId, join26(dir, entry), chatsById.get(chatId), capture).then((artifact) => {
|
|
10180
10346
|
flushed++;
|
|
10181
10347
|
if (artifact && capture) revisions.push(artifact);
|
|
10182
10348
|
}).catch((err) => {
|
|
@@ -10278,7 +10444,7 @@ async function flushRepoState() {
|
|
|
10278
10444
|
// src/services/upload-engine-logs.ts
|
|
10279
10445
|
import { createReadStream as createReadStream2 } from "fs";
|
|
10280
10446
|
import { readdir as readdir9, stat as stat5 } from "fs/promises";
|
|
10281
|
-
import { join as
|
|
10447
|
+
import { join as join27 } from "path";
|
|
10282
10448
|
var MAX_ENGINE_LOG_FLUSH_SESSIONS = 10;
|
|
10283
10449
|
var MAX_ENGINE_LOG_FLUSH_BYTES = 5 * 1024 * 1024;
|
|
10284
10450
|
var ENGINE_LOG_FLUSH_TIMEOUT_MS = 2e4;
|
|
@@ -10307,7 +10473,7 @@ async function flushAllEngineLogs() {
|
|
|
10307
10473
|
const candidates = (await Promise.all(filenames.slice(0, MAX_ENGINE_LOG_FLUSH_SESSIONS).map(async (filename) => {
|
|
10308
10474
|
try {
|
|
10309
10475
|
const sessionId = filename.slice(0, -".log".length);
|
|
10310
|
-
const filePath =
|
|
10476
|
+
const filePath = join27(LOG_DIR, filename);
|
|
10311
10477
|
const fileStat = await runBeforeDeadline(() => stat5(filePath), deadline);
|
|
10312
10478
|
if (!fileStat.isFile()) {
|
|
10313
10479
|
skipped++;
|
|
@@ -10403,7 +10569,7 @@ async function uploadEngineLog(input, timeoutMs) {
|
|
|
10403
10569
|
}
|
|
10404
10570
|
|
|
10405
10571
|
// src/services/chat/chat-service.ts
|
|
10406
|
-
var CODEX_AUTH_PATH2 =
|
|
10572
|
+
var CODEX_AUTH_PATH2 = join28(homedir15(), ".codex", "auth.json");
|
|
10407
10573
|
var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
|
|
10408
10574
|
function isCodexAvailable() {
|
|
10409
10575
|
return existsSync7(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
|
|
@@ -10897,7 +11063,7 @@ var ChatService = class {
|
|
|
10897
11063
|
return descendants;
|
|
10898
11064
|
}
|
|
10899
11065
|
async deleteHistoryFile(persisted) {
|
|
10900
|
-
await rm2(
|
|
11066
|
+
await rm2(join28(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
|
|
10901
11067
|
await rm2(chatMessageSendersFilePath(persisted.id), { force: true });
|
|
10902
11068
|
}
|
|
10903
11069
|
async getChatHistory(chatId, page = {}) {
|
|
@@ -11002,7 +11168,7 @@ var ChatService = class {
|
|
|
11002
11168
|
if (persisted.provider === "claude") {
|
|
11003
11169
|
provider = new ClaudeManager({
|
|
11004
11170
|
workingDirectory: this.workingDirectory,
|
|
11005
|
-
historyFilePath:
|
|
11171
|
+
historyFilePath: join28(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
11006
11172
|
initialSessionId: persisted.providerSessionId,
|
|
11007
11173
|
onSaveSessionId: saveSession,
|
|
11008
11174
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -11012,7 +11178,7 @@ var ChatService = class {
|
|
|
11012
11178
|
} else if (persisted.provider === "relay") {
|
|
11013
11179
|
provider = new RelayManager({
|
|
11014
11180
|
workingDirectory: this.workingDirectory,
|
|
11015
|
-
historyFilePath:
|
|
11181
|
+
historyFilePath: join28(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
11016
11182
|
initialSessionId: persisted.providerSessionId,
|
|
11017
11183
|
onSaveSessionId: saveSession,
|
|
11018
11184
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -11027,7 +11193,7 @@ var ChatService = class {
|
|
|
11027
11193
|
} else if (persisted.provider === "cursor") {
|
|
11028
11194
|
provider = new CursorManager({
|
|
11029
11195
|
workingDirectory: this.workingDirectory,
|
|
11030
|
-
historyFilePath:
|
|
11196
|
+
historyFilePath: join28(CURSOR_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
11031
11197
|
initialSessionId: persisted.providerSessionId,
|
|
11032
11198
|
onSaveSessionId: saveSession,
|
|
11033
11199
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -11037,7 +11203,7 @@ var ChatService = class {
|
|
|
11037
11203
|
} else if (persisted.provider === "opencode") {
|
|
11038
11204
|
provider = new OpencodeManager({
|
|
11039
11205
|
workingDirectory: this.workingDirectory,
|
|
11040
|
-
historyFilePath:
|
|
11206
|
+
historyFilePath: join28(OPENCODE_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
11041
11207
|
initialSessionId: persisted.providerSessionId,
|
|
11042
11208
|
onSaveSessionId: saveSession,
|
|
11043
11209
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -11047,7 +11213,7 @@ var ChatService = class {
|
|
|
11047
11213
|
} else if (persisted.provider === "pi") {
|
|
11048
11214
|
provider = new PiManager({
|
|
11049
11215
|
workingDirectory: this.workingDirectory,
|
|
11050
|
-
historyFilePath:
|
|
11216
|
+
historyFilePath: join28(PI_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
11051
11217
|
initialSessionId: persisted.providerSessionId,
|
|
11052
11218
|
onSaveSessionId: saveSession,
|
|
11053
11219
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -11057,7 +11223,7 @@ var ChatService = class {
|
|
|
11057
11223
|
} else {
|
|
11058
11224
|
provider = new CodexAspManager({
|
|
11059
11225
|
workingDirectory: this.workingDirectory,
|
|
11060
|
-
historyFilePath:
|
|
11226
|
+
historyFilePath: join28(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
|
|
11061
11227
|
initialSessionId: persisted.providerSessionId,
|
|
11062
11228
|
onSaveSessionId: saveSession,
|
|
11063
11229
|
onTurnComplete: onProviderTurnComplete,
|
|
@@ -11221,7 +11387,7 @@ var ChatService = class {
|
|
|
11221
11387
|
});
|
|
11222
11388
|
uploadChatTranscript(
|
|
11223
11389
|
chatId,
|
|
11224
|
-
|
|
11390
|
+
join28(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
|
|
11225
11391
|
this.toSummary(chat)
|
|
11226
11392
|
).catch((err) => {
|
|
11227
11393
|
console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
|
|
@@ -11359,7 +11525,7 @@ var ChatService = class {
|
|
|
11359
11525
|
// src/services/repo-file-service.ts
|
|
11360
11526
|
import { execFile } from "child_process";
|
|
11361
11527
|
import { readFile as readFile16, realpath, stat as stat6 } from "fs/promises";
|
|
11362
|
-
import { join as
|
|
11528
|
+
import { join as join29, resolve as resolve2, extname as extname2 } from "path";
|
|
11363
11529
|
var CACHE_TTL_MS = 3e4;
|
|
11364
11530
|
var SEARCH_TIMEOUT_MS = 15e3;
|
|
11365
11531
|
var MAX_CONTENT_BYTES = 256 * 1024;
|
|
@@ -11511,7 +11677,7 @@ var RepoFileService = class {
|
|
|
11511
11677
|
const repo = repos.find((r) => r.name === repoName);
|
|
11512
11678
|
if (!repo) return null;
|
|
11513
11679
|
try {
|
|
11514
|
-
const fullPath = await realpath(resolve2(
|
|
11680
|
+
const fullPath = await realpath(resolve2(join29(repo.path, filePath)));
|
|
11515
11681
|
const repoRoot = await realpath(repo.path);
|
|
11516
11682
|
const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
|
|
11517
11683
|
if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
|
|
@@ -11646,20 +11812,20 @@ var RepoFileService = class {
|
|
|
11646
11812
|
import { Hono } from "hono";
|
|
11647
11813
|
import { z as z4 } from "zod";
|
|
11648
11814
|
import { readdir as readdir11, stat as stat7, readFile as readFile19 } from "fs/promises";
|
|
11649
|
-
import { join as
|
|
11815
|
+
import { join as join32, resolve as resolve3 } from "path";
|
|
11650
11816
|
|
|
11651
11817
|
// src/services/warm-hooks-service.ts
|
|
11652
11818
|
import { spawn as spawn3 } from "child_process";
|
|
11653
11819
|
import { readFile as readFile18 } from "fs/promises";
|
|
11654
11820
|
import { existsSync as existsSync8 } from "fs";
|
|
11655
|
-
import { join as
|
|
11821
|
+
import { join as join31 } from "path";
|
|
11656
11822
|
|
|
11657
11823
|
// src/services/warm-hook-logs-service.ts
|
|
11658
11824
|
import { mkdir as mkdir16, readFile as readFile17, writeFile as writeFile6, readdir as readdir10, appendFile as appendFile5, unlink as unlink4 } from "fs/promises";
|
|
11659
|
-
import { homedir as
|
|
11660
|
-
import { join as
|
|
11661
|
-
var LOGS_DIR2 =
|
|
11662
|
-
var CURRENT_RUN_LOG =
|
|
11825
|
+
import { homedir as homedir16 } from "os";
|
|
11826
|
+
import { join as join30 } from "path";
|
|
11827
|
+
var LOGS_DIR2 = join30(homedir16(), ".replicas", "warm-hook-logs");
|
|
11828
|
+
var CURRENT_RUN_LOG = join30(LOGS_DIR2, "current-run.log");
|
|
11663
11829
|
var GLOBAL_FILENAME = "global.json";
|
|
11664
11830
|
function withPreview2(stored) {
|
|
11665
11831
|
const preview = buildHookOutputPreview(stored.output);
|
|
@@ -11676,7 +11842,7 @@ var WarmHookLogsService = class {
|
|
|
11676
11842
|
hookName: "organization",
|
|
11677
11843
|
...entry
|
|
11678
11844
|
};
|
|
11679
|
-
await writeFile6(
|
|
11845
|
+
await writeFile6(join30(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
11680
11846
|
`, "utf-8");
|
|
11681
11847
|
}
|
|
11682
11848
|
async saveEnvironmentHookLog(entry) {
|
|
@@ -11686,7 +11852,7 @@ var WarmHookLogsService = class {
|
|
|
11686
11852
|
hookName: "environment",
|
|
11687
11853
|
...entry
|
|
11688
11854
|
};
|
|
11689
|
-
await writeFile6(
|
|
11855
|
+
await writeFile6(join30(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
|
|
11690
11856
|
`, "utf-8");
|
|
11691
11857
|
}
|
|
11692
11858
|
async saveRepoHookLog(repoName, entry) {
|
|
@@ -11696,7 +11862,7 @@ var WarmHookLogsService = class {
|
|
|
11696
11862
|
hookName: repoName,
|
|
11697
11863
|
...entry
|
|
11698
11864
|
};
|
|
11699
|
-
await writeFile6(
|
|
11865
|
+
await writeFile6(join30(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
|
|
11700
11866
|
`, "utf-8");
|
|
11701
11867
|
}
|
|
11702
11868
|
async getAllLogs() {
|
|
@@ -11715,7 +11881,7 @@ var WarmHookLogsService = class {
|
|
|
11715
11881
|
continue;
|
|
11716
11882
|
}
|
|
11717
11883
|
try {
|
|
11718
|
-
const raw = await readFile17(
|
|
11884
|
+
const raw = await readFile17(join30(LOGS_DIR2, file), "utf-8");
|
|
11719
11885
|
const stored = JSON.parse(raw);
|
|
11720
11886
|
logs.push(withPreview2(stored));
|
|
11721
11887
|
} catch {
|
|
@@ -11753,7 +11919,7 @@ var WarmHookLogsService = class {
|
|
|
11753
11919
|
async getFullOutput(hookType, hookName) {
|
|
11754
11920
|
const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
11755
11921
|
try {
|
|
11756
|
-
const raw = await readFile17(
|
|
11922
|
+
const raw = await readFile17(join30(LOGS_DIR2, filename), "utf-8");
|
|
11757
11923
|
const stored = JSON.parse(raw);
|
|
11758
11924
|
if (stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
11759
11925
|
return null;
|
|
@@ -11772,7 +11938,7 @@ var warmHookLogsService = new WarmHookLogsService();
|
|
|
11772
11938
|
// src/services/warm-hooks-service.ts
|
|
11773
11939
|
async function readRepoWarmHook(repoPath) {
|
|
11774
11940
|
for (const filename of REPLICAS_CONFIG_FILENAMES) {
|
|
11775
|
-
const configPath =
|
|
11941
|
+
const configPath = join31(repoPath, filename);
|
|
11776
11942
|
if (!existsSync8(configPath)) {
|
|
11777
11943
|
continue;
|
|
11778
11944
|
}
|
|
@@ -13036,7 +13202,7 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
13036
13202
|
const logFiles = files.filter((f) => f.endsWith(".log"));
|
|
13037
13203
|
const sessions = await Promise.all(
|
|
13038
13204
|
logFiles.map(async (filename) => {
|
|
13039
|
-
const filePath =
|
|
13205
|
+
const filePath = join32(LOG_DIR, filename);
|
|
13040
13206
|
const fileStat = await stat7(filePath);
|
|
13041
13207
|
const sessionId = filename.replace(/\.log$/, "");
|
|
13042
13208
|
return {
|