@osfactory/har 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +725 -485
- package/dist/templates/har-boilerplate/agent-slot.sh +3 -9
- package/dist/templates/har-boilerplate/launch.sh +1 -8
- package/dist/templates/har-boilerplate-cli/agent-cli.sh +0 -2
- package/dist/templates/har-boilerplate-cli/agent-slot.sh +3 -9
- package/dist/templates/har-boilerplate-cli/launch.sh +1 -8
- package/dist/templates/har-boilerplate-ios/agent-slot.sh +2 -5
- package/dist/templates/har-boilerplate-ios/launch.sh +1 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -765,14 +765,14 @@ var require_url_state_machine = __commonJS({
|
|
|
765
765
|
return url.replace(/\u0009|\u000A|\u000D/g, "");
|
|
766
766
|
}
|
|
767
767
|
function shortenPath(url) {
|
|
768
|
-
const
|
|
769
|
-
if (
|
|
768
|
+
const path49 = url.path;
|
|
769
|
+
if (path49.length === 0) {
|
|
770
770
|
return;
|
|
771
771
|
}
|
|
772
|
-
if (url.scheme === "file" &&
|
|
772
|
+
if (url.scheme === "file" && path49.length === 1 && isNormalizedWindowsDriveLetter(path49[0])) {
|
|
773
773
|
return;
|
|
774
774
|
}
|
|
775
|
-
|
|
775
|
+
path49.pop();
|
|
776
776
|
}
|
|
777
777
|
function includesCredentials(url) {
|
|
778
778
|
return url.username !== "" || url.password !== "";
|
|
@@ -2092,7 +2092,7 @@ var require_lib2 = __commonJS({
|
|
|
2092
2092
|
let accum = [];
|
|
2093
2093
|
let accumBytes = 0;
|
|
2094
2094
|
let abort = false;
|
|
2095
|
-
return new Body.Promise(function(
|
|
2095
|
+
return new Body.Promise(function(resolve34, reject) {
|
|
2096
2096
|
let resTimeout;
|
|
2097
2097
|
if (_this4.timeout) {
|
|
2098
2098
|
resTimeout = setTimeout(function() {
|
|
@@ -2126,7 +2126,7 @@ var require_lib2 = __commonJS({
|
|
|
2126
2126
|
}
|
|
2127
2127
|
clearTimeout(resTimeout);
|
|
2128
2128
|
try {
|
|
2129
|
-
|
|
2129
|
+
resolve34(Buffer.concat(accum, accumBytes));
|
|
2130
2130
|
} catch (err) {
|
|
2131
2131
|
reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, "system", err));
|
|
2132
2132
|
}
|
|
@@ -2801,7 +2801,7 @@ var require_lib2 = __commonJS({
|
|
|
2801
2801
|
throw new Error("native promise missing, set fetch.Promise to your favorite alternative");
|
|
2802
2802
|
}
|
|
2803
2803
|
Body.Promise = fetch3.Promise;
|
|
2804
|
-
return new fetch3.Promise(function(
|
|
2804
|
+
return new fetch3.Promise(function(resolve34, reject) {
|
|
2805
2805
|
const request = new Request3(url, opts);
|
|
2806
2806
|
const options = getNodeRequestOptions(request);
|
|
2807
2807
|
const send = (options.protocol === "https:" ? https : http).request;
|
|
@@ -2934,7 +2934,7 @@ var require_lib2 = __commonJS({
|
|
|
2934
2934
|
requestOpts.body = void 0;
|
|
2935
2935
|
requestOpts.headers.delete("content-length");
|
|
2936
2936
|
}
|
|
2937
|
-
|
|
2937
|
+
resolve34(fetch3(new Request3(locationURL, requestOpts)));
|
|
2938
2938
|
finalize();
|
|
2939
2939
|
return;
|
|
2940
2940
|
}
|
|
@@ -2955,7 +2955,7 @@ var require_lib2 = __commonJS({
|
|
|
2955
2955
|
const codings = headers.get("Content-Encoding");
|
|
2956
2956
|
if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
|
|
2957
2957
|
response = new Response3(body, response_options);
|
|
2958
|
-
|
|
2958
|
+
resolve34(response);
|
|
2959
2959
|
return;
|
|
2960
2960
|
}
|
|
2961
2961
|
const zlibOptions = {
|
|
@@ -2965,7 +2965,7 @@ var require_lib2 = __commonJS({
|
|
|
2965
2965
|
if (codings == "gzip" || codings == "x-gzip") {
|
|
2966
2966
|
body = body.pipe(zlib.createGunzip(zlibOptions));
|
|
2967
2967
|
response = new Response3(body, response_options);
|
|
2968
|
-
|
|
2968
|
+
resolve34(response);
|
|
2969
2969
|
return;
|
|
2970
2970
|
}
|
|
2971
2971
|
if (codings == "deflate" || codings == "x-deflate") {
|
|
@@ -2977,12 +2977,12 @@ var require_lib2 = __commonJS({
|
|
|
2977
2977
|
body = body.pipe(zlib.createInflateRaw());
|
|
2978
2978
|
}
|
|
2979
2979
|
response = new Response3(body, response_options);
|
|
2980
|
-
|
|
2980
|
+
resolve34(response);
|
|
2981
2981
|
});
|
|
2982
2982
|
raw.on("end", function() {
|
|
2983
2983
|
if (!response) {
|
|
2984
2984
|
response = new Response3(body, response_options);
|
|
2985
|
-
|
|
2985
|
+
resolve34(response);
|
|
2986
2986
|
}
|
|
2987
2987
|
});
|
|
2988
2988
|
return;
|
|
@@ -2990,11 +2990,11 @@ var require_lib2 = __commonJS({
|
|
|
2990
2990
|
if (codings == "br" && typeof zlib.createBrotliDecompress === "function") {
|
|
2991
2991
|
body = body.pipe(zlib.createBrotliDecompress());
|
|
2992
2992
|
response = new Response3(body, response_options);
|
|
2993
|
-
|
|
2993
|
+
resolve34(response);
|
|
2994
2994
|
return;
|
|
2995
2995
|
}
|
|
2996
2996
|
response = new Response3(body, response_options);
|
|
2997
|
-
|
|
2997
|
+
resolve34(response);
|
|
2998
2998
|
});
|
|
2999
2999
|
writeToStream(req, request);
|
|
3000
3000
|
});
|
|
@@ -6351,14 +6351,14 @@ __export(fileFromPath_exports, {
|
|
|
6351
6351
|
fileFromPathSync: () => fileFromPathSync,
|
|
6352
6352
|
isFile: () => isFile
|
|
6353
6353
|
});
|
|
6354
|
-
function createFileFromPath(
|
|
6354
|
+
function createFileFromPath(path49, { mtimeMs, size }, filenameOrOptions, options = {}) {
|
|
6355
6355
|
let filename;
|
|
6356
6356
|
if (isPlainObject_default2(filenameOrOptions)) {
|
|
6357
6357
|
[options, filename] = [filenameOrOptions, void 0];
|
|
6358
6358
|
} else {
|
|
6359
6359
|
filename = filenameOrOptions;
|
|
6360
6360
|
}
|
|
6361
|
-
const file = new FileFromPath({ path:
|
|
6361
|
+
const file = new FileFromPath({ path: path49, size, lastModified: mtimeMs });
|
|
6362
6362
|
if (!filename) {
|
|
6363
6363
|
filename = file.name;
|
|
6364
6364
|
}
|
|
@@ -6367,13 +6367,13 @@ function createFileFromPath(path48, { mtimeMs, size }, filenameOrOptions, option
|
|
|
6367
6367
|
lastModified: file.lastModified
|
|
6368
6368
|
});
|
|
6369
6369
|
}
|
|
6370
|
-
function fileFromPathSync(
|
|
6371
|
-
const stats = (0, import_fs5.statSync)(
|
|
6372
|
-
return createFileFromPath(
|
|
6370
|
+
function fileFromPathSync(path49, filenameOrOptions, options = {}) {
|
|
6371
|
+
const stats = (0, import_fs5.statSync)(path49);
|
|
6372
|
+
return createFileFromPath(path49, stats, filenameOrOptions, options);
|
|
6373
6373
|
}
|
|
6374
|
-
async function fileFromPath2(
|
|
6375
|
-
const stats = await import_fs5.promises.stat(
|
|
6376
|
-
return createFileFromPath(
|
|
6374
|
+
async function fileFromPath2(path49, filenameOrOptions, options) {
|
|
6375
|
+
const stats = await import_fs5.promises.stat(path49);
|
|
6376
|
+
return createFileFromPath(path49, stats, filenameOrOptions, options);
|
|
6377
6377
|
}
|
|
6378
6378
|
var import_fs5, import_path5, import_node_domexception, __classPrivateFieldSet5, __classPrivateFieldGet6, _FileFromPath_path, _FileFromPath_start, MESSAGE, FileFromPath;
|
|
6379
6379
|
var init_fileFromPath = __esm({
|
|
@@ -6433,6 +6433,412 @@ var init_fileFromPath = __esm({
|
|
|
6433
6433
|
}
|
|
6434
6434
|
});
|
|
6435
6435
|
|
|
6436
|
+
// src/core/control-config.ts
|
|
6437
|
+
function getControlApiUrl() {
|
|
6438
|
+
return process.env.HAR_CONTROL_API_URL ?? DEFAULT_CONTROL_API_URL;
|
|
6439
|
+
}
|
|
6440
|
+
function isControlEnabled() {
|
|
6441
|
+
return process.env.HAR_CONTROL_DISABLED !== "true";
|
|
6442
|
+
}
|
|
6443
|
+
var DEFAULT_CONTROL_API_URL;
|
|
6444
|
+
var init_control_config = __esm({
|
|
6445
|
+
"src/core/control-config.ts"() {
|
|
6446
|
+
"use strict";
|
|
6447
|
+
DEFAULT_CONTROL_API_URL = "http://localhost:3847";
|
|
6448
|
+
}
|
|
6449
|
+
});
|
|
6450
|
+
|
|
6451
|
+
// src/core/telemetry-config.ts
|
|
6452
|
+
function getPreferencePath() {
|
|
6453
|
+
if (process.env.HAR_TELEMETRY_CONFIG_PATH) {
|
|
6454
|
+
return path34.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
|
|
6455
|
+
}
|
|
6456
|
+
return path34.join(os9.homedir(), ".har", "telemetry.json");
|
|
6457
|
+
}
|
|
6458
|
+
function parseEnvOverride(raw) {
|
|
6459
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
6460
|
+
const normalized = raw.trim().toLowerCase();
|
|
6461
|
+
if (["0", "false", "off", "no", "disabled"].includes(normalized)) return false;
|
|
6462
|
+
if (["1", "true", "on", "yes", "enabled"].includes(normalized)) return true;
|
|
6463
|
+
return void 0;
|
|
6464
|
+
}
|
|
6465
|
+
function normalizeSignals(enabled, raw) {
|
|
6466
|
+
if (!enabled) return { ...DEFAULT_SIGNALS_OFF };
|
|
6467
|
+
return {
|
|
6468
|
+
metrics: raw?.metrics !== false,
|
|
6469
|
+
logs: raw?.logs !== false,
|
|
6470
|
+
prompts: raw?.prompts === true,
|
|
6471
|
+
traces: raw?.traces !== false
|
|
6472
|
+
};
|
|
6473
|
+
}
|
|
6474
|
+
function readTelemetryPreference() {
|
|
6475
|
+
const preferencePath = getPreferencePath();
|
|
6476
|
+
try {
|
|
6477
|
+
if (!fs34.existsSync(preferencePath)) {
|
|
6478
|
+
return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
|
|
6479
|
+
}
|
|
6480
|
+
const parsed = JSON.parse(fs34.readFileSync(preferencePath, "utf8"));
|
|
6481
|
+
const enabled = parsed.enabled !== false;
|
|
6482
|
+
return {
|
|
6483
|
+
enabled,
|
|
6484
|
+
signals: normalizeSignals(enabled, parsed.signals),
|
|
6485
|
+
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : void 0
|
|
6486
|
+
};
|
|
6487
|
+
} catch {
|
|
6488
|
+
return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
|
|
6489
|
+
}
|
|
6490
|
+
}
|
|
6491
|
+
function writeTelemetryPreference(enabled, signals) {
|
|
6492
|
+
const current = readTelemetryPreference();
|
|
6493
|
+
const nextSignals = normalizeSignals(enabled, {
|
|
6494
|
+
...current.signals,
|
|
6495
|
+
...signals
|
|
6496
|
+
});
|
|
6497
|
+
const preference = {
|
|
6498
|
+
enabled,
|
|
6499
|
+
signals: enabled ? nextSignals : { ...DEFAULT_SIGNALS_OFF },
|
|
6500
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6501
|
+
};
|
|
6502
|
+
const preferencePath = getPreferencePath();
|
|
6503
|
+
fs34.mkdirSync(path34.dirname(preferencePath), { recursive: true });
|
|
6504
|
+
fs34.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
|
|
6505
|
+
return preference;
|
|
6506
|
+
}
|
|
6507
|
+
function isTelemetryEnabled() {
|
|
6508
|
+
const envOverride = parseEnvOverride(process.env.HAR_TELEMETRY);
|
|
6509
|
+
if (envOverride !== void 0) return envOverride;
|
|
6510
|
+
return readTelemetryPreference().enabled;
|
|
6511
|
+
}
|
|
6512
|
+
function getTelemetrySignals() {
|
|
6513
|
+
if (!isTelemetryEnabled()) return { ...DEFAULT_SIGNALS_OFF };
|
|
6514
|
+
return readTelemetryPreference().signals;
|
|
6515
|
+
}
|
|
6516
|
+
function getTelemetryPreferencePath() {
|
|
6517
|
+
return getPreferencePath();
|
|
6518
|
+
}
|
|
6519
|
+
var fs34, os9, path34, DEFAULT_SIGNALS_ON, DEFAULT_SIGNALS_OFF, TELEMETRY_SIGNALS;
|
|
6520
|
+
var init_telemetry_config = __esm({
|
|
6521
|
+
"src/core/telemetry-config.ts"() {
|
|
6522
|
+
"use strict";
|
|
6523
|
+
fs34 = __toESM(require("fs"));
|
|
6524
|
+
os9 = __toESM(require("os"));
|
|
6525
|
+
path34 = __toESM(require("path"));
|
|
6526
|
+
DEFAULT_SIGNALS_ON = {
|
|
6527
|
+
metrics: true,
|
|
6528
|
+
logs: true,
|
|
6529
|
+
prompts: false,
|
|
6530
|
+
/** Hooks are traces-first; usage metrics are derived from span gen_ai.usage.* in Mission Control. */
|
|
6531
|
+
traces: true
|
|
6532
|
+
};
|
|
6533
|
+
DEFAULT_SIGNALS_OFF = {
|
|
6534
|
+
metrics: false,
|
|
6535
|
+
logs: false,
|
|
6536
|
+
prompts: false,
|
|
6537
|
+
traces: false
|
|
6538
|
+
};
|
|
6539
|
+
TELEMETRY_SIGNALS = [
|
|
6540
|
+
"Traces (default): Cursor / Claude / Codex activity via opentelemetry-hooks \u2192 Mission Control",
|
|
6541
|
+
"Logs/events (default): hook lifecycle logs without prompt bodies",
|
|
6542
|
+
"Metrics (default): token usage derived from span gen_ai.usage.* attributes",
|
|
6543
|
+
"Prompts (opt-in): user prompt text via IDE_OTEL_CAPTURE_TEXT \u2014 har telemetry on --prompts (also fills Mission Control purpose)",
|
|
6544
|
+
"Fallback: har control sync harvests local Claude/Codex session files when hooks telemetry is missing"
|
|
6545
|
+
];
|
|
6546
|
+
}
|
|
6547
|
+
});
|
|
6548
|
+
|
|
6549
|
+
// src/core/otel-hooks.ts
|
|
6550
|
+
var otel_hooks_exports = {};
|
|
6551
|
+
__export(otel_hooks_exports, {
|
|
6552
|
+
OTEL_HOOKS_AGENTS: () => OTEL_HOOKS_AGENTS,
|
|
6553
|
+
OTEL_HOOKS_PACKAGE: () => OTEL_HOOKS_PACKAGE,
|
|
6554
|
+
buildOtelHooksConfig: () => buildOtelHooksConfig,
|
|
6555
|
+
disableOtelHooksExport: () => disableOtelHooksExport,
|
|
6556
|
+
ensureOtelHooks: () => ensureOtelHooks,
|
|
6557
|
+
getOtelHooksConfigPath: () => getOtelHooksConfigPath,
|
|
6558
|
+
getOtelHooksHome: () => getOtelHooksHome,
|
|
6559
|
+
getOtelHooksWrapperPath: () => getOtelHooksWrapperPath,
|
|
6560
|
+
rewriteHookCommandsToWrapper: () => rewriteHookCommandsToWrapper,
|
|
6561
|
+
writeOtelHooksConfig: () => writeOtelHooksConfig,
|
|
6562
|
+
writeOtelHooksWrapper: () => writeOtelHooksWrapper
|
|
6563
|
+
});
|
|
6564
|
+
function getOtelHooksHome() {
|
|
6565
|
+
if (process.env.HAR_OTEL_HOOKS_HOME) {
|
|
6566
|
+
return path40.resolve(process.env.HAR_OTEL_HOOKS_HOME);
|
|
6567
|
+
}
|
|
6568
|
+
return path40.join(os12.homedir(), ".har", "otel-hooks");
|
|
6569
|
+
}
|
|
6570
|
+
function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
|
|
6571
|
+
return path40.join(hooksHome, "otel_config.json");
|
|
6572
|
+
}
|
|
6573
|
+
function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
|
|
6574
|
+
return path40.join(hooksHome, "run-otel-hook.sh");
|
|
6575
|
+
}
|
|
6576
|
+
function buildOtelHooksConfig(options) {
|
|
6577
|
+
const enabled = options?.enabled ?? isTelemetryEnabled();
|
|
6578
|
+
const signals = getTelemetrySignals();
|
|
6579
|
+
const apiUrl = (options?.apiUrl ?? getControlApiUrl()).replace(/\/$/, "");
|
|
6580
|
+
return {
|
|
6581
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: enabled ? `${apiUrl}/api/otel/v1/traces` : null,
|
|
6582
|
+
OTEL_EXPORTER_OTLP_PROTOCOL: "http/json",
|
|
6583
|
+
OTEL_SERVICE_NAME: "har-ide-agent",
|
|
6584
|
+
IDE_OTEL_BATCH_ON_STOP: "true",
|
|
6585
|
+
IDE_OTEL_ENABLE_LOGS: enabled && signals.logs ? "true" : "false",
|
|
6586
|
+
IDE_OTEL_LOG_ALL_EVENTS: enabled && signals.logs ? "true" : "false",
|
|
6587
|
+
IDE_OTEL_CAPTURE_TEXT: enabled && signals.prompts ? "true" : "false",
|
|
6588
|
+
IDE_OTEL_MASK_PROMPTS: "false",
|
|
6589
|
+
OTEL_RESOURCE_ATTRIBUTES: options?.resourceAttributes ?? null
|
|
6590
|
+
};
|
|
6591
|
+
}
|
|
6592
|
+
function writeOtelHooksConfig(config2, hooksHome = getOtelHooksHome()) {
|
|
6593
|
+
fs38.mkdirSync(hooksHome, { recursive: true });
|
|
6594
|
+
const configPath = getOtelHooksConfigPath(hooksHome);
|
|
6595
|
+
const payload = {
|
|
6596
|
+
_comment: "Managed by har telemetry \u2014 do not edit by hand; use: har telemetry on|off",
|
|
6597
|
+
...config2
|
|
6598
|
+
};
|
|
6599
|
+
fs38.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}
|
|
6600
|
+
`);
|
|
6601
|
+
return configPath;
|
|
6602
|
+
}
|
|
6603
|
+
function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome()) {
|
|
6604
|
+
fs38.mkdirSync(hooksHome, { recursive: true });
|
|
6605
|
+
const wrapperPath = getOtelHooksWrapperPath(hooksHome);
|
|
6606
|
+
const script = `#!/usr/bin/env bash
|
|
6607
|
+
# Managed by har telemetry \u2014 invokes opentelemetry-hooks with HAR config home.
|
|
6608
|
+
set -euo pipefail
|
|
6609
|
+
export IDE_OTEL_HOOK_HOME="${hooksHome}"
|
|
6610
|
+
exec "${otelHookCommand}" "$@"
|
|
6611
|
+
`;
|
|
6612
|
+
fs38.writeFileSync(wrapperPath, script, { mode: 493 });
|
|
6613
|
+
try {
|
|
6614
|
+
fs38.chmodSync(wrapperPath, 493);
|
|
6615
|
+
} catch {
|
|
6616
|
+
}
|
|
6617
|
+
return wrapperPath;
|
|
6618
|
+
}
|
|
6619
|
+
function commandExists(command2) {
|
|
6620
|
+
const result = (0, import_child_process9.spawnSync)("sh", ["-c", `command -v ${JSON.stringify(command2)}`], {
|
|
6621
|
+
encoding: "utf8"
|
|
6622
|
+
});
|
|
6623
|
+
return result.status === 0 && Boolean(result.stdout?.trim());
|
|
6624
|
+
}
|
|
6625
|
+
function resolveOtelHookCommand() {
|
|
6626
|
+
if (commandExists("otel-hook")) {
|
|
6627
|
+
const which = (0, import_child_process9.spawnSync)("sh", ["-c", "command -v otel-hook"], { encoding: "utf8" });
|
|
6628
|
+
return which.stdout?.trim() || "otel-hook";
|
|
6629
|
+
}
|
|
6630
|
+
return null;
|
|
6631
|
+
}
|
|
6632
|
+
function tryInstallPackage() {
|
|
6633
|
+
if (commandExists("uv")) {
|
|
6634
|
+
const result = (0, import_child_process9.spawnSync)(
|
|
6635
|
+
"uv",
|
|
6636
|
+
["tool", "install", "--force", OTEL_HOOKS_PACKAGE],
|
|
6637
|
+
{ encoding: "utf8", timeout: 18e4 }
|
|
6638
|
+
);
|
|
6639
|
+
if (result.status === 0) {
|
|
6640
|
+
return { ok: true, detail: `uv tool install ${OTEL_HOOKS_PACKAGE}` };
|
|
6641
|
+
}
|
|
6642
|
+
}
|
|
6643
|
+
if (commandExists("pipx")) {
|
|
6644
|
+
const result = (0, import_child_process9.spawnSync)("pipx", ["install", "--force", OTEL_HOOKS_PACKAGE], {
|
|
6645
|
+
encoding: "utf8",
|
|
6646
|
+
timeout: 18e4
|
|
6647
|
+
});
|
|
6648
|
+
if (result.status === 0) {
|
|
6649
|
+
return { ok: true, detail: `pipx install ${OTEL_HOOKS_PACKAGE}` };
|
|
6650
|
+
}
|
|
6651
|
+
return {
|
|
6652
|
+
ok: false,
|
|
6653
|
+
detail: `pipx install failed: ${(result.stderr || result.stdout || "").trim().slice(0, 400)}`
|
|
6654
|
+
};
|
|
6655
|
+
}
|
|
6656
|
+
if (commandExists("pip3") || commandExists("pip")) {
|
|
6657
|
+
const pip = commandExists("pip3") ? "pip3" : "pip";
|
|
6658
|
+
const result = (0, import_child_process9.spawnSync)(
|
|
6659
|
+
pip,
|
|
6660
|
+
["install", "--user", OTEL_HOOKS_PACKAGE],
|
|
6661
|
+
{ encoding: "utf8", timeout: 18e4 }
|
|
6662
|
+
);
|
|
6663
|
+
if (result.status === 0) {
|
|
6664
|
+
return { ok: true, detail: `${pip} install --user ${OTEL_HOOKS_PACKAGE}` };
|
|
6665
|
+
}
|
|
6666
|
+
return {
|
|
6667
|
+
ok: false,
|
|
6668
|
+
detail: `${pip} install failed: ${(result.stderr || result.stdout || "").trim().slice(0, 400)}`
|
|
6669
|
+
};
|
|
6670
|
+
}
|
|
6671
|
+
return {
|
|
6672
|
+
ok: false,
|
|
6673
|
+
detail: "Neither uv, pipx, nor pip3/pip found; install Python tooling to use opentelemetry-hooks"
|
|
6674
|
+
};
|
|
6675
|
+
}
|
|
6676
|
+
function runSetupAgent(agent, otelHookCommand, hooksHome) {
|
|
6677
|
+
const result = (0, import_child_process9.spawnSync)(otelHookCommand, ["setup", "--agent", agent], {
|
|
6678
|
+
encoding: "utf8",
|
|
6679
|
+
env: {
|
|
6680
|
+
...process.env,
|
|
6681
|
+
IDE_OTEL_HOOK_HOME: hooksHome
|
|
6682
|
+
},
|
|
6683
|
+
timeout: 6e4
|
|
6684
|
+
});
|
|
6685
|
+
if (result.status === 0) {
|
|
6686
|
+
return { ok: true, detail: `setup --agent ${agent}` };
|
|
6687
|
+
}
|
|
6688
|
+
return {
|
|
6689
|
+
ok: false,
|
|
6690
|
+
detail: `setup --agent ${agent} failed: ${(result.stderr || result.stdout || "").trim().slice(0, 400)}`
|
|
6691
|
+
};
|
|
6692
|
+
}
|
|
6693
|
+
function rewriteHookCommandsToWrapper(filePath, wrapperPath) {
|
|
6694
|
+
if (!fs38.existsSync(filePath)) return false;
|
|
6695
|
+
let raw;
|
|
6696
|
+
try {
|
|
6697
|
+
raw = fs38.readFileSync(filePath, "utf8");
|
|
6698
|
+
} catch {
|
|
6699
|
+
return false;
|
|
6700
|
+
}
|
|
6701
|
+
let parsed;
|
|
6702
|
+
try {
|
|
6703
|
+
parsed = JSON.parse(raw);
|
|
6704
|
+
} catch {
|
|
6705
|
+
return false;
|
|
6706
|
+
}
|
|
6707
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
6708
|
+
const quoted = JSON.stringify(wrapperPath);
|
|
6709
|
+
const rewriteCommand = (command2) => {
|
|
6710
|
+
if (!command2.includes("otel-hook") && !command2.includes("otel_hook.py")) return command2;
|
|
6711
|
+
if (command2.includes(wrapperPath)) return command2;
|
|
6712
|
+
return command2.replace(
|
|
6713
|
+
/(?:^|[;&|]\s*)(?:env\s+[^=\s]+=\S+\s+)*(?:python3?\s+)?(?:\S*otel[_-]hook\S*)/,
|
|
6714
|
+
(match) => match.replace(/(?:python3?\s+)?(?:\S*otel[_-]hook\S*)/, quoted.slice(1, -1))
|
|
6715
|
+
);
|
|
6716
|
+
};
|
|
6717
|
+
const walk = (node) => {
|
|
6718
|
+
let changed = false;
|
|
6719
|
+
if (Array.isArray(node)) {
|
|
6720
|
+
for (const item of node) changed = walk(item) || changed;
|
|
6721
|
+
return changed;
|
|
6722
|
+
}
|
|
6723
|
+
if (!node || typeof node !== "object") return false;
|
|
6724
|
+
const obj = node;
|
|
6725
|
+
if (typeof obj.command === "string") {
|
|
6726
|
+
const next = rewriteCommand(obj.command);
|
|
6727
|
+
if (next !== obj.command) {
|
|
6728
|
+
obj.command = next;
|
|
6729
|
+
changed = true;
|
|
6730
|
+
}
|
|
6731
|
+
}
|
|
6732
|
+
for (const value of Object.values(obj)) changed = walk(value) || changed;
|
|
6733
|
+
return changed;
|
|
6734
|
+
};
|
|
6735
|
+
if (!walk(parsed)) return false;
|
|
6736
|
+
fs38.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
6737
|
+
`);
|
|
6738
|
+
return true;
|
|
6739
|
+
}
|
|
6740
|
+
function rewriteKnownHookRegistrations(wrapperPath) {
|
|
6741
|
+
const home = os12.homedir();
|
|
6742
|
+
const candidates = [
|
|
6743
|
+
path40.join(home, ".cursor", "hooks.json"),
|
|
6744
|
+
path40.join(home, ".claude", "settings.json"),
|
|
6745
|
+
path40.join(home, ".codex", "hooks.json")
|
|
6746
|
+
];
|
|
6747
|
+
for (const filePath of candidates) {
|
|
6748
|
+
try {
|
|
6749
|
+
rewriteHookCommandsToWrapper(filePath, wrapperPath);
|
|
6750
|
+
} catch {
|
|
6751
|
+
}
|
|
6752
|
+
}
|
|
6753
|
+
}
|
|
6754
|
+
function ensureOtelHooks(options) {
|
|
6755
|
+
const hooksHome = getOtelHooksHome();
|
|
6756
|
+
const errors = [];
|
|
6757
|
+
const agentsSetup = [];
|
|
6758
|
+
fs38.mkdirSync(hooksHome, { recursive: true });
|
|
6759
|
+
let otelHookCommand = resolveOtelHookCommand();
|
|
6760
|
+
if (!otelHookCommand) {
|
|
6761
|
+
const installed = tryInstallPackage();
|
|
6762
|
+
if (!installed.ok) {
|
|
6763
|
+
errors.push(installed.detail);
|
|
6764
|
+
const configPath2 = writeOtelHooksConfig(
|
|
6765
|
+
buildOtelHooksConfig({ resourceAttributes: options?.resourceAttributes }),
|
|
6766
|
+
hooksHome
|
|
6767
|
+
);
|
|
6768
|
+
return {
|
|
6769
|
+
ok: false,
|
|
6770
|
+
hooksHome,
|
|
6771
|
+
configPath: configPath2,
|
|
6772
|
+
wrapperPath: getOtelHooksWrapperPath(hooksHome),
|
|
6773
|
+
otelHookCommand: null,
|
|
6774
|
+
warning: installed.detail,
|
|
6775
|
+
agentsSetup,
|
|
6776
|
+
errors
|
|
6777
|
+
};
|
|
6778
|
+
}
|
|
6779
|
+
otelHookCommand = resolveOtelHookCommand();
|
|
6780
|
+
if (!otelHookCommand) {
|
|
6781
|
+
errors.push("opentelemetry-hooks installed but otel-hook is not on PATH");
|
|
6782
|
+
const configPath2 = writeOtelHooksConfig(
|
|
6783
|
+
buildOtelHooksConfig({ resourceAttributes: options?.resourceAttributes }),
|
|
6784
|
+
hooksHome
|
|
6785
|
+
);
|
|
6786
|
+
return {
|
|
6787
|
+
ok: false,
|
|
6788
|
+
hooksHome,
|
|
6789
|
+
configPath: configPath2,
|
|
6790
|
+
wrapperPath: getOtelHooksWrapperPath(hooksHome),
|
|
6791
|
+
otelHookCommand: null,
|
|
6792
|
+
warning: errors[errors.length - 1],
|
|
6793
|
+
agentsSetup,
|
|
6794
|
+
errors
|
|
6795
|
+
};
|
|
6796
|
+
}
|
|
6797
|
+
}
|
|
6798
|
+
const configPath = writeOtelHooksConfig(
|
|
6799
|
+
buildOtelHooksConfig({ resourceAttributes: options?.resourceAttributes }),
|
|
6800
|
+
hooksHome
|
|
6801
|
+
);
|
|
6802
|
+
const wrapperPath = writeOtelHooksWrapper(otelHookCommand, hooksHome);
|
|
6803
|
+
if (options?.setupAgents !== false && isTelemetryEnabled()) {
|
|
6804
|
+
for (const agent of OTEL_HOOKS_AGENTS) {
|
|
6805
|
+
const setup = runSetupAgent(agent, otelHookCommand, hooksHome);
|
|
6806
|
+
if (setup.ok) agentsSetup.push(agent);
|
|
6807
|
+
else errors.push(setup.detail);
|
|
6808
|
+
}
|
|
6809
|
+
rewriteKnownHookRegistrations(wrapperPath);
|
|
6810
|
+
}
|
|
6811
|
+
const ok = errors.length === 0;
|
|
6812
|
+
return {
|
|
6813
|
+
ok,
|
|
6814
|
+
hooksHome,
|
|
6815
|
+
configPath,
|
|
6816
|
+
wrapperPath,
|
|
6817
|
+
otelHookCommand,
|
|
6818
|
+
message: ok ? `opentelemetry-hooks ready (${agentsSetup.join(", ") || "config only"}) \u2192 ${configPath}` : void 0,
|
|
6819
|
+
warning: errors.length ? errors.join("; ") : void 0,
|
|
6820
|
+
agentsSetup,
|
|
6821
|
+
errors
|
|
6822
|
+
};
|
|
6823
|
+
}
|
|
6824
|
+
function disableOtelHooksExport() {
|
|
6825
|
+
return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
|
|
6826
|
+
}
|
|
6827
|
+
var import_child_process9, fs38, os12, path40, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
|
|
6828
|
+
var init_otel_hooks = __esm({
|
|
6829
|
+
"src/core/otel-hooks.ts"() {
|
|
6830
|
+
"use strict";
|
|
6831
|
+
import_child_process9 = require("child_process");
|
|
6832
|
+
fs38 = __toESM(require("fs"));
|
|
6833
|
+
os12 = __toESM(require("os"));
|
|
6834
|
+
path40 = __toESM(require("path"));
|
|
6835
|
+
init_control_config();
|
|
6836
|
+
init_telemetry_config();
|
|
6837
|
+
OTEL_HOOKS_PACKAGE = "opentelemetry-hooks==0.14.0";
|
|
6838
|
+
OTEL_HOOKS_AGENTS = ["cursor", "claude", "codex"];
|
|
6839
|
+
}
|
|
6840
|
+
});
|
|
6841
|
+
|
|
6436
6842
|
// node_modules/ajv/dist/compile/codegen/code.js
|
|
6437
6843
|
var require_code = __commonJS({
|
|
6438
6844
|
"node_modules/ajv/dist/compile/codegen/code.js"(exports2) {
|
|
@@ -9384,7 +9790,7 @@ var require_compile = __commonJS({
|
|
|
9384
9790
|
const schOrFunc = root.refs[ref];
|
|
9385
9791
|
if (schOrFunc)
|
|
9386
9792
|
return schOrFunc;
|
|
9387
|
-
let _sch =
|
|
9793
|
+
let _sch = resolve34.call(this, root, ref);
|
|
9388
9794
|
if (_sch === void 0) {
|
|
9389
9795
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
9390
9796
|
const { schemaId } = this.opts;
|
|
@@ -9411,7 +9817,7 @@ var require_compile = __commonJS({
|
|
|
9411
9817
|
function sameSchemaEnv(s1, s2) {
|
|
9412
9818
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
9413
9819
|
}
|
|
9414
|
-
function
|
|
9820
|
+
function resolve34(root, ref) {
|
|
9415
9821
|
let sch;
|
|
9416
9822
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
9417
9823
|
ref = sch;
|
|
@@ -9629,8 +10035,8 @@ var require_utils2 = __commonJS({
|
|
|
9629
10035
|
}
|
|
9630
10036
|
return ind;
|
|
9631
10037
|
}
|
|
9632
|
-
function removeDotSegments(
|
|
9633
|
-
let input =
|
|
10038
|
+
function removeDotSegments(path49) {
|
|
10039
|
+
let input = path49;
|
|
9634
10040
|
const output = [];
|
|
9635
10041
|
let nextSlash = -1;
|
|
9636
10042
|
let len = 0;
|
|
@@ -9882,8 +10288,8 @@ var require_schemes = __commonJS({
|
|
|
9882
10288
|
wsComponent.secure = void 0;
|
|
9883
10289
|
}
|
|
9884
10290
|
if (wsComponent.resourceName) {
|
|
9885
|
-
const [
|
|
9886
|
-
wsComponent.path =
|
|
10291
|
+
const [path49, query] = wsComponent.resourceName.split("?");
|
|
10292
|
+
wsComponent.path = path49 && path49 !== "/" ? path49 : void 0;
|
|
9887
10293
|
wsComponent.query = query;
|
|
9888
10294
|
wsComponent.resourceName = void 0;
|
|
9889
10295
|
}
|
|
@@ -10042,7 +10448,7 @@ var require_fast_uri = __commonJS({
|
|
|
10042
10448
|
}
|
|
10043
10449
|
return uri;
|
|
10044
10450
|
}
|
|
10045
|
-
function
|
|
10451
|
+
function resolve34(baseURI, relativeURI, options) {
|
|
10046
10452
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
10047
10453
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
10048
10454
|
schemelessOptions.skipEscape = true;
|
|
@@ -10300,7 +10706,7 @@ var require_fast_uri = __commonJS({
|
|
|
10300
10706
|
var fastUri = {
|
|
10301
10707
|
SCHEMES,
|
|
10302
10708
|
normalize: normalize3,
|
|
10303
|
-
resolve:
|
|
10709
|
+
resolve: resolve34,
|
|
10304
10710
|
resolveComponent,
|
|
10305
10711
|
equal,
|
|
10306
10712
|
serialize,
|
|
@@ -14565,11 +14971,11 @@ var parser = new YargsParser({
|
|
|
14565
14971
|
resolve: import_path2.resolve,
|
|
14566
14972
|
// TODO: figure out a way to combine ESM and CJS coverage, such that
|
|
14567
14973
|
// we can exercise all the lines below:
|
|
14568
|
-
require: (
|
|
14974
|
+
require: (path49) => {
|
|
14569
14975
|
if (typeof require !== "undefined") {
|
|
14570
|
-
return require(
|
|
14571
|
-
} else if (
|
|
14572
|
-
return JSON.parse((0, import_fs2.readFileSync)(
|
|
14976
|
+
return require(path49);
|
|
14977
|
+
} else if (path49.match(/\.json$/)) {
|
|
14978
|
+
return JSON.parse((0, import_fs2.readFileSync)(path49, "utf8"));
|
|
14573
14979
|
} else {
|
|
14574
14980
|
throw Error("only .json config files are supported in ESM");
|
|
14575
14981
|
}
|
|
@@ -17095,12 +17501,12 @@ var YargsInstance = class {
|
|
|
17095
17501
|
async getCompletion(args, done) {
|
|
17096
17502
|
argsert("<array> [function]", [args, done], arguments.length);
|
|
17097
17503
|
if (!done) {
|
|
17098
|
-
return new Promise((
|
|
17504
|
+
return new Promise((resolve34, reject) => {
|
|
17099
17505
|
__classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
|
|
17100
17506
|
if (err)
|
|
17101
17507
|
reject(err);
|
|
17102
17508
|
else
|
|
17103
|
-
|
|
17509
|
+
resolve34(completions);
|
|
17104
17510
|
});
|
|
17105
17511
|
});
|
|
17106
17512
|
} else {
|
|
@@ -19250,8 +19656,8 @@ function getErrorMap() {
|
|
|
19250
19656
|
|
|
19251
19657
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
19252
19658
|
var makeIssue = (params) => {
|
|
19253
|
-
const { data, path:
|
|
19254
|
-
const fullPath = [...
|
|
19659
|
+
const { data, path: path49, errorMaps, issueData } = params;
|
|
19660
|
+
const fullPath = [...path49, ...issueData.path || []];
|
|
19255
19661
|
const fullIssue = {
|
|
19256
19662
|
...issueData,
|
|
19257
19663
|
path: fullPath
|
|
@@ -19367,11 +19773,11 @@ var errorUtil;
|
|
|
19367
19773
|
|
|
19368
19774
|
// node_modules/zod/v3/types.js
|
|
19369
19775
|
var ParseInputLazyPath = class {
|
|
19370
|
-
constructor(parent, value,
|
|
19776
|
+
constructor(parent, value, path49, key) {
|
|
19371
19777
|
this._cachedPath = [];
|
|
19372
19778
|
this.parent = parent;
|
|
19373
19779
|
this.data = value;
|
|
19374
|
-
this._path =
|
|
19780
|
+
this._path = path49;
|
|
19375
19781
|
this._key = key;
|
|
19376
19782
|
}
|
|
19377
19783
|
get path() {
|
|
@@ -22992,7 +23398,6 @@ var SlotRegistryEntrySchema = external_exports.object({
|
|
|
22992
23398
|
/** Random per-session chars; absent in root mode. */
|
|
22993
23399
|
suffix: external_exports.string().optional(),
|
|
22994
23400
|
createdAt: external_exports.string(),
|
|
22995
|
-
purpose: external_exports.string().optional(),
|
|
22996
23401
|
ports: external_exports.record(external_exports.number()).optional(),
|
|
22997
23402
|
previewUrls: external_exports.record(external_exports.string()).optional(),
|
|
22998
23403
|
status: external_exports.enum(["starting", "active", "failed", "completed"]).default("active"),
|
|
@@ -23038,6 +23443,7 @@ var AgentSlotStatusSchema = external_exports.object({
|
|
|
23038
23443
|
baseBranch: external_exports.string().optional(),
|
|
23039
23444
|
baseCommit: external_exports.string().optional(),
|
|
23040
23445
|
sessionCreatedAt: external_exports.string().optional(),
|
|
23446
|
+
/** Derived from first captured user prompt (OTEL hooks); not set at launch. */
|
|
23041
23447
|
purpose: external_exports.string().optional(),
|
|
23042
23448
|
sessionStatus: external_exports.enum(["starting", "active", "failed", "completed"]).optional(),
|
|
23043
23449
|
lastError: external_exports.string().optional(),
|
|
@@ -23106,7 +23512,7 @@ var ValidationRecordSchema = external_exports.object({
|
|
|
23106
23512
|
var SyncValidationsInputSchema = external_exports.object({
|
|
23107
23513
|
validations: external_exports.array(ValidationRecordSchema)
|
|
23108
23514
|
});
|
|
23109
|
-
var AgentToolSchema = external_exports.enum(["claude_code", "codex"]);
|
|
23515
|
+
var AgentToolSchema = external_exports.enum(["claude_code", "codex", "cursor"]);
|
|
23110
23516
|
var UsageSourceSchema = external_exports.enum(["otel", "harvest"]);
|
|
23111
23517
|
var AgentSessionUsageSchema = external_exports.object({
|
|
23112
23518
|
sessionKey: external_exports.string().min(1),
|
|
@@ -23410,16 +23816,16 @@ async function handleAgentSkills(options) {
|
|
|
23410
23816
|
}
|
|
23411
23817
|
async function askYesNo(question) {
|
|
23412
23818
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
23413
|
-
return new Promise((
|
|
23819
|
+
return new Promise((resolve34) => {
|
|
23414
23820
|
process.stderr.write(`${question} `);
|
|
23415
23821
|
rl.once("line", (answer) => {
|
|
23416
23822
|
rl.close();
|
|
23417
23823
|
const trimmed = answer.trim();
|
|
23418
23824
|
if (trimmed === "") {
|
|
23419
|
-
|
|
23825
|
+
resolve34(true);
|
|
23420
23826
|
return;
|
|
23421
23827
|
}
|
|
23422
|
-
|
|
23828
|
+
resolve34(/^y(es)?$/i.test(trimmed));
|
|
23423
23829
|
});
|
|
23424
23830
|
});
|
|
23425
23831
|
}
|
|
@@ -23498,7 +23904,7 @@ function handleRemove(argv) {
|
|
|
23498
23904
|
}
|
|
23499
23905
|
|
|
23500
23906
|
// src/cli/commands/env.ts
|
|
23501
|
-
var
|
|
23907
|
+
var path42 = __toESM(require("path"));
|
|
23502
23908
|
|
|
23503
23909
|
// src/core/harness.ts
|
|
23504
23910
|
var fs20 = __toESM(require("fs"));
|
|
@@ -24277,13 +24683,13 @@ var MultipartBody = class {
|
|
|
24277
24683
|
// node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
|
|
24278
24684
|
var import_web = require("node:stream/web");
|
|
24279
24685
|
var fileFromPathWarned = false;
|
|
24280
|
-
async function fileFromPath3(
|
|
24686
|
+
async function fileFromPath3(path49, ...args) {
|
|
24281
24687
|
const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => (init_fileFromPath(), fileFromPath_exports));
|
|
24282
24688
|
if (!fileFromPathWarned) {
|
|
24283
|
-
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(
|
|
24689
|
+
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path49)}) instead`);
|
|
24284
24690
|
fileFromPathWarned = true;
|
|
24285
24691
|
}
|
|
24286
|
-
return await _fileFromPath(
|
|
24692
|
+
return await _fileFromPath(path49, ...args);
|
|
24287
24693
|
}
|
|
24288
24694
|
var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
24289
24695
|
var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
@@ -24779,8 +25185,8 @@ async function defaultParseResponse(props) {
|
|
|
24779
25185
|
}
|
|
24780
25186
|
var APIPromise = class _APIPromise extends Promise {
|
|
24781
25187
|
constructor(responsePromise, parseResponse = defaultParseResponse) {
|
|
24782
|
-
super((
|
|
24783
|
-
|
|
25188
|
+
super((resolve34) => {
|
|
25189
|
+
resolve34(null);
|
|
24784
25190
|
});
|
|
24785
25191
|
this.responsePromise = responsePromise;
|
|
24786
25192
|
this.parseResponse = parseResponse;
|
|
@@ -24880,29 +25286,29 @@ var APIClient = class {
|
|
|
24880
25286
|
defaultIdempotencyKey() {
|
|
24881
25287
|
return `stainless-node-retry-${uuid4()}`;
|
|
24882
25288
|
}
|
|
24883
|
-
get(
|
|
24884
|
-
return this.methodRequest("get",
|
|
25289
|
+
get(path49, opts) {
|
|
25290
|
+
return this.methodRequest("get", path49, opts);
|
|
24885
25291
|
}
|
|
24886
|
-
post(
|
|
24887
|
-
return this.methodRequest("post",
|
|
25292
|
+
post(path49, opts) {
|
|
25293
|
+
return this.methodRequest("post", path49, opts);
|
|
24888
25294
|
}
|
|
24889
|
-
patch(
|
|
24890
|
-
return this.methodRequest("patch",
|
|
25295
|
+
patch(path49, opts) {
|
|
25296
|
+
return this.methodRequest("patch", path49, opts);
|
|
24891
25297
|
}
|
|
24892
|
-
put(
|
|
24893
|
-
return this.methodRequest("put",
|
|
25298
|
+
put(path49, opts) {
|
|
25299
|
+
return this.methodRequest("put", path49, opts);
|
|
24894
25300
|
}
|
|
24895
|
-
delete(
|
|
24896
|
-
return this.methodRequest("delete",
|
|
25301
|
+
delete(path49, opts) {
|
|
25302
|
+
return this.methodRequest("delete", path49, opts);
|
|
24897
25303
|
}
|
|
24898
|
-
methodRequest(method,
|
|
25304
|
+
methodRequest(method, path49, opts) {
|
|
24899
25305
|
return this.request(Promise.resolve(opts).then(async (opts2) => {
|
|
24900
25306
|
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;
|
|
24901
|
-
return { method, path:
|
|
25307
|
+
return { method, path: path49, ...opts2, body };
|
|
24902
25308
|
}));
|
|
24903
25309
|
}
|
|
24904
|
-
getAPIList(
|
|
24905
|
-
return this.requestAPIList(Page, { method: "get", path:
|
|
25310
|
+
getAPIList(path49, Page, opts) {
|
|
25311
|
+
return this.requestAPIList(Page, { method: "get", path: path49, ...opts });
|
|
24906
25312
|
}
|
|
24907
25313
|
calculateContentLength(body) {
|
|
24908
25314
|
if (typeof body === "string") {
|
|
@@ -24920,10 +25326,10 @@ var APIClient = class {
|
|
|
24920
25326
|
return null;
|
|
24921
25327
|
}
|
|
24922
25328
|
buildRequest(options) {
|
|
24923
|
-
const { method, path:
|
|
25329
|
+
const { method, path: path49, query, headers = {} } = options;
|
|
24924
25330
|
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;
|
|
24925
25331
|
const contentLength = this.calculateContentLength(body);
|
|
24926
|
-
const url = this.buildURL(
|
|
25332
|
+
const url = this.buildURL(path49, query);
|
|
24927
25333
|
if ("timeout" in options)
|
|
24928
25334
|
validatePositiveInteger("timeout", options.timeout);
|
|
24929
25335
|
const timeout = options.timeout ?? this.timeout;
|
|
@@ -25032,8 +25438,8 @@ var APIClient = class {
|
|
|
25032
25438
|
const request = this.makeRequest(options, null);
|
|
25033
25439
|
return new PagePromise(this, request, Page);
|
|
25034
25440
|
}
|
|
25035
|
-
buildURL(
|
|
25036
|
-
const url = isAbsoluteURL(
|
|
25441
|
+
buildURL(path49, query) {
|
|
25442
|
+
const url = isAbsoluteURL(path49) ? new URL(path49) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path49.startsWith("/") ? path49.slice(1) : path49));
|
|
25037
25443
|
const defaultQuery = this.defaultQuery();
|
|
25038
25444
|
if (!isEmptyObj(defaultQuery)) {
|
|
25039
25445
|
query = { ...defaultQuery, ...query };
|
|
@@ -25318,7 +25724,7 @@ var startsWithSchemeRegexp = new RegExp("^(?:[a-z]+:)?//", "i");
|
|
|
25318
25724
|
var isAbsoluteURL = (url) => {
|
|
25319
25725
|
return startsWithSchemeRegexp.test(url);
|
|
25320
25726
|
};
|
|
25321
|
-
var sleep = (ms) => new Promise((
|
|
25727
|
+
var sleep = (ms) => new Promise((resolve34) => setTimeout(resolve34, ms));
|
|
25322
25728
|
var validatePositiveInteger = (name, n2) => {
|
|
25323
25729
|
if (typeof n2 !== "number" || !Number.isInteger(n2)) {
|
|
25324
25730
|
throw new AnthropicError(`${name} must be an integer`);
|
|
@@ -25809,12 +26215,12 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
|
|
|
25809
26215
|
}
|
|
25810
26216
|
return this._emit("error", new AnthropicError(String(error3)));
|
|
25811
26217
|
});
|
|
25812
|
-
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((
|
|
25813
|
-
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise,
|
|
26218
|
+
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve34, reject) => {
|
|
26219
|
+
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve34, "f");
|
|
25814
26220
|
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectConnectedPromise, reject, "f");
|
|
25815
26221
|
}), "f");
|
|
25816
|
-
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((
|
|
25817
|
-
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise,
|
|
26222
|
+
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve34, reject) => {
|
|
26223
|
+
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve34, "f");
|
|
25818
26224
|
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_rejectEndPromise, reject, "f");
|
|
25819
26225
|
}), "f");
|
|
25820
26226
|
__classPrivateFieldGet8(this, _PromptCachingBetaMessageStream_connectedPromise, "f").catch(() => {
|
|
@@ -25943,11 +26349,11 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
|
|
|
25943
26349
|
* const message = await stream.emitted('message') // rejects if the stream errors
|
|
25944
26350
|
*/
|
|
25945
26351
|
emitted(event) {
|
|
25946
|
-
return new Promise((
|
|
26352
|
+
return new Promise((resolve34, reject) => {
|
|
25947
26353
|
__classPrivateFieldSet7(this, _PromptCachingBetaMessageStream_catchingPromiseCreated, true, "f");
|
|
25948
26354
|
if (event !== "error")
|
|
25949
26355
|
this.once("error", reject);
|
|
25950
|
-
this.once(event,
|
|
26356
|
+
this.once(event, resolve34);
|
|
25951
26357
|
});
|
|
25952
26358
|
}
|
|
25953
26359
|
async done() {
|
|
@@ -26174,7 +26580,7 @@ var PromptCachingBetaMessageStream = class _PromptCachingBetaMessageStream {
|
|
|
26174
26580
|
if (done) {
|
|
26175
26581
|
return { value: void 0, done: true };
|
|
26176
26582
|
}
|
|
26177
|
-
return new Promise((
|
|
26583
|
+
return new Promise((resolve34, reject) => readQueue.push({ resolve: resolve34, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
|
26178
26584
|
}
|
|
26179
26585
|
const chunk = pushQueue.shift();
|
|
26180
26586
|
return { value: chunk, done: false };
|
|
@@ -26322,12 +26728,12 @@ var MessageStream = class _MessageStream {
|
|
|
26322
26728
|
}
|
|
26323
26729
|
return this._emit("error", new AnthropicError(String(error3)));
|
|
26324
26730
|
});
|
|
26325
|
-
__classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((
|
|
26326
|
-
__classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise,
|
|
26731
|
+
__classPrivateFieldSet8(this, _MessageStream_connectedPromise, new Promise((resolve34, reject) => {
|
|
26732
|
+
__classPrivateFieldSet8(this, _MessageStream_resolveConnectedPromise, resolve34, "f");
|
|
26327
26733
|
__classPrivateFieldSet8(this, _MessageStream_rejectConnectedPromise, reject, "f");
|
|
26328
26734
|
}), "f");
|
|
26329
|
-
__classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((
|
|
26330
|
-
__classPrivateFieldSet8(this, _MessageStream_resolveEndPromise,
|
|
26735
|
+
__classPrivateFieldSet8(this, _MessageStream_endPromise, new Promise((resolve34, reject) => {
|
|
26736
|
+
__classPrivateFieldSet8(this, _MessageStream_resolveEndPromise, resolve34, "f");
|
|
26331
26737
|
__classPrivateFieldSet8(this, _MessageStream_rejectEndPromise, reject, "f");
|
|
26332
26738
|
}), "f");
|
|
26333
26739
|
__classPrivateFieldGet9(this, _MessageStream_connectedPromise, "f").catch(() => {
|
|
@@ -26456,11 +26862,11 @@ var MessageStream = class _MessageStream {
|
|
|
26456
26862
|
* const message = await stream.emitted('message') // rejects if the stream errors
|
|
26457
26863
|
*/
|
|
26458
26864
|
emitted(event) {
|
|
26459
|
-
return new Promise((
|
|
26865
|
+
return new Promise((resolve34, reject) => {
|
|
26460
26866
|
__classPrivateFieldSet8(this, _MessageStream_catchingPromiseCreated, true, "f");
|
|
26461
26867
|
if (event !== "error")
|
|
26462
26868
|
this.once("error", reject);
|
|
26463
|
-
this.once(event,
|
|
26869
|
+
this.once(event, resolve34);
|
|
26464
26870
|
});
|
|
26465
26871
|
}
|
|
26466
26872
|
async done() {
|
|
@@ -26687,7 +27093,7 @@ var MessageStream = class _MessageStream {
|
|
|
26687
27093
|
if (done) {
|
|
26688
27094
|
return { value: void 0, done: true };
|
|
26689
27095
|
}
|
|
26690
|
-
return new Promise((
|
|
27096
|
+
return new Promise((resolve34, reject) => readQueue.push({ resolve: resolve34, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
|
26691
27097
|
}
|
|
26692
27098
|
const chunk = pushQueue.shift();
|
|
26693
27099
|
return { value: chunk, done: false };
|
|
@@ -26947,11 +27353,11 @@ async function promptApplyAgentMdProposal(repoPath) {
|
|
|
26947
27353
|
}
|
|
26948
27354
|
async function askYesNo2(question) {
|
|
26949
27355
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
26950
|
-
return new Promise((
|
|
27356
|
+
return new Promise((resolve34) => {
|
|
26951
27357
|
process.stderr.write(`${question} `);
|
|
26952
27358
|
rl.once("line", (answer) => {
|
|
26953
27359
|
rl.close();
|
|
26954
|
-
|
|
27360
|
+
resolve34(/^y(es)?$/i.test(answer.trim()));
|
|
26955
27361
|
});
|
|
26956
27362
|
});
|
|
26957
27363
|
}
|
|
@@ -27181,7 +27587,7 @@ async function executeAuthoringToolCall(toolName, input, repoPath, harnessDir, c
|
|
|
27181
27587
|
}
|
|
27182
27588
|
async function askUser(question, options) {
|
|
27183
27589
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
|
|
27184
|
-
return new Promise((
|
|
27590
|
+
return new Promise((resolve34) => {
|
|
27185
27591
|
process.stderr.write("\n");
|
|
27186
27592
|
process.stderr.write(`\u2753 ${question}
|
|
27187
27593
|
`);
|
|
@@ -27192,7 +27598,7 @@ async function askUser(question, options) {
|
|
|
27192
27598
|
process.stderr.write("> ");
|
|
27193
27599
|
rl.once("line", (answer) => {
|
|
27194
27600
|
rl.close();
|
|
27195
|
-
|
|
27601
|
+
resolve34(answer.trim());
|
|
27196
27602
|
});
|
|
27197
27603
|
});
|
|
27198
27604
|
}
|
|
@@ -27336,7 +27742,7 @@ function runScript(scriptPath, args = [], options = {}) {
|
|
|
27336
27742
|
function runScriptCapture(scriptPath, args = [], options = {}) {
|
|
27337
27743
|
const stream = options.stream ?? false;
|
|
27338
27744
|
const { stream: _stream, ...spawnOptions } = options;
|
|
27339
|
-
return new Promise((
|
|
27745
|
+
return new Promise((resolve34) => {
|
|
27340
27746
|
const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
|
|
27341
27747
|
...spawnOptions,
|
|
27342
27748
|
stdio: ["inherit", "pipe", "pipe"]
|
|
@@ -27351,13 +27757,13 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
|
|
|
27351
27757
|
stderr += d2;
|
|
27352
27758
|
if (stream) process.stderr.write(d2);
|
|
27353
27759
|
});
|
|
27354
|
-
proc.on("close", (code) =>
|
|
27760
|
+
proc.on("close", (code) => resolve34({ stdout, stderr, code: code ?? 0 }));
|
|
27355
27761
|
});
|
|
27356
27762
|
}
|
|
27357
27763
|
function runShellCommand(command2, options = {}) {
|
|
27358
27764
|
const stream = options.stream ?? false;
|
|
27359
27765
|
const { stream: _stream, ...spawnOptions } = options;
|
|
27360
|
-
return new Promise((
|
|
27766
|
+
return new Promise((resolve34) => {
|
|
27361
27767
|
const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
|
|
27362
27768
|
...spawnOptions,
|
|
27363
27769
|
stdio: ["inherit", "pipe", "pipe"]
|
|
@@ -27372,7 +27778,7 @@ function runShellCommand(command2, options = {}) {
|
|
|
27372
27778
|
stderr += d2;
|
|
27373
27779
|
if (stream) process.stderr.write(d2);
|
|
27374
27780
|
});
|
|
27375
|
-
proc.on("close", (code) =>
|
|
27781
|
+
proc.on("close", (code) => resolve34({ stdout, stderr, code: code ?? 0 }));
|
|
27376
27782
|
});
|
|
27377
27783
|
}
|
|
27378
27784
|
|
|
@@ -28536,16 +28942,16 @@ async function promptScaffoldCursorRule(exists) {
|
|
|
28536
28942
|
}
|
|
28537
28943
|
async function askYesNo3(question) {
|
|
28538
28944
|
const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
|
|
28539
|
-
return new Promise((
|
|
28945
|
+
return new Promise((resolve34) => {
|
|
28540
28946
|
process.stderr.write(`${question} `);
|
|
28541
28947
|
rl.once("line", (answer) => {
|
|
28542
28948
|
rl.close();
|
|
28543
28949
|
const trimmed = answer.trim();
|
|
28544
28950
|
if (trimmed === "") {
|
|
28545
|
-
|
|
28951
|
+
resolve34(true);
|
|
28546
28952
|
return;
|
|
28547
28953
|
}
|
|
28548
|
-
|
|
28954
|
+
resolve34(/^y(es)?$/i.test(trimmed));
|
|
28549
28955
|
});
|
|
28550
28956
|
});
|
|
28551
28957
|
}
|
|
@@ -28663,7 +29069,6 @@ function buildLaunchFlagArgs(flags) {
|
|
|
28663
29069
|
if (flags.confirmReplace) args.push("--replace");
|
|
28664
29070
|
if (flags.force) args.push("--force");
|
|
28665
29071
|
if (flags.resume) args.push("--resume");
|
|
28666
|
-
if (flags.purpose) args.push(`--purpose=${flags.purpose}`);
|
|
28667
29072
|
return args;
|
|
28668
29073
|
}
|
|
28669
29074
|
function resolveRepoPath(repoPath) {
|
|
@@ -28744,9 +29149,6 @@ function buildExecutionPlan(repoPath, stage, options) {
|
|
|
28744
29149
|
const cwd = stage.cwd ? path24.resolve(resolvedRepo, stage.cwd) : resolvedRepo;
|
|
28745
29150
|
const extraArgs = options.args ?? [];
|
|
28746
29151
|
const launchFlagArgs = stage.kind === "launch" && options.launchFlags ? buildLaunchFlagArgs(options.launchFlags) : [];
|
|
28747
|
-
if (stage.kind === "launch" && options.launchFlags?.purpose) {
|
|
28748
|
-
mergedEnv.HAR_SESSION_PURPOSE = options.launchFlags.purpose;
|
|
28749
|
-
}
|
|
28750
29152
|
if (stage.command) {
|
|
28751
29153
|
let shellCommand = substituteAgentId(stage.command, options.agentId);
|
|
28752
29154
|
for (const extra of [...extraArgs, ...launchFlagArgs]) {
|
|
@@ -28843,15 +29245,7 @@ var localScriptExecutor = new LocalScriptExecutor();
|
|
|
28843
29245
|
|
|
28844
29246
|
// src/core/control-sync.ts
|
|
28845
29247
|
var path38 = __toESM(require("path"));
|
|
28846
|
-
|
|
28847
|
-
// src/core/control-config.ts
|
|
28848
|
-
var DEFAULT_CONTROL_API_URL = "http://localhost:3847";
|
|
28849
|
-
function getControlApiUrl() {
|
|
28850
|
-
return process.env.HAR_CONTROL_API_URL ?? DEFAULT_CONTROL_API_URL;
|
|
28851
|
-
}
|
|
28852
|
-
function isControlEnabled() {
|
|
28853
|
-
return process.env.HAR_CONTROL_DISABLED !== "true";
|
|
28854
|
-
}
|
|
29248
|
+
init_control_config();
|
|
28855
29249
|
|
|
28856
29250
|
// src/core/control-registry.ts
|
|
28857
29251
|
var fs26 = __toESM(require("fs"));
|
|
@@ -29097,6 +29491,7 @@ var path30 = __toESM(require("path"));
|
|
|
29097
29491
|
var import_child_process4 = require("child_process");
|
|
29098
29492
|
var fs29 = __toESM(require("fs"));
|
|
29099
29493
|
var path28 = __toESM(require("path"));
|
|
29494
|
+
init_control_config();
|
|
29100
29495
|
|
|
29101
29496
|
// src/core/slot-ports.ts
|
|
29102
29497
|
var import_child_process3 = require("child_process");
|
|
@@ -29319,7 +29714,6 @@ function collectOccupiedSlot(repoPath, agentId) {
|
|
|
29319
29714
|
sessionStatus: session?.status,
|
|
29320
29715
|
lastError: session?.lastError,
|
|
29321
29716
|
sessionCreatedAt: session?.createdAt,
|
|
29322
|
-
purpose: session?.purpose,
|
|
29323
29717
|
dirty,
|
|
29324
29718
|
harnessUsage: "none"
|
|
29325
29719
|
};
|
|
@@ -29330,7 +29724,6 @@ function formatOccupiedSlot(slot, resume) {
|
|
|
29330
29724
|
slot.worktreePath ? ` Worktree: ${slot.worktreePath}` : void 0,
|
|
29331
29725
|
slot.branch ? ` Branch: ${slot.branch}` : void 0,
|
|
29332
29726
|
slot.workDir ? ` Work dir: ${slot.workDir}` : void 0,
|
|
29333
|
-
slot.purpose ? ` Purpose: ${slot.purpose}` : void 0,
|
|
29334
29727
|
slot.sessionStatus ? ` Status: ${slot.sessionStatus}` : void 0,
|
|
29335
29728
|
slot.lastError ? ` Error: ${slot.lastError}` : void 0,
|
|
29336
29729
|
slot.sessionCreatedAt ? ` Since: ${slot.sessionCreatedAt}` : void 0,
|
|
@@ -29805,7 +30198,6 @@ function collectSlotStatus(harnessRoot, agentId, runs, pm2Procs) {
|
|
|
29805
30198
|
baseBranch: session?.baseBranch,
|
|
29806
30199
|
baseCommit: session?.baseCommit,
|
|
29807
30200
|
sessionCreatedAt: session?.createdAt,
|
|
29808
|
-
purpose: session?.purpose,
|
|
29809
30201
|
sessionStatus: session?.status,
|
|
29810
30202
|
lastError: session?.lastError,
|
|
29811
30203
|
resumeHint,
|
|
@@ -30044,105 +30436,19 @@ function createRemoteExecutor(apiUrl, apiKey) {
|
|
|
30044
30436
|
return new RemoteExecutor(url, key);
|
|
30045
30437
|
}
|
|
30046
30438
|
|
|
30047
|
-
// src/core/
|
|
30048
|
-
|
|
30049
|
-
var os9 = __toESM(require("os"));
|
|
30050
|
-
var path34 = __toESM(require("path"));
|
|
30051
|
-
var DEFAULT_SIGNALS_ON = {
|
|
30052
|
-
metrics: true,
|
|
30053
|
-
logs: true,
|
|
30054
|
-
prompts: false,
|
|
30055
|
-
traces: false
|
|
30056
|
-
};
|
|
30057
|
-
var DEFAULT_SIGNALS_OFF = {
|
|
30058
|
-
metrics: false,
|
|
30059
|
-
logs: false,
|
|
30060
|
-
prompts: false,
|
|
30061
|
-
traces: false
|
|
30062
|
-
};
|
|
30063
|
-
function getPreferencePath() {
|
|
30064
|
-
if (process.env.HAR_TELEMETRY_CONFIG_PATH) {
|
|
30065
|
-
return path34.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
|
|
30066
|
-
}
|
|
30067
|
-
return path34.join(os9.homedir(), ".har", "telemetry.json");
|
|
30068
|
-
}
|
|
30069
|
-
function parseEnvOverride(raw) {
|
|
30070
|
-
if (raw === void 0 || raw === "") return void 0;
|
|
30071
|
-
const normalized = raw.trim().toLowerCase();
|
|
30072
|
-
if (["0", "false", "off", "no", "disabled"].includes(normalized)) return false;
|
|
30073
|
-
if (["1", "true", "on", "yes", "enabled"].includes(normalized)) return true;
|
|
30074
|
-
return void 0;
|
|
30075
|
-
}
|
|
30076
|
-
function normalizeSignals(enabled, raw) {
|
|
30077
|
-
if (!enabled) return { ...DEFAULT_SIGNALS_OFF };
|
|
30078
|
-
return {
|
|
30079
|
-
metrics: raw?.metrics !== false,
|
|
30080
|
-
logs: raw?.logs !== false,
|
|
30081
|
-
prompts: raw?.prompts === true,
|
|
30082
|
-
traces: raw?.traces === true
|
|
30083
|
-
};
|
|
30084
|
-
}
|
|
30085
|
-
function readTelemetryPreference() {
|
|
30086
|
-
const preferencePath = getPreferencePath();
|
|
30087
|
-
try {
|
|
30088
|
-
if (!fs34.existsSync(preferencePath)) {
|
|
30089
|
-
return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
|
|
30090
|
-
}
|
|
30091
|
-
const parsed = JSON.parse(fs34.readFileSync(preferencePath, "utf8"));
|
|
30092
|
-
const enabled = parsed.enabled !== false;
|
|
30093
|
-
return {
|
|
30094
|
-
enabled,
|
|
30095
|
-
signals: normalizeSignals(enabled, parsed.signals),
|
|
30096
|
-
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : void 0
|
|
30097
|
-
};
|
|
30098
|
-
} catch {
|
|
30099
|
-
return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
|
|
30100
|
-
}
|
|
30101
|
-
}
|
|
30102
|
-
function writeTelemetryPreference(enabled, signals) {
|
|
30103
|
-
const current = readTelemetryPreference();
|
|
30104
|
-
const nextSignals = normalizeSignals(enabled, {
|
|
30105
|
-
...current.signals,
|
|
30106
|
-
...signals
|
|
30107
|
-
});
|
|
30108
|
-
const preference = {
|
|
30109
|
-
enabled,
|
|
30110
|
-
signals: enabled ? nextSignals : { ...DEFAULT_SIGNALS_OFF },
|
|
30111
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
30112
|
-
};
|
|
30113
|
-
const preferencePath = getPreferencePath();
|
|
30114
|
-
fs34.mkdirSync(path34.dirname(preferencePath), { recursive: true });
|
|
30115
|
-
fs34.writeFileSync(preferencePath, JSON.stringify(preference, null, 2) + "\n");
|
|
30116
|
-
return preference;
|
|
30117
|
-
}
|
|
30118
|
-
function isTelemetryEnabled() {
|
|
30119
|
-
const envOverride = parseEnvOverride(process.env.HAR_TELEMETRY);
|
|
30120
|
-
if (envOverride !== void 0) return envOverride;
|
|
30121
|
-
return readTelemetryPreference().enabled;
|
|
30122
|
-
}
|
|
30123
|
-
function getTelemetrySignals() {
|
|
30124
|
-
if (!isTelemetryEnabled()) return { ...DEFAULT_SIGNALS_OFF };
|
|
30125
|
-
return readTelemetryPreference().signals;
|
|
30126
|
-
}
|
|
30127
|
-
function getTelemetryPreferencePath() {
|
|
30128
|
-
return getPreferencePath();
|
|
30129
|
-
}
|
|
30130
|
-
var TELEMETRY_SIGNALS = [
|
|
30131
|
-
"Metrics (default): tokens and estimated USD cost via OTEL metrics",
|
|
30132
|
-
"Logs/events (default): session events (tool calls, api_request) without prompt bodies",
|
|
30133
|
-
"Prompts (opt-in): user/assistant text via OTEL_LOG_USER_PROMPTS \u2014 har telemetry on --prompts",
|
|
30134
|
-
"Traces (opt-in): thin span ingest when CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1",
|
|
30135
|
-
"Fallback: har control sync harvests local Claude/Codex session files when OTEL is missing"
|
|
30136
|
-
];
|
|
30439
|
+
// src/core/control-sync.ts
|
|
30440
|
+
init_telemetry_config();
|
|
30137
30441
|
|
|
30138
30442
|
// src/core/usage-harvest/claude.ts
|
|
30139
30443
|
var fs36 = __toESM(require("fs"));
|
|
30140
30444
|
var os10 = __toESM(require("os"));
|
|
30141
30445
|
var path36 = __toESM(require("path"));
|
|
30446
|
+
init_telemetry_config();
|
|
30142
30447
|
|
|
30143
30448
|
// src/core/telemetry-env.ts
|
|
30144
30449
|
var fs35 = __toESM(require("fs"));
|
|
30145
30450
|
var path35 = __toESM(require("path"));
|
|
30451
|
+
init_control_config();
|
|
30146
30452
|
function escapeAttrValue(value) {
|
|
30147
30453
|
return value.replace(/[,=]/g, "_");
|
|
30148
30454
|
}
|
|
@@ -30155,7 +30461,6 @@ function buildOtelResourceAttributes(attrs) {
|
|
|
30155
30461
|
];
|
|
30156
30462
|
if (attrs.branch) parts.push(`har.branch=${escapeAttrValue(attrs.branch)}`);
|
|
30157
30463
|
if (attrs.suffix) parts.push(`har.suffix=${escapeAttrValue(attrs.suffix)}`);
|
|
30158
|
-
if (attrs.purpose) parts.push(`har.purpose=${escapeAttrValue(attrs.purpose)}`);
|
|
30159
30464
|
return parts.join(",");
|
|
30160
30465
|
}
|
|
30161
30466
|
function buildSessionKey(input) {
|
|
@@ -30163,49 +30468,22 @@ function buildSessionKey(input) {
|
|
|
30163
30468
|
const stamp = (input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()).replace(/[:.]/g, "-");
|
|
30164
30469
|
return `agent-${input.agentId}-${input.suffix ?? stamp}`;
|
|
30165
30470
|
}
|
|
30166
|
-
function buildTelemetryEnvBlock(attrs
|
|
30471
|
+
function buildTelemetryEnvBlock(attrs) {
|
|
30167
30472
|
const apiUrl = getControlApiUrl().replace(/\/$/, "");
|
|
30168
30473
|
const lines = [
|
|
30169
30474
|
"",
|
|
30170
30475
|
"# HAR session attribution (generated)",
|
|
30171
30476
|
`HAR_SESSION_KEY=${attrs.sessionKey}`,
|
|
30172
30477
|
`HAR_CONTROL_API_URL=${apiUrl}`,
|
|
30173
|
-
`OTEL_RESOURCE_ATTRIBUTES=${buildOtelResourceAttributes(attrs)}
|
|
30478
|
+
`OTEL_RESOURCE_ATTRIBUTES=${buildOtelResourceAttributes(attrs)}`,
|
|
30479
|
+
"# Agent telemetry: opentelemetry-hooks \u2192 Mission Control (har telemetry on|off)"
|
|
30174
30480
|
];
|
|
30175
|
-
const injectOtel = isTelemetryEnabled() && options?.otelReady !== false;
|
|
30176
|
-
if (injectOtel) {
|
|
30177
|
-
const signals = getTelemetrySignals();
|
|
30178
|
-
lines.push(
|
|
30179
|
-
"# HAR telemetry \u2192 Mission Control OTLP (disable: har telemetry off)",
|
|
30180
|
-
"CLAUDE_CODE_ENABLE_TELEMETRY=1",
|
|
30181
|
-
"OTEL_EXPORTER_OTLP_PROTOCOL=http/json",
|
|
30182
|
-
`OTEL_EXPORTER_OTLP_ENDPOINT=${apiUrl}/api/otel`
|
|
30183
|
-
);
|
|
30184
|
-
if (signals.metrics) {
|
|
30185
|
-
lines.push("OTEL_METRICS_EXPORTER=otlp");
|
|
30186
|
-
}
|
|
30187
|
-
if (signals.logs) {
|
|
30188
|
-
lines.push("OTEL_LOGS_EXPORTER=otlp");
|
|
30189
|
-
}
|
|
30190
|
-
if (signals.prompts) {
|
|
30191
|
-
lines.push(
|
|
30192
|
-
"OTEL_LOG_USER_PROMPTS=1",
|
|
30193
|
-
"OTEL_LOG_ASSISTANT_RESPONSES=1"
|
|
30194
|
-
);
|
|
30195
|
-
}
|
|
30196
|
-
if (signals.traces) {
|
|
30197
|
-
lines.push(
|
|
30198
|
-
"OTEL_TRACES_EXPORTER=otlp",
|
|
30199
|
-
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1"
|
|
30200
|
-
);
|
|
30201
|
-
}
|
|
30202
|
-
}
|
|
30203
30481
|
return lines.join("\n") + "\n";
|
|
30204
30482
|
}
|
|
30205
30483
|
var TELEMETRY_MARKER_START = "# HAR session attribution (generated)";
|
|
30206
30484
|
var TELEMETRY_MARKER_END = "# end HAR telemetry";
|
|
30207
|
-
function appendTelemetryEnvToFile(envFilePath, attrs
|
|
30208
|
-
const block = buildTelemetryEnvBlock(attrs
|
|
30485
|
+
function appendTelemetryEnvToFile(envFilePath, attrs) {
|
|
30486
|
+
const block = buildTelemetryEnvBlock(attrs).trimEnd() + `
|
|
30209
30487
|
${TELEMETRY_MARKER_END}
|
|
30210
30488
|
`;
|
|
30211
30489
|
let existing = "";
|
|
@@ -30225,22 +30503,6 @@ ${TELEMETRY_MARKER_END}
|
|
|
30225
30503
|
const combined = (existing.replace(/\n+$/, "\n") + block).replace(/^\n+/, "");
|
|
30226
30504
|
fs35.writeFileSync(envFilePath, combined.endsWith("\n") ? combined : combined + "\n");
|
|
30227
30505
|
}
|
|
30228
|
-
function buildCodexOtelSnippet(attrs) {
|
|
30229
|
-
const apiUrl = getControlApiUrl().replace(/\/$/, "");
|
|
30230
|
-
const resource = buildOtelResourceAttributes(attrs);
|
|
30231
|
-
return `# Merge into ~/.codex/config.toml (HAR does not overwrite your config)
|
|
30232
|
-
# Generated for session ${attrs.sessionKey}
|
|
30233
|
-
|
|
30234
|
-
[otel]
|
|
30235
|
-
exporter = "otlp-http"
|
|
30236
|
-
endpoint = "${apiUrl}/api/otel"
|
|
30237
|
-
metrics_exporter = "otlp-http"
|
|
30238
|
-
|
|
30239
|
-
# Optional: set resource attributes via environment when starting Codex:
|
|
30240
|
-
# export OTEL_RESOURCE_ATTRIBUTES="${resource}"
|
|
30241
|
-
# export HAR_SESSION_KEY="${attrs.sessionKey}"
|
|
30242
|
-
`;
|
|
30243
|
-
}
|
|
30244
30506
|
|
|
30245
30507
|
// src/core/usage-harvest/claude.ts
|
|
30246
30508
|
function pathsMatch(candidate, targets) {
|
|
@@ -30578,7 +30840,7 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
|
|
|
30578
30840
|
const deadline = Date.now() + timeoutMs;
|
|
30579
30841
|
while (Date.now() < deadline) {
|
|
30580
30842
|
if (await isControlApiReachable(apiUrl)) return true;
|
|
30581
|
-
await new Promise((
|
|
30843
|
+
await new Promise((resolve34) => setTimeout(resolve34, intervalMs));
|
|
30582
30844
|
}
|
|
30583
30845
|
return false;
|
|
30584
30846
|
}
|
|
@@ -30775,6 +31037,9 @@ function checkLaunchGuard2(repoPath, agentId, options = {}) {
|
|
|
30775
31037
|
return { allowed: true, slot: occupied.slot, readiness };
|
|
30776
31038
|
}
|
|
30777
31039
|
|
|
31040
|
+
// src/core/telemetry-ensure.ts
|
|
31041
|
+
init_control_config();
|
|
31042
|
+
|
|
30778
31043
|
// src/core/control-lifecycle.ts
|
|
30779
31044
|
var import_child_process8 = require("child_process");
|
|
30780
31045
|
var path39 = __toESM(require("path"));
|
|
@@ -30795,6 +31060,7 @@ function shouldBuildControlLocally() {
|
|
|
30795
31060
|
}
|
|
30796
31061
|
|
|
30797
31062
|
// src/core/control-lifecycle.ts
|
|
31063
|
+
init_control_config();
|
|
30798
31064
|
var CONTROL_CONTAINER_NAME = "har-control";
|
|
30799
31065
|
var CONTROL_DATA_VOLUME = "har_control_data";
|
|
30800
31066
|
var CONTROL_CONTAINER_PORT = 3847;
|
|
@@ -30903,6 +31169,7 @@ async function startControlAndSync(options) {
|
|
|
30903
31169
|
}
|
|
30904
31170
|
|
|
30905
31171
|
// src/core/telemetry-ensure.ts
|
|
31172
|
+
init_telemetry_config();
|
|
30906
31173
|
async function ensureTelemetryInfrastructure(options) {
|
|
30907
31174
|
const apiUrl = getControlApiUrl();
|
|
30908
31175
|
const telemetryEnabled = isTelemetryEnabled();
|
|
@@ -31001,7 +31268,8 @@ async function ensureTelemetryInfrastructure(options) {
|
|
|
31001
31268
|
}
|
|
31002
31269
|
|
|
31003
31270
|
// src/core/run-service.ts
|
|
31004
|
-
|
|
31271
|
+
init_telemetry_config();
|
|
31272
|
+
var path41 = __toESM(require("path"));
|
|
31005
31273
|
function extractShellOutput(result) {
|
|
31006
31274
|
const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
|
|
31007
31275
|
const stderr = result.logs?.find((log) => log.stream === "stderr")?.content ?? "";
|
|
@@ -31117,23 +31385,31 @@ var RunService = class {
|
|
|
31117
31385
|
worktreePath: slot.worktreePath,
|
|
31118
31386
|
branch: slot.branch,
|
|
31119
31387
|
dirty: slot.dirty,
|
|
31120
|
-
sessionCreatedAt: slot.sessionCreatedAt
|
|
31121
|
-
purpose: slot.purpose
|
|
31388
|
+
sessionCreatedAt: slot.sessionCreatedAt
|
|
31122
31389
|
} : void 0
|
|
31123
31390
|
};
|
|
31124
31391
|
}
|
|
31125
31392
|
let telemetryBanner = "";
|
|
31126
|
-
let otelReady = false;
|
|
31127
31393
|
if (isTelemetryEnabled() && process.env.NODE_ENV !== "test") {
|
|
31128
31394
|
const ensured = await ensureTelemetryInfrastructure({ startIfNeeded: true });
|
|
31129
|
-
otelReady = ensured.otelReady;
|
|
31130
31395
|
if (ensured.message) {
|
|
31131
31396
|
telemetryBanner += `${ensured.message}
|
|
31132
|
-
Usage from Claude
|
|
31397
|
+
Usage from Cursor / Claude / Codex (opentelemetry-hooks) will appear under Worktrees. Disable: har telemetry off
|
|
31133
31398
|
`;
|
|
31134
31399
|
}
|
|
31135
31400
|
if (ensured.warning) {
|
|
31136
31401
|
telemetryBanner += `${ensured.warning}
|
|
31402
|
+
`;
|
|
31403
|
+
}
|
|
31404
|
+
try {
|
|
31405
|
+
const { ensureOtelHooks: ensureOtelHooks2 } = await Promise.resolve().then(() => (init_otel_hooks(), otel_hooks_exports));
|
|
31406
|
+
const hooks = ensureOtelHooks2({ setupAgents: true });
|
|
31407
|
+
if (hooks.message) telemetryBanner += `${hooks.message}
|
|
31408
|
+
`;
|
|
31409
|
+
if (hooks.warning) telemetryBanner += `${hooks.warning}
|
|
31410
|
+
`;
|
|
31411
|
+
} catch (err) {
|
|
31412
|
+
telemetryBanner += `opentelemetry-hooks setup skipped: ${err instanceof Error ? err.message : String(err)}
|
|
31137
31413
|
`;
|
|
31138
31414
|
}
|
|
31139
31415
|
}
|
|
@@ -31147,8 +31423,7 @@ Usage from Claude Code / Codex will appear under Worktrees. Disable: har telemet
|
|
|
31147
31423
|
claude: options.claude,
|
|
31148
31424
|
confirmReplace: options.confirmReplace,
|
|
31149
31425
|
force: options.force,
|
|
31150
|
-
resume: options.resume
|
|
31151
|
-
purpose: options.purpose
|
|
31426
|
+
resume: options.resume
|
|
31152
31427
|
},
|
|
31153
31428
|
trigger: "cli"
|
|
31154
31429
|
});
|
|
@@ -31167,21 +31442,16 @@ Usage from Claude Code / Codex will appear under Worktrees. Disable: har telemet
|
|
|
31167
31442
|
suffix: session.suffix,
|
|
31168
31443
|
createdAt: session.createdAt
|
|
31169
31444
|
});
|
|
31170
|
-
const envFile =
|
|
31445
|
+
const envFile = path41.join(session.workDir, `.env.agent.${options.agentId}`);
|
|
31171
31446
|
try {
|
|
31172
|
-
appendTelemetryEnvToFile(
|
|
31173
|
-
|
|
31174
|
-
|
|
31175
|
-
|
|
31176
|
-
|
|
31177
|
-
|
|
31178
|
-
|
|
31179
|
-
|
|
31180
|
-
suffix: session.suffix,
|
|
31181
|
-
purpose: session.purpose
|
|
31182
|
-
},
|
|
31183
|
-
{ otelReady: otelReady && isTelemetryEnabled() }
|
|
31184
|
-
);
|
|
31447
|
+
appendTelemetryEnvToFile(envFile, {
|
|
31448
|
+
sessionKey,
|
|
31449
|
+
agentId: options.agentId,
|
|
31450
|
+
repoPath: path41.resolve(options.repoPath),
|
|
31451
|
+
workDir: session.workDir,
|
|
31452
|
+
branch: session.branch,
|
|
31453
|
+
suffix: session.suffix
|
|
31454
|
+
});
|
|
31185
31455
|
} catch {
|
|
31186
31456
|
}
|
|
31187
31457
|
}
|
|
@@ -31467,9 +31737,6 @@ var envCommand = {
|
|
|
31467
31737
|
type: "boolean",
|
|
31468
31738
|
default: false,
|
|
31469
31739
|
describe: "Resume a failed or partial launch without creating a new worktree"
|
|
31470
|
-
}).option("purpose", {
|
|
31471
|
-
type: "string",
|
|
31472
|
-
describe: "Optional session label stored in the slot registry (shown in status and occupied-slot warnings)"
|
|
31473
31740
|
}),
|
|
31474
31741
|
handleLaunch
|
|
31475
31742
|
).command(
|
|
@@ -31543,7 +31810,7 @@ var envCommand = {
|
|
|
31543
31810
|
}
|
|
31544
31811
|
};
|
|
31545
31812
|
async function handleInit(argv) {
|
|
31546
|
-
const repoPath =
|
|
31813
|
+
const repoPath = path42.resolve(argv.repo);
|
|
31547
31814
|
header("har env init");
|
|
31548
31815
|
info(`Repository: ${repoPath}`);
|
|
31549
31816
|
try {
|
|
@@ -31601,7 +31868,7 @@ async function handleInit(argv) {
|
|
|
31601
31868
|
}
|
|
31602
31869
|
}
|
|
31603
31870
|
async function handleMaintain(argv) {
|
|
31604
|
-
const repoPath =
|
|
31871
|
+
const repoPath = path42.resolve(argv.repo);
|
|
31605
31872
|
header("har env maintain");
|
|
31606
31873
|
info(`Repository: ${repoPath}`);
|
|
31607
31874
|
try {
|
|
@@ -31699,7 +31966,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
|
|
|
31699
31966
|
if (autoYes) {
|
|
31700
31967
|
const proposal = readAgentMdProposal(repoPath);
|
|
31701
31968
|
if (proposal) {
|
|
31702
|
-
writeFileSafe(
|
|
31969
|
+
writeFileSafe(path42.join(repoPath, "AGENT.md"), proposal.content);
|
|
31703
31970
|
clearAgentMdProposal(repoPath);
|
|
31704
31971
|
info("Applied AGENT.md proposal (--yes)");
|
|
31705
31972
|
}
|
|
@@ -31708,7 +31975,7 @@ async function handleAgentMdProposal(repoPath, autoYes) {
|
|
|
31708
31975
|
await promptApplyAgentMdProposal(repoPath);
|
|
31709
31976
|
}
|
|
31710
31977
|
async function handleAddStage(argv) {
|
|
31711
|
-
const repoPath =
|
|
31978
|
+
const repoPath = path42.resolve(argv.repo);
|
|
31712
31979
|
const available = listStageTemplateIds();
|
|
31713
31980
|
if (argv.list) {
|
|
31714
31981
|
for (const id of available) {
|
|
@@ -31785,7 +32052,7 @@ async function handleAddStage(argv) {
|
|
|
31785
32052
|
}
|
|
31786
32053
|
}
|
|
31787
32054
|
async function handlePreflight(argv) {
|
|
31788
|
-
const repo =
|
|
32055
|
+
const repo = path42.resolve(argv.repo);
|
|
31789
32056
|
const agentId = validateAgentId(argv.id, repo);
|
|
31790
32057
|
const result = await preflightEnvironment({
|
|
31791
32058
|
repoPath: repo,
|
|
@@ -31803,7 +32070,7 @@ async function handlePreflight(argv) {
|
|
|
31803
32070
|
process.exit(result.code);
|
|
31804
32071
|
}
|
|
31805
32072
|
async function handleLaunch(argv) {
|
|
31806
|
-
const repo =
|
|
32073
|
+
const repo = path42.resolve(argv.repo);
|
|
31807
32074
|
const agentId = validateAgentId(argv.id, repo);
|
|
31808
32075
|
let confirmReplace = argv.replace;
|
|
31809
32076
|
let force = argv.force;
|
|
@@ -31815,8 +32082,8 @@ async function handleLaunch(argv) {
|
|
|
31815
32082
|
console.error(guard.reason ?? "");
|
|
31816
32083
|
const readline5 = await import("readline");
|
|
31817
32084
|
const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
|
|
31818
|
-
const answer = await new Promise((
|
|
31819
|
-
rl.question("Replace this slot? [y/N] ",
|
|
32085
|
+
const answer = await new Promise((resolve34) => {
|
|
32086
|
+
rl.question("Replace this slot? [y/N] ", resolve34);
|
|
31820
32087
|
});
|
|
31821
32088
|
rl.close();
|
|
31822
32089
|
if (!/^[Yy]$/.test(answer.trim())) {
|
|
@@ -31832,8 +32099,8 @@ async function handleLaunch(argv) {
|
|
|
31832
32099
|
warn("Worktree has uncommitted changes.");
|
|
31833
32100
|
const readline5 = await import("readline");
|
|
31834
32101
|
const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
|
|
31835
|
-
const answer = await new Promise((
|
|
31836
|
-
rl.question("Discard uncommitted changes? [y/N] ",
|
|
32102
|
+
const answer = await new Promise((resolve34) => {
|
|
32103
|
+
rl.question("Discard uncommitted changes? [y/N] ", resolve34);
|
|
31837
32104
|
});
|
|
31838
32105
|
rl.close();
|
|
31839
32106
|
if (!/^[Yy]$/.test(answer.trim())) {
|
|
@@ -31855,7 +32122,6 @@ async function handleLaunch(argv) {
|
|
|
31855
32122
|
confirmReplace,
|
|
31856
32123
|
force,
|
|
31857
32124
|
resume: argv.resume,
|
|
31858
|
-
purpose: argv.purpose,
|
|
31859
32125
|
capture: false
|
|
31860
32126
|
});
|
|
31861
32127
|
if (result.blocked) {
|
|
@@ -31888,7 +32154,7 @@ async function handleRecover(argv) {
|
|
|
31888
32154
|
});
|
|
31889
32155
|
}
|
|
31890
32156
|
async function handleVerify(argv) {
|
|
31891
|
-
const repo =
|
|
32157
|
+
const repo = path42.resolve(argv.repo);
|
|
31892
32158
|
const agentId = validateAgentId(argv.id, repo);
|
|
31893
32159
|
const result = await runVerification({
|
|
31894
32160
|
repoPath: repo,
|
|
@@ -31900,7 +32166,7 @@ async function handleVerify(argv) {
|
|
|
31900
32166
|
process.exit(result.code);
|
|
31901
32167
|
}
|
|
31902
32168
|
async function handleTeardown(argv) {
|
|
31903
|
-
const repo =
|
|
32169
|
+
const repo = path42.resolve(argv.repo);
|
|
31904
32170
|
const agentId = validateAgentId(argv.id, repo);
|
|
31905
32171
|
const result = await teardownEnvironment({
|
|
31906
32172
|
repoPath: repo,
|
|
@@ -31911,7 +32177,7 @@ async function handleTeardown(argv) {
|
|
|
31911
32177
|
process.exit(result.code);
|
|
31912
32178
|
}
|
|
31913
32179
|
async function handleComplete(argv) {
|
|
31914
|
-
const repo =
|
|
32180
|
+
const repo = path42.resolve(argv.repo);
|
|
31915
32181
|
const agentId = validateAgentId(argv.id, repo);
|
|
31916
32182
|
const result = await completeEnvironment({
|
|
31917
32183
|
repoPath: repo,
|
|
@@ -31932,7 +32198,7 @@ async function handleComplete(argv) {
|
|
|
31932
32198
|
process.exit(result.code);
|
|
31933
32199
|
}
|
|
31934
32200
|
async function handleStatus(argv) {
|
|
31935
|
-
const repoPath =
|
|
32201
|
+
const repoPath = path42.resolve(argv.repo);
|
|
31936
32202
|
if (argv.json) {
|
|
31937
32203
|
const status = collectEnvironmentStatus(repoPath);
|
|
31938
32204
|
const output = EnvironmentStatusSchema.parse(status);
|
|
@@ -31945,7 +32211,7 @@ async function handleStatus(argv) {
|
|
|
31945
32211
|
});
|
|
31946
32212
|
}
|
|
31947
32213
|
async function handleRunsList(argv) {
|
|
31948
|
-
const repoPath =
|
|
32214
|
+
const repoPath = path42.resolve(argv.repo);
|
|
31949
32215
|
const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
|
|
31950
32216
|
if (argv.json) {
|
|
31951
32217
|
process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
|
|
@@ -31962,7 +32228,7 @@ async function handleRunsList(argv) {
|
|
|
31962
32228
|
}
|
|
31963
32229
|
}
|
|
31964
32230
|
async function handleRunsGet(argv) {
|
|
31965
|
-
const run2 = getRun(
|
|
32231
|
+
const run2 = getRun(path42.resolve(argv.repo), argv.runId);
|
|
31966
32232
|
if (!run2) {
|
|
31967
32233
|
error(`Run not found: ${argv.runId}`);
|
|
31968
32234
|
process.exit(1);
|
|
@@ -32041,7 +32307,8 @@ function printNextSteps(auto2) {
|
|
|
32041
32307
|
}
|
|
32042
32308
|
|
|
32043
32309
|
// src/cli/commands/control.ts
|
|
32044
|
-
var
|
|
32310
|
+
var path43 = __toESM(require("path"));
|
|
32311
|
+
init_control_config();
|
|
32045
32312
|
var controlCommand = {
|
|
32046
32313
|
command: "control <subcommand>",
|
|
32047
32314
|
describe: "Mission Control dashboard (local)",
|
|
@@ -32144,7 +32411,7 @@ async function handleDown() {
|
|
|
32144
32411
|
process.exit(code);
|
|
32145
32412
|
}
|
|
32146
32413
|
async function handleRegister(argv) {
|
|
32147
|
-
const repoPath =
|
|
32414
|
+
const repoPath = path43.resolve(argv.repo);
|
|
32148
32415
|
header("har control register");
|
|
32149
32416
|
info(`Repository: ${repoPath}`);
|
|
32150
32417
|
try {
|
|
@@ -32164,7 +32431,7 @@ async function handleRegister(argv) {
|
|
|
32164
32431
|
}
|
|
32165
32432
|
}
|
|
32166
32433
|
async function handleSync(argv) {
|
|
32167
|
-
const repoPath =
|
|
32434
|
+
const repoPath = path43.resolve(argv.repo);
|
|
32168
32435
|
try {
|
|
32169
32436
|
await syncRepoWithControl({
|
|
32170
32437
|
repoPath,
|
|
@@ -32203,7 +32470,7 @@ async function handleWatch(argv) {
|
|
|
32203
32470
|
};
|
|
32204
32471
|
const tick = async () => {
|
|
32205
32472
|
if (argv.repo) {
|
|
32206
|
-
await syncOne(
|
|
32473
|
+
await syncOne(path43.resolve(argv.repo));
|
|
32207
32474
|
return;
|
|
32208
32475
|
}
|
|
32209
32476
|
try {
|
|
@@ -32234,12 +32501,12 @@ async function handleLogin(argv) {
|
|
|
32234
32501
|
}
|
|
32235
32502
|
|
|
32236
32503
|
// src/cli/commands/hooks.ts
|
|
32237
|
-
var
|
|
32504
|
+
var path46 = __toESM(require("path"));
|
|
32238
32505
|
|
|
32239
32506
|
// src/core/hooks.ts
|
|
32240
|
-
var
|
|
32241
|
-
var
|
|
32242
|
-
var
|
|
32507
|
+
var fs39 = __toESM(require("fs"));
|
|
32508
|
+
var os13 = __toESM(require("os"));
|
|
32509
|
+
var path44 = __toESM(require("path"));
|
|
32243
32510
|
var MARKER_START = "# >>> har commit gate (managed by `har hooks`) >>>";
|
|
32244
32511
|
var MARKER_END = "# <<< har commit gate <<<";
|
|
32245
32512
|
var PRE_COMMIT_BLOCK = [
|
|
@@ -32264,7 +32531,7 @@ function resolveCheckoutRoot(cwd) {
|
|
|
32264
32531
|
function resolveHooksDir(checkoutDir) {
|
|
32265
32532
|
const hooksPath = tryGit2(checkoutDir, "rev-parse --git-path hooks");
|
|
32266
32533
|
if (!hooksPath) throw new Error(`Not a git checkout: ${checkoutDir}`);
|
|
32267
|
-
return
|
|
32534
|
+
return path44.resolve(checkoutDir, hooksPath);
|
|
32268
32535
|
}
|
|
32269
32536
|
function getConfiguredHooksPath(checkoutDir) {
|
|
32270
32537
|
return tryGit2(checkoutDir, "config core.hooksPath") || void 0;
|
|
@@ -32272,9 +32539,9 @@ function getConfiguredHooksPath(checkoutDir) {
|
|
|
32272
32539
|
function defaultHarInvocation() {
|
|
32273
32540
|
const entry = process.argv[1];
|
|
32274
32541
|
if (entry && entry.endsWith(".js")) {
|
|
32275
|
-
return `"${process.execPath}" "${
|
|
32542
|
+
return `"${process.execPath}" "${path44.resolve(entry)}"`;
|
|
32276
32543
|
}
|
|
32277
|
-
if (entry) return `"${
|
|
32544
|
+
if (entry) return `"${path44.resolve(entry)}"`;
|
|
32278
32545
|
return "har";
|
|
32279
32546
|
}
|
|
32280
32547
|
function buildHookScript(harInvocation, subcommand, failOpenNotice) {
|
|
@@ -32295,40 +32562,40 @@ exit 0
|
|
|
32295
32562
|
`;
|
|
32296
32563
|
}
|
|
32297
32564
|
function upsertMarkedBlock(filePath, block) {
|
|
32298
|
-
if (!
|
|
32299
|
-
|
|
32565
|
+
if (!fs39.existsSync(filePath)) {
|
|
32566
|
+
fs39.writeFileSync(filePath, `#!/bin/sh
|
|
32300
32567
|
${block}
|
|
32301
32568
|
`, { mode: 493 });
|
|
32302
32569
|
return "created";
|
|
32303
32570
|
}
|
|
32304
|
-
const content =
|
|
32571
|
+
const content = fs39.readFileSync(filePath, "utf8");
|
|
32305
32572
|
if (content.includes(MARKER_START)) {
|
|
32306
32573
|
const pattern = new RegExp(
|
|
32307
32574
|
`${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}`
|
|
32308
32575
|
);
|
|
32309
|
-
|
|
32310
|
-
|
|
32576
|
+
fs39.writeFileSync(filePath, content.replace(pattern, block));
|
|
32577
|
+
fs39.chmodSync(filePath, 493);
|
|
32311
32578
|
return "updated";
|
|
32312
32579
|
}
|
|
32313
32580
|
const suffix = content.endsWith("\n") ? "" : "\n";
|
|
32314
|
-
|
|
32581
|
+
fs39.writeFileSync(filePath, `${content}${suffix}
|
|
32315
32582
|
${block}
|
|
32316
32583
|
`);
|
|
32317
|
-
|
|
32584
|
+
fs39.chmodSync(filePath, 493);
|
|
32318
32585
|
return "appended";
|
|
32319
32586
|
}
|
|
32320
32587
|
function removeMarkedBlock(filePath) {
|
|
32321
|
-
if (!
|
|
32322
|
-
const content =
|
|
32588
|
+
if (!fs39.existsSync(filePath)) return false;
|
|
32589
|
+
const content = fs39.readFileSync(filePath, "utf8");
|
|
32323
32590
|
if (!content.includes(MARKER_START)) return false;
|
|
32324
32591
|
const pattern = new RegExp(
|
|
32325
32592
|
`\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`
|
|
32326
32593
|
);
|
|
32327
32594
|
const stripped = content.replace(pattern, "\n");
|
|
32328
32595
|
if (stripped.replace(/^#!\/bin\/sh\n?/, "").trim() === "") {
|
|
32329
|
-
|
|
32596
|
+
fs39.rmSync(filePath);
|
|
32330
32597
|
} else {
|
|
32331
|
-
|
|
32598
|
+
fs39.writeFileSync(filePath, stripped);
|
|
32332
32599
|
}
|
|
32333
32600
|
return true;
|
|
32334
32601
|
}
|
|
@@ -32350,20 +32617,20 @@ Or re-run with --force to write into that directory anyway.`
|
|
|
32350
32617
|
);
|
|
32351
32618
|
}
|
|
32352
32619
|
const hooksDir = resolveHooksDir(checkout);
|
|
32353
|
-
|
|
32620
|
+
fs39.mkdirSync(hooksDir, { recursive: true });
|
|
32354
32621
|
const invocation = options.harInvocation ?? defaultHarInvocation();
|
|
32355
|
-
|
|
32356
|
-
|
|
32622
|
+
fs39.writeFileSync(
|
|
32623
|
+
path44.join(hooksDir, "har-pre-commit"),
|
|
32357
32624
|
buildHookScript(invocation, "check", "har: binary not found; skipping commit gate (reinstall with har hooks install)"),
|
|
32358
32625
|
{ mode: 493 }
|
|
32359
32626
|
);
|
|
32360
|
-
|
|
32361
|
-
|
|
32627
|
+
fs39.writeFileSync(
|
|
32628
|
+
path44.join(hooksDir, "har-post-commit"),
|
|
32362
32629
|
buildHookScript(invocation, "record-commit", "har: binary not found; skipping commit association"),
|
|
32363
32630
|
{ mode: 493 }
|
|
32364
32631
|
);
|
|
32365
|
-
const preCommit = upsertMarkedBlock(
|
|
32366
|
-
const postCommit = upsertMarkedBlock(
|
|
32632
|
+
const preCommit = upsertMarkedBlock(path44.join(hooksDir, "pre-commit"), PRE_COMMIT_BLOCK);
|
|
32633
|
+
const postCommit = upsertMarkedBlock(path44.join(hooksDir, "post-commit"), POST_COMMIT_BLOCK);
|
|
32367
32634
|
ensureValidationsIgnored(checkout);
|
|
32368
32635
|
return { hooksDir, preCommit, postCommit };
|
|
32369
32636
|
}
|
|
@@ -32372,12 +32639,12 @@ function uninstallHooks(repoPath) {
|
|
|
32372
32639
|
if (!checkout) throw new Error(`Not a git repository: ${repoPath}`);
|
|
32373
32640
|
const hooksDir = resolveHooksDir(checkout);
|
|
32374
32641
|
let removed = false;
|
|
32375
|
-
removed = removeMarkedBlock(
|
|
32376
|
-
removed = removeMarkedBlock(
|
|
32642
|
+
removed = removeMarkedBlock(path44.join(hooksDir, "pre-commit")) || removed;
|
|
32643
|
+
removed = removeMarkedBlock(path44.join(hooksDir, "post-commit")) || removed;
|
|
32377
32644
|
for (const file of ["har-pre-commit", "har-post-commit"]) {
|
|
32378
|
-
const full =
|
|
32379
|
-
if (
|
|
32380
|
-
|
|
32645
|
+
const full = path44.join(hooksDir, file);
|
|
32646
|
+
if (fs39.existsSync(full)) {
|
|
32647
|
+
fs39.rmSync(full);
|
|
32381
32648
|
removed = true;
|
|
32382
32649
|
}
|
|
32383
32650
|
}
|
|
@@ -32394,9 +32661,9 @@ function getCommitGateConfig(checkoutDir) {
|
|
|
32394
32661
|
function isAgentWorktree(checkoutDir) {
|
|
32395
32662
|
const branch = getCurrentBranch(checkoutDir);
|
|
32396
32663
|
if (branch && /^har-agent-\d+$/.test(branch)) return true;
|
|
32397
|
-
const worktreesRoot =
|
|
32398
|
-
const resolved =
|
|
32399
|
-
return resolved.startsWith(`${worktreesRoot}${
|
|
32664
|
+
const worktreesRoot = path44.join(os13.homedir(), "worktrees");
|
|
32665
|
+
const resolved = path44.resolve(checkoutDir);
|
|
32666
|
+
return resolved.startsWith(`${worktreesRoot}${path44.sep}`) && /-agent-\d+$/.test(path44.basename(resolved));
|
|
32400
32667
|
}
|
|
32401
32668
|
function resolveEffectiveMode(checkoutDir, gate) {
|
|
32402
32669
|
if (!gate.enabled) return "off";
|
|
@@ -32409,15 +32676,15 @@ function getHooksStatus(repoPath) {
|
|
|
32409
32676
|
const hooksDir = resolveHooksDir(checkout);
|
|
32410
32677
|
const gate = getCommitGateConfig(checkout);
|
|
32411
32678
|
const hasBlock = (name) => {
|
|
32412
|
-
const file =
|
|
32413
|
-
return
|
|
32679
|
+
const file = path44.join(hooksDir, name);
|
|
32680
|
+
return fs39.existsSync(file) && fs39.readFileSync(file, "utf8").includes(MARKER_START);
|
|
32414
32681
|
};
|
|
32415
32682
|
return {
|
|
32416
32683
|
checkout,
|
|
32417
32684
|
hooksDir,
|
|
32418
32685
|
configuredHooksPath: getConfiguredHooksPath(checkout),
|
|
32419
|
-
preCommitInstalled: hasBlock("pre-commit") &&
|
|
32420
|
-
postCommitInstalled: hasBlock("post-commit") &&
|
|
32686
|
+
preCommitInstalled: hasBlock("pre-commit") && fs39.existsSync(path44.join(hooksDir, "har-pre-commit")),
|
|
32687
|
+
postCommitInstalled: hasBlock("post-commit") && fs39.existsSync(path44.join(hooksDir, "har-post-commit")),
|
|
32421
32688
|
gate,
|
|
32422
32689
|
effectiveMode: resolveEffectiveMode(checkout, gate)
|
|
32423
32690
|
};
|
|
@@ -32428,7 +32695,7 @@ function checkCommitGate(cwd) {
|
|
|
32428
32695
|
}
|
|
32429
32696
|
const checkout = resolveCheckoutRoot(cwd);
|
|
32430
32697
|
if (!checkout) return { exitCode: 0, messages: [] };
|
|
32431
|
-
if (!
|
|
32698
|
+
if (!fs39.existsSync(path44.join(checkout, ".har", "stages.json"))) {
|
|
32432
32699
|
return { exitCode: 0, messages: [] };
|
|
32433
32700
|
}
|
|
32434
32701
|
const gate = getCommitGateConfig(checkout);
|
|
@@ -32499,8 +32766,8 @@ async function recordCommitAssociation(cwd) {
|
|
|
32499
32766
|
}
|
|
32500
32767
|
|
|
32501
32768
|
// src/core/claude-hooks.ts
|
|
32502
|
-
var
|
|
32503
|
-
var
|
|
32769
|
+
var fs40 = __toESM(require("fs"));
|
|
32770
|
+
var path45 = __toESM(require("path"));
|
|
32504
32771
|
var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
|
|
32505
32772
|
var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
|
|
32506
32773
|
var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
|
|
@@ -32511,8 +32778,8 @@ function isHarGuardEntry(entry) {
|
|
|
32511
32778
|
);
|
|
32512
32779
|
}
|
|
32513
32780
|
function readSettings(settingsPath) {
|
|
32514
|
-
if (!
|
|
32515
|
-
const raw =
|
|
32781
|
+
if (!fs40.existsSync(settingsPath)) return {};
|
|
32782
|
+
const raw = fs40.readFileSync(settingsPath, "utf8").trim();
|
|
32516
32783
|
if (raw === "") return {};
|
|
32517
32784
|
const parsed = JSON.parse(raw);
|
|
32518
32785
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -32521,19 +32788,19 @@ function readSettings(settingsPath) {
|
|
|
32521
32788
|
return parsed;
|
|
32522
32789
|
}
|
|
32523
32790
|
function writeSettings(settingsPath, settings) {
|
|
32524
|
-
|
|
32525
|
-
|
|
32791
|
+
fs40.mkdirSync(path45.dirname(settingsPath), { recursive: true });
|
|
32792
|
+
fs40.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
32526
32793
|
}
|
|
32527
32794
|
function installClaudeGuard(repoPath) {
|
|
32528
32795
|
const templatePath = resolveTemplateFile("claude-worktree-guard.sh.template");
|
|
32529
32796
|
if (!templatePath) {
|
|
32530
32797
|
throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
|
|
32531
32798
|
}
|
|
32532
|
-
const guardScript =
|
|
32533
|
-
|
|
32534
|
-
|
|
32535
|
-
|
|
32536
|
-
const settingsPath =
|
|
32799
|
+
const guardScript = path45.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
32800
|
+
fs40.mkdirSync(path45.dirname(guardScript), { recursive: true });
|
|
32801
|
+
fs40.copyFileSync(templatePath, guardScript);
|
|
32802
|
+
fs40.chmodSync(guardScript, 493);
|
|
32803
|
+
const settingsPath = path45.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
32537
32804
|
const settings = readSettings(settingsPath);
|
|
32538
32805
|
const hooks = settings.hooks ?? {};
|
|
32539
32806
|
const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
|
|
@@ -32547,15 +32814,15 @@ function installClaudeGuard(repoPath) {
|
|
|
32547
32814
|
}
|
|
32548
32815
|
function uninstallClaudeGuard(repoPath) {
|
|
32549
32816
|
let removed = false;
|
|
32550
|
-
const guardScript =
|
|
32551
|
-
if (
|
|
32552
|
-
|
|
32817
|
+
const guardScript = path45.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
32818
|
+
if (fs40.existsSync(guardScript)) {
|
|
32819
|
+
fs40.rmSync(guardScript);
|
|
32553
32820
|
removed = true;
|
|
32554
|
-
const parent =
|
|
32555
|
-
if (
|
|
32821
|
+
const parent = path45.dirname(guardScript);
|
|
32822
|
+
if (fs40.existsSync(parent) && fs40.readdirSync(parent).length === 0) fs40.rmdirSync(parent);
|
|
32556
32823
|
}
|
|
32557
|
-
const settingsPath =
|
|
32558
|
-
if (
|
|
32824
|
+
const settingsPath = path45.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
32825
|
+
if (fs40.existsSync(settingsPath)) {
|
|
32559
32826
|
const settings = readSettings(settingsPath);
|
|
32560
32827
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
32561
32828
|
if (preToolUse) {
|
|
@@ -32580,8 +32847,8 @@ function uninstallClaudeGuard(repoPath) {
|
|
|
32580
32847
|
return { removed };
|
|
32581
32848
|
}
|
|
32582
32849
|
function claudeGuardInstalled(repoPath) {
|
|
32583
|
-
const settingsPath =
|
|
32584
|
-
if (!
|
|
32850
|
+
const settingsPath = path45.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
32851
|
+
if (!fs40.existsSync(settingsPath)) return false;
|
|
32585
32852
|
try {
|
|
32586
32853
|
const settings = readSettings(settingsPath);
|
|
32587
32854
|
return (settings.hooks?.PreToolUse ?? []).some(isHarGuardEntry);
|
|
@@ -32597,7 +32864,7 @@ function repoOption(y2) {
|
|
|
32597
32864
|
function handleInstall2(argv) {
|
|
32598
32865
|
try {
|
|
32599
32866
|
if (argv.claude) {
|
|
32600
|
-
const result2 = installClaudeGuard(
|
|
32867
|
+
const result2 = installClaudeGuard(path46.resolve(argv.repo));
|
|
32601
32868
|
success("Claude Code worktree guard installed.");
|
|
32602
32869
|
info(`Guard script: ${result2.guardScript}`);
|
|
32603
32870
|
info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
|
|
@@ -32605,7 +32872,7 @@ function handleInstall2(argv) {
|
|
|
32605
32872
|
info("Commit both files so the guard travels with the repo.");
|
|
32606
32873
|
return;
|
|
32607
32874
|
}
|
|
32608
|
-
const result = installHooks({ repoPath:
|
|
32875
|
+
const result = installHooks({ repoPath: path46.resolve(argv.repo), force: argv.force });
|
|
32609
32876
|
success(`Commit gate installed in ${result.hooksDir}`);
|
|
32610
32877
|
info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
|
|
32611
32878
|
info("Commits of unverified change batches will be blocked in agent worktrees.");
|
|
@@ -32618,7 +32885,7 @@ function handleInstall2(argv) {
|
|
|
32618
32885
|
function handleUninstall(argv) {
|
|
32619
32886
|
try {
|
|
32620
32887
|
if (argv.claude) {
|
|
32621
|
-
const result2 = uninstallClaudeGuard(
|
|
32888
|
+
const result2 = uninstallClaudeGuard(path46.resolve(argv.repo));
|
|
32622
32889
|
if (result2.removed) {
|
|
32623
32890
|
success("Claude Code worktree guard removed.");
|
|
32624
32891
|
} else {
|
|
@@ -32626,7 +32893,7 @@ function handleUninstall(argv) {
|
|
|
32626
32893
|
}
|
|
32627
32894
|
return;
|
|
32628
32895
|
}
|
|
32629
|
-
const result = uninstallHooks(
|
|
32896
|
+
const result = uninstallHooks(path46.resolve(argv.repo));
|
|
32630
32897
|
if (result.removed) {
|
|
32631
32898
|
success(`Commit gate removed from ${result.hooksDir}`);
|
|
32632
32899
|
} else {
|
|
@@ -32639,7 +32906,7 @@ function handleUninstall(argv) {
|
|
|
32639
32906
|
}
|
|
32640
32907
|
function handleStatus2(argv) {
|
|
32641
32908
|
try {
|
|
32642
|
-
const status = getHooksStatus(
|
|
32909
|
+
const status = getHooksStatus(path46.resolve(argv.repo));
|
|
32643
32910
|
if (argv.json) {
|
|
32644
32911
|
process.stdout.write(`${JSON.stringify(status, null, 2)}
|
|
32645
32912
|
`);
|
|
@@ -32657,7 +32924,7 @@ function handleStatus2(argv) {
|
|
|
32657
32924
|
);
|
|
32658
32925
|
info(`Effective: ${status.effectiveMode} (in this checkout)`);
|
|
32659
32926
|
info(
|
|
32660
|
-
`Claude guard: ${claudeGuardInstalled(
|
|
32927
|
+
`Claude guard: ${claudeGuardInstalled(path46.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
|
|
32661
32928
|
);
|
|
32662
32929
|
} catch (err) {
|
|
32663
32930
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -32918,10 +33185,10 @@ function assignProp(target, prop, value) {
|
|
|
32918
33185
|
configurable: true
|
|
32919
33186
|
});
|
|
32920
33187
|
}
|
|
32921
|
-
function getElementAtPath(obj,
|
|
32922
|
-
if (!
|
|
33188
|
+
function getElementAtPath(obj, path49) {
|
|
33189
|
+
if (!path49)
|
|
32923
33190
|
return obj;
|
|
32924
|
-
return
|
|
33191
|
+
return path49.reduce((acc, key) => acc?.[key], obj);
|
|
32925
33192
|
}
|
|
32926
33193
|
function promiseAllObject(promisesObj) {
|
|
32927
33194
|
const keys = Object.keys(promisesObj);
|
|
@@ -33241,11 +33508,11 @@ function aborted(x2, startIndex = 0) {
|
|
|
33241
33508
|
}
|
|
33242
33509
|
return false;
|
|
33243
33510
|
}
|
|
33244
|
-
function prefixIssues(
|
|
33511
|
+
function prefixIssues(path49, issues) {
|
|
33245
33512
|
return issues.map((iss) => {
|
|
33246
33513
|
var _a3;
|
|
33247
33514
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
33248
|
-
iss.path.unshift(
|
|
33515
|
+
iss.path.unshift(path49);
|
|
33249
33516
|
return iss;
|
|
33250
33517
|
});
|
|
33251
33518
|
}
|
|
@@ -38568,7 +38835,7 @@ var Protocol = class {
|
|
|
38568
38835
|
return;
|
|
38569
38836
|
}
|
|
38570
38837
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
38571
|
-
await new Promise((
|
|
38838
|
+
await new Promise((resolve34) => setTimeout(resolve34, pollInterval));
|
|
38572
38839
|
options?.signal?.throwIfAborted();
|
|
38573
38840
|
}
|
|
38574
38841
|
} catch (error3) {
|
|
@@ -38585,7 +38852,7 @@ var Protocol = class {
|
|
|
38585
38852
|
*/
|
|
38586
38853
|
request(request, resultSchema, options) {
|
|
38587
38854
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
38588
|
-
return new Promise((
|
|
38855
|
+
return new Promise((resolve34, reject) => {
|
|
38589
38856
|
const earlyReject = (error3) => {
|
|
38590
38857
|
reject(error3);
|
|
38591
38858
|
};
|
|
@@ -38663,7 +38930,7 @@ var Protocol = class {
|
|
|
38663
38930
|
if (!parseResult.success) {
|
|
38664
38931
|
reject(parseResult.error);
|
|
38665
38932
|
} else {
|
|
38666
|
-
|
|
38933
|
+
resolve34(parseResult.data);
|
|
38667
38934
|
}
|
|
38668
38935
|
} catch (error3) {
|
|
38669
38936
|
reject(error3);
|
|
@@ -38924,12 +39191,12 @@ var Protocol = class {
|
|
|
38924
39191
|
}
|
|
38925
39192
|
} catch {
|
|
38926
39193
|
}
|
|
38927
|
-
return new Promise((
|
|
39194
|
+
return new Promise((resolve34, reject) => {
|
|
38928
39195
|
if (signal.aborted) {
|
|
38929
39196
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
38930
39197
|
return;
|
|
38931
39198
|
}
|
|
38932
|
-
const timeoutId = setTimeout(
|
|
39199
|
+
const timeoutId = setTimeout(resolve34, interval);
|
|
38933
39200
|
signal.addEventListener("abort", () => {
|
|
38934
39201
|
clearTimeout(timeoutId);
|
|
38935
39202
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -39719,7 +39986,7 @@ var Server = class extends Protocol {
|
|
|
39719
39986
|
};
|
|
39720
39987
|
|
|
39721
39988
|
// src/mcp/server.ts
|
|
39722
|
-
var
|
|
39989
|
+
var path47 = __toESM(require("path"));
|
|
39723
39990
|
|
|
39724
39991
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
39725
39992
|
var import_node_process2 = __toESM(require("node:process"), 1);
|
|
@@ -39802,12 +40069,12 @@ var StdioServerTransport = class {
|
|
|
39802
40069
|
this.onclose?.();
|
|
39803
40070
|
}
|
|
39804
40071
|
send(message) {
|
|
39805
|
-
return new Promise((
|
|
40072
|
+
return new Promise((resolve34) => {
|
|
39806
40073
|
const json = serializeMessage(message);
|
|
39807
40074
|
if (this._stdout.write(json)) {
|
|
39808
|
-
|
|
40075
|
+
resolve34();
|
|
39809
40076
|
} else {
|
|
39810
|
-
this._stdout.once("drain",
|
|
40077
|
+
this._stdout.once("drain", resolve34);
|
|
39811
40078
|
}
|
|
39812
40079
|
});
|
|
39813
40080
|
}
|
|
@@ -39890,10 +40157,7 @@ var LaunchEnvironmentInputSchema = external_exports.object({
|
|
|
39890
40157
|
force: external_exports.boolean().default(false).describe(
|
|
39891
40158
|
"Discard uncommitted changes in a dirty occupied worktree. Requires confirmReplace=true and explicit user approval \u2014 never set autonomously."
|
|
39892
40159
|
),
|
|
39893
|
-
resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree.")
|
|
39894
|
-
purpose: external_exports.string().optional().describe(
|
|
39895
|
-
"Optional session label stored in the slot registry (shown in status and occupied-slot warnings)."
|
|
39896
|
-
)
|
|
40160
|
+
resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree.")
|
|
39897
40161
|
});
|
|
39898
40162
|
var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
|
|
39899
40163
|
previewUrls: external_exports.record(external_exports.string()).optional(),
|
|
@@ -39907,8 +40171,7 @@ var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
|
|
|
39907
40171
|
worktreePath: external_exports.string().optional(),
|
|
39908
40172
|
branch: external_exports.string().optional(),
|
|
39909
40173
|
dirty: external_exports.boolean().optional(),
|
|
39910
|
-
sessionCreatedAt: external_exports.string().optional()
|
|
39911
|
-
purpose: external_exports.string().optional()
|
|
40174
|
+
sessionCreatedAt: external_exports.string().optional()
|
|
39912
40175
|
}).optional()
|
|
39913
40176
|
});
|
|
39914
40177
|
var PreflightEnvironmentInputSchema = external_exports.object({
|
|
@@ -40033,10 +40296,6 @@ var HAR_MCP_TOOLS = [
|
|
|
40033
40296
|
resume: {
|
|
40034
40297
|
type: "boolean",
|
|
40035
40298
|
description: "Resume a failed or partial launch (status failed/starting) without --replace. Preserves worktree and env."
|
|
40036
|
-
},
|
|
40037
|
-
purpose: {
|
|
40038
|
-
type: "string",
|
|
40039
|
-
description: "Optional session label stored in the slot registry (shown in status and occupied-slot warnings)."
|
|
40040
40299
|
}
|
|
40041
40300
|
},
|
|
40042
40301
|
["agentId"]
|
|
@@ -40220,7 +40479,6 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
40220
40479
|
confirmReplace: input.confirmReplace,
|
|
40221
40480
|
force: input.force,
|
|
40222
40481
|
resume: input.resume,
|
|
40223
|
-
purpose: input.purpose,
|
|
40224
40482
|
capture: true
|
|
40225
40483
|
});
|
|
40226
40484
|
const parsed = LaunchEnvironmentOutputSchema.parse(result);
|
|
@@ -40360,7 +40618,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
40360
40618
|
const input = ControlUpInputSchema.parse({ ...args, repo });
|
|
40361
40619
|
const result = await startControlAndSync({
|
|
40362
40620
|
detach: input.detach,
|
|
40363
|
-
cwd:
|
|
40621
|
+
cwd: path47.resolve(input.repo)
|
|
40364
40622
|
});
|
|
40365
40623
|
if (result.code !== 0) {
|
|
40366
40624
|
return {
|
|
@@ -40423,8 +40681,10 @@ var mcpCommand = {
|
|
|
40423
40681
|
};
|
|
40424
40682
|
|
|
40425
40683
|
// src/cli/commands/telemetry.ts
|
|
40426
|
-
var
|
|
40427
|
-
|
|
40684
|
+
var path48 = __toESM(require("path"));
|
|
40685
|
+
init_control_config();
|
|
40686
|
+
init_otel_hooks();
|
|
40687
|
+
init_telemetry_config();
|
|
40428
40688
|
function printSignals() {
|
|
40429
40689
|
info("Collected when enabled (local Mission Control only):");
|
|
40430
40690
|
for (const signal of TELEMETRY_SIGNALS) {
|
|
@@ -40448,6 +40708,8 @@ async function handleStatus3(argv) {
|
|
|
40448
40708
|
controlApiUrl: apiUrl,
|
|
40449
40709
|
controlReachable: reachable,
|
|
40450
40710
|
otelEndpoint: `${apiUrl.replace(/\/$/, "")}/api/otel`,
|
|
40711
|
+
otelHooksHome: getOtelHooksHome(),
|
|
40712
|
+
otelHooksConfig: getOtelHooksConfigPath(),
|
|
40451
40713
|
signalDescriptions: [...TELEMETRY_SIGNALS]
|
|
40452
40714
|
};
|
|
40453
40715
|
if (argv.json) {
|
|
@@ -40463,25 +40725,29 @@ async function handleStatus3(argv) {
|
|
|
40463
40725
|
);
|
|
40464
40726
|
info(`Mission Control: ${apiUrl} (${reachable ? "reachable" : "not reachable"})`);
|
|
40465
40727
|
info(`OTLP endpoint: ${payload.otelEndpoint}`);
|
|
40728
|
+
info(`Hooks home: ${payload.otelHooksHome}`);
|
|
40466
40729
|
printSignals();
|
|
40467
40730
|
}
|
|
40468
40731
|
async function handleOn(argv) {
|
|
40469
40732
|
header("har telemetry on");
|
|
40470
40733
|
const preference = writeTelemetryPreference(true, {
|
|
40471
40734
|
prompts: argv.prompts === true ? true : void 0,
|
|
40472
|
-
traces:
|
|
40735
|
+
traces: true
|
|
40473
40736
|
});
|
|
40474
|
-
success("Telemetry enabled
|
|
40737
|
+
success("Telemetry enabled. Cursor / Claude / Codex export via opentelemetry-hooks \u2192 Mission Control.");
|
|
40475
40738
|
info(
|
|
40476
40739
|
`Signals: metrics=${preference.signals.metrics} logs=${preference.signals.logs} prompts=${preference.signals.prompts} traces=${preference.signals.traces}`
|
|
40477
40740
|
);
|
|
40478
40741
|
if (preference.signals.prompts) {
|
|
40479
|
-
warn("Prompt
|
|
40742
|
+
warn("Prompt text will leave the agent machine for local Mission Control (also used as session purpose).");
|
|
40480
40743
|
}
|
|
40481
40744
|
printSignals();
|
|
40482
40745
|
const result = await ensureTelemetryInfrastructure({ startIfNeeded: true });
|
|
40483
40746
|
if (result.message) success(result.message);
|
|
40484
40747
|
if (result.warning) warn(result.warning);
|
|
40748
|
+
const hooks = ensureOtelHooks({ setupAgents: true });
|
|
40749
|
+
if (hooks.message) success(hooks.message);
|
|
40750
|
+
if (hooks.warning) warn(hooks.warning);
|
|
40485
40751
|
if (result.otelReady) {
|
|
40486
40752
|
info(`OTLP ingest: ${result.apiUrl.replace(/\/$/, "")}/api/otel`);
|
|
40487
40753
|
info("Usage appears under Mission Control \u2192 Worktrees / Usage. Disable: har telemetry off");
|
|
@@ -40490,44 +40756,48 @@ async function handleOn(argv) {
|
|
|
40490
40756
|
async function handleOff() {
|
|
40491
40757
|
header("har telemetry off");
|
|
40492
40758
|
writeTelemetryPreference(false);
|
|
40759
|
+
try {
|
|
40760
|
+
disableOtelHooksExport();
|
|
40761
|
+
} catch (err) {
|
|
40762
|
+
warn(`Could not refresh hooks config: ${err instanceof Error ? err.message : String(err)}`);
|
|
40763
|
+
}
|
|
40493
40764
|
success("Telemetry disabled.");
|
|
40494
|
-
info("
|
|
40495
|
-
info("
|
|
40765
|
+
info("Hooks stay registered but OTLP export is cleared in ~/.har/otel-hooks/otel_config.json.");
|
|
40766
|
+
info("Mission Control will not auto-start. Existing usage rows are kept.");
|
|
40496
40767
|
}
|
|
40497
40768
|
async function handleWriteEnv(argv) {
|
|
40498
|
-
const repoPath =
|
|
40769
|
+
const repoPath = path48.resolve(argv.repo);
|
|
40499
40770
|
const harnessRoot = resolveHarnessRoot(repoPath);
|
|
40500
40771
|
const session = readSlotRegistry(harnessRoot, argv.agentId);
|
|
40501
40772
|
const workDir = argv.workDir ?? session?.workDir ?? repoPath;
|
|
40502
40773
|
const branch = argv.branch ?? session?.branch;
|
|
40503
40774
|
const suffix = argv.suffix ?? session?.suffix;
|
|
40504
|
-
const purpose = argv.purpose ?? session?.purpose;
|
|
40505
40775
|
const sessionKey = argv.sessionKey ?? buildSessionKey({
|
|
40506
40776
|
branch,
|
|
40507
40777
|
agentId: argv.agentId,
|
|
40508
40778
|
suffix,
|
|
40509
40779
|
createdAt: session?.createdAt
|
|
40510
40780
|
});
|
|
40511
|
-
const envFile = argv.envFile ??
|
|
40512
|
-
let otelReady = argv.otelReady;
|
|
40513
|
-
if (otelReady === void 0 && isTelemetryEnabled()) {
|
|
40514
|
-
const ensured = await ensureTelemetryInfrastructure({ startIfNeeded: false });
|
|
40515
|
-
otelReady = ensured.otelReady;
|
|
40516
|
-
}
|
|
40781
|
+
const envFile = argv.envFile ?? path48.join(workDir, `.env.agent.${argv.agentId}`);
|
|
40517
40782
|
const attrs = {
|
|
40518
40783
|
sessionKey,
|
|
40519
40784
|
agentId: argv.agentId,
|
|
40520
40785
|
repoPath,
|
|
40521
40786
|
workDir,
|
|
40522
40787
|
branch,
|
|
40523
|
-
suffix
|
|
40524
|
-
purpose
|
|
40788
|
+
suffix
|
|
40525
40789
|
};
|
|
40526
|
-
appendTelemetryEnvToFile(envFile, attrs
|
|
40527
|
-
|
|
40790
|
+
appendTelemetryEnvToFile(envFile, attrs);
|
|
40791
|
+
if (isTelemetryEnabled()) {
|
|
40792
|
+
ensureOtelHooks({
|
|
40793
|
+
setupAgents: false,
|
|
40794
|
+
resourceAttributes: buildOtelResourceAttributes(attrs)
|
|
40795
|
+
});
|
|
40796
|
+
}
|
|
40797
|
+
success(`Wrote session attribution to ${envFile}`);
|
|
40528
40798
|
}
|
|
40529
40799
|
function handlePrintEnv(argv) {
|
|
40530
|
-
const repoPath =
|
|
40800
|
+
const repoPath = path48.resolve(argv.repo);
|
|
40531
40801
|
const workDir = argv.workDir ?? repoPath;
|
|
40532
40802
|
const sessionKey = buildSessionKey({
|
|
40533
40803
|
branch: argv.branch,
|
|
@@ -40535,55 +40805,38 @@ function handlePrintEnv(argv) {
|
|
|
40535
40805
|
suffix: argv.suffix
|
|
40536
40806
|
});
|
|
40537
40807
|
process.stdout.write(
|
|
40538
|
-
buildTelemetryEnvBlock(
|
|
40539
|
-
|
|
40540
|
-
|
|
40541
|
-
|
|
40542
|
-
|
|
40543
|
-
|
|
40544
|
-
|
|
40545
|
-
|
|
40546
|
-
},
|
|
40547
|
-
{ otelReady: argv.otelReady && isTelemetryEnabled() }
|
|
40548
|
-
)
|
|
40808
|
+
buildTelemetryEnvBlock({
|
|
40809
|
+
sessionKey,
|
|
40810
|
+
agentId: argv.agentId,
|
|
40811
|
+
repoPath,
|
|
40812
|
+
workDir,
|
|
40813
|
+
branch: argv.branch,
|
|
40814
|
+
suffix: argv.suffix
|
|
40815
|
+
})
|
|
40549
40816
|
);
|
|
40550
40817
|
}
|
|
40551
|
-
function
|
|
40552
|
-
|
|
40553
|
-
|
|
40554
|
-
|
|
40555
|
-
|
|
40556
|
-
|
|
40557
|
-
const
|
|
40558
|
-
|
|
40559
|
-
|
|
40560
|
-
|
|
40561
|
-
|
|
40562
|
-
|
|
40563
|
-
|
|
40564
|
-
|
|
40565
|
-
|
|
40566
|
-
|
|
40567
|
-
|
|
40568
|
-
workDir,
|
|
40569
|
-
branch,
|
|
40570
|
-
suffix,
|
|
40571
|
-
purpose: session?.purpose
|
|
40572
|
-
});
|
|
40573
|
-
if (argv.write) {
|
|
40574
|
-
const outDir = path47.join(harnessRoot, ".har", "telemetry");
|
|
40575
|
-
fs40.mkdirSync(outDir, { recursive: true });
|
|
40576
|
-
const outPath = path47.join(outDir, "codex.otel.toml.snippet");
|
|
40577
|
-
fs40.writeFileSync(outPath, snippet);
|
|
40578
|
-
success(`Wrote ${outPath}`);
|
|
40579
|
-
info("Merge the [otel] table into ~/.codex/config.toml manually.");
|
|
40580
|
-
return;
|
|
40818
|
+
async function handleInstallHooks() {
|
|
40819
|
+
header("har telemetry install-hooks");
|
|
40820
|
+
if (!isTelemetryEnabled()) {
|
|
40821
|
+
warn("Telemetry is off \u2014 enabling preference so hooks can export.");
|
|
40822
|
+
writeTelemetryPreference(true, { traces: true });
|
|
40823
|
+
}
|
|
40824
|
+
const result = await ensureTelemetryInfrastructure({ startIfNeeded: true });
|
|
40825
|
+
if (result.message) success(result.message);
|
|
40826
|
+
if (result.warning) warn(result.warning);
|
|
40827
|
+
const hooks = ensureOtelHooks({ setupAgents: true });
|
|
40828
|
+
if (hooks.ok) {
|
|
40829
|
+
success(hooks.message ?? "opentelemetry-hooks installed and agents registered");
|
|
40830
|
+
info(`Config: ${hooks.configPath}`);
|
|
40831
|
+
info(`Wrapper: ${hooks.wrapperPath}`);
|
|
40832
|
+
} else {
|
|
40833
|
+
error(hooks.warning ?? "Failed to install opentelemetry-hooks");
|
|
40834
|
+
process.exitCode = 1;
|
|
40581
40835
|
}
|
|
40582
|
-
process.stdout.write(snippet);
|
|
40583
40836
|
}
|
|
40584
40837
|
var telemetryCommand = {
|
|
40585
40838
|
command: "telemetry <subcommand>",
|
|
40586
|
-
describe: "Agent usage telemetry (Claude
|
|
40839
|
+
describe: "Agent usage telemetry (Cursor / Claude / Codex via opentelemetry-hooks \u2192 Mission Control)",
|
|
40587
40840
|
builder: (yargs) => yargs.command(
|
|
40588
40841
|
"status",
|
|
40589
40842
|
"Show telemetry preference and Mission Control reachability",
|
|
@@ -40593,34 +40846,40 @@ var telemetryCommand = {
|
|
|
40593
40846
|
}
|
|
40594
40847
|
).command(
|
|
40595
40848
|
"on",
|
|
40596
|
-
"Enable telemetry
|
|
40849
|
+
"Enable telemetry, ensure Mission Control, install/configure opentelemetry-hooks",
|
|
40597
40850
|
(y2) => y2.option("prompts", {
|
|
40598
40851
|
type: "boolean",
|
|
40599
40852
|
default: false,
|
|
40600
|
-
describe: "Opt in to shipping user
|
|
40601
|
-
}).option("traces", {
|
|
40602
|
-
type: "boolean",
|
|
40603
|
-
default: false,
|
|
40604
|
-
describe: "Opt in to thin OTEL traces ingest (Claude beta)"
|
|
40853
|
+
describe: "Opt in to shipping user prompt text (also fills Mission Control purpose)"
|
|
40605
40854
|
}),
|
|
40606
40855
|
(argv) => {
|
|
40607
40856
|
void handleOn({
|
|
40608
|
-
prompts: argv.prompts
|
|
40609
|
-
traces: argv.traces
|
|
40857
|
+
prompts: argv.prompts
|
|
40610
40858
|
});
|
|
40611
40859
|
}
|
|
40612
40860
|
).command(
|
|
40613
40861
|
"off",
|
|
40614
|
-
"Disable telemetry (
|
|
40862
|
+
"Disable telemetry (clear hooks OTLP endpoint, no MC auto-start)",
|
|
40615
40863
|
() => {
|
|
40616
40864
|
},
|
|
40617
40865
|
() => {
|
|
40618
40866
|
void handleOff();
|
|
40619
40867
|
}
|
|
40868
|
+
).command(
|
|
40869
|
+
"install-hooks",
|
|
40870
|
+
"Install opentelemetry-hooks and register Cursor / Claude / Codex",
|
|
40871
|
+
() => {
|
|
40872
|
+
},
|
|
40873
|
+
() => {
|
|
40874
|
+
void handleInstallHooks().catch((err) => {
|
|
40875
|
+
error(err instanceof Error ? err.message : String(err));
|
|
40876
|
+
process.exitCode = 1;
|
|
40877
|
+
});
|
|
40878
|
+
}
|
|
40620
40879
|
).command(
|
|
40621
40880
|
"write-env",
|
|
40622
|
-
"Append session
|
|
40623
|
-
(y2) => y2.option("agent-id", { type: "number", demandOption: true }).option("repo", { type: "string", default: "." }).option("env-file", { type: "string" }).option("work-dir", { type: "string" }).option("branch", { type: "string" }).option("suffix", { type: "string" }).option("
|
|
40881
|
+
"Append HAR session attribution to .env.agent.<id> and refresh hooks config",
|
|
40882
|
+
(y2) => y2.option("agent-id", { type: "number", demandOption: true }).option("repo", { type: "string", default: "." }).option("env-file", { type: "string" }).option("work-dir", { type: "string" }).option("branch", { type: "string" }).option("suffix", { type: "string" }).option("session-key", { type: "string" }),
|
|
40624
40883
|
(argv) => handleWriteEnv({
|
|
40625
40884
|
agentId: argv["agent-id"],
|
|
40626
40885
|
repo: argv.repo,
|
|
@@ -40628,42 +40887,23 @@ var telemetryCommand = {
|
|
|
40628
40887
|
workDir: argv["work-dir"],
|
|
40629
40888
|
branch: argv.branch,
|
|
40630
40889
|
suffix: argv.suffix,
|
|
40631
|
-
|
|
40632
|
-
sessionKey: argv["session-key"],
|
|
40633
|
-
otelReady: argv["otel-ready"]
|
|
40890
|
+
sessionKey: argv["session-key"]
|
|
40634
40891
|
}).catch((err) => {
|
|
40635
40892
|
error(err instanceof Error ? err.message : String(err));
|
|
40636
40893
|
process.exitCode = 1;
|
|
40637
40894
|
})
|
|
40638
40895
|
).command(
|
|
40639
40896
|
"print-env",
|
|
40640
|
-
"Print
|
|
40641
|
-
(y2) => y2.option("agent-id", { type: "number", demandOption: true }).option("repo", { type: "string", default: "." }).option("work-dir", { type: "string" }).option("branch", { type: "string" }).option("suffix", { type: "string" })
|
|
40897
|
+
"Print session attribution env block to stdout",
|
|
40898
|
+
(y2) => y2.option("agent-id", { type: "number", demandOption: true }).option("repo", { type: "string", default: "." }).option("work-dir", { type: "string" }).option("branch", { type: "string" }).option("suffix", { type: "string" }),
|
|
40642
40899
|
(argv) => handlePrintEnv({
|
|
40643
40900
|
agentId: argv["agent-id"],
|
|
40644
40901
|
repo: argv.repo,
|
|
40645
40902
|
workDir: argv["work-dir"],
|
|
40646
40903
|
branch: argv.branch,
|
|
40647
|
-
suffix: argv.suffix
|
|
40648
|
-
otelReady: argv["otel-ready"]
|
|
40649
|
-
})
|
|
40650
|
-
).command(
|
|
40651
|
-
"codex-snippet",
|
|
40652
|
-
"Print or write a Codex [otel] config snippet",
|
|
40653
|
-
(y2) => y2.option("agent-id", { type: "number", demandOption: true }).option("repo", { type: "string", default: "." }).option("work-dir", { type: "string" }).option("branch", { type: "string" }).option("suffix", { type: "string" }).option("write", {
|
|
40654
|
-
type: "boolean",
|
|
40655
|
-
default: false,
|
|
40656
|
-
describe: "Write to .har/telemetry/codex.otel.toml.snippet"
|
|
40657
|
-
}),
|
|
40658
|
-
(argv) => handleCodexSnippet({
|
|
40659
|
-
agentId: argv["agent-id"],
|
|
40660
|
-
repo: argv.repo,
|
|
40661
|
-
workDir: argv["work-dir"],
|
|
40662
|
-
branch: argv.branch,
|
|
40663
|
-
suffix: argv.suffix,
|
|
40664
|
-
write: argv.write
|
|
40904
|
+
suffix: argv.suffix
|
|
40665
40905
|
})
|
|
40666
|
-
).demandCommand(1, "Please specify a subcommand: status, on, off, write-env, print-env
|
|
40906
|
+
).demandCommand(1, "Please specify a subcommand: status, on, off, install-hooks, write-env, print-env"),
|
|
40667
40907
|
handler: () => {
|
|
40668
40908
|
}
|
|
40669
40909
|
};
|