@inkeep/agents-work-apps 0.0.0-dev-20260213223619 → 0.0.0-dev-20260214054632

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.
@@ -4,10 +4,10 @@ import "./routes/setup.js";
4
4
  import "./routes/tokenExchange.js";
5
5
  import { WebhookVerificationResult, verifyWebhookSignature } from "./routes/webhooks.js";
6
6
  import { Hono } from "hono";
7
- import * as hono_types6 from "hono/types";
7
+ import * as hono_types0 from "hono/types";
8
8
 
9
9
  //#region src/github/index.d.ts
10
- declare function createGithubRoutes(): Hono<hono_types6.BlankEnv, hono_types6.BlankSchema, "/">;
11
- declare const githubRoutes: Hono<hono_types6.BlankEnv, hono_types6.BlankSchema, "/">;
10
+ declare function createGithubRoutes(): Hono<hono_types0.BlankEnv, hono_types0.BlankSchema, "/">;
11
+ declare const githubRoutes: Hono<hono_types0.BlankEnv, hono_types0.BlankSchema, "/">;
12
12
  //#endregion
13
13
  export { GenerateInstallationAccessTokenResult, GenerateTokenError, GenerateTokenResult, GitHubAppConfig, InstallationAccessToken, InstallationInfo, LookupInstallationError, LookupInstallationForRepoResult, LookupInstallationResult, WebhookVerificationResult, clearConfigCache, createAppJwt, createGithubRoutes, determineStatus, fetchInstallationDetails, fetchInstallationRepositories, generateInstallationAccessToken, getGitHubAppConfig, getGitHubAppName, getStateSigningSecret, getWebhookSecret, githubRoutes, isGitHubAppConfigured, isGitHubAppNameConfigured, isStateSigningConfigured, isWebhookConfigured, lookupInstallationForRepo, validateGitHubAppConfigOnStartup, validateGitHubInstallFlowConfigOnStartup, validateGitHubWebhookConfigOnStartup, verifyWebhookSignature };
@@ -1,7 +1,7 @@
1
- import * as hono0 from "hono";
1
+ import * as hono1 from "hono";
2
2
 
3
3
  //#region src/github/mcp/auth.d.ts
4
- declare const githubMcpAuth: () => hono0.MiddlewareHandler<{
4
+ declare const githubMcpAuth: () => hono1.MiddlewareHandler<{
5
5
  Variables: {
6
6
  toolId: string;
7
7
  };
@@ -1,11 +1,11 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types3 from "hono/types";
2
+ import * as hono_types0 from "hono/types";
3
3
 
4
4
  //#region src/github/mcp/index.d.ts
5
5
  declare const app: Hono<{
6
6
  Variables: {
7
7
  toolId: string;
8
8
  };
9
- }, hono_types3.BlankSchema, "/">;
9
+ }, hono_types0.BlankSchema, "/">;
10
10
  //#endregion
11
11
  export { app as default };
@@ -1,7 +1,7 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types0 from "hono/types";
2
+ import * as hono_types8 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/setup.d.ts
5
- declare const app: Hono<hono_types0.BlankEnv, hono_types0.BlankSchema, "/">;
5
+ declare const app: Hono<hono_types8.BlankEnv, hono_types8.BlankSchema, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,7 +1,7 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types4 from "hono/types";
2
+ import * as hono_types6 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/tokenExchange.d.ts
5
- declare const app: Hono<hono_types4.BlankEnv, hono_types4.BlankSchema, "/">;
5
+ declare const app: Hono<hono_types6.BlankEnv, hono_types6.BlankSchema, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,5 +1,5 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types1 from "hono/types";
2
+ import * as hono_types4 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/webhooks.d.ts
5
5
  interface WebhookVerificationResult {
@@ -7,6 +7,6 @@ interface WebhookVerificationResult {
7
7
  error?: string;
8
8
  }
9
9
  declare function verifyWebhookSignature(payload: string, signature: string | undefined, secret: string): WebhookVerificationResult;
10
- declare const app: Hono<hono_types1.BlankEnv, hono_types1.BlankSchema, "/">;
10
+ declare const app: Hono<hono_types4.BlankEnv, hono_types4.BlankSchema, "/">;
11
11
  //#endregion
12
12
  export { WebhookVerificationResult, app as default, verifyWebhookSignature };
@@ -13,7 +13,7 @@ import "../services/events/index.js";
13
13
  import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "../services/security.js";
14
14
  import "../services/index.js";
15
15
  import { OpenAPIHono } from "@hono/zod-openapi";
16
- import { deleteAllWorkAppSlackChannelAgentConfigsByTeam, deleteAllWorkAppSlackUserMappingsByTeam, deleteWorkAppSlackWorkspaceByNangoConnectionId } from "@inkeep/agents-core";
16
+ import { deleteAllWorkAppSlackChannelAgentConfigsByTeam, deleteAllWorkAppSlackUserMappingsByTeam, deleteWorkAppSlackWorkspaceByNangoConnectionId, flushTraces, getWaitUntil } from "@inkeep/agents-core";
17
17
  import { SpanStatusCode } from "@opentelemetry/api";
18
18
 
19
19
  //#region src/slack/routes/events.ts
@@ -76,6 +76,7 @@ app.post("/events", async (c) => {
76
76
  span.end();
77
77
  return c.json({ ok: true });
78
78
  });
79
+ const waitUntil = await getWaitUntil();
79
80
  return tracer.startActiveSpan(SLACK_SPAN_NAMES.WEBHOOK, async (span) => {
80
81
  let outcome = "ignored_unknown_event";
81
82
  try {
@@ -156,7 +157,7 @@ app.post("/events", async (c) => {
156
157
  teamId,
157
158
  hasQuery: question.length > 0
158
159
  }, "Handling event: app_mention");
159
- handleAppMention({
160
+ const mentionWork = handleAppMention({
160
161
  slackUserId: event.user,
161
162
  channel: event.channel,
162
163
  text: question,
@@ -170,7 +171,8 @@ app.post("/events", async (c) => {
170
171
  errorMessage,
171
172
  errorStack
172
173
  }, "Failed to handle app mention (outer catch)");
173
- });
174
+ }).finally(() => flushTraces());
175
+ if (waitUntil) waitUntil(mentionWork);
174
176
  } else {
175
177
  outcome = "ignored_unknown_event";
176
178
  span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
@@ -198,7 +200,7 @@ app.post("/events", async (c) => {
198
200
  teamId,
199
201
  actionId: action.action_id
200
202
  }, "Handling block_action: open_agent_selector_modal");
201
- handleOpenAgentSelectorModal({
203
+ const selectorWork = handleOpenAgentSelectorModal({
202
204
  triggerId,
203
205
  actionValue: action.value,
204
206
  teamId,
@@ -213,7 +215,8 @@ app.post("/events", async (c) => {
213
215
  text: "Sorry, something went wrong while opening the agent selector. Please try again.",
214
216
  response_type: "ephemeral"
215
217
  }).catch((e) => logger.warn({ error: e }, "Failed to send error notification via response URL"));
216
- });
218
+ }).finally(() => flushTraces());
219
+ if (waitUntil) waitUntil(selectorWork);
217
220
  }
218
221
  if (action.action_id === "modal_project_select") {
219
222
  anyHandled = true;
@@ -224,54 +227,59 @@ app.post("/events", async (c) => {
224
227
  actionId: action.action_id,
225
228
  selectedProjectId
226
229
  }, "Handling block_action: modal_project_select");
227
- if (selectedProjectId && view?.id) (async () => {
228
- try {
229
- const metadata = JSON.parse(view.private_metadata || "{}");
230
- const tenantId = metadata.tenantId;
231
- if (!tenantId) {
232
- logger.warn({ teamId }, "No tenantId in modal metadata — skipping project update");
233
- return;
230
+ if (selectedProjectId && view?.id) {
231
+ const projectSelectWork = (async () => {
232
+ try {
233
+ const metadata = JSON.parse(view.private_metadata || "{}");
234
+ const tenantId = metadata.tenantId;
235
+ if (!tenantId) {
236
+ logger.warn({ teamId }, "No tenantId in modal metadata — skipping project update");
237
+ return;
238
+ }
239
+ const workspace = await findWorkspaceConnectionByTeamId(teamId);
240
+ if (!workspace?.botToken) return;
241
+ const slackClient = getSlackClient(workspace.botToken);
242
+ const { fetchProjectsForTenant, fetchAgentsForProject } = await import("../services/events/utils.js");
243
+ const { buildAgentSelectorModal, buildMessageShortcutModal } = await import("../services/modals.js");
244
+ const projectList = await fetchProjectsForTenant(tenantId);
245
+ const agentList = await fetchAgentsForProject(tenantId, selectedProjectId);
246
+ const agentOptions = agentList.map((a) => ({
247
+ id: a.id,
248
+ name: a.name,
249
+ projectId: a.projectId,
250
+ projectName: a.projectName || a.projectId
251
+ }));
252
+ const modal = metadata.messageContext ? buildMessageShortcutModal({
253
+ projects: projectList,
254
+ agents: agentOptions,
255
+ metadata,
256
+ selectedProjectId,
257
+ messageContext: metadata.messageContext
258
+ }) : buildAgentSelectorModal({
259
+ projects: projectList,
260
+ agents: agentOptions,
261
+ metadata,
262
+ selectedProjectId
263
+ });
264
+ await slackClient.views.update({
265
+ view_id: view.id,
266
+ view: modal
267
+ });
268
+ logger.debug({
269
+ selectedProjectId,
270
+ agentCount: agentList.length
271
+ }, "Updated modal with agents for selected project");
272
+ } catch (err) {
273
+ logger.error({
274
+ err,
275
+ selectedProjectId
276
+ }, "Failed to update modal on project change");
277
+ } finally {
278
+ await flushTraces();
234
279
  }
235
- const workspace = await findWorkspaceConnectionByTeamId(teamId);
236
- if (!workspace?.botToken) return;
237
- const slackClient = getSlackClient(workspace.botToken);
238
- const { fetchProjectsForTenant, fetchAgentsForProject } = await import("../services/events/utils.js");
239
- const { buildAgentSelectorModal, buildMessageShortcutModal } = await import("../services/modals.js");
240
- const projectList = await fetchProjectsForTenant(tenantId);
241
- const agentList = await fetchAgentsForProject(tenantId, selectedProjectId);
242
- const agentOptions = agentList.map((a) => ({
243
- id: a.id,
244
- name: a.name,
245
- projectId: a.projectId,
246
- projectName: a.projectName || a.projectId
247
- }));
248
- const modal = metadata.messageContext ? buildMessageShortcutModal({
249
- projects: projectList,
250
- agents: agentOptions,
251
- metadata,
252
- selectedProjectId,
253
- messageContext: metadata.messageContext
254
- }) : buildAgentSelectorModal({
255
- projects: projectList,
256
- agents: agentOptions,
257
- metadata,
258
- selectedProjectId
259
- });
260
- await slackClient.views.update({
261
- view_id: view.id,
262
- view: modal
263
- });
264
- logger.debug({
265
- selectedProjectId,
266
- agentCount: agentList.length
267
- }, "Updated modal with agents for selected project");
268
- } catch (err) {
269
- logger.error({
270
- err,
271
- selectedProjectId
272
- }, "Failed to update modal on project change");
273
- }
274
- })();
280
+ })();
281
+ if (waitUntil) waitUntil(projectSelectWork);
282
+ }
275
283
  }
276
284
  if (action.action_id === "open_follow_up_modal" && action.value && triggerId) {
277
285
  anyHandled = true;
@@ -279,7 +287,7 @@ app.post("/events", async (c) => {
279
287
  teamId,
280
288
  actionId: action.action_id
281
289
  }, "Handling block_action: open_follow_up_modal");
282
- handleOpenFollowUpModal({
290
+ const followUpModalWork = handleOpenFollowUpModal({
283
291
  triggerId,
284
292
  actionValue: action.value,
285
293
  teamId,
@@ -290,7 +298,8 @@ app.post("/events", async (c) => {
290
298
  errorMessage,
291
299
  actionId: action.action_id
292
300
  }, "Failed to open follow-up modal");
293
- });
301
+ }).finally(() => flushTraces());
302
+ if (waitUntil) waitUntil(followUpModalWork);
294
303
  }
295
304
  }
296
305
  outcome = anyHandled ? "handled" : "ignored_no_action_match";
@@ -333,7 +342,7 @@ app.post("/events", async (c) => {
333
342
  userId,
334
343
  callbackId
335
344
  }, "Handling message_action: ask_agent_shortcut");
336
- handleMessageShortcut({
345
+ const shortcutWork = handleMessageShortcut({
337
346
  triggerId,
338
347
  teamId,
339
348
  channelId,
@@ -348,7 +357,8 @@ app.post("/events", async (c) => {
348
357
  errorMessage,
349
358
  callbackId
350
359
  }, "Failed to handle message shortcut");
351
- });
360
+ }).finally(() => flushTraces());
361
+ if (waitUntil) waitUntil(shortcutWork);
352
362
  } else {
353
363
  outcome = "ignored_unknown_event";
354
364
  span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
@@ -386,13 +396,14 @@ app.post("/events", async (c) => {
386
396
  outcome = "handled";
387
397
  span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
388
398
  logger.info({ callbackId }, "Handling view_submission: agent_selector_modal");
389
- handleModalSubmission(view).catch((err) => {
399
+ const modalWork = handleModalSubmission(view).catch((err) => {
390
400
  const errorMessage = err instanceof Error ? err.message : String(err);
391
401
  logger.error({
392
402
  errorMessage,
393
403
  callbackId
394
404
  }, "Failed to handle modal submission");
395
- });
405
+ }).finally(() => flushTraces());
406
+ if (waitUntil) waitUntil(modalWork);
396
407
  span.end();
397
408
  return new Response(null, { status: 200 });
398
409
  }
@@ -401,13 +412,14 @@ app.post("/events", async (c) => {
401
412
  outcome = "handled";
402
413
  span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
403
414
  logger.info({ callbackId }, "Handling view_submission: follow_up_modal");
404
- handleFollowUpSubmission(view).catch((err) => {
415
+ const followUpWork = handleFollowUpSubmission(view).catch((err) => {
405
416
  const errorMessage = err instanceof Error ? err.message : String(err);
406
417
  logger.error({
407
418
  errorMessage,
408
419
  callbackId
409
420
  }, "Failed to handle follow-up submission");
410
- });
421
+ }).finally(() => flushTraces());
422
+ if (waitUntil) waitUntil(followUpWork);
411
423
  span.end();
412
424
  return new Response(null, { status: 200 });
413
425
  }
@@ -113,7 +113,7 @@ app.openapi(createRoute({
113
113
  });
114
114
  app.openapi(createRoute({
115
115
  method: "get",
116
- path: "/:teamId",
116
+ path: "/{teamId}",
117
117
  summary: "Get Workspace",
118
118
  description: "Get details of a specific Slack workspace",
119
119
  operationId: "slack-get-workspace",
@@ -157,7 +157,7 @@ app.openapi(createRoute({
157
157
  });
158
158
  app.openapi(createRoute({
159
159
  method: "get",
160
- path: "/:teamId/settings",
160
+ path: "/{teamId}/settings",
161
161
  summary: "Get Workspace Settings",
162
162
  description: "Get settings for a Slack workspace including default agent",
163
163
  operationId: "slack-get-workspace-settings",
@@ -190,7 +190,7 @@ app.openapi(createRoute({
190
190
  });
191
191
  app.openapi(createRoute({
192
192
  method: "put",
193
- path: "/:teamId/settings",
193
+ path: "/{teamId}/settings",
194
194
  summary: "Update Workspace Settings",
195
195
  description: "Update workspace settings including default agent",
196
196
  operationId: "slack-update-workspace-settings",
@@ -234,7 +234,7 @@ app.openapi(createRoute({
234
234
  });
235
235
  app.openapi(createRoute({
236
236
  method: "delete",
237
- path: "/:teamId",
237
+ path: "/{teamId}",
238
238
  summary: "Uninstall Workspace",
239
239
  description: "Uninstall Slack app from workspace. Accepts either teamId or connectionId.",
240
240
  operationId: "slack-delete-workspace",
@@ -303,7 +303,7 @@ app.openapi(createRoute({
303
303
  });
304
304
  app.openapi(createRoute({
305
305
  method: "get",
306
- path: "/:teamId/channels",
306
+ path: "/{teamId}/channels",
307
307
  summary: "List Channels",
308
308
  description: "List Slack channels in the workspace that the bot can see",
309
309
  operationId: "slack-list-channels",
@@ -387,7 +387,7 @@ app.openapi(createRoute({
387
387
  });
388
388
  app.openapi(createRoute({
389
389
  method: "get",
390
- path: "/:teamId/channels/:channelId/settings",
390
+ path: "/{teamId}/channels/{channelId}/settings",
391
391
  summary: "Get Channel Settings",
392
392
  description: "Get default agent configuration for a specific channel",
393
393
  operationId: "slack-get-channel-settings",
@@ -430,7 +430,7 @@ app.openapi(createRoute({
430
430
  });
431
431
  app.openapi(createRoute({
432
432
  method: "put",
433
- path: "/:teamId/channels/:channelId/settings",
433
+ path: "/{teamId}/channels/{channelId}/settings",
434
434
  summary: "Set Channel Default Agent",
435
435
  description: "Set or update the default agent for a specific channel",
436
436
  operationId: "slack-set-channel-settings",
@@ -496,7 +496,7 @@ app.use("/:teamId/channels/bulk", async (c, next) => {
496
496
  });
497
497
  app.openapi(createRoute({
498
498
  method: "put",
499
- path: "/:teamId/channels/bulk",
499
+ path: "/{teamId}/channels/bulk",
500
500
  summary: "Bulk Set Channel Agents",
501
501
  description: "Apply the same agent configuration to multiple channels at once",
502
502
  operationId: "slack-bulk-set-channel-agents",
@@ -593,7 +593,7 @@ app.openapi(createRoute({
593
593
  });
594
594
  app.openapi(createRoute({
595
595
  method: "delete",
596
- path: "/:teamId/channels/bulk",
596
+ path: "/{teamId}/channels/bulk",
597
597
  summary: "Bulk Remove Channel Configs",
598
598
  description: "Remove agent configuration from multiple channels at once",
599
599
  operationId: "slack-bulk-delete-channel-agents",
@@ -640,7 +640,7 @@ app.openapi(createRoute({
640
640
  });
641
641
  app.openapi(createRoute({
642
642
  method: "delete",
643
- path: "/:teamId/channels/:channelId/settings",
643
+ path: "/{teamId}/channels/{channelId}/settings",
644
644
  summary: "Remove Channel Config",
645
645
  description: "Remove the default agent configuration for a channel",
646
646
  operationId: "slack-delete-channel-settings",
@@ -675,7 +675,7 @@ app.openapi(createRoute({
675
675
  });
676
676
  app.openapi(createRoute({
677
677
  method: "get",
678
- path: "/:teamId/users",
678
+ path: "/{teamId}/users",
679
679
  summary: "List Linked Users",
680
680
  description: "List all users linked to Inkeep in this workspace",
681
681
  operationId: "slack-list-linked-users",
@@ -725,7 +725,7 @@ app.openapi(createRoute({
725
725
  });
726
726
  app.openapi(createRoute({
727
727
  method: "get",
728
- path: "/:teamId/health",
728
+ path: "/{teamId}/health",
729
729
  summary: "Check Workspace Health",
730
730
  description: "Verify the bot token is valid and check permissions. Returns bot info and permission status.",
731
731
  operationId: "slack-workspace-health",
@@ -821,7 +821,7 @@ app.openapi(createRoute({
821
821
  });
822
822
  app.openapi(createRoute({
823
823
  method: "post",
824
- path: "/:teamId/test-message",
824
+ path: "/{teamId}/test-message",
825
825
  summary: "Send Test Message",
826
826
  description: "Send a test message to verify the bot is working correctly.",
827
827
  operationId: "slack-test-message",
@@ -8,7 +8,7 @@ import { createAgentListMessage, createAlreadyLinkedMessage, createContextBlock,
8
8
  import { getSlackClient } from "../client.js";
9
9
  import { fetchAgentsForProject, fetchProjectsForTenant, getChannelAgentConfig, sendResponseUrlMessage } from "../events/utils.js";
10
10
  import { buildAgentSelectorModal } from "../modals.js";
11
- import { deleteWorkAppSlackUserMapping, findWorkAppSlackUserMapping, findWorkAppSlackUserMappingBySlackUser, signSlackLinkToken, signSlackUserToken } from "@inkeep/agents-core";
11
+ import { deleteWorkAppSlackUserMapping, findWorkAppSlackUserMapping, findWorkAppSlackUserMappingBySlackUser, flushTraces, getWaitUntil, signSlackLinkToken, signSlackUserToken } from "@inkeep/agents-core";
12
12
 
13
13
  //#region src/slack/services/commands/index.ts
14
14
  /**
@@ -327,13 +327,15 @@ async function handleQuestionCommand(payload, question, _dashboardUrl, tenantId)
327
327
  response_type: "ephemeral",
328
328
  ...createErrorMessage("No default agent configured. Ask your admin to set a workspace default in the dashboard.\n\nUse `/inkeep list` to see available agents.")
329
329
  };
330
- executeAgentInBackground(payload, existingLink, {
330
+ const questionWork = executeAgentInBackground(payload, existingLink, {
331
331
  id: resolvedAgent.agentId,
332
332
  name: resolvedAgent.agentName || null,
333
333
  projectId: resolvedAgent.projectId
334
334
  }, question, userTenantId).catch((error) => {
335
335
  logger.error({ error }, "Background execution promise rejected");
336
- });
336
+ }).finally(() => flushTraces());
337
+ const waitUntil = await getWaitUntil();
338
+ if (waitUntil) waitUntil(questionWork);
337
339
  return {};
338
340
  }
339
341
  async function executeAgentInBackground(payload, existingLink, targetAgent, question, tenantId) {
@@ -445,9 +447,11 @@ async function handleRunCommand(payload, agentIdentifier, question, _dashboardUr
445
447
  response_type: "ephemeral",
446
448
  ...createErrorMessage(`Agent "${agentIdentifier}" not found. Use \`/inkeep list\` to see available agents.`)
447
449
  };
448
- executeAgentInBackground(payload, existingLink, targetAgent, question, userTenantId).catch((error) => {
450
+ const runWork = executeAgentInBackground(payload, existingLink, targetAgent, question, userTenantId).catch((error) => {
449
451
  logger.error({ error }, "Background execution promise rejected");
450
- });
452
+ }).finally(() => flushTraces());
453
+ const waitUntil = await getWaitUntil();
454
+ if (waitUntil) waitUntil(runWork);
451
455
  return {};
452
456
  } catch (error) {
453
457
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-work-apps",
3
- "version": "0.0.0-dev-20260213223619",
3
+ "version": "0.0.0-dev-20260214054632",
4
4
  "description": "First party integrations for Inkeep Agents",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -33,7 +33,7 @@
33
33
  "jose": "^6.1.0",
34
34
  "minimatch": "^10.1.1",
35
35
  "slack-block-builder": "^2.8.0",
36
- "@inkeep/agents-core": "0.0.0-dev-20260213223619"
36
+ "@inkeep/agents-core": "0.0.0-dev-20260214054632"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@hono/zod-openapi": "^1.1.5",