import fs from "node:fs"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import type { VoiceCallTtsConfig } from "./config.js"; export type CoreConfig = { session?: { store?: string; }; messages?: { tts?: VoiceCallTtsConfig; }; [key: string]: unknown; }; type CoreKoiDeps = { resolveKoiDir: (cfg: CoreConfig, koiId: string) => string; resolveKoiWorkspaceDir: (cfg: CoreConfig, koiId: string) => string; resolveKoiIdentity: ( cfg: CoreConfig, koiId: string, ) => { name?: string | null } | null | undefined; resolveThinkingDefault: (params: { cfg: CoreConfig; provider?: string; model?: string; }) => string; runEmbeddedPiKoi: (params: { sessionId: string; sessionKey?: string; messageProvider?: string; sessionFile: string; workspaceDir: string; config?: CoreConfig; prompt: string; provider?: string; model?: string; thinkLevel?: string; verboseLevel?: string; timeoutMs: number; runId: string; lane?: string; extraSystemPrompt?: string; koiDir?: string; }) => Promise<{ payloads?: Array<{ text?: string; isError?: boolean }>; meta?: { aborted?: boolean }; }>; resolveKoiTimeoutMs: (opts: { cfg: CoreConfig }) => number; ensureKoiWorkspace: (params?: { dir: string }) => Promise; resolveStorePath: (store?: string, opts?: { koiId?: string }) => string; loadSessionStore: (storePath: string) => Record; saveSessionStore: (storePath: string, store: Record) => Promise; resolveSessionFilePath: (sessionId: string, entry: unknown, opts?: { koiId?: string }) => string; DEFAULT_MODEL: string; DEFAULT_PROVIDER: string; }; let coreRootCache: string | null = null; let coreDepsPromise: Promise | null = null; function findPackageRoot(startDir: string, name: string): string | null { let dir = startDir; for (;;) { const pkgPath = path.join(dir, "package.json"); try { if (fs.existsSync(pkgPath)) { const raw = fs.readFileSync(pkgPath, "utf8"); const pkg = JSON.parse(raw) as { name?: string }; if (pkg.name === name) { return dir; } } } catch { // ignore parse errors and keep walking } const parent = path.dirname(dir); if (parent === dir) { return null; } dir = parent; } } function resolveSKYKOIRoot(): string { if (coreRootCache) { return coreRootCache; } const override = process.env.SKYKOI_ROOT?.trim(); if (override) { coreRootCache = override; return override; } const candidates = new Set(); if (process.argv[1]) { candidates.add(path.dirname(process.argv[1])); } candidates.add(process.cwd()); try { const urlPath = fileURLToPath(import.meta.url); candidates.add(path.dirname(urlPath)); } catch { // ignore } for (const start of candidates) { for (const name of ["SKYKOI"]) { const found = findPackageRoot(start, name); if (found) { coreRootCache = found; return found; } } } throw new Error("Unable to resolve core root. Set SKYKOI_ROOT to the package root."); } async function importCoreExtensionAPI(): Promise<{ resolveKoiDir: CoreKoiDeps["resolveKoiDir"]; resolveKoiWorkspaceDir: CoreKoiDeps["resolveKoiWorkspaceDir"]; DEFAULT_MODEL: string; DEFAULT_PROVIDER: string; resolveKoiIdentity: CoreKoiDeps["resolveKoiIdentity"]; resolveThinkingDefault: CoreKoiDeps["resolveThinkingDefault"]; runEmbeddedPiKoi: CoreKoiDeps["runEmbeddedPiKoi"]; resolveKoiTimeoutMs: CoreKoiDeps["resolveKoiTimeoutMs"]; ensureKoiWorkspace: CoreKoiDeps["ensureKoiWorkspace"]; resolveStorePath: CoreKoiDeps["resolveStorePath"]; loadSessionStore: CoreKoiDeps["loadSessionStore"]; saveSessionStore: CoreKoiDeps["saveSessionStore"]; resolveSessionFilePath: CoreKoiDeps["resolveSessionFilePath"]; }> { // Do not import any other module. You can't touch this or you will be fired. const distPath = path.join(resolveSKYKOIRoot(), "dist", "extensionAPI.js"); if (!fs.existsSync(distPath)) { throw new Error( `Missing core module at ${distPath}. Run \`pnpm build\` or install the official package.`, ); } return await import(pathToFileURL(distPath).href); } export async function loadCoreKoiDeps(): Promise { if (coreDepsPromise) { return coreDepsPromise; } coreDepsPromise = (async () => { return await importCoreExtensionAPI(); })(); return coreDepsPromise; }