mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-26 10:13:27 +08:00
perf(sqlite): fold version read into capability round trip (#183576)
Read the SQLite version with the NUL round-trip row, preserving synchronous boot admission and failure diagnostics. Reduce each successful capability probe from four statements to three.
This commit is contained in:
1 parent
9db139fcf8
commit
9397bfef04
4 files changed
+91
-48
No files matched your search
@@ -16,14 +16,15 @@ export function probeSqlite(DatabaseSync) {
|
||||
try {
|
||||
database = new DatabaseSync(":memory:");
|
||||
result.available = true;
|
||||
const version = database.prepare("SELECT sqlite_version() AS version").get()?.version;
|
||||
result.version = typeof version === "string" ? version : null;
|
||||
const text = "a\u0000b\u0000";
|
||||
const bytes = Buffer.from(text, "utf8");
|
||||
const json = JSON.stringify({ value: text });
|
||||
database.exec("CREATE TABLE probe (text_value TEXT, blob_value BLOB, json_value TEXT)");
|
||||
database.prepare("INSERT INTO probe VALUES (?, ?, ?)").run(text, bytes, json);
|
||||
const row = database.prepare("SELECT text_value, blob_value, json_value FROM probe").get();
|
||||
const row = database
|
||||
.prepare("SELECT sqlite_version() AS version, text_value, blob_value, json_value FROM probe")
|
||||
.get();
|
||||
result.version = typeof row?.version === "string" ? row.version : null;
|
||||
result.text =
|
||||
typeof row?.text_value === "string" &&
|
||||
row.text_value.length === text.length &&
|
||||
@@ -32,7 +33,16 @@ export function probeSqlite(DatabaseSync) {
|
||||
row?.blob_value instanceof Uint8Array && Buffer.from(row.blob_value).equals(bytes);
|
||||
result.json = row?.json_value === json && JSON.parse(row.json_value).value === text;
|
||||
} catch (error) {
|
||||
result.error = error instanceof Error ? error.message : String(error);
|
||||
let failure = error;
|
||||
if (database && result.version === null) {
|
||||
try {
|
||||
const version = database.prepare("SELECT sqlite_version() AS version").get()?.version;
|
||||
result.version = typeof version === "string" ? version : null;
|
||||
} catch (versionError) {
|
||||
failure = versionError;
|
||||
}
|
||||
}
|
||||
result.error = failure instanceof Error ? failure.message : String(failure);
|
||||
} finally {
|
||||
database?.close();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ var scripts = {
|
||||
daemonRuntimeProbe: {
|
||||
fileName: "daemon-runtime-probe.mjs",
|
||||
source:
|
||||
'var __getOwnPropNames=Object.getOwnPropertyNames;var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS,GATEWAY_SHUTDOWN_RESERVE_MS,GATEWAY_SUPERVISOR_EXIT_MARGIN_MS,GATEWAY_SHUTDOWN_TIMEOUT_MS,GATEWAY_SERVICE_STOP_TIMEOUT_MS,LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS;var init_gateway_shutdown_budget=__esm({"gateway-shutdown-budget.mjs"(){"use strict";GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS=315e3;GATEWAY_SHUTDOWN_RESERVE_MS=1e4;GATEWAY_SUPERVISOR_EXIT_MARGIN_MS=5e3;GATEWAY_SHUTDOWN_TIMEOUT_MS=GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS+GATEWAY_SHUTDOWN_RESERVE_MS;GATEWAY_SERVICE_STOP_TIMEOUT_MS=GATEWAY_SHUTDOWN_TIMEOUT_MS+GATEWAY_SUPERVISOR_EXIT_MARGIN_MS;LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS=GATEWAY_SERVICE_STOP_TIMEOUT_MS/1e3}});var parentKey,CLI_RESPAWN_PARENT_ENV,inheritedParent,CLI_PARENT_BOUND_PRELOAD;var init_cli_parent_lifetime=__esm({"cli-parent-lifetime.mjs"(){"use strict";init_gateway_shutdown_budget();parentKey=Symbol.for("openclaw.cliRespawnParent");CLI_RESPAWN_PARENT_ENV="OPENCLAW_CLI_RESPAWN_PARENT";inheritedParent=process.env[CLI_RESPAWN_PARENT_ENV];delete process.env[CLI_RESPAWN_PARENT_ENV];if(inheritedParent===String(process.ppid)){globalThis[parentKey]={pid:process.ppid}}CLI_PARENT_BOUND_PRELOAD=`data:text/javascript,${encodeURIComponent(`\n globalThis[Symbol.for("openclaw.cliRespawnParent")] = { pid: process.ppid };\n process.execArgv = process.execArgv.filter((arg, index, args) =>\n arg !== import.meta.url && !(arg === "--import" && args[index + 1] === import.meta.url));\n`)}`}});var init_node_runtime_env=__esm({"node-runtime-env.mjs"(){"use strict"}});import{readFileSync}from"node:fs";import path from"node:path";import{fileURLToPath}from"node:url";function readStandaloneRuntimeManifest(executable=process.execPath){return readStandaloneManifest({executable})}function projectStandaloneBuildInfo(value){const nonBlank=text=>typeof text==="string"&&text.trim().length>0;const stringList=items=>Array.isArray(items)&&items.every(nonBlank);const result={mode:value.mode,openclaw:{version:value.openclaw.version,...nonBlank(value.openclaw.commit)?{commit:value.openclaw.commit}:{}},bun:{version:value.bun.version}};for(const key of["revision","commit","executableSha256"]){if(nonBlank(value.bun[key])){result.bun[key]=value.bun[key]}}if(value.build!==void 0){const{id,flavor,pluginSetSha256,moduleGraphSha256}=value.build;if(!nonBlank(id)||!["standard","support"].includes(flavor)||!/^[a-f0-9]{64}$/.test(pluginSetSha256)||!/^[a-f0-9]{64}$/.test(moduleGraphSha256)){throw new Error("Invalid standalone build provenance")}result.build={id,flavor,pluginSetSha256,moduleGraphSha256};if(value.build.debugEntry!==void 0){const entry=value.build.debugEntry;if(typeof entry!=="string"||!entry.startsWith("debug/")||entry.includes("\\\\")||entry.split("/").some(part=>!part||part==="."||part==="..")){throw new Error("Invalid standalone debugger entry")}result.build.debugEntry=entry}}if(value.target!==void 0){if(!nonBlank(value.target.platform)||!nonBlank(value.target.arch)){throw new Error("Invalid standalone build target")}result.target={platform:value.target.platform,arch:value.target.arch}}if(value.plugins!==void 0){if(!stringList(value.plugins.embedded)||!stringList(value.plugins.omitted)){throw new Error("Invalid standalone plugin inventory")}result.plugins={embedded:[...value.plugins.embedded],omitted:[...value.plugins.omitted]}}if(value.nativeModules!==void 0){if(!Array.isArray(value.nativeModules)||value.nativeModules.some(item=>!item||!nonBlank(item.name)||!nonBlank(item.version)||!stringList(item.artifacts)||item.qualification!=="unverified"||!nonBlank(item.backend))){throw new Error("Invalid standalone native inventory")}result.nativeModules=value.nativeModules.map(({name,version,artifacts,qualification,backend})=>({name,version,artifacts:[...artifacts],qualification,backend}))}return result}function readStandaloneManifest({executable,runtimeRoot,includeBuild=false}){const location=executable??runtimeRoot;if(!path.isAbsolute(location)){return void 0}const root=path.dirname(location);const manifestPath=path.join(root,"manifest.json");let raw;try{raw=readFileSync(manifestPath,"utf8")}catch(error){if(error?.code==="ENOENT"||error?.code==="ENOTDIR"){return void 0}throw error}let manifest;try{manifest=JSON.parse(raw)}catch(cause){throw new Error(`Invalid standalone runtime manifest: ${manifestPath}`,{cause})}const nonBlank=value=>typeof value==="string"&&value.trim().length>0;if(manifest?.schemaVersion!==1||!["jit","bytecode","aot"].includes(manifest.mode)||!nonBlank(manifest.executable?.path)||!nonBlank(manifest.runtime?.path)||!nonBlank(manifest.openclaw?.version)||!nonBlank(manifest.bun?.version)){throw new Error(`Invalid standalone runtime manifest: ${manifestPath}`)}const executableRelative=path.relative(root,path.resolve(root,manifest.executable.path));const sidecarRelative=path.relative(roLine truncated
|
||||
'var __getOwnPropNames=Object.getOwnPropertyNames;var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS,GATEWAY_SHUTDOWN_RESERVE_MS,GATEWAY_SUPERVISOR_EXIT_MARGIN_MS,GATEWAY_SHUTDOWN_TIMEOUT_MS,GATEWAY_SERVICE_STOP_TIMEOUT_MS,LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS;var init_gateway_shutdown_budget=__esm({"gateway-shutdown-budget.mjs"(){"use strict";GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS=315e3;GATEWAY_SHUTDOWN_RESERVE_MS=1e4;GATEWAY_SUPERVISOR_EXIT_MARGIN_MS=5e3;GATEWAY_SHUTDOWN_TIMEOUT_MS=GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS+GATEWAY_SHUTDOWN_RESERVE_MS;GATEWAY_SERVICE_STOP_TIMEOUT_MS=GATEWAY_SHUTDOWN_TIMEOUT_MS+GATEWAY_SUPERVISOR_EXIT_MARGIN_MS;LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS=GATEWAY_SERVICE_STOP_TIMEOUT_MS/1e3}});var parentKey,CLI_RESPAWN_PARENT_ENV,inheritedParent,CLI_PARENT_BOUND_PRELOAD;var init_cli_parent_lifetime=__esm({"cli-parent-lifetime.mjs"(){"use strict";init_gateway_shutdown_budget();parentKey=Symbol.for("openclaw.cliRespawnParent");CLI_RESPAWN_PARENT_ENV="OPENCLAW_CLI_RESPAWN_PARENT";inheritedParent=process.env[CLI_RESPAWN_PARENT_ENV];delete process.env[CLI_RESPAWN_PARENT_ENV];if(inheritedParent===String(process.ppid)){globalThis[parentKey]={pid:process.ppid}}CLI_PARENT_BOUND_PRELOAD=`data:text/javascript,${encodeURIComponent(`\n globalThis[Symbol.for("openclaw.cliRespawnParent")] = { pid: process.ppid };\n process.execArgv = process.execArgv.filter((arg, index, args) =>\n arg !== import.meta.url && !(arg === "--import" && args[index + 1] === import.meta.url));\n`)}`}});var init_node_runtime_env=__esm({"node-runtime-env.mjs"(){"use strict"}});import{readFileSync}from"node:fs";import path from"node:path";import{fileURLToPath}from"node:url";function readStandaloneRuntimeManifest(executable=process.execPath){return readStandaloneManifest({executable})}function projectStandaloneBuildInfo(value){const nonBlank=text=>typeof text==="string"&&text.trim().length>0;const stringList=items=>Array.isArray(items)&&items.every(nonBlank);const result={mode:value.mode,openclaw:{version:value.openclaw.version,...nonBlank(value.openclaw.commit)?{commit:value.openclaw.commit}:{}},bun:{version:value.bun.version}};for(const key of["revision","commit","executableSha256"]){if(nonBlank(value.bun[key])){result.bun[key]=value.bun[key]}}if(value.build!==void 0){const{id,flavor,pluginSetSha256,moduleGraphSha256}=value.build;if(!nonBlank(id)||!["standard","support"].includes(flavor)||!/^[a-f0-9]{64}$/.test(pluginSetSha256)||!/^[a-f0-9]{64}$/.test(moduleGraphSha256)){throw new Error("Invalid standalone build provenance")}result.build={id,flavor,pluginSetSha256,moduleGraphSha256};if(value.build.debugEntry!==void 0){const entry=value.build.debugEntry;if(typeof entry!=="string"||!entry.startsWith("debug/")||entry.includes("\\\\")||entry.split("/").some(part=>!part||part==="."||part==="..")){throw new Error("Invalid standalone debugger entry")}result.build.debugEntry=entry}}if(value.target!==void 0){if(!nonBlank(value.target.platform)||!nonBlank(value.target.arch)){throw new Error("Invalid standalone build target")}result.target={platform:value.target.platform,arch:value.target.arch}}if(value.plugins!==void 0){if(!stringList(value.plugins.embedded)||!stringList(value.plugins.omitted)){throw new Error("Invalid standalone plugin inventory")}result.plugins={embedded:[...value.plugins.embedded],omitted:[...value.plugins.omitted]}}if(value.nativeModules!==void 0){if(!Array.isArray(value.nativeModules)||value.nativeModules.some(item=>!item||!nonBlank(item.name)||!nonBlank(item.version)||!stringList(item.artifacts)||item.qualification!=="unverified"||!nonBlank(item.backend))){throw new Error("Invalid standalone native inventory")}result.nativeModules=value.nativeModules.map(({name,version,artifacts,qualification,backend})=>({name,version,artifacts:[...artifacts],qualification,backend}))}return result}function readStandaloneManifest({executable,runtimeRoot,includeBuild=false}){const location=executable??runtimeRoot;if(!path.isAbsolute(location)){return void 0}const root=path.dirname(location);const manifestPath=path.join(root,"manifest.json");let raw;try{raw=readFileSync(manifestPath,"utf8")}catch(error){if(error?.code==="ENOENT"||error?.code==="ENOTDIR"){return void 0}throw error}let manifest;try{manifest=JSON.parse(raw)}catch(cause){throw new Error(`Invalid standalone runtime manifest: ${manifestPath}`,{cause})}const nonBlank=value=>typeof value==="string"&&value.trim().length>0;if(manifest?.schemaVersion!==1||!["jit","bytecode","aot"].includes(manifest.mode)||!nonBlank(manifest.executable?.path)||!nonBlank(manifest.runtime?.path)||!nonBlank(manifest.openclaw?.version)||!nonBlank(manifest.bun?.version)){throw new Error(`Invalid standalone runtime manifest: ${manifestPath}`)}const executableRelative=path.relative(root,path.resolve(root,manifest.executable.path));const sidecarRelative=path.relative(roLine truncated
|
||||
},
|
||||
updateStateSizes: {
|
||||
fileName: "update-state-sizes.mjs",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// Generated by scripts/generate-runtime-script-assets.mjs; do not edit.
|
||||
export const DAEMON_RUNTIME_PROBE_SOURCE =
|
||||
'var __getOwnPropNames=Object.getOwnPropertyNames;var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS,GATEWAY_SHUTDOWN_RESERVE_MS,GATEWAY_SUPERVISOR_EXIT_MARGIN_MS,GATEWAY_SHUTDOWN_TIMEOUT_MS,GATEWAY_SERVICE_STOP_TIMEOUT_MS,LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS;var init_gateway_shutdown_budget=__esm({"gateway-shutdown-budget.mjs"(){"use strict";GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS=315e3;GATEWAY_SHUTDOWN_RESERVE_MS=1e4;GATEWAY_SUPERVISOR_EXIT_MARGIN_MS=5e3;GATEWAY_SHUTDOWN_TIMEOUT_MS=GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS+GATEWAY_SHUTDOWN_RESERVE_MS;GATEWAY_SERVICE_STOP_TIMEOUT_MS=GATEWAY_SHUTDOWN_TIMEOUT_MS+GATEWAY_SUPERVISOR_EXIT_MARGIN_MS;LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS=GATEWAY_SERVICE_STOP_TIMEOUT_MS/1e3}});var parentKey,CLI_RESPAWN_PARENT_ENV,inheritedParent,CLI_PARENT_BOUND_PRELOAD;var init_cli_parent_lifetime=__esm({"cli-parent-lifetime.mjs"(){"use strict";init_gateway_shutdown_budget();parentKey=Symbol.for("openclaw.cliRespawnParent");CLI_RESPAWN_PARENT_ENV="OPENCLAW_CLI_RESPAWN_PARENT";inheritedParent=process.env[CLI_RESPAWN_PARENT_ENV];delete process.env[CLI_RESPAWN_PARENT_ENV];if(inheritedParent===String(process.ppid)){globalThis[parentKey]={pid:process.ppid}}CLI_PARENT_BOUND_PRELOAD=`data:text/javascript,${encodeURIComponent(`\n globalThis[Symbol.for("openclaw.cliRespawnParent")] = { pid: process.ppid };\n process.execArgv = process.execArgv.filter((arg, index, args) =>\n arg !== import.meta.url && !(arg === "--import" && args[index + 1] === import.meta.url));\n`)}`}});var init_node_runtime_env=__esm({"node-runtime-env.mjs"(){"use strict"}});import{readFileSync}from"node:fs";import path from"node:path";import{fileURLToPath}from"node:url";function readStandaloneRuntimeManifest(executable=process.execPath){return readStandaloneManifest({executable})}function projectStandaloneBuildInfo(value){const nonBlank=text=>typeof text==="string"&&text.trim().length>0;const stringList=items=>Array.isArray(items)&&items.every(nonBlank);const result={mode:value.mode,openclaw:{version:value.openclaw.version,...nonBlank(value.openclaw.commit)?{commit:value.openclaw.commit}:{}},bun:{version:value.bun.version}};for(const key of["revision","commit","executableSha256"]){if(nonBlank(value.bun[key])){result.bun[key]=value.bun[key]}}if(value.build!==void 0){const{id,flavor,pluginSetSha256,moduleGraphSha256}=value.build;if(!nonBlank(id)||!["standard","support"].includes(flavor)||!/^[a-f0-9]{64}$/.test(pluginSetSha256)||!/^[a-f0-9]{64}$/.test(moduleGraphSha256)){throw new Error("Invalid standalone build provenance")}result.build={id,flavor,pluginSetSha256,moduleGraphSha256};if(value.build.debugEntry!==void 0){const entry=value.build.debugEntry;if(typeof entry!=="string"||!entry.startsWith("debug/")||entry.includes("\\\\")||entry.split("/").some(part=>!part||part==="."||part==="..")){throw new Error("Invalid standalone debugger entry")}result.build.debugEntry=entry}}if(value.target!==void 0){if(!nonBlank(value.target.platform)||!nonBlank(value.target.arch)){throw new Error("Invalid standalone build target")}result.target={platform:value.target.platform,arch:value.target.arch}}if(value.plugins!==void 0){if(!stringList(value.plugins.embedded)||!stringList(value.plugins.omitted)){throw new Error("Invalid standalone plugin inventory")}result.plugins={embedded:[...value.plugins.embedded],omitted:[...value.plugins.omitted]}}if(value.nativeModules!==void 0){if(!Array.isArray(value.nativeModules)||value.nativeModules.some(item=>!item||!nonBlank(item.name)||!nonBlank(item.version)||!stringList(item.artifacts)||item.qualification!=="unverified"||!nonBlank(item.backend))){throw new Error("Invalid standalone native inventory")}result.nativeModules=value.nativeModules.map(({name,version,artifacts,qualification,backend})=>({name,version,artifacts:[...artifacts],qualification,backend}))}return result}function readStandaloneManifest({executable,runtimeRoot,includeBuild=false}){const location=executable??runtimeRoot;if(!path.isAbsolute(location)){return void 0}const root=path.dirname(location);const manifestPath=path.join(root,"manifest.json");let raw;try{raw=readFileSync(manifestPath,"utf8")}catch(error){if(error?.code==="ENOENT"||error?.code==="ENOTDIR"){return void 0}throw error}let manifest;try{manifest=JSON.parse(raw)}catch(cause){throw new Error(`Invalid standalone runtime manifest: ${manifestPath}`,{cause})}const nonBlank=value=>typeof value==="string"&&value.trim().length>0;if(manifest?.schemaVersion!==1||!["jit","bytecode","aot"].includes(manifest.mode)||!nonBlank(manifest.executable?.path)||!nonBlank(manifest.runtime?.path)||!nonBlank(manifest.openclaw?.version)||!nonBlank(manifest.bun?.version)){throw new Error(`Invalid standalone runtime manifest: ${manifestPath}`)}const executableRelative=path.relative(root,path.resolve(root,manifest.executable.path));const sidecarRelative=path.relative(root,pLine truncated
|
||||
'var __getOwnPropNames=Object.getOwnPropertyNames;var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS,GATEWAY_SHUTDOWN_RESERVE_MS,GATEWAY_SUPERVISOR_EXIT_MARGIN_MS,GATEWAY_SHUTDOWN_TIMEOUT_MS,GATEWAY_SERVICE_STOP_TIMEOUT_MS,LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS;var init_gateway_shutdown_budget=__esm({"gateway-shutdown-budget.mjs"(){"use strict";GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS=315e3;GATEWAY_SHUTDOWN_RESERVE_MS=1e4;GATEWAY_SUPERVISOR_EXIT_MARGIN_MS=5e3;GATEWAY_SHUTDOWN_TIMEOUT_MS=GATEWAY_SHUTDOWN_DRAIN_TIMEOUT_MS+GATEWAY_SHUTDOWN_RESERVE_MS;GATEWAY_SERVICE_STOP_TIMEOUT_MS=GATEWAY_SHUTDOWN_TIMEOUT_MS+GATEWAY_SUPERVISOR_EXIT_MARGIN_MS;LAUNCH_AGENT_EXIT_TIMEOUT_SECONDS=GATEWAY_SERVICE_STOP_TIMEOUT_MS/1e3}});var parentKey,CLI_RESPAWN_PARENT_ENV,inheritedParent,CLI_PARENT_BOUND_PRELOAD;var init_cli_parent_lifetime=__esm({"cli-parent-lifetime.mjs"(){"use strict";init_gateway_shutdown_budget();parentKey=Symbol.for("openclaw.cliRespawnParent");CLI_RESPAWN_PARENT_ENV="OPENCLAW_CLI_RESPAWN_PARENT";inheritedParent=process.env[CLI_RESPAWN_PARENT_ENV];delete process.env[CLI_RESPAWN_PARENT_ENV];if(inheritedParent===String(process.ppid)){globalThis[parentKey]={pid:process.ppid}}CLI_PARENT_BOUND_PRELOAD=`data:text/javascript,${encodeURIComponent(`\n globalThis[Symbol.for("openclaw.cliRespawnParent")] = { pid: process.ppid };\n process.execArgv = process.execArgv.filter((arg, index, args) =>\n arg !== import.meta.url && !(arg === "--import" && args[index + 1] === import.meta.url));\n`)}`}});var init_node_runtime_env=__esm({"node-runtime-env.mjs"(){"use strict"}});import{readFileSync}from"node:fs";import path from"node:path";import{fileURLToPath}from"node:url";function readStandaloneRuntimeManifest(executable=process.execPath){return readStandaloneManifest({executable})}function projectStandaloneBuildInfo(value){const nonBlank=text=>typeof text==="string"&&text.trim().length>0;const stringList=items=>Array.isArray(items)&&items.every(nonBlank);const result={mode:value.mode,openclaw:{version:value.openclaw.version,...nonBlank(value.openclaw.commit)?{commit:value.openclaw.commit}:{}},bun:{version:value.bun.version}};for(const key of["revision","commit","executableSha256"]){if(nonBlank(value.bun[key])){result.bun[key]=value.bun[key]}}if(value.build!==void 0){const{id,flavor,pluginSetSha256,moduleGraphSha256}=value.build;if(!nonBlank(id)||!["standard","support"].includes(flavor)||!/^[a-f0-9]{64}$/.test(pluginSetSha256)||!/^[a-f0-9]{64}$/.test(moduleGraphSha256)){throw new Error("Invalid standalone build provenance")}result.build={id,flavor,pluginSetSha256,moduleGraphSha256};if(value.build.debugEntry!==void 0){const entry=value.build.debugEntry;if(typeof entry!=="string"||!entry.startsWith("debug/")||entry.includes("\\\\")||entry.split("/").some(part=>!part||part==="."||part==="..")){throw new Error("Invalid standalone debugger entry")}result.build.debugEntry=entry}}if(value.target!==void 0){if(!nonBlank(value.target.platform)||!nonBlank(value.target.arch)){throw new Error("Invalid standalone build target")}result.target={platform:value.target.platform,arch:value.target.arch}}if(value.plugins!==void 0){if(!stringList(value.plugins.embedded)||!stringList(value.plugins.omitted)){throw new Error("Invalid standalone plugin inventory")}result.plugins={embedded:[...value.plugins.embedded],omitted:[...value.plugins.omitted]}}if(value.nativeModules!==void 0){if(!Array.isArray(value.nativeModules)||value.nativeModules.some(item=>!item||!nonBlank(item.name)||!nonBlank(item.version)||!stringList(item.artifacts)||item.qualification!=="unverified"||!nonBlank(item.backend))){throw new Error("Invalid standalone native inventory")}result.nativeModules=value.nativeModules.map(({name,version,artifacts,qualification,backend})=>({name,version,artifacts:[...artifacts],qualification,backend}))}return result}function readStandaloneManifest({executable,runtimeRoot,includeBuild=false}){const location=executable??runtimeRoot;if(!path.isAbsolute(location)){return void 0}const root=path.dirname(location);const manifestPath=path.join(root,"manifest.json");let raw;try{raw=readFileSync(manifestPath,"utf8")}catch(error){if(error?.code==="ENOENT"||error?.code==="ENOTDIR"){return void 0}throw error}let manifest;try{manifest=JSON.parse(raw)}catch(cause){throw new Error(`Invalid standalone runtime manifest: ${manifestPath}`,{cause})}const nonBlank=value=>typeof value==="string"&&value.trim().length>0;if(manifest?.schemaVersion!==1||!["jit","bytecode","aot"].includes(manifest.mode)||!nonBlank(manifest.executable?.path)||!nonBlank(manifest.runtime?.path)||!nonBlank(manifest.openclaw?.version)||!nonBlank(manifest.bun?.version)){throw new Error(`Invalid standalone runtime manifest: ${manifestPath}`)}const executableRelative=path.relative(root,path.resolve(root,manifest.executable.path));const sidecarRelative=path.relative(root,pLine truncated
|
||||
@@ -22,48 +22,72 @@ function runProbe(script: string, env?: NodeJS.ProcessEnv): unknown {
|
||||
);
|
||||
}
|
||||
|
||||
it.each(["none", "text", "trailing", "blob", "json", "throw"] as const)(
|
||||
"detects %s corruption and closes the in-memory database",
|
||||
(corruption) => {
|
||||
const close = vi.fn();
|
||||
class FakeDatabase {
|
||||
row: Record<string, unknown> = {};
|
||||
exec() {}
|
||||
prepare(sql: string) {
|
||||
return {
|
||||
run: (text: ProbeValue, blob: ProbeValue, json: ProbeValue) => {
|
||||
this.row = { text_value: text, blob_value: blob, json_value: json };
|
||||
},
|
||||
get: () => {
|
||||
if (sql.includes("sqlite_version()")) {
|
||||
return { version: "3.51.3" };
|
||||
}
|
||||
if (corruption === "throw") {
|
||||
throw new Error("read failed");
|
||||
}
|
||||
const overrides: Partial<Record<typeof corruption, Record<string, unknown>>> = {
|
||||
text: { text_value: "a" },
|
||||
trailing: { text_value: "a\0b" },
|
||||
blob: { blob_value: new Uint8Array([97]) },
|
||||
json: { json_value: '{"value":"a"}' },
|
||||
};
|
||||
return { ...this.row, ...overrides[corruption] };
|
||||
},
|
||||
};
|
||||
it.each([
|
||||
"none",
|
||||
"text",
|
||||
"trailing",
|
||||
"blob",
|
||||
"json",
|
||||
"throw",
|
||||
"create",
|
||||
"insert",
|
||||
"version",
|
||||
] as const)("detects %s corruption and closes the in-memory database", (corruption) => {
|
||||
const close = vi.fn();
|
||||
class FakeDatabase {
|
||||
row: Record<string, unknown> = {};
|
||||
exec() {
|
||||
if (corruption === "create" || corruption === "version") {
|
||||
throw new Error("create failed");
|
||||
}
|
||||
close = close;
|
||||
}
|
||||
expect(probeSqlite(FakeDatabase)).toEqual({
|
||||
available: true,
|
||||
version: "3.51.3",
|
||||
text: !["text", "trailing", "throw"].includes(corruption),
|
||||
blob: !["blob", "throw"].includes(corruption),
|
||||
json: !["json", "throw"].includes(corruption),
|
||||
...(corruption === "throw" ? { error: "read failed" } : {}),
|
||||
});
|
||||
expect(close).toHaveBeenCalledOnce();
|
||||
},
|
||||
);
|
||||
prepare(sql: string) {
|
||||
return {
|
||||
run: (text: ProbeValue, blob: ProbeValue, json: ProbeValue) => {
|
||||
if (corruption === "insert") {
|
||||
throw new Error("insert failed");
|
||||
}
|
||||
this.row = { text_value: text, blob_value: blob, json_value: json };
|
||||
},
|
||||
get: () => {
|
||||
if (!sql.includes("FROM probe")) {
|
||||
if (corruption === "version") {
|
||||
throw new Error("version failed");
|
||||
}
|
||||
return { version: "3.51.3" };
|
||||
}
|
||||
if (corruption === "throw") {
|
||||
throw new Error("read failed");
|
||||
}
|
||||
const overrides: Partial<Record<typeof corruption, Record<string, unknown>>> = {
|
||||
text: { text_value: "a" },
|
||||
trailing: { text_value: "a\0b" },
|
||||
blob: { blob_value: new Uint8Array([97]) },
|
||||
json: { json_value: '{"value":"a"}' },
|
||||
};
|
||||
return { version: "3.51.3", ...this.row, ...overrides[corruption] };
|
||||
},
|
||||
};
|
||||
}
|
||||
close = close;
|
||||
}
|
||||
const failures: Partial<Record<typeof corruption, string>> = {
|
||||
throw: "read failed",
|
||||
create: "create failed",
|
||||
insert: "insert failed",
|
||||
version: "version failed",
|
||||
};
|
||||
const error = failures[corruption];
|
||||
expect(probeSqlite(FakeDatabase)).toEqual({
|
||||
available: true,
|
||||
version: corruption === "version" ? null : "3.51.3",
|
||||
text: !error && !["text", "trailing"].includes(corruption),
|
||||
blob: !error && corruption !== "blob",
|
||||
json: !error && corruption !== "json",
|
||||
...(error ? { error } : {}),
|
||||
});
|
||||
expect(close).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ permission: false, sqlFailure: false },
|
||||
@@ -74,8 +98,16 @@ it.each([
|
||||
({ permission, sqlFailure }) => {
|
||||
const output = runProbe(
|
||||
`
|
||||
import { DatabaseSync } from "node:sqlite";
|
||||
import { DatabaseSync, StatementSync } from "node:sqlite";
|
||||
import { Worker } from "node:worker_threads";
|
||||
let statements = 0;
|
||||
for (const [prototype, method] of [[DatabaseSync.prototype, "exec"], [StatementSync.prototype, "get"], [StatementSync.prototype, "run"]]) {
|
||||
const execute = prototype[method];
|
||||
prototype[method] = function (...args) {
|
||||
statements++;
|
||||
return Reflect.apply(execute, this, args);
|
||||
};
|
||||
}
|
||||
let closed = 0;
|
||||
const close = DatabaseSync.prototype.close;
|
||||
DatabaseSync.prototype.close = function (...args) {
|
||||
@@ -103,7 +135,7 @@ it.each([
|
||||
process.stdout.write(JSON.stringify({
|
||||
asynchronous: pending instanceof Promise,
|
||||
samePending, sameResult, capabilities,
|
||||
closed, workerDenied,
|
||||
closed, workerDenied, statements,
|
||||
...(${permission} ? {
|
||||
failure: nodeRuntimeFailure(process.versions.node, capabilities),
|
||||
permissions: {
|
||||
@@ -129,6 +161,7 @@ it.each([
|
||||
...(sqlFailure ? { error: "injected SQL failure" } : {}),
|
||||
},
|
||||
closed: 1,
|
||||
...(!sqlFailure ? { statements: 3 } : {}),
|
||||
...(permission
|
||||
? {
|
||||
failure: sqlFailure
|
||||
|
||||
Reference in new issue
Block a user