@herbcaudill/ralph 0.4.3 → 0.6.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.
Files changed (53) hide show
  1. package/README.md +3 -14
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +33 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/components/App.d.ts.map +1 -1
  6. package/dist/components/App.js +2 -8
  7. package/dist/components/App.js.map +1 -1
  8. package/dist/components/EventDisplay.d.ts +8 -1
  9. package/dist/components/EventDisplay.d.ts.map +1 -1
  10. package/dist/components/EventDisplay.js +175 -57
  11. package/dist/components/EventDisplay.js.map +1 -1
  12. package/dist/components/EventDisplay.replay.test.js +53 -43
  13. package/dist/components/EventDisplay.replay.test.js.map +1 -1
  14. package/dist/components/EventDisplay.test.js +107 -11
  15. package/dist/components/EventDisplay.test.js.map +1 -1
  16. package/dist/components/FullScreenLayout.d.ts +14 -0
  17. package/dist/components/FullScreenLayout.d.ts.map +1 -0
  18. package/dist/components/FullScreenLayout.js +30 -0
  19. package/dist/components/FullScreenLayout.js.map +1 -0
  20. package/dist/components/Header.d.ts +2 -1
  21. package/dist/components/Header.d.ts.map +1 -1
  22. package/dist/components/Header.js +2 -2
  23. package/dist/components/Header.js.map +1 -1
  24. package/dist/components/InitRalph.js +1 -1
  25. package/dist/components/InitRalph.js.map +1 -1
  26. package/dist/components/IterationRunner.d.ts +3 -1
  27. package/dist/components/IterationRunner.d.ts.map +1 -1
  28. package/dist/components/IterationRunner.js +268 -186
  29. package/dist/components/IterationRunner.js.map +1 -1
  30. package/dist/components/IterationRunner.test.js +6 -6
  31. package/dist/components/IterationRunner.test.js.map +1 -1
  32. package/dist/components/ReplayLog.d.ts.map +1 -1
  33. package/dist/components/ReplayLog.js +7 -8
  34. package/dist/components/ReplayLog.js.map +1 -1
  35. package/dist/index.d.ts +0 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +0 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/lib/addTodo.d.ts +10 -0
  40. package/dist/lib/addTodo.d.ts.map +1 -0
  41. package/dist/lib/addTodo.js +55 -0
  42. package/dist/lib/addTodo.js.map +1 -0
  43. package/dist/lib/formatContentBlock.d.ts +10 -0
  44. package/dist/lib/formatContentBlock.d.ts.map +1 -0
  45. package/dist/lib/formatContentBlock.js +60 -0
  46. package/dist/lib/formatContentBlock.js.map +1 -0
  47. package/dist/lib/useTerminalSize.d.ts +5 -0
  48. package/dist/lib/useTerminalSize.d.ts.map +1 -0
  49. package/dist/lib/useTerminalSize.js +21 -0
  50. package/dist/lib/useTerminalSize.js.map +1 -0
  51. package/package.json +8 -5
  52. package/templates/prompt.md +1 -12
  53. package/templates/progress.md +0 -11
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
2
2
  import { Box, Text, useApp } from "ink";
3
3
  import { readFileSync } from "fs";
4
4
  import { EventDisplay } from "./EventDisplay.js";
5
+ import { FullScreenLayout, useContentHeight } from "./FullScreenLayout.js";
5
6
  export const ReplayLog = ({ filePath }) => {
6
7
  const { exit } = useApp();
7
8
  const [events, setEvents] = useState([]);
@@ -39,13 +40,11 @@ export const ReplayLog = ({ filePath }) => {
39
40
  return (React.createElement(Box, { flexDirection: "column" },
40
41
  React.createElement(Text, { color: "red" }, error)));
41
42
  }
42
- return (React.createElement(Box, { flexDirection: "column" },
43
- React.createElement(Box, { marginBottom: 1 },
44
- React.createElement(Text, { color: "cyan" },
45
- "Replaying: ",
46
- filePath)),
47
- React.createElement(Box, { marginBottom: 1 },
48
- React.createElement(Text, { dimColor: true }, "─".repeat(40))),
49
- React.createElement(EventDisplay, { events: events })));
43
+ const footer = React.createElement(Text, { dimColor: true },
44
+ "Replaying: ",
45
+ filePath);
46
+ const contentHeight = useContentHeight(true);
47
+ return (React.createElement(FullScreenLayout, { title: "Ralph", footer: footer },
48
+ React.createElement(EventDisplay, { events: events, iteration: 1, completedIterations: [], height: contentHeight })));
50
49
  };
51
50
  //# sourceMappingURL=ReplayLog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReplayLog.js","sourceRoot":"","sources":["../../src/components/ReplayLog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAClD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAE,QAAQ,EAAS,EAAE,EAAE;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAA;IACzB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAiC,EAAE,CAAC,CAAA;IACxE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAU,CAAA;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YAC/C,yEAAyE;YACzE,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YAEjE,MAAM,YAAY,GAAmC,EAAE,CAAA;YACvD,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;gBACpC,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;oBAClC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC1B,CAAC;gBAAC,MAAM,CAAC;oBACP,yBAAyB;gBAC3B,CAAC;YACH,CAAC;YAED,SAAS,CAAC,YAAY,CAAC,CAAA;YACvB,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,EAAE,CAAA;gBACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC,EAAE,GAAG,CAAC,CAAA;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC3F,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,EAAE,CAAA;gBACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC,EAAE,GAAG,CAAC,CAAA;QACT,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;IAEpB,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;YACzB,oBAAC,IAAI,IAAC,KAAK,EAAC,KAAK,IAAE,KAAK,CAAQ,CAC5B,CACP,CAAA;IACH,CAAC;IAED,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;QACzB,oBAAC,GAAG,IAAC,YAAY,EAAE,CAAC;YAClB,oBAAC,IAAI,IAAC,KAAK,EAAC,MAAM;;gBAAa,QAAQ,CAAQ,CAC3C;QACN,oBAAC,GAAG,IAAC,YAAY,EAAE,CAAC;YAClB,oBAAC,IAAI,IAAC,QAAQ,UAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAQ,CAClC;QACN,oBAAC,YAAY,IAAC,MAAM,EAAE,MAAM,GAAI,CAC5B,CACP,CAAA;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"ReplayLog.js","sourceRoot":"","sources":["../../src/components/ReplayLog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAClD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAE1E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAE,QAAQ,EAAS,EAAE,EAAE;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAA;IACzB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAiC,EAAE,CAAC,CAAA;IACxE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAU,CAAA;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YAC/C,yEAAyE;YACzE,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YAEjE,MAAM,YAAY,GAAmC,EAAE,CAAA;YACvD,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;gBACpC,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;oBAClC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC1B,CAAC;gBAAC,MAAM,CAAC;oBACP,yBAAyB;gBAC3B,CAAC;YACH,CAAC;YAED,SAAS,CAAC,YAAY,CAAC,CAAA;YACvB,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,EAAE,CAAA;gBACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC,EAAE,GAAG,CAAC,CAAA;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC3F,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,EAAE,CAAA;gBACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC,EAAE,GAAG,CAAC,CAAA;QACT,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;IAEpB,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;YACzB,oBAAC,IAAI,IAAC,KAAK,EAAC,KAAK,IAAE,KAAK,CAAQ,CAC5B,CACP,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,oBAAC,IAAI,IAAC,QAAQ;;QAAa,QAAQ,CAAQ,CAAA;IAC1D,MAAM,aAAa,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAE5C,OAAO,CACL,oBAAC,gBAAgB,IAAC,KAAK,EAAC,OAAO,EAAC,MAAM,EAAE,MAAM;QAC5C,oBAAC,YAAY,IAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,mBAAmB,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,GAAI,CAC7E,CACpB,CAAA;AACH,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- import "./lib/signalHandler.js";
2
1
  export declare const run: () => void;
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,wBAAwB,CAAA;AAE/B,eAAO,MAAM,GAAG,YAEf,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG,YAEf,CAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { program } from "./cli.js";
2
- import "./lib/signalHandler.js"; // Register global SIGINT/SIGTERM handlers
3
2
  export const run = () => {
4
3
  program.parse(process.argv);
5
4
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,OAAO,wBAAwB,CAAA,CAAC,0CAA0C;AAE1E,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;AAC7B,CAAC,CAAA;AAED,yBAAyB;AACzB,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACpD,GAAG,EAAE,CAAA;AACP,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAElC,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;AAC7B,CAAC,CAAA;AAED,yBAAyB;AACzB,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACpD,GAAG,EAAE,CAAA;AACP,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Adds a todo item to the todo.md file and commits just that line.
3
+ * Inserts the todo into the working directory, stages only that line, and commits.
4
+ */
5
+ export declare const addTodo: (description: string, cwd?: string) => void;
6
+ /**
7
+ * Inserts a todo item into the content, right after the "To do" header.
8
+ */
9
+ export declare const insertTodo: (content: string, description: string) => string;
10
+ //# sourceMappingURL=addTodo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addTodo.d.ts","sourceRoot":"","sources":["../../src/lib/addTodo.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,aAAa,MAAM,EAAE,MAAK,MAAsB,KAAG,IAqC1E,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,aAAa,MAAM,KAAG,MAmBjE,CAAA"}
@@ -0,0 +1,55 @@
1
+ import { execSync } from "child_process";
2
+ import { readFileSync, writeFileSync } from "fs";
3
+ import { join } from "path";
4
+ /**
5
+ * Adds a todo item to the todo.md file and commits just that line.
6
+ * Inserts the todo into the working directory, stages only that line, and commits.
7
+ */
8
+ export const addTodo = (description, cwd = process.cwd()) => {
9
+ const todoPath = join(cwd, ".ralph", "todo.md");
10
+ // Read current working directory file and insert the new todo
11
+ const content = readFileSync(todoPath, "utf-8");
12
+ const newContent = insertTodo(content, description);
13
+ // Write updated content to working directory
14
+ writeFileSync(todoPath, newContent);
15
+ // Get what's currently in the index for this file (or HEAD if not staged)
16
+ const indexContent = execSync("git show :0:.ralph/todo.md 2>/dev/null || git show HEAD:.ralph/todo.md", {
17
+ cwd,
18
+ encoding: "utf-8",
19
+ });
20
+ // Create a blob with just the todo added to the index version
21
+ const indexWithTodo = insertTodo(indexContent, description);
22
+ const blobHash = execSync("git hash-object -w --stdin", {
23
+ cwd,
24
+ encoding: "utf-8",
25
+ input: indexWithTodo,
26
+ }).trim();
27
+ // Stage just our change by updating the index to this blob
28
+ execSync(`git update-index --cacheinfo 100644,${blobHash},.ralph/todo.md`, {
29
+ cwd,
30
+ stdio: "pipe",
31
+ });
32
+ // Commit just the staged change
33
+ execSync(`git commit -m "todo: ${description}"`, { cwd, stdio: "pipe" });
34
+ console.log(`✅ added`);
35
+ };
36
+ /**
37
+ * Inserts a todo item into the content, right after the "To do" header.
38
+ */
39
+ export const insertTodo = (content, description) => {
40
+ const lines = content.split("\n");
41
+ const todoHeaderIndex = lines.findIndex(line => /^###?\s*To\s*do/i.test(line));
42
+ if (todoHeaderIndex === -1) {
43
+ // No "To do" section found, add one at the beginning
44
+ return `### To do\n\n- [ ] ${description}\n\n${content}`;
45
+ }
46
+ // Find the first line after the header (skip empty lines)
47
+ let insertIndex = todoHeaderIndex + 1;
48
+ while (insertIndex < lines.length && lines[insertIndex].trim() === "") {
49
+ insertIndex++;
50
+ }
51
+ // Insert the new todo item
52
+ lines.splice(insertIndex, 0, `- [ ] ${description}`);
53
+ return lines.join("\n");
54
+ };
55
+ //# sourceMappingURL=addTodo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addTodo.js","sourceRoot":"","sources":["../../src/lib/addTodo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,WAAmB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE,EAAQ,EAAE;IAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;IAE/C,8DAA8D;IAC9D,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC/C,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IAEnD,6CAA6C;IAC7C,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IAEnC,0EAA0E;IAC1E,MAAM,YAAY,GAAG,QAAQ,CAC3B,wEAAwE,EACxE;QACE,GAAG;QACH,QAAQ,EAAE,OAAO;KAClB,CACF,CAAA;IAED,8DAA8D;IAC9D,MAAM,aAAa,GAAG,UAAU,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;IAC3D,MAAM,QAAQ,GAAG,QAAQ,CAAC,4BAA4B,EAAE;QACtD,GAAG;QACH,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,aAAa;KACrB,CAAC,CAAC,IAAI,EAAE,CAAA;IAET,2DAA2D;IAC3D,QAAQ,CAAC,uCAAuC,QAAQ,iBAAiB,EAAE;QACzE,GAAG;QACH,KAAK,EAAE,MAAM;KACd,CAAC,CAAA;IAEF,gCAAgC;IAChC,QAAQ,CAAC,wBAAwB,WAAW,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAExE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;AACxB,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,WAAmB,EAAU,EAAE;IACzE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,eAAe,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAE9E,IAAI,eAAe,KAAK,CAAC,CAAC,EAAE,CAAC;QAC3B,qDAAqD;QACrD,OAAO,sBAAsB,WAAW,OAAO,OAAO,EAAE,CAAA;IAC1D,CAAC;IAED,0DAA0D;IAC1D,IAAI,WAAW,GAAG,eAAe,GAAG,CAAC,CAAA;IACrC,OAAO,WAAW,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACtE,WAAW,EAAE,CAAA;IACf,CAAC;IAED,2BAA2B;IAC3B,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC,CAAA;IAEpD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ import type { ContentBlock } from "../components/eventToBlocks.js";
2
+ /**
3
+ * Convert a content block to formatted string lines
4
+ */
5
+ export declare const formatContentBlock: (block: ContentBlock) => string[];
6
+ /**
7
+ * Format an iteration header
8
+ */
9
+ export declare const formatIterationHeader: (iteration: number) => string;
10
+ //# sourceMappingURL=formatContentBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatContentBlock.d.ts","sourceRoot":"","sources":["../../src/lib/formatContentBlock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AA8ClE;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,YAAY,KAAG,MAAM,EAQ9D,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAW,MAAM,KAAG,MAEzD,CAAA"}
@@ -0,0 +1,60 @@
1
+ import chalk from "chalk";
2
+ /**
3
+ * Format a text string with markdown-style formatting (bold and inline code)
4
+ */
5
+ const formatText = (content) => {
6
+ let result = "";
7
+ let i = 0;
8
+ let inBold = false;
9
+ let inCode = false;
10
+ while (i < content.length) {
11
+ if (content[i] === "*" && content[i + 1] === "*") {
12
+ inBold = !inBold;
13
+ i += 2;
14
+ }
15
+ else if (content[i] === "`") {
16
+ inCode = !inCode;
17
+ i++;
18
+ }
19
+ else {
20
+ let char = content[i];
21
+ if (inCode) {
22
+ char = chalk.yellow(char);
23
+ }
24
+ else if (inBold) {
25
+ char = chalk.bold(char);
26
+ }
27
+ result += char;
28
+ i++;
29
+ }
30
+ }
31
+ return result;
32
+ };
33
+ /**
34
+ * Format a tool use block as a string
35
+ */
36
+ const formatToolUse = (name, arg) => {
37
+ const formattedName = chalk.blue(name);
38
+ if (arg) {
39
+ return ` ${formattedName} ${chalk.dim(arg)}`;
40
+ }
41
+ return ` ${formattedName}`;
42
+ };
43
+ /**
44
+ * Convert a content block to formatted string lines
45
+ */
46
+ export const formatContentBlock = (block) => {
47
+ if (block.type === "text") {
48
+ const formatted = formatText(block.content);
49
+ // Split into lines, preserving empty lines for paragraph breaks
50
+ return formatted.split("\n");
51
+ }
52
+ return [formatToolUse(block.name, block.arg)];
53
+ };
54
+ /**
55
+ * Format an iteration header
56
+ */
57
+ export const formatIterationHeader = (iteration) => {
58
+ return chalk.cyan.bold(`─── Iteration ${iteration} ───`);
59
+ };
60
+ //# sourceMappingURL=formatContentBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatContentBlock.js","sourceRoot":"","sources":["../../src/lib/formatContentBlock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB;;GAEG;AACH,MAAM,UAAU,GAAG,CAAC,OAAe,EAAU,EAAE;IAC7C,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,IAAI,MAAM,GAAG,KAAK,CAAA;IAElB,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACjD,MAAM,GAAG,CAAC,MAAM,CAAA;YAChB,CAAC,IAAI,CAAC,CAAA;QACR,CAAC;aAAM,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC9B,MAAM,GAAG,CAAC,MAAM,CAAA;YAChB,CAAC,EAAE,CAAA;QACL,CAAC;aAAM,CAAC;YACN,IAAI,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;YAErB,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAC3B,CAAC;iBAAM,IAAI,MAAM,EAAE,CAAC;gBAClB,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACzB,CAAC;YAED,MAAM,IAAI,IAAI,CAAA;YACd,CAAC,EAAE,CAAA;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,GAAY,EAAU,EAAE;IAC3D,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACtC,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,KAAK,aAAa,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/C,CAAC;IACD,OAAO,KAAK,aAAa,EAAE,CAAA;AAC7B,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAmB,EAAY,EAAE;IAClE,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC3C,gEAAgE;QAChE,OAAO,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;IAED,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;AAC/C,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,SAAiB,EAAU,EAAE;IACjE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,SAAS,MAAM,CAAC,CAAA;AAC1D,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ export declare const useTerminalSize: () => {
2
+ columns: number;
3
+ rows: number;
4
+ };
5
+ //# sourceMappingURL=useTerminalSize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTerminalSize.d.ts","sourceRoot":"","sources":["../../src/lib/useTerminalSize.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe;;;CAuB3B,CAAA"}
@@ -0,0 +1,21 @@
1
+ import { useState, useEffect } from "react";
2
+ import { useStdout } from "ink";
3
+ export const useTerminalSize = () => {
4
+ const { stdout } = useStdout();
5
+ const getSize = () => ({
6
+ columns: stdout?.columns ?? 80,
7
+ rows: stdout?.rows ?? 24,
8
+ });
9
+ const [size, setSize] = useState(getSize);
10
+ useEffect(() => {
11
+ const handleResize = () => {
12
+ setSize(getSize());
13
+ };
14
+ stdout?.on("resize", handleResize);
15
+ return () => {
16
+ stdout?.off("resize", handleResize);
17
+ };
18
+ }, [stdout]);
19
+ return size;
20
+ };
21
+ //# sourceMappingURL=useTerminalSize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTerminalSize.js","sourceRoot":"","sources":["../../src/lib/useTerminalSize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AAE/B,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE;IAClC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAA;IAE9B,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,EAAE;QAC9B,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE;KACzB,CAAC,CAAA;IAEF,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAEzC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,YAAY,GAAG,GAAG,EAAE;YACxB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;QACpB,CAAC,CAAA;QAED,MAAM,EAAE,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;QAElC,OAAO,GAAG,EAAE;YACV,MAAM,EAAE,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;QACrC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herbcaudill/ralph",
3
- "version": "0.4.3",
3
+ "version": "0.6.0",
4
4
  "description": "Autonomous AI iteration engine for Claude CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,20 +28,22 @@
28
28
  "url": "https://github.com/HerbCaudill/ralph.git"
29
29
  },
30
30
  "dependencies": {
31
+ "@anthropic-ai/claude-agent-sdk": "^0.2.7",
31
32
  "chalk": "^5.6.2",
32
33
  "commander": "^14.0.2",
33
- "execa": "^9.6.1",
34
34
  "ink": "^6.6.0",
35
35
  "ink-big-text": "^2.0.0",
36
36
  "ink-gradient": "^3.0.0",
37
37
  "ink-select-input": "^6.2.0",
38
38
  "ink-spinner": "^5.0.0",
39
+ "ink-text-input": "^6.0.0",
39
40
  "react": "^19.2.3"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@types/node": "^24.10.1",
43
44
  "@types/react": "^19.2.8",
44
45
  "@vitest/ui": "^4.0.17",
46
+ "execa": "^9.6.1",
45
47
  "ink-testing-library": "^4.0.0",
46
48
  "prettier": "^3.5.3",
47
49
  "tsx": "^4.21.0",
@@ -54,10 +56,11 @@
54
56
  "scripts": {
55
57
  "build": "tsc",
56
58
  "dev": "tsc --watch",
59
+ "typecheck": "tsc --noEmit",
57
60
  "ralph": "tsx src/index.ts",
58
- "test": "vitest run",
59
- "test:unit": "pnpm test --exclude test/e2e/**",
60
- "test:e2e": "pnpm test --config vitest.e2e.config.ts",
61
+ "test:all": "pnpm typecheck && pnpm test",
62
+ "test": "vitest --exclude test/e2e/** run",
63
+ "test:e2e": "vitest --config vitest.e2e.config.ts",
61
64
  "test:watch": "vitest --watch",
62
65
  "test:ui": "vitest --ui",
63
66
  "format": "prettier --write ."
@@ -1,9 +1,3 @@
1
- ## Context
2
-
3
- You are working in a git worktree. Each iteration runs in an isolated worktree branch, and your changes will be automatically merged back to the main branch when this iteration completes.
4
-
5
- ## Workflow
6
-
7
1
  Before doing anything, check that the project builds successfully. Run your project's build/typecheck commands and tests.
8
2
 
9
3
  If there are build errors or test failures: YOUR ONLY TASK IS TO FIX THEM.
@@ -19,10 +13,5 @@ When you complete a task, before committing:
19
13
  - Check that the project builds successfully and tests pass
20
14
  - Where applicable, add tests to validate your changes and confirm that they pass
21
15
  - Update the todo list by checking off the completed task and moving it to the "Done" section
22
- - Append your progress to the @.ralph/progress.md file. Use this to leave a note for the next person working in the codebase
23
-
24
- Make one git commit for this task.
25
-
26
- If merge conflicts occur when your changes are merged back to main, resolve them in the next iteration. The merge process happens automatically after each iteration completes.
27
16
 
28
- If, while implementing the task, you notice the todo list is complete, output <promise>COMPLETE</promise> and exit.
17
+ Make one git commit for this task. If, while implementing the task, you notice the todo list is complete, output <promise>COMPLETE</promise> and exit.
@@ -1,11 +0,0 @@
1
- # Progress Log
2
-
3
- This file tracks completed tasks and changes made to the codebase during ralph iterations.
4
-
5
- Each entry should include:
6
-
7
- - What was changed
8
- - Why it was changed
9
- - Any important notes for future work
10
-
11
- ---