@inkeep/agents-api 0.43.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/.well-known/workflow/v1/manifest.debug.json +1 -1
  2. package/dist/.well-known/workflow/v1/step.cjs +211602 -195751
  3. package/dist/createApp.js +11 -9
  4. package/dist/domains/evals/routes/datasetTriggers.d.ts +2 -2
  5. package/dist/domains/evals/routes/index.d.ts +2 -2
  6. package/dist/domains/evals/workflow/routes.d.ts +2 -2
  7. package/dist/domains/manage/index.js +8 -0
  8. package/dist/domains/manage/routes/availableAgents.d.ts +7 -0
  9. package/dist/domains/manage/routes/availableAgents.js +94 -0
  10. package/dist/domains/manage/routes/branches.js +9 -0
  11. package/dist/domains/manage/routes/conversations.d.ts +2 -2
  12. package/dist/domains/manage/routes/evals/datasetItems.js +13 -0
  13. package/dist/domains/manage/routes/evals/datasets.js +9 -0
  14. package/dist/domains/manage/routes/evals/evaluationJobConfigEvaluatorRelations.js +5 -0
  15. package/dist/domains/manage/routes/evals/evaluationJobConfigs.js +9 -0
  16. package/dist/domains/manage/routes/evals/evaluationResults.d.ts +4 -2
  17. package/dist/domains/manage/routes/evals/evaluationResults.js +9 -0
  18. package/dist/domains/manage/routes/evals/evaluationRunConfigs.js +9 -0
  19. package/dist/domains/manage/routes/evals/evaluationSuiteConfigEvaluatorRelations.js +5 -0
  20. package/dist/domains/manage/routes/evals/evaluationSuiteConfigs.js +9 -0
  21. package/dist/domains/manage/routes/evals/evaluators.js +9 -0
  22. package/dist/domains/manage/routes/github.d.ts +16 -0
  23. package/dist/domains/manage/routes/github.js +511 -0
  24. package/dist/domains/manage/routes/index.d.ts +2 -2
  25. package/dist/domains/manage/routes/invitations.d.ts +4 -3
  26. package/dist/domains/manage/routes/invitations.js +16 -28
  27. package/dist/domains/manage/routes/mcp.d.ts +2 -2
  28. package/dist/domains/manage/routes/mcpToolGithubAccess.d.ts +9 -0
  29. package/dist/domains/manage/routes/mcpToolGithubAccess.js +205 -0
  30. package/dist/domains/manage/routes/playgroundToken.js +3 -2
  31. package/dist/domains/manage/routes/projectGithubAccess.d.ts +9 -0
  32. package/dist/domains/manage/routes/projectGithubAccess.js +167 -0
  33. package/dist/domains/manage/routes/projectMembers.js +1 -14
  34. package/dist/domains/manage/routes/projectPermissions.js +2 -9
  35. package/dist/domains/manage/routes/projects.js +14 -16
  36. package/dist/domains/manage/routes/signoz.d.ts +2 -2
  37. package/dist/domains/manage/routes/signoz.js +22 -16
  38. package/dist/domains/manage/routes/tools.js +4 -2
  39. package/dist/domains/manage/routes/userOrganizations.d.ts +4 -3
  40. package/dist/domains/manage/routes/userOrganizations.js +16 -45
  41. package/dist/domains/manage/routes/userProjectMemberships.js +1 -2
  42. package/dist/domains/run/agents/Agent.js +29 -2
  43. package/dist/domains/run/agents/relationTools.js +2 -1
  44. package/dist/domains/run/constants/execution-limits/defaults.d.ts +1 -1
  45. package/dist/domains/run/constants/execution-limits/defaults.js +1 -1
  46. package/dist/domains/run/constants/execution-limits/index.d.ts +1 -1
  47. package/dist/domains/run/context/ContextResolver.js +1 -1
  48. package/dist/domains/run/context/validation.d.ts +1 -1
  49. package/dist/domains/run/services/AgentSession.js +5 -1
  50. package/dist/domains/run/services/BaseCompressor.js +1 -1
  51. package/dist/domains/run/services/TriggerService.d.ts +1 -1
  52. package/dist/domains/run/services/TriggerService.js +15 -13
  53. package/dist/domains/run/tools/sandbox-utils.js +1 -1
  54. package/dist/domains/run/types/executionContext.js +3 -1
  55. package/dist/env.d.ts +12 -2
  56. package/dist/env.js +37 -32
  57. package/dist/factory.d.ts +7 -7
  58. package/dist/factory.js +4 -10
  59. package/dist/index.d.ts +6 -5
  60. package/dist/index.js +3 -5
  61. package/dist/middleware/branchScopedDb.d.ts +1 -1
  62. package/dist/middleware/evalsAuth.d.ts +1 -1
  63. package/dist/middleware/manageAuth.d.ts +1 -1
  64. package/dist/middleware/projectAccess.d.ts +2 -11
  65. package/dist/middleware/projectAccess.js +7 -33
  66. package/dist/middleware/projectConfig.d.ts +3 -3
  67. package/dist/middleware/ref.d.ts +1 -1
  68. package/dist/middleware/requirePermission.d.ts +2 -2
  69. package/dist/middleware/requirePermission.js +1 -2
  70. package/dist/middleware/runAuth.d.ts +4 -4
  71. package/dist/middleware/runAuth.js +39 -4
  72. package/dist/middleware/sessionAuth.d.ts +3 -3
  73. package/dist/middleware/sessionAuth.js +1 -2
  74. package/dist/middleware/tracing.d.ts +3 -3
  75. package/dist/openapi.d.ts +1 -2
  76. package/dist/openapi.js +1 -2
  77. package/dist/types/runExecutionContext.js +3 -1
  78. package/package.json +5 -4
  79. package/dist/domains/github/config.d.ts +0 -14
  80. package/dist/domains/github/config.js +0 -47
  81. package/dist/domains/github/index.d.ts +0 -12
  82. package/dist/domains/github/index.js +0 -18
  83. package/dist/domains/github/installation.d.ts +0 -34
  84. package/dist/domains/github/installation.js +0 -172
  85. package/dist/domains/github/jwks.d.ts +0 -20
  86. package/dist/domains/github/jwks.js +0 -85
  87. package/dist/domains/github/oidcToken.d.ts +0 -22
  88. package/dist/domains/github/oidcToken.js +0 -140
  89. package/dist/domains/github/routes/tokenExchange.d.ts +0 -7
  90. package/dist/domains/github/routes/tokenExchange.js +0 -130
  91. package/dist/initialization.d.ts +0 -6
  92. package/dist/initialization.js +0 -72
@@ -0,0 +1,511 @@
1
+ import { getLogger as getLogger$1 } from "../../../logger.js";
2
+ import runDbClient_default from "../../../data/db/runDbClient.js";
3
+ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
4
+ import { TenantParamsSchema, WorkAppGitHubRepositorySelectSchema, WorkAppGithubInstallationApiSelectSchema, commonCreateErrorResponses, commonDeleteErrorResponses, commonGetErrorResponses, createApiError, deleteInstallation, disconnectInstallation, getInstallationById, getInstallationsByTenantId, getRepositoriesByInstallationId, getRepositoryCountsByTenantId, syncRepositories, updateInstallationStatus } from "@inkeep/agents-core";
5
+ import { createAppJwt, fetchInstallationRepositories, getGitHubAppName, getStateSigningSecret, isGitHubAppNameConfigured, isStateSigningConfigured } from "@inkeep/agents-work-apps/github";
6
+ import { HTTPException } from "hono/http-exception";
7
+ import { SignJWT } from "jose";
8
+
9
+ //#region src/domains/manage/routes/github.ts
10
+ const logger = getLogger$1("github-manage");
11
+ const app = new OpenAPIHono();
12
+ const InstallUrlResponseSchema = z.object({ url: z.url().describe("GitHub App installation URL with signed state parameter") });
13
+ const STATE_JWT_ISSUER = "inkeep-agents-api";
14
+ const STATE_JWT_AUDIENCE = "github-app-install";
15
+ /**
16
+ * Signs a JWT state token for the GitHub App installation flow.
17
+ * The state contains the tenantId and expires after 10 minutes.
18
+ */
19
+ async function signStateToken(tenantId) {
20
+ const secret = getStateSigningSecret();
21
+ const secretKey = new TextEncoder().encode(secret);
22
+ return await new SignJWT({ tenantId }).setProtectedHeader({
23
+ alg: "HS256",
24
+ typ: "JWT"
25
+ }).setIssuer(STATE_JWT_ISSUER).setAudience(STATE_JWT_AUDIENCE).setIssuedAt().setExpirationTime("10m").sign(secretKey);
26
+ }
27
+ app.openapi(createRoute({
28
+ method: "get",
29
+ path: "/install-url",
30
+ summary: "Get GitHub App installation URL",
31
+ operationId: "get-github-install-url",
32
+ tags: ["GitHub"],
33
+ description: "Generates a URL to install the GitHub App on an organization or user account. The URL includes a signed state parameter that encodes the tenant ID and expires after 10 minutes. After installation, GitHub will redirect back to our callback endpoint with this state.",
34
+ request: { params: TenantParamsSchema },
35
+ responses: {
36
+ 200: {
37
+ description: "GitHub App installation URL generated successfully",
38
+ content: { "application/json": { schema: InstallUrlResponseSchema } }
39
+ },
40
+ ...commonGetErrorResponses
41
+ }
42
+ }), async (c) => {
43
+ const { tenantId } = c.req.valid("param");
44
+ if (!isStateSigningConfigured()) {
45
+ logger.error({}, "GITHUB_STATE_SIGNING_SECRET is not configured");
46
+ throw createApiError({
47
+ code: "internal_server_error",
48
+ message: "GitHub App installation is not configured"
49
+ });
50
+ }
51
+ if (!isGitHubAppNameConfigured()) {
52
+ logger.error({}, "GITHUB_APP_NAME is not configured");
53
+ throw createApiError({
54
+ code: "internal_server_error",
55
+ message: "GitHub App installation is not configured"
56
+ });
57
+ }
58
+ const appName = getGitHubAppName();
59
+ logger.info({ tenantId }, "Generating GitHub App installation URL");
60
+ const state = await signStateToken(tenantId);
61
+ const installUrl = `https://github.com/apps/${appName}/installations/new?state=${encodeURIComponent(state)}`;
62
+ logger.info({ tenantId }, "GitHub App installation URL generated");
63
+ return c.json({ url: installUrl }, 200);
64
+ });
65
+ const InstallationWithRepoCountSchema = WorkAppGithubInstallationApiSelectSchema.extend({ repositoryCount: z.number().describe("Number of repositories accessible to this installation") });
66
+ const ListInstallationsResponseSchema = z.object({ installations: z.array(InstallationWithRepoCountSchema).describe("List of GitHub App installations") });
67
+ const ListInstallationsQuerySchema = z.object({ includeDisconnected: z.string().optional().transform((val) => val === "true").describe("Include disconnected installations in the response") });
68
+ app.openapi(createRoute({
69
+ method: "get",
70
+ path: "/installations",
71
+ summary: "List GitHub App installations",
72
+ operationId: "list-github-installations",
73
+ tags: ["GitHub"],
74
+ description: "Returns a list of GitHub App installations connected to this tenant. By default, deleted installations are filtered out. Use the includeDisconnected query parameter to include them.",
75
+ request: {
76
+ params: TenantParamsSchema,
77
+ query: ListInstallationsQuerySchema
78
+ },
79
+ responses: {
80
+ 200: {
81
+ description: "List of GitHub App installations",
82
+ content: { "application/json": { schema: ListInstallationsResponseSchema } }
83
+ },
84
+ ...commonGetErrorResponses
85
+ }
86
+ }), async (c) => {
87
+ const { tenantId } = c.req.valid("param");
88
+ const { includeDisconnected } = c.req.valid("query");
89
+ logger.info({
90
+ tenantId,
91
+ includeDisconnected
92
+ }, "Listing GitHub App installations");
93
+ const [installations, repositoryCounts] = await Promise.all([getInstallationsByTenantId(runDbClient_default)({
94
+ tenantId,
95
+ includeDisconnected
96
+ }), getRepositoryCountsByTenantId(runDbClient_default)({
97
+ tenantId,
98
+ includeDisconnected
99
+ })]);
100
+ const installationsWithCounts = installations.map((installation) => ({
101
+ id: installation.id,
102
+ installationId: installation.installationId,
103
+ accountLogin: installation.accountLogin,
104
+ accountId: installation.accountId,
105
+ accountType: installation.accountType,
106
+ status: installation.status,
107
+ repositoryCount: repositoryCounts.get(installation.id) ?? 0,
108
+ createdAt: installation.createdAt,
109
+ updatedAt: installation.updatedAt
110
+ }));
111
+ logger.info({
112
+ tenantId,
113
+ count: installationsWithCounts.length
114
+ }, "Listed GitHub App installations");
115
+ return c.json({ installations: installationsWithCounts }, 200);
116
+ });
117
+ const InstallationIdParamSchema = z.object({ installationId: z.string().describe("The internal installation ID") });
118
+ const InstallationDetailResponseSchema = z.object({
119
+ installation: WorkAppGithubInstallationApiSelectSchema.describe("Installation details"),
120
+ repositories: z.array(WorkAppGitHubRepositorySelectSchema).describe("List of repositories")
121
+ });
122
+ app.openapi(createRoute({
123
+ method: "get",
124
+ path: "/installations/:installationId",
125
+ summary: "Get GitHub App installation details",
126
+ operationId: "get-github-installation-details",
127
+ tags: ["GitHub"],
128
+ description: "Returns detailed information about a specific GitHub App installation, including the full list of repositories.",
129
+ request: { params: TenantParamsSchema.merge(InstallationIdParamSchema) },
130
+ responses: {
131
+ 200: {
132
+ description: "Installation details retrieved successfully",
133
+ content: { "application/json": { schema: InstallationDetailResponseSchema } }
134
+ },
135
+ ...commonGetErrorResponses
136
+ }
137
+ }), async (c) => {
138
+ const { tenantId, installationId } = c.req.valid("param");
139
+ logger.info({
140
+ tenantId,
141
+ installationId
142
+ }, "Getting GitHub App installation details");
143
+ const [installation, repositories] = await Promise.all([getInstallationById(runDbClient_default)({
144
+ tenantId,
145
+ id: installationId
146
+ }), getRepositoriesByInstallationId(runDbClient_default)(installationId)]);
147
+ if (!installation) {
148
+ logger.warn({
149
+ tenantId,
150
+ installationId
151
+ }, "Installation not found");
152
+ throw createApiError({
153
+ code: "not_found",
154
+ message: "Installation not found"
155
+ });
156
+ }
157
+ logger.info({
158
+ tenantId,
159
+ installationId,
160
+ repositoryCount: repositories.length
161
+ }, "Got GitHub App installation details");
162
+ return c.json({
163
+ installation: {
164
+ id: installation.id,
165
+ installationId: installation.installationId,
166
+ accountLogin: installation.accountLogin,
167
+ accountId: installation.accountId,
168
+ accountType: installation.accountType,
169
+ status: installation.status,
170
+ createdAt: installation.createdAt,
171
+ updatedAt: installation.updatedAt
172
+ },
173
+ repositories
174
+ }, 200);
175
+ });
176
+ const DisconnectInstallationResponseSchema = z.object({ success: z.literal(true).describe("Whether the disconnection was successful") });
177
+ app.openapi(createRoute({
178
+ method: "post",
179
+ path: "/installations/:installationId/disconnect",
180
+ summary: "Disconnect a GitHub App installation",
181
+ operationId: "disconnect-github-installation",
182
+ tags: ["GitHub"],
183
+ description: "Disconnects a GitHub App installation from the tenant. This soft deletes the installation (sets status to \"disconnected\") and removes all project repository access entries. The installation record is preserved for audit purposes. Note: This does NOT uninstall the GitHub App from GitHub - the user can do that separately from GitHub settings.",
184
+ request: { params: TenantParamsSchema.merge(InstallationIdParamSchema) },
185
+ responses: {
186
+ 200: {
187
+ description: "Installation disconnected successfully",
188
+ content: { "application/json": { schema: DisconnectInstallationResponseSchema } }
189
+ },
190
+ ...commonCreateErrorResponses
191
+ }
192
+ }), async (c) => {
193
+ const { tenantId, installationId } = c.req.valid("param");
194
+ logger.info({
195
+ tenantId,
196
+ installationId
197
+ }, "Disconnecting GitHub App installation");
198
+ const installation = await getInstallationById(runDbClient_default)({
199
+ tenantId,
200
+ id: installationId
201
+ });
202
+ if (!installation) {
203
+ logger.warn({
204
+ tenantId,
205
+ installationId
206
+ }, "Installation not found");
207
+ throw createApiError({
208
+ code: "not_found",
209
+ message: "Installation not found"
210
+ });
211
+ }
212
+ if (installation.status === "disconnected") {
213
+ logger.warn({
214
+ tenantId,
215
+ installationId
216
+ }, "Installation already disconnected");
217
+ throw createApiError({
218
+ code: "bad_request",
219
+ message: "Installation is already disconnected"
220
+ });
221
+ }
222
+ if (!await disconnectInstallation(runDbClient_default)({
223
+ tenantId,
224
+ id: installationId
225
+ })) {
226
+ logger.error({
227
+ tenantId,
228
+ installationId
229
+ }, "Failed to disconnect installation");
230
+ throw createApiError({
231
+ code: "internal_server_error",
232
+ message: "Failed to disconnect installation"
233
+ });
234
+ }
235
+ logger.info({
236
+ tenantId,
237
+ installationId
238
+ }, "GitHub App installation disconnected");
239
+ return c.json({ success: true }, 200);
240
+ });
241
+ const ReconnectInstallationResponseSchema = z.object({
242
+ success: z.literal(true).describe("Whether the reconnection was successful"),
243
+ syncResult: z.object({
244
+ added: z.number().describe("Number of repositories added"),
245
+ removed: z.number().describe("Number of repositories removed"),
246
+ updated: z.number().describe("Number of repositories updated")
247
+ }).optional().describe("Repository sync results (if sync was performed)")
248
+ });
249
+ function createServiceUnavailableError(message) {
250
+ const responseBody = {
251
+ title: "Service Unavailable",
252
+ status: 503,
253
+ detail: message,
254
+ code: "service_unavailable",
255
+ error: {
256
+ code: "service_unavailable",
257
+ message: message.length > 100 ? `${message.substring(0, 97)}...` : message
258
+ }
259
+ };
260
+ return new HTTPException(503, {
261
+ message,
262
+ res: new Response(JSON.stringify(responseBody), {
263
+ status: 503,
264
+ headers: {
265
+ "Content-Type": "application/problem+json",
266
+ "X-Content-Type-Options": "nosniff"
267
+ }
268
+ })
269
+ });
270
+ }
271
+ const serviceUnavailableSchema = {
272
+ description: "Service Unavailable - GitHub API is not accessible",
273
+ content: { "application/problem+json": { schema: z.object({
274
+ title: z.string().openapi({ example: "Service Unavailable" }),
275
+ status: z.number().openapi({ example: 503 }),
276
+ detail: z.string().openapi({ example: "Failed to connect to GitHub API" }),
277
+ code: z.literal("service_unavailable").openapi({ example: "service_unavailable" }),
278
+ error: z.object({
279
+ code: z.literal("service_unavailable"),
280
+ message: z.string()
281
+ })
282
+ }) } }
283
+ };
284
+ app.openapi(createRoute({
285
+ method: "post",
286
+ path: "/installations/:installationId/reconnect",
287
+ summary: "Reconnect a disconnected GitHub App installation",
288
+ operationId: "reconnect-github-installation",
289
+ tags: ["GitHub"],
290
+ description: "Reconnects a previously disconnected GitHub App installation by setting its status back to \"active\" and syncing the available repositories from GitHub. This can only be used on installations with \"disconnected\" status.",
291
+ request: { params: TenantParamsSchema.merge(InstallationIdParamSchema) },
292
+ responses: {
293
+ 200: {
294
+ description: "Installation reconnected successfully",
295
+ content: { "application/json": { schema: ReconnectInstallationResponseSchema } }
296
+ },
297
+ ...commonCreateErrorResponses,
298
+ 503: serviceUnavailableSchema
299
+ }
300
+ }), async (c) => {
301
+ const { tenantId, installationId } = c.req.valid("param");
302
+ logger.info({
303
+ tenantId,
304
+ installationId
305
+ }, "Reconnecting GitHub App installation");
306
+ const installation = await getInstallationById(runDbClient_default)({
307
+ tenantId,
308
+ id: installationId
309
+ });
310
+ if (!installation) {
311
+ logger.warn({
312
+ tenantId,
313
+ installationId
314
+ }, "Installation not found");
315
+ throw createApiError({
316
+ code: "not_found",
317
+ message: "Installation not found"
318
+ });
319
+ }
320
+ if (installation.status !== "disconnected") {
321
+ logger.warn({
322
+ tenantId,
323
+ installationId,
324
+ status: installation.status
325
+ }, "Installation is not disconnected");
326
+ throw createApiError({
327
+ code: "bad_request",
328
+ message: "Installation is not disconnected"
329
+ });
330
+ }
331
+ if (!await updateInstallationStatus(runDbClient_default)({
332
+ tenantId,
333
+ id: installationId,
334
+ status: "active"
335
+ })) {
336
+ logger.error({
337
+ tenantId,
338
+ installationId
339
+ }, "Failed to reconnect installation");
340
+ throw createApiError({
341
+ code: "internal_server_error",
342
+ message: "Failed to reconnect installation"
343
+ });
344
+ }
345
+ logger.info({
346
+ tenantId,
347
+ installationId
348
+ }, "GitHub App installation reconnected, syncing repositories");
349
+ let appJwt;
350
+ try {
351
+ appJwt = await createAppJwt();
352
+ } catch (error) {
353
+ logger.error({ error }, "Failed to create GitHub App JWT");
354
+ throw createServiceUnavailableError("GitHub App not configured properly");
355
+ }
356
+ const reposResult = await fetchInstallationRepositories(installation.installationId, appJwt);
357
+ if (!reposResult.success) {
358
+ logger.error({
359
+ error: reposResult.error,
360
+ installationId
361
+ }, "Failed to fetch repositories from GitHub");
362
+ throw createServiceUnavailableError("Failed to fetch repositories from GitHub API");
363
+ }
364
+ const syncResult = await syncRepositories(runDbClient_default)({
365
+ installationId: installation.id,
366
+ repositories: reposResult.repositories.map((repo) => ({
367
+ repositoryId: String(repo.id),
368
+ repositoryName: repo.name,
369
+ repositoryFullName: repo.full_name,
370
+ private: repo.private
371
+ }))
372
+ });
373
+ logger.info({
374
+ tenantId,
375
+ installationId,
376
+ added: syncResult.added,
377
+ removed: syncResult.removed,
378
+ updated: syncResult.updated
379
+ }, "GitHub App installation reconnected and repositories synced");
380
+ return c.json({
381
+ success: true,
382
+ syncResult: {
383
+ added: syncResult.added,
384
+ removed: syncResult.removed,
385
+ updated: syncResult.updated
386
+ }
387
+ }, 200);
388
+ });
389
+ app.openapi(createRoute({
390
+ method: "delete",
391
+ path: "/installations/:installationId",
392
+ summary: "Delete a GitHub App installation permanently",
393
+ operationId: "delete-github-installation",
394
+ tags: ["GitHub"],
395
+ description: "Permanently deletes a GitHub App installation from the tenant. This hard deletes the installation record, all associated repositories, and project repository access entries. This action cannot be undone. Use POST /disconnect for soft delete instead. Note: This does NOT uninstall the GitHub App from GitHub - the user can do that separately from GitHub settings.",
396
+ request: { params: TenantParamsSchema.merge(InstallationIdParamSchema) },
397
+ responses: {
398
+ 200: {
399
+ description: "Installation deleted successfully",
400
+ content: { "application/json": { schema: z.object({ success: z.literal(true).describe("Whether the deletion was successful") }) } }
401
+ },
402
+ ...commonDeleteErrorResponses
403
+ }
404
+ }), async (c) => {
405
+ const { tenantId, installationId } = c.req.valid("param");
406
+ logger.info({
407
+ tenantId,
408
+ installationId
409
+ }, "Deleting GitHub App installation permanently");
410
+ if (!await deleteInstallation(runDbClient_default)({
411
+ tenantId,
412
+ id: installationId
413
+ })) throw createApiError({
414
+ code: "not_found",
415
+ message: "Installation not found"
416
+ });
417
+ logger.info({
418
+ tenantId,
419
+ installationId
420
+ }, "GitHub App installation deleted permanently");
421
+ return c.json({ success: true }, 200);
422
+ });
423
+ const SyncRepositoriesResponseSchema = z.object({
424
+ repositories: z.array(WorkAppGitHubRepositorySelectSchema).describe("Updated list of repositories"),
425
+ syncResult: z.object({
426
+ added: z.number().describe("Number of repositories added"),
427
+ removed: z.number().describe("Number of repositories removed"),
428
+ updated: z.number().describe("Number of repositories updated")
429
+ })
430
+ });
431
+ app.openapi(createRoute({
432
+ method: "post",
433
+ path: "/installations/:installationId/sync",
434
+ summary: "Sync repositories for a GitHub App installation",
435
+ operationId: "sync-github-installation-repositories",
436
+ tags: ["GitHub"],
437
+ description: "Manually refreshes the repository list for a GitHub App installation by fetching the current list from GitHub API. This is useful if webhooks were missed or to ensure the local data is in sync with GitHub.",
438
+ request: { params: TenantParamsSchema.merge(InstallationIdParamSchema) },
439
+ responses: {
440
+ 200: {
441
+ description: "Repositories synced successfully",
442
+ content: { "application/json": { schema: SyncRepositoriesResponseSchema } }
443
+ },
444
+ ...commonGetErrorResponses,
445
+ 503: serviceUnavailableSchema
446
+ }
447
+ }), async (c) => {
448
+ const { tenantId, installationId } = c.req.valid("param");
449
+ logger.info({
450
+ tenantId,
451
+ installationId
452
+ }, "Syncing repositories for GitHub App installation");
453
+ const installation = await getInstallationById(runDbClient_default)({
454
+ tenantId,
455
+ id: installationId
456
+ });
457
+ if (!installation) {
458
+ logger.warn({
459
+ tenantId,
460
+ installationId
461
+ }, "Installation not found");
462
+ throw createApiError({
463
+ code: "not_found",
464
+ message: "Installation not found"
465
+ });
466
+ }
467
+ let appJwt;
468
+ try {
469
+ appJwt = await createAppJwt();
470
+ } catch (error) {
471
+ logger.error({ error }, "Failed to create GitHub App JWT");
472
+ throw createServiceUnavailableError("GitHub App not configured properly");
473
+ }
474
+ const reposResult = await fetchInstallationRepositories(installation.installationId, appJwt);
475
+ if (!reposResult.success) {
476
+ logger.error({
477
+ error: reposResult.error,
478
+ installationId
479
+ }, "Failed to fetch repositories from GitHub");
480
+ throw createServiceUnavailableError("Failed to fetch repositories from GitHub API");
481
+ }
482
+ const syncResult = await syncRepositories(runDbClient_default)({
483
+ installationId: installation.id,
484
+ repositories: reposResult.repositories.map((repo) => ({
485
+ repositoryId: String(repo.id),
486
+ repositoryName: repo.name,
487
+ repositoryFullName: repo.full_name,
488
+ private: repo.private
489
+ }))
490
+ });
491
+ logger.info({
492
+ tenantId,
493
+ installationId,
494
+ added: syncResult.added,
495
+ removed: syncResult.removed,
496
+ updated: syncResult.updated
497
+ }, "Repositories synced successfully");
498
+ const updatedRepositories = await getRepositoriesByInstallationId(runDbClient_default)(installation.id);
499
+ return c.json({
500
+ repositories: updatedRepositories,
501
+ syncResult: {
502
+ added: syncResult.added,
503
+ removed: syncResult.removed,
504
+ updated: syncResult.updated
505
+ }
506
+ }, 200);
507
+ });
508
+ var github_default = app;
509
+
510
+ //#endregion
511
+ export { STATE_JWT_AUDIENCE, STATE_JWT_ISSUER, github_default as default, signStateToken };
@@ -1,7 +1,7 @@
1
1
  import { OpenAPIHono } from "@hono/zod-openapi";
2
- import * as hono17 from "hono";
2
+ import * as hono18 from "hono";
3
3
 
4
4
  //#region src/domains/manage/routes/index.d.ts
5
- declare const app: OpenAPIHono<hono17.Env, {}, "/">;
5
+ declare const app: OpenAPIHono<hono18.Env, {}, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,9 +1,10 @@
1
1
  import { ManageAppVariables } from "../../../types/app.js";
2
- import { OpenAPIHono } from "@hono/zod-openapi";
2
+ import { Hono } from "hono";
3
+ import * as hono_types7 from "hono/types";
3
4
 
4
5
  //#region src/domains/manage/routes/invitations.d.ts
5
- declare const invitationsRoutes: OpenAPIHono<{
6
+ declare const invitationsRoutes: Hono<{
6
7
  Variables: ManageAppVariables;
7
- }, {}, "/">;
8
+ }, hono_types7.BlankSchema, "/">;
8
9
  //#endregion
9
10
  export { invitationsRoutes as default };
@@ -1,34 +1,22 @@
1
1
  import runDbClient_default from "../../../data/db/runDbClient.js";
2
- import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
3
- import { getPendingInvitationsByEmail } from "@inkeep/agents-core";
2
+ import { sessionAuth } from "../../../middleware/sessionAuth.js";
3
+ import { createApiError, getPendingInvitationsByEmail } from "@inkeep/agents-core";
4
+ import { Hono } from "hono";
4
5
 
5
6
  //#region src/domains/manage/routes/invitations.ts
6
- const invitationsRoutes = new OpenAPIHono();
7
- const PendingInvitationSchema = z.object({
8
- id: z.string(),
9
- email: z.string(),
10
- organizationId: z.string(),
11
- organizationName: z.string().nullable(),
12
- organizationSlug: z.string().nullable(),
13
- role: z.string().nullable(),
14
- status: z.string(),
15
- expiresAt: z.number(),
16
- inviterId: z.string()
17
- });
18
- const PendingInvitationsResponseSchema = z.array(PendingInvitationSchema);
19
- invitationsRoutes.openapi(createRoute({
20
- method: "get",
21
- path: "/pending",
22
- tags: ["Invitations"],
23
- summary: "Get pending invitations",
24
- description: "Get all pending (non-expired) invitations for a given email address",
25
- request: { query: z.object({ email: z.email().describe("Email address to check for invitations") }) },
26
- responses: { 200: {
27
- description: "List of pending invitations",
28
- content: { "application/json": { schema: PendingInvitationsResponseSchema } }
29
- } }
30
- }), async (c) => {
31
- const { email } = c.req.valid("query");
7
+ const invitationsRoutes = new Hono();
8
+ invitationsRoutes.use("*", sessionAuth());
9
+ invitationsRoutes.get("/pending", async (c) => {
10
+ const email = c.req.query("email");
11
+ const authenticatedEmail = c.get("userEmail");
12
+ if (!email) throw createApiError({
13
+ code: "bad_request",
14
+ message: "Email parameter is required"
15
+ });
16
+ if (email !== authenticatedEmail) throw createApiError({
17
+ code: "forbidden",
18
+ message: "Cannot access invitations for another email"
19
+ });
32
20
  const response = (await getPendingInvitationsByEmail(runDbClient_default)(email)).map((inv) => ({
33
21
  ...inv,
34
22
  expiresAt: inv.expiresAt instanceof Date ? inv.expiresAt.getTime() : inv.expiresAt
@@ -1,7 +1,7 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types15 from "hono/types";
2
+ import * as hono_types8 from "hono/types";
3
3
 
4
4
  //#region src/domains/manage/routes/mcp.d.ts
5
- declare const app: Hono<hono_types15.BlankEnv, hono_types15.BlankSchema, "/">;
5
+ declare const app: Hono<hono_types8.BlankEnv, hono_types8.BlankSchema, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -0,0 +1,9 @@
1
+ import { ManageAppVariables } from "../../../types/app.js";
2
+ import { OpenAPIHono } from "@hono/zod-openapi";
3
+
4
+ //#region src/domains/manage/routes/mcpToolGithubAccess.d.ts
5
+ declare const app: OpenAPIHono<{
6
+ Variables: ManageAppVariables;
7
+ }, {}, "/">;
8
+ //#endregion
9
+ export { app as default };