diff --git a/lambda/slack-processor/index.ts b/lambda/slack-processor/index.ts index 015e3ad..990f371 100644 --- a/lambda/slack-processor/index.ts +++ b/lambda/slack-processor/index.ts @@ -41,7 +41,7 @@ async function postToSlack( channel: string, text: string, threadTs?: string, -): Promise { +): Promise { const body: Record = { channel, text }; if (threadTs) body.thread_ts = threadTs; @@ -55,8 +55,29 @@ async function postToSlack( }); if (!res.ok) throw new Error(`Slack HTTP error ${res.status}`); - const data = (await res.json()) as { ok: boolean; error?: string }; + const data = (await res.json()) as { ok: boolean; ts?: string; error?: string }; if (!data.ok) throw new Error(`Slack API error: ${data.error}`); + return data.ts!; +} + +async function updateSlack( + token: string, + channel: string, + ts: string, + text: string, +): Promise { + const res = await fetch('https://slack.com/api/chat.update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ channel, ts, text }), + }); + + if (!res.ok) throw new Error(`Slack HTTP error ${res.status}`); + const data = (await res.json()) as { ok: boolean; error?: string }; + if (!data.ok) throw new Error(`Slack update error: ${data.error}`); } // Reuse the most recent Bedrock session if there's been activity in the last 30 minutes. @@ -113,6 +134,14 @@ export const handler = async (event: ProcessorEvent): Promise => { resolveSessionId(userId), ]); + // Post placeholder immediately so the user sees a response while the agent thinks + const placeholderTs = await postToSlack( + credentials.botToken, + channelId, + '_Sea Haven Assistant is thinking..._', + threadTs ?? ts, + ); + let answer: string; try { answer = await invokeAgent(sessionId, text); @@ -121,7 +150,7 @@ export const handler = async (event: ProcessorEvent): Promise => { answer = 'Sorry, I encountered an error processing your request. Please try again in a moment.'; } - await postToSlack(credentials.botToken, channelId, answer, threadTs ?? ts); + await updateSlack(credentials.botToken, channelId, placeholderTs, answer); const now = new Date().toISOString(); const ttl = Math.floor(Date.now() / 1000) + 90 * 24 * 60 * 60; // 90-day TTL diff --git a/lib/constructs/bedrock-agent.ts b/lib/constructs/bedrock-agent.ts index 00f600b..9f8f7ad 100644 --- a/lib/constructs/bedrock-agent.ts +++ b/lib/constructs/bedrock-agent.ts @@ -189,7 +189,7 @@ Keep responses concise, professional, and actionable.`; }, location: { type: 'string', - description: 'City, address, or area to search near (e.g., "Seattle WA", "Chicago IL")', + description: 'Location to search near — can be a city, address, zip code, or facility/business name (e.g., "Seattle WA", "Amazon BFI9", "3230 International Pl DuPont WA"). Pass whatever location context the user provided; Google Maps will resolve it.', required: true, }, }, @@ -205,7 +205,7 @@ Keep responses concise, professional, and actionable.`; this.agentAlias = new bedrock.CfnAgentAlias(this, 'AgentAlias', { agentId: this.agent.attrAgentId, agentAliasName: 'live', - description: 'Production alias — seahaven-assistant v2 (Claude Sonnet 4.5)', + description: 'Production alias — seahaven-assistant v3 (flexible location lookup)', }); } }