staff-mcp 2.0.2 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  # Independent file manager extension
2
2
 
3
- This document describes the current file extension, including unreleased runtime simplifications after 2.0.1; published release notes remain unchanged. Reverse and extensions require a matching chat-ai host implementing reverse v1 and session-relative data paths, with matching host/descriptors/UI assets. The authoritative protocol is `chat-ai/docs/protocol/README.md` at that compatible host version; both endpoints implement it themselves, with no required extension SDK. Standard stdio/Streamable HTTP tools/resources/prompts remain supported. No Chat8/schema9/format7/share protocol2 data migration is required. See [compatibility and upgrade](../README.md#compatibility-and-coordinated-upgrades).
3
+ This document describes the current file-extension source contract, including the shared workspace and allowed-directory configuration introduced in 2.0.2. Windows native terminal and eligible Windows Docker Desktop Linux-container extension support are included in staff-mcp 2.0.4, not 2.0.3; extension protocol versions are unchanged. Reverse and extensions require a matching chat-ai host implementing reverse v1 and session-relative data paths, with matching host/descriptors/UI assets. The authoritative protocol is `chat-ai/docs/protocol/README.md` at that compatible host version; both endpoints implement it themselves, with no required extension SDK. Standard stdio/Streamable HTTP tools/resources/prompts remain supported. No Chat8/schema9/format7/share protocol2 data migration is required. See [compatibility and upgrade](../README.md#compatibility-and-coordinated-upgrades).
4
4
 
5
5
  Extensions are off by default. Unsupported versions, unavailable optional features or failed data setup leave an otherwise healthy standard MCP connection usable, without enabling the affected App. This does not make the old reverse handshake compatible: reverse requires a paired upgrade even when extensions are disabled, with no old-protocol fallback or automatic transfer resumption.
6
6
 
7
- Requires Node.js 22.22.2 or newer on the host and in Docker. Linux and Linux-host local Docker Engine are the primary full-extension environments. Windows native standard MCP (stdio and HTTP) and Windows Docker standard MCP have been validated, not full extensions. Non-Linux Docker launchers disable optional extensions; macOS is untested.
7
+ Requires Node.js 22.22.2 or newer on the host and in Docker. Current source supports native Windows extensions and eligible Windows Docker Desktop Linux containers, subject to per-feature prerequisites. Docker preflight checks the Linux-container daemon OS, not the launcher OS; HTTP/stdio also require a verified local Unix socket or named-pipe (`npipe`) endpoint. Windows containers are not supported for extensions. Native terminal needs Windows build >= 18309 and a loadable ConPTY dependency, not merely a file UI that opens. Windows arm64 and macOS are not hardware-validated; musl/Alpine terminal support is not promised.
8
8
 
9
9
  ## Tools, file apps, and Resources
10
10
 
@@ -29,7 +29,7 @@ The initialize capability uses one discovery root:
29
29
  }
30
30
  ```
31
31
 
32
- All extensions are disabled by default. The manifest above applies when files is explicitly enabled; a usable, explicitly enabled Linux PTY adds `cc.qqxing/streams: {versions:[1]}` (not a terminal manifest entry). Apps/data dependencies are derived automatically from enabled, available features; terminal alone does not enable files. Disabled features register no corresponding business handlers or UI Resources. With all extensions off there is no extension manifest, app/data handler or application data listener/session; ordinary tools and non-UI Resources remain. If the requested terminal's platform/native PTY/shell requirements are unavailable, staff warns and omits terminal/streams while retaining standard MCP and any available files capability. Negotiation is tied to the actual initialized SDK session, not a client name. Calls to `cc.qqxing/apps/v1/list {}` return `{apps:[...]}`. The `files` descriptor uses `ui://staff-file-manager/v1/index.html`, `mimeType:"text/html"`, `bridgeVersion:1`, `icon:"folder"`, `requiredExtensions:{"cc.qqxing/files":1,"cc.qqxing/data":1}`, and the ordinary `cc.qqxing/file-manager/*` methods listed below. It declares `capabilities.files:{version:1,upload:true,download:true}`; file lifecycle methods are owned by the files module, not descriptor-provided method mappings.
32
+ All extensions are disabled by default. The manifest above applies when files is explicitly enabled; a usable, explicitly enabled Linux/Windows PTY adds `cc.qqxing/streams: {versions:[1]}` (not a terminal manifest entry). Apps/data dependencies are derived automatically from enabled, available features; terminal alone does not enable files. Disabled features register no corresponding business handlers or UI Resources. With all extensions off there is no extension manifest, app/data handler or application data listener/session; ordinary tools and non-UI Resources remain. If the explicitly requested terminal's platform/native PTY/shell requirements are unavailable, startup fails even when files is also requested; terminal/streams are not silently omitted. With terminal disabled, native PTY code is not loaded. Files-only optional-extension degradation is unchanged. Negotiation is tied to the actual initialized SDK session, not a client name. Calls to `cc.qqxing/apps/v1/list {}` return `{apps:[...]}`. The `files` descriptor uses `ui://staff-file-manager/v1/index.html`, `mimeType:"text/html"`, `bridgeVersion:1`, `icon:"folder"`, `requiredExtensions:{"cc.qqxing/files":1,"cc.qqxing/data":1}`, and the ordinary `cc.qqxing/file-manager/*` methods listed below. It declares `capabilities.files:{version:1,upload:true,download:true}`; file lifecycle methods are owned by the files module, not descriptor-provided method mappings.
33
33
 
34
34
  Old `experimental["cc.qqxing/apps"]`, `cc.qqxing/file-transfer/*` and private FTE chunks are not aliases or fallbacks; no backend MCP WS data path remains (the independent browser App stream WS is not a fallback). Ordinary tools and standard non-UI Resources do not require app negotiation; they remain available without granting implicit file-app or terminal access. A files manifest alone does not provide a binary path: negotiate data v1 and configure the current connection dataSession. Local stdio/Docker, direct HTTP and reverse use the same raw HTTP/consumption-ACK protocol; unsupported extensions do not affect standard MCP clients.
35
35
 
@@ -77,7 +77,7 @@ Files is enabled by `--extensions files` (or `--extensions files,terminal`). Fil
77
77
 
78
78
  No system root is authorized automatically. Explicit `-d /` authorizes the filesystem visible to staff for both tools and files, subject to OS permissions. Docker reuses only the existing workspace and allowed-directory mounts, not separate file-root mounts; explicit host-root authorization is deliberately broad and remains subject to Docker topology and permissions. Terminal still starts at the workspace. File/path guards are not a machine-wide boundary against an arbitrary same-user shell. Removed CLI options fail as unknown options; see [CLI changes](../README.md).
79
79
 
80
- Docker uses the same allowed-directory mounts for tools and files. Host filesystem roots map to `/opt/staff-allowed/root-N`, never container `/`; inner allowed directories and protected staging aliases follow that mapping.
80
+ Docker uses the same allowed-directory mounts for tools and files. Host filesystem roots map to `/opt/staff-allowed/root-N`, never container `/`; Windows drive/UNC allowed directories are translated into the POSIX container namespace. Inner allowed directories and protected staging aliases follow the same mapping, including overlapping mounts: Windows path translation does not bypass staging protection or add authorization.
81
81
 
82
82
  Public paths are root-relative literal names, not host absolute paths or URL-encoded paths. Traversal, symlink traversal, protected roots, and private staging access are checked by the file core. Percent signs in RPC paths are literal filename characters; only the resource URI boundary decodes each component once. Root IDs are session/configuration context, not portable filesystem permissions.
83
83
 
@@ -124,7 +124,7 @@ The host generates operationId before the first asynchronous prepare. Prepared m
124
124
 
125
125
  All transports return the same prepared resource metadata, not a file-specific HTTP ticket. The host opens `purpose:"cc.qqxing/files",resourceId:transferId,direction:"host-to-remote"|"remote-to-host"` through the current shared dataSession, also used by terminal. Only a live, unused prepared resource can be bound once. `cc.qqxing/data/v1/configure {binding,origin?}` establishes the connection; `cc.qqxing/data/v1/open {binding,open,link?}` negotiates a temporary `DataLink` with version, endpoint, channel, token, binding, open and expiresInMs. expiresInMs is a relative positive TTL bounded by the open timeout, measured using local monotonic time rather than peer wall-clock timestamps. No numeric WS channel ID or file-specific `/mcp/transfers` router remains.
126
126
 
127
- With files enabled and data v1 negotiated/configured, direct HTTP uses `/mcp/data/<binding>` on the existing MCP listener, mounted before JSON parsing. For direct HTTP only, configure may include the host's configured HTTP(S) origin (no path/credentials/query/fragment) for HTTPS proxy advertisement; it does not authorize outbound fetch or trust Forwarded headers. Without it the initial request authority is used; stdio/reverse reject origin. Local stdio lazily starts a same-process 127.0.0.1 random-port listener at configure; stdout remains standard MCP JSON-RPC. The local Docker wrapper automatically publishes a private container port to a random 127.0.0.1 host port and passes baseUrl in read-only 0600 metadata, inspecting only its own cidfile container. This Docker application-data publication exists only when at least one extension is enabled; its listener remains lazy until configure. With all extensions off, dataAuto is false and no application-data publication, metadata mount, bootstrap or dataSession is created; ordinary workspace/package mounts remain. Non-Docker stdio has no application listener before configure. HTTP/reverse add no extra publication, and HTTP retains its standard MCP listener even with extensions off. The full-extension stdio Docker path requires Linux, reachable shared host loopback and a local daemon. Non-Linux Docker launchers and unsupported stdio data topologies warn and omit optional extensions, preserving standard tools when the base connection is usable; macOS is untested. Bootstrap/configure failure leaves standard MCP alive and data-dependent Apps unavailable. See the README for actual mount/daemon prerequisites; this does not add a remote tunnel or a legacy data fallback. Metadata/container uid and mount uid/gid permissions and native ABI/libc must match; no automatic chown or permission relaxation. See [README topology limits](../README.md).
127
+ With files enabled and data v1 negotiated/configured, direct HTTP uses `/mcp/data/<binding>` on the existing MCP listener, mounted before JSON parsing. For direct HTTP only, configure may include the host's configured HTTP(S) origin (no path/credentials/query/fragment) for HTTPS proxy advertisement; it does not authorize outbound fetch or trust Forwarded headers. Without it the initial request authority is used; stdio/reverse reject origin. Local stdio lazily starts a same-process 127.0.0.1 random-port listener at configure; stdout remains standard MCP JSON-RPC. The local Docker wrapper automatically publishes a private container port to a random 127.0.0.1 host port and passes baseUrl in read-only 0600 metadata, inspecting only its own cidfile container. This Docker application-data publication exists only when at least one extension is enabled; its listener remains lazy until configure. With all extensions off, dataAuto is false and no application-data publication, metadata mount, bootstrap or dataSession is created; ordinary workspace/package mounts remain. Non-Docker stdio has no application listener before configure. HTTP/reverse add no extra publication, and HTTP retains its standard MCP listener even with extensions off. The stdio Docker data path requires a verified local Linux-container daemon over Unix socket or `npipe`, reachable shared host loopback and compatible port publication; Windows Docker Desktop Linux containers can meet these conditions. Daemon OS/endpoint, not launcher OS, decides preflight. A non-Linux/unverified daemon OS, nonlocal HTTP/stdio endpoint or unsupported stdio data topology fails explicit terminal startup; files-only requests still warn and disable the optional extension when the base connection is usable. HTTP/reverse do not use this extra stdio port mapping. HTTP retains the verified-local-daemon/reachable-loopback checks; reverse still requires Linux containers and valid existing mounts. macOS is untested. Bootstrap/configure failure leaves standard MCP alive and data-dependent Apps unavailable. See the README for actual mount/daemon prerequisites; this does not add a remote tunnel or a legacy data fallback. Metadata/container uid and mount uid/gid permissions and native ABI/libc must match; no automatic chown or permission relaxation. See [README topology limits](../README.md).
128
128
 
129
129
  Reverse control uses SSE + POST on the existing Next Web port. The host includes its data link in open with the exact root-relative `/api/mcp/reverse/data/<session>` endpoint; remote resolves it against the existing `--ru` origin, validates the current session path, and actively GETs/PUTs without an inbound listener. No public URL setting is required on chat-ai. Direct HTTP/stdio return the staff endpoint link for host access instead. Both use raw binary `get` GET / `put` PUT, cumulative ACK (`ack` POST for GET consumption, `ack` GET stream for PUT consumption), and `close` DELETE. Bearer token and X-Data-Binding scope access; no browser Origin, arbitrary URL, redirects or replay. Tickets never reach the iframe. Proxy/CA-aware HTTP clients are injected by the connection; actual proxy streaming still needs validation.
130
130
 
@@ -140,7 +140,7 @@ The UI expands transfer feedback on download/upload actions. Download preparatio
140
140
 
141
141
  Image preview is limited to 2 MiB. Cancellation admitted before the final commit prevents publication; once commit has started the host returns `TOO_LATE` rather than claiming an already-issued write was undone.
142
142
 
143
- Terminal is a separate human app, not an implicit capability of enabling files; the host does not add a separate terminal permission switch. It requires the existing current-chat MCP grant, staff terminal extension enablement, Linux optional `node-pty`, and negotiated streams/data v1 with a usable duplex dataSession over supported local stdio/Docker, direct HTTP or reverse topology. Its starting cwd is not an OS sandbox, and it runs as the staff uid. Terminal I/O is not added to model context or chat history. It uses the generic browser-host `/api/mcp/app-stream` WebSocket (`chat-app-stream-v1`) with rendering-consumption ACKs, a separate 120-second browser-presence deadline and server-returned remote lease (staff defaults to 30 seconds), not the file app's two-hour TTL. Only the browser host refreshes presence every 10 seconds; the generic stream module schedules remote renewal from the returned lease; opening the app starts a PTY once, without another open button or high-risk confirmation. Exit/failure leaves the app shell available for manual reconnect, never automatic replay. Backpressured process exit can have incomplete output: current source reports remote `status.error:{code:"OUTPUT_INCOMPLETE",message:string}`, and host generic stream-frame `incomplete?:boolean` / `error?:{code:string,message:string}` on abnormal close/status, with UI warning handling. The generic `incomplete` flag belongs to the host stream result, not remote status; the app-local terminal adapter maps it to its presentation warning. These diagnostics detect possible loss; they neither recover missing bytes nor guarantee lossless output, even with exit code 0 or EOF. See the [terminal UI contract](terminal.md) and chat-ai's authoritative terminal protocol for lifecycle and limitations.
143
+ Terminal is a separate human app, not an implicit capability of enabling files; the host does not add a separate terminal permission switch. It requires the existing current-chat MCP grant, staff terminal extension enablement, a loadable optional `node-pty` on Linux or Windows (build >= 18309), and negotiated streams/data v1 with a usable duplex dataSession over supported local stdio/Docker, direct HTTP or reverse topology. Its starting cwd is not an OS sandbox, and it runs under the staff process's operating-system identity. Terminal I/O is not added to model context or chat history. It uses the generic browser-host `/api/mcp/app-stream` WebSocket (`chat-app-stream-v1`) with rendering-consumption ACKs, a separate 120-second browser-presence deadline and server-returned remote lease (staff defaults to 30 seconds), not the file app's two-hour TTL. Only the browser host refreshes presence every 10 seconds; the generic stream module schedules remote renewal from the returned lease; opening the app starts a PTY once, without another open button or high-risk confirmation. Exit/failure leaves the app shell available for manual reconnect, never automatic replay. Backpressured process exit can have incomplete output: current source reports remote `status.error:{code:"OUTPUT_INCOMPLETE",message:string}`, and host generic stream-frame `incomplete?:boolean` / `error?:{code:string,message:string}` on abnormal close/status, with UI warning handling. The generic `incomplete` flag belongs to the host stream result, not remote status; the app-local terminal adapter maps it to its presentation warning. These diagnostics detect possible loss; they neither recover missing bytes nor guarantee lossless output, even with exit code 0 or EOF. See the [terminal UI contract](terminal.md) and chat-ai's authoritative terminal protocol for lifecycle and limitations.
144
144
 
145
145
  A configured optional file root that cannot initialize disables files with a stderr warning; it does not replace or widen the standard workspace tool roots. Invalid CLI syntax is still an error, and workspace/mount access errors still fail the relevant startup or file/tool operation rather than granting access. Availability and extension-version negotiation remain distinct from authorization.
146
146
 
package/docs/terminal.md CHANGED
@@ -1,18 +1,24 @@
1
1
  # Terminal app UI
2
2
 
3
- This document describes the current terminal extension, including unreleased runtime simplifications after 2.0.1; published release notes remain unchanged. Reverse and extensions require a matching chat-ai host implementing reverse v1 and session-relative data paths, with matching host/descriptors/UI assets. The authoritative generic stream contract is `chat-ai/docs/protocol/streams.md` at that compatible host version; `chat-ai/docs/protocol/terminal.md` defines only the PTY business adapter, safety boundaries and UI differences. No Chat8/schema9/format7/share protocol2 data migration is required. See [compatibility and upgrade](../README.md#compatibility-and-coordinated-upgrades).
3
+ This document describes the current terminal source contract. Windows native ConPTY and eligible Windows Docker Desktop Linux-container extension support are included in staff-mcp 2.0.4, not 2.0.3; the dependency pin and extension protocol versions are unchanged. Reverse and extensions require a matching chat-ai host implementing reverse v1 and session-relative data paths, with matching host/descriptors/UI assets. The authoritative generic stream contract is `chat-ai/docs/protocol/streams.md` at that compatible host version; `chat-ai/docs/protocol/terminal.md` defines only the PTY business adapter, safety boundaries and UI differences. No Chat8/schema9/format7/share protocol2 data migration is required. See [compatibility and upgrade](../README.md#compatibility-and-coordinated-upgrades).
4
4
 
5
- Requires Node.js 22.22.2 or newer on the host and in Docker. Linux and Linux-host local Docker Engine are the primary full-extension environments. Windows native standard MCP (stdio and HTTP) and Windows Docker standard MCP have been validated, not full extensions. Non-Linux Docker launchers disable optional extensions; macOS is untested. Unavailable or incompatible optional capabilities must not break an otherwise healthy standard MCP connection. The old reverse handshake itself is incompatible even with extensions disabled: upgrade both endpoints rather than relying on extension degradation. There is no old-protocol fallback or automatic terminal input replay.
5
+ Requires Node.js 22.22.2 or newer on the host and in Docker. Current source supports Linux PTY and Windows native ConPTY; Windows build >= 18309 is necessary but does not guarantee native loading or shell availability. Docker preflight checks the Linux-container daemon OS, not the launcher OS; HTTP/stdio also require a verified local Unix socket or named pipe (`npipe`) endpoint, allowing eligible Windows Docker Desktop Linux containers. Windows arm64 and macOS remain untested on real hardware; musl/Alpine terminal support is not promised. Optional discovery/data negotiation failures still preserve an otherwise healthy standard MCP connection; explicit terminal platform/native/shell startup errors do not degrade silently. The old reverse handshake itself is incompatible even with extensions disabled: upgrade both endpoints rather than relying on extension degradation. There is no old-protocol fallback or automatic terminal input replay.
6
6
 
7
- `terminal` is an independent, human-operated app enabled with `--extensions terminal` or `--extensions files,terminal`. It requires Linux, a loadable optional `node-pty`, an executable shell, and streams/data v1 with a usable duplex dataSession. All extensions are disabled by default; apps/data dependencies and terminal's streams v1 manifest are derived automatically. When Linux/native PTY/shell prerequisites are unavailable, staff warns on stderr and disables terminal/streams without failing standard MCP or an available files extension; the default disabled state does not load native PTY code. Non-Linux Docker launchers disable optional extensions before starting the container; standard MCP tools/resources/prompts remain available when the base connection is usable. Local stdio/Docker, direct HTTP and reverse share that public raw HTTP data protocol; standard MCP control transports remain unchanged. The host uses the existing current-chat MCP grant and same-origin browser requests, without a separate terminal permission switch or high-risk confirmation. HTTP/HTTPS follows the site-wide deployment policy, with no terminal-only TLS gate or origin allowlist. HTTPS is recommended for the whole site; HTTP does not encrypt login sessions, tool calls or terminal traffic. Reverse resolves the host-provided current-session data path against the existing `--ru` origin; chat-ai does not need a public URL setting. Upgrade both endpoints together; HTTP/stdio addresses and extension versions remain unchanged. Topology and CLI details are in the [README](../README.md). The self-contained HTML Resource is built to `dist/src/terminal/ui/index.html`; terminal bytes do not add model tools, chat messages or chat history.
7
+ `terminal` is an independent, human-operated app enabled with `--extensions terminal` or `--extensions files,terminal`. It requires Linux or Windows (build >= 18309), a loadable optional `node-pty`, an executable shell, and streams/data v1 with a usable duplex dataSession. All extensions are disabled by default; apps/data dependencies and terminal's streams v1 manifest are derived automatically. When platform/native PTY/shell prerequisites are unavailable, an explicit terminal request fails startup with an error, even when files is also requested; the default disabled state does not load native PTY code. A non-Linux container daemon, unverified/nonlocal HTTP/stdio daemon endpoint or unsupported stdio Docker data topology likewise fails explicit terminal requests rather than silently dropping them. Files-only degradation is unchanged. HTTP/reverse avoid the extra stdio data-port mapping. HTTP retains local-daemon/reachable-loopback checks; reverse still requires Linux containers and valid existing mounts. Local stdio/Docker, direct HTTP and reverse share that public raw HTTP data protocol; standard MCP control transports remain unchanged. The host uses the existing current-chat MCP grant and same-origin browser requests, without a separate terminal permission switch or high-risk confirmation. HTTP/HTTPS follows the site-wide deployment policy, with no terminal-only TLS gate or origin allowlist. HTTPS is recommended for the whole site; HTTP does not encrypt login sessions, tool calls or terminal traffic. Reverse resolves the host-provided current-session data path against the existing `--ru` origin; chat-ai does not need a public URL setting. Upgrade both endpoints together; HTTP/stdio addresses and extension versions remain unchanged. Topology and CLI details are in the [README](../README.md). The self-contained HTML Resource is built to `dist/src/terminal/ui/index.html`; terminal bytes do not add model tools, chat messages or chat history.
8
+
9
+ ## Native dependency delivery
10
+
11
+ The optional dependency remains pinned exactly to the official prerelease `node-pty@1.2.0-beta.18`, including Linux x64/arm64 N-API prebuilds for glibc >= 2.28 and Windows x64/arm64 ConPTY prebuilds. A shipped architecture build is not hardware validation: Windows arm64 and macOS are untested. Windows requires build >= 18309, compatible native binaries and system dependencies; there is no winpty fallback. Linux still requires system libraries such as `libstdc++` and `libgcc`; both platforms require an executable shell. No user image is upgraded automatically; musl/Alpine terminal support is not promised (Alpine examples without terminal remain standard MCP examples).
12
+
13
+ Docker still mounts the host package and `node_modules` read-only. This fixes prebuilt delivery for normal installs, not complete container dependency isolation: local build leftovers and architecture/platform/libc mismatches remain limitations. N-API does not remove system-library or platform requirements.
8
14
 
9
15
  ## Opening and stopping
10
16
 
11
- A valid absolute executable `$SHELL` is selected automatically, otherwise `/bin/bash`. If that executable or node-pty is unavailable, terminal is disabled with a warning; there is no further shell fallback or shell-selection parameter. `--shell` is removed and fails as an unknown option. The shell starts with `-i`, honors normal user startup files and preserves normal HOME, PATH, virtual environments and other staff environment variables. [`src/terminal/pty.ts`](../src/terminal/pty.ts) filters only these exact internal control keys: `STAFF_GLOBAL_DIR`, `STAFF_MCP_IS_DOCKER`, `STAFF_MCP_DATA_BOOTSTRAP`, `STAFF_MCP_DATA_HOST`, `STAFF_MCP_DATA_PORT`, `MCP_REVERSE_URL`, `MCP_REVERSE_TOKEN`, `MCP_REVERSE_NAME`, `MCP_HTTP_TOKEN`, `STAFF_MCP_HTTP_TOKEN`, `STAFF_MCP_REVERSE_TOKEN`. Missing `TERM` becomes `xterm-256color`, and `SHELL` is set to the selected executable. This is not a general secret scrubber or environment sandbox; the same OS identity may still access credentials and other files.
17
+ On Linux, a valid absolute executable `$SHELL` is selected automatically, otherwise `/bin/bash`. It starts with `-i`; normal profiles/startup files and HOME behavior are unchanged, with no further shell fallback if unavailable. On Windows, executable `pwsh.exe` is preferred, then `powershell.exe` (including the system installation), using `-NoLogo -NoProfile`; fallback is `ComSpec`/system `cmd.exe` with `/d` to disable CMD AutoRun. Candidates must pass an executable check; Windows does not use `$SHELL` to select the shell. Missing shell or node-pty fails explicit terminal startup. There is no public shell-selection parameter: `--shell` is removed and fails as an unknown option. PATH, virtual environments and other staff environment variables are preserved. [`src/terminal/pty.ts`](../src/terminal/pty.ts) filters only these exact internal control keys: `STAFF_GLOBAL_DIR`, `STAFF_MCP_IS_DOCKER`, `STAFF_MCP_DATA_BOOTSTRAP`, `STAFF_MCP_DATA_HOST`, `STAFF_MCP_DATA_PORT`, `MCP_REVERSE_URL`, `MCP_REVERSE_TOKEN`, `MCP_REVERSE_NAME`, `MCP_HTTP_TOKEN`, `STAFF_MCP_HTTP_TOKEN`, `STAFF_MCP_REVERSE_TOKEN`. Missing `TERM` becomes `xterm-256color`, and `SHELL` is set to the selected executable. This is not a general secret scrubber or environment sandbox; the same OS identity may still access credentials and other files.
12
18
 
13
- Selecting the Shell App automatically starts one PTY after the host bridge becomes usable and the visible xterm viewport has been measured with its fonts ready; there is no additional open button or high-risk confirmation. The initial PTY uses those fitted columns and rows rather than starting at 80×24 and resizing after the first prompt. Hidden, zero-sized or not-yet-measurable views wait for a usable layout. The toolbar reserves its control height before connecting, so showing the buttons does not invalidate the initial row measurement; subsequent viewport changes continue through the normal resize path. The toolbar shows the returned shell and starting path. The PTY defaults to staff's workspace `main`, independently of file-app roots, and inherits staff's environment and OS identity, not a separate browser-user identity; its cwd is not an operating-system sandbox. Shell startup configuration and history are not suppressed, so the remote shell or programs may record content even though chat-ai does not add terminal bytes to chat history.
19
+ Selecting the Shell App automatically starts one PTY after the host bridge becomes usable and the visible xterm viewport has been measured with its fonts ready; there is no additional open button or high-risk confirmation. The initial PTY uses those fitted columns and rows rather than starting at 80×24 and resizing after the first prompt. Hidden, zero-sized or not-yet-measurable views wait for a usable layout. The toolbar reserves its control height before connecting, so showing the buttons does not invalidate the initial row measurement; subsequent viewport changes continue through the normal resize path. The toolbar shows the returned shell and starting path. The PTY defaults to staff's workspace `main`, independently of file-app roots, and inherits staff's environment and OS identity, not a separate browser-user identity; its cwd is not an operating-system sandbox. Linux startup profiles remain normal; Windows PowerShell profile loading/CMD AutoRun are disabled as above. This is not a guarantee that shell, programs or the OS never record history, even though chat-ai does not add terminal bytes to chat history.
14
20
 
15
- **清屏** clears only the local terminal display and scrollback; it sends no shell command. Closing the terminal disables input immediately and requests remote cleanup. Closing cannot undo filesystem/network effects and does not guarantee every descendant process has ended. Normal server/session shutdown waits for the owned PTY exit, including the existing TERM-to-KILL escalation, before CLI exit; this does not change normal output/ACK draining or promise cleanup after SIGKILL. Input, including Ctrl-C and pasted text, goes to the PTY in order; uncertain acknowledgements are never replayed. Normal exit or PTY failure stops the current PTY but preserves the app shell for manual reconnect, not automatic restart.
21
+ **清屏** clears only the local terminal display and scrollback; it sends no shell command. Closing the terminal disables input immediately and requests remote cleanup. Closing cannot undo filesystem/network effects and does not guarantee every descendant process has ended. Normal server/session shutdown waits for owned PTY cleanup before CLI exit. Linux retains TERM-to-KILL escalation; Windows closes the owned ConPTY console on a best-effort basis, without promising cleanup of every detached descendant. Neither rolls back filesystem/network effects. This does not change normal output/ACK draining or promise cleanup after forced process termination. Input, including Ctrl-C and pasted text, goes to the PTY in order; uncertain acknowledgements are never replayed. Normal exit or PTY failure stops the current PTY but preserves the app shell for manual reconnect, not automatic restart.
16
22
 
17
23
  Hiding the browser page or switching/collapsing app views within the same chat keeps the existing App and PTY. Visibility gates new opening, input and resize requests, not instance identity: already-admitted input, output reads and xterm consumption acknowledgements continue. Returning fits the viewport and enables input on that same PTY, without opening another shell. Genuine host lifecycle/permission loss, chat changes, explicit close, non-BFCache page exit and unmount still fence the instance, discard unsent input and request best-effort cleanup. An actually stopped or failed PTY requires manual reconnect; visibility restoration does not recreate it. Temporary settings loading or catalog-request errors are not confirmed revocation/disconnection. Real lease expiry, grant revocation or connection retirement still fences the PTY. Failed cleanup relies on host cleanup and the remote lease; a disconnected page cannot guarantee that its close request arrived. A pending open may return its terminal ID after the local instance was invalidated, so the host must fence and clean late creation results.
18
24
 
@@ -28,7 +34,7 @@ The app-local [`stream-adapter.ts`](../src/terminal/ui/stream-adapter.ts) passes
28
34
 
29
35
  node-pty can lose tail output when exit races paused reads. Staff reports detected risk as `error:{code:"OUTPUT_INCOMPLETE",message}`. The UI adapter maps generic ended to its local exited state, metadata.exitCode to the exit display and incomplete to **输出可能不完整**; read rejection displays **输出完整性无法确认**. The warning persists through later lifecycle changes, including exit code 0, and preserves displayed content. These local names are not bridge fields; diagnostics cannot recover lost bytes or guarantee completeness, and absent warnings/EOF/exit 0 do not prove complete history.
30
36
 
31
- Input requests are sequential and small inputs are coalesced within bounded pending storage, each request at most 32 KiB UTF-8 with code-point-safe splitting. Pending UI input including the in-flight request is bounded at 256 KiB; overflow stops the instance instead of silently dropping/replaying input. Backend deliveries can be 64 KiB; staff splits them into ordered, awaited fd writes of at most 32 KiB without decoding arbitrary byte boundaries. Input consumption ACK follows complete fd writes; output ACK follows actual xterm rendering, never fetch/socket enqueue. The common 256 KiB sliding ACK window permits multiple backend blocks in flight, not per-block stop-and-wait; final EOF awaits receiver.end and its ACK, while interruption fails visibly and releases blocked work. Input acknowledgement does not prove command execution.
37
+ Input requests are sequential and small inputs are coalesced within bounded pending storage, each request at most 32 KiB UTF-8 with code-point-safe splitting. Pending UI input including the in-flight request is bounded at 256 KiB; overflow stops the instance instead of silently dropping/replaying input. Backend deliveries can be 64 KiB; staff splits them into ordered, awaited input writes of at most 32 KiB. Linux retains raw-byte fd writes with EAGAIN handling, without UTF-8 decoding. Windows targets the ConPTY UTF-8 input pipe with one bounded write in flight; input ACK follows the pipe write callback, not mere JavaScript enqueue or locally retained bytes. Data v1 stays raw binary, host cursors/ACKs count raw bytes and the generic host does not decode UTF-8. Linux input ACK follows complete fd writes; output ACK follows actual xterm rendering, never fetch/socket enqueue. The common 256 KiB sliding ACK window permits multiple backend blocks in flight, not per-block stop-and-wait; final EOF awaits receiver.end and its ACK, while interruption fails visibly and releases blocked work. Input acknowledgement does not prove command execution.
32
38
 
33
39
  Presence and lease scheduling belong to the generic host stream contract, not an iframe timer. Staff retains its 30-second default remote lease. Hidden views keep output consumption active; BFCache/freeze does not guarantee indefinite PTY survival after presence or pending-consumption deadlines expire. PTY exit/draining is distinct from revocation or expiry; the UI retains read/ACK until the final frame rather than treating normal exit as loss of authorization.
34
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "staff-mcp",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/ChineseAStar/staff-mcp.git"
@@ -66,6 +66,6 @@
66
66
  "node": ">=22.22.2"
67
67
  },
68
68
  "optionalDependencies": {
69
- "node-pty": "1.1.0"
69
+ "node-pty": "1.2.0-beta.18"
70
70
  }
71
71
  }