@mastra/factory 0.16.0-alpha.9 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/auth.js +1 -1
- package/dist/auth.js.map +1 -1
- package/dist/boards/review.d.ts.map +1 -1
- package/dist/boards/review.js +19 -8
- package/dist/boards/review.js.map +1 -1
- package/dist/boards/work.d.ts.map +1 -1
- package/dist/boards/work.js +31 -3
- package/dist/boards/work.js.map +1 -1
- package/dist/capabilities/intake.d.ts +4 -0
- package/dist/capabilities/intake.d.ts.map +1 -1
- package/dist/capabilities/version-control.d.ts +15 -0
- package/dist/capabilities/version-control.d.ts.map +1 -1
- package/dist/factory.d.ts +7 -7
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +100 -40
- package/dist/factory.js.map +1 -1
- package/dist/integrations/base.d.ts +3 -0
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +21 -0
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/routes.js +2 -1
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/sandbox.d.ts +41 -42
- package/dist/integrations/github/sandbox.d.ts.map +1 -1
- package/dist/integrations/github/sandbox.js +416 -227
- package/dist/integrations/github/sandbox.js.map +1 -1
- package/dist/integrations/github/webhook.d.ts +2 -5
- package/dist/integrations/github/webhook.d.ts.map +1 -1
- package/dist/integrations/github/webhook.js +8 -48
- package/dist/integrations/github/webhook.js.map +1 -1
- package/dist/integrations/gitlab/agent-tools.d.ts +14 -0
- package/dist/integrations/gitlab/agent-tools.d.ts.map +1 -0
- package/dist/integrations/gitlab/agent-tools.js +42 -0
- package/dist/integrations/gitlab/agent-tools.js.map +1 -0
- package/dist/integrations/gitlab/api.d.ts +222 -0
- package/dist/integrations/gitlab/api.d.ts.map +1 -0
- package/dist/integrations/gitlab/api.js +274 -0
- package/dist/integrations/gitlab/api.js.map +1 -0
- package/dist/integrations/gitlab/default-rules.d.ts +125 -0
- package/dist/integrations/gitlab/default-rules.d.ts.map +1 -0
- package/dist/integrations/gitlab/default-rules.js +172 -0
- package/dist/integrations/gitlab/default-rules.js.map +1 -0
- package/dist/integrations/gitlab/integration.d.ts +138 -0
- package/dist/integrations/gitlab/integration.d.ts.map +1 -0
- package/dist/integrations/gitlab/integration.js +705 -0
- package/dist/integrations/gitlab/integration.js.map +1 -0
- package/dist/integrations/gitlab/issue-reconciler.d.ts +6 -0
- package/dist/integrations/gitlab/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/gitlab/issue-reconciler.js +123 -0
- package/dist/integrations/gitlab/issue-reconciler.js.map +1 -0
- package/dist/integrations/gitlab/merge-request-reconciler.d.ts +6 -0
- package/dist/integrations/gitlab/merge-request-reconciler.d.ts.map +1 -0
- package/dist/integrations/gitlab/merge-request-reconciler.js +267 -0
- package/dist/integrations/gitlab/merge-request-reconciler.js.map +1 -0
- package/dist/integrations/gitlab/reconciler.d.ts +5 -0
- package/dist/integrations/gitlab/reconciler.d.ts.map +1 -0
- package/dist/integrations/gitlab/reconciler.js +31 -0
- package/dist/integrations/gitlab/reconciler.js.map +1 -0
- package/dist/integrations/gitlab/reconciliation-config.d.ts +3 -0
- package/dist/integrations/gitlab/reconciliation-config.d.ts.map +1 -0
- package/dist/integrations/gitlab/reconciliation-config.js +17 -0
- package/dist/integrations/gitlab/reconciliation-config.js.map +1 -0
- package/dist/integrations/gitlab/routes.d.ts +20 -0
- package/dist/integrations/gitlab/routes.d.ts.map +1 -0
- package/dist/integrations/gitlab/routes.js +473 -0
- package/dist/integrations/gitlab/routes.js.map +1 -0
- package/dist/integrations/gitlab/rules.d.ts +35 -0
- package/dist/integrations/gitlab/rules.d.ts.map +1 -0
- package/dist/integrations/gitlab/rules.js +391 -0
- package/dist/integrations/gitlab/rules.js.map +1 -0
- package/dist/integrations/gitlab/session-subscriptions.d.ts +32 -0
- package/dist/integrations/gitlab/session-subscriptions.d.ts.map +1 -0
- package/dist/integrations/gitlab/session-subscriptions.js +192 -0
- package/dist/integrations/gitlab/session-subscriptions.js.map +1 -0
- package/dist/integrations/gitlab/subscriptions.d.ts +70 -0
- package/dist/integrations/gitlab/subscriptions.d.ts.map +1 -0
- package/dist/integrations/gitlab/subscriptions.js +76 -0
- package/dist/integrations/gitlab/subscriptions.js.map +1 -0
- package/dist/integrations/gitlab/version-control.d.ts +16 -0
- package/dist/integrations/gitlab/version-control.d.ts.map +1 -0
- package/dist/integrations/gitlab/version-control.js +622 -0
- package/dist/integrations/gitlab/version-control.js.map +1 -0
- package/dist/integrations/gitlab/webhook-dispatch.d.ts +75 -0
- package/dist/integrations/gitlab/webhook-dispatch.d.ts.map +1 -0
- package/dist/integrations/gitlab/webhook-dispatch.js +235 -0
- package/dist/integrations/gitlab/webhook-dispatch.js.map +1 -0
- package/dist/integrations/gitlab/webhook.d.ts +72 -0
- package/dist/integrations/gitlab/webhook.d.ts.map +1 -0
- package/dist/integrations/gitlab/webhook.js +201 -0
- package/dist/integrations/gitlab/webhook.js.map +1 -0
- package/dist/integrations/incidentio/integration.js +1 -1
- package/dist/integrations/issue-reconciler.d.ts +3 -3
- package/dist/integrations/issue-reconciler.d.ts.map +1 -1
- package/dist/integrations/issue-reconciler.js +22 -2
- package/dist/integrations/issue-reconciler.js.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +21 -0
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/gitlab/event-worker.d.ts +64 -0
- package/dist/integrations/platform/gitlab/event-worker.d.ts.map +1 -0
- package/dist/integrations/platform/gitlab/event-worker.js +306 -0
- package/dist/integrations/platform/gitlab/event-worker.js.map +1 -0
- package/dist/integrations/platform/gitlab/integration.d.ts +57 -0
- package/dist/integrations/platform/gitlab/integration.d.ts.map +1 -0
- package/dist/integrations/platform/gitlab/integration.js +125 -0
- package/dist/integrations/platform/gitlab/integration.js.map +1 -0
- package/dist/integrations/platform/incidentio/integration.js +1 -1
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/integration.js +3 -3
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts +2 -0
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +21 -7
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/integrations/subscription-session.d.ts +37 -0
- package/dist/integrations/subscription-session.d.ts.map +1 -0
- package/dist/integrations/subscription-session.js +83 -0
- package/dist/integrations/subscription-session.js.map +1 -0
- package/dist/packages/_internals/workspace/dist/index.js +1 -11
- package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
- package/dist/routes/intake.d.ts.map +1 -1
- package/dist/routes/intake.js +4 -2
- package/dist/routes/intake.js.map +1 -1
- package/dist/routes/oauth.js +1 -1
- package/dist/routes/projects.d.ts +1 -0
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +1 -0
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/source-control-sessions.d.ts +20 -0
- package/dist/routes/source-control-sessions.d.ts.map +1 -0
- package/dist/routes/source-control-sessions.js +319 -0
- package/dist/routes/source-control-sessions.js.map +1 -0
- package/dist/routes/source-control-settings.d.ts +10 -0
- package/dist/routes/source-control-settings.d.ts.map +1 -0
- package/dist/routes/source-control-settings.js +87 -0
- package/dist/routes/source-control-settings.js.map +1 -0
- package/dist/routes/surface.d.ts +3 -3
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +55 -13
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/tenant-credentials.d.ts +8 -0
- package/dist/routes/tenant-credentials.d.ts.map +1 -1
- package/dist/routes/tenant-credentials.js +20 -3
- package/dist/routes/tenant-credentials.js.map +1 -1
- package/dist/routes/work-items.d.ts.map +1 -1
- package/dist/routes/work-items.js +1 -1
- package/dist/routes/work-items.js.map +1 -1
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +7 -1
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts +1 -1
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +3 -2
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/rules/transition-service.d.ts.map +1 -1
- package/dist/rules/transition-service.js +6 -3
- package/dist/rules/transition-service.js.map +1 -1
- package/dist/rules/types.d.ts +67 -3
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js +23 -2
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.d.ts.map +1 -1
- package/dist/rules/validation.js +2 -0
- package/dist/rules/validation.js.map +1 -1
- package/dist/sandbox/git-ref.d.ts +7 -0
- package/dist/sandbox/git-ref.d.ts.map +1 -0
- package/dist/sandbox/git-ref.js +15 -0
- package/dist/sandbox/git-ref.js.map +1 -0
- package/dist/sandbox/session-retirement.js +1 -1
- package/dist/sandbox/workdir.d.ts.map +1 -1
- package/dist/sandbox/workdir.js +6 -6
- package/dist/sandbox/workdir.js.map +1 -1
- package/dist/session/factory-session.d.ts +31 -1
- package/dist/session/factory-session.d.ts.map +1 -1
- package/dist/session/factory-session.js +60 -1
- package/dist/session/factory-session.js.map +1 -1
- package/dist/session/source-control-tools.d.ts +16 -0
- package/dist/session/source-control-tools.d.ts.map +1 -0
- package/dist/session/source-control-tools.js +464 -0
- package/dist/session/source-control-tools.js.map +1 -0
- package/dist/storage/domains/intake/base.d.ts +18 -0
- package/dist/storage/domains/intake/base.d.ts.map +1 -1
- package/dist/storage/domains/intake/base.js +77 -0
- package/dist/storage/domains/intake/base.js.map +1 -1
- package/dist/work-item-branch.d.ts +3 -1
- package/dist/work-item-branch.d.ts.map +1 -1
- package/dist/work-item-branch.js +22 -4
- package/dist/work-item-branch.js.map +1 -1
- package/dist/workspace.d.ts +15 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +57 -23
- package/dist/workspace.js.map +1 -1
- package/factory-skills/factory-gitlab-rereview/SKILL.md +19 -0
- package/factory-skills/factory-gitlab-review/SKILL.md +30 -0
- package/factory-skills/factory-rereview/SKILL.md +13 -6
- package/factory-skills/factory-review/SKILL.md +13 -6
- package/factory-skills/factory-review/references/archaeology.md +225 -0
- package/factory-skills/factory-review/references/categories/README.md +34 -0
- package/factory-skills/factory-review/references/categories/behavior-change.md +36 -0
- package/factory-skills/factory-review/references/categories/bug-fix.md +37 -0
- package/factory-skills/factory-review/references/categories/docs.md +32 -0
- package/factory-skills/factory-review/references/categories/experimental-flagged.md +34 -0
- package/factory-skills/factory-review/references/categories/infra-tooling.md +37 -0
- package/factory-skills/factory-review/references/categories/internal-capability.md +35 -0
- package/factory-skills/factory-review/references/categories/large-cross-cutting.md +35 -0
- package/factory-skills/factory-review/references/categories/mechanical.md +36 -0
- package/factory-skills/factory-review/references/categories/performance.md +33 -0
- package/factory-skills/factory-review/references/categories/public-api.md +38 -0
- package/factory-skills/factory-review/references/categories/refactor.md +35 -0
- package/factory-skills/factory-review/references/categories/revert.md +31 -0
- package/factory-skills/factory-review/references/categories/schema-storage.md +39 -0
- package/factory-skills/factory-review/references/categories/security.md +35 -0
- package/factory-skills/factory-review/references/categories/tests-only.md +38 -0
- package/package.json +9 -9
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { getFactoryAuthOrgId, getFactoryAuthUserFromContext, getFactoryAuthUserId } from "../../auth.js";
|
|
2
|
+
import { subscribeToMergeRequest, unsubscribeFromMergeRequest } from "./subscriptions.js";
|
|
3
|
+
import { normalizeGitLabHost } from "./integration.js";
|
|
4
|
+
import { createTool } from "@mastra/core/tools";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
//#region src/integrations/gitlab/session-subscriptions.ts
|
|
7
|
+
const MERGE_REQUEST_URL = /^https?:\/\/([^/\s]+)\/(.+?)\/-\/merge_requests\/(\d+)\/?$/i;
|
|
8
|
+
function sessionUserId(requestContext) {
|
|
9
|
+
return getFactoryAuthUserId(getFactoryAuthUserFromContext(requestContext));
|
|
10
|
+
}
|
|
11
|
+
function sessionOrgId(requestContext) {
|
|
12
|
+
return getFactoryAuthOrgId(getFactoryAuthUserFromContext(requestContext));
|
|
13
|
+
}
|
|
14
|
+
const mergeRequestInputSchema = z.object({ mergeRequest: z.union([z.number().int().positive(), z.string().min(1)]) });
|
|
15
|
+
function normalizePath(value) {
|
|
16
|
+
return value.replace(/^\/+|\/+$/g, "").toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
function parseMergeRequestUrl(url) {
|
|
19
|
+
const match = url.trim().match(MERGE_REQUEST_URL);
|
|
20
|
+
if (!match) return void 0;
|
|
21
|
+
const iid = Number(match[3]);
|
|
22
|
+
if (!Number.isSafeInteger(iid) || iid < 1) return void 0;
|
|
23
|
+
return {
|
|
24
|
+
host: normalizeGitLabHost(match[1]),
|
|
25
|
+
projectPath: match[2].replace(/\/+$/, ""),
|
|
26
|
+
iid
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function parseMergeRequest(value, target) {
|
|
30
|
+
if (typeof value === "number") return value;
|
|
31
|
+
if (/^\d+$/.test(value)) return Number(value);
|
|
32
|
+
const parsed = parseMergeRequestUrl(value);
|
|
33
|
+
if (!parsed || parsed.host !== target.host || normalizePath(parsed.projectPath) !== normalizePath(target.repository.slug)) throw new Error(`Merge request must belong to ${target.host}/${target.repository.slug}.`);
|
|
34
|
+
return parsed.iid;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether the current request comes from a session that merge-request
|
|
38
|
+
* subscriptions can ever apply to: an authenticated org user on a repository
|
|
39
|
+
* session with an active thread. Mirrors the GitHub gate; whether the
|
|
40
|
+
* repository is GitLab-linked is only known after a storage read, so the
|
|
41
|
+
* entry points verify that and fail loudly for the explicit tools.
|
|
42
|
+
*/
|
|
43
|
+
function isRepositorySession(requestContext) {
|
|
44
|
+
const context = requestContext.get("controller");
|
|
45
|
+
return Boolean(context?.threadId && context.getState().projectRepositoryId && sessionOrgId(requestContext) && sessionUserId(requestContext));
|
|
46
|
+
}
|
|
47
|
+
async function resolveSessionTarget(requestContext, gitlab) {
|
|
48
|
+
const context = requestContext.get("controller");
|
|
49
|
+
const orgId = sessionOrgId(requestContext);
|
|
50
|
+
const userId = sessionUserId(requestContext);
|
|
51
|
+
const projectRepositoryId = context?.getState().projectRepositoryId;
|
|
52
|
+
if (!context || !context.threadId || !projectRepositoryId || !orgId || !userId) throw new Error("GitLab subscriptions require an authenticated repository session with an active thread.");
|
|
53
|
+
const storage = gitlab.sourceControlStorage;
|
|
54
|
+
if (!storage) throw new Error("GitLab source control is unavailable.");
|
|
55
|
+
const projectRepository = await storage.projectRepositories.get({
|
|
56
|
+
orgId,
|
|
57
|
+
id: projectRepositoryId
|
|
58
|
+
});
|
|
59
|
+
if (!projectRepository) return void 0;
|
|
60
|
+
const connection = await storage.connections.get({
|
|
61
|
+
orgId,
|
|
62
|
+
id: projectRepository.connectionId
|
|
63
|
+
});
|
|
64
|
+
if (!connection || connection.integrationId !== "gitlab") return void 0;
|
|
65
|
+
const repository = await storage.repositories.get({
|
|
66
|
+
orgId,
|
|
67
|
+
id: projectRepository.repositoryId
|
|
68
|
+
});
|
|
69
|
+
if (!repository) throw new Error("Repository not found for this organization.");
|
|
70
|
+
const installation = await storage.installations.get({
|
|
71
|
+
orgId,
|
|
72
|
+
id: connection.installationId
|
|
73
|
+
});
|
|
74
|
+
if (!installation) throw new Error("Source-control installation not found for this organization.");
|
|
75
|
+
const host = installation.providerMetadata.host;
|
|
76
|
+
if (typeof host !== "string" || !host) throw new Error("GitLab installation is missing its instance host.");
|
|
77
|
+
return {
|
|
78
|
+
context,
|
|
79
|
+
projectRepository,
|
|
80
|
+
connection,
|
|
81
|
+
installation,
|
|
82
|
+
repository,
|
|
83
|
+
host: normalizeGitLabHost(host),
|
|
84
|
+
orgId,
|
|
85
|
+
userId
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async function requireGitLabSessionTarget(requestContext, gitlab) {
|
|
89
|
+
const target = await resolveSessionTarget(requestContext, gitlab);
|
|
90
|
+
if (!target) throw new Error("The active session is not backed by a GitLab repository.");
|
|
91
|
+
return target;
|
|
92
|
+
}
|
|
93
|
+
async function verifyMergeRequest(target, iid, gitlab) {
|
|
94
|
+
const repositoryTarget = await gitlab.versionControl.getRepositoryTarget({
|
|
95
|
+
orgId: target.orgId,
|
|
96
|
+
repositoryId: target.repository.id
|
|
97
|
+
});
|
|
98
|
+
const mergeRequest = await gitlab.versionControl.getPullRequest({
|
|
99
|
+
...repositoryTarget,
|
|
100
|
+
pullRequestId: String(iid)
|
|
101
|
+
});
|
|
102
|
+
if (!mergeRequest) throw new Error(`Merge request !${iid} was not found in ${target.repository.slug}.`);
|
|
103
|
+
const parsed = parseMergeRequestUrl(mergeRequest.url);
|
|
104
|
+
if (parsed && (parsed.host !== target.host || normalizePath(parsed.projectPath) !== normalizePath(target.repository.slug))) throw new Error("Merge request project does not match the active project repository.");
|
|
105
|
+
}
|
|
106
|
+
function subscriptionInput(target, iid) {
|
|
107
|
+
return {
|
|
108
|
+
orgId: target.orgId,
|
|
109
|
+
host: target.host,
|
|
110
|
+
projectId: target.repository.externalId,
|
|
111
|
+
projectPath: target.repository.slug,
|
|
112
|
+
projectRepositoryId: target.projectRepository.id,
|
|
113
|
+
installationExternalId: target.installation.externalId,
|
|
114
|
+
changeRequestId: String(iid),
|
|
115
|
+
sessionId: target.context.session.id,
|
|
116
|
+
ownerId: target.context.session.ownerId,
|
|
117
|
+
resourceId: target.connection.factoryProjectId,
|
|
118
|
+
threadId: target.context.threadId,
|
|
119
|
+
sessionScope: target.context.scope,
|
|
120
|
+
source: "explicit-tool",
|
|
121
|
+
subscribedByUserId: target.userId
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
async function subscribeCurrentSessionToMergeRequest(requestContext, mergeRequest, source, gitlab) {
|
|
125
|
+
if (source === "auto-create-change-request") {
|
|
126
|
+
if (!isRepositorySession(requestContext)) return void 0;
|
|
127
|
+
const target = await resolveSessionTarget(requestContext, gitlab);
|
|
128
|
+
if (!target) return void 0;
|
|
129
|
+
const iid = parseMergeRequest(mergeRequest, target);
|
|
130
|
+
await verifyMergeRequest(target, iid, gitlab);
|
|
131
|
+
await subscribeToMergeRequest({
|
|
132
|
+
...subscriptionInput(target, iid),
|
|
133
|
+
source
|
|
134
|
+
}, gitlab.integrationStorage);
|
|
135
|
+
return iid;
|
|
136
|
+
}
|
|
137
|
+
const target = await requireGitLabSessionTarget(requestContext, gitlab);
|
|
138
|
+
const iid = parseMergeRequest(mergeRequest, target);
|
|
139
|
+
await verifyMergeRequest(target, iid, gitlab);
|
|
140
|
+
await subscribeToMergeRequest({
|
|
141
|
+
...subscriptionInput(target, iid),
|
|
142
|
+
source
|
|
143
|
+
}, gitlab.integrationStorage);
|
|
144
|
+
return iid;
|
|
145
|
+
}
|
|
146
|
+
async function unsubscribeCurrentSessionFromMergeRequest(requestContext, mergeRequest, gitlab) {
|
|
147
|
+
const target = await requireGitLabSessionTarget(requestContext, gitlab);
|
|
148
|
+
const iid = parseMergeRequest(mergeRequest, target);
|
|
149
|
+
await unsubscribeFromMergeRequest(subscriptionInput(target, iid), gitlab.integrationStorage);
|
|
150
|
+
return iid;
|
|
151
|
+
}
|
|
152
|
+
function createGitLabSubscriptionTools(requestContext, gitlab) {
|
|
153
|
+
if (!isRepositorySession(requestContext)) return {};
|
|
154
|
+
return {
|
|
155
|
+
gitlab_subscribe_mr: createTool({
|
|
156
|
+
id: "gitlab_subscribe_mr",
|
|
157
|
+
description: "Subscribe this thread to GitLab merge request activity. You usually do not need this tool: successful source_control_create_change_request calls subscribe automatically. Use it for an existing MR or to recover when automatic subscription did not occur. Closed or merged MRs are unsubscribed automatically. Accepts an MR IID or canonical URL for the active project.",
|
|
158
|
+
inputSchema: mergeRequestInputSchema,
|
|
159
|
+
execute: async ({ mergeRequest }) => {
|
|
160
|
+
return {
|
|
161
|
+
subscribed: true,
|
|
162
|
+
mergeRequestIid: await subscribeCurrentSessionToMergeRequest(requestContext, mergeRequest, "explicit-tool", gitlab)
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}),
|
|
166
|
+
gitlab_unsubscribe_mr: createTool({
|
|
167
|
+
id: "gitlab_unsubscribe_mr",
|
|
168
|
+
description: "Manually unsubscribe this thread from GitLab merge request activity. You usually do not need this tool because closed or merged MRs are unsubscribed automatically. Use it to stop notifications before then. Accepts an MR IID or canonical URL for the active project.",
|
|
169
|
+
inputSchema: mergeRequestInputSchema,
|
|
170
|
+
execute: async ({ mergeRequest }) => {
|
|
171
|
+
return {
|
|
172
|
+
subscribed: false,
|
|
173
|
+
mergeRequestIid: await unsubscribeCurrentSessionFromMergeRequest(requestContext, mergeRequest, gitlab)
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The merge request URL a successful provider-neutral change-request creation
|
|
181
|
+
* reported, when that URL is a GitLab one. Anything else is not ours to observe.
|
|
182
|
+
*/
|
|
183
|
+
function parseCreatedMergeRequest(context) {
|
|
184
|
+
if (context.toolName !== "source_control_create_change_request" || context.error) return void 0;
|
|
185
|
+
const url = context.output?.url;
|
|
186
|
+
if (typeof url !== "string" || !parseMergeRequestUrl(url)) return void 0;
|
|
187
|
+
return url.trim().replace(/\/$/, "");
|
|
188
|
+
}
|
|
189
|
+
//#endregion
|
|
190
|
+
export { createGitLabSubscriptionTools, parseCreatedMergeRequest, parseMergeRequestUrl, subscribeCurrentSessionToMergeRequest, unsubscribeCurrentSessionFromMergeRequest };
|
|
191
|
+
|
|
192
|
+
//# sourceMappingURL=session-subscriptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-subscriptions.js","names":[],"sources":["../../../src/integrations/gitlab/session-subscriptions.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { getFactoryAuthOrgId, getFactoryAuthUserFromContext, getFactoryAuthUserId } from '../../auth.js';\nimport type {\n ProjectRepository,\n ProjectSourceControlConnection,\n SourceControlInstallation,\n SourceControlRepository,\n} from '../../storage/domains/source-control/base.js';\nimport type { GitLabIntegrationBase } from './integration.js';\nimport { normalizeGitLabHost } from './integration.js';\nimport { subscribeToMergeRequest, unsubscribeFromMergeRequest } from './subscriptions.js';\nimport type { GitLabSignalSubscriptionSource } from './subscriptions.js';\n\ntype RepositorySessionState = { factoryProjectId?: string; projectRepositoryId?: string };\n\nconst MERGE_REQUEST_URL = /^https?:\\/\\/([^/\\s]+)\\/(.+?)\\/-\\/merge_requests\\/(\\d+)\\/?$/i;\n\nfunction sessionUserId(requestContext: RequestContext): string | undefined {\n return getFactoryAuthUserId(getFactoryAuthUserFromContext(requestContext));\n}\n\nfunction sessionOrgId(requestContext: RequestContext): string | undefined {\n return getFactoryAuthOrgId(getFactoryAuthUserFromContext(requestContext));\n}\n\nconst mergeRequestInputSchema = z.object({\n mergeRequest: z.union([z.number().int().positive(), z.string().min(1)]),\n});\n\ninterface SessionTarget {\n context: AgentControllerRequestContext<RepositorySessionState>;\n projectRepository: ProjectRepository;\n connection: ProjectSourceControlConnection;\n installation: SourceControlInstallation;\n repository: SourceControlRepository;\n host: string;\n orgId: string;\n userId: string;\n}\n\nfunction normalizePath(value: string): string {\n return value.replace(/^\\/+|\\/+$/g, '').toLowerCase();\n}\n\nexport function parseMergeRequestUrl(url: string): { host: string; projectPath: string; iid: number } | undefined {\n const match = url.trim().match(MERGE_REQUEST_URL);\n if (!match) return undefined;\n const iid = Number(match[3]);\n if (!Number.isSafeInteger(iid) || iid < 1) return undefined;\n return { host: normalizeGitLabHost(match[1]!), projectPath: match[2]!.replace(/\\/+$/, ''), iid };\n}\n\nfunction parseMergeRequest(value: number | string, target: SessionTarget): number {\n if (typeof value === 'number') return value;\n if (/^\\d+$/.test(value)) return Number(value);\n const parsed = parseMergeRequestUrl(value);\n if (\n !parsed ||\n parsed.host !== target.host ||\n normalizePath(parsed.projectPath) !== normalizePath(target.repository.slug)\n ) {\n throw new Error(`Merge request must belong to ${target.host}/${target.repository.slug}.`);\n }\n return parsed.iid;\n}\n\n/**\n * Whether the current request comes from a session that merge-request\n * subscriptions can ever apply to: an authenticated org user on a repository\n * session with an active thread. Mirrors the GitHub gate; whether the\n * repository is GitLab-linked is only known after a storage read, so the\n * entry points verify that and fail loudly for the explicit tools.\n */\nfunction isRepositorySession(requestContext: RequestContext): boolean {\n const context = requestContext.get('controller') as AgentControllerRequestContext<RepositorySessionState> | undefined;\n return Boolean(\n context?.threadId &&\n context.getState().projectRepositoryId &&\n sessionOrgId(requestContext) &&\n sessionUserId(requestContext),\n );\n}\n\nasync function resolveSessionTarget(\n requestContext: RequestContext,\n gitlab: GitLabIntegrationBase,\n): Promise<SessionTarget | undefined> {\n const context = requestContext.get('controller') as AgentControllerRequestContext<RepositorySessionState> | undefined;\n const orgId = sessionOrgId(requestContext);\n const userId = sessionUserId(requestContext);\n const projectRepositoryId = context?.getState().projectRepositoryId;\n if (!context || !context.threadId || !projectRepositoryId || !orgId || !userId) {\n throw new Error('GitLab subscriptions require an authenticated repository session with an active thread.');\n }\n const storage = gitlab.sourceControlStorage;\n if (!storage) throw new Error('GitLab source control is unavailable.');\n\n // The handle is scoped to GitLab rows, so a GitHub-linked repository is\n // simply absent here rather than misidentified.\n const projectRepository = await storage.projectRepositories.get({ orgId, id: projectRepositoryId });\n if (!projectRepository) return undefined;\n const connection = await storage.connections.get({ orgId, id: projectRepository.connectionId });\n if (!connection || connection.integrationId !== 'gitlab') return undefined;\n const repository = await storage.repositories.get({ orgId, id: projectRepository.repositoryId });\n if (!repository) throw new Error('Repository not found for this organization.');\n const installation = await storage.installations.get({ orgId, id: connection.installationId });\n if (!installation) throw new Error('Source-control installation not found for this organization.');\n const host = installation.providerMetadata.host;\n if (typeof host !== 'string' || !host) throw new Error('GitLab installation is missing its instance host.');\n return {\n context,\n projectRepository,\n connection,\n installation,\n repository,\n host: normalizeGitLabHost(host),\n orgId,\n userId,\n };\n}\n\nasync function requireGitLabSessionTarget(\n requestContext: RequestContext,\n gitlab: GitLabIntegrationBase,\n): Promise<SessionTarget> {\n const target = await resolveSessionTarget(requestContext, gitlab);\n if (!target) throw new Error('The active session is not backed by a GitLab repository.');\n return target;\n}\n\nasync function verifyMergeRequest(target: SessionTarget, iid: number, gitlab: GitLabIntegrationBase): Promise<void> {\n const repositoryTarget = await gitlab.versionControl.getRepositoryTarget({\n orgId: target.orgId,\n repositoryId: target.repository.id,\n });\n const mergeRequest = await gitlab.versionControl.getPullRequest({ ...repositoryTarget, pullRequestId: String(iid) });\n if (!mergeRequest) throw new Error(`Merge request !${iid} was not found in ${target.repository.slug}.`);\n const parsed = parseMergeRequestUrl(mergeRequest.url);\n if (\n parsed &&\n (parsed.host !== target.host || normalizePath(parsed.projectPath) !== normalizePath(target.repository.slug))\n ) {\n throw new Error('Merge request project does not match the active project repository.');\n }\n}\n\nfunction subscriptionInput(target: SessionTarget, iid: number) {\n return {\n orgId: target.orgId,\n host: target.host,\n projectId: target.repository.externalId,\n projectPath: target.repository.slug,\n projectRepositoryId: target.projectRepository.id,\n installationExternalId: target.installation.externalId,\n changeRequestId: String(iid),\n sessionId: target.context.session.id,\n ownerId: target.context.session.ownerId,\n resourceId: target.connection.factoryProjectId,\n threadId: target.context.threadId!,\n sessionScope: target.context.scope,\n source: 'explicit-tool' as GitLabSignalSubscriptionSource,\n subscribedByUserId: target.userId,\n };\n}\n\nexport async function subscribeCurrentSessionToMergeRequest(\n requestContext: RequestContext,\n mergeRequest: number | string,\n source: GitLabSignalSubscriptionSource,\n gitlab: GitLabIntegrationBase,\n): Promise<number | undefined> {\n // The auto path observes every successful change-request creation in every\n // session, including GitHub-project sessions where a GitLab subscription can\n // never apply. Skip silently there; only the explicit tool should surface\n // \"this session cannot subscribe\" as an error.\n if (source === 'auto-create-change-request') {\n if (!isRepositorySession(requestContext)) return undefined;\n const target = await resolveSessionTarget(requestContext, gitlab);\n if (!target) return undefined;\n const iid = parseMergeRequest(mergeRequest, target);\n await verifyMergeRequest(target, iid, gitlab);\n await subscribeToMergeRequest({ ...subscriptionInput(target, iid), source }, gitlab.integrationStorage);\n return iid;\n }\n const target = await requireGitLabSessionTarget(requestContext, gitlab);\n const iid = parseMergeRequest(mergeRequest, target);\n await verifyMergeRequest(target, iid, gitlab);\n await subscribeToMergeRequest({ ...subscriptionInput(target, iid), source }, gitlab.integrationStorage);\n return iid;\n}\n\nexport async function unsubscribeCurrentSessionFromMergeRequest(\n requestContext: RequestContext,\n mergeRequest: number | string,\n gitlab: GitLabIntegrationBase,\n): Promise<number> {\n const target = await requireGitLabSessionTarget(requestContext, gitlab);\n const iid = parseMergeRequest(mergeRequest, target);\n await unsubscribeFromMergeRequest(subscriptionInput(target, iid), gitlab.integrationStorage);\n return iid;\n}\n\nexport function createGitLabSubscriptionTools(requestContext: RequestContext, gitlab: GitLabIntegrationBase) {\n if (!isRepositorySession(requestContext)) return {};\n\n return {\n gitlab_subscribe_mr: createTool({\n id: 'gitlab_subscribe_mr',\n description:\n 'Subscribe this thread to GitLab merge request activity. You usually do not need this tool: successful source_control_create_change_request calls subscribe automatically. Use it for an existing MR or to recover when automatic subscription did not occur. Closed or merged MRs are unsubscribed automatically. Accepts an MR IID or canonical URL for the active project.',\n inputSchema: mergeRequestInputSchema,\n execute: async ({ mergeRequest }) => {\n const iid = await subscribeCurrentSessionToMergeRequest(requestContext, mergeRequest, 'explicit-tool', gitlab);\n return { subscribed: true, mergeRequestIid: iid };\n },\n }),\n gitlab_unsubscribe_mr: createTool({\n id: 'gitlab_unsubscribe_mr',\n description:\n 'Manually unsubscribe this thread from GitLab merge request activity. You usually do not need this tool because closed or merged MRs are unsubscribed automatically. Use it to stop notifications before then. Accepts an MR IID or canonical URL for the active project.',\n inputSchema: mergeRequestInputSchema,\n execute: async ({ mergeRequest }) => {\n const iid = await unsubscribeCurrentSessionFromMergeRequest(requestContext, mergeRequest, gitlab);\n return { subscribed: false, mergeRequestIid: iid };\n },\n }),\n };\n}\n\n/**\n * The merge request URL a successful provider-neutral change-request creation\n * reported, when that URL is a GitLab one. Anything else is not ours to observe.\n */\nexport function parseCreatedMergeRequest(context: {\n toolName: string;\n input: unknown;\n output?: unknown;\n error?: unknown;\n}): string | undefined {\n if (context.toolName !== 'source_control_create_change_request' || context.error) return undefined;\n const url = (context.output as { url?: unknown } | undefined)?.url;\n if (typeof url !== 'string' || !parseMergeRequestUrl(url)) return undefined;\n return url.trim().replace(/\\/$/, '');\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { IntegrationStorageHandle, IntegrationSubscription } from '../../storage/domains/integrations/base.js';
|
|
2
|
+
export type GitLabSignalSubscriptionSource = 'auto-create-change-request' | 'explicit-tool';
|
|
3
|
+
export type GitLabSignalSubscriptionStatus = 'open' | 'closed' | 'merged';
|
|
4
|
+
export interface GitLabSignalSubscriptionData {
|
|
5
|
+
/** Normalized GitLab instance host. */
|
|
6
|
+
host: string;
|
|
7
|
+
/** Immutable numeric GitLab project id, as stored on the repository row. */
|
|
8
|
+
projectId: string;
|
|
9
|
+
/** Project `path_with_namespace`, used for links and summaries. */
|
|
10
|
+
projectPath: string;
|
|
11
|
+
projectRepositoryId: string;
|
|
12
|
+
/** The stored connection id of the installation the link was created under. */
|
|
13
|
+
installationExternalId: string;
|
|
14
|
+
/** Merge request IID. */
|
|
15
|
+
changeRequestId: string;
|
|
16
|
+
ownerId: string;
|
|
17
|
+
source: GitLabSignalSubscriptionSource;
|
|
18
|
+
subscribedByUserId: string | null;
|
|
19
|
+
}
|
|
20
|
+
export type GitLabSignalSubscriptionRow = IntegrationSubscription<GitLabSignalSubscriptionData>;
|
|
21
|
+
export type GitLabSubscriptionStorage = IntegrationStorageHandle<Record<string, unknown>, Record<string, unknown>, GitLabSignalSubscriptionData>;
|
|
22
|
+
export interface SubscribeToMergeRequestInput {
|
|
23
|
+
orgId: string;
|
|
24
|
+
host: string;
|
|
25
|
+
projectId: string;
|
|
26
|
+
projectPath: string;
|
|
27
|
+
projectRepositoryId: string;
|
|
28
|
+
installationExternalId: string;
|
|
29
|
+
changeRequestId: string;
|
|
30
|
+
sessionId: string;
|
|
31
|
+
ownerId: string;
|
|
32
|
+
resourceId: string;
|
|
33
|
+
threadId: string;
|
|
34
|
+
sessionScope?: string;
|
|
35
|
+
source: GitLabSignalSubscriptionSource;
|
|
36
|
+
subscribedByUserId?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface GitLabThreadSubscriptionTarget {
|
|
39
|
+
orgId: string;
|
|
40
|
+
resourceId: string;
|
|
41
|
+
threadId: string;
|
|
42
|
+
sessionScope?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface MergeRequestSubscriptionTarget {
|
|
45
|
+
orgId: string;
|
|
46
|
+
host: string;
|
|
47
|
+
projectId: string;
|
|
48
|
+
changeRequestId: string;
|
|
49
|
+
}
|
|
50
|
+
export type GitLabWebhookMergeRequestTarget = Omit<MergeRequestSubscriptionTarget, 'orgId'>;
|
|
51
|
+
export declare function normalizeSubscriptionHost(host: string): string;
|
|
52
|
+
export declare function mergeRequestTargetKey(input: GitLabWebhookMergeRequestTarget): string;
|
|
53
|
+
export declare function mergeRequestUrl(host: string, projectPath: string, changeRequestId: string | number): string;
|
|
54
|
+
export declare function subscribeToMergeRequest(input: SubscribeToMergeRequestInput, storage: GitLabSubscriptionStorage): Promise<GitLabSignalSubscriptionRow>;
|
|
55
|
+
export declare function unsubscribeFromMergeRequest(input: SubscribeToMergeRequestInput, storage: GitLabSubscriptionStorage): Promise<void>;
|
|
56
|
+
export declare function listMergeRequestSubscriptionsForThread(input: GitLabThreadSubscriptionTarget, storage: GitLabSubscriptionStorage): Promise<GitLabSignalSubscriptionRow[]>;
|
|
57
|
+
export declare function listMergeRequestSubscriptions(input: MergeRequestSubscriptionTarget, storage: GitLabSubscriptionStorage): Promise<GitLabSignalSubscriptionRow[]>;
|
|
58
|
+
export declare function listMergeRequestSubscriptionsForWebhook(input: GitLabWebhookMergeRequestTarget, options: {
|
|
59
|
+
includeTerminal?: boolean;
|
|
60
|
+
} | undefined, storage: GitLabSubscriptionStorage): Promise<GitLabSignalSubscriptionRow[]>;
|
|
61
|
+
export declare function retireMergeRequestSubscription(id: string, status: GitLabSignalSubscriptionStatus, storage: GitLabSubscriptionStorage): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Retire every open subscription for a merge request that reached a terminal
|
|
64
|
+
* state outside the webhook path (the reconcile sweep), so the thread's MR chip
|
|
65
|
+
* and the workspace row do not stay `open` on a deployment GitLab cannot reach.
|
|
66
|
+
*/
|
|
67
|
+
export declare function retireMergeRequestSubscriptions(input: GitLabWebhookMergeRequestTarget & {
|
|
68
|
+
merged: boolean;
|
|
69
|
+
}, storage: GitLabSubscriptionStorage): Promise<void>;
|
|
70
|
+
//# sourceMappingURL=subscriptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriptions.d.ts","sourceRoot":"","sources":["../../../src/integrations/gitlab/subscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAEpH,MAAM,MAAM,8BAA8B,GAAG,4BAA4B,GAAG,eAAe,CAAC;AAC5F,MAAM,MAAM,8BAA8B,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1E,MAAM,WAAW,4BAA4B;IAC3C,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,sBAAsB,EAAE,MAAM,CAAC;IAC/B,yBAAyB;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,8BAA8B,CAAC;IACvC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,MAAM,2BAA2B,GAAG,uBAAuB,CAAC,4BAA4B,CAAC,CAAC;AAChG,MAAM,MAAM,yBAAyB,GAAG,wBAAwB,CAC9D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,8BAA8B,CAAC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,+BAA+B,GAAG,IAAI,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;AAE5F,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,+BAA+B,GAAG,MAAM,CAEpF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAE3G;AAYD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,4BAA4B,EACnC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,2BAA2B,CAAC,CA4BtC;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,4BAA4B,EACnC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,sCAAsC,CAC1D,KAAK,EAAE,8BAA8B,EACrC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,2BAA2B,EAAE,CAAC,CAcxC;AAED,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,8BAA8B,EACrC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,2BAA2B,EAAE,CAAC,CAGxC;AAED,wBAAsB,uCAAuC,CAC3D,KAAK,EAAE,+BAA+B,EACtC,OAAO,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EAClD,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,2BAA2B,EAAE,CAAC,CAGxC;AAED,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,8BAA8B,EACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;GAIG;AACH,wBAAsB,+BAA+B,CACnD,KAAK,EAAE,+BAA+B,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAC5D,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//#region src/integrations/gitlab/subscriptions.ts
|
|
2
|
+
function normalizeSubscriptionHost(host) {
|
|
3
|
+
return host.trim().toLowerCase().replace(/\.$/, "");
|
|
4
|
+
}
|
|
5
|
+
function mergeRequestTargetKey(input) {
|
|
6
|
+
return `change-request:gitlab:${normalizeSubscriptionHost(input.host)}:${input.projectId}:${input.changeRequestId}`;
|
|
7
|
+
}
|
|
8
|
+
function mergeRequestUrl(host, projectPath, changeRequestId) {
|
|
9
|
+
return `https://${normalizeSubscriptionHost(host)}/${projectPath.replace(/^\/+|\/+$/g, "")}/-/merge_requests/${changeRequestId}`;
|
|
10
|
+
}
|
|
11
|
+
function sameSession(row, input) {
|
|
12
|
+
return row.orgId === input.orgId && row.sessionId === input.sessionId && row.resourceId === input.resourceId && row.threadId === input.threadId && (row.sessionScope ?? "") === (input.sessionScope ?? "");
|
|
13
|
+
}
|
|
14
|
+
async function subscribeToMergeRequest(input, storage) {
|
|
15
|
+
const targetKey = mergeRequestTargetKey(input);
|
|
16
|
+
const existing = (await storage.subscriptions.listByTarget(targetKey)).find((row) => sameSession(row, input));
|
|
17
|
+
if (existing) {
|
|
18
|
+
if (existing.status !== "open") await storage.subscriptions.updateStatus(existing.id, "open");
|
|
19
|
+
return {
|
|
20
|
+
...existing,
|
|
21
|
+
status: "open"
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return storage.subscriptions.create({
|
|
25
|
+
orgId: input.orgId,
|
|
26
|
+
targetKey,
|
|
27
|
+
sessionId: input.sessionId,
|
|
28
|
+
resourceId: input.resourceId,
|
|
29
|
+
threadId: input.threadId,
|
|
30
|
+
sessionScope: input.sessionScope ?? "",
|
|
31
|
+
status: "open",
|
|
32
|
+
data: {
|
|
33
|
+
host: normalizeSubscriptionHost(input.host),
|
|
34
|
+
projectId: input.projectId,
|
|
35
|
+
projectPath: input.projectPath,
|
|
36
|
+
projectRepositoryId: input.projectRepositoryId,
|
|
37
|
+
installationExternalId: input.installationExternalId,
|
|
38
|
+
changeRequestId: input.changeRequestId,
|
|
39
|
+
ownerId: input.ownerId,
|
|
40
|
+
source: input.source,
|
|
41
|
+
subscribedByUserId: input.subscribedByUserId ?? null
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async function unsubscribeFromMergeRequest(input, storage) {
|
|
46
|
+
const rows = await storage.subscriptions.listByTarget(mergeRequestTargetKey(input));
|
|
47
|
+
await Promise.all(rows.filter((row) => sameSession(row, input)).map((row) => storage.subscriptions.delete(row.id)));
|
|
48
|
+
}
|
|
49
|
+
async function listMergeRequestSubscriptionsForThread(input, storage) {
|
|
50
|
+
const matching = (await storage.subscriptions.listByThread(input.resourceId, input.threadId)).filter((row) => row.orgId === input.orgId && row.resourceId === input.resourceId && row.threadId === input.threadId && (row.sessionScope ?? "") === (input.sessionScope ?? ""));
|
|
51
|
+
if (matching.length > 0 || input.sessionScope) return matching;
|
|
52
|
+
return (await storage.subscriptions.listBySession(input.resourceId)).filter((row) => row.orgId === input.orgId && row.threadId === input.threadId && !row.sessionScope);
|
|
53
|
+
}
|
|
54
|
+
async function listMergeRequestSubscriptions(input, storage) {
|
|
55
|
+
return (await storage.subscriptions.listByTarget(mergeRequestTargetKey(input))).filter((row) => row.orgId === input.orgId && row.status === "open");
|
|
56
|
+
}
|
|
57
|
+
async function listMergeRequestSubscriptionsForWebhook(input, options, storage) {
|
|
58
|
+
const rows = await storage.subscriptions.listByTarget(mergeRequestTargetKey(input));
|
|
59
|
+
return options?.includeTerminal ? rows : rows.filter((row) => row.status === "open");
|
|
60
|
+
}
|
|
61
|
+
function retireMergeRequestSubscription(id, status, storage) {
|
|
62
|
+
return storage.subscriptions.updateStatus(id, status);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Retire every open subscription for a merge request that reached a terminal
|
|
66
|
+
* state outside the webhook path (the reconcile sweep), so the thread's MR chip
|
|
67
|
+
* and the workspace row do not stay `open` on a deployment GitLab cannot reach.
|
|
68
|
+
*/
|
|
69
|
+
async function retireMergeRequestSubscriptions(input, storage) {
|
|
70
|
+
const rows = await storage.subscriptions.listByTarget(mergeRequestTargetKey(input));
|
|
71
|
+
await Promise.all(rows.filter((row) => row.status === "open").map((row) => storage.subscriptions.updateStatus(row.id, input.merged ? "merged" : "closed")));
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { listMergeRequestSubscriptions, listMergeRequestSubscriptionsForThread, listMergeRequestSubscriptionsForWebhook, mergeRequestTargetKey, mergeRequestUrl, normalizeSubscriptionHost, retireMergeRequestSubscription, retireMergeRequestSubscriptions, subscribeToMergeRequest, unsubscribeFromMergeRequest };
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=subscriptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriptions.js","names":[],"sources":["../../../src/integrations/gitlab/subscriptions.ts"],"sourcesContent":["import type { IntegrationStorageHandle, IntegrationSubscription } from '../../storage/domains/integrations/base.js';\n\nexport type GitLabSignalSubscriptionSource = 'auto-create-change-request' | 'explicit-tool';\nexport type GitLabSignalSubscriptionStatus = 'open' | 'closed' | 'merged';\n\nexport interface GitLabSignalSubscriptionData {\n /** Normalized GitLab instance host. */\n host: string;\n /** Immutable numeric GitLab project id, as stored on the repository row. */\n projectId: string;\n /** Project `path_with_namespace`, used for links and summaries. */\n projectPath: string;\n projectRepositoryId: string;\n /** The stored connection id of the installation the link was created under. */\n installationExternalId: string;\n /** Merge request IID. */\n changeRequestId: string;\n ownerId: string;\n source: GitLabSignalSubscriptionSource;\n subscribedByUserId: string | null;\n}\n\nexport type GitLabSignalSubscriptionRow = IntegrationSubscription<GitLabSignalSubscriptionData>;\nexport type GitLabSubscriptionStorage = IntegrationStorageHandle<\n Record<string, unknown>,\n Record<string, unknown>,\n GitLabSignalSubscriptionData\n>;\n\nexport interface SubscribeToMergeRequestInput {\n orgId: string;\n host: string;\n projectId: string;\n projectPath: string;\n projectRepositoryId: string;\n installationExternalId: string;\n changeRequestId: string;\n sessionId: string;\n ownerId: string;\n resourceId: string;\n threadId: string;\n sessionScope?: string;\n source: GitLabSignalSubscriptionSource;\n subscribedByUserId?: string;\n}\n\nexport interface GitLabThreadSubscriptionTarget {\n orgId: string;\n resourceId: string;\n threadId: string;\n sessionScope?: string;\n}\n\nexport interface MergeRequestSubscriptionTarget {\n orgId: string;\n host: string;\n projectId: string;\n changeRequestId: string;\n}\n\nexport type GitLabWebhookMergeRequestTarget = Omit<MergeRequestSubscriptionTarget, 'orgId'>;\n\nexport function normalizeSubscriptionHost(host: string): string {\n return host.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nexport function mergeRequestTargetKey(input: GitLabWebhookMergeRequestTarget): string {\n return `change-request:gitlab:${normalizeSubscriptionHost(input.host)}:${input.projectId}:${input.changeRequestId}`;\n}\n\nexport function mergeRequestUrl(host: string, projectPath: string, changeRequestId: string | number): string {\n return `https://${normalizeSubscriptionHost(host)}/${projectPath.replace(/^\\/+|\\/+$/g, '')}/-/merge_requests/${changeRequestId}`;\n}\n\nfunction sameSession(row: GitLabSignalSubscriptionRow, input: SubscribeToMergeRequestInput): boolean {\n return (\n row.orgId === input.orgId &&\n row.sessionId === input.sessionId &&\n row.resourceId === input.resourceId &&\n row.threadId === input.threadId &&\n (row.sessionScope ?? '') === (input.sessionScope ?? '')\n );\n}\n\nexport async function subscribeToMergeRequest(\n input: SubscribeToMergeRequestInput,\n storage: GitLabSubscriptionStorage,\n): Promise<GitLabSignalSubscriptionRow> {\n const targetKey = mergeRequestTargetKey(input);\n const existing = (await storage.subscriptions.listByTarget(targetKey)).find(row => sameSession(row, input));\n if (existing) {\n if (existing.status !== 'open') await storage.subscriptions.updateStatus(existing.id, 'open');\n return { ...existing, status: 'open' };\n }\n\n return storage.subscriptions.create({\n orgId: input.orgId,\n targetKey,\n sessionId: input.sessionId,\n resourceId: input.resourceId,\n threadId: input.threadId,\n sessionScope: input.sessionScope ?? '',\n status: 'open',\n data: {\n host: normalizeSubscriptionHost(input.host),\n projectId: input.projectId,\n projectPath: input.projectPath,\n projectRepositoryId: input.projectRepositoryId,\n installationExternalId: input.installationExternalId,\n changeRequestId: input.changeRequestId,\n ownerId: input.ownerId,\n source: input.source,\n subscribedByUserId: input.subscribedByUserId ?? null,\n },\n });\n}\n\nexport async function unsubscribeFromMergeRequest(\n input: SubscribeToMergeRequestInput,\n storage: GitLabSubscriptionStorage,\n): Promise<void> {\n const rows = await storage.subscriptions.listByTarget(mergeRequestTargetKey(input));\n await Promise.all(rows.filter(row => sameSession(row, input)).map(row => storage.subscriptions.delete(row.id)));\n}\n\nexport async function listMergeRequestSubscriptionsForThread(\n input: GitLabThreadSubscriptionTarget,\n storage: GitLabSubscriptionStorage,\n): Promise<GitLabSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByThread(input.resourceId, input.threadId);\n const matching = rows.filter(\n row =>\n row.orgId === input.orgId &&\n row.resourceId === input.resourceId &&\n row.threadId === input.threadId &&\n (row.sessionScope ?? '') === (input.sessionScope ?? ''),\n );\n if (matching.length > 0 || input.sessionScope) return matching;\n // Same as GitHub: a user session addresses itself by its own id while its\n // rows name the owning Factory project, so fall back to the session's rows.\n const owned = await storage.subscriptions.listBySession(input.resourceId);\n return owned.filter(row => row.orgId === input.orgId && row.threadId === input.threadId && !row.sessionScope);\n}\n\nexport async function listMergeRequestSubscriptions(\n input: MergeRequestSubscriptionTarget,\n storage: GitLabSubscriptionStorage,\n): Promise<GitLabSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByTarget(mergeRequestTargetKey(input));\n return rows.filter(row => row.orgId === input.orgId && row.status === 'open');\n}\n\nexport async function listMergeRequestSubscriptionsForWebhook(\n input: GitLabWebhookMergeRequestTarget,\n options: { includeTerminal?: boolean } | undefined,\n storage: GitLabSubscriptionStorage,\n): Promise<GitLabSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByTarget(mergeRequestTargetKey(input));\n return options?.includeTerminal ? rows : rows.filter(row => row.status === 'open');\n}\n\nexport function retireMergeRequestSubscription(\n id: string,\n status: GitLabSignalSubscriptionStatus,\n storage: GitLabSubscriptionStorage,\n): Promise<void> {\n return storage.subscriptions.updateStatus(id, status);\n}\n\n/**\n * Retire every open subscription for a merge request that reached a terminal\n * state outside the webhook path (the reconcile sweep), so the thread's MR chip\n * and the workspace row do not stay `open` on a deployment GitLab cannot reach.\n */\nexport async function retireMergeRequestSubscriptions(\n input: GitLabWebhookMergeRequestTarget & { merged: boolean },\n storage: GitLabSubscriptionStorage,\n): Promise<void> {\n const rows = await storage.subscriptions.listByTarget(mergeRequestTargetKey(input));\n await Promise.all(\n rows\n .filter(row => row.status === 'open')\n .map(row => storage.subscriptions.updateStatus(row.id, input.merged ? 'merged' : 'closed')),\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IntegrationConnection } from '../../capabilities/connection.js';
|
|
2
|
+
import type { VersionControl } from '../../capabilities/version-control.js';
|
|
3
|
+
import type { GitLabApiClient } from './api.js';
|
|
4
|
+
export interface GitLabVersionControlContext {
|
|
5
|
+
api: GitLabApiClient;
|
|
6
|
+
connection: IntegrationConnection;
|
|
7
|
+
host: string;
|
|
8
|
+
webBaseUrl?: string;
|
|
9
|
+
repositoryAccessToken?: () => Promise<string>;
|
|
10
|
+
}
|
|
11
|
+
export interface GitLabVersionControlDependencies {
|
|
12
|
+
contextForConnection(connection: IntegrationConnection): Promise<GitLabVersionControlContext>;
|
|
13
|
+
contextForStoredInstallation?(connection: IntegrationConnection, host: string | undefined): Promise<GitLabVersionControlContext>;
|
|
14
|
+
}
|
|
15
|
+
export declare function buildGitLabVersionControl(deps: GitLabVersionControlDependencies): VersionControl;
|
|
16
|
+
//# sourceMappingURL=version-control.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-control.d.ts","sourceRoot":"","sources":["../../../src/integrations/gitlab/version-control.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,KAAK,EAMV,cAAc,EACf,MAAM,uCAAuC,CAAC;AAQ/C,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,eAAe,CAAC;IACrB,UAAU,EAAE,qBAAqB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,gCAAgC;IAC/C,oBAAoB,CAAC,UAAU,EAAE,qBAAqB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAC9F,4BAA4B,CAAC,CAAC,UAAU,EAAE,qBAAqB,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;CAClI;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,gCAAgC,GAAG,cAAc,CAmfhG"}
|