@w32191/just-loop 0.1.7 → 0.1.9

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.
@@ -4,10 +4,10 @@ export function parseRalphLoopCommand(input) {
4
4
  if (trimmed === "/cancel-ralph") {
5
5
  return { kind: "cancel" };
6
6
  }
7
- if (!/^\/ralph-loop(?:\s|$)/.test(trimmed)) {
7
+ if (!/^\/just-loop(?:\s|$)/.test(trimmed)) {
8
8
  return null;
9
9
  }
10
- let rest = trimmed.slice("/ralph-loop".length);
10
+ let rest = trimmed.slice("/just-loop".length);
11
11
  let maxIterations;
12
12
  let completionPromise = DEFAULT_COMPLETION_PROMISE;
13
13
  while (true) {
@@ -41,8 +41,8 @@ This will:
41
41
  Check if a loop is active and cancel it. Inform the user of the result.`;
42
42
  export function getBuiltinCommands() {
43
43
  return {
44
- "ralph-loop": {
45
- name: "ralph-loop",
44
+ "just-loop": {
45
+ name: "just-loop",
46
46
  description: "(builtin) Start self-referential development loop until completion",
47
47
  template: `<command-instruction>
48
48
  ${RALPH_LOOP_TEMPLATE}
@@ -1,10 +1,7 @@
1
1
  function hasInterruptCommand(input) {
2
2
  if (!input || typeof input !== "object")
3
3
  return false;
4
- const properties = input.properties;
5
- if (!properties || typeof properties !== "object")
6
- return false;
7
- return properties.command === "session.interrupt";
4
+ return input.command === "session.interrupt";
8
5
  }
9
6
  export async function handleTuiCommandExecute(input, core) {
10
7
  if (!hasInterruptCommand(input))
@@ -257,7 +257,14 @@ export function createLoopCore(deps) {
257
257
  showToast("Ralph Loop", `Injecting next continuation in ${remaining - 1}s. Use interrupt to cancel once.`, "warning");
258
258
  }
259
259
  }
260
- const promptGate = await runStateMutation(async () => {
260
+ const dispatchToken = randomUUID();
261
+ const continuationPrompt = buildContinuationPrompt({
262
+ iteration: nextIteration,
263
+ prompt: continuationState.prompt,
264
+ completionPromise: continuationState.completion_promise,
265
+ maxIterations: continuationState.max_iterations,
266
+ });
267
+ const dispatchResult = await runStateMutation(async () => {
261
268
  const currentState = await readCurrentState(event.sessionID, incarnationToken);
262
269
  if (!currentState?.pending_continuation)
263
270
  return { kind: "aborted" };
@@ -270,13 +277,6 @@ export function createLoopCore(deps) {
270
277
  await writeState(deps.rootDir, nextState);
271
278
  return { kind: "cancelled" };
272
279
  }
273
- const dispatchToken = randomUUID();
274
- const prompt = buildContinuationPrompt({
275
- iteration: nextIteration,
276
- prompt: currentState.prompt,
277
- completionPromise: currentState.completion_promise,
278
- maxIterations: currentState.max_iterations,
279
- });
280
280
  await writeState(deps.rootDir, {
281
281
  ...currentState,
282
282
  pending_continuation: {
@@ -285,23 +285,30 @@ export function createLoopCore(deps) {
285
285
  dispatch_token: dispatchToken,
286
286
  },
287
287
  });
288
- try {
289
- await deps.adapter.prompt(event.sessionID, prompt);
290
- }
291
- catch (error) {
288
+ });
289
+ if (dispatchResult?.kind === "aborted" || dispatchResult?.kind === "cancelled") {
290
+ return;
291
+ }
292
+ try {
293
+ await deps.adapter.prompt(event.sessionID, continuationPrompt);
294
+ }
295
+ catch (error) {
296
+ await runStateMutation(async () => {
292
297
  const latest = await readCurrentState(event.sessionID, incarnationToken);
293
- if (latest?.pending_continuation?.dispatch_token === dispatchToken) {
294
- const nextState = { ...latest };
295
- delete nextState.pending_continuation;
296
- await writeState(deps.rootDir, nextState);
297
- }
298
- throw error;
299
- }
298
+ if (latest?.pending_continuation?.dispatch_token !== dispatchToken)
299
+ return;
300
+ const nextState = { ...latest };
301
+ delete nextState.pending_continuation;
302
+ await writeState(deps.rootDir, nextState);
303
+ });
304
+ throw error;
305
+ }
306
+ await runStateMutation(async () => {
300
307
  const latest = await readCurrentState(event.sessionID, incarnationToken);
301
308
  if (!latest?.pending_continuation)
302
- return { kind: "aborted" };
309
+ return;
303
310
  if (latest.pending_continuation.dispatch_token !== dispatchToken)
304
- return { kind: "aborted" };
311
+ return;
305
312
  const nextState = {
306
313
  ...latest,
307
314
  iteration: nextIteration,
@@ -309,21 +316,31 @@ export function createLoopCore(deps) {
309
316
  };
310
317
  delete nextState.pending_continuation;
311
318
  await writeState(deps.rootDir, nextState);
312
- return { kind: "dispatched" };
313
319
  });
314
- if (promptGate.kind !== "dispatched")
315
- return;
316
320
  }
317
321
  if (wait) {
318
322
  showToast("Ralph Loop", "Injected Ralph Loop continuation.", "success");
319
323
  return;
320
324
  }
321
- await deps.adapter.prompt(event.sessionID, buildContinuationPrompt({
322
- iteration: nextIteration,
323
- prompt: continuationState.prompt,
324
- completionPromise: continuationState.completion_promise,
325
- maxIterations: continuationState.max_iterations,
326
- }));
325
+ try {
326
+ await deps.adapter.prompt(event.sessionID, buildContinuationPrompt({
327
+ iteration: nextIteration,
328
+ prompt: continuationState.prompt,
329
+ completionPromise: continuationState.completion_promise,
330
+ maxIterations: continuationState.max_iterations,
331
+ }));
332
+ }
333
+ catch (error) {
334
+ await runStateMutation(async () => {
335
+ const currentState = await readCurrentState(event.sessionID, incarnationToken);
336
+ if (!currentState?.pending_continuation)
337
+ return;
338
+ const nextState = { ...currentState };
339
+ delete nextState.pending_continuation;
340
+ await writeState(deps.rootDir, nextState);
341
+ });
342
+ throw error;
343
+ }
327
344
  await runStateMutation(async () => {
328
345
  const currentState = await readState(deps.rootDir);
329
346
  if (!currentState ||
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@w32191/just-loop",
3
3
  "type": "module",
4
- "version": "0.1.7",
4
+ "version": "0.1.9",
5
5
  "description": "OpenCode plugin package for just-loop.",
6
6
  "license": "MIT",
7
7
  "repository": {