feat(files): a Files section over the caller's whole space
Nightly Build / build (push) Successful in 5m36s
Nightly Build / build (push) Successful in 5m36s
Until now file browsing existed only inside a project, and the two memory
stores were reachable only by the agent's tools. `#files` is the general
surface: home, both memory stores, the shared folders and projects the
caller belongs to, plus the read-only skills and docs trees.
The root is virtual, and that is the design. Anchoring at `~` is wrong:
the explorer reads host-side, while `shared/`, `projects/`, `skills/` and
`docs/` are bind mounts inside the container — a page rooted at the home
would show less than the user has with no way to reach the rest, and on
native Linux would show Docker's empty mountpoint stubs, a door that
appears to work and leads nowhere. So level 0 is a synthetic list from the
new `GET /api/files/roots`, serialized from the caller's `UserFs` plus the
two virtual memory roots. It sends `kind`, never a label: labels are copy
and get translated.
`GET /api/files/dir` now answers `{ path, can_write, entries }`, and a
memory path is classified before `resolve_view_path` (which refuses one)
and listed from `memory_docs`: one level derived from the flat key space
by the pure `memory_docs::immediate_children`, over a single query whose
unslashed prefix also spots an exact note as "not a directory". Memory is
read-only from the page — every writer routes through `resolve_view_path`,
and `shared-memory/*` is `@fs_write require` for the agent, so a button
that walks past that rule is a decision of its own.
The explorer moves out of projects into `shared/file-explorer.js`, taking
`root` + `rootLabel` and reading `can_write` from the listing rather than
from its host: writability changes per branch and comes from the same
`UserFs::can_write_to` the server rejects writes with, so the buttons
offered and the writes accepted cannot disagree. Deep-linking needed it
steerable without a two-way binding, hence `rel` in and
`explorer-navigate` out — the event fires only for a click, never for a
`rel` the host set, so echoing it back is a no-op.
The URL carries the agent path of the open folder in one parameter, the
same vocabulary the assistant uses, so a link is shareable and pasteable
into a conversation; which root it belongs to is derived, not stored.
docs/: a new files.md, plus two pages this made false — shared-folders.md
claimed in three places that a shared folder has no explorer, and
memory.md never said a user can now read their own notes.
This commit is contained in:
@@ -19,6 +19,8 @@ The rule that decides between them, and the one to explain when a user asks: **s
|
||||
|
||||
**Writing to shared memory asks for confirmation.** Saving to their private memory is silent; adding or changing something in shared memory shows an approval card first, because it becomes visible to everyone. Appending to the shared `log.md` is the one exception — the history must always be recorded.
|
||||
|
||||
**They can read their notes themselves.** Both stores appear as folders on the **Files** page (sidebar → Files), so a user can open and read any note without asking you — but **read-only**: editing and deleting still go through you, which is what keeps `log.md` honest and, for shared memory, keeps the confirmation step in place. See [files.md](files.md).
|
||||
|
||||
**Superseded facts stay visible.** In shared memory nothing is deleted; an outdated fact is struck through and the new one added underneath. A user asking "why is the old date still there?" is seeing this on purpose.
|
||||
|
||||
**You may decline to change a shared fact.** Every shared fact records who put it there. If someone tells you a fact is wrong and it isn't theirs, you note their claim — marked `unconfirmed` — but leave the fact alone until the person it belongs to, or an admin, confirms it. Explain it as protection, not distrust: it means nobody can quietly rewrite what the group relies on, and it means a mistake or a joke can be undone.
|
||||
|
||||
Reference in New Issue
Block a user