fraim-framework 2.0.145 → 2.0.147
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/desktop-main.js +10 -1
- package/dist/src/ai-hub/hosts.js +36 -18
- package/dist/src/ai-hub/preferences.js +3 -0
- package/dist/src/ai-hub/server.js +110 -4
- package/dist/src/cli/commands/add-ide.js +22 -21
- package/dist/src/cli/setup/ide-detector.js +13 -1
- package/package.json +1 -1
- package/public/ai-hub/index.html +77 -41
- package/public/ai-hub/script.js +611 -89
- package/public/ai-hub/styles.css +712 -220
- package/public/first-run/index.html +1 -0
- package/public/first-run/script.js +30 -18
- package/public/first-run/styles.css +73 -49
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>FRAIM Setup</title>
|
|
7
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Crect width='48' height='48' rx='10' fill='%230f2540'/%3E%3Ctext x='24' y='31' text-anchor='middle' font-family='Helvetica,Arial,sans-serif' font-size='22' font-weight='700' fill='%23f6efe4'%3EF%3C/text%3E%3C/svg%3E">
|
|
7
8
|
<link rel="stylesheet" href="/first-run/styles.css">
|
|
8
9
|
</head>
|
|
9
10
|
<body>
|
|
@@ -480,16 +480,21 @@
|
|
|
480
480
|
CHECKLIST_EL.className = 'selection-container start-container';
|
|
481
481
|
CHECKLIST_EL.innerHTML = '';
|
|
482
482
|
PRIMARY_BUTTON.style.display = 'none';
|
|
483
|
-
setHeader('
|
|
483
|
+
setHeader('Start in your IDE', 'Recommended: fully restart your favorite IDE, open your project there, and let FRAIM run in the surface you already use.');
|
|
484
484
|
|
|
485
485
|
const ideLi = document.createElement('li');
|
|
486
486
|
const ideCard = document.createElement('div');
|
|
487
|
-
ideCard.className = 'user-type-card';
|
|
488
|
-
ideCard.appendChild(cardHeader('</>', 'In my IDE', 'Claude Code, Cursor, Codex, or
|
|
487
|
+
ideCard.className = 'user-type-card user-type-card--featured user-type-card--ide-default';
|
|
488
|
+
ideCard.appendChild(cardHeader('</>', 'In my IDE', 'Recommended. Restart Claude Code, Cursor, Codex, or your favorite AI IDE before you continue.'));
|
|
489
|
+
ideCard.appendChild(cardEyebrow('Recommended default'));
|
|
490
|
+
const ideNote = document.createElement('p');
|
|
491
|
+
ideNote.className = 'route-note';
|
|
492
|
+
ideNote.textContent = 'This keeps FRAIM inside the tool you already work in and avoids the extra layer of the Hub.';
|
|
493
|
+
ideCard.appendChild(ideNote);
|
|
489
494
|
const ideBtn = document.createElement('button');
|
|
490
495
|
ideBtn.type = 'button';
|
|
491
|
-
ideBtn.className = 'btn btn-
|
|
492
|
-
ideBtn.textContent = '
|
|
496
|
+
ideBtn.className = 'btn btn-primary btn-block';
|
|
497
|
+
ideBtn.textContent = 'Continue in my IDE';
|
|
493
498
|
ideBtn.addEventListener('click', async () => {
|
|
494
499
|
try {
|
|
495
500
|
await api('/api/first-run/set-preference', 'POST', { choice: 'ide' });
|
|
@@ -500,21 +505,19 @@
|
|
|
500
505
|
ideLi.appendChild(ideCard);
|
|
501
506
|
CHECKLIST_EL.appendChild(ideLi);
|
|
502
507
|
|
|
503
|
-
const orLi = document.createElement('li');
|
|
504
|
-
orLi.className = 'route-or';
|
|
505
|
-
orLi.setAttribute('role', 'separator');
|
|
506
|
-
orLi.setAttribute('aria-hidden', 'true');
|
|
507
|
-
orLi.textContent = 'or';
|
|
508
|
-
CHECKLIST_EL.appendChild(orLi);
|
|
509
|
-
|
|
510
508
|
const hubLi = document.createElement('li');
|
|
511
509
|
const hubCard = document.createElement('div');
|
|
512
|
-
hubCard.className = 'user-type-card user-type-card--
|
|
513
|
-
hubCard.appendChild(cardHeader('
|
|
510
|
+
hubCard.className = 'user-type-card user-type-card--compact user-type-card--alpha';
|
|
511
|
+
hubCard.appendChild(cardHeader('α', 'AI Hub Alpha', 'Early testers only'));
|
|
512
|
+
hubCard.appendChild(cardEyebrow('Optional fallback'));
|
|
513
|
+
const hubNote = document.createElement('p');
|
|
514
|
+
hubNote.className = 'route-note route-note--compact';
|
|
515
|
+
hubNote.textContent = 'Use the Hub only if you specifically want the experimental browser shell.';
|
|
516
|
+
hubCard.appendChild(hubNote);
|
|
514
517
|
const hubBtn = document.createElement('button');
|
|
515
518
|
hubBtn.type = 'button';
|
|
516
|
-
hubBtn.className = 'btn btn-
|
|
517
|
-
hubBtn.textContent = 'Open Hub';
|
|
519
|
+
hubBtn.className = 'btn btn-secondary';
|
|
520
|
+
hubBtn.textContent = 'Open AI Hub Alpha';
|
|
518
521
|
hubBtn.addEventListener('click', async () => {
|
|
519
522
|
try {
|
|
520
523
|
await api('/api/first-run/set-preference', 'POST', { choice: 'hub' });
|
|
@@ -538,6 +541,8 @@
|
|
|
538
541
|
hubCard.appendChild(hubBtn);
|
|
539
542
|
hubLi.appendChild(hubCard);
|
|
540
543
|
CHECKLIST_EL.appendChild(hubLi);
|
|
544
|
+
|
|
545
|
+
setTimeout(() => ideBtn.focus(), 0);
|
|
541
546
|
}
|
|
542
547
|
|
|
543
548
|
function cardHeader(iconText, titleText, descText) {
|
|
@@ -560,10 +565,17 @@
|
|
|
560
565
|
return header;
|
|
561
566
|
}
|
|
562
567
|
|
|
568
|
+
function cardEyebrow(text) {
|
|
569
|
+
const eyebrow = document.createElement('span');
|
|
570
|
+
eyebrow.className = 'card-eyebrow';
|
|
571
|
+
eyebrow.textContent = text;
|
|
572
|
+
return eyebrow;
|
|
573
|
+
}
|
|
574
|
+
|
|
563
575
|
function renderIdeCommandDisplay(commands) {
|
|
564
576
|
CHECKLIST_EL.className = 'selection-container';
|
|
565
577
|
CHECKLIST_EL.innerHTML = '';
|
|
566
|
-
setHeader('
|
|
578
|
+
setHeader('Restart your favorite IDE', 'Fully restart your IDE first so it picks up the new FRAIM setup. Then open your project there and type:');
|
|
567
579
|
|
|
568
580
|
const cmdList = (commands && commands.length > 0) ? commands : ['/fraim onboard this project'];
|
|
569
581
|
for (const cmd of cmdList) {
|
|
@@ -612,7 +624,7 @@
|
|
|
612
624
|
const switchLink = document.createElement('button');
|
|
613
625
|
switchLink.type = 'button';
|
|
614
626
|
switchLink.className = 'text-button';
|
|
615
|
-
switchLink.textContent = '
|
|
627
|
+
switchLink.textContent = 'Prefer AI Hub Alpha instead';
|
|
616
628
|
switchLink.addEventListener('click', async () => {
|
|
617
629
|
try {
|
|
618
630
|
await api('/api/first-run/set-preference', 'POST', { choice: 'hub' });
|
|
@@ -421,10 +421,14 @@ body {
|
|
|
421
421
|
flex-direction: column;
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
.recruit-container,
|
|
425
|
-
.start-container {
|
|
426
|
-
gap: 12px;
|
|
427
|
-
}
|
|
424
|
+
.recruit-container,
|
|
425
|
+
.start-container {
|
|
426
|
+
gap: 12px;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.start-container {
|
|
430
|
+
gap: 14px;
|
|
431
|
+
}
|
|
428
432
|
|
|
429
433
|
.user-type-card {
|
|
430
434
|
background: var(--surface);
|
|
@@ -444,9 +448,23 @@ body {
|
|
|
444
448
|
border-color: var(--accent);
|
|
445
449
|
background: var(--accent-soft);
|
|
446
450
|
}
|
|
447
|
-
.user-type-card--featured:hover {
|
|
448
|
-
box-shadow: 0 4px 20px rgba(61, 138, 110, 0.18);
|
|
449
|
-
}
|
|
451
|
+
.user-type-card--featured:hover {
|
|
452
|
+
box-shadow: 0 4px 20px rgba(61, 138, 110, 0.18);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.user-type-card--ide-default {
|
|
456
|
+
padding: 24px;
|
|
457
|
+
gap: 18px;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.user-type-card--compact {
|
|
461
|
+
padding: 16px 18px;
|
|
462
|
+
gap: 12px;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.user-type-card--alpha {
|
|
466
|
+
background: linear-gradient(180deg, #fbfcfa 0%, #f4f7f2 100%);
|
|
467
|
+
}
|
|
450
468
|
|
|
451
469
|
.card-header {
|
|
452
470
|
display: flex;
|
|
@@ -474,14 +492,38 @@ body {
|
|
|
474
492
|
border-color: var(--accent);
|
|
475
493
|
}
|
|
476
494
|
|
|
477
|
-
.card-title {
|
|
478
|
-
display: block;
|
|
479
|
-
font-size: 15px;
|
|
480
|
-
font-weight: 600;
|
|
481
|
-
color: var(--text);
|
|
482
|
-
margin-bottom: 3px;
|
|
483
|
-
}
|
|
484
|
-
.card-desc { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.45; }
|
|
495
|
+
.card-title {
|
|
496
|
+
display: block;
|
|
497
|
+
font-size: 15px;
|
|
498
|
+
font-weight: 600;
|
|
499
|
+
color: var(--text);
|
|
500
|
+
margin-bottom: 3px;
|
|
501
|
+
}
|
|
502
|
+
.card-desc { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.45; }
|
|
503
|
+
|
|
504
|
+
.card-eyebrow {
|
|
505
|
+
display: inline-flex;
|
|
506
|
+
align-self: flex-start;
|
|
507
|
+
padding: 4px 10px;
|
|
508
|
+
border-radius: 999px;
|
|
509
|
+
background: var(--accent-soft);
|
|
510
|
+
color: var(--accent-strong);
|
|
511
|
+
font-size: 11px;
|
|
512
|
+
font-weight: 700;
|
|
513
|
+
letter-spacing: 0.06em;
|
|
514
|
+
text-transform: uppercase;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.route-note {
|
|
518
|
+
margin: 0;
|
|
519
|
+
color: var(--muted);
|
|
520
|
+
font-size: 13px;
|
|
521
|
+
line-height: 1.5;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.route-note--compact {
|
|
525
|
+
font-size: 12px;
|
|
526
|
+
}
|
|
485
527
|
|
|
486
528
|
.btn {
|
|
487
529
|
display: inline-flex;
|
|
@@ -530,31 +572,9 @@ body {
|
|
|
530
572
|
border-color: var(--line);
|
|
531
573
|
}
|
|
532
574
|
|
|
533
|
-
/*
|
|
534
|
-
.
|
|
535
|
-
|
|
536
|
-
color: var(--muted);
|
|
537
|
-
font-size: 12px;
|
|
538
|
-
letter-spacing: 0.05em;
|
|
539
|
-
text-transform: uppercase;
|
|
540
|
-
padding: 8px 0;
|
|
541
|
-
position: relative;
|
|
542
|
-
}
|
|
543
|
-
.route-or::before,
|
|
544
|
-
.route-or::after {
|
|
545
|
-
content: '';
|
|
546
|
-
position: absolute;
|
|
547
|
-
top: 50%;
|
|
548
|
-
width: calc(50% - 22px);
|
|
549
|
-
height: 1px;
|
|
550
|
-
background: var(--line);
|
|
551
|
-
}
|
|
552
|
-
.route-or::before { left: 0; }
|
|
553
|
-
.route-or::after { right: 0; }
|
|
554
|
-
|
|
555
|
-
/* IDE command display — shown after choosing "In my IDE". */
|
|
556
|
-
.cmd-block {
|
|
557
|
-
background: #0d1410;
|
|
575
|
+
/* IDE command display — shown after choosing "In my IDE". */
|
|
576
|
+
.cmd-block {
|
|
577
|
+
background: #0d1410;
|
|
558
578
|
color: #c8d3cd;
|
|
559
579
|
font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
|
|
560
580
|
font-size: 14px;
|
|
@@ -592,12 +612,16 @@ body {
|
|
|
592
612
|
* want the surface to degrade gracefully for users who happen to open it
|
|
593
613
|
* in a narrow window. Stack the label / verb / change link vertically and
|
|
594
614
|
* let the row breathe. */
|
|
595
|
-
@media (max-width: 600px) {
|
|
596
|
-
.page { padding: 24px 16px 24px; }
|
|
597
|
-
.checklist .row { gap: 8px; padding: 12px 14px; }
|
|
598
|
-
.row .label { min-width: 0; }
|
|
599
|
-
.row .verb { flex: 1 1 100%; }
|
|
600
|
-
.row .change-link { margin-left: auto; }
|
|
601
|
-
.row .project-picker { gap: 8px; }
|
|
602
|
-
.row .project-picker input { width: 100%; min-width: 0; }
|
|
603
|
-
|
|
615
|
+
@media (max-width: 600px) {
|
|
616
|
+
.page { padding: 24px 16px 24px; }
|
|
617
|
+
.checklist .row { gap: 8px; padding: 12px 14px; }
|
|
618
|
+
.row .label { min-width: 0; }
|
|
619
|
+
.row .verb { flex: 1 1 100%; }
|
|
620
|
+
.row .change-link { margin-left: auto; }
|
|
621
|
+
.row .project-picker { gap: 8px; }
|
|
622
|
+
.row .project-picker input { width: 100%; min-width: 0; }
|
|
623
|
+
.user-type-card--ide-default,
|
|
624
|
+
.user-type-card--compact {
|
|
625
|
+
padding: 18px 16px;
|
|
626
|
+
}
|
|
627
|
+
}
|