fraim-framework 2.0.167 → 2.0.169

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.
Files changed (33) hide show
  1. package/dist/src/ai-hub/catalog.js +28 -14
  2. package/dist/src/ai-hub/server.js +34 -406
  3. package/dist/src/cli/commands/init-project.js +1 -98
  4. package/dist/src/cli/commands/manager.js +40 -0
  5. package/dist/src/cli/commands/sync.js +17 -21
  6. package/dist/src/cli/fraim.js +2 -0
  7. package/dist/src/cli/utils/github-workflow-sync.js +12 -146
  8. package/dist/src/cli/utils/manager-pack-sync.js +188 -0
  9. package/dist/src/cli/utils/manager-publish.js +76 -0
  10. package/dist/src/cli/utils/user-config.js +20 -0
  11. package/dist/src/core/fraim-config-schema.generated.js +85 -10
  12. package/dist/src/core/manager-pack.js +26 -0
  13. package/dist/src/first-run/install-state.js +1 -0
  14. package/dist/src/first-run/server.js +9 -0
  15. package/dist/src/first-run/session-service.js +117 -23
  16. package/dist/src/first-run/types.js +2 -5
  17. package/dist/src/local-mcp-server/learning-context-builder.js +45 -8
  18. package/dist/src/local-mcp-server/stdio-server.js +28 -0
  19. package/package.json +1 -2
  20. package/public/ai-hub/index.html +0 -81
  21. package/public/ai-hub/script.js +3 -219
  22. package/public/ai-hub/styles.css +8 -36
  23. package/public/first-run/index.html +1 -1
  24. package/public/first-run/script.js +459 -530
  25. package/public/first-run/styles.css +288 -73
  26. package/dist/src/config/ai-manager-hiring.js +0 -121
  27. package/dist/src/config/compat.js +0 -16
  28. package/dist/src/config/feature-flags.js +0 -25
  29. package/dist/src/config/persona-capability-bundles.js +0 -273
  30. package/dist/src/config/persona-hiring.js +0 -270
  31. package/dist/src/config/portfolio-slug-overrides.js +0 -17
  32. package/dist/src/config/pricing.js +0 -37
  33. package/dist/src/config/stripe.js +0 -43
@@ -421,14 +421,209 @@ body {
421
421
  flex-direction: column;
422
422
  }
423
423
 
424
- .recruit-container,
425
- .start-container {
426
- gap: 12px;
427
- }
428
-
429
- .start-container {
430
- gap: 14px;
431
- }
424
+ .setup-shell {
425
+ list-style: none;
426
+ margin: 0;
427
+ padding: 0;
428
+ display: grid;
429
+ grid-template-columns: minmax(190px, 0.85fr) minmax(0, 2fr);
430
+ gap: 20px;
431
+ }
432
+ .setup-steps {
433
+ display: flex;
434
+ flex-direction: column;
435
+ gap: 8px;
436
+ border-right: 1px solid var(--line);
437
+ padding-right: 16px;
438
+ }
439
+ .setup-step {
440
+ width: 100%;
441
+ min-height: 44px;
442
+ display: flex;
443
+ align-items: center;
444
+ gap: 10px;
445
+ border: 1px solid var(--line);
446
+ border-radius: 8px;
447
+ background: var(--surface);
448
+ color: var(--text);
449
+ padding: 9px 10px;
450
+ font: inherit;
451
+ font-weight: 600;
452
+ text-align: left;
453
+ cursor: pointer;
454
+ }
455
+ .setup-step[aria-current="step"] {
456
+ border-color: var(--accent);
457
+ background: var(--accent-soft);
458
+ }
459
+ .setup-step:disabled {
460
+ opacity: 0.55;
461
+ cursor: not-allowed;
462
+ }
463
+ .step-dot {
464
+ width: 24px;
465
+ height: 24px;
466
+ border-radius: 50%;
467
+ display: inline-flex;
468
+ align-items: center;
469
+ justify-content: center;
470
+ background: var(--line);
471
+ color: var(--muted);
472
+ font-size: 12px;
473
+ flex: 0 0 auto;
474
+ }
475
+ .setup-step[data-status="done"] .step-dot {
476
+ background: var(--accent);
477
+ color: #fff;
478
+ }
479
+ .setup-pane {
480
+ min-width: 0;
481
+ display: flex;
482
+ flex-direction: column;
483
+ gap: 14px;
484
+ }
485
+ .setup-pane h2 {
486
+ margin: 0;
487
+ font-size: 18px;
488
+ font-weight: 650;
489
+ }
490
+ .pane-copy,
491
+ .locked-note {
492
+ margin: 0;
493
+ color: var(--muted);
494
+ font-size: 14px;
495
+ }
496
+ .locked-note { color: var(--warn); }
497
+ .row-list {
498
+ list-style: none;
499
+ margin: 0;
500
+ padding: 0;
501
+ border: 1px solid var(--line);
502
+ border-radius: 10px;
503
+ overflow: hidden;
504
+ }
505
+ .row-list .row {
506
+ display: flex;
507
+ gap: 10px;
508
+ align-items: center;
509
+ padding: 12px;
510
+ border-bottom: 1px solid var(--line);
511
+ }
512
+ .row-list .row:last-child { border-bottom: 0; }
513
+ .agent-grid,
514
+ .choice-grid {
515
+ display: grid;
516
+ grid-template-columns: repeat(2, minmax(0, 1fr));
517
+ gap: 12px;
518
+ }
519
+ .ready-strip {
520
+ background: var(--accent-soft);
521
+ border: 1px solid var(--accent);
522
+ color: var(--accent-strong);
523
+ border-radius: 8px;
524
+ padding: 10px 12px;
525
+ font-size: 13px;
526
+ font-weight: 600;
527
+ }
528
+ .ready-strip--muted {
529
+ background: var(--soft);
530
+ border-color: var(--line);
531
+ color: var(--muted);
532
+ }
533
+ .ready-strip--error {
534
+ background: #fff1f2;
535
+ border-color: #fb7185;
536
+ color: #9f1239;
537
+ }
538
+ .btn {
539
+ border-radius: 8px;
540
+ padding: 9px 14px;
541
+ font: inherit;
542
+ font-weight: 600;
543
+ cursor: pointer;
544
+ border: 1px solid var(--line);
545
+ align-self: flex-start;
546
+ }
547
+ .btn:disabled {
548
+ opacity: 0.55;
549
+ cursor: not-allowed;
550
+ }
551
+ .btn-primary {
552
+ background: var(--accent);
553
+ border-color: var(--accent);
554
+ color: #fff;
555
+ }
556
+ .btn-primary:hover { background: var(--accent-strong); }
557
+ .btn-secondary {
558
+ background: var(--surface);
559
+ color: var(--accent-strong);
560
+ }
561
+ .btn-secondary:hover {
562
+ border-color: var(--accent);
563
+ background: var(--soft);
564
+ }
565
+ .btn-ghost {
566
+ background: transparent;
567
+ color: var(--muted);
568
+ }
569
+ .modal-backdrop {
570
+ position: fixed;
571
+ inset: 0;
572
+ z-index: 1000;
573
+ display: flex;
574
+ align-items: center;
575
+ justify-content: center;
576
+ padding: 18px;
577
+ background: rgba(31, 42, 36, 0.36);
578
+ }
579
+ .modal {
580
+ width: min(520px, 100%);
581
+ background: var(--surface);
582
+ border: 1px solid var(--line);
583
+ border-radius: 12px;
584
+ box-shadow: var(--shadow-lg);
585
+ padding: 22px;
586
+ display: flex;
587
+ flex-direction: column;
588
+ gap: 14px;
589
+ }
590
+ .modal h2 {
591
+ margin: 0;
592
+ font-size: 19px;
593
+ }
594
+ .install-status {
595
+ margin: 0;
596
+ border: 1px solid var(--line);
597
+ background: var(--soft);
598
+ border-radius: 8px;
599
+ padding: 10px 12px;
600
+ color: var(--muted);
601
+ }
602
+ .install-status[data-tone="error"] {
603
+ color: var(--danger);
604
+ background: #fbf1f1;
605
+ border-color: var(--danger);
606
+ }
607
+ .modal-help {
608
+ margin: -4px 0 0;
609
+ color: var(--muted);
610
+ font-size: 13px;
611
+ line-height: 1.45;
612
+ }
613
+ .install-actions {
614
+ display: flex;
615
+ flex-wrap: wrap;
616
+ gap: 8px;
617
+ }
618
+
619
+ .recruit-container,
620
+ .start-container {
621
+ gap: 12px;
622
+ }
623
+
624
+ .start-container {
625
+ gap: 14px;
626
+ }
432
627
 
433
628
  .user-type-card {
434
629
  background: var(--surface);
@@ -448,23 +643,23 @@ body {
448
643
  border-color: var(--accent);
449
644
  background: var(--accent-soft);
450
645
  }
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
- }
646
+ .user-type-card--featured:hover {
647
+ box-shadow: 0 4px 20px rgba(61, 138, 110, 0.18);
648
+ }
649
+
650
+ .user-type-card--ide-default {
651
+ padding: 24px;
652
+ gap: 18px;
653
+ }
654
+
655
+ .user-type-card--compact {
656
+ padding: 16px 18px;
657
+ gap: 12px;
658
+ }
659
+
660
+ .user-type-card--alpha {
661
+ background: linear-gradient(180deg, #fbfcfa 0%, #f4f7f2 100%);
662
+ }
468
663
 
469
664
  .card-header {
470
665
  display: flex;
@@ -492,38 +687,38 @@ body {
492
687
  border-color: var(--accent);
493
688
  }
494
689
 
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
- }
690
+ .card-title {
691
+ display: block;
692
+ font-size: 15px;
693
+ font-weight: 600;
694
+ color: var(--text);
695
+ margin-bottom: 3px;
696
+ }
697
+ .card-desc { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.45; }
698
+
699
+ .card-eyebrow {
700
+ display: inline-flex;
701
+ align-self: flex-start;
702
+ padding: 4px 10px;
703
+ border-radius: 999px;
704
+ background: var(--accent-soft);
705
+ color: var(--accent-strong);
706
+ font-size: 11px;
707
+ font-weight: 700;
708
+ letter-spacing: 0.06em;
709
+ text-transform: uppercase;
710
+ }
711
+
712
+ .route-note {
713
+ margin: 0;
714
+ color: var(--muted);
715
+ font-size: 13px;
716
+ line-height: 1.5;
717
+ }
718
+
719
+ .route-note--compact {
720
+ font-size: 12px;
721
+ }
527
722
 
528
723
  .btn {
529
724
  display: inline-flex;
@@ -567,14 +762,25 @@ body {
567
762
  .recruit-card {
568
763
  cursor: default;
569
764
  }
765
+
766
+ .byoa-card {
767
+ grid-column: 1 / -1;
768
+ }
769
+
770
+ .byoa-card .cmd-block {
771
+ align-self: flex-start;
772
+ display: inline-block;
773
+ white-space: nowrap;
774
+ word-break: normal;
775
+ }
570
776
  .recruit-card:hover {
571
777
  box-shadow: none;
572
778
  border-color: var(--line);
573
779
  }
574
780
 
575
- /* IDE command display — shown after choosing "In my IDE". */
576
- .cmd-block {
577
- background: #0d1410;
781
+ /* IDE command display — shown after choosing "In my IDE". */
782
+ .cmd-block {
783
+ background: #0d1410;
578
784
  color: #c8d3cd;
579
785
  font-family: "JetBrains Mono", "Cascadia Code", Consolas, monospace;
580
786
  font-size: 14px;
@@ -612,16 +818,25 @@ body {
612
818
  * want the surface to degrade gracefully for users who happen to open it
613
819
  * in a narrow window. Stack the label / verb / change link vertically and
614
820
  * let the row breathe. */
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
- }
821
+ @media (max-width: 600px) {
822
+ .page { padding: 24px 16px 24px; }
823
+ .setup-shell { grid-template-columns: 1fr; }
824
+ .setup-steps {
825
+ border-right: 0;
826
+ border-bottom: 1px solid var(--line);
827
+ padding-right: 0;
828
+ padding-bottom: 12px;
829
+ }
830
+ .agent-grid,
831
+ .choice-grid { grid-template-columns: 1fr; }
832
+ .checklist .row { gap: 8px; padding: 12px 14px; }
833
+ .row .label { min-width: 0; }
834
+ .row .verb { flex: 1 1 100%; }
835
+ .row .change-link { margin-left: auto; }
836
+ .row .project-picker { gap: 8px; }
837
+ .row .project-picker input { width: 100%; min-width: 0; }
838
+ .user-type-card--ide-default,
839
+ .user-type-card--compact {
840
+ padding: 18px 16px;
841
+ }
842
+ }
@@ -1,121 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HUMAN_MANAGER_PROFILES = exports.AI_MANAGER_QUALITIES = exports.HIRING_SERVICES = void 0;
4
- exports.getHumanManagerProfile = getHumanManagerProfile;
5
- exports.buildSearchQuery = buildSearchQuery;
6
- exports.buildJobDescription = buildJobDescription;
7
- exports.buildServiceUrl = buildServiceUrl;
8
- exports.buildManagerHiringCatalog = buildManagerHiringCatalog;
9
- /**
10
- * Issue #538 — human-manager hiring engine (app side).
11
- *
12
- * Self-contained on purpose: the app (AI Hub UI modal + bootstrap) must resolve this
13
- * at runtime in every packaging context (dev tsx, compiled dist, packed CLI), so it
14
- * must NOT import across the app→registry boundary. The `hire-the-right-human-ai-manager`
15
- * job uses the mirror engine `registry/scripts/ai-manager-hiring.ts` (self-contained +
16
- * CLI). The two are kept identical by a parity test (tests/isolated/test-538-ai-manager-hiring.ts);
17
- * that is the DRY contract — one behavior, enforced, with no fragile cross-boundary import.
18
- */
19
- const persona_hiring_1 = require("./persona-hiring");
20
- exports.HIRING_SERVICES = ['linkedin', 'indeed', 'seekout'];
21
- /** The qualities of a strong AI manager — embedded in both the query and the JD. */
22
- exports.AI_MANAGER_QUALITIES = [
23
- { title: 'Clear specification & written communication', detail: 'Can brief an AI agent so it executes correctly the first time.' },
24
- { title: 'Trust-but-verify judgment', detail: 'Knows when to delegate to the agent and when to review deeply.' },
25
- { title: 'Coaching mindset', detail: 'Gives feedback that compounds into reusable rules and learnings.' },
26
- { title: 'Outcome ownership & AI fluency', detail: 'Owns results; comfortable directing autonomous agents.' },
27
- ];
28
- const GENERALIST_PROFILE = {
29
- humanTitle: 'Manager',
30
- keywords: ['"Manager"', '"Director"', '"Team Lead"', '"Chief of Staff"'],
31
- };
32
- /** Role key -> the human manager best suited to manage that AI employee. Mirror of registry/scripts/ai-manager-hiring.ts. */
33
- exports.HUMAN_MANAGER_PROFILES = {
34
- maestro: { humanTitle: 'Co-Founder / General Manager', keywords: ['"Co-Founder"', '"General Manager"', '"Chief of Staff"', '"Founder"'] },
35
- beza: { humanTitle: 'Head of Strategy', keywords: ['"Head of Strategy"', '"Strategy Director"', '"Chief of Staff"'] },
36
- pam: { humanTitle: 'Head of Product', keywords: ['"Head of Product"', '"Group Product Manager"', '"Director of Product"'] },
37
- swen: { humanTitle: 'Engineering Manager', keywords: ['"Engineering Manager"', '"Tech Lead"', '"Staff Software Engineer"'] },
38
- qasm: { humanTitle: 'QA Manager', keywords: ['"QA Manager"', '"QA Lead"', '"Head of Quality"'] },
39
- huxley: { humanTitle: 'Design Manager', keywords: ['"Design Manager"', '"Head of Design"', '"Design Lead"'] },
40
- gautam: { humanTitle: 'Marketing Director', keywords: ['"Head of Growth"', '"Marketing Director"', '"Demand Generation Lead"'] },
41
- cela: { humanTitle: 'General Counsel', keywords: ['"General Counsel"', '"Head of Legal"', '"Legal Director"'] },
42
- sekhar: { humanTitle: 'Security Manager', keywords: ['"Security Manager"', '"Head of Security"', '"CISO"'] },
43
- ashley: { humanTitle: 'Chief of Staff', keywords: ['"Chief of Staff"', '"Executive Operations Manager"', '"Office Manager"'] },
44
- mandy: { humanTitle: 'Head of Operations', keywords: ['"Head of Operations"', '"Director of Operations"', '"Program Manager"'] },
45
- ricardo: { humanTitle: 'Recruiting Manager', keywords: ['"Recruiting Manager"', '"Head of Talent"', '"Talent Acquisition Lead"'] },
46
- hari: { humanTitle: 'HR Manager', keywords: ['"HR Manager"', '"Head of People"', '"HR Business Partner"'] },
47
- careena: { humanTitle: 'Head of Talent Development', keywords: ['"Head of Talent Development"', '"L&D Manager"', '"Career Coaching Lead"'] },
48
- sade: { humanTitle: 'Salesforce Manager', keywords: ['"Salesforce Manager"', '"CRM Lead"', '"Salesforce Architect"'] },
49
- sam: { humanTitle: 'Sales Manager', keywords: ['"Sales Manager"', '"Head of Sales"', '"Director of Sales"'] },
50
- casey: { humanTitle: 'Customer Success Manager', keywords: ['"Customer Success Manager"', '"Head of Customer Success"', '"Support Manager"'] },
51
- deidre: { humanTitle: 'Head of DEI', keywords: ['"Head of DEI"', '"Director of Inclusion"', '"DEI Program Manager"'] },
52
- mona: { humanTitle: 'Finance Manager', keywords: ['"Finance Manager"', '"Head of Finance"', '"Controller"'] },
53
- sreya: { humanTitle: 'SRE Manager', keywords: ['"SRE Manager"', '"Head of Reliability"', '"Platform Engineering Lead"'] },
54
- procella: { humanTitle: 'Procurement Manager', keywords: ['"Procurement Manager"', '"Head of Procurement"', '"Sourcing Lead"'] },
55
- banke: { humanTitle: 'KYC Operations Manager', keywords: ['"KYC Operations Manager"', '"AML Compliance Manager"', '"Banking Compliance Lead"'] },
56
- auditya: { humanTitle: 'Audit Manager', keywords: ['"Audit Manager"', '"Internal Audit Lead"', '"Compliance Audit Manager"'] },
57
- };
58
- function getHumanManagerProfile(roleKey) {
59
- return exports.HUMAN_MANAGER_PROFILES[roleKey] ?? GENERALIST_PROFILE;
60
- }
61
- const AI_MANAGER_QUERY_TERMS = '("AI" OR "LLM" OR "agentic") AND ("coaching" OR "mentoring")';
62
- function buildSearchQuery(roleKey) {
63
- const profile = getHumanManagerProfile(roleKey);
64
- return `${profile.keywords.join(' OR ')} AND ${AI_MANAGER_QUERY_TERMS}`;
65
- }
66
- function buildJobDescription(roleKey) {
67
- const profile = getHumanManagerProfile(roleKey);
68
- const role = persona_hiring_1.PERSONA_HIRE_CATALOG[roleKey]?.role ?? 'AI Employee';
69
- return [
70
- `${profile.humanTitle} — manager for an ${role}`,
71
- '',
72
- `You will manage an ${role} (an autonomous AI agent) and the humans around it, owning the outcomes it ships.`,
73
- '',
74
- "What you'll do:",
75
- `- Write crisp specifications and acceptance criteria the ${role} can execute against.`,
76
- `- Review the agent's output with judgment: know when to trust it and when to dig in.`,
77
- '- Coach the agent and team so feedback compounds into reusable rules.',
78
- '- Own delivery outcomes, not activity; prioritize ruthlessly.',
79
- '',
80
- 'What makes a strong AI manager:',
81
- ...exports.AI_MANAGER_QUALITIES.map((q) => `- ${q.title}: ${q.detail}`),
82
- ].join('\n');
83
- }
84
- function buildServiceUrl(service, query, location) {
85
- const q = encodeURIComponent(query);
86
- const loc = location && location.trim().length > 0 ? location.trim() : '';
87
- switch (service) {
88
- case 'linkedin':
89
- return `https://www.linkedin.com/search/results/people/?keywords=${q}`;
90
- case 'indeed':
91
- return `https://www.indeed.com/jobs?q=${q}${loc ? `&l=${encodeURIComponent(loc)}` : ''}`;
92
- case 'seekout':
93
- return 'https://app.seekout.com/';
94
- }
95
- }
96
- /**
97
- * Catalog projection for the AI Hub bootstrap so the client renders off the server's
98
- * source of truth. Defaults to exactly the hireable personas in `PERSONA_HIRE_CATALOG`.
99
- */
100
- function buildManagerHiringCatalog(roleKeys = Object.keys(persona_hiring_1.PERSONA_HIRE_CATALOG)) {
101
- const roles = {};
102
- for (const key of roleKeys) {
103
- const profile = getHumanManagerProfile(key);
104
- const query = buildSearchQuery(key);
105
- // managedRole is derived from PERSONA_HIRE_CATALOG so the bootstrap response
106
- // shape is unchanged even after removing the field from HumanManagerProfile.
107
- const managedRole = persona_hiring_1.PERSONA_HIRE_CATALOG[key]?.role ?? 'AI Employee';
108
- roles[key] = {
109
- ...profile,
110
- managedRole,
111
- query,
112
- jobDescription: buildJobDescription(key),
113
- serviceUrls: {
114
- linkedin: buildServiceUrl('linkedin', query),
115
- indeed: buildServiceUrl('indeed', query),
116
- seekout: buildServiceUrl('seekout', query),
117
- },
118
- };
119
- }
120
- return { qualities: exports.AI_MANAGER_QUALITIES, services: exports.HIRING_SERVICES, roles };
121
- }
@@ -1,16 +0,0 @@
1
- "use strict";
2
- /**
3
- * Compatibility configuration for FRAIM.
4
- * This file defines breaking changes and minimum required versions for clients.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.getBreakingChangesNotice = exports.MINIMUM_CLIENT_VERSION = void 0;
8
- exports.MINIMUM_CLIENT_VERSION = '2.0.94';
9
- /**
10
- * Notice template for clients running outdated versions.
11
- * This is appended to tool responses to guide users toward the standardized setup.
12
- */
13
- const getBreakingChangesNotice = (currentVersion) => {
14
- return `\n\n---\n\n> [!WARNING] migration_notice\n> **Action Required**: You are using an outdated FRAIM configuration (v${currentVersion}). FRAIM requires at least v${exports.MINIMUM_CLIENT_VERSION}.\n> \n> To fix this permanently so you never have to update again, please run this terminal command **once**:\n> \`\`\`bash\n> npx fraim@latest setup\n> \`\`\`\n> Then restart your IDE.`;
15
- };
16
- exports.getBreakingChangesNotice = getBreakingChangesNotice;
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFeatureFlags = getFeatureFlags;
4
- exports.isPersonaEntitlementsEnabled = isPersonaEntitlementsEnabled;
5
- exports.getPublicFeatureFlags = getPublicFeatureFlags;
6
- function parseBooleanFlag(value) {
7
- if (!value)
8
- return false;
9
- return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase());
10
- }
11
- function getFeatureFlags() {
12
- return {
13
- personaEntitlements: {
14
- enabled: parseBooleanFlag(process.env.FRAIM_FF_PERSONA_ENTITLEMENTS)
15
- }
16
- };
17
- }
18
- function isPersonaEntitlementsEnabled() {
19
- return getFeatureFlags().personaEntitlements.enabled;
20
- }
21
- function getPublicFeatureFlags() {
22
- return {
23
- personaEntitlementsEnabled: isPersonaEntitlementsEnabled()
24
- };
25
- }