ui: CWD for agent (#26518)
* 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>
This commit is contained in:
co-authored by
Pascal
parent
0713275082
commit
2f56fc3431
@@ -15,6 +15,7 @@ import {
|
||||
FilePlus,
|
||||
FileSearch,
|
||||
FileText,
|
||||
Info,
|
||||
SearchCode,
|
||||
Terminal
|
||||
} from '@lucide/svelte';
|
||||
@@ -41,6 +42,7 @@ export const BUILTIN_TOOL_UI: Readonly<Record<BuiltInTool, BuiltinToolUiEntry>>
|
||||
source: ToolSource.BUILTIN
|
||||
},
|
||||
[BuiltInTool.GET_DATETIME]: { icon: Clock, label: 'Current time', source: ToolSource.BUILTIN },
|
||||
[BuiltInTool.GET_INFO]: { icon: Info, label: 'Runtime info', source: ToolSource.BUILTIN },
|
||||
[BuiltInTool.EXEC_SHELL_COMMAND]: {
|
||||
icon: Terminal,
|
||||
label: 'Run command',
|
||||
|
||||
@@ -40,6 +40,7 @@ export * from './mcp';
|
||||
export * from './mcp-form';
|
||||
export * from './mcp-resource';
|
||||
export * from './message-export';
|
||||
export * from './path-display';
|
||||
export * from './model-id';
|
||||
export * from './model-loading';
|
||||
export * from './sse';
|
||||
@@ -60,3 +61,4 @@ export * from './ui';
|
||||
export * from './uri-template';
|
||||
export * from './url';
|
||||
export * from './viewport';
|
||||
export * from './working-directory';
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Constants for synthetic working-directory messages.
|
||||
*
|
||||
* The synthetic cwd-change message is text the UI renders as a folder row
|
||||
* and the model sees as a turn reminder. The prefix and cleared marker keep
|
||||
* the human-readable wording; the file-link regexes parse the
|
||||
* `[file:///abs/path](display)` payload back out on the UI side.
|
||||
*/
|
||||
|
||||
import { UrlProtocol } from '$lib/enums';
|
||||
|
||||
export const CWD_CHANGED_PREFIX = 'Set working directory to ';
|
||||
export const CWD_CLEARED_TEXT = 'Working directory cleared';
|
||||
|
||||
export const HOME_TILDE = '~';
|
||||
export const HOME_TILDE_PREFIX = '~/'; // tilde plus path separator
|
||||
|
||||
/** Scheme prefix of the file link embedded in a synthetic cwd message. */
|
||||
export const FILE_URI_PREFIX = `${UrlProtocol.FILE}//`;
|
||||
|
||||
/** Matches the leading `[file:///abs/path](display)` link; not anchored to the end so trailing guidance may follow. */
|
||||
export const CWD_LINK_REGEX = /^\[file:\/\/([\s\S]*?)\]\(([\s\S]*?)\)/;
|
||||
@@ -1,5 +1,8 @@
|
||||
import { ToolSource } from '$lib/enums/tools.enums';
|
||||
|
||||
/** HTTP header carrying the working directory a tool call runs in. The server resolves relative paths against it; the model cannot override it. */
|
||||
export const X_TOOL_CWD_HEADER = 'x-tool-cwd';
|
||||
|
||||
export const TOOL_GROUP_LABELS = {
|
||||
[ToolSource.BUILTIN]: 'Built-in',
|
||||
[ToolSource.CUSTOM]: 'JSON Schema',
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Constants for the working-directory picker's glob search.
|
||||
*
|
||||
* The picker glob-matches home-relative names client-side. Character classes
|
||||
* are built case-insensitively and the reserved glob metacharacters are
|
||||
* escaped (passed through literally) so a query never changes matching.
|
||||
*/
|
||||
|
||||
export const GLOB_WILDCARD = '*';
|
||||
|
||||
/** Character that starts and ends a glob character-class fragment. */
|
||||
export const GLOB_RANGE_OPEN = '[';
|
||||
export const GLOB_RANGE_CLOSE = ']';
|
||||
|
||||
/** Query characters that carry glob meaning and are passed through literally. */
|
||||
export const GLOB_SPECIAL_CHARS = '*?[]';
|
||||
|
||||
/** Separator Windows accepts alongside `/`, and a legal POSIX filename character. */
|
||||
export const WINDOWS_SEPARATOR = '\\';
|
||||
|
||||
/** `C:`, the drive part of a Windows absolute path. */
|
||||
export const DRIVE_PREFIX_REGEX = /^[A-Za-z]:/;
|
||||
|
||||
/** `C:` or `C:/`, the root of a Windows drive-absolute path. */
|
||||
export const DRIVE_ROOT_REGEX = /^[A-Za-z]:\/?/;
|
||||
|
||||
/** `//host/share` or `//host/share/`, the root of a UNC path. */
|
||||
export const UNC_ROOT_REGEX = /^\/\/[^/]+\/[^/]+\/?/;
|
||||
|
||||
// Search tuning for the picker's file_glob_search calls.
|
||||
export const SEARCH_DEBOUNCE_MS = 180;
|
||||
export const SEARCH_LIMIT = 100;
|
||||
export const MAX_RESULTS_SHOWN = 20;
|
||||
// Home-relative globs descend deeper than path navigation, which only
|
||||
// needs the direct children of the parent.
|
||||
export const SEARCH_MAX_DEPTH = 6;
|
||||
export const PATH_NAV_MAX_DEPTH = 1;
|
||||
// Native folder-picker resolution searches a shallow, bounded window.
|
||||
export const NATIVE_MAX_DEPTH = 4;
|
||||
export const NATIVE_LIMIT = 20;
|
||||
Reference in New Issue
Block a user