linkshell-cli 0.2.120 → 0.2.122

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.
@@ -222,10 +222,21 @@ export class ClaudeStreamJsonClient {
222
222
  let currentToolId: string | undefined;
223
223
  let currentToolName: string | undefined;
224
224
  let currentMessageId: string | undefined;
225
+ const progressItemId = `claude-progress:${input.clientMessageId}`;
225
226
  // Map tool_use_id → tool_name so tool_result can look up the correct name
226
227
  // even when multiple tools are in flight
227
228
  const toolNames = new Map<string, string>();
228
229
 
230
+ this.input.onNotification("item/started", {
231
+ sessionId: input.sessionId ?? this.claudeSessionId,
232
+ item: {
233
+ id: progressItemId,
234
+ type: "thinking",
235
+ text: "Claude 正在处理请求",
236
+ status: "running",
237
+ },
238
+ });
239
+
229
240
  rl.on("line", (line: string) => {
230
241
  if (this.pendingCancel) {
231
242
  child.kill("SIGTERM");
@@ -375,6 +386,16 @@ export class ClaudeStreamJsonClient {
375
386
  }
376
387
 
377
388
  case "result": {
389
+ const isError = event.subtype === "error" || event.is_error === true;
390
+ this.input.onNotification("item/completed", {
391
+ sessionId: this.claudeSessionId ?? input.sessionId,
392
+ item: {
393
+ id: progressItemId,
394
+ type: "thinking",
395
+ text: isError ? "Claude 运行出错" : "Claude 已完成",
396
+ status: isError ? "failed" : "completed",
397
+ },
398
+ });
378
399
  // Mark the last agent message as complete so isStreaming flips to false
379
400
  if (currentMessageId) {
380
401
  this.input.onNotification("item/completed", {
@@ -387,7 +408,6 @@ export class ClaudeStreamJsonClient {
387
408
  });
388
409
  }
389
410
  // Turn complete
390
- const isError = event.subtype === "error" || event.is_error === true;
391
411
  this.input.onNotification("turn/completed", {
392
412
  sessionId: this.claudeSessionId,
393
413
  stopReason: event.stop_reason ?? (isError ? "error" : "end_turn"),
@@ -408,11 +428,29 @@ export class ClaudeStreamJsonClient {
408
428
  });
409
429
 
410
430
  child.on("error", (err) => {
431
+ this.input.onNotification("item/completed", {
432
+ sessionId: this.claudeSessionId ?? input.sessionId,
433
+ item: {
434
+ id: progressItemId,
435
+ type: "thinking",
436
+ text: "Claude 运行出错",
437
+ status: "failed",
438
+ },
439
+ });
411
440
  finish(err, undefined);
412
441
  });
413
442
 
414
443
  child.on("exit", (code, signal) => {
415
444
  if (!settled) {
445
+ this.input.onNotification("item/completed", {
446
+ sessionId: this.claudeSessionId ?? input.sessionId,
447
+ item: {
448
+ id: progressItemId,
449
+ type: "thinking",
450
+ text: this.pendingCancel ? "Claude 已停止" : "Claude 意外退出",
451
+ status: "failed",
452
+ },
453
+ });
416
454
  finish(
417
455
  new Error(`Claude exited unexpectedly (code=${code ?? "null"}, signal=${signal ?? "null"})`),
418
456
  undefined,
@@ -1138,7 +1138,7 @@ export class BridgeSession {
1138
1138
  hookPort = result.port;
1139
1139
  hookConfigPaths.push(result.configPath);
1140
1140
  // Also set up hooks for other providers (curlCmd already has marker from setupHookServer)
1141
- const curlCmd = `curl -s -X POST "http://127.0.0.1:${result.port}/hook?m=${hookMarker}&lid=$LINKSHELL_ID" -H 'Content-Type: application/json' --data-binary @-`;
1141
+ const curlCmd = `curl -s --connect-timeout 1 --max-time ${Math.ceil((PERMISSION_REQUEST_TIMEOUT_MS + 30_000) / 1000)} -X POST "http://127.0.0.1:${result.port}/hook?m=${hookMarker}&lid=$LINKSHELL_ID" -H 'Content-Type: application/json' --data-binary @- || true`;
1142
1142
  hookConfigPaths.push(this.setupCodexHooks(terminalId, curlCmd, hookMarker));
1143
1143
  hookConfigPaths.push(this.setupGeminiHooks(terminalId, curlCmd, hookMarker));
1144
1144
  hookConfigPaths.push(this.setupCopilotHooks(terminalId, curlCmd, hookMarker));
@@ -1317,7 +1317,7 @@ export class BridgeSession {
1317
1317
  });
1318
1318
  this.log(`hook server for ${terminalId} (${provider}) listening on port ${port}, marker=${marker}`);
1319
1319
 
1320
- const curlCmd = `curl -s -X POST "http://127.0.0.1:${port}/hook?m=${marker}&lid=$LINKSHELL_ID" -H 'Content-Type: application/json' --data-binary @-`;
1320
+ const curlCmd = `curl -s --connect-timeout 1 --max-time ${Math.ceil((PERMISSION_REQUEST_TIMEOUT_MS + 30_000) / 1000)} -X POST "http://127.0.0.1:${port}/hook?m=${marker}&lid=$LINKSHELL_ID" -H 'Content-Type: application/json' --data-binary @- || true`;
1321
1321
  let configPath: string;
1322
1322
 
1323
1323
  if (provider === "codex") {
@@ -1338,7 +1338,7 @@ export class BridgeSession {
1338
1338
  const term = this.terminals.get(DEFAULT_TERMINAL_ID);
1339
1339
  if (!term?.hookPort) return;
1340
1340
  const marker = term.hookMarker;
1341
- const curlCmd = `curl -s -X POST "http://127.0.0.1:${term.hookPort}/hook?m=${marker}&lid=$LINKSHELL_ID" -H 'Content-Type: application/json' --data-binary @-`;
1341
+ const curlCmd = `curl -s --connect-timeout 1 --max-time ${Math.ceil((PERMISSION_REQUEST_TIMEOUT_MS + 30_000) / 1000)} -X POST "http://127.0.0.1:${term.hookPort}/hook?m=${marker}&lid=$LINKSHELL_ID" -H 'Content-Type: application/json' --data-binary @- || true`;
1342
1342
  const providers = this.options.agentProvider
1343
1343
  ? [normalizeAgentProvider(this.options.agentProvider)]
1344
1344
  : detectAvailableProviders();