fix(claude-code-command-loader): skip EXCLUDED_DIRS and memoize per directory
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,37 @@
|
|||||||
|
import { promises as fs } from "fs"
|
||||||
|
import { resolve } from "path"
|
||||||
|
|
||||||
|
import type { CommandDefinition } from "./types"
|
||||||
|
|
||||||
|
const commandLoaderCache = new Map<string, Promise<Record<string, CommandDefinition>>>()
|
||||||
|
|
||||||
|
export async function getCommandLoaderCacheKey(directory?: string): Promise<string> {
|
||||||
|
const resolvedDirectory = resolve(directory ?? process.cwd())
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await fs.realpath(resolvedDirectory)
|
||||||
|
} catch {
|
||||||
|
return resolvedDirectory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCachedCommands(
|
||||||
|
cacheKey: string,
|
||||||
|
): Promise<Record<string, CommandDefinition>> | undefined {
|
||||||
|
return commandLoaderCache.get(cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setCachedCommands(
|
||||||
|
cacheKey: string,
|
||||||
|
commands: Promise<Record<string, CommandDefinition>>,
|
||||||
|
): void {
|
||||||
|
commandLoaderCache.set(cacheKey, commands)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteCachedCommands(cacheKey: string): void {
|
||||||
|
commandLoaderCache.delete(cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearCommandLoaderCache(): void {
|
||||||
|
commandLoaderCache.clear()
|
||||||
|
}
|
||||||
@@ -4,13 +4,23 @@ import { parseFrontmatter } from "../../shared/frontmatter"
|
|||||||
import { sanitizeModelField } from "../../shared/model-sanitizer"
|
import { sanitizeModelField } from "../../shared/model-sanitizer"
|
||||||
import { isMarkdownFile } from "../../shared/file-utils"
|
import { isMarkdownFile } from "../../shared/file-utils"
|
||||||
import {
|
import {
|
||||||
|
EXCLUDED_DIRS,
|
||||||
findProjectOpencodeCommandDirs,
|
findProjectOpencodeCommandDirs,
|
||||||
getClaudeConfigDir,
|
getClaudeConfigDir,
|
||||||
getOpenCodeCommandDirs,
|
getOpenCodeCommandDirs,
|
||||||
} from "../../shared"
|
} from "../../shared"
|
||||||
import { log } from "../../shared/logger"
|
import { log } from "../../shared/logger"
|
||||||
|
import {
|
||||||
|
clearCommandLoaderCache,
|
||||||
|
deleteCachedCommands,
|
||||||
|
getCachedCommands,
|
||||||
|
getCommandLoaderCacheKey,
|
||||||
|
setCachedCommands,
|
||||||
|
} from "./loader-cache"
|
||||||
import type { CommandScope, CommandDefinition, CommandFrontmatter, LoadedCommand } from "./types"
|
import type { CommandScope, CommandDefinition, CommandFrontmatter, LoadedCommand } from "./types"
|
||||||
|
|
||||||
|
export { clearCommandLoaderCache }
|
||||||
|
|
||||||
async function loadCommandsFromDir(
|
async function loadCommandsFromDir(
|
||||||
commandsDir: string,
|
commandsDir: string,
|
||||||
scope: CommandScope,
|
scope: CommandScope,
|
||||||
@@ -48,6 +58,7 @@ async function loadCommandsFromDir(
|
|||||||
|
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
|
if (EXCLUDED_DIRS.has(entry.name)) continue
|
||||||
if (entry.name.startsWith(".")) continue
|
if (entry.name.startsWith(".")) continue
|
||||||
const subDirPath = join(commandsDir, entry.name)
|
const subDirPath = join(commandsDir, entry.name)
|
||||||
const subPrefix = prefix ? `${prefix}/${entry.name}` : entry.name
|
const subPrefix = prefix ? `${prefix}/${entry.name}` : entry.name
|
||||||
@@ -159,11 +170,26 @@ export async function loadOpencodeProjectCommands(directory?: string): Promise<R
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function loadAllCommands(directory?: string): Promise<Record<string, CommandDefinition>> {
|
export async function loadAllCommands(directory?: string): Promise<Record<string, CommandDefinition>> {
|
||||||
const [user, project, global, projectOpencode] = await Promise.all([
|
const cacheKey = await getCommandLoaderCacheKey(directory)
|
||||||
|
const cachedCommands = getCachedCommands(cacheKey)
|
||||||
|
if (cachedCommands) {
|
||||||
|
return cachedCommands
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadCommandsPromise = Promise.all([
|
||||||
loadUserCommands(),
|
loadUserCommands(),
|
||||||
loadProjectCommands(directory),
|
loadProjectCommands(directory),
|
||||||
loadOpencodeGlobalCommands(),
|
loadOpencodeGlobalCommands(),
|
||||||
loadOpencodeProjectCommands(directory),
|
loadOpencodeProjectCommands(directory),
|
||||||
])
|
])
|
||||||
return { ...projectOpencode, ...global, ...project, ...user }
|
.then(([user, project, global, projectOpencode]) => {
|
||||||
|
return { ...projectOpencode, ...global, ...project, ...user }
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
deleteCachedCommands(cacheKey)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
|
||||||
|
setCachedCommands(cacheKey, loadCommandsPromise)
|
||||||
|
return loadCommandsPromise
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user