Skip to content

Commit 4fcebad

Browse files
committed
feat: add ping router
1 parent 16ffab4 commit 4fcebad

File tree

1 file changed

+85
-5
lines changed
  • examples/agent-in-aws-bedrock-agent-core/src

1 file changed

+85
-5
lines changed

examples/agent-in-aws-bedrock-agent-core/src/server.ts

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,42 @@ import { StreamingAgent } from '@astack-tech/components/agents';
66
import { Deepseek } from '@astack-tech/integrations/model-provider';
77
import type { ModelProvider } from '@astack-tech/components';
88

9+
// Enhanced logging function with immediate flush
10+
const log = (...args: unknown[]) => {
11+
const timestamp = new Date().toISOString();
12+
console.log(`[${timestamp}]`, ...args);
13+
// Force flush to stdout for CloudWatch
14+
if (process.stdout.write) {
15+
process.stdout.write('');
16+
}
17+
};
18+
19+
const logError = (...args: unknown[]) => {
20+
const timestamp = new Date().toISOString();
21+
console.error(`[${timestamp}] ERROR:`, ...args);
22+
if (process.stderr.write) {
23+
process.stderr.write('');
24+
}
25+
};
26+
927
// Initialize Hono app
1028
const app = new Hono();
1129

30+
// Global request logger middleware
31+
app.use('*', async (c, next) => {
32+
const method = c.req.method;
33+
const path = c.req.path;
34+
const startTime = Date.now();
35+
36+
log(`➡️ ${method} ${path}`);
37+
log(`📋 Headers:`, JSON.stringify(c.req.header(), null, 2));
38+
39+
await next();
40+
41+
const duration = Date.now() - startTime;
42+
log(`⬅️ ${method} ${path} - Status: ${c.res.status} - Duration: ${duration}ms`);
43+
});
44+
1245
// Create Deepseek model instance
1346
const createModel = (): ModelProvider => {
1447
const apiKey = process.env.DEEPSEEK_API_KEY;
@@ -56,26 +89,60 @@ app.get('/health', (c: Context) => {
5689
});
5790
});
5891

92+
// Ping endpoint for AgentCore health checks
93+
app.get('/ping', (c: Context) => {
94+
return c.json({ status: 'healthy' });
95+
});
96+
5997
// AWS Bedrock AgentCore invocations endpoint (port 8080 required)
6098
app.post('/invocations', async (c: Context) => {
6199
try {
62-
const request: BedrockRequest = await c.req.json();
100+
log('🔍 Parsing request body...');
101+
const rawBody = await c.req.text();
102+
log('📦 Raw request body:', rawBody);
103+
104+
let request: BedrockRequest;
105+
try {
106+
request = JSON.parse(rawBody);
107+
log('✅ Request parsed successfully:', JSON.stringify(request, null, 2));
108+
} catch (parseError) {
109+
logError('❌ JSON parse error:', parseError);
110+
return c.json(
111+
{
112+
error: 'Invalid JSON in request body',
113+
details: parseError instanceof Error ? parseError.message : 'Unknown parse error',
114+
receivedBody: rawBody.substring(0, 500), // First 500 chars for debugging
115+
},
116+
400
117+
);
118+
}
63119

64120
// Extract messages from request
65121
const messages = request.messages || [
66122
{ role: 'user' as const, content: request.inputText || '' },
67123
];
68124

125+
log('💬 Processing messages:', JSON.stringify(messages, null, 2));
126+
69127
const agent = getAgent();
128+
log('🤖 Agent instance ready');
70129

71130
// Stream response using SSE format
131+
log('🌊 Starting SSE stream...');
72132
return streamSSE(c, async (stream: SSEStreamingApi) => {
73133
try {
134+
log('📡 Beginning agent execution...');
135+
let chunkCount = 0;
136+
74137
for await (const chunk of agent.runStream({ messages })) {
138+
chunkCount++;
139+
log(`📨 Chunk ${chunkCount}:`, chunk.type);
140+
75141
// Transform AStack chunks to SSE events
76142
switch (chunk.type) {
77143
case 'assistant_message':
78144
if (chunk.content) {
145+
log(`💬 Assistant message: "${chunk.content.substring(0, 100)}..."`);
79146
await stream.writeSSE({
80147
event: 'message',
81148
data: JSON.stringify({
@@ -87,6 +154,7 @@ app.post('/invocations', async (c: Context) => {
87154
break;
88155

89156
case 'completed':
157+
log('✅ Stream completed:', chunk.finalMessage?.substring(0, 100));
90158
await stream.writeSSE({
91159
event: 'done',
92160
data: JSON.stringify({
@@ -97,6 +165,7 @@ app.post('/invocations', async (c: Context) => {
97165
break;
98166

99167
case 'error':
168+
logError('❌ Stream error:', chunk.error);
100169
await stream.writeSSE({
101170
event: 'error',
102171
data: JSON.stringify({
@@ -106,19 +175,25 @@ app.post('/invocations', async (c: Context) => {
106175
break;
107176
}
108177
}
178+
179+
log(`✨ Stream finished successfully with ${chunkCount} chunks`);
109180
} catch (error) {
181+
logError('❌ Stream processing error:', error);
110182
await stream.writeSSE({
111183
event: 'error',
112184
data: JSON.stringify({
113185
error: error instanceof Error ? error.message : 'Stream error',
186+
stack: error instanceof Error ? error.stack : undefined,
114187
}),
115188
});
116189
}
117190
});
118191
} catch (error) {
192+
logError('❌ Request handling error:', error);
119193
return c.json(
120194
{
121195
error: error instanceof Error ? error.message : 'Invalid request',
196+
stack: error instanceof Error ? error.stack : undefined,
122197
},
123198
400
124199
);
@@ -136,9 +211,14 @@ serve(
136211
hostname: HOST,
137212
},
138213
() => {
139-
console.log(`🚀 AStack Bedrock Agent Runtime started`);
140-
console.log(`📡 Listening on ${HOST}:${PORT}`);
141-
console.log(`🔗 Health: http://localhost:${PORT}/health`);
142-
console.log(`🤖 Invocations: http://localhost:${PORT}/invocations`);
214+
log('🚀 AStack Bedrock Agent Runtime started');
215+
log(`📡 Listening on ${HOST}:${PORT}`);
216+
log(`🔗 Health: http://localhost:${PORT}/health`);
217+
log(`🤖 Invocations: http://localhost:${PORT}/invocations`);
218+
log('🔧 Environment:', {
219+
NODE_ENV: process.env.NODE_ENV,
220+
HAS_DEEPSEEK_KEY: !!process.env.DEEPSEEK_API_KEY,
221+
});
222+
log('✨ Ready to handle requests');
143223
}
144224
);

0 commit comments

Comments
 (0)