@osfactory/har 0.20.0 → 0.21.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/README.md +14 -0
- package/dist/index.js +701 -283
- package/dist/templates/agent-skills/har-wt.md +11 -0
- package/dist/templates/har-boilerplate/agent-slot.sh +3 -1
- package/dist/templates/har-boilerplate/gitignore.template +3 -0
- package/dist/templates/har-boilerplate/launch.sh +10 -0
- package/dist/templates/har-boilerplate-cli/agent-slot.sh +3 -1
- package/dist/templates/har-boilerplate-cli/gitignore.template +3 -0
- package/dist/templates/har-boilerplate-cli/launch.sh +10 -0
- package/dist/templates/har-boilerplate-ios/agent-slot.sh +3 -1
- package/dist/templates/har-boilerplate-ios/gitignore.template +3 -0
- package/dist/templates/har-boilerplate-ios/launch.sh +10 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -765,14 +765,14 @@ var require_url_state_machine = __commonJS({
|
|
|
765
765
|
return url.replace(/\u0009|\u000A|\u000D/g, "");
|
|
766
766
|
}
|
|
767
767
|
function shortenPath(url) {
|
|
768
|
-
const
|
|
769
|
-
if (
|
|
768
|
+
const path53 = url.path;
|
|
769
|
+
if (path53.length === 0) {
|
|
770
770
|
return;
|
|
771
771
|
}
|
|
772
|
-
if (url.scheme === "file" &&
|
|
772
|
+
if (url.scheme === "file" && path53.length === 1 && isNormalizedWindowsDriveLetter(path53[0])) {
|
|
773
773
|
return;
|
|
774
774
|
}
|
|
775
|
-
|
|
775
|
+
path53.pop();
|
|
776
776
|
}
|
|
777
777
|
function includesCredentials(url) {
|
|
778
778
|
return url.username !== "" || url.password !== "";
|
|
@@ -6351,14 +6351,14 @@ __export(fileFromPath_exports, {
|
|
|
6351
6351
|
fileFromPathSync: () => fileFromPathSync,
|
|
6352
6352
|
isFile: () => isFile
|
|
6353
6353
|
});
|
|
6354
|
-
function createFileFromPath(
|
|
6354
|
+
function createFileFromPath(path53, { mtimeMs, size }, filenameOrOptions, options = {}) {
|
|
6355
6355
|
let filename;
|
|
6356
6356
|
if (isPlainObject_default2(filenameOrOptions)) {
|
|
6357
6357
|
[options, filename] = [filenameOrOptions, void 0];
|
|
6358
6358
|
} else {
|
|
6359
6359
|
filename = filenameOrOptions;
|
|
6360
6360
|
}
|
|
6361
|
-
const file = new FileFromPath({ path:
|
|
6361
|
+
const file = new FileFromPath({ path: path53, size, lastModified: mtimeMs });
|
|
6362
6362
|
if (!filename) {
|
|
6363
6363
|
filename = file.name;
|
|
6364
6364
|
}
|
|
@@ -6367,13 +6367,13 @@ function createFileFromPath(path52, { mtimeMs, size }, filenameOrOptions, option
|
|
|
6367
6367
|
lastModified: file.lastModified
|
|
6368
6368
|
});
|
|
6369
6369
|
}
|
|
6370
|
-
function fileFromPathSync(
|
|
6371
|
-
const stats = (0, import_fs5.statSync)(
|
|
6372
|
-
return createFileFromPath(
|
|
6370
|
+
function fileFromPathSync(path53, filenameOrOptions, options = {}) {
|
|
6371
|
+
const stats = (0, import_fs5.statSync)(path53);
|
|
6372
|
+
return createFileFromPath(path53, stats, filenameOrOptions, options);
|
|
6373
6373
|
}
|
|
6374
|
-
async function fileFromPath2(
|
|
6375
|
-
const stats = await import_fs5.promises.stat(
|
|
6376
|
-
return createFileFromPath(
|
|
6374
|
+
async function fileFromPath2(path53, filenameOrOptions, options) {
|
|
6375
|
+
const stats = await import_fs5.promises.stat(path53);
|
|
6376
|
+
return createFileFromPath(path53, stats, filenameOrOptions, options);
|
|
6377
6377
|
}
|
|
6378
6378
|
var import_fs5, import_path5, import_node_domexception, __classPrivateFieldSet5, __classPrivateFieldGet6, _FileFromPath_path, _FileFromPath_start, MESSAGE, FileFromPath;
|
|
6379
6379
|
var init_fileFromPath = __esm({
|
|
@@ -6451,9 +6451,9 @@ var init_control_config = __esm({
|
|
|
6451
6451
|
// src/core/telemetry-config.ts
|
|
6452
6452
|
function getPreferencePath() {
|
|
6453
6453
|
if (process.env.HAR_TELEMETRY_CONFIG_PATH) {
|
|
6454
|
-
return
|
|
6454
|
+
return path36.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
|
|
6455
6455
|
}
|
|
6456
|
-
return
|
|
6456
|
+
return path36.join(os9.homedir(), ".har", "telemetry.json");
|
|
6457
6457
|
}
|
|
6458
6458
|
function parseEnvOverride(raw) {
|
|
6459
6459
|
if (raw === void 0 || raw === "") return void 0;
|
|
@@ -6474,10 +6474,10 @@ function normalizeSignals(enabled, raw) {
|
|
|
6474
6474
|
function readTelemetryPreference() {
|
|
6475
6475
|
const preferencePath = getPreferencePath();
|
|
6476
6476
|
try {
|
|
6477
|
-
if (!
|
|
6477
|
+
if (!fs36.existsSync(preferencePath)) {
|
|
6478
6478
|
return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
|
|
6479
6479
|
}
|
|
6480
|
-
const parsed = JSON.parse(
|
|
6480
|
+
const parsed = JSON.parse(fs36.readFileSync(preferencePath, "utf8"));
|
|
6481
6481
|
const enabled = parsed.enabled !== false;
|
|
6482
6482
|
return {
|
|
6483
6483
|
enabled,
|
|
@@ -6500,8 +6500,8 @@ function writeTelemetryPreference(enabled, signals2) {
|
|
|
6500
6500
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6501
6501
|
};
|
|
6502
6502
|
const preferencePath = getPreferencePath();
|
|
6503
|
-
|
|
6504
|
-
|
|
6503
|
+
fs36.mkdirSync(path36.dirname(preferencePath), { recursive: true });
|
|
6504
|
+
fs36.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
|
|
6505
6505
|
return preference;
|
|
6506
6506
|
}
|
|
6507
6507
|
function isTelemetryEnabled() {
|
|
@@ -6516,13 +6516,13 @@ function getTelemetrySignals() {
|
|
|
6516
6516
|
function getTelemetryPreferencePath() {
|
|
6517
6517
|
return getPreferencePath();
|
|
6518
6518
|
}
|
|
6519
|
-
var
|
|
6519
|
+
var fs36, os9, path36, DEFAULT_SIGNALS_ON, DEFAULT_SIGNALS_OFF, TELEMETRY_SIGNALS;
|
|
6520
6520
|
var init_telemetry_config = __esm({
|
|
6521
6521
|
"src/core/telemetry-config.ts"() {
|
|
6522
6522
|
"use strict";
|
|
6523
|
-
|
|
6523
|
+
fs36 = __toESM(require("fs"));
|
|
6524
6524
|
os9 = __toESM(require("os"));
|
|
6525
|
-
|
|
6525
|
+
path36 = __toESM(require("path"));
|
|
6526
6526
|
DEFAULT_SIGNALS_ON = {
|
|
6527
6527
|
metrics: true,
|
|
6528
6528
|
logs: true,
|
|
@@ -6563,15 +6563,15 @@ __export(otel_hooks_exports, {
|
|
|
6563
6563
|
});
|
|
6564
6564
|
function getOtelHooksHome() {
|
|
6565
6565
|
if (process.env.HAR_OTEL_HOOKS_HOME) {
|
|
6566
|
-
return
|
|
6566
|
+
return path42.resolve(process.env.HAR_OTEL_HOOKS_HOME);
|
|
6567
6567
|
}
|
|
6568
|
-
return
|
|
6568
|
+
return path42.join(os12.homedir(), ".har", "otel-hooks");
|
|
6569
6569
|
}
|
|
6570
6570
|
function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
|
|
6571
|
-
return
|
|
6571
|
+
return path42.join(hooksHome, "otel_config.json");
|
|
6572
6572
|
}
|
|
6573
6573
|
function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
|
|
6574
|
-
return
|
|
6574
|
+
return path42.join(hooksHome, "run-otel-hook.sh");
|
|
6575
6575
|
}
|
|
6576
6576
|
function buildOtelHooksConfig(options) {
|
|
6577
6577
|
const enabled = options?.enabled ?? isTelemetryEnabled();
|
|
@@ -6590,18 +6590,18 @@ function buildOtelHooksConfig(options) {
|
|
|
6590
6590
|
};
|
|
6591
6591
|
}
|
|
6592
6592
|
function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
|
|
6593
|
-
|
|
6593
|
+
fs40.mkdirSync(hooksHome, { recursive: true });
|
|
6594
6594
|
const configPath = getOtelHooksConfigPath(hooksHome);
|
|
6595
6595
|
const payload = {
|
|
6596
6596
|
_comment: "Managed by har telemetry \u2014 do not edit by hand; use: har telemetry on|off",
|
|
6597
6597
|
...config2
|
|
6598
6598
|
};
|
|
6599
|
-
|
|
6599
|
+
fs40.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
|
|
6600
6600
|
`);
|
|
6601
6601
|
return configPath;
|
|
6602
6602
|
}
|
|
6603
6603
|
function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
|
|
6604
|
-
|
|
6604
|
+
fs40.mkdirSync(hooksHome, { recursive: true });
|
|
6605
6605
|
const wrapperPath = getOtelHooksWrapperPath(hooksHome);
|
|
6606
6606
|
const script = `#!/usr/bin/env bash
|
|
6607
6607
|
# Managed by har telemetry \u2014 invokes opentelemetry-hooks with HAR config home.
|
|
@@ -6609,9 +6609,9 @@ set -euo pipefail
|
|
|
6609
6609
|
export IDE_OTEL_HOOK_HOME="${hooksHome}"
|
|
6610
6610
|
exec "${otelHookCommand}" "$@"
|
|
6611
6611
|
`;
|
|
6612
|
-
|
|
6612
|
+
fs40.writeFileSync(wrapperPath, script, { mode: 493 });
|
|
6613
6613
|
try {
|
|
6614
|
-
|
|
6614
|
+
fs40.chmodSync(wrapperPath, 493);
|
|
6615
6615
|
} catch {
|
|
6616
6616
|
}
|
|
6617
6617
|
return wrapperPath;
|
|
@@ -6691,10 +6691,10 @@ function runSetupAgent(agent, otelHookCommand, hooksHome) {
|
|
|
6691
6691
|
};
|
|
6692
6692
|
}
|
|
6693
6693
|
function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
|
|
6694
|
-
if (!
|
|
6694
|
+
if (!fs40.existsSync(filePath)) return false;
|
|
6695
6695
|
let raw;
|
|
6696
6696
|
try {
|
|
6697
|
-
raw =
|
|
6697
|
+
raw = fs40.readFileSync(filePath, "utf8");
|
|
6698
6698
|
} catch {
|
|
6699
6699
|
return false;
|
|
6700
6700
|
}
|
|
@@ -6733,16 +6733,16 @@ function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
|
|
|
6733
6733
|
return changed;
|
|
6734
6734
|
};
|
|
6735
6735
|
if (!walk(parsed)) return false;
|
|
6736
|
-
|
|
6736
|
+
fs40.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
6737
6737
|
`);
|
|
6738
6738
|
return true;
|
|
6739
6739
|
}
|
|
6740
6740
|
function rewriteKnownHookRegistrations(wrapperPath) {
|
|
6741
6741
|
const home = os12.homedir();
|
|
6742
6742
|
const candidates = [
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6743
|
+
path42.join(home, ".cursor", "hooks.json"),
|
|
6744
|
+
path42.join(home, ".claude", "settings.json"),
|
|
6745
|
+
path42.join(home, ".codex", "hooks.json")
|
|
6746
6746
|
];
|
|
6747
6747
|
for (const filePath of candidates) {
|
|
6748
6748
|
try {
|
|
@@ -6755,7 +6755,7 @@ function ensureOtelHooks(options) {
|
|
|
6755
6755
|
const hooksHome = getOtelHooksHome();
|
|
6756
6756
|
const errors = [];
|
|
6757
6757
|
const agentsSetup = [];
|
|
6758
|
-
|
|
6758
|
+
fs40.mkdirSync(hooksHome, { recursive: true });
|
|
6759
6759
|
let otelHookCommand = resolveOtelHookCommand();
|
|
6760
6760
|
if (!otelHookCommand) {
|
|
6761
6761
|
const installed = tryInstallPackage();
|
|
@@ -6824,14 +6824,14 @@ function ensureOtelHooks(options) {
|
|
|
6824
6824
|
function disableOtelHooksExport() {
|
|
6825
6825
|
return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
|
|
6826
6826
|
}
|
|
6827
|
-
var import_child_process9,
|
|
6827
|
+
var import_child_process9, fs40, os12, path42, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
|
|
6828
6828
|
var init_otel_hooks = __esm({
|
|
6829
6829
|
"src/core/otel-hooks.ts"() {
|
|
6830
6830
|
"use strict";
|
|
6831
6831
|
import_child_process9 = require("child_process");
|
|
6832
|
-
|
|
6832
|
+
fs40 = __toESM(require("fs"));
|
|
6833
6833
|
os12 = __toESM(require("os"));
|
|
6834
|
-
|
|
6834
|
+
path42 = __toESM(require("path"));
|
|
6835
6835
|
init_control_config();
|
|
6836
6836
|
init_telemetry_config();
|
|
6837
6837
|
OTEL_HOOKS_PACKAGE = "opentelemetry-hooks==0.14.0";
|
|
@@ -10035,8 +10035,8 @@ var require_utils2 = __commonJS({
|
|
|
10035
10035
|
}
|
|
10036
10036
|
return ind;
|
|
10037
10037
|
}
|
|
10038
|
-
function removeDotSegments(
|
|
10039
|
-
let input =
|
|
10038
|
+
function removeDotSegments(path53) {
|
|
10039
|
+
let input = path53;
|
|
10040
10040
|
const output = [];
|
|
10041
10041
|
let nextSlash = -1;
|
|
10042
10042
|
let len = 0;
|
|
@@ -10288,8 +10288,8 @@ var require_schemes = __commonJS({
|
|
|
10288
10288
|
wsComponent.secure = void 0;
|
|
10289
10289
|
}
|
|
10290
10290
|
if (wsComponent.resourceName) {
|
|
10291
|
-
const [
|
|
10292
|
-
wsComponent.path =
|
|
10291
|
+
const [path53, query] = wsComponent.resourceName.split("?");
|
|
10292
|
+
wsComponent.path = path53 && path53 !== "/" ? path53 : void 0;
|
|
10293
10293
|
wsComponent.query = query;
|
|
10294
10294
|
wsComponent.resourceName = void 0;
|
|
10295
10295
|
}
|
|
@@ -13682,12 +13682,12 @@ var require_dist = __commonJS({
|
|
|
13682
13682
|
throw new Error(`Unknown format "${name}"`);
|
|
13683
13683
|
return f2;
|
|
13684
13684
|
};
|
|
13685
|
-
function addFormats(ajv, list,
|
|
13685
|
+
function addFormats(ajv, list, fs45, exportName) {
|
|
13686
13686
|
var _a3;
|
|
13687
13687
|
var _b2;
|
|
13688
13688
|
(_a3 = (_b2 = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
13689
13689
|
for (const f2 of list)
|
|
13690
|
-
ajv.addFormat(f2,
|
|
13690
|
+
ajv.addFormat(f2, fs45[f2]);
|
|
13691
13691
|
}
|
|
13692
13692
|
module2.exports = exports2 = formatsPlugin;
|
|
13693
13693
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -14787,15 +14787,15 @@ var require_route = __commonJS({
|
|
|
14787
14787
|
};
|
|
14788
14788
|
}
|
|
14789
14789
|
function wrapConversion(toModel, graph) {
|
|
14790
|
-
const
|
|
14790
|
+
const path53 = [graph[toModel].parent, toModel];
|
|
14791
14791
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
14792
14792
|
let cur = graph[toModel].parent;
|
|
14793
14793
|
while (graph[cur].parent) {
|
|
14794
|
-
|
|
14794
|
+
path53.unshift(graph[cur].parent);
|
|
14795
14795
|
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
14796
14796
|
cur = graph[cur].parent;
|
|
14797
14797
|
}
|
|
14798
|
-
fn.conversion =
|
|
14798
|
+
fn.conversion = path53;
|
|
14799
14799
|
return fn;
|
|
14800
14800
|
}
|
|
14801
14801
|
module2.exports = function(fromModel) {
|
|
@@ -20725,7 +20725,7 @@ var require_iso2022 = __commonJS({
|
|
|
20725
20725
|
// node_modules/chardet/index.js
|
|
20726
20726
|
var require_chardet = __commonJS({
|
|
20727
20727
|
"node_modules/chardet/index.js"(exports2, module2) {
|
|
20728
|
-
var
|
|
20728
|
+
var fs45 = require("fs");
|
|
20729
20729
|
var utf8 = require_utf8();
|
|
20730
20730
|
var unicode = require_unicode();
|
|
20731
20731
|
var mbcs = require_mbcs();
|
|
@@ -20799,28 +20799,28 @@ var require_chardet = __commonJS({
|
|
|
20799
20799
|
var fd;
|
|
20800
20800
|
var handler = function(err, buffer) {
|
|
20801
20801
|
if (fd) {
|
|
20802
|
-
|
|
20802
|
+
fs45.closeSync(fd);
|
|
20803
20803
|
}
|
|
20804
20804
|
if (err) return cb(err, null);
|
|
20805
20805
|
cb(null, self.detect(buffer, opts));
|
|
20806
20806
|
};
|
|
20807
20807
|
if (opts && opts.sampleSize) {
|
|
20808
|
-
fd =
|
|
20809
|
-
|
|
20808
|
+
fd = fs45.openSync(filepath, "r"), sample = Buffer.allocUnsafe(opts.sampleSize);
|
|
20809
|
+
fs45.read(fd, sample, 0, opts.sampleSize, null, function(err) {
|
|
20810
20810
|
handler(err, sample);
|
|
20811
20811
|
});
|
|
20812
20812
|
return;
|
|
20813
20813
|
}
|
|
20814
|
-
|
|
20814
|
+
fs45.readFile(filepath, handler);
|
|
20815
20815
|
};
|
|
20816
20816
|
module2.exports.detectFileSync = function(filepath, opts) {
|
|
20817
20817
|
if (opts && opts.sampleSize) {
|
|
20818
|
-
var fd =
|
|
20819
|
-
|
|
20820
|
-
|
|
20818
|
+
var fd = fs45.openSync(filepath, "r"), sample2 = Buffer.allocUnsafe(opts.sampleSize);
|
|
20819
|
+
fs45.readSync(fd, sample2, 0, opts.sampleSize);
|
|
20820
|
+
fs45.closeSync(fd);
|
|
20821
20821
|
return self.detect(sample2, opts);
|
|
20822
20822
|
}
|
|
20823
|
-
return self.detect(
|
|
20823
|
+
return self.detect(fs45.readFileSync(filepath), opts);
|
|
20824
20824
|
};
|
|
20825
20825
|
module2.exports.detectAll = function(buffer, opts) {
|
|
20826
20826
|
if (typeof opts !== "object") {
|
|
@@ -24285,16 +24285,16 @@ var require_os_tmpdir = __commonJS({
|
|
|
24285
24285
|
var isWindows = process.platform === "win32";
|
|
24286
24286
|
var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
|
|
24287
24287
|
module2.exports = function() {
|
|
24288
|
-
var
|
|
24288
|
+
var path53;
|
|
24289
24289
|
if (isWindows) {
|
|
24290
|
-
|
|
24290
|
+
path53 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
|
|
24291
24291
|
} else {
|
|
24292
|
-
|
|
24292
|
+
path53 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
|
|
24293
24293
|
}
|
|
24294
|
-
if (trailingSlashRe.test(
|
|
24295
|
-
|
|
24294
|
+
if (trailingSlashRe.test(path53)) {
|
|
24295
|
+
path53 = path53.slice(0, -1);
|
|
24296
24296
|
}
|
|
24297
|
-
return
|
|
24297
|
+
return path53;
|
|
24298
24298
|
};
|
|
24299
24299
|
}
|
|
24300
24300
|
});
|
|
@@ -24302,9 +24302,9 @@ var require_os_tmpdir = __commonJS({
|
|
|
24302
24302
|
// node_modules/tmp/lib/tmp.js
|
|
24303
24303
|
var require_tmp = __commonJS({
|
|
24304
24304
|
"node_modules/tmp/lib/tmp.js"(exports2, module2) {
|
|
24305
|
-
var
|
|
24306
|
-
var
|
|
24307
|
-
var
|
|
24305
|
+
var fs45 = require("fs");
|
|
24306
|
+
var path53 = require("path");
|
|
24307
|
+
var crypto6 = require("crypto");
|
|
24308
24308
|
var osTmpDir = require_os_tmpdir();
|
|
24309
24309
|
var _c2 = process.binding("constants");
|
|
24310
24310
|
var tmpDir = osTmpDir();
|
|
@@ -24322,9 +24322,9 @@ var require_tmp = __commonJS({
|
|
|
24322
24322
|
function _randomChars(howMany) {
|
|
24323
24323
|
var value = [], rnd = null;
|
|
24324
24324
|
try {
|
|
24325
|
-
rnd =
|
|
24325
|
+
rnd = crypto6.randomBytes(howMany);
|
|
24326
24326
|
} catch (e2) {
|
|
24327
|
-
rnd =
|
|
24327
|
+
rnd = crypto6.pseudoRandomBytes(howMany);
|
|
24328
24328
|
}
|
|
24329
24329
|
for (var i2 = 0; i2 < howMany; i2++) {
|
|
24330
24330
|
value.push(RANDOM_CHARS[rnd[i2] % RANDOM_CHARS.length]);
|
|
@@ -24345,7 +24345,7 @@ var require_tmp = __commonJS({
|
|
|
24345
24345
|
}
|
|
24346
24346
|
function _generateTmpName(opts) {
|
|
24347
24347
|
if (opts.name) {
|
|
24348
|
-
return
|
|
24348
|
+
return path53.join(opts.dir || tmpDir, opts.name);
|
|
24349
24349
|
}
|
|
24350
24350
|
if (opts.template) {
|
|
24351
24351
|
return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
|
|
@@ -24356,7 +24356,7 @@ var require_tmp = __commonJS({
|
|
|
24356
24356
|
_randomChars(12),
|
|
24357
24357
|
opts.postfix || ""
|
|
24358
24358
|
].join("");
|
|
24359
|
-
return
|
|
24359
|
+
return path53.join(opts.dir || tmpDir, name);
|
|
24360
24360
|
}
|
|
24361
24361
|
function tmpName(options, callback) {
|
|
24362
24362
|
var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
|
|
@@ -24366,7 +24366,7 @@ var require_tmp = __commonJS({
|
|
|
24366
24366
|
return cb(new Error("Invalid template provided"));
|
|
24367
24367
|
(function _getUniqueName() {
|
|
24368
24368
|
const name = _generateTmpName(opts);
|
|
24369
|
-
|
|
24369
|
+
fs45.stat(name, function(err) {
|
|
24370
24370
|
if (!err) {
|
|
24371
24371
|
if (tries-- > 0) return _getUniqueName();
|
|
24372
24372
|
return cb(new Error("Could not get a unique tmp filename, max tries reached " + name));
|
|
@@ -24384,7 +24384,7 @@ var require_tmp = __commonJS({
|
|
|
24384
24384
|
do {
|
|
24385
24385
|
const name = _generateTmpName(opts);
|
|
24386
24386
|
try {
|
|
24387
|
-
|
|
24387
|
+
fs45.statSync(name);
|
|
24388
24388
|
} catch (e2) {
|
|
24389
24389
|
return name;
|
|
24390
24390
|
}
|
|
@@ -24396,13 +24396,13 @@ var require_tmp = __commonJS({
|
|
|
24396
24396
|
opts.postfix = _isUndefined(opts.postfix) ? ".tmp" : opts.postfix;
|
|
24397
24397
|
tmpName(opts, function _tmpNameCreated(err, name) {
|
|
24398
24398
|
if (err) return cb(err);
|
|
24399
|
-
|
|
24399
|
+
fs45.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err2, fd) {
|
|
24400
24400
|
if (err2) return cb(err2);
|
|
24401
24401
|
if (opts.discardDescriptor) {
|
|
24402
|
-
return
|
|
24402
|
+
return fs45.close(fd, function _discardCallback(err3) {
|
|
24403
24403
|
if (err3) {
|
|
24404
24404
|
try {
|
|
24405
|
-
|
|
24405
|
+
fs45.unlinkSync(name);
|
|
24406
24406
|
} catch (e2) {
|
|
24407
24407
|
if (!isENOENT(e2)) {
|
|
24408
24408
|
err3 = e2;
|
|
@@ -24425,9 +24425,9 @@ var require_tmp = __commonJS({
|
|
|
24425
24425
|
opts.postfix = opts.postfix || ".tmp";
|
|
24426
24426
|
const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
|
|
24427
24427
|
const name = tmpNameSync(opts);
|
|
24428
|
-
var fd =
|
|
24428
|
+
var fd = fs45.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
|
|
24429
24429
|
if (opts.discardDescriptor) {
|
|
24430
|
-
|
|
24430
|
+
fs45.closeSync(fd);
|
|
24431
24431
|
fd = void 0;
|
|
24432
24432
|
}
|
|
24433
24433
|
return {
|
|
@@ -24439,9 +24439,9 @@ var require_tmp = __commonJS({
|
|
|
24439
24439
|
function _rmdirRecursiveSync(root) {
|
|
24440
24440
|
const dirs = [root];
|
|
24441
24441
|
do {
|
|
24442
|
-
var dir2 = dirs.pop(), deferred = false, files =
|
|
24442
|
+
var dir2 = dirs.pop(), deferred = false, files = fs45.readdirSync(dir2);
|
|
24443
24443
|
for (var i2 = 0, length = files.length; i2 < length; i2++) {
|
|
24444
|
-
var file2 =
|
|
24444
|
+
var file2 = path53.join(dir2, files[i2]), stat = fs45.lstatSync(file2);
|
|
24445
24445
|
if (stat.isDirectory()) {
|
|
24446
24446
|
if (!deferred) {
|
|
24447
24447
|
deferred = true;
|
|
@@ -24449,11 +24449,11 @@ var require_tmp = __commonJS({
|
|
|
24449
24449
|
}
|
|
24450
24450
|
dirs.push(file2);
|
|
24451
24451
|
} else {
|
|
24452
|
-
|
|
24452
|
+
fs45.unlinkSync(file2);
|
|
24453
24453
|
}
|
|
24454
24454
|
}
|
|
24455
24455
|
if (!deferred) {
|
|
24456
|
-
|
|
24456
|
+
fs45.rmdirSync(dir2);
|
|
24457
24457
|
}
|
|
24458
24458
|
} while (dirs.length !== 0);
|
|
24459
24459
|
}
|
|
@@ -24461,7 +24461,7 @@ var require_tmp = __commonJS({
|
|
|
24461
24461
|
var args = _parseArguments(options, callback), opts = args[0], cb = args[1];
|
|
24462
24462
|
tmpName(opts, function _tmpNameCreated(err, name) {
|
|
24463
24463
|
if (err) return cb(err);
|
|
24464
|
-
|
|
24464
|
+
fs45.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err2) {
|
|
24465
24465
|
if (err2) return cb(err2);
|
|
24466
24466
|
cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
|
|
24467
24467
|
});
|
|
@@ -24470,7 +24470,7 @@ var require_tmp = __commonJS({
|
|
|
24470
24470
|
function dirSync(options) {
|
|
24471
24471
|
var args = _parseArguments(options), opts = args[0];
|
|
24472
24472
|
const name = tmpNameSync(opts);
|
|
24473
|
-
|
|
24473
|
+
fs45.mkdirSync(name, opts.mode || DIR_MODE);
|
|
24474
24474
|
return {
|
|
24475
24475
|
name,
|
|
24476
24476
|
removeCallback: _prepareTmpDirRemoveCallback(name, opts)
|
|
@@ -24480,7 +24480,7 @@ var require_tmp = __commonJS({
|
|
|
24480
24480
|
const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
|
|
24481
24481
|
try {
|
|
24482
24482
|
if (0 <= fdPath[0]) {
|
|
24483
|
-
|
|
24483
|
+
fs45.closeSync(fdPath[0]);
|
|
24484
24484
|
}
|
|
24485
24485
|
} catch (e2) {
|
|
24486
24486
|
if (!isEBADF(e2) && !isENOENT(e2)) {
|
|
@@ -24488,7 +24488,7 @@ var require_tmp = __commonJS({
|
|
|
24488
24488
|
}
|
|
24489
24489
|
}
|
|
24490
24490
|
try {
|
|
24491
|
-
|
|
24491
|
+
fs45.unlinkSync(fdPath[1]);
|
|
24492
24492
|
} catch (e2) {
|
|
24493
24493
|
if (!isENOENT(e2)) {
|
|
24494
24494
|
throw e2;
|
|
@@ -24501,7 +24501,7 @@ var require_tmp = __commonJS({
|
|
|
24501
24501
|
return removeCallback;
|
|
24502
24502
|
}
|
|
24503
24503
|
function _prepareTmpDirRemoveCallback(name, opts) {
|
|
24504
|
-
const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync :
|
|
24504
|
+
const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs45.rmdirSync.bind(fs45);
|
|
24505
24505
|
const removeCallback = _prepareRemoveCallback(removeFunction, name);
|
|
24506
24506
|
if (!opts.keep) {
|
|
24507
24507
|
_removeObjects.unshift(removeCallback);
|
|
@@ -35714,11 +35714,11 @@ var parser = new YargsParser({
|
|
|
35714
35714
|
resolve: import_path2.resolve,
|
|
35715
35715
|
// TODO: figure out a way to combine ESM and CJS coverage, such that
|
|
35716
35716
|
// we can exercise all the lines below:
|
|
35717
|
-
require: (
|
|
35717
|
+
require: (path53) => {
|
|
35718
35718
|
if (typeof require !== "undefined") {
|
|
35719
|
-
return require(
|
|
35720
|
-
} else if (
|
|
35721
|
-
return JSON.parse((0, import_fs2.readFileSync)(
|
|
35719
|
+
return require(path53);
|
|
35720
|
+
} else if (path53.match(/\.json$/)) {
|
|
35721
|
+
return JSON.parse((0, import_fs2.readFileSync)(path53, "utf8"));
|
|
35722
35722
|
} else {
|
|
35723
35723
|
throw Error("only .json config files are supported in ESM");
|
|
35724
35724
|
}
|
|
@@ -40399,8 +40399,8 @@ function getErrorMap() {
|
|
|
40399
40399
|
|
|
40400
40400
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
40401
40401
|
var makeIssue = (params) => {
|
|
40402
|
-
const { data, path:
|
|
40403
|
-
const fullPath = [...
|
|
40402
|
+
const { data, path: path53, errorMaps, issueData } = params;
|
|
40403
|
+
const fullPath = [...path53, ...issueData.path || []];
|
|
40404
40404
|
const fullIssue = {
|
|
40405
40405
|
...issueData,
|
|
40406
40406
|
path: fullPath
|
|
@@ -40516,11 +40516,11 @@ var errorUtil;
|
|
|
40516
40516
|
|
|
40517
40517
|
// node_modules/zod/v3/types.js
|
|
40518
40518
|
var ParseInputLazyPath = class {
|
|
40519
|
-
constructor(parent, value,
|
|
40519
|
+
constructor(parent, value, path53, key) {
|
|
40520
40520
|
this._cachedPath = [];
|
|
40521
40521
|
this.parent = parent;
|
|
40522
40522
|
this.data = value;
|
|
40523
|
-
this._path =
|
|
40523
|
+
this._path = path53;
|
|
40524
40524
|
this._key = key;
|
|
40525
40525
|
}
|
|
40526
40526
|
get path() {
|
|
@@ -44117,6 +44117,51 @@ var StageKindSchema = HarnessStageKindSchema;
|
|
|
44117
44117
|
var VerificationResultSchema = HarnessVerificationResultSchema;
|
|
44118
44118
|
var StageResultSchema = HarnessStageRunResultSchema;
|
|
44119
44119
|
var RunRecordTriggerSchema = external_exports.enum(["cli", "mcp", "script"]);
|
|
44120
|
+
var WorkUnitIdSchema = external_exports.string().min(1).max(128).regex(
|
|
44121
|
+
/^[A-Za-z0-9][A-Za-z0-9._:/#@-]*$/,
|
|
44122
|
+
"work unit id must start with an alphanumeric character and contain only stable identifier characters"
|
|
44123
|
+
);
|
|
44124
|
+
var WorkAttemptIdSchema = external_exports.string().uuid();
|
|
44125
|
+
var WorkUnitMetadataSchema = external_exports.object({
|
|
44126
|
+
workUnitId: WorkUnitIdSchema,
|
|
44127
|
+
source: external_exports.string().min(1).max(64).optional(),
|
|
44128
|
+
sourceUrl: external_exports.string().url().optional(),
|
|
44129
|
+
title: external_exports.string().min(1).max(256).optional(),
|
|
44130
|
+
parentWorkUnitId: WorkUnitIdSchema.optional()
|
|
44131
|
+
});
|
|
44132
|
+
var WorkUnitOutcomeSchema = external_exports.object({
|
|
44133
|
+
decision: external_exports.enum(["completed", "abandoned"]),
|
|
44134
|
+
decidedAt: external_exports.string(),
|
|
44135
|
+
attemptId: WorkAttemptIdSchema.optional(),
|
|
44136
|
+
validationId: external_exports.string().uuid().optional(),
|
|
44137
|
+
treeHash: external_exports.string().regex(/^[0-9a-f]{40,64}$/).optional(),
|
|
44138
|
+
reason: external_exports.string().max(2e3).optional()
|
|
44139
|
+
}).superRefine((outcome, ctx) => {
|
|
44140
|
+
if (outcome.decision === "completed" && (!outcome.attemptId || !outcome.validationId || !outcome.treeHash)) {
|
|
44141
|
+
ctx.addIssue({
|
|
44142
|
+
code: external_exports.ZodIssueCode.custom,
|
|
44143
|
+
message: "completed work must reference an attempt and exact-tree validation"
|
|
44144
|
+
});
|
|
44145
|
+
}
|
|
44146
|
+
});
|
|
44147
|
+
var WorkUnitRecordSchema = WorkUnitMetadataSchema.extend({
|
|
44148
|
+
version: external_exports.number().int().default(1),
|
|
44149
|
+
createdAt: external_exports.string(),
|
|
44150
|
+
updatedAt: external_exports.string(),
|
|
44151
|
+
outcome: WorkUnitOutcomeSchema.optional()
|
|
44152
|
+
}).passthrough();
|
|
44153
|
+
var WorkAttemptRecordSchema = external_exports.object({
|
|
44154
|
+
version: external_exports.number().int().default(1),
|
|
44155
|
+
attemptId: WorkAttemptIdSchema,
|
|
44156
|
+
workUnitId: WorkUnitIdSchema,
|
|
44157
|
+
agentId: external_exports.number().int().min(HAR_AGENT_SLOT_MIN),
|
|
44158
|
+
sessionKey: external_exports.string().min(1).optional(),
|
|
44159
|
+
workDir: external_exports.string().optional(),
|
|
44160
|
+
worktreePath: external_exports.string().optional(),
|
|
44161
|
+
branch: external_exports.string().optional(),
|
|
44162
|
+
baseCommit: external_exports.string().optional(),
|
|
44163
|
+
createdAt: external_exports.string()
|
|
44164
|
+
}).passthrough();
|
|
44120
44165
|
var RunRecordSchema = external_exports.object({
|
|
44121
44166
|
runId: external_exports.string().uuid(),
|
|
44122
44167
|
repoPath: external_exports.string(),
|
|
@@ -44132,7 +44177,9 @@ var RunRecordSchema = external_exports.object({
|
|
|
44132
44177
|
relativePath: external_exports.string().optional(),
|
|
44133
44178
|
command: external_exports.string().optional(),
|
|
44134
44179
|
workDir: external_exports.string().optional(),
|
|
44135
|
-
harnessRoot: external_exports.string().optional()
|
|
44180
|
+
harnessRoot: external_exports.string().optional(),
|
|
44181
|
+
workUnitId: WorkUnitIdSchema.optional(),
|
|
44182
|
+
attemptId: WorkAttemptIdSchema.optional()
|
|
44136
44183
|
}).passthrough();
|
|
44137
44184
|
var SlotRegistryEntrySchema = external_exports.object({
|
|
44138
44185
|
version: external_exports.number().int().default(1),
|
|
@@ -44154,6 +44201,8 @@ var SlotRegistryEntrySchema = external_exports.object({
|
|
|
44154
44201
|
createdAt: external_exports.string(),
|
|
44155
44202
|
ports: external_exports.record(external_exports.number()).optional(),
|
|
44156
44203
|
previewUrls: external_exports.record(external_exports.string()).optional(),
|
|
44204
|
+
workUnitId: WorkUnitIdSchema.optional(),
|
|
44205
|
+
attemptId: WorkAttemptIdSchema.optional(),
|
|
44157
44206
|
status: external_exports.enum(["starting", "active", "failed", "completed"]).default("active"),
|
|
44158
44207
|
lastError: external_exports.string().optional()
|
|
44159
44208
|
}).passthrough();
|
|
@@ -44199,6 +44248,8 @@ var AgentSlotStatusSchema = external_exports.object({
|
|
|
44199
44248
|
sessionCreatedAt: external_exports.string().optional(),
|
|
44200
44249
|
/** Derived from first captured user prompt (OTEL hooks); not set at launch. */
|
|
44201
44250
|
purpose: external_exports.string().optional(),
|
|
44251
|
+
workUnitId: WorkUnitIdSchema.optional(),
|
|
44252
|
+
attemptId: WorkAttemptIdSchema.optional(),
|
|
44202
44253
|
sessionStatus: external_exports.enum(["starting", "active", "failed", "completed"]).optional(),
|
|
44203
44254
|
lastError: external_exports.string().optional(),
|
|
44204
44255
|
/** Set when a failed/starting session can be resumed without --replace. */
|
|
@@ -44259,6 +44310,10 @@ var SyncSlotsInputSchema = external_exports.object({
|
|
|
44259
44310
|
slots: external_exports.array(AgentSlotStatusSchema),
|
|
44260
44311
|
generatedAt: external_exports.string()
|
|
44261
44312
|
});
|
|
44313
|
+
var SyncWorkUnitsInputSchema = external_exports.object({
|
|
44314
|
+
workUnits: external_exports.array(WorkUnitRecordSchema),
|
|
44315
|
+
attempts: external_exports.array(WorkAttemptRecordSchema)
|
|
44316
|
+
});
|
|
44262
44317
|
var ChangedFileStatusSchema = external_exports.enum(["A", "M", "D", "R", "C", "T", "U"]);
|
|
44263
44318
|
var ChangedFileSchema = external_exports.object({
|
|
44264
44319
|
path: external_exports.string(),
|
|
@@ -44285,6 +44340,17 @@ var ValidationRecordSchema = external_exports.object({
|
|
|
44285
44340
|
var SyncValidationsInputSchema = external_exports.object({
|
|
44286
44341
|
validations: external_exports.array(ValidationRecordSchema)
|
|
44287
44342
|
});
|
|
44343
|
+
var ValidationBindingRecordSchema = external_exports.object({
|
|
44344
|
+
bindingId: external_exports.string().uuid(),
|
|
44345
|
+
workUnitId: WorkUnitIdSchema,
|
|
44346
|
+
attemptId: WorkAttemptIdSchema,
|
|
44347
|
+
validationId: external_exports.string().uuid(),
|
|
44348
|
+
treeHash: external_exports.string().regex(/^[0-9a-f]{40,64}$/),
|
|
44349
|
+
createdAt: external_exports.string()
|
|
44350
|
+
});
|
|
44351
|
+
var SyncValidationBindingsInputSchema = external_exports.object({
|
|
44352
|
+
bindings: external_exports.array(ValidationBindingRecordSchema)
|
|
44353
|
+
});
|
|
44288
44354
|
var AgentToolSchema = external_exports.enum(["claude_code", "codex", "cursor"]);
|
|
44289
44355
|
var UsageSourceSchema = external_exports.enum(["otel", "harvest"]);
|
|
44290
44356
|
var AgentSessionUsageSchema = external_exports.object({
|
|
@@ -44294,6 +44360,8 @@ var AgentSessionUsageSchema = external_exports.object({
|
|
|
44294
44360
|
workDir: external_exports.string().optional(),
|
|
44295
44361
|
branch: external_exports.string().optional(),
|
|
44296
44362
|
suffix: external_exports.string().optional(),
|
|
44363
|
+
workUnitId: WorkUnitIdSchema.optional(),
|
|
44364
|
+
attemptId: WorkAttemptIdSchema.optional(),
|
|
44297
44365
|
tokensInput: external_exports.number().nonnegative().default(0),
|
|
44298
44366
|
tokensOutput: external_exports.number().nonnegative().default(0),
|
|
44299
44367
|
tokensCacheRead: external_exports.number().nonnegative().default(0),
|
|
@@ -44315,6 +44383,8 @@ var AgentSessionEventSchema = external_exports.object({
|
|
|
44315
44383
|
eventName: external_exports.string().min(1),
|
|
44316
44384
|
sequence: external_exports.number().int().nonnegative().default(0),
|
|
44317
44385
|
timestamp: external_exports.string(),
|
|
44386
|
+
workUnitId: WorkUnitIdSchema.optional(),
|
|
44387
|
+
attemptId: WorkAttemptIdSchema.optional(),
|
|
44318
44388
|
attributes: external_exports.record(external_exports.unknown()).optional(),
|
|
44319
44389
|
promptText: external_exports.string().nullable().optional(),
|
|
44320
44390
|
responseText: external_exports.string().nullable().optional(),
|
|
@@ -44677,7 +44747,7 @@ function handleRemove(argv) {
|
|
|
44677
44747
|
}
|
|
44678
44748
|
|
|
44679
44749
|
// src/cli/commands/env.ts
|
|
44680
|
-
var
|
|
44750
|
+
var path46 = __toESM(require("path"));
|
|
44681
44751
|
|
|
44682
44752
|
// src/core/harness.ts
|
|
44683
44753
|
var fs20 = __toESM(require("fs"));
|
|
@@ -45456,13 +45526,13 @@ var MultipartBody = class {
|
|
|
45456
45526
|
// node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
|
|
45457
45527
|
var import_web = require("node:stream/web");
|
|
45458
45528
|
var fileFromPathWarned = false;
|
|
45459
|
-
async function fileFromPath3(
|
|
45529
|
+
async function fileFromPath3(path53, ...args) {
|
|
45460
45530
|
const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
|
|
45461
45531
|
if (!fileFromPathWarned) {
|
|
45462
|
-
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(
|
|
45532
|
+
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path53)}) instead`);
|
|
45463
45533
|
fileFromPathWarned = true;
|
|
45464
45534
|
}
|
|
45465
|
-
return await _fileFromPath(
|
|
45535
|
+
return await _fileFromPath(path53, ...args);
|
|
45466
45536
|
}
|
|
45467
45537
|
var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
45468
45538
|
var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
@@ -46059,29 +46129,29 @@ var APIClient = class {
|
|
|
46059
46129
|
defaultIdempotencyKey() {
|
|
46060
46130
|
return `stainless-node-retry-${uuid4()}`;
|
|
46061
46131
|
}
|
|
46062
|
-
get(
|
|
46063
|
-
return this.methodRequest("get",
|
|
46132
|
+
get(path53, opts) {
|
|
46133
|
+
return this.methodRequest("get", path53, opts);
|
|
46064
46134
|
}
|
|
46065
|
-
post(
|
|
46066
|
-
return this.methodRequest("post",
|
|
46135
|
+
post(path53, opts) {
|
|
46136
|
+
return this.methodRequest("post", path53, opts);
|
|
46067
46137
|
}
|
|
46068
|
-
patch(
|
|
46069
|
-
return this.methodRequest("patch",
|
|
46138
|
+
patch(path53, opts) {
|
|
46139
|
+
return this.methodRequest("patch", path53, opts);
|
|
46070
46140
|
}
|
|
46071
|
-
put(
|
|
46072
|
-
return this.methodRequest("put",
|
|
46141
|
+
put(path53, opts) {
|
|
46142
|
+
return this.methodRequest("put", path53, opts);
|
|
46073
46143
|
}
|
|
46074
|
-
delete(
|
|
46075
|
-
return this.methodRequest("delete",
|
|
46144
|
+
delete(path53, opts) {
|
|
46145
|
+
return this.methodRequest("delete", path53, opts);
|
|
46076
46146
|
}
|
|
46077
|
-
methodRequest(method,
|
|
46147
|
+
methodRequest(method, path53, opts) {
|
|
46078
46148
|
return this.request(Promise.resolve(opts).then(async (opts2) => {
|
|
46079
46149
|
const body = opts2 && isBlobLike(opts2?.body) ? new DataView(await opts2.body.arrayBuffer()) : opts2?.body instanceof DataView ? opts2.body : opts2?.body instanceof ArrayBuffer ? new DataView(opts2.body) : opts2 && ArrayBuffer.isView(opts2?.body) ? new DataView(opts2.body.buffer) : opts2?.body;
|
|
46080
|
-
return { method, path:
|
|
46150
|
+
return { method, path: path53, ...opts2, body };
|
|
46081
46151
|
}));
|
|
46082
46152
|
}
|
|
46083
|
-
getAPIList(
|
|
46084
|
-
return this.requestAPIList(Page, { method: "get", path:
|
|
46153
|
+
getAPIList(path53, Page, opts) {
|
|
46154
|
+
return this.requestAPIList(Page, { method: "get", path: path53, ...opts });
|
|
46085
46155
|
}
|
|
46086
46156
|
calculateContentLength(body) {
|
|
46087
46157
|
if (typeof body === "string") {
|
|
@@ -46099,10 +46169,10 @@ var APIClient = class {
|
|
|
46099
46169
|
return null;
|
|
46100
46170
|
}
|
|
46101
46171
|
buildRequest(options) {
|
|
46102
|
-
const { method, path:
|
|
46172
|
+
const { method, path: path53, query, headers = {} } = options;
|
|
46103
46173
|
const body = ArrayBuffer.isView(options.body) || options.__binaryRequest && typeof options.body === "string" ? options.body : isMultipartBody(options.body) ? options.body.body : options.body ? JSON.stringify(options.body, null, 2) : null;
|
|
46104
46174
|
const contentLength = this.calculateContentLength(body);
|
|
46105
|
-
const url = this.buildURL(
|
|
46175
|
+
const url = this.buildURL(path53, query);
|
|
46106
46176
|
if ("timeout" in options)
|
|
46107
46177
|
validatePositiveInteger("timeout", options.timeout);
|
|
46108
46178
|
const timeout = options.timeout ?? this.timeout;
|
|
@@ -46211,8 +46281,8 @@ var APIClient = class {
|
|
|
46211
46281
|
const request = this.makeRequest(options, null);
|
|
46212
46282
|
return new PagePromise(this, request, Page);
|
|
46213
46283
|
}
|
|
46214
|
-
buildURL(
|
|
46215
|
-
const url = isAbsoluteURL(
|
|
46284
|
+
buildURL(path53, query) {
|
|
46285
|
+
const url = isAbsoluteURL(path53) ? new URL(path53) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path53.startsWith("/") ? path53.slice(1) : path53));
|
|
46216
46286
|
const defaultQuery = this.defaultQuery();
|
|
46217
46287
|
if (!isEmptyObj(defaultQuery)) {
|
|
46218
46288
|
query = { ...defaultQuery, ...query };
|
|
@@ -49802,6 +49872,9 @@ function buildStageResult(input) {
|
|
|
49802
49872
|
});
|
|
49803
49873
|
}
|
|
49804
49874
|
|
|
49875
|
+
// src/core/run-service.ts
|
|
49876
|
+
var crypto5 = __toESM(require("crypto"));
|
|
49877
|
+
|
|
49805
49878
|
// src/core/local-executor.ts
|
|
49806
49879
|
var fs25 = __toESM(require("fs"));
|
|
49807
49880
|
var path24 = __toESM(require("path"));
|
|
@@ -49854,6 +49927,8 @@ function buildLaunchFlagArgs(flags) {
|
|
|
49854
49927
|
if (flags.confirmReplace) args.push("--replace");
|
|
49855
49928
|
if (flags.force) args.push("--force");
|
|
49856
49929
|
if (flags.resume) args.push("--resume");
|
|
49930
|
+
if (flags.workUnitId) args.push(`--work-id=${flags.workUnitId}`);
|
|
49931
|
+
if (flags.attemptId) args.push(`--attempt-id=${flags.attemptId}`);
|
|
49857
49932
|
return args;
|
|
49858
49933
|
}
|
|
49859
49934
|
function resolveRepoPath(repoPath) {
|
|
@@ -50029,7 +50104,7 @@ var LocalScriptExecutor = class {
|
|
|
50029
50104
|
var localScriptExecutor = new LocalScriptExecutor();
|
|
50030
50105
|
|
|
50031
50106
|
// src/core/control-sync.ts
|
|
50032
|
-
var
|
|
50107
|
+
var path40 = __toESM(require("path"));
|
|
50033
50108
|
init_control_config();
|
|
50034
50109
|
|
|
50035
50110
|
// src/core/control-registry.ts
|
|
@@ -50288,7 +50363,9 @@ function createRun(ctx, meta) {
|
|
|
50288
50363
|
status: "unknown",
|
|
50289
50364
|
startedAt,
|
|
50290
50365
|
relativePath,
|
|
50291
|
-
trigger: ctx.trigger ?? "cli"
|
|
50366
|
+
trigger: ctx.trigger ?? "cli",
|
|
50367
|
+
workUnitId: ctx.workUnitId,
|
|
50368
|
+
attemptId: ctx.attemptId
|
|
50292
50369
|
});
|
|
50293
50370
|
fs28.writeFileSync(runFilePath, JSON.stringify(run2, null, 2) + "\n");
|
|
50294
50371
|
return run2;
|
|
@@ -51069,6 +51146,8 @@ function collectSlotStatus(harnessRoot, agentId, runs, pm2Procs) {
|
|
|
51069
51146
|
baseBranch: session?.baseBranch,
|
|
51070
51147
|
baseCommit: session?.baseCommit,
|
|
51071
51148
|
sessionCreatedAt: session?.createdAt,
|
|
51149
|
+
workUnitId: session?.workUnitId,
|
|
51150
|
+
attemptId: session?.attemptId,
|
|
51072
51151
|
sessionStatus: session?.status,
|
|
51073
51152
|
lastError: session?.lastError,
|
|
51074
51153
|
resumeHint,
|
|
@@ -51285,6 +51364,173 @@ function listValidations(harnessRoot) {
|
|
|
51285
51364
|
return records.sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
|
|
51286
51365
|
}
|
|
51287
51366
|
|
|
51367
|
+
// src/core/work-units.ts
|
|
51368
|
+
var crypto4 = __toESM(require("crypto"));
|
|
51369
|
+
var fs35 = __toESM(require("fs"));
|
|
51370
|
+
var path35 = __toESM(require("path"));
|
|
51371
|
+
var WORK_UNITS_DIR = "work-units";
|
|
51372
|
+
var WORK_ATTEMPTS_DIR = "work-attempts";
|
|
51373
|
+
var VALIDATION_BINDINGS_DIR = "validation-bindings";
|
|
51374
|
+
var EVIDENCE_DIRS = [WORK_UNITS_DIR, WORK_ATTEMPTS_DIR, VALIDATION_BINDINGS_DIR];
|
|
51375
|
+
function harEvidenceDir(harnessRoot, name) {
|
|
51376
|
+
return path35.join(harnessRoot, ".har", name);
|
|
51377
|
+
}
|
|
51378
|
+
function hashedRecordPath(harnessRoot, dir, id) {
|
|
51379
|
+
const digest = crypto4.createHash("sha256").update(id).digest("hex");
|
|
51380
|
+
return path35.join(harEvidenceDir(harnessRoot, dir), `${digest}.json`);
|
|
51381
|
+
}
|
|
51382
|
+
function writeRecord2(file, value) {
|
|
51383
|
+
fs35.mkdirSync(path35.dirname(file), { recursive: true });
|
|
51384
|
+
const temp = `${file}.${process.pid}.tmp`;
|
|
51385
|
+
fs35.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
|
|
51386
|
+
`);
|
|
51387
|
+
fs35.renameSync(temp, file);
|
|
51388
|
+
}
|
|
51389
|
+
function ensureWorkEvidenceIgnored(harnessRoot) {
|
|
51390
|
+
const harDir = path35.join(harnessRoot, ".har");
|
|
51391
|
+
if (!fs35.existsSync(harDir)) return;
|
|
51392
|
+
const gitignorePath = path35.join(harDir, ".gitignore");
|
|
51393
|
+
const content = fs35.existsSync(gitignorePath) ? fs35.readFileSync(gitignorePath, "utf8") : "";
|
|
51394
|
+
const lines2 = new Set(content.split("\n").map((line) => line.trim()));
|
|
51395
|
+
const missing = EVIDENCE_DIRS.map((dir) => `${dir}/`).filter((dir) => !lines2.has(dir));
|
|
51396
|
+
if (missing.length === 0) return;
|
|
51397
|
+
const separator = content.length === 0 || content.endsWith("\n") ? "" : "\n";
|
|
51398
|
+
fs35.writeFileSync(gitignorePath, `${content}${separator}${missing.join("\n")}
|
|
51399
|
+
`);
|
|
51400
|
+
}
|
|
51401
|
+
function listRecords(harnessRoot, dir, parse4) {
|
|
51402
|
+
const recordDir = harEvidenceDir(harnessRoot, dir);
|
|
51403
|
+
if (!fs35.existsSync(recordDir)) return [];
|
|
51404
|
+
const records = [];
|
|
51405
|
+
for (const name of fs35.readdirSync(recordDir)) {
|
|
51406
|
+
if (!name.endsWith(".json")) continue;
|
|
51407
|
+
try {
|
|
51408
|
+
records.push(parse4(JSON.parse(fs35.readFileSync(path35.join(recordDir, name), "utf8"))));
|
|
51409
|
+
} catch {
|
|
51410
|
+
}
|
|
51411
|
+
}
|
|
51412
|
+
return records;
|
|
51413
|
+
}
|
|
51414
|
+
function findWorkUnit(harnessRoot, workUnitId) {
|
|
51415
|
+
const metadata = WorkUnitMetadataSchema.parse({ workUnitId });
|
|
51416
|
+
const file = hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId);
|
|
51417
|
+
if (!fs35.existsSync(file)) return void 0;
|
|
51418
|
+
try {
|
|
51419
|
+
return WorkUnitRecordSchema.parse(JSON.parse(fs35.readFileSync(file, "utf8")));
|
|
51420
|
+
} catch {
|
|
51421
|
+
return void 0;
|
|
51422
|
+
}
|
|
51423
|
+
}
|
|
51424
|
+
function upsertWorkUnit(harnessRoot, input) {
|
|
51425
|
+
const metadata = WorkUnitMetadataSchema.parse(input);
|
|
51426
|
+
ensureWorkEvidenceIgnored(harnessRoot);
|
|
51427
|
+
const existing = findWorkUnit(harnessRoot, metadata.workUnitId);
|
|
51428
|
+
if (existing) {
|
|
51429
|
+
if (existing.outcome) {
|
|
51430
|
+
throw new Error(
|
|
51431
|
+
`Work unit ${metadata.workUnitId} is already ${existing.outcome.decision}; reopening is not supported`
|
|
51432
|
+
);
|
|
51433
|
+
}
|
|
51434
|
+
for (const field of ["source", "sourceUrl", "title", "parentWorkUnitId"]) {
|
|
51435
|
+
if (metadata[field] !== void 0 && existing[field] !== void 0 && metadata[field] !== existing[field]) {
|
|
51436
|
+
throw new Error(
|
|
51437
|
+
`Work unit ${metadata.workUnitId} has immutable ${field}=${existing[field]}`
|
|
51438
|
+
);
|
|
51439
|
+
}
|
|
51440
|
+
}
|
|
51441
|
+
}
|
|
51442
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
51443
|
+
const record2 = WorkUnitRecordSchema.parse({
|
|
51444
|
+
...existing,
|
|
51445
|
+
workUnitId: metadata.workUnitId,
|
|
51446
|
+
source: existing?.source ?? metadata.source,
|
|
51447
|
+
sourceUrl: existing?.sourceUrl ?? metadata.sourceUrl,
|
|
51448
|
+
title: existing?.title ?? metadata.title,
|
|
51449
|
+
parentWorkUnitId: existing?.parentWorkUnitId ?? metadata.parentWorkUnitId,
|
|
51450
|
+
version: 1,
|
|
51451
|
+
createdAt: existing?.createdAt ?? now,
|
|
51452
|
+
updatedAt: now,
|
|
51453
|
+
outcome: existing?.outcome
|
|
51454
|
+
});
|
|
51455
|
+
writeRecord2(
|
|
51456
|
+
hashedRecordPath(harnessRoot, WORK_UNITS_DIR, metadata.workUnitId),
|
|
51457
|
+
record2
|
|
51458
|
+
);
|
|
51459
|
+
return record2;
|
|
51460
|
+
}
|
|
51461
|
+
function listWorkUnits(harnessRoot) {
|
|
51462
|
+
return listRecords(
|
|
51463
|
+
harnessRoot,
|
|
51464
|
+
WORK_UNITS_DIR,
|
|
51465
|
+
(value) => WorkUnitRecordSchema.parse(value)
|
|
51466
|
+
).sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
|
|
51467
|
+
}
|
|
51468
|
+
function createWorkAttempt(harnessRoot, input) {
|
|
51469
|
+
const attempt = WorkAttemptRecordSchema.parse({
|
|
51470
|
+
...input,
|
|
51471
|
+
version: 1,
|
|
51472
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
51473
|
+
});
|
|
51474
|
+
ensureWorkEvidenceIgnored(harnessRoot);
|
|
51475
|
+
writeRecord2(
|
|
51476
|
+
hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR, attempt.attemptId),
|
|
51477
|
+
attempt
|
|
51478
|
+
);
|
|
51479
|
+
return attempt;
|
|
51480
|
+
}
|
|
51481
|
+
function listWorkAttempts(harnessRoot) {
|
|
51482
|
+
return listRecords(
|
|
51483
|
+
harnessRoot,
|
|
51484
|
+
WORK_ATTEMPTS_DIR,
|
|
51485
|
+
(value) => WorkAttemptRecordSchema.parse(value)
|
|
51486
|
+
).sort((a2, b2) => b2.createdAt.localeCompare(a2.createdAt));
|
|
51487
|
+
}
|
|
51488
|
+
function bindValidationToAttempt(harnessRoot, input) {
|
|
51489
|
+
const stableKey = `${input.attemptId}:${input.validation.validationId}`;
|
|
51490
|
+
ensureWorkEvidenceIgnored(harnessRoot);
|
|
51491
|
+
const existingFile = hashedRecordPath(
|
|
51492
|
+
harnessRoot,
|
|
51493
|
+
VALIDATION_BINDINGS_DIR,
|
|
51494
|
+
stableKey
|
|
51495
|
+
);
|
|
51496
|
+
if (fs35.existsSync(existingFile)) {
|
|
51497
|
+
try {
|
|
51498
|
+
return ValidationBindingRecordSchema.parse(
|
|
51499
|
+
JSON.parse(fs35.readFileSync(existingFile, "utf8"))
|
|
51500
|
+
);
|
|
51501
|
+
} catch {
|
|
51502
|
+
}
|
|
51503
|
+
}
|
|
51504
|
+
const binding = ValidationBindingRecordSchema.parse({
|
|
51505
|
+
bindingId: crypto4.randomUUID(),
|
|
51506
|
+
workUnitId: input.workUnitId,
|
|
51507
|
+
attemptId: input.attemptId,
|
|
51508
|
+
validationId: input.validation.validationId,
|
|
51509
|
+
treeHash: input.validation.treeHash,
|
|
51510
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
51511
|
+
});
|
|
51512
|
+
writeRecord2(existingFile, binding);
|
|
51513
|
+
return binding;
|
|
51514
|
+
}
|
|
51515
|
+
function listValidationBindings(harnessRoot) {
|
|
51516
|
+
return listRecords(
|
|
51517
|
+
harnessRoot,
|
|
51518
|
+
VALIDATION_BINDINGS_DIR,
|
|
51519
|
+
(value) => ValidationBindingRecordSchema.parse(value)
|
|
51520
|
+
).sort((a2, b2) => b2.createdAt.localeCompare(a2.createdAt));
|
|
51521
|
+
}
|
|
51522
|
+
function decideWorkUnitOutcome(harnessRoot, workUnitId, outcome) {
|
|
51523
|
+
const existing = findWorkUnit(harnessRoot, workUnitId);
|
|
51524
|
+
if (!existing) throw new Error(`Unknown work unit: ${workUnitId}`);
|
|
51525
|
+
const record2 = WorkUnitRecordSchema.parse({
|
|
51526
|
+
...existing,
|
|
51527
|
+
outcome,
|
|
51528
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
51529
|
+
});
|
|
51530
|
+
writeRecord2(hashedRecordPath(harnessRoot, WORK_UNITS_DIR, workUnitId), record2);
|
|
51531
|
+
return record2;
|
|
51532
|
+
}
|
|
51533
|
+
|
|
51288
51534
|
// src/core/cloud-executor.ts
|
|
51289
51535
|
var RemoteExecutor = class {
|
|
51290
51536
|
constructor(apiUrl, apiKey) {
|
|
@@ -51311,14 +51557,14 @@ function createRemoteExecutor(apiUrl, apiKey) {
|
|
|
51311
51557
|
init_telemetry_config();
|
|
51312
51558
|
|
|
51313
51559
|
// src/core/usage-harvest/claude.ts
|
|
51314
|
-
var
|
|
51560
|
+
var fs38 = __toESM(require("fs"));
|
|
51315
51561
|
var os10 = __toESM(require("os"));
|
|
51316
|
-
var
|
|
51562
|
+
var path38 = __toESM(require("path"));
|
|
51317
51563
|
init_telemetry_config();
|
|
51318
51564
|
|
|
51319
51565
|
// src/core/telemetry-env.ts
|
|
51320
|
-
var
|
|
51321
|
-
var
|
|
51566
|
+
var fs37 = __toESM(require("fs"));
|
|
51567
|
+
var path37 = __toESM(require("path"));
|
|
51322
51568
|
init_control_config();
|
|
51323
51569
|
function escapeAttrValue(value) {
|
|
51324
51570
|
return value.replace(/[,=]/g, "_");
|
|
@@ -51332,6 +51578,10 @@ function buildOtelResourceAttributes(attrs) {
|
|
|
51332
51578
|
];
|
|
51333
51579
|
if (attrs.branch) parts.push(`har.branch=${escapeAttrValue(attrs.branch)}`);
|
|
51334
51580
|
if (attrs.suffix) parts.push(`har.suffix=${escapeAttrValue(attrs.suffix)}`);
|
|
51581
|
+
if (attrs.workUnitId) {
|
|
51582
|
+
parts.push(`har.work_unit_id=${escapeAttrValue(attrs.workUnitId)}`);
|
|
51583
|
+
}
|
|
51584
|
+
if (attrs.attemptId) parts.push(`har.attempt_id=${attrs.attemptId}`);
|
|
51335
51585
|
return parts.join(",");
|
|
51336
51586
|
}
|
|
51337
51587
|
function buildSessionKey(input) {
|
|
@@ -51345,6 +51595,8 @@ function buildTelemetryEnvBlock(attrs) {
|
|
|
51345
51595
|
"",
|
|
51346
51596
|
"# HAR session attribution (generated)",
|
|
51347
51597
|
`HAR_SESSION_KEY=${attrs.sessionKey}`,
|
|
51598
|
+
...attrs.workUnitId ? [`HAR_WORK_UNIT_ID=${attrs.workUnitId}`] : [],
|
|
51599
|
+
...attrs.attemptId ? [`HAR_ATTEMPT_ID=${attrs.attemptId}`] : [],
|
|
51348
51600
|
`HAR_CONTROL_API_URL=${apiUrl}`,
|
|
51349
51601
|
`OTEL_RESOURCE_ATTRIBUTES=${buildOtelResourceAttributes(attrs)}`,
|
|
51350
51602
|
"# Agent telemetry: opentelemetry-hooks \u2192 Mission Control (har telemetry on|off)"
|
|
@@ -51358,8 +51610,8 @@ function appendTelemetryEnvToFile(envFilePath, attrs) {
|
|
|
51358
51610
|
${TELEMETRY_MARKER_END}
|
|
51359
51611
|
`;
|
|
51360
51612
|
let existing = "";
|
|
51361
|
-
if (
|
|
51362
|
-
existing =
|
|
51613
|
+
if (fs37.existsSync(envFilePath)) {
|
|
51614
|
+
existing = fs37.readFileSync(envFilePath, "utf8");
|
|
51363
51615
|
const start = existing.indexOf(TELEMETRY_MARKER_START);
|
|
51364
51616
|
if (start >= 0) {
|
|
51365
51617
|
const end = existing.indexOf(TELEMETRY_MARKER_END, start);
|
|
@@ -51370,28 +51622,28 @@ ${TELEMETRY_MARKER_END}
|
|
|
51370
51622
|
}
|
|
51371
51623
|
}
|
|
51372
51624
|
}
|
|
51373
|
-
|
|
51625
|
+
fs37.mkdirSync(path37.dirname(envFilePath), { recursive: true });
|
|
51374
51626
|
const combined = (existing.replace(/\n+$/, "\n") + block).replace(/^\n+/, "");
|
|
51375
|
-
|
|
51627
|
+
fs37.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
|
|
51376
51628
|
}
|
|
51377
51629
|
|
|
51378
51630
|
// src/core/usage-harvest/claude.ts
|
|
51379
51631
|
function pathsMatch(candidate, targets) {
|
|
51380
|
-
const norm =
|
|
51632
|
+
const norm = path38.resolve(candidate);
|
|
51381
51633
|
return targets.some((t2) => {
|
|
51382
|
-
const target =
|
|
51383
|
-
return norm === target || norm.startsWith(target +
|
|
51634
|
+
const target = path38.resolve(t2);
|
|
51635
|
+
return norm === target || norm.startsWith(target + path38.sep) || target.startsWith(norm + path38.sep);
|
|
51384
51636
|
});
|
|
51385
51637
|
}
|
|
51386
51638
|
function claudeProjectsRoot() {
|
|
51387
|
-
return process.env.HAR_CLAUDE_PROJECTS_DIR ?
|
|
51639
|
+
return process.env.HAR_CLAUDE_PROJECTS_DIR ? path38.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path38.join(os10.homedir(), ".claude", "projects");
|
|
51388
51640
|
}
|
|
51389
51641
|
function encodeClaudeProjectDir(cwd) {
|
|
51390
51642
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
51391
51643
|
}
|
|
51392
51644
|
function readJsonlRecords(filePath) {
|
|
51393
|
-
if (!
|
|
51394
|
-
const lines2 =
|
|
51645
|
+
if (!fs38.existsSync(filePath)) return [];
|
|
51646
|
+
const lines2 = fs38.readFileSync(filePath, "utf8").split(/\r?\n/);
|
|
51395
51647
|
const out = [];
|
|
51396
51648
|
for (const line of lines2) {
|
|
51397
51649
|
const trimmed = line.trim();
|
|
@@ -51434,16 +51686,16 @@ function findMatchingClaudeTranscripts(slot) {
|
|
|
51434
51686
|
const targets = [slot.workDir, slot.worktreePath].filter(Boolean);
|
|
51435
51687
|
if (targets.length === 0) return [];
|
|
51436
51688
|
const root = claudeProjectsRoot();
|
|
51437
|
-
if (!
|
|
51689
|
+
if (!fs38.existsSync(root)) return [];
|
|
51438
51690
|
const matches = [];
|
|
51439
|
-
for (const entry of
|
|
51691
|
+
for (const entry of fs38.readdirSync(root, { withFileTypes: true })) {
|
|
51440
51692
|
if (!entry.isDirectory()) continue;
|
|
51441
|
-
const projectDir =
|
|
51693
|
+
const projectDir = path38.join(root, entry.name);
|
|
51442
51694
|
const encodedHit = targets.some((t2) => entry.name.includes(encodeClaudeProjectDir(t2).slice(0, 40)));
|
|
51443
|
-
for (const file of
|
|
51695
|
+
for (const file of fs38.readdirSync(projectDir)) {
|
|
51444
51696
|
if (!file.endsWith(".jsonl")) continue;
|
|
51445
|
-
const filePath =
|
|
51446
|
-
const stat =
|
|
51697
|
+
const filePath = path38.join(projectDir, file);
|
|
51698
|
+
const stat = fs38.statSync(filePath);
|
|
51447
51699
|
const records = readJsonlRecords(filePath);
|
|
51448
51700
|
let cwdHit = encodedHit;
|
|
51449
51701
|
for (const record2 of records) {
|
|
@@ -51554,30 +51806,30 @@ function harvestClaudeEvents(slot) {
|
|
|
51554
51806
|
}
|
|
51555
51807
|
|
|
51556
51808
|
// src/core/usage-harvest/codex.ts
|
|
51557
|
-
var
|
|
51809
|
+
var fs39 = __toESM(require("fs"));
|
|
51558
51810
|
var os11 = __toESM(require("os"));
|
|
51559
|
-
var
|
|
51811
|
+
var path39 = __toESM(require("path"));
|
|
51560
51812
|
function pathsMatch2(candidate, targets) {
|
|
51561
|
-
const norm =
|
|
51813
|
+
const norm = path39.resolve(candidate);
|
|
51562
51814
|
return targets.some((t2) => {
|
|
51563
|
-
const target =
|
|
51564
|
-
return norm === target || norm.startsWith(target +
|
|
51815
|
+
const target = path39.resolve(t2);
|
|
51816
|
+
return norm === target || norm.startsWith(target + path39.sep) || target.startsWith(norm + path39.sep);
|
|
51565
51817
|
});
|
|
51566
51818
|
}
|
|
51567
51819
|
function codexSessionsRoot() {
|
|
51568
|
-
return process.env.HAR_CODEX_SESSIONS_DIR ?
|
|
51820
|
+
return process.env.HAR_CODEX_SESSIONS_DIR ? path39.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path39.join(os11.homedir(), ".codex", "sessions");
|
|
51569
51821
|
}
|
|
51570
51822
|
function walkJsonlFiles(dir, out = []) {
|
|
51571
|
-
if (!
|
|
51572
|
-
for (const entry of
|
|
51573
|
-
const full =
|
|
51823
|
+
if (!fs39.existsSync(dir)) return out;
|
|
51824
|
+
for (const entry of fs39.readdirSync(dir, { withFileTypes: true })) {
|
|
51825
|
+
const full = path39.join(dir, entry.name);
|
|
51574
51826
|
if (entry.isDirectory()) walkJsonlFiles(full, out);
|
|
51575
51827
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) out.push(full);
|
|
51576
51828
|
}
|
|
51577
51829
|
return out;
|
|
51578
51830
|
}
|
|
51579
51831
|
function readJsonl(filePath) {
|
|
51580
|
-
const lines2 =
|
|
51832
|
+
const lines2 = fs39.readFileSync(filePath, "utf8").split(/\r?\n/);
|
|
51581
51833
|
const out = [];
|
|
51582
51834
|
for (const line of lines2) {
|
|
51583
51835
|
const trimmed = line.trim();
|
|
@@ -51641,7 +51893,7 @@ function harvestCodexUsage(slot) {
|
|
|
51641
51893
|
const extracted = extractCodexTokens(records);
|
|
51642
51894
|
if (!extracted.cwd || !pathsMatch2(extracted.cwd, targets)) continue;
|
|
51643
51895
|
if (extracted.tokensInput + extracted.tokensOutput + extracted.tokensCacheRead === 0) continue;
|
|
51644
|
-
const mtime =
|
|
51896
|
+
const mtime = fs39.statSync(file).mtimeMs;
|
|
51645
51897
|
if (mtime >= bestMtime) {
|
|
51646
51898
|
bestMtime = mtime;
|
|
51647
51899
|
best = extracted;
|
|
@@ -51787,13 +52039,22 @@ async function syncRepoWithControl(options) {
|
|
|
51787
52039
|
}
|
|
51788
52040
|
const runs = listRuns(repoPath);
|
|
51789
52041
|
const status = collectEnvironmentStatus(repoPath);
|
|
52042
|
+
const harnessRoot = resolveHarnessRoot(repoPath);
|
|
51790
52043
|
const response = await fetch(`${process.env.HAR_CLOUD_API_URL}/api/sync`, {
|
|
51791
52044
|
method: "POST",
|
|
51792
52045
|
headers: {
|
|
51793
52046
|
"Content-Type": "application/json",
|
|
51794
52047
|
Authorization: `Bearer ${process.env.HAR_CLOUD_API_KEY}`
|
|
51795
52048
|
},
|
|
51796
|
-
body: JSON.stringify({
|
|
52049
|
+
body: JSON.stringify({
|
|
52050
|
+
path: repoPath,
|
|
52051
|
+
runs,
|
|
52052
|
+
slots: status.slots,
|
|
52053
|
+
workUnits: listWorkUnits(harnessRoot),
|
|
52054
|
+
attempts: listWorkAttempts(harnessRoot),
|
|
52055
|
+
validations: listValidations(harnessRoot),
|
|
52056
|
+
validationBindings: listValidationBindings(harnessRoot)
|
|
52057
|
+
})
|
|
51797
52058
|
});
|
|
51798
52059
|
if (!response.ok) {
|
|
51799
52060
|
throw new Error(`Cloud sync failed: ${response.status}`);
|
|
@@ -51806,7 +52067,7 @@ async function syncRepoWithControl(options) {
|
|
|
51806
52067
|
const listResponse = await fetch(`${apiUrl}/api/repos`);
|
|
51807
52068
|
if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
|
|
51808
52069
|
const repos = await listResponse.json();
|
|
51809
|
-
const existing = repos.find((r2) =>
|
|
52070
|
+
const existing = repos.find((r2) => path40.resolve(r2.path) === repoPath);
|
|
51810
52071
|
if (!existing) {
|
|
51811
52072
|
return;
|
|
51812
52073
|
}
|
|
@@ -51827,6 +52088,13 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
|
|
|
51827
52088
|
generatedAt: status.generatedAt
|
|
51828
52089
|
});
|
|
51829
52090
|
await postJson(`${apiUrl}/api/repos/${repoId}/slots`, slotsBody, dryRun);
|
|
52091
|
+
const workUnitsBody = SyncWorkUnitsInputSchema.parse({
|
|
52092
|
+
workUnits: listWorkUnits(resolveHarnessRoot(repoPath)),
|
|
52093
|
+
attempts: listWorkAttempts(resolveHarnessRoot(repoPath))
|
|
52094
|
+
});
|
|
52095
|
+
if (workUnitsBody.workUnits.length > 0 || workUnitsBody.attempts.length > 0) {
|
|
52096
|
+
await postJson(`${apiUrl}/api/repos/${repoId}/work-units`, workUnitsBody, dryRun);
|
|
52097
|
+
}
|
|
51830
52098
|
if (isTelemetryEnabled() && process.env.NODE_ENV !== "test") {
|
|
51831
52099
|
try {
|
|
51832
52100
|
const usage2 = status.slots.flatMap(
|
|
@@ -51840,6 +52108,8 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
|
|
|
51840
52108
|
repoPath
|
|
51841
52109
|
}).map((row) => ({
|
|
51842
52110
|
...row,
|
|
52111
|
+
workUnitId: slot.workUnitId,
|
|
52112
|
+
attemptId: slot.attemptId,
|
|
51843
52113
|
sessionKey: row.sessionKey || buildSessionKey({
|
|
51844
52114
|
branch: slot.branch,
|
|
51845
52115
|
agentId: slot.agentId,
|
|
@@ -51861,7 +52131,11 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
|
|
|
51861
52131
|
suffix: slot.suffix,
|
|
51862
52132
|
sessionCreatedAt: slot.sessionCreatedAt,
|
|
51863
52133
|
repoPath
|
|
51864
|
-
})
|
|
52134
|
+
}).map((event) => ({
|
|
52135
|
+
...event,
|
|
52136
|
+
workUnitId: slot.workUnitId,
|
|
52137
|
+
attemptId: slot.attemptId
|
|
52138
|
+
}))
|
|
51865
52139
|
);
|
|
51866
52140
|
if (events.length > 0) {
|
|
51867
52141
|
const eventsBody = SyncSessionEventsInputSchema.parse({ events });
|
|
@@ -51878,6 +52152,16 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
|
|
|
51878
52152
|
const validationsBody = SyncValidationsInputSchema.parse({ validations });
|
|
51879
52153
|
await postJson(`${apiUrl}/api/repos/${repoId}/validations`, validationsBody, dryRun);
|
|
51880
52154
|
}
|
|
52155
|
+
const bindingsBody = SyncValidationBindingsInputSchema.parse({
|
|
52156
|
+
bindings: listValidationBindings(resolveHarnessRoot(repoPath))
|
|
52157
|
+
});
|
|
52158
|
+
if (bindingsBody.bindings.length > 0) {
|
|
52159
|
+
await postJson(
|
|
52160
|
+
`${apiUrl}/api/repos/${repoId}/validation-bindings`,
|
|
52161
|
+
bindingsBody,
|
|
52162
|
+
dryRun
|
|
52163
|
+
);
|
|
52164
|
+
}
|
|
51881
52165
|
}
|
|
51882
52166
|
var SYNC_TIMEOUT_MS = 15e3;
|
|
51883
52167
|
function withTimeout(promise, ms, label) {
|
|
@@ -51935,7 +52219,7 @@ init_control_config();
|
|
|
51935
52219
|
|
|
51936
52220
|
// src/core/control-lifecycle.ts
|
|
51937
52221
|
var import_child_process8 = require("child_process");
|
|
51938
|
-
var
|
|
52222
|
+
var path41 = __toESM(require("path"));
|
|
51939
52223
|
|
|
51940
52224
|
// src/core/control-image.ts
|
|
51941
52225
|
var DEFAULT_CONTROL_IMAGE = "theosfactory/har-control";
|
|
@@ -51959,10 +52243,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
|
|
|
51959
52243
|
var CONTROL_CONTAINER_PORT = 3847;
|
|
51960
52244
|
var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
|
|
51961
52245
|
function resolveControlDir() {
|
|
51962
|
-
return
|
|
52246
|
+
return path41.resolve(__dirname, "..", "control");
|
|
51963
52247
|
}
|
|
51964
52248
|
function resolveControlBuildContext() {
|
|
51965
|
-
return
|
|
52249
|
+
return path41.resolve(resolveControlDir(), "..");
|
|
51966
52250
|
}
|
|
51967
52251
|
function buildDockerRunArgs(options) {
|
|
51968
52252
|
const name = options.containerName ?? CONTROL_CONTAINER_NAME;
|
|
@@ -52018,7 +52302,7 @@ async function startMissionControl(options) {
|
|
|
52018
52302
|
"-t",
|
|
52019
52303
|
imageRef,
|
|
52020
52304
|
"-f",
|
|
52021
|
-
|
|
52305
|
+
path41.join(resolveControlDir(), "Dockerfile"),
|
|
52022
52306
|
resolveControlBuildContext()
|
|
52023
52307
|
]);
|
|
52024
52308
|
if (buildCode !== 0) {
|
|
@@ -52162,7 +52446,7 @@ async function ensureTelemetryInfrastructure(options) {
|
|
|
52162
52446
|
|
|
52163
52447
|
// src/core/run-service.ts
|
|
52164
52448
|
init_telemetry_config();
|
|
52165
|
-
var
|
|
52449
|
+
var path43 = __toESM(require("path"));
|
|
52166
52450
|
function extractShellOutput(result) {
|
|
52167
52451
|
const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
|
|
52168
52452
|
const stderr = result.logs?.find((log) => log.stream === "stderr")?.content ?? "";
|
|
@@ -52200,11 +52484,14 @@ var RunService = class {
|
|
|
52200
52484
|
this.executor = executor;
|
|
52201
52485
|
}
|
|
52202
52486
|
async runStage(options) {
|
|
52487
|
+
const activeSession = options.agentId !== void 0 && options.kind !== "launch" ? readSlotRegistry(resolveHarnessRoot(options.repoPath), options.agentId) : void 0;
|
|
52203
52488
|
const ctx = {
|
|
52204
52489
|
repoPath: options.repoPath,
|
|
52205
52490
|
capture: options.capture,
|
|
52206
52491
|
agentId: options.agentId,
|
|
52207
|
-
trigger: options.trigger
|
|
52492
|
+
trigger: options.trigger,
|
|
52493
|
+
workUnitId: options.workUnitId ?? activeSession?.workUnitId,
|
|
52494
|
+
attemptId: options.attemptId ?? activeSession?.attemptId
|
|
52208
52495
|
};
|
|
52209
52496
|
const stageLookup = options.stageId ? { id: options.stageId } : options.kind ? { kind: options.kind } : null;
|
|
52210
52497
|
if (!stageLookup) {
|
|
@@ -52306,47 +52593,96 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
|
|
|
52306
52593
|
`;
|
|
52307
52594
|
}
|
|
52308
52595
|
}
|
|
52596
|
+
const harnessRoot = resolveHarnessRoot(options.repoPath);
|
|
52597
|
+
const resumableSession = options.resume ? readSlotRegistry(harnessRoot, options.agentId) : void 0;
|
|
52598
|
+
const workUnitId = options.workUnitId ?? resumableSession?.workUnitId;
|
|
52599
|
+
const attemptId = workUnitId ? resumableSession?.attemptId ?? crypto5.randomUUID() : void 0;
|
|
52600
|
+
if (workUnitId && attemptId) {
|
|
52601
|
+
const conflictingSession = listSlotRegistryEntries(harnessRoot).find(
|
|
52602
|
+
(entry) => entry.workUnitId === workUnitId && !(entry.agentId === options.agentId && (options.resume || options.confirmReplace))
|
|
52603
|
+
);
|
|
52604
|
+
if (conflictingSession) {
|
|
52605
|
+
return {
|
|
52606
|
+
code: 2,
|
|
52607
|
+
stdout: "",
|
|
52608
|
+
stderr: `Work unit ${workUnitId} is already bound to slot ${conflictingSession.agentId} (attempt ${conflictingSession.attemptId ?? "unknown"}).`,
|
|
52609
|
+
blocked: true
|
|
52610
|
+
};
|
|
52611
|
+
}
|
|
52612
|
+
upsertWorkUnit(harnessRoot, {
|
|
52613
|
+
workUnitId,
|
|
52614
|
+
source: options.source,
|
|
52615
|
+
sourceUrl: options.sourceUrl,
|
|
52616
|
+
title: options.title,
|
|
52617
|
+
parentWorkUnitId: options.parentWorkUnitId
|
|
52618
|
+
});
|
|
52619
|
+
createWorkAttempt(harnessRoot, {
|
|
52620
|
+
attemptId,
|
|
52621
|
+
workUnitId,
|
|
52622
|
+
agentId: options.agentId
|
|
52623
|
+
});
|
|
52624
|
+
}
|
|
52309
52625
|
const result = await this.runStage({
|
|
52310
52626
|
repoPath: options.repoPath,
|
|
52311
52627
|
kind: "launch",
|
|
52312
52628
|
agentId: options.agentId,
|
|
52629
|
+
workUnitId,
|
|
52630
|
+
attemptId,
|
|
52313
52631
|
capture: options.capture ?? false,
|
|
52314
52632
|
launchFlags: {
|
|
52315
52633
|
worktree: options.worktree,
|
|
52316
52634
|
claude: options.claude,
|
|
52317
52635
|
confirmReplace: options.confirmReplace,
|
|
52318
52636
|
force: options.force,
|
|
52319
|
-
resume: options.resume
|
|
52637
|
+
resume: options.resume,
|
|
52638
|
+
workUnitId,
|
|
52639
|
+
attemptId
|
|
52320
52640
|
},
|
|
52321
52641
|
trigger: "cli"
|
|
52322
52642
|
});
|
|
52323
52643
|
const envResult = toEnvironmentRunResult(result);
|
|
52324
52644
|
if (envResult.code === 0) {
|
|
52325
|
-
const harnessRoot = resolveHarnessRoot(options.repoPath);
|
|
52326
52645
|
const session = readSlotRegistry(harnessRoot, options.agentId);
|
|
52327
52646
|
if (session) {
|
|
52328
52647
|
envResult.workDir = session.workDir;
|
|
52329
52648
|
envResult.worktreePath = session.worktreePath;
|
|
52330
52649
|
envResult.branch = session.branch;
|
|
52331
52650
|
envResult.previewUrls = envResult.previewUrls ?? session.previewUrls;
|
|
52651
|
+
envResult.workUnitId = session.workUnitId;
|
|
52652
|
+
envResult.attemptId = session.attemptId;
|
|
52332
52653
|
const sessionKey = buildSessionKey({
|
|
52333
52654
|
branch: session.branch,
|
|
52334
52655
|
agentId: options.agentId,
|
|
52335
52656
|
suffix: session.suffix,
|
|
52336
52657
|
createdAt: session.createdAt
|
|
52337
52658
|
});
|
|
52338
|
-
const envFile =
|
|
52659
|
+
const envFile = path43.join(session.workDir, `.env.agent.${options.agentId}`);
|
|
52339
52660
|
try {
|
|
52340
52661
|
appendTelemetryEnvToFile(envFile, {
|
|
52341
52662
|
sessionKey,
|
|
52342
52663
|
agentId: options.agentId,
|
|
52343
|
-
repoPath:
|
|
52664
|
+
repoPath: path43.resolve(options.repoPath),
|
|
52344
52665
|
workDir: session.workDir,
|
|
52345
52666
|
branch: session.branch,
|
|
52346
|
-
suffix: session.suffix
|
|
52667
|
+
suffix: session.suffix,
|
|
52668
|
+
workUnitId: session.workUnitId,
|
|
52669
|
+
attemptId: session.attemptId
|
|
52347
52670
|
});
|
|
52348
52671
|
} catch {
|
|
52349
52672
|
}
|
|
52673
|
+
if (session.workUnitId && session.attemptId) {
|
|
52674
|
+
createWorkAttempt(harnessRoot, {
|
|
52675
|
+
attemptId: session.attemptId,
|
|
52676
|
+
workUnitId: session.workUnitId,
|
|
52677
|
+
agentId: options.agentId,
|
|
52678
|
+
sessionKey,
|
|
52679
|
+
workDir: session.workDir,
|
|
52680
|
+
worktreePath: session.worktreePath,
|
|
52681
|
+
branch: session.branch,
|
|
52682
|
+
baseCommit: session.baseCommit,
|
|
52683
|
+
createdAt: session.createdAt
|
|
52684
|
+
});
|
|
52685
|
+
}
|
|
52350
52686
|
}
|
|
52351
52687
|
if (telemetryBanner) {
|
|
52352
52688
|
envResult.stderr = `${telemetryBanner}${envResult.stderr ?? ""}`;
|
|
@@ -52377,7 +52713,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
|
|
|
52377
52713
|
const harnessRoot = resolveHarnessRoot(options.repoPath);
|
|
52378
52714
|
const checkoutDir = resolveAgentWorkDir(harnessRoot, options.agentId) ?? harnessRoot;
|
|
52379
52715
|
const runId = typeof result.data === "object" && result.data !== null && !Array.isArray(result.data) ? result.data.runId : void 0;
|
|
52380
|
-
recordValidation({
|
|
52716
|
+
const validation2 = recordValidation({
|
|
52381
52717
|
checkoutDir,
|
|
52382
52718
|
harnessRoot,
|
|
52383
52719
|
status: verification.status,
|
|
@@ -52385,7 +52721,22 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
|
|
|
52385
52721
|
runId,
|
|
52386
52722
|
agentId: options.agentId
|
|
52387
52723
|
});
|
|
52724
|
+
const session = readSlotRegistry(harnessRoot, options.agentId);
|
|
52725
|
+
if (session?.workUnitId && session.attemptId) {
|
|
52726
|
+
bindValidationToAttempt(harnessRoot, {
|
|
52727
|
+
workUnitId: session.workUnitId,
|
|
52728
|
+
attemptId: session.attemptId,
|
|
52729
|
+
validation: validation2
|
|
52730
|
+
});
|
|
52731
|
+
}
|
|
52388
52732
|
await syncRepoWithControlAsync(options.repoPath);
|
|
52733
|
+
return {
|
|
52734
|
+
code: shell.code,
|
|
52735
|
+
stdout: shell.stdout,
|
|
52736
|
+
stderr: shell.stderr,
|
|
52737
|
+
verification,
|
|
52738
|
+
validation: validation2
|
|
52739
|
+
};
|
|
52389
52740
|
} catch {
|
|
52390
52741
|
}
|
|
52391
52742
|
}
|
|
@@ -52423,6 +52774,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
|
|
|
52423
52774
|
};
|
|
52424
52775
|
}
|
|
52425
52776
|
let verification;
|
|
52777
|
+
let validation2;
|
|
52426
52778
|
if (!options.skipVerify) {
|
|
52427
52779
|
const verify = await this.runVerification({
|
|
52428
52780
|
repoPath: options.repoPath,
|
|
@@ -52432,6 +52784,7 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
|
|
|
52432
52784
|
trigger: options.trigger
|
|
52433
52785
|
});
|
|
52434
52786
|
verification = verify.verification;
|
|
52787
|
+
validation2 = verify.validation;
|
|
52435
52788
|
if (verify.code !== 0 || verification?.status !== "pass") {
|
|
52436
52789
|
return {
|
|
52437
52790
|
...verify,
|
|
@@ -52439,6 +52792,24 @@ Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Workt
|
|
|
52439
52792
|
};
|
|
52440
52793
|
}
|
|
52441
52794
|
}
|
|
52795
|
+
if (session.workUnitId && session.attemptId && !options.skipVerify && !validation2) {
|
|
52796
|
+
return {
|
|
52797
|
+
code: 1,
|
|
52798
|
+
stdout: "",
|
|
52799
|
+
stderr: "Full verification passed, but HAR could not record exact-tree validation proof. Session NOT completed.",
|
|
52800
|
+
verification
|
|
52801
|
+
};
|
|
52802
|
+
}
|
|
52803
|
+
if (session.workUnitId && session.attemptId && validation2) {
|
|
52804
|
+
decideWorkUnitOutcome(harnessRoot, session.workUnitId, {
|
|
52805
|
+
decision: "completed",
|
|
52806
|
+
decidedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
52807
|
+
attemptId: session.attemptId,
|
|
52808
|
+
validationId: validation2.validationId,
|
|
52809
|
+
treeHash: validation2.treeHash
|
|
52810
|
+
});
|
|
52811
|
+
await syncRepoWithControlAsync(options.repoPath);
|
|
52812
|
+
}
|
|
52442
52813
|
const teardown = await this.teardownEnvironment({
|
|
52443
52814
|
repoPath: options.repoPath,
|
|
52444
52815
|
agentId: options.agentId,
|
|
@@ -52522,9 +52893,9 @@ var getEnvironmentLogs = defaultRunService.getEnvironmentLogs.bind(defaultRunSer
|
|
|
52522
52893
|
var readline5 = __toESM(require("readline"));
|
|
52523
52894
|
|
|
52524
52895
|
// src/core/hooks.ts
|
|
52525
|
-
var
|
|
52896
|
+
var fs41 = __toESM(require("fs"));
|
|
52526
52897
|
var os13 = __toESM(require("os"));
|
|
52527
|
-
var
|
|
52898
|
+
var path44 = __toESM(require("path"));
|
|
52528
52899
|
var MARKER_START = "# >>> har commit gate (managed by `har hooks`) >>>";
|
|
52529
52900
|
var MARKER_END = "# <<< har commit gate <<<";
|
|
52530
52901
|
var PRE_COMMIT_BLOCK = [
|
|
@@ -52549,7 +52920,7 @@ function resolveCheckoutRoot(cwd) {
|
|
|
52549
52920
|
function resolveHooksDir(checkoutDir) {
|
|
52550
52921
|
const hooksPath = tryGit3(checkoutDir, "rev-parse --git-path hooks");
|
|
52551
52922
|
if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
|
|
52552
|
-
return
|
|
52923
|
+
return path44.resolve(checkoutDir, hooksPath);
|
|
52553
52924
|
}
|
|
52554
52925
|
function getConfiguredHooksPath(checkoutDir) {
|
|
52555
52926
|
return tryGit3(checkoutDir, "config core.hooksPath") || void 0;
|
|
@@ -52557,9 +52928,9 @@ function getConfiguredHooksPath(checkoutDir) {
|
|
|
52557
52928
|
function defaultHarInvocation() {
|
|
52558
52929
|
const entry = process.argv[1];
|
|
52559
52930
|
if (entry && entry.endsWith(".js")) {
|
|
52560
|
-
return `"${process.execPath}" "${
|
|
52931
|
+
return `"${process.execPath}" "${path44.resolve(entry)}"`;
|
|
52561
52932
|
}
|
|
52562
|
-
if (entry) return `"${
|
|
52933
|
+
if (entry) return `"${path44.resolve(entry)}"`;
|
|
52563
52934
|
return "har";
|
|
52564
52935
|
}
|
|
52565
52936
|
function buildHookScript(harInvocation, subcommand, failOpenNotice) {
|
|
@@ -52580,40 +52951,40 @@ exit 0
|
|
|
52580
52951
|
`;
|
|
52581
52952
|
}
|
|
52582
52953
|
function upsertMarkedBlock(filePath, block) {
|
|
52583
|
-
if (!
|
|
52584
|
-
|
|
52954
|
+
if (!fs41.existsSync(filePath)) {
|
|
52955
|
+
fs41.writeFileSync(filePath, `#!/bin/sh
|
|
52585
52956
|
${block}
|
|
52586
52957
|
`, { mode: 493 });
|
|
52587
52958
|
return "created";
|
|
52588
52959
|
}
|
|
52589
|
-
const content =
|
|
52960
|
+
const content = fs41.readFileSync(filePath, "utf8");
|
|
52590
52961
|
if (content.includes(MARKER_START)) {
|
|
52591
52962
|
const pattern = new RegExp(
|
|
52592
52963
|
`${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}`
|
|
52593
52964
|
);
|
|
52594
|
-
|
|
52595
|
-
|
|
52965
|
+
fs41.writeFileSync(filePath, content.replace(pattern, block));
|
|
52966
|
+
fs41.chmodSync(filePath, 493);
|
|
52596
52967
|
return "updated";
|
|
52597
52968
|
}
|
|
52598
52969
|
const suffix = content.endsWith("\n") ? "" : "\n";
|
|
52599
|
-
|
|
52970
|
+
fs41.writeFileSync(filePath, `${content}${suffix}
|
|
52600
52971
|
${block}
|
|
52601
52972
|
`);
|
|
52602
|
-
|
|
52973
|
+
fs41.chmodSync(filePath, 493);
|
|
52603
52974
|
return "appended";
|
|
52604
52975
|
}
|
|
52605
52976
|
function removeMarkedBlock(filePath) {
|
|
52606
|
-
if (!
|
|
52607
|
-
const content =
|
|
52977
|
+
if (!fs41.existsSync(filePath)) return false;
|
|
52978
|
+
const content = fs41.readFileSync(filePath, "utf8");
|
|
52608
52979
|
if (!content.includes(MARKER_START)) return false;
|
|
52609
52980
|
const pattern = new RegExp(
|
|
52610
52981
|
`\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`
|
|
52611
52982
|
);
|
|
52612
52983
|
const stripped = content.replace(pattern, "\n");
|
|
52613
52984
|
if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
|
|
52614
|
-
|
|
52985
|
+
fs41.rmSync(filePath);
|
|
52615
52986
|
} else {
|
|
52616
|
-
|
|
52987
|
+
fs41.writeFileSync(filePath, stripped);
|
|
52617
52988
|
}
|
|
52618
52989
|
return true;
|
|
52619
52990
|
}
|
|
@@ -52635,20 +53006,20 @@ Or re-run with --force to write into that directory anyway.`
|
|
|
52635
53006
|
);
|
|
52636
53007
|
}
|
|
52637
53008
|
const hooksDir = resolveHooksDir(checkout);
|
|
52638
|
-
|
|
53009
|
+
fs41.mkdirSync(hooksDir, { recursive: true });
|
|
52639
53010
|
const invocation = options.harInvocation ?? defaultHarInvocation();
|
|
52640
|
-
|
|
52641
|
-
|
|
53011
|
+
fs41.writeFileSync(
|
|
53012
|
+
path44.join(hooksDir, "har-pre-commit"),
|
|
52642
53013
|
buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
|
|
52643
53014
|
{ mode: 493 }
|
|
52644
53015
|
);
|
|
52645
|
-
|
|
52646
|
-
|
|
53016
|
+
fs41.writeFileSync(
|
|
53017
|
+
path44.join(hooksDir, "har-post-commit"),
|
|
52647
53018
|
buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
|
|
52648
53019
|
{ mode: 493 }
|
|
52649
53020
|
);
|
|
52650
|
-
const preCommit = upsertMarkedBlock(
|
|
52651
|
-
const postCommit = upsertMarkedBlock(
|
|
53021
|
+
const preCommit = upsertMarkedBlock(path44.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
|
|
53022
|
+
const postCommit = upsertMarkedBlock(path44.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
|
|
52652
53023
|
ensureValidationsIgnored(checkout);
|
|
52653
53024
|
return { hooksDir, preCommit, postCommit };
|
|
52654
53025
|
}
|
|
@@ -52657,12 +53028,12 @@ function uninstallHooks(repoPath) {
|
|
|
52657
53028
|
if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
|
|
52658
53029
|
const hooksDir = resolveHooksDir(checkout);
|
|
52659
53030
|
let removed = false;
|
|
52660
|
-
removed = removeMarkedBlock(
|
|
52661
|
-
removed = removeMarkedBlock(
|
|
53031
|
+
removed = removeMarkedBlock(path44.join(hooksDir, "pre-commit")) || removed;
|
|
53032
|
+
removed = removeMarkedBlock(path44.join(hooksDir, "post-commit")) || removed;
|
|
52662
53033
|
for (const file of ["har-pre-commit", "har-post-commit"]) {
|
|
52663
|
-
const full =
|
|
52664
|
-
if (
|
|
52665
|
-
|
|
53034
|
+
const full = path44.join(hooksDir, file);
|
|
53035
|
+
if (fs41.existsSync(full)) {
|
|
53036
|
+
fs41.rmSync(full);
|
|
52666
53037
|
removed = true;
|
|
52667
53038
|
}
|
|
52668
53039
|
}
|
|
@@ -52681,10 +53052,10 @@ function isAgentWorktree(checkoutDir) {
|
|
|
52681
53052
|
if (branch && (/^har-agent-\d+$/.test(branch) || /-har-agent-\d+-[a-z0-9]+$/.test(branch))) {
|
|
52682
53053
|
return true;
|
|
52683
53054
|
}
|
|
52684
|
-
const worktreesRoot =
|
|
52685
|
-
const resolved =
|
|
52686
|
-
const name =
|
|
52687
|
-
return resolved.startsWith(`${worktreesRoot}${
|
|
53055
|
+
const worktreesRoot = path44.join(os13.homedir(), "worktrees");
|
|
53056
|
+
const resolved = path44.resolve(checkoutDir);
|
|
53057
|
+
const name = path44.basename(resolved);
|
|
53058
|
+
return resolved.startsWith(`${worktreesRoot}${path44.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
|
|
52688
53059
|
}
|
|
52689
53060
|
function resolveEffectiveMode(checkoutDir, gate) {
|
|
52690
53061
|
if (!gate.enabled) return "off";
|
|
@@ -52697,15 +53068,15 @@ function getHooksStatus(repoPath) {
|
|
|
52697
53068
|
const hooksDir = resolveHooksDir(checkout);
|
|
52698
53069
|
const gate = getCommitGateConfig(checkout);
|
|
52699
53070
|
const hasBlock = (name) => {
|
|
52700
|
-
const file =
|
|
52701
|
-
return
|
|
53071
|
+
const file = path44.join(hooksDir, name);
|
|
53072
|
+
return fs41.existsSync(file) && fs41.readFileSync(file, "utf8").includes(MARKER_START);
|
|
52702
53073
|
};
|
|
52703
53074
|
return {
|
|
52704
53075
|
checkout,
|
|
52705
53076
|
hooksDir,
|
|
52706
53077
|
configuredHooksPath: getConfiguredHooksPath(checkout),
|
|
52707
|
-
preCommitInstalled: hasBlock("pre-commit") &&
|
|
52708
|
-
postCommitInstalled: hasBlock("post-commit") &&
|
|
53078
|
+
preCommitInstalled: hasBlock("pre-commit") && fs41.existsSync(path44.join(hooksDir, "har-pre-commit")),
|
|
53079
|
+
postCommitInstalled: hasBlock("post-commit") && fs41.existsSync(path44.join(hooksDir, "har-post-commit")),
|
|
52709
53080
|
gate,
|
|
52710
53081
|
effectiveMode: resolveEffectiveMode(checkout, gate)
|
|
52711
53082
|
};
|
|
@@ -52716,7 +53087,7 @@ function checkCommitGate(cwd) {
|
|
|
52716
53087
|
}
|
|
52717
53088
|
const checkout = resolveCheckoutRoot(cwd);
|
|
52718
53089
|
if (!checkout) return { exitCode: 0, messages: [] };
|
|
52719
|
-
if (!
|
|
53090
|
+
if (!fs41.existsSync(path44.join(checkout, ".har", "stages.json"))) {
|
|
52720
53091
|
return { exitCode: 0, messages: [] };
|
|
52721
53092
|
}
|
|
52722
53093
|
const gate = getCommitGateConfig(checkout);
|
|
@@ -52836,20 +53207,20 @@ async function handleCommitGateOnboarding(options) {
|
|
|
52836
53207
|
}
|
|
52837
53208
|
|
|
52838
53209
|
// src/core/onboarding-preferences.ts
|
|
52839
|
-
var
|
|
53210
|
+
var fs42 = __toESM(require("fs"));
|
|
52840
53211
|
var os14 = __toESM(require("os"));
|
|
52841
|
-
var
|
|
53212
|
+
var path45 = __toESM(require("path"));
|
|
52842
53213
|
function getOnboardingPreferencesPath() {
|
|
52843
53214
|
if (process.env.HAR_PREFERENCES_PATH) {
|
|
52844
|
-
return
|
|
53215
|
+
return path45.resolve(process.env.HAR_PREFERENCES_PATH);
|
|
52845
53216
|
}
|
|
52846
|
-
return
|
|
53217
|
+
return path45.join(os14.homedir(), ".har", "preferences.json");
|
|
52847
53218
|
}
|
|
52848
53219
|
function readOnboardingPreferences() {
|
|
52849
53220
|
const preferencePath = getOnboardingPreferencesPath();
|
|
52850
53221
|
try {
|
|
52851
|
-
if (!
|
|
52852
|
-
return OnboardingPreferencesSchema.parse(JSON.parse(
|
|
53222
|
+
if (!fs42.existsSync(preferencePath)) return OnboardingPreferencesSchema.parse({});
|
|
53223
|
+
return OnboardingPreferencesSchema.parse(JSON.parse(fs42.readFileSync(preferencePath, "utf8")));
|
|
52853
53224
|
} catch {
|
|
52854
53225
|
return OnboardingPreferencesSchema.parse({});
|
|
52855
53226
|
}
|
|
@@ -52874,8 +53245,8 @@ function writeOnboardingPreferences(overrides) {
|
|
|
52874
53245
|
};
|
|
52875
53246
|
const parsed = OnboardingPreferencesSchema.parse(preference);
|
|
52876
53247
|
const preferencePath = getOnboardingPreferencesPath();
|
|
52877
|
-
|
|
52878
|
-
|
|
53248
|
+
fs42.mkdirSync(path45.dirname(preferencePath), { recursive: true });
|
|
53249
|
+
fs42.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
|
|
52879
53250
|
`);
|
|
52880
53251
|
return parsed;
|
|
52881
53252
|
}
|
|
@@ -53070,6 +53441,15 @@ var envCommand = {
|
|
|
53070
53441
|
type: "boolean",
|
|
53071
53442
|
default: false,
|
|
53072
53443
|
describe: LAUNCH_RESUME_DESCRIBE
|
|
53444
|
+
}).option("work-id", {
|
|
53445
|
+
type: "string",
|
|
53446
|
+
describe: "Bind this session to a durable external work identifier"
|
|
53447
|
+
}).option("work-source", {
|
|
53448
|
+
type: "string",
|
|
53449
|
+
describe: "Optional provider/source name (for example github or linear)"
|
|
53450
|
+
}).option("work-url", { type: "string", describe: "Optional source URL for the work" }).option("work-title", { type: "string", describe: "Optional human-readable title" }).option("parent-work-id", {
|
|
53451
|
+
type: "string",
|
|
53452
|
+
describe: "Optional parent work unit identifier"
|
|
53073
53453
|
}).epilog(LAUNCH_EPILOG),
|
|
53074
53454
|
handleLaunch
|
|
53075
53455
|
).command(
|
|
@@ -53146,7 +53526,7 @@ var envCommand = {
|
|
|
53146
53526
|
}
|
|
53147
53527
|
};
|
|
53148
53528
|
async function handleInit(argv) {
|
|
53149
|
-
const repoPath =
|
|
53529
|
+
const repoPath = path46.resolve(argv.repo);
|
|
53150
53530
|
const onboarding = resolveOnboardingOptions(argv);
|
|
53151
53531
|
header("har env init");
|
|
53152
53532
|
info(`Repository: ${repoPath}`);
|
|
@@ -53210,7 +53590,7 @@ async function handleInit(argv) {
|
|
|
53210
53590
|
}
|
|
53211
53591
|
}
|
|
53212
53592
|
async function handleMaintain(argv) {
|
|
53213
|
-
const repoPath =
|
|
53593
|
+
const repoPath = path46.resolve(argv.repo);
|
|
53214
53594
|
const onboarding = resolveOnboardingOptions(argv);
|
|
53215
53595
|
header("har env maintain");
|
|
53216
53596
|
info(`Repository: ${repoPath}`);
|
|
@@ -53325,7 +53705,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
|
|
|
53325
53705
|
if (autoYes) {
|
|
53326
53706
|
const proposal = readAgentMdProposal(repoPath);
|
|
53327
53707
|
if (proposal) {
|
|
53328
|
-
writeFileSafe(
|
|
53708
|
+
writeFileSafe(path46.join(repoPath, "AGENT.md"), proposal.content);
|
|
53329
53709
|
clearAgentMdProposal(repoPath);
|
|
53330
53710
|
info("Applied AGENT.md proposal (--yes)");
|
|
53331
53711
|
}
|
|
@@ -53334,7 +53714,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
|
|
|
53334
53714
|
await promptApplyAgentMdProposal(repoPath);
|
|
53335
53715
|
}
|
|
53336
53716
|
async function handleAddStage(argv) {
|
|
53337
|
-
const repoPath =
|
|
53717
|
+
const repoPath = path46.resolve(argv.repo);
|
|
53338
53718
|
const available = listStageTemplateIds();
|
|
53339
53719
|
if (argv.list) {
|
|
53340
53720
|
for (const id of available) {
|
|
@@ -53411,7 +53791,7 @@ async function handleAddStage(argv) {
|
|
|
53411
53791
|
}
|
|
53412
53792
|
}
|
|
53413
53793
|
async function handlePreflight(argv) {
|
|
53414
|
-
const repo =
|
|
53794
|
+
const repo = path46.resolve(argv.repo);
|
|
53415
53795
|
const agentId = validateAgentId(argv.id, repo);
|
|
53416
53796
|
const result = await preflightEnvironment({
|
|
53417
53797
|
repoPath: repo,
|
|
@@ -53429,7 +53809,7 @@ async function handlePreflight(argv) {
|
|
|
53429
53809
|
process.exit(result.code);
|
|
53430
53810
|
}
|
|
53431
53811
|
async function handleLaunch(argv) {
|
|
53432
|
-
const repo =
|
|
53812
|
+
const repo = path46.resolve(argv.repo);
|
|
53433
53813
|
const agentId = validateAgentId(argv.id, repo);
|
|
53434
53814
|
let confirmReplace = argv.replace;
|
|
53435
53815
|
let force = argv.force;
|
|
@@ -53481,6 +53861,11 @@ async function handleLaunch(argv) {
|
|
|
53481
53861
|
confirmReplace,
|
|
53482
53862
|
force,
|
|
53483
53863
|
resume: argv.resume,
|
|
53864
|
+
workUnitId: argv.workId,
|
|
53865
|
+
source: argv.workSource,
|
|
53866
|
+
sourceUrl: argv.workUrl,
|
|
53867
|
+
title: argv.workTitle,
|
|
53868
|
+
parentWorkUnitId: argv.parentWorkId,
|
|
53484
53869
|
capture: false
|
|
53485
53870
|
});
|
|
53486
53871
|
if (result.blocked) {
|
|
@@ -53509,11 +53894,16 @@ async function handleRecover(argv) {
|
|
|
53509
53894
|
claude: false,
|
|
53510
53895
|
replace: false,
|
|
53511
53896
|
force: false,
|
|
53512
|
-
resume: true
|
|
53897
|
+
resume: true,
|
|
53898
|
+
workId: void 0,
|
|
53899
|
+
workSource: void 0,
|
|
53900
|
+
workUrl: void 0,
|
|
53901
|
+
workTitle: void 0,
|
|
53902
|
+
parentWorkId: void 0
|
|
53513
53903
|
});
|
|
53514
53904
|
}
|
|
53515
53905
|
async function handleVerify(argv) {
|
|
53516
|
-
const repo =
|
|
53906
|
+
const repo = path46.resolve(argv.repo);
|
|
53517
53907
|
const agentId = validateAgentId(argv.id, repo);
|
|
53518
53908
|
const result = await runVerification({
|
|
53519
53909
|
repoPath: repo,
|
|
@@ -53525,7 +53915,7 @@ async function handleVerify(argv) {
|
|
|
53525
53915
|
process.exit(result.code);
|
|
53526
53916
|
}
|
|
53527
53917
|
async function handleTeardown(argv) {
|
|
53528
|
-
const repo =
|
|
53918
|
+
const repo = path46.resolve(argv.repo);
|
|
53529
53919
|
const agentId = validateAgentId(argv.id, repo);
|
|
53530
53920
|
const result = await teardownEnvironment({
|
|
53531
53921
|
repoPath: repo,
|
|
@@ -53536,7 +53926,7 @@ async function handleTeardown(argv) {
|
|
|
53536
53926
|
process.exit(result.code);
|
|
53537
53927
|
}
|
|
53538
53928
|
async function handleComplete(argv) {
|
|
53539
|
-
const repo =
|
|
53929
|
+
const repo = path46.resolve(argv.repo);
|
|
53540
53930
|
const agentId = validateAgentId(argv.id, repo);
|
|
53541
53931
|
const result = await completeEnvironment({
|
|
53542
53932
|
repoPath: repo,
|
|
@@ -53557,7 +53947,7 @@ async function handleComplete(argv) {
|
|
|
53557
53947
|
process.exit(result.code);
|
|
53558
53948
|
}
|
|
53559
53949
|
async function handleStatus(argv) {
|
|
53560
|
-
const repoPath =
|
|
53950
|
+
const repoPath = path46.resolve(argv.repo);
|
|
53561
53951
|
if (argv.json) {
|
|
53562
53952
|
const status = collectEnvironmentStatus(repoPath);
|
|
53563
53953
|
const output = EnvironmentStatusSchema.parse(status);
|
|
@@ -53570,7 +53960,7 @@ async function handleStatus(argv) {
|
|
|
53570
53960
|
});
|
|
53571
53961
|
}
|
|
53572
53962
|
async function handleRunsList(argv) {
|
|
53573
|
-
const repoPath =
|
|
53963
|
+
const repoPath = path46.resolve(argv.repo);
|
|
53574
53964
|
const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
|
|
53575
53965
|
if (argv.json) {
|
|
53576
53966
|
process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
|
|
@@ -53587,7 +53977,7 @@ async function handleRunsList(argv) {
|
|
|
53587
53977
|
}
|
|
53588
53978
|
}
|
|
53589
53979
|
async function handleRunsGet(argv) {
|
|
53590
|
-
const run2 = getRun(
|
|
53980
|
+
const run2 = getRun(path46.resolve(argv.repo), argv.runId);
|
|
53591
53981
|
if (!run2) {
|
|
53592
53982
|
error(`Run not found: ${argv.runId}`);
|
|
53593
53983
|
process.exit(1);
|
|
@@ -53666,20 +54056,20 @@ function printNextSteps(auto2) {
|
|
|
53666
54056
|
}
|
|
53667
54057
|
|
|
53668
54058
|
// src/cli/commands/control.ts
|
|
53669
|
-
var
|
|
54059
|
+
var path48 = __toESM(require("path"));
|
|
53670
54060
|
init_control_config();
|
|
53671
54061
|
|
|
53672
54062
|
// src/core/control-unregister.ts
|
|
53673
|
-
var
|
|
53674
|
-
var
|
|
54063
|
+
var fs43 = __toESM(require("fs"));
|
|
54064
|
+
var path47 = __toESM(require("path"));
|
|
53675
54065
|
init_control_config();
|
|
53676
54066
|
function listUnregisterWorktreeCandidates(repoPath) {
|
|
53677
54067
|
const harnessRoot = canonicalizeControlRepoPath(repoPath);
|
|
53678
54068
|
const byPath = /* @__PURE__ */ new Map();
|
|
53679
54069
|
const add = (partial2) => {
|
|
53680
|
-
const resolved =
|
|
54070
|
+
const resolved = path47.resolve(partial2.worktreePath);
|
|
53681
54071
|
if (!resolved || resolved === harnessRoot) return;
|
|
53682
|
-
const exists = partial2.exists ??
|
|
54072
|
+
const exists = partial2.exists ?? fs43.existsSync(resolved);
|
|
53683
54073
|
const prev = byPath.get(resolved);
|
|
53684
54074
|
if (prev) {
|
|
53685
54075
|
byPath.set(resolved, {
|
|
@@ -53793,28 +54183,28 @@ async function teardownWorktrees(repoPath, candidates, dryRun) {
|
|
|
53793
54183
|
trigger: "cli"
|
|
53794
54184
|
});
|
|
53795
54185
|
if (result.code !== 0) {
|
|
53796
|
-
if (
|
|
53797
|
-
|
|
54186
|
+
if (fs43.existsSync(candidate.worktreePath)) {
|
|
54187
|
+
fs43.rmSync(candidate.worktreePath, { recursive: true, force: true });
|
|
53798
54188
|
}
|
|
53799
54189
|
}
|
|
53800
54190
|
outcomes.push({
|
|
53801
54191
|
path: candidate.worktreePath,
|
|
53802
54192
|
agentId: candidate.agentId,
|
|
53803
|
-
deleted: !
|
|
53804
|
-
error: result.code !== 0 &&
|
|
54193
|
+
deleted: !fs43.existsSync(candidate.worktreePath),
|
|
54194
|
+
error: result.code !== 0 && fs43.existsSync(candidate.worktreePath) ? result.stderr : void 0
|
|
53805
54195
|
});
|
|
53806
54196
|
} catch (err) {
|
|
53807
54197
|
const message = err instanceof Error ? err.message : String(err);
|
|
53808
54198
|
try {
|
|
53809
|
-
if (
|
|
53810
|
-
|
|
54199
|
+
if (fs43.existsSync(candidate.worktreePath)) {
|
|
54200
|
+
fs43.rmSync(candidate.worktreePath, { recursive: true, force: true });
|
|
53811
54201
|
}
|
|
53812
54202
|
} catch {
|
|
53813
54203
|
}
|
|
53814
54204
|
outcomes.push({
|
|
53815
54205
|
path: candidate.worktreePath,
|
|
53816
54206
|
agentId: candidate.agentId,
|
|
53817
|
-
deleted: !
|
|
54207
|
+
deleted: !fs43.existsSync(candidate.worktreePath),
|
|
53818
54208
|
error: message
|
|
53819
54209
|
});
|
|
53820
54210
|
}
|
|
@@ -53996,7 +54386,7 @@ async function handleDown() {
|
|
|
53996
54386
|
process.exit(code);
|
|
53997
54387
|
}
|
|
53998
54388
|
async function handleRegister(argv) {
|
|
53999
|
-
const repoPath =
|
|
54389
|
+
const repoPath = path48.resolve(argv.repo);
|
|
54000
54390
|
header("har control register");
|
|
54001
54391
|
info(`Repository: ${repoPath}`);
|
|
54002
54392
|
try {
|
|
@@ -54020,7 +54410,7 @@ async function handleRegister(argv) {
|
|
|
54020
54410
|
}
|
|
54021
54411
|
}
|
|
54022
54412
|
async function handleUnregister(argv) {
|
|
54023
|
-
const repoPath =
|
|
54413
|
+
const repoPath = path48.resolve(argv.repo);
|
|
54024
54414
|
const worktrees = listUnregisterWorktreeCandidates(repoPath);
|
|
54025
54415
|
try {
|
|
54026
54416
|
let deleteWorktrees = argv.deleteWorktrees;
|
|
@@ -54089,7 +54479,7 @@ async function handleUnregister(argv) {
|
|
|
54089
54479
|
}
|
|
54090
54480
|
}
|
|
54091
54481
|
async function handleSync(argv) {
|
|
54092
|
-
const repoPath =
|
|
54482
|
+
const repoPath = path48.resolve(argv.repo);
|
|
54093
54483
|
try {
|
|
54094
54484
|
await syncRepoWithControl({
|
|
54095
54485
|
repoPath,
|
|
@@ -54128,7 +54518,7 @@ async function handleWatch(argv) {
|
|
|
54128
54518
|
};
|
|
54129
54519
|
const tick = async () => {
|
|
54130
54520
|
if (argv.repo) {
|
|
54131
|
-
await syncOne(
|
|
54521
|
+
await syncOne(path48.resolve(argv.repo));
|
|
54132
54522
|
return;
|
|
54133
54523
|
}
|
|
54134
54524
|
try {
|
|
@@ -54159,11 +54549,11 @@ async function handleLogin(argv) {
|
|
|
54159
54549
|
}
|
|
54160
54550
|
|
|
54161
54551
|
// src/cli/commands/hooks.ts
|
|
54162
|
-
var
|
|
54552
|
+
var path50 = __toESM(require("path"));
|
|
54163
54553
|
|
|
54164
54554
|
// src/core/claude-hooks.ts
|
|
54165
|
-
var
|
|
54166
|
-
var
|
|
54555
|
+
var fs44 = __toESM(require("fs"));
|
|
54556
|
+
var path49 = __toESM(require("path"));
|
|
54167
54557
|
var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
|
|
54168
54558
|
var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
|
|
54169
54559
|
var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
|
|
@@ -54174,8 +54564,8 @@ function isHarGuardEntry(entry) {
|
|
|
54174
54564
|
);
|
|
54175
54565
|
}
|
|
54176
54566
|
function readSettings(settingsPath) {
|
|
54177
|
-
if (!
|
|
54178
|
-
const raw =
|
|
54567
|
+
if (!fs44.existsSync(settingsPath)) return {};
|
|
54568
|
+
const raw = fs44.readFileSync(settingsPath, "utf8").trim();
|
|
54179
54569
|
if (raw === "") return {};
|
|
54180
54570
|
const parsed = JSON.parse(raw);
|
|
54181
54571
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -54184,19 +54574,19 @@ function readSettings(settingsPath) {
|
|
|
54184
54574
|
return parsed;
|
|
54185
54575
|
}
|
|
54186
54576
|
function writeSettings(settingsPath, settings) {
|
|
54187
|
-
|
|
54188
|
-
|
|
54577
|
+
fs44.mkdirSync(path49.dirname(settingsPath), { recursive: true });
|
|
54578
|
+
fs44.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
54189
54579
|
}
|
|
54190
54580
|
function installClaudeGuard(repoPath) {
|
|
54191
54581
|
const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
|
|
54192
54582
|
if (!templatePath) {
|
|
54193
54583
|
throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
|
|
54194
54584
|
}
|
|
54195
|
-
const guardScript =
|
|
54196
|
-
|
|
54197
|
-
|
|
54198
|
-
|
|
54199
|
-
const settingsPath =
|
|
54585
|
+
const guardScript = path49.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
54586
|
+
fs44.mkdirSync(path49.dirname(guardScript), { recursive: true });
|
|
54587
|
+
fs44.copyFileSync(templatePath, guardScript);
|
|
54588
|
+
fs44.chmodSync(guardScript, 493);
|
|
54589
|
+
const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
54200
54590
|
const settings = readSettings(settingsPath);
|
|
54201
54591
|
const hooks = settings.hooks ?? {};
|
|
54202
54592
|
const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
|
|
@@ -54210,15 +54600,15 @@ function installClaudeGuard(repoPath) {
|
|
|
54210
54600
|
}
|
|
54211
54601
|
function uninstallClaudeGuard(repoPath) {
|
|
54212
54602
|
let removed = false;
|
|
54213
|
-
const guardScript =
|
|
54214
|
-
if (
|
|
54215
|
-
|
|
54603
|
+
const guardScript = path49.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
54604
|
+
if (fs44.existsSync(guardScript)) {
|
|
54605
|
+
fs44.rmSync(guardScript);
|
|
54216
54606
|
removed = true;
|
|
54217
|
-
const parent =
|
|
54218
|
-
if (
|
|
54607
|
+
const parent = path49.dirname(guardScript);
|
|
54608
|
+
if (fs44.existsSync(parent) && fs44.readdirSync(parent).length === 0) fs44.rmdirSync(parent);
|
|
54219
54609
|
}
|
|
54220
|
-
const settingsPath =
|
|
54221
|
-
if (
|
|
54610
|
+
const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
54611
|
+
if (fs44.existsSync(settingsPath)) {
|
|
54222
54612
|
const settings = readSettings(settingsPath);
|
|
54223
54613
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
54224
54614
|
if (preToolUse) {
|
|
@@ -54243,8 +54633,8 @@ function uninstallClaudeGuard(repoPath) {
|
|
|
54243
54633
|
return { removed };
|
|
54244
54634
|
}
|
|
54245
54635
|
function claudeGuardInstalled(repoPath) {
|
|
54246
|
-
const settingsPath =
|
|
54247
|
-
if (!
|
|
54636
|
+
const settingsPath = path49.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
54637
|
+
if (!fs44.existsSync(settingsPath)) return false;
|
|
54248
54638
|
try {
|
|
54249
54639
|
const settings = readSettings(settingsPath);
|
|
54250
54640
|
return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
|
|
@@ -54260,7 +54650,7 @@ function repoOption(y2) {
|
|
|
54260
54650
|
function handleInstall2(argv) {
|
|
54261
54651
|
try {
|
|
54262
54652
|
if (argv.claude) {
|
|
54263
|
-
const result2 = installClaudeGuard(
|
|
54653
|
+
const result2 = installClaudeGuard(path50.resolve(argv.repo));
|
|
54264
54654
|
success("Claude Code worktree guard installed.");
|
|
54265
54655
|
info(`Guard script: ${result2.guardScript}`);
|
|
54266
54656
|
info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
|
|
@@ -54268,7 +54658,7 @@ function handleInstall2(argv) {
|
|
|
54268
54658
|
info("Commit both files so the guard travels with the repo.");
|
|
54269
54659
|
return;
|
|
54270
54660
|
}
|
|
54271
|
-
const result = installHooks({ repoPath:
|
|
54661
|
+
const result = installHooks({ repoPath: path50.resolve(argv.repo), force: argv.force });
|
|
54272
54662
|
success(`Commit gate installed in ${result.hooksDir}`);
|
|
54273
54663
|
info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
|
|
54274
54664
|
info("Commits of unverified change batches will be blocked in agent worktrees.");
|
|
@@ -54281,7 +54671,7 @@ function handleInstall2(argv) {
|
|
|
54281
54671
|
function handleUninstall(argv) {
|
|
54282
54672
|
try {
|
|
54283
54673
|
if (argv.claude) {
|
|
54284
|
-
const result2 = uninstallClaudeGuard(
|
|
54674
|
+
const result2 = uninstallClaudeGuard(path50.resolve(argv.repo));
|
|
54285
54675
|
if (result2.removed) {
|
|
54286
54676
|
success("Claude Code worktree guard removed.");
|
|
54287
54677
|
} else {
|
|
@@ -54289,7 +54679,7 @@ function handleUninstall(argv) {
|
|
|
54289
54679
|
}
|
|
54290
54680
|
return;
|
|
54291
54681
|
}
|
|
54292
|
-
const result = uninstallHooks(
|
|
54682
|
+
const result = uninstallHooks(path50.resolve(argv.repo));
|
|
54293
54683
|
if (result.removed) {
|
|
54294
54684
|
success(`Commit gate removed from ${result.hooksDir}`);
|
|
54295
54685
|
} else {
|
|
@@ -54302,7 +54692,7 @@ function handleUninstall(argv) {
|
|
|
54302
54692
|
}
|
|
54303
54693
|
function handleStatus2(argv) {
|
|
54304
54694
|
try {
|
|
54305
|
-
const status = getHooksStatus(
|
|
54695
|
+
const status = getHooksStatus(path50.resolve(argv.repo));
|
|
54306
54696
|
if (argv.json) {
|
|
54307
54697
|
process.stdout.write(`${JSON.stringify(status, null, 2)}
|
|
54308
54698
|
`);
|
|
@@ -54320,7 +54710,7 @@ function handleStatus2(argv) {
|
|
|
54320
54710
|
);
|
|
54321
54711
|
info(`Effective: ${status.effectiveMode} (in this checkout)`);
|
|
54322
54712
|
info(
|
|
54323
|
-
`Claude guard: ${claudeGuardInstalled(
|
|
54713
|
+
`Claude guard: ${claudeGuardInstalled(path50.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
|
|
54324
54714
|
);
|
|
54325
54715
|
} catch (err) {
|
|
54326
54716
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -54581,10 +54971,10 @@ function assignProp(target, prop, value) {
|
|
|
54581
54971
|
configurable: true
|
|
54582
54972
|
});
|
|
54583
54973
|
}
|
|
54584
|
-
function getElementAtPath(obj,
|
|
54585
|
-
if (!
|
|
54974
|
+
function getElementAtPath(obj, path53) {
|
|
54975
|
+
if (!path53)
|
|
54586
54976
|
return obj;
|
|
54587
|
-
return
|
|
54977
|
+
return path53.reduce((acc, key) => acc?.[key], obj);
|
|
54588
54978
|
}
|
|
54589
54979
|
function promiseAllObject(promisesObj) {
|
|
54590
54980
|
const keys = Object.keys(promisesObj);
|
|
@@ -54904,11 +55294,11 @@ function aborted(x2, startIndex = 0) {
|
|
|
54904
55294
|
}
|
|
54905
55295
|
return false;
|
|
54906
55296
|
}
|
|
54907
|
-
function prefixIssues(
|
|
55297
|
+
function prefixIssues(path53, issues) {
|
|
54908
55298
|
return issues.map((iss) => {
|
|
54909
55299
|
var _a3;
|
|
54910
55300
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
54911
|
-
iss.path.unshift(
|
|
55301
|
+
iss.path.unshift(path53);
|
|
54912
55302
|
return iss;
|
|
54913
55303
|
});
|
|
54914
55304
|
}
|
|
@@ -61382,7 +61772,7 @@ var Server = class extends Protocol {
|
|
|
61382
61772
|
};
|
|
61383
61773
|
|
|
61384
61774
|
// src/mcp/server.ts
|
|
61385
|
-
var
|
|
61775
|
+
var path51 = __toESM(require("path"));
|
|
61386
61776
|
|
|
61387
61777
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
61388
61778
|
var import_node_process2 = __toESM(require("node:process"), 1);
|
|
@@ -61553,13 +61943,20 @@ var LaunchEnvironmentInputSchema = external_exports.object({
|
|
|
61553
61943
|
force: external_exports.boolean().default(false).describe(
|
|
61554
61944
|
"Discard uncommitted changes in a dirty occupied worktree. Requires confirmReplace=true and explicit user approval \u2014 never set autonomously."
|
|
61555
61945
|
),
|
|
61556
|
-
resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree.")
|
|
61946
|
+
resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree."),
|
|
61947
|
+
workUnitId: external_exports.string().min(1).max(128).optional(),
|
|
61948
|
+
source: external_exports.string().min(1).max(64).optional(),
|
|
61949
|
+
sourceUrl: external_exports.string().url().optional(),
|
|
61950
|
+
title: external_exports.string().min(1).max(256).optional(),
|
|
61951
|
+
parentWorkUnitId: external_exports.string().min(1).max(128).optional()
|
|
61557
61952
|
});
|
|
61558
61953
|
var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
|
|
61559
61954
|
previewUrls: external_exports.record(external_exports.string()).optional(),
|
|
61560
61955
|
workDir: external_exports.string().optional().describe("Where the session code lives \u2014 ALL file edits must go under this path"),
|
|
61561
61956
|
worktreePath: external_exports.string().optional(),
|
|
61562
61957
|
branch: external_exports.string().optional(),
|
|
61958
|
+
workUnitId: external_exports.string().optional(),
|
|
61959
|
+
attemptId: external_exports.string().uuid().optional(),
|
|
61563
61960
|
blocked: external_exports.boolean().optional(),
|
|
61564
61961
|
occupiedSlot: external_exports.object({
|
|
61565
61962
|
agentId: external_exports.number().int(),
|
|
@@ -61692,6 +62089,17 @@ var HAR_MCP_TOOLS = [
|
|
|
61692
62089
|
resume: {
|
|
61693
62090
|
type: "boolean",
|
|
61694
62091
|
description: "Resume a failed or partial launch (status failed/starting) without confirmReplace. Preserves worktree and env."
|
|
62092
|
+
},
|
|
62093
|
+
workUnitId: {
|
|
62094
|
+
type: "string",
|
|
62095
|
+
description: "Durable external work identifier to bind to this session."
|
|
62096
|
+
},
|
|
62097
|
+
source: { type: "string", description: "Optional provider/source name." },
|
|
62098
|
+
sourceUrl: { type: "string", description: "Optional source URL." },
|
|
62099
|
+
title: { type: "string", description: "Optional human-readable work title." },
|
|
62100
|
+
parentWorkUnitId: {
|
|
62101
|
+
type: "string",
|
|
62102
|
+
description: "Optional parent work unit identifier."
|
|
61695
62103
|
}
|
|
61696
62104
|
},
|
|
61697
62105
|
["agentId"]
|
|
@@ -61875,6 +62283,11 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
61875
62283
|
confirmReplace: input.confirmReplace,
|
|
61876
62284
|
force: input.force,
|
|
61877
62285
|
resume: input.resume,
|
|
62286
|
+
workUnitId: input.workUnitId,
|
|
62287
|
+
source: input.source,
|
|
62288
|
+
sourceUrl: input.sourceUrl,
|
|
62289
|
+
title: input.title,
|
|
62290
|
+
parentWorkUnitId: input.parentWorkUnitId,
|
|
61878
62291
|
capture: true
|
|
61879
62292
|
});
|
|
61880
62293
|
const parsed = LaunchEnvironmentOutputSchema.parse(result);
|
|
@@ -61894,6 +62307,11 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
61894
62307
|
confirmReplace: false,
|
|
61895
62308
|
force: false,
|
|
61896
62309
|
resume: true,
|
|
62310
|
+
workUnitId: input.workUnitId,
|
|
62311
|
+
source: input.source,
|
|
62312
|
+
sourceUrl: input.sourceUrl,
|
|
62313
|
+
title: input.title,
|
|
62314
|
+
parentWorkUnitId: input.parentWorkUnitId,
|
|
61897
62315
|
capture: true
|
|
61898
62316
|
});
|
|
61899
62317
|
const parsed = LaunchEnvironmentOutputSchema.parse(result);
|
|
@@ -62014,7 +62432,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
62014
62432
|
const input = ControlUpInputSchema.parse({ ...args, repo });
|
|
62015
62433
|
const result = await startControlAndSync({
|
|
62016
62434
|
detach: input.detach,
|
|
62017
|
-
cwd:
|
|
62435
|
+
cwd: path51.resolve(input.repo)
|
|
62018
62436
|
});
|
|
62019
62437
|
if (result.code !== 0) {
|
|
62020
62438
|
return {
|
|
@@ -64128,9 +64546,9 @@ var import_run_async = __toESM(require_run_async(), 1);
|
|
|
64128
64546
|
var import_mute_stream2 = __toESM(require_lib3(), 1);
|
|
64129
64547
|
var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
|
|
64130
64548
|
var _2 = {
|
|
64131
|
-
set: (obj,
|
|
64549
|
+
set: (obj, path53 = "", value) => {
|
|
64132
64550
|
let pointer = obj;
|
|
64133
|
-
|
|
64551
|
+
path53.split(".").forEach((key, index, arr) => {
|
|
64134
64552
|
if (key === "__proto__" || key === "constructor")
|
|
64135
64553
|
return;
|
|
64136
64554
|
if (index === arr.length - 1) {
|
|
@@ -64141,8 +64559,8 @@ var _2 = {
|
|
|
64141
64559
|
pointer = pointer[key];
|
|
64142
64560
|
});
|
|
64143
64561
|
},
|
|
64144
|
-
get: (obj,
|
|
64145
|
-
const travel = (regexp) => String.prototype.split.call(
|
|
64562
|
+
get: (obj, path53 = "", defaultValue) => {
|
|
64563
|
+
const travel = (regexp) => String.prototype.split.call(path53, regexp).filter(Boolean).reduce(
|
|
64146
64564
|
// @ts-expect-error implicit any on res[key]
|
|
64147
64565
|
(res, key) => res !== null && res !== void 0 ? res[key] : res,
|
|
64148
64566
|
obj
|
|
@@ -64506,7 +64924,7 @@ var preferencesCommand = {
|
|
|
64506
64924
|
};
|
|
64507
64925
|
|
|
64508
64926
|
// src/cli/commands/telemetry.ts
|
|
64509
|
-
var
|
|
64927
|
+
var path52 = __toESM(require("path"));
|
|
64510
64928
|
init_control_config();
|
|
64511
64929
|
init_otel_hooks();
|
|
64512
64930
|
init_telemetry_config();
|
|
@@ -64591,7 +65009,7 @@ async function handleOff() {
|
|
|
64591
65009
|
info("Mission Control will not auto-start. Existing usage rows are kept.");
|
|
64592
65010
|
}
|
|
64593
65011
|
async function handleWriteEnv(argv) {
|
|
64594
|
-
const repoPath =
|
|
65012
|
+
const repoPath = path52.resolve(argv.repo);
|
|
64595
65013
|
const harnessRoot = resolveHarnessRoot(repoPath);
|
|
64596
65014
|
const session = readSlotRegistry(harnessRoot, argv.agentId);
|
|
64597
65015
|
const workDir = argv.workDir ?? session?.workDir ?? repoPath;
|
|
@@ -64603,7 +65021,7 @@ async function handleWriteEnv(argv) {
|
|
|
64603
65021
|
suffix,
|
|
64604
65022
|
createdAt: session?.createdAt
|
|
64605
65023
|
});
|
|
64606
|
-
const envFile = argv.envFile ??
|
|
65024
|
+
const envFile = argv.envFile ?? path52.join(workDir, `.env.agent.${argv.agentId}`);
|
|
64607
65025
|
const attrs = {
|
|
64608
65026
|
sessionKey,
|
|
64609
65027
|
agentId: argv.agentId,
|
|
@@ -64622,7 +65040,7 @@ async function handleWriteEnv(argv) {
|
|
|
64622
65040
|
success(`Wrote session attribution to ${envFile}`);
|
|
64623
65041
|
}
|
|
64624
65042
|
function handlePrintEnv(argv) {
|
|
64625
|
-
const repoPath =
|
|
65043
|
+
const repoPath = path52.resolve(argv.repo);
|
|
64626
65044
|
const workDir = argv.workDir ?? repoPath;
|
|
64627
65045
|
const sessionKey = buildSessionKey({
|
|
64628
65046
|
branch: argv.branch,
|