mirror of
https://github.com/kennethnym/aris.git
synced 2026-06-15 03:51:18 +01:00
151 lines
4.5 KiB
TypeScript
151 lines
4.5 KiB
TypeScript
import { Hono } from "hono"
|
|
import { cors } from "hono/cors"
|
|
|
|
import { registerAdminHttpHandlers } from "./admin/http.ts"
|
|
import { createQueryDebugTools } from "./agent/debug-tools.ts"
|
|
import { registerAgentHttpHandlers, registerDebugAgentHttpHandlers } from "./agent/http.ts"
|
|
import { PiQueryAgent } from "./agent/pi-query-agent.ts"
|
|
import { createRequireAdmin } from "./auth/admin-middleware.ts"
|
|
import { registerAuthHandlers } from "./auth/http.ts"
|
|
import { createAuth } from "./auth/index.ts"
|
|
import { createRequireSession } from "./auth/session-middleware.ts"
|
|
import { CalDavSourceProvider } from "./caldav/provider.ts"
|
|
import { createDatabase } from "./db/index.ts"
|
|
import { registerFeedHttpHandlers } from "./engine/http.ts"
|
|
import { createFeedEnhancer } from "./enhancement/enhance-feed.ts"
|
|
import { createLlmClient } from "./enhancement/llm-client.ts"
|
|
import { GoogleMapsSourceProvider } from "./google-maps/provider.ts"
|
|
import { CredentialEncryptor } from "./lib/crypto.ts"
|
|
import { ensureEnv } from "./lib/env.ts"
|
|
import { registerLocationHttpHandlers } from "./location/http.ts"
|
|
import { LocationSourceProvider } from "./location/provider.ts"
|
|
import { ReminderSourceProvider } from "./reminders/provider.ts"
|
|
import { UserSessionManager } from "./session/index.ts"
|
|
import { registerSourcesHttpHandlers } from "./sources/http.ts"
|
|
import { TflSourceProvider } from "./tfl/provider.ts"
|
|
import { WeatherSourceProvider } from "./weather/provider.ts"
|
|
import { WebSearchSourceProvider } from "./web-search/provider.ts"
|
|
|
|
function main() {
|
|
const env = ensureEnv(process.env)
|
|
|
|
const { db, close: closeDb } = createDatabase(env.databaseUrl)
|
|
const auth = createAuth(db)
|
|
|
|
const feedEnhancer = createFeedEnhancer({
|
|
client: createLlmClient({
|
|
apiKey: env.openrouterApiKey,
|
|
model: env.openrouterModel,
|
|
}),
|
|
})
|
|
|
|
const credentialEncryptor = new CredentialEncryptor(env.credentialEncryptionKey)
|
|
|
|
const sessionManager = new UserSessionManager({
|
|
db,
|
|
providers: [
|
|
new CalDavSourceProvider(),
|
|
new LocationSourceProvider(),
|
|
new ReminderSourceProvider({ db }),
|
|
new WeatherSourceProvider({
|
|
credentials: {
|
|
privateKey: env.weatherkitPrivateKey,
|
|
keyId: env.weatherkitKeyId,
|
|
teamId: env.weatherkitTeamId,
|
|
serviceId: env.weatherkitServiceId,
|
|
},
|
|
}),
|
|
new TflSourceProvider({ apiKey: env.tflApiKey }),
|
|
new WebSearchSourceProvider({ apiKey: env.exaApiKey }),
|
|
new GoogleMapsSourceProvider({
|
|
apiKey: env.googleMapsApiKey,
|
|
}),
|
|
],
|
|
feedEnhancer,
|
|
credentialEncryptor,
|
|
})
|
|
const piApiKey = process.env.PI_API_KEY ?? env.openrouterApiKey
|
|
const queryAgent = new PiQueryAgent({
|
|
sessionManager,
|
|
modelProvider: process.env.PI_MODEL_PROVIDER ?? "openrouter",
|
|
modelId: process.env.PI_MODEL ?? env.openrouterModel ?? "z-ai/glm-4.7-flash",
|
|
apiKey: piApiKey,
|
|
})
|
|
if (!piApiKey) {
|
|
console.warn("[query] PI_API_KEY or OPENROUTER_API_KEY not set — query agent unavailable")
|
|
}
|
|
|
|
const app = new Hono()
|
|
|
|
const isDev = process.env.NODE_ENV !== "production"
|
|
const isDebugMode = isDev
|
|
const allowedOrigins = process.env.CORS_ORIGINS?.split(",").map((o) => o.trim()) ?? []
|
|
|
|
function resolveOrigin(origin: string): string | undefined {
|
|
if (isDev) return origin
|
|
return allowedOrigins.includes(origin) ? origin : undefined
|
|
}
|
|
|
|
app.use(
|
|
"/api/auth/*",
|
|
cors({
|
|
origin: resolveOrigin,
|
|
allowHeaders: ["Content-Type", "Authorization"],
|
|
allowMethods: ["POST", "GET", "OPTIONS"],
|
|
exposeHeaders: ["Content-Length"],
|
|
maxAge: 600,
|
|
credentials: true,
|
|
}),
|
|
)
|
|
|
|
app.use(
|
|
"*",
|
|
cors({
|
|
origin: resolveOrigin,
|
|
credentials: true,
|
|
}),
|
|
)
|
|
|
|
app.get("/health", (c) => c.json({ status: "ok" }))
|
|
|
|
const authSessionMiddleware = createRequireSession(auth)
|
|
const adminMiddleware = createRequireAdmin(auth)
|
|
|
|
registerAuthHandlers(app, auth)
|
|
|
|
registerFeedHttpHandlers(app, {
|
|
sessionManager,
|
|
authSessionMiddleware,
|
|
})
|
|
registerLocationHttpHandlers(app, { sessionManager, authSessionMiddleware })
|
|
registerSourcesHttpHandlers(app, { sessionManager, authSessionMiddleware })
|
|
registerAgentHttpHandlers(app, {
|
|
queryAgent,
|
|
authSessionMiddleware,
|
|
})
|
|
if (isDebugMode) {
|
|
registerDebugAgentHttpHandlers(app, {
|
|
authSessionMiddleware,
|
|
debugTools: createQueryDebugTools(sessionManager),
|
|
debug: isDebugMode,
|
|
})
|
|
}
|
|
registerAdminHttpHandlers(app, { sessionManager, adminMiddleware, db })
|
|
|
|
process.on("SIGTERM", async () => {
|
|
queryAgent.dispose()
|
|
await closeDb()
|
|
process.exit(0)
|
|
})
|
|
|
|
return app
|
|
}
|
|
|
|
const app = main()
|
|
|
|
export default {
|
|
port: 3000,
|
|
hostname: "0.0.0.0",
|
|
fetch: app.fetch,
|
|
}
|