The terminal learns where one command ends, and can be dragged wider
"The last command and its output" was not something the panel could honestly offer. sendToChat took the last forty rows of the screen buffer, hard-wrapped at the terminal's width with no way to tell a wrap from a newline -- its own comment said so. So bash and zsh are given the OSC 133 markers VS Code and WezTerm use, and Copy, Send and an Auto toggle are built on those. The integration is written by the PTY command string itself, with printf. sshd runs that string through $SHELL -c, so it can case on the shell's own name and needs no probe, no second channel and no writable home. Passing it through the environment does not work -- every distribution ships AcceptEnv LANG LC_*, so anything else is dropped silently -- and feeding `source ...` in as keystrokes races a slow .zshrc, echoes into the scrollback and lands in shell history. Nothing needs hiding, which is the point of choosing it: the setup runs before the shell exists and never writes to the PTY's input side, so there is nothing to echo and no fan-out gate to build. Two things were wrong in the first version and both were found by running it against real shells rather than the fake one. bash: the DEBUG trap fires before every simple command *including each one inside PROMPT_COMMAND*, so $? read from there is whatever ran a moment ago -- every command reported success. The status is captured in the trap now, which also removes the two-entry PROMPT_COMMAND dance entirely. zsh: $ZDOTDIR is already ours by the time .zshenv runs, so the shims were sourcing themselves and none of the user's configuration loaded; the original is passed on the exec line. Parsing is server-side. The `behind` path resets the terminal and replays a truncated scrollback, so a client parser routinely sees a finish with no start; two tabs share one shell and can disagree; and what comes out of this ends up inside a prompt, so deriving it here leaves nothing to disbelieve. The bytes are fanned out unchanged -- xterm consumes an OSC it has no handler for. Output is bounded head and tail, 48KB and 16KB: a build that fails ten megabytes in has the invocation at the top and the error at the bottom. Carriage returns collapse to the last state of each line, which is the difference between a usable prompt and two megabytes of spinner. The fence is sized to its content, because output containing three backticks would otherwise break out and read as prose. Any shell that is not bash or zsh starts exactly as it did before. The buttons then scrape the screen and say so, and Auto is disabled rather than degraded: forty arbitrary lines on every message is worse than nothing. Also a generic [data-resize] handle, keyboard included, persisted the way the theme is. The inspector and sidebar can have it whenever they want it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ that would be expensive to revisit. Kept current as work lands; the detail of
|
||||
**Status:** usable daily. Streaming chat, attachments, reasoning, tool calling
|
||||
with web search, custom HTTP tools and MCP servers, agent chats that work on a
|
||||
machine over SSH, a knowledge library, notes, memory and skills, speech in and
|
||||
out, users and groups, model administration, installable as an app. 837 tests,
|
||||
out, users and groups, model administration, installable as an app. 981 tests,
|
||||
`ruff` clean.
|
||||
|
||||
---
|
||||
@@ -120,6 +120,22 @@ be a different project, not a refactor.
|
||||
running, and coming back reattaches with the scrollback. An idle timeout
|
||||
is what eventually ends one, and so does deleting the chat, or disabling,
|
||||
moving or deleting the connection
|
||||
- [x] **The panel is resizable**, dragged from its edge or nudged with the
|
||||
arrow keys, and the width follows you to another browser
|
||||
- [x] **It knows where one command ends and the next begins** — bash and zsh
|
||||
are given the markers VS Code and WezTerm use, so *Copy* and *Send* mean
|
||||
one command and its output rather than the last forty rows of the screen.
|
||||
An **Auto** toggle collects each one into the next message. Any other
|
||||
shell starts exactly as it did before, the buttons fall back to the
|
||||
screen and say so, and Auto is disabled rather than degraded
|
||||
- [x] **The project directory is listed for the model** — one read-only
|
||||
command, `git ls-files` where that works so `.gitignore` is honoured for
|
||||
free, budgeted so a big directory becomes a count rather than a thousand
|
||||
filenames on every request
|
||||
- [x] **A directory is chosen by browsing it** over SFTP, not by typing a path
|
||||
into an unlabelled box
|
||||
- [x] The approval mode is chosen **before** the first message, beside the
|
||||
message box rather than in the header
|
||||
|
||||
### The library
|
||||
- [x] **Knowledge bases** — documents, images and saved web pages, grouped into
|
||||
@@ -143,6 +159,10 @@ be a different project, not a refactor.
|
||||
actually has, so the tools get used rather than ignored
|
||||
- [x] Attach menu: file, image, a web page fetched on the spot, or a document
|
||||
from the library
|
||||
- [x] **`@` to name one** — the library everywhere, and files in the project
|
||||
directory in an agent chat. The reference stays in the sentence and the
|
||||
contents come along, with the path and the machine, so the model knows
|
||||
exactly which file it was handed
|
||||
|
||||
### Audio
|
||||
- [x] **Dictation** — record in the composer, transcribed by any OpenAI-shaped
|
||||
@@ -193,6 +213,11 @@ be a different project, not a refactor.
|
||||
- [x] Admin-managed cards on the new-chat screen; three seeded once at startup
|
||||
|
||||
### Interface
|
||||
- [x] **`/` for commands** — compact, usage, mode, model, title, the panels,
|
||||
the theme. Anything not in the table is sent as an ordinary message, and
|
||||
`//` starts one with a literal slash
|
||||
- [x] **Keyboard shortcuts** for the same jobs, listed beside the commands in
|
||||
one table so `/help` cannot go stale
|
||||
- [x] **Installable** — manifest, generated PWA icons, a service worker for the
|
||||
shell and a themed offline page. The worker deliberately never touches
|
||||
`/api/`: a reply is an event stream and caching one breaks it
|
||||
|
||||
Reference in New Issue
Block a user