@basein/runner 0.2.12 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +540 -369
  2. package/dist/auth/client.d.ts +65 -3
  3. package/dist/auth/client.js +305 -53
  4. package/dist/bin/bir-hooks.d.ts +72 -31
  5. package/dist/bin/bir-hooks.js +176 -284
  6. package/dist/bin/bir-proxy.d.ts +17 -2
  7. package/dist/bin/bir-proxy.js +222 -28
  8. package/dist/bin/bir-scenario.d.ts +61 -21
  9. package/dist/bin/bir-scenario.js +593 -122
  10. package/dist/bin/bir.d.ts +12 -6
  11. package/dist/bin/bir.js +2935 -489
  12. package/dist/bin/investigate.js +40 -15
  13. package/dist/bin/scenario-edit.d.ts +7 -1
  14. package/dist/bin/scenario-edit.js +43 -21
  15. package/dist/bin/scenario-liveness.d.ts +194 -0
  16. package/dist/bin/scenario-liveness.js +459 -0
  17. package/dist/bin/scenario-stderr.d.ts +43 -0
  18. package/dist/bin/scenario-stderr.js +76 -0
  19. package/dist/bin/service-read.d.ts +88 -0
  20. package/dist/bin/service-read.js +128 -0
  21. package/dist/bin/setup.d.ts +19 -0
  22. package/dist/bin/setup.js +146 -20
  23. package/dist/config/adapters/claude-code.d.ts +92 -14
  24. package/dist/config/adapters/claude-code.js +291 -101
  25. package/dist/config/adapters/generic.d.ts +4 -1
  26. package/dist/config/adapters/generic.js +13 -14
  27. package/dist/config/generate.d.ts +392 -14
  28. package/dist/config/generate.js +666 -19
  29. package/dist/config/mcp-approval.d.ts +76 -0
  30. package/dist/config/mcp-approval.js +210 -0
  31. package/dist/config/node-path.d.ts +42 -0
  32. package/dist/config/node-path.js +102 -0
  33. package/dist/config/overrides.d.ts +62 -0
  34. package/dist/config/overrides.js +136 -0
  35. package/dist/config/resolve.d.ts +70 -8
  36. package/dist/config/resolve.js +186 -15
  37. package/dist/control/client.d.ts +22 -0
  38. package/dist/control/client.js +26 -7
  39. package/dist/control/correlation.d.ts +23 -5
  40. package/dist/control/correlation.js +0 -0
  41. package/dist/control/daemon.d.ts +400 -18
  42. package/dist/control/daemon.js +1105 -102
  43. package/dist/control/discovery.d.ts +77 -5
  44. package/dist/control/discovery.js +186 -11
  45. package/dist/control/ensure-hook.d.ts +61 -0
  46. package/dist/control/ensure-hook.js +160 -8
  47. package/dist/control/paths.d.ts +26 -0
  48. package/dist/control/paths.js +34 -0
  49. package/dist/control/pin-guard.d.ts +83 -0
  50. package/dist/control/pin-guard.js +534 -0
  51. package/dist/control/recorder-keeper.d.ts +229 -0
  52. package/dist/control/recorder-keeper.js +721 -0
  53. package/dist/control/recorder-main.d.ts +73 -0
  54. package/dist/control/recorder-main.js +778 -0
  55. package/dist/control/server.d.ts +707 -31
  56. package/dist/control/server.js +2787 -302
  57. package/dist/control/transcript.d.ts +21 -1
  58. package/dist/control/transcript.js +378 -112
  59. package/dist/index.d.ts +5 -1
  60. package/dist/index.js +5 -1
  61. package/dist/jsonrpc/framing.d.ts +76 -12
  62. package/dist/jsonrpc/framing.js +216 -59
  63. package/dist/proxy/intercept.d.ts +49 -5
  64. package/dist/proxy/intercept.js +188 -59
  65. package/dist/proxy/relay.d.ts +16 -0
  66. package/dist/proxy/relay.js +77 -5
  67. package/dist/proxy/revive.d.ts +122 -0
  68. package/dist/proxy/revive.js +251 -0
  69. package/dist/proxy/session.d.ts +222 -14
  70. package/dist/proxy/session.js +708 -99
  71. package/dist/record/recorder.d.ts +51 -3
  72. package/dist/record/recorder.js +3 -0
  73. package/dist/record/redact.d.ts +103 -9
  74. package/dist/record/redact.js +659 -30
  75. package/dist/record/remote-recorder.d.ts +327 -32
  76. package/dist/record/remote-recorder.js +1517 -187
  77. package/dist/record/switchable-recorder.d.ts +126 -0
  78. package/dist/record/switchable-recorder.js +351 -0
  79. package/dist/record/truncate.d.ts +40 -1
  80. package/dist/record/truncate.js +111 -4
  81. package/dist/replay/bash-channel.d.ts +35 -0
  82. package/dist/replay/bash-channel.js +133 -0
  83. package/dist/replay/bundle.d.ts +10 -0
  84. package/dist/replay/bundle.js +10 -0
  85. package/dist/replay/controller.d.ts +369 -20
  86. package/dist/replay/controller.js +1176 -107
  87. package/dist/replay/derive.d.ts +1 -0
  88. package/dist/replay/derive.js +81 -24
  89. package/dist/replay/executor.d.ts +51 -16
  90. package/dist/replay/executor.js +114 -41
  91. package/dist/replay/handover.d.ts +54 -1
  92. package/dist/replay/handover.js +55 -5
  93. package/dist/replay/logic.d.ts +62 -10
  94. package/dist/replay/logic.js +140 -22
  95. package/dist/replay/plan.d.ts +201 -27
  96. package/dist/replay/plan.js +581 -141
  97. package/dist/replay/safety.d.ts +72 -0
  98. package/dist/replay/safety.js +303 -0
  99. package/dist/replay/source-run.d.ts +10 -0
  100. package/dist/replay/source-run.js +80 -35
  101. package/dist/replay/targets.d.ts +15 -1
  102. package/dist/replay/targets.js +62 -4
  103. package/dist/replay/tool-error.d.ts +15 -1
  104. package/dist/replay/tool-error.js +33 -1
  105. package/dist/replay/types.d.ts +7 -4
  106. package/dist/upstream/client.d.ts +56 -3
  107. package/dist/upstream/client.js +61 -4
  108. package/dist/upstream/headers.d.ts +43 -0
  109. package/dist/upstream/headers.js +90 -0
  110. package/dist/upstream/http-client.d.ts +213 -22
  111. package/dist/upstream/http-client.js +1034 -168
  112. package/dist/upstream/http-transport.d.ts +143 -0
  113. package/dist/upstream/http-transport.js +391 -0
  114. package/dist/upstream/lazy-client.d.ts +8 -0
  115. package/dist/upstream/lazy-client.js +29 -1
  116. package/dist/upstream/sse.d.ts +78 -0
  117. package/dist/upstream/sse.js +189 -0
  118. package/dist/upstream/stdio-client.d.ts +61 -1
  119. package/dist/upstream/stdio-client.js +356 -33
  120. package/dist/util/atomic-write.d.ts +29 -0
  121. package/dist/util/atomic-write.js +96 -0
  122. package/dist/util/journal.d.ts +15 -0
  123. package/dist/util/journal.js +48 -3
  124. package/dist/util/log.d.ts +10 -0
  125. package/dist/util/log.js +28 -1
  126. package/dist/util/off-switch.d.ts +46 -0
  127. package/dist/util/off-switch.js +91 -0
  128. package/dist/util/service-health.d.ts +133 -0
  129. package/dist/util/service-health.js +217 -0
  130. package/docs/BaseInstRunner.md +694 -621
  131. package/docs/calculatedReplay.md +1625 -1304
  132. package/docs/calculatedReplayGuide.md +1212 -1087
  133. package/docs/installRun.md +1013 -772
  134. package/docs/loginWeb.md +627 -607
  135. package/docs/mcpmark.md +49 -16
  136. package/docs/my-first-sample.md +569 -545
  137. package/docs/quickstart.md +384 -311
  138. package/docs/t-bench.md +406 -394
  139. package/package.json +58 -57
  140. package/production.md +1371 -0
  141. package/scripts/install.ps1 +97 -6
  142. package/scripts/install.sh +104 -7
@@ -0,0 +1,35 @@
1
+ /**
2
+ * bash-channel — delivering text to the model as a `Bash` command's genuine
3
+ * output (docs/calculatedReplay.md §8).
4
+ *
5
+ * The model reaches for `Bash` when it cannot call a scripted tool, and a real
6
+ * command output is trusted where a `deny` reason reads as interception, so a
7
+ * divergence bundle or a hand-over note is delivered by rewriting that call
8
+ * into a `cat`.
9
+ *
10
+ * THE COMMAND MUST STAY SHORT. It used to carry the whole text as a heredoc —
11
+ * up to 60 000 characters inside the command string. Measured through Git Bash
12
+ * on Windows: 8 000 characters print intact; 9 000 to 30 000 print only the
13
+ * first 8 171, with "here-document delimited by end-of-file"; 40 000 fail to
14
+ * spawn at all (ENAMETOOLONG). A bundle cut there loses its later steps and its
15
+ * footer, and the model redoes work that already ran. So a short text still
16
+ * rides inline, and anything longer is written to a private file the command
17
+ * reads. The caller caps the text itself ({@link ./bundle.ts}'s
18
+ * `BASH_CHANNEL_MAX`), because the host truncates long command output too.
19
+ */
20
+ /** Up to this many characters the text rides inside the command, as a heredoc. */
21
+ export declare const HEREDOC_MAX = 6000;
22
+ /** Where delivered texts wait to be read. Under `BIR_HOME`, mode 0700. */
23
+ export declare function deliveryDir(): string;
24
+ /**
25
+ * The command that prints `text`, or undefined when it could not be prepared —
26
+ * the caller then delivers through another channel.
27
+ */
28
+ export declare function bashCommandFor(text: string): string | undefined;
29
+ /**
30
+ * Remove delivered texts older than an hour. For the recorder to call when it
31
+ * starts and on its housekeeping tick: a process that exits within the hour
32
+ * cannot sweep what it wrote. Never throws; returns how many it removed.
33
+ */
34
+ export declare function sweepDeliveries(dir?: string): number;
35
+ //# sourceMappingURL=bash-channel.d.ts.map
@@ -0,0 +1,133 @@
1
+ /**
2
+ * bash-channel — delivering text to the model as a `Bash` command's genuine
3
+ * output (docs/calculatedReplay.md §8).
4
+ *
5
+ * The model reaches for `Bash` when it cannot call a scripted tool, and a real
6
+ * command output is trusted where a `deny` reason reads as interception, so a
7
+ * divergence bundle or a hand-over note is delivered by rewriting that call
8
+ * into a `cat`.
9
+ *
10
+ * THE COMMAND MUST STAY SHORT. It used to carry the whole text as a heredoc —
11
+ * up to 60 000 characters inside the command string. Measured through Git Bash
12
+ * on Windows: 8 000 characters print intact; 9 000 to 30 000 print only the
13
+ * first 8 171, with "here-document delimited by end-of-file"; 40 000 fail to
14
+ * spawn at all (ENAMETOOLONG). A bundle cut there loses its later steps and its
15
+ * footer, and the model redoes work that already ran. So a short text still
16
+ * rides inline, and anything longer is written to a private file the command
17
+ * reads. The caller caps the text itself ({@link ./bundle.ts}'s
18
+ * `BASH_CHANNEL_MAX`), because the host truncates long command output too.
19
+ */
20
+ import { randomUUID } from "node:crypto";
21
+ import { readdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
22
+ import { join } from "node:path";
23
+ import { configDir, ensureDir } from "../control/paths.js";
24
+ /** Up to this many characters the text rides inside the command, as a heredoc. */
25
+ export const HEREDOC_MAX = 6_000;
26
+ /** A delivered file is read once, at once; an hour is a generous margin. */
27
+ const MAX_AGE_MS = 60 * 60_000;
28
+ /** Where delivered texts wait to be read. Under `BIR_HOME`, mode 0700. */
29
+ export function deliveryDir() {
30
+ return join(configDir(), "tmp");
31
+ }
32
+ /**
33
+ * The command that prints `text`, or undefined when it could not be prepared —
34
+ * the caller then delivers through another channel.
35
+ */
36
+ export function bashCommandFor(text) {
37
+ if (text.length <= HEREDOC_MAX) {
38
+ // Neutralise the delimiter, so no text can end the heredoc early.
39
+ const delimiter = "BIR_EOF";
40
+ const safe = text.split(delimiter).join("BIR_EOF_");
41
+ return `cat <<'${delimiter}'\n${safe}\n${delimiter}`;
42
+ }
43
+ try {
44
+ const dir = deliveryDir();
45
+ ensureDir(dir);
46
+ sweep(dir);
47
+ const path = join(dir, `replay-${randomUUID()}.txt`);
48
+ writeFileSync(path, text, { encoding: "utf8", mode: 0o600 });
49
+ // The file holds live tool outputs. It is kept an hour — a Bash call can
50
+ // wait that long on a permission prompt before it reads it — and then
51
+ // removed by this process, not only by a later delivery that may never
52
+ // come ("swept after 1 h").
53
+ scheduleSweep(dir);
54
+ return `cat ${shellQuote(shellPath(path))}`;
55
+ }
56
+ catch {
57
+ return undefined;
58
+ }
59
+ }
60
+ /**
61
+ * Remove delivered texts older than an hour. For the recorder to call when it
62
+ * starts and on its housekeeping tick: a process that exits within the hour
63
+ * cannot sweep what it wrote. Never throws; returns how many it removed.
64
+ */
65
+ export function sweepDeliveries(dir = deliveryDir()) {
66
+ return sweep(dir).removed;
67
+ }
68
+ /** Past {@link MAX_AGE_MS}, how long a scheduled sweep waits more. */
69
+ const SWEEP_SLACK_MS = 60_000;
70
+ /** The sweep waiting for this process's newest delivered file to age out, by directory. */
71
+ const scheduledSweeps = new Map();
72
+ /**
73
+ * Sweep `dir` once the file just written is old enough to go, and again while
74
+ * younger ones are left. Unref'd: it never keeps the process alive.
75
+ */
76
+ function scheduleSweep(dir) {
77
+ const earlier = scheduledSweeps.get(dir);
78
+ if (earlier)
79
+ clearTimeout(earlier);
80
+ const timer = setTimeout(() => {
81
+ scheduledSweeps.delete(dir);
82
+ if (sweep(dir).left > 0)
83
+ scheduleSweep(dir);
84
+ }, MAX_AGE_MS + SWEEP_SLACK_MS);
85
+ timer.unref?.();
86
+ scheduledSweeps.set(dir, timer);
87
+ }
88
+ /**
89
+ * A path every shell the host may run can open. Forward slashes on Windows:
90
+ * Git Bash reads `C:/Users/…` as it is, and so does PowerShell's `cat`.
91
+ */
92
+ function shellPath(path) {
93
+ return process.platform === "win32" ? path.replace(/\\/g, "/") : path;
94
+ }
95
+ /** Single-quoted for a POSIX shell (and harmless in PowerShell). */
96
+ function shellQuote(s) {
97
+ return `'${s.replace(/'/g, `'\\''`)}'`;
98
+ }
99
+ /**
100
+ * Remove delivered texts older than {@link MAX_AGE_MS}. Never throws. Says how
101
+ * many it removed, and how many younger ones are left.
102
+ */
103
+ function sweep(dir) {
104
+ let names;
105
+ try {
106
+ names = readdirSync(dir);
107
+ }
108
+ catch {
109
+ return { removed: 0, left: 0 };
110
+ }
111
+ const cutoff = Date.now() - MAX_AGE_MS;
112
+ let removed = 0;
113
+ let left = 0;
114
+ for (const name of names) {
115
+ if (!name.startsWith("replay-") || !name.endsWith(".txt"))
116
+ continue;
117
+ const path = join(dir, name);
118
+ try {
119
+ if (statSync(path).mtimeMs < cutoff) {
120
+ unlinkSync(path);
121
+ removed += 1;
122
+ }
123
+ else {
124
+ left += 1;
125
+ }
126
+ }
127
+ catch {
128
+ // Gone already, or not ours to remove.
129
+ }
130
+ }
131
+ return { removed, left };
132
+ }
133
+ //# sourceMappingURL=bash-channel.js.map
@@ -16,6 +16,16 @@
16
16
  */
17
17
  /** `permissionDecisionReason` is fed to the model as text; keep denials bounded. */
18
18
  export declare const MAX_REPLAY_REASON = 60000;
19
+ /**
20
+ * Ceiling on text delivered as a `Bash` command's output.
21
+ *
22
+ * Claude Code middle-truncates Bash output above `BASH_MAX_OUTPUT_LENGTH`
23
+ * (30 000 by default), and a bundle cut in the middle loses exactly the steps
24
+ * the model needs to see were already done — so it does them again. Laid out
25
+ * at this size with the fair-share rule, every step stays represented and the
26
+ * cut never happens. A hand-over note in front of it is counted inside this.
27
+ */
28
+ export declare const BASH_CHANNEL_MAX = 25000;
19
29
  /** One executed step, pre-stringified and ready to lay out. */
20
30
  export interface BundleEntry {
21
31
  toolName: string;
@@ -16,6 +16,16 @@
16
16
  */
17
17
  /** `permissionDecisionReason` is fed to the model as text; keep denials bounded. */
18
18
  export const MAX_REPLAY_REASON = 60_000;
19
+ /**
20
+ * Ceiling on text delivered as a `Bash` command's output.
21
+ *
22
+ * Claude Code middle-truncates Bash output above `BASH_MAX_OUTPUT_LENGTH`
23
+ * (30 000 by default), and a bundle cut in the middle loses exactly the steps
24
+ * the model needs to see were already done — so it does them again. Laid out
25
+ * at this size with the fair-share rule, every step stays represented and the
26
+ * cut never happens. A hand-over note in front of it is counted inside this.
27
+ */
28
+ export const BASH_CHANNEL_MAX = 25_000;
19
29
  /** Cap each computed input so one huge argument object cannot starve responses. */
20
30
  const MAX_INPUT_CHARS = 2_000;
21
31
  /** Fixed structural overhead reserved per step (labels, separators). */