replicas-engine 0.1.711 → 0.1.713
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-F4HJ4HAT.js → chunk-4TBCMRGQ.js} +2 -2
- package/dist/src/{chunk-VTONH6X5.js → chunk-GSMOYM7N.js} +7 -1
- package/dist/src/{chunk-Z7X6ZWKP.js → chunk-JSCZVP7Q.js} +1 -1
- package/dist/src/{chunk-SI3I5LZI.js → chunk-OF3EDBVV.js} +1 -1
- package/dist/src/command-protection-hook.js +2 -2
- package/dist/src/deepseek-command-protection-plugin.js +3 -3
- package/dist/src/headless-agent.js +2 -2
- package/dist/src/index.js +137 -48
- package/dist/src/post-tool-pr-hook.js +2 -2
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
HOOK_EXEC_MAX_BUFFER_BYTES,
|
|
4
4
|
isVersionBelow
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GSMOYM7N.js";
|
|
6
6
|
|
|
7
7
|
// src/utils/presigned-upload.ts
|
|
8
8
|
import { createReadStream } from "fs";
|
|
@@ -267,7 +267,7 @@ var DEFAULT_CODEX_ARGS = [
|
|
|
267
267
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
268
268
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
269
269
|
var codexCliVersionEnsured = null;
|
|
270
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
270
|
+
var ENGINE_PACKAGE_VERSION = "0.1.713";
|
|
271
271
|
var INITIALIZE_METHOD = "initialize";
|
|
272
272
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
273
273
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -536,7 +536,8 @@ function serializeCanvasContentResponse(input) {
|
|
|
536
536
|
filename: input.filename,
|
|
537
537
|
kind: input.kind,
|
|
538
538
|
sizeBytes: input.sizeBytes,
|
|
539
|
-
mimeType: input.mimeType
|
|
539
|
+
mimeType: input.mimeType,
|
|
540
|
+
revision: input.revision
|
|
540
541
|
};
|
|
541
542
|
if (isCanvasTextKind(input.kind)) {
|
|
542
543
|
return { ...base, content: new TextDecoder().decode(input.bytes) };
|
|
@@ -4066,6 +4067,9 @@ var AUDIT_LOG_ACTIONS = Object.values(AUDIT_LOG_ACTION);
|
|
|
4066
4067
|
// ../shared/src/automations/types.ts
|
|
4067
4068
|
var AUTOMATION_DEBOUNCE_MAX_SECONDS = 24 * 60 * 60;
|
|
4068
4069
|
|
|
4070
|
+
// ../shared/src/routes/repo-files.ts
|
|
4071
|
+
var MAX_REPO_FILE_CONTENT_BYTES = 256 * 1024;
|
|
4072
|
+
|
|
4069
4073
|
// ../shared/src/routes/admin.ts
|
|
4070
4074
|
var WEBHOOK_PROVIDERS = ["linear", "github", "gitlab", "slack", "e2b", "stripe", "sentry"];
|
|
4071
4075
|
var WEBHOOK_PROVIDER_SET = new Set(WEBHOOK_PROVIDERS);
|
|
@@ -6685,6 +6689,7 @@ export {
|
|
|
6685
6689
|
IMAGE_MEDIA_TYPES,
|
|
6686
6690
|
MAX_CANVAS_FILE_BYTES,
|
|
6687
6691
|
MAX_CANVAS_PREVIEW_BYTES,
|
|
6692
|
+
isCanvasTextKind,
|
|
6688
6693
|
sanitizeCanvasFilename,
|
|
6689
6694
|
serializeCanvasContentResponse,
|
|
6690
6695
|
classifyCanvasFilename,
|
|
@@ -6768,6 +6773,7 @@ export {
|
|
|
6768
6773
|
findPrMergeSignals,
|
|
6769
6774
|
findGitCommitSignals,
|
|
6770
6775
|
mayCreatePullRequest,
|
|
6776
|
+
MAX_REPO_FILE_CONTENT_BYTES,
|
|
6771
6777
|
coerceBackgroundTaskPayload,
|
|
6772
6778
|
isTerminalBackgroundTaskStatus,
|
|
6773
6779
|
areUserMessagesWithinMatchWindow,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
evaluateCommandProtection
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JSCZVP7Q.js";
|
|
5
5
|
import {
|
|
6
6
|
isRecord
|
|
7
7
|
} from "./chunk-2RB7SIP3.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-GSMOYM7N.js";
|
|
9
9
|
|
|
10
10
|
// src/command-protection-hook.ts
|
|
11
11
|
var provider = process.argv[2];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
evaluateCommandProtection
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JSCZVP7Q.js";
|
|
5
5
|
import {
|
|
6
6
|
notifyPostToolUse
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OF3EDBVV.js";
|
|
8
8
|
import "./chunk-2RB7SIP3.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-GSMOYM7N.js";
|
|
10
10
|
|
|
11
11
|
// src/deepseek-command-protection-plugin.ts
|
|
12
12
|
function replicasCommandProtection(context) {
|
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
buildCodexAgentEnv,
|
|
5
5
|
putPresignedFile,
|
|
6
6
|
recoverCompletedTurn
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4TBCMRGQ.js";
|
|
8
8
|
import {
|
|
9
9
|
AGENT,
|
|
10
10
|
getMemoryOutputSafetyViolation,
|
|
11
11
|
headlessAgentRequestSchema
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GSMOYM7N.js";
|
|
13
13
|
|
|
14
14
|
// src/headless-agent.ts
|
|
15
15
|
import { createHash } from "crypto";
|
package/dist/src/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
monolithService,
|
|
9
9
|
reportCommandProtectionBlock,
|
|
10
10
|
setAgentCredentialSnapshot
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-JSCZVP7Q.js";
|
|
12
12
|
import {
|
|
13
13
|
ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
|
|
14
14
|
AGENT_MESSAGE_DELTA_METHOD,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
execFileAsync,
|
|
36
36
|
putPresignedFile,
|
|
37
37
|
recoverCompletedTurn
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-4TBCMRGQ.js";
|
|
39
39
|
import {
|
|
40
40
|
isRecord as isRecord2
|
|
41
41
|
} from "./chunk-2RB7SIP3.js";
|
|
@@ -97,6 +97,7 @@ import {
|
|
|
97
97
|
MAX_CANVAS_FILE_BYTES,
|
|
98
98
|
MAX_CANVAS_PREVIEW_BYTES,
|
|
99
99
|
MAX_CODEX_GOAL_OBJECTIVE_CHARS,
|
|
100
|
+
MAX_REPO_FILE_CONTENT_BYTES,
|
|
100
101
|
MEMORY_INDEX_FILENAME,
|
|
101
102
|
MEMORY_ROOT,
|
|
102
103
|
MERGED_MESSAGE_SEPARATOR,
|
|
@@ -165,6 +166,7 @@ import {
|
|
|
165
166
|
isAgentChatMcpActivityRecord,
|
|
166
167
|
isAgentChatSkillActivityRecord,
|
|
167
168
|
isAgentChatTurnActivityRecord,
|
|
169
|
+
isCanvasTextKind,
|
|
168
170
|
isChatMessageSender,
|
|
169
171
|
isClaudeAuthErrorText,
|
|
170
172
|
isClaudeResultError,
|
|
@@ -211,7 +213,7 @@ import {
|
|
|
211
213
|
shellQuotePosix,
|
|
212
214
|
stripAgentDiagnosticErrors,
|
|
213
215
|
withTimeout
|
|
214
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-GSMOYM7N.js";
|
|
215
217
|
|
|
216
218
|
// src/index.ts
|
|
217
219
|
import { serve } from "@hono/node-server";
|
|
@@ -2627,7 +2629,7 @@ async function registerDesktopPreview() {
|
|
|
2627
2629
|
|
|
2628
2630
|
// src/services/chat/chat-service.ts
|
|
2629
2631
|
import { existsSync as existsSync11 } from "fs";
|
|
2630
|
-
import { appendFile as appendFile4, copyFile as copyFile2, mkdir as mkdir18, readFile as
|
|
2632
|
+
import { appendFile as appendFile4, copyFile as copyFile2, mkdir as mkdir18, readFile as readFile20, rename as rename3, rm as rm3 } from "fs/promises";
|
|
2631
2633
|
import { join as join28 } from "path";
|
|
2632
2634
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
2633
2635
|
|
|
@@ -11929,9 +11931,49 @@ var KeepAliveService = class _KeepAliveService {
|
|
|
11929
11931
|
var keepAliveService = new KeepAliveService();
|
|
11930
11932
|
|
|
11931
11933
|
// src/services/canvas-service.ts
|
|
11932
|
-
import { readdir as readdir7, readFile as
|
|
11934
|
+
import { readdir as readdir7, readFile as readFile18, stat as stat4 } from "fs/promises";
|
|
11933
11935
|
import { homedir as homedir12 } from "os";
|
|
11934
11936
|
import { join as join24 } from "path";
|
|
11937
|
+
|
|
11938
|
+
// src/utils/contained-file.ts
|
|
11939
|
+
import { realpath, stat as stat3 } from "fs/promises";
|
|
11940
|
+
import { resolve as resolve2 } from "path";
|
|
11941
|
+
async function resolveContainedFile(root, relativePath) {
|
|
11942
|
+
try {
|
|
11943
|
+
const [fullPath, resolvedRoot] = await Promise.all([
|
|
11944
|
+
realpath(resolve2(root, relativePath)),
|
|
11945
|
+
realpath(root)
|
|
11946
|
+
]);
|
|
11947
|
+
const fileStat = await stat3(fullPath);
|
|
11948
|
+
const rootPrefix = resolvedRoot.endsWith("/") ? resolvedRoot : `${resolvedRoot}/`;
|
|
11949
|
+
return fullPath.startsWith(rootPrefix) && fileStat.isFile() ? { fullPath, sizeBytes: fileStat.size } : null;
|
|
11950
|
+
} catch {
|
|
11951
|
+
return null;
|
|
11952
|
+
}
|
|
11953
|
+
}
|
|
11954
|
+
|
|
11955
|
+
// src/utils/file-revision.ts
|
|
11956
|
+
import { createHash as createHash3 } from "crypto";
|
|
11957
|
+
function fileRevision(content) {
|
|
11958
|
+
return createHash3("sha256").update(content).digest("hex");
|
|
11959
|
+
}
|
|
11960
|
+
|
|
11961
|
+
// src/utils/revisioned-text-file.ts
|
|
11962
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
11963
|
+
async function writeRevisionedTextFile(filePath, content, expectedRevision) {
|
|
11964
|
+
const current = await readFile17(filePath, "utf8");
|
|
11965
|
+
const revision = fileRevision(current);
|
|
11966
|
+
if (revision !== expectedRevision) {
|
|
11967
|
+
return {
|
|
11968
|
+
saved: false,
|
|
11969
|
+
current: { content: current, revision, sizeBytes: Buffer.byteLength(current) }
|
|
11970
|
+
};
|
|
11971
|
+
}
|
|
11972
|
+
await atomicWriteFile(filePath, content);
|
|
11973
|
+
return { saved: true, revision: fileRevision(content), sizeBytes: Buffer.byteLength(content) };
|
|
11974
|
+
}
|
|
11975
|
+
|
|
11976
|
+
// src/services/canvas-service.ts
|
|
11935
11977
|
var GLOBAL_CANVAS_DIRECTORIES = [
|
|
11936
11978
|
join24(homedir12(), ".claude", "plans"),
|
|
11937
11979
|
join24(process.env.XDG_DATA_HOME ?? join24(homedir12(), ".local", "share"), "opencode", "plans"),
|
|
@@ -11949,6 +11991,7 @@ var CanvasService = class {
|
|
|
11949
11991
|
this.directories = directories;
|
|
11950
11992
|
}
|
|
11951
11993
|
directories;
|
|
11994
|
+
writeLock = new AsyncLock();
|
|
11952
11995
|
async listItems() {
|
|
11953
11996
|
const items = /* @__PURE__ */ new Map();
|
|
11954
11997
|
for (const directory of await this.directories()) {
|
|
@@ -11974,7 +12017,7 @@ var CanvasService = class {
|
|
|
11974
12017
|
const { kind } = classifyCanvasFilename(filename);
|
|
11975
12018
|
let sizeBytes = 0;
|
|
11976
12019
|
try {
|
|
11977
|
-
const s = await
|
|
12020
|
+
const s = await stat4(filePath);
|
|
11978
12021
|
sizeBytes = s.size;
|
|
11979
12022
|
} catch {
|
|
11980
12023
|
continue;
|
|
@@ -11994,7 +12037,7 @@ var CanvasService = class {
|
|
|
11994
12037
|
let sizeBytes = 0;
|
|
11995
12038
|
let updatedAt = "";
|
|
11996
12039
|
try {
|
|
11997
|
-
const s = await
|
|
12040
|
+
const s = await stat4(filePath);
|
|
11998
12041
|
sizeBytes = s.size;
|
|
11999
12042
|
updatedAt = s.mtime.toISOString();
|
|
12000
12043
|
} catch {
|
|
@@ -12011,7 +12054,7 @@ var CanvasService = class {
|
|
|
12011
12054
|
};
|
|
12012
12055
|
}
|
|
12013
12056
|
try {
|
|
12014
|
-
const bytes = await
|
|
12057
|
+
const bytes = await readFile18(filePath);
|
|
12015
12058
|
return { filename: safe, kind, sizeBytes, mimeType, updatedAt, bytes };
|
|
12016
12059
|
} catch {
|
|
12017
12060
|
continue;
|
|
@@ -12036,7 +12079,19 @@ var CanvasService = class {
|
|
|
12036
12079
|
kind: item.kind,
|
|
12037
12080
|
sizeBytes: item.sizeBytes,
|
|
12038
12081
|
mimeType: item.mimeType,
|
|
12039
|
-
bytes: item.bytes
|
|
12082
|
+
bytes: item.bytes,
|
|
12083
|
+
revision: fileRevision(item.bytes)
|
|
12084
|
+
});
|
|
12085
|
+
}
|
|
12086
|
+
async updateItem(filename, content, expectedRevision) {
|
|
12087
|
+
const safe = sanitizeCanvasFilename(filename);
|
|
12088
|
+
if (!safe || !isCanvasTextKind(classifyCanvasFilename(safe).kind) || Buffer.byteLength(content) > MAX_CANVAS_PREVIEW_BYTES) return null;
|
|
12089
|
+
return this.writeLock.run(async () => {
|
|
12090
|
+
for (const directory of await this.directories()) {
|
|
12091
|
+
const file = await resolveContainedFile(directory, safe);
|
|
12092
|
+
if (file) return await writeRevisionedTextFile(file.fullPath, content, expectedRevision);
|
|
12093
|
+
}
|
|
12094
|
+
return null;
|
|
12040
12095
|
});
|
|
12041
12096
|
}
|
|
12042
12097
|
};
|
|
@@ -12160,8 +12215,8 @@ async function reconcileCanvasItems(filenames) {
|
|
|
12160
12215
|
|
|
12161
12216
|
// src/services/upload-chat-transcripts.ts
|
|
12162
12217
|
import { createReadStream } from "fs";
|
|
12163
|
-
import { createHash as
|
|
12164
|
-
import { readFile as
|
|
12218
|
+
import { createHash as createHash4 } from "crypto";
|
|
12219
|
+
import { readFile as readFile19, readdir as readdir8, stat as stat5 } from "fs/promises";
|
|
12165
12220
|
import { basename as basename3, join as join26 } from "path";
|
|
12166
12221
|
|
|
12167
12222
|
// src/services/chat/chat-senders.ts
|
|
@@ -12218,9 +12273,9 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map(), ca
|
|
|
12218
12273
|
return capture ? { flushed, failed, captureSupported: true, revisions } : { flushed, failed };
|
|
12219
12274
|
}
|
|
12220
12275
|
async function uploadChatTranscript(chatId, filePath, chat, capture) {
|
|
12221
|
-
const { size } = await
|
|
12276
|
+
const { size } = await stat5(filePath);
|
|
12222
12277
|
if (size === 0) return null;
|
|
12223
|
-
const historyPages = createChatTranscriptPages(await
|
|
12278
|
+
const historyPages = createChatTranscriptPages(await readFile19(filePath));
|
|
12224
12279
|
const metadata = chat ? {
|
|
12225
12280
|
provider: chat.provider,
|
|
12226
12281
|
credential: ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS[chat.provider],
|
|
@@ -12231,7 +12286,7 @@ async function uploadChatTranscript(chatId, filePath, chat, capture) {
|
|
|
12231
12286
|
deletedAt: chat.deletedAt ?? null
|
|
12232
12287
|
} : {};
|
|
12233
12288
|
if (capture) {
|
|
12234
|
-
const hash =
|
|
12289
|
+
const hash = createHash4("sha256");
|
|
12235
12290
|
for await (const chunk of createReadStream(filePath)) hash.update(chunk);
|
|
12236
12291
|
metadata.captureId = capture.captureId;
|
|
12237
12292
|
metadata.captureReason = capture.reason;
|
|
@@ -12239,7 +12294,7 @@ async function uploadChatTranscript(chatId, filePath, chat, capture) {
|
|
|
12239
12294
|
}
|
|
12240
12295
|
try {
|
|
12241
12296
|
metadata.senders = parseChatMessageSendersJsonl(
|
|
12242
|
-
await
|
|
12297
|
+
await readFile19(chatMessageSendersFilePath(chatId), "utf-8")
|
|
12243
12298
|
);
|
|
12244
12299
|
} catch (error) {
|
|
12245
12300
|
if (!(error && typeof error === "object" && "code" in error && error.code === "ENOENT")) throw error;
|
|
@@ -12288,7 +12343,7 @@ async function uploadChatTranscript(chatId, filePath, chat, capture) {
|
|
|
12288
12343
|
|
|
12289
12344
|
// src/services/upload-engine-logs.ts
|
|
12290
12345
|
import { createReadStream as createReadStream2 } from "fs";
|
|
12291
|
-
import { readdir as readdir9, stat as
|
|
12346
|
+
import { readdir as readdir9, stat as stat6 } from "fs/promises";
|
|
12292
12347
|
import { join as join27 } from "path";
|
|
12293
12348
|
var MAX_ENGINE_LOG_FLUSH_SESSIONS = 10;
|
|
12294
12349
|
var MAX_ENGINE_LOG_FLUSH_BYTES = 5 * 1024 * 1024;
|
|
@@ -12319,7 +12374,7 @@ async function flushAllEngineLogs() {
|
|
|
12319
12374
|
try {
|
|
12320
12375
|
const sessionId = filename.slice(0, -".log".length);
|
|
12321
12376
|
const filePath = join27(LOG_DIR, filename);
|
|
12322
|
-
const fileStat = await runBeforeDeadline(() =>
|
|
12377
|
+
const fileStat = await runBeforeDeadline(() => stat6(filePath), deadline);
|
|
12323
12378
|
if (!fileStat.isFile()) {
|
|
12324
12379
|
skipped++;
|
|
12325
12380
|
return null;
|
|
@@ -12776,7 +12831,7 @@ var ChatService = class {
|
|
|
12776
12831
|
}
|
|
12777
12832
|
}
|
|
12778
12833
|
async readSenders(chatId) {
|
|
12779
|
-
return
|
|
12834
|
+
return readFile20(chatMessageSendersFilePath(chatId), "utf-8").then(parseChatMessageSendersJsonl).catch((error) => {
|
|
12780
12835
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") return [];
|
|
12781
12836
|
console.error("[ChatService] Failed to read sender records:", error);
|
|
12782
12837
|
return [];
|
|
@@ -13479,7 +13534,7 @@ var ChatService = class {
|
|
|
13479
13534
|
}
|
|
13480
13535
|
async loadChats() {
|
|
13481
13536
|
try {
|
|
13482
|
-
const content = await
|
|
13537
|
+
const content = await readFile20(CHATS_FILE, "utf-8");
|
|
13483
13538
|
return parsePersistedChatsContent(content);
|
|
13484
13539
|
} catch (error) {
|
|
13485
13540
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
@@ -13494,7 +13549,7 @@ var ChatService = class {
|
|
|
13494
13549
|
console.error("[ChatService] Failed to quarantine corrupt chats file:", renameError);
|
|
13495
13550
|
}
|
|
13496
13551
|
try {
|
|
13497
|
-
const backupContent = await
|
|
13552
|
+
const backupContent = await readFile20(CHATS_BACKUP_FILE, "utf-8");
|
|
13498
13553
|
return parsePersistedChatsContent(backupContent);
|
|
13499
13554
|
} catch (backupError) {
|
|
13500
13555
|
if (backupError && typeof backupError === "object" && "code" in backupError && backupError.code === "ENOENT") {
|
|
@@ -13584,11 +13639,10 @@ var ChatService = class {
|
|
|
13584
13639
|
|
|
13585
13640
|
// src/services/repo-file-service.ts
|
|
13586
13641
|
import { execFile } from "child_process";
|
|
13587
|
-
import { readFile as
|
|
13588
|
-
import {
|
|
13642
|
+
import { readFile as readFile21 } from "fs/promises";
|
|
13643
|
+
import { extname as extname2 } from "path";
|
|
13589
13644
|
var CACHE_TTL_MS = 3e4;
|
|
13590
13645
|
var SEARCH_TIMEOUT_MS = 15e3;
|
|
13591
|
-
var MAX_CONTENT_BYTES = 256 * 1024;
|
|
13592
13646
|
var DEFAULT_LIMIT = 50;
|
|
13593
13647
|
var MAX_LIMIT = 5e3;
|
|
13594
13648
|
var EXCLUDED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", ".next", "dist", "build", "out", "vendor", ".turbo", "__pycache__"]);
|
|
@@ -13667,6 +13721,7 @@ var RepoFileService = class {
|
|
|
13667
13721
|
cache = /* @__PURE__ */ new Map();
|
|
13668
13722
|
gitService;
|
|
13669
13723
|
indexInflight = null;
|
|
13724
|
+
writeLock = new AsyncLock();
|
|
13670
13725
|
constructor(gitService2) {
|
|
13671
13726
|
this.gitService = gitService2;
|
|
13672
13727
|
}
|
|
@@ -13730,20 +13785,10 @@ var RepoFileService = class {
|
|
|
13730
13785
|
};
|
|
13731
13786
|
}
|
|
13732
13787
|
async readFile(repoName, filePath) {
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
}
|
|
13736
|
-
const repos = await this.gitService.listRepositories();
|
|
13737
|
-
const repo = repos.find((r) => r.name === repoName);
|
|
13738
|
-
if (!repo) return null;
|
|
13788
|
+
const resolved = await this.resolveFile(repoName, filePath);
|
|
13789
|
+
if (!resolved) return null;
|
|
13790
|
+
const { fullPath, sizeBytes } = resolved;
|
|
13739
13791
|
try {
|
|
13740
|
-
const fullPath = await realpath(resolve2(join29(repo.path, filePath)));
|
|
13741
|
-
const repoRoot = await realpath(repo.path);
|
|
13742
|
-
const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
|
|
13743
|
-
if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
|
|
13744
|
-
const fileStat = await stat6(fullPath);
|
|
13745
|
-
if (!fileStat.isFile()) return null;
|
|
13746
|
-
const sizeBytes = fileStat.size;
|
|
13747
13792
|
if (isBinaryExtension(filePath)) {
|
|
13748
13793
|
const { kind, mimeType } = classifyCanvasFilename(filePath);
|
|
13749
13794
|
if (kind === "image" || kind === "pdf") {
|
|
@@ -13768,7 +13813,7 @@ var RepoFileService = class {
|
|
|
13768
13813
|
sizeBytes,
|
|
13769
13814
|
binary: true,
|
|
13770
13815
|
tooLarge: false,
|
|
13771
|
-
base64: (await
|
|
13816
|
+
base64: (await readFile21(fullPath)).toString("base64"),
|
|
13772
13817
|
mimeType
|
|
13773
13818
|
};
|
|
13774
13819
|
}
|
|
@@ -13782,7 +13827,7 @@ var RepoFileService = class {
|
|
|
13782
13827
|
tooLarge: false
|
|
13783
13828
|
};
|
|
13784
13829
|
}
|
|
13785
|
-
if (sizeBytes >
|
|
13830
|
+
if (sizeBytes > MAX_REPO_FILE_CONTENT_BYTES) {
|
|
13786
13831
|
return {
|
|
13787
13832
|
repoName,
|
|
13788
13833
|
path: filePath,
|
|
@@ -13793,7 +13838,7 @@ var RepoFileService = class {
|
|
|
13793
13838
|
tooLarge: true
|
|
13794
13839
|
};
|
|
13795
13840
|
}
|
|
13796
|
-
const content = await
|
|
13841
|
+
const content = await readFile21(fullPath, "utf-8");
|
|
13797
13842
|
return {
|
|
13798
13843
|
repoName,
|
|
13799
13844
|
path: filePath,
|
|
@@ -13801,12 +13846,33 @@ var RepoFileService = class {
|
|
|
13801
13846
|
language: detectLanguageByPath(filePath),
|
|
13802
13847
|
sizeBytes,
|
|
13803
13848
|
binary: false,
|
|
13804
|
-
tooLarge: false
|
|
13849
|
+
tooLarge: false,
|
|
13850
|
+
revision: fileRevision(content)
|
|
13805
13851
|
};
|
|
13806
13852
|
} catch {
|
|
13807
13853
|
return null;
|
|
13808
13854
|
}
|
|
13809
13855
|
}
|
|
13856
|
+
async updateFile(repoName, filePath, content, expectedRevision) {
|
|
13857
|
+
if (filePath.includes("..") || filePath.startsWith("/") || isBinaryExtension(filePath) || Buffer.byteLength(content) > MAX_REPO_FILE_CONTENT_BYTES) return null;
|
|
13858
|
+
return this.writeLock.run(async () => {
|
|
13859
|
+
const resolved = await this.resolveFile(repoName, filePath);
|
|
13860
|
+
if (!resolved) return null;
|
|
13861
|
+
try {
|
|
13862
|
+
const result = await writeRevisionedTextFile(resolved.fullPath, content, expectedRevision);
|
|
13863
|
+
if (result.saved) this.cache.delete(repoName);
|
|
13864
|
+
return result;
|
|
13865
|
+
} catch {
|
|
13866
|
+
return null;
|
|
13867
|
+
}
|
|
13868
|
+
});
|
|
13869
|
+
}
|
|
13870
|
+
async resolveFile(repoName, filePath) {
|
|
13871
|
+
if (filePath.includes("..") || filePath.startsWith("/")) return null;
|
|
13872
|
+
const repo = (await this.gitService.listRepositories()).find((repository) => repository.name === repoName);
|
|
13873
|
+
if (!repo) return null;
|
|
13874
|
+
return await resolveContainedFile(repo.path, filePath);
|
|
13875
|
+
}
|
|
13810
13876
|
async indexAll(refresh) {
|
|
13811
13877
|
const repos = await this.gitService.listRepositories();
|
|
13812
13878
|
for (const repo of repos) {
|
|
@@ -13871,17 +13937,17 @@ var RepoFileService = class {
|
|
|
13871
13937
|
// src/v1-routes.ts
|
|
13872
13938
|
import { Hono } from "hono";
|
|
13873
13939
|
import { z as z5 } from "zod";
|
|
13874
|
-
import { readdir as readdir11, stat as stat7, readFile as
|
|
13940
|
+
import { readdir as readdir11, stat as stat7, readFile as readFile24 } from "fs/promises";
|
|
13875
13941
|
import { join as join32, resolve as resolve3 } from "path";
|
|
13876
13942
|
|
|
13877
13943
|
// src/services/warm-hooks-service.ts
|
|
13878
13944
|
import { spawn as spawn6 } from "child_process";
|
|
13879
|
-
import { readFile as
|
|
13945
|
+
import { readFile as readFile23 } from "fs/promises";
|
|
13880
13946
|
import { existsSync as existsSync12 } from "fs";
|
|
13881
13947
|
import { join as join31 } from "path";
|
|
13882
13948
|
|
|
13883
13949
|
// src/services/warm-hook-logs-service.ts
|
|
13884
|
-
import { mkdir as mkdir19, readFile as
|
|
13950
|
+
import { mkdir as mkdir19, readFile as readFile22, writeFile as writeFile9, readdir as readdir10, appendFile as appendFile5, unlink as unlink4 } from "fs/promises";
|
|
13885
13951
|
import { homedir as homedir13 } from "os";
|
|
13886
13952
|
import { join as join30 } from "path";
|
|
13887
13953
|
var LOGS_DIR2 = join30(homedir13(), ".replicas", "warm-hook-logs");
|
|
@@ -13941,7 +14007,7 @@ var WarmHookLogsService = class {
|
|
|
13941
14007
|
continue;
|
|
13942
14008
|
}
|
|
13943
14009
|
try {
|
|
13944
|
-
const raw = await
|
|
14010
|
+
const raw = await readFile22(join30(LOGS_DIR2, file), "utf-8");
|
|
13945
14011
|
const stored = JSON.parse(raw);
|
|
13946
14012
|
logs.push(withPreview2(stored));
|
|
13947
14013
|
} catch {
|
|
@@ -13970,7 +14036,7 @@ var WarmHookLogsService = class {
|
|
|
13970
14036
|
}
|
|
13971
14037
|
async getCurrentRunLog() {
|
|
13972
14038
|
try {
|
|
13973
|
-
return await
|
|
14039
|
+
return await readFile22(CURRENT_RUN_LOG, "utf-8");
|
|
13974
14040
|
} catch (err) {
|
|
13975
14041
|
if (err.code === "ENOENT") return null;
|
|
13976
14042
|
throw err;
|
|
@@ -13979,7 +14045,7 @@ var WarmHookLogsService = class {
|
|
|
13979
14045
|
async getFullOutput(hookType, hookName) {
|
|
13980
14046
|
const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
|
|
13981
14047
|
try {
|
|
13982
|
-
const raw = await
|
|
14048
|
+
const raw = await readFile22(join30(LOGS_DIR2, filename), "utf-8");
|
|
13983
14049
|
const stored = JSON.parse(raw);
|
|
13984
14050
|
if (stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
13985
14051
|
return null;
|
|
@@ -14003,7 +14069,7 @@ async function readRepoWarmHook(repoPath) {
|
|
|
14003
14069
|
continue;
|
|
14004
14070
|
}
|
|
14005
14071
|
try {
|
|
14006
|
-
const raw = await
|
|
14072
|
+
const raw = await readFile23(configPath, "utf-8");
|
|
14007
14073
|
const config = parseReplicasConfigString(raw, filename);
|
|
14008
14074
|
if (!config.warmHook) {
|
|
14009
14075
|
return null;
|
|
@@ -14401,6 +14467,10 @@ var updateGoalSchema = z5.object({
|
|
|
14401
14467
|
}).refine((body) => body.objective !== void 0 || body.status !== void 0, {
|
|
14402
14468
|
message: "Goal objective or status required"
|
|
14403
14469
|
});
|
|
14470
|
+
var updateTextFileSchema = (maxLength) => z5.object({
|
|
14471
|
+
content: z5.string().max(maxLength),
|
|
14472
|
+
expectedRevision: z5.string().regex(/^[a-f0-9]{64}$/)
|
|
14473
|
+
});
|
|
14404
14474
|
function jsonError(message, details) {
|
|
14405
14475
|
return { error: message, details };
|
|
14406
14476
|
}
|
|
@@ -14782,6 +14852,17 @@ function createV1Routes(deps) {
|
|
|
14782
14852
|
}
|
|
14783
14853
|
return c.json(result);
|
|
14784
14854
|
});
|
|
14855
|
+
app2.put("/repo-files/content", async (c) => {
|
|
14856
|
+
const repoName = c.req.query("repoName");
|
|
14857
|
+
const path6 = c.req.query("path");
|
|
14858
|
+
if (!repoName || !path6) {
|
|
14859
|
+
return c.json(jsonError("repoName and path are required"), 400);
|
|
14860
|
+
}
|
|
14861
|
+
const body = updateTextFileSchema(MAX_REPO_FILE_CONTENT_BYTES).parse(await c.req.json());
|
|
14862
|
+
const result = await deps.repoFileService.updateFile(repoName, path6, body.content, body.expectedRevision);
|
|
14863
|
+
if (!result) return c.json(jsonError("File is not editable"), 400);
|
|
14864
|
+
return c.json(result);
|
|
14865
|
+
});
|
|
14785
14866
|
app2.get("/terminal/sessions", (c) => {
|
|
14786
14867
|
return c.json({ sessions: terminalService.list() });
|
|
14787
14868
|
});
|
|
@@ -14883,6 +14964,14 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
14883
14964
|
);
|
|
14884
14965
|
}
|
|
14885
14966
|
});
|
|
14967
|
+
app2.put("/canvas/:filename{.+}", async (c) => {
|
|
14968
|
+
const filename = c.req.param("filename");
|
|
14969
|
+
if (!filename) return c.json(jsonError("Filename required"), 400);
|
|
14970
|
+
const body = updateTextFileSchema(MAX_CANVAS_PREVIEW_BYTES).parse(await c.req.json());
|
|
14971
|
+
const result = await deps.canvasService.updateItem(filename, body.content, body.expectedRevision);
|
|
14972
|
+
if (!result) return c.json(jsonError("Canvas item is not editable"), 400);
|
|
14973
|
+
return c.json(result);
|
|
14974
|
+
});
|
|
14886
14975
|
app2.get("/hooks/status", (c) => {
|
|
14887
14976
|
const response = {
|
|
14888
14977
|
running: replicasConfigService.areHooksRunning(),
|
|
@@ -15250,7 +15339,7 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
15250
15339
|
}
|
|
15251
15340
|
let content;
|
|
15252
15341
|
try {
|
|
15253
|
-
content = await
|
|
15342
|
+
content = await readFile24(filePath, "utf-8");
|
|
15254
15343
|
} catch {
|
|
15255
15344
|
return c.json(jsonError("Log session not found"), 404);
|
|
15256
15345
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
notifyPostToolUse
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OF3EDBVV.js";
|
|
5
5
|
import {
|
|
6
6
|
isRecord
|
|
7
7
|
} from "./chunk-2RB7SIP3.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-GSMOYM7N.js";
|
|
9
9
|
|
|
10
10
|
// src/post-tool-pr-hook.ts
|
|
11
11
|
async function main() {
|