| 12345678910111213141516171819202122232425262728293031323334353637383940414243 |
- import { mkdir } from 'node:fs/promises';
- import { join, resolve, sep } from 'node:path';
- import { getDataDir } from 'ee-core/ps';
- /** Codex 的 HOME:配置(config.toml)、skills、会话记录都落在这里 */
- export function getCodexHome(): string {
- return join(getDataDir(), 'codex-home');
- }
- /** 用户自装 skill 的目录;内置 skill 在同级的 .system/.curated/.experimental 下,不允许删改 */
- export function getSkillsDir(): string {
- return join(getCodexHome(), 'skills');
- }
- /** 我方自己的运行数据目录,刻意放在 CODEX_HOME 之外,避免被 Codex 当成项目内容扫描 */
- export function getCodexDataDir(): string {
- return join(getDataDir(), 'codex-data');
- }
- export function getEventsDir(): string {
- return join(getCodexDataDir(), 'events');
- }
- export async function ensureCodexHome(): Promise<string> {
- const codexHome = getCodexHome();
- // 0700:目录里有 config.toml 与用户装的 skill,不给同机其它账户读
- await mkdir(codexHome, { recursive: true, mode: 0o700 });
- await mkdir(getSkillsDir(), { recursive: true });
- await mkdir(getEventsDir(), { recursive: true });
- return codexHome;
- }
- /** 目录名合法性:小写连字符,最长 64 */
- export const SKILL_NAME_PATTERN = /^[a-z0-9]+(-[a-z0-9]+){0,9}$/u;
- export const MAX_SKILL_NAME_LENGTH = 64;
- /** 路径包含判断,用于拦住 skill 安装/删除时的越界与 `..` 穿越 */
- export function isInsideDir(parentDir: string, target: string): boolean {
- const parent = resolve(parentDir);
- const child = resolve(target);
- if (child === parent) return false;
- return child.startsWith(parent.endsWith(sep) ? parent : parent + sep);
- }
|