Skip to content

feat(ai): write the AI analysis in the session language, with a summary - #2118

Open
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 5 commits into
feat/recording-events-pushfrom
feat/ai-session-language-summary
Open

irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 5 commits into
feat/recording-events-pushfrom
feat/ai-session-language-summary

Conversation

@irvingoujAtDevolution

@irvingoujAtDevolution irvingouj@Devolutions (irvingoujAtDevolution) commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

The AI analysis now writes in the session language and ends with a summary. This touches the AI crate only.

  • AnalyzeRecording::language("fr-CA"): action descriptions and the summary are written in that BCP 47 language. Without it, output stays in English as before. A value that isn't a valid tag is ignored, with a warning, because it comes from recorder data and goes into the prompt.
  • A new purpose, session_summary (AiClient::summarize_session): one extra request after the actions, only when there are actions. Its tokens count in the usage. The summary goes in summary on the AI log's session.end.
  • A summary that fails for good (refused, cut short, empty) does not throw the actions away: the log is written without summary, with a warning. A transient failure is retried, and the retry resumes from the described chunks.
  • The model and the prompt versions leave the log: they are in the analysis result.
  • Every AI log line now has source: "ai", so a caller showing it next to the recorder's events log can tell the two apart.
  • Prompt versions: session-actions-4, screen-actions-2, session-summary-1. The analysis reports session-actions-4+session-summary-1.
  • A retry with a different language starts over instead of reusing the working files.

Where to look hardest: the summary step at the end of recording_analysis/mod.rs, and the resume check on WorkspaceSettings.language in the same file.

Known limit: the summary sends all actions in one request, so a very long session could go over the model's context window.

Tests: cargo test -p devolutions-gateway-ai (the mock provider tests cover the language in the prompts, the summary call, no call when there are no actions, and a failed summary being transient).

🤖 Generated with Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Truncated summaries lose token usage, and malformed language tags pass validation.

2 open issues
What changed in this PR

Adds language-aware action descriptions and session summaries to the AI crate, supporting Gateway’s recording-log integration.

Changes:

  • Passes session language into prompts and checkpoint compatibility checks.
  • Generates summaries with retry and fallback handling.
  • Marks every AI log entry with source: "ai" and keeps model metadata in analysis results.
File Description
crates/​devolutions-gateway-ai/​tests/​providers.rs Tests language prompts and summary responses.
crates/​devolutions-gateway-ai/​src/​session_summary.rs Adds session-summary requests and serialization.
crates/​devolutions-gateway-ai/​src/​session_actions.rs Adds language-aware transcript descriptions.
crates/​devolutions-gateway-ai/​src/​screen_actions.rs Adds language-aware screenshot descriptions.
crates/​devolutions-gateway-ai/​src/​recording_analysis/​tests.rs Tests summaries, fallback, and language-sensitive resume.
crates/​devolutions-gateway-ai/​src/​recording_analysis/​slog.rs Writes summaries and AI source markers.
crates/​devolutions-gateway-ai/​src/​recording_analysis/​mod.rs Integrates language, summaries, and usage accounting.
crates/​devolutions-gateway-ai/​src/​lib.rs Exposes and documents the summary module.
crates/​devolutions-gateway-ai/​src/​client.rs Adds shared language validation and prompt rules.

Review effort: Balanced

Comment on lines +242 to +245
tag.len() <= 64
&& tag
.split('-')
.all(|subtag| (1..=8).contains(&subtag.len()) && subtag.bytes().all(|byte| byte.is_ascii_alphanumeric()))
Comment on lines +590 to +592
Err(error) => {
warn!(%error, "Writing the session log without a summary");
None
@irvingoujAtDevolution
irvingouj@Devolutions (irvingoujAtDevolution) force-pushed the feat/ai-session-language-summary branch 4 times, most recently from 5873f2b to 91d1bea Compare October 19, 2026 21:01
The recorder's events log carries the locale of the session on its
session.start. The AI log, a separate file next to it, must be written in
that language, carry a summary, and mark its own lines.

- AnalyzeRecording, DescribeSessionActions and DescribeScreenActions take
  an optional BCP 47 language; the prompts ask for descriptions in it.
  A value that is not a tag is ignored, so recorder data never adds
  instructions. Working files of another language are not reused.
- New purpose: AiClient::summarize_session. The analysis calls it once
  when there are actions and writes the text as `summary` on session.end.
- Every AI log line carries "source":"ai".
- Prompt versions: session-actions-4, screen-actions-2, session-summary-1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A summary request that fails for good (refused, cut short, empty) no
longer throws away the actions already found: the log is written
without `summary`, with a warning. A transient failure still fails the
attempt, since a retry resumes from the described chunks.

The language is checked once when the analysis is set up, so an
invalid one is reported once, not on every request. The model and the
prompt versions leave the log: they are part of the analysis result.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The reported prompt versions leave out the summary prompt when no
  summary was asked for or it could not be written.
- `Writing` is reported once the summary is done, not before asking
  for it.
- Docs no longer say the log names the model and prompt versions.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

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

Development

Successfully merging this pull request may close these issues.

2 participants