Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type { GenericMessageEvent } from "@slack/types";
import { db } from "@superset/db/client";
import { integrationConnections } from "@superset/db/schema";
import { and, eq } from "drizzle-orm";
import { runSlackAgent } from "../utils/run-agent";
import { formatActionsAsText } from "../utils/slack-blocks";
import { formatErrorForSlack, runSlackAgent } from "../utils/run-agent";
import { formatSideEffectsMessage } from "../utils/slack-blocks";
import { createSlackClient } from "../utils/slack-client";

interface ProcessAssistantMessageParams {
Expand Down Expand Up @@ -43,15 +43,18 @@ export async function processAssistantMessage({

const threadTs = event.thread_ts ?? event.ts;

// Post an initial message that gets updated as the agent works
let messageTs: string | undefined;
try {
await slack.assistant.threads.setStatus({
channel_id: event.channel,
const initialMsg = await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
status: "Thinking...",
text: "Thinking...",
});
messageTs = initialMsg.ts;
} catch (err) {
console.warn(
"[slack/process-assistant-message] Failed to set status:",
console.error(
"[slack/process-assistant-message] Failed to post initial message:",
err,
);
}
Expand All @@ -63,34 +66,67 @@ export async function processAssistantMessage({
threadTs,
organizationId: connection.organizationId,
slackToken: connection.accessToken,
onProgress: messageTs
? async (status) => {
try {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: status,
});
} catch {
// Non-critical: progress updates are best-effort
}
Comment on lines +69 to +79
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find and read the specific file
find . -path "*/apps/api/src/app/api/integrations/slack/events/process-assistant-message/process-assistant-message.ts" -type f

Repository: superset-sh/superset

Length of output: 167


🏁 Script executed:

# If found, read the file to verify the code at lines 61-71
if [ -f "apps/api/src/app/api/integrations/slack/events/process-assistant-message/process-assistant-message.ts" ]; then
  wc -l "apps/api/src/app/api/integrations/slack/events/process-assistant-message/process-assistant-message.ts"
  echo "---"
  sed -n '50,80p' "apps/api/src/app/api/integrations/slack/events/process-assistant-message/process-assistant-message.ts"
fi

Repository: superset-sh/superset

Length of output: 881


🏁 Script executed:

# Search for the file using fd
fd "process-assistant-message.ts" -type f

Repository: superset-sh/superset

Length of output: 234


🏁 Script executed:

# Read the full file to understand logging patterns and other error handling
cat -n "apps/api/src/app/api/integrations/slack/events/process-assistant-message/process-assistant-message.ts"

Repository: superset-sh/superset

Length of output: 3803


🏁 Script executed:

# Check for other console/logging patterns in the same directory or file
grep -r "console\." "apps/api/src/app/api/integrations/slack/" --include="*.ts" --include="*.tsx" | head -20

Repository: superset-sh/superset

Length of output: 2766


🏁 Script executed:

# Search for error handling patterns in the file
grep -n "catch" "apps/api/src/app/api/integrations/slack/events/process-assistant-message/process-assistant-message.ts"

Repository: superset-sh/superset

Length of output: 102


Log progress update failures for observability.

The silent catch block at line 69 violates the coding guideline requiring all errors to be logged with context. While progress updates are best-effort, failures should still be logged at minimum for Slack API observability.

💡 Suggested fix
-						} catch {
-							// Non-critical: progress updates are best-effort
-						}
+						} catch (error) {
+							console.warn(
+								"[slack/process-assistant-message] Failed to update progress:",
+								error,
+							);
+						}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onProgress: messageTs
? async (status) => {
try {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: status,
});
} catch {
// Non-critical: progress updates are best-effort
}
onProgress: messageTs
? async (status) => {
try {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: status,
});
} catch (error) {
console.warn(
"[slack/process-assistant-message] Failed to update progress:",
error,
);
}
🤖 Prompt for AI Agents
In
`@apps/api/src/app/api/integrations/slack/events/process-assistant-message/process-assistant-message.ts`
around lines 61 - 71, The onProgress handler currently swallows errors in the
catch block when calling slack.chat.update; replace the silent catch with a
logged error that includes context (event.channel, messageTs, and the status
string) and the caught error object to aid observability. Update the catch in
the onProgress async function (the block around slack.chat.update) to call your
project's logger (use the existing logger instance, e.g., processLogger or
logger) and log a descriptive message plus the error, ensuring progress update
failures remain non-fatal but are recorded.

}
: undefined,
});

// Format actions as text with URLs (enables Slack unfurling)
const hasActions = result.actions.length > 0;
const responseText = hasActions
? formatActionsAsText(result.actions)
: result.text;
// Update the message with Claude's final summary
if (messageTs) {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: result.text,
});
} else {
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: result.text,
});
}

await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: responseText,
});
// Post side effects as a separate message
if (result.actions.length > 0) {
try {
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: formatSideEffectsMessage(result.actions),
});
} catch (err) {
console.error(
"[slack/process-assistant-message] Failed to post side effects:",
err,
);
}
}
} catch (err) {
console.error("[slack/process-assistant-message] Agent error:", err);

await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: `Sorry, something went wrong: ${err instanceof Error ? err.message : "Unknown error"}`,
});
} finally {
try {
await slack.assistant.threads.setStatus({
channel_id: event.channel,
const errorText = await formatErrorForSlack(err);
if (messageTs) {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: errorText,
});
} else {
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
status: "",
text: errorText,
});
} catch {}
}
Comment on lines 114 to +130
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Wrap error-handler Slack calls in try-catch to prevent masking original error.

If chat.update or chat.postMessage throws in the error handler, the original error context is lost. Consider wrapping these calls.

💡 Suggested fix
 	} catch (err) {
 		console.error("[slack/process-assistant-message] Agent error:", err);
 
 		const errorText = `Sorry, something went wrong: ${err instanceof Error ? err.message : "Unknown error"}`;
-		if (messageTs) {
-			await slack.chat.update({
-				channel: event.channel,
-				ts: messageTs,
-				text: errorText,
-			});
-		} else {
-			await slack.chat.postMessage({
-				channel: event.channel,
-				thread_ts: threadTs,
-				text: errorText,
-			});
+		try {
+			if (messageTs) {
+				await slack.chat.update({
+					channel: event.channel,
+					ts: messageTs,
+					text: errorText,
+				});
+			} else {
+				await slack.chat.postMessage({
+					channel: event.channel,
+					thread_ts: threadTs,
+					text: errorText,
+				});
+			}
+		} catch (postError) {
+			console.error(
+				"[slack/process-assistant-message] Failed to post error message:",
+				postError,
+			);
 		}
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (err) {
console.error("[slack/process-assistant-message] Agent error:", err);
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: `Sorry, something went wrong: ${err instanceof Error ? err.message : "Unknown error"}`,
});
} finally {
try {
await slack.assistant.threads.setStatus({
channel_id: event.channel,
const errorText = `Sorry, something went wrong: ${err instanceof Error ? err.message : "Unknown error"}`;
if (messageTs) {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: errorText,
});
} else {
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
status: "",
text: errorText,
});
} catch {}
}
} catch (err) {
console.error("[slack/process-assistant-message] Agent error:", err);
const errorText = `Sorry, something went wrong: ${err instanceof Error ? err.message : "Unknown error"}`;
try {
if (messageTs) {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: errorText,
});
} else {
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: errorText,
});
}
} catch (postError) {
console.error(
"[slack/process-assistant-message] Failed to post error message:",
postError,
);
}
}
🤖 Prompt for AI Agents
In
`@apps/api/src/app/api/integrations/slack/events/process-assistant-message/process-assistant-message.ts`
around lines 99 - 115, The current catch block logs the original error but calls
slack.chat.update/postMessage directly, which can throw and mask the original
error; wrap the calls to slack.chat.update (when messageTs) and
slack.chat.postMessage (otherwise) in their own try-catch inside the existing
catch so any Slack-send failure is caught and logged (e.g., console.error with
both the original error id and the secondary Slack error) without overwriting or
rethrowing the original error; reference the catch block handling messageTs,
slack.chat.update, slack.chat.postMessage, event.channel, and threadTs to locate
and modify the code.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type { AppMentionEvent } from "@slack/types";
import { db } from "@superset/db/client";
import { integrationConnections } from "@superset/db/schema";
import { and, eq } from "drizzle-orm";
import { runSlackAgent } from "../utils/run-agent";
import { formatActionsAsText } from "../utils/slack-blocks";
import { formatErrorForSlack, runSlackAgent } from "../utils/run-agent";
import { formatSideEffectsMessage } from "../utils/slack-blocks";
import { createSlackClient } from "../utils/slack-client";

interface ProcessMentionParams {
Expand Down Expand Up @@ -53,34 +53,91 @@ export async function processSlackMention({

const threadTs = event.thread_ts ?? event.ts;

// Post an initial message that gets updated as the agent works
let messageTs: string | undefined;
try {
const initialMsg = await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: "Thinking...",
});
messageTs = initialMsg.ts;
} catch (err) {
console.error(
"[slack/process-mention] Failed to post initial message:",
err,
);
}

Comment thread
coderabbitai[bot] marked this conversation as resolved.
try {
const result = await runSlackAgent({
prompt: event.text,
channelId: event.channel,
threadTs,
organizationId: connection.organizationId,
slackToken: connection.accessToken,
onProgress: messageTs
? async (status) => {
try {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: status,
});
} catch {
// Non-critical: progress updates are best-effort
}
Comment on lines +79 to +89
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd "process-mention.ts" --type f

Repository: superset-sh/superset

Length of output: 145


🏁 Script executed:

cat -n apps/api/src/app/api/integrations/slack/events/process-mention/process-mention.ts | sed -n '65,85p'

Repository: superset-sh/superset

Length of output: 695


Log progress update failures instead of silently swallowing them.

The silent catch block violates the coding guidelines requiring that errors are always logged with context. Add logging using the [domain/operation] prefix pattern.

💡 Suggested fix
-						} catch {
-							// Non-critical: progress updates are best-effort
-						}
+						} catch (error) {
+							console.warn(
+								"[slack/process-mention] Failed to update progress:",
+								error,
+							);
+						}
🤖 Prompt for AI Agents
In
`@apps/api/src/app/api/integrations/slack/events/process-mention/process-mention.ts`
around lines 71 - 81, The onProgress async handler currently swallows errors
from slack.chat.update; replace the empty catch with a logged error using the
repository's logger (e.g., logger or processLogger) and the
[slack/process-mention] prefix so failures are visible; specifically, in the
onProgress block (the function passed to onProgress that calls slack.chat.update
with channel: event.channel, ts: messageTs, text: status) catch the error and
call logger.error with a message like "[slack/process-mention] Failed to update
progress for message {messageTs} in channel {event.channel} (status={status})"
and include the caught error object, then continue without rethrowing.

}
: undefined,
});

// Format actions as text with URLs (enables Slack unfurling)
const hasActions = result.actions.length > 0;
const responseText = hasActions
? formatActionsAsText(result.actions)
: result.text;
// Update the message with Claude's final summary
if (messageTs) {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: result.text,
});
} else {
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: result.text,
});
}

await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: responseText,
});
// Post side effects as a separate message
if (result.actions.length > 0) {
try {
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: formatSideEffectsMessage(result.actions),
});
} catch (err) {
console.error(
"[slack/process-mention] Failed to post side effects:",
err,
);
}
}
} catch (err) {
console.error("[slack/process-mention] Agent error:", err);

await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: `Sorry, something went wrong: ${err instanceof Error ? err.message : "Unknown error"}`,
});
const errorText = await formatErrorForSlack(err);
if (messageTs) {
await slack.chat.update({
channel: event.channel,
ts: messageTs,
text: errorText,
});
} else {
await slack.chat.postMessage({
channel: event.channel,
thread_ts: threadTs,
text: errorText,
});
}
Comment on lines 124 to +140
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Wrap error-handler Slack calls in try-catch to prevent masking the original error.

Same issue as in process-assistant-message.ts. If the error notification fails, the original error context is lost.

💡 Suggested fix
 	} catch (err) {
 		console.error("[slack/process-mention] Agent error:", err);
 
 		const errorText = `Sorry, something went wrong: ${err instanceof Error ? err.message : "Unknown error"}`;
-		if (messageTs) {
-			await slack.chat.update({
-				channel: event.channel,
-				ts: messageTs,
-				text: errorText,
-			});
-		} else {
-			await slack.chat.postMessage({
-				channel: event.channel,
-				thread_ts: threadTs,
-				text: errorText,
-			});
+		try {
+			if (messageTs) {
+				await slack.chat.update({
+					channel: event.channel,
+					ts: messageTs,
+					text: errorText,
+				});
+			} else {
+				await slack.chat.postMessage({
+					channel: event.channel,
+					thread_ts: threadTs,
+					text: errorText,
+				});
+			}
+		} catch (postError) {
+			console.error(
+				"[slack/process-mention] Failed to post error message:",
+				postError,
+			);
 		}
 	}
🤖 Prompt for AI Agents
In
`@apps/api/src/app/api/integrations/slack/events/process-mention/process-mention.ts`
around lines 109 - 125, The current catch in process-mention.ts logs the
original error and then calls slack.chat.update or slack.chat.postMessage
directly, which can throw and mask the original error; wrap the notification
calls (the branches that call slack.chat.update and slack.chat.postMessage that
use messageTs and threadTs) in their own try-catch so any failure to send the
error notification is caught and logged (e.g., console.error with a clear tag
like "[slack/process-mention] Error sending error notification") without
overriding or swallowing the original err; after attempting the notification,
rethrow or propagate the original err as before so the original error context is
preserved.

} finally {
try {
await slack.reactions.remove({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export type { SlackAgentResult } from "./run-agent";
export { runSlackAgent } from "./run-agent";
export { formatErrorForSlack, runSlackAgent } from "./run-agent";
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,42 @@ interface RunSlackAgentParams {
threadTs: string;
organizationId: string;
slackToken: string;
onProgress?: (status: string) => void | Promise<void>;
}

export interface SlackAgentResult {
text: string;
actions: AgentAction[];
}

export async function formatErrorForSlack(error: unknown): Promise<string> {
const message =
error instanceof Error ? error.message : "Unknown error occurred";
try {
const anthropic = new Anthropic({ apiKey: env.ANTHROPIC_API_KEY });
const response = await anthropic.messages.create({
model: "claude-3-5-haiku-latest",
max_tokens: 256,
messages: [
{
role: "user",
content: `Rewrite this API error as a brief, friendly Slack message (1-2 sentences). No technical jargon, no JSON. If it's a rate limit, tell them to try again shortly.\n\nError: ${message}`,
},
],
});
const text = response.content.find(
(b): b is Anthropic.TextBlock => b.type === "text",
);
return text?.text ?? "Sorry, something went wrong. Please try again.";
} catch {
// Haiku itself failed (possibly also rate limited) — use static fallback
if (error instanceof Anthropic.APIError && error.status === 429) {
return "I'm a bit overloaded right now — please try again in a moment.";
}
return "Sorry, something went wrong. Please try again.";
}
}
Comment on lines +69 to +95
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Log Haiku fallback failures for observability.
The catch currently swallows errors, making formatting failures invisible.

💡 Suggested fix
-	} catch {
-		// Haiku itself failed (possibly also rate limited) — use static fallback
+	} catch (err) {
+		console.warn(
+			"[slack-agent/format-error] Failed to format error message:",
+			err,
+		);
+		// Haiku itself failed (possibly also rate limited) — use static fallback
 		if (error instanceof Anthropic.APIError && error.status === 429) {
 			return "I'm a bit overloaded right now — please try again in a moment.";
 		}
 		return "Sorry, something went wrong. Please try again.";
 	}

As per coding guidelines, "Never swallow errors silently; at minimum log them with context" and "Use prefixed console logging with pattern [domain/operation] message for all logging".

🤖 Prompt for AI Agents
In `@apps/api/src/app/api/integrations/slack/events/utils/run-agent/run-agent.ts`
around lines 69 - 95, In formatErrorForSlack, the catch block currently swallows
the failure and incorrectly inspects the outer `error`; change it to `catch
(err)` and log the caught error with a prefixed message (e.g.
console.error(`[slack/run-agent] formatErrorForSlack fallback failed:`, err, {
originalErrorMessage: message })) for observability, then use the caught error
when checking Anthropic.APIError/status 429 to return the rate-limit fallback,
otherwise return the static fallback string as before.


function getActionFromToolResult(
toolName: string,
// biome-ignore lint/suspicious/noExplicitAny: MCP result varies by tool
Expand Down Expand Up @@ -100,6 +129,19 @@ function getActionFromToolResult(
};
}

if (toolName === "delete_task" && data.deleted) {
return {
type: "task_deleted",
tasks: (
data.deleted as { id: string; slug: string; title: string }[]
).map((t) => ({
id: t.id,
slug: t.slug,
title: t.title,
})),
};
}

if (toolName === "create_workspace" && data.workspaceId) {
return {
type: "workspace_created",
Expand Down Expand Up @@ -149,6 +191,21 @@ function parseTextContent(content: any): Record<string, unknown> | null {
}
}

const TOOL_PROGRESS_STATUS: Record<string, string> = {
create_task: "Creating task...",
update_task: "Updating task...",
delete_task: "Deleting task...",
list_tasks: "Searching tasks...",
get_task: "Fetching task details...",
list_task_statuses: "Fetching statuses...",
create_workspace: "Creating workspace...",
list_workspaces: "Fetching workspaces...",
list_devices: "Fetching devices...",
list_projects: "Fetching projects...",
list_members: "Fetching team members...",
slack_get_channel_history: "Reading channel history...",
};

// Desktop-only tools that don't make sense in Slack context
const DENIED_SUPERSET_TOOLS = new Set([
"navigate_to_workspace",
Expand Down Expand Up @@ -271,7 +328,7 @@ export async function runSlackAgent(
{
type: "web_search_20250305" as const,
name: "web_search" as const,
max_uses: 3,
max_uses: 1,
},
];

Expand Down Expand Up @@ -313,6 +370,11 @@ Current context:

// pause_turn: server-side tool (web search) paused a long-running turn
if (response.stop_reason === "pause_turn") {
try {
await params.onProgress?.("Searching the web...");
} catch {
// Non-critical
}
Comment on lines +373 to +377
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Log onProgress failures in the pause_turn path.

This silent catch mirrors the issue already flagged in the tool execution loop. Progress failures should be logged for observability.

💡 Suggested fix
 			try {
 				await params.onProgress?.("Searching the web...");
-			} catch {
-				// Non-critical
+			} catch (error) {
+				console.warn(
+					"[slack-agent/on-progress] Failed to emit progress:",
+					error,
+				);
 			}

As per coding guidelines, "Never swallow errors silently; at minimum log them with context" and "Use prefixed console logging with pattern [domain/operation] message".

🤖 Prompt for AI Agents
In `@apps/api/src/app/api/integrations/slack/events/utils/run-agent/run-agent.ts`
around lines 345 - 349, The pause_turn path currently swallows errors from
params.onProgress (the try { await params.onProgress?.("Searching the web...");
} catch { /* Non-critical */ }) — change the catch to log the error instead of
dropping it: catch (err) { console.error("[slack/run-agent pause_turn]
onProgress failed:", err); } so failures in params.onProgress are observable and
include the error object and a clear prefix for context.

messages.push({ role: "assistant", content: response.content });
response = await anthropic.messages.create({
model: "claude-sonnet-4-5",
Expand All @@ -333,6 +395,18 @@ Current context:

for (const toolUse of toolUseBlocks) {
try {
const { toolName: rawToolName } = parseToolName(toolUse.name);
const progressStatus =
TOOL_PROGRESS_STATUS[toolUse.name] ??
TOOL_PROGRESS_STATUS[rawToolName] ??
"Working...";

try {
await params.onProgress?.(progressStatus);
} catch {
// Non-critical: don't fail the agent if progress update fails
}
Comment on lines +398 to +408
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Log onProgress failures instead of swallowing them silently.

This currently hides callback failures, making Slack update issues hard to diagnose.

💡 Suggested fix
-					try {
-						await params.onProgress?.(progressStatus);
-					} catch {
-						// Non-critical: don't fail the agent if progress update fails
-					}
+					try {
+						await params.onProgress?.(progressStatus);
+					} catch (error) {
+						console.warn(
+							"[slack-agent/on-progress] Failed to emit progress:",
+							error,
+						);
+					}

As per coding guidelines, "Never swallow errors silently; at minimum log them with context" and "Use prefixed console logging with pattern [domain/operation] message".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { toolName: rawToolName } = parseToolName(toolUse.name);
const progressStatus =
TOOL_PROGRESS_STATUS[toolUse.name] ??
TOOL_PROGRESS_STATUS[rawToolName] ??
"Working...";
try {
await params.onProgress?.(progressStatus);
} catch {
// Non-critical: don't fail the agent if progress update fails
}
const { toolName: rawToolName } = parseToolName(toolUse.name);
const progressStatus =
TOOL_PROGRESS_STATUS[toolUse.name] ??
TOOL_PROGRESS_STATUS[rawToolName] ??
"Working...";
try {
await params.onProgress?.(progressStatus);
} catch (error) {
console.warn(
"[slack-agent/on-progress] Failed to emit progress:",
error,
);
}
🤖 Prompt for AI Agents
In `@apps/api/src/app/api/integrations/slack/events/utils/run-agent/run-agent.ts`
around lines 341 - 351, The try/catch around invoking params.onProgress
currently swallows failures; update the catch to log the error instead of
ignoring it: when calling params.onProgress(progressStatus) (in the run-agent
function that uses parseToolName, TOOL_PROGRESS_STATUS and computes
progressStatus), catch any thrown error and call the logger (or console) with a
prefixed message like "[slack/run-agent onProgress]" including progressStatus,
toolUse.name/rawToolName and the caught error details so failures are recorded
for diagnostics.


let resultContent: string;

if (toolUse.name === "slack_get_channel_history") {
Expand Down Expand Up @@ -407,9 +481,12 @@ Current context:
});
}

const textBlock = response.content.find(
// Use the last text block — server-side tools like web_search produce
// multiple text blocks (preamble + synthesis) and we want the final one.
const textBlocks = response.content.filter(
(b): b is Anthropic.TextBlock => b.type === "text",
);
const textBlock = textBlocks.at(-1);

return {
text: textBlock?.text ?? "Done!",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export type { AgentAction } from "./slack-blocks";
export { formatActionsAsText } from "./slack-blocks";
export { formatActionsAsText, formatSideEffectsMessage } from "./slack-blocks";
Loading