@xopcai/xopc 0.0.100 → 0.0.101
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/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +5 -3
- package/dist/extensions/weixin/src/api/api.js.map +1 -1
- package/dist/gateway/static/root/assets/{agents-C5jtBK-H.js → agents-u8cmUfGQ.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-smJl-qf_.js → apps-page-DF8m9cUE.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-preview-renderer-DBAxQXb-.js → attachment-preview-renderer-CybMSIoS.js} +2 -2
- package/dist/gateway/static/root/assets/{attachment-process-heavy-Csq3TrrP.js → attachment-process-heavy-RnGYy9bC.js} +2 -2
- package/dist/gateway/static/root/assets/{channels-settings-CH6KgFK6.js → channels-settings-BM3doRvi.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-status-swr-CV70xvY7.js → channels-status-swr-ah4zWEIP.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-CgBO8B7I.js → cron-api-DgMuL_2b.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-Be0cW1cR.js → cron-page-COfUPKfq.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-P8HRGUuh.js → dist-Dzy3Q0ZH.js} +1 -1
- package/dist/gateway/static/root/assets/{docx-preview-Dxj1EkCO.js → docx-preview-CajIk2FR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BowuycYu.js → extension-debug-page-kyxxefKh.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-27-Zpv8O.js → extension-page-BVbCBHoI.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DDFa_rIq.js → extension-settings-page-t1lb2A7v.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives-BWLssxEb.js → field-primitives-6Vo1Yga4.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BVuYNYT_.js → heartbeat-config-api-BF3psu4O.js} +1 -1
- package/dist/gateway/static/root/assets/{index-CRDAmr3W.js → index-WAyKAilR.js} +9 -9
- package/dist/gateway/static/root/assets/{logs-page-BDX8IrDQ.js → logs-page-BTVPXcHV.js} +1 -1
- package/dist/gateway/static/root/assets/{note-detail-page-BmQ9KeiA.js → note-detail-page-DqSAg_5Z.js} +1 -1
- package/dist/gateway/static/root/assets/{note-time-14I9Sgqh.js → note-time-FSOjchic.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-BMfP0FFf.js → notes-page-DkRX7BE2.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-C3scyChq.js → sessions-page-Khdw35Zk.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-advanced-gate-2ODuCjHP.js → settings-advanced-gate-DspC8oEm.js} +2 -2
- package/dist/gateway/static/root/assets/{settings-form-section-DUoGKAiW.js → settings-form-section-DuxvUuur.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-CttAfOWV.js → settings-page-DN8JBZ8F.js} +2 -2
- package/dist/gateway/static/root/assets/{share-preview-page-B77xqiiI.js → share-preview-page-UNAcbiMb.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-B_bAZGzB.js → skills-page-ByYT0fXZ.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-BgCPrmxU.js → theme-store-B6KXPHgK.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-CCGejlcX.js → utils-DK_1H47k.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-DZzzihcY.js → voice-api-key-field-BYN2EIMs.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-page.utils-D5RMAmT4.js → workflow-page.utils-Bi19YNTr.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-DEYpC6Bv.js → workflows-page-DP57FEKW.js} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +16 -0
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/embedded/run-for-session.js +1 -0
- package/dist/src/agent/embedded/run-for-session.js.map +1 -1
- package/dist/src/auth/credentials.js +0 -1
- package/dist/src/auth/credentials.js.map +1 -1
- package/dist/src/cli/bin.d.ts +1 -0
- package/dist/src/cli/bin.js +1 -0
- package/dist/src/cli/bin.js.map +1 -1
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/oauth-async.js +36 -3
- package/dist/src/gateway/hono/oauth-async.js.map +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/http-proxy-env.d.ts +4 -0
- package/dist/src/infra/http-proxy-env.js +23 -0
- package/dist/src/infra/http-proxy-env.js.map +1 -0
- package/package.json +3 -3
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "telegram",
|
|
3
3
|
"name": "Telegram Channel",
|
|
4
4
|
"description": "Bundled Telegram Bot channel (private workspace sources; ships inside @xopcai/xopc dist/)",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.101",
|
|
6
6
|
"kind": "channel",
|
|
7
7
|
"main": "src/index.ts",
|
|
8
8
|
"channels": ["telegram"],
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { logger } from "../util/logger.js";
|
|
2
|
+
import { hasProxyEnv } from "../../../../src/infra/http-proxy-env.js";
|
|
2
3
|
import { redactBody, redactUrl } from "../util/redact.js";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import fs from "node:fs";
|
|
5
6
|
import crypto from "node:crypto";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { Agent, fetch as fetch$1 } from "undici";
|
|
8
|
+
import { Agent, EnvHttpProxyAgent, fetch as fetch$1 } from "undici";
|
|
8
9
|
//#region extensions/weixin/src/api/api.ts
|
|
9
10
|
function readPackageJson() {
|
|
10
11
|
try {
|
|
@@ -152,11 +153,12 @@ async function apiPostFetch(params) {
|
|
|
152
153
|
async function getUpdates(params) {
|
|
153
154
|
const timeout = params.timeoutMs ?? DEFAULT_LONG_POLL_TIMEOUT_MS;
|
|
154
155
|
const headersTimeout = timeout + LONG_POLL_HEADERS_SLACK_MS;
|
|
155
|
-
const
|
|
156
|
+
const agentOpts = {
|
|
156
157
|
connectTimeout: 6e4,
|
|
157
158
|
headersTimeout,
|
|
158
159
|
bodyTimeout: headersTimeout
|
|
159
|
-
}
|
|
160
|
+
};
|
|
161
|
+
const agent = hasProxyEnv() ? new EnvHttpProxyAgent(agentOpts) : new Agent(agentOpts);
|
|
160
162
|
try {
|
|
161
163
|
const rawText = await apiPostFetch({
|
|
162
164
|
baseUrl: params.baseUrl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","names":["undiciFetch"],"sources":["../../../../../extensions/weixin/src/api/api.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { Agent, type Dispatcher, fetch as undiciFetch } from \"undici\";\n\nimport { logger } from \"../util/logger.js\";\nimport { redactBody, redactUrl } from \"../util/redact.js\";\n\nimport type {\n BaseInfo,\n GetUploadUrlReq,\n GetUploadUrlResp,\n GetUpdatesReq,\n GetUpdatesResp,\n SendMessageReq,\n SendMessageResp,\n SendTypingReq,\n GetConfigResp,\n} from \"./types.js\";\n\nexport type WeixinApiOptions = {\n baseUrl: string;\n token?: string;\n timeoutMs?: number;\n /** Long-poll timeout for getUpdates (server may hold the request up to this). */\n longPollTimeoutMs?: number;\n /** Optional ilink SKRouteTag (from config / account). */\n routeTag?: string;\n};\n\n// ---------------------------------------------------------------------------\n// BaseInfo — attached to every outgoing CGI request\n// ---------------------------------------------------------------------------\n\ninterface PackageJson {\n name?: string;\n version?: string;\n ilink_appid?: string;\n}\n\nfunction readPackageJson(): PackageJson {\n try {\n const dir = path.dirname(fileURLToPath(import.meta.url));\n const pkgPath = path.resolve(dir, \"..\", \"..\", \"package.json\");\n return JSON.parse(fs.readFileSync(pkgPath, \"utf-8\")) as PackageJson;\n } catch {\n return {};\n }\n}\n\nconst pkg = readPackageJson();\n\nconst CHANNEL_VERSION = pkg.version ?? \"unknown\";\n\n/** iLink-App-Id: from package.json `ilink_appid`. */\nconst ILINK_APP_ID: string = pkg.ilink_appid ?? \"\";\n\n/**\n * iLink-App-ClientVersion: uint32 encoded as 0x00MMNNPP\n * High 8 bits fixed to 0; remaining bits: major<<16 | minor<<8 | patch.\n */\nfunction buildClientVersion(version: string): number {\n const parts = version.split(\".\").map((p) => parseInt(p, 10));\n const major = parts[0] ?? 0;\n const minor = parts[1] ?? 0;\n const patch = parts[2] ?? 0;\n return ((major & 0xff) << 16) | ((minor & 0xff) << 8) | (patch & 0xff);\n}\n\nconst ILINK_APP_CLIENT_VERSION: number = buildClientVersion(pkg.version ?? \"0.0.0\");\n\n/** Build the `base_info` payload included in every API request. */\nexport function buildBaseInfo(): BaseInfo {\n return { channel_version: CHANNEL_VERSION };\n}\n\n/** Default timeout for long-poll getUpdates requests. */\nconst DEFAULT_LONG_POLL_TIMEOUT_MS = 35_000;\n/** Extra time beyond client long-poll timeout for undici `headersTimeout` (server may idle before first byte). */\nconst LONG_POLL_HEADERS_SLACK_MS = 15_000;\n/** Default timeout for regular API requests (sendMessage, getUploadUrl). */\nconst DEFAULT_API_TIMEOUT_MS = 15_000;\n/** Default timeout for lightweight API requests (getConfig, sendTyping). */\nconst DEFAULT_CONFIG_TIMEOUT_MS = 10_000;\n\nfunction ensureTrailingSlash(url: string): string {\n return url.endsWith(\"/\") ? url : `${url}/`;\n}\n\nfunction isUndiciHeadersTimeout(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n (err as { code?: string }).code === \"UND_ERR_HEADERS_TIMEOUT\"\n );\n}\n\n/** X-WECHAT-UIN header: random uint32 -> decimal string -> base64. */\nfunction randomWechatUin(): string {\n const uint32 = crypto.randomBytes(4).readUInt32BE(0);\n return Buffer.from(String(uint32), \"utf-8\").toString(\"base64\");\n}\n\n/** Build headers shared by GET and POST requests. */\nfunction buildCommonHeaders(routeTag?: string): Record<string, string> {\n const headers: Record<string, string> = {\n \"iLink-App-Id\": ILINK_APP_ID,\n \"iLink-App-ClientVersion\": String(ILINK_APP_CLIENT_VERSION),\n };\n const tag = routeTag?.trim();\n if (tag) {\n headers.SKRouteTag = tag;\n }\n return headers;\n}\n\nfunction buildHeaders(opts: { token?: string; body: string; routeTag?: string }): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n AuthorizationType: \"ilink_bot_token\",\n \"Content-Length\": String(Buffer.byteLength(opts.body, \"utf-8\")),\n \"X-WECHAT-UIN\": randomWechatUin(),\n ...buildCommonHeaders(opts.routeTag),\n };\n if (opts.token?.trim()) {\n headers.Authorization = `Bearer ${opts.token.trim()}`;\n }\n logger.debug(\n `requestHeaders: ${JSON.stringify({ ...headers, Authorization: headers.Authorization ? \"Bearer ***\" : undefined })}`,\n );\n return headers;\n}\n\n/**\n * GET fetch wrapper (QR login and other GET endpoints).\n */\nexport async function apiGetFetch(params: {\n baseUrl: string;\n endpoint: string;\n timeoutMs?: number;\n label: string;\n routeTag?: string;\n}): Promise<string> {\n const base = ensureTrailingSlash(params.baseUrl);\n const url = new URL(params.endpoint, base);\n const hdrs = buildCommonHeaders(params.routeTag);\n logger.debug(`GET ${redactUrl(url.toString())}`);\n\n const timeoutMs = params.timeoutMs;\n const controller =\n timeoutMs != null && timeoutMs > 0 ? new AbortController() : undefined;\n const t =\n controller != null && timeoutMs != null\n ? setTimeout(() => controller.abort(), timeoutMs)\n : undefined;\n try {\n const res = await fetch(url.toString(), {\n method: \"GET\",\n headers: hdrs,\n ...(controller ? { signal: controller.signal } : {}),\n // 复用连接,避免 VPN/网络不稳定时卡住\n keepalive: true,\n });\n if (t !== undefined) clearTimeout(t);\n const rawText = await res.text();\n logger.debug(`${params.label} status=${res.status} raw=${redactBody(rawText)}`);\n if (!res.ok) {\n throw new Error(`${params.label} ${res.status}: ${rawText}`);\n }\n return rawText;\n } catch (err) {\n if (t !== undefined) clearTimeout(t);\n throw err;\n }\n}\n\n/**\n * Common POST fetch wrapper: POST JSON to a Weixin API endpoint with timeout + abort.\n */\nasync function apiPostFetch(params: {\n baseUrl: string;\n endpoint: string;\n body: string;\n token?: string;\n timeoutMs: number;\n label: string;\n routeTag?: string;\n dispatcher?: Dispatcher;\n keepalive?: boolean;\n abortSignal?: AbortSignal;\n}): Promise<string> {\n const base = ensureTrailingSlash(params.baseUrl);\n const url = new URL(params.endpoint, base);\n const hdrs = buildHeaders({ token: params.token, body: params.body, routeTag: params.routeTag });\n logger.debug(`POST ${redactUrl(url.toString())} body=${redactBody(params.body)}`);\n\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), params.timeoutMs);\n const signal =\n params.abortSignal != null\n ? AbortSignal.any([controller.signal, params.abortSignal])\n : controller.signal;\n const keepalive = params.keepalive ?? true;\n try {\n const init: RequestInit = {\n method: \"POST\",\n headers: hdrs,\n body: params.body,\n signal,\n keepalive,\n };\n // `dispatcher` is an undici extension. Node's `fetch` types come from `undici-types`,\n // which may not match the installed undici version's `Dispatcher` type.\n if (params.dispatcher) (init as any).dispatcher = params.dispatcher;\n\n // Use undici's fetch implementation so `dispatcher` is interpreted consistently.\n const res = await undiciFetch(url.toString(), init as any);\n clearTimeout(t);\n const rawText = await res.text();\n logger.debug(`${params.label} status=${res.status} raw=${redactBody(rawText)}`);\n if (!res.ok) {\n throw new Error(`${params.label} ${res.status}: ${rawText}`);\n }\n return rawText;\n } catch (err) {\n clearTimeout(t);\n throw err;\n }\n}\n\n/**\n * Long-poll getUpdates. Server should hold the request until new messages or timeout.\n *\n * On client-side timeout (no server response within timeoutMs), returns an empty response\n * with ret=0 so the caller can simply retry. This is normal for long-poll.\n */\nexport async function getUpdates(\n params: GetUpdatesReq & {\n baseUrl: string;\n token?: string;\n timeoutMs?: number;\n routeTag?: string;\n abortSignal?: AbortSignal;\n },\n): Promise<GetUpdatesResp> {\n const timeout = params.timeoutMs ?? DEFAULT_LONG_POLL_TIMEOUT_MS;\n const headersTimeout = timeout + LONG_POLL_HEADERS_SLACK_MS;\n const agent = new Agent({\n connectTimeout: 60_000,\n headersTimeout,\n bodyTimeout: headersTimeout,\n });\n try {\n const rawText = await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/getupdates\",\n body: JSON.stringify({\n get_updates_buf: params.get_updates_buf ?? \"\",\n base_info: buildBaseInfo(),\n }),\n token: params.token,\n timeoutMs: timeout,\n label: \"getUpdates\",\n routeTag: params.routeTag,\n dispatcher: agent,\n keepalive: true,\n abortSignal: params.abortSignal,\n });\n const resp: GetUpdatesResp = JSON.parse(rawText);\n return resp;\n } catch (err) {\n if (params.abortSignal?.aborted && err instanceof Error && err.name === \"AbortError\") {\n throw err;\n }\n if (err instanceof Error && err.name === \"AbortError\") {\n logger.debug(`getUpdates: client-side timeout after ${timeout}ms, returning empty response`);\n return { ret: 0, msgs: [], get_updates_buf: params.get_updates_buf };\n }\n if (isUndiciHeadersTimeout(err)) {\n logger.debug(\n `getUpdates: undici headers timeout (UND_ERR_HEADERS_TIMEOUT), returning empty response`,\n );\n return { ret: 0, msgs: [], get_updates_buf: params.get_updates_buf ?? \"\" };\n }\n throw err;\n } finally {\n try {\n await agent.close();\n } catch {\n // ignore\n }\n }\n}\n\n/** Get a pre-signed CDN upload URL for a file. */\nexport async function getUploadUrl(\n params: GetUploadUrlReq & WeixinApiOptions,\n): Promise<GetUploadUrlResp> {\n const rawText = await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/getuploadurl\",\n body: JSON.stringify({\n filekey: params.filekey,\n media_type: params.media_type,\n to_user_id: params.to_user_id,\n rawsize: params.rawsize,\n rawfilemd5: params.rawfilemd5,\n filesize: params.filesize,\n thumb_rawsize: params.thumb_rawsize,\n thumb_rawfilemd5: params.thumb_rawfilemd5,\n thumb_filesize: params.thumb_filesize,\n no_need_thumb: params.no_need_thumb,\n aeskey: params.aeskey,\n base_info: buildBaseInfo(),\n }),\n token: params.token,\n timeoutMs: params.timeoutMs ?? DEFAULT_API_TIMEOUT_MS,\n label: \"getUploadUrl\",\n routeTag: params.routeTag,\n });\n const resp: GetUploadUrlResp = JSON.parse(rawText);\n return resp;\n}\n\nfunction assertSendMessageOk(resp: SendMessageResp): void {\n if (typeof resp.ret === \"number\" && resp.ret !== 0) {\n throw new Error(`sendMessage ret=${resp.ret} errmsg=${resp.errmsg ?? \"\"}`);\n }\n if (typeof resp.errcode === \"number\" && resp.errcode !== 0) {\n throw new Error(`sendMessage errcode=${resp.errcode} errmsg=${resp.errmsg ?? \"\"}`);\n }\n}\n\n/** Send a single message downstream. Returns parsed body (incl. refreshed `context_token` when present). */\nexport async function sendMessage(\n params: WeixinApiOptions & { body: SendMessageReq },\n): Promise<SendMessageResp> {\n const rawText = await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/sendmessage\",\n body: JSON.stringify({ ...params.body, base_info: buildBaseInfo() }),\n token: params.token,\n timeoutMs: params.timeoutMs ?? DEFAULT_API_TIMEOUT_MS,\n label: \"sendMessage\",\n routeTag: params.routeTag,\n });\n const t = rawText.trim();\n if (!t.startsWith(\"{\")) {\n return {};\n }\n let resp: SendMessageResp;\n try {\n resp = JSON.parse(t) as SendMessageResp;\n } catch (e) {\n throw new Error(`sendMessage invalid JSON: ${String(e)}`);\n }\n assertSendMessageOk(resp);\n return resp;\n}\n\n/** Fetch bot config (includes typing_ticket) for a given user. */\nexport async function getConfig(\n params: WeixinApiOptions & { ilinkUserId: string; contextToken?: string },\n): Promise<GetConfigResp> {\n const rawText = await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/getconfig\",\n body: JSON.stringify({\n ilink_user_id: params.ilinkUserId,\n context_token: params.contextToken,\n base_info: buildBaseInfo(),\n }),\n token: params.token,\n timeoutMs: params.timeoutMs ?? DEFAULT_CONFIG_TIMEOUT_MS,\n label: \"getConfig\",\n routeTag: params.routeTag,\n });\n const resp: GetConfigResp = JSON.parse(rawText);\n return resp;\n}\n\n/** Send a typing indicator to a user. */\nexport async function sendTyping(\n params: WeixinApiOptions & { body: SendTypingReq },\n): Promise<void> {\n await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/sendtyping\",\n body: JSON.stringify({ ...params.body, base_info: buildBaseInfo() }),\n token: params.token,\n timeoutMs: params.timeoutMs ?? DEFAULT_CONFIG_TIMEOUT_MS,\n label: \"sendTyping\",\n routeTag: params.routeTag,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.js","names":["undiciFetch"],"sources":["../../../../../extensions/weixin/src/api/api.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { Agent, EnvHttpProxyAgent, type Dispatcher, fetch as undiciFetch } from \"undici\";\n\nimport { hasProxyEnv } from \"../../../../src/infra/http-proxy-env.js\";\n\nimport { logger } from \"../util/logger.js\";\nimport { redactBody, redactUrl } from \"../util/redact.js\";\n\nimport type {\n BaseInfo,\n GetUploadUrlReq,\n GetUploadUrlResp,\n GetUpdatesReq,\n GetUpdatesResp,\n SendMessageReq,\n SendMessageResp,\n SendTypingReq,\n GetConfigResp,\n} from \"./types.js\";\n\nexport type WeixinApiOptions = {\n baseUrl: string;\n token?: string;\n timeoutMs?: number;\n /** Long-poll timeout for getUpdates (server may hold the request up to this). */\n longPollTimeoutMs?: number;\n /** Optional ilink SKRouteTag (from config / account). */\n routeTag?: string;\n};\n\n// ---------------------------------------------------------------------------\n// BaseInfo — attached to every outgoing CGI request\n// ---------------------------------------------------------------------------\n\ninterface PackageJson {\n name?: string;\n version?: string;\n ilink_appid?: string;\n}\n\nfunction readPackageJson(): PackageJson {\n try {\n const dir = path.dirname(fileURLToPath(import.meta.url));\n const pkgPath = path.resolve(dir, \"..\", \"..\", \"package.json\");\n return JSON.parse(fs.readFileSync(pkgPath, \"utf-8\")) as PackageJson;\n } catch {\n return {};\n }\n}\n\nconst pkg = readPackageJson();\n\nconst CHANNEL_VERSION = pkg.version ?? \"unknown\";\n\n/** iLink-App-Id: from package.json `ilink_appid`. */\nconst ILINK_APP_ID: string = pkg.ilink_appid ?? \"\";\n\n/**\n * iLink-App-ClientVersion: uint32 encoded as 0x00MMNNPP\n * High 8 bits fixed to 0; remaining bits: major<<16 | minor<<8 | patch.\n */\nfunction buildClientVersion(version: string): number {\n const parts = version.split(\".\").map((p) => parseInt(p, 10));\n const major = parts[0] ?? 0;\n const minor = parts[1] ?? 0;\n const patch = parts[2] ?? 0;\n return ((major & 0xff) << 16) | ((minor & 0xff) << 8) | (patch & 0xff);\n}\n\nconst ILINK_APP_CLIENT_VERSION: number = buildClientVersion(pkg.version ?? \"0.0.0\");\n\n/** Build the `base_info` payload included in every API request. */\nexport function buildBaseInfo(): BaseInfo {\n return { channel_version: CHANNEL_VERSION };\n}\n\n/** Default timeout for long-poll getUpdates requests. */\nconst DEFAULT_LONG_POLL_TIMEOUT_MS = 35_000;\n/** Extra time beyond client long-poll timeout for undici `headersTimeout` (server may idle before first byte). */\nconst LONG_POLL_HEADERS_SLACK_MS = 15_000;\n/** Default timeout for regular API requests (sendMessage, getUploadUrl). */\nconst DEFAULT_API_TIMEOUT_MS = 15_000;\n/** Default timeout for lightweight API requests (getConfig, sendTyping). */\nconst DEFAULT_CONFIG_TIMEOUT_MS = 10_000;\n\nfunction ensureTrailingSlash(url: string): string {\n return url.endsWith(\"/\") ? url : `${url}/`;\n}\n\nfunction isUndiciHeadersTimeout(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n (err as { code?: string }).code === \"UND_ERR_HEADERS_TIMEOUT\"\n );\n}\n\n/** X-WECHAT-UIN header: random uint32 -> decimal string -> base64. */\nfunction randomWechatUin(): string {\n const uint32 = crypto.randomBytes(4).readUInt32BE(0);\n return Buffer.from(String(uint32), \"utf-8\").toString(\"base64\");\n}\n\n/** Build headers shared by GET and POST requests. */\nfunction buildCommonHeaders(routeTag?: string): Record<string, string> {\n const headers: Record<string, string> = {\n \"iLink-App-Id\": ILINK_APP_ID,\n \"iLink-App-ClientVersion\": String(ILINK_APP_CLIENT_VERSION),\n };\n const tag = routeTag?.trim();\n if (tag) {\n headers.SKRouteTag = tag;\n }\n return headers;\n}\n\nfunction buildHeaders(opts: { token?: string; body: string; routeTag?: string }): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n AuthorizationType: \"ilink_bot_token\",\n \"Content-Length\": String(Buffer.byteLength(opts.body, \"utf-8\")),\n \"X-WECHAT-UIN\": randomWechatUin(),\n ...buildCommonHeaders(opts.routeTag),\n };\n if (opts.token?.trim()) {\n headers.Authorization = `Bearer ${opts.token.trim()}`;\n }\n logger.debug(\n `requestHeaders: ${JSON.stringify({ ...headers, Authorization: headers.Authorization ? \"Bearer ***\" : undefined })}`,\n );\n return headers;\n}\n\n/**\n * GET fetch wrapper (QR login and other GET endpoints).\n */\nexport async function apiGetFetch(params: {\n baseUrl: string;\n endpoint: string;\n timeoutMs?: number;\n label: string;\n routeTag?: string;\n}): Promise<string> {\n const base = ensureTrailingSlash(params.baseUrl);\n const url = new URL(params.endpoint, base);\n const hdrs = buildCommonHeaders(params.routeTag);\n logger.debug(`GET ${redactUrl(url.toString())}`);\n\n const timeoutMs = params.timeoutMs;\n const controller =\n timeoutMs != null && timeoutMs > 0 ? new AbortController() : undefined;\n const t =\n controller != null && timeoutMs != null\n ? setTimeout(() => controller.abort(), timeoutMs)\n : undefined;\n try {\n const res = await fetch(url.toString(), {\n method: \"GET\",\n headers: hdrs,\n ...(controller ? { signal: controller.signal } : {}),\n // 复用连接,避免 VPN/网络不稳定时卡住\n keepalive: true,\n });\n if (t !== undefined) clearTimeout(t);\n const rawText = await res.text();\n logger.debug(`${params.label} status=${res.status} raw=${redactBody(rawText)}`);\n if (!res.ok) {\n throw new Error(`${params.label} ${res.status}: ${rawText}`);\n }\n return rawText;\n } catch (err) {\n if (t !== undefined) clearTimeout(t);\n throw err;\n }\n}\n\n/**\n * Common POST fetch wrapper: POST JSON to a Weixin API endpoint with timeout + abort.\n */\nasync function apiPostFetch(params: {\n baseUrl: string;\n endpoint: string;\n body: string;\n token?: string;\n timeoutMs: number;\n label: string;\n routeTag?: string;\n dispatcher?: Dispatcher;\n keepalive?: boolean;\n abortSignal?: AbortSignal;\n}): Promise<string> {\n const base = ensureTrailingSlash(params.baseUrl);\n const url = new URL(params.endpoint, base);\n const hdrs = buildHeaders({ token: params.token, body: params.body, routeTag: params.routeTag });\n logger.debug(`POST ${redactUrl(url.toString())} body=${redactBody(params.body)}`);\n\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), params.timeoutMs);\n const signal =\n params.abortSignal != null\n ? AbortSignal.any([controller.signal, params.abortSignal])\n : controller.signal;\n const keepalive = params.keepalive ?? true;\n try {\n const init: RequestInit = {\n method: \"POST\",\n headers: hdrs,\n body: params.body,\n signal,\n keepalive,\n };\n // `dispatcher` is an undici extension. Node's `fetch` types come from `undici-types`,\n // which may not match the installed undici version's `Dispatcher` type.\n if (params.dispatcher) (init as any).dispatcher = params.dispatcher;\n\n // Use undici's fetch implementation so `dispatcher` is interpreted consistently.\n const res = await undiciFetch(url.toString(), init as any);\n clearTimeout(t);\n const rawText = await res.text();\n logger.debug(`${params.label} status=${res.status} raw=${redactBody(rawText)}`);\n if (!res.ok) {\n throw new Error(`${params.label} ${res.status}: ${rawText}`);\n }\n return rawText;\n } catch (err) {\n clearTimeout(t);\n throw err;\n }\n}\n\n/**\n * Long-poll getUpdates. Server should hold the request until new messages or timeout.\n *\n * On client-side timeout (no server response within timeoutMs), returns an empty response\n * with ret=0 so the caller can simply retry. This is normal for long-poll.\n */\nexport async function getUpdates(\n params: GetUpdatesReq & {\n baseUrl: string;\n token?: string;\n timeoutMs?: number;\n routeTag?: string;\n abortSignal?: AbortSignal;\n },\n): Promise<GetUpdatesResp> {\n const timeout = params.timeoutMs ?? DEFAULT_LONG_POLL_TIMEOUT_MS;\n const headersTimeout = timeout + LONG_POLL_HEADERS_SLACK_MS;\n const agentOpts = {\n connectTimeout: 60_000,\n headersTimeout,\n bodyTimeout: headersTimeout,\n };\n const agent = hasProxyEnv() ? new EnvHttpProxyAgent(agentOpts) : new Agent(agentOpts);\n try {\n const rawText = await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/getupdates\",\n body: JSON.stringify({\n get_updates_buf: params.get_updates_buf ?? \"\",\n base_info: buildBaseInfo(),\n }),\n token: params.token,\n timeoutMs: timeout,\n label: \"getUpdates\",\n routeTag: params.routeTag,\n dispatcher: agent,\n keepalive: true,\n abortSignal: params.abortSignal,\n });\n const resp: GetUpdatesResp = JSON.parse(rawText);\n return resp;\n } catch (err) {\n if (params.abortSignal?.aborted && err instanceof Error && err.name === \"AbortError\") {\n throw err;\n }\n if (err instanceof Error && err.name === \"AbortError\") {\n logger.debug(`getUpdates: client-side timeout after ${timeout}ms, returning empty response`);\n return { ret: 0, msgs: [], get_updates_buf: params.get_updates_buf };\n }\n if (isUndiciHeadersTimeout(err)) {\n logger.debug(\n `getUpdates: undici headers timeout (UND_ERR_HEADERS_TIMEOUT), returning empty response`,\n );\n return { ret: 0, msgs: [], get_updates_buf: params.get_updates_buf ?? \"\" };\n }\n throw err;\n } finally {\n try {\n await agent.close();\n } catch {\n // ignore\n }\n }\n}\n\n/** Get a pre-signed CDN upload URL for a file. */\nexport async function getUploadUrl(\n params: GetUploadUrlReq & WeixinApiOptions,\n): Promise<GetUploadUrlResp> {\n const rawText = await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/getuploadurl\",\n body: JSON.stringify({\n filekey: params.filekey,\n media_type: params.media_type,\n to_user_id: params.to_user_id,\n rawsize: params.rawsize,\n rawfilemd5: params.rawfilemd5,\n filesize: params.filesize,\n thumb_rawsize: params.thumb_rawsize,\n thumb_rawfilemd5: params.thumb_rawfilemd5,\n thumb_filesize: params.thumb_filesize,\n no_need_thumb: params.no_need_thumb,\n aeskey: params.aeskey,\n base_info: buildBaseInfo(),\n }),\n token: params.token,\n timeoutMs: params.timeoutMs ?? DEFAULT_API_TIMEOUT_MS,\n label: \"getUploadUrl\",\n routeTag: params.routeTag,\n });\n const resp: GetUploadUrlResp = JSON.parse(rawText);\n return resp;\n}\n\nfunction assertSendMessageOk(resp: SendMessageResp): void {\n if (typeof resp.ret === \"number\" && resp.ret !== 0) {\n throw new Error(`sendMessage ret=${resp.ret} errmsg=${resp.errmsg ?? \"\"}`);\n }\n if (typeof resp.errcode === \"number\" && resp.errcode !== 0) {\n throw new Error(`sendMessage errcode=${resp.errcode} errmsg=${resp.errmsg ?? \"\"}`);\n }\n}\n\n/** Send a single message downstream. Returns parsed body (incl. refreshed `context_token` when present). */\nexport async function sendMessage(\n params: WeixinApiOptions & { body: SendMessageReq },\n): Promise<SendMessageResp> {\n const rawText = await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/sendmessage\",\n body: JSON.stringify({ ...params.body, base_info: buildBaseInfo() }),\n token: params.token,\n timeoutMs: params.timeoutMs ?? DEFAULT_API_TIMEOUT_MS,\n label: \"sendMessage\",\n routeTag: params.routeTag,\n });\n const t = rawText.trim();\n if (!t.startsWith(\"{\")) {\n return {};\n }\n let resp: SendMessageResp;\n try {\n resp = JSON.parse(t) as SendMessageResp;\n } catch (e) {\n throw new Error(`sendMessage invalid JSON: ${String(e)}`);\n }\n assertSendMessageOk(resp);\n return resp;\n}\n\n/** Fetch bot config (includes typing_ticket) for a given user. */\nexport async function getConfig(\n params: WeixinApiOptions & { ilinkUserId: string; contextToken?: string },\n): Promise<GetConfigResp> {\n const rawText = await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/getconfig\",\n body: JSON.stringify({\n ilink_user_id: params.ilinkUserId,\n context_token: params.contextToken,\n base_info: buildBaseInfo(),\n }),\n token: params.token,\n timeoutMs: params.timeoutMs ?? DEFAULT_CONFIG_TIMEOUT_MS,\n label: \"getConfig\",\n routeTag: params.routeTag,\n });\n const resp: GetConfigResp = JSON.parse(rawText);\n return resp;\n}\n\n/** Send a typing indicator to a user. */\nexport async function sendTyping(\n params: WeixinApiOptions & { body: SendTypingReq },\n): Promise<void> {\n await apiPostFetch({\n baseUrl: params.baseUrl,\n endpoint: \"ilink/bot/sendtyping\",\n body: JSON.stringify({ ...params.body, base_info: buildBaseInfo() }),\n token: params.token,\n timeoutMs: params.timeoutMs ?? DEFAULT_CONFIG_TIMEOUT_MS,\n label: \"sendTyping\",\n routeTag: params.routeTag,\n });\n}\n"],"mappings":"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"}
|