mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 09:07:40 +00:00
* fix(files): never write through a dangling symlink A path that doesn't exist yet was authorized by walking up to the nearest existing folder. A dangling symlink fails realpath with ENOENT, so the walk stepped over it and approved the link's own path; the write then followed the link and created its target outside the allowed folders. The walk now continues from the link's target, and returns that real destination. * refactor(native-chat): rename the chat visuals folder to the chat scratch folder The per-chat folder agents write into is the chat's scratch space, not only a visuals folder. Its root becomes <state>/chat-scratch/<hash> (the hash is unchanged) and the agent variable becomes ORCA_CHAT_SCRATCH_DIR. The old ORCA_CHAT_VISUALS_DIR is never set and is still stripped from what every agent child inherits, Pi included. The visuals skill names the new variable and says the folder is temporary. * test(native-chat): keep the delivery test to the rename The launch parity snapshot already pins that every agent drops the pre-rename variable. * fix(files): refuse any dangling symlink in the missing-path walk Following a dangling link by hand resolved relative targets against the lexical parent, not the link's real folder: through a folder link the walk could loop forever or authorize the wrong file. Refuse instead: realpath can't say where a dangling link leads, but a write would follow it. * feat(runtime-files): the host serves a chat's scratch folder as a file root File commands accept `path:<this host's chat-scratch root>/<32 hex>` and resolve it only when it names this host's own folder, at the file-commands seam so the selector never reaches chat placement. They authorize against the project roots plus the chat-scratch root, refuse files.open/openDiff for the folder, and agentSession.readVisual's ok results carry the file's absolute path so a client can build the selector. * test(runtime-files): name the readVisual helper's parameter type * test(files): drop the loop case that duplicated the dangling-link refusal * test(runtime-files): run the readVisual RPC test, which opens a real SQLite store, under Node * test(runtime-files): put the same-suffix folder inside the authorized root so only the selector refuses it * refactor(native-chat): open a chat visual like any file "Open in new tab" on an inline chat visual now opens the visual's file the way any HTML file of the chat's workspace opens: a file:// browser tab for a local chat (its overflow menu gains "Open source file"), the document preview for a paired-host chat (with its existing source action and Share). Edits save on the chat's host through the exact path: selector the host serves, and a matching editor save re-reads the inline copy freshly. The read-only chat-visual tab is removed. * fix(native-chat): a visual read without a path is a malformed reply A visual's path is always on the current host's readVisual answer, so the inline Open needs no branch for a missing one. Also prune the deleted chat-visual tab action from the layout-writer baseline. * test(native-chat): give visual read replies their path without longer lines * fix(native-chat): address a scratch file by its folder only outside every workspace A workspace that contains the host's state folder keeps its own address, so explorer drops, folder creation and renames inside it stay on one root. Document preview Share reads a runtime grant's own selector and root directly instead of passing the selector off as a workspace id. * test(runtime-files): wait for the stores to close before removing the state folder