Features: - 30+ Custom Skills (cognitive, development, UI/UX, autonomous agents) - RalphLoop autonomous agent integration - Multi-AI consultation (Qwen) - Agent management system with sync capabilities - Custom hooks for session management - MCP servers integration - Plugin marketplace setup - Comprehensive installation script Components: - Skills: always-use-superpowers, ralph, brainstorming, ui-ux-pro-max, etc. - Agents: 100+ agents across engineering, marketing, product, etc. - Hooks: session-start-superpowers, qwen-consult, ralph-auto-trigger - Commands: /brainstorm, /write-plan, /execute-plan - MCP Servers: zai-mcp-server, web-search-prime, web-reader, zread - Binaries: ralphloop wrapper Installation: ./supercharge.sh
80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
import {
|
|
type AnalyzeOptions,
|
|
type AnalyzeResult,
|
|
type Config,
|
|
MAX_RECURSION_DEPTH,
|
|
} from '../../types.ts';
|
|
|
|
import { splitShellCommands } from '../shell.ts';
|
|
|
|
import { dangerousInText } from './dangerous-text.ts';
|
|
import { analyzeSegment, segmentChangesCwd } from './segment.ts';
|
|
|
|
const REASON_STRICT_UNPARSEABLE =
|
|
'Command could not be safely analyzed (strict mode). Verify manually.';
|
|
|
|
const REASON_RECURSION_LIMIT =
|
|
'Command exceeds maximum recursion depth and cannot be safely analyzed.';
|
|
|
|
export type InternalOptions = AnalyzeOptions & { config: Config };
|
|
|
|
export function analyzeCommandInternal(
|
|
command: string,
|
|
depth: number,
|
|
options: InternalOptions,
|
|
): AnalyzeResult | null {
|
|
if (depth >= MAX_RECURSION_DEPTH) {
|
|
return { reason: REASON_RECURSION_LIMIT, segment: command };
|
|
}
|
|
|
|
const segments = splitShellCommands(command);
|
|
|
|
// Strict mode: block if command couldn't be parsed (unclosed quotes, etc.)
|
|
// Detected when splitShellCommands returns a single segment containing the raw command
|
|
if (
|
|
options.strict &&
|
|
segments.length === 1 &&
|
|
segments[0]?.length === 1 &&
|
|
segments[0][0] === command &&
|
|
command.includes(' ')
|
|
) {
|
|
return { reason: REASON_STRICT_UNPARSEABLE, segment: command };
|
|
}
|
|
|
|
const originalCwd = options.cwd;
|
|
let effectiveCwd: string | null | undefined = options.cwd;
|
|
|
|
for (const segment of segments) {
|
|
const segmentStr = segment.join(' ');
|
|
|
|
if (segment.length === 1 && segment[0]?.includes(' ')) {
|
|
const textReason = dangerousInText(segment[0]);
|
|
if (textReason) {
|
|
return { reason: textReason, segment: segmentStr };
|
|
}
|
|
if (segmentChangesCwd(segment)) {
|
|
effectiveCwd = null;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
const reason = analyzeSegment(segment, depth, {
|
|
...options,
|
|
cwd: originalCwd,
|
|
effectiveCwd,
|
|
analyzeNested: (nestedCommand: string): string | null => {
|
|
return analyzeCommandInternal(nestedCommand, depth + 1, options)?.reason ?? null;
|
|
},
|
|
});
|
|
if (reason) {
|
|
return { reason, segment: segmentStr };
|
|
}
|
|
|
|
if (segmentChangesCwd(segment)) {
|
|
effectiveCwd = null;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|