wechat-claude-sessions 1.0.1 → 1.2.0-dev.session-naming.6.11ccb2b
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/README.en.md +72 -1
- package/README.md +53 -1
- package/dist/claude-sessions.d.ts +11 -0
- package/dist/claude-sessions.js +100 -0
- package/dist/claude-sessions.js.map +1 -0
- package/dist/cli.js +0 -0
- package/dist/daemon.js +257 -15
- package/dist/daemon.js.map +1 -1
- package/dist/i18n.d.ts +12 -0
- package/dist/i18n.js +30 -0
- package/dist/i18n.js.map +1 -1
- package/dist/nudge.d.ts +2 -0
- package/dist/nudge.js +29 -0
- package/dist/nudge.js.map +1 -0
- package/dist/paths.d.ts +3 -0
- package/dist/paths.js +16 -1
- package/dist/paths.js.map +1 -1
- package/dist/replies.d.ts +3 -0
- package/dist/replies.js +51 -0
- package/dist/replies.js.map +1 -0
- package/dist/routing.js +6 -1
- package/dist/routing.js.map +1 -1
- package/dist/server.js +88 -5
- package/dist/server.js.map +1 -1
- package/dist/sessions.d.ts +12 -0
- package/dist/sessions.js +56 -6
- package/dist/sessions.js.map +1 -1
- package/dist/transcripts.d.ts +9 -0
- package/dist/transcripts.js +71 -0
- package/dist/transcripts.js.map +1 -0
- package/dist/usage.d.ts +33 -0
- package/dist/usage.js +260 -0
- package/dist/usage.js.map +1 -0
- package/dist/watch-inbox.js +18 -1
- package/dist/watch-inbox.js.map +1 -1
- package/package.json +1 -1
- package/templates/wechat.md +17 -8
- package/dist/router.d.ts +0 -31
- package/dist/router.js +0 -339
- package/dist/router.js.map +0 -1
package/README.en.md
CHANGED
|
@@ -85,6 +85,7 @@ Send these from WeChat to control routing:
|
|
|
85
85
|
| `/runs` | List running `/run` task sessions |
|
|
86
86
|
| `/stop <name>` | Kill a `/run` task session (names start with `wc-`) |
|
|
87
87
|
| `/close <number\|name\|pid>` | Close a Claude session remotely — terminates its Claude process (and MCP server) and removes it from the list. Unsaved work in that session is lost. If a name matches several sessions it lists them instead of guessing; `/close <name> all` closes all matches, `/close idle` cleans up every unmonitored session idle for 2+ hours. Every close reply ends with a remaining-session summary |
|
|
88
|
+
| `/usage` | Check whether Claude's usage limit is what's blocking replies. Runs one tiny headless probe (Haiku by default — see below) |
|
|
88
89
|
| `/help` | Show command help |
|
|
89
90
|
| *(no prefix)* | Send to the most recently active **monitoring** session (falls back to most recently active overall) |
|
|
90
91
|
|
|
@@ -92,6 +93,47 @@ Delivery feedback: if a message lands in a session that isn't monitoring its
|
|
|
92
93
|
inbox, the daemon warns you immediately; if a delivered message is still
|
|
93
94
|
unread after 2 minutes, it sends a reminder.
|
|
94
95
|
|
|
96
|
+
### Usage limits (when every session goes quiet)
|
|
97
|
+
|
|
98
|
+
When the Claude account hits its usage limit, **every** session goes silent at
|
|
99
|
+
once: model calls are rejected, so nothing is read and nothing is answered —
|
|
100
|
+
from WeChat that is indistinguishable from a dead daemon. So the daemon works
|
|
101
|
+
it out itself:
|
|
102
|
+
|
|
103
|
+
1. A delivered message with no reply for 90 seconds, **and** a target session
|
|
104
|
+
whose *own* transcript (`~/.claude/projects/….jsonl` — the MCP server records
|
|
105
|
+
the exact path, so a busy neighbour sharing the directory can't mask it)
|
|
106
|
+
hasn't been written for 60 seconds — i.e. it isn't busy, it is stuck —
|
|
107
|
+
triggers one headless probe (`claude -p ok`, with no MCP servers loaded).
|
|
108
|
+
2. If the probe confirms a usage limit, the daemon says so on WeChat with the
|
|
109
|
+
expected reset time, and suppresses the misleading "that session may not be
|
|
110
|
+
monitoring" reminder. Messages you send meanwhile are still delivered, with
|
|
111
|
+
a note attached.
|
|
112
|
+
3. When the limit lifts, the daemon sends a recovery message and gets the
|
|
113
|
+
unanswered work moving: messages still in an inbox only need their watcher
|
|
114
|
+
poked (the original announcement is long gone and never repeats); messages
|
|
115
|
+
Claude *read* but never got to answer are put back in the inbox first, since
|
|
116
|
+
there is nothing left to announce. Only deliveries with no reply are
|
|
117
|
+
replayed, so nothing is handled twice.
|
|
118
|
+
|
|
119
|
+
Probes cost a little quota, so: only one runs at a time; at most one every 5
|
|
120
|
+
minutes while things look healthy; once a limit is confirmed probes are free
|
|
121
|
+
(the request is rejected outright), and a known reset time is waited out.
|
|
122
|
+
|
|
123
|
+
Optional config (`~/.claude/wechat/config.json`):
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{ "probeModel": "claude-haiku-4-5-20251001", "claudeBin": "~/.local/bin/claude" }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- `probeModel` — model used for the probe. Haiku by default: cheap, and
|
|
130
|
+
subscription limits are account-wide, so it is rejected by the same limit.
|
|
131
|
+
Set `"default"` to probe with your own default model — needed if the limit you
|
|
132
|
+
care about is an Opus-only weekly cap.
|
|
133
|
+
- `claudeBin` — path to the `claude` executable, only needed when launchd's
|
|
134
|
+
minimal PATH can't find it (`~/.local/bin`, `~/.claude/local`, Homebrew and
|
|
135
|
+
`/usr/local/bin` are tried).
|
|
136
|
+
|
|
95
137
|
Incoming images are downloaded and decrypted automatically to
|
|
96
138
|
`~/.claude/wechat/media/` (cleaned up after 7 days); the routed message text
|
|
97
139
|
contains the local path (`[图片: /path/to/file.png]`) so the receiving Claude
|
|
@@ -135,7 +177,28 @@ Sessions are automatically named based on the working directory:
|
|
|
135
177
|
- Worktree: `reponame/worktree-name` (e.g., `myapp/feature-x`)
|
|
136
178
|
- Non-git: directory name
|
|
137
179
|
|
|
138
|
-
|
|
180
|
+
To pick a name, pass it when you start monitoring: `/wechat integration`.
|
|
181
|
+
That names the session and starts the watcher in one go; running it again on
|
|
182
|
+
a session that already has that name is a no-op. You can also call
|
|
183
|
+
`wechat_set_session_name` on its own at any time. A name must be a single word
|
|
184
|
+
without whitespace (`/s <name> <msg>` reads one word), must not be purely
|
|
185
|
+
numeric (it would be read as a session number or pid), and must not collide
|
|
186
|
+
with another live session — a collision is refused with the holder's pid
|
|
187
|
+
rather than silently suffixed.
|
|
188
|
+
|
|
189
|
+
**Two namespaces — don't mix them up.** The names above are **WeChat routing
|
|
190
|
+
names**, used only in `/s <name> <msg>`. Claude Code gives every session its
|
|
191
|
+
own, separate name (e.g. `myapp-a9`), which is what other Claude sessions must
|
|
192
|
+
pass to `SendMessage` (see `ListAgents`). `wechat_status` lists both side by
|
|
193
|
+
side in `Active sessions` (the `SendMessage: ...` column), and `/s` accepts the
|
|
194
|
+
Claude Code name as an alias, so whichever name you saw will route.
|
|
195
|
+
|
|
196
|
+
That also makes **relaying** possible: a plain message lands in the default or
|
|
197
|
+
bound session, but you may mean another one ("tell integration to run the
|
|
198
|
+
tests"). The receiving session works out the target from the `Active sessions`
|
|
199
|
+
list (routing name, `SendMessage:` name, or working directory), forwards it
|
|
200
|
+
with `SendMessage`, tells you on WeChat which session it went to and how to
|
|
201
|
+
`/s` it directly next time, and relays the reply back.
|
|
139
202
|
|
|
140
203
|
## File Layout
|
|
141
204
|
|
|
@@ -151,6 +214,11 @@ Use `wechat_set_session_name` to set a custom name.
|
|
|
151
214
|
├── daemon.log # daemon output
|
|
152
215
|
├── cursor.txt # message polling cursor
|
|
153
216
|
├── expired.flag # present when the WeChat login has expired
|
|
217
|
+
├── usage-limit.json # known Claude usage-limit state (incl. notified users)
|
|
218
|
+
├── replies/ # last time each session replied to each WeChat user
|
|
219
|
+
│ └── <pid>--<userId>
|
|
220
|
+
├── nudge/ # signal to re-announce a backlog (after a limit lifts)
|
|
221
|
+
│ └── <pid>
|
|
154
222
|
├── sessions/ # registered Claude Code sessions
|
|
155
223
|
│ └── <pid>.json
|
|
156
224
|
├── inbox/ # per-session message queues
|
|
@@ -204,6 +272,9 @@ server's pid.
|
|
|
204
272
|
4. **MCP Server** reads from its inbox when Claude calls `wechat_get_messages`
|
|
205
273
|
5. Claude processes the message and replies via `wechat_send_text`
|
|
206
274
|
6. The MCP server clears the typing indicator file; the daemon detects this and stops typing
|
|
275
|
+
7. If a message goes unread *and* unanswered for too long, the daemon checks
|
|
276
|
+
whether Claude's usage limit is the cause and explains it on WeChat (see
|
|
277
|
+
[Usage limits](#usage-limits-when-every-session-goes-quiet))
|
|
207
278
|
|
|
208
279
|
## Language
|
|
209
280
|
|
package/README.md
CHANGED
|
@@ -78,12 +78,42 @@ wechat-claude daemon # 前台运行 / 交给你自己的进程管理
|
|
|
78
78
|
| `/runs` | 列出运行中的 `/run` 任务 session |
|
|
79
79
|
| `/stop <名字>` | 终止一个 `/run` 任务 session(名字以 `wc-` 开头) |
|
|
80
80
|
| `/close <编号\|名字\|pid>` | 远程关闭一个 Claude session —— 终结它的 Claude 进程(以及 MCP server)并从列表移除。该 session 里未保存的工作会丢失。如果一个名字匹配到多个,会列出来而不是瞎猜;`/close <名字> all` 关闭全部匹配项,`/close idle` 清理所有闲置 2 小时以上且未被监控的 session。每次关闭的回复末尾都会附上剩余 session 概览 |
|
|
81
|
+
| `/usage` | 查询 Claude 用量是否已达上限(session 集体不回复时用)。会跑一次极小的 headless 探测(默认用 Haiku,见下) |
|
|
81
82
|
| `/help` | 显示命令帮助 |
|
|
82
83
|
| *(无前缀)* | 发给最近活跃的**监控中** session(没有的话退回到最近活跃的那个) |
|
|
83
84
|
|
|
84
85
|
**投递反馈**:如果消息落到了一个没在监控 inbox 的 session,daemon 会立刻警告你;如果一条
|
|
85
86
|
已投递的消息 2 分钟后仍未被读取,它会再发一条提醒。
|
|
86
87
|
|
|
88
|
+
### 用量上限(session 集体不回复)
|
|
89
|
+
|
|
90
|
+
Claude 账号一旦触达用量上限,**所有** session 会同时哑掉:模型调用被拒绝,消息既没人读、
|
|
91
|
+
也没人回,从微信看和 daemon 挂了一模一样。为此 daemon 会自己判断:
|
|
92
|
+
|
|
93
|
+
1. 一条已投递的消息 90 秒没有得到回复,**并且**目标 session 自己的 transcript
|
|
94
|
+
(`~/.claude/projects/…jsonl`,由 MCP server 记下确切路径,不会被同目录下别的 session
|
|
95
|
+
干扰)也 60 秒没有任何写入 —— 即它不是在忙,而是真的停住了 —— daemon 会跑一次 headless
|
|
96
|
+
探测(`claude -p ok`,不加载任何 MCP server)。
|
|
97
|
+
2. 探测确认是用量上限,daemon 会主动在微信里说明情况,附上预计恢复时间,并且不再发那条
|
|
98
|
+
容易误导人的"session 可能没在监控"提醒。期间新发的消息照常投递,但会附一条提示。
|
|
99
|
+
3. 上限解除后,daemon 会再发一条"已恢复",并把没被回答的消息重新推起来:还留在 inbox 里的,
|
|
100
|
+
戳一下让 watcher 重新播报(否则那条播报早过去了);已经被读走、但还没来得及回复的(inbox
|
|
101
|
+
已经被清空,没东西可播报),会先塞回 inbox 再播报。只有确实没得到回复的才会重来,不会重复处理。
|
|
102
|
+
|
|
103
|
+
探测本身要花一点点额度,所以:同一时间只跑一个;正常状态下最多 5 分钟一次;确认受限之后
|
|
104
|
+
探测是免费的(请求被直接拒绝),有明确恢复时间时会等到那个时间点再查。
|
|
105
|
+
|
|
106
|
+
可选配置(`~/.claude/wechat/config.json`):
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{ "probeModel": "claude-haiku-4-5-20251001", "claudeBin": "~/.local/bin/claude" }
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- `probeModel` —— 探测用的模型,默认 Haiku(便宜,且订阅的用量上限是账号级的,拒绝同样会
|
|
113
|
+
发生)。设成 `"default"` 用你自己的默认模型 —— 如果你想抓的是 Opus 专属的周上限,就得这么设。
|
|
114
|
+
- `claudeBin` —— `claude` 可执行文件路径,launchd 环境下 PATH 很干净时才需要(默认会依次
|
|
115
|
+
找 `~/.local/bin`、`~/.claude/local`、Homebrew、`/usr/local/bin`)。
|
|
116
|
+
|
|
87
117
|
**图片**会被自动下载解密到 `~/.claude/wechat/media/`(保留 7 天);路由后的消息文本里带
|
|
88
118
|
本地路径(`[图片: /path/to/file.png]`),接收方的 Claude session 可以直接打开该文件。
|
|
89
119
|
|
|
@@ -122,7 +152,22 @@ Session 会根据工作目录自动命名:
|
|
|
122
152
|
- Worktree:`仓库名/worktree名`(例如 `myapp/feature-x`)
|
|
123
153
|
- 非 Git 目录:目录名
|
|
124
154
|
|
|
125
|
-
|
|
155
|
+
要自定义名字,启动监听时直接带上:`/wechat integration`。这会在同一次调用里完成
|
|
156
|
+
监听和命名;对一个已经叫这个名字的 session 重复执行是 no-op。也可以随时单独调用
|
|
157
|
+
`wechat_set_session_name`。名字必须是不含空格的一个词(`/s <名字> <消息>` 只读一个
|
|
158
|
+
词),不能是纯数字(会被当成编号或 pid),并且不能和另一个活着的 session 重名 ——
|
|
159
|
+
重名会被拒绝并告知占用者的 pid,而不是悄悄加后缀。
|
|
160
|
+
|
|
161
|
+
**两套命名空间,别混用。** 上面这些是**微信路由名**,只用于 `/s <名字> <消息>`。
|
|
162
|
+
Claude Code 自己给每个 session 另有一个名字(例如 `myapp-a9`),那是其他 Claude
|
|
163
|
+
session 用 `SendMessage` 找它时要用的(见 `ListAgents`)。`wechat_status` 的
|
|
164
|
+
`Active sessions` 列表会把两个名字并排列出来(`SendMessage: ...` 那一栏),并且
|
|
165
|
+
`/s` 也接受 Claude Code 名作为别名,所以看到哪个名字都能路由。
|
|
166
|
+
|
|
167
|
+
这也让**转发**成为可能:不带前缀的消息会落到默认或绑定的 session,但你说的可能是另一个
|
|
168
|
+
("让 integration 跑一下测试")。收到消息的 session 会对照 `Active sessions` 列表
|
|
169
|
+
(路由名、`SendMessage:` 名或工作目录)推算出目标,用 `SendMessage` 转过去,在微信里
|
|
170
|
+
告诉你转给了谁、下次怎么直接 `/s` 过去,并把对方的回复转回来。
|
|
126
171
|
|
|
127
172
|
## 文件布局
|
|
128
173
|
|
|
@@ -138,6 +183,11 @@ Session 会根据工作目录自动命名:
|
|
|
138
183
|
├── daemon.log # daemon 输出
|
|
139
184
|
├── cursor.txt # 消息轮询游标
|
|
140
185
|
├── expired.flag # 微信登录过期时存在
|
|
186
|
+
├── usage-limit.json # 已知的 Claude 用量上限状态(含已通知的用户)
|
|
187
|
+
├── replies/ # 各 session 最近一次回复各微信用户的时间戳
|
|
188
|
+
│ └── <pid>--<userId>
|
|
189
|
+
├── nudge/ # 让 watcher 重播积压 inbox 的信号(上限解除后)
|
|
190
|
+
│ └── <pid>
|
|
141
191
|
├── sessions/ # 已注册的 Claude Code session
|
|
142
192
|
│ └── <pid>.json
|
|
143
193
|
├── inbox/ # 各 session 的消息队列
|
|
@@ -189,6 +239,8 @@ wechat-claude daemon restart
|
|
|
189
239
|
4. **MCP Server** 在 Claude 调用 `wechat_get_messages` 时读取自己的 inbox
|
|
190
240
|
5. Claude 处理消息并通过 `wechat_send_text` 回复
|
|
191
241
|
6. MCP server 清除输入状态文件,daemon 检测到后停止"正在输入"
|
|
242
|
+
7. 如果长时间既没被读也没被回,daemon 会检查是不是撞上了 Claude 用量上限,并在微信里说明
|
|
243
|
+
(见[用量上限](#用量上限session-集体不回复))
|
|
192
244
|
|
|
193
245
|
## 语言
|
|
194
246
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const CLAUDE_SESSIONS_DIR: string;
|
|
2
|
+
export type ClaudeSessionRecord = {
|
|
3
|
+
pid: number;
|
|
4
|
+
name: string;
|
|
5
|
+
sessionId?: string;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function readClaudeSession(claudePid: number, sessionsDir?: string): ClaudeSessionRecord | undefined;
|
|
9
|
+
export declare function ownClaudeSessionName(claudePid: number, claudeSessionId: string | undefined, sessionsDir?: string): string | undefined;
|
|
10
|
+
export declare function parentPids(pids: number[]): Map<number, number>;
|
|
11
|
+
export declare function claudeNameForMcpPid(mcpPid: number, parents: Map<number, number>, sessionsDir?: string): string | undefined;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Claude Code keeps its own registry of live sessions at
|
|
2
|
+
// ~/.claude/sessions/<claude pid>.json. Among other things it records the
|
|
3
|
+
// name other Claude sessions use to reach this one via SendMessage/ListAgents
|
|
4
|
+
// (e.g. "fintary-a9"). That name is a different namespace from the WeChat
|
|
5
|
+
// routing name in ~/.claude/wechat/sessions — the two look alike, and an agent
|
|
6
|
+
// that reads one list will happily use those names against the other tool.
|
|
7
|
+
// Surfacing both side by side is the fix; this module reads the Claude side.
|
|
8
|
+
//
|
|
9
|
+
// An MCP server is spawned by Claude Code, so its parent pid is the Claude
|
|
10
|
+
// pid: process.ppid for ourselves, `ps` for other sessions. That link is
|
|
11
|
+
// exact. Matching by working directory is not — a Claude session can move into
|
|
12
|
+
// a worktree after its MCP server started — so it is deliberately not used.
|
|
13
|
+
//
|
|
14
|
+
// The file format is Claude Code's, not ours: read defensively and return
|
|
15
|
+
// undefined for anything that doesn't look right.
|
|
16
|
+
import { spawnSync } from "node:child_process";
|
|
17
|
+
import fs from "node:fs";
|
|
18
|
+
import os from "node:os";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
export const CLAUDE_SESSIONS_DIR = path.join(os.homedir(), ".claude", "sessions");
|
|
21
|
+
export function readClaudeSession(claudePid, sessionsDir = CLAUDE_SESSIONS_DIR) {
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = JSON.parse(fs.readFileSync(path.join(sessionsDir, `${claudePid}.json`), "utf-8"));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
30
|
+
return undefined;
|
|
31
|
+
const rec = parsed;
|
|
32
|
+
if (typeof rec.name !== "string" || rec.name.trim() === "")
|
|
33
|
+
return undefined;
|
|
34
|
+
if (rec.pid !== undefined && rec.pid !== claudePid)
|
|
35
|
+
return undefined;
|
|
36
|
+
return {
|
|
37
|
+
pid: claudePid,
|
|
38
|
+
name: rec.name,
|
|
39
|
+
sessionId: typeof rec.sessionId === "string" ? rec.sessionId : undefined,
|
|
40
|
+
cwd: typeof rec.cwd === "string" ? rec.cwd : undefined,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// The cross-session name of the Claude Code process that owns an MCP server
|
|
44
|
+
// (its process.ppid), or undefined when it can't be established. When Claude
|
|
45
|
+
// Code told us its session id (CLAUDE_CODE_SESSION_ID), a record with a
|
|
46
|
+
// different id is rejected — pids get reused, and a stale file must not lend
|
|
47
|
+
// us a stranger's name. Callers pass the process values explicitly; defaults
|
|
48
|
+
// here would silently kick back in whenever a caller passes undefined.
|
|
49
|
+
export function ownClaudeSessionName(claudePid, claudeSessionId, sessionsDir = CLAUDE_SESSIONS_DIR) {
|
|
50
|
+
const rec = readClaudeSession(claudePid, sessionsDir);
|
|
51
|
+
if (!rec)
|
|
52
|
+
return undefined;
|
|
53
|
+
if (claudeSessionId && rec.sessionId && rec.sessionId !== claudeSessionId) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
return rec.name;
|
|
57
|
+
}
|
|
58
|
+
// Largest pid any supported platform hands out (Linux pid_max ceiling; macOS
|
|
59
|
+
// stops at 99999). macOS `ps` rejects the whole request over one oversized pid.
|
|
60
|
+
const MAX_PID = 4_194_304;
|
|
61
|
+
function psParents(pids, out) {
|
|
62
|
+
const res = spawnSync("ps", ["-o", "pid=,ppid=", "-p", pids.join(",")], {
|
|
63
|
+
encoding: "utf-8",
|
|
64
|
+
});
|
|
65
|
+
if (typeof res.stdout !== "string")
|
|
66
|
+
return false;
|
|
67
|
+
let any = false;
|
|
68
|
+
for (const line of res.stdout.split("\n")) {
|
|
69
|
+
const m = line.trim().match(/^(\d+)\s+(\d+)$/);
|
|
70
|
+
if (m) {
|
|
71
|
+
out.set(Number(m[1]), Number(m[2]));
|
|
72
|
+
any = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return any;
|
|
76
|
+
}
|
|
77
|
+
// Parent pid of each given pid, normally in one `ps` call (argv array, no
|
|
78
|
+
// shell). Pids that are gone, or a failing `ps`, are simply absent from the
|
|
79
|
+
// result. If a batch comes back empty (one bad pid can sink the whole call on
|
|
80
|
+
// some platforms) the pids are retried one at a time.
|
|
81
|
+
export function parentPids(pids) {
|
|
82
|
+
const out = new Map();
|
|
83
|
+
const wanted = pids.filter((p) => Number.isInteger(p) && p > 0 && p <= MAX_PID);
|
|
84
|
+
if (wanted.length === 0)
|
|
85
|
+
return out;
|
|
86
|
+
if (!psParents(wanted, out) && wanted.length > 1) {
|
|
87
|
+
for (const p of wanted)
|
|
88
|
+
psParents([p], out);
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
// Claude Code name of the session whose MCP server has pid `mcpPid`, for
|
|
93
|
+
// sessions that did not record it themselves (registered by an older build).
|
|
94
|
+
export function claudeNameForMcpPid(mcpPid, parents, sessionsDir = CLAUDE_SESSIONS_DIR) {
|
|
95
|
+
const claudePid = parents.get(mcpPid);
|
|
96
|
+
if (claudePid === undefined)
|
|
97
|
+
return undefined;
|
|
98
|
+
return readClaudeSession(claudePid, sessionsDir)?.name;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=claude-sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-sessions.js","sourceRoot":"","sources":["../src/claude-sessions.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
File without changes
|