Native fs events do not propagate from Windows hosts into Linux
containers, causing Vite's HMR to stop detecting file changes.
When the DOCKER environment variable is set, Chokidar now falls back
to polling with a 300ms interval, which reliably detects changes
across the Docker volume mount boundary.
Fixes#2456
An assistant message with several produced artifacts rendered one chip each in a
non-wrapping flex row, so 3+ chips overflowed and the bubble showed a horizontal
scrollbar. Add flex-wrap + gap-y-2 (the existing per-chip mr-2 keeps the
horizontal spacing) so the chips wrap to the next line, matching the other
artifact-chip render branch.
Add Material Symbols-style SVG icons (terminal / document / document-scanner) for
code_executor, artifact_generator, and read_document so they render with an icon
like the other tools. The ToolIcon import.meta.glob resolves tool_<name>.svg by
backend tool name automatically — no registration needed.
Rename the Artifact Generator display name to "Artifact" (the internal
artifact_generator key is unchanged) and tighten the user-facing one-line
descriptions for Code Executor, Artifact, and Read Document.
Enable code_executor and artifact_generator by default in chats (added to
DEFAULT_CHAT_TOOLS) — they load via the synthetic-id path user- and
conversation-scoped like scheduler, and persist artifacts (no user_tools FK).
Make read_document an internal agent-builtin flagged workflow_only so it appears
only in the workflow builder, not the classic agent picker or the Add-Tool
catalog (reuses the builtin synthetic-id path; still run-scoped and authz-gated).
Per decision, default-on code_executor runs sandboxed code without an approval
prompt (the sandbox is the trust boundary); this is documented in settings and
the threat model, and multi-tenant deployments should add per-tenant isolation
(Daytona / gVisor / egress policy).
Wrap a storage read in a context manager (close the file handle), add a comment
on the expected SandboxCapacityError in the churn test, and unify the
artifacts-routes test on a single import style. Also annotate the intentional
per-session sandbox workspace path with # nosec B108 (controlled dir inside the
runner container, not an insecure shared temp file).
When code_executor or read_document is given an input that doesn't resolve to an
existing artifact, it now falls back to the caller's own chat attachments,
bridges the referenced one into a conversation-scoped artifact (idempotent,
server-computed size/sha256, quota-respected), and stages it. This is lazy —
plain chat uploads are never bridged, only a file a tool actually references —
and conversation-scoped only (workflow nodes bridge attachments up front).
The match is confined to the request's own attachments and re-verified against
the user-scoped attachments repo, so a model-supplied name/id can only ever reach
the caller's own files. Only the current request's attachments are reachable (the
attachments table has no conversation column); prior-turn files are a follow-up.