pi-ssh-remote 0.1.11 → 0.1.12

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.
package/CHANGELOG.md CHANGED
@@ -18,6 +18,20 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Rel
18
18
 
19
19
  - None.
20
20
 
21
+ ## [0.1.12] - 2026-08-25
22
+
23
+ ### Added
24
+
25
+ - None.
26
+
27
+ ### Changed
28
+
29
+ - Simplified the server-memory documentation to focus on adding, listing, updating, and deleting entries without exposing implementation details.
30
+
31
+ ### Fixed
32
+
33
+ - Prevented follow-up SSH client errors during a connection loss before handshake from becoming an uncaught exception that exits Pi.
34
+
21
35
  ## [0.1.11] - 2026-08-16
22
36
 
23
37
  ### Added
@@ -206,7 +220,8 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Rel
206
220
 
207
221
  - None.
208
222
 
209
- [Unreleased]: https://github.com/petrichor20211/pi-ssh-remote/compare/v0.1.11...HEAD
223
+ [Unreleased]: https://github.com/petrichor20211/pi-ssh-remote/compare/v0.1.12...HEAD
224
+ [0.1.12]: https://github.com/petrichor20211/pi-ssh-remote/compare/v0.1.11...v0.1.12
210
225
  [0.1.11]: https://github.com/petrichor20211/pi-ssh-remote/compare/v0.1.10...v0.1.11
211
226
  [0.1.10]: https://github.com/petrichor20211/pi-ssh-remote/compare/v0.1.9...v0.1.10
212
227
  [0.1.9]: https://github.com/petrichor20211/pi-ssh-remote/compare/v0.1.8...v0.1.9
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
@@ -31,7 +31,7 @@ The extension exposes `remote` for the agent and `/remote` for the user. You can
31
31
 
32
32
  ### Stateful endpoints instead of disposable SSH commands
33
33
 
34
- Each `user@host:port` endpoint remembers its remote working directory, note, and port-forward configuration locally. Server memory is a per-`user@host` JSON file containing stable `{ "id", "content" }` entries, so another SSH port for the same user and host uses the same entries. Pi is told the exact local file path and can use its normal `read`, `edit`, and `write` tools for entry-level CRUD even while other tools are routed remotely. Notes such as `H100 training`, `staging`, or `customer demo` appear in configuration, status messages, and Pi's footer, so the active execution environment stays visible. Valid server-memory entries are automatically injected into the model context whenever a matching endpoint is connected as the active remote workspace.
34
+ Each `user@host:port` endpoint remembers its remote working directory, note, and port-forward configuration locally. Notes such as `H100 training`, `staging`, or `customer demo` appear in configuration, status messages, and Pi's footer, so the active execution environment stays visible.
35
35
 
36
36
  ### Resilient and bounded by default
37
37
 
@@ -67,8 +67,6 @@ Requires Node.js 20+. The remote server must provide Bash, SFTP, and GNU `timeou
67
67
  /remote cd /srv/project
68
68
  /remote config note H100 training server
69
69
  /remote status
70
-
71
- You: Add a server-memory entry saying to use /opt/conda/bin/python and never stop shared jobs.
72
70
  ```
73
71
 
74
72
  From this point, normal Pi operations target `/srv/project` on the remote server. The footer makes that routing explicit:
@@ -83,6 +81,29 @@ Return to local tools with:
83
81
  /remote off
84
82
  ```
85
83
 
84
+ ### Server memory
85
+
86
+ Tell Pi what to remember for the current server:
87
+
88
+ ```text
89
+ Remember for this server: use /opt/conda/bin/python and never stop shared jobs.
90
+ ```
91
+
92
+ List saved entries and their IDs:
93
+
94
+ ```text
95
+ /remote memory
96
+ ```
97
+
98
+ Use an ID to update or delete an entry:
99
+
100
+ ```text
101
+ Update memory deploy-command to use /opt/deploy/v2/run.sh.
102
+ Delete memory obsolete-proxy-rule.
103
+ ```
104
+
105
+ Pi automatically applies saved memory when you work on that server. Deletion only happens when you explicitly request it.
106
+
86
107
  ### Private key authentication
87
108
 
88
109
  Pass an explicit local private key with `-i`:
@@ -132,7 +153,7 @@ The default foreground timeout prevents an accidental long-running command from
132
153
  /remote
133
154
  ```
134
155
 
135
- Endpoint notes and working directories survive Pi restarts in the local remote configuration. `user@host`-specific memory survives in a separate local JSON file under `~/.pi/agent/ssh-remote-memories/`; each entry has a stable `id` and `content`. When Pi connects to an endpoint, valid entries matching its user and host are added to the model context on every agent run while remote tool routing remains active; the SSH port does not affect memory selection. Disconnecting or switching to tunnel-only mode removes them from subsequent model requests.
156
+ Endpoint notes and working directories survive Pi restarts and remain separate for each saved endpoint.
136
157
 
137
158
  ### 4. Expose a remote service while editing locally
138
159
 
@@ -165,25 +186,6 @@ Forward the remote service on port 8000 to localhost:8000, but keep my coding
165
186
  tools on the local repository.
166
187
  ```
167
188
 
168
- ```text
169
- Add a server-memory entry that says deployments must use /opt/deploy/run.sh.
170
- ```
171
-
172
- List the current server's entries and IDs before referring to one:
173
-
174
- ```text
175
- /remote memory
176
- ```
177
-
178
- Then update or delete by the displayed ID:
179
-
180
- ```text
181
- Update the entry with ID deploy-command to use /opt/deploy/v2/run.sh.
182
- Delete the server-memory entry with ID obsolete-proxy-rule.
183
- ```
184
-
185
- These requests are handled through the agent-facing `remote` tool; slash commands are optional. The `memory` action locates and inspects the matching JSON file, while Pi's normal `read`, `edit`, and `write` tools perform entry-level add, query, update, and delete operations. The injected instructions make deletion deliberately strict: Pi must first read the file, identify the exact entry ID, and delete only that object—and only after the user explicitly asks to delete, remove, or forget memory. Ambiguous targets require clarification, update requests do not imply deletion, and deleting all entries requires an explicit request to delete all server memory.
186
-
187
189
  ## Command reference
188
190
 
189
191
  | Command | Purpose |
@@ -194,7 +196,7 @@ These requests are handled through the agent-facing `remote` tool; slash command
194
196
  | `/remote use USER@HOST:PORT` | Select a saved endpoint |
195
197
  | `/remote config note TEXT` | Persist a note for the selected endpoint |
196
198
  | `/remote config note --clear` | Clear its note |
197
- | `/remote memory` | List the current server's memory entries, IDs, and JSON file path |
199
+ | `/remote memory` | List the current server's memory entries and IDs |
198
200
  | `/remote config cwd PATH` | Persist its default remote working directory |
199
201
  | `/remote cd PATH` | Change the connected remote cwd and persist it |
200
202
  | `/remote config forward MAPPING...` | Persist port forwards such as `7860:127.0.0.1:7860` |
@@ -222,7 +224,7 @@ Endpoint configuration is stored locally in:
222
224
  ~/.pi/agent/ssh-remote-config.json
223
225
  ```
224
226
 
225
- Saved global values include endpoints, active endpoint, notes, remote working directories, forwards, identity file paths, preview settings, and model-output budgets. Server-memory entries are stored separately under `~/.pi/agent/ssh-remote-memories/` as `{ "server", "entries": [{ "id", "content" }] }`; legacy string memories are migrated automatically. Each Pi session also stores non-secret SSH workspace metadata so `/resume` can restore the server associated with that session. Server memory is user-configured trusted context and is inserted into each model request only while a matching endpoint is the active remote workspace; it is not read from the remote server. The current server's exact memory path is the only local path that the routed `read`, `edit`, and `write` tools special-case. Private key contents, passwords, and key passphrases are **never written to these files**. Private keys are read locally only when connecting; prompted passwords and passphrases remain only in process memory.
227
+ Saved global values include endpoints, active endpoint, notes, remote working directories, forwards, identity file paths, preview settings, and model-output budgets. Each Pi session also stores non-secret SSH workspace metadata so `/resume` can restore the server associated with that session. Private key contents, passwords, and key passphrases are **never written to this file**. Private keys are read locally only when connecting; prompted passwords and passphrases remain only in process memory.
226
228
 
227
229
  New or changed host keys require interactive confirmation and are stored separately from OpenSSH. By default, remote text reads return at most 400 lines or 16 KB, remote command results return the last 200 lines or 8 KB, and all remote tools in one agent turn share a 32 KB output budget. Text reads support `offset`/`limit` continuation without downloading the complete remote file. Oversized command output is streamed to a permission-restricted temporary local file rather than accumulated in memory. Configured limits may be raised only to the extension's hard safety ceilings. Preview-line settings affect only the collapsed UI and never increase model output.
228
230
 
@@ -232,13 +234,13 @@ The extension currently supports direct SSH commands with `-p`, `-l`, and `-i`.
232
234
 
233
235
  ## Releases
234
236
 
235
- Latest release: [v0.1.11](https://github.com/petrichor20211/pi-ssh-remote/releases/tag/v0.1.11)
237
+ Latest release: [v0.1.12](https://github.com/petrichor20211/pi-ssh-remote/releases/tag/v0.1.12)
236
238
 
237
239
  | Version | Date | Highlights |
238
240
  |---|---|---|
241
+ | [0.1.12](CHANGELOG.md#0112---2026-08-25) | 2026-08-25 | Safe handling of repeated SSH errors when a connection is lost during handshake |
239
242
  | [0.1.11](CHANGELOG.md#0111---2026-08-16) | 2026-08-16 | JSON memory entries, prompt-guided CRUD, and `/remote memory` listing |
240
243
  | [0.1.10](CHANGELOG.md#0110---2026-08-16) | 2026-08-16 | Safe inspect-by-default and append-only agent updates for server memory |
241
- | [0.1.9](CHANGELOG.md#019---2026-08-12) | 2026-08-12 | Stable deduplicated server-memory context and shorter footer labels |
242
244
 
243
245
  See [CHANGELOG.md](CHANGELOG.md) for the complete release history, including additions, behavior changes, and bug fixes.
244
246
 
package/README.zh-CN.md CHANGED
@@ -54,7 +54,7 @@ H100 训练机 (root@gpu-box.example.com:2202):/srv/project
54
54
  - 服务器特定记忆;
55
55
  - 端口转发配置。
56
56
 
57
- 例如可以把几台机器分别备注为 `8xH100 训练机`、`预发布环境`、`线上只读机`。服务器记忆按 `user@host` 保存为 JSON 文件,每条记忆都是稳定的 `{ "id", "content" }` 对象;同一用户和主机即使通过不同 SSH 端口连接,也会使用同一组条目。插件会把精确的本地文件路径告诉 Pi,因此即使其他工具已路由到远端,Pi 仍能用普通 `read`、`edit`、`write` 工具对记忆条目增删查改。连接匹配的 endpoint 并启用远端工具路由后,有效条目会自动注入模型上下文;断开连接或切换到纯隧道模式后,后续请求不再注入。所有配置保存在本地,重启 Pi 后仍然存在。
57
+ 例如可以把几台机器分别备注为 `8xH100 训练机`、`预发布环境`、`线上只读机`。这些配置保存在本地,重启 Pi 后仍然存在。
58
58
 
59
59
  ### 断线后可以自动恢复
60
60
 
@@ -109,12 +109,6 @@ pi install npm:pi-ssh-remote
109
109
  /remote config note H100 训练机
110
110
  ```
111
111
 
112
- 然后直接告诉 Pi:
113
-
114
- ```text
115
- 添加一条服务器记忆:使用 /opt/conda/bin/python,不要停止其他用户的共享任务。
116
- ```
117
-
118
112
  查看当前状态:
119
113
 
120
114
  ```text
@@ -129,6 +123,29 @@ pi install npm:pi-ssh-remote
129
123
  /remote off
130
124
  ```
131
125
 
126
+ ### 服务器记忆
127
+
128
+ 直接告诉 Pi 要为当前服务器记住什么:
129
+
130
+ ```text
131
+ 记住这台服务器使用 /opt/conda/bin/python,不要停止共享任务。
132
+ ```
133
+
134
+ 查看已有记忆和 ID:
135
+
136
+ ```text
137
+ /remote memory
138
+ ```
139
+
140
+ 通过 ID 修改或删除:
141
+
142
+ ```text
143
+ 把记忆 deploy-command 改为使用 /opt/deploy/v2/run.sh。
144
+ 删除记忆 obsolete-proxy-rule。
145
+ ```
146
+
147
+ 以后连接这台服务器时,Pi 会自动使用这些记忆。只有明确要求删除时才会删除。
148
+
132
149
  ### 使用私钥文件登录
133
150
 
134
151
  通过 `-i` 指定本地私钥:
@@ -188,7 +205,7 @@ pi install npm:pi-ssh-remote
188
205
  /remote
189
206
  ```
190
207
 
191
- 备注和默认目录会按 `user@host:port` 分别保存,不会互相覆盖;服务器记忆则按 `user@host` 保存为独立 JSON 文件并跨端口共享。
208
+ 备注和默认目录会按 `user@host:port` 分别保存,不会互相覆盖。
192
209
 
193
210
  ### 4. 远端启动模型,本地开发界面
194
211
 
@@ -223,25 +240,6 @@ pi install npm:pi-ssh-remote
223
240
  把远端 8000 端口转发到本地 8000,但代码工具继续留在本地。
224
241
  ```
225
242
 
226
- ```text
227
- 添加一条服务器记忆:部署必须使用 /opt/deploy/run.sh。
228
- ```
229
-
230
- 更新或删除前,可以先展示当前服务器的全部记忆和 ID:
231
-
232
- ```text
233
- /remote memory
234
- ```
235
-
236
- 然后使用展示出的 ID:
237
-
238
- ```text
239
- 把 ID 为 deploy-command 的记忆更新为使用 /opt/deploy/v2/run.sh。
240
- 删除 ID 为 obsolete-proxy-rule 的服务器记忆。
241
- ```
242
-
243
- Pi 会通过插件提供的 `remote` 工具完成这些操作。`memory` action 只负责定位和查看匹配的 JSON 文件,实际增删查改使用 Pi 自带的 `read`、`edit`、`write`。删除规则会明确注入给 Agent:只有用户明确要求“删除/移除/忘记”服务器记忆时,Pi 才能先读取文件、确认准确条目 ID,再只删除该对象;目标不明确时必须询问,修改请求不等于删除授权,删除全部条目也必须由用户明确提出。
244
-
245
243
  ## 命令说明
246
244
 
247
245
  | 命令 | 作用 |
@@ -252,7 +250,7 @@ Pi 会通过插件提供的 `remote` 工具完成这些操作。`memory` action
252
250
  | `/remote use USER@HOST:PORT` | 切换到指定服务器 |
253
251
  | `/remote config note TEXT` | 给当前服务器添加或修改备注 |
254
252
  | `/remote config note --clear` | 清除当前服务器备注 |
255
- | `/remote memory` | 展示当前服务器的全部记忆条目、ID 和 JSON 文件路径 |
253
+ | `/remote memory` | 展示当前服务器的记忆条目和 ID |
256
254
  | `/remote config cwd PATH` | 设置默认远程工作目录 |
257
255
  | `/remote cd PATH` | 切换当前远程目录并保存 |
258
256
  | `/remote config forward MAPPING...` | 保存端口转发配置,例如 `7860:127.0.0.1:7860` |
@@ -291,15 +289,9 @@ Pi 会通过插件提供的 `remote` 工具完成这些操作。`memory` action
291
289
  - 命令预览设置;
292
290
  - 模型输出预算。
293
291
 
294
- 服务器记忆单独保存在:
295
-
296
- ```text
297
- ~/.pi/agent/ssh-remote-memories/
298
- ```
299
-
300
- 文件结构为 `{ "server", "entries": [{ "id", "content" }] }`,旧版字符串记忆会自动迁移为 JSON 条目。此外,每个 Pi session 都会记录不含凭据的 SSH 工作区元数据,用于在 `/resume` 时恢复该历史 session 对应的服务器环境。服务器记忆按 `user@host` 识别,不受 SSH 端口影响。它是由用户在本地配置的可信上下文,不会从远程服务器自动读取;仅当匹配的 endpoint 作为远端工作区启用时才会加入每次模型请求。远端路由启用时,只有当前服务器对应的精确记忆文件路径会被 `read`、`edit`、`write` 特殊处理为本地文件。
292
+ 此外,每个 Pi session 都会记录不含凭据的 SSH 工作区元数据,用于在 `/resume` 时恢复该历史 session 对应的服务器环境。
301
293
 
302
- 私钥内容、密码和密钥 passphrase 都不会写入这些配置文件。插件仅在连接时从本地读取私钥;手动输入的密码和 passphrase 只会缓存在当前 Pi 进程的内存中。
294
+ 私钥内容、密码和密钥 passphrase 都不会写入配置文件。插件仅在连接时从本地读取私钥;手动输入的密码和 passphrase 只会缓存在当前 Pi 进程的内存中。
303
295
 
304
296
  ## 安全与输出限制
305
297
 
@@ -320,13 +312,13 @@ Pi 会通过插件提供的 `remote` 工具完成这些操作。`memory` action
320
312
 
321
313
  ## 版本发布
322
314
 
323
- 最新版本:[v0.1.11](https://github.com/petrichor20211/pi-ssh-remote/releases/tag/v0.1.11)
315
+ 最新版本:[v0.1.12](https://github.com/petrichor20211/pi-ssh-remote/releases/tag/v0.1.12)
324
316
 
325
317
  | 版本 | 日期 | 主要内容 |
326
318
  |---|---|---|
319
+ | [0.1.12](CHANGELOG.md#0112---2026-08-25) | 2026-08-25 | 安全处理 SSH 握手期间断线所触发的连续错误 |
327
320
  | [0.1.11](CHANGELOG.md#0111---2026-08-16) | 2026-08-16 | JSON 记忆条目、Prompt 引导增删查改与 `/remote memory` 展示命令 |
328
321
  | [0.1.10](CHANGELOG.md#0110---2026-08-16) | 2026-08-16 | 默认安全读取且仅追加的服务器记忆 agent 更新逻辑 |
329
- | [0.1.9](CHANGELOG.md#019---2026-08-12) | 2026-08-12 | 稳定且去重的服务器记忆上下文与更短的状态栏标签 |
330
322
 
331
323
  完整的新增内容、行为变更和 Bug 修复记录请查看 [CHANGELOG.md](CHANGELOG.md)。
332
324
 
package/index.ts CHANGED
@@ -726,7 +726,11 @@ function connect(config: ParsedSsh, authentication: SshAuthentication, fingerpri
726
726
  hostVerifier: (hash) => hash === fingerprint,
727
727
  };
728
728
  client.once("ready", () => resolve(client));
729
- client.once("error", reject);
729
+ // ssh2 may emit a socket error followed by a protocol error while a
730
+ // connection is lost during handshake. Keep consuming client errors after
731
+ // the first one so EventEmitter does not turn the follow-up into an
732
+ // uncaught exception; rejecting an already-settled promise is a no-op.
733
+ client.on("error", reject);
730
734
  client.connect(options);
731
735
  });
732
736
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ssh-remote",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Persistent remote SSH workspaces for Pi.",
5
5
  "type": "module",
6
6
  "author": "Yutong Bian",