@neriros/ralphy 2.13.2 → 2.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +184 -33
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -56407,7 +56407,7 @@ function log(msg) {
|
|
|
56407
56407
|
// package.json
|
|
56408
56408
|
var package_default = {
|
|
56409
56409
|
name: "@neriros/ralphy",
|
|
56410
|
-
version: "2.13.
|
|
56410
|
+
version: "2.13.4",
|
|
56411
56411
|
description: "An iterative AI task execution framework. Orchestrates multi-phase autonomous work using Claude or Codex engines.",
|
|
56412
56412
|
keywords: [
|
|
56413
56413
|
"agent",
|
|
@@ -56653,8 +56653,6 @@ async function parseArgs(argv) {
|
|
|
56653
56653
|
let expectMaxRuntime = false;
|
|
56654
56654
|
let expectMaxFailures = false;
|
|
56655
56655
|
let expectMaxIterations = false;
|
|
56656
|
-
let expectTimeout = false;
|
|
56657
|
-
let expectPushInterval = false;
|
|
56658
56656
|
let expectLinearTeam = false;
|
|
56659
56657
|
let expectLinearAssignee = false;
|
|
56660
56658
|
let expectPollInterval = false;
|
|
@@ -56717,14 +56715,6 @@ async function parseArgs(argv) {
|
|
|
56717
56715
|
expectMaxIterations = false;
|
|
56718
56716
|
continue;
|
|
56719
56717
|
}
|
|
56720
|
-
if (expectTimeout) {
|
|
56721
|
-
expectTimeout = false;
|
|
56722
|
-
continue;
|
|
56723
|
-
}
|
|
56724
|
-
if (expectPushInterval) {
|
|
56725
|
-
expectPushInterval = false;
|
|
56726
|
-
continue;
|
|
56727
|
-
}
|
|
56728
56718
|
if (expectLinearTeam) {
|
|
56729
56719
|
result2.linearTeam = arg;
|
|
56730
56720
|
expectLinearTeam = false;
|
|
@@ -56794,12 +56784,6 @@ async function parseArgs(argv) {
|
|
|
56794
56784
|
case "--max-iterations":
|
|
56795
56785
|
expectMaxIterations = true;
|
|
56796
56786
|
break;
|
|
56797
|
-
case "--timeout":
|
|
56798
|
-
expectTimeout = true;
|
|
56799
|
-
break;
|
|
56800
|
-
case "--push-interval":
|
|
56801
|
-
expectPushInterval = true;
|
|
56802
|
-
break;
|
|
56803
56787
|
case "--unlimited":
|
|
56804
56788
|
result2.maxIterations = 0;
|
|
56805
56789
|
break;
|
|
@@ -69479,6 +69463,10 @@ var HOST = "https://eu.i.posthog.com";
|
|
|
69479
69463
|
var enabled = process.env["RALPH_TELEMETRY"] !== "0";
|
|
69480
69464
|
var client = null;
|
|
69481
69465
|
var distinctId = "anonymous";
|
|
69466
|
+
var defaultProps = {};
|
|
69467
|
+
function setDefaultProperties(props) {
|
|
69468
|
+
defaultProps = { ...defaultProps, ...props };
|
|
69469
|
+
}
|
|
69482
69470
|
async function init() {
|
|
69483
69471
|
if (!enabled)
|
|
69484
69472
|
return;
|
|
@@ -69497,7 +69485,8 @@ async function init() {
|
|
|
69497
69485
|
});
|
|
69498
69486
|
}
|
|
69499
69487
|
function capture(event, properties) {
|
|
69500
|
-
|
|
69488
|
+
const merged = { ...defaultProps, ...properties };
|
|
69489
|
+
client?.capture({ distinctId, event, properties: merged });
|
|
69501
69490
|
}
|
|
69502
69491
|
async function shutdown() {
|
|
69503
69492
|
if (client)
|
|
@@ -69889,10 +69878,16 @@ function useLoop(opts) {
|
|
|
69889
69878
|
const result2 = `failed:exit-${engineResult.exitCode}`;
|
|
69890
69879
|
updateStateIteration(stateDir, result2, iterStart, opts.engine, opts.model, engineResult.usage);
|
|
69891
69880
|
if (failure.shouldStop || engineResult.rateLimited) {
|
|
69881
|
+
capture("engine_rate_limited", { exit_code: engineResult.exitCode, iteration: iter });
|
|
69892
69882
|
finalStopReason = "rateLimited";
|
|
69893
69883
|
setStopReason("rateLimited");
|
|
69894
69884
|
break;
|
|
69895
69885
|
}
|
|
69886
|
+
capture("iteration_failed", {
|
|
69887
|
+
exit_code: engineResult.exitCode,
|
|
69888
|
+
iteration: iter,
|
|
69889
|
+
consecutive_failures: consFailures + 1
|
|
69890
|
+
});
|
|
69896
69891
|
if (result2 === lastResult) {
|
|
69897
69892
|
consFailures++;
|
|
69898
69893
|
} else {
|
|
@@ -69921,7 +69916,9 @@ function useLoop(opts) {
|
|
|
69921
69916
|
await sleep(opts.delay);
|
|
69922
69917
|
}
|
|
69923
69918
|
} catch (err) {
|
|
69919
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
69924
69920
|
addInfo(`Engine error: ${err}`);
|
|
69921
|
+
capture("engine_error", { iteration: iter, error: message });
|
|
69925
69922
|
break;
|
|
69926
69923
|
}
|
|
69927
69924
|
}
|
|
@@ -70206,23 +70203,145 @@ var RalphyConfigSchema = exports_external.object({
|
|
|
70206
70203
|
model: "opus",
|
|
70207
70204
|
linear: { postComments: true, updateEveryIterations: 10, indicators: {} }
|
|
70208
70205
|
});
|
|
70206
|
+
function stripJsonComments(text) {
|
|
70207
|
+
return text.replace(/\/\/[^\n]*/g, "");
|
|
70208
|
+
}
|
|
70209
70209
|
async function loadRalphyConfig(projectRoot) {
|
|
70210
70210
|
const path = join10(projectRoot, "ralphy.config.json");
|
|
70211
70211
|
const file = Bun.file(path);
|
|
70212
70212
|
if (!await file.exists()) {
|
|
70213
70213
|
return RalphyConfigSchema.parse({});
|
|
70214
70214
|
}
|
|
70215
|
-
const
|
|
70215
|
+
const text = await file.text();
|
|
70216
|
+
const raw = JSON.parse(stripJsonComments(text));
|
|
70216
70217
|
return RalphyConfigSchema.parse(raw);
|
|
70217
70218
|
}
|
|
70219
|
+
var DEFAULT_CONFIG_TEMPLATE = `{
|
|
70220
|
+
// How many tasks to run in parallel.
|
|
70221
|
+
"concurrency": 1,
|
|
70222
|
+
|
|
70223
|
+
// Seconds between polls for new Linear issues (agent mode).
|
|
70224
|
+
"pollIntervalSeconds": 60,
|
|
70225
|
+
|
|
70226
|
+
// Maximum iterations per task. 0 = unlimited.
|
|
70227
|
+
"maxIterationsPerTask": 0,
|
|
70228
|
+
|
|
70229
|
+
// Maximum cost in USD per task. 0 = unlimited.
|
|
70230
|
+
"maxCostUsdPerTask": 0,
|
|
70231
|
+
|
|
70232
|
+
// Maximum wall-clock minutes per task. 0 = unlimited.
|
|
70233
|
+
"maxRuntimeMinutesPerTask": 0,
|
|
70234
|
+
|
|
70235
|
+
// Stop a task after this many consecutive identical failures.
|
|
70236
|
+
"maxConsecutiveFailuresPerTask": 5,
|
|
70237
|
+
|
|
70238
|
+
// Seconds to wait between loop iterations (throttle).
|
|
70239
|
+
"iterationDelaySeconds": 0,
|
|
70240
|
+
|
|
70241
|
+
// Log the raw engine stream to stdout.
|
|
70242
|
+
"logRawStream": false,
|
|
70243
|
+
|
|
70244
|
+
// Pass --verbose to the ralph task sub-process.
|
|
70245
|
+
"taskVerbose": false,
|
|
70246
|
+
|
|
70247
|
+
// Run each task in an isolated git worktree.
|
|
70248
|
+
"useWorktree": false,
|
|
70249
|
+
|
|
70250
|
+
// Delete the worktree after a successful task.
|
|
70251
|
+
"cleanupWorktreeOnSuccess": false,
|
|
70252
|
+
|
|
70253
|
+
// Shell script to run inside the worktree before the task starts.
|
|
70254
|
+
// "setupScript": "bun install",
|
|
70255
|
+
|
|
70256
|
+
// Shell script to run inside the worktree after the task finishes.
|
|
70257
|
+
// "teardownScript": "bun run lint",
|
|
70258
|
+
|
|
70259
|
+
// Extra text appended to every task prompt.
|
|
70260
|
+
// "appendPrompt": "Always run tests before finishing.",
|
|
70261
|
+
|
|
70262
|
+
// Open a pull request after a task succeeds.
|
|
70263
|
+
"createPrOnSuccess": false,
|
|
70264
|
+
|
|
70265
|
+
// Base branch for pull requests.
|
|
70266
|
+
"prBaseBranch": "main",
|
|
70267
|
+
|
|
70268
|
+
// Let the agent attempt to fix CI failures after a PR is created.
|
|
70269
|
+
"fixCiOnFailure": false,
|
|
70270
|
+
|
|
70271
|
+
// Maximum number of CI-fix attempts per task.
|
|
70272
|
+
"maxCiFixAttempts": 5,
|
|
70273
|
+
|
|
70274
|
+
// Seconds between CI status polls.
|
|
70275
|
+
"ciPollIntervalSeconds": 30,
|
|
70276
|
+
|
|
70277
|
+
// Underlying engine: "claude" or "codex".
|
|
70278
|
+
"engine": "claude",
|
|
70279
|
+
|
|
70280
|
+
// Model tier: "haiku", "sonnet", or "opus".
|
|
70281
|
+
"model": "opus",
|
|
70282
|
+
|
|
70283
|
+
"linear": {
|
|
70284
|
+
// Linear team key to filter issues (e.g. "ENG"). Omit to match all teams.
|
|
70285
|
+
// "team": "ENG",
|
|
70286
|
+
|
|
70287
|
+
// Linear user to filter issues. Can be an email address or user ID.
|
|
70288
|
+
// Omit to match issues regardless of assignee.
|
|
70289
|
+
// "assignee": "dev@example.com",
|
|
70290
|
+
|
|
70291
|
+
// Post progress comments on the Linear issue while a task is running.
|
|
70292
|
+
"postComments": true,
|
|
70293
|
+
|
|
70294
|
+
// Post a progress update every N iterations. 0 disables. Requires postComments.
|
|
70295
|
+
"updateEveryIterations": 10,
|
|
70296
|
+
|
|
70297
|
+
// ---------------------------------------------------------------------------
|
|
70298
|
+
// Linear indicators \u2014 COMMENTED OUT BY DEFAULT
|
|
70299
|
+
//
|
|
70300
|
+
// Indicators map Ralph lifecycle events to Linear labels/statuses.
|
|
70301
|
+
// WARNING: Activating indicators will query AND mutate your Linear workspace.
|
|
70302
|
+
// Labels or statuses that do not already exist may be created automatically.
|
|
70303
|
+
// Review every value against your actual Linear workspace before enabling,
|
|
70304
|
+
// then replace the empty object below with the full indicators block.
|
|
70305
|
+
//
|
|
70306
|
+
// To activate, replace "indicators": {} with:
|
|
70307
|
+
//
|
|
70308
|
+
// "indicators": {
|
|
70309
|
+
// // Issues to pick up (any-of filter \u2014 Ralph will start working on these).
|
|
70310
|
+
// "getTodo": { "filter": [{ "type": "status", "value": "Todo" }] },
|
|
70311
|
+
//
|
|
70312
|
+
// // Issues already in flight (resume after restart).
|
|
70313
|
+
// "getInProgress": { "filter": [{ "type": "label", "value": "ralph:in-progress" }] },
|
|
70314
|
+
//
|
|
70315
|
+
// // Issues whose PR has a merge conflict (Ralph will attempt a re-fix run).
|
|
70316
|
+
// "getConflicted": { "filter": [{ "type": "label", "value": "ralph:conflict" }] },
|
|
70317
|
+
//
|
|
70318
|
+
// // Applied when Ralph picks up an issue.
|
|
70319
|
+
// "setInProgress": { "type": "label", "value": "ralph:in-progress" },
|
|
70320
|
+
//
|
|
70321
|
+
// // Applied on clean success.
|
|
70322
|
+
// "setDone": { "type": "status", "value": "In Review" },
|
|
70323
|
+
//
|
|
70324
|
+
// // Applied when the task exits with an error (quarantine signal).
|
|
70325
|
+
// "setError": { "type": "label", "value": "ralph:error" },
|
|
70326
|
+
//
|
|
70327
|
+
// // Applied when a PR merge conflict is detected.
|
|
70328
|
+
// "setConflicted": { "type": "label", "value": "ralph:conflict" },
|
|
70329
|
+
//
|
|
70330
|
+
// // Label-only marker(s) removed once the conflict is fixed.
|
|
70331
|
+
// // Note: only label-typed markers are valid here \u2014 status removal is not supported.
|
|
70332
|
+
// "clearConflicted": { "type": "label", "value": "ralph:conflict" }
|
|
70333
|
+
// }
|
|
70334
|
+
// ---------------------------------------------------------------------------
|
|
70335
|
+
"indicators": {}
|
|
70336
|
+
}
|
|
70337
|
+
}
|
|
70338
|
+
`;
|
|
70218
70339
|
async function ensureRalphyConfig(projectRoot) {
|
|
70219
70340
|
const path = join10(projectRoot, "ralphy.config.json");
|
|
70220
70341
|
const file = Bun.file(path);
|
|
70221
70342
|
if (await file.exists())
|
|
70222
70343
|
return path;
|
|
70223
|
-
|
|
70224
|
-
await Bun.write(path, JSON.stringify(defaults2, null, 2) + `
|
|
70225
|
-
`);
|
|
70344
|
+
await Bun.write(path, DEFAULT_CONFIG_TEMPLATE);
|
|
70226
70345
|
return path;
|
|
70227
70346
|
}
|
|
70228
70347
|
|
|
@@ -70469,6 +70588,7 @@ class AgentCoordinator {
|
|
|
70469
70588
|
]);
|
|
70470
70589
|
} catch (err) {
|
|
70471
70590
|
this.deps.onLog(`! Linear poll failed: ${err.message}`, "red");
|
|
70591
|
+
capture("agent_linear_poll_failed", { error: err.message });
|
|
70472
70592
|
return { found: 0, added: 0 };
|
|
70473
70593
|
}
|
|
70474
70594
|
const queuedIds = new Set(this.queue.map((q) => q.issue.id));
|
|
@@ -70593,10 +70713,16 @@ class AgentCoordinator {
|
|
|
70593
70713
|
const alreadyNotified = this.conflictNotified.has(issue.id);
|
|
70594
70714
|
if (alreadyNotified)
|
|
70595
70715
|
continue;
|
|
70716
|
+
capture("agent_conflict_detected", { issue_identifier: issue.identifier });
|
|
70596
70717
|
try {
|
|
70597
70718
|
await this.deps.applyIndicator(issue, this.opts.setConflicted);
|
|
70598
70719
|
} catch (err) {
|
|
70599
70720
|
this.deps.onLog(`! Linear setConflicted failed for ${issue.identifier}: ${err.message}`, "red");
|
|
70721
|
+
capture("agent_indicator_failed", {
|
|
70722
|
+
indicator: "setConflicted",
|
|
70723
|
+
issue_identifier: issue.identifier,
|
|
70724
|
+
error: err.message
|
|
70725
|
+
});
|
|
70600
70726
|
continue;
|
|
70601
70727
|
}
|
|
70602
70728
|
this.conflictNotified.add(issue.id);
|
|
@@ -70627,6 +70753,11 @@ class AgentCoordinator {
|
|
|
70627
70753
|
} catch (err) {
|
|
70628
70754
|
this.pendingIds.delete(issue.id);
|
|
70629
70755
|
this.deps.onLog(`! prepare(${mode}) failed for ${issue.identifier}: ${err.message}`, "red");
|
|
70756
|
+
capture("agent_prepare_failed", {
|
|
70757
|
+
spawn_mode: mode,
|
|
70758
|
+
issue_identifier: issue.identifier,
|
|
70759
|
+
error: err.message
|
|
70760
|
+
});
|
|
70630
70761
|
this.spawnNext();
|
|
70631
70762
|
return;
|
|
70632
70763
|
}
|
|
@@ -70639,6 +70770,11 @@ class AgentCoordinator {
|
|
|
70639
70770
|
await this.deps.applyIndicator(issue, this.opts.setInProgress);
|
|
70640
70771
|
} catch (err) {
|
|
70641
70772
|
this.deps.onLog(`! Linear setInProgress failed for ${issue.identifier}: ${err.message}`, "yellow");
|
|
70773
|
+
capture("agent_indicator_failed", {
|
|
70774
|
+
indicator: "setInProgress",
|
|
70775
|
+
issue_identifier: issue.identifier,
|
|
70776
|
+
error: err.message
|
|
70777
|
+
});
|
|
70642
70778
|
}
|
|
70643
70779
|
}
|
|
70644
70780
|
if (mode === "fresh" && this.opts.postComments !== false) {
|
|
@@ -70670,6 +70806,10 @@ class AgentCoordinator {
|
|
|
70670
70806
|
};
|
|
70671
70807
|
this.workers.push(worker);
|
|
70672
70808
|
this.pendingIds.delete(issue.id);
|
|
70809
|
+
capture("agent_worker_spawned", {
|
|
70810
|
+
spawn_mode: mode,
|
|
70811
|
+
issue_identifier: issue.identifier
|
|
70812
|
+
});
|
|
70673
70813
|
this.deps.onWorkersChanged();
|
|
70674
70814
|
handle.exited.then(async (code) => {
|
|
70675
70815
|
const idx = this.workers.indexOf(worker);
|
|
@@ -70677,6 +70817,12 @@ class AgentCoordinator {
|
|
|
70677
70817
|
this.workers.splice(idx, 1);
|
|
70678
70818
|
const ok = code === 0;
|
|
70679
70819
|
this.deps.onLog(`${ok ? "\u2713" : "\u2717"} ${issue.identifier} \u2192 ${prep.changeName} exited (code ${code})`, ok ? "green" : "red");
|
|
70820
|
+
capture("agent_worker_exited", {
|
|
70821
|
+
spawn_mode: mode,
|
|
70822
|
+
issue_identifier: issue.identifier,
|
|
70823
|
+
exit_code: code,
|
|
70824
|
+
ok
|
|
70825
|
+
});
|
|
70680
70826
|
await this.notifyExited(issue, prep.changeName, code, mode);
|
|
70681
70827
|
this.deps.onWorkersChanged();
|
|
70682
70828
|
this.spawnNext();
|
|
@@ -70701,6 +70847,11 @@ class AgentCoordinator {
|
|
|
70701
70847
|
await this.deps.removeIndicator(issue, this.opts.clearConflicted);
|
|
70702
70848
|
} catch (err) {
|
|
70703
70849
|
this.deps.onLog(`! Linear clearConflicted failed for ${issue.identifier}: ${err.message}`, "red");
|
|
70850
|
+
capture("agent_indicator_failed", {
|
|
70851
|
+
indicator: "clearConflicted",
|
|
70852
|
+
issue_identifier: issue.identifier,
|
|
70853
|
+
error: err.message
|
|
70854
|
+
});
|
|
70704
70855
|
}
|
|
70705
70856
|
}
|
|
70706
70857
|
this.conflictNotified.delete(issue.id);
|
|
@@ -70709,6 +70860,11 @@ class AgentCoordinator {
|
|
|
70709
70860
|
await this.deps.applyIndicator(issue, this.opts.setDone);
|
|
70710
70861
|
} catch (err) {
|
|
70711
70862
|
this.deps.onLog(`! Linear setDone failed for ${issue.identifier}: ${err.message}`, "red");
|
|
70863
|
+
capture("agent_indicator_failed", {
|
|
70864
|
+
indicator: "setDone",
|
|
70865
|
+
issue_identifier: issue.identifier,
|
|
70866
|
+
error: err.message
|
|
70867
|
+
});
|
|
70712
70868
|
}
|
|
70713
70869
|
}
|
|
70714
70870
|
} else if (this.opts.setError) {
|
|
@@ -70716,6 +70872,11 @@ class AgentCoordinator {
|
|
|
70716
70872
|
await this.deps.applyIndicator(issue, this.opts.setError);
|
|
70717
70873
|
} catch (err) {
|
|
70718
70874
|
this.deps.onLog(`! Linear setError failed for ${issue.identifier}: ${err.message}`, "red");
|
|
70875
|
+
capture("agent_indicator_failed", {
|
|
70876
|
+
indicator: "setError",
|
|
70877
|
+
issue_identifier: issue.identifier,
|
|
70878
|
+
error: err.message
|
|
70879
|
+
});
|
|
70719
70880
|
}
|
|
70720
70881
|
}
|
|
70721
70882
|
}
|
|
@@ -71892,17 +72053,6 @@ PR: ${prUrl}` : ""
|
|
|
71892
72053
|
postComments: cfg.linear.postComments,
|
|
71893
72054
|
commentEveryIterations: cfg.linear.updateEveryIterations
|
|
71894
72055
|
});
|
|
71895
|
-
(async () => {
|
|
71896
|
-
const legacy = Bun.file(projectLayout(projectRoot).agentStateFile);
|
|
71897
|
-
if (await legacy.exists()) {
|
|
71898
|
-
onLog(" legacy .ralph/agent-state.json detected \u2014 Linear is now the source of truth; deleting", "gray");
|
|
71899
|
-
try {
|
|
71900
|
-
await legacy.delete();
|
|
71901
|
-
} catch (err) {
|
|
71902
|
-
onLog(`! failed to delete legacy agent-state.json: ${err.message}`, "yellow");
|
|
71903
|
-
}
|
|
71904
|
-
}
|
|
71905
|
-
})();
|
|
71906
72056
|
const filterDesc = describeIndicators(indicators, team, assignee);
|
|
71907
72057
|
return {
|
|
71908
72058
|
coord,
|
|
@@ -72457,6 +72607,7 @@ try {
|
|
|
72457
72607
|
printHelp();
|
|
72458
72608
|
process.exit(1);
|
|
72459
72609
|
}
|
|
72610
|
+
setDefaultProperties({ mode: args.mode, engine: args.engine, model: args.model });
|
|
72460
72611
|
capture("command_run", { mode: args.mode, engine: args.engine, model: args.model });
|
|
72461
72612
|
try {
|
|
72462
72613
|
const projectRoot = await findProjectRoot();
|