sessix-server 0.2.3 → 0.2.5

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/dist/index.js CHANGED
@@ -1113,6 +1113,7 @@ var SessionManager = class {
1113
1113
  }
1114
1114
  /**
1115
1115
  * 刷新缓冲的 assistant 事件,批量发送
1116
+ * Public:subscribe 时需要在读取缓冲区前先刷出,避免事件同时出现在 session_history 和广播中
1116
1117
  */
1117
1118
  flushPendingAssistant(sessionId) {
1118
1119
  const pending = this.pendingAssistantEvents.get(sessionId);
@@ -2038,7 +2039,13 @@ var MdnsService = class {
2038
2039
  return;
2039
2040
  }
2040
2041
  const lanAddrs = getLanAddresses();
2041
- this.bonjour = lanAddrs.length > 0 ? new import_bonjour_service.default({ interface: lanAddrs[0] }) : new import_bonjour_service.default();
2042
+ const onMdnsError = (err) => {
2043
+ console.warn(`[MdnsService] mDNS error (non-fatal): ${err.message}`);
2044
+ this.stop();
2045
+ };
2046
+ const opts = lanAddrs.length > 0 ? { interface: lanAddrs[0] } : {};
2047
+ this.bonjour = new import_bonjour_service.default(opts, onMdnsError);
2048
+ this.bonjour.server?.mdns?.on("error", onMdnsError);
2042
2049
  if (lanAddrs.length > 0) {
2043
2050
  console.log(`[MdnsService] ${t("mdns.boundInterface", { ip: lanAddrs[0] })}`);
2044
2051
  }
@@ -2386,7 +2393,7 @@ var NotificationService = class {
2386
2393
  const title = pendingCount > 1 ? t("notification.pendingApprovals", { title: sessionTitle, count: pendingCount }) : sessionTitle;
2387
2394
  const body = pendingCount > 1 ? `\u{1F527} \u6700\u65B0: ${request.toolName}: ${request.description}` : `\u{1F527} ${request.toolName}: ${request.description}`;
2388
2395
  if (this.activityPushChannel?.hasToken(request.sessionId)) {
2389
- const dangerLevel = this.getDangerLevel(request.toolName);
2396
+ const dangerLevel2 = this.getDangerLevel(request.toolName);
2390
2397
  const isYoloMode = this.getYoloMode(request.sessionId);
2391
2398
  this.activityPushChannel.updateActivityWithAlert(
2392
2399
  request.sessionId,
@@ -2398,7 +2405,7 @@ var NotificationService = class {
2398
2405
  requestId: request.id,
2399
2406
  toolName: request.toolName,
2400
2407
  description: request.description.slice(0, 80),
2401
- dangerLevel,
2408
+ dangerLevel: dangerLevel2,
2402
2409
  pendingCount
2403
2410
  },
2404
2411
  isYoloMode,
@@ -2408,15 +2415,28 @@ var NotificationService = class {
2408
2415
  );
2409
2416
  return;
2410
2417
  }
2418
+ const dangerLevel = this.getDangerLevel(request.toolName);
2419
+ const isDangerous = dangerLevel === "danger" || dangerLevel === "write";
2420
+ const categoryId = isDangerous ? "APPROVAL_DANGEROUS" : "APPROVAL_NORMAL";
2421
+ const projectName = (0, import_node_path3.basename)(
2422
+ this.sessionManager.getActiveSessions().find((s) => s.id === request.sessionId)?.projectPath ?? ""
2423
+ );
2424
+ const pushTitle = isDangerous ? `\u26A0\uFE0F ${title}` : title;
2425
+ const subtitle = `\u{1F527} ${request.toolName}: ${this.extractTarget(request)}`;
2411
2426
  this.notify({
2412
- title,
2427
+ title: pushTitle,
2428
+ subtitle,
2413
2429
  body,
2414
2430
  sound: "default",
2415
2431
  badge: this.getGlobalPendingCount(),
2432
+ categoryId,
2416
2433
  data: {
2417
2434
  type: "approval_request",
2418
2435
  sessionId: request.sessionId,
2419
- requestId: request.id
2436
+ requestId: request.id,
2437
+ toolName: request.toolName,
2438
+ projectName,
2439
+ dangerLevel
2420
2440
  }
2421
2441
  });
2422
2442
  }
@@ -2451,6 +2471,13 @@ var NotificationService = class {
2451
2471
  }
2452
2472
  });
2453
2473
  }
2474
+ /** 从审批请求中提取操作目标的简短描述 */
2475
+ extractTarget(request) {
2476
+ const input = request.toolInput;
2477
+ if (input.file_path) return (0, import_node_path3.basename)(String(input.file_path));
2478
+ if (input.command) return String(input.command).slice(0, 40);
2479
+ return request.description.slice(0, 40);
2480
+ }
2454
2481
  /** 简单的工具危险等级判断 */
2455
2482
  getDangerLevel(toolName) {
2456
2483
  if (toolName === "Bash") return "danger";
@@ -2630,9 +2657,11 @@ var ExpoNotificationChannel = class {
2630
2657
  return {
2631
2658
  to,
2632
2659
  title: payload.title,
2660
+ subtitle: payload.subtitle,
2633
2661
  body: payload.body,
2634
2662
  badge: payload.badge,
2635
2663
  sound: pushSound,
2664
+ categoryId: payload.categoryId,
2636
2665
  data: payload.data ?? {}
2637
2666
  };
2638
2667
  });
@@ -3495,7 +3524,8 @@ async function start(opts = {}) {
3495
3524
  type: "session_list",
3496
3525
  sessions: sessionManager.getActiveSessions()
3497
3526
  });
3498
- const bufferedEvents = sessionManager.getSessionEvents(event.sessionId);
3527
+ sessionManager.flushPendingAssistant(event.sessionId);
3528
+ const bufferedEvents = [...sessionManager.getSessionEvents(event.sessionId)];
3499
3529
  if (sessionManager.isBufferTruncated(event.sessionId)) {
3500
3530
  const projectPath = sessionManager.getSessionProjectPath(event.sessionId);
3501
3531
  if (projectPath) {
package/dist/server.js CHANGED
@@ -1119,6 +1119,7 @@ var SessionManager = class {
1119
1119
  }
1120
1120
  /**
1121
1121
  * 刷新缓冲的 assistant 事件,批量发送
1122
+ * Public:subscribe 时需要在读取缓冲区前先刷出,避免事件同时出现在 session_history 和广播中
1122
1123
  */
1123
1124
  flushPendingAssistant(sessionId) {
1124
1125
  const pending = this.pendingAssistantEvents.get(sessionId);
@@ -2044,7 +2045,13 @@ var MdnsService = class {
2044
2045
  return;
2045
2046
  }
2046
2047
  const lanAddrs = getLanAddresses();
2047
- this.bonjour = lanAddrs.length > 0 ? new import_bonjour_service.default({ interface: lanAddrs[0] }) : new import_bonjour_service.default();
2048
+ const onMdnsError = (err) => {
2049
+ console.warn(`[MdnsService] mDNS error (non-fatal): ${err.message}`);
2050
+ this.stop();
2051
+ };
2052
+ const opts = lanAddrs.length > 0 ? { interface: lanAddrs[0] } : {};
2053
+ this.bonjour = new import_bonjour_service.default(opts, onMdnsError);
2054
+ this.bonjour.server?.mdns?.on("error", onMdnsError);
2048
2055
  if (lanAddrs.length > 0) {
2049
2056
  console.log(`[MdnsService] ${t("mdns.boundInterface", { ip: lanAddrs[0] })}`);
2050
2057
  }
@@ -2392,7 +2399,7 @@ var NotificationService = class {
2392
2399
  const title = pendingCount > 1 ? t("notification.pendingApprovals", { title: sessionTitle, count: pendingCount }) : sessionTitle;
2393
2400
  const body = pendingCount > 1 ? `\u{1F527} \u6700\u65B0: ${request.toolName}: ${request.description}` : `\u{1F527} ${request.toolName}: ${request.description}`;
2394
2401
  if (this.activityPushChannel?.hasToken(request.sessionId)) {
2395
- const dangerLevel = this.getDangerLevel(request.toolName);
2402
+ const dangerLevel2 = this.getDangerLevel(request.toolName);
2396
2403
  const isYoloMode = this.getYoloMode(request.sessionId);
2397
2404
  this.activityPushChannel.updateActivityWithAlert(
2398
2405
  request.sessionId,
@@ -2404,7 +2411,7 @@ var NotificationService = class {
2404
2411
  requestId: request.id,
2405
2412
  toolName: request.toolName,
2406
2413
  description: request.description.slice(0, 80),
2407
- dangerLevel,
2414
+ dangerLevel: dangerLevel2,
2408
2415
  pendingCount
2409
2416
  },
2410
2417
  isYoloMode,
@@ -2414,15 +2421,28 @@ var NotificationService = class {
2414
2421
  );
2415
2422
  return;
2416
2423
  }
2424
+ const dangerLevel = this.getDangerLevel(request.toolName);
2425
+ const isDangerous = dangerLevel === "danger" || dangerLevel === "write";
2426
+ const categoryId = isDangerous ? "APPROVAL_DANGEROUS" : "APPROVAL_NORMAL";
2427
+ const projectName = (0, import_node_path3.basename)(
2428
+ this.sessionManager.getActiveSessions().find((s) => s.id === request.sessionId)?.projectPath ?? ""
2429
+ );
2430
+ const pushTitle = isDangerous ? `\u26A0\uFE0F ${title}` : title;
2431
+ const subtitle = `\u{1F527} ${request.toolName}: ${this.extractTarget(request)}`;
2417
2432
  this.notify({
2418
- title,
2433
+ title: pushTitle,
2434
+ subtitle,
2419
2435
  body,
2420
2436
  sound: "default",
2421
2437
  badge: this.getGlobalPendingCount(),
2438
+ categoryId,
2422
2439
  data: {
2423
2440
  type: "approval_request",
2424
2441
  sessionId: request.sessionId,
2425
- requestId: request.id
2442
+ requestId: request.id,
2443
+ toolName: request.toolName,
2444
+ projectName,
2445
+ dangerLevel
2426
2446
  }
2427
2447
  });
2428
2448
  }
@@ -2457,6 +2477,13 @@ var NotificationService = class {
2457
2477
  }
2458
2478
  });
2459
2479
  }
2480
+ /** 从审批请求中提取操作目标的简短描述 */
2481
+ extractTarget(request) {
2482
+ const input = request.toolInput;
2483
+ if (input.file_path) return (0, import_node_path3.basename)(String(input.file_path));
2484
+ if (input.command) return String(input.command).slice(0, 40);
2485
+ return request.description.slice(0, 40);
2486
+ }
2460
2487
  /** 简单的工具危险等级判断 */
2461
2488
  getDangerLevel(toolName) {
2462
2489
  if (toolName === "Bash") return "danger";
@@ -2636,9 +2663,11 @@ var ExpoNotificationChannel = class {
2636
2663
  return {
2637
2664
  to,
2638
2665
  title: payload.title,
2666
+ subtitle: payload.subtitle,
2639
2667
  body: payload.body,
2640
2668
  badge: payload.badge,
2641
2669
  sound: pushSound,
2670
+ categoryId: payload.categoryId,
2642
2671
  data: payload.data ?? {}
2643
2672
  };
2644
2673
  });
@@ -3501,7 +3530,8 @@ async function start(opts = {}) {
3501
3530
  type: "session_list",
3502
3531
  sessions: sessionManager.getActiveSessions()
3503
3532
  });
3504
- const bufferedEvents = sessionManager.getSessionEvents(event.sessionId);
3533
+ sessionManager.flushPendingAssistant(event.sessionId);
3534
+ const bufferedEvents = [...sessionManager.getSessionEvents(event.sessionId)];
3505
3535
  if (sessionManager.isBufferTruncated(event.sessionId)) {
3506
3536
  const projectPath = sessionManager.getSessionProjectPath(event.sessionId);
3507
3537
  if (projectPath) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sessix-server",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "bin": {
5
5
  "sessix-server": "./dist/index.js"
6
6
  },