opencode-ralph-loop
Advanced tools
+1
-1
| { | ||
| "name": "opencode-ralph-loop", | ||
| "version": "1.0.3", | ||
| "version": "1.0.4", | ||
| "description": "Minimal Ralph Loop plugin for opencode - auto-continues until task completion", | ||
@@ -5,0 +5,0 @@ "main": "src/index.ts", |
+24
-20
@@ -1,2 +0,2 @@ | ||
| import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, readdirSync, cpSync } from "fs"; | ||
| import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, cpSync } from "fs"; | ||
| import { dirname, join } from "path"; | ||
@@ -16,3 +16,2 @@ import { fileURLToPath } from "url"; | ||
| const STATE_FILENAME = "ralph-loop.local.md"; | ||
| const MESSAGE_DIR = join(process.env.HOME || "~", ".local/share/opencode/storage/message"); | ||
| const OPENCODE_CONFIG_DIR = join(process.env.HOME || "~", ".config/opencode"); | ||
@@ -151,24 +150,29 @@ const COMPLETION_TAG = /<promise>\s*DONE\s*<\/promise>/is; | ||
| // Check completion by scanning session messages | ||
| function isComplete(sessionId?: string): boolean { | ||
| if (!sessionId) return false; | ||
| // Check completion by fetching session messages via API | ||
| async function isComplete(client: any, sessionId: string): Promise<boolean> { | ||
| try { | ||
| const sessionMsgDir = join(MESSAGE_DIR, sessionId); | ||
| if (!existsSync(sessionMsgDir)) return false; | ||
| const response = await client.session.messages({ | ||
| path: { id: sessionId } | ||
| }); | ||
| const files = readdirSync(sessionMsgDir) | ||
| .filter(f => f.endsWith(".json")) | ||
| .sort() | ||
| .reverse(); | ||
| if (!response?.data) return false; | ||
| for (const file of files.slice(0, 10)) { | ||
| try { | ||
| const content = readFileSync(join(sessionMsgDir, file), "utf-8"); | ||
| if (COMPLETION_TAG.test(content)) { | ||
| return true; | ||
| // Check recent assistant messages for completion promise | ||
| const messages = response.data; | ||
| for (const msg of messages.slice(-10)) { | ||
| if (msg.role === "assistant") { | ||
| // Check parts for text content | ||
| const parts = msg.parts || []; | ||
| for (const part of parts) { | ||
| if (part.type === "text" && part.text) { | ||
| if (COMPLETION_TAG.test(part.text)) { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| } catch {} | ||
| } | ||
| } | ||
| } catch {} | ||
| } catch (e) { | ||
| console.error("[ralph-loop] Failed to check completion:", e); | ||
| } | ||
@@ -279,3 +283,3 @@ return false; | ||
| if (isComplete(sessionId)) { | ||
| if (await isComplete(client, sessionId)) { | ||
| console.log("[ralph-loop] Task complete - DONE promise found"); | ||
@@ -282,0 +286,0 @@ clearState(directory); |
21861
0.62%272
1.87%3
-25%