@zhin.js/adapter-github 5.0.3 → 5.0.5
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 +74 -0
- package/adapters/github.js +2 -2
- package/adapters/github.ts +4 -4
- package/lib/endpoint.d.ts +3 -3
- package/lib/endpoint.js +12 -11
- package/lib/github-agent-deps.d.ts +2 -2
- package/lib/github-agent-deps.js +8 -8
- package/lib/oauth-users.d.ts +2 -2
- package/lib/protocol.d.ts +3 -3
- package/lib/protocol.js +5 -5
- package/package.json +16 -16
- package/schema.json +40 -4
- package/src/endpoint.ts +16 -15
- package/src/github-agent-deps.ts +9 -9
- package/src/oauth-users.ts +2 -2
- package/src/protocol.ts +7 -7
- /package/commands/endpoint/add/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/add/{[name].ts → [id].ts} +0 -0
- /package/commands/endpoint/remove/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/remove/{[name].ts → [id].ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
1
1
|
# @zhin.js/adapter-github
|
|
2
2
|
|
|
3
|
+
## 5.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 36c7400: Replace `AgentPromptBuildContext.commMessage` with an authenticated platform projection and make Agent prompt assembly consume canonical Turn identity. Platform contributors and prompt hooks no longer receive a classic IM `Message`.
|
|
8
|
+
|
|
9
|
+
Remove the unused Message field and active-context escape hatch from PromptController; turn scheduling is keyed only by canonical session identity.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [6f9c366]
|
|
12
|
+
- Updated dependencies [373a56b]
|
|
13
|
+
- Updated dependencies [0de46a8]
|
|
14
|
+
- Updated dependencies [c106ecc]
|
|
15
|
+
- Updated dependencies [ca92e03]
|
|
16
|
+
- Updated dependencies [b0f37ae]
|
|
17
|
+
- Updated dependencies [ba08a2f]
|
|
18
|
+
- Updated dependencies [b08f7fe]
|
|
19
|
+
- Updated dependencies [daffd4c]
|
|
20
|
+
- Updated dependencies [36c7400]
|
|
21
|
+
- Updated dependencies [a9fa72e]
|
|
22
|
+
- Updated dependencies [c8de3ef]
|
|
23
|
+
- Updated dependencies [60f0fc8]
|
|
24
|
+
- Updated dependencies [574c990]
|
|
25
|
+
- Updated dependencies [d096f16]
|
|
26
|
+
- Updated dependencies [3f29623]
|
|
27
|
+
- Updated dependencies [2916852]
|
|
28
|
+
- Updated dependencies [d047869]
|
|
29
|
+
- Updated dependencies [162fa34]
|
|
30
|
+
- Updated dependencies [e62561e]
|
|
31
|
+
- Updated dependencies [3eeeb46]
|
|
32
|
+
- Updated dependencies [85d0f82]
|
|
33
|
+
- Updated dependencies [61bfc1c]
|
|
34
|
+
- Updated dependencies [04bad47]
|
|
35
|
+
- Updated dependencies [e40b048]
|
|
36
|
+
- Updated dependencies [5a5b1bb]
|
|
37
|
+
- Updated dependencies [f1708c3]
|
|
38
|
+
- Updated dependencies [d254a81]
|
|
39
|
+
- Updated dependencies [7123c47]
|
|
40
|
+
- Updated dependencies [05befc1]
|
|
41
|
+
- Updated dependencies [0663b6a]
|
|
42
|
+
- Updated dependencies [f28f9b3]
|
|
43
|
+
- Updated dependencies [9f340f7]
|
|
44
|
+
- Updated dependencies [e53444f]
|
|
45
|
+
- Updated dependencies [5eedd26]
|
|
46
|
+
- Updated dependencies [92b0dd7]
|
|
47
|
+
- Updated dependencies [f919b6f]
|
|
48
|
+
- Updated dependencies [098e411]
|
|
49
|
+
- Updated dependencies [e1b7c01]
|
|
50
|
+
- Updated dependencies [9b94f87]
|
|
51
|
+
- Updated dependencies [a7df753]
|
|
52
|
+
- @zhin.js/agent@1.1.5
|
|
53
|
+
- @zhin.js/host-http@1.0.8
|
|
54
|
+
- @zhin.js/im-contract@1.0.3
|
|
55
|
+
- @zhin.js/adapter@1.1.7
|
|
56
|
+
- @zhin.js/plugin-runtime@1.1.5
|
|
57
|
+
- @zhin.js/command@1.0.9
|
|
58
|
+
- @zhin.js/core@1.5.4
|
|
59
|
+
- zhin.js@6.0.4
|
|
60
|
+
|
|
61
|
+
## 5.0.4
|
|
62
|
+
|
|
63
|
+
### Patch Changes
|
|
64
|
+
|
|
65
|
+
- f8c7a54: fix: im
|
|
66
|
+
- Updated dependencies [f8c7a54]
|
|
67
|
+
- @zhin.js/logger@1.0.76
|
|
68
|
+
- @zhin.js/host-http@1.0.7
|
|
69
|
+
- @zhin.js/adapter@1.1.6
|
|
70
|
+
- @zhin.js/agent@1.1.4
|
|
71
|
+
- @zhin.js/command@1.0.8
|
|
72
|
+
- @zhin.js/core@1.5.3
|
|
73
|
+
- @zhin.js/im-contract@1.0.2
|
|
74
|
+
- @zhin.js/plugin-runtime@1.1.4
|
|
75
|
+
- zhin.js@6.0.3
|
|
76
|
+
|
|
3
77
|
## 5.0.3
|
|
4
78
|
|
|
5
79
|
### Patch Changes
|
package/adapters/github.js
CHANGED
|
@@ -30,8 +30,8 @@ export default defineAdapter({
|
|
|
30
30
|
const config = resolveGithubConfig(context.config);
|
|
31
31
|
const database = optionalDatabase(context);
|
|
32
32
|
// 注册到插件运行时状态(github.endpoint list 的"运行中"数据源)
|
|
33
|
-
context.use(githubRuntimeStateToken).endpoints.set(config.
|
|
34
|
-
|
|
33
|
+
context.use(githubRuntimeStateToken).endpoints.set(config.id, {
|
|
34
|
+
id: config.id,
|
|
35
35
|
mode: config.webhookSecret ? 'webhook' : 'api',
|
|
36
36
|
});
|
|
37
37
|
if (config.webhookSecret) {
|
package/adapters/github.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { messageGatewayToken } from '@zhin.js/core/runtime';
|
|
|
7
7
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
8
8
|
import {
|
|
9
9
|
databaseHostToken,
|
|
10
|
-
type
|
|
10
|
+
type PluginDatabaseHost,
|
|
11
11
|
} from '@zhin.js/plugin-runtime';
|
|
12
12
|
import { GithubEndpoint } from '../src/endpoint.js';
|
|
13
13
|
import { githubRuntimeStateToken } from '../src/github-runtime-state.js';
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
export { GithubEndpoint } from '../src/endpoint.js';
|
|
20
20
|
export type { GithubEndpointOptions } from '../src/endpoint.js';
|
|
21
21
|
|
|
22
|
-
function optionalDatabase(context: AdapterContext):
|
|
22
|
+
function optionalDatabase(context: AdapterContext): PluginDatabaseHost | undefined {
|
|
23
23
|
try {
|
|
24
24
|
return context.use(databaseHostToken);
|
|
25
25
|
} catch {
|
|
@@ -38,8 +38,8 @@ export default defineAdapter<GithubAdapterConfig>({
|
|
|
38
38
|
const config = resolveGithubConfig(context.config);
|
|
39
39
|
const database = optionalDatabase(context);
|
|
40
40
|
// 注册到插件运行时状态(github.endpoint list 的"运行中"数据源)
|
|
41
|
-
context.use(githubRuntimeStateToken).endpoints.set(config.
|
|
42
|
-
|
|
41
|
+
context.use(githubRuntimeStateToken).endpoints.set(config.id, {
|
|
42
|
+
id: config.id,
|
|
43
43
|
mode: config.webhookSecret ? 'webhook' : 'api',
|
|
44
44
|
});
|
|
45
45
|
if (config.webhookSecret) {
|
package/lib/endpoint.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { EndpointInstance, EndpointSendRequest } from '@zhin.js/adapter';
|
|
2
2
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
3
3
|
import type { HttpHost } from '@zhin.js/host-http';
|
|
4
|
-
import type { CapabilityId,
|
|
4
|
+
import type { CapabilityId, PluginDatabaseHost } from '@zhin.js/plugin-runtime';
|
|
5
5
|
import { GhClient } from './gh-client.js';
|
|
6
6
|
import { type GithubInboundComment, type ResolvedGithubConfig } from './protocol.js';
|
|
7
7
|
import { WorkspaceManager } from './workspace-manager.js';
|
|
@@ -9,7 +9,7 @@ export interface GithubEndpointOptions {
|
|
|
9
9
|
readonly id: CapabilityId;
|
|
10
10
|
readonly gateway: MessageGateway;
|
|
11
11
|
readonly http?: HttpHost;
|
|
12
|
-
readonly database?:
|
|
12
|
+
readonly database?: PluginDatabaseHost;
|
|
13
13
|
readonly config: ResolvedGithubConfig;
|
|
14
14
|
readonly createClient?: (config: ResolvedGithubConfig) => GhClient;
|
|
15
15
|
}
|
|
@@ -37,7 +37,7 @@ export declare class GithubEndpoint implements EndpointInstance {
|
|
|
37
37
|
target_type: string;
|
|
38
38
|
}[];
|
|
39
39
|
getWorkspaceManager(): WorkspaceManager;
|
|
40
|
-
getDatabase():
|
|
40
|
+
getDatabase(): PluginDatabaseHost | undefined;
|
|
41
41
|
start(): Promise<void>;
|
|
42
42
|
open(): void;
|
|
43
43
|
close(): void;
|
package/lib/endpoint.js
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
* GithubEndpoint — lifecycle, outbound send, inbound admit.
|
|
3
3
|
*/
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import { formatCompact,
|
|
5
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
6
6
|
import { GhClient } from './gh-client.js';
|
|
7
7
|
import { registerGithubAgentEndpoint } from './github-agent-deps.js';
|
|
8
8
|
import { lookupGithubOauthAccessToken } from './oauth-users.js';
|
|
9
9
|
import { enrichInboundContent, formatInboundContent, formatOutboundBody, githubInboundConversation, parseChannelId, } from './protocol.js';
|
|
10
10
|
import { registerGithubWebhookRoutes } from './webhook.js';
|
|
11
11
|
import { WorkspaceManager } from './workspace-manager.js';
|
|
12
|
-
const logger = getLogger('github');
|
|
13
12
|
/**
|
|
14
13
|
* GitHub 是代码协作面(issue/PR),无好友/群/频道等 IM 社交概念,
|
|
15
14
|
* 不适用 EndpointManagement 语义端口;本 endpoint 不暴露该端口。
|
|
16
15
|
*/
|
|
17
16
|
export class GithubEndpoint {
|
|
17
|
+
#logger;
|
|
18
18
|
#options;
|
|
19
19
|
gh;
|
|
20
20
|
config;
|
|
@@ -25,9 +25,10 @@ export class GithubEndpoint {
|
|
|
25
25
|
#started = false;
|
|
26
26
|
#unregisterAgent;
|
|
27
27
|
constructor(options) {
|
|
28
|
+
this.#logger = getAdapterLogger('github', options.config.id);
|
|
28
29
|
this.#options = options;
|
|
29
30
|
this.config = options.config;
|
|
30
|
-
this.name = options.config.
|
|
31
|
+
this.name = options.config.id;
|
|
31
32
|
this.gh = options.createClient?.(options.config) ?? defaultCreateClient(options.config);
|
|
32
33
|
}
|
|
33
34
|
getAPI() {
|
|
@@ -78,14 +79,14 @@ export class GithubEndpoint {
|
|
|
78
79
|
throw new TypeError('GitHub webhook_secret requires httpHostToken');
|
|
79
80
|
}
|
|
80
81
|
this.#routeReleases.push(...registerGithubWebhookRoutes(this.#options.http, this));
|
|
81
|
-
logger.debug(formatCompact({
|
|
82
|
+
this.#logger.debug(formatCompact({
|
|
82
83
|
endpoint: this.name,
|
|
83
84
|
op: 'webhook',
|
|
84
85
|
path: this.config.webhookPath,
|
|
85
86
|
}));
|
|
86
87
|
}
|
|
87
88
|
else {
|
|
88
|
-
logger.debug(formatCompact({
|
|
89
|
+
this.#logger.debug(formatCompact({
|
|
89
90
|
endpoint: this.name,
|
|
90
91
|
op: 'connect',
|
|
91
92
|
mode: 'api-only',
|
|
@@ -95,7 +96,7 @@ export class GithubEndpoint {
|
|
|
95
96
|
}
|
|
96
97
|
catch (error) {
|
|
97
98
|
await this.stop();
|
|
98
|
-
logger.error('Failed to connect GitHub endpoint:', error);
|
|
99
|
+
this.#logger.error('Failed to connect GitHub endpoint:', error);
|
|
99
100
|
throw error;
|
|
100
101
|
}
|
|
101
102
|
}
|
|
@@ -112,7 +113,7 @@ export class GithubEndpoint {
|
|
|
112
113
|
this.#unregisterAgent?.();
|
|
113
114
|
this.#unregisterAgent = undefined;
|
|
114
115
|
this.#started = false;
|
|
115
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
116
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
116
117
|
}
|
|
117
118
|
async send({ conversation, payload }) {
|
|
118
119
|
const parsed = parseChannelId(conversation.id);
|
|
@@ -124,7 +125,7 @@ export class GithubEndpoint {
|
|
|
124
125
|
: await this.gh.createPRComment(parsed.repo, parsed.number, text);
|
|
125
126
|
if (!r.ok)
|
|
126
127
|
throw new Error(`发送失败: ${JSON.stringify(r.data)}`);
|
|
127
|
-
logger.debug(formatCompact({
|
|
128
|
+
this.#logger.debug(formatCompact({
|
|
128
129
|
op: 'github_send',
|
|
129
130
|
endpoint: this.name,
|
|
130
131
|
target: `${conversation.kind}:${conversation.id}`,
|
|
@@ -145,15 +146,15 @@ export class GithubEndpoint {
|
|
|
145
146
|
conversation,
|
|
146
147
|
message: { conversation, id: comment.id },
|
|
147
148
|
content,
|
|
148
|
-
sender: comment.sender,
|
|
149
|
+
sender: { id: comment.sender, name: comment.sender },
|
|
150
|
+
endpointId: this.name,
|
|
149
151
|
metadata: Object.freeze({
|
|
150
|
-
endpoint: this.name,
|
|
151
152
|
repo: comment.repo,
|
|
152
153
|
kind: comment.kind,
|
|
153
154
|
createdAt: comment.createdAt,
|
|
154
155
|
}),
|
|
155
156
|
}).catch((err) => {
|
|
156
|
-
logger.warn(formatCompact({
|
|
157
|
+
this.#logger.warn(formatCompact({
|
|
157
158
|
op: 'github_gateway_receive_failed',
|
|
158
159
|
target: `${conversation.kind}:${conversation.id}`,
|
|
159
160
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -27,7 +27,7 @@ export interface GithubAgentEndpoint {
|
|
|
27
27
|
getDatabase?(): unknown;
|
|
28
28
|
}
|
|
29
29
|
export interface GithubAgentDeps {
|
|
30
|
-
getEndpoint: (
|
|
30
|
+
getEndpoint: (endpointKey?: string) => GithubAgentEndpoint;
|
|
31
31
|
/** Alias kept for existing agent handlers that call getAdapter(). */
|
|
32
32
|
getAdapter: () => GithubAgentEndpoint;
|
|
33
33
|
getWorkspaceManager: () => WorkspaceManager;
|
|
@@ -40,7 +40,7 @@ export interface GithubAgentDeps {
|
|
|
40
40
|
error: (...args: unknown[]) => void;
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
export declare function registerGithubAgentEndpoint(
|
|
43
|
+
export declare function registerGithubAgentEndpoint(endpointKey: string, endpoint: GithubAgentEndpoint): () => void;
|
|
44
44
|
/** Optional override used by tests / transitional callers. Pass `null` to clear. */
|
|
45
45
|
export declare function setGithubAgentDeps(deps: GithubAgentDeps | null): void;
|
|
46
46
|
export declare function getGithubAgentDeps(): GithubAgentDeps;
|
package/lib/github-agent-deps.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const endpoints = new Map();
|
|
6
6
|
let override = null;
|
|
7
|
-
export function registerGithubAgentEndpoint(
|
|
8
|
-
endpoints.set(
|
|
7
|
+
export function registerGithubAgentEndpoint(endpointKey, endpoint) {
|
|
8
|
+
endpoints.set(endpointKey, endpoint);
|
|
9
9
|
return () => {
|
|
10
|
-
if (endpoints.get(
|
|
11
|
-
endpoints.delete(
|
|
10
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
11
|
+
endpoints.delete(endpointKey);
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -16,11 +16,11 @@ export function registerGithubAgentEndpoint(endpointId, endpoint) {
|
|
|
16
16
|
export function setGithubAgentDeps(deps) {
|
|
17
17
|
override = deps;
|
|
18
18
|
}
|
|
19
|
-
function lookup(
|
|
20
|
-
if (
|
|
21
|
-
const registered = endpoints.get(
|
|
19
|
+
function lookup(endpointKey) {
|
|
20
|
+
if (endpointKey) {
|
|
21
|
+
const registered = endpoints.get(endpointKey);
|
|
22
22
|
if (!registered)
|
|
23
|
-
throw new Error(`Endpoint ${
|
|
23
|
+
throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
24
24
|
return registered;
|
|
25
25
|
}
|
|
26
26
|
const first = endpoints.values().next().value;
|
package/lib/oauth-users.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DatabaseHost } from '@zhin.js/plugin-runtime';
|
|
1
|
+
import type { DatabaseHost, PluginDatabaseHost } from '@zhin.js/plugin-runtime';
|
|
2
2
|
export declare const GITHUB_OAUTH_USERS_TABLE = "github_oauth_users";
|
|
3
3
|
export declare const GITHUB_OAUTH_USERS_SCHEMA: {
|
|
4
4
|
readonly id: {
|
|
@@ -30,4 +30,4 @@ export declare function defineGithubOauthUsersTable(host: {
|
|
|
30
30
|
define(name: string, definition: Record<string, unknown>): void;
|
|
31
31
|
}): void;
|
|
32
32
|
/** Resolve a stored PAT/device-flow token; null when DB missing or no row. */
|
|
33
|
-
export declare function lookupGithubOauthAccessToken(database: DatabaseHost | undefined, platform: string, platformUid: string): Promise<string | null>;
|
|
33
|
+
export declare function lookupGithubOauthAccessToken(database: DatabaseHost | PluginDatabaseHost | undefined, platform: string, platformUid: string): Promise<string | null>;
|
package/lib/protocol.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export type { EventType, GenericWebhookPayload, GitHubComment, GitHubEndpointCon
|
|
|
9
9
|
export { buildChannelId, parseChannelId } from './types.js';
|
|
10
10
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
11
11
|
export interface GithubAdapterConfig {
|
|
12
|
-
readonly
|
|
12
|
+
readonly id?: string;
|
|
13
13
|
readonly host?: string;
|
|
14
14
|
readonly app_id?: string | number;
|
|
15
15
|
readonly appId?: string | number;
|
|
@@ -42,7 +42,7 @@ export interface GithubAdapterConfig {
|
|
|
42
42
|
}
|
|
43
43
|
export interface ResolvedGithubConfig {
|
|
44
44
|
readonly context: 'github';
|
|
45
|
-
readonly
|
|
45
|
+
readonly id: string;
|
|
46
46
|
readonly host?: string;
|
|
47
47
|
readonly appId?: string | number;
|
|
48
48
|
readonly privateKey?: string;
|
|
@@ -71,7 +71,7 @@ export interface GithubInboundComment {
|
|
|
71
71
|
* 仓库(owner/repo)进 `parent`。出站侧用 `parseChannelId(conversation.id)`
|
|
72
72
|
* 在平台边界还原 repo/type/number。
|
|
73
73
|
*/
|
|
74
|
-
export declare function githubInboundConversation(
|
|
74
|
+
export declare function githubInboundConversation(endpointKey: string, comment: GithubInboundComment): ConversationRef;
|
|
75
75
|
export declare function resolveGithubConfig(config?: GithubAdapterConfig): ResolvedGithubConfig;
|
|
76
76
|
export declare function normalizeWebhookPath(path: string): string;
|
|
77
77
|
export declare function shouldAutoReplyRepo(config: Pick<ResolvedGithubConfig, 'autoReplyRepos'>, repo: string): boolean;
|
package/lib/protocol.js
CHANGED
|
@@ -14,9 +14,9 @@ export { buildChannelId, parseChannelId } from './types.js';
|
|
|
14
14
|
* 仓库(owner/repo)进 `parent`。出站侧用 `parseChannelId(conversation.id)`
|
|
15
15
|
* 在平台边界还原 repo/type/number。
|
|
16
16
|
*/
|
|
17
|
-
export function githubInboundConversation(
|
|
17
|
+
export function githubInboundConversation(endpointKey, comment) {
|
|
18
18
|
return {
|
|
19
|
-
endpoint: { id:
|
|
19
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
20
20
|
kind: 'channel',
|
|
21
21
|
id: comment.channelId,
|
|
22
22
|
parent: { kind: 'channel', id: comment.repo },
|
|
@@ -30,8 +30,8 @@ export function resolveGithubConfig(config = {}) {
|
|
|
30
30
|
if (!appId || !privateKey) {
|
|
31
31
|
throw new TypeError('GitHub adapter requires app_id + private_key (plugins.<key> or GITHUB_APP_ID)');
|
|
32
32
|
}
|
|
33
|
-
const
|
|
34
|
-
|| (typeof entry?.
|
|
33
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
34
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
35
35
|
|| process.env.GITHUB_BOT_NAME
|
|
36
36
|
|| 'github-bot';
|
|
37
37
|
const webhookSecret = config.webhookSecret ?? config.webhook_secret
|
|
@@ -51,7 +51,7 @@ export function resolveGithubConfig(config = {}) {
|
|
|
51
51
|
?? entry?.workspaceRoot ?? entry?.workspace_root;
|
|
52
52
|
return {
|
|
53
53
|
context: 'github',
|
|
54
|
-
|
|
54
|
+
id,
|
|
55
55
|
...(host ? { host } : {}),
|
|
56
56
|
...(appId != null ? { appId } : {}),
|
|
57
57
|
...(privateKey ? { privateKey } : {}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-github",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.5",
|
|
4
4
|
"description": "Zhin.js GitHub adapter for Plugin Runtime (App auth + webhook)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -41,22 +41,22 @@
|
|
|
41
41
|
"directory": "plugins/adapters/github"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@zhin.js/adapter": "1.1.
|
|
45
|
-
"@zhin.js/command": "1.0.
|
|
46
|
-
"@zhin.js/core": "1.5.
|
|
47
|
-
"@zhin.js/host-http": "1.0.
|
|
48
|
-
"@zhin.js/im-contract": "1.0.
|
|
49
|
-
"@zhin.js/logger": "1.0.
|
|
50
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
44
|
+
"@zhin.js/adapter": "1.1.7",
|
|
45
|
+
"@zhin.js/command": "1.0.9",
|
|
46
|
+
"@zhin.js/core": "1.5.4",
|
|
47
|
+
"@zhin.js/host-http": "1.0.8",
|
|
48
|
+
"@zhin.js/im-contract": "1.0.3",
|
|
49
|
+
"@zhin.js/logger": "1.0.76",
|
|
50
|
+
"@zhin.js/plugin-runtime": "1.1.5"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"zod": "^4.0.0",
|
|
54
|
-
"@zhin.js/adapter": "1.1.
|
|
55
|
-
"@zhin.js/agent": "1.1.
|
|
56
|
-
"@zhin.js/core": "1.5.
|
|
57
|
-
"@zhin.js/host-http": "1.0.
|
|
58
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
59
|
-
"zhin.js": "6.0.
|
|
54
|
+
"@zhin.js/adapter": "1.1.7",
|
|
55
|
+
"@zhin.js/agent": "1.1.5",
|
|
56
|
+
"@zhin.js/core": "1.5.4",
|
|
57
|
+
"@zhin.js/host-http": "1.0.8",
|
|
58
|
+
"@zhin.js/plugin-runtime": "1.1.5",
|
|
59
|
+
"zhin.js": "6.0.4"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"zhin.js": {
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"typescript": "^6.0.3",
|
|
75
75
|
"vitest": "^4.1.10",
|
|
76
76
|
"zod": "^4.4.3",
|
|
77
|
-
"@zhin.js/agent": "1.1.
|
|
78
|
-
"zhin.js": "6.0.
|
|
77
|
+
"@zhin.js/agent": "1.1.5",
|
|
78
|
+
"zhin.js": "6.0.4"
|
|
79
79
|
},
|
|
80
80
|
"files": [
|
|
81
81
|
"adapters",
|
package/schema.json
CHANGED
|
@@ -35,6 +35,24 @@
|
|
|
35
35
|
"type": "string",
|
|
36
36
|
"description": "Managed git workspace root"
|
|
37
37
|
},
|
|
38
|
+
"master": {
|
|
39
|
+
"type": [
|
|
40
|
+
"string",
|
|
41
|
+
"number"
|
|
42
|
+
],
|
|
43
|
+
"description": "框架 master(GitHub user login or id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
|
|
44
|
+
},
|
|
45
|
+
"trusted": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": {
|
|
48
|
+
"type": [
|
|
49
|
+
"string",
|
|
50
|
+
"number"
|
|
51
|
+
],
|
|
52
|
+
"description": "Trusted GitHub user login or id"
|
|
53
|
+
},
|
|
54
|
+
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
|
|
55
|
+
},
|
|
38
56
|
"endpoints": {
|
|
39
57
|
"type": "array",
|
|
40
58
|
"description": "多账号:一个插件实例挂多个 endpoint",
|
|
@@ -42,9 +60,23 @@
|
|
|
42
60
|
"type": "object",
|
|
43
61
|
"additionalProperties": true,
|
|
44
62
|
"properties": {
|
|
45
|
-
"
|
|
46
|
-
"type":
|
|
47
|
-
|
|
63
|
+
"master": {
|
|
64
|
+
"type": [
|
|
65
|
+
"string",
|
|
66
|
+
"number"
|
|
67
|
+
],
|
|
68
|
+
"description": "本 endpoint 的框架 master(GitHub user login or id);覆盖顶层 master"
|
|
69
|
+
},
|
|
70
|
+
"trusted": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"items": {
|
|
73
|
+
"type": [
|
|
74
|
+
"string",
|
|
75
|
+
"number"
|
|
76
|
+
],
|
|
77
|
+
"description": "Trusted GitHub user login or id"
|
|
78
|
+
},
|
|
79
|
+
"description": "本 endpoint 的 trusted 列表"
|
|
48
80
|
},
|
|
49
81
|
"app_id": {
|
|
50
82
|
"type": [
|
|
@@ -75,10 +107,14 @@
|
|
|
75
107
|
"webhookSecret": {
|
|
76
108
|
"type": "string",
|
|
77
109
|
"description": "Webhook HMAC secret (camelCase alias)"
|
|
110
|
+
},
|
|
111
|
+
"id": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"description": "GitHub App bot name"
|
|
78
114
|
}
|
|
79
115
|
},
|
|
80
116
|
"required": [
|
|
81
|
-
"
|
|
117
|
+
"id"
|
|
82
118
|
]
|
|
83
119
|
}
|
|
84
120
|
},
|
package/src/endpoint.ts
CHANGED
|
@@ -5,8 +5,8 @@ import path from 'node:path';
|
|
|
5
5
|
import type { EndpointInstance, EndpointSendRequest } from '@zhin.js/adapter';
|
|
6
6
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
7
7
|
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
8
|
-
import { formatCompact,
|
|
9
|
-
import type { CapabilityId,
|
|
8
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
9
|
+
import type { CapabilityId, PluginDatabaseHost } from '@zhin.js/plugin-runtime';
|
|
10
10
|
import { GhClient } from './gh-client.js';
|
|
11
11
|
import { registerGithubAgentEndpoint } from './github-agent-deps.js';
|
|
12
12
|
import { lookupGithubOauthAccessToken } from './oauth-users.js';
|
|
@@ -22,13 +22,11 @@ import {
|
|
|
22
22
|
import { registerGithubWebhookRoutes } from './webhook.js';
|
|
23
23
|
import { WorkspaceManager } from './workspace-manager.js';
|
|
24
24
|
|
|
25
|
-
const logger = getLogger('github');
|
|
26
|
-
|
|
27
25
|
export interface GithubEndpointOptions {
|
|
28
26
|
readonly id: CapabilityId;
|
|
29
27
|
readonly gateway: MessageGateway;
|
|
30
28
|
readonly http?: HttpHost;
|
|
31
|
-
readonly database?:
|
|
29
|
+
readonly database?: PluginDatabaseHost;
|
|
32
30
|
readonly config: ResolvedGithubConfig;
|
|
33
31
|
readonly createClient?: (config: ResolvedGithubConfig) => GhClient;
|
|
34
32
|
}
|
|
@@ -38,6 +36,8 @@ export interface GithubEndpointOptions {
|
|
|
38
36
|
* 不适用 EndpointManagement 语义端口;本 endpoint 不暴露该端口。
|
|
39
37
|
*/
|
|
40
38
|
export class GithubEndpoint implements EndpointInstance {
|
|
39
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
40
|
+
|
|
41
41
|
readonly #options: GithubEndpointOptions;
|
|
42
42
|
readonly gh: GhClient;
|
|
43
43
|
readonly config: ResolvedGithubConfig;
|
|
@@ -49,9 +49,10 @@ export class GithubEndpoint implements EndpointInstance {
|
|
|
49
49
|
#unregisterAgent?: () => void;
|
|
50
50
|
|
|
51
51
|
constructor(options: GithubEndpointOptions) {
|
|
52
|
+
this.#logger = getAdapterLogger('github', options.config.id);
|
|
52
53
|
this.#options = options;
|
|
53
54
|
this.config = options.config;
|
|
54
|
-
this.name = options.config.
|
|
55
|
+
this.name = options.config.id;
|
|
55
56
|
this.gh = options.createClient?.(options.config) ?? defaultCreateClient(options.config);
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -95,7 +96,7 @@ export class GithubEndpoint implements EndpointInstance {
|
|
|
95
96
|
return this.#workspaceManager;
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
getDatabase():
|
|
99
|
+
getDatabase(): PluginDatabaseHost | undefined {
|
|
99
100
|
return this.#options.database;
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -111,13 +112,13 @@ export class GithubEndpoint implements EndpointInstance {
|
|
|
111
112
|
throw new TypeError('GitHub webhook_secret requires httpHostToken');
|
|
112
113
|
}
|
|
113
114
|
this.#routeReleases.push(...registerGithubWebhookRoutes(this.#options.http, this));
|
|
114
|
-
logger.debug(formatCompact({
|
|
115
|
+
this.#logger.debug(formatCompact({
|
|
115
116
|
endpoint: this.name,
|
|
116
117
|
op: 'webhook',
|
|
117
118
|
path: this.config.webhookPath,
|
|
118
119
|
}));
|
|
119
120
|
} else {
|
|
120
|
-
logger.debug(formatCompact({
|
|
121
|
+
this.#logger.debug(formatCompact({
|
|
121
122
|
endpoint: this.name,
|
|
122
123
|
op: 'connect',
|
|
123
124
|
mode: 'api-only',
|
|
@@ -126,7 +127,7 @@ export class GithubEndpoint implements EndpointInstance {
|
|
|
126
127
|
}
|
|
127
128
|
} catch (error) {
|
|
128
129
|
await this.stop();
|
|
129
|
-
logger.error('Failed to connect GitHub endpoint:', error);
|
|
130
|
+
this.#logger.error('Failed to connect GitHub endpoint:', error);
|
|
130
131
|
throw error;
|
|
131
132
|
}
|
|
132
133
|
}
|
|
@@ -145,7 +146,7 @@ export class GithubEndpoint implements EndpointInstance {
|
|
|
145
146
|
this.#unregisterAgent?.();
|
|
146
147
|
this.#unregisterAgent = undefined;
|
|
147
148
|
this.#started = false;
|
|
148
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
149
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
@@ -156,7 +157,7 @@ export class GithubEndpoint implements EndpointInstance {
|
|
|
156
157
|
? await this.gh.createIssueComment(parsed.repo, parsed.number, text)
|
|
157
158
|
: await this.gh.createPRComment(parsed.repo, parsed.number, text);
|
|
158
159
|
if (!r.ok) throw new Error(`发送失败: ${JSON.stringify(r.data)}`);
|
|
159
|
-
logger.debug(formatCompact({
|
|
160
|
+
this.#logger.debug(formatCompact({
|
|
160
161
|
op: 'github_send',
|
|
161
162
|
endpoint: this.name,
|
|
162
163
|
target: `${conversation.kind}:${conversation.id}`,
|
|
@@ -181,15 +182,15 @@ export class GithubEndpoint implements EndpointInstance {
|
|
|
181
182
|
conversation,
|
|
182
183
|
message: { conversation, id: comment.id },
|
|
183
184
|
content,
|
|
184
|
-
sender: comment.sender,
|
|
185
|
+
sender: { id: comment.sender, name: comment.sender },
|
|
186
|
+
endpointId: this.name,
|
|
185
187
|
metadata: Object.freeze({
|
|
186
|
-
endpoint: this.name,
|
|
187
188
|
repo: comment.repo,
|
|
188
189
|
kind: comment.kind,
|
|
189
190
|
createdAt: comment.createdAt,
|
|
190
191
|
}),
|
|
191
192
|
}).catch((err) => {
|
|
192
|
-
logger.warn(formatCompact({
|
|
193
|
+
this.#logger.warn(formatCompact({
|
|
193
194
|
op: 'github_gateway_receive_failed',
|
|
194
195
|
target: `${conversation.kind}:${conversation.id}`,
|
|
195
196
|
error: err instanceof Error ? err.message : String(err),
|
package/src/github-agent-deps.ts
CHANGED
|
@@ -23,7 +23,7 @@ export interface GithubAgentEndpoint {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export interface GithubAgentDeps {
|
|
26
|
-
getEndpoint: (
|
|
26
|
+
getEndpoint: (endpointKey?: string) => GithubAgentEndpoint;
|
|
27
27
|
/** Alias kept for existing agent handlers that call getAdapter(). */
|
|
28
28
|
getAdapter: () => GithubAgentEndpoint;
|
|
29
29
|
getWorkspaceManager: () => WorkspaceManager;
|
|
@@ -39,13 +39,13 @@ const endpoints = new Map<string, GithubAgentEndpoint>();
|
|
|
39
39
|
let override: GithubAgentDeps | null = null;
|
|
40
40
|
|
|
41
41
|
export function registerGithubAgentEndpoint(
|
|
42
|
-
|
|
42
|
+
endpointKey: string,
|
|
43
43
|
endpoint: GithubAgentEndpoint,
|
|
44
44
|
): () => void {
|
|
45
|
-
endpoints.set(
|
|
45
|
+
endpoints.set(endpointKey, endpoint);
|
|
46
46
|
return () => {
|
|
47
|
-
if (endpoints.get(
|
|
48
|
-
endpoints.delete(
|
|
47
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
48
|
+
endpoints.delete(endpointKey);
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
}
|
|
@@ -55,10 +55,10 @@ export function setGithubAgentDeps(deps: GithubAgentDeps | null): void {
|
|
|
55
55
|
override = deps;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function lookup(
|
|
59
|
-
if (
|
|
60
|
-
const registered = endpoints.get(
|
|
61
|
-
if (!registered) throw new Error(`Endpoint ${
|
|
58
|
+
function lookup(endpointKey?: string): GithubAgentEndpoint {
|
|
59
|
+
if (endpointKey) {
|
|
60
|
+
const registered = endpoints.get(endpointKey);
|
|
61
|
+
if (!registered) throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
62
62
|
return registered;
|
|
63
63
|
}
|
|
64
64
|
const first = endpoints.values().next().value;
|
package/src/oauth-users.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* github_oauth_users — SSOT for Runtime user-token binding (gh bind / Endpoint lookup).
|
|
3
3
|
*/
|
|
4
4
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
5
|
-
import type { DatabaseHost } from '@zhin.js/plugin-runtime';
|
|
5
|
+
import type { DatabaseHost, PluginDatabaseHost } from '@zhin.js/plugin-runtime';
|
|
6
6
|
|
|
7
7
|
const logger = getLogger('github');
|
|
8
8
|
|
|
@@ -25,7 +25,7 @@ export function defineGithubOauthUsersTable(
|
|
|
25
25
|
|
|
26
26
|
/** Resolve a stored PAT/device-flow token; null when DB missing or no row. */
|
|
27
27
|
export async function lookupGithubOauthAccessToken(
|
|
28
|
-
database: DatabaseHost | undefined,
|
|
28
|
+
database: DatabaseHost | PluginDatabaseHost | undefined,
|
|
29
29
|
platform: string,
|
|
30
30
|
platformUid: string,
|
|
31
31
|
): Promise<string | null> {
|
package/src/protocol.ts
CHANGED
|
@@ -40,7 +40,7 @@ export { buildChannelId, parseChannelId } from './types.js';
|
|
|
40
40
|
|
|
41
41
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
42
42
|
export interface GithubAdapterConfig {
|
|
43
|
-
readonly
|
|
43
|
+
readonly id?: string;
|
|
44
44
|
readonly host?: string;
|
|
45
45
|
readonly app_id?: string | number;
|
|
46
46
|
readonly appId?: string | number;
|
|
@@ -74,7 +74,7 @@ export interface GithubAdapterConfig {
|
|
|
74
74
|
|
|
75
75
|
export interface ResolvedGithubConfig {
|
|
76
76
|
readonly context: 'github';
|
|
77
|
-
readonly
|
|
77
|
+
readonly id: string;
|
|
78
78
|
readonly host?: string;
|
|
79
79
|
readonly appId?: string | number;
|
|
80
80
|
readonly privateKey?: string;
|
|
@@ -107,11 +107,11 @@ export interface GithubInboundComment {
|
|
|
107
107
|
* 在平台边界还原 repo/type/number。
|
|
108
108
|
*/
|
|
109
109
|
export function githubInboundConversation(
|
|
110
|
-
|
|
110
|
+
endpointKey: string,
|
|
111
111
|
comment: GithubInboundComment,
|
|
112
112
|
): ConversationRef {
|
|
113
113
|
return {
|
|
114
|
-
endpoint: { id:
|
|
114
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
115
115
|
kind: 'channel',
|
|
116
116
|
id: comment.channelId,
|
|
117
117
|
parent: { kind: 'channel', id: comment.repo },
|
|
@@ -139,8 +139,8 @@ export function resolveGithubConfig(config: GithubAdapterConfig = {}): ResolvedG
|
|
|
139
139
|
'GitHub adapter requires app_id + private_key (plugins.<key> or GITHUB_APP_ID)',
|
|
140
140
|
);
|
|
141
141
|
}
|
|
142
|
-
const
|
|
143
|
-
|| (typeof entry?.
|
|
142
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
143
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
144
144
|
|| process.env.GITHUB_BOT_NAME
|
|
145
145
|
|| 'github-bot';
|
|
146
146
|
const webhookSecret = config.webhookSecret ?? config.webhook_secret
|
|
@@ -165,7 +165,7 @@ export function resolveGithubConfig(config: GithubAdapterConfig = {}): ResolvedG
|
|
|
165
165
|
|
|
166
166
|
return {
|
|
167
167
|
context: 'github',
|
|
168
|
-
|
|
168
|
+
id,
|
|
169
169
|
...(host ? { host } : {}),
|
|
170
170
|
...(appId != null ? { appId } : {}),
|
|
171
171
|
...(privateKey ? { privateKey } : {}),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|