fix(plugin): handle raw /ulw-loop commands appearing after injected messages
Fix parseRawLoopSlashCommand to correctly extract and parse loop commands that appear after injected background task messages (e.g., "[BACKGROUND TASK COMPLETED]"). Previously, the function only checked if the entire message started with a slash command, failing when injected content preceded the command. 🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
@@ -136,6 +136,51 @@ describe("createChatMessageHandler - /ulw-loop raw slash fallback", () => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("starts ultrawork loop when injected messages appear before the raw /ulw-loop command", async () => {
|
||||||
|
// given
|
||||||
|
const startLoopCalls: Array<{
|
||||||
|
sessionID: string
|
||||||
|
prompt: string
|
||||||
|
options: Record<string, unknown>
|
||||||
|
}> = []
|
||||||
|
const args = createMockHandlerArgs()
|
||||||
|
args.hooks.ralphLoop = {
|
||||||
|
startLoop: (sessionID: string, prompt: string, options?: Record<string, unknown>) => {
|
||||||
|
startLoopCalls.push({ sessionID, prompt, options: options ?? {} })
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
cancelLoop: () => true,
|
||||||
|
}
|
||||||
|
const handler = createChatMessageHandler(args)
|
||||||
|
const input = createMockInput("sisyphus")
|
||||||
|
const output: ChatMessageHandlerOutput = {
|
||||||
|
message: {},
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: "[BACKGROUND TASK COMPLETED]\nPlan finished.\n\n---\n\n/ulw-loop \"Ship feature\" --strategy=continue",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
// when
|
||||||
|
await handler(input, output)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(startLoopCalls).toEqual([
|
||||||
|
{
|
||||||
|
sessionID: "test-session",
|
||||||
|
prompt: "Ship feature",
|
||||||
|
options: {
|
||||||
|
ultrawork: true,
|
||||||
|
maxIterations: undefined,
|
||||||
|
completionPromise: undefined,
|
||||||
|
strategy: "continue",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function createMockInput(agent?: string, model?: { providerID: string; modelID: string }) {
|
function createMockInput(agent?: string, model?: { providerID: string; modelID: string }) {
|
||||||
|
|||||||
@@ -90,17 +90,24 @@ function getStoredMainSessionModel(
|
|||||||
|
|
||||||
function parseRawLoopSlashCommand(promptText: string): RawLoopCommand | null {
|
function parseRawLoopSlashCommand(promptText: string): RawLoopCommand | null {
|
||||||
const trimmed = promptText.trim()
|
const trimmed = promptText.trim()
|
||||||
|
const commandText = trimmed.startsWith("/")
|
||||||
|
? trimmed
|
||||||
|
: trimmed
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.filter((line) => /^\/(?:ralph-loop|ulw-loop|cancel-ralph)\b/i.test(line))
|
||||||
|
.at(-1)
|
||||||
|
|
||||||
if (!trimmed.startsWith("/")) {
|
if (!commandText) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const cancelMatch = trimmed.match(/^\/cancel-ralph(?:\s+.*)?$/i)
|
const cancelMatch = commandText.match(/^\/cancel-ralph(?:\s+.*)?$/i)
|
||||||
if (cancelMatch) {
|
if (cancelMatch) {
|
||||||
return { command: "cancel-ralph", args: "" }
|
return { command: "cancel-ralph", args: "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
const loopMatch = trimmed.match(/^\/(ralph-loop|ulw-loop)\s*([\s\S]*)$/i)
|
const loopMatch = commandText.match(/^\/(ralph-loop|ulw-loop)\s*([\s\S]*)$/i)
|
||||||
if (!loopMatch) {
|
if (!loopMatch) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user