Skip to content

Conversation

@govambam
Copy link
Owner

@govambam govambam commented Feb 4, 2026

Recreated from writer#1263 for Macroscope review.

Original PR: writer#1263 by @bybash
Status: open (open)

Recreated using direct PR head fetch - exact current state preserved.

Original PR: writer#1263

@macroscopeapp
Copy link

macroscopeapp bot commented Feb 4, 2026

Add AI code completion and Python IntelliSense to the Builder editor by starting writer.lsp_manager.LSPManager.start at app startup in edit mode and exposing /api/lsp-config and /api/code-completion

Introduce a Python LSP server lifecycle manager, wire its startup/shutdown into the ASGI app in edit mode, add backend endpoints for LSP config and AI completion, and implement a browser LSP client that integrates with Monaco for completions and diagnostics. UI adds switches for linting and AI completion and updates dropdown/menu components accordingly. Build updates include Node.js 22.x in CI and Monaco/VSCode API packages with a Vite resolver plugin.

📍Where to Start

Start with server wiring in get_asgi_app and new endpoints in serve.py, then review the LSP manager in lsp_manager.py, followed by the UI LSP bootstrap in lspSetup.ts.


Macroscope summarized f2faa21.

const uri = model.uri.toString();
const languageId = model.getLanguageId();

let timeoutId: ReturnType<typeof setTimeout> | null = null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low

lsp/lspModelSync.ts:38 Consider tracking whether didOpen was sent before sending didClose. If dispose() is called before the 100ms timeout fires, didClose is sent for a document that was never opened, which violates the LSP specification.

🚀 Want me to fix this? Reply ex: "fix it for me".

// Intercept: @codingame/monaco-vscode-api/vscode/vs/...
// Transform to absolute path in node_modules
if (source.startsWith("@codingame/monaco-vscode-api/vscode/vs/")) {
// Extract the path after /vscode/vs/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium

ui/vite.config.ts:18 If the import source contains a query string (e.g., ?worker), appending .js creates an invalid path like foo?worker.js. Consider stripping query parameters before constructing the path.

🚀 Want me to fix this? Reply ex: "fix it for me".

port 0 (letting the OS assign a port) would require parsing pylsp's output
to discover the assigned port, adding complexity for minimal benefit.
"""
for port in range(start_port, end_port):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low

writer/lsp_manager.py:48 range(start_port, end_port) excludes end_port, so port 5099 is never checked despite the error message implying it should be. Consider using end_port + 1.

Suggested change
for port in range(start_port, end_port):
for port in range(start_port, end_port + 1):

🚀 Want me to fix this? Reply ex: "fix it for me".

logger.error("LSP WebSocket error:", error);
};

ws.onclose = () => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium

lsp/lspClient.ts:206 Race condition: onclose handler accesses global state without verifying the closing socket matches the current one. If stopLSPClient then initializeLSPClient are called quickly, the old socket's onclose can corrupt the new session's state. Consider capturing ws reference and checking webSocket === ws before modifying globals.

-		ws.onclose = () => {
+		ws.onclose = () => {
+			// Guard against stale handler from previous connection
+			if (webSocket !== ws) return;
+

🚀 Want me to fix this? Reply ex: "fix it for me".

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix it for me

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working on the fix to add a guard against the race condition in the onclose handler. The changes will be pushed to a new branch and automatically merged when checks pass.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a guard at the beginning of the ws.onclose handler in initWebSocketAndStartClient that checks if the global webSocket matches the current ws instance. If they don't match, the handler returns early without modifying any global state, preventing race conditions where a quickly closed old socket could corrupt a new session's state.
Commit cc68ac0 pushed to #5. When checks pass, it will merge automatically into this PR.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I automatically merged #5 into this PR (f2faa21).

Co-authored-by: macroscopeapp[bot] <170038800+macroscopeapp[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant