Skip to content

devagentic-canvas: distinguish auth/404/network failures in slash commands#16

Merged
PowerCreek merged 1 commit into
mainfrom
canvas-louder-errors
May 22, 2026
Merged

devagentic-canvas: distinguish auth/404/network failures in slash commands#16
PowerCreek merged 1 commit into
mainfrom
canvas-louder-errors

Conversation

@PowerCreek

Copy link
Copy Markdown

Summary

Closes #15. Previously _request collapsed six distinct failure modes into a single opaque None, and slash commands printed the generic "Couldn't reach devagentic" string for all of them — wrong four-of-six ways.

Changes

  • plugins/devagentic-canvas/client.py: new module-level last_error_text() helper. _request records a short kind on every failure path (auth, 404, generic HTTP, unreachable, parse, no user_id) and clears it on entry to the next call.
  • plugins/devagentic-canvas/commands.py: new _failure_detail() helper that appends Reason: <text>. to the existing user-facing strings in /canvas list, /canvas open, /canvas show, /canvas new.
  • The pre_llm_call hook in preamble.py is intentionally unchanged — its loss-tolerant silent-None contract is correct for ephemeral context injection.

Why this matters across the boundary

This is exactly the diagnostic gap that ate iterations during #8 / #9 / #13 triage. An operator who sets DEVAGENTIC_BASE_URL=\$DUPLEX_SERVICE_URL (or who forgets DEVAGENTIC_API_KEY) will now see, e.g.:

Couldn't reach devagentic. Check that it's running at $DEVAGENTIC_BASE_URL
… Reason: authentication failed — set DEVAGENTIC_API_KEY (any non-empty
value works when devagentic runs in trust-header mode).

Instead of having to grep hermes DEBUG logs to find that out.

Test plan

  • 6 new unit tests in tests/test_devagentic_canvas_plugin.py:
    • test_last_error_unresolved_user_id
    • test_last_error_auth_failed (401)
    • test_last_error_not_found (404)
    • test_last_error_unreachable (URLError)
    • test_last_error_cleared_on_success — proves we don't leak stale Reason text across calls
    • test_handle_list_appends_failure_detail — covers the commands.py integration
  • pytest tests/test_devagentic_canvas_plugin.py → 42 passed (36 previous + 6 new).
  • Live end-to-end against a running devagentic blocked by devagentic#157 (out of scope this session).

Filed by hermes-maintainer (PowerCreek).

…mands

_request previously collapsed every failure mode into a single
opaque None. Slash commands then printed "Couldn't reach devagentic"
even when the real cause was a missing API key, an unresolved
user_id, or a 5xx — wrong four-of-six ways.

Add a module-level last_error_text() helper. _request populates it
with a short kind on failure (auth, not_found, unreachable, parse,
no user_id) and clears it on entry. Slash commands append the
Reason. Hook intentionally ignores the slot — its loss-tolerant
contract is correct for ephemeral context injection.

Backward-compatible: existing return signatures unchanged; the
helper is purely additive.

Closes #15.
@PowerCreek PowerCreek merged commit 52ed4ae into main May 22, 2026
@PowerCreek PowerCreek deleted the canvas-louder-errors branch May 22, 2026 20:21
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.

[synergy] canvas slash commands collapse all _request failures into one message (auth vs network vs 404)

1 participant