@osfactory/har 0.49.1 → 0.50.0
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/index.js +92 -55
- package/dist/templates/adaptation-prompt-init.md +5 -0
- package/dist/templates/adaptation-prompt-maintain.md +1 -1
- package/dist/templates/har-boilerplate/agent-cli.sh +7 -6
- package/dist/templates/har-boilerplate/agent-slot.sh +1 -1
- package/dist/templates/har-boilerplate/harness.env +117 -0
- package/dist/templates/har-boilerplate/launch.sh +3 -3
- package/dist/templates/har-boilerplate/provision-toolchain.sh +136 -15
- package/dist/templates/har-boilerplate/setup-infra.sh +1 -1
- package/dist/templates/har-boilerplate/teardown.sh +1 -1
- package/dist/templates/har-boilerplate-cli/agent-slot.sh +1 -1
- package/dist/templates/har-boilerplate-cli/harness.env +117 -0
- package/dist/templates/har-boilerplate-cli/launch.sh +3 -2
- package/dist/templates/har-boilerplate-cli/provision-toolchain.sh +136 -15
- package/dist/templates/har-boilerplate-cli/setup-infra.sh +1 -1
- package/dist/templates/har-boilerplate-ios/harness.env +117 -0
- package/dist/templates/har-boilerplate-ios/provision-toolchain.sh +136 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28694,6 +28694,10 @@ var init_control_config = __esm({
|
|
|
28694
28694
|
});
|
|
28695
28695
|
|
|
28696
28696
|
// src/utils/shell.ts
|
|
28697
|
+
function quoteShellArg(arg) {
|
|
28698
|
+
if (/^[A-Za-z0-9_./:=+-]+$/.test(arg)) return arg;
|
|
28699
|
+
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
28700
|
+
}
|
|
28697
28701
|
function run(command2, options = {}) {
|
|
28698
28702
|
try {
|
|
28699
28703
|
const stdout = (0, import_child_process.execSync)(command2, {
|
|
@@ -29055,10 +29059,6 @@ var init_slot_registry = __esm({
|
|
|
29055
29059
|
});
|
|
29056
29060
|
|
|
29057
29061
|
// src/core/local-executor.ts
|
|
29058
|
-
function quoteShellArg(arg) {
|
|
29059
|
-
if (/^[A-Za-z0-9_./:=+-]+$/.test(arg)) return arg;
|
|
29060
|
-
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
29061
|
-
}
|
|
29062
29062
|
function buildLaunchFlagArgs(flags) {
|
|
29063
29063
|
const args = [];
|
|
29064
29064
|
if (flags.worktree === false) args.push("--no-worktree");
|
|
@@ -29790,10 +29790,32 @@ var init_slot_launch_guard_occupied = __esm({
|
|
|
29790
29790
|
}
|
|
29791
29791
|
});
|
|
29792
29792
|
|
|
29793
|
+
// src/utils/package-runner.ts
|
|
29794
|
+
function commandExists(command2) {
|
|
29795
|
+
const result = (0, import_child_process6.spawnSync)("sh", ["-c", `command -v ${JSON.stringify(command2)}`], {
|
|
29796
|
+
encoding: "utf8"
|
|
29797
|
+
});
|
|
29798
|
+
return result.status === 0 && Boolean(result.stdout?.trim());
|
|
29799
|
+
}
|
|
29800
|
+
function packageRunner() {
|
|
29801
|
+
if (cached !== void 0) return cached;
|
|
29802
|
+
const available = RUNNERS.find((runner) => commandExists(runner.split(" ")[0]));
|
|
29803
|
+
cached = available ?? RUNNERS[0];
|
|
29804
|
+
return cached;
|
|
29805
|
+
}
|
|
29806
|
+
var import_child_process6, RUNNERS, cached;
|
|
29807
|
+
var init_package_runner = __esm({
|
|
29808
|
+
"src/utils/package-runner.ts"() {
|
|
29809
|
+
"use strict";
|
|
29810
|
+
import_child_process6 = require("child_process");
|
|
29811
|
+
RUNNERS = ["npx --yes", "bunx", "pnpm dlx", "yarn dlx"];
|
|
29812
|
+
}
|
|
29813
|
+
});
|
|
29814
|
+
|
|
29793
29815
|
// src/core/slot-preflight.ts
|
|
29794
29816
|
function listPm2Processes() {
|
|
29795
29817
|
try {
|
|
29796
|
-
const raw = (0,
|
|
29818
|
+
const raw = (0, import_child_process7.execSync)(`${packageRunner()} pm2 jlist`, {
|
|
29797
29819
|
encoding: "utf8",
|
|
29798
29820
|
stdio: ["pipe", "pipe", "ignore"],
|
|
29799
29821
|
timeout: 3e3
|
|
@@ -29874,7 +29896,7 @@ function inspectSlotReadiness(repoPath, agentId, options = {}) {
|
|
|
29874
29896
|
remediation: "Stop the other harness session (./.har/teardown.sh in that repo) or use a different agent slot.",
|
|
29875
29897
|
details: { processes: foreign.processes }
|
|
29876
29898
|
});
|
|
29877
|
-
remediations.push(
|
|
29899
|
+
remediations.push(`Inspect with: ${packageRunner()} pm2 jlist | grep agent-${agentId}`);
|
|
29878
29900
|
}
|
|
29879
29901
|
if (usesPm2 && pm2Procs) {
|
|
29880
29902
|
const slotPrefix = `har-${projectName}-agent-${agentId}-`;
|
|
@@ -30008,7 +30030,7 @@ function formatPreflightReport(agentId, readiness) {
|
|
|
30008
30030
|
}
|
|
30009
30031
|
return lines2.join("\n");
|
|
30010
30032
|
}
|
|
30011
|
-
var path16,
|
|
30033
|
+
var path16, import_child_process7;
|
|
30012
30034
|
var init_slot_preflight = __esm({
|
|
30013
30035
|
"src/core/slot-preflight.ts"() {
|
|
30014
30036
|
"use strict";
|
|
@@ -30019,14 +30041,15 @@ var init_slot_preflight = __esm({
|
|
|
30019
30041
|
init_slot_launch_guard_occupied();
|
|
30020
30042
|
init_slot_ports();
|
|
30021
30043
|
init_slot_registry();
|
|
30022
|
-
|
|
30044
|
+
import_child_process7 = require("child_process");
|
|
30045
|
+
init_package_runner();
|
|
30023
30046
|
}
|
|
30024
30047
|
});
|
|
30025
30048
|
|
|
30026
30049
|
// src/core/slot-status.ts
|
|
30027
30050
|
function readGitRemote(repoPath) {
|
|
30028
30051
|
try {
|
|
30029
|
-
const remote = (0,
|
|
30052
|
+
const remote = (0, import_child_process8.execSync)("git remote get-url origin", {
|
|
30030
30053
|
cwd: repoPath,
|
|
30031
30054
|
encoding: "utf8",
|
|
30032
30055
|
stdio: ["pipe", "pipe", "ignore"]
|
|
@@ -30038,7 +30061,7 @@ function readGitRemote(repoPath) {
|
|
|
30038
30061
|
}
|
|
30039
30062
|
function runGit2(cwd, args) {
|
|
30040
30063
|
try {
|
|
30041
|
-
return (0,
|
|
30064
|
+
return (0, import_child_process8.execSync)(`git ${args}`, {
|
|
30042
30065
|
cwd,
|
|
30043
30066
|
encoding: "utf8",
|
|
30044
30067
|
stdio: ["pipe", "pipe", "ignore"]
|
|
@@ -30114,7 +30137,7 @@ function lastBuildPass(run2) {
|
|
|
30114
30137
|
}
|
|
30115
30138
|
function listPm2Processes2() {
|
|
30116
30139
|
try {
|
|
30117
|
-
const raw = (0,
|
|
30140
|
+
const raw = (0, import_child_process8.execSync)(`${packageRunner()} pm2 jlist`, {
|
|
30118
30141
|
encoding: "utf8",
|
|
30119
30142
|
stdio: ["pipe", "pipe", "ignore"],
|
|
30120
30143
|
timeout: 3e3
|
|
@@ -30217,14 +30240,14 @@ function collectEnvironmentStatus(repoPath) {
|
|
|
30217
30240
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
30218
30241
|
};
|
|
30219
30242
|
}
|
|
30220
|
-
var fs16, os6, path17,
|
|
30243
|
+
var fs16, os6, path17, import_child_process8, BYPASS_WARNING_MS;
|
|
30221
30244
|
var init_slot_status = __esm({
|
|
30222
30245
|
"src/core/slot-status.ts"() {
|
|
30223
30246
|
"use strict";
|
|
30224
30247
|
fs16 = __toESM(require("fs"));
|
|
30225
30248
|
os6 = __toESM(require("os"));
|
|
30226
30249
|
path17 = __toESM(require("path"));
|
|
30227
|
-
|
|
30250
|
+
import_child_process8 = require("child_process");
|
|
30228
30251
|
init_env();
|
|
30229
30252
|
init_manifest();
|
|
30230
30253
|
init_stages();
|
|
@@ -30232,6 +30255,7 @@ var init_slot_status = __esm({
|
|
|
30232
30255
|
init_runs();
|
|
30233
30256
|
init_slot_registry();
|
|
30234
30257
|
init_slot_preflight();
|
|
30258
|
+
init_package_runner();
|
|
30235
30259
|
BYPASS_WARNING_MS = 15 * 60 * 1e3;
|
|
30236
30260
|
}
|
|
30237
30261
|
});
|
|
@@ -31227,11 +31251,11 @@ function buildTelemetryEnvBlock(attrs) {
|
|
|
31227
31251
|
const lines2 = [
|
|
31228
31252
|
"",
|
|
31229
31253
|
"# HAR session attribution (generated)",
|
|
31230
|
-
`HAR_SESSION_KEY=${attrs.sessionKey}`,
|
|
31231
|
-
...attrs.workUnitId ? [`HAR_WORK_UNIT_ID=${attrs.workUnitId}`] : [],
|
|
31232
|
-
...attrs.attemptId ? [`HAR_ATTEMPT_ID=${attrs.attemptId}`] : [],
|
|
31233
|
-
`HAR_CONTROL_API_URL=${apiUrl}`,
|
|
31234
|
-
`OTEL_RESOURCE_ATTRIBUTES=${buildOtelResourceAttributes(attrs)}`,
|
|
31254
|
+
`HAR_SESSION_KEY=${quoteShellArg(attrs.sessionKey)}`,
|
|
31255
|
+
...attrs.workUnitId ? [`HAR_WORK_UNIT_ID=${quoteShellArg(attrs.workUnitId)}`] : [],
|
|
31256
|
+
...attrs.attemptId ? [`HAR_ATTEMPT_ID=${quoteShellArg(attrs.attemptId)}`] : [],
|
|
31257
|
+
`HAR_CONTROL_API_URL=${quoteShellArg(apiUrl)}`,
|
|
31258
|
+
`OTEL_RESOURCE_ATTRIBUTES=${quoteShellArg(buildOtelResourceAttributes(attrs))}`,
|
|
31235
31259
|
"# Agent telemetry: @osfactory/otel-hook \u2192 Mission Control (har telemetry on|off)"
|
|
31236
31260
|
];
|
|
31237
31261
|
return lines2.join("\n") + "\n";
|
|
@@ -31264,6 +31288,7 @@ var init_telemetry_env = __esm({
|
|
|
31264
31288
|
fs20 = __toESM(require("fs"));
|
|
31265
31289
|
path21 = __toESM(require("path"));
|
|
31266
31290
|
init_control_config();
|
|
31291
|
+
init_shell();
|
|
31267
31292
|
TELEMETRY_MARKER_START = "# HAR session attribution (generated)";
|
|
31268
31293
|
TELEMETRY_MARKER_END = "# end HAR telemetry";
|
|
31269
31294
|
}
|
|
@@ -53489,8 +53514,8 @@ exec "${otelHookCommand}" run \\
|
|
|
53489
53514
|
}
|
|
53490
53515
|
return wrapperPath;
|
|
53491
53516
|
}
|
|
53492
|
-
function
|
|
53493
|
-
const result = (0,
|
|
53517
|
+
function commandExists3(command2) {
|
|
53518
|
+
const result = (0, import_child_process11.spawnSync)("sh", ["-c", `command -v ${JSON.stringify(command2)}`], {
|
|
53494
53519
|
encoding: "utf8"
|
|
53495
53520
|
});
|
|
53496
53521
|
return result.status === 0 && Boolean(result.stdout?.trim());
|
|
@@ -53500,25 +53525,37 @@ function resolveOtelHookCommand(hooksHome) {
|
|
|
53500
53525
|
if (fs41.existsSync(local)) return local;
|
|
53501
53526
|
return null;
|
|
53502
53527
|
}
|
|
53528
|
+
function resolveHooksInstaller(hooksHome) {
|
|
53529
|
+
const candidates = [
|
|
53530
|
+
{
|
|
53531
|
+
command: "npm",
|
|
53532
|
+
args: ["install", "--prefix", hooksHome, "--no-fund", "--no-audit", OTEL_HOOKS_PACKAGE]
|
|
53533
|
+
},
|
|
53534
|
+
{ command: "bun", args: ["add", "--cwd", hooksHome, OTEL_HOOKS_PACKAGE] },
|
|
53535
|
+
{ command: "pnpm", args: ["add", "--dir", hooksHome, OTEL_HOOKS_PACKAGE] }
|
|
53536
|
+
];
|
|
53537
|
+
return candidates.find((candidate) => commandExists3(candidate.command)) ?? null;
|
|
53538
|
+
}
|
|
53503
53539
|
function tryInstallPackage(hooksHome) {
|
|
53504
53540
|
fs41.mkdirSync(hooksHome, { recursive: true });
|
|
53505
|
-
|
|
53541
|
+
const installer = resolveHooksInstaller(hooksHome);
|
|
53542
|
+
if (!installer) {
|
|
53506
53543
|
return {
|
|
53507
53544
|
ok: false,
|
|
53508
|
-
detail: "
|
|
53545
|
+
detail: "no package manager found; install Node.js or bun to use @osfactory/otel-hook"
|
|
53509
53546
|
};
|
|
53510
53547
|
}
|
|
53511
|
-
const
|
|
53512
|
-
|
|
53513
|
-
|
|
53514
|
-
|
|
53515
|
-
);
|
|
53548
|
+
const described = `${installer.command} ${installer.args.join(" ")}`;
|
|
53549
|
+
const result = (0, import_child_process11.spawnSync)(installer.command, installer.args, {
|
|
53550
|
+
encoding: "utf8",
|
|
53551
|
+
timeout: 18e4
|
|
53552
|
+
});
|
|
53516
53553
|
if (result.status === 0 && fs41.existsSync(localOtelHookBin(hooksHome))) {
|
|
53517
|
-
return { ok: true, detail:
|
|
53554
|
+
return { ok: true, detail: described };
|
|
53518
53555
|
}
|
|
53519
53556
|
return {
|
|
53520
53557
|
ok: false,
|
|
53521
|
-
detail:
|
|
53558
|
+
detail: `${described} failed: ${(result.stderr || result.stdout || "").trim().slice(0, 400)}`
|
|
53522
53559
|
};
|
|
53523
53560
|
}
|
|
53524
53561
|
function uninstallLegacyPythonHooks(hooksHome) {
|
|
@@ -53529,9 +53566,9 @@ function uninstallLegacyPythonHooks(hooksHome) {
|
|
|
53529
53566
|
["pip3", ["uninstall", "-y", "opentelemetry-hooks"]]
|
|
53530
53567
|
];
|
|
53531
53568
|
for (const [cmd, args] of attempts) {
|
|
53532
|
-
if (!
|
|
53569
|
+
if (!commandExists3(cmd)) continue;
|
|
53533
53570
|
try {
|
|
53534
|
-
(0,
|
|
53571
|
+
(0, import_child_process11.spawnSync)(cmd, args, { encoding: "utf8", timeout: 6e4 });
|
|
53535
53572
|
} catch {
|
|
53536
53573
|
}
|
|
53537
53574
|
}
|
|
@@ -53563,7 +53600,7 @@ function normalizeLegacyProviderFlagsInCommand(command2) {
|
|
|
53563
53600
|
}
|
|
53564
53601
|
function runSetupProvider(providerId, otelHookCommand, wrapperPath) {
|
|
53565
53602
|
const hookCommand = `${wrapperPath} --provider ${providerId}`;
|
|
53566
|
-
const result = (0,
|
|
53603
|
+
const result = (0, import_child_process11.spawnSync)(
|
|
53567
53604
|
otelHookCommand,
|
|
53568
53605
|
[
|
|
53569
53606
|
"setup",
|
|
@@ -53804,11 +53841,11 @@ function ensureOtelHooks(options) {
|
|
|
53804
53841
|
function disableOtelHooksExport() {
|
|
53805
53842
|
return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
|
|
53806
53843
|
}
|
|
53807
|
-
var
|
|
53844
|
+
var import_child_process11, fs41, os15, path47, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
|
|
53808
53845
|
var init_otel_hooks = __esm({
|
|
53809
53846
|
"src/core/otel-hooks.ts"() {
|
|
53810
53847
|
"use strict";
|
|
53811
|
-
|
|
53848
|
+
import_child_process11 = require("child_process");
|
|
53812
53849
|
fs41 = __toESM(require("fs"));
|
|
53813
53850
|
os15 = __toESM(require("os"));
|
|
53814
53851
|
path47 = __toESM(require("path"));
|
|
@@ -70177,13 +70214,13 @@ var path44 = __toESM(require("path"));
|
|
|
70177
70214
|
var readline5 = __toESM(require("readline"));
|
|
70178
70215
|
|
|
70179
70216
|
// src/utils/clipboard.ts
|
|
70180
|
-
var
|
|
70181
|
-
function
|
|
70182
|
-
const probe = process.platform === "win32" ? (0,
|
|
70217
|
+
var import_child_process9 = require("child_process");
|
|
70218
|
+
function commandExists2(command2) {
|
|
70219
|
+
const probe = process.platform === "win32" ? (0, import_child_process9.spawnSync)("where", [command2], { encoding: "utf8", stdio: ["ignore", "ignore", "ignore"] }) : (0, import_child_process9.spawnSync)("which", [command2], { encoding: "utf8", stdio: ["ignore", "ignore", "ignore"] });
|
|
70183
70220
|
return probe.status === 0;
|
|
70184
70221
|
}
|
|
70185
70222
|
function tryPipeCommand(command2, args, text) {
|
|
70186
|
-
const result = (0,
|
|
70223
|
+
const result = (0, import_child_process9.spawnSync)(command2, args, {
|
|
70187
70224
|
input: text,
|
|
70188
70225
|
encoding: "utf8",
|
|
70189
70226
|
stdio: ["pipe", "ignore", "ignore"]
|
|
@@ -70198,12 +70235,12 @@ function writeOsc52Clipboard(text, stream = process.stderr) {
|
|
|
70198
70235
|
return true;
|
|
70199
70236
|
}
|
|
70200
70237
|
function copyViaPlatformTools(text) {
|
|
70201
|
-
if (process.platform === "darwin" &&
|
|
70238
|
+
if (process.platform === "darwin" && commandExists2("pbcopy")) {
|
|
70202
70239
|
if (tryPipeCommand("pbcopy", [], text)) return { ok: true, method: "pbcopy" };
|
|
70203
70240
|
}
|
|
70204
70241
|
if (process.platform === "win32") {
|
|
70205
|
-
if (
|
|
70206
|
-
const result = (0,
|
|
70242
|
+
if (commandExists2("powershell")) {
|
|
70243
|
+
const result = (0, import_child_process9.spawnSync)(
|
|
70207
70244
|
"powershell",
|
|
70208
70245
|
[
|
|
70209
70246
|
"-NoProfile",
|
|
@@ -70219,18 +70256,18 @@ function copyViaPlatformTools(text) {
|
|
|
70219
70256
|
);
|
|
70220
70257
|
if (result.status === 0 && !result.error) return { ok: true, method: "powershell" };
|
|
70221
70258
|
}
|
|
70222
|
-
if (
|
|
70259
|
+
if (commandExists2("clip") && tryPipeCommand("clip", [], text)) {
|
|
70223
70260
|
return { ok: true, method: "clip" };
|
|
70224
70261
|
}
|
|
70225
70262
|
}
|
|
70226
70263
|
if (process.platform === "linux" || process.platform === "freebsd" || process.platform === "openbsd") {
|
|
70227
|
-
if (
|
|
70264
|
+
if (commandExists2("wl-copy") && tryPipeCommand("wl-copy", [], text)) {
|
|
70228
70265
|
return { ok: true, method: "wl-copy" };
|
|
70229
70266
|
}
|
|
70230
|
-
if (
|
|
70267
|
+
if (commandExists2("xclip") && tryPipeCommand("xclip", ["-selection", "clipboard"], text)) {
|
|
70231
70268
|
return { ok: true, method: "xclip" };
|
|
70232
70269
|
}
|
|
70233
|
-
if (
|
|
70270
|
+
if (commandExists2("xsel") && tryPipeCommand("xsel", ["--clipboard", "--input"], text)) {
|
|
70234
70271
|
return { ok: true, method: "xsel" };
|
|
70235
70272
|
}
|
|
70236
70273
|
}
|
|
@@ -70449,7 +70486,7 @@ init_validation();
|
|
|
70449
70486
|
init_control_config();
|
|
70450
70487
|
|
|
70451
70488
|
// src/core/control-lifecycle.ts
|
|
70452
|
-
var
|
|
70489
|
+
var import_child_process10 = require("child_process");
|
|
70453
70490
|
var path46 = __toESM(require("path"));
|
|
70454
70491
|
|
|
70455
70492
|
// src/core/control-image.ts
|
|
@@ -70502,7 +70539,7 @@ function buildDockerRunArgs(options) {
|
|
|
70502
70539
|
return args;
|
|
70503
70540
|
}
|
|
70504
70541
|
function runDocker(args) {
|
|
70505
|
-
const result = (0,
|
|
70542
|
+
const result = (0, import_child_process10.spawnSync)("docker", args, {
|
|
70506
70543
|
stdio: "inherit",
|
|
70507
70544
|
env: process.env
|
|
70508
70545
|
});
|
|
@@ -70512,7 +70549,7 @@ function runDocker(args) {
|
|
|
70512
70549
|
return result.status ?? 1;
|
|
70513
70550
|
}
|
|
70514
70551
|
function controlContainerExists(name = CONTROL_CONTAINER_NAME) {
|
|
70515
|
-
const result = (0,
|
|
70552
|
+
const result = (0, import_child_process10.spawnSync)("docker", ["ps", "-aq", "-f", `name=^${name}$`], {
|
|
70516
70553
|
encoding: "utf8",
|
|
70517
70554
|
stdio: ["pipe", "pipe", "ignore"]
|
|
70518
70555
|
});
|
|
@@ -72352,13 +72389,13 @@ init_portal_credentials();
|
|
|
72352
72389
|
// src/core/portal-login.ts
|
|
72353
72390
|
var http = __toESM(require("http"));
|
|
72354
72391
|
var import_crypto = require("crypto");
|
|
72355
|
-
var
|
|
72392
|
+
var import_child_process12 = require("child_process");
|
|
72356
72393
|
var CALLBACK_PATH = "/callback";
|
|
72357
72394
|
var LOGIN_TIMEOUT_MS = 3 * 6e4;
|
|
72358
72395
|
function openBrowser(url) {
|
|
72359
72396
|
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
72360
72397
|
try {
|
|
72361
|
-
const child = (0,
|
|
72398
|
+
const child = (0, import_child_process12.spawn)(cmd, args, { stdio: "ignore", detached: true });
|
|
72362
72399
|
child.on("error", () => {
|
|
72363
72400
|
});
|
|
72364
72401
|
child.unref();
|
|
@@ -73518,7 +73555,7 @@ __export(util_exports, {
|
|
|
73518
73555
|
assertNever: () => assertNever,
|
|
73519
73556
|
assertNotEqual: () => assertNotEqual,
|
|
73520
73557
|
assignProp: () => assignProp,
|
|
73521
|
-
cached: () =>
|
|
73558
|
+
cached: () => cached2,
|
|
73522
73559
|
captureStackTrace: () => captureStackTrace,
|
|
73523
73560
|
cleanEnum: () => cleanEnum,
|
|
73524
73561
|
cleanRegex: () => cleanRegex,
|
|
@@ -73583,7 +73620,7 @@ function jsonStringifyReplacer(_2, value) {
|
|
|
73583
73620
|
return value.toString();
|
|
73584
73621
|
return value;
|
|
73585
73622
|
}
|
|
73586
|
-
function
|
|
73623
|
+
function cached2(getter) {
|
|
73587
73624
|
const set = false;
|
|
73588
73625
|
return {
|
|
73589
73626
|
get value() {
|
|
@@ -73672,7 +73709,7 @@ var captureStackTrace = Error.captureStackTrace ? Error.captureStackTrace : (...
|
|
|
73672
73709
|
function isObject(data) {
|
|
73673
73710
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
73674
73711
|
}
|
|
73675
|
-
var allowsEval =
|
|
73712
|
+
var allowsEval = cached2(() => {
|
|
73676
73713
|
if (typeof navigator !== "undefined" && navigator?.userAgent?.includes("Cloudflare")) {
|
|
73677
73714
|
return false;
|
|
73678
73715
|
}
|
|
@@ -75167,7 +75204,7 @@ function handleOptionalObjectResult(result, final, key, input) {
|
|
|
75167
75204
|
}
|
|
75168
75205
|
var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
75169
75206
|
$ZodType.init(inst, def);
|
|
75170
|
-
const _normalized =
|
|
75207
|
+
const _normalized = cached2(() => {
|
|
75171
75208
|
const keys = Object.keys(def.shape);
|
|
75172
75209
|
for (const k of keys) {
|
|
75173
75210
|
if (!(def.shape[k] instanceof $ZodType)) {
|
|
@@ -75402,7 +75439,7 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
75402
75439
|
}
|
|
75403
75440
|
return propValues;
|
|
75404
75441
|
});
|
|
75405
|
-
const disc =
|
|
75442
|
+
const disc = cached2(() => {
|
|
75406
75443
|
const opts = def.options;
|
|
75407
75444
|
const map = /* @__PURE__ */ new Map();
|
|
75408
75445
|
for (const o of opts) {
|
|
@@ -69,6 +69,11 @@ how this project is built and tested. Use toolchain variables from `.env.agent.<
|
|
|
69
69
|
The stock verify section is keyed by `HARNESS_ECOSYSTEM`; it is a starting point,
|
|
70
70
|
not the repo's final contract. Replace conventions that do not match this project.
|
|
71
71
|
|
|
72
|
+
`${NPM_BIN}` may resolve to bun, pnpm, or yarn as well as npm, so keep Node steps
|
|
73
|
+
package-manager agnostic: always `${NPM_BIN:-npm} run <script>` (never bare
|
|
74
|
+
`${NPM_BIN} test`, which runs bun's own test runner), and never npm-only flags
|
|
75
|
+
such as `--prefix` — use a subshell like `(cd docs && ${NPM_BIN:-npm} run build)`.
|
|
76
|
+
|
|
72
77
|
**Tier contract:**
|
|
73
78
|
|
|
74
79
|
| Mode | Command | Intent |
|
|
@@ -25,7 +25,7 @@ Prefer targeted edits over full rewrites. Key files to review:
|
|
|
25
25
|
Keep this accurate — it is the harness index. Update whenever scripts, stages, or workflow change.
|
|
26
26
|
|
|
27
27
|
### `.har/harness.env`, `verify.sh`, `provision-toolchain.sh`, `ecosystem.agent.template.cjs`, `CLAUDE.agent.md`
|
|
28
|
-
Align commands and instructions with the current stack. Verify steps must use toolchain paths from `.env.agent.<id>` (`PYTHON_BIN`, `NPM_BIN`, `XCODEBUILD_BIN`, …) — never hardcoded venv or interpreter paths. Replace stock ecosystem conventions that do not match the repository; do not leave npm/pytest/go/cargo/maven/gradle examples in place by accident.
|
|
28
|
+
Align commands and instructions with the current stack. Verify steps must use toolchain paths from `.env.agent.<id>` (`PYTHON_BIN`, `NPM_BIN`, `XCODEBUILD_BIN`, …) — never hardcoded venv or interpreter paths. `NPM_BIN` may be bun, pnpm, or yarn, so Node steps must use `${NPM_BIN:-npm} run <script>` and avoid npm-only flags such as `--prefix`. Replace stock ecosystem conventions that do not match the repository; do not leave npm/pytest/go/cargo/maven/gradle examples in place by accident.
|
|
29
29
|
|
|
30
30
|
### `.har/env.template`, `setup-infra.sh`, `docker-compose.agent.yml`
|
|
31
31
|
Update only if infra changed.
|
|
@@ -28,7 +28,7 @@ case "$COMMAND" in
|
|
|
28
28
|
ENV_FILE="$(resolve_agent_env_file "$AGENT_ID" "$REPO_ROOT" || true)"
|
|
29
29
|
WORKTREE_DIR="$(existing_slot_worktree "$AGENT_ID")"
|
|
30
30
|
REG_FILE="$(slot_registry_file "$AGENT_ID")"
|
|
31
|
-
PM2_RAW=$(
|
|
31
|
+
PM2_RAW=$($(har_pkg_exec) pm2 jlist 2>/dev/null || true)
|
|
32
32
|
PM2_FOUND=false
|
|
33
33
|
PM2_FOREIGN=false
|
|
34
34
|
PM2_LEGACY=false
|
|
@@ -123,22 +123,23 @@ process.stdin.on('end', () => {
|
|
|
123
123
|
logs)
|
|
124
124
|
SERVICE="${3:-}"
|
|
125
125
|
if [ -n "$SERVICE" ]; then
|
|
126
|
-
|
|
126
|
+
$(har_pkg_exec) pm2 logs "${PM2_SLOT_PREFIX}-${SERVICE}" --lines 100
|
|
127
127
|
else
|
|
128
|
-
|
|
128
|
+
$(har_pkg_exec) pm2 logs --name "${PM2_SLOT_PREFIX}" --lines 100
|
|
129
129
|
fi
|
|
130
130
|
;;
|
|
131
131
|
|
|
132
132
|
restart)
|
|
133
133
|
SERVICE="${3:-}"
|
|
134
|
+
PKG_EXEC="$(har_pkg_exec)"
|
|
134
135
|
if [ -n "$SERVICE" ]; then
|
|
135
|
-
|
|
136
|
+
$(har_pkg_exec) pm2 restart "${PM2_SLOT_PREFIX}-${SERVICE}"
|
|
136
137
|
else
|
|
137
|
-
|
|
138
|
+
$(har_pkg_exec) pm2 jlist 2>/dev/null | node -e "
|
|
138
139
|
const prefix = '${PM2_SLOT_PREFIX}-';
|
|
139
140
|
const d = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));
|
|
140
141
|
const names = d.filter(x => x.name && x.name.startsWith(prefix)).map(x => x.name);
|
|
141
|
-
names.forEach(n => require('child_process').execSync('
|
|
142
|
+
names.forEach(n => require('child_process').execSync('${PKG_EXEC} pm2 restart ' + n, {stdio:'inherit'}));
|
|
142
143
|
if (names.length === 0) console.log('No processes found for ${PM2_SLOT_PREFIX}');
|
|
143
144
|
" 2>/dev/null || true
|
|
144
145
|
fi
|
|
@@ -184,7 +184,7 @@ har_check_foreign_pm2() {
|
|
|
184
184
|
local agent_id="$1"
|
|
185
185
|
local pm2_raw
|
|
186
186
|
har_harness_uses_pm2 || return 0
|
|
187
|
-
pm2_raw="$(
|
|
187
|
+
pm2_raw="$($(har_pkg_exec) pm2 jlist 2>/dev/null || true)"
|
|
188
188
|
[ -n "$pm2_raw" ] || return 0
|
|
189
189
|
set +e
|
|
190
190
|
echo "$pm2_raw" | node -e "
|
|
@@ -51,6 +51,10 @@ export HARNESS_AGENT_SLOT_MAX=5
|
|
|
51
51
|
# Ecosystem: auto (detect from manifests) | node | python | go | rust | java | ruby | none
|
|
52
52
|
export HARNESS_ECOSYSTEM="auto"
|
|
53
53
|
# export HARNESS_INSTALL_CMD="make deps"
|
|
54
|
+
# Node package manager: auto-detected from package.json "packageManager" and the
|
|
55
|
+
# lockfile (bun.lock → bun, pnpm-lock.yaml → pnpm, yarn.lock → yarn, else npm),
|
|
56
|
+
# falling back to whichever is installed. Set to pin one: npm | bun | pnpm | yarn
|
|
57
|
+
# export HARNESS_NODE_PACKAGE_MANAGER="bun"
|
|
54
58
|
|
|
55
59
|
# Shared infrastructure — space-separated docker compose service names from
|
|
56
60
|
# docker-compose.agent.yml. Started ONCE by setup-infra.sh and shared by all
|
|
@@ -66,6 +70,119 @@ har_infra_enabled() {
|
|
|
66
70
|
esac
|
|
67
71
|
}
|
|
68
72
|
|
|
73
|
+
# ── Node package manager helpers ──────────────────────────────────────────────
|
|
74
|
+
# Mirrored verbatim in harness.env and provision-toolchain.sh so a sourcing
|
|
75
|
+
# script and the provisioning subprocess resolve the same tool.
|
|
76
|
+
|
|
77
|
+
# Package managers HAR can drive, in fallback preference order.
|
|
78
|
+
HAR_NODE_PACKAGE_MANAGERS="npm bun pnpm yarn"
|
|
79
|
+
|
|
80
|
+
# Package manager the repo declares: an explicit HARNESS_NODE_PACKAGE_MANAGER
|
|
81
|
+
# wins, then package.json "packageManager", then the lockfile. Empty when the
|
|
82
|
+
# repo says nothing.
|
|
83
|
+
har_node_declared_package_manager() {
|
|
84
|
+
local dir="${1:-.}"
|
|
85
|
+
|
|
86
|
+
if [ -n "${HARNESS_NODE_PACKAGE_MANAGER:-}" ]; then
|
|
87
|
+
echo "$HARNESS_NODE_PACKAGE_MANAGER"
|
|
88
|
+
return
|
|
89
|
+
fi
|
|
90
|
+
if [ -f "$dir/package.json" ]; then
|
|
91
|
+
local field
|
|
92
|
+
field="$(sed -n 's/.*"packageManager"[[:space:]]*:[[:space:]]*"\([a-z]*\)@.*/\1/p' "$dir/package.json" | head -1)"
|
|
93
|
+
if [ -n "$field" ]; then
|
|
94
|
+
echo "$field"
|
|
95
|
+
return
|
|
96
|
+
fi
|
|
97
|
+
fi
|
|
98
|
+
if [ -f "$dir/bun.lock" ] || [ -f "$dir/bun.lockb" ]; then echo bun; return; fi
|
|
99
|
+
if [ -f "$dir/pnpm-lock.yaml" ]; then echo pnpm; return; fi
|
|
100
|
+
if [ -f "$dir/yarn.lock" ]; then echo yarn; return; fi
|
|
101
|
+
if [ -f "$dir/package-lock.json" ]; then echo npm; return; fi
|
|
102
|
+
echo ""
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# Package manager to actually run. A manager the repo declares but this machine
|
|
106
|
+
# lacks falls back to one that is installed, so a repo pinned to npm still
|
|
107
|
+
# provisions on a bun-only machine (and the reverse).
|
|
108
|
+
har_node_package_manager() {
|
|
109
|
+
local dir="${1:-.}"
|
|
110
|
+
local declared
|
|
111
|
+
declared="$(har_node_declared_package_manager "$dir")"
|
|
112
|
+
|
|
113
|
+
if [ -n "$declared" ] && command -v "$declared" >/dev/null 2>&1; then
|
|
114
|
+
echo "$declared"
|
|
115
|
+
return
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
local candidate
|
|
119
|
+
for candidate in $HAR_NODE_PACKAGE_MANAGERS; do
|
|
120
|
+
if command -v "$candidate" >/dev/null 2>&1; then
|
|
121
|
+
echo "$candidate"
|
|
122
|
+
return
|
|
123
|
+
fi
|
|
124
|
+
done
|
|
125
|
+
|
|
126
|
+
echo "${declared:-npm}"
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Lockfile a manager writes, so a substitute install can clean up after itself.
|
|
130
|
+
har_node_lockfile() {
|
|
131
|
+
case "$1" in
|
|
132
|
+
bun) echo "bun.lock" ;;
|
|
133
|
+
npm) echo "package-lock.json" ;;
|
|
134
|
+
pnpm) echo "pnpm-lock.yaml" ;;
|
|
135
|
+
yarn) echo "yarn.lock" ;;
|
|
136
|
+
*) echo "" ;;
|
|
137
|
+
esac
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
# Install dependencies in a directory. When a substitute manager stands in for
|
|
141
|
+
# the one the repo declares, any lockfile it creates is removed afterwards:
|
|
142
|
+
# provisioning must not migrate the repo to a different package manager.
|
|
143
|
+
# (bun writes bun.lock even under --no-save, so the flags alone are not enough.)
|
|
144
|
+
har_node_install() {
|
|
145
|
+
local dir="$1"
|
|
146
|
+
local manager="$2"
|
|
147
|
+
local declared="${3:-}"
|
|
148
|
+
local substituting=false
|
|
149
|
+
local lockfile=""
|
|
150
|
+
local had_lockfile=false
|
|
151
|
+
|
|
152
|
+
if [ -n "$declared" ] && [ "$declared" != "$manager" ]; then
|
|
153
|
+
substituting=true
|
|
154
|
+
lockfile="$(har_node_lockfile "$manager")"
|
|
155
|
+
if [ -n "$lockfile" ] && [ -e "$dir/$lockfile" ]; then
|
|
156
|
+
had_lockfile=true
|
|
157
|
+
fi
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
local code=0
|
|
161
|
+
(cd "$dir" && "$manager" install --silent) || code=$?
|
|
162
|
+
|
|
163
|
+
if [ "$substituting" = true ] && [ "$had_lockfile" = false ] && [ -n "$lockfile" ]; then
|
|
164
|
+
rm -f "$dir/$lockfile"
|
|
165
|
+
[ "$manager" = "bun" ] && rm -f "$dir/bun.lockb"
|
|
166
|
+
fi
|
|
167
|
+
return $code
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# Package runner (npx equivalent) for one-off CLIs such as pm2, including the
|
|
171
|
+
# flag that keeps it non-interactive. Takes a manager name, or none to resolve
|
|
172
|
+
# from the environment and PATH.
|
|
173
|
+
har_pkg_exec() {
|
|
174
|
+
case "${1:-${HARNESS_NODE_PACKAGE_MANAGER:-}}" in
|
|
175
|
+
bun) echo "bunx"; return ;;
|
|
176
|
+
pnpm) echo "pnpm dlx"; return ;;
|
|
177
|
+
yarn) echo "yarn dlx"; return ;;
|
|
178
|
+
npm) echo "npx --yes"; return ;;
|
|
179
|
+
esac
|
|
180
|
+
if command -v npx >/dev/null 2>&1; then echo "npx --yes"; return; fi
|
|
181
|
+
if command -v bunx >/dev/null 2>&1; then echo "bunx"; return; fi
|
|
182
|
+
if command -v pnpm >/dev/null 2>&1; then echo "pnpm dlx"; return; fi
|
|
183
|
+
echo "npx --yes"
|
|
184
|
+
}
|
|
185
|
+
|
|
69
186
|
# Postgres client — uses host tools when installed, otherwise docker exec into
|
|
70
187
|
# the shared db container. Usage: har_pg psql -d postgres -c "SELECT 1"
|
|
71
188
|
# har_pg createdb -T template_x agent_1
|
|
@@ -249,13 +249,13 @@ DEBUG_PORT="$DEBUG_PORT" \
|
|
|
249
249
|
|
|
250
250
|
PM2_REGEX="$(har_pm2_delete_regex "$AGENT_ID")"
|
|
251
251
|
# Stop existing processes for this agent (project-scoped — never touch other harnesses).
|
|
252
|
-
|
|
252
|
+
$(har_pkg_exec) pm2 delete "$PM2_REGEX" 2>/dev/null || true
|
|
253
253
|
|
|
254
254
|
# Start PM2 processes
|
|
255
255
|
log "Starting PM2 processes..."
|
|
256
256
|
cd "$WORK_DIR"
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
$(har_pkg_exec) pm2 start "$ECOSYSTEM_FILE"
|
|
258
|
+
$(har_pkg_exec) pm2 save --force >/dev/null 2>&1 || true
|
|
259
259
|
|
|
260
260
|
# Health check
|
|
261
261
|
if [ -n "${HARNESS_HEALTH_CHECK_PATH:-}" ]; then
|