ralph-cli-sandboxed 0.6.5 → 0.7.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.
- package/LICENSE +191 -0
- package/README.md +1 -1
- package/dist/commands/action.js +6 -8
- package/dist/commands/ask.d.ts +6 -0
- package/dist/commands/ask.js +140 -0
- package/dist/commands/branch.js +8 -4
- package/dist/commands/chat.js +11 -8
- package/dist/commands/docker.js +19 -4
- package/dist/commands/fix-config.js +0 -41
- package/dist/commands/help.js +10 -0
- package/dist/commands/run.js +9 -9
- package/dist/config/languages.json +5 -3
- package/dist/index.js +2 -0
- package/dist/providers/telegram.js +1 -1
- package/dist/responders/claude-code-responder.js +1 -0
- package/dist/responders/cli-responder.js +1 -0
- package/dist/responders/llm-responder.js +1 -1
- package/dist/templates/macos-scripts.js +18 -18
- package/dist/tui/components/JsonSnippetEditor.js +7 -7
- package/dist/tui/components/KeyValueEditor.js +5 -1
- package/dist/tui/components/LLMProvidersEditor.js +7 -9
- package/dist/tui/components/Preview.js +1 -1
- package/dist/tui/components/SectionNav.js +18 -2
- package/dist/utils/chat-client.js +1 -0
- package/dist/utils/config.d.ts +1 -0
- package/dist/utils/config.js +3 -1
- package/dist/utils/config.test.d.ts +1 -0
- package/dist/utils/config.test.js +424 -0
- package/dist/utils/notification.js +1 -1
- package/dist/utils/prd-validator.js +16 -4
- package/dist/utils/prd-validator.test.d.ts +1 -0
- package/dist/utils/prd-validator.test.js +1095 -0
- package/dist/utils/responder.js +4 -1
- package/dist/utils/stream-json.test.d.ts +1 -0
- package/dist/utils/stream-json.test.js +1007 -0
- package/docs/DOCKER.md +14 -0
- package/docs/PRD-GENERATOR.md +15 -0
- package/package.json +16 -13
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"checkCommand": "mvn compile",
|
|
138
138
|
"testCommand": "mvn test",
|
|
139
139
|
"docker": {
|
|
140
|
-
"install": "# Install Java ${version} and Maven\nRUN apt-get update && apt-get install -y \\\n
|
|
140
|
+
"install": "# Install Java ${version} and Maven (via Eclipse Temurin)\nRUN mkdir -p /etc/apt/keyrings \\\n && wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor -o /etc/apt/keyrings/adoptium.gpg \\\n && echo \"deb [signed-by=/etc/apt/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb bookworm main\" > /etc/apt/sources.list.d/adoptium.list \\\n && apt-get update && apt-get install -y \\\n temurin-${version}-jdk \\\n maven \\\n && rm -rf /var/lib/apt/lists/* \\\n && ln -s /usr/lib/jvm/temurin-${version}-jdk-$(dpkg --print-architecture) /usr/lib/jvm/temurin-${version}-jdk\nENV JAVA_HOME=\"/usr/lib/jvm/temurin-${version}-jdk\"\nENV PATH=\"$JAVA_HOME/bin:$PATH\"",
|
|
141
141
|
"version": 17,
|
|
142
142
|
"versionConfigurable": true
|
|
143
143
|
},
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
"checkCommand": "gradle build",
|
|
166
166
|
"testCommand": "gradle test",
|
|
167
167
|
"docker": {
|
|
168
|
-
"install": "# Install Kotlin and Gradle (Java ${version})\nRUN apt-get update && apt-get install -y \\\n
|
|
168
|
+
"install": "# Install Kotlin and Gradle (Java ${version} via Eclipse Temurin)\nRUN mkdir -p /etc/apt/keyrings \\\n && wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor -o /etc/apt/keyrings/adoptium.gpg \\\n && echo \"deb [signed-by=/etc/apt/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb bookworm main\" > /etc/apt/sources.list.d/adoptium.list \\\n && apt-get update && apt-get install -y \\\n temurin-${version}-jdk \\\n && rm -rf /var/lib/apt/lists/* \\\n && ln -s /usr/lib/jvm/temurin-${version}-jdk-$(dpkg --print-architecture) /usr/lib/jvm/temurin-${version}-jdk\nENV JAVA_HOME=\"/usr/lib/jvm/temurin-${version}-jdk\"\nENV PATH=\"$JAVA_HOME/bin:$PATH\"\n# Install Gradle\nRUN curl -fsSL https://services.gradle.org/distributions/gradle-8.5-bin.zip -o /tmp/gradle.zip && \\\n unzip -d /opt /tmp/gradle.zip && \\\n rm /tmp/gradle.zip\nENV PATH=\"/opt/gradle-8.5/bin:$PATH\"\n# Install Kotlin compiler\nRUN curl -fsSL https://github.com/JetBrains/kotlin/releases/download/v1.9.22/kotlin-compiler-1.9.22.zip -o /tmp/kotlin.zip && \\\n unzip -d /opt /tmp/kotlin.zip && \\\n rm /tmp/kotlin.zip\nENV PATH=\"/opt/kotlinc/bin:$PATH\"",
|
|
169
169
|
"version": 17,
|
|
170
170
|
"versionConfigurable": true,
|
|
171
171
|
"gradleVersion": "8.5",
|
|
@@ -282,7 +282,9 @@
|
|
|
282
282
|
"checkCommand": "mix compile --warnings-as-errors",
|
|
283
283
|
"testCommand": "mix test",
|
|
284
284
|
"docker": {
|
|
285
|
-
"install": "# Install Erlang
|
|
285
|
+
"install": "# Install Erlang/OTP 27 from RabbitMQ team's apt repo\nRUN apt-get update && apt-get install -y curl gnupg \\\n && curl -1sLf \"https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA\" | gpg --dearmor > /usr/share/keyrings/rabbitmq-erlang.gpg \\\n && echo \"deb [signed-by=/usr/share/keyrings/rabbitmq-erlang.gpg] https://deb1.rabbitmq.com/rabbitmq-erlang/debian/bookworm bookworm main\" > /etc/apt/sources.list.d/rabbitmq-erlang.list \\\n && apt-get update && apt-get install -y erlang-base erlang-dev erlang-parsetools erlang-xmerl erlang-tools erlang-ssl erlang-public-key erlang-asn1 erlang-crypto erlang-runtime-tools erlang-inets erlang-mnesia erlang-eunit \\\n && rm -rf /var/lib/apt/lists/*\n# Install Elixir 1.19.5 (precompiled for OTP 27)\nRUN curl -fsSL https://github.com/elixir-lang/elixir/releases/download/v1.19.5/elixir-otp-27.zip -o /tmp/elixir.zip \\\n && mkdir -p /opt/elixir \\\n && unzip -q /tmp/elixir.zip -d /opt/elixir \\\n && rm /tmp/elixir.zip\nENV PATH=\"/opt/elixir/bin:$PATH\"\nRUN mix local.hex --force && mix local.rebar --force",
|
|
286
|
+
"elixirVersion": "1.19.5",
|
|
287
|
+
"erlangVersion": "27"
|
|
286
288
|
},
|
|
287
289
|
"technologies": [
|
|
288
290
|
{ "name": "Phoenix", "description": "Web framework for Elixir" },
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { fixPrd } from "./commands/fix-prd.js";
|
|
|
13
13
|
import { fixConfig } from "./commands/fix-config.js";
|
|
14
14
|
import { daemon } from "./commands/daemon.js";
|
|
15
15
|
import { notify } from "./commands/notify.js";
|
|
16
|
+
import { ask } from "./commands/ask.js";
|
|
16
17
|
import { chat } from "./commands/chat.js";
|
|
17
18
|
import { listen } from "./commands/listen.js";
|
|
18
19
|
import { config } from "./commands/config.js";
|
|
@@ -38,6 +39,7 @@ const commands = {
|
|
|
38
39
|
docker,
|
|
39
40
|
daemon,
|
|
40
41
|
notify,
|
|
42
|
+
ask,
|
|
41
43
|
chat,
|
|
42
44
|
listen,
|
|
43
45
|
config,
|
|
@@ -175,7 +175,7 @@ export class TelegramChatClient {
|
|
|
175
175
|
reject(new Error(`Telegram API error: ${response.description || "Unknown error"} (code: ${response.error_code})`));
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
-
catch
|
|
178
|
+
catch {
|
|
179
179
|
reject(new Error(`Failed to parse Telegram response: ${data}`));
|
|
180
180
|
}
|
|
181
181
|
});
|
|
@@ -155,6 +155,7 @@ export async function executeClaudeCodeResponder(prompt, responderConfig, option
|
|
|
155
155
|
*/
|
|
156
156
|
function formatClaudeCodeOutput(output) {
|
|
157
157
|
// Remove ANSI escape codes
|
|
158
|
+
// eslint-disable-next-line no-control-regex
|
|
158
159
|
let cleaned = output.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
|
|
159
160
|
// Remove carriage returns (used for progress overwriting)
|
|
160
161
|
cleaned = cleaned.replace(/\r/g, "");
|
|
@@ -244,6 +244,7 @@ function formatCLIOutput(stdout, stderr) {
|
|
|
244
244
|
output = output.trim() + "\n\n[stderr]\n" + stderr.trim();
|
|
245
245
|
}
|
|
246
246
|
// Remove ANSI escape codes
|
|
247
|
+
// eslint-disable-next-line no-control-regex
|
|
247
248
|
let cleaned = output.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
|
|
248
249
|
// Remove carriage returns (used for progress overwriting)
|
|
249
250
|
cleaned = cleaned.replace(/\r/g, "");
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* LLM Responder - Sends messages to LLM providers and returns responses.
|
|
3
3
|
* Used by chat clients to respond to messages matched by the responder matcher.
|
|
4
4
|
*/
|
|
5
|
-
import { getLLMProviders, loadConfig
|
|
5
|
+
import { getLLMProviders, loadConfig } from "../utils/config.js";
|
|
6
6
|
import { createLLMClient } from "../utils/llm-client.js";
|
|
7
7
|
import { createResponderLog } from "../utils/responder-logger.js";
|
|
8
8
|
import { basename, resolve } from "path";
|
|
@@ -48,8 +48,8 @@ PROJECT_NAME="\${1:-${projectName}}"
|
|
|
48
48
|
SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
|
49
49
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
50
50
|
|
|
51
|
-
echo "Generating Xcode project:
|
|
52
|
-
echo "Project root:
|
|
51
|
+
echo "Generating Xcode project: $PROJECT_NAME"
|
|
52
|
+
echo "Project root: $PROJECT_ROOT"
|
|
53
53
|
echo ""
|
|
54
54
|
|
|
55
55
|
cd "$PROJECT_ROOT"
|
|
@@ -62,7 +62,7 @@ if [ ! -f "Package.swift" ]; then
|
|
|
62
62
|
fi
|
|
63
63
|
|
|
64
64
|
# Create Supporting Files directory for Info.plist and entitlements
|
|
65
|
-
SUPPORT_DIR="$PROJECT_ROOT/Sources
|
|
65
|
+
SUPPORT_DIR="$PROJECT_ROOT/Sources/$PROJECT_NAME/Supporting Files"
|
|
66
66
|
mkdir -p "$SUPPORT_DIR"
|
|
67
67
|
|
|
68
68
|
# Generate Info.plist if it doesn't exist
|
|
@@ -105,7 +105,7 @@ PLIST_EOF
|
|
|
105
105
|
fi
|
|
106
106
|
|
|
107
107
|
# Generate entitlements file if it doesn't exist
|
|
108
|
-
ENTITLEMENTS="$SUPPORT_DIR
|
|
108
|
+
ENTITLEMENTS="$SUPPORT_DIR/$PROJECT_NAME.entitlements"
|
|
109
109
|
if [ ! -f "$ENTITLEMENTS" ]; then
|
|
110
110
|
echo "Creating entitlements file..."
|
|
111
111
|
cat > "$ENTITLEMENTS" << 'ENTITLEMENTS_EOF'
|
|
@@ -135,7 +135,7 @@ if command -v xcodegen &> /dev/null; then
|
|
|
135
135
|
if [ ! -f "$PROJECT_YML" ]; then
|
|
136
136
|
echo "Creating project.yml for xcodegen..."
|
|
137
137
|
cat > "$PROJECT_YML" << YAML_EOF
|
|
138
|
-
name:
|
|
138
|
+
name: $PROJECT_NAME
|
|
139
139
|
options:
|
|
140
140
|
bundleIdPrefix: com.example
|
|
141
141
|
deploymentTarget:
|
|
@@ -144,18 +144,18 @@ options:
|
|
|
144
144
|
generateEmptyDirectories: true
|
|
145
145
|
|
|
146
146
|
targets:
|
|
147
|
-
|
|
147
|
+
$PROJECT_NAME:
|
|
148
148
|
type: application
|
|
149
149
|
platform: macOS
|
|
150
150
|
sources:
|
|
151
|
-
- path: Sources
|
|
151
|
+
- path: Sources/$PROJECT_NAME
|
|
152
152
|
excludes:
|
|
153
153
|
- "**/*.entitlements"
|
|
154
154
|
settings:
|
|
155
155
|
base:
|
|
156
|
-
PRODUCT_BUNDLE_IDENTIFIER: com.example
|
|
157
|
-
INFOPLIST_FILE: Sources
|
|
158
|
-
CODE_SIGN_ENTITLEMENTS: Sources
|
|
156
|
+
PRODUCT_BUNDLE_IDENTIFIER: com.example.$PROJECT_NAME
|
|
157
|
+
INFOPLIST_FILE: Sources/$PROJECT_NAME/Supporting Files/Info.plist
|
|
158
|
+
CODE_SIGN_ENTITLEMENTS: Sources/$PROJECT_NAME/Supporting Files/$PROJECT_NAME.entitlements
|
|
159
159
|
MACOSX_DEPLOYMENT_TARGET: "13.0"
|
|
160
160
|
SWIFT_VERSION: "5.9"
|
|
161
161
|
DEVELOPMENT_TEAM: ""
|
|
@@ -191,7 +191,7 @@ fi
|
|
|
191
191
|
|
|
192
192
|
echo ""
|
|
193
193
|
echo "Next steps:"
|
|
194
|
-
echo " 1. Open
|
|
194
|
+
echo " 1. Open $PROJECT_NAME.xcodeproj in Xcode"
|
|
195
195
|
echo " 2. Configure your Team ID for code signing"
|
|
196
196
|
echo " 3. Build and run (Cmd+R)"
|
|
197
197
|
echo ""
|
|
@@ -389,9 +389,9 @@ app_identifier "${bundleId}"
|
|
|
389
389
|
* @param projectName - Name of the Xcode project/app
|
|
390
390
|
*/
|
|
391
391
|
export function generateFastlaneReadmeSection(projectName = "App") {
|
|
392
|
-
return `## Fastlane Deployment
|
|
392
|
+
return `## Fastlane Deployment for ${projectName}
|
|
393
393
|
|
|
394
|
-
This project includes [Fastlane](https://fastlane.tools/) configuration for automated builds and deployments.
|
|
394
|
+
This project includes [Fastlane](https://fastlane.tools/) configuration for automated builds and deployments of ${projectName}.
|
|
395
395
|
|
|
396
396
|
### Setup
|
|
397
397
|
|
|
@@ -418,9 +418,9 @@ Run Fastlane commands from the \`scripts/\` directory:
|
|
|
418
418
|
|
|
419
419
|
| Lane | Description |
|
|
420
420
|
|------|-------------|
|
|
421
|
-
| \`fastlane tests\` | Run all unit and UI tests |
|
|
422
|
-
| \`fastlane beta\` | Build and upload to TestFlight |
|
|
423
|
-
| \`fastlane release\` | Build and submit to App Store |
|
|
421
|
+
| \`fastlane tests\` | Run all ${projectName} unit and UI tests |
|
|
422
|
+
| \`fastlane beta\` | Build ${projectName} and upload to TestFlight |
|
|
423
|
+
| \`fastlane release\` | Build ${projectName} and submit to App Store |
|
|
424
424
|
|
|
425
425
|
### Using with Ralph
|
|
426
426
|
|
|
@@ -438,8 +438,8 @@ ralph action fastlane_release
|
|
|
438
438
|
|
|
439
439
|
### Customization
|
|
440
440
|
|
|
441
|
-
- **Fastfile** (\`scripts/fastlane/Fastfile\`): Add custom lanes for your workflow
|
|
442
|
-
- **Appfile** (\`scripts/fastlane/Appfile\`): Configure
|
|
441
|
+
- **Fastfile** (\`scripts/fastlane/Fastfile\`): Add custom lanes for your ${projectName} workflow
|
|
442
|
+
- **Appfile** (\`scripts/fastlane/Appfile\`): Configure ${projectName} bundle ID and team settings
|
|
443
443
|
|
|
444
444
|
For more information, see the [Fastlane documentation](https://docs.fastlane.tools/).
|
|
445
445
|
`;
|
|
@@ -161,16 +161,16 @@ function truncateJsonString(str, maxLen) {
|
|
|
161
161
|
/**
|
|
162
162
|
* Simple syntax highlighting for JSON preview.
|
|
163
163
|
*/
|
|
164
|
-
function highlightJson(json, maxLines, maxLineWidth = 60) {
|
|
164
|
+
function highlightJson(json, maxLines, maxLineWidth = 60, scrollOffset = 0) {
|
|
165
165
|
const lines = json.split("\n");
|
|
166
|
-
const displayLines = lines.slice(
|
|
167
|
-
const hasMore = lines.length > maxLines;
|
|
166
|
+
const displayLines = lines.slice(scrollOffset, scrollOffset + maxLines);
|
|
167
|
+
const hasMore = lines.length > scrollOffset + maxLines;
|
|
168
168
|
const elements = [];
|
|
169
169
|
// Calculate max string length based on available width (account for line number, indentation)
|
|
170
170
|
const maxStringLen = Math.max(20, Math.min(50, maxLineWidth - 15));
|
|
171
171
|
for (let i = 0; i < displayLines.length; i++) {
|
|
172
172
|
const line = displayLines[i];
|
|
173
|
-
const lineNum = String(i + 1).padStart(3, " ");
|
|
173
|
+
const lineNum = String(scrollOffset + i + 1).padStart(3, " ");
|
|
174
174
|
// Simple tokenization for highlighting
|
|
175
175
|
const tokens = [];
|
|
176
176
|
let remaining = line;
|
|
@@ -230,7 +230,7 @@ function highlightJson(json, maxLines, maxLineWidth = 60) {
|
|
|
230
230
|
elements.push(_jsxs(Box, { children: [_jsxs(Text, { dimColor: true, children: [lineNum, " "] }), tokens] }, i));
|
|
231
231
|
}
|
|
232
232
|
if (hasMore) {
|
|
233
|
-
elements.push(_jsx(Box, { children: _jsxs(Text, { dimColor: true, children: [" ... (", lines.length - maxLines, " more lines)"] }) }, "more"));
|
|
233
|
+
elements.push(_jsx(Box, { children: _jsxs(Text, { dimColor: true, children: [" ... (", lines.length - scrollOffset - maxLines, " more lines)"] }) }, "more"));
|
|
234
234
|
}
|
|
235
235
|
return elements;
|
|
236
236
|
}
|
|
@@ -246,8 +246,8 @@ export function JsonSnippetEditor({ label, value, onConfirm, onCancel, isFocused
|
|
|
246
246
|
const [editText, setEditText] = useState(initialJson);
|
|
247
247
|
const [parseError, setParseError] = useState(null);
|
|
248
248
|
const [warnings, setWarnings] = useState([]);
|
|
249
|
-
const [scrollOffset, setScrollOffset] = useState(0);
|
|
250
249
|
const [copied, setCopied] = useState(false);
|
|
250
|
+
const [scrollOffset, setScrollOffset] = useState(0);
|
|
251
251
|
// Validate JSON as user types
|
|
252
252
|
useEffect(() => {
|
|
253
253
|
const result = parseJsonWithLineInfo(editText);
|
|
@@ -375,7 +375,7 @@ export function JsonSnippetEditor({ label, value, onConfirm, onCancel, isFocused
|
|
|
375
375
|
// Render view mode with syntax-highlighted preview
|
|
376
376
|
// Account for border (2) and padding (2) when calculating preview width
|
|
377
377
|
const previewWidth = Math.max(40, maxWidth - 4);
|
|
378
|
-
const previewLines = highlightJson(editText, previewMaxLines, previewWidth);
|
|
378
|
+
const previewLines = highlightJson(editText, previewMaxLines, previewWidth, scrollOffset);
|
|
379
379
|
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, justifyContent: "space-between", children: [_jsxs(Text, { bold: true, color: "cyan", children: ["Edit as JSON: ", label] }), copied && _jsx(Text, { color: "green", children: " Copied!" })] }), _jsx(Box, { flexDirection: "column", marginBottom: 1, children: previewLines }), _jsx(Box, { marginBottom: 1, flexDirection: "column", children: parseError ? (_jsx(Box, { children: _jsxs(Text, { color: "red", bold: true, children: ["Error:", " ", parseError.line && parseError.column
|
|
380
380
|
? `Line ${parseError.line}:${parseError.column} - `
|
|
381
381
|
: "", parseError.message] }) })) : warningCount > 0 ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "yellow", bold: true, children: [warningCount, " warning", warningCount > 1 ? "s" : "", ":"] }), warnings.slice(0, 3).map((w, i) => (_jsxs(Text, { color: "yellow", dimColor: true, children: [" ", "- ", w] }, i))), warningCount > 3 && _jsxs(Text, { dimColor: true, children: [" ... and ", warningCount - 3, " more"] })] })) : (_jsx(Text, { color: "green", children: "Valid JSON" })) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "e/Enter: edit | s: save | c: copy | f: format" }), _jsx(Text, { dimColor: true, children: "j/k: scroll | PgUp/Dn: page | Esc: cancel" })] })] }));
|
|
@@ -72,7 +72,11 @@ export const PROVIDER_HINTS = {
|
|
|
72
72
|
],
|
|
73
73
|
openai: [
|
|
74
74
|
{ key: "type", description: "Provider type (openai)", required: true },
|
|
75
|
-
{
|
|
75
|
+
{
|
|
76
|
+
key: "model",
|
|
77
|
+
description: "Model name (e.g., gpt-4o, gpt-4-turbo, gpt-3.5-turbo)",
|
|
78
|
+
required: true,
|
|
79
|
+
},
|
|
76
80
|
{ key: "apiKey", description: "API key (defaults to OPENAI_API_KEY env var)" },
|
|
77
81
|
{ key: "baseUrl", description: "Custom API base URL (for OpenAI-compatible services)" },
|
|
78
82
|
],
|
|
@@ -252,19 +252,13 @@ export function LLMProvidersEditor({ label, providers, onConfirm, onCancel, isFo
|
|
|
252
252
|
}, { isActive: isFocused && mode === "select-type" });
|
|
253
253
|
// Handle keyboard input for text editing modes
|
|
254
254
|
useInput((_input, key) => {
|
|
255
|
-
if (!isFocused ||
|
|
256
|
-
mode === "list" ||
|
|
257
|
-
mode === "select-type" ||
|
|
258
|
-
mode === "edit-provider")
|
|
255
|
+
if (!isFocused || mode === "list" || mode === "select-type" || mode === "edit-provider")
|
|
259
256
|
return;
|
|
260
257
|
if (key.escape) {
|
|
261
258
|
handleCancel();
|
|
262
259
|
}
|
|
263
260
|
}, {
|
|
264
|
-
isActive: isFocused &&
|
|
265
|
-
mode !== "list" &&
|
|
266
|
-
mode !== "select-type" &&
|
|
267
|
-
mode !== "edit-provider",
|
|
261
|
+
isActive: isFocused && mode !== "list" && mode !== "select-type" && mode !== "edit-provider",
|
|
268
262
|
});
|
|
269
263
|
// Handle keyboard input for edit-provider mode (viewing a provider)
|
|
270
264
|
useInput((input, key) => {
|
|
@@ -315,7 +309,11 @@ export function LLMProvidersEditor({ label, providers, onConfirm, onCancel, isFo
|
|
|
315
309
|
if (mode === "select-type") {
|
|
316
310
|
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "Select Provider Type" }), editingProvider && _jsxs(Text, { dimColor: true, children: [" for \"", editingProvider.name, "\""] })] }), PROVIDER_TYPES.map((type, index) => {
|
|
317
311
|
const isHighlighted = index === typeIndex;
|
|
318
|
-
return (_jsxs(Box, { children: [_jsx(Text, { color: isHighlighted ? "cyan" : undefined, children: isHighlighted ? "▸ " : " " }), _jsx(Text, { bold: isHighlighted, color: isHighlighted ? "cyan" : undefined, inverse: isHighlighted, children: type }), _jsxs(Text, { dimColor: true, children: ["
|
|
312
|
+
return (_jsxs(Box, { children: [_jsx(Text, { color: isHighlighted ? "cyan" : undefined, children: isHighlighted ? "▸ " : " " }), _jsx(Text, { bold: isHighlighted, color: isHighlighted ? "cyan" : undefined, inverse: isHighlighted, children: type }), _jsxs(Text, { dimColor: true, children: [" ", "-", " ", type === "anthropic"
|
|
313
|
+
? "Claude models"
|
|
314
|
+
: type === "openai"
|
|
315
|
+
? "GPT models"
|
|
316
|
+
: "Local models"] })] }, type));
|
|
319
317
|
}), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "j/k: navigate | Enter: select | Esc: cancel" }) })] }));
|
|
320
318
|
}
|
|
321
319
|
// Render name input mode
|
|
@@ -89,7 +89,7 @@ function highlightJson(jsonString) {
|
|
|
89
89
|
continue;
|
|
90
90
|
}
|
|
91
91
|
// Match brackets
|
|
92
|
-
const bracketMatch = remaining.match(/^[
|
|
92
|
+
const bracketMatch = remaining.match(/^[[\]{}]/);
|
|
93
93
|
if (bracketMatch) {
|
|
94
94
|
tokens.push({ type: "bracket", value: bracketMatch[0] });
|
|
95
95
|
remaining = remaining.slice(1);
|
|
@@ -16,7 +16,16 @@ export const CONFIG_SECTIONS = [
|
|
|
16
16
|
id: "cli",
|
|
17
17
|
label: "CLI",
|
|
18
18
|
icon: "⌨",
|
|
19
|
-
fields: [
|
|
19
|
+
fields: [
|
|
20
|
+
"cliProvider",
|
|
21
|
+
"cli.command",
|
|
22
|
+
"cli.args",
|
|
23
|
+
"cli.model",
|
|
24
|
+
"cli.yoloArgs",
|
|
25
|
+
"cli.promptArgs",
|
|
26
|
+
"cli.modelArgs",
|
|
27
|
+
"cli.fileArgs",
|
|
28
|
+
],
|
|
20
29
|
},
|
|
21
30
|
{
|
|
22
31
|
id: "docker",
|
|
@@ -52,7 +61,14 @@ export const CONFIG_SECTIONS = [
|
|
|
52
61
|
id: "chat",
|
|
53
62
|
label: "Chat",
|
|
54
63
|
icon: "💬",
|
|
55
|
-
fields: [
|
|
64
|
+
fields: [
|
|
65
|
+
"chat.enabled",
|
|
66
|
+
"chat.provider",
|
|
67
|
+
"chat.telegram",
|
|
68
|
+
"chat.slack",
|
|
69
|
+
"chat.discord",
|
|
70
|
+
"chat.responders",
|
|
71
|
+
],
|
|
56
72
|
},
|
|
57
73
|
{
|
|
58
74
|
id: "notifications",
|
|
@@ -84,6 +84,7 @@ export function escapeHtml(text) {
|
|
|
84
84
|
*/
|
|
85
85
|
export function stripAnsiCodes(text) {
|
|
86
86
|
// Match ANSI escape sequences: ESC[...m (SGR), ESC[...K (EL), etc.
|
|
87
|
+
// eslint-disable-next-line no-control-regex
|
|
87
88
|
return text.replace(/\x1B\[[0-9;]*[mKJHfsu]/g, "");
|
|
88
89
|
}
|
|
89
90
|
/**
|
package/dist/utils/config.d.ts
CHANGED
package/dist/utils/config.js
CHANGED
|
@@ -134,7 +134,9 @@ export function getProjectName() {
|
|
|
134
134
|
catch {
|
|
135
135
|
// Config not available, fall back to directory name
|
|
136
136
|
}
|
|
137
|
-
return basename(process.cwd())
|
|
137
|
+
return basename(process.cwd())
|
|
138
|
+
.toLowerCase()
|
|
139
|
+
.replace(/[^a-z0-9-]/g, "-");
|
|
138
140
|
}
|
|
139
141
|
export function loadPrompt() {
|
|
140
142
|
const promptPath = join(getRalphDir(), PROMPT_FILE);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|