@osfactory/har 0.37.0 → 0.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +450 -493
- package/dist/templates/adaptation-prompt-init.md +1 -1
- package/dist/templates/agent-skills/har-wt.md +2 -2
- package/dist/templates/cursor-rule.mdc.template +2 -3
- package/dist/templates/har-boilerplate/CLAUDE.agent.md +1 -1
- package/dist/templates/har-boilerplate/README.md +4 -4
- package/dist/templates/har-boilerplate/agent-cli.sh +1 -1
- package/dist/templates/har-boilerplate/agent-slot.sh +24 -66
- package/dist/templates/har-boilerplate/launch.sh +6 -15
- package/dist/templates/har-boilerplate/preflight.sh +3 -12
- package/dist/templates/har-boilerplate-cli/CLAUDE.agent.md +1 -1
- package/dist/templates/har-boilerplate-cli/README.md +3 -3
- package/dist/templates/har-boilerplate-cli/agent-slot.sh +24 -64
- package/dist/templates/har-boilerplate-cli/launch.sh +6 -14
- package/dist/templates/har-boilerplate-cli/preflight.sh +3 -12
- package/dist/templates/har-boilerplate-ios/CLAUDE.agent.md +1 -1
- package/dist/templates/har-boilerplate-ios/README.md +3 -3
- package/dist/templates/har-boilerplate-ios/agent-slot.sh +15 -48
- package/dist/templates/har-boilerplate-ios/launch.sh +9 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -873,14 +873,14 @@ var require_url_state_machine = __commonJS({
|
|
|
873
873
|
return url.replace(/\u0009|\u000A|\u000D/g, "");
|
|
874
874
|
}
|
|
875
875
|
function shortenPath(url) {
|
|
876
|
-
const
|
|
877
|
-
if (
|
|
876
|
+
const path62 = url.path;
|
|
877
|
+
if (path62.length === 0) {
|
|
878
878
|
return;
|
|
879
879
|
}
|
|
880
|
-
if (url.scheme === "file" &&
|
|
880
|
+
if (url.scheme === "file" && path62.length === 1 && isNormalizedWindowsDriveLetter(path62[0])) {
|
|
881
881
|
return;
|
|
882
882
|
}
|
|
883
|
-
|
|
883
|
+
path62.pop();
|
|
884
884
|
}
|
|
885
885
|
function includesCredentials(url) {
|
|
886
886
|
return url.username !== "" || url.password !== "";
|
|
@@ -2200,7 +2200,7 @@ var require_lib2 = __commonJS({
|
|
|
2200
2200
|
let accum = [];
|
|
2201
2201
|
let accumBytes = 0;
|
|
2202
2202
|
let abort = false;
|
|
2203
|
-
return new Body.Promise(function(
|
|
2203
|
+
return new Body.Promise(function(resolve46, reject) {
|
|
2204
2204
|
let resTimeout;
|
|
2205
2205
|
if (_this4.timeout) {
|
|
2206
2206
|
resTimeout = setTimeout(function() {
|
|
@@ -2234,7 +2234,7 @@ var require_lib2 = __commonJS({
|
|
|
2234
2234
|
}
|
|
2235
2235
|
clearTimeout(resTimeout);
|
|
2236
2236
|
try {
|
|
2237
|
-
|
|
2237
|
+
resolve46(Buffer.concat(accum, accumBytes));
|
|
2238
2238
|
} catch (err) {
|
|
2239
2239
|
reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, "system", err));
|
|
2240
2240
|
}
|
|
@@ -2909,7 +2909,7 @@ var require_lib2 = __commonJS({
|
|
|
2909
2909
|
throw new Error("native promise missing, set fetch.Promise to your favorite alternative");
|
|
2910
2910
|
}
|
|
2911
2911
|
Body.Promise = fetch3.Promise;
|
|
2912
|
-
return new fetch3.Promise(function(
|
|
2912
|
+
return new fetch3.Promise(function(resolve46, reject) {
|
|
2913
2913
|
const request = new Request3(url, opts);
|
|
2914
2914
|
const options = getNodeRequestOptions(request);
|
|
2915
2915
|
const send = (options.protocol === "https:" ? https : http2).request;
|
|
@@ -3042,7 +3042,7 @@ var require_lib2 = __commonJS({
|
|
|
3042
3042
|
requestOpts.body = void 0;
|
|
3043
3043
|
requestOpts.headers.delete("content-length");
|
|
3044
3044
|
}
|
|
3045
|
-
|
|
3045
|
+
resolve46(fetch3(new Request3(locationURL, requestOpts)));
|
|
3046
3046
|
finalize();
|
|
3047
3047
|
return;
|
|
3048
3048
|
}
|
|
@@ -3063,7 +3063,7 @@ var require_lib2 = __commonJS({
|
|
|
3063
3063
|
const codings = headers.get("Content-Encoding");
|
|
3064
3064
|
if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
|
|
3065
3065
|
response = new Response3(body, response_options);
|
|
3066
|
-
|
|
3066
|
+
resolve46(response);
|
|
3067
3067
|
return;
|
|
3068
3068
|
}
|
|
3069
3069
|
const zlibOptions = {
|
|
@@ -3073,7 +3073,7 @@ var require_lib2 = __commonJS({
|
|
|
3073
3073
|
if (codings == "gzip" || codings == "x-gzip") {
|
|
3074
3074
|
body = body.pipe(zlib.createGunzip(zlibOptions));
|
|
3075
3075
|
response = new Response3(body, response_options);
|
|
3076
|
-
|
|
3076
|
+
resolve46(response);
|
|
3077
3077
|
return;
|
|
3078
3078
|
}
|
|
3079
3079
|
if (codings == "deflate" || codings == "x-deflate") {
|
|
@@ -3085,12 +3085,12 @@ var require_lib2 = __commonJS({
|
|
|
3085
3085
|
body = body.pipe(zlib.createInflateRaw());
|
|
3086
3086
|
}
|
|
3087
3087
|
response = new Response3(body, response_options);
|
|
3088
|
-
|
|
3088
|
+
resolve46(response);
|
|
3089
3089
|
});
|
|
3090
3090
|
raw.on("end", function() {
|
|
3091
3091
|
if (!response) {
|
|
3092
3092
|
response = new Response3(body, response_options);
|
|
3093
|
-
|
|
3093
|
+
resolve46(response);
|
|
3094
3094
|
}
|
|
3095
3095
|
});
|
|
3096
3096
|
return;
|
|
@@ -3098,11 +3098,11 @@ var require_lib2 = __commonJS({
|
|
|
3098
3098
|
if (codings == "br" && typeof zlib.createBrotliDecompress === "function") {
|
|
3099
3099
|
body = body.pipe(zlib.createBrotliDecompress());
|
|
3100
3100
|
response = new Response3(body, response_options);
|
|
3101
|
-
|
|
3101
|
+
resolve46(response);
|
|
3102
3102
|
return;
|
|
3103
3103
|
}
|
|
3104
3104
|
response = new Response3(body, response_options);
|
|
3105
|
-
|
|
3105
|
+
resolve46(response);
|
|
3106
3106
|
});
|
|
3107
3107
|
writeToStream(req, request);
|
|
3108
3108
|
});
|
|
@@ -6459,14 +6459,14 @@ __export(fileFromPath_exports, {
|
|
|
6459
6459
|
fileFromPathSync: () => fileFromPathSync,
|
|
6460
6460
|
isFile: () => isFile
|
|
6461
6461
|
});
|
|
6462
|
-
function createFileFromPath(
|
|
6462
|
+
function createFileFromPath(path62, { mtimeMs, size }, filenameOrOptions, options = {}) {
|
|
6463
6463
|
let filename;
|
|
6464
6464
|
if (isPlainObject_default2(filenameOrOptions)) {
|
|
6465
6465
|
[options, filename] = [filenameOrOptions, void 0];
|
|
6466
6466
|
} else {
|
|
6467
6467
|
filename = filenameOrOptions;
|
|
6468
6468
|
}
|
|
6469
|
-
const file = new FileFromPath({ path:
|
|
6469
|
+
const file = new FileFromPath({ path: path62, size, lastModified: mtimeMs });
|
|
6470
6470
|
if (!filename) {
|
|
6471
6471
|
filename = file.name;
|
|
6472
6472
|
}
|
|
@@ -6475,13 +6475,13 @@ function createFileFromPath(path61, { mtimeMs, size }, filenameOrOptions, option
|
|
|
6475
6475
|
lastModified: file.lastModified
|
|
6476
6476
|
});
|
|
6477
6477
|
}
|
|
6478
|
-
function fileFromPathSync(
|
|
6479
|
-
const stats = (0, import_fs5.statSync)(
|
|
6480
|
-
return createFileFromPath(
|
|
6478
|
+
function fileFromPathSync(path62, filenameOrOptions, options = {}) {
|
|
6479
|
+
const stats = (0, import_fs5.statSync)(path62);
|
|
6480
|
+
return createFileFromPath(path62, stats, filenameOrOptions, options);
|
|
6481
6481
|
}
|
|
6482
|
-
async function fileFromPath2(
|
|
6483
|
-
const stats = await import_fs5.promises.stat(
|
|
6484
|
-
return createFileFromPath(
|
|
6482
|
+
async function fileFromPath2(path62, filenameOrOptions, options) {
|
|
6483
|
+
const stats = await import_fs5.promises.stat(path62);
|
|
6484
|
+
return createFileFromPath(path62, stats, filenameOrOptions, options);
|
|
6485
6485
|
}
|
|
6486
6486
|
var import_fs5, import_path5, import_node_domexception, __classPrivateFieldSet5, __classPrivateFieldGet6, _FileFromPath_path, _FileFromPath_start, MESSAGE, FileFromPath;
|
|
6487
6487
|
var init_fileFromPath = __esm({
|
|
@@ -6640,25 +6640,25 @@ __export(otel_hooks_exports, {
|
|
|
6640
6640
|
});
|
|
6641
6641
|
function getOtelHooksHome() {
|
|
6642
6642
|
if (process.env.HAR_OTEL_HOOKS_HOME) {
|
|
6643
|
-
return
|
|
6643
|
+
return path47.resolve(process.env.HAR_OTEL_HOOKS_HOME);
|
|
6644
6644
|
}
|
|
6645
|
-
return
|
|
6645
|
+
return path47.join(os14.homedir(), ".har", "otel-hooks");
|
|
6646
6646
|
}
|
|
6647
6647
|
function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
|
|
6648
|
-
return
|
|
6648
|
+
return path47.join(hooksHome, "otel_config.json");
|
|
6649
6649
|
}
|
|
6650
6650
|
function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
|
|
6651
|
-
return
|
|
6651
|
+
return path47.join(hooksHome, "run-otel-hook.sh");
|
|
6652
6652
|
}
|
|
6653
6653
|
function getOtelHooksStateDir(hooksHome = getOtelHooksHome()) {
|
|
6654
|
-
return
|
|
6654
|
+
return path47.join(hooksHome, "state");
|
|
6655
6655
|
}
|
|
6656
6656
|
function localOtelHookBin(hooksHome) {
|
|
6657
|
-
return
|
|
6657
|
+
return path47.join(hooksHome, "node_modules", ".bin", "otel-hook");
|
|
6658
6658
|
}
|
|
6659
6659
|
function installedPackageVersion(hooksHome) {
|
|
6660
6660
|
try {
|
|
6661
|
-
const pkgPath =
|
|
6661
|
+
const pkgPath = path47.join(
|
|
6662
6662
|
hooksHome,
|
|
6663
6663
|
"node_modules",
|
|
6664
6664
|
"@osfactory",
|
|
@@ -6793,9 +6793,9 @@ function uninstallLegacyPythonHooks(hooksHome) {
|
|
|
6793
6793
|
}
|
|
6794
6794
|
function removeLegacyPythonArtifacts(hooksHome) {
|
|
6795
6795
|
const legacyPaths = [
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6796
|
+
path47.join(hooksHome, ".venv"),
|
|
6797
|
+
path47.join(hooksHome, "otel_config.yaml"),
|
|
6798
|
+
path47.join(hooksHome, "venv")
|
|
6799
6799
|
];
|
|
6800
6800
|
for (const target of legacyPaths) {
|
|
6801
6801
|
try {
|
|
@@ -6941,14 +6941,14 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
|
|
|
6941
6941
|
function rewriteKnownHookRegistrations(wrapperPath) {
|
|
6942
6942
|
const home = os14.homedir();
|
|
6943
6943
|
const candidates = [
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6944
|
+
path47.join(home, ".cursor", "hooks.json"),
|
|
6945
|
+
path47.join(home, ".claude", "settings.json"),
|
|
6946
|
+
path47.join(home, ".codex", "hooks.json")
|
|
6947
6947
|
];
|
|
6948
6948
|
for (const filePath of candidates) {
|
|
6949
6949
|
try {
|
|
6950
6950
|
rewriteHookCommandsToWrapper(filePath, wrapperPath);
|
|
6951
|
-
if (filePath.endsWith(`${
|
|
6951
|
+
if (filePath.endsWith(`${path47.sep}.cursor${path47.sep}hooks.json`)) {
|
|
6952
6952
|
pruneLegacyCursorHookEvents(filePath, wrapperPath);
|
|
6953
6953
|
}
|
|
6954
6954
|
} catch {
|
|
@@ -7058,14 +7058,14 @@ function ensureOtelHooks(options) {
|
|
|
7058
7058
|
function disableOtelHooksExport() {
|
|
7059
7059
|
return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
|
|
7060
7060
|
}
|
|
7061
|
-
var import_child_process10, fs43, os14,
|
|
7061
|
+
var import_child_process10, fs43, os14, path47, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
|
|
7062
7062
|
var init_otel_hooks = __esm({
|
|
7063
7063
|
"src/core/otel-hooks.ts"() {
|
|
7064
7064
|
"use strict";
|
|
7065
7065
|
import_child_process10 = require("child_process");
|
|
7066
7066
|
fs43 = __toESM(require("fs"));
|
|
7067
7067
|
os14 = __toESM(require("os"));
|
|
7068
|
-
|
|
7068
|
+
path47 = __toESM(require("path"));
|
|
7069
7069
|
init_control_config();
|
|
7070
7070
|
init_telemetry_config();
|
|
7071
7071
|
OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.1.2";
|
|
@@ -8181,15 +8181,15 @@ var require_route = __commonJS({
|
|
|
8181
8181
|
};
|
|
8182
8182
|
}
|
|
8183
8183
|
function wrapConversion(toModel, graph) {
|
|
8184
|
-
const
|
|
8184
|
+
const path62 = [graph[toModel].parent, toModel];
|
|
8185
8185
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
8186
8186
|
let cur = graph[toModel].parent;
|
|
8187
8187
|
while (graph[cur].parent) {
|
|
8188
|
-
|
|
8188
|
+
path62.unshift(graph[cur].parent);
|
|
8189
8189
|
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
8190
8190
|
cur = graph[cur].parent;
|
|
8191
8191
|
}
|
|
8192
|
-
fn.conversion =
|
|
8192
|
+
fn.conversion = path62;
|
|
8193
8193
|
return fn;
|
|
8194
8194
|
}
|
|
8195
8195
|
module2.exports = function(fromModel) {
|
|
@@ -17679,16 +17679,16 @@ var require_os_tmpdir = __commonJS({
|
|
|
17679
17679
|
var isWindows = process.platform === "win32";
|
|
17680
17680
|
var trailingSlashRe = isWindows ? /[^:]\\$/ : /.\/$/;
|
|
17681
17681
|
module2.exports = function() {
|
|
17682
|
-
var
|
|
17682
|
+
var path62;
|
|
17683
17683
|
if (isWindows) {
|
|
17684
|
-
|
|
17684
|
+
path62 = process.env.TEMP || process.env.TMP || (process.env.SystemRoot || process.env.windir) + "\\temp";
|
|
17685
17685
|
} else {
|
|
17686
|
-
|
|
17686
|
+
path62 = process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp";
|
|
17687
17687
|
}
|
|
17688
|
-
if (trailingSlashRe.test(
|
|
17689
|
-
|
|
17688
|
+
if (trailingSlashRe.test(path62)) {
|
|
17689
|
+
path62 = path62.slice(0, -1);
|
|
17690
17690
|
}
|
|
17691
|
-
return
|
|
17691
|
+
return path62;
|
|
17692
17692
|
};
|
|
17693
17693
|
}
|
|
17694
17694
|
});
|
|
@@ -17697,7 +17697,7 @@ var require_os_tmpdir = __commonJS({
|
|
|
17697
17697
|
var require_tmp = __commonJS({
|
|
17698
17698
|
"node_modules/tmp/lib/tmp.js"(exports2, module2) {
|
|
17699
17699
|
var fs50 = require("fs");
|
|
17700
|
-
var
|
|
17700
|
+
var path62 = require("path");
|
|
17701
17701
|
var crypto6 = require("crypto");
|
|
17702
17702
|
var osTmpDir = require_os_tmpdir();
|
|
17703
17703
|
var _c2 = process.binding("constants");
|
|
@@ -17739,7 +17739,7 @@ var require_tmp = __commonJS({
|
|
|
17739
17739
|
}
|
|
17740
17740
|
function _generateTmpName(opts) {
|
|
17741
17741
|
if (opts.name) {
|
|
17742
|
-
return
|
|
17742
|
+
return path62.join(opts.dir || tmpDir, opts.name);
|
|
17743
17743
|
}
|
|
17744
17744
|
if (opts.template) {
|
|
17745
17745
|
return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
|
|
@@ -17750,7 +17750,7 @@ var require_tmp = __commonJS({
|
|
|
17750
17750
|
_randomChars(12),
|
|
17751
17751
|
opts.postfix || ""
|
|
17752
17752
|
].join("");
|
|
17753
|
-
return
|
|
17753
|
+
return path62.join(opts.dir || tmpDir, name);
|
|
17754
17754
|
}
|
|
17755
17755
|
function tmpName(options, callback) {
|
|
17756
17756
|
var args = _parseArguments(options, callback), opts = args[0], cb = args[1], tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
|
|
@@ -17835,7 +17835,7 @@ var require_tmp = __commonJS({
|
|
|
17835
17835
|
do {
|
|
17836
17836
|
var dir2 = dirs.pop(), deferred = false, files = fs50.readdirSync(dir2);
|
|
17837
17837
|
for (var i2 = 0, length = files.length; i2 < length; i2++) {
|
|
17838
|
-
var file2 =
|
|
17838
|
+
var file2 = path62.join(dir2, files[i2]), stat = fs50.lstatSync(file2);
|
|
17839
17839
|
if (stat.isDirectory()) {
|
|
17840
17840
|
if (!deferred) {
|
|
17841
17841
|
deferred = true;
|
|
@@ -19046,7 +19046,7 @@ var require_Observable = __commonJS({
|
|
|
19046
19046
|
Observable2.prototype.forEach = function(next, promiseCtor) {
|
|
19047
19047
|
var _this = this;
|
|
19048
19048
|
promiseCtor = getPromiseCtor(promiseCtor);
|
|
19049
|
-
return new promiseCtor(function(
|
|
19049
|
+
return new promiseCtor(function(resolve46, reject) {
|
|
19050
19050
|
var subscriber = new Subscriber_1.SafeSubscriber({
|
|
19051
19051
|
next: function(value) {
|
|
19052
19052
|
try {
|
|
@@ -19057,7 +19057,7 @@ var require_Observable = __commonJS({
|
|
|
19057
19057
|
}
|
|
19058
19058
|
},
|
|
19059
19059
|
error: reject,
|
|
19060
|
-
complete:
|
|
19060
|
+
complete: resolve46
|
|
19061
19061
|
});
|
|
19062
19062
|
_this.subscribe(subscriber);
|
|
19063
19063
|
});
|
|
@@ -19079,14 +19079,14 @@ var require_Observable = __commonJS({
|
|
|
19079
19079
|
Observable2.prototype.toPromise = function(promiseCtor) {
|
|
19080
19080
|
var _this = this;
|
|
19081
19081
|
promiseCtor = getPromiseCtor(promiseCtor);
|
|
19082
|
-
return new promiseCtor(function(
|
|
19082
|
+
return new promiseCtor(function(resolve46, reject) {
|
|
19083
19083
|
var value;
|
|
19084
19084
|
_this.subscribe(function(x2) {
|
|
19085
19085
|
return value = x2;
|
|
19086
19086
|
}, function(err) {
|
|
19087
19087
|
return reject(err);
|
|
19088
19088
|
}, function() {
|
|
19089
|
-
return
|
|
19089
|
+
return resolve46(value);
|
|
19090
19090
|
});
|
|
19091
19091
|
});
|
|
19092
19092
|
};
|
|
@@ -21182,11 +21182,11 @@ var require_innerFrom = __commonJS({
|
|
|
21182
21182
|
"use strict";
|
|
21183
21183
|
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P3, generator) {
|
|
21184
21184
|
function adopt(value) {
|
|
21185
|
-
return value instanceof P3 ? value : new P3(function(
|
|
21186
|
-
|
|
21185
|
+
return value instanceof P3 ? value : new P3(function(resolve46) {
|
|
21186
|
+
resolve46(value);
|
|
21187
21187
|
});
|
|
21188
21188
|
}
|
|
21189
|
-
return new (P3 || (P3 = Promise))(function(
|
|
21189
|
+
return new (P3 || (P3 = Promise))(function(resolve46, reject) {
|
|
21190
21190
|
function fulfilled(value) {
|
|
21191
21191
|
try {
|
|
21192
21192
|
step(generator.next(value));
|
|
@@ -21202,7 +21202,7 @@ var require_innerFrom = __commonJS({
|
|
|
21202
21202
|
}
|
|
21203
21203
|
}
|
|
21204
21204
|
function step(result) {
|
|
21205
|
-
result.done ?
|
|
21205
|
+
result.done ? resolve46(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
21206
21206
|
}
|
|
21207
21207
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
21208
21208
|
});
|
|
@@ -21284,14 +21284,14 @@ var require_innerFrom = __commonJS({
|
|
|
21284
21284
|
}, i2);
|
|
21285
21285
|
function verb(n2) {
|
|
21286
21286
|
i2[n2] = o2[n2] && function(v3) {
|
|
21287
|
-
return new Promise(function(
|
|
21288
|
-
v3 = o2[n2](v3), settle(
|
|
21287
|
+
return new Promise(function(resolve46, reject) {
|
|
21288
|
+
v3 = o2[n2](v3), settle(resolve46, reject, v3.done, v3.value);
|
|
21289
21289
|
});
|
|
21290
21290
|
};
|
|
21291
21291
|
}
|
|
21292
|
-
function settle(
|
|
21292
|
+
function settle(resolve46, reject, d2, v3) {
|
|
21293
21293
|
Promise.resolve(v3).then(function(v4) {
|
|
21294
|
-
|
|
21294
|
+
resolve46({ value: v4, done: d2 });
|
|
21295
21295
|
}, reject);
|
|
21296
21296
|
}
|
|
21297
21297
|
};
|
|
@@ -21910,7 +21910,7 @@ var require_lastValueFrom = __commonJS({
|
|
|
21910
21910
|
var EmptyError_1 = require_EmptyError();
|
|
21911
21911
|
function lastValueFrom2(source, config2) {
|
|
21912
21912
|
var hasConfig = typeof config2 === "object";
|
|
21913
|
-
return new Promise(function(
|
|
21913
|
+
return new Promise(function(resolve46, reject) {
|
|
21914
21914
|
var _hasValue = false;
|
|
21915
21915
|
var _value;
|
|
21916
21916
|
source.subscribe({
|
|
@@ -21921,9 +21921,9 @@ var require_lastValueFrom = __commonJS({
|
|
|
21921
21921
|
error: reject,
|
|
21922
21922
|
complete: function() {
|
|
21923
21923
|
if (_hasValue) {
|
|
21924
|
-
|
|
21924
|
+
resolve46(_value);
|
|
21925
21925
|
} else if (hasConfig) {
|
|
21926
|
-
|
|
21926
|
+
resolve46(config2.defaultValue);
|
|
21927
21927
|
} else {
|
|
21928
21928
|
reject(new EmptyError_1.EmptyError());
|
|
21929
21929
|
}
|
|
@@ -21945,16 +21945,16 @@ var require_firstValueFrom = __commonJS({
|
|
|
21945
21945
|
var Subscriber_1 = require_Subscriber();
|
|
21946
21946
|
function firstValueFrom(source, config2) {
|
|
21947
21947
|
var hasConfig = typeof config2 === "object";
|
|
21948
|
-
return new Promise(function(
|
|
21948
|
+
return new Promise(function(resolve46, reject) {
|
|
21949
21949
|
var subscriber = new Subscriber_1.SafeSubscriber({
|
|
21950
21950
|
next: function(value) {
|
|
21951
|
-
|
|
21951
|
+
resolve46(value);
|
|
21952
21952
|
subscriber.unsubscribe();
|
|
21953
21953
|
},
|
|
21954
21954
|
error: reject,
|
|
21955
21955
|
complete: function() {
|
|
21956
21956
|
if (hasConfig) {
|
|
21957
|
-
|
|
21957
|
+
resolve46(config2.defaultValue);
|
|
21958
21958
|
} else {
|
|
21959
21959
|
reject(new EmptyError_1.EmptyError());
|
|
21960
21960
|
}
|
|
@@ -27747,14 +27747,14 @@ var require_run_async = __commonJS({
|
|
|
27747
27747
|
return function() {
|
|
27748
27748
|
var args = arguments;
|
|
27749
27749
|
var originalThis = this;
|
|
27750
|
-
var promise = new Promise(function(
|
|
27750
|
+
var promise = new Promise(function(resolve46, reject) {
|
|
27751
27751
|
var resolved = false;
|
|
27752
27752
|
const wrappedResolve = function(value) {
|
|
27753
27753
|
if (resolved) {
|
|
27754
27754
|
console.warn("Run-async promise already resolved.");
|
|
27755
27755
|
}
|
|
27756
27756
|
resolved = true;
|
|
27757
|
-
|
|
27757
|
+
resolve46(value);
|
|
27758
27758
|
};
|
|
27759
27759
|
var rejected = false;
|
|
27760
27760
|
const wrappedReject = function(value) {
|
|
@@ -30783,7 +30783,7 @@ var require_compile = __commonJS({
|
|
|
30783
30783
|
const schOrFunc = root.refs[ref];
|
|
30784
30784
|
if (schOrFunc)
|
|
30785
30785
|
return schOrFunc;
|
|
30786
|
-
let _sch =
|
|
30786
|
+
let _sch = resolve46.call(this, root, ref);
|
|
30787
30787
|
if (_sch === void 0) {
|
|
30788
30788
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
30789
30789
|
const { schemaId } = this.opts;
|
|
@@ -30810,7 +30810,7 @@ var require_compile = __commonJS({
|
|
|
30810
30810
|
function sameSchemaEnv(s1, s2) {
|
|
30811
30811
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
30812
30812
|
}
|
|
30813
|
-
function
|
|
30813
|
+
function resolve46(root, ref) {
|
|
30814
30814
|
let sch;
|
|
30815
30815
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
30816
30816
|
ref = sch;
|
|
@@ -31028,8 +31028,8 @@ var require_utils2 = __commonJS({
|
|
|
31028
31028
|
}
|
|
31029
31029
|
return ind;
|
|
31030
31030
|
}
|
|
31031
|
-
function removeDotSegments(
|
|
31032
|
-
let input =
|
|
31031
|
+
function removeDotSegments(path62) {
|
|
31032
|
+
let input = path62;
|
|
31033
31033
|
const output = [];
|
|
31034
31034
|
let nextSlash = -1;
|
|
31035
31035
|
let len = 0;
|
|
@@ -31281,8 +31281,8 @@ var require_schemes = __commonJS({
|
|
|
31281
31281
|
wsComponent.secure = void 0;
|
|
31282
31282
|
}
|
|
31283
31283
|
if (wsComponent.resourceName) {
|
|
31284
|
-
const [
|
|
31285
|
-
wsComponent.path =
|
|
31284
|
+
const [path62, query] = wsComponent.resourceName.split("?");
|
|
31285
|
+
wsComponent.path = path62 && path62 !== "/" ? path62 : void 0;
|
|
31286
31286
|
wsComponent.query = query;
|
|
31287
31287
|
wsComponent.resourceName = void 0;
|
|
31288
31288
|
}
|
|
@@ -31441,7 +31441,7 @@ var require_fast_uri = __commonJS({
|
|
|
31441
31441
|
}
|
|
31442
31442
|
return uri;
|
|
31443
31443
|
}
|
|
31444
|
-
function
|
|
31444
|
+
function resolve46(baseURI, relativeURI, options) {
|
|
31445
31445
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
31446
31446
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
31447
31447
|
schemelessOptions.skipEscape = true;
|
|
@@ -31699,7 +31699,7 @@ var require_fast_uri = __commonJS({
|
|
|
31699
31699
|
var fastUri = {
|
|
31700
31700
|
SCHEMES,
|
|
31701
31701
|
normalize: normalize3,
|
|
31702
|
-
resolve:
|
|
31702
|
+
resolve: resolve46,
|
|
31703
31703
|
resolveComponent,
|
|
31704
31704
|
equal,
|
|
31705
31705
|
serialize,
|
|
@@ -35964,11 +35964,11 @@ var parser = new YargsParser({
|
|
|
35964
35964
|
resolve: import_path2.resolve,
|
|
35965
35965
|
// TODO: figure out a way to combine ESM and CJS coverage, such that
|
|
35966
35966
|
// we can exercise all the lines below:
|
|
35967
|
-
require: (
|
|
35967
|
+
require: (path62) => {
|
|
35968
35968
|
if (typeof require !== "undefined") {
|
|
35969
|
-
return require(
|
|
35970
|
-
} else if (
|
|
35971
|
-
return JSON.parse((0, import_fs2.readFileSync)(
|
|
35969
|
+
return require(path62);
|
|
35970
|
+
} else if (path62.match(/\.json$/)) {
|
|
35971
|
+
return JSON.parse((0, import_fs2.readFileSync)(path62, "utf8"));
|
|
35972
35972
|
} else {
|
|
35973
35973
|
throw Error("only .json config files are supported in ESM");
|
|
35974
35974
|
}
|
|
@@ -37311,13 +37311,13 @@ function usage(yargs, shim3) {
|
|
|
37311
37311
|
};
|
|
37312
37312
|
self.stringifiedValues = function stringifiedValues(values, separator) {
|
|
37313
37313
|
let string3 = "";
|
|
37314
|
-
const
|
|
37314
|
+
const sep6 = separator || ", ";
|
|
37315
37315
|
const array2 = [].concat(values);
|
|
37316
37316
|
if (!values || !array2.length)
|
|
37317
37317
|
return string3;
|
|
37318
37318
|
array2.forEach((value) => {
|
|
37319
37319
|
if (string3.length)
|
|
37320
|
-
string3 +=
|
|
37320
|
+
string3 += sep6;
|
|
37321
37321
|
string3 += JSON.stringify(value);
|
|
37322
37322
|
});
|
|
37323
37323
|
return string3;
|
|
@@ -38494,12 +38494,12 @@ var YargsInstance = class {
|
|
|
38494
38494
|
async getCompletion(args, done) {
|
|
38495
38495
|
argsert("<array> [function]", [args, done], arguments.length);
|
|
38496
38496
|
if (!done) {
|
|
38497
|
-
return new Promise((
|
|
38497
|
+
return new Promise((resolve46, reject) => {
|
|
38498
38498
|
__classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
|
|
38499
38499
|
if (err)
|
|
38500
38500
|
reject(err);
|
|
38501
38501
|
else
|
|
38502
|
-
|
|
38502
|
+
resolve46(completions);
|
|
38503
38503
|
});
|
|
38504
38504
|
});
|
|
38505
38505
|
} else {
|
|
@@ -40652,8 +40652,8 @@ function getErrorMap() {
|
|
|
40652
40652
|
|
|
40653
40653
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
40654
40654
|
var makeIssue = (params) => {
|
|
40655
|
-
const { data, path:
|
|
40656
|
-
const fullPath = [...
|
|
40655
|
+
const { data, path: path62, errorMaps, issueData } = params;
|
|
40656
|
+
const fullPath = [...path62, ...issueData.path || []];
|
|
40657
40657
|
const fullIssue = {
|
|
40658
40658
|
...issueData,
|
|
40659
40659
|
path: fullPath
|
|
@@ -40769,11 +40769,11 @@ var errorUtil;
|
|
|
40769
40769
|
|
|
40770
40770
|
// node_modules/zod/v3/types.js
|
|
40771
40771
|
var ParseInputLazyPath = class {
|
|
40772
|
-
constructor(parent, value,
|
|
40772
|
+
constructor(parent, value, path62, key) {
|
|
40773
40773
|
this._cachedPath = [];
|
|
40774
40774
|
this.parent = parent;
|
|
40775
40775
|
this.data = value;
|
|
40776
|
-
this._path =
|
|
40776
|
+
this._path = path62;
|
|
40777
40777
|
this._key = key;
|
|
40778
40778
|
}
|
|
40779
40779
|
get path() {
|
|
@@ -44506,7 +44506,7 @@ var AgentSlotStatusSchema = external_exports.object({
|
|
|
44506
44506
|
attemptId: WorkAttemptIdSchema.optional(),
|
|
44507
44507
|
sessionStatus: external_exports.enum(["starting", "active", "failed", "completed"]).optional(),
|
|
44508
44508
|
lastError: external_exports.string().optional(),
|
|
44509
|
-
/** Set when a failed/starting session can be resumed
|
|
44509
|
+
/** Set when a failed/starting session can be resumed with --resume instead of a fresh launch. */
|
|
44510
44510
|
resumeHint: external_exports.string().optional(),
|
|
44511
44511
|
/** Worktree checked out to no branch (legacy failure mode; should not happen with sessions). */
|
|
44512
44512
|
detachedHead: external_exports.boolean().optional(),
|
|
@@ -68312,16 +68312,16 @@ async function handleAgentSkills(options) {
|
|
|
68312
68312
|
}
|
|
68313
68313
|
async function askYesNo(question) {
|
|
68314
68314
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
68315
|
-
return new Promise((
|
|
68315
|
+
return new Promise((resolve46) => {
|
|
68316
68316
|
process.stderr.write(`${question} `);
|
|
68317
68317
|
rl.once("line", (answer) => {
|
|
68318
68318
|
rl.close();
|
|
68319
68319
|
const trimmed = answer.trim();
|
|
68320
68320
|
if (trimmed === "") {
|
|
68321
|
-
|
|
68321
|
+
resolve46(true);
|
|
68322
68322
|
return;
|
|
68323
68323
|
}
|
|
68324
|
-
|
|
68324
|
+
resolve46(/^y(es)?$/i.test(trimmed));
|
|
68325
68325
|
});
|
|
68326
68326
|
});
|
|
68327
68327
|
}
|
|
@@ -68400,7 +68400,7 @@ function handleRemove(argv) {
|
|
|
68400
68400
|
}
|
|
68401
68401
|
|
|
68402
68402
|
// src/cli/commands/env.ts
|
|
68403
|
-
var
|
|
68403
|
+
var path51 = __toESM(require("path"));
|
|
68404
68404
|
|
|
68405
68405
|
// src/core/harness.ts
|
|
68406
68406
|
var fs22 = __toESM(require("fs"));
|
|
@@ -68486,6 +68486,7 @@ function parseHarnessEnvInt(env3, key) {
|
|
|
68486
68486
|
|
|
68487
68487
|
// src/harness/stages.ts
|
|
68488
68488
|
var STAGE_REGISTRY_FILE = "stages.json";
|
|
68489
|
+
var HAR_AGENT_SLOT_ONBOARD_MAX = 10;
|
|
68489
68490
|
var AGENT_REQUIRED_KINDS = /* @__PURE__ */ new Set([
|
|
68490
68491
|
"launch",
|
|
68491
68492
|
"verify",
|
|
@@ -68672,6 +68673,15 @@ ${maxLine}
|
|
|
68672
68673
|
fs10.writeFileSync(envPath, content);
|
|
68673
68674
|
return true;
|
|
68674
68675
|
}
|
|
68676
|
+
function applyAgentSlotMax(repoPath, max) {
|
|
68677
|
+
const slots = HarnessAgentSlotsSchema.parse({ min: HAR_AGENT_SLOT_MIN, max });
|
|
68678
|
+
const registry2 = readStageRegistry(repoPath);
|
|
68679
|
+
writeStageRegistry(repoPath, {
|
|
68680
|
+
...registry2,
|
|
68681
|
+
agentSlots: slots
|
|
68682
|
+
});
|
|
68683
|
+
syncAgentSlotsToHarnessEnv(repoPath);
|
|
68684
|
+
}
|
|
68675
68685
|
function stageRequiresAgentId(stage) {
|
|
68676
68686
|
if (typeof stage.requiresAgentId === "boolean") return stage.requiresAgentId;
|
|
68677
68687
|
return AGENT_REQUIRED_KINDS.has(stage.kind);
|
|
@@ -69179,13 +69189,13 @@ var MultipartBody = class {
|
|
|
69179
69189
|
// node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
|
|
69180
69190
|
var import_web = require("node:stream/web");
|
|
69181
69191
|
var fileFromPathWarned = false;
|
|
69182
|
-
async function fileFromPath3(
|
|
69192
|
+
async function fileFromPath3(path62, ...args) {
|
|
69183
69193
|
const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
|
|
69184
69194
|
if (!fileFromPathWarned) {
|
|
69185
|
-
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(
|
|
69195
|
+
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path62)}) instead`);
|
|
69186
69196
|
fileFromPathWarned = true;
|
|
69187
69197
|
}
|
|
69188
|
-
return await _fileFromPath(
|
|
69198
|
+
return await _fileFromPath(path62, ...args);
|
|
69189
69199
|
}
|
|
69190
69200
|
var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
69191
69201
|
var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
@@ -69681,8 +69691,8 @@ async function defaultParseResponse(props) {
|
|
|
69681
69691
|
}
|
|
69682
69692
|
var APIPromise = class _APIPromise extends Promise {
|
|
69683
69693
|
constructor(responsePromise, parseResponse = defaultParseResponse) {
|
|
69684
|
-
super((
|
|
69685
|
-
|
|
69694
|
+
super((resolve46) => {
|
|
69695
|
+
resolve46(null);
|
|
69686
69696
|
});
|
|
69687
69697
|
this.responsePromise = responsePromise;
|
|
69688
69698
|
this.parseResponse = parseResponse;
|
|
@@ -69782,29 +69792,29 @@ var APIClient = class {
|
|
|
69782
69792
|
defaultIdempotencyKey() {
|
|
69783
69793
|
return `stainless-node-retry-${uuid4()}`;
|
|
69784
69794
|
}
|
|
69785
|
-
get(
|
|
69786
|
-
return this.methodRequest("get",
|
|
69795
|
+
get(path62, opts) {
|
|
69796
|
+
return this.methodRequest("get", path62, opts);
|
|
69787
69797
|
}
|
|
69788
|
-
post(
|
|
69789
|
-
return this.methodRequest("post",
|
|
69798
|
+
post(path62, opts) {
|
|
69799
|
+
return this.methodRequest("post", path62, opts);
|
|
69790
69800
|
}
|
|
69791
|
-
patch(
|
|
69792
|
-
return this.methodRequest("patch",
|
|
69801
|
+
patch(path62, opts) {
|
|
69802
|
+
return this.methodRequest("patch", path62, opts);
|
|
69793
69803
|
}
|
|
69794
|
-
put(
|
|
69795
|
-
return this.methodRequest("put",
|
|
69804
|
+
put(path62, opts) {
|
|
69805
|
+
return this.methodRequest("put", path62, opts);
|
|
69796
69806
|
}
|
|
69797
|
-
delete(
|
|
69798
|
-
return this.methodRequest("delete",
|
|
69807
|
+
delete(path62, opts) {
|
|
69808
|
+
return this.methodRequest("delete", path62, opts);
|
|
69799
69809
|
}
|
|
69800
|
-
methodRequest(method,
|
|
69810
|
+
methodRequest(method, path62, opts) {
|
|
69801
69811
|
return this.request(Promise.resolve(opts).then(async (opts2) => {
|
|
69802
69812
|
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;
|
|
69803
|
-
return { method, path:
|
|
69813
|
+
return { method, path: path62, ...opts2, body };
|
|
69804
69814
|
}));
|
|
69805
69815
|
}
|
|
69806
|
-
getAPIList(
|
|
69807
|
-
return this.requestAPIList(Page, { method: "get", path:
|
|
69816
|
+
getAPIList(path62, Page, opts) {
|
|
69817
|
+
return this.requestAPIList(Page, { method: "get", path: path62, ...opts });
|
|
69808
69818
|
}
|
|
69809
69819
|
calculateContentLength(body) {
|
|
69810
69820
|
if (typeof body === "string") {
|
|
@@ -69822,10 +69832,10 @@ var APIClient = class {
|
|
|
69822
69832
|
return null;
|
|
69823
69833
|
}
|
|
69824
69834
|
buildRequest(options) {
|
|
69825
|
-
const { method, path:
|
|
69835
|
+
const { method, path: path62, query, headers = {} } = options;
|
|
69826
69836
|
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;
|
|
69827
69837
|
const contentLength = this.calculateContentLength(body);
|
|
69828
|
-
const url = this.buildURL(
|
|
69838
|
+
const url = this.buildURL(path62, query);
|
|
69829
69839
|
if ("timeout" in options)
|
|
69830
69840
|
validatePositiveInteger("timeout", options.timeout);
|
|
69831
69841
|
const timeout = options.timeout ?? this.timeout;
|
|
@@ -69934,8 +69944,8 @@ var APIClient = class {
|
|
|
69934
69944
|
const request = this.makeRequest(options, null);
|
|
69935
69945
|
return new PagePromise(this, request, Page);
|
|
69936
69946
|
}
|
|
69937
|
-
buildURL(
|
|
69938
|
-
const url = isAbsoluteURL(
|
|
69947
|
+
buildURL(path62, query) {
|
|
69948
|
+
const url = isAbsoluteURL(path62) ? new URL(path62) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path62.startsWith("/") ? path62.slice(1) : path62));
|
|
69939
69949
|
const defaultQuery = this.defaultQuery();
|
|
69940
69950
|
if (!isEmptyObj(defaultQuery)) {
|
|
69941
69951
|
query = { ...defaultQuery, ...query };
|
|
@@ -70220,7 +70230,7 @@ var startsWithSchemeRegexp = new RegExp("^(?:[a-z]+:)?//", "i");
|
|
|
70220
70230
|
var isAbsoluteURL = (url) => {
|
|
70221
70231
|
return startsWithSchemeRegexp.test(url);
|
|
70222
70232
|
};
|
|
70223
|
-
var sleep = (ms) => new Promise((
|
|
70233
|
+
var sleep = (ms) => new Promise((resolve46) => setTimeout(resolve46, ms));
|
|
70224
70234
|
var validatePositiveInteger = (name, n2) => {
|
|
70225
70235
|
if (typeof n2 !== "number" || !Number.isInteger(n2)) {
|
|
70226
70236
|
throw new AnthropicError(`${name} must be an integer`);
|
|
@@ -70711,12 +70721,12 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
|
|
|
70711
70721
|
}
|
|
70712
70722
|
return this._emit("error", new AnthropicError(String(error3)));
|
|
70713
70723
|
});
|
|
70714
|
-
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((
|
|
70715
|
-
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise,
|
|
70724
|
+
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve46, reject) => {
|
|
70725
|
+
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve46, "f");
|
|
70716
70726
|
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectConnectedPromise, reject, "f");
|
|
70717
70727
|
}), "f");
|
|
70718
|
-
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((
|
|
70719
|
-
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise,
|
|
70728
|
+
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve46, reject) => {
|
|
70729
|
+
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve46, "f");
|
|
70720
70730
|
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectEndPromise, reject, "f");
|
|
70721
70731
|
}), "f");
|
|
70722
70732
|
__classPrivateFieldGet8(this, _PromptCachingBetaMessageStream_connectedPromise, "f").catch(() => {
|
|
@@ -70845,11 +70855,11 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
|
|
|
70845
70855
|
* const message = await stream.emitted('message') // rejects if the stream errors
|
|
70846
70856
|
*/
|
|
70847
70857
|
emitted(event) {
|
|
70848
|
-
return new Promise((
|
|
70858
|
+
return new Promise((resolve46, reject) => {
|
|
70849
70859
|
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_catchingPromiseCreated, true, "f");
|
|
70850
70860
|
if (event !== "error")
|
|
70851
70861
|
this.once("error", reject);
|
|
70852
|
-
this.once(event,
|
|
70862
|
+
this.once(event, resolve46);
|
|
70853
70863
|
});
|
|
70854
70864
|
}
|
|
70855
70865
|
async done() {
|
|
@@ -71076,7 +71086,7 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
|
|
|
71076
71086
|
if (done) {
|
|
71077
71087
|
return { value: void 0, done: true };
|
|
71078
71088
|
}
|
|
71079
|
-
return new Promise((
|
|
71089
|
+
return new Promise((resolve46, reject) => readQueue.push({ resolve: resolve46, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
|
71080
71090
|
}
|
|
71081
71091
|
const chunk = pushQueue.shift();
|
|
71082
71092
|
return { value: chunk, done: false };
|
|
@@ -71224,12 +71234,12 @@ var MessageStream = class _MessageStream {
|
|
|
71224
71234
|
}
|
|
71225
71235
|
return this._emit("error", new AnthropicError(String(error3)));
|
|
71226
71236
|
});
|
|
71227
|
-
__classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((
|
|
71228
|
-
__classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise,
|
|
71237
|
+
__classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((resolve46, reject) => {
|
|
71238
|
+
__classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise, resolve46, "f");
|
|
71229
71239
|
__classPrivateFieldSet8(this, _MessageStream_rejectConnectedPromise, reject, "f");
|
|
71230
71240
|
}), "f");
|
|
71231
|
-
__classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((
|
|
71232
|
-
__classPrivateFieldSet8(this, _MessageStream_resolveEndPromise,
|
|
71241
|
+
__classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((resolve46, reject) => {
|
|
71242
|
+
__classPrivateFieldSet8(this, _MessageStream_resolveEndPromise, resolve46, "f");
|
|
71233
71243
|
__classPrivateFieldSet8(this, _MessageStream_rejectEndPromise, reject, "f");
|
|
71234
71244
|
}), "f");
|
|
71235
71245
|
__classPrivateFieldGet9(this, _MessageStream_connectedPromise, "f").catch(() => {
|
|
@@ -71358,11 +71368,11 @@ var MessageStream = class _MessageStream {
|
|
|
71358
71368
|
* const message = await stream.emitted('message') // rejects if the stream errors
|
|
71359
71369
|
*/
|
|
71360
71370
|
emitted(event) {
|
|
71361
|
-
return new Promise((
|
|
71371
|
+
return new Promise((resolve46, reject) => {
|
|
71362
71372
|
__classPrivateFieldSet8(this, _MessageStream_catchingPromiseCreated, true, "f");
|
|
71363
71373
|
if (event !== "error")
|
|
71364
71374
|
this.once("error", reject);
|
|
71365
|
-
this.once(event,
|
|
71375
|
+
this.once(event, resolve46);
|
|
71366
71376
|
});
|
|
71367
71377
|
}
|
|
71368
71378
|
async done() {
|
|
@@ -71589,7 +71599,7 @@ var MessageStream = class _MessageStream {
|
|
|
71589
71599
|
if (done) {
|
|
71590
71600
|
return { value: void 0, done: true };
|
|
71591
71601
|
}
|
|
71592
|
-
return new Promise((
|
|
71602
|
+
return new Promise((resolve46, reject) => readQueue.push({ resolve: resolve46, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
|
71593
71603
|
}
|
|
71594
71604
|
const chunk = pushQueue.shift();
|
|
71595
71605
|
return { value: chunk, done: false };
|
|
@@ -71849,11 +71859,11 @@ async function promptApplyAgentMdProposal(repoPath) {
|
|
|
71849
71859
|
}
|
|
71850
71860
|
async function askYesNo2(question) {
|
|
71851
71861
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
71852
|
-
return new Promise((
|
|
71862
|
+
return new Promise((resolve46) => {
|
|
71853
71863
|
process.stderr.write(`${question} `);
|
|
71854
71864
|
rl.once("line", (answer) => {
|
|
71855
71865
|
rl.close();
|
|
71856
|
-
|
|
71866
|
+
resolve46(/^y(es)?$/i.test(answer.trim()));
|
|
71857
71867
|
});
|
|
71858
71868
|
});
|
|
71859
71869
|
}
|
|
@@ -72083,7 +72093,7 @@ async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, c
|
|
|
72083
72093
|
}
|
|
72084
72094
|
async function askUser(question, options) {
|
|
72085
72095
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
|
|
72086
|
-
return new Promise((
|
|
72096
|
+
return new Promise((resolve46) => {
|
|
72087
72097
|
process.stderr.write("\n");
|
|
72088
72098
|
process.stderr.write(`\u2753 ${question}
|
|
72089
72099
|
`);
|
|
@@ -72094,7 +72104,7 @@ async function askUser(question, options) {
|
|
|
72094
72104
|
process.stderr.write("> ");
|
|
72095
72105
|
rl.once("line", (answer) => {
|
|
72096
72106
|
rl.close();
|
|
72097
|
-
|
|
72107
|
+
resolve46(answer.trim());
|
|
72098
72108
|
});
|
|
72099
72109
|
});
|
|
72100
72110
|
}
|
|
@@ -72238,7 +72248,7 @@ function runScript(scriptPath, args = [], options = {}) {
|
|
|
72238
72248
|
function runScriptCapture(scriptPath, args = [], options = {}) {
|
|
72239
72249
|
const stream = options.stream ?? false;
|
|
72240
72250
|
const { stream: _stream, ...spawnOptions } = options;
|
|
72241
|
-
return new Promise((
|
|
72251
|
+
return new Promise((resolve46) => {
|
|
72242
72252
|
const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
|
|
72243
72253
|
...spawnOptions,
|
|
72244
72254
|
stdio: ["inherit", "pipe", "pipe"]
|
|
@@ -72253,13 +72263,13 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
|
|
|
72253
72263
|
stderr += d2;
|
|
72254
72264
|
if (stream) process.stderr.write(d2);
|
|
72255
72265
|
});
|
|
72256
|
-
proc.on("close", (code) =>
|
|
72266
|
+
proc.on("close", (code) => resolve46({ stdout, stderr, code: code ?? 0 }));
|
|
72257
72267
|
});
|
|
72258
72268
|
}
|
|
72259
72269
|
function runShellCommand(command2, options = {}) {
|
|
72260
72270
|
const stream = options.stream ?? false;
|
|
72261
72271
|
const { stream: _stream, ...spawnOptions } = options;
|
|
72262
|
-
return new Promise((
|
|
72272
|
+
return new Promise((resolve46) => {
|
|
72263
72273
|
const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
|
|
72264
72274
|
...spawnOptions,
|
|
72265
72275
|
stdio: ["inherit", "pipe", "pipe"]
|
|
@@ -72274,7 +72284,7 @@ function runShellCommand(command2, options = {}) {
|
|
|
72274
72284
|
stderr += d2;
|
|
72275
72285
|
if (stream) process.stderr.write(d2);
|
|
72276
72286
|
});
|
|
72277
|
-
proc.on("close", (code) =>
|
|
72287
|
+
proc.on("close", (code) => resolve46({ stdout, stderr, code: code ?? 0 }));
|
|
72278
72288
|
});
|
|
72279
72289
|
}
|
|
72280
72290
|
|
|
@@ -73732,12 +73742,12 @@ function printAdaptationPrompt(content) {
|
|
|
73732
73742
|
}
|
|
73733
73743
|
function askYesNo3(question) {
|
|
73734
73744
|
const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
|
|
73735
|
-
return new Promise((
|
|
73745
|
+
return new Promise((resolve46) => {
|
|
73736
73746
|
process.stderr.write(`${question} `);
|
|
73737
73747
|
rl.once("line", (answer) => {
|
|
73738
73748
|
rl.close();
|
|
73739
73749
|
const trimmed = answer.trim();
|
|
73740
|
-
|
|
73750
|
+
resolve46(trimmed === "" || /^y(es)?$/i.test(trimmed));
|
|
73741
73751
|
});
|
|
73742
73752
|
});
|
|
73743
73753
|
}
|
|
@@ -73824,16 +73834,16 @@ async function promptScaffoldCursorRule(exists) {
|
|
|
73824
73834
|
}
|
|
73825
73835
|
async function askYesNo4(question) {
|
|
73826
73836
|
const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
|
|
73827
|
-
return new Promise((
|
|
73837
|
+
return new Promise((resolve46) => {
|
|
73828
73838
|
process.stderr.write(`${question} `);
|
|
73829
73839
|
rl.once("line", (answer) => {
|
|
73830
73840
|
rl.close();
|
|
73831
73841
|
const trimmed = answer.trim();
|
|
73832
73842
|
if (trimmed === "") {
|
|
73833
|
-
|
|
73843
|
+
resolve46(true);
|
|
73834
73844
|
return;
|
|
73835
73845
|
}
|
|
73836
|
-
|
|
73846
|
+
resolve46(/^y(es)?$/i.test(trimmed));
|
|
73837
73847
|
});
|
|
73838
73848
|
});
|
|
73839
73849
|
}
|
|
@@ -73963,8 +73973,6 @@ function buildLaunchFlagArgs(flags) {
|
|
|
73963
73973
|
const args = [];
|
|
73964
73974
|
if (flags.worktree === false) args.push("--no-worktree");
|
|
73965
73975
|
if (flags.claude) args.push("--claude");
|
|
73966
|
-
if (flags.confirmReplace) args.push("--replace");
|
|
73967
|
-
if (flags.force) args.push("--force");
|
|
73968
73976
|
if (flags.resume) args.push("--resume");
|
|
73969
73977
|
if (flags.workUnitId) args.push(`--work-id=${flags.workUnitId}`);
|
|
73970
73978
|
if (flags.attemptId) args.push(`--attempt-id=${flags.attemptId}`);
|
|
@@ -74143,7 +74151,7 @@ var LocalScriptExecutor = class {
|
|
|
74143
74151
|
var localScriptExecutor = new LocalScriptExecutor();
|
|
74144
74152
|
|
|
74145
74153
|
// src/core/control-sync.ts
|
|
74146
|
-
var
|
|
74154
|
+
var path45 = __toESM(require("path"));
|
|
74147
74155
|
init_control_config();
|
|
74148
74156
|
|
|
74149
74157
|
// src/core/control-registry.ts
|
|
@@ -74223,6 +74231,7 @@ function registryChanged(before, after) {
|
|
|
74223
74231
|
function recordRepoForControlSync(repoPath) {
|
|
74224
74232
|
if (process.env.HAR_CONTROL_DISABLED === "true") return;
|
|
74225
74233
|
const resolved = canonicalizeControlRepoPath(repoPath);
|
|
74234
|
+
if (!resolveMainWorkingTree(resolved)) return;
|
|
74226
74235
|
if (!readManifest(resolved)) return;
|
|
74227
74236
|
const registry2 = readRegistry();
|
|
74228
74237
|
if (registry2.repos.includes(resolved)) return;
|
|
@@ -74709,7 +74718,7 @@ function describeLaunchBase(repoPath) {
|
|
|
74709
74718
|
return [
|
|
74710
74719
|
`New session will be based on: ${branch}${sha ? ` @ ${sha}` : ""}`,
|
|
74711
74720
|
` (HEAD of ${harnessRoot})`,
|
|
74712
|
-
"
|
|
74721
|
+
" Switch the main checkout to your intended base before launching a new session."
|
|
74713
74722
|
];
|
|
74714
74723
|
}
|
|
74715
74724
|
function formatOccupiedSlot(slot, repoPath, resume) {
|
|
@@ -74721,27 +74730,30 @@ function formatOccupiedSlot(slot, repoPath, resume) {
|
|
|
74721
74730
|
slot.sessionStatus ? ` Status: ${slot.sessionStatus}` : void 0,
|
|
74722
74731
|
slot.lastError ? ` Error: ${slot.lastError}` : void 0,
|
|
74723
74732
|
slot.sessionCreatedAt ? ` Since: ${slot.sessionCreatedAt}` : void 0,
|
|
74724
|
-
slot.dirty ? " Git: dirty (uncommitted changes \u2014 commit or
|
|
74733
|
+
slot.dirty ? " Git: dirty (uncommitted changes \u2014 commit or discard them in the worktree)" : " Git: clean",
|
|
74725
74734
|
"",
|
|
74726
74735
|
...describeLaunchBase(repoPath),
|
|
74727
74736
|
""
|
|
74728
74737
|
];
|
|
74729
74738
|
if (resume || slot.sessionStatus === "failed" || slot.sessionStatus === "starting") {
|
|
74730
74739
|
lines2.push(
|
|
74731
|
-
"This session failed partway through launch. Resume without
|
|
74740
|
+
"This session failed partway through launch. Resume without a new launch:",
|
|
74732
74741
|
` har env launch ${slot.agentId} --resume`,
|
|
74733
74742
|
` har env recover ${slot.agentId}`,
|
|
74734
74743
|
` ./.har/launch.sh ${slot.agentId} --resume`,
|
|
74735
74744
|
""
|
|
74736
74745
|
);
|
|
74746
|
+
} else {
|
|
74747
|
+
lines2.push(
|
|
74748
|
+
"Free the slot before starting a new session:",
|
|
74749
|
+
slot.dirty ? ` Commit or discard changes in the worktree, then: har env teardown ${slot.agentId} (or complete ${slot.agentId})` : ` har env complete ${slot.agentId} # or: har env teardown ${slot.agentId}`,
|
|
74750
|
+
` har env launch ${slot.agentId}`,
|
|
74751
|
+
""
|
|
74752
|
+
);
|
|
74737
74753
|
}
|
|
74738
74754
|
lines2.push(
|
|
74739
|
-
"
|
|
74740
|
-
"
|
|
74741
|
-
"Gitignored paths (state/, runs/, local clones) are NOT preserved.",
|
|
74742
|
-
"",
|
|
74743
|
-
"To replace: pass confirmReplace=true (MCP), --replace (CLI), or answer y at the prompt.",
|
|
74744
|
-
"If the worktree is dirty, also pass force=true / --force after explicit user approval."
|
|
74755
|
+
"complete/teardown remove the worktree. The session branch is kept only if you committed.",
|
|
74756
|
+
"Gitignored paths (state/, runs/, local clones) are NOT preserved."
|
|
74745
74757
|
);
|
|
74746
74758
|
return lines2.filter(Boolean).join("\n");
|
|
74747
74759
|
}
|
|
@@ -74761,42 +74773,18 @@ function checkLaunchGuard(repoPath, agentId, options = {}) {
|
|
|
74761
74773
|
reason: [
|
|
74762
74774
|
`Slot ${agentId} is not resumable (status=${session?.status ?? "none"}).`,
|
|
74763
74775
|
"Only failed or starting sessions can be resumed.",
|
|
74764
|
-
|
|
74776
|
+
`Free the slot first: har env teardown ${agentId} (or complete ${agentId}), then har env launch ${agentId}.`
|
|
74765
74777
|
].join("\n")
|
|
74766
74778
|
};
|
|
74767
74779
|
}
|
|
74768
74780
|
return { allowed: true, slot };
|
|
74769
74781
|
}
|
|
74770
|
-
|
|
74771
|
-
|
|
74772
|
-
|
|
74773
|
-
|
|
74774
|
-
|
|
74775
|
-
|
|
74776
|
-
};
|
|
74777
|
-
}
|
|
74778
|
-
if (!options.confirmReplace) {
|
|
74779
|
-
return {
|
|
74780
|
-
allowed: false,
|
|
74781
|
-
blocked: true,
|
|
74782
|
-
slot,
|
|
74783
|
-
reason: formatOccupiedSlot(slot, repoPath)
|
|
74784
|
-
};
|
|
74785
|
-
}
|
|
74786
|
-
if (slot.dirty && !options.force) {
|
|
74787
|
-
return {
|
|
74788
|
-
allowed: false,
|
|
74789
|
-
blocked: true,
|
|
74790
|
-
slot,
|
|
74791
|
-
reason: [
|
|
74792
|
-
formatOccupiedSlot(slot, repoPath),
|
|
74793
|
-
"",
|
|
74794
|
-
"The occupied worktree has uncommitted changes.",
|
|
74795
|
-
"Pass force=true / --force to discard them (only after explicit user approval)."
|
|
74796
|
-
].join("\n")
|
|
74797
|
-
};
|
|
74798
|
-
}
|
|
74799
|
-
return { allowed: true, slot };
|
|
74782
|
+
return {
|
|
74783
|
+
allowed: false,
|
|
74784
|
+
blocked: true,
|
|
74785
|
+
slot,
|
|
74786
|
+
reason: formatOccupiedSlot(slot, repoPath)
|
|
74787
|
+
};
|
|
74800
74788
|
}
|
|
74801
74789
|
|
|
74802
74790
|
// src/core/slot-preflight.ts
|
|
@@ -74858,24 +74846,20 @@ function inspectSlotReadiness(repoPath, agentId, options = {}) {
|
|
|
74858
74846
|
const warnings = [];
|
|
74859
74847
|
const ports = {};
|
|
74860
74848
|
const session = readSlotRegistry(harnessRoot, agentId);
|
|
74861
|
-
const guard = options.occupied !== void 0 ? options.occupied.active ? options.resume && isSlotResumable(session) ? { allowed: true } :
|
|
74849
|
+
const guard = options.occupied !== void 0 ? options.occupied.active ? options.resume && isSlotResumable(session) ? { allowed: true } : {
|
|
74862
74850
|
allowed: false,
|
|
74863
74851
|
blocked: true,
|
|
74864
74852
|
reason: `Slot ${agentId} is already in use.`
|
|
74865
|
-
} :
|
|
74866
|
-
allowed: false,
|
|
74867
|
-
blocked: true,
|
|
74868
|
-
reason: `Slot ${agentId} worktree has uncommitted changes.`
|
|
74869
|
-
} : { allowed: true } : { allowed: true } : checkLaunchGuard(repoPath, agentId, options);
|
|
74853
|
+
} : { allowed: true } : checkLaunchGuard(repoPath, agentId, options);
|
|
74870
74854
|
if (!guard.allowed) {
|
|
74871
74855
|
const resumable = isSlotResumable(session);
|
|
74872
74856
|
blockers.push({
|
|
74873
74857
|
code: options.occupied?.dirty ? "slot_dirty" : resumable ? "slot_resumable" : "slot_occupied",
|
|
74874
74858
|
message: guard.reason ?? `Slot ${agentId} is occupied.`,
|
|
74875
|
-
remediation: resumable ? `Resume the partial launch: har env launch ${agentId} --resume (or har env recover ${agentId})` :
|
|
74859
|
+
remediation: resumable ? `Resume the partial launch: har env launch ${agentId} --resume (or har env recover ${agentId})` : `Free the slot: har env teardown ${agentId} (or complete ${agentId}), then har env launch ${agentId}.`
|
|
74876
74860
|
});
|
|
74877
74861
|
remediations.push(
|
|
74878
|
-
resumable ? `har env launch ${agentId} --resume` :
|
|
74862
|
+
resumable ? `har env launch ${agentId} --resume` : `har env teardown ${agentId}`
|
|
74879
74863
|
);
|
|
74880
74864
|
}
|
|
74881
74865
|
const pm2Procs = usesPm2 ? options.pm2Processes !== void 0 ? options.pm2Processes : listPm2Processes() : void 0;
|
|
@@ -74904,7 +74888,7 @@ function inspectSlotReadiness(repoPath, agentId, options = {}) {
|
|
|
74904
74888
|
blockers.push({
|
|
74905
74889
|
code: "project_mismatch",
|
|
74906
74890
|
message: `Slot registry projectName=${session.projectName} does not match harness ${projectName}.`,
|
|
74907
|
-
remediation: "Teardown the stale session
|
|
74891
|
+
remediation: "Teardown the stale session, then relaunch."
|
|
74908
74892
|
});
|
|
74909
74893
|
}
|
|
74910
74894
|
}
|
|
@@ -75614,7 +75598,7 @@ init_telemetry_config();
|
|
|
75614
75598
|
// src/core/usage-harvest/claude.ts
|
|
75615
75599
|
var fs40 = __toESM(require("fs"));
|
|
75616
75600
|
var os11 = __toESM(require("os"));
|
|
75617
|
-
var
|
|
75601
|
+
var path41 = __toESM(require("path"));
|
|
75618
75602
|
init_telemetry_config();
|
|
75619
75603
|
|
|
75620
75604
|
// src/core/telemetry-env.ts
|
|
@@ -75682,16 +75666,24 @@ ${TELEMETRY_MARKER_END}
|
|
|
75682
75666
|
fs39.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
|
|
75683
75667
|
}
|
|
75684
75668
|
|
|
75685
|
-
// src/core/
|
|
75686
|
-
|
|
75687
|
-
|
|
75688
|
-
return
|
|
75689
|
-
|
|
75690
|
-
|
|
75691
|
-
|
|
75669
|
+
// src/core/workspace-path-match.ts
|
|
75670
|
+
var path40 = __toESM(require("path"));
|
|
75671
|
+
function stripTrailingSeparators(value) {
|
|
75672
|
+
return value.replace(/[/\\]+$/, "");
|
|
75673
|
+
}
|
|
75674
|
+
function isWorkspaceUnderPath(workspace, basePath) {
|
|
75675
|
+
const workspaceNorm = stripTrailingSeparators(path40.resolve(workspace));
|
|
75676
|
+
const baseNorm = stripTrailingSeparators(path40.resolve(basePath));
|
|
75677
|
+
if (!workspaceNorm || !baseNorm) return false;
|
|
75678
|
+
return workspaceNorm === baseNorm || workspaceNorm.startsWith(`${baseNorm}${path40.sep}`);
|
|
75692
75679
|
}
|
|
75680
|
+
function workspaceMatchesTarget(workspace, targets) {
|
|
75681
|
+
return targets.some((target) => isWorkspaceUnderPath(workspace, target));
|
|
75682
|
+
}
|
|
75683
|
+
|
|
75684
|
+
// src/core/usage-harvest/claude.ts
|
|
75693
75685
|
function claudeProjectsRoot() {
|
|
75694
|
-
return process.env.HAR_CLAUDE_PROJECTS_DIR ?
|
|
75686
|
+
return process.env.HAR_CLAUDE_PROJECTS_DIR ? path41.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path41.join(os11.homedir(), ".claude", "projects");
|
|
75695
75687
|
}
|
|
75696
75688
|
function encodeClaudeProjectDir(cwd) {
|
|
75697
75689
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
@@ -75766,18 +75758,18 @@ function findMatchingClaudeTranscripts(slot) {
|
|
|
75766
75758
|
const matches = [];
|
|
75767
75759
|
for (const entry of fs40.readdirSync(root, { withFileTypes: true })) {
|
|
75768
75760
|
if (!entry.isDirectory()) continue;
|
|
75769
|
-
const projectDir =
|
|
75770
|
-
const encodedHit = targets.some((t2) => entry.name
|
|
75761
|
+
const projectDir = path41.join(root, entry.name);
|
|
75762
|
+
const encodedHit = targets.some((t2) => entry.name === encodeClaudeProjectDir(t2));
|
|
75771
75763
|
for (const file of fs40.readdirSync(projectDir)) {
|
|
75772
75764
|
if (!file.endsWith(".jsonl")) continue;
|
|
75773
|
-
const filePath =
|
|
75765
|
+
const filePath = path41.join(projectDir, file);
|
|
75774
75766
|
const stat = fs40.statSync(filePath);
|
|
75775
75767
|
const records = readJsonlRecords(filePath);
|
|
75776
75768
|
let cwdHit = encodedHit;
|
|
75777
75769
|
for (const record2 of records) {
|
|
75778
75770
|
if (!record2 || typeof record2 !== "object") continue;
|
|
75779
75771
|
const cwd = String(record2.cwd ?? "");
|
|
75780
|
-
if (cwd &&
|
|
75772
|
+
if (cwd && workspaceMatchesTarget(cwd, targets)) {
|
|
75781
75773
|
cwdHit = true;
|
|
75782
75774
|
break;
|
|
75783
75775
|
}
|
|
@@ -75885,21 +75877,14 @@ function harvestClaudeEvents(slot) {
|
|
|
75885
75877
|
// src/core/usage-harvest/codex.ts
|
|
75886
75878
|
var fs41 = __toESM(require("fs"));
|
|
75887
75879
|
var os12 = __toESM(require("os"));
|
|
75888
|
-
var
|
|
75889
|
-
function pathsMatch2(candidate, targets) {
|
|
75890
|
-
const norm = path41.resolve(candidate);
|
|
75891
|
-
return targets.some((t2) => {
|
|
75892
|
-
const target = path41.resolve(t2);
|
|
75893
|
-
return norm === target || norm.startsWith(target + path41.sep) || target.startsWith(norm + path41.sep);
|
|
75894
|
-
});
|
|
75895
|
-
}
|
|
75880
|
+
var path42 = __toESM(require("path"));
|
|
75896
75881
|
function codexSessionsRoot() {
|
|
75897
|
-
return process.env.HAR_CODEX_SESSIONS_DIR ?
|
|
75882
|
+
return process.env.HAR_CODEX_SESSIONS_DIR ? path42.resolve(process.env.HAR_CODEX_SESSIONS_DIR) : path42.join(os12.homedir(), ".codex", "sessions");
|
|
75898
75883
|
}
|
|
75899
75884
|
function walkJsonlFiles(dir, out = []) {
|
|
75900
75885
|
if (!fs41.existsSync(dir)) return out;
|
|
75901
75886
|
for (const entry of fs41.readdirSync(dir, { withFileTypes: true })) {
|
|
75902
|
-
const full =
|
|
75887
|
+
const full = path42.join(dir, entry.name);
|
|
75903
75888
|
if (entry.isDirectory()) walkJsonlFiles(full, out);
|
|
75904
75889
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) out.push(full);
|
|
75905
75890
|
}
|
|
@@ -75968,7 +75953,7 @@ function harvestCodexUsage(slot) {
|
|
|
75968
75953
|
for (const file of files) {
|
|
75969
75954
|
const records = readJsonl(file);
|
|
75970
75955
|
const extracted = extractCodexTokens(records);
|
|
75971
|
-
if (!extracted.cwd || !
|
|
75956
|
+
if (!extracted.cwd || !workspaceMatchesTarget(extracted.cwd, targets)) continue;
|
|
75972
75957
|
if (extracted.tokensInput + extracted.tokensOutput + extracted.tokensCacheRead === 0) continue;
|
|
75973
75958
|
const mtime = fs41.statSync(file).mtimeMs;
|
|
75974
75959
|
if (mtime >= bestMtime) {
|
|
@@ -76012,17 +75997,17 @@ function harvestEventsForSlot(slot) {
|
|
|
76012
75997
|
}
|
|
76013
75998
|
|
|
76014
75999
|
// src/core/control-persisted-usage.ts
|
|
76015
|
-
var
|
|
76000
|
+
var path44 = __toESM(require("path"));
|
|
76016
76001
|
|
|
76017
76002
|
// src/core/portal-watermark.ts
|
|
76018
76003
|
var fs42 = __toESM(require("fs"));
|
|
76019
76004
|
var os13 = __toESM(require("os"));
|
|
76020
|
-
var
|
|
76005
|
+
var path43 = __toESM(require("path"));
|
|
76021
76006
|
function getStatePath() {
|
|
76022
76007
|
if (process.env.HAR_PORTAL_SYNC_STATE_PATH) {
|
|
76023
|
-
return
|
|
76008
|
+
return path43.resolve(process.env.HAR_PORTAL_SYNC_STATE_PATH);
|
|
76024
76009
|
}
|
|
76025
|
-
return
|
|
76010
|
+
return path43.join(os13.homedir(), ".har", "portal-sync-state.json");
|
|
76026
76011
|
}
|
|
76027
76012
|
function readState() {
|
|
76028
76013
|
const statePath = getStatePath();
|
|
@@ -76036,7 +76021,7 @@ function readState() {
|
|
|
76036
76021
|
}
|
|
76037
76022
|
function writeState(state) {
|
|
76038
76023
|
const statePath = getStatePath();
|
|
76039
|
-
fs42.mkdirSync(
|
|
76024
|
+
fs42.mkdirSync(path43.dirname(statePath), { recursive: true });
|
|
76040
76025
|
fs42.writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
|
|
76041
76026
|
}
|
|
76042
76027
|
function readPortalWatermark(repoPath, portalUrl) {
|
|
@@ -76088,8 +76073,8 @@ async function getJson(url) {
|
|
|
76088
76073
|
async function resolveControlRepoId(apiUrl, repoPath) {
|
|
76089
76074
|
const repos = await getJson(`${apiUrl}/api/repos`);
|
|
76090
76075
|
if (!Array.isArray(repos)) return null;
|
|
76091
|
-
const target =
|
|
76092
|
-
return repos.find((repo) =>
|
|
76076
|
+
const target = path44.resolve(repoPath);
|
|
76077
|
+
return repos.find((repo) => path44.resolve(repo.path) === target)?.id ?? null;
|
|
76093
76078
|
}
|
|
76094
76079
|
function optionalString(value) {
|
|
76095
76080
|
return value == null ? void 0 : value;
|
|
@@ -76392,28 +76377,16 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
|
|
|
76392
76377
|
const deadline = Date.now() + timeoutMs;
|
|
76393
76378
|
while (Date.now() < deadline) {
|
|
76394
76379
|
if (await isControlApiReachable(apiUrl)) return true;
|
|
76395
|
-
await new Promise((
|
|
76380
|
+
await new Promise((resolve46) => setTimeout(resolve46, intervalMs));
|
|
76396
76381
|
}
|
|
76397
76382
|
return false;
|
|
76398
76383
|
}
|
|
76399
76384
|
async function discoverHarRepos(options) {
|
|
76400
|
-
const apiUrl = options?.apiUrl ?? getControlApiUrl();
|
|
76401
76385
|
const repoPaths = new Set(listRegisteredRepos());
|
|
76402
76386
|
if (options?.cwd) {
|
|
76403
76387
|
const cwd = canonicalizeControlRepoPath(options.cwd);
|
|
76404
76388
|
if (readManifest(cwd)) repoPaths.add(cwd);
|
|
76405
76389
|
}
|
|
76406
|
-
try {
|
|
76407
|
-
const listResponse = await fetch(`${apiUrl}/api/repos`);
|
|
76408
|
-
if (listResponse.ok) {
|
|
76409
|
-
const repos = await listResponse.json();
|
|
76410
|
-
for (const repo of repos) {
|
|
76411
|
-
const resolved = canonicalizeControlRepoPath(repo.path);
|
|
76412
|
-
if (readManifest(resolved)) repoPaths.add(resolved);
|
|
76413
|
-
}
|
|
76414
|
-
}
|
|
76415
|
-
} catch {
|
|
76416
|
-
}
|
|
76417
76390
|
return [...repoPaths];
|
|
76418
76391
|
}
|
|
76419
76392
|
async function syncReposWithControl(options) {
|
|
@@ -76495,7 +76468,7 @@ async function syncRepoWithLocalControl(options) {
|
|
|
76495
76468
|
const listResponse = await fetch(`${apiUrl}/api/repos`);
|
|
76496
76469
|
if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
|
|
76497
76470
|
const repos = await listResponse.json();
|
|
76498
|
-
const existing = repos.find((r2) =>
|
|
76471
|
+
const existing = repos.find((r2) => path45.resolve(r2.path) === repoPath);
|
|
76499
76472
|
if (!existing) {
|
|
76500
76473
|
return;
|
|
76501
76474
|
}
|
|
@@ -76654,6 +76627,7 @@ async function syncRepoWithControlAsync(repoPath) {
|
|
|
76654
76627
|
if (process.env.HAR_CONTROL_DISABLED === "true" || process.env.NODE_ENV === "test") return;
|
|
76655
76628
|
const verbose = process.env.HAR_CONTROL_VERBOSE === "true";
|
|
76656
76629
|
try {
|
|
76630
|
+
recordRepoForControlSync(repoPath);
|
|
76657
76631
|
const apiUrl = getControlApiUrl();
|
|
76658
76632
|
if (!await isControlApiReachable(apiUrl)) {
|
|
76659
76633
|
if (verbose) {
|
|
@@ -76698,7 +76672,7 @@ init_control_config();
|
|
|
76698
76672
|
|
|
76699
76673
|
// src/core/control-lifecycle.ts
|
|
76700
76674
|
var import_child_process9 = require("child_process");
|
|
76701
|
-
var
|
|
76675
|
+
var path46 = __toESM(require("path"));
|
|
76702
76676
|
|
|
76703
76677
|
// src/core/control-image.ts
|
|
76704
76678
|
var DEFAULT_CONTROL_IMAGE = "theosfactory/har-control";
|
|
@@ -76722,10 +76696,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
|
|
|
76722
76696
|
var CONTROL_CONTAINER_PORT = 3847;
|
|
76723
76697
|
var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
|
|
76724
76698
|
function resolveControlDir() {
|
|
76725
|
-
return
|
|
76699
|
+
return path46.resolve(__dirname, "..", "control");
|
|
76726
76700
|
}
|
|
76727
76701
|
function resolveControlBuildContext() {
|
|
76728
|
-
return
|
|
76702
|
+
return path46.resolve(resolveControlDir(), "..");
|
|
76729
76703
|
}
|
|
76730
76704
|
function buildDockerRunArgs(options) {
|
|
76731
76705
|
const name = options.containerName ?? CONTROL_CONTAINER_NAME;
|
|
@@ -76781,7 +76755,7 @@ async function startMissionControl(options) {
|
|
|
76781
76755
|
"-t",
|
|
76782
76756
|
imageRef,
|
|
76783
76757
|
"-f",
|
|
76784
|
-
|
|
76758
|
+
path46.join(resolveControlDir(), "Dockerfile"),
|
|
76785
76759
|
resolveControlBuildContext()
|
|
76786
76760
|
]);
|
|
76787
76761
|
if (buildCode !== 0) {
|
|
@@ -76926,7 +76900,7 @@ async function ensureTelemetryInfrastructure(options) {
|
|
|
76926
76900
|
|
|
76927
76901
|
// src/core/run-service.ts
|
|
76928
76902
|
init_telemetry_config();
|
|
76929
|
-
var
|
|
76903
|
+
var path48 = __toESM(require("path"));
|
|
76930
76904
|
function extractShellOutput(result) {
|
|
76931
76905
|
const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
|
|
76932
76906
|
const stderr = result.logs?.find((log) => log.stream === "stderr")?.content ?? "";
|
|
@@ -77013,10 +76987,7 @@ var RunService = class {
|
|
|
77013
76987
|
return this.executor.listArtifacts({ repoPath: options.repoPath }, { stageId: options.stageId });
|
|
77014
76988
|
}
|
|
77015
76989
|
async preflightEnvironment(options) {
|
|
77016
|
-
const readiness = inspectSlotReadiness(options.repoPath, options.agentId, {
|
|
77017
|
-
confirmReplace: options.confirmReplace,
|
|
77018
|
-
force: options.force
|
|
77019
|
-
});
|
|
76990
|
+
const readiness = inspectSlotReadiness(options.repoPath, options.agentId, {});
|
|
77020
76991
|
const report = formatPreflightReport(options.agentId, readiness);
|
|
77021
76992
|
return {
|
|
77022
76993
|
code: readiness.canLaunch ? 0 : 1,
|
|
@@ -77028,8 +76999,6 @@ var RunService = class {
|
|
|
77028
76999
|
}
|
|
77029
77000
|
async launchEnvironment(options) {
|
|
77030
77001
|
const guard = checkLaunchGuard2(options.repoPath, options.agentId, {
|
|
77031
|
-
confirmReplace: options.confirmReplace,
|
|
77032
|
-
force: options.force,
|
|
77033
77002
|
resume: options.resume
|
|
77034
77003
|
});
|
|
77035
77004
|
if (!guard.allowed) {
|
|
@@ -77079,7 +77048,7 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
77079
77048
|
const attemptId = workUnitId ? resumableSession?.attemptId ?? crypto5.randomUUID() : void 0;
|
|
77080
77049
|
if (workUnitId && attemptId) {
|
|
77081
77050
|
const conflictingSession = listSlotRegistryEntries(harnessRoot).find(
|
|
77082
|
-
(entry) => entry.workUnitId === workUnitId && !(entry.agentId === options.agentId &&
|
|
77051
|
+
(entry) => entry.workUnitId === workUnitId && !(entry.agentId === options.agentId && options.resume)
|
|
77083
77052
|
);
|
|
77084
77053
|
if (conflictingSession) {
|
|
77085
77054
|
return {
|
|
@@ -77112,8 +77081,6 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
77112
77081
|
launchFlags: {
|
|
77113
77082
|
worktree: options.worktree,
|
|
77114
77083
|
claude: options.claude,
|
|
77115
|
-
confirmReplace: options.confirmReplace,
|
|
77116
|
-
force: options.force,
|
|
77117
77084
|
resume: options.resume,
|
|
77118
77085
|
workUnitId,
|
|
77119
77086
|
attemptId
|
|
@@ -77136,12 +77103,12 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
77136
77103
|
suffix: session.suffix,
|
|
77137
77104
|
createdAt: session.createdAt
|
|
77138
77105
|
});
|
|
77139
|
-
const envFile =
|
|
77106
|
+
const envFile = path48.join(session.workDir, `.env.agent.${options.agentId}`);
|
|
77140
77107
|
try {
|
|
77141
77108
|
appendTelemetryEnvToFile(envFile, {
|
|
77142
77109
|
sessionKey,
|
|
77143
77110
|
agentId: options.agentId,
|
|
77144
|
-
repoPath:
|
|
77111
|
+
repoPath: path48.resolve(options.repoPath),
|
|
77145
77112
|
workDir: session.workDir,
|
|
77146
77113
|
branch: session.branch,
|
|
77147
77114
|
suffix: session.suffix,
|
|
@@ -77379,7 +77346,7 @@ var readline6 = __toESM(require("readline"));
|
|
|
77379
77346
|
// src/core/hooks.ts
|
|
77380
77347
|
var fs44 = __toESM(require("fs"));
|
|
77381
77348
|
var os15 = __toESM(require("os"));
|
|
77382
|
-
var
|
|
77349
|
+
var path49 = __toESM(require("path"));
|
|
77383
77350
|
var MARKER_START = "# >>> har commit gate (managed by `har hooks`) >>>";
|
|
77384
77351
|
var MARKER_END = "# <<< har commit gate <<<";
|
|
77385
77352
|
var PRE_COMMIT_BLOCK = [
|
|
@@ -77404,7 +77371,7 @@ function resolveCheckoutRoot(cwd) {
|
|
|
77404
77371
|
function resolveHooksDir(checkoutDir) {
|
|
77405
77372
|
const hooksPath = tryGit3(checkoutDir, "rev-parse --git-path hooks");
|
|
77406
77373
|
if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
|
|
77407
|
-
return
|
|
77374
|
+
return path49.resolve(checkoutDir, hooksPath);
|
|
77408
77375
|
}
|
|
77409
77376
|
function getConfiguredHooksPath(checkoutDir) {
|
|
77410
77377
|
return tryGit3(checkoutDir, "config core.hooksPath") || void 0;
|
|
@@ -77412,9 +77379,9 @@ function getConfiguredHooksPath(checkoutDir) {
|
|
|
77412
77379
|
function defaultHarInvocation() {
|
|
77413
77380
|
const entry = process.argv[1];
|
|
77414
77381
|
if (entry && entry.endsWith(".js")) {
|
|
77415
|
-
return `"${process.execPath}" "${
|
|
77382
|
+
return `"${process.execPath}" "${path49.resolve(entry)}"`;
|
|
77416
77383
|
}
|
|
77417
|
-
if (entry) return `"${
|
|
77384
|
+
if (entry) return `"${path49.resolve(entry)}"`;
|
|
77418
77385
|
return "har";
|
|
77419
77386
|
}
|
|
77420
77387
|
function buildHookScript(harInvocation, subcommand, failOpenNotice) {
|
|
@@ -77493,17 +77460,17 @@ Or re-run with --force to write into that directory anyway.`
|
|
|
77493
77460
|
fs44.mkdirSync(hooksDir, { recursive: true });
|
|
77494
77461
|
const invocation = options.harInvocation ?? defaultHarInvocation();
|
|
77495
77462
|
fs44.writeFileSync(
|
|
77496
|
-
|
|
77463
|
+
path49.join(hooksDir, "har-pre-commit"),
|
|
77497
77464
|
buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
|
|
77498
77465
|
{ mode: 493 }
|
|
77499
77466
|
);
|
|
77500
77467
|
fs44.writeFileSync(
|
|
77501
|
-
|
|
77468
|
+
path49.join(hooksDir, "har-post-commit"),
|
|
77502
77469
|
buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
|
|
77503
77470
|
{ mode: 493 }
|
|
77504
77471
|
);
|
|
77505
|
-
const preCommit = upsertMarkedBlock(
|
|
77506
|
-
const postCommit = upsertMarkedBlock(
|
|
77472
|
+
const preCommit = upsertMarkedBlock(path49.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
|
|
77473
|
+
const postCommit = upsertMarkedBlock(path49.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
|
|
77507
77474
|
ensureValidationsIgnored(checkout);
|
|
77508
77475
|
return { hooksDir, preCommit, postCommit };
|
|
77509
77476
|
}
|
|
@@ -77512,10 +77479,10 @@ function uninstallHooks(repoPath) {
|
|
|
77512
77479
|
if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
|
|
77513
77480
|
const hooksDir = resolveHooksDir(checkout);
|
|
77514
77481
|
let removed = false;
|
|
77515
|
-
removed = removeMarkedBlock(
|
|
77516
|
-
removed = removeMarkedBlock(
|
|
77482
|
+
removed = removeMarkedBlock(path49.join(hooksDir, "pre-commit")) || removed;
|
|
77483
|
+
removed = removeMarkedBlock(path49.join(hooksDir, "post-commit")) || removed;
|
|
77517
77484
|
for (const file of ["har-pre-commit", "har-post-commit"]) {
|
|
77518
|
-
const full =
|
|
77485
|
+
const full = path49.join(hooksDir, file);
|
|
77519
77486
|
if (fs44.existsSync(full)) {
|
|
77520
77487
|
fs44.rmSync(full);
|
|
77521
77488
|
removed = true;
|
|
@@ -77536,10 +77503,10 @@ function isAgentWorktree(checkoutDir) {
|
|
|
77536
77503
|
if (branch && (/^har-agent-\d+$/.test(branch) || /-har-agent-\d+-[a-z0-9]+$/.test(branch))) {
|
|
77537
77504
|
return true;
|
|
77538
77505
|
}
|
|
77539
|
-
const worktreesRoot =
|
|
77540
|
-
const resolved =
|
|
77541
|
-
const name =
|
|
77542
|
-
return resolved.startsWith(`${worktreesRoot}${
|
|
77506
|
+
const worktreesRoot = path49.join(os15.homedir(), "worktrees");
|
|
77507
|
+
const resolved = path49.resolve(checkoutDir);
|
|
77508
|
+
const name = path49.basename(resolved);
|
|
77509
|
+
return resolved.startsWith(`${worktreesRoot}${path49.sep}`) && (/-agent-\d+$/.test(name) || /-har-agent-\d+-[a-z0-9]+$/.test(name));
|
|
77543
77510
|
}
|
|
77544
77511
|
function resolveEffectiveMode(checkoutDir, gate) {
|
|
77545
77512
|
if (!gate.enabled) return "off";
|
|
@@ -77552,15 +77519,15 @@ function getHooksStatus(repoPath) {
|
|
|
77552
77519
|
const hooksDir = resolveHooksDir(checkout);
|
|
77553
77520
|
const gate = getCommitGateConfig(checkout);
|
|
77554
77521
|
const hasBlock = (name) => {
|
|
77555
|
-
const file =
|
|
77522
|
+
const file = path49.join(hooksDir, name);
|
|
77556
77523
|
return fs44.existsSync(file) && fs44.readFileSync(file, "utf8").includes(MARKER_START);
|
|
77557
77524
|
};
|
|
77558
77525
|
return {
|
|
77559
77526
|
checkout,
|
|
77560
77527
|
hooksDir,
|
|
77561
77528
|
configuredHooksPath: getConfiguredHooksPath(checkout),
|
|
77562
|
-
preCommitInstalled: hasBlock("pre-commit") && fs44.existsSync(
|
|
77563
|
-
postCommitInstalled: hasBlock("post-commit") && fs44.existsSync(
|
|
77529
|
+
preCommitInstalled: hasBlock("pre-commit") && fs44.existsSync(path49.join(hooksDir, "har-pre-commit")),
|
|
77530
|
+
postCommitInstalled: hasBlock("post-commit") && fs44.existsSync(path49.join(hooksDir, "har-post-commit")),
|
|
77564
77531
|
gate,
|
|
77565
77532
|
effectiveMode: resolveEffectiveMode(checkout, gate)
|
|
77566
77533
|
};
|
|
@@ -77571,7 +77538,7 @@ function checkCommitGate(cwd) {
|
|
|
77571
77538
|
}
|
|
77572
77539
|
const checkout = resolveCheckoutRoot(cwd);
|
|
77573
77540
|
if (!checkout) return { exitCode: 0, messages: [] };
|
|
77574
|
-
if (!fs44.existsSync(
|
|
77541
|
+
if (!fs44.existsSync(path49.join(checkout, ".har", "stages.json"))) {
|
|
77575
77542
|
return { exitCode: 0, messages: [] };
|
|
77576
77543
|
}
|
|
77577
77544
|
const gate = getCommitGateConfig(checkout);
|
|
@@ -77644,12 +77611,12 @@ async function recordCommitAssociation(cwd) {
|
|
|
77644
77611
|
// src/core/commit-gate-onboarding.ts
|
|
77645
77612
|
function askYesNo5(question) {
|
|
77646
77613
|
const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
|
|
77647
|
-
return new Promise((
|
|
77614
|
+
return new Promise((resolve46) => {
|
|
77648
77615
|
process.stderr.write(`${question} `);
|
|
77649
77616
|
rl.once("line", (answer) => {
|
|
77650
77617
|
rl.close();
|
|
77651
77618
|
const trimmed = answer.trim();
|
|
77652
|
-
|
|
77619
|
+
resolve46(trimmed === "" || /^y(es)?$/i.test(trimmed));
|
|
77653
77620
|
});
|
|
77654
77621
|
});
|
|
77655
77622
|
}
|
|
@@ -77693,12 +77660,12 @@ async function handleCommitGateOnboarding(options) {
|
|
|
77693
77660
|
// src/core/onboarding-preferences.ts
|
|
77694
77661
|
var fs45 = __toESM(require("fs"));
|
|
77695
77662
|
var os16 = __toESM(require("os"));
|
|
77696
|
-
var
|
|
77663
|
+
var path50 = __toESM(require("path"));
|
|
77697
77664
|
function getOnboardingPreferencesPath() {
|
|
77698
77665
|
if (process.env.HAR_PREFERENCES_PATH) {
|
|
77699
|
-
return
|
|
77666
|
+
return path50.resolve(process.env.HAR_PREFERENCES_PATH);
|
|
77700
77667
|
}
|
|
77701
|
-
return
|
|
77668
|
+
return path50.join(os16.homedir(), ".har", "preferences.json");
|
|
77702
77669
|
}
|
|
77703
77670
|
function readOnboardingPreferences() {
|
|
77704
77671
|
const preferencePath = getOnboardingPreferencesPath();
|
|
@@ -77729,7 +77696,7 @@ function writeOnboardingPreferences(overrides) {
|
|
|
77729
77696
|
};
|
|
77730
77697
|
const parsed = OnboardingPreferencesSchema.parse(preference);
|
|
77731
77698
|
const preferencePath = getOnboardingPreferencesPath();
|
|
77732
|
-
fs45.mkdirSync(
|
|
77699
|
+
fs45.mkdirSync(path50.dirname(preferencePath), { recursive: true });
|
|
77733
77700
|
fs45.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
|
|
77734
77701
|
`);
|
|
77735
77702
|
return parsed;
|
|
@@ -77752,10 +77719,11 @@ Slot lifecycle (do not confuse these):
|
|
|
77752
77719
|
complete finish successfully: full verify, then teardown (frees the slot)
|
|
77753
77720
|
teardown abandon / free the slot without a completion validation
|
|
77754
77721
|
|
|
77755
|
-
|
|
77756
|
-
|
|
77757
|
-
|
|
77758
|
-
|
|
77722
|
+
Occupied slots always block a new launch:
|
|
77723
|
+
har env complete <id> # or: har env teardown <id>
|
|
77724
|
+
har env launch <id> # then start the new session
|
|
77725
|
+
|
|
77726
|
+
--resume recover a failed/starting session; never needed for a fresh launch
|
|
77759
77727
|
|
|
77760
77728
|
For a new unrelated task: checkout main (or your intended base) on the main
|
|
77761
77729
|
repo checkout, free the slot (complete/teardown), then launch.`;
|
|
@@ -77768,23 +77736,23 @@ var HAR_ENV_EPILOG = `Environment lifecycle:
|
|
|
77768
77736
|
teardown <id> free the slot without recording a completion validation
|
|
77769
77737
|
|
|
77770
77738
|
Occupied slots:
|
|
77771
|
-
|
|
77772
|
-
|
|
77773
|
-
|
|
77774
|
-
|
|
77739
|
+
Always blocked for a fresh launch \u2014 free the slot first, then launch again:
|
|
77740
|
+
har env complete <id> # or: har env teardown <id>
|
|
77741
|
+
har env launch <id>
|
|
77742
|
+
A new launch uses the main checkout's current HEAD \u2014 switch that checkout to
|
|
77743
|
+
your intended base first.
|
|
77744
|
+
Failed/starting sessions can be resumed instead: har env launch <id> --resume
|
|
77745
|
+
(or har env recover <id>).`;
|
|
77775
77746
|
var LAUNCH_COMMAND_DESCRIBE = "Start a fresh agent session (new worktree from the main checkout HEAD)";
|
|
77776
|
-
var
|
|
77777
|
-
var LAUNCH_FORCE_DESCRIBE = "With --replace: discard uncommitted changes in the old worktree (only after explicit user approval)";
|
|
77778
|
-
var LAUNCH_RESUME_DESCRIBE = "Continue a failed or starting launch without creating a new worktree (prefer over --replace)";
|
|
77747
|
+
var LAUNCH_RESUME_DESCRIBE = "Continue a failed or starting launch without creating a new worktree";
|
|
77779
77748
|
var LAUNCH_EPILOG = `Every launch creates a NEW session from the current HEAD of --repo (the main
|
|
77780
77749
|
checkout). The worktree path encodes that base branch \u2014 switch --repo to main
|
|
77781
77750
|
before launch for a new unrelated task unless you intentionally stack on a
|
|
77782
77751
|
feature branch.
|
|
77783
77752
|
|
|
77784
77753
|
Free slot: har env launch 1
|
|
77785
|
-
Occupied: har env complete 1 # or teardown
|
|
77786
|
-
har env launch 1
|
|
77787
|
-
har env launch 1 --replace --force # + discard dirty work
|
|
77754
|
+
Occupied: har env complete 1 # or teardown
|
|
77755
|
+
har env launch 1 # then start the new session
|
|
77788
77756
|
Failed launch: har env recover 1 # or: har env launch 1 --resume`;
|
|
77789
77757
|
|
|
77790
77758
|
// src/cli/commands/env.ts
|
|
@@ -77936,15 +77904,7 @@ var envCommand = {
|
|
|
77936
77904
|
type: "boolean",
|
|
77937
77905
|
default: true,
|
|
77938
77906
|
describe: "Use an isolated git worktree (default)"
|
|
77939
|
-
}).option("claude", { type: "boolean", default: false }).option("
|
|
77940
|
-
type: "boolean",
|
|
77941
|
-
default: false,
|
|
77942
|
-
describe: LAUNCH_REPLACE_DESCRIBE
|
|
77943
|
-
}).option("force", {
|
|
77944
|
-
type: "boolean",
|
|
77945
|
-
default: false,
|
|
77946
|
-
describe: LAUNCH_FORCE_DESCRIBE
|
|
77947
|
-
}).option("resume", {
|
|
77907
|
+
}).option("claude", { type: "boolean", default: false }).option("resume", {
|
|
77948
77908
|
type: "boolean",
|
|
77949
77909
|
default: false,
|
|
77950
77910
|
describe: LAUNCH_RESUME_DESCRIBE
|
|
@@ -77967,15 +77927,7 @@ var envCommand = {
|
|
|
77967
77927
|
).command(
|
|
77968
77928
|
"preflight <id>",
|
|
77969
77929
|
"Check whether a slot can launch now (ports, PM2, Docker, occupied slot)",
|
|
77970
|
-
(y2) => y2.positional("id", { type: "number", describe: "Agent slot id (see .har/stages.json agentSlots)" }).option("repo", { type: "string", default: "." }).option("json", { type: "boolean", default: false, describe: "Structured JSON output" })
|
|
77971
|
-
type: "boolean",
|
|
77972
|
-
default: false,
|
|
77973
|
-
describe: "Treat an occupied slot as replaceable (same as launch --replace)"
|
|
77974
|
-
}).option("force", {
|
|
77975
|
-
type: "boolean",
|
|
77976
|
-
default: false,
|
|
77977
|
-
describe: "Allow replacing a dirty worktree (only after explicit approval)"
|
|
77978
|
-
}),
|
|
77930
|
+
(y2) => y2.positional("id", { type: "number", describe: "Agent slot id (see .har/stages.json agentSlots)" }).option("repo", { type: "string", default: "." }).option("json", { type: "boolean", default: false, describe: "Structured JSON output" }),
|
|
77979
77931
|
handlePreflight
|
|
77980
77932
|
).command(
|
|
77981
77933
|
"verify <id>",
|
|
@@ -78033,7 +77985,7 @@ var envCommand = {
|
|
|
78033
77985
|
}
|
|
78034
77986
|
};
|
|
78035
77987
|
async function handleInit(argv) {
|
|
78036
|
-
const repoPath =
|
|
77988
|
+
const repoPath = path51.resolve(argv.repo);
|
|
78037
77989
|
const onboarding = resolveOnboardingOptions(argv);
|
|
78038
77990
|
header("har env init");
|
|
78039
77991
|
info(`Repository: ${repoPath}`);
|
|
@@ -78071,7 +78023,6 @@ async function handleInit(argv) {
|
|
|
78071
78023
|
}
|
|
78072
78024
|
divider();
|
|
78073
78025
|
success("Harness initialized!");
|
|
78074
|
-
recordRepoForControlSync(repoPath);
|
|
78075
78026
|
await handleCommitGateOnboarding({
|
|
78076
78027
|
repoPath,
|
|
78077
78028
|
...onboarding.commitGate,
|
|
@@ -78097,7 +78048,7 @@ async function handleInit(argv) {
|
|
|
78097
78048
|
}
|
|
78098
78049
|
}
|
|
78099
78050
|
async function handleMaintain(argv) {
|
|
78100
|
-
const repoPath =
|
|
78051
|
+
const repoPath = path51.resolve(argv.repo);
|
|
78101
78052
|
const onboarding = resolveOnboardingOptions(argv);
|
|
78102
78053
|
header("har env maintain");
|
|
78103
78054
|
info(`Repository: ${repoPath}`);
|
|
@@ -78219,7 +78170,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
|
|
|
78219
78170
|
if (autoYes) {
|
|
78220
78171
|
const proposal = readAgentMdProposal(repoPath);
|
|
78221
78172
|
if (proposal) {
|
|
78222
|
-
writeFileSafe(
|
|
78173
|
+
writeFileSafe(path51.join(repoPath, "AGENT.md"), proposal.content);
|
|
78223
78174
|
clearAgentMdProposal(repoPath);
|
|
78224
78175
|
info("Applied AGENT.md proposal (--yes)");
|
|
78225
78176
|
}
|
|
@@ -78228,7 +78179,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
|
|
|
78228
78179
|
await promptApplyAgentMdProposal(repoPath);
|
|
78229
78180
|
}
|
|
78230
78181
|
async function handleAddPlugin(argv) {
|
|
78231
|
-
const repoPath =
|
|
78182
|
+
const repoPath = path51.resolve(argv.repo);
|
|
78232
78183
|
const available = listPluginIds();
|
|
78233
78184
|
if (argv.list) {
|
|
78234
78185
|
for (const id of available) {
|
|
@@ -78266,7 +78217,7 @@ async function handleAddPlugin(argv) {
|
|
|
78266
78217
|
}
|
|
78267
78218
|
}
|
|
78268
78219
|
async function handleAddStage(argv) {
|
|
78269
|
-
const repoPath =
|
|
78220
|
+
const repoPath = path51.resolve(argv.repo);
|
|
78270
78221
|
const available = listPluginIds();
|
|
78271
78222
|
if (argv.list) {
|
|
78272
78223
|
warn("har env add-stage --list is deprecated; prefer: har env add-plugin --list");
|
|
@@ -78332,13 +78283,11 @@ async function handleAddStage(argv) {
|
|
|
78332
78283
|
});
|
|
78333
78284
|
}
|
|
78334
78285
|
async function handlePreflight(argv) {
|
|
78335
|
-
const repo =
|
|
78286
|
+
const repo = path51.resolve(argv.repo);
|
|
78336
78287
|
const agentId = validateAgentId(argv.id, repo);
|
|
78337
78288
|
const result = await preflightEnvironment({
|
|
78338
78289
|
repoPath: repo,
|
|
78339
|
-
agentId
|
|
78340
|
-
confirmReplace: argv.replace,
|
|
78341
|
-
force: argv.force
|
|
78290
|
+
agentId
|
|
78342
78291
|
});
|
|
78343
78292
|
if (argv.json) {
|
|
78344
78293
|
const output = SlotReadinessSchema.parse(result.readiness);
|
|
@@ -78350,48 +78299,13 @@ async function handlePreflight(argv) {
|
|
|
78350
78299
|
process.exit(result.code);
|
|
78351
78300
|
}
|
|
78352
78301
|
async function handleLaunch(argv) {
|
|
78353
|
-
const repo =
|
|
78302
|
+
const repo = path51.resolve(argv.repo);
|
|
78354
78303
|
const agentId = validateAgentId(argv.id, repo);
|
|
78355
|
-
let confirmReplace = argv.replace;
|
|
78356
|
-
let force = argv.force;
|
|
78357
78304
|
if (!argv.resume) {
|
|
78358
|
-
const guard = checkLaunchGuard2(repo, agentId, {
|
|
78305
|
+
const guard = checkLaunchGuard2(repo, agentId, {});
|
|
78359
78306
|
if (!guard.allowed && guard.blocked) {
|
|
78360
|
-
|
|
78361
|
-
|
|
78362
|
-
console.error(guard.reason ?? "");
|
|
78363
|
-
const readline10 = await import("readline");
|
|
78364
|
-
const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
|
|
78365
|
-
const answer = await new Promise((resolve45) => {
|
|
78366
|
-
rl.question("Replace this slot? [y/N] ", resolve45);
|
|
78367
|
-
});
|
|
78368
|
-
rl.close();
|
|
78369
|
-
if (!/^[Yy]$/.test(answer.trim())) {
|
|
78370
|
-
error("Aborted \u2014 slot left unchanged.");
|
|
78371
|
-
process.exit(2);
|
|
78372
|
-
}
|
|
78373
|
-
confirmReplace = true;
|
|
78374
|
-
}
|
|
78375
|
-
}
|
|
78376
|
-
const guardAfterConfirm = checkLaunchGuard2(repo, agentId, { confirmReplace, force });
|
|
78377
|
-
if (!guardAfterConfirm.allowed && guardAfterConfirm.blocked && guardAfterConfirm.slot?.dirty) {
|
|
78378
|
-
if (!force && process.stdin.isTTY && process.stdout.isTTY) {
|
|
78379
|
-
warn("Worktree has uncommitted changes.");
|
|
78380
|
-
const readline10 = await import("readline");
|
|
78381
|
-
const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
|
|
78382
|
-
const answer = await new Promise((resolve45) => {
|
|
78383
|
-
rl.question("Discard uncommitted changes? [y/N] ", resolve45);
|
|
78384
|
-
});
|
|
78385
|
-
rl.close();
|
|
78386
|
-
if (!/^[Yy]$/.test(answer.trim())) {
|
|
78387
|
-
error("Aborted \u2014 uncommitted work preserved.");
|
|
78388
|
-
process.exit(2);
|
|
78389
|
-
}
|
|
78390
|
-
force = true;
|
|
78391
|
-
} else if (!force) {
|
|
78392
|
-
error(guardAfterConfirm.reason ?? "Dirty worktree requires --force.");
|
|
78393
|
-
process.exit(2);
|
|
78394
|
-
}
|
|
78307
|
+
error(guard.reason ?? `Slot ${agentId} is occupied.`);
|
|
78308
|
+
process.exit(2);
|
|
78395
78309
|
}
|
|
78396
78310
|
}
|
|
78397
78311
|
const result = await launchEnvironment({
|
|
@@ -78399,8 +78313,6 @@ async function handleLaunch(argv) {
|
|
|
78399
78313
|
agentId,
|
|
78400
78314
|
worktree: argv.worktree,
|
|
78401
78315
|
claude: argv.claude,
|
|
78402
|
-
confirmReplace,
|
|
78403
|
-
force,
|
|
78404
78316
|
resume: argv.resume,
|
|
78405
78317
|
workUnitId: argv.workId,
|
|
78406
78318
|
source: argv.workSource,
|
|
@@ -78433,8 +78345,6 @@ async function handleRecover(argv) {
|
|
|
78433
78345
|
repo: argv.repo,
|
|
78434
78346
|
worktree: true,
|
|
78435
78347
|
claude: false,
|
|
78436
|
-
replace: false,
|
|
78437
|
-
force: false,
|
|
78438
78348
|
resume: true,
|
|
78439
78349
|
workId: void 0,
|
|
78440
78350
|
workSource: void 0,
|
|
@@ -78444,7 +78354,7 @@ async function handleRecover(argv) {
|
|
|
78444
78354
|
});
|
|
78445
78355
|
}
|
|
78446
78356
|
async function handleVerify(argv) {
|
|
78447
|
-
const repo =
|
|
78357
|
+
const repo = path51.resolve(argv.repo);
|
|
78448
78358
|
const agentId = validateAgentId(argv.id, repo);
|
|
78449
78359
|
const result = await runVerification({
|
|
78450
78360
|
repoPath: repo,
|
|
@@ -78456,7 +78366,7 @@ async function handleVerify(argv) {
|
|
|
78456
78366
|
process.exit(result.code);
|
|
78457
78367
|
}
|
|
78458
78368
|
async function handleTeardown(argv) {
|
|
78459
|
-
const repo =
|
|
78369
|
+
const repo = path51.resolve(argv.repo);
|
|
78460
78370
|
const agentId = validateAgentId(argv.id, repo);
|
|
78461
78371
|
const result = await teardownEnvironment({
|
|
78462
78372
|
repoPath: repo,
|
|
@@ -78467,7 +78377,7 @@ async function handleTeardown(argv) {
|
|
|
78467
78377
|
process.exit(result.code);
|
|
78468
78378
|
}
|
|
78469
78379
|
async function handleComplete(argv) {
|
|
78470
|
-
const repo =
|
|
78380
|
+
const repo = path51.resolve(argv.repo);
|
|
78471
78381
|
const agentId = validateAgentId(argv.id, repo);
|
|
78472
78382
|
const result = await completeEnvironment({
|
|
78473
78383
|
repoPath: repo,
|
|
@@ -78488,7 +78398,7 @@ async function handleComplete(argv) {
|
|
|
78488
78398
|
process.exit(result.code);
|
|
78489
78399
|
}
|
|
78490
78400
|
async function handleStatus(argv) {
|
|
78491
|
-
const repoPath =
|
|
78401
|
+
const repoPath = path51.resolve(argv.repo);
|
|
78492
78402
|
if (argv.json) {
|
|
78493
78403
|
const status = collectEnvironmentStatus(repoPath);
|
|
78494
78404
|
const output = EnvironmentStatusSchema.parse(status);
|
|
@@ -78501,7 +78411,7 @@ async function handleStatus(argv) {
|
|
|
78501
78411
|
});
|
|
78502
78412
|
}
|
|
78503
78413
|
async function handleRunsList(argv) {
|
|
78504
|
-
const repoPath =
|
|
78414
|
+
const repoPath = path51.resolve(argv.repo);
|
|
78505
78415
|
const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
|
|
78506
78416
|
if (argv.json) {
|
|
78507
78417
|
process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
|
|
@@ -78518,7 +78428,7 @@ async function handleRunsList(argv) {
|
|
|
78518
78428
|
}
|
|
78519
78429
|
}
|
|
78520
78430
|
async function handleRunsGet(argv) {
|
|
78521
|
-
const run2 = getRun(
|
|
78431
|
+
const run2 = getRun(path51.resolve(argv.repo), argv.runId);
|
|
78522
78432
|
if (!run2) {
|
|
78523
78433
|
error(`Run not found: ${argv.runId}`);
|
|
78524
78434
|
process.exit(1);
|
|
@@ -78604,7 +78514,7 @@ function printNextSteps(auto2) {
|
|
|
78604
78514
|
}
|
|
78605
78515
|
|
|
78606
78516
|
// src/cli/commands/control.ts
|
|
78607
|
-
var
|
|
78517
|
+
var path55 = __toESM(require("path"));
|
|
78608
78518
|
|
|
78609
78519
|
// node_modules/@inquirer/core/dist/esm/lib/key.mjs
|
|
78610
78520
|
var isUpKey = (key) => (
|
|
@@ -79624,13 +79534,13 @@ var PromisePolyfill = class extends Promise {
|
|
|
79624
79534
|
// Available starting from Node 22
|
|
79625
79535
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
|
|
79626
79536
|
static withResolver() {
|
|
79627
|
-
let
|
|
79537
|
+
let resolve46;
|
|
79628
79538
|
let reject;
|
|
79629
79539
|
const promise = new Promise((res, rej) => {
|
|
79630
|
-
|
|
79540
|
+
resolve46 = res;
|
|
79631
79541
|
reject = rej;
|
|
79632
79542
|
});
|
|
79633
|
-
return { promise, resolve:
|
|
79543
|
+
return { promise, resolve: resolve46, reject };
|
|
79634
79544
|
}
|
|
79635
79545
|
};
|
|
79636
79546
|
|
|
@@ -79647,7 +79557,7 @@ function createPrompt(view) {
|
|
|
79647
79557
|
output
|
|
79648
79558
|
});
|
|
79649
79559
|
const screen = new ScreenManager(rl);
|
|
79650
|
-
const { promise, resolve:
|
|
79560
|
+
const { promise, resolve: resolve46, reject } = PromisePolyfill.withResolver();
|
|
79651
79561
|
const cancel = () => reject(new CancelPromptError());
|
|
79652
79562
|
if (signal) {
|
|
79653
79563
|
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
@@ -79671,7 +79581,7 @@ function createPrompt(view) {
|
|
|
79671
79581
|
cycle(() => {
|
|
79672
79582
|
try {
|
|
79673
79583
|
const nextView = view(config2, (value) => {
|
|
79674
|
-
setImmediate(() =>
|
|
79584
|
+
setImmediate(() => resolve46(value));
|
|
79675
79585
|
});
|
|
79676
79586
|
const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
|
|
79677
79587
|
screen.render(content, bottomContent);
|
|
@@ -80658,9 +80568,9 @@ var import_run_async = __toESM(require_run_async(), 1);
|
|
|
80658
80568
|
var import_mute_stream2 = __toESM(require_lib3(), 1);
|
|
80659
80569
|
var import_ansi_escapes5 = __toESM(require_ansi_escapes(), 1);
|
|
80660
80570
|
var _2 = {
|
|
80661
|
-
set: (obj,
|
|
80571
|
+
set: (obj, path62 = "", value) => {
|
|
80662
80572
|
let pointer = obj;
|
|
80663
|
-
|
|
80573
|
+
path62.split(".").forEach((key, index, arr) => {
|
|
80664
80574
|
if (key === "__proto__" || key === "constructor")
|
|
80665
80575
|
return;
|
|
80666
80576
|
if (index === arr.length - 1) {
|
|
@@ -80671,8 +80581,8 @@ var _2 = {
|
|
|
80671
80581
|
pointer = pointer[key];
|
|
80672
80582
|
});
|
|
80673
80583
|
},
|
|
80674
|
-
get: (obj,
|
|
80675
|
-
const travel = (regexp) => String.prototype.split.call(
|
|
80584
|
+
get: (obj, path62 = "", defaultValue) => {
|
|
80585
|
+
const travel = (regexp) => String.prototype.split.call(path62, regexp).filter(Boolean).reduce(
|
|
80676
80586
|
// @ts-expect-error implicit any on res[key]
|
|
80677
80587
|
(res, key) => res !== null && res !== void 0 ? res[key] : res,
|
|
80678
80588
|
obj
|
|
@@ -80786,7 +80696,7 @@ var PromptsRunner = class {
|
|
|
80786
80696
|
throw new Error(`Prompt for type ${question.type} not found`);
|
|
80787
80697
|
}
|
|
80788
80698
|
let cleanupSignal;
|
|
80789
|
-
const promptFn = isPromptConstructor(prompt2) ? (q2, { signal: signal2 } = {}) => new Promise((
|
|
80699
|
+
const promptFn = isPromptConstructor(prompt2) ? (q2, { signal: signal2 } = {}) => new Promise((resolve46, reject) => {
|
|
80790
80700
|
const rl = import_node_readline.default.createInterface(setupReadlineOptions(this.opt));
|
|
80791
80701
|
rl.resume();
|
|
80792
80702
|
const onClose = () => {
|
|
@@ -80822,7 +80732,7 @@ var PromptsRunner = class {
|
|
|
80822
80732
|
cleanupSignal = void 0;
|
|
80823
80733
|
};
|
|
80824
80734
|
}
|
|
80825
|
-
activePrompt.run().then(
|
|
80735
|
+
activePrompt.run().then(resolve46, reject).finally(cleanup);
|
|
80826
80736
|
}) : prompt2;
|
|
80827
80737
|
const { signal: moduleSignal } = this.opt;
|
|
80828
80738
|
if (moduleSignal?.aborted) {
|
|
@@ -80926,12 +80836,12 @@ init_control_config();
|
|
|
80926
80836
|
// src/core/control-sync-selection.ts
|
|
80927
80837
|
var fs46 = __toESM(require("fs"));
|
|
80928
80838
|
var os17 = __toESM(require("os"));
|
|
80929
|
-
var
|
|
80839
|
+
var path52 = __toESM(require("path"));
|
|
80930
80840
|
function getSelectionPath() {
|
|
80931
80841
|
if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
|
|
80932
|
-
return
|
|
80842
|
+
return path52.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
|
|
80933
80843
|
}
|
|
80934
|
-
return
|
|
80844
|
+
return path52.join(os17.homedir(), ".har", "sync-selection.json");
|
|
80935
80845
|
}
|
|
80936
80846
|
function readSyncSelection() {
|
|
80937
80847
|
const selectionPath = getSelectionPath();
|
|
@@ -80947,7 +80857,7 @@ function readSyncSelection() {
|
|
|
80947
80857
|
function writeSyncSelection(repos) {
|
|
80948
80858
|
const selectionPath = getSelectionPath();
|
|
80949
80859
|
const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
|
|
80950
|
-
fs46.mkdirSync(
|
|
80860
|
+
fs46.mkdirSync(path52.dirname(selectionPath), { recursive: true });
|
|
80951
80861
|
fs46.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
|
|
80952
80862
|
}
|
|
80953
80863
|
function resolveSyncSelection(input) {
|
|
@@ -80995,7 +80905,7 @@ function openBrowser(url) {
|
|
|
80995
80905
|
}
|
|
80996
80906
|
async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
|
|
80997
80907
|
const state = (0, import_crypto.randomUUID)();
|
|
80998
|
-
return new Promise((
|
|
80908
|
+
return new Promise((resolve46, reject) => {
|
|
80999
80909
|
let timer;
|
|
81000
80910
|
const server = http.createServer((req, res) => {
|
|
81001
80911
|
const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
|
|
@@ -81018,7 +80928,7 @@ async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
|
|
|
81018
80928
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
81019
80929
|
res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
|
|
81020
80930
|
cleanup();
|
|
81021
|
-
|
|
80931
|
+
resolve46({ portalUrl, token, workspace, email: email2, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
81022
80932
|
});
|
|
81023
80933
|
const cleanup = () => {
|
|
81024
80934
|
clearTimeout(timer);
|
|
@@ -81046,13 +80956,13 @@ If your browser did not open, paste that URL.
|
|
|
81046
80956
|
|
|
81047
80957
|
// src/core/control-unregister.ts
|
|
81048
80958
|
var fs47 = __toESM(require("fs"));
|
|
81049
|
-
var
|
|
80959
|
+
var path53 = __toESM(require("path"));
|
|
81050
80960
|
init_control_config();
|
|
81051
80961
|
function listUnregisterWorktreeCandidates(repoPath) {
|
|
81052
80962
|
const harnessRoot = canonicalizeControlRepoPath(repoPath);
|
|
81053
80963
|
const byPath = /* @__PURE__ */ new Map();
|
|
81054
80964
|
const add = (partial2) => {
|
|
81055
|
-
const resolved =
|
|
80965
|
+
const resolved = path53.resolve(partial2.worktreePath);
|
|
81056
80966
|
if (!resolved || resolved === harnessRoot) return;
|
|
81057
80967
|
const exists = partial2.exists ?? fs47.existsSync(resolved);
|
|
81058
80968
|
const prev = byPath.get(resolved);
|
|
@@ -81105,8 +81015,8 @@ async function askYesNo6(question) {
|
|
|
81105
81015
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
81106
81016
|
const readline10 = await import("readline");
|
|
81107
81017
|
const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
|
|
81108
|
-
const answer = await new Promise((
|
|
81109
|
-
rl.question(question,
|
|
81018
|
+
const answer = await new Promise((resolve46) => {
|
|
81019
|
+
rl.question(question, resolve46);
|
|
81110
81020
|
});
|
|
81111
81021
|
rl.close();
|
|
81112
81022
|
return /^[Yy]$/.test(answer.trim());
|
|
@@ -81252,15 +81162,15 @@ init_control_config();
|
|
|
81252
81162
|
|
|
81253
81163
|
// src/core/harness-scrub.ts
|
|
81254
81164
|
var fs48 = __toESM(require("fs"));
|
|
81255
|
-
var
|
|
81165
|
+
var path54 = __toESM(require("path"));
|
|
81256
81166
|
var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
|
|
81257
81167
|
function scrubLocalHarnessDirs(repoPath) {
|
|
81258
81168
|
const results = [];
|
|
81259
|
-
const resolved =
|
|
81169
|
+
const resolved = path54.resolve(repoPath);
|
|
81260
81170
|
if (!fs48.existsSync(resolved)) {
|
|
81261
81171
|
for (const directory of HARNESS_SCRUB_DIRS) {
|
|
81262
81172
|
results.push({
|
|
81263
|
-
path:
|
|
81173
|
+
path: path54.join(resolved, ".har", directory),
|
|
81264
81174
|
directory,
|
|
81265
81175
|
deleted: false,
|
|
81266
81176
|
error: "repository path does not exist"
|
|
@@ -81269,7 +81179,7 @@ function scrubLocalHarnessDirs(repoPath) {
|
|
|
81269
81179
|
return results;
|
|
81270
81180
|
}
|
|
81271
81181
|
for (const directory of HARNESS_SCRUB_DIRS) {
|
|
81272
|
-
const target =
|
|
81182
|
+
const target = path54.join(resolved, ".har", directory);
|
|
81273
81183
|
if (!fs48.existsSync(target)) {
|
|
81274
81184
|
results.push({ path: target, directory, deleted: true });
|
|
81275
81185
|
continue;
|
|
@@ -81297,7 +81207,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
|
|
|
81297
81207
|
const results = [];
|
|
81298
81208
|
const seen = /* @__PURE__ */ new Set();
|
|
81299
81209
|
for (const repoPath of repoPaths) {
|
|
81300
|
-
const key =
|
|
81210
|
+
const key = path54.resolve(repoPath);
|
|
81301
81211
|
if (seen.has(key)) continue;
|
|
81302
81212
|
seen.add(key);
|
|
81303
81213
|
results.push(...scrubLocalHarnessDirs(key));
|
|
@@ -81310,8 +81220,8 @@ async function askYesNo7(question) {
|
|
|
81310
81220
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
81311
81221
|
const readline10 = await import("readline");
|
|
81312
81222
|
const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
|
|
81313
|
-
const answer = await new Promise((
|
|
81314
|
-
rl.question(question,
|
|
81223
|
+
const answer = await new Promise((resolve46) => {
|
|
81224
|
+
rl.question(question, resolve46);
|
|
81315
81225
|
});
|
|
81316
81226
|
rl.close();
|
|
81317
81227
|
return /^[Yy]$/.test(answer.trim());
|
|
@@ -81556,7 +81466,7 @@ async function handleDown() {
|
|
|
81556
81466
|
process.exit(code);
|
|
81557
81467
|
}
|
|
81558
81468
|
async function handleRegister(argv) {
|
|
81559
|
-
const repoPath =
|
|
81469
|
+
const repoPath = path55.resolve(argv.repo);
|
|
81560
81470
|
header("har control register");
|
|
81561
81471
|
info(`Repository: ${repoPath}`);
|
|
81562
81472
|
try {
|
|
@@ -81648,7 +81558,7 @@ async function handleReset(argv) {
|
|
|
81648
81558
|
}
|
|
81649
81559
|
}
|
|
81650
81560
|
async function handleUnregister(argv) {
|
|
81651
|
-
const repoPath =
|
|
81561
|
+
const repoPath = path55.resolve(argv.repo);
|
|
81652
81562
|
const worktrees = listUnregisterWorktreeCandidates(repoPath);
|
|
81653
81563
|
try {
|
|
81654
81564
|
let deleteWorktrees = argv.deleteWorktrees;
|
|
@@ -81809,7 +81719,7 @@ async function handleWatch(argv) {
|
|
|
81809
81719
|
};
|
|
81810
81720
|
const tick = async () => {
|
|
81811
81721
|
if (argv.repo) {
|
|
81812
|
-
await syncOne(
|
|
81722
|
+
await syncOne(path55.resolve(argv.repo));
|
|
81813
81723
|
return;
|
|
81814
81724
|
}
|
|
81815
81725
|
try {
|
|
@@ -81859,11 +81769,11 @@ async function handleLogin(argv) {
|
|
|
81859
81769
|
}
|
|
81860
81770
|
|
|
81861
81771
|
// src/cli/commands/hooks.ts
|
|
81862
|
-
var
|
|
81772
|
+
var path57 = __toESM(require("path"));
|
|
81863
81773
|
|
|
81864
81774
|
// src/core/claude-hooks.ts
|
|
81865
81775
|
var fs49 = __toESM(require("fs"));
|
|
81866
|
-
var
|
|
81776
|
+
var path56 = __toESM(require("path"));
|
|
81867
81777
|
var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
|
|
81868
81778
|
var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
|
|
81869
81779
|
var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
|
|
@@ -81884,7 +81794,7 @@ function readSettings(settingsPath) {
|
|
|
81884
81794
|
return parsed;
|
|
81885
81795
|
}
|
|
81886
81796
|
function writeSettings(settingsPath, settings) {
|
|
81887
|
-
fs49.mkdirSync(
|
|
81797
|
+
fs49.mkdirSync(path56.dirname(settingsPath), { recursive: true });
|
|
81888
81798
|
fs49.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
81889
81799
|
}
|
|
81890
81800
|
function installClaudeGuard(repoPath) {
|
|
@@ -81892,11 +81802,11 @@ function installClaudeGuard(repoPath) {
|
|
|
81892
81802
|
if (!templatePath) {
|
|
81893
81803
|
throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
|
|
81894
81804
|
}
|
|
81895
|
-
const guardScript =
|
|
81896
|
-
fs49.mkdirSync(
|
|
81805
|
+
const guardScript = path56.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
81806
|
+
fs49.mkdirSync(path56.dirname(guardScript), { recursive: true });
|
|
81897
81807
|
fs49.copyFileSync(templatePath, guardScript);
|
|
81898
81808
|
fs49.chmodSync(guardScript, 493);
|
|
81899
|
-
const settingsPath =
|
|
81809
|
+
const settingsPath = path56.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
81900
81810
|
const settings = readSettings(settingsPath);
|
|
81901
81811
|
const hooks = settings.hooks ?? {};
|
|
81902
81812
|
const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
|
|
@@ -81910,14 +81820,14 @@ function installClaudeGuard(repoPath) {
|
|
|
81910
81820
|
}
|
|
81911
81821
|
function uninstallClaudeGuard(repoPath) {
|
|
81912
81822
|
let removed = false;
|
|
81913
|
-
const guardScript =
|
|
81823
|
+
const guardScript = path56.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
81914
81824
|
if (fs49.existsSync(guardScript)) {
|
|
81915
81825
|
fs49.rmSync(guardScript);
|
|
81916
81826
|
removed = true;
|
|
81917
|
-
const parent =
|
|
81827
|
+
const parent = path56.dirname(guardScript);
|
|
81918
81828
|
if (fs49.existsSync(parent) && fs49.readdirSync(parent).length === 0) fs49.rmdirSync(parent);
|
|
81919
81829
|
}
|
|
81920
|
-
const settingsPath =
|
|
81830
|
+
const settingsPath = path56.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
81921
81831
|
if (fs49.existsSync(settingsPath)) {
|
|
81922
81832
|
const settings = readSettings(settingsPath);
|
|
81923
81833
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
@@ -81943,7 +81853,7 @@ function uninstallClaudeGuard(repoPath) {
|
|
|
81943
81853
|
return { removed };
|
|
81944
81854
|
}
|
|
81945
81855
|
function claudeGuardInstalled(repoPath) {
|
|
81946
|
-
const settingsPath =
|
|
81856
|
+
const settingsPath = path56.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
81947
81857
|
if (!fs49.existsSync(settingsPath)) return false;
|
|
81948
81858
|
try {
|
|
81949
81859
|
const settings = readSettings(settingsPath);
|
|
@@ -81960,7 +81870,7 @@ function repoOption(y2) {
|
|
|
81960
81870
|
function handleInstall2(argv) {
|
|
81961
81871
|
try {
|
|
81962
81872
|
if (argv.claude) {
|
|
81963
|
-
const result2 = installClaudeGuard(
|
|
81873
|
+
const result2 = installClaudeGuard(path57.resolve(argv.repo));
|
|
81964
81874
|
success("Claude Code worktree guard installed.");
|
|
81965
81875
|
info(`Guard script: ${result2.guardScript}`);
|
|
81966
81876
|
info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
|
|
@@ -81968,7 +81878,7 @@ function handleInstall2(argv) {
|
|
|
81968
81878
|
info("Commit both files so the guard travels with the repo.");
|
|
81969
81879
|
return;
|
|
81970
81880
|
}
|
|
81971
|
-
const result = installHooks({ repoPath:
|
|
81881
|
+
const result = installHooks({ repoPath: path57.resolve(argv.repo), force: argv.force });
|
|
81972
81882
|
success(`Commit gate installed in ${result.hooksDir}`);
|
|
81973
81883
|
info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
|
|
81974
81884
|
info("Commits of unverified change batches will be blocked in agent worktrees.");
|
|
@@ -81981,7 +81891,7 @@ function handleInstall2(argv) {
|
|
|
81981
81891
|
function handleUninstall(argv) {
|
|
81982
81892
|
try {
|
|
81983
81893
|
if (argv.claude) {
|
|
81984
|
-
const result2 = uninstallClaudeGuard(
|
|
81894
|
+
const result2 = uninstallClaudeGuard(path57.resolve(argv.repo));
|
|
81985
81895
|
if (result2.removed) {
|
|
81986
81896
|
success("Claude Code worktree guard removed.");
|
|
81987
81897
|
} else {
|
|
@@ -81989,7 +81899,7 @@ function handleUninstall(argv) {
|
|
|
81989
81899
|
}
|
|
81990
81900
|
return;
|
|
81991
81901
|
}
|
|
81992
|
-
const result = uninstallHooks(
|
|
81902
|
+
const result = uninstallHooks(path57.resolve(argv.repo));
|
|
81993
81903
|
if (result.removed) {
|
|
81994
81904
|
success(`Commit gate removed from ${result.hooksDir}`);
|
|
81995
81905
|
} else {
|
|
@@ -82002,7 +81912,7 @@ function handleUninstall(argv) {
|
|
|
82002
81912
|
}
|
|
82003
81913
|
function handleStatus2(argv) {
|
|
82004
81914
|
try {
|
|
82005
|
-
const status = getHooksStatus(
|
|
81915
|
+
const status = getHooksStatus(path57.resolve(argv.repo));
|
|
82006
81916
|
if (argv.json) {
|
|
82007
81917
|
process.stdout.write(`${JSON.stringify(status, null, 2)}
|
|
82008
81918
|
`);
|
|
@@ -82020,7 +81930,7 @@ function handleStatus2(argv) {
|
|
|
82020
81930
|
);
|
|
82021
81931
|
info(`Effective: ${status.effectiveMode} (in this checkout)`);
|
|
82022
81932
|
info(
|
|
82023
|
-
`Claude guard: ${claudeGuardInstalled(
|
|
81933
|
+
`Claude guard: ${claudeGuardInstalled(path57.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
|
|
82024
81934
|
);
|
|
82025
81935
|
} catch (err) {
|
|
82026
81936
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -82281,10 +82191,10 @@ function assignProp(target, prop, value) {
|
|
|
82281
82191
|
configurable: true
|
|
82282
82192
|
});
|
|
82283
82193
|
}
|
|
82284
|
-
function getElementAtPath(obj,
|
|
82285
|
-
if (!
|
|
82194
|
+
function getElementAtPath(obj, path62) {
|
|
82195
|
+
if (!path62)
|
|
82286
82196
|
return obj;
|
|
82287
|
-
return
|
|
82197
|
+
return path62.reduce((acc, key) => acc?.[key], obj);
|
|
82288
82198
|
}
|
|
82289
82199
|
function promiseAllObject(promisesObj) {
|
|
82290
82200
|
const keys = Object.keys(promisesObj);
|
|
@@ -82604,11 +82514,11 @@ function aborted(x2, startIndex = 0) {
|
|
|
82604
82514
|
}
|
|
82605
82515
|
return false;
|
|
82606
82516
|
}
|
|
82607
|
-
function prefixIssues(
|
|
82517
|
+
function prefixIssues(path62, issues) {
|
|
82608
82518
|
return issues.map((iss) => {
|
|
82609
82519
|
var _a3;
|
|
82610
82520
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
82611
|
-
iss.path.unshift(
|
|
82521
|
+
iss.path.unshift(path62);
|
|
82612
82522
|
return iss;
|
|
82613
82523
|
});
|
|
82614
82524
|
}
|
|
@@ -87931,7 +87841,7 @@ var Protocol = class {
|
|
|
87931
87841
|
return;
|
|
87932
87842
|
}
|
|
87933
87843
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
87934
|
-
await new Promise((
|
|
87844
|
+
await new Promise((resolve46) => setTimeout(resolve46, pollInterval));
|
|
87935
87845
|
options?.signal?.throwIfAborted();
|
|
87936
87846
|
}
|
|
87937
87847
|
} catch (error3) {
|
|
@@ -87948,7 +87858,7 @@ var Protocol = class {
|
|
|
87948
87858
|
*/
|
|
87949
87859
|
request(request, resultSchema, options) {
|
|
87950
87860
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
87951
|
-
return new Promise((
|
|
87861
|
+
return new Promise((resolve46, reject) => {
|
|
87952
87862
|
const earlyReject = (error3) => {
|
|
87953
87863
|
reject(error3);
|
|
87954
87864
|
};
|
|
@@ -88026,7 +87936,7 @@ var Protocol = class {
|
|
|
88026
87936
|
if (!parseResult.success) {
|
|
88027
87937
|
reject(parseResult.error);
|
|
88028
87938
|
} else {
|
|
88029
|
-
|
|
87939
|
+
resolve46(parseResult.data);
|
|
88030
87940
|
}
|
|
88031
87941
|
} catch (error3) {
|
|
88032
87942
|
reject(error3);
|
|
@@ -88287,12 +88197,12 @@ var Protocol = class {
|
|
|
88287
88197
|
}
|
|
88288
88198
|
} catch {
|
|
88289
88199
|
}
|
|
88290
|
-
return new Promise((
|
|
88200
|
+
return new Promise((resolve46, reject) => {
|
|
88291
88201
|
if (signal.aborted) {
|
|
88292
88202
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
88293
88203
|
return;
|
|
88294
88204
|
}
|
|
88295
|
-
const timeoutId = setTimeout(
|
|
88205
|
+
const timeoutId = setTimeout(resolve46, interval);
|
|
88296
88206
|
signal.addEventListener("abort", () => {
|
|
88297
88207
|
clearTimeout(timeoutId);
|
|
88298
88208
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -89082,7 +88992,7 @@ var Server = class extends Protocol {
|
|
|
89082
88992
|
};
|
|
89083
88993
|
|
|
89084
88994
|
// src/mcp/server.ts
|
|
89085
|
-
var
|
|
88995
|
+
var path58 = __toESM(require("path"));
|
|
89086
88996
|
|
|
89087
88997
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
89088
88998
|
var import_node_process3 = __toESM(require("node:process"), 1);
|
|
@@ -89165,12 +89075,12 @@ var StdioServerTransport = class {
|
|
|
89165
89075
|
this.onclose?.();
|
|
89166
89076
|
}
|
|
89167
89077
|
send(message) {
|
|
89168
|
-
return new Promise((
|
|
89078
|
+
return new Promise((resolve46) => {
|
|
89169
89079
|
const json = serializeMessage(message);
|
|
89170
89080
|
if (this._stdout.write(json)) {
|
|
89171
|
-
|
|
89081
|
+
resolve46();
|
|
89172
89082
|
} else {
|
|
89173
|
-
this._stdout.once("drain",
|
|
89083
|
+
this._stdout.once("drain", resolve46);
|
|
89174
89084
|
}
|
|
89175
89085
|
});
|
|
89176
89086
|
}
|
|
@@ -89250,13 +89160,9 @@ var LaunchEnvironmentInputSchema = external_exports.object({
|
|
|
89250
89160
|
agentId: agentIdSchema,
|
|
89251
89161
|
worktree: external_exports.boolean().default(true),
|
|
89252
89162
|
claude: external_exports.boolean().default(false),
|
|
89253
|
-
|
|
89254
|
-
"
|
|
89255
|
-
),
|
|
89256
|
-
force: external_exports.boolean().default(false).describe(
|
|
89257
|
-
"Discard uncommitted changes in a dirty occupied worktree. Requires confirmReplace=true and explicit user approval \u2014 never set autonomously."
|
|
89163
|
+
resume: external_exports.boolean().default(false).describe(
|
|
89164
|
+
"Resume a failed or partial launch without creating a new worktree. Only valid for failed/starting sessions \u2014 otherwise call har_get_status, then har_complete_environment or har_teardown_environment before launching again."
|
|
89258
89165
|
),
|
|
89259
|
-
resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree."),
|
|
89260
89166
|
workUnitId: external_exports.string().min(1).max(128).optional(),
|
|
89261
89167
|
source: external_exports.string().min(1).max(64).optional(),
|
|
89262
89168
|
sourceUrl: external_exports.string().url().optional(),
|
|
@@ -89282,9 +89188,7 @@ var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
|
|
|
89282
89188
|
});
|
|
89283
89189
|
var PreflightEnvironmentInputSchema = external_exports.object({
|
|
89284
89190
|
repo: external_exports.string().default("."),
|
|
89285
|
-
agentId: agentIdSchema
|
|
89286
|
-
confirmReplace: external_exports.boolean().default(false).describe("Treat an occupied slot as replaceable (same as launch confirmReplace)."),
|
|
89287
|
-
force: external_exports.boolean().default(false).describe("Allow replacing a dirty worktree (requires explicit user approval).")
|
|
89191
|
+
agentId: agentIdSchema
|
|
89288
89192
|
});
|
|
89289
89193
|
var PreflightEnvironmentOutputSchema = ShellRunOutputSchema.extend({
|
|
89290
89194
|
readiness: SlotReadinessSchema,
|
|
@@ -89384,24 +89288,16 @@ var HAR_MCP_TOOLS = [
|
|
|
89384
89288
|
},
|
|
89385
89289
|
{
|
|
89386
89290
|
name: "har_launch_environment",
|
|
89387
|
-
description: "Start a FRESH agent session from the main checkout HEAD (switch that checkout to main first for a new unrelated task). Run BEFORE editing any file: returns workDir \u2014 ALL edits go there, never the main checkout.
|
|
89291
|
+
description: "Start a FRESH agent session from the main checkout HEAD (switch that checkout to main first for a new unrelated task). Run BEFORE editing any file: returns workDir \u2014 ALL edits go there, never the main checkout. Occupied slots always block: call har_get_status, then har_complete_environment or har_teardown_environment, then relaunch \u2014 unless the session is failed/starting, in which case pass resume=true (or use har_recover_environment).",
|
|
89388
89292
|
inputSchema: objectJsonSchema(
|
|
89389
89293
|
{
|
|
89390
89294
|
repo: repoJsonProperty,
|
|
89391
89295
|
agentId: agentIdJsonProperty,
|
|
89392
89296
|
worktree: { type: "boolean" },
|
|
89393
89297
|
claude: { type: "boolean" },
|
|
89394
|
-
confirmReplace: {
|
|
89395
|
-
type: "boolean",
|
|
89396
|
-
description: "Destroy the previous session on this slot and start another from main-checkout HEAD. Does not choose main. Prefer complete/teardown when the prior task is finished. Call har_get_status first; get explicit user approval."
|
|
89397
|
-
},
|
|
89398
|
-
force: {
|
|
89399
|
-
type: "boolean",
|
|
89400
|
-
description: "Discard uncommitted changes when replacing a dirty worktree. Requires confirmReplace=true and explicit user approval."
|
|
89401
|
-
},
|
|
89402
89298
|
resume: {
|
|
89403
89299
|
type: "boolean",
|
|
89404
|
-
description: "Resume a failed or partial launch (status failed/starting) without
|
|
89300
|
+
description: "Resume a failed or partial launch (status failed/starting) without creating a new worktree. Preserves worktree and env. Not usable to replace an active/completed slot \u2014 free it with har_complete_environment or har_teardown_environment first."
|
|
89405
89301
|
},
|
|
89406
89302
|
workUnitId: {
|
|
89407
89303
|
type: "string",
|
|
@@ -89435,15 +89331,7 @@ var HAR_MCP_TOOLS = [
|
|
|
89435
89331
|
inputSchema: objectJsonSchema(
|
|
89436
89332
|
{
|
|
89437
89333
|
repo: repoJsonProperty,
|
|
89438
|
-
agentId: agentIdJsonProperty
|
|
89439
|
-
confirmReplace: {
|
|
89440
|
-
type: "boolean",
|
|
89441
|
-
description: "Treat an occupied slot as replaceable (same as launch confirmReplace)."
|
|
89442
|
-
},
|
|
89443
|
-
force: {
|
|
89444
|
-
type: "boolean",
|
|
89445
|
-
description: "Allow replacing a dirty worktree (only after explicit user approval)."
|
|
89446
|
-
}
|
|
89334
|
+
agentId: agentIdJsonProperty
|
|
89447
89335
|
},
|
|
89448
89336
|
["agentId"]
|
|
89449
89337
|
)
|
|
@@ -89577,7 +89465,6 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
89577
89465
|
smoke: input.smoke,
|
|
89578
89466
|
profile: input.profile
|
|
89579
89467
|
});
|
|
89580
|
-
recordRepoForControlSync(repo);
|
|
89581
89468
|
return jsonContent({
|
|
89582
89469
|
harnessDir: result.harnessDir,
|
|
89583
89470
|
validation: result.validation,
|
|
@@ -89593,8 +89480,6 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
89593
89480
|
agentId,
|
|
89594
89481
|
worktree: input.worktree,
|
|
89595
89482
|
claude: input.claude,
|
|
89596
|
-
confirmReplace: input.confirmReplace,
|
|
89597
|
-
force: input.force,
|
|
89598
89483
|
resume: input.resume,
|
|
89599
89484
|
workUnitId: input.workUnitId,
|
|
89600
89485
|
source: input.source,
|
|
@@ -89617,8 +89502,6 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
89617
89502
|
agentId,
|
|
89618
89503
|
worktree: input.worktree,
|
|
89619
89504
|
claude: input.claude,
|
|
89620
|
-
confirmReplace: false,
|
|
89621
|
-
force: false,
|
|
89622
89505
|
resume: true,
|
|
89623
89506
|
workUnitId: input.workUnitId,
|
|
89624
89507
|
source: input.source,
|
|
@@ -89638,9 +89521,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
89638
89521
|
const agentId = validateAgentId(input.agentId, repo);
|
|
89639
89522
|
const result = await preflightEnvironment({
|
|
89640
89523
|
repoPath: repo,
|
|
89641
|
-
agentId
|
|
89642
|
-
confirmReplace: input.confirmReplace,
|
|
89643
|
-
force: input.force
|
|
89524
|
+
agentId
|
|
89644
89525
|
});
|
|
89645
89526
|
const parsed = PreflightEnvironmentOutputSchema.parse(result);
|
|
89646
89527
|
return {
|
|
@@ -89745,7 +89626,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
89745
89626
|
const input = ControlUpInputSchema.parse({ ...args, repo });
|
|
89746
89627
|
const result = await startControlAndSync({
|
|
89747
89628
|
detach: input.detach,
|
|
89748
|
-
cwd:
|
|
89629
|
+
cwd: path58.resolve(input.repo)
|
|
89749
89630
|
});
|
|
89750
89631
|
if (result.code !== 0) {
|
|
89751
89632
|
return {
|
|
@@ -89809,10 +89690,10 @@ var mcpCommand = {
|
|
|
89809
89690
|
};
|
|
89810
89691
|
|
|
89811
89692
|
// src/cli/commands/onboard.ts
|
|
89812
|
-
var
|
|
89693
|
+
var path60 = __toESM(require("path"));
|
|
89813
89694
|
|
|
89814
89695
|
// src/core/onboarding.ts
|
|
89815
|
-
var
|
|
89696
|
+
var path59 = __toESM(require("path"));
|
|
89816
89697
|
init_control_config();
|
|
89817
89698
|
init_otel_hooks();
|
|
89818
89699
|
init_telemetry_config();
|
|
@@ -89944,7 +89825,7 @@ async function defaultEnsureControl(options) {
|
|
|
89944
89825
|
return { started: true, apiUrl: result.apiUrl };
|
|
89945
89826
|
}
|
|
89946
89827
|
async function runOnboarding(options, deps = {}) {
|
|
89947
|
-
const repoPath =
|
|
89828
|
+
const repoPath = path59.resolve(options.repoPath);
|
|
89948
89829
|
const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
|
|
89949
89830
|
const ensureControl = deps.ensureControl ?? defaultEnsureControl;
|
|
89950
89831
|
const init = deps.initHarness ?? initHarness;
|
|
@@ -89977,9 +89858,20 @@ async function runOnboarding(options, deps = {}) {
|
|
|
89977
89858
|
warn("Harness has validation errors \u2014 review .har/ after adaptation.");
|
|
89978
89859
|
}
|
|
89979
89860
|
harnessInitialized = true;
|
|
89980
|
-
recordRepoForControlSync(repoPath);
|
|
89981
89861
|
success("Harness scaffolded");
|
|
89982
89862
|
}
|
|
89863
|
+
let agentSlots = null;
|
|
89864
|
+
if (harnessExists(repoPath)) {
|
|
89865
|
+
if (options.agentSlotsMax !== void 0) {
|
|
89866
|
+
applyAgentSlotMax(repoPath, options.agentSlotsMax);
|
|
89867
|
+
info(`Agent slots: 1\u2013${options.agentSlotsMax} parallel (written to .har/stages.json)`);
|
|
89868
|
+
}
|
|
89869
|
+
try {
|
|
89870
|
+
agentSlots = getAgentSlotRange(repoPath);
|
|
89871
|
+
} catch {
|
|
89872
|
+
agentSlots = null;
|
|
89873
|
+
}
|
|
89874
|
+
}
|
|
89983
89875
|
const pluginsApplied = [];
|
|
89984
89876
|
const pluginWarnings = [];
|
|
89985
89877
|
if (options.plugins.length > 0) {
|
|
@@ -90028,7 +89920,8 @@ async function runOnboarding(options, deps = {}) {
|
|
|
90028
89920
|
pluginsApplied,
|
|
90029
89921
|
pluginWarnings,
|
|
90030
89922
|
adaptationPromptPath,
|
|
90031
|
-
adaptationPromptCopied
|
|
89923
|
+
adaptationPromptCopied,
|
|
89924
|
+
agentSlots
|
|
90032
89925
|
};
|
|
90033
89926
|
}
|
|
90034
89927
|
async function finalizeOnboardingAdaptation(options) {
|
|
@@ -90059,6 +89952,27 @@ function parsePluginsFlag(raw) {
|
|
|
90059
89952
|
}
|
|
90060
89953
|
return selected;
|
|
90061
89954
|
}
|
|
89955
|
+
function defaultAgentSlotMaxForProfile(profile) {
|
|
89956
|
+
return profile === "default" ? 5 : 3;
|
|
89957
|
+
}
|
|
89958
|
+
function parseAgentSlotsFlag(raw) {
|
|
89959
|
+
if (raw === void 0) return void 0;
|
|
89960
|
+
if (!Number.isInteger(raw) || raw < HAR_AGENT_SLOT_MIN || raw > HAR_AGENT_SLOT_ONBOARD_MAX) {
|
|
89961
|
+
throw new Error(
|
|
89962
|
+
`--agent-slots must be an integer from ${HAR_AGENT_SLOT_MIN} to ${HAR_AGENT_SLOT_ONBOARD_MAX}`
|
|
89963
|
+
);
|
|
89964
|
+
}
|
|
89965
|
+
return raw;
|
|
89966
|
+
}
|
|
89967
|
+
function resolveDefaultAgentSlotsMax(repoPath, profile, alreadyPresent) {
|
|
89968
|
+
if (alreadyPresent) {
|
|
89969
|
+
try {
|
|
89970
|
+
return getAgentSlotRange(repoPath).max;
|
|
89971
|
+
} catch {
|
|
89972
|
+
}
|
|
89973
|
+
}
|
|
89974
|
+
return defaultAgentSlotMaxForProfile(profile);
|
|
89975
|
+
}
|
|
90062
89976
|
async function pauseForGuide(autoYes) {
|
|
90063
89977
|
if (autoYes || !process.stdin.isTTY || !process.stdout.isTTY) return;
|
|
90064
89978
|
await esm_default13.prompt([
|
|
@@ -90070,20 +89984,23 @@ async function pauseForGuide(autoYes) {
|
|
|
90070
89984
|
]);
|
|
90071
89985
|
}
|
|
90072
89986
|
async function promptChoices(args) {
|
|
89987
|
+
const flaggedSlots = parseAgentSlotsFlag(args.agentSlots);
|
|
89988
|
+
const shouldConfigureSlots = !args.skipInit;
|
|
90073
89989
|
if (args.yes) {
|
|
90074
89990
|
const telemetry2 = args.telemetry ?? "on";
|
|
90075
89991
|
return {
|
|
90076
89992
|
profile: args.profile ?? "default",
|
|
90077
89993
|
telemetry: telemetry2,
|
|
90078
89994
|
startControl: args.control ?? telemetry2 !== "off",
|
|
90079
|
-
plugins: parsePluginsFlag(args.plugins) ?? []
|
|
89995
|
+
plugins: parsePluginsFlag(args.plugins) ?? [],
|
|
89996
|
+
agentSlotsMax: shouldConfigureSlots ? flaggedSlots : void 0
|
|
90080
89997
|
};
|
|
90081
89998
|
}
|
|
90082
89999
|
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
90083
90000
|
if (!interactive) {
|
|
90084
|
-
if (args.telemetry === void 0 && args.control === void 0 && args.plugins === void 0 && args.profile === void 0) {
|
|
90001
|
+
if (args.telemetry === void 0 && args.control === void 0 && args.plugins === void 0 && args.profile === void 0 && args.agentSlots === void 0) {
|
|
90085
90002
|
throw new Error(
|
|
90086
|
-
"Interactive onboarding requires a TTY. Pass --yes or flags (--profile, --telemetry, --control/--no-control, --plugins)."
|
|
90003
|
+
"Interactive onboarding requires a TTY. Pass --yes or flags (--profile, --telemetry, --control/--no-control, --plugins, --agent-slots)."
|
|
90087
90004
|
);
|
|
90088
90005
|
}
|
|
90089
90006
|
const telemetry2 = args.telemetry ?? "on";
|
|
@@ -90091,12 +90008,20 @@ async function promptChoices(args) {
|
|
|
90091
90008
|
profile: args.profile ?? "default",
|
|
90092
90009
|
telemetry: telemetry2,
|
|
90093
90010
|
startControl: args.control ?? telemetry2 !== "off",
|
|
90094
|
-
plugins: parsePluginsFlag(args.plugins) ?? []
|
|
90011
|
+
plugins: parsePluginsFlag(args.plugins) ?? [],
|
|
90012
|
+
agentSlotsMax: shouldConfigureSlots ? flaggedSlots : void 0
|
|
90095
90013
|
};
|
|
90096
90014
|
}
|
|
90097
90015
|
const pluginChoices = listPluginChoices();
|
|
90098
|
-
const
|
|
90016
|
+
const repoPath = path60.resolve(args.repo);
|
|
90017
|
+
const alreadyPresent = harnessExists(repoPath);
|
|
90099
90018
|
const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
|
|
90019
|
+
const needAgentSlots = shouldConfigureSlots && flaggedSlots === void 0;
|
|
90020
|
+
if (needAgentSlots) {
|
|
90021
|
+
info(
|
|
90022
|
+
"Each parallel slot runs an isolated copy of the stack. The practical limit depends on your machine resources (RAM/CPU) and how expensive the stack is to run (Docker services, databases, frontends, etc.). You can change this later in .har/stages.json."
|
|
90023
|
+
);
|
|
90024
|
+
}
|
|
90100
90025
|
const answers = await esm_default13.prompt([
|
|
90101
90026
|
{
|
|
90102
90027
|
type: "list",
|
|
@@ -90138,14 +90063,37 @@ async function promptChoices(args) {
|
|
|
90138
90063
|
name: plugin.label,
|
|
90139
90064
|
value: plugin.id
|
|
90140
90065
|
}))
|
|
90066
|
+
},
|
|
90067
|
+
{
|
|
90068
|
+
type: "number",
|
|
90069
|
+
name: "agentSlotsMax",
|
|
90070
|
+
message: `How many agents do you want to run in parallel? (${HAR_AGENT_SLOT_MIN}\u2013${HAR_AGENT_SLOT_ONBOARD_MAX})`,
|
|
90071
|
+
when: () => needAgentSlots,
|
|
90072
|
+
default: (current) => resolveDefaultAgentSlotsMax(
|
|
90073
|
+
repoPath,
|
|
90074
|
+
args.profile ?? current.profile ?? "default",
|
|
90075
|
+
alreadyPresent
|
|
90076
|
+
),
|
|
90077
|
+
validate: (value) => {
|
|
90078
|
+
if (value === void 0 || !Number.isInteger(value) || value < HAR_AGENT_SLOT_MIN || value > HAR_AGENT_SLOT_ONBOARD_MAX) {
|
|
90079
|
+
return `Enter an integer from ${HAR_AGENT_SLOT_MIN} to ${HAR_AGENT_SLOT_ONBOARD_MAX}`;
|
|
90080
|
+
}
|
|
90081
|
+
return true;
|
|
90082
|
+
}
|
|
90141
90083
|
}
|
|
90142
90084
|
]);
|
|
90143
90085
|
const telemetry = args.telemetry ?? answers.telemetry ?? "on";
|
|
90086
|
+
const profile = args.profile ?? answers.profile ?? "default";
|
|
90087
|
+
let agentSlotsMax;
|
|
90088
|
+
if (shouldConfigureSlots) {
|
|
90089
|
+
agentSlotsMax = flaggedSlots ?? answers.agentSlotsMax;
|
|
90090
|
+
}
|
|
90144
90091
|
return {
|
|
90145
|
-
profile
|
|
90092
|
+
profile,
|
|
90146
90093
|
telemetry,
|
|
90147
90094
|
startControl: args.control ?? answers.startControl ?? telemetry !== "off",
|
|
90148
|
-
plugins: parsePluginsFlag(args.plugins) ?? answers.plugins ?? []
|
|
90095
|
+
plugins: parsePluginsFlag(args.plugins) ?? answers.plugins ?? [],
|
|
90096
|
+
agentSlotsMax
|
|
90149
90097
|
};
|
|
90150
90098
|
}
|
|
90151
90099
|
function printSummary(result) {
|
|
@@ -90162,6 +90110,11 @@ function printSummary(result) {
|
|
|
90162
90110
|
info(
|
|
90163
90111
|
`Plugins: ${result.pluginsApplied.length > 0 ? result.pluginsApplied.join(", ") : "none"}`
|
|
90164
90112
|
);
|
|
90113
|
+
if (result.agentSlots) {
|
|
90114
|
+
info(
|
|
90115
|
+
`Agent slots: ${result.agentSlots.min}\u2013${result.agentSlots.max} parallel (see .har/stages.json)`
|
|
90116
|
+
);
|
|
90117
|
+
}
|
|
90165
90118
|
if (result.adaptationPromptPath) {
|
|
90166
90119
|
info(`Adapt prompt: ${result.adaptationPromptPath}`);
|
|
90167
90120
|
info(
|
|
@@ -90177,7 +90130,7 @@ function printSummary(result) {
|
|
|
90177
90130
|
console.error("");
|
|
90178
90131
|
}
|
|
90179
90132
|
async function handleOnboard(argv) {
|
|
90180
|
-
const repoPath =
|
|
90133
|
+
const repoPath = path60.resolve(argv.repo);
|
|
90181
90134
|
header("har onboard");
|
|
90182
90135
|
info(`Repository: ${repoPath}`);
|
|
90183
90136
|
try {
|
|
@@ -90198,7 +90151,8 @@ async function handleOnboard(argv) {
|
|
|
90198
90151
|
skipInit: argv.skipInit,
|
|
90199
90152
|
deferAdaptationPrompt: true,
|
|
90200
90153
|
autoYes: argv.yes,
|
|
90201
|
-
forcePlugins: argv.force
|
|
90154
|
+
forcePlugins: argv.force,
|
|
90155
|
+
agentSlotsMax: choices.agentSlotsMax
|
|
90202
90156
|
});
|
|
90203
90157
|
if (result.harnessInitialized || harnessExists(repoPath)) {
|
|
90204
90158
|
await handleCommitGateOnboarding({
|
|
@@ -90261,6 +90215,9 @@ var onboardCommand = {
|
|
|
90261
90215
|
}).option("plugins", {
|
|
90262
90216
|
type: "string",
|
|
90263
90217
|
describe: "Comma-separated plugins to install (e.g. playwright); --no-plugins to skip; interactive checkbox when omitted"
|
|
90218
|
+
}).option("agent-slots", {
|
|
90219
|
+
type: "number",
|
|
90220
|
+
describe: `Max parallel agent slots to configure in .har/stages.json (${HAR_AGENT_SLOT_MIN}\u2013${HAR_AGENT_SLOT_ONBOARD_MAX})`
|
|
90264
90221
|
}).option("skip-guide", {
|
|
90265
90222
|
type: "boolean",
|
|
90266
90223
|
default: false,
|
|
@@ -90408,7 +90365,7 @@ var preferencesCommand = {
|
|
|
90408
90365
|
};
|
|
90409
90366
|
|
|
90410
90367
|
// src/cli/commands/telemetry.ts
|
|
90411
|
-
var
|
|
90368
|
+
var path61 = __toESM(require("path"));
|
|
90412
90369
|
init_control_config();
|
|
90413
90370
|
init_otel_hooks();
|
|
90414
90371
|
init_telemetry_config();
|
|
@@ -90496,7 +90453,7 @@ async function handleOff() {
|
|
|
90496
90453
|
info("Mission Control will not auto-start. Existing usage rows are kept.");
|
|
90497
90454
|
}
|
|
90498
90455
|
async function handleWriteEnv(argv) {
|
|
90499
|
-
const repoPath =
|
|
90456
|
+
const repoPath = path61.resolve(argv.repo);
|
|
90500
90457
|
const harnessRoot = resolveHarnessRoot(repoPath);
|
|
90501
90458
|
const session = readSlotRegistry(harnessRoot, argv.agentId);
|
|
90502
90459
|
const workDir = argv.workDir ?? session?.workDir ?? repoPath;
|
|
@@ -90508,7 +90465,7 @@ async function handleWriteEnv(argv) {
|
|
|
90508
90465
|
suffix,
|
|
90509
90466
|
createdAt: session?.createdAt
|
|
90510
90467
|
});
|
|
90511
|
-
const envFile = argv.envFile ??
|
|
90468
|
+
const envFile = argv.envFile ?? path61.join(workDir, `.env.agent.${argv.agentId}`);
|
|
90512
90469
|
const attrs = {
|
|
90513
90470
|
sessionKey,
|
|
90514
90471
|
agentId: argv.agentId,
|
|
@@ -90524,7 +90481,7 @@ async function handleWriteEnv(argv) {
|
|
|
90524
90481
|
success(`Wrote session attribution to ${envFile}`);
|
|
90525
90482
|
}
|
|
90526
90483
|
function handlePrintEnv(argv) {
|
|
90527
|
-
const repoPath =
|
|
90484
|
+
const repoPath = path61.resolve(argv.repo);
|
|
90528
90485
|
const workDir = argv.workDir ?? repoPath;
|
|
90529
90486
|
const sessionKey = buildSessionKey({
|
|
90530
90487
|
branch: argv.branch,
|