3.1 KiB
3.1 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec |
|---|---|---|---|---|---|---|
| 01-normalize-action-url | Normalize OpenCode action URLs | done | 1 | plan.md | ../../specs/agents/requirements/agent-stall-recovery.md |
Task 01: Normalize OpenCode Action URLs
Acceptance
ProviderErrorhas an optionalremediation_urlfield with the existing bounded/sanitized contract.- The OpenCode parser extracts only
https://opencode.ai/workspace/<safe-workspace-id>/go; it removes the URL and identifiers frommessageand never returns arbitrary URLs. - Future structured ACP error data may supply
action_url, but only the same validator accepts it; missing, malformed, wrong-host, query-bearing, and oversized values produce no URL. - Existing correlation, prompt races, stderr projection, and generic error behavior remain unchanged.
Verification
cd apps/backend && go test ./internal/agentctl/server/adapter/transport/acp ./internal/agentctl/server/api -run 'Test(OpenCode|ProviderError|Prompt.*Error|HandleWSPrompt)' -count=1
Use TDD with the observed URL as a fixture and table-driven rejection cases. Include a structured ACP error fixture without requiring a live OpenCode process. Assert no raw URL or workspace identifier appears in the sanitized message or generic stderr projection.
Files likely touched
apps/backend/internal/agentctl/types/streams/provider_error.goapps/backend/internal/agentctl/server/adapter/transport/acp/opencode_stderr.goapps/backend/internal/agentctl/server/adapter/transport/acp/opencode_stderr_test.goapps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt.goapps/backend/internal/agentctl/server/api/agent.goapps/backend/internal/agentctl/server/api/agent_test.go
Dependencies and risks
None inside Kandev. The live current-version path still depends on OpenCode
emitting action_url through ACP or structured stderr. Do not read its private
log directory or widen the parser to arbitrary prose.
Results
Implemented 2026-08-07.
streams.ProviderError.RemediationURLadded (remediation_url,omitempty); newProviderErrorSourceOpenCodeACPsource for the structured ACP path.- Shared allowlist
NormalizeOpenCodeActionURLaccepts onlyhttps://opencode.ai/workspace/<safe-workspace-id>/go(exact host, HTTPS, no userinfo/query/fragment/port/percent-encoding, bounded identifier and URL). Stderr parser captures it from a dedicatedaction_urlfield or from the provider error text before sanitization;ProviderErrorFromErrorprojects a future ACPRequestErrorcarrying structuredaction_url, and the message runs through the existing sanitizer so no URL or workspace identifier leaks. - Table-driven tests cover the observed fixture URL, the explicit field, wrong hosts/schemes/paths, query/fragment/userinfo/port, traversal IDs, oversized values, malformed ACP data, and wrapped generic errors.
Verification: go test ./internal/agentctl/server/adapter/transport/acp ./internal/agentctl/server/api -run 'Test(OpenCode|ProviderError|Prompt.*Error|HandleWSPrompt)' -count=1 — passed (plus the full acp package suite, 787 tests).