agent-relay 2.0.23 → 2.0.24
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 +66 -13
- 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,504 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic Webhook Router
|
|
3
|
-
*
|
|
4
|
-
* Routes incoming webhooks from any source through the configurable pipeline:
|
|
5
|
-
* 1. Verify signature
|
|
6
|
-
* 2. Parse payload into normalized events
|
|
7
|
-
* 3. Match events against rules
|
|
8
|
-
* 4. Execute actions
|
|
9
|
-
* 5. Send responses
|
|
10
|
-
*/
|
|
11
|
-
import crypto from 'crypto';
|
|
12
|
-
import { getParser } from './parsers/index.js';
|
|
13
|
-
import { getResponder } from './responders/index.js';
|
|
14
|
-
import { findMatchingRules, resolveActionTemplate, defaultRules } from './rules-engine.js';
|
|
15
|
-
import { db } from '../db/index.js';
|
|
16
|
-
/**
|
|
17
|
-
* Default webhook source configurations
|
|
18
|
-
*/
|
|
19
|
-
export const defaultSources = {
|
|
20
|
-
github: {
|
|
21
|
-
id: 'github',
|
|
22
|
-
name: 'GitHub',
|
|
23
|
-
enabled: true,
|
|
24
|
-
signature: {
|
|
25
|
-
header: 'x-hub-signature-256',
|
|
26
|
-
algorithm: 'sha256',
|
|
27
|
-
secretEnvVar: 'GITHUB_WEBHOOK_SECRET',
|
|
28
|
-
signaturePrefix: 'sha256=',
|
|
29
|
-
},
|
|
30
|
-
parser: 'github',
|
|
31
|
-
responder: 'github',
|
|
32
|
-
},
|
|
33
|
-
linear: {
|
|
34
|
-
id: 'linear',
|
|
35
|
-
name: 'Linear',
|
|
36
|
-
enabled: true,
|
|
37
|
-
signature: {
|
|
38
|
-
header: 'linear-signature',
|
|
39
|
-
algorithm: 'sha256',
|
|
40
|
-
secretEnvVar: 'LINEAR_WEBHOOK_SECRET',
|
|
41
|
-
},
|
|
42
|
-
parser: 'linear',
|
|
43
|
-
responder: 'linear',
|
|
44
|
-
},
|
|
45
|
-
slack: {
|
|
46
|
-
id: 'slack',
|
|
47
|
-
name: 'Slack',
|
|
48
|
-
enabled: true,
|
|
49
|
-
signature: {
|
|
50
|
-
header: 'x-slack-signature',
|
|
51
|
-
algorithm: 'slack-v0',
|
|
52
|
-
secretEnvVar: 'SLACK_SIGNING_SECRET',
|
|
53
|
-
},
|
|
54
|
-
parser: 'slack',
|
|
55
|
-
responder: 'slack',
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Get webhook configuration
|
|
60
|
-
* In the future, this could load from database per-workspace
|
|
61
|
-
*/
|
|
62
|
-
export function getWebhookConfig() {
|
|
63
|
-
return {
|
|
64
|
-
sources: defaultSources,
|
|
65
|
-
rules: defaultRules,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Verify webhook signature
|
|
70
|
-
*/
|
|
71
|
-
function verifySignature(payload, signature, config, headers) {
|
|
72
|
-
if (config.signature.algorithm === 'none') {
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
if (!signature) {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
const secret = process.env[config.signature.secretEnvVar];
|
|
79
|
-
if (!secret) {
|
|
80
|
-
console.warn(`[webhook-router] Secret not configured: ${config.signature.secretEnvVar}`);
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
try {
|
|
84
|
-
let expectedSignature;
|
|
85
|
-
let actualSignature = signature;
|
|
86
|
-
// Remove prefix if configured
|
|
87
|
-
if (config.signature.signaturePrefix && actualSignature.startsWith(config.signature.signaturePrefix)) {
|
|
88
|
-
actualSignature = actualSignature.slice(config.signature.signaturePrefix.length);
|
|
89
|
-
}
|
|
90
|
-
switch (config.signature.algorithm) {
|
|
91
|
-
case 'sha256':
|
|
92
|
-
expectedSignature = crypto
|
|
93
|
-
.createHmac('sha256', secret)
|
|
94
|
-
.update(payload)
|
|
95
|
-
.digest('hex');
|
|
96
|
-
break;
|
|
97
|
-
case 'sha1':
|
|
98
|
-
expectedSignature = crypto
|
|
99
|
-
.createHmac('sha1', secret)
|
|
100
|
-
.update(payload)
|
|
101
|
-
.digest('hex');
|
|
102
|
-
break;
|
|
103
|
-
case 'token':
|
|
104
|
-
// Direct token comparison
|
|
105
|
-
return actualSignature === secret;
|
|
106
|
-
case 'slack-v0': {
|
|
107
|
-
// Slack signature verification
|
|
108
|
-
// Format: v0=<HMAC-SHA256 of v0:timestamp:body>
|
|
109
|
-
const timestamp = headers?.['x-slack-request-timestamp'];
|
|
110
|
-
if (!timestamp)
|
|
111
|
-
return false;
|
|
112
|
-
// Check timestamp is within 5 minutes
|
|
113
|
-
const now = Math.floor(Date.now() / 1000);
|
|
114
|
-
if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
|
|
115
|
-
console.warn('[webhook-router] Slack request timestamp too old');
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
const sigBasestring = `v0:${timestamp}:${payload}`;
|
|
119
|
-
expectedSignature = 'v0=' + crypto
|
|
120
|
-
.createHmac('sha256', secret)
|
|
121
|
-
.update(sigBasestring)
|
|
122
|
-
.digest('hex');
|
|
123
|
-
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature));
|
|
124
|
-
}
|
|
125
|
-
default:
|
|
126
|
-
console.warn(`[webhook-router] Unknown signature algorithm: ${config.signature.algorithm}`);
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
return crypto.timingSafeEqual(Buffer.from(actualSignature), Buffer.from(expectedSignature));
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
console.error('[webhook-router] Signature verification error:', error);
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Execute an action for an event
|
|
138
|
-
*/
|
|
139
|
-
async function executeAction(action, event, responder, responderConfig) {
|
|
140
|
-
const resolvedAction = resolveActionTemplate(action, event);
|
|
141
|
-
switch (resolvedAction.type) {
|
|
142
|
-
case 'spawn_agent': {
|
|
143
|
-
const agentType = resolvedAction.agentType || 'lead';
|
|
144
|
-
const prompt = buildPrompt(resolvedAction.prompt || 'default', event);
|
|
145
|
-
// Find the repository and queue spawn command
|
|
146
|
-
const repository = await db.repositories.findByFullName(event.context.name);
|
|
147
|
-
if (!repository?.userId) {
|
|
148
|
-
return { success: false, error: 'Repository not found or not linked' };
|
|
149
|
-
}
|
|
150
|
-
// Find an available daemon
|
|
151
|
-
const daemons = await db.linkedDaemons.findByUserId(repository.userId);
|
|
152
|
-
const onlineDaemon = daemons.find(d => d.status === 'online');
|
|
153
|
-
if (!onlineDaemon) {
|
|
154
|
-
// Post a response indicating no daemon available
|
|
155
|
-
if (responder && event.item?.number) {
|
|
156
|
-
await responder.respond(event, {
|
|
157
|
-
type: 'comment',
|
|
158
|
-
target: event.item.number,
|
|
159
|
-
body: `⚠️ No Agent Relay daemon is available to handle this request. Please ensure you have a linked daemon running.`,
|
|
160
|
-
}, responderConfig);
|
|
161
|
-
}
|
|
162
|
-
return { success: false, error: 'No available daemon' };
|
|
163
|
-
}
|
|
164
|
-
// Post acknowledgment
|
|
165
|
-
if (responder && event.item?.number) {
|
|
166
|
-
await responder.respond(event, {
|
|
167
|
-
type: 'comment',
|
|
168
|
-
target: event.item.number,
|
|
169
|
-
body: `👋 Routing to **@${agentType}** agent. The agent will respond shortly.`,
|
|
170
|
-
}, responderConfig);
|
|
171
|
-
}
|
|
172
|
-
// Queue spawn command
|
|
173
|
-
const agentName = `${agentType}-${event.id.slice(0, 8)}`;
|
|
174
|
-
await db.linkedDaemons.queueMessage(onlineDaemon.id, {
|
|
175
|
-
from: { daemonId: 'cloud', daemonName: 'Agent Relay Cloud', agent: 'system' },
|
|
176
|
-
to: '__spawner__',
|
|
177
|
-
content: JSON.stringify({
|
|
178
|
-
type: 'spawn_agent',
|
|
179
|
-
agentName,
|
|
180
|
-
cli: 'claude',
|
|
181
|
-
task: prompt,
|
|
182
|
-
metadata: {
|
|
183
|
-
eventId: event.id,
|
|
184
|
-
source: event.source,
|
|
185
|
-
eventType: event.type,
|
|
186
|
-
repository: event.context.name,
|
|
187
|
-
itemNumber: event.item?.number,
|
|
188
|
-
},
|
|
189
|
-
}),
|
|
190
|
-
metadata: { type: 'spawn_command' },
|
|
191
|
-
timestamp: new Date().toISOString(),
|
|
192
|
-
});
|
|
193
|
-
console.log(`[webhook-router] Queued spawn command for ${agentName}`);
|
|
194
|
-
return { success: true };
|
|
195
|
-
}
|
|
196
|
-
case 'message_agent': {
|
|
197
|
-
// Send message to existing agent
|
|
198
|
-
return { success: false, error: 'message_agent not yet implemented' };
|
|
199
|
-
}
|
|
200
|
-
case 'post_comment': {
|
|
201
|
-
if (!responder) {
|
|
202
|
-
return { success: false, error: 'No responder available' };
|
|
203
|
-
}
|
|
204
|
-
const body = resolvedAction.config?.body || 'Action received.';
|
|
205
|
-
const target = event.item?.number || event.item?.id || '';
|
|
206
|
-
const result = await responder.respond(event, {
|
|
207
|
-
type: 'comment',
|
|
208
|
-
target,
|
|
209
|
-
body,
|
|
210
|
-
}, responderConfig);
|
|
211
|
-
return { success: result.success, error: result.error };
|
|
212
|
-
}
|
|
213
|
-
case 'create_issue': {
|
|
214
|
-
return { success: false, error: 'create_issue not yet implemented' };
|
|
215
|
-
}
|
|
216
|
-
case 'custom': {
|
|
217
|
-
// Custom action handler
|
|
218
|
-
const handler = resolvedAction.config?.handler;
|
|
219
|
-
if (handler) {
|
|
220
|
-
await handler(event);
|
|
221
|
-
return { success: true };
|
|
222
|
-
}
|
|
223
|
-
return { success: false, error: 'No custom handler defined' };
|
|
224
|
-
}
|
|
225
|
-
default:
|
|
226
|
-
return { success: false, error: `Unknown action type: ${resolvedAction.type}` };
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Build a prompt from a template name and event
|
|
231
|
-
*/
|
|
232
|
-
function buildPrompt(templateName, event) {
|
|
233
|
-
const templates = {
|
|
234
|
-
'ci-failure': (e) => `
|
|
235
|
-
# CI Failure Fix Task
|
|
236
|
-
|
|
237
|
-
A CI check has failed in ${e.context.name}.
|
|
238
|
-
|
|
239
|
-
## Failure Details
|
|
240
|
-
|
|
241
|
-
**Check Name:** ${e.item?.title || 'Unknown'}
|
|
242
|
-
**Branch:** ${e.metadata?.branch || 'unknown'}
|
|
243
|
-
**Commit:** ${e.metadata?.commitSha || 'unknown'}
|
|
244
|
-
|
|
245
|
-
${e.metadata?.failureSummary ? `**Summary:**\n${e.metadata.failureSummary}` : ''}
|
|
246
|
-
|
|
247
|
-
${e.metadata?.annotations ? `## Annotations\n\n${formatAnnotations(e.metadata.annotations)}` : ''}
|
|
248
|
-
|
|
249
|
-
## Your Task
|
|
250
|
-
|
|
251
|
-
1. Analyze the failure
|
|
252
|
-
2. Fix the issues
|
|
253
|
-
3. Push your changes
|
|
254
|
-
4. Report back with a summary
|
|
255
|
-
`.trim(),
|
|
256
|
-
'mention': (e) => `
|
|
257
|
-
# Agent Mention Task
|
|
258
|
-
|
|
259
|
-
You were mentioned in ${e.source} in ${e.context.name}.
|
|
260
|
-
|
|
261
|
-
## Context
|
|
262
|
-
|
|
263
|
-
**Item:** ${e.item?.title || 'N/A'} (#${e.item?.number || e.item?.id || 'N/A'})
|
|
264
|
-
**Author:** @${e.actor.name}
|
|
265
|
-
|
|
266
|
-
## Message
|
|
267
|
-
|
|
268
|
-
${e.item?.body || 'No message content'}
|
|
269
|
-
|
|
270
|
-
## Your Task
|
|
271
|
-
|
|
272
|
-
Respond helpfully to the mention. If code changes are needed, make them and push.
|
|
273
|
-
`.trim(),
|
|
274
|
-
'issue': (e) => `
|
|
275
|
-
# Issue Assignment
|
|
276
|
-
|
|
277
|
-
You've been assigned to work on an issue in ${e.context.name}.
|
|
278
|
-
|
|
279
|
-
## Issue Details
|
|
280
|
-
|
|
281
|
-
**Title:** ${e.item?.title}
|
|
282
|
-
**Priority:** ${e.priority || 'normal'}
|
|
283
|
-
**Labels:** ${e.labels.join(', ') || 'none'}
|
|
284
|
-
|
|
285
|
-
## Description
|
|
286
|
-
|
|
287
|
-
${e.item?.body || 'No description provided.'}
|
|
288
|
-
|
|
289
|
-
## Your Task
|
|
290
|
-
|
|
291
|
-
1. Analyze the issue
|
|
292
|
-
2. Implement a solution
|
|
293
|
-
3. Create a PR
|
|
294
|
-
`.trim(),
|
|
295
|
-
'linear-issue': (e) => `
|
|
296
|
-
# Linear Issue
|
|
297
|
-
|
|
298
|
-
A new issue was created in ${e.context.name}.
|
|
299
|
-
|
|
300
|
-
## Issue Details
|
|
301
|
-
|
|
302
|
-
**Identifier:** ${e.metadata?.identifier || 'N/A'}
|
|
303
|
-
**Title:** ${e.item?.title}
|
|
304
|
-
**Priority:** ${e.priority || 'normal'}
|
|
305
|
-
**State:** ${e.item?.state || 'unknown'}
|
|
306
|
-
|
|
307
|
-
## Description
|
|
308
|
-
|
|
309
|
-
${e.item?.body || 'No description provided.'}
|
|
310
|
-
|
|
311
|
-
## Your Task
|
|
312
|
-
|
|
313
|
-
Analyze and work on this issue if appropriate.
|
|
314
|
-
`.trim(),
|
|
315
|
-
'slack-request': (e) => `
|
|
316
|
-
# Slack Request
|
|
317
|
-
|
|
318
|
-
Someone mentioned you in Slack.
|
|
319
|
-
|
|
320
|
-
## Message
|
|
321
|
-
|
|
322
|
-
${e.item?.body || 'No message content'}
|
|
323
|
-
|
|
324
|
-
## Your Task
|
|
325
|
-
|
|
326
|
-
Respond to the request. Use the Slack API to post your response.
|
|
327
|
-
`.trim(),
|
|
328
|
-
'default': (e) => `
|
|
329
|
-
# Webhook Event
|
|
330
|
-
|
|
331
|
-
A webhook event was received from ${e.source}.
|
|
332
|
-
|
|
333
|
-
## Event Details
|
|
334
|
-
|
|
335
|
-
**Type:** ${e.type}
|
|
336
|
-
**Context:** ${e.context.name}
|
|
337
|
-
**Actor:** ${e.actor.name}
|
|
338
|
-
|
|
339
|
-
## Item
|
|
340
|
-
|
|
341
|
-
${e.item ? `**${e.item.type}:** ${e.item.title || e.item.id}` : 'No item'}
|
|
342
|
-
|
|
343
|
-
## Body
|
|
344
|
-
|
|
345
|
-
${e.item?.body || 'No content'}
|
|
346
|
-
`.trim(),
|
|
347
|
-
};
|
|
348
|
-
const template = templates[templateName] || templates['default'];
|
|
349
|
-
return template(event);
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Format annotations for prompt
|
|
353
|
-
*/
|
|
354
|
-
function formatAnnotations(annotations) {
|
|
355
|
-
return annotations
|
|
356
|
-
.slice(0, 20)
|
|
357
|
-
.map(a => `- ${a.path}:${a.startLine} - ${a.message}`)
|
|
358
|
-
.join('\n');
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* Process a webhook from any source
|
|
362
|
-
*/
|
|
363
|
-
export async function processWebhook(source, payload, headers, config) {
|
|
364
|
-
const webhookConfig = config || getWebhookConfig();
|
|
365
|
-
const sourceConfig = webhookConfig.sources[source];
|
|
366
|
-
if (!sourceConfig) {
|
|
367
|
-
return {
|
|
368
|
-
success: false,
|
|
369
|
-
eventId: 'unknown',
|
|
370
|
-
source,
|
|
371
|
-
eventType: 'unknown',
|
|
372
|
-
matchedRules: [],
|
|
373
|
-
actions: [],
|
|
374
|
-
responses: [{
|
|
375
|
-
type: 'error',
|
|
376
|
-
success: false,
|
|
377
|
-
error: `Unknown webhook source: ${source}`,
|
|
378
|
-
}],
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
if (!sourceConfig.enabled) {
|
|
382
|
-
return {
|
|
383
|
-
success: false,
|
|
384
|
-
eventId: 'unknown',
|
|
385
|
-
source,
|
|
386
|
-
eventType: 'unknown',
|
|
387
|
-
matchedRules: [],
|
|
388
|
-
actions: [],
|
|
389
|
-
responses: [{
|
|
390
|
-
type: 'error',
|
|
391
|
-
success: false,
|
|
392
|
-
error: `Webhook source disabled: ${source}`,
|
|
393
|
-
}],
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
// Verify signature
|
|
397
|
-
const signature = headers[sourceConfig.signature.header];
|
|
398
|
-
if (!verifySignature(payload, signature, sourceConfig, headers)) {
|
|
399
|
-
console.error(`[webhook-router] Invalid signature for source: ${source}`);
|
|
400
|
-
return {
|
|
401
|
-
success: false,
|
|
402
|
-
eventId: 'unknown',
|
|
403
|
-
source,
|
|
404
|
-
eventType: 'unknown',
|
|
405
|
-
matchedRules: [],
|
|
406
|
-
actions: [],
|
|
407
|
-
responses: [{
|
|
408
|
-
type: 'error',
|
|
409
|
-
success: false,
|
|
410
|
-
error: 'Invalid signature',
|
|
411
|
-
}],
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
// Parse payload
|
|
415
|
-
const parser = getParser(sourceConfig.parser);
|
|
416
|
-
if (!parser) {
|
|
417
|
-
return {
|
|
418
|
-
success: false,
|
|
419
|
-
eventId: 'unknown',
|
|
420
|
-
source,
|
|
421
|
-
eventType: 'unknown',
|
|
422
|
-
matchedRules: [],
|
|
423
|
-
actions: [],
|
|
424
|
-
responses: [{
|
|
425
|
-
type: 'error',
|
|
426
|
-
success: false,
|
|
427
|
-
error: `Parser not found: ${sourceConfig.parser}`,
|
|
428
|
-
}],
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
let parsedPayload;
|
|
432
|
-
try {
|
|
433
|
-
parsedPayload = JSON.parse(payload);
|
|
434
|
-
}
|
|
435
|
-
catch {
|
|
436
|
-
return {
|
|
437
|
-
success: false,
|
|
438
|
-
eventId: 'unknown',
|
|
439
|
-
source,
|
|
440
|
-
eventType: 'unknown',
|
|
441
|
-
matchedRules: [],
|
|
442
|
-
actions: [],
|
|
443
|
-
responses: [{
|
|
444
|
-
type: 'error',
|
|
445
|
-
success: false,
|
|
446
|
-
error: 'Invalid JSON payload',
|
|
447
|
-
}],
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
const events = parser.parse(parsedPayload, headers, sourceConfig.parserConfig);
|
|
451
|
-
if (events.length === 0) {
|
|
452
|
-
return {
|
|
453
|
-
success: true,
|
|
454
|
-
eventId: 'none',
|
|
455
|
-
source,
|
|
456
|
-
eventType: 'none',
|
|
457
|
-
matchedRules: [],
|
|
458
|
-
actions: [],
|
|
459
|
-
responses: [],
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
// Get responder
|
|
463
|
-
const responder = getResponder(sourceConfig.responder);
|
|
464
|
-
// Process each event
|
|
465
|
-
const results = [];
|
|
466
|
-
for (const event of events) {
|
|
467
|
-
const matchedRules = findMatchingRules(webhookConfig.rules, event);
|
|
468
|
-
const actionResults = [];
|
|
469
|
-
const responseResults = [];
|
|
470
|
-
console.log(`[webhook-router] Event ${event.id}: type=${event.type}, matched ${matchedRules.length} rules`);
|
|
471
|
-
for (const rule of matchedRules) {
|
|
472
|
-
const result = await executeAction(rule.action, event, responder, sourceConfig.responderConfig);
|
|
473
|
-
actionResults.push({
|
|
474
|
-
ruleId: rule.id,
|
|
475
|
-
action: rule.action,
|
|
476
|
-
success: result.success,
|
|
477
|
-
error: result.error,
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
results.push({
|
|
481
|
-
success: actionResults.every(a => a.success),
|
|
482
|
-
eventId: event.id,
|
|
483
|
-
source: event.source,
|
|
484
|
-
eventType: event.type,
|
|
485
|
-
matchedRules: matchedRules.map(r => r.id),
|
|
486
|
-
actions: actionResults,
|
|
487
|
-
responses: responseResults,
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
// Return combined result
|
|
491
|
-
if (results.length === 1) {
|
|
492
|
-
return results[0];
|
|
493
|
-
}
|
|
494
|
-
return {
|
|
495
|
-
success: results.every(r => r.success),
|
|
496
|
-
eventId: events[0].id,
|
|
497
|
-
source,
|
|
498
|
-
eventType: events.map(e => e.type).join(','),
|
|
499
|
-
matchedRules: results.flatMap(r => r.matchedRules),
|
|
500
|
-
actions: results.flatMap(r => r.actions),
|
|
501
|
-
responses: results.flatMap(r => r.responses),
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
//# sourceMappingURL=router.js.map
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Webhook Rules Engine
|
|
3
|
-
*
|
|
4
|
-
* Matches normalized events against configured rules and determines actions to take.
|
|
5
|
-
*/
|
|
6
|
-
import type { NormalizedEvent, WebhookRule, WebhookAction } from './types.js';
|
|
7
|
-
/**
|
|
8
|
-
* Check if a rule matches an event
|
|
9
|
-
*/
|
|
10
|
-
export declare function matchesRule(rule: WebhookRule, event: NormalizedEvent): boolean;
|
|
11
|
-
/**
|
|
12
|
-
* Find all matching rules for an event, sorted by priority
|
|
13
|
-
*/
|
|
14
|
-
export declare function findMatchingRules(rules: WebhookRule[], event: NormalizedEvent): WebhookRule[];
|
|
15
|
-
/**
|
|
16
|
-
* Resolve template variables in action configuration
|
|
17
|
-
* Supports: ${event.field}, ${event.field.subfield}
|
|
18
|
-
*/
|
|
19
|
-
export declare function resolveActionTemplate(action: WebhookAction, event: NormalizedEvent): WebhookAction;
|
|
20
|
-
/**
|
|
21
|
-
* Default rules for common patterns
|
|
22
|
-
*/
|
|
23
|
-
export declare const defaultRules: WebhookRule[];
|
|
24
|
-
//# sourceMappingURL=rules-engine.d.ts.map
|