@lnai/core 0.5.0 → 0.6.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/dist/index.d.ts +19 -2
- package/dist/index.js +189 -35
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
declare const UNIFIED_DIR = ".ai";
|
|
4
|
-
declare const TOOL_IDS: readonly ["claudeCode", "opencode", "cursor", "copilot", "windsurf", "gemini"];
|
|
4
|
+
declare const TOOL_IDS: readonly ["claudeCode", "opencode", "cursor", "copilot", "windsurf", "gemini", "codex"];
|
|
5
5
|
type ToolId = (typeof TOOL_IDS)[number];
|
|
6
6
|
declare const CONFIG_FILES: {
|
|
7
7
|
readonly config: "config.json";
|
|
@@ -69,6 +69,7 @@ declare const toolIdSchema: z.ZodEnum<{
|
|
|
69
69
|
copilot: "copilot";
|
|
70
70
|
windsurf: "windsurf";
|
|
71
71
|
gemini: "gemini";
|
|
72
|
+
codex: "codex";
|
|
72
73
|
}>;
|
|
73
74
|
/** Settings configuration (Claude format as source of truth) */
|
|
74
75
|
declare const settingsSchema: z.ZodObject<{
|
|
@@ -116,6 +117,10 @@ declare const configSchema: z.ZodObject<{
|
|
|
116
117
|
enabled: z.ZodBoolean;
|
|
117
118
|
versionControl: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
118
119
|
}, z.core.$strip>>;
|
|
120
|
+
codex: z.ZodOptional<z.ZodObject<{
|
|
121
|
+
enabled: z.ZodBoolean;
|
|
122
|
+
versionControl: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
123
|
+
}, z.core.$strip>>;
|
|
119
124
|
}, z.core.$strip>>;
|
|
120
125
|
}, z.core.$strip>;
|
|
121
126
|
/** Skill frontmatter (name and description required) */
|
|
@@ -249,6 +254,18 @@ interface Plugin {
|
|
|
249
254
|
*/
|
|
250
255
|
declare const claudeCodePlugin: Plugin;
|
|
251
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Codex plugin for exporting to .codex/ format
|
|
259
|
+
*
|
|
260
|
+
* Output structure:
|
|
261
|
+
* - AGENTS.md (symlink -> .ai/AGENTS.md) [at project root]
|
|
262
|
+
* - <dir>/AGENTS.md (generated from .ai/rules/*.md, per glob directory)
|
|
263
|
+
* - .codex/skills/<name>/ (symlink -> ../../.ai/skills/<name>)
|
|
264
|
+
* - .codex/config.toml (generated from settings.mcpServers)
|
|
265
|
+
* - .codex/<path> (symlink -> ../.ai/.codex/<path>) for override files
|
|
266
|
+
*/
|
|
267
|
+
declare const codexPlugin: Plugin;
|
|
268
|
+
|
|
252
269
|
/**
|
|
253
270
|
* OpenCode plugin for exporting to opencode.json format
|
|
254
271
|
*
|
|
@@ -320,4 +337,4 @@ declare function initUnifiedConfig(options: InitOptions): Promise<InitResult>;
|
|
|
320
337
|
declare function hasUnifiedConfig(rootDir: string): Promise<boolean>;
|
|
321
338
|
declare function generateDefaultConfig(tools?: ToolId[], versionControl?: Record<ToolId, boolean>): Config;
|
|
322
339
|
|
|
323
|
-
export { CONFIG_DIRS, CONFIG_FILES, type ChangeResult, type Config, FileNotFoundError, type InitOptions, type InitResult, LnaiError, type MarkdownFile, type MarkdownFrontmatter, type McpServer, type OutputFile, ParseError, type PermissionLevel, type Permissions, type Plugin, PluginError, type RuleFrontmatter, type Settings, type SkillFrontmatter, type SkippedFeatureDetail, type SyncOptions, type SyncResult, TOOL_IDS, TOOL_OUTPUT_DIRS, type ToolConfig, type ToolId, UNIFIED_DIR, type UnifiedState, ValidationError, type ValidationErrorDetail, type ValidationResult, type ValidationWarningDetail, WriteError, type WriterOptions, claudeCodePlugin, computeHash, configSchema, generateDefaultConfig, hasUnifiedConfig, initUnifiedConfig, mcpServerSchema, opencodePlugin, parseFrontmatter, parseUnifiedConfig, permissionsSchema, pluginRegistry, ruleFrontmatterSchema, runSyncPipeline, settingsSchema, skillFrontmatterSchema, toolConfigSchema, toolIdSchema, updateGitignore, validateConfig, validateSettings, validateUnifiedState, writeFiles };
|
|
340
|
+
export { CONFIG_DIRS, CONFIG_FILES, type ChangeResult, type Config, FileNotFoundError, type InitOptions, type InitResult, LnaiError, type MarkdownFile, type MarkdownFrontmatter, type McpServer, type OutputFile, ParseError, type PermissionLevel, type Permissions, type Plugin, PluginError, type RuleFrontmatter, type Settings, type SkillFrontmatter, type SkippedFeatureDetail, type SyncOptions, type SyncResult, TOOL_IDS, TOOL_OUTPUT_DIRS, type ToolConfig, type ToolId, UNIFIED_DIR, type UnifiedState, ValidationError, type ValidationErrorDetail, type ValidationResult, type ValidationWarningDetail, WriteError, type WriterOptions, claudeCodePlugin, codexPlugin, computeHash, configSchema, generateDefaultConfig, hasUnifiedConfig, initUnifiedConfig, mcpServerSchema, opencodePlugin, parseFrontmatter, parseUnifiedConfig, permissionsSchema, pluginRegistry, ruleFrontmatterSchema, runSyncPipeline, settingsSchema, skillFrontmatterSchema, toolConfigSchema, toolIdSchema, updateGitignore, validateConfig, validateSettings, validateUnifiedState, writeFiles };
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,8 @@ var TOOL_IDS = [
|
|
|
12
12
|
"cursor",
|
|
13
13
|
"copilot",
|
|
14
14
|
"windsurf",
|
|
15
|
-
"gemini"
|
|
15
|
+
"gemini",
|
|
16
|
+
"codex"
|
|
16
17
|
];
|
|
17
18
|
var CONFIG_FILES = {
|
|
18
19
|
config: "config.json",
|
|
@@ -30,7 +31,8 @@ var TOOL_OUTPUT_DIRS = {
|
|
|
30
31
|
cursor: ".cursor",
|
|
31
32
|
copilot: ".github",
|
|
32
33
|
windsurf: ".windsurf",
|
|
33
|
-
gemini: ".gemini"
|
|
34
|
+
gemini: ".gemini",
|
|
35
|
+
codex: ".codex"
|
|
34
36
|
};
|
|
35
37
|
var OVERRIDE_DIRS = {
|
|
36
38
|
claudeCode: ".claude",
|
|
@@ -38,7 +40,8 @@ var OVERRIDE_DIRS = {
|
|
|
38
40
|
cursor: ".cursor",
|
|
39
41
|
copilot: ".copilot",
|
|
40
42
|
windsurf: ".windsurf",
|
|
41
|
-
gemini: ".gemini"
|
|
43
|
+
gemini: ".gemini",
|
|
44
|
+
codex: ".codex"
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
// src/errors.ts
|
|
@@ -124,7 +127,8 @@ var toolIdSchema = z.enum([
|
|
|
124
127
|
"cursor",
|
|
125
128
|
"copilot",
|
|
126
129
|
"windsurf",
|
|
127
|
-
"gemini"
|
|
130
|
+
"gemini",
|
|
131
|
+
"codex"
|
|
128
132
|
]);
|
|
129
133
|
var settingsSchema = z.object({
|
|
130
134
|
permissions: permissionsSchema.optional(),
|
|
@@ -137,7 +141,8 @@ var configSchema = z.object({
|
|
|
137
141
|
cursor: toolConfigSchema,
|
|
138
142
|
copilot: toolConfigSchema,
|
|
139
143
|
windsurf: toolConfigSchema,
|
|
140
|
-
gemini: toolConfigSchema
|
|
144
|
+
gemini: toolConfigSchema,
|
|
145
|
+
codex: toolConfigSchema
|
|
141
146
|
}).partial().optional()
|
|
142
147
|
});
|
|
143
148
|
var skillFrontmatterSchema = z.object({
|
|
@@ -501,6 +506,183 @@ var claudeCodePlugin = {
|
|
|
501
506
|
return { valid: true, errors: [], warnings, skipped: [] };
|
|
502
507
|
}
|
|
503
508
|
};
|
|
509
|
+
function getDirFromGlob(glob) {
|
|
510
|
+
const cleanPath = glob.replace(/(\*\*|\*|\{.*,.*\}).*$/, "");
|
|
511
|
+
const dir = cleanPath.replace(/\/$/, "");
|
|
512
|
+
if (dir === glob) {
|
|
513
|
+
const dirname4 = path.dirname(dir);
|
|
514
|
+
return dirname4 === "." && !dir.includes("/") ? "." : dirname4;
|
|
515
|
+
}
|
|
516
|
+
if (!dir) {
|
|
517
|
+
return ".";
|
|
518
|
+
}
|
|
519
|
+
return dir;
|
|
520
|
+
}
|
|
521
|
+
function groupRulesByDirectory(rules) {
|
|
522
|
+
const rulesMap = /* @__PURE__ */ new Map();
|
|
523
|
+
const addedRules = /* @__PURE__ */ new Map();
|
|
524
|
+
for (const rule of rules) {
|
|
525
|
+
for (const pathGlob of rule.frontmatter.paths) {
|
|
526
|
+
const dir = getDirFromGlob(pathGlob);
|
|
527
|
+
if (!rulesMap.has(dir)) {
|
|
528
|
+
rulesMap.set(dir, []);
|
|
529
|
+
addedRules.set(dir, /* @__PURE__ */ new Set());
|
|
530
|
+
}
|
|
531
|
+
if (addedRules.get(dir)?.has(rule.path)) {
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
addedRules.get(dir)?.add(rule.path);
|
|
535
|
+
const content = `## ${rule.path}
|
|
536
|
+
|
|
537
|
+
${rule.content}
|
|
538
|
+
`;
|
|
539
|
+
rulesMap.get(dir)?.push(content);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return rulesMap;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// src/plugins/codex/index.ts
|
|
546
|
+
var codexPlugin = {
|
|
547
|
+
id: "codex",
|
|
548
|
+
name: "Codex",
|
|
549
|
+
async detect(_rootDir) {
|
|
550
|
+
return false;
|
|
551
|
+
},
|
|
552
|
+
async import(_rootDir) {
|
|
553
|
+
return null;
|
|
554
|
+
},
|
|
555
|
+
async export(state, rootDir) {
|
|
556
|
+
const files = [];
|
|
557
|
+
const outputDir = TOOL_OUTPUT_DIRS.codex;
|
|
558
|
+
if (state.agents) {
|
|
559
|
+
files.push({
|
|
560
|
+
path: "AGENTS.md",
|
|
561
|
+
type: "symlink",
|
|
562
|
+
target: `${UNIFIED_DIR}/AGENTS.md`
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
const rulesMap = groupRulesByDirectory(state.rules);
|
|
566
|
+
for (const [dir, contents] of rulesMap.entries()) {
|
|
567
|
+
if (dir === ".") {
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
const combinedContent = contents.join("\n---\n\n");
|
|
571
|
+
files.push({
|
|
572
|
+
path: `${dir}/AGENTS.md`,
|
|
573
|
+
type: "text",
|
|
574
|
+
content: combinedContent
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
for (const skill of state.skills) {
|
|
578
|
+
files.push({
|
|
579
|
+
path: `${outputDir}/skills/${skill.path}`,
|
|
580
|
+
type: "symlink",
|
|
581
|
+
target: `../../${UNIFIED_DIR}/skills/${skill.path}`
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
const configToml = buildCodexConfigToml(state.settings?.mcpServers);
|
|
585
|
+
if (configToml) {
|
|
586
|
+
files.push({
|
|
587
|
+
path: `${outputDir}/config.toml`,
|
|
588
|
+
type: "text",
|
|
589
|
+
content: configToml
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
return applyFileOverrides(files, rootDir, "codex");
|
|
593
|
+
},
|
|
594
|
+
validate(state) {
|
|
595
|
+
const warnings = [];
|
|
596
|
+
const skipped = [];
|
|
597
|
+
if (!state.agents) {
|
|
598
|
+
warnings.push({
|
|
599
|
+
path: ["AGENTS.md"],
|
|
600
|
+
message: "No AGENTS.md found - root AGENTS.md will not be created"
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
const rulesMap = groupRulesByDirectory(state.rules);
|
|
604
|
+
if (rulesMap.has(".")) {
|
|
605
|
+
warnings.push({
|
|
606
|
+
path: ["rules"],
|
|
607
|
+
message: "Rules with root globs are not exported - Codex only receives subdirectory AGENTS.md files"
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
const mcpServers = state.settings?.mcpServers;
|
|
611
|
+
if (mcpServers) {
|
|
612
|
+
for (const [name, server] of Object.entries(mcpServers)) {
|
|
613
|
+
if (!server.command && !server.url) {
|
|
614
|
+
warnings.push({
|
|
615
|
+
path: ["settings", "mcpServers", name],
|
|
616
|
+
message: `MCP server "${name}" has no command or url - it will be skipped`
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
if (state.settings?.permissions) {
|
|
622
|
+
const hasPermissions = (state.settings.permissions.allow?.length ?? 0) > 0 || (state.settings.permissions.ask?.length ?? 0) > 0 || (state.settings.permissions.deny?.length ?? 0) > 0;
|
|
623
|
+
if (hasPermissions) {
|
|
624
|
+
skipped.push({
|
|
625
|
+
feature: "permissions",
|
|
626
|
+
reason: "Codex rules are not generated from LNAI permissions"
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return { valid: true, errors: [], warnings, skipped };
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
function buildCodexConfigToml(mcpServers) {
|
|
634
|
+
if (!mcpServers || Object.keys(mcpServers).length === 0) {
|
|
635
|
+
return void 0;
|
|
636
|
+
}
|
|
637
|
+
const lines = [];
|
|
638
|
+
for (const [name, server] of Object.entries(mcpServers)) {
|
|
639
|
+
const hasCommand = !!server.command;
|
|
640
|
+
const hasUrl = !!server.url;
|
|
641
|
+
if (!hasCommand && !hasUrl) {
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
lines.push(`[mcp_servers.${formatTomlKey(name)}]`);
|
|
645
|
+
if (server.command) {
|
|
646
|
+
lines.push(`command = ${formatTomlString(server.command)}`);
|
|
647
|
+
if (server.args && server.args.length > 0) {
|
|
648
|
+
lines.push(`args = ${formatTomlArray(server.args)}`);
|
|
649
|
+
}
|
|
650
|
+
if (server.env && Object.keys(server.env).length > 0) {
|
|
651
|
+
lines.push(`env = ${formatTomlInlineTable(server.env)}`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
if (server.url) {
|
|
655
|
+
lines.push(`url = ${formatTomlString(server.url)}`);
|
|
656
|
+
if (server.headers && Object.keys(server.headers).length > 0) {
|
|
657
|
+
lines.push(`http_headers = ${formatTomlInlineTable(server.headers)}`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
lines.push("");
|
|
661
|
+
}
|
|
662
|
+
if (lines.length === 0) {
|
|
663
|
+
return void 0;
|
|
664
|
+
}
|
|
665
|
+
return `${lines.join("\n").trimEnd()}
|
|
666
|
+
`;
|
|
667
|
+
}
|
|
668
|
+
function formatTomlString(value) {
|
|
669
|
+
return JSON.stringify(value);
|
|
670
|
+
}
|
|
671
|
+
function formatTomlArray(values) {
|
|
672
|
+
return `[${values.map(formatTomlString).join(", ")}]`;
|
|
673
|
+
}
|
|
674
|
+
function formatTomlKey(key) {
|
|
675
|
+
if (/^[A-Za-z0-9_-]+$/.test(key)) {
|
|
676
|
+
return key;
|
|
677
|
+
}
|
|
678
|
+
return JSON.stringify(key);
|
|
679
|
+
}
|
|
680
|
+
function formatTomlInlineTable(values) {
|
|
681
|
+
const entries = Object.entries(values).map(
|
|
682
|
+
([key, value]) => `${formatTomlKey(key)} = ${formatTomlString(value)}`
|
|
683
|
+
);
|
|
684
|
+
return `{ ${entries.join(", ")} }`;
|
|
685
|
+
}
|
|
504
686
|
|
|
505
687
|
// src/utils/transforms.ts
|
|
506
688
|
var ENV_VAR_PATTERN = /\$\{([^}:]+)(:-[^}]*)?\}/g;
|
|
@@ -907,18 +1089,6 @@ function buildCliContent(permissions) {
|
|
|
907
1089
|
}
|
|
908
1090
|
return { permissions: permissionsResult.permissions };
|
|
909
1091
|
}
|
|
910
|
-
function getDirFromGlob(glob) {
|
|
911
|
-
const cleanPath = glob.replace(/(\*\*|\*|\{.*,.*\}).*$/, "");
|
|
912
|
-
const dir = cleanPath.replace(/\/$/, "");
|
|
913
|
-
if (dir === glob) {
|
|
914
|
-
const dirname4 = path.dirname(dir);
|
|
915
|
-
return dirname4 === "." && !dir.includes("/") ? "." : dirname4;
|
|
916
|
-
}
|
|
917
|
-
if (!dir) {
|
|
918
|
-
return ".";
|
|
919
|
-
}
|
|
920
|
-
return dir;
|
|
921
|
-
}
|
|
922
1092
|
|
|
923
1093
|
// src/plugins/gemini/transforms.ts
|
|
924
1094
|
function transformMcpToGemini(mcpServers) {
|
|
@@ -941,23 +1111,6 @@ function transformMcpToGemini(mcpServers) {
|
|
|
941
1111
|
}
|
|
942
1112
|
return Object.keys(geminiMcp).length > 0 ? geminiMcp : void 0;
|
|
943
1113
|
}
|
|
944
|
-
function groupRulesByDirectory(rules) {
|
|
945
|
-
const rulesMap = /* @__PURE__ */ new Map();
|
|
946
|
-
for (const rule of rules) {
|
|
947
|
-
for (const pathGlob of rule.frontmatter.paths) {
|
|
948
|
-
const dir = getDirFromGlob(pathGlob);
|
|
949
|
-
if (!rulesMap.has(dir)) {
|
|
950
|
-
rulesMap.set(dir, []);
|
|
951
|
-
}
|
|
952
|
-
const content = `## ${rule.path}
|
|
953
|
-
|
|
954
|
-
${rule.content}
|
|
955
|
-
`;
|
|
956
|
-
rulesMap.get(dir)?.push(content);
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
return rulesMap;
|
|
960
|
-
}
|
|
961
1114
|
|
|
962
1115
|
// src/plugins/gemini/index.ts
|
|
963
1116
|
var geminiPlugin = {
|
|
@@ -1304,6 +1457,7 @@ var windsurfPlugin = {
|
|
|
1304
1457
|
pluginRegistry.register(claudeCodePlugin);
|
|
1305
1458
|
pluginRegistry.register(copilotPlugin);
|
|
1306
1459
|
pluginRegistry.register(cursorPlugin);
|
|
1460
|
+
pluginRegistry.register(codexPlugin);
|
|
1307
1461
|
pluginRegistry.register(opencodePlugin);
|
|
1308
1462
|
pluginRegistry.register(windsurfPlugin);
|
|
1309
1463
|
pluginRegistry.register(geminiPlugin);
|
|
@@ -1570,4 +1724,4 @@ function generateDefaultConfig(tools, versionControl) {
|
|
|
1570
1724
|
return { tools: toolsConfig };
|
|
1571
1725
|
}
|
|
1572
1726
|
|
|
1573
|
-
export { CONFIG_DIRS, CONFIG_FILES, FileNotFoundError, LnaiError, ParseError, PluginError, TOOL_IDS, TOOL_OUTPUT_DIRS, UNIFIED_DIR, ValidationError, WriteError, claudeCodePlugin, computeHash, configSchema, generateDefaultConfig, hasUnifiedConfig, initUnifiedConfig, mcpServerSchema, opencodePlugin, parseFrontmatter, parseUnifiedConfig, permissionsSchema, pluginRegistry, ruleFrontmatterSchema, runSyncPipeline, settingsSchema, skillFrontmatterSchema, toolConfigSchema, toolIdSchema, updateGitignore, validateConfig, validateSettings, validateUnifiedState, writeFiles };
|
|
1727
|
+
export { CONFIG_DIRS, CONFIG_FILES, FileNotFoundError, LnaiError, ParseError, PluginError, TOOL_IDS, TOOL_OUTPUT_DIRS, UNIFIED_DIR, ValidationError, WriteError, claudeCodePlugin, codexPlugin, computeHash, configSchema, generateDefaultConfig, hasUnifiedConfig, initUnifiedConfig, mcpServerSchema, opencodePlugin, parseFrontmatter, parseUnifiedConfig, permissionsSchema, pluginRegistry, ruleFrontmatterSchema, runSyncPipeline, settingsSchema, skillFrontmatterSchema, toolConfigSchema, toolIdSchema, updateGitignore, validateConfig, validateSettings, validateUnifiedState, writeFiles };
|