c735b911a0
端到端 haiku 考 0/3、1/3,**斷點在教材不在引擎**(另一 agent 取證,別重查): 探針零 code 實測 n=10→TRUE、n=1→FALSE 兩次 success;**考生的作品其實會動** (amount=5000→true、amount=100→false 條件求值全對),但它以為跑不通而放棄改寫 code; 考生第二次自己指認「MCP 說明聲稱不支援 ON_TRUE/ON_FALSE,與實際系統行為不符」。 ① skill `write_intent_workflow` **同一份前後打架**(我 08-01 只改了 §2 沒掃全篇): §2.1 教用 ON_TRUE,§7 第 1 條卻把 ON_TRUE 列為「不存在的邊」⇒ 教材自我否定。 改:§7 只留 ON_FAILURE(真的沒有),並明寫「ON_TRUE/ON_FALSE/ON_BRANCH 是存在的, 見 §2.1,本行舊世代已更正」。全篇 grep 過確認無其他矛盾。 ② **補 §2.2「怎麼確認分支真的走對」**——這是「看到對的結果卻以為失敗」的直接解: 看 verdict,且**走 true 路時 false 路節點不出現=正確行為不是失敗**; 附 08-01 實撞案例,明講「只有一條路有輸出」不該判定壞掉。 MCP instructions 同步加這段(比 skill 更前置,AI 一連上就讀到)。 ③ #23 殘留清除(leo 08-01:「已經沒有 publish 了,零件等級一律走 PR,這條路封了」): `git rm mcp/src/tools/arcrun_publish_component.ts`+拔掉 registry.ts 的 import (註冊呼叫本來就已註解掉=純死代碼配活 import)。刪前 grep 全 repo 呼叫方: 除本檔與 registry.ts 外,其餘命中全是 md/SDD 的歷史記載(不需動)。tsc 綠。 替代路徑=`Leo/arcrun-components` fork→PR→人審,已寫進 registry.ts 註解。 SDD: workflow-discovery 3.11|CP: arcrun-usable 步驟 5
68 lines
4.4 KiB
TypeScript
68 lines
4.4 KiB
TypeScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
||
import { registerAllTools } from "./tools/registry.js";
|
||
import { buildLibraryMapInstructions } from "./lib/library-map.js";
|
||
import { Env } from "./types.js";
|
||
|
||
export async function handleMcpRequest(
|
||
request: Request,
|
||
env: Env,
|
||
orgNamespace: string,
|
||
partnerToken: string,
|
||
): Promise<Response> {
|
||
// library-map SDD M4(design §4/§6):連線時把全館藏書地圖嵌進 server instructions,
|
||
// session 一開就知道館裡有哪些庫(push 零查詢)。builder 內建 timeout+isolate TTL 快取
|
||
//(選型理由見 lib/library-map.ts 檔頭);任何失敗回 null → 靜默略過,絕不擋 MCP 連線(鐵律)。
|
||
const mapInstructions = await buildLibraryMapInstructions(env);
|
||
|
||
// 2026-07-30(leo 問「人類說『幫我用 arcrun 寫 xxx』,Haiku 會知道要用這些資源嗎?
|
||
// 如果不會,要寫什麼在外面讓它一聽到就知道?」):
|
||
// 實測答案是**不會**——AI 只看到 41 個工具名,會自己猜(很可能直接跳到 push_workflow
|
||
// 瞎編,或去讀 registry/examples 那 8/13 引用不存在零件的壞範例)。
|
||
// instructions 是唯一「AI 一連上就必看」的欄位 ⇒ 開場就指路,不依賴任何查詢成功。
|
||
// ⚠️ 這段是靜態常數:即使 KBDB 掛了、藏書地圖抓不到,它也必須出現(鐵律:不擋連線)。
|
||
const startHere = [
|
||
"# Arcrun — 你已經配備了這套工具,別上網找",
|
||
"",
|
||
"**Arcrun 是什麼**:跑在 Cloudflare 上的工作流引擎(類 n8n)。你用 `>>` 寫「意圖」,",
|
||
"系統告訴你有哪些現成零件/recipe 可用,你只要填 payload——**不必自己寫程式**。",
|
||
"**你現在就有完整能力**:查零件、查 recipe、看實跑過的 workflow、部署、觸發、看執行紀錄。",
|
||
"⚠️ **不要上網搜 Arcrun 文件**(網路上沒有/會過時)。答案都在下面的工具裡。",
|
||
"",
|
||
"【先讀這裡】要在 Arcrun 上做任何事(用戶說「幫我用 Arcrun 做 X」),**照這個順序**:",
|
||
"",
|
||
"1. `arcrun_get_skill('write_intent_workflow')` — **必讀第一支**。",
|
||
" 教你用 `>>` 寫「意圖工作流」。你**不需要先知道有哪些零件**,先寫意圖。",
|
||
"2. `arcrun_whoami()` — 確認連到哪個帳號(勿自行 curl 猜帳號 URL)。",
|
||
"3. 把意圖丟 `POST /cypher/search` 或 `arcrun_validate_yaml` — 系統告訴你哪些零件存在。",
|
||
"4. 卡住/不知道該查什麼 → `arcrun_get_skill('INDEX')`(全館導航:什麼問題查哪裡+已知的坑)。",
|
||
"5. 缺零件時:缺 API → 寫 recipe(`arcrun_recipe_push`);缺能力 → 投稿零件 PR。",
|
||
" 🔴 **不要因為查不到零件就改寫成 `code` 節點**——那叫「腹語術」(表面用 Arcrun、",
|
||
" 實際全寫 JS)。`code` 只用於局部整形(例:剝掉 LLM 回應的雜訊)。",
|
||
"",
|
||
"邊:`ON_SUCCESS`(成功往下)、`對每個 <變數>`(FOREACH)、",
|
||
"以及**條件分支**(2026-08-01 起引擎支援):",
|
||
"`ON_TRUE`/`ON_FALSE`(配 `if_control`)、`ON_BRANCH`+`branch:` 標籤",
|
||
"(配 `switch` 的每個 case/`try_catch` 的 try·catch)。",
|
||
"🔴 **需要判斷時用分支邊,不要寫 code 判斷**——查零件的回應會附 `branch_hint`",
|
||
"(哪些邊型+可照抄範例),照著接即可。",
|
||
"🔴 **分支跑完怎麼判斷成功**:看 `verdict`(`arcrun_get_execution_trace` 或",
|
||
"`GET /workflows/<name>/executions`)。**走 true 路時 false 路的節點不出現=正確行為**,",
|
||
"不是失敗——別因為「只有一條路有輸出」就以為壞掉而改寫成 code(2026-08-01 實撞)。",
|
||
"第一個節點固定是 `input`。",
|
||
].join("\n");
|
||
|
||
const instructions = mapInstructions ? `${startHere}\n\n---\n\n${mapInstructions}` : startHere;
|
||
|
||
const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
||
const server = new McpServer(
|
||
{ name: "arcrun-mcp-server", version: "1.0.0" },
|
||
{ instructions },
|
||
);
|
||
|
||
registerAllTools(server, env, orgNamespace, partnerToken);
|
||
await server.connect(transport);
|
||
|
||
return transport.handleRequest(request);
|
||
}
|