UNPKG

@puls-atlas/cli

Version:

The Puls Atlas CLI tool for managing Atlas projects

122 lines 4.1 kB
import fs from 'fs'; import path from 'path'; import { normalizeOptionalString } from '../../utils/value.js'; import { readJsonFile } from '../../utils/file.js'; import { createAtlasAiArtifacts, createCoverageFindings, createGeneratedFileDriftIssues, normalizeAtlasAiRefreshMode, writeAtlasAiArtifacts } from './artifactsRuntime.js'; const DEFAULT_VERIFY_POLICY_MODE = 'localDevelopment'; const isMissingSharedAtlasAiPackageError = error => normalizeOptionalString(error?.message)?.includes('Atlas AI shared package was not found at') === true; const readTextFile = (filePath, dependencies = {}) => { const { fsImpl = fs } = dependencies; if (!fsImpl.existsSync(filePath)) { return null; } try { return fsImpl.readFileSync(filePath, 'utf-8'); } catch (error) { throw new Error(`Failed to read file: ${filePath}\nError: ${error.message}`); } }; export const ensureAtlasAiContextForStart = async (options = {}, dependencies = {}, cwd = process.cwd()) => { const mode = normalizeAtlasAiRefreshMode(options.mode ?? options.aiRefresh ?? options['ai-refresh']); const { fsImpl = fs, pathImpl = path } = dependencies; const consumerPackageJsonPath = pathImpl.join(cwd, 'package.json'); if (mode === 'off') { return { status: 'disabled', summaryRows: [{ label: 'Atlas AI', value: 'disabled' }], warnings: [] }; } if (!fsImpl.existsSync(consumerPackageJsonPath)) { return { status: 'skipped', summaryRows: [], warnings: [] }; } let artifacts; try { artifacts = createAtlasAiArtifacts(options, dependencies, cwd, 'atlas start'); } catch (error) { if (isMissingSharedAtlasAiPackageError(error)) { return { status: 'skipped', summaryRows: [], warnings: [] }; } return { status: 'warning', summaryRows: [{ label: 'Atlas AI', value: 'warning', tone: 'warning' }], warnings: [`Atlas AI refresh check failed: ${error.message}`] }; } const hasExistingAgentFile = artifacts.outputPaths.agentPaths.some(agentPath => readTextFile(agentPath, dependencies) !== null); const instructionsText = readTextFile(artifacts.outputPaths.instructionsPath, dependencies); const existingSnapshot = readJsonFile(artifacts.outputPaths.snapshotPath, { allowMissing: true }, dependencies); const existingLock = readJsonFile(artifacts.outputPaths.lockFilePath, { allowMissing: true }, dependencies); const coverageFindings = createCoverageFindings(artifacts, { policyMode: DEFAULT_VERIFY_POLICY_MODE }); const warnings = [...coverageFindings.issues, ...coverageFindings.warnings]; if (mode === 'force') { writeAtlasAiArtifacts(artifacts, dependencies); return { status: 'synced', summaryRows: [{ label: 'Atlas AI', value: 'force-refresh', tone: 'success' }], warnings }; } if ((hasExistingAgentFile || instructionsText !== null || existingSnapshot !== null) && existingLock === null) { return { status: 'manual', summaryRows: [{ label: 'Atlas AI', value: 'manual', tone: 'warning' }], warnings: [...warnings, 'Atlas AI generated files exist without a managed lock file (' + `${artifacts.outputPaths.relativeAgentPaths.join(', ')}, ${artifacts.outputPaths.relativeInstructionsPath}, ${artifacts.outputPaths.relativeSnapshotPath}). ` + 'Skipping automatic refresh; run "atlas ai sync" manually when ready.'] }; } const driftIssues = createGeneratedFileDriftIssues(artifacts, dependencies); if (driftIssues.length === 0) { return { status: 'current', summaryRows: [{ label: 'Atlas AI', value: 'current' }], warnings }; } writeAtlasAiArtifacts(artifacts, dependencies); return { status: 'synced', summaryRows: [{ label: 'Atlas AI', value: instructionsText === null && existingLock === null ? 'initialized' : 'synced', tone: 'success' }], warnings }; };