@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.
- package/CHANGELOG.md +1212 -0
- package/README.md +73 -195
- package/adapters/github/index.js +51 -0
- package/adapters/github/index.ts +59 -0
- package/agents/github/agent.json +20 -0
- package/agents/github/boundaries.md +3 -0
- package/agents/github/conventions.md +3 -0
- package/agents/github/skills/github-account/SKILL.md +20 -0
- package/agents/github/skills/github-account/handlers.js +116 -0
- package/agents/github/skills/github-account/handlers.ts +136 -0
- package/agents/github/skills/github-account/tools/bind/index.js +13 -0
- package/agents/github/skills/github-account/tools/bind/index.ts +13 -0
- package/agents/github/skills/github-account/tools/install/index.js +13 -0
- package/agents/github/skills/github-account/tools/install/index.ts +13 -0
- package/agents/github/skills/github-account/tools/unbind/index.js +13 -0
- package/agents/github/skills/github-account/tools/unbind/index.ts +13 -0
- package/agents/github/skills/github-account/tools/whoami/index.js +13 -0
- package/agents/github/skills/github-account/tools/whoami/index.ts +13 -0
- package/agents/github/skills/github-cli/SKILL.md +47 -0
- package/agents/github/skills/github-repository/SKILL.md +21 -0
- package/agents/github/skills/github-repository/handlers.js +77 -0
- package/agents/github/skills/github-repository/handlers.ts +113 -0
- package/agents/github/skills/github-repository/tools/create_pr/index.js +20 -0
- package/agents/github/skills/github-repository/tools/create_pr/index.ts +20 -0
- package/agents/github/skills/github-repository/tools/patch_file/index.js +19 -0
- package/agents/github/skills/github-repository/tools/patch_file/index.ts +19 -0
- package/agents/github/skills/github-repository/tools/prepare_workspace/index.js +15 -0
- package/agents/github/skills/github-repository/tools/prepare_workspace/index.ts +15 -0
- package/agents/github/skills/github-repository/tools/push_branch/index.js +18 -0
- package/agents/github/skills/github-repository/tools/push_branch/index.ts +18 -0
- package/agents/github/skills/github-subscriptions/SKILL.md +20 -0
- package/agents/github/skills/github-subscriptions/handlers.js +101 -0
- package/agents/github/skills/github-subscriptions/handlers.ts +119 -0
- package/agents/github/skills/github-subscriptions/tools/star/index.js +16 -0
- package/agents/github/skills/github-subscriptions/tools/star/index.ts +16 -0
- package/agents/github/skills/github-subscriptions/tools/subscribe/index.js +16 -0
- package/agents/github/skills/github-subscriptions/tools/subscribe/index.ts +16 -0
- package/agents/github/skills/github-subscriptions/tools/subscriptions/index.js +13 -0
- package/agents/github/skills/github-subscriptions/tools/subscriptions/index.ts +13 -0
- package/agents/github/skills/github-subscriptions/tools/unsubscribe/index.js +15 -0
- package/agents/github/skills/github-subscriptions/tools/unsubscribe/index.ts +15 -0
- package/agents/github/system.md +3 -0
- package/commands/github/endpoint/add/[id]/index.js +3 -0
- package/commands/github/endpoint/add/[id]/index.ts +3 -0
- package/commands/github/endpoint/definition.js +23 -0
- package/commands/github/endpoint/definition.ts +23 -0
- package/commands/github/endpoint/list/index.js +3 -0
- package/commands/github/endpoint/list/index.ts +3 -0
- package/commands/github/endpoint/remove/[id]/index.js +3 -0
- package/commands/github/endpoint/remove/[id]/index.ts +3 -0
- package/lib/client.d.ts +36 -0
- package/lib/client.js +44 -0
- package/lib/endpoint.d.ts +32 -22
- package/lib/endpoint.js +125 -145
- package/lib/gh-client.d.ts +73 -1
- package/lib/gh-client.js +99 -1
- package/lib/github-channel-context.d.ts +16 -0
- package/lib/github-channel-context.js +31 -0
- package/lib/github-runtime-state.d.ts +1 -0
- package/lib/github-runtime-state.js +6 -0
- package/lib/index.d.ts +7 -32
- package/lib/index.js +7 -385
- package/lib/oauth-users.d.ts +33 -0
- package/lib/oauth-users.js +38 -0
- package/lib/protocol.d.ts +72 -0
- package/lib/protocol.js +281 -0
- package/lib/types.d.ts +0 -18
- package/lib/types.js +2 -4
- package/lib/webhook.d.ts +14 -0
- package/lib/webhook.js +88 -0
- package/lib/workspace-manager.d.ts +21 -0
- package/lib/workspace-manager.js +154 -0
- package/package.json +93 -23
- package/plugin.js +38 -0
- package/prompt-sections/platform/index.js +16 -0
- package/prompt-sections/platform/index.ts +16 -0
- package/schema.json +137 -0
- package/src/client.ts +62 -0
- package/src/endpoint.ts +145 -150
- package/src/gh-client.ts +131 -0
- package/src/github-channel-context.ts +46 -0
- package/src/github-runtime-state.ts +7 -0
- package/src/index.ts +48 -431
- package/src/oauth-users.ts +47 -0
- package/src/protocol.ts +372 -0
- package/src/types.ts +0 -22
- package/src/webhook.ts +130 -0
- package/src/workspace-manager.ts +168 -0
- package/lib/adapter.d.ts +0 -64
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js +0 -416
- 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 +0 -82
- package/lib/agent-prompt.js.map +0 -1
- package/lib/endpoint.d.ts.map +0 -1
- package/lib/endpoint.js.map +0 -1
- package/lib/gh-client.d.ts.map +0 -1
- package/lib/gh-client.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/register-github-mcp.d.ts +0 -6
- package/lib/register-github-mcp.d.ts.map +0 -1
- package/lib/register-github-mcp.js +0 -35
- package/lib/register-github-mcp.js.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js.map +0 -1
- package/plugin.yml +0 -3
- package/skills/github/SKILL.md +0 -266
- package/src/adapter.ts +0 -448
- package/src/agent-prompt.ts +0 -99
- 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,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);
|
package/lib/client.d.ts
ADDED
|
@@ -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
|
-
*
|
|
3
|
+
* GithubEndpoint — lifecycle, outbound send, inbound admit.
|
|
3
4
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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;
|