@unimatrix27/ralph-harness 1.0.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/CONTRIBUTING.md +89 -0
- package/README.md +401 -0
- package/dist/bin/ralph-bootstrap-aws.d.ts +3 -0
- package/dist/bin/ralph-bootstrap-aws.d.ts.map +1 -0
- package/dist/bin/ralph-bootstrap-aws.js +43 -0
- package/dist/bin/ralph-bootstrap-aws.js.map +1 -0
- package/dist/bin/ralph-fire.d.ts +3 -0
- package/dist/bin/ralph-fire.d.ts.map +1 -0
- package/dist/bin/ralph-fire.js +59 -0
- package/dist/bin/ralph-fire.js.map +1 -0
- package/dist/bin/ralph-gsm.d.ts +3 -0
- package/dist/bin/ralph-gsm.d.ts.map +1 -0
- package/dist/bin/ralph-gsm.js +93 -0
- package/dist/bin/ralph-gsm.js.map +1 -0
- package/dist/bin/ralph-orchestrate.d.ts +3 -0
- package/dist/bin/ralph-orchestrate.d.ts.map +1 -0
- package/dist/bin/ralph-orchestrate.js +20 -0
- package/dist/bin/ralph-orchestrate.js.map +1 -0
- package/dist/bin/ralph-sync-credential.d.ts +3 -0
- package/dist/bin/ralph-sync-credential.d.ts.map +1 -0
- package/dist/bin/ralph-sync-credential.js +44 -0
- package/dist/bin/ralph-sync-credential.js.map +1 -0
- package/dist/bin/ralph-sync-github-pat.d.ts +3 -0
- package/dist/bin/ralph-sync-github-pat.d.ts.map +1 -0
- package/dist/bin/ralph-sync-github-pat.js +93 -0
- package/dist/bin/ralph-sync-github-pat.js.map +1 -0
- package/dist/bin/ralph-tail-logs.d.ts +3 -0
- package/dist/bin/ralph-tail-logs.d.ts.map +1 -0
- package/dist/bin/ralph-tail-logs.js +72 -0
- package/dist/bin/ralph-tail-logs.js.map +1 -0
- package/dist/bin/ralph-validate-config.d.ts +3 -0
- package/dist/bin/ralph-validate-config.d.ts.map +1 -0
- package/dist/bin/ralph-validate-config.js +41 -0
- package/dist/bin/ralph-validate-config.js.map +1 -0
- package/dist/lib/aws-bootstrap.d.ts +53 -0
- package/dist/lib/aws-bootstrap.d.ts.map +1 -0
- package/dist/lib/aws-bootstrap.js +438 -0
- package/dist/lib/aws-bootstrap.js.map +1 -0
- package/dist/lib/aws-clients.d.ts +17 -0
- package/dist/lib/aws-clients.d.ts.map +1 -0
- package/dist/lib/aws-clients.js +25 -0
- package/dist/lib/aws-clients.js.map +1 -0
- package/dist/lib/claude-runner.d.ts +21 -0
- package/dist/lib/claude-runner.d.ts.map +1 -0
- package/dist/lib/claude-runner.js +101 -0
- package/dist/lib/claude-runner.js.map +1 -0
- package/dist/lib/credential-syncer.d.ts +27 -0
- package/dist/lib/credential-syncer.d.ts.map +1 -0
- package/dist/lib/credential-syncer.js +116 -0
- package/dist/lib/credential-syncer.js.map +1 -0
- package/dist/lib/ec2-orchestrator.d.ts +38 -0
- package/dist/lib/ec2-orchestrator.d.ts.map +1 -0
- package/dist/lib/ec2-orchestrator.js +469 -0
- package/dist/lib/ec2-orchestrator.js.map +1 -0
- package/dist/lib/env-loader.d.ts +18 -0
- package/dist/lib/env-loader.d.ts.map +1 -0
- package/dist/lib/env-loader.js +120 -0
- package/dist/lib/env-loader.js.map +1 -0
- package/dist/lib/fire-launcher.d.ts +59 -0
- package/dist/lib/fire-launcher.d.ts.map +1 -0
- package/dist/lib/fire-launcher.js +320 -0
- package/dist/lib/fire-launcher.js.map +1 -0
- package/dist/lib/gh-runner.d.ts +13 -0
- package/dist/lib/gh-runner.d.ts.map +1 -0
- package/dist/lib/gh-runner.js +50 -0
- package/dist/lib/gh-runner.js.map +1 -0
- package/dist/lib/github-state-mutator.d.ts +11 -0
- package/dist/lib/github-state-mutator.d.ts.map +1 -0
- package/dist/lib/github-state-mutator.js +179 -0
- package/dist/lib/github-state-mutator.js.map +1 -0
- package/dist/lib/phase-result-schemas.d.ts +88 -0
- package/dist/lib/phase-result-schemas.d.ts.map +1 -0
- package/dist/lib/phase-result-schemas.js +180 -0
- package/dist/lib/phase-result-schemas.js.map +1 -0
- package/dist/lib/post-hoc-agent-stuck-checker.d.ts +26 -0
- package/dist/lib/post-hoc-agent-stuck-checker.d.ts.map +1 -0
- package/dist/lib/post-hoc-agent-stuck-checker.js +142 -0
- package/dist/lib/post-hoc-agent-stuck-checker.js.map +1 -0
- package/dist/lib/prompt-renderer.d.ts +4 -0
- package/dist/lib/prompt-renderer.d.ts.map +1 -0
- package/dist/lib/prompt-renderer.js +30 -0
- package/dist/lib/prompt-renderer.js.map +1 -0
- package/dist/lib/security-runner.d.ts +7 -0
- package/dist/lib/security-runner.d.ts.map +1 -0
- package/dist/lib/security-runner.js +53 -0
- package/dist/lib/security-runner.js.map +1 -0
- package/dist/lib/structured-log-emitter.d.ts +53 -0
- package/dist/lib/structured-log-emitter.d.ts.map +1 -0
- package/dist/lib/structured-log-emitter.js +122 -0
- package/dist/lib/structured-log-emitter.js.map +1 -0
- package/dist/lib/target-config-schema.d.ts +28 -0
- package/dist/lib/target-config-schema.d.ts.map +1 -0
- package/dist/lib/target-config-schema.js +157 -0
- package/dist/lib/target-config-schema.js.map +1 -0
- package/dist/lib/user-data-renderer.d.ts +20 -0
- package/dist/lib/user-data-renderer.d.ts.map +1 -0
- package/dist/lib/user-data-renderer.js +75 -0
- package/dist/lib/user-data-renderer.js.map +1 -0
- package/lib/cloud-init/system-setup.sh +338 -0
- package/package.json +55 -0
- package/prompts/discovery.md +182 -0
- package/prompts/implementation.md +161 -0
- package/prompts/review.md +135 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
// aws-bootstrap — idempotent AWS-side and target-side bootstrap for the
|
|
2
|
+
// ralph-harness operator. Public functions ensure each resource exists;
|
|
3
|
+
// re-running on an already-bootstrapped account is a clean no-op.
|
|
4
|
+
//
|
|
5
|
+
// Public surface:
|
|
6
|
+
// ensureKmsAlias(clients, alias)
|
|
7
|
+
// ensureSsmSecureString(clients, name, description, kmsAlias)
|
|
8
|
+
// ensureIamRoleAndProfile(clients, role, profile, githubKey, oauthKey, logGroup, kmsAlias)
|
|
9
|
+
// ensureSecurityGroup(clients, name, description)
|
|
10
|
+
// ensureLogGroup(clients, name)
|
|
11
|
+
// ensureAgentStuckLabel(repo, label)
|
|
12
|
+
// runAll(opts)
|
|
13
|
+
//
|
|
14
|
+
// Idempotency contract (must match lib/aws-bootstrap.sh — bash module is
|
|
15
|
+
// being deleted in this slice; the contract is what's tested):
|
|
16
|
+
// Every ensure* function probes for the resource's current state and only
|
|
17
|
+
// issues create/put calls when state is missing. On second run the only
|
|
18
|
+
// AWS calls made are read-only describe/get operations.
|
|
19
|
+
//
|
|
20
|
+
// Errors throw; the CLI (ralph-bootstrap-aws) maps them to exit codes.
|
|
21
|
+
import { CreateLogGroupCommand, DescribeLogGroupsCommand, } from "@aws-sdk/client-cloudwatch-logs";
|
|
22
|
+
import { CreateSecurityGroupCommand, DescribeSecurityGroupsCommand, DescribeVpcsCommand, } from "@aws-sdk/client-ec2";
|
|
23
|
+
import { AddRoleToInstanceProfileCommand, AttachRolePolicyCommand, CreateInstanceProfileCommand, CreateRoleCommand, GetInstanceProfileCommand, GetRoleCommand, GetRolePolicyCommand, ListAttachedRolePoliciesCommand, PutRolePolicyCommand, } from "@aws-sdk/client-iam";
|
|
24
|
+
import { CreateAliasCommand, CreateKeyCommand, DescribeKeyCommand, } from "@aws-sdk/client-kms";
|
|
25
|
+
import { GetParameterCommand, ParameterAlreadyExists, PutParameterCommand, } from "@aws-sdk/client-ssm";
|
|
26
|
+
import { GetCallerIdentityCommand } from "@aws-sdk/client-sts";
|
|
27
|
+
import { AWS_REGION } from "./aws-clients.js";
|
|
28
|
+
import { GhRunnerError, runGh } from "./gh-runner.js";
|
|
29
|
+
export const MODULE_PREFIX = "aws-bootstrap";
|
|
30
|
+
export const DEFAULTS = {
|
|
31
|
+
region: AWS_REGION,
|
|
32
|
+
kmsAlias: "alias/ralph",
|
|
33
|
+
iamRole: "ralph-ec2-role",
|
|
34
|
+
iamProfile: "ralph-ec2-profile",
|
|
35
|
+
sgName: "ralph-sg",
|
|
36
|
+
agentStuckLabel: "agent-stuck",
|
|
37
|
+
agentStuckColor: "d73a4a",
|
|
38
|
+
githubKey: "/ralph/github-pat",
|
|
39
|
+
oauthKey: "/ralph/claude-oauth-credential",
|
|
40
|
+
logGroup: "/ralph/main",
|
|
41
|
+
};
|
|
42
|
+
export function moduleErr(message) {
|
|
43
|
+
return `${MODULE_PREFIX}: error: ${message}`;
|
|
44
|
+
}
|
|
45
|
+
export function moduleInfo(message) {
|
|
46
|
+
return `${MODULE_PREFIX}: ${message}`;
|
|
47
|
+
}
|
|
48
|
+
const defaultInfo = (line) => process.stdout.write(`${line}\n`);
|
|
49
|
+
// ---- KMS -------------------------------------------------------------
|
|
50
|
+
// ensureKmsAlias — ensure a KMS CMK exists behind the given alias. If the
|
|
51
|
+
// alias resolves, no-op. Otherwise create a symmetric encrypt/decrypt key
|
|
52
|
+
// and point the alias at it.
|
|
53
|
+
export async function ensureKmsAlias(clients, alias, info = defaultInfo) {
|
|
54
|
+
try {
|
|
55
|
+
await clients.kms.send(new DescribeKeyCommand({ KeyId: alias }));
|
|
56
|
+
info(moduleInfo(`kms: ${alias} already exists`));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
if (!isNotFound(err))
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
const created = await clients.kms.send(new CreateKeyCommand({
|
|
64
|
+
Description: `ralph-harness CMK (used by ${alias})`,
|
|
65
|
+
KeyUsage: "ENCRYPT_DECRYPT",
|
|
66
|
+
}));
|
|
67
|
+
const keyId = created.KeyMetadata?.KeyId;
|
|
68
|
+
if (!keyId) {
|
|
69
|
+
throw new Error(moduleErr(`kms: create-key returned no KeyId`));
|
|
70
|
+
}
|
|
71
|
+
await clients.kms.send(new CreateAliasCommand({ AliasName: alias, TargetKeyId: keyId }));
|
|
72
|
+
info(moduleInfo(`kms: created ${alias} -> ${keyId}`));
|
|
73
|
+
}
|
|
74
|
+
// ---- SSM SecureString -----------------------------------------------
|
|
75
|
+
const SSM_PLACEHOLDER = "PLACEHOLDER-set-via-credential-syncer";
|
|
76
|
+
// ensureSsmSecureString — ensure a SecureString parameter exists at <name>.
|
|
77
|
+
// If missing, create it with a placeholder. If present, leave it untouched
|
|
78
|
+
// (we never overwrite an existing parameter).
|
|
79
|
+
export async function ensureSsmSecureString(clients, name, description, kmsAlias, info = defaultInfo) {
|
|
80
|
+
try {
|
|
81
|
+
await clients.ssm.send(new GetParameterCommand({ Name: name, WithDecryption: true }));
|
|
82
|
+
info(moduleInfo(`ssm: ${name} already exists`));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
if (!isNotFound(err))
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
await clients.ssm.send(new PutParameterCommand({
|
|
91
|
+
Name: name,
|
|
92
|
+
Description: description,
|
|
93
|
+
Type: "SecureString",
|
|
94
|
+
KeyId: kmsAlias,
|
|
95
|
+
Value: SSM_PLACEHOLDER,
|
|
96
|
+
Overwrite: false,
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
// Race: another caller created it between our get and put. Treat the
|
|
101
|
+
// already-exists error as success — the post-condition is "parameter
|
|
102
|
+
// exists with some value", which is satisfied either way.
|
|
103
|
+
if (err instanceof ParameterAlreadyExists) {
|
|
104
|
+
info(moduleInfo(`ssm: ${name} already exists (raced put)`));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
info(moduleInfo(`ssm: created ${name}`));
|
|
110
|
+
}
|
|
111
|
+
const TRUST_POLICY = {
|
|
112
|
+
Version: "2012-10-17",
|
|
113
|
+
Statement: [
|
|
114
|
+
{
|
|
115
|
+
Sid: "EC2AssumeRole",
|
|
116
|
+
Effect: "Allow",
|
|
117
|
+
Action: ["sts:AssumeRole"],
|
|
118
|
+
// The IAM service ignores Sid uniqueness in trust docs; this is just
|
|
119
|
+
// the canonical shape. Kept as a literal so the JSON we send is stable.
|
|
120
|
+
Resource: "ec2.amazonaws.com",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
};
|
|
124
|
+
// The bash port emits the trust policy in a slightly different shape (single
|
|
125
|
+
// Principal:Service statement). The IAM API requires that exact shape, so we
|
|
126
|
+
// emit raw JSON for the trust policy rather than reusing the inline-policy
|
|
127
|
+
// builder.
|
|
128
|
+
const TRUST_POLICY_DOC_JSON = JSON.stringify({
|
|
129
|
+
Version: "2012-10-17",
|
|
130
|
+
Statement: [
|
|
131
|
+
{
|
|
132
|
+
Effect: "Allow",
|
|
133
|
+
Principal: { Service: "ec2.amazonaws.com" },
|
|
134
|
+
Action: "sts:AssumeRole",
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
});
|
|
138
|
+
export function buildInlinePolicy(account, githubKey, oauthKey, logGroup, kmsAlias, region = DEFAULTS.region) {
|
|
139
|
+
return {
|
|
140
|
+
Version: "2012-10-17",
|
|
141
|
+
Statement: [
|
|
142
|
+
{
|
|
143
|
+
Sid: "ReadAssignedSSMParameters",
|
|
144
|
+
Effect: "Allow",
|
|
145
|
+
Action: ["ssm:GetParameter", "ssm:GetParameters"],
|
|
146
|
+
Resource: [
|
|
147
|
+
`arn:aws:ssm:${region}:${account}:parameter${githubKey}`,
|
|
148
|
+
`arn:aws:ssm:${region}:${account}:parameter${oauthKey}`,
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
Sid: "DecryptRalphKMS",
|
|
153
|
+
Effect: "Allow",
|
|
154
|
+
Action: ["kms:Decrypt"],
|
|
155
|
+
Resource: "*",
|
|
156
|
+
Condition: {
|
|
157
|
+
"ForAnyValue:StringEquals": { "kms:ResourceAliases": kmsAlias },
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
Sid: "PutRalphLogs",
|
|
162
|
+
Effect: "Allow",
|
|
163
|
+
Action: [
|
|
164
|
+
"logs:CreateLogStream",
|
|
165
|
+
"logs:PutLogEvents",
|
|
166
|
+
"logs:DescribeLogStreams",
|
|
167
|
+
],
|
|
168
|
+
Resource: `arn:aws:logs:${region}:${account}:log-group:${logGroup}:*`,
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// canonicalJson — stable key-sorted JSON. Used to compare an existing inline
|
|
174
|
+
// policy against the desired one without false-diffing on key order.
|
|
175
|
+
export function canonicalJson(value) {
|
|
176
|
+
return JSON.stringify(sortKeys(value));
|
|
177
|
+
}
|
|
178
|
+
function sortKeys(value) {
|
|
179
|
+
if (Array.isArray(value))
|
|
180
|
+
return value.map(sortKeys);
|
|
181
|
+
if (value && typeof value === "object") {
|
|
182
|
+
const obj = value;
|
|
183
|
+
const out = {};
|
|
184
|
+
for (const k of Object.keys(obj).sort()) {
|
|
185
|
+
out[k] = sortKeys(obj[k]);
|
|
186
|
+
}
|
|
187
|
+
return out;
|
|
188
|
+
}
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
// ensureIamRoleAndProfile — ensure the EC2 role exists with the EC2 trust
|
|
192
|
+
// policy, AmazonSSMManagedInstanceCore attached, and the inline policy
|
|
193
|
+
// `ralph-inline` granting:
|
|
194
|
+
// - SSM read on the two assigned parameter keys
|
|
195
|
+
// - kms:Decrypt scoped to <kmsAlias>
|
|
196
|
+
// - PutLogEvents scoped to <logGroup>
|
|
197
|
+
// Plus: the instance profile exists and the role is attached to it.
|
|
198
|
+
export async function ensureIamRoleAndProfile(clients, role, profile, githubKey, oauthKey, logGroup, kmsAlias, info = defaultInfo, region = DEFAULTS.region) {
|
|
199
|
+
const account = await getAccountId(clients);
|
|
200
|
+
const inlineDoc = buildInlinePolicy(account, githubKey, oauthKey, logGroup, kmsAlias, region);
|
|
201
|
+
// role
|
|
202
|
+
let roleExists = false;
|
|
203
|
+
try {
|
|
204
|
+
await clients.iam.send(new GetRoleCommand({ RoleName: role }));
|
|
205
|
+
roleExists = true;
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
if (!isNotFound(err))
|
|
209
|
+
throw err;
|
|
210
|
+
}
|
|
211
|
+
if (roleExists) {
|
|
212
|
+
info(moduleInfo(`iam: role ${role} already exists`));
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
await clients.iam.send(new CreateRoleCommand({
|
|
216
|
+
RoleName: role,
|
|
217
|
+
Description: "ralph-harness EC2 worker role",
|
|
218
|
+
AssumeRolePolicyDocument: TRUST_POLICY_DOC_JSON,
|
|
219
|
+
}));
|
|
220
|
+
info(moduleInfo(`iam: created role ${role}`));
|
|
221
|
+
}
|
|
222
|
+
// managed policy attach
|
|
223
|
+
const attached = await clients.iam.send(new ListAttachedRolePoliciesCommand({ RoleName: role }));
|
|
224
|
+
const ssmManaged = (attached.AttachedPolicies ?? []).some((p) => p.PolicyName === "AmazonSSMManagedInstanceCore");
|
|
225
|
+
if (ssmManaged) {
|
|
226
|
+
info(moduleInfo(`iam: AmazonSSMManagedInstanceCore already attached to ${role}`));
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
await clients.iam.send(new AttachRolePolicyCommand({
|
|
230
|
+
RoleName: role,
|
|
231
|
+
PolicyArn: "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
|
|
232
|
+
}));
|
|
233
|
+
info(moduleInfo(`iam: attached AmazonSSMManagedInstanceCore to ${role}`));
|
|
234
|
+
}
|
|
235
|
+
// inline policy
|
|
236
|
+
let existingInlineRaw;
|
|
237
|
+
try {
|
|
238
|
+
const got = await clients.iam.send(new GetRolePolicyCommand({
|
|
239
|
+
RoleName: role,
|
|
240
|
+
PolicyName: "ralph-inline",
|
|
241
|
+
}));
|
|
242
|
+
// GetRolePolicy returns the document URL-encoded in the bash CLI; the
|
|
243
|
+
// SDK decodes it for us into a JSON string.
|
|
244
|
+
existingInlineRaw = got.PolicyDocument;
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
if (!isNotFound(err))
|
|
248
|
+
throw err;
|
|
249
|
+
}
|
|
250
|
+
const desiredCompact = canonicalJson(inlineDoc);
|
|
251
|
+
let existingCompact = "";
|
|
252
|
+
if (existingInlineRaw) {
|
|
253
|
+
try {
|
|
254
|
+
existingCompact = canonicalJson(JSON.parse(decodeURIComponent(existingInlineRaw)));
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
// The SDK may already return a decoded JSON string. Try parse-as-is.
|
|
258
|
+
try {
|
|
259
|
+
existingCompact = canonicalJson(JSON.parse(existingInlineRaw));
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
existingCompact = "";
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (existingCompact === desiredCompact) {
|
|
267
|
+
info(moduleInfo(`iam: inline policy ralph-inline already up to date on ${role}`));
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
await clients.iam.send(new PutRolePolicyCommand({
|
|
271
|
+
RoleName: role,
|
|
272
|
+
PolicyName: "ralph-inline",
|
|
273
|
+
PolicyDocument: JSON.stringify(inlineDoc),
|
|
274
|
+
}));
|
|
275
|
+
info(moduleInfo(`iam: wrote inline policy ralph-inline on ${role}`));
|
|
276
|
+
}
|
|
277
|
+
// instance profile
|
|
278
|
+
let profileExists = false;
|
|
279
|
+
let profileHasRole = false;
|
|
280
|
+
try {
|
|
281
|
+
const got = await clients.iam.send(new GetInstanceProfileCommand({ InstanceProfileName: profile }));
|
|
282
|
+
profileExists = true;
|
|
283
|
+
profileHasRole = (got.InstanceProfile?.Roles ?? []).some((r) => r.RoleName === role);
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
if (!isNotFound(err))
|
|
287
|
+
throw err;
|
|
288
|
+
}
|
|
289
|
+
if (profileExists) {
|
|
290
|
+
info(moduleInfo(`iam: instance profile ${profile} already exists`));
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
await clients.iam.send(new CreateInstanceProfileCommand({ InstanceProfileName: profile }));
|
|
294
|
+
info(moduleInfo(`iam: created instance profile ${profile}`));
|
|
295
|
+
}
|
|
296
|
+
if (profileHasRole) {
|
|
297
|
+
info(moduleInfo(`iam: role ${role} already attached to profile ${profile}`));
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
await clients.iam.send(new AddRoleToInstanceProfileCommand({
|
|
301
|
+
InstanceProfileName: profile,
|
|
302
|
+
RoleName: role,
|
|
303
|
+
}));
|
|
304
|
+
info(moduleInfo(`iam: attached role ${role} to profile ${profile}`));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// ---- EC2 security group ---------------------------------------------
|
|
308
|
+
// ensureSecurityGroup — ensure a security group named <name> exists in the
|
|
309
|
+
// region's default VPC. Newly-created groups inherit the default
|
|
310
|
+
// "no inbound, all outbound" posture, which is what the harness wants.
|
|
311
|
+
export async function ensureSecurityGroup(clients, name, description, info = defaultInfo, region = DEFAULTS.region) {
|
|
312
|
+
const vpcs = await clients.ec2.send(new DescribeVpcsCommand({
|
|
313
|
+
Filters: [{ Name: "is-default", Values: ["true"] }],
|
|
314
|
+
}));
|
|
315
|
+
const vpcId = vpcs.Vpcs?.[0]?.VpcId;
|
|
316
|
+
if (!vpcId) {
|
|
317
|
+
throw new Error(moduleErr(`no default VPC in region ${region}; refusing to create security group`));
|
|
318
|
+
}
|
|
319
|
+
const existing = await clients.ec2.send(new DescribeSecurityGroupsCommand({
|
|
320
|
+
Filters: [
|
|
321
|
+
{ Name: "group-name", Values: [name] },
|
|
322
|
+
{ Name: "vpc-id", Values: [vpcId] },
|
|
323
|
+
],
|
|
324
|
+
}));
|
|
325
|
+
const existingId = existing.SecurityGroups?.[0]?.GroupId;
|
|
326
|
+
if (existingId) {
|
|
327
|
+
info(moduleInfo(`ec2: security group ${name} already exists (${existingId})`));
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const created = await clients.ec2.send(new CreateSecurityGroupCommand({
|
|
331
|
+
GroupName: name,
|
|
332
|
+
Description: description,
|
|
333
|
+
VpcId: vpcId,
|
|
334
|
+
}));
|
|
335
|
+
info(moduleInfo(`ec2: created security group ${name} (${created.GroupId})`));
|
|
336
|
+
}
|
|
337
|
+
// ---- CloudWatch log group -------------------------------------------
|
|
338
|
+
// ensureLogGroup — ensure a CloudWatch log group named <name> exists.
|
|
339
|
+
export async function ensureLogGroup(clients, name, info = defaultInfo) {
|
|
340
|
+
const list = await clients.logs.send(new DescribeLogGroupsCommand({ logGroupNamePrefix: name }));
|
|
341
|
+
const found = (list.logGroups ?? []).some((g) => g.logGroupName === name);
|
|
342
|
+
if (found) {
|
|
343
|
+
info(moduleInfo(`logs: log group ${name} already exists`));
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
await clients.logs.send(new CreateLogGroupCommand({ logGroupName: name }));
|
|
347
|
+
info(moduleInfo(`logs: created log group ${name}`));
|
|
348
|
+
}
|
|
349
|
+
// ---- target-side gh label -------------------------------------------
|
|
350
|
+
// ensureAgentStuckLabel — ensure the target repo has the configured stuck
|
|
351
|
+
// label (red). Uses `gh label`, not the AWS SDK.
|
|
352
|
+
export function ensureAgentStuckLabel(repo, label, info = defaultInfo, color = DEFAULTS.agentStuckColor) {
|
|
353
|
+
let existing = [];
|
|
354
|
+
try {
|
|
355
|
+
const r = runGh([
|
|
356
|
+
"label",
|
|
357
|
+
"list",
|
|
358
|
+
"--repo",
|
|
359
|
+
repo,
|
|
360
|
+
"--json",
|
|
361
|
+
"name",
|
|
362
|
+
"--jq",
|
|
363
|
+
".[].name",
|
|
364
|
+
]);
|
|
365
|
+
existing = r.stdout
|
|
366
|
+
.split("\n")
|
|
367
|
+
.map((l) => l.trim())
|
|
368
|
+
.filter((l) => l.length > 0);
|
|
369
|
+
}
|
|
370
|
+
catch (err) {
|
|
371
|
+
// gh exits non-zero only on a real failure (auth missing, repo not
|
|
372
|
+
// found). Surface that — listing labels is a precondition.
|
|
373
|
+
throw err instanceof GhRunnerError
|
|
374
|
+
? new Error(moduleErr(`label list ${repo} failed: ${err.message}`))
|
|
375
|
+
: err;
|
|
376
|
+
}
|
|
377
|
+
if (existing.includes(label)) {
|
|
378
|
+
info(moduleInfo(`github: label ${label} already exists on ${repo}`));
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
runGh([
|
|
382
|
+
"label",
|
|
383
|
+
"create",
|
|
384
|
+
label,
|
|
385
|
+
"--repo",
|
|
386
|
+
repo,
|
|
387
|
+
"--color",
|
|
388
|
+
color,
|
|
389
|
+
"--description",
|
|
390
|
+
"Set by ralph-harness when an iteration escapes via the stuck-budget path.",
|
|
391
|
+
]);
|
|
392
|
+
info(moduleInfo(`github: created label ${label} on ${repo}`));
|
|
393
|
+
}
|
|
394
|
+
// runAll — ensure every resource. Idempotent on second run.
|
|
395
|
+
export async function runAll(opts) {
|
|
396
|
+
const { clients, repo, githubKey = DEFAULTS.githubKey, oauthKey = DEFAULTS.oauthKey, logGroup = DEFAULTS.logGroup, kmsAlias = DEFAULTS.kmsAlias, iamRole = DEFAULTS.iamRole, iamProfile = DEFAULTS.iamProfile, sgName = DEFAULTS.sgName, agentStuckLabel = DEFAULTS.agentStuckLabel, region = DEFAULTS.region, info = defaultInfo, } = opts;
|
|
397
|
+
info(moduleInfo(`region=${region} target=${repo}`));
|
|
398
|
+
info(moduleInfo(`github_key=${githubKey} oauth_key=${oauthKey} log_group=${logGroup}`));
|
|
399
|
+
await ensureKmsAlias(clients, kmsAlias, info);
|
|
400
|
+
await ensureSsmSecureString(clients, githubKey, "ralph-harness GitHub PAT (SecureString placeholder)", kmsAlias, info);
|
|
401
|
+
await ensureSsmSecureString(clients, oauthKey, "ralph-harness Claude OAuth credential (SecureString placeholder)", kmsAlias, info);
|
|
402
|
+
await ensureLogGroup(clients, logGroup, info);
|
|
403
|
+
await ensureIamRoleAndProfile(clients, iamRole, iamProfile, githubKey, oauthKey, logGroup, kmsAlias, info, region);
|
|
404
|
+
await ensureSecurityGroup(clients, sgName, "ralph-harness EC2 worker (no inbound, all outbound)", info, region);
|
|
405
|
+
ensureAgentStuckLabel(repo, agentStuckLabel, info);
|
|
406
|
+
}
|
|
407
|
+
// ---- helpers --------------------------------------------------------
|
|
408
|
+
async function getAccountId(clients) {
|
|
409
|
+
const r = await clients.sts.send(new GetCallerIdentityCommand({}));
|
|
410
|
+
if (!r.Account) {
|
|
411
|
+
throw new Error(moduleErr("sts: GetCallerIdentity returned no Account"));
|
|
412
|
+
}
|
|
413
|
+
return r.Account;
|
|
414
|
+
}
|
|
415
|
+
// isNotFound — recognize "resource doesn't exist" errors from the AWS SDK
|
|
416
|
+
// across services. Each service has its own typed exception, but they all
|
|
417
|
+
// share the `name` property convention.
|
|
418
|
+
function isNotFound(err) {
|
|
419
|
+
if (!err || typeof err !== "object")
|
|
420
|
+
return false;
|
|
421
|
+
const e = err;
|
|
422
|
+
const name = e.name ?? e.Code ?? "";
|
|
423
|
+
if (name === "NotFoundException" ||
|
|
424
|
+
name === "NoSuchEntityException" ||
|
|
425
|
+
name === "ParameterNotFound" ||
|
|
426
|
+
name === "ResourceNotFoundException" ||
|
|
427
|
+
name === "ResourceNotFoundFault" ||
|
|
428
|
+
name === "NotFound" ||
|
|
429
|
+
name === "InvalidGroup.NotFound") {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
// Some errors only carry the httpStatusCode — IAM GetRole returns 404 with
|
|
433
|
+
// name=NoSuchEntityException already, but be defensive.
|
|
434
|
+
if (e.$metadata?.httpStatusCode === 404)
|
|
435
|
+
return true;
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=aws-bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-bootstrap.js","sourceRoot":"","sources":["../../src/lib/aws-bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CloudWatchLogsClient } from "@aws-sdk/client-cloudwatch-logs";
|
|
2
|
+
import { EC2Client } from "@aws-sdk/client-ec2";
|
|
3
|
+
import { IAMClient } from "@aws-sdk/client-iam";
|
|
4
|
+
import { KMSClient } from "@aws-sdk/client-kms";
|
|
5
|
+
import { SSMClient } from "@aws-sdk/client-ssm";
|
|
6
|
+
import { STSClient } from "@aws-sdk/client-sts";
|
|
7
|
+
export declare const AWS_REGION = "eu-central-1";
|
|
8
|
+
export interface AwsClients {
|
|
9
|
+
kms: KMSClient;
|
|
10
|
+
ssm: SSMClient;
|
|
11
|
+
iam: IAMClient;
|
|
12
|
+
ec2: EC2Client;
|
|
13
|
+
logs: CloudWatchLogsClient;
|
|
14
|
+
sts: STSClient;
|
|
15
|
+
}
|
|
16
|
+
export declare function defaultAwsClients(region?: string): AwsClients;
|
|
17
|
+
//# sourceMappingURL=aws-clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-clients.d.ts","sourceRoot":"","sources":["../../src/lib/aws-clients.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,eAAO,MAAM,UAAU,iBAAiB,CAAC;AAEzC,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,SAAS,CAAC;IACf,GAAG,EAAE,SAAS,CAAC;IACf,GAAG,EAAE,SAAS,CAAC;IACf,GAAG,EAAE,SAAS,CAAC;IACf,IAAI,EAAE,oBAAoB,CAAC;IAC3B,GAAG,EAAE,SAAS,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,MAAmB,GAAG,UAAU,CASzE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// aws-clients — typed wrappers around the AWS SDK clients the operator CLIs
|
|
2
|
+
// need. Centralized so every module shares the same region and credential
|
|
3
|
+
// chain, and so tests can inject mocks via the `AwsClients` interface.
|
|
4
|
+
//
|
|
5
|
+
// Region is forced to `eu-central-1` — matching the bash port and the rest
|
|
6
|
+
// of the harness. Override only via the explicit constructor argument (used
|
|
7
|
+
// by tests).
|
|
8
|
+
import { CloudWatchLogsClient } from "@aws-sdk/client-cloudwatch-logs";
|
|
9
|
+
import { EC2Client } from "@aws-sdk/client-ec2";
|
|
10
|
+
import { IAMClient } from "@aws-sdk/client-iam";
|
|
11
|
+
import { KMSClient } from "@aws-sdk/client-kms";
|
|
12
|
+
import { SSMClient } from "@aws-sdk/client-ssm";
|
|
13
|
+
import { STSClient } from "@aws-sdk/client-sts";
|
|
14
|
+
export const AWS_REGION = "eu-central-1";
|
|
15
|
+
export function defaultAwsClients(region = AWS_REGION) {
|
|
16
|
+
return {
|
|
17
|
+
kms: new KMSClient({ region }),
|
|
18
|
+
ssm: new SSMClient({ region }),
|
|
19
|
+
iam: new IAMClient({ region }),
|
|
20
|
+
ec2: new EC2Client({ region }),
|
|
21
|
+
logs: new CloudWatchLogsClient({ region }),
|
|
22
|
+
sts: new STSClient({ region }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=aws-clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-clients.js","sourceRoot":"","sources":["../../src/lib/aws-clients.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,0EAA0E;AAC1E,uEAAuE;AACvE,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,aAAa;AAEb,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC;AAWzC,MAAM,UAAU,iBAAiB,CAAC,SAAiB,UAAU;IAC3D,OAAO;QACL,GAAG,EAAE,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QAC9B,GAAG,EAAE,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QAC9B,GAAG,EAAE,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QAC9B,GAAG,EAAE,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QAC9B,IAAI,EAAE,IAAI,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1C,GAAG,EAAE,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KAC/B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const MODULE_PREFIX = "claude-runner";
|
|
2
|
+
export interface RunClaudeOptions {
|
|
3
|
+
bin?: string;
|
|
4
|
+
flags?: string;
|
|
5
|
+
model?: string;
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
stdout?: NodeJS.WritableStream;
|
|
8
|
+
stderr?: NodeJS.WritableStream;
|
|
9
|
+
}
|
|
10
|
+
export interface ClaudeResult {
|
|
11
|
+
exitCode: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class ClaudeRunnerError extends Error {
|
|
14
|
+
readonly cause: unknown;
|
|
15
|
+
constructor(cause: unknown, message: string);
|
|
16
|
+
}
|
|
17
|
+
export declare function resolveFlags(env?: NodeJS.ProcessEnv): string;
|
|
18
|
+
export declare function resolveBin(env?: NodeJS.ProcessEnv): string;
|
|
19
|
+
export declare function buildArgv(flags: string, model?: string): string[];
|
|
20
|
+
export declare function runClaude(prompt: string, opts?: RunClaudeOptions): Promise<ClaudeResult>;
|
|
21
|
+
//# sourceMappingURL=claude-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-runner.d.ts","sourceRoot":"","sources":["../../src/lib/claude-runner.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAM7C,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAGxB,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,iBAAkB,SAAQ,KAAK;aACd,KAAK,EAAE,OAAO;gBAAd,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM;CAI5D;AAMD,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAKzE;AAED,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAIvE;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,EAAE,CAMV;AAYD,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA6CvB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// claude-runner — subprocess wrapper around `claude --print`.
|
|
2
|
+
//
|
|
3
|
+
// Exists so the orchestrator can be unit-tested by mocking exactly one module
|
|
4
|
+
// instead of stubbing the `claude` binary. The contract:
|
|
5
|
+
//
|
|
6
|
+
// runClaude(prompt, opts) — spawn `claude --print [flags...]`, pipe the
|
|
7
|
+
// prompt to stdin, forward stdout/stderr to the parent so CloudWatch
|
|
8
|
+
// captures everything. Returns { exitCode } once the child exits.
|
|
9
|
+
//
|
|
10
|
+
// Knobs (read from opts; falls back to env or hard defaults):
|
|
11
|
+
// bin — process binary; default `claude` (override:
|
|
12
|
+
// RALPH_CLAUDE_BIN). Tests inject a stub.
|
|
13
|
+
// flags — extra CLI flags split on whitespace; default
|
|
14
|
+
// `--permission-mode bypassPermissions` (override:
|
|
15
|
+
// RALPH_CLAUDE_FLAGS). RALPH_DEBUG_TRANSCRIPT=1 swaps in the
|
|
16
|
+
// stream-json + --verbose set so the per-instance
|
|
17
|
+
// CloudWatch stream captures every assistant message and
|
|
18
|
+
// tool_use/tool_result.
|
|
19
|
+
// model — passed as `--model <value>` if set. Phase callers pull
|
|
20
|
+
// from RALPH_DISCOVERY_MODEL / RALPH_IMPL_MODEL /
|
|
21
|
+
// RALPH_REVIEW_MODEL.
|
|
22
|
+
//
|
|
23
|
+
// The wrapper does not interpret the prompt or claude's output — it is a
|
|
24
|
+
// thin pipe. Callers branch on exitCode and on the contract files claude
|
|
25
|
+
// writes under /tmp/ralph/.
|
|
26
|
+
import { spawn } from "node:child_process";
|
|
27
|
+
export const MODULE_PREFIX = "claude-runner";
|
|
28
|
+
const DEFAULT_FLAGS = "--permission-mode bypassPermissions";
|
|
29
|
+
const DEBUG_FLAGS = "--permission-mode bypassPermissions --output-format stream-json --verbose";
|
|
30
|
+
export class ClaudeRunnerError extends Error {
|
|
31
|
+
cause;
|
|
32
|
+
constructor(cause, message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.cause = cause;
|
|
35
|
+
this.name = "ClaudeRunnerError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// resolveFlags — picks the flag set per the env contract:
|
|
39
|
+
// RALPH_DEBUG_TRANSCRIPT=1 → DEBUG_FLAGS (stream-json + --verbose)
|
|
40
|
+
// RALPH_CLAUDE_FLAGS set → use as-is
|
|
41
|
+
// else → DEFAULT_FLAGS
|
|
42
|
+
export function resolveFlags(env = process.env) {
|
|
43
|
+
if (env.RALPH_DEBUG_TRANSCRIPT === "1")
|
|
44
|
+
return DEBUG_FLAGS;
|
|
45
|
+
const explicit = env.RALPH_CLAUDE_FLAGS;
|
|
46
|
+
if (explicit && explicit.length > 0)
|
|
47
|
+
return explicit;
|
|
48
|
+
return DEFAULT_FLAGS;
|
|
49
|
+
}
|
|
50
|
+
export function resolveBin(env = process.env) {
|
|
51
|
+
return env.RALPH_CLAUDE_BIN && env.RALPH_CLAUDE_BIN.length > 0
|
|
52
|
+
? env.RALPH_CLAUDE_BIN
|
|
53
|
+
: "claude";
|
|
54
|
+
}
|
|
55
|
+
export function buildArgv(flags, model) {
|
|
56
|
+
const argv = ["--print", ...splitFlags(flags)];
|
|
57
|
+
if (model && model.length > 0) {
|
|
58
|
+
argv.push("--model", model);
|
|
59
|
+
}
|
|
60
|
+
return argv;
|
|
61
|
+
}
|
|
62
|
+
function splitFlags(s) {
|
|
63
|
+
// The bash port used `${RALPH_CLAUDE_FLAGS:-...}` array-splitting, which
|
|
64
|
+
// splits on IFS. We replicate by splitting on runs of whitespace and
|
|
65
|
+
// dropping empty fragments.
|
|
66
|
+
return s
|
|
67
|
+
.split(/[ \t\n]+/)
|
|
68
|
+
.map((t) => t.trim())
|
|
69
|
+
.filter((t) => t.length > 0);
|
|
70
|
+
}
|
|
71
|
+
export async function runClaude(prompt, opts = {}) {
|
|
72
|
+
const env = opts.env ?? process.env;
|
|
73
|
+
const bin = opts.bin ?? resolveBin(env);
|
|
74
|
+
const flags = opts.flags ?? resolveFlags(env);
|
|
75
|
+
const argv = buildArgv(flags, opts.model);
|
|
76
|
+
const stdout = opts.stdout ?? process.stdout;
|
|
77
|
+
const stderr = opts.stderr ?? process.stderr;
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
let child;
|
|
80
|
+
try {
|
|
81
|
+
child = spawn(bin, argv, {
|
|
82
|
+
env: { ...env },
|
|
83
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
reject(new ClaudeRunnerError(err, `${MODULE_PREFIX}: failed to spawn ${bin}: ${err instanceof Error ? err.message : String(err)}`));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
child.on("error", (err) => {
|
|
91
|
+
reject(new ClaudeRunnerError(err, `${MODULE_PREFIX}: ${bin} errored: ${err.message}`));
|
|
92
|
+
});
|
|
93
|
+
child.stdout?.on("data", (chunk) => stdout.write(chunk));
|
|
94
|
+
child.stderr?.on("data", (chunk) => stderr.write(chunk));
|
|
95
|
+
child.on("close", (code) => {
|
|
96
|
+
resolve({ exitCode: code ?? -1 });
|
|
97
|
+
});
|
|
98
|
+
child.stdin?.end(prompt);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=claude-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-runner.js","sourceRoot":"","sources":["../../src/lib/claude-runner.ts"],"names":[],"mappings":"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"}
|