@phamvuhoang/otto-core 0.1.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 +53 -0
- package/dist/branch.d.ts +61 -0
- package/dist/branch.d.ts.map +1 -0
- package/dist/branch.js +215 -0
- package/dist/branch.js.map +1 -0
- package/dist/cli-help.d.ts +68 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +365 -0
- package/dist/cli-help.js.map +1 -0
- package/dist/detach.d.ts +36 -0
- package/dist/detach.d.ts.map +1 -0
- package/dist/detach.js +52 -0
- package/dist/detach.js.map +1 -0
- package/dist/gh-main.d.ts +5 -0
- package/dist/gh-main.d.ts.map +1 -0
- package/dist/gh-main.js +16 -0
- package/dist/gh-main.js.map +1 -0
- package/dist/git.d.ts +14 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +50 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/keepalive.d.ts +24 -0
- package/dist/keepalive.d.ts.map +1 -0
- package/dist/keepalive.js +138 -0
- package/dist/keepalive.js.map +1 -0
- package/dist/loop.d.ts +42 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +238 -0
- package/dist/loop.js.map +1 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +16 -0
- package/dist/main.js.map +1 -0
- package/dist/notify.d.ts +28 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +119 -0
- package/dist/notify.js.map +1 -0
- package/dist/pacing.d.ts +8 -0
- package/dist/pacing.d.ts.map +1 -0
- package/dist/pacing.js +33 -0
- package/dist/pacing.js.map +1 -0
- package/dist/panel.d.ts +24 -0
- package/dist/panel.d.ts.map +1 -0
- package/dist/panel.js +202 -0
- package/dist/panel.js.map +1 -0
- package/dist/rate-limit.d.ts +16 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +35 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/render.d.ts +8 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +130 -0
- package/dist/render.js.map +1 -0
- package/dist/retry.d.ts +17 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +34 -0
- package/dist/retry.js.map +1 -0
- package/dist/run-bin.d.ts +35 -0
- package/dist/run-bin.d.ts.map +1 -0
- package/dist/run-bin.js +241 -0
- package/dist/run-bin.js.map +1 -0
- package/dist/runner.d.ts +55 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +297 -0
- package/dist/runner.js.map +1 -0
- package/dist/stage-exec.d.ts +16 -0
- package/dist/stage-exec.d.ts.map +1 -0
- package/dist/stage-exec.js +35 -0
- package/dist/stage-exec.js.map +1 -0
- package/dist/stages.d.ts +38 -0
- package/dist/stages.d.ts.map +1 -0
- package/dist/stages.js +38 -0
- package/dist/stages.js.map +1 -0
- package/dist/state.d.ts +25 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +30 -0
- package/dist/state.js.map +1 -0
- package/dist/stream-render.d.ts +68 -0
- package/dist/stream-render.d.ts.map +1 -0
- package/dist/stream-render.js +162 -0
- package/dist/stream-render.js.map +1 -0
- package/dist/watch.d.ts +22 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +93 -0
- package/dist/watch.js.map +1 -0
- package/package.json +67 -0
- package/templates/afk.md +21 -0
- package/templates/apply-review.md +71 -0
- package/templates/ghafk-issue.md +29 -0
- package/templates/ghafk.md +29 -0
- package/templates/ghprompt-workflow.md +83 -0
- package/templates/ghprompt.md +39 -0
- package/templates/prompt.md +97 -0
- package/templates/review-lens.md +41 -0
- package/templates/review-synth.md +29 -0
- package/templates/review-verify.md +52 -0
- package/templates/review.md +62 -0
- package/templates/superpowers.md +70 -0
- package/templates/verify.md +74 -0
package/dist/run-bin.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { existsSync, readFileSync, appendFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { dirtyTreeWarning, ensureTmpIgnored, resolveBranch, } from "./branch.js";
|
|
5
|
+
import { parseFlags, parseDurationMs, printConfig, printHelp, printVersion, } from "./cli-help.js";
|
|
6
|
+
import { detachAndExit } from "./detach.js";
|
|
7
|
+
import { runLoop } from "./loop.js";
|
|
8
|
+
/**
|
|
9
|
+
* Ensure .otto/state.json is listed in the workspace .gitignore.
|
|
10
|
+
* No-op when the workspace has no .git directory (not a git repo).
|
|
11
|
+
* Kept separate from branch.ts's ensureTmpIgnored: that targets the parent
|
|
12
|
+
* workspaceDir (.otto-tmp/), while state.json lives in the effective workspace
|
|
13
|
+
* (the worktree, in worktree mode) where the loop writes it.
|
|
14
|
+
*/
|
|
15
|
+
function ensureStateGitignored(workspaceDir) {
|
|
16
|
+
if (!existsSync(join(workspaceDir, ".git")))
|
|
17
|
+
return;
|
|
18
|
+
const gitignorePath = join(workspaceDir, ".gitignore");
|
|
19
|
+
const entry = ".otto/state.json";
|
|
20
|
+
const existing = existsSync(gitignorePath)
|
|
21
|
+
? readFileSync(gitignorePath, "utf8")
|
|
22
|
+
: "";
|
|
23
|
+
const alreadyPresent = existing
|
|
24
|
+
.split("\n")
|
|
25
|
+
.some((line) => line.trim() === entry);
|
|
26
|
+
if (!alreadyPresent) {
|
|
27
|
+
const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
28
|
+
appendFileSync(gitignorePath, `${prefix}${entry}\n`, "utf8");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Shared entry for the AFK bins: parse flags, handle --version/--help/--print-config,
|
|
33
|
+
* resolve the workspace / package dirs, validate the positional args,
|
|
34
|
+
* optionally fork into the background (--detach), then drive runLoop.
|
|
35
|
+
*/
|
|
36
|
+
export async function runBin(argv, cfg) {
|
|
37
|
+
const flags = parseFlags(argv);
|
|
38
|
+
if (flags.version) {
|
|
39
|
+
printVersion(cfg.bin, cfg.cliVersion);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (flags.help) {
|
|
43
|
+
printHelp(cfg.bin, cfg.usage, cfg.desc);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// run-bin.js ships in the same dist/ dir as the bin entrypoints, so ".." is
|
|
47
|
+
// the installed @phamvuhoang/otto-core package dir (which holds templates/).
|
|
48
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
49
|
+
const packageDir = resolve(here, "..");
|
|
50
|
+
const workspaceDir = resolve(process.env.OTTO_WORKSPACE ?? process.cwd());
|
|
51
|
+
const envMaxWait = process.env.OTTO_MAX_WAIT?.trim();
|
|
52
|
+
const maxWaitMs = flags.maxWaitMs ?? (envMaxWait ? parseDurationMs(envMaxWait) : undefined);
|
|
53
|
+
const envBranch = process.env.OTTO_BRANCH?.trim();
|
|
54
|
+
const branchStrategyArg = flags.branch ??
|
|
55
|
+
(envBranch === "current" ||
|
|
56
|
+
envBranch === "branch" ||
|
|
57
|
+
envBranch === "worktree"
|
|
58
|
+
? envBranch
|
|
59
|
+
: undefined);
|
|
60
|
+
const branchPrefixArg = flags.branchPrefix ??
|
|
61
|
+
(process.env.OTTO_BRANCH_PREFIX?.trim() || undefined);
|
|
62
|
+
const detachLogPath = flags.detach
|
|
63
|
+
? (flags.log ??
|
|
64
|
+
join(workspaceDir, ".otto-tmp", "logs", `detached-${process.pid}.log`))
|
|
65
|
+
: undefined;
|
|
66
|
+
const DEFAULT_LENSES = ["correctness", "security", "tests"];
|
|
67
|
+
const envLenses = (process.env.OTTO_REVIEW_LENSES ?? "")
|
|
68
|
+
.split(",")
|
|
69
|
+
.map((s) => s.trim())
|
|
70
|
+
.filter(Boolean);
|
|
71
|
+
const reviewLenses = envLenses.length > 0
|
|
72
|
+
? envLenses
|
|
73
|
+
: flags.reviewPanel
|
|
74
|
+
? DEFAULT_LENSES
|
|
75
|
+
: undefined;
|
|
76
|
+
// Resolve the run mode before the --print-config early-return so it reflects
|
|
77
|
+
// the selected mode. Depends only on flags, not on the guards below.
|
|
78
|
+
const runMode = flags.verify
|
|
79
|
+
? "verify"
|
|
80
|
+
: flags.applyReview != null
|
|
81
|
+
? "review"
|
|
82
|
+
: cfg.mode;
|
|
83
|
+
if (flags.printConfig) {
|
|
84
|
+
printConfig(cfg.bin, workspaceDir, packageDir, {
|
|
85
|
+
cliVersion: cfg.cliVersion,
|
|
86
|
+
mode: runMode,
|
|
87
|
+
noKeepAlive: flags.noKeepAlive,
|
|
88
|
+
maxRetries: flags.maxRetries,
|
|
89
|
+
detach: flags.detach,
|
|
90
|
+
detachLogPath,
|
|
91
|
+
notify: flags.notify,
|
|
92
|
+
budget: flags.budget,
|
|
93
|
+
cooldownMs: flags.cooldownMs,
|
|
94
|
+
reviewLenses: reviewLenses ?? [],
|
|
95
|
+
watch: flags.watch,
|
|
96
|
+
watchIntervalSec: flags.watchIntervalSec,
|
|
97
|
+
issue: flags.issue,
|
|
98
|
+
maxWaitMs,
|
|
99
|
+
branchStrategy: branchStrategyArg,
|
|
100
|
+
branchPrefix: branchPrefixArg,
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (flags.issue != null && !cfg.issueStage) {
|
|
105
|
+
console.error("--issue is only supported by otto-ghafk");
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
const modeCount = (flags.issue != null ? 1 : 0) +
|
|
109
|
+
(flags.verify ? 1 : 0) +
|
|
110
|
+
(flags.applyReview != null ? 1 : 0) +
|
|
111
|
+
(flags.watch ? 1 : 0);
|
|
112
|
+
if (modeCount > 1) {
|
|
113
|
+
console.error("--issue, --verify, --apply-review, and --watch are mutually exclusive");
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
if (flags.verify && !cfg.verifyStage) {
|
|
117
|
+
console.error("--verify is only supported by otto-afk");
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
if (flags.applyReview != null && !cfg.applyReviewStage) {
|
|
121
|
+
console.error("--apply-review is only supported by otto-afk");
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
const inputs = flags.issue != null
|
|
125
|
+
? String(flags.issue)
|
|
126
|
+
: flags.applyReview != null
|
|
127
|
+
? flags.applyReview
|
|
128
|
+
: cfg.takesInputArg
|
|
129
|
+
? flags.rest[0]
|
|
130
|
+
: "";
|
|
131
|
+
// --verify is one-shot (iterations forced to 1 below); --apply-review takes the
|
|
132
|
+
// doc as its flag value, so the iterations count is the first remaining positional.
|
|
133
|
+
const iterationsArg = flags.applyReview != null
|
|
134
|
+
? flags.rest[0]
|
|
135
|
+
: cfg.takesInputArg
|
|
136
|
+
? flags.rest[1]
|
|
137
|
+
: flags.rest[0];
|
|
138
|
+
if (flags.verify && (!cfg.takesInputArg || !inputs)) {
|
|
139
|
+
console.error(`Usage: ${cfg.bin} --verify "<plan-and-prd>"`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
if (!flags.verify && ((cfg.takesInputArg && !inputs) || !iterationsArg)) {
|
|
143
|
+
console.error(`Usage: ${cfg.bin} ${cfg.usage}`);
|
|
144
|
+
console.error(` ${cfg.bin} --help`);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
// --verify is one-shot regardless of any positional count.
|
|
148
|
+
if (flags.verify && iterationsArg) {
|
|
149
|
+
console.error("--verify is one-shot; ignoring the iterations argument");
|
|
150
|
+
}
|
|
151
|
+
const iterations = flags.verify ? 1 : Number.parseInt(iterationsArg, 10);
|
|
152
|
+
if (!flags.verify && (!Number.isFinite(iterations) || iterations < 1)) {
|
|
153
|
+
console.error(`Invalid iterations: ${iterationsArg}`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
if (flags.issue != null) {
|
|
157
|
+
if (flags.watch) {
|
|
158
|
+
console.error("--issue cannot be combined with --watch");
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
// Validated positive integer (parseIssueRef) — safe for the static
|
|
162
|
+
// `gh issue view "$OTTO_ISSUE"` command in ghafk-issue.md. See render.ts.
|
|
163
|
+
process.env.OTTO_ISSUE = String(flags.issue);
|
|
164
|
+
}
|
|
165
|
+
const stages = flags.verify
|
|
166
|
+
? [cfg.verifyStage]
|
|
167
|
+
: flags.applyReview != null
|
|
168
|
+
? [cfg.applyReviewStage, ...cfg.stages.slice(1)]
|
|
169
|
+
: flags.issue != null
|
|
170
|
+
? [cfg.issueStage, ...cfg.stages.slice(1)]
|
|
171
|
+
: cfg.stages;
|
|
172
|
+
if (flags.detach && detachLogPath) {
|
|
173
|
+
detachAndExit({
|
|
174
|
+
logPath: detachLogPath,
|
|
175
|
+
argv,
|
|
176
|
+
binEntry: process.argv[1],
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const resolved = await resolveBranch({
|
|
180
|
+
workspaceDir,
|
|
181
|
+
inputs,
|
|
182
|
+
isTTY: Boolean(process.stdout.isTTY),
|
|
183
|
+
flagStrategy: branchStrategyArg,
|
|
184
|
+
flagPrefix: branchPrefixArg,
|
|
185
|
+
});
|
|
186
|
+
process.stderr.write(`${resolved.summaryLine}\n`);
|
|
187
|
+
// Evaluate the dirty-tree warning against the user's tree BEFORE we mutate the
|
|
188
|
+
// workspace's .gitignore below — otherwise Otto's own .otto-tmp/ edit would
|
|
189
|
+
// make a tracked .gitignore "dirty" and fire a spurious warning on first run.
|
|
190
|
+
const dirtyWarn = dirtyTreeWarning(workspaceDir, resolved.strategy);
|
|
191
|
+
if (dirtyWarn)
|
|
192
|
+
process.stderr.write(`⚠ ${dirtyWarn}\n`);
|
|
193
|
+
ensureTmpIgnored(workspaceDir);
|
|
194
|
+
const effectiveWorkspaceDir = resolved.effectiveWorkspaceDir;
|
|
195
|
+
// state.json is written by the loop into effectiveWorkspaceDir (the worktree in
|
|
196
|
+
// worktree mode), which differs from the parent workspaceDir that
|
|
197
|
+
// ensureTmpIgnored targets — so this stays a separate call.
|
|
198
|
+
ensureStateGitignored(effectiveWorkspaceDir);
|
|
199
|
+
if (flags.watch) {
|
|
200
|
+
if (!cfg.supportsWatch) {
|
|
201
|
+
console.error("--watch is only supported by otto-ghafk");
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const { runWatch } = await import("./watch.js");
|
|
205
|
+
await runWatch({
|
|
206
|
+
stages,
|
|
207
|
+
iterations,
|
|
208
|
+
workspaceDir: effectiveWorkspaceDir,
|
|
209
|
+
packageDir,
|
|
210
|
+
watchIntervalSec: flags.watchIntervalSec ?? 300,
|
|
211
|
+
watchLabel: process.env.OTTO_WATCH_LABEL?.trim() || "otto",
|
|
212
|
+
budgetUsd: flags.budget,
|
|
213
|
+
cooldownMs: flags.cooldownMs,
|
|
214
|
+
maxRetries: flags.maxRetries,
|
|
215
|
+
reviewLenses,
|
|
216
|
+
notify: flags.notify,
|
|
217
|
+
bin: cfg.bin,
|
|
218
|
+
cliVersion: cfg.cliVersion,
|
|
219
|
+
});
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
await runLoop({
|
|
223
|
+
stages,
|
|
224
|
+
inputs: inputs ?? "",
|
|
225
|
+
iterations,
|
|
226
|
+
workspaceDir: effectiveWorkspaceDir,
|
|
227
|
+
packageDir,
|
|
228
|
+
noKeepAlive: flags.noKeepAlive,
|
|
229
|
+
maxRetries: flags.maxRetries,
|
|
230
|
+
notify: flags.notify,
|
|
231
|
+
bin: cfg.bin,
|
|
232
|
+
cliVersion: cfg.cliVersion,
|
|
233
|
+
budgetUsd: flags.budget,
|
|
234
|
+
cooldownMs: flags.cooldownMs,
|
|
235
|
+
reviewLenses,
|
|
236
|
+
mode: runMode,
|
|
237
|
+
maxWaitMs,
|
|
238
|
+
fresh: flags.fresh,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=run-bin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-bin.js","sourceRoot":"","sources":["../src/run-bin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,SAAS,EACT,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BpC;;;;;;GAMG;AACH,SAAS,qBAAqB,CAAC,YAAoB;IACjD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAAE,OAAO;IACpD,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,kBAAkB,CAAC;IACjC,MAAM,QAAQ,GAAG,UAAU,CAAC,aAAa,CAAC;QACxC,CAAC,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC;QACrC,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,cAAc,GAAG,QAAQ;SAC5B,KAAK,CAAC,IAAI,CAAC;SACX,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC;IACzC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,cAAc,CAAC,aAAa,EAAE,GAAG,MAAM,GAAG,KAAK,IAAI,EAAE,MAAM,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc,EAAE,GAAiB;IAC5D,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;QACtC,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IAED,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvC,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAE1E,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;IACrD,MAAM,SAAS,GACb,KAAK,CAAC,SAAS,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAE5E,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAClD,MAAM,iBAAiB,GACrB,KAAK,CAAC,MAAM;QACZ,CAAC,SAAS,KAAK,SAAS;YACxB,SAAS,KAAK,QAAQ;YACtB,SAAS,KAAK,UAAU;YACtB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,SAAS,CAAC,CAAC;IACjB,MAAM,eAAe,GACnB,KAAK,CAAC,YAAY;QAClB,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC,CAAC;IAExD,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM;QAChC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;YACV,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;QACzE,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,cAAc,GAAG,CAAC,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC;SACrD,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,YAAY,GAChB,SAAS,CAAC,MAAM,GAAG,CAAC;QAClB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,KAAK,CAAC,WAAW;YACjB,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,SAAS,CAAC;IAElB,6EAA6E;IAC7E,qEAAqE;IACrE,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM;QAC1B,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI;YACzB,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IAEf,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE;YAC7C,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,aAAa;YACb,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,YAAY,EAAE,YAAY,IAAI,EAAE;YAChC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;YACxC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,SAAS;YACT,cAAc,EAAE,iBAAiB;YACjC,YAAY,EAAE,eAAe;SAC9B,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GACb,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CACX,uEAAuE,CACxE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GACV,KAAK,CAAC,KAAK,IAAI,IAAI;QACjB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;QACrB,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI;YACzB,CAAC,CAAC,KAAK,CAAC,WAAW;YACnB,CAAC,CAAC,GAAG,CAAC,aAAa;gBACjB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBACf,CAAC,CAAC,EAAE,CAAC;IACb,gFAAgF;IAChF,oFAAoF;IACpF,MAAM,aAAa,GACjB,KAAK,CAAC,WAAW,IAAI,IAAI;QACvB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACf,CAAC,CAAC,GAAG,CAAC,aAAa;YACjB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YACf,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,GAAG,4BAA4B,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,2DAA2D;IAC3D,IAAI,KAAK,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC;QACtE,OAAO,CAAC,KAAK,CAAC,uBAAuB,aAAa,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,mEAAmE;QACnE,0EAA0E;QAC1E,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,MAAM,GAAwB,KAAK,CAAC,MAAM;QAC9C,CAAC,CAAC,CAAC,GAAG,CAAC,WAAY,CAAC;QACpB,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI;YACzB,CAAC,CAAC,CAAC,GAAG,CAAC,gBAAiB,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjD,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI;gBACnB,CAAC,CAAC,CAAC,GAAG,CAAC,UAAW,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC3C,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IAEnB,IAAI,KAAK,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;QAClC,aAAa,CAAC;YACZ,OAAO,EAAE,aAAa;YACtB,IAAI;YACJ,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC;QACnC,YAAY;QACZ,MAAM;QACN,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;QACpC,YAAY,EAAE,iBAAiB;QAC/B,UAAU,EAAE,eAAe;KAC5B,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,WAAW,IAAI,CAAC,CAAC;IAClD,+EAA+E;IAC/E,4EAA4E;IAC5E,8EAA8E;IAC9E,MAAM,SAAS,GAAG,gBAAgB,CAAC,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACpE,IAAI,SAAS;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC;IAExD,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAE/B,MAAM,qBAAqB,GAAG,QAAQ,CAAC,qBAAqB,CAAC;IAC7D,gFAAgF;IAChF,kEAAkE;IAClE,4DAA4D;IAC5D,qBAAqB,CAAC,qBAAqB,CAAC,CAAC;IAE7C,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,QAAQ,CAAC;YACb,MAAM;YACN,UAAU;YACV,YAAY,EAAE,qBAAqB;YACnC,UAAU;YACV,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,IAAI,GAAG;YAC/C,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,MAAM;YAC1D,SAAS,EAAE,KAAK,CAAC,MAAM;YACvB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,YAAY;YACZ,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,UAAU,EAAE,GAAG,CAAC,UAAU;SAC3B,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,OAAO,CAAC;QACZ,MAAM;QACN,MAAM,EAAE,MAAM,IAAI,EAAE;QACpB,UAAU;QACV,YAAY,EAAE,qBAAqB;QACnC,UAAU;QACV,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,KAAK,CAAC,MAAM;QACvB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,YAAY;QACZ,IAAI,EAAE,OAAO;QACb,SAAS;QACT,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC,CAAC;AACL,CAAC"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Stage } from "./stages.js";
|
|
2
|
+
export type RunStageOptions = {
|
|
3
|
+
signal?: AbortSignal;
|
|
4
|
+
};
|
|
5
|
+
export type StageResult = {
|
|
6
|
+
result: string;
|
|
7
|
+
costUsd: number;
|
|
8
|
+
isError: boolean;
|
|
9
|
+
apiErrorStatus: string | null;
|
|
10
|
+
};
|
|
11
|
+
/** Pure extraction of the fields Otto tracks from a stream-json `result` event. */
|
|
12
|
+
export declare function resultFromEvent(ev: unknown): StageResult;
|
|
13
|
+
/**
|
|
14
|
+
* Parse `OTTO_RESULT_GRACE_MS`. Returns the configured millisecond budget,
|
|
15
|
+
* `0` to disable the timer entirely, or `defaultMs` for any invalid input
|
|
16
|
+
* (unset, empty, non-finite, negative).
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseGraceMs(raw: string | undefined, defaultMs?: number): number;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve `OTTO_MODEL` into a `claude` argv fragment. Returns
|
|
21
|
+
* `["--model", trimmed]` for a non-empty value, or `[]` for unset / empty /
|
|
22
|
+
* whitespace-only input. Pass-through: otto never validates the model spec,
|
|
23
|
+
* the `claude` CLI owns that.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveModelArgs(raw: string | undefined): string[];
|
|
26
|
+
export type Runner = "sandbox" | "host";
|
|
27
|
+
/** `OTTO_RUNNER=host` → bare host run; anything else (incl. unset) → sandbox. */
|
|
28
|
+
export declare function resolveRunner(raw: string | undefined): Runner;
|
|
29
|
+
/** Parse `OTTO_SANDBOX_NET` into a domain allowlist. Empty = unrestricted. */
|
|
30
|
+
export declare function resolveSandboxNet(raw: string | undefined): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Claude Code native-sandbox settings: confine writes to the workspace and run
|
|
33
|
+
* the Go-TLS CLIs unsandboxed. When `allowedDomains` is non-empty, also restrict
|
|
34
|
+
* network egress to that list; otherwise leave network unrestricted (filesystem
|
|
35
|
+
* is the blast-radius control; network commands fall back to the bypass-approved
|
|
36
|
+
* escape hatch).
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildSandboxSettings(workspaceDir: string, allowedDomains: string[]): Record<string, unknown>;
|
|
39
|
+
export declare function stageLogPath(workspaceDir: string, iteration: number, stageName: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Build the `claude` argv. Extracted as a pure helper so callers can unit-test
|
|
42
|
+
* the argv without spawning a process.
|
|
43
|
+
*
|
|
44
|
+
* @param stage - The stage configuration (name, permissionMode, etc.).
|
|
45
|
+
* @param promptRelPath - The workspace-relative path to the rendered prompt file.
|
|
46
|
+
* @param modelArgs - The `["--model", "<spec>"]` fragment from {@link resolveModelArgs},
|
|
47
|
+
* or `[]` when `OTTO_MODEL` is unset.
|
|
48
|
+
* @param settingsPath - Optional absolute path to a transient settings JSON file
|
|
49
|
+
* (written by `runStage` when `OTTO_RUNNER=sandbox`).
|
|
50
|
+
* @returns The full argv starting with `"claude"` and ending with the prompt
|
|
51
|
+
* instruction string.
|
|
52
|
+
*/
|
|
53
|
+
export declare function buildClaudeArgs(stage: Stage, promptRelPath: string, modelArgs: string[], settingsPath?: string): string[];
|
|
54
|
+
export declare function runStage(stage: Stage, renderedPrompt: string, workspaceDir: string, iteration: number, spillHostDir?: string, logPathOverride?: string, options?: RunStageOptions): Promise<StageResult>;
|
|
55
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAazC,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,GAAG,WAAW,CASxD;AAKD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,SAAS,GAAE,MAAgC,GAC1C,MAAM,CAQR;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAKlE;AAED,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAExC,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE7D;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAMnE;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,EAAE,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAQD,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,CAQR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,EAAE,CAmBV;AAED,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,WAAW,CAAC,CA0CtB"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { appendFileSync, closeSync, mkdirSync, openSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { createInterface } from "node:readline";
|
|
4
|
+
import { join, posix } from "node:path";
|
|
5
|
+
import { dim, renderEvent, } from "./stream-render.js";
|
|
6
|
+
import { RateLimitError, isLimitResult, resetsAtFromEvent, } from "./rate-limit.js";
|
|
7
|
+
/** Pure extraction of the fields Otto tracks from a stream-json `result` event. */
|
|
8
|
+
export function resultFromEvent(ev) {
|
|
9
|
+
const e = (ev ?? {});
|
|
10
|
+
return {
|
|
11
|
+
result: typeof e.result === "string" ? e.result : "",
|
|
12
|
+
costUsd: typeof e.total_cost_usd === "number" ? e.total_cost_usd : 0,
|
|
13
|
+
isError: e.is_error === true,
|
|
14
|
+
apiErrorStatus: typeof e.api_error_status === "string" ? e.api_error_status : null,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const STDERR_TAIL_LINES = 40;
|
|
18
|
+
const DEFAULT_RESULT_GRACE_MS = 30_000;
|
|
19
|
+
/**
|
|
20
|
+
* Parse `OTTO_RESULT_GRACE_MS`. Returns the configured millisecond budget,
|
|
21
|
+
* `0` to disable the timer entirely, or `defaultMs` for any invalid input
|
|
22
|
+
* (unset, empty, non-finite, negative).
|
|
23
|
+
*/
|
|
24
|
+
export function parseGraceMs(raw, defaultMs = DEFAULT_RESULT_GRACE_MS) {
|
|
25
|
+
if (raw == null)
|
|
26
|
+
return defaultMs;
|
|
27
|
+
const trimmed = raw.trim();
|
|
28
|
+
if (trimmed === "")
|
|
29
|
+
return defaultMs;
|
|
30
|
+
const n = Number(trimmed);
|
|
31
|
+
if (!Number.isFinite(n))
|
|
32
|
+
return defaultMs;
|
|
33
|
+
if (n < 0)
|
|
34
|
+
return defaultMs;
|
|
35
|
+
return Math.floor(n);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve `OTTO_MODEL` into a `claude` argv fragment. Returns
|
|
39
|
+
* `["--model", trimmed]` for a non-empty value, or `[]` for unset / empty /
|
|
40
|
+
* whitespace-only input. Pass-through: otto never validates the model spec,
|
|
41
|
+
* the `claude` CLI owns that.
|
|
42
|
+
*/
|
|
43
|
+
export function resolveModelArgs(raw) {
|
|
44
|
+
if (raw == null)
|
|
45
|
+
return [];
|
|
46
|
+
const trimmed = raw.trim();
|
|
47
|
+
if (trimmed === "")
|
|
48
|
+
return [];
|
|
49
|
+
return ["--model", trimmed];
|
|
50
|
+
}
|
|
51
|
+
/** `OTTO_RUNNER=host` → bare host run; anything else (incl. unset) → sandbox. */
|
|
52
|
+
export function resolveRunner(raw) {
|
|
53
|
+
return raw?.trim() === "host" ? "host" : "sandbox";
|
|
54
|
+
}
|
|
55
|
+
/** Parse `OTTO_SANDBOX_NET` into a domain allowlist. Empty = unrestricted. */
|
|
56
|
+
export function resolveSandboxNet(raw) {
|
|
57
|
+
if (!raw)
|
|
58
|
+
return [];
|
|
59
|
+
return raw
|
|
60
|
+
.split(",")
|
|
61
|
+
.map((s) => s.trim())
|
|
62
|
+
.filter(Boolean);
|
|
63
|
+
}
|
|
64
|
+
// Go-based CLIs fail TLS verification under macOS Seatbelt; run them outside the
|
|
65
|
+
// sandbox so `gh`/`gcloud`/`terraform` keep working (otto-ghafk relies on gh).
|
|
66
|
+
const SANDBOX_EXCLUDED_COMMANDS = ["gh *", "gcloud *", "terraform *"];
|
|
67
|
+
/**
|
|
68
|
+
* Claude Code native-sandbox settings: confine writes to the workspace and run
|
|
69
|
+
* the Go-TLS CLIs unsandboxed. When `allowedDomains` is non-empty, also restrict
|
|
70
|
+
* network egress to that list; otherwise leave network unrestricted (filesystem
|
|
71
|
+
* is the blast-radius control; network commands fall back to the bypass-approved
|
|
72
|
+
* escape hatch).
|
|
73
|
+
*/
|
|
74
|
+
export function buildSandboxSettings(workspaceDir, allowedDomains) {
|
|
75
|
+
const sandbox = {
|
|
76
|
+
enabled: true,
|
|
77
|
+
filesystem: { allowWrite: [workspaceDir] },
|
|
78
|
+
excludedCommands: SANDBOX_EXCLUDED_COMMANDS,
|
|
79
|
+
};
|
|
80
|
+
if (allowedDomains.length > 0) {
|
|
81
|
+
sandbox.network = { allowedDomains };
|
|
82
|
+
}
|
|
83
|
+
return { sandbox };
|
|
84
|
+
}
|
|
85
|
+
function abortError() {
|
|
86
|
+
const err = new Error("claude command aborted");
|
|
87
|
+
err.name = "AbortError";
|
|
88
|
+
return err;
|
|
89
|
+
}
|
|
90
|
+
export function stageLogPath(workspaceDir, iteration, stageName) {
|
|
91
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
92
|
+
return join(workspaceDir, ".otto-tmp", "logs", `${timestamp}-iter${iteration}-${stageName}.ndjson`);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Build the `claude` argv. Extracted as a pure helper so callers can unit-test
|
|
96
|
+
* the argv without spawning a process.
|
|
97
|
+
*
|
|
98
|
+
* @param stage - The stage configuration (name, permissionMode, etc.).
|
|
99
|
+
* @param promptRelPath - The workspace-relative path to the rendered prompt file.
|
|
100
|
+
* @param modelArgs - The `["--model", "<spec>"]` fragment from {@link resolveModelArgs},
|
|
101
|
+
* or `[]` when `OTTO_MODEL` is unset.
|
|
102
|
+
* @param settingsPath - Optional absolute path to a transient settings JSON file
|
|
103
|
+
* (written by `runStage` when `OTTO_RUNNER=sandbox`).
|
|
104
|
+
* @returns The full argv starting with `"claude"` and ending with the prompt
|
|
105
|
+
* instruction string.
|
|
106
|
+
*/
|
|
107
|
+
export function buildClaudeArgs(stage, promptRelPath, modelArgs, settingsPath) {
|
|
108
|
+
const args = [
|
|
109
|
+
"claude",
|
|
110
|
+
"--verbose",
|
|
111
|
+
"--print",
|
|
112
|
+
"--output-format",
|
|
113
|
+
"stream-json",
|
|
114
|
+
];
|
|
115
|
+
if (stage.permissionMode) {
|
|
116
|
+
args.push("--permission-mode", stage.permissionMode);
|
|
117
|
+
}
|
|
118
|
+
if (settingsPath) {
|
|
119
|
+
args.push("--settings", settingsPath);
|
|
120
|
+
}
|
|
121
|
+
args.push(...modelArgs);
|
|
122
|
+
args.push(`Read the full instructions from the file ./${promptRelPath} in the current workspace and execute them.`);
|
|
123
|
+
return args;
|
|
124
|
+
}
|
|
125
|
+
export async function runStage(stage, renderedPrompt, workspaceDir, iteration, spillHostDir, logPathOverride, options = {}) {
|
|
126
|
+
const tmpHostDir = join(workspaceDir, ".otto-tmp");
|
|
127
|
+
mkdirSync(tmpHostDir, { recursive: true });
|
|
128
|
+
const logsDir = join(tmpHostDir, "logs");
|
|
129
|
+
mkdirSync(logsDir, { recursive: true });
|
|
130
|
+
const logPath = logPathOverride ?? stageLogPath(workspaceDir, iteration, stage.name);
|
|
131
|
+
const promptName = `.run-${process.pid}-${iteration}-${Date.now()}.md`;
|
|
132
|
+
const promptHostPath = join(tmpHostDir, promptName);
|
|
133
|
+
const promptRelPath = posix.join(".otto-tmp", promptName);
|
|
134
|
+
writeFileSync(promptHostPath, renderedPrompt, "utf8");
|
|
135
|
+
let settingsHostPath;
|
|
136
|
+
if (resolveRunner(process.env.OTTO_RUNNER) === "sandbox") {
|
|
137
|
+
const settings = buildSandboxSettings(workspaceDir, resolveSandboxNet(process.env.OTTO_SANDBOX_NET));
|
|
138
|
+
settingsHostPath = join(tmpHostDir, `.sandbox-${process.pid}-${iteration}-${Date.now()}.json`);
|
|
139
|
+
writeFileSync(settingsHostPath, JSON.stringify(settings), "utf8");
|
|
140
|
+
}
|
|
141
|
+
process.stderr.write(`${dim("log → " + logPath)}\n`);
|
|
142
|
+
try {
|
|
143
|
+
const argv = buildClaudeArgs(stage, promptRelPath, resolveModelArgs(process.env.OTTO_MODEL), settingsHostPath);
|
|
144
|
+
return await streamClaude(argv, workspaceDir, logPath, options);
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
rmSync(promptHostPath, { force: true });
|
|
148
|
+
if (settingsHostPath)
|
|
149
|
+
rmSync(settingsHostPath, { force: true });
|
|
150
|
+
if (spillHostDir)
|
|
151
|
+
rmSync(spillHostDir, { recursive: true, force: true });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function streamClaude(argv, cwd, logPath, options = {}) {
|
|
155
|
+
if (options.signal?.aborted) {
|
|
156
|
+
return Promise.reject(abortError());
|
|
157
|
+
}
|
|
158
|
+
return new Promise((resolve, reject) => {
|
|
159
|
+
const logFd = openSync(logPath, "a");
|
|
160
|
+
const toolMap = new Map();
|
|
161
|
+
const graceMs = parseGraceMs(process.env.OTTO_RESULT_GRACE_MS);
|
|
162
|
+
// Spawn claude (argv[0]) on the host instead of docker.
|
|
163
|
+
const child = spawn(argv[0], argv.slice(1), {
|
|
164
|
+
cwd,
|
|
165
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
166
|
+
});
|
|
167
|
+
let final = {
|
|
168
|
+
result: "",
|
|
169
|
+
costUsd: 0,
|
|
170
|
+
isError: false,
|
|
171
|
+
apiErrorStatus: null,
|
|
172
|
+
};
|
|
173
|
+
let lastResetsAt = null;
|
|
174
|
+
const stderrTail = [];
|
|
175
|
+
let settled = false;
|
|
176
|
+
let onAbort = () => { };
|
|
177
|
+
let rl;
|
|
178
|
+
let rlErr;
|
|
179
|
+
let graceTimer;
|
|
180
|
+
const finish = (fn) => {
|
|
181
|
+
if (settled)
|
|
182
|
+
return;
|
|
183
|
+
settled = true;
|
|
184
|
+
if (graceTimer) {
|
|
185
|
+
clearTimeout(graceTimer);
|
|
186
|
+
graceTimer = undefined;
|
|
187
|
+
}
|
|
188
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
189
|
+
try {
|
|
190
|
+
rl?.close();
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Already closed.
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
rlErr?.close();
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Already closed.
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
closeSync(logFd);
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
// Already closed.
|
|
206
|
+
}
|
|
207
|
+
fn();
|
|
208
|
+
};
|
|
209
|
+
const rejectOnce = (err) => finish(() => reject(err));
|
|
210
|
+
const resolveOnce = (value) => finish(() => resolve(value));
|
|
211
|
+
onAbort = () => {
|
|
212
|
+
try {
|
|
213
|
+
child.kill();
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Already dead; close handling below will settle if needed.
|
|
217
|
+
}
|
|
218
|
+
rejectOnce(abortError());
|
|
219
|
+
};
|
|
220
|
+
rl = createInterface({ input: child.stdout });
|
|
221
|
+
rl.on("line", (line) => {
|
|
222
|
+
if (settled)
|
|
223
|
+
return;
|
|
224
|
+
if (!line.startsWith("{"))
|
|
225
|
+
return;
|
|
226
|
+
appendFileSync(logFd, line + "\n");
|
|
227
|
+
let parsed;
|
|
228
|
+
try {
|
|
229
|
+
parsed = JSON.parse(line);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
renderEvent(parsed, toolMap);
|
|
235
|
+
if (parsed.type === "rate_limit_event") {
|
|
236
|
+
const r = resetsAtFromEvent(parsed);
|
|
237
|
+
if (r != null)
|
|
238
|
+
lastResetsAt = r;
|
|
239
|
+
}
|
|
240
|
+
if (parsed.type === "result") {
|
|
241
|
+
final = resultFromEvent(parsed);
|
|
242
|
+
// Arm one-shot post-result grace timer to recover from claude-CLI
|
|
243
|
+
// self-deadlocks where the child emits its final NDJSON but never
|
|
244
|
+
// exits. See docs/prd/result-grace-timer.md.
|
|
245
|
+
if (!graceTimer && graceMs > 0) {
|
|
246
|
+
graceTimer = setTimeout(() => {
|
|
247
|
+
if (settled)
|
|
248
|
+
return;
|
|
249
|
+
process.stderr.write(`${dim(`grace timer fired after ${graceMs}ms post-result — killing claude child`)}\n`);
|
|
250
|
+
try {
|
|
251
|
+
child.kill();
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Already dead; close handler will be a no-op via settle guard.
|
|
255
|
+
}
|
|
256
|
+
if (final && isLimitResult(final)) {
|
|
257
|
+
rejectOnce(new RateLimitError(final.result || "rate limit", lastResetsAt));
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
resolveOnce(final);
|
|
261
|
+
}
|
|
262
|
+
}, graceMs);
|
|
263
|
+
graceTimer.unref?.();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
rlErr = createInterface({ input: child.stderr });
|
|
268
|
+
rlErr.on("line", (line) => {
|
|
269
|
+
if (settled)
|
|
270
|
+
return;
|
|
271
|
+
stderrTail.push(line);
|
|
272
|
+
if (stderrTail.length > STDERR_TAIL_LINES)
|
|
273
|
+
stderrTail.shift();
|
|
274
|
+
process.stderr.write(`${dim("claude " + line)}\n`);
|
|
275
|
+
});
|
|
276
|
+
if (options.signal?.aborted) {
|
|
277
|
+
onAbort();
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
281
|
+
child.on("error", (err) => {
|
|
282
|
+
rejectOnce(err);
|
|
283
|
+
});
|
|
284
|
+
child.on("close", (code) => {
|
|
285
|
+
if (final && isLimitResult(final)) {
|
|
286
|
+
rejectOnce(new RateLimitError(final.result || "rate limit", lastResetsAt));
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (code !== 0) {
|
|
290
|
+
rejectOnce(new Error(`claude exited with ${code}\n${stderrTail.join("\n")}`));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
resolveOnce(final);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type StageResult } from "./runner.js";
|
|
2
|
+
import type { Stage } from "./stages.js";
|
|
3
|
+
export type ExecuteStageOptions = {
|
|
4
|
+
stage: Stage;
|
|
5
|
+
vars: Record<string, string>;
|
|
6
|
+
workspaceDir: string;
|
|
7
|
+
packageDir: string;
|
|
8
|
+
iteration: number;
|
|
9
|
+
maxRetries: number;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
/** Disambiguates spill/log paths when multiple sub-stages share an iteration (panel lenses). */
|
|
12
|
+
logLabel?: string;
|
|
13
|
+
};
|
|
14
|
+
/** Render a stage's template (inside the retry, so flaky shell tags retry) and run it. */
|
|
15
|
+
export declare function executeStage(opts: ExecuteStageOptions): Promise<StageResult>;
|
|
16
|
+
//# sourceMappingURL=stage-exec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-exec.d.ts","sourceRoot":"","sources":["../src/stage-exec.ts"],"names":[],"mappings":"AAIA,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,gGAAgG;IAChG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,0FAA0F;AAC1F,wBAAsB,YAAY,CAChC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,WAAW,CAAC,CAmDtB"}
|