@dsiloed/silo-link 1.5.3 → 1.6.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 (43) hide show
  1. package/README.md +41 -5
  2. package/dist/api/dsiloed-client.d.ts.map +1 -1
  3. package/dist/api/dsiloed-client.js +7 -1
  4. package/dist/api/dsiloed-client.js.map +1 -1
  5. package/dist/cli/claude-md-block.d.ts +3 -1
  6. package/dist/cli/claude-md-block.d.ts.map +1 -1
  7. package/dist/cli/claude-md-block.js +10 -39
  8. package/dist/cli/claude-md-block.js.map +1 -1
  9. package/dist/cli/commands.d.ts.map +1 -1
  10. package/dist/cli/commands.js +45 -14
  11. package/dist/cli/commands.js.map +1 -1
  12. package/dist/cli/daemon.d.ts +3 -3
  13. package/dist/cli/daemon.d.ts.map +1 -1
  14. package/dist/cli/daemon.js +12 -8
  15. package/dist/cli/daemon.js.map +1 -1
  16. package/dist/config/config-manager.d.ts +24 -0
  17. package/dist/config/config-manager.d.ts.map +1 -1
  18. package/dist/config/config-manager.js +168 -11
  19. package/dist/config/config-manager.js.map +1 -1
  20. package/dist/config/jwt-generator.d.ts +11 -6
  21. package/dist/config/jwt-generator.d.ts.map +1 -1
  22. package/dist/config/jwt-generator.js +20 -39
  23. package/dist/config/jwt-generator.js.map +1 -1
  24. package/dist/core/base-tmux-launcher.d.ts +13 -0
  25. package/dist/core/base-tmux-launcher.d.ts.map +1 -1
  26. package/dist/core/base-tmux-launcher.js +96 -4
  27. package/dist/core/base-tmux-launcher.js.map +1 -1
  28. package/dist/core/bridge.d.ts.map +1 -1
  29. package/dist/core/bridge.js +50 -11
  30. package/dist/core/bridge.js.map +1 -1
  31. package/dist/core/claude-launcher.d.ts +46 -0
  32. package/dist/core/claude-launcher.d.ts.map +1 -1
  33. package/dist/core/claude-launcher.js +259 -29
  34. package/dist/core/claude-launcher.js.map +1 -1
  35. package/dist/core/gemini-launcher.d.ts.map +1 -1
  36. package/dist/core/gemini-launcher.js +36 -13
  37. package/dist/core/gemini-launcher.js.map +1 -1
  38. package/dist/mcp/tools/register-tools.d.ts.map +1 -1
  39. package/dist/mcp/tools/register-tools.js +23 -18
  40. package/dist/mcp/tools/register-tools.js.map +1 -1
  41. package/dist/types/index.d.ts +4 -1
  42. package/dist/types/index.d.ts.map +1 -1
  43. package/package.json +1 -1
@@ -10,18 +10,18 @@ function getConfigPath(env) {
10
10
  const DEFAULT_CONFIG = {
11
11
  host: 'https://www.dsiloed.com',
12
12
  tenant_id: 'harmoniq',
13
- shared_key: '',
14
13
  user_sub: '',
14
+ jwt: '',
15
15
  mcp_port: 3579,
16
16
  reconnect_interval_ms: 5000,
17
17
  max_reconnect_attempts: 20,
18
18
  projects_path: '',
19
19
  claude_command: 'claude',
20
- claude_auto_respawn: false,
20
+ claude_auto_respawn: true,
21
21
  claude_idle_timeout_ms: 30000,
22
22
  claude_session_prompt: 'Register with SiloLink as "portablemind" and enter the poll loop.',
23
23
  gemini_command: 'gemini',
24
- gemini_auto_respawn: false,
24
+ gemini_auto_respawn: true,
25
25
  gemini_idle_timeout_ms: 30000,
26
26
  gemini_session_prompt: 'Register with SiloLink as "portablemind" and enter the poll loop.',
27
27
  };
@@ -38,15 +38,134 @@ export function loadConfig(env) {
38
38
  }
39
39
  const raw = fs.readFileSync(configPath, 'utf-8');
40
40
  const parsed = JSON.parse(raw);
41
- return { ...DEFAULT_CONFIG, ...parsed };
41
+ const merged = { ...DEFAULT_CONFIG, ...parsed };
42
+ // Per-env staging dir keeps each agent's project-scoped MCP config isolated
43
+ // (see SiloLinkConfig.staging_path). Default only computed when not set
44
+ // explicitly so existing configs keep working.
45
+ if (!merged.staging_path) {
46
+ const slug = env || 'default';
47
+ merged.staging_path = path.join(CONFIG_DIR, 'staging', slug);
48
+ }
49
+ return merged;
42
50
  }
43
51
  export function saveConfig(config, env) {
44
52
  fs.mkdirSync(CONFIG_DIR, { recursive: true });
45
- fs.writeFileSync(getConfigPath(env), JSON.stringify(config, null, 2) + '\n');
53
+ const configPath = getConfigPath(env);
54
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
55
+ // JWT is a credential — make sure the file is only readable by the owner.
56
+ try {
57
+ fs.chmodSync(configPath, 0o600);
58
+ }
59
+ catch { /* best-effort */ }
46
60
  }
47
61
  export function configExists(env) {
48
62
  return fs.existsSync(getConfigPath(env));
49
63
  }
64
+ /**
65
+ * POST {host}/api/v1/users/login with the user's credentials and Tenant-Id
66
+ * header. Returns the JWT on success. Throws with a descriptive message
67
+ * on failure.
68
+ */
69
+ export async function login(opts) {
70
+ const isEmail = opts.user_sub.includes('@');
71
+ const body = {
72
+ password: opts.password,
73
+ };
74
+ body[isEmail ? 'email' : 'username'] = opts.user_sub;
75
+ let res;
76
+ try {
77
+ res = await fetch(`${opts.host}/api/v1/users/login`, {
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ 'Tenant-Id': opts.tenant_id,
82
+ },
83
+ body: JSON.stringify(body),
84
+ });
85
+ }
86
+ catch (err) {
87
+ throw new Error(`Could not reach ${opts.host}: ${err.message}`);
88
+ }
89
+ let data;
90
+ try {
91
+ data = (await res.json());
92
+ }
93
+ catch {
94
+ throw new Error(`Login failed (HTTP ${res.status}) — non-JSON response`);
95
+ }
96
+ if (!res.ok || !data.success || !data.token) {
97
+ throw new Error(data.message || `Login failed (HTTP ${res.status})`);
98
+ }
99
+ return { token: data.token, requires_password_change: data.requires_password_change };
100
+ }
101
+ /**
102
+ * Read a line from stdin without echoing — used to collect a password
103
+ * without printing it to the terminal.
104
+ */
105
+ function askSilent(prompt) {
106
+ return new Promise((resolve) => {
107
+ process.stdout.write(prompt);
108
+ const stdin = process.stdin;
109
+ const wasRaw = stdin.isTTY ? stdin.isRaw === true : false;
110
+ if (stdin.isTTY)
111
+ stdin.setRawMode(true);
112
+ stdin.resume();
113
+ stdin.setEncoding('utf8');
114
+ const ETX = String.fromCharCode(3); // Ctrl-C
115
+ const BS = String.fromCharCode(8); // backspace
116
+ const DEL = String.fromCharCode(127); // DEL (terminal backspace)
117
+ let buffer = '';
118
+ const onData = (chunk) => {
119
+ for (const ch of chunk) {
120
+ if (ch === '\r' || ch === '\n') {
121
+ stdin.removeListener('data', onData);
122
+ if (stdin.isTTY)
123
+ stdin.setRawMode(wasRaw);
124
+ stdin.pause();
125
+ process.stdout.write('\n');
126
+ resolve(buffer);
127
+ return;
128
+ }
129
+ if (ch === ETX) {
130
+ process.stdout.write('\n');
131
+ process.exit(130);
132
+ }
133
+ if (ch === BS || ch === DEL) {
134
+ buffer = buffer.slice(0, -1);
135
+ continue;
136
+ }
137
+ buffer += ch;
138
+ }
139
+ };
140
+ stdin.on('data', onData);
141
+ });
142
+ }
143
+ export function nonInteractiveConfig(opts) {
144
+ if (!opts.host || !opts.tenant_id || !opts.user_sub || !opts.jwt) {
145
+ throw new Error('Non-interactive config requires --host, --tenant, --user-sub, and --jwt.');
146
+ }
147
+ if (opts.identity_type && opts.identity_type !== 'user' && opts.identity_type !== 'agent') {
148
+ throw new Error('identity_type must be "user" or "agent".');
149
+ }
150
+ let existing = DEFAULT_CONFIG;
151
+ try {
152
+ existing = loadConfig(opts.env);
153
+ }
154
+ catch {
155
+ // first-time setup
156
+ }
157
+ const config = {
158
+ ...existing,
159
+ host: opts.host,
160
+ tenant_id: opts.tenant_id,
161
+ user_sub: opts.user_sub,
162
+ jwt: opts.jwt,
163
+ mcp_port: opts.mcp_port ?? existing.mcp_port,
164
+ projects_path: opts.projects_path ?? existing.projects_path,
165
+ identity_type: opts.identity_type ?? existing.identity_type ?? 'user',
166
+ };
167
+ saveConfig(config, opts.env);
168
+ }
50
169
  export async function interactiveConfig(env) {
51
170
  const rl = readline.createInterface({
52
171
  input: process.stdin,
@@ -67,25 +186,63 @@ export async function interactiveConfig(env) {
67
186
  }
68
187
  const envLabel = env ? ` (${env})` : '';
69
188
  console.log(`\nSiloLink Configuration${envLabel}\n`);
189
+ // Identity type — humans log in with username/password and we mint a
190
+ // JWT against /api/v1/users/login; agents paste the JWT issued from
191
+ // the LLM Manager UI (POST /llm_agents/:id/issue_silolink_jwt) so we
192
+ // never need their User credentials.
193
+ const identityRaw = await ask('Identity type — (u)ser or (a)gent', 'u');
194
+ const isAgent = identityRaw.trim().toLowerCase().startsWith('a');
70
195
  const host = await ask('DSiloed host', existing.host);
71
- const tenant_id = await ask('Tenant ID', existing.tenant_id);
72
- const shared_key = await ask('Shared key', existing.shared_key || undefined);
73
- const user_sub = await ask('User login (email or username)', existing.user_sub || undefined);
196
+ const tenant_id = await ask('Tenant ID (enterprise identifier)', existing.tenant_id);
197
+ const user_sub = await ask(isAgent ? 'Agent name (sub claim from the issued token)' : 'User login (email or username)', existing.user_sub || undefined);
74
198
  const mcp_port_str = await ask('MCP port', String(existing.mcp_port));
75
199
  const mcp_port = parseInt(mcp_port_str, 10) || existing.mcp_port;
76
200
  const projects_path = await ask('Projects path (where your repos live locally)', existing.projects_path || undefined);
201
+ rl.close();
202
+ let token;
203
+ let requires_password_change = false;
204
+ if (isAgent) {
205
+ token = (await askSilent('Agent JWT (paste from LLM Manager → Agent → SiloLink Authentication): ')).trim();
206
+ if (!token) {
207
+ console.error('\nAgent JWT is required. Generate one in the LLM Manager and re-run silolink config.');
208
+ process.exit(1);
209
+ }
210
+ }
211
+ else {
212
+ const password = await askSilent('Password (not stored): ');
213
+ if (!password) {
214
+ console.error('\nPassword is required to obtain a JWT. Aborting.');
215
+ process.exit(1);
216
+ }
217
+ console.log(`\nLogging in to ${host} as ${user_sub}...`);
218
+ try {
219
+ const result = await login({ host, tenant_id, user_sub, password });
220
+ token = result.token;
221
+ requires_password_change = result.requires_password_change === true;
222
+ }
223
+ catch (err) {
224
+ console.error(`Login failed: ${err.message}`);
225
+ process.exit(1);
226
+ }
227
+ }
77
228
  const config = {
78
229
  ...existing,
79
230
  host,
80
231
  tenant_id,
81
- shared_key,
82
232
  user_sub,
233
+ jwt: token,
83
234
  mcp_port,
84
235
  projects_path,
236
+ identity_type: isAgent ? 'agent' : 'user',
85
237
  };
86
238
  saveConfig(config, env);
87
239
  const configPath = getConfigPath(env);
88
- console.log(`\nConfig saved to ${configPath}\n`);
89
- rl.close();
240
+ console.log(isAgent
241
+ ? `\nAgent token stored. Config saved to ${configPath}`
242
+ : `\nLogin successful. Config saved to ${configPath}`);
243
+ if (requires_password_change) {
244
+ console.log('Note: this account is flagged for password change — update it via the web UI.');
245
+ }
246
+ console.log('');
90
247
  }
91
248
  //# sourceMappingURL=config-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/config/config-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/config/config-manager.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,20 @@
1
1
  import type { SiloLinkConfig } from '../types/index.js';
2
+ /**
3
+ * Token store for the long-lived JWT obtained at `silolink config` time
4
+ * via POST /api/v1/users/login. The server-issued token has no `exp`
5
+ * claim, so there's nothing to refresh client-side — if it ever stops
6
+ * working, the user has to re-run `silolink config` to log in again.
7
+ *
8
+ * The class keeps the original `JwtGenerator` shape (generate / getToken /
9
+ * startAutoRefresh / stopAutoRefresh) so the rest of the bridge can
10
+ * continue to call into it unchanged.
11
+ */
2
12
  export declare class JwtGenerator {
3
13
  private config;
4
- private currentToken;
5
- private tokenExpiry;
6
- private refreshTimer;
7
- private onRefresh;
8
14
  constructor(config: SiloLinkConfig);
9
15
  generate(): string;
10
16
  getToken(): string;
11
- private isExpiringSoon;
12
- startAutoRefresh(onRefresh: (token: string) => void): void;
17
+ startAutoRefresh(_onRefresh: (token: string) => void): void;
13
18
  stopAutoRefresh(): void;
14
19
  }
15
20
  //# sourceMappingURL=jwt-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-generator.d.ts","sourceRoot":"","sources":["../../src/config/jwt-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAKxD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,SAAS,CAA0C;gBAE/C,MAAM,EAAE,cAAc;IAIlC,QAAQ,IAAI,MAAM;IAiBlB,QAAQ,IAAI,MAAM;IAOlB,OAAO,CAAC,cAAc;IAMtB,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAU1D,eAAe,IAAI,IAAI;CAMxB"}
1
+ {"version":3,"file":"jwt-generator.d.ts","sourceRoot":"","sources":["../../src/config/jwt-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;;;;;GASG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,cAAc;IAIlC,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;IAYlB,gBAAgB,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAI3D,eAAe,IAAI,IAAI;CAGxB"}
@@ -1,54 +1,35 @@
1
- import jwt from 'jsonwebtoken';
2
- const TOKEN_LIFETIME_HOURS = 24;
3
- const REFRESH_INTERVAL_HOURS = 12;
1
+ /**
2
+ * Token store for the long-lived JWT obtained at `silolink config` time
3
+ * via POST /api/v1/users/login. The server-issued token has no `exp`
4
+ * claim, so there's nothing to refresh client-side — if it ever stops
5
+ * working, the user has to re-run `silolink config` to log in again.
6
+ *
7
+ * The class keeps the original `JwtGenerator` shape (generate / getToken /
8
+ * startAutoRefresh / stopAutoRefresh) so the rest of the bridge can
9
+ * continue to call into it unchanged.
10
+ */
4
11
  export class JwtGenerator {
5
12
  config;
6
- currentToken = null;
7
- tokenExpiry = 0;
8
- refreshTimer = null;
9
- onRefresh = null;
10
13
  constructor(config) {
11
14
  this.config = config;
12
15
  }
13
16
  generate() {
14
- const now = Math.floor(Date.now() / 1000);
15
- const exp = now + TOKEN_LIFETIME_HOURS * 3600;
16
- const payload = {
17
- sub: this.config.user_sub,
18
- iat: now,
19
- exp,
20
- };
21
- this.currentToken = jwt.sign(payload, this.config.shared_key, {
22
- algorithm: 'HS256',
23
- });
24
- this.tokenExpiry = exp;
25
- return this.currentToken;
17
+ return this.getToken();
26
18
  }
27
19
  getToken() {
28
- if (!this.currentToken || this.isExpiringSoon()) {
29
- return this.generate();
20
+ const token = this.config.jwt;
21
+ if (!token) {
22
+ throw new Error('No JWT in config. Run "silolink config" to log in and obtain a token.');
30
23
  }
31
- return this.currentToken;
24
+ return token;
32
25
  }
33
- isExpiringSoon() {
34
- const now = Math.floor(Date.now() / 1000);
35
- // Refresh if less than 1 hour remaining
36
- return this.tokenExpiry - now < 3600;
37
- }
38
- startAutoRefresh(onRefresh) {
39
- this.onRefresh = onRefresh;
40
- this.refreshTimer = setInterval(() => {
41
- const token = this.generate();
42
- if (this.onRefresh) {
43
- this.onRefresh(token);
44
- }
45
- }, REFRESH_INTERVAL_HOURS * 3600 * 1000);
26
+ // No-op: server JWTs have no exp, so there is nothing to refresh.
27
+ // Kept so existing callers compile.
28
+ startAutoRefresh(_onRefresh) {
29
+ void _onRefresh;
46
30
  }
47
31
  stopAutoRefresh() {
48
- if (this.refreshTimer) {
49
- clearInterval(this.refreshTimer);
50
- this.refreshTimer = null;
51
- }
32
+ // no-op
52
33
  }
53
34
  }
54
35
  //# sourceMappingURL=jwt-generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-generator.js","sourceRoot":"","sources":["../../src/config/jwt-generator.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAG/B,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAElC,MAAM,OAAO,YAAY;IACf,MAAM,CAAiB;IACvB,YAAY,GAAkB,IAAI,CAAC;IACnC,WAAW,GAAW,CAAC,CAAC;IACxB,YAAY,GAA0C,IAAI,CAAC;IAC3D,SAAS,GAAqC,IAAI,CAAC;IAE3D,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,QAAQ;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,GAAG,GAAG,oBAAoB,GAAG,IAAI,CAAC;QAE9C,MAAM,OAAO,GAAG;YACd,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YACzB,GAAG,EAAE,GAAG;YACR,GAAG;SACJ,CAAC;QAEF,IAAI,CAAC,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;YAC5D,SAAS,EAAE,OAAO;SACnB,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;QACvB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAChD,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAEO,cAAc;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,wCAAwC;QACxC,OAAO,IAAI,CAAC,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC;IACvC,CAAC;IAED,gBAAgB,CAAC,SAAkC;QACjD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;YACnC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;QACH,CAAC,EAAE,sBAAsB,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"jwt-generator.js","sourceRoot":"","sources":["../../src/config/jwt-generator.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,OAAO,YAAY;IACf,MAAM,CAAiB;IAE/B,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;IAED,QAAQ;QACN,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;QAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CACb,uEAAuE,CACxE,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,kEAAkE;IAClE,oCAAoC;IACpC,gBAAgB,CAAC,UAAmC;QAClD,KAAK,UAAU,CAAC;IAClB,CAAC;IAED,eAAe;QACb,QAAQ;IACV,CAAC;CACF"}
@@ -115,6 +115,19 @@ export declare abstract class BaseTmuxLauncher implements AgentLauncher {
115
115
  * by checkTmuxSessions to inspect output for usage-limit patterns etc).
116
116
  */
117
117
  protected capturePaneTail(tmuxSession: string, reason: string, onContent?: (content: string) => void): void;
118
+ /**
119
+ * When an agent fails to show its ready indicator within the timeout,
120
+ * grab the pane content and scan for known stuck-pane signatures we've
121
+ * seen in production. Each pattern maps to a clear actionable hint so a
122
+ * future CLI-schema or first-run-flow change shows up as a 30-second
123
+ * diagnostic in the daemon log instead of a multi-hour silent hang.
124
+ *
125
+ * Patterns are intentionally loose (case-insensitive substring) so a
126
+ * minor wording shift in CC/Gemini doesn't blind us. If something stops
127
+ * matching, we fall through to the existing "did not show ready"
128
+ * warning — same posture as before, no regression.
129
+ */
130
+ protected diagnoseStuckPane(tmuxSession: string): void;
118
131
  /**
119
132
  * Hook invoked after a tmux pane dies and its final content has been captured.
120
133
  * Subclasses override to inspect the content (e.g. for usage-limit messages)
@@ -1 +1 @@
1
- {"version":3,"file":"base-tmux-launcher.d.ts","sourceRoot":"","sources":["../../src/core/base-tmux-launcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base-tmux-launcher.d.ts","sourceRoot":"","sources":["../../src/core/base-tmux-launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAErF,UAAU,eAAe;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;GAIG;AACH,8BAAsB,gBAAiB,YAAW,aAAa;IAC7D,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC;IACjC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IACzC,SAAS,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9C,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpD,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5C,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAa;IACjE,SAAS,CAAC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;IACjE,SAAS,CAAC,gBAAgB,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,IAAI,CAAQ;IACzE,SAAS,CAAC,cAAc,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,IAAI,CAAQ;IACvE,SAAS,CAAC,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAC1D,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,WAAW,SAAK;IAC1B,SAAS,CAAC,UAAU,SAAK;IACzB,SAAS,CAAC,eAAe,SAAK;IAC9B,SAAS,CAAC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;IAChE,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9C,SAAS,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACtD,SAAS,CAAC,sBAAsB,EAAE,qBAAqB,GAAG,IAAI,CAAQ;IACtE,SAAS,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACpD,SAAS,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAClD,SAAS,CAAC,uBAAuB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAQ;gBAGxD,MAAM,EAAE,cAAc,EACtB,cAAc,EAAE,cAAc,EAC9B,aAAa,CAAC,EAAE,aAAa,EAC7B,YAAY,CAAC,EAAE,YAAY,EAC3B,gBAAgB,CAAC,EAAE,gBAAgB;IAYrC,+DAA+D;IAC/D,SAAS,CAAC,QAAQ,CAAC,UAAU,IAAI,MAAM;IAEvC,uCAAuC;IACvC,SAAS,CAAC,QAAQ,CAAC,OAAO,IAAI,MAAM,EAAE;IAEtC,uFAAuF;IACvF,SAAS,CAAC,QAAQ,CAAC,iBAAiB,IAAI,MAAM,EAAE;IAEhD,sGAAsG;IACtG,SAAS,CAAC,iBAAiB,IAAI,MAAM;IAErC,0GAA0G;IAC1G,SAAS,CAAC,mBAAmB,IAAI,MAAM;IAEvC,qDAAqD;IACrD,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAEvD,sEAAsE;IACtE,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE9F,yDAAyD;IACzD,SAAS,CAAC,QAAQ,CAAC,YAAY,IAAI,OAAO;IAE1C,+CAA+C;IAC/C,SAAS,CAAC,QAAQ,CAAC,mBAAmB,IAAI,MAAM;IAEhD,0CAA0C;IAC1C,SAAS,CAAC,QAAQ,CAAC,uBAAuB,IAAI,OAAO;IAErD,0CAA0C;IAC1C,SAAS,CAAC,QAAQ,CAAC,gBAAgB,IAAI,MAAM;IAE7C,4CAA4C;IAC5C,SAAS,CAAC,QAAQ,CAAC,gBAAgB,IAAI,MAAM,GAAG,SAAS;IAEzD,uEAAuE;IACvE,SAAS,CAAC,QAAQ,CAAC,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAExD,wFAAwF;IACxF,SAAS,CAAC,QAAQ,CAAC,aAAa,IAAI,MAAM;IAE1C,sEAAsE;IACtE,SAAS,CAAC,QAAQ,CAAC,SAAS,IAAI,MAAM;IAEtC,oCAAoC;IACpC,SAAS,CAAC,QAAQ,CAAC,kBAAkB,IAAI,MAAM;IAE/C,kEAAkE;IAClE,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAClC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,GACvB;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE;IAIpC,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAkC1D,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAK5E,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAQtD,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAItC,YAAY,IAAI,IAAI;IAIpB,YAAY,IAAI,YAAY,EAAE;IAU9B,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAenE,KAAK,IAAI,OAAO;IAgBhB;;;;;;;;OAQG;IACH,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,SAAiB;IAChE,SAAS,CAAC,cAAc,IAAI,OAAO;IAcnC,SAAS,IAAI,OAAO;IACpB,oBAAoB,IAAI,OAAO;IAC/B,cAAc,IAAI,OAAO;IAEzB,gBAAgB,IAAI,IAAI;IAaxB,OAAO,IAAI,IAAI;IAQf,kBAAkB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI;IAC9D,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAClC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAC3C,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI;IACjD,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKjC,eAAe,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkB9G,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,GAAE,MAA6B,GAAG,IAAI;IAgBvF,IAAI,IAAI,IAAI;IAiBZ;;;;;;;;OAQG;IACH,SAAS,CAAC,eAAe,CACvB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACpC,IAAI;IAuBP;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IA0CtD;;;;;OAKG;IACH,SAAS,CAAC,UAAU,CAClB,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,GACnB;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAI/D,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoB3E,6BAA6B,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAS9D,cAAc,CAAC,MAAM,GAAE,MAAiB,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgO1F,SAAS,CAAC,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAMxD,SAAS,CAAC,iBAAiB,IAAI,IAAI;IAoBnC,OAAO,CAAC,kBAAkB;IA8C1B,SAAS,CAAC,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI;cAiChE,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B1C,SAAS,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;CAYnE"}
@@ -156,11 +156,17 @@ export class BaseTmuxLauncher {
156
156
  isAutoRespawnEnabled() { return this.enabled && this.isAutoRespawnConfigured(); }
157
157
  hasLiveProcess() { return this.tmuxSessions.size > 0; }
158
158
  startIdleMonitor() {
159
- if (!this.isAutoRespawnEnabled())
159
+ // Run the idle monitor whenever the launcher is enabled. The heartbeat
160
+ // nudge needs to fire even when auto-respawn is off — it's a benign
161
+ // keystroke that keeps Claude's poll loop alive during long quiet
162
+ // stretches. Respawn-specific actions inside the monitor still check
163
+ // isAutoRespawnEnabled() at their own call sites.
164
+ if (!this.enabled)
160
165
  return;
161
166
  const checkInterval = Math.max(this.getIdleTimeoutMs() / 2, 5000);
162
167
  this.idleCheckTimer = setInterval(() => this.checkIdle(), checkInterval);
163
- console.log(` ${this.getLogTag()} auto-manage enabled (idle timeout: ${this.getIdleTimeoutMs()}ms)`);
168
+ const respawnState = this.isAutoRespawnConfigured() ? 'auto-respawn on' : 'auto-respawn off';
169
+ console.log(` ${this.getLogTag()} idle monitor running (idle timeout: ${this.getIdleTimeoutMs()}ms, ${respawnState})`);
164
170
  }
165
171
  destroy() {
166
172
  if (this.idleCheckTimer) {
@@ -266,6 +272,59 @@ export class BaseTmuxLauncher {
266
272
  onContent('');
267
273
  }
268
274
  }
275
+ /**
276
+ * When an agent fails to show its ready indicator within the timeout,
277
+ * grab the pane content and scan for known stuck-pane signatures we've
278
+ * seen in production. Each pattern maps to a clear actionable hint so a
279
+ * future CLI-schema or first-run-flow change shows up as a 30-second
280
+ * diagnostic in the daemon log instead of a multi-hour silent hang.
281
+ *
282
+ * Patterns are intentionally loose (case-insensitive substring) so a
283
+ * minor wording shift in CC/Gemini doesn't blind us. If something stops
284
+ * matching, we fall through to the existing "did not show ready"
285
+ * warning — same posture as before, no regression.
286
+ */
287
+ diagnoseStuckPane(tmuxSession) {
288
+ try {
289
+ const capture = spawn('tmux', ['capture-pane', '-t', tmuxSession, '-p', '-S', '-200'], {
290
+ stdio: ['ignore', 'pipe', 'pipe'],
291
+ });
292
+ let output = '';
293
+ capture.stdout.on('data', (data) => { output += data.toString(); });
294
+ capture.on('exit', () => {
295
+ if (!output)
296
+ return;
297
+ const lower = output.toLowerCase();
298
+ // Each entry: substring → human-readable explanation. Order matters
299
+ // — first match wins, so put the most specific failure shapes first.
300
+ const signatures = [
301
+ ['error: unknown option', 'CLI rejected one of the args getArgs() supplied. Likely a flag introduced/removed across CLI versions — check installed agent CLI version vs. flags in getArgs().'],
302
+ ['command not found', 'Agent binary not on PATH for the spawned process. Confirm the binary is in $PATH the daemon was launched with (silolink reads $PATH at start; ~/.local/bin etc. must be present).'],
303
+ ['cannot find module', 'Agent binary points at a missing node module. Likely a stale/partial install — try reinstalling the agent CLI.'],
304
+ ['do you trust this directory', 'Workspace trust dialog visible — ensureClaudeWorkspaceTrust pre-write either failed or CC changed the gate name. Check ~/.claude.json[projects][cwd].hasTrustDialogAccepted and the cwd CC actually launched in.'],
305
+ ['warning: bypass permissions mode', 'Bypass-permissions consent dialog visible — CC is asking the human to confirm. If you can\'t change this gate via flag, bake an answer (`Yes I accept` etc.) into a settings file CC reads at startup.'],
306
+ ['approve project-scope mcp', 'Project-scope MCP-enable dialog visible — pre-write enabledMcpjsonServers in ~/.claude.json[projects][cwd] for the server names registered via `mcp add -s project`.'],
307
+ ['no mcp servers', 'Agent reports zero MCP servers loaded. Check both per-cwd .mcp.json and user-scope ~/.claude.json[mcpServers], plus any per-project enable list.'],
308
+ ['authentication required', 'Agent CLI is asking the human to log in. Ensure JWTs / API keys are baked into config files, not interactive prompts.'],
309
+ ];
310
+ for (const [needle, hint] of signatures) {
311
+ if (lower.includes(needle)) {
312
+ console.warn(`${this.getLogTag()} DIAGNOSTIC for "${tmuxSession}": ${hint}`);
313
+ console.warn(`${this.getLogTag()} DIAGNOSTIC matched signature: "${needle}"`);
314
+ return;
315
+ }
316
+ }
317
+ // Fell through — no known pattern matched. Log the pane tail anyway
318
+ // so future runs can be triaged from log alone without a re-spawn.
319
+ console.warn(`${this.getLogTag()} DIAGNOSTIC for "${tmuxSession}": stuck on unrecognised state. Pane tail (last 30 lines):`);
320
+ const tail = output.trim().split('\n').slice(-30).join('\n');
321
+ console.warn(tail);
322
+ });
323
+ }
324
+ catch (err) {
325
+ console.error(`${this.getLogTag()} diagnoseStuckPane failed for ${tmuxSession}: ${err}`);
326
+ }
327
+ }
269
328
  /**
270
329
  * Hook invoked after a tmux pane dies and its final content has been captured.
271
330
  * Subclasses override to inspect the content (e.g. for usage-limit messages)
@@ -377,8 +436,40 @@ export class BaseTmuxLauncher {
377
436
  console.log(` Working directory: ${cwd}`);
378
437
  if (workspaceBranch)
379
438
  console.log(` Workspace branch: ${workspaceBranch}`);
380
- const tmuxSession = `${this.getTmuxPrefix()}-${Date.now()}`;
381
- // Fix 1: Use tmux new-session -c to set working directory safely instead of
439
+ // Deterministic tmux name when we know the conversation: peek
440
+ // (and any UI tooling) can compute the tmux session name from
441
+ // a conversation_id alone, without a metadata round-trip. Falls
442
+ // back to a timestamped name for ad-hoc launches that have no
443
+ // conversation context.
444
+ //
445
+ // If a tmux with the same name already exists (a prior session
446
+ // for this conversation that wasn't cleaned up), kill it first
447
+ // so the new launch doesn't fail with "duplicate session". The
448
+ // server-side end-prior-AgentSession fix makes the duplicate
449
+ // case rare, but defending against it here keeps the daemon
450
+ // robust against orphan tmux drift.
451
+ const tmuxSession = conversationId
452
+ ? `${this.getTmuxPrefix()}-conv${conversationId}`
453
+ : `${this.getTmuxPrefix()}-${Date.now()}`;
454
+ try {
455
+ await new Promise((resolve) => {
456
+ const has = spawn('tmux', ['has-session', '-t', tmuxSession], { stdio: 'ignore' });
457
+ has.on('exit', (code) => {
458
+ if (code === 0) {
459
+ console.log(`${this.getLogTag()} Existing tmux "${tmuxSession}" found — killing before relaunch`);
460
+ const kill = spawn('tmux', ['kill-session', '-t', tmuxSession], { stdio: 'ignore' });
461
+ kill.on('exit', () => resolve());
462
+ kill.on('error', () => resolve());
463
+ }
464
+ else {
465
+ resolve();
466
+ }
467
+ });
468
+ has.on('error', () => resolve());
469
+ });
470
+ }
471
+ catch { /* best-effort cleanup */ }
472
+ // Use tmux new-session -c to set working directory safely instead of
382
473
  // interpolating into a shell string. This prevents shell injection via cwd/command.
383
474
  const tmuxArgs = [
384
475
  'new-session', '-d', '-s', tmuxSession, '-c', cwd, '-x', '200', '-y', '50',
@@ -445,6 +536,7 @@ export class BaseTmuxLauncher {
445
536
  }
446
537
  if (!ready) {
447
538
  console.warn(`${this.getLogTag()} Agent in "${sessionToPrompt}" did not show ready indicator within ${maxWaitMs / 1000}s — sending prompt anyway`);
539
+ this.diagnoseStuckPane(sessionToPrompt);
448
540
  }
449
541
  else {
450
542
  console.log(`${this.getLogTag()} Agent ready after ${((Date.now() - startWait) / 1000).toFixed(1)}s`);