@neriros/ralphy 2.10.2 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli/index.js +64 -28
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -50837,8 +50837,8 @@ var require_axios = __commonJS((exports, module) => {
50837
50837
  });
50838
50838
 
50839
50839
  // apps/cli/src/index.ts
50840
- import { resolve, join as join17, dirname as dirname4 } from "path";
50841
- import { exists as exists2, mkdir as mkdir3, rm } from "fs/promises";
50840
+ import { resolve, join as join17, dirname as dirname5 } from "path";
50841
+ import { exists as exists2, mkdir as mkdir4, rm } from "fs/promises";
50842
50842
 
50843
50843
  // node_modules/.bun/ink@5.2.1+1f88f629f0141b18/node_modules/ink/build/render.js
50844
50844
  import { Stream } from "stream";
@@ -56407,7 +56407,7 @@ function log(msg) {
56407
56407
  // package.json
56408
56408
  var package_default = {
56409
56409
  name: "@neriros/ralphy",
56410
- version: "2.10.2",
56410
+ version: "2.11.1",
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",
@@ -64894,7 +64894,9 @@ var {spawn: bunSpawn } = globalThis.Bun;
64894
64894
  var spawn = bunSpawn;
64895
64895
 
64896
64896
  // packages/engine/src/engine.ts
64897
- import { mkdtemp, unlink } from "fs/promises";
64897
+ import { createWriteStream } from "fs";
64898
+ import { mkdtemp, unlink, mkdir } from "fs/promises";
64899
+ import { dirname as dirname2 } from "path";
64898
64900
  import { join as join5 } from "path";
64899
64901
  import { tmpdir } from "os";
64900
64902
 
@@ -65711,6 +65713,21 @@ async function runEngine(opts) {
65711
65713
  stdin.write(new TextEncoder().encode(prompt));
65712
65714
  await stdin.flush();
65713
65715
  stdin.end();
65716
+ let rawWriter = null;
65717
+ if (opts.logFlag && opts.logFile) {
65718
+ await mkdir(dirname2(opts.logFile), { recursive: true });
65719
+ rawWriter = createWriteStream(opts.logFile, { flags: "a" });
65720
+ }
65721
+ const writeRaw = (line) => {
65722
+ if (rawWriter)
65723
+ rawWriter.write(line + `
65724
+ `);
65725
+ };
65726
+ const closeRaw = () => new Promise((resolve) => {
65727
+ if (!rawWriter)
65728
+ return resolve();
65729
+ rawWriter.end(resolve);
65730
+ });
65714
65731
  const emit = opts.onFeedEvent;
65715
65732
  function emitEvent(event) {
65716
65733
  if (emit) {
@@ -65745,6 +65762,7 @@ async function runEngine(opts) {
65745
65762
  usage: null
65746
65763
  };
65747
65764
  for await (const line of streamLines(stdout)) {
65765
+ writeRaw(line);
65748
65766
  if (sessionId === null) {
65749
65767
  try {
65750
65768
  const parsed = JSON.parse(line);
@@ -65772,6 +65790,7 @@ async function runEngine(opts) {
65772
65790
  pendingTools: 0
65773
65791
  };
65774
65792
  for await (const line of streamLines(stdout)) {
65793
+ writeRaw(line);
65775
65794
  for (const event of parseCodexLine(line, codexState)) {
65776
65795
  emitEvent(event);
65777
65796
  }
@@ -65779,12 +65798,14 @@ async function runEngine(opts) {
65779
65798
  if (proc.stderr) {
65780
65799
  const stderr = proc.stderr;
65781
65800
  for await (const line of streamLines(stderr)) {
65801
+ writeRaw(line);
65782
65802
  for (const event of parseCodexLine(line, codexState)) {
65783
65803
  emitEvent(event);
65784
65804
  }
65785
65805
  }
65786
65806
  }
65787
65807
  }
65808
+ await closeRaw();
65788
65809
  const exitCode = await proc.exited;
65789
65810
  const wasIntentionalKill = (exitCode === 143 || exitCode === 137) && (usage !== null || aborted);
65790
65811
  const normalizedExitCode = wasIntentionalKill ? 0 : exitCode;
@@ -65843,7 +65864,7 @@ function commitTaskDir(taskDir, message) {
65843
65864
  }
65844
65865
 
65845
65866
  // node_modules/.bun/posthog-node@4.18.0/node_modules/posthog-node/lib/node/index.mjs
65846
- import { posix, dirname as dirname2, sep } from "path";
65867
+ import { posix, dirname as dirname3, sep } from "path";
65847
65868
  import { createReadStream } from "fs";
65848
65869
  import { createInterface } from "readline";
65849
65870
  var NAME = "posthog-node";
@@ -66423,7 +66444,7 @@ class ErrorTracking {
66423
66444
  return !this.client.isDisabled && this._exceptionAutocaptureEnabled;
66424
66445
  }
66425
66446
  }
66426
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname2(process.argv[1]) : process.cwd(), isWindows3 = sep === "\\") {
66447
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname3(process.argv[1]) : process.cwd(), isWindows3 = sep === "\\") {
66427
66448
  const normalizedBase = isWindows3 ? normalizeWindowsPath(basePath) : basePath;
66428
66449
  return (filename) => {
66429
66450
  if (!filename) {
@@ -69460,11 +69481,16 @@ var STEERING_MAX_LINES = 20;
69460
69481
  function extractFirstUncheckedSection(tasksContent) {
69461
69482
  const sections = tasksContent.split(/(?=^## )/m);
69462
69483
  for (const section of sections) {
69463
- if (/^- \[ \]/m.test(section))
69484
+ if (/^## /m.test(section) && /^- \[ \]/m.test(section))
69464
69485
  return section.trim();
69465
69486
  }
69487
+ if (/^- \[ \]/m.test(tasksContent))
69488
+ return tasksContent.trim();
69466
69489
  return null;
69467
69490
  }
69491
+ function countUncheckedTasks(tasksContent) {
69492
+ return (tasksContent.match(/^- \[ \]/gm) ?? []).length;
69493
+ }
69468
69494
  function allTasksCompleted(tasksContent) {
69469
69495
  return !/^- \[ \]/m.test(tasksContent);
69470
69496
  }
@@ -69504,6 +69530,9 @@ function buildTaskPrompt(state, taskDir) {
69504
69530
  `;
69505
69531
  prompt += `---
69506
69532
 
69533
+ `;
69534
+ prompt += `**Tracking progress**: as you finish each item above, edit ` + `\`${join7(taskDir, "tasks.md")}\` and change its \`- [ ]\` to ` + `\`- [x]\` in the same commit. The loop reads this file between ` + `iterations and stops when no \`- [ ]\` items remain \u2014 if you do ` + `not tick the box, the next iteration will repeat this task.
69535
+
69507
69536
  `;
69508
69537
  }
69509
69538
  } else if (state.prompt) {
@@ -69723,6 +69752,10 @@ function useLoop(opts) {
69723
69752
  break;
69724
69753
  }
69725
69754
  const tasksContent = storage.read(join8(tasksDir, "tasks.md"));
69755
+ if (tasksContent !== null) {
69756
+ const remaining = countUncheckedTasks(tasksContent);
69757
+ addInfo(`tasks.md: ${remaining} unchecked item${remaining === 1 ? "" : "s"} remaining`);
69758
+ }
69726
69759
  if (tasksContent !== null && allTasksCompleted(tasksContent)) {
69727
69760
  addInfo("All tasks completed \u2014 archiving change.");
69728
69761
  currentState = {
@@ -69758,6 +69791,7 @@ function useLoop(opts) {
69758
69791
  model: opts.model,
69759
69792
  prompt,
69760
69793
  logFlag: opts.log,
69794
+ logFile: join8(stateDir, "log.json"),
69761
69795
  taskDir: tasksDir,
69762
69796
  interactive: false,
69763
69797
  onFeedEvent: addFeedEvent,
@@ -69780,6 +69814,7 @@ function useLoop(opts) {
69780
69814
  model: opts.model,
69781
69815
  prompt: buildSteeringPrompt(steerMessage),
69782
69816
  logFlag: opts.log,
69817
+ logFile: join8(stateDir, "log.json"),
69783
69818
  taskDir: tasksDir,
69784
69819
  onFeedEvent: addResumeFeedEvent,
69785
69820
  signal: resumeController.signal,
@@ -70262,7 +70297,7 @@ async function writeAgentState(projectRoot, state) {
70262
70297
 
70263
70298
  // apps/cli/src/agent/scaffold.ts
70264
70299
  import { join as join11 } from "path";
70265
- import { mkdir } from "fs/promises";
70300
+ import { mkdir as mkdir2 } from "fs/promises";
70266
70301
  function changeNameForIssue(issue) {
70267
70302
  const slug = issue.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
70268
70303
  return slug ? `${issue.identifier.toLowerCase()}-${slug}` : issue.identifier.toLowerCase();
@@ -70271,9 +70306,9 @@ async function scaffoldChangeForIssue(tasksDir, statesDir, issue, comments = [],
70271
70306
  const name = changeNameForIssue(issue);
70272
70307
  const changeDir = join11(tasksDir, name);
70273
70308
  const stateDir = join11(statesDir, name);
70274
- await mkdir(changeDir, { recursive: true });
70275
- await mkdir(join11(changeDir, "specs"), { recursive: true });
70276
- await mkdir(stateDir, { recursive: true });
70309
+ await mkdir2(changeDir, { recursive: true });
70310
+ await mkdir2(join11(changeDir, "specs"), { recursive: true });
70311
+ await mkdir2(stateDir, { recursive: true });
70277
70312
  const commentsBlock = comments.length > 0 ? [
70278
70313
  "",
70279
70314
  "## Linear comments",
@@ -70308,6 +70343,8 @@ async function scaffoldChangeForIssue(tasksDir, statesDir, issue, comments = [],
70308
70343
  const tasks = [
70309
70344
  `# Tasks for ${issue.identifier}`,
70310
70345
  "",
70346
+ "## Subtasks",
70347
+ "",
70311
70348
  `- [ ] Read the Linear issue at ${issue.url} and break it into concrete subtasks`,
70312
70349
  `- [ ] Implement the changes described in proposal.md`,
70313
70350
  `- [ ] Add or update tests covering the new behavior`,
@@ -70851,15 +70888,14 @@ var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
70851
70888
  import { join as join14 } from "path";
70852
70889
  import { exists } from "fs/promises";
70853
70890
  async function seedWorktreeMcpConfig(projectRoot, worktreeCwd) {
70854
- const src = join14(projectRoot, ".mcp.json");
70855
- if (!await exists(src))
70856
- return;
70857
70891
  const dst = join14(worktreeCwd, ".mcp.json");
70858
- if (await exists(dst))
70892
+ const src = join14(projectRoot, ".mcp.json");
70893
+ const source = await exists(dst) ? dst : await exists(src) ? src : null;
70894
+ if (!source)
70859
70895
  return;
70860
70896
  let parsed;
70861
70897
  try {
70862
- parsed = await Bun.file(src).json();
70898
+ parsed = await Bun.file(source).json();
70863
70899
  } catch {
70864
70900
  return;
70865
70901
  }
@@ -71480,11 +71516,11 @@ ${check.unpushedCommits}`, "yellow");
71480
71516
  }
71481
71517
 
71482
71518
  // packages/openspec/src/openspec-change-store.ts
71483
- import { join as join15, dirname as dirname3 } from "path";
71484
- import { readdir, mkdir as mkdir2 } from "fs/promises";
71519
+ import { join as join15, dirname as dirname4 } from "path";
71520
+ import { readdir, mkdir as mkdir3 } from "fs/promises";
71485
71521
  function resolveOpenspecBin() {
71486
71522
  const pkgJsonPath = Bun.resolveSync("@fission-ai/openspec/package.json", import.meta.dir);
71487
- return join15(dirname3(pkgJsonPath), "bin", "openspec.js");
71523
+ return join15(dirname4(pkgJsonPath), "bin", "openspec.js");
71488
71524
  }
71489
71525
  function runOpenspec(args, options = {}) {
71490
71526
  const stdio = options.inherit ? ["inherit", "inherit", "inherit"] : ["ignore", "pipe", "pipe"];
@@ -71542,7 +71578,7 @@ class OpenSpecChangeStore {
71542
71578
  }
71543
71579
  async writeTaskList(name, content) {
71544
71580
  const path = join15("openspec", "changes", name, "tasks.md");
71545
- await mkdir2(dirname3(path), { recursive: true });
71581
+ await mkdir3(dirname4(path), { recursive: true });
71546
71582
  await Bun.write(path, content);
71547
71583
  }
71548
71584
  async appendSteering(name, message) {
@@ -71553,7 +71589,7 @@ class OpenSpecChangeStore {
71553
71589
 
71554
71590
  ${existing.trimStart()}` : `${message}
71555
71591
  `;
71556
- await mkdir2(dirname3(path), { recursive: true });
71592
+ await mkdir3(dirname4(path), { recursive: true });
71557
71593
  await Bun.write(path, updated);
71558
71594
  }
71559
71595
  async readSection(name, artifact, heading) {
@@ -71739,8 +71775,8 @@ try {
71739
71775
  const statesDir = join17(projectRoot, ".ralph", "tasks");
71740
71776
  const tasksDir = join17(projectRoot, "openspec", "changes");
71741
71777
  if (args.mode === "init") {
71742
- await mkdir3(statesDir, { recursive: true });
71743
- const openspecBin = join17(dirname4(Bun.resolveSync("@fission-ai/openspec/package.json", import.meta.dir)), "bin", "openspec.js");
71778
+ await mkdir4(statesDir, { recursive: true });
71779
+ const openspecBin = join17(dirname5(Bun.resolveSync("@fission-ai/openspec/package.json", import.meta.dir)), "bin", "openspec.js");
71744
71780
  Bun.spawnSync({
71745
71781
  cmd: [process.execPath, openspecBin, "init", "--tools", "none", "--force"],
71746
71782
  stdio: ["inherit", "inherit", "inherit"],
@@ -71816,13 +71852,13 @@ try {
71816
71852
  process.exit(0);
71817
71853
  }
71818
71854
  if (args.mode === "task" && args.name) {
71819
- await mkdir3(join17(statesDir, args.name), { recursive: true });
71820
- await mkdir3(join17(tasksDir, args.name), { recursive: true });
71855
+ await mkdir4(join17(statesDir, args.name), { recursive: true });
71856
+ await mkdir4(join17(tasksDir, args.name), { recursive: true });
71821
71857
  }
71822
71858
  if (args.mode === "agent") {
71823
- await mkdir3(statesDir, { recursive: true });
71824
- await mkdir3(tasksDir, { recursive: true });
71825
- await mkdir3(join17(projectRoot, ".ralph"), { recursive: true });
71859
+ await mkdir4(statesDir, { recursive: true });
71860
+ await mkdir4(tasksDir, { recursive: true });
71861
+ await mkdir4(join17(projectRoot, ".ralph"), { recursive: true });
71826
71862
  }
71827
71863
  await runWithContext(createDefaultContext(), async () => {
71828
71864
  const { waitUntilExit } = render_default(import_react59.createElement(App2, { args, statesDir, tasksDir, projectRoot }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neriros/ralphy",
3
- "version": "2.10.2",
3
+ "version": "2.11.1",
4
4
  "description": "An iterative AI task execution framework. Orchestrates multi-phase autonomous work using Claude or Codex engines.",
5
5
  "keywords": [
6
6
  "agent",