@inkeep/agents-work-apps 0.0.0-dev-20260213181729 → 0.0.0-dev-20260213213510

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/env.d.ts CHANGED
@@ -14,11 +14,11 @@ declare const envSchema: z.ZodObject<{
14
14
  pentest: "pentest";
15
15
  }>>;
16
16
  LOG_LEVEL: z.ZodDefault<z.ZodEnum<{
17
+ error: "error";
17
18
  trace: "trace";
18
19
  debug: "debug";
19
20
  info: "info";
20
21
  warn: "warn";
21
- error: "error";
22
22
  }>>;
23
23
  INKEEP_AGENTS_RUN_DATABASE_URL: z.ZodString;
24
24
  INKEEP_AGENTS_MANAGE_UI_URL: z.ZodOptional<z.ZodString>;
@@ -43,7 +43,7 @@ declare const envSchema: z.ZodObject<{
43
43
  declare const env: {
44
44
  NODE_ENV: "development" | "production" | "test";
45
45
  ENVIRONMENT: "development" | "production" | "test" | "pentest";
46
- LOG_LEVEL: "trace" | "debug" | "info" | "warn" | "error";
46
+ LOG_LEVEL: "error" | "trace" | "debug" | "info" | "warn";
47
47
  INKEEP_AGENTS_RUN_DATABASE_URL: string;
48
48
  INKEEP_AGENTS_MANAGE_UI_URL?: string | undefined;
49
49
  GITHUB_APP_ID?: string | undefined;
@@ -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_types3 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_types3.BlankEnv, hono_types3.BlankSchema, "/">;
11
- declare const githubRoutes: Hono<hono_types3.BlankEnv, hono_types3.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 hono1 from "hono";
1
+ import * as hono0 from "hono";
2
2
 
3
3
  //#region src/github/mcp/auth.d.ts
4
- declare const githubMcpAuth: () => hono1.MiddlewareHandler<{
4
+ declare const githubMcpAuth: () => hono0.MiddlewareHandler<{
5
5
  Variables: {
6
6
  toolId: string;
7
7
  };
@@ -1,11 +1,11 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types7 from "hono/types";
2
+ import * as hono_types3 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_types7.BlankSchema, "/">;
9
+ }, hono_types3.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_types6 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/tokenExchange.d.ts
5
- declare const app: Hono<hono_types0.BlankEnv, hono_types0.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 };
@@ -534,7 +534,17 @@ app.openapi(createRoute({
534
534
  const workspace = await findWorkspaceConnectionByTeamId(teamId);
535
535
  if (!workspace?.botToken || !verifyTenantOwnership(c, workspace.tenantId)) return c.json({ error: "Workspace not found or no bot token" }, 404);
536
536
  const tenantId = workspace.tenantId;
537
- const channels = await getSlackChannels(getSlackClient(workspace.botToken), 500);
537
+ const slackClient = getSlackClient(workspace.botToken);
538
+ let channels = [];
539
+ try {
540
+ channels = await getSlackChannels(slackClient, 500);
541
+ } catch (error) {
542
+ logger.error({
543
+ error,
544
+ teamId
545
+ }, "Failed to fetch channels for bulk operation");
546
+ return c.json({ error: "Failed to fetch channels" }, 500);
547
+ }
538
548
  const channelMap = new Map(channels.map((ch) => [ch.id, ch]));
539
549
  let updated = 0;
540
550
  const errors = [];
@@ -6,6 +6,9 @@ import { WebClient } from "@slack/web-api";
6
6
  /**
7
7
  * Create a Slack WebClient with the provided bot token.
8
8
  *
9
+ * Built-in retry behavior:
10
+ * - **Connection errors**: 5 retries in 5 minutes (exponential backoff + jitter).
11
+ *
9
12
  * @param token - Bot OAuth token from Nango connection
10
13
  * @returns Configured Slack WebClient instance
11
14
  */
@@ -47,7 +50,7 @@ declare function getSlackTeamInfo(client: WebClient): Promise<{
47
50
  * Users can invite the bot with `/invite @BotName` in the private channel.
48
51
  *
49
52
  * @param client - Authenticated Slack WebClient
50
- * @param limit - Maximum number of channels to return (default 20)
53
+ * @param limit - Maximum number of channels to return. Fetches in pages of up to 200 until the limit is reached or all channels are returned.
51
54
  * @returns Array of channel objects with id, name, member count, and privacy status
52
55
  */
53
56
  declare function getSlackChannels(client: WebClient, limit?: number): Promise<{
@@ -1,5 +1,5 @@
1
1
  import { getLogger } from "../../logger.js";
2
- import { WebClient } from "@slack/web-api";
2
+ import { WebClient, retryPolicies } from "@slack/web-api";
3
3
 
4
4
  //#region src/slack/services/client.ts
5
5
  /**
@@ -9,14 +9,27 @@ import { WebClient } from "@slack/web-api";
9
9
  * Tokens are fetched from Nango at runtime and passed to these functions.
10
10
  */
11
11
  const logger = getLogger("slack-client");
12
+ async function paginateSlack({ fetchPage, extractItems, getNextCursor, limit }) {
13
+ const items = [];
14
+ let cursor;
15
+ do {
16
+ const response = await fetchPage(cursor);
17
+ items.push(...extractItems(response));
18
+ cursor = getNextCursor(response);
19
+ } while (cursor && (limit === void 0 || items.length < limit));
20
+ return limit !== void 0 ? items.slice(0, limit) : items;
21
+ }
12
22
  /**
13
23
  * Create a Slack WebClient with the provided bot token.
14
24
  *
25
+ * Built-in retry behavior:
26
+ * - **Connection errors**: 5 retries in 5 minutes (exponential backoff + jitter).
27
+ *
15
28
  * @param token - Bot OAuth token from Nango connection
16
29
  * @returns Configured Slack WebClient instance
17
30
  */
18
31
  function getSlackClient(token) {
19
- return new WebClient(token);
32
+ return new WebClient(token, { retryConfig: retryPolicies.fiveRetriesInFiveMinutes });
20
33
  }
21
34
  /**
22
35
  * Fetch user profile information from Slack.
@@ -76,29 +89,34 @@ async function getSlackTeamInfo(client) {
76
89
  * Users can invite the bot with `/invite @BotName` in the private channel.
77
90
  *
78
91
  * @param client - Authenticated Slack WebClient
79
- * @param limit - Maximum number of channels to return (default 20)
92
+ * @param limit - Maximum number of channels to return. Fetches in pages of up to 200 until the limit is reached or all channels are returned.
80
93
  * @returns Array of channel objects with id, name, member count, and privacy status
81
94
  */
82
- async function getSlackChannels(client, limit = 20) {
83
- try {
84
- const result = await client.conversations.list({
95
+ async function getSlackChannels(client, limit = 200) {
96
+ return paginateSlack({
97
+ fetchPage: (cursor) => client.conversations.list({
85
98
  types: "public_channel,private_channel",
86
99
  exclude_archived: true,
87
- limit
88
- });
89
- if (result.ok && result.channels) return result.channels.map((ch) => ({
90
- id: ch.id,
91
- name: ch.name,
92
- memberCount: ch.num_members,
93
- isBotMember: ch.is_member,
94
- isPrivate: ch.is_private ?? false,
95
- isShared: ch.is_shared ?? ch.is_ext_shared ?? false
96
- }));
97
- return [];
98
- } catch (error) {
99
- logger.error({ error }, "Failed to fetch Slack channels");
100
- return [];
101
- }
100
+ limit: Math.min(limit, 200),
101
+ cursor
102
+ }),
103
+ extractItems: (result) => {
104
+ if (!result.ok) {
105
+ logger.warn({ error: result.error }, "Slack API returned ok: false during channel pagination");
106
+ return [];
107
+ }
108
+ return result.channels ? result.channels.map((ch) => ({
109
+ id: ch.id,
110
+ name: ch.name,
111
+ memberCount: ch.num_members,
112
+ isBotMember: ch.is_member,
113
+ isPrivate: ch.is_private ?? false,
114
+ isShared: ch.is_shared ?? ch.is_ext_shared ?? false
115
+ })) : [];
116
+ },
117
+ getNextCursor: (result) => result.response_metadata?.next_cursor || void 0,
118
+ limit
119
+ });
102
120
  }
103
121
  /**
104
122
  * Post a message to a Slack channel.
@@ -165,27 +183,21 @@ async function postMessageInThread(client, channel, threadTs, text, blocks) {
165
183
  * @returns true if user is a member, false otherwise
166
184
  */
167
185
  async function checkUserIsChannelMember(client, channelId, userId) {
168
- try {
169
- let cursor;
170
- do {
171
- const result = await client.conversations.members({
172
- channel: channelId,
173
- limit: 200,
174
- cursor
175
- });
176
- if (!result.ok || !result.members) return false;
177
- if (result.members.includes(userId)) return true;
178
- cursor = result.response_metadata?.next_cursor;
179
- } while (cursor);
180
- return false;
181
- } catch (error) {
182
- logger.error({
183
- error,
184
- channelId,
185
- userId
186
- }, "Failed to check channel membership");
187
- return false;
188
- }
186
+ return (await paginateSlack({
187
+ fetchPage: (cursor) => client.conversations.members({
188
+ channel: channelId,
189
+ limit: 200,
190
+ cursor
191
+ }),
192
+ extractItems: (result) => {
193
+ if (!result.ok) {
194
+ logger.warn({ error: result.error }, "Slack API returned ok: false during members pagination");
195
+ return [];
196
+ }
197
+ return result.members ?? [];
198
+ },
199
+ getNextCursor: (result) => result.response_metadata?.next_cursor || void 0
200
+ })).includes(userId);
189
201
  }
190
202
  /**
191
203
  * Revoke a Slack bot token.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-work-apps",
3
- "version": "0.0.0-dev-20260213181729",
3
+ "version": "0.0.0-dev-20260213213510",
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-20260213181729"
36
+ "@inkeep/agents-core": "0.0.0-dev-20260213213510"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@hono/zod-openapi": "^1.1.5",