建立ToolDbProcessPort合约层

结论:已新增ToolDbProcessPort合约、OPFS tool DB flat-file/transcript store和Node/WASM gates,baseline保持28/28/131/0且promotion继续锁定。
This commit is contained in:
2026-06-19 06:36:26 +08:00
parent d9ac3770a7
commit d8e0196c61
13 changed files with 711 additions and 0 deletions

View File

@@ -61,6 +61,37 @@ export function toolTablePath(machineId, filename = "tool.tbl") {
);
}
export function toolDbRootPath(machineId) {
return opfsPath(
ROOT,
"machines",
assertSegment(machineId, "machine id"),
"tool-db",
);
}
export function toolDbFilePath(machineId, filename = "db_nonran_file") {
return opfsPath(
ROOT,
"machines",
assertSegment(machineId, "machine id"),
"tool-db",
assertSegment(filename, "tool DB filename"),
);
}
export function toolDbTranscriptPath(machineId, runId, filename = "transcript.json") {
return opfsPath(
ROOT,
"machines",
assertSegment(machineId, "machine id"),
"tool-db",
"transcripts",
assertSegment(runId, "tool DB run id"),
assertSegment(filename, "tool DB transcript filename"),
);
}
export function parameterFilePath(machineId, filename = "linuxcnc.var") {
return opfsPath(
ROOT,

View File

@@ -0,0 +1,78 @@
import { loadTextFile, saveTextFile } from "./file-service.js";
import { toolDbFilePath, toolDbTranscriptPath } from "./path-model.js";
function stableTextHash(text) {
let hash = 0x811c9dc5;
for (let index = 0; index < text.length; index += 1) {
hash ^= text.charCodeAt(index);
hash = Math.imul(hash, 0x01000193) >>> 0;
}
return hash.toString(16).padStart(8, "0");
}
function displayOpfsPath(path) {
return path.startsWith("linuxcnc/") ? path.slice("linuxcnc".length) : `/${path}`;
}
export function createToolDbStorePaths(machineId, {
dbFilename = "db_nonran_file",
runId = "run-1",
transcriptFilename = "transcript.json",
} = {}) {
return {
dbFile: toolDbFilePath(machineId, dbFilename),
transcript: toolDbTranscriptPath(machineId, runId, transcriptFilename),
};
}
export async function saveToolDbFile(machineId, text, options = {}) {
const path = options.path ?? toolDbFilePath(machineId, options.filename);
await saveTextFile(path, text, options.storage);
return {
opfsPath: path,
displayPath: displayOpfsPath(path),
dbFileHash: stableTextHash(text),
savedText: text,
};
}
export async function loadToolDbFile(machineId, options = {}) {
const path = options.path ?? toolDbFilePath(machineId, options.filename);
const text = await loadTextFile(path, options.storage);
return {
opfsPath: path,
displayPath: displayOpfsPath(path),
dbFileHash: stableTextHash(text),
text,
};
}
export async function saveToolDbTranscript(machineId, runId, transcript, options = {}) {
if (!Array.isArray(transcript)) {
throw new Error("transcript must be an array.");
}
const path = options.path ?? toolDbTranscriptPath(machineId, runId, options.filename);
const text = JSON.stringify({
schema: "linuxcnc.toolDbProcessTranscript.v1",
transcript,
}, null, 2);
await saveTextFile(path, text, options.storage);
return {
opfsPath: path,
displayPath: displayOpfsPath(path),
transcriptHash: stableTextHash(text),
text,
};
}
export async function loadToolDbTranscript(machineId, runId, options = {}) {
const path = options.path ?? toolDbTranscriptPath(machineId, runId, options.filename);
const text = await loadTextFile(path, options.storage);
const payload = JSON.parse(text);
return {
opfsPath: path,
displayPath: displayOpfsPath(path),
transcriptHash: stableTextHash(text),
payload,
};
}