@0xmaxma/claude-gateway 1.8.13 → 1.8.14
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.md +8 -0
- package/dist/agent/runner.d.ts +17 -0
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +187 -14
- package/dist/agent/runner.js.map +1 -1
- package/dist/api/router.d.ts.map +1 -1
- package/dist/api/router.js +237 -1
- package/dist/api/router.js.map +1 -1
- package/dist/api/wechat-access.d.ts +45 -0
- package/dist/api/wechat-access.d.ts.map +1 -0
- package/dist/api/wechat-access.js +48 -0
- package/dist/api/wechat-access.js.map +1 -0
- package/dist/history/types.d.ts +10 -1
- package/dist/history/types.d.ts.map +1 -1
- package/dist/history/types.js +10 -1
- package/dist/history/types.js.map +1 -1
- package/dist/session/process.d.ts.map +1 -1
- package/dist/session/process.js +1 -0
- package/dist/session/process.js.map +1 -1
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/wechat/ilink-client.d.ts +194 -0
- package/dist/wechat/ilink-client.d.ts.map +1 -0
- package/dist/wechat/ilink-client.js +641 -0
- package/dist/wechat/ilink-client.js.map +1 -0
- package/dist/wechat/manager.d.ts +93 -0
- package/dist/wechat/manager.d.ts.map +1 -0
- package/dist/wechat/manager.js +409 -0
- package/dist/wechat/manager.js.map +1 -0
- package/mcp/server.ts +2 -0
- package/mcp/tools/wechat/client.ts +49 -0
- package/mcp/tools/wechat/module.ts +88 -0
- package/package.json +1 -1
package/dist/api/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/api/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAW,QAAQ,EAAE,MAAM,SAAS,CAAC;AAOpD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAe,WAAW,EAAe,MAAM,UAAU,CAAC;AAoFtF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAExD;AAMD,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAEtD;AAuED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CA4CjD;AAmUD,wBAAgB,eAAe,CAC7B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EACtC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EACtC,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,WAAW,EAAE,GACrB,MAAM,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/api/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAW,QAAQ,EAAE,MAAM,SAAS,CAAC;AAOpD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAe,WAAW,EAAe,MAAM,UAAU,CAAC;AAoFtF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAExD;AAMD,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAEtD;AAuED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CA4CjD;AAmUD,wBAAgB,eAAe,CAC7B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EACtC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EACtC,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,WAAW,EAAE,GACrB,MAAM,CAytIR"}
|
package/dist/api/router.js
CHANGED
|
@@ -1008,6 +1008,13 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
1008
1008
|
whatsapp_cloud_dm_allowlist: cfg.whatsapp_cloud?.appSecret ? (cfg.whatsapp_cloud?.dmAllowlist ?? []) : null,
|
|
1009
1009
|
whatsapp_cloud_pairing: cfg.whatsapp_cloud?.appSecret ? (cfg.whatsapp_cloud?.pairing ?? true) : null,
|
|
1010
1010
|
whatsapp_cloud_templates_enabled: cfg.whatsapp_cloud?.appSecret ? (cfg.whatsapp_cloud?.templatesEnabled ?? false) : null,
|
|
1011
|
+
// WeChat — "connected" is LIVE manager state (a linked QR session),
|
|
1012
|
+
// never config-derived (there is no credential field to check — see
|
|
1013
|
+
// AgentConfig.wechat's doc comment). DM-only: no group_* fields exist.
|
|
1014
|
+
wechat_connected: agentRunners.get(id)?.getWeChatStatus?.()?.status === 'linked',
|
|
1015
|
+
wechat_dm_policy: cfg.wechat?.dmPolicy ?? null,
|
|
1016
|
+
wechat_dm_allowlist: cfg.wechat?.dmAllowlist ?? [],
|
|
1017
|
+
wechat_pairing: cfg.wechat?.pairing ?? true,
|
|
1011
1018
|
}));
|
|
1012
1019
|
res.json({ agents });
|
|
1013
1020
|
});
|
|
@@ -1760,7 +1767,7 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
1760
1767
|
return;
|
|
1761
1768
|
}
|
|
1762
1769
|
const body = req.body;
|
|
1763
|
-
const { name, description, model, allow_tools, telegram_bot_token, discord_bot_token, line_channel_access_token, line_channel_secret, line_dm_policy, line_dm_allowlist, line_group_policy, line_group_allowlist, line_require_mention, line_pairing, slack_bot_token, slack_signing_secret, slack_dm_policy, slack_dm_allowlist, slack_group_policy, slack_group_allowlist, slack_require_mention, slack_pairing, connectors, whatsapp_account_id, whatsapp_dm_policy, whatsapp_dm_allowlist, whatsapp_group_policy, whatsapp_group_allowlist, whatsapp_require_mention, whatsapp_pairing, whatsapp_cloud_access_token, whatsapp_cloud_phone_number_id, whatsapp_cloud_app_secret, whatsapp_cloud_verify_token, whatsapp_cloud_dm_policy, whatsapp_cloud_dm_allowlist, whatsapp_cloud_pairing, whatsapp_cloud_templates_enabled } = body;
|
|
1770
|
+
const { name, description, model, allow_tools, telegram_bot_token, discord_bot_token, line_channel_access_token, line_channel_secret, line_dm_policy, line_dm_allowlist, line_group_policy, line_group_allowlist, line_require_mention, line_pairing, slack_bot_token, slack_signing_secret, slack_dm_policy, slack_dm_allowlist, slack_group_policy, slack_group_allowlist, slack_require_mention, slack_pairing, connectors, whatsapp_account_id, whatsapp_dm_policy, whatsapp_dm_allowlist, whatsapp_group_policy, whatsapp_group_allowlist, whatsapp_require_mention, whatsapp_pairing, whatsapp_cloud_access_token, whatsapp_cloud_phone_number_id, whatsapp_cloud_app_secret, whatsapp_cloud_verify_token, whatsapp_cloud_dm_policy, whatsapp_cloud_dm_allowlist, whatsapp_cloud_pairing, whatsapp_cloud_templates_enabled, wechat_dm_policy, wechat_dm_allowlist, wechat_pairing } = body;
|
|
1764
1771
|
if (name !== undefined && name !== null && typeof name !== 'string') {
|
|
1765
1772
|
res.status(400).json({ error: 'name must be a string or null' });
|
|
1766
1773
|
return;
|
|
@@ -1912,6 +1919,29 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
1912
1919
|
const slackAccessTouched = slack_dm_policy !== undefined || slack_dm_allowlist !== undefined ||
|
|
1913
1920
|
slack_group_policy !== undefined || slack_group_allowlist !== undefined || slack_require_mention !== undefined ||
|
|
1914
1921
|
slack_pairing !== undefined;
|
|
1922
|
+
// WeChat — DM-only access control (no credential, no group tier: see
|
|
1923
|
+
// AgentConfig.wechat's doc comment for why). Unlike LINE/Slack's access
|
|
1924
|
+
// fields, this is NOT gated on an existing wechat block already being
|
|
1925
|
+
// present — linking happens out-of-band (QR scan, via the /wechat/link
|
|
1926
|
+
// route below) and never touches config.json, so policy must be settable
|
|
1927
|
+
// independent of link status.
|
|
1928
|
+
if (wechat_dm_policy !== undefined && wechat_dm_policy !== null &&
|
|
1929
|
+
!(typeof wechat_dm_policy === 'string' && ['open', 'allowlist', 'disabled'].includes(wechat_dm_policy))) {
|
|
1930
|
+
res.status(400).json({ error: "wechat_dm_policy must be 'open', 'allowlist', 'disabled', or null" });
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
if (wechat_dm_allowlist !== undefined && wechat_dm_allowlist !== null &&
|
|
1934
|
+
!(Array.isArray(wechat_dm_allowlist) && wechat_dm_allowlist.every((u) => typeof u === 'string'))) {
|
|
1935
|
+
res.status(400).json({ error: 'wechat_dm_allowlist must be an array of strings or null' });
|
|
1936
|
+
return;
|
|
1937
|
+
}
|
|
1938
|
+
if (wechat_pairing !== undefined && wechat_pairing !== null &&
|
|
1939
|
+
typeof wechat_pairing !== 'boolean') {
|
|
1940
|
+
res.status(400).json({ error: 'wechat_pairing must be a boolean or null' });
|
|
1941
|
+
return;
|
|
1942
|
+
}
|
|
1943
|
+
const wechatAccessTouched = wechat_dm_policy !== undefined || wechat_dm_allowlist !== undefined ||
|
|
1944
|
+
wechat_pairing !== undefined;
|
|
1915
1945
|
// connectors: a partial map of { [connectorId]: { enabled: boolean } } to merge.
|
|
1916
1946
|
const connectorPatch = {};
|
|
1917
1947
|
if (connectors !== undefined) {
|
|
@@ -2231,6 +2261,31 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
2231
2261
|
}
|
|
2232
2262
|
}
|
|
2233
2263
|
}
|
|
2264
|
+
// WeChat access fields — get-or-create `agent.wechat` (not gated on it
|
|
2265
|
+
// already existing, unlike LINE/Slack: see the validation block above
|
|
2266
|
+
// for why).
|
|
2267
|
+
if (wechatAccessTouched) {
|
|
2268
|
+
const existing = agent.wechat ?? {};
|
|
2269
|
+
if (wechat_dm_policy !== undefined) {
|
|
2270
|
+
if (wechat_dm_policy === null)
|
|
2271
|
+
delete existing.dmPolicy;
|
|
2272
|
+
else
|
|
2273
|
+
existing.dmPolicy = wechat_dm_policy;
|
|
2274
|
+
}
|
|
2275
|
+
if (wechat_dm_allowlist !== undefined) {
|
|
2276
|
+
if (wechat_dm_allowlist === null)
|
|
2277
|
+
delete existing.dmAllowlist;
|
|
2278
|
+
else
|
|
2279
|
+
existing.dmAllowlist = wechat_dm_allowlist;
|
|
2280
|
+
}
|
|
2281
|
+
if (wechat_pairing !== undefined) {
|
|
2282
|
+
if (wechat_pairing === null)
|
|
2283
|
+
delete existing.pairing;
|
|
2284
|
+
else
|
|
2285
|
+
existing.pairing = wechat_pairing;
|
|
2286
|
+
}
|
|
2287
|
+
agent.wechat = existing;
|
|
2288
|
+
}
|
|
2234
2289
|
if (connectors !== undefined) {
|
|
2235
2290
|
const existing = agent.connectors ?? {};
|
|
2236
2291
|
agent.connectors = { ...existing, ...connectorPatch };
|
|
@@ -2492,6 +2547,38 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
2492
2547
|
(0, pending_senders_1.clearPendingSender)('slack', agentId, id);
|
|
2493
2548
|
}
|
|
2494
2549
|
}
|
|
2550
|
+
if (wechatAccessTouched) {
|
|
2551
|
+
const existing = cfg.wechat ?? {};
|
|
2552
|
+
if (wechat_dm_policy !== undefined) {
|
|
2553
|
+
if (wechat_dm_policy === null)
|
|
2554
|
+
delete existing.dmPolicy;
|
|
2555
|
+
else
|
|
2556
|
+
existing.dmPolicy = wechat_dm_policy;
|
|
2557
|
+
}
|
|
2558
|
+
if (wechat_dm_allowlist !== undefined) {
|
|
2559
|
+
if (wechat_dm_allowlist === null)
|
|
2560
|
+
delete existing.dmAllowlist;
|
|
2561
|
+
else
|
|
2562
|
+
existing.dmAllowlist = wechat_dm_allowlist;
|
|
2563
|
+
}
|
|
2564
|
+
if (wechat_pairing !== undefined) {
|
|
2565
|
+
if (wechat_pairing === null)
|
|
2566
|
+
delete existing.pairing;
|
|
2567
|
+
else
|
|
2568
|
+
existing.pairing = wechat_pairing;
|
|
2569
|
+
}
|
|
2570
|
+
cfg.wechat = existing;
|
|
2571
|
+
// WeChat has no receiver/webhook to start/stop — WeChatManager reads
|
|
2572
|
+
// access control live off the agent config on every inbound message
|
|
2573
|
+
// (see AgentRunner.handleWeChatInboundMessage); just keep it in sync.
|
|
2574
|
+
agentRunners.get(agentId)?.updateAgentConfig(cfg);
|
|
2575
|
+
// Anyone just added to an allowlist is now allowed — drop them from the
|
|
2576
|
+
// in-memory knock list so the discovery UI stops surfacing them.
|
|
2577
|
+
if (Array.isArray(wechat_dm_allowlist)) {
|
|
2578
|
+
for (const userId of wechat_dm_allowlist)
|
|
2579
|
+
(0, pending_senders_1.clearPendingSender)('wechat', agentId, userId);
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2495
2582
|
if (connectors !== undefined) {
|
|
2496
2583
|
const before = cfg.connectors ?? {};
|
|
2497
2584
|
const merged = { ...before, ...connectorPatch };
|
|
@@ -2664,6 +2751,10 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
2664
2751
|
whatsapp_cloud_dm_allowlist: cfg.whatsapp_cloud?.appSecret ? (cfg.whatsapp_cloud?.dmAllowlist ?? []) : null,
|
|
2665
2752
|
whatsapp_cloud_pairing: cfg.whatsapp_cloud?.appSecret ? (cfg.whatsapp_cloud?.pairing ?? true) : null,
|
|
2666
2753
|
whatsapp_cloud_templates_enabled: cfg.whatsapp_cloud?.appSecret ? (cfg.whatsapp_cloud?.templatesEnabled ?? false) : null,
|
|
2754
|
+
wechat_connected: agentRunners.get(agentId)?.getWeChatStatus?.()?.status === 'linked',
|
|
2755
|
+
wechat_dm_policy: cfg.wechat?.dmPolicy ?? null,
|
|
2756
|
+
wechat_dm_allowlist: cfg.wechat?.dmAllowlist ?? [],
|
|
2757
|
+
wechat_pairing: cfg.wechat?.pairing ?? true,
|
|
2667
2758
|
},
|
|
2668
2759
|
});
|
|
2669
2760
|
});
|
|
@@ -2940,6 +3031,151 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
2940
3031
|
(0, pending_senders_1.clearPendingSender)('slack', agentId, senderId);
|
|
2941
3032
|
res.json({ ok: true });
|
|
2942
3033
|
});
|
|
3034
|
+
/**
|
|
3035
|
+
* GET /api/v1/agents/:agentId/wechat/status
|
|
3036
|
+
* Live link status — status/qr straight from the in-process WeChatManager,
|
|
3037
|
+
* never config-derived (there is no credential field to derive it from —
|
|
3038
|
+
* see AgentConfig.wechat's doc comment). Polled by the web UI during
|
|
3039
|
+
* linking and while showing the connected card. Requires write access
|
|
3040
|
+
* (same as every other channel's connect surface), not just read. Mirrors
|
|
3041
|
+
* WhatsApp's `/whatsapp/status` route shape, once that channel lands.
|
|
3042
|
+
*/
|
|
3043
|
+
router.get('/v1/agents/:agentId/wechat/status', auth, (req, res) => {
|
|
3044
|
+
const { agentId } = req.params;
|
|
3045
|
+
const apiKey = req.apiKey;
|
|
3046
|
+
if (!(0, auth_1.canWriteAgent)(apiKey, agentId)) {
|
|
3047
|
+
res.status(403).json({ error: 'Write permission required' });
|
|
3048
|
+
return;
|
|
3049
|
+
}
|
|
3050
|
+
const runner = agentRunners.get(agentId);
|
|
3051
|
+
if (!runner) {
|
|
3052
|
+
res.status(404).json({ error: `Agent '${agentId}' not found` });
|
|
3053
|
+
return;
|
|
3054
|
+
}
|
|
3055
|
+
res.json(runner.getWeChatStatus());
|
|
3056
|
+
});
|
|
3057
|
+
/**
|
|
3058
|
+
* POST /api/v1/agents/:agentId/wechat/link
|
|
3059
|
+
* Start (or restart) a QR-code linking flow. Returns once linked or once
|
|
3060
|
+
* the attempt window elapses — unlike WhatsApp's fire-and-forget
|
|
3061
|
+
* `/whatsapp/link`, there is no separate pairing-code path to race against,
|
|
3062
|
+
* so the client can simply await this and then re-check `/status` once.
|
|
3063
|
+
*/
|
|
3064
|
+
router.post('/v1/agents/:agentId/wechat/link', auth, async (req, res) => {
|
|
3065
|
+
const { agentId } = req.params;
|
|
3066
|
+
const apiKey = req.apiKey;
|
|
3067
|
+
if (!(0, auth_1.canWriteAgent)(apiKey, agentId)) {
|
|
3068
|
+
res.status(403).json({ error: 'Write permission required' });
|
|
3069
|
+
return;
|
|
3070
|
+
}
|
|
3071
|
+
const runner = agentRunners.get(agentId);
|
|
3072
|
+
if (!runner) {
|
|
3073
|
+
res.status(404).json({ error: `Agent '${agentId}' not found` });
|
|
3074
|
+
return;
|
|
3075
|
+
}
|
|
3076
|
+
try {
|
|
3077
|
+
await runner.startWeChatLinking();
|
|
3078
|
+
res.json({ ok: true, status: runner.getWeChatStatus() });
|
|
3079
|
+
}
|
|
3080
|
+
catch (err) {
|
|
3081
|
+
res.status(500).json({ error: err.message });
|
|
3082
|
+
}
|
|
3083
|
+
});
|
|
3084
|
+
/**
|
|
3085
|
+
* POST /api/v1/agents/:agentId/wechat/unlink
|
|
3086
|
+
* Logout and wipe the linked session. The user must scan fresh afterward.
|
|
3087
|
+
*/
|
|
3088
|
+
router.post('/v1/agents/:agentId/wechat/unlink', auth, async (req, res) => {
|
|
3089
|
+
const { agentId } = req.params;
|
|
3090
|
+
const apiKey = req.apiKey;
|
|
3091
|
+
if (!(0, auth_1.canWriteAgent)(apiKey, agentId)) {
|
|
3092
|
+
res.status(403).json({ error: 'Write permission required' });
|
|
3093
|
+
return;
|
|
3094
|
+
}
|
|
3095
|
+
const runner = agentRunners.get(agentId);
|
|
3096
|
+
if (!runner) {
|
|
3097
|
+
res.status(404).json({ error: `Agent '${agentId}' not found` });
|
|
3098
|
+
return;
|
|
3099
|
+
}
|
|
3100
|
+
await runner.unlinkWeChat();
|
|
3101
|
+
res.json({ ok: true });
|
|
3102
|
+
});
|
|
3103
|
+
/**
|
|
3104
|
+
* POST /api/v1/agents/:agentId/wechat/send
|
|
3105
|
+
* INTERNAL — called by the `wechat_reply` MCP tool (via GATEWAY_API_URL/
|
|
3106
|
+
* GATEWAY_API_KEY, same as every other MCP subprocess reaches the
|
|
3107
|
+
* gateway), never by the web UI. Exists because the manager's live iLink
|
|
3108
|
+
* session/credentials only exist inside this process — same reasoning
|
|
3109
|
+
* WhatsApp's `/whatsapp/send` route documents for its Baileys socket.
|
|
3110
|
+
*/
|
|
3111
|
+
router.post('/v1/agents/:agentId/wechat/send', auth, async (req, res) => {
|
|
3112
|
+
const { agentId } = req.params;
|
|
3113
|
+
const apiKey = req.apiKey;
|
|
3114
|
+
if (!(0, auth_1.canWriteAgent)(apiKey, agentId)) {
|
|
3115
|
+
res.status(403).json({ error: 'Write permission required' });
|
|
3116
|
+
return;
|
|
3117
|
+
}
|
|
3118
|
+
const runner = agentRunners.get(agentId);
|
|
3119
|
+
if (!runner) {
|
|
3120
|
+
res.status(404).json({ error: `Agent '${agentId}' not found` });
|
|
3121
|
+
return;
|
|
3122
|
+
}
|
|
3123
|
+
const { to_id, text } = req.body;
|
|
3124
|
+
if (typeof to_id !== 'string' || !to_id) {
|
|
3125
|
+
res.status(400).json({ error: 'to_id is required' });
|
|
3126
|
+
return;
|
|
3127
|
+
}
|
|
3128
|
+
if (typeof text !== 'string' || !text) {
|
|
3129
|
+
res.status(400).json({ error: 'text is required' });
|
|
3130
|
+
return;
|
|
3131
|
+
}
|
|
3132
|
+
try {
|
|
3133
|
+
await runner.sendWeChatMessage(to_id, text);
|
|
3134
|
+
res.json({ ok: true });
|
|
3135
|
+
}
|
|
3136
|
+
catch (err) {
|
|
3137
|
+
res.status(500).json({ error: err.message });
|
|
3138
|
+
}
|
|
3139
|
+
});
|
|
3140
|
+
/**
|
|
3141
|
+
* GET /api/v1/agents/:agentId/wechat/pending
|
|
3142
|
+
* Recently denied WeChat senders (Tier 1 allowlist discovery aid). Admin
|
|
3143
|
+
* only. Mirrors GET .../line/pending exactly, keyed under the 'wechat'
|
|
3144
|
+
* channel namespace in the shared pending-senders store.
|
|
3145
|
+
*/
|
|
3146
|
+
router.get('/v1/agents/:agentId/wechat/pending', auth, (req, res) => {
|
|
3147
|
+
const { agentId } = req.params;
|
|
3148
|
+
const apiKey = req.apiKey;
|
|
3149
|
+
if (!(0, auth_1.isAdmin)(apiKey)) {
|
|
3150
|
+
res.status(403).json({ error: 'Admin key required' });
|
|
3151
|
+
return;
|
|
3152
|
+
}
|
|
3153
|
+
if (!agentConfigs.has(agentId)) {
|
|
3154
|
+
res.status(404).json({ error: `Agent '${agentId}' not found` });
|
|
3155
|
+
return;
|
|
3156
|
+
}
|
|
3157
|
+
res.json({ senders: (0, pending_senders_1.getPendingSenders)('wechat', agentId) });
|
|
3158
|
+
});
|
|
3159
|
+
/**
|
|
3160
|
+
* DELETE /api/v1/agents/:agentId/wechat/pending/:senderId
|
|
3161
|
+
* Dismiss one knock from the in-memory pending list (admin only). Mirrors
|
|
3162
|
+
* DELETE .../line/pending/:senderId exactly. The id is an iLink sender id,
|
|
3163
|
+
* so no format validation.
|
|
3164
|
+
*/
|
|
3165
|
+
router.delete('/v1/agents/:agentId/wechat/pending/:senderId', auth, (req, res) => {
|
|
3166
|
+
const apiKey = req.apiKey;
|
|
3167
|
+
if (!(0, auth_1.isAdmin)(apiKey)) {
|
|
3168
|
+
res.status(403).json({ error: 'Admin key required' });
|
|
3169
|
+
return;
|
|
3170
|
+
}
|
|
3171
|
+
const { agentId, senderId } = req.params;
|
|
3172
|
+
if (!agentConfigs.has(agentId)) {
|
|
3173
|
+
res.status(404).json({ error: `Agent '${agentId}' not found` });
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
(0, pending_senders_1.clearPendingSender)('wechat', agentId, senderId);
|
|
3177
|
+
res.json({ ok: true });
|
|
3178
|
+
});
|
|
2943
3179
|
/**
|
|
2944
3180
|
* GET /api/v1/agents/:agentId/whatsapp/pending?account_id=...
|
|
2945
3181
|
* Recently denied WhatsApp senders/groups (Tier 1/3 discovery aid) for ONE
|