Skip to content
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

Allow agent to be debugged by IntelliJ #2930

Merged
merged 1 commit into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ dist/
.DS_Store
.env
.idea/
.run/
playwright/**/*.webm
**/*.iml
**/*.vsix
2 changes: 1 addition & 1 deletion agent/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export class Agent extends MessageHandler {
public workspace = new AgentWorkspaceDocuments({
edit: (uri, callback, options) => {
if (this.clientInfo?.capabilities?.edit !== 'enabled') {
logDebug('CodyAgent', 'client does not support operation: AgenTextDocument.edit()')
logDebug('CodyAgent', 'client does not support operation: textDocument/edit')
return Promise.resolve(false)
}
const edits: TextEdit[] = []
Expand Down
51 changes: 37 additions & 14 deletions agent/src/cli/jsonrpc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { EXPIRY_STRATEGY, MODE, Polly, Request } from '@pollyjs/core'
import * as commander from 'commander'
import { Command, Option } from 'commander'
import { createServer } from 'net'

import { startPollyRecording } from '../../../vscode/src/testutils/polly'
import { Agent } from '../agent'
Expand Down Expand Up @@ -44,6 +45,11 @@ function expiryStrategyOption(value: string): EXPIRY_STRATEGY {
}
}

const isDebugMode = process.env.CODY_AGENT_DEBUG_REMOTE === 'true'
const debugPort = process.env.CODY_AGENT_DEBUG_PORT
? parseInt(process.env.CODY_AGENT_DEBUG_PORT, 10)
: 3113

export const jsonrpcCommand = new Command('jsonrpc')
.description(
'Interact with the Agent using JSON-RPC via stdout/stdin. ' +
Expand Down Expand Up @@ -132,21 +138,38 @@ export const jsonrpcCommand = new Command('jsonrpc')
process.exit(1)
}

if (process.env.CODY_DEBUG === 'true') {
process.stderr.write('Starting Cody Agent...\n')
if (isDebugMode) {
const server = createServer(socket => {
setupAgentCommunication(polly, networkRequests, socket, socket)
})

server.listen(debugPort, () => {
console.log(`Agent debug server listening on port ${debugPort}`)
})
} else {
setupAgentCommunication(polly, networkRequests, process.stdin, process.stdout)
}
})

const agent = new Agent({ polly, networkRequests })
function setupAgentCommunication(
polly: Polly | undefined,
networkRequests: Request[],
stdin: NodeJS.ReadableStream,
stdout: NodeJS.WritableStream
) {
const agent = new Agent({ polly, networkRequests })

// Force the agent process to exit when stdin/stdout close as an attempt to
// prevent zombie agent processes. We experienced this problem when we
// forcefully exit the IntelliJ process during local `./gradlew :runIde`
// workflows. We manually confirmed that this logic makes the agent exit even
// when we forcefully quit IntelliJ
// https://github.com/sourcegraph/cody/pull/1439#discussion_r1365610354
process.stdout.on('close', () => process.exit(1))
process.stdin.on('close', () => process.exit(1))
// Force the agent process to exit when stdin/stdout close as an attempt to
// prevent zombie agent processes. We experienced this problem when we
// forcefully exit the IntelliJ process during local `./gradlew :runIde`
// workflows. We manually confirmed that this logic makes the agent exit even
// when we forcefully quit IntelliJ
// https://github.com/sourcegraph/cody/pull/1439#discussion_r1365610354
if (!isDebugMode) {
stdout.on('close', () => process.exit(1))
stdin.on('close', () => process.exit(1))
}

process.stdin.pipe(agent.messageDecoder)
agent.messageEncoder.pipe(process.stdout)
})
stdin.pipe(agent.messageDecoder)
agent.messageEncoder.pipe(stdout)
}
2 changes: 1 addition & 1 deletion vscode/src/chat/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export type WebviewMessage =
command: 'openLocalFileWithRange'
filePath: string
// Note: we're not using vscode.Range objects or nesting here, as the protocol
// tends ot munge the type in a weird way (nested fields become array indices).
// tends to munge the type in a weird way (nested fields become array indices).
range?: {
startLine: number
startCharacter: number
Expand Down
2 changes: 1 addition & 1 deletion vscode/src/jsonrpc/jsonrpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ type MessageHandlerCallback = (err: Error | null, msg: Message | null) => void

/**
* Absolute path to a file where the agent can write low-level debugging logs to
* trace all incoming/outgoin JSON messages.
* trace all incoming/outgoing JSON messages.
*/
const tracePath = process.env.CODY_AGENT_TRACE_PATH ?? ''

Expand Down
Loading