Repository navigation
Conversation
…credentials The explorer and a project's evaluation replays need the app signed in, and the credentials typed into the app must never pass through a model, a log, a span or a recording. A project secret now has a kind: env (what a boot hands the app, as before), sign_in (login URL, login, password and optional field selectors) or storage_state (a browser's saved sign-in). Only env secrets reach the sandbox's environment, and a sign-in secret joins the scrub lists part by part, so its password and each saved cookie value are masked on their own. Migration template 024 adds the column. BrowserSignIn fills the login form from the Rails process through a second MCP session on the sandbox's browser (SandboxBrowserDriver) and answers only whether the browser left the login page; it empties the password field when it did not, since a page snapshot shows what a password field holds. A login page without a password field is reported as unsupported. The test account step gets session endpoints to set the credentials, check them, keep the running browser's sign-in, or remove both, all asked of the permission checker as :manage_project_secrets. A browser started for a project starts with its saved sign-in. Sandbox apps write mail to files: backends set ACTION_AGENT_SANDBOX_MAIL_DIR, the engine switches Action Mailer to file delivery when it is set, and SandboxMail reads the newest message for an address through the backend's read_file verb. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A project could collect candidate scenarios only from an agent outside the dashboard. The engine now walks the project's app itself: POST /api/projects/:id/explorations asks the host's quota about :exploration first (402 and nothing started on a denial), gives the project's ready sandbox a browser (headless with the saved sign-in when none runs, asked as :browser_minutes), creates the explorer's run and the exploration, records :exploration once and queues ExplorationJob. The explorer is an ordinary AgentRun of a project-owned agent, so it is traced and its browser actions land on the browser's recording. ExplorerExecutionService offers it an allowlist of the sidecar's browser tools without their file arguments, plus sign_in (by secret reference, done in the Rails process), read_last_email, propose_candidate (through Exploration#add_candidates!, with the pages, steps and recording range since the last candidate filled in server-side) and finish. Navigation off the app is refused before it reaches the browser, and every browser result is scrubbed of the project's secrets. Its instructions list the target agent's real tools, and candidates are checked against them with the sandbox and its browser attached. The budget (minutes, browser steps, optional cost from the run's own generations) is checked after every tool call. Running out, or Stop and review, ends the walk in review with its candidates; a model that keeps calling tools after that is cut short; a crash fails the exploration and keeps what it found. A browser the start launched is stopped afterwards. AgentExecutionService gains the seams this needs: tool dispatch in its own method, extra generation options (the explorer raises max_tool_turns), and a provider class override. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scenarios found by walking an app's pages are replayed by an agent that may need the same browser. A run of a project's evaluation now gives every replay the sandbox's browser beside the sandbox: one already running, or one started headless with the project's saved sign-in before the first replay, recording to the dashboard the run was started from. Each replay's browser opens at the project's start URL, the diagnosis roster lists the browser's tools, and the run's selection records both server keys. A browser that cannot start fails the run before any replay, the way a sandbox that is no longer live does. On a backend that runs no browsers the replays reach the sandbox alone, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dashboard guide gains sections on starting the explorer and what it is offered, the test account step and its endpoints, the sandbox's mail, and the browser a project's evaluation runs reach; the secrets section names the new secret kinds and the permissions table the sign-in endpoints. The browser sessions page says a project's browser starts with its saved sign-in. CHANGELOG entries are under Unreleased. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t page The explorer and the test account step had only endpoints. The Project page's Explorations tab now starts with an "Explore the app" panel (an optional budget of minutes, browser steps and a cost cap, and the reason a start was refused) and a Sign-in panel: save a seeded account's credentials and check them, open the sandbox's browser in a window to sign in by hand and keep that sign-in, or use no sign-in. A check that finds no password field says the app's sign-in is not supported in the sandbox. The Environment tab lists only the secrets that reach the sandbox's environment, and a review says in words why a walk stopped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A browser tool the sandbox's browser did not answer for fell through to AgentToolbox, which on a single-tenant install drives the process-wide Playwright browser, outside the sandbox and its recording. The explorer now answers such a call with an error. Its run also uses the agent the run was created for, rather than looking the project's explorer agent up again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The schema tools generator writes every column commented out, so a person reviews the allowlist by editing the file. Something that has already made that judgement elsewhere, such as a dashboard where a developer ticked the columns, had no way to write the result. --filterable and --returns now declare exactly the named columns after id, in place of the commented suggestions. A column that looks like a secret, or that the model's table lacks, is left out with a note. The secret-column pattern moves to ActiveAgent::SchemaTools::SECRET_COLUMNS so the dashboard can apply the same rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A project's install pull request carries files the dashboard writes itself (the sandbox.yml that booted the project, its evaluation suite), and allows engine migrations by their whole name after any timestamp, which a File.fnmatch pattern cannot say. DraftPullRequestPublisher now takes generated_files: content offered for a path in place of anything the sandbox wrote there, compared with the checkout commit and filtered and scanned like the sandbox's own changes. An allowlist entry may be a Regexp the whole path must match. A file holding one of the project's secrets is refused: the secret scan reads SandboxSession#secret_values, which now includes the secrets of the project the sandbox was booted for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tab's count included the sign-in secrets, which the tab does not list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A project's secrets form asks for what discovery can find before the first boot. A boot that fails for anything else left the developer reading logs by hand. The setup assistant is an agent the engine defines for each project, started once per failed boot (or on request), whose runs have exactly four tools whatever the agent record names: - read_step_log: the failed boot's steps, and scrubbed log pages - set_env: a value that is not secret, stored as a project secret with the source setup_assistant and passed as boot env, unmasked; it refuses the names project secrets refuse, and values a person set - request_secret: a secret a person types in, stored as a project secret; the model never sees it - retry_boot: resume the kept boot from the failed step, once per run It has no shell, no file reads and no code session, so a log written by the repository's code can steer it no further than those tools. A run counts only when the project recorded it (agent id and run id in its settings, which only engine code writes), so the same agent run from the agents API gets none of them. Agent#execute yields the run before enqueuing it, so the record exists when the job starts. SecretRequests handlers can now refuse a name before anyone is asked, word the question (who asks, the repository, the variable, and that the value is handed to the repository's code), and decide who may answer: answering the setup assistant also needs :manage_project_secrets. The handler is told the tool call's id when it takes one, to record who answered. Automatic runs stop after three in a row without a good boot, can be switched off per project, and are executions for the quota checker. GET /api/projects/:id/input_requests lists what the project's agents are waiting on, and the project summary counts it. A boot spec that does not apply to a checkout now hands it its env as well as its secrets, so set_env values reach installed repositories too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A repository without its own agents is evaluated with the App assistant, whose tools are whatever the sandbox's MCP facade serves. A fresh install serves no schema tools, so the assistant had nothing app-specific to read, and writing the tools meant editing the checkout by hand. The sandbox manifest now lists the app's models under app/models with their columns, leaving out id and the columns that look like secrets; a backend reports them as app_models and the project keeps the last list. A developer picks models and the columns the assistant may filter on and read back (GET /api/projects/:id/app_models, PUT /api/projects/:id/schema_tools), checked against that list. Every later boot runs a trusted schema_tools step after db_prepare, built by the engine from the stored choices, which writes app/agent_tools/<model>_tools.rb through the schema tools generator's --filterable and --returns. The choices therefore survive a sandbox expiring; apply: true replaces the running sandbox with a new boot at once. The assistant's sandbox server has no allowlist, so it lists the new tools as soon as the facade serves them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Once a project's sandbox has installed the engine, the developer still had to redo the install by hand to keep it. The install pull request publishes it from the dashboard through DraftPullRequestPublisher: from the project's live sandbox (booting one first, answering 202), with a token minted at publish time, after the dialog shows the exact diff, and only on an explicit request that needs :publish_pull_request. ProjectInstallPullRequest#allowlist lets through only the Gemfile and lock, the engine's initializer and routes, the framework's config and application agent when the bootstrap generated them, the migrations action_agent:install emits matched by their whole name after the timestamp (several, such as add_agent_releases, do not mention active_agent), the schema, and the chosen schema tools. It also generates .activeagents/sandbox.yml (the setup that booted the project and the names of its secrets, never their values) and .activeagents/evals/<project>.yml (the project evaluation's enabled scenarios as a suite ActiveAgent::Evals::Suite.load reads). Anything else, .github/, and files holding a project secret are refused. While the pull request is open, every boot checks out its branch and runs SandboxBootSpec.installed, the bootstrap without the steps that install the engine. An update from a later sandbox of that branch goes on top of the branch as the sandbox checked it out. A branch GitHub would not open as a draft can be opened as a regular pull request. When the status poll reports the pull request merged, the project is installed and boots its own branch; a closed one leaves it bootstrapping again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Project page showed a failed boot and its log tail, and nothing to do about it but the Environment tab. It now carries the rest of the setup: - Waiting for you: the requests for input the project's agents are waiting on, answered in place through the input requests API, with a masked field for a secret; the boot status reads "Waiting for you: N". - Setup assistant: whether it can run and why not, whether a failed boot starts it, its latest run, and Ask the setup assistant on a failed boot. - Choose what the assistant may read: for an App assistant project, the models the last boot listed with a filter and a read box per column, saved, or saved and booted again. - Install pull request: its status (read again every minute while open), Open install PR and Update draft PR through the publish dialog, which takes a patch link of its own, and what the allowlist lets through. The page also polls while the setup assistant works or a request waits, and the Environment tab names values the assistant set. The pure logic is in utils/projectSetup.mjs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dashboard guide gains the setup assistant (its four tools, automatic and requested runs, who may answer its secret requests), requests for input on the Project page, choosing what the App assistant may read, and the install pull request with its allowlist and how boots follow its branch. The manifest section documents the models field, the boot spec section the extra steps, SandboxBootSpec.installed and the schema tools step, and the permissions table the actions these endpoints ask about. The CHANGELOG notes both entries under Unreleased. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…plorer Three paths let a sign-in secret escape the browser it was typed into: - MCPClient#call_tool logs every call's arguments at debug level, so the password and login BrowserSignIn typed landed in a development log. call_tool now takes log_arguments: false, which logs only the argument keys, and SandboxBrowserDriver#type uses it. - browser_network_request answers a request's body, and a page's request list keeps the sign-in POST until the next navigation, so the explorer could read the form body. Scrubbing only caught passwords of 8 or more characters, and none in their JSON-escaped form. The network tools are dropped from the explorer's allowlist, and SecretScrubber.with_encodings adds the JSON-escaped forms. - A sign-in was judged by whether the path changed, so an app that renders a failure on its form's POST path counted as signed in, and the typed password stayed in the field for the next snapshot. BrowserSignIn now judges by whether a password field is still shown, which also lets an app whose signed-in page shares the login path sign in. The sentinel test now also checks a debug-level log, and the failed sign-in test uses a password too short to scrub, so it checks the field is emptied rather than relying on the scrubber. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…started A project evaluation run started the sandbox's browser when none ran and never stopped it, so it ran headless until the sandbox expired, metering browser minutes for up to two hours. It was also started before the empty-selection check, so a run with nothing to replay started one too. The runner now records whether it started the browser, stops it in an ensure once the run completes or fails, and starts it only after the scenarios are known. A browser that was already running is left alone, as ExplorationJob does. ExplorationJob returned before its ensure when the exploration was no longer pending (Stop and review before the job ran) or its run was gone, leaving the browser the start launched running. Those returns now sit inside the ensure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… names
ProjectSecret#scrub_parts listed every cookie and localStorage value of a
saved storage state, and the sign-in's login. Those lists feed every
scrubber of the project's output and the owner's MCP tool results, so
ordinary values ("accepted", "expanded", a time zone) were redacted from
every page snapshot, and the test account's address was redacted from
every page and candidate, which kept the explorer from reading that
account's mail.
A storage state now contributes only the values that look like a
credential: httpOnly cookies, and any value of at least
STORAGE_SECRET_MIN_LENGTH (20) characters, which session ids and tokens
are. The login is an account name the app shows and mails, so it is no
longer scrubbed; the password still is.
An env secret named APP_SIGN_IN or APP_STORAGE_STATE could be created,
and then blocked the sign-in step with "Kind cannot change". Both names
are now refused for env secrets.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… blank Project#assign_sign_in stripped every field, the password included, while the Sign-in panel deliberately sends the password as typed. A password with leading or trailing spaces was stored without them and signed in as "failed" with no clue why. The password is now kept as typed. With credentials saved, the panel's password field is empty, and Save stayed disabled with no explanation until the password was typed again, although the placeholder suggested a blank field kept it. A blank password now keeps the saved one on the server, the panel sends the form without it, says so in the placeholder, and shows why Save is disabled whenever it is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…urn-Path SandboxMail.last_raw_message found where each message starts by a blank line followed by "Date: ". Mail puts a Return-Path (or Received) header ahead of Date, so for an app that sets return_path no start was found, the whole file parsed as one message, and read_last_email answered the oldest message's subject and links rather than the newest's. A message may now start at any header line after the blank line Mail's file delivery appends, and the Message-ID check still rejects a blank line inside a body. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rflows Every browser action answers with a page snapshot, which the sidecar inlines up to 256 KB, and every result stays in the explorer's conversation. Within the default budget of 150 steps the request would outgrow a model's context window, and the provider error then failed the walk instead of ending it in review with its candidates. Each browser result the explorer sees is now cut to RESULT_TEXT_LIMIT (24,000) characters, and once the results it was answered with add up to CONVERSATION_LIMIT (400,000 characters, about 100,000 tokens) the walk ends like a spent budget, with stop_reason "budget_context". The dashboard names that reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AgentExecutionService#prompt_provider_class and the provider_class: keyword on ExplorerExecutionService existed only so a test could run the explorer on a scripted model. The test now stubs the mock provider's constant, which the explorer agent's provider resolves to, and the hook leaves production code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Project#summary's secret_count counted the sign-in and saved-sign-in secrets as well, while the Environment tab lists environment secrets only, so the two disagreed once a sign-in was set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… built The dashboard guide and the changelog now say what the review fixes changed: the network request tools are not offered, results are cut and a full conversation ends the walk as "budget_context", a sign-in is judged by the password field and never logged, which values of a sign-in are scrubbed, that a blank password keeps the saved one, that the two sign-in names are refused for environment secrets, and that an evaluation run stops the browser it started. It also corrects the claim that a run started outside the project page reaches no browser: it uses one that is already running. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Built from the current frontend sources with npm run build, for the Sign-in panel's saved-password handling and the budget_context stop reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nages A dashboard project writes app/agent_tools/<model>_tools.rb for the models its App assistant may read, on every boot. To change or take back a choice, the boot has to rewrite or remove the files it wrote, and only those: a repository can have tools files of its own. `active_agent:schema_tools --managed` heads the file with ActiveAgent::SchemaTools::MANAGED_MARKER, which the project's boots look for. Deleting the header hands the file back to whoever edits it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…COLUMNS The sandbox manifest runs inside the checkout, against the activeagent release the checkout locks. The engine allows activeagent >= 1.4, so a repository that already locked an older framework keeps it when the bootstrap adds the engine. There ActiveAgent::SchemaTools::SECRET_COLUMNS is undefined, every model's listing raised NameError inside its rescue, and the manifest listed no models, leaving the schema tools chooser empty. SandboxManifest::SECRET_COLUMNS is the framework's pattern when it has one, and the same pattern spelled out otherwise. Reading a manifest and checking a schema tools choice use it too, since the dashboard's own framework can be as old. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hat fit Three problems with how a project's schema tool choices reached a boot: - Once a checkout locked the engine (after the install pull request merged, or a repository that already bundled it), its boot spec did not apply and the checkout booted from its own sandbox.yml. That boot dropped the spec's steps, so PUT /schema_tools answered 200 and the tools were never written. - Every chosen model went into one command, which a boot step caps at 4096 characters, and the cap was checked only when a boot built the spec. A dozen models with their columns saved fine and then failed every later boot, starting setup runs that could not fix it. - Taking a model off the list left its tools file in any checkout that already held it, so the App assistant kept those tools. --force also overwrote a tools file the repository wrote itself. A boot spec step can now be marked `always`: it runs whether the spec applies or not, after the checkout's own sandbox.yml setup when it does not. The local backend's config boot runs those steps. SandboxBootSpec.schema_tools_steps replaces schema_tools_step. It first removes every app/agent_tools file headed by the managed marker, then writes each chosen model's file with --managed unless a file the dashboard did not write is there. The commands are packed into steps of at most 4096 characters (schema_tools, schema_tools_2, ...), up to ten. Choices that need more, or one model whose command alone is too long, are refused when they are chosen (422), not at boot. A project that emptied its list still gets the removing step. The project records every model it was ever given, for the install pull request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lowlist While the install pull request is open, every boot checks out its branch with a spec that installs nothing. The publish dialog let a person untick any file, so a branch without its Gemfile.lock, routes or initializer could not load the engine, every boot failed, and "Update draft PR" needed a live sandbox that could no longer boot. - A publish, opening or updating, must take every Gemfile, Gemfile.lock, initializer, routes, schema and engine migration the sandbox changed. Leaving one out answers 422 incomplete_install, naming the files. DraftPullRequestPublisher#changed_paths lists them without reading. - The allowlist covers the tools file of every model the App assistant was ever given, so a file a boot removed after the model was taken off the list is removed on the branch too. Setup commands in the generated sandbox.yml leave out every schema tools step, however many. - The generated sandbox.yml names only real secrets under `secrets:`. Values the setup assistant set are not secrets, stay with the project and are passed to every boot. - The install patch is limited to the allowlist even when paths are named (DraftPullRequestPublisher#patch takes allowlist:). - Asking to open a new pull request while the branch is published without one says to open one for the branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the Project page's button checked whether a setup run was already at work. A second POST /setup, or a boot that failed again while the first run waited for a secret, started another run: two runs asked for the same secrets and raced to retry the boot. ProjectSetup.active_run is the project's last setup run while it is pending, running, or waiting on a request that has not expired (expired requests are settled first, which fails the run they paused). start! raises Unavailable while there is one, so POST /setup answers 409, and an automatic run after a failed boot is skipped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A value the setup assistant sets is not secret: a boot passes it unmasked as env, it is left out of scrub lists and the publisher's secret scan, and set_env may overwrite it. The secrets API passed any source through, so a person could store a real secret with the source "setup_assistant" and lose all of that protection. POST /api/projects, PUT /api/projects/:id/secrets and PUT /api/projects/:id/secrets/:name now refuse any source but "entered" and "organization_key" with 422 invalid_source. Since those values are not secret, the secrets API lists them with their value, so a person can see what the setup assistant changed. A secret's value is still never returned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e provider feat: add Opper as an OpenAI-compatible provider
…o the dashboard catalog Add opt-in Parallel Search MCP to the dashboard catalog
… cache token fields Recognise Anthropic usage by its cache token fields
…s and examples Replace retired model ids in docs and examples
…tistics Resolved on main: the changelog bullet joins a new Fixed section under Unreleased, and the dashboard bundle is rebuilt from main's frontend with this change rather than taken from the branch.
… to its provider Resolved on main: the changelog bullet joins the Fixed section under Unreleased, and the dashboard bundle is rebuilt from main's frontend with this change rather than taken from the branch.
…s that carry no index Resolved on main: the changelog bullet joins the Fixed section under Unreleased.
…eneration stopped Carries activeagents#610 (a streamed generation reports why it stopped). Resolved on main: the changelog bullets join the Fixed section under Unreleased.
…he Anthropic usage fix Merged from activeagents#583, activeagents#575 and activeagents#611 without entries. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FVSMckjfmJy2QWSb4wRrGh
…SON, HTML, Markdown) and Copy as Markdown (1.9.3) Export evaluation run reports (JSON, HTML, Markdown) and Copy as Markdown
…4m5ap6 # Conflicts: # actionagent/app/assets/builds/action_agent.js
Say what 1.9.3 releases, and what changes for a host upgrading. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FVSMckjfmJy2QWSb4wRrGh
…d code conversations, report export, provider and evaluation fixes 1.9.3 release: browser upload and code conversations, report export, provider and evaluation fixes
The agent cards carried a light-only Tailwind status pill and an ad-hoc provider chip; Agent Interactions and the sandbox runner each kept a status color map of their own; the conversation stream's role pills had their colors inline per theme. Each is now the dashboard's Badge (soft tint, strong mono text, radius 4, theme tokens), with one status tone map (statusTone) and one role map (roleBadge) in primitives, so the same word reads the same on every surface and in both themes. roleBubble keeps its shape for the callers that read its colors, over the shared tones. Two tones join the tokens for the system and developer roles. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FVSMckjfmJy2QWSb4wRrGh
The evaluation report paints with ActiveAgent::Evals::DesignTokens, which the parity test holds equal to the dashboard's tokens.css; the two tones added there for the message roles go here too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FVSMckjfmJy2QWSb4wRrGh
…role badge through the shared Badge Render every status and message role badge through the shared Badge
ActionAgent.user_menu_links takes an Array of { label:, href: } or a Proc
receiving the signed-in user and the current owner; the header lists the
result above Sign out. A hosted platform points them at its workspace,
members and account settings pages and shows its admin pages to admins.
Malformed entries are dropped and a raising Proc is logged.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QmKPEAPx8CWA9PNKDAgEKT
* Make generated agent previews discoverable and callable 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. * Restore Rails browser preview and download endpoints 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. * Clarify preview access and initialization behavior
* Keep the trace console usable without external assets The server-rendered fallback loads Tailwind, Turbo and Stimulus from CDNs, so expanding a trace needs a network and JavaScript. Ship small console-scoped styles and use native details with standalone links. Make refresh opt-in through bounded HTML refresh intervals, preserving filters without interpreting query parameters as routing options. Cover list, detail, metrics, empty states and escaped trace contents. Refs activeagents#384 * Drop the console's CDN caveat from the docs and initializer The self-hosted observability guide and the generated initializer still said the trace console loads Tailwind, Turbo and Stimulus from CDNs and recommended a custom layout to avoid them. Neither is true any longer, and a custom layout now drops the console's built-in styles. --------- Co-authored-by: Justin Bowen <JusBowen@gmail.com>
…r menu Dashboard: host links in the user menu
…iew and test generator fixes Bump activeagent, actionagent and the browser sidecar to 1.9.4 and date the changelog section. No engine migrations since 1.9.3. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QmKPEAPx8CWA9PNKDAgEKT
Release 1.9.4
The dark Traces view offered a Tools button without rendering the results. Reuse one themed renderer for calls, durations, failures and empty results in both layouts, including narrow table scrolling. Refs activeagents#384
Mount the shared themed selector in the dark header as well as the light one. Keep the chosen window, zoom bounds and agent scope when refreshing results, and allow the header controls to wrap. Refs activeagents#384
Raw limits could hide every row, raise on malformed input or load an unbounded number of traces. Parse decimal integers, default invalid input to 50, and clamp the result to 1 through 1000 after filtering. Describe the bounded recent list accurately: it has no pagination, and its row limit does not narrow the 24-hour summary. Refs activeagents#384
Moving the tool table into renderToolsBreakdown dropped the comments that explain why it exists, why it uses flexbox rather than the 12-col grid (those classes are not in the compiled Tailwind build), and what the bar measures. Restore them and note why the table has a minimum width. Minified output is unchanged. Refs activeagents#384
Tailwind compiles every class name it finds in the source, comments included. Naming the 12-column grid class in the restored comment added that rule to action_agent.css, so the committed bundle no longer matched its source. Describe the constraint without naming the class. Refs activeagents#384
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #384. This covers the two findings still open: the dark-mode TracesView gaps and the console's unbounded, mis-documented list limit. The other findings already landed: window totals and the truncation notice in #615, the offline console in #631, and the
tool_usagekey fallback in d7b31ac.What changes
renderToolsBreakdown(dark), next torenderSpansBreakdown, and both themes call it. Colors come fromtelemetryColors. Counts, failure counts, total/avg/slowest durations, the share bar, sort order and the empty state are unchanged. The table gets a 520px minimum width and scrolls horizontally on narrow screens instead of crushing its columns.TimeWindowSelector, which already resolves the theme palette, next to the view-mode toggle. That includes the agent page (embedded) and empty windows. Both header rows wrap.TracesController#fetch_traces).traces.limit(params[:limit] || 50)passed the raw value through:0showed no rows,-1or a huge value loaded everything, and some malformed values raised. The limit now goes throughInteger(params[:limit], 10, exception: false), falls back to 50 when invalid, and is clamped to 1–1000. Agent, service, status and date filters still apply first.self-hosted-observability.mddescribes the bounded recent list and notes that the 24-hour summary tiles don't depend on the limit. CHANGELOG entries are under Unreleased.Checks
actionagent/frontend/test/traceControlsViews.test.mjs(new, 8 tests, both themes): tool rows with aggregated calls, failures and durations; the empty state; a window change that refetches withminutes/bucket_seconds, keepsagent_idand replaces the tool rows; zoom stopping at the shortest and longest windows. Against main'sTracesView.jsx, every dark-mode test fails.actionagent/test/trace_console_test.rb(4 new tests): default 50 and a smaller limit in newest-first order;0,-1,1000and an oversized integer clamped; blank,abc,3oops,1.5, array and hash values falling back to 50; filters applied before the limit while the summary keeps the full count.npm test, 719 pass. A freshnpm run build:jsandbuild:cssmatches the committedapp/assets/buildsbyte for byte.bin/test: 4111 runs, 0 failures. The 182 errors are allMissing credentialsfrom the OpenAI client when noOPENAI_API_KEYis set. They reproduce on main and are unrelated.bin/rubocopreports no offenses.