fraim-framework 2.0.170 → 2.0.173
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/src/ai-hub/hosts.js +227 -6
- package/dist/src/ai-hub/server.js +1014 -35
- package/dist/src/cli/commands/add-ide.js +4 -2
- package/dist/src/cli/commands/cleanup-artifacts.js +38 -0
- package/dist/src/cli/commands/init-project.js +12 -5
- package/dist/src/cli/commands/setup.js +1 -1
- package/dist/src/cli/commands/sync.js +74 -7
- package/dist/src/cli/doctor/checks/ide-config-checks.js +2 -2
- package/dist/src/cli/fraim.js +2 -0
- package/dist/src/cli/mcp/ide-formats.js +10 -2
- package/dist/src/cli/setup/auto-mcp-setup.js +4 -2
- package/dist/src/cli/setup/ide-detector.js +26 -0
- package/dist/src/cli/setup/ide-global-integration.js +6 -2
- package/dist/src/cli/setup/ide-invocation-surfaces.js +12 -4
- package/dist/src/cli/setup/mcp-config-generator.js +12 -1
- package/dist/src/cli/utils/agent-adapters.js +42 -17
- package/dist/src/cli/utils/fraim-gitignore.js +13 -0
- package/dist/src/cli/utils/remote-sync.js +129 -53
- package/dist/src/cli/utils/user-config.js +12 -0
- package/dist/src/config/ai-manager-hiring.js +121 -0
- package/dist/src/config/compat.js +16 -0
- package/dist/src/config/feature-flags.js +25 -0
- package/dist/src/config/persona-capability-bundles.js +273 -0
- package/dist/src/config/persona-hiring.js +270 -0
- package/dist/src/config/portfolio-slug-overrides.js +17 -0
- package/dist/src/config/pricing.js +37 -0
- package/dist/src/config/stripe.js +43 -0
- package/dist/src/core/fraim-config-schema.generated.js +8 -2
- package/dist/src/core/utils/local-registry-resolver.js +26 -0
- package/dist/src/core/utils/project-fraim-paths.js +89 -2
- package/dist/src/first-run/session-service.js +12 -3
- package/dist/src/local-mcp-server/artifact-retention-cleanup.js +255 -0
- package/dist/src/local-mcp-server/learning-context-builder.js +41 -81
- package/dist/src/local-mcp-server/stdio-server.js +42 -7
- package/package.json +5 -1
- package/public/ai-hub/index.html +205 -89
- package/public/ai-hub/review.css +12 -0
- package/public/ai-hub/script.js +1734 -253
- package/public/ai-hub/styles.css +473 -6
|
@@ -51,6 +51,7 @@ const mcp_server_registry_1 = require("../mcp/mcp-server-registry");
|
|
|
51
51
|
const get_provider_client_1 = require("../api/get-provider-client");
|
|
52
52
|
const provider_prompts_1 = require("../setup/provider-prompts");
|
|
53
53
|
const provider_registry_1 = require("../providers/provider-registry");
|
|
54
|
+
const user_config_1 = require("../utils/user-config");
|
|
54
55
|
const loadGlobalConfig = async () => {
|
|
55
56
|
const globalConfigPath = path_1.default.join((0, script_sync_utils_1.getUserFraimDir)(), 'config.json');
|
|
56
57
|
if (!fs_1.default.existsSync(globalConfigPath)) {
|
|
@@ -384,7 +385,7 @@ const runAddIDE = async (options) => {
|
|
|
384
385
|
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
385
386
|
if (detectedIDEs.length === 0) {
|
|
386
387
|
console.log(chalk_1.default.yellow('⚠️ No supported IDEs detected on your system.'));
|
|
387
|
-
console.log(chalk_1.default.gray('Supported IDEs: Claude, Claude Code, Antigravity, Gemini CLI, Kiro, Cursor, VSCode, Codex, Windsurf'));
|
|
388
|
+
console.log(chalk_1.default.gray('Supported IDEs: Claude, Claude Code, Antigravity, Gemini CLI, Kiro, Cursor, VSCode, Codex, Grok, Windsurf'));
|
|
388
389
|
console.log(chalk_1.default.blue('\n💡 Install an IDE and run this command again.'));
|
|
389
390
|
return;
|
|
390
391
|
}
|
|
@@ -410,6 +411,7 @@ const runAddIDE = async (options) => {
|
|
|
410
411
|
try {
|
|
411
412
|
await configureIDEMCP(ide, globalConfig.fraimKey, platformTokens, globalConfig.providerConfigs);
|
|
412
413
|
results.successful.push(ide.name);
|
|
414
|
+
(0, user_config_1.addInstalledIde)((0, ide_detector_1.getAdapterConfigType)(ide));
|
|
413
415
|
}
|
|
414
416
|
catch (error) {
|
|
415
417
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
@@ -446,7 +448,7 @@ const runAddIDE = async (options) => {
|
|
|
446
448
|
exports.runAddIDE = runAddIDE;
|
|
447
449
|
exports.addIDECommand = new commander_1.Command('add-ide')
|
|
448
450
|
.description('Add FRAIM configuration to additional IDEs')
|
|
449
|
-
.option('--ide <name>', 'Configure specific IDE (claude, claude-code, claude-desktop, claude-cowork, antigravity, gemini, gemini-cli, kiro, cursor, vscode, codex, windsurf)')
|
|
451
|
+
.option('--ide <name>', 'Configure specific IDE (claude, claude-code, claude-desktop, claude-cowork, antigravity, gemini, gemini-cli, kiro, cursor, vscode, codex, grok, windsurf)')
|
|
450
452
|
.option('--all', 'Configure all detected IDEs')
|
|
451
453
|
.option('--list', 'List all supported IDEs and their detection status')
|
|
452
454
|
.action(exports.runAddIDE);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.cleanupArtifactsCommand = void 0;
|
|
7
|
+
exports.runCleanupArtifactsCommand = runCleanupArtifactsCommand;
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const artifact_retention_cleanup_1 = require("../../local-mcp-server/artifact-retention-cleanup");
|
|
11
|
+
function runCleanupArtifactsCommand(options) {
|
|
12
|
+
const activeUserEmail = options.user || process.env.FRAIM_ACTIVE_USER_EMAIL || '';
|
|
13
|
+
if (!activeUserEmail.trim()) {
|
|
14
|
+
throw new Error('Missing active user email. Pass --user <email> or set FRAIM_ACTIVE_USER_EMAIL.');
|
|
15
|
+
}
|
|
16
|
+
const workspaceRoot = node_path_1.default.resolve(options.workspaceRoot || options.root || process.cwd());
|
|
17
|
+
const report = (0, artifact_retention_cleanup_1.runArtifactCleanup)(workspaceRoot, {
|
|
18
|
+
activeUserEmail: activeUserEmail.trim(),
|
|
19
|
+
apply: Boolean(options.apply),
|
|
20
|
+
});
|
|
21
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
22
|
+
}
|
|
23
|
+
exports.cleanupArtifactsCommand = new commander_1.Command('cleanup-artifacts')
|
|
24
|
+
.description('Evaluate and optionally apply artifact retention cleanup for the current FRAIM workspace')
|
|
25
|
+
.option('--user <email>', 'Active user email used only for user-scoped cleanup categories')
|
|
26
|
+
.option('--workspace-root <path>', 'Workspace root containing fraim/config.json')
|
|
27
|
+
.option('--root <path>', 'Alias for --workspace-root')
|
|
28
|
+
.option('--apply', 'Delete eligible files. Without this flag the command performs a dry run.')
|
|
29
|
+
.action((options) => {
|
|
30
|
+
try {
|
|
31
|
+
runCleanupArtifactsCommand(options);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
35
|
+
process.stderr.write(`artifact cleanup failed: ${message}\n`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -18,6 +18,7 @@ const fraim_gitignore_1 = require("../utils/fraim-gitignore");
|
|
|
18
18
|
const agent_adapters_1 = require("../utils/agent-adapters");
|
|
19
19
|
const project_fraim_paths_1 = require("../../core/utils/project-fraim-paths");
|
|
20
20
|
const project_bootstrap_1 = require("../utils/project-bootstrap");
|
|
21
|
+
const user_config_1 = require("../utils/user-config");
|
|
21
22
|
const checkGlobalSetup = () => {
|
|
22
23
|
const fraimUserDir = process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim');
|
|
23
24
|
const globalConfigPath = path_1.default.join(fraimUserDir, 'config.json');
|
|
@@ -178,20 +179,26 @@ const runInitProject = async (options = {}) => {
|
|
|
178
179
|
else {
|
|
179
180
|
result.warnings.push('Sync was skipped for this run.');
|
|
180
181
|
}
|
|
181
|
-
const
|
|
182
|
-
(0, ide_detector_1.detectInstalledIDEs)(
|
|
182
|
+
const detectedIdes = [
|
|
183
|
+
...(0, ide_detector_1.detectInstalledIDEs)(),
|
|
184
|
+
...(0, ide_detector_1.detectInstalledIDEs)('cli-runnable')
|
|
185
|
+
];
|
|
186
|
+
const detectedConfigTypes = [...new Set(detectedIdes.map((ide) => (0, ide_detector_1.getAdapterConfigType)(ide)))];
|
|
187
|
+
if (detectedConfigTypes.length > 0) {
|
|
188
|
+
(0, user_config_1.writeUserFraimConfig)({ installedIdes: detectedConfigTypes });
|
|
189
|
+
}
|
|
190
|
+
const codexAvailable = detectedIdes.some((ide) => ide.configType === 'codex');
|
|
183
191
|
if (codexAvailable) {
|
|
184
192
|
const codexLocalResult = (0, codex_local_config_1.ensureCodexLocalConfig)(projectRoot);
|
|
185
193
|
const status = codexLocalResult.created ? 'Created' : codexLocalResult.updated ? 'Updated' : 'Verified';
|
|
186
194
|
console.log(chalk_1.default.green(`${status} project Codex config at ${codexLocalResult.path}`));
|
|
187
195
|
}
|
|
188
196
|
// Enable token telemetry for Claude Code (user-level, applies to all projects)
|
|
189
|
-
const claudeCodeAvailable =
|
|
190
|
-
(0, ide_detector_1.detectInstalledIDEs)('cli-runnable').some((ide) => ide.configType === 'claude-code');
|
|
197
|
+
const claudeCodeAvailable = detectedIdes.some((ide) => ide.configType === 'claude-code');
|
|
191
198
|
if (claudeCodeAvailable) {
|
|
192
199
|
(0, claude_code_telemetry_1.ensureClaudeCodeTelemetryEnv)();
|
|
193
200
|
}
|
|
194
|
-
const adapterUpdates = (0, agent_adapters_1.ensureAgentAdapterFiles)(projectRoot);
|
|
201
|
+
const adapterUpdates = (0, agent_adapters_1.ensureAgentAdapterFiles)(projectRoot, detectedConfigTypes.length > 0 ? detectedConfigTypes : null);
|
|
195
202
|
if (adapterUpdates.length > 0) {
|
|
196
203
|
console.log(chalk_1.default.green(`Updated FRAIM agent adapter files: ${adapterUpdates.join(', ')}`));
|
|
197
204
|
}
|
|
@@ -677,7 +677,7 @@ const runSetup = async (options) => {
|
|
|
677
677
|
name: 'choice',
|
|
678
678
|
message: 'How would you like to work with your AI employees?',
|
|
679
679
|
choices: [
|
|
680
|
-
{ title: 'In my IDE (Claude Code, Cursor, or another AI tool)', value: 'ide' },
|
|
680
|
+
{ title: 'In my IDE (Claude Code, Cursor, Grok, or another AI tool)', value: 'ide' },
|
|
681
681
|
{ title: 'In FRAIM Hub (browser-based — no terminal needed)', value: 'hub' },
|
|
682
682
|
],
|
|
683
683
|
});
|
|
@@ -47,6 +47,9 @@ const script_sync_utils_1 = require("../utils/script-sync-utils");
|
|
|
47
47
|
const git_utils_1 = require("../../core/utils/git-utils");
|
|
48
48
|
const agent_adapters_1 = require("../utils/agent-adapters");
|
|
49
49
|
const fraim_gitignore_1 = require("../utils/fraim-gitignore");
|
|
50
|
+
const user_config_1 = require("../utils/user-config");
|
|
51
|
+
const ide_detector_1 = require("../setup/ide-detector");
|
|
52
|
+
const remote_sync_1 = require("../utils/remote-sync");
|
|
50
53
|
const project_fraim_paths_1 = require("../../core/utils/project-fraim-paths");
|
|
51
54
|
function resolveExplicitLocalSyncUrl() {
|
|
52
55
|
const candidates = [
|
|
@@ -83,9 +86,10 @@ function loadUserApiKey() {
|
|
|
83
86
|
return undefined;
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
|
-
function writeSyncMetadata(
|
|
87
|
-
|
|
88
|
-
fs_1.default.
|
|
89
|
+
function writeSyncMetadata(mode, remoteUrl) {
|
|
90
|
+
const userDir = (0, project_fraim_paths_1.getUserFraimDirPath)();
|
|
91
|
+
fs_1.default.mkdirSync(userDir, { recursive: true });
|
|
92
|
+
fs_1.default.writeFileSync(path_1.default.join(userDir, '.sync-metadata.json'), JSON.stringify({
|
|
89
93
|
localVersion: (0, version_utils_1.getFraimVersion)(),
|
|
90
94
|
mode,
|
|
91
95
|
remoteUrl,
|
|
@@ -109,6 +113,65 @@ function removeLegacyVersionFromConfig(fraimDir) {
|
|
|
109
113
|
console.warn(chalk_1.default.yellow('Could not remove legacy version from config.json.'));
|
|
110
114
|
}
|
|
111
115
|
}
|
|
116
|
+
function resolveAllowedConfigTypes() {
|
|
117
|
+
const persisted = (0, user_config_1.getInstalledIdes)();
|
|
118
|
+
const liveDetected = [
|
|
119
|
+
...(0, ide_detector_1.detectInstalledIDEs)(),
|
|
120
|
+
...(0, ide_detector_1.detectInstalledIDEs)('cli-runnable')
|
|
121
|
+
].map((ide) => (0, ide_detector_1.getAdapterConfigType)(ide));
|
|
122
|
+
const liveSet = [...new Set(liveDetected)];
|
|
123
|
+
if (!persisted) {
|
|
124
|
+
return liveSet.length > 0 ? liveSet : null;
|
|
125
|
+
}
|
|
126
|
+
const merged = [...new Set([...persisted, ...liveSet])];
|
|
127
|
+
return merged.length > 0 ? merged : null;
|
|
128
|
+
}
|
|
129
|
+
async function cleanupStaleAdapterFiles(projectRoot, allowedConfigTypes) {
|
|
130
|
+
if (!allowedConfigTypes) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
(0, project_fraim_paths_1.assertWorkspaceFraimRoot)(projectRoot);
|
|
134
|
+
const { execFile } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
135
|
+
const { promisify } = await Promise.resolve().then(() => __importStar(require('util')));
|
|
136
|
+
const execFileAsync = promisify(execFile);
|
|
137
|
+
for (const [relPath, configType] of Object.entries((0, agent_adapters_1.getAdapterConfigTypes)())) {
|
|
138
|
+
if (configType === 'standard' || allowedConfigTypes.includes(configType)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const fullPath = path_1.default.join(projectRoot, relPath);
|
|
142
|
+
if (!fs_1.default.existsSync(fullPath)) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const content = fs_1.default.readFileSync(fullPath, 'utf8');
|
|
147
|
+
if (!content.includes(remote_sync_1.SYNCED_CONTENT_BANNER_MARKER)) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
await execFileAsync('git', ['rm', '--cached', relPath], { cwd: projectRoot });
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Not tracked or git unavailable — still clean up from disk and gitignore.
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
(0, fraim_gitignore_1.addToFraimGitignore)(projectRoot, relPath);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// Best-effort.
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
fs_1.default.unlinkSync(fullPath);
|
|
168
|
+
console.log(chalk_1.default.green(`Removed stale FRAIM adapter file: ${relPath}`));
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Best-effort.
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
112
175
|
function failSync(mode, message) {
|
|
113
176
|
if (mode === 'throw') {
|
|
114
177
|
throw new Error(message);
|
|
@@ -222,9 +285,11 @@ const runSync = async (options) => {
|
|
|
222
285
|
if (result.success) {
|
|
223
286
|
console.log(chalk_1.default.green(`Successfully synced ${result.employeeJobsSynced} ai-employee jobs, ${result.managerJobsSynced} ai-manager jobs, ${result.skillsSynced} skills, ${result.rulesSynced} rules, ${result.scriptsSynced} scripts, and ${result.docsSynced} docs from local server`));
|
|
224
287
|
removeLegacyVersionFromConfig(fraimDir);
|
|
225
|
-
writeSyncMetadata(
|
|
288
|
+
writeSyncMetadata('local', localUrl);
|
|
226
289
|
refreshLocalIgnoreConfig();
|
|
227
|
-
const
|
|
290
|
+
const allowedTypes = resolveAllowedConfigTypes();
|
|
291
|
+
await cleanupStaleAdapterFiles(projectRoot, allowedTypes);
|
|
292
|
+
const adapterUpdates = (0, agent_adapters_1.ensureAgentAdapterFiles)(projectRoot, allowedTypes);
|
|
228
293
|
if (adapterUpdates.length > 0) {
|
|
229
294
|
console.log(chalk_1.default.green(`Updated FRAIM agent adapter files: ${adapterUpdates.join(', ')}`));
|
|
230
295
|
}
|
|
@@ -267,9 +332,11 @@ const runSync = async (options) => {
|
|
|
267
332
|
}
|
|
268
333
|
console.log(chalk_1.default.green(`Successfully synced ${result.employeeJobsSynced} ai-employee jobs, ${result.managerJobsSynced} ai-manager jobs, ${result.skillsSynced} skills, ${result.rulesSynced} rules, ${result.scriptsSynced} scripts, and ${result.docsSynced} docs from remote`));
|
|
269
334
|
removeLegacyVersionFromConfig(fraimDir);
|
|
270
|
-
writeSyncMetadata(
|
|
335
|
+
writeSyncMetadata('remote', config.remoteUrl || process.env.FRAIM_REMOTE_URL || 'https://fraim.wellnessatwork.me');
|
|
271
336
|
refreshLocalIgnoreConfig();
|
|
272
|
-
const
|
|
337
|
+
const allowedTypes = resolveAllowedConfigTypes();
|
|
338
|
+
await cleanupStaleAdapterFiles(projectRoot, allowedTypes);
|
|
339
|
+
const adapterUpdates = (0, agent_adapters_1.ensureAgentAdapterFiles)(projectRoot, allowedTypes);
|
|
273
340
|
if (adapterUpdates.length > 0) {
|
|
274
341
|
console.log(chalk_1.default.green(`Updated FRAIM agent adapter files: ${adapterUpdates.join(', ')}`));
|
|
275
342
|
}
|
|
@@ -35,8 +35,8 @@ function checkIDEsDetected() {
|
|
|
35
35
|
return {
|
|
36
36
|
status: 'warning',
|
|
37
37
|
message: 'No IDEs detected',
|
|
38
|
-
suggestion: 'Install Claude Desktop, Cursor, or another supported IDE',
|
|
39
|
-
details: { supportedIDEs: ['Claude Desktop', 'Cursor', 'Windsurf', 'VS Code', 'Zed', 'Codex'] }
|
|
38
|
+
suggestion: 'Install Claude Desktop, Cursor, Grok, or another supported IDE',
|
|
39
|
+
details: { supportedIDEs: ['Claude Desktop', 'Cursor', 'Windsurf', 'VS Code', 'Zed', 'Codex', 'Grok'] }
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
};
|
package/dist/src/cli/fraim.js
CHANGED
|
@@ -55,6 +55,7 @@ const first_run_1 = require("./commands/first-run");
|
|
|
55
55
|
const workspace_config_1 = require("./commands/workspace-config");
|
|
56
56
|
const org_1 = require("./commands/org");
|
|
57
57
|
const manager_1 = require("./commands/manager");
|
|
58
|
+
const cleanup_artifacts_1 = require("./commands/cleanup-artifacts");
|
|
58
59
|
const fs_1 = __importDefault(require("fs"));
|
|
59
60
|
const path_1 = __importDefault(require("path"));
|
|
60
61
|
const program = new commander_1.Command();
|
|
@@ -99,6 +100,7 @@ program.addCommand(first_run_1.firstRunCommand);
|
|
|
99
100
|
program.addCommand(workspace_config_1.workspaceConfigCommand);
|
|
100
101
|
program.addCommand(org_1.orgCommand);
|
|
101
102
|
program.addCommand(manager_1.managerCommand);
|
|
103
|
+
program.addCommand(cleanup_artifacts_1.cleanupArtifactsCommand);
|
|
102
104
|
// Wait for async command initialization before parsing
|
|
103
105
|
(async () => {
|
|
104
106
|
// Import the initialization promise from setup command
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// IDE Format Adapters - transform logical server structure to IDE-specific formats
|
|
3
3
|
// Uses the centralized registry to determine server types
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.IDE_FORMATS = exports.CodexFormat = exports.WindsurfFormat = exports.ClaudeCodeFormat = exports.ClaudeFormat = exports.GeminiCliFormat = exports.VSCodeFormat = exports.KiroFormat = exports.StandardFormat = void 0;
|
|
5
|
+
exports.IDE_FORMATS = exports.GrokFormat = exports.CodexFormat = exports.WindsurfFormat = exports.ClaudeCodeFormat = exports.ClaudeFormat = exports.GeminiCliFormat = exports.VSCodeFormat = exports.KiroFormat = exports.StandardFormat = void 0;
|
|
6
6
|
exports.getIDEFormat = getIDEFormat;
|
|
7
7
|
const mcp_server_registry_1 = require("./mcp-server-registry");
|
|
8
8
|
const provider_registry_1 = require("../providers/provider-registry");
|
|
@@ -252,6 +252,13 @@ class CodexFormat {
|
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
exports.CodexFormat = CodexFormat;
|
|
255
|
+
class GrokFormat extends CodexFormat {
|
|
256
|
+
constructor() {
|
|
257
|
+
super(...arguments);
|
|
258
|
+
this.name = 'grok';
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
exports.GrokFormat = GrokFormat;
|
|
255
262
|
// Format registry
|
|
256
263
|
exports.IDE_FORMATS = {
|
|
257
264
|
standard: new StandardFormat(),
|
|
@@ -261,7 +268,8 @@ exports.IDE_FORMATS = {
|
|
|
261
268
|
claude: new ClaudeFormat(),
|
|
262
269
|
'claude-code': new ClaudeCodeFormat(),
|
|
263
270
|
windsurf: new WindsurfFormat(),
|
|
264
|
-
codex: new CodexFormat()
|
|
271
|
+
codex: new CodexFormat(),
|
|
272
|
+
grok: new GrokFormat()
|
|
265
273
|
};
|
|
266
274
|
function getIDEFormat(configType) {
|
|
267
275
|
const format = exports.IDE_FORMATS[configType];
|
|
@@ -187,7 +187,9 @@ const configureIDEMCP = async (ide, fraimKey, tokenInput, providerConfigs) => {
|
|
|
187
187
|
}
|
|
188
188
|
const newTomlContent = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, tokens, providerConfigs);
|
|
189
189
|
const { getAllMCPServerIds } = await Promise.resolve().then(() => __importStar(require('../mcp/mcp-server-registry')));
|
|
190
|
-
const
|
|
190
|
+
const baseServerIds = getAllMCPServerIds();
|
|
191
|
+
const providerServerIds = Object.keys(tokens).filter(id => tokens[id]);
|
|
192
|
+
const serversToAdd = [...baseServerIds, ...providerServerIds];
|
|
191
193
|
const mergeResult = (0, mcp_config_generator_1.mergeTomlMCPServers)(existingTomlContent, newTomlContent, serversToAdd);
|
|
192
194
|
fs_1.default.writeFileSync(configPath, mergeResult.content);
|
|
193
195
|
mergeResult.addedServers.forEach(server => {
|
|
@@ -254,7 +256,7 @@ const autoConfigureMCP = async (fraimKey, tokenInput, selectedIDEs, providerConf
|
|
|
254
256
|
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
255
257
|
if (detectedIDEs.length === 0 && (!selectedIDEs || selectedIDEs.length === 0)) {
|
|
256
258
|
console.log(chalk_1.default.yellow('⚠️ No supported IDEs detected.'));
|
|
257
|
-
console.log(chalk_1.default.gray('Supported IDEs: Claude, Claude Code, Antigravity, Gemini CLI, Kiro, Cursor, VSCode, Codex, Windsurf'));
|
|
259
|
+
console.log(chalk_1.default.gray('Supported IDEs: Claude, Claude Code, Antigravity, Gemini CLI, Kiro, Cursor, VSCode, Codex, Grok, Windsurf'));
|
|
258
260
|
console.log(chalk_1.default.blue('\n💡 You can install an IDE and run setup again later.'));
|
|
259
261
|
console.log(chalk_1.default.gray(' Or continue with manual MCP configuration.'));
|
|
260
262
|
if (process.env.FRAIM_NON_INTERACTIVE) {
|
|
@@ -4,10 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.expandPath = exports.findIDEByName = exports.getAllSupportedIDEs = exports.detectInstalledIDEs = exports.IDE_CONFIGS = void 0;
|
|
7
|
+
exports.getAdapterConfigType = getAdapterConfigType;
|
|
7
8
|
const fs_1 = __importDefault(require("fs"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
const os_1 = __importDefault(require("os"));
|
|
10
11
|
const child_process_1 = require("child_process");
|
|
12
|
+
/** Returns the configType to use for adapter file filtering. Falls back to configType when adapterConfigType is not set. */
|
|
13
|
+
function getAdapterConfigType(ide) {
|
|
14
|
+
return ide.adapterConfigType ?? ide.configType;
|
|
15
|
+
}
|
|
11
16
|
const expandPath = (filePath) => {
|
|
12
17
|
if (filePath.startsWith('~/')) {
|
|
13
18
|
return path_1.default.join(os_1.default.homedir(), filePath.slice(2));
|
|
@@ -79,6 +84,13 @@ const detectCodexSurface = () => {
|
|
|
79
84
|
];
|
|
80
85
|
return checkMultiplePaths(paths);
|
|
81
86
|
};
|
|
87
|
+
const detectGrokSurface = () => {
|
|
88
|
+
const paths = [
|
|
89
|
+
'~/.grok',
|
|
90
|
+
'~/.grok/config.toml'
|
|
91
|
+
];
|
|
92
|
+
return checkMultiplePaths(paths);
|
|
93
|
+
};
|
|
82
94
|
exports.IDE_CONFIGS = [
|
|
83
95
|
{
|
|
84
96
|
name: 'Claude Code',
|
|
@@ -144,6 +156,7 @@ exports.IDE_CONFIGS = [
|
|
|
144
156
|
configPath: '~/.cursor/mcp.json',
|
|
145
157
|
configFormat: 'json',
|
|
146
158
|
configType: 'kiro',
|
|
159
|
+
adapterConfigType: 'cursor',
|
|
147
160
|
invocationProfile: 'cursor-mention',
|
|
148
161
|
detectMethod: detectCursor,
|
|
149
162
|
alternativePaths: [
|
|
@@ -180,6 +193,17 @@ exports.IDE_CONFIGS = [
|
|
|
180
193
|
detectMethod: detectCodexSurface,
|
|
181
194
|
description: 'Codex AI development environment'
|
|
182
195
|
},
|
|
196
|
+
{
|
|
197
|
+
name: 'Grok',
|
|
198
|
+
configPath: '~/.grok/config.toml',
|
|
199
|
+
configFormat: 'toml',
|
|
200
|
+
configType: 'grok',
|
|
201
|
+
invocationProfile: 'grok-skill',
|
|
202
|
+
detectMethod: detectGrokSurface,
|
|
203
|
+
supportsConfigBootstrap: true,
|
|
204
|
+
aliases: ['grok', 'grok-cli', 'grok cli', 'grok build'],
|
|
205
|
+
description: 'xAI Grok Build CLI local settings'
|
|
206
|
+
},
|
|
183
207
|
{
|
|
184
208
|
name: 'Windsurf',
|
|
185
209
|
configPath: '~/.codeium/windsurf/mcp_config.json',
|
|
@@ -219,6 +243,8 @@ const isDetectedForMode = (ide, mode) => {
|
|
|
219
243
|
return availableByVersionProbe('claude');
|
|
220
244
|
case 'codex':
|
|
221
245
|
return availableByVersionProbe('codex');
|
|
246
|
+
case 'grok':
|
|
247
|
+
return availableByVersionProbe('grok');
|
|
222
248
|
case 'gemini-cli':
|
|
223
249
|
return detectGeminiCli();
|
|
224
250
|
default:
|
|
@@ -35,7 +35,7 @@ function describeOnboardingInvocationSurfaces(installedIDEs) {
|
|
|
35
35
|
return `${ide.name}: onboard this project`;
|
|
36
36
|
if (profile === 'instructions-only')
|
|
37
37
|
return `${ide.name}: "onboard this project"`;
|
|
38
|
-
// claude-slash, vscode-prompt, codex-skill, windsurf-command, kiro-hashtag, gemini-command
|
|
38
|
+
// claude-slash, vscode-prompt, codex-skill, grok-skill, windsurf-command, kiro-hashtag, gemini-command
|
|
39
39
|
return `${ide.name}: /fraim onboard this project`;
|
|
40
40
|
});
|
|
41
41
|
}
|
|
@@ -55,7 +55,7 @@ async function installSlashCommands(homeDir) {
|
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* Install FRAIM invocation artifacts for non-Claude IDEs.
|
|
58
|
-
* Supports: Cursor, Codex, Gemini CLI, Windsurf, Kiro
|
|
58
|
+
* Supports: Cursor, Codex, Grok, Gemini CLI, Windsurf, Kiro
|
|
59
59
|
* Does not overwrite existing files.
|
|
60
60
|
*/
|
|
61
61
|
async function installGlobalRules(homeDir) {
|
|
@@ -68,6 +68,10 @@ async function installGlobalRules(homeDir) {
|
|
|
68
68
|
if (fs_1.default.existsSync(codexDir)) {
|
|
69
69
|
installFileIfMissing(path_1.default.join(codexDir, 'skills', 'fraim', 'SKILL.md'), (0, ide_invocation_surfaces_1.buildCodexSkillContent)(), 'Codex FRAIM skill (~/.codex/skills/fraim/SKILL.md)');
|
|
70
70
|
}
|
|
71
|
+
const grokDir = path_1.default.join(home, '.grok');
|
|
72
|
+
if (fs_1.default.existsSync(grokDir)) {
|
|
73
|
+
installFileIfMissing(path_1.default.join(grokDir, 'skills', 'fraim', 'SKILL.md'), (0, ide_invocation_surfaces_1.buildGrokSkillContent)(), 'Grok FRAIM skill (~/.grok/skills/fraim/SKILL.md)');
|
|
74
|
+
}
|
|
71
75
|
const geminiDir = path_1.default.join(home, '.gemini');
|
|
72
76
|
if (fs_1.default.existsSync(geminiDir)) {
|
|
73
77
|
installFileIfMissing(path_1.default.join(geminiDir, 'commands', 'fraim.toml'), (0, ide_invocation_surfaces_1.buildGeminiCommandContent)(), 'Gemini CLI FRAIM command (~/.gemini/commands/fraim.toml)');
|
|
@@ -7,6 +7,7 @@ exports.buildClaudeCommandShimContent = buildClaudeCommandShimContent;
|
|
|
7
7
|
exports.buildClaudeSlashCommandContent = buildClaudeSlashCommandContent;
|
|
8
8
|
exports.buildCursorMentionRuleContent = buildCursorMentionRuleContent;
|
|
9
9
|
exports.buildCodexSkillContent = buildCodexSkillContent;
|
|
10
|
+
exports.buildGrokSkillContent = buildGrokSkillContent;
|
|
10
11
|
exports.buildWindsurfCommandContent = buildWindsurfCommandContent;
|
|
11
12
|
exports.buildKiroCommandContent = buildKiroCommandContent;
|
|
12
13
|
exports.buildAntigravityCommandContent = buildAntigravityCommandContent;
|
|
@@ -95,13 +96,18 @@ ${buildFraimInvocationBody('generic-tool-discovery')}
|
|
|
95
96
|
`;
|
|
96
97
|
}
|
|
97
98
|
function buildCodexSkillContent() {
|
|
98
|
-
return `# FRAIM
|
|
99
|
-
|
|
99
|
+
return `# FRAIM
|
|
100
|
+
|
|
100
101
|
${buildFraimInvocationBody('codex-tool-search')}`;
|
|
101
102
|
}
|
|
103
|
+
function buildGrokSkillContent() {
|
|
104
|
+
return `# FRAIM
|
|
105
|
+
|
|
106
|
+
${buildFraimInvocationBody('generic-tool-discovery')}`;
|
|
107
|
+
}
|
|
102
108
|
function buildWindsurfCommandContent() {
|
|
103
|
-
return `# FRAIM
|
|
104
|
-
|
|
109
|
+
return `# FRAIM
|
|
110
|
+
|
|
105
111
|
${buildFraimInvocationBody('generic-tool-discovery')}`;
|
|
106
112
|
}
|
|
107
113
|
function buildKiroCommandContent() {
|
|
@@ -139,6 +145,8 @@ function describeInvocationSurface(ideName, invocationProfile) {
|
|
|
139
145
|
return `${ideName}: /fraim via workspace prompt`;
|
|
140
146
|
case 'codex-skill':
|
|
141
147
|
return `${ideName}: /fraim, $fraim`;
|
|
148
|
+
case 'grok-skill':
|
|
149
|
+
return `${ideName}: /fraim`;
|
|
142
150
|
case 'windsurf-command':
|
|
143
151
|
return `${ideName}: /fraim`;
|
|
144
152
|
case 'kiro-hashtag':
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateMCPConfig = exports.generateWindsurfMCPServers = exports.generateGeminiCliMCPServers = exports.generateVSCodeMCPServers = exports.generateCodexMCPServers = exports.generateKiroMCPServers = exports.generateClaudeCodeMCPServers = exports.generateClaudeMCPServers = exports.generateStandardMCPServers = exports.mergeTomlMCPServers = exports.extractTomlMcpServerBlock = void 0;
|
|
3
|
+
exports.generateMCPConfig = exports.generateWindsurfMCPServers = exports.generateGeminiCliMCPServers = exports.generateVSCodeMCPServers = exports.generateGrokMCPServers = exports.generateCodexMCPServers = exports.generateKiroMCPServers = exports.generateClaudeCodeMCPServers = exports.generateClaudeMCPServers = exports.generateStandardMCPServers = exports.mergeTomlMCPServers = exports.extractTomlMcpServerBlock = void 0;
|
|
4
4
|
const mcp_server_builder_1 = require("../mcp/mcp-server-builder");
|
|
5
5
|
const ide_formats_1 = require("../mcp/ide-formats");
|
|
6
6
|
const normalizeTokens = (tokenInput) => {
|
|
@@ -151,6 +151,15 @@ const generateCodexMCPServers = async (fraimKey, tokenInput, providerConfigs) =>
|
|
|
151
151
|
return format.transform(builder.getServers());
|
|
152
152
|
};
|
|
153
153
|
exports.generateCodexMCPServers = generateCodexMCPServers;
|
|
154
|
+
const generateGrokMCPServers = async (fraimKey, tokenInput, providerConfigs) => {
|
|
155
|
+
const tokens = normalizeTokens(tokenInput);
|
|
156
|
+
const builder = new mcp_server_builder_1.MCPServerBuilder();
|
|
157
|
+
builder.addBaseServers(fraimKey);
|
|
158
|
+
await addProviderServers(builder, tokens, providerConfigs);
|
|
159
|
+
const format = (0, ide_formats_1.getIDEFormat)('grok');
|
|
160
|
+
return format.transform(builder.getServers());
|
|
161
|
+
};
|
|
162
|
+
exports.generateGrokMCPServers = generateGrokMCPServers;
|
|
154
163
|
const generateVSCodeMCPServers = async (fraimKey, tokenInput, providerConfigs) => {
|
|
155
164
|
const tokens = normalizeTokens(tokenInput);
|
|
156
165
|
const builder = new mcp_server_builder_1.MCPServerBuilder();
|
|
@@ -194,6 +203,8 @@ const generateMCPConfig = async (configType, fraimKey, tokenInput, providerConfi
|
|
|
194
203
|
return await (0, exports.generateGeminiCliMCPServers)(fraimKey, tokenInput, providerConfigs);
|
|
195
204
|
case 'codex':
|
|
196
205
|
return await (0, exports.generateCodexMCPServers)(fraimKey, tokenInput, providerConfigs);
|
|
206
|
+
case 'grok':
|
|
207
|
+
return await (0, exports.generateGrokMCPServers)(fraimKey, tokenInput, providerConfigs);
|
|
197
208
|
case 'windsurf':
|
|
198
209
|
return await (0, exports.generateWindsurfMCPServers)(fraimKey, tokenInput, providerConfigs);
|
|
199
210
|
default:
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getAdapterConfigTypes = getAdapterConfigTypes;
|
|
6
7
|
exports.ensureAgentAdapterFiles = ensureAgentAdapterFiles;
|
|
7
8
|
const fs_1 = __importDefault(require("fs"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
@@ -15,6 +16,7 @@ const CLAUDE_FRAIM_COMMAND_PATH = path_1.default.join('.claude', 'commands', 'fr
|
|
|
15
16
|
const CLAUDE_FRAIM_SKILL_PATH = path_1.default.join('.claude', 'skills', 'fraim', 'SKILL.md');
|
|
16
17
|
const VSCODE_FRAIM_PROMPT_PATH = path_1.default.join('.github', 'prompts', 'fraim.prompt.md');
|
|
17
18
|
const CODEX_FRAIM_SKILL_PATH = path_1.default.join('.codex', 'skills', 'fraim', 'SKILL.md');
|
|
19
|
+
const GROK_FRAIM_SKILL_PATH = path_1.default.join('.grok', 'skills', 'fraim', 'SKILL.md');
|
|
18
20
|
const GEMINI_FRAIM_COMMAND_PATH = path_1.default.join('.gemini', 'commands', 'fraim.toml');
|
|
19
21
|
const GEMINI_PROJECT_INSTRUCTIONS_PATH = path_1.default.join('.gemini', 'GEMINI.md');
|
|
20
22
|
const WINDSURF_FRAIM_COMMAND_PATH = path_1.default.join('.windsurf', 'commands', 'fraim.md');
|
|
@@ -46,7 +48,7 @@ function mergeCursorRule(existingContent, managedSection) {
|
|
|
46
48
|
const mergedBody = mergeManagedSection(bodyWithoutLeadingFrontmatter, managedSection).trim();
|
|
47
49
|
return `${ide_invocation_surfaces_1.CURSOR_MDC_FRONTMATTER}\n\n${mergedBody}\n`;
|
|
48
50
|
}
|
|
49
|
-
function getAdapterFiles() {
|
|
51
|
+
function getAdapterFiles(allowedConfigTypes = null) {
|
|
50
52
|
const fraimRoot = (0, project_fraim_paths_1.getWorkspaceFraimDisplayPath)().replace(/\/$/, '');
|
|
51
53
|
const employeeJobsPath = (0, project_fraim_paths_1.getWorkspaceFraimDisplayPath)('ai-employee/jobs');
|
|
52
54
|
const managerJobsPath = (0, project_fraim_paths_1.getWorkspaceFraimDisplayPath)('ai-manager/jobs');
|
|
@@ -108,26 +110,48 @@ ${(0, ide_invocation_surfaces_1.buildFraimInvocationBody)('generic-tool-discover
|
|
|
108
110
|
|
|
109
111
|
@../AGENTS.md
|
|
110
112
|
`;
|
|
111
|
-
|
|
112
|
-
{ path: 'AGENTS.md', content: markdownBody },
|
|
113
|
-
{ path: 'CLAUDE.md', content: markdownBody },
|
|
114
|
-
{ path: path_1.default.join('.github', 'copilot-instructions.md'), content: copilotBody },
|
|
115
|
-
{ path: CURSOR_RULE_PATH, content: cursorManagedBody },
|
|
116
|
-
{ path: VSCODE_FRAIM_PROMPT_PATH, content: vscodePrompt },
|
|
117
|
-
{ path: path_1.default.join(project_fraim_paths_1.WORKSPACE_FRAIM_DIRNAME, 'README.md'), content: fraimReadme },
|
|
118
|
-
{ path: CLAUDE_FRAIM_SKILL_PATH, content: (0, ide_invocation_surfaces_1.buildClaudeSkillContent)() },
|
|
119
|
-
{ path: CLAUDE_FRAIM_COMMAND_PATH, content: (0, ide_invocation_surfaces_1.buildClaudeCommandShimContent)() },
|
|
120
|
-
{ path: CODEX_FRAIM_SKILL_PATH, content: (0, ide_invocation_surfaces_1.buildCodexSkillContent)() },
|
|
121
|
-
{ path:
|
|
122
|
-
{ path:
|
|
123
|
-
{ path:
|
|
124
|
-
{ path:
|
|
113
|
+
const all = [
|
|
114
|
+
{ path: 'AGENTS.md', content: markdownBody, configType: 'standard' },
|
|
115
|
+
{ path: 'CLAUDE.md', content: markdownBody, configType: 'standard' },
|
|
116
|
+
{ path: path_1.default.join('.github', 'copilot-instructions.md'), content: copilotBody, configType: 'vscode' },
|
|
117
|
+
{ path: CURSOR_RULE_PATH, content: cursorManagedBody, configType: 'cursor' },
|
|
118
|
+
{ path: VSCODE_FRAIM_PROMPT_PATH, content: vscodePrompt, configType: 'vscode' },
|
|
119
|
+
{ path: path_1.default.join(project_fraim_paths_1.WORKSPACE_FRAIM_DIRNAME, 'README.md'), content: fraimReadme, configType: 'standard' },
|
|
120
|
+
{ path: CLAUDE_FRAIM_SKILL_PATH, content: (0, ide_invocation_surfaces_1.buildClaudeSkillContent)(), configType: 'claude-code' },
|
|
121
|
+
{ path: CLAUDE_FRAIM_COMMAND_PATH, content: (0, ide_invocation_surfaces_1.buildClaudeCommandShimContent)(), configType: 'claude-code' },
|
|
122
|
+
{ path: CODEX_FRAIM_SKILL_PATH, content: (0, ide_invocation_surfaces_1.buildCodexSkillContent)(), configType: 'codex' },
|
|
123
|
+
{ path: GROK_FRAIM_SKILL_PATH, content: (0, ide_invocation_surfaces_1.buildGrokSkillContent)(), configType: 'grok' },
|
|
124
|
+
{ path: GEMINI_FRAIM_COMMAND_PATH, content: (0, ide_invocation_surfaces_1.buildGeminiCommandContent)(), configType: 'gemini-cli' },
|
|
125
|
+
{ path: GEMINI_PROJECT_INSTRUCTIONS_PATH, content: geminiProjectInstructions, configType: 'gemini-cli' },
|
|
126
|
+
{ path: WINDSURF_FRAIM_COMMAND_PATH, content: (0, ide_invocation_surfaces_1.buildWindsurfCommandContent)(), configType: 'windsurf' },
|
|
127
|
+
{ path: KIRO_FRAIM_COMMAND_PATH, content: (0, ide_invocation_surfaces_1.buildKiroCommandContent)(), configType: 'kiro' }
|
|
125
128
|
];
|
|
129
|
+
if (allowedConfigTypes === null) {
|
|
130
|
+
return all;
|
|
131
|
+
}
|
|
132
|
+
return all.filter(f => f.configType === 'standard' || allowedConfigTypes.includes(f.configType));
|
|
133
|
+
}
|
|
134
|
+
function getAdapterConfigTypes() {
|
|
135
|
+
const result = {};
|
|
136
|
+
for (const f of getAdapterFiles()) {
|
|
137
|
+
result[f.path.replace(/\\/g, '/')] = f.configType;
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
126
140
|
}
|
|
127
|
-
function ensureAgentAdapterFiles(projectRoot) {
|
|
141
|
+
function ensureAgentAdapterFiles(projectRoot, allowedConfigTypes = null) {
|
|
142
|
+
(0, project_fraim_paths_1.assertWorkspaceFraimRoot)(projectRoot);
|
|
128
143
|
const updatedPaths = [];
|
|
129
|
-
|
|
144
|
+
const resolvedProjectRoot = path_1.default.resolve(projectRoot);
|
|
145
|
+
for (const file of getAdapterFiles(allowedConfigTypes)) {
|
|
130
146
|
const fullPath = path_1.default.join(projectRoot, file.path);
|
|
147
|
+
const resolvedFullPath = path_1.default.resolve(fullPath);
|
|
148
|
+
const relativeToProject = path_1.default.relative(resolvedProjectRoot, resolvedFullPath);
|
|
149
|
+
if (relativeToProject === '' || relativeToProject.startsWith('..') || path_1.default.isAbsolute(relativeToProject)) {
|
|
150
|
+
throw new Error(`Refusing to write FRAIM adapter outside project root: ${resolvedFullPath}`);
|
|
151
|
+
}
|
|
152
|
+
if (file.path.replace(/\\/g, '/').startsWith(`${project_fraim_paths_1.WORKSPACE_FRAIM_DIRNAME}/`)) {
|
|
153
|
+
(0, project_fraim_paths_1.assertWorkspaceFraimPath)(projectRoot, fullPath);
|
|
154
|
+
}
|
|
131
155
|
const dir = path_1.default.dirname(fullPath);
|
|
132
156
|
if (!fs_1.default.existsSync(dir)) {
|
|
133
157
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
@@ -140,6 +164,7 @@ function ensureAgentAdapterFiles(projectRoot) {
|
|
|
140
164
|
|| file.path === CLAUDE_FRAIM_SKILL_PATH
|
|
141
165
|
|| file.path === CLAUDE_FRAIM_COMMAND_PATH
|
|
142
166
|
|| file.path === CODEX_FRAIM_SKILL_PATH
|
|
167
|
+
|| file.path === GROK_FRAIM_SKILL_PATH
|
|
143
168
|
|| file.path === GEMINI_FRAIM_COMMAND_PATH
|
|
144
169
|
|| file.path === GEMINI_PROJECT_INSTRUCTIONS_PATH
|
|
145
170
|
|| file.path === WINDSURF_FRAIM_COMMAND_PATH
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ensureFraimSyncedContentLocallyExcluded = exports.removeFraimSyncedContentGitignoreBlock = exports.FRAIM_SYNC_GITIGNORE_ENTRIES = exports.FRAIM_SYNC_GITIGNORE_END = exports.FRAIM_SYNC_GITIGNORE_START = void 0;
|
|
7
|
+
exports.addToFraimGitignore = addToFraimGitignore;
|
|
7
8
|
const fs_1 = __importDefault(require("fs"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
exports.FRAIM_SYNC_GITIGNORE_START = '# BEGIN FRAIM SYNCED CONTENT';
|
|
@@ -73,6 +74,18 @@ const removeFraimSyncedContentGitignoreBlock = (projectRoot) => {
|
|
|
73
74
|
return true;
|
|
74
75
|
};
|
|
75
76
|
exports.removeFraimSyncedContentGitignoreBlock = removeFraimSyncedContentGitignoreBlock;
|
|
77
|
+
function addToFraimGitignore(projectRoot, entry) {
|
|
78
|
+
const gitignorePath = path_1.default.join(projectRoot, '.gitignore');
|
|
79
|
+
const existing = fs_1.default.existsSync(gitignorePath) ? fs_1.default.readFileSync(gitignorePath, 'utf8') : '';
|
|
80
|
+
const lines = existing.replace(/\r\n/g, '\n').split('\n');
|
|
81
|
+
if (lines.includes(entry)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const appended = existing.trimEnd().length > 0
|
|
85
|
+
? `${existing.trimEnd()}\n${entry}\n`
|
|
86
|
+
: `${entry}\n`;
|
|
87
|
+
fs_1.default.writeFileSync(gitignorePath, appended, 'utf8');
|
|
88
|
+
}
|
|
76
89
|
const ensureFraimSyncedContentLocallyExcluded = (projectRoot) => {
|
|
77
90
|
const gitignoreUpdated = (0, exports.removeFraimSyncedContentGitignoreBlock)(projectRoot);
|
|
78
91
|
const excludePath = resolveGitInfoExcludePath(projectRoot);
|