fix(server): remove 60s A2A client timeout + correct file-read cat args
Two bugs surfaced while testing Claude Code + OAuth deploys: 1. A2A proxy: a2aClient had a 60s Client.Timeout "safety net" that defeated the per-request context deadlines the code otherwise sets (canvas = 5m, agent-to-agent = 30m). Claude Code's first-token cold start over OAuth takes 30-60s, so every first "hi" into a fresh claude-code workspace returned 503 at exactly the 1m mark. Removed the Client.Timeout — the context deadline now governs as documented in the adjacent comment. 2. Files tab: ReadFile ran `cat <rootPath> <filePath>` as two args to cat. `cat /home agent/turtle_draw.py` tries to read the rootPath directory (errors "Is a directory") and then resolves the filePath relative to the container cwd, which is not guaranteed to equal rootPath. Result: the file-content pane stayed blank even though the file listed fine. Join into a single path before exec. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e337efe974
commit
18ebb1d7bf
@ -89,11 +89,13 @@ func isSystemCaller(callerID string) bool {
|
||||
const maxProxyResponseBody = 10 << 20
|
||||
|
||||
// a2aClient is a shared HTTP client for proxying A2A requests to workspace agents.
|
||||
// No client-level timeout — timeouts are enforced per-request via context deadlines:
|
||||
// canvas = 5 min (Rule 3), agent-to-agent = 30 min (DoS cap).
|
||||
var a2aClient = &http.Client{
|
||||
Timeout: 60 * time.Second, // Safety net for when context deadlines are missing
|
||||
}
|
||||
// No client-level timeout — timeouts are enforced per-request via context
|
||||
// deadlines: canvas = 5 min (Rule 3), agent-to-agent = 30 min (DoS cap). Do NOT
|
||||
// set a Client.Timeout here: it is enforced independently of ctx deadlines and
|
||||
// would pre-empt legitimate slow cold-start flows (e.g. Claude Code first-token
|
||||
// over OAuth can take 30-60s on boot). Callers that want a safety net should
|
||||
// build a context.WithTimeout themselves.
|
||||
var a2aClient = &http.Client{}
|
||||
|
||||
type proxyA2AError struct {
|
||||
Status int
|
||||
|
||||
@ -298,9 +298,13 @@ func (h *TemplatesHandler) ReadFile(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Try container first
|
||||
// Try container first. `cat` wants a single path argument — passing
|
||||
// rootPath and filePath as two args would make `cat` try to read the
|
||||
// rootPath directory (error) and then resolve filePath relative to
|
||||
// the container's cwd, which isn't guaranteed to equal rootPath.
|
||||
if containerName := h.findContainer(ctx, workspaceID); containerName != "" {
|
||||
content, err := h.execInContainer(ctx, containerName, []string{"cat", rootPath, filePath})
|
||||
fullPath := strings.TrimRight(rootPath, "/") + "/" + filePath
|
||||
content, err := h.execInContainer(ctx, containerName, []string{"cat", fullPath})
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"path": filePath,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user