@kenkaiiii/ggcoder 4.3.236 → 4.3.237

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.
Files changed (45) hide show
  1. package/dist/core/loop-breaker.d.ts +46 -0
  2. package/dist/core/loop-breaker.d.ts.map +1 -0
  3. package/dist/core/loop-breaker.js +79 -0
  4. package/dist/core/loop-breaker.js.map +1 -0
  5. package/dist/core/loop-breaker.test.d.ts +2 -0
  6. package/dist/core/loop-breaker.test.d.ts.map +1 -0
  7. package/dist/core/loop-breaker.test.js +110 -0
  8. package/dist/core/loop-breaker.test.js.map +1 -0
  9. package/dist/core/regrounding.d.ts +23 -0
  10. package/dist/core/regrounding.d.ts.map +1 -0
  11. package/dist/core/regrounding.js +21 -0
  12. package/dist/core/regrounding.js.map +1 -0
  13. package/dist/core/regrounding.test.d.ts +2 -0
  14. package/dist/core/regrounding.test.d.ts.map +1 -0
  15. package/dist/core/regrounding.test.js +38 -0
  16. package/dist/core/regrounding.test.js.map +1 -0
  17. package/dist/ui/App.d.ts.map +1 -1
  18. package/dist/ui/App.js +29 -2
  19. package/dist/ui/App.js.map +1 -1
  20. package/dist/ui/app-items.d.ts +20 -3
  21. package/dist/ui/app-items.d.ts.map +1 -1
  22. package/dist/ui/app-items.js +11 -0
  23. package/dist/ui/app-items.js.map +1 -1
  24. package/dist/ui/components/ChatInputStack.js +1 -1
  25. package/dist/ui/components/ChatInputStack.js.map +1 -1
  26. package/dist/ui/components/IdealHookMessage.d.ts +3 -1
  27. package/dist/ui/components/IdealHookMessage.d.ts.map +1 -1
  28. package/dist/ui/components/IdealHookMessage.js +4 -2
  29. package/dist/ui/components/IdealHookMessage.js.map +1 -1
  30. package/dist/ui/hooks/useAgentLoop.d.ts +7 -0
  31. package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
  32. package/dist/ui/hooks/useAgentLoop.js +108 -9
  33. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  34. package/dist/ui/hooks/useChatLayoutMeasurements.d.ts.map +1 -1
  35. package/dist/ui/hooks/useChatLayoutMeasurements.js +6 -7
  36. package/dist/ui/hooks/useChatLayoutMeasurements.js.map +1 -1
  37. package/dist/ui/render.d.ts.map +1 -1
  38. package/dist/ui/render.js +6 -0
  39. package/dist/ui/render.js.map +1 -1
  40. package/dist/ui/terminal-history.js +9 -7
  41. package/dist/ui/terminal-history.js.map +1 -1
  42. package/dist/ui/transcript/TranscriptRenderer.d.ts.map +1 -1
  43. package/dist/ui/transcript/TranscriptRenderer.js +1 -1
  44. package/dist/ui/transcript/TranscriptRenderer.js.map +1 -1
  45. package/package.json +3 -3
@@ -0,0 +1,46 @@
1
+ import type { Message } from "@kenkaiiii/gg-ai";
2
+ /**
3
+ * Loop-breaker hook — the mid-loop counterpart to the ideal review.
4
+ *
5
+ * Where the ideal review fires when the agent is about to STOP, the
6
+ * loop-breaker fires when the agent is STUCK: repeating the same failing
7
+ * action, hammering the same file, or degenerating into repeated output.
8
+ * The decision is pure arithmetic over signals useAgentLoop already
9
+ * collects, so the trigger itself costs nothing — only the (at most one)
10
+ * injected message costs a round-trip.
11
+ *
12
+ * Two independent detectors per the research:
13
+ * - tool-call level: signature repeats / same-file edits / failures.
14
+ * - text level: a streamed block repeating verbatim (high-temp / stuck
15
+ * token degeneration), which signature hashing alone never catches.
16
+ */
17
+ export interface LoopBreakStats {
18
+ /** Failed tool calls in an unbroken streak (reset by any success). */
19
+ consecutiveFailures: number;
20
+ /** Highest repeat count for any single tool-call signature this run. */
21
+ maxSignatureRepeats: number;
22
+ /** Highest number of edits to any single file this run. */
23
+ maxSameFileEdits: number;
24
+ /** Whether streamed assistant text degenerated into repetition. */
25
+ textRepetitionDetected: boolean;
26
+ }
27
+ export interface LoopBreakDecision {
28
+ shouldBreak: boolean;
29
+ reasons: string[];
30
+ }
31
+ export declare const LOOP_BREAK_PROMPT: string;
32
+ /**
33
+ * Stable signature for a tool call: name + canonicalized args. Key order is
34
+ * normalized so semantically identical calls hash identically.
35
+ */
36
+ export declare function toolCallSignature(name: string, args: unknown): string;
37
+ /**
38
+ * Detects verbatim repetition at the tail of streamed text — the model
39
+ * looping on a phrase/block. Scans candidate block lengths and checks how
40
+ * many times the trailing block repeats consecutively. Cheap: bounded to a
41
+ * fixed tail window.
42
+ */
43
+ export declare function detectTextRepetition(text: string): boolean;
44
+ export declare function evaluateLoopBreak(stats: LoopBreakStats): LoopBreakDecision;
45
+ export declare function buildLoopBreakMessage(reasons: readonly string[]): Message;
46
+ //# sourceMappingURL=loop-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-breaker.d.ts","sourceRoot":"","sources":["../../src/core/loop-breaker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,2DAA2D;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,sBAAsB,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAMD,eAAO,MAAM,iBAAiB,QAOuC,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAErE;AAmBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAiB1D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,iBAAiB,CAiB1E;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAMzE"}
@@ -0,0 +1,79 @@
1
+ const CONSECUTIVE_FAILURE_LIMIT = 3;
2
+ const SIGNATURE_REPEAT_LIMIT = 3;
3
+ const SAME_FILE_EDIT_LIMIT = 5;
4
+ export const LOOP_BREAK_PROMPT = "Stuck? You've repeated essentially the same action and it keeps failing or not advancing. " +
5
+ "Stop and break the pattern. Read the latest error or result literally \u2014 not what you " +
6
+ "expected it to say. Then question the assumption underneath your approach: the file, path, " +
7
+ "API, command, or premise you've been treating as true may be wrong. Either try a " +
8
+ "fundamentally different approach or, if you genuinely cannot make progress, stop and tell " +
9
+ "the user what's blocking you and what you need. Do NOT repeat the previous attempt with minor " +
10
+ "tweaks. Do not mention this note unless it changed your approach.";
11
+ /**
12
+ * Stable signature for a tool call: name + canonicalized args. Key order is
13
+ * normalized so semantically identical calls hash identically.
14
+ */
15
+ export function toolCallSignature(name, args) {
16
+ return `${name}\u0000${canonicalize(args)}`;
17
+ }
18
+ function canonicalize(value) {
19
+ if (value === null || typeof value !== "object") {
20
+ return JSON.stringify(value) ?? "null";
21
+ }
22
+ if (Array.isArray(value)) {
23
+ return `[${value.map(canonicalize).join(",")}]`;
24
+ }
25
+ const entries = Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
26
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalize(v)}`).join(",")}}`;
27
+ }
28
+ const TEXT_REPETITION_MIN_LENGTH = 40;
29
+ const TEXT_REPETITION_MIN_REPEATS = 3;
30
+ const TEXT_REPETITION_TAIL = 4096;
31
+ /**
32
+ * Detects verbatim repetition at the tail of streamed text — the model
33
+ * looping on a phrase/block. Scans candidate block lengths and checks how
34
+ * many times the trailing block repeats consecutively. Cheap: bounded to a
35
+ * fixed tail window.
36
+ */
37
+ export function detectTextRepetition(text) {
38
+ if (text.length < TEXT_REPETITION_MIN_LENGTH * TEXT_REPETITION_MIN_REPEATS) {
39
+ return false;
40
+ }
41
+ const tail = text.slice(-TEXT_REPETITION_TAIL);
42
+ const maxBlock = Math.floor(tail.length / TEXT_REPETITION_MIN_REPEATS);
43
+ for (let block = TEXT_REPETITION_MIN_LENGTH; block <= maxBlock; block++) {
44
+ const unit = tail.slice(tail.length - block);
45
+ let repeats = 1;
46
+ let offset = tail.length - block * 2;
47
+ while (offset >= 0 && tail.slice(offset, offset + block) === unit) {
48
+ repeats++;
49
+ offset -= block;
50
+ }
51
+ if (repeats >= TEXT_REPETITION_MIN_REPEATS)
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ export function evaluateLoopBreak(stats) {
57
+ const reasons = [];
58
+ if (stats.consecutiveFailures >= CONSECUTIVE_FAILURE_LIMIT) {
59
+ reasons.push(`${stats.consecutiveFailures} consecutive failed tool calls`);
60
+ }
61
+ if (stats.maxSignatureRepeats >= SIGNATURE_REPEAT_LIMIT) {
62
+ reasons.push(`identical tool call repeated ${stats.maxSignatureRepeats}x`);
63
+ }
64
+ if (stats.maxSameFileEdits >= SAME_FILE_EDIT_LIMIT) {
65
+ reasons.push(`${stats.maxSameFileEdits} edits to the same file`);
66
+ }
67
+ if (stats.textRepetitionDetected) {
68
+ reasons.push("repeated output detected");
69
+ }
70
+ return { shouldBreak: reasons.length > 0, reasons };
71
+ }
72
+ export function buildLoopBreakMessage(reasons) {
73
+ const reasonText = reasons.length > 0 ? ` Triggered because: ${reasons.join(", ")}.` : "";
74
+ return {
75
+ role: "user",
76
+ content: `${LOOP_BREAK_PROMPT}${reasonText}`,
77
+ };
78
+ }
79
+ //# sourceMappingURL=loop-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-breaker.js","sourceRoot":"","sources":["../../src/core/loop-breaker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=loop-breaker.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-breaker.test.d.ts","sourceRoot":"","sources":["../../src/core/loop-breaker.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,110 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildLoopBreakMessage, detectTextRepetition, evaluateLoopBreak, toolCallSignature, } from "./loop-breaker.js";
3
+ describe("toolCallSignature", () => {
4
+ it("is stable regardless of key order in args", () => {
5
+ const a = toolCallSignature("edit", { file_path: "a.ts", old: "x", new: "y" });
6
+ const b = toolCallSignature("edit", { new: "y", old: "x", file_path: "a.ts" });
7
+ expect(a).toBe(b);
8
+ });
9
+ it("differs when the tool name differs", () => {
10
+ expect(toolCallSignature("read", { file_path: "a.ts" })).not.toBe(toolCallSignature("write", { file_path: "a.ts" }));
11
+ });
12
+ it("differs when args differ", () => {
13
+ expect(toolCallSignature("read", { file_path: "a.ts" })).not.toBe(toolCallSignature("read", { file_path: "b.ts" }));
14
+ });
15
+ it("handles non-object args without throwing", () => {
16
+ expect(() => toolCallSignature("bash", "ls -la")).not.toThrow();
17
+ expect(toolCallSignature("bash", "ls")).toBe(toolCallSignature("bash", "ls"));
18
+ });
19
+ });
20
+ describe("detectTextRepetition", () => {
21
+ it("returns false for ordinary varied prose", () => {
22
+ const text = "I read the config file, then updated the handler, ran the tests, and verified the output looks correct now.";
23
+ expect(detectTextRepetition(text)).toBe(false);
24
+ });
25
+ it("detects a long block repeated consecutively at the tail", () => {
26
+ const block = "ERROR: could not resolve module './missing'\n";
27
+ expect(detectTextRepetition(block.repeat(6))).toBe(true);
28
+ });
29
+ it("does not trip on a block repeated only twice", () => {
30
+ const block = "Let me try a slightly different approach here.\n";
31
+ expect(detectTextRepetition(block.repeat(2))).toBe(false);
32
+ });
33
+ it("ignores short empty input", () => {
34
+ expect(detectTextRepetition("")).toBe(false);
35
+ expect(detectTextRepetition("ok")).toBe(false);
36
+ });
37
+ });
38
+ describe("evaluateLoopBreak", () => {
39
+ it("does not break on healthy progress", () => {
40
+ const decision = evaluateLoopBreak({
41
+ consecutiveFailures: 1,
42
+ maxSignatureRepeats: 1,
43
+ maxSameFileEdits: 2,
44
+ textRepetitionDetected: false,
45
+ });
46
+ expect(decision.shouldBreak).toBe(false);
47
+ expect(decision.reasons).toHaveLength(0);
48
+ });
49
+ it("breaks after repeated consecutive tool failures", () => {
50
+ const decision = evaluateLoopBreak({
51
+ consecutiveFailures: 3,
52
+ maxSignatureRepeats: 1,
53
+ maxSameFileEdits: 1,
54
+ textRepetitionDetected: false,
55
+ });
56
+ expect(decision.shouldBreak).toBe(true);
57
+ expect(decision.reasons.join(" ")).toContain("3 consecutive failed tool calls");
58
+ });
59
+ it("breaks when the identical tool call is repeated", () => {
60
+ const decision = evaluateLoopBreak({
61
+ consecutiveFailures: 0,
62
+ maxSignatureRepeats: 3,
63
+ maxSameFileEdits: 1,
64
+ textRepetitionDetected: false,
65
+ });
66
+ expect(decision.shouldBreak).toBe(true);
67
+ expect(decision.reasons.join(" ")).toContain("identical tool call");
68
+ });
69
+ it("breaks when one file is edited many times in a run", () => {
70
+ const decision = evaluateLoopBreak({
71
+ consecutiveFailures: 0,
72
+ maxSignatureRepeats: 1,
73
+ maxSameFileEdits: 5,
74
+ textRepetitionDetected: false,
75
+ });
76
+ expect(decision.shouldBreak).toBe(true);
77
+ expect(decision.reasons.join(" ")).toContain("5 edits to the same file");
78
+ });
79
+ it("breaks when streaming text degenerates into repetition", () => {
80
+ const decision = evaluateLoopBreak({
81
+ consecutiveFailures: 0,
82
+ maxSignatureRepeats: 1,
83
+ maxSameFileEdits: 1,
84
+ textRepetitionDetected: true,
85
+ });
86
+ expect(decision.shouldBreak).toBe(true);
87
+ expect(decision.reasons.join(" ")).toContain("repeated output");
88
+ });
89
+ });
90
+ describe("buildLoopBreakMessage", () => {
91
+ it("tells the model to stop, re-read the evidence, and question its assumption", () => {
92
+ const message = buildLoopBreakMessage(["3 consecutive failed tool calls"]);
93
+ expect(message.role).toBe("user");
94
+ expect(message.content).toContain("Stuck?");
95
+ expect(message.content).toContain("assumption");
96
+ expect(message.content).toContain("3 consecutive failed tool calls");
97
+ });
98
+ it("permits escalating to the user as a last resort", () => {
99
+ const message = buildLoopBreakMessage([]);
100
+ expect(message.content).toContain("tell the user");
101
+ expect(message.content).not.toContain("Triggered because");
102
+ });
103
+ it("does not instruct the model to narrate the note", () => {
104
+ const message = buildLoopBreakMessage(["identical tool call repeated 3x"]);
105
+ const content = message.content;
106
+ expect(content).toContain("Triggered because");
107
+ expect(content.toLowerCase()).toContain("do not mention this note");
108
+ });
109
+ });
110
+ //# sourceMappingURL=loop-breaker.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-breaker.test.js","sourceRoot":"","sources":["../../src/core/loop-breaker.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Message } from "@kenkaiiii/gg-ai";
2
+ /**
3
+ * Post-compaction re-grounding hook.
4
+ *
5
+ * Compaction summarizes earlier context, which is a known drift point: the
6
+ * model can quietly lose the verbatim original ask or a subtle constraint.
7
+ * After a compaction this run, inject the original request verbatim (the one
8
+ * piece of ground truth the summary may have lossily rewritten) so the model
9
+ * re-anchors before its next step. Fires at most once per compaction event.
10
+ *
11
+ * Per the "introspection alone fails" research, this injects concrete
12
+ * evidence (the literal original request) rather than asking the model to
13
+ * "think harder".
14
+ */
15
+ export interface RegroundingState {
16
+ /** A compaction/overflow-compaction happened during this run. */
17
+ compactionOccurred: boolean;
18
+ /** A re-grounding message was already injected for this compaction. */
19
+ alreadyInjected: boolean;
20
+ }
21
+ export declare function shouldReground(state: RegroundingState): boolean;
22
+ export declare function buildRegroundingMessage(originalRequest: string): Message;
23
+ //# sourceMappingURL=regrounding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regrounding.d.ts","sourceRoot":"","sources":["../../src/core/regrounding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,kBAAkB,EAAE,OAAO,CAAC;IAC5B,uEAAuE;IACvE,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAE/D;AAED,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAkBxE"}
@@ -0,0 +1,21 @@
1
+ export function shouldReground(state) {
2
+ return state.compactionOccurred && !state.alreadyInjected;
3
+ }
4
+ export function buildRegroundingMessage(originalRequest) {
5
+ const trimmed = originalRequest.trim();
6
+ const pin = trimmed.length > 0
7
+ ? `\n\nThe user's original request was:\n\n ${trimmed}\n\n`
8
+ : " The original request is in the earlier messages that remain. ";
9
+ return {
10
+ role: "user",
11
+ content: "Re-ground. The conversation was just compacted, so earlier detail is now a summary and " +
12
+ "easy to drift from." +
13
+ pin +
14
+ "Before continuing, re-anchor on two things: that original request, and the specific " +
15
+ "objective you're working on right now. Verify your next step still serves the original " +
16
+ "ask \u2014 not a reshaped or narrowed version of it. If the summary dropped a constraint, " +
17
+ "file, or requirement you were tracking, recover it from the messages that remain before " +
18
+ "acting. Then continue. Do not restate this note; just proceed correctly.",
19
+ };
20
+ }
21
+ //# sourceMappingURL=regrounding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regrounding.js","sourceRoot":"","sources":["../../src/core/regrounding.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,cAAc,CAAC,KAAuB;IACpD,OAAO,KAAK,CAAC,kBAAkB,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,eAAuB;IAC7D,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,GAAG,GACP,OAAO,CAAC,MAAM,GAAG,CAAC;QAChB,CAAC,CAAC,6CAA6C,OAAO,MAAM;QAC5D,CAAC,CAAC,gEAAgE,CAAC;IACvE,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EACL,yFAAyF;YACzF,qBAAqB;YACrB,GAAG;YACH,sFAAsF;YACtF,yFAAyF;YACzF,4FAA4F;YAC5F,0FAA0F;YAC1F,0EAA0E;KAC7E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=regrounding.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regrounding.test.d.ts","sourceRoot":"","sources":["../../src/core/regrounding.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildRegroundingMessage, shouldReground } from "./regrounding.js";
3
+ describe("shouldReground", () => {
4
+ it("fires once after a compaction occurs", () => {
5
+ expect(shouldReground({ compactionOccurred: true, alreadyInjected: false })).toBe(true);
6
+ });
7
+ it("does not fire when no compaction has happened", () => {
8
+ expect(shouldReground({ compactionOccurred: false, alreadyInjected: false })).toBe(false);
9
+ });
10
+ it("does not fire twice for the same compaction", () => {
11
+ expect(shouldReground({ compactionOccurred: true, alreadyInjected: true })).toBe(false);
12
+ });
13
+ });
14
+ describe("buildRegroundingMessage", () => {
15
+ it("pins the original request verbatim", () => {
16
+ const original = "Rename the qty field to quantity everywhere in inventory.ts";
17
+ const message = buildRegroundingMessage(original);
18
+ expect(message.role).toBe("user");
19
+ expect(message.content).toContain("Re-ground");
20
+ expect(message.content).toContain(original);
21
+ });
22
+ it("explains that context was compacted and warns against drift", () => {
23
+ const content = buildRegroundingMessage("do the thing").content;
24
+ expect(content).toContain("compacted");
25
+ expect(content.toLowerCase()).toContain("drift");
26
+ });
27
+ it("does not instruct the model to narrate the note", () => {
28
+ const content = buildRegroundingMessage("do the thing").content;
29
+ expect(content.toLowerCase()).toContain("do not restate");
30
+ });
31
+ it("trims whitespace and tolerates an empty original request", () => {
32
+ const message = buildRegroundingMessage(" ");
33
+ expect(message.role).toBe("user");
34
+ expect(message.content).toContain("Re-ground");
35
+ expect(message.content).not.toContain('""');
36
+ });
37
+ });
38
+ //# sourceMappingURL=regrounding.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regrounding.test.js","sourceRoot":"","sources":["../../src/core/regrounding.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE3E,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,cAAc,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,cAAc,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,cAAc,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,QAAQ,GAAG,6DAA6D,CAAC;QAC/E,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,OAAO,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAC,OAAiB,CAAC;QAC1E,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,OAAO,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAC,OAAiB,CAAC;QAC1E,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"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"}
package/dist/ui/App.js CHANGED
@@ -44,6 +44,8 @@ import { buildUserContentWithAttachments } from "./prompt-routing.js";
44
44
  import { submitPromptCommand } from "./submit-prompt-command.js";
45
45
  import { handleUiSlashCommand } from "./submit-slash-commands.js";
46
46
  import { buildIdealReviewMessage, evaluateIdealReview } from "../core/ideal-review.js";
47
+ import { buildLoopBreakMessage, evaluateLoopBreak } from "../core/loop-breaker.js";
48
+ import { buildRegroundingMessage } from "../core/regrounding.js";
47
49
  import { getNextThinkingLevel, isThinkingLevelSupported } from "./thinking-level.js";
48
50
  import { getDoneFlushDecision, shouldTopSpaceAfterPrintedAgentBoundary, shouldTopSpaceStreamingAssistant, } from "./layout-decisions.js";
49
51
  import { isTranscriptSpacingItem } from "./transcript/spacing.js";
@@ -56,7 +58,7 @@ import { pickDurationVerb } from "./duration-summary.js";
56
58
  import { toErrorItem } from "./error-item.js";
57
59
  import { addLinesChanged, buildSessionSummary, createSessionStats, recordServerToolCall, recordToolEnd, recordTurnEnd, } from "./session-summary.js";
58
60
  import { compactHistory, getNextGeneratedItemId, isActiveItem, isSameAssistantText, normalizeAssistantText, partitionCompleted, pinStreamingTextBeforeToolBoundary, removeItemsWithIds, uniqueItemsById, } from "./item-helpers.js";
59
- import { IDEAL_HOOK_NOTICE_TEXT, lastVisibleTranscriptItem } from "./app-items.js";
61
+ import { IDEAL_HOOK_NOTICE_TEXT, LOOP_BREAK_NOTICE_TEXT, REGROUNDING_NOTICE_TEXT, lastVisibleTranscriptItem, } from "./app-items.js";
60
62
  export { buildUserContentWithAttachments, routePromptCommandInput } from "./prompt-routing.js";
61
63
  export { getNextThinkingLevel } from "./thinking-level.js";
62
64
  export { getChatControlsLayoutDecision, getDoneFlushDecision, getScrollStabilizationDecision, getStaticHistoryKey, hasParagraphBreakLiveUserMessage, isTallLiveUserMessage, shouldHideHistoryForOverlayView, shouldHideStaticItemsForOverlayView, shouldStabilizeOverlayPaneRerender, shouldTopSpaceAfterPrintedAgentBoundary, shouldTopSpaceAssistantAfterToolBoundary, shouldTopSpaceStreamingAssistant, } from "./layout-decisions.js";
@@ -580,10 +582,35 @@ export function App(props) {
580
582
  });
581
583
  setLiveItems((prev) => [
582
584
  ...prev,
583
- { kind: "ideal_hook", text: IDEAL_HOOK_NOTICE_TEXT, id: getId() },
585
+ { kind: "ideal_hook", text: IDEAL_HOOK_NOTICE_TEXT, tone: "review", id: getId() },
584
586
  ]);
585
587
  return buildIdealReviewMessage(decision.reasons);
586
588
  },
589
+ getLoopBreakMessage: (stats) => {
590
+ if (!idealReviewEnabledRef.current)
591
+ return null;
592
+ const decision = evaluateLoopBreak(stats);
593
+ if (!decision.shouldBreak)
594
+ return null;
595
+ log("INFO", "loop-break", "Injecting loop-break nudge", {
596
+ reasons: decision.reasons.join(", "),
597
+ });
598
+ setLiveItems((prev) => [
599
+ ...prev,
600
+ { kind: "ideal_hook", text: LOOP_BREAK_NOTICE_TEXT, tone: "warning", id: getId() },
601
+ ]);
602
+ return buildLoopBreakMessage(decision.reasons);
603
+ },
604
+ getRegroundingMessage: (originalRequest) => {
605
+ if (!idealReviewEnabledRef.current)
606
+ return null;
607
+ log("INFO", "reground", "Injecting re-grounding after compaction", {});
608
+ setLiveItems((prev) => [
609
+ ...prev,
610
+ { kind: "ideal_hook", text: REGROUNDING_NOTICE_TEXT, tone: "info", id: getId() },
611
+ ]);
612
+ return buildRegroundingMessage(originalRequest);
613
+ },
587
614
  }, {
588
615
  onComplete: useCallback(() => {
589
616
  persistNewMessages();