@nerviq/cli 1.17.3 → 1.19.0
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/LICENSE +23 -23
- package/README.md +4 -4
- package/bin/cli.js +61 -274
- package/package.json +60 -60
- package/src/activity.js +1039 -1039
- package/src/adoption-advisor.js +299 -299
- package/src/aider/config-parser.js +166 -166
- package/src/aider/context.js +158 -158
- package/src/aider/deep-review.js +316 -316
- package/src/aider/domain-packs.js +303 -303
- package/src/aider/freshness.js +93 -93
- package/src/aider/governance.js +253 -253
- package/src/aider/interactive.js +334 -334
- package/src/aider/mcp-packs.js +329 -329
- package/src/aider/patch.js +214 -214
- package/src/aider/plans.js +186 -186
- package/src/aider/premium.js +360 -360
- package/src/aider/setup.js +404 -404
- package/src/aider/techniques.js +16 -16
- package/src/analyze.js +951 -951
- package/src/anti-patterns.js +485 -485
- package/src/audit/instruction-files.js +180 -180
- package/src/audit/recommendations.js +577 -577
- package/src/auto-suggest.js +154 -154
- package/src/badge.js +13 -13
- package/src/behavioral-drift.js +801 -801
- package/src/benchmark.js +67 -67
- package/src/catalog.js +103 -103
- package/src/certification.js +128 -128
- package/src/codex/config-parser.js +183 -183
- package/src/codex/context.js +223 -223
- package/src/codex/deep-review.js +493 -493
- package/src/codex/domain-packs.js +394 -394
- package/src/codex/freshness.js +84 -84
- package/src/codex/governance.js +192 -192
- package/src/codex/interactive.js +618 -618
- package/src/codex/mcp-packs.js +914 -914
- package/src/codex/patch.js +209 -209
- package/src/codex/plans.js +251 -251
- package/src/codex/premium.js +614 -614
- package/src/codex/setup.js +591 -591
- package/src/context.js +320 -320
- package/src/continuous-ops.js +681 -681
- package/src/copilot/activity.js +309 -309
- package/src/copilot/config-parser.js +280 -226
- package/src/copilot/context.js +218 -197
- package/src/copilot/deep-review.js +346 -346
- package/src/copilot/domain-packs.js +372 -372
- package/src/copilot/freshness.js +57 -57
- package/src/copilot/governance.js +222 -222
- package/src/copilot/interactive.js +406 -406
- package/src/copilot/mcp-packs.js +826 -826
- package/src/copilot/plans.js +253 -253
- package/src/copilot/premium.js +451 -451
- package/src/copilot/setup.js +488 -488
- package/src/copilot/techniques.js +219 -78
- package/src/cost-tracking.js +61 -61
- package/src/cursor/activity.js +301 -301
- package/src/cursor/config-parser.js +265 -265
- package/src/cursor/context.js +256 -256
- package/src/cursor/deep-review.js +334 -334
- package/src/cursor/domain-packs.js +368 -368
- package/src/cursor/freshness.js +65 -65
- package/src/cursor/governance.js +229 -229
- package/src/cursor/interactive.js +391 -391
- package/src/cursor/mcp-packs.js +828 -828
- package/src/cursor/plans.js +254 -254
- package/src/cursor/premium.js +469 -469
- package/src/cursor/setup.js +488 -488
- package/src/dashboard.js +493 -493
- package/src/deep-review.js +428 -428
- package/src/deprecation.js +98 -98
- package/src/diff-only.js +280 -280
- package/src/doctor.js +119 -119
- package/src/domain-pack-expansion.js +1033 -1033
- package/src/domain-packs.js +387 -387
- package/src/feedback.js +178 -178
- package/src/fix-engine.js +783 -0
- package/src/fix-prompts.js +122 -122
- package/src/formatters/sarif.js +115 -115
- package/src/freshness.js +74 -74
- package/src/gemini/config-parser.js +275 -275
- package/src/gemini/context.js +221 -221
- package/src/gemini/deep-review.js +559 -559
- package/src/gemini/domain-packs.js +393 -393
- package/src/gemini/freshness.js +66 -66
- package/src/gemini/governance.js +201 -201
- package/src/gemini/interactive.js +860 -860
- package/src/gemini/mcp-packs.js +915 -915
- package/src/gemini/plans.js +269 -269
- package/src/gemini/premium.js +760 -760
- package/src/gemini/setup.js +692 -692
- package/src/gemini/techniques.js +14 -14
- package/src/governance.js +72 -72
- package/src/harmony/add.js +68 -68
- package/src/harmony/advisor.js +333 -333
- package/src/harmony/canon.js +565 -565
- package/src/harmony/cli.js +591 -591
- package/src/harmony/drift.js +401 -401
- package/src/harmony/governance.js +313 -313
- package/src/harmony/memory.js +239 -239
- package/src/harmony/sync.js +475 -475
- package/src/harmony/watch.js +370 -370
- package/src/hook-validation.js +342 -342
- package/src/index.js +271 -271
- package/src/init.js +184 -184
- package/src/instruction-surfaces.js +185 -185
- package/src/integrations.js +144 -144
- package/src/interactive.js +118 -118
- package/src/locales/en.json +1 -1
- package/src/locales/es.json +1 -1
- package/src/mcp-packs.js +830 -830
- package/src/mcp-server.js +726 -726
- package/src/mcp-validation.js +337 -337
- package/src/nerviq-sync.json +7 -7
- package/src/opencode/config-parser.js +109 -109
- package/src/opencode/context.js +247 -247
- package/src/opencode/deep-review.js +313 -313
- package/src/opencode/domain-packs.js +262 -262
- package/src/opencode/freshness.js +66 -66
- package/src/opencode/governance.js +159 -159
- package/src/opencode/interactive.js +392 -392
- package/src/opencode/mcp-packs.js +705 -705
- package/src/opencode/patch.js +184 -184
- package/src/opencode/plans.js +231 -231
- package/src/opencode/premium.js +413 -413
- package/src/opencode/setup.js +449 -449
- package/src/opencode/techniques.js +27 -27
- package/src/operating-profile.js +574 -574
- package/src/org.js +152 -152
- package/src/permission-rules.js +218 -218
- package/src/plans.js +839 -839
- package/src/platform-change-manifest.js +86 -86
- package/src/plugins.js +110 -110
- package/src/policy-layers.js +210 -210
- package/src/profiles.js +124 -124
- package/src/prompt-injection.js +74 -74
- package/src/public-api.js +173 -173
- package/src/recommendation-rules.js +84 -84
- package/src/repo-archetype.js +386 -386
- package/src/secret-patterns.js +39 -39
- package/src/server.js +527 -527
- package/src/setup/analysis.js +607 -607
- package/src/setup/runtime.js +172 -172
- package/src/setup.js +677 -677
- package/src/shared/capabilities.js +194 -194
- package/src/source-urls.js +132 -132
- package/src/stack-checks.js +565 -565
- package/src/supplemental-checks.js +13 -13
- package/src/synergy/adaptive.js +261 -261
- package/src/synergy/compensation.js +137 -137
- package/src/synergy/evidence.js +193 -193
- package/src/synergy/learning.js +199 -199
- package/src/synergy/patterns.js +227 -227
- package/src/synergy/ranking.js +83 -83
- package/src/synergy/report.js +165 -165
- package/src/synergy/routing.js +146 -146
- package/src/techniques/api.js +407 -407
- package/src/techniques/automation.js +316 -316
- package/src/techniques/compliance.js +257 -257
- package/src/techniques/hygiene.js +294 -294
- package/src/techniques/instructions.js +243 -243
- package/src/techniques/observability.js +226 -226
- package/src/techniques/optimization.js +142 -142
- package/src/techniques/quality.js +318 -318
- package/src/techniques/security.js +237 -237
- package/src/techniques/shared.js +443 -443
- package/src/techniques/stacks.js +2294 -2294
- package/src/techniques/tools.js +106 -106
- package/src/techniques/workflow.js +413 -413
- package/src/techniques.js +81 -81
- package/src/terminology.js +73 -73
- package/src/token-estimate.js +35 -35
- package/src/usage-patterns.js +99 -99
- package/src/verification-metadata.js +145 -145
- package/src/watch.js +247 -247
- package/src/windsurf/activity.js +302 -302
- package/src/windsurf/config-parser.js +267 -267
- package/src/windsurf/context.js +249 -249
- package/src/windsurf/deep-review.js +337 -337
- package/src/windsurf/domain-packs.js +370 -370
- package/src/windsurf/freshness.js +36 -36
- package/src/windsurf/governance.js +231 -231
- package/src/windsurf/interactive.js +388 -388
- package/src/windsurf/mcp-packs.js +792 -792
- package/src/windsurf/plans.js +247 -247
- package/src/windsurf/premium.js +468 -468
- package/src/windsurf/setup.js +471 -471
- package/src/windsurf/techniques.js +17 -17
- package/src/workspace.js +375 -375
package/src/codex/context.js
CHANGED
|
@@ -1,223 +1,223 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const { spawnSync } = require('child_process');
|
|
5
|
-
const { ProjectContext } = require('../context');
|
|
6
|
-
const { tryParseToml, getValueByPath } = require('./config-parser');
|
|
7
|
-
|
|
8
|
-
let codexVersionCache = null;
|
|
9
|
-
|
|
10
|
-
function detectCodexVersion() {
|
|
11
|
-
if (codexVersionCache !== null) {
|
|
12
|
-
return codexVersionCache;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const result = spawnSync('codex', ['--version'], { encoding: 'utf8' });
|
|
17
|
-
const output = `${result.stdout || ''} ${result.stderr || ''}`.trim();
|
|
18
|
-
const match = output.match(/codex-cli\s+([^\s]+)/i);
|
|
19
|
-
codexVersionCache = match ? match[1] : (output || null);
|
|
20
|
-
return codexVersionCache;
|
|
21
|
-
} catch {
|
|
22
|
-
codexVersionCache = null;
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function listDirs(fullPath) {
|
|
28
|
-
try {
|
|
29
|
-
return fs.readdirSync(fullPath, { withFileTypes: true }).filter(entry => entry.isDirectory());
|
|
30
|
-
} catch {
|
|
31
|
-
return [];
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
class CodexProjectContext extends ProjectContext {
|
|
36
|
-
configContent() {
|
|
37
|
-
return this.fileContent('.codex/config.toml');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
globalConfigContent() {
|
|
41
|
-
const homeDir = os.homedir();
|
|
42
|
-
const globalPath = path.join(homeDir, '.codex', 'config.toml');
|
|
43
|
-
try {
|
|
44
|
-
return fs.readFileSync(globalPath, 'utf8');
|
|
45
|
-
} catch {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
agentsMdContent() {
|
|
51
|
-
const direct = this.fileContent('AGENTS.md');
|
|
52
|
-
if (direct) return direct;
|
|
53
|
-
|
|
54
|
-
const fallbackNames = this.projectDocFallbackFilenames();
|
|
55
|
-
for (const fileName of fallbackNames) {
|
|
56
|
-
const content = this.fileContent(fileName);
|
|
57
|
-
if (content) return content;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
agentsMdPath() {
|
|
64
|
-
if (this.fileContent('AGENTS.md')) return 'AGENTS.md';
|
|
65
|
-
// .codex/AGENTS.md is an emerging pattern (e.g., jessfraz/dotfiles)
|
|
66
|
-
if (this.fileContent('.codex/AGENTS.md')) return '.codex/AGENTS.md';
|
|
67
|
-
const fallbackNames = this.projectDocFallbackFilenames();
|
|
68
|
-
for (const fileName of fallbackNames) {
|
|
69
|
-
if (this.fileContent(fileName)) return fileName;
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
agentsOverrideMdContent() {
|
|
75
|
-
return this.fileContent('AGENTS.override.md');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
hasAgentsOverride() {
|
|
79
|
-
return Boolean(this.agentsOverrideMdContent());
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
configToml() {
|
|
83
|
-
const content = this.fileContent('.codex/config.toml');
|
|
84
|
-
if (!content) {
|
|
85
|
-
return { ok: false, data: null, error: 'missing project config', source: '.codex/config.toml' };
|
|
86
|
-
}
|
|
87
|
-
const parsed = tryParseToml(content);
|
|
88
|
-
return { ...parsed, source: '.codex/config.toml' };
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
globalConfigToml() {
|
|
92
|
-
const homeDir = os.homedir();
|
|
93
|
-
const globalPath = path.join(homeDir, '.codex', 'config.toml');
|
|
94
|
-
try {
|
|
95
|
-
const content = fs.readFileSync(globalPath, 'utf8');
|
|
96
|
-
const parsed = tryParseToml(content);
|
|
97
|
-
return { ...parsed, source: globalPath };
|
|
98
|
-
} catch {
|
|
99
|
-
return { ok: false, data: null, error: 'missing global config', source: globalPath };
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
configValue(dottedPath) {
|
|
104
|
-
const project = this.configToml();
|
|
105
|
-
if (project.ok) {
|
|
106
|
-
const projectValue = getValueByPath(project.data, dottedPath);
|
|
107
|
-
if (projectValue !== undefined) return projectValue;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const globalConfig = this.globalConfigToml();
|
|
111
|
-
if (globalConfig.ok) {
|
|
112
|
-
return getValueByPath(globalConfig.data, dottedPath);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return undefined;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
projectDocFallbackFilenames() {
|
|
119
|
-
const configured = this.configValue('project_doc_fallback_filenames');
|
|
120
|
-
if (Array.isArray(configured) && configured.length > 0) {
|
|
121
|
-
return configured.filter(item => typeof item === 'string' && item.trim()).map(item => item.trim());
|
|
122
|
-
}
|
|
123
|
-
return [];
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
hooksJson() {
|
|
127
|
-
return this.jsonFile('.codex/hooks.json');
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
hooksJsonContent() {
|
|
131
|
-
return this.fileContent('.codex/hooks.json');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
hookFiles() {
|
|
135
|
-
const hooksDir = path.join(this.dir, '.codex', 'hooks');
|
|
136
|
-
return listDirs(hooksDir).map(entry => entry.name);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
skillDirs() {
|
|
140
|
-
const skillsDir = path.join(this.dir, '.agents', 'skills');
|
|
141
|
-
return listDirs(skillsDir).map(entry => entry.name);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
skillMetadata(name) {
|
|
145
|
-
return this.fileContent(path.join('.agents', 'skills', name, 'SKILL.md'));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
customAgentFiles() {
|
|
149
|
-
return this.dirFiles('.codex/agents').filter(file => file.endsWith('.toml'));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
customAgentConfig(fileName) {
|
|
153
|
-
const content = this.fileContent(path.join('.codex', 'agents', fileName));
|
|
154
|
-
if (!content) return { ok: false, data: null, error: 'missing agent config' };
|
|
155
|
-
return tryParseToml(content);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
mcpServers() {
|
|
159
|
-
return this.configValue('mcp_servers') || {};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
workflowFiles() {
|
|
163
|
-
return this.dirFiles('.github/workflows')
|
|
164
|
-
.filter(file => /\.ya?ml$/i.test(file))
|
|
165
|
-
.map(file => path.join('.github', 'workflows', file).replace(/\\/g, '/'));
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
ruleFiles() {
|
|
169
|
-
const candidateDirs = ['codex/rules', '.codex/rules'];
|
|
170
|
-
const files = [];
|
|
171
|
-
|
|
172
|
-
for (const dirPath of candidateDirs) {
|
|
173
|
-
for (const file of this.dirFiles(dirPath)) {
|
|
174
|
-
if (file.startsWith('.')) continue;
|
|
175
|
-
files.push(path.join(dirPath, file).replace(/\\/g, '/'));
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return files;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
isProjectTrusted() {
|
|
183
|
-
const content = this.globalConfigContent();
|
|
184
|
-
if (!content) return false;
|
|
185
|
-
|
|
186
|
-
const resolved = path.resolve(this.dir);
|
|
187
|
-
const variants = new Set([
|
|
188
|
-
resolved,
|
|
189
|
-
resolved.replace(/\\/g, '/'),
|
|
190
|
-
resolved.replace(/\//g, '\\'),
|
|
191
|
-
resolved.replace(/\\/g, '\\\\'),
|
|
192
|
-
]);
|
|
193
|
-
|
|
194
|
-
for (const variant of variants) {
|
|
195
|
-
const escaped = variant.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
196
|
-
const patterns = [
|
|
197
|
-
new RegExp(`["']${escaped}["'][\\s\\S]{0,220}?trust_level\\s*=\\s*["']trusted["']`, 'i'),
|
|
198
|
-
new RegExp(`trust_level\\s*=\\s*["']trusted["'][\\s\\S]{0,220}?["']${escaped}["']`, 'i'),
|
|
199
|
-
new RegExp(`projects[\\s\\S]{0,1200}?["']${escaped}["'][\\s\\S]{0,220}?trust_level\\s*=\\s*["']trusted["']`, 'i'),
|
|
200
|
-
];
|
|
201
|
-
if (patterns.some((pattern) => pattern.test(content))) {
|
|
202
|
-
return true;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return false;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
static isCodexRepo(dir) {
|
|
210
|
-
try {
|
|
211
|
-
return fs.existsSync(path.join(dir, 'AGENTS.md')) ||
|
|
212
|
-
fs.existsSync(path.join(dir, '.codex')) ||
|
|
213
|
-
fs.existsSync(path.join(dir, '.agents'));
|
|
214
|
-
} catch {
|
|
215
|
-
return false;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
module.exports = {
|
|
221
|
-
CodexProjectContext,
|
|
222
|
-
detectCodexVersion,
|
|
223
|
-
};
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { spawnSync } = require('child_process');
|
|
5
|
+
const { ProjectContext } = require('../context');
|
|
6
|
+
const { tryParseToml, getValueByPath } = require('./config-parser');
|
|
7
|
+
|
|
8
|
+
let codexVersionCache = null;
|
|
9
|
+
|
|
10
|
+
function detectCodexVersion() {
|
|
11
|
+
if (codexVersionCache !== null) {
|
|
12
|
+
return codexVersionCache;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const result = spawnSync('codex', ['--version'], { encoding: 'utf8' });
|
|
17
|
+
const output = `${result.stdout || ''} ${result.stderr || ''}`.trim();
|
|
18
|
+
const match = output.match(/codex-cli\s+([^\s]+)/i);
|
|
19
|
+
codexVersionCache = match ? match[1] : (output || null);
|
|
20
|
+
return codexVersionCache;
|
|
21
|
+
} catch {
|
|
22
|
+
codexVersionCache = null;
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function listDirs(fullPath) {
|
|
28
|
+
try {
|
|
29
|
+
return fs.readdirSync(fullPath, { withFileTypes: true }).filter(entry => entry.isDirectory());
|
|
30
|
+
} catch {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class CodexProjectContext extends ProjectContext {
|
|
36
|
+
configContent() {
|
|
37
|
+
return this.fileContent('.codex/config.toml');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
globalConfigContent() {
|
|
41
|
+
const homeDir = os.homedir();
|
|
42
|
+
const globalPath = path.join(homeDir, '.codex', 'config.toml');
|
|
43
|
+
try {
|
|
44
|
+
return fs.readFileSync(globalPath, 'utf8');
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
agentsMdContent() {
|
|
51
|
+
const direct = this.fileContent('AGENTS.md');
|
|
52
|
+
if (direct) return direct;
|
|
53
|
+
|
|
54
|
+
const fallbackNames = this.projectDocFallbackFilenames();
|
|
55
|
+
for (const fileName of fallbackNames) {
|
|
56
|
+
const content = this.fileContent(fileName);
|
|
57
|
+
if (content) return content;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
agentsMdPath() {
|
|
64
|
+
if (this.fileContent('AGENTS.md')) return 'AGENTS.md';
|
|
65
|
+
// .codex/AGENTS.md is an emerging pattern (e.g., jessfraz/dotfiles)
|
|
66
|
+
if (this.fileContent('.codex/AGENTS.md')) return '.codex/AGENTS.md';
|
|
67
|
+
const fallbackNames = this.projectDocFallbackFilenames();
|
|
68
|
+
for (const fileName of fallbackNames) {
|
|
69
|
+
if (this.fileContent(fileName)) return fileName;
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
agentsOverrideMdContent() {
|
|
75
|
+
return this.fileContent('AGENTS.override.md');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
hasAgentsOverride() {
|
|
79
|
+
return Boolean(this.agentsOverrideMdContent());
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
configToml() {
|
|
83
|
+
const content = this.fileContent('.codex/config.toml');
|
|
84
|
+
if (!content) {
|
|
85
|
+
return { ok: false, data: null, error: 'missing project config', source: '.codex/config.toml' };
|
|
86
|
+
}
|
|
87
|
+
const parsed = tryParseToml(content);
|
|
88
|
+
return { ...parsed, source: '.codex/config.toml' };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
globalConfigToml() {
|
|
92
|
+
const homeDir = os.homedir();
|
|
93
|
+
const globalPath = path.join(homeDir, '.codex', 'config.toml');
|
|
94
|
+
try {
|
|
95
|
+
const content = fs.readFileSync(globalPath, 'utf8');
|
|
96
|
+
const parsed = tryParseToml(content);
|
|
97
|
+
return { ...parsed, source: globalPath };
|
|
98
|
+
} catch {
|
|
99
|
+
return { ok: false, data: null, error: 'missing global config', source: globalPath };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
configValue(dottedPath) {
|
|
104
|
+
const project = this.configToml();
|
|
105
|
+
if (project.ok) {
|
|
106
|
+
const projectValue = getValueByPath(project.data, dottedPath);
|
|
107
|
+
if (projectValue !== undefined) return projectValue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const globalConfig = this.globalConfigToml();
|
|
111
|
+
if (globalConfig.ok) {
|
|
112
|
+
return getValueByPath(globalConfig.data, dottedPath);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
projectDocFallbackFilenames() {
|
|
119
|
+
const configured = this.configValue('project_doc_fallback_filenames');
|
|
120
|
+
if (Array.isArray(configured) && configured.length > 0) {
|
|
121
|
+
return configured.filter(item => typeof item === 'string' && item.trim()).map(item => item.trim());
|
|
122
|
+
}
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
hooksJson() {
|
|
127
|
+
return this.jsonFile('.codex/hooks.json');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
hooksJsonContent() {
|
|
131
|
+
return this.fileContent('.codex/hooks.json');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
hookFiles() {
|
|
135
|
+
const hooksDir = path.join(this.dir, '.codex', 'hooks');
|
|
136
|
+
return listDirs(hooksDir).map(entry => entry.name);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
skillDirs() {
|
|
140
|
+
const skillsDir = path.join(this.dir, '.agents', 'skills');
|
|
141
|
+
return listDirs(skillsDir).map(entry => entry.name);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
skillMetadata(name) {
|
|
145
|
+
return this.fileContent(path.join('.agents', 'skills', name, 'SKILL.md'));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
customAgentFiles() {
|
|
149
|
+
return this.dirFiles('.codex/agents').filter(file => file.endsWith('.toml'));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
customAgentConfig(fileName) {
|
|
153
|
+
const content = this.fileContent(path.join('.codex', 'agents', fileName));
|
|
154
|
+
if (!content) return { ok: false, data: null, error: 'missing agent config' };
|
|
155
|
+
return tryParseToml(content);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
mcpServers() {
|
|
159
|
+
return this.configValue('mcp_servers') || {};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
workflowFiles() {
|
|
163
|
+
return this.dirFiles('.github/workflows')
|
|
164
|
+
.filter(file => /\.ya?ml$/i.test(file))
|
|
165
|
+
.map(file => path.join('.github', 'workflows', file).replace(/\\/g, '/'));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
ruleFiles() {
|
|
169
|
+
const candidateDirs = ['codex/rules', '.codex/rules'];
|
|
170
|
+
const files = [];
|
|
171
|
+
|
|
172
|
+
for (const dirPath of candidateDirs) {
|
|
173
|
+
for (const file of this.dirFiles(dirPath)) {
|
|
174
|
+
if (file.startsWith('.')) continue;
|
|
175
|
+
files.push(path.join(dirPath, file).replace(/\\/g, '/'));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return files;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
isProjectTrusted() {
|
|
183
|
+
const content = this.globalConfigContent();
|
|
184
|
+
if (!content) return false;
|
|
185
|
+
|
|
186
|
+
const resolved = path.resolve(this.dir);
|
|
187
|
+
const variants = new Set([
|
|
188
|
+
resolved,
|
|
189
|
+
resolved.replace(/\\/g, '/'),
|
|
190
|
+
resolved.replace(/\//g, '\\'),
|
|
191
|
+
resolved.replace(/\\/g, '\\\\'),
|
|
192
|
+
]);
|
|
193
|
+
|
|
194
|
+
for (const variant of variants) {
|
|
195
|
+
const escaped = variant.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
196
|
+
const patterns = [
|
|
197
|
+
new RegExp(`["']${escaped}["'][\\s\\S]{0,220}?trust_level\\s*=\\s*["']trusted["']`, 'i'),
|
|
198
|
+
new RegExp(`trust_level\\s*=\\s*["']trusted["'][\\s\\S]{0,220}?["']${escaped}["']`, 'i'),
|
|
199
|
+
new RegExp(`projects[\\s\\S]{0,1200}?["']${escaped}["'][\\s\\S]{0,220}?trust_level\\s*=\\s*["']trusted["']`, 'i'),
|
|
200
|
+
];
|
|
201
|
+
if (patterns.some((pattern) => pattern.test(content))) {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
static isCodexRepo(dir) {
|
|
210
|
+
try {
|
|
211
|
+
return fs.existsSync(path.join(dir, 'AGENTS.md')) ||
|
|
212
|
+
fs.existsSync(path.join(dir, '.codex')) ||
|
|
213
|
+
fs.existsSync(path.join(dir, '.agents'));
|
|
214
|
+
} catch {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
module.exports = {
|
|
221
|
+
CodexProjectContext,
|
|
222
|
+
detectCodexVersion,
|
|
223
|
+
};
|