@mastra/factory 0.13.0 → 0.13.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/factory.d.ts +3 -2
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +5 -2
- package/dist/factory.js.map +1 -1
- package/dist/integrations/incidentio/api.d.ts +400 -0
- package/dist/integrations/incidentio/api.d.ts.map +1 -0
- package/dist/integrations/incidentio/api.js +192 -0
- package/dist/integrations/incidentio/api.js.map +1 -0
- package/dist/integrations/incidentio/intake.d.ts +10 -0
- package/dist/integrations/incidentio/intake.d.ts.map +1 -0
- package/dist/integrations/incidentio/intake.js +307 -0
- package/dist/integrations/incidentio/intake.js.map +1 -0
- package/dist/integrations/incidentio/integration.d.ts +17 -0
- package/dist/integrations/incidentio/integration.d.ts.map +1 -0
- package/dist/integrations/incidentio/integration.js +54 -0
- package/dist/integrations/incidentio/integration.js.map +1 -0
- package/dist/integrations/incidentio/issue-reconciler.d.ts +8 -0
- package/dist/integrations/incidentio/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/incidentio/issue-reconciler.js +39 -0
- package/dist/integrations/incidentio/issue-reconciler.js.map +1 -0
- package/dist/integrations/incidentio/reconciliation-config.d.ts +3 -0
- package/dist/integrations/incidentio/reconciliation-config.d.ts.map +1 -0
- package/dist/integrations/incidentio/reconciliation-config.js +17 -0
- package/dist/integrations/incidentio/reconciliation-config.js.map +1 -0
- package/dist/integrations/linear/reconciliation-config.d.ts.map +1 -1
- package/dist/integrations/linear/reconciliation-config.js +4 -10
- package/dist/integrations/linear/reconciliation-config.js.map +1 -1
- package/dist/integrations/platform/incidentio/integration.d.ts +17 -0
- package/dist/integrations/platform/incidentio/integration.d.ts.map +1 -0
- package/dist/integrations/platform/incidentio/integration.js +56 -0
- package/dist/integrations/platform/incidentio/integration.js.map +1 -0
- package/dist/integrations/reconciliation-config.d.ts +1 -0
- package/dist/integrations/reconciliation-config.d.ts.map +1 -1
- package/dist/integrations/reconciliation-config.js +8 -1
- package/dist/integrations/reconciliation-config.js.map +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../../../src/integrations/incidentio/intake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,KAAK,EAEV,MAAM,EASP,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,mBAAmB,EAKpB,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,8BAA8B,yBAAyB,CAAC;AACrE,eAAO,MAAM,+BAA+B,0BAA0B,CAAC;AAavE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,GAAG,EAAE,mBAAmB,CAAC;IACzB,UAAU,EAAE,qBAAqB,CAAC;CACnC,GAAG,MAAM,CAqIT"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { IncidentioApiError } from "./api.js";
|
|
2
|
+
//#region src/integrations/incidentio/intake.ts
|
|
3
|
+
const INCIDENTIO_INCIDENTS_SOURCE_ID = "incidentio:incidents";
|
|
4
|
+
const INCIDENTIO_FOLLOW_UPS_SOURCE_ID = "incidentio:follow-ups";
|
|
5
|
+
const INCIDENT_PREFIX = "incidentio:incident:";
|
|
6
|
+
const FOLLOW_UP_PREFIX = "incidentio:follow-up:";
|
|
7
|
+
const SOURCE_IDS = [INCIDENTIO_INCIDENTS_SOURCE_ID, INCIDENTIO_FOLLOW_UPS_SOURCE_ID];
|
|
8
|
+
function createIncidentioIntake(config) {
|
|
9
|
+
const assertConnection = (connection) => {
|
|
10
|
+
if (connection.type !== config.connection.type || connection.type !== "oauth" || config.connection.type !== "oauth" || connection.accessToken !== config.connection.accessToken) throw new Error("incident.io Intake received a connection it did not create.");
|
|
11
|
+
};
|
|
12
|
+
const listIssueEntries = async ({ sourceIds, labels, cursor }) => {
|
|
13
|
+
const selectedSources = SOURCE_IDS.filter((sourceId) => sourceIds.includes(sourceId));
|
|
14
|
+
const decodedCursor = decodePageCursor(cursor);
|
|
15
|
+
if (decodedCursor.sourceIndex >= selectedSources.length) return {
|
|
16
|
+
entries: [],
|
|
17
|
+
nextCursor: null
|
|
18
|
+
};
|
|
19
|
+
const sourceId = selectedSources[decodedCursor.sourceIndex];
|
|
20
|
+
let entries;
|
|
21
|
+
let providerCursor;
|
|
22
|
+
if (sourceId === "incidentio:incidents") {
|
|
23
|
+
const page = await config.api.listIncidents(decodedCursor.provider);
|
|
24
|
+
entries = page.items.map((incident) => {
|
|
25
|
+
const issue = incidentToIntakeIssue(incident);
|
|
26
|
+
return {
|
|
27
|
+
issue,
|
|
28
|
+
metadata: incidentIntakeMetadata(incident, issue)
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
providerCursor = page.nextCursor;
|
|
32
|
+
} else {
|
|
33
|
+
const page = await config.api.listFollowUps(decodedCursor.provider);
|
|
34
|
+
entries = page.items.map((followUp) => {
|
|
35
|
+
const issue = followUpToIntakeIssue(followUp);
|
|
36
|
+
return {
|
|
37
|
+
issue,
|
|
38
|
+
metadata: followUpIntakeMetadata(followUp, issue)
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
providerCursor = page.nextCursor;
|
|
42
|
+
}
|
|
43
|
+
entries = entries.filter(({ issue }) => isActive(issue.stateType) && matchesLabels(issue.labels, labels));
|
|
44
|
+
const nextCursor = providerCursor ? encodePageCursor({
|
|
45
|
+
sourceIndex: decodedCursor.sourceIndex,
|
|
46
|
+
provider: providerCursor
|
|
47
|
+
}) : decodedCursor.sourceIndex + 1 < selectedSources.length ? encodePageCursor({ sourceIndex: decodedCursor.sourceIndex + 1 }) : null;
|
|
48
|
+
return {
|
|
49
|
+
entries,
|
|
50
|
+
nextCursor
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const listIssues = async (input) => {
|
|
54
|
+
const page = await listIssueEntries(input);
|
|
55
|
+
return {
|
|
56
|
+
issues: page.entries.map(({ issue }) => issue),
|
|
57
|
+
nextCursor: page.nextCursor
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const getIssue = async ({ connection, issueId }) => {
|
|
61
|
+
assertConnection(connection);
|
|
62
|
+
const reference = decodeItemReference(issueId);
|
|
63
|
+
if (!reference) return null;
|
|
64
|
+
try {
|
|
65
|
+
if (reference.type === "incident") {
|
|
66
|
+
const incident = await config.api.getIncident(reference.id);
|
|
67
|
+
return {
|
|
68
|
+
...incidentToIntakeIssue(incident),
|
|
69
|
+
description: incident.summary ?? null,
|
|
70
|
+
comments: []
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const followUp = await config.api.getFollowUp(reference.id);
|
|
74
|
+
return {
|
|
75
|
+
...followUpToIntakeIssue(followUp),
|
|
76
|
+
description: followUp.description ?? null,
|
|
77
|
+
comments: []
|
|
78
|
+
};
|
|
79
|
+
} catch (error) {
|
|
80
|
+
if (error instanceof IncidentioApiError && error.status === 404) return null;
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
resolveIntakeDispatch: (input) => {
|
|
86
|
+
if (input.externalSource.type !== "issue") return Promise.resolve(null);
|
|
87
|
+
const reference = decodeItemReference(input.externalSource.externalId);
|
|
88
|
+
if (!reference) return Promise.resolve(null);
|
|
89
|
+
return Promise.resolve({
|
|
90
|
+
connection: config.connection,
|
|
91
|
+
sourceId: reference.type === "incident" ? INCIDENTIO_INCIDENTS_SOURCE_ID : INCIDENTIO_FOLLOW_UPS_SOURCE_ID,
|
|
92
|
+
issueId: input.externalSource.externalId
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
listSources: async () => [{
|
|
96
|
+
id: INCIDENTIO_INCIDENTS_SOURCE_ID,
|
|
97
|
+
name: "Incidents",
|
|
98
|
+
type: "incident"
|
|
99
|
+
}, {
|
|
100
|
+
id: INCIDENTIO_FOLLOW_UPS_SOURCE_ID,
|
|
101
|
+
name: "Incident follow-ups",
|
|
102
|
+
type: "follow-up"
|
|
103
|
+
}],
|
|
104
|
+
listItems: async (input) => {
|
|
105
|
+
const page = await listIssueEntries({
|
|
106
|
+
connection: config.connection,
|
|
107
|
+
sourceIds: input.sourceIds,
|
|
108
|
+
...input.cursor ? { cursor: input.cursor } : {}
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
items: page.entries.map(({ issue, metadata }) => ({
|
|
112
|
+
source: {
|
|
113
|
+
type: "issue",
|
|
114
|
+
externalId: issue.id,
|
|
115
|
+
url: issue.url
|
|
116
|
+
},
|
|
117
|
+
sourceId: issue.id.startsWith(INCIDENT_PREFIX) ? INCIDENTIO_INCIDENTS_SOURCE_ID : INCIDENTIO_FOLLOW_UPS_SOURCE_ID,
|
|
118
|
+
title: `${issue.identifier}: ${issue.title}`,
|
|
119
|
+
status: issue.state ?? void 0,
|
|
120
|
+
labels: issue.labels,
|
|
121
|
+
assignee: issue.assignee,
|
|
122
|
+
createdAt: issue.createdAt,
|
|
123
|
+
updatedAt: issue.updatedAt,
|
|
124
|
+
metadata
|
|
125
|
+
})),
|
|
126
|
+
nextCursor: page.nextCursor
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
listIssues: async (input) => {
|
|
130
|
+
assertConnection(input.connection);
|
|
131
|
+
return listIssues(input);
|
|
132
|
+
},
|
|
133
|
+
getIssue,
|
|
134
|
+
createComment: async (input) => {
|
|
135
|
+
assertConnection(input.connection);
|
|
136
|
+
return null;
|
|
137
|
+
},
|
|
138
|
+
updateIssue: async (input) => {
|
|
139
|
+
assertConnection(input.connection);
|
|
140
|
+
const reference = decodeItemReference(input.issueId);
|
|
141
|
+
if (!reference || reference.type !== "follow-up") return null;
|
|
142
|
+
let followUp;
|
|
143
|
+
try {
|
|
144
|
+
followUp = await config.api.getFollowUp(reference.id);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (error instanceof IncidentioApiError && error.status === 404) return null;
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
const status = followUpStatusForTarget(input);
|
|
150
|
+
if (!status) return null;
|
|
151
|
+
if (followUp.status === status) return followUpToIntakeIssue(followUp);
|
|
152
|
+
return followUpToIntakeIssue(await config.api.updateFollowUp(followUp, status));
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function incidentToIntakeIssue(incident) {
|
|
157
|
+
const labels = [
|
|
158
|
+
incident.severity?.name,
|
|
159
|
+
incident.incident_type?.name,
|
|
160
|
+
incident.mode
|
|
161
|
+
].filter((label) => Boolean(label));
|
|
162
|
+
return {
|
|
163
|
+
id: `${INCIDENT_PREFIX}${incident.id}`,
|
|
164
|
+
identifier: incident.reference,
|
|
165
|
+
title: incident.name,
|
|
166
|
+
url: incident.permalink ?? incident.slack_channel_url ?? incident.postmortem_document_url ?? `https://app.incident.io/incidents/${encodeURIComponent(incident.id)}`,
|
|
167
|
+
author: actorName(incident.creator),
|
|
168
|
+
state: incident.incident_status.name,
|
|
169
|
+
stateType: incidentStateType(incident.incident_status.category),
|
|
170
|
+
priority: incident.severity?.name ?? null,
|
|
171
|
+
assignee: null,
|
|
172
|
+
source: "Incident",
|
|
173
|
+
labels,
|
|
174
|
+
commentCount: 0,
|
|
175
|
+
createdAt: incident.created_at,
|
|
176
|
+
updatedAt: incident.updated_at
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function followUpToIntakeIssue(followUp) {
|
|
180
|
+
const assignees = [followUp.assignee?.name, followUp.assignee_team?.name].filter((assignee) => Boolean(assignee));
|
|
181
|
+
return {
|
|
182
|
+
id: `${FOLLOW_UP_PREFIX}${followUp.id}`,
|
|
183
|
+
identifier: followUp.external_issue_reference?.issue_name ?? followUp.id,
|
|
184
|
+
title: followUp.title,
|
|
185
|
+
url: followUp.external_issue_reference?.issue_permalink ?? `https://app.incident.io/incidents/${encodeURIComponent(followUp.incident_id)}`,
|
|
186
|
+
author: actorName(followUp.creator),
|
|
187
|
+
state: followUp.status,
|
|
188
|
+
stateType: followUpStateType(followUp.status),
|
|
189
|
+
priority: followUp.priority?.name ?? null,
|
|
190
|
+
assignee: assignees[0] ?? null,
|
|
191
|
+
assignees,
|
|
192
|
+
source: "Follow-up",
|
|
193
|
+
labels: followUp.labels,
|
|
194
|
+
commentCount: 0,
|
|
195
|
+
createdAt: followUp.created_at,
|
|
196
|
+
updatedAt: followUp.updated_at
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function intakeMetadata(issue) {
|
|
200
|
+
return {
|
|
201
|
+
identifier: issue.identifier,
|
|
202
|
+
autoStartCandidate: issue.stateType === "unstarted" || issue.stateType === "started",
|
|
203
|
+
incidentioState: issue.state,
|
|
204
|
+
incidentioStateType: issue.stateType,
|
|
205
|
+
incidentioPriority: issue.priority,
|
|
206
|
+
incidentioAssignee: issue.assignee,
|
|
207
|
+
stateType: issue.stateType,
|
|
208
|
+
priority: issue.priority,
|
|
209
|
+
source: issue.source,
|
|
210
|
+
assignee: issue.assignee,
|
|
211
|
+
assignees: issue.assignees ?? [],
|
|
212
|
+
creator: issue.author,
|
|
213
|
+
author: issue.author,
|
|
214
|
+
labels: issue.labels,
|
|
215
|
+
updatedAt: issue.updatedAt
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function incidentIntakeMetadata(incident, issue) {
|
|
219
|
+
return {
|
|
220
|
+
...intakeMetadata(issue),
|
|
221
|
+
incidentioItemType: "incident",
|
|
222
|
+
incidentioIncidentId: incident.id,
|
|
223
|
+
...incident.summary ? { incidentioDescription: incident.summary } : {}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function followUpIntakeMetadata(followUp, issue) {
|
|
227
|
+
return {
|
|
228
|
+
...intakeMetadata(issue),
|
|
229
|
+
incidentioItemType: "follow-up",
|
|
230
|
+
incidentioIncidentId: followUp.incident_id,
|
|
231
|
+
...followUp.description ? { incidentioDescription: followUp.description } : {}
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function actorName(actor) {
|
|
235
|
+
return actor.user?.name ?? actor.api_key?.name ?? actor.workflow?.name ?? actor.alert?.title ?? null;
|
|
236
|
+
}
|
|
237
|
+
function incidentStateType(category) {
|
|
238
|
+
switch (category) {
|
|
239
|
+
case "triage": return "unstarted";
|
|
240
|
+
case "declined":
|
|
241
|
+
case "canceled": return "canceled";
|
|
242
|
+
case "merged":
|
|
243
|
+
case "closed": return "completed";
|
|
244
|
+
case "live":
|
|
245
|
+
case "learning":
|
|
246
|
+
case "paused": return "started";
|
|
247
|
+
default: return null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function followUpStateType(status) {
|
|
251
|
+
switch (status) {
|
|
252
|
+
case "outstanding": return "unstarted";
|
|
253
|
+
case "completed": return "completed";
|
|
254
|
+
case "deleted":
|
|
255
|
+
case "not_doing": return "canceled";
|
|
256
|
+
default: return null;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function followUpStatusForTarget(input) {
|
|
260
|
+
if (input.state.kind === "byType") switch (input.state.stateType) {
|
|
261
|
+
case "unstarted":
|
|
262
|
+
case "started": return "outstanding";
|
|
263
|
+
case "completed": return "completed";
|
|
264
|
+
case "canceled": return "not_doing";
|
|
265
|
+
}
|
|
266
|
+
const status = input.state.name.toLowerCase().replaceAll("-", "_").replaceAll(" ", "_");
|
|
267
|
+
return status === "outstanding" || status === "completed" || status === "not_doing" ? status : null;
|
|
268
|
+
}
|
|
269
|
+
function isActive(stateType) {
|
|
270
|
+
return stateType !== "completed" && stateType !== "canceled";
|
|
271
|
+
}
|
|
272
|
+
function matchesLabels(issueLabels, requestedLabels) {
|
|
273
|
+
if (!requestedLabels?.length) return true;
|
|
274
|
+
const labels = new Set(issueLabels.map((label) => label.toLowerCase()));
|
|
275
|
+
return requestedLabels.every((label) => labels.has(label.toLowerCase()));
|
|
276
|
+
}
|
|
277
|
+
function decodeItemReference(value) {
|
|
278
|
+
if (value.startsWith(INCIDENT_PREFIX)) return {
|
|
279
|
+
type: "incident",
|
|
280
|
+
id: value.slice(20)
|
|
281
|
+
};
|
|
282
|
+
if (value.startsWith(FOLLOW_UP_PREFIX)) return {
|
|
283
|
+
type: "follow-up",
|
|
284
|
+
id: value.slice(21)
|
|
285
|
+
};
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
function encodePageCursor(cursor) {
|
|
289
|
+
return Buffer.from(JSON.stringify(cursor)).toString("base64url");
|
|
290
|
+
}
|
|
291
|
+
function decodePageCursor(cursor) {
|
|
292
|
+
if (!cursor) return { sourceIndex: 0 };
|
|
293
|
+
try {
|
|
294
|
+
const parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
|
|
295
|
+
if (!Number.isSafeInteger(parsed.sourceIndex) || (parsed.sourceIndex ?? -1) < 0) return { sourceIndex: 0 };
|
|
296
|
+
return {
|
|
297
|
+
sourceIndex: parsed.sourceIndex,
|
|
298
|
+
...typeof parsed.provider === "string" && parsed.provider ? { provider: parsed.provider } : {}
|
|
299
|
+
};
|
|
300
|
+
} catch {
|
|
301
|
+
return { sourceIndex: 0 };
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//#endregion
|
|
305
|
+
export { INCIDENTIO_FOLLOW_UPS_SOURCE_ID, INCIDENTIO_INCIDENTS_SOURCE_ID, createIncidentioIntake };
|
|
306
|
+
|
|
307
|
+
//# sourceMappingURL=intake.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intake.js","names":[],"sources":["../../../src/integrations/incidentio/intake.ts"],"sourcesContent":["import type { IntegrationConnection } from '../../capabilities/connection.js';\nimport type {\n GetIntakeIssueInput,\n Intake,\n IntakeIssue,\n IntakeIssueDetail,\n IntakeItemPage,\n ListIntakeIssuesInput,\n ListIntakeItemsInput,\n ResolveIntakeDispatchInput,\n ResolvedIntakeDispatch,\n UpdateIntakeIssueInput,\n} from '../../capabilities/intake.js';\nimport {\n IncidentioApiClient,\n IncidentioApiError,\n type IncidentioActor,\n type IncidentioFollowUp,\n type IncidentioIncident,\n} from './api.js';\n\nexport const INCIDENTIO_INCIDENTS_SOURCE_ID = 'incidentio:incidents';\nexport const INCIDENTIO_FOLLOW_UPS_SOURCE_ID = 'incidentio:follow-ups';\n\nconst INCIDENT_PREFIX = 'incidentio:incident:';\nconst FOLLOW_UP_PREFIX = 'incidentio:follow-up:';\nconst SOURCE_IDS = [INCIDENTIO_INCIDENTS_SOURCE_ID, INCIDENTIO_FOLLOW_UPS_SOURCE_ID] as const;\n\ntype IncidentioItemReference = { type: 'incident' | 'follow-up'; id: string };\ntype IncidentioPageCursor = { sourceIndex: number; provider?: string };\ninterface ListedIncidentioIssue {\n issue: IntakeIssue;\n metadata: Record<string, unknown>;\n}\n\nexport function createIncidentioIntake(config: {\n api: IncidentioApiClient;\n connection: IntegrationConnection;\n}): Intake {\n const assertConnection = (connection: IntegrationConnection): void => {\n if (\n connection.type !== config.connection.type ||\n connection.type !== 'oauth' ||\n config.connection.type !== 'oauth' ||\n connection.accessToken !== config.connection.accessToken\n ) {\n throw new Error('incident.io Intake received a connection it did not create.');\n }\n };\n\n const listIssueEntries = async ({ sourceIds, labels, cursor }: ListIntakeIssuesInput) => {\n const selectedSources = SOURCE_IDS.filter(sourceId => sourceIds.includes(sourceId));\n const decodedCursor = decodePageCursor(cursor);\n if (decodedCursor.sourceIndex >= selectedSources.length) {\n return { entries: [] as ListedIncidentioIssue[], nextCursor: null };\n }\n\n const sourceId = selectedSources[decodedCursor.sourceIndex]!;\n let entries: ListedIncidentioIssue[];\n let providerCursor: string | null;\n if (sourceId === INCIDENTIO_INCIDENTS_SOURCE_ID) {\n const page = await config.api.listIncidents(decodedCursor.provider);\n entries = page.items.map(incident => {\n const issue = incidentToIntakeIssue(incident);\n return { issue, metadata: incidentIntakeMetadata(incident, issue) };\n });\n providerCursor = page.nextCursor;\n } else {\n const page = await config.api.listFollowUps(decodedCursor.provider);\n entries = page.items.map(followUp => {\n const issue = followUpToIntakeIssue(followUp);\n return { issue, metadata: followUpIntakeMetadata(followUp, issue) };\n });\n providerCursor = page.nextCursor;\n }\n entries = entries.filter(({ issue }) => isActive(issue.stateType) && matchesLabels(issue.labels, labels));\n const nextCursor = providerCursor\n ? encodePageCursor({ sourceIndex: decodedCursor.sourceIndex, provider: providerCursor })\n : decodedCursor.sourceIndex + 1 < selectedSources.length\n ? encodePageCursor({ sourceIndex: decodedCursor.sourceIndex + 1 })\n : null;\n return { entries, nextCursor };\n };\n\n const listIssues = async (input: ListIntakeIssuesInput) => {\n const page = await listIssueEntries(input);\n return { issues: page.entries.map(({ issue }) => issue), nextCursor: page.nextCursor };\n };\n\n const getIssue = async ({ connection, issueId }: GetIntakeIssueInput): Promise<IntakeIssueDetail | null> => {\n assertConnection(connection);\n const reference = decodeItemReference(issueId);\n if (!reference) return null;\n try {\n if (reference.type === 'incident') {\n const incident = await config.api.getIncident(reference.id);\n return { ...incidentToIntakeIssue(incident), description: incident.summary ?? null, comments: [] };\n }\n const followUp = await config.api.getFollowUp(reference.id);\n return { ...followUpToIntakeIssue(followUp), description: followUp.description ?? null, comments: [] };\n } catch (error) {\n if (error instanceof IncidentioApiError && error.status === 404) return null;\n throw error;\n }\n };\n\n return {\n resolveIntakeDispatch: (input: ResolveIntakeDispatchInput): Promise<ResolvedIntakeDispatch | null> => {\n if (input.externalSource.type !== 'issue') return Promise.resolve(null);\n const reference = decodeItemReference(input.externalSource.externalId);\n if (!reference) return Promise.resolve(null);\n return Promise.resolve({\n connection: config.connection,\n sourceId:\n reference.type === 'incident' ? INCIDENTIO_INCIDENTS_SOURCE_ID : INCIDENTIO_FOLLOW_UPS_SOURCE_ID,\n issueId: input.externalSource.externalId,\n });\n },\n listSources: async () => [\n { id: INCIDENTIO_INCIDENTS_SOURCE_ID, name: 'Incidents', type: 'incident' },\n { id: INCIDENTIO_FOLLOW_UPS_SOURCE_ID, name: 'Incident follow-ups', type: 'follow-up' },\n ],\n listItems: async (input: ListIntakeItemsInput): Promise<IntakeItemPage> => {\n const page = await listIssueEntries({\n connection: config.connection,\n sourceIds: input.sourceIds,\n ...(input.cursor ? { cursor: input.cursor } : {}),\n });\n return {\n items: page.entries.map(({ issue, metadata }) => ({\n source: { type: 'issue', externalId: issue.id, url: issue.url },\n sourceId: issue.id.startsWith(INCIDENT_PREFIX)\n ? INCIDENTIO_INCIDENTS_SOURCE_ID\n : INCIDENTIO_FOLLOW_UPS_SOURCE_ID,\n title: `${issue.identifier}: ${issue.title}`,\n status: issue.state ?? undefined,\n labels: issue.labels,\n assignee: issue.assignee,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n metadata,\n })),\n nextCursor: page.nextCursor,\n };\n },\n listIssues: async input => {\n assertConnection(input.connection);\n return listIssues(input);\n },\n getIssue,\n createComment: async input => {\n assertConnection(input.connection);\n return null;\n },\n updateIssue: async (input: UpdateIntakeIssueInput): Promise<IntakeIssue | null> => {\n assertConnection(input.connection);\n const reference = decodeItemReference(input.issueId);\n if (!reference || reference.type !== 'follow-up') return null;\n let followUp: IncidentioFollowUp;\n try {\n followUp = await config.api.getFollowUp(reference.id);\n } catch (error) {\n if (error instanceof IncidentioApiError && error.status === 404) return null;\n throw error;\n }\n const status = followUpStatusForTarget(input);\n if (!status) return null;\n if (followUp.status === status) return followUpToIntakeIssue(followUp);\n return followUpToIntakeIssue(await config.api.updateFollowUp(followUp, status));\n },\n };\n}\n\nfunction incidentToIntakeIssue(incident: IncidentioIncident): IntakeIssue {\n const labels = [incident.severity?.name, incident.incident_type?.name, incident.mode].filter(\n (label): label is string => Boolean(label),\n );\n return {\n id: `${INCIDENT_PREFIX}${incident.id}`,\n identifier: incident.reference,\n title: incident.name,\n url:\n incident.permalink ??\n incident.slack_channel_url ??\n incident.postmortem_document_url ??\n `https://app.incident.io/incidents/${encodeURIComponent(incident.id)}`,\n author: actorName(incident.creator),\n state: incident.incident_status.name,\n stateType: incidentStateType(incident.incident_status.category),\n priority: incident.severity?.name ?? null,\n assignee: null,\n source: 'Incident',\n labels,\n commentCount: 0,\n createdAt: incident.created_at,\n updatedAt: incident.updated_at,\n };\n}\n\nfunction followUpToIntakeIssue(followUp: IncidentioFollowUp): IntakeIssue {\n const assignees = [followUp.assignee?.name, followUp.assignee_team?.name].filter(\n (assignee): assignee is string => Boolean(assignee),\n );\n return {\n id: `${FOLLOW_UP_PREFIX}${followUp.id}`,\n identifier: followUp.external_issue_reference?.issue_name ?? followUp.id,\n title: followUp.title,\n url:\n followUp.external_issue_reference?.issue_permalink ??\n `https://app.incident.io/incidents/${encodeURIComponent(followUp.incident_id)}`,\n author: actorName(followUp.creator),\n state: followUp.status,\n stateType: followUpStateType(followUp.status),\n priority: followUp.priority?.name ?? null,\n assignee: assignees[0] ?? null,\n assignees,\n source: 'Follow-up',\n labels: followUp.labels,\n commentCount: 0,\n createdAt: followUp.created_at,\n updatedAt: followUp.updated_at,\n };\n}\n\nfunction intakeMetadata(issue: IntakeIssue): Record<string, unknown> {\n return {\n identifier: issue.identifier,\n autoStartCandidate: issue.stateType === 'unstarted' || issue.stateType === 'started',\n incidentioState: issue.state,\n incidentioStateType: issue.stateType,\n incidentioPriority: issue.priority,\n incidentioAssignee: issue.assignee,\n stateType: issue.stateType,\n priority: issue.priority,\n source: issue.source,\n assignee: issue.assignee,\n assignees: issue.assignees ?? [],\n creator: issue.author,\n author: issue.author,\n labels: issue.labels,\n updatedAt: issue.updatedAt,\n };\n}\n\nfunction incidentIntakeMetadata(incident: IncidentioIncident, issue: IntakeIssue): Record<string, unknown> {\n return {\n ...intakeMetadata(issue),\n incidentioItemType: 'incident',\n incidentioIncidentId: incident.id,\n ...(incident.summary ? { incidentioDescription: incident.summary } : {}),\n };\n}\n\nfunction followUpIntakeMetadata(followUp: IncidentioFollowUp, issue: IntakeIssue): Record<string, unknown> {\n return {\n ...intakeMetadata(issue),\n incidentioItemType: 'follow-up',\n incidentioIncidentId: followUp.incident_id,\n ...(followUp.description ? { incidentioDescription: followUp.description } : {}),\n };\n}\n\nfunction actorName(actor: IncidentioActor): string | null {\n return actor.user?.name ?? actor.api_key?.name ?? actor.workflow?.name ?? actor.alert?.title ?? null;\n}\n\nfunction incidentStateType(category: string): string | null {\n switch (category) {\n case 'triage':\n return 'unstarted';\n case 'declined':\n case 'canceled':\n return 'canceled';\n case 'merged':\n case 'closed':\n return 'completed';\n case 'live':\n case 'learning':\n case 'paused':\n return 'started';\n default:\n return null;\n }\n}\n\nfunction followUpStateType(status: IncidentioFollowUp['status']): string | null {\n switch (status) {\n case 'outstanding':\n return 'unstarted';\n case 'completed':\n return 'completed';\n case 'deleted':\n case 'not_doing':\n return 'canceled';\n default:\n return null;\n }\n}\n\nfunction followUpStatusForTarget(input: UpdateIntakeIssueInput): IncidentioFollowUp['status'] | null {\n if (input.state.kind === 'byType') {\n switch (input.state.stateType) {\n case 'unstarted':\n case 'started':\n return 'outstanding';\n case 'completed':\n return 'completed';\n case 'canceled':\n return 'not_doing';\n }\n }\n const status = input.state.name.toLowerCase().replaceAll('-', '_').replaceAll(' ', '_');\n return status === 'outstanding' || status === 'completed' || status === 'not_doing' ? status : null;\n}\n\nfunction isActive(stateType: string | null): boolean {\n return stateType !== 'completed' && stateType !== 'canceled';\n}\n\nfunction matchesLabels(issueLabels: string[], requestedLabels: string[] | undefined): boolean {\n if (!requestedLabels?.length) return true;\n const labels = new Set(issueLabels.map(label => label.toLowerCase()));\n return requestedLabels.every(label => labels.has(label.toLowerCase()));\n}\n\nfunction decodeItemReference(value: string): IncidentioItemReference | null {\n if (value.startsWith(INCIDENT_PREFIX)) return { type: 'incident', id: value.slice(INCIDENT_PREFIX.length) };\n if (value.startsWith(FOLLOW_UP_PREFIX)) return { type: 'follow-up', id: value.slice(FOLLOW_UP_PREFIX.length) };\n return null;\n}\n\nfunction encodePageCursor(cursor: IncidentioPageCursor): string {\n return Buffer.from(JSON.stringify(cursor)).toString('base64url');\n}\n\nfunction decodePageCursor(cursor: string | undefined): IncidentioPageCursor {\n if (!cursor) return { sourceIndex: 0 };\n try {\n const parsed = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8')) as Partial<IncidentioPageCursor>;\n if (!Number.isSafeInteger(parsed.sourceIndex) || (parsed.sourceIndex ?? -1) < 0) return { sourceIndex: 0 };\n return {\n sourceIndex: parsed.sourceIndex!,\n ...(typeof parsed.provider === 'string' && parsed.provider ? { provider: parsed.provider } : {}),\n };\n } catch {\n return { sourceIndex: 0 };\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MastraWorker } from '@mastra/core/worker';
|
|
2
|
+
import type { FactoryIntegration, IntegrationContext } from '../base.js';
|
|
3
|
+
export interface IncidentioIntegrationConfig {
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
fetchImpl?: typeof fetch;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class IncidentioIntegration implements FactoryIntegration {
|
|
9
|
+
#private;
|
|
10
|
+
readonly id = "incidentio";
|
|
11
|
+
readonly intake: import("../../capabilities/intake.js").Intake;
|
|
12
|
+
constructor(config?: IncidentioIntegrationConfig);
|
|
13
|
+
workers(ctx: IntegrationContext): MastraWorker[];
|
|
14
|
+
routes(): [];
|
|
15
|
+
diagnostics(): Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=integration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../src/integrations/incidentio/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAOzE,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,qBAAa,qBAAsB,YAAW,kBAAkB;;IAC9D,QAAQ,CAAC,EAAE,gBAAgB;IAC3B,QAAQ,CAAC,MAAM,gDAAC;gBAGJ,MAAM,GAAE,2BAAgC;IAkBpD,OAAO,CAAC,GAAG,EAAE,kBAAkB,GAAG,YAAY,EAAE;IAchD,MAAM,IAAI,EAAE;IAIZ,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAGvC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { IncidentioApiClient } from "./api.js";
|
|
2
|
+
import { createIncidentioIntake } from "./intake.js";
|
|
3
|
+
import { attachIncidentioIssueReconciler } from "./issue-reconciler.js";
|
|
4
|
+
import { incidentioReconciliationEnabled, incidentioReconciliationInterval } from "./reconciliation-config.js";
|
|
5
|
+
import { IssueReconcileWorker } from "../issue-reconcile-worker.js";
|
|
6
|
+
//#region src/integrations/incidentio/integration.ts
|
|
7
|
+
const DIRECT_CONNECTION_TOKEN = "incidentio-direct-api-key";
|
|
8
|
+
var IncidentioIntegration = class {
|
|
9
|
+
id = "incidentio";
|
|
10
|
+
intake;
|
|
11
|
+
#endpointHost;
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
const apiKey = config.apiKey?.trim() || process.env.INCIDENT_IO_API_KEY?.trim();
|
|
14
|
+
if (!apiKey) throw new Error("IncidentioIntegration: missing required INCIDENT_IO_API_KEY.");
|
|
15
|
+
const baseUrl = config.baseUrl ?? "https://api.incident.io";
|
|
16
|
+
this.#endpointHost = new URL(baseUrl).host;
|
|
17
|
+
const api = new IncidentioApiClient({
|
|
18
|
+
baseUrl,
|
|
19
|
+
accessToken: apiKey,
|
|
20
|
+
...config.fetchImpl ? { fetchImpl: config.fetchImpl } : {}
|
|
21
|
+
});
|
|
22
|
+
this.intake = createIncidentioIntake({
|
|
23
|
+
api,
|
|
24
|
+
connection: {
|
|
25
|
+
type: "oauth",
|
|
26
|
+
accessToken: DIRECT_CONNECTION_TOKEN
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
workers(ctx) {
|
|
31
|
+
if (!incidentioReconciliationEnabled()) return [];
|
|
32
|
+
const reconcile = attachIncidentioIssueReconciler(this, ctx);
|
|
33
|
+
if (!reconcile) return [];
|
|
34
|
+
const intervalMs = incidentioReconciliationInterval();
|
|
35
|
+
return [new IssueReconcileWorker({
|
|
36
|
+
integrationId: this.id,
|
|
37
|
+
reconcile,
|
|
38
|
+
...intervalMs ? { intervalMs } : {}
|
|
39
|
+
})];
|
|
40
|
+
}
|
|
41
|
+
routes() {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
diagnostics() {
|
|
45
|
+
return {
|
|
46
|
+
mode: "api-key",
|
|
47
|
+
endpointHost: this.#endpointHost
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
export { IncidentioIntegration };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.js","names":["#endpointHost"],"sources":["../../../src/integrations/incidentio/integration.ts"],"sourcesContent":["import type { MastraWorker } from '@mastra/core/worker';\n\nimport type { FactoryIntegration, IntegrationContext } from '../base.js';\nimport { IssueReconcileWorker } from '../issue-reconcile-worker.js';\nimport { IncidentioApiClient } from './api.js';\nimport { createIncidentioIntake } from './intake.js';\nimport { attachIncidentioIssueReconciler } from './issue-reconciler.js';\nimport { incidentioReconciliationEnabled, incidentioReconciliationInterval } from './reconciliation-config.js';\n\nexport interface IncidentioIntegrationConfig {\n apiKey?: string;\n fetchImpl?: typeof fetch;\n baseUrl?: string;\n}\n\nconst DIRECT_CONNECTION_TOKEN = 'incidentio-direct-api-key';\n\nexport class IncidentioIntegration implements FactoryIntegration {\n readonly id = 'incidentio';\n readonly intake;\n readonly #endpointHost: string;\n\n constructor(config: IncidentioIntegrationConfig = {}) {\n const apiKey = config.apiKey?.trim() || process.env.INCIDENT_IO_API_KEY?.trim();\n if (!apiKey) {\n throw new Error('IncidentioIntegration: missing required INCIDENT_IO_API_KEY.');\n }\n const baseUrl = config.baseUrl ?? 'https://api.incident.io';\n this.#endpointHost = new URL(baseUrl).host;\n const api = new IncidentioApiClient({\n baseUrl,\n accessToken: apiKey,\n ...(config.fetchImpl ? { fetchImpl: config.fetchImpl } : {}),\n });\n this.intake = createIncidentioIntake({\n api,\n connection: { type: 'oauth', accessToken: DIRECT_CONNECTION_TOKEN },\n });\n }\n\n workers(ctx: IntegrationContext): MastraWorker[] {\n if (!incidentioReconciliationEnabled()) return [];\n const reconcile = attachIncidentioIssueReconciler(this, ctx);\n if (!reconcile) return [];\n const intervalMs = incidentioReconciliationInterval();\n return [\n new IssueReconcileWorker({\n integrationId: this.id,\n reconcile,\n ...(intervalMs ? { intervalMs } : {}),\n }),\n ];\n }\n\n routes(): [] {\n return [];\n }\n\n diagnostics(): Record<string, unknown> {\n return { mode: 'api-key', endpointHost: this.#endpointHost };\n }\n}\n"],"mappings":";;;;;;AAeA,MAAM,0BAA0B;AAEhC,IAAa,wBAAb,MAAiE;CAC/D,KAAc;CACd;CACA;CAEA,YAAY,SAAsC,CAAC,GAAG;EACpD,MAAM,SAAS,OAAO,QAAQ,KAAK,KAAK,QAAQ,IAAI,qBAAqB,KAAK;EAC9E,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,8DAA8D;EAEhF,MAAM,UAAU,OAAO,WAAW;EAClC,KAAKA,gBAAgB,IAAI,IAAI,OAAO,CAAC,CAAC;EACtC,MAAM,MAAM,IAAI,oBAAoB;GAClC;GACA,aAAa;GACb,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;EAC5D,CAAC;EACD,KAAK,SAAS,uBAAuB;GACnC;GACA,YAAY;IAAE,MAAM;IAAS,aAAa;GAAwB;EACpE,CAAC;CACH;CAEA,QAAQ,KAAyC;EAC/C,IAAI,CAAC,gCAAgC,GAAG,OAAO,CAAC;EAChD,MAAM,YAAY,gCAAgC,MAAM,GAAG;EAC3D,IAAI,CAAC,WAAW,OAAO,CAAC;EACxB,MAAM,aAAa,iCAAiC;EACpD,OAAO,CACL,IAAI,qBAAqB;GACvB,eAAe,KAAK;GACpB;GACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;EACrC,CAAC,CACH;CACF;CAEA,SAAa;EACX,OAAO,CAAC;CACV;CAEA,cAAuC;EACrC,OAAO;GAAE,MAAM;GAAW,cAAc,KAAKA;EAAc;CAC7D;AACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Intake } from '../../capabilities/intake.js';
|
|
2
|
+
import type { IntegrationContext } from '../base.js';
|
|
3
|
+
import type { IssueReconciler } from '../issue-reconciler.js';
|
|
4
|
+
export type IncidentioIssueReconciler = IssueReconciler;
|
|
5
|
+
export declare function attachIncidentioIssueReconciler(incidentio: {
|
|
6
|
+
intake: Intake;
|
|
7
|
+
}, context: IntegrationContext): IncidentioIssueReconciler | undefined;
|
|
8
|
+
//# sourceMappingURL=issue-reconciler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-reconciler.d.ts","sourceRoot":"","sources":["../../../src/integrations/incidentio/issue-reconciler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,MAAM,yBAAyB,GAAG,eAAe,CAAC;AAExD,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC9B,OAAO,EAAE,kBAAkB,GAC1B,yBAAyB,GAAG,SAAS,CA+BvC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { workItemPhaseSemantics } from "../../boards/semantics.js";
|
|
2
|
+
import "../../boards/index.js";
|
|
3
|
+
import { createIssueReconciler } from "../issue-reconciler.js";
|
|
4
|
+
//#region src/integrations/incidentio/issue-reconciler.ts
|
|
5
|
+
function attachIncidentioIssueReconciler(incidentio, context) {
|
|
6
|
+
if (!context.runtime || !incidentio.intake.resolveIntakeDispatch) return void 0;
|
|
7
|
+
const boards = context.runtime.boards;
|
|
8
|
+
return createIssueReconciler({
|
|
9
|
+
integrationId: "incidentio",
|
|
10
|
+
intake: incidentio.intake,
|
|
11
|
+
projects: context.storage.projects,
|
|
12
|
+
storage: context.runtime.workItems,
|
|
13
|
+
isTerminal: (item) => workItemPhaseSemantics(boards, item)?.kind === "terminal",
|
|
14
|
+
issueId: (item) => item.externalSource?.externalId,
|
|
15
|
+
metadata: (_item, issue) => ({
|
|
16
|
+
identifier: issue.identifier,
|
|
17
|
+
autoStartCandidate: issue.stateType === "unstarted" || issue.stateType === "started",
|
|
18
|
+
incidentioItemType: issue.source === "Follow-up" ? "follow-up" : "incident",
|
|
19
|
+
incidentioState: issue.state,
|
|
20
|
+
incidentioStateType: issue.stateType,
|
|
21
|
+
incidentioPriority: issue.priority,
|
|
22
|
+
incidentioAssignee: issue.assignee,
|
|
23
|
+
incidentioDescription: "description" in issue && typeof issue.description === "string" ? issue.description : null,
|
|
24
|
+
stateType: issue.stateType,
|
|
25
|
+
priority: issue.priority,
|
|
26
|
+
source: issue.source,
|
|
27
|
+
assignee: issue.assignee,
|
|
28
|
+
assignees: issue.assignees ?? [],
|
|
29
|
+
creator: issue.author,
|
|
30
|
+
author: issue.author,
|
|
31
|
+
labels: issue.labels ?? [],
|
|
32
|
+
updatedAt: issue.updatedAt
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { attachIncidentioIssueReconciler };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=issue-reconciler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-reconciler.js","names":[],"sources":["../../../src/integrations/incidentio/issue-reconciler.ts"],"sourcesContent":["import { workItemPhaseSemantics } from '../../boards/index.js';\nimport type { Intake } from '../../capabilities/intake.js';\nimport type { IntegrationContext } from '../base.js';\nimport { createIssueReconciler } from '../issue-reconciler.js';\nimport type { IssueReconciler } from '../issue-reconciler.js';\n\nexport type IncidentioIssueReconciler = IssueReconciler;\n\nexport function attachIncidentioIssueReconciler(\n incidentio: { intake: Intake },\n context: IntegrationContext,\n): IncidentioIssueReconciler | undefined {\n if (!context.runtime || !incidentio.intake.resolveIntakeDispatch) return undefined;\n const boards = context.runtime.boards;\n\n return createIssueReconciler({\n integrationId: 'incidentio',\n intake: incidentio.intake,\n projects: context.storage.projects,\n storage: context.runtime.workItems,\n isTerminal: item => workItemPhaseSemantics(boards, item)?.kind === 'terminal',\n issueId: item => item.externalSource?.externalId,\n metadata: (_item, issue) => ({\n identifier: issue.identifier,\n autoStartCandidate: issue.stateType === 'unstarted' || issue.stateType === 'started',\n incidentioItemType: issue.source === 'Follow-up' ? 'follow-up' : 'incident',\n incidentioState: issue.state,\n incidentioStateType: issue.stateType,\n incidentioPriority: issue.priority,\n incidentioAssignee: issue.assignee,\n incidentioDescription: 'description' in issue && typeof issue.description === 'string' ? issue.description : null,\n stateType: issue.stateType,\n priority: issue.priority,\n source: issue.source,\n assignee: issue.assignee,\n assignees: issue.assignees ?? [],\n creator: issue.author,\n author: issue.author,\n labels: issue.labels ?? [],\n updatedAt: issue.updatedAt,\n }),\n });\n}\n"],"mappings":";;;;AAQA,SAAgB,gCACd,YACA,SACuC;CACvC,IAAI,CAAC,QAAQ,WAAW,CAAC,WAAW,OAAO,uBAAuB,OAAO,KAAA;CACzE,MAAM,SAAS,QAAQ,QAAQ;CAE/B,OAAO,sBAAsB;EAC3B,eAAe;EACf,QAAQ,WAAW;EACnB,UAAU,QAAQ,QAAQ;EAC1B,SAAS,QAAQ,QAAQ;EACzB,aAAY,SAAQ,uBAAuB,QAAQ,IAAI,CAAC,EAAE,SAAS;EACnE,UAAS,SAAQ,KAAK,gBAAgB;EACtC,WAAW,OAAO,WAAW;GAC3B,YAAY,MAAM;GAClB,oBAAoB,MAAM,cAAc,eAAe,MAAM,cAAc;GAC3E,oBAAoB,MAAM,WAAW,cAAc,cAAc;GACjE,iBAAiB,MAAM;GACvB,qBAAqB,MAAM;GAC3B,oBAAoB,MAAM;GAC1B,oBAAoB,MAAM;GAC1B,uBAAuB,iBAAiB,SAAS,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc;GAC7G,WAAW,MAAM;GACjB,UAAU,MAAM;GAChB,QAAQ,MAAM;GACd,UAAU,MAAM;GAChB,WAAW,MAAM,aAAa,CAAC;GAC/B,SAAS,MAAM;GACf,QAAQ,MAAM;GACd,QAAQ,MAAM,UAAU,CAAC;GACzB,WAAW,MAAM;EACnB;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconciliation-config.d.ts","sourceRoot":"","sources":["../../../src/integrations/incidentio/reconciliation-config.ts"],"names":[],"mappings":"AAIA,wBAAgB,+BAA+B,IAAI,OAAO,CAQzD;AAED,wBAAgB,gCAAgC,IAAI,MAAM,GAAG,SAAS,CAQrE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { optionalBoolean, optionalPositiveInteger } from "../reconciliation-config.js";
|
|
2
|
+
//#region src/integrations/incidentio/reconciliation-config.ts
|
|
3
|
+
const RECONCILIATION_LABEL = "incident.io reconciliation";
|
|
4
|
+
function incidentioReconciliationEnabled() {
|
|
5
|
+
return optionalBoolean("MASTRACODE_INCIDENT_IO_RECONCILE_ENABLED", process.env.MASTRACODE_INCIDENT_IO_RECONCILE_ENABLED, RECONCILIATION_LABEL) ?? true;
|
|
6
|
+
}
|
|
7
|
+
function incidentioReconciliationInterval() {
|
|
8
|
+
const name = "MASTRACODE_INCIDENT_IO_RECONCILE_INTERVAL_MS";
|
|
9
|
+
const value = process.env.MASTRACODE_INCIDENT_IO_RECONCILE_INTERVAL_MS;
|
|
10
|
+
const interval = optionalPositiveInteger(value);
|
|
11
|
+
if (value?.trim() && interval === void 0) console.warn(`[${RECONCILIATION_LABEL}] ${name} must be a positive integer; received ${JSON.stringify(value)}.`);
|
|
12
|
+
return interval;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { incidentioReconciliationEnabled, incidentioReconciliationInterval };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=reconciliation-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconciliation-config.js","names":[],"sources":["../../../src/integrations/incidentio/reconciliation-config.ts"],"sourcesContent":["import { optionalBoolean, optionalPositiveInteger } from '../reconciliation-config.js';\n\nconst RECONCILIATION_LABEL = 'incident.io reconciliation';\n\nexport function incidentioReconciliationEnabled(): boolean {\n return (\n optionalBoolean(\n 'MASTRACODE_INCIDENT_IO_RECONCILE_ENABLED',\n process.env.MASTRACODE_INCIDENT_IO_RECONCILE_ENABLED,\n RECONCILIATION_LABEL,\n ) ?? true\n );\n}\n\nexport function incidentioReconciliationInterval(): number | undefined {\n const name = 'MASTRACODE_INCIDENT_IO_RECONCILE_INTERVAL_MS';\n const value = process.env.MASTRACODE_INCIDENT_IO_RECONCILE_INTERVAL_MS;\n const interval = optionalPositiveInteger(value);\n if (value?.trim() && interval === undefined) {\n console.warn(`[${RECONCILIATION_LABEL}] ${name} must be a positive integer; received ${JSON.stringify(value)}.`);\n }\n return interval;\n}\n"],"mappings":";;AAEA,MAAM,uBAAuB;AAE7B,SAAgB,kCAA2C;CACzD,OACE,gBACE,4CACA,QAAQ,IAAI,0CACZ,oBACF,KAAK;AAET;AAEA,SAAgB,mCAAuD;CACrE,MAAM,OAAO;CACb,MAAM,QAAQ,QAAQ,IAAI;CAC1B,MAAM,WAAW,wBAAwB,KAAK;CAC9C,IAAI,OAAO,KAAK,KAAK,aAAa,KAAA,GAChC,QAAQ,KAAK,IAAI,qBAAqB,IAAI,KAAK,wCAAwC,KAAK,UAAU,KAAK,EAAE,EAAE;CAEjH,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconciliation-config.d.ts","sourceRoot":"","sources":["../../../src/integrations/linear/reconciliation-config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reconciliation-config.d.ts","sourceRoot":"","sources":["../../../src/integrations/linear/reconciliation-config.ts"],"names":[],"mappings":"AAyBA,wBAAgB,gCAAgC,IAAI,OAAO,CAO1D;AAED,wBAAgB,iCAAiC,IAAI,MAAM,GAAG,SAAS,CAWtE"}
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
import { optionalPositiveInteger } from "../reconciliation-config.js";
|
|
1
|
+
import { optionalBoolean, optionalPositiveInteger } from "../reconciliation-config.js";
|
|
2
2
|
//#region src/integrations/linear/reconciliation-config.ts
|
|
3
|
+
const RECONCILIATION_LABEL = "Linear reconciliation";
|
|
3
4
|
function reconciliationEnabled(childName, childValue, legacyName, legacyValue) {
|
|
4
|
-
return
|
|
5
|
+
return optionalBoolean(childName, childValue, RECONCILIATION_LABEL) ?? optionalBoolean(legacyName, legacyValue, RECONCILIATION_LABEL) ?? true;
|
|
5
6
|
}
|
|
6
7
|
function optionalPositiveInterval(name, value) {
|
|
7
8
|
const interval = optionalPositiveInteger(value);
|
|
8
|
-
if (value?.trim() && interval === void 0) console.warn(`[
|
|
9
|
+
if (value?.trim() && interval === void 0) console.warn(`[${RECONCILIATION_LABEL}] ${name} must be a positive integer; received ${JSON.stringify(value)}.`);
|
|
9
10
|
return interval;
|
|
10
11
|
}
|
|
11
|
-
function parseBoolean(name, value) {
|
|
12
|
-
const normalized = value?.trim().toLowerCase();
|
|
13
|
-
if (!normalized) return void 0;
|
|
14
|
-
if (normalized === "true") return true;
|
|
15
|
-
if (normalized === "false") return false;
|
|
16
|
-
console.warn(`[Linear reconciliation] ${name} must be true or false; received ${JSON.stringify(value)}.`);
|
|
17
|
-
}
|
|
18
12
|
function linearIssueReconciliationEnabled() {
|
|
19
13
|
return reconciliationEnabled("MASTRACODE_LINEAR_ISSUE_RECONCILE_ENABLED", process.env.MASTRACODE_LINEAR_ISSUE_RECONCILE_ENABLED, "MASTRACODE_LINEAR_RECONCILE_ENABLED", process.env.MASTRACODE_LINEAR_RECONCILE_ENABLED);
|
|
20
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconciliation-config.js","names":[],"sources":["../../../src/integrations/linear/reconciliation-config.ts"],"sourcesContent":["import { optionalPositiveInteger } from '../reconciliation-config.js';\n\nfunction reconciliationEnabled(\n childName: string,\n childValue: string | undefined,\n legacyName: string,\n legacyValue: string | undefined,\n): boolean {\n return
|
|
1
|
+
{"version":3,"file":"reconciliation-config.js","names":[],"sources":["../../../src/integrations/linear/reconciliation-config.ts"],"sourcesContent":["import { optionalBoolean, optionalPositiveInteger } from '../reconciliation-config.js';\n\nconst RECONCILIATION_LABEL = 'Linear reconciliation';\n\nfunction reconciliationEnabled(\n childName: string,\n childValue: string | undefined,\n legacyName: string,\n legacyValue: string | undefined,\n): boolean {\n return (\n optionalBoolean(childName, childValue, RECONCILIATION_LABEL) ??\n optionalBoolean(legacyName, legacyValue, RECONCILIATION_LABEL) ??\n true\n );\n}\n\nfunction optionalPositiveInterval(name: string, value: string | undefined): number | undefined {\n const interval = optionalPositiveInteger(value);\n if (value?.trim() && interval === undefined) {\n console.warn(`[${RECONCILIATION_LABEL}] ${name} must be a positive integer; received ${JSON.stringify(value)}.`);\n }\n return interval;\n}\n\nexport function linearIssueReconciliationEnabled(): boolean {\n return reconciliationEnabled(\n 'MASTRACODE_LINEAR_ISSUE_RECONCILE_ENABLED',\n process.env.MASTRACODE_LINEAR_ISSUE_RECONCILE_ENABLED,\n 'MASTRACODE_LINEAR_RECONCILE_ENABLED',\n process.env.MASTRACODE_LINEAR_RECONCILE_ENABLED,\n );\n}\n\nexport function linearIssueReconciliationInterval(): number | undefined {\n return (\n optionalPositiveInterval(\n 'MASTRACODE_LINEAR_ISSUE_RECONCILE_INTERVAL_MS',\n process.env.MASTRACODE_LINEAR_ISSUE_RECONCILE_INTERVAL_MS,\n ) ??\n optionalPositiveInterval(\n 'MASTRACODE_LINEAR_RECONCILE_INTERVAL_MS',\n process.env.MASTRACODE_LINEAR_RECONCILE_INTERVAL_MS,\n )\n );\n}\n"],"mappings":";;AAEA,MAAM,uBAAuB;AAE7B,SAAS,sBACP,WACA,YACA,YACA,aACS;CACT,OACE,gBAAgB,WAAW,YAAY,oBAAoB,KAC3D,gBAAgB,YAAY,aAAa,oBAAoB,KAC7D;AAEJ;AAEA,SAAS,yBAAyB,MAAc,OAA+C;CAC7F,MAAM,WAAW,wBAAwB,KAAK;CAC9C,IAAI,OAAO,KAAK,KAAK,aAAa,KAAA,GAChC,QAAQ,KAAK,IAAI,qBAAqB,IAAI,KAAK,wCAAwC,KAAK,UAAU,KAAK,EAAE,EAAE;CAEjH,OAAO;AACT;AAEA,SAAgB,mCAA4C;CAC1D,OAAO,sBACL,6CACA,QAAQ,IAAI,2CACZ,uCACA,QAAQ,IAAI,mCACd;AACF;AAEA,SAAgB,oCAAwD;CACtE,OACE,yBACE,iDACA,QAAQ,IAAI,6CACd,KACA,yBACE,2CACA,QAAQ,IAAI,uCACd;AAEJ"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MastraWorker } from '@mastra/core/worker';
|
|
2
|
+
import type { FactoryIntegration, IntegrationContext } from '../../base.js';
|
|
3
|
+
import { type PlatformApiClientConfig } from '../api-client.js';
|
|
4
|
+
export interface PlatformIncidentioIntegrationConfig {
|
|
5
|
+
clientConfig?: PlatformApiClientConfig;
|
|
6
|
+
connectionId?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class PlatformIncidentioIntegration implements FactoryIntegration {
|
|
9
|
+
#private;
|
|
10
|
+
readonly id = "incidentio";
|
|
11
|
+
readonly intake: import("../../../capabilities/intake.js").Intake;
|
|
12
|
+
constructor(config?: PlatformIncidentioIntegrationConfig);
|
|
13
|
+
workers(ctx: IntegrationContext): MastraWorker[];
|
|
14
|
+
routes(): [];
|
|
15
|
+
diagnostics(): Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=integration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/incidentio/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAS5E,OAAO,EAAkC,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhG,MAAM,WAAW,mCAAmC;IAClD,YAAY,CAAC,EAAE,uBAAuB,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,qBAAa,6BAA8B,YAAW,kBAAkB;;IACtE,QAAQ,CAAC,EAAE,gBAAgB;IAC3B,QAAQ,CAAC,MAAM,mDAAC;gBAGJ,MAAM,GAAE,mCAAwC;IAsB5D,OAAO,CAAC,GAAG,EAAE,kBAAkB,GAAG,YAAY,EAAE;IAchD,MAAM,IAAI,EAAE;IAIZ,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAGvC"}
|