SLOPSHOPPER

sysinit-output

One-pass local response cleanup without agent retries

newprocess
A shopper browsing a rack in a slop shop
Source 1 files
hooks/register.ts 68 lines
1import type { Register, TurnStepChunk } from "claude-code";
2
3export const register: Register = (on) => {
4  on("turn.step", async function* ($, e, next) {
5    if (e.agentId) return yield* next(e);
6    const pending: TurnStepChunk[] = [];
7    let passthrough = false;
8    let size = 0;
9    try {
10      for await (const chunk of next(e)) {
11        if (passthrough) {
12          yield chunk;
13          continue;
14        }
15        pending.push(chunk);
16        if (chunk.kind === "text") size += chunk.text.length;
17        if (chunk.kind === "tool" || size > 24000) {
18          passthrough = true;
19          yield* pending;
20          pending.length = 0;
21        }
22      }
23    } catch (error) {
24      yield* pending;
25      throw error;
26    }
27    if (passthrough) return;
28    const stop = pending.findLast((chunk) => chunk.kind === "stop");
29    if (stop?.kind === "stop" && stop.stopReason === "end_turn") {
30      const texts = pending.filter((chunk) => chunk.kind === "text");
31      // Keep separate content blocks and all engine handles in their original order.
32      const indices = new Set(texts.map((chunk) => chunk.index));
33      if (indices.size === 1) {
34        const original = texts.map((chunk) => chunk.text).join("");
35        try {
36          const result = await $.process.run(["@rewriter@"], {
37            stdin: JSON.stringify({ text: original }),
38            timeoutMs: 16000,
39          });
40          if (result.exitCode === 0) {
41            const reply: unknown = JSON.parse(result.stdout);
42            if (
43              typeof reply === "object" &&
44              reply !== null &&
45              "text" in reply &&
46              typeof reply.text === "string"
47            ) {
48              let first = true;
49              for (const chunk of pending) {
50                if (chunk.kind === "text") {
51                  yield { ...chunk, text: first ? reply.text : "" };
52                  first = false;
53                } else yield chunk;
54              }
55              return;
56            }
57          }
58        } catch {
59          $.ui.log("Output cleanup unavailable; kept the original response.", {
60            to: "debug",
61          });
62        }
63      }
64    }
65    yield* pending;
66  });
67};
68