@zhin.js/adapter-github 3.0.0 → 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.
Files changed (100) hide show
  1. package/README.md +23 -12
  2. package/{skills/github/SKILL.md → agent/skills/github.md} +22 -5
  3. package/agent/tools/bind.ts +12 -0
  4. package/agent/tools/create_pr.ts +19 -0
  5. package/agent/tools/install.ts +12 -0
  6. package/agent/tools/patch_file.ts +18 -0
  7. package/agent/tools/prepare_workspace.ts +14 -0
  8. package/agent/tools/push_branch.ts +17 -0
  9. package/agent/tools/star.ts +15 -0
  10. package/agent/tools/subscribe.ts +16 -0
  11. package/agent/tools/subscriptions.ts +13 -0
  12. package/agent/tools/unbind.ts +12 -0
  13. package/agent/tools/unsubscribe.ts +15 -0
  14. package/agent/tools/whoami.ts +12 -0
  15. package/lib/agent/tools/bind.js +12 -0
  16. package/lib/agent/tools/bind.js.map +1 -0
  17. package/lib/agent/tools/create_pr.js +19 -0
  18. package/lib/agent/tools/create_pr.js.map +1 -0
  19. package/lib/agent/tools/install.js +12 -0
  20. package/lib/agent/tools/install.js.map +1 -0
  21. package/lib/agent/tools/patch_file.js +18 -0
  22. package/lib/agent/tools/patch_file.js.map +1 -0
  23. package/lib/agent/tools/prepare_workspace.js +14 -0
  24. package/lib/agent/tools/prepare_workspace.js.map +1 -0
  25. package/lib/agent/tools/push_branch.js +17 -0
  26. package/lib/agent/tools/push_branch.js.map +1 -0
  27. package/lib/agent/tools/star.js +15 -0
  28. package/lib/agent/tools/star.js.map +1 -0
  29. package/lib/agent/tools/subscribe.js +16 -0
  30. package/lib/agent/tools/subscribe.js.map +1 -0
  31. package/lib/agent/tools/subscriptions.js +13 -0
  32. package/lib/agent/tools/subscriptions.js.map +1 -0
  33. package/lib/agent/tools/unbind.js +12 -0
  34. package/lib/agent/tools/unbind.js.map +1 -0
  35. package/lib/agent/tools/unsubscribe.js +15 -0
  36. package/lib/agent/tools/unsubscribe.js.map +1 -0
  37. package/lib/agent/tools/whoami.js +12 -0
  38. package/lib/agent/tools/whoami.js.map +1 -0
  39. package/lib/{adapter.js → src/adapter.js} +12 -6
  40. package/lib/src/adapter.js.map +1 -0
  41. package/lib/{agent-prompt.js → src/agent-prompt.js} +10 -8
  42. package/lib/src/agent-prompt.js.map +1 -0
  43. package/lib/{endpoint.js → src/endpoint.js} +37 -8
  44. package/lib/src/endpoint.js.map +1 -0
  45. package/lib/{gh-client.js → src/gh-client.js} +99 -0
  46. package/lib/src/gh-client.js.map +1 -0
  47. package/lib/src/github-agent-deps.js +13 -0
  48. package/lib/src/github-agent-deps.js.map +1 -0
  49. package/lib/src/github-bot-handlers.js +78 -0
  50. package/lib/src/github-bot-handlers.js.map +1 -0
  51. package/lib/src/github-channel-context.js +32 -0
  52. package/lib/src/github-channel-context.js.map +1 -0
  53. package/lib/src/github-tool-handlers.js +215 -0
  54. package/lib/src/github-tool-handlers.js.map +1 -0
  55. package/lib/src/index.js +104 -0
  56. package/lib/src/index.js.map +1 -0
  57. package/lib/{register-github-mcp.js → src/register-github-mcp.js} +5 -0
  58. package/lib/src/register-github-mcp.js.map +1 -0
  59. package/lib/src/segment-mapper.js +2 -0
  60. package/lib/src/segment-mapper.js.map +1 -0
  61. package/lib/src/types.js.map +1 -0
  62. package/lib/src/workspace-manager.js +109 -0
  63. package/lib/src/workspace-manager.js.map +1 -0
  64. package/package.json +16 -6
  65. package/src/adapter.ts +13 -8
  66. package/src/agent-prompt.ts +11 -10
  67. package/src/endpoint.ts +48 -14
  68. package/src/gh-client.ts +131 -0
  69. package/src/github-agent-deps.ts +27 -0
  70. package/src/github-bot-handlers.ts +109 -0
  71. package/src/github-channel-context.ts +46 -0
  72. package/src/github-tool-handlers.ts +244 -0
  73. package/src/index.ts +32 -326
  74. package/src/register-github-mcp.ts +5 -0
  75. package/src/segment-mapper.ts +1 -0
  76. package/src/types.ts +6 -0
  77. package/src/workspace-manager.ts +114 -0
  78. package/lib/adapter.d.ts +0 -65
  79. package/lib/adapter.d.ts.map +0 -1
  80. package/lib/adapter.js.map +0 -1
  81. package/lib/agent-prompt.d.ts +0 -3
  82. package/lib/agent-prompt.d.ts.map +0 -1
  83. package/lib/agent-prompt.js.map +0 -1
  84. package/lib/endpoint.d.ts +0 -26
  85. package/lib/endpoint.d.ts.map +0 -1
  86. package/lib/endpoint.js.map +0 -1
  87. package/lib/gh-client.d.ts +0 -228
  88. package/lib/gh-client.d.ts.map +0 -1
  89. package/lib/gh-client.js.map +0 -1
  90. package/lib/index.d.ts +0 -34
  91. package/lib/index.d.ts.map +0 -1
  92. package/lib/index.js +0 -388
  93. package/lib/index.js.map +0 -1
  94. package/lib/register-github-mcp.d.ts +0 -7
  95. package/lib/register-github-mcp.d.ts.map +0 -1
  96. package/lib/register-github-mcp.js.map +0 -1
  97. package/lib/types.d.ts +0 -144
  98. package/lib/types.d.ts.map +0 -1
  99. package/lib/types.js.map +0 -1
  100. /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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"}
@@ -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,2 @@
1
+ export { toCanonicalSegments, fromCanonicalSegments } from 'zhin.js';
2
+ //# sourceMappingURL=segment-mapper.js.map
@@ -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.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
- "@zhin.js/host-router": "2.0.1",
50
- "zhin.js": "4.1.0"
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
- "@zhin.js/host-router": "2.0.1",
54
- "zhin.js": "4.1.0"
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 { GitHubEndpointConfig, EventType, GenericWebhookPayload, Subscription } from './types.js';
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
 
@@ -72,6 +71,7 @@ function formatNotification(event: string, p: GenericWebhookPayload): string {
72
71
  export class GitHubAdapter extends Adapter<GitHubEndpoint> {
73
72
  static override readonly capabilities = ['inbound', 'outbound'] as const;
74
73
  static override outboundRichSegmentPolicy = OUTBOUND_RICH_SEGMENT_POLICY_TEXT_ONLY;
74
+ static override interactivePolicy = 'text' as const;
75
75
 
76
76
  /** 轮询定时器 */
77
77
  private _pollTimer: ReturnType<typeof setInterval> | null = null;
@@ -226,7 +226,8 @@ export class GitHubAdapter extends Adapter<GitHubEndpoint> {
226
226
 
227
227
  // 处理消息类事件(Issue/PR 评论)
228
228
  if (endpoint && event === 'issue_comment' && payload.action === 'created' && payload.comment) {
229
- const message = endpoint.$formatMessage(payload as IssueCommentPayload);
229
+ let message = endpoint.$formatMessage(payload as IssueCommentPayload);
230
+ message = enrichGithubInboundMessage(message, endpoint.$config, endpoint.gh, repo);
230
231
  const botUser = endpoint.gh.authenticatedUser;
231
232
  if (!(botUser && message.$sender.id === botUser)) {
232
233
  this.emit('message.receive', message);
@@ -234,7 +235,8 @@ export class GitHubAdapter extends Adapter<GitHubEndpoint> {
234
235
  }
235
236
 
236
237
  if (endpoint && event === 'pull_request_review_comment' && payload.action === 'created' && payload.comment) {
237
- const message = endpoint.formatPRReviewComment(payload as PRReviewCommentPayload);
238
+ let message = endpoint.formatPRReviewComment(payload as PRReviewCommentPayload);
239
+ message = enrichGithubInboundMessage(message, endpoint.$config, endpoint.gh, repo);
238
240
  const botUser = endpoint.gh.authenticatedUser;
239
241
  if (!(botUser && message.$sender.id === botUser)) {
240
242
  this.emit('message.receive', message);
@@ -242,8 +244,10 @@ export class GitHubAdapter extends Adapter<GitHubEndpoint> {
242
244
  }
243
245
 
244
246
  if (endpoint && event === 'pull_request_review' && payload.action === 'submitted') {
245
- const message = endpoint.formatPRReview(payload as PRReviewPayload);
246
- if (message) {
247
+ const formatted = endpoint.formatPRReview(payload as PRReviewPayload);
248
+ if (formatted) {
249
+ let message = formatted;
250
+ message = enrichGithubInboundMessage(message, endpoint.$config, endpoint.gh, repo);
247
251
  const botUser = endpoint.gh.authenticatedUser;
248
252
  if (!(botUser && message.$sender.id === botUser)) {
249
253
  this.emit('message.receive', message);
@@ -370,7 +374,8 @@ export class GitHubAdapter extends Adapter<GitHubEndpoint> {
370
374
 
371
375
  // 处理消息类事件(Issue/PR 评论)
372
376
  if (endpoint && eventName === 'issue_comment' && ev.payload?.action === 'created' && ev.payload?.comment) {
373
- const message = endpoint.$formatMessage(ev.payload as IssueCommentPayload);
377
+ let message = endpoint.$formatMessage(ev.payload as IssueCommentPayload);
378
+ message = enrichGithubInboundMessage(message, endpoint.$config, endpoint.gh, repo);
374
379
  const botUser = endpoint.gh.authenticatedUser;
375
380
  if (!(botUser && message.$sender.id === botUser)) {
376
381
  this.emit('message.receive', message);