// 圖遍歷路由入口 // 僅驗證參數,呼叫 actions(actions 走基本盤 API,圖在插件層組裝) import { Hono } from 'hono'; import type { Bindings } from '../types'; import { traverseGraph, queryRelation } from '../actions/graph-traverse'; import { getNodeEdges, getNeighbors } from '../actions/graph-nodes'; import { findShortestPath } from '../actions/graph-path'; import { getSource } from '../actions/graph-source'; import { refreshSource } from '../actions/graph-refresh'; import { makeKbdbClient } from '../lib/kbdb-client'; const graphRoutes = new Hono<{ Bindings: Bindings }>(); graphRoutes.get('/traverse', async (c) => { const start = c.req.query('start'); if (!start) return c.json({ error: 'start parameter required' }, 400); const depth = Number(c.req.query('depth') ?? 2); const results = await traverseGraph(makeKbdbClient(c.env), start, depth); return c.json({ start, depth, nodes: results, nodeCount: results.length }); }); graphRoutes.get('/relation', async (c) => { const from = c.req.query('from'); const to = c.req.query('to'); if (!from || !to) return c.json({ error: 'from and to parameters required' }, 400); const relations = await queryRelation(makeKbdbClient(c.env), from, to); return c.json({ from, to, relations, count: relations.length }); }); // GET /graph/neighbors/:name — 合併原 nodes/:name 的 edges + neighbors graphRoutes.get('/neighbors/:name', async (c) => { const name = decodeURIComponent(c.req.param('name')); const client = makeKbdbClient(c.env); const [edges, neighbors] = await Promise.all([ getNodeEdges(client, name), getNeighbors(client, name), ]); return c.json({ node: name, edges, neighbors, edgeCount: edges.length, neighborCount: neighbors.length }); }); // GET /graph/path — 取代 /shortest-path,行為不變 graphRoutes.get('/path', async (c) => { const from = c.req.query('from'); const to = c.req.query('to'); if (!from || !to) return c.json({ error: 'from and to parameters required' }, 400); const result = await findShortestPath(makeKbdbClient(c.env), from, to); return c.json({ from, to, ...result }); }); // GET /graph/source/:name — get_source(T3.7):回節點的原文來源指標(uri+anchor) graphRoutes.get('/source/:name', async (c) => { const name = decodeURIComponent(c.req.param('name')); const sources = await getSource(makeKbdbClient(c.env), name); return c.json({ node: name, sources, count: sources.length }); }); // POST /graph/refresh — 代轉 ingest 重抓+萃(T3.6/3.6b) // 🚫 只人發起 MCP 調用觸發,禁排程/webhook 自動(fan-out 紅線)。 graphRoutes.post('/refresh', async (c) => { const body = await c.req.json().catch(() => ({})); const uri = body?.uri; if (!uri) return c.json({ error: 'uri required' }, 400); const result = await refreshSource({ uri, owner_id: body?.owner_id }, c.env.KBDB_INGEST_URL); return c.json(result); }); export { graphRoutes };