-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix(ACS-175): Resolve integrations freeze and improve rate limit handling #839
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
aslaker
merged 10 commits into
AndyMik90:develop
from
MikeeBuilds:fix/acs-175-integrations-freeze
Jan 12, 2026
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
b03e446
fix(ACS-175): Resolve integrations freeze and improve rate limit hand…
MikeeBuilds b20c1bb
Merge branch 'develop' into fix/acs-175-integrations-freeze
AndyMik90 27ae640
fix(i18n): replace hardcoded toast strings with translation keys
MikeeBuilds 56a6bed
fix: replace console.log with debugLog in IntegrationSettings
MikeeBuilds a37e072
fix: replace console.log with debugLog in main process files
MikeeBuilds f9fdd8d
Merge branch 'develop' into fix/acs-175-integrations-freeze
aslaker 8328066
fix: address Auto Claude PR review findings - console.error→debugErro…
MikeeBuilds da9b707
fix: address Auto Claude PR review findings - race condition + consol…
MikeeBuilds e033f51
Merge branch 'develop' into fix/acs-175-integrations-freeze
aslaker 0f1a7ec
Merge branch 'develop' into fix/acs-175-integrations-freeze
aslaker File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ import type { TerminalProcess, WindowGetter } from './types'; | |
| import { IPC_CHANNELS } from '../../shared/constants'; | ||
| import { getClaudeProfileManager } from '../claude-profile-manager'; | ||
| import { readSettingsFile } from '../settings-utils'; | ||
| import { debugLog, debugError } from '../../shared/utils/debug-logger'; | ||
| import type { SupportedTerminal } from '../../shared/types/settings'; | ||
|
|
||
| /** | ||
|
|
@@ -84,7 +85,7 @@ export function spawnPtyProcess( | |
|
|
||
| const shellArgs = process.platform === 'win32' ? [] : ['-l']; | ||
|
|
||
| console.warn('[PtyManager] Spawning shell:', shell, shellArgs, '(preferred:', preferredTerminal || 'system', ')'); | ||
| debugLog('[PtyManager] Spawning shell:', shell, shellArgs, '(preferred:', preferredTerminal || 'system', ')'); | ||
|
|
||
| // Create a clean environment without DEBUG to prevent Claude Code from | ||
| // enabling debug mode when the Electron app is run in development mode. | ||
|
|
@@ -137,7 +138,7 @@ export function setupPtyHandlers( | |
|
|
||
| // Handle terminal exit | ||
| ptyProcess.onExit(({ exitCode }) => { | ||
| console.warn('[PtyManager] Terminal exited:', id, 'code:', exitCode); | ||
| debugLog('[PtyManager] Terminal exited:', id, 'code:', exitCode); | ||
|
|
||
| const win = getWindow(); | ||
| if (win) { | ||
|
|
@@ -151,11 +152,97 @@ export function setupPtyHandlers( | |
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Constants for chunked write behavior | ||
| * CHUNKED_WRITE_THRESHOLD: Data larger than this (bytes) will be written in chunks | ||
| * CHUNK_SIZE: Size of each chunk - smaller chunks yield to event loop more frequently | ||
| */ | ||
| const CHUNKED_WRITE_THRESHOLD = 1000; | ||
| const CHUNK_SIZE = 100; | ||
|
|
||
| /** | ||
| * Write queue per terminal to prevent interleaving of concurrent writes. | ||
| * Maps terminal ID to the last write Promise in the queue. | ||
| */ | ||
| const pendingWrites = new Map<string, Promise<void>>(); | ||
|
|
||
| /** | ||
| * Internal function to perform the actual write (chunked or direct) | ||
| * Returns a Promise that resolves when the write is complete | ||
| */ | ||
| function performWrite(terminal: TerminalProcess, data: string): Promise<void> { | ||
| return new Promise((resolve) => { | ||
| // For large commands, write in chunks to prevent blocking | ||
| if (data.length > CHUNKED_WRITE_THRESHOLD) { | ||
| debugLog('[PtyManager:writeToPty] Large write detected, using chunked write'); | ||
| let offset = 0; | ||
| let chunkNum = 0; | ||
|
|
||
| const writeChunk = () => { | ||
| // Check if terminal is still valid before writing | ||
| if (!terminal.pty) { | ||
| debugError('[PtyManager:writeToPty] Terminal PTY no longer valid, aborting chunked write'); | ||
| resolve(); | ||
| return; | ||
| } | ||
|
|
||
| if (offset >= data.length) { | ||
| debugLog('[PtyManager:writeToPty] Chunked write completed, total chunks:', chunkNum); | ||
| resolve(); | ||
| return; | ||
| } | ||
|
|
||
| const chunk = data.slice(offset, offset + CHUNK_SIZE); | ||
| chunkNum++; | ||
| try { | ||
| terminal.pty.write(chunk); | ||
| offset += CHUNK_SIZE; | ||
| // Use setImmediate to yield to the event loop between chunks | ||
| setImmediate(writeChunk); | ||
| } catch (error) { | ||
| debugError('[PtyManager:writeToPty] Chunked write FAILED at chunk', chunkNum, ':', error); | ||
| resolve(); // Resolve anyway - fire-and-forget semantics | ||
| } | ||
| }; | ||
|
|
||
| // Start the chunked write after yielding | ||
| setImmediate(writeChunk); | ||
| } else { | ||
| try { | ||
| terminal.pty.write(data); | ||
| debugLog('[PtyManager:writeToPty] Write completed successfully'); | ||
| } catch (error) { | ||
| debugError('[PtyManager:writeToPty] Write FAILED:', error); | ||
| } | ||
| resolve(); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Write data to a PTY process | ||
| * Uses setImmediate to prevent blocking the event loop on large writes. | ||
| * Serializes writes per terminal to prevent interleaving of concurrent writes. | ||
| */ | ||
| export function writeToPty(terminal: TerminalProcess, data: string): void { | ||
| terminal.pty.write(data); | ||
| debugLog('[PtyManager:writeToPty] About to write to pty, data length:', data.length); | ||
|
|
||
| // Get the previous write Promise for this terminal (if any) | ||
| const previousWrite = pendingWrites.get(terminal.id) || Promise.resolve(); | ||
|
|
||
| // Chain this write after the previous one completes | ||
| const currentWrite = previousWrite.then(() => performWrite(terminal, data)); | ||
|
|
||
| // Update the pending write for this terminal | ||
| pendingWrites.set(terminal.id, currentWrite); | ||
|
|
||
| // Clean up the Map entry when done to prevent memory leaks | ||
| currentWrite.finally(() => { | ||
| // Only clean up if this is still the latest write | ||
| if (pendingWrites.get(terminal.id) === currentWrite) { | ||
| pendingWrites.delete(terminal.id); | ||
| } | ||
| }); | ||
| } | ||
|
Comment on lines
+155
to
246
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Fix “bytes” vs
Proposed diff- * CHUNKED_WRITE_THRESHOLD: Data larger than this (bytes) will be written in chunks
+ * CHUNKED_WRITE_THRESHOLD: Data larger than this (string length) will be written in chunks
* CHUNK_SIZE: Size of each chunk - smaller chunks yield to event loop more frequently export function writeToPty(terminal: TerminalProcess, data: string): void {
debugLog('[PtyManager:writeToPty] About to write to pty, data length:', data.length);
// Get the previous write Promise for this terminal (if any)
const previousWrite = pendingWrites.get(terminal.id) || Promise.resolve();
// Chain this write after the previous one completes
- const currentWrite = previousWrite.then(() => performWrite(terminal, data));
+ const currentWrite = previousWrite
+ .catch(() => undefined)
+ .then(() => performWrite(terminal, data));- const chunk = data.slice(offset, offset + CHUNK_SIZE);
+ const chunk = data.slice(offset, offset + CHUNK_SIZE);
chunkNum++;
try {
terminal.pty.write(chunk);
- offset += CHUNK_SIZE;
+ offset += chunk.length;
// Use setImmediate to yield to the event loop between chunks
setImmediate(writeChunk);🤖 Prompt for AI Agents |
||
|
|
||
| /** | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
Repository: AndyMik90/Auto-Claude
Length of output: 171
🏁 Script executed:
Repository: AndyMik90/Auto-Claude
Length of output: 3092
🏁 Script executed:
Repository: AndyMik90/Auto-Claude
Length of output: 158
🏁 Script executed:
Repository: AndyMik90/Auto-Claude
Length of output: 9408
🏁 Script executed:
Repository: AndyMik90/Auto-Claude
Length of output: 4038
The chunked write approach is sound, though the rationale for specific chunk size could be clearer.
The constants are well-extracted and documented. However, the logic is intentionally designed to yield to the event loop via
setImmediatebetween chunks—this is not a latency concern but the intended behavior to prevent blocking. CHUNK_SIZE of 100 bytes is conservative by design for this purpose, and the 1000-byte threshold ensures small writes bypass chunking entirely. While performance testing could validate whether the chunk size is optimal for actual throughput, it is not necessary for correctness, as the current values are reasonable for a terminal I/O operation.🤖 Prompt for AI Agents