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.
- package/README.md +185 -3
- package/dist/commands/docker.js +103 -2
- package/dist/commands/help.js +2 -1
- package/dist/commands/init.js +30 -2
- package/dist/commands/once.js +174 -15
- package/dist/commands/run.js +189 -18
- package/dist/config/cli-providers.json +28 -3
- package/dist/config/skills.json +12 -0
- package/dist/templates/prompts.d.ts +13 -0
- package/dist/templates/prompts.js +17 -0
- package/dist/utils/config.d.ts +6 -0
- package/dist/utils/config.js +5 -1
- package/dist/utils/notification.d.ts +28 -0
- package/dist/utils/notification.js +69 -0
- package/dist/utils/stream-json.d.ts +132 -0
- package/dist/utils/stream-json.js +662 -0
- package/docs/SECURITY.md +21 -6
- package/package.json +1 -1
|
@@ -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();
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -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;
|
package/dist/utils/config.js
CHANGED
|
@@ -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: [
|
|
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 {};
|