* fix: run full browseros-agent test suite
* fix: stabilize server test reporting in CI
* fix: address PR review feedback
* refactor: extract server core test runner
* refactor: group server tests by filesystem
* fix: align CI suites with server test groups
* fix: provision server env for all CI suites
* fix: stabilize ci checks
* fix: report real test counts in ci
* refactor: remove redundant context-overflow middleware
The middleware caught provider overflow errors and re-tried with a
naive prompt truncation, but its `nonSystem.slice()` had no awareness
of tool_use/tool_result pairing — a cut between an assistant tool_use
and the matching tool_result produces an orphaned tool_use that
providers reject with a different error.
Compaction (`createCompactionPrepareStep`) already handles this safely:
`findSafeSplitPoint` walks past tool messages to preserve pair
integrity, and the pipeline (strip binary → prune → reduce outputs →
LLM summarize → sliding window) handles every overflow path before
the request leaves the agent.
Drops 426 lines: the middleware itself, its wiring in ai-sdk-agent,
and the matching test block + helpers in compaction.test.ts.
* docs: document BROWSEROS_AI_SDK_DEVTOOLS in .env.example
Surfaces the opt-in dev flag so contributors know it exists. Captures
every LLM call to .devtools/generations.json for post-hoc inspection.
- Add tool approval system with per-category approval configuration
- Build unified Governance dashboard (renamed from Admin) with pending
approvals view and execution audit log
- Move execution history tracking into the app shell
- Extract buildChatRequestBody helper and add newtab system prompt
- Add approval config change detection for mid-conversation rebuilds
* fix: remove filesystem tools when no workspace is selected
- Make workingDir optional on ResolvedAgentConfig
- Remove resolveSessionDir() fallback that always created a session dir,
masking the no-workspace state and keeping filesystem tools available
- Gate buildFilesystemToolSet() on workingDir being defined
- Add workspace change detection mid-conversation — rebuilds the agent
session when workspace is added, removed, or switched (same pattern
as existing MCP server change detection)
- download_file falls back to tmpdir() when no workspace is set
- Memory/soul tools are unaffected — they use ~/BrowserOS/ paths
* fix: sanitize message history when session rebuilds with different tools
When a session is rebuilt due to workspace or MCP changes, the carried-over
message history may contain tool parts for tools that no longer exist in
the new session. The AI SDK validates messages against the current toolset
and rejects parts with no matching schema.
- Add toolNames getter to AiSdkAgent exposing registered tool names
- Add sanitizeMessagesForToolset() to strip tool parts referencing
removed tools from carried-over messages
- Apply sanitization in both MCP and workspace session rebuilds
* fix: prepend tool-change context to user message on session rebuild
When workspace or MCP integrations change mid-conversation, prepend a
[Context: ...] block to the user's message explaining what changed.
This prevents the LLM from hallucinating tool usage based on patterns
in the carried-over conversation history.
Context messages vary by change type:
- Workspace removed: lists unavailable filesystem tools, suggests
selecting a working directory
- Workspace added: confirms filesystem tools are available with path
- Workspace switched: notes the new working directory
- MCP changed: notes that some integration tools may have changed
Only fires on the first message after a rebuild. Invisible in the UI.
* fix: make MCP change context specific about which apps were added/removed
Diff the old and new MCP server keys to produce specific context like:
- "The following app integrations were disconnected: Gmail, Slack."
- "The following app integrations were connected: Linear."
instead of a generic "some tools may no longer be available" message.
* refactor: extract shared rebuildSession helper in ChatService
Eliminates the duplicated 20-line dispose→create→sanitize→store flow
that existed separately in both the MCP and workspace change-detection
blocks.
Co-authored-by: Dani Akash <DaniAkash@users.noreply.github.com>
* test: add sanitizeMessagesForToolset test suite
Tests for the message sanitization that runs when a session rebuilds
with a different toolset (workspace or MCP change mid-conversation):
- Preserves messages with no tool parts
- Preserves tool parts when tool is in the toolset
- Strips tool parts when tool is NOT in the toolset
- Strips multiple removed tool parts from same message
- Keeps browser tools while removing filesystem tools
- Removes messages that become empty after stripping
- Preserves non-tool parts (reasoning, step-start, file)
- Returns same references when no filtering needed
- Handles empty message array and empty toolset
* style: fix biome formatting in chat-service.ts
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
* feat: isolate new-tab agent navigation from origin tab
Add origin-aware navigation isolation so the agent never navigates
away from the new-tab chat UI. This is a two-layer defense:
1. Prompt adaptation: When origin is 'newtab', the system prompt's
execution and tool-selection sections are rewritten to prohibit
navigating the active tab and default all lookups to new_page.
2. Tool-level guards: navigate_page and close_page reject attempts
to act on the origin tab when in newtab mode, returning an error
that teaches the agent to self-correct.
The client now sends an `origin` field ('sidepanel' | 'newtab')
instead of injecting a soft NEWTAB_SYSTEM_PROMPT that LLMs could
ignore. Backwards compatible — defaults to 'sidepanel'.
Closes TKT-592, addresses TKT-564
* test: add newtab origin navigation guard tests
- 14 new prompt tests verifying the system prompt adapts correctly
for newtab vs sidepanel origin (execution rules, tool selection table,
absence of conflicting single-tab guidance)
- 6 new integration tests for navigate_page and close_page guards:
rejects origin tab in newtab mode, allows non-origin tabs, allows
all tabs in sidepanel mode, backwards compatible with no session
* fix: remove daily rate-limit middleware
The daily conversation rate limit is no longer needed. Remove the
middleware, RateLimiter class, fetch-config, error type, shared
constants, DB schema table, and integration tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove unused getDb() method
No longer needed after rate-limiter removal.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sharp is a native C module (libvips) whose .node binaries can't be
embedded in Bun compiled executables. It was imported at the top level
in copilot-fetch.ts, crashing the entire server at startup.
Replace with jimp (pure JavaScript, zero native deps) which bundles
cleanly into compiled binaries. Same resize algorithm preserved.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>