ralph-cli-sandboxed 0.2.6 → 0.2.8

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.
@@ -17,6 +17,12 @@ function loadCliProvidersConfig() {
17
17
  const content = readFileSync(configPath, "utf-8");
18
18
  return JSON.parse(content);
19
19
  }
20
+ // Load skills from JSON config file
21
+ function loadSkillsConfig() {
22
+ const configPath = join(__dirname, "..", "config", "skills.json");
23
+ const content = readFileSync(configPath, "utf-8");
24
+ return JSON.parse(content);
25
+ }
20
26
  // Convert JSON config to the legacy format for compatibility
21
27
  function convertToLanguageConfig(config) {
22
28
  return {
@@ -31,6 +37,7 @@ function convertToLanguageConfig(config) {
31
37
  let _languagesCache = null;
32
38
  let _languagesJsonCache = null;
33
39
  let _cliProvidersCache = null;
40
+ let _skillsCache = null;
34
41
  export function getLanguagesJson() {
35
42
  if (!_languagesJsonCache) {
36
43
  _languagesJsonCache = loadLanguagesConfig();
@@ -46,6 +53,16 @@ export function getCliProvidersJson() {
46
53
  export function getCliProviders() {
47
54
  return getCliProvidersJson().providers;
48
55
  }
56
+ export function getSkillsJson() {
57
+ if (!_skillsCache) {
58
+ _skillsCache = loadSkillsConfig();
59
+ }
60
+ return _skillsCache;
61
+ }
62
+ export function getSkillsForLanguage(language) {
63
+ const skills = getSkillsJson().skills;
64
+ return skills[language] || [];
65
+ }
49
66
  export function getLanguages() {
50
67
  if (!_languagesCache) {
51
68
  const json = getLanguagesJson();
@@ -4,6 +4,7 @@ export interface CliConfig {
4
4
  yoloArgs?: string[];
5
5
  promptArgs?: string[];
6
6
  modelArgs?: string[];
7
+ fileArgs?: string[];
7
8
  }
8
9
  export interface McpServerConfig {
9
10
  command: string;
@@ -16,10 +17,15 @@ export interface SkillConfig {
16
17
  instructions: string;
17
18
  userInvocable?: boolean;
18
19
  }
20
+ export interface StreamJsonConfig {
21
+ enabled: boolean;
22
+ saveRawJson?: boolean;
23
+ }
19
24
  export interface AsciinemaConfig {
20
25
  enabled: boolean;
21
26
  autoRecord?: boolean;
22
27
  outputDir?: string;
28
+ streamJson?: StreamJsonConfig;
23
29
  }
24
30
  export interface RalphConfig {
25
31
  language: string;
@@ -3,7 +3,7 @@ import { join } from "path";
3
3
  import { getCliProviders } from "../templates/prompts.js";
4
4
  export const DEFAULT_CLI_CONFIG = {
5
5
  command: "claude",
6
- args: ["--permission-mode", "acceptEdits"],
6
+ args: [],
7
7
  promptArgs: ["-p"],
8
8
  };
9
9
  export function getCliConfig(config) {
@@ -21,6 +21,10 @@ export function getCliConfig(config) {
21
21
  if (result.modelArgs === undefined && provider?.modelArgs !== undefined) {
22
22
  result.modelArgs = provider.modelArgs;
23
23
  }
24
+ // Use provider's fileArgs if not already set
25
+ if (result.fileArgs === undefined && provider?.fileArgs !== undefined) {
26
+ result.fileArgs = provider.fileArgs;
27
+ }
24
28
  // Default promptArgs for backwards compatibility
25
29
  if (result.promptArgs === undefined) {
26
30
  result.promptArgs = ["-p"];
@@ -0,0 +1,28 @@
1
+ export interface NotificationOptions {
2
+ /** The notification command from config (e.g., "ntfy pub mytopic" or "notify-send") */
3
+ command?: string;
4
+ /** Whether to enable debug output */
5
+ debug?: boolean;
6
+ }
7
+ export type NotificationEvent = "prd_complete" | "iteration_complete" | "run_stopped" | "error";
8
+ /**
9
+ * Send a notification using the configured notify command.
10
+ *
11
+ * The notification command is split by spaces, with the message appended as the last argument.
12
+ * This supports various notification tools:
13
+ * - ntfy: "ntfy pub mytopic" → "ntfy pub mytopic 'message'"
14
+ * - notify-send: "notify-send Ralph" → "notify-send Ralph 'message'"
15
+ * - terminal-notifier: "terminal-notifier -title Ralph -message" → "terminal-notifier -title Ralph -message 'message'"
16
+ * - Custom scripts: "/path/to/notify.sh" → "/path/to/notify.sh 'message'"
17
+ *
18
+ * @param event The type of notification event
19
+ * @param message Optional custom message (default message based on event)
20
+ * @param options Notification options including the command
21
+ * @returns Promise that resolves when notification is sent (or immediately if no command configured)
22
+ */
23
+ export declare function sendNotification(event: NotificationEvent, message?: string, options?: NotificationOptions): Promise<void>;
24
+ /**
25
+ * Create a notifier function bound to specific options.
26
+ * Useful for creating a reusable notifier within a command.
27
+ */
28
+ export declare function createNotifier(options: NotificationOptions): (event: NotificationEvent, message?: string) => Promise<void>;
@@ -0,0 +1,69 @@
1
+ import { spawn } from "child_process";
2
+ /**
3
+ * Send a notification using the configured notify command.
4
+ *
5
+ * The notification command is split by spaces, with the message appended as the last argument.
6
+ * This supports various notification tools:
7
+ * - ntfy: "ntfy pub mytopic" → "ntfy pub mytopic 'message'"
8
+ * - notify-send: "notify-send Ralph" → "notify-send Ralph 'message'"
9
+ * - terminal-notifier: "terminal-notifier -title Ralph -message" → "terminal-notifier -title Ralph -message 'message'"
10
+ * - Custom scripts: "/path/to/notify.sh" → "/path/to/notify.sh 'message'"
11
+ *
12
+ * @param event The type of notification event
13
+ * @param message Optional custom message (default message based on event)
14
+ * @param options Notification options including the command
15
+ * @returns Promise that resolves when notification is sent (or immediately if no command configured)
16
+ */
17
+ export function sendNotification(event, message, options) {
18
+ return new Promise((resolve) => {
19
+ const { command, debug } = options ?? {};
20
+ // No notification if command is not configured or empty
21
+ if (!command || command.trim() === "") {
22
+ if (debug) {
23
+ console.error("[notification] No notifyCommand configured, skipping notification");
24
+ }
25
+ resolve();
26
+ return;
27
+ }
28
+ // Generate default message based on event type
29
+ const defaultMessages = {
30
+ prd_complete: "Ralph: PRD Complete! All tasks finished.",
31
+ iteration_complete: "Ralph: Iteration complete.",
32
+ run_stopped: "Ralph: Run stopped.",
33
+ error: "Ralph: An error occurred.",
34
+ };
35
+ const finalMessage = message ?? defaultMessages[event];
36
+ // Split command into executable and args
37
+ const parts = command.trim().split(/\s+/);
38
+ const [cmd, ...cmdArgs] = parts;
39
+ if (debug) {
40
+ console.error(`[notification] Sending: ${cmd} ${[...cmdArgs, finalMessage].join(" ")}`);
41
+ }
42
+ // Spawn the notification process, appending the message as the last argument
43
+ const proc = spawn(cmd, [...cmdArgs, finalMessage], {
44
+ stdio: "ignore",
45
+ // Don't let notification process block ralph from exiting
46
+ detached: true,
47
+ });
48
+ // Unref so the parent process can exit independently
49
+ proc.unref();
50
+ proc.on("error", (err) => {
51
+ if (debug) {
52
+ console.error(`[notification] Failed to send notification: ${err.message}`);
53
+ }
54
+ // Don't reject - notification failures shouldn't break ralph
55
+ resolve();
56
+ });
57
+ proc.on("spawn", () => {
58
+ // Notification process started successfully
59
+ resolve();
60
+ });
61
+ });
62
+ }
63
+ /**
64
+ * Create a notifier function bound to specific options.
65
+ * Useful for creating a reusable notifier within a command.
66
+ */
67
+ export function createNotifier(options) {
68
+ return (event, message) => sendNotification(event, message, options);
69
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Stream JSON parser interface and provider-specific implementations.
3
+ *
4
+ * Each CLI provider has its own stream-json event format. This module provides
5
+ * a unified interface for parsing stream-json output from different providers.
6
+ */
7
+ /**
8
+ * Interface for parsing stream-json lines from CLI providers.
9
+ */
10
+ export interface StreamJsonParser {
11
+ /**
12
+ * Parse a single line of stream-json output and return displayable text.
13
+ * @param line - A single line of JSON output
14
+ * @returns Human-readable text to display, or empty string if nothing to show
15
+ */
16
+ parseStreamJsonLine(line: string): string;
17
+ }
18
+ /**
19
+ * Base class for stream-json parsers with common utilities.
20
+ */
21
+ declare abstract class BaseStreamParser implements StreamJsonParser {
22
+ protected debug: boolean;
23
+ constructor(debug?: boolean);
24
+ abstract parseStreamJsonLine(line: string): string;
25
+ protected debugLog(message: string): void;
26
+ protected truncateOutput(output: string | unknown, maxLength?: number): string;
27
+ }
28
+ /**
29
+ * Parser for Claude Code CLI stream-json events.
30
+ *
31
+ * Event types:
32
+ * - content_block_delta: Incremental text updates (text_delta, input_json_delta)
33
+ * - content_block_start: Tool use or text block start
34
+ * - content_block_stop: End of content block
35
+ * - tool_result: Tool execution results
36
+ * - assistant: Complete assistant message with content blocks
37
+ * - message_start/message_delta/message_stop: Message lifecycle
38
+ * - system/user: System and user messages
39
+ * - result/error: Final results or errors
40
+ * - file_edit/file_write/file_read: File operations
41
+ * - bash/command: Command execution
42
+ * - bash_output/command_output: Command results
43
+ */
44
+ export declare class ClaudeStreamParser extends BaseStreamParser {
45
+ parseStreamJsonLine(line: string): string;
46
+ private handleFallback;
47
+ }
48
+ /**
49
+ * Parser for Gemini CLI stream-json events.
50
+ *
51
+ * Event types:
52
+ * - initialization: Model initialization info
53
+ * - messages: Conversation messages
54
+ * - tools: Tool calls and results
55
+ * - turn_complete: End of turn
56
+ * - response: Final response text
57
+ */
58
+ export declare class GeminiStreamParser extends BaseStreamParser {
59
+ parseStreamJsonLine(line: string): string;
60
+ private handleFallback;
61
+ }
62
+ /**
63
+ * Parser for OpenCode CLI stream-json events.
64
+ *
65
+ * Event types:
66
+ * - step_start/step_end/step_finish: Step lifecycle
67
+ * - tool_use: Tool invocation with nested part structure (part.type="tool", part.tool, part.state)
68
+ * - tool/tool_call: Direct tool invocation (alternate format)
69
+ * - tool_response: Tool results
70
+ * - text: Text output with nested part structure (part.text)
71
+ * - assistant_message/model_response: Model output
72
+ * - thinking/reasoning: Thinking process
73
+ * - done/complete: Completion
74
+ */
75
+ export declare class OpenCodeStreamParser extends BaseStreamParser {
76
+ parseStreamJsonLine(line: string): string;
77
+ private handleFallback;
78
+ }
79
+ /**
80
+ * Parser for Codex CLI stream-json events.
81
+ *
82
+ * Event types:
83
+ * - thread.started: Thread initialization
84
+ * - turn.started/turn.completed/turn.failed: Turn lifecycle
85
+ * - item.started/item.completed/item.failed: Action lifecycle
86
+ * - command_execution, file_change, file_read, mcp_tool_call, web_search, plan_update
87
+ */
88
+ export declare class CodexStreamParser extends BaseStreamParser {
89
+ parseStreamJsonLine(line: string): string;
90
+ private handleFallback;
91
+ }
92
+ /**
93
+ * Parser for Goose CLI stream-json events.
94
+ *
95
+ * Goose uses a similar event format to Claude Code.
96
+ * Falls back to Claude parser behavior for common events.
97
+ */
98
+ export declare class GooseStreamParser extends BaseStreamParser {
99
+ private claudeParser;
100
+ constructor(debug?: boolean);
101
+ parseStreamJsonLine(line: string): string;
102
+ }
103
+ /**
104
+ * Parser for Aider CLI stream events.
105
+ *
106
+ * Aider's --stream flag outputs JSON events for:
107
+ * - text: Streamed text content
108
+ * - tool_call: Tool/function calls
109
+ * - tool_result: Tool execution results
110
+ * - file_edit: File modifications
111
+ * - error: Error messages
112
+ */
113
+ export declare class AiderStreamParser extends BaseStreamParser {
114
+ parseStreamJsonLine(line: string): string;
115
+ private handleFallback;
116
+ }
117
+ /**
118
+ * Universal fallback parser that handles common event patterns.
119
+ * Used for providers without specific stream-json support or as a fallback.
120
+ */
121
+ export declare class DefaultStreamParser extends BaseStreamParser {
122
+ parseStreamJsonLine(line: string): string;
123
+ }
124
+ /**
125
+ * Get the appropriate stream-json parser for a CLI provider.
126
+ *
127
+ * @param provider - The CLI provider name (e.g., "claude", "gemini", "opencode")
128
+ * @param debug - Enable debug logging
129
+ * @returns The appropriate StreamJsonParser for the provider
130
+ */
131
+ export declare function getStreamJsonParser(provider: string | undefined, debug?: boolean): StreamJsonParser;
132
+ export {};