agent-shell-chat 1.2.2
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/LICENSE +21 -0
- package/README.md +199 -0
- package/dist/bin/agent-shell.d.ts +15 -0
- package/dist/bin/agent-shell.d.ts.map +1 -0
- package/dist/bin/agent-shell.js +816 -0
- package/dist/bin/agent-shell.js.map +1 -0
- package/dist/package.json +54 -0
- package/dist/src/acp/agent-manager.d.ts +22 -0
- package/dist/src/acp/agent-manager.d.ts.map +1 -0
- package/dist/src/acp/agent-manager.js +79 -0
- package/dist/src/acp/agent-manager.js.map +1 -0
- package/dist/src/acp/client.d.ts +64 -0
- package/dist/src/acp/client.d.ts.map +1 -0
- package/dist/src/acp/client.js +265 -0
- package/dist/src/acp/client.js.map +1 -0
- package/dist/src/acp/session.d.ts +81 -0
- package/dist/src/acp/session.d.ts.map +1 -0
- package/dist/src/acp/session.js +339 -0
- package/dist/src/acp/session.js.map +1 -0
- package/dist/src/adapter/inbound.d.ts +39 -0
- package/dist/src/adapter/inbound.d.ts.map +1 -0
- package/dist/src/adapter/inbound.js +264 -0
- package/dist/src/adapter/inbound.js.map +1 -0
- package/dist/src/bridge.d.ts +115 -0
- package/dist/src/bridge.d.ts.map +1 -0
- package/dist/src/bridge.js +969 -0
- package/dist/src/bridge.js.map +1 -0
- package/dist/src/config.d.ts +155 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +265 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +7 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/inject/monitor.d.ts +24 -0
- package/dist/src/inject/monitor.d.ts.map +1 -0
- package/dist/src/inject/monitor.js +149 -0
- package/dist/src/inject/monitor.js.map +1 -0
- package/dist/src/inject/queue.d.ts +13 -0
- package/dist/src/inject/queue.d.ts.map +1 -0
- package/dist/src/inject/queue.js +35 -0
- package/dist/src/inject/queue.js.map +1 -0
- package/dist/src/inject/types.d.ts +10 -0
- package/dist/src/inject/types.d.ts.map +1 -0
- package/dist/src/inject/types.js +2 -0
- package/dist/src/inject/types.js.map +1 -0
- package/dist/src/storage/accounts.d.ts +43 -0
- package/dist/src/storage/accounts.d.ts.map +1 -0
- package/dist/src/storage/accounts.js +289 -0
- package/dist/src/storage/accounts.js.map +1 -0
- package/dist/src/storage/runtime.d.ts +23 -0
- package/dist/src/storage/runtime.d.ts.map +1 -0
- package/dist/src/storage/runtime.js +104 -0
- package/dist/src/storage/runtime.js.map +1 -0
- package/dist/src/storage/state.d.ts +17 -0
- package/dist/src/storage/state.d.ts.map +1 -0
- package/dist/src/storage/state.js +78 -0
- package/dist/src/storage/state.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +33 -0
- package/dist/src/telemetry/index.d.ts.map +1 -0
- package/dist/src/telemetry/index.js +167 -0
- package/dist/src/telemetry/index.js.map +1 -0
- package/dist/src/weixin/api.d.ts +50 -0
- package/dist/src/weixin/api.d.ts.map +1 -0
- package/dist/src/weixin/api.js +90 -0
- package/dist/src/weixin/api.js.map +1 -0
- package/dist/src/weixin/auth.d.ts +26 -0
- package/dist/src/weixin/auth.d.ts.map +1 -0
- package/dist/src/weixin/auth.js +103 -0
- package/dist/src/weixin/auth.js.map +1 -0
- package/dist/src/weixin/media.d.ts +24 -0
- package/dist/src/weixin/media.d.ts.map +1 -0
- package/dist/src/weixin/media.js +64 -0
- package/dist/src/weixin/media.js.map +1 -0
- package/dist/src/weixin/monitor.d.ts +16 -0
- package/dist/src/weixin/monitor.d.ts.map +1 -0
- package/dist/src/weixin/monitor.js +113 -0
- package/dist/src/weixin/monitor.js.map +1 -0
- package/dist/src/weixin/send.d.ts +28 -0
- package/dist/src/weixin/send.d.ts.map +1 -0
- package/dist/src/weixin/send.js +162 -0
- package/dist/src/weixin/send.js.map +1 -0
- package/dist/src/weixin/types.d.ts +149 -0
- package/dist/src/weixin/types.d.ts.map +1 -0
- package/dist/src/weixin/types.js +33 -0
- package/dist/src/weixin/types.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbound adapter: convert WeChat messages to ACP ContentBlock[].
|
|
3
|
+
*/
|
|
4
|
+
import fsp from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { MessageItemType } from "../weixin/types.js";
|
|
7
|
+
import { parseAesKey, downloadAndDecrypt } from "../weixin/media.js";
|
|
8
|
+
/**
|
|
9
|
+
* Extract text body from a WeChat message's item_list.
|
|
10
|
+
*/
|
|
11
|
+
function extractText(itemList) {
|
|
12
|
+
if (!itemList?.length)
|
|
13
|
+
return "";
|
|
14
|
+
for (const item of itemList) {
|
|
15
|
+
if (item.type === MessageItemType.TEXT && item.text_item?.text != null) {
|
|
16
|
+
const text = String(item.text_item.text);
|
|
17
|
+
const ref = item.ref_msg;
|
|
18
|
+
if (!ref)
|
|
19
|
+
return text;
|
|
20
|
+
// Build quoted context
|
|
21
|
+
const parts = [];
|
|
22
|
+
if (ref.title)
|
|
23
|
+
parts.push(ref.title);
|
|
24
|
+
if (ref.message_item?.text_item?.text)
|
|
25
|
+
parts.push(ref.message_item.text_item.text);
|
|
26
|
+
if (!parts.length)
|
|
27
|
+
return text;
|
|
28
|
+
return `[引用: ${parts.join(" | ")}]\n${text}`;
|
|
29
|
+
}
|
|
30
|
+
// Voice transcription
|
|
31
|
+
if (item.type === MessageItemType.VOICE && item.voice_item?.text) {
|
|
32
|
+
return item.voice_item.text;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Find the first media item in a message.
|
|
39
|
+
*/
|
|
40
|
+
function findMediaItem(itemList) {
|
|
41
|
+
if (!itemList)
|
|
42
|
+
return undefined;
|
|
43
|
+
return (itemList.find((i) => i.type === MessageItemType.IMAGE && i.image_item?.media?.encrypt_query_param) ??
|
|
44
|
+
itemList.find((i) => i.type === MessageItemType.VIDEO && i.video_item?.media?.encrypt_query_param) ??
|
|
45
|
+
itemList.find((i) => i.type === MessageItemType.FILE && i.file_item?.media?.encrypt_query_param) ??
|
|
46
|
+
itemList.find((i) => i.type === MessageItemType.VOICE && i.voice_item?.media?.encrypt_query_param && !i.voice_item.text));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Convert a WeChat message to ACP ContentBlock[] for use in session/prompt.
|
|
50
|
+
*/
|
|
51
|
+
export async function weixinMessageToPrompt(msg, cdnBaseUrl, log, inboxDir) {
|
|
52
|
+
const blocks = [];
|
|
53
|
+
// Extract text
|
|
54
|
+
const text = extractText(msg.item_list);
|
|
55
|
+
if (text) {
|
|
56
|
+
blocks.push({ type: "text", text });
|
|
57
|
+
}
|
|
58
|
+
// Try to download and attach media
|
|
59
|
+
const mediaItem = findMediaItem(msg.item_list);
|
|
60
|
+
if (mediaItem) {
|
|
61
|
+
try {
|
|
62
|
+
const attached = await convertMediaItem(mediaItem, cdnBaseUrl, log, inboxDir ?? null);
|
|
63
|
+
if (attached)
|
|
64
|
+
blocks.push(attached);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
log(`Media download failed, skipping: ${String(err)}`);
|
|
68
|
+
// Add a text note about the media
|
|
69
|
+
const mediaType = mediaItem.type === MessageItemType.IMAGE ? "image"
|
|
70
|
+
: mediaItem.type === MessageItemType.VIDEO ? "video"
|
|
71
|
+
: mediaItem.type === MessageItemType.FILE ? `file (${mediaItem.file_item?.file_name ?? "unknown"})`
|
|
72
|
+
: mediaItem.type === MessageItemType.VOICE ? "voice"
|
|
73
|
+
: "media";
|
|
74
|
+
blocks.push({ type: "text", text: `[Received ${mediaType} - download failed]` });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Fallback: always have at least one content block
|
|
78
|
+
if (blocks.length === 0) {
|
|
79
|
+
blocks.push({ type: "text", text: "[empty message]" });
|
|
80
|
+
}
|
|
81
|
+
return blocks;
|
|
82
|
+
}
|
|
83
|
+
async function convertMediaItem(item, cdnBaseUrl, log, inboxDir) {
|
|
84
|
+
if (item.type === MessageItemType.IMAGE && item.image_item?.media) {
|
|
85
|
+
const media = item.image_item.media;
|
|
86
|
+
const aesKey = parseAesKey(media);
|
|
87
|
+
if (!aesKey || !media.encrypt_query_param)
|
|
88
|
+
return null;
|
|
89
|
+
log("Downloading image from CDN...");
|
|
90
|
+
const buffer = await downloadAndDecrypt(media.encrypt_query_param, aesKey, cdnBaseUrl);
|
|
91
|
+
const base64 = buffer.toString("base64");
|
|
92
|
+
return {
|
|
93
|
+
type: "image",
|
|
94
|
+
data: base64,
|
|
95
|
+
mimeType: "image/jpeg",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (item.type === MessageItemType.FILE && item.file_item?.media) {
|
|
99
|
+
const media = item.file_item.media;
|
|
100
|
+
const aesKey = parseAesKey(media);
|
|
101
|
+
if (!aesKey || !media.encrypt_query_param)
|
|
102
|
+
return null;
|
|
103
|
+
log(`Downloading file "${item.file_item.file_name}" from CDN...`);
|
|
104
|
+
const buffer = await downloadAndDecrypt(media.encrypt_query_param, aesKey, cdnBaseUrl);
|
|
105
|
+
// For text-like files, send as resource; for binary, describe it
|
|
106
|
+
const fileName = item.file_item.file_name ?? "file";
|
|
107
|
+
if (isTextFile(fileName)) {
|
|
108
|
+
const content = buffer.toString("utf-8");
|
|
109
|
+
return {
|
|
110
|
+
type: "resource",
|
|
111
|
+
resource: {
|
|
112
|
+
uri: `file:///${fileName}`,
|
|
113
|
+
mimeType: guessMimeType(fileName),
|
|
114
|
+
text: content,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return { type: "text", text: await buildBinaryFileText(fileName, buffer, inboxDir, log) };
|
|
119
|
+
}
|
|
120
|
+
if (item.type === MessageItemType.VOICE && item.voice_item?.media) {
|
|
121
|
+
// If there's a transcription, it was already handled in extractText
|
|
122
|
+
// Otherwise, note we received voice
|
|
123
|
+
return { type: "text", text: "[Received voice message - no transcription available]" };
|
|
124
|
+
}
|
|
125
|
+
if (item.type === MessageItemType.VIDEO) {
|
|
126
|
+
return { type: "text", text: "[Received video message]" };
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
function isTextFile(name) {
|
|
131
|
+
const ext = name.split(".").pop()?.toLowerCase() ?? "";
|
|
132
|
+
return [
|
|
133
|
+
"txt", "md", "json", "js", "ts", "py", "java", "c", "cpp", "h",
|
|
134
|
+
"css", "html", "xml", "yaml", "yml", "toml", "ini", "cfg", "sh",
|
|
135
|
+
"bash", "rs", "go", "rb", "php", "sql", "csv", "log", "env",
|
|
136
|
+
].includes(ext);
|
|
137
|
+
}
|
|
138
|
+
function guessMimeType(name) {
|
|
139
|
+
const ext = name.split(".").pop()?.toLowerCase() ?? "";
|
|
140
|
+
const map = {
|
|
141
|
+
txt: "text/plain", md: "text/markdown", json: "application/json",
|
|
142
|
+
js: "text/javascript", ts: "text/typescript", py: "text/x-python",
|
|
143
|
+
html: "text/html", css: "text/css", xml: "text/xml",
|
|
144
|
+
yaml: "text/yaml", yml: "text/yaml", csv: "text/csv",
|
|
145
|
+
};
|
|
146
|
+
return map[ext] ?? "text/plain";
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Build the text block describing a received binary file.
|
|
150
|
+
*
|
|
151
|
+
* When `inboxDir` is set, the buffer is persisted to disk so the agent
|
|
152
|
+
* can read it by path. On any save failure we silently fall back to the
|
|
153
|
+
* legacy size-only notice (with a log line for diagnostics) — the agent
|
|
154
|
+
* still gets *something* and the message poll loop is not blocked.
|
|
155
|
+
*/
|
|
156
|
+
async function buildBinaryFileText(fileName, buffer, inboxDir, log) {
|
|
157
|
+
if (!inboxDir) {
|
|
158
|
+
return `[Received file: ${fileName}, ${buffer.length} bytes]`;
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const savedPath = await saveToInbox(buffer, fileName, inboxDir);
|
|
162
|
+
return `[Received file: ${fileName} (${buffer.length} bytes) \u2014 saved to: ${savedPath}]`;
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
log(`Failed to save received file "${fileName}" to inbox: ${String(err)}`);
|
|
166
|
+
return `[Received file: ${fileName}, ${buffer.length} bytes]`;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Permissions: 0o600 on the file and 0o700 on the inbox dir so that on
|
|
170
|
+
// multi-user POSIX systems received files (which often contain personal
|
|
171
|
+
// info: IDs, contracts, photos…) aren't readable by other local users.
|
|
172
|
+
// We apply both via the {mode} option AND an explicit chmod after the
|
|
173
|
+
// op, because:
|
|
174
|
+
// - mkdir's {mode} is only applied to dirs we *create*; if the inbox
|
|
175
|
+
// dir already exists with looser perms (e.g. from a previous bridge
|
|
176
|
+
// version, or a hand-created dir), {mode} silently does nothing.
|
|
177
|
+
// - writeFile's {mode} is subject to the process umask: in practice
|
|
178
|
+
// umask can only *remove* bits, so 0o600 → at most 0o600, which is
|
|
179
|
+
// fine for confidentiality — the explicit chmod is just belt-and-
|
|
180
|
+
// braces against a future change that uses a less minimal mode.
|
|
181
|
+
// Both chmods are best-effort: failures (e.g. on Windows where chmod
|
|
182
|
+
// is largely a no-op, or on a network mount with restricted perms)
|
|
183
|
+
// don't block the save itself.
|
|
184
|
+
const INBOX_DIR_MODE = 0o700;
|
|
185
|
+
const INBOX_FILE_MODE = 0o600;
|
|
186
|
+
// Safety cap on the EEXIST retry loop. With a deterministic numeric
|
|
187
|
+
// suffix per attempt, true collision past this count is essentially
|
|
188
|
+
// impossible; the cap exists only to bound a pathological hot loop.
|
|
189
|
+
const INBOX_MAX_COLLISION_RETRIES = 100;
|
|
190
|
+
/**
|
|
191
|
+
* Write `buffer` into `inboxDir` and return the absolute path.
|
|
192
|
+
*
|
|
193
|
+
* Filename convention: `${ISO-timestamp}-${safeName}` for the first
|
|
194
|
+
* attempt, `${ISO-timestamp}-${N}-${safeName}` on the Nth retry, where
|
|
195
|
+
* - the timestamp uses ISO 8601 with colons and dots replaced by
|
|
196
|
+
* dashes (so the name avoids characters reserved on Windows),
|
|
197
|
+
* - `safeName` is `fileName` with path separators stripped, ASCII
|
|
198
|
+
* control + Windows-reserved chars (`<>:"/\|?*`) replaced by `_`,
|
|
199
|
+
* leading dots and trailing dots/spaces (which Windows silently
|
|
200
|
+
* trims) normalized to `_`, while Unicode is preserved so Chinese
|
|
201
|
+
* filenames stay readable,
|
|
202
|
+
* - if the sanitized name is empty, it falls back to `"file"`.
|
|
203
|
+
*
|
|
204
|
+
* Writes use the `wx` flag (fail-if-exists) so a collision — two
|
|
205
|
+
* bridge instances sharing an inbox, the user re-sending the same
|
|
206
|
+
* file twice in quick succession, a stubbed/frozen clock — never
|
|
207
|
+
* silently overwrites an existing file. On `EEXIST` we keep the
|
|
208
|
+
* original timestamp and bump a deterministic numeric suffix
|
|
209
|
+
* (`-1-`, `-2-`, …) capped at `INBOX_MAX_COLLISION_RETRIES`.
|
|
210
|
+
*
|
|
211
|
+
* Reserved-name corner case (Windows `CON`, `PRN`, `NUL`, `COM1`, …):
|
|
212
|
+
* Windows matches reserved device names against the basename exactly
|
|
213
|
+
* (case-insensitive, with or without extension). Because we always
|
|
214
|
+
* prefix the saved name with a timestamp like `2026-05-21T...Z-`,
|
|
215
|
+
* the basename is never one of those reserved tokens, so no extra
|
|
216
|
+
* handling is needed here.
|
|
217
|
+
*/
|
|
218
|
+
export async function saveToInbox(buffer, fileName, inboxDir) {
|
|
219
|
+
await fsp.mkdir(inboxDir, { recursive: true, mode: INBOX_DIR_MODE });
|
|
220
|
+
// Best-effort chmod the dir in case it pre-existed with looser
|
|
221
|
+
// permissions — mkdir's {mode} only applies to dirs we just created.
|
|
222
|
+
await fsp.chmod(inboxDir, INBOX_DIR_MODE).catch(() => { });
|
|
223
|
+
const safeBase = sanitizeFilename(fileName);
|
|
224
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
225
|
+
for (let attempt = 0; attempt < INBOX_MAX_COLLISION_RETRIES; attempt++) {
|
|
226
|
+
// attempt 0 → "stamp-name"; subsequent retries → "stamp-N-name".
|
|
227
|
+
// Putting the counter ahead of the user-supplied name keeps the
|
|
228
|
+
// file extension at the tail (so OS open-by-extension still works)
|
|
229
|
+
// and guarantees a fresh path even when the wall clock hasn't
|
|
230
|
+
// ticked between retries (super-fast disk, stubbed time, etc.).
|
|
231
|
+
const suffix = attempt === 0 ? "" : `-${attempt}`;
|
|
232
|
+
const target = path.resolve(inboxDir, `${stamp}${suffix}-${safeBase}`);
|
|
233
|
+
try {
|
|
234
|
+
await fsp.writeFile(target, buffer, { flag: "wx", mode: INBOX_FILE_MODE });
|
|
235
|
+
// Best-effort chmod the file too — belt-and-braces against
|
|
236
|
+
// a future change to a less minimal {mode} above.
|
|
237
|
+
await fsp.chmod(target, INBOX_FILE_MODE).catch(() => { });
|
|
238
|
+
return target;
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
if (err.code !== "EEXIST")
|
|
242
|
+
throw err;
|
|
243
|
+
// Yield to the event loop between retries so we don't starve
|
|
244
|
+
// the bridge's poll loop on a pathological hot loop.
|
|
245
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
throw new Error(`saveToInbox: exhausted ${INBOX_MAX_COLLISION_RETRIES} collision retries for ${safeBase}`);
|
|
249
|
+
}
|
|
250
|
+
function sanitizeFilename(name) {
|
|
251
|
+
// Drop any path separators a remote sender might have included.
|
|
252
|
+
const tail = name.split(/[\\/]/).pop() ?? "";
|
|
253
|
+
// Replace ASCII control chars and Windows-reserved chars. Then:
|
|
254
|
+
// - leading dots → `_` (no hidden files / no path-walk-via-dot)
|
|
255
|
+
// - trailing dots and spaces → `_` (Windows silently trims them
|
|
256
|
+
// when creating files, which would make the path we return to
|
|
257
|
+
// the agent differ from the on-disk name).
|
|
258
|
+
const cleaned = tail
|
|
259
|
+
.replace(/[\x00-\x1f<>:"/\\|?*]/g, "_")
|
|
260
|
+
.replace(/^\.+/, "_")
|
|
261
|
+
.replace(/[. ]+$/, "_");
|
|
262
|
+
return cleaned.length > 0 ? cleaned : "file";
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=inbound.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../../src/adapter/inbound.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentShellBridge — the main orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Connects WeChat's iLink long-poll to ACP agent subprocesses.
|
|
5
|
+
* One bridge = one WeChat bot account → many users → many agent sessions.
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentShellConfig } from "./config.js";
|
|
8
|
+
export declare class AgentShellBridge {
|
|
9
|
+
private config;
|
|
10
|
+
private abortController;
|
|
11
|
+
private sessionManager;
|
|
12
|
+
private injectionMonitor;
|
|
13
|
+
private tokenData;
|
|
14
|
+
private stateUpdate;
|
|
15
|
+
private typingTickets;
|
|
16
|
+
private lastSendAt;
|
|
17
|
+
private sendChains;
|
|
18
|
+
private messageBuffers;
|
|
19
|
+
private bufferTimers;
|
|
20
|
+
private bufferFlushing;
|
|
21
|
+
private log;
|
|
22
|
+
constructor(config: AgentShellConfig, log?: (msg: string) => void);
|
|
23
|
+
start(opts?: {
|
|
24
|
+
forceLogin?: boolean;
|
|
25
|
+
renderQrUrl?: (url: string) => void;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
stop(): Promise<void>;
|
|
28
|
+
private handleMessage;
|
|
29
|
+
private enqueueMessage;
|
|
30
|
+
private enqueueInjectedMessage;
|
|
31
|
+
private handleAcpConfigCommand;
|
|
32
|
+
private handleAcpCancelCommand;
|
|
33
|
+
private formatAcpCancelResult;
|
|
34
|
+
private formatAcpCancelUsage;
|
|
35
|
+
private isBufferStartCommand;
|
|
36
|
+
private isBufferDoneCommand;
|
|
37
|
+
private handleBufferStart;
|
|
38
|
+
private handleBufferDone;
|
|
39
|
+
private doFlush;
|
|
40
|
+
private appendToBuffer;
|
|
41
|
+
private resetBufferTimer;
|
|
42
|
+
private clearBufferTimer;
|
|
43
|
+
private rememberActiveUser;
|
|
44
|
+
private sendReply;
|
|
45
|
+
private deliverReply;
|
|
46
|
+
/**
|
|
47
|
+
* Wait, if necessary, so that consecutive text messages to the same user
|
|
48
|
+
* are issued at least {@link REPLY_SEND_SPACING_MS} apart. This spaces
|
|
49
|
+
* out their server-receive timestamps so WeChat preserves the order the
|
|
50
|
+
* bridge sent them in, instead of racing and delivering them reversed
|
|
51
|
+
* (issue #38). Sends to different users are tracked independently and do
|
|
52
|
+
* not delay each other.
|
|
53
|
+
*/
|
|
54
|
+
private paceConsecutiveSend;
|
|
55
|
+
private cancelTypingIndicator;
|
|
56
|
+
private sendTypingIndicator;
|
|
57
|
+
private getTypingTicket;
|
|
58
|
+
private previewMessage;
|
|
59
|
+
private messageKind;
|
|
60
|
+
private extractAcpConfigCommand;
|
|
61
|
+
private extractAcpCancelCommand;
|
|
62
|
+
private extractBridgeCommand;
|
|
63
|
+
/**
|
|
64
|
+
* Render a usage hint suffix listing any configured aliases for a
|
|
65
|
+
* canonical command, e.g. " (aliases: /cancel, /取消)". Returns an
|
|
66
|
+
* empty string when no aliases are configured.
|
|
67
|
+
*/
|
|
68
|
+
private aliasHint;
|
|
69
|
+
private formatAcpConfigList;
|
|
70
|
+
private formatAcpConfigUsage;
|
|
71
|
+
private describeCurrentConfigValue;
|
|
72
|
+
private listConfigOptionChoices;
|
|
73
|
+
private resolveAcpConfigValue;
|
|
74
|
+
private flattenSelectOptions;
|
|
75
|
+
private findConfigOptionChoice;
|
|
76
|
+
private configChoiceAliases;
|
|
77
|
+
private describeConfigChoice;
|
|
78
|
+
private extractConfigValueTail;
|
|
79
|
+
/**
|
|
80
|
+
* Scan the reply text for file-path references (markdown links and
|
|
81
|
+
* backtick-enclosed paths), resolve them inside the agent workspace,
|
|
82
|
+
* and send the corresponding files as WeChat media messages.
|
|
83
|
+
*
|
|
84
|
+
* Modeled after codex-wechat's `sendAssistantAttachmentsForReply()` and
|
|
85
|
+
* `extractAutoSendFilePathsFromReply()`.
|
|
86
|
+
*/
|
|
87
|
+
private tryAutoSendMedia;
|
|
88
|
+
/**
|
|
89
|
+
* Extract file-path candidates from reply text.
|
|
90
|
+
*
|
|
91
|
+
* Supports two patterns (matching codex-wechat):
|
|
92
|
+
* - Markdown links: `` or `[text](path)`
|
|
93
|
+
* - Backtick-enclosed paths: `` `path` ``
|
|
94
|
+
*/
|
|
95
|
+
private extractFilePathsFromReply;
|
|
96
|
+
/**
|
|
97
|
+
* Extract file-path candidates tagged with `@send:` marker.
|
|
98
|
+
*
|
|
99
|
+
* Supports patterns:
|
|
100
|
+
* - `@send:path/to/file` — explicit send marker
|
|
101
|
+
* - `📎path/to/file` — emoji send marker
|
|
102
|
+
*
|
|
103
|
+
* Only these explicitly tagged paths are returned; regular file
|
|
104
|
+
* references in code discussions are ignored.
|
|
105
|
+
*/
|
|
106
|
+
private extractTaggedFilePaths;
|
|
107
|
+
/**
|
|
108
|
+
* Strip decorations from a raw path candidate so it resolves cleanly:
|
|
109
|
+
* - `< >` wrapping (auto-linked bare paths on some platforms)
|
|
110
|
+
* - `#L…` line references from editor / code-review links
|
|
111
|
+
* - `file.ext:line:col` suffixes
|
|
112
|
+
*/
|
|
113
|
+
private stripPathDecorations;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA2BpD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,WAAW,CAAqB;IAExC,OAAO,CAAC,aAAa,CAA4D;IAGjF,OAAO,CAAC,UAAU,CAA6B;IAI/C,OAAO,CAAC,UAAU,CAAoC;IAEtD,OAAO,CAAC,cAAc,CAKjB;IAEL,OAAO,CAAC,YAAY,CAAoD;IAKxE,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,GAAG,CAAwB;gBAEvB,MAAM,EAAE,gBAAgB,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI;IAK3D,KAAK,CAAC,IAAI,CAAC,EAAE;QACjB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;KACrC,GAAG,OAAO,CAAC,IAAI,CAAC;IA+EX,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,OAAO,CAAC,aAAa;YAyEP,cAAc;YAed,sBAAsB;YAsBtB,sBAAsB;YAmEtB,sBAAsB;IAmCpC,OAAO,CAAC,qBAAqB;IAoB7B,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,gBAAgB;YAyBV,OAAO;IA4CrB,OAAO,CAAC,cAAc;IAgDtB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,kBAAkB;YAWZ,SAAS;YAgBT,YAAY;IA8E1B;;;;;;;OAOG;YACW,mBAAmB;YAYnB,qBAAqB;YAerB,mBAAmB;YAmBnB,eAAe;IAyB7B,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,oBAAoB;IAyB5B;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,mBAAmB;IAoC3B,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,0BAA0B;IASlC,OAAO,CAAC,uBAAuB;IAK/B,OAAO,CAAC,qBAAqB;IA6C7B,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,sBAAsB;IAgB9B;;;;;;;OAOG;YACW,gBAAgB;IA2D9B;;;;;;OAMG;IACH,OAAO,CAAC,yBAAyB;IAkCjC;;;;;;;;;OASG;IACH,OAAO,CAAC,sBAAsB;IA4B9B;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;CAyB7B"}
|