@osfactory/har 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +305 -74
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ cd MyApp && har env init --profile ios
|
|
|
69
69
|
har env add-stage rocketsim # optional: UI flow validation on the simulator
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
After init, paste the
|
|
72
|
+
After init, paste the adaptation prompt into your coding agent (interactive terminals offer a clipboard copy; also saved to `.har/ADAPT-PROMPT.md`) to tailor scripts to your stack. For built-in Claude adaptation: `har env init --auto` (requires `ANTHROPIC_API_KEY`).
|
|
73
73
|
|
|
74
74
|
Optional stage templates depend on the profile: `har env add-stage playwright` for browser E2E on web apps, `har env add-stage rocketsim` for simulator user-flow checks on iOS.
|
|
75
75
|
|
package/dist/index.js
CHANGED
|
@@ -6449,6 +6449,7 @@ function readPortalCredentials() {
|
|
|
6449
6449
|
portalUrl: parsed.portalUrl,
|
|
6450
6450
|
token: parsed.token,
|
|
6451
6451
|
workspace: parsed.workspace,
|
|
6452
|
+
email: parsed.email,
|
|
6452
6453
|
createdAt: parsed.createdAt ?? ""
|
|
6453
6454
|
};
|
|
6454
6455
|
} catch {
|
|
@@ -6677,22 +6678,22 @@ exec "${otelHookCommand}" "$@"
|
|
|
6677
6678
|
}
|
|
6678
6679
|
return wrapperPath;
|
|
6679
6680
|
}
|
|
6680
|
-
function
|
|
6681
|
-
const result = (0,
|
|
6681
|
+
function commandExists2(command2) {
|
|
6682
|
+
const result = (0, import_child_process10.spawnSync)("sh", ["-c", `command -v ${JSON.stringify(command2)}`], {
|
|
6682
6683
|
encoding: "utf8"
|
|
6683
6684
|
});
|
|
6684
6685
|
return result.status === 0 && Boolean(result.stdout?.trim());
|
|
6685
6686
|
}
|
|
6686
6687
|
function resolveOtelHookCommand() {
|
|
6687
|
-
if (
|
|
6688
|
-
const which = (0,
|
|
6688
|
+
if (commandExists2("otel-hook")) {
|
|
6689
|
+
const which = (0, import_child_process10.spawnSync)("sh", ["-c", "command -v otel-hook"], { encoding: "utf8" });
|
|
6689
6690
|
return which.stdout?.trim() || "otel-hook";
|
|
6690
6691
|
}
|
|
6691
6692
|
return null;
|
|
6692
6693
|
}
|
|
6693
6694
|
function tryInstallPackage() {
|
|
6694
|
-
if (
|
|
6695
|
-
const result = (0,
|
|
6695
|
+
if (commandExists2("uv")) {
|
|
6696
|
+
const result = (0, import_child_process10.spawnSync)(
|
|
6696
6697
|
"uv",
|
|
6697
6698
|
["tool", "install", "--force", OTEL_HOOKS_PACKAGE],
|
|
6698
6699
|
{ encoding: "utf8", timeout: 18e4 }
|
|
@@ -6701,8 +6702,8 @@ function tryInstallPackage() {
|
|
|
6701
6702
|
return { ok: true, detail: `uv tool install ${OTEL_HOOKS_PACKAGE}` };
|
|
6702
6703
|
}
|
|
6703
6704
|
}
|
|
6704
|
-
if (
|
|
6705
|
-
const result = (0,
|
|
6705
|
+
if (commandExists2("pipx")) {
|
|
6706
|
+
const result = (0, import_child_process10.spawnSync)("pipx", ["install", "--force", OTEL_HOOKS_PACKAGE], {
|
|
6706
6707
|
encoding: "utf8",
|
|
6707
6708
|
timeout: 18e4
|
|
6708
6709
|
});
|
|
@@ -6714,9 +6715,9 @@ function tryInstallPackage() {
|
|
|
6714
6715
|
detail: `pipx install failed: ${(result.stderr || result.stdout || "").trim().slice(0, 400)}`
|
|
6715
6716
|
};
|
|
6716
6717
|
}
|
|
6717
|
-
if (
|
|
6718
|
-
const pip =
|
|
6719
|
-
const result = (0,
|
|
6718
|
+
if (commandExists2("pip3") || commandExists2("pip")) {
|
|
6719
|
+
const pip = commandExists2("pip3") ? "pip3" : "pip";
|
|
6720
|
+
const result = (0, import_child_process10.spawnSync)(
|
|
6720
6721
|
pip,
|
|
6721
6722
|
["install", "--user", OTEL_HOOKS_PACKAGE],
|
|
6722
6723
|
{ encoding: "utf8", timeout: 18e4 }
|
|
@@ -6735,7 +6736,7 @@ function tryInstallPackage() {
|
|
|
6735
6736
|
};
|
|
6736
6737
|
}
|
|
6737
6738
|
function runSetupAgent(agent, otelHookCommand, hooksHome) {
|
|
6738
|
-
const result = (0,
|
|
6739
|
+
const result = (0, import_child_process10.spawnSync)(otelHookCommand, ["setup", "--agent", agent], {
|
|
6739
6740
|
encoding: "utf8",
|
|
6740
6741
|
env: {
|
|
6741
6742
|
...process.env,
|
|
@@ -6885,11 +6886,11 @@ function ensureOtelHooks(options) {
|
|
|
6885
6886
|
function disableOtelHooksExport() {
|
|
6886
6887
|
return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
|
|
6887
6888
|
}
|
|
6888
|
-
var
|
|
6889
|
+
var import_child_process10, fs41, os13, path43, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_AGENTS;
|
|
6889
6890
|
var init_otel_hooks = __esm({
|
|
6890
6891
|
"src/core/otel-hooks.ts"() {
|
|
6891
6892
|
"use strict";
|
|
6892
|
-
|
|
6893
|
+
import_child_process10 = require("child_process");
|
|
6893
6894
|
fs41 = __toESM(require("fs"));
|
|
6894
6895
|
os13 = __toESM(require("os"));
|
|
6895
6896
|
path43 = __toESM(require("path"));
|
|
@@ -49738,6 +49739,81 @@ function addCustomStage(repoPath, options) {
|
|
|
49738
49739
|
// src/harness/adaptation-prompt.ts
|
|
49739
49740
|
var fs22 = __toESM(require("fs"));
|
|
49740
49741
|
var path21 = __toESM(require("path"));
|
|
49742
|
+
var readline4 = __toESM(require("readline"));
|
|
49743
|
+
|
|
49744
|
+
// src/utils/clipboard.ts
|
|
49745
|
+
var import_child_process2 = require("child_process");
|
|
49746
|
+
function commandExists(command2) {
|
|
49747
|
+
const probe = process.platform === "win32" ? (0, import_child_process2.spawnSync)("where", [command2], { encoding: "utf8", stdio: ["ignore", "ignore", "ignore"] }) : (0, import_child_process2.spawnSync)("which", [command2], { encoding: "utf8", stdio: ["ignore", "ignore", "ignore"] });
|
|
49748
|
+
return probe.status === 0;
|
|
49749
|
+
}
|
|
49750
|
+
function tryPipeCommand(command2, args, text) {
|
|
49751
|
+
const result = (0, import_child_process2.spawnSync)(command2, args, {
|
|
49752
|
+
input: text,
|
|
49753
|
+
encoding: "utf8",
|
|
49754
|
+
stdio: ["pipe", "ignore", "ignore"]
|
|
49755
|
+
});
|
|
49756
|
+
return result.status === 0 && !result.error;
|
|
49757
|
+
}
|
|
49758
|
+
function writeOsc52Clipboard(text, stream = process.stderr) {
|
|
49759
|
+
if (!("isTTY" in stream) || !stream.isTTY) return false;
|
|
49760
|
+
if (Buffer.byteLength(text, "utf8") > 2e5) return false;
|
|
49761
|
+
const b64 = Buffer.from(text, "utf8").toString("base64");
|
|
49762
|
+
stream.write(`\x1B]52;c;${b64}\x07`);
|
|
49763
|
+
return true;
|
|
49764
|
+
}
|
|
49765
|
+
function copyViaPlatformTools(text) {
|
|
49766
|
+
if (process.platform === "darwin" && commandExists("pbcopy")) {
|
|
49767
|
+
if (tryPipeCommand("pbcopy", [], text)) return { ok: true, method: "pbcopy" };
|
|
49768
|
+
}
|
|
49769
|
+
if (process.platform === "win32") {
|
|
49770
|
+
if (commandExists("powershell")) {
|
|
49771
|
+
const result = (0, import_child_process2.spawnSync)(
|
|
49772
|
+
"powershell",
|
|
49773
|
+
[
|
|
49774
|
+
"-NoProfile",
|
|
49775
|
+
"-NonInteractive",
|
|
49776
|
+
"-Command",
|
|
49777
|
+
"$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new(); Set-Clipboard -Value ([Console]::In.ReadToEnd())"
|
|
49778
|
+
],
|
|
49779
|
+
{
|
|
49780
|
+
input: text,
|
|
49781
|
+
encoding: "utf8",
|
|
49782
|
+
stdio: ["pipe", "ignore", "ignore"]
|
|
49783
|
+
}
|
|
49784
|
+
);
|
|
49785
|
+
if (result.status === 0 && !result.error) return { ok: true, method: "powershell" };
|
|
49786
|
+
}
|
|
49787
|
+
if (commandExists("clip") && tryPipeCommand("clip", [], text)) {
|
|
49788
|
+
return { ok: true, method: "clip" };
|
|
49789
|
+
}
|
|
49790
|
+
}
|
|
49791
|
+
if (process.platform === "linux" || process.platform === "freebsd" || process.platform === "openbsd") {
|
|
49792
|
+
if (commandExists("wl-copy") && tryPipeCommand("wl-copy", [], text)) {
|
|
49793
|
+
return { ok: true, method: "wl-copy" };
|
|
49794
|
+
}
|
|
49795
|
+
if (commandExists("xclip") && tryPipeCommand("xclip", ["-selection", "clipboard"], text)) {
|
|
49796
|
+
return { ok: true, method: "xclip" };
|
|
49797
|
+
}
|
|
49798
|
+
if (commandExists("xsel") && tryPipeCommand("xsel", ["--clipboard", "--input"], text)) {
|
|
49799
|
+
return { ok: true, method: "xsel" };
|
|
49800
|
+
}
|
|
49801
|
+
}
|
|
49802
|
+
return {
|
|
49803
|
+
ok: false,
|
|
49804
|
+
detail: "No system clipboard command available (pbcopy, wl-copy/xclip/xsel, or clip)"
|
|
49805
|
+
};
|
|
49806
|
+
}
|
|
49807
|
+
function copyTextToClipboard(text) {
|
|
49808
|
+
const platform = copyViaPlatformTools(text);
|
|
49809
|
+
if (platform.ok) return platform;
|
|
49810
|
+
if (writeOsc52Clipboard(text)) {
|
|
49811
|
+
return { ok: true, method: "osc52" };
|
|
49812
|
+
}
|
|
49813
|
+
return platform;
|
|
49814
|
+
}
|
|
49815
|
+
|
|
49816
|
+
// src/harness/adaptation-prompt.ts
|
|
49741
49817
|
var ADAPTATION_PROMPT_FILE = "ADAPT-PROMPT.md";
|
|
49742
49818
|
var PROFILE_HINTS = {
|
|
49743
49819
|
default: "Web app profile (SaaS/full-stack) \u2014 Docker Compose for shared infra (HARNESS_INFRA_SERVICES), PM2 for the primary application only, git worktree per agent slot by default. Launch provisions toolchain via harness.env (HARNESS_ECOSYSTEM, HARNESS_INSTALL_CMD) and writes paths to .env.agent.<id>. Identify the primary app agents modify; run supporting services shared.",
|
|
@@ -49788,11 +49864,47 @@ function printAdaptationPrompt(content) {
|
|
|
49788
49864
|
`);
|
|
49789
49865
|
process.stderr.write("\n");
|
|
49790
49866
|
}
|
|
49867
|
+
function askYesNo3(question) {
|
|
49868
|
+
const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
|
|
49869
|
+
return new Promise((resolve38) => {
|
|
49870
|
+
process.stderr.write(`${question} `);
|
|
49871
|
+
rl.once("line", (answer) => {
|
|
49872
|
+
rl.close();
|
|
49873
|
+
const trimmed = answer.trim();
|
|
49874
|
+
resolve38(trimmed === "" || /^y(es)?$/i.test(trimmed));
|
|
49875
|
+
});
|
|
49876
|
+
});
|
|
49877
|
+
}
|
|
49878
|
+
async function offerAdaptationPromptClipboard(content, options = {}) {
|
|
49879
|
+
const interactive = Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
49880
|
+
if (!interactive && !options.autoYes) {
|
|
49881
|
+
info("Prompt also saved to .har/ADAPT-PROMPT.md (open or copy from there)");
|
|
49882
|
+
return false;
|
|
49883
|
+
}
|
|
49884
|
+
let shouldCopy = options.autoYes === true;
|
|
49885
|
+
if (!shouldCopy && interactive) {
|
|
49886
|
+
shouldCopy = await askYesNo3("Copy adaptation prompt to clipboard for your coding agent? [Y/n]");
|
|
49887
|
+
}
|
|
49888
|
+
if (!shouldCopy) {
|
|
49889
|
+
info("Skipped clipboard copy \u2014 prompt is in .har/ADAPT-PROMPT.md");
|
|
49890
|
+
return false;
|
|
49891
|
+
}
|
|
49892
|
+
const result = copyTextToClipboard(content);
|
|
49893
|
+
if (result.ok) {
|
|
49894
|
+
success(
|
|
49895
|
+
result.method === "osc52" ? "Copied adaptation prompt to clipboard (terminal OSC 52) \u2014 paste into your coding agent" : "Copied adaptation prompt to clipboard \u2014 paste into your coding agent"
|
|
49896
|
+
);
|
|
49897
|
+
return true;
|
|
49898
|
+
}
|
|
49899
|
+
warn(`Could not copy to clipboard: ${result.detail}`);
|
|
49900
|
+
info("Open .har/ADAPT-PROMPT.md and paste that into your coding agent instead");
|
|
49901
|
+
return false;
|
|
49902
|
+
}
|
|
49791
49903
|
|
|
49792
49904
|
// src/harness/cursor-rule.ts
|
|
49793
49905
|
var fs23 = __toESM(require("fs"));
|
|
49794
49906
|
var path22 = __toESM(require("path"));
|
|
49795
|
-
var
|
|
49907
|
+
var readline5 = __toESM(require("readline"));
|
|
49796
49908
|
var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
|
|
49797
49909
|
function getCursorRulePath(repoPath) {
|
|
49798
49910
|
return path22.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
|
|
@@ -49842,10 +49954,10 @@ async function handleCursorRule(options) {
|
|
|
49842
49954
|
}
|
|
49843
49955
|
async function promptScaffoldCursorRule(exists) {
|
|
49844
49956
|
const action = exists ? "Update" : "Create";
|
|
49845
|
-
return
|
|
49957
|
+
return askYesNo4(`${action} ${CURSOR_RULE_RELATIVE_PATH}? [Y/n]`);
|
|
49846
49958
|
}
|
|
49847
|
-
async function
|
|
49848
|
-
const rl =
|
|
49959
|
+
async function askYesNo4(question) {
|
|
49960
|
+
const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
|
|
49849
49961
|
return new Promise((resolve38) => {
|
|
49850
49962
|
process.stderr.write(`${question} `);
|
|
49851
49963
|
rl.once("line", (answer) => {
|
|
@@ -50283,22 +50395,25 @@ function listRegisteredRepos() {
|
|
|
50283
50395
|
return kept;
|
|
50284
50396
|
}
|
|
50285
50397
|
|
|
50398
|
+
// src/core/control-sync.ts
|
|
50399
|
+
init_portal_credentials();
|
|
50400
|
+
|
|
50286
50401
|
// src/core/slot-status.ts
|
|
50287
50402
|
var fs33 = __toESM(require("fs"));
|
|
50288
50403
|
var os8 = __toESM(require("os"));
|
|
50289
50404
|
var path33 = __toESM(require("path"));
|
|
50290
|
-
var
|
|
50405
|
+
var import_child_process8 = require("child_process");
|
|
50291
50406
|
|
|
50292
50407
|
// src/core/runs.ts
|
|
50293
50408
|
var crypto2 = __toESM(require("crypto"));
|
|
50294
|
-
var
|
|
50409
|
+
var import_child_process3 = require("child_process");
|
|
50295
50410
|
var fs29 = __toESM(require("fs"));
|
|
50296
50411
|
var os6 = __toESM(require("os"));
|
|
50297
50412
|
var path28 = __toESM(require("path"));
|
|
50298
50413
|
var RUNS_DIR = "runs";
|
|
50299
50414
|
function gitCommonDir(cwd) {
|
|
50300
50415
|
try {
|
|
50301
|
-
const out = (0,
|
|
50416
|
+
const out = (0, import_child_process3.execSync)("git rev-parse --git-common-dir", {
|
|
50302
50417
|
cwd,
|
|
50303
50418
|
encoding: "utf8",
|
|
50304
50419
|
stdio: ["pipe", "pipe", "ignore"]
|
|
@@ -50315,7 +50430,7 @@ function sameGitCheckout(a2, b2) {
|
|
|
50315
50430
|
}
|
|
50316
50431
|
function gitPrefix(cwd) {
|
|
50317
50432
|
try {
|
|
50318
|
-
return (0,
|
|
50433
|
+
return (0, import_child_process3.execSync)("git rev-parse --show-prefix", {
|
|
50319
50434
|
cwd,
|
|
50320
50435
|
encoding: "utf8",
|
|
50321
50436
|
stdio: ["pipe", "pipe", "ignore"]
|
|
@@ -50484,13 +50599,13 @@ function listRuns(repoPath, filter2 = {}) {
|
|
|
50484
50599
|
var path32 = __toESM(require("path"));
|
|
50485
50600
|
|
|
50486
50601
|
// src/core/control-port.ts
|
|
50487
|
-
var
|
|
50602
|
+
var import_child_process5 = require("child_process");
|
|
50488
50603
|
var fs31 = __toESM(require("fs"));
|
|
50489
50604
|
var path30 = __toESM(require("path"));
|
|
50490
50605
|
init_control_config();
|
|
50491
50606
|
|
|
50492
50607
|
// src/core/slot-ports.ts
|
|
50493
|
-
var
|
|
50608
|
+
var import_child_process4 = require("child_process");
|
|
50494
50609
|
var fs30 = __toESM(require("fs"));
|
|
50495
50610
|
var path29 = __toESM(require("path"));
|
|
50496
50611
|
function portStep(env3) {
|
|
@@ -50504,7 +50619,7 @@ function slotPortLaneEnd(defaultPort, step) {
|
|
|
50504
50619
|
}
|
|
50505
50620
|
function isPortInUse(port, host = "127.0.0.1") {
|
|
50506
50621
|
try {
|
|
50507
|
-
(0,
|
|
50622
|
+
(0, import_child_process4.execSync)(`bash -c 'exec 3<>/dev/tcp/${host}/${port}'`, { stdio: "ignore" });
|
|
50508
50623
|
return true;
|
|
50509
50624
|
} catch {
|
|
50510
50625
|
return false;
|
|
@@ -50575,7 +50690,7 @@ function controlContainerOnPort(containers, port) {
|
|
|
50575
50690
|
}
|
|
50576
50691
|
function listDockerContainers() {
|
|
50577
50692
|
try {
|
|
50578
|
-
const raw = (0,
|
|
50693
|
+
const raw = (0, import_child_process5.execSync)("docker ps --format {{.Names}}\\t{{.Ports}}", {
|
|
50579
50694
|
encoding: "utf8",
|
|
50580
50695
|
stdio: ["pipe", "pipe", "ignore"],
|
|
50581
50696
|
timeout: 3e3
|
|
@@ -50643,10 +50758,10 @@ function inspectControlUpReadiness(repoPath) {
|
|
|
50643
50758
|
var fs32 = __toESM(require("fs"));
|
|
50644
50759
|
var os7 = __toESM(require("os"));
|
|
50645
50760
|
var path31 = __toESM(require("path"));
|
|
50646
|
-
var
|
|
50761
|
+
var import_child_process6 = require("child_process");
|
|
50647
50762
|
function runGit(cwd, args) {
|
|
50648
50763
|
try {
|
|
50649
|
-
return (0,
|
|
50764
|
+
return (0, import_child_process6.execSync)(`git ${args}`, {
|
|
50650
50765
|
cwd,
|
|
50651
50766
|
encoding: "utf8",
|
|
50652
50767
|
stdio: ["pipe", "pipe", "ignore"]
|
|
@@ -50812,10 +50927,10 @@ function checkLaunchGuard(repoPath, agentId, options = {}) {
|
|
|
50812
50927
|
}
|
|
50813
50928
|
|
|
50814
50929
|
// src/core/slot-preflight.ts
|
|
50815
|
-
var
|
|
50930
|
+
var import_child_process7 = require("child_process");
|
|
50816
50931
|
function listPm2Processes() {
|
|
50817
50932
|
try {
|
|
50818
|
-
const raw = (0,
|
|
50933
|
+
const raw = (0, import_child_process7.execSync)("npx --yes pm2 jlist", {
|
|
50819
50934
|
encoding: "utf8",
|
|
50820
50935
|
stdio: ["pipe", "pipe", "ignore"],
|
|
50821
50936
|
timeout: 3e3
|
|
@@ -51039,7 +51154,7 @@ function formatPreflightReport(agentId, readiness) {
|
|
|
51039
51154
|
var BYPASS_WARNING_MS = 15 * 60 * 1e3;
|
|
51040
51155
|
function readGitRemote(repoPath) {
|
|
51041
51156
|
try {
|
|
51042
|
-
const remote = (0,
|
|
51157
|
+
const remote = (0, import_child_process8.execSync)("git remote get-url origin", {
|
|
51043
51158
|
cwd: repoPath,
|
|
51044
51159
|
encoding: "utf8",
|
|
51045
51160
|
stdio: ["pipe", "pipe", "ignore"]
|
|
@@ -51051,7 +51166,7 @@ function readGitRemote(repoPath) {
|
|
|
51051
51166
|
}
|
|
51052
51167
|
function runGit2(cwd, args) {
|
|
51053
51168
|
try {
|
|
51054
|
-
return (0,
|
|
51169
|
+
return (0, import_child_process8.execSync)(`git ${args}`, {
|
|
51055
51170
|
cwd,
|
|
51056
51171
|
encoding: "utf8",
|
|
51057
51172
|
stdio: ["pipe", "pipe", "ignore"]
|
|
@@ -51127,7 +51242,7 @@ function lastBuildPass(run2) {
|
|
|
51127
51242
|
}
|
|
51128
51243
|
function listPm2Processes2() {
|
|
51129
51244
|
try {
|
|
51130
|
-
const raw = (0,
|
|
51245
|
+
const raw = (0, import_child_process8.execSync)("npx --yes pm2 jlist", {
|
|
51131
51246
|
encoding: "utf8",
|
|
51132
51247
|
stdio: ["pipe", "pipe", "ignore"],
|
|
51133
51248
|
timeout: 3e3
|
|
@@ -51722,6 +51837,7 @@ function extractClaudeUsageFromRecords(records) {
|
|
|
51722
51837
|
let tokensCacheRead = 0;
|
|
51723
51838
|
let tokensCacheCreation = 0;
|
|
51724
51839
|
let costUsd = null;
|
|
51840
|
+
const modelBreakdown = {};
|
|
51725
51841
|
for (const record2 of records) {
|
|
51726
51842
|
if (!record2 || typeof record2 !== "object") continue;
|
|
51727
51843
|
const payload = record2;
|
|
@@ -51733,15 +51849,35 @@ function extractClaudeUsageFromRecords(records) {
|
|
|
51733
51849
|
tokensCacheCreation = Number(usage2.cache_creation_input_tokens ?? 0);
|
|
51734
51850
|
if (payload.total_cost_usd != null) costUsd = Number(payload.total_cost_usd);
|
|
51735
51851
|
}
|
|
51736
|
-
const
|
|
51852
|
+
const message = payload.message;
|
|
51853
|
+
const nestedUsage = payload.usage ?? message?.usage;
|
|
51737
51854
|
if (nestedUsage && payload.type !== "result") {
|
|
51738
|
-
|
|
51739
|
-
|
|
51740
|
-
|
|
51741
|
-
|
|
51855
|
+
const i2 = Number(nestedUsage.input_tokens ?? 0);
|
|
51856
|
+
const o2 = Number(nestedUsage.output_tokens ?? 0);
|
|
51857
|
+
const cr2 = Number(nestedUsage.cache_read_input_tokens ?? 0);
|
|
51858
|
+
const cc = Number(nestedUsage.cache_creation_input_tokens ?? 0);
|
|
51859
|
+
tokensInput += i2;
|
|
51860
|
+
tokensOutput += o2;
|
|
51861
|
+
tokensCacheRead += cr2;
|
|
51862
|
+
tokensCacheCreation += cc;
|
|
51863
|
+
const model = typeof message?.model === "string" ? message.model : void 0;
|
|
51864
|
+
if (model && model !== "<synthetic>") {
|
|
51865
|
+
const totals = modelBreakdown[model] ??= {
|
|
51866
|
+
tokensInput: 0,
|
|
51867
|
+
tokensOutput: 0,
|
|
51868
|
+
tokensCacheRead: 0,
|
|
51869
|
+
tokensCacheCreation: 0,
|
|
51870
|
+
tokensTotal: 0
|
|
51871
|
+
};
|
|
51872
|
+
totals.tokensInput += i2;
|
|
51873
|
+
totals.tokensOutput += o2;
|
|
51874
|
+
totals.tokensCacheRead += cr2;
|
|
51875
|
+
totals.tokensCacheCreation += cc;
|
|
51876
|
+
totals.tokensTotal += i2 + o2 + cr2 + cc;
|
|
51877
|
+
}
|
|
51742
51878
|
}
|
|
51743
51879
|
}
|
|
51744
|
-
return { tokensInput, tokensOutput, tokensCacheRead, tokensCacheCreation, costUsd };
|
|
51880
|
+
return { tokensInput, tokensOutput, tokensCacheRead, tokensCacheCreation, costUsd, modelBreakdown };
|
|
51745
51881
|
}
|
|
51746
51882
|
function findMatchingClaudeTranscripts(slot) {
|
|
51747
51883
|
const targets = [slot.workDir, slot.worktreePath].filter(Boolean);
|
|
@@ -51848,6 +51984,7 @@ function harvestClaudeUsage(slot) {
|
|
|
51848
51984
|
tokensCacheCreation: best.tokensCacheCreation,
|
|
51849
51985
|
tokensTotal,
|
|
51850
51986
|
costUsd: best.costUsd,
|
|
51987
|
+
...Object.keys(best.modelBreakdown).length > 0 ? { modelBreakdown: best.modelBreakdown } : {},
|
|
51851
51988
|
sources: ["harvest"],
|
|
51852
51989
|
firstSeenAt: slot.sessionCreatedAt ?? now,
|
|
51853
51990
|
lastSeenAt: now
|
|
@@ -52009,9 +52146,9 @@ async function postJson(url, body, dryRun) {
|
|
|
52009
52146
|
}
|
|
52010
52147
|
return await response.json();
|
|
52011
52148
|
}
|
|
52012
|
-
async function
|
|
52149
|
+
async function postPortal(target, endpoint, body, dryRun) {
|
|
52013
52150
|
if (dryRun) return;
|
|
52014
|
-
const response = await fetch(`${target.url}
|
|
52151
|
+
const response = await fetch(`${target.url}${endpoint}`, {
|
|
52015
52152
|
method: "POST",
|
|
52016
52153
|
headers: {
|
|
52017
52154
|
"Content-Type": "application/json",
|
|
@@ -52029,21 +52166,98 @@ async function postPortalSync(target, body, dryRun) {
|
|
|
52029
52166
|
throw new Error(`har-portal sync failed: HTTP ${response.status}${text ? ` \u2014 ${text}` : ""}`);
|
|
52030
52167
|
}
|
|
52031
52168
|
}
|
|
52032
|
-
function
|
|
52169
|
+
function resolvePortalUserEmail() {
|
|
52170
|
+
return readPortalCredentials()?.email || void 0;
|
|
52171
|
+
}
|
|
52172
|
+
function dropNullFields(record2) {
|
|
52173
|
+
return Object.fromEntries(Object.entries(record2).filter(([, value]) => value !== null));
|
|
52174
|
+
}
|
|
52175
|
+
function modelsFromBreakdown(breakdown) {
|
|
52176
|
+
if (!breakdown) return [];
|
|
52177
|
+
return Object.entries(breakdown).map(([model, totals]) => ({
|
|
52178
|
+
model,
|
|
52179
|
+
...totals && typeof totals === "object" ? totals : {}
|
|
52180
|
+
}));
|
|
52181
|
+
}
|
|
52182
|
+
function collectPortalTelemetry(repoPath, slots) {
|
|
52183
|
+
if (!isTelemetryEnabled()) return { usage: [], events: [] };
|
|
52184
|
+
try {
|
|
52185
|
+
const userEmail = resolvePortalUserEmail();
|
|
52186
|
+
const usage2 = slots.flatMap(
|
|
52187
|
+
(slot) => harvestUsageForSlot({
|
|
52188
|
+
agentId: slot.agentId,
|
|
52189
|
+
workDir: slot.workDir,
|
|
52190
|
+
worktreePath: slot.worktreePath,
|
|
52191
|
+
branch: slot.branch,
|
|
52192
|
+
suffix: slot.suffix,
|
|
52193
|
+
sessionCreatedAt: slot.sessionCreatedAt,
|
|
52194
|
+
repoPath
|
|
52195
|
+
}).map((row) => {
|
|
52196
|
+
const models = modelsFromBreakdown(
|
|
52197
|
+
row.modelBreakdown
|
|
52198
|
+
);
|
|
52199
|
+
return {
|
|
52200
|
+
...row,
|
|
52201
|
+
workUnitId: slot.workUnitId ?? row.workUnitId,
|
|
52202
|
+
attemptId: slot.attemptId ?? row.attemptId,
|
|
52203
|
+
sessionKey: row.sessionKey || buildSessionKey({
|
|
52204
|
+
branch: slot.branch,
|
|
52205
|
+
agentId: slot.agentId,
|
|
52206
|
+
suffix: slot.suffix,
|
|
52207
|
+
createdAt: slot.sessionCreatedAt
|
|
52208
|
+
}),
|
|
52209
|
+
...userEmail ? { userEmail } : {},
|
|
52210
|
+
...models.length > 0 ? { models } : {}
|
|
52211
|
+
};
|
|
52212
|
+
})
|
|
52213
|
+
);
|
|
52214
|
+
const events = slots.flatMap(
|
|
52215
|
+
(slot) => harvestEventsForSlot({
|
|
52216
|
+
agentId: slot.agentId,
|
|
52217
|
+
workDir: slot.workDir,
|
|
52218
|
+
worktreePath: slot.worktreePath,
|
|
52219
|
+
branch: slot.branch,
|
|
52220
|
+
suffix: slot.suffix,
|
|
52221
|
+
sessionCreatedAt: slot.sessionCreatedAt,
|
|
52222
|
+
repoPath
|
|
52223
|
+
}).map(
|
|
52224
|
+
(event) => dropNullFields({
|
|
52225
|
+
...event,
|
|
52226
|
+
workUnitId: slot.workUnitId ?? event.workUnitId,
|
|
52227
|
+
attemptId: slot.attemptId ?? event.attemptId
|
|
52228
|
+
})
|
|
52229
|
+
)
|
|
52230
|
+
);
|
|
52231
|
+
return { usage: usage2, events };
|
|
52232
|
+
} catch {
|
|
52233
|
+
return { usage: [], events: [] };
|
|
52234
|
+
}
|
|
52235
|
+
}
|
|
52236
|
+
function buildPortalPayload(repoPath) {
|
|
52033
52237
|
const runs = listRuns(repoPath);
|
|
52034
52238
|
const status = collectEnvironmentStatus(repoPath);
|
|
52035
52239
|
const manifest = readManifest(repoPath);
|
|
52036
52240
|
const stagesRegistry = readStageRegistry(repoPath);
|
|
52037
|
-
const
|
|
52038
|
-
|
|
52241
|
+
const harnessRoot = resolveHarnessRoot(repoPath);
|
|
52242
|
+
const validations = listValidations(harnessRoot);
|
|
52243
|
+
const workUnits = listWorkUnits(harnessRoot);
|
|
52244
|
+
const attempts = listWorkAttempts(harnessRoot);
|
|
52245
|
+
const validationBindings = listValidationBindings(harnessRoot);
|
|
52246
|
+
const { usage: usage2, events } = collectPortalTelemetry(repoPath, status.slots);
|
|
52247
|
+
const syncBody = {
|
|
52039
52248
|
path: repoPath,
|
|
52040
52249
|
...manifest ? { manifest } : {},
|
|
52041
52250
|
...stagesRegistry ? { stagesRegistry } : {},
|
|
52042
52251
|
runs,
|
|
52043
52252
|
slots: status.slots,
|
|
52044
52253
|
generatedAt: status.generatedAt,
|
|
52045
|
-
...validations.length > 0 ? { validations } : {}
|
|
52254
|
+
...validations.length > 0 ? { validations } : {},
|
|
52255
|
+
...workUnits.length > 0 ? { workUnits } : {},
|
|
52256
|
+
...attempts.length > 0 ? { attempts } : {},
|
|
52257
|
+
...validationBindings.length > 0 ? { validationBindings } : {},
|
|
52258
|
+
...usage2.length > 0 ? { usage: usage2 } : {}
|
|
52046
52259
|
};
|
|
52260
|
+
return { syncBody, events };
|
|
52047
52261
|
}
|
|
52048
52262
|
async function isControlApiReachable(apiUrl = getControlApiUrl()) {
|
|
52049
52263
|
try {
|
|
@@ -52161,7 +52375,16 @@ async function syncRepoWithControl(options) {
|
|
|
52161
52375
|
}
|
|
52162
52376
|
const portal = getPortalTarget();
|
|
52163
52377
|
if (portal) {
|
|
52164
|
-
|
|
52378
|
+
const { syncBody, events } = buildPortalPayload(repoPath);
|
|
52379
|
+
await postPortal(portal, "/api/sync", syncBody, options.dryRun);
|
|
52380
|
+
if (events.length > 0) {
|
|
52381
|
+
await postPortal(
|
|
52382
|
+
portal,
|
|
52383
|
+
"/api/otel",
|
|
52384
|
+
{ path: repoPath, events, spans: [] },
|
|
52385
|
+
options.dryRun
|
|
52386
|
+
);
|
|
52387
|
+
}
|
|
52165
52388
|
return;
|
|
52166
52389
|
}
|
|
52167
52390
|
const registerResult = await registerRepoWithControl({ ...options, repoPath });
|
|
@@ -52322,7 +52545,7 @@ function checkLaunchGuard2(repoPath, agentId, options = {}) {
|
|
|
52322
52545
|
init_control_config();
|
|
52323
52546
|
|
|
52324
52547
|
// src/core/control-lifecycle.ts
|
|
52325
|
-
var
|
|
52548
|
+
var import_child_process9 = require("child_process");
|
|
52326
52549
|
var path42 = __toESM(require("path"));
|
|
52327
52550
|
|
|
52328
52551
|
// src/core/control-image.ts
|
|
@@ -52373,7 +52596,7 @@ function buildDockerRunArgs(options) {
|
|
|
52373
52596
|
return args;
|
|
52374
52597
|
}
|
|
52375
52598
|
function runDocker(args) {
|
|
52376
|
-
const result = (0,
|
|
52599
|
+
const result = (0, import_child_process9.spawnSync)("docker", args, {
|
|
52377
52600
|
stdio: "inherit",
|
|
52378
52601
|
env: process.env
|
|
52379
52602
|
});
|
|
@@ -52383,7 +52606,7 @@ function runDocker(args) {
|
|
|
52383
52606
|
return result.status ?? 1;
|
|
52384
52607
|
}
|
|
52385
52608
|
function controlContainerExists(name = CONTROL_CONTAINER_NAME) {
|
|
52386
|
-
const result = (0,
|
|
52609
|
+
const result = (0, import_child_process9.spawnSync)("docker", ["ps", "-aq", "-f", `name=^${name}$`], {
|
|
52387
52610
|
encoding: "utf8",
|
|
52388
52611
|
stdio: ["pipe", "pipe", "ignore"]
|
|
52389
52612
|
});
|
|
@@ -52994,7 +53217,7 @@ var getEnvironmentStatus = defaultRunService.getEnvironmentStatus.bind(defaultRu
|
|
|
52994
53217
|
var getEnvironmentLogs = defaultRunService.getEnvironmentLogs.bind(defaultRunService);
|
|
52995
53218
|
|
|
52996
53219
|
// src/core/commit-gate-onboarding.ts
|
|
52997
|
-
var
|
|
53220
|
+
var readline6 = __toESM(require("readline"));
|
|
52998
53221
|
|
|
52999
53222
|
// src/core/hooks.ts
|
|
53000
53223
|
var fs42 = __toESM(require("fs"));
|
|
@@ -53262,8 +53485,8 @@ async function recordCommitAssociation(cwd) {
|
|
|
53262
53485
|
}
|
|
53263
53486
|
|
|
53264
53487
|
// src/core/commit-gate-onboarding.ts
|
|
53265
|
-
function
|
|
53266
|
-
const rl =
|
|
53488
|
+
function askYesNo5(question) {
|
|
53489
|
+
const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
|
|
53267
53490
|
return new Promise((resolve38) => {
|
|
53268
53491
|
process.stderr.write(`${question} `);
|
|
53269
53492
|
rl.once("line", (answer) => {
|
|
@@ -53294,7 +53517,7 @@ async function handleCommitGateOnboarding(options) {
|
|
|
53294
53517
|
const status = getHooksStatus(options.repoPath);
|
|
53295
53518
|
let shouldInstall = status.preCommitInstalled || status.postCommitInstalled || options.install === "always" || options.autoYes === true;
|
|
53296
53519
|
if (!shouldInstall && options.install === "prompt" && process.stdin.isTTY && process.stdout.isTTY) {
|
|
53297
|
-
shouldInstall = await
|
|
53520
|
+
shouldInstall = await askYesNo5("Install the HAR commit gate for this repository? [Y/n]");
|
|
53298
53521
|
}
|
|
53299
53522
|
if (!shouldInstall) {
|
|
53300
53523
|
info("Commit gate is not installed; run `har hooks install` when ready.");
|
|
@@ -53664,7 +53887,7 @@ async function handleInit(argv) {
|
|
|
53664
53887
|
if (argv.auto) {
|
|
53665
53888
|
await handleAgentMdProposal(repoPath, argv.yes);
|
|
53666
53889
|
} else {
|
|
53667
|
-
emitManualAdaptationPrompt(repoPath, "init", argv.profile);
|
|
53890
|
+
await emitManualAdaptationPrompt(repoPath, "init", argv.profile, void 0, argv.yes);
|
|
53668
53891
|
}
|
|
53669
53892
|
divider();
|
|
53670
53893
|
success("Harness initialized!");
|
|
@@ -53736,7 +53959,13 @@ async function handleMaintain(argv) {
|
|
|
53736
53959
|
if (!result.validation.pass) {
|
|
53737
53960
|
warn("Harness has validation errors \u2014 fix them before running --finalize.");
|
|
53738
53961
|
}
|
|
53739
|
-
emitManualAdaptationPrompt(
|
|
53962
|
+
await emitManualAdaptationPrompt(
|
|
53963
|
+
repoPath,
|
|
53964
|
+
"maintain",
|
|
53965
|
+
"default",
|
|
53966
|
+
result.bundle?.report,
|
|
53967
|
+
argv.yes
|
|
53968
|
+
);
|
|
53740
53969
|
info("After your coding agent finishes adapting, record it with: har env maintain --finalize");
|
|
53741
53970
|
}
|
|
53742
53971
|
divider();
|
|
@@ -53788,7 +54017,7 @@ function resolveOnboardingOptions(argv) {
|
|
|
53788
54017
|
}
|
|
53789
54018
|
};
|
|
53790
54019
|
}
|
|
53791
|
-
function emitManualAdaptationPrompt(repoPath, mode, profile = "default", bundleReport) {
|
|
54020
|
+
async function emitManualAdaptationPrompt(repoPath, mode, profile = "default", bundleReport, autoYes = false) {
|
|
53792
54021
|
const prompt2 = mode === "init" ? buildInitAdaptationPrompt(repoPath, profile) : buildMaintainAdaptationPrompt(repoPath, bundleReport);
|
|
53793
54022
|
writeAdaptationPrompt(repoPath, prompt2);
|
|
53794
54023
|
process.stderr.write("\n");
|
|
@@ -53804,6 +54033,7 @@ function emitManualAdaptationPrompt(repoPath, mode, profile = "default", bundleR
|
|
|
53804
54033
|
info(" Reference templates are in .har/maintain/templates/");
|
|
53805
54034
|
}
|
|
53806
54035
|
printAdaptationPrompt(prompt2);
|
|
54036
|
+
await offerAdaptationPromptClipboard(prompt2, { autoYes });
|
|
53807
54037
|
}
|
|
53808
54038
|
async function handleAgentMdProposal(repoPath, autoYes) {
|
|
53809
54039
|
if (autoYes) {
|
|
@@ -53923,8 +54153,8 @@ async function handleLaunch(argv) {
|
|
|
53923
54153
|
if (!confirmReplace && process.stdin.isTTY && process.stdout.isTTY) {
|
|
53924
54154
|
warn("Occupied slot \u2014 review before replacing:");
|
|
53925
54155
|
console.error(guard.reason ?? "");
|
|
53926
|
-
const
|
|
53927
|
-
const rl =
|
|
54156
|
+
const readline10 = await import("readline");
|
|
54157
|
+
const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
|
|
53928
54158
|
const answer = await new Promise((resolve38) => {
|
|
53929
54159
|
rl.question("Replace this slot? [y/N] ", resolve38);
|
|
53930
54160
|
});
|
|
@@ -53940,8 +54170,8 @@ async function handleLaunch(argv) {
|
|
|
53940
54170
|
if (!guardAfterConfirm.allowed && guardAfterConfirm.blocked && guardAfterConfirm.slot?.dirty) {
|
|
53941
54171
|
if (!force && process.stdin.isTTY && process.stdout.isTTY) {
|
|
53942
54172
|
warn("Worktree has uncommitted changes.");
|
|
53943
|
-
const
|
|
53944
|
-
const rl =
|
|
54173
|
+
const readline10 = await import("readline");
|
|
54174
|
+
const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
|
|
53945
54175
|
const answer = await new Promise((resolve38) => {
|
|
53946
54176
|
rl.question("Discard uncommitted changes? [y/N] ", resolve38);
|
|
53947
54177
|
});
|
|
@@ -54146,7 +54376,7 @@ function printNextSteps(auto2) {
|
|
|
54146
54376
|
console.error("");
|
|
54147
54377
|
console.error(" Read: .har/README.md");
|
|
54148
54378
|
if (!auto2) {
|
|
54149
|
-
console.error(" Adapt: paste prompt above into your coding agent");
|
|
54379
|
+
console.error(" Adapt: paste clipboard / prompt above into your coding agent");
|
|
54150
54380
|
console.error(" Prompt file: .har/ADAPT-PROMPT.md");
|
|
54151
54381
|
} else {
|
|
54152
54382
|
console.error(" Agent guide: AGENT.md (repo root, if applied)");
|
|
@@ -54167,13 +54397,13 @@ init_portal_credentials();
|
|
|
54167
54397
|
// src/core/portal-login.ts
|
|
54168
54398
|
var http = __toESM(require("http"));
|
|
54169
54399
|
var import_crypto = require("crypto");
|
|
54170
|
-
var
|
|
54400
|
+
var import_child_process11 = require("child_process");
|
|
54171
54401
|
var CALLBACK_PATH = "/callback";
|
|
54172
54402
|
var LOGIN_TIMEOUT_MS = 3 * 6e4;
|
|
54173
54403
|
function openBrowser(url) {
|
|
54174
54404
|
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
54175
54405
|
try {
|
|
54176
|
-
const child = (0,
|
|
54406
|
+
const child = (0, import_child_process11.spawn)(cmd, args, { stdio: "ignore", detached: true });
|
|
54177
54407
|
child.on("error", () => {
|
|
54178
54408
|
});
|
|
54179
54409
|
child.unref();
|
|
@@ -54194,6 +54424,7 @@ async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
|
|
|
54194
54424
|
const token = requestUrl.searchParams.get("token");
|
|
54195
54425
|
const returnedState = requestUrl.searchParams.get("state");
|
|
54196
54426
|
const workspace = requestUrl.searchParams.get("workspace") ?? void 0;
|
|
54427
|
+
const email2 = requestUrl.searchParams.get("email") ?? void 0;
|
|
54197
54428
|
if (returnedState !== state || !token) {
|
|
54198
54429
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
54199
54430
|
res.end("<h1>Login failed</h1><p>You can close this tab and try again.</p>");
|
|
@@ -54204,7 +54435,7 @@ async function loginViaBrowser(portalUrl, openUrl = openBrowser) {
|
|
|
54204
54435
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
54205
54436
|
res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
|
|
54206
54437
|
cleanup();
|
|
54207
|
-
resolve38({ portalUrl, token, workspace, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
54438
|
+
resolve38({ portalUrl, token, workspace, email: email2, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
54208
54439
|
});
|
|
54209
54440
|
const cleanup = () => {
|
|
54210
54441
|
clearTimeout(timer);
|
|
@@ -54287,10 +54518,10 @@ function listUnregisterWorktreeCandidates(repoPath) {
|
|
|
54287
54518
|
}
|
|
54288
54519
|
return [...byPath.values()].sort((a2, b2) => a2.agentId - b2.agentId);
|
|
54289
54520
|
}
|
|
54290
|
-
async function
|
|
54521
|
+
async function askYesNo6(question) {
|
|
54291
54522
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
54292
|
-
const
|
|
54293
|
-
const rl =
|
|
54523
|
+
const readline10 = await import("readline");
|
|
54524
|
+
const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
|
|
54294
54525
|
const answer = await new Promise((resolve38) => {
|
|
54295
54526
|
rl.question(question, resolve38);
|
|
54296
54527
|
});
|
|
@@ -54304,7 +54535,7 @@ async function confirmUnregister(options) {
|
|
|
54304
54535
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
54305
54536
|
throw new Error("Non-interactive terminal \u2014 pass --yes (and optionally --delete-worktrees)");
|
|
54306
54537
|
}
|
|
54307
|
-
const proceed = await
|
|
54538
|
+
const proceed = await askYesNo6("Unregister this repository from Mission Control? [y/N] ");
|
|
54308
54539
|
if (!proceed) return { proceed: false, deleteWorktrees: false };
|
|
54309
54540
|
const existing = options.worktrees.filter((w2) => w2.exists);
|
|
54310
54541
|
if (existing.length === 0) {
|
|
@@ -54316,7 +54547,7 @@ async function confirmUnregister(options) {
|
|
|
54316
54547
|
process.stderr.write(` agent-${wt2.agentId}: ${wt2.worktreePath}${dirty}
|
|
54317
54548
|
`);
|
|
54318
54549
|
}
|
|
54319
|
-
const deleteWorktrees = await
|
|
54550
|
+
const deleteWorktrees = await askYesNo6(
|
|
54320
54551
|
`Also delete ${existing.length} session worktree(s) on disk? [y/N] `
|
|
54321
54552
|
);
|
|
54322
54553
|
return { proceed: true, deleteWorktrees };
|
|
@@ -62766,7 +62997,7 @@ function getStore() {
|
|
|
62766
62997
|
}
|
|
62767
62998
|
return store;
|
|
62768
62999
|
}
|
|
62769
|
-
function
|
|
63000
|
+
function readline7() {
|
|
62770
63001
|
return getStore().rl;
|
|
62771
63002
|
}
|
|
62772
63003
|
function withUpdates(fn) {
|
|
@@ -62811,7 +63042,7 @@ var effectScheduler = {
|
|
|
62811
63042
|
const { index } = store;
|
|
62812
63043
|
store.hooksEffect.push(() => {
|
|
62813
63044
|
store.hooksCleanup[index]?.();
|
|
62814
|
-
const cleanFn = cb(
|
|
63045
|
+
const cleanFn = cb(readline7());
|
|
62815
63046
|
if (cleanFn != null && typeof cleanFn !== "function") {
|
|
62816
63047
|
throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
|
|
62817
63048
|
}
|
|
@@ -63287,7 +63518,7 @@ function breakLines(content, width) {
|
|
|
63287
63518
|
return content.split("\n").flatMap((line) => (0, import_wrap_ansi.default)(line, width, { trim: false, hard: true }).split("\n").map((str) => str.trimEnd())).join("\n");
|
|
63288
63519
|
}
|
|
63289
63520
|
function readlineWidth() {
|
|
63290
|
-
return (0, import_cli_width.default)({ defaultWidth: 80, output:
|
|
63521
|
+
return (0, import_cli_width.default)({ defaultWidth: 80, output: readline7().output });
|
|
63291
63522
|
}
|
|
63292
63523
|
|
|
63293
63524
|
// node_modules/@inquirer/core/dist/esm/lib/pagination/lines.mjs
|
|
@@ -63379,7 +63610,7 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
|
|
|
63379
63610
|
}
|
|
63380
63611
|
|
|
63381
63612
|
// node_modules/@inquirer/core/dist/esm/lib/create-prompt.mjs
|
|
63382
|
-
var
|
|
63613
|
+
var readline8 = __toESM(require("node:readline"), 1);
|
|
63383
63614
|
var import_node_async_hooks3 = require("node:async_hooks");
|
|
63384
63615
|
var import_mute_stream = __toESM(require_lib3(), 1);
|
|
63385
63616
|
|
|
@@ -63722,7 +63953,7 @@ function createPrompt(view) {
|
|
|
63722
63953
|
const cleanups = /* @__PURE__ */ new Set();
|
|
63723
63954
|
const output = new import_mute_stream.default();
|
|
63724
63955
|
output.pipe(context.output ?? process.stdout);
|
|
63725
|
-
const rl =
|
|
63956
|
+
const rl = readline8.createInterface({
|
|
63726
63957
|
terminal: true,
|
|
63727
63958
|
input,
|
|
63728
63959
|
output
|