From 69ae0dda2f7907442be73e17257f5a8df284df09 Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Wed, 14 Jan 2026 23:48:43 +1000 Subject: [PATCH] fix: add error handling for agent env vars save and sprites-exec JSON errors - Agent env vars: auto-save now awaits response and shows alert on failure - sprites-exec v0.1.4: detect JSON error responses (e.g., auth failures) before binary parsing --- .../src/app/dashboard/agents/[id]/page.tsx | 26 ++++++++++++++----- .../tools/official/sprites-exec/package.json | 2 +- .../tools/official/sprites-exec/src/index.ts | 23 +++++++++++++++- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/apps/web/src/app/dashboard/agents/[id]/page.tsx b/apps/web/src/app/dashboard/agents/[id]/page.tsx index 9d49904..3efb612 100644 --- a/apps/web/src/app/dashboard/agents/[id]/page.tsx +++ b/apps/web/src/app/dashboard/agents/[id]/page.tsx @@ -1029,14 +1029,26 @@ export default function AgentDetailPage(): React.ReactElement {
{ + onChange={async (newEnvVars) => { setEnvVars(newEnvVars); - // Auto-save env vars - fetch(`/api/agents/${agentId}`, { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ envVars: newEnvVars }), - }); + // Auto-save env vars with error handling + try { + const response = await fetch(`/api/agents/${agentId}`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ envVars: newEnvVars }), + }); + const result = await response.json(); + if (!result.success) { + console.error('Failed to save env vars:', result.error); + alert( + 'Failed to save environment variables: ' + (result.error || 'Unknown error') + ); + } + } catch (err) { + console.error('Failed to save env vars:', err); + alert('Failed to save environment variables. Please try again.'); + } }} title="Environment Variables" description="Passed to tools at runtime. Agent vars override collection vars. Changes are saved automatically." diff --git a/packages/tools/official/sprites-exec/package.json b/packages/tools/official/sprites-exec/package.json index 2628486..ccc204c 100644 --- a/packages/tools/official/sprites-exec/package.json +++ b/packages/tools/official/sprites-exec/package.json @@ -1,6 +1,6 @@ { "name": "@tpmjs/tools-sprites-exec", - "version": "0.1.3", + "version": "0.1.4", "description": "Execute a command inside a sprite and return the output with exit code", "type": "module", "keywords": [ diff --git a/packages/tools/official/sprites-exec/src/index.ts b/packages/tools/official/sprites-exec/src/index.ts index 08208d9..2550790 100644 --- a/packages/tools/official/sprites-exec/src/index.ts +++ b/packages/tools/official/sprites-exec/src/index.ts @@ -254,9 +254,30 @@ export const spritesExecTool = tool({ ); } - // Parse binary response + // Parse response - handle both binary and JSON error responses const arrayBuffer = await response.arrayBuffer(); const buffer = new Uint8Array(arrayBuffer); + + // Check if response is JSON error (starts with '{') instead of binary (starts with 0x00-0x03) + // Sprites API returns HTTP 200 with JSON body for some errors like auth failures + if (buffer.length > 0 && buffer[0] === 0x7b) { + // 0x7B = '{' + const decoder = new TextDecoder(); + const jsonText = decoder.decode(buffer); + try { + const errorResponse = JSON.parse(jsonText) as { error?: string }; + if (errorResponse.error) { + throw new Error(`Failed to execute command in sprite "${name}": ${errorResponse.error}`); + } + } catch (parseError) { + // If JSON parsing fails, throw generic error with raw text + if (parseError instanceof SyntaxError) { + throw new Error(`Failed to execute command in sprite "${name}": ${jsonText}`); + } + throw parseError; + } + } + const { stdout, stderr, exitCode } = parseBinaryResponse(buffer); return {