Skip to content

Restore Rails browser previews for agents - #632

Open
yorzi wants to merge 2 commits into
activeagents:mainfrom
yorzi:fix/rails-agent-previews
Open

yorzi wants to merge 2 commits into
activeagents:mainfrom
yorzi:fix/rails-agent-previews

Conversation

@yorzi

@yorzi yorzi commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Follows up #187, which was closed with "Previews are back … the railtie mounts /rails/agents". The routes are registered, but nothing behind them works:

  1. /rails/agents routes to rails/agents#index, and no Rails::AgentsController exists, so every preview URL raises uninitialized constant Rails::AgentsController.
  2. The TestUnit generator writes previews to test/docs/previews, while the Railtie searches test/agents/previews. A generated preview is never found.
  3. Generated previews still point at /active_agent/agents/... (the URL reported in How to get agent previews working #187) and say "Preview this email".
  4. ActiveAgent::Preview.all loads files only while no preview class exists, so a preview added after the first lookup is never discovered.
  5. The default InlinePreviewInterceptor calls html_part, which only exists on mail objects, so Preview.call raises NoMethodError on every ActiveAgent::Generation.

What changes

  • lib/rails/agents_controller.rb (new, autoloaded as Rails::AgentsController like Rails::MailersController):
    • Index lists previews, including namespaced ones.
    • Preview renders Generation#prompt_preview as escaped Markdown, which never calls the provider.
    • Download sends the same text as text/markdown.
    • Only actions listed by Preview.prompts run; unknown previews or actions (including object_id) return 404.
    • require_local! is inherited from Rails::ApplicationController, the same restriction as /rails/info.
    • Small views and a layout live under lib/active_agent/preview/templates.
  • Routes get names and format: false, so .../greet.md isn't parsed as a format.
  • Railtie: test/agents/previews, the legacy test/docs/previews and any configured preview_paths join the autoload paths when previews are enabled, so preview files reload in development. Discovery uses require_dependency and rescans on each lookup.
  • Generator: previews are written to test/agents/previews, with /rails/agents/... URLs, and call Agent.with(params).action so query parameters reach the agent.
  • InlinePreviewInterceptor: skips objects without html_part, and keeps rewriting cid: images for mail-shaped objects.
  • Docs: a "Browser previews" section in docs/framework/rails.md; generator output paths fixed there and in AGENTS.md.

show_previews still defaults to development only, and the actionagent dashboard gem is not needed.

Checks

  • test/preview_integration_test.rb (new) generates plain and namespaced agents into fresh framework-only hosts (no Active Record) and drives them through an integration session. The mock provider is patched to raise, so any provider call fails the test.
    • Enabled:
      • Index lists generated, namespaced, legacy and custom-path previews.
      • Preview escapes <script> in parameters.
      • The download link ignores host/script_name query parameters.
      • Download returns a text/markdown attachment that contains the passed parameter.
      • Unknown paths and object_id return 404.
      • After a preview file is edited, reloader.reload! picks up the change.
      • A remote address gets 403 on all three endpoints.
    • Disabled, and production by default: no rails/agents routes.
  • test/preview_test.rb (new): the interceptor accepts a Generation and still rewrites inline images for mail-shaped objects. A preview file added after the first discovery is found.
  • Each fix was reverted one at a time, and each revert fails at least one test: controller removed, old generator path, no with(params), old interceptor, cached discovery, no autoload paths (reload fails), no require_local! (remote request accepted).
  • bin/test: 4098 runs, 0 failures, 0 errors. bin/rubocop reports no offenses.

🤖 Generated with Claude Code

yorzi added 2 commits October 24, 2026 12:28
Write previews to the directory the Railtie searches and use current
preview URLs. Forward preview parameters to the generated agent call.

Look for new preview files on each discovery, and leave generation
objects intact in the mail-specific image interceptor. Cover the
original failures and retain inline-image handling for mail objects.
The Railtie registers preview routes but ships no controller for them.
Render escaped Markdown requests, list namespaced previews and download
only declared preview actions. Apply Rails diagnostic-page access rules.

Register default, legacy and configured preview directories with the
Rails reloader. Exercise generated previews in fresh framework-only
hosts, including reloads, disabled routes and refused remote requests.
The tests fail if a preview executes the mock provider.

This branch has not been deployed

No deployments
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.

1 participant