replicas-engine 0.1.114 → 0.1.116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/index.js +114 -17
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -995,7 +995,8 @@ import { parse as parseYaml } from "yaml";
|
|
|
995
995
|
// ../shared/src/warm-hooks.ts
|
|
996
996
|
var DEFAULT_WARM_HOOK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
997
997
|
var MAX_WARM_HOOK_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
998
|
-
var
|
|
998
|
+
var DEFAULT_HOOK_OUTPUT_PREVIEW_CHARS = 1e5;
|
|
999
|
+
var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
999
1000
|
function isRecord2(value) {
|
|
1000
1001
|
return typeof value === "object" && value !== null;
|
|
1001
1002
|
}
|
|
@@ -1005,12 +1006,16 @@ function clampWarmHookTimeoutMs(timeoutMs) {
|
|
|
1005
1006
|
}
|
|
1006
1007
|
return Math.min(timeoutMs, MAX_WARM_HOOK_TIMEOUT_MS);
|
|
1007
1008
|
}
|
|
1008
|
-
function
|
|
1009
|
+
function buildHookOutputPreview(text, maxChars = DEFAULT_HOOK_OUTPUT_PREVIEW_CHARS) {
|
|
1009
1010
|
if (text.length <= maxChars) {
|
|
1010
|
-
return text;
|
|
1011
|
+
return { output: text, outputTruncated: false, outputTotalChars: text.length };
|
|
1011
1012
|
}
|
|
1012
|
-
return
|
|
1013
|
-
|
|
1013
|
+
return {
|
|
1014
|
+
output: `${text.slice(0, maxChars)}
|
|
1015
|
+
...[truncated \u2014 download the full log to see the rest]`,
|
|
1016
|
+
outputTruncated: true,
|
|
1017
|
+
outputTotalChars: text.length
|
|
1018
|
+
};
|
|
1014
1019
|
}
|
|
1015
1020
|
function parseWarmHookConfig(value, filename = "replicas.json") {
|
|
1016
1021
|
if (typeof value === "string") {
|
|
@@ -1097,7 +1102,7 @@ function parseReplicasConfigString(content, filename) {
|
|
|
1097
1102
|
}
|
|
1098
1103
|
|
|
1099
1104
|
// ../shared/src/engine/environment.ts
|
|
1100
|
-
var DAYTONA_SNAPSHOT_ID = "
|
|
1105
|
+
var DAYTONA_SNAPSHOT_ID = "21-04-2026-islington-v1";
|
|
1101
1106
|
|
|
1102
1107
|
// ../shared/src/engine/types.ts
|
|
1103
1108
|
var DEFAULT_CHAT_TITLES = {
|
|
@@ -1275,6 +1280,13 @@ function sanitizeFilename(name) {
|
|
|
1275
1280
|
const hash = createHash("sha256").update(name).digest("hex").slice(0, 8);
|
|
1276
1281
|
return `${safe}-${hash}`;
|
|
1277
1282
|
}
|
|
1283
|
+
function repoFilename(repoName) {
|
|
1284
|
+
return `repo-${sanitizeFilename(repoName)}.json`;
|
|
1285
|
+
}
|
|
1286
|
+
function withPreview(stored) {
|
|
1287
|
+
const preview = buildHookOutputPreview(stored.output);
|
|
1288
|
+
return { ...stored, ...preview };
|
|
1289
|
+
}
|
|
1278
1290
|
var StartHookLogsService = class {
|
|
1279
1291
|
async ensureDir() {
|
|
1280
1292
|
await mkdir4(LOGS_DIR, { recursive: true });
|
|
@@ -1282,8 +1294,7 @@ var StartHookLogsService = class {
|
|
|
1282
1294
|
async saveRepoLog(repoName, entry) {
|
|
1283
1295
|
await this.ensureDir();
|
|
1284
1296
|
const log = { repoName, ...entry };
|
|
1285
|
-
|
|
1286
|
-
await writeFile4(join6(LOGS_DIR, filename), `${JSON.stringify(log, null, 2)}
|
|
1297
|
+
await writeFile4(join6(LOGS_DIR, repoFilename(repoName)), `${JSON.stringify(log, null, 2)}
|
|
1287
1298
|
`, "utf-8");
|
|
1288
1299
|
}
|
|
1289
1300
|
async getAllLogs() {
|
|
@@ -1303,13 +1314,29 @@ var StartHookLogsService = class {
|
|
|
1303
1314
|
}
|
|
1304
1315
|
try {
|
|
1305
1316
|
const raw = await readFile3(join6(LOGS_DIR, file), "utf-8");
|
|
1306
|
-
|
|
1317
|
+
const stored = JSON.parse(raw);
|
|
1318
|
+
logs.push(withPreview(stored));
|
|
1307
1319
|
} catch {
|
|
1308
1320
|
}
|
|
1309
1321
|
}
|
|
1310
1322
|
logs.sort((a, b) => a.repoName.localeCompare(b.repoName));
|
|
1311
1323
|
return logs;
|
|
1312
1324
|
}
|
|
1325
|
+
async getFullOutput(repoName) {
|
|
1326
|
+
try {
|
|
1327
|
+
const raw = await readFile3(join6(LOGS_DIR, repoFilename(repoName)), "utf-8");
|
|
1328
|
+
const stored = JSON.parse(raw);
|
|
1329
|
+
if (stored.repoName !== repoName) {
|
|
1330
|
+
return null;
|
|
1331
|
+
}
|
|
1332
|
+
return stored.output;
|
|
1333
|
+
} catch (err) {
|
|
1334
|
+
if (err.code === "ENOENT") {
|
|
1335
|
+
return null;
|
|
1336
|
+
}
|
|
1337
|
+
throw err;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1313
1340
|
};
|
|
1314
1341
|
var startHookLogsService = new StartHookLogsService();
|
|
1315
1342
|
|
|
@@ -1454,6 +1481,7 @@ Repositories: ${hookEntries.length}
|
|
|
1454
1481
|
const { stdout, stderr } = await execAsync(hook, {
|
|
1455
1482
|
cwd: entry.workingDirectory,
|
|
1456
1483
|
timeout,
|
|
1484
|
+
maxBuffer: HOOK_EXEC_MAX_BUFFER_BYTES,
|
|
1457
1485
|
env: process.env
|
|
1458
1486
|
});
|
|
1459
1487
|
if (stdout) {
|
|
@@ -1466,7 +1494,6 @@ Repositories: ${hookEntries.length}
|
|
|
1466
1494
|
}
|
|
1467
1495
|
await this.logToFile(`[${entry.repoName}] --- Completed: ${hook} ---`);
|
|
1468
1496
|
} catch (error) {
|
|
1469
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1470
1497
|
const execError = error;
|
|
1471
1498
|
lastExitCode = execError.code ?? 1;
|
|
1472
1499
|
if (execError.killed) {
|
|
@@ -1474,6 +1501,16 @@ Repositories: ${hookEntries.length}
|
|
|
1474
1501
|
}
|
|
1475
1502
|
this.hooksFailed = true;
|
|
1476
1503
|
repoFailed = true;
|
|
1504
|
+
if (execError.stdout) {
|
|
1505
|
+
repoOutput.push(execError.stdout);
|
|
1506
|
+
await this.logToFile(`[${entry.repoName}] [stdout] ${execError.stdout}`);
|
|
1507
|
+
}
|
|
1508
|
+
if (execError.stderr) {
|
|
1509
|
+
repoOutput.push(execError.stderr);
|
|
1510
|
+
await this.logToFile(`[${entry.repoName}] [stderr] ${execError.stderr}`);
|
|
1511
|
+
}
|
|
1512
|
+
const rawMessage = execError.message ?? "Unknown error";
|
|
1513
|
+
const errorMessage = rawMessage.split("\n", 1)[0];
|
|
1477
1514
|
repoOutput.push(`[ERROR] ${hook} failed: ${errorMessage}`);
|
|
1478
1515
|
await this.logToFile(`[${entry.repoName}] [ERROR] ${hook} failed: ${errorMessage}`);
|
|
1479
1516
|
await environmentDetailsService.setRepositoryStartHook(entry.repoName, "no");
|
|
@@ -4046,6 +4083,16 @@ function sanitizeFilename2(name) {
|
|
|
4046
4083
|
const hash = createHash2("sha256").update(name).digest("hex").slice(0, 8);
|
|
4047
4084
|
return `${safe}-${hash}`;
|
|
4048
4085
|
}
|
|
4086
|
+
function globalFilename() {
|
|
4087
|
+
return "global.json";
|
|
4088
|
+
}
|
|
4089
|
+
function repoFilename2(repoName) {
|
|
4090
|
+
return `repo-${sanitizeFilename2(repoName)}.json`;
|
|
4091
|
+
}
|
|
4092
|
+
function withPreview2(stored) {
|
|
4093
|
+
const preview = buildHookOutputPreview(stored.output);
|
|
4094
|
+
return { ...stored, ...preview };
|
|
4095
|
+
}
|
|
4049
4096
|
var WarmHookLogsService = class {
|
|
4050
4097
|
async ensureDir() {
|
|
4051
4098
|
await mkdir11(LOGS_DIR2, { recursive: true });
|
|
@@ -4057,7 +4104,7 @@ var WarmHookLogsService = class {
|
|
|
4057
4104
|
hookName: "organization",
|
|
4058
4105
|
...entry
|
|
4059
4106
|
};
|
|
4060
|
-
await writeFile9(join13(LOGS_DIR2,
|
|
4107
|
+
await writeFile9(join13(LOGS_DIR2, globalFilename()), `${JSON.stringify(log, null, 2)}
|
|
4061
4108
|
`, "utf-8");
|
|
4062
4109
|
}
|
|
4063
4110
|
async saveRepoHookLog(repoName, entry) {
|
|
@@ -4067,8 +4114,7 @@ var WarmHookLogsService = class {
|
|
|
4067
4114
|
hookName: repoName,
|
|
4068
4115
|
...entry
|
|
4069
4116
|
};
|
|
4070
|
-
|
|
4071
|
-
await writeFile9(join13(LOGS_DIR2, filename), `${JSON.stringify(log, null, 2)}
|
|
4117
|
+
await writeFile9(join13(LOGS_DIR2, repoFilename2(repoName)), `${JSON.stringify(log, null, 2)}
|
|
4072
4118
|
`, "utf-8");
|
|
4073
4119
|
}
|
|
4074
4120
|
async getAllLogs() {
|
|
@@ -4088,7 +4134,8 @@ var WarmHookLogsService = class {
|
|
|
4088
4134
|
}
|
|
4089
4135
|
try {
|
|
4090
4136
|
const raw = await readFile10(join13(LOGS_DIR2, file), "utf-8");
|
|
4091
|
-
|
|
4137
|
+
const stored = JSON.parse(raw);
|
|
4138
|
+
logs.push(withPreview2(stored));
|
|
4092
4139
|
} catch {
|
|
4093
4140
|
}
|
|
4094
4141
|
}
|
|
@@ -4100,6 +4147,22 @@ var WarmHookLogsService = class {
|
|
|
4100
4147
|
});
|
|
4101
4148
|
return logs;
|
|
4102
4149
|
}
|
|
4150
|
+
async getFullOutput(hookType, hookName) {
|
|
4151
|
+
const filename = hookType === "global" ? globalFilename() : repoFilename2(hookName);
|
|
4152
|
+
try {
|
|
4153
|
+
const raw = await readFile10(join13(LOGS_DIR2, filename), "utf-8");
|
|
4154
|
+
const stored = JSON.parse(raw);
|
|
4155
|
+
if (stored.hookType !== hookType || stored.hookName !== hookName) {
|
|
4156
|
+
return null;
|
|
4157
|
+
}
|
|
4158
|
+
return stored.output;
|
|
4159
|
+
} catch (err) {
|
|
4160
|
+
if (err.code === "ENOENT") {
|
|
4161
|
+
return null;
|
|
4162
|
+
}
|
|
4163
|
+
throw err;
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4103
4166
|
};
|
|
4104
4167
|
var warmHookLogsService = new WarmHookLogsService();
|
|
4105
4168
|
|
|
@@ -4111,13 +4174,13 @@ async function executeHookScript(params) {
|
|
|
4111
4174
|
const { stdout, stderr } = await execFileAsync2("bash", ["-lc", params.content], {
|
|
4112
4175
|
cwd: params.cwd,
|
|
4113
4176
|
timeout,
|
|
4114
|
-
maxBuffer:
|
|
4177
|
+
maxBuffer: HOOK_EXEC_MAX_BUFFER_BYTES,
|
|
4115
4178
|
env: process.env
|
|
4116
4179
|
});
|
|
4117
4180
|
const combined = [`$ ${params.label}`, stdout ?? "", stderr ?? ""].filter(Boolean).join("\n");
|
|
4118
4181
|
return {
|
|
4119
4182
|
exitCode: 0,
|
|
4120
|
-
output:
|
|
4183
|
+
output: combined,
|
|
4121
4184
|
timedOut: false
|
|
4122
4185
|
};
|
|
4123
4186
|
} catch (error) {
|
|
@@ -4127,7 +4190,7 @@ async function executeHookScript(params) {
|
|
|
4127
4190
|
const combined = [`$ ${params.label}`, execError.stdout ?? "", execError.stderr ?? "", execError.message].filter(Boolean).join("\n");
|
|
4128
4191
|
return {
|
|
4129
4192
|
exitCode,
|
|
4130
|
-
output:
|
|
4193
|
+
output: combined,
|
|
4131
4194
|
timedOut
|
|
4132
4195
|
};
|
|
4133
4196
|
}
|
|
@@ -4573,6 +4636,25 @@ function createV1Routes(deps) {
|
|
|
4573
4636
|
);
|
|
4574
4637
|
}
|
|
4575
4638
|
});
|
|
4639
|
+
app2.get("/warm-hooks/logs/:hookType/:hookName/full", async (c) => {
|
|
4640
|
+
try {
|
|
4641
|
+
const hookType = c.req.param("hookType");
|
|
4642
|
+
const hookName = c.req.param("hookName");
|
|
4643
|
+
if (hookType !== "global" && hookType !== "repository") {
|
|
4644
|
+
return c.json(jsonError("Invalid hookType", 'Must be "global" or "repository"'), 400);
|
|
4645
|
+
}
|
|
4646
|
+
const output = await warmHookLogsService.getFullOutput(hookType, hookName);
|
|
4647
|
+
if (output === null) {
|
|
4648
|
+
return c.json(jsonError("Warm hook log not found"), 404);
|
|
4649
|
+
}
|
|
4650
|
+
return c.json({ output });
|
|
4651
|
+
} catch (error) {
|
|
4652
|
+
return c.json(
|
|
4653
|
+
jsonError("Failed to read warm hook log", error instanceof Error ? error.message : "Unknown error"),
|
|
4654
|
+
500
|
|
4655
|
+
);
|
|
4656
|
+
}
|
|
4657
|
+
});
|
|
4576
4658
|
app2.get("/start-hooks/logs", async (c) => {
|
|
4577
4659
|
try {
|
|
4578
4660
|
const logs = await startHookLogsService.getAllLogs();
|
|
@@ -4584,6 +4666,21 @@ function createV1Routes(deps) {
|
|
|
4584
4666
|
);
|
|
4585
4667
|
}
|
|
4586
4668
|
});
|
|
4669
|
+
app2.get("/start-hooks/logs/:repoName/full", async (c) => {
|
|
4670
|
+
try {
|
|
4671
|
+
const repoName = c.req.param("repoName");
|
|
4672
|
+
const output = await startHookLogsService.getFullOutput(repoName);
|
|
4673
|
+
if (output === null) {
|
|
4674
|
+
return c.json(jsonError("Start hook log not found"), 404);
|
|
4675
|
+
}
|
|
4676
|
+
return c.json({ output });
|
|
4677
|
+
} catch (error) {
|
|
4678
|
+
return c.json(
|
|
4679
|
+
jsonError("Failed to read start hook log", error instanceof Error ? error.message : "Unknown error"),
|
|
4680
|
+
500
|
|
4681
|
+
);
|
|
4682
|
+
}
|
|
4683
|
+
});
|
|
4587
4684
|
app2.post("/workspace-name", async (c) => {
|
|
4588
4685
|
try {
|
|
4589
4686
|
const body = setWorkspaceNameSchema.parse(await c.req.json());
|