@0xmaxma/claude-gateway 1.7.6 → 1.7.7
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 +1 -1
- package/dist/agent/builtin-commands.d.ts +2 -1
- package/dist/agent/builtin-commands.d.ts.map +1 -1
- package/dist/agent/builtin-commands.js.map +1 -1
- package/dist/agent/incident.d.ts +1 -1
- package/dist/agent/incident.d.ts.map +1 -1
- package/dist/agent/runner.d.ts +7 -2
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +91 -7
- package/dist/agent/runner.js.map +1 -1
- package/dist/api/line-webhook-router.js +8 -8
- package/dist/api/line-webhook-router.js.map +1 -1
- package/dist/api/{line-pending-senders.d.ts → pending-senders.d.ts} +13 -13
- package/dist/api/pending-senders.d.ts.map +1 -0
- package/dist/api/pending-senders.js +128 -0
- package/dist/api/pending-senders.js.map +1 -0
- package/dist/api/router.d.ts.map +1 -1
- package/dist/api/router.js +296 -10
- package/dist/api/router.js.map +1 -1
- package/dist/api/slack-access.d.ts +74 -0
- package/dist/api/slack-access.d.ts.map +1 -0
- package/dist/api/slack-access.js +78 -0
- package/dist/api/slack-access.js.map +1 -0
- package/dist/api/slack-client.d.ts +68 -0
- package/dist/api/slack-client.d.ts.map +1 -0
- package/dist/api/slack-client.js +121 -0
- package/dist/api/slack-client.js.map +1 -0
- package/dist/api/slack-webhook-router.d.ts +34 -0
- package/dist/api/slack-webhook-router.d.ts.map +1 -0
- package/dist/api/slack-webhook-router.js +280 -0
- package/dist/api/slack-webhook-router.js.map +1 -0
- package/dist/api/webhooks-router.d.ts +18 -9
- package/dist/api/webhooks-router.d.ts.map +1 -1
- package/dist/api/webhooks-router.js +12 -7
- package/dist/api/webhooks-router.js.map +1 -1
- package/dist/cli-viewer/pairing-store.d.ts +3 -2
- package/dist/cli-viewer/pairing-store.d.ts.map +1 -1
- package/dist/cli-viewer/pairing-store.js +3 -5
- package/dist/cli-viewer/pairing-store.js.map +1 -1
- package/dist/history/types.d.ts +29 -1
- package/dist/history/types.d.ts.map +1 -1
- package/dist/history/types.js +32 -0
- package/dist/history/types.js.map +1 -1
- package/dist/session/compactor.d.ts +2 -1
- package/dist/session/compactor.d.ts.map +1 -1
- package/dist/session/compactor.js.map +1 -1
- package/dist/session/process.d.ts +3 -2
- package/dist/session/process.d.ts.map +1 -1
- package/dist/session/process.js +17 -6
- package/dist/session/process.js.map +1 -1
- package/dist/session/store.d.ts +14 -13
- package/dist/session/store.d.ts.map +1 -1
- package/dist/session/store.js +7 -2
- package/dist/session/store.js.map +1 -1
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/cli-viewer-ui.d.ts +2 -1
- package/dist/ui/cli-viewer-ui.d.ts.map +1 -1
- package/dist/ui/cli-viewer-ui.js.map +1 -1
- package/mcp/server.ts +2 -0
- package/mcp/tools/slack/module.ts +113 -0
- package/package.json +1 -1
- package/dist/api/line-pending-senders.d.ts.map +0 -1
- package/dist/api/line-pending-senders.js +0 -112
- package/dist/api/line-pending-senders.js.map +0 -1
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeSlackEvent = normalizeSlackEvent;
|
|
4
|
+
exports.verifySlackSignature = verifySlackSignature;
|
|
5
|
+
exports.createSlackWebhookHandler = createSlackWebhookHandler;
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
const logger_1 = require("../logger");
|
|
8
|
+
const slack_access_1 = require("./slack-access");
|
|
9
|
+
const pending_senders_1 = require("./pending-senders");
|
|
10
|
+
const slack_client_1 = require("./slack-client");
|
|
11
|
+
// Requests older than this are rejected outright (Slack's own replay-protection
|
|
12
|
+
// guidance: reject if the timestamp is more than 5 minutes from "now").
|
|
13
|
+
const MAX_REQUEST_AGE_SECONDS = 60 * 5;
|
|
14
|
+
/**
|
|
15
|
+
* One-time pairing-code message — same visual-match-code contract as LINE's
|
|
16
|
+
* `pairingMessage` (line-webhook-router.ts), reused verbatim ("ใช้ระบบ pair
|
|
17
|
+
* เดิม"): the sender reports the code to the admin, who matches it in the UI
|
|
18
|
+
* before adding them to the allowlist. The sender does NOT reply with it.
|
|
19
|
+
*/
|
|
20
|
+
function pairingMessage(code, kind) {
|
|
21
|
+
const inChannel = kind === 'group';
|
|
22
|
+
const thWhere = inChannel ? 'ในช่องนี้' : '';
|
|
23
|
+
const enWhere = inChannel ? ' in this channel' : '';
|
|
24
|
+
return (`รหัสจับคู่ (pairing code) ของคุณคือ: ${code}\n` +
|
|
25
|
+
`กรุณาแจ้งรหัสนี้ให้แอดมินเพื่อขอเปิดใช้งานบอท${thWhere} (ไม่ต้องพิมพ์รหัสตอบกลับ)\n\n` +
|
|
26
|
+
`Your pairing code: ${code}\n` +
|
|
27
|
+
`Share this code with the admin to get access${enWhere}. (No need to reply with it.)`);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Strip a leading/embedded bot self-mention (`<@U…>`) from `app_mention` text.
|
|
31
|
+
* Slack delivers the raw text with the mention markup inline (e.g.
|
|
32
|
+
* `<@U0BOT> hello`), which is noise to the agent. Only the bot's OWN id is
|
|
33
|
+
* removed — mentions of other users are left intact so the agent can still see
|
|
34
|
+
* who else was referenced. No-op when the bot id is unknown.
|
|
35
|
+
*/
|
|
36
|
+
function stripBotMention(text, botUserId) {
|
|
37
|
+
if (!text || !botUserId)
|
|
38
|
+
return text;
|
|
39
|
+
// Match `<@U123>` or `<@U123|label>` for exactly this bot id.
|
|
40
|
+
const re = new RegExp(`<@${botUserId}(?:\\|[^>]*)?>`, 'g');
|
|
41
|
+
return text.replace(re, '').replace(/\s{2,}/g, ' ').trim();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Normalize a Slack Events API `event` into the gateway's {content, meta}
|
|
45
|
+
* intake shape. Returns null for anything not handled in v1 (bot-authored
|
|
46
|
+
* events, missing channel/user, non message/app_mention types — see 2c for
|
|
47
|
+
* what's deliberately deferred: files, edits, reactions, etc.).
|
|
48
|
+
*/
|
|
49
|
+
function normalizeSlackEvent(event, resolved, botUserId) {
|
|
50
|
+
if (event.type !== 'message' && event.type !== 'app_mention')
|
|
51
|
+
return null;
|
|
52
|
+
// Bot-loop protection (2c #18) — never respond to our own or another bot's
|
|
53
|
+
// messages. Hard default, not a config toggle.
|
|
54
|
+
if (event.bot_id)
|
|
55
|
+
return null;
|
|
56
|
+
const r = resolved ?? (0, slack_access_1.resolveSlackSource)(event);
|
|
57
|
+
if (r.kind === 'other' || !r.conversationId)
|
|
58
|
+
return null;
|
|
59
|
+
const meta = {
|
|
60
|
+
source: 'slack',
|
|
61
|
+
chat_id: r.conversationId,
|
|
62
|
+
user_id: r.senderId || r.conversationId,
|
|
63
|
+
user: r.senderId || r.conversationId,
|
|
64
|
+
message_id: event.ts ?? '',
|
|
65
|
+
ts: event.event_ts ?? event.ts ?? '',
|
|
66
|
+
slack_chat_type: r.kind, // 'user' | 'group'
|
|
67
|
+
};
|
|
68
|
+
if (event.thread_ts)
|
|
69
|
+
meta.thread_ts = event.thread_ts;
|
|
70
|
+
return { content: stripBotMention(event.text ?? '', botUserId), meta };
|
|
71
|
+
}
|
|
72
|
+
/** Verify `X-Slack-Signature` (HMAC-SHA256 of "v0:{timestamp}:{rawBody}") and reject stale requests. */
|
|
73
|
+
function verifySlackSignature(rawBody, signingSecret, timestampHeader, signatureHeader) {
|
|
74
|
+
if (!signingSecret || !timestampHeader || !signatureHeader)
|
|
75
|
+
return false;
|
|
76
|
+
const timestamp = Number(timestampHeader);
|
|
77
|
+
if (!Number.isFinite(timestamp))
|
|
78
|
+
return false;
|
|
79
|
+
if (Math.abs(Date.now() / 1000 - timestamp) > MAX_REQUEST_AGE_SECONDS)
|
|
80
|
+
return false;
|
|
81
|
+
const base = `v0:${timestampHeader}:${rawBody.toString('utf8')}`;
|
|
82
|
+
const expected = `v0=${(0, crypto_1.createHmac)('sha256', signingSecret).update(base).digest('hex')}`;
|
|
83
|
+
const expectedBuf = Buffer.from(expected, 'utf8');
|
|
84
|
+
const actualBuf = Buffer.from(signatureHeader, 'utf8');
|
|
85
|
+
if (expectedBuf.length !== actualBuf.length)
|
|
86
|
+
return false;
|
|
87
|
+
return (0, crypto_1.timingSafeEqual)(expectedBuf, actualBuf);
|
|
88
|
+
}
|
|
89
|
+
/** Find the agent that has Slack configured (mirrors resolveLineAgent — single-agent-per-secret POC, or by id). */
|
|
90
|
+
function resolveSlackAgent(agents, agentId) {
|
|
91
|
+
if (agentId) {
|
|
92
|
+
const r = agents.get(agentId);
|
|
93
|
+
return r && r.getAgentConfig().slack?.signingSecret ? r : null;
|
|
94
|
+
}
|
|
95
|
+
for (const runner of agents.values()) {
|
|
96
|
+
if (runner.getAgentConfig().slack?.signingSecret)
|
|
97
|
+
return runner;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
// Slack retries an event (at-least-once delivery) if our 200 ack is slow or
|
|
102
|
+
// dropped — event_id is Slack's own dedup key for exactly this case. A bounded
|
|
103
|
+
// map is enough here, not a full LRU: entries are pruned by age on each
|
|
104
|
+
// insert, and Slack's retry window is short (seconds to a few minutes), so
|
|
105
|
+
// this only needs to outlive that window, not forever.
|
|
106
|
+
const SLACK_EVENT_ID_TTL_MS = 10 * 60000;
|
|
107
|
+
function createSlackWebhookHandler(agents, logDir, opts = {}) {
|
|
108
|
+
const logger = (0, logger_1.createLogger)('slack-webhook', logDir);
|
|
109
|
+
const seenEventIds = new Map();
|
|
110
|
+
const isDuplicateSlackEvent = (eventId) => {
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
for (const [id, ts] of seenEventIds) {
|
|
113
|
+
if (now - ts > SLACK_EVENT_ID_TTL_MS)
|
|
114
|
+
seenEventIds.delete(id);
|
|
115
|
+
}
|
|
116
|
+
if (seenEventIds.has(eventId))
|
|
117
|
+
return true;
|
|
118
|
+
seenEventIds.set(eventId, now);
|
|
119
|
+
return false;
|
|
120
|
+
};
|
|
121
|
+
// Slack's URL-verification handshake arrives as a signed POST, not a GET —
|
|
122
|
+
// unlike LINE's Console "Verify" (an empty GET/POST) — so this handler is
|
|
123
|
+
// effectively unused; kept only because WebhookAppHandler requires it.
|
|
124
|
+
const verify = (_req, res) => {
|
|
125
|
+
res.status(200).json({ ok: true });
|
|
126
|
+
};
|
|
127
|
+
const handlePost = async (req, res) => {
|
|
128
|
+
const agentId = req.params.agentId;
|
|
129
|
+
const runner = resolveSlackAgent(agents, agentId);
|
|
130
|
+
if (!runner) {
|
|
131
|
+
res.status(404).json({ error: 'no Slack-enabled agent' });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const cfg = runner.getAgentConfig().slack;
|
|
135
|
+
const secret = cfg?.signingSecret ?? '';
|
|
136
|
+
const buf = Buffer.isBuffer(req.body) ? req.body : Buffer.from('');
|
|
137
|
+
if (!verifySlackSignature(buf, secret, req.header('x-slack-request-timestamp'), req.header('x-slack-signature'))) {
|
|
138
|
+
logger.warn('Slack webhook rejected: bad signature', { agentId: runner.getAgentConfig().id });
|
|
139
|
+
res.status(401).json({ error: 'invalid signature' });
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
let payload;
|
|
143
|
+
try {
|
|
144
|
+
payload = JSON.parse(buf.toString('utf8'));
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
logger.warn('Slack webhook: bad JSON', { error: err.message });
|
|
148
|
+
res.status(400).json({ error: 'bad JSON' });
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// URL verification handshake (signature already verified above — Slack
|
|
152
|
+
// signs this request type too). Must respond with the raw challenge, not JSON-wrapped.
|
|
153
|
+
if (payload.type === 'url_verification') {
|
|
154
|
+
res.status(200).json({ challenge: payload.challenge });
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Ack immediately (Slack retries if we don't respond within ~3s) — process after.
|
|
158
|
+
res.status(200).json({ ok: true });
|
|
159
|
+
if (payload.type !== 'event_callback')
|
|
160
|
+
return;
|
|
161
|
+
const eventId = typeof payload.event_id === 'string' ? payload.event_id : '';
|
|
162
|
+
if (eventId && isDuplicateSlackEvent(eventId)) {
|
|
163
|
+
logger.debug('Slack webhook: duplicate event_id (Slack retry), skipping', { eventId });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const event = payload.event;
|
|
167
|
+
if (!event)
|
|
168
|
+
return;
|
|
169
|
+
// The bot's own Slack user id — carried on every event_callback in
|
|
170
|
+
// `authorizations` — used to strip the bot's self-mention from
|
|
171
|
+
// app_mention text (see normalizeSlackEvent below).
|
|
172
|
+
const authorizations = payload.authorizations;
|
|
173
|
+
const botUserId = authorizations?.[0]?.user_id;
|
|
174
|
+
const deniedAgentId = runner.getAgentConfig().id;
|
|
175
|
+
const resolved = (0, slack_access_1.resolveSlackSource)(event);
|
|
176
|
+
// Bot-loop protection before the access gate too — a bot's own message
|
|
177
|
+
// should never mint a pairing knock either.
|
|
178
|
+
if (event.bot_id)
|
|
179
|
+
return;
|
|
180
|
+
if (!(0, slack_access_1.isResolvedSourceAllowed)(cfg, resolved)) {
|
|
181
|
+
logger.debug('Slack webhook: source not allowed', {
|
|
182
|
+
agentId: deniedAgentId,
|
|
183
|
+
kind: resolved.kind,
|
|
184
|
+
policy: (resolved.kind === 'user' ? cfg?.dmPolicy : cfg?.groupPolicy) ?? '(closed)',
|
|
185
|
+
conversationId: resolved.conversationId,
|
|
186
|
+
});
|
|
187
|
+
const knockId = resolved.kind === 'user' ? resolved.senderId : resolved.conversationId;
|
|
188
|
+
if (knockId) {
|
|
189
|
+
const sourcePolicy = resolved.kind === 'user' ? cfg?.dmPolicy : cfg?.groupPolicy;
|
|
190
|
+
const isPairing = cfg?.pairing !== false && sourcePolicy !== 'open' && sourcePolicy !== 'disabled';
|
|
191
|
+
const prev = (0, pending_senders_1.getPendingSender)('slack', deniedAgentId, knockId);
|
|
192
|
+
const code = prev?.code ?? (isPairing ? (0, pending_senders_1.generatePairingCode)() : undefined);
|
|
193
|
+
const client = cfg?.botToken
|
|
194
|
+
? new slack_client_1.SlackClient({ botToken: cfg.botToken, logDir, apiBase: opts.apiBase })
|
|
195
|
+
: null;
|
|
196
|
+
let wasNew = false;
|
|
197
|
+
if (resolved.kind === 'user') {
|
|
198
|
+
wasNew = (0, pending_senders_1.recordDeniedSender)('slack', deniedAgentId, knockId, undefined, Date.now(), code);
|
|
199
|
+
// Best-effort display-name backfill — mirrors LINE's getProfile() call.
|
|
200
|
+
if (client) {
|
|
201
|
+
void client
|
|
202
|
+
.getUserDisplayName(knockId)
|
|
203
|
+
.then((name) => {
|
|
204
|
+
const e = (0, pending_senders_1.getPendingSender)('slack', deniedAgentId, knockId);
|
|
205
|
+
if (e && name && !e.displayName)
|
|
206
|
+
e.displayName = name;
|
|
207
|
+
})
|
|
208
|
+
.catch(() => { });
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else if (resolved.kind === 'group') {
|
|
212
|
+
wasNew = (0, pending_senders_1.recordDeniedConversation)('slack', deniedAgentId, knockId, 'group', undefined, Date.now(), code);
|
|
213
|
+
// Best-effort channel-name backfill — mirrors LINE's getGroupSummary() call.
|
|
214
|
+
if (client) {
|
|
215
|
+
void client
|
|
216
|
+
.getChannelName(knockId)
|
|
217
|
+
.then((name) => {
|
|
218
|
+
const e = (0, pending_senders_1.getPendingSender)('slack', deniedAgentId, knockId);
|
|
219
|
+
if (e && name && !e.displayName)
|
|
220
|
+
e.displayName = name;
|
|
221
|
+
})
|
|
222
|
+
.catch(() => { });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Send the pairing code exactly once — on first contact only.
|
|
226
|
+
if (isPairing && wasNew && code && client) {
|
|
227
|
+
const target = resolved.conversationId;
|
|
228
|
+
void client
|
|
229
|
+
.postMessage(target, pairingMessage(code, resolved.kind === 'group' ? 'group' : 'user'))
|
|
230
|
+
.catch((err) => logger.debug('Slack pairing code reply failed', { error: err.message }));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const norm = normalizeSlackEvent(event, resolved, botUserId);
|
|
236
|
+
if (!norm)
|
|
237
|
+
return;
|
|
238
|
+
// Channel activation gate: unless requireMention is explicitly false,
|
|
239
|
+
// only respond to app_mention events in channels (DMs always pass).
|
|
240
|
+
// event.type === 'app_mention' already IS the "bot was mentioned" signal
|
|
241
|
+
// at the Slack API level — a plain 'message' event in a channel never
|
|
242
|
+
// reaches this handler unless the workspace also subscribes to broader
|
|
243
|
+
// message.* events, so this check is a defensive no-op today but keeps
|
|
244
|
+
// the same explicit posture LINE's requireMention gate has.
|
|
245
|
+
if (resolved.kind === 'group' &&
|
|
246
|
+
cfg?.requireMention !== false &&
|
|
247
|
+
event.type !== 'app_mention') {
|
|
248
|
+
logger.debug('Slack webhook: channel message without bot mention, ignoring', {
|
|
249
|
+
agentId: deniedAgentId,
|
|
250
|
+
conversationId: resolved.conversationId,
|
|
251
|
+
});
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
// Ack-reaction (2c): added here on receipt; removed by the `slack_reply`
|
|
255
|
+
// MCP tool (mcp/tools/slack/module.ts) once the agent's reply actually
|
|
256
|
+
// posts, using the same `chat_id`/`message_id` passed through `norm.meta`
|
|
257
|
+
// below — this file only ever adds it, never removes it.
|
|
258
|
+
const token = cfg?.botToken;
|
|
259
|
+
if (token) {
|
|
260
|
+
const client = new slack_client_1.SlackClient({ botToken: token, logDir, apiBase: opts.apiBase });
|
|
261
|
+
if (event.ts) {
|
|
262
|
+
void client.addReaction(resolved.conversationId, event.ts).catch(() => { });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
await fetch(`http://127.0.0.1:${runner.getCallbackPort()}/channel`, {
|
|
267
|
+
method: 'POST',
|
|
268
|
+
headers: { 'Content-Type': 'application/json' },
|
|
269
|
+
body: JSON.stringify(norm),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
logger.error('Slack webhook: failed to forward to callback', {
|
|
274
|
+
error: err.message,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
return { verify, handlePost };
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=slack-webhook-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-webhook-router.js","sourceRoot":"","sources":["../../src/api/slack-webhook-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unified public webhook ingress.
|
|
3
3
|
*
|
|
4
|
-
* All external, unauthenticated webhooks (LINE
|
|
5
|
-
* single route `/webhooks/:app/:agentId?` and are dispatched to a
|
|
6
|
-
* by the `:app` path segment. Mounted BEFORE express.json()
|
|
7
|
-
* the raw request bytes it needs for signature
|
|
4
|
+
* All external, unauthenticated webhooks (LINE, Slack; more later) enter
|
|
5
|
+
* through a single route `/webhooks/:app/:agentId?` and are dispatched to a
|
|
6
|
+
* per-app handler by the `:app` path segment. Mounted BEFORE express.json()
|
|
7
|
+
* so each handler sees the raw request bytes it needs for signature
|
|
8
|
+
* validation.
|
|
8
9
|
*
|
|
9
10
|
* The whole `/webhooks/*` zone bypasses the gateway's API-key auth (it is mounted
|
|
10
11
|
* outside the /api routers, exactly like the old LINE mount) AND Traefik's
|
|
11
12
|
* ForwardAuth (a single `/gateway/webhooks` bypass router upstream). Therefore
|
|
12
13
|
* EVERY app handler MUST authenticate its own requests (e.g. LINE's HMAC
|
|
13
|
-
* signature) as its first step — there is no ambient
|
|
14
|
+
* signature, Slack's HMAC signature) as its first step — there is no ambient
|
|
15
|
+
* auth on this path.
|
|
14
16
|
*
|
|
15
17
|
* Adding a new webhook app = register one entry in `handlers` below; no Traefik or
|
|
16
|
-
* getpod change is needed once the `/gateway/webhooks` ingress exists.
|
|
18
|
+
* getpod change is needed once the `/gateway/webhooks` ingress exists. Slack is
|
|
19
|
+
* the first proof this generalizes past LINE — see slack-webhook-router.ts.
|
|
17
20
|
*/
|
|
18
21
|
import { Router, type Request, type Response } from 'express';
|
|
19
22
|
import type { AgentRunner } from '../agent/runner';
|
|
20
23
|
import { type LineWebhookOptions } from './line-webhook-router';
|
|
24
|
+
import { type SlackWebhookOptions } from './slack-webhook-router';
|
|
21
25
|
/**
|
|
22
26
|
* A per-app webhook handler. `verify` answers provider URL-verification probes
|
|
23
27
|
* (GET / empty POST); `handlePost` processes a signed inbound POST. Each handler
|
|
@@ -28,9 +32,14 @@ export interface WebhookAppHandler {
|
|
|
28
32
|
handlePost(req: Request, res: Response): Promise<void>;
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
|
-
* Options forwarded to app handlers
|
|
32
|
-
*
|
|
35
|
+
* Options forwarded to app handlers, keyed by app so each handler only sees
|
|
36
|
+
* its own test-only overrides (LINE's apiBase/dataApiBase are meaningless to
|
|
37
|
+
* Slack and vice versa — a flat merged type would let one app's option leak
|
|
38
|
+
* into another's constructor by accident).
|
|
33
39
|
*/
|
|
34
|
-
export
|
|
40
|
+
export interface WebhooksOptions {
|
|
41
|
+
line?: LineWebhookOptions;
|
|
42
|
+
slack?: SlackWebhookOptions;
|
|
43
|
+
}
|
|
35
44
|
export declare function createWebhooksRouter(agents: Map<string, AgentRunner>, logDir: string, opts?: WebhooksOptions): Router;
|
|
36
45
|
//# sourceMappingURL=webhooks-router.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks-router.d.ts","sourceRoot":"","sources":["../../src/api/webhooks-router.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"webhooks-router.d.ts","sourceRoot":"","sources":["../../src/api/webhooks-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAgB,EAAE,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAI7F;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1C,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,KAAK,CAAC,EAAE,mBAAmB,CAAC;CAC7B;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EAChC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,eAAoB,GACzB,MAAM,CAsCR"}
|
|
@@ -37,28 +37,33 @@ exports.createWebhooksRouter = createWebhooksRouter;
|
|
|
37
37
|
/**
|
|
38
38
|
* Unified public webhook ingress.
|
|
39
39
|
*
|
|
40
|
-
* All external, unauthenticated webhooks (LINE
|
|
41
|
-
* single route `/webhooks/:app/:agentId?` and are dispatched to a
|
|
42
|
-
* by the `:app` path segment. Mounted BEFORE express.json()
|
|
43
|
-
* the raw request bytes it needs for signature
|
|
40
|
+
* All external, unauthenticated webhooks (LINE, Slack; more later) enter
|
|
41
|
+
* through a single route `/webhooks/:app/:agentId?` and are dispatched to a
|
|
42
|
+
* per-app handler by the `:app` path segment. Mounted BEFORE express.json()
|
|
43
|
+
* so each handler sees the raw request bytes it needs for signature
|
|
44
|
+
* validation.
|
|
44
45
|
*
|
|
45
46
|
* The whole `/webhooks/*` zone bypasses the gateway's API-key auth (it is mounted
|
|
46
47
|
* outside the /api routers, exactly like the old LINE mount) AND Traefik's
|
|
47
48
|
* ForwardAuth (a single `/gateway/webhooks` bypass router upstream). Therefore
|
|
48
49
|
* EVERY app handler MUST authenticate its own requests (e.g. LINE's HMAC
|
|
49
|
-
* signature) as its first step — there is no ambient
|
|
50
|
+
* signature, Slack's HMAC signature) as its first step — there is no ambient
|
|
51
|
+
* auth on this path.
|
|
50
52
|
*
|
|
51
53
|
* Adding a new webhook app = register one entry in `handlers` below; no Traefik or
|
|
52
|
-
* getpod change is needed once the `/gateway/webhooks` ingress exists.
|
|
54
|
+
* getpod change is needed once the `/gateway/webhooks` ingress exists. Slack is
|
|
55
|
+
* the first proof this generalizes past LINE — see slack-webhook-router.ts.
|
|
53
56
|
*/
|
|
54
57
|
const express_1 = __importStar(require("express"));
|
|
55
58
|
const line_webhook_router_1 = require("./line-webhook-router");
|
|
59
|
+
const slack_webhook_router_1 = require("./slack-webhook-router");
|
|
56
60
|
const MAX_BODY_BYTES = 256 * 1024; // pre-auth body cap
|
|
57
61
|
function createWebhooksRouter(agents, logDir, opts = {}) {
|
|
58
62
|
const router = (0, express_1.Router)();
|
|
59
63
|
const rawBody = express_1.default.raw({ type: '*/*', limit: MAX_BODY_BYTES });
|
|
60
64
|
const handlers = {
|
|
61
|
-
line: (0, line_webhook_router_1.createLineWebhookHandler)(agents, logDir, opts),
|
|
65
|
+
line: (0, line_webhook_router_1.createLineWebhookHandler)(agents, logDir, opts.line ?? {}),
|
|
66
|
+
slack: (0, slack_webhook_router_1.createSlackWebhookHandler)(agents, logDir, opts.slack ?? {}),
|
|
62
67
|
};
|
|
63
68
|
const resolve = (req, res) => {
|
|
64
69
|
const app = req.params.app;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks-router.js","sourceRoot":"","sources":["../../src/api/webhooks-router.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"webhooks-router.js","sourceRoot":"","sources":["../../src/api/webhooks-router.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,oDA0CC;AA1FD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,mDAAuE;AAEvE,+DAA0F;AAC1F,iEAA6F;AAE7F,MAAM,cAAc,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,oBAAoB;AAuBvD,SAAgB,oBAAoB,CAClC,MAAgC,EAChC,MAAc,EACd,OAAwB,EAAE;IAE1B,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;IACxB,MAAM,OAAO,GAAG,iBAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IAEpE,MAAM,QAAQ,GAAsC;QAClD,IAAI,EAAE,IAAA,8CAAwB,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QAC/D,KAAK,EAAE,IAAA,gDAAyB,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;KACnE,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,GAAY,EAAE,GAAa,EAA4B,EAAE;QACxE,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;QAC3B,+EAA+E;QAC/E,oFAAoF;QACpF,kFAAkF;QAClF,yCAAyC;QACzC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChG,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wBAAwB,GAAG,EAAE,EAAE,CAAC,CAAC;YAC/D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,GAAY,EAAE,GAAa,EAAQ,EAAE;QACxD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAClC,IAAI,OAAO;YAAE,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,CAAC,GAAY,EAAE,GAAa,EAAQ,EAAE;QACzD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAClC,IAAI,OAAO;YAAE,KAAK,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;IAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAErD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { type ChatChannel, isChatChannel } from '../history/types';
|
|
1
2
|
/**
|
|
2
3
|
* Chat channel a `/cli` pairing originated from. The channel already
|
|
3
4
|
* authenticated the requesting user (allowlist / pairing gate) before a pairing
|
|
4
5
|
* is ever created, so the channel + user id recorded here is a trusted binding.
|
|
5
6
|
*/
|
|
6
|
-
export type CliChannel =
|
|
7
|
+
export type CliChannel = ChatChannel;
|
|
7
8
|
/** Runtime guard for the trusted channel set (payloads cross a process boundary). */
|
|
8
|
-
export declare
|
|
9
|
+
export declare const isCliChannel: typeof isChatChannel;
|
|
9
10
|
/**
|
|
10
11
|
* Pairing lifecycle:
|
|
11
12
|
* pending — created by `/cli`, waiting for proof (chat-approve or initData).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairing-store.d.ts","sourceRoot":"","sources":["../../src/cli-viewer/pairing-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pairing-store.d.ts","sourceRoot":"","sources":["../../src/cli-viewer/pairing-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC;AAErC,qFAAqF;AACrF,eAAO,MAAM,YAAY,sBAAgB,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE9E,MAAM,WAAW,UAAU;IACzB;4EACwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB;sEACkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf;kFAC8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,CAAC;IACzB;;iFAE6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;gFAC4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAOD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAE1D,+DAA+D;IAC/D,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc;IAmB5E,4EAA4E;IAC5E,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAI9C,2EAA2E;IAC3E,OAAO,CAAC,MAAM;IAId;;;;;OAKG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM;IAclF;;;OAGG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM;IAQ3F,2DAA2D;IAC3D,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM;IAQxF;;;;;;OAMG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAoBhF;;;;;;;OAOG;IACH,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAkBnG;;;OAGG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAcrD,+EAA+E;IAC/E,KAAK,IAAI,IAAI;IASb,iCAAiC;IACjC,IAAI,IAAI,MAAM;CAGf;AAED,mFAAmF;AACnF,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
|
@@ -3,13 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.cliPairingStore = exports.CliPairingStore = void 0;
|
|
7
|
-
exports.isCliChannel = isCliChannel;
|
|
6
|
+
exports.cliPairingStore = exports.CliPairingStore = exports.isCliChannel = void 0;
|
|
8
7
|
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
const types_1 = require("../history/types");
|
|
9
9
|
/** Runtime guard for the trusted channel set (payloads cross a process boundary). */
|
|
10
|
-
|
|
11
|
-
return value === 'telegram' || value === 'discord' || value === 'line';
|
|
12
|
-
}
|
|
10
|
+
exports.isCliChannel = types_1.isChatChannel;
|
|
13
11
|
/** Approval window: how long the operator has to approve after `/cli`. */
|
|
14
12
|
const PAIRING_TTL_MS = 3 * 60 * 1000;
|
|
15
13
|
/** Viewer session lifetime once unlocked. Short — re-run `/cli` to renew. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairing-store.js","sourceRoot":"","sources":["../../src/cli-viewer/pairing-store.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"pairing-store.js","sourceRoot":"","sources":["../../src/cli-viewer/pairing-store.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAC5B,4CAAmE;AASnE,qFAAqF;AACxE,QAAA,YAAY,GAAG,qBAAa,CAAC;AAsC1C,0EAA0E;AAC1E,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACrC,6EAA6E;AAC7E,MAAM,aAAa,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAOrC;;;;;;;;;;;;;;GAcG;AACH,MAAa,eAAe;IAA5B;QACmB,aAAQ,GAAG,IAAI,GAAG,EAAsB,CAAC;IA8J5D,CAAC;IA5JC,+DAA+D;IAC/D,MAAM,CAAC,OAAe,EAAE,OAAmB,EAAE,MAAc;QACzD,MAAM,SAAS,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACzD,4EAA4E;QAC5E,4EAA4E;QAC5E,MAAM,IAAI,GAAG,MAAM,CAAC,gBAAM,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE;YAC3B,SAAS;YACT,OAAO;YACP,OAAO;YACP,MAAM;YACN,IAAI;YACJ,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG,GAAG,cAAc;SAChC,CAAC,CAAC;QACH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC7B,CAAC;IAED,4EAA4E;IAC5E,GAAG,CAAC,SAAiB;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAED,2EAA2E;IACnE,MAAM,CAAC,CAAyB;QACtC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7F,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,SAAiB,EAAE,YAAoB;QACjD,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvC,6EAA6E;QAC7E,yEAAyE;QACzE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YAC1F,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;YACpB,CAAC,CAAC,YAAY,GAAG,YAAY,CAAC;YAC9B,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,CAAC,CAAC,YAAY,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/D,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,SAAiB,EAAE,OAAmB,EAAE,MAAc;QAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC;QACnC,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,UAAU,CAAC;QACpE,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;YAAE,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC,SAAiB,EAAE,OAAmB,EAAE,MAAc;QACzD,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC;QACnC,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,UAAU,CAAC;QACpE,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,SAAiB,EAAE,YAAoB;QAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,6EAA6E;QAC7E,sCAAsC;QACtC,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,YAAY,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC9F,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YACxC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QACtE,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,YAAY,KAAK,YAAY;YAAE,OAAO,IAAI,CAAC;QACpE,MAAM,WAAW,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC3D,CAAC,CAAC,WAAW,GAAG,WAAW,CAAC;QAC5B,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC;QACtB,CAAC,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC;QAC/C,OAAO,EAAE,WAAW,EAAE,CAAC;IACzB,CAAC;IAED;;;;;;;OAOG;IACH,0BAA0B,CAAC,SAAiB,EAAE,YAAoB;QAChE,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC7C,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,YAAY,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC9F,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YACxC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QAC3C,CAAC,CAAC,YAAY,GAAG,YAAY,CAAC;QAC9B,MAAM,WAAW,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC3D,CAAC,CAAC,WAAW,GAAG,WAAW,CAAC;QAC5B,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC;QACtB,CAAC,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC;QAC/C,OAAO,EAAE,WAAW,EAAE,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,WAAmB;QAC/B,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,IACE,CAAC,CAAC,MAAM,KAAK,UAAU;gBACvB,CAAC,CAAC,WAAW,KAAK,WAAW;gBAC7B,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,EACrC,CAAC;gBACD,OAAO,CAAC,CAAC;YACX,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+EAA+E;IAC/E,KAAK;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC;YAClE,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC;YAC9E,IAAI,WAAW,IAAI,UAAU;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,iCAAiC;IACjC,IAAI;QACF,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;CACF;AA/JD,0CA+JC;AAED,mFAAmF;AACtE,QAAA,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC"}
|
package/dist/history/types.d.ts
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Canonical channel list — the SINGLE source of truth for the
|
|
3
|
+
* 'telegram' | 'discord' | 'line' | 'slack' union that used to be
|
|
4
|
+
* hand-copied into ~10 files (session/process.ts, agent/runner.ts,
|
|
5
|
+
* api/router.ts, session/compactor.ts, agent/builtin-commands.ts,
|
|
6
|
+
* cli-viewer/pairing-store.ts, ui/cli-viewer-ui.ts, ...).
|
|
7
|
+
*
|
|
8
|
+
* That duplication is exactly what caused three real bugs when Slack was
|
|
9
|
+
* added: a channelSource ternary with no 'slack' branch (every Slack
|
|
10
|
+
* session silently became 'telegram'), a replyToolName ternary with the
|
|
11
|
+
* same gap, and an isCliChannel() runtime guard whose type was widened to
|
|
12
|
+
* include 'slack' but whose implementation wasn't. Deriving both the type
|
|
13
|
+
* AND a runtime guard from one array makes that specific failure mode
|
|
14
|
+
* (type says X is valid, some hand-copied runtime check disagrees)
|
|
15
|
+
* impossible to reintroduce for this union — adding a channel here updates
|
|
16
|
+
* every consumer's type AND its guard in one place.
|
|
17
|
+
*/
|
|
18
|
+
export declare const CHAT_CHANNELS: readonly ["telegram", "discord", "line", "slack"];
|
|
19
|
+
export type ChatChannel = (typeof CHAT_CHANNELS)[number];
|
|
20
|
+
export declare function isChatChannel(value: unknown): value is ChatChannel;
|
|
21
|
+
/** ChatChannel plus 'api' — a session spawned via direct API access, not a channel. */
|
|
22
|
+
export type ChatChannelOrApi = ChatChannel | 'api';
|
|
23
|
+
export type HistorySource = ChatChannelOrApi | 'ui';
|
|
24
|
+
/**
|
|
25
|
+
* Normalize a ChatChannelOrApi down to a live ChatChannel — 'api' (not a real
|
|
26
|
+
* channel) falls back to 'telegram', matching this codebase's long-standing
|
|
27
|
+
* default for channel-scoped state paths (session/process.ts's stateSubDir).
|
|
28
|
+
*/
|
|
29
|
+
export declare function toChatChannel(source: ChatChannelOrApi): ChatChannel;
|
|
2
30
|
export type MessageRole = 'user' | 'assistant' | 'system';
|
|
3
31
|
export interface HistoryMessage {
|
|
4
32
|
id?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/history/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/history/types.ts"],"names":[],"mappings":"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"}
|
package/dist/history/types.js
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CHAT_CHANNELS = void 0;
|
|
4
|
+
exports.isChatChannel = isChatChannel;
|
|
5
|
+
exports.toChatChannel = toChatChannel;
|
|
6
|
+
/**
|
|
7
|
+
* Canonical channel list — the SINGLE source of truth for the
|
|
8
|
+
* 'telegram' | 'discord' | 'line' | 'slack' union that used to be
|
|
9
|
+
* hand-copied into ~10 files (session/process.ts, agent/runner.ts,
|
|
10
|
+
* api/router.ts, session/compactor.ts, agent/builtin-commands.ts,
|
|
11
|
+
* cli-viewer/pairing-store.ts, ui/cli-viewer-ui.ts, ...).
|
|
12
|
+
*
|
|
13
|
+
* That duplication is exactly what caused three real bugs when Slack was
|
|
14
|
+
* added: a channelSource ternary with no 'slack' branch (every Slack
|
|
15
|
+
* session silently became 'telegram'), a replyToolName ternary with the
|
|
16
|
+
* same gap, and an isCliChannel() runtime guard whose type was widened to
|
|
17
|
+
* include 'slack' but whose implementation wasn't. Deriving both the type
|
|
18
|
+
* AND a runtime guard from one array makes that specific failure mode
|
|
19
|
+
* (type says X is valid, some hand-copied runtime check disagrees)
|
|
20
|
+
* impossible to reintroduce for this union — adding a channel here updates
|
|
21
|
+
* every consumer's type AND its guard in one place.
|
|
22
|
+
*/
|
|
23
|
+
exports.CHAT_CHANNELS = ['telegram', 'discord', 'line', 'slack'];
|
|
24
|
+
function isChatChannel(value) {
|
|
25
|
+
return typeof value === 'string' && exports.CHAT_CHANNELS.includes(value);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Normalize a ChatChannelOrApi down to a live ChatChannel — 'api' (not a real
|
|
29
|
+
* channel) falls back to 'telegram', matching this codebase's long-standing
|
|
30
|
+
* default for channel-scoped state paths (session/process.ts's stateSubDir).
|
|
31
|
+
*/
|
|
32
|
+
function toChatChannel(source) {
|
|
33
|
+
return isChatChannel(source) ? source : 'telegram';
|
|
34
|
+
}
|
|
3
35
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/history/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/history/types.ts"],"names":[],"mappings":";;;AAmBA,sCAEC;AAWD,sCAEC;AAlCD;;;;;;;;;;;;;;;;GAgBG;AACU,QAAA,aAAa,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAE/E,SAAgB,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,qBAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC3F,CAAC;AAMD;;;;GAIG;AACH,SAAgB,aAAa,CAAC,MAAwB;IACpD,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;AACrD,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ChatChannelOrApi } from '../history/types';
|
|
1
2
|
import { SessionStore } from './store';
|
|
2
3
|
export interface CompactionResult {
|
|
3
4
|
beforeMessages: number;
|
|
@@ -14,7 +15,7 @@ export declare class NotEnoughMessagesError extends Error {
|
|
|
14
15
|
export declare class SessionCompactor {
|
|
15
16
|
private readonly sessionStore;
|
|
16
17
|
constructor(sessionStore: SessionStore);
|
|
17
|
-
compact(agentId: string, chatId: string, sessionId: string, model: string, contextWindow: number, channel?:
|
|
18
|
+
compact(agentId: string, chatId: string, sessionId: string, model: string, contextWindow: number, channel?: ChatChannelOrApi): Promise<CompactionResult>;
|
|
18
19
|
private summarizeWithChunking;
|
|
19
20
|
private splitIntoChunks;
|
|
20
21
|
private callClaudeForSummary;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compactor.d.ts","sourceRoot":"","sources":["../../src/session/compactor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,KAAK,EAAE,MAAM;CAI1B;AAqBD,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAEjD,OAAO,CACX,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,
|
|
1
|
+
{"version":3,"file":"compactor.d.ts","sourceRoot":"","sources":["../../src/session/compactor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,KAAK,EAAE,MAAM;CAI1B;AAqBD,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAEjD,OAAO,CACX,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,gBAA6B,GACrC,OAAO,CAAC,gBAAgB,CAAC;YA2Cd,qBAAqB;IA4BnC,OAAO,CAAC,eAAe;YAkBT,oBAAoB;CAiCnC"}
|