/** * workflow-search — 本租戶 workflow 名字搜尋的**唯一一條路** * * 既有機制(workflow-discovery 3.1):轉發 KBDB /entries/search * (entry_type=workflow + owner_id=apiKey 租戶隔離;優先 semantic,KBDB 未開 * Vectorize 自動降級 keyword + capability_hint)。 * * 為什麼抽成共用(leo 07-31:「search 節點名稱和 search 工作流名稱是同一個? * 難道我不能指定要搜尋工作流或節點或 recipe 嗎?」+「外部 API 只有一條一致的路」鐵律): * - GET /workflows/search(MCP arcrun_search_workflows 走的路) * - POST /cypher/search { target: "workflow", query }(discover 入口指定搜尋對象) * 兩個入口共用本函式 ⇒ 行為必然一致,改一處兩邊同步。 * * 已知缺口(如實透傳,不掩蓋):workflow_metadata 無 description slot—— * 無 description 的 workflow 沒有 search entry、搜不到;補救走 * POST /workflows/backfill-search-entries(有 description 的補 entry、沒有的誠實列出)。 * * flag 安全:主動 pull,無輪詢/排程。 */ export type WorkflowSearchEnv = { KBDB_BASE_URL?: string; KBDB_INTERNAL_TOKEN?: string; }; export type WorkflowSearchMode = 'semantic' | 'keyword'; /** * 打 KBDB /entries/search(本租戶、entry_type=workflow)。 * 回原始 Response——GET /workflows/search 直接 stream 透傳(既有行為,一字不改); * target=workflow 的呼叫端自行 json() 解析。 */ export async function fetchTenantWorkflowSearch( env: WorkflowSearchEnv, apiKey: string, q: string, mode: WorkflowSearchMode = 'semantic', ): Promise { const base = (env.KBDB_BASE_URL ?? 'https://arcrun-kbdb.uncle6-me.workers.dev').replace(/\/$/, ''); const headers: Record = { 'Content-Type': 'application/json' }; if (env.KBDB_INTERNAL_TOKEN) headers['Authorization'] = `Bearer ${env.KBDB_INTERNAL_TOKEN}`; const params = new URLSearchParams({ q, owner_id: apiKey, // 租戶隔離(只搜本租戶的 workflow) entry_type: 'workflow', // base 通用 filter(Q4),只回 workflow entry mode, }); return fetch(`${base}/entries/search?${params.toString()}`, { headers }); }