@lnai/core 0.4.1 → 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 +24 -2
- package/dist/index.js +299 -12
- package/package.json +3 -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"];
|
|
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";
|
|
@@ -68,6 +68,8 @@ declare const toolIdSchema: z.ZodEnum<{
|
|
|
68
68
|
cursor: "cursor";
|
|
69
69
|
copilot: "copilot";
|
|
70
70
|
windsurf: "windsurf";
|
|
71
|
+
gemini: "gemini";
|
|
72
|
+
codex: "codex";
|
|
71
73
|
}>;
|
|
72
74
|
/** Settings configuration (Claude format as source of truth) */
|
|
73
75
|
declare const settingsSchema: z.ZodObject<{
|
|
@@ -111,6 +113,14 @@ declare const configSchema: z.ZodObject<{
|
|
|
111
113
|
enabled: z.ZodBoolean;
|
|
112
114
|
versionControl: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
113
115
|
}, z.core.$strip>>;
|
|
116
|
+
gemini: z.ZodOptional<z.ZodObject<{
|
|
117
|
+
enabled: z.ZodBoolean;
|
|
118
|
+
versionControl: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
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>>;
|
|
114
124
|
}, z.core.$strip>>;
|
|
115
125
|
}, z.core.$strip>;
|
|
116
126
|
/** Skill frontmatter (name and description required) */
|
|
@@ -244,6 +254,18 @@ interface Plugin {
|
|
|
244
254
|
*/
|
|
245
255
|
declare const claudeCodePlugin: Plugin;
|
|
246
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
|
+
|
|
247
269
|
/**
|
|
248
270
|
* OpenCode plugin for exporting to opencode.json format
|
|
249
271
|
*
|
|
@@ -315,4 +337,4 @@ declare function initUnifiedConfig(options: InitOptions): Promise<InitResult>;
|
|
|
315
337
|
declare function hasUnifiedConfig(rootDir: string): Promise<boolean>;
|
|
316
338
|
declare function generateDefaultConfig(tools?: ToolId[], versionControl?: Record<ToolId, boolean>): Config;
|
|
317
339
|
|
|
318
|
-
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
|
@@ -11,7 +11,9 @@ var TOOL_IDS = [
|
|
|
11
11
|
"opencode",
|
|
12
12
|
"cursor",
|
|
13
13
|
"copilot",
|
|
14
|
-
"windsurf"
|
|
14
|
+
"windsurf",
|
|
15
|
+
"gemini",
|
|
16
|
+
"codex"
|
|
15
17
|
];
|
|
16
18
|
var CONFIG_FILES = {
|
|
17
19
|
config: "config.json",
|
|
@@ -28,14 +30,18 @@ var TOOL_OUTPUT_DIRS = {
|
|
|
28
30
|
opencode: ".opencode",
|
|
29
31
|
cursor: ".cursor",
|
|
30
32
|
copilot: ".github",
|
|
31
|
-
windsurf: ".windsurf"
|
|
33
|
+
windsurf: ".windsurf",
|
|
34
|
+
gemini: ".gemini",
|
|
35
|
+
codex: ".codex"
|
|
32
36
|
};
|
|
33
37
|
var OVERRIDE_DIRS = {
|
|
34
38
|
claudeCode: ".claude",
|
|
35
39
|
opencode: ".opencode",
|
|
36
40
|
cursor: ".cursor",
|
|
37
41
|
copilot: ".copilot",
|
|
38
|
-
windsurf: ".windsurf"
|
|
42
|
+
windsurf: ".windsurf",
|
|
43
|
+
gemini: ".gemini",
|
|
44
|
+
codex: ".codex"
|
|
39
45
|
};
|
|
40
46
|
|
|
41
47
|
// src/errors.ts
|
|
@@ -61,10 +67,10 @@ var ParseError = class extends LnaiError {
|
|
|
61
67
|
var ValidationError = class extends LnaiError {
|
|
62
68
|
path;
|
|
63
69
|
value;
|
|
64
|
-
constructor(message,
|
|
70
|
+
constructor(message, path6, value) {
|
|
65
71
|
super(message, "VALIDATION_ERROR");
|
|
66
72
|
this.name = "ValidationError";
|
|
67
|
-
this.path =
|
|
73
|
+
this.path = path6;
|
|
68
74
|
this.value = value;
|
|
69
75
|
}
|
|
70
76
|
};
|
|
@@ -120,7 +126,9 @@ var toolIdSchema = z.enum([
|
|
|
120
126
|
"opencode",
|
|
121
127
|
"cursor",
|
|
122
128
|
"copilot",
|
|
123
|
-
"windsurf"
|
|
129
|
+
"windsurf",
|
|
130
|
+
"gemini",
|
|
131
|
+
"codex"
|
|
124
132
|
]);
|
|
125
133
|
var settingsSchema = z.object({
|
|
126
134
|
permissions: permissionsSchema.optional(),
|
|
@@ -132,7 +140,9 @@ var configSchema = z.object({
|
|
|
132
140
|
opencode: toolConfigSchema,
|
|
133
141
|
cursor: toolConfigSchema,
|
|
134
142
|
copilot: toolConfigSchema,
|
|
135
|
-
windsurf: toolConfigSchema
|
|
143
|
+
windsurf: toolConfigSchema,
|
|
144
|
+
gemini: toolConfigSchema,
|
|
145
|
+
codex: toolConfigSchema
|
|
136
146
|
}).partial().optional()
|
|
137
147
|
});
|
|
138
148
|
var skillFrontmatterSchema = z.object({
|
|
@@ -496,6 +506,183 @@ var claudeCodePlugin = {
|
|
|
496
506
|
return { valid: true, errors: [], warnings, skipped: [] };
|
|
497
507
|
}
|
|
498
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
|
+
}
|
|
499
686
|
|
|
500
687
|
// src/utils/transforms.ts
|
|
501
688
|
var ENV_VAR_PATTERN = /\$\{([^}:]+)(:-[^}]*)?\}/g;
|
|
@@ -652,6 +839,7 @@ var copilotPlugin = {
|
|
|
652
839
|
},
|
|
653
840
|
validate(state) {
|
|
654
841
|
const warnings = [];
|
|
842
|
+
const skipped = [];
|
|
655
843
|
if (!state.agents) {
|
|
656
844
|
warnings.push({
|
|
657
845
|
path: ["AGENTS.md"],
|
|
@@ -661,9 +849,9 @@ var copilotPlugin = {
|
|
|
661
849
|
const permissions = state.settings?.permissions;
|
|
662
850
|
const hasPermissions = permissions && (permissions.allow && permissions.allow.length > 0 || permissions.ask && permissions.ask.length > 0 || permissions.deny && permissions.deny.length > 0);
|
|
663
851
|
if (hasPermissions) {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
852
|
+
skipped.push({
|
|
853
|
+
feature: "permissions",
|
|
854
|
+
reason: "GitHub Copilot does not support declarative permissions"
|
|
667
855
|
});
|
|
668
856
|
}
|
|
669
857
|
const mcpServers = state.settings?.mcpServers;
|
|
@@ -684,7 +872,7 @@ var copilotPlugin = {
|
|
|
684
872
|
}
|
|
685
873
|
}
|
|
686
874
|
}
|
|
687
|
-
return { valid: true, errors: [], warnings, skipped
|
|
875
|
+
return { valid: true, errors: [], warnings, skipped };
|
|
688
876
|
}
|
|
689
877
|
};
|
|
690
878
|
|
|
@@ -902,6 +1090,103 @@ function buildCliContent(permissions) {
|
|
|
902
1090
|
return { permissions: permissionsResult.permissions };
|
|
903
1091
|
}
|
|
904
1092
|
|
|
1093
|
+
// src/plugins/gemini/transforms.ts
|
|
1094
|
+
function transformMcpToGemini(mcpServers) {
|
|
1095
|
+
if (!mcpServers) {
|
|
1096
|
+
return void 0;
|
|
1097
|
+
}
|
|
1098
|
+
const geminiMcp = {};
|
|
1099
|
+
for (const [name, config] of Object.entries(mcpServers)) {
|
|
1100
|
+
if (!config.command && !config.url && !config.type) {
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
geminiMcp[name] = {
|
|
1104
|
+
command: config.command,
|
|
1105
|
+
args: config.args,
|
|
1106
|
+
env: config.env
|
|
1107
|
+
};
|
|
1108
|
+
if (config.url) {
|
|
1109
|
+
geminiMcp[name].httpUrl = config.url;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
return Object.keys(geminiMcp).length > 0 ? geminiMcp : void 0;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// src/plugins/gemini/index.ts
|
|
1116
|
+
var geminiPlugin = {
|
|
1117
|
+
id: "gemini",
|
|
1118
|
+
name: "Gemini CLI",
|
|
1119
|
+
async detect(_rootDir) {
|
|
1120
|
+
return false;
|
|
1121
|
+
},
|
|
1122
|
+
async import(_rootDir) {
|
|
1123
|
+
return null;
|
|
1124
|
+
},
|
|
1125
|
+
async export(state, rootDir) {
|
|
1126
|
+
const files = [];
|
|
1127
|
+
const outputDir = TOOL_OUTPUT_DIRS.gemini;
|
|
1128
|
+
if (state.agents) {
|
|
1129
|
+
files.push({
|
|
1130
|
+
path: `${outputDir}/GEMINI.md`,
|
|
1131
|
+
type: "symlink",
|
|
1132
|
+
target: `../${UNIFIED_DIR}/AGENTS.md`
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
const rulesMap = groupRulesByDirectory(state.rules);
|
|
1136
|
+
for (const [dir, contents] of rulesMap.entries()) {
|
|
1137
|
+
const combinedContent = contents.join("\n---\n\n");
|
|
1138
|
+
const filePath = dir === "." ? "GEMINI.md" : `${dir}/GEMINI.md`;
|
|
1139
|
+
files.push({
|
|
1140
|
+
path: filePath,
|
|
1141
|
+
type: "text",
|
|
1142
|
+
content: combinedContent
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
for (const skill of state.skills) {
|
|
1146
|
+
files.push({
|
|
1147
|
+
path: `${outputDir}/skills/${skill.path}`,
|
|
1148
|
+
type: "symlink",
|
|
1149
|
+
target: `../../${UNIFIED_DIR}/skills/${skill.path}`
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
const mcpServers = transformMcpToGemini(state.settings?.mcpServers);
|
|
1153
|
+
if (mcpServers) {
|
|
1154
|
+
files.push({
|
|
1155
|
+
path: `${outputDir}/settings.json`,
|
|
1156
|
+
type: "json",
|
|
1157
|
+
content: { mcpServers }
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
return applyFileOverrides(files, rootDir, "gemini");
|
|
1161
|
+
},
|
|
1162
|
+
validate(state) {
|
|
1163
|
+
const warnings = [];
|
|
1164
|
+
const skipped = [];
|
|
1165
|
+
if (!state.agents) {
|
|
1166
|
+
warnings.push({
|
|
1167
|
+
path: ["AGENTS.md"],
|
|
1168
|
+
message: "No AGENTS.md found - GEMINI.md will not be created"
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
if (state.settings?.permissions) {
|
|
1172
|
+
const hasPermissions = (state.settings.permissions.allow?.length ?? 0) > 0 || (state.settings.permissions.ask?.length ?? 0) > 0 || (state.settings.permissions.deny?.length ?? 0) > 0;
|
|
1173
|
+
if (hasPermissions) {
|
|
1174
|
+
skipped.push({
|
|
1175
|
+
feature: "permissions",
|
|
1176
|
+
reason: "Gemini CLI does not support declarative permissions - permissions must be granted interactively"
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
if (state.rules.length > 0) {
|
|
1181
|
+
warnings.push({
|
|
1182
|
+
path: ["rules"],
|
|
1183
|
+
message: "Rules will be generated into GEMINI.md files in their respective subdirectories (e.g. apps/cli/GEMINI.md)."
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
return { valid: true, errors: [], warnings, skipped };
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
|
|
905
1190
|
// src/plugins/opencode/transforms.ts
|
|
906
1191
|
function transformMcpToOpenCode(servers) {
|
|
907
1192
|
if (!servers || Object.keys(servers).length === 0) {
|
|
@@ -1172,8 +1457,10 @@ var windsurfPlugin = {
|
|
|
1172
1457
|
pluginRegistry.register(claudeCodePlugin);
|
|
1173
1458
|
pluginRegistry.register(copilotPlugin);
|
|
1174
1459
|
pluginRegistry.register(cursorPlugin);
|
|
1460
|
+
pluginRegistry.register(codexPlugin);
|
|
1175
1461
|
pluginRegistry.register(opencodePlugin);
|
|
1176
1462
|
pluginRegistry.register(windsurfPlugin);
|
|
1463
|
+
pluginRegistry.register(geminiPlugin);
|
|
1177
1464
|
function computeHash(content) {
|
|
1178
1465
|
return crypto.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
1179
1466
|
}
|
|
@@ -1437,4 +1724,4 @@ function generateDefaultConfig(tools, versionControl) {
|
|
|
1437
1724
|
return { tools: toolsConfig };
|
|
1438
1725
|
}
|
|
1439
1726
|
|
|
1440
|
-
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lnai/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Core library for LNAI - unified AI config management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"configuration",
|
|
21
21
|
"claude",
|
|
22
22
|
"cursor",
|
|
23
|
+
"gemini",
|
|
24
|
+
"antigravity",
|
|
23
25
|
"opencode",
|
|
24
26
|
"copilot",
|
|
25
27
|
"github-copilot",
|