codecanon
Version:
CLI tool that downloads documentation from 3rd party libraries, converts them to Markdown, and optimizes for LLMs
104 lines (102 loc) • 3.51 kB
JavaScript
import { promises as fs } from "fs";
import { join } from "path";
const CANON_DIR = ".canon";
const SETTINGS_FILE = "settings.json";
const LOCAL_SETTINGS_FILE = "settings.local.json";
/**
* Initialize a new CodeCanon workspace
*/
export async function initWorkspace(options) {
const canonPath = join(options.cwd, CANON_DIR);
const settingsPath = join(canonPath, SETTINGS_FILE);
// Check if workspace already exists
try {
await fs.access(canonPath);
if (!options.force) {
throw new Error(`CodeCanon workspace already exists at ${canonPath}. Use --force to overwrite.`);
}
}
catch (error) {
// Directory doesn't exist, which is fine
}
// Create directory structure
await fs.mkdir(canonPath, { recursive: true });
await fs.mkdir(join(canonPath, "cache"), { recursive: true });
await fs.mkdir(join(canonPath, "context"), { recursive: true });
await fs.mkdir(join(canonPath, "db"), { recursive: true });
// Create initial config
const config = {
version: "0.0.2",
model: options.model,
createdAt: new Date().toISOString(),
packages: [],
};
await fs.writeFile(settingsPath, JSON.stringify(config, null, 2));
// Create initial llms.txt following the emerging standard
const llmsTxtPath = join(canonPath, "context", "llms.txt");
const llmsTxtContent = `# CodeCanon Context Index
# This file follows the llms.txt standard for LLM context discovery
# Generated on ${new Date().toISOString()}
# No packages added yet. Use 'canon add <package>' to get started.
`;
await fs.writeFile(llmsTxtPath, llmsTxtContent);
}
/**
* Load workspace configuration
*/
export async function loadWorkspaceConfig(cwd) {
const settingsPath = join(cwd, CANON_DIR, SETTINGS_FILE);
const localSettingsPath = join(cwd, CANON_DIR, LOCAL_SETTINGS_FILE);
try {
// Load base settings
const settingsData = await fs.readFile(settingsPath, "utf-8");
const config = JSON.parse(settingsData);
// Try to load local settings and merge them
try {
const localSettingsData = await fs.readFile(localSettingsPath, "utf-8");
const localConfig = JSON.parse(localSettingsData);
return { ...config, ...localConfig };
}
catch {
// Local settings file doesn't exist or is invalid, use base settings
return config;
}
}
catch (error) {
throw new Error("No CodeCanon workspace found. Run 'canon init' to create one.");
}
}
/**
* Save workspace configuration
*/
export async function saveWorkspaceConfig(cwd, config) {
const settingsPath = join(cwd, CANON_DIR, SETTINGS_FILE);
await fs.writeFile(settingsPath, JSON.stringify(config, null, 2));
}
/**
* Check if workspace is initialized
*/
export async function isWorkspaceInitialized(cwd) {
try {
await fs.access(join(cwd, CANON_DIR, SETTINGS_FILE));
return true;
}
catch {
return false;
}
}
/**
* Get paths for the workspace
*/
export function getWorkspacePaths(cwd) {
const canonPath = join(cwd, CANON_DIR);
return {
root: canonPath,
cache: join(canonPath, "cache"),
context: join(canonPath, "context"),
db: join(canonPath, "db"),
settings: join(canonPath, SETTINGS_FILE),
localSettings: join(canonPath, LOCAL_SETTINGS_FILE),
llmsTxt: join(canonPath, "context", "llms.txt"),
};
}