@seamnet/client 0.20.1 → 0.20.3

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.
Files changed (2) hide show
  1. package/lib/tmux-utils.cjs +22 -4
  2. package/package.json +1 -1
@@ -18,18 +18,23 @@ const EXEC_OPTS = { encoding: 'utf8', timeout: 5000, stdio: ['pipe', 'pipe', 'pi
18
18
  // kind → 启动命令族。声明式数据小表,不是 adapter。新增 kind 加一行即可。
19
19
  // - fresh:全新会话的启动命令
20
20
  // - resume:续上一次会话的命令(restart 默认走这个;--no-continue 走 fresh)
21
- // - exit:TUI 内的优雅退出命令(restart 发它 + Enter)
21
+ // - resetKeys/resetWaitMs:发 exit 前先把 TUI 拉回干净空闲态(逐个键发送,每个键后等一小下)
22
+ // - exit:TUI 内的优雅退出命令(restart 发 reset 后再发它 + Enter)
22
23
  // - downTimeout:发了 exit 后等进程退出的轮询超时(ms)
23
24
  const KIND_CMD = {
24
25
  cc: {
25
26
  fresh: 'claude --dangerously-skip-permissions',
26
27
  resume: 'claude --dangerously-skip-permissions --continue',
28
+ resetKeys: ['Escape'],
29
+ resetWaitMs: 1000,
27
30
  exit: '/exit',
28
31
  downTimeout: 120000, // cc 退出跑 Stop hook(auto-save / semantic_memory)要 ~90s
29
32
  },
30
33
  codex: {
31
- fresh: 'codex -m gpt-5.4',
34
+ fresh: 'codex',
32
35
  resume: 'codex resume --last',
36
+ resetKeys: ['Escape', 'Escape'],
37
+ resetWaitMs: 1000,
33
38
  exit: '/exit',
34
39
  downTimeout: 60000, // 实测 codex /exit ~25s(退出存 session),留余量
35
40
  },
@@ -196,11 +201,16 @@ function startTerm({ kind, cmd, session, dir, socketPath } = {}) {
196
201
  * - poll-up 后 ~5s 存活复检:化解「起来一瞬间被检测到、随即自更新退出」的假 success
197
202
  * - poll-up 失败:C-c 清半行重试一次
198
203
  */
199
- async function restartSkeleton(session, socketPath, { targetKind, stopAction, downTimeout, startCmd }) {
204
+ async function restartSkeleton(
205
+ session,
206
+ socketPath,
207
+ { targetKind, resetAction = async () => {}, stopAction, downTimeout, startCmd }
208
+ ) {
200
209
  const tmux = tmuxCmd(socketPath);
201
210
  let warning = null;
202
211
 
203
- // 1.
212
+ // 1. 先 reset TUI,再优雅退出
213
+ await resetAction();
204
214
  stopAction();
205
215
 
206
216
  // 2. poll-down:轮询直到 kind 不再是 targetKind;超时强制 kill 兜底
@@ -282,6 +292,14 @@ async function restartTerm(session, { socketPath, continueSession = true } = {})
282
292
  const startCmd = continueSession ? spec.resume : spec.fresh;
283
293
  return restartSkeleton(session, socketPath, {
284
294
  targetKind: kind,
295
+ resetAction: async () => {
296
+ if (Array.isArray(spec.resetKeys) && spec.resetKeys.length > 0) {
297
+ for (const key of spec.resetKeys) {
298
+ execSync(`${tmux} send-keys -t "${session}" ${JSON.stringify(key)}`, EXEC_OPTS);
299
+ if (spec.resetWaitMs > 0) await sleep(spec.resetWaitMs);
300
+ }
301
+ }
302
+ },
285
303
  stopAction: () => {
286
304
  execSync(`${tmux} send-keys -t "${session}" -l ${JSON.stringify(spec.exit)}`, EXEC_OPTS);
287
305
  execSync(`${tmux} send-keys -t "${session}" Enter`, EXEC_OPTS);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamnet/client",
3
- "version": "0.20.1",
3
+ "version": "0.20.3",
4
4
  "description": "One command to join Seam — the network where people and AI stay in sync.",
5
5
  "bin": {
6
6
  "seam-client": "bin/cli.js",