ai-nexus 1.3.14 → 1.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +3 -3
- package/README.md +3 -3
- package/dist/commands/init-interactive.js +5 -5
- package/dist/commands/update.js +27 -1
- package/dist/utils/files.d.ts +6 -0
- package/dist/utils/files.js +50 -0
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -90,7 +90,7 @@ npx ai-nexus install --rules github.com/your-org/team-rules
|
|
|
90
90
|
|------|-----------|-----------|
|
|
91
91
|
| **Claude Code** | 시맨틱 라우터가 프롬프트마다 동적으로 룰 교체 | 필요한 룰만 로딩 |
|
|
92
92
|
| **Cursor** | 룰을 `.mdc` 형식으로 변환; Cursor 내장 검색이 필터링 | Cursor 검색에 의존 |
|
|
93
|
-
| **Codex** |
|
|
93
|
+
| **Codex** | 집계된 `AGENTS.md` (개별 룰 병합) | 전체 룰 로딩 |
|
|
94
94
|
|
|
95
95
|
---
|
|
96
96
|
|
|
@@ -136,9 +136,9 @@ alwaysApply: false
|
|
|
136
136
|
|
|
137
137
|
변환 후 룰 필터링은 **Cursor 내장 시맨틱 서치**가 처리합니다 — ai-nexus가 Cursor에서 라우터를 실행하지는 않습니다. 핵심 가치는 통합 룰 관리: 룰을 한 번 작성하면 Claude Code, Cursor, Codex에서 모두 사용할 수 있습니다.
|
|
138
138
|
|
|
139
|
-
### Codex:
|
|
139
|
+
### Codex: 룰 집계
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
개별 룰 파일들이 단일 `AGENTS.md` 파일로 자동 병합되며, 세션 시작 시 로드됩니다. 동적 로딩 없음.
|
|
142
142
|
|
|
143
143
|
---
|
|
144
144
|
|
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ npx ai-nexus install --rules github.com/your-org/team-rules
|
|
|
90
90
|
|------|--------------|----------------|
|
|
91
91
|
| **Claude Code** | Semantic Router dynamically swaps rules per prompt | Only relevant rules loaded |
|
|
92
92
|
| **Cursor** | Converts rules to `.mdc` format; Cursor's built-in search handles filtering | Depends on Cursor's search |
|
|
93
|
-
| **Codex** |
|
|
93
|
+
| **Codex** | Aggregated `AGENTS.md` (rules merged into single file) | All rules loaded |
|
|
94
94
|
|
|
95
95
|
---
|
|
96
96
|
|
|
@@ -136,9 +136,9 @@ alwaysApply: false
|
|
|
136
136
|
|
|
137
137
|
After conversion, **Cursor's built-in semantic search** handles rule filtering — ai-nexus does not run a router for Cursor. The value is unified rule management: write rules once, use them across Claude Code, Cursor, and Codex.
|
|
138
138
|
|
|
139
|
-
### Codex:
|
|
139
|
+
### Codex: Aggregated Rules
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
Individual rule files are aggregated into a single `AGENTS.md` file, which is loaded at session start. No dynamic loading.
|
|
142
142
|
|
|
143
143
|
---
|
|
144
144
|
|
|
@@ -5,7 +5,7 @@ import { createRequire } from 'module';
|
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
import ora from 'ora';
|
|
8
|
-
import { getTargetDir, getConfigPath, ensureDir, createSymlink, scanDir, computeFileHashes, } from '../utils/files.js';
|
|
8
|
+
import { getTargetDir, getConfigPath, ensureDir, createSymlink, scanDir, computeFileHashes, aggregateToAgentsMd, } from '../utils/files.js';
|
|
9
9
|
import { scanConfigDir } from '../utils/config-scanner.js';
|
|
10
10
|
// Convert .md to .mdc format for Cursor
|
|
11
11
|
function convertToMdc(content, filename) {
|
|
@@ -376,13 +376,13 @@ async function install(selections) {
|
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
378
|
}
|
|
379
|
-
//
|
|
379
|
+
// Generate aggregated AGENTS.md for Codex
|
|
380
380
|
if (tool === 'codex') {
|
|
381
|
-
const agentsFile = path.join(builtinConfigDir, 'codex', 'AGENTS.md');
|
|
382
381
|
const destAgents = path.join(toolDir, 'AGENTS.md');
|
|
383
382
|
// Local priority: skip if file exists
|
|
384
|
-
if (!fs.existsSync(destAgents)
|
|
385
|
-
|
|
383
|
+
if (!fs.existsSync(destAgents)) {
|
|
384
|
+
const content = aggregateToAgentsMd(configDir, selectedFiles);
|
|
385
|
+
fs.writeFileSync(destAgents, content);
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
}
|
package/dist/commands/update.js
CHANGED
|
@@ -3,7 +3,7 @@ import path from 'path';
|
|
|
3
3
|
import os from 'os';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
|
-
import { detectInstall, scanDir, compareConfigs, ensureDir, computeFileHashes } from '../utils/files.js';
|
|
6
|
+
import { detectInstall, scanDir, compareConfigs, ensureDir, computeFileHashes, aggregateToAgentsMd } from '../utils/files.js';
|
|
7
7
|
import crypto from 'crypto';
|
|
8
8
|
import { updateRepo } from '../utils/git.js';
|
|
9
9
|
export async function update(options = {}) {
|
|
@@ -184,6 +184,32 @@ export async function update(options = {}) {
|
|
|
184
184
|
hasChanges = true;
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
+
// Regenerate AGENTS.md for Codex
|
|
188
|
+
if (meta.tools && meta.tools.includes('codex')) {
|
|
189
|
+
const codexDir = path.join(targetDir, '.codex');
|
|
190
|
+
const destAgents = path.join(codexDir, 'AGENTS.md');
|
|
191
|
+
const content = aggregateToAgentsMd(configDir);
|
|
192
|
+
if (fs.existsSync(destAgents)) {
|
|
193
|
+
const existing = fs.readFileSync(destAgents, 'utf8');
|
|
194
|
+
if (existing !== content) {
|
|
195
|
+
if (options.force) {
|
|
196
|
+
ensureDir(codexDir);
|
|
197
|
+
fs.writeFileSync(destAgents, content);
|
|
198
|
+
console.log(chalk.green(' ✓ Codex AGENTS.md regenerated'));
|
|
199
|
+
hasChanges = true;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
console.log(chalk.gray(' Codex AGENTS.md has changes (use --force to regenerate)'));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
ensureDir(codexDir);
|
|
208
|
+
fs.writeFileSync(destAgents, content);
|
|
209
|
+
console.log(chalk.green(' ✓ Codex AGENTS.md generated'));
|
|
210
|
+
hasChanges = true;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
187
213
|
// Update metadata (refresh file hashes for copy mode)
|
|
188
214
|
meta.updatedAt = new Date().toISOString();
|
|
189
215
|
if (meta.mode === 'copy') {
|
package/dist/utils/files.d.ts
CHANGED
|
@@ -15,6 +15,12 @@ export declare function getConfigPath(scope: 'project' | 'global'): string;
|
|
|
15
15
|
export declare function ensureDir(dir: string): void;
|
|
16
16
|
export declare function copyFile(src: string, dest: string): void;
|
|
17
17
|
export declare function createSymlink(target: string, linkPath: string): void;
|
|
18
|
+
/**
|
|
19
|
+
* Aggregate rule files into a single AGENTS.md content string.
|
|
20
|
+
* If selectedFiles is provided, only those files are included.
|
|
21
|
+
* Otherwise, all .md files in each category directory are included.
|
|
22
|
+
*/
|
|
23
|
+
export declare function aggregateToAgentsMd(configDir: string, selectedFiles?: Record<string, string[]>): string;
|
|
18
24
|
export declare function detectInstall(): {
|
|
19
25
|
configPath: string;
|
|
20
26
|
scope: 'project' | 'global';
|
package/dist/utils/files.js
CHANGED
|
@@ -83,6 +83,56 @@ export function createSymlink(target, linkPath) {
|
|
|
83
83
|
}
|
|
84
84
|
fs.symlinkSync(target, linkPath);
|
|
85
85
|
}
|
|
86
|
+
const AGENTS_CATEGORIES = ['rules', 'commands', 'skills', 'agents', 'contexts'];
|
|
87
|
+
const CATEGORY_LABELS = {
|
|
88
|
+
rules: 'Rules',
|
|
89
|
+
commands: 'Commands',
|
|
90
|
+
skills: 'Skills',
|
|
91
|
+
agents: 'Agents',
|
|
92
|
+
contexts: 'Contexts',
|
|
93
|
+
};
|
|
94
|
+
function stripFrontmatter(content) {
|
|
95
|
+
return content.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n*/, '').trim();
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Aggregate rule files into a single AGENTS.md content string.
|
|
99
|
+
* If selectedFiles is provided, only those files are included.
|
|
100
|
+
* Otherwise, all .md files in each category directory are included.
|
|
101
|
+
*/
|
|
102
|
+
export function aggregateToAgentsMd(configDir, selectedFiles) {
|
|
103
|
+
const sections = [];
|
|
104
|
+
sections.push('# AI Agent Guidelines\n');
|
|
105
|
+
sections.push('> Auto-generated by ai-nexus. Do not edit manually.\n');
|
|
106
|
+
for (const category of AGENTS_CATEGORIES) {
|
|
107
|
+
const catDir = path.join(configDir, category);
|
|
108
|
+
if (!fs.existsSync(catDir))
|
|
109
|
+
continue;
|
|
110
|
+
let files;
|
|
111
|
+
if (selectedFiles && selectedFiles[category]) {
|
|
112
|
+
files = selectedFiles[category];
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// Scan all .md files in the category directory
|
|
116
|
+
files = fs.readdirSync(catDir).filter(f => f.endsWith('.md'));
|
|
117
|
+
}
|
|
118
|
+
if (files.length === 0)
|
|
119
|
+
continue;
|
|
120
|
+
const label = CATEGORY_LABELS[category] || category;
|
|
121
|
+
sections.push(`## ${label}\n`);
|
|
122
|
+
for (const file of files) {
|
|
123
|
+
const filePath = path.join(catDir, file);
|
|
124
|
+
if (!fs.existsSync(filePath))
|
|
125
|
+
continue;
|
|
126
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
127
|
+
const body = stripFrontmatter(raw);
|
|
128
|
+
if (!body)
|
|
129
|
+
continue;
|
|
130
|
+
sections.push(body);
|
|
131
|
+
sections.push('');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return sections.join('\n').trim() + '\n';
|
|
135
|
+
}
|
|
86
136
|
export function detectInstall() {
|
|
87
137
|
const projectPath = path.join(process.cwd(), '.ai-nexus');
|
|
88
138
|
if (fs.existsSync(projectPath)) {
|