refactor: move routes under /tori/ prefix and add /api/obj mount
Routes now live at /tori/api, /ws/tori, and static files at /tori/. Root / redirects to /tori/. Object storage mounted at /api/obj. Dev proxy updated accordingly.
This commit is contained in:
parent
84779a0527
commit
ae72e699f4
20
src/main.rs
20
src/main.rs
@ -5,7 +5,9 @@ mod kb;
|
||||
mod llm;
|
||||
mod exec;
|
||||
pub mod state;
|
||||
mod template;
|
||||
mod timer;
|
||||
mod tools;
|
||||
mod ws;
|
||||
|
||||
use std::sync::Arc;
|
||||
@ -19,6 +21,7 @@ pub struct AppState {
|
||||
pub config: Config,
|
||||
pub agent_mgr: Arc<agent::AgentManager>,
|
||||
pub kb: Option<Arc<kb::KbManager>>,
|
||||
pub obj_root: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Deserialize)]
|
||||
@ -83,17 +86,28 @@ async fn main() -> anyhow::Result<()> {
|
||||
// Resume incomplete workflows after restart
|
||||
resume_workflows(database.pool.clone(), agent_mgr.clone()).await;
|
||||
|
||||
let obj_root = std::env::var("OBJ_ROOT").unwrap_or_else(|_| "/data/obj".to_string());
|
||||
|
||||
let state = Arc::new(AppState {
|
||||
db: database,
|
||||
config: config.clone(),
|
||||
agent_mgr: agent_mgr.clone(),
|
||||
kb: kb_arc,
|
||||
obj_root: obj_root.clone(),
|
||||
});
|
||||
|
||||
let app = Router::new()
|
||||
.nest("/api", api::router(state))
|
||||
.nest("/ws", ws::router(agent_mgr))
|
||||
.fallback_service(ServeDir::new("web/dist").fallback(ServeFile::new("web/dist/index.html")))
|
||||
.nest("/tori/api", api::router(state))
|
||||
.nest("/api/obj", api::obj::router(obj_root.clone()))
|
||||
.route("/api/obj/", axum::routing::get({
|
||||
let r = obj_root;
|
||||
move || api::obj::root_listing(r)
|
||||
}))
|
||||
.nest("/ws/tori", ws::router(agent_mgr))
|
||||
.nest_service("/tori", ServeDir::new("web/dist").fallback(ServeFile::new("web/dist/index.html")))
|
||||
.route("/", axum::routing::get(|| async {
|
||||
axum::response::Redirect::permanent("/tori/")
|
||||
}))
|
||||
.layer(CorsLayer::permissive());
|
||||
|
||||
let addr = format!("{}:{}", &config.server.host, config.server.port);
|
||||
|
||||
8
web/package-lock.json
generated
8
web/package-lock.json
generated
@ -1127,6 +1127,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.11.0.tgz",
|
||||
"integrity": "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
@ -1324,6 +1325,7 @@
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.2.tgz",
|
||||
"integrity": "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@chevrotain/cst-dts-gen": "11.1.2",
|
||||
"@chevrotain/gast": "11.1.2",
|
||||
@ -1374,6 +1376,7 @@
|
||||
"version": "3.33.1",
|
||||
"resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz",
|
||||
"integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
@ -1740,6 +1743,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
@ -2136,6 +2140,7 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -2314,6 +2319,7 @@
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"devOptional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@ -2350,6 +2356,7 @@
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
|
||||
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.27.0",
|
||||
"fdir": "^6.5.0",
|
||||
@ -2466,6 +2473,7 @@
|
||||
"version": "3.5.29",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.29.tgz",
|
||||
"integrity": "sha512-BZqN4Ze6mDQVNAni0IHeMJ5mwr8VAJ3MQC9FmprRhcBYENw+wOAAjRj8jfmN6FLl0j96OXbR+CjWhmAmM+QGnA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.29",
|
||||
"@vue/compiler-sfc": "3.5.29",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { Project, Workflow, ExecutionLogEntry, Comment, Timer, KbArticle, KbArticleSummary, PlanStepInfo, LlmCallLogEntry } from './types'
|
||||
|
||||
const BASE = '/api'
|
||||
const BASE = `${import.meta.env.BASE_URL.replace(/\/$/, '')}/api`
|
||||
|
||||
async function request<T>(path: string, options?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${BASE}${path}`, {
|
||||
@ -102,4 +102,12 @@ export const api = {
|
||||
|
||||
deleteArticle: (id: string) =>
|
||||
request<boolean>(`/kb/articles/${id}`, { method: 'DELETE' }),
|
||||
|
||||
getSettings: () => request<Record<string, string>>('/settings'),
|
||||
|
||||
putSetting: (key: string, value: string) =>
|
||||
request<Record<string, string>>(`/settings/${key}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ value }),
|
||||
}),
|
||||
}
|
||||
|
||||
@ -51,7 +51,8 @@ export type WsHandler = (msg: WsMessage) => void
|
||||
|
||||
export function connectWs(projectId: string, onMessage: WsHandler): { close: () => void } {
|
||||
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
const url = `${proto}//${location.host}/ws/${projectId}`
|
||||
const wsBase = import.meta.env.BASE_URL.replace(/\/$/, '')
|
||||
const url = `${proto}//${location.host}/ws${wsBase}/${projectId}`
|
||||
let ws: WebSocket | null = null
|
||||
let reconnectTimer: ReturnType<typeof setTimeout> | null = null
|
||||
let closed = false
|
||||
|
||||
@ -2,11 +2,13 @@ import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
export default defineConfig({
|
||||
base: process.env.VITE_BASE_PATH || '/tori/',
|
||||
plugins: [vue()],
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': 'http://localhost:3000',
|
||||
'/ws': {
|
||||
'/tori/api': 'http://localhost:3000',
|
||||
'/api/obj': 'http://localhost:3000',
|
||||
'/ws/tori': {
|
||||
target: 'ws://localhost:3000',
|
||||
ws: true,
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user