replicas-engine 0.1.156 → 0.1.157
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 -50
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -205,9 +205,13 @@ function parseWarmHookConfig(value, filename = "replicas.json") {
|
|
|
205
205
|
if (value.timeout !== void 0 && (typeof value.timeout !== "number" || value.timeout <= 0)) {
|
|
206
206
|
throw new Error(`Invalid ${filename}: "warmHook.timeout" must be a positive number`);
|
|
207
207
|
}
|
|
208
|
+
if (value.separate !== void 0 && typeof value.separate !== "boolean") {
|
|
209
|
+
throw new Error(`Invalid ${filename}: "warmHook.separate" must be a boolean`);
|
|
210
|
+
}
|
|
208
211
|
return {
|
|
209
212
|
commands: value.commands,
|
|
210
|
-
timeout: value.timeout
|
|
213
|
+
timeout: value.timeout,
|
|
214
|
+
separate: value.separate
|
|
211
215
|
};
|
|
212
216
|
}
|
|
213
217
|
function resolveWarmHookConfig(value) {
|
|
@@ -221,7 +225,8 @@ function resolveWarmHookConfig(value) {
|
|
|
221
225
|
}
|
|
222
226
|
return {
|
|
223
227
|
commands,
|
|
224
|
-
timeoutMs: typeof parsed === "string" ? void 0 : parsed.timeout
|
|
228
|
+
timeoutMs: typeof parsed === "string" ? void 0 : parsed.timeout,
|
|
229
|
+
separate: typeof parsed === "string" ? void 0 : parsed.separate
|
|
225
230
|
};
|
|
226
231
|
}
|
|
227
232
|
|
|
@@ -251,14 +256,17 @@ function parseReplicasConfig(value, filename = "replicas.json") {
|
|
|
251
256
|
if (!isRecord2(value.startHook)) {
|
|
252
257
|
throw new Error(`Invalid ${filename}: "startHook" must be an object with "commands" array`);
|
|
253
258
|
}
|
|
254
|
-
const { commands, timeout } = value.startHook;
|
|
259
|
+
const { commands, timeout, separate } = value.startHook;
|
|
255
260
|
if (!Array.isArray(commands) || !commands.every((entry) => typeof entry === "string")) {
|
|
256
261
|
throw new Error(`Invalid ${filename}: "startHook.commands" must be an array of shell commands`);
|
|
257
262
|
}
|
|
258
263
|
if (timeout !== void 0 && (typeof timeout !== "number" || timeout <= 0)) {
|
|
259
264
|
throw new Error(`Invalid ${filename}: "startHook.timeout" must be a positive number`);
|
|
260
265
|
}
|
|
261
|
-
|
|
266
|
+
if (separate !== void 0 && typeof separate !== "boolean") {
|
|
267
|
+
throw new Error(`Invalid ${filename}: "startHook.separate" must be a boolean`);
|
|
268
|
+
}
|
|
269
|
+
config.startHook = { commands, timeout, separate };
|
|
262
270
|
}
|
|
263
271
|
if ("warmHook" in value) {
|
|
264
272
|
config.warmHook = parseWarmHookConfig(value.warmHook, filename);
|
|
@@ -277,7 +285,7 @@ function parseReplicasConfigString(content, filename) {
|
|
|
277
285
|
}
|
|
278
286
|
|
|
279
287
|
// ../shared/src/engine/environment.ts
|
|
280
|
-
var DAYTONA_SNAPSHOT_ID = "11-05-2026-royal-york-
|
|
288
|
+
var DAYTONA_SNAPSHOT_ID = "11-05-2026-royal-york-v3";
|
|
281
289
|
|
|
282
290
|
// ../shared/src/engine/types.ts
|
|
283
291
|
var DEFAULT_CHAT_TITLES = {
|
|
@@ -1592,6 +1600,43 @@ var ReplicasConfigService = class {
|
|
|
1592
1600
|
console.error("Failed to write to start hooks log:", error);
|
|
1593
1601
|
}
|
|
1594
1602
|
}
|
|
1603
|
+
async execStartHookCommand(params) {
|
|
1604
|
+
const output = [];
|
|
1605
|
+
try {
|
|
1606
|
+
await this.logToFile(`[${params.repoName}] --- Running: ${params.label} ---`);
|
|
1607
|
+
const { stdout, stderr } = await execAsync(params.command, {
|
|
1608
|
+
cwd: params.cwd,
|
|
1609
|
+
timeout: params.timeout,
|
|
1610
|
+
maxBuffer: HOOK_EXEC_MAX_BUFFER_BYTES,
|
|
1611
|
+
env: process.env
|
|
1612
|
+
});
|
|
1613
|
+
if (stdout) {
|
|
1614
|
+
output.push(stdout);
|
|
1615
|
+
await this.logToFile(`[${params.repoName}] [stdout] ${stdout}`);
|
|
1616
|
+
}
|
|
1617
|
+
if (stderr) {
|
|
1618
|
+
output.push(stderr);
|
|
1619
|
+
await this.logToFile(`[${params.repoName}] [stderr] ${stderr}`);
|
|
1620
|
+
}
|
|
1621
|
+
await this.logToFile(`[${params.repoName}] --- Completed: ${params.label} ---`);
|
|
1622
|
+
return { exitCode: 0, timedOut: false, output };
|
|
1623
|
+
} catch (error) {
|
|
1624
|
+
const execError = error;
|
|
1625
|
+
if (execError.stdout) {
|
|
1626
|
+
output.push(execError.stdout);
|
|
1627
|
+
await this.logToFile(`[${params.repoName}] [stdout] ${execError.stdout}`);
|
|
1628
|
+
}
|
|
1629
|
+
if (execError.stderr) {
|
|
1630
|
+
output.push(execError.stderr);
|
|
1631
|
+
await this.logToFile(`[${params.repoName}] [stderr] ${execError.stderr}`);
|
|
1632
|
+
}
|
|
1633
|
+
const rawMessage = execError.message ?? "Unknown error";
|
|
1634
|
+
const errorMessage = rawMessage.split("\n", 1)[0];
|
|
1635
|
+
output.push(`[ERROR] ${params.label} failed: ${errorMessage}`);
|
|
1636
|
+
await this.logToFile(`[${params.repoName}] [ERROR] ${params.label} failed: ${errorMessage}`);
|
|
1637
|
+
return { exitCode: execError.code ?? 1, timedOut: execError.killed === true, output };
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1595
1640
|
/**
|
|
1596
1641
|
* Execute start hooks from all repositories sequentially.
|
|
1597
1642
|
*/
|
|
@@ -1644,46 +1689,43 @@ Repositories: ${hookEntries.length}
|
|
|
1644
1689
|
let repoTimedOut = false;
|
|
1645
1690
|
const repoOutput = [];
|
|
1646
1691
|
await this.logToFile(`[${entry.repoName}] Executing ${startHookConfig.commands.length} hook(s) with timeout ${timeout}ms`);
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
repoOutput.push(stderr);
|
|
1662
|
-
await this.logToFile(`[${entry.repoName}] [stderr] ${stderr}`);
|
|
1663
|
-
}
|
|
1664
|
-
await this.logToFile(`[${entry.repoName}] --- Completed: ${hook} ---`);
|
|
1665
|
-
} catch (error) {
|
|
1666
|
-
const execError = error;
|
|
1667
|
-
lastExitCode = execError.code ?? 1;
|
|
1668
|
-
if (execError.killed) {
|
|
1669
|
-
repoTimedOut = true;
|
|
1670
|
-
}
|
|
1692
|
+
if (startHookConfig.separate === false) {
|
|
1693
|
+
const combinedScript = `set -e
|
|
1694
|
+
${startHookConfig.commands.join("\n")}`;
|
|
1695
|
+
const result = await this.execStartHookCommand({
|
|
1696
|
+
command: combinedScript,
|
|
1697
|
+
label: "combined script",
|
|
1698
|
+
repoName: entry.repoName,
|
|
1699
|
+
cwd: entry.workingDirectory,
|
|
1700
|
+
timeout
|
|
1701
|
+
});
|
|
1702
|
+
repoOutput.push(...result.output);
|
|
1703
|
+
if (result.exitCode !== 0) {
|
|
1704
|
+
lastExitCode = result.exitCode;
|
|
1705
|
+
repoTimedOut = result.timedOut;
|
|
1671
1706
|
this.hooksFailed = true;
|
|
1672
1707
|
repoFailed = true;
|
|
1673
|
-
if (execError.stdout) {
|
|
1674
|
-
repoOutput.push(execError.stdout);
|
|
1675
|
-
await this.logToFile(`[${entry.repoName}] [stdout] ${execError.stdout}`);
|
|
1676
|
-
}
|
|
1677
|
-
if (execError.stderr) {
|
|
1678
|
-
repoOutput.push(execError.stderr);
|
|
1679
|
-
await this.logToFile(`[${entry.repoName}] [stderr] ${execError.stderr}`);
|
|
1680
|
-
}
|
|
1681
|
-
const rawMessage = execError.message ?? "Unknown error";
|
|
1682
|
-
const errorMessage = rawMessage.split("\n", 1)[0];
|
|
1683
|
-
repoOutput.push(`[ERROR] ${hook} failed: ${errorMessage}`);
|
|
1684
|
-
await this.logToFile(`[${entry.repoName}] [ERROR] ${hook} failed: ${errorMessage}`);
|
|
1685
1708
|
await environmentDetailsService.setRepositoryStartHook(entry.repoName, "no");
|
|
1686
1709
|
}
|
|
1710
|
+
} else {
|
|
1711
|
+
for (const hook of startHookConfig.commands) {
|
|
1712
|
+
const result = await this.execStartHookCommand({
|
|
1713
|
+
command: hook,
|
|
1714
|
+
label: hook,
|
|
1715
|
+
repoName: entry.repoName,
|
|
1716
|
+
cwd: entry.workingDirectory,
|
|
1717
|
+
timeout
|
|
1718
|
+
});
|
|
1719
|
+
repoOutput.push(...result.output);
|
|
1720
|
+
if (result.exitCode !== 0) {
|
|
1721
|
+
lastExitCode = result.exitCode;
|
|
1722
|
+
repoTimedOut = result.timedOut;
|
|
1723
|
+
this.hooksFailed = true;
|
|
1724
|
+
repoFailed = true;
|
|
1725
|
+
await environmentDetailsService.setRepositoryStartHook(entry.repoName, "no");
|
|
1726
|
+
break;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1687
1729
|
}
|
|
1688
1730
|
await startHookLogsService.saveRepoLog(entry.repoName, {
|
|
1689
1731
|
hookCommands: startHookConfig.commands,
|
|
@@ -4599,7 +4641,8 @@ async function collectRepoWarmHooks() {
|
|
|
4599
4641
|
repoName: repo.name,
|
|
4600
4642
|
repoPath: repo.path,
|
|
4601
4643
|
commands: warmHook.commands,
|
|
4602
|
-
timeoutMs: warmHook.timeoutMs
|
|
4644
|
+
timeoutMs: warmHook.timeoutMs,
|
|
4645
|
+
separate: warmHook.separate
|
|
4603
4646
|
});
|
|
4604
4647
|
}
|
|
4605
4648
|
collected.sort((a, b) => a.repoName.localeCompare(b.repoName));
|
|
@@ -4746,29 +4789,50 @@ async function runWarmHooksStreaming(params) {
|
|
|
4746
4789
|
let repoFailed = false;
|
|
4747
4790
|
let repoTimedOut = false;
|
|
4748
4791
|
let repoExitCode = 0;
|
|
4749
|
-
|
|
4792
|
+
if (repoHook.separate === false) {
|
|
4793
|
+
const scriptWithErrExit = `set -e
|
|
4794
|
+
${combinedScript}`;
|
|
4750
4795
|
const repoResult = await executeHookScriptStreaming({
|
|
4751
4796
|
label: `repo-warm-hook:${repoHook.repoName}`,
|
|
4752
4797
|
cwd: repoHook.repoPath,
|
|
4753
|
-
content:
|
|
4798
|
+
content: scriptWithErrExit,
|
|
4754
4799
|
timeoutMs: repoHook.timeoutMs,
|
|
4755
4800
|
onChunk: (chunk) => params.onEvent({ type: "output", data: chunk, label: `repo:${repoHook.repoName}` })
|
|
4756
4801
|
});
|
|
4757
4802
|
outputBlocks.push(repoResult.output);
|
|
4758
4803
|
repoOutputBlocks.push(repoResult.output);
|
|
4759
|
-
await environmentDetailsService.setRepositoryWarmHook(
|
|
4760
|
-
repoHook.repoName,
|
|
4761
|
-
repoResult.exitCode === 0 ? "yes" : "no"
|
|
4762
|
-
);
|
|
4763
4804
|
if (repoResult.exitCode !== 0) {
|
|
4764
4805
|
repoFailed = true;
|
|
4765
4806
|
repoTimedOut = repoResult.timedOut;
|
|
4766
4807
|
repoExitCode = repoResult.exitCode;
|
|
4767
|
-
|
|
4808
|
+
}
|
|
4809
|
+
} else {
|
|
4810
|
+
for (const command of repoHook.commands) {
|
|
4811
|
+
const repoResult = await executeHookScriptStreaming({
|
|
4812
|
+
label: `repo-warm-hook:${repoHook.repoName}`,
|
|
4813
|
+
cwd: repoHook.repoPath,
|
|
4814
|
+
content: command,
|
|
4815
|
+
timeoutMs: repoHook.timeoutMs,
|
|
4816
|
+
onChunk: (chunk) => params.onEvent({ type: "output", data: chunk, label: `repo:${repoHook.repoName}` })
|
|
4817
|
+
});
|
|
4818
|
+
outputBlocks.push(repoResult.output);
|
|
4819
|
+
repoOutputBlocks.push(repoResult.output);
|
|
4820
|
+
if (repoResult.exitCode !== 0) {
|
|
4821
|
+
repoFailed = true;
|
|
4822
|
+
repoTimedOut = repoResult.timedOut;
|
|
4823
|
+
repoExitCode = repoResult.exitCode;
|
|
4824
|
+
break;
|
|
4825
|
+
}
|
|
4768
4826
|
}
|
|
4769
4827
|
}
|
|
4828
|
+
await environmentDetailsService.setRepositoryWarmHook(
|
|
4829
|
+
repoHook.repoName,
|
|
4830
|
+
repoFailed ? "no" : "yes"
|
|
4831
|
+
);
|
|
4832
|
+
const loggedScript = repoHook.separate === false ? `set -e
|
|
4833
|
+
${combinedScript}` : combinedScript;
|
|
4770
4834
|
await warmHookLogsService.saveRepoHookLog(repoHook.repoName, {
|
|
4771
|
-
hookScript:
|
|
4835
|
+
hookScript: loggedScript,
|
|
4772
4836
|
output: repoOutputBlocks.join("\n\n"),
|
|
4773
4837
|
exitCode: repoFailed ? repoExitCode : 0,
|
|
4774
4838
|
timedOut: repoTimedOut,
|