agent-relay 2.0.23 → 2.0.25
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/dist/src/cli/index.js +160 -17
- package/package.json +18 -52
- package/packages/api-types/package.json +1 -1
- package/packages/bridge/package.json +8 -8
- package/packages/cli-tester/package.json +1 -1
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +1 -1
- package/packages/daemon/package.json +12 -12
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/package.json +1 -1
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/package.json +2 -2
- package/packages/spawner/package.json +1 -1
- package/packages/state/package.json +1 -1
- package/packages/storage/package.json +2 -2
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/package.json +1 -1
- package/packages/wrapper/package.json +6 -6
- package/deploy/init-db.sql +0 -5
- package/deploy/scripts/setup-fly-workspaces.sh +0 -69
- package/deploy/scripts/setup-railway.sh +0 -75
- package/dist/src/cloud/index.d.ts +0 -8
- package/dist/src/cloud/index.js +0 -8
- package/packages/cloud/dist/api/admin.d.ts +0 -8
- package/packages/cloud/dist/api/admin.js +0 -225
- package/packages/cloud/dist/api/auth.d.ts +0 -20
- package/packages/cloud/dist/api/auth.js +0 -138
- package/packages/cloud/dist/api/billing.d.ts +0 -7
- package/packages/cloud/dist/api/billing.js +0 -564
- package/packages/cloud/dist/api/cli-pty-runner.d.ts +0 -53
- package/packages/cloud/dist/api/cli-pty-runner.js +0 -175
- package/packages/cloud/dist/api/codex-auth-helper.d.ts +0 -21
- package/packages/cloud/dist/api/codex-auth-helper.js +0 -327
- package/packages/cloud/dist/api/consensus.d.ts +0 -13
- package/packages/cloud/dist/api/consensus.js +0 -261
- package/packages/cloud/dist/api/coordinators.d.ts +0 -8
- package/packages/cloud/dist/api/coordinators.js +0 -750
- package/packages/cloud/dist/api/daemons.d.ts +0 -12
- package/packages/cloud/dist/api/daemons.js +0 -535
- package/packages/cloud/dist/api/email-auth.d.ts +0 -11
- package/packages/cloud/dist/api/email-auth.js +0 -347
- package/packages/cloud/dist/api/generic-webhooks.d.ts +0 -8
- package/packages/cloud/dist/api/generic-webhooks.js +0 -129
- package/packages/cloud/dist/api/git.d.ts +0 -8
- package/packages/cloud/dist/api/git.js +0 -269
- package/packages/cloud/dist/api/github-app.d.ts +0 -11
- package/packages/cloud/dist/api/github-app.js +0 -223
- package/packages/cloud/dist/api/middleware/planLimits.d.ts +0 -43
- package/packages/cloud/dist/api/middleware/planLimits.js +0 -202
- package/packages/cloud/dist/api/monitoring.d.ts +0 -11
- package/packages/cloud/dist/api/monitoring.js +0 -578
- package/packages/cloud/dist/api/nango-auth.d.ts +0 -9
- package/packages/cloud/dist/api/nango-auth.js +0 -741
- package/packages/cloud/dist/api/onboarding.d.ts +0 -15
- package/packages/cloud/dist/api/onboarding.js +0 -679
- package/packages/cloud/dist/api/policy.d.ts +0 -8
- package/packages/cloud/dist/api/policy.js +0 -229
- package/packages/cloud/dist/api/provider-env.d.ts +0 -26
- package/packages/cloud/dist/api/provider-env.js +0 -141
- package/packages/cloud/dist/api/providers.d.ts +0 -7
- package/packages/cloud/dist/api/providers.js +0 -574
- package/packages/cloud/dist/api/repos.d.ts +0 -8
- package/packages/cloud/dist/api/repos.js +0 -577
- package/packages/cloud/dist/api/sessions.d.ts +0 -11
- package/packages/cloud/dist/api/sessions.js +0 -302
- package/packages/cloud/dist/api/teams.d.ts +0 -7
- package/packages/cloud/dist/api/teams.js +0 -281
- package/packages/cloud/dist/api/test-helpers.d.ts +0 -10
- package/packages/cloud/dist/api/test-helpers.js +0 -745
- package/packages/cloud/dist/api/usage.d.ts +0 -7
- package/packages/cloud/dist/api/usage.js +0 -111
- package/packages/cloud/dist/api/webhooks.d.ts +0 -8
- package/packages/cloud/dist/api/webhooks.js +0 -645
- package/packages/cloud/dist/api/workspaces.d.ts +0 -25
- package/packages/cloud/dist/api/workspaces.js +0 -1799
- package/packages/cloud/dist/billing/index.d.ts +0 -9
- package/packages/cloud/dist/billing/index.js +0 -9
- package/packages/cloud/dist/billing/plans.d.ts +0 -39
- package/packages/cloud/dist/billing/plans.js +0 -245
- package/packages/cloud/dist/billing/service.d.ts +0 -80
- package/packages/cloud/dist/billing/service.js +0 -388
- package/packages/cloud/dist/billing/types.d.ts +0 -141
- package/packages/cloud/dist/billing/types.js +0 -7
- package/packages/cloud/dist/config.d.ts +0 -5
- package/packages/cloud/dist/config.js +0 -5
- package/packages/cloud/dist/db/bulk-ingest.d.ts +0 -89
- package/packages/cloud/dist/db/bulk-ingest.js +0 -268
- package/packages/cloud/dist/db/drizzle.d.ts +0 -290
- package/packages/cloud/dist/db/drizzle.js +0 -1422
- package/packages/cloud/dist/db/index.d.ts +0 -56
- package/packages/cloud/dist/db/index.js +0 -70
- package/packages/cloud/dist/db/schema.d.ts +0 -5117
- package/packages/cloud/dist/db/schema.js +0 -656
- package/packages/cloud/dist/index.d.ts +0 -11
- package/packages/cloud/dist/index.js +0 -38
- package/packages/cloud/dist/provisioner/index.d.ts +0 -207
- package/packages/cloud/dist/provisioner/index.js +0 -2118
- package/packages/cloud/dist/server.d.ts +0 -17
- package/packages/cloud/dist/server.js +0 -2055
- package/packages/cloud/dist/services/auto-scaler.d.ts +0 -152
- package/packages/cloud/dist/services/auto-scaler.js +0 -439
- package/packages/cloud/dist/services/capacity-manager.d.ts +0 -148
- package/packages/cloud/dist/services/capacity-manager.js +0 -449
- package/packages/cloud/dist/services/ci-agent-spawner.d.ts +0 -49
- package/packages/cloud/dist/services/ci-agent-spawner.js +0 -373
- package/packages/cloud/dist/services/cloud-message-bus.d.ts +0 -28
- package/packages/cloud/dist/services/cloud-message-bus.js +0 -19
- package/packages/cloud/dist/services/compute-enforcement.d.ts +0 -57
- package/packages/cloud/dist/services/compute-enforcement.js +0 -175
- package/packages/cloud/dist/services/coordinator.d.ts +0 -62
- package/packages/cloud/dist/services/coordinator.js +0 -389
- package/packages/cloud/dist/services/index.d.ts +0 -17
- package/packages/cloud/dist/services/index.js +0 -25
- package/packages/cloud/dist/services/intro-expiration.d.ts +0 -60
- package/packages/cloud/dist/services/intro-expiration.js +0 -252
- package/packages/cloud/dist/services/mention-handler.d.ts +0 -65
- package/packages/cloud/dist/services/mention-handler.js +0 -405
- package/packages/cloud/dist/services/nango.d.ts +0 -219
- package/packages/cloud/dist/services/nango.js +0 -424
- package/packages/cloud/dist/services/persistence.d.ts +0 -131
- package/packages/cloud/dist/services/persistence.js +0 -200
- package/packages/cloud/dist/services/planLimits.d.ts +0 -147
- package/packages/cloud/dist/services/planLimits.js +0 -335
- package/packages/cloud/dist/services/presence-registry.d.ts +0 -56
- package/packages/cloud/dist/services/presence-registry.js +0 -91
- package/packages/cloud/dist/services/scaling-orchestrator.d.ts +0 -159
- package/packages/cloud/dist/services/scaling-orchestrator.js +0 -502
- package/packages/cloud/dist/services/scaling-policy.d.ts +0 -121
- package/packages/cloud/dist/services/scaling-policy.js +0 -415
- package/packages/cloud/dist/services/ssh-security.d.ts +0 -31
- package/packages/cloud/dist/services/ssh-security.js +0 -63
- package/packages/cloud/dist/services/workspace-keepalive.d.ts +0 -76
- package/packages/cloud/dist/services/workspace-keepalive.js +0 -234
- package/packages/cloud/dist/shims/consensus.d.ts +0 -23
- package/packages/cloud/dist/shims/consensus.js +0 -5
- package/packages/cloud/dist/webhooks/index.d.ts +0 -24
- package/packages/cloud/dist/webhooks/index.js +0 -29
- package/packages/cloud/dist/webhooks/parsers/github.d.ts +0 -8
- package/packages/cloud/dist/webhooks/parsers/github.js +0 -234
- package/packages/cloud/dist/webhooks/parsers/index.d.ts +0 -23
- package/packages/cloud/dist/webhooks/parsers/index.js +0 -30
- package/packages/cloud/dist/webhooks/parsers/linear.d.ts +0 -9
- package/packages/cloud/dist/webhooks/parsers/linear.js +0 -258
- package/packages/cloud/dist/webhooks/parsers/slack.d.ts +0 -9
- package/packages/cloud/dist/webhooks/parsers/slack.js +0 -214
- package/packages/cloud/dist/webhooks/responders/github.d.ts +0 -8
- package/packages/cloud/dist/webhooks/responders/github.js +0 -73
- package/packages/cloud/dist/webhooks/responders/index.d.ts +0 -23
- package/packages/cloud/dist/webhooks/responders/index.js +0 -30
- package/packages/cloud/dist/webhooks/responders/linear.d.ts +0 -9
- package/packages/cloud/dist/webhooks/responders/linear.js +0 -149
- package/packages/cloud/dist/webhooks/responders/slack.d.ts +0 -20
- package/packages/cloud/dist/webhooks/responders/slack.js +0 -178
- package/packages/cloud/dist/webhooks/router.d.ts +0 -25
- package/packages/cloud/dist/webhooks/router.js +0 -504
- package/packages/cloud/dist/webhooks/rules-engine.d.ts +0 -24
- package/packages/cloud/dist/webhooks/rules-engine.js +0 -287
- package/packages/cloud/dist/webhooks/types.d.ts +0 -186
- package/packages/cloud/dist/webhooks/types.js +0 -8
- package/packages/cloud/package.json +0 -60
- package/scripts/run-migrations.js +0 -43
- package/scripts/setup-stripe-products.ts +0 -312
- package/scripts/verify-schema.js +0 -134
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Linear Webhook Parser
|
|
3
|
-
*
|
|
4
|
-
* Transforms Linear webhook payloads into normalized events.
|
|
5
|
-
* Linear webhooks: https://developers.linear.app/docs/graphql/webhooks
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Extract @mentions from text (Linear uses @username format)
|
|
9
|
-
*/
|
|
10
|
-
function extractMentions(text) {
|
|
11
|
-
if (!text)
|
|
12
|
-
return [];
|
|
13
|
-
const mentionPattern = /@([a-zA-Z][a-zA-Z0-9_-]*)/g;
|
|
14
|
-
const mentions = [];
|
|
15
|
-
let match;
|
|
16
|
-
while ((match = mentionPattern.exec(text)) !== null) {
|
|
17
|
-
mentions.push(match[1].toLowerCase());
|
|
18
|
-
}
|
|
19
|
-
return [...new Set(mentions)];
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Map Linear priority to normalized priority
|
|
23
|
-
* Linear: 0 = No priority, 1 = Urgent, 2 = High, 3 = Normal, 4 = Low
|
|
24
|
-
*/
|
|
25
|
-
function mapPriority(priority) {
|
|
26
|
-
switch (priority) {
|
|
27
|
-
case 1: return 'critical';
|
|
28
|
-
case 2: return 'high';
|
|
29
|
-
case 3: return 'medium';
|
|
30
|
-
case 4: return 'low';
|
|
31
|
-
default: return undefined;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
export const linearParser = {
|
|
35
|
-
id: 'linear',
|
|
36
|
-
parse(payload) {
|
|
37
|
-
const data = payload;
|
|
38
|
-
const events = [];
|
|
39
|
-
const action = data.action; // create, update, remove
|
|
40
|
-
const type = data.type; // Issue, Comment, Project, etc.
|
|
41
|
-
const webhookData = data.data;
|
|
42
|
-
const webhookId = data.webhookId;
|
|
43
|
-
const createdAt = data.createdAt;
|
|
44
|
-
if (!webhookData)
|
|
45
|
-
return events;
|
|
46
|
-
const baseEvent = {
|
|
47
|
-
id: webhookId || `linear-${Date.now()}`,
|
|
48
|
-
source: 'linear',
|
|
49
|
-
timestamp: createdAt ? new Date(createdAt) : new Date(),
|
|
50
|
-
actor: {
|
|
51
|
-
id: 'unknown',
|
|
52
|
-
name: 'unknown',
|
|
53
|
-
},
|
|
54
|
-
context: {
|
|
55
|
-
name: 'unknown',
|
|
56
|
-
},
|
|
57
|
-
labels: [],
|
|
58
|
-
mentions: [],
|
|
59
|
-
metadata: {},
|
|
60
|
-
rawPayload: payload,
|
|
61
|
-
};
|
|
62
|
-
// Extract actor from various fields
|
|
63
|
-
const creator = webhookData.creator;
|
|
64
|
-
const user = webhookData.user;
|
|
65
|
-
const actor = creator || user;
|
|
66
|
-
if (actor) {
|
|
67
|
-
baseEvent.actor = {
|
|
68
|
-
id: String(actor.id || 'unknown'),
|
|
69
|
-
name: String(actor.name || actor.email || 'unknown'),
|
|
70
|
-
email: actor.email,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
// Extract team/project context
|
|
74
|
-
const team = webhookData.team;
|
|
75
|
-
const project = webhookData.project;
|
|
76
|
-
if (team) {
|
|
77
|
-
baseEvent.context = {
|
|
78
|
-
name: String(team.key || team.name || 'unknown'),
|
|
79
|
-
url: `https://linear.app/team/${team.key}`,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
else if (project) {
|
|
83
|
-
baseEvent.context = {
|
|
84
|
-
name: String(project.name || 'unknown'),
|
|
85
|
-
url: project.url,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
switch (type) {
|
|
89
|
-
case 'Issue': {
|
|
90
|
-
const issue = webhookData;
|
|
91
|
-
const labels = (issue.labels || []);
|
|
92
|
-
const labelNames = labels.map(l => String(l.name));
|
|
93
|
-
const assignee = issue.assignee;
|
|
94
|
-
if (action === 'create') {
|
|
95
|
-
events.push({
|
|
96
|
-
...baseEvent,
|
|
97
|
-
type: 'issue_created',
|
|
98
|
-
item: {
|
|
99
|
-
type: 'ticket',
|
|
100
|
-
id: String(issue.id),
|
|
101
|
-
number: issue.number,
|
|
102
|
-
title: String(issue.title || ''),
|
|
103
|
-
body: String(issue.description || ''),
|
|
104
|
-
url: String(issue.url || ''),
|
|
105
|
-
state: String(issue.state?.name || issue.state || 'unknown'),
|
|
106
|
-
},
|
|
107
|
-
labels: labelNames,
|
|
108
|
-
priority: mapPriority(issue.priority),
|
|
109
|
-
mentions: extractMentions(issue.description),
|
|
110
|
-
metadata: {
|
|
111
|
-
action,
|
|
112
|
-
identifier: issue.identifier, // e.g., "ENG-123"
|
|
113
|
-
estimate: issue.estimate,
|
|
114
|
-
dueDate: issue.dueDate,
|
|
115
|
-
assignee: assignee?.name,
|
|
116
|
-
assigneeEmail: assignee?.email,
|
|
117
|
-
cycle: issue.cycle?.name,
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
else if (action === 'update') {
|
|
122
|
-
// Check for assignment changes
|
|
123
|
-
const updatedFrom = data.updatedFrom;
|
|
124
|
-
const wasAssigned = updatedFrom?.assigneeId !== undefined &&
|
|
125
|
-
!updatedFrom?.assigneeId &&
|
|
126
|
-
assignee?.id;
|
|
127
|
-
// Check if assigned to an agent (name matches agent pattern)
|
|
128
|
-
const assigneeName = String(assignee?.name || '').toLowerCase();
|
|
129
|
-
// Order matters: more specific patterns first, generic 'agent' and 'bot' last
|
|
130
|
-
const agentPatterns = ['developer', 'reviewer', 'debugger', 'ci-fix', 'refactor', 'lead', 'test', 'docs', 'agent', 'bot'];
|
|
131
|
-
const isAgentAssignment = wasAssigned && agentPatterns.some(p => assigneeName.includes(p));
|
|
132
|
-
if (isAgentAssignment) {
|
|
133
|
-
// Extract the agent type from the assignee name (finds first/most-specific match)
|
|
134
|
-
const matchedAgent = agentPatterns.find(p => assigneeName.includes(p)) || 'developer';
|
|
135
|
-
events.push({
|
|
136
|
-
...baseEvent,
|
|
137
|
-
type: 'issue_assigned',
|
|
138
|
-
item: {
|
|
139
|
-
type: 'ticket',
|
|
140
|
-
id: String(issue.id),
|
|
141
|
-
number: issue.number,
|
|
142
|
-
title: String(issue.title || ''),
|
|
143
|
-
body: String(issue.description || ''),
|
|
144
|
-
url: String(issue.url || ''),
|
|
145
|
-
state: String(issue.state?.name || issue.state || 'unknown'),
|
|
146
|
-
},
|
|
147
|
-
labels: labelNames,
|
|
148
|
-
priority: mapPriority(issue.priority),
|
|
149
|
-
mentions: [matchedAgent], // The assigned agent type
|
|
150
|
-
metadata: {
|
|
151
|
-
action: 'assigned',
|
|
152
|
-
identifier: issue.identifier,
|
|
153
|
-
assignee: assignee?.name,
|
|
154
|
-
assigneeEmail: assignee?.email,
|
|
155
|
-
previousAssignee: updatedFrom?.assigneeId,
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
// Regular update event
|
|
161
|
-
events.push({
|
|
162
|
-
...baseEvent,
|
|
163
|
-
type: 'issue_updated',
|
|
164
|
-
item: {
|
|
165
|
-
type: 'ticket',
|
|
166
|
-
id: String(issue.id),
|
|
167
|
-
number: issue.number,
|
|
168
|
-
title: String(issue.title || ''),
|
|
169
|
-
body: String(issue.description || ''),
|
|
170
|
-
url: String(issue.url || ''),
|
|
171
|
-
state: String(issue.state?.name || issue.state || 'unknown'),
|
|
172
|
-
},
|
|
173
|
-
labels: labelNames,
|
|
174
|
-
priority: mapPriority(issue.priority),
|
|
175
|
-
metadata: {
|
|
176
|
-
action,
|
|
177
|
-
identifier: issue.identifier,
|
|
178
|
-
updatedFrom,
|
|
179
|
-
},
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
break;
|
|
184
|
-
}
|
|
185
|
-
case 'Comment': {
|
|
186
|
-
const comment = webhookData;
|
|
187
|
-
const issue = comment.issue;
|
|
188
|
-
if (action === 'create' && issue) {
|
|
189
|
-
const mentions = extractMentions(comment.body);
|
|
190
|
-
events.push({
|
|
191
|
-
...baseEvent,
|
|
192
|
-
type: mentions.length > 0 ? 'mention' : 'comment_created',
|
|
193
|
-
item: {
|
|
194
|
-
type: 'comment',
|
|
195
|
-
id: String(comment.id),
|
|
196
|
-
number: issue.number,
|
|
197
|
-
title: String(issue.title || ''),
|
|
198
|
-
body: String(comment.body || ''),
|
|
199
|
-
url: String(comment.url || issue.url || ''),
|
|
200
|
-
},
|
|
201
|
-
mentions,
|
|
202
|
-
metadata: {
|
|
203
|
-
action,
|
|
204
|
-
issueId: issue.id,
|
|
205
|
-
issueIdentifier: issue.identifier,
|
|
206
|
-
parentCommentId: comment.parent?.id,
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
break;
|
|
211
|
-
}
|
|
212
|
-
case 'Project': {
|
|
213
|
-
const project = webhookData;
|
|
214
|
-
if (action === 'create') {
|
|
215
|
-
events.push({
|
|
216
|
-
...baseEvent,
|
|
217
|
-
type: 'project_created',
|
|
218
|
-
context: {
|
|
219
|
-
name: String(project.name || 'unknown'),
|
|
220
|
-
url: String(project.url || ''),
|
|
221
|
-
},
|
|
222
|
-
metadata: {
|
|
223
|
-
action,
|
|
224
|
-
projectId: project.id,
|
|
225
|
-
description: project.description,
|
|
226
|
-
targetDate: project.targetDate,
|
|
227
|
-
},
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
case 'IssueLabel': {
|
|
233
|
-
// Label added/removed from issue
|
|
234
|
-
const label = webhookData;
|
|
235
|
-
events.push({
|
|
236
|
-
...baseEvent,
|
|
237
|
-
type: 'label_change',
|
|
238
|
-
labels: [String(label.name || '')],
|
|
239
|
-
metadata: {
|
|
240
|
-
action,
|
|
241
|
-
labelId: label.id,
|
|
242
|
-
color: label.color,
|
|
243
|
-
},
|
|
244
|
-
});
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
default:
|
|
248
|
-
// Unknown type - create generic event
|
|
249
|
-
events.push({
|
|
250
|
-
...baseEvent,
|
|
251
|
-
type: `linear.${type?.toLowerCase() || 'unknown'}.${action || 'unknown'}`,
|
|
252
|
-
metadata: { action, type },
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
return events;
|
|
256
|
-
},
|
|
257
|
-
};
|
|
258
|
-
//# sourceMappingURL=linear.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack Webhook Parser
|
|
3
|
-
*
|
|
4
|
-
* Transforms Slack Events API payloads into normalized events.
|
|
5
|
-
* https://api.slack.com/apis/connections/events-api
|
|
6
|
-
*/
|
|
7
|
-
import type { WebhookParser } from '../types.js';
|
|
8
|
-
export declare const slackParser: WebhookParser;
|
|
9
|
-
//# sourceMappingURL=slack.d.ts.map
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack Webhook Parser
|
|
3
|
-
*
|
|
4
|
-
* Transforms Slack Events API payloads into normalized events.
|
|
5
|
-
* https://api.slack.com/apis/connections/events-api
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Extract user mentions from Slack message text
|
|
9
|
-
* Slack format: <@U12345678> or <@U12345678|username>
|
|
10
|
-
*/
|
|
11
|
-
function extractSlackMentions(text) {
|
|
12
|
-
if (!text)
|
|
13
|
-
return [];
|
|
14
|
-
const mentionPattern = /<@([A-Z0-9]+)(?:\|([^>]+))?>/g;
|
|
15
|
-
const mentions = [];
|
|
16
|
-
let match;
|
|
17
|
-
while ((match = mentionPattern.exec(text)) !== null) {
|
|
18
|
-
// Prefer display name if available, otherwise use ID
|
|
19
|
-
mentions.push(match[2] || match[1]);
|
|
20
|
-
}
|
|
21
|
-
return [...new Set(mentions)];
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Extract agent mentions from text (our custom @agent-name format)
|
|
25
|
-
*/
|
|
26
|
-
function extractAgentMentions(text) {
|
|
27
|
-
if (!text)
|
|
28
|
-
return [];
|
|
29
|
-
// Match @agent-name patterns that aren't Slack user mentions
|
|
30
|
-
const mentionPattern = /(?<![<])@([a-zA-Z][a-zA-Z0-9_-]*)(?![>])/g;
|
|
31
|
-
const mentions = [];
|
|
32
|
-
let match;
|
|
33
|
-
while ((match = mentionPattern.exec(text)) !== null) {
|
|
34
|
-
mentions.push(match[1].toLowerCase());
|
|
35
|
-
}
|
|
36
|
-
return [...new Set(mentions)];
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Clean Slack message text (remove user mention formatting)
|
|
40
|
-
*/
|
|
41
|
-
function cleanSlackText(text) {
|
|
42
|
-
if (!text)
|
|
43
|
-
return '';
|
|
44
|
-
// Replace <@U12345678|username> with @username
|
|
45
|
-
return text.replace(/<@[A-Z0-9]+\|([^>]+)>/g, '@$1')
|
|
46
|
-
.replace(/<@[A-Z0-9]+>/g, '@user')
|
|
47
|
-
// Replace <URL|text> with text
|
|
48
|
-
.replace(/<([^|>]+)\|([^>]+)>/g, '$2')
|
|
49
|
-
// Replace <URL> with URL
|
|
50
|
-
.replace(/<([^>]+)>/g, '$1');
|
|
51
|
-
}
|
|
52
|
-
export const slackParser = {
|
|
53
|
-
id: 'slack',
|
|
54
|
-
parse(payload) {
|
|
55
|
-
const data = payload;
|
|
56
|
-
const events = [];
|
|
57
|
-
// Handle URL verification challenge
|
|
58
|
-
if (data.type === 'url_verification') {
|
|
59
|
-
// This is handled separately in the router
|
|
60
|
-
return [];
|
|
61
|
-
}
|
|
62
|
-
// Events API wrapper
|
|
63
|
-
if (data.type !== 'event_callback') {
|
|
64
|
-
return [];
|
|
65
|
-
}
|
|
66
|
-
const event = data.event;
|
|
67
|
-
if (!event)
|
|
68
|
-
return [];
|
|
69
|
-
const eventType = event.type;
|
|
70
|
-
const teamId = data.team_id || 'unknown';
|
|
71
|
-
const eventId = data.event_id || `slack-${Date.now()}`;
|
|
72
|
-
const eventTime = data.event_time;
|
|
73
|
-
const baseEvent = {
|
|
74
|
-
id: eventId,
|
|
75
|
-
source: 'slack',
|
|
76
|
-
timestamp: eventTime ? new Date(eventTime * 1000) : new Date(),
|
|
77
|
-
actor: {
|
|
78
|
-
id: String(event.user || 'unknown'),
|
|
79
|
-
name: String(event.user || 'unknown'),
|
|
80
|
-
},
|
|
81
|
-
context: {
|
|
82
|
-
name: teamId,
|
|
83
|
-
},
|
|
84
|
-
labels: [],
|
|
85
|
-
mentions: [],
|
|
86
|
-
metadata: {
|
|
87
|
-
teamId,
|
|
88
|
-
channelId: event.channel,
|
|
89
|
-
channelType: event.channel_type,
|
|
90
|
-
},
|
|
91
|
-
rawPayload: payload,
|
|
92
|
-
};
|
|
93
|
-
switch (eventType) {
|
|
94
|
-
case 'app_mention': {
|
|
95
|
-
// Bot was mentioned in a channel
|
|
96
|
-
const text = event.text;
|
|
97
|
-
const agentMentions = extractAgentMentions(text);
|
|
98
|
-
events.push({
|
|
99
|
-
...baseEvent,
|
|
100
|
-
type: 'mention',
|
|
101
|
-
item: {
|
|
102
|
-
type: 'message',
|
|
103
|
-
id: String(event.ts),
|
|
104
|
-
body: cleanSlackText(text),
|
|
105
|
-
},
|
|
106
|
-
mentions: agentMentions.length > 0 ? agentMentions : ['lead'], // Default to lead if no specific agent
|
|
107
|
-
metadata: {
|
|
108
|
-
...baseEvent.metadata,
|
|
109
|
-
ts: event.ts,
|
|
110
|
-
threadTs: event.thread_ts,
|
|
111
|
-
userMentions: extractSlackMentions(text),
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
case 'message': {
|
|
117
|
-
// Regular message in channel
|
|
118
|
-
const text = event.text;
|
|
119
|
-
const subtype = event.subtype;
|
|
120
|
-
// Ignore bot messages, message changes, etc.
|
|
121
|
-
if (subtype && subtype !== 'thread_broadcast') {
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
const agentMentions = extractAgentMentions(text);
|
|
125
|
-
// Only create event if there are agent mentions
|
|
126
|
-
if (agentMentions.length > 0) {
|
|
127
|
-
events.push({
|
|
128
|
-
...baseEvent,
|
|
129
|
-
type: 'mention',
|
|
130
|
-
item: {
|
|
131
|
-
type: 'message',
|
|
132
|
-
id: String(event.ts),
|
|
133
|
-
body: cleanSlackText(text),
|
|
134
|
-
},
|
|
135
|
-
mentions: agentMentions,
|
|
136
|
-
metadata: {
|
|
137
|
-
...baseEvent.metadata,
|
|
138
|
-
ts: event.ts,
|
|
139
|
-
threadTs: event.thread_ts,
|
|
140
|
-
userMentions: extractSlackMentions(text),
|
|
141
|
-
},
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
case 'reaction_added': {
|
|
147
|
-
// Reaction added to a message
|
|
148
|
-
const reaction = event.reaction;
|
|
149
|
-
const item = event.item;
|
|
150
|
-
events.push({
|
|
151
|
-
...baseEvent,
|
|
152
|
-
type: 'reaction_added',
|
|
153
|
-
item: {
|
|
154
|
-
type: 'message',
|
|
155
|
-
id: String(item?.ts || 'unknown'),
|
|
156
|
-
},
|
|
157
|
-
labels: [reaction],
|
|
158
|
-
metadata: {
|
|
159
|
-
...baseEvent.metadata,
|
|
160
|
-
reaction,
|
|
161
|
-
itemType: item?.type,
|
|
162
|
-
itemChannel: item?.channel,
|
|
163
|
-
itemTs: item?.ts,
|
|
164
|
-
},
|
|
165
|
-
});
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
case 'channel_created': {
|
|
169
|
-
const channel = event.channel;
|
|
170
|
-
events.push({
|
|
171
|
-
...baseEvent,
|
|
172
|
-
type: 'channel_created',
|
|
173
|
-
context: {
|
|
174
|
-
name: String(channel?.name || 'unknown'),
|
|
175
|
-
},
|
|
176
|
-
metadata: {
|
|
177
|
-
...baseEvent.metadata,
|
|
178
|
-
channelId: channel?.id,
|
|
179
|
-
channelName: channel?.name,
|
|
180
|
-
creator: channel?.creator,
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
break;
|
|
184
|
-
}
|
|
185
|
-
case 'member_joined_channel': {
|
|
186
|
-
events.push({
|
|
187
|
-
...baseEvent,
|
|
188
|
-
type: 'member_joined',
|
|
189
|
-
actor: {
|
|
190
|
-
id: String(event.user),
|
|
191
|
-
name: String(event.user),
|
|
192
|
-
},
|
|
193
|
-
metadata: {
|
|
194
|
-
...baseEvent.metadata,
|
|
195
|
-
inviter: event.inviter,
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
default:
|
|
201
|
-
// Unknown event type
|
|
202
|
-
events.push({
|
|
203
|
-
...baseEvent,
|
|
204
|
-
type: `slack.${eventType}`,
|
|
205
|
-
metadata: {
|
|
206
|
-
...baseEvent.metadata,
|
|
207
|
-
subtype: event.subtype,
|
|
208
|
-
},
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
return events;
|
|
212
|
-
},
|
|
213
|
-
};
|
|
214
|
-
//# sourceMappingURL=slack.js.map
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GitHub Responder
|
|
3
|
-
*
|
|
4
|
-
* Sends responses back to GitHub via the GitHub App API.
|
|
5
|
-
*/
|
|
6
|
-
import { nangoService } from '../../services/nango.js';
|
|
7
|
-
import { db } from '../../db/index.js';
|
|
8
|
-
export const githubResponder = {
|
|
9
|
-
id: 'github',
|
|
10
|
-
async respond(event, response, _config) {
|
|
11
|
-
try {
|
|
12
|
-
// Get repository info from event context
|
|
13
|
-
const repoFullName = event.context.name;
|
|
14
|
-
const [owner, repo] = repoFullName.split('/');
|
|
15
|
-
if (!owner || !repo) {
|
|
16
|
-
return { success: false, error: `Invalid repository name: ${repoFullName}` };
|
|
17
|
-
}
|
|
18
|
-
// Find the repository in our database to get the Nango connection
|
|
19
|
-
const repository = await db.repositories.findByFullName(repoFullName);
|
|
20
|
-
if (!repository?.nangoConnectionId) {
|
|
21
|
-
return {
|
|
22
|
-
success: false,
|
|
23
|
-
error: `Repository ${repoFullName} not found or has no Nango connection`,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
switch (response.type) {
|
|
27
|
-
case 'comment': {
|
|
28
|
-
// Post a comment on an issue or PR
|
|
29
|
-
const issueNumber = typeof response.target === 'number'
|
|
30
|
-
? response.target
|
|
31
|
-
: parseInt(String(response.target), 10);
|
|
32
|
-
if (isNaN(issueNumber)) {
|
|
33
|
-
return { success: false, error: `Invalid issue number: ${response.target}` };
|
|
34
|
-
}
|
|
35
|
-
const result = await nangoService.addGithubIssueComment(repository.nangoConnectionId, owner, repo, issueNumber, response.body);
|
|
36
|
-
return {
|
|
37
|
-
success: true,
|
|
38
|
-
id: String(result.id),
|
|
39
|
-
url: result.html_url,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
case 'reaction': {
|
|
43
|
-
// Add a reaction to a comment or issue
|
|
44
|
-
// Note: This would need to be added to NangoService
|
|
45
|
-
return {
|
|
46
|
-
success: false,
|
|
47
|
-
error: 'Reactions not yet implemented for GitHub',
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
case 'status': {
|
|
51
|
-
// Update a check run status
|
|
52
|
-
// Note: This would need to be added to NangoService
|
|
53
|
-
return {
|
|
54
|
-
success: false,
|
|
55
|
-
error: 'Status updates not yet implemented for GitHub',
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
default:
|
|
59
|
-
return {
|
|
60
|
-
success: false,
|
|
61
|
-
error: `Unknown response type: ${response.type}`,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
return {
|
|
67
|
-
success: false,
|
|
68
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
//# sourceMappingURL=github.js.map
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Webhook Responders Index
|
|
3
|
-
*
|
|
4
|
-
* Registry of all available responders.
|
|
5
|
-
*/
|
|
6
|
-
import type { WebhookResponder } from '../types.js';
|
|
7
|
-
import { githubResponder } from './github.js';
|
|
8
|
-
import { linearResponder } from './linear.js';
|
|
9
|
-
import { slackResponder, formatSlackBlocks } from './slack.js';
|
|
10
|
-
/**
|
|
11
|
-
* Registry of all available responders
|
|
12
|
-
*/
|
|
13
|
-
export declare const responders: Record<string, WebhookResponder>;
|
|
14
|
-
/**
|
|
15
|
-
* Get a responder by ID
|
|
16
|
-
*/
|
|
17
|
-
export declare function getResponder(id: string): WebhookResponder | undefined;
|
|
18
|
-
/**
|
|
19
|
-
* Register a custom responder
|
|
20
|
-
*/
|
|
21
|
-
export declare function registerResponder(responder: WebhookResponder): void;
|
|
22
|
-
export { githubResponder, linearResponder, slackResponder, formatSlackBlocks };
|
|
23
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Webhook Responders Index
|
|
3
|
-
*
|
|
4
|
-
* Registry of all available responders.
|
|
5
|
-
*/
|
|
6
|
-
import { githubResponder } from './github.js';
|
|
7
|
-
import { linearResponder } from './linear.js';
|
|
8
|
-
import { slackResponder, formatSlackBlocks } from './slack.js';
|
|
9
|
-
/**
|
|
10
|
-
* Registry of all available responders
|
|
11
|
-
*/
|
|
12
|
-
export const responders = {
|
|
13
|
-
github: githubResponder,
|
|
14
|
-
linear: linearResponder,
|
|
15
|
-
slack: slackResponder,
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Get a responder by ID
|
|
19
|
-
*/
|
|
20
|
-
export function getResponder(id) {
|
|
21
|
-
return responders[id];
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Register a custom responder
|
|
25
|
-
*/
|
|
26
|
-
export function registerResponder(responder) {
|
|
27
|
-
responders[responder.id] = responder;
|
|
28
|
-
}
|
|
29
|
-
export { githubResponder, linearResponder, slackResponder, formatSlackBlocks };
|
|
30
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Linear Responder
|
|
3
|
-
*
|
|
4
|
-
* Sends responses back to Linear via their GraphQL API.
|
|
5
|
-
* https://developers.linear.app/docs/graphql/working-with-the-graphql-api
|
|
6
|
-
*/
|
|
7
|
-
import type { WebhookResponder } from '../types.js';
|
|
8
|
-
export declare const linearResponder: WebhookResponder;
|
|
9
|
-
//# sourceMappingURL=linear.d.ts.map
|