import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager'; const secretsClient = new SecretsManagerClient({}); interface SlackCredentials { botToken: string; signingSecret: string; } let cachedCredentials: SlackCredentials | undefined; async function getSlackCredentials(): Promise { if (!cachedCredentials) { const res = await secretsClient.send( new GetSecretValueCommand({ SecretId: process.env.SLACK_SECRET_ARN! }), ); cachedCredentials = JSON.parse(res.SecretString!) as SlackCredentials; } return cachedCredentials; } interface AppHomeEvent { userId: string; } export const handler = async (event: AppHomeEvent): Promise => { const credentials = await getSlackCredentials(); const blocks = [ { type: 'header', text: { type: 'plain_text', text: "Hi, I'm Alex!", emoji: true }, }, { type: 'section', text: { type: 'mrkdwn', text: "I'm Sea Haven's internal AI assistant. Here's what I can help you with:", }, }, { type: 'divider' }, { type: 'section', text: { type: 'mrkdwn', text: '*Vendor Lookup*\nFind existing vendors in QuickBooks or discover new ones nearby.\n_Try: "Find me a plumber near ABE2"_', }, }, { type: 'section', text: { type: 'mrkdwn', text: '*Work Order Status*\nLook up any work order by its WO number.\n_Try: "What\'s the status of WO 10046966057?"_', }, }, { type: 'section', text: { type: 'mrkdwn', text: '*Purchase Order Details*\nLook up PO status, line items, and shipping info.\n_Try: "Show me PO 2D-20023475"_', }, }, { type: 'section', text: { type: 'mrkdwn', text: '*Payment & Invoice Status*\nCheck if a vendor has been paid or if an invoice is scheduled.\n_Try: "Has invoice 12345 been paid?" or "What payments went to Acme?"_', }, }, { type: 'section', text: { type: 'mrkdwn', text: '*Site Lookups*\nFind the address and details for any Amazon facility by site code.\n_Try: "Where is DFW6?" or "List all sites in Texas"_', }, }, { type: 'section', text: { type: 'mrkdwn', text: '*Company Policies & SOPs*\nAnswer questions about the employee handbook, SA8000 compliance, and SOPs.\n_Try: "What\'s our PTO policy?"_', }, }, { type: 'divider' }, { type: 'section', text: { type: 'mrkdwn', text: '*How to reach me:*\n• Send me a DM right here\n• @mention me in any channel I\'m in', }, }, { type: 'context', elements: [ { type: 'mrkdwn', text: "I only know about data in our systems. If I can't answer something, I'll let you know — and my team reviews those gaps regularly to keep improving.", }, ], }, ]; const res = await fetch('https://slack.com/api/views.publish', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${credentials.botToken}`, }, body: JSON.stringify({ user_id: event.userId, view: { type: 'home', blocks }, }), }); if (!res.ok) { throw new Error(`Slack views.publish HTTP error: ${res.status}`); } const data = (await res.json()) as { ok: boolean; error?: string }; if (!data.ok) { throw new Error(`Slack views.publish API error: ${data.error}`); } };