mirror of
https://github.com/infinilabs/coco-app.git
synced 2026-07-09 12:00:44 +02:00
fix: resolve fst-no-std version conflict causing pizza-engine CI check failure (#1074)
* feat: add deep research report workflow and viewer * docs: update changelog * ci: update pizza repository reference from infinilabs to pizza-rs org * fix deep research completion state * fix: prevent deep research stream timeout * fix: update deep research cancel copy * fix: apply rustfmt formatting to attachment.rs * fix: resolve fst-no-std version conflict in pizza-engine CI check The 'check (macos-latest)' CI job fails because pizza-engine (added as a CI dependency) uses infinilabs/fst-no-std while its transitive dependency fst-regex uses pizza-rs/fst-no-std. Cargo treats these as two separate crates, causing: 1. Automaton trait incompatibility between the two fst_no_std instances 2. MapBuilder, Error::Io, and Set::from_iter not found because the infinilabs fork gates them behind 'std' feature while pizza-engine only enabled 'alloc' Fix: - Add [patch."https://github.com/infinilabs/fst-no-std"] to src-tauri/Cargo.toml to redirect the infinilabs fork to pizza-rs/fst-no-std, unifying both into a single crate instance. This patch is a no-op for normal builds without pizza-engine. - Update the CI workflow to also add fst-no-std with std feature so that Error::Io (gated by std) and MapBuilder are available after the redirect. * Update Cargo.toml --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Medcl <m@medcl.net>
This commit is contained in:
155
scripts/buildWeb.ts
Normal file
155
scripts/buildWeb.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
import { spawn } from "child_process";
|
||||
import { readFileSync, writeFileSync } from "fs";
|
||||
import { dirname, join } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const projectRoot = join(__dirname, "..");
|
||||
const adapterPath = join(projectRoot, "src/utils/platformAdapter.ts");
|
||||
|
||||
type AdapterMode = "tauri" | "web";
|
||||
|
||||
function stripLineComments(content: string) {
|
||||
return content
|
||||
.split(/\r?\n/)
|
||||
.filter((line) => !line.trimStart().startsWith("//"))
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
function detectAdapterMode(content: string): AdapterMode {
|
||||
const activeContent = stripLineComments(content);
|
||||
const usesTauriAdapter =
|
||||
/import\s*\{\s*createTauriAdapter\s*\}\s*from\s*["']\.\/tauriAdapter["']/.test(
|
||||
activeContent
|
||||
) && /platformAdapter\s*=\s*createTauriAdapter\s*\(/.test(activeContent);
|
||||
const usesWebAdapter =
|
||||
/import\s*\{\s*createWebAdapter\s*\}\s*from\s*["']\.\/webAdapter["']/.test(
|
||||
activeContent
|
||||
) && /platformAdapter\s*=\s*createWebAdapter\s*\(/.test(activeContent);
|
||||
|
||||
if (usesTauriAdapter && !usesWebAdapter) {
|
||||
return "tauri";
|
||||
}
|
||||
|
||||
if (usesWebAdapter && !usesTauriAdapter) {
|
||||
return "web";
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Unable to detect active platform adapter in ${adapterPath}. ` +
|
||||
`Expected either createTauriAdapter() or createWebAdapter() to be active.`
|
||||
);
|
||||
}
|
||||
|
||||
function setLineComment(line: string, commented: boolean) {
|
||||
const indent = line.match(/^\s*/)?.[0] ?? "";
|
||||
const content = line.slice(indent.length);
|
||||
const uncommented = content.replace(/^\/\/\s?/, "");
|
||||
|
||||
return commented ? `${indent}// ${uncommented}` : `${indent}${uncommented}`;
|
||||
}
|
||||
|
||||
function switchToWebAdapter(content: string) {
|
||||
let hasTauriImport = false;
|
||||
let hasTauriInit = false;
|
||||
let hasWebImport = false;
|
||||
let hasWebInit = false;
|
||||
|
||||
const nextContent = content
|
||||
.split(/\r?\n/)
|
||||
.map((line) => {
|
||||
const normalized = line.trim().replace(/^\/\/\s?/, "");
|
||||
|
||||
if (
|
||||
normalized === 'import { createTauriAdapter } from "./tauriAdapter";'
|
||||
) {
|
||||
hasTauriImport = true;
|
||||
return setLineComment(line, true);
|
||||
}
|
||||
|
||||
if (normalized === "let platformAdapter = createTauriAdapter();") {
|
||||
hasTauriInit = true;
|
||||
return setLineComment(line, true);
|
||||
}
|
||||
|
||||
if (normalized === 'import { createWebAdapter } from "./webAdapter";') {
|
||||
hasWebImport = true;
|
||||
return setLineComment(line, false);
|
||||
}
|
||||
|
||||
if (normalized === "let platformAdapter = createWebAdapter();") {
|
||||
hasWebInit = true;
|
||||
return setLineComment(line, false);
|
||||
}
|
||||
|
||||
return line;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
if (!hasTauriImport || !hasTauriInit || !hasWebImport || !hasWebInit) {
|
||||
throw new Error(
|
||||
`Unable to switch ${adapterPath} to Web mode. ` +
|
||||
`Expected both Tauri and Web adapter import/init lines to exist.`
|
||||
);
|
||||
}
|
||||
|
||||
detectAdapterMode(nextContent);
|
||||
return nextContent;
|
||||
}
|
||||
|
||||
function run(command: string, args: string[]) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const child = spawn(command, args, {
|
||||
cwd: projectRoot,
|
||||
env: {
|
||||
...process.env,
|
||||
BUILD_TARGET: "web",
|
||||
},
|
||||
shell: process.platform === "win32",
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
child.on("error", reject);
|
||||
child.on("exit", (code) => {
|
||||
if (code === 0) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const originalContent = readFileSync(adapterPath, "utf-8");
|
||||
const originalMode = detectAdapterMode(originalContent);
|
||||
const shouldRestore = originalMode !== "web";
|
||||
|
||||
if (shouldRestore) {
|
||||
console.log("[build:web] Switching platform adapter to Web for packaging.");
|
||||
writeFileSync(adapterPath, switchToWebAdapter(originalContent), "utf-8");
|
||||
} else {
|
||||
console.log("[build:web] Platform adapter is already Web; leaving it as-is.");
|
||||
}
|
||||
|
||||
try {
|
||||
await run("pnpm", ["exec", "tsc"]);
|
||||
await run("pnpm", ["exec", "tsup", "--format", "esm"]);
|
||||
} finally {
|
||||
if (shouldRestore) {
|
||||
writeFileSync(adapterPath, originalContent, "utf-8");
|
||||
console.log("[build:web] Restored original platform adapter.");
|
||||
} else {
|
||||
console.log("[build:web] Kept platform adapter in original Web mode.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user