Primeiro Commit v0.beta1
This commit is contained in:
351
scripts/lib/runtime-paths.mjs
Normal file
351
scripts/lib/runtime-paths.mjs
Normal file
@@ -0,0 +1,351 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
export const SKILL_SLUG = "knowledge-one-view-cli";
|
||||
export const LEGACY_SKILL_SLUG = "oracle-sales-intelligence-direct";
|
||||
export const DISPLAY_RUNTIME_HOME = "<workspace>/knowledge-one-view-cli/runtime";
|
||||
export const DISPLAY_STATE_PATH = "<workspace>/knowledge-one-view-cli/runtime/auth-state.json";
|
||||
export const DISPLAY_META_PATH = "<workspace>/knowledge-one-view-cli/runtime/session-meta.json";
|
||||
export const DISPLAY_PROFILE_DIR = "<workspace>/knowledge-one-view-cli/runtime/chrome-profile";
|
||||
export const DISPLAY_CHROME_PATH = "auto-detected by platform";
|
||||
export const LEGACY_DISPLAY_HOME = `~/.codex/${LEGACY_SKILL_SLUG}`;
|
||||
|
||||
const helperDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
export const SKILL_HOME = path.resolve(helperDir, "..", "..");
|
||||
export const CODEX_HOME = path.join(os.homedir(), ".codex");
|
||||
export const LEGACY_HOME = path.join(os.homedir(), ".codex", LEGACY_SKILL_SLUG);
|
||||
export const LEGACY_STATE_PATH = path.join(LEGACY_HOME, "auth-state.json");
|
||||
export const LEGACY_META_PATH = path.join(LEGACY_HOME, "session-meta.json");
|
||||
export const LEGACY_PROFILE_DIR = path.join(LEGACY_HOME, "chrome-profile");
|
||||
|
||||
function pathExists(targetPath) {
|
||||
return Boolean(targetPath) && fs.existsSync(targetPath);
|
||||
}
|
||||
|
||||
function normalizeDir(targetPath) {
|
||||
return path.resolve(targetPath);
|
||||
}
|
||||
|
||||
function normalizeWorkspaceRuntimeHomeCandidate(targetPath) {
|
||||
const resolved = normalizeDir(targetPath);
|
||||
const runtimeName = path.basename(resolved).toLowerCase();
|
||||
if (runtimeName === "runtime") {
|
||||
return resolved;
|
||||
}
|
||||
if (!runtimeName.startsWith("runtime-")) {
|
||||
return resolved;
|
||||
}
|
||||
const parentDir = path.dirname(resolved);
|
||||
if (path.basename(parentDir) !== SKILL_SLUG) {
|
||||
return resolved;
|
||||
}
|
||||
// Keep one canonical runtime path in the workspace skill folder.
|
||||
return path.join(parentDir, "runtime");
|
||||
}
|
||||
|
||||
function looksLikeTemporaryFileName(fileName) {
|
||||
const lower = String(fileName || "").toLowerCase();
|
||||
return (
|
||||
lower.startsWith("tmp-") ||
|
||||
lower.startsWith("temp-") ||
|
||||
lower.startsWith("scratch-") ||
|
||||
lower.startsWith("intermediate-") ||
|
||||
lower.startsWith("render-output-") ||
|
||||
lower.includes(".tmp.") ||
|
||||
lower.endsWith(".tmp") ||
|
||||
lower.endsWith(".temp")
|
||||
);
|
||||
}
|
||||
|
||||
function isSameOrInside(targetPath, parentPath) {
|
||||
const relative = path.relative(parentPath, targetPath);
|
||||
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
||||
}
|
||||
|
||||
function looksLikeInstalledSkillHome(targetPath) {
|
||||
return ["SKILL.md", "scripts", "docs", "references", "tests"].some((name) =>
|
||||
pathExists(path.join(targetPath, name))
|
||||
);
|
||||
}
|
||||
|
||||
function looksLikeWorkspaceSkillHome(targetPath) {
|
||||
if (path.basename(targetPath) !== SKILL_SLUG) return false;
|
||||
if (looksLikeInstalledSkillHome(targetPath)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function candidateChromePaths() {
|
||||
if (process.platform === "win32") {
|
||||
return [
|
||||
process.env.ORACLE_SI_CHROME_PATH,
|
||||
process.env.LOCALAPPDATA
|
||||
? path.join(process.env.LOCALAPPDATA, "Google", "Chrome", "Application", "chrome.exe")
|
||||
: null,
|
||||
process.env["PROGRAMFILES"]
|
||||
? path.join(process.env["PROGRAMFILES"], "Google", "Chrome", "Application", "chrome.exe")
|
||||
: null,
|
||||
process.env["PROGRAMFILES(X86)"]
|
||||
? path.join(process.env["PROGRAMFILES(X86)"], "Google", "Chrome", "Application", "chrome.exe")
|
||||
: null,
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
if (process.platform === "darwin") {
|
||||
return [
|
||||
process.env.ORACLE_SI_CHROME_PATH,
|
||||
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
||||
path.join(os.homedir(), "Applications", "Google Chrome.app", "Contents", "MacOS", "Google Chrome"),
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
return [
|
||||
process.env.ORACLE_SI_CHROME_PATH,
|
||||
"/usr/bin/google-chrome",
|
||||
"/usr/bin/chromium",
|
||||
"/usr/bin/chromium-browser",
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
export function resolveWorkspaceRoot(candidatePath = process.cwd()) {
|
||||
const cwd = normalizeDir(candidatePath);
|
||||
const codexHome = normalizeDir(CODEX_HOME);
|
||||
if (isSameOrInside(cwd, codexHome)) {
|
||||
throw new Error(
|
||||
`Cannot infer a workspace root from ${cwd}. Run this command from the target workspace or pass --runtime-home (or ORACLE_SI_RUNTIME_HOME) explicitly. Refusing to create runtime files inside ${codexHome}.`
|
||||
);
|
||||
}
|
||||
if (looksLikeWorkspaceSkillHome(cwd)) {
|
||||
return path.dirname(cwd);
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
|
||||
export function buildRuntimeHomeFromWorkspace(workspaceRoot) {
|
||||
return path.join(normalizeDir(workspaceRoot), SKILL_SLUG, "runtime");
|
||||
}
|
||||
|
||||
export function buildLegacyRuntimeHomeFromWorkspace(workspaceRoot) {
|
||||
return path.join(normalizeDir(workspaceRoot), LEGACY_SKILL_SLUG, "runtime");
|
||||
}
|
||||
|
||||
export function resolveWorkspaceSkillHome(runtimeHome) {
|
||||
return path.dirname(resolveRuntimeHome(runtimeHome));
|
||||
}
|
||||
|
||||
export function resolveLegacyWorkspaceSkillHome(runtimeHome) {
|
||||
return path.dirname(resolveLegacyRuntimeHomeCandidate(runtimeHome));
|
||||
}
|
||||
|
||||
export function resolveRuntimeHome(explicitPath) {
|
||||
if (explicitPath) return normalizeWorkspaceRuntimeHomeCandidate(explicitPath);
|
||||
if (process.env.ORACLE_SI_RUNTIME_HOME) {
|
||||
return normalizeWorkspaceRuntimeHomeCandidate(process.env.ORACLE_SI_RUNTIME_HOME);
|
||||
}
|
||||
return buildRuntimeHomeFromWorkspace(resolveWorkspaceRoot());
|
||||
}
|
||||
|
||||
export function resolveLegacyRuntimeHomeCandidate(runtimeHome) {
|
||||
const resolvedRuntimeHome = resolveRuntimeHome(runtimeHome);
|
||||
const workspaceRoot = path.dirname(path.dirname(resolvedRuntimeHome));
|
||||
return buildLegacyRuntimeHomeFromWorkspace(workspaceRoot);
|
||||
}
|
||||
|
||||
export function resolveOutputDir(runtimeHome) {
|
||||
return path.join(resolveWorkspaceSkillHome(runtimeHome), "output");
|
||||
}
|
||||
|
||||
export function resolveOutputFilePath(explicitPath, runtimeHome) {
|
||||
if (!explicitPath) return null;
|
||||
if (path.isAbsolute(explicitPath)) return path.resolve(explicitPath);
|
||||
|
||||
const workspaceSkillHome = resolveWorkspaceSkillHome(runtimeHome);
|
||||
if (path.dirname(explicitPath) === ".") {
|
||||
// Keep user-facing/final outputs in output/, but route temporary/intermediate
|
||||
// file names directly into tmp/ to avoid polluting output/.
|
||||
const fileName = path.basename(explicitPath);
|
||||
if (looksLikeTemporaryFileName(fileName)) {
|
||||
return path.join(resolveTmpDir(runtimeHome), fileName);
|
||||
}
|
||||
return path.join(resolveOutputDir(runtimeHome), explicitPath);
|
||||
}
|
||||
|
||||
return path.join(workspaceSkillHome, explicitPath);
|
||||
}
|
||||
|
||||
export function resolveTmpDir(runtimeHome) {
|
||||
return path.join(resolveWorkspaceSkillHome(runtimeHome), "tmp");
|
||||
}
|
||||
|
||||
export function resolveTestRunsDir(runtimeHome) {
|
||||
return path.join(resolveOutputDir(runtimeHome), "test-runs");
|
||||
}
|
||||
|
||||
export function resolveTmpTestInputsDir(runtimeHome) {
|
||||
return resolveTmpDir(runtimeHome);
|
||||
}
|
||||
|
||||
export function resolveTmpRenderedSqlDir(runtimeHome) {
|
||||
return resolveTmpDir(runtimeHome);
|
||||
}
|
||||
|
||||
export function resolveTmpScratchDir(runtimeHome) {
|
||||
return resolveTmpDir(runtimeHome);
|
||||
}
|
||||
|
||||
export function resolveStateWritePath(options = {}) {
|
||||
if (options.explicitPath) return path.resolve(options.explicitPath);
|
||||
if (process.env.ORACLE_SI_STATE_PATH) return path.resolve(process.env.ORACLE_SI_STATE_PATH);
|
||||
return path.join(resolveRuntimeHome(options.runtimeHome), "auth-state.json");
|
||||
}
|
||||
|
||||
export function resolveMetaWritePath(options = {}) {
|
||||
if (options.explicitPath) return path.resolve(options.explicitPath);
|
||||
if (process.env.ORACLE_SI_META_PATH) return path.resolve(process.env.ORACLE_SI_META_PATH);
|
||||
return path.join(resolveRuntimeHome(options.runtimeHome), "session-meta.json");
|
||||
}
|
||||
|
||||
export function resolveProfileDir(options = {}) {
|
||||
if (options.explicitPath) return path.resolve(options.explicitPath);
|
||||
if (process.env.ORACLE_SI_PROFILE_DIR) return path.resolve(process.env.ORACLE_SI_PROFILE_DIR);
|
||||
return path.join(resolveRuntimeHome(options.runtimeHome), "chrome-profile");
|
||||
}
|
||||
|
||||
export function resolveStateReadPath(options = {}) {
|
||||
const preferred = resolveStateWritePath(options);
|
||||
if (pathExists(preferred)) return preferred;
|
||||
const legacyWorkspacePath = path.join(
|
||||
resolveLegacyRuntimeHomeCandidate(options.runtimeHome),
|
||||
"auth-state.json"
|
||||
);
|
||||
if (pathExists(legacyWorkspacePath)) return legacyWorkspacePath;
|
||||
return pathExists(LEGACY_STATE_PATH) ? LEGACY_STATE_PATH : preferred;
|
||||
}
|
||||
|
||||
export function resolveMetaReadPath(options = {}) {
|
||||
const preferred = resolveMetaWritePath(options);
|
||||
if (pathExists(preferred)) return preferred;
|
||||
const legacyWorkspacePath = path.join(
|
||||
resolveLegacyRuntimeHomeCandidate(options.runtimeHome),
|
||||
"session-meta.json"
|
||||
);
|
||||
if (pathExists(legacyWorkspacePath)) return legacyWorkspacePath;
|
||||
return pathExists(LEGACY_META_PATH) ? LEGACY_META_PATH : preferred;
|
||||
}
|
||||
|
||||
export function resolveChromePath(explicitPath) {
|
||||
if (explicitPath) return path.resolve(explicitPath);
|
||||
if (process.env.ORACLE_SI_CHROME_PATH) return path.resolve(process.env.ORACLE_SI_CHROME_PATH);
|
||||
|
||||
for (const candidate of candidateChromePaths()) {
|
||||
if (pathExists(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return candidateChromePaths()[0] || "google-chrome";
|
||||
}
|
||||
|
||||
export async function ensureDir(dirPath) {
|
||||
await fs.promises.mkdir(dirPath, { recursive: true });
|
||||
}
|
||||
|
||||
export async function ensureParentDir(filePath) {
|
||||
await ensureDir(path.dirname(filePath));
|
||||
}
|
||||
|
||||
async function migrateLegacyTmpSubdirs(tmpDir) {
|
||||
const legacySubdirs = ["test-inputs", "rendered-sql", "scratch"];
|
||||
const moveFileToTmpRoot = async (sourcePath) => {
|
||||
const ext = path.extname(sourcePath);
|
||||
const base = path.basename(sourcePath, ext);
|
||||
let candidateName = path.basename(sourcePath);
|
||||
let targetPath = path.join(tmpDir, candidateName);
|
||||
let suffix = 1;
|
||||
|
||||
while (pathExists(targetPath)) {
|
||||
candidateName = `${base}-migrated-${suffix}${ext}`;
|
||||
targetPath = path.join(tmpDir, candidateName);
|
||||
suffix += 1;
|
||||
}
|
||||
|
||||
await fs.promises.rename(sourcePath, targetPath);
|
||||
};
|
||||
|
||||
const walkAndMoveFiles = async (currentDir) => {
|
||||
const entries = await fs.promises.readdir(currentDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const absolutePath = path.join(currentDir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
await walkAndMoveFiles(absolutePath);
|
||||
continue;
|
||||
}
|
||||
await moveFileToTmpRoot(absolutePath);
|
||||
}
|
||||
};
|
||||
|
||||
for (const subdirName of legacySubdirs) {
|
||||
const legacyDir = path.join(tmpDir, subdirName);
|
||||
if (!pathExists(legacyDir)) continue;
|
||||
await walkAndMoveFiles(legacyDir);
|
||||
await fs.promises.rm(legacyDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
async function migrateTemporaryOutputFiles(outputDir, tmpDir) {
|
||||
if (!pathExists(outputDir)) return;
|
||||
const entries = await fs.promises.readdir(outputDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (!entry.isFile()) continue;
|
||||
if (!looksLikeTemporaryFileName(entry.name)) continue;
|
||||
const sourcePath = path.join(outputDir, entry.name);
|
||||
let candidateName = entry.name;
|
||||
let targetPath = path.join(tmpDir, candidateName);
|
||||
let suffix = 1;
|
||||
const ext = path.extname(entry.name);
|
||||
const base = path.basename(entry.name, ext);
|
||||
while (pathExists(targetPath)) {
|
||||
candidateName = `${base}-migrated-${suffix}${ext}`;
|
||||
targetPath = path.join(tmpDir, candidateName);
|
||||
suffix += 1;
|
||||
}
|
||||
await fs.promises.rename(sourcePath, targetPath);
|
||||
}
|
||||
}
|
||||
|
||||
export async function ensureRuntimeTree(runtimeHome) {
|
||||
const resolvedRuntimeHome = resolveRuntimeHome(runtimeHome);
|
||||
const workspaceSkillHome = resolveWorkspaceSkillHome(resolvedRuntimeHome);
|
||||
const outputDir = resolveOutputDir(resolvedRuntimeHome);
|
||||
const testRunsDir = resolveTestRunsDir(resolvedRuntimeHome);
|
||||
const tmpDir = resolveTmpDir(resolvedRuntimeHome);
|
||||
const tmpTestInputsDir = resolveTmpTestInputsDir(resolvedRuntimeHome);
|
||||
const tmpRenderedSqlDir = resolveTmpRenderedSqlDir(resolvedRuntimeHome);
|
||||
const tmpScratchDir = resolveTmpScratchDir(resolvedRuntimeHome);
|
||||
const profileDir = resolveProfileDir({ runtimeHome: resolvedRuntimeHome });
|
||||
|
||||
await ensureDir(workspaceSkillHome);
|
||||
await ensureDir(resolvedRuntimeHome);
|
||||
await ensureDir(outputDir);
|
||||
await ensureDir(testRunsDir);
|
||||
await ensureDir(tmpDir);
|
||||
await migrateLegacyTmpSubdirs(tmpDir);
|
||||
await migrateTemporaryOutputFiles(outputDir, tmpDir);
|
||||
await ensureDir(tmpTestInputsDir);
|
||||
await ensureDir(tmpRenderedSqlDir);
|
||||
await ensureDir(tmpScratchDir);
|
||||
await ensureDir(profileDir);
|
||||
|
||||
return {
|
||||
workspaceSkillHome,
|
||||
runtimeHome: resolvedRuntimeHome,
|
||||
outputDir,
|
||||
testRunsDir,
|
||||
tmpDir,
|
||||
tmpTestInputsDir,
|
||||
tmpRenderedSqlDir,
|
||||
tmpScratchDir,
|
||||
profileDir,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user