@qwen-code/channel-github 0.21.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,37 @@
1
+ import type { ChannelAgentBridge, ChannelBaseOptions, ChannelConfig } from '@qwen-code/channel-base';
2
+ import { PollingChannelBase } from '@qwen-code/channel-base';
3
+ interface GithubConfig extends ChannelConfig {
4
+ baseUrl?: string;
5
+ }
6
+ interface GithubCursor {
7
+ lastProcessedAt: string;
8
+ /**
9
+ * Thread keys (`chatId|threadId`) whose issue/PR body has already been fed as
10
+ * a first-contact trigger. Dedupes body dispatch when a thread is re-fetched
11
+ * with `last_read_at` still null — which happens if `markNotificationsAsRead`
12
+ * failed to mark it read (its `updated_at` was bumped past the cutoff between
13
+ * fetch and mark). Bounded to the most recent entries so the cursor stays small.
14
+ */
15
+ dispatchedBodies?: string[];
16
+ }
17
+ export declare class GithubChannel extends PollingChannelBase<GithubCursor> {
18
+ private octokit;
19
+ private botUsername;
20
+ private webOrigin;
21
+ constructor(name: string, config: GithubConfig & Record<string, unknown>, bridge: ChannelAgentBridge, options?: ChannelBaseOptions);
22
+ protected createInitialCursor(): GithubCursor;
23
+ protected validateCursor(parsed: unknown): GithubCursor | null;
24
+ connect(): Promise<void>;
25
+ disconnect(): void;
26
+ sendMessage(_chatId: string, _text: string): Promise<void>;
27
+ protected sendThreadMessage(chatId: string, threadId: string | undefined, text: string): Promise<void>;
28
+ protected pollOnce(): Promise<void>;
29
+ private tryFirstContactBody;
30
+ private recordDispatchedBody;
31
+ private extractFromSubjectUrl;
32
+ private buildMetadata;
33
+ private githubApi;
34
+ private markNotificationsAsRead;
35
+ private postErrorComment;
36
+ }
37
+ export {};
@@ -0,0 +1,297 @@
1
+ import process from 'node:process';
2
+ import { Octokit } from '@octokit/rest';
3
+ import { HttpsProxyAgent } from 'https-proxy-agent';
4
+ import { PollingChannelBase } from '@qwen-code/channel-base';
5
+ import { testBotMention, stripBotMention } from './mention.js';
6
+ const MAX_DISPATCHED_BODIES = 500;
7
+ export class GithubChannel extends PollingChannelBase {
8
+ octokit;
9
+ botUsername = null;
10
+ webOrigin = 'https://github.com';
11
+ constructor(name, config, bridge, options) {
12
+ super(name, config, bridge, options);
13
+ }
14
+ createInitialCursor() {
15
+ return { lastProcessedAt: new Date().toISOString() };
16
+ }
17
+ validateCursor(parsed) {
18
+ const base = super.validateCursor(parsed);
19
+ if (!base || typeof base.lastProcessedAt !== 'string')
20
+ return null;
21
+ if (Number.isNaN(new Date(base.lastProcessedAt).getTime()))
22
+ return null;
23
+ if (base.dispatchedBodies !== undefined &&
24
+ !Array.isArray(base.dispatchedBodies)) {
25
+ base.dispatchedBodies = [];
26
+ }
27
+ return base;
28
+ }
29
+ async connect() {
30
+ const cfg = this.config;
31
+ const baseUrl = cfg.baseUrl || 'https://api.github.com';
32
+ this.webOrigin = baseUrl
33
+ .replace(/\/api\/v3\/?$/, '')
34
+ .replace(/^https:\/\/api\.github\.com/, 'https://github.com');
35
+ this.octokit = new Octokit({
36
+ auth: cfg.token,
37
+ baseUrl,
38
+ ...(this.proxy
39
+ ? { request: { agent: new HttpsProxyAgent(this.proxy) } }
40
+ : {}),
41
+ });
42
+ try {
43
+ const { data } = await this.octokit.rest.users.getAuthenticated();
44
+ this.botUsername = data.login;
45
+ }
46
+ catch (err) {
47
+ throw new Error(`[Channel:${this.name}] failed to resolve bot identity: ${err}`);
48
+ }
49
+ // GitHub logins are case-insensitive; normalize both sides so the
50
+ // allowlist gate and ChannelBase's shared-session authorization match
51
+ // regardless of how the operator typed the config entry.
52
+ const allowed = (this.config.allowedUsers ?? []).map((u) => u.toLowerCase());
53
+ this.config.allowedUsers = allowed;
54
+ this.gate.replaceAllowedUsers(allowed);
55
+ this.startPollLoop();
56
+ }
57
+ disconnect() {
58
+ this.stopPollLoop();
59
+ }
60
+ async sendMessage(_chatId, _text) {
61
+ throw new Error(`[Channel:${this.name}] sendMessage requires a threadId; use sendThreadMessage`);
62
+ }
63
+ async sendThreadMessage(chatId, threadId, text) {
64
+ if (!threadId) {
65
+ return super.sendThreadMessage(chatId, threadId, text);
66
+ }
67
+ const match = threadId.match(/^(?:issue|pr):(\d+)$/);
68
+ if (!match) {
69
+ throw new Error(`[Channel:${this.name}] invalid threadId format: ${threadId}`);
70
+ }
71
+ const issueNumber = Number(match[1]);
72
+ await this.githubApi(() => this.octokit.rest.issues.createComment({
73
+ owner: chatId.split('/')[0],
74
+ repo: chatId.split('/')[1],
75
+ issue_number: issueNumber,
76
+ body: text,
77
+ }), `createComment(${threadId})`);
78
+ }
79
+ async pollOnce() {
80
+ const since = new Date(new Date(this.cursor.lastProcessedAt).getTime() - 1000).toISOString();
81
+ const notifications = await this.githubApi(() => this.octokit.paginate(this.octokit.rest.activity.listNotificationsForAuthenticatedUser, { since, per_page: 100 }), 'listNotifications');
82
+ notifications.sort((a, b) => a.updated_at.localeCompare(b.updated_at));
83
+ const maxUpdatedAt = notifications.length > 0
84
+ ? notifications[notifications.length - 1].updated_at
85
+ : this.cursor.lastProcessedAt;
86
+ // Comment window lower bound: the cursor BEFORE this poll advances it.
87
+ // Comments with updated_at <= windowSince were already eligible for
88
+ // processing in a previous poll — skip them to prevent duplicates when
89
+ // PUT /notifications' async mark fails to mark the thread read.
90
+ const windowSince = this.cursor.lastProcessedAt;
91
+ await this.markNotificationsAsRead(maxUpdatedAt);
92
+ if (maxUpdatedAt > this.cursor.lastProcessedAt) {
93
+ this.cursor.lastProcessedAt = maxUpdatedAt;
94
+ }
95
+ for (const notification of notifications) {
96
+ if (!notification.subject.url)
97
+ continue;
98
+ const extracted = this.extractFromSubjectUrl(notification.subject.url);
99
+ if (!extracted) {
100
+ continue;
101
+ }
102
+ const { chatId, threadId, issueNumber } = extracted;
103
+ const lastReadAt = notification.last_read_at;
104
+ try {
105
+ const comments = await this.githubApi(() => this.octokit.paginate(this.octokit.rest.issues.listComments, {
106
+ owner: chatId.split('/')[0],
107
+ repo: chatId.split('/')[1],
108
+ issue_number: issueNumber,
109
+ since: windowSince,
110
+ per_page: 100,
111
+ }), `listComments(${threadId})`);
112
+ comments.sort((a, b) => (a.created_at || '').localeCompare(b.created_at || ''));
113
+ const newComments = comments.filter((c) => {
114
+ if (c.user?.login === this.botUsername) {
115
+ return false;
116
+ }
117
+ if (c.created_at && c.created_at > maxUpdatedAt) {
118
+ return false;
119
+ }
120
+ if (c.created_at && c.created_at <= windowSince) {
121
+ return false;
122
+ }
123
+ return true;
124
+ });
125
+ let dispatchedMention = false;
126
+ for (const comment of newComments) {
127
+ const body = comment.body || '';
128
+ const isMentioned = this.botUsername
129
+ ? testBotMention(body, this.botUsername)
130
+ : false;
131
+ const text = this.botUsername
132
+ ? stripBotMention(body, this.botUsername)
133
+ : body;
134
+ const envelope = {
135
+ channelName: this.name,
136
+ senderId: (comment.user?.login || 'unknown').toLowerCase(),
137
+ senderName: comment.user?.login || 'unknown',
138
+ chatId,
139
+ threadId,
140
+ messageId: String(comment.id),
141
+ text,
142
+ isGroup: true,
143
+ isMentioned,
144
+ isReplyToBot: false,
145
+ metadata: this.buildMetadata(chatId, threadId, notification),
146
+ };
147
+ try {
148
+ await this.handleInbound(envelope);
149
+ if (isMentioned && this.gate.isAllowed(envelope.senderId))
150
+ dispatchedMention = true;
151
+ }
152
+ catch (err) {
153
+ process.stderr.write(`[Channel:${this.name}] handleInbound failed for comment ${comment.id}: ${err}\n`);
154
+ await this.postErrorComment(chatId, issueNumber);
155
+ dispatchedMention = true;
156
+ break;
157
+ }
158
+ }
159
+ if (!dispatchedMention && !lastReadAt) {
160
+ await this.tryFirstContactBody(chatId, threadId, issueNumber, notification);
161
+ }
162
+ }
163
+ catch (err) {
164
+ process.stderr.write(`[Channel:${this.name}] API error processing ${threadId}, skipping: ${err}\n`);
165
+ continue;
166
+ }
167
+ }
168
+ }
169
+ async tryFirstContactBody(chatId, threadId, issueNumber, notification) {
170
+ // First contact is gated by `last_read_at` in the caller, but a thread can
171
+ // be re-fetched with `last_read_at` still null if marking it read failed
172
+ // (its updated_at was bumped past the cutoff). Dedup on an explicit record
173
+ // of which bodies we have already fed, so that re-fetch never feeds the body
174
+ // twice. Unlike a `created_at <= cursor` guard, this also feeds bodies whose
175
+ // notification arrived late — after the cursor had advanced past created_at.
176
+ const bodyKey = `${chatId}|${threadId}`;
177
+ if (this.cursor.dispatchedBodies?.includes(bodyKey))
178
+ return;
179
+ try {
180
+ const { data: issue } = await this.githubApi(() => this.octokit.rest.issues.get({
181
+ owner: chatId.split('/')[0],
182
+ repo: chatId.split('/')[1],
183
+ issue_number: issueNumber,
184
+ }), `issues.get(${threadId})`);
185
+ const body = issue.body || '';
186
+ if (issue.user?.login === this.botUsername)
187
+ return;
188
+ const isMentioned = this.botUsername
189
+ ? testBotMention(body, this.botUsername)
190
+ : false;
191
+ const text = this.botUsername
192
+ ? stripBotMention(body, this.botUsername)
193
+ : body;
194
+ const envelope = {
195
+ channelName: this.name,
196
+ senderId: (issue.user?.login || 'unknown').toLowerCase(),
197
+ senderName: issue.user?.login || 'unknown',
198
+ chatId,
199
+ threadId,
200
+ messageId: `issue-body-${issueNumber}`,
201
+ text,
202
+ isGroup: true,
203
+ isMentioned,
204
+ isReplyToBot: false,
205
+ metadata: this.buildMetadata(chatId, threadId, {
206
+ subject: { title: notification.subject.title },
207
+ }),
208
+ };
209
+ try {
210
+ await this.handleInbound(envelope);
211
+ this.recordDispatchedBody(bodyKey);
212
+ }
213
+ catch (err) {
214
+ process.stderr.write(`[Channel:${this.name}] handleInbound failed for issue body ${issueNumber}: ${err}\n`);
215
+ await this.postErrorComment(chatId, issueNumber);
216
+ this.recordDispatchedBody(bodyKey);
217
+ }
218
+ }
219
+ catch (err) {
220
+ process.stderr.write(`[Channel:${this.name}] failed to fetch issue for first contact: ${err}\n`);
221
+ }
222
+ }
223
+ recordDispatchedBody(key) {
224
+ const list = this.cursor.dispatchedBodies ?? [];
225
+ list.push(key);
226
+ this.cursor.dispatchedBodies = list.slice(-MAX_DISPATCHED_BODIES);
227
+ }
228
+ extractFromSubjectUrl(url) {
229
+ const match = url.match(/\/repos\/([^/]+\/[^/]+)\/(issues|pulls)\/(\d+)/);
230
+ if (!match)
231
+ return null;
232
+ const chatId = match[1];
233
+ const kind = match[2] === 'pulls' ? 'pr' : 'issue';
234
+ const issueNumber = Number(match[3]);
235
+ const threadId = `${kind}:${issueNumber}`;
236
+ return { chatId, threadId, issueNumber };
237
+ }
238
+ buildMetadata(chatId, threadId, notification) {
239
+ const type = threadId.startsWith('pr:') ? 'Pull Request' : 'Issue';
240
+ const title = notification.subject.title || '';
241
+ const url = `${this.webOrigin}/${chatId}/${threadId.startsWith('pr:') ? 'pull' : 'issues'}/${threadId.split(':')[1]}`;
242
+ return `Type: ${type} | Title: ${title} | URL: ${url}`;
243
+ }
244
+ async githubApi(fn, label, retries = 3) {
245
+ for (let attempt = 1; attempt <= retries; attempt++) {
246
+ try {
247
+ return await fn();
248
+ }
249
+ catch (err) {
250
+ if (attempt === retries)
251
+ throw err;
252
+ // Octokit RequestError: { status, response?: { headers } }
253
+ const e = err;
254
+ const headers = e.response?.headers ?? {};
255
+ let cooldown;
256
+ if (headers['retry-after']) {
257
+ const retryAfter = Number(headers['retry-after']);
258
+ cooldown = Number.isFinite(retryAfter)
259
+ ? retryAfter * 1000
260
+ : 1000 * 2 ** (attempt - 1);
261
+ }
262
+ else if ((e.status === 403 || e.status === 429) &&
263
+ Number(headers['x-ratelimit-remaining']) === 0 &&
264
+ Number(headers['x-ratelimit-reset']) > 0) {
265
+ cooldown =
266
+ Math.max(0, Number(headers['x-ratelimit-reset']) * 1000 - Date.now()) + 1000;
267
+ }
268
+ else {
269
+ cooldown = 1000 * 2 ** (attempt - 1);
270
+ }
271
+ process.stderr.write(`[Channel:${this.name}] ${label} failed (attempt ${attempt}/${retries}, status=${e.status}), retrying in ${cooldown}ms: ${e.message}\n`);
272
+ await this.abortableSleep(cooldown);
273
+ }
274
+ }
275
+ throw new Error('unreachable');
276
+ }
277
+ async markNotificationsAsRead(lastReadAt) {
278
+ await this.githubApi(() => this.octokit.rest.activity.markNotificationsAsRead({
279
+ last_read_at: lastReadAt,
280
+ read: true,
281
+ }), 'markNotificationsAsRead');
282
+ }
283
+ async postErrorComment(chatId, issueNumber) {
284
+ try {
285
+ await this.githubApi(() => this.octokit.rest.issues.createComment({
286
+ owner: chatId.split('/')[0],
287
+ repo: chatId.split('/')[1],
288
+ issue_number: issueNumber,
289
+ body: '⚠️ Failed to process this request. Please re-mention the bot to retry.',
290
+ }), `postErrorComment(${chatId}#${issueNumber})`);
291
+ }
292
+ catch (err) {
293
+ process.stderr.write(`[Channel:${this.name}] postErrorComment also failed for ${chatId}#${issueNumber}, user must re-mention manually: ${err}\n`);
294
+ }
295
+ }
296
+ }
297
+ //# sourceMappingURL=GithubAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GithubAdapter.js","sourceRoot":"","sources":["../src/GithubAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ChannelPlugin } from '@qwen-code/channel-base';
2
+ import { GithubChannel } from './GithubAdapter.js';
3
+ export { GithubChannel };
4
+ export declare const plugin: ChannelPlugin;
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ import { GithubChannel } from './GithubAdapter.js';
2
+ export { GithubChannel };
3
+ export const plugin = {
4
+ channelType: 'github',
5
+ displayName: 'GitHub',
6
+ requiredConfigFields: ['token'],
7
+ envResolvableConfigFields: ['baseUrl'],
8
+ defaultSessionScope: 'chat_thread',
9
+ createChannel: (name, config, bridge, options) => new GithubChannel(name, config, bridge, options),
10
+ };
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,MAAM,CAAC,MAAM,MAAM,GAAkB;IACnC,WAAW,EAAE,QAAQ;IACrB,WAAW,EAAE,QAAQ;IACrB,oBAAoB,EAAE,CAAC,OAAO,CAAC;IAC/B,yBAAyB,EAAE,CAAC,SAAS,CAAC;IACtC,mBAAmB,EAAE,aAAa;IAClC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAC/C,IAAI,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC;CACnD,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function escapeRegex(str: string): string;
2
+ export declare function testBotMention(text: string, username: string): boolean;
3
+ export declare function stripBotMention(text: string, username: string): string;
@@ -0,0 +1,14 @@
1
+ export function escapeRegex(str) {
2
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
3
+ }
4
+ const MENTION_LOOKBEHIND = '(?<=\\s|^|[([{<:;"\'])';
5
+ const MENTION_LOOKAHEAD = '(?=[^a-zA-Z0-9_/-]|$)';
6
+ export function testBotMention(text, username) {
7
+ const re = new RegExp(`${MENTION_LOOKBEHIND}@${escapeRegex(username)}${MENTION_LOOKAHEAD}`, 'i');
8
+ return re.test(text);
9
+ }
10
+ export function stripBotMention(text, username) {
11
+ const re = new RegExp(`${MENTION_LOOKBEHIND}@${escapeRegex(username)}${MENTION_LOOKAHEAD}`, 'gi');
12
+ return text.replace(re, '');
13
+ }
14
+ //# sourceMappingURL=mention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mention.js","sourceRoot":"","sources":["../src/mention.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AACpD,MAAM,iBAAiB,GAAG,uBAAuB,CAAC;AAElD,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,QAAgB;IAC3D,MAAM,EAAE,GAAG,IAAI,MAAM,CACnB,GAAG,kBAAkB,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,iBAAiB,EAAE,EACpE,GAAG,CACJ,CAAC;IACF,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,QAAgB;IAC5D,MAAM,EAAE,GAAG,IAAI,MAAM,CACnB,GAAG,kBAAkB,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,iBAAiB,EAAE,EACpE,IAAI,CACL,CAAC;IACF,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC9B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@qwen-code/channel-github",
3
+ "version": "0.21.0-preview.0",
4
+ "description": "GitHub polling channel adapter for Qwen Code",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc --build",
19
+ "test": "vitest run",
20
+ "test:ci": "vitest run"
21
+ },
22
+ "dependencies": {
23
+ "@qwen-code/channel-base": "^0.21.0",
24
+ "@octokit/rest": "^21.1.1",
25
+ "https-proxy-agent": "^7.0.6"
26
+ },
27
+ "devDependencies": {
28
+ "typescript": "^5.0.0"
29
+ }
30
+ }