@sideboard-ai/core 0.1.19 → 0.1.23

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.
@@ -448,13 +448,383 @@ var init_thread_store = __esm({
448
448
  }
449
449
  });
450
450
 
451
+ // src/git/team-meta.ts
452
+ var SOCCER_TEAM_META;
453
+ var init_team_meta = __esm({
454
+ "src/git/team-meta.ts"() {
455
+ "use strict";
456
+ SOCCER_TEAM_META = {
457
+ "aalborg": { location: "Aalborg, Denmark", league: "Danish Superliga" },
458
+ "aalesund": { location: "\xC5lesund, Norway", league: "Norwegian First Division" },
459
+ "aarhus": { location: "Aarhus, Denmark", league: "Danish Superliga" },
460
+ "aberdeen": { location: "Aberdeen, Scotland", league: "Scottish Premiership" },
461
+ "ac-milan": { location: "Milan, Italy", league: "Serie A" },
462
+ "ado-den-haag": { location: "The Hague, Netherlands", league: "Eerste Divisie" },
463
+ "aik": { location: "Stockholm, Sweden", league: "Allsvenskan" },
464
+ "ajaccio": { location: "Ajaccio, France", league: "Ligue 2" },
465
+ "ajax": { location: "Amsterdam, Netherlands", league: "Eredivisie" },
466
+ "al-ahly": { location: "Cairo, Egypt", league: "Egyptian Premier League" },
467
+ "al-hilal": { location: "Riyadh, Saudi Arabia", league: "Saudi Pro League" },
468
+ "alajuelense": { location: "Alajuela, Costa Rica", league: "Liga FPD" },
469
+ "almere-city": { location: "Almere, Netherlands", league: "Eredivisie" },
470
+ "amiens": { location: "Amiens, France", league: "Ligue 2" },
471
+ "angers": { location: "Angers, France", league: "Ligue 1" },
472
+ "anyang": { location: "Anyang, South Korea", league: "K League 1" },
473
+ "argentinos-juniors": { location: "Buenos Aires, Argentina", league: "Argentine Primera Divisi\xF3n" },
474
+ "arsenal": { location: "London, England", league: "Premier League" },
475
+ "aston-villa": { location: "Birmingham, England", league: "Premier League" },
476
+ "athletico-paranaense": { location: "Curitiba, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
477
+ "atlanta-united": { location: "Atlanta, USA", league: "MLS" },
478
+ "atlas": { location: "Guadalajara, Mexico", league: "Liga MX" },
479
+ "atletico-madrid": { location: "Madrid, Spain", league: "La Liga" },
480
+ "atletico-mineiro": { location: "Belo Horizonte, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
481
+ "atletico-san-luis": { location: "San Luis Potos\xED, Mexico", league: "Liga MX" },
482
+ "augsburg": { location: "Augsburg, Germany", league: "Bundesliga" },
483
+ "austin-fc": { location: "Austin, USA", league: "MLS" },
484
+ "auxerre": { location: "Auxerre, France", league: "Ligue 1" },
485
+ "avispa-fukuoka": { location: "Fukuoka, Japan", league: "J1 League" },
486
+ "az": { location: "Alkmaar, Netherlands", league: "Eredivisie" },
487
+ "bahia": { location: "Salvador, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
488
+ "banfield": { location: "Banfield, Argentina", league: "Argentine Primera Divisi\xF3n" },
489
+ "barcelona": { location: "Barcelona, Spain", league: "La Liga" },
490
+ "bayer-leverkusen": { location: "Leverkusen, Germany", league: "Bundesliga" },
491
+ "bayern-munich": { location: "Munich, Germany", league: "Bundesliga" },
492
+ "belgrano": { location: "C\xF3rdoba, Argentina", league: "Argentine Primera Divisi\xF3n" },
493
+ "benfica": { location: "Lisbon, Portugal", league: "Primeira Liga" },
494
+ "birmingham-legion": { location: "Birmingham, USA", league: "USL Championship" },
495
+ "boca-juniors": { location: "Buenos Aires, Argentina", league: "Argentine Primera Divisi\xF3n" },
496
+ "bodo-glimt": { location: "Bod\xF8, Norway", league: "Eliteserien" },
497
+ "bordeaux": { location: "Bordeaux, France", league: "Championnat National" },
498
+ "borussia-dortmund": { location: "Dortmund, Germany", league: "Bundesliga" },
499
+ "botafogo": { location: "Rio de Janeiro, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
500
+ "bragantino": { location: "Bragan\xE7a Paulista, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
501
+ "brann": { location: "Bergen, Norway", league: "Eliteserien" },
502
+ "brest": { location: "Brest, France", league: "Ligue 1" },
503
+ "brommapojkarna": { location: "Stockholm, Sweden", league: "Allsvenskan" },
504
+ "brondby": { location: "Br\xF8ndby, Denmark", league: "Danish Superliga" },
505
+ "brooklyn-fc": { location: "Brooklyn, USA", league: "USL Championship" },
506
+ "bucheon": { location: "Bucheon, South Korea", league: "K League 2" },
507
+ "caen": { location: "Caen, France", league: "Ligue 2" },
508
+ "cambuur": { location: "Leeuwarden, Netherlands", league: "Eerste Divisie" },
509
+ "carmelita": { location: "Alajuela, Costa Rica", league: "Liga de Ascenso" },
510
+ "cartagines": { location: "Cartago, Costa Rica", league: "Liga FPD" },
511
+ "ceara": { location: "Fortaleza, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
512
+ "celtic": { location: "Glasgow, Scotland", league: "Scottish Premiership" },
513
+ "central-cordoba": { location: "Santiago del Estero, Argentina", league: "Argentine Primera Divisi\xF3n" },
514
+ "cerezo-osaka": { location: "Osaka, Japan", league: "J1 League" },
515
+ "cf-montreal": { location: "Montreal, Canada", league: "MLS" },
516
+ "charleston-battery": { location: "Charleston, USA", league: "USL Championship" },
517
+ "charlotte-fc": { location: "Charlotte, USA", league: "MLS" },
518
+ "chelsea": { location: "London, England", league: "Premier League" },
519
+ "chicago-fire": { location: "Chicago, USA", league: "MLS" },
520
+ "chivas": { location: "Guadalajara, Mexico", league: "Liga MX" },
521
+ "clermont": { location: "Clermont-Ferrand, France", league: "Ligue 2" },
522
+ "club-america": { location: "Mexico City, Mexico", league: "Liga MX" },
523
+ "cologne": { location: "Cologne, Germany", league: "Bundesliga" },
524
+ "colorado-rapids": { location: "Commerce City, USA", league: "MLS" },
525
+ "columbus-crew": { location: "Columbus, USA", league: "MLS" },
526
+ "corinthians": { location: "S\xE3o Paulo, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
527
+ "cruz-azul": { location: "Mexico City, Mexico", league: "Liga MX" },
528
+ "cruzeiro": { location: "Belo Horizonte, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
529
+ "daejeon": { location: "Daejeon, South Korea", league: "K League 1" },
530
+ "dc-united": { location: "Washington, D.C., USA", league: "MLS" },
531
+ "defensa-y-justicia": { location: "Florencio Varela, Argentina", league: "Argentine Primera Divisi\xF3n" },
532
+ "degerfors": { location: "Degerfors, Sweden", league: "Allsvenskan" },
533
+ "detroit-city": { location: "Detroit, USA", league: "USL Championship" },
534
+ "dijon": { location: "Dijon, France", league: "Championnat National" },
535
+ "djurgarden": { location: "Stockholm, Sweden", league: "Allsvenskan" },
536
+ "dundee": { location: "Dundee, Scotland", league: "Scottish Premiership" },
537
+ "dundee-united": { location: "Dundee, Scotland", league: "Scottish Premiership" },
538
+ "dynamo-kyiv": { location: "Kyiv, Ukraine", league: "Ukrainian Premier League" },
539
+ "eintracht-frankfurt": { location: "Frankfurt, Germany", league: "Bundesliga" },
540
+ "el-paso-locomotive": { location: "El Paso, USA", league: "USL Championship" },
541
+ "elfsborg": { location: "Bor\xE5s, Sweden", league: "Allsvenskan" },
542
+ "emmen": { location: "Emmen, Netherlands", league: "Eerste Divisie" },
543
+ "esbjerg": { location: "Esbjerg, Denmark", league: "Danish 1st Division" },
544
+ "estudiantes": { location: "La Plata, Argentina", league: "Argentine Primera Divisi\xF3n" },
545
+ "everton": { location: "Liverpool, England", league: "Premier League" },
546
+ "excelsior": { location: "Rotterdam, Netherlands", league: "Eerste Divisie" },
547
+ "fagiano-okayama": { location: "Okayama, Japan", league: "J1 League" },
548
+ "falkirk": { location: "Falkirk, Scotland", league: "Scottish Championship" },
549
+ "fc-cincinnati": { location: "Cincinnati, USA", league: "MLS" },
550
+ "fc-copenhagen": { location: "Copenhagen, Denmark", league: "Danish Superliga" },
551
+ "fc-dallas": { location: "Frisco, USA", league: "MLS" },
552
+ "fc-seoul": { location: "Seoul, South Korea", league: "K League 1" },
553
+ "fc-tokyo": { location: "Tokyo, Japan", league: "J1 League" },
554
+ "fc-tulsa": { location: "Tulsa, USA", league: "USL Championship" },
555
+ "feyenoord": { location: "Rotterdam, Netherlands", league: "Eredivisie" },
556
+ "flamengo": { location: "Rio de Janeiro, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
557
+ "fluminense": { location: "Rio de Janeiro, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
558
+ "fortaleza": { location: "Fortaleza, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
559
+ "fortuna-sittard": { location: "Sittard, Netherlands", league: "Eredivisie" },
560
+ "fredrikstad": { location: "Fredrikstad, Norway", league: "Eliteserien" },
561
+ "freiburg": { location: "Freiburg, Germany", league: "Bundesliga" },
562
+ "gais": { location: "Gothenburg, Sweden", league: "Allsvenskan" },
563
+ "galatasaray": { location: "Istanbul, Turkey", league: "S\xFCper Lig" },
564
+ "gamba-osaka": { location: "Osaka, Japan", league: "J1 League" },
565
+ "gangwon": { location: "Gangneung, South Korea", league: "K League 1" },
566
+ "gimcheon-sangmu": { location: "Gimcheon, South Korea", league: "K League 1" },
567
+ "gimnasia": { location: "La Plata, Argentina", league: "Argentine Primera Divisi\xF3n" },
568
+ "gladbach": { location: "M\xF6nchengladbach, Germany", league: "Bundesliga" },
569
+ "go-ahead-eagles": { location: "Deventer, Netherlands", league: "Eredivisie" },
570
+ "godoy-cruz": { location: "Mendoza, Argentina", league: "Argentine Primera Divisi\xF3n" },
571
+ "gremio": { location: "Porto Alegre, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
572
+ "groningen": { location: "Groningen, Netherlands", league: "Eredivisie" },
573
+ "guadalupe": { location: "Goicoechea, Costa Rica", league: "Liga de Ascenso" },
574
+ "guanacasteca": { location: "Nicoya, Costa Rica", league: "Liga FPD" },
575
+ "guingamp": { location: "Guingamp, France", league: "Ligue 2" },
576
+ "gwangju": { location: "Gwangju, South Korea", league: "K League 1" },
577
+ "hacken": { location: "Gothenburg, Sweden", league: "Allsvenskan" },
578
+ "halmstad": { location: "Halmstad, Sweden", league: "Allsvenskan" },
579
+ "hamburg": { location: "Hamburg, Germany", league: "2. Bundesliga" },
580
+ "hammarby": { location: "Stockholm, Sweden", league: "Allsvenskan" },
581
+ "hartford-athletic": { location: "Hartford, USA", league: "USL Championship" },
582
+ "haugesund": { location: "Haugesund, Norway", league: "Eliteserien" },
583
+ "hearts": { location: "Edinburgh, Scotland", league: "Scottish Premiership" },
584
+ "heerenveen": { location: "Heerenveen, Netherlands", league: "Eredivisie" },
585
+ "heidenheim": { location: "Heidenheim, Germany", league: "Bundesliga" },
586
+ "helsingborg": { location: "Helsingborg, Sweden", league: "Superettan" },
587
+ "heracles": { location: "Almelo, Netherlands", league: "Eredivisie" },
588
+ "herediano": { location: "Heredia, Costa Rica", league: "Liga FPD" },
589
+ "hibernian": { location: "Edinburgh, Scotland", league: "Scottish Premiership" },
590
+ "hoffenheim": { location: "Sinsheim, Germany", league: "Bundesliga" },
591
+ "horsens": { location: "Horsens, Denmark", league: "Danish 1st Division" },
592
+ "houston-dynamo": { location: "Houston, USA", league: "MLS" },
593
+ "huracan": { location: "Buenos Aires, Argentina", league: "Argentine Primera Divisi\xF3n" },
594
+ "ifk-goteborg": { location: "Gothenburg, Sweden", league: "Allsvenskan" },
595
+ "norrkoping": { location: "Norrk\xF6ping, Sweden", league: "Allsvenskan" },
596
+ "incheon-united": { location: "Incheon, South Korea", league: "K League 1" },
597
+ "independiente": { location: "Avellaneda, Argentina", league: "Argentine Primera Divisi\xF3n" },
598
+ "indy-eleven": { location: "Indianapolis, USA", league: "USL Championship" },
599
+ "instituto": { location: "C\xF3rdoba, Argentina", league: "Argentine Primera Divisi\xF3n" },
600
+ "inter-miami": { location: "Fort Lauderdale, USA", league: "MLS" },
601
+ "inter-milan": { location: "Milan, Italy", league: "Serie A" },
602
+ "internacional": { location: "Porto Alegre, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
603
+ "jef-united": { location: "Chiba, Japan", league: "J2 League" },
604
+ "jeju-sk": { location: "Jeju, South Korea", league: "K League 1" },
605
+ "jeonbuk": { location: "Jeonju, South Korea", league: "K League 1" },
606
+ "juarez": { location: "Ciudad Ju\xE1rez, Mexico", league: "Liga MX" },
607
+ "juventude": { location: "Caxias do Sul, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
608
+ "juventus": { location: "Turin, Italy", league: "Serie A" },
609
+ "kalmar": { location: "Kalmar, Sweden", league: "Superettan" },
610
+ "kashima-antlers": { location: "Kashima, Japan", league: "J1 League" },
611
+ "kashiwa-reysol": { location: "Kashiwa, Japan", league: "J1 League" },
612
+ "kawasaki-frontale": { location: "Kawasaki, Japan", league: "J1 League" },
613
+ "kfum-oslo": { location: "Oslo, Norway", league: "Eliteserien" },
614
+ "kilmarnock": { location: "Kilmarnock, Scotland", league: "Scottish Premiership" },
615
+ "kristiansund": { location: "Kristiansund, Norway", league: "Eliteserien" },
616
+ "kyoto-sanga": { location: "Kyoto, Japan", league: "J1 League" },
617
+ "la-galaxy": { location: "Carson, USA", league: "MLS" },
618
+ "lafc": { location: "Los Angeles, USA", league: "MLS" },
619
+ "lanus": { location: "Lan\xFAs, Argentina", league: "Argentine Primera Divisi\xF3n" },
620
+ "las-vegas-lights": { location: "Las Vegas, USA", league: "USL Championship" },
621
+ "lazio": { location: "Rome, Italy", league: "Serie A" },
622
+ "le-havre": { location: "Le Havre, France", league: "Ligue 1" },
623
+ "le-mans": { location: "Le Mans, France", league: "Ligue 2" },
624
+ "leeds-united": { location: "Leeds, England", league: "Premier League" },
625
+ "leicester-city": { location: "Leicester, England", league: "Championship" },
626
+ "lens": { location: "Lens, France", league: "Ligue 1" },
627
+ "leon": { location: "Le\xF3n, Mexico", league: "Liga MX" },
628
+ "lexington-sc": { location: "Lexington, USA", league: "USL Championship" },
629
+ "liberia": { location: "Liberia, Costa Rica", league: "Liga FPD" },
630
+ "lille": { location: "Lille, France", league: "Ligue 1" },
631
+ "lillestrom": { location: "Lillestr\xF8m, Norway", league: "Eliteserien" },
632
+ "limon": { location: "Lim\xF3n, Costa Rica", league: "Liga de Ascenso" },
633
+ "liverpool": { location: "Liverpool, England", league: "Premier League" },
634
+ "livingston": { location: "Livingston, Scotland", league: "Scottish Championship" },
635
+ "lorient": { location: "Lorient, France", league: "Ligue 1" },
636
+ "loudoun-united": { location: "Leesburg, USA", league: "USL Championship" },
637
+ "louisville-city": { location: "Louisville, USA", league: "USL Championship" },
638
+ "lyngby": { location: "Kongens Lyngby, Denmark", league: "Danish Superliga" },
639
+ "lyon": { location: "Lyon, France", league: "Ligue 1" },
640
+ "machida-zelvia": { location: "Machida, Japan", league: "J1 League" },
641
+ "mainz": { location: "Mainz, Germany", league: "Bundesliga" },
642
+ "malmo": { location: "Malm\xF6, Sweden", league: "Allsvenskan" },
643
+ "manchester-city": { location: "Manchester, England", league: "Premier League" },
644
+ "manchester-united": { location: "Manchester, England", league: "Premier League" },
645
+ "marseille": { location: "Marseille, France", league: "Ligue 1" },
646
+ "mazatlan": { location: "Mazatl\xE1n, Mexico", league: "Liga MX" },
647
+ "metz": { location: "Metz, France", league: "Ligue 1" },
648
+ "miami-fc": { location: "Miami, USA", league: "USL Championship" },
649
+ "midtjylland": { location: "Herning, Denmark", league: "Danish Superliga" },
650
+ "minnesota-united": { location: "Saint Paul, USA", league: "MLS" },
651
+ "mirassol": { location: "Mirassol, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
652
+ "mito-hollyhock": { location: "Mito, Japan", league: "J2 League" },
653
+ "mjallby": { location: "H\xE4llevik, Sweden", league: "Allsvenskan" },
654
+ "molde": { location: "Molde, Norway", league: "Eliteserien" },
655
+ "monaco": { location: "Monaco", league: "Ligue 1" },
656
+ "monterey-bay": { location: "Monterey, USA", league: "USL Championship" },
657
+ "monterrey": { location: "Monterrey, Mexico", league: "Liga MX" },
658
+ "montpellier": { location: "Montpellier, France", league: "Ligue 2" },
659
+ "motherwell": { location: "Motherwell, Scotland", league: "Scottish Premiership" },
660
+ "grecia": { location: "Grecia, Costa Rica", league: "Liga de Ascenso" },
661
+ "nac-breda": { location: "Breda, Netherlands", league: "Eredivisie" },
662
+ "nagoya-grampus": { location: "Nagoya, Japan", league: "J1 League" },
663
+ "nancy": { location: "Nancy, France", league: "Ligue 2" },
664
+ "nantes": { location: "Nantes, France", league: "Ligue 1" },
665
+ "napoli": { location: "Naples, Italy", league: "Serie A" },
666
+ "nashville-sc": { location: "Nashville, USA", league: "MLS" },
667
+ "nec": { location: "Nijmegen, Netherlands", league: "Eredivisie" },
668
+ "necaxa": { location: "Aguascalientes, Mexico", league: "Liga MX" },
669
+ "new-england": { location: "Foxborough, USA", league: "MLS" },
670
+ "new-mexico-united": { location: "Albuquerque, USA", league: "USL Championship" },
671
+ "newcastle": { location: "Newcastle, England", league: "Premier League" },
672
+ "newells": { location: "Rosario, Argentina", league: "Argentine Primera Divisi\xF3n" },
673
+ "nice": { location: "Nice, France", league: "Ligue 1" },
674
+ "nimes": { location: "N\xEEmes, France", league: "Championnat National" },
675
+ "nordsjaelland": { location: "Farum, Denmark", league: "Danish Superliga" },
676
+ "ny-red-bulls": { location: "Harrison, USA", league: "MLS" },
677
+ "nycfc": { location: "New York City, USA", league: "MLS" },
678
+ "oakland-roots": { location: "Oakland, USA", league: "USL Championship" },
679
+ "ob-odense": { location: "Odense, Denmark", league: "Danish Superliga" },
680
+ "odd": { location: "Skien, Norway", league: "Norwegian First Division" },
681
+ "olympiacos": { location: "Piraeus, Greece", league: "Super League Greece" },
682
+ "orange-county-sc": { location: "Irvine, USA", league: "USL Championship" },
683
+ "orebro": { location: "\xD6rebro, Sweden", league: "Superettan" },
684
+ "orlando-city": { location: "Orlando, USA", league: "MLS" },
685
+ "pachuca": { location: "Pachuca, Mexico", league: "Liga MX" },
686
+ "palmeiras": { location: "S\xE3o Paulo, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
687
+ "paris-fc": { location: "Paris, France", league: "Ligue 1" },
688
+ "psg": { location: "Paris, France", league: "Ligue 1" },
689
+ "pec-zwolle": { location: "Zwolle, Netherlands", league: "Eredivisie" },
690
+ "perez-zeledon": { location: "San Isidro, Costa Rica", league: "Liga FPD" },
691
+ "philadelphia-union": { location: "Chester, USA", league: "MLS" },
692
+ "phoenix-rising": { location: "Phoenix, USA", league: "USL Championship" },
693
+ "pittsburgh-riverhounds": { location: "Pittsburgh, USA", league: "USL Championship" },
694
+ "platense": { location: "Florida, Argentina", league: "Argentine Primera Divisi\xF3n" },
695
+ "pohang-steelers": { location: "Pohang, South Korea", league: "K League 1" },
696
+ "portland-timbers": { location: "Portland, USA", league: "MLS" },
697
+ "porto": { location: "Porto, Portugal", league: "Primeira Liga" },
698
+ "psv": { location: "Eindhoven, Netherlands", league: "Eredivisie" },
699
+ "puebla": { location: "Puebla, Mexico", league: "Liga MX" },
700
+ "pumas": { location: "Mexico City, Mexico", league: "Liga MX" },
701
+ "puntarenas": { location: "Puntarenas, Costa Rica", league: "Liga FPD" },
702
+ "queretaro": { location: "Quer\xE9taro, Mexico", league: "Liga MX" },
703
+ "racing": { location: "Avellaneda, Argentina", league: "Argentine Primera Divisi\xF3n" },
704
+ "randers": { location: "Randers, Denmark", league: "Danish Superliga" },
705
+ "rangers": { location: "Glasgow, Scotland", league: "Scottish Premiership" },
706
+ "rb-leipzig": { location: "Leipzig, Germany", league: "Bundesliga" },
707
+ "real-madrid": { location: "Madrid, Spain", league: "La Liga" },
708
+ "real-salt-lake": { location: "Sandy, USA", league: "MLS" },
709
+ "red-star": { location: "Saint-Ouen, France", league: "Ligue 2" },
710
+ "reims": { location: "Reims, France", league: "Ligue 2" },
711
+ "rennes": { location: "Rennes, France", league: "Ligue 1" },
712
+ "rhode-island-fc": { location: "Pawtucket, USA", league: "USL Championship" },
713
+ "river-plate": { location: "Buenos Aires, Argentina", league: "Argentine Primera Divisi\xF3n" },
714
+ "rkc": { location: "Waalwijk, Netherlands", league: "Eredivisie" },
715
+ "roma": { location: "Rome, Italy", league: "Serie A" },
716
+ "rosario-central": { location: "Rosario, Argentina", league: "Argentine Primera Divisi\xF3n" },
717
+ "rosenborg": { location: "Trondheim, Norway", league: "Eliteserien" },
718
+ "sacramento-republic": { location: "Sacramento, USA", league: "USL Championship" },
719
+ "saint-etienne": { location: "Saint-\xC9tienne, France", league: "Ligue 2" },
720
+ "san-antonio-fc": { location: "San Antonio, USA", league: "USL Championship" },
721
+ "san-carlos": { location: "Quesada, Costa Rica", league: "Liga FPD" },
722
+ "san-diego-fc": { location: "San Diego, USA", league: "MLS" },
723
+ "san-jose-earthquakes": { location: "San Jose, USA", league: "MLS" },
724
+ "san-lorenzo": { location: "Buenos Aires, Argentina", league: "Argentine Primera Divisi\xF3n" },
725
+ "sanfrecce-hiroshima": { location: "Hiroshima, Japan", league: "J1 League" },
726
+ "santos": { location: "Santos, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
727
+ "santos-guapiles": { location: "Gu\xE1piles, Costa Rica", league: "Liga FPD" },
728
+ "santos-laguna": { location: "Torre\xF3n, Mexico", league: "Liga MX" },
729
+ "sao-paulo": { location: "S\xE3o Paulo, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
730
+ "saprissa": { location: "San Jos\xE9, Costa Rica", league: "Liga FPD" },
731
+ "sarpsborg": { location: "Sarpsborg, Norway", league: "Eliteserien" },
732
+ "schalke": { location: "Gelsenkirchen, Germany", league: "2. Bundesliga" },
733
+ "seattle-sounders": { location: "Seattle, USA", league: "MLS" },
734
+ "sevilla": { location: "Seville, Spain", league: "La Liga" },
735
+ "shakhtar": { location: "Donetsk, Ukraine", league: "Ukrainian Premier League" },
736
+ "shimizu-s-pulse": { location: "Shizuoka, Japan", league: "J1 League" },
737
+ "silkeborg": { location: "Silkeborg, Denmark", league: "Danish Superliga" },
738
+ "sirius": { location: "Uppsala, Sweden", league: "Allsvenskan" },
739
+ "sochaux": { location: "Montb\xE9liard, France", league: "Championnat National" },
740
+ "sonderjyske": { location: "Haderslev, Denmark", league: "Danish Superliga" },
741
+ "sparta-rotterdam": { location: "Rotterdam, Netherlands", league: "Eredivisie" },
742
+ "sport-recife": { location: "Recife, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
743
+ "sporting": { location: "Lisbon, Portugal", league: "Primeira Liga" },
744
+ "sporting-jax": { location: "Jacksonville, USA", league: "MLS Next Pro" },
745
+ "sporting-kc": { location: "Kansas City, USA", league: "MLS" },
746
+ "sporting-san-jose": { location: "San Jos\xE9, Costa Rica", league: "Liga FPD" },
747
+ "st-mirren": { location: "Paisley, Scotland", league: "Scottish Premiership" },
748
+ "st-louis-city": { location: "St. Louis, USA", league: "MLS" },
749
+ "st-pauli": { location: "Hamburg, Germany", league: "Bundesliga" },
750
+ "stabaek": { location: "B\xE6rum, Norway", league: "Norwegian First Division" },
751
+ "strasbourg": { location: "Strasbourg, France", league: "Ligue 1" },
752
+ "stromsgodset": { location: "Drammen, Norway", league: "Eliteserien" },
753
+ "stuttgart": { location: "Stuttgart, Germany", league: "Bundesliga" },
754
+ "switchbacks": { location: "Colorado Springs, USA", league: "USL Championship" },
755
+ "talleres": { location: "C\xF3rdoba, Argentina", league: "Argentine Primera Divisi\xF3n" },
756
+ "tampa-bay-rowdies": { location: "St. Petersburg, USA", league: "USL Championship" },
757
+ "tigre": { location: "Victoria, Argentina", league: "Argentine Primera Divisi\xF3n" },
758
+ "tigres": { location: "San Nicol\xE1s de los Garza, Mexico", league: "Liga MX" },
759
+ "tijuana": { location: "Tijuana, Mexico", league: "Liga MX" },
760
+ "tokyo-verdy": { location: "Tokyo, Japan", league: "J1 League" },
761
+ "toluca": { location: "Toluca, Mexico", league: "Liga MX" },
762
+ "toronto-fc": { location: "Toronto, Canada", league: "MLS" },
763
+ "tottenham": { location: "London, England", league: "Premier League" },
764
+ "toulouse": { location: "Toulouse, France", league: "Ligue 1" },
765
+ "tromso": { location: "Troms\xF8, Norway", league: "Eliteserien" },
766
+ "troyes": { location: "Troyes, France", league: "Ligue 2" },
767
+ "twente": { location: "Enschede, Netherlands", league: "Eredivisie" },
768
+ "ulsan-hd": { location: "Ulsan, South Korea", league: "K League 1" },
769
+ "union": { location: "Santa Fe, Argentina", league: "Argentine Primera Divisi\xF3n" },
770
+ "union-berlin": { location: "Berlin, Germany", league: "Bundesliga" },
771
+ "urawa-reds": { location: "Saitama, Japan", league: "J1 League" },
772
+ "utrecht": { location: "Utrecht, Netherlands", league: "Eredivisie" },
773
+ "v-varen-nagasaki": { location: "Nagasaki, Japan", league: "J2 League" },
774
+ "valencia": { location: "Valencia, Spain", league: "La Liga" },
775
+ "valerenga": { location: "Oslo, Norway", league: "Eliteserien" },
776
+ "vancouver-whitecaps": { location: "Vancouver, Canada", league: "MLS" },
777
+ "varnamo": { location: "V\xE4rnamo, Sweden", league: "Allsvenskan" },
778
+ "vasco": { location: "Rio de Janeiro, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
779
+ "vejle": { location: "Vejle, Denmark", league: "Danish Superliga" },
780
+ "velez": { location: "Buenos Aires, Argentina", league: "Argentine Primera Divisi\xF3n" },
781
+ "viborg": { location: "Viborg, Denmark", league: "Danish Superliga" },
782
+ "viking": { location: "Stavanger, Norway", league: "Eliteserien" },
783
+ "vissel-kobe": { location: "Kobe, Japan", league: "J1 League" },
784
+ "vitesse": { location: "Arnhem, Netherlands", league: "Eerste Divisie" },
785
+ "vitoria": { location: "Salvador, Brazil", league: "Brasileir\xE3o S\xE9rie A" },
786
+ "volendam": { location: "Volendam, Netherlands", league: "Eredivisie" },
787
+ "werder-bremen": { location: "Bremen, Germany", league: "Bundesliga" },
788
+ "west-ham": { location: "London, England", league: "Premier League" },
789
+ "willem-ii": { location: "Tilburg, Netherlands", league: "Eerste Divisie" },
790
+ "wolfsburg": { location: "Wolfsburg, Germany", league: "Bundesliga" },
791
+ "yokohama-marinos": { location: "Yokohama, Japan", league: "J1 League" }
792
+ };
793
+ }
794
+ });
795
+
451
796
  // src/git/teams.ts
797
+ function withMeta(seed) {
798
+ const baseSlug = seed.slug.replace(/-\d+$/, "");
799
+ const meta = SOCCER_TEAM_META[baseSlug];
800
+ return {
801
+ name: seed.name,
802
+ slug: seed.slug,
803
+ location: meta?.location ?? "Unknown",
804
+ league: meta?.league ?? "Unknown league"
805
+ };
806
+ }
807
+ function lookupSoccerTeam(titleOrSlug) {
808
+ const trimmed = titleOrSlug.trim();
809
+ if (!trimmed) return null;
810
+ const fromName = teamSlugFromName(trimmed);
811
+ const slug = fromName ?? normalizeTakenSlug(trimmed);
812
+ const baseSlug = slug.replace(/-\d+$/, "");
813
+ const seed = FAMOUS_SOCCER_TEAM_SEEDS.find((t) => t.slug === baseSlug);
814
+ if (!seed) return null;
815
+ const suffixMatch = slug.match(/-(\d+)$/) || trimmed.match(/\s+(\d+)$/);
816
+ const suffix = suffixMatch?.[1];
817
+ return withMeta({
818
+ name: suffix ? `${seed.name} ${suffix}` : seed.name,
819
+ slug: suffix ? `${seed.slug}-${suffix}` : seed.slug
820
+ });
821
+ }
452
822
  function teamNameFromSlug(slug) {
453
823
  const normalized = slug.toLowerCase().replace(/^thread\//, "");
454
824
  const suffixMatch = normalized.match(/^(.+)-(\d+)$/);
455
825
  const base = suffixMatch?.[1] ?? normalized;
456
826
  const suffix = suffixMatch?.[2];
457
- const team = FAMOUS_SOCCER_TEAMS.find((t) => t.slug === base);
827
+ const team = FAMOUS_SOCCER_TEAM_SEEDS.find((t) => t.slug === base);
458
828
  if (team) return suffix ? `${team.name} ${suffix}` : team.name;
459
829
  return normalized.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
460
830
  }
@@ -464,7 +834,7 @@ function teamSlugFromName(name) {
464
834
  const suffixMatch = trimmed.match(/^(.+?)\s+(\d+)$/);
465
835
  const baseName = suffixMatch?.[1] ?? trimmed;
466
836
  const suffix = suffixMatch?.[2];
467
- const team = FAMOUS_SOCCER_TEAMS.find(
837
+ const team = FAMOUS_SOCCER_TEAM_SEEDS.find(
468
838
  (t) => t.name.toLowerCase() === baseName.toLowerCase()
469
839
  );
470
840
  if (!team) return null;
@@ -492,26 +862,27 @@ function allocateTeamName(taken, random = Math.random) {
492
862
  const takenSet = new Set(
493
863
  [...taken].map((s) => normalizeTakenSlug(s)).filter(Boolean)
494
864
  );
495
- const available = FAMOUS_SOCCER_TEAMS.filter((t) => !takenSet.has(t.slug));
865
+ const available = FAMOUS_SOCCER_TEAM_SEEDS.filter((t) => !takenSet.has(t.slug));
496
866
  if (available.length > 0) {
497
867
  const idx = Math.floor(random() * available.length);
498
- return available[idx];
868
+ return withMeta(available[idx]);
499
869
  }
500
870
  for (let n = 2; n < 1e3; n++) {
501
- for (const t of FAMOUS_SOCCER_TEAMS) {
871
+ for (const t of FAMOUS_SOCCER_TEAM_SEEDS) {
502
872
  const slug = `${t.slug}-${n}`;
503
873
  if (!takenSet.has(slug)) {
504
- return { name: `${t.name} ${n}`, slug };
874
+ return withMeta({ name: `${t.name} ${n}`, slug });
505
875
  }
506
876
  }
507
877
  }
508
878
  throw new Error("No available soccer team names left");
509
879
  }
510
- var FAMOUS_SOCCER_TEAMS;
880
+ var FAMOUS_SOCCER_TEAM_SEEDS, FAMOUS_SOCCER_TEAMS;
511
881
  var init_teams = __esm({
512
882
  "src/git/teams.ts"() {
513
883
  "use strict";
514
- FAMOUS_SOCCER_TEAMS = [
884
+ init_team_meta();
885
+ FAMOUS_SOCCER_TEAM_SEEDS = [
515
886
  { name: "Aalborg", slug: "aalborg" },
516
887
  { name: "Aalesund", slug: "aalesund" },
517
888
  { name: "Aarhus", slug: "aarhus" },
@@ -848,6 +1219,7 @@ var init_teams = __esm({
848
1219
  { name: "Wolfsburg", slug: "wolfsburg" },
849
1220
  { name: "Yokohama Marinos", slug: "yokohama-marinos" }
850
1221
  ];
1222
+ FAMOUS_SOCCER_TEAMS = FAMOUS_SOCCER_TEAM_SEEDS.map(withMeta);
851
1223
  }
852
1224
  });
853
1225
 
@@ -1165,6 +1537,7 @@ __export(worktree_exports, {
1165
1537
  listBranches: () => listBranches,
1166
1538
  listPrs: () => listPrs,
1167
1539
  listWorktrees: () => listWorktrees,
1540
+ lookupSoccerTeam: () => lookupSoccerTeam,
1168
1541
  mergePr: () => mergePr,
1169
1542
  normalizeWorktreePath: () => normalizeWorktreePath,
1170
1543
  originGhRepoEnv: () => originGhRepoEnv,
@@ -2441,7 +2814,7 @@ function coordinatorGreenfieldPlaybook(reposDir) {
2441
2814
  "- Examples:",
2442
2815
  ` - Clone: \`git clone <url> ${reposDir}/<name>\``,
2443
2816
  ` - New GitHub repo: \`gh repo create <owner>/<name> --private --clone -- ${reposDir}/<name>\` (or mkdir + git init + gh repo create + remote add + push)`,
2444
- "- Then: add_workspace with that absolute path \u2192 create_thread (repoPath + parentThreadId) \u2192 send_to_thread (build) \u2192 wait_for_turn \u2192 send_to_thread (`gh pr create --draft -R <origin-owner/name>`) or create_draft_pr.",
2817
+ "- Then: add_workspace with that absolute path \u2192 create_thread (repoPath + parentThreadId) \u2192 send_to_thread (build) \u2192 wait_for_turn \u2192 send_to_thread (`gh pr create --draft -R <origin-owner/name>`).",
2445
2818
  "- Always target the child worktree's **origin** (`github:` slug from list_workspaces / `git remote get-url origin` in that worktree). Never open PRs against `upstream`.",
2446
2819
  "- Do coding work in the child worktree thread, not by editing files in this home cwd."
2447
2820
  ].join("\n");
@@ -2481,8 +2854,8 @@ function ensureGlobalCoordinatorCwd() {
2481
2854
  "",
2482
2855
  "When creating threads, pass `repoPath` from `list_workspaces` (or the path you just registered) and `parentThreadId` for children.",
2483
2856
  "Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn.",
2484
- "Typical flow (new app): Bash create/clone under repos dir \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 draft PR.",
2485
- "Prefer asking worktree agents to open draft PRs; use create_draft_pr as fallback."
2857
+ "Typical flow (new app): Bash create/clone under repos dir \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 draft PR via worktree agent.",
2858
+ "Always ask worktree agents to open draft PRs (`send_to_thread` + `gh pr create --draft -R <origin>`); never open PRs from the orchestrator."
2486
2859
  ].join("\n");
2487
2860
  (0, import_node_fs6.writeFileSync)((0, import_node_path7.join)(dir, "CLAUDE.md"), `${body}
2488
2861
  `, "utf8");
@@ -2507,8 +2880,8 @@ function coordinatorSystemPrompt(opts) {
2507
2880
  COORDINATOR_TOOL_PLAYBOOK,
2508
2881
  coordinatorGreenfieldPlaybook(reposDir),
2509
2882
  "When creating threads, pass the correct repoPath for the target workspace and parentThreadId for children.",
2510
- "Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 send_to_thread (ask for `gh pr create --draft -R <origin-owner/name>` using the workspace github slug) \u2192 wait_for_turn. Use create_draft_pr only if the child cannot open the PR. Never target upstream.",
2511
- "Typical flow (new app): Bash under repos dir (clone or gh repo create) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 draft PR.",
2883
+ "Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 send_to_thread (ask for `gh pr create --draft -R <origin-owner/name>` using the workspace github slug) \u2192 wait_for_turn. Never target upstream. Never open PRs from the orchestrator.",
2884
+ "Typical flow (new app): Bash under repos dir (clone or gh repo create) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 draft PR via worktree agent.",
2512
2885
  `Goal: ${opts.goal}`,
2513
2886
  `Parent thread id (pass as parentThreadId when creating children): ${opts.parentId}`,
2514
2887
  "Registered workspaces:",
@@ -2543,10 +2916,8 @@ var init_coordinator_prompt = __esm({
2543
2916
  "- list_run_scripts / run_dev_script / stop_dev_script \u2014 start/stop named run scripts",
2544
2917
  "Inspect / PRs:",
2545
2918
  "- get_diff \u2014 compact diff summary",
2546
- "- preview_land \u2014 preview push+PR (does not push)",
2547
- "- Prefer asking the worktree agent via send_to_thread to open a draft PR with `gh pr create --draft -R <origin-owner/name>` (use the workspace `github:` slug / that worktree's origin \u2014 never upstream) so it owns title/body from the diff.",
2548
- "- create_draft_pr \u2014 fallback: commit (if dirty), push to origin, open/update a DRAFT PR from the orchestrator (always against origin)",
2549
- "Human-only (do not attempt): ready-for-review confirm_land, purge_thread.",
2919
+ "- Ask the worktree agent via send_to_thread to open a draft PR with `gh pr create --draft -R <origin-owner/name>` (workspace `github:` slug / that worktree's origin \u2014 never upstream). Do not open PRs from the orchestrator yourself.",
2920
+ "Human-only (do not attempt): merge, ready-for-review land, purge_thread.",
2550
2921
  "Thread links in replies: when mentioning a chat/thread for the user, include a markdown link `[Title](sideboard://thread/<id>)` using the full id (or the link field from create_thread / list_threads). Sideboard renders these as clickable opens.",
2551
2922
  "Bash / Read / etc: allowed for (1) inspecting target worktrees / registered repo paths from MCP, and (2) greenfield setup under ~/sideboard/repos (git clone, gh repo create, git init+remote). Never git init/clone *inside* this synthetic home cwd \u2014 emptiness here is expected, not a bug."
2552
2923
  ].join("\n");
@@ -3359,10 +3730,6 @@ function findSideboardMcpJsEntry() {
3359
3730
  return null;
3360
3731
  }
3361
3732
  async function resolveSideboardMcpServer() {
3362
- const which = await run("which", ["sideboard"], { reject: false });
3363
- if (which.exitCode === 0 && which.stdout.trim()) {
3364
- return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
3365
- }
3366
3733
  const entry = findSideboardMcpJsEntry();
3367
3734
  if (entry) {
3368
3735
  const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
@@ -3373,6 +3740,10 @@ async function resolveSideboardMcpServer() {
3373
3740
  args: isCli ? [entry, "mcp"] : [entry]
3374
3741
  };
3375
3742
  }
3743
+ const which = await run("which", ["sideboard"], { reject: false });
3744
+ if (which.exitCode === 0 && which.stdout.trim()) {
3745
+ return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
3746
+ }
3376
3747
  return { name: "sideboard", command: "sideboard", args: ["mcp"] };
3377
3748
  }
3378
3749
  async function buildInjectedMcpServers(opts) {
@@ -3412,7 +3783,7 @@ function writeMcpServersConfig(servers) {
3412
3783
  (0, import_node_fs9.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
3413
3784
  return cfgPath;
3414
3785
  }
3415
- var import_node_fs9, import_node_module, import_node_os6, import_node_path10, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache;
3786
+ var import_node_fs9, import_node_module, import_node_os6, import_node_path10, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache;
3416
3787
  var init_injected_mcp = __esm({
3417
3788
  "src/agents/injected-mcp.ts"() {
3418
3789
  "use strict";
@@ -3429,6 +3800,11 @@ var init_injected_mcp = __esm({
3429
3800
  "mcp__sideboard",
3430
3801
  "mcp__sideboard__*"
3431
3802
  ];
3803
+ SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
3804
+ "mcp__sideboard__present_artifact",
3805
+ "mcp__sideboard__present_schema",
3806
+ "mcp__sideboard__present_files"
3807
+ ];
3432
3808
  brightsyMcpCommandCache = null;
3433
3809
  }
3434
3810
  });
@@ -3550,7 +3926,7 @@ function parseIssuesJson(raw) {
3550
3926
  }
3551
3927
  return [];
3552
3928
  }
3553
- var import_node_fs10, BASE_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
3929
+ var import_node_fs10, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
3554
3930
  var init_claude = __esm({
3555
3931
  "src/agents/claude.ts"() {
3556
3932
  "use strict";
@@ -3561,7 +3937,21 @@ var init_claude = __esm({
3561
3937
  init_injected_mcp();
3562
3938
  init_turn_input();
3563
3939
  init_types();
3564
- BASE_ALLOWED_TOOLS = ["Edit", "Write", "Bash", "Read", "Glob", "Grep"];
3940
+ BASE_ALLOWED_TOOLS = [
3941
+ "Edit",
3942
+ "Write",
3943
+ "Bash",
3944
+ "Read",
3945
+ "Glob",
3946
+ "Grep",
3947
+ "WebFetch",
3948
+ "WebSearch"
3949
+ ];
3950
+ CLAUDE_CHROME_ALLOWED_TOOLS = [
3951
+ "mcp__claude-in-chrome",
3952
+ "mcp__claude-in-chrome__*",
3953
+ "Skill(claude-in-chrome)"
3954
+ ];
3565
3955
  CLAUDE_PROMPT_ARG_MAX = 2e5;
3566
3956
  claudeAdapter = {
3567
3957
  kind: "claude",
@@ -3622,10 +4012,11 @@ var init_claude = __esm({
3622
4012
  const { isOrchestratorThread: isOrchestratorThread2 } = await Promise.resolve().then(() => (init_global_workspace(), global_workspace_exports));
3623
4013
  const isOrchestrator = isOrchestratorThread2(thread);
3624
4014
  const injectedServers = await buildInjectedMcpServers({
3625
- includeSideboard: isOrchestrator,
4015
+ includeSideboard: true,
3626
4016
  includeBrightsy: isBrightsyConnected()
3627
4017
  });
3628
4018
  const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
4019
+ const chromeOn = claudeChromeEnabled();
3629
4020
  let allowedTools;
3630
4021
  if (isOrchestrator) {
3631
4022
  allowedTools = [
@@ -3638,9 +4029,13 @@ var init_claude = __esm({
3638
4029
  allowedTools = [
3639
4030
  ...BASE_ALLOWED_TOOLS,
3640
4031
  ...mcpAllowTools(servers),
4032
+ ...SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS,
3641
4033
  ...brightsyMcpAllowedTools(injectedBrightsyNames)
3642
4034
  ];
3643
4035
  }
4036
+ if (chromeOn) {
4037
+ allowedTools = [...allowedTools, ...CLAUDE_CHROME_ALLOWED_TOOLS];
4038
+ }
3644
4039
  const args = [
3645
4040
  "-p",
3646
4041
  ...useStdin ? [] : [promptText],
@@ -3655,7 +4050,7 @@ var init_claude = __esm({
3655
4050
  if (mcpConfigPath) {
3656
4051
  args.push("--mcp-config", mcpConfigPath);
3657
4052
  }
3658
- if (claudeChromeEnabled()) {
4053
+ if (chromeOn) {
3659
4054
  args.push("--chrome");
3660
4055
  }
3661
4056
  if (useStdin) {
@@ -4589,6 +4984,18 @@ function toolDescription(name, input) {
4589
4984
  if (/connectedAgentRequest/i.test(name)) {
4590
4985
  return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
4591
4986
  }
4987
+ if (/present_artifact$/i.test(name)) {
4988
+ return str(input?.title) ? `Present ${str(input?.title)}` : "Present artifact";
4989
+ }
4990
+ if (/present_schema$/i.test(name)) {
4991
+ return str(input?.title) ? `Schema ${str(input?.title)}` : "Present schema";
4992
+ }
4993
+ if (/present_files$/i.test(name)) {
4994
+ return str(input?.title) ? `Files ${str(input?.title)}` : "Present files";
4995
+ }
4996
+ if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
4997
+ return str(input?.title) ? `Artifact ${str(input?.title)}` : "Artifact";
4998
+ }
4592
4999
  if (!input) return n;
4593
5000
  if (/bash|shell|terminal/i.test(name) && str(input.command)) {
4594
5001
  const cmd = str(input.command);
@@ -6675,6 +7082,27 @@ function isImageRelativePath(relativePath) {
6675
7082
  const ext = base.includes(".") ? base.split(".").pop() || "" : "";
6676
7083
  return IMAGE_EXTENSIONS.has(ext);
6677
7084
  }
7085
+ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
7086
+ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
7087
+ assertSafeRelativePath(relativePath);
7088
+ const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
7089
+ const abs = (0, import_node_path19.join)(worktreePath, relativePath);
7090
+ const st = (0, import_node_fs20.statSync)(abs);
7091
+ if (!st.isFile()) {
7092
+ throw new Error(`Not a file: ${relativePath}`);
7093
+ }
7094
+ if (st.size > maxBytes) {
7095
+ throw new Error(
7096
+ `File too large to upload (${st.size} bytes; max ${maxBytes})`
7097
+ );
7098
+ }
7099
+ const buf = (0, import_node_fs20.readFileSync)(abs);
7100
+ return {
7101
+ path: relativePath,
7102
+ contentBase64: buf.toString("base64"),
7103
+ size: buf.length
7104
+ };
7105
+ }
6678
7106
  function readWorktreeFile(worktreePath, relativePath, opts) {
6679
7107
  assertSafeRelativePath(relativePath);
6680
7108
  const maxBytes = opts?.maxBytes ?? 2e5;
@@ -7203,6 +7631,26 @@ function formatWorktreeDirective(thread, opts) {
7203
7631
  }
7204
7632
  return lines.join("\n");
7205
7633
  }
7634
+ function formatArtifactDirective() {
7635
+ return [
7636
+ "Sideboard side column (desktop UI):",
7637
+ "claude.ai\u2019s \u201CArtifact\u201D tool does NOT exist in Claude Code. That is expected.",
7638
+ "Documents (HTML/SVG/markdown):",
7639
+ "1) Emit a fenced code block tagged `html` (preferred), `svg`, or `markdown` with the FULL document \u2014 Sideboard opens a side column. Example:",
7640
+ "```html",
7641
+ "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
7642
+ "```",
7643
+ "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content.",
7644
+ "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
7645
+ "3) Call Sideboard MCP `present_schema` with title, mode (table|form), and either:",
7646
+ " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
7647
+ " - datasource=inline + resource: { id, title, schema, schemaUi } and optional records/record.",
7648
+ "Files / media browser (CMS file manager column):",
7649
+ "4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
7650
+ " Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
7651
+ "Never say artifacts, CMS UI, or the Files column are unavailable. Prefer present_schema for list/edit/publish; present_files for storage UI; html fences for standalone pages."
7652
+ ].join("\n");
7653
+ }
7206
7654
  var FILES_BY_AGENT = {
7207
7655
  claude: [
7208
7656
  "CLAUDE.md",
@@ -7537,9 +7985,18 @@ var Orchestrator = class {
7537
7985
  parentId: threadId,
7538
7986
  goal: thread.sourceRef || thread.title
7539
7987
  }) : null;
7988
+ const artifactReminder = thread.agent !== "brightsy" ? [
7989
+ "Sideboard side column (important):",
7990
+ "There is no claude.ai Artifact tool here \u2014 that is normal.",
7991
+ "HTML/SVG/markdown: ```html fence or MCP present_artifact.",
7992
+ "CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
7993
+ "Files column: MCP present_files (brightsy account storage or memory).",
7994
+ "Do not say artifacts/CMS UI are unavailable."
7995
+ ].join(" ") : null;
7540
7996
  const agentPrompt = [
7541
7997
  thread.planMode ? PLAN_MODE_INSTRUCTION : null,
7542
7998
  orchestrationReminder,
7999
+ artifactReminder,
7543
8000
  expandedPrompt
7544
8001
  ].filter(Boolean).join("\n\n");
7545
8002
  const instructionFiles = loadAgentInstructions(thread.worktreePath, thread.agent);
@@ -7564,6 +8021,7 @@ var Orchestrator = class {
7564
8021
  () => null
7565
8022
  )
7566
8023
  });
8024
+ const artifactDirective = isBrightsy ? null : formatArtifactDirective();
7567
8025
  const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
7568
8026
  const { autoRenameBranchEnabled: autoRenameBranchEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
7569
8027
  const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled2() ? formatRenameBranchDirective(fresh, {
@@ -7591,6 +8049,7 @@ var Orchestrator = class {
7591
8049
  const cachedPrefix = [
7592
8050
  coordinatorDirective,
7593
8051
  worktreeDirective,
8052
+ artifactDirective,
7594
8053
  renameBranchDirective,
7595
8054
  ...fresh.agent === "claude" && fresh.sessionId ? [] : [instructions, seed]
7596
8055
  ].filter(Boolean).join("\n\n---\n\n");
@@ -8011,6 +8470,13 @@ var Orchestrator = class {
8011
8470
  }
8012
8471
  return readWorktreeFile(thread.worktreePath, relativePath);
8013
8472
  }
8473
+ async readFileForUpload(threadRef, relativePath) {
8474
+ const thread = this.requireThread(threadRef);
8475
+ if (relativePath.includes("..") || relativePath.startsWith("/")) {
8476
+ throw new Error("Invalid path");
8477
+ }
8478
+ return readWorktreeFileForUpload(thread.worktreePath, relativePath);
8479
+ }
8014
8480
  async writeFile(threadRef, relativePath, content) {
8015
8481
  const thread = this.requireThread(threadRef);
8016
8482
  if (relativePath.includes("..") || relativePath.startsWith("/")) {
@@ -8460,6 +8926,82 @@ async function startMcpServer() {
8460
8926
  return { content: [{ type: "text", text: JSON.stringify(summary, null, 2) }] };
8461
8927
  }
8462
8928
  );
8929
+ server.tool(
8930
+ "present_artifact",
8931
+ "Show an HTML, SVG, or markdown document in Sideboard\u2019s Claude-style side column (desktop). Use instead of claude.ai\u2019s artifact tool \u2014 pass the full document content. Prefer type=html for interactive pages.",
8932
+ {
8933
+ title: import_zod.z.string().describe("Short title shown in the artifact pane header"),
8934
+ type: import_zod.z.enum(["html", "svg", "markdown"]).describe("Artifact kind \u2014 html opens an iframe preview"),
8935
+ content: import_zod.z.string().describe("Full document body (complete HTML page, SVG markup, or markdown)"),
8936
+ artifact_id: import_zod.z.string().optional().describe("Stable id when updating the same artifact across turns")
8937
+ },
8938
+ async ({ title, type, content, artifact_id }) => {
8939
+ const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
8940
+ const payload = {
8941
+ ok: true,
8942
+ artifact_id: id,
8943
+ title,
8944
+ type,
8945
+ content,
8946
+ message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
8947
+ };
8948
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
8949
+ }
8950
+ );
8951
+ server.tool(
8952
+ "present_schema",
8953
+ "Open Sideboard\u2019s schema-driven CMS side column (filterable table and/or form). Pass JSON Schema + schemaUi (Brightsy extensions supported). Use datasource=brightsy with resource_id (record type UUID) when logged into Brightsy; use datasource=inline with embedded resource/records for any other source.",
8954
+ {
8955
+ title: import_zod.z.string().describe("Pane title"),
8956
+ mode: import_zod.z.enum(["table", "form"]).optional().describe("table = list/filter records; form = edit one record"),
8957
+ datasource: import_zod.z.enum(["brightsy", "inline"]).optional().describe("brightsy resolves via login; inline uses embedded resource/records"),
8958
+ resource_id: import_zod.z.string().optional().describe("Brightsy record type UUID (or generic resource id)"),
8959
+ record_id: import_zod.z.string().optional().describe("Record id when opening form mode"),
8960
+ resource: import_zod.z.record(import_zod.z.unknown()).optional().describe("Inline { id, title, schema, schemaUi?, slug? }"),
8961
+ record: import_zod.z.record(import_zod.z.unknown()).optional().describe("Inline record { id, data, published_at? }"),
8962
+ records: import_zod.z.array(import_zod.z.record(import_zod.z.unknown())).optional().describe("Inline records for table mode"),
8963
+ pane_id: import_zod.z.string().optional().describe("Stable pane id across updates")
8964
+ },
8965
+ async (args) => {
8966
+ const id = args.pane_id?.trim() || `schema_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
8967
+ const payload = {
8968
+ ok: true,
8969
+ pane_id: id,
8970
+ title: args.title,
8971
+ mode: args.mode ?? (args.record_id || args.record ? "form" : "table"),
8972
+ datasource: args.datasource ?? (args.resource ? "inline" : "brightsy"),
8973
+ resource_id: args.resource_id,
8974
+ record_id: args.record_id,
8975
+ resource: args.resource,
8976
+ record: args.record,
8977
+ records: args.records,
8978
+ message: "Schema pane accepted. Sideboard desktop opens the CMS column beside chat."
8979
+ };
8980
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
8981
+ }
8982
+ );
8983
+ server.tool(
8984
+ "present_files",
8985
+ "Open Sideboard\u2019s Files column (CMS-style file manager: browse, upload, pick). Use datasource=brightsy when the user is logged into Brightsy account storage; datasource=memory for a session-local demo store. Prefer this over claiming a file manager UI is unavailable. Pair with present_schema when editing records that need media.",
8986
+ {
8987
+ title: import_zod.z.string().optional().describe("Pane title (default: Files)"),
8988
+ datasource: import_zod.z.enum(["brightsy", "memory"]).optional().describe("brightsy = account storage via login; memory = session demo store"),
8989
+ path: import_zod.z.string().optional().describe("Initial folder path (e.g. public)"),
8990
+ pane_id: import_zod.z.string().optional().describe("Stable pane id across updates")
8991
+ },
8992
+ async (args) => {
8993
+ const id = args.pane_id?.trim() || `files_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
8994
+ const payload = {
8995
+ ok: true,
8996
+ pane_id: id,
8997
+ title: args.title?.trim() || "Files",
8998
+ datasource: args.datasource ?? "brightsy",
8999
+ path: args.path,
9000
+ message: "Files pane accepted. Sideboard desktop opens the Files column beside chat."
9001
+ };
9002
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
9003
+ }
9004
+ );
8463
9005
  server.tool(
8464
9006
  "create_thread",
8465
9007
  "Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces and parentThreadId when spawning from an orchestrator. Then use send_to_thread to chat.",
@@ -8801,45 +9343,6 @@ async function startMcpServer() {
8801
9343
  };
8802
9344
  }
8803
9345
  );
8804
- server.tool(
8805
- "preview_land",
8806
- "Preview push+PR land (does NOT push). Use before create_draft_pr.",
8807
- { ref: import_zod.z.string() },
8808
- async ({ ref }) => {
8809
- const preview = await orch.previewLand(ref);
8810
- return { content: [{ type: "text", text: JSON.stringify(preview, null, 2) }] };
8811
- }
8812
- );
8813
- server.tool(
8814
- "create_draft_pr",
8815
- "Commit dirty changes if needed, push the thread branch to origin, and create/update a DRAFT GitHub PR against that worktree's origin (never upstream). Ready-for-review / non-draft land stays human-only (CLI/app confirm_land). Prefer this when the orchestrator should open a PR itself; alternatively send_to_thread asking the worktree agent to run `gh pr create --draft -R <origin-owner/name>`.",
8816
- { ref: import_zod.z.string() },
8817
- async ({ ref }) => {
8818
- try {
8819
- const result = await orch.confirmLand(ref, { draft: true });
8820
- return {
8821
- content: [
8822
- {
8823
- type: "text",
8824
- text: JSON.stringify(
8825
- {
8826
- prUrl: result.prUrl,
8827
- pushed: result.pushed,
8828
- committed: result.committed,
8829
- draft: true
8830
- },
8831
- null,
8832
- 2
8833
- )
8834
- }
8835
- ]
8836
- };
8837
- } catch (err) {
8838
- const message = err instanceof Error ? err.message : String(err);
8839
- return { content: [{ type: "text", text: message }], isError: true };
8840
- }
8841
- }
8842
- );
8843
9346
  server.tool(
8844
9347
  "list_branches",
8845
9348
  "List git branches in a registered workspace. Pass repoPath from list_workspaces (unmerged into the default branch by default \u2014 for create_thread sourceType=branch).",