@puls-atlas/cli
Version:
The Puls Atlas CLI tool for managing Atlas projects
122 lines • 4.1 kB
JavaScript
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
};
};