@mastra/factory 0.25.0-alpha.5 → 0.25.0-alpha.7

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.
Files changed (105) hide show
  1. package/README.md +3 -1
  2. package/dist/boards/work-transition-policy.d.ts.map +1 -1
  3. package/dist/boards/work-transition-policy.js +3 -3
  4. package/dist/boards/work-transition-policy.js.map +1 -1
  5. package/dist/default-thinking-level.d.ts +3 -0
  6. package/dist/default-thinking-level.d.ts.map +1 -0
  7. package/dist/default-thinking-level.js +5 -0
  8. package/dist/default-thinking-level.js.map +1 -0
  9. package/dist/factory.d.ts.map +1 -1
  10. package/dist/factory.js +19 -5
  11. package/dist/factory.js.map +1 -1
  12. package/dist/integrations/gitlab/integration.d.ts +4 -0
  13. package/dist/integrations/gitlab/integration.d.ts.map +1 -1
  14. package/dist/integrations/gitlab/integration.js +10 -1
  15. package/dist/integrations/gitlab/integration.js.map +1 -1
  16. package/dist/integrations/gitlab/routes.d.ts +6 -0
  17. package/dist/integrations/gitlab/routes.d.ts.map +1 -1
  18. package/dist/integrations/gitlab/routes.js +153 -1
  19. package/dist/integrations/gitlab/routes.js.map +1 -1
  20. package/dist/integrations/gitlab/rules.d.ts.map +1 -1
  21. package/dist/integrations/gitlab/rules.js +4 -1
  22. package/dist/integrations/gitlab/rules.js.map +1 -1
  23. package/dist/integrations/jira/api.d.ts +1 -1
  24. package/dist/integrations/jira/api.d.ts.map +1 -1
  25. package/dist/integrations/jira/api.js +1 -1
  26. package/dist/integrations/jira/api.js.map +1 -1
  27. package/dist/integrations/jira/integration.d.ts +3 -1
  28. package/dist/integrations/jira/integration.d.ts.map +1 -1
  29. package/dist/integrations/jira/integration.js +17 -2
  30. package/dist/integrations/jira/integration.js.map +1 -1
  31. package/dist/integrations/pull-request-head.d.ts +1 -0
  32. package/dist/integrations/pull-request-head.d.ts.map +1 -1
  33. package/dist/integrations/pull-request-head.js +2 -1
  34. package/dist/integrations/pull-request-head.js.map +1 -1
  35. package/dist/integrations/slack/channel-reply-processor.d.ts +1 -0
  36. package/dist/integrations/slack/channel-reply-processor.d.ts.map +1 -1
  37. package/dist/integrations/slack/channel-reply-processor.js +11 -3
  38. package/dist/integrations/slack/channel-reply-processor.js.map +1 -1
  39. package/dist/integrations/slack/channel-session-link-processor.d.ts +1 -0
  40. package/dist/integrations/slack/channel-session-link-processor.d.ts.map +1 -1
  41. package/dist/integrations/slack/channel-session-link-processor.js +1 -1
  42. package/dist/integrations/slack/channel-session-link-processor.js.map +1 -1
  43. package/dist/integrations/slack/reply-tool.d.ts.map +1 -1
  44. package/dist/integrations/slack/reply-tool.js +3 -11
  45. package/dist/integrations/slack/reply-tool.js.map +1 -1
  46. package/dist/integrations/slack/run-error-card.d.ts +3 -0
  47. package/dist/integrations/slack/run-error-card.d.ts.map +1 -0
  48. package/dist/integrations/slack/run-error-card.js +44 -0
  49. package/dist/integrations/slack/run-error-card.js.map +1 -0
  50. package/dist/integrations/slack/slack.d.ts.map +1 -1
  51. package/dist/integrations/slack/slack.js +5 -1
  52. package/dist/integrations/slack/slack.js.map +1 -1
  53. package/dist/links.d.ts +24 -0
  54. package/dist/links.d.ts.map +1 -0
  55. package/dist/links.js +40 -0
  56. package/dist/links.js.map +1 -0
  57. package/dist/routes/config.d.ts +3 -0
  58. package/dist/routes/config.d.ts.map +1 -1
  59. package/dist/routes/config.js +22 -1
  60. package/dist/routes/config.js.map +1 -1
  61. package/dist/routes/intake.js +5 -2
  62. package/dist/routes/intake.js.map +1 -1
  63. package/dist/routes/surface.js +1 -1
  64. package/dist/routes/surface.js.map +1 -1
  65. package/dist/rules/dispatcher.d.ts.map +1 -1
  66. package/dist/rules/dispatcher.js +8 -1
  67. package/dist/rules/dispatcher.js.map +1 -1
  68. package/dist/run-error.d.ts +13 -0
  69. package/dist/run-error.d.ts.map +1 -0
  70. package/dist/run-error.js +81 -0
  71. package/dist/run-error.js.map +1 -0
  72. package/dist/session/thinking-default.d.ts +1 -1
  73. package/dist/session/thinking-default.d.ts.map +1 -1
  74. package/dist/session/thinking-default.js +10 -11
  75. package/dist/session/thinking-default.js.map +1 -1
  76. package/dist/storage/domains/intake/base.d.ts +5 -0
  77. package/dist/storage/domains/intake/base.d.ts.map +1 -1
  78. package/dist/storage/domains/intake/base.js +9 -0
  79. package/dist/storage/domains/intake/base.js.map +1 -1
  80. package/dist/storage/domains/projects/base.d.ts +0 -1
  81. package/dist/storage/domains/projects/base.d.ts.map +1 -1
  82. package/dist/storage/domains/projects/base.js +4 -4
  83. package/dist/storage/domains/projects/base.js.map +1 -1
  84. package/dist/tools/read-tools.d.ts.map +1 -1
  85. package/dist/tools/read-tools.js +18 -2
  86. package/dist/tools/read-tools.js.map +1 -1
  87. package/dist/tools/run-watch.d.ts +0 -2
  88. package/dist/tools/run-watch.d.ts.map +1 -1
  89. package/dist/tools/run-watch.js +3 -42
  90. package/dist/tools/run-watch.js.map +1 -1
  91. package/dist/tools/scope.js +1 -1
  92. package/dist/tools/scope.js.map +1 -1
  93. package/dist/tools/session-tools.d.ts.map +1 -1
  94. package/dist/tools/session-tools.js +21 -5
  95. package/dist/tools/session-tools.js.map +1 -1
  96. package/dist/tools/work-item-tools.d.ts.map +1 -1
  97. package/dist/tools/work-item-tools.js +7 -1
  98. package/dist/tools/work-item-tools.js.map +1 -1
  99. package/factory-skills/factory-gitlab-review/SKILL.md +1 -1
  100. package/factory-skills/factory-plan/SKILL.md +1 -1
  101. package/factory-skills/factory-rereview/SKILL.md +2 -1
  102. package/factory-skills/factory-review/SKILL.md +2 -1
  103. package/factory-skills/factory-self-review/SKILL.md +1 -1
  104. package/factory-skills/factory-triage/SKILL.md +46 -23
  105. package/package.json +12 -12
@@ -95,6 +95,10 @@ export declare abstract class GitLabIntegrationBase implements FactoryIntegratio
95
95
  protected get webhookSecret(): string | undefined;
96
96
  workers(ctx: IntegrationContext): MastraWorker[];
97
97
  routes(ctx: IntegrationContext): ApiRoute[];
98
+ ingestLinkedRepositoryBacklog(args: {
99
+ orgId: string;
100
+ projectRepositoryId: string;
101
+ }): Promise<void>;
98
102
  agentTools(args: {
99
103
  requestContext: RequestContext;
100
104
  }): Promise<IntegrationTools>;
@@ -1 +1 @@
1
- {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../src/integrations/gitlab/integration.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../src/integrations/gitlab/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,KAAK,EAIV,MAAM,EAEN,iBAAiB,EAQlB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAC3F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AACrF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8CAA8C,CAAC;AAC/F,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG3F,OAAO,EAIL,eAAe,EAEhB,MAAM,UAAU,CAAC;AAGlB,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAUhF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAGpE,UAAU,uBAAuB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,eAAe,CAAC;IACrB,UAAU,EAAE,qBAAqB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED,UAAU,qBAAqB;IAC7B,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAQD,UAAU,oBAAqB,SAAQ,qBAAqB;IAC1D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,CAAC,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAOD,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,QAAQ,GAAG,cAAc,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAOD,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAK9C,8BAAsB,qBAAsB,YAAW,kBAAkB;;IACvE,QAAQ,CAAC,EAAE,YAAY;IAOvB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;gBAErB,KAAK,CAAC,EAAE,mBAAmB;IAIvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAQrB;IACF,QAAQ,CAAC,cAAc,iEAGpB;IACH,UAAU,CAAC,EACT,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,aAAa,GACd,EAAE;QACD,OAAO,CAAC,EAAE,wBAAwB,CAAC;QACnC,QAAQ,EAAE,sBAAsB,CAAC;QACjC,IAAI,EAAE,SAAS,CAAC;QAChB,aAAa,CAAC,EAAE,0BAA0B,CAAC;KAC5C,GAAG,IAAI;IAOR,qEAAqE;IACrE,IAAI,kBAAkB,IAAI,yBAAyB,CAKlD;IAED,wFAAwF;IACxF,IAAI,oBAAoB,IAAI,0BAA0B,GAAG,SAAS,CAEjE;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,QAAQ,IAAI,sBAAsB,CAKrC;IAEK,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAkB9D,WAAW,IAAI,IAAI;IAInB,QAAQ,CAAC,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IACjD,QAAQ,CAAC,kBAAkB,IAAI,MAAM;IACrC,SAAS,CAAC,QAAQ,CAAC,cAAc,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IACvE,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAEtF,oFAAoF;IAC9E,mBAAmB,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE;;;;IA2BnG,2BAA2B,CAC/B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAUxB,yBAAyB,CAC7B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GAAG,eAAe,EAC/B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAMxB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrF,yBAAyB,CAAC,KAAK,EAAE;QACrC,KAAK,EAAE,MAAM,CAAC;QACd,gBAAgB,EAAE,MAAM,CAAC;QACzB,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IA2DrC,4EAA4E;IACtE,iBAAiB,IAAI,OAAO,CAAC,sBAAsB,EAAE,GAAG,SAAS,CAAC;IAIxE,4FAA4F;IACtF,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAInC,SAAS,KAAK,aAAa,IAAI,MAAM,GAAG,SAAS,CAEhD;IAED,OAAO,CAAC,GAAG,EAAE,kBAAkB,GAAG,YAAY,EAAE;IAahD,MAAM,CAAC,GAAG,EAAE,kBAAkB,GAAG,QAAQ,EAAE;IAerC,6BAA6B,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlG,UAAU,CAAC,IAAI,EAAE;QAAE,cAAc,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIrF,YAAY,CAAC,EAAE,cAAc,EAAE,EAAE;QAAE,cAAc,EAAE,cAAc,CAAA;KAAE,GAAG,gBAAgB;IAIhF,gBAAgB,CAAC,EACrB,WAAW,EACX,cAAc,GACf,EAAE,UAAU,CAAC,WAAW,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrF,QAAQ,CAAC,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE/C,+FAA+F;IACzF,8BAA8B,CAAC,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAkThG;AAED,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2GAA2G;IAC3G,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAID,qBAAa,iBAAkB,SAAQ,qBAAqB;;gBAO9C,MAAM,GAAE,uBAA4B;IA4BhD,cAAuB,aAAa,IAAI,MAAM,GAAG,SAAS,CAEzD;IAEK,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5C,kBAAkB,IAAI,MAAM;cAIZ,cAAc,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;cAIpD,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAOnF,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CASvC;AAQD,wBAAgB,cAAc,CAAC,SAAS,EAAE,qBAAqB,GAAG,MAAM,CAYvE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAE1E;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,GAAG,MAAM,CAa5E;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAE/E;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,2BAA2B,GAAG,IAAI,CAE7F;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,qBAAqB,CAE5E;AAqBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD"}
@@ -5,7 +5,7 @@ import { resolveGitLabRules } from "./default-rules.js";
5
5
  import { attachGitLabRules } from "./rules.js";
6
6
  import { attachGitLabReconciler } from "./reconciler.js";
7
7
  import { gitlabReconciliationEnabled, gitlabReconciliationInterval } from "./reconciliation-config.js";
8
- import { buildGitLabRoutes } from "./routes.js";
8
+ import { buildGitLabRoutes, ingestLinkedGitLabRepositoryBacklog } from "./routes.js";
9
9
  import { createGitLabSubscriptionTools, parseCreatedMergeRequest, subscribeCurrentSessionToMergeRequest } from "./session-subscriptions.js";
10
10
  import { buildGitLabVersionControl } from "./version-control.js";
11
11
  // src/integrations/gitlab/integration.ts
@@ -23,6 +23,7 @@ var GitLabIntegrationBase = class {
23
23
  #sourceControl;
24
24
  #integrationStorage;
25
25
  #auth;
26
+ #ingestFactoryEvent;
26
27
  #orgIdByResourceId = /* @__PURE__ */ new Map();
27
28
  rules;
28
29
  constructor(rules) {
@@ -195,6 +196,7 @@ var GitLabIntegrationBase = class {
195
196
  }
196
197
  routes(ctx) {
197
198
  const ingestFactoryEvent = attachGitLabRules(this, ctx);
199
+ this.#ingestFactoryEvent = ingestFactoryEvent;
198
200
  return buildGitLabRoutes({
199
201
  gitlab: this,
200
202
  auth: ctx.auth,
@@ -206,6 +208,13 @@ var GitLabIntegrationBase = class {
206
208
  ...ctx.controller ? { controller: ctx.controller } : {}
207
209
  });
208
210
  }
211
+ async ingestLinkedRepositoryBacklog(args) {
212
+ await ingestLinkedGitLabRepositoryBacklog({
213
+ gitlab: this,
214
+ ...args,
215
+ ingestFactoryEvent: this.#ingestFactoryEvent
216
+ });
217
+ }
209
218
  async agentTools(args) {
210
219
  return buildGitLabAgentTools({
211
220
  requestContext: args.requestContext,
@@ -1 +1 @@
1
- {"version":3,"file":"integration.js","names":[],"sources":["../../../src/integrations/gitlab/integration.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport type { ApiRoute } from '@mastra/core/server';\nimport type { MastraWorker } from '@mastra/core/worker';\n\nimport type { IntegrationConnection } from '../../capabilities/connection.js';\nimport type {\n CreateIntakeCommentInput,\n CreatedIntakeComment,\n GetIntakeIssueInput,\n Intake,\n IntakeIssue,\n IntakeIssueDetail,\n IntakeItemPage,\n IntakeSource,\n ListIntakeIssuesInput,\n ListIntakeItemsInput,\n ResolveIntakeDispatchInput,\n ResolvedIntakeDispatch,\n UpdateIntakeIssueInput,\n} from '../../capabilities/intake.js';\nimport type { RouteAuth } from '../../routes/route.js';\nimport type { IntegrationStorageHandle } from '../../storage/domains/integrations/base.js';\nimport type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';\nimport type { SourceControlStorageHandle } from '../../storage/domains/source-control/base.js';\nimport type { FactoryIntegration, IntegrationContext, IntegrationTools } from '../base.js';\nimport { IssueReconcileWorker } from '../issue-reconcile-worker.js';\nimport { buildGitLabAgentTools } from './agent-tools.js';\nimport {\n GITLAB_ISSUES_PAGE_SIZE,\n GITLAB_NOTES_PAGE_SIZE,\n GITLAB_PROJECTS_PAGE_SIZE,\n GitLabApiClient,\n GitLabApiError,\n} from './api.js';\nimport type { GitLabIssue, GitLabNote, GitLabProject } from './api.js';\nimport { resolveGitLabRules } from './default-rules.js';\nimport type { GitLabEventRules, GitLabRuleOverrides } from './default-rules.js';\nimport { attachGitLabReconciler } from './reconciler.js';\nimport { gitlabReconciliationEnabled, gitlabReconciliationInterval } from './reconciliation-config.js';\nimport { buildGitLabRoutes } from './routes.js';\nimport { attachGitLabRules } from './rules.js';\nimport {\n createGitLabSubscriptionTools,\n parseCreatedMergeRequest,\n subscribeCurrentSessionToMergeRequest,\n} from './session-subscriptions.js';\nimport type { GitLabSubscriptionStorage } from './subscriptions.js';\nimport { buildGitLabVersionControl } from './version-control.js';\n\ninterface GitLabConnectionContext {\n id: string;\n label: string | null;\n api: GitLabApiClient;\n connection: IntegrationConnection;\n host: string;\n webBaseUrl?: string;\n /** Resolves a fresh provider token for a single brokered git operation. */\n repositoryAccessToken?: () => Promise<string>;\n}\n\ninterface GitLabSourceReference {\n /** Present only on legacy v1 ids; authentication is not resource identity. */\n connectionId?: string;\n /** Canonical v2 ids use the GitLab instance host plus immutable project id. */\n host?: string;\n projectId: string;\n /** Legacy ids carry display metadata; v2 resolves it from GitLab. */\n projectPath?: string;\n}\n\ninterface ResolvedGitLabSourceReference extends GitLabSourceReference {\n connectionId: string;\n host: string;\n projectPath: string;\n}\n\ninterface GitLabIssueReference extends GitLabSourceReference {\n issueIid: number;\n}\n\nexport interface GitLabMergeRequestReference {\n version: 1;\n host: string;\n projectId: number;\n mergeRequestIid: number;\n}\n\ninterface GitLabPageCursor {\n source: number;\n page: number;\n}\n\nexport interface GitLabStatusConnection {\n id: string;\n integrationId: string;\n status: 'active' | 'needs_reauth';\n accountLabel: string | null;\n}\n\nconst DIRECT_CONNECTION_ID = 'direct';\nconst GITLAB_CONNECTION_TOKEN_PREFIX = 'gitlab-connection:';\nconst GITLAB_SOURCE_PREFIX = 'gitlab-project:';\nconst GITLAB_ISSUE_PREFIX = 'gitlab-issue:';\nconst GITLAB_MERGE_REQUEST_PREFIX = 'gitlab-pr:';\nexport const GITLAB_TRUSTED_ACCESS_LEVEL = 30;\n// Bound issue detail reads to 2,000 notes. GitLab does not expose truncation through the Intake contract.\nconst MAX_NOTES_PAGES = 20;\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport abstract class GitLabIntegrationBase implements FactoryIntegration {\n readonly id = 'gitlab';\n #projects: FactoryProjectsStorage | undefined;\n #sourceControl: SourceControlStorageHandle | undefined;\n #integrationStorage: GitLabSubscriptionStorage | undefined;\n #auth: RouteAuth | undefined;\n readonly #orgIdByResourceId = new Map<string, string | null>();\n readonly rules: GitLabEventRules;\n\n constructor(rules?: GitLabRuleOverrides) {\n this.rules = resolveGitLabRules(rules);\n }\n\n readonly intake: Intake = {\n resolveIntakeDispatch: input => this.#resolveIntakeDispatch(input),\n listSources: () => this.#listSources(),\n listItems: input => this.#listItems(input),\n listIssues: input => this.#listIssues(input),\n getIssue: input => this.#getIssue(input),\n createComment: input => this.#createComment(input),\n updateIssue: input => this.#updateIssue(input),\n };\n readonly versionControl = buildGitLabVersionControl({\n contextForConnection: connection => this.#versionControlContext(connection),\n contextForStoredInstallation: (connection, host) => this.#versionControlContextForInstallation(connection, host),\n });\n initialize({\n storage,\n projects,\n auth,\n sourceControl,\n }: {\n storage?: IntegrationStorageHandle;\n projects: FactoryProjectsStorage;\n auth: RouteAuth;\n sourceControl?: SourceControlStorageHandle;\n }): void {\n this.#projects = projects;\n this.#auth = auth;\n this.#sourceControl = sourceControl;\n this.#integrationStorage = storage as GitLabSubscriptionStorage | undefined;\n }\n\n /** Generic integration persistence (merge-request subscriptions). */\n get integrationStorage(): GitLabSubscriptionStorage {\n if (!this.#integrationStorage) {\n throw new Error(`${this.constructor.name} is not initialized — the factory binds storage during prepare().`);\n }\n return this.#integrationStorage;\n }\n\n /** Source-control rows for this integration; absent when the host runs without them. */\n get sourceControlStorage(): SourceControlStorageHandle | undefined {\n return this.#sourceControl;\n }\n\n get authEnabled(): boolean {\n return this.#auth?.enabled() ?? false;\n }\n\n get projects(): FactoryProjectsStorage {\n if (!this.#projects) {\n throw new Error(`${this.constructor.name} is not initialized — the factory binds storage during prepare().`);\n }\n return this.#projects;\n }\n\n async resolveOrgId(resourceId: string): Promise<string | null> {\n const cached = this.#orgIdByResourceId.get(resourceId);\n if (cached !== undefined) return cached;\n if (!UUID_PATTERN.test(resourceId)) {\n this.#orgIdByResourceId.set(resourceId, null);\n return null;\n }\n try {\n await this.projects.ensureReady();\n const project = await this.projects.getById({ id: resourceId });\n const orgId = project?.orgId ?? null;\n this.#orgIdByResourceId.set(resourceId, orgId);\n return orgId;\n } catch {\n return null;\n }\n }\n\n clearCaches(): void {\n this.#orgIdByResourceId.clear();\n }\n\n abstract hasActiveConnections(): Promise<boolean>;\n abstract authFailureMessage(): string;\n protected abstract activeContexts(): Promise<GitLabConnectionContext[]>;\n protected abstract contextById(connectionId: string): Promise<GitLabConnectionContext>;\n\n /** Resolve only a GitLab repository linked to this Factory in this organization. */\n async getLinkedRepository(input: { orgId: string; factoryProjectId: string; projectRepositoryId: string }) {\n if (!this.#sourceControl) return null;\n const connections = await this.#sourceControl.connections.list({\n orgId: input.orgId,\n factoryProjectId: input.factoryProjectId,\n });\n for (const connection of connections) {\n if (connection.integrationId !== 'gitlab') continue;\n const links = await this.#sourceControl.projectRepositories.list({\n orgId: input.orgId,\n connectionId: connection.id,\n });\n const link = links.find(candidate => candidate.id === input.projectRepositoryId);\n if (!link) continue;\n const repository = await this.#sourceControl.repositories.get({ orgId: input.orgId, id: link.repositoryId });\n const installation = await this.#sourceControl.installations.get({\n orgId: input.orgId,\n id: connection.installationId,\n });\n if (!repository || !installation) return null;\n const host = installation.providerMetadata.host;\n if (typeof host !== 'string' || !host) return null;\n return { repository, host: normalizeGitLabHost(host) };\n }\n return null;\n }\n\n async getProjectMemberAccessLevel(\n connectionId: string,\n projectId: string,\n username: string,\n ): Promise<number | undefined> {\n const normalized = username.trim().toLowerCase();\n if (!normalized) return undefined;\n const members = await (await this.contextById(connectionId)).api.listProjectMembers(projectId, { query: username });\n const member = members.find(\n candidate => candidate.username.toLowerCase() === normalized && candidate.state !== 'blocked',\n );\n return member?.access_level;\n }\n\n async getWorkItemAuthorUsername(\n connectionId: string,\n projectId: string,\n kind: 'issue' | 'merge_request',\n iid: number,\n ): Promise<string | undefined> {\n const api = (await this.contextById(connectionId)).api;\n const item = kind === 'issue' ? await api.getIssue(projectId, iid) : await api.getMergeRequest(projectId, iid);\n return item.author?.username;\n }\n\n async isProjectMemberTrustedForSource(sourceId: string, username: string): Promise<boolean> {\n const reference = decodeSourceId(sourceId);\n if (!reference) throw new GitLabApiError('GitLab source identity is invalid.', 400);\n const { context, source } = await this.#resolveSourceReference(reference);\n const accessLevel = await this.getProjectMemberAccessLevel(context.id, source.projectId, username);\n return (accessLevel ?? 0) >= GITLAB_TRUSTED_ACCESS_LEVEL;\n }\n\n async getIssueForFactoryProject(input: {\n orgId: string;\n factoryProjectId: string;\n issueId: string;\n }): Promise<IntakeIssueDetail | null> {\n if (!this.#sourceControl) throw new GitLabApiError('GitLab source control is unavailable.', 503);\n const reference = decodeIssueReference(input.issueId);\n const locator = parseIssueLocator(input.issueId);\n if (!reference && !locator) {\n throw new GitLabApiError('GitLab issue must include a project and issue IID.', 400);\n }\n\n const normalizePath = (value: string) => value.replace(/^\\/+|\\/+$/g, '').toLowerCase();\n const matches: Array<{\n connectionId: string;\n projectId: string;\n projectPath: string;\n }> = [];\n const connections = await this.#sourceControl.connections.list({\n orgId: input.orgId,\n factoryProjectId: input.factoryProjectId,\n });\n for (const connection of connections) {\n const installation = await this.#sourceControl.installations.get({\n orgId: input.orgId,\n id: connection.installationId,\n });\n if (!installation) continue;\n for (const projectRepository of await this.#sourceControl.projectRepositories.list({\n orgId: input.orgId,\n connectionId: connection.id,\n })) {\n const repository = await this.#sourceControl.repositories.get({\n orgId: input.orgId,\n id: projectRepository.repositoryId,\n });\n if (!repository) continue;\n if (reference?.projectId && repository.externalId !== reference.projectId) continue;\n if (reference?.projectPath && normalizePath(repository.slug) !== normalizePath(reference.projectPath)) continue;\n if (locator?.projectPath && normalizePath(repository.slug) !== normalizePath(locator.projectPath)) continue;\n if (reference?.connectionId && installation.externalId !== reference.connectionId) continue;\n const installationHost =\n typeof installation.providerMetadata.host === 'string'\n ? normalizeGitLabHost(installation.providerMetadata.host)\n : null;\n if (reference?.host && installationHost !== normalizeGitLabHost(reference.host)) continue;\n if (locator?.host && installationHost !== normalizeGitLabHost(locator.host)) continue;\n matches.push({\n connectionId: installation.externalId,\n projectId: repository.externalId,\n projectPath: repository.slug,\n });\n }\n }\n const match = matches.sort((left, right) => left.connectionId.localeCompare(right.connectionId))[0];\n if (!match) throw new GitLabApiError('GitLab issue is outside the active Factory project.', 404);\n return this.intake.getIssue({\n connection: gitlabConnection(match.connectionId),\n sourceId: encodeSourceId(match),\n issueId: input.issueId,\n });\n }\n\n /** Platform mode exposes org connections; direct mode returns undefined. */\n async statusConnections(): Promise<GitLabStatusConnection[] | undefined> {\n return undefined;\n }\n\n /** Direct mode verifies its configured credential; Platform mode uses connection status. */\n async verifyStatus(): Promise<void> {\n // Platform connection state is authoritative unless a provider overrides this probe.\n }\n\n protected get webhookSecret(): string | undefined {\n return undefined;\n }\n\n workers(ctx: IntegrationContext): MastraWorker[] {\n if (!gitlabReconciliationEnabled()) return [];\n const reconcile = attachGitLabReconciler(this, ctx);\n if (!reconcile) return [];\n const intervalMs = gitlabReconciliationInterval();\n return [\n new IssueReconcileWorker({\n integrationId: this.id,\n reconcile,\n ...(intervalMs ? { intervalMs } : {}),\n }),\n ];\n }\n routes(ctx: IntegrationContext): ApiRoute[] {\n const ingestFactoryEvent = attachGitLabRules(this, ctx);\n return buildGitLabRoutes({\n gitlab: this,\n auth: ctx.auth,\n intake: ctx.storage?.intake,\n emitAudit: ctx.hooks?.emitAudit,\n sandbox: ctx.sandbox,\n webhookSecret: this.webhookSecret,\n ingestFactoryEvent,\n ...(ctx.controller ? { controller: ctx.controller } : {}),\n });\n }\n\n async agentTools(args: { requestContext: RequestContext }): Promise<IntegrationTools> {\n return buildGitLabAgentTools({ requestContext: args.requestContext, gitlab: this });\n }\n\n sessionTools({ requestContext }: { requestContext: RequestContext }): IntegrationTools {\n return createGitLabSubscriptionTools(requestContext, this);\n }\n\n async postToolObserver({\n toolContext,\n requestContext,\n }: Parameters<NonNullable<FactoryIntegration['postToolObserver']>>[0]): Promise<void> {\n const mergeRequestUrl = parseCreatedMergeRequest(toolContext);\n if (!mergeRequestUrl || !requestContext) return;\n await subscribeCurrentSessionToMergeRequest(requestContext, mergeRequestUrl, 'auto-create-change-request', this);\n }\n\n abstract diagnostics(): Record<string, unknown>;\n\n /** Prefer the configured direct token over an older Platform installation on the same host. */\n async resolveActiveConnectionForHost(storedConnectionId: string, host: string): Promise<string> {\n if (this.diagnostics().mode !== 'direct') return storedConnectionId;\n const [direct] = await this.activeContexts();\n return direct && normalizeGitLabHost(direct.host) === normalizeGitLabHost(host) ? direct.id : storedConnectionId;\n }\n\n async #versionControlContext(connection: IntegrationConnection): Promise<GitLabConnectionContext> {\n const connectionId = connectionIdFromConnection(connection);\n if (connectionId) return this.contextById(connectionId);\n const contexts = await this.activeContexts();\n if (contexts.length !== 1) {\n throw new GitLabApiError(\n 'GitLab version-control requests must identify a connection when multiple GitLab accounts are connected.',\n 400,\n );\n }\n return contexts[0]!;\n }\n async #versionControlContextForInstallation(\n connection: IntegrationConnection,\n host: string | undefined,\n ): Promise<GitLabConnectionContext> {\n // A direct PAT intentionally overrides Platform credentials. Old links can\n // retain their Platform connection id; use the PAT only for the same host.\n if (this.diagnostics().mode === 'direct' && host) {\n const [direct] = await this.activeContexts();\n if (direct && normalizeGitLabHost(host) === normalizeGitLabHost(direct.host)) return direct;\n }\n return this.#versionControlContext(connection);\n }\n async #contextForReference(reference: GitLabSourceReference): Promise<GitLabConnectionContext> {\n if (reference.connectionId) return this.contextById(reference.connectionId);\n const contexts = (await this.activeContexts()).filter(\n context => !reference.host || normalizeGitLabHost(context.host) === normalizeGitLabHost(reference.host),\n );\n if (contexts.length === 0) {\n throw new GitLabApiError('No active GitLab connection can access this source.', 401);\n }\n if (contexts.length === 1) return contexts[0]!;\n\n if (this.#sourceControl) {\n const linkedConnectionIds = new Set(\n (await this.#sourceControl.projectRepositories.listConfiguredExternalKeys())\n .filter(key => key.repositoryExternalId === reference.projectId)\n .map(key => key.installationExternalId),\n );\n const linked = contexts.filter(context => linkedConnectionIds.has(context.id));\n if (linked.length > 0) return linked.sort((left, right) => left.id.localeCompare(right.id))[0]!;\n }\n\n for (const context of contexts.sort((left, right) => left.id.localeCompare(right.id))) {\n try {\n await context.api.getProject(reference.projectId);\n return context;\n } catch (error) {\n if (!(error instanceof GitLabApiError) || ![401, 403, 404].includes(error.status ?? 0)) throw error;\n // This credential cannot access the project; try another active account for the same canonical source.\n }\n }\n throw new GitLabApiError('No active GitLab connection can access this source.', 404);\n }\n\n async #resolveSourceReference(\n reference: GitLabSourceReference,\n ): Promise<{ context: GitLabConnectionContext; source: ResolvedGitLabSourceReference }> {\n const context = await this.#contextForReference(reference);\n const projectPath =\n reference.projectPath ?? (await context.api.getProject(reference.projectId)).path_with_namespace;\n return {\n context,\n source: {\n connectionId: context.id,\n host: normalizeGitLabHost(reference.host ?? context.host),\n projectId: reference.projectId,\n projectPath,\n },\n };\n }\n\n async #resolveIntakeDispatch({ externalSource }: ResolveIntakeDispatchInput): Promise<ResolvedIntakeDispatch | null> {\n if (externalSource.type !== 'issue') return null;\n const reference = decodeIssueReference(externalSource.externalId);\n if (!reference) return null;\n const { context, source } = await this.#resolveSourceReference(reference);\n return {\n connection: context.connection,\n sourceId: encodeSourceId(source),\n issueId: String(reference.issueIid),\n };\n }\n\n async #listSources(): Promise<IntakeSource[]> {\n const sources = new Map<string, IntakeSource>();\n for (const context of await this.activeContexts()) {\n for (let page = 1; ; page++) {\n const projects = await context.api.listProjects({ page });\n for (const project of projects) {\n const source = this.#toIntakeSource(context, project);\n if (!sources.has(source.id)) sources.set(source.id, source);\n }\n if (projects.length < GITLAB_PROJECTS_PAGE_SIZE) break;\n }\n }\n return [...sources.values()];\n }\n\n async #listItems(input: ListIntakeItemsInput): Promise<IntakeItemPage> {\n const result = await this.#listIssuePage(input.sourceIds, input.cursor);\n return {\n items: result.issues.map(({ issue, source, context }) => ({\n source: {\n type: 'issue',\n externalId: encodeIssueReference({ ...source, issueIid: issue.iid }),\n url: issue.web_url,\n },\n sourceId: encodeSourceId(source),\n title: `${source.projectPath}#${issue.iid}: ${issue.title}`,\n status: issue.state,\n labels: issue.labels ?? [],\n assignee: displayName(issue.assignee),\n createdAt: issue.created_at,\n updatedAt: issue.updated_at,\n metadata: {\n identifier: `${source.projectPath}#${issue.iid}`,\n projectId: source.projectId,\n projectPath: source.projectPath,\n connectionId: context.id,\n accountLabel: context.label,\n labelColors: Object.fromEntries((issue.labelDetails ?? []).map(label => [label.name, label.color])),\n },\n })),\n nextCursor: result.nextCursor,\n };\n }\n\n async #listIssues(input: ListIntakeIssuesInput) {\n const result = await this.#listIssuePage(input.sourceIds, input.cursor, input.labels);\n return {\n issues: result.issues.map(({ issue, source }) => ({\n ...this.#toIntakeIssue(issue, source.projectPath),\n sourceId: encodeSourceId(source),\n })),\n nextCursor: result.nextCursor,\n };\n }\n\n async #listIssuePage(sourceIds: string[], cursor?: string, labels?: string[]) {\n const sources = sourceIds.map(decodeSourceId).filter((source): source is GitLabSourceReference => source !== null);\n if (sources.length === 0) return { issues: [], nextCursor: null };\n const current = decodePageCursor(cursor);\n if (!current || current.source >= sources.length) return { issues: [], nextCursor: null };\n\n for (let sourceIndex = current.source; sourceIndex < sources.length; sourceIndex++) {\n const { source, context } = await this.#resolveSourceReference(sources[sourceIndex]!);\n const page = sourceIndex === current.source ? current.page : 1;\n const issues = await context.api.listIssues(source.projectId, { page, labels });\n const nextCursor =\n issues.length === GITLAB_ISSUES_PAGE_SIZE\n ? encodePageCursor({ source: sourceIndex, page: page + 1 })\n : sourceIndex + 1 < sources.length\n ? encodePageCursor({ source: sourceIndex + 1, page: 1 })\n : null;\n return { issues: issues.map(issue => ({ issue, source, context })), nextCursor };\n }\n return { issues: [], nextCursor: null };\n }\n\n async #getIssue(input: GetIntakeIssueInput): Promise<IntakeIssueDetail | null> {\n const resolved = await this.#resolveRequest(input);\n let issue: GitLabIssue;\n try {\n issue = await resolved.context.api.getIssue(resolved.projectId, resolved.issueIid);\n } catch (error) {\n if (error instanceof GitLabApiError && error.status === 404) return null;\n throw error;\n }\n const notes = await this.#listAllNotes(resolved.context.api, resolved.projectId, resolved.issueIid);\n return {\n ...this.#toIntakeIssue(issue, resolved.projectPath),\n description: issue.description?.trim() || null,\n comments: notes\n .filter(note => !note.system)\n .map(note => ({ author: displayName(note.author), body: note.body, createdAt: note.created_at })),\n };\n }\n\n async #listAllNotes(api: GitLabApiClient, projectId: string, issueIid: number): Promise<GitLabNote[]> {\n const notes: GitLabNote[] = [];\n for (let page = 1; page <= MAX_NOTES_PAGES; page++) {\n const result = await api.listNotes(projectId, issueIid, { page });\n notes.push(...result);\n if (result.length < GITLAB_NOTES_PAGE_SIZE) break;\n }\n return notes;\n }\n\n async #createComment(input: CreateIntakeCommentInput): Promise<CreatedIntakeComment | null> {\n const resolved = await this.#resolveRequest(input);\n try {\n const issue = await resolved.context.api.getIssue(resolved.projectId, resolved.issueIid);\n const note = await resolved.context.api.createNote(resolved.projectId, resolved.issueIid, input.body);\n return { id: String(note.id), url: `${issue.web_url}#note_${note.id}` };\n } catch (error) {\n if (error instanceof GitLabApiError && error.status === 404) return null;\n throw error;\n }\n }\n\n async #updateIssue(input: UpdateIntakeIssueInput): Promise<IntakeIssue | null> {\n const resolved = await this.#resolveRequest(input);\n let issue: GitLabIssue;\n try {\n issue = await resolved.context.api.getIssue(resolved.projectId, resolved.issueIid);\n } catch (error) {\n if (error instanceof GitLabApiError && error.status === 404) return null;\n throw error;\n }\n const stateEvent = targetStateEvent(input);\n if (!stateEvent) return null;\n if ((stateEvent === 'close' && issue.state === 'closed') || (stateEvent === 'reopen' && issue.state === 'opened')) {\n return this.#toIntakeIssue(issue, resolved.projectPath);\n }\n const updated = await resolved.context.api.updateIssueState(resolved.projectId, resolved.issueIid, stateEvent);\n return this.#toIntakeIssue(updated, resolved.projectPath);\n }\n\n async #resolveRequest(input: GetIntakeIssueInput): Promise<{\n context: GitLabConnectionContext;\n projectId: string;\n projectPath: string;\n issueIid: number;\n }> {\n const issueReference = decodeIssueReference(input.issueId);\n const source = input.sourceId ? decodeSourceId(input.sourceId) : null;\n const locator = parseIssueLocator(input.issueId);\n const reference = issueReference ?? source;\n let context: GitLabConnectionContext;\n if (reference) {\n context = await this.#contextForReference(reference);\n } else {\n const connectionId = connectionIdFromConnection(input.connection);\n const contexts = connectionId ? [await this.contextById(connectionId)] : await this.activeContexts();\n if (contexts.length !== 1) {\n throw new GitLabApiError('GitLab issue reference must resolve to exactly one active connection.', 400);\n }\n context = contexts[0]!;\n }\n const projectId = issueReference?.projectId ?? source?.projectId ?? locator?.projectPath;\n const issueIid = issueReference?.issueIid ?? locator?.issueIid ?? parsePositiveInteger(input.issueId);\n if (!projectId || !issueIid) {\n throw new GitLabApiError(\n 'GitLab issue must include a project and issue IID (for example, group/project#42).',\n 400,\n );\n }\n const projectPath =\n issueReference?.projectPath ??\n source?.projectPath ??\n locator?.projectPath ??\n (await context.api.getProject(projectId)).path_with_namespace;\n return { context, projectId, projectPath, issueIid };\n }\n\n #toIntakeSource(context: GitLabConnectionContext, project: GitLabProject): IntakeSource {\n const reference: GitLabSourceReference = {\n host: normalizeGitLabHost(context.host),\n projectId: String(project.id),\n projectPath: project.path_with_namespace,\n };\n return {\n id: encodeSourceId(reference),\n name: project.path_with_namespace,\n type: 'project',\n metadata: {\n projectId: String(project.id),\n projectPath: project.path_with_namespace,\n defaultBranch: project.default_branch ?? null,\n connectionId: context.id,\n accountLabel: context.label,\n url: project.web_url,\n },\n };\n }\n\n #toIntakeIssue(issue: GitLabIssue, projectPath: string): IntakeIssue {\n const assignees = issue.assignees?.map(displayName).filter((name): name is string => name !== null) ?? [];\n return {\n id: String(issue.iid),\n identifier: `${projectPath}#${issue.iid}`,\n title: issue.title,\n url: issue.web_url,\n author: displayName(issue.author),\n authorUsername: issue.author?.username ?? null,\n state: issue.state,\n stateType: issue.state === 'closed' ? 'completed' : 'unstarted',\n priority: typeof issue.weight === 'number' ? String(issue.weight) : null,\n assignee: displayName(issue.assignee) ?? assignees[0] ?? null,\n assignees,\n source: projectPath,\n labels: issue.labels ?? [],\n labelColors: Object.fromEntries((issue.labelDetails ?? []).map(label => [label.name, label.color])),\n commentCount: issue.user_notes_count ?? null,\n createdAt: issue.created_at,\n updatedAt: issue.updated_at,\n };\n }\n}\n\nexport type GitLabAccessTokenType = 'personal' | 'group';\n\nexport interface GitLabIntegrationConfig {\n rules?: GitLabRuleOverrides;\n accessToken?: string;\n /** Defaults to `personal`; both token types authenticate identically but have different resource reach. */\n accessTokenType?: GitLabAccessTokenType;\n baseUrl?: string;\n webhookSecret?: string;\n fetchImpl?: typeof fetch;\n}\n\nconst DIRECT_CONNECTION_TOKEN = 'gitlab-direct-access-token';\n\nexport class GitLabIntegration extends GitLabIntegrationBase {\n readonly #accessToken: string;\n readonly #accessTokenType: GitLabAccessTokenType;\n readonly #baseUrl: string;\n readonly #webhookSecret: string | undefined;\n readonly #context: GitLabConnectionContext;\n\n constructor(config: GitLabIntegrationConfig = {}) {\n super(config.rules);\n const accessToken = config.accessToken?.trim() || process.env.GITLAB_ACCESS_TOKEN?.trim();\n if (!accessToken) {\n throw new Error('GitLabIntegration: missing required GITLAB_ACCESS_TOKEN.');\n }\n this.#accessToken = accessToken;\n this.#accessTokenType = parseAccessTokenType(\n config.accessTokenType ?? process.env.GITLAB_ACCESS_TOKEN_TYPE?.trim(),\n );\n this.#baseUrl = (config.baseUrl ?? process.env.GITLAB_BASE_URL?.trim() ?? 'https://gitlab.com').replace(/\\/+$/, '');\n this.#webhookSecret = config.webhookSecret?.trim() || process.env.GITLAB_WEBHOOK_SECRET?.trim() || undefined;\n const api = new GitLabApiClient({\n baseUrl: this.#baseUrl,\n accessToken: this.#accessToken,\n ...(config.fetchImpl ? { fetchImpl: config.fetchImpl } : {}),\n });\n this.#context = {\n id: DIRECT_CONNECTION_ID,\n label: new URL(this.#baseUrl).host,\n api,\n connection: { type: 'oauth', accessToken: DIRECT_CONNECTION_TOKEN },\n host: new URL(this.#baseUrl).host,\n webBaseUrl: this.#baseUrl,\n repositoryAccessToken: async () => this.#accessToken,\n };\n }\n\n protected override get webhookSecret(): string | undefined {\n return this.#webhookSecret;\n }\n\n async hasActiveConnections(): Promise<boolean> {\n return true;\n }\n\n override async verifyStatus(): Promise<void> {\n await this.#context.api.getCurrentUser();\n }\n\n authFailureMessage(): string {\n return `GitLab rejected the configured ${this.#accessTokenType} access token. Check the token and its scopes.`;\n }\n\n protected async activeContexts(): Promise<GitLabConnectionContext[]> {\n return [this.#context];\n }\n\n protected async contextById(connectionId: string): Promise<GitLabConnectionContext> {\n if (connectionId !== DIRECT_CONNECTION_ID) {\n throw new GitLabApiError('GitLab connection is unavailable.', 401);\n }\n return this.#context;\n }\n\n diagnostics(): Record<string, unknown> {\n return {\n configured: true,\n mode: 'direct',\n accessTokenType: this.#accessTokenType,\n endpointHost: new URL(this.#baseUrl).host,\n webhookConfigured: Boolean(this.#webhookSecret),\n };\n }\n}\n\nfunction parseAccessTokenType(value: string | undefined): GitLabAccessTokenType {\n const normalized = value?.trim().toLowerCase() || 'personal';\n if (normalized === 'personal' || normalized === 'group') return normalized;\n throw new Error(\"GitLabIntegration: GITLAB_ACCESS_TOKEN_TYPE must be 'personal' or 'group'.\");\n}\n\nexport function encodeSourceId(reference: GitLabSourceReference): string {\n if (reference.host) {\n return `${GITLAB_SOURCE_PREFIX}${encodeOpaque({\n version: 2,\n host: normalizeGitLabHost(reference.host),\n projectId: reference.projectId,\n })}`;\n }\n if (!reference.connectionId || !reference.projectPath) {\n throw new Error('GitLab source reference is missing its instance host.');\n }\n return `${GITLAB_SOURCE_PREFIX}${encodeOpaque(reference)}`;\n}\n\nexport function decodeSourceId(value: string): GitLabSourceReference | null {\n return decodeOpaque(value, GITLAB_SOURCE_PREFIX, isSourceReference);\n}\n\nexport function encodeIssueReference(reference: GitLabIssueReference): string {\n if (reference.host) {\n return `${GITLAB_ISSUE_PREFIX}${encodeOpaque({\n version: 2,\n host: normalizeGitLabHost(reference.host),\n projectId: reference.projectId,\n issueIid: reference.issueIid,\n })}`;\n }\n if (!reference.connectionId || !reference.projectPath) {\n throw new Error('GitLab issue reference is missing its instance host.');\n }\n return `${GITLAB_ISSUE_PREFIX}${encodeOpaque(reference)}`;\n}\n\nexport function decodeIssueReference(value: string): GitLabIssueReference | null {\n return decodeOpaque(value, GITLAB_ISSUE_PREFIX, isIssueReference);\n}\n\nexport function decodeMergeRequestReference(value: string): GitLabMergeRequestReference | null {\n return decodeOpaque(value, GITLAB_MERGE_REQUEST_PREFIX, isMergeRequestReference);\n}\n\nexport function gitlabConnection(connectionId: string): IntegrationConnection {\n return { type: 'oauth', accessToken: `${GITLAB_CONNECTION_TOKEN_PREFIX}${connectionId}` };\n}\n\nfunction connectionIdFromConnection(connection: IntegrationConnection): string | null {\n if (connection.type !== 'oauth' || !connection.accessToken.startsWith(GITLAB_CONNECTION_TOKEN_PREFIX)) return null;\n return connection.accessToken.slice(GITLAB_CONNECTION_TOKEN_PREFIX.length) || null;\n}\n\nfunction encodeOpaque(value: unknown): string {\n return Buffer.from(JSON.stringify(value)).toString('base64url');\n}\n\nfunction decodeOpaque<T>(value: string, prefix: string, guard: (value: unknown) => value is T): T | null {\n if (!value.startsWith(prefix)) return null;\n try {\n const decoded = JSON.parse(Buffer.from(value.slice(prefix.length), 'base64url').toString('utf8')) as unknown;\n return guard(decoded) ? decoded : null;\n } catch {\n return null;\n }\n}\n\nexport function normalizeGitLabHost(host: string): string {\n return host.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction isSourceReference(value: unknown): value is GitLabSourceReference {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const ref = value as Record<string, unknown>;\n if (typeof ref.projectId !== 'string' || ref.projectId.length === 0) return false;\n const canonical = ref.version === 2 && typeof ref.host === 'string' && normalizeGitLabHost(ref.host).length > 0;\n const legacy =\n typeof ref.connectionId === 'string' &&\n ref.connectionId.length > 0 &&\n typeof ref.projectPath === 'string' &&\n ref.projectPath.length > 0;\n return canonical || legacy;\n}\n\nfunction isIssueReference(value: unknown): value is GitLabIssueReference {\n return (\n isSourceReference(value) &&\n Number.isSafeInteger((value as GitLabIssueReference).issueIid) &&\n (value as GitLabIssueReference).issueIid > 0\n );\n}\n\nfunction isMergeRequestReference(value: unknown): value is GitLabMergeRequestReference {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const ref = value as Record<string, unknown>;\n return (\n ref.version === 1 &&\n typeof ref.host === 'string' &&\n normalizeGitLabHost(ref.host).length > 0 &&\n Number.isSafeInteger(ref.projectId) &&\n (ref.projectId as number) > 0 &&\n Number.isSafeInteger(ref.mergeRequestIid) &&\n (ref.mergeRequestIid as number) > 0\n );\n}\n\nfunction encodePageCursor(cursor: GitLabPageCursor): string {\n return encodeOpaque(cursor);\n}\n\nfunction decodePageCursor(value: string | undefined): GitLabPageCursor | null {\n if (!value) return { source: 0, page: 1 };\n try {\n const decoded = JSON.parse(Buffer.from(value, 'base64url').toString('utf8')) as Record<string, unknown>;\n if (!Number.isSafeInteger(decoded.source) || Number(decoded.source) < 0) return null;\n if (!Number.isSafeInteger(decoded.page) || Number(decoded.page) < 1) return null;\n return { source: Number(decoded.source), page: Number(decoded.page) };\n } catch {\n return null;\n }\n}\n\nfunction displayName(user: { name?: string | null; username: string } | null | undefined): string | null {\n return user?.name?.trim() || user?.username || null;\n}\n\nfunction parsePositiveInteger(value: string): number | null {\n if (!/^\\d+$/.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction parseIssueLocator(value: string): {\n host?: string;\n projectPath: string;\n issueIid: number;\n} | null {\n const shorthand = value.match(/^(.+?)#(\\d+)$/);\n if (shorthand) {\n const issueIid = parsePositiveInteger(shorthand[2]!);\n const projectPath = shorthand[1]!.replace(/^\\/+|\\/+$/g, '');\n return issueIid && projectPath ? { projectPath, issueIid } : null;\n }\n try {\n const url = new URL(value);\n const match = url.pathname.match(/^\\/(.+)\\/-\\/issues\\/(\\d+)\\/?$/);\n if (!match) return null;\n const issueIid = parsePositiveInteger(match[2]!);\n if (!issueIid) return null;\n const projectPath = decodeURIComponent(match[1]!);\n return { host: url.host, projectPath, issueIid };\n } catch {\n return null;\n }\n}\n\nfunction targetStateEvent(input: UpdateIntakeIssueInput): 'close' | 'reopen' | null {\n if (input.state.kind === 'byType') {\n // GitLab issues have only opened/closed states, so canceled is intentionally mapped to close.\n return input.state.stateType === 'completed' || input.state.stateType === 'canceled' ? 'close' : 'reopen';\n }\n const name = input.state.name.trim().toLowerCase();\n if (name === 'closed' || name === 'close') return 'close';\n if (name === 'opened' || name === 'open' || name === 'reopen') return 'reopen';\n return null;\n}\n"],"mappings":";;;;;;;;;;;AAmGA,MAAM,uBAAuB;AAC7B,MAAM,iCAAiC;AACvC,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAC5B,MAAM,8BAA8B;AACpC,MAAa,8BAA8B;AAE3C,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAErB,IAAsB,wBAAtB,MAA0E;CACxE,KAAc;CACd;CACA;CACA;CACA;CACA,qCAA8B,IAAI,IAA2B;CAC7D;CAEA,YAAY,OAA6B;EACvC,KAAK,QAAQ,mBAAmB,KAAK;CACvC;CAEA,SAA0B;EACxB,wBAAuB,UAAS,KAAK,uBAAuB,KAAK;EACjE,mBAAmB,KAAK,aAAa;EACrC,YAAW,UAAS,KAAK,WAAW,KAAK;EACzC,aAAY,UAAS,KAAK,YAAY,KAAK;EAC3C,WAAU,UAAS,KAAK,UAAU,KAAK;EACvC,gBAAe,UAAS,KAAK,eAAe,KAAK;EACjD,cAAa,UAAS,KAAK,aAAa,KAAK;CAC/C;CACA,iBAA0B,0BAA0B;EAClD,uBAAsB,eAAc,KAAK,uBAAuB,UAAU;EAC1E,+BAA+B,YAAY,SAAS,KAAK,sCAAsC,YAAY,IAAI;CACjH,CAAC;CACD,WAAW,EACT,SACA,UACA,MACA,iBAMO;EACP,KAAK,YAAY;EACjB,KAAK,QAAQ;EACb,KAAK,iBAAiB;EACtB,KAAK,sBAAsB;CAC7B;;CAGA,IAAI,qBAAgD;EAClD,IAAI,CAAC,KAAK,qBACR,MAAM,IAAI,MAAM,GAAG,KAAK,YAAY,KAAK,kEAAkE;EAE7G,OAAO,KAAK;CACd;;CAGA,IAAI,uBAA+D;EACjE,OAAO,KAAK;CACd;CAEA,IAAI,cAAuB;EACzB,OAAO,KAAK,OAAO,QAAQ,KAAK;CAClC;CAEA,IAAI,WAAmC;EACrC,IAAI,CAAC,KAAK,WACR,MAAM,IAAI,MAAM,GAAG,KAAK,YAAY,KAAK,kEAAkE;EAE7G,OAAO,KAAK;CACd;CAEA,MAAM,aAAa,YAA4C;EAC7D,MAAM,SAAS,KAAK,mBAAmB,IAAI,UAAU;EACrD,IAAI,WAAW,KAAA,GAAW,OAAO;EACjC,IAAI,CAAC,aAAa,KAAK,UAAU,GAAG;GAClC,KAAK,mBAAmB,IAAI,YAAY,IAAI;GAC5C,OAAO;EACT;EACA,IAAI;GACF,MAAM,KAAK,SAAS,YAAY;GAEhC,MAAM,SAAQ,MADQ,KAAK,SAAS,QAAQ,EAAE,IAAI,WAAW,CAAC,EAAA,EACvC,SAAS;GAChC,KAAK,mBAAmB,IAAI,YAAY,KAAK;GAC7C,OAAO;EACT,QAAQ;GACN,OAAO;EACT;CACF;CAEA,cAAoB;EAClB,KAAK,mBAAmB,MAAM;CAChC;;CAQA,MAAM,oBAAoB,OAAiF;EACzG,IAAI,CAAC,KAAK,gBAAgB,OAAO;EACjC,MAAM,cAAc,MAAM,KAAK,eAAe,YAAY,KAAK;GAC7D,OAAO,MAAM;GACb,kBAAkB,MAAM;EAC1B,CAAC;EACD,KAAK,MAAM,cAAc,aAAa;GACpC,IAAI,WAAW,kBAAkB,UAAU;GAK3C,MAAM,QAAO,MAJO,KAAK,eAAe,oBAAoB,KAAK;IAC/D,OAAO,MAAM;IACb,cAAc,WAAW;GAC3B,CAAC,EAAA,CACkB,MAAK,cAAa,UAAU,OAAO,MAAM,mBAAmB;GAC/E,IAAI,CAAC,MAAM;GACX,MAAM,aAAa,MAAM,KAAK,eAAe,aAAa,IAAI;IAAE,OAAO,MAAM;IAAO,IAAI,KAAK;GAAa,CAAC;GAC3G,MAAM,eAAe,MAAM,KAAK,eAAe,cAAc,IAAI;IAC/D,OAAO,MAAM;IACb,IAAI,WAAW;GACjB,CAAC;GACD,IAAI,CAAC,cAAc,CAAC,cAAc,OAAO;GACzC,MAAM,OAAO,aAAa,iBAAiB;GAC3C,IAAI,OAAO,SAAS,YAAY,CAAC,MAAM,OAAO;GAC9C,OAAO;IAAE;IAAY,MAAM,oBAAoB,IAAI;GAAE;EACvD;EACA,OAAO;CACT;CAEA,MAAM,4BACJ,cACA,WACA,UAC6B;EAC7B,MAAM,aAAa,SAAS,KAAK,CAAC,CAAC,YAAY;EAC/C,IAAI,CAAC,YAAY,OAAO,KAAA;EAKxB,QAHe,OADQ,MAAM,KAAK,YAAY,YAAY,EAAA,CAAG,IAAI,mBAAmB,WAAW,EAAE,OAAO,SAAS,CAAC,EAAA,CAC3F,MACrB,cAAa,UAAU,SAAS,YAAY,MAAM,cAAc,UAAU,UAAU,SAE1E,CAAC,EAAE;CACjB;CAEA,MAAM,0BACJ,cACA,WACA,MACA,KAC6B;EAC7B,MAAM,OAAO,MAAM,KAAK,YAAY,YAAY,EAAA,CAAG;EAEnD,QADa,SAAS,UAAU,MAAM,IAAI,SAAS,WAAW,GAAG,IAAI,MAAM,IAAI,gBAAgB,WAAW,GAAG,EAAA,CACjG,QAAQ;CACtB;CAEA,MAAM,gCAAgC,UAAkB,UAAoC;EAC1F,MAAM,YAAY,eAAe,QAAQ;EACzC,IAAI,CAAC,WAAW,MAAM,IAAI,eAAe,sCAAsC,GAAG;EAClF,MAAM,EAAE,SAAS,WAAW,MAAM,KAAK,wBAAwB,SAAS;EAExE,QAAQ,MADkB,KAAK,4BAA4B,QAAQ,IAAI,OAAO,WAAW,QAAQ,KAC1E,MAAA;CACzB;CAEA,MAAM,0BAA0B,OAIM;EACpC,IAAI,CAAC,KAAK,gBAAgB,MAAM,IAAI,eAAe,yCAAyC,GAAG;EAC/F,MAAM,YAAY,qBAAqB,MAAM,OAAO;EACpD,MAAM,UAAU,kBAAkB,MAAM,OAAO;EAC/C,IAAI,CAAC,aAAa,CAAC,SACjB,MAAM,IAAI,eAAe,sDAAsD,GAAG;EAGpF,MAAM,iBAAiB,UAAkB,MAAM,QAAQ,cAAc,EAAE,CAAC,CAAC,YAAY;EACrF,MAAM,UAID,CAAC;EACN,MAAM,cAAc,MAAM,KAAK,eAAe,YAAY,KAAK;GAC7D,OAAO,MAAM;GACb,kBAAkB,MAAM;EAC1B,CAAC;EACD,KAAK,MAAM,cAAc,aAAa;GACpC,MAAM,eAAe,MAAM,KAAK,eAAe,cAAc,IAAI;IAC/D,OAAO,MAAM;IACb,IAAI,WAAW;GACjB,CAAC;GACD,IAAI,CAAC,cAAc;GACnB,KAAK,MAAM,qBAAqB,MAAM,KAAK,eAAe,oBAAoB,KAAK;IACjF,OAAO,MAAM;IACb,cAAc,WAAW;GAC3B,CAAC,GAAG;IACF,MAAM,aAAa,MAAM,KAAK,eAAe,aAAa,IAAI;KAC5D,OAAO,MAAM;KACb,IAAI,kBAAkB;IACxB,CAAC;IACD,IAAI,CAAC,YAAY;IACjB,IAAI,WAAW,aAAa,WAAW,eAAe,UAAU,WAAW;IAC3E,IAAI,WAAW,eAAe,cAAc,WAAW,IAAI,MAAM,cAAc,UAAU,WAAW,GAAG;IACvG,IAAI,SAAS,eAAe,cAAc,WAAW,IAAI,MAAM,cAAc,QAAQ,WAAW,GAAG;IACnG,IAAI,WAAW,gBAAgB,aAAa,eAAe,UAAU,cAAc;IACnF,MAAM,mBACJ,OAAO,aAAa,iBAAiB,SAAS,WAC1C,oBAAoB,aAAa,iBAAiB,IAAI,IACtD;IACN,IAAI,WAAW,QAAQ,qBAAqB,oBAAoB,UAAU,IAAI,GAAG;IACjF,IAAI,SAAS,QAAQ,qBAAqB,oBAAoB,QAAQ,IAAI,GAAG;IAC7E,QAAQ,KAAK;KACX,cAAc,aAAa;KAC3B,WAAW,WAAW;KACtB,aAAa,WAAW;IAC1B,CAAC;GACH;EACF;EACA,MAAM,QAAQ,QAAQ,MAAM,MAAM,UAAU,KAAK,aAAa,cAAc,MAAM,YAAY,CAAC,CAAC,CAAC;EACjG,IAAI,CAAC,OAAO,MAAM,IAAI,eAAe,uDAAuD,GAAG;EAC/F,OAAO,KAAK,OAAO,SAAS;GAC1B,YAAY,iBAAiB,MAAM,YAAY;GAC/C,UAAU,eAAe,KAAK;GAC9B,SAAS,MAAM;EACjB,CAAC;CACH;;CAGA,MAAM,oBAAmE,CAEzE;;CAGA,MAAM,eAA8B,CAEpC;CAEA,IAAc,gBAAoC,CAElD;CAEA,QAAQ,KAAyC;EAC/C,IAAI,CAAC,4BAA4B,GAAG,OAAO,CAAC;EAC5C,MAAM,YAAY,uBAAuB,MAAM,GAAG;EAClD,IAAI,CAAC,WAAW,OAAO,CAAC;EACxB,MAAM,aAAa,6BAA6B;EAChD,OAAO,CACL,IAAI,qBAAqB;GACvB,eAAe,KAAK;GACpB;GACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;EACrC,CAAC,CACH;CACF;CACA,OAAO,KAAqC;EAC1C,MAAM,qBAAqB,kBAAkB,MAAM,GAAG;EACtD,OAAO,kBAAkB;GACvB,QAAQ;GACR,MAAM,IAAI;GACV,QAAQ,IAAI,SAAS;GACrB,WAAW,IAAI,OAAO;GACtB,SAAS,IAAI;GACb,eAAe,KAAK;GACpB;GACA,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,WAAW,IAAI,CAAC;EACzD,CAAC;CACH;CAEA,MAAM,WAAW,MAAqE;EACpF,OAAO,sBAAsB;GAAE,gBAAgB,KAAK;GAAgB,QAAQ;EAAK,CAAC;CACpF;CAEA,aAAa,EAAE,kBAAwE;EACrF,OAAO,8BAA8B,gBAAgB,IAAI;CAC3D;CAEA,MAAM,iBAAiB,EACrB,aACA,kBACoF;EACpF,MAAM,kBAAkB,yBAAyB,WAAW;EAC5D,IAAI,CAAC,mBAAmB,CAAC,gBAAgB;EACzC,MAAM,sCAAsC,gBAAgB,iBAAiB,8BAA8B,IAAI;CACjH;;CAKA,MAAM,+BAA+B,oBAA4B,MAA+B;EAC9F,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,UAAU,OAAO;EACjD,MAAM,CAAC,UAAU,MAAM,KAAK,eAAe;EAC3C,OAAO,UAAU,oBAAoB,OAAO,IAAI,MAAM,oBAAoB,IAAI,IAAI,OAAO,KAAK;CAChG;CAEA,MAAM,uBAAuB,YAAqE;EAChG,MAAM,eAAe,2BAA2B,UAAU;EAC1D,IAAI,cAAc,OAAO,KAAK,YAAY,YAAY;EACtD,MAAM,WAAW,MAAM,KAAK,eAAe;EAC3C,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,eACR,2GACA,GACF;EAEF,OAAO,SAAS;CAClB;CACA,MAAM,sCACJ,YACA,MACkC;EAGlC,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,YAAY,MAAM;GAChD,MAAM,CAAC,UAAU,MAAM,KAAK,eAAe;GAC3C,IAAI,UAAU,oBAAoB,IAAI,MAAM,oBAAoB,OAAO,IAAI,GAAG,OAAO;EACvF;EACA,OAAO,KAAK,uBAAuB,UAAU;CAC/C;CACA,MAAM,qBAAqB,WAAoE;EAC7F,IAAI,UAAU,cAAc,OAAO,KAAK,YAAY,UAAU,YAAY;EAC1E,MAAM,YAAY,MAAM,KAAK,eAAe,EAAA,CAAG,QAC7C,YAAW,CAAC,UAAU,QAAQ,oBAAoB,QAAQ,IAAI,MAAM,oBAAoB,UAAU,IAAI,CACxG;EACA,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,eAAe,uDAAuD,GAAG;EAErF,IAAI,SAAS,WAAW,GAAG,OAAO,SAAS;EAE3C,IAAI,KAAK,gBAAgB;GACvB,MAAM,sBAAsB,IAAI,KAC7B,MAAM,KAAK,eAAe,oBAAoB,2BAA2B,EAAA,CACvE,QAAO,QAAO,IAAI,yBAAyB,UAAU,SAAS,CAAC,CAC/D,KAAI,QAAO,IAAI,sBAAsB,CAC1C;GACA,MAAM,SAAS,SAAS,QAAO,YAAW,oBAAoB,IAAI,QAAQ,EAAE,CAAC;GAC7E,IAAI,OAAO,SAAS,GAAG,OAAO,OAAO,MAAM,MAAM,UAAU,KAAK,GAAG,cAAc,MAAM,EAAE,CAAC,CAAC,CAAC;EAC9F;EAEA,KAAK,MAAM,WAAW,SAAS,MAAM,MAAM,UAAU,KAAK,GAAG,cAAc,MAAM,EAAE,CAAC,GAClF,IAAI;GACF,MAAM,QAAQ,IAAI,WAAW,UAAU,SAAS;GAChD,OAAO;EACT,SAAS,OAAO;GACd,IAAI,EAAE,iBAAiB,mBAAmB,CAAC;IAAC;IAAK;IAAK;GAAG,CAAC,CAAC,SAAS,MAAM,UAAU,CAAC,GAAG,MAAM;EAEhG;EAEF,MAAM,IAAI,eAAe,uDAAuD,GAAG;CACrF;CAEA,MAAM,wBACJ,WACsF;EACtF,MAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;EACzD,MAAM,cACJ,UAAU,gBAAgB,MAAM,QAAQ,IAAI,WAAW,UAAU,SAAS,EAAA,CAAG;EAC/E,OAAO;GACL;GACA,QAAQ;IACN,cAAc,QAAQ;IACtB,MAAM,oBAAoB,UAAU,QAAQ,QAAQ,IAAI;IACxD,WAAW,UAAU;IACrB;GACF;EACF;CACF;CAEA,MAAM,uBAAuB,EAAE,kBAAsF;EACnH,IAAI,eAAe,SAAS,SAAS,OAAO;EAC5C,MAAM,YAAY,qBAAqB,eAAe,UAAU;EAChE,IAAI,CAAC,WAAW,OAAO;EACvB,MAAM,EAAE,SAAS,WAAW,MAAM,KAAK,wBAAwB,SAAS;EACxE,OAAO;GACL,YAAY,QAAQ;GACpB,UAAU,eAAe,MAAM;GAC/B,SAAS,OAAO,UAAU,QAAQ;EACpC;CACF;CAEA,MAAM,eAAwC;EAC5C,MAAM,0BAAU,IAAI,IAA0B;EAC9C,KAAK,MAAM,WAAW,MAAM,KAAK,eAAe,GAC9C,KAAK,IAAI,OAAO,IAAK,QAAQ;GAC3B,MAAM,WAAW,MAAM,QAAQ,IAAI,aAAa,EAAE,KAAK,CAAC;GACxD,KAAK,MAAM,WAAW,UAAU;IAC9B,MAAM,SAAS,KAAK,gBAAgB,SAAS,OAAO;IACpD,IAAI,CAAC,QAAQ,IAAI,OAAO,EAAE,GAAG,QAAQ,IAAI,OAAO,IAAI,MAAM;GAC5D;GACA,IAAI,SAAS,SAAA,KAAoC;EACnD;EAEF,OAAO,CAAC,GAAG,QAAQ,OAAO,CAAC;CAC7B;CAEA,MAAM,WAAW,OAAsD;EACrE,MAAM,SAAS,MAAM,KAAK,eAAe,MAAM,WAAW,MAAM,MAAM;EACtE,OAAO;GACL,OAAO,OAAO,OAAO,KAAK,EAAE,OAAO,QAAQ,eAAe;IACxD,QAAQ;KACN,MAAM;KACN,YAAY,qBAAqB;MAAE,GAAG;MAAQ,UAAU,MAAM;KAAI,CAAC;KACnE,KAAK,MAAM;IACb;IACA,UAAU,eAAe,MAAM;IAC/B,OAAO,GAAG,OAAO,YAAY,GAAG,MAAM,IAAI,IAAI,MAAM;IACpD,QAAQ,MAAM;IACd,QAAQ,MAAM,UAAU,CAAC;IACzB,UAAU,YAAY,MAAM,QAAQ;IACpC,WAAW,MAAM;IACjB,WAAW,MAAM;IACjB,UAAU;KACR,YAAY,GAAG,OAAO,YAAY,GAAG,MAAM;KAC3C,WAAW,OAAO;KAClB,aAAa,OAAO;KACpB,cAAc,QAAQ;KACtB,cAAc,QAAQ;KACtB,aAAa,OAAO,aAAa,MAAM,gBAAgB,CAAC,EAAA,CAAG,KAAI,UAAS,CAAC,MAAM,MAAM,MAAM,KAAK,CAAC,CAAC;IACpG;GACF,EAAE;GACF,YAAY,OAAO;EACrB;CACF;CAEA,MAAM,YAAY,OAA8B;EAC9C,MAAM,SAAS,MAAM,KAAK,eAAe,MAAM,WAAW,MAAM,QAAQ,MAAM,MAAM;EACpF,OAAO;GACL,QAAQ,OAAO,OAAO,KAAK,EAAE,OAAO,cAAc;IAChD,GAAG,KAAK,eAAe,OAAO,OAAO,WAAW;IAChD,UAAU,eAAe,MAAM;GACjC,EAAE;GACF,YAAY,OAAO;EACrB;CACF;CAEA,MAAM,eAAe,WAAqB,QAAiB,QAAmB;EAC5E,MAAM,UAAU,UAAU,IAAI,cAAc,CAAC,CAAC,QAAQ,WAA4C,WAAW,IAAI;EACjH,IAAI,QAAQ,WAAW,GAAG,OAAO;GAAE,QAAQ,CAAC;GAAG,YAAY;EAAK;EAChE,MAAM,UAAU,iBAAiB,MAAM;EACvC,IAAI,CAAC,WAAW,QAAQ,UAAU,QAAQ,QAAQ,OAAO;GAAE,QAAQ,CAAC;GAAG,YAAY;EAAK;EAExF,KAAK,IAAI,cAAc,QAAQ,QAAQ,cAAc,QAAQ,QAAQ,eAAe;GAClF,MAAM,EAAE,QAAQ,YAAY,MAAM,KAAK,wBAAwB,QAAQ,YAAa;GACpF,MAAM,OAAO,gBAAgB,QAAQ,SAAS,QAAQ,OAAO;GAC7D,MAAM,SAAS,MAAM,QAAQ,IAAI,WAAW,OAAO,WAAW;IAAE;IAAM;GAAO,CAAC;GAC9E,MAAM,aACJ,OAAO,WAAA,KACH,iBAAiB;IAAE,QAAQ;IAAa,MAAM,OAAO;GAAE,CAAC,IACxD,cAAc,IAAI,QAAQ,SACxB,iBAAiB;IAAE,QAAQ,cAAc;IAAG,MAAM;GAAE,CAAC,IACrD;GACR,OAAO;IAAE,QAAQ,OAAO,KAAI,WAAU;KAAE;KAAO;KAAQ;IAAQ,EAAE;IAAG;GAAW;EACjF;EACA,OAAO;GAAE,QAAQ,CAAC;GAAG,YAAY;EAAK;CACxC;CAEA,MAAM,UAAU,OAA+D;EAC7E,MAAM,WAAW,MAAM,KAAK,gBAAgB,KAAK;EACjD,IAAI;EACJ,IAAI;GACF,QAAQ,MAAM,SAAS,QAAQ,IAAI,SAAS,SAAS,WAAW,SAAS,QAAQ;EACnF,SAAS,OAAO;GACd,IAAI,iBAAiB,kBAAkB,MAAM,WAAW,KAAK,OAAO;GACpE,MAAM;EACR;EACA,MAAM,QAAQ,MAAM,KAAK,cAAc,SAAS,QAAQ,KAAK,SAAS,WAAW,SAAS,QAAQ;EAClG,OAAO;GACL,GAAG,KAAK,eAAe,OAAO,SAAS,WAAW;GAClD,aAAa,MAAM,aAAa,KAAK,KAAK;GAC1C,UAAU,MACP,QAAO,SAAQ,CAAC,KAAK,MAAM,CAAC,CAC5B,KAAI,UAAS;IAAE,QAAQ,YAAY,KAAK,MAAM;IAAG,MAAM,KAAK;IAAM,WAAW,KAAK;GAAW,EAAE;EACpG;CACF;CAEA,MAAM,cAAc,KAAsB,WAAmB,UAAyC;EACpG,MAAM,QAAsB,CAAC;EAC7B,KAAK,IAAI,OAAO,GAAG,QAAQ,iBAAiB,QAAQ;GAClD,MAAM,SAAS,MAAM,IAAI,UAAU,WAAW,UAAU,EAAE,KAAK,CAAC;GAChE,MAAM,KAAK,GAAG,MAAM;GACpB,IAAI,OAAO,SAAA,KAAiC;EAC9C;EACA,OAAO;CACT;CAEA,MAAM,eAAe,OAAuE;EAC1F,MAAM,WAAW,MAAM,KAAK,gBAAgB,KAAK;EACjD,IAAI;GACF,MAAM,QAAQ,MAAM,SAAS,QAAQ,IAAI,SAAS,SAAS,WAAW,SAAS,QAAQ;GACvF,MAAM,OAAO,MAAM,SAAS,QAAQ,IAAI,WAAW,SAAS,WAAW,SAAS,UAAU,MAAM,IAAI;GACpG,OAAO;IAAE,IAAI,OAAO,KAAK,EAAE;IAAG,KAAK,GAAG,MAAM,QAAQ,QAAQ,KAAK;GAAK;EACxE,SAAS,OAAO;GACd,IAAI,iBAAiB,kBAAkB,MAAM,WAAW,KAAK,OAAO;GACpE,MAAM;EACR;CACF;CAEA,MAAM,aAAa,OAA4D;EAC7E,MAAM,WAAW,MAAM,KAAK,gBAAgB,KAAK;EACjD,IAAI;EACJ,IAAI;GACF,QAAQ,MAAM,SAAS,QAAQ,IAAI,SAAS,SAAS,WAAW,SAAS,QAAQ;EACnF,SAAS,OAAO;GACd,IAAI,iBAAiB,kBAAkB,MAAM,WAAW,KAAK,OAAO;GACpE,MAAM;EACR;EACA,MAAM,aAAa,iBAAiB,KAAK;EACzC,IAAI,CAAC,YAAY,OAAO;EACxB,IAAK,eAAe,WAAW,MAAM,UAAU,YAAc,eAAe,YAAY,MAAM,UAAU,UACtG,OAAO,KAAK,eAAe,OAAO,SAAS,WAAW;EAExD,MAAM,UAAU,MAAM,SAAS,QAAQ,IAAI,iBAAiB,SAAS,WAAW,SAAS,UAAU,UAAU;EAC7G,OAAO,KAAK,eAAe,SAAS,SAAS,WAAW;CAC1D;CAEA,MAAM,gBAAgB,OAKnB;EACD,MAAM,iBAAiB,qBAAqB,MAAM,OAAO;EACzD,MAAM,SAAS,MAAM,WAAW,eAAe,MAAM,QAAQ,IAAI;EACjE,MAAM,UAAU,kBAAkB,MAAM,OAAO;EAC/C,MAAM,YAAY,kBAAkB;EACpC,IAAI;EACJ,IAAI,WACF,UAAU,MAAM,KAAK,qBAAqB,SAAS;OAC9C;GACL,MAAM,eAAe,2BAA2B,MAAM,UAAU;GAChE,MAAM,WAAW,eAAe,CAAC,MAAM,KAAK,YAAY,YAAY,CAAC,IAAI,MAAM,KAAK,eAAe;GACnG,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,eAAe,yEAAyE,GAAG;GAEvG,UAAU,SAAS;EACrB;EACA,MAAM,YAAY,gBAAgB,aAAa,QAAQ,aAAa,SAAS;EAC7E,MAAM,WAAW,gBAAgB,YAAY,SAAS,YAAY,qBAAqB,MAAM,OAAO;EACpG,IAAI,CAAC,aAAa,CAAC,UACjB,MAAM,IAAI,eACR,sFACA,GACF;EAEF,MAAM,cACJ,gBAAgB,eAChB,QAAQ,eACR,SAAS,gBACR,MAAM,QAAQ,IAAI,WAAW,SAAS,EAAA,CAAG;EAC5C,OAAO;GAAE;GAAS;GAAW;GAAa;EAAS;CACrD;CAEA,gBAAgB,SAAkC,SAAsC;EAMtF,OAAO;GACL,IAAI,eAAe;IALnB,MAAM,oBAAoB,QAAQ,IAAI;IACtC,WAAW,OAAO,QAAQ,EAAE;IAC5B,aAAa,QAAQ;GAGM,CAAC;GAC5B,MAAM,QAAQ;GACd,MAAM;GACN,UAAU;IACR,WAAW,OAAO,QAAQ,EAAE;IAC5B,aAAa,QAAQ;IACrB,eAAe,QAAQ,kBAAkB;IACzC,cAAc,QAAQ;IACtB,cAAc,QAAQ;IACtB,KAAK,QAAQ;GACf;EACF;CACF;CAEA,eAAe,OAAoB,aAAkC;EACnE,MAAM,YAAY,MAAM,WAAW,IAAI,WAAW,CAAC,CAAC,QAAQ,SAAyB,SAAS,IAAI,KAAK,CAAC;EACxG,OAAO;GACL,IAAI,OAAO,MAAM,GAAG;GACpB,YAAY,GAAG,YAAY,GAAG,MAAM;GACpC,OAAO,MAAM;GACb,KAAK,MAAM;GACX,QAAQ,YAAY,MAAM,MAAM;GAChC,gBAAgB,MAAM,QAAQ,YAAY;GAC1C,OAAO,MAAM;GACb,WAAW,MAAM,UAAU,WAAW,cAAc;GACpD,UAAU,OAAO,MAAM,WAAW,WAAW,OAAO,MAAM,MAAM,IAAI;GACpE,UAAU,YAAY,MAAM,QAAQ,KAAK,UAAU,MAAM;GACzD;GACA,QAAQ;GACR,QAAQ,MAAM,UAAU,CAAC;GACzB,aAAa,OAAO,aAAa,MAAM,gBAAgB,CAAC,EAAA,CAAG,KAAI,UAAS,CAAC,MAAM,MAAM,MAAM,KAAK,CAAC,CAAC;GAClG,cAAc,MAAM,oBAAoB;GACxC,WAAW,MAAM;GACjB,WAAW,MAAM;EACnB;CACF;AACF;AAcA,MAAM,0BAA0B;AAEhC,IAAa,oBAAb,cAAuC,sBAAsB;CAC3D;CACA;CACA;CACA;CACA;CAEA,YAAY,SAAkC,CAAC,GAAG;EAChD,MAAM,OAAO,KAAK;EAClB,MAAM,cAAc,OAAO,aAAa,KAAK,KAAK,QAAQ,IAAI,qBAAqB,KAAK;EACxF,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,0DAA0D;EAE5E,KAAK,eAAe;EACpB,KAAK,mBAAmB,qBACtB,OAAO,mBAAmB,QAAQ,IAAI,0BAA0B,KAAK,CACvE;EACA,KAAK,YAAY,OAAO,WAAW,QAAQ,IAAI,iBAAiB,KAAK,KAAK,qBAAA,CAAsB,QAAQ,QAAQ,EAAE;EAClH,KAAK,iBAAiB,OAAO,eAAe,KAAK,KAAK,QAAQ,IAAI,uBAAuB,KAAK,KAAK,KAAA;EACnG,MAAM,MAAM,IAAI,gBAAgB;GAC9B,SAAS,KAAK;GACd,aAAa,KAAK;GAClB,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;EAC5D,CAAC;EACD,KAAK,WAAW;GACd,IAAI;GACJ,OAAO,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC;GAC9B;GACA,YAAY;IAAE,MAAM;IAAS,aAAa;GAAwB;GAClE,MAAM,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC;GAC7B,YAAY,KAAK;GACjB,uBAAuB,YAAY,KAAK;EAC1C;CACF;CAEA,IAAuB,gBAAoC;EACzD,OAAO,KAAK;CACd;CAEA,MAAM,uBAAyC;EAC7C,OAAO;CACT;CAEA,MAAe,eAA8B;EAC3C,MAAM,KAAK,SAAS,IAAI,eAAe;CACzC;CAEA,qBAA6B;EAC3B,OAAO,kCAAkC,KAAK,iBAAiB;CACjE;CAEA,MAAgB,iBAAqD;EACnE,OAAO,CAAC,KAAK,QAAQ;CACvB;CAEA,MAAgB,YAAY,cAAwD;EAClF,IAAI,iBAAiB,sBACnB,MAAM,IAAI,eAAe,qCAAqC,GAAG;EAEnE,OAAO,KAAK;CACd;CAEA,cAAuC;EACrC,OAAO;GACL,YAAY;GACZ,MAAM;GACN,iBAAiB,KAAK;GACtB,cAAc,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC;GACrC,mBAAmB,QAAQ,KAAK,cAAc;EAChD;CACF;AACF;AAEA,SAAS,qBAAqB,OAAkD;CAC9E,MAAM,aAAa,OAAO,KAAK,CAAC,CAAC,YAAY,KAAK;CAClD,IAAI,eAAe,cAAc,eAAe,SAAS,OAAO;CAChE,MAAM,IAAI,MAAM,4EAA4E;AAC9F;AAEA,SAAgB,eAAe,WAA0C;CACvE,IAAI,UAAU,MACZ,OAAO,GAAG,uBAAuB,aAAa;EAC5C,SAAS;EACT,MAAM,oBAAoB,UAAU,IAAI;EACxC,WAAW,UAAU;CACvB,CAAC;CAEH,IAAI,CAAC,UAAU,gBAAgB,CAAC,UAAU,aACxC,MAAM,IAAI,MAAM,uDAAuD;CAEzE,OAAO,GAAG,uBAAuB,aAAa,SAAS;AACzD;AAEA,SAAgB,eAAe,OAA6C;CAC1E,OAAO,aAAa,OAAO,sBAAsB,iBAAiB;AACpE;AAEA,SAAgB,qBAAqB,WAAyC;CAC5E,IAAI,UAAU,MACZ,OAAO,GAAG,sBAAsB,aAAa;EAC3C,SAAS;EACT,MAAM,oBAAoB,UAAU,IAAI;EACxC,WAAW,UAAU;EACrB,UAAU,UAAU;CACtB,CAAC;CAEH,IAAI,CAAC,UAAU,gBAAgB,CAAC,UAAU,aACxC,MAAM,IAAI,MAAM,sDAAsD;CAExE,OAAO,GAAG,sBAAsB,aAAa,SAAS;AACxD;AAEA,SAAgB,qBAAqB,OAA4C;CAC/E,OAAO,aAAa,OAAO,qBAAqB,gBAAgB;AAClE;AAEA,SAAgB,4BAA4B,OAAmD;CAC7F,OAAO,aAAa,OAAO,6BAA6B,uBAAuB;AACjF;AAEA,SAAgB,iBAAiB,cAA6C;CAC5E,OAAO;EAAE,MAAM;EAAS,aAAa,GAAG,iCAAiC;CAAe;AAC1F;AAEA,SAAS,2BAA2B,YAAkD;CACpF,IAAI,WAAW,SAAS,WAAW,CAAC,WAAW,YAAY,WAAW,8BAA8B,GAAG,OAAO;CAC9G,OAAO,WAAW,YAAY,MAAM,EAAqC,KAAK;AAChF;AAEA,SAAS,aAAa,OAAwB;CAC5C,OAAO,OAAO,KAAK,KAAK,UAAU,KAAK,CAAC,CAAC,CAAC,SAAS,WAAW;AAChE;AAEA,SAAS,aAAgB,OAAe,QAAgB,OAAiD;CACvG,IAAI,CAAC,MAAM,WAAW,MAAM,GAAG,OAAO;CACtC,IAAI;EACF,MAAM,UAAU,KAAK,MAAM,OAAO,KAAK,MAAM,MAAM,OAAO,MAAM,GAAG,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC;EAChG,OAAO,MAAM,OAAO,IAAI,UAAU;CACpC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,oBAAoB,MAAsB;CACxD,OAAO,KAAK,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,OAAO,EAAE;AACpD;AAEA,SAAS,kBAAkB,OAAgD;CACzE,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO;CACxE,MAAM,MAAM;CACZ,IAAI,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,WAAW,GAAG,OAAO;CAC5E,MAAM,YAAY,IAAI,YAAY,KAAK,OAAO,IAAI,SAAS,YAAY,oBAAoB,IAAI,IAAI,CAAC,CAAC,SAAS;CAC9G,MAAM,SACJ,OAAO,IAAI,iBAAiB,YAC5B,IAAI,aAAa,SAAS,KAC1B,OAAO,IAAI,gBAAgB,YAC3B,IAAI,YAAY,SAAS;CAC3B,OAAO,aAAa;AACtB;AAEA,SAAS,iBAAiB,OAA+C;CACvE,OACE,kBAAkB,KAAK,KACvB,OAAO,cAAe,MAA+B,QAAQ,KAC5D,MAA+B,WAAW;AAE/C;AAEA,SAAS,wBAAwB,OAAsD;CACrF,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO;CACxE,MAAM,MAAM;CACZ,OACE,IAAI,YAAY,KAChB,OAAO,IAAI,SAAS,YACpB,oBAAoB,IAAI,IAAI,CAAC,CAAC,SAAS,KACvC,OAAO,cAAc,IAAI,SAAS,KACjC,IAAI,YAAuB,KAC5B,OAAO,cAAc,IAAI,eAAe,KACvC,IAAI,kBAA6B;AAEtC;AAEA,SAAS,iBAAiB,QAAkC;CAC1D,OAAO,aAAa,MAAM;AAC5B;AAEA,SAAS,iBAAiB,OAAoD;CAC5E,IAAI,CAAC,OAAO,OAAO;EAAE,QAAQ;EAAG,MAAM;CAAE;CACxC,IAAI;EACF,MAAM,UAAU,KAAK,MAAM,OAAO,KAAK,OAAO,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC;EAC3E,IAAI,CAAC,OAAO,cAAc,QAAQ,MAAM,KAAK,OAAO,QAAQ,MAAM,IAAI,GAAG,OAAO;EAChF,IAAI,CAAC,OAAO,cAAc,QAAQ,IAAI,KAAK,OAAO,QAAQ,IAAI,IAAI,GAAG,OAAO;EAC5E,OAAO;GAAE,QAAQ,OAAO,QAAQ,MAAM;GAAG,MAAM,OAAO,QAAQ,IAAI;EAAE;CACtE,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,YAAY,MAAoF;CACvG,OAAO,MAAM,MAAM,KAAK,KAAK,MAAM,YAAY;AACjD;AAEA,SAAS,qBAAqB,OAA8B;CAC1D,IAAI,CAAC,QAAQ,KAAK,KAAK,GAAG,OAAO;CACjC,MAAM,SAAS,OAAO,KAAK;CAC3B,OAAO,OAAO,cAAc,MAAM,KAAK,SAAS,IAAI,SAAS;AAC/D;AAEA,SAAS,kBAAkB,OAIlB;CACP,MAAM,YAAY,MAAM,MAAM,eAAe;CAC7C,IAAI,WAAW;EACb,MAAM,WAAW,qBAAqB,UAAU,EAAG;EACnD,MAAM,cAAc,UAAU,EAAE,CAAE,QAAQ,cAAc,EAAE;EAC1D,OAAO,YAAY,cAAc;GAAE;GAAa;EAAS,IAAI;CAC/D;CACA,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,KAAK;EACzB,MAAM,QAAQ,IAAI,SAAS,MAAM,+BAA+B;EAChE,IAAI,CAAC,OAAO,OAAO;EACnB,MAAM,WAAW,qBAAqB,MAAM,EAAG;EAC/C,IAAI,CAAC,UAAU,OAAO;EACtB,MAAM,cAAc,mBAAmB,MAAM,EAAG;EAChD,OAAO;GAAE,MAAM,IAAI;GAAM;GAAa;EAAS;CACjD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,iBAAiB,OAA0D;CAClF,IAAI,MAAM,MAAM,SAAS,UAEvB,OAAO,MAAM,MAAM,cAAc,eAAe,MAAM,MAAM,cAAc,aAAa,UAAU;CAEnG,MAAM,OAAO,MAAM,MAAM,KAAK,KAAK,CAAC,CAAC,YAAY;CACjD,IAAI,SAAS,YAAY,SAAS,SAAS,OAAO;CAClD,IAAI,SAAS,YAAY,SAAS,UAAU,SAAS,UAAU,OAAO;CACtE,OAAO;AACT"}
1
+ {"version":3,"file":"integration.js","names":[],"sources":["../../../src/integrations/gitlab/integration.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport type { ApiRoute } from '@mastra/core/server';\nimport type { MastraWorker } from '@mastra/core/worker';\n\nimport type { IntegrationConnection } from '../../capabilities/connection.js';\nimport type {\n CreateIntakeCommentInput,\n CreatedIntakeComment,\n GetIntakeIssueInput,\n Intake,\n IntakeIssue,\n IntakeIssueDetail,\n IntakeItemPage,\n IntakeSource,\n ListIntakeIssuesInput,\n ListIntakeItemsInput,\n ResolveIntakeDispatchInput,\n ResolvedIntakeDispatch,\n UpdateIntakeIssueInput,\n} from '../../capabilities/intake.js';\nimport type { RouteAuth } from '../../routes/route.js';\nimport type { IntegrationStorageHandle } from '../../storage/domains/integrations/base.js';\nimport type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';\nimport type { SourceControlStorageHandle } from '../../storage/domains/source-control/base.js';\nimport type { FactoryIntegration, IntegrationContext, IntegrationTools } from '../base.js';\nimport { IssueReconcileWorker } from '../issue-reconcile-worker.js';\nimport { buildGitLabAgentTools } from './agent-tools.js';\nimport {\n GITLAB_ISSUES_PAGE_SIZE,\n GITLAB_NOTES_PAGE_SIZE,\n GITLAB_PROJECTS_PAGE_SIZE,\n GitLabApiClient,\n GitLabApiError,\n} from './api.js';\nimport type { GitLabIssue, GitLabNote, GitLabProject } from './api.js';\nimport { resolveGitLabRules } from './default-rules.js';\nimport type { GitLabEventRules, GitLabRuleOverrides } from './default-rules.js';\nimport { attachGitLabReconciler } from './reconciler.js';\nimport { gitlabReconciliationEnabled, gitlabReconciliationInterval } from './reconciliation-config.js';\nimport { buildGitLabRoutes, ingestLinkedGitLabRepositoryBacklog } from './routes.js';\nimport { attachGitLabRules } from './rules.js';\nimport {\n createGitLabSubscriptionTools,\n parseCreatedMergeRequest,\n subscribeCurrentSessionToMergeRequest,\n} from './session-subscriptions.js';\nimport type { GitLabSubscriptionStorage } from './subscriptions.js';\nimport { buildGitLabVersionControl } from './version-control.js';\n\ninterface GitLabConnectionContext {\n id: string;\n label: string | null;\n api: GitLabApiClient;\n connection: IntegrationConnection;\n host: string;\n webBaseUrl?: string;\n /** Resolves a fresh provider token for a single brokered git operation. */\n repositoryAccessToken?: () => Promise<string>;\n}\n\ninterface GitLabSourceReference {\n /** Present only on legacy v1 ids; authentication is not resource identity. */\n connectionId?: string;\n /** Canonical v2 ids use the GitLab instance host plus immutable project id. */\n host?: string;\n projectId: string;\n /** Legacy ids carry display metadata; v2 resolves it from GitLab. */\n projectPath?: string;\n}\n\ninterface ResolvedGitLabSourceReference extends GitLabSourceReference {\n connectionId: string;\n host: string;\n projectPath: string;\n}\n\ninterface GitLabIssueReference extends GitLabSourceReference {\n issueIid: number;\n}\n\nexport interface GitLabMergeRequestReference {\n version: 1;\n host: string;\n projectId: number;\n mergeRequestIid: number;\n}\n\ninterface GitLabPageCursor {\n source: number;\n page: number;\n}\n\nexport interface GitLabStatusConnection {\n id: string;\n integrationId: string;\n status: 'active' | 'needs_reauth';\n accountLabel: string | null;\n}\n\nconst DIRECT_CONNECTION_ID = 'direct';\nconst GITLAB_CONNECTION_TOKEN_PREFIX = 'gitlab-connection:';\nconst GITLAB_SOURCE_PREFIX = 'gitlab-project:';\nconst GITLAB_ISSUE_PREFIX = 'gitlab-issue:';\nconst GITLAB_MERGE_REQUEST_PREFIX = 'gitlab-pr:';\nexport const GITLAB_TRUSTED_ACCESS_LEVEL = 30;\n// Bound issue detail reads to 2,000 notes. GitLab does not expose truncation through the Intake contract.\nconst MAX_NOTES_PAGES = 20;\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport abstract class GitLabIntegrationBase implements FactoryIntegration {\n readonly id = 'gitlab';\n #projects: FactoryProjectsStorage | undefined;\n #sourceControl: SourceControlStorageHandle | undefined;\n #integrationStorage: GitLabSubscriptionStorage | undefined;\n #auth: RouteAuth | undefined;\n #ingestFactoryEvent: ReturnType<typeof attachGitLabRules>;\n readonly #orgIdByResourceId = new Map<string, string | null>();\n readonly rules: GitLabEventRules;\n\n constructor(rules?: GitLabRuleOverrides) {\n this.rules = resolveGitLabRules(rules);\n }\n\n readonly intake: Intake = {\n resolveIntakeDispatch: input => this.#resolveIntakeDispatch(input),\n listSources: () => this.#listSources(),\n listItems: input => this.#listItems(input),\n listIssues: input => this.#listIssues(input),\n getIssue: input => this.#getIssue(input),\n createComment: input => this.#createComment(input),\n updateIssue: input => this.#updateIssue(input),\n };\n readonly versionControl = buildGitLabVersionControl({\n contextForConnection: connection => this.#versionControlContext(connection),\n contextForStoredInstallation: (connection, host) => this.#versionControlContextForInstallation(connection, host),\n });\n initialize({\n storage,\n projects,\n auth,\n sourceControl,\n }: {\n storage?: IntegrationStorageHandle;\n projects: FactoryProjectsStorage;\n auth: RouteAuth;\n sourceControl?: SourceControlStorageHandle;\n }): void {\n this.#projects = projects;\n this.#auth = auth;\n this.#sourceControl = sourceControl;\n this.#integrationStorage = storage as GitLabSubscriptionStorage | undefined;\n }\n\n /** Generic integration persistence (merge-request subscriptions). */\n get integrationStorage(): GitLabSubscriptionStorage {\n if (!this.#integrationStorage) {\n throw new Error(`${this.constructor.name} is not initialized — the factory binds storage during prepare().`);\n }\n return this.#integrationStorage;\n }\n\n /** Source-control rows for this integration; absent when the host runs without them. */\n get sourceControlStorage(): SourceControlStorageHandle | undefined {\n return this.#sourceControl;\n }\n\n get authEnabled(): boolean {\n return this.#auth?.enabled() ?? false;\n }\n\n get projects(): FactoryProjectsStorage {\n if (!this.#projects) {\n throw new Error(`${this.constructor.name} is not initialized — the factory binds storage during prepare().`);\n }\n return this.#projects;\n }\n\n async resolveOrgId(resourceId: string): Promise<string | null> {\n const cached = this.#orgIdByResourceId.get(resourceId);\n if (cached !== undefined) return cached;\n if (!UUID_PATTERN.test(resourceId)) {\n this.#orgIdByResourceId.set(resourceId, null);\n return null;\n }\n try {\n await this.projects.ensureReady();\n const project = await this.projects.getById({ id: resourceId });\n const orgId = project?.orgId ?? null;\n this.#orgIdByResourceId.set(resourceId, orgId);\n return orgId;\n } catch {\n return null;\n }\n }\n\n clearCaches(): void {\n this.#orgIdByResourceId.clear();\n }\n\n abstract hasActiveConnections(): Promise<boolean>;\n abstract authFailureMessage(): string;\n protected abstract activeContexts(): Promise<GitLabConnectionContext[]>;\n protected abstract contextById(connectionId: string): Promise<GitLabConnectionContext>;\n\n /** Resolve only a GitLab repository linked to this Factory in this organization. */\n async getLinkedRepository(input: { orgId: string; factoryProjectId: string; projectRepositoryId: string }) {\n if (!this.#sourceControl) return null;\n const connections = await this.#sourceControl.connections.list({\n orgId: input.orgId,\n factoryProjectId: input.factoryProjectId,\n });\n for (const connection of connections) {\n if (connection.integrationId !== 'gitlab') continue;\n const links = await this.#sourceControl.projectRepositories.list({\n orgId: input.orgId,\n connectionId: connection.id,\n });\n const link = links.find(candidate => candidate.id === input.projectRepositoryId);\n if (!link) continue;\n const repository = await this.#sourceControl.repositories.get({ orgId: input.orgId, id: link.repositoryId });\n const installation = await this.#sourceControl.installations.get({\n orgId: input.orgId,\n id: connection.installationId,\n });\n if (!repository || !installation) return null;\n const host = installation.providerMetadata.host;\n if (typeof host !== 'string' || !host) return null;\n return { repository, host: normalizeGitLabHost(host) };\n }\n return null;\n }\n\n async getProjectMemberAccessLevel(\n connectionId: string,\n projectId: string,\n username: string,\n ): Promise<number | undefined> {\n const normalized = username.trim().toLowerCase();\n if (!normalized) return undefined;\n const members = await (await this.contextById(connectionId)).api.listProjectMembers(projectId, { query: username });\n const member = members.find(\n candidate => candidate.username.toLowerCase() === normalized && candidate.state !== 'blocked',\n );\n return member?.access_level;\n }\n\n async getWorkItemAuthorUsername(\n connectionId: string,\n projectId: string,\n kind: 'issue' | 'merge_request',\n iid: number,\n ): Promise<string | undefined> {\n const api = (await this.contextById(connectionId)).api;\n const item = kind === 'issue' ? await api.getIssue(projectId, iid) : await api.getMergeRequest(projectId, iid);\n return item.author?.username;\n }\n\n async isProjectMemberTrustedForSource(sourceId: string, username: string): Promise<boolean> {\n const reference = decodeSourceId(sourceId);\n if (!reference) throw new GitLabApiError('GitLab source identity is invalid.', 400);\n const { context, source } = await this.#resolveSourceReference(reference);\n const accessLevel = await this.getProjectMemberAccessLevel(context.id, source.projectId, username);\n return (accessLevel ?? 0) >= GITLAB_TRUSTED_ACCESS_LEVEL;\n }\n\n async getIssueForFactoryProject(input: {\n orgId: string;\n factoryProjectId: string;\n issueId: string;\n }): Promise<IntakeIssueDetail | null> {\n if (!this.#sourceControl) throw new GitLabApiError('GitLab source control is unavailable.', 503);\n const reference = decodeIssueReference(input.issueId);\n const locator = parseIssueLocator(input.issueId);\n if (!reference && !locator) {\n throw new GitLabApiError('GitLab issue must include a project and issue IID.', 400);\n }\n\n const normalizePath = (value: string) => value.replace(/^\\/+|\\/+$/g, '').toLowerCase();\n const matches: Array<{\n connectionId: string;\n projectId: string;\n projectPath: string;\n }> = [];\n const connections = await this.#sourceControl.connections.list({\n orgId: input.orgId,\n factoryProjectId: input.factoryProjectId,\n });\n for (const connection of connections) {\n const installation = await this.#sourceControl.installations.get({\n orgId: input.orgId,\n id: connection.installationId,\n });\n if (!installation) continue;\n for (const projectRepository of await this.#sourceControl.projectRepositories.list({\n orgId: input.orgId,\n connectionId: connection.id,\n })) {\n const repository = await this.#sourceControl.repositories.get({\n orgId: input.orgId,\n id: projectRepository.repositoryId,\n });\n if (!repository) continue;\n if (reference?.projectId && repository.externalId !== reference.projectId) continue;\n if (reference?.projectPath && normalizePath(repository.slug) !== normalizePath(reference.projectPath)) continue;\n if (locator?.projectPath && normalizePath(repository.slug) !== normalizePath(locator.projectPath)) continue;\n if (reference?.connectionId && installation.externalId !== reference.connectionId) continue;\n const installationHost =\n typeof installation.providerMetadata.host === 'string'\n ? normalizeGitLabHost(installation.providerMetadata.host)\n : null;\n if (reference?.host && installationHost !== normalizeGitLabHost(reference.host)) continue;\n if (locator?.host && installationHost !== normalizeGitLabHost(locator.host)) continue;\n matches.push({\n connectionId: installation.externalId,\n projectId: repository.externalId,\n projectPath: repository.slug,\n });\n }\n }\n const match = matches.sort((left, right) => left.connectionId.localeCompare(right.connectionId))[0];\n if (!match) throw new GitLabApiError('GitLab issue is outside the active Factory project.', 404);\n return this.intake.getIssue({\n connection: gitlabConnection(match.connectionId),\n sourceId: encodeSourceId(match),\n issueId: input.issueId,\n });\n }\n\n /** Platform mode exposes org connections; direct mode returns undefined. */\n async statusConnections(): Promise<GitLabStatusConnection[] | undefined> {\n return undefined;\n }\n\n /** Direct mode verifies its configured credential; Platform mode uses connection status. */\n async verifyStatus(): Promise<void> {\n // Platform connection state is authoritative unless a provider overrides this probe.\n }\n\n protected get webhookSecret(): string | undefined {\n return undefined;\n }\n\n workers(ctx: IntegrationContext): MastraWorker[] {\n if (!gitlabReconciliationEnabled()) return [];\n const reconcile = attachGitLabReconciler(this, ctx);\n if (!reconcile) return [];\n const intervalMs = gitlabReconciliationInterval();\n return [\n new IssueReconcileWorker({\n integrationId: this.id,\n reconcile,\n ...(intervalMs ? { intervalMs } : {}),\n }),\n ];\n }\n routes(ctx: IntegrationContext): ApiRoute[] {\n const ingestFactoryEvent = attachGitLabRules(this, ctx);\n this.#ingestFactoryEvent = ingestFactoryEvent;\n return buildGitLabRoutes({\n gitlab: this,\n auth: ctx.auth,\n intake: ctx.storage?.intake,\n emitAudit: ctx.hooks?.emitAudit,\n sandbox: ctx.sandbox,\n webhookSecret: this.webhookSecret,\n ingestFactoryEvent,\n ...(ctx.controller ? { controller: ctx.controller } : {}),\n });\n }\n\n async ingestLinkedRepositoryBacklog(args: { orgId: string; projectRepositoryId: string }): Promise<void> {\n await ingestLinkedGitLabRepositoryBacklog({ gitlab: this, ...args, ingestFactoryEvent: this.#ingestFactoryEvent });\n }\n\n async agentTools(args: { requestContext: RequestContext }): Promise<IntegrationTools> {\n return buildGitLabAgentTools({ requestContext: args.requestContext, gitlab: this });\n }\n\n sessionTools({ requestContext }: { requestContext: RequestContext }): IntegrationTools {\n return createGitLabSubscriptionTools(requestContext, this);\n }\n\n async postToolObserver({\n toolContext,\n requestContext,\n }: Parameters<NonNullable<FactoryIntegration['postToolObserver']>>[0]): Promise<void> {\n const mergeRequestUrl = parseCreatedMergeRequest(toolContext);\n if (!mergeRequestUrl || !requestContext) return;\n await subscribeCurrentSessionToMergeRequest(requestContext, mergeRequestUrl, 'auto-create-change-request', this);\n }\n\n abstract diagnostics(): Record<string, unknown>;\n\n /** Prefer the configured direct token over an older Platform installation on the same host. */\n async resolveActiveConnectionForHost(storedConnectionId: string, host: string): Promise<string> {\n if (this.diagnostics().mode !== 'direct') return storedConnectionId;\n const [direct] = await this.activeContexts();\n return direct && normalizeGitLabHost(direct.host) === normalizeGitLabHost(host) ? direct.id : storedConnectionId;\n }\n\n async #versionControlContext(connection: IntegrationConnection): Promise<GitLabConnectionContext> {\n const connectionId = connectionIdFromConnection(connection);\n if (connectionId) return this.contextById(connectionId);\n const contexts = await this.activeContexts();\n if (contexts.length !== 1) {\n throw new GitLabApiError(\n 'GitLab version-control requests must identify a connection when multiple GitLab accounts are connected.',\n 400,\n );\n }\n return contexts[0]!;\n }\n async #versionControlContextForInstallation(\n connection: IntegrationConnection,\n host: string | undefined,\n ): Promise<GitLabConnectionContext> {\n // A direct PAT intentionally overrides Platform credentials. Old links can\n // retain their Platform connection id; use the PAT only for the same host.\n if (this.diagnostics().mode === 'direct' && host) {\n const [direct] = await this.activeContexts();\n if (direct && normalizeGitLabHost(host) === normalizeGitLabHost(direct.host)) return direct;\n }\n return this.#versionControlContext(connection);\n }\n async #contextForReference(reference: GitLabSourceReference): Promise<GitLabConnectionContext> {\n if (reference.connectionId) return this.contextById(reference.connectionId);\n const contexts = (await this.activeContexts()).filter(\n context => !reference.host || normalizeGitLabHost(context.host) === normalizeGitLabHost(reference.host),\n );\n if (contexts.length === 0) {\n throw new GitLabApiError('No active GitLab connection can access this source.', 401);\n }\n if (contexts.length === 1) return contexts[0]!;\n\n if (this.#sourceControl) {\n const linkedConnectionIds = new Set(\n (await this.#sourceControl.projectRepositories.listConfiguredExternalKeys())\n .filter(key => key.repositoryExternalId === reference.projectId)\n .map(key => key.installationExternalId),\n );\n const linked = contexts.filter(context => linkedConnectionIds.has(context.id));\n if (linked.length > 0) return linked.sort((left, right) => left.id.localeCompare(right.id))[0]!;\n }\n\n for (const context of contexts.sort((left, right) => left.id.localeCompare(right.id))) {\n try {\n await context.api.getProject(reference.projectId);\n return context;\n } catch (error) {\n if (!(error instanceof GitLabApiError) || ![401, 403, 404].includes(error.status ?? 0)) throw error;\n // This credential cannot access the project; try another active account for the same canonical source.\n }\n }\n throw new GitLabApiError('No active GitLab connection can access this source.', 404);\n }\n\n async #resolveSourceReference(\n reference: GitLabSourceReference,\n ): Promise<{ context: GitLabConnectionContext; source: ResolvedGitLabSourceReference }> {\n const context = await this.#contextForReference(reference);\n const projectPath =\n reference.projectPath ?? (await context.api.getProject(reference.projectId)).path_with_namespace;\n return {\n context,\n source: {\n connectionId: context.id,\n host: normalizeGitLabHost(reference.host ?? context.host),\n projectId: reference.projectId,\n projectPath,\n },\n };\n }\n\n async #resolveIntakeDispatch({ externalSource }: ResolveIntakeDispatchInput): Promise<ResolvedIntakeDispatch | null> {\n if (externalSource.type !== 'issue') return null;\n const reference = decodeIssueReference(externalSource.externalId);\n if (!reference) return null;\n const { context, source } = await this.#resolveSourceReference(reference);\n return {\n connection: context.connection,\n sourceId: encodeSourceId(source),\n issueId: String(reference.issueIid),\n };\n }\n\n async #listSources(): Promise<IntakeSource[]> {\n const sources = new Map<string, IntakeSource>();\n for (const context of await this.activeContexts()) {\n for (let page = 1; ; page++) {\n const projects = await context.api.listProjects({ page });\n for (const project of projects) {\n const source = this.#toIntakeSource(context, project);\n if (!sources.has(source.id)) sources.set(source.id, source);\n }\n if (projects.length < GITLAB_PROJECTS_PAGE_SIZE) break;\n }\n }\n return [...sources.values()];\n }\n\n async #listItems(input: ListIntakeItemsInput): Promise<IntakeItemPage> {\n const result = await this.#listIssuePage(input.sourceIds, input.cursor);\n return {\n items: result.issues.map(({ issue, source, context }) => ({\n source: {\n type: 'issue',\n externalId: encodeIssueReference({ ...source, issueIid: issue.iid }),\n url: issue.web_url,\n },\n sourceId: encodeSourceId(source),\n title: `${source.projectPath}#${issue.iid}: ${issue.title}`,\n status: issue.state,\n labels: issue.labels ?? [],\n assignee: displayName(issue.assignee),\n createdAt: issue.created_at,\n updatedAt: issue.updated_at,\n metadata: {\n identifier: `${source.projectPath}#${issue.iid}`,\n projectId: source.projectId,\n projectPath: source.projectPath,\n connectionId: context.id,\n accountLabel: context.label,\n labelColors: Object.fromEntries((issue.labelDetails ?? []).map(label => [label.name, label.color])),\n },\n })),\n nextCursor: result.nextCursor,\n };\n }\n\n async #listIssues(input: ListIntakeIssuesInput) {\n const result = await this.#listIssuePage(input.sourceIds, input.cursor, input.labels);\n return {\n issues: result.issues.map(({ issue, source }) => ({\n ...this.#toIntakeIssue(issue, source.projectPath),\n sourceId: encodeSourceId(source),\n })),\n nextCursor: result.nextCursor,\n };\n }\n\n async #listIssuePage(sourceIds: string[], cursor?: string, labels?: string[]) {\n const sources = sourceIds.map(decodeSourceId).filter((source): source is GitLabSourceReference => source !== null);\n if (sources.length === 0) return { issues: [], nextCursor: null };\n const current = decodePageCursor(cursor);\n if (!current || current.source >= sources.length) return { issues: [], nextCursor: null };\n\n for (let sourceIndex = current.source; sourceIndex < sources.length; sourceIndex++) {\n const { source, context } = await this.#resolveSourceReference(sources[sourceIndex]!);\n const page = sourceIndex === current.source ? current.page : 1;\n const issues = await context.api.listIssues(source.projectId, { page, labels });\n const nextCursor =\n issues.length === GITLAB_ISSUES_PAGE_SIZE\n ? encodePageCursor({ source: sourceIndex, page: page + 1 })\n : sourceIndex + 1 < sources.length\n ? encodePageCursor({ source: sourceIndex + 1, page: 1 })\n : null;\n return { issues: issues.map(issue => ({ issue, source, context })), nextCursor };\n }\n return { issues: [], nextCursor: null };\n }\n\n async #getIssue(input: GetIntakeIssueInput): Promise<IntakeIssueDetail | null> {\n const resolved = await this.#resolveRequest(input);\n let issue: GitLabIssue;\n try {\n issue = await resolved.context.api.getIssue(resolved.projectId, resolved.issueIid);\n } catch (error) {\n if (error instanceof GitLabApiError && error.status === 404) return null;\n throw error;\n }\n const notes = await this.#listAllNotes(resolved.context.api, resolved.projectId, resolved.issueIid);\n return {\n ...this.#toIntakeIssue(issue, resolved.projectPath),\n description: issue.description?.trim() || null,\n comments: notes\n .filter(note => !note.system)\n .map(note => ({ author: displayName(note.author), body: note.body, createdAt: note.created_at })),\n };\n }\n\n async #listAllNotes(api: GitLabApiClient, projectId: string, issueIid: number): Promise<GitLabNote[]> {\n const notes: GitLabNote[] = [];\n for (let page = 1; page <= MAX_NOTES_PAGES; page++) {\n const result = await api.listNotes(projectId, issueIid, { page });\n notes.push(...result);\n if (result.length < GITLAB_NOTES_PAGE_SIZE) break;\n }\n return notes;\n }\n\n async #createComment(input: CreateIntakeCommentInput): Promise<CreatedIntakeComment | null> {\n const resolved = await this.#resolveRequest(input);\n try {\n const issue = await resolved.context.api.getIssue(resolved.projectId, resolved.issueIid);\n const note = await resolved.context.api.createNote(resolved.projectId, resolved.issueIid, input.body);\n return { id: String(note.id), url: `${issue.web_url}#note_${note.id}` };\n } catch (error) {\n if (error instanceof GitLabApiError && error.status === 404) return null;\n throw error;\n }\n }\n\n async #updateIssue(input: UpdateIntakeIssueInput): Promise<IntakeIssue | null> {\n const resolved = await this.#resolveRequest(input);\n let issue: GitLabIssue;\n try {\n issue = await resolved.context.api.getIssue(resolved.projectId, resolved.issueIid);\n } catch (error) {\n if (error instanceof GitLabApiError && error.status === 404) return null;\n throw error;\n }\n const stateEvent = targetStateEvent(input);\n if (!stateEvent) return null;\n if ((stateEvent === 'close' && issue.state === 'closed') || (stateEvent === 'reopen' && issue.state === 'opened')) {\n return this.#toIntakeIssue(issue, resolved.projectPath);\n }\n const updated = await resolved.context.api.updateIssueState(resolved.projectId, resolved.issueIid, stateEvent);\n return this.#toIntakeIssue(updated, resolved.projectPath);\n }\n\n async #resolveRequest(input: GetIntakeIssueInput): Promise<{\n context: GitLabConnectionContext;\n projectId: string;\n projectPath: string;\n issueIid: number;\n }> {\n const issueReference = decodeIssueReference(input.issueId);\n const source = input.sourceId ? decodeSourceId(input.sourceId) : null;\n const locator = parseIssueLocator(input.issueId);\n const reference = issueReference ?? source;\n let context: GitLabConnectionContext;\n if (reference) {\n context = await this.#contextForReference(reference);\n } else {\n const connectionId = connectionIdFromConnection(input.connection);\n const contexts = connectionId ? [await this.contextById(connectionId)] : await this.activeContexts();\n if (contexts.length !== 1) {\n throw new GitLabApiError('GitLab issue reference must resolve to exactly one active connection.', 400);\n }\n context = contexts[0]!;\n }\n const projectId = issueReference?.projectId ?? source?.projectId ?? locator?.projectPath;\n const issueIid = issueReference?.issueIid ?? locator?.issueIid ?? parsePositiveInteger(input.issueId);\n if (!projectId || !issueIid) {\n throw new GitLabApiError(\n 'GitLab issue must include a project and issue IID (for example, group/project#42).',\n 400,\n );\n }\n const projectPath =\n issueReference?.projectPath ??\n source?.projectPath ??\n locator?.projectPath ??\n (await context.api.getProject(projectId)).path_with_namespace;\n return { context, projectId, projectPath, issueIid };\n }\n\n #toIntakeSource(context: GitLabConnectionContext, project: GitLabProject): IntakeSource {\n const reference: GitLabSourceReference = {\n host: normalizeGitLabHost(context.host),\n projectId: String(project.id),\n projectPath: project.path_with_namespace,\n };\n return {\n id: encodeSourceId(reference),\n name: project.path_with_namespace,\n type: 'project',\n metadata: {\n projectId: String(project.id),\n projectPath: project.path_with_namespace,\n defaultBranch: project.default_branch ?? null,\n connectionId: context.id,\n accountLabel: context.label,\n url: project.web_url,\n },\n };\n }\n\n #toIntakeIssue(issue: GitLabIssue, projectPath: string): IntakeIssue {\n const assignees = issue.assignees?.map(displayName).filter((name): name is string => name !== null) ?? [];\n return {\n id: String(issue.iid),\n identifier: `${projectPath}#${issue.iid}`,\n title: issue.title,\n url: issue.web_url,\n author: displayName(issue.author),\n authorUsername: issue.author?.username ?? null,\n state: issue.state,\n stateType: issue.state === 'closed' ? 'completed' : 'unstarted',\n priority: typeof issue.weight === 'number' ? String(issue.weight) : null,\n assignee: displayName(issue.assignee) ?? assignees[0] ?? null,\n assignees,\n source: projectPath,\n labels: issue.labels ?? [],\n labelColors: Object.fromEntries((issue.labelDetails ?? []).map(label => [label.name, label.color])),\n commentCount: issue.user_notes_count ?? null,\n createdAt: issue.created_at,\n updatedAt: issue.updated_at,\n };\n }\n}\n\nexport type GitLabAccessTokenType = 'personal' | 'group';\n\nexport interface GitLabIntegrationConfig {\n rules?: GitLabRuleOverrides;\n accessToken?: string;\n /** Defaults to `personal`; both token types authenticate identically but have different resource reach. */\n accessTokenType?: GitLabAccessTokenType;\n baseUrl?: string;\n webhookSecret?: string;\n fetchImpl?: typeof fetch;\n}\n\nconst DIRECT_CONNECTION_TOKEN = 'gitlab-direct-access-token';\n\nexport class GitLabIntegration extends GitLabIntegrationBase {\n readonly #accessToken: string;\n readonly #accessTokenType: GitLabAccessTokenType;\n readonly #baseUrl: string;\n readonly #webhookSecret: string | undefined;\n readonly #context: GitLabConnectionContext;\n\n constructor(config: GitLabIntegrationConfig = {}) {\n super(config.rules);\n const accessToken = config.accessToken?.trim() || process.env.GITLAB_ACCESS_TOKEN?.trim();\n if (!accessToken) {\n throw new Error('GitLabIntegration: missing required GITLAB_ACCESS_TOKEN.');\n }\n this.#accessToken = accessToken;\n this.#accessTokenType = parseAccessTokenType(\n config.accessTokenType ?? process.env.GITLAB_ACCESS_TOKEN_TYPE?.trim(),\n );\n this.#baseUrl = (config.baseUrl ?? process.env.GITLAB_BASE_URL?.trim() ?? 'https://gitlab.com').replace(/\\/+$/, '');\n this.#webhookSecret = config.webhookSecret?.trim() || process.env.GITLAB_WEBHOOK_SECRET?.trim() || undefined;\n const api = new GitLabApiClient({\n baseUrl: this.#baseUrl,\n accessToken: this.#accessToken,\n ...(config.fetchImpl ? { fetchImpl: config.fetchImpl } : {}),\n });\n this.#context = {\n id: DIRECT_CONNECTION_ID,\n label: new URL(this.#baseUrl).host,\n api,\n connection: { type: 'oauth', accessToken: DIRECT_CONNECTION_TOKEN },\n host: new URL(this.#baseUrl).host,\n webBaseUrl: this.#baseUrl,\n repositoryAccessToken: async () => this.#accessToken,\n };\n }\n\n protected override get webhookSecret(): string | undefined {\n return this.#webhookSecret;\n }\n\n async hasActiveConnections(): Promise<boolean> {\n return true;\n }\n\n override async verifyStatus(): Promise<void> {\n await this.#context.api.getCurrentUser();\n }\n\n authFailureMessage(): string {\n return `GitLab rejected the configured ${this.#accessTokenType} access token. Check the token and its scopes.`;\n }\n\n protected async activeContexts(): Promise<GitLabConnectionContext[]> {\n return [this.#context];\n }\n\n protected async contextById(connectionId: string): Promise<GitLabConnectionContext> {\n if (connectionId !== DIRECT_CONNECTION_ID) {\n throw new GitLabApiError('GitLab connection is unavailable.', 401);\n }\n return this.#context;\n }\n\n diagnostics(): Record<string, unknown> {\n return {\n configured: true,\n mode: 'direct',\n accessTokenType: this.#accessTokenType,\n endpointHost: new URL(this.#baseUrl).host,\n webhookConfigured: Boolean(this.#webhookSecret),\n };\n }\n}\n\nfunction parseAccessTokenType(value: string | undefined): GitLabAccessTokenType {\n const normalized = value?.trim().toLowerCase() || 'personal';\n if (normalized === 'personal' || normalized === 'group') return normalized;\n throw new Error(\"GitLabIntegration: GITLAB_ACCESS_TOKEN_TYPE must be 'personal' or 'group'.\");\n}\n\nexport function encodeSourceId(reference: GitLabSourceReference): string {\n if (reference.host) {\n return `${GITLAB_SOURCE_PREFIX}${encodeOpaque({\n version: 2,\n host: normalizeGitLabHost(reference.host),\n projectId: reference.projectId,\n })}`;\n }\n if (!reference.connectionId || !reference.projectPath) {\n throw new Error('GitLab source reference is missing its instance host.');\n }\n return `${GITLAB_SOURCE_PREFIX}${encodeOpaque(reference)}`;\n}\n\nexport function decodeSourceId(value: string): GitLabSourceReference | null {\n return decodeOpaque(value, GITLAB_SOURCE_PREFIX, isSourceReference);\n}\n\nexport function encodeIssueReference(reference: GitLabIssueReference): string {\n if (reference.host) {\n return `${GITLAB_ISSUE_PREFIX}${encodeOpaque({\n version: 2,\n host: normalizeGitLabHost(reference.host),\n projectId: reference.projectId,\n issueIid: reference.issueIid,\n })}`;\n }\n if (!reference.connectionId || !reference.projectPath) {\n throw new Error('GitLab issue reference is missing its instance host.');\n }\n return `${GITLAB_ISSUE_PREFIX}${encodeOpaque(reference)}`;\n}\n\nexport function decodeIssueReference(value: string): GitLabIssueReference | null {\n return decodeOpaque(value, GITLAB_ISSUE_PREFIX, isIssueReference);\n}\n\nexport function decodeMergeRequestReference(value: string): GitLabMergeRequestReference | null {\n return decodeOpaque(value, GITLAB_MERGE_REQUEST_PREFIX, isMergeRequestReference);\n}\n\nexport function gitlabConnection(connectionId: string): IntegrationConnection {\n return { type: 'oauth', accessToken: `${GITLAB_CONNECTION_TOKEN_PREFIX}${connectionId}` };\n}\n\nfunction connectionIdFromConnection(connection: IntegrationConnection): string | null {\n if (connection.type !== 'oauth' || !connection.accessToken.startsWith(GITLAB_CONNECTION_TOKEN_PREFIX)) return null;\n return connection.accessToken.slice(GITLAB_CONNECTION_TOKEN_PREFIX.length) || null;\n}\n\nfunction encodeOpaque(value: unknown): string {\n return Buffer.from(JSON.stringify(value)).toString('base64url');\n}\n\nfunction decodeOpaque<T>(value: string, prefix: string, guard: (value: unknown) => value is T): T | null {\n if (!value.startsWith(prefix)) return null;\n try {\n const decoded = JSON.parse(Buffer.from(value.slice(prefix.length), 'base64url').toString('utf8')) as unknown;\n return guard(decoded) ? decoded : null;\n } catch {\n return null;\n }\n}\n\nexport function normalizeGitLabHost(host: string): string {\n return host.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction isSourceReference(value: unknown): value is GitLabSourceReference {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const ref = value as Record<string, unknown>;\n if (typeof ref.projectId !== 'string' || ref.projectId.length === 0) return false;\n const canonical = ref.version === 2 && typeof ref.host === 'string' && normalizeGitLabHost(ref.host).length > 0;\n const legacy =\n typeof ref.connectionId === 'string' &&\n ref.connectionId.length > 0 &&\n typeof ref.projectPath === 'string' &&\n ref.projectPath.length > 0;\n return canonical || legacy;\n}\n\nfunction isIssueReference(value: unknown): value is GitLabIssueReference {\n return (\n isSourceReference(value) &&\n Number.isSafeInteger((value as GitLabIssueReference).issueIid) &&\n (value as GitLabIssueReference).issueIid > 0\n );\n}\n\nfunction isMergeRequestReference(value: unknown): value is GitLabMergeRequestReference {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const ref = value as Record<string, unknown>;\n return (\n ref.version === 1 &&\n typeof ref.host === 'string' &&\n normalizeGitLabHost(ref.host).length > 0 &&\n Number.isSafeInteger(ref.projectId) &&\n (ref.projectId as number) > 0 &&\n Number.isSafeInteger(ref.mergeRequestIid) &&\n (ref.mergeRequestIid as number) > 0\n );\n}\n\nfunction encodePageCursor(cursor: GitLabPageCursor): string {\n return encodeOpaque(cursor);\n}\n\nfunction decodePageCursor(value: string | undefined): GitLabPageCursor | null {\n if (!value) return { source: 0, page: 1 };\n try {\n const decoded = JSON.parse(Buffer.from(value, 'base64url').toString('utf8')) as Record<string, unknown>;\n if (!Number.isSafeInteger(decoded.source) || Number(decoded.source) < 0) return null;\n if (!Number.isSafeInteger(decoded.page) || Number(decoded.page) < 1) return null;\n return { source: Number(decoded.source), page: Number(decoded.page) };\n } catch {\n return null;\n }\n}\n\nfunction displayName(user: { name?: string | null; username: string } | null | undefined): string | null {\n return user?.name?.trim() || user?.username || null;\n}\n\nfunction parsePositiveInteger(value: string): number | null {\n if (!/^\\d+$/.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction parseIssueLocator(value: string): {\n host?: string;\n projectPath: string;\n issueIid: number;\n} | null {\n const shorthand = value.match(/^(.+?)#(\\d+)$/);\n if (shorthand) {\n const issueIid = parsePositiveInteger(shorthand[2]!);\n const projectPath = shorthand[1]!.replace(/^\\/+|\\/+$/g, '');\n return issueIid && projectPath ? { projectPath, issueIid } : null;\n }\n try {\n const url = new URL(value);\n const match = url.pathname.match(/^\\/(.+)\\/-\\/issues\\/(\\d+)\\/?$/);\n if (!match) return null;\n const issueIid = parsePositiveInteger(match[2]!);\n if (!issueIid) return null;\n const projectPath = decodeURIComponent(match[1]!);\n return { host: url.host, projectPath, issueIid };\n } catch {\n return null;\n }\n}\n\nfunction targetStateEvent(input: UpdateIntakeIssueInput): 'close' | 'reopen' | null {\n if (input.state.kind === 'byType') {\n // GitLab issues have only opened/closed states, so canceled is intentionally mapped to close.\n return input.state.stateType === 'completed' || input.state.stateType === 'canceled' ? 'close' : 'reopen';\n }\n const name = input.state.name.trim().toLowerCase();\n if (name === 'closed' || name === 'close') return 'close';\n if (name === 'opened' || name === 'open' || name === 'reopen') return 'reopen';\n return null;\n}\n"],"mappings":";;;;;;;;;;;AAmGA,MAAM,uBAAuB;AAC7B,MAAM,iCAAiC;AACvC,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAC5B,MAAM,8BAA8B;AACpC,MAAa,8BAA8B;AAE3C,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAErB,IAAsB,wBAAtB,MAA0E;CACxE,KAAc;CACd;CACA;CACA;CACA;CACA;CACA,qCAA8B,IAAI,IAA2B;CAC7D;CAEA,YAAY,OAA6B;EACvC,KAAK,QAAQ,mBAAmB,KAAK;CACvC;CAEA,SAA0B;EACxB,wBAAuB,UAAS,KAAK,uBAAuB,KAAK;EACjE,mBAAmB,KAAK,aAAa;EACrC,YAAW,UAAS,KAAK,WAAW,KAAK;EACzC,aAAY,UAAS,KAAK,YAAY,KAAK;EAC3C,WAAU,UAAS,KAAK,UAAU,KAAK;EACvC,gBAAe,UAAS,KAAK,eAAe,KAAK;EACjD,cAAa,UAAS,KAAK,aAAa,KAAK;CAC/C;CACA,iBAA0B,0BAA0B;EAClD,uBAAsB,eAAc,KAAK,uBAAuB,UAAU;EAC1E,+BAA+B,YAAY,SAAS,KAAK,sCAAsC,YAAY,IAAI;CACjH,CAAC;CACD,WAAW,EACT,SACA,UACA,MACA,iBAMO;EACP,KAAK,YAAY;EACjB,KAAK,QAAQ;EACb,KAAK,iBAAiB;EACtB,KAAK,sBAAsB;CAC7B;;CAGA,IAAI,qBAAgD;EAClD,IAAI,CAAC,KAAK,qBACR,MAAM,IAAI,MAAM,GAAG,KAAK,YAAY,KAAK,kEAAkE;EAE7G,OAAO,KAAK;CACd;;CAGA,IAAI,uBAA+D;EACjE,OAAO,KAAK;CACd;CAEA,IAAI,cAAuB;EACzB,OAAO,KAAK,OAAO,QAAQ,KAAK;CAClC;CAEA,IAAI,WAAmC;EACrC,IAAI,CAAC,KAAK,WACR,MAAM,IAAI,MAAM,GAAG,KAAK,YAAY,KAAK,kEAAkE;EAE7G,OAAO,KAAK;CACd;CAEA,MAAM,aAAa,YAA4C;EAC7D,MAAM,SAAS,KAAK,mBAAmB,IAAI,UAAU;EACrD,IAAI,WAAW,KAAA,GAAW,OAAO;EACjC,IAAI,CAAC,aAAa,KAAK,UAAU,GAAG;GAClC,KAAK,mBAAmB,IAAI,YAAY,IAAI;GAC5C,OAAO;EACT;EACA,IAAI;GACF,MAAM,KAAK,SAAS,YAAY;GAEhC,MAAM,SAAQ,MADQ,KAAK,SAAS,QAAQ,EAAE,IAAI,WAAW,CAAC,EAAA,EACvC,SAAS;GAChC,KAAK,mBAAmB,IAAI,YAAY,KAAK;GAC7C,OAAO;EACT,QAAQ;GACN,OAAO;EACT;CACF;CAEA,cAAoB;EAClB,KAAK,mBAAmB,MAAM;CAChC;;CAQA,MAAM,oBAAoB,OAAiF;EACzG,IAAI,CAAC,KAAK,gBAAgB,OAAO;EACjC,MAAM,cAAc,MAAM,KAAK,eAAe,YAAY,KAAK;GAC7D,OAAO,MAAM;GACb,kBAAkB,MAAM;EAC1B,CAAC;EACD,KAAK,MAAM,cAAc,aAAa;GACpC,IAAI,WAAW,kBAAkB,UAAU;GAK3C,MAAM,QAAO,MAJO,KAAK,eAAe,oBAAoB,KAAK;IAC/D,OAAO,MAAM;IACb,cAAc,WAAW;GAC3B,CAAC,EAAA,CACkB,MAAK,cAAa,UAAU,OAAO,MAAM,mBAAmB;GAC/E,IAAI,CAAC,MAAM;GACX,MAAM,aAAa,MAAM,KAAK,eAAe,aAAa,IAAI;IAAE,OAAO,MAAM;IAAO,IAAI,KAAK;GAAa,CAAC;GAC3G,MAAM,eAAe,MAAM,KAAK,eAAe,cAAc,IAAI;IAC/D,OAAO,MAAM;IACb,IAAI,WAAW;GACjB,CAAC;GACD,IAAI,CAAC,cAAc,CAAC,cAAc,OAAO;GACzC,MAAM,OAAO,aAAa,iBAAiB;GAC3C,IAAI,OAAO,SAAS,YAAY,CAAC,MAAM,OAAO;GAC9C,OAAO;IAAE;IAAY,MAAM,oBAAoB,IAAI;GAAE;EACvD;EACA,OAAO;CACT;CAEA,MAAM,4BACJ,cACA,WACA,UAC6B;EAC7B,MAAM,aAAa,SAAS,KAAK,CAAC,CAAC,YAAY;EAC/C,IAAI,CAAC,YAAY,OAAO,KAAA;EAKxB,QAHe,OADQ,MAAM,KAAK,YAAY,YAAY,EAAA,CAAG,IAAI,mBAAmB,WAAW,EAAE,OAAO,SAAS,CAAC,EAAA,CAC3F,MACrB,cAAa,UAAU,SAAS,YAAY,MAAM,cAAc,UAAU,UAAU,SAE1E,CAAC,EAAE;CACjB;CAEA,MAAM,0BACJ,cACA,WACA,MACA,KAC6B;EAC7B,MAAM,OAAO,MAAM,KAAK,YAAY,YAAY,EAAA,CAAG;EAEnD,QADa,SAAS,UAAU,MAAM,IAAI,SAAS,WAAW,GAAG,IAAI,MAAM,IAAI,gBAAgB,WAAW,GAAG,EAAA,CACjG,QAAQ;CACtB;CAEA,MAAM,gCAAgC,UAAkB,UAAoC;EAC1F,MAAM,YAAY,eAAe,QAAQ;EACzC,IAAI,CAAC,WAAW,MAAM,IAAI,eAAe,sCAAsC,GAAG;EAClF,MAAM,EAAE,SAAS,WAAW,MAAM,KAAK,wBAAwB,SAAS;EAExE,QAAQ,MADkB,KAAK,4BAA4B,QAAQ,IAAI,OAAO,WAAW,QAAQ,KAC1E,MAAA;CACzB;CAEA,MAAM,0BAA0B,OAIM;EACpC,IAAI,CAAC,KAAK,gBAAgB,MAAM,IAAI,eAAe,yCAAyC,GAAG;EAC/F,MAAM,YAAY,qBAAqB,MAAM,OAAO;EACpD,MAAM,UAAU,kBAAkB,MAAM,OAAO;EAC/C,IAAI,CAAC,aAAa,CAAC,SACjB,MAAM,IAAI,eAAe,sDAAsD,GAAG;EAGpF,MAAM,iBAAiB,UAAkB,MAAM,QAAQ,cAAc,EAAE,CAAC,CAAC,YAAY;EACrF,MAAM,UAID,CAAC;EACN,MAAM,cAAc,MAAM,KAAK,eAAe,YAAY,KAAK;GAC7D,OAAO,MAAM;GACb,kBAAkB,MAAM;EAC1B,CAAC;EACD,KAAK,MAAM,cAAc,aAAa;GACpC,MAAM,eAAe,MAAM,KAAK,eAAe,cAAc,IAAI;IAC/D,OAAO,MAAM;IACb,IAAI,WAAW;GACjB,CAAC;GACD,IAAI,CAAC,cAAc;GACnB,KAAK,MAAM,qBAAqB,MAAM,KAAK,eAAe,oBAAoB,KAAK;IACjF,OAAO,MAAM;IACb,cAAc,WAAW;GAC3B,CAAC,GAAG;IACF,MAAM,aAAa,MAAM,KAAK,eAAe,aAAa,IAAI;KAC5D,OAAO,MAAM;KACb,IAAI,kBAAkB;IACxB,CAAC;IACD,IAAI,CAAC,YAAY;IACjB,IAAI,WAAW,aAAa,WAAW,eAAe,UAAU,WAAW;IAC3E,IAAI,WAAW,eAAe,cAAc,WAAW,IAAI,MAAM,cAAc,UAAU,WAAW,GAAG;IACvG,IAAI,SAAS,eAAe,cAAc,WAAW,IAAI,MAAM,cAAc,QAAQ,WAAW,GAAG;IACnG,IAAI,WAAW,gBAAgB,aAAa,eAAe,UAAU,cAAc;IACnF,MAAM,mBACJ,OAAO,aAAa,iBAAiB,SAAS,WAC1C,oBAAoB,aAAa,iBAAiB,IAAI,IACtD;IACN,IAAI,WAAW,QAAQ,qBAAqB,oBAAoB,UAAU,IAAI,GAAG;IACjF,IAAI,SAAS,QAAQ,qBAAqB,oBAAoB,QAAQ,IAAI,GAAG;IAC7E,QAAQ,KAAK;KACX,cAAc,aAAa;KAC3B,WAAW,WAAW;KACtB,aAAa,WAAW;IAC1B,CAAC;GACH;EACF;EACA,MAAM,QAAQ,QAAQ,MAAM,MAAM,UAAU,KAAK,aAAa,cAAc,MAAM,YAAY,CAAC,CAAC,CAAC;EACjG,IAAI,CAAC,OAAO,MAAM,IAAI,eAAe,uDAAuD,GAAG;EAC/F,OAAO,KAAK,OAAO,SAAS;GAC1B,YAAY,iBAAiB,MAAM,YAAY;GAC/C,UAAU,eAAe,KAAK;GAC9B,SAAS,MAAM;EACjB,CAAC;CACH;;CAGA,MAAM,oBAAmE,CAEzE;;CAGA,MAAM,eAA8B,CAEpC;CAEA,IAAc,gBAAoC,CAElD;CAEA,QAAQ,KAAyC;EAC/C,IAAI,CAAC,4BAA4B,GAAG,OAAO,CAAC;EAC5C,MAAM,YAAY,uBAAuB,MAAM,GAAG;EAClD,IAAI,CAAC,WAAW,OAAO,CAAC;EACxB,MAAM,aAAa,6BAA6B;EAChD,OAAO,CACL,IAAI,qBAAqB;GACvB,eAAe,KAAK;GACpB;GACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;EACrC,CAAC,CACH;CACF;CACA,OAAO,KAAqC;EAC1C,MAAM,qBAAqB,kBAAkB,MAAM,GAAG;EACtD,KAAK,sBAAsB;EAC3B,OAAO,kBAAkB;GACvB,QAAQ;GACR,MAAM,IAAI;GACV,QAAQ,IAAI,SAAS;GACrB,WAAW,IAAI,OAAO;GACtB,SAAS,IAAI;GACb,eAAe,KAAK;GACpB;GACA,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,WAAW,IAAI,CAAC;EACzD,CAAC;CACH;CAEA,MAAM,8BAA8B,MAAqE;EACvG,MAAM,oCAAoC;GAAE,QAAQ;GAAM,GAAG;GAAM,oBAAoB,KAAK;EAAoB,CAAC;CACnH;CAEA,MAAM,WAAW,MAAqE;EACpF,OAAO,sBAAsB;GAAE,gBAAgB,KAAK;GAAgB,QAAQ;EAAK,CAAC;CACpF;CAEA,aAAa,EAAE,kBAAwE;EACrF,OAAO,8BAA8B,gBAAgB,IAAI;CAC3D;CAEA,MAAM,iBAAiB,EACrB,aACA,kBACoF;EACpF,MAAM,kBAAkB,yBAAyB,WAAW;EAC5D,IAAI,CAAC,mBAAmB,CAAC,gBAAgB;EACzC,MAAM,sCAAsC,gBAAgB,iBAAiB,8BAA8B,IAAI;CACjH;;CAKA,MAAM,+BAA+B,oBAA4B,MAA+B;EAC9F,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,UAAU,OAAO;EACjD,MAAM,CAAC,UAAU,MAAM,KAAK,eAAe;EAC3C,OAAO,UAAU,oBAAoB,OAAO,IAAI,MAAM,oBAAoB,IAAI,IAAI,OAAO,KAAK;CAChG;CAEA,MAAM,uBAAuB,YAAqE;EAChG,MAAM,eAAe,2BAA2B,UAAU;EAC1D,IAAI,cAAc,OAAO,KAAK,YAAY,YAAY;EACtD,MAAM,WAAW,MAAM,KAAK,eAAe;EAC3C,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,eACR,2GACA,GACF;EAEF,OAAO,SAAS;CAClB;CACA,MAAM,sCACJ,YACA,MACkC;EAGlC,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,YAAY,MAAM;GAChD,MAAM,CAAC,UAAU,MAAM,KAAK,eAAe;GAC3C,IAAI,UAAU,oBAAoB,IAAI,MAAM,oBAAoB,OAAO,IAAI,GAAG,OAAO;EACvF;EACA,OAAO,KAAK,uBAAuB,UAAU;CAC/C;CACA,MAAM,qBAAqB,WAAoE;EAC7F,IAAI,UAAU,cAAc,OAAO,KAAK,YAAY,UAAU,YAAY;EAC1E,MAAM,YAAY,MAAM,KAAK,eAAe,EAAA,CAAG,QAC7C,YAAW,CAAC,UAAU,QAAQ,oBAAoB,QAAQ,IAAI,MAAM,oBAAoB,UAAU,IAAI,CACxG;EACA,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,eAAe,uDAAuD,GAAG;EAErF,IAAI,SAAS,WAAW,GAAG,OAAO,SAAS;EAE3C,IAAI,KAAK,gBAAgB;GACvB,MAAM,sBAAsB,IAAI,KAC7B,MAAM,KAAK,eAAe,oBAAoB,2BAA2B,EAAA,CACvE,QAAO,QAAO,IAAI,yBAAyB,UAAU,SAAS,CAAC,CAC/D,KAAI,QAAO,IAAI,sBAAsB,CAC1C;GACA,MAAM,SAAS,SAAS,QAAO,YAAW,oBAAoB,IAAI,QAAQ,EAAE,CAAC;GAC7E,IAAI,OAAO,SAAS,GAAG,OAAO,OAAO,MAAM,MAAM,UAAU,KAAK,GAAG,cAAc,MAAM,EAAE,CAAC,CAAC,CAAC;EAC9F;EAEA,KAAK,MAAM,WAAW,SAAS,MAAM,MAAM,UAAU,KAAK,GAAG,cAAc,MAAM,EAAE,CAAC,GAClF,IAAI;GACF,MAAM,QAAQ,IAAI,WAAW,UAAU,SAAS;GAChD,OAAO;EACT,SAAS,OAAO;GACd,IAAI,EAAE,iBAAiB,mBAAmB,CAAC;IAAC;IAAK;IAAK;GAAG,CAAC,CAAC,SAAS,MAAM,UAAU,CAAC,GAAG,MAAM;EAEhG;EAEF,MAAM,IAAI,eAAe,uDAAuD,GAAG;CACrF;CAEA,MAAM,wBACJ,WACsF;EACtF,MAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;EACzD,MAAM,cACJ,UAAU,gBAAgB,MAAM,QAAQ,IAAI,WAAW,UAAU,SAAS,EAAA,CAAG;EAC/E,OAAO;GACL;GACA,QAAQ;IACN,cAAc,QAAQ;IACtB,MAAM,oBAAoB,UAAU,QAAQ,QAAQ,IAAI;IACxD,WAAW,UAAU;IACrB;GACF;EACF;CACF;CAEA,MAAM,uBAAuB,EAAE,kBAAsF;EACnH,IAAI,eAAe,SAAS,SAAS,OAAO;EAC5C,MAAM,YAAY,qBAAqB,eAAe,UAAU;EAChE,IAAI,CAAC,WAAW,OAAO;EACvB,MAAM,EAAE,SAAS,WAAW,MAAM,KAAK,wBAAwB,SAAS;EACxE,OAAO;GACL,YAAY,QAAQ;GACpB,UAAU,eAAe,MAAM;GAC/B,SAAS,OAAO,UAAU,QAAQ;EACpC;CACF;CAEA,MAAM,eAAwC;EAC5C,MAAM,0BAAU,IAAI,IAA0B;EAC9C,KAAK,MAAM,WAAW,MAAM,KAAK,eAAe,GAC9C,KAAK,IAAI,OAAO,IAAK,QAAQ;GAC3B,MAAM,WAAW,MAAM,QAAQ,IAAI,aAAa,EAAE,KAAK,CAAC;GACxD,KAAK,MAAM,WAAW,UAAU;IAC9B,MAAM,SAAS,KAAK,gBAAgB,SAAS,OAAO;IACpD,IAAI,CAAC,QAAQ,IAAI,OAAO,EAAE,GAAG,QAAQ,IAAI,OAAO,IAAI,MAAM;GAC5D;GACA,IAAI,SAAS,SAAA,KAAoC;EACnD;EAEF,OAAO,CAAC,GAAG,QAAQ,OAAO,CAAC;CAC7B;CAEA,MAAM,WAAW,OAAsD;EACrE,MAAM,SAAS,MAAM,KAAK,eAAe,MAAM,WAAW,MAAM,MAAM;EACtE,OAAO;GACL,OAAO,OAAO,OAAO,KAAK,EAAE,OAAO,QAAQ,eAAe;IACxD,QAAQ;KACN,MAAM;KACN,YAAY,qBAAqB;MAAE,GAAG;MAAQ,UAAU,MAAM;KAAI,CAAC;KACnE,KAAK,MAAM;IACb;IACA,UAAU,eAAe,MAAM;IAC/B,OAAO,GAAG,OAAO,YAAY,GAAG,MAAM,IAAI,IAAI,MAAM;IACpD,QAAQ,MAAM;IACd,QAAQ,MAAM,UAAU,CAAC;IACzB,UAAU,YAAY,MAAM,QAAQ;IACpC,WAAW,MAAM;IACjB,WAAW,MAAM;IACjB,UAAU;KACR,YAAY,GAAG,OAAO,YAAY,GAAG,MAAM;KAC3C,WAAW,OAAO;KAClB,aAAa,OAAO;KACpB,cAAc,QAAQ;KACtB,cAAc,QAAQ;KACtB,aAAa,OAAO,aAAa,MAAM,gBAAgB,CAAC,EAAA,CAAG,KAAI,UAAS,CAAC,MAAM,MAAM,MAAM,KAAK,CAAC,CAAC;IACpG;GACF,EAAE;GACF,YAAY,OAAO;EACrB;CACF;CAEA,MAAM,YAAY,OAA8B;EAC9C,MAAM,SAAS,MAAM,KAAK,eAAe,MAAM,WAAW,MAAM,QAAQ,MAAM,MAAM;EACpF,OAAO;GACL,QAAQ,OAAO,OAAO,KAAK,EAAE,OAAO,cAAc;IAChD,GAAG,KAAK,eAAe,OAAO,OAAO,WAAW;IAChD,UAAU,eAAe,MAAM;GACjC,EAAE;GACF,YAAY,OAAO;EACrB;CACF;CAEA,MAAM,eAAe,WAAqB,QAAiB,QAAmB;EAC5E,MAAM,UAAU,UAAU,IAAI,cAAc,CAAC,CAAC,QAAQ,WAA4C,WAAW,IAAI;EACjH,IAAI,QAAQ,WAAW,GAAG,OAAO;GAAE,QAAQ,CAAC;GAAG,YAAY;EAAK;EAChE,MAAM,UAAU,iBAAiB,MAAM;EACvC,IAAI,CAAC,WAAW,QAAQ,UAAU,QAAQ,QAAQ,OAAO;GAAE,QAAQ,CAAC;GAAG,YAAY;EAAK;EAExF,KAAK,IAAI,cAAc,QAAQ,QAAQ,cAAc,QAAQ,QAAQ,eAAe;GAClF,MAAM,EAAE,QAAQ,YAAY,MAAM,KAAK,wBAAwB,QAAQ,YAAa;GACpF,MAAM,OAAO,gBAAgB,QAAQ,SAAS,QAAQ,OAAO;GAC7D,MAAM,SAAS,MAAM,QAAQ,IAAI,WAAW,OAAO,WAAW;IAAE;IAAM;GAAO,CAAC;GAC9E,MAAM,aACJ,OAAO,WAAA,KACH,iBAAiB;IAAE,QAAQ;IAAa,MAAM,OAAO;GAAE,CAAC,IACxD,cAAc,IAAI,QAAQ,SACxB,iBAAiB;IAAE,QAAQ,cAAc;IAAG,MAAM;GAAE,CAAC,IACrD;GACR,OAAO;IAAE,QAAQ,OAAO,KAAI,WAAU;KAAE;KAAO;KAAQ;IAAQ,EAAE;IAAG;GAAW;EACjF;EACA,OAAO;GAAE,QAAQ,CAAC;GAAG,YAAY;EAAK;CACxC;CAEA,MAAM,UAAU,OAA+D;EAC7E,MAAM,WAAW,MAAM,KAAK,gBAAgB,KAAK;EACjD,IAAI;EACJ,IAAI;GACF,QAAQ,MAAM,SAAS,QAAQ,IAAI,SAAS,SAAS,WAAW,SAAS,QAAQ;EACnF,SAAS,OAAO;GACd,IAAI,iBAAiB,kBAAkB,MAAM,WAAW,KAAK,OAAO;GACpE,MAAM;EACR;EACA,MAAM,QAAQ,MAAM,KAAK,cAAc,SAAS,QAAQ,KAAK,SAAS,WAAW,SAAS,QAAQ;EAClG,OAAO;GACL,GAAG,KAAK,eAAe,OAAO,SAAS,WAAW;GAClD,aAAa,MAAM,aAAa,KAAK,KAAK;GAC1C,UAAU,MACP,QAAO,SAAQ,CAAC,KAAK,MAAM,CAAC,CAC5B,KAAI,UAAS;IAAE,QAAQ,YAAY,KAAK,MAAM;IAAG,MAAM,KAAK;IAAM,WAAW,KAAK;GAAW,EAAE;EACpG;CACF;CAEA,MAAM,cAAc,KAAsB,WAAmB,UAAyC;EACpG,MAAM,QAAsB,CAAC;EAC7B,KAAK,IAAI,OAAO,GAAG,QAAQ,iBAAiB,QAAQ;GAClD,MAAM,SAAS,MAAM,IAAI,UAAU,WAAW,UAAU,EAAE,KAAK,CAAC;GAChE,MAAM,KAAK,GAAG,MAAM;GACpB,IAAI,OAAO,SAAA,KAAiC;EAC9C;EACA,OAAO;CACT;CAEA,MAAM,eAAe,OAAuE;EAC1F,MAAM,WAAW,MAAM,KAAK,gBAAgB,KAAK;EACjD,IAAI;GACF,MAAM,QAAQ,MAAM,SAAS,QAAQ,IAAI,SAAS,SAAS,WAAW,SAAS,QAAQ;GACvF,MAAM,OAAO,MAAM,SAAS,QAAQ,IAAI,WAAW,SAAS,WAAW,SAAS,UAAU,MAAM,IAAI;GACpG,OAAO;IAAE,IAAI,OAAO,KAAK,EAAE;IAAG,KAAK,GAAG,MAAM,QAAQ,QAAQ,KAAK;GAAK;EACxE,SAAS,OAAO;GACd,IAAI,iBAAiB,kBAAkB,MAAM,WAAW,KAAK,OAAO;GACpE,MAAM;EACR;CACF;CAEA,MAAM,aAAa,OAA4D;EAC7E,MAAM,WAAW,MAAM,KAAK,gBAAgB,KAAK;EACjD,IAAI;EACJ,IAAI;GACF,QAAQ,MAAM,SAAS,QAAQ,IAAI,SAAS,SAAS,WAAW,SAAS,QAAQ;EACnF,SAAS,OAAO;GACd,IAAI,iBAAiB,kBAAkB,MAAM,WAAW,KAAK,OAAO;GACpE,MAAM;EACR;EACA,MAAM,aAAa,iBAAiB,KAAK;EACzC,IAAI,CAAC,YAAY,OAAO;EACxB,IAAK,eAAe,WAAW,MAAM,UAAU,YAAc,eAAe,YAAY,MAAM,UAAU,UACtG,OAAO,KAAK,eAAe,OAAO,SAAS,WAAW;EAExD,MAAM,UAAU,MAAM,SAAS,QAAQ,IAAI,iBAAiB,SAAS,WAAW,SAAS,UAAU,UAAU;EAC7G,OAAO,KAAK,eAAe,SAAS,SAAS,WAAW;CAC1D;CAEA,MAAM,gBAAgB,OAKnB;EACD,MAAM,iBAAiB,qBAAqB,MAAM,OAAO;EACzD,MAAM,SAAS,MAAM,WAAW,eAAe,MAAM,QAAQ,IAAI;EACjE,MAAM,UAAU,kBAAkB,MAAM,OAAO;EAC/C,MAAM,YAAY,kBAAkB;EACpC,IAAI;EACJ,IAAI,WACF,UAAU,MAAM,KAAK,qBAAqB,SAAS;OAC9C;GACL,MAAM,eAAe,2BAA2B,MAAM,UAAU;GAChE,MAAM,WAAW,eAAe,CAAC,MAAM,KAAK,YAAY,YAAY,CAAC,IAAI,MAAM,KAAK,eAAe;GACnG,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,eAAe,yEAAyE,GAAG;GAEvG,UAAU,SAAS;EACrB;EACA,MAAM,YAAY,gBAAgB,aAAa,QAAQ,aAAa,SAAS;EAC7E,MAAM,WAAW,gBAAgB,YAAY,SAAS,YAAY,qBAAqB,MAAM,OAAO;EACpG,IAAI,CAAC,aAAa,CAAC,UACjB,MAAM,IAAI,eACR,sFACA,GACF;EAEF,MAAM,cACJ,gBAAgB,eAChB,QAAQ,eACR,SAAS,gBACR,MAAM,QAAQ,IAAI,WAAW,SAAS,EAAA,CAAG;EAC5C,OAAO;GAAE;GAAS;GAAW;GAAa;EAAS;CACrD;CAEA,gBAAgB,SAAkC,SAAsC;EAMtF,OAAO;GACL,IAAI,eAAe;IALnB,MAAM,oBAAoB,QAAQ,IAAI;IACtC,WAAW,OAAO,QAAQ,EAAE;IAC5B,aAAa,QAAQ;GAGM,CAAC;GAC5B,MAAM,QAAQ;GACd,MAAM;GACN,UAAU;IACR,WAAW,OAAO,QAAQ,EAAE;IAC5B,aAAa,QAAQ;IACrB,eAAe,QAAQ,kBAAkB;IACzC,cAAc,QAAQ;IACtB,cAAc,QAAQ;IACtB,KAAK,QAAQ;GACf;EACF;CACF;CAEA,eAAe,OAAoB,aAAkC;EACnE,MAAM,YAAY,MAAM,WAAW,IAAI,WAAW,CAAC,CAAC,QAAQ,SAAyB,SAAS,IAAI,KAAK,CAAC;EACxG,OAAO;GACL,IAAI,OAAO,MAAM,GAAG;GACpB,YAAY,GAAG,YAAY,GAAG,MAAM;GACpC,OAAO,MAAM;GACb,KAAK,MAAM;GACX,QAAQ,YAAY,MAAM,MAAM;GAChC,gBAAgB,MAAM,QAAQ,YAAY;GAC1C,OAAO,MAAM;GACb,WAAW,MAAM,UAAU,WAAW,cAAc;GACpD,UAAU,OAAO,MAAM,WAAW,WAAW,OAAO,MAAM,MAAM,IAAI;GACpE,UAAU,YAAY,MAAM,QAAQ,KAAK,UAAU,MAAM;GACzD;GACA,QAAQ;GACR,QAAQ,MAAM,UAAU,CAAC;GACzB,aAAa,OAAO,aAAa,MAAM,gBAAgB,CAAC,EAAA,CAAG,KAAI,UAAS,CAAC,MAAM,MAAM,MAAM,KAAK,CAAC,CAAC;GAClG,cAAc,MAAM,oBAAoB;GACxC,WAAW,MAAM;GACjB,WAAW,MAAM;EACnB;CACF;AACF;AAcA,MAAM,0BAA0B;AAEhC,IAAa,oBAAb,cAAuC,sBAAsB;CAC3D;CACA;CACA;CACA;CACA;CAEA,YAAY,SAAkC,CAAC,GAAG;EAChD,MAAM,OAAO,KAAK;EAClB,MAAM,cAAc,OAAO,aAAa,KAAK,KAAK,QAAQ,IAAI,qBAAqB,KAAK;EACxF,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,0DAA0D;EAE5E,KAAK,eAAe;EACpB,KAAK,mBAAmB,qBACtB,OAAO,mBAAmB,QAAQ,IAAI,0BAA0B,KAAK,CACvE;EACA,KAAK,YAAY,OAAO,WAAW,QAAQ,IAAI,iBAAiB,KAAK,KAAK,qBAAA,CAAsB,QAAQ,QAAQ,EAAE;EAClH,KAAK,iBAAiB,OAAO,eAAe,KAAK,KAAK,QAAQ,IAAI,uBAAuB,KAAK,KAAK,KAAA;EACnG,MAAM,MAAM,IAAI,gBAAgB;GAC9B,SAAS,KAAK;GACd,aAAa,KAAK;GAClB,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;EAC5D,CAAC;EACD,KAAK,WAAW;GACd,IAAI;GACJ,OAAO,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC;GAC9B;GACA,YAAY;IAAE,MAAM;IAAS,aAAa;GAAwB;GAClE,MAAM,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC;GAC7B,YAAY,KAAK;GACjB,uBAAuB,YAAY,KAAK;EAC1C;CACF;CAEA,IAAuB,gBAAoC;EACzD,OAAO,KAAK;CACd;CAEA,MAAM,uBAAyC;EAC7C,OAAO;CACT;CAEA,MAAe,eAA8B;EAC3C,MAAM,KAAK,SAAS,IAAI,eAAe;CACzC;CAEA,qBAA6B;EAC3B,OAAO,kCAAkC,KAAK,iBAAiB;CACjE;CAEA,MAAgB,iBAAqD;EACnE,OAAO,CAAC,KAAK,QAAQ;CACvB;CAEA,MAAgB,YAAY,cAAwD;EAClF,IAAI,iBAAiB,sBACnB,MAAM,IAAI,eAAe,qCAAqC,GAAG;EAEnE,OAAO,KAAK;CACd;CAEA,cAAuC;EACrC,OAAO;GACL,YAAY;GACZ,MAAM;GACN,iBAAiB,KAAK;GACtB,cAAc,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC;GACrC,mBAAmB,QAAQ,KAAK,cAAc;EAChD;CACF;AACF;AAEA,SAAS,qBAAqB,OAAkD;CAC9E,MAAM,aAAa,OAAO,KAAK,CAAC,CAAC,YAAY,KAAK;CAClD,IAAI,eAAe,cAAc,eAAe,SAAS,OAAO;CAChE,MAAM,IAAI,MAAM,4EAA4E;AAC9F;AAEA,SAAgB,eAAe,WAA0C;CACvE,IAAI,UAAU,MACZ,OAAO,GAAG,uBAAuB,aAAa;EAC5C,SAAS;EACT,MAAM,oBAAoB,UAAU,IAAI;EACxC,WAAW,UAAU;CACvB,CAAC;CAEH,IAAI,CAAC,UAAU,gBAAgB,CAAC,UAAU,aACxC,MAAM,IAAI,MAAM,uDAAuD;CAEzE,OAAO,GAAG,uBAAuB,aAAa,SAAS;AACzD;AAEA,SAAgB,eAAe,OAA6C;CAC1E,OAAO,aAAa,OAAO,sBAAsB,iBAAiB;AACpE;AAEA,SAAgB,qBAAqB,WAAyC;CAC5E,IAAI,UAAU,MACZ,OAAO,GAAG,sBAAsB,aAAa;EAC3C,SAAS;EACT,MAAM,oBAAoB,UAAU,IAAI;EACxC,WAAW,UAAU;EACrB,UAAU,UAAU;CACtB,CAAC;CAEH,IAAI,CAAC,UAAU,gBAAgB,CAAC,UAAU,aACxC,MAAM,IAAI,MAAM,sDAAsD;CAExE,OAAO,GAAG,sBAAsB,aAAa,SAAS;AACxD;AAEA,SAAgB,qBAAqB,OAA4C;CAC/E,OAAO,aAAa,OAAO,qBAAqB,gBAAgB;AAClE;AAEA,SAAgB,4BAA4B,OAAmD;CAC7F,OAAO,aAAa,OAAO,6BAA6B,uBAAuB;AACjF;AAEA,SAAgB,iBAAiB,cAA6C;CAC5E,OAAO;EAAE,MAAM;EAAS,aAAa,GAAG,iCAAiC;CAAe;AAC1F;AAEA,SAAS,2BAA2B,YAAkD;CACpF,IAAI,WAAW,SAAS,WAAW,CAAC,WAAW,YAAY,WAAW,8BAA8B,GAAG,OAAO;CAC9G,OAAO,WAAW,YAAY,MAAM,EAAqC,KAAK;AAChF;AAEA,SAAS,aAAa,OAAwB;CAC5C,OAAO,OAAO,KAAK,KAAK,UAAU,KAAK,CAAC,CAAC,CAAC,SAAS,WAAW;AAChE;AAEA,SAAS,aAAgB,OAAe,QAAgB,OAAiD;CACvG,IAAI,CAAC,MAAM,WAAW,MAAM,GAAG,OAAO;CACtC,IAAI;EACF,MAAM,UAAU,KAAK,MAAM,OAAO,KAAK,MAAM,MAAM,OAAO,MAAM,GAAG,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC;EAChG,OAAO,MAAM,OAAO,IAAI,UAAU;CACpC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,oBAAoB,MAAsB;CACxD,OAAO,KAAK,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,OAAO,EAAE;AACpD;AAEA,SAAS,kBAAkB,OAAgD;CACzE,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO;CACxE,MAAM,MAAM;CACZ,IAAI,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,WAAW,GAAG,OAAO;CAC5E,MAAM,YAAY,IAAI,YAAY,KAAK,OAAO,IAAI,SAAS,YAAY,oBAAoB,IAAI,IAAI,CAAC,CAAC,SAAS;CAC9G,MAAM,SACJ,OAAO,IAAI,iBAAiB,YAC5B,IAAI,aAAa,SAAS,KAC1B,OAAO,IAAI,gBAAgB,YAC3B,IAAI,YAAY,SAAS;CAC3B,OAAO,aAAa;AACtB;AAEA,SAAS,iBAAiB,OAA+C;CACvE,OACE,kBAAkB,KAAK,KACvB,OAAO,cAAe,MAA+B,QAAQ,KAC5D,MAA+B,WAAW;AAE/C;AAEA,SAAS,wBAAwB,OAAsD;CACrF,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO;CACxE,MAAM,MAAM;CACZ,OACE,IAAI,YAAY,KAChB,OAAO,IAAI,SAAS,YACpB,oBAAoB,IAAI,IAAI,CAAC,CAAC,SAAS,KACvC,OAAO,cAAc,IAAI,SAAS,KACjC,IAAI,YAAuB,KAC5B,OAAO,cAAc,IAAI,eAAe,KACvC,IAAI,kBAA6B;AAEtC;AAEA,SAAS,iBAAiB,QAAkC;CAC1D,OAAO,aAAa,MAAM;AAC5B;AAEA,SAAS,iBAAiB,OAAoD;CAC5E,IAAI,CAAC,OAAO,OAAO;EAAE,QAAQ;EAAG,MAAM;CAAE;CACxC,IAAI;EACF,MAAM,UAAU,KAAK,MAAM,OAAO,KAAK,OAAO,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC;EAC3E,IAAI,CAAC,OAAO,cAAc,QAAQ,MAAM,KAAK,OAAO,QAAQ,MAAM,IAAI,GAAG,OAAO;EAChF,IAAI,CAAC,OAAO,cAAc,QAAQ,IAAI,KAAK,OAAO,QAAQ,IAAI,IAAI,GAAG,OAAO;EAC5E,OAAO;GAAE,QAAQ,OAAO,QAAQ,MAAM;GAAG,MAAM,OAAO,QAAQ,IAAI;EAAE;CACtE,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,YAAY,MAAoF;CACvG,OAAO,MAAM,MAAM,KAAK,KAAK,MAAM,YAAY;AACjD;AAEA,SAAS,qBAAqB,OAA8B;CAC1D,IAAI,CAAC,QAAQ,KAAK,KAAK,GAAG,OAAO;CACjC,MAAM,SAAS,OAAO,KAAK;CAC3B,OAAO,OAAO,cAAc,MAAM,KAAK,SAAS,IAAI,SAAS;AAC/D;AAEA,SAAS,kBAAkB,OAIlB;CACP,MAAM,YAAY,MAAM,MAAM,eAAe;CAC7C,IAAI,WAAW;EACb,MAAM,WAAW,qBAAqB,UAAU,EAAG;EACnD,MAAM,cAAc,UAAU,EAAE,CAAE,QAAQ,cAAc,EAAE;EAC1D,OAAO,YAAY,cAAc;GAAE;GAAa;EAAS,IAAI;CAC/D;CACA,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,KAAK;EACzB,MAAM,QAAQ,IAAI,SAAS,MAAM,+BAA+B;EAChE,IAAI,CAAC,OAAO,OAAO;EACnB,MAAM,WAAW,qBAAqB,MAAM,EAAG;EAC/C,IAAI,CAAC,UAAU,OAAO;EACtB,MAAM,cAAc,mBAAmB,MAAM,EAAG;EAChD,OAAO;GAAE,MAAM,IAAI;GAAM;GAAa;EAAS;CACjD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,iBAAiB,OAA0D;CAClF,IAAI,MAAM,MAAM,SAAS,UAEvB,OAAO,MAAM,MAAM,cAAc,eAAe,MAAM,MAAM,cAAc,aAAa,UAAU;CAEnG,MAAM,OAAO,MAAM,MAAM,KAAK,KAAK,CAAC,CAAC,YAAY;CACjD,IAAI,SAAS,YAAY,SAAS,SAAS,OAAO;CAClD,IAAI,SAAS,YAAY,SAAS,UAAU,SAAS,UAAU,OAAO;CACtE,OAAO;AACT"}
@@ -16,5 +16,11 @@ export interface BuildGitLabRoutesOptions {
16
16
  /** Mounted agent controller; enables webhook delivery to subscribed sessions. */
17
17
  controller?: GitLabWebhookHandlerOptions['controller'];
18
18
  }
19
+ export declare function ingestLinkedGitLabRepositoryBacklog(args: {
20
+ gitlab: GitLabIntegrationBase;
21
+ orgId: string;
22
+ projectRepositoryId: string;
23
+ ingestFactoryEvent?: BuildGitLabRoutesOptions['ingestFactoryEvent'];
24
+ }): Promise<void>;
19
25
  export declare function buildGitLabRoutes(options: BuildGitLabRoutesOptions): ApiRoute[];
20
26
  //# sourceMappingURL=routes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/integrations/gitlab/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAS1E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAG9D,OAAO,KAAK,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAQrF,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,iFAAiF;IACjF,UAAU,CAAC,EAAE,2BAA2B,CAAC,YAAY,CAAC,CAAC;CACxD;AAkGD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,QAAQ,EAAE,CA8Z/E"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/integrations/gitlab/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAI7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAS1E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAG9D,OAAO,KAAK,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAQrF,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,iFAAiF;IACjF,UAAU,CAAC,EAAE,2BAA2B,CAAC,YAAY,CAAC,CAAC;CACxD;AA8JD,wBAAsB,mCAAmC,CAAC,IAAI,EAAE;IAC9D,MAAM,EAAE,qBAAqB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,wBAAwB,CAAC,oBAAoB,CAAC,CAAC;CACrE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChB;AAwCD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,QAAQ,EAAE,CAqa/E"}
@@ -64,6 +64,152 @@ function mergeRequestSourceKey(host, projectId, mergeRequestIid) {
64
64
  mergeRequestIid
65
65
  }), "utf8").toString("base64url")}`;
66
66
  }
67
+ const LINKED_BACKLOG_MAX_PAGES = 5;
68
+ const POLLED_ACTOR = "__factory_poll__";
69
+ function listedMergeRequestEvent(project, pr) {
70
+ const iid = Number(pr.id);
71
+ return {
72
+ event: "Merge Request Hook",
73
+ deliveryId: `poll:merge-request:${project.host}:${project.projectId}:${iid}:${pr.createdAt}`,
74
+ instanceHost: project.host,
75
+ payload: {
76
+ user_username: POLLED_ACTOR,
77
+ project: {
78
+ id: project.projectId,
79
+ path_with_namespace: project.projectPath,
80
+ web_url: `https://${project.host}/${project.projectPath}`
81
+ },
82
+ object_attributes: {
83
+ iid,
84
+ action: "open",
85
+ state: "opened",
86
+ title: pr.title,
87
+ url: pr.url,
88
+ created_at: pr.createdAt,
89
+ updated_at: pr.updatedAt,
90
+ source_branch: pr.headBranch,
91
+ target_branch: pr.baseBranch,
92
+ draft: pr.draft,
93
+ author: pr.author ? { username: pr.author } : void 0,
94
+ assignees: (pr.assignees ?? []).map((username) => ({ username })),
95
+ reviewers: (pr.requestedReviewers ?? []).map((username) => ({ username })),
96
+ labels: pr.labels ?? []
97
+ }
98
+ }
99
+ };
100
+ }
101
+ function listedMergeRequestEvents(project, pr) {
102
+ const opened = listedMergeRequestEvent(project, pr);
103
+ if (!pr.headSha || pr.updatedAt === pr.createdAt) return [opened];
104
+ return [opened, {
105
+ ...opened,
106
+ deliveryId: `poll:merge-request-head:${project.host}:${project.projectId}:${pr.id}:${pr.updatedAt}:${pr.headSha}`,
107
+ payload: {
108
+ ...opened.payload,
109
+ object_attributes: {
110
+ ...opened.payload.object_attributes,
111
+ action: "update",
112
+ last_commit: { id: pr.headSha }
113
+ }
114
+ }
115
+ }];
116
+ }
117
+ function listedIssueEvent(issue) {
118
+ const source = decodeSourceId(issue.sourceId ?? "");
119
+ const projectId = source && positiveId(source.projectId);
120
+ const iid = positiveId(issue.id);
121
+ const projectPath = issue.source || source?.projectPath;
122
+ if (!source?.host || !projectId || !iid || !projectPath) return null;
123
+ return {
124
+ event: "Issue Hook",
125
+ deliveryId: `poll:issue:${source.host}:${projectId}:${iid}:${issue.createdAt}`,
126
+ instanceHost: source.host,
127
+ payload: {
128
+ user_username: POLLED_ACTOR,
129
+ project: {
130
+ id: projectId,
131
+ path_with_namespace: projectPath,
132
+ web_url: `https://${source.host}/${projectPath}`
133
+ },
134
+ object_attributes: {
135
+ iid,
136
+ action: "open",
137
+ state: "opened",
138
+ title: issue.title,
139
+ url: issue.url,
140
+ created_at: issue.createdAt,
141
+ updated_at: issue.updatedAt,
142
+ author: issue.authorUsername ? { username: issue.authorUsername } : void 0,
143
+ labels: issue.labels ?? []
144
+ }
145
+ }
146
+ };
147
+ }
148
+ async function ingestListedEvents(events, ingest) {
149
+ if (!ingest) return;
150
+ const listed = events.filter((event) => event !== null);
151
+ const openings = listed.filter((event) => !event.deliveryId.startsWith("poll:merge-request-head:"));
152
+ const headUpdates = listed.filter((event) => event.deliveryId.startsWith("poll:merge-request-head:"));
153
+ for (const batch of [openings, headUpdates]) {
154
+ const rejected = (await Promise.allSettled(batch.map((event) => ingest(event)))).find((result) => result.status === "rejected");
155
+ if (rejected) console.warn("[Mastra Factory] Failed to ingest listed GitLab events", { error: rejected.reason });
156
+ }
157
+ }
158
+ async function ingestLinkedGitLabRepositoryBacklog(args) {
159
+ if (!args.ingestFactoryEvent) return;
160
+ const storage = args.gitlab.sourceControlStorage;
161
+ const link = await storage?.projectRepositories.get({
162
+ orgId: args.orgId,
163
+ id: args.projectRepositoryId
164
+ });
165
+ if (!link) return;
166
+ const connection = await storage.connections.get({
167
+ orgId: args.orgId,
168
+ id: link.connectionId
169
+ });
170
+ if (!connection || connection.integrationId !== "gitlab") return;
171
+ const linked = await args.gitlab.getLinkedRepository({
172
+ orgId: args.orgId,
173
+ factoryProjectId: connection.factoryProjectId,
174
+ projectRepositoryId: link.id
175
+ });
176
+ if (!linked) return;
177
+ const projectId = positiveId(linked.repository.externalId);
178
+ if (!projectId) return;
179
+ const project = {
180
+ host: linked.host,
181
+ projectId,
182
+ projectPath: linked.repository.slug
183
+ };
184
+ const target = await args.gitlab.versionControl.getRepositoryTarget({
185
+ orgId: args.orgId,
186
+ repositoryId: linked.repository.id
187
+ });
188
+ for (let page = 1; page <= LINKED_BACKLOG_MAX_PAGES; page += 1) {
189
+ const result = await args.gitlab.versionControl.listPullRequests({
190
+ ...target,
191
+ includeDrafts: false,
192
+ cursor: String(page)
193
+ });
194
+ await ingestListedEvents(result.pullRequests.flatMap((pr) => listedMergeRequestEvents(project, pr)), args.ingestFactoryEvent);
195
+ if (result.nextCursor === null) break;
196
+ }
197
+ const sourceId = encodeSourceId({
198
+ host: linked.host,
199
+ projectId: String(projectId)
200
+ });
201
+ let cursor;
202
+ for (let page = 1; page <= LINKED_BACKLOG_MAX_PAGES; page += 1) {
203
+ const result = await args.gitlab.intake.listIssues({
204
+ connection: target.connection,
205
+ sourceIds: [sourceId],
206
+ cursor
207
+ });
208
+ await ingestListedEvents(result.issues.map(listedIssueEvent), args.ingestFactoryEvent);
209
+ if (result.nextCursor === null) break;
210
+ cursor = result.nextCursor;
211
+ }
212
+ }
67
213
  async function reconcileGitLabSourceIdentity({ intake, orgId, sources }) {
68
214
  await intake.ensureReady();
69
215
  const [config, bindings] = await Promise.all([intake.getConfig({ orgId }), intake.listBindings({
@@ -251,6 +397,11 @@ function buildGitLabRoutes(options) {
251
397
  includeDrafts: false,
252
398
  cursor: String(page)
253
399
  });
400
+ await ingestListedEvents(result.pullRequests.flatMap((pr) => listedMergeRequestEvents({
401
+ host: linked.host,
402
+ projectId,
403
+ projectPath: linked.repository.slug
404
+ }, pr)), options.ingestFactoryEvent);
254
405
  return c.json({
255
406
  pullRequests: result.pullRequests.map((pr) => ({
256
407
  number: Number(pr.id),
@@ -355,6 +506,7 @@ function buildGitLabRoutes(options) {
355
506
  sourceIds,
356
507
  cursor: c.req.query("after")?.trim() || void 0
357
508
  });
509
+ await ingestListedEvents(result.issues.map(listedIssueEvent), options.ingestFactoryEvent);
358
510
  return c.json({
359
511
  ...result,
360
512
  issues: result.issues.map((issue) => {
@@ -472,6 +624,6 @@ function buildGitLabRoutes(options) {
472
624
  }));
473
625
  return routes;
474
626
  }
475
- export { buildGitLabRoutes };
627
+ export { buildGitLabRoutes, ingestLinkedGitLabRepositoryBacklog };
476
628
 
477
629
  //# sourceMappingURL=routes.js.map