Spaces:
Sleeping
Sleeping
File size: 3,948 Bytes
a00031a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | import { randomUUID } from 'node:crypto';
import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';
import { buildAgentCard, resolveTemplateAgentConfig, TEMPLATE_AGENT_ID, TEMPLATE_AGENT_NAME } from './metadata.js';
import { executeTemplateAgentAction, type TemplateAgentAction } from './runtime.js';
type RpcRequest = { jsonrpc?: string; id?: string | number | null; method?: string; params?: Record<string, unknown> };
export function createTemplateAgentHttpServer() {
const config = resolveTemplateAgentConfig();
const server = createServer((request, response) => void handleRequest(request, response, config.publicBaseUrl));
return {
server,
async start() {
await new Promise<void>((resolve, reject) => {
server.once('error', reject);
server.listen(config.port, config.host, () => resolve());
});
},
async stop() {
await new Promise<void>((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
},
};
}
async function handleRequest(request: IncomingMessage, response: ServerResponse, baseUrl: string) {
if (request.method === 'GET' && request.url === '/health') return sendJson(response, 200, { ok: true, agent: TEMPLATE_AGENT_ID });
if (request.method === 'GET' && request.url === '/') return sendHtml(response, 200, `<html><body><h1>${TEMPLATE_AGENT_NAME}</h1></body></html>`);
if (request.method === 'GET' && (request.url === '/.well-known/agent-card.json' || request.url === '/.well-known/agent.json')) {
return sendJson(response, 200, buildAgentCard(baseUrl));
}
if (request.method === 'POST' && request.url === '/a2a/v1') {
const rpc = ((await readJson(request)) || {}) as RpcRequest;
if (rpc.method === 'agent/getCard') return sendJson(response, 200, { jsonrpc: '2.0', id: rpc.id ?? null, result: buildAgentCard(baseUrl) });
if (rpc.method === 'message/send') {
const action = parseAction((rpc.params?.message as { parts?: Array<{ text?: string }> } | undefined)?.parts?.map((part) => part.text || '').join(' ').trim() || '');
const result = await executeTemplateAgentAction(action);
return sendJson(response, 200, {
jsonrpc: '2.0',
id: rpc.id ?? null,
result: {
id: randomUUID(),
kind: 'task',
status: { state: 'completed', timestamp: new Date().toISOString(), message: { role: 'agent', parts: [{ type: 'text', text: 'done' }] } },
artifacts: [{ id: randomUUID(), name: action.action, description: action.action, parts: [{ type: 'data', data: result }] }],
metadata: { action: action.action },
},
});
}
}
sendJson(response, 404, { error: 'not_found' });
}
function parseAction(text: string): TemplateAgentAction {
const value = text.toLowerCase();
if (value === 'sin.code.integration health') return { action: 'sin.code.integration.health' };
if (value === 'sin.code.integration room13 claim') return { action: 'sin.code.integration.room13.claim', confirm: true };
if (value === 'sin.code.integration onboarding status') return { action: 'sin.code.integration.onboarding.status' };
return { action: 'agent.help' };
}
async function readJson(request: IncomingMessage) {
const chunks: Buffer[] = [];
for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
const raw = Buffer.concat(chunks).toString('utf8').trim();
return raw ? JSON.parse(raw) : null;
}
function sendJson(response: ServerResponse, statusCode: number, payload: unknown) {
response.statusCode = statusCode;
response.setHeader('content-type', 'application/json; charset=utf-8');
response.end(JSON.stringify(payload, null, 2));
}
function sendHtml(response: ServerResponse, statusCode: number, payload: string) {
response.statusCode = statusCode;
response.setHeader('content-type', 'text/html; charset=utf-8');
response.end(payload);
}
|