@relaycast/engine 2.1.0 → 2.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/dist/adapters/node/presence.d.ts +3 -3
- package/dist/adapters/node/presence.d.ts.map +1 -1
- package/dist/adapters/node/presence.js +7 -6
- package/dist/adapters/node/presence.js.map +1 -1
- package/dist/db/migrations/0014_normalize_delivery_pending.sql +9 -0
- package/dist/db/migrations/0015_sdk_v8_contract.sql +7 -0
- package/dist/db/schema.d.ts +38 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +3 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/engine/action.d.ts +2 -2
- package/dist/engine/action.d.ts.map +1 -1
- package/dist/engine/action.js +11 -4
- package/dist/engine/action.js.map +1 -1
- package/dist/engine/agent.d.ts.map +1 -1
- package/dist/engine/agent.js +3 -1
- package/dist/engine/agent.js.map +1 -1
- package/dist/engine/delivery.d.ts +93 -0
- package/dist/engine/delivery.d.ts.map +1 -0
- package/dist/engine/delivery.js +192 -0
- package/dist/engine/delivery.js.map +1 -0
- package/dist/engine/eventDelivery.d.ts.map +1 -1
- package/dist/engine/eventDelivery.js +16 -0
- package/dist/engine/eventDelivery.js.map +1 -1
- package/dist/engine/eventSubscription.d.ts +5 -0
- package/dist/engine/eventSubscription.d.ts.map +1 -1
- package/dist/engine/eventSubscription.js +9 -0
- package/dist/engine/eventSubscription.js.map +1 -1
- package/dist/engine/inboundWebhook.d.ts +5 -2
- package/dist/engine/inboundWebhook.d.ts.map +1 -1
- package/dist/engine/inboundWebhook.js +24 -2
- package/dist/engine/inboundWebhook.js.map +1 -1
- package/dist/engine/message.d.ts.map +1 -1
- package/dist/engine/message.js +9 -7
- package/dist/engine/message.js.map +1 -1
- package/dist/engine/messageMetadata.d.ts +10 -0
- package/dist/engine/messageMetadata.d.ts.map +1 -0
- package/dist/engine/messageMetadata.js +40 -0
- package/dist/engine/messageMetadata.js.map +1 -0
- package/dist/engine/receipt.d.ts.map +1 -1
- package/dist/engine/receipt.js +6 -3
- package/dist/engine/receipt.js.map +1 -1
- package/dist/engine/resyncQuery.d.ts.map +1 -1
- package/dist/engine/resyncQuery.js +2 -1
- package/dist/engine/resyncQuery.js.map +1 -1
- package/dist/engine/thread.d.ts.map +1 -1
- package/dist/engine/thread.js +8 -6
- package/dist/engine/thread.js.map +1 -1
- package/dist/engine/wsTransform.d.ts.map +1 -1
- package/dist/engine/wsTransform.js +34 -13
- package/dist/engine/wsTransform.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +2 -0
- package/dist/engine.js.map +1 -1
- package/dist/ports/presence.d.ts +3 -3
- package/dist/ports/presence.d.ts.map +1 -1
- package/dist/routes/action.d.ts.map +1 -1
- package/dist/routes/action.js +23 -4
- package/dist/routes/action.js.map +1 -1
- package/dist/routes/agent.js +73 -8
- package/dist/routes/agent.js.map +1 -1
- package/dist/routes/delivery.d.ts +4 -0
- package/dist/routes/delivery.d.ts.map +1 -0
- package/dist/routes/delivery.js +153 -0
- package/dist/routes/delivery.js.map +1 -0
- package/dist/routes/eventSubscription.js +5 -2
- package/dist/routes/eventSubscription.js.map +1 -1
- package/dist/routes/inboundWebhook.js +29 -12
- package/dist/routes/inboundWebhook.js.map +1 -1
- package/dist/routes/reaction.js +13 -12
- package/dist/routes/reaction.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { getDb } from '../db/index.js';
|
|
2
|
+
import { deliveries } from '../db/schema.js';
|
|
3
|
+
import type { DeliveryStatus } from '@relaycast/types';
|
|
4
|
+
type Db = ReturnType<typeof getDb>;
|
|
5
|
+
type DeliveryRow = typeof deliveries.$inferSelect;
|
|
6
|
+
declare function serializeDelivery(row: DeliveryRow & {
|
|
7
|
+
channelId?: string;
|
|
8
|
+
}): {
|
|
9
|
+
id: string;
|
|
10
|
+
message_id: string;
|
|
11
|
+
channel_id: string;
|
|
12
|
+
agent_id: string;
|
|
13
|
+
status: DeliveryStatus;
|
|
14
|
+
mode: string;
|
|
15
|
+
reason: string | null;
|
|
16
|
+
priority: string;
|
|
17
|
+
retryable: boolean | null;
|
|
18
|
+
error: string | null;
|
|
19
|
+
available_at: string | null;
|
|
20
|
+
deadline: string | null;
|
|
21
|
+
created_at: string;
|
|
22
|
+
updated_at: string | null;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* List durable delivery items for an agent. Defaults to the non-terminal
|
|
26
|
+
* (`accepted` + `deferred`) queue so an offline consumer can replay what it
|
|
27
|
+
* missed on reconnect, oldest first (FIFO). Each item carries the message
|
|
28
|
+
* payload so the consumer does not need a second round-trip.
|
|
29
|
+
*/
|
|
30
|
+
export declare function listDeliveries(db: Db, workspaceId: string, agentId: string, opts?: {
|
|
31
|
+
status?: DeliveryStatus;
|
|
32
|
+
limit?: number;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
channel_id: string;
|
|
35
|
+
message: {
|
|
36
|
+
id: string;
|
|
37
|
+
channel_id: string;
|
|
38
|
+
agent_id: string;
|
|
39
|
+
agent_name: string | null;
|
|
40
|
+
text: string;
|
|
41
|
+
thread_id: string | null;
|
|
42
|
+
created_at: string;
|
|
43
|
+
} | null;
|
|
44
|
+
id: string;
|
|
45
|
+
message_id: string;
|
|
46
|
+
agent_id: string;
|
|
47
|
+
status: DeliveryStatus;
|
|
48
|
+
mode: string;
|
|
49
|
+
reason: string | null;
|
|
50
|
+
priority: string;
|
|
51
|
+
retryable: boolean | null;
|
|
52
|
+
error: string | null;
|
|
53
|
+
available_at: string | null;
|
|
54
|
+
deadline: string | null;
|
|
55
|
+
created_at: string;
|
|
56
|
+
updated_at: string | null;
|
|
57
|
+
}[]>;
|
|
58
|
+
export type TransitionResult = {
|
|
59
|
+
delivery: ReturnType<typeof serializeDelivery>;
|
|
60
|
+
changed: boolean;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Idempotently transition a delivery to `delivered`. `delivered` is terminal,
|
|
64
|
+
* so repeated acks are no-ops (reported as `changed: false`). Returns null if
|
|
65
|
+
* the delivery is not found / not owned.
|
|
66
|
+
*/
|
|
67
|
+
export declare function ackDelivery(db: Db, workspaceId: string, agentId: string, deliveryId: string): Promise<TransitionResult | null>;
|
|
68
|
+
/**
|
|
69
|
+
* Idempotently record a delivery as `failed`, capturing error text and
|
|
70
|
+
* retryability. Both `delivered` and `failed` are treated as settled: once a
|
|
71
|
+
* delivery has failed, repeated calls are no-ops that preserve the original
|
|
72
|
+
* failure metadata (no `null` overwrite, no `updatedAt` churn, no duplicate
|
|
73
|
+
* event). The WHERE guard also closes the read→write race against a concurrent
|
|
74
|
+
* ack. Returns null if not found / not owned.
|
|
75
|
+
*/
|
|
76
|
+
export declare function failDelivery(db: Db, workspaceId: string, agentId: string, deliveryId: string, opts?: {
|
|
77
|
+
error?: string;
|
|
78
|
+
retryable?: boolean;
|
|
79
|
+
}): Promise<TransitionResult | null>;
|
|
80
|
+
/**
|
|
81
|
+
* Idempotently record a delivery as `deferred` with the time it next becomes
|
|
82
|
+
* available. A re-defer to the same `available_at`/reason is a no-op (reported
|
|
83
|
+
* as `changed: false`); deferring to a new time is a real change. `delivered`
|
|
84
|
+
* is terminal, so a defer never resurrects an already-acked delivery (the WHERE
|
|
85
|
+
* guard also closes the read→write race against a concurrent ack). Returns null
|
|
86
|
+
* if not found / not owned.
|
|
87
|
+
*/
|
|
88
|
+
export declare function deferDelivery(db: Db, workspaceId: string, agentId: string, deliveryId: string, opts: {
|
|
89
|
+
availableAt: Date;
|
|
90
|
+
reason?: string;
|
|
91
|
+
}): Promise<TransitionResult | null>;
|
|
92
|
+
export {};
|
|
93
|
+
//# sourceMappingURL=delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/engine/delivery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAEnC,KAAK,WAAW,GAAG,OAAO,UAAU,CAAC,YAAY,CAAC;AAMlD,iBAAS,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;YAM1C,cAAc;;;;;;;;;;EAWvC;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,cAAc,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO;;;;;;;;;;;;;;YAvB9B,cAAc;;;;;;;;;;KA+EvC;AA6BD,MAAM,MAAM,gBAAgB,GAAG;IAAE,QAAQ,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpG;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAelC;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACjD,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAsBlC;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE;IAAE,WAAW,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAoClC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { eq, ne, and, not, asc, isNull, inArray, notInArray } from 'drizzle-orm';
|
|
2
|
+
import { deliveries, messages, agents } from '../db/schema.js';
|
|
3
|
+
function toIso(value) {
|
|
4
|
+
return value ? value.toISOString() : null;
|
|
5
|
+
}
|
|
6
|
+
function serializeDelivery(row) {
|
|
7
|
+
return {
|
|
8
|
+
id: row.id,
|
|
9
|
+
message_id: row.messageId,
|
|
10
|
+
channel_id: row.channelId ?? '',
|
|
11
|
+
agent_id: row.agentId,
|
|
12
|
+
status: row.status,
|
|
13
|
+
mode: row.mode,
|
|
14
|
+
reason: row.reason,
|
|
15
|
+
priority: row.priority,
|
|
16
|
+
retryable: row.retryable ?? null,
|
|
17
|
+
error: row.error,
|
|
18
|
+
available_at: toIso(row.availableAt),
|
|
19
|
+
deadline: toIso(row.deadline),
|
|
20
|
+
created_at: toIso(row.createdAt) ?? new Date(0).toISOString(),
|
|
21
|
+
updated_at: toIso(row.updatedAt),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* List durable delivery items for an agent. Defaults to the non-terminal
|
|
26
|
+
* (`accepted` + `deferred`) queue so an offline consumer can replay what it
|
|
27
|
+
* missed on reconnect, oldest first (FIFO). Each item carries the message
|
|
28
|
+
* payload so the consumer does not need a second round-trip.
|
|
29
|
+
*/
|
|
30
|
+
export async function listDeliveries(db, workspaceId, agentId, opts = {}) {
|
|
31
|
+
const limit = Math.min(Math.max(opts.limit ?? 100, 1), 200);
|
|
32
|
+
const statusFilter = opts.status
|
|
33
|
+
? eq(deliveries.status, opts.status)
|
|
34
|
+
: inArray(deliveries.status, ['accepted', 'deferred']);
|
|
35
|
+
const rows = await db
|
|
36
|
+
.select()
|
|
37
|
+
.from(deliveries)
|
|
38
|
+
.where(and(eq(deliveries.workspaceId, workspaceId), eq(deliveries.agentId, agentId), statusFilter))
|
|
39
|
+
.orderBy(asc(deliveries.createdAt), asc(deliveries.id))
|
|
40
|
+
.limit(limit);
|
|
41
|
+
if (rows.length === 0)
|
|
42
|
+
return [];
|
|
43
|
+
const messageIds = [...new Set(rows.map((r) => r.messageId))];
|
|
44
|
+
const msgRows = await db
|
|
45
|
+
.select({
|
|
46
|
+
id: messages.id,
|
|
47
|
+
channelId: messages.channelId,
|
|
48
|
+
agentId: messages.agentId,
|
|
49
|
+
agentName: agents.name,
|
|
50
|
+
body: messages.body,
|
|
51
|
+
threadId: messages.threadId,
|
|
52
|
+
createdAt: messages.createdAt,
|
|
53
|
+
})
|
|
54
|
+
.from(messages)
|
|
55
|
+
.leftJoin(agents, eq(messages.agentId, agents.id))
|
|
56
|
+
.where(inArray(messages.id, messageIds));
|
|
57
|
+
const msgById = new Map(msgRows.map((m) => [m.id, m]));
|
|
58
|
+
return rows.map((row) => {
|
|
59
|
+
const msg = msgById.get(row.messageId);
|
|
60
|
+
return {
|
|
61
|
+
...serializeDelivery(row),
|
|
62
|
+
channel_id: msg?.channelId ?? '',
|
|
63
|
+
message: msg
|
|
64
|
+
? {
|
|
65
|
+
id: msg.id,
|
|
66
|
+
channel_id: msg.channelId,
|
|
67
|
+
agent_id: msg.agentId ?? null,
|
|
68
|
+
agent_name: msg.agentName ?? null,
|
|
69
|
+
text: msg.body,
|
|
70
|
+
thread_id: msg.threadId ?? null,
|
|
71
|
+
created_at: msg.createdAt.toISOString(),
|
|
72
|
+
}
|
|
73
|
+
: null,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Fetch a single delivery owned by the agent, joined to its message so the
|
|
79
|
+
* caller has the `channelId` for serialization. Returns null if not found.
|
|
80
|
+
*/
|
|
81
|
+
async function getOwnedDelivery(db, workspaceId, agentId, deliveryId) {
|
|
82
|
+
const [row] = await db
|
|
83
|
+
.select({ delivery: deliveries, channelId: messages.channelId })
|
|
84
|
+
.from(deliveries)
|
|
85
|
+
.innerJoin(messages, eq(deliveries.messageId, messages.id))
|
|
86
|
+
.where(and(eq(deliveries.id, deliveryId), eq(deliveries.workspaceId, workspaceId), eq(deliveries.agentId, agentId)));
|
|
87
|
+
return row ? { ...row.delivery, channelId: row.channelId } : null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Idempotently transition a delivery to `delivered`. `delivered` is terminal,
|
|
91
|
+
* so repeated acks are no-ops (reported as `changed: false`). Returns null if
|
|
92
|
+
* the delivery is not found / not owned.
|
|
93
|
+
*/
|
|
94
|
+
export async function ackDelivery(db, workspaceId, agentId, deliveryId) {
|
|
95
|
+
const existing = await getOwnedDelivery(db, workspaceId, agentId, deliveryId);
|
|
96
|
+
if (!existing)
|
|
97
|
+
return null;
|
|
98
|
+
if (existing.status === 'delivered')
|
|
99
|
+
return { delivery: serializeDelivery(existing), changed: false };
|
|
100
|
+
// The `status != 'delivered'` predicate lives in the UPDATE so the DB decides
|
|
101
|
+
// atomically whether this call transitioned the row. Under concurrent acks
|
|
102
|
+
// only one update matches (SQLite serializes writes); the loser sees no row
|
|
103
|
+
// and reports `changed: false`, so the delivered event fires exactly once.
|
|
104
|
+
const [updated] = await db
|
|
105
|
+
.update(deliveries)
|
|
106
|
+
.set({ status: 'delivered', updatedAt: new Date() })
|
|
107
|
+
.where(and(eq(deliveries.id, deliveryId), ne(deliveries.status, 'delivered')))
|
|
108
|
+
.returning();
|
|
109
|
+
return resolveTransition(db, workspaceId, agentId, deliveryId, updated, existing.channelId);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Idempotently record a delivery as `failed`, capturing error text and
|
|
113
|
+
* retryability. Both `delivered` and `failed` are treated as settled: once a
|
|
114
|
+
* delivery has failed, repeated calls are no-ops that preserve the original
|
|
115
|
+
* failure metadata (no `null` overwrite, no `updatedAt` churn, no duplicate
|
|
116
|
+
* event). The WHERE guard also closes the read→write race against a concurrent
|
|
117
|
+
* ack. Returns null if not found / not owned.
|
|
118
|
+
*/
|
|
119
|
+
export async function failDelivery(db, workspaceId, agentId, deliveryId, opts = {}) {
|
|
120
|
+
const existing = await getOwnedDelivery(db, workspaceId, agentId, deliveryId);
|
|
121
|
+
if (!existing)
|
|
122
|
+
return null;
|
|
123
|
+
if (existing.status === 'delivered' || existing.status === 'failed') {
|
|
124
|
+
return { delivery: serializeDelivery(existing), changed: false };
|
|
125
|
+
}
|
|
126
|
+
// Both `delivered` and `failed` are settled, so the UPDATE only matches a
|
|
127
|
+
// not-yet-settled row. Under concurrent fails the DB lets exactly one win;
|
|
128
|
+
// the loser matches no row, preserves the first failure's metadata, and
|
|
129
|
+
// reports `changed: false` (no duplicate event).
|
|
130
|
+
const [updated] = await db
|
|
131
|
+
.update(deliveries)
|
|
132
|
+
.set({
|
|
133
|
+
status: 'failed',
|
|
134
|
+
error: opts.error ?? null,
|
|
135
|
+
retryable: opts.retryable ?? null,
|
|
136
|
+
updatedAt: new Date(),
|
|
137
|
+
})
|
|
138
|
+
.where(and(eq(deliveries.id, deliveryId), notInArray(deliveries.status, ['delivered', 'failed'])))
|
|
139
|
+
.returning();
|
|
140
|
+
return resolveTransition(db, workspaceId, agentId, deliveryId, updated, existing.channelId);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Idempotently record a delivery as `deferred` with the time it next becomes
|
|
144
|
+
* available. A re-defer to the same `available_at`/reason is a no-op (reported
|
|
145
|
+
* as `changed: false`); deferring to a new time is a real change. `delivered`
|
|
146
|
+
* is terminal, so a defer never resurrects an already-acked delivery (the WHERE
|
|
147
|
+
* guard also closes the read→write race against a concurrent ack). Returns null
|
|
148
|
+
* if not found / not owned.
|
|
149
|
+
*/
|
|
150
|
+
export async function deferDelivery(db, workspaceId, agentId, deliveryId, opts) {
|
|
151
|
+
const existing = await getOwnedDelivery(db, workspaceId, agentId, deliveryId);
|
|
152
|
+
if (!existing)
|
|
153
|
+
return null;
|
|
154
|
+
if (existing.status === 'delivered')
|
|
155
|
+
return { delivery: serializeDelivery(existing), changed: false };
|
|
156
|
+
// The defer reason is its own concept; don't inherit the acceptance reason
|
|
157
|
+
// (message/mention/dm/...) when the caller omits one, or deferred records and
|
|
158
|
+
// delivery.deferred events would carry a misleading reason. Default to null.
|
|
159
|
+
const targetReason = opts.reason ?? null;
|
|
160
|
+
const reasonMatches = targetReason === null
|
|
161
|
+
? isNull(deliveries.reason)
|
|
162
|
+
: eq(deliveries.reason, targetReason);
|
|
163
|
+
// A real change means: not terminal-delivered, and not already deferred to
|
|
164
|
+
// this exact (available_at, reason). Encoding the no-op predicate in the
|
|
165
|
+
// UPDATE makes it atomic — identical concurrent defers match no row on the
|
|
166
|
+
// loser and report `changed: false`, so no duplicate event fires.
|
|
167
|
+
const isNoop = and(eq(deliveries.status, 'deferred'), eq(deliveries.availableAt, opts.availableAt), reasonMatches);
|
|
168
|
+
const [updated] = await db
|
|
169
|
+
.update(deliveries)
|
|
170
|
+
.set({
|
|
171
|
+
status: 'deferred',
|
|
172
|
+
availableAt: opts.availableAt,
|
|
173
|
+
reason: targetReason,
|
|
174
|
+
updatedAt: new Date(),
|
|
175
|
+
})
|
|
176
|
+
.where(and(eq(deliveries.id, deliveryId), ne(deliveries.status, 'delivered'), not(isNoop)))
|
|
177
|
+
.returning();
|
|
178
|
+
return resolveTransition(db, workspaceId, agentId, deliveryId, updated, existing.channelId);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Resolve the result of a status-guarded transition: when the write landed,
|
|
182
|
+
* report the updated row as changed. When it did not (the row was deleted, or a
|
|
183
|
+
* concurrent ack won the race and the row is now terminal), re-read and return
|
|
184
|
+
* the current state as unchanged — never resurrecting it or emitting an event.
|
|
185
|
+
*/
|
|
186
|
+
async function resolveTransition(db, workspaceId, agentId, deliveryId, updated, channelId) {
|
|
187
|
+
if (updated)
|
|
188
|
+
return { delivery: serializeDelivery({ ...updated, channelId }), changed: true };
|
|
189
|
+
const current = await getOwnedDelivery(db, workspaceId, agentId, deliveryId);
|
|
190
|
+
return current ? { delivery: serializeDelivery(current), changed: false } : null;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../src/engine/delivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventDelivery.d.ts","sourceRoot":"","sources":["../../src/engine/eventDelivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAI5C,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAEnC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5E;
|
|
1
|
+
{"version":3,"file":"eventDelivery.d.ts","sourceRoot":"","sources":["../../src/engine/eventDelivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAI5C,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAEnC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5E;AAcD,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAyED,wBAAsB,YAAY,CAChC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAmE/B"}
|
|
@@ -3,6 +3,14 @@ import { getActiveSubscriptions } from './eventSubscription.js';
|
|
|
3
3
|
export function signPayload(payload, secret) {
|
|
4
4
|
return hmacSha256Hex(payload, secret);
|
|
5
5
|
}
|
|
6
|
+
function publicDeliveryHeaders(headers) {
|
|
7
|
+
if (!headers)
|
|
8
|
+
return {};
|
|
9
|
+
return Object.fromEntries(Object.entries(headers).filter(([name]) => {
|
|
10
|
+
const lower = name.toLowerCase();
|
|
11
|
+
return lower !== 'content-type' && !lower.startsWith('x-relay-');
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
6
14
|
function matchesFilter(filter, payload) {
|
|
7
15
|
if (!filter)
|
|
8
16
|
return true;
|
|
@@ -21,6 +29,12 @@ function matchesFilter(filter, payload) {
|
|
|
21
29
|
return true;
|
|
22
30
|
}
|
|
23
31
|
async function attemptDelivery(url, body, headers, retries = 3) {
|
|
32
|
+
try {
|
|
33
|
+
new Headers(headers);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return { ok: false, retryable: false };
|
|
37
|
+
}
|
|
24
38
|
for (let attempt = 0; attempt < retries; attempt++) {
|
|
25
39
|
try {
|
|
26
40
|
const response = await globalThis.fetch(url, {
|
|
@@ -55,6 +69,7 @@ export async function deliverEvent(db, workspaceId, eventType, payload) {
|
|
|
55
69
|
subscriptions = rows.map((r) => ({
|
|
56
70
|
url: r.url,
|
|
57
71
|
secret: r.secret,
|
|
72
|
+
headers: r.headers ?? null,
|
|
58
73
|
filter: r.filter,
|
|
59
74
|
}));
|
|
60
75
|
}
|
|
@@ -80,6 +95,7 @@ export async function deliverEvent(db, workspaceId, eventType, payload) {
|
|
|
80
95
|
}
|
|
81
96
|
const deliveryResults = await Promise.all(filteredSubscriptions.map(async (sub) => {
|
|
82
97
|
const headers = {
|
|
98
|
+
...publicDeliveryHeaders(sub.headers),
|
|
83
99
|
'Content-Type': 'application/json',
|
|
84
100
|
'X-Relay-Event': eventType,
|
|
85
101
|
'X-Relay-Timestamp': timestamp,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventDelivery.js","sourceRoot":"","sources":["../../src/engine/eventDelivery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,MAAc;IACzD,OAAO,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC;
|
|
1
|
+
{"version":3,"file":"eventDelivery.js","sourceRoot":"","sources":["../../src/engine/eventDelivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ export declare function createSubscription(db: Db, workspaceId: string, data: {
|
|
|
7
7
|
mentions?: string;
|
|
8
8
|
} | null;
|
|
9
9
|
url: string;
|
|
10
|
+
headers?: Record<string, string>;
|
|
10
11
|
secret?: string;
|
|
11
12
|
}): Promise<{
|
|
12
13
|
id: string;
|
|
@@ -16,6 +17,7 @@ export declare function createSubscription(db: Db, workspaceId: string, data: {
|
|
|
16
17
|
mentions?: string;
|
|
17
18
|
} | null;
|
|
18
19
|
url: string;
|
|
20
|
+
headers: Record<string, string> | null;
|
|
19
21
|
is_active: boolean;
|
|
20
22
|
created_at: string;
|
|
21
23
|
}>;
|
|
@@ -27,6 +29,7 @@ export declare function listSubscriptions(db: Db, workspaceId: string): Promise<
|
|
|
27
29
|
mentions?: string;
|
|
28
30
|
} | null;
|
|
29
31
|
url: string;
|
|
32
|
+
headers: Record<string, string> | null;
|
|
30
33
|
is_active: boolean;
|
|
31
34
|
created_at: string;
|
|
32
35
|
}[]>;
|
|
@@ -38,6 +41,7 @@ export declare function getSubscription(db: Db, workspaceId: string, subId: stri
|
|
|
38
41
|
mentions?: string;
|
|
39
42
|
} | null;
|
|
40
43
|
url: string;
|
|
44
|
+
headers: Record<string, string> | null;
|
|
41
45
|
is_active: boolean;
|
|
42
46
|
created_at: string;
|
|
43
47
|
} | null>;
|
|
@@ -51,6 +55,7 @@ export declare function getActiveSubscriptions(db: Db, workspaceId: string, even
|
|
|
51
55
|
mentions?: string;
|
|
52
56
|
} | null;
|
|
53
57
|
url: string;
|
|
58
|
+
headers: Record<string, string> | null;
|
|
54
59
|
secret: string | null;
|
|
55
60
|
isActive: boolean;
|
|
56
61
|
createdAt: Date;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventSubscription.d.ts","sourceRoot":"","sources":["../../src/engine/eventSubscription.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAI5C,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"eventSubscription.d.ts","sourceRoot":"","sources":["../../src/engine/eventSubscription.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAI5C,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAOnC,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACJ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;YAmBuB,MAAM,EAAE;YACR;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;;;;;GAMvE;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM;;YAQ3C,MAAM,EAAE;YACR;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;;;;;KAMrE;AAED,wBAAsB,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;YAetD,MAAM,EAAE;YACR;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;;;;;UAMvE;AAED,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,oBAYlF;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM;;;;;;;;;;;;;KAiBlB"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { eq, and } from 'drizzle-orm';
|
|
2
2
|
import { eventSubscriptions } from '../db/schema.js';
|
|
3
3
|
import { generateId } from './snowflake.js';
|
|
4
|
+
function redactHeaders(headers) {
|
|
5
|
+
if (!headers)
|
|
6
|
+
return null;
|
|
7
|
+
return Object.fromEntries(Object.keys(headers).map((name) => [name, '[redacted]']));
|
|
8
|
+
}
|
|
4
9
|
export async function createSubscription(db, workspaceId, data) {
|
|
5
10
|
const id = `sub_${generateId()}`;
|
|
6
11
|
const [sub] = await db
|
|
@@ -11,6 +16,7 @@ export async function createSubscription(db, workspaceId, data) {
|
|
|
11
16
|
events: data.events,
|
|
12
17
|
filter: data.filter || null,
|
|
13
18
|
url: data.url,
|
|
19
|
+
headers: data.headers ?? null,
|
|
14
20
|
secret: data.secret || null,
|
|
15
21
|
})
|
|
16
22
|
.returning();
|
|
@@ -19,6 +25,7 @@ export async function createSubscription(db, workspaceId, data) {
|
|
|
19
25
|
events: sub.events,
|
|
20
26
|
filter: sub.filter,
|
|
21
27
|
url: sub.url,
|
|
28
|
+
headers: redactHeaders(sub.headers),
|
|
22
29
|
is_active: sub.isActive,
|
|
23
30
|
created_at: sub.createdAt.toISOString(),
|
|
24
31
|
};
|
|
@@ -33,6 +40,7 @@ export async function listSubscriptions(db, workspaceId) {
|
|
|
33
40
|
events: r.events,
|
|
34
41
|
filter: r.filter,
|
|
35
42
|
url: r.url,
|
|
43
|
+
headers: redactHeaders(r.headers),
|
|
36
44
|
is_active: r.isActive,
|
|
37
45
|
created_at: r.createdAt.toISOString(),
|
|
38
46
|
}));
|
|
@@ -49,6 +57,7 @@ export async function getSubscription(db, workspaceId, subId) {
|
|
|
49
57
|
events: row.events,
|
|
50
58
|
filter: row.filter,
|
|
51
59
|
url: row.url,
|
|
60
|
+
headers: redactHeaders(row.headers),
|
|
52
61
|
is_active: row.isActive,
|
|
53
62
|
created_at: row.createdAt.toISOString(),
|
|
54
63
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventSubscription.js","sourceRoot":"","sources":["../../src/engine/eventSubscription.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAI5C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,EAAM,EACN,WAAmB,EACnB,
|
|
1
|
+
{"version":3,"file":"eventSubscription.js","sourceRoot":"","sources":["../../src/engine/eventSubscription.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { getDb } from '../db/index.js';
|
|
2
2
|
type Db = ReturnType<typeof getDb>;
|
|
3
3
|
export declare function createWebhook(db: Db, workspaceId: string, channelId: string, data: {
|
|
4
|
-
name
|
|
4
|
+
name?: string;
|
|
5
5
|
}, createdBy?: string): Promise<{
|
|
6
6
|
webhook_id: string;
|
|
7
7
|
name: string;
|
|
8
8
|
channel: string;
|
|
9
9
|
url: string;
|
|
10
|
+
token: string;
|
|
10
11
|
is_active: boolean;
|
|
11
12
|
created_at: string;
|
|
12
13
|
}>;
|
|
@@ -27,9 +28,10 @@ export declare function getWebhook(db: Db, workspaceId: string, webhookId: strin
|
|
|
27
28
|
created_at: string;
|
|
28
29
|
} | null>;
|
|
29
30
|
export declare function deleteWebhook(db: Db, workspaceId: string, webhookId: string): Promise<boolean>;
|
|
30
|
-
export declare function triggerWebhook(db: Db, webhookId: string, data: {
|
|
31
|
+
export declare function triggerWebhook(db: Db, webhookId: string, token: string | null, data: {
|
|
31
32
|
text?: string;
|
|
32
33
|
source?: string;
|
|
34
|
+
author?: string;
|
|
33
35
|
payload?: Record<string, unknown>;
|
|
34
36
|
}): Promise<{
|
|
35
37
|
message_id: string;
|
|
@@ -39,6 +41,7 @@ export declare function triggerWebhook(db: Db, webhookId: string, data: {
|
|
|
39
41
|
channel: string;
|
|
40
42
|
text: string;
|
|
41
43
|
source: string | null;
|
|
44
|
+
author: string;
|
|
42
45
|
created_at: string;
|
|
43
46
|
} | null>;
|
|
44
47
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inboundWebhook.d.ts","sourceRoot":"","sources":["../../src/engine/inboundWebhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"inboundWebhook.d.ts","sourceRoot":"","sources":["../../src/engine/inboundWebhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAO5C,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAyCnC,wBAAsB,aAAa,CACjC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACvB,SAAS,CAAC,EAAE,MAAM;;;;;;;;GAkCnB;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM;;;;;;;KAuB7D;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;;;;;UAyB9E;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,oBAOjF;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,EAAE,EACN,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE;;;;;;;;;;UAoE7F"}
|
|
@@ -3,6 +3,7 @@ import { webhooks, channels, messages, agents } from '../db/schema.js';
|
|
|
3
3
|
import { randomHex, sha256Hex } from '../lib/crypto.js';
|
|
4
4
|
import { codedError } from '../lib/httpError.js';
|
|
5
5
|
import { generateId } from './snowflake.js';
|
|
6
|
+
import { inboundWebhookMessageMetadata } from './messageMetadata.js';
|
|
6
7
|
const WEBHOOK_AGENT_NAME = '__relay_webhook__';
|
|
7
8
|
async function ensureWebhookAgent(db, workspaceId) {
|
|
8
9
|
const [existing] = await db
|
|
@@ -38,6 +39,8 @@ async function ensureWebhookAgent(db, workspaceId) {
|
|
|
38
39
|
}
|
|
39
40
|
export async function createWebhook(db, workspaceId, channelId, data, createdBy) {
|
|
40
41
|
const id = `wh_${generateId()}`;
|
|
42
|
+
const token = `wh_live_${randomHex(24)}`;
|
|
43
|
+
const tokenHash = await sha256Hex(token);
|
|
41
44
|
const postingAgentId = createdBy ?? await ensureWebhookAgent(db, workspaceId);
|
|
42
45
|
const [webhook] = await db
|
|
43
46
|
.insert(webhooks)
|
|
@@ -45,8 +48,9 @@ export async function createWebhook(db, workspaceId, channelId, data, createdBy)
|
|
|
45
48
|
id,
|
|
46
49
|
workspaceId,
|
|
47
50
|
channelId,
|
|
48
|
-
name: data.name,
|
|
51
|
+
name: data.name ?? id,
|
|
49
52
|
createdBy: postingAgentId,
|
|
53
|
+
tokenHash,
|
|
50
54
|
})
|
|
51
55
|
.returning();
|
|
52
56
|
// Get channel name for response
|
|
@@ -59,6 +63,7 @@ export async function createWebhook(db, workspaceId, channelId, data, createdBy)
|
|
|
59
63
|
name: webhook.name,
|
|
60
64
|
channel: channel?.name || '',
|
|
61
65
|
url: `/v1/hooks/${webhook.id}`,
|
|
66
|
+
token,
|
|
62
67
|
is_active: webhook.isActive,
|
|
63
68
|
created_at: webhook.createdAt.toISOString(),
|
|
64
69
|
};
|
|
@@ -118,7 +123,7 @@ export async function deleteWebhook(db, workspaceId, webhookId) {
|
|
|
118
123
|
.returning();
|
|
119
124
|
return result.length > 0;
|
|
120
125
|
}
|
|
121
|
-
export async function triggerWebhook(db, webhookId, data) {
|
|
126
|
+
export async function triggerWebhook(db, webhookId, token, data) {
|
|
122
127
|
// Look up webhook
|
|
123
128
|
const [webhook] = await db
|
|
124
129
|
.select()
|
|
@@ -126,11 +131,21 @@ export async function triggerWebhook(db, webhookId, data) {
|
|
|
126
131
|
.where(and(eq(webhooks.id, webhookId), eq(webhooks.isActive, true)));
|
|
127
132
|
if (!webhook)
|
|
128
133
|
return null;
|
|
134
|
+
if (webhook.tokenHash) {
|
|
135
|
+
if (!token) {
|
|
136
|
+
throw codedError('Webhook bearer token required', 'webhook_token_required', 401);
|
|
137
|
+
}
|
|
138
|
+
const tokenHash = await sha256Hex(token);
|
|
139
|
+
if (tokenHash !== webhook.tokenHash) {
|
|
140
|
+
throw codedError('Invalid webhook bearer token', 'webhook_token_invalid', 401);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
129
143
|
// Build message text from payload or text
|
|
130
144
|
const text = data.text ||
|
|
131
145
|
(data.payload
|
|
132
146
|
? `Webhook ${webhook.name}: ${JSON.stringify(data.payload)}`
|
|
133
147
|
: `Webhook event from ${data.source || 'external'}`);
|
|
148
|
+
const author = data.author || data.source || webhook.name;
|
|
134
149
|
// Webhook must have a creator agent to post messages
|
|
135
150
|
if (!webhook.createdBy) {
|
|
136
151
|
throw codedError('Webhook has no associated agent and cannot post messages', 'webhook_no_agent', 422);
|
|
@@ -145,6 +160,12 @@ export async function triggerWebhook(db, webhookId, data) {
|
|
|
145
160
|
channelId: webhook.channelId,
|
|
146
161
|
agentId: webhook.createdBy,
|
|
147
162
|
body: text,
|
|
163
|
+
metadata: inboundWebhookMessageMetadata({
|
|
164
|
+
webhookId: webhook.id,
|
|
165
|
+
webhookName: webhook.name,
|
|
166
|
+
source: data.source ?? null,
|
|
167
|
+
author,
|
|
168
|
+
}),
|
|
148
169
|
})
|
|
149
170
|
.returning();
|
|
150
171
|
// Get channel name
|
|
@@ -160,6 +181,7 @@ export async function triggerWebhook(db, webhookId, data) {
|
|
|
160
181
|
channel: channel?.name || '',
|
|
161
182
|
text: message.body,
|
|
162
183
|
source: data.source || null,
|
|
184
|
+
author,
|
|
163
185
|
created_at: message.createdAt.toISOString(),
|
|
164
186
|
};
|
|
165
187
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inboundWebhook.js","sourceRoot":"","sources":["../../src/engine/inboundWebhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"inboundWebhook.js","sourceRoot":"","sources":["../../src/engine/inboundWebhook.ts"],"names":[],"mappings":"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"}
|