diff --git a/README.md b/README.md index a41d7cf..68dca8d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Served via jsDelivr; fetched automatically during install — you never need to - `arcrun-wait/` — **arcrun-wait**(首裝) - `daemon/` — 桌面 App(Mac/Windows)安裝檔 -Built from `Arcrun@d60cd1258f43` by `installer/scripts/ship.mjs`(arcrun-rag repo,release 1.4.55,built 2026-08-26)。 +Built from `Arcrun@6521914df572` by `installer/scripts/ship.mjs`(arcrun-rag repo,release 1.4.56,built 2026-08-26)。 ⚠️ 這份檔案由出貨管線每次自動重寫(`installer/scripts/render-bundles-readme.mjs`)—— 不要手動改這裡列的零件清單——它是算出來的:公庫=Arcrun 這一版編了什麼, diff --git a/arcrun-cypher-executor/worker.mjs b/arcrun-cypher-executor/worker.mjs index d2b3b9e..5699eeb 100644 --- a/arcrun-cypher-executor/worker.mjs +++ b/arcrun-cypher-executor/worker.mjs @@ -12908,9 +12908,21 @@ var PORTAL_TEMPLATE_SEEDS = [ // 這裡只是「有哪些庫」的登記簿。 // graph_source(design D-4,P3):'true'=此庫是知識圖譜的萃取來源——graph 粗閘按 // 「用戶是否擁有 graph 來源庫權限」放行。**沒有任何庫標記時預設視同 general**(D-4 定案)。 + // root / mode / reason(InkStoneCo#44,2026-08-17):**一個庫=地端的一個資料夾**, + // 而在此之前雲端只記得住它的名字,於是「資料夾」在雲端不是一個持久物件—— + // 它是「有卡片才有庫」的副作用(arcrun-rag#106 實測:空資料夾指定了,雲端什麼都不出現)。 + // leo:「**不能因為地端資料夾內沒東西就當作不存在,如果那是他打算放東西的資料夾呢?**」 + // ⇒ 小幫手一報上來就登記,不必等到有卡片。 + // root=地端絕對路徑(使用者認得回去的那條路) + // mode=收檔策略(all/curated-wiki/docs-only,地端 IngestPlan 決定) + // reason=那句人話(「為什麼只收這些」) + // 🔴 這三個是**欄位、不是 JSON 團**(D91):它們是「資料夾」這個物件本身的屬性。 + // 每輪會變的計數(同步數/總數/整棵樹)**不住在這裡**——那是投影, + // 見 portal.ts 的 folderTreeKey() 與那段「為什麼樹不進 KBDB」的說明。 + // 既有實例靠 ensurePortalTemplates 的「補 slots」路徑自動補上(同 P3 加 graph_source 那次)。 name: "portal_library", - description: "RAG Portal \u5EAB\u76EE\u9304\u767B\u8A18\uFF08portal-auth \xA73.2\uFF1B\u5EAB\uFF1Dmetadata_json.$.library \u6A19\u8A18\uFF09", - slots: ["name", "display_name", "description", "status", "graph_source"], + description: "RAG Portal \u5EAB\u76EE\u9304\u767B\u8A18\uFF08portal-auth \xA73.2\uFF1B\u4E00\u500B\u5EAB\uFF1D\u5C0F\u5E6B\u624B\u770B\u5B88\u7684\u4E00\u500B\u8CC7\u6599\u593E\uFF09", + slots: ["name", "display_name", "description", "status", "graph_source", "root", "mode", "reason"], created_by: "system" }, { @@ -13784,9 +13796,171 @@ function toPublicLibrary(rec) { description: v.description ?? "", status: v.status ?? "", // D-4:此庫是否為知識圖譜萃取來源(graph 粗閘按這個判定;全都沒標 → 預設 general) - graph_source: (v.graph_source ?? "") === "true" + graph_source: (v.graph_source ?? "") === "true", + // InkStoneCo#44:一個庫=地端的一個資料夾。這三個是「資料夾」這個物件本身的屬性 + // (小幫手回報時登記,見 POST /portal/daemon/folder-tree),空字串=這台小幫手還沒報過。 + root: v.root ?? "", + mode: v.mode ?? "", + reason: v.reason ?? "" }; } +function folderTreeKey(env, library) { + return `${portalTenant(env)}:portal:folder_tree:${library}`; +} +function normalizeFolderNode(raw2) { + if (!raw2 || typeof raw2 !== "object") return null; + const r = raw2; + const path = typeof r.path === "string" ? r.path : ""; + const num = (v) => { + const n = Number(v); + return Number.isFinite(n) && n >= 0 ? Math.floor(n) : 0; + }; + const node = { + path, + name: typeof r.name === "string" && r.name ? r.name : path.split("/").pop() || "", + parent: typeof r.parent === "string" ? r.parent : "-", + depth: num(r.depth), + total_files: num(r.total_files), + synced_files: num(r.synced_files), + pending_files: num(r.pending_files), + unsupported_files: num(r.unsupported_files), + excluded_files: num(r.excluded_files) + }; + if (r.skipped === true) { + node.skipped = true; + node.skip_reason = typeof r.skip_reason === "string" ? r.skip_reason : ""; + } + return node; +} +async function readFolderTree(env, library) { + let raw2 = null; + try { + raw2 = await env.WEBHOOKS.get(folderTreeKey(env, library), "text"); + } catch { + return null; + } + if (!raw2) return null; + try { + return JSON.parse(raw2); + } catch { + return null; + } +} +function summarizeFolderTree(tree) { + let total = 0; + let synced = 0; + let pending = 0; + let unsupported = 0; + let excluded = 0; + let skippedDirs = 0; + for (const n of tree.nodes ?? []) { + if (n.skipped) { + skippedDirs++; + continue; + } + total += n.total_files; + synced += n.synced_files; + pending += n.pending_files; + unsupported += n.unsupported_files; + excluded += n.excluded_files; + } + return { + root: tree.root, + mode: tree.mode, + reason: tree.reason, + node_count: (tree.nodes ?? []).length, + total_nodes: tree.total_nodes, + truncated: !!tree.truncated, + total_files: total, + synced_files: synced, + pending_files: pending, + unsupported_files: unsupported, + excluded_files: excluded, + skipped_dirs: skippedDirs, + generated_at: tree.generated_at, + received_at: tree.received_at + }; +} +portalRouter.post( + "/portal/daemon/folder-tree", + (c) => run(c, async () => { + const apiKey = (c.req.header("X-Arcrun-API-Key") ?? "").trim(); + if (!apiKey) return c.json({ error: "\u7F3A\u5C11 X-Arcrun-API-Key header" }, 401); + const body = await c.req.json().catch(() => null); + if (!body) return c.json({ error: "body \u5FC5\u9808\u662F JSON" }, 400); + const library = String(body.library ?? "").trim(); + if (!isValidLibraryName(library) || library === "*") { + return c.json({ error: "library \u9808\u70BA\u5408\u6CD5\u5EAB\u540D\uFF08A-Za-z0-9_-\uFF0C1-64 \u5B57\uFF09" }, 400); + } + const rawNodes = Array.isArray(body.nodes) ? body.nodes : []; + const nodes = rawNodes.map(normalizeFolderNode).filter((n) => n !== null); + const displayName = String(body.display_name ?? "").trim() || library; + const root = String(body.root ?? "").trim(); + const mode = String(body.mode ?? "").trim(); + const reason = String(body.reason ?? "").trim(); + const seeded = await ensurePortalTemplates(c.env); + if (seeded.errors.length > 0) { + return c.json({ error: `portal templates seed \u5931\u6557\uFF1A${seeded.errors.join("; ")}` }, 502); + } + const existing = await listRecordsByTemplate(c.env, LIBRARY_TEMPLATE); + const mine = existing.find((l) => (l.values.name ?? "") === library); + let registered = false; + if (!mine) { + const res = await kbdbFetch(c.env, "/records", { + method: "POST", + body: JSON.stringify({ + template: LIBRARY_TEMPLATE, + owner_id: portalNamespace(c.env), + values: { name: library, display_name: displayName, description: "", status: "active", root, mode, reason } + }) + }); + if (!res.ok) throw new KbdbError(`POST /records\uFF08portal_library\uFF0C\u8CC7\u6599\u593E\u6A39\u767B\u8A18\uFF09\u2192 ${res.status}`); + registered = true; + } else { + const patch = {}; + if ((mine.values.root ?? "") !== root) patch.root = root; + if ((mine.values.mode ?? "") !== mode) patch.mode = mode; + if ((mine.values.reason ?? "") !== reason) patch.reason = reason; + if (Object.keys(patch).length > 0) await patchRecordValues(c.env, mine.record_id, patch); + } + const stored = { + library, + display_name: displayName, + root, + mode, + reason, + truncated: body.truncated === true, + total_nodes: Number.isFinite(Number(body.total_nodes)) ? Number(body.total_nodes) : nodes.length, + sync_token: String(body.sync_token ?? ""), + generated_at: Number.isFinite(Number(body.generated_at)) ? Number(body.generated_at) : 0, + received_at: Math.floor(Date.now() / 1e3), + nodes + }; + await c.env.WEBHOOKS.put(folderTreeKey(c.env, library), JSON.stringify(stored)); + return c.json({ success: true, library, registered, nodes: nodes.length, truncated: stored.truncated }); + }) +); +portalRouter.get( + "/portal/admin/folder-tree", + (c) => run(c, async () => { + const auth = await requirePortalAdmin(c); + if (!auth.ok) return auth.res; + const library = (c.req.query("library") ?? "").trim(); + if (!isValidLibraryName(library) || library === "*") { + return c.json({ error: "library \u53C3\u6578\u5FC5\u586B\u4E14\u9808\u70BA\u5408\u6CD5\u5EAB\u540D" }, 400); + } + const tree = await readFolderTree(c.env, library); + if (!tree) { + return c.json({ + success: true, + library, + tree: null, + note: "\u540C\u6B65\u5C0F\u5E6B\u624B\u9084\u6C92\u56DE\u5831\u904E\u9019\u500B\u8CC7\u6599\u593E\u7684\u7D50\u69CB\uFF08\u820A\u7248\u5C0F\u5E6B\u624B\u4E0D\u6703\u56DE\u5831\uFF0C\u66F4\u65B0\u5F8C\u624D\u6703\u51FA\u73FE\uFF09\u3002" + }); + } + return c.json({ success: true, library, tree }); + }) +); portalRouter.post( "/portal/daemon/extract", (c) => run(c, async () => { @@ -14020,6 +14194,12 @@ portalRouter.get( } } catch { } + await Promise.all(out.map(async (lib) => { + const name = String(lib.name ?? ""); + if (!name) return; + const tree = await readFolderTree(c.env, name); + if (tree) lib.folder_tree = summarizeFolderTree(tree); + })); return c.json({ success: true, libraries: out, count: out.length }); }) ); @@ -14210,6 +14390,10 @@ portalRouter.delete( if (!target) return c.json({ error: "\u5EAB\u4E0D\u5B58\u5728" }, 404); const found = await deleteKbdbRecord(c.env, recordId); if (!found) return c.json({ error: "\u5EAB\u4E0D\u5B58\u5728" }, 404); + try { + await c.env.WEBHOOKS.delete(folderTreeKey(c.env, target.values.name ?? "")); + } catch { + } return c.json({ success: true, name: target.values.name ?? "", diff --git a/daemon/Arcrun-0.18.38.dmg b/daemon/Arcrun-0.18.38.dmg new file mode 100644 index 0000000..fafddb8 Binary files /dev/null and b/daemon/Arcrun-0.18.38.dmg differ diff --git a/daemon/Arcrun-0.18.38.msix b/daemon/Arcrun-0.18.38.msix new file mode 100644 index 0000000..5417269 Binary files /dev/null and b/daemon/Arcrun-0.18.38.msix differ diff --git a/daemon/Arcrun-win-0.18.38.exe b/daemon/Arcrun-win-0.18.38.exe new file mode 100755 index 0000000..181a6c5 Binary files /dev/null and b/daemon/Arcrun-win-0.18.38.exe differ diff --git a/manifest.json b/manifest.json index 208d08f..2ea3744 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "schema": 2, "built": "2026-08-26", - "source": "Arcrun@d60cd1258f43", + "source": "Arcrun@6521914df572", "core": [ { "name": "arcrun-array-ops", @@ -198,7 +198,7 @@ "name": "arcrun-cypher-executor", "main_module": "worker.mjs", "main_file": "arcrun-cypher-executor/worker.mjs", - "js_bytes": 683598, + "js_bytes": 691420, "modules": [], "compat_date": "2025-02-19", "compat_flags": [ @@ -239,10 +239,10 @@ "stripped": { "services": 13 }, - "source_commit": "72a18e30b06c2318fb71872ac9dcbbb6b47fab66", - "source_content_sha256": "d4ad7f488c673dfb886ee2bc02c909b62acecba6ffaf19aeedd6a9199fe9a1d4", - "sha256": "d4ad7f488c673dfb886ee2bc02c909b62acecba6ffaf19aeedd6a9199fe9a1d4", - "bytes": 683598 + "source_commit": "8257fd90a9a172a160a77980b0f10c1bc5a2eabb", + "source_content_sha256": "1750e8a938ae467a7091b9faa6c0549fac64fc7d35cd9067bf4c43f4b2db49d3", + "sha256": "1750e8a938ae467a7091b9faa6c0549fac64fc7d35cd9067bf4c43f4b2db49d3", + "bytes": 691420 }, { "name": "arcrun-date-ops", @@ -507,7 +507,7 @@ "name": "arcrun-rag-ui", "main_module": "index.js", "main_file": "tier2/ui/index.js", - "js_bytes": 723179, + "js_bytes": 660202, "modules": [], "compat_date": "2026-07-01", "compat_flags": [], @@ -518,10 +518,10 @@ "ai": false, "vars": {} }, - "source_commit": "15c5cedff39fe6567fc7d586254acb411fb7ad6d", - "source_content_sha256": "594637e14cd18c45b380ce118845ad58a549f3227cff284ea31efd25c005787f", - "sha256": "594637e14cd18c45b380ce118845ad58a549f3227cff284ea31efd25c005787f", - "bytes": 723179 + "source_commit": "b35c820be7264ab30295cfb35a6674bf11cc24e8", + "source_content_sha256": "a4d920dfef53171f0e62f174dddae79d125f6fecf60c0c5781debc81f3ae0c53", + "sha256": "a4d920dfef53171f0e62f174dddae79d125f6fecf60c0c5781debc81f3ae0c53", + "bytes": 660202 }, { "name": "arcrun-set", @@ -698,29 +698,12 @@ "bytes": 67697 } ], - "daemon": { - "version": "0.18.37", - "built": "20260826-1711", - "notes": "雲端被清空過的檔案,小幫手現在會自己發現並補送・重跑第二次不會又全部送一遍・補送的時候看得到", - "mac": { - "file": "daemon/Arcrun-0.18.37.dmg", - "sha256": "6c4dd003e29f06e3a326b2c28ef295168391408ea2800378287ab9701b7c771d" - }, - "win": { - "file": "daemon/Arcrun-win-0.18.37.exe", - "sha256": "99df0dcdbca54b0c0c4feb3af2e28ce982bb5ebd02f0f1fb0c61210b5aecae48" - }, - "msix": { - "file": "daemon/Arcrun-0.18.37.msix", - "sha256": "91b2c217891d6a06fb0269c090e5c2dd7aa2779a3a8ac72ec677b9f46ed0516d" - } - }, - "release": "1.4.55", + "release": "1.4.56", "built_for": "oauth-installer-lazy-load", "notes": [ "rag_takedown_direct 用了 __CARDS_PREFIX__,但安裝器的代換表沒有它 ⇒ 這個佔位符會原封不動被推進使用者的工作流。" ], - "fingerprint": "83e5e42de07dac5a13f504af9ffc0649493322ab1cd9e40e0fe8aa0af83b73c3", + "fingerprint": "a4051e876cc06cad3523c47d263882da17855abfc660eec9d8ecd29e9455ff8a", "library": [ { "name": "arcrun-array-ops", @@ -905,7 +888,7 @@ "name": "arcrun-cypher-executor", "main_module": "worker.mjs", "main_file": "arcrun-cypher-executor/worker.mjs", - "js_bytes": 683598, + "js_bytes": 691420, "modules": [], "compat_date": "2025-02-19", "compat_flags": [ @@ -946,8 +929,8 @@ "stripped": { "services": 13 }, - "source_commit": "72a18e30b06c2318fb71872ac9dcbbb6b47fab66", - "source_content_sha256": "d4ad7f488c673dfb886ee2bc02c909b62acecba6ffaf19aeedd6a9199fe9a1d4", + "source_commit": "8257fd90a9a172a160a77980b0f10c1bc5a2eabb", + "source_content_sha256": "1750e8a938ae467a7091b9faa6c0549fac64fc7d35cd9067bf4c43f4b2db49d3", "first_install": true }, { @@ -1197,7 +1180,7 @@ "name": "arcrun-rag-ui", "main_module": "index.js", "main_file": "tier2/ui/index.js", - "js_bytes": 723179, + "js_bytes": 660202, "modules": [], "compat_date": "2026-07-01", "compat_flags": [], @@ -1208,8 +1191,8 @@ "ai": false, "vars": {} }, - "source_commit": "15c5cedff39fe6567fc7d586254acb411fb7ad6d", - "source_content_sha256": "594637e14cd18c45b380ce118845ad58a549f3227cff284ea31efd25c005787f", + "source_commit": "b35c820be7264ab30295cfb35a6674bf11cc24e8", + "source_content_sha256": "a4d920dfef53171f0e62f174dddae79d125f6fecf60c0c5781debc81f3ae0c53", "first_install": true }, { @@ -1500,5 +1483,22 @@ "worker": "arcrun-auth-static-key", "why": "rag_takedown_direct 用 {{credential.kbdb_internal_token}},解憑證要打這顆" } - ] + ], + "daemon": { + "version": "0.18.38", + "mac": { + "file": "daemon/Arcrun-0.18.38.dmg", + "sha256": "0b91b70295823f343166e31f53bd170ec315b5a4d84c4858424547bdafaf4aa5" + }, + "win": { + "file": "daemon/Arcrun-win-0.18.38.exe", + "sha256": "92927b0f8b7f3063d569628deec72b2b95c124060612741ef1aa6d6734656f56" + }, + "msix": { + "file": "daemon/Arcrun-0.18.38.msix", + "sha256": "9f0527b60fba0bd27316b86cf606178bc221a3ef3265880490467a76b2d4ed98" + }, + "built": "20260826-2051", + "notes": "每一層子資料夾都看得到,不是只有第一層・小幫手看得到,不必等雲端、也不必連線・每一層都告訴你「幾份、上去了幾份」・整個沒走進去的資料夾,不會假裝成 0 / 0" + } } diff --git a/manifest.json.bak-0826 b/manifest.json.bak-0826 new file mode 100644 index 0000000..6fc059a --- /dev/null +++ b/manifest.json.bak-0826 @@ -0,0 +1,1504 @@ +{ + "schema": 2, + "built": "2026-08-26", + "source": "Arcrun@d60cd1258f43", + "core": [ + { + "name": "arcrun-array-ops", + "main_module": "worker.mjs", + "main_file": "arcrun-array-ops/worker.mjs", + "js_bytes": 67802, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-array-ops/component.wasm", + "sha256": "74dc9d99f8b9ef43628b55c85c05beb1af8f6f90d78d07cd132ffe4b865147ae" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "array_ops" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "35ad5be6332dde2299efd10be726300c6cace1eb085ab24f08173536ca7fb950", + "sha256": "35ad5be6332dde2299efd10be726300c6cace1eb085ab24f08173536ca7fb950", + "bytes": 67802 + }, + { + "name": "arcrun-auth-oauth2", + "main_module": "worker.mjs", + "main_file": "arcrun-auth-oauth2/worker.mjs", + "js_bytes": 80472, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-auth-oauth2/component.wasm", + "sha256": "3622c20644e6c8c39487109e7353e2590bad90b1207139e34dfb0cf1c2696664" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [ + "CREDENTIALS_KV", + "RECIPES" + ], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "auth_oauth2" + } + }, + "source_commit": "20c7610371c401f622ef4e6ea1b9ba812963be95", + "source_content_sha256": "a9b0d45ee6a63e0eebd45554df16d9fa4e6e717e0c31dac13b630e132f1a96db", + "sha256": "a9b0d45ee6a63e0eebd45554df16d9fa4e6e717e0c31dac13b630e132f1a96db", + "bytes": 80472 + }, + { + "name": "arcrun-auth-service-account", + "main_module": "worker.mjs", + "main_file": "arcrun-auth-service-account/worker.mjs", + "js_bytes": 81693, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-auth-service-account/component.wasm", + "sha256": "7d0808b4b9a2df4fbb54977eafe34a5bdb99e0cc941d97462c62e26f3651951e" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [ + "CREDENTIALS_KV", + "RECIPES" + ], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "auth_service_account" + } + }, + "source_commit": "20c7610371c401f622ef4e6ea1b9ba812963be95", + "source_content_sha256": "68675ec76f3f060309492e55301936a47f4ae0a5e9b00865eb861e0e631e40e5", + "sha256": "68675ec76f3f060309492e55301936a47f4ae0a5e9b00865eb861e0e631e40e5", + "bytes": 81693 + }, + { + "name": "arcrun-auth-static-key", + "main_module": "worker.mjs", + "main_file": "arcrun-auth-static-key/worker.mjs", + "js_bytes": 81217, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-auth-static-key/component.wasm", + "sha256": "cd0f69a80ced0979749e0ec30b1981795a49eaa56bdb2ba102cd4b64f4670369" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [ + "CREDENTIALS_KV", + "RECIPES" + ], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "auth_static_key" + } + }, + "source_commit": "20c7610371c401f622ef4e6ea1b9ba812963be95", + "source_content_sha256": "140c163d2e8c609eebf281de25d16e521d85004f8437cc842613c249e44aa7ff", + "sha256": "140c163d2e8c609eebf281de25d16e521d85004f8437cc842613c249e44aa7ff", + "bytes": 81217 + }, + { + "name": "arcrun-code", + "main_module": "worker.mjs", + "main_file": "arcrun-code/worker.mjs", + "js_bytes": 153758, + "modules": [ + { + "name": "quickjs.wasm", + "type": "application/wasm", + "file": "arcrun-code/quickjs.wasm", + "sha256": "105c3bed22d457e43e3d1c3c1c6959fda62a8fe06f0fc8a985303c3a2be72232" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "code" + } + }, + "source_commit": "621cb8d948d61be6202063fd02effb3f538437fe", + "source_content_sha256": "751634a3fc9a99cc2da662026818d754c48f031d10bff3b3be2d3a8ee2311bd6", + "sha256": "751634a3fc9a99cc2da662026818d754c48f031d10bff3b3be2d3a8ee2311bd6", + "bytes": 153758 + }, + { + "name": "arcrun-cron", + "main_module": "worker.mjs", + "main_file": "arcrun-cron/worker.mjs", + "js_bytes": 78911, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-cron/component.wasm", + "sha256": "afb3a14f8c8f00f4f5573f44153cb1dcf6fc715b2fb47c2afb0aaf95b74d3cde" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "cron" + } + }, + "source_commit": "6e92ca03727bf22143499d6c0df06b40cb65c17b", + "source_content_sha256": "17068f03f686aee6c0aec9d7d748bbb1998edc8918260033f985697bc718aa76", + "sha256": "17068f03f686aee6c0aec9d7d748bbb1998edc8918260033f985697bc718aa76", + "bytes": 78911 + }, + { + "name": "arcrun-cypher-executor", + "main_module": "worker.mjs", + "main_file": "arcrun-cypher-executor/worker.mjs", + "js_bytes": 683598, + "modules": [], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat", + "global_fetch_strictly_public" + ], + "requires": { + "kv": [ + "EXEC_CONTEXT", + "WEBHOOKS", + "CREDENTIALS_KV", + "ANALYTICS_KV", + "RECIPES", + "USERS_KV", + "SESSIONS_KV" + ], + "d1": [ + { + "binding": "CREDENTIALS_DB", + "database_name": "arcrun-kbdb" + } + ], + "vectorize": 0, + "ai": true, + "vars": { + "ENVIRONMENT": "production", + "CF_ACCOUNT_ID": "", + "WORKER_SUBDOMAIN": "uncle6-me", + "KBDB_BASE_URL": "https://arcrun-kbdb.uncle6-me.workers.dev", + "CONSOLE_TENANT": "leo", + "PORTAL_SESSION_TTL": "604800", + "PORTAL_SHOW_WORKFLOWS": "admin", + "GITEA_BASE_URL": "https://git.uncle6.me", + "GITEA_SPRINT_REPO": "Leo/InkStoneCo", + "GITEA_SPRINT_DIR": "system-dev/docs/3-specs/autonomy-dispatch" + } + }, + "stripped": { + "services": 13 + }, + "source_commit": "72a18e30b06c2318fb71872ac9dcbbb6b47fab66", + "source_content_sha256": "d4ad7f488c673dfb886ee2bc02c909b62acecba6ffaf19aeedd6a9199fe9a1d4", + "sha256": "d4ad7f488c673dfb886ee2bc02c909b62acecba6ffaf19aeedd6a9199fe9a1d4", + "bytes": 683598 + }, + { + "name": "arcrun-date-ops", + "main_module": "worker.mjs", + "main_file": "arcrun-date-ops/worker.mjs", + "js_bytes": 67781, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-date-ops/component.wasm", + "sha256": "4e2c1329ce4014aa86a9a6449d8699e67c6c616f5c07088dc21216d4036ca41e" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "date_ops" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "60ebc1d17ab0b9d3bb66f1c71ec63eb5d35bc97ed9f8b4cd1c1c95f4eeb171b7", + "sha256": "60ebc1d17ab0b9d3bb66f1c71ec63eb5d35bc97ed9f8b4cd1c1c95f4eeb171b7", + "bytes": 67781 + }, + { + "name": "arcrun-filter", + "main_module": "worker.mjs", + "main_file": "arcrun-filter/worker.mjs", + "js_bytes": 67739, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-filter/component.wasm", + "sha256": "6a0692b386522918b3b5af79cf7877394d1f02c350018dbaef68ef380dad1b9e" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "filter" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "c7fd5070ff7c0f0341e9dd364805e393f9d68056a846f48e6bc61ef6f4e67187", + "sha256": "c7fd5070ff7c0f0341e9dd364805e393f9d68056a846f48e6bc61ef6f4e67187", + "bytes": 67739 + }, + { + "name": "arcrun-foreach-control", + "main_module": "worker.mjs", + "main_file": "arcrun-foreach-control/worker.mjs", + "js_bytes": 67928, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-foreach-control/component.wasm", + "sha256": "8ae161ab37cc78ef6fae65364a47f7accb572378b395c4637daa2ffa57f14632" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "foreach_control" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "e52410c9611a93ac7fe38c7b11291cc18711c7da3370492788c3c55bc0fb03d5", + "sha256": "e52410c9611a93ac7fe38c7b11291cc18711c7da3370492788c3c55bc0fb03d5", + "bytes": 67928 + }, + { + "name": "arcrun-http-request", + "main_module": "worker.mjs", + "main_file": "arcrun-http-request/worker.mjs", + "js_bytes": 80079, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-http-request/component.wasm", + "sha256": "cc15cc785703e7bbb8dbff2d38dc84a4ac24e2f44316182730abae0f170ef133" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat", + "global_fetch_strictly_public" + ], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "http_request" + } + }, + "source_commit": "1e85dfb49b0e8d81c0854781d93ee4e6a300c7b3", + "source_content_sha256": "cdd97364f277587cbade69e09bb40812c68f26a1e8bc9aa632c65b1b962b0b85", + "sha256": "cdd97364f277587cbade69e09bb40812c68f26a1e8bc9aa632c65b1b962b0b85", + "bytes": 80079 + }, + { + "name": "arcrun-if-control", + "main_module": "worker.mjs", + "main_file": "arcrun-if-control/worker.mjs", + "js_bytes": 67823, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-if-control/component.wasm", + "sha256": "87c81e9cf5e664f60c06a364508dd365d49953e1b7afba6a5753fce5a4c82636" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "if_control" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "557ecf4ee955105af07b2227b08365eb9de8c39ad8ffb323b101397704f438bd", + "sha256": "557ecf4ee955105af07b2227b08365eb9de8c39ad8ffb323b101397704f438bd", + "bytes": 67823 + }, + { + "name": "arcrun-kbdb", + "main_module": "worker.mjs", + "main_file": "arcrun-kbdb/worker.mjs", + "js_bytes": 185704, + "modules": [], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [], + "d1": [ + { + "binding": "DB", + "database_name": "arcrun-kbdb" + } + ], + "vectorize": 0, + "ai": false, + "vars": { + "ENVIRONMENT": "production" + } + }, + "source_commit": "a1f45aef73de264236ff044e5b5fd5eb4d1cadc1", + "source_content_sha256": "68efc2b8958d1047c8d17f63325949af738379f8f1a2d509b9fa8bcf09440855", + "sha256": "68efc2b8958d1047c8d17f63325949af738379f8f1a2d509b9fa8bcf09440855", + "bytes": 185704 + }, + { + "name": "arcrun-mcp", + "main_module": "worker.mjs", + "main_file": "arcrun-mcp/worker.mjs", + "js_bytes": 1193125, + "modules": [], + "compat_date": "2024-11-27", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [ + "OAUTH_KV" + ], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": {} + }, + "source_commit": "c3efed7d1a01fc171df6eefb67d0bd380781be73", + "source_content_sha256": "e14dedfd630fed6e30f5d5f24a9d9b885899b81f4131ffb463705b151028c579", + "sha256": "e14dedfd630fed6e30f5d5f24a9d9b885899b81f4131ffb463705b151028c579", + "bytes": 1193125 + }, + { + "name": "arcrun-merge", + "main_module": "worker.mjs", + "main_file": "arcrun-merge/worker.mjs", + "js_bytes": 67718, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-merge/component.wasm", + "sha256": "55a4d143246df172f60b5e15e7b26e55279deda9db436e3d65bccc25c86d7cd9" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "merge" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "e4216249436000bbb4db0318cc9028f936ca6537d3d656228cfdd3cb31df25f8", + "sha256": "e4216249436000bbb4db0318cc9028f936ca6537d3d656228cfdd3cb31df25f8", + "bytes": 67718 + }, + { + "name": "arcrun-number-ops", + "main_module": "worker.mjs", + "main_file": "arcrun-number-ops/worker.mjs", + "js_bytes": 67823, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-number-ops/component.wasm", + "sha256": "452d1940f6e2b2b36dc97c145abcb7b5bacdbfa7631c742827c2f6f6db87b4ea" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "number_ops" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "91821a291117e033bfa4f013cd88de09479cd4ac43708e37a39df3f31c72aaa6", + "sha256": "91821a291117e033bfa4f013cd88de09479cd4ac43708e37a39df3f31c72aaa6", + "bytes": 67823 + }, + { + "name": "arcrun-rag-ui", + "main_module": "index.js", + "main_file": "tier2/ui/index.js", + "js_bytes": 723179, + "modules": [], + "compat_date": "2026-07-01", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": {} + }, + "source_commit": "15c5cedff39fe6567fc7d586254acb411fb7ad6d", + "source_content_sha256": "594637e14cd18c45b380ce118845ad58a549f3227cff284ea31efd25c005787f", + "sha256": "594637e14cd18c45b380ce118845ad58a549f3227cff284ea31efd25c005787f", + "bytes": 723179 + }, + { + "name": "arcrun-set", + "main_module": "worker.mjs", + "main_file": "arcrun-set/worker.mjs", + "js_bytes": 67676, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-set/component.wasm", + "sha256": "f5afcf6e57401d2d83b21fb971ec80ca56d5e8e4bdb74a004f3d118875ed57c4" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "set" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "6cac587802cae7dc1651d6b461232abafe40dcf0fbfe9e0adc5b1d8e35b41cc1", + "sha256": "6cac587802cae7dc1651d6b461232abafe40dcf0fbfe9e0adc5b1d8e35b41cc1", + "bytes": 67676 + }, + { + "name": "arcrun-string-ops", + "main_module": "worker.mjs", + "main_file": "arcrun-string-ops/worker.mjs", + "js_bytes": 67823, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-string-ops/component.wasm", + "sha256": "41f3243ee18bb9f4fcbaa417bd773347128dec2971132e240eddec19ba6a9da2" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "string_ops" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "c85166e357b76828c7020426d912b591006152ac38f024a095a4d9dcd10dee72", + "sha256": "c85166e357b76828c7020426d912b591006152ac38f024a095a4d9dcd10dee72", + "bytes": 67823 + }, + { + "name": "arcrun-switch", + "main_module": "worker.mjs", + "main_file": "arcrun-switch/worker.mjs", + "js_bytes": 67739, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-switch/component.wasm", + "sha256": "6d993dc9b1affe16b600aaa7cae5af977108cc08513bb11d9d9db908285fea8b" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "switch" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "e0e7689dbba735a254556272d6d233396c7fa05cc0fba5835a3e20b0ddf00fca", + "sha256": "e0e7689dbba735a254556272d6d233396c7fa05cc0fba5835a3e20b0ddf00fca", + "bytes": 67739 + }, + { + "name": "arcrun-try-catch", + "main_module": "worker.mjs", + "main_file": "arcrun-try-catch/worker.mjs", + "js_bytes": 67802, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-try-catch/component.wasm", + "sha256": "10eaddc5ef0d3dc68e3f009970541ac7f5fce30dcdbecec9a333afd5a29e3486" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "try_catch" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "a5fbcbf452ab00269dc857997df3059bee7eb1f2c1b322d249146ab4e5e5bac9", + "sha256": "a5fbcbf452ab00269dc857997df3059bee7eb1f2c1b322d249146ab4e5e5bac9", + "bytes": 67802 + }, + { + "name": "arcrun-validate-json", + "main_module": "worker.mjs", + "main_file": "arcrun-validate-json/worker.mjs", + "js_bytes": 67886, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-validate-json/component.wasm", + "sha256": "8142ffd3cc57efbb9128faaf450b646111b0f2e2575cc29a7b562a7b185912ab" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "validate_json" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "2d0efa26e9fe38db87eb9585daf72e0f2ba8c859d15d1b65f36798656cc4e83b", + "sha256": "2d0efa26e9fe38db87eb9585daf72e0f2ba8c859d15d1b65f36798656cc4e83b", + "bytes": 67886 + }, + { + "name": "arcrun-wait", + "main_module": "worker.mjs", + "main_file": "arcrun-wait/worker.mjs", + "js_bytes": 67697, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-wait/component.wasm", + "sha256": "52ca2d184bf3dcc646bb94f29f7f3e69b5540276363e83a54cb435ff33ca2f3c" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "wait" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "3d1b46e7b1ff056abb2c1aeed738d23d58eaa7c8f36b674e4ea2ed1602015f9e", + "sha256": "3d1b46e7b1ff056abb2c1aeed738d23d58eaa7c8f36b674e4ea2ed1602015f9e", + "bytes": 67697 + } + ], + "daemon": { + "version": "0.18.38", + "built": "20260826-2048", + "notes": "雲端被清空過的檔案,小幫手現在會自己發現並補送・重跑第二次不會又全部送一遍・補送的時候看得到", + "mac": { + "file": "daemon/Arcrun-0.18.38.dmg", + "sha256": "0b91b70295823f343166e31f53bd170ec315b5a4d84c4858424547bdafaf4aa5" + }, + "win": { + "file": "daemon/Arcrun-win-0.18.38.exe", + "sha256": "78f8e47b1d1d3e429af6c944fa1c873632e38a626157879a2e52745e58feec95" + }, + "msix": { + "file": "daemon/Arcrun-0.18.37.msix", + "sha256": "91b2c217891d6a06fb0269c090e5c2dd7aa2779a3a8ac72ec677b9f46ed0516d" + } + }, + "release": "1.4.55", + "built_for": "oauth-installer-lazy-load", + "notes": [ + "rag_takedown_direct 用了 __CARDS_PREFIX__,但安裝器的代換表沒有它 ⇒ 這個佔位符會原封不動被推進使用者的工作流。" + ], + "fingerprint": "83e5e42de07dac5a13f504af9ffc0649493322ab1cd9e40e0fe8aa0af83b73c3", + "library": [ + { + "name": "arcrun-array-ops", + "main_module": "worker.mjs", + "main_file": "arcrun-array-ops/worker.mjs", + "js_bytes": 67802, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-array-ops/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "array_ops" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "35ad5be6332dde2299efd10be726300c6cace1eb085ab24f08173536ca7fb950", + "first_install": true + }, + { + "name": "arcrun-auth-oauth2", + "main_module": "worker.mjs", + "main_file": "arcrun-auth-oauth2/worker.mjs", + "js_bytes": 80472, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-auth-oauth2/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [ + "CREDENTIALS_KV", + "RECIPES" + ], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "auth_oauth2" + } + }, + "source_commit": "20c7610371c401f622ef4e6ea1b9ba812963be95", + "source_content_sha256": "a9b0d45ee6a63e0eebd45554df16d9fa4e6e717e0c31dac13b630e132f1a96db", + "first_install": true + }, + { + "name": "arcrun-auth-service-account", + "main_module": "worker.mjs", + "main_file": "arcrun-auth-service-account/worker.mjs", + "js_bytes": 81693, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-auth-service-account/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [ + "CREDENTIALS_KV", + "RECIPES" + ], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "auth_service_account" + } + }, + "source_commit": "20c7610371c401f622ef4e6ea1b9ba812963be95", + "source_content_sha256": "68675ec76f3f060309492e55301936a47f4ae0a5e9b00865eb861e0e631e40e5", + "first_install": true + }, + { + "name": "arcrun-auth-static-key", + "main_module": "worker.mjs", + "main_file": "arcrun-auth-static-key/worker.mjs", + "js_bytes": 81217, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-auth-static-key/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [ + "CREDENTIALS_KV", + "RECIPES" + ], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "auth_static_key" + } + }, + "source_commit": "20c7610371c401f622ef4e6ea1b9ba812963be95", + "source_content_sha256": "140c163d2e8c609eebf281de25d16e521d85004f8437cc842613c249e44aa7ff", + "first_install": true + }, + { + "name": "arcrun-code", + "main_module": "worker.mjs", + "main_file": "arcrun-code/worker.mjs", + "js_bytes": 153758, + "modules": [ + { + "name": "quickjs.wasm", + "type": "application/wasm", + "file": "arcrun-code/quickjs.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "code" + } + }, + "source_commit": "621cb8d948d61be6202063fd02effb3f538437fe", + "source_content_sha256": "751634a3fc9a99cc2da662026818d754c48f031d10bff3b3be2d3a8ee2311bd6", + "first_install": true + }, + { + "name": "arcrun-cron", + "main_module": "worker.mjs", + "main_file": "arcrun-cron/worker.mjs", + "js_bytes": 78911, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-cron/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "cron" + } + }, + "source_commit": "6e92ca03727bf22143499d6c0df06b40cb65c17b", + "source_content_sha256": "17068f03f686aee6c0aec9d7d748bbb1998edc8918260033f985697bc718aa76", + "first_install": true + }, + { + "name": "arcrun-cypher-executor", + "main_module": "worker.mjs", + "main_file": "arcrun-cypher-executor/worker.mjs", + "js_bytes": 683598, + "modules": [], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat", + "global_fetch_strictly_public" + ], + "requires": { + "kv": [ + "EXEC_CONTEXT", + "WEBHOOKS", + "CREDENTIALS_KV", + "ANALYTICS_KV", + "RECIPES", + "USERS_KV", + "SESSIONS_KV" + ], + "d1": [ + { + "binding": "CREDENTIALS_DB", + "database_name": "arcrun-kbdb" + } + ], + "vectorize": 0, + "ai": true, + "vars": { + "ENVIRONMENT": "production", + "CF_ACCOUNT_ID": "", + "WORKER_SUBDOMAIN": "uncle6-me", + "KBDB_BASE_URL": "https://arcrun-kbdb.uncle6-me.workers.dev", + "CONSOLE_TENANT": "leo", + "PORTAL_SESSION_TTL": "604800", + "PORTAL_SHOW_WORKFLOWS": "admin", + "GITEA_BASE_URL": "https://git.uncle6.me", + "GITEA_SPRINT_REPO": "Leo/InkStoneCo", + "GITEA_SPRINT_DIR": "system-dev/docs/3-specs/autonomy-dispatch" + } + }, + "stripped": { + "services": 13 + }, + "source_commit": "72a18e30b06c2318fb71872ac9dcbbb6b47fab66", + "source_content_sha256": "d4ad7f488c673dfb886ee2bc02c909b62acecba6ffaf19aeedd6a9199fe9a1d4", + "first_install": true + }, + { + "name": "arcrun-date-ops", + "main_module": "worker.mjs", + "main_file": "arcrun-date-ops/worker.mjs", + "js_bytes": 67781, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-date-ops/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "date_ops" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "60ebc1d17ab0b9d3bb66f1c71ec63eb5d35bc97ed9f8b4cd1c1c95f4eeb171b7", + "first_install": true + }, + { + "name": "arcrun-filter", + "main_module": "worker.mjs", + "main_file": "arcrun-filter/worker.mjs", + "js_bytes": 67739, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-filter/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "filter" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "c7fd5070ff7c0f0341e9dd364805e393f9d68056a846f48e6bc61ef6f4e67187", + "first_install": true + }, + { + "name": "arcrun-foreach-control", + "main_module": "worker.mjs", + "main_file": "arcrun-foreach-control/worker.mjs", + "js_bytes": 67928, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-foreach-control/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "foreach_control" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "e52410c9611a93ac7fe38c7b11291cc18711c7da3370492788c3c55bc0fb03d5", + "first_install": true + }, + { + "name": "arcrun-http-request", + "main_module": "worker.mjs", + "main_file": "arcrun-http-request/worker.mjs", + "js_bytes": 80079, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-http-request/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat", + "global_fetch_strictly_public" + ], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "http_request" + } + }, + "source_commit": "1e85dfb49b0e8d81c0854781d93ee4e6a300c7b3", + "source_content_sha256": "cdd97364f277587cbade69e09bb40812c68f26a1e8bc9aa632c65b1b962b0b85", + "first_install": true + }, + { + "name": "arcrun-if-control", + "main_module": "worker.mjs", + "main_file": "arcrun-if-control/worker.mjs", + "js_bytes": 67823, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-if-control/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "if_control" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "557ecf4ee955105af07b2227b08365eb9de8c39ad8ffb323b101397704f438bd", + "first_install": true + }, + { + "name": "arcrun-kbdb", + "main_module": "worker.mjs", + "main_file": "arcrun-kbdb/worker.mjs", + "js_bytes": 185704, + "modules": [], + "compat_date": "2025-02-19", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [], + "d1": [ + { + "binding": "DB", + "database_name": "arcrun-kbdb" + } + ], + "vectorize": 0, + "ai": false, + "vars": { + "ENVIRONMENT": "production" + } + }, + "source_commit": "a1f45aef73de264236ff044e5b5fd5eb4d1cadc1", + "source_content_sha256": "68efc2b8958d1047c8d17f63325949af738379f8f1a2d509b9fa8bcf09440855", + "first_install": true + }, + { + "name": "arcrun-mcp", + "main_module": "worker.mjs", + "main_file": "arcrun-mcp/worker.mjs", + "js_bytes": 1193125, + "modules": [], + "compat_date": "2024-11-27", + "compat_flags": [ + "nodejs_compat" + ], + "requires": { + "kv": [ + "OAUTH_KV" + ], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": {} + }, + "source_commit": "c3efed7d1a01fc171df6eefb67d0bd380781be73", + "source_content_sha256": "e14dedfd630fed6e30f5d5f24a9d9b885899b81f4131ffb463705b151028c579", + "first_install": true + }, + { + "name": "arcrun-merge", + "main_module": "worker.mjs", + "main_file": "arcrun-merge/worker.mjs", + "js_bytes": 67718, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-merge/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "merge" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "e4216249436000bbb4db0318cc9028f936ca6537d3d656228cfdd3cb31df25f8", + "first_install": true + }, + { + "name": "arcrun-number-ops", + "main_module": "worker.mjs", + "main_file": "arcrun-number-ops/worker.mjs", + "js_bytes": 67823, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-number-ops/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "number_ops" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "91821a291117e033bfa4f013cd88de09479cd4ac43708e37a39df3f31c72aaa6", + "first_install": true + }, + { + "name": "arcrun-rag-ui", + "main_module": "index.js", + "main_file": "tier2/ui/index.js", + "js_bytes": 723179, + "modules": [], + "compat_date": "2026-07-01", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": {} + }, + "source_commit": "15c5cedff39fe6567fc7d586254acb411fb7ad6d", + "source_content_sha256": "594637e14cd18c45b380ce118845ad58a549f3227cff284ea31efd25c005787f", + "first_install": true + }, + { + "name": "arcrun-set", + "main_module": "worker.mjs", + "main_file": "arcrun-set/worker.mjs", + "js_bytes": 67676, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-set/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "set" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "6cac587802cae7dc1651d6b461232abafe40dcf0fbfe9e0adc5b1d8e35b41cc1", + "first_install": true + }, + { + "name": "arcrun-string-ops", + "main_module": "worker.mjs", + "main_file": "arcrun-string-ops/worker.mjs", + "js_bytes": 67823, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-string-ops/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "string_ops" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "c85166e357b76828c7020426d912b591006152ac38f024a095a4d9dcd10dee72", + "first_install": true + }, + { + "name": "arcrun-switch", + "main_module": "worker.mjs", + "main_file": "arcrun-switch/worker.mjs", + "js_bytes": 67739, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-switch/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "switch" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "e0e7689dbba735a254556272d6d233396c7fa05cc0fba5835a3e20b0ddf00fca", + "first_install": true + }, + { + "name": "arcrun-try-catch", + "main_module": "worker.mjs", + "main_file": "arcrun-try-catch/worker.mjs", + "js_bytes": 67802, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-try-catch/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "try_catch" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "a5fbcbf452ab00269dc857997df3059bee7eb1f2c1b322d249146ab4e5e5bac9", + "first_install": true + }, + { + "name": "arcrun-validate-json", + "main_module": "worker.mjs", + "main_file": "arcrun-validate-json/worker.mjs", + "js_bytes": 67886, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-validate-json/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "validate_json" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "2d0efa26e9fe38db87eb9585daf72e0f2ba8c859d15d1b65f36798656cc4e83b", + "first_install": true + }, + { + "name": "arcrun-wait", + "main_module": "worker.mjs", + "main_file": "arcrun-wait/worker.mjs", + "js_bytes": 67697, + "modules": [ + { + "name": "component.wasm", + "type": "application/wasm", + "file": "arcrun-wait/component.wasm" + } + ], + "compat_date": "2025-02-19", + "compat_flags": [], + "requires": { + "kv": [], + "d1": [], + "vectorize": 0, + "ai": false, + "vars": { + "COMPONENT_ID": "wait" + } + }, + "source_commit": "922a57fe3458dfda82bcc25d287cef93f8dab838", + "source_content_sha256": "3d1b46e7b1ff056abb2c1aeed738d23d58eaa7c8f36b674e4ea2ed1602015f9e", + "first_install": true + } + ], + "first_install_reasons": [ + { + "worker": "arcrun-cypher-executor", + "why": "工作流引擎本身。沒有它,這台機器上什麼都不會執行。" + }, + { + "worker": "arcrun-kbdb", + "why": "知識庫資料層。ingest 寫進去、查詢讀出來,都只有這一個入口(D38:一律 API)。" + }, + { + "worker": "arcrun-rag-ui", + "why": "portal 前端。這是使用者**唯一**看得到的畫面——沒有它,裝完等於沒有產品。" + }, + { + "worker": "arcrun-mcp", + "why": "leo 2026-08-10:「今天只要清單含有 MCP 即可」。產品承諾是「把自己的 AI 接上自己的知識庫」,MCP 就是那條線;缺它的話那句承諾從第一步就不成立(prod 1.4.30 曾整包沒有它)。" + }, + { + "worker": "arcrun-http-request", + "why": "graph_neighbors/fetch_triplets 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-code", + "why": "graph_neighbors/bfs_neighbors 用 __CODE_URL__" + }, + { + "worker": "arcrun-auth-static-key", + "why": "graph_neighbors 用 {{credential.kbdb_internal_token}},解憑證要打這顆" + }, + { + "worker": "arcrun-code", + "why": "rag_chat/prep 用 __CODE_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_chat/select_libraries 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-code", + "why": "rag_chat/pick_libs 用 __CODE_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_chat/fetch_pages 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-code", + "why": "rag_chat/assemble 用 __CODE_URL__" + }, + { + "worker": "arcrun-code", + "why": "rag_chat/finalize 用 __CODE_URL__" + }, + { + "worker": "arcrun-auth-static-key", + "why": "rag_chat 用 {{credential.kbdb_internal_token}},解憑證要打這顆" + }, + { + "worker": "arcrun-http-request", + "why": "rag_ingest_card/list_old_blocks 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_ingest_card/list_old_triplets 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-code", + "why": "rag_ingest_card/pick_stale 用 __CODE_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_ingest_card/delete_entry 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_ingest_card/delete_record 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-code", + "why": "rag_ingest_card/parse_card 用 __CODE_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_ingest_card/post_block 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_ingest_card/post_triplet 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-auth-static-key", + "why": "rag_ingest_card 用 {{credential.kbdb_internal_token}},解憑證要打這顆" + }, + { + "worker": "arcrun-code", + "why": "rag_takedown_direct/prep 用 __CODE_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_takedown_direct/list_dead_blocks 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-code", + "why": "rag_takedown_direct/build_deprecations 用 __CODE_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_takedown_direct/deprecate_entry 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_takedown_direct/list_triplets 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-code", + "why": "rag_takedown_direct/pick_dead_triplets 用 __CODE_URL__" + }, + { + "worker": "arcrun-http-request", + "why": "rag_takedown_direct/deprecate_triplet 用 __HTTP_REQ_URL__" + }, + { + "worker": "arcrun-auth-static-key", + "why": "rag_takedown_direct 用 {{credential.kbdb_internal_token}},解憑證要打這顆" + } + ] +} diff --git a/tier2/ui/index.js b/tier2/ui/index.js index bd6ce6b..7a6a573 100644 --- a/tier2/ui/index.js +++ b/tier2/ui/index.js @@ -1,6 +1,6 @@ // arcrun-rag-ui — 用戶實例的 GUI(console-ui/public 內嵌;由 Arcrun scripts/build-ui-worker.mjs 產生,勿手改) -const FILES = {"/apple-touch-icon.png":{"type":"image/png","b64":true,"data":"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"},"/console/dashboard/index.html":{"type":"text/html; charset=utf-8","b64":false,"data":"\n\n\n\n\nArcrun 駕駛艙\n\n\n\n\n\n\n
\n
\n
Arcrun 駕駛艙
\n
\n
\n \n
\n
\n
\n
\n
\n
載入中
\n
\n
\n
\n
\n
\n
今日完成
\n
/
\n
\n
\n
\n
收件匣未處理
\n
\n
來自 Telegram
\n
\n
\n
\n
等你的事
\n
載入中…
\n
\n
\n
今日路線
\n \n
本週
\n \n
系統狀況live 健康信號
\n
載入中…
\n
每 60 秒自動刷新
\n 進入完整控制台 ›\n
\n\n\n\n"},"/console/index.html":{"type":"text/html; charset=utf-8","b64":false,"data":"\n\n\n\n\nArcrun Console\n\n\n\n\n\n\n\n\n
\n
\n
\n
Arcrun
\n
私人系統・僅供擁有者進入
\n
\n
\n \n \n \n
\n
\n
這是一個人的智慧總部。
若你不是擁有者,這裡沒有你要找的東西。
\n \n \n
\n
\n\n\n
\n
\n
\n
Arcrun
\n
首次設定
\n
系統偵測到尚未設定擁有者帳號。
設定一組 Email 與密碼,之後只有你能進入。
\n
\n
\n \n \n \n \n
\n
\n \n
\n
\n\n\n
\n
\n
Arcrun
\n \n
總庫搜尋
\n
工作流
\n \n
設定
\n
☾ 切深色
\n
\n
\n
\n\n \n
\n
Arcrun 控制台
\n
\n
\n
\n
\n
\n
載入中
\n
\n
\n
\n
\n
\n
今日完成
\n
/
\n
\n
\n
\n
收件匣未處理
\n
\n
來自 Telegram
\n
\n
\n
\n
等你的事
\n
載入中…
\n
\n
\n
\n
\n
\n 今日路線狀態即時同步\n
\n
  • 載入中…
\n
本週
\n
    \n
    每 60 秒自動刷新
    \n
    \n
    \n
    \n\n \n
    \n
    總庫搜尋
    \n
    \n
    \n
    \n 藏書地圖\n
    \n
    地圖載入中…
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n \n
    \n
    \n \n 知識卡片\n
    \n
    \n
    載入中…
    \n
    \n
    關聯視圖
    \n
    \n
    \n
    \n
    \n
    \n\n \n
    \n
    工作流
    \n \n
    載入中…
    \n
    \n
    零件與 Recipes(框架資源)
    \n
    \n \n \n
    \n
    \n
    \n
    \n\n \n
    \n
    憑證管理
    \n
    \n 🛡 保險箱原則:系統只保存目錄與加密後的值,任何頁面都看不到密文內容。只能整筆替換或刪除。\n
    \n
    \n
    新增憑證
    \n
    \n \n \n \n \n
    \n
    \n
    \n
    載入中…
    \n
    \n\n \n
    \n
    分流台全部待辦・80/15/5
    \n
    \n
    載入中…
    \n
    \n\n \n
    \n
    設定
    \n
    \n
    \n
    \n
    \n
    深色模式
    \n
    預設淺色(紙感)。切換立即生效,選擇記在這台裝置(localStorage)。
    \n
    \n
    \n
    \n
    \n
    \n \n
    語意搜尋
    \n
    狀態偵測中…
    \n
    \n
    \n
    \n
    MCP token 有效期(TTL)
    \n
    讀取中…
    \n
    \n 誠實佔位:此頁還不能改這個值——可調功能=Arcrun#19(設定頁改→存 KBDB→發 token 時讀)。實作前要調整請在部署端 env MCP_TOKEN_TTL(mcp worker)設定。\n
    \n
    \n
    \n
    更換帳號密碼
    \n
    需輸入舊密碼驗證身分
    \n
    \n \n \n \n \n
    \n
    \n
    \n \n
    \n
    Portal 帳號密碼救援
    \n
    忘記某個 Portal(RAG 搜尋頁)帳號的密碼,包含你自己那組管理員帳號——不需要先登進 Portal。輸入該帳號的 Email,會產生一組新密碼,只顯示這一次,請立刻抄下並拿去 Portal 登入頁使用。
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    系統資訊
    \n
    載入中…
    \n
    \n \n
    \n
    \n\n
    \n
    \n\n\n
    \n \n
    搜尋
    \n
    工作流
    \n \n
    設定
    \n
    \n\n
    \n\n\n\n\n"},"/favicon.ico":{"type":"image/x-icon","b64":true,"data":"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"},"/favicon.svg":{"type":"image/svg+xml","b64":false,"data":"arcrun icon"},"/index.html":{"type":"text/html; charset=utf-8","b64":false,"data":"\n\n\n\nArcrun RAG\n\n\n\n\n\n\n\n

    正在前往搜尋頁… 沒有自動跳轉請點這裡

    \n\n\n"},"/portal/app-mount.test.mjs":{"type":"application/javascript; charset=utf-8","b64":false,"data":"// App 掛載協定 v0.2 的結構自測(Arcrun#152/#82,leo 2026-08-24 拍板)\n// 跑法:node console-ui/public/portal/app-mount.test.mjs\n//\n// 這支守的是**協定的形狀**,不是長相——長相要用瀏覽器量(見 #152 的驗收留言)。\n// 之所以要有它:這一輪的病根是「出口與樣式被做成個案」——筆記 App 有返回鍵、總圖沒有;\n// CIS 表複製進 shadow 了、但 App 根本沒接上。個案會悄悄再長出來,所以把\n// 「不准再有個案」這件事寫成可執行的檢查。\nimport fs from 'node:fs';\n\nconst html = fs.readFileSync(new URL('./index.html', import.meta.url).pathname, 'utf8');\nlet pass = 0, fail = 0;\nconst chk = (label, cond, extra = '') => {\n if (cond) { console.log('PASS:', label); pass++; }\n else { console.log('FAIL:', label, extra); fail++; }\n};\n\n// ── ① 出口:每一個非首頁的 view 都必須有 .pagehead ────────────────────────────\n// ensureBackControls() 是往 `#v- .pagehead` 裡塞返回鍵的。少了那一列 = 那個 view\n// 悄悄沒有出口,而且沒有人會發現(leo 就是這樣卡在總圖)。\nconst viewsLine = html.match(/var VIEWS = \\[(.*?)\\];/);\nif (!viewsLine) throw new Error('抽不到 VIEWS 清單');\nconst VIEWS = viewsLine[1].split(',').map((s) => s.trim().replace(/^'|'$/g, ''));\nconst HOME = (html.match(/var HOME = '([^']+)'/) || [])[1];\nchk('抽得到 VIEWS 與 HOME', VIEWS.length > 0 && !!HOME, `VIEWS=${VIEWS.length} HOME=${HOME}`);\n\nfor (const v of VIEWS) {\n if (v === HOME) continue;\n // 抓 `
    \">` 之後、下一個 view 之前那一段,看有沒有 pagehead\n const at = html.indexOf(`id=\"v-${v}\"`);\n if (at < 0) { chk(`view ${v} 存在於 HTML`, false); continue; }\n const nextView = html.indexOf('id=\"v-', at + 10);\n const block = html.slice(at, nextView < 0 ? at + 4000 : nextView);\n chk(`非首頁 view「${v}」有 .pagehead(返回鍵才掛得上)`, /class=\"pagehead\"/.test(block));\n}\n\n// ── ② 不准再有「某一頁自己的返回鍵」 ─────────────────────────────────────────\nchk('沒有殘留的個案返回鍵(app-back-btn 已撤)', !html.includes('app-back-btn'));\nchk('返回鍵只由 ensureBackControls() 產生(全檔只有一處 createElement 出 data-portal-back)',\n (html.match(/setAttribute\\('data-portal-back'/g) || []).length === 1);\nchk('返回鍵是頁首第一格(insertBefore firstChild)', /insertBefore\\(b, head\\.firstChild\\)/.test(html));\nchk('返回鍵一律回 HOME', /data-portal-back\\]'\\)\\) nav\\(HOME\\)/.test(html));\n\n// ── ③ 樣式:兩種模式與層序 ──────────────────────────────────────────────────\nchk('層序=arcrun-base < app < arcrun(全局在最上面才蓋得過 App)',\n html.includes('@layer arcrun-base, app, arcrun;'));\nchk('沒宣告=跟隨全局(預設 inherit,不是維持 App 原樣)',\n /var inherit = style !== 'own';/.test(html));\nchk('App 自己的 style 會被包進 app 層', /'@layer app\\{' \\+ st\\.textContent \\+ '\\}'/.test(html));\nchk('全局色票/CIS 都進 arcrun 層', (html.match(/'@layer arcrun\\{'/g) || []).length === 2);\nchk('樣式模式從 App 宣告來(不是 Portal 猜的)', /mountAppUi\\(host, app\\.ui_html, app\\.ui_style\\)/.test(html));\n\n// ── ④ 畫布是全局決定的(兩種模式都一樣)────────────────────────────────────\n// leo:「全局要給它多大的畫布也是全局決定的⋯⋯應該整個右側邊欄都是它的」\nchk('App 頁不吃 .page 的寬度上限與左右留白', /#v-app\\.on \\{[^}]*max-width: none;[^}]*padding: 0;/.test(html));\nchk('shadow host 由**外部文件**決定尺寸(App 在 shadow 裡改不動)',\n /#app-ui-mount \\{[^}]*width: 100%/.test(html));\n\n// ── ⑤ 隔離沒有被拆掉(這一輪的紅線)──────────────────────────────────────\nchk('App 仍然掛進 Shadow DOM', /host\\.attachShadow\\(\\{ mode: 'open' \\}\\)/.test(html));\n\nconsole.log(`\\n${fail === 0 ? '✅' : '❌'} pass=${pass} fail=${fail}`);\nprocess.exit(fail === 0 ? 0 : 1);\n"},"/portal/index.html":{"type":"text/html; charset=utf-8","b64":false,"data":"\n\n\n\n\nArcrun Portal\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\n
    \n
    \n
    \n
    \"arc>run\" width=\"986\" height=\"176\">\"arc>run\" width=\"986\" height=\"176\">
    \n
    知識入口・Portal
    \n
    \n
    \n \n \n \n
    \n
    \n \n
    \n 忘記密碼了?寄一條「修改密碼」連結給我\n
    \n
    \n \n \n
    \n
    \n \n
    \n
    \n\n\n
    \n
    \n
    \n
    設定新密碼
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \"arc>run\" width=\"986\" height=\"176\">\"arc>run\" width=\"986\" height=\"176\">
    \n
    歡迎!先建立你的帳號
    \n
    \n
    \n \n \n \n \n
    \n \n \n
    \n
    這組帳密就是之後登入知識庫用的,只需要設定這一次。
    \n
    \n
    \n\n\n
    \n
    \n
    \"arcrun\"\"arcrun\"
    \n \n
    App 界面
    \n
    App 市集
    \n
    AR 設定
    \n
    App 開發
    \n
    ☾ 切深色
    \n
    \n
    \n
    \n\n \n
    \n
    App 界面
    \n
    載入中…
    \n
    \n\n \n
    \n
    搜尋
    \n
    \n
    \n \n \n
    \n
    \n \n \n \n
    \n \n
    \n
    AI 問答・答案附出處,可回搜尋驗證
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n \n
    \n
    總圖
    \n
    \n
    \n
    \n 點節點可跳到該實體的圖譜搜尋。這張圖由知識庫的三元組即時算出——同一份地圖的文字版\n (給 AI 注入用的總庫目錄)。\n
    \n
    \n
    \n\n \n
    \n
    \n \n 知識卡片\n
    \n
    載入中…
    \n
    \n\n \n
    \n
    App 市集瀏覽、安裝、或上傳你自己做的 App
    \n
    \n
    \n
    \n
    \n
    上傳你的 App
    \n
    打包成一份宣告,讓其他人也能安裝——尚未接後端,先佔位
    \n
    \n
    \n
    已安裝
    \n
    載入中…
    \n
    可安裝
    \n \n
    載入中…
    \n
    \n
    \n\n \n
    \n
    上傳Markdown / 純文字
    \n
    \n 上傳的文件會進入知識庫收件管線:約 1 分鐘後可在搜尋頁找到;AI 整理後會以 wiki 卡形式出現。支援 .md / .txt(一律以 .md 收件)。\n
    \n
    \n
    把 .md / .txt 檔案拖放到這裡
    \n
    \n \n \n
    \n
    \n
    \n\n \n \n
    \n
    App 開發Workflows/零件/Recipe/Credential
    \n
    \n
    \n
    \n
    \n
    叫 AI 幫你做一個 App
    \n
    用一句話描述你要什麼——尚未接後端,先佔位
    \n
    \n
    \n
    工作環境
    \n
    \n
    \n Workflows\n
    \n
    \n 資料上傳\n
    \n
    零件尚未接進 Portal
    \n
    Recipe尚未接進 Portal
    \n
    Credential尚未接進 Portal
    \n
    \n
    \n
    \n\n
    \n
    工作流唯讀・系統狀態
    \n
    \n 此頁只顯示系統裡的工作流與最近執行狀態,不能觸發執行(觸發屬系統擁有者權限)。\n
    \n
    載入中…
    \n
    \n\n \n
    \n
    \n \n App\n \n
    \n
    載入中…
    \n
    \n\n \n
    \n
    設定
    \n \n
    \n
    帳號
    \n
    管理
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n 版本\n \n
    \n
    查詢中…
    \n
    \n \n
    \n
    \n
    \n
    我的帳號
    \n
    載入中…
    \n
    \n
    \n
    \n
    \n
    深色模式
    \n
    預設淺色(紙感)。切換立即生效,選擇記在這台裝置。
    \n
    \n
    \n
    \n
    \n \n
    \n
    更改密碼
    \n
    需輸入舊密碼驗證身分;新密碼至少 8 碼
    \n
    \n \n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n 你的知識庫網址(小幫手連線用)\n \n \n
    \n
    同步小幫手
    \n
    把你電腦上的資料夾變成知識庫。換電腦或重裝時可以再下載一次。
    \n
    \n 下載 Mac 版\n
    封測版未簽章,第一次請右鍵→打開。裝好第一次開啟時,貼上這個網址+你的帳號密碼就連上了。
    \n
    \n
    \n \n
    \n
    \n 你的 MCP 網址(給你的 AI 連線用)\n \n \n
    \n
    接上你的 AI(MCP)
    \n
    把上面這串網址貼到 Claude、ChatGPT 等 AI 的「新增自訂連接器」欄位,就能讓你的 AI 直接查這個知識庫。
    \n
    \n \n
    \n
    AI 設定
    \n
    \n 這裡不需要任何設定。聊天問答用的是你自己 Cloudflare 帳號內建的 AI,裝好就能直接問。
    \n 文件整理成知識卡的部分,請在同步小幫手(電腦上的托盤圖示)的「AI 設定…」填一把 Gemini API Key。\n
    \n
    \n \n
    \n
    疑難排解
    \n
    要回報問題,請到你電腦上的 Arcrun(同步小幫手)「版本與更新」頁——那裡的「疑難排解」按一下就能匯出完整診斷檔給我們(只有統計數字,不含你的任何文件內容)。
    \n
    \n \n
    \n
    \n\n \n
    \n
    管理帳號與知識庫授權
    \n
    \n
    帳號
    \n
    管理
    \n
    \n\n
    執行紀錄保留期
    \n
    \n
    保留天數
    \n
    執行紀錄是稽核資料,超過保留天數會被每日自動清除;預設 90 天(3 個月),也可設為「不刪除」(企業稽核用途)。
    \n
    \n \n \n \n
    \n
    \n
    \n
    \n\n
    帳號管理
    \n
    \n
    新增同仁帳號
    \n
    建立後會產生一組一次性密碼——只顯示這一次,請當場轉交同仁(同仁可在「設定」自行改密)。
    \n
    \n \n \n \n \n
    \n
    \n
    \n
    \n
    載入中…
    \n\n
    庫目錄管理
    \n
    \n 你的知識庫網址(小幫手連線用)\n \n \n
    \n
    \n \n 裝好同步小幫手並選好要看守的資料夾之後,每個資料夾會自動成為一個「庫」出現在下面——不需要人工新增。下面還是空的,代表小幫手還沒裝好或還沒選資料夾。\n
    \n
    載入中…
    \n
    \n\n
    \n
    \n\n\n
    \n
    App 界面
    \n
    App 市集
    \n
    AR 設定
    \n
    App 開發
    \n
    \n\n
    \n\n\n\n"},"/portal/os-split.test.mjs":{"type":"application/javascript; charset=utf-8","b64":false,"data":"import fs from 'node:fs';\nconst html = fs.readFileSync(new URL('./index.html', import.meta.url).pathname,'utf8');\n// 抽出 daemonPick 相關函式(從 DAEMON_BASE_DEFAULT 到 daemonHint 結尾)\n//\n// 🔴 2026-08-05:結尾標記本來寫死 daemonHint 的**整句文案**,於是同日改 Mac 提示語\n// (zip→DMG 的步驟不同)就讓這支自測直接炸「抽不到函式區塊」,而且沒人發現。\n// ⇒ 改成錨定「函式結束」這個結構,不再綁文案——文案本來就會改,測試不該為此壞掉。\nconst start = html.indexOf('var DAEMON_BASE_DEFAULT');\nconst hintAt = html.indexOf('function daemonHint', start);\nconst endMark = '\\n }';\nconst end = hintAt < 0 ? -1 : html.indexOf(endMark, hintAt) + endMark.length;\nif (start < 0 || hintAt < 0 || end < start) throw new Error('抽不到函式區塊');\nconst src = html.slice(start, end);\n\nconst cases = [\n ['Windows', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Safari/537.36'],\n ['Mac', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Safari/605.1.15'],\n ['iPhone', 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 Safari/604.1'],\n ['Linux', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120 Safari/537.36'],\n];\nlet pass=0, fail=0;\nconst chk=(l,c,extra='')=>{ if(c){console.log('PASS:',l);pass++;} else {console.log('FAIL:',l,extra);fail++;} };\n\nfor (const [name, ua] of cases) {\n const fn = new Function('navigator','window', src + '; return {daemonPick:daemonPick, daemonHint:daemonHint, daemonBase:daemonBase};');\n const api = fn({userAgent: ua}, {});\n const d = api.daemonPick();\n const label = d.sure ? d.pick.label : '(兩個都給)';\n const url = d.sure ? d.pick.url : d.mac.url + ' + ' + d.win.url;\n console.log(`\\n[${name}] sure=${d.sure} → ${label}`);\n console.log(` url: ${url}`);\n if (name==='Windows') {\n chk('Windows 給 win zip', d.sure && d.pick.url.endsWith('ArcrunRAG-win-unsigned.zip'), d.pick&&d.pick.url);\n chk('Windows 另一版是 Mac', d.other && d.other.url.endsWith('ArcrunRAG-mac.dmg'));\n chk('Windows 話術提 藍色視窗', api.daemonHint('win').includes('仍要執行'));\n }\n if (name==='Mac') {\n // 2026-08-05:Mac 一律給 DMG(拖進 Applications 的標準安裝畫面),不再給 zip\n // ——zip 解開就是一個裸 .app,使用者會直接在「下載」資料夾雙擊執行,自更新會蓋錯位置。\n chk('Mac 給 dmg(不是 zip)', d.sure && d.pick.url.endsWith('ArcrunRAG-mac.dmg'));\n chk('Mac 另一版是 Windows', d.other && d.other.url.endsWith('win-unsigned.zip'));\n chk('Mac 話術提 右鍵打開', api.daemonHint('mac').includes('右鍵'));\n }\n if (name==='iPhone' || name==='Linux') {\n // iPhone 含 \"Mac OS X\" 但不是桌機 Mac;Linux 兩者皆非 → 都該落在「不確定=兩個都給」\n if (name==='Linux') chk('Linux 判不出來→兩個都給', d.sure===false);\n if (name==='iPhone') chk('iPhone 不該被判成 Mac(手機→兩個都給)', d.sure===false, 'sure='+d.sure);\n }\n}\n// 舊 key 相容\nconst fn2 = new Function('navigator','window', src + '; return daemonBase();');\nconsole.log('\\n[相容] daemonDownload 舊 key →', fn2({userAgent:''},{ARCRUN_CONFIG:{daemonDownload:'https://x.dev/d/ArcrunRAG-mac-unsigned.zip'}}));\nchk('舊 key 推得出目錄', fn2({userAgent:''},{ARCRUN_CONFIG:{daemonDownload:'https://x.dev/d/ArcrunRAG-mac-unsigned.zip'}})==='https://x.dev/d/');\nchk('daemonBase 新 key 優先', fn2({userAgent:''},{ARCRUN_CONFIG:{daemonBase:'https://y.dev/z'}})==='https://y.dev/z/');\nconsole.log(`\\n=== ${pass} passed, ${fail} failed ===`);\nprocess.exit(fail?1:0);\n"},"/portal/retrieval-tree.test.mjs":{"type":"application/javascript; charset=utf-8","b64":false,"data":"// 檢索過程樹(Arcrun#44 第二輪,leo 2026-08-18「希望以樹狀圖來展示」)的資料組裝測試。\n// 只測**樹的資料**,不測 markmap 怎麼畫——畫圖是現成函式庫的事(D97),\n// 我們自己要為之負責的是「層級對不對、有沒有把讀過的東西吞掉」。\n// 跑法:node console-ui/public/portal/retrieval-tree.test.mjs\nimport fs from 'node:fs';\nconst html = fs.readFileSync(new URL('./index.html', import.meta.url).pathname, 'utf8');\n\nconst grab = (name) => {\n const i = html.indexOf(`function ${name}(`);\n if (i < 0) throw new Error(`找不到 ${name}`);\n let d = 0, j = html.indexOf('{', i);\n for (let k = j; k < html.length; k++) { if (html[k] === '{') d++; if (html[k] === '}') { d--; if (!d) return html.slice(i, k + 1); } }\n throw new Error('括號不平衡');\n};\nconst src = ['esc', 'srcLocalPath', 'machineLabelMap', 'srcCrumbs', 'retrievalTreeData', 'visibleLeaves', 'treeListHtml'].map(grab).join('\\n');\nconst fn = new Function(src + '\\nvar SEARCH_ROUTE_LABEL = { graph: \"圖譜命中子庫\", index: \"索引退回選庫\", all: \"全庫讀取\" };'\n + '\\nreturn { srcCrumbs, machineLabelMap, retrievalTreeData, visibleLeaves, treeListHtml };')();\n\nlet pass = 0, fail = 0;\nconst t = (l, c, e = '') => { c ? (console.log('PASS:', l), pass++) : (console.log('FAIL:', l, e), fail++); };\nconst txt = (n) => String(n.content).replace(/<[^>]*>/g, '');\n\n// 2026-08-18 從 youlin stage 實跑 /portal/data/chat 抓下來的真回應形狀(narrative 真的是空字串)\nconst REAL = {\n route: 'graph', vector_used: false, libraries_considered: 8,\n libraries: [{ library: 'testkb', score: 1.69, via: 'graph', matched_entities: ['Arcrun124驗證卡'] }],\n indexes_read: [\n { library: 'general', narrative: '', selected: false, top_entities: [], triplet_count: 0, entry_count: 100 },\n { library: 'testkb', narrative: '', selected: true, top_entities: ['Arcrun124驗證卡'], triplet_count: 4, entry_count: 9 },\n { library: 'kb', narrative: '', selected: false, top_entities: ['knowledge-base'], triplet_count: 7, entry_count: 16 }\n ],\n pages_read: [{ page: 'Arcrun124驗證卡', library: 'testkb', chars: 231, source: 'kb://test/arcrun-124-verify.md#0' }]\n};\n\n// ① 層級=leo 畫的那張:搜尋詞 → 命中子庫 → 索引敘事 → 原文片段\nconst tree = fn.retrievalTreeData('Arcrun124驗證卡是什麼?', REAL);\nt('第 1 層是搜尋詞', txt(tree).indexOf('Arcrun124驗證卡是什麼?') === 0, txt(tree));\nconst lib = tree.children[0];\nt('第 2 層是命中子庫(帶分數與命中實體)', /testkb/.test(txt(lib)) && /1\\.69/.test(txt(lib)) && /命中實體/.test(txt(lib)), txt(lib));\nconst idx = lib.children[0];\nt('第 3 層是該子庫的索引敘事', /三元組/.test(txt(idx)) && /筆條目/.test(txt(idx)), txt(idx));\nconst page = idx.children[0];\nt('第 4 層是原文片段(掛在索引敘事底下)', /Arcrun124驗證卡/.test(txt(page)) && /231 字/.test(txt(page)), txt(page));\nt('原文片段帶資料夾麵包屑', /test › arcrun-124-verify\\.md/.test(txt(page)), txt(page));\n\n// ② narrative 是空字串時不假裝有敘事(線上真資料就是這樣)\nt('沒有敘事就說沒有,不留空白', /索引沒有敘事/.test(txt(idx)), txt(idx));\n\n// ③ 沒被選用的子庫不可以被吞掉,但要收合起來不擠掉主線\nconst rest = tree.children[tree.children.length - 1];\nt('沒讀原文的子庫收在一個節點底下', /考慮過但沒讀原文(2 個子庫)/.test(txt(rest)), txt(rest));\nt('那個節點預設收合', rest.payload && rest.payload.fold === 1, JSON.stringify(rest.payload));\nt('主線只有命中的子庫', tree.children.length === 2, `實得 ${tree.children.length} 條分支`);\n\n// ④ 讀了原文、但沒出現在 libraries[] 的子庫(route=all)也要長出來\nconst allRoute = fn.retrievalTreeData('問句', {\n route: 'all', libraries: [], indexes_read: [],\n pages_read: [{ page: 'P', library: 'kb', chars: 10, source: 'kb://a/b/c.md#2' }]\n});\nt('route=all 時仍有子庫分支', allRoute.children.length === 1 && /kb/.test(txt(allRoute.children[0])), txt(allRoute.children[0]));\nt('沒有索引敘事時不生假的中間層', /^P/.test(txt(allRoute.children[0].children[0])), txt(allRoute.children[0].children[0]));\n\n// ⑤ 完全沒資料時不要生一棵空樹\nconst empty = fn.retrievalTreeData('問句', { route: 'all', libraries: [], indexes_read: [], pages_read: [] });\nt('沒有任何子庫時說明原因', /全庫作答|沒有回報/.test(txt(empty.children[0])), txt(empty.children[0]));\n\n// ⑥ 麵包屑:資料夾可以有很多層,全部拆開;機器那一層現在是「沒有」\nconst c = fn.srcCrumbs('kb://RFP/2026/design.md#3', 'kb');\nt('多層資料夾全部拆開', JSON.stringify(c.dirs) === '[\"RFP\",\"2026\"]', JSON.stringify(c.dirs));\nt('檔名拆得出來', c.file === 'design.md', c.file);\nt('片段編號拆得出來', c.frag === '3', c.frag);\nt('子庫帶得進來', c.library === 'kb', c.library);\nt('機器那一層是 null(資料裡真的沒有)', c.machine === null, String(c.machine));\nt('相對路徑原樣留著(複製給用戶去本機找)', c.path === 'RFP/2026/design.md', c.path);\n\nconst g = fn.srcCrumbs('gitea:Leo/InkStoneCo@wiki/x.md#1', 'kb');\nt('非 kb:// 來源不硬拆成假麵包屑', g.path === '' && g.file === '' && g.dirs.length === 0, JSON.stringify(g));\n\n// ⑦ markmap 載不進來時的退路:同一份樹資料畫成巢狀清單\nconst list = fn.treeListHtml(tree);\nt('退路是巢狀清單', /