@zhin.js/adapter-github 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -12
- package/{skills/github/SKILL.md → agent/skills/github.md} +22 -5
- package/agent/tools/bind.ts +12 -0
- package/agent/tools/create_pr.ts +19 -0
- package/agent/tools/install.ts +12 -0
- package/agent/tools/patch_file.ts +18 -0
- package/agent/tools/prepare_workspace.ts +14 -0
- package/agent/tools/push_branch.ts +17 -0
- package/agent/tools/star.ts +15 -0
- package/agent/tools/subscribe.ts +16 -0
- package/agent/tools/subscriptions.ts +13 -0
- package/agent/tools/unbind.ts +12 -0
- package/agent/tools/unsubscribe.ts +15 -0
- package/agent/tools/whoami.ts +12 -0
- package/lib/agent/tools/bind.js +12 -0
- package/lib/agent/tools/bind.js.map +1 -0
- package/lib/agent/tools/create_pr.js +19 -0
- package/lib/agent/tools/create_pr.js.map +1 -0
- package/lib/agent/tools/install.js +12 -0
- package/lib/agent/tools/install.js.map +1 -0
- package/lib/agent/tools/patch_file.js +18 -0
- package/lib/agent/tools/patch_file.js.map +1 -0
- package/lib/agent/tools/prepare_workspace.js +14 -0
- package/lib/agent/tools/prepare_workspace.js.map +1 -0
- package/lib/agent/tools/push_branch.js +17 -0
- package/lib/agent/tools/push_branch.js.map +1 -0
- package/lib/agent/tools/star.js +15 -0
- package/lib/agent/tools/star.js.map +1 -0
- package/lib/agent/tools/subscribe.js +16 -0
- package/lib/agent/tools/subscribe.js.map +1 -0
- package/lib/agent/tools/subscriptions.js +13 -0
- package/lib/agent/tools/subscriptions.js.map +1 -0
- package/lib/agent/tools/unbind.js +12 -0
- package/lib/agent/tools/unbind.js.map +1 -0
- package/lib/agent/tools/unsubscribe.js +15 -0
- package/lib/agent/tools/unsubscribe.js.map +1 -0
- package/lib/agent/tools/whoami.js +12 -0
- package/lib/agent/tools/whoami.js.map +1 -0
- package/lib/{adapter.js → src/adapter.js} +11 -6
- package/lib/src/adapter.js.map +1 -0
- package/lib/{agent-prompt.js → src/agent-prompt.js} +10 -8
- package/lib/src/agent-prompt.js.map +1 -0
- package/lib/{endpoint.js → src/endpoint.js} +27 -3
- package/lib/src/endpoint.js.map +1 -0
- package/lib/{gh-client.js → src/gh-client.js} +99 -0
- package/lib/src/gh-client.js.map +1 -0
- package/lib/src/github-agent-deps.js +13 -0
- package/lib/src/github-agent-deps.js.map +1 -0
- package/lib/src/github-bot-handlers.js +78 -0
- package/lib/src/github-bot-handlers.js.map +1 -0
- package/lib/src/github-channel-context.js +32 -0
- package/lib/src/github-channel-context.js.map +1 -0
- package/lib/src/github-tool-handlers.js +215 -0
- package/lib/src/github-tool-handlers.js.map +1 -0
- package/lib/src/index.js +104 -0
- package/lib/src/index.js.map +1 -0
- package/lib/{register-github-mcp.js → src/register-github-mcp.js} +5 -0
- package/lib/src/register-github-mcp.js.map +1 -0
- package/lib/src/segment-mapper.js.map +1 -0
- package/lib/src/types.js.map +1 -0
- package/lib/src/workspace-manager.js +109 -0
- package/lib/src/workspace-manager.js.map +1 -0
- package/package.json +16 -6
- package/src/adapter.ts +12 -8
- package/src/agent-prompt.ts +11 -10
- package/src/endpoint.ts +38 -10
- package/src/gh-client.ts +131 -0
- package/src/github-agent-deps.ts +27 -0
- package/src/github-bot-handlers.ts +109 -0
- package/src/github-channel-context.ts +46 -0
- package/src/github-tool-handlers.ts +244 -0
- package/src/index.ts +32 -326
- package/src/register-github-mcp.ts +5 -0
- package/src/types.ts +6 -0
- package/src/workspace-manager.ts +114 -0
- package/lib/adapter.d.ts +0 -66
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js.map +0 -1
- package/lib/agent-prompt.d.ts +0 -3
- package/lib/agent-prompt.d.ts.map +0 -1
- package/lib/agent-prompt.js.map +0 -1
- package/lib/endpoint.d.ts +0 -26
- package/lib/endpoint.d.ts.map +0 -1
- package/lib/endpoint.js.map +0 -1
- package/lib/gh-client.d.ts +0 -228
- package/lib/gh-client.d.ts.map +0 -1
- package/lib/gh-client.js.map +0 -1
- package/lib/index.d.ts +0 -34
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -388
- package/lib/index.js.map +0 -1
- package/lib/register-github-mcp.d.ts +0 -7
- package/lib/register-github-mcp.d.ts.map +0 -1
- package/lib/register-github-mcp.js.map +0 -1
- package/lib/segment-mapper.d.ts +0 -2
- package/lib/segment-mapper.d.ts.map +0 -1
- package/lib/segment-mapper.js.map +0 -1
- package/lib/types.d.ts +0 -144
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js.map +0 -1
- /package/lib/{segment-mapper.js → src/segment-mapper.js} +0 -0
- /package/lib/{types.js → src/types.js} +0 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { formatCompact } from 'zhin.js';
|
|
2
|
+
import { getCurrentCommMessage } from '@zhin.js/agent/security';
|
|
3
|
+
import { GhClient } from './gh-client.js';
|
|
4
|
+
import { getAdapter, getGithubAgentDeps } from './github-agent-deps.js';
|
|
5
|
+
function oauthModel() {
|
|
6
|
+
const db = getGithubAgentDeps().plugin.root?.inject('database');
|
|
7
|
+
return db?.models?.get('github_oauth_users');
|
|
8
|
+
}
|
|
9
|
+
function subscriptionsModel() {
|
|
10
|
+
const db = getGithubAgentDeps().plugin.root?.inject('database');
|
|
11
|
+
return db?.models?.get('github_subscriptions');
|
|
12
|
+
}
|
|
13
|
+
export async function executeGithubStar(args, commMessage) {
|
|
14
|
+
const adapter = getAdapter();
|
|
15
|
+
const msg = commMessage ?? getCurrentCommMessage();
|
|
16
|
+
const gh = await adapter.getUserOrDefaultAPI(msg?.$adapter, msg?.$sender.id);
|
|
17
|
+
if (!gh)
|
|
18
|
+
return '❌ 没有可用的 GitHub bot';
|
|
19
|
+
switch (args.action) {
|
|
20
|
+
case 'star': {
|
|
21
|
+
const r = await gh.starRepo(args.repo);
|
|
22
|
+
return r.ok ? `⭐ 已 Star ${args.repo}` : `❌ ${r.data?.message || JSON.stringify(r.data)}`;
|
|
23
|
+
}
|
|
24
|
+
case 'unstar': {
|
|
25
|
+
const r = await gh.unstarRepo(args.repo);
|
|
26
|
+
return r.ok ? `💔 已取消 Star ${args.repo}` : `❌ ${r.data?.message || JSON.stringify(r.data)}`;
|
|
27
|
+
}
|
|
28
|
+
case 'check': {
|
|
29
|
+
const starred = await gh.isStarred(args.repo);
|
|
30
|
+
return starred ? `⭐ 已 Star ${args.repo}` : `☆ 尚未 Star ${args.repo}`;
|
|
31
|
+
}
|
|
32
|
+
default:
|
|
33
|
+
return `❌ 未知操作: ${args.action}`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function executeGithubBind(_args, commMessage) {
|
|
37
|
+
const adapter = getAdapter();
|
|
38
|
+
const { plugin } = getGithubAgentDeps();
|
|
39
|
+
const msg = commMessage ?? getCurrentCommMessage();
|
|
40
|
+
if (!msg?.$adapter || !msg?.$sender?.id)
|
|
41
|
+
return '❌ 无法获取当前用户信息';
|
|
42
|
+
const clientId = adapter.getClientId();
|
|
43
|
+
if (!clientId)
|
|
44
|
+
return '❌ Endpoint 未配置 GitHub App 或 App 无 client_id,无法进行账号绑定';
|
|
45
|
+
const model = oauthModel();
|
|
46
|
+
if (!model)
|
|
47
|
+
return '❌ 数据库未就绪';
|
|
48
|
+
const [existing] = await model.select().where({ platform: msg.$adapter, platform_uid: msg.$sender.id });
|
|
49
|
+
if (existing) {
|
|
50
|
+
return `⚠️ 你已绑定 GitHub 账号: ${existing.github_login}\n如需重新绑定,请先执行 github_unbind`;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const host = adapter.getHost();
|
|
54
|
+
const codeResp = await GhClient.deviceFlowRequestCode(clientId, host);
|
|
55
|
+
const tokenPromise = GhClient.deviceFlowPollToken(clientId, codeResp.device_code, codeResp.interval, codeResp.expires_in, host);
|
|
56
|
+
const replyMsg = [
|
|
57
|
+
'🔗 请在浏览器中打开以下链接进行授权:',
|
|
58
|
+
` ${codeResp.verification_uri}`,
|
|
59
|
+
'',
|
|
60
|
+
`📋 输入验证码: **${codeResp.user_code}**`,
|
|
61
|
+
'',
|
|
62
|
+
`⏳ 等待授权中…(${Math.floor(codeResp.expires_in / 60)} 分钟内有效)`,
|
|
63
|
+
].join('\n');
|
|
64
|
+
tokenPromise.then(async (tokenData) => {
|
|
65
|
+
if (!tokenData) {
|
|
66
|
+
plugin.logger.warn(formatCompact({ op: 'device_flow', ok: false, platform: msg.$adapter, sender: msg.$sender.id }));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const userGh = new GhClient({ host, token: tokenData.access_token });
|
|
70
|
+
const authResult = await userGh.verifyAuth();
|
|
71
|
+
const login = authResult.ok ? authResult.user : 'unknown';
|
|
72
|
+
await model.insert({
|
|
73
|
+
id: Date.now(),
|
|
74
|
+
platform: msg.$adapter,
|
|
75
|
+
platform_uid: msg.$sender.id,
|
|
76
|
+
github_login: login,
|
|
77
|
+
access_token: tokenData.access_token,
|
|
78
|
+
created_at: Date.now(),
|
|
79
|
+
});
|
|
80
|
+
plugin.logger.debug(formatCompact({ op: 'bind', platform: msg.$adapter, sender: msg.$sender.id, login }));
|
|
81
|
+
if (msg?.$reply) {
|
|
82
|
+
await msg.$reply(`✅ GitHub 账号绑定成功!\n👤 ${login}`);
|
|
83
|
+
}
|
|
84
|
+
}).catch((err) => {
|
|
85
|
+
plugin.logger.error('GitHub Device Flow 错误:', err);
|
|
86
|
+
});
|
|
87
|
+
return replyMsg;
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
return `❌ Device Flow 启动失败: ${e instanceof Error ? e.message : String(e)}`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export async function executeGithubUnbind(_args, commMessage) {
|
|
94
|
+
const msg = commMessage ?? getCurrentCommMessage();
|
|
95
|
+
if (!msg?.$adapter || !msg?.$sender?.id)
|
|
96
|
+
return '❌ 无法获取当前用户信息';
|
|
97
|
+
const model = oauthModel();
|
|
98
|
+
if (!model)
|
|
99
|
+
return '❌ 数据库未就绪';
|
|
100
|
+
const [existing] = await model.select().where({ platform: msg.$adapter, platform_uid: msg.$sender.id });
|
|
101
|
+
if (!existing)
|
|
102
|
+
return '📭 你尚未绑定 GitHub 账号';
|
|
103
|
+
await model.delete().where({ id: existing.id });
|
|
104
|
+
return `✅ 已解除 GitHub 账号绑定: ${existing.github_login}`;
|
|
105
|
+
}
|
|
106
|
+
export async function executeGithubWhoami(_args, commMessage) {
|
|
107
|
+
const adapter = getAdapter();
|
|
108
|
+
const msg = commMessage ?? getCurrentCommMessage();
|
|
109
|
+
if (!msg?.$adapter || !msg?.$sender?.id)
|
|
110
|
+
return '❌ 无法获取当前用户信息';
|
|
111
|
+
const model = oauthModel();
|
|
112
|
+
if (!model)
|
|
113
|
+
return '❌ 数据库未就绪';
|
|
114
|
+
const [existing] = await model.select().where({ platform: msg.$adapter, platform_uid: msg.$sender.id });
|
|
115
|
+
if (!existing)
|
|
116
|
+
return '📭 你尚未绑定 GitHub 账号\n🔗 使用 github_bind 绑定你的账号';
|
|
117
|
+
const userGh = new GhClient({ host: adapter.getHost(), token: existing.access_token });
|
|
118
|
+
const auth = await userGh.verifyAuth();
|
|
119
|
+
if (auth.ok) {
|
|
120
|
+
return `👤 已绑定 GitHub 账号: ${auth.user}\n📅 绑定时间: ${new Date(existing.created_at).toLocaleString('zh-CN')}`;
|
|
121
|
+
}
|
|
122
|
+
return `⚠️ 已绑定账号 ${existing.github_login},但 Token 已失效\n🔗 请执行 github_unbind 后重新 github_bind`;
|
|
123
|
+
}
|
|
124
|
+
export async function executeGithubInstall() {
|
|
125
|
+
const adapter = getAdapter();
|
|
126
|
+
const slug = adapter.getAppSlug();
|
|
127
|
+
if (!slug)
|
|
128
|
+
return '❌ Endpoint 未配置 GitHub App';
|
|
129
|
+
const host = adapter.getHost() || 'github.com';
|
|
130
|
+
const installations = adapter.getInstallations();
|
|
131
|
+
let msg = `🔗 请点击以下链接安装 GitHub App 到你的仓库:\n https://${host}/apps/${slug}/installations/new`;
|
|
132
|
+
if (installations.length) {
|
|
133
|
+
msg += `\n\n📋 当前已安装 (${installations.length}):`;
|
|
134
|
+
for (const inst of installations) {
|
|
135
|
+
msg += `\n • ${inst.account.login} (${inst.account.type})`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return msg;
|
|
139
|
+
}
|
|
140
|
+
export async function executeGithubSubscribe(args, commMessage) {
|
|
141
|
+
const msg = commMessage ?? getCurrentCommMessage();
|
|
142
|
+
if (!msg?.$adapter || !msg?.$sender.id || !msg?.$channel?.id || !msg?.$endpoint) {
|
|
143
|
+
return '❌ 无法获取当前聊天通道信息';
|
|
144
|
+
}
|
|
145
|
+
const model = subscriptionsModel();
|
|
146
|
+
if (!model)
|
|
147
|
+
return '❌ 数据库未就绪';
|
|
148
|
+
const validEvents = ['push', 'issue', 'star', 'fork', 'unstar', 'pull_request'];
|
|
149
|
+
const events = args.events
|
|
150
|
+
? args.events.split(',').map((s) => s.trim()).filter((e) => validEvents.includes(e))
|
|
151
|
+
: validEvents;
|
|
152
|
+
if (!events.length)
|
|
153
|
+
return `❌ 无效的事件类型,可选: ${validEvents.join(', ')}`;
|
|
154
|
+
const [existing] = await model.select().where({
|
|
155
|
+
repo: args.repo,
|
|
156
|
+
target_id: msg.$channel?.id,
|
|
157
|
+
adapter: msg.$adapter,
|
|
158
|
+
endpoint: msg.$endpoint,
|
|
159
|
+
});
|
|
160
|
+
if (existing) {
|
|
161
|
+
await model.update({ events, target_type: msg.$channel?.type || 'private' }).where({ id: existing.id });
|
|
162
|
+
return `✅ 已更新订阅 ${args.repo}\n📡 事件: ${events.join(', ')}`;
|
|
163
|
+
}
|
|
164
|
+
await model.insert({
|
|
165
|
+
id: Date.now(),
|
|
166
|
+
repo: args.repo,
|
|
167
|
+
events,
|
|
168
|
+
target_id: msg.$channel?.id,
|
|
169
|
+
target_type: msg.$channel?.type || 'private',
|
|
170
|
+
adapter: msg.$adapter,
|
|
171
|
+
endpoint: msg.$endpoint,
|
|
172
|
+
});
|
|
173
|
+
return `✅ 已订阅 ${args.repo}\n📡 事件: ${events.join(', ')}\n📌 通知将推送到当前通道`;
|
|
174
|
+
}
|
|
175
|
+
export async function executeGithubUnsubscribe(args, commMessage) {
|
|
176
|
+
const msg = commMessage ?? getCurrentCommMessage();
|
|
177
|
+
if (!msg?.$adapter || !msg?.$channel?.id || !msg?.$endpoint) {
|
|
178
|
+
return '❌ 无法获取当前聊天通道信息';
|
|
179
|
+
}
|
|
180
|
+
const model = subscriptionsModel();
|
|
181
|
+
if (!model)
|
|
182
|
+
return '❌ 数据库未就绪';
|
|
183
|
+
const [existing] = await model.select().where({
|
|
184
|
+
repo: args.repo,
|
|
185
|
+
target_id: msg.$channel?.id,
|
|
186
|
+
adapter: msg.$adapter,
|
|
187
|
+
endpoint: msg.$endpoint,
|
|
188
|
+
});
|
|
189
|
+
if (!existing)
|
|
190
|
+
return `📭 当前通道未订阅 ${args.repo}`;
|
|
191
|
+
await model.delete().where({ id: existing.id });
|
|
192
|
+
return `✅ 已取消订阅 ${args.repo}`;
|
|
193
|
+
}
|
|
194
|
+
export async function executeGithubSubscriptions(_args, commMessage) {
|
|
195
|
+
const msg = commMessage ?? getCurrentCommMessage();
|
|
196
|
+
if (!msg?.$adapter || !msg?.$channel?.id || !msg?.$endpoint) {
|
|
197
|
+
return '❌ 无法获取当前聊天通道信息';
|
|
198
|
+
}
|
|
199
|
+
const model = subscriptionsModel();
|
|
200
|
+
if (!model)
|
|
201
|
+
return '❌ 数据库未就绪';
|
|
202
|
+
const subs = await model.select().where({
|
|
203
|
+
target_id: msg.$channel?.id,
|
|
204
|
+
adapter: msg.$adapter,
|
|
205
|
+
endpoint: msg.$endpoint,
|
|
206
|
+
});
|
|
207
|
+
if (!subs?.length)
|
|
208
|
+
return '📭 当前通道没有任何 GitHub 订阅';
|
|
209
|
+
return `📋 当前通道订阅 (${subs.length}):\n\n` +
|
|
210
|
+
subs.map((s) => {
|
|
211
|
+
const events = Array.isArray(s.events) ? s.events : [];
|
|
212
|
+
return ` 📦 ${s.repo}\n 📡 ${events.join(', ') || '(无事件)'}`;
|
|
213
|
+
}).join('\n\n');
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=github-tool-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-tool-handlers.js","sourceRoot":"","sources":["../../src/github-tool-handlers.ts"],"names":[],"mappings":"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"}
|
package/lib/src/index.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub 适配器入口:类型扩展、模型、导出、注册
|
|
3
|
+
*/
|
|
4
|
+
import { formatCompact, usePlugin } from 'zhin.js';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { registerAgentPromptContributor, unregisterAgentPromptContributor } from 'zhin.js/agent';
|
|
7
|
+
import { createGithubAgentPromptContributor } from './agent-prompt.js';
|
|
8
|
+
import { GitHubAdapter } from './adapter.js';
|
|
9
|
+
import { registerGithubMcp } from './register-github-mcp.js';
|
|
10
|
+
import { setGithubAgentDeps } from './github-agent-deps.js';
|
|
11
|
+
import { WorkspaceManager } from './workspace-manager.js';
|
|
12
|
+
export * from './types.js';
|
|
13
|
+
export { GitHubEndpoint, parseMarkdown, toMarkdown, enrichGithubInboundMessage, shouldAutoReplyRepo } from './endpoint.js';
|
|
14
|
+
export { GitHubAdapter } from './adapter.js';
|
|
15
|
+
export { GhClient } from './gh-client.js';
|
|
16
|
+
export { WorkspaceManager } from './workspace-manager.js';
|
|
17
|
+
export { parseMessageChannel, issueBranchName, resolveWorkspaceBranch } from './github-channel-context.js';
|
|
18
|
+
const plugin = usePlugin();
|
|
19
|
+
const { provide, defineModel, useContext, logger } = plugin;
|
|
20
|
+
registerGithubMcp(plugin);
|
|
21
|
+
defineModel('github_subscriptions', {
|
|
22
|
+
id: { type: 'integer', primary: true },
|
|
23
|
+
repo: { type: 'text', nullable: false },
|
|
24
|
+
events: { type: 'json', default: [] },
|
|
25
|
+
target_id: { type: 'text', nullable: false },
|
|
26
|
+
target_type: { type: 'text', nullable: false },
|
|
27
|
+
adapter: { type: 'text', nullable: false },
|
|
28
|
+
endpoint: { type: 'text', nullable: false },
|
|
29
|
+
});
|
|
30
|
+
defineModel('github_events', {
|
|
31
|
+
id: { type: 'integer', primary: true },
|
|
32
|
+
repo: { type: 'text', nullable: false },
|
|
33
|
+
event_type: { type: 'text', nullable: false },
|
|
34
|
+
payload: { type: 'json', default: {} },
|
|
35
|
+
});
|
|
36
|
+
defineModel('github_oauth_users', {
|
|
37
|
+
id: { type: 'integer', primary: true },
|
|
38
|
+
platform: { type: 'text', nullable: false },
|
|
39
|
+
platform_uid: { type: 'text', nullable: false },
|
|
40
|
+
github_login: { type: 'text', nullable: false },
|
|
41
|
+
access_token: { type: 'text', nullable: false },
|
|
42
|
+
created_at: { type: 'integer', default: 0 },
|
|
43
|
+
});
|
|
44
|
+
provide({
|
|
45
|
+
name: 'github',
|
|
46
|
+
description: 'GitHub Adapter — Issues/PRs as chat channels, full repo management via gh CLI',
|
|
47
|
+
mounted: async (p) => {
|
|
48
|
+
registerAgentPromptContributor(createGithubAgentPromptContributor());
|
|
49
|
+
const adapter = new GitHubAdapter(p);
|
|
50
|
+
await adapter.start();
|
|
51
|
+
return adapter;
|
|
52
|
+
},
|
|
53
|
+
dispose: async (adapter) => {
|
|
54
|
+
unregisterAgentPromptContributor('github');
|
|
55
|
+
await adapter.stop();
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
// 混合模式:有 router + webhook_secret → Webhook 实时;否则 → 轮询降级
|
|
59
|
+
useContext('github', (adapter) => {
|
|
60
|
+
if (adapter.hasWebhookConfig) {
|
|
61
|
+
const router = plugin.inject('router');
|
|
62
|
+
if (router) {
|
|
63
|
+
adapter.setupWebhook(router);
|
|
64
|
+
logger.debug(formatCompact({ op: 'events', source: 'webhook' }));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
plugin.useContext('router', (r) => {
|
|
68
|
+
adapter.setupWebhook(r);
|
|
69
|
+
logger.debug(formatCompact({ op: 'events', source: 'webhook', deferred: true }));
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!adapter.webhookActive) {
|
|
74
|
+
adapter.startPolling();
|
|
75
|
+
logger.debug(formatCompact({ op: 'events', source: 'poll' }));
|
|
76
|
+
}
|
|
77
|
+
return () => adapter.stopPolling();
|
|
78
|
+
});
|
|
79
|
+
useContext('tool', 'github', (_toolService, adapter) => {
|
|
80
|
+
// Endpoint 由 App 从 zhin.config endpoints 注入,可能晚于本回调;懒解析 GhClient。
|
|
81
|
+
let workspaceManager = null;
|
|
82
|
+
setGithubAgentDeps({
|
|
83
|
+
getAdapter: () => adapter,
|
|
84
|
+
getWorkspaceManager: () => {
|
|
85
|
+
if (workspaceManager)
|
|
86
|
+
return workspaceManager;
|
|
87
|
+
const gh = adapter.getAPI();
|
|
88
|
+
if (!gh) {
|
|
89
|
+
throw new Error('GitHub Endpoint 尚未就绪(检查 endpoints 中 github 配置是否已连接)');
|
|
90
|
+
}
|
|
91
|
+
const endpoint = adapter.endpoints.values().next().value;
|
|
92
|
+
const cfg = endpoint?.$config;
|
|
93
|
+
const workspaceRoot = cfg?.workspace_root
|
|
94
|
+
?? path.join(process.cwd(), 'data', 'github-workspaces');
|
|
95
|
+
workspaceManager = new WorkspaceManager(gh, workspaceRoot);
|
|
96
|
+
return workspaceManager;
|
|
97
|
+
},
|
|
98
|
+
plugin,
|
|
99
|
+
});
|
|
100
|
+
logger.debug('GitHub agent deps initialized (lazy workspace)');
|
|
101
|
+
return () => { };
|
|
102
|
+
});
|
|
103
|
+
logger.debug('GitHub 适配器已加载 (gh CLI 认证)');
|
|
104
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,11 @@ export function registerGithubMcp(plugin) {
|
|
|
19
19
|
return;
|
|
20
20
|
const configService = root.inject('config');
|
|
21
21
|
const appConfig = configService?.getPrimary() || {};
|
|
22
|
+
const githubMcp = appConfig.ai?.githubMcp;
|
|
23
|
+
if (githubMcp?.enabled !== true) {
|
|
24
|
+
logger.debug('[MCP] server-github skipped: set ai.githubMcp.enabled=true to opt in (PAT / human identity)');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
22
27
|
const token = resolveGithubMcpToken(appConfig.ai);
|
|
23
28
|
if (!token) {
|
|
24
29
|
logger.debug('[MCP] server-github skipped: set GITHUB_PERSONAL_ACCESS_TOKEN or ai.githubMcp.token');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-github-mcp.js","sourceRoot":"","sources":["../../src/register-github-mcp.ts"],"names":[],"mappings":"AAKA,OAAO,eAAe,CAAC;AAevB,SAAS,qBAAqB,CAAC,EAAa;IAC1C,MAAM,UAAU,GAAG,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAChD,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,IAAI,EAAE;QAChD,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE;QAChC,SAAS,CACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAE5C,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;QACtB,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;YAAE,OAAO;QAE7B,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAsC,CAAC;QAC/E,IAAI,CAAC,YAAY;YAAE,OAAO;QAE1B,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO;QAE5C,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,aAAa,EAAE,UAAU,EAAqB,IAAI,EAAE,CAAC;QACvE,MAAM,SAAS,GAAG,SAAS,CAAC,EAAE,EAAE,SAA8D,CAAC;QAC/F,IAAI,SAAS,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,6FAA6F,CAAC,CAAC;YAC5G,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,qFAAqF,CAAC,CAAC;YACpG,OAAO;QACT,CAAC;QAED,OAAO,YAAY,CAAC,MAAM,CACxB;YACE,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,OAAO;YAClB,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,qCAAqC,CAAC;YACnD,GAAG,EAAE,EAAE,4BAA4B,EAAE,KAAK,EAAE;SAC7C,EACD,EAAE,EACF,gBAAgB,CACjB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment-mapper.js","sourceRoot":"","sources":["../../src/segment-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,kCAAkC;AAClC,sBAAsB;AAmCtB,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAClE,IAAI,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC7D,IAAI,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAoB,EAAE,MAAc;IAC/E,OAAO,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,WAAW,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,MAAM,EAAE,CAAC;AAClF,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Managed git workspaces for GitHub App Bot development flow.
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
export class WorkspaceManager {
|
|
8
|
+
gh;
|
|
9
|
+
rootDir;
|
|
10
|
+
constructor(gh, rootDir) {
|
|
11
|
+
this.gh = gh;
|
|
12
|
+
this.rootDir = rootDir;
|
|
13
|
+
}
|
|
14
|
+
getRepoPath(repo) {
|
|
15
|
+
const [owner, name] = repo.split('/');
|
|
16
|
+
return path.join(this.rootDir, owner, name);
|
|
17
|
+
}
|
|
18
|
+
runGit(cwd, args, env) {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
const proc = spawn('git', args, {
|
|
21
|
+
cwd,
|
|
22
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
23
|
+
env: { ...process.env, ...env },
|
|
24
|
+
});
|
|
25
|
+
let stdout = '';
|
|
26
|
+
let stderr = '';
|
|
27
|
+
proc.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
28
|
+
proc.stderr.on('data', (d) => { stderr += d.toString(); });
|
|
29
|
+
proc.on('error', (err) => {
|
|
30
|
+
if (err.code === 'ENOENT')
|
|
31
|
+
reject(new Error('git 未安装'));
|
|
32
|
+
else
|
|
33
|
+
reject(err);
|
|
34
|
+
});
|
|
35
|
+
proc.on('close', (code) => {
|
|
36
|
+
if (code === 0)
|
|
37
|
+
resolve(stdout);
|
|
38
|
+
else
|
|
39
|
+
reject(new Error(stderr.trim() || `git ${args.join(' ')} failed (${code})`));
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
configureBotGit(repoPath, identity) {
|
|
44
|
+
return Promise.all([
|
|
45
|
+
this.runGit(repoPath, ['config', 'user.name', identity.login]),
|
|
46
|
+
this.runGit(repoPath, ['config', 'user.email', identity.email]),
|
|
47
|
+
]).then(() => undefined);
|
|
48
|
+
}
|
|
49
|
+
async ensureRepo(repo) {
|
|
50
|
+
if (!this.gh.isAppAuth) {
|
|
51
|
+
throw new Error('GitHub App 认证未配置,无法托管工作区');
|
|
52
|
+
}
|
|
53
|
+
const token = await this.gh.ensureInstallationTokenForRepo(repo);
|
|
54
|
+
if (!token)
|
|
55
|
+
throw new Error(`无法获取 ${repo} 的 Installation Token`);
|
|
56
|
+
const repoPath = this.getRepoPath(repo);
|
|
57
|
+
fs.mkdirSync(path.dirname(repoPath), { recursive: true });
|
|
58
|
+
const identity = await this.gh.getBotIdentity();
|
|
59
|
+
if (!identity)
|
|
60
|
+
throw new Error('无法解析 GitHub App Bot 身份');
|
|
61
|
+
const cloneUrl = this.gh.buildCloneUrl(repo, token);
|
|
62
|
+
if (!fs.existsSync(path.join(repoPath, '.git'))) {
|
|
63
|
+
await this.runGit(path.dirname(repoPath), ['clone', cloneUrl, path.basename(repoPath)]);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
await this.runGit(repoPath, ['remote', 'set-url', 'origin', cloneUrl]);
|
|
67
|
+
await this.runGit(repoPath, ['fetch', 'origin', '--prune']);
|
|
68
|
+
}
|
|
69
|
+
await this.configureBotGit(repoPath, identity);
|
|
70
|
+
return repoPath;
|
|
71
|
+
}
|
|
72
|
+
async checkoutBranch(repo, branch, baseRef) {
|
|
73
|
+
const repoPath = await this.ensureRepo(repo);
|
|
74
|
+
const localBranches = await this.runGit(repoPath, ['branch', '--list', branch]);
|
|
75
|
+
if (localBranches.trim()) {
|
|
76
|
+
await this.runGit(repoPath, ['checkout', branch]);
|
|
77
|
+
await this.runGit(repoPath, ['pull', '--rebase', 'origin', branch]).catch(async () => {
|
|
78
|
+
await this.runGit(repoPath, ['fetch', 'origin', branch]);
|
|
79
|
+
});
|
|
80
|
+
return repoPath;
|
|
81
|
+
}
|
|
82
|
+
const remoteBranch = await this.runGit(repoPath, ['ls-remote', '--heads', 'origin', branch]);
|
|
83
|
+
if (remoteBranch.trim()) {
|
|
84
|
+
await this.runGit(repoPath, ['checkout', '-B', branch, `origin/${branch}`]);
|
|
85
|
+
return repoPath;
|
|
86
|
+
}
|
|
87
|
+
await this.runGit(repoPath, ['fetch', 'origin', baseRef]);
|
|
88
|
+
await this.runGit(repoPath, ['checkout', '-B', branch, `origin/${baseRef}`]);
|
|
89
|
+
return repoPath;
|
|
90
|
+
}
|
|
91
|
+
async commitAndPush(repo, branch, message) {
|
|
92
|
+
const repoPath = this.getRepoPath(repo);
|
|
93
|
+
if (!fs.existsSync(repoPath)) {
|
|
94
|
+
throw new Error(`工作区不存在: ${repoPath},请先 github_prepare_workspace`);
|
|
95
|
+
}
|
|
96
|
+
const token = await this.gh.ensureInstallationTokenForRepo(repo);
|
|
97
|
+
if (!token)
|
|
98
|
+
throw new Error('Installation Token 不可用');
|
|
99
|
+
await this.runGit(repoPath, ['remote', 'set-url', 'origin', this.gh.buildCloneUrl(repo, token)]);
|
|
100
|
+
const status = await this.runGit(repoPath, ['status', '--porcelain']);
|
|
101
|
+
if (!status.trim())
|
|
102
|
+
return '没有可提交的变更';
|
|
103
|
+
await this.runGit(repoPath, ['add', '-A']);
|
|
104
|
+
await this.runGit(repoPath, ['commit', '-m', message]);
|
|
105
|
+
await this.runGit(repoPath, ['push', '-u', 'origin', branch]);
|
|
106
|
+
return `已 push 到 origin/${branch}`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=workspace-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-manager.js","sourceRoot":"","sources":["../../src/workspace-manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-github",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Zhin.js adapter for GitHub (gh CLI) — treat issues/PRs as chat channels, full repo management, webhook notifications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"files": [
|
|
22
22
|
"src",
|
|
23
23
|
"lib",
|
|
24
|
+
"agent",
|
|
24
25
|
"client",
|
|
25
26
|
"dist",
|
|
26
|
-
"skills",
|
|
27
27
|
"plugin.yml",
|
|
28
28
|
"README.md"
|
|
29
29
|
],
|
|
@@ -46,16 +46,26 @@
|
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"typescript": "^6.0.3",
|
|
49
|
-
"
|
|
50
|
-
"zhin.js": "
|
|
49
|
+
"zod": "^4.4.3",
|
|
50
|
+
"@zhin.js/agent": "1.0.3",
|
|
51
|
+
"@zhin.js/host-router": "2.0.3",
|
|
52
|
+
"zhin.js": "4.1.2"
|
|
51
53
|
},
|
|
52
54
|
"peerDependencies": {
|
|
53
|
-
"
|
|
54
|
-
"zhin.js": "
|
|
55
|
+
"zod": "^4.0.0",
|
|
56
|
+
"@zhin.js/host-router": "2.0.3",
|
|
57
|
+
"zhin.js": "4.1.2",
|
|
58
|
+
"@zhin.js/agent": "1.0.3"
|
|
55
59
|
},
|
|
56
60
|
"peerDependenciesMeta": {
|
|
57
61
|
"@zhin.js/host-router": {
|
|
58
62
|
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"@zhin.js/agent": {
|
|
65
|
+
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"zod": {
|
|
68
|
+
"optional": true
|
|
59
69
|
}
|
|
60
70
|
},
|
|
61
71
|
"repository": {
|
package/src/adapter.ts
CHANGED
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { formatCompact, Adapter, Message, Plugin, OUTBOUND_RICH_SEGMENT_POLICY_TEXT_ONLY } from 'zhin.js';
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
|
-
import { GitHubEndpoint } from './endpoint.js';
|
|
6
|
+
import { GitHubEndpoint, enrichGithubInboundMessage } from './endpoint.js';
|
|
7
7
|
import type { Router } from '@zhin.js/host-router';
|
|
8
|
-
import type
|
|
8
|
+
import { type GitHubEndpointConfig, type EventType, type GenericWebhookPayload, type Subscription, type IssueCommentPayload, type PRReviewCommentPayload, type PRReviewPayload } from './types.js';
|
|
9
9
|
import type { GhClient } from './gh-client.js';
|
|
10
|
-
import type { IssueCommentPayload, PRReviewCommentPayload, PRReviewPayload } from './types.js';
|
|
11
10
|
|
|
12
11
|
const VALID_EVENTS: EventType[] = ['push', 'issue', 'star', 'fork', 'unstar', 'pull_request'];
|
|
13
12
|
|
|
@@ -227,7 +226,8 @@ export class GitHubAdapter extends Adapter<GitHubEndpoint> {
|
|
|
227
226
|
|
|
228
227
|
// 处理消息类事件(Issue/PR 评论)
|
|
229
228
|
if (endpoint && event === 'issue_comment' && payload.action === 'created' && payload.comment) {
|
|
230
|
-
|
|
229
|
+
let message = endpoint.$formatMessage(payload as IssueCommentPayload);
|
|
230
|
+
message = enrichGithubInboundMessage(message, endpoint.$config, endpoint.gh, repo);
|
|
231
231
|
const botUser = endpoint.gh.authenticatedUser;
|
|
232
232
|
if (!(botUser && message.$sender.id === botUser)) {
|
|
233
233
|
this.emit('message.receive', message);
|
|
@@ -235,7 +235,8 @@ export class GitHubAdapter extends Adapter<GitHubEndpoint> {
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
if (endpoint && event === 'pull_request_review_comment' && payload.action === 'created' && payload.comment) {
|
|
238
|
-
|
|
238
|
+
let message = endpoint.formatPRReviewComment(payload as PRReviewCommentPayload);
|
|
239
|
+
message = enrichGithubInboundMessage(message, endpoint.$config, endpoint.gh, repo);
|
|
239
240
|
const botUser = endpoint.gh.authenticatedUser;
|
|
240
241
|
if (!(botUser && message.$sender.id === botUser)) {
|
|
241
242
|
this.emit('message.receive', message);
|
|
@@ -243,8 +244,10 @@ export class GitHubAdapter extends Adapter<GitHubEndpoint> {
|
|
|
243
244
|
}
|
|
244
245
|
|
|
245
246
|
if (endpoint && event === 'pull_request_review' && payload.action === 'submitted') {
|
|
246
|
-
const
|
|
247
|
-
if (
|
|
247
|
+
const formatted = endpoint.formatPRReview(payload as PRReviewPayload);
|
|
248
|
+
if (formatted) {
|
|
249
|
+
let message = formatted;
|
|
250
|
+
message = enrichGithubInboundMessage(message, endpoint.$config, endpoint.gh, repo);
|
|
248
251
|
const botUser = endpoint.gh.authenticatedUser;
|
|
249
252
|
if (!(botUser && message.$sender.id === botUser)) {
|
|
250
253
|
this.emit('message.receive', message);
|
|
@@ -371,7 +374,8 @@ export class GitHubAdapter extends Adapter<GitHubEndpoint> {
|
|
|
371
374
|
|
|
372
375
|
// 处理消息类事件(Issue/PR 评论)
|
|
373
376
|
if (endpoint && eventName === 'issue_comment' && ev.payload?.action === 'created' && ev.payload?.comment) {
|
|
374
|
-
|
|
377
|
+
let message = endpoint.$formatMessage(ev.payload as IssueCommentPayload);
|
|
378
|
+
message = enrichGithubInboundMessage(message, endpoint.$config, endpoint.gh, repo);
|
|
375
379
|
const botUser = endpoint.gh.authenticatedUser;
|
|
376
380
|
if (!(botUser && message.$sender.id === botUser)) {
|
|
377
381
|
this.emit('message.receive', message);
|