Skip to content

fix: AI assistant not showing logs when run selected mid-session#4475

Merged
midigofrank merged 5 commits intomainfrom
fix/4380-ai-assistant-logs-not-sent
Mar 5, 2026
Merged

fix: AI assistant not showing logs when run selected mid-session#4475
midigofrank merged 5 commits intomainfrom
fix/4380-ai-assistant-logs-not-sent

Conversation

@lmac-1
Copy link
Copy Markdown
Collaborator

@lmac-1 lmac-1 commented Feb 27, 2026

Description

Users reported that logs weren't appearing in the AI assistant even when the "Send logs" checkbox was checked. Sentry showed context.log = null errors.

The bug occurred when:

  1. User opens AI assistant for a job (no run selected)
  2. User later selects a run from history
  3. User checks "Send logs" and sends a message
  4. Logs don't appear (context.log is null)

Root cause: follow_run_id was only stored during session creation. When users selected a run mid-session, the frontend sent follow_run_id in params, but the backend wasn't updating session.meta with the new run context, so logs couldn't be fetched.

Closes #4380

Solution

Store and propagate follow_run_id during message processing:

  • Added maybe_put_follow_run_id_in_meta/2 helper in AiAssistantChannel to store follow_run_id from params in message.meta
  • Updated MessageProcessor.update_session_with_job_context/2 to propagate follow_run_id from message.meta to in-memory session.meta
  • This ensures maybe_add_run_logs can find the run_id and fetch logs during enrichment

Regression tests:

  • Channel test: Verifies follow_run_id is stored in message.meta
  • Message processor test: Verifies successful processing with follow_run_id
  • Integration test: Verifies logs are fetched when follow_run_id is added mid-session

Validation steps

  1. Open a workflow
  2. Run it
  3. But make sure no run is selected (viewed) in the canvas
  4. Select a job node
  5. Open the IDE
  6. Now open the AI Assistant
  7. Send a message to create a brand new AI session
  8. Now select a run (click the History button in the IDE and pick a run, or just run the workflow again)
  9. Now check the 'Send logs' checkbox in the AI Assistant (don't create a new AI session, continue with the session you created at step 7)
  10. Now ask the AI Assistant if it 'sees' your logs. It should now see your logs. Ask questions about the logs or ask it to give more information to make sure it's not inventing the logs.

Additional notes for the reviewer

n/a

AI Usage

Please disclose whether you've used AI anywhere in this PR (it's cool, we just
want to know!):

  • I have used Claude Code
  • I have used another model
  • I have not used AI

You can read more details in our
Responsible AI Policy

Pre-submission checklist

  • I have performed an AI review of my code (we recommend using /review
    with Claude Code)
  • I have implemented and tested all related authorization policies.
    (e.g., :owner, :admin, :editor, :viewer)
  • I have updated the changelog.
  • I have ticked a box in "AI usage" in this PR

elias-ba and others added 3 commits February 26, 2026 20:05
follow_run_id was only stored in session meta during channel JOIN.
When a user created a session without a run selected and later picked
one, the backend silently dropped follow_run_id from new_message params,
so maybe_add_run_logs never found it and context.log was null.

Now follow_run_id is stored per-message on message meta (same pattern as
unsaved_job), and the Oban worker propagates it to the in-memory session
before enrichment.
Add tests to prevent regression of the bug where logs weren't sent
to Apollo when users selected a run mid-session. Tests verify that
follow_run_id is properly stored in message.meta and propagated
during message processing for log enrichment.
@josephjclark
Copy link
Copy Markdown
Collaborator

This all seems very plausible @lmac-1 but I am still unable to reproduce this against main locally. I consistently see the logs being uploaded. I've tried following your steps several times - I must be doing something subtly wrong? I presume you've managed to repro?

I for one would be happy to merge it and see. We'd have to track it closely in prod.

@lmac-1
Copy link
Copy Markdown
Collaborator Author

lmac-1 commented Mar 2, 2026

Loom here to see it in action before and after the fix. The steps are a bit fiddly. https://www.loom.com/share/a569fbb2e34f4fb3bb006aea028ec50d

@josephjclark
Copy link
Copy Markdown
Collaborator

Ah fantastic @lmac-1 thank you - I'll take a look in the morning

@josephjclark
Copy link
Copy Markdown
Collaborator

That's amazing @lmac-1 I can repro!!!

Copy link
Copy Markdown
Collaborator

@josephjclark josephjclark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot comment on the technical solution but I've tested this and verified

What makes this hard is a litany of bugs around logging (from being able to tick Send Logs when none are available in the first place, to the assistant happily lying about the logs it receives). And the use-case reproduced feels a bit niche - is this the problem that's being reporting in production?

But @lmac-1 has 100% identified a bug and 100% fixed it as far as I'm concerned, so it's a Yes from me, Jim.

Copy link
Copy Markdown
Collaborator

@midigofrank midigofrank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done

@midigofrank
Copy link
Copy Markdown
Collaborator

@lmac-1 looks like you have one failing test.

lmac-1 added 2 commits March 4, 2026 15:43
The regression test added in 5a22a97 had three setup issues:
- Missing workflow and project in test context
- Missing required dataclip for run creation
- Message lookup found first user message instead of the specific
  message with follow_run_id

Fix by using workflow/project from context, creating a dataclip,
and finding the message by content to get the correct one.
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.42%. Comparing base (675fda7) to head (f9b7d5a).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4475   +/-   ##
=======================================
  Coverage   89.41%   89.42%           
=======================================
  Files         425      425           
  Lines       20245    20253    +8     
=======================================
+ Hits        18102    18111    +9     
+ Misses       2143     2142    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lmac-1
Copy link
Copy Markdown
Collaborator Author

lmac-1 commented Mar 4, 2026

@midigofrank tests are now fixed. Thanks!

@midigofrank midigofrank merged commit 734287a into main Mar 5, 2026
7 checks passed
@midigofrank midigofrank deleted the fix/4380-ai-assistant-logs-not-sent branch March 5, 2026 06:19
@github-project-automation github-project-automation Bot moved this from New Issues to Done in Core Mar 5, 2026
stuartc added a commit that referenced this pull request Mar 6, 2026
* feat: add SearchParams and list_channel_requests/3 to Channels context

Introduces Lightning.Channels.SearchParams, an embedded schema that
parses and validates channel request filter params from URL query strings.
Adds list_channel_requests/3 to the Channels context, returning a
paginated Scrivener.Page of ChannelRequest structs with :channel and
filtered :channel_events preloaded (source_received and error types only).

* feat: add Channel Requests log page

Adds a paginated Channel Requests page at /projects/:id/channels/requests
with a changeset-backed channel filter dropdown. The page uses
SearchParams and list_channel_requests/3 from the Channels context to
display request ID, path, channel name, started-at timestamp, status
badge, and error message.

Also adds a "Channel Requests" nav item in the sidebar (experimental
features only) and converts the Requests count and Last Activity cells
on the Channels CRUD page into links that navigate to the requests page
pre-filtered to that channel.

* refactor: use ExMachina factories in list_channel_requests test helpers

* improve channel request logs page styling and fix pagination path bug

* fix failing tests

* update changelog with 2.15.15

closes #4477

* allow URL_HOST, URL_PORT, URL_SCHEME env vars to work in dev/test

Previously these env vars only took effect in production. In dev/test
the endpoint URL was hardcoded by config/*.exs, making it impossible to
configure via env vars in dev containers (e.g. dev-elixir.local:4000).

Move the unified URL config (host, port, scheme) before the prod block
so it applies in all environments, with sensible per-env defaults.

* fix: return 401 consistently for channel source auth failures

Previously, invalid credentials returned 404 while missing credentials
returned 401. This was inconsistent and leaked resource existence via
the 401 anyway. Simplify authenticate_source into a single function.

* fix: display request path on channel requests page

The events preload and helper were filtering for :source_received events
which are never created — the handler only writes :sink_response or
:error events. Also remove em dash fallbacks for empty values.

* Support batched logs from the worker (#4174)

* support batched logs

* Introduce another event run:batch_logs for batch logs

* update changelog

* refactor to make credo happy

---------

Co-authored-by: Frank Midigo <midigofrank@gmail.com>

* fix: AI assistant not showing logs when run selected mid-session (#4475)

* fix: store follow_run_id on message meta so logs reach Apollo (#4380)

follow_run_id was only stored in session meta during channel JOIN.
When a user created a session without a run selected and later picked
one, the backend silently dropped follow_run_id from new_message params,
so maybe_add_run_logs never found it and context.log was null.

Now follow_run_id is stored per-message on message meta (same pattern as
unsaved_job), and the Oban worker propagates it to the in-memory session
before enrichment.

* test: add regression tests for follow_run_id propagation (#4380)

Add tests to prevent regression of the bug where logs weren't sent
to Apollo when users selected a run mid-session. Tests verify that
follow_run_id is properly stored in message.meta and propagated
during message processing for log enrichment.

* updates changelog

* test: fix failing follow_run_id regression test (#4380)

The regression test added in 5a22a97 had three setup issues:
- Missing workflow and project in test context
- Missing required dataclip for run creation
- Message lookup found first user message instead of the specific
  message with follow_run_id

Fix by using workflow/project from context, creating a dataclip,
and finding the message by content to get the correct one.

---------

Co-authored-by: Elias W. BA <eliaswalyba@gmail.com>

* fix: move Plug.Telemetry before ChannelProxyPlug so proxied requests get instrumented

* feat: add LOG_QUEUE_QUERIES config to control queue claim log noise

The run claim polling generates heavy Ecto debug output in development.
Add a LOG_QUEUE_QUERIES env var (default: false) that controls whether
queue claim queries are logged, threading the value through all SQL
calls in Runs.Queue.

* fix: update channel request index tests after template changes

- source_event_path now queries :sink_response events (not :source_received)
- Dash placeholder test updated since template renders nil instead of em-dashes

* fix: add @moduletag :capture_log to all AI assistant test files

AI assistant tests were leaking error-level log messages into unrelated
test output during concurrent async execution. The MessageProcessor Oban
worker and AiAssistant module log errors when AI queries fail (e.g.
"AI query failed for session", "[MessageProcessor] Failed to process
message"), and with Oban configured as `testing: :inline`, these jobs
execute synchronously within the test process.

While many individual tests had `@tag :capture_log`, this only captures
logs from the tagged test's own process. Logs from spawned processes or
PubSub callbacks could escape capture and appear in the output of
completely unrelated tests running concurrently — such as channel request
LiveView tests that have nothing to do with AI.

Adding `@moduletag :capture_log` at the module level ensures all logs
from every test in these files are captured, preventing cross-test log
contamination. Only ai_assistant_test.exs already had this tag.

* feat: extract pill_tabs component for reusable tab bar

Move the inline tab switcher styling into a new TabBar component
(LightningWeb.Components.TabBar) with a pill_tabs/1 function component.
Matches the React Tabs.tsx visual style with slate background and
indigo active state. Includes unit tests for rendering, active state
styling, patch paths, and multi-tab support.

* fix: change channel_snapshots FK to cascade delete on channel removal

channel_snapshots.channel_id used on_delete: :restrict which blocked
project purging when channels had snapshots. Changed to :delete_all
to match the workflow_snapshots pattern.

* feat: add channel logs tab to History page

Move channel request logs from a standalone page to a tab within the
History page. Adds ChannelLogsComponent as a live_component with
filtering and pagination, a new /history/channels route, and updates
links in the channel index to point to the new location.

* refactor: remove standalone channel requests page

Remove the separate ChannelRequestLive page and its nav menu item, now
that channel request logs are accessible via the History page tab.

* fix: resolve credo warnings and update cascade delete test

- Add @moduledoc to TabBar component
- Reorder import before alias in ChannelLive modules
- Remove obsolete foreign_key_constraint on channel_snapshots
- Replace snapshot deletion error test with cascade delete assertion

* fix: correct channel event types and remove unused enum values

The list_channel_requests query correctly filters to :sink_response and
:error, but the docstring and test referenced :source_received. Since
:source_received and :sink_request are never emitted by production code,
remove them from the migration enum, Ecto schema, and test factory.

* fix: use parameterized set_config() instead of string-interpolated SET LOCAL

Replace string interpolation in SET LOCAL work_mem with PostgreSQL's
set_config() function and a bind parameter. SET LOCAL doesn't support
$1 placeholders, but set_config('work_mem', $1, true) is equivalent
and eliminates the SQL injection surface.

* perf: skip re-querying in ChannelLogsComponent when params unchanged

Guard update/2 to only re-fetch channel requests when params have
actually changed. Use assign_new for the channels list so it's only
fetched once per component lifecycle.

* refactor: extract base_pill and add channel_state_pill component

Split state_pill into a shared base_pill (outer styling) and
domain-specific components. Add channel_state_pill with correct
mappings for channel request states — notably :pending displays as
"In Progress" (blue) instead of "Enqueued" (gray).

* fix: replace catch-all handle_info with explicit event clause

Replace the blanket handle_info(_event, socket) with a clause that
explicitly matches the four known PubSub events (RunCreated,
RunUpdated, WorkOrderCreated, WorkOrderUpdated) on the channel_logs
tab, preventing silent swallowing of unexpected messages.

* fix: move CORSPlug before Plug.Telemetry in endpoint pipeline

Place CORSPlug before Plug.Telemetry so CORS preflight (OPTIONS)
requests are halted before the telemetry span opens, keeping them
out of endpoint duration metrics. Channel proxy and webhook requests
remain fully captured within the span.

---------

Co-authored-by: Stuart Corbishley <corbish@gmail.com>
Co-authored-by: Joe Clark <josephjclark@gmail.com>
Co-authored-by: Lucy Macartney <64803272+lmac-1@users.noreply.github.com>
Co-authored-by: Elias W. BA <eliaswalyba@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

AI assistant not sending logs in prod?

4 participants