@zhin.js/adapter-github 1.0.1 → 1.1.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 (113) hide show
  1. package/CHANGELOG.md +1212 -0
  2. package/README.md +73 -195
  3. package/adapters/github/index.js +51 -0
  4. package/adapters/github/index.ts +59 -0
  5. package/agents/github/agent.json +20 -0
  6. package/agents/github/boundaries.md +3 -0
  7. package/agents/github/conventions.md +3 -0
  8. package/agents/github/skills/github-account/SKILL.md +20 -0
  9. package/agents/github/skills/github-account/handlers.js +116 -0
  10. package/agents/github/skills/github-account/handlers.ts +136 -0
  11. package/agents/github/skills/github-account/tools/bind/index.js +13 -0
  12. package/agents/github/skills/github-account/tools/bind/index.ts +13 -0
  13. package/agents/github/skills/github-account/tools/install/index.js +13 -0
  14. package/agents/github/skills/github-account/tools/install/index.ts +13 -0
  15. package/agents/github/skills/github-account/tools/unbind/index.js +13 -0
  16. package/agents/github/skills/github-account/tools/unbind/index.ts +13 -0
  17. package/agents/github/skills/github-account/tools/whoami/index.js +13 -0
  18. package/agents/github/skills/github-account/tools/whoami/index.ts +13 -0
  19. package/agents/github/skills/github-cli/SKILL.md +47 -0
  20. package/agents/github/skills/github-repository/SKILL.md +21 -0
  21. package/agents/github/skills/github-repository/handlers.js +77 -0
  22. package/agents/github/skills/github-repository/handlers.ts +113 -0
  23. package/agents/github/skills/github-repository/tools/create_pr/index.js +20 -0
  24. package/agents/github/skills/github-repository/tools/create_pr/index.ts +20 -0
  25. package/agents/github/skills/github-repository/tools/patch_file/index.js +19 -0
  26. package/agents/github/skills/github-repository/tools/patch_file/index.ts +19 -0
  27. package/agents/github/skills/github-repository/tools/prepare_workspace/index.js +15 -0
  28. package/agents/github/skills/github-repository/tools/prepare_workspace/index.ts +15 -0
  29. package/agents/github/skills/github-repository/tools/push_branch/index.js +18 -0
  30. package/agents/github/skills/github-repository/tools/push_branch/index.ts +18 -0
  31. package/agents/github/skills/github-subscriptions/SKILL.md +20 -0
  32. package/agents/github/skills/github-subscriptions/handlers.js +101 -0
  33. package/agents/github/skills/github-subscriptions/handlers.ts +119 -0
  34. package/agents/github/skills/github-subscriptions/tools/star/index.js +16 -0
  35. package/agents/github/skills/github-subscriptions/tools/star/index.ts +16 -0
  36. package/agents/github/skills/github-subscriptions/tools/subscribe/index.js +16 -0
  37. package/agents/github/skills/github-subscriptions/tools/subscribe/index.ts +16 -0
  38. package/agents/github/skills/github-subscriptions/tools/subscriptions/index.js +13 -0
  39. package/agents/github/skills/github-subscriptions/tools/subscriptions/index.ts +13 -0
  40. package/agents/github/skills/github-subscriptions/tools/unsubscribe/index.js +15 -0
  41. package/agents/github/skills/github-subscriptions/tools/unsubscribe/index.ts +15 -0
  42. package/agents/github/system.md +3 -0
  43. package/commands/github/endpoint/add/[id]/index.js +3 -0
  44. package/commands/github/endpoint/add/[id]/index.ts +3 -0
  45. package/commands/github/endpoint/definition.js +23 -0
  46. package/commands/github/endpoint/definition.ts +23 -0
  47. package/commands/github/endpoint/list/index.js +3 -0
  48. package/commands/github/endpoint/list/index.ts +3 -0
  49. package/commands/github/endpoint/remove/[id]/index.js +3 -0
  50. package/commands/github/endpoint/remove/[id]/index.ts +3 -0
  51. package/lib/client.d.ts +36 -0
  52. package/lib/client.js +44 -0
  53. package/lib/endpoint.d.ts +32 -22
  54. package/lib/endpoint.js +125 -145
  55. package/lib/gh-client.d.ts +73 -1
  56. package/lib/gh-client.js +99 -1
  57. package/lib/github-channel-context.d.ts +16 -0
  58. package/lib/github-channel-context.js +31 -0
  59. package/lib/github-runtime-state.d.ts +1 -0
  60. package/lib/github-runtime-state.js +6 -0
  61. package/lib/index.d.ts +7 -32
  62. package/lib/index.js +7 -385
  63. package/lib/oauth-users.d.ts +33 -0
  64. package/lib/oauth-users.js +38 -0
  65. package/lib/protocol.d.ts +72 -0
  66. package/lib/protocol.js +281 -0
  67. package/lib/types.d.ts +0 -18
  68. package/lib/types.js +2 -4
  69. package/lib/webhook.d.ts +14 -0
  70. package/lib/webhook.js +88 -0
  71. package/lib/workspace-manager.d.ts +21 -0
  72. package/lib/workspace-manager.js +154 -0
  73. package/package.json +93 -23
  74. package/plugin.js +38 -0
  75. package/prompt-sections/platform/index.js +16 -0
  76. package/prompt-sections/platform/index.ts +16 -0
  77. package/schema.json +137 -0
  78. package/src/client.ts +62 -0
  79. package/src/endpoint.ts +145 -150
  80. package/src/gh-client.ts +131 -0
  81. package/src/github-channel-context.ts +46 -0
  82. package/src/github-runtime-state.ts +7 -0
  83. package/src/index.ts +48 -431
  84. package/src/oauth-users.ts +47 -0
  85. package/src/protocol.ts +372 -0
  86. package/src/types.ts +0 -22
  87. package/src/webhook.ts +130 -0
  88. package/src/workspace-manager.ts +168 -0
  89. package/lib/adapter.d.ts +0 -64
  90. package/lib/adapter.d.ts.map +0 -1
  91. package/lib/adapter.js +0 -416
  92. package/lib/adapter.js.map +0 -1
  93. package/lib/agent-prompt.d.ts +0 -3
  94. package/lib/agent-prompt.d.ts.map +0 -1
  95. package/lib/agent-prompt.js +0 -82
  96. package/lib/agent-prompt.js.map +0 -1
  97. package/lib/endpoint.d.ts.map +0 -1
  98. package/lib/endpoint.js.map +0 -1
  99. package/lib/gh-client.d.ts.map +0 -1
  100. package/lib/gh-client.js.map +0 -1
  101. package/lib/index.d.ts.map +0 -1
  102. package/lib/index.js.map +0 -1
  103. package/lib/register-github-mcp.d.ts +0 -6
  104. package/lib/register-github-mcp.d.ts.map +0 -1
  105. package/lib/register-github-mcp.js +0 -35
  106. package/lib/register-github-mcp.js.map +0 -1
  107. package/lib/types.d.ts.map +0 -1
  108. package/lib/types.js.map +0 -1
  109. package/plugin.yml +0 -3
  110. package/skills/github/SKILL.md +0 -266
  111. package/src/adapter.ts +0 -448
  112. package/src/agent-prompt.ts +0 -99
  113. package/src/register-github-mcp.ts +0 -60
@@ -0,0 +1,18 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { executeGithubPushBranch } from '../../handlers.js';
4
+
5
+ export default defineAgentTool<{ repo?: string; branch?: string; message: string }>({
6
+ description: '在托管工作区 git commit 并 push 到远程分支(需 HITL 确认;Bot 身份)',
7
+ adapter: 'github',
8
+ inputSchema: z.object({
9
+ repo: z.string().optional().describe('owner/repo'),
10
+ branch: z.string().optional().describe('分支名,缺省从上下文推断'),
11
+ message: z.string().describe('commit message'),
12
+ }),
13
+ tags: ['github'],
14
+ requiresApproval: 'always',
15
+ async execute(input, context) {
16
+ return executeGithubPushBranch(input, context.$client);
17
+ },
18
+ });
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: github-subscriptions
3
+ platforms:
4
+ - github
5
+ description: GitHub Star 与仓库订阅管理能力。
6
+ keywords:
7
+ - "github"
8
+ - "star"
9
+ - "订阅"
10
+ - "通知"
11
+ tools:
12
+ - "star"
13
+ - "subscribe"
14
+ - "subscriptions"
15
+ - "unsubscribe"
16
+ ---
17
+
18
+ # github-subscriptions
19
+
20
+ 先用 `subscriptions` 查询当前聊天通道的已有订阅,再执行订阅或取消。Webhook 订阅绑定当前聊天通道,只会向该通道投递事件。`star` 优先使用用户绑定的 OAuth 身份,未绑定时才使用 Endpoint 默认身份;外部写操作遵守审批策略。
@@ -0,0 +1,101 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { getCurrentCommMessage } from '@zhin.js/agent/security';
3
+ function subscriptionsModel(client) {
4
+ const db = client.database;
5
+ return db?.models?.get('github_subscriptions');
6
+ }
7
+ export async function executeGithubStar(args, client, commMessage) {
8
+ const msg = commMessage ?? getCurrentCommMessage();
9
+ const gh = await client.getUserOrDefaultApi(msg?.$adapter, msg?.$sender.id);
10
+ switch (args.action) {
11
+ case 'star': {
12
+ const r = await gh.starRepo(args.repo);
13
+ return r.ok ? `⭐ 已 Star ${args.repo}` : `❌ ${r.data?.message || JSON.stringify(r.data)}`;
14
+ }
15
+ case 'unstar': {
16
+ const r = await gh.unstarRepo(args.repo);
17
+ return r.ok ? `💔 已取消 Star ${args.repo}` : `❌ ${r.data?.message || JSON.stringify(r.data)}`;
18
+ }
19
+ case 'check': {
20
+ const starred = await gh.isStarred(args.repo);
21
+ return starred ? `⭐ 已 Star ${args.repo}` : `☆ 尚未 Star ${args.repo}`;
22
+ }
23
+ default:
24
+ return `❌ 未知操作: ${args.action}`;
25
+ }
26
+ }
27
+ export async function executeGithubSubscribe(args, client, commMessage) {
28
+ const msg = commMessage ?? getCurrentCommMessage();
29
+ if (!msg?.$adapter || !msg?.$sender.id || !msg?.$channel?.id || !msg?.$endpoint) {
30
+ return '❌ 无法获取当前聊天通道信息';
31
+ }
32
+ const model = subscriptionsModel(client);
33
+ if (!model)
34
+ return '❌ 数据库未就绪';
35
+ const validEvents = ['push', 'issue', 'star', 'fork', 'unstar', 'pull_request'];
36
+ const events = args.events
37
+ ? args.events.split(',').map((s) => s.trim()).filter((e) => validEvents.includes(e))
38
+ : validEvents;
39
+ if (!events.length)
40
+ return `❌ 无效的事件类型,可选: ${validEvents.join(', ')}`;
41
+ const [existing] = await model.select().where({
42
+ repo: args.repo,
43
+ target_id: msg.$channel?.id,
44
+ adapter: msg.$adapter,
45
+ endpoint: msg.$endpoint,
46
+ });
47
+ if (existing) {
48
+ await model.update({ events, target_type: msg.$channel?.type || 'private' }).where({ id: existing.id });
49
+ return `✅ 已更新订阅 ${args.repo}\n📡 事件: ${events.join(', ')}`;
50
+ }
51
+ await model.insert({
52
+ id: Date.now(),
53
+ repo: args.repo,
54
+ events,
55
+ target_id: msg.$channel?.id,
56
+ target_type: msg.$channel?.type || 'private',
57
+ adapter: msg.$adapter,
58
+ endpoint: msg.$endpoint,
59
+ });
60
+ return `✅ 已订阅 ${args.repo}\n📡 事件: ${events.join(', ')}\n📌 通知将推送到当前通道`;
61
+ }
62
+ export async function executeGithubUnsubscribe(args, client, commMessage) {
63
+ const msg = commMessage ?? getCurrentCommMessage();
64
+ if (!msg?.$adapter || !msg?.$channel?.id || !msg?.$endpoint) {
65
+ return '❌ 无法获取当前聊天通道信息';
66
+ }
67
+ const model = subscriptionsModel(client);
68
+ if (!model)
69
+ return '❌ 数据库未就绪';
70
+ const [existing] = await model.select().where({
71
+ repo: args.repo,
72
+ target_id: msg.$channel?.id,
73
+ adapter: msg.$adapter,
74
+ endpoint: msg.$endpoint,
75
+ });
76
+ if (!existing)
77
+ return `📭 当前通道未订阅 ${args.repo}`;
78
+ await model.delete().where({ id: existing.id });
79
+ return `✅ 已取消订阅 ${args.repo}`;
80
+ }
81
+ export async function executeGithubSubscriptions(_args, client, commMessage) {
82
+ const msg = commMessage ?? getCurrentCommMessage();
83
+ if (!msg?.$adapter || !msg?.$channel?.id || !msg?.$endpoint) {
84
+ return '❌ 无法获取当前聊天通道信息';
85
+ }
86
+ const model = subscriptionsModel(client);
87
+ if (!model)
88
+ return '❌ 数据库未就绪';
89
+ const subs = await model.select().where({
90
+ target_id: msg.$channel?.id,
91
+ adapter: msg.$adapter,
92
+ endpoint: msg.$endpoint,
93
+ });
94
+ if (!subs?.length)
95
+ return '📭 当前通道没有任何 GitHub 订阅';
96
+ return `📋 当前通道订阅 (${subs.length}):\n\n` +
97
+ subs.map((s) => {
98
+ const events = Array.isArray(s.events) ? s.events : [];
99
+ return ` 📦 ${s.repo}\n 📡 ${events.join(', ') || '(无事件)'}`;
100
+ }).join('\n\n');
101
+ }
@@ -0,0 +1,119 @@
1
+ import type { Message } from 'zhin.js';
2
+ import { getCurrentCommMessage } from '@zhin.js/agent/security';
3
+ import type { GithubClient } from '../../../../src/client.js';
4
+ import type { EventType } from '../../../../src/types.js';
5
+
6
+ function subscriptionsModel(client: GithubClient) {
7
+ const db = client.database as {
8
+ models?: Map<string, unknown>;
9
+ } | null | undefined;
10
+ return db?.models?.get('github_subscriptions') as {
11
+ select: () => { where: (q: object) => Promise<any[]> };
12
+ insert: (row: object) => Promise<void>;
13
+ update: (row: object) => { where: (q: object) => Promise<void> };
14
+ delete: () => { where: (q: object) => Promise<void> };
15
+ } | undefined;
16
+ }
17
+
18
+ export async function executeGithubStar(args: { action: 'star' | 'unstar' | 'check'; repo: string }, client: GithubClient, commMessage?: Message) {
19
+ const msg = commMessage ?? getCurrentCommMessage();
20
+ const gh = await client.getUserOrDefaultApi(msg?.$adapter, msg?.$sender.id);
21
+ switch (args.action) {
22
+ case 'star': {
23
+ const r = await gh.starRepo(args.repo);
24
+ return r.ok ? `⭐ 已 Star ${args.repo}` : `❌ ${r.data?.message || JSON.stringify(r.data)}`;
25
+ }
26
+ case 'unstar': {
27
+ const r = await gh.unstarRepo(args.repo);
28
+ return r.ok ? `💔 已取消 Star ${args.repo}` : `❌ ${r.data?.message || JSON.stringify(r.data)}`;
29
+ }
30
+ case 'check': {
31
+ const starred = await gh.isStarred(args.repo);
32
+ return starred ? `⭐ 已 Star ${args.repo}` : `☆ 尚未 Star ${args.repo}`;
33
+ }
34
+ default:
35
+ return `❌ 未知操作: ${args.action}`;
36
+ }
37
+ }
38
+
39
+ export async function executeGithubSubscribe(args: { repo: string; events?: string }, client: GithubClient, commMessage?: Message) {
40
+ const msg = commMessage ?? getCurrentCommMessage();
41
+ if (!msg?.$adapter || !msg?.$sender.id || !msg?.$channel?.id || !msg?.$endpoint) {
42
+ return '❌ 无法获取当前聊天通道信息';
43
+ }
44
+
45
+ const model = subscriptionsModel(client);
46
+ if (!model) return '❌ 数据库未就绪';
47
+
48
+ const validEvents: EventType[] = ['push', 'issue', 'star', 'fork', 'unstar', 'pull_request'];
49
+ const events: EventType[] = args.events
50
+ ? args.events.split(',').map((s) => s.trim()).filter((e): e is EventType => validEvents.includes(e as EventType))
51
+ : validEvents;
52
+ if (!events.length) return `❌ 无效的事件类型,可选: ${validEvents.join(', ')}`;
53
+
54
+ const [existing] = await model.select().where({
55
+ repo: args.repo,
56
+ target_id: msg.$channel?.id,
57
+ adapter: msg.$adapter,
58
+ endpoint: msg.$endpoint,
59
+ });
60
+ if (existing) {
61
+ await model.update({ events, target_type: msg.$channel?.type || 'private' }).where({ id: existing.id });
62
+ return `✅ 已更新订阅 ${args.repo}\n📡 事件: ${events.join(', ')}`;
63
+ }
64
+
65
+ await model.insert({
66
+ id: Date.now(),
67
+ repo: args.repo,
68
+ events,
69
+ target_id: msg.$channel?.id,
70
+ target_type: msg.$channel?.type || 'private',
71
+ adapter: msg.$adapter,
72
+ endpoint: msg.$endpoint,
73
+ });
74
+ return `✅ 已订阅 ${args.repo}\n📡 事件: ${events.join(', ')}\n📌 通知将推送到当前通道`;
75
+ }
76
+
77
+ export async function executeGithubUnsubscribe(args: { repo: string }, client: GithubClient, commMessage?: Message) {
78
+ const msg = commMessage ?? getCurrentCommMessage();
79
+ if (!msg?.$adapter || !msg?.$channel?.id || !msg?.$endpoint) {
80
+ return '❌ 无法获取当前聊天通道信息';
81
+ }
82
+
83
+ const model = subscriptionsModel(client);
84
+ if (!model) return '❌ 数据库未就绪';
85
+
86
+ const [existing] = await model.select().where({
87
+ repo: args.repo,
88
+ target_id: msg.$channel?.id,
89
+ adapter: msg.$adapter,
90
+ endpoint: msg.$endpoint,
91
+ });
92
+ if (!existing) return `📭 当前通道未订阅 ${args.repo}`;
93
+
94
+ await model.delete().where({ id: existing.id });
95
+ return `✅ 已取消订阅 ${args.repo}`;
96
+ }
97
+
98
+ export async function executeGithubSubscriptions(_args: Record<string, never>, client: GithubClient, commMessage?: Message) {
99
+ const msg = commMessage ?? getCurrentCommMessage();
100
+ if (!msg?.$adapter || !msg?.$channel?.id || !msg?.$endpoint) {
101
+ return '❌ 无法获取当前聊天通道信息';
102
+ }
103
+
104
+ const model = subscriptionsModel(client);
105
+ if (!model) return '❌ 数据库未就绪';
106
+
107
+ const subs = await model.select().where({
108
+ target_id: msg.$channel?.id,
109
+ adapter: msg.$adapter,
110
+ endpoint: msg.$endpoint,
111
+ });
112
+ if (!subs?.length) return '📭 当前通道没有任何 GitHub 订阅';
113
+
114
+ return `📋 当前通道订阅 (${subs.length}):\n\n` +
115
+ subs.map((s: any) => {
116
+ const events = Array.isArray(s.events) ? s.events : [];
117
+ return ` 📦 ${s.repo}\n 📡 ${events.join(', ') || '(无事件)'}`;
118
+ }).join('\n\n');
119
+ }
@@ -0,0 +1,16 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { executeGithubStar } from '../../handlers.js';
5
+ export default defineAgentTool({
6
+ description: 'Star 或取消 Star 一个 GitHub 仓库(使用你绑定的 GitHub 账号,未绑定则用 Endpoint 默认账号)',
7
+ adapter: 'github',
8
+ inputSchema: z.object({
9
+ action: z.enum(['star', 'unstar', 'check']),
10
+ repo: z.string().min(1),
11
+ }),
12
+ tags: ['github'],
13
+ async execute(input, context) {
14
+ return executeGithubStar(input, context.$client);
15
+ },
16
+ });
@@ -0,0 +1,16 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { executeGithubStar } from '../../handlers.js';
4
+
5
+ export default defineAgentTool<{ action: 'star' | 'unstar' | 'check'; repo: string }>({
6
+ description: 'Star 或取消 Star 一个 GitHub 仓库(使用你绑定的 GitHub 账号,未绑定则用 Endpoint 默认账号)',
7
+ adapter: 'github',
8
+ inputSchema: z.object({
9
+ action: z.enum(['star', 'unstar', 'check']),
10
+ repo: z.string().min(1),
11
+ }),
12
+ tags: ['github'],
13
+ async execute(input, context) {
14
+ return executeGithubStar(input, context.$client);
15
+ },
16
+ });
@@ -0,0 +1,16 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { executeGithubSubscribe } from '../../handlers.js';
5
+ export default defineAgentTool({
6
+ description: '订阅 GitHub 仓库的 Webhook 事件,事件将推送到当前聊天通道',
7
+ inputSchema: z.object({
8
+ repo: z.string().min(1),
9
+ events: z.string().optional(),
10
+ }),
11
+ adapter: 'github',
12
+ tags: ['github'],
13
+ async execute(input, context) {
14
+ return executeGithubSubscribe(input, context.$client);
15
+ },
16
+ });
@@ -0,0 +1,16 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { executeGithubSubscribe } from '../../handlers.js';
4
+
5
+ export default defineAgentTool<{ repo: string; events?: string }>({
6
+ description: '订阅 GitHub 仓库的 Webhook 事件,事件将推送到当前聊天通道',
7
+ inputSchema: z.object({
8
+ repo: z.string().min(1),
9
+ events: z.string().optional(),
10
+ }),
11
+ adapter: 'github',
12
+ tags: ['github'],
13
+ async execute(input, context) {
14
+ return executeGithubSubscribe(input, context.$client);
15
+ },
16
+ });
@@ -0,0 +1,13 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { executeGithubSubscriptions } from '../../handlers.js';
5
+ export default defineAgentTool({
6
+ description: '查看当前聊天通道的 GitHub 仓库订阅列表',
7
+ inputSchema: z.object({}),
8
+ adapter: 'github',
9
+ tags: ['github'],
10
+ async execute(input, context) {
11
+ return executeGithubSubscriptions({}, context.$client);
12
+ },
13
+ });
@@ -0,0 +1,13 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { executeGithubSubscriptions } from '../../handlers.js';
4
+
5
+ export default defineAgentTool<{}>({
6
+ description: '查看当前聊天通道的 GitHub 仓库订阅列表',
7
+ inputSchema: z.object({}),
8
+ adapter: 'github',
9
+ tags: ['github'],
10
+ async execute(input, context) {
11
+ return executeGithubSubscriptions({}, context.$client);
12
+ },
13
+ });
@@ -0,0 +1,15 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { executeGithubUnsubscribe } from '../../handlers.js';
5
+ export default defineAgentTool({
6
+ description: '取消订阅 GitHub 仓库的 Webhook 事件',
7
+ inputSchema: z.object({
8
+ repo: z.string().min(1),
9
+ }),
10
+ adapter: 'github',
11
+ tags: ['github'],
12
+ async execute(input, context) {
13
+ return executeGithubUnsubscribe(input, context.$client);
14
+ },
15
+ });
@@ -0,0 +1,15 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { executeGithubUnsubscribe } from '../../handlers.js';
4
+
5
+ export default defineAgentTool<{ repo: string }>({
6
+ description: '取消订阅 GitHub 仓库的 Webhook 事件',
7
+ inputSchema: z.object({
8
+ repo: z.string().min(1),
9
+ }),
10
+ adapter: 'github',
11
+ tags: ['github'],
12
+ async execute(input, context) {
13
+ return executeGithubUnsubscribe(input, context.$client);
14
+ },
15
+ });
@@ -0,0 +1,3 @@
1
+ # GITHUB Platform Agent
2
+
3
+ You are the github platform specialist. Interpret requests in the current github conversation and load only the narrowest private Skill needed for the task.
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { githubEndpointCommands } from '../../definition.js';
3
+ export default githubEndpointCommands.add;
@@ -0,0 +1,3 @@
1
+ import { githubEndpointCommands } from '../../definition.js';
2
+
3
+ export default githubEndpointCommands.add;
@@ -0,0 +1,23 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ /**
3
+ * `github endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
4
+ * commands/github/endpoint/ 下的 list / add / remove 直接默认导出这三项。
5
+ *
6
+ * 字段说明:private_key 内容长且含换行,不适合 kv 直传——运行时(gh-client
7
+ * resolvePrivateKey)本就支持 PEM 内容或文件路径,故 add 采用**内联路径**形式:
8
+ * `github endpoint add mybot app_id=123456 private_key=./data/mybot.pem`。
9
+ */
10
+ import { createEndpointCommands } from 'zhin.js/adapter';
11
+ import { defineCommand } from 'zhin.js/command';
12
+ import { githubRuntimeStateToken } from "../../../lib/github-runtime-state.js";
13
+ export const githubEndpointCommands = createEndpointCommands({
14
+ adapterKey: 'github',
15
+ adapterDisplayName: 'GitHub',
16
+ fields: [
17
+ { key: 'app_id', required: true, env: true, description: 'GitHub App ID' },
18
+ { key: 'private_key', required: true, description: 'PEM 文件路径(推荐,如 ./data/xxx.pem)或 PEM 内容' },
19
+ { key: 'webhook_secret', env: true, description: 'webhook 签名密钥(不配则 API-only)' },
20
+ ],
21
+ running: (use) => use(githubRuntimeStateToken).endpoints.values(),
22
+ describeEntry: (entry) => `app_id: ${String(entry.app_id)}`,
23
+ }, defineCommand);
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `github endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
3
+ * commands/github/endpoint/ 下的 list / add / remove 直接默认导出这三项。
4
+ *
5
+ * 字段说明:private_key 内容长且含换行,不适合 kv 直传——运行时(gh-client
6
+ * resolvePrivateKey)本就支持 PEM 内容或文件路径,故 add 采用**内联路径**形式:
7
+ * `github endpoint add mybot app_id=123456 private_key=./data/mybot.pem`。
8
+ */
9
+ import { createEndpointCommands } from 'zhin.js/adapter';
10
+ import { defineCommand } from 'zhin.js/command';
11
+ import { githubRuntimeStateToken } from '../../../src/github-runtime-state.js';
12
+
13
+ export const githubEndpointCommands = createEndpointCommands({
14
+ adapterKey: 'github',
15
+ adapterDisplayName: 'GitHub',
16
+ fields: [
17
+ { key: 'app_id', required: true, env: true, description: 'GitHub App ID' },
18
+ { key: 'private_key', required: true, description: 'PEM 文件路径(推荐,如 ./data/xxx.pem)或 PEM 内容' },
19
+ { key: 'webhook_secret', env: true, description: 'webhook 签名密钥(不配则 API-only)' },
20
+ ],
21
+ running: (use) => use(githubRuntimeStateToken).endpoints.values(),
22
+ describeEntry: (entry) => `app_id: ${String(entry.app_id)}`,
23
+ }, defineCommand);
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { githubEndpointCommands } from '../definition.js';
3
+ export default githubEndpointCommands.list;
@@ -0,0 +1,3 @@
1
+ import { githubEndpointCommands } from '../definition.js';
2
+
3
+ export default githubEndpointCommands.list;
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { githubEndpointCommands } from '../../definition.js';
3
+ export default githubEndpointCommands.remove;
@@ -0,0 +1,3 @@
1
+ import { githubEndpointCommands } from '../../definition.js';
2
+
3
+ export default githubEndpointCommands.remove;
@@ -0,0 +1,36 @@
1
+ import type { PluginDatabaseHost } from 'zhin.js';
2
+ import { GhClient } from './gh-client.js';
3
+ import type { ResolvedGithubConfig } from './protocol.js';
4
+ import { WorkspaceManager } from './workspace-manager.js';
5
+ /** GitHub SDK surface exposed to plugin handlers and Agent tools. */
6
+ export declare class GithubClient {
7
+ #private;
8
+ readonly name: string;
9
+ readonly api: GhClient;
10
+ readonly config: ResolvedGithubConfig;
11
+ readonly database?: PluginDatabaseHost | undefined;
12
+ constructor(name: string, api: GhClient, config: ResolvedGithubConfig, database?: PluginDatabaseHost | undefined);
13
+ getUserOrDefaultApi(platform?: string, platformUid?: string): Promise<GhClient>;
14
+ get clientId(): string | null;
15
+ get host(): string | undefined;
16
+ get appSlug(): string | null;
17
+ get installations(): {
18
+ id: number;
19
+ account: {
20
+ login: string;
21
+ type: string;
22
+ };
23
+ target_type: string;
24
+ }[];
25
+ get workspaceManager(): WorkspaceManager;
26
+ }
27
+ export type GithubClientEventMap = Record<string, unknown>;
28
+ declare module '@zhin.js/feature-kit' {
29
+ interface AdapterClientRegistry {
30
+ readonly github: {
31
+ readonly client: GithubClient;
32
+ readonly events: GithubClientEventMap;
33
+ };
34
+ }
35
+ }
36
+ export declare const githubClient: import("@zhin.js/adapter").EndpointClientToken<GithubClient, GithubClientEventMap>;
package/lib/client.js ADDED
@@ -0,0 +1,44 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ import { lookupGithubOauthAccessToken } from './oauth-users.js';
3
+ import { WorkspaceManager } from './workspace-manager.js';
4
+ /** GitHub SDK surface exposed to plugin handlers and Agent tools. */
5
+ export class GithubClient {
6
+ name;
7
+ api;
8
+ config;
9
+ database;
10
+ #workspaceManager;
11
+ constructor(name, api, config, database) {
12
+ this.name = name;
13
+ this.api = api;
14
+ this.config = config;
15
+ this.database = database;
16
+ }
17
+ async getUserOrDefaultApi(platform, platformUid) {
18
+ if (platform && platformUid) {
19
+ const token = await lookupGithubOauthAccessToken(this.database, platform, platformUid);
20
+ if (token)
21
+ return this.api.withToken(token);
22
+ }
23
+ return this.api;
24
+ }
25
+ get clientId() {
26
+ return this.api.clientId || null;
27
+ }
28
+ get host() {
29
+ return this.config.host;
30
+ }
31
+ get appSlug() {
32
+ return this.api.appSlug || null;
33
+ }
34
+ get installations() {
35
+ return this.api.installations || [];
36
+ }
37
+ get workspaceManager() {
38
+ if (!this.#workspaceManager) {
39
+ this.#workspaceManager = new WorkspaceManager(this.api, this.config.workspaceRoot);
40
+ }
41
+ return this.#workspaceManager;
42
+ }
43
+ }
44
+ export const githubClient = defineEndpointClient('github');
package/lib/endpoint.d.ts CHANGED
@@ -1,26 +1,36 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
1
2
  /**
2
- * GitHub Endpoint 实现(基于 gh CLI)
3
+ * GithubEndpoint — lifecycle, outbound send, inbound admit.
3
4
  */
4
- import { Endpoint, Message, SendContent, SendOptions, type MessageSegment } from 'zhin.js';
5
- import type { GitHubEndpointConfig, IssueCommentPayload, PRReviewCommentPayload, PRReviewPayload } from './types.js';
6
- import type { GitHubAdapter } from './adapter.js';
5
+ import { type EndpointSendRequest } from 'zhin.js/adapter';
6
+ import type { HttpHost } from '@zhin.js/host-http';
7
+ import type { CapabilityId, PluginDatabaseHost } from 'zhin.js';
7
8
  import { GhClient } from './gh-client.js';
8
- export declare function parseMarkdown(md: string): MessageSegment[];
9
- export declare function toMarkdown(content: SendContent): string;
10
- export declare class GitHubEndpoint implements Endpoint<GitHubEndpointConfig, IssueCommentPayload> {
11
- adapter: GitHubAdapter;
12
- $config: GitHubEndpointConfig;
13
- $connected: boolean;
14
- gh: GhClient;
15
- get $id(): string;
16
- get logger(): import("zhin.js").Logger;
17
- constructor(adapter: GitHubAdapter, $config: GitHubEndpointConfig);
18
- $connect(): Promise<void>;
19
- $disconnect(): Promise<void>;
20
- $formatMessage(payload: IssueCommentPayload): Message<IssueCommentPayload>;
21
- formatPRReviewComment(payload: PRReviewCommentPayload): Message<PRReviewCommentPayload>;
22
- formatPRReview(payload: PRReviewPayload): Message<PRReviewPayload> | null;
23
- $sendMessage(options: SendOptions): Promise<string>;
24
- $recallMessage(id: string): Promise<void>;
9
+ import { type GithubInboundComment, type ResolvedGithubConfig } from './protocol.js';
10
+ import { GithubClient } from './client.js';
11
+ export interface GithubEndpointOptions {
12
+ readonly id: CapabilityId;
13
+ readonly http?: HttpHost;
14
+ readonly database?: PluginDatabaseHost;
15
+ readonly config: ResolvedGithubConfig;
16
+ readonly createClient?: (config: ResolvedGithubConfig) => GhClient;
25
17
  }
26
- //# sourceMappingURL=endpoint.d.ts.map
18
+ /**
19
+ * GitHub 是代码协作面(issue/PR),无好友/群/频道等 IM 社交概念,
20
+ * 不适用 EndpointManagement 语义端口;本 endpoint 不暴露该端口。
21
+ */
22
+ export declare class GithubEndpoint extends Endpoint<GithubClient> {
23
+ #private;
24
+ readonly client: GithubClient;
25
+ constructor(options: GithubEndpointOptions);
26
+ get config(): ResolvedGithubConfig;
27
+ start(): Promise<void>;
28
+ open(): void;
29
+ close(): void;
30
+ stop(): Promise<void>;
31
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
32
+ /** Test / internal: admit a parsed comment when open. */
33
+ admit(comment: GithubInboundComment): void;
34
+ admitPlatform(name: string, event: unknown): void;
35
+ }
36
+ export declare function defaultCreateClient(config: ResolvedGithubConfig): GhClient;