fraim 2.0.174 → 2.0.175
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.
|
@@ -3,7 +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.expandPath = exports.findIDEByName = exports.getAllSupportedIDEs = exports.detectInstalledIDEs = exports.IDE_CONFIGS = void 0;
|
|
6
|
+
exports.expandPath = exports.findIDEByName = exports.getAllSupportedIDEs = exports.detectInstalledIDEs = exports.CLI_PROBE_CONFIGTYPES = exports.IDE_CONFIGS = void 0;
|
|
7
7
|
exports.getAdapterConfigType = getAdapterConfigType;
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
@@ -71,9 +71,9 @@ const detectGeminiCli = () => {
|
|
|
71
71
|
};
|
|
72
72
|
const detectGeminiSurface = () => {
|
|
73
73
|
const paths = [
|
|
74
|
-
'~/.gemini',
|
|
75
|
-
'~/AppData/Roaming/gemini',
|
|
76
|
-
'~/.config/gemini'
|
|
74
|
+
'~/.gemini/settings.json',
|
|
75
|
+
'~/AppData/Roaming/gemini/settings.json',
|
|
76
|
+
'~/.config/gemini/settings.json'
|
|
77
77
|
];
|
|
78
78
|
return checkMultiplePaths(paths);
|
|
79
79
|
};
|
|
@@ -103,7 +103,8 @@ exports.IDE_CONFIGS = [
|
|
|
103
103
|
alternativePaths: [
|
|
104
104
|
'~/.claude/settings.json'
|
|
105
105
|
],
|
|
106
|
-
description: 'Anthropic Claude Code local surfaces (CLI and Desktop Code tab)'
|
|
106
|
+
description: 'Anthropic Claude Code local surfaces (CLI and Desktop Code tab)',
|
|
107
|
+
downloadUrl: 'https://claude.ai/code',
|
|
107
108
|
},
|
|
108
109
|
{
|
|
109
110
|
name: 'Claude Desktop / Cowork',
|
|
@@ -116,7 +117,8 @@ exports.IDE_CONFIGS = [
|
|
|
116
117
|
alternativePaths: [
|
|
117
118
|
'~/Library/Application Support/Claude/claude_desktop_config.json'
|
|
118
119
|
],
|
|
119
|
-
description: 'Anthropic Claude Desktop chat and Cowork surfaces'
|
|
120
|
+
description: 'Anthropic Claude Desktop chat and Cowork surfaces',
|
|
121
|
+
downloadUrl: 'https://claude.ai/download',
|
|
120
122
|
},
|
|
121
123
|
{
|
|
122
124
|
name: 'Antigravity',
|
|
@@ -125,7 +127,8 @@ exports.IDE_CONFIGS = [
|
|
|
125
127
|
configType: 'standard',
|
|
126
128
|
invocationProfile: 'cursor-mention',
|
|
127
129
|
detectMethod: () => fs_1.default.existsSync(expandPath('~/.gemini/antigravity')),
|
|
128
|
-
description: 'Google Gemini Antigravity IDE'
|
|
130
|
+
description: 'Google Gemini Antigravity IDE',
|
|
131
|
+
downloadUrl: 'https://deepmind.google/technologies/gemini/',
|
|
129
132
|
},
|
|
130
133
|
{
|
|
131
134
|
name: 'Gemini CLI',
|
|
@@ -140,7 +143,8 @@ exports.IDE_CONFIGS = [
|
|
|
140
143
|
'~/AppData/Roaming/gemini/settings.json',
|
|
141
144
|
'~/.config/gemini/settings.json'
|
|
142
145
|
],
|
|
143
|
-
description: 'Google Gemini CLI local settings'
|
|
146
|
+
description: 'Google Gemini CLI local settings',
|
|
147
|
+
downloadUrl: 'https://github.com/google-gemini/gemini-cli',
|
|
144
148
|
},
|
|
145
149
|
{
|
|
146
150
|
name: 'Kiro',
|
|
@@ -149,7 +153,8 @@ exports.IDE_CONFIGS = [
|
|
|
149
153
|
configType: 'kiro',
|
|
150
154
|
invocationProfile: 'kiro-hashtag',
|
|
151
155
|
detectMethod: () => fs_1.default.existsSync(expandPath('~/.kiro')),
|
|
152
|
-
description: 'Kiro AI-powered IDE'
|
|
156
|
+
description: 'Kiro AI-powered IDE',
|
|
157
|
+
downloadUrl: 'https://kiro.dev/',
|
|
153
158
|
},
|
|
154
159
|
{
|
|
155
160
|
name: 'Cursor',
|
|
@@ -164,7 +169,8 @@ exports.IDE_CONFIGS = [
|
|
|
164
169
|
'~/AppData/Roaming/Cursor/mcp.json',
|
|
165
170
|
'~/.config/Cursor/mcp.json'
|
|
166
171
|
],
|
|
167
|
-
description: 'Cursor AI code editor'
|
|
172
|
+
description: 'Cursor AI code editor',
|
|
173
|
+
downloadUrl: 'https://cursor.com/',
|
|
168
174
|
},
|
|
169
175
|
{
|
|
170
176
|
name: 'VSCode',
|
|
@@ -182,7 +188,8 @@ exports.IDE_CONFIGS = [
|
|
|
182
188
|
'~/AppData/Roaming/Code/User/mcp.json',
|
|
183
189
|
'~/.config/Code/User/mcp.json'
|
|
184
190
|
],
|
|
185
|
-
description: 'Visual Studio Code'
|
|
191
|
+
description: 'Visual Studio Code',
|
|
192
|
+
downloadUrl: 'https://code.visualstudio.com/',
|
|
186
193
|
},
|
|
187
194
|
{
|
|
188
195
|
name: 'Codex',
|
|
@@ -191,7 +198,8 @@ exports.IDE_CONFIGS = [
|
|
|
191
198
|
configType: 'codex',
|
|
192
199
|
invocationProfile: 'codex-skill',
|
|
193
200
|
detectMethod: detectCodexSurface,
|
|
194
|
-
description: 'Codex AI development environment'
|
|
201
|
+
description: 'Codex AI development environment',
|
|
202
|
+
downloadUrl: 'https://github.com/openai/codex',
|
|
195
203
|
},
|
|
196
204
|
{
|
|
197
205
|
name: 'Grok',
|
|
@@ -202,7 +210,8 @@ exports.IDE_CONFIGS = [
|
|
|
202
210
|
detectMethod: detectGrokSurface,
|
|
203
211
|
supportsConfigBootstrap: true,
|
|
204
212
|
aliases: ['grok', 'grok-cli', 'grok cli', 'grok build'],
|
|
205
|
-
description: 'xAI Grok Build CLI local settings'
|
|
213
|
+
description: 'xAI Grok Build CLI local settings',
|
|
214
|
+
downloadUrl: 'https://x.ai/grok',
|
|
206
215
|
},
|
|
207
216
|
{
|
|
208
217
|
name: 'Windsurf',
|
|
@@ -216,7 +225,8 @@ exports.IDE_CONFIGS = [
|
|
|
216
225
|
'~/AppData/Roaming/Windsurf/mcp_config.json',
|
|
217
226
|
'~/.config/windsurf/mcp_config.json'
|
|
218
227
|
],
|
|
219
|
-
description: 'Codeium Windsurf IDE'
|
|
228
|
+
description: 'Codeium Windsurf IDE',
|
|
229
|
+
downloadUrl: 'https://windsurf.com/',
|
|
220
230
|
}
|
|
221
231
|
];
|
|
222
232
|
const findBestConfigPath = (ide) => {
|
|
@@ -236,6 +246,8 @@ const _cachedIDEs = new Map();
|
|
|
236
246
|
const _cacheTimestamps = new Map();
|
|
237
247
|
const _cacheHomeDirs = new Map();
|
|
238
248
|
const DETECT_CACHE_TTL_MS = 5000;
|
|
249
|
+
/** configTypes that require a binary probe in cli-runnable mode; config folder alone is insufficient. */
|
|
250
|
+
exports.CLI_PROBE_CONFIGTYPES = new Set(['claude-code', 'codex', 'grok', 'gemini-cli']);
|
|
239
251
|
const isDetectedForMode = (ide, mode) => {
|
|
240
252
|
if (mode === 'cli-runnable') {
|
|
241
253
|
switch (ide.configType) {
|
|
@@ -175,7 +175,13 @@ function normalizeRows(rows) {
|
|
|
175
175
|
}));
|
|
176
176
|
}
|
|
177
177
|
function buildRunnableAgentSurfaces() {
|
|
178
|
-
|
|
178
|
+
// GUI agents (Claude Desktop, VSCode, Cursor, Windsurf, Kiro) are detected by config-surface:
|
|
179
|
+
// their config folder is sufficient evidence of installation.
|
|
180
|
+
// CLI agents require a binary on PATH; a config folder alone does not mean the agent is
|
|
181
|
+
// runnable, so they are gated through cli-runnable as well.
|
|
182
|
+
const configSurface = (0, ide_detector_1.detectInstalledIDEs)('config-surface');
|
|
183
|
+
const cliRunnableTypes = new Set((0, ide_detector_1.detectInstalledIDEs)('cli-runnable').map((ide) => ide.configType));
|
|
184
|
+
const ides = configSurface.filter((ide) => !ide_detector_1.CLI_PROBE_CONFIGTYPES.has(ide.configType) || cliRunnableTypes.has(ide.configType));
|
|
179
185
|
const hints = (0, ide_global_integration_1.describeOnboardingInvocationSurfaces)(ides);
|
|
180
186
|
return ides.map((ide, index) => ({
|
|
181
187
|
id: ide.configType,
|
|
@@ -426,6 +432,13 @@ class FirstRunSessionService {
|
|
|
426
432
|
getSession() {
|
|
427
433
|
this.detectRowsOnLoad();
|
|
428
434
|
this.persist();
|
|
435
|
+
const detectedNames = new Set((this.state.setupResult?.configuredSurfaces ?? []).map((s) => s.name));
|
|
436
|
+
const supportedAgents = ide_detector_1.IDE_CONFIGS
|
|
437
|
+
.map((ide) => ({
|
|
438
|
+
name: ide.name,
|
|
439
|
+
detected: detectedNames.has(ide.name),
|
|
440
|
+
downloadUrl: ide.downloadUrl ?? null,
|
|
441
|
+
}));
|
|
429
442
|
return {
|
|
430
443
|
state: this.state,
|
|
431
444
|
rows: this.state.rows,
|
|
@@ -435,6 +448,7 @@ class FirstRunSessionService {
|
|
|
435
448
|
requestToken: this.requestToken,
|
|
436
449
|
agentOptions: types_1.FIRST_RUN_AGENT_OPTIONS,
|
|
437
450
|
currentAgentId: this.state.agentId,
|
|
451
|
+
supportedAgents,
|
|
438
452
|
};
|
|
439
453
|
}
|
|
440
454
|
respond(message, ok) {
|
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
configureError: null,
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
|
|
16
17
|
const STEP_LABELS = {
|
|
17
18
|
prereqs: 'Prerequisites',
|
|
18
19
|
agents: 'Local Agents',
|
|
@@ -86,15 +87,6 @@
|
|
|
86
87
|
return configuredSurfaces().some((surface) => surface && (surface.id === opt.id || surface.name === opt.label));
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
function readyAgentLabels() {
|
|
90
|
-
const labels = new Set();
|
|
91
|
-
for (const agent of readyAgents()) labels.add(agent.label);
|
|
92
|
-
for (const surface of configuredSurfaces()) {
|
|
93
|
-
if (surface && surface.name) labels.add(surface.name);
|
|
94
|
-
}
|
|
95
|
-
return Array.from(labels);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
90
|
function detectedAgentCount() {
|
|
99
91
|
const setupResult = state.session && state.session.state ? state.session.state.setupResult : null;
|
|
100
92
|
return (setupResult && setupResult.detectedSurfaceCount) || readyAgents().length;
|
|
@@ -216,60 +208,74 @@
|
|
|
216
208
|
h.textContent = 'Locally installed AI agents';
|
|
217
209
|
pane.appendChild(h);
|
|
218
210
|
|
|
211
|
+
const anyDetected = detectedAgentCount() > 0;
|
|
219
212
|
const p = document.createElement('p');
|
|
220
213
|
p.className = 'pane-copy';
|
|
221
|
-
p.textContent =
|
|
222
|
-
? '
|
|
223
|
-
: '
|
|
214
|
+
p.textContent = anyDetected
|
|
215
|
+
? 'An AI tool is ready. You can add more or continue to configure FRAIM.'
|
|
216
|
+
: 'Install any of the AI tools below, then click Rescan once it is running.';
|
|
224
217
|
pane.appendChild(p);
|
|
225
218
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
readyList.className = 'ready-strip';
|
|
230
|
-
readyList.setAttribute('data-testid', 'ready-agents');
|
|
231
|
-
readyList.textContent = `Already installed: ${readyLabels.join(', ')}`;
|
|
232
|
-
pane.appendChild(readyList);
|
|
233
|
-
} else {
|
|
234
|
-
const readyList = document.createElement('div');
|
|
235
|
-
readyList.className = 'ready-strip ready-strip--muted';
|
|
236
|
-
readyList.setAttribute('data-testid', 'ready-agents');
|
|
237
|
-
readyList.textContent = 'Already installed: none detected yet';
|
|
238
|
-
pane.appendChild(readyList);
|
|
239
|
-
}
|
|
219
|
+
// Server-driven list: session.supportedAgents contains every GUI-detectable IDE
|
|
220
|
+
// with detection status and download URL already resolved.
|
|
221
|
+
const agents = (state.session && state.session.supportedAgents) || [];
|
|
240
222
|
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
223
|
+
const list = document.createElement('ul');
|
|
224
|
+
list.className = 'agent-list';
|
|
225
|
+
list.setAttribute('data-testid', 'agent-list');
|
|
226
|
+
|
|
227
|
+
for (const agent of agents) {
|
|
228
|
+
const li = document.createElement('li');
|
|
229
|
+
li.className = 'agent-row' + (agent.detected ? ' agent-row--detected' : '');
|
|
230
|
+
li.setAttribute('data-testid', `agent-row-${agent.name.toLowerCase().replace(/\s+/g, '-')}`);
|
|
231
|
+
|
|
232
|
+
const nameSpan = document.createElement('span');
|
|
233
|
+
nameSpan.className = 'agent-row__name';
|
|
234
|
+
nameSpan.textContent = agent.name;
|
|
235
|
+
|
|
236
|
+
const actionSpan = document.createElement('span');
|
|
237
|
+
actionSpan.className = 'agent-row__action';
|
|
238
|
+
|
|
239
|
+
if (agent.detected) {
|
|
240
|
+
const badge = document.createElement('span');
|
|
241
|
+
badge.className = 'agent-badge agent-badge--installed';
|
|
242
|
+
badge.setAttribute('data-testid', `agent-installed-${agent.name.toLowerCase().replace(/\s+/g, '-')}`);
|
|
243
|
+
badge.textContent = 'Installed';
|
|
244
|
+
actionSpan.appendChild(badge);
|
|
245
|
+
} else if (agent.downloadUrl) {
|
|
246
|
+
const link = document.createElement('a');
|
|
247
|
+
link.className = 'agent-download-link';
|
|
248
|
+
link.href = agent.downloadUrl;
|
|
249
|
+
link.target = '_blank';
|
|
250
|
+
link.rel = 'noopener noreferrer';
|
|
251
|
+
link.textContent = 'Download';
|
|
252
|
+
link.setAttribute('data-testid', `agent-download-${agent.name.toLowerCase().replace(/\s+/g, '-')}`);
|
|
253
|
+
actionSpan.appendChild(link);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
li.appendChild(nameSpan);
|
|
257
|
+
li.appendChild(actionSpan);
|
|
258
|
+
list.appendChild(li);
|
|
266
259
|
}
|
|
267
260
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
261
|
+
pane.appendChild(list);
|
|
262
|
+
|
|
263
|
+
const otherNote = document.createElement('p');
|
|
264
|
+
otherNote.className = 'pane-copy';
|
|
265
|
+
otherNote.innerHTML = 'Using a different tool? Run <code>npx fraim add-ide</code> from your project directory after setup.';
|
|
266
|
+
pane.appendChild(otherNote);
|
|
267
|
+
|
|
268
|
+
const rescanBtn = button('Rescan installed tools', 'ghost');
|
|
269
|
+
rescanBtn.setAttribute('data-testid', 'rescan-agents');
|
|
270
|
+
rescanBtn.addEventListener('click', async () => {
|
|
271
|
+
rescanBtn.disabled = true;
|
|
272
|
+
rescanBtn.textContent = 'Scanning...';
|
|
273
|
+
try { await loadSession(false); } finally {
|
|
274
|
+
state.activeStep = 'agents';
|
|
275
|
+
render();
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
pane.appendChild(rescanBtn);
|
|
273
279
|
|
|
274
280
|
const done = button('Next', 'primary');
|
|
275
281
|
done.setAttribute('data-testid', 'done-installing-agents');
|
|
@@ -516,6 +516,53 @@ body {
|
|
|
516
516
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
517
517
|
gap: 12px;
|
|
518
518
|
}
|
|
519
|
+
|
|
520
|
+
/* Compact server-driven agent list */
|
|
521
|
+
.agent-list {
|
|
522
|
+
list-style: none;
|
|
523
|
+
margin: 0 0 12px;
|
|
524
|
+
padding: 0;
|
|
525
|
+
border: 1px solid var(--line);
|
|
526
|
+
border-radius: 10px;
|
|
527
|
+
overflow: hidden;
|
|
528
|
+
}
|
|
529
|
+
.agent-row {
|
|
530
|
+
display: flex;
|
|
531
|
+
align-items: center;
|
|
532
|
+
justify-content: space-between;
|
|
533
|
+
padding: 12px 16px;
|
|
534
|
+
border-bottom: 1px solid var(--line);
|
|
535
|
+
background: var(--surface);
|
|
536
|
+
gap: 12px;
|
|
537
|
+
}
|
|
538
|
+
.agent-row:last-child { border-bottom: 0; }
|
|
539
|
+
.agent-row--detected { background: var(--accent-soft); }
|
|
540
|
+
.agent-row__name {
|
|
541
|
+
font-size: 14px;
|
|
542
|
+
font-weight: 500;
|
|
543
|
+
color: var(--text);
|
|
544
|
+
flex: 1;
|
|
545
|
+
}
|
|
546
|
+
.agent-row--detected .agent-row__name { color: var(--accent-strong); }
|
|
547
|
+
.agent-row__action { flex-shrink: 0; }
|
|
548
|
+
.agent-badge {
|
|
549
|
+
font-size: 12px;
|
|
550
|
+
font-weight: 600;
|
|
551
|
+
padding: 3px 10px;
|
|
552
|
+
border-radius: 20px;
|
|
553
|
+
}
|
|
554
|
+
.agent-badge--installed {
|
|
555
|
+
background: var(--accent);
|
|
556
|
+
color: #fff;
|
|
557
|
+
}
|
|
558
|
+
.agent-download-link {
|
|
559
|
+
font-size: 13px;
|
|
560
|
+
font-weight: 500;
|
|
561
|
+
color: var(--accent-strong);
|
|
562
|
+
text-decoration: none;
|
|
563
|
+
}
|
|
564
|
+
.agent-download-link:hover { text-decoration: underline; }
|
|
565
|
+
|
|
519
566
|
.ready-strip {
|
|
520
567
|
background: var(--accent-soft);
|
|
521
568
|
border: 1px solid var(--accent);
|