@holon-run/agentinbox 0.1.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/src/adapters.js +33 -2
- package/dist/src/cli.js +173 -14
- package/dist/src/current_agent.js +1 -0
- package/dist/src/http.js +242 -8
- package/dist/src/runtime_gate.js +464 -0
- package/dist/src/service.js +1114 -23
- package/dist/src/source_resolution.js +100 -0
- package/dist/src/source_schema.js +23 -1
- package/dist/src/sources/github.js +73 -1
- package/dist/src/sources/remote.js +24 -0
- package/dist/src/sources/remote_profiles.js +133 -0
- package/dist/src/store.js +234 -9
- package/dist/src/terminal.js +12 -4
- package/drizzle/migrations/0002_subscription_cleanup_policy.sql +45 -0
- package/drizzle/migrations/0003_subscription_lifecycle_retirements.sql +14 -0
- package/drizzle/migrations/0004_source_idle_states.sql +10 -0
- package/drizzle/migrations/0005_timers.sql +22 -0
- package/drizzle/migrations/0006_terminal_runtime_pid.sql +1 -0
- package/drizzle/schema.ts +45 -2
- package/package.json +1 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveSourceIdentity = resolveSourceIdentity;
|
|
4
|
+
exports.resolveSourceSchema = resolveSourceSchema;
|
|
5
|
+
exports.withResolvedIdentity = withResolvedIdentity;
|
|
6
|
+
const paths_1 = require("./paths");
|
|
7
|
+
const remote_profiles_1 = require("./sources/remote_profiles");
|
|
8
|
+
const source_schema_1 = require("./source_schema");
|
|
9
|
+
async function resolveSourceIdentity(source, context = {}) {
|
|
10
|
+
if (source.sourceType === "local_event") {
|
|
11
|
+
return {
|
|
12
|
+
hostType: "local_event",
|
|
13
|
+
sourceKind: "local_event",
|
|
14
|
+
implementationId: "builtin.local_event",
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const builtinImplementationId = (0, remote_profiles_1.builtInProfileIdForSourceType)(source.sourceType);
|
|
18
|
+
if (builtinImplementationId) {
|
|
19
|
+
return {
|
|
20
|
+
hostType: "remote_source",
|
|
21
|
+
sourceKind: source.sourceType,
|
|
22
|
+
implementationId: builtinImplementationId,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (source.sourceType !== "remote_source") {
|
|
26
|
+
throw new Error(`unsupported source type for source resolution: ${source.sourceType}`);
|
|
27
|
+
}
|
|
28
|
+
const profileRegistry = context.profileRegistry ?? new remote_profiles_1.RemoteSourceProfileRegistry();
|
|
29
|
+
const homeDir = context.homeDir ?? (0, paths_1.resolveAgentInboxHome)(process.env);
|
|
30
|
+
const profile = await profileRegistry.resolve(source, homeDir);
|
|
31
|
+
const capabilityDescription = typeof profile.describeCapabilities === "function"
|
|
32
|
+
? profile.describeCapabilities(profileInputSource(source))
|
|
33
|
+
: undefined;
|
|
34
|
+
return {
|
|
35
|
+
hostType: "remote_source",
|
|
36
|
+
sourceKind: capabilityDescription?.sourceKind?.trim() || `remote:${profile.id}`,
|
|
37
|
+
implementationId: profile.id,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async function resolveSourceSchema(source, context = {}) {
|
|
41
|
+
const profileRegistry = context.profileRegistry ?? new remote_profiles_1.RemoteSourceProfileRegistry();
|
|
42
|
+
const homeDir = context.homeDir ?? (0, paths_1.resolveAgentInboxHome)(process.env);
|
|
43
|
+
const resolvedContext = { ...context, profileRegistry, homeDir };
|
|
44
|
+
const identity = await resolveSourceIdentity(source, resolvedContext);
|
|
45
|
+
const staticSchema = (0, source_schema_1.getSourceSchema)(source.sourceType);
|
|
46
|
+
let capabilityDescription;
|
|
47
|
+
let profile = null;
|
|
48
|
+
if (identity.hostType === "remote_source") {
|
|
49
|
+
profile = await profileRegistry.resolve(source, homeDir);
|
|
50
|
+
capabilityDescription = typeof profile.describeCapabilities === "function"
|
|
51
|
+
? profile.describeCapabilities(profileInputSource(source))
|
|
52
|
+
: undefined;
|
|
53
|
+
}
|
|
54
|
+
return withResolvedIdentity(source.sourceId, {
|
|
55
|
+
sourceType: staticSchema.sourceType,
|
|
56
|
+
metadataFields: capabilityDescription?.metadataFields ?? staticSchema.metadataFields,
|
|
57
|
+
payloadExamples: capabilityDescription?.payloadExamples ?? staticSchema.payloadExamples,
|
|
58
|
+
eventVariantExamples: capabilityDescription?.eventVariantExamples ?? staticSchema.eventVariantExamples,
|
|
59
|
+
configFields: capabilityDescription?.configSchema ?? staticSchema.configFields,
|
|
60
|
+
}, identity, identity.hostType === "remote_source"
|
|
61
|
+
? {
|
|
62
|
+
aliases: capabilityDescription?.aliases,
|
|
63
|
+
supportsTrackedResourceRef: typeof profile?.deriveTrackedResource === "function",
|
|
64
|
+
supportsLifecycleSignals: typeof profile?.projectLifecycleSignal === "function",
|
|
65
|
+
shortcuts: typeof profile?.listSubscriptionShortcuts === "function"
|
|
66
|
+
? profile.listSubscriptionShortcuts(profileInputSource(source))
|
|
67
|
+
: [],
|
|
68
|
+
}
|
|
69
|
+
: undefined);
|
|
70
|
+
}
|
|
71
|
+
function withResolvedIdentity(sourceId, schema, identity, capabilityMetadata) {
|
|
72
|
+
return {
|
|
73
|
+
sourceId,
|
|
74
|
+
sourceType: schema.sourceType,
|
|
75
|
+
metadataFields: schema.metadataFields,
|
|
76
|
+
payloadExamples: schema.payloadExamples,
|
|
77
|
+
eventVariantExamples: schema.eventVariantExamples,
|
|
78
|
+
configFields: schema.configFields,
|
|
79
|
+
hostType: identity.hostType,
|
|
80
|
+
sourceKind: identity.sourceKind,
|
|
81
|
+
implementationId: identity.implementationId,
|
|
82
|
+
...(capabilityMetadata?.aliases?.length ? { aliases: capabilityMetadata.aliases } : {}),
|
|
83
|
+
...(capabilityMetadata ? {
|
|
84
|
+
subscriptionSchema: {
|
|
85
|
+
supportsTrackedResourceRef: capabilityMetadata.supportsTrackedResourceRef ?? false,
|
|
86
|
+
supportsLifecycleSignals: capabilityMetadata.supportsLifecycleSignals ?? false,
|
|
87
|
+
shortcuts: capabilityMetadata.shortcuts ?? [],
|
|
88
|
+
},
|
|
89
|
+
} : {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function profileInputSource(source) {
|
|
93
|
+
if (source.sourceType !== "remote_source") {
|
|
94
|
+
return source;
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
...source,
|
|
98
|
+
config: (0, remote_profiles_1.profileConfigForSource)(source),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -32,6 +32,7 @@ const SOURCE_SCHEMAS = {
|
|
|
32
32
|
{ name: "action", type: "string", description: "GitHub event action suffix such as created." },
|
|
33
33
|
{ name: "author", type: "string|null", description: "Actor login for the event." },
|
|
34
34
|
{ name: "isPullRequest", type: "boolean", description: "Whether the event targets a pull request surface." },
|
|
35
|
+
{ name: "reviewState", type: "string|null", description: "Review decision state for PullRequestReviewEvent such as approved or changes_requested." },
|
|
35
36
|
{ name: "labels", type: "string[]", description: "Labels extracted from the issue or pull request." },
|
|
36
37
|
{ name: "mentions", type: "string[]", description: "Mention handles extracted from title/body/comment text." },
|
|
37
38
|
{ name: "number", type: "number|null", description: "Issue or pull request number when present." },
|
|
@@ -49,8 +50,29 @@ const SOURCE_SCHEMAS = {
|
|
|
49
50
|
issue: { number: 12, title: "Track filtering work" },
|
|
50
51
|
comment: { body: "@alpha please look" },
|
|
51
52
|
},
|
|
53
|
+
{
|
|
54
|
+
id: "1234567891",
|
|
55
|
+
type: "PullRequestReviewEvent",
|
|
56
|
+
action: "created",
|
|
57
|
+
actor: "Copilot",
|
|
58
|
+
pull_request: { number: 67, title: "feat: add remote module capability hooks" },
|
|
59
|
+
review: { state: "commented", body: "review summary" },
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "1234567892",
|
|
63
|
+
type: "PullRequestEvent",
|
|
64
|
+
action: "closed",
|
|
65
|
+
actor: "jolestar",
|
|
66
|
+
pull_request: { number: 72, title: "feat: add cleanup policy lifecycle engine", merged: true },
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
eventVariantExamples: [
|
|
70
|
+
"IssueCommentEvent.created",
|
|
71
|
+
"PullRequestEvent.opened",
|
|
72
|
+
"PullRequestEvent.closed",
|
|
73
|
+
"PullRequestReviewEvent.created",
|
|
74
|
+
"PullRequestReviewCommentEvent.created",
|
|
52
75
|
],
|
|
53
|
-
eventVariantExamples: ["IssueCommentEvent.created", "PullRequestEvent.opened", "PullRequestReviewCommentEvent.created"],
|
|
54
76
|
configFields: [
|
|
55
77
|
{ name: "owner", type: "string", required: true, description: "GitHub repository owner." },
|
|
56
78
|
{ name: "repo", type: "string", required: true, description: "GitHub repository name." },
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GithubDeliveryAdapter = exports.GithubUxcClient = exports.DEFAULT_GITHUB_EVENT_TYPES = exports.GITHUB_ENDPOINT = void 0;
|
|
4
4
|
exports.normalizeGithubRepoEvent = normalizeGithubRepoEvent;
|
|
5
|
+
exports.deriveGithubTrackedResource = deriveGithubTrackedResource;
|
|
6
|
+
exports.githubSubscriptionShortcutSpec = githubSubscriptionShortcutSpec;
|
|
7
|
+
exports.expandGithubSubscriptionShortcut = expandGithubSubscriptionShortcut;
|
|
8
|
+
exports.projectGithubLifecycleSignal = projectGithubLifecycleSignal;
|
|
5
9
|
exports.parseGithubSourceConfig = parseGithubSourceConfig;
|
|
6
10
|
const uxc_daemon_client_1 = require("@holon-run/uxc-daemon-client");
|
|
7
11
|
exports.GITHUB_ENDPOINT = "https://api.github.com";
|
|
@@ -9,6 +13,7 @@ exports.DEFAULT_GITHUB_EVENT_TYPES = [
|
|
|
9
13
|
"IssuesEvent",
|
|
10
14
|
"IssueCommentEvent",
|
|
11
15
|
"PullRequestEvent",
|
|
16
|
+
"PullRequestReviewEvent",
|
|
12
17
|
"PullRequestReviewCommentEvent",
|
|
13
18
|
];
|
|
14
19
|
class GithubUxcClient {
|
|
@@ -97,15 +102,18 @@ function normalizeGithubRepoEvent(source, config, raw) {
|
|
|
97
102
|
const repo = asRecord(event.repo);
|
|
98
103
|
const issue = asRecord(payload.issue);
|
|
99
104
|
const pullRequest = asRecord(payload.pull_request);
|
|
105
|
+
const review = asRecord(payload.review);
|
|
100
106
|
const comment = asRecord(payload.comment);
|
|
101
107
|
const action = asString(payload.action) ?? "observed";
|
|
102
108
|
const number = asNumber(issue.number) ?? asNumber(pullRequest.number);
|
|
103
109
|
const isPullRequest = eventType.startsWith("PullRequest");
|
|
104
110
|
const title = asString(issue.title) ?? asString(pullRequest.title) ?? null;
|
|
105
|
-
const
|
|
111
|
+
const reviewState = asString(review.state) ?? null;
|
|
112
|
+
const body = asString(comment.body) ?? asString(review.body) ?? asString(issue.body) ?? asString(pullRequest.body) ?? null;
|
|
106
113
|
const labels = extractLabels(issue.labels);
|
|
107
114
|
const mentions = extractMentions(title, body);
|
|
108
115
|
const url = asString(comment.html_url) ??
|
|
116
|
+
asString(review.html_url) ??
|
|
109
117
|
asString(issue.html_url) ??
|
|
110
118
|
asString(pullRequest.html_url) ??
|
|
111
119
|
asString(event.url);
|
|
@@ -125,6 +133,7 @@ function normalizeGithubRepoEvent(source, config, raw) {
|
|
|
125
133
|
number,
|
|
126
134
|
author: asString(actor.login) ?? null,
|
|
127
135
|
isPullRequest,
|
|
136
|
+
reviewState,
|
|
128
137
|
labels,
|
|
129
138
|
mentions,
|
|
130
139
|
title,
|
|
@@ -138,11 +147,71 @@ function normalizeGithubRepoEvent(source, config, raw) {
|
|
|
138
147
|
actor: actor.login ?? null,
|
|
139
148
|
issue,
|
|
140
149
|
pull_request: pullRequest,
|
|
150
|
+
review,
|
|
141
151
|
comment,
|
|
152
|
+
merged: asBoolean(pullRequest.merged),
|
|
142
153
|
},
|
|
143
154
|
deliveryHandle,
|
|
144
155
|
};
|
|
145
156
|
}
|
|
157
|
+
function deriveGithubTrackedResource(filter) {
|
|
158
|
+
const metadata = asRecord(filter.metadata);
|
|
159
|
+
const payload = asRecord(filter.payload);
|
|
160
|
+
const number = asNumber(metadata.number) ?? asNumber(payload.number) ?? asNumber(payload.ref);
|
|
161
|
+
const isPullRequest = asBoolean(metadata.isPullRequest);
|
|
162
|
+
if (!number || isPullRequest !== true) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return { ref: `pr:${number}` };
|
|
166
|
+
}
|
|
167
|
+
function githubSubscriptionShortcutSpec() {
|
|
168
|
+
return [{
|
|
169
|
+
name: "pr",
|
|
170
|
+
description: "Follow one pull request and auto-retire when it closes.",
|
|
171
|
+
argsSchema: [{ name: "number", type: "number", required: true, description: "Pull request number." }],
|
|
172
|
+
}];
|
|
173
|
+
}
|
|
174
|
+
function expandGithubSubscriptionShortcut(input) {
|
|
175
|
+
if (input.name !== "pr") {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
const number = typeof input.args?.number === "number" ? input.args.number : null;
|
|
179
|
+
if (!number || !Number.isInteger(number) || number <= 0) {
|
|
180
|
+
throw new Error("subscription shortcut pr requires a positive integer number");
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
filter: {
|
|
184
|
+
metadata: {
|
|
185
|
+
number,
|
|
186
|
+
isPullRequest: true,
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
trackedResourceRef: `pr:${number}`,
|
|
190
|
+
cleanupPolicy: { mode: "on_terminal" },
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function projectGithubLifecycleSignal(rawPayload) {
|
|
194
|
+
const eventType = asString(rawPayload.type);
|
|
195
|
+
if (eventType !== "PullRequestEvent") {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
const action = asString(rawPayload.action);
|
|
199
|
+
if (action !== "closed" && action !== "merged") {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const pullRequest = asRecord(rawPayload.pull_request);
|
|
203
|
+
const number = asNumber(pullRequest.number);
|
|
204
|
+
if (!number) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const merged = action === "merged" || asBoolean(rawPayload.merged) === true || asBoolean(pullRequest.merged) === true;
|
|
208
|
+
return {
|
|
209
|
+
ref: `pr:${number}`,
|
|
210
|
+
terminal: true,
|
|
211
|
+
state: "closed",
|
|
212
|
+
result: merged ? "merged" : "closed",
|
|
213
|
+
};
|
|
214
|
+
}
|
|
146
215
|
function buildGithubDeliveryHandle(config, eventType, number, comment) {
|
|
147
216
|
if (!number) {
|
|
148
217
|
return null;
|
|
@@ -243,6 +312,9 @@ function asString(value) {
|
|
|
243
312
|
function asNumber(value) {
|
|
244
313
|
return typeof value === "number" ? value : null;
|
|
245
314
|
}
|
|
315
|
+
function asBoolean(value) {
|
|
316
|
+
return typeof value === "boolean" ? value : null;
|
|
317
|
+
}
|
|
246
318
|
function asStringArray(value) {
|
|
247
319
|
if (!Array.isArray(value)) {
|
|
248
320
|
return null;
|
|
@@ -167,6 +167,30 @@ class RemoteSourceRuntime {
|
|
|
167
167
|
erroredSourceIds: Array.from(this.errorCounts.keys()).sort(),
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
|
+
async projectLifecycleSignal(source, rawPayload) {
|
|
171
|
+
if (!REMOTE_SOURCE_TYPES.has(source.sourceType)) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
const profile = await this.profileRegistry.resolve(source, this.homeDir);
|
|
175
|
+
if (typeof profile.projectLifecycleSignal !== "function") {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
return profile.projectLifecycleSignal(rawPayload, profileInputSource(source));
|
|
179
|
+
}
|
|
180
|
+
async expandSubscriptionShortcut(source, input) {
|
|
181
|
+
if (!REMOTE_SOURCE_TYPES.has(source.sourceType)) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
const profile = await this.profileRegistry.resolve(source, this.homeDir);
|
|
185
|
+
if (typeof profile.expandSubscriptionShortcut !== "function") {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
return profile.expandSubscriptionShortcut({
|
|
189
|
+
name: input.name,
|
|
190
|
+
args: input.args,
|
|
191
|
+
source: profileInputSource(source),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
170
194
|
async syncAll() {
|
|
171
195
|
const sources = this.store
|
|
172
196
|
.listSources()
|
|
@@ -90,6 +90,16 @@ function validateProfileContract(profile, sourcePath) {
|
|
|
90
90
|
if (typeof profile.mapRawEvent !== "function") {
|
|
91
91
|
throw new Error(`remote_source profile missing mapRawEvent(): ${sourcePath}`);
|
|
92
92
|
}
|
|
93
|
+
validateOptionalHook(profile.describeCapabilities, "describeCapabilities", sourcePath);
|
|
94
|
+
validateOptionalHook(profile.listSubscriptionShortcuts, "listSubscriptionShortcuts", sourcePath);
|
|
95
|
+
validateOptionalHook(profile.expandSubscriptionShortcut, "expandSubscriptionShortcut", sourcePath);
|
|
96
|
+
validateOptionalHook(profile.deriveTrackedResource, "deriveTrackedResource", sourcePath);
|
|
97
|
+
validateOptionalHook(profile.projectLifecycleSignal, "projectLifecycleSignal", sourcePath);
|
|
98
|
+
}
|
|
99
|
+
function validateOptionalHook(value, name, sourcePath) {
|
|
100
|
+
if (value !== undefined && typeof value !== "function") {
|
|
101
|
+
throw new Error(`remote_source profile ${name} must be a function when provided: ${sourcePath}`);
|
|
102
|
+
}
|
|
93
103
|
}
|
|
94
104
|
function resolveAndValidateProfilePath(profileRoot, profilePath) {
|
|
95
105
|
const resolved = node_path_1.default.isAbsolute(profilePath)
|
|
@@ -120,6 +130,71 @@ function asNonEmptyString(value) {
|
|
|
120
130
|
}
|
|
121
131
|
const GITHUB_REPO_PROFILE = {
|
|
122
132
|
id: "builtin.github_repo",
|
|
133
|
+
describeCapabilities(source) {
|
|
134
|
+
const config = (0, github_1.parseGithubSourceConfig)(source);
|
|
135
|
+
return {
|
|
136
|
+
sourceKind: "github_repo",
|
|
137
|
+
aliases: ["github_repo"],
|
|
138
|
+
configSchema: [
|
|
139
|
+
{ name: "owner", type: "string", required: true, description: "GitHub repository owner." },
|
|
140
|
+
{ name: "repo", type: "string", required: true, description: "GitHub repository name." },
|
|
141
|
+
{ name: "uxcAuth", type: "string", required: false, description: "Optional uxc auth profile." },
|
|
142
|
+
{ name: "eventTypes", type: "string[]", required: false, description: "Optional GitHub event type allowlist." },
|
|
143
|
+
{ name: "perPage", type: "number", required: false, description: `Repository events requested per poll. Default ${config.perPage ?? 10}.` },
|
|
144
|
+
{ name: "pollIntervalSecs", type: "number", required: false, description: `Polling interval in seconds. Default ${config.pollIntervalSecs ?? 30}.` },
|
|
145
|
+
],
|
|
146
|
+
metadataFields: [
|
|
147
|
+
{ name: "eventType", type: "string", description: "GitHub event type such as IssueCommentEvent." },
|
|
148
|
+
{ name: "action", type: "string", description: "GitHub event action suffix such as created." },
|
|
149
|
+
{ name: "author", type: "string|null", description: "Actor login for the event." },
|
|
150
|
+
{ name: "isPullRequest", type: "boolean", description: "Whether the event targets a pull request surface." },
|
|
151
|
+
{ name: "reviewState", type: "string|null", description: "Review decision state for PullRequestReviewEvent such as approved or changes_requested." },
|
|
152
|
+
{ name: "labels", type: "string[]", description: "Labels extracted from the issue or pull request." },
|
|
153
|
+
{ name: "mentions", type: "string[]", description: "Mention handles extracted from title/body/comment text." },
|
|
154
|
+
{ name: "number", type: "number|null", description: "Issue or pull request number when present." },
|
|
155
|
+
{ name: "repoFullName", type: "string", description: "Repository full name in owner/repo form." },
|
|
156
|
+
{ name: "title", type: "string|null", description: "Issue, pull request, or comment title." },
|
|
157
|
+
{ name: "body", type: "string|null", description: "Issue, pull request, or comment body text." },
|
|
158
|
+
{ name: "url", type: "string|null", description: "Primary GitHub HTML URL for the event target." },
|
|
159
|
+
],
|
|
160
|
+
payloadExamples: [
|
|
161
|
+
{
|
|
162
|
+
id: "1234567891",
|
|
163
|
+
type: "PullRequestReviewEvent",
|
|
164
|
+
action: "created",
|
|
165
|
+
actor: "Copilot",
|
|
166
|
+
pull_request: { number: 67, title: "feat: add remote module capability hooks" },
|
|
167
|
+
review: { state: "commented", body: "review summary" },
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: "1234567892",
|
|
171
|
+
type: "PullRequestEvent",
|
|
172
|
+
action: "closed",
|
|
173
|
+
actor: "jolestar",
|
|
174
|
+
pull_request: { number: 72, title: "feat: add cleanup policy lifecycle engine", merged: true },
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
eventVariantExamples: [
|
|
178
|
+
"IssueCommentEvent.created",
|
|
179
|
+
"PullRequestEvent.opened",
|
|
180
|
+
"PullRequestEvent.closed",
|
|
181
|
+
"PullRequestReviewEvent.created",
|
|
182
|
+
"PullRequestReviewCommentEvent.created",
|
|
183
|
+
],
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
listSubscriptionShortcuts() {
|
|
187
|
+
return (0, github_1.githubSubscriptionShortcutSpec)();
|
|
188
|
+
},
|
|
189
|
+
expandSubscriptionShortcut(input) {
|
|
190
|
+
return (0, github_1.expandGithubSubscriptionShortcut)(input);
|
|
191
|
+
},
|
|
192
|
+
deriveTrackedResource(filter) {
|
|
193
|
+
return (0, github_1.deriveGithubTrackedResource)(filter);
|
|
194
|
+
},
|
|
195
|
+
projectLifecycleSignal(rawPayload) {
|
|
196
|
+
return (0, github_1.projectGithubLifecycleSignal)(rawPayload);
|
|
197
|
+
},
|
|
123
198
|
validateConfig(source) {
|
|
124
199
|
(0, github_1.parseGithubSourceConfig)(source);
|
|
125
200
|
},
|
|
@@ -164,6 +239,34 @@ const GITHUB_REPO_PROFILE = {
|
|
|
164
239
|
};
|
|
165
240
|
const GITHUB_REPO_CI_PROFILE = {
|
|
166
241
|
id: "builtin.github_repo_ci",
|
|
242
|
+
describeCapabilities() {
|
|
243
|
+
return {
|
|
244
|
+
sourceKind: "github_repo_ci",
|
|
245
|
+
aliases: ["github_repo_ci"],
|
|
246
|
+
configSchema: [
|
|
247
|
+
{ name: "owner", type: "string", required: true, description: "GitHub repository owner." },
|
|
248
|
+
{ name: "repo", type: "string", required: true, description: "GitHub repository name." },
|
|
249
|
+
{ name: "uxcAuth", type: "string", required: false, description: "Optional uxc auth profile." },
|
|
250
|
+
{ name: "pollIntervalSecs", type: "number", required: false, description: "Polling interval in seconds." },
|
|
251
|
+
{ name: "perPage", type: "number", required: false, description: "Workflow runs requested per poll." },
|
|
252
|
+
{ name: "eventFilter", type: "string", required: false, description: "Optional GitHub workflow event filter." },
|
|
253
|
+
{ name: "branch", type: "string", required: false, description: "Optional branch filter for workflow runs." },
|
|
254
|
+
{ name: "statusFilter", type: "string", required: false, description: "Optional workflow status filter." },
|
|
255
|
+
],
|
|
256
|
+
metadataFields: [
|
|
257
|
+
{ name: "name", type: "string|null", description: "Workflow run name." },
|
|
258
|
+
{ name: "status", type: "string", description: "Normalized workflow run status." },
|
|
259
|
+
{ name: "conclusion", type: "string|null", description: "Workflow run conclusion when completed." },
|
|
260
|
+
{ name: "event", type: "string|null", description: "GitHub trigger event for the workflow run." },
|
|
261
|
+
{ name: "headBranch", type: "string|null", description: "Head branch for the workflow run." },
|
|
262
|
+
{ name: "headSha", type: "string|null", description: "Head commit SHA for the workflow run." },
|
|
263
|
+
{ name: "actor", type: "string|null", description: "Actor login for the workflow run." },
|
|
264
|
+
{ name: "commitMessage", type: "string|null", description: "Head commit message when present." },
|
|
265
|
+
{ name: "htmlUrl", type: "string|null", description: "GitHub Actions run URL." },
|
|
266
|
+
],
|
|
267
|
+
eventVariantExamples: ["workflow_run.ci.completed.failure", "workflow_run.nightly_checks.observed"],
|
|
268
|
+
};
|
|
269
|
+
},
|
|
167
270
|
validateConfig(source) {
|
|
168
271
|
(0, github_ci_1.parseGithubCiSourceConfig)(source);
|
|
169
272
|
},
|
|
@@ -217,6 +320,36 @@ const GITHUB_REPO_CI_PROFILE = {
|
|
|
217
320
|
};
|
|
218
321
|
const FEISHU_BOT_PROFILE = {
|
|
219
322
|
id: "builtin.feishu_bot",
|
|
323
|
+
describeCapabilities() {
|
|
324
|
+
return {
|
|
325
|
+
sourceKind: "feishu_bot",
|
|
326
|
+
aliases: ["feishu_bot"],
|
|
327
|
+
configSchema: [
|
|
328
|
+
{ name: "appId", type: "string", required: true, description: "Feishu app ID." },
|
|
329
|
+
{ name: "appSecret", type: "string", required: true, description: "Feishu app secret." },
|
|
330
|
+
{ name: "eventTypes", type: "string[]", required: false, description: "Optional Feishu event type allowlist." },
|
|
331
|
+
{ name: "chatIds", type: "string[]", required: false, description: "Optional Feishu chat allowlist." },
|
|
332
|
+
{ name: "schemaUrl", type: "string", required: false, description: "Optional Feishu OpenAPI schema URL." },
|
|
333
|
+
{ name: "replyInThread", type: "boolean", required: false, description: "Reply in thread when sending outbound messages." },
|
|
334
|
+
{ name: "uxcAuth", type: "string", required: false, description: "Optional uxc auth profile." },
|
|
335
|
+
],
|
|
336
|
+
metadataFields: [
|
|
337
|
+
{ name: "eventType", type: "string", description: "Feishu event type." },
|
|
338
|
+
{ name: "chatId", type: "string", description: "Target chat ID." },
|
|
339
|
+
{ name: "chatType", type: "string|null", description: "Feishu chat type." },
|
|
340
|
+
{ name: "messageId", type: "string", description: "Feishu message ID." },
|
|
341
|
+
{ name: "messageType", type: "string", description: "Feishu message type such as text." },
|
|
342
|
+
{ name: "senderOpenId", type: "string|null", description: "Sender open_id when present." },
|
|
343
|
+
{ name: "senderType", type: "string|null", description: "Sender type." },
|
|
344
|
+
{ name: "mentions", type: "string[]", description: "Mention names extracted from the message." },
|
|
345
|
+
{ name: "mentionOpenIds", type: "string[]", description: "Mention open_ids extracted from the message." },
|
|
346
|
+
{ name: "content", type: "string|null", description: "Normalized message content string." },
|
|
347
|
+
{ name: "threadId", type: "string|null", description: "Thread or root message ID when present." },
|
|
348
|
+
{ name: "parentId", type: "string|null", description: "Parent message ID when present." },
|
|
349
|
+
],
|
|
350
|
+
eventVariantExamples: ["im.message.receive_v1.text"],
|
|
351
|
+
};
|
|
352
|
+
},
|
|
220
353
|
validateConfig(source) {
|
|
221
354
|
(0, feishu_1.parseFeishuSourceConfig)(source);
|
|
222
355
|
},
|