From 940e49b44c3b91d95b57fb76d66a0646c66f7d03 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sat, 21 Feb 2026 05:30:05 +0900 Subject: [PATCH] fix(ralph-loop): use shared isRecord, fix quoted argument parsing for prompt and completion-promise --- src/hooks/ralph-loop/command-arguments.ts | 10 ++++++---- src/hooks/ralph-loop/session-reset-strategy.ts | 7 ++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/hooks/ralph-loop/command-arguments.ts b/src/hooks/ralph-loop/command-arguments.ts index adfa3df3..35d40dda 100644 --- a/src/hooks/ralph-loop/command-arguments.ts +++ b/src/hooks/ralph-loop/command-arguments.ts @@ -10,19 +10,21 @@ export type ParsedRalphLoopArguments = { const DEFAULT_PROMPT = "Complete the task as instructed" export function parseRalphLoopArguments(rawArguments: string): ParsedRalphLoopArguments { - const taskMatch = rawArguments.match(/^["'](.+?)["']/) - const promptCandidate = taskMatch?.[1] ?? (rawArguments.startsWith("--") ? "" : rawArguments.split(/\s+--/)[0]?.trim() ?? "") + const taskMatch = rawArguments.match(/^(["'])(.+?)\1/) + const promptCandidate = taskMatch?.[2] ?? (rawArguments.startsWith("--") ? "" : rawArguments.split(/\s+--/)[0]?.trim() ?? "") const prompt = promptCandidate || DEFAULT_PROMPT const maxIterationMatch = rawArguments.match(/--max-iterations=(\d+)/i) - const completionPromiseMatch = rawArguments.match(/--completion-promise=["']?([^"'\s]+)["']?/i) + const completionPromiseQuoted = rawArguments.match(/--completion-promise=(["'])(.+?)\1/i) + const completionPromiseUnquoted = rawArguments.match(/--completion-promise=([^\s"']+)/i) + const completionPromise = completionPromiseQuoted?.[2] ?? completionPromiseUnquoted?.[1] const strategyMatch = rawArguments.match(/--strategy=(reset|continue)/i) const strategyValue = strategyMatch?.[1]?.toLowerCase() return { prompt, maxIterations: maxIterationMatch ? Number.parseInt(maxIterationMatch[1], 10) : undefined, - completionPromise: completionPromiseMatch?.[1], + completionPromise, strategy: strategyValue === "reset" || strategyValue === "continue" ? strategyValue : undefined, } } diff --git a/src/hooks/ralph-loop/session-reset-strategy.ts b/src/hooks/ralph-loop/session-reset-strategy.ts index a352560b..d6854727 100644 --- a/src/hooks/ralph-loop/session-reset-strategy.ts +++ b/src/hooks/ralph-loop/session-reset-strategy.ts @@ -1,5 +1,6 @@ import type { PluginInput } from "@opencode-ai/plugin" -import { log } from "../../shared" +import { isRecord } from "../../shared/record-type-guard" +import { log } from "../../shared/logger" export async function createIterationSession( ctx: PluginInput, @@ -48,10 +49,6 @@ export async function selectSessionInTui( type SelectSessionApi = (args: { body: { sessionID: string } }) => Promise -function isRecord(value: unknown): value is Record { - return typeof value === "object" && value !== null -} - function getSelectSessionApi(client: unknown): SelectSessionApi | null { if (!isRecord(client)) { return null