Extract the previously monolithic knowledge page into focused modules under
features/knowledges/ to match the resources/flows convention:
- knowledge-form: schema, helpers and RHF wiring
- knowledge-form-layout: desktop split / mobile stacked layouts
- knowledge-form-controls: meta fields and content (markdown) field
- knowledge-header / knowledge-layout: shared header and loading/not-found shell
Promote the unsaved-changes machinery to reusable primitives
(use-unsaved-changes-guard hook + unsaved-changes-dialog) so other forms
can adopt the same flow.
Tighten markdown-editor for knowledge content authoring: disable
transformPastedText (a leading "- " or "1. " no longer silently turns a
plain paste into a list/blockquote) and reserve the editor's bounding box
during tiptap initialization to avoid layout jumps on mount.
Co-authored-by: Cursor <cursoragent@cursor.com>
On the knowledge edit page the Save button was enabled immediately
after load — and the toolbar's Undo button along with it — even though
the user had not edited anything. Two distinct mount-time noises were
leaking into RHF and the UndoRedo plugin.
1. tiptap-markdown re-serializes the initial content during view
construction (whitespace around fenced code blocks, hard-break
markers, etc.) and fires onUpdate with the normalized markdown.
Forwarding this echo to field.onChange flips RHF's isDirty.
Defer onUpdate forwarding via isInitializedRef set inside onCreate
and use the editor's own serialized markdown as the echo baseline.
2. Construction-time transactions from trailingNode and the mount-time
setContent land in the UndoRedo plugin's event stack. PM's
history() uses a singleton PluginKey, so state.reconfigure({plugins})
carries the old state over; reset the stack by rebuilding the entire
EditorState instead, then dispatch an empty addToHistory:false
transaction to wake tiptap-react's subscription so the toolbar
re-renders. Only reset on initial mount and on external value sync
so user edits are not erased.
Also dedupe knowledge.tsx Create/Update payload projection into a
shared formValuesToBasePayload helper and rename its parameter from
v to values per code-style conventions.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced a new `docType` field in the `UpdateKnowledgeDocumentInput` to manage document type changes.
- Updated the `doUpdate` method to clear subtype fields (GuideType, AnswerType, CodeLang) when the document type changes.
- Added comprehensive tests for various document type transitions to ensure correct behavior and state preservation.
- Updated GraphQL schema and generated models to accommodate the new `docType` field.
Build a small Autocomplete family on top of cmdk and Radix Popover so the
Pull dialog's container path field gets fuzzy-filtered suggestions from
paths the user has already touched (cached files, current listing,
ancestors), while still letting them type arbitrary paths. Renders inline
(no portal) to survive Radix Dialog's body scroll-lock, and delegates the
DOM input to the project Input component via Radix Slot (asChild) so cmdk
keeps the value sync and combobox ARIA without duplicating styles.
A single useCommandState selector returning a primitive hasActiveMatch
boolean keeps the per-keystroke re-render count down to one.
Drive-by: pluralize the "Upload file" dropdown item in FlowForm to "Upload
files" to match the input's multiple attribute.
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds a chevron toggle next to the "Name" header that flips every
directory in the full tree (filter-independent). Uses the existing
overrides map via a new `setExpansion(paths, isExpanded)` bulk helper
on `useFileManagerExpansion`, so a single gesture wins over the
auto-expand-on-search behavior. Skeleton header stays in lock-step.
Co-authored-by: Cursor <cursoragent@cursor.com>
The old helpers mutated the Set passed in, but the type signature
(`Set<string>`) did not communicate that — only the JSDoc did. Every
existing caller already cloned `prev` before calling, so the migration
to pure `(prev, paths) => new Set` variants is zero-cost and removes a
foot-gun. `toggleSubtreeOnSet` and `computeRowClickSelection` now
compose the pure helpers directly instead of clone-then-mutate.
Co-authored-by: Cursor <cursoragent@cursor.com>
Document the ref-based loop between performSave, onSaveFromDialog, and
useUnsavedChangesGuard so a cold reader can answer "why is the ref
declared after performSave?" without re-tracing the whole component.
Co-authored-by: Cursor <cursoragent@cursor.com>
Lock in the contract that directories collapse to size 0 in compareSizes.
Invisible while folders-first is on, but user-visible (and easy to regress)
once the Resources page lets the user disable that partition.
Co-authored-by: Cursor <cursoragent@cursor.com>
App shell:
- Switch from BrowserRouter+Routes to createBrowserRouter so pages can use
data-router-only APIs (useBlocker). Route definitions live at module scope.
FileManager:
- Sortable headers (name/size/modified) with three-state cycle, optional
per-column sortability, controlled / uncontrolled+localStorage modes via
the new useFileManagerSorting hook.
- isFoldersFirst toggle and recursive sortFileManagerTree pure reducer.
- formatModifiedAbsolute alongside the relative formatter; hosts switch via
the new Resources "Relative dates" toggle.
- Mirror hover highlight while a row's context/dropdown menu is open so the
user knows which row the menu belongs to.
- Guard row pointerdown so a touch long-press no longer stacks the row menu
on top of the empty-area menu.
Knowledge edit page:
- Decompose into focused subcomponents (header, intro, meta fields, content,
desktop/mobile body, leave dialog).
- Targeted useWatch on docType so the markdown editor no longer re-renders
meta fields on every keystroke.
- New useUnsavedChangesGuard hook encapsulates useBlocker, beforeunload and
the "Save & Leave" dialog; supports skipNextBlock for post-save navigation.
MarkdownEditor:
- Suppress echo updates from tiptap-markdown's re-serializer so RHF's
isDirty flag stays accurate.
Shared utilities:
- lib/local-storage.ts (zod-validated getStorageItem/setStorageItem) used by
both table-storage.ts and the new file-manager-storage.ts.
- lib/table-sort.ts#cycleColumnSort shared between Knowledges and Templates.
- hooks/use-latest-ref.ts replaces five useRef+useEffect pairs in FileManager.
DataTable:
- Filter input upgraded to InputGroup with search icon and clear button.
- Extract DataTableFilter subcomponent to drop the inline IIFE.
Resources page:
- Per-page persisted view options (folders-first, relative dates, optional
size/modified columns) extracted into a typed ResourcesViewOptions shape
with a centralized defaultViewOptions and a single loadViewOptions reader.
- Promote upload / new-folder buttons to the page header.
Misc:
- Replace MoreHorizontal / MoreVertical icons with Ellipsis for visual
consistency.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced "/resources" and "/knowledges" routes to the frontendRoutes array in the router configuration, expanding the application's routing capabilities.
- Removed the requirement for the "destination" field in MoveResourceRequest, allowing it to be an empty string, which signifies moving to the root directory.
- Updated related documentation in swagger.json, swagger.yaml, and docs.go to reflect the new behavior.
- Adjusted the MoveResource function to handle cases where the destination is empty, ensuring proper path sanitization and resource movement semantics.
- Enhanced test cases to cover scenarios involving moving resources to the root directory and handling conflicts appropriately.
- Allow POST /flows/0/assistants/ to create a new flow together with the assistant, mirroring the existing GraphQL createAssistant(flowID: 0) behavior
- Require both assistants.create and flows.create permissions when flowID=0
- Add explicit flow ownership check for non-zero flowID using flows.admin scope
- Load flow data in the response by fetching it via assistant.FlowID after creation, ensuring AssistantFlow is fully populated in all cases
- replace plain textarea with a tiptap-based markdown editor (StarterKit, tiptap-markdown, placeholder) and a basic formatting toolbar so authors can edit knowledge content with rich formatting while keeping markdown as the storage format for embeddings
- introduce a reusable MarkdownEditor shared component and a tiptap Storage type augmentation
- move the save action from the input addon into the page header on the right
- give each desktop resizable panel its own internal scroll so long meta or content no longer makes the whole page scroll
Co-authored-by: Cursor <cursoragent@cursor.com>
Wire up KnowledgesProvider with Apollo subscriptions and cache policies,
add /knowledges routes and sidebar entry, plus minor formatting cleanups
across file-manager, upload-validation and resources upload helpers.
Co-authored-by: Cursor <cursoragent@cursor.com>
- File manager core:
- Chevron click on folder rows now drills in via `onOpenDirectory`
(when set), matching the existing double-click / Enter semantics.
Consumers that don't wire the prop keep the legacy expand/collapse
behaviour, so flow-files / resources trees stay unchanged.
- Bulk actions bar wraps and collapses to icon-only buttons (Cancel
included) on small viewports so the bar stays usable on mobile.
- Fix tri-state subtree toggle requiring two clicks when the
directory's own path was never in the selection (e.g. user ticked
children one-by-one). \`toggleSubtreeOnSet\` now accepts an optional
\`rootPath\` and ignores it for the "all selected?" check, mirroring
what \`computeDirSelectionState\` shows on the visible checkbox.
Covered by new regression tests in \`file-manager-utils.test.ts\`.
- Built-in icons swapped: copy-path uses \`ClipboardCopy\` instead of
\`Copy\`; bulk \"Save as resources\" uses \`FolderOutput\` instead of
\`BookmarkPlus\`.
- Pull dialog: flatten the container listing (\`name\` as \`path\`,
absolute path in \`id\`) so the chevron / double-click drill into
real subfolders instead of toggling a synthetic \`work/\` wrapper that
has no meaningful navigation target. Selection is mapped back to
absolute paths via a name → absolute lookup before pulling.
- Resources page: drop the focus-derived \`currentDir\` plumbing —
toolbar mkdir / upload always target the library root, row context
menu loses \"Upload files here\" and renames \"New folder here\" to
\"New folder\". Page wraps in \`h-[calc(100dvh-3rem)]\` so the bulk
bar stays inside the viewport. Tooltips simplified accordingly.
- Flow files toolbar: replace the standalone Info icon with rich
per-button tooltips that explain where each gesture lands
(/work/uploads, /work/resources, separate Container snapshot area);
upload button uses the standard \`Upload\` glyph.
- Attach resources dialog: switch the ad-hoc footer to a proper
\`DialogFooter\` with responsive layout, tighten the dialog title.
- \`Dialog\` / \`Sheet\` footers always apply the inter-button gap,
not only at the \`sm+\` breakpoint.
Co-authored-by: Cursor <cursoragent@cursor.com>
Two cleanups closing the remaining P2/P3 gaps in the flow-files / resources
upload + delete paths.
A.4 — unify upload-batch validation
- New shared validator at `frontend/src/lib/upload-validation.ts` (with
tests) exposing `validateUploadBatch(files, limits)`. Mirrors the
per-file / per-batch / empty-file rules enforced by both backends
(`pkg/resources/resources.go`, `pkg/flowfiles/files.go`).
- `useResourcesUpload` migrated off its private validator onto the shared
helper; behaviour and toast strings unchanged.
- `useFlowFilesUpload` now runs the same preflight before constructing
the FormData. Hitting any of the 300 MB / 1000 files / 2 GB / 0-byte
rules surfaces a synchronous toast instead of a network round-trip
followed by a generic 413.
- Added `FLOW_FILES_MAX_FILE_SIZE_MB`, `FLOW_FILES_MAX_UPLOAD_TOTAL_SIZE_MB`
and `FLOW_FILES_MAX_UPLOAD_FILES_PER_REQUEST` to flow-files-constants
alongside the existing resources constants — kept as a separate set so
the two backends can diverge later without touching unrelated call
sites.
C.2 — drop redundant refetchFiles() after flow-file mutations
- The backend already publishes per-file flowFileAdded / flowFileDeleted
events (with directory expansion on delete), `lib/apollo.ts` already
maps them through the universal subscriptionCacheLink, and
`useFlowFilesRealtime` already wires the three subscriptions. Only the
imperative `await refetchFiles()` in upload/delete plus the
`onSuccess={refetchFiles}` props on pull/attach dialogs were left over
from the pre-subscription era.
- Dropped `refetchFiles` from `useFlowFilesUpload` and `useFlowFilesDelete`
param types and removed the matching `await` calls. Added optional
`onAfterDelete` to the delete hook (mirrors `useResourcesDelete`) for
callers that want a UI hook without driving a refetch.
- Made `onSuccess` optional on `FlowFilesPullDialog` and
`FlowFilesAttachResourcesDialog`; removed the `onSuccess={refetchFiles}`
passthroughs in `flow-files.tsx`. The pull dialog's internal
`refetchListing` over the container listing (a separate hook) is kept.
Verified: vitest 140/140, eslint clean on touched files, tsc shows only
the same pre-existing errors as before this change (`User.ts`/`user.ts`
casing; `single possibly undefined` in unrelated delete branches).
Co-authored-by: Cursor <cursoragent@cursor.com>
- Send `sources[]` (was single `source`) to /resources/copy,
/resources/move and /files/to-resources so multi-select operations
execute in one DB transaction; replace the per-feature 409 aggregation
state and the now-unused `resources-conflict-dialog` with the shared
`useOverwriteAction` workflow returning `OverwriteOutcome`.
- Extend `FileManager` with `emptyAreaActions` (right-click context menu
over the tree's empty area), `appliesToFiles` filter (companion to
`appliesToDirs`), `onActiveRowChange` focus reporting and row-level
external-file drop (`onExternalFileDrop`).
- `useFilesDragAndDrop`: capture-phase `onDropCapture` resets the
internal counter / `isDragging` flag before any descendant claims the
drop with `stopPropagation`, fixing the page-level upload overlay
staying stuck after a row-level drop.
- `useResourcesUpload` gains `defaultDir` (read via ref so `uploadFiles`
stays reference-stable) and `openFilePickerForDir` so toolbar /
sidebar / CTA pickers upload into the focused folder by default and
per-row "Upload here" actions can target a specific directory.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the single `onBulkDelete` prop with a generic `bulkActions` array so the
host owns which gestures appear in the footer bar. Built-in helpers (`bulkDeleteAction`,
`bulkCopyPathsAction`, `bulkMoveAction`, `bulkCopyAction`, `bulkPromoteAction`)
match the row-action pattern; each entry supports inline button or trailing
overflow menu, optional confirm dialog, isDisabled / isHidden predicates, and
receives the deduped FileNode[]. The bar also surfaces a cumulative size
summary alongside the item count.
Fix Shift+click range selection so it matches user expectations and the rest
of the file-manager's folder semantics:
- Range clicks are now ADDITIVE: the visible-order slice is unioned onto the
previous selection instead of replacing it, so Cmd-clicked picks, earlier
shift-ranges, and explicitly clicked folder subtrees survive a follow-up
Shift+click.
- Folders inside the slice expand to their full subtree via `dirSubtreePaths`,
mirroring the contract of a plain folder click. Without this, a Shift+click
across collapsed sibling folders left the folder paths in `selectedPaths`
but rendered their tri-state checkboxes as unchecked because no descendants
had been added to the selection.
- Anchor preservation across chained Shift+clicks is unchanged; toggle/single
still move the anchor.
Migrate `flow-files`, `resources`, and the move/copy/promote dialogs to the
new `bulkActions` API.
Tests: 131 passing — covers reverse direction, expanded vs. collapsed folders,
nested folders, mixed file/folder anchors, empty folders in range, omitted
`dirSubtreePaths` (tree-less callers), anchor=null and off-screen anchor
fallbacks, chained shift-clicks accumulating subtrees, toggle + shift-click
combinations, idempotent same-row range clicks, and the additive contract's
explicit divergence from Finder/Explorer (range never shrinks the selection).
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced new fields `version` and `isDevelopMode` in the Settings model to provide application versioning and development mode status.
- Updated GraphQL schema and resolvers to support the new fields, ensuring they are accessible via the Settings query.
- Enhanced Swagger documentation to reflect the changes in the Settings API endpoint.
- Added necessary validation and response handling for the new fields in the Settings service.
- Add Sources []string to MoveResourceRequest, CopyResourceRequest and AddResourceFromFlowRequest; merged with Source, deduplicated; multi-source uses destination as base dir and runs in a single atomic DB transaction
- Fix MoveResource response to return Added + Updated (not Updated only) so Apollo cache receives new parent directory entries alongside moved items
- Add missing errResourceNotFound case in CopyResource (was 500 instead of 404)
- Cover all new behaviour with table-driven tests (basename conflict, force overwrite, missing source, empty input, dir-into-itself guard, etc.)
- GraphQL/REST CRUD + semantic search for knowledge documents
- KnowledgeStore with admin/user-scoped filtering, re-embedding on update
- Real-time subscriptions (created/updated/deleted) per user and admin
- user_id tracking in all agent-stored documents (guide/answer/code/memory)
- sqlc queries, goose migrations, privilege grants, user_id backfill
- Memory cleanup on flow deletion; stale orphan purge via migration
- Unit tests for all KnowledgeStore operations including security cases
- Frontend GraphQL schema and TypeScript types regenerated
- Added `paths[]` query/body parameter to DeleteFlowFile, DownloadFlowFile,
GetFlowContainerFiles, PullFlowFiles, ListResources, DeleteResource, and
DownloadResource; single `path` parameter retained for backward compatibility.
- Introduced `DeduplicatePaths` in flowfiles package with coverage-based
deduplication (parent covers children), path normalization, and traversal safety.
- Added `ZipRelativePaths` to create ZIP archives from cache-relative paths,
sharing `zipWriteFile` helper with refactored `ZipDirectory`.
- Switched all ZIP and single-file responses to buffered `DataFromReader` with
explicit `Content-Length`, fixing Swagger UI download rendering.
- Expanded response payloads: delete and pull operations now enumerate all
affected nested files; list responses include ancestor directories for tree
completeness.
- Extended test coverage across flowfiles, flow_files, and resources packages
with batch, deduplication, atomicity, Docker exec, and security scenarios.
- Implemented `SanitizeJSONControlChars` to escape literal control characters in JSON string values, ensuring compliance with the JSON specification.
- Enhanced `SanitizeToolCallArguments` method to apply sanitization across tool call arguments in the chain.
- Added comprehensive tests for both sanitization functions to validate behavior with various input scenarios.
- Updated the logic in `determineRecentSectionsToKeep` to clamp the lower bound of the recent sections to keep, ensuring it does not exceed the available sections. This prevents potential out-of-range errors when `keepQASections` is greater than the total number of sections.
- Updated `getHTML` and `getMD` methods to return warnings for small content instead of errors.
- Implemented checks for binary URLs, returning descriptive errors when such URLs are encountered.
- Added new tests to validate the updated behavior for small and empty content handling.
- Added TryLock mechanism to avoid deadlock situations when reading from the channel while the mutex is held.
- Enhanced timer handling to reset when the mutex is not available, ensuring continuous operation of the stream.
- Added new provider configurations for vLLM Qwen 3.6 in both thinking and non-thinking modes.
- Updated the Dockerfile to include the new configuration files for vLLM Qwen 3.6 and ensure proper setup for deployment.
- Folder rows now surface a tri-state checkbox derived from descendant selection;
clicking / shift-clicking / toggling a folder flips the entire subtree in one
gesture, including descendants of a collapsed folder.
- Files get a new onOpen prop, fired on double-click and Enter; directories keep
expanding/collapsing. The resources page wires it to the existing download flow.
- Drop on a file row forwards to its parent folder so the whole folder acts as a
single drop zone (Finder/Explorer semantics), with a shared drag-enter counter
so highlight stays stable when moving the cursor between sibling rows.
- Extract pure data layer into useFileManagerData and pure selection reducers
(computeRowClickSelection / computeToggleSelection / computeToggleSelectAll /
computeDirSelectionState) into file-manager-utils; bundle per-tree row props
into display / handlers so memoized rows stay reference-stable across parent
re-renders, keyboard expansion, and selection changes.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Updated resource ID handling to ensure consistent string coercion for numeric IDs across components.
- Enhanced sorting of resources in the FlowForm to use alphabetical order based on path.
- Improved resource attachment logic in the FlowFilesAttachResourcesDialog to avoid deduplication of descendants.
- Introduced utility functions for converting REST resource entries to a consistent format for Apollo cache.
- Adjusted upload handling to ensure proper type consistency between REST and GraphQL responses.
- Refactored promote functionality to align with updated resource ID handling and improve clarity in parameters.
- Adjusted descriptions in API documentation to clarify paths for uploads, resources, and containers.
- Updated data models to use consistent naming conventions (e.g., `isDir` to `is_dir`, `modifiedAt` to `modified_at`).
- Changed resource ID types from string to uint64 for better consistency across the application.
- Enhanced flow file upload functionality to support batch processing of resource files.
- Removed deprecated code related to resource entry responses in tests.
- Replace resources feature mocks with real GraphQL + REST integration
(Apollo subscriptions-backed cache, dedicated hooks for search, upload,
copy, move, mkdir, delete, plus conflict / mkdir / copy / move dialogs
and a shared FileDropZone UI component).
- Let flows attach user resources on creation and in chat messages:
FlowForm exposes resourceIds as a form field with a multi-select
dropdown (file/folder icons), wired through createFlow, createAssistant,
putUserInput and callAssistant mutations.
- Add attach-resources and save-as-resource (promote) dialogs to the
flow files page; unify drag-and-drop via a shared
hooks/use-files-drag-and-drop.
- Harden file manager: align skeleton layout (grid + column config) with
real rows, extract use-file-manager-dnd, add group selection state and
tree-node accessibility fixes.
- Normalize numeric id/userId from REST /resources/ responses to strings
so GraphQL ID-typed consumers (zod-validated resource picker) work.
Marked with TODO(backend) for removal once the REST endpoint matches
the GraphQL ID scalar.
- Ignore *.tsbuildinfo artifacts.
Made-with: Cursor
Drops `components/ai/file-tree.tsx` and `components/blocks/{crud,skeleton}/*`
reference snippets that were never imported anywhere; the real
file manager lives under `components/file-manager/` and is the only
implementation in use.
Made-with: Cursor
- split monolithic FileManager into FileManagerTreeNode, FileManagerBulkActionsBar, and useFileManagerKeyboardNavigation
- group FileManagerProps columns/search into nested configs and rename visibility booleans from show* to is*Visible per project convention
- replace abbreviations (idx, i, Sep, Item) with full names across components, hooks, and tests
- add ARIA tree-pattern attributes (aria-level, aria-posinset, aria-setsize, aria-multiselectable) and fix aria-hidden hiding the Select-all checkbox
- add labels.formatModified to localize the date column
- make walkTree strictly pure by hiding its internal accumulator
- move side effects out of the setState updater in useFileManagerSelection
- drop redundant stopPropagation in favor of the data-fm-skip-row-click marker
Made-with: Cursor
- vendor the shadcn ai/file-tree primitive (recursive collapsible tree with shared expand/select context) for future AI chat surfaces
- vendor the shadcn crud-file-manager and skeleton-file-manager demo blocks as design references; not wired into any route yet
Made-with: Cursor
- handleConfirm now accepts () => Promise<void> | void; the dialog awaits the promise before closing
- show a Loader2 spinner on the confirm button while the handler is in flight, and disable both confirm and cancel
- block onOpenChange and outside-clicks while processing so the dialog can't be dismissed mid-action
- caller no longer needs to manage its own loading state for confirm-then-async flows
Made-with: Cursor
- add ApiResponse<T> / ApiSuccessResponse<T> / ApiErrorResponse / ApiHttpError types describing the backend protocol
- expose a typed api wrapper with helper methods (api.get / api.post / api.put / api.delete) that returns ApiResponse<T> directly and accepts per-call AxiosRequestConfig
- add unwrapApiResponse(...) and getApiErrorMessage(...) helpers so callers no longer reimplement success/error branching
- set a sensible default request timeout (30s) on the shared axios instance; long uploads still opt out via { timeout: 0 }
- migrate user-provider and password-change-form from the raw axios instance to the new typed api helpers, dropping their bespoke error-shape interfaces
Made-with: Cursor
- replace the inline file tree implementation in flow-files with the new FileManager component
- compose row actions via factory helpers (downloadAction / copyPathAction / deleteAction) instead of bespoke menus
- delegate search highlighting, expand/collapse, multi-select and bulk delete to the shared component; the page now only owns upload, drag-and-drop, pull-from-container and per-file delete confirmation
- switch to the typed axios helpers (api / unwrapApiResponse / getApiErrorMessage) for upload, pull and delete calls
Made-with: Cursor
- introduce src/components/file-manager with tree rendering, search highlighting, multi-select (single / toggle / shift-range), keyboard navigation (arrows, Home/End, Space, Cmd+A, Esc) and bulk delete
- expose unified actions[] API with downloadAction / copyPathAction / deleteAction factory helpers instead of separate built-in props
- split orchestration into useFileManagerExpansion and useFileManagerSelection hooks; derive expanded/selected state during render without useEffect, preserving Set identity for memo-friendly downstream
- add ARIA tree semantics (role=tree on the container, treeitem rows, roving tabindex via activeRowPath, aria-expanded/aria-selected)
- pure tree utils: O(1) folder lookup via Map, normalizeRootGroups, dedupeOverlappingPaths, findNodeByPath, plus 37 vitest unit tests
- ship shadcn checkbox primitive (depends on @radix-ui/react-checkbox) which the file manager uses for row and select-all controls
Made-with: Cursor
- Replaced ambiguous "user's language" guidance in tools/args.go with explicit engagement-log vs technical-channel markers per field, with strong English-only requirement for vector-store and search-engine queries.
- Added a unified LANGUAGE POLICY block to every agent prompt (primary_agent, assistant, pentester, coder, installer, searcher, memorist, generator, refiner, reporter, enricher), tailored per agent based on its actual tool set.
- Extended template variables and tool access (TerminalToolName, FileToolName) for coder, pentester, installer, memorist, generator, refiner, and enricher to match their runtime tool registrations.
- Fixed inverted UseAgents condition and removed misleading vector-store write references in assistant prompt; corrected MEMORY SYSTEM INTEGRATION for mode-specific tool references.
- Compressed COMPLETION REQUIREMENTS across templates and aligned closing-tool guidance with the channel mapping (engagement-log message vs technical-channel result).
Fixes#285.
Co-Authored-By: Octopus <liyuan851277048@icloud.com>