@wu529778790/open-im 1.10.9-beta.5 → 1.10.9-beta.6

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.
@@ -13,6 +13,7 @@ interface ClaudeSessionMeta {
13
13
  sessionId: string;
14
14
  mtime: number;
15
15
  filePath: string;
16
+ size: number;
16
17
  }
17
18
  /**
18
19
  * 扫描 ~/.claude/projects/<encoded-path>/ 找到最新的 CLI session。
@@ -9,7 +9,7 @@
9
9
  * 认证:ANTHROPIC_API_KEY 或 CLAUDE_CODE_OAUTH_TOKEN
10
10
  */
11
11
  import { unstable_v2_createSession, unstable_v2_resumeSession } from '@anthropic-ai/claude-agent-sdk';
12
- import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
12
+ import { existsSync, readFileSync, readdirSync, statSync, openSync, readSync, closeSync } from 'fs';
13
13
  import { execSync } from 'child_process';
14
14
  import { homedir } from 'os';
15
15
  import { join } from 'path';
@@ -53,17 +53,19 @@ loadUserPluginSettings();
53
53
  * ~/.claude/projects/-Users-mac-github-open-im/
54
54
  */
55
55
  function workDirToProjectPath(workDir) {
56
- // Claude Code 使用路径中的 / 替换为 -,去掉开头的 -
56
+ // Claude Code 将路径中的 / 替换为 -,leading - 保留
57
57
  // /Users/mac/github/open-im → -Users-mac-github-open-im
58
58
  return workDir.replace(/\//g, '-');
59
59
  }
60
60
  /**
61
- * 检查 CLI 进程是否正在使用某个 session(通过 /proc 或 ps 检测)
61
+ * 检查 CLI 进程是否正在使用某个 session(通过 ps 检测)
62
+ * 注意:仅支持 macOS/Linux,Windows 上会静默返回 false
62
63
  */
63
64
  function isCliSessionActive(sessionId) {
64
65
  try {
65
- // macOS: 用 ps 搜索包含该 sessionId 的 claude 进程
66
- const result = execSync(`ps -axo pid,command 2>/dev/null | grep -v grep | grep "claude" | grep "${sessionId}" || true`, { encoding: 'utf-8', timeout: 3000 });
66
+ // macOS/Linux: 用 ps 搜索包含该 sessionId 的 claude 进程
67
+ // -F 固定字符串匹配,避免正则意外;-- 防止 sessionId 被误认为 flag
68
+ const result = execSync(`ps -axo pid,command 2>/dev/null | grep -v grep | grep "claude" | grep -F -- "${sessionId}" || true`, { encoding: 'utf-8', timeout: 3000 });
67
69
  return result.trim().length > 0;
68
70
  }
69
71
  catch {
@@ -98,7 +100,7 @@ export function findLatestClaudeSession(workDir, homeOverride) {
98
100
  // 跳过空文件
99
101
  if (stat.size === 0)
100
102
  continue;
101
- sessions.push({ sessionId, mtime: stat.mtimeMs, filePath });
103
+ sessions.push({ sessionId, mtime: stat.mtimeMs, filePath, size: stat.size });
102
104
  }
103
105
  catch {
104
106
  continue;
@@ -111,7 +113,7 @@ export function findLatestClaudeSession(workDir, homeOverride) {
111
113
  // 按修改时间倒序,最新的在前
112
114
  sessions.sort((a, b) => b.mtime - a.mtime);
113
115
  const latest = sessions[0];
114
- log.info(`Found latest Claude Code session: ${latest.sessionId} (mtime: ${new Date(latest.mtime).toISOString()}, size: ${statSync(latest.filePath).size})`);
116
+ log.info(`Found latest Claude Code session: ${latest.sessionId} (mtime: ${new Date(latest.mtime).toISOString()}, size: ${latest.size})`);
115
117
  return latest;
116
118
  }
117
119
  catch (err) {
@@ -121,11 +123,17 @@ export function findLatestClaudeSession(workDir, homeOverride) {
121
123
  }
122
124
  /**
123
125
  * 从 JSONL 文件的第一行提取 sessionId,验证文件内容与文件名一致。
126
+ * 只读取前 4KB,避免大文件全量读入内存。
124
127
  */
125
128
  function validateSessionFile(filePath, expectedSessionId) {
129
+ let fd;
126
130
  try {
127
- const content = readFileSync(filePath, 'utf-8');
128
- const firstLine = content.split('\n')[0];
131
+ fd = openSync(filePath, 'r');
132
+ const buf = Buffer.alloc(4096);
133
+ const bytesRead = readSync(fd, buf, 0, 4096, 0);
134
+ if (bytesRead === 0)
135
+ return false;
136
+ const firstLine = buf.toString('utf-8', 0, bytesRead).split('\n')[0];
129
137
  if (!firstLine)
130
138
  return false;
131
139
  const firstEntry = JSON.parse(firstLine);
@@ -134,6 +142,14 @@ function validateSessionFile(filePath, expectedSessionId) {
134
142
  catch {
135
143
  return false;
136
144
  }
145
+ finally {
146
+ if (fd !== undefined) {
147
+ try {
148
+ closeSync(fd);
149
+ }
150
+ catch { /* ignore */ }
151
+ }
152
+ }
137
153
  }
138
154
  // 存储所有活跃的 SDKSession 对象,key 为 sessionId
139
155
  // 使用 Map 而不是 Set,因为我们需要通过 sessionId 获取 session
@@ -357,7 +373,7 @@ async function getOrCreateSession(sessionId, workDir, model, permissionMode, onS
357
373
  return { session, sessionId: latest.sessionId };
358
374
  }
359
375
  catch (err) {
360
- log.warn(`Failed to auto-resume CLI session ${latest.sessionId}, creating new one: ${err}`);
376
+ log.warn(`Failed to auto-resume CLI session ${latest.sessionId}, skipping auto-resume: ${err}`);
361
377
  }
362
378
  }
363
379
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.10.9-beta.5",
3
+ "version": "1.10.9-beta.6",
4
4
  "description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, CodeBuddy)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",