@seamnet/client 0.17.0 → 0.17.1

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 +52 -17
  2. package/package.json +1 -1
@@ -93,30 +93,65 @@ function startCC(dir, session, socketPath) {
93
93
  );
94
94
  }
95
95
 
96
+ function sleep(ms) {
97
+ return new Promise((r) => setTimeout(r, ms));
98
+ }
99
+
96
100
  /**
97
101
  * 给 CC 发 /exit 然后重启(带 --continue)。
98
102
  * guardian 升级后自动重启 CC 用这个。
103
+ *
104
+ * 不再固定等 3s——有 Stop hook(auto-save / semantic_memory)的 AI 退出要
105
+ * 60-90s,3s 时旧 claude 还活着,重启命令会被当成旧 TUI 的 queued message,
106
+ * CC 永远没重启。改成轮询 isCCRunning 确认状态再动作。
99
107
  */
100
- function restartCC(session, { socketPath, continueSession = true } = {}) {
108
+ async function restartCC(session, { socketPath, continueSession = true } = {}) {
101
109
  const tmux = tmuxCmd(socketPath);
102
- // /exit
110
+ const restartCmd = continueSession
111
+ ? 'claude --dangerously-skip-permissions --continue'
112
+ : 'claude --dangerously-skip-permissions';
113
+
114
+ // 1. 发 /exit
103
115
  execSync(`${tmux} send-keys -t "${session}" -l '/exit'`, EXEC_OPTS);
104
116
  execSync(`${tmux} send-keys -t "${session}" Enter`, EXEC_OPTS);
105
- // 等 CC 退出
106
- return new Promise((resolve) => {
107
- setTimeout(() => {
108
- try {
109
- const cmd = continueSession
110
- ? 'claude --dangerously-skip-permissions --continue'
111
- : 'claude --dangerously-skip-permissions';
112
- execSync(`${tmux} send-keys -t "${session}" -l ${JSON.stringify(cmd)}`, EXEC_OPTS);
113
- execSync(`${tmux} send-keys -t "${session}" Enter`, EXEC_OPTS);
114
- resolve(true);
115
- } catch (e) {
116
- resolve(false);
117
- }
118
- }, 3000);
119
- });
117
+
118
+ // 2. 轮询直到 CC 退出(120s 覆盖 90s Stop hook + 余量)
119
+ const exitDeadline = Date.now() + 120000;
120
+ while (isCCRunning(session, socketPath)) {
121
+ if (Date.now() >= exitDeadline) {
122
+ // CC 还没退,发重启命令会变成 queued message 污染 TUI——放弃
123
+ return false;
124
+ }
125
+ await sleep(1000);
126
+ }
127
+
128
+ // 3. 退出确认后等 shell prompt 落定
129
+ await sleep(500);
130
+
131
+ // 4-5. 发重启命令 + 轮询确认 CC 起来(30s 超时)
132
+ const tryStart = async () => {
133
+ try {
134
+ execSync(`${tmux} send-keys -t "${session}" -l ${JSON.stringify(restartCmd)}`, EXEC_OPTS);
135
+ execSync(`${tmux} send-keys -t "${session}" Enter`, EXEC_OPTS);
136
+ } catch {
137
+ return false;
138
+ }
139
+ const upDeadline = Date.now() + 30000;
140
+ while (!isCCRunning(session, socketPath)) {
141
+ if (Date.now() >= upDeadline) return false;
142
+ await sleep(1000);
143
+ }
144
+ return true;
145
+ };
146
+
147
+ if (await tryStart()) return true;
148
+
149
+ // 6. 超时没起来:C-c 清掉可能的半行,重试一次
150
+ try {
151
+ execSync(`${tmux} send-keys -t "${session}" C-c`, EXEC_OPTS);
152
+ } catch {}
153
+ await sleep(500);
154
+ return tryStart();
120
155
  }
121
156
 
122
157
  module.exports = { listSessions, isCCRunning, sendToCC, readOutput, startCC, restartCC, tmuxCmd };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamnet/client",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
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",