botmux 2.24.4 → 2.25.0
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 +4 -2
- package/README.md +4 -2
- package/dist/adapters/cli/claude-code.js +1 -1
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/shared-hints.js +2 -2
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/cli/arg-utils.d.ts +11 -0
- package/dist/cli/arg-utils.d.ts.map +1 -0
- package/dist/cli/arg-utils.js +25 -0
- package/dist/cli/arg-utils.js.map +1 -0
- package/dist/cli/quoted-render.d.ts +30 -0
- package/dist/cli/quoted-render.d.ts.map +1 -0
- package/dist/cli/quoted-render.js +29 -0
- package/dist/cli/quoted-render.js.map +1 -0
- package/dist/cli.js +63 -14
- package/dist/cli.js.map +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +34 -19
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +13 -4
- package/dist/daemon.js.map +1 -1
- package/dist/im/lark/client.d.ts +1 -1
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +8 -5
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/md-card.d.ts +21 -0
- package/dist/im/lark/md-card.d.ts.map +1 -1
- package/dist/im/lark/md-card.js +63 -0
- package/dist/im/lark/md-card.js.map +1 -1
- package/dist/im/lark/message-parser.d.ts +9 -3
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +13 -5
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/quote-hint.d.ts +18 -0
- package/dist/im/lark/quote-hint.d.ts.map +1 -0
- package/dist/im/lark/quote-hint.js +23 -0
- package/dist/im/lark/quote-hint.js.map +1 -0
- package/dist/services/coco-transcript.d.ts +11 -8
- package/dist/services/coco-transcript.d.ts.map +1 -1
- package/dist/services/coco-transcript.js +77 -40
- package/dist/services/coco-transcript.js.map +1 -1
- package/dist/services/codex-transcript.d.ts +26 -10
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js +95 -30
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/skills/definitions.d.ts +4 -0
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +69 -12
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/installer.d.ts +3 -1
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +18 -3
- package/dist/skills/installer.js.map +1 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +1 -1
- package/dist/worker.js +78 -40
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reader for CoCo's per-session events JSONL.
|
|
3
3
|
*
|
|
4
|
-
* CoCo
|
|
5
|
-
* ~/.cache/coco/sessions/<sessionId>/events.jsonl
|
|
4
|
+
* CoCo (Rust, 用 `dirs` crate 选 cache dir) 的会话路径按平台分叉:
|
|
5
|
+
* Linux: ~/.cache/coco/sessions/<sessionId>/events.jsonl
|
|
6
|
+
* macOS: ~/Library/Caches/coco/sessions/<sessionId>/events.jsonl
|
|
7
|
+
* Windows 这里不考虑(botmux 跟 tmux 强绑,跑不了 Windows)。
|
|
6
8
|
*
|
|
7
9
|
* The bridge fallback only needs the original user prompt and the final
|
|
8
10
|
* assistant message. Those appear as event objects containing
|
|
@@ -12,62 +14,97 @@
|
|
|
12
14
|
* turn fingerprints against the user's prompt, not injected context.
|
|
13
15
|
*/
|
|
14
16
|
import { existsSync, statSync, openSync, readSync, closeSync, readdirSync, readlinkSync } from 'node:fs';
|
|
15
|
-
import {
|
|
17
|
+
import { execSync } from 'node:child_process';
|
|
18
|
+
import { homedir, platform } from 'node:os';
|
|
16
19
|
import { join } from 'node:path';
|
|
17
|
-
|
|
20
|
+
// macOS 上 Rust `dirs` crate 把 cache 放在 ~/Library/Caches/,跟 Linux 的
|
|
21
|
+
// ~/.cache 不同。这里硬编码两条平台路径,对不上的话 adopt 完全读不到
|
|
22
|
+
// events.jsonl(user-visible: Lark 收不到模型回复)。
|
|
23
|
+
const COCO_SESSIONS_ROOT = platform() === 'darwin'
|
|
24
|
+
? join(homedir(), 'Library', 'Caches', 'coco', 'sessions')
|
|
25
|
+
: join(homedir(), '.cache', 'coco', 'sessions');
|
|
18
26
|
const SESSION_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
27
|
+
const IS_LINUX = platform() === 'linux';
|
|
28
|
+
// substring anchor —— 同时匹配 Linux 的 `/.cache/coco/sessions/` 和 macOS 的
|
|
29
|
+
// `/Library/Caches/coco/sessions/` 两种路径形态。anchor 后紧跟一段 UUID 才认
|
|
30
|
+
// 账(matchCocoSessionPath 里 SESSION_UUID_RE 校验),避免误命中。
|
|
31
|
+
const COCO_SESSIONS_ANCHOR = '/coco/sessions/';
|
|
19
32
|
export function cocoEventsPathForSession(sessionId) {
|
|
20
33
|
return join(COCO_SESSIONS_ROOT, sessionId, 'events.jsonl');
|
|
21
34
|
}
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* CoCo opens-writes-closes `events.jsonl` per event, so we
|
|
25
|
-
* file under the session dir — `session.log` and
|
|
26
|
-
* open for the session's lifetime and reveal the
|
|
35
|
+
/** Find which CoCo session a running CoCo process is bound to by scanning
|
|
36
|
+
* its open file handles. Unlike Codex (which keeps its rollout fd open
|
|
37
|
+
* continuously), CoCo opens-writes-closes `events.jsonl` per event, so we
|
|
38
|
+
* look for ANY open file under the session dir — `session.log` and
|
|
39
|
+
* `traces.jsonl` are held open for the session's lifetime and reveal the
|
|
40
|
+
* same `<sid>` segment.
|
|
27
41
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
42
|
+
* Linux: `/proc/<pid>/fd` 快路径,procfs 会把 unlinked-but-open 的 fd 标
|
|
43
|
+
* ` (deleted)`,跳过它们以免读到失效 inode(曾被 e2e 清理触发)。
|
|
44
|
+
* macOS / BSD: `lsof -p <pid> -Fn` 兜底。macOS 上 lsof 不给 deleted 标记,
|
|
45
|
+
* 但 worker 端在 `codexBridgeAttach` 之前还有 `existsSync(sessionDir)` 的
|
|
46
|
+
* 二次校验,所以这里不会让一个失效 sid 跑死循环。 */
|
|
31
47
|
export function findCocoSessionByPid(pid) {
|
|
32
48
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
33
49
|
return undefined;
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
50
|
+
if (IS_LINUX) {
|
|
51
|
+
const fdDir = `/proc/${pid}/fd`;
|
|
52
|
+
if (existsSync(fdDir)) {
|
|
53
|
+
let entries;
|
|
54
|
+
try {
|
|
55
|
+
entries = readdirSync(fdDir);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
for (const fd of entries) {
|
|
61
|
+
let target;
|
|
62
|
+
try {
|
|
63
|
+
target = readlinkSync(join(fdDir, fd));
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// procfs 标 deleted 的 fd 跳过 —— 后面 lsof 路径上没这个保护,因
|
|
69
|
+
// 为 macOS lsof 不给标记;worker 端 sessionDir existsSync 兜底。
|
|
70
|
+
if (target.endsWith(' (deleted)'))
|
|
71
|
+
continue;
|
|
72
|
+
const hit = matchCocoSessionPath(target);
|
|
73
|
+
if (hit)
|
|
74
|
+
return hit;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
let out;
|
|
40
80
|
try {
|
|
41
|
-
|
|
81
|
+
out = execSync(`lsof -p ${pid} -Fn`, {
|
|
82
|
+
encoding: 'utf-8',
|
|
83
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
84
|
+
});
|
|
42
85
|
}
|
|
43
86
|
catch {
|
|
44
87
|
return undefined;
|
|
45
88
|
}
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
let target;
|
|
49
|
-
try {
|
|
50
|
-
target = readlinkSync(join(fdDir, fd));
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
89
|
+
for (const line of out.split('\n')) {
|
|
90
|
+
if (!line.startsWith('n/'))
|
|
53
91
|
continue;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// CoCo writes to a dangling inode — empirically observed when an e2e
|
|
59
|
-
// test wiped the session dir without restarting CoCo.
|
|
60
|
-
if (target.endsWith(' (deleted)'))
|
|
61
|
-
continue;
|
|
62
|
-
if (!target.startsWith(prefix))
|
|
63
|
-
continue;
|
|
64
|
-
const sid = target.slice(prefix.length).split('/')[0];
|
|
65
|
-
if (sid && SESSION_UUID_RE.test(sid)) {
|
|
66
|
-
return { sessionId: sid, eventsPath: cocoEventsPathForSession(sid) };
|
|
67
|
-
}
|
|
92
|
+
const target = line.slice(1);
|
|
93
|
+
const hit = matchCocoSessionPath(target);
|
|
94
|
+
if (hit)
|
|
95
|
+
return hit;
|
|
68
96
|
}
|
|
69
97
|
return undefined;
|
|
70
98
|
}
|
|
99
|
+
function matchCocoSessionPath(target) {
|
|
100
|
+
const idx = target.indexOf(COCO_SESSIONS_ANCHOR);
|
|
101
|
+
if (idx < 0)
|
|
102
|
+
return undefined;
|
|
103
|
+
const sid = target.slice(idx + COCO_SESSIONS_ANCHOR.length).split('/')[0];
|
|
104
|
+
if (!sid || !SESSION_UUID_RE.test(sid))
|
|
105
|
+
return undefined;
|
|
106
|
+
return { sessionId: sid, eventsPath: cocoEventsPathForSession(sid) };
|
|
107
|
+
}
|
|
71
108
|
function messageText(content) {
|
|
72
109
|
return typeof content === 'string' ? content : '';
|
|
73
110
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coco-transcript.js","sourceRoot":"","sources":["../../src/services/coco-transcript.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"coco-transcript.js","sourceRoot":"","sources":["../../src/services/coco-transcript.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,17 +4,16 @@
|
|
|
4
4
|
* contains its own dashes that would otherwise let a greedy match swallow
|
|
5
5
|
* parts of the sid. Returns undefined for paths that don't match. */
|
|
6
6
|
export declare function codexSessionIdFromRolloutPath(path: string): string | undefined;
|
|
7
|
-
/** Find the rollout file an externally-running Codex process has open
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
/** Find the rollout file an externally-running Codex process has open. The
|
|
8
|
+
* Codex process keeps fd open on its current rollout for the entire
|
|
9
|
+
* lifetime of the session, so this is the authoritative way to bind a
|
|
10
|
+
* Codex pid to its sessionId — far more reliable than scanning
|
|
11
|
+
* `~/.codex/sessions` by mtime (which would race with sibling Codex panes
|
|
12
|
+
* in the same project).
|
|
13
13
|
*
|
|
14
|
-
* Linux
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* /adopt, which already runs on Linux servers in practice. */
|
|
14
|
+
* Linux: `/proc/<pid>/fd/*` fast path.
|
|
15
|
+
* macOS / BSD: `lsof -p <pid> -Fn` 兜底(同 session-discovery 里的 readCwd)。
|
|
16
|
+
* 两种平台都用 `codexSessionIdFromRolloutPath` 提取 sid。 */
|
|
18
17
|
export declare function findCodexRolloutByPid(pid: number): {
|
|
19
18
|
path: string;
|
|
20
19
|
cliSessionId: string;
|
|
@@ -35,6 +34,23 @@ export interface CodexBridgeEvent {
|
|
|
35
34
|
* user, output_text for assistant). */
|
|
36
35
|
text: string;
|
|
37
36
|
}
|
|
37
|
+
/** Extract the last completed user/assistant turn from a Codex / CoCo bridge
|
|
38
|
+
* event sequence. Used by /adopt to surface the previous turn as a
|
|
39
|
+
* preamble card in the Lark thread — gives the user context to continue
|
|
40
|
+
* from. CoCo events share the same shape (uuid/timestampMs/kind/text),
|
|
41
|
+
* so this works for both bridges.
|
|
42
|
+
*
|
|
43
|
+
* Algorithm: scan tail-first for the most recent `assistant_final`, then
|
|
44
|
+
* pair it with the most recent `user` event that precedes it. Returns
|
|
45
|
+
* undefined when either side is missing — typically a fresh session whose
|
|
46
|
+
* user typed something but the model hasn't replied yet. */
|
|
47
|
+
export declare function extractLastCodexTurn(events: readonly {
|
|
48
|
+
kind: 'user' | 'assistant_final';
|
|
49
|
+
text: string;
|
|
50
|
+
}[]): {
|
|
51
|
+
userText: string;
|
|
52
|
+
assistantText: string;
|
|
53
|
+
} | undefined;
|
|
38
54
|
/** Split a drained event list into "history" (older than the live cutoff)
|
|
39
55
|
* and "live" (cutoff or newer). The Codex adopt bridge uses this when
|
|
40
56
|
* it discovers the rollout file LATE (after the user already typed in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-transcript.d.ts","sourceRoot":"","sources":["../../src/services/codex-transcript.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codex-transcript.d.ts","sourceRoot":"","sources":["../../src/services/codex-transcript.ts"],"names":[],"mappings":"AAkCA;;;;sEAIsE;AACtE,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG9E;AAED;;;;;;;;;qDASqD;AACrD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAmCrG;AAUD,MAAM,WAAW,gBAAgB;IAC/B;yEACqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb;;4CAEwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB;;oEAEgE;IAChE,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACjC;4CACwC;IACxC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;6DAS6D;AAC7D,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GACpE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAezD;AAED;;;;;;;gEAOgE;AAChE,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,gBAAgB,EAAE,EACnC,WAAW,EAAE,MAAM,GAClB;IAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAAC,IAAI,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAQ3D;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B;qDACiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB;8DAC0D;IAC1D,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;oDAGoD;AACpD,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAoBpF;AAkBD;;mEAEmE;AACnE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,CAqDpF"}
|
|
@@ -25,9 +25,11 @@
|
|
|
25
25
|
* Pure I/O. Attribution belongs in CodexBridgeQueue.
|
|
26
26
|
*/
|
|
27
27
|
import { existsSync, statSync, openSync, readSync, closeSync, readdirSync, readlinkSync } from 'node:fs';
|
|
28
|
-
import {
|
|
28
|
+
import { execSync } from 'node:child_process';
|
|
29
|
+
import { homedir, platform } from 'node:os';
|
|
29
30
|
import { join } from 'node:path';
|
|
30
31
|
const CODEX_SESSIONS_ROOT = join(homedir(), '.codex', 'sessions');
|
|
32
|
+
const IS_LINUX = platform() === 'linux';
|
|
31
33
|
/** Extract the cliSessionId encoded in a rollout filename. Codex's session
|
|
32
34
|
* id is UUID-shaped (8-4-4-4-12 hex), which lets us anchor the regex on
|
|
33
35
|
* the UUID alone — the `<ts>` segment between "rollout-" and the sid
|
|
@@ -37,48 +39,111 @@ export function codexSessionIdFromRolloutPath(path) {
|
|
|
37
39
|
const m = /rollout-.*-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i.exec(path);
|
|
38
40
|
return m ? m[1] : undefined;
|
|
39
41
|
}
|
|
40
|
-
/** Find the rollout file an externally-running Codex process has open
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
42
|
+
/** Find the rollout file an externally-running Codex process has open. The
|
|
43
|
+
* Codex process keeps fd open on its current rollout for the entire
|
|
44
|
+
* lifetime of the session, so this is the authoritative way to bind a
|
|
45
|
+
* Codex pid to its sessionId — far more reliable than scanning
|
|
46
|
+
* `~/.codex/sessions` by mtime (which would race with sibling Codex panes
|
|
47
|
+
* in the same project).
|
|
46
48
|
*
|
|
47
|
-
* Linux
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* /adopt, which already runs on Linux servers in practice. */
|
|
49
|
+
* Linux: `/proc/<pid>/fd/*` fast path.
|
|
50
|
+
* macOS / BSD: `lsof -p <pid> -Fn` 兜底(同 session-discovery 里的 readCwd)。
|
|
51
|
+
* 两种平台都用 `codexSessionIdFromRolloutPath` 提取 sid。 */
|
|
51
52
|
export function findCodexRolloutByPid(pid) {
|
|
52
53
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
53
54
|
return undefined;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
if (IS_LINUX) {
|
|
56
|
+
const fdDir = `/proc/${pid}/fd`;
|
|
57
|
+
if (existsSync(fdDir)) {
|
|
58
|
+
let entries;
|
|
59
|
+
try {
|
|
60
|
+
entries = readdirSync(fdDir);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
for (const fd of entries) {
|
|
66
|
+
let target;
|
|
67
|
+
try {
|
|
68
|
+
target = readlinkSync(join(fdDir, fd));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const hit = matchCodexRolloutPath(target);
|
|
74
|
+
if (hit)
|
|
75
|
+
return hit;
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
// /proc 不可读时落到下面的 lsof 兜底(极少见,但兜一下)
|
|
80
|
+
}
|
|
81
|
+
// BSD ps 的 lsof:每个 fd 输出一行 `f<n>` 加一行 `n<path>`,socket / pipe
|
|
82
|
+
// 之类的内部条目以 `n->0x...` 或 `n<garbage>` 开头,所以只接受 `n/` 开头。
|
|
83
|
+
let out;
|
|
58
84
|
try {
|
|
59
|
-
|
|
85
|
+
out = execSync(`lsof -p ${pid} -Fn`, {
|
|
86
|
+
encoding: 'utf-8',
|
|
87
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
88
|
+
});
|
|
60
89
|
}
|
|
61
90
|
catch {
|
|
62
91
|
return undefined;
|
|
63
92
|
}
|
|
64
|
-
for (const
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
target = readlinkSync(join(fdDir, fd));
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (!target.endsWith('.jsonl'))
|
|
93
|
+
for (const line of out.split('\n')) {
|
|
94
|
+
if (!line.startsWith('n/'))
|
|
73
95
|
continue;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return { path: target, cliSessionId: sid };
|
|
96
|
+
const target = line.slice(1);
|
|
97
|
+
const hit = matchCodexRolloutPath(target);
|
|
98
|
+
if (hit)
|
|
99
|
+
return hit;
|
|
79
100
|
}
|
|
80
101
|
return undefined;
|
|
81
102
|
}
|
|
103
|
+
function matchCodexRolloutPath(target) {
|
|
104
|
+
if (!target.endsWith('.jsonl'))
|
|
105
|
+
return undefined;
|
|
106
|
+
if (!target.includes('/.codex/sessions/'))
|
|
107
|
+
return undefined;
|
|
108
|
+
const sid = codexSessionIdFromRolloutPath(target);
|
|
109
|
+
if (!sid)
|
|
110
|
+
return undefined;
|
|
111
|
+
return { path: target, cliSessionId: sid };
|
|
112
|
+
}
|
|
113
|
+
/** Extract the last completed user/assistant turn from a Codex / CoCo bridge
|
|
114
|
+
* event sequence. Used by /adopt to surface the previous turn as a
|
|
115
|
+
* preamble card in the Lark thread — gives the user context to continue
|
|
116
|
+
* from. CoCo events share the same shape (uuid/timestampMs/kind/text),
|
|
117
|
+
* so this works for both bridges.
|
|
118
|
+
*
|
|
119
|
+
* Algorithm: scan tail-first for the most recent `assistant_final`, then
|
|
120
|
+
* pair it with the most recent `user` event that precedes it. Returns
|
|
121
|
+
* undefined when either side is missing — typically a fresh session whose
|
|
122
|
+
* user typed something but the model hasn't replied yet. */
|
|
123
|
+
export function extractLastCodexTurn(events) {
|
|
124
|
+
let assistantIdx = -1;
|
|
125
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
126
|
+
if (events[i].kind === 'assistant_final') {
|
|
127
|
+
assistantIdx = i;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (assistantIdx < 0)
|
|
132
|
+
return undefined;
|
|
133
|
+
let userIdx = -1;
|
|
134
|
+
for (let i = assistantIdx - 1; i >= 0; i--) {
|
|
135
|
+
if (events[i].kind === 'user') {
|
|
136
|
+
userIdx = i;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (userIdx < 0)
|
|
141
|
+
return undefined;
|
|
142
|
+
return {
|
|
143
|
+
userText: events[userIdx].text,
|
|
144
|
+
assistantText: events[assistantIdx].text,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
82
147
|
/** Split a drained event list into "history" (older than the live cutoff)
|
|
83
148
|
* and "live" (cutoff or newer). The Codex adopt bridge uses this when
|
|
84
149
|
* it discovers the rollout file LATE (after the user already typed in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-transcript.js","sourceRoot":"","sources":["../../src/services/codex-transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACzG,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"codex-transcript.js","sourceRoot":"","sources":["../../src/services/codex-transcript.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,4 +14,8 @@ export interface SkillDef {
|
|
|
14
14
|
content: string;
|
|
15
15
|
}
|
|
16
16
|
export declare const BUILTIN_SKILLS: SkillDef[];
|
|
17
|
+
/** Skills that earlier botmux versions installed but no longer ship. The
|
|
18
|
+
* installer cleans these up so renamed skills don't linger as duplicates
|
|
19
|
+
* in the CLI's skills directory. */
|
|
20
|
+
export declare const RETIRED_SKILL_NAMES: string[];
|
|
17
21
|
//# sourceMappingURL=definitions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/skills/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,QAAQ;IACvB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/skills/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,QAAQ;IACvB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;CACjB;AAuXD,eAAO,MAAM,cAAc,EAAE,QAAQ,EAMpC,CAAC;AAEF;;qCAEqC;AACrC,eAAO,MAAM,mBAAmB,EAAE,MAAM,EAEvC,CAAC"}
|
|
@@ -99,26 +99,26 @@ botmux schedule add "每日11:00" "
|
|
|
99
99
|
|
|
100
100
|
详见 \`botmux-send\` 技能的"顶层广播 / 跨群发布"章节。
|
|
101
101
|
`;
|
|
102
|
-
const
|
|
103
|
-
name: botmux-
|
|
104
|
-
description:
|
|
102
|
+
const HISTORY_SKILL = `---
|
|
103
|
+
name: botmux-history
|
|
104
|
+
description: 需要查看当前飞书会话历史消息时触发。话题群拉话题内消息,普通群拉整群消息(从 session 创建起的最近 N 条)。适合"看看之前聊了什么"、"最近的消息"、"上下文"类请求。在 CLI 会话内自动推断 session-id。
|
|
105
105
|
---
|
|
106
106
|
|
|
107
|
-
# botmux-
|
|
107
|
+
# botmux-history — 读取会话消息历史
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
想回顾当前飞书会话里用户之前发过什么、别的机器人说了什么时使用。**话题群和普通群都支持**:话题群里只返回当前话题内的消息,普通群里返回整群从 session 创建起的最近 N 条。
|
|
110
110
|
|
|
111
111
|
## 用法
|
|
112
112
|
|
|
113
113
|
\`\`\`bash
|
|
114
114
|
# 拉取最近 50 条(默认)
|
|
115
|
-
botmux
|
|
115
|
+
botmux history
|
|
116
116
|
|
|
117
117
|
# 拉取最近 100 条
|
|
118
|
-
botmux
|
|
118
|
+
botmux history --limit 100
|
|
119
119
|
|
|
120
120
|
# 指定 session-id(不在 CLI 会话内时用)
|
|
121
|
-
botmux
|
|
121
|
+
botmux history --session-id <uuid>
|
|
122
122
|
\`\`\`
|
|
123
123
|
|
|
124
124
|
## 输出
|
|
@@ -128,7 +128,9 @@ JSON 格式,字段:
|
|
|
128
128
|
\`\`\`json
|
|
129
129
|
{
|
|
130
130
|
"sessionId": "...",
|
|
131
|
-
"
|
|
131
|
+
"chatId": "...",
|
|
132
|
+
"scope": "thread" | "chat",
|
|
133
|
+
"rootMessageId": "...", // 仅 scope=thread 时存在
|
|
132
134
|
"messages": [
|
|
133
135
|
{ "messageId": "...", "senderId": "...", "senderType": "user|app", "msgType": "text|post|interactive", "content": "...", "createTime": "..." }
|
|
134
136
|
],
|
|
@@ -138,11 +140,59 @@ JSON 格式,字段:
|
|
|
138
140
|
|
|
139
141
|
## 注意
|
|
140
142
|
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
+
- \`scope=thread\`:只返回属于当前话题的消息(按 rootMessageId 过滤)
|
|
144
|
+
- \`scope=chat\`:返回当前群从 session 创建起的最近 N 条整群消息
|
|
145
|
+
- \`senderType="app"\` 表示机器人发的消息(包括 Claude Code / Codex / 其它 bot),\`"user"\` 表示用户
|
|
143
146
|
- **合并转发**消息会自动展开:\`msgType\` 变为 \`merge_forward_expanded\`,\`content\` 是 \`<forwarded_messages>...</forwarded_messages>\` XML(含 \`<participants>\` 别名表 + 嵌套 \`<msg from="A">\` 节点),与 daemon 实时事件路径一致
|
|
144
147
|
- 需要先把 JSON 读进来再做总结,不要直接把 JSON 扔给用户
|
|
145
148
|
`;
|
|
149
|
+
const QUOTED_SKILL = `---
|
|
150
|
+
name: botmux-quoted
|
|
151
|
+
description: 当 prompt 顶部出现 \`[用户引用了消息 用 botmux quoted om_xxx 查看]\` 提示时,用本技能按需读取被引用的那条消息内容。看到这种提示就该判断引用内容是否对当前任务必要,必要就调用,不必要就跳过。
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
# botmux-quoted — 读取被引用的消息
|
|
155
|
+
|
|
156
|
+
用户在飞书里使用"引用回复" UI @ 机器人时,daemon 会在喂给你的 prompt 头部加一行:
|
|
157
|
+
|
|
158
|
+
\`\`\`
|
|
159
|
+
[用户引用了消息 用 botmux quoted om_xxx 查看]
|
|
160
|
+
<用户的实际文字>
|
|
161
|
+
\`\`\`
|
|
162
|
+
|
|
163
|
+
看到这种提示,先判断引用内容是否对当前任务必要:必要就调用 \`botmux quoted om_xxx\` 拉取,不必要就忽略(不要无脑调用、污染上下文)。
|
|
164
|
+
|
|
165
|
+
## 用法
|
|
166
|
+
|
|
167
|
+
\`\`\`bash
|
|
168
|
+
botmux quoted <message_id>
|
|
169
|
+
\`\`\`
|
|
170
|
+
|
|
171
|
+
\`message_id\` 直接从提示行里复制即可。
|
|
172
|
+
|
|
173
|
+
## 输出
|
|
174
|
+
|
|
175
|
+
JSON 格式,与 \`botmux history\` 的单条消息字段一致,并附带 \`resources\` 列表:
|
|
176
|
+
|
|
177
|
+
\`\`\`json
|
|
178
|
+
{
|
|
179
|
+
"messageId": "om_xxx",
|
|
180
|
+
"senderId": "ou_xxx",
|
|
181
|
+
"senderType": "user|app",
|
|
182
|
+
"msgType": "text|post|interactive|image|file|merge_forward_expanded",
|
|
183
|
+
"content": "...",
|
|
184
|
+
"createTime": "1234567890000",
|
|
185
|
+
"resources": [{"type":"image","key":"img_v3_xxx","name":"img_v3_xxx.jpg"}]
|
|
186
|
+
}
|
|
187
|
+
\`\`\`
|
|
188
|
+
|
|
189
|
+
## 注意
|
|
190
|
+
|
|
191
|
+
- 图片/文件渲染成 \`[图片 N]\` / \`[文件 N: name.pdf]\` 占位符(与 \`botmux history\` 一致),实际附件 key 在 \`resources\` 列表里
|
|
192
|
+
- 卡片消息会被解析成可读文本
|
|
193
|
+
- 合并转发消息会自动展开
|
|
194
|
+
- 当前不支持自动下载附件本地化;要看图片实际内容,目前只能让用户单独转发或 \`botmux send\` 询问
|
|
195
|
+
`;
|
|
146
196
|
const SEND_SKILL = `---
|
|
147
197
|
name: botmux-send
|
|
148
198
|
description: 向飞书话题发送消息。用户在飞书上阅读看不到终端输出,需要用户看到的内容(关键结论、方案、最终结果、进度更新)必须通过 botmux send 发送。支持图文混排(图片穿插在 markdown 正文中)、文本、图片/文件附件、@mention。
|
|
@@ -327,8 +377,15 @@ botmux send --mention "ou_yyy:Aiden" "请 @Aiden 帮忙处理"
|
|
|
327
377
|
`;
|
|
328
378
|
export const BUILTIN_SKILLS = [
|
|
329
379
|
{ name: 'botmux-schedule', content: SCHEDULE_SKILL },
|
|
330
|
-
{ name: 'botmux-
|
|
380
|
+
{ name: 'botmux-history', content: HISTORY_SKILL },
|
|
381
|
+
{ name: 'botmux-quoted', content: QUOTED_SKILL },
|
|
331
382
|
{ name: 'botmux-send', content: SEND_SKILL },
|
|
332
383
|
{ name: 'botmux-bots', content: BOTS_SKILL },
|
|
333
384
|
];
|
|
385
|
+
/** Skills that earlier botmux versions installed but no longer ship. The
|
|
386
|
+
* installer cleans these up so renamed skills don't linger as duplicates
|
|
387
|
+
* in the CLI's skills directory. */
|
|
388
|
+
export const RETIRED_SKILL_NAMES = [
|
|
389
|
+
'botmux-thread-messages',
|
|
390
|
+
];
|
|
334
391
|
//# sourceMappingURL=definitions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/skills/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2FtB,CAAC;AAEF,MAAM,
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/skills/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2FtB,CAAC;AAEF,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CrB,CAAC;AAEF,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CpB,CAAC;AAEF,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkJlB,CAAC;AAEF,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkClB,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,cAAc,EAAE;IACpD,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAAE;IAClD,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE;IAChD,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE;IAC5C,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE;CAC7C,CAAC;AAEF;;qCAEqC;AACrC,MAAM,CAAC,MAAM,mBAAmB,GAAa;IAC3C,wBAAwB;CACzB,CAAC"}
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* directory. Idempotent — only writes when content differs.
|
|
4
4
|
*
|
|
5
5
|
* Each skill becomes {skillsDir}/<name>/SKILL.md. Sub-directory layout
|
|
6
|
-
* matches Claude Code / Gemini / OpenCode convention.
|
|
6
|
+
* matches Claude Code / Gemini / OpenCode convention. Retired skills (renamed
|
|
7
|
+
* or removed in a later version) are deleted from the directory so the CLI
|
|
8
|
+
* doesn't keep surfacing stale entries alongside their replacements.
|
|
7
9
|
*/
|
|
8
10
|
export declare function ensureSkills(cliId: string, skillsDir: string | undefined): void;
|
|
9
11
|
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/skills/installer.ts"],"names":[],"mappings":"AAUA
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/skills/installer.ts"],"names":[],"mappings":"AAUA;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAgC/E"}
|
package/dist/skills/installer.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { writeFileSync, mkdirSync, existsSync, readFileSync } from 'node:fs';
|
|
1
|
+
import { writeFileSync, mkdirSync, existsSync, readFileSync, rmSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { logger } from '../utils/logger.js';
|
|
5
|
-
import { BUILTIN_SKILLS } from './definitions.js';
|
|
5
|
+
import { BUILTIN_SKILLS, RETIRED_SKILL_NAMES } from './definitions.js';
|
|
6
6
|
function expandHome(p) {
|
|
7
7
|
return p.startsWith('~') ? join(homedir(), p.slice(1)) : p;
|
|
8
8
|
}
|
|
@@ -11,7 +11,9 @@ function expandHome(p) {
|
|
|
11
11
|
* directory. Idempotent — only writes when content differs.
|
|
12
12
|
*
|
|
13
13
|
* Each skill becomes {skillsDir}/<name>/SKILL.md. Sub-directory layout
|
|
14
|
-
* matches Claude Code / Gemini / OpenCode convention.
|
|
14
|
+
* matches Claude Code / Gemini / OpenCode convention. Retired skills (renamed
|
|
15
|
+
* or removed in a later version) are deleted from the directory so the CLI
|
|
16
|
+
* doesn't keep surfacing stale entries alongside their replacements.
|
|
15
17
|
*/
|
|
16
18
|
export function ensureSkills(cliId, skillsDir) {
|
|
17
19
|
if (!skillsDir)
|
|
@@ -38,5 +40,18 @@ export function ensureSkills(cliId, skillsDir) {
|
|
|
38
40
|
logger.warn(`[skills] Failed to install ${skill.name} for ${cliId}: ${err.message}`);
|
|
39
41
|
}
|
|
40
42
|
}
|
|
43
|
+
// Clean up retired skill directories (e.g. botmux-thread-messages → botmux-history).
|
|
44
|
+
for (const retired of RETIRED_SKILL_NAMES) {
|
|
45
|
+
const retiredDir = join(dir, retired);
|
|
46
|
+
if (!existsSync(retiredDir))
|
|
47
|
+
continue;
|
|
48
|
+
try {
|
|
49
|
+
rmSync(retiredDir, { recursive: true, force: true });
|
|
50
|
+
logger.info(`[skills] Removed retired skill ${retired} for ${cliId}`);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
logger.warn(`[skills] Failed to remove retired skill ${retired} for ${cliId}: ${err.message}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
41
56
|
}
|
|
42
57
|
//# sourceMappingURL=installer.js.map
|