ralph-cli-sandboxed 0.4.0 → 0.4.2
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 +30 -0
- package/dist/commands/action.js +47 -20
- package/dist/commands/chat.d.ts +1 -1
- package/dist/commands/chat.js +325 -62
- package/dist/commands/config.js +2 -1
- package/dist/commands/daemon.d.ts +2 -5
- package/dist/commands/daemon.js +118 -49
- package/dist/commands/docker.js +110 -73
- package/dist/commands/fix-config.js +2 -1
- package/dist/commands/fix-prd.js +2 -2
- package/dist/commands/help.js +19 -3
- package/dist/commands/init.js +78 -17
- package/dist/commands/listen.js +116 -5
- package/dist/commands/logo.d.ts +5 -0
- package/dist/commands/logo.js +41 -0
- package/dist/commands/notify.js +1 -1
- package/dist/commands/once.js +19 -9
- package/dist/commands/prd.js +20 -2
- package/dist/commands/run.js +111 -27
- package/dist/commands/slack.d.ts +10 -0
- package/dist/commands/slack.js +333 -0
- package/dist/config/responder-presets.json +69 -0
- package/dist/index.js +6 -1
- package/dist/providers/discord.d.ts +82 -0
- package/dist/providers/discord.js +697 -0
- package/dist/providers/slack.d.ts +79 -0
- package/dist/providers/slack.js +715 -0
- package/dist/providers/telegram.d.ts +30 -0
- package/dist/providers/telegram.js +190 -7
- package/dist/responders/claude-code-responder.d.ts +48 -0
- package/dist/responders/claude-code-responder.js +203 -0
- package/dist/responders/cli-responder.d.ts +62 -0
- package/dist/responders/cli-responder.js +298 -0
- package/dist/responders/llm-responder.d.ts +135 -0
- package/dist/responders/llm-responder.js +582 -0
- package/dist/templates/macos-scripts.js +2 -4
- package/dist/templates/prompts.js +4 -2
- package/dist/tui/ConfigEditor.js +42 -5
- package/dist/tui/components/ArrayEditor.js +1 -1
- package/dist/tui/components/EditorPanel.js +10 -6
- package/dist/tui/components/HelpPanel.d.ts +1 -1
- package/dist/tui/components/HelpPanel.js +1 -1
- package/dist/tui/components/JsonSnippetEditor.js +8 -5
- package/dist/tui/components/KeyValueEditor.js +69 -5
- package/dist/tui/components/LLMProvidersEditor.d.ts +22 -0
- package/dist/tui/components/LLMProvidersEditor.js +357 -0
- package/dist/tui/components/ObjectEditor.js +1 -1
- package/dist/tui/components/Preview.js +1 -1
- package/dist/tui/components/RespondersEditor.d.ts +22 -0
- package/dist/tui/components/RespondersEditor.js +437 -0
- package/dist/tui/components/SectionNav.js +27 -3
- package/dist/tui/utils/presets.js +15 -2
- package/dist/utils/chat-client.d.ts +33 -4
- package/dist/utils/chat-client.js +20 -1
- package/dist/utils/config.d.ts +100 -1
- package/dist/utils/config.js +78 -1
- package/dist/utils/daemon-actions.d.ts +19 -0
- package/dist/utils/daemon-actions.js +111 -0
- package/dist/utils/daemon-client.d.ts +21 -0
- package/dist/utils/daemon-client.js +28 -1
- package/dist/utils/llm-client.d.ts +82 -0
- package/dist/utils/llm-client.js +185 -0
- package/dist/utils/message-queue.js +6 -6
- package/dist/utils/notification.d.ts +10 -2
- package/dist/utils/notification.js +111 -4
- package/dist/utils/prd-validator.js +60 -19
- package/dist/utils/prompt.js +22 -12
- package/dist/utils/responder-logger.d.ts +47 -0
- package/dist/utils/responder-logger.js +129 -0
- package/dist/utils/responder-presets.d.ts +92 -0
- package/dist/utils/responder-presets.js +156 -0
- package/dist/utils/responder.d.ts +88 -0
- package/dist/utils/responder.js +207 -0
- package/dist/utils/stream-json.js +6 -6
- package/docs/CHAT-CLIENTS.md +520 -0
- package/docs/CHAT-RESPONDERS.md +785 -0
- package/docs/DEVELOPMENT.md +25 -0
- package/docs/USEFUL_ACTIONS.md +815 -0
- package/docs/chat-architecture.md +251 -0
- package/package.json +14 -1
package/dist/commands/daemon.js
CHANGED
|
@@ -2,9 +2,16 @@ import { existsSync, watch } from "fs";
|
|
|
2
2
|
import { spawn } from "child_process";
|
|
3
3
|
import { loadConfig, getRalphDir, isRunningInContainer } from "../utils/config.js";
|
|
4
4
|
import { getMessagesPath, readMessages, getPendingMessages, respondToMessage, cleanupOldMessages, initializeMessages, } from "../utils/message-queue.js";
|
|
5
|
+
import { getDefaultActions } from "../utils/daemon-actions.js";
|
|
5
6
|
// Telegram client for sending messages (lazy loaded)
|
|
6
7
|
let telegramClient = null;
|
|
7
8
|
let telegramConfig = null;
|
|
9
|
+
// Slack client for sending messages (lazy loaded)
|
|
10
|
+
let slackClient = null;
|
|
11
|
+
let slackConfig = null;
|
|
12
|
+
// Discord client for sending messages (lazy loaded)
|
|
13
|
+
let discordClient = null;
|
|
14
|
+
let discordConfig = null;
|
|
8
15
|
/**
|
|
9
16
|
* Check if Telegram is enabled (has token and not explicitly disabled).
|
|
10
17
|
*/
|
|
@@ -15,6 +22,31 @@ function isTelegramEnabled(config) {
|
|
|
15
22
|
return false;
|
|
16
23
|
return true;
|
|
17
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Check if Slack is enabled (has required tokens and not explicitly disabled).
|
|
27
|
+
*/
|
|
28
|
+
function isSlackEnabled(config) {
|
|
29
|
+
if (!config.chat?.slack?.botToken)
|
|
30
|
+
return false;
|
|
31
|
+
if (!config.chat?.slack?.appToken)
|
|
32
|
+
return false;
|
|
33
|
+
if (!config.chat?.slack?.signingSecret)
|
|
34
|
+
return false;
|
|
35
|
+
if (config.chat.slack.enabled === false)
|
|
36
|
+
return false;
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if Discord is enabled (has token and not explicitly disabled).
|
|
41
|
+
*/
|
|
42
|
+
function isDiscordEnabled(config) {
|
|
43
|
+
if (!config.chat?.discord?.botToken)
|
|
44
|
+
return false;
|
|
45
|
+
if (config.chat.discord.enabled === false)
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
// Note: getDefaultActions moved to utils/daemon-actions.ts for sharing with action.ts
|
|
18
50
|
/**
|
|
19
51
|
* Initialize Telegram client if configured.
|
|
20
52
|
*/
|
|
@@ -26,6 +58,28 @@ async function initTelegramClient(config) {
|
|
|
26
58
|
telegramClient = createTelegramClient(telegramConfig, false);
|
|
27
59
|
}
|
|
28
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Initialize Slack client if configured.
|
|
63
|
+
*/
|
|
64
|
+
async function initSlackClient(config) {
|
|
65
|
+
if (isSlackEnabled(config)) {
|
|
66
|
+
slackConfig = config.chat.slack;
|
|
67
|
+
// Dynamic import to avoid circular dependency
|
|
68
|
+
const { createSlackClient } = await import("../providers/slack.js");
|
|
69
|
+
slackClient = createSlackClient(slackConfig, false);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Initialize Discord client if configured.
|
|
74
|
+
*/
|
|
75
|
+
async function initDiscordClient(config) {
|
|
76
|
+
if (isDiscordEnabled(config)) {
|
|
77
|
+
discordConfig = config.chat.discord;
|
|
78
|
+
// Dynamic import to avoid circular dependency
|
|
79
|
+
const { createDiscordClient } = await import("../providers/discord.js");
|
|
80
|
+
discordClient = createDiscordClient(discordConfig, false);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
29
83
|
/**
|
|
30
84
|
* Send a message via Telegram if configured.
|
|
31
85
|
*/
|
|
@@ -49,56 +103,48 @@ async function sendTelegramMessage(message) {
|
|
|
49
103
|
}
|
|
50
104
|
}
|
|
51
105
|
/**
|
|
52
|
-
*
|
|
106
|
+
* Send a message via Slack if configured.
|
|
53
107
|
*/
|
|
54
|
-
function
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
command: "echo pong",
|
|
58
|
-
description: "Health check - responds with 'pong'",
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
// Add notify action based on notifications config
|
|
62
|
-
if (config.notifications?.provider === "ntfy" && config.notifications.ntfy?.topic) {
|
|
63
|
-
const server = config.notifications.ntfy.server || "https://ntfy.sh";
|
|
64
|
-
const topic = config.notifications.ntfy.topic;
|
|
65
|
-
actions.notify = {
|
|
66
|
-
command: "curl", // Placeholder - ntfyUrl triggers special handling
|
|
67
|
-
description: `Send notification via ntfy to ${topic}`,
|
|
68
|
-
ntfyUrl: `${server}/${topic}`,
|
|
69
|
-
};
|
|
108
|
+
async function sendSlackMessage(message) {
|
|
109
|
+
if (!slackClient || !slackConfig) {
|
|
110
|
+
return { success: false, error: "Slack not configured" };
|
|
70
111
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
112
|
+
try {
|
|
113
|
+
// Send to all allowed channel IDs, or fail if none configured
|
|
114
|
+
const channelIds = slackConfig.allowedChannelIds;
|
|
115
|
+
if (!channelIds || channelIds.length === 0) {
|
|
116
|
+
return { success: false, error: "No channel IDs configured for Slack" };
|
|
117
|
+
}
|
|
118
|
+
for (const channelId of channelIds) {
|
|
119
|
+
await slackClient.sendMessage(channelId, message);
|
|
120
|
+
}
|
|
121
|
+
return { success: true };
|
|
76
122
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
actions.notify = {
|
|
80
|
-
command: config.notifyCommand,
|
|
81
|
-
description: "Send notification to host",
|
|
82
|
-
};
|
|
123
|
+
catch (err) {
|
|
124
|
+
return { success: false, error: err instanceof Error ? err.message : "Unknown error" };
|
|
83
125
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Send a message via Discord if configured.
|
|
129
|
+
*/
|
|
130
|
+
async function sendDiscordMessage(message) {
|
|
131
|
+
if (!discordClient || !discordConfig) {
|
|
132
|
+
return { success: false, error: "Discord not configured" };
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
// Send to all allowed channel IDs, or fail if none configured
|
|
136
|
+
const channelIds = discordConfig.allowedChannelIds;
|
|
137
|
+
if (!channelIds || channelIds.length === 0) {
|
|
138
|
+
return { success: false, error: "No channel IDs configured for Discord" };
|
|
139
|
+
}
|
|
140
|
+
for (const channelId of channelIds) {
|
|
141
|
+
await discordClient.sendMessage(channelId, message);
|
|
142
|
+
}
|
|
143
|
+
return { success: true };
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
return { success: false, error: err instanceof Error ? err.message : "Unknown error" };
|
|
90
147
|
}
|
|
91
|
-
// Add chat_status action for querying PRD status from container
|
|
92
|
-
actions.chat_status = {
|
|
93
|
-
command: "ralph prd status --json 2>/dev/null || echo '{}'",
|
|
94
|
-
description: "Get PRD status as JSON",
|
|
95
|
-
};
|
|
96
|
-
// Add chat_add action for adding PRD tasks from container
|
|
97
|
-
actions.chat_add = {
|
|
98
|
-
command: "ralph add",
|
|
99
|
-
description: "Add a new task to the PRD",
|
|
100
|
-
};
|
|
101
|
-
return actions;
|
|
102
148
|
}
|
|
103
149
|
/**
|
|
104
150
|
* Execute an action command with arguments.
|
|
@@ -116,6 +162,26 @@ async function executeAction(action, args = []) {
|
|
|
116
162
|
error: result.error,
|
|
117
163
|
};
|
|
118
164
|
}
|
|
165
|
+
// Special handling for Slack
|
|
166
|
+
if (action.command === "__slack__") {
|
|
167
|
+
const message = args.join(" ") || "Ralph notification";
|
|
168
|
+
const result = await sendSlackMessage(message);
|
|
169
|
+
return {
|
|
170
|
+
success: result.success,
|
|
171
|
+
output: result.success ? "Sent to Slack" : "",
|
|
172
|
+
error: result.error,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// Special handling for Discord
|
|
176
|
+
if (action.command === "__discord__") {
|
|
177
|
+
const message = args.join(" ") || "Ralph notification";
|
|
178
|
+
const result = await sendDiscordMessage(message);
|
|
179
|
+
return {
|
|
180
|
+
success: result.success,
|
|
181
|
+
output: result.success ? "Sent to Discord" : "",
|
|
182
|
+
error: result.error,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
119
185
|
return new Promise((resolve) => {
|
|
120
186
|
let fullCommand;
|
|
121
187
|
const message = args.join(" ") || "";
|
|
@@ -132,9 +198,10 @@ async function executeAction(action, args = []) {
|
|
|
132
198
|
else {
|
|
133
199
|
// Command can use $RALPH_MESSAGE env var
|
|
134
200
|
// Also pass args for backwards compatibility
|
|
135
|
-
fullCommand =
|
|
136
|
-
|
|
137
|
-
|
|
201
|
+
fullCommand =
|
|
202
|
+
args.length > 0
|
|
203
|
+
? `${action.command} ${args.map((a) => `"${a.replace(/"/g, '\\"')}"`).join(" ")}`
|
|
204
|
+
: action.command;
|
|
138
205
|
}
|
|
139
206
|
const proc = spawn(fullCommand, [], {
|
|
140
207
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -203,8 +270,10 @@ async function startDaemon(debug) {
|
|
|
203
270
|
}
|
|
204
271
|
const config = loadConfig();
|
|
205
272
|
const daemonConfig = config.daemon || {};
|
|
206
|
-
// Initialize
|
|
273
|
+
// Initialize chat clients if configured
|
|
207
274
|
await initTelegramClient(config);
|
|
275
|
+
await initSlackClient(config);
|
|
276
|
+
await initDiscordClient(config);
|
|
208
277
|
// Merge default and configured actions
|
|
209
278
|
const defaultActions = getDefaultActions(config);
|
|
210
279
|
const configuredActions = daemonConfig.actions || {};
|