Files
sproutclaw-data/agent/extensions/pi-mcp-adapter/onboarding-state.ts
shumengya 50edff80f5 feat: 导出 SproutClaw .sproutclaw 配置
包含 extensions、skills、prompts、settings、auth、models、mcp 等配置。
排除 node_modules、npm 缓存、sessions 等运行时数据。
2026-06-26 15:48:56 +08:00

69 lines
2.2 KiB
TypeScript

import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from "node:fs";
import { dirname } from "node:path";
import { getAgentPath } from "./agent-dir.ts";
export interface McpOnboardingState {
version: 1;
sharedConfigHintShown: boolean;
setupCompleted: boolean;
lastDiscoveryFingerprint?: string;
}
const DEFAULT_STATE: McpOnboardingState = {
version: 1,
sharedConfigHintShown: false,
setupCompleted: false,
};
export function getOnboardingStatePath(): string {
return getAgentPath("mcp-onboarding.json");
}
export function loadOnboardingState(): McpOnboardingState {
const path = getOnboardingStatePath();
if (!existsSync(path)) return { ...DEFAULT_STATE };
try {
const raw = JSON.parse(readFileSync(path, "utf-8")) as Partial<McpOnboardingState>;
if (!raw || typeof raw !== "object") return { ...DEFAULT_STATE };
return {
version: 1,
sharedConfigHintShown: raw.sharedConfigHintShown === true,
setupCompleted: raw.setupCompleted === true,
lastDiscoveryFingerprint: typeof raw.lastDiscoveryFingerprint === "string" ? raw.lastDiscoveryFingerprint : undefined,
};
} catch {
return { ...DEFAULT_STATE };
}
}
export function saveOnboardingState(state: McpOnboardingState): void {
const path = getOnboardingStatePath();
mkdirSync(dirname(path), { recursive: true });
const tmpPath = `${path}.${process.pid}.tmp`;
writeFileSync(tmpPath, `${JSON.stringify(state, null, 2)}\n`, "utf-8");
renameSync(tmpPath, path);
}
export function updateOnboardingState(updater: (state: McpOnboardingState) => McpOnboardingState): McpOnboardingState {
const next = updater(loadOnboardingState());
saveOnboardingState(next);
return next;
}
export function markSharedConfigHintShown(fingerprint?: string): McpOnboardingState {
return updateOnboardingState((state) => ({
...state,
sharedConfigHintShown: true,
lastDiscoveryFingerprint: fingerprint ?? state.lastDiscoveryFingerprint,
}));
}
export function markSetupCompleted(fingerprint?: string): McpOnboardingState {
return updateOnboardingState((state) => ({
...state,
setupCompleted: true,
lastDiscoveryFingerprint: fingerprint ?? state.lastDiscoveryFingerprint,
}));
}