Files
fusion/plugins/fusion-plugin-hermes-runtime/dist/fusion-skill-install.js
gsxdsm 72691c6fd6 fix(dashboard): write ChatView visualViewport vars imperatively
The mobile composer/footer slid over the message list when the user
swiped with the keyboard up. Cause: --vv-height / --vv-offset-top were
routed through React state via useMobileKeyboard, so on iOS — which
fires visualViewport scroll/resize on the same frame as its keyboard
animation — the .chat-thread translation lagged by one paint, visible
as the composer momentarily floating over messages.

Now those two vars are written imperatively in a useLayoutEffect
directly to the .chat-thread DOM node on every visualViewport event,
mirroring the working pattern at QuickChatFAB.tsx:1032-1052 (which
already works correctly on mobile). Only --keyboard-overlap (a
structural open/close signal, not per-frame) still flows through
React state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:25:38 -07:00

152 lines
5.4 KiB
JavaScript

import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, rmSync, symlinkSync, unlinkSync, } from "node:fs";
import { homedir } from "node:os";
import { basename, dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
export const FUSION_SKILL_NAME = "fusion";
export function resolveHermesHome(profile) {
const base = process.env.HERMES_HOME ?? join(homedir(), ".hermes");
if (!profile || profile === "default")
return base;
return join(base, "profiles", profile);
}
export function getFusionSkillSourceCandidates(moduleUrl = import.meta.url) {
const here = fileURLToPath(moduleUrl);
const moduleDir = dirname(here);
return [
resolve(moduleDir, "..", "..", "..", "..", "packages", "cli", "skill", FUSION_SKILL_NAME),
resolve(moduleDir, "..", "..", "..", "skill", FUSION_SKILL_NAME),
resolve(moduleDir, "..", "..", "skill", FUSION_SKILL_NAME),
resolve(moduleDir, "..", "..", "..", "..", "skill", FUSION_SKILL_NAME),
];
}
export function resolveBundledFusionSkillSource() {
const candidates = getFusionSkillSourceCandidates();
for (const candidate of candidates) {
if (existsSync(join(candidate, "SKILL.md")))
return candidate;
}
return null;
}
export function resolveBundledFusionSkillSourceFromCandidates(candidates) {
for (const candidate of candidates) {
if (existsSync(join(candidate, "SKILL.md")))
return candidate;
}
return null;
}
export function installFusionSkillIntoHermesHome(options = {}) {
const sourceDir = options.sourceDir ?? resolveBundledFusionSkillSource();
const targetDir = join(resolveHermesHome(options.profile), "skills", FUSION_SKILL_NAME);
if (!sourceDir) {
return {
outcome: "warning",
sourceDir,
targetDir,
reason: "bundled Fusion skill source directory not found",
};
}
try {
mkdirSync(dirname(targetDir), { recursive: true });
let replaced = false;
if (existsSync(targetDir) || isBrokenSymlink(targetDir)) {
const stat = lstatSync(targetDir);
if (stat.isSymbolicLink()) {
const currentTarget = safeReadlink(targetDir);
if (currentTarget && resolve(dirname(targetDir), currentTarget) === resolve(sourceDir)) {
return { outcome: "already-installed", sourceDir, targetDir };
}
if (!looksLikeFusionSkillTarget(resolve(dirname(targetDir), currentTarget ?? ""))) {
return {
outcome: "skipped",
sourceDir,
targetDir,
reason: "existing symlink does not look like a Fusion skill install",
};
}
unlinkSync(targetDir);
replaced = true;
}
else {
if (!looksLikePriorFusionInstall(targetDir)) {
return {
outcome: "skipped",
sourceDir,
targetDir,
reason: "existing directory does not look like a Fusion skill install",
};
}
rmSync(targetDir, { recursive: true, force: true });
replaced = true;
}
}
try {
symlinkSync(sourceDir, targetDir, "dir");
}
catch (error) {
const symlinkReason = error instanceof Error ? error.message : String(error);
try {
cpSync(sourceDir, targetDir, { recursive: true });
return {
outcome: replaced ? "replaced" : "installed",
sourceDir,
targetDir,
reason: `symlink failed (${symlinkReason}); copied files instead`,
};
}
catch (copyError) {
return {
outcome: "warning",
sourceDir,
targetDir,
reason: copyError instanceof Error ? copyError.message : String(copyError),
};
}
}
return { outcome: replaced ? "replaced" : "installed", sourceDir, targetDir };
}
catch (error) {
return {
outcome: "warning",
sourceDir,
targetDir,
reason: error instanceof Error ? error.message : String(error),
};
}
}
function safeReadlink(path) {
try {
return readlinkSync(path);
}
catch {
return null;
}
}
function isBrokenSymlink(path) {
try {
const stat = lstatSync(path);
return stat.isSymbolicLink() && !existsSync(path);
}
catch {
return false;
}
}
function looksLikePriorFusionInstall(path) {
const skillMd = join(path, "SKILL.md");
if (!existsSync(skillMd))
return false;
try {
const body = readFileSync(skillMd, "utf-8");
return /\bfusion\b/i.test(body) && /\bskill\b/i.test(body);
}
catch {
return false;
}
}
function looksLikeFusionSkillTarget(path) {
if (!path)
return false;
if (basename(path).toLowerCase() === FUSION_SKILL_NAME)
return true;
return existsSync(join(path, "SKILL.md"));
}
//# sourceMappingURL=fusion-skill-install.js.map