mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 08:35:57 +00:00
fix(pi-ssh): harden remote execution and search
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
Pi and its default tools remain local. Explicit collision-free tools perform selected operations on one configured remote server:
|
||||
|
||||
- `ssh_connect`
|
||||
- `ssh_cd`
|
||||
- `ssh_read`
|
||||
- `ssh_write`
|
||||
- `ssh_edit`
|
||||
@@ -33,7 +34,7 @@ The resulting host ID is the only runtime selector. When a direct user request n
|
||||
ssh_connect({ hostId: "<host-id>", remotePath?: "/absolute/or/~/path" })
|
||||
```
|
||||
|
||||
`ssh_connect` is the only runtime connection surface. It is a model tool governed by `pi-permission-system`; there is no `/ssh` command, `--ssh` flag, session-resume reconnect, or user `!` remote-shell override.
|
||||
`ssh_connect` is the only runtime connection surface. It is a sequential, cancellable model tool governed by `pi-permission-system`: the agent calls it as a separate step and waits for success before dependent remote tools, so establishing or replacing a connection cannot overlap another tool call. Unknown IDs return at most ten sorted imported IDs and never endpoint credentials. There is no `/ssh` command, `--ssh` flag, session-resume reconnect, or user `!` remote-shell override.
|
||||
|
||||
Arbitrary `user@host`, port overrides, ProxyJump, and ProxyCommand are not supported in the first pure-ssh2 version. Unsupported imported configuration is rejected rather than ignored.
|
||||
|
||||
@@ -69,11 +70,13 @@ Import displays the observed host-key algorithm and SHA256 fingerprint for expli
|
||||
|
||||
## Transport
|
||||
|
||||
One persistent `ssh2.Client` belongs to the active host. Connection loss fails closed and no operation is automatically replayed.
|
||||
One persistent `ssh2.Client` belongs to the active host. The transport persists, but there is no persistent interactive shell or PTY. Connection loss fails closed and no operation is automatically replayed.
|
||||
|
||||
### Shell
|
||||
|
||||
`ssh_bash` opens exec channels. Commands run through `bash -lc` after changing to the selected remote cwd. Output streams through the normal Pi Bash operations callback. Abort or timeout closes the channel without reconnecting or replaying.
|
||||
`ssh_bash` opens a fresh exec channel and non-interactive Bash process for every call. Commands run through `bash -lc` after changing to the active remote cwd. The cwd supplied by Pi's local Bash factory is ignored at the transport adapter boundary; only connection state may select the remote cwd. A command-local `cd` is intentionally temporary; shell-local `cd`, exports, aliases, functions, and other process state do not persist across calls. Output streams through the normal Pi Bash operations callback. Abort or timeout closes the channel without reconnecting or replaying.
|
||||
|
||||
`ssh_cd` is the explicit persistent workspace operation and declares Pi's sequential execution mode so it cannot overlap sibling tool calls. It resolves absolute paths, paths relative to the active remote cwd, and `~/` paths relative to remote HOME; validates the directory by executing `pwd` from it; and updates connection state without reconnecting. The model calls it as a separate step and waits for success before issuing subsequent relative file/search operations or `ssh_bash` calls that depend on the updated cwd.
|
||||
|
||||
### Files
|
||||
|
||||
@@ -92,10 +95,13 @@ Remote paths map from Pi's local factory cwd into the selected remote cwd, but p
|
||||
Search tools execute one capability-adaptive, bounded shell pipeline inside the already approved tool call. They never install or upload binaries.
|
||||
|
||||
- `ssh_find`: `fd` → `fdfind` → `git ls-files` → `find`; fixed filename/path substring semantics.
|
||||
- `ssh_grep`: `rg` → `git grep` → `find -exec grep`; literal case-insensitive semantics by default.
|
||||
- each backend emits at most `limit + 1` lines so truncation is explicit; public `limit` is 1–200; each returned line is capped.
|
||||
- relative paths resolve against remote cwd and `~/` against remote home.
|
||||
- `ssh_grep`: `rg` → `git grep` → `find + grep`; literal case-insensitive semantics by default, optional hidden-path inclusion, basename-only include globs, and a portable POSIX ERE subset when literal mode is disabled.
|
||||
- each backend emits at most `limit + 1` NUL-delimited path/line/content records so truncation is explicit and newline filenames remain one result; public `limit` is 1–200; each returned line is capped.
|
||||
- relative paths resolve against remote cwd and `~/` against remote home; other `~user` forms are rejected.
|
||||
- the search target root is passed to the backend as an absolute argument, while the search process executes from the active remote cwd; a single-file `ssh_grep` target is never used as a process cwd.
|
||||
- searches time out after 30 seconds with the resolved root and explicit guidance to narrow it before retrying.
|
||||
- user strings are single-quoted as shell arguments and NUL/newline input is rejected.
|
||||
- backend stdout contains only parseable results; stderr is captured independently for warnings and failure diagnostics.
|
||||
- capability detection occurs only within the reviewed search call.
|
||||
- search output is normalized by `pi-ssh` and excluded from RTK compaction.
|
||||
|
||||
@@ -106,7 +112,7 @@ Direct search commands remain denied through `ssh_bash`; structured search tools
|
||||
There is one permission gate: `pi-permission-system`.
|
||||
|
||||
- `ssh_connect` defaults to `ask`; its preview resolves the imported host ID to the non-secret endpoint, port, and requested/default cwd before connection.
|
||||
- `ssh_read`, `ssh_write`, `ssh_edit`, `ssh_find`, and `ssh_grep` default to `ask`.
|
||||
- `ssh_cd`, `ssh_read`, `ssh_write`, `ssh_edit`, `ssh_find`, and `ssh_grep` default to `ask`; remote path extractors disable local path normalization for all six tools, while previews resolve relative and `~/` requests against the active remote cwd/HOME and display both requested and absolute paths.
|
||||
- `ssh_bash` is a Bash-semantic `shellTools` alias with `decisionFloor: "ask"`.
|
||||
- Bash hard denies remain denies.
|
||||
- All asks enter the configured authorizer chain.
|
||||
@@ -114,8 +120,10 @@ There is one permission gate: `pi-permission-system`.
|
||||
|
||||
Evidence includes configured host ID, endpoint, port, remote cwd, and a bounded operation summary, never credentials.
|
||||
|
||||
Connection HOME/cwd discovery and `ssh_cd` validation use a bounded random-marker probe over a cancellable exec channel. The parser accepts exactly one framed absolute POSIX path; startup banners, malformed/multiline values, overflow, timeout, or cancellation cannot update connection state. Independent exec operations use at most four concurrent SSH channels, while SFTP operations remain serialized.
|
||||
|
||||
## Session lifecycle
|
||||
|
||||
Connections are created only by an approved `ssh_connect` call after session start. They are not persisted or automatically resumed. Connecting another imported host disposes the previous client, and session shutdown disposes the active client.
|
||||
|
||||
The system prompt states that default tools are local and `ssh_*` tools are remote after a connection becomes active. It does not include remote file content.
|
||||
The system prompt states that default tools are local, `ssh_*` tools are remote, and each `ssh_bash` call starts a fresh non-interactive shell after a connection becomes active. It directs persistent workspace changes through `ssh_cd` and does not include remote file content.
|
||||
|
||||
Reference in New Issue
Block a user