All files / api/src/v1 index.ts

91.56% Statements 76/83
100% Branches 0/0
0% Functions 0/1
91.56% Lines 76/83

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 1411x 1x           1x 1x 1x   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x   1x     1x     1x   1x     1x               1x   1x     1x 1x 1x     1x   1x 1x 1x 1x 1x     1x       1x       1x       1x     1x     1x 1x 1x   1x 1x 1x   1x 1x 1x 1x 1x     1x     1x     1x     1x     1x   1x 1x 1x 1x         1x 1x 1x 1x 1x         1x  
import { initializeModelCapabilities } from '@api/ai-providers/initialize-capabilities';
import {
  resolveCacheConnector,
  resolveLogsConnector,
  resolveUserDataConnector,
} from '@api/connectors';
// import { argumentCorrectnessEvaluationConnector } from '@api/connectors/evaluations/argument-correctness';
import { conversationCompletenessEvaluationConnector } from '@api/connectors/evaluations/conversation-completeness';
import { knowledgeRetentionEvaluationConnector } from '@api/connectors/evaluations/knowledge-retention';
import { latencyEvaluationConnector } from '@api/connectors/evaluations/latency/latency';
// import { roleAdherenceEvaluationConnector } from '@api/connectors/evaluations/role-adherence';
import { taskCompletionEvaluationConnector } from '@api/connectors/evaluations/task-completion';
import { toolCorrectnessEvaluationConnector } from '@api/connectors/evaluations/tool-correctness';
import { turnRelevancyEvaluationConnector } from '@api/connectors/evaluations/turn-relevancy';
import { getAllowedOrigins } from '@api/constants';
import { agentAndSkillMiddleware } from '@api/middlewares/agent-and-skill';
import { authenticatedMiddleware } from '@api/middlewares/auth';
import { cacheMiddleware } from '@api/middlewares/cache';
import { evaluationMethodConnectors } from '@api/middlewares/evaluations';
import { hooksMiddleware } from '@api/middlewares/hooks';
import { logsMiddleware } from '@api/middlewares/logs';
import { saConfigurationInjectorMiddleware } from '@api/middlewares/super-agents-configuration';
import { toolMiddleware } from '@api/middlewares/tool';
import { userDataMiddleware } from '@api/middlewares/user-data';
import { commonVariablesMiddleware } from '@api/middlewares/variables';
import type { AppContext, AppEnv, AppHono } from '@api/types/hono';
import { chatRouter } from '@api/v1/chat';
import { completionsRouter } from '@api/v1/completions';
import { embeddingsRouter } from '@api/v1/embeddings';
import { responsesRouter } from '@api/v1/responses';
import { superAgentsRouter } from '@api/v1/super-agents';
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { createFactory } from 'hono/factory';
import { logger } from 'hono/logger';
import { prettyJSON } from 'hono/pretty-json';
 
const factory = createFactory<AppEnv>();
 
/** Path prefix that scopes a gateway request to an agent and one of its skills. */
const AGENT_SKILL_BASE_PATH = '/agents/:agent_name/skills/:skill_name';
 
// Lazy initialization of model capabilities (Cloudflare Workers can't do this at module load time)
let modelCapabilitiesInitialized = false;
 
const app: AppHono = new Hono<AppEnv>().basePath('/v1');
 
// Initialize model capabilities on first request
app.use('*', async (_c, next) => {
  if (!modelCapabilitiesInitialized) {
    initializeModelCapabilities();
    modelCapabilitiesInitialized = true;
  }
  await next();
});
 
app.get('/', (c) => c.text('Super Agents'));
 
app.use('*', logger());
 
// CORS middleware for cross-origin requests from the web app
app.use(
  '*',
  cors({
    // `origin` receives the request context, so the allowed list is resolved
    // per request rather than captured at module load.
    origin: (origin, c) =>
      getAllowedOrigins(c as AppContext).includes(origin) ? origin : null,
    credentials: true,
    allowHeaders: ['Content-Type', 'Authorization', 'sa-config'],
    allowMethods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],
  }),
);
 
// Use prettyJSON middleware for all routes
app.use('*', prettyJSON());
 
// Keep this middleware before the other middlewares
// so that the common variables are available to the other middlewares
app.use('*', commonVariablesMiddleware);
 
// Keep this middleware before agent and skill middleware
// Use user data middleware for all routes
app.use('*', userDataMiddleware(factory, resolveUserDataConnector));
 
// Use logs middleware for all routes
// Runs skill optimizer after processing logs
app.use('*', logsMiddleware(factory, resolveLogsConnector));
 
// Use hooks middleware for all routes
app.use('*', hooksMiddleware(factory, []));
 
// Use evaluation middleware for all routes
app.use(
  '*',
  evaluationMethodConnectors(factory, [
    // argumentCorrectnessEvaluationConnector,
    conversationCompletenessEvaluationConnector,
    knowledgeRetentionEvaluationConnector,
    latencyEvaluationConnector,
    // roleAdherenceEvaluationConnector,
    taskCompletionEvaluationConnector,
    toolCorrectnessEvaluationConnector,
    turnRelevancyEvaluationConnector,
  ]),
);
 
// Use cache middleware for all routes
app.use('*', cacheMiddleware(factory, resolveCacheConnector));
 
// Use authenticated middleware for all routes
app.use('*', authenticatedMiddleware(factory));
 
// Use agent and skill middleware for all routes
app.use('*', agentAndSkillMiddleware);
 
// Use Super Agents configuration injector middleware for all routes
app.use('*', saConfigurationInjectorMiddleware);
 
// Use tool middleware for all routes
app.use(toolMiddleware);
 
app.route('/chat', chatRouter);
app.route('/completions', completionsRouter);
app.route('/responses', responsesRouter);
app.route('/embeddings', embeddingsRouter);
 
// The same endpoints scoped to an agent and a skill through the path, so that
// OpenAI-compatible clients can point their base URL at a single skill instead
// of sending the names in the `sa-config` header.
app.route(`${AGENT_SKILL_BASE_PATH}/chat`, chatRouter);
app.route(`${AGENT_SKILL_BASE_PATH}/completions`, completionsRouter);
app.route(`${AGENT_SKILL_BASE_PATH}/responses`, responsesRouter);
app.route(`${AGENT_SKILL_BASE_PATH}/embeddings`, embeddingsRouter);
const superAgentsRoute = app.route('/super-agents', superAgentsRouter);
 
export type SuperAgentsRoute = typeof superAgentsRoute;
 
// Export the app for Cloudflare Workers
export default app;