613071f41d
對應 issue #1 T3 C 段(圖工具 HTTP API 備好,MCP 註冊薄殼待 arcrun)。 - get_source (3.7): graph-source.ts + GET /graph/source/:name — 回節點的 active triplet 來源指標(uri/anchor/block_id/content_hash),去重。 連帶加 source_anchor slot,ingest 從 source.anchor 帶入 - refresh (3.6/3.6b): graph-refresh.ts + POST /graph/refresh — 純被動代轉 ingest(KBDB_INGEST_URL),只人發起、無排程/webhook(fan-out 紅線)。 未設 URL → 誠實 forwarded:false,不假綠 - 3.6d: POST /search 移除公開 keyword 模式(重複 KBDB MCP),收斂 suggest-only; keywordSearch helper 留作 suggest 內部建構塊 - 3 新測試(get_source uri+anchor / active-only / refresh 未就緒誠實回報) gates: vitest 19 passed / zero SQL / 無新綁定 / dry-run bundle 乾淨 待接:MCP 註冊薄殼併 arcrun u6u-mcp-server;refresh 端到端待 ingest(T4) 部署 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
2.9 KiB
TypeScript
69 lines
2.9 KiB
TypeScript
// 圖遍歷路由入口
|
||
// 僅驗證參數,呼叫 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 };
|