ui: CWD for agent - #26518
Conversation
Treat path-like queries (starting with / or ~) as directory navigation instead of glob-matching the whole query: search the parent for the last segment, and descend into an exactly-typed directory by listing its children. Show the effective search scope in the footer and auto-search on open so the current directory and its siblings appear immediately. Assisted-by: Claude
15fc821 to
fd25bd5
Compare
There was a problem hiding this comment.
Pull request overview
Adds working-directory (CWD) support to the web UI’s agent/tooling flow: users can pick a server-side working directory, tool calls execute relative paths against it via a request header, and the UI records/display CWD changes as synthetic chat rows. On the server side, file_glob_search gains directory listing + depth/limit controls and a new get_info tool is surfaced in the UI.
Changes:
- UI: adds a working-directory picker (popover + results list) and synthetic CWD-change message rendering; persists CWD on conversations and on tool-result messages.
- UI/Tools: threads
cwdinto built-in tool executions viax-tool-cwdand adds helpers for path display/parsing and picker search. - Server: extends
file_glob_search(type/max_depth/limit + structured{entries, base}response) and adds/extends unit tests around cwd behavior and glob search.
Reviewed changes
Copilot reviewed 38 out of 42 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/ui/tests/unit/working-directory.test.ts | New unit tests for working-directory picker/search helper utilities. |
| tools/ui/tests/unit/tool-calls.test.ts | Adds tests for new path-display + cwd message format/parser helpers. |
| tools/ui/src/lib/utils/working-directory.ts | New pure helpers for working-directory picker search and ranking. |
| tools/ui/src/lib/utils/path-display.ts | New helpers for path abbreviation and synthetic cwd message format/parse. |
| tools/ui/src/lib/utils/index.ts | Re-exports new working-directory/path-display helpers from $lib/utils. |
| tools/ui/src/lib/utils/agentic.ts | Extends AgenticSection with toolCwd sourced from tool result messages. |
| tools/ui/src/lib/types/database.d.ts | Adds persisted conversation cwd, plus per-message toolCwd/isSynthetic. |
| tools/ui/src/lib/types/chat.d.ts | Extends tool-result message callback signature to accept toolCwd. |
| tools/ui/src/lib/types/agentic.d.ts | Extends agentic callbacks to accept toolCwd on tool result creation. |
| tools/ui/src/lib/stores/tools.svelte.ts | Adds server home resolution via file_glob_search and caches it for abbreviations. |
| tools/ui/src/lib/stores/conversations.svelte.ts | Persists conversation cwd; adds pendingCwd for new-chat screen; adds setCwd(). |
| tools/ui/src/lib/stores/chat.svelte.ts | Records cwd changes as synthetic messages; injects pending cwd before first user turn. |
| tools/ui/src/lib/stores/agentic.svelte.ts | Threads conversation cwd into tool execution/streaming calls and tool-result creation. |
| tools/ui/src/lib/services/tools.service.ts | Adds x-tool-cwd header support; adds executeToolRaw(); threads cwd into streaming. |
| tools/ui/src/lib/services/database.service.ts | Ensures forked conversations preserve cwd. |
| tools/ui/src/lib/hooks/use-auto-scroll.svelte.ts | Adjusts auto-scroll behavior for discrete synthetic row injection. |
| tools/ui/src/lib/enums/ui.enums.ts | Adds file: to UrlProtocol enum. |
| tools/ui/src/lib/enums/tools.enums.ts | Adds GlobSearchType enum and GET_INFO built-in tool identifier. |
| tools/ui/src/lib/enums/index.ts | Re-exports GlobSearchType. |
| tools/ui/src/lib/constants/working-directory.ts | Adds constants/tuning for working-directory picker glob search behavior. |
| tools/ui/src/lib/constants/tools.ts | Defines X_TOOL_CWD_HEADER constant. |
| tools/ui/src/lib/constants/path-display.ts | Adds constants and regexes for synthetic cwd message encoding/parsing. |
| tools/ui/src/lib/constants/index.ts | Re-exports new constants modules. |
| tools/ui/src/lib/constants/built-in-tools.ts | Adds UI metadata for GET_INFO tool block. |
| tools/ui/src/lib/components/app/chat/index.ts | Exports new working-directory selector and synthetic message components. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageToolCall/ChatMessageToolCallBlockWriteFile.svelte | Abbreviates file paths under server home in tool-call UI. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageToolCall/ChatMessageToolCallBlockGrepSearch.svelte | Abbreviates grep path under server home in tool-call UI. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageToolCall/ChatMessageToolCallBlockGetInfo.svelte | New UI block for GET_INFO tool results. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageToolCall/ChatMessageToolCallBlockFileGlobSearch.svelte | Abbreviates glob-search base path under server home in tool-call UI. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageToolCall/ChatMessageToolCallBlockExecShellCommand.svelte | Displays per-call working directory for exec_shell_command results. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageToolCall/ChatMessageToolCallBlockEditFile.svelte | Abbreviates edit target path under server home in tool-call UI. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageToolCall/ChatMessageToolCallBlock.svelte | Routes GET_INFO tool calls to the new tool-call block component. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageSynthetic.svelte | New synthetic-message wrapper that routes cwd changes to a dedicated renderer. |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessageCwdChange.svelte | New synthetic cwd-change row renderer (folder row UI). |
| tools/ui/src/lib/components/app/chat/ChatMessages/ChatMessage/ChatMessage.svelte | Detects synthetic/cwd messages and renders via synthetic component; adjusts intrinsic sizing. |
| tools/ui/src/lib/components/app/chat/ChatForm/ChatFormWorkingDirectoryResultsList.svelte | New picker results list UI with match highlighting. |
| tools/ui/src/lib/components/app/chat/ChatForm/ChatFormWorkingDirectoryChip.svelte | New chip UI for showing/clearing the active cwd. |
| tools/ui/src/lib/components/app/chat/ChatForm/ChatFormWorkingDirectory.svelte | New working-directory picker component wired to file_glob_search. |
| tools/ui/src/lib/components/app/chat/ChatForm/ChatForm.svelte | Integrates the working-directory selector into the chat form. |
| tools/ui/src/app.d.ts | Adds Window.showDirectoryPicker typing for File System Access API usage. |
| tools/server/tests/unit/test_tools_builtin.py | Adds unit tests for file_glob_search type/depth/limit and cwd header path resolution. |
| tools/server/server-tools.cpp | Implements file_glob_search enhancements + structured response; adds get_info output sizing constants; refactors listing internals. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… guard, absolute base)
|
@ngxson can u take a look at the server-side code please? |
|
Opus 5 backend only review inside my testing context :
|
| // into absolute paths. `plain_text_response` is what the model sees; | ||
| // `entries` is the same data as structured JSON for the UI picker, | ||
| // which reads `entries`/`base` instead of re-parsing the text. | ||
| return {{"plain_text_response", output_text.str()}, {"entries", entries_json}, {"base", base}}; |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
There was a problem hiding this comment.
nevermind, let's keep both responses for now to simply the handling logic on web ui
There was a problem hiding this comment.
For that one we'd need to change the client and the server together, since the WebUI falls back to dumping the raw JSON into the model's context when plain_text_response is missing.
ngxson
left a comment
There was a problem hiding this comment.
I'll let you and @ServeurpersoCom discuss if these issues are worth addressing in this PR, or better to be a follow-up
ggerganov
left a comment
There was a problem hiding this comment.
Tested briefly and it works nicely
|
I've distilled my AI review this down to the essentials here, it stops the walk from crashing on a directory that disappears, makes build/ and node_modules/ selectable as a working directory without letting searches descend into them, and gives git and the walker a single 15s budget to share instead of one each. I can commit this: |
|
That leaves only Windows letter support, so that you can enter "X:\...." I push a small UI only commit |
recognize a drive root (C:) and a UNC share (//host/share) as path navigation, alongside the POSIX root and ~, so a query like D:\repos lists that directory instead of glob-matching it under the home dir split below the root, so a bare drive resolves to its root rather than to a drive-relative prefix rewrite backslashes into forward slashes only when the query carries a Windows root, since a backslash is a legal POSIX filename character paths keep travelling with forward slashes, which is what the server returns and what Windows accepts
* server : extend file_glob_search for UI pickers * ui : add per-conversation working directory with picker * ui : add path navigation and search scope to cwd picker Treat path-like queries (starting with / or ~) as directory navigation instead of glob-matching the whole query: search the parent for the last segment, and descend into an exactly-typed directory by listing its children. Show the effective search scope in the footer and auto-search on open so the current directory and its siblings appear immediately. Assisted-by: Claude * db : persist per-call tool cwd on tool result messages * ui : abbreviate tool paths under home with a tilde * ui : show the per-call cwd on exec shell rows * ui : clarify the synthetic cwd message for the model * ui : reuse the trailing cwd row on a repeated pick * ui : don't jump when a cwd row is injected mid-chat * chore: Formatting * refactor: Cleanup comments * ui : unify working directory naming and add a synthetic-message flag * ui : render synthetic cwd rows without a scroll jump * ui : decouple the working directory picker into utils and sub-components * ui : add get_info tool call block * chore: Formatting * refactor: Cleanup * refactor: Cleanup * refactor: Cleanup * fix: UI * server : harden file_glob_search listing (kind enum, timeout, symlink guard, absolute base) * ui : use persisted isSynthetic flag for cwd rows, drop legacy formats * ui : cache picker search, fail visibly on native resolve * ui : escape glob metacharacters in picker search glob * ui : simplify auto-scroll pin * chore: Format * fix: Use `SvelteMap` * refactor: Post-review fixes * ui: accept Windows roots in the working directory picker recognize a drive root (C:) and a UNC share (//host/share) as path navigation, alongside the POSIX root and ~, so a query like D:\repos lists that directory instead of glob-matching it under the home dir split below the root, so a bare drive resolves to its root rather than to a drive-relative prefix rewrite backslashes into forward slashes only when the query carries a Windows root, since a backslash is a legal POSIX filename character paths keep travelling with forward slashes, which is what the server returns and what Windows accepts --------- Co-authored-by: Pascal <admin@serveurperso.com>
Overview
Additional information
Requirements