ship 1.4.60:Arcrun@98b45409740b
This commit is contained in:
@@ -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@f87260b1234f` by `installer/scripts/ship.mjs`(arcrun-rag repo,release 1.4.59,built 2026-08-27)。
|
||||
Built from `Arcrun@98b45409740b` by `installer/scripts/ship.mjs`(arcrun-rag repo,release 1.4.60,built 2026-08-27)。
|
||||
|
||||
⚠️ 這份檔案由出貨管線每次自動重寫(`installer/scripts/render-bundles-readme.mjs`)——
|
||||
不要手動改這裡列的零件清單——它是算出來的:公庫=Arcrun 這一版編了什麼,
|
||||
|
||||
@@ -12978,7 +12978,87 @@ var PORTAL_TEMPLATE_SEEDS = [
|
||||
|
||||
// cypher-executor/src/routes/portal.ts
|
||||
init_credentials();
|
||||
|
||||
// cypher-executor/src/lib/ai-response.ts
|
||||
function pickChatContent(o) {
|
||||
const choices = o.choices;
|
||||
if (!Array.isArray(choices) || choices.length === 0) return void 0;
|
||||
const first = choices[0];
|
||||
if (!first || typeof first !== "object") return void 0;
|
||||
const msg = first.message;
|
||||
if (!msg || typeof msg !== "object") return void 0;
|
||||
const content = msg.content;
|
||||
return typeof content === "string" && content.length > 0 ? content : void 0;
|
||||
}
|
||||
function pickResponseValue(out) {
|
||||
if (out === null || out === void 0) return void 0;
|
||||
if (typeof out === "string") return out;
|
||||
if (typeof out !== "object") return out;
|
||||
const o = out;
|
||||
const chat = pickChatContent(o);
|
||||
if (chat !== void 0) return chat;
|
||||
if ("response" in o) return o.response;
|
||||
const result = o.result;
|
||||
if (result && typeof result === "object") {
|
||||
const r = result;
|
||||
const rc = pickChatContent(r);
|
||||
if (rc !== void 0) return rc;
|
||||
if ("response" in r) return r.response;
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
function normalizeAiText(out) {
|
||||
const v = pickResponseValue(out);
|
||||
if (v === null || v === void 0) return { text: "", kind: "empty" };
|
||||
if (typeof v === "string") return { text: v.trim(), kind: v.trim() ? "string" : "empty" };
|
||||
if (typeof v === "number" || typeof v === "boolean" || typeof v === "bigint") {
|
||||
return { text: String(v), kind: "scalar" };
|
||||
}
|
||||
if (typeof v === "object") {
|
||||
try {
|
||||
const s = JSON.stringify(v);
|
||||
if (typeof s !== "string") {
|
||||
return { text: "", kind: "unrenderable", reason: "JSON.stringify \u56DE undefined" };
|
||||
}
|
||||
return { text: s, kind: "json" };
|
||||
} catch (e) {
|
||||
return {
|
||||
text: "",
|
||||
kind: "unrenderable",
|
||||
reason: e instanceof Error ? e.message : "\u7121\u6CD5\u5E8F\u5217\u5316"
|
||||
};
|
||||
}
|
||||
}
|
||||
return { text: "", kind: "unrenderable", reason: `\u672A\u9810\u671F\u7684\u578B\u5225 ${typeof v}` };
|
||||
}
|
||||
function parseExpectShape(raw2, hasPrompt) {
|
||||
const s = String(raw2 ?? "").trim();
|
||||
if (s === "json_object" || s === "text") return s;
|
||||
return hasPrompt ? "json_object" : "text";
|
||||
}
|
||||
function hasJsonObject(text) {
|
||||
const start = text.indexOf("{");
|
||||
const end = text.lastIndexOf("}");
|
||||
if (start < 0 || end <= start) return { ok: false, reason: "\u6574\u6BB5\u56DE\u61C9\u88E1\u627E\u4E0D\u5230 JSON \u7269\u4EF6\uFF08\u6C92\u6709\u6210\u5C0D\u7684\u5927\u62EC\u865F\uFF09" };
|
||||
try {
|
||||
const parsed = JSON.parse(text.slice(start, end + 1));
|
||||
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
||||
return { ok: false, reason: "\u5927\u62EC\u865F\u88E1\u7684\u5167\u5BB9\u4E0D\u662F JSON \u7269\u4EF6" };
|
||||
}
|
||||
return { ok: true };
|
||||
} catch (e) {
|
||||
return { ok: false, reason: `JSON \u89E3\u6790\u5931\u6557\uFF1A${e instanceof Error ? e.message : "\u672A\u77E5\u932F\u8AA4"}` };
|
||||
}
|
||||
}
|
||||
function snippetForError(text, max = 120) {
|
||||
const one = text.replace(/\s+/g, " ").trim();
|
||||
if (!one) return "\uFF08\u7A7A\u7684\uFF09";
|
||||
return one.length <= max ? one : one.slice(0, max) + "\u2026";
|
||||
}
|
||||
|
||||
// cypher-executor/src/routes/portal.ts
|
||||
var portalRouter = new Hono2();
|
||||
var EXTRACT_MODEL = "@cf/meta/llama-4-scout-17b-16e-instruct";
|
||||
var SESSION_PREFIX2 = "portal_sess:";
|
||||
var LOCKFAIL_PREFIX = "portal_lockfail:";
|
||||
var LOCK_LIMIT = 5;
|
||||
@@ -13983,6 +14063,7 @@ portalRouter.post(
|
||||
const pageName = String(body?.page_name ?? "").trim();
|
||||
const srcText = String(body?.text ?? "");
|
||||
const daemonPrompt = String(body?.prompt ?? "").trim();
|
||||
const expectShape = parseExpectShape(body?.expect, Boolean(daemonPrompt));
|
||||
if (!daemonPrompt && (!pageName || !srcText.trim()))
|
||||
return c.json({ error: "page_name \u8207 text \u5FC5\u586B" }, 400);
|
||||
if (!c.env.AI) {
|
||||
@@ -14003,15 +14084,44 @@ portalRouter.post(
|
||||
\u539F\u7A3F\uFF1A
|
||||
${srcText}`;
|
||||
try {
|
||||
const out = await c.env.AI.run("@cf/meta/llama-4-scout-17b-16e-instruct", {
|
||||
const out = await c.env.AI.run(EXTRACT_MODEL, {
|
||||
messages: [{ role: "user", content: prompt }],
|
||||
max_tokens: daemonPrompt ? 8192 : 2048,
|
||||
temperature: 0.2
|
||||
temperature: 0.2,
|
||||
// 🔴 Arcrun#134(2026-08-27):呼叫端說它要一個 JSON 物件 ⇒ **就用模型保證得了的方式去要**。
|
||||
// 不加這個的實測(youlin 真檔《火星座標_短片劇本_v1》打 6 次):**3 次壞在
|
||||
// 模型把字串的收尾引號打成全形 `”`** ⇒ 字串沒收掉 ⇒ 後面那個換行變成 JSON 裡的
|
||||
// 裸控制字元 ⇒ daemon 與雲端都解析不了。那是第二顆骰子,和 `[object Object]`
|
||||
// 不同源但同一種傷害:**同一份檔、同一個請求,成敗看運氣**。
|
||||
// `response_format: json_object` 走的是受限解碼,語法由平台保證 ⇒ 骰子拿掉。
|
||||
// 只在呼叫端宣告要 JSON 時才加:legacy(要 markdown 卡)那條路一個字都沒動。
|
||||
...expectShape === "json_object" ? { response_format: { type: "json_object" } } : {}
|
||||
// 🔴 **不准把回傳值宣告成 `{ response?: string }`**。
|
||||
// 那個型別斷言正是本票的病根——binding 把純 JSON 回應解析成 JS 物件交回來,
|
||||
// 而斷言讓編譯器相信它是字串 ⇒ `String(物件)` = '[object Object]' ⇒ 整張卡沒了。
|
||||
// 一律 `unknown`,由 normalizeAiText 認形狀(見 lib/ai-response.ts 檔頭實測)。
|
||||
});
|
||||
const raw2 = String(out?.response ?? "").trim();
|
||||
const norm = normalizeAiText(out);
|
||||
if (norm.kind === "unrenderable") {
|
||||
return c.json({ error: `\u96F2\u7AEF\u8403\u53D6\uFF1AWorkers AI \u7684\u56DE\u61C9\u9084\u539F\u4E0D\u56DE\u6587\u5B57\uFF08${norm.reason ?? "\u672A\u77E5\u539F\u56E0"}\uFF09` }, 502);
|
||||
}
|
||||
const raw2 = norm.text;
|
||||
if (!raw2) return c.json({ error: "Workers AI \u6C92\u6709\u56DE\u50B3\u5167\u5BB9" }, 502);
|
||||
if (daemonPrompt) {
|
||||
return c.json({ success: true, output: raw2 });
|
||||
if (expectShape === "json_object") {
|
||||
const check = hasJsonObject(raw2);
|
||||
if (!check.ok) {
|
||||
return c.json(
|
||||
{
|
||||
error: `\u96F2\u7AEF\u8403\u53D6\uFF1A\u6A21\u578B\u6C92\u6709\u7167\u5951\u7D04\u56DE JSON \u7269\u4EF6\uFF08${check.reason}\uFF09\u3002\u9019\u4E00\u6BB5\u662F\u5728\u4F60\u7684\u77E5\u8B58\u5EAB\u96F2\u7AEF\u8DD1\u7684\uFF08Workers AI ${EXTRACT_MODEL}\uFF09\uFF0C\u4E0D\u662F\u5728\u4F60\u7684\u96FB\u8166\u4E0A\u3002\u6A21\u578B\u5BE6\u969B\u56DE\u7684\u524D 120 \u5B57\uFF1A${snippetForError(raw2)}`,
|
||||
code: "ai_output_not_json_object",
|
||||
output_kind: norm.kind
|
||||
},
|
||||
502
|
||||
);
|
||||
}
|
||||
}
|
||||
return c.json({ success: true, output: raw2, output_kind: norm.kind });
|
||||
}
|
||||
const marker = `# ${pageName}`;
|
||||
const idx = raw2.lastIndexOf(marker);
|
||||
@@ -17099,7 +17209,7 @@ async function tripletCensus(env, tenant2) {
|
||||
if (owned !== 0) return { owned, any: null };
|
||||
return { owned, any: await tripletCount(env, null) };
|
||||
}
|
||||
async function fuzzyFindNode(env, tenant2, searchTerm) {
|
||||
async function fuzzyFindNode(env, tenant2, searchTerm, libraries) {
|
||||
try {
|
||||
const res = await kbdbFetch(env, `/records/by-template/triplet?${ownerQuery(tenant2)}`);
|
||||
if (!res.ok) return null;
|
||||
@@ -17109,6 +17219,8 @@ async function fuzzyFindNode(env, tenant2, searchTerm) {
|
||||
for (const r of body.records) {
|
||||
const v = r?.values;
|
||||
if (!v || typeof v !== "object") continue;
|
||||
const lib = recordLibrary(v);
|
||||
if (lib !== null && !canReadLibrary(libraries, lib)) continue;
|
||||
if (typeof v.subject === "string" && v.subject.trim()) nodeNames.add(v.subject.trim());
|
||||
if (typeof v.object === "string" && v.object.trim()) nodeNames.add(v.object.trim());
|
||||
}
|
||||
@@ -17170,10 +17282,11 @@ portalDataRouter.get(
|
||||
return c.json({ success: true, entry });
|
||||
})
|
||||
);
|
||||
async function fetchNeighborsFromKbdb(env, tenant2, node, depth) {
|
||||
async function fetchNeighborsFromKbdb(env, tenant2, node, depth, libraries) {
|
||||
const qs = new URLSearchParams();
|
||||
qs.set("depth", String(depth));
|
||||
qs.set("template", "triplet");
|
||||
if (!libraries.includes("*")) qs.set("library", libraries.join(","));
|
||||
const res = await kbdbFetch(env, `/graph/neighbors/${encodeURIComponent(node)}?${qs.toString()}&${ownerQuery(tenant2)}`);
|
||||
const body = await res.json().catch(() => null);
|
||||
return { ok: res.ok, status: res.status, body };
|
||||
@@ -17197,16 +17310,16 @@ portalDataRouter.get(
|
||||
let first = null;
|
||||
try {
|
||||
for (const name of tryNames) {
|
||||
const r = await fetchNeighborsFromKbdb(c.env, tenant2, name, depth);
|
||||
const r = await fetchNeighborsFromKbdb(c.env, tenant2, name, depth, libraries);
|
||||
if (!first) first = r;
|
||||
if (!r.ok) break;
|
||||
const mapped = mapGraphNeighborsResponse(r.body);
|
||||
if (mapped.count > 0) return c.json(mapped);
|
||||
}
|
||||
if (first?.ok) {
|
||||
const fallbackName = await fuzzyFindNode(c.env, tenant2, rawName);
|
||||
const fallbackName = await fuzzyFindNode(c.env, tenant2, rawName, libraries);
|
||||
if (fallbackName && !tryNames.includes(fallbackName)) {
|
||||
const r = await fetchNeighborsFromKbdb(c.env, tenant2, fallbackName, depth);
|
||||
const r = await fetchNeighborsFromKbdb(c.env, tenant2, fallbackName, depth, libraries);
|
||||
if (r.ok) {
|
||||
const mapped = mapGraphNeighborsResponse(r.body);
|
||||
if (mapped.count > 0) return c.json(mapped);
|
||||
|
||||
+64
-38
@@ -2127,6 +2127,11 @@ function libraryOf(expr) {
|
||||
var ENTRY_LIBRARY_EXPR = "json_extract(metadata_json, '$.library')";
|
||||
var ENTRY_LIBRARY = libraryOf(ENTRY_LIBRARY_EXPR);
|
||||
var ENTRY_UNLABELLED = `(${ENTRY_LIBRARY_EXPR} IS NULL OR ${ENTRY_LIBRARY_EXPR} = '')`;
|
||||
function parseLibraryList(raw2) {
|
||||
if (!raw2) return void 0;
|
||||
const libs = raw2.split(",").map((s) => s.trim()).filter(Boolean);
|
||||
return libs.length > 0 ? libs : void 0;
|
||||
}
|
||||
|
||||
// kbdb/src/actions/entry-crud.ts
|
||||
function uid(prefix) {
|
||||
@@ -3198,11 +3203,7 @@ function fireAndForget(c, p) {
|
||||
else void p.catch(() => {
|
||||
});
|
||||
}
|
||||
function parseLibraryParam(raw2) {
|
||||
if (!raw2) return void 0;
|
||||
const libs = raw2.split(",").map((s) => s.trim()).filter(Boolean);
|
||||
return libs.length > 0 ? libs : void 0;
|
||||
}
|
||||
var parseLibraryParam = parseLibraryList;
|
||||
entryRoutes.post("/", async (c) => {
|
||||
const body = await c.req.json().catch(() => null);
|
||||
if (!body || !body.entry_type) return c.json({ success: false, error: "entry_type required" }, 400);
|
||||
@@ -4550,7 +4551,15 @@ mapRoutes.get("/:library", async (c) => {
|
||||
});
|
||||
|
||||
// kbdb/src/actions/graph-query.ts
|
||||
async function findTripletEdgesByNode(db, templateIdOrName, fields, nodeValue, owner_id) {
|
||||
var D1_MAX_BOUND_PARAMS = 90;
|
||||
function chunkForD1(items, fixedParams) {
|
||||
const size = Math.max(1, D1_MAX_BOUND_PARAMS - fixedParams);
|
||||
if (items.length <= size) return [items];
|
||||
const out = [];
|
||||
for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));
|
||||
return out;
|
||||
}
|
||||
async function findTripletEdgesByNode(db, templateIdOrName, fields, nodeValue, owner_id, libraries) {
|
||||
if (!nodeValue || fields.length === 0) return [];
|
||||
const tpl = await getTemplate(db, templateIdOrName);
|
||||
if (!tpl) return [];
|
||||
@@ -4560,42 +4569,58 @@ async function findTripletEdgesByNode(db, templateIdOrName, fields, nodeValue, o
|
||||
const valueIds = (valueRows.results ?? []).map((r) => r.id);
|
||||
if (valueIds.length === 0) return [];
|
||||
const fieldIds = fields.map((f) => fieldEntryId(tpl.id, f));
|
||||
const dstPh = valueIds.map(() => "?").join(",");
|
||||
const relPh = fieldIds.map(() => "?").join(",");
|
||||
const relSql = owner_id ? `SELECT DISTINCT src_id AS record_id FROM entries
|
||||
WHERE dst_id IN (${dstPh}) AND rel_id IN (${relPh}) AND owner_id = ?` : `SELECT DISTINCT src_id AS record_id FROM entries
|
||||
WHERE dst_id IN (${dstPh}) AND rel_id IN (${relPh})`;
|
||||
const relParams = owner_id ? [...valueIds, ...fieldIds, owner_id] : [...valueIds, ...fieldIds];
|
||||
const relRows = await db.prepare(relSql).bind(...relParams).all();
|
||||
const recordIds = (relRows.results ?? []).map((r) => r.record_id);
|
||||
const recordIdSet = /* @__PURE__ */ new Set();
|
||||
for (const idsChunk of chunkForD1(valueIds, fieldIds.length + (owner_id ? 1 : 0))) {
|
||||
const dstPh = idsChunk.map(() => "?").join(",");
|
||||
const relSql = owner_id ? `SELECT DISTINCT src_id AS record_id FROM entries
|
||||
WHERE dst_id IN (${dstPh}) AND rel_id IN (${relPh}) AND owner_id = ?` : `SELECT DISTINCT src_id AS record_id FROM entries
|
||||
WHERE dst_id IN (${dstPh}) AND rel_id IN (${relPh})`;
|
||||
const relParams = owner_id ? [...idsChunk, ...fieldIds, owner_id] : [...idsChunk, ...fieldIds];
|
||||
const relRows = await db.prepare(relSql).bind(...relParams).all();
|
||||
for (const r of relRows.results ?? []) recordIdSet.add(r.record_id);
|
||||
}
|
||||
const recordIds = [...recordIdSet];
|
||||
if (recordIds.length === 0) return [];
|
||||
const recPh = recordIds.map(() => "?").join(",");
|
||||
const pivotSql = `
|
||||
SELECT b.src_id AS record_id,
|
||||
MAX(CASE WHEN r.rel_id = ? THEN v.content END) AS subject,
|
||||
MAX(CASE WHEN r.rel_id = ? THEN v.content END) AS predicate,
|
||||
MAX(CASE WHEN r.rel_id = ? THEN v.content END) AS object,
|
||||
MAX(CASE WHEN r.rel_id = ? THEN v.content END) AS status
|
||||
FROM entries b
|
||||
LEFT JOIN entries r ON r.src_id = b.src_id AND r.rel_id != 'sys_belongs'
|
||||
LEFT JOIN entries v ON v.id = r.dst_id
|
||||
WHERE b.rel_id = 'sys_belongs' AND b.src_id IN (${recPh})
|
||||
GROUP BY b.src_id`;
|
||||
const pivotParams = [
|
||||
fieldEntryId(tpl.id, "subject"),
|
||||
fieldEntryId(tpl.id, "predicate"),
|
||||
fieldEntryId(tpl.id, "object"),
|
||||
fieldEntryId(tpl.id, "status"),
|
||||
...recordIds
|
||||
];
|
||||
const pivotRows = await db.prepare(pivotSql).bind(...pivotParams).all();
|
||||
return pivotRows.results ?? [];
|
||||
const libFilter = libraries && libraries.length > 0 ? libraries : null;
|
||||
const libAgg = "MAX(CASE WHEN r.rel_id = ? THEN v.content END)";
|
||||
const pivotFixed = 5 + (libFilter ? 1 + libFilter.length : 0);
|
||||
const rows = [];
|
||||
for (const recChunk of chunkForD1(recordIds, pivotFixed)) {
|
||||
const recPh = recChunk.map(() => "?").join(",");
|
||||
const pivotSql = `
|
||||
SELECT b.src_id AS record_id,
|
||||
MAX(CASE WHEN r.rel_id = ? THEN v.content END) AS subject,
|
||||
MAX(CASE WHEN r.rel_id = ? THEN v.content END) AS predicate,
|
||||
MAX(CASE WHEN r.rel_id = ? THEN v.content END) AS object,
|
||||
MAX(CASE WHEN r.rel_id = ? THEN v.content END) AS status,
|
||||
${libAgg} AS library
|
||||
FROM entries b
|
||||
LEFT JOIN entries r ON r.src_id = b.src_id AND r.rel_id != 'sys_belongs'
|
||||
LEFT JOIN entries v ON v.id = r.dst_id
|
||||
WHERE b.rel_id = 'sys_belongs' AND b.src_id IN (${recPh})
|
||||
GROUP BY b.src_id${libFilter ? `
|
||||
HAVING ${libraryOf(libAgg)} IN (${libFilter.map(() => "?").join(",")})` : ""}`;
|
||||
const pivotParams = [
|
||||
fieldEntryId(tpl.id, "subject"),
|
||||
fieldEntryId(tpl.id, "predicate"),
|
||||
fieldEntryId(tpl.id, "object"),
|
||||
fieldEntryId(tpl.id, "status"),
|
||||
fieldEntryId(tpl.id, "library"),
|
||||
...recChunk,
|
||||
...libFilter ? [fieldEntryId(tpl.id, "library"), ...libFilter] : []
|
||||
];
|
||||
const pivotRows = await db.prepare(pivotSql).bind(...pivotParams).all();
|
||||
rows.push(...pivotRows.results ?? []);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
async function graphNeighbors(db, start, opts = {}) {
|
||||
const depth = Math.max(1, Math.min(Math.floor(opts.depth ?? 1) || 1, 10));
|
||||
const template = opts.template ?? "triplet";
|
||||
const directed = !!opts.directed;
|
||||
const owner_id = opts.owner_id;
|
||||
const libraries = opts.library && opts.library.length > 0 ? opts.library : void 0;
|
||||
const visited = /* @__PURE__ */ new Set([start]);
|
||||
let frontier = [start];
|
||||
const neighbors = [];
|
||||
@@ -4603,7 +4628,7 @@ async function graphNeighbors(db, start, opts = {}) {
|
||||
if (frontier.length === 0) break;
|
||||
const next = [];
|
||||
for (const cur of frontier) {
|
||||
const outgoing = await findTripletEdgesByNode(db, template, ["subject"], cur, owner_id);
|
||||
const outgoing = await findTripletEdgesByNode(db, template, ["subject"], cur, owner_id, libraries);
|
||||
for (const e of outgoing) {
|
||||
if (e.status === "deprecated") continue;
|
||||
const nb = e.object;
|
||||
@@ -4613,7 +4638,7 @@ async function graphNeighbors(db, start, opts = {}) {
|
||||
next.push(nb);
|
||||
}
|
||||
if (!directed) {
|
||||
const incoming = await findTripletEdgesByNode(db, template, ["object"], cur, owner_id);
|
||||
const incoming = await findTripletEdgesByNode(db, template, ["object"], cur, owner_id, libraries);
|
||||
for (const e of incoming) {
|
||||
if (e.status === "deprecated") continue;
|
||||
const nb = e.subject;
|
||||
@@ -4626,7 +4651,7 @@ async function graphNeighbors(db, start, opts = {}) {
|
||||
}
|
||||
frontier = next;
|
||||
}
|
||||
return { success: true, start, depth, directed, neighbors, count: neighbors.length };
|
||||
return { success: true, start, depth, directed, libraries: libraries ?? null, neighbors, count: neighbors.length };
|
||||
}
|
||||
|
||||
// kbdb/src/routes/graph.ts
|
||||
@@ -4639,8 +4664,9 @@ graphRoutes.get("/neighbors/:node", async (c) => {
|
||||
const directed = c.req.query("directed") === "true";
|
||||
const template = c.req.query("template") || void 0;
|
||||
const owner_id = c.req.query("owner_id") || void 0;
|
||||
const library = parseLibraryList(c.req.query("library"));
|
||||
try {
|
||||
const result = await graphNeighbors(c.env.DB, node, { depth, template, directed, owner_id });
|
||||
const result = await graphNeighbors(c.env.DB, node, { depth, template, directed, owner_id, library });
|
||||
const edges = result.neighbors.map((n) => ({
|
||||
subject: n.from,
|
||||
predicate: n.predicate,
|
||||
|
||||
+19
-19
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema": 2,
|
||||
"built": "2026-08-27",
|
||||
"source": "Arcrun@f87260b1234f",
|
||||
"source": "Arcrun@98b45409740b",
|
||||
"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": 696639,
|
||||
"js_bytes": 702374,
|
||||
"modules": [],
|
||||
"compat_date": "2025-02-19",
|
||||
"compat_flags": [
|
||||
@@ -239,10 +239,10 @@
|
||||
"stripped": {
|
||||
"services": 13
|
||||
},
|
||||
"source_commit": "f87260b1234f0c108c378caf474d7af78cdd6cb9",
|
||||
"source_content_sha256": "2390294711ed529125559e505ed8f575093798480606253b31021b6faca4c758",
|
||||
"sha256": "2390294711ed529125559e505ed8f575093798480606253b31021b6faca4c758",
|
||||
"bytes": 696639
|
||||
"source_commit": "98b45409740bdb4976f8744f09255c98be8fc10c",
|
||||
"source_content_sha256": "b5cb49e2d2c263adea38418289d61fac470d1d121391d4805928e5a6cbb6c012",
|
||||
"sha256": "b5cb49e2d2c263adea38418289d61fac470d1d121391d4805928e5a6cbb6c012",
|
||||
"bytes": 702374
|
||||
},
|
||||
{
|
||||
"name": "arcrun-date-ops",
|
||||
@@ -396,7 +396,7 @@
|
||||
"name": "arcrun-kbdb",
|
||||
"main_module": "worker.mjs",
|
||||
"main_file": "arcrun-kbdb/worker.mjs",
|
||||
"js_bytes": 194366,
|
||||
"js_bytes": 195715,
|
||||
"modules": [],
|
||||
"compat_date": "2025-02-19",
|
||||
"compat_flags": [
|
||||
@@ -416,10 +416,10 @@
|
||||
"ENVIRONMENT": "production"
|
||||
}
|
||||
},
|
||||
"source_commit": "f87260b1234f0c108c378caf474d7af78cdd6cb9",
|
||||
"source_content_sha256": "97140b9d10337c0f995b5bd5a4a3403ff06403afb6a51394b3ede013293c5bf6",
|
||||
"sha256": "97140b9d10337c0f995b5bd5a4a3403ff06403afb6a51394b3ede013293c5bf6",
|
||||
"bytes": 194366
|
||||
"source_commit": "98b45409740bdb4976f8744f09255c98be8fc10c",
|
||||
"source_content_sha256": "fc1b12b56c7b3f8d68021349c72b5301afbb93333bf25887595b0fedc0e2232d",
|
||||
"sha256": "fc1b12b56c7b3f8d68021349c72b5301afbb93333bf25887595b0fedc0e2232d",
|
||||
"bytes": 195715
|
||||
},
|
||||
{
|
||||
"name": "arcrun-mcp",
|
||||
@@ -698,12 +698,12 @@
|
||||
"bytes": 67697
|
||||
}
|
||||
],
|
||||
"release": "1.4.59",
|
||||
"release": "1.4.60",
|
||||
"built_for": "oauth-installer-lazy-load",
|
||||
"notes": [
|
||||
"rag_takedown_direct 用了 __CARDS_PREFIX__,但安裝器的代換表沒有它 ⇒ 這個佔位符會原封不動被推進使用者的工作流。"
|
||||
],
|
||||
"fingerprint": "6d5575253074f913fa548e13da8ce6c9cda4d9598a8bd5971642ab66ea43bf80",
|
||||
"fingerprint": "731204104f2d9354af6b5e236dcfdf71f366b0ec56d103fb5bf242b99718d4bf",
|
||||
"library": [
|
||||
{
|
||||
"name": "arcrun-array-ops",
|
||||
@@ -888,7 +888,7 @@
|
||||
"name": "arcrun-cypher-executor",
|
||||
"main_module": "worker.mjs",
|
||||
"main_file": "arcrun-cypher-executor/worker.mjs",
|
||||
"js_bytes": 696639,
|
||||
"js_bytes": 702374,
|
||||
"modules": [],
|
||||
"compat_date": "2025-02-19",
|
||||
"compat_flags": [
|
||||
@@ -929,8 +929,8 @@
|
||||
"stripped": {
|
||||
"services": 13
|
||||
},
|
||||
"source_commit": "f87260b1234f0c108c378caf474d7af78cdd6cb9",
|
||||
"source_content_sha256": "2390294711ed529125559e505ed8f575093798480606253b31021b6faca4c758",
|
||||
"source_commit": "98b45409740bdb4976f8744f09255c98be8fc10c",
|
||||
"source_content_sha256": "b5cb49e2d2c263adea38418289d61fac470d1d121391d4805928e5a6cbb6c012",
|
||||
"first_install": true
|
||||
},
|
||||
{
|
||||
@@ -1075,7 +1075,7 @@
|
||||
"name": "arcrun-kbdb",
|
||||
"main_module": "worker.mjs",
|
||||
"main_file": "arcrun-kbdb/worker.mjs",
|
||||
"js_bytes": 194366,
|
||||
"js_bytes": 195715,
|
||||
"modules": [],
|
||||
"compat_date": "2025-02-19",
|
||||
"compat_flags": [
|
||||
@@ -1095,8 +1095,8 @@
|
||||
"ENVIRONMENT": "production"
|
||||
}
|
||||
},
|
||||
"source_commit": "f87260b1234f0c108c378caf474d7af78cdd6cb9",
|
||||
"source_content_sha256": "97140b9d10337c0f995b5bd5a4a3403ff06403afb6a51394b3ede013293c5bf6",
|
||||
"source_commit": "98b45409740bdb4976f8744f09255c98be8fc10c",
|
||||
"source_content_sha256": "fc1b12b56c7b3f8d68021349c72b5301afbb93333bf25887595b0fedc0e2232d",
|
||||
"first_install": true
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user