@simonepri/refined-antigravity-acp 1.2.1 → 1.2.2

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.
@@ -3,18 +3,25 @@
3
3
  * When a user cancels an in-flight turn via `session/cancel`, upstream `agy_acp_server`
4
4
  * leaks internal Go/Python cancellation error strings (`"context canceledThe request was cancelled by the client."`)
5
5
  * directly into assistant message stream chunks before terminating the turn.
6
+ * Additionally, if a subsequent prompt is sent immediately after cancellation before upstream has finished
7
+ * unwinding, raw agy fails or crashes with concurrent receive_steps errors.
6
8
  *
7
9
  * Solution:
8
- * Intercepts inbound `session/update` chunks matching upstream cancellation error strings
9
- * and silently drops them, ensuring the editor message feed remains clean.
10
+ * Intercepts inbound `session/update` chunks matching upstream cancellation error strings and drops them,
11
+ * preserves terminal `tool_call_update` status notifications so client UIs complete running tools,
12
+ * waits for upstream's natural cancellation response with a safety timeout fallback, and queues any
13
+ * subsequent outbound prompt until the previous cancellation has completely unwound.
10
14
  */
11
15
  import { type AcpFix, type AcpStreamMessage } from "../../core/types.js";
12
16
  export declare const CANCELLATION_ERROR_REGEX: RegExp;
13
17
  export declare const CONCURRENT_RECEIVE_STEPS_REGEX: RegExp;
14
- export declare const CANCEL_PROMPT_SETTLED_KEY = "cancelPromptSettled";
18
+ export declare const DEFAULT_CANCELLATION_TIMEOUT_MS = 2500;
15
19
  export declare function isCancellationText(text: string): boolean;
16
20
  export declare function extractMessageChunkText(msg: AcpStreamMessage): string | null;
17
- export declare function createCancellationLeakFix(): AcpFix;
21
+ export interface CancellationOptions {
22
+ timeoutMs?: number;
23
+ }
24
+ export declare function createCancellationLeakFix(options?: CancellationOptions): AcpFix;
18
25
  export declare const cancellationLeakFix: AcpFix;
19
26
  export declare const interruptionCleanupFix: AcpFix;
20
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/fixes/cancellation-leak/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAKL,KAAK,MAAM,EACX,KAAK,gBAAgB,EAItB,MAAM,qBAAqB,CAAC;AAG7B,eAAO,MAAM,wBAAwB,QACkD,CAAC;AAExF,eAAO,MAAM,8BAA8B,QACmG,CAAC;AAE/I,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAE/D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASxD;AAiBD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAK5E;AAgFD,wBAAgB,yBAAyB,IAAI,MAAM,CA+ClD;AAED,eAAO,MAAM,mBAAmB,QAA8B,CAAC;AAC/D,eAAO,MAAM,sBAAsB,QAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/fixes/cancellation-leak/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAKL,KAAK,MAAM,EACX,KAAK,gBAAgB,EAItB,MAAM,qBAAqB,CAAC;AAG7B,eAAO,MAAM,wBAAwB,QACkD,CAAC;AAExF,eAAO,MAAM,8BAA8B,QACmG,CAAC;AAE/I,eAAO,MAAM,+BAA+B,OAAO,CAAC;AAEpD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASxD;AAiBD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAK5E;AAeD,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6GD,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAkD/E;AAED,eAAO,MAAM,mBAAmB,QAA8B,CAAC;AAC/D,eAAO,MAAM,sBAAsB,QAAsB,CAAC"}
@@ -3,16 +3,20 @@
3
3
  * When a user cancels an in-flight turn via `session/cancel`, upstream `agy_acp_server`
4
4
  * leaks internal Go/Python cancellation error strings (`"context canceledThe request was cancelled by the client."`)
5
5
  * directly into assistant message stream chunks before terminating the turn.
6
+ * Additionally, if a subsequent prompt is sent immediately after cancellation before upstream has finished
7
+ * unwinding, raw agy fails or crashes with concurrent receive_steps errors.
6
8
  *
7
9
  * Solution:
8
- * Intercepts inbound `session/update` chunks matching upstream cancellation error strings
9
- * and silently drops them, ensuring the editor message feed remains clean.
10
+ * Intercepts inbound `session/update` chunks matching upstream cancellation error strings and drops them,
11
+ * preserves terminal `tool_call_update` status notifications so client UIs complete running tools,
12
+ * waits for upstream's natural cancellation response with a safety timeout fallback, and queues any
13
+ * subsequent outbound prompt until the previous cancellation has completely unwound.
10
14
  */
11
15
  import { ACP_METHODS, SESSION_UPDATES, STOP_REASONS, isMethod, } from "../../core/types.js";
12
- import { extractSessionId, getFixData, setFixData } from "../../core/session-cache.js";
16
+ import { extractSessionId } from "../../core/session-cache.js";
13
17
  export const CANCELLATION_ERROR_REGEX = /^(?:context\s+canceled)?\s*The\s+request\s+was\s+cancelled\s+by\s+the\s+client\.?$/i;
14
18
  export const CONCURRENT_RECEIVE_STEPS_REGEX = /^Agent connection was lost and could not be re-established:\s*Concurrent receive_steps\(\) calls are not supported on this connection\.?$/i;
15
- export const CANCEL_PROMPT_SETTLED_KEY = "cancelPromptSettled";
19
+ export const DEFAULT_CANCELLATION_TIMEOUT_MS = 2500;
16
20
  export function isCancellationText(text) {
17
21
  const trimmed = text.trim();
18
22
  if (!trimmed)
@@ -46,15 +50,20 @@ export function extractMessageChunkText(msg) {
46
50
  return null;
47
51
  return extractContentText(update.content);
48
52
  }
49
- function handleOutboundPrompt(msg, state) {
53
+ async function handleOutboundPrompt(msg, state) {
50
54
  const sessionId = extractSessionId(msg);
51
55
  const id = msg.id;
52
- if (sessionId && id !== undefined && id !== null) {
53
- state.activePrompts.set(sessionId, id);
54
- state.cancelledSessions.delete(sessionId);
56
+ if (sessionId) {
57
+ const cancelling = state.cancellingSessions.get(sessionId);
58
+ if (cancelling) {
59
+ await cancelling.promise;
60
+ }
61
+ if (id !== undefined && id !== null) {
62
+ state.activePrompts.set(sessionId, id);
63
+ }
55
64
  }
56
65
  }
57
- function handleOutboundCancel(msg, context, state) {
66
+ function handleOutboundCancel(msg, context, state, timeoutMs) {
58
67
  const sessionId = extractSessionId(msg);
59
68
  if (!sessionId)
60
69
  return;
@@ -62,58 +71,85 @@ function handleOutboundCancel(msg, context, state) {
62
71
  if (promptId === undefined)
63
72
  return;
64
73
  state.activePrompts.delete(sessionId);
65
- state.cancelledSessions.add(sessionId);
66
- state.cancelledPromptIds.add(promptId);
67
- const alreadySettled = context.session &&
68
- getFixData(context.session, CANCEL_PROMPT_SETTLED_KEY) === promptId;
69
- if (alreadySettled)
74
+ if (state.cancellingSessions.has(sessionId))
70
75
  return;
71
- if (context.session) {
72
- setFixData(context.session, CANCEL_PROMPT_SETTLED_KEY, promptId);
73
- }
74
- const cancelResponse = {
75
- jsonrpc: "2.0",
76
- id: promptId,
77
- result: { stopReason: STOP_REASONS.CANCELLED },
78
- };
79
- context.forwardInbound?.(cancelResponse);
80
- }
81
- function tryHandleCancelledPrompt(id, sessionId, state) {
82
- if (!state.cancelledPromptIds.has(id))
83
- return false;
84
- state.cancelledPromptIds.delete(id);
85
- if (sessionId)
86
- state.cancelledSessions.delete(sessionId);
87
- return true;
76
+ let resolveFn;
77
+ const promise = new Promise((resolve) => {
78
+ resolveFn = resolve;
79
+ });
80
+ const timer = setTimeout(() => {
81
+ const current = state.cancellingSessions.get(sessionId);
82
+ if (current && current.promptId === promptId) {
83
+ state.cancellingSessions.delete(sessionId);
84
+ state.suppressedLateResponseIds.add(promptId);
85
+ if (context.session) {
86
+ context.session.needsRecycle = true;
87
+ }
88
+ const cancelResponse = {
89
+ jsonrpc: "2.0",
90
+ id: promptId,
91
+ result: { stopReason: STOP_REASONS.CANCELLED },
92
+ };
93
+ context.forwardInbound?.(cancelResponse);
94
+ resolveFn();
95
+ }
96
+ }, timeoutMs);
97
+ timer.unref?.();
98
+ state.cancellingSessions.set(sessionId, {
99
+ promptId,
100
+ timer,
101
+ promise,
102
+ resolve: resolveFn,
103
+ });
88
104
  }
89
- function handleInboundPromptId(msg, context, state) {
105
+ function handleInboundPromptId(msg, _context, state) {
90
106
  const id = msg.id;
91
107
  if (id === null || id === undefined)
92
108
  return false;
93
- const sessionId = extractSessionId(msg) ?? context.session?.sessionId;
94
- if (tryHandleCancelledPrompt(id, sessionId, state)) {
109
+ if (state.suppressedLateResponseIds.has(id)) {
110
+ state.suppressedLateResponseIds.delete(id);
95
111
  return true;
96
112
  }
97
- if (sessionId && state.activePrompts.get(sessionId) === id) {
98
- state.activePrompts.delete(sessionId);
113
+ for (const [sessId, cancelling] of state.cancellingSessions.entries()) {
114
+ if (cancelling.promptId === id) {
115
+ clearTimeout(cancelling.timer);
116
+ state.cancellingSessions.delete(sessId);
117
+ cancelling.resolve();
118
+ return false;
119
+ }
120
+ }
121
+ for (const [sessId, promptId] of state.activePrompts.entries()) {
122
+ if (promptId === id) {
123
+ state.activePrompts.delete(sessId);
124
+ break;
125
+ }
99
126
  }
100
127
  return false;
101
128
  }
102
- export function createCancellationLeakFix() {
129
+ function isSuppressedDuringCancellation(msg, sessionId, state) {
130
+ if (!sessionId || !state.cancellingSessions.has(sessionId))
131
+ return false;
132
+ if (!isMethod(msg, ACP_METHODS.SESSION_UPDATE))
133
+ return false;
134
+ const update = msg.params?.update;
135
+ return update?.sessionUpdate !== SESSION_UPDATES.TOOL_CALL_UPDATE;
136
+ }
137
+ export function createCancellationLeakFix(options) {
138
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_CANCELLATION_TIMEOUT_MS;
103
139
  const state = {
104
140
  activePrompts: new Map(),
105
- cancelledPromptIds: new Set(),
106
- cancelledSessions: new Set(),
141
+ cancellingSessions: new Map(),
142
+ suppressedLateResponseIds: new Set(),
107
143
  };
108
144
  return {
109
145
  name: "cancellation-leak",
110
146
  description: "Suppresses raw upstream Go/Python cancellation error chunks and ensures prompt settlement during client interruptions",
111
- onOutbound(msg, context) {
147
+ async onOutbound(msg, context) {
112
148
  if (isMethod(msg, ACP_METHODS.SESSION_PROMPT)) {
113
- handleOutboundPrompt(msg, state);
149
+ await handleOutboundPrompt(msg, state);
114
150
  }
115
151
  else if (isMethod(msg, ACP_METHODS.SESSION_CANCEL)) {
116
- handleOutboundCancel(msg, context, state);
152
+ handleOutboundCancel(msg, context, state, timeoutMs);
117
153
  }
118
154
  return msg;
119
155
  },
@@ -122,10 +158,8 @@ export function createCancellationLeakFix() {
122
158
  return [];
123
159
  }
124
160
  const sessionId = extractSessionId(msg) ?? context.session?.sessionId;
125
- if (sessionId && state.cancelledSessions.has(sessionId)) {
126
- if (isMethod(msg, ACP_METHODS.SESSION_UPDATE)) {
127
- return [];
128
- }
161
+ if (isSuppressedDuringCancellation(msg, sessionId, state)) {
162
+ return [];
129
163
  }
130
164
  const text = extractMessageChunkText(msg);
131
165
  if (text && isCancellationText(text)) {
@@ -134,9 +168,13 @@ export function createCancellationLeakFix() {
134
168
  return [msg];
135
169
  },
136
170
  dispose() {
171
+ for (const cancelling of state.cancellingSessions.values()) {
172
+ clearTimeout(cancelling.timer);
173
+ cancelling.resolve();
174
+ }
137
175
  state.activePrompts.clear();
138
- state.cancelledPromptIds.clear();
139
- state.cancelledSessions.clear();
176
+ state.cancellingSessions.clear();
177
+ state.suppressedLateResponseIds.clear();
140
178
  },
141
179
  };
142
180
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fixes/cancellation-leak/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fixes/cancellation-leak/index.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,7 @@ export * from "./missing-usage-metrics/index.js";
17
17
  export * from "./dangling-tool-calls/index.js";
18
18
  export * from "./missing-question-fallback/index.js";
19
19
  export * from "./premature-turn-stop/index.js";
20
+ export * from "./repetitive-tool-loop/index.js";
20
21
  /**
21
22
  * Returns a list of all active fixes addressing the upstream issues documented in readme.md.
22
23
  * As upstream releases fix these defects, retirement is as simple as removing the fix here
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoB/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AACrD,cAAc,gCAAgC,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAqB7C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAqB/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AACrD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAEhD;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAsB7C"}
@@ -16,6 +16,7 @@ import { missingUsageMetricsFix } from "./missing-usage-metrics/index.js";
16
16
  import { danglingToolCallsFix } from "./dangling-tool-calls/index.js";
17
17
  import { missingQuestionFallbackFix } from "./missing-question-fallback/index.js";
18
18
  import { prematureTurnStopFix } from "./premature-turn-stop/index.js";
19
+ import { repetitiveToolLoopFix } from "./repetitive-tool-loop/index.js";
19
20
  export * from "./missing-localharness/index.js";
20
21
  export * from "./missing-system-prompt/index.js";
21
22
  export * from "./missing-slash-skills/index.js";
@@ -34,6 +35,7 @@ export * from "./missing-usage-metrics/index.js";
34
35
  export * from "./dangling-tool-calls/index.js";
35
36
  export * from "./missing-question-fallback/index.js";
36
37
  export * from "./premature-turn-stop/index.js";
38
+ export * from "./repetitive-tool-loop/index.js";
37
39
  /**
38
40
  * Returns a list of all active fixes addressing the upstream issues documented in readme.md.
39
41
  * As upstream releases fix these defects, retirement is as simple as removing the fix here
@@ -49,6 +51,7 @@ export function createDefaultFixes() {
49
51
  malformedStreamSyntaxFix,
50
52
  activeTurnCollisionFix,
51
53
  cancellationLeakFix,
54
+ repetitiveToolLoopFix,
52
55
  danglingToolCallsFix,
53
56
  staleMcpEndpointsFix,
54
57
  orphanedCheckpointsFix,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/fixes/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AACrD,cAAc,gCAAgC,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,sBAAsB;QACtB,sBAAsB;QACtB,qBAAqB;QACrB,eAAe;QACf,wBAAwB;QACxB,wBAAwB;QACxB,sBAAsB;QACtB,mBAAmB;QACnB,oBAAoB;QACpB,oBAAoB;QACpB,sBAAsB;QACtB,uBAAuB;QACvB,kBAAkB;QAClB,wBAAwB;QACxB,sBAAsB;QACtB,sBAAsB;QACtB,0BAA0B;QAC1B,oBAAoB;KACrB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/fixes/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AACrD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAEhD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,sBAAsB;QACtB,sBAAsB;QACtB,qBAAqB;QACrB,eAAe;QACf,wBAAwB;QACxB,wBAAwB;QACxB,sBAAsB;QACtB,mBAAmB;QACnB,qBAAqB;QACrB,oBAAoB;QACpB,oBAAoB;QACpB,sBAAsB;QACtB,uBAAuB;QACvB,kBAAkB;QAClB,wBAAwB;QACxB,sBAAsB;QACtB,sBAAsB;QACtB,0BAA0B;QAC1B,oBAAoB;KACrB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Problem:
3
+ * Upstream `agy_acp_server` does not detect repetitive tool calling loops or autoregressive attractor cycles.
4
+ * When a model degenerates into repeating the same tool call or cycling through the same set of file slices,
5
+ * raw agy blindly executes tool calls indefinitely, burning thousands of tokens and freezing editor sessions.
6
+ *
7
+ * Solution:
8
+ * Tracks canonicalized tool call signatures per prompt turn using suffix cycle matching.
9
+ * When identical tool calls or periodic cycles repeat beyond safety thresholds, the wrapper sends
10
+ * `session/cancel` upstream to halt runaway execution, auto-completes pending tool updates, emits an
11
+ * explanatory message chunk to the editor chat, and cleanly settles the turn.
12
+ */
13
+ import { type AcpFix } from "../../core/types.js";
14
+ export declare const IGNORED_METADATA_KEYS: Set<string>;
15
+ export declare const READ_ONLY_TOOLS: Set<string>;
16
+ export interface RepetitiveToolLoopOptions {
17
+ maxPeriod?: number;
18
+ readOnlySingleThreshold?: number;
19
+ mutatingSingleThreshold?: number;
20
+ cycleThreshold?: number;
21
+ }
22
+ export declare function normalizeKey(key: string): string;
23
+ export declare function canonicalizeValue(val: unknown): unknown;
24
+ export declare function inferToolNameFromUpdate(title?: string | null, kind?: string | null, rawInput?: unknown): string;
25
+ export declare function computeToolCallSignature(toolName: string, rawInput: unknown): string;
26
+ export interface CycleDetectionResult {
27
+ isLoop: boolean;
28
+ cycleLength: number;
29
+ repetitions: number;
30
+ pattern: string[];
31
+ }
32
+ export declare function detectCycle(signatures: readonly string[], options?: {
33
+ maxPeriod?: number;
34
+ singleToolThreshold?: number;
35
+ cycleThreshold?: number;
36
+ }): CycleDetectionResult;
37
+ export declare class RepetitiveToolLoopTracker {
38
+ private readonly sessions;
39
+ private readonly promptIdToSessionId;
40
+ private getOrCreate;
41
+ startTurn(sessionId: string, promptId?: string | number): void;
42
+ getSessionIdForPrompt(promptId: string | number): string | undefined;
43
+ recordToolCall(sessionId: string, toolName: string, rawInput: unknown, options?: RepetitiveToolLoopOptions): CycleDetectionResult;
44
+ isLoopInterrupted(sessionId: string): boolean;
45
+ getActivePromptId(sessionId: string): string | number | undefined;
46
+ clearSession(sessionId: string): void;
47
+ clear(): void;
48
+ }
49
+ export declare function createRepetitiveToolLoopFix(options?: RepetitiveToolLoopOptions): AcpFix;
50
+ export declare const repetitiveToolLoopFix: AcpFix;
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/fixes/repetitive-tool-loop/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAKL,KAAK,MAAM,EAKZ,MAAM,qBAAqB,CAAC;AAG7B,eAAO,MAAM,qBAAqB,aAAwD,CAAC;AAE3F,eAAO,MAAM,eAAe,aAO1B,CAAC;AAEH,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAcvD;AAED,wBAAgB,uBAAuB,CACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,EACpB,QAAQ,CAAC,EAAE,OAAO,GACjB,MAAM,CAcR;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAWpF;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAkBD,wBAAgB,WAAW,CACzB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CACpB,GACL,oBAAoB,CA2BtB;AAQD,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAChE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsC;IAE1E,OAAO,CAAC,WAAW;IASnB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAU9D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS;IAIpE,cAAc,CACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,EACjB,OAAO,GAAE,yBAA8B,GACtC,oBAAoB;IA2BvB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI7C,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS;IAIjE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrC,KAAK,IAAI,IAAI;CAId;AA2GD,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,yBAA8B,GAAG,MAAM,CAmC3F;AAED,eAAO,MAAM,qBAAqB,QAAgC,CAAC"}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Problem:
3
+ * Upstream `agy_acp_server` does not detect repetitive tool calling loops or autoregressive attractor cycles.
4
+ * When a model degenerates into repeating the same tool call or cycling through the same set of file slices,
5
+ * raw agy blindly executes tool calls indefinitely, burning thousands of tokens and freezing editor sessions.
6
+ *
7
+ * Solution:
8
+ * Tracks canonicalized tool call signatures per prompt turn using suffix cycle matching.
9
+ * When identical tool calls or periodic cycles repeat beyond safety thresholds, the wrapper sends
10
+ * `session/cancel` upstream to halt runaway execution, auto-completes pending tool updates, emits an
11
+ * explanatory message chunk to the editor chat, and cleanly settles the turn.
12
+ */
13
+ import { ACP_METHODS, SESSION_UPDATES, STOP_REASONS, isMethod, } from "../../core/types.js";
14
+ import { extractSessionId } from "../../core/session-cache.js";
15
+ export const IGNORED_METADATA_KEYS = new Set(["toolaction", "toolsummary", "description"]);
16
+ export const READ_ONLY_TOOLS = new Set([
17
+ "view_file",
18
+ "list_directory",
19
+ "find_file",
20
+ "read_url_content",
21
+ "search_web",
22
+ "read_file",
23
+ ]);
24
+ export function normalizeKey(key) {
25
+ return key.toLowerCase().replace(/_/g, "");
26
+ }
27
+ export function canonicalizeValue(val) {
28
+ if (val === null || val === undefined)
29
+ return null;
30
+ if (typeof val !== "object")
31
+ return val;
32
+ if (Array.isArray(val)) {
33
+ return val.map(canonicalizeValue);
34
+ }
35
+ const sortedObj = {};
36
+ const entries = Object.entries(val);
37
+ const filteredEntries = entries.filter(([k]) => !IGNORED_METADATA_KEYS.has(normalizeKey(k)));
38
+ filteredEntries.sort(([a], [b]) => normalizeKey(a).localeCompare(normalizeKey(b)));
39
+ for (const [k, v] of filteredEntries) {
40
+ sortedObj[normalizeKey(k)] = canonicalizeValue(v);
41
+ }
42
+ return sortedObj;
43
+ }
44
+ export function inferToolNameFromUpdate(title, kind, rawInput) {
45
+ if (title) {
46
+ const cleaned = title.replace(/^Running:?\s+/i, "").trim();
47
+ if (cleaned.length > 0)
48
+ return cleaned;
49
+ }
50
+ if (kind && kind !== "other") {
51
+ return kind;
52
+ }
53
+ if (rawInput && typeof rawInput === "object") {
54
+ if ("CommandLine" in rawInput)
55
+ return "run_command";
56
+ if ("AbsolutePath" in rawInput)
57
+ return "view_file";
58
+ if ("Subagents" in rawInput)
59
+ return "invoke_subagent";
60
+ }
61
+ return "tool";
62
+ }
63
+ export function computeToolCallSignature(toolName, rawInput) {
64
+ let parsedInput = rawInput;
65
+ if (typeof rawInput === "string") {
66
+ try {
67
+ parsedInput = JSON.parse(rawInput);
68
+ }
69
+ catch {
70
+ parsedInput = rawInput;
71
+ }
72
+ }
73
+ const canonical = canonicalizeValue(parsedInput);
74
+ return `${toolName}:${JSON.stringify(canonical)}`;
75
+ }
76
+ function isSuffixCycleMatch(signatures, n, k, repetitions) {
77
+ for (let r = 1; r < repetitions; r++) {
78
+ for (let i = 0; i < k; i++) {
79
+ if (signatures[n - k + i] !== signatures[n - (r + 1) * k + i]) {
80
+ return false;
81
+ }
82
+ }
83
+ }
84
+ return true;
85
+ }
86
+ export function detectCycle(signatures, options = {}) {
87
+ const maxPeriod = options.maxPeriod ?? 4;
88
+ const singleToolThreshold = options.singleToolThreshold ?? 3;
89
+ const cycleThreshold = options.cycleThreshold ?? 3;
90
+ const n = signatures.length;
91
+ for (let k = 1; k <= maxPeriod; k++) {
92
+ const requiredRepetitions = k === 1 ? singleToolThreshold : cycleThreshold;
93
+ const requiredLength = k * requiredRepetitions;
94
+ if (n < requiredLength)
95
+ continue;
96
+ if (isSuffixCycleMatch(signatures, n, k, requiredRepetitions)) {
97
+ return {
98
+ isLoop: true,
99
+ cycleLength: k,
100
+ repetitions: requiredRepetitions,
101
+ pattern: signatures.slice(n - k),
102
+ };
103
+ }
104
+ }
105
+ return {
106
+ isLoop: false,
107
+ cycleLength: 0,
108
+ repetitions: 0,
109
+ pattern: [],
110
+ };
111
+ }
112
+ export class RepetitiveToolLoopTracker {
113
+ sessions = new Map();
114
+ promptIdToSessionId = new Map();
115
+ getOrCreate(sessionId) {
116
+ let state = this.sessions.get(sessionId);
117
+ if (!state) {
118
+ state = { signatures: [], loopInterrupted: false };
119
+ this.sessions.set(sessionId, state);
120
+ }
121
+ return state;
122
+ }
123
+ startTurn(sessionId, promptId) {
124
+ const state = this.getOrCreate(sessionId);
125
+ state.activePromptId = promptId;
126
+ state.signatures = [];
127
+ state.loopInterrupted = false;
128
+ if (promptId !== undefined && promptId !== null) {
129
+ this.promptIdToSessionId.set(promptId, sessionId);
130
+ }
131
+ }
132
+ getSessionIdForPrompt(promptId) {
133
+ return this.promptIdToSessionId.get(promptId);
134
+ }
135
+ recordToolCall(sessionId, toolName, rawInput, options = {}) {
136
+ const state = this.getOrCreate(sessionId);
137
+ if (state.loopInterrupted) {
138
+ return { isLoop: true, cycleLength: 0, repetitions: 0, pattern: [] };
139
+ }
140
+ const signature = computeToolCallSignature(toolName, rawInput);
141
+ state.signatures.push(signature);
142
+ const isReadOnly = READ_ONLY_TOOLS.has(toolName);
143
+ const singleThreshold = isReadOnly
144
+ ? (options.readOnlySingleThreshold ?? 3)
145
+ : (options.mutatingSingleThreshold ?? 5);
146
+ const result = detectCycle(state.signatures, {
147
+ maxPeriod: options.maxPeriod ?? 4,
148
+ singleToolThreshold: singleThreshold,
149
+ cycleThreshold: options.cycleThreshold ?? 3,
150
+ });
151
+ if (result.isLoop) {
152
+ state.loopInterrupted = true;
153
+ }
154
+ return result;
155
+ }
156
+ isLoopInterrupted(sessionId) {
157
+ return this.sessions.get(sessionId)?.loopInterrupted ?? false;
158
+ }
159
+ getActivePromptId(sessionId) {
160
+ return this.sessions.get(sessionId)?.activePromptId;
161
+ }
162
+ clearSession(sessionId) {
163
+ this.sessions.delete(sessionId);
164
+ }
165
+ clear() {
166
+ this.sessions.clear();
167
+ this.promptIdToSessionId.clear();
168
+ }
169
+ }
170
+ async function interruptLoopExecution(sessionId, toolCallId, toolName, loopResult, context) {
171
+ await context
172
+ .writeToChild({
173
+ jsonrpc: "2.0",
174
+ method: ACP_METHODS.SESSION_CANCEL,
175
+ params: { sessionId },
176
+ })
177
+ .catch(() => { });
178
+ context.forwardInbound?.({
179
+ jsonrpc: "2.0",
180
+ method: ACP_METHODS.SESSION_UPDATE,
181
+ params: {
182
+ sessionId,
183
+ update: {
184
+ sessionUpdate: SESSION_UPDATES.TOOL_CALL_UPDATE,
185
+ toolCallId,
186
+ status: "completed",
187
+ },
188
+ },
189
+ });
190
+ const cycleDesc = loopResult.cycleLength > 1
191
+ ? `a cycle of ${loopResult.cycleLength} alternating tool calls`
192
+ : `identical tool call (${toolName})`;
193
+ context.forwardInbound?.({
194
+ jsonrpc: "2.0",
195
+ method: ACP_METHODS.SESSION_UPDATE,
196
+ params: {
197
+ sessionId,
198
+ update: {
199
+ sessionUpdate: SESSION_UPDATES.AGENT_MESSAGE_CHUNK,
200
+ content: {
201
+ type: "text",
202
+ text: `\n\n⚠️ Interrupted repetitive tool calling loop: detected ${cycleDesc} repeating without progress. Stopping turn to prevent runaway token usage.`,
203
+ },
204
+ },
205
+ },
206
+ });
207
+ }
208
+ function settleInterruptedPromptResponse(msg, sessionId, tracker) {
209
+ if (!("result" in msg) || !tracker.isLoopInterrupted(sessionId)) {
210
+ return null;
211
+ }
212
+ const res = msg.result;
213
+ if (res && (res.stopReason === STOP_REASONS.CANCELLED || !res.stopReason)) {
214
+ tracker.startTurn(sessionId);
215
+ return [
216
+ {
217
+ ...msg,
218
+ result: {
219
+ ...res,
220
+ stopReason: STOP_REASONS.END_TURN,
221
+ },
222
+ },
223
+ ];
224
+ }
225
+ return null;
226
+ }
227
+ function resolveSessionId(msg, tracker) {
228
+ const fromMsg = extractSessionId(msg);
229
+ if (fromMsg)
230
+ return fromMsg;
231
+ const id = msg.id;
232
+ return id !== null && id !== undefined ? tracker.getSessionIdForPrompt(id) : undefined;
233
+ }
234
+ async function handleInboundSessionUpdate(msg, sessionId, tracker, options, context) {
235
+ const update = "params" in msg ? msg.params?.update : undefined;
236
+ if (update?.sessionUpdate !== SESSION_UPDATES.TOOL_CALL) {
237
+ return null;
238
+ }
239
+ const toolCallId = update.toolCallId ?? "unknown";
240
+ const toolName = inferToolNameFromUpdate(update.title, update.kind, update.rawInput);
241
+ const loopResult = tracker.recordToolCall(sessionId, toolName, update.rawInput, options);
242
+ if (loopResult.isLoop) {
243
+ await interruptLoopExecution(sessionId, toolCallId, toolName, loopResult, context);
244
+ return [];
245
+ }
246
+ return null;
247
+ }
248
+ export function createRepetitiveToolLoopFix(options = {}) {
249
+ const tracker = new RepetitiveToolLoopTracker();
250
+ return {
251
+ name: "repetitive-tool-loop",
252
+ description: "Detects and interrupts repetitive tool calling cycles and autoregressive attractor loops",
253
+ onOutbound(msg, _context) {
254
+ const sessionId = extractSessionId(msg);
255
+ if (!sessionId)
256
+ return msg;
257
+ if (isMethod(msg, ACP_METHODS.SESSION_PROMPT)) {
258
+ const promptId = msg.id;
259
+ tracker.startTurn(sessionId, promptId);
260
+ }
261
+ return msg;
262
+ },
263
+ async onInbound(msg, context) {
264
+ const sessionId = resolveSessionId(msg, tracker);
265
+ if (!sessionId)
266
+ return [msg];
267
+ const settled = settleInterruptedPromptResponse(msg, sessionId, tracker);
268
+ if (settled)
269
+ return settled;
270
+ if (isMethod(msg, ACP_METHODS.SESSION_UPDATE)) {
271
+ const handled = await handleInboundSessionUpdate(msg, sessionId, tracker, options, context);
272
+ if (handled)
273
+ return handled;
274
+ }
275
+ return [msg];
276
+ },
277
+ };
278
+ }
279
+ export const repetitiveToolLoopFix = createRepetitiveToolLoopFix();
280
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fixes/repetitive-tool-loop/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,WAAW,EACX,eAAe,EACf,YAAY,EACZ,QAAQ,GAMT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC;AAE3F,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IACrC,WAAW;IACX,gBAAgB;IAChB,WAAW;IACX,kBAAkB;IAClB,YAAY;IACZ,WAAW;CACZ,CAAC,CAAC;AASH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,CAAC;IAC/D,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC;QACrC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,KAAqB,EACrB,IAAoB,EACpB,QAAkB;IAElB,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,OAAO,CAAC;IACzC,CAAC;IACD,IAAI,IAAI,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC7C,IAAI,aAAa,IAAK,QAAoC;YAAE,OAAO,aAAa,CAAC;QACjF,IAAI,cAAc,IAAK,QAAoC;YAAE,OAAO,WAAW,CAAC;QAChF,IAAI,WAAW,IAAK,QAAoC;YAAE,OAAO,iBAAiB,CAAC;IACrF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,QAAgB,EAAE,QAAiB;IAC1E,IAAI,WAAW,GAAG,QAAQ,CAAC;IAC3B,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,GAAG,QAAQ,CAAC;QACzB,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACjD,OAAO,GAAG,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;AACpD,CAAC;AASD,SAAS,kBAAkB,CACzB,UAA6B,EAC7B,CAAS,EACT,CAAS,EACT,WAAmB;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,IAAI,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAC9D,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,UAA6B,EAC7B,UAII,EAAE;IAEN,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC;IACzC,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,IAAI,CAAC,CAAC;IAC7D,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,mBAAmB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,cAAc,CAAC;QAC3E,MAAM,cAAc,GAAG,CAAC,GAAG,mBAAmB,CAAC;QAC/C,IAAI,CAAC,GAAG,cAAc;YAAE,SAAS;QAEjC,IAAI,kBAAkB,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,EAAE,mBAAmB,CAAC,EAAE,CAAC;YAC9D,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,WAAW,EAAE,CAAC;gBACd,WAAW,EAAE,mBAAmB;gBAChC,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;aACjC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,CAAC;QACd,WAAW,EAAE,CAAC;QACd,OAAO,EAAE,EAAE;KACZ,CAAC;AACJ,CAAC;AAQD,MAAM,OAAO,yBAAyB;IACnB,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC/C,mBAAmB,GAAG,IAAI,GAAG,EAA2B,CAAC;IAElE,WAAW,CAAC,SAAiB;QACnC,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;YACnD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,CAAC,SAAiB,EAAE,QAA0B;QACrD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAC1C,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;QAChC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC;QACtB,KAAK,CAAC,eAAe,GAAG,KAAK,CAAC;QAC9B,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAChD,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,qBAAqB,CAAC,QAAyB;QAC7C,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED,cAAc,CACZ,SAAiB,EACjB,QAAgB,EAChB,QAAiB,EACjB,UAAqC,EAAE;QAEvC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACvE,CAAC;QAED,MAAM,SAAS,GAAG,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/D,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEjC,MAAM,UAAU,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,eAAe,GAAG,UAAU;YAChC,CAAC,CAAC,CAAC,OAAO,CAAC,uBAAuB,IAAI,CAAC,CAAC;YACxC,CAAC,CAAC,CAAC,OAAO,CAAC,uBAAuB,IAAI,CAAC,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,EAAE;YAC3C,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC;YACjC,mBAAmB,EAAE,eAAe;YACpC,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,CAAC;SAC5C,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC;QAC/B,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,iBAAiB,CAAC,SAAiB;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,eAAe,IAAI,KAAK,CAAC;IAChE,CAAC;IAED,iBAAiB,CAAC,SAAiB;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;IACtD,CAAC;IAED,YAAY,CAAC,SAAiB;QAC5B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;IACnC,CAAC;CACF;AAED,KAAK,UAAU,sBAAsB,CACnC,SAAiB,EACjB,UAAkB,EAClB,QAAgB,EAChB,UAAgC,EAChC,OAAuB;IAEvB,MAAM,OAAO;SACV,YAAY,CAAC;QACZ,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,WAAW,CAAC,cAAc;QAClC,MAAM,EAAE,EAAE,SAAS,EAAE;KACS,CAAC;SAChC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAEnB,OAAO,CAAC,cAAc,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,WAAW,CAAC,cAAc;QAClC,MAAM,EAAE;YACN,SAAS;YACT,MAAM,EAAE;gBACN,aAAa,EAAE,eAAe,CAAC,gBAAgB;gBAC/C,UAAU;gBACV,MAAM,EAAE,WAAW;aACpB;SACF;KAC6B,CAAC,CAAC;IAElC,MAAM,SAAS,GACb,UAAU,CAAC,WAAW,GAAG,CAAC;QACxB,CAAC,CAAC,cAAc,UAAU,CAAC,WAAW,yBAAyB;QAC/D,CAAC,CAAC,wBAAwB,QAAQ,GAAG,CAAC;IAE1C,OAAO,CAAC,cAAc,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,WAAW,CAAC,cAAc;QAClC,MAAM,EAAE;YACN,SAAS;YACT,MAAM,EAAE;gBACN,aAAa,EAAE,eAAe,CAAC,mBAAmB;gBAClD,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,6DAA6D,SAAS,4EAA4E;iBACzJ;aACF;SACF;KAC6B,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,+BAA+B,CACtC,GAAqB,EACrB,SAAiB,EACjB,OAAkC;IAElC,IAAI,CAAC,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAwC,CAAC;IACzD,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,YAAY,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1E,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7B,OAAO;YACL;gBACE,GAAG,GAAG;gBACN,MAAM,EAAE;oBACN,GAAG,GAAG;oBACN,UAAU,EAAE,YAAY,CAAC,QAAQ;iBAClC;aACF;SACF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CACvB,GAAqB,EACrB,OAAkC;IAElC,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,MAAM,EAAE,GAAI,GAAuC,CAAC,EAAE,CAAC;IACvD,OAAO,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACzF,CAAC;AAED,KAAK,UAAU,0BAA0B,CACvC,GAAqB,EACrB,SAAiB,EACjB,OAAkC,EAClC,OAAkC,EAClC,OAAuB;IAEvB,MAAM,MAAM,GACV,QAAQ,IAAI,GAAG,CAAC,CAAC,CAAE,GAAG,CAAC,MAA0C,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACxF,IAAI,MAAM,EAAE,aAAa,KAAK,eAAe,CAAC,SAAS,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,SAAS,CAAC;IAClD,MAAM,QAAQ,GAAG,uBAAuB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrF,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzF,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,sBAAsB,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QACnF,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,UAAqC,EAAE;IACjF,MAAM,OAAO,GAAG,IAAI,yBAAyB,EAAE,CAAC;IAEhD,OAAO;QACL,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EACT,0FAA0F;QAE5F,UAAU,CAAC,GAAqB,EAAE,QAAyB;YACzD,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,SAAS;gBAAE,OAAO,GAAG,CAAC;YAE3B,IAAI,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;gBAC9C,MAAM,QAAQ,GAAI,GAAgC,CAAC,EAAE,CAAC;gBACtD,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACzC,CAAC;YAED,OAAO,GAAG,CAAC;QACb,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,GAAqB,EAAE,OAAuB;YAC5D,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACjD,IAAI,CAAC,SAAS;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC;YAE7B,MAAM,OAAO,GAAG,+BAA+B,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACzE,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;YAE5B,IAAI,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;gBAC9C,MAAM,OAAO,GAAG,MAAM,0BAA0B,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC5F,IAAI,OAAO;oBAAE,OAAO,OAAO,CAAC;YAC9B,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,2BAA2B,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonepri/refined-antigravity-acp",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "🤦 A Google Antigravity ACP binary that actually works.",
5
5
  "keywords": [
6
6
  "acp",
package/readme.md CHANGED
@@ -160,6 +160,7 @@ The matrix below documents upstream defects across process startup, turn executi
160
160
  | [**Dangling Running Tool Calls**](src/fixes/dangling-tool-calls/index.ts) | **Problem**: When commands are backgrounded, upstream never emits terminal `tool_call_update` with `status: "completed"`, leaving editor UIs with an infinite active running animation.<br>🔗 [`problem: dangling running tool call`](src/fixes/dangling-tool-calls/index.test.ts#L67) | Tracks active tool calls and marks backgrounded tools completed immediately, before assistant text streams, and upon turn completion.<br>🔗 [`solution: tool call auto-completion`](src/fixes/dangling-tool-calls/index.test.ts#L79) |
161
161
  | [**Interactive Question Deadlock**](src/fixes/missing-question-fallback/index.ts) | **Problem**: When `ask_question` is active, sending a chat prompt or cancel causes upstream to reject the message with _"A foreground turn is already active"_, deadlocking sessions indefinitely.<br>🔗 [`problem: question collision`](src/fixes/missing-question-fallback/index.e2e.test.ts#L16) | Intercepts user chat prompts and cancellations to auto-unblock pending question permission requests to the child process and complete UI tool states.<br>🔗 [`solution: question unblocking`](src/fixes/missing-question-fallback/index.e2e.test.ts#L53) |
162
162
  | [**Premature Empty Turn Stop**](src/fixes/premature-turn-stop/index.ts) | **Problem**: Upstream binary prematurely concludes prompt turns with empty completions (`stopReason=16`) without emitting assistant message chunks, leaving editor UIs frozen in silence.<br>🔗 [`problem: premature turn termination`](src/fixes/premature-turn-stop/index.test.ts#L48) | Injects explicit system prompt steering instructing the model to always emit clear status messages and never terminate turns silently.<br>🔗 [`solution: prompt steering`](src/fixes/premature-turn-stop/index.test.ts#L79) |
163
+ | [**Repetitive Tool Calling Loop**](src/fixes/repetitive-tool-loop/index.ts) | **Problem**: Upstream binary has no loop detector and will execute cyclic or identical tool calls indefinitely, burning thousands of tokens and freezing sessions.<br>🔗 [`problem: repetitive tool loop`](src/fixes/repetitive-tool-loop/index.e2e.test.ts#L25) | Tracks tool signatures per turn using suffix cycle matching, sending `session/cancel` upstream, auto-completing tools, and notifying the user when cycles repeat.<br>🔗 [`solution: loop circuit breaker`](src/fixes/repetitive-tool-loop/index.e2e.test.ts#L81) |
163
164
 
164
165
  ## Setup
165
166